diff --git a/extractors/npm/Dockerfile b/extractors/npm/Dockerfile new file mode 100644 index 0000000..92a4e5f --- /dev/null +++ b/extractors/npm/Dockerfile @@ -0,0 +1,13 @@ +FROM alpine:latest + +RUN apk add --no-cache jq bash fd + +VOLUME [ "/project" ] + +WORKDIR /project + +COPY entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh + +ENTRYPOINT ["/app/entrypoint.sh"] + diff --git a/extractors/npm/entrypoint.sh b/extractors/npm/entrypoint.sh new file mode 100644 index 0000000..26e98e2 --- /dev/null +++ b/extractors/npm/entrypoint.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +OUTPUT_JSON="{}" + +PACKAGE_JSONS=$(fd -e package.json) + +TOTAL_PACKAGE_JSONS=$(echo "$PACKAGE_JSONS" | wc -l) + +OUTPUT_JSON=$(echo "$OUTPUT_JSON" | jq -c ".total_package_json_files = $TOTAL_PACKAGE_JSONS") +# If no package.json files are found, exit +if [ "$TOTAL_PACKAGE_JSONS" -eq 0 ]; then + echo "No package.json files found in the current directory" + exit 1 +fi + +# If root level package.json +if [ -f "package.json" ]; then + OUTPUT_JSON=$(echo "$OUTPUT_JSON" | jq -c ".root_package_json = $(cat package.json)") + +fi + +# If has node_modules +if [ -d "node_modules" ]; then + ARG="$(ls node_modules | wc -l) directories" + OUTPUT_JSON=$(echo "$OUTPUT_JSON" | jq --arg ARG "$ARG" '.node_modules = $ARG') +fi + +# If has package-lock.json +if [ -f "package-lock.json" ]; then + OUTPUT_JSON=$(echo "$OUTPUT_JSON" | jq -c ".package_lock = true") +fi + +# If has yarn.lock +if [ -f "yarn.lock" ]; then + OUTPUT_JSON=$(echo "$OUTPUT_JSON" | jq -c ".yarn_lock = true") +fi + +# If has pnpm-lock.yaml +if [ -f "pnpm-lock.yaml" ]; then + OUTPUT_JSON=$(echo "$OUTPUT_JSON" | jq -c ".pnpm_lock = true") +fi + +echo -e "{\"npm\": $OUTPUT_JSON }" \ No newline at end of file diff --git a/extractors/registry.yaml b/extractors/registry.yaml index 41a2bb7..bb1bc9a 100644 --- a/extractors/registry.yaml +++ b/extractors/registry.yaml @@ -13,5 +13,7 @@ registry: command: - -json output-handler: linguist + - name: npm + image: vonwig/npm:latest diff --git a/prompts/npm/1_system_prompt.md b/prompts/npm/1_system_prompt.md new file mode 100644 index 0000000..2246390 --- /dev/null +++ b/prompts/npm/1_system_prompt.md @@ -0,0 +1,11 @@ +You are and assistant that is an expert at npm projects. + +An NPM project will be described to you. It will include information about the project, the package.json files, the node_modules directory, and the package lock files. + +Inside of a package.json file, the source of truth for package manager should be the key `packageManager` but it is rarely defined. + +If there are multiple lockfiles, you need to respond warning that there are multiple lockfiles. Recommend running the prompt `github.com:docker/labs-ai-tools-for-devs?path=prompts/choose-package-manager` to choose the correct package manager. + +If there is one lockfile, tell them what package manager is used for the project. + +Otherwise, simply summarize the project. Be brief, but consider the package.json provided, and what the typical developer would want to know about the project. \ No newline at end of file diff --git a/prompts/npm/2_user_prompt.md b/prompts/npm/2_user_prompt.md new file mode 100644 index 0000000..e134618 --- /dev/null +++ b/prompts/npm/2_user_prompt.md @@ -0,0 +1,23 @@ +The project has {{npm.total_package_json_files}} package.json files. + +The root package.json file is: + +```json +{{npm.root_package_json}} +``` + +There are {{npm.node_modules}} currently installed in the project. + +The package lock files are: + +```json +{{npm.package_lock}} +``` + +```json +{{npm.yarn_lock}} +``` + +```json +{{npm.pnpm_lock}} +``` \ No newline at end of file diff --git a/prompts/npm/README.md b/prompts/npm/README.md new file mode 100644 index 0000000..2c46009 --- /dev/null +++ b/prompts/npm/README.md @@ -0,0 +1,6 @@ +--- +extractors: + - image: vonwig/npm:latest +--- + +Responds with a summary of the NPM project. \ No newline at end of file diff --git a/src/extension/ui/src/App.tsx b/src/extension/ui/src/App.tsx index 5867f75..d9ceb65 100644 --- a/src/extension/ui/src/App.tsx +++ b/src/extension/ui/src/App.tsx @@ -7,6 +7,8 @@ import Projects from './components/Projects'; import Prompts from './components/Prompts'; import RunOutput from './components/RunOutput'; import Runner from './components/Runner'; // Added this import +import { run } from 'node:test'; +import { ExecResult } from '@docker/extension-api-client-types/dist/v0'; const client = createDockerDesktopClient(); @@ -62,6 +64,8 @@ const debounce = (fn: Function, ms: number) => { const debouncedToastSuccess = debounce(client.desktopUI.toast.success, 1000) +let pullImagePromise: Promise | undefined; + export function App() { const [projects, setProjects] = React.useState(localStorage.getItem('projects') ? JSON.parse(localStorage.getItem('projects')!) : []); const [selectedProject, setSelectedProject] = React.useState(localStorage.getItem('selectedProject') || null); @@ -84,15 +88,7 @@ export function App() { useEffect(() => { try { - client.docker.cli.exec("pull", ["vonwig/function_write_files"]).then(() => { - client.docker.cli.exec("run", [ - "-v", - "openai_key:/root", - "--workdir", "/root", - "vonwig/function_write_files", - `'` + JSON.stringify({ files: [{ path: ".openai-api-key", content: openAIKey, executable: false }] }) + `'` - ]); - }); + pullImagePromise = client.docker.cli.exec("pull", ["vonwig/function_write_files"]) client.docker.cli.exec("pull", ["vonwig/prompts"], { stream: { onOutput: ({ stdout, stderr }) => { @@ -168,7 +164,16 @@ export function App() { const startPrompt = async () => { track('DockerPromptsStartPrompt'); - runOutput.updateOutput({ method: 'message', params: { debug: 'Pulling images' } }) + + await pullImagePromise + + client.docker.cli.exec("run", [ + "-v", + "openai_key:/secret", + "--workdir", "/secret", + "vonwig/function_write_files", + `'` + JSON.stringify({ files: [{ path: ".openai-api-key", content: openAIKey, executable: false }] }) + `'` + ]); runOutput.updateOutput({ method: 'message', params: { debug: 'Running prompts...' } }) const args = getRunArgs(selectedPrompt!, selectedProject!, "", client.host.platform) diff --git a/src/extension/ui/src/args.ts b/src/extension/ui/src/args.ts index 75530ec..de85737 100644 --- a/src/extension/ui/src/args.ts +++ b/src/extension/ui/src/args.ts @@ -14,8 +14,9 @@ export const getRunArgs = (promptRef: string, projectDir: string, username: stri const baseArgs: string[] = [ '--rm', '-v', '/var/run/docker.sock:/var/run/docker.sock', - '-v', 'openai_key:/root', - '--mount', 'type=volume,source=docker-prompts,target=/prompts' + '-v', 'openai_key:/secret', + '--mount', 'type=volume,source=docker-prompts,target=/prompts', + '-e', 'OPENAI_API_KEY_LOCATION=/secret' ]; const runArgs: string[] = render ? [] : [