@openhands/agent-canvas 1.0.0-alpha.5 → 1.0.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -7
- package/bin/agent-canvas.mjs +9 -2
- package/build/assets/automation-detail-D7GEU0vR.js +1 -0
- package/build/assets/automations-list-CkVNsgzm.js +1 -0
- package/build/assets/conversation-COZAKz_K.js +1 -0
- package/build/assets/{conversation-D8scXOe7.js → conversation-DWcvnmds.js} +3 -1
- package/build/assets/conversation-panel-CZDStT0b.js +1 -0
- package/build/assets/conversation-websocket-context-DulnrIHh.js +3 -0
- package/build/assets/edit-automation-modal-C3bFxS2f.js +1 -0
- package/build/assets/git-control-bar-branch-button-Bm6rzSpo.js +27 -0
- package/build/assets/{home-D9fJfhQA.js → home-DR11ejqB.js} +1 -1
- package/build/assets/{manifest-f141dc70.js → manifest-f041e61a.js} +1 -1
- package/build/assets/{messages-BfaEAG2q.js → messages-v-q35ObG.js} +1 -1
- package/build/assets/{root-luPHQiBx.js → root-D2PVd51i.js} +1 -1
- package/build/assets/root-layout-B4QioBS6.js +2 -0
- package/build/assets/{shared-conversation-BfZNCsvo.js → shared-conversation-DQlzwdpo.js} +1 -1
- package/build/index.html +3 -3
- package/config/defaults.json +38 -0
- package/dist/components/features/backends/backend-selector.cjs +1 -1
- package/dist/components/features/backends/backend-selector.cjs.map +1 -1
- package/dist/components/features/backends/backend-selector.js +95 -95
- package/dist/components/features/backends/backend-selector.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-actions.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-actions.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-actions.js +118 -118
- package/dist/components/features/chat/components/chat-input-actions.js.map +1 -1
- package/dist/components/features/chat/components/slash-command-menu.cjs +1 -1
- package/dist/components/features/chat/components/slash-command-menu.cjs.map +1 -1
- package/dist/components/features/chat/components/slash-command-menu.js +1 -1
- package/dist/components/features/chat/components/slash-command-menu.js.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.d.ts +1 -2
- package/dist/components/features/sidebar/sidebar-rail-body.js +104 -104
- package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
- package/dist/components/features/sidebar/sidebar.cjs +1 -1
- package/dist/components/features/sidebar/sidebar.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar.js +82 -83
- package/dist/components/features/sidebar/sidebar.js.map +1 -1
- package/dist/contexts/conversation-websocket-context.cjs +3 -3
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.js +36 -36
- package/dist/contexts/conversation-websocket-context.js.map +1 -1
- package/dist/hooks/query/use-local-git-info.cjs +3 -1
- package/dist/hooks/query/use-local-git-info.cjs.map +1 -1
- package/dist/hooks/query/use-local-git-info.d.ts +2 -2
- package/dist/hooks/query/use-local-git-info.js +27 -24
- package/dist/hooks/query/use-local-git-info.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +2 -1
- package/dist/package.js.map +1 -1
- package/dist/stores/error-message-store.cjs +1 -1
- package/dist/stores/error-message-store.cjs.map +1 -1
- package/dist/stores/error-message-store.d.ts +10 -1
- package/dist/stores/error-message-store.js +16 -3
- package/dist/stores/error-message-store.js.map +1 -1
- package/package.json +2 -1
- package/scripts/dev-static.mjs +8 -1
- package/scripts/dev-with-automation.mjs +30 -49
- package/scripts/static-build.mjs +2 -6
- package/scripts/static-server.mjs +85 -4
- package/build/assets/automation-detail-ZQs6D2d3.js +0 -1
- package/build/assets/automations-list-CqHXGwSw.js +0 -1
- package/build/assets/conversation-CeGMBOyB.js +0 -1
- package/build/assets/conversation-panel-DMz46ji-.js +0 -1
- package/build/assets/conversation-websocket-context-B0Gd3yiT.js +0 -3
- package/build/assets/edit-automation-modal-DgW0Q8vr.js +0 -1
- package/build/assets/git-control-bar-branch-button-DhpPgadK.js +0 -27
- package/build/assets/root-layout-DvYGxAnr.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-local-git-info.js","names":[],"sources":["../../../src/hooks/query/use-local-git-info.ts"],"sourcesContent":["import { useQuery } from \"@tanstack/react-query\";\nimport { useRef } from \"react\";\n\nimport type { CommandResult } from \"#/api/runtime-service/agent-server-runtime-service\";\nimport { getAgentServerWorkingDir } from \"#/api/agent-server-config\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useRuntimeIsReady } from \"#/hooks/use-runtime-is-ready\";\nimport { useBashCommandRunner } from \"#/hooks/use-bash-command-runner\";\nimport { Provider } from \"#/types/settings\";\nimport { parseGitRemoteUrl } from \"#/utils/parse-git-remote-url\";\n\nexport interface LocalGitInfo {\n repository: string | null;\n branch: string | null;\n provider: Provider | null;\n remoteUrl: string | null;\n}\n\nconst EMPTY_LOCAL_GIT_INFO: LocalGitInfo = {\n repository: null,\n branch: null,\n provider: null,\n remoteUrl: null,\n};\n\ntype RunCommand = (\n command: string,\n cwd: string,\n timeout: number,\n) => Promise<CommandResult>;\n\
|
|
1
|
+
{"version":3,"file":"use-local-git-info.js","names":[],"sources":["../../../src/hooks/query/use-local-git-info.ts"],"sourcesContent":["import { useQuery } from \"@tanstack/react-query\";\nimport { useRef } from \"react\";\n\nimport type { CommandResult } from \"#/api/runtime-service/agent-server-runtime-service\";\nimport { getAgentServerWorkingDir } from \"#/api/agent-server-config\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useActiveConversation } from \"#/hooks/query/use-active-conversation\";\nimport { useRuntimeIsReady } from \"#/hooks/use-runtime-is-ready\";\nimport { useBashCommandRunner } from \"#/hooks/use-bash-command-runner\";\nimport { Provider } from \"#/types/settings\";\nimport { parseGitRemoteUrl } from \"#/utils/parse-git-remote-url\";\n\nexport interface LocalGitInfo {\n repository: string | null;\n branch: string | null;\n provider: Provider | null;\n remoteUrl: string | null;\n}\n\nconst EMPTY_LOCAL_GIT_INFO: LocalGitInfo = {\n repository: null,\n branch: null,\n provider: null,\n remoteUrl: null,\n};\n\ntype RunCommand = (\n command: string,\n cwd: string,\n timeout: number,\n) => Promise<CommandResult>;\n\n// Single shell script that replaces the former probeGitInfoAtDir +\n// probeNestedRepoInDir pair. It runs as one bash WebSocket round-trip:\n// 1. Read the origin remote URL and current branch at the workspace root.\n// 2. If neither is set, search for exactly one nested git repo up to 4\n// levels deep and repeat the probe there.\n// Output: two lines — <remote-url>\\n<branch> — either may be empty.\nconst GIT_INFO_COMMAND = [\n \"r=$(git remote get-url origin 2>/dev/null)\",\n \"b=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)\",\n 'if [ -z \"$r$b\" ]; then',\n \"n=$(find . -mindepth 2 -maxdepth 4 -name .git 2>/dev/null | cut -c3- | sed 's|/.git$||' | sort -u)\",\n \"c=$(printf '%s\\\\n' \\\"$n\\\" | grep -c '[^[:space:]]')\",\n 'if [ \"$c\" = \"1\" ] && [ -n \"$n\" ]; then',\n 'r=$(git -C \"$n\" remote get-url origin 2>/dev/null)',\n 'b=$(git -C \"$n\" rev-parse --abbrev-ref HEAD 2>/dev/null)',\n \"fi\",\n \"fi\",\n 'printf \\'%s\\\\n%s\\' \"$r\" \"$b\"',\n].join(\"\\n\");\n\nasync function probeGitInfo(\n run: RunCommand,\n directory: string,\n): Promise<LocalGitInfo> {\n const result = await run(GIT_INFO_COMMAND, directory, 10);\n if (result.exit_code !== 0) return EMPTY_LOCAL_GIT_INFO;\n\n const nl = result.stdout.indexOf(\"\\n\");\n const remoteUrl = (\n nl >= 0 ? result.stdout.slice(0, nl) : result.stdout\n ).trim();\n const rawBranch = (nl >= 0 ? result.stdout.slice(nl + 1) : \"\").trim();\n const branch = rawBranch && rawBranch !== \"HEAD\" ? rawBranch : null;\n\n if (!remoteUrl && !branch) return EMPTY_LOCAL_GIT_INFO;\n\n const parsedRemote = parseGitRemoteUrl(remoteUrl);\n return {\n repository: parsedRemote?.repository ?? null,\n provider: parsedRemote?.provider ?? null,\n remoteUrl: remoteUrl || null,\n branch,\n };\n}\n\n/**\n * Probe git metadata for a **local** backend's workspace checkout by\n * shelling out via the agent server using a single consolidated bash\n * script (see `GIT_INFO_COMMAND`).\n *\n * Local-only by design. On cloud backends the conversation metadata\n * (`selected_repository`, `git_provider`, `selected_branch`) is the\n * source of truth, and probing via `/api/bash/execute_bash_command`\n * would (a) leak the user's local `getAgentServerWorkingDir()` path to\n * the cloud runtime when `workspace.working_dir` is missing, and\n * (b) hit a bash endpoint we don't want the frontend driving on cloud.\n *\n * On local, we keep the probe enabled until the active conversation\n * has a complete repo tuple so the control bar can recover from\n * partial metadata hydration after connect/clone flows.\n *\n * Returns `null` fields when the working dir is not a git checkout —\n * callers should treat that the same as \"no repo detected\".\n */\nexport const useLocalGitInfo = () => {\n const { data: conversation } = useActiveConversation();\n const runtimeIsReady = useRuntimeIsReady();\n const { backend } = useActiveBackend();\n const isLocalBackend = backend.kind === \"local\";\n\n const conversationId = conversation?.id;\n const conversationUrl = conversation?.conversation_url;\n const sessionApiKey = conversation?.session_api_key;\n const workingDir =\n conversation?.workspace?.working_dir?.trim() || getAgentServerWorkingDir();\n const hasConversationRepo = !!conversation?.selected_repository;\n const hasConversationProvider = !!conversation?.git_provider;\n const hasConversationBranch = !!conversation?.selected_branch;\n\n const queryEnabled =\n isLocalBackend &&\n runtimeIsReady &&\n !!conversationId &&\n (!hasConversationRepo ||\n !hasConversationProvider ||\n !hasConversationBranch);\n\n // Persistent WebSocket connection to the bash-events endpoint. The\n // connection is opened when the query is enabled and closed on unmount or\n // when the conversation changes.\n const runCommand = useBashCommandRunner(\n conversationUrl,\n sessionApiKey,\n queryEnabled,\n );\n\n // Keep a ref so queryFn can call the latest runner without capturing it\n // as a queryKey dependency (runCommand is stable but the linter can't\n // infer that).\n const runCommandRef = useRef(runCommand);\n runCommandRef.current = runCommand;\n\n // runCommandRef is a ref (always stable); the linter cannot infer this so\n // we disable the exhaustive-deps check here.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n return useQuery<LocalGitInfo>({\n queryKey: [\n \"local-git-info\",\n conversationId,\n conversationUrl,\n sessionApiKey,\n workingDir,\n ],\n queryFn: async () => {\n const run: RunCommand = (command, cwd, timeout) =>\n runCommandRef.current(command, cwd, timeout);\n return probeGitInfo(run, workingDir);\n },\n enabled: queryEnabled,\n retry: false,\n // Re-probe the workspace every 10s so the UI reflects branch/repo\n // changes (e.g. `git checkout`, adding a remote) without requiring a\n // manual refresh when there is no `selected_repository` recorded on\n // the conversation. Commands now run over the persistent WebSocket\n // connection rather than individual REST calls.\n staleTime: 10_000,\n refetchInterval: 10_000,\n gcTime: 1000 * 60 * 5,\n meta: { disableToast: true },\n });\n};\n"],"mappings":";;;;;;;;;AAmBA,IAAM,IAAqC;CACzC,YAAY;CACZ,QAAQ;CACR,UAAU;CACV,WAAW;CACZ,EAcK,IAAmB;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC,KAAK,KAAK;AAEZ,eAAe,EACb,GACA,GACuB;CACvB,IAAM,IAAS,MAAM,EAAI,GAAkB,GAAW,GAAG;AACzD,KAAI,EAAO,cAAc,EAAG,QAAO;CAEnC,IAAM,IAAK,EAAO,OAAO,QAAQ,KAAK,EAChC,KACJ,KAAM,IAAI,EAAO,OAAO,MAAM,GAAG,EAAG,GAAG,EAAO,QAC9C,MAAM,EACF,KAAa,KAAM,IAAI,EAAO,OAAO,MAAM,IAAK,EAAE,GAAG,IAAI,MAAM,EAC/D,IAAS,KAAa,MAAc,SAAS,IAAY;AAE/D,KAAI,CAAC,KAAa,CAAC,EAAQ,QAAO;CAElC,IAAM,IAAe,EAAkB,EAAU;AACjD,QAAO;EACL,YAAY,GAAc,cAAc;EACxC,UAAU,GAAc,YAAY;EACpC,WAAW,KAAa;EACxB;EACD;;AAsBH,IAAa,UAAwB;CACnC,IAAM,EAAE,MAAM,MAAiB,GAAuB,EAChD,IAAiB,GAAmB,EACpC,EAAE,eAAY,GAAkB,EAChC,IAAiB,EAAQ,SAAS,SAElC,IAAiB,GAAc,IAC/B,IAAkB,GAAc,kBAChC,IAAgB,GAAc,iBAC9B,IACJ,GAAc,WAAW,aAAa,MAAM,IAAI,GAA0B,EACtE,IAAsB,CAAC,CAAC,GAAc,qBACtC,IAA0B,CAAC,CAAC,GAAc,cAC1C,IAAwB,CAAC,CAAC,GAAc,iBAExC,IACJ,KACA,KACA,CAAC,CAAC,MACD,CAAC,KACA,CAAC,KACD,CAAC,IAKC,IAAa,EACjB,GACA,GACA,EACD,EAKK,IAAgB,EAAO,EAAW;AAMxC,QALA,EAAc,UAAU,GAKjB,EAAuB;EAC5B,UAAU;GACR;GACA;GACA;GACA;GACA;GACD;EACD,SAAS,YAGA,GAFkB,GAAS,GAAK,MACrC,EAAc,QAAQ,GAAS,GAAK,EAAQ,EACrB,EAAW;EAEtC,SAAS;EACT,OAAO;EAMP,WAAW;EACX,iBAAiB;EACjB,QAAQ,MAAO,KAAK;EACpB,MAAM,EAAE,cAAc,IAAM;EAC7B,CAAC"}
|
package/dist/package.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`./_virtual/_rolldown/runtime.cjs`);var e={name:`@openhands/agent-canvas`,version:`1.0.0-alpha.
|
|
1
|
+
require(`./_virtual/_rolldown/runtime.cjs`);var e={name:`@openhands/agent-canvas`,version:`1.0.0-alpha.7`,description:`Agent Canvas UI for OpenHands - run AI coding agents with a visual interface`,license:`MIT`,private:!1,type:`module`,repository:{type:`git`,url:`https://github.com/OpenHands/agent-canvas`},homepage:`https://github.com/OpenHands/agent-canvas#readme`,bugs:{url:`https://github.com/OpenHands/agent-canvas/issues`},bin:{"agent-canvas":`bin/agent-canvas.mjs`},engines:{node:`>=22.12.0`},dependencies:{"@heroui/react":`2.8.10`,"@microlink/react-json-view":`1.31.20`,"@monaco-editor/react":`4.7.0`,"@openhands/extensions":`git+https://github.com/OpenHands/extensions.git#b8c1869ec9dea4467bb27d5754dc695d14e27889`,"@openhands/typescript-client":`1.23.3`,"@react-router/node":`7.14.2`,"@react-router/serve":`7.14.2`,"@tailwindcss/vite":`4.2.4`,"@tanstack/react-query":`5.100.9`,"@types/shell-quote":`^1.7.5`,"@uidotdev/usehooks":`2.4.1`,"@xterm/addon-fit":`0.11.0`,"@xterm/xterm":`6.0.0`,axios:`1.16.0`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,downshift:`9.3.2`,"framer-motion":`12.38.0`,i18next:`26.0.8`,"i18next-browser-languagedetector":`8.2.1`,"i18next-http-backend":`4.0.0`,isbot:`5.1.39`,"lucide-react":`1.14.0`,"monaco-editor":`0.55.1`,"posthog-js":`1.372.6`,react:`19.2.5`,"react-dom":`19.2.5`,"react-hot-toast":`2.6.0`,"react-i18next":`17.0.6`,"react-icons":`5.6.0`,"react-markdown":`10.1.0`,"react-router":`7.14.2`,"react-syntax-highlighter":`16.1.1`,"rehype-raw":`7.0.0`,"rehype-sanitize":`6.0.0`,"remark-breaks":`4.0.0`,"remark-gfm":`4.0.1`,"shell-quote":`^1.8.3`,"sirv-cli":`3.0.1`,"socket.io-client":`4.8.3`,"tailwind-merge":`3.5.0`,"tailwind-scrollbar":`4.0.2`,"unist-util-visit":`5.1.0`,uuid:`14.0.0`,vite:`8.0.10`,zustand:`5.0.12`},scripts:{dev:`node --env-file-if-exists=.env scripts/dev-with-automation.mjs`,"dev:static":`node --env-file-if-exists=.env scripts/dev-static.mjs`,"dev:extra-backend":`node --env-file-if-exists=.env scripts/dev-extra-backend.mjs`,"dev:minimal":`node --env-file-if-exists=.env scripts/dev-safe.mjs`,"dev:frontend":`npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev`,"dev:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev`,build:`npm run build:app`,"build:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router build`,start:`npx sirv-cli build/ --single`,test:`npm run make-i18n && vitest run`,"test:e2e":`playwright test --pass-with-no-tests`,"test:e2e:live":`node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs`,"test:e2e:snapshots":`playwright test tests/e2e/snapshots --project=chromium --retries=0`,"test:e2e:snapshots:update":`playwright test tests/e2e/snapshots --project=chromium --update-snapshots`,"test:coverage":`npm run make-i18n && vitest run --coverage`,dev_wsl:`VITE_WATCH_USE_POLLING=true vite`,preview:`vite preview`,"make-i18n":`node scripts/make-i18n-translations.cjs`,prelint:`npm run make-i18n`,lint:`npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}`,"lint:fix":`eslint src --fix && prettier --write src/**/*.{ts,tsx}`,prepare:`husky`,typecheck:`react-router typegen && tsc`,"typecheck:staged":`react-router typegen && npx tsc --noEmit --skipLibCheck`,"check-translation-completeness":`node scripts/check-translation-completeness.cjs`,"build:app":`npm run make-i18n && react-router build`,"build:lib":`npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true VITE_APP_ENV=production vite build && tsc -p tsconfig.lib.json`,"build:docker":`node scripts/docker-build.mjs`},"lint-staged":{"src/**/*.{ts,tsx,js}":[`eslint --fix`,`prettier --write`],"src/**/*.{ts,tsx}":[`bash -c 'npm run typecheck:staged'`],"src/**/*":[`npm run check-translation-completeness`]},devDependencies:{"@eslint/eslintrc":`3.3.1`,"@eslint/js":`9.39.4`,"@mswjs/socket.io-binding":`0.2.0`,"@playwright/test":`1.59.1`,"@react-router/dev":`7.14.2`,"@tailwindcss/typography":`0.5.19`,"@tanstack/eslint-plugin-query":`5.100.9`,"@testing-library/dom":`10.4.1`,"@testing-library/jest-dom":`6.9.1`,"@testing-library/react":`16.3.2`,"@testing-library/user-event":`14.6.1`,"@types/mdast":`4.0.4`,"@types/node":`25.6.0`,"@types/react":`19.2.14`,"@types/react-dom":`19.2.3`,"@types/react-syntax-highlighter":`15.5.13`,"@typescript-eslint/eslint-plugin":`8.59.2`,"@typescript-eslint/parser":`8.59.2`,"@vercel/react-router":`1.3.0`,"@vitest/coverage-v8":`4.1.5`,"cross-env":`10.1.0`,eslint:`9.39.4`,"eslint-config-prettier":`10.1.8`,"eslint-import-resolver-typescript":`4.4.4`,"eslint-plugin-i18next":`6.1.4`,"eslint-plugin-import-x":`4.16.2`,"eslint-plugin-jsx-a11y":`6.10.2`,"eslint-plugin-prettier":`5.5.5`,"eslint-plugin-react":`7.37.5`,"eslint-plugin-react-hooks":`7.1.1`,"eslint-plugin-unused-imports":`4.4.1`,globals:`16.5.0`,husky:`9.1.7`,jsdom:`29.1.1`,"lint-staged":`16.4.0`,msw:`2.14.2`,"postcss-prefix-selector":`2.1.1`,prettier:`3.8.3`,tailwindcss:`4.2.4`,typescript:`6.0.3`,"vite-plugin-svgr":`5.2.0`,vitest:`4.1.5`},packageManager:`npm@10.5.0`,volta:{node:`22.12.0`},msw:{workerDirectory:[`public`]},overrides:{dompurify:`3.3.2`},main:`./dist/index.cjs`,module:`./dist/index.js`,types:`./dist/index.d.ts`,files:[`dist`,`bin`,`build`,`config`,`scripts`],exports:{".":{types:`./dist/index.d.ts`,import:`./dist/index.js`,require:`./dist/index.cjs`},"./browser":{types:`./dist/components/browser/index.d.ts`,import:`./dist/components/browser/index.js`,require:`./dist/components/browser/index.cjs`},"./conversation":{types:`./dist/components/conversation/index.d.ts`,import:`./dist/components/conversation/index.js`,require:`./dist/components/conversation/index.cjs`},"./files":{types:`./dist/components/files/index.d.ts`,import:`./dist/components/files/index.js`,require:`./dist/components/files/index.cjs`},"./settings":{types:`./dist/components/settings/index.d.ts`,import:`./dist/components/settings/index.js`,require:`./dist/components/settings/index.cjs`},"./sidebar":{types:`./dist/components/sidebar/index.d.ts`,import:`./dist/components/sidebar/index.js`,require:`./dist/components/sidebar/index.cjs`},"./terminal":{types:`./dist/components/terminal/index.d.ts`,import:`./dist/components/terminal/index.js`,require:`./dist/components/terminal/index.cjs`},"./i18n":{types:`./dist/i18n/index.d.ts`,import:`./dist/i18n/index.js`,require:`./dist/i18n/index.cjs`},"./package.json":`./package.json`},peerDependencies:{react:`19.2.5`,"react-dom":`19.2.5`,"react-router":`7.14.2`}};exports.default=e;
|
|
2
2
|
//# sourceMappingURL=package.cjs.map
|
package/dist/package.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.cjs","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.0.0-alpha.
|
|
1
|
+
{"version":3,"file":"package.cjs","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.0.0-alpha.7\",\n \"description\": \"Agent Canvas UI for OpenHands - run AI coding agents with a visual interface\",\n \"license\": \"MIT\",\n \"private\": false,\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/OpenHands/agent-canvas\"\n },\n \"homepage\": \"https://github.com/OpenHands/agent-canvas#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/OpenHands/agent-canvas/issues\"\n },\n \"bin\": {\n \"agent-canvas\": \"bin/agent-canvas.mjs\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"dependencies\": {\n \"@heroui/react\": \"2.8.10\",\n \"@microlink/react-json-view\": \"1.31.20\",\n \"@monaco-editor/react\": \"4.7.0\",\n \"@openhands/extensions\": \"git+https://github.com/OpenHands/extensions.git#b8c1869ec9dea4467bb27d5754dc695d14e27889\",\n \"@openhands/typescript-client\": \"1.23.3\",\n \"@react-router/node\": \"7.14.2\",\n \"@react-router/serve\": \"7.14.2\",\n \"@tailwindcss/vite\": \"4.2.4\",\n \"@tanstack/react-query\": \"5.100.9\",\n \"@types/shell-quote\": \"^1.7.5\",\n \"@uidotdev/usehooks\": \"2.4.1\",\n \"@xterm/addon-fit\": \"0.11.0\",\n \"@xterm/xterm\": \"6.0.0\",\n \"axios\": \"1.16.0\",\n \"class-variance-authority\": \"0.7.1\",\n \"clsx\": \"2.1.1\",\n \"downshift\": \"9.3.2\",\n \"framer-motion\": \"12.38.0\",\n \"i18next\": \"26.0.8\",\n \"i18next-browser-languagedetector\": \"8.2.1\",\n \"i18next-http-backend\": \"4.0.0\",\n \"isbot\": \"5.1.39\",\n \"lucide-react\": \"1.14.0\",\n \"monaco-editor\": \"0.55.1\",\n \"posthog-js\": \"1.372.6\",\n \"react\": \"19.2.5\",\n \"react-dom\": \"19.2.5\",\n \"react-hot-toast\": \"2.6.0\",\n \"react-i18next\": \"17.0.6\",\n \"react-icons\": \"5.6.0\",\n \"react-markdown\": \"10.1.0\",\n \"react-router\": \"7.14.2\",\n \"react-syntax-highlighter\": \"16.1.1\",\n \"rehype-raw\": \"7.0.0\",\n \"rehype-sanitize\": \"6.0.0\",\n \"remark-breaks\": \"4.0.0\",\n \"remark-gfm\": \"4.0.1\",\n \"shell-quote\": \"^1.8.3\",\n \"sirv-cli\": \"3.0.1\",\n \"socket.io-client\": \"4.8.3\",\n \"tailwind-merge\": \"3.5.0\",\n \"tailwind-scrollbar\": \"4.0.2\",\n \"unist-util-visit\": \"5.1.0\",\n \"uuid\": \"14.0.0\",\n \"vite\": \"8.0.10\",\n \"zustand\": \"5.0.12\"\n },\n \"scripts\": {\n \"dev\": \"node --env-file-if-exists=.env scripts/dev-with-automation.mjs\",\n \"dev:static\": \"node --env-file-if-exists=.env scripts/dev-static.mjs\",\n \"dev:extra-backend\": \"node --env-file-if-exists=.env scripts/dev-extra-backend.mjs\",\n \"dev:minimal\": \"node --env-file-if-exists=.env scripts/dev-safe.mjs\",\n \"dev:frontend\": \"npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev\",\n \"dev:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev\",\n \"build\": \"npm run build:app\",\n \"build:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router build\",\n \"start\": \"npx sirv-cli build/ --single\",\n \"test\": \"npm run make-i18n && vitest run\",\n \"test:e2e\": \"playwright test --pass-with-no-tests\",\n \"test:e2e:live\": \"node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs\",\n \"test:e2e:snapshots\": \"playwright test tests/e2e/snapshots --project=chromium --retries=0\",\n \"test:e2e:snapshots:update\": \"playwright test tests/e2e/snapshots --project=chromium --update-snapshots\",\n \"test:coverage\": \"npm run make-i18n && vitest run --coverage\",\n \"dev_wsl\": \"VITE_WATCH_USE_POLLING=true vite\",\n \"preview\": \"vite preview\",\n \"make-i18n\": \"node scripts/make-i18n-translations.cjs\",\n \"prelint\": \"npm run make-i18n\",\n \"lint\": \"npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint src --fix && prettier --write src/**/*.{ts,tsx}\",\n \"prepare\": \"husky\",\n \"typecheck\": \"react-router typegen && tsc\",\n \"typecheck:staged\": \"react-router typegen && npx tsc --noEmit --skipLibCheck\",\n \"check-translation-completeness\": \"node scripts/check-translation-completeness.cjs\",\n \"build:app\": \"npm run make-i18n && react-router build\",\n \"build:lib\": \"npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true VITE_APP_ENV=production vite build && tsc -p tsconfig.lib.json\",\n \"build:docker\": \"node scripts/docker-build.mjs\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"src/**/*.{ts,tsx}\": [\n \"bash -c 'npm run typecheck:staged'\"\n ],\n \"src/**/*\": [\n \"npm run check-translation-completeness\"\n ]\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"3.3.1\",\n \"@eslint/js\": \"9.39.4\",\n \"@mswjs/socket.io-binding\": \"0.2.0\",\n \"@playwright/test\": \"1.59.1\",\n \"@react-router/dev\": \"7.14.2\",\n \"@tailwindcss/typography\": \"0.5.19\",\n \"@tanstack/eslint-plugin-query\": \"5.100.9\",\n \"@testing-library/dom\": \"10.4.1\",\n \"@testing-library/jest-dom\": \"6.9.1\",\n \"@testing-library/react\": \"16.3.2\",\n \"@testing-library/user-event\": \"14.6.1\",\n \"@types/mdast\": \"4.0.4\",\n \"@types/node\": \"25.6.0\",\n \"@types/react\": \"19.2.14\",\n \"@types/react-dom\": \"19.2.3\",\n \"@types/react-syntax-highlighter\": \"15.5.13\",\n \"@typescript-eslint/eslint-plugin\": \"8.59.2\",\n \"@typescript-eslint/parser\": \"8.59.2\",\n \"@vercel/react-router\": \"1.3.0\",\n \"@vitest/coverage-v8\": \"4.1.5\",\n \"cross-env\": \"10.1.0\",\n \"eslint\": \"9.39.4\",\n \"eslint-config-prettier\": \"10.1.8\",\n \"eslint-import-resolver-typescript\": \"4.4.4\",\n \"eslint-plugin-i18next\": \"6.1.4\",\n \"eslint-plugin-import-x\": \"4.16.2\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-prettier\": \"5.5.5\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-react-hooks\": \"7.1.1\",\n \"eslint-plugin-unused-imports\": \"4.4.1\",\n \"globals\": \"16.5.0\",\n \"husky\": \"9.1.7\",\n \"jsdom\": \"29.1.1\",\n \"lint-staged\": \"16.4.0\",\n \"msw\": \"2.14.2\",\n \"postcss-prefix-selector\": \"2.1.1\",\n \"prettier\": \"3.8.3\",\n \"tailwindcss\": \"4.2.4\",\n \"typescript\": \"6.0.3\",\n \"vite-plugin-svgr\": \"5.2.0\",\n \"vitest\": \"4.1.5\"\n },\n \"packageManager\": \"npm@10.5.0\",\n \"volta\": {\n \"node\": \"22.12.0\"\n },\n \"msw\": {\n \"workerDirectory\": [\n \"public\"\n ]\n },\n \"overrides\": {\n \"dompurify\": \"3.3.2\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"bin\",\n \"build\",\n \"config\",\n \"scripts\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./browser\": {\n \"types\": \"./dist/components/browser/index.d.ts\",\n \"import\": \"./dist/components/browser/index.js\",\n \"require\": \"./dist/components/browser/index.cjs\"\n },\n \"./conversation\": {\n \"types\": \"./dist/components/conversation/index.d.ts\",\n \"import\": \"./dist/components/conversation/index.js\",\n \"require\": \"./dist/components/conversation/index.cjs\"\n },\n \"./files\": {\n \"types\": \"./dist/components/files/index.d.ts\",\n \"import\": \"./dist/components/files/index.js\",\n \"require\": \"./dist/components/files/index.cjs\"\n },\n \"./settings\": {\n \"types\": \"./dist/components/settings/index.d.ts\",\n \"import\": \"./dist/components/settings/index.js\",\n \"require\": \"./dist/components/settings/index.cjs\"\n },\n \"./sidebar\": {\n \"types\": \"./dist/components/sidebar/index.d.ts\",\n \"import\": \"./dist/components/sidebar/index.js\",\n \"require\": \"./dist/components/sidebar/index.cjs\"\n },\n \"./terminal\": {\n \"types\": \"./dist/components/terminal/index.d.ts\",\n \"import\": \"./dist/components/terminal/index.js\",\n \"require\": \"./dist/components/terminal/index.cjs\"\n },\n \"./i18n\": {\n \"types\": \"./dist/i18n/index.d.ts\",\n \"import\": \"./dist/i18n/index.js\",\n \"require\": \"./dist/i18n/index.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"peerDependencies\": {\n \"react\": \"19.2.5\",\n \"react-dom\": \"19.2.5\",\n \"react-router\": \"7.14.2\"\n }\n}\n"],"mappings":""}
|
package/dist/package.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var e = {
|
|
2
2
|
name: "@openhands/agent-canvas",
|
|
3
|
-
version: "1.0.0-alpha.
|
|
3
|
+
version: "1.0.0-alpha.7",
|
|
4
4
|
description: "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
|
|
5
5
|
license: "MIT",
|
|
6
6
|
private: !1,
|
|
@@ -151,6 +151,7 @@ var e = {
|
|
|
151
151
|
"dist",
|
|
152
152
|
"bin",
|
|
153
153
|
"build",
|
|
154
|
+
"config",
|
|
154
155
|
"scripts"
|
|
155
156
|
],
|
|
156
157
|
exports: {
|
package/dist/package.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.0.0-alpha.
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.0.0-alpha.7\",\n \"description\": \"Agent Canvas UI for OpenHands - run AI coding agents with a visual interface\",\n \"license\": \"MIT\",\n \"private\": false,\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/OpenHands/agent-canvas\"\n },\n \"homepage\": \"https://github.com/OpenHands/agent-canvas#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/OpenHands/agent-canvas/issues\"\n },\n \"bin\": {\n \"agent-canvas\": \"bin/agent-canvas.mjs\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"dependencies\": {\n \"@heroui/react\": \"2.8.10\",\n \"@microlink/react-json-view\": \"1.31.20\",\n \"@monaco-editor/react\": \"4.7.0\",\n \"@openhands/extensions\": \"git+https://github.com/OpenHands/extensions.git#b8c1869ec9dea4467bb27d5754dc695d14e27889\",\n \"@openhands/typescript-client\": \"1.23.3\",\n \"@react-router/node\": \"7.14.2\",\n \"@react-router/serve\": \"7.14.2\",\n \"@tailwindcss/vite\": \"4.2.4\",\n \"@tanstack/react-query\": \"5.100.9\",\n \"@types/shell-quote\": \"^1.7.5\",\n \"@uidotdev/usehooks\": \"2.4.1\",\n \"@xterm/addon-fit\": \"0.11.0\",\n \"@xterm/xterm\": \"6.0.0\",\n \"axios\": \"1.16.0\",\n \"class-variance-authority\": \"0.7.1\",\n \"clsx\": \"2.1.1\",\n \"downshift\": \"9.3.2\",\n \"framer-motion\": \"12.38.0\",\n \"i18next\": \"26.0.8\",\n \"i18next-browser-languagedetector\": \"8.2.1\",\n \"i18next-http-backend\": \"4.0.0\",\n \"isbot\": \"5.1.39\",\n \"lucide-react\": \"1.14.0\",\n \"monaco-editor\": \"0.55.1\",\n \"posthog-js\": \"1.372.6\",\n \"react\": \"19.2.5\",\n \"react-dom\": \"19.2.5\",\n \"react-hot-toast\": \"2.6.0\",\n \"react-i18next\": \"17.0.6\",\n \"react-icons\": \"5.6.0\",\n \"react-markdown\": \"10.1.0\",\n \"react-router\": \"7.14.2\",\n \"react-syntax-highlighter\": \"16.1.1\",\n \"rehype-raw\": \"7.0.0\",\n \"rehype-sanitize\": \"6.0.0\",\n \"remark-breaks\": \"4.0.0\",\n \"remark-gfm\": \"4.0.1\",\n \"shell-quote\": \"^1.8.3\",\n \"sirv-cli\": \"3.0.1\",\n \"socket.io-client\": \"4.8.3\",\n \"tailwind-merge\": \"3.5.0\",\n \"tailwind-scrollbar\": \"4.0.2\",\n \"unist-util-visit\": \"5.1.0\",\n \"uuid\": \"14.0.0\",\n \"vite\": \"8.0.10\",\n \"zustand\": \"5.0.12\"\n },\n \"scripts\": {\n \"dev\": \"node --env-file-if-exists=.env scripts/dev-with-automation.mjs\",\n \"dev:static\": \"node --env-file-if-exists=.env scripts/dev-static.mjs\",\n \"dev:extra-backend\": \"node --env-file-if-exists=.env scripts/dev-extra-backend.mjs\",\n \"dev:minimal\": \"node --env-file-if-exists=.env scripts/dev-safe.mjs\",\n \"dev:frontend\": \"npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev\",\n \"dev:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev\",\n \"build\": \"npm run build:app\",\n \"build:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router build\",\n \"start\": \"npx sirv-cli build/ --single\",\n \"test\": \"npm run make-i18n && vitest run\",\n \"test:e2e\": \"playwright test --pass-with-no-tests\",\n \"test:e2e:live\": \"node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs\",\n \"test:e2e:snapshots\": \"playwright test tests/e2e/snapshots --project=chromium --retries=0\",\n \"test:e2e:snapshots:update\": \"playwright test tests/e2e/snapshots --project=chromium --update-snapshots\",\n \"test:coverage\": \"npm run make-i18n && vitest run --coverage\",\n \"dev_wsl\": \"VITE_WATCH_USE_POLLING=true vite\",\n \"preview\": \"vite preview\",\n \"make-i18n\": \"node scripts/make-i18n-translations.cjs\",\n \"prelint\": \"npm run make-i18n\",\n \"lint\": \"npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint src --fix && prettier --write src/**/*.{ts,tsx}\",\n \"prepare\": \"husky\",\n \"typecheck\": \"react-router typegen && tsc\",\n \"typecheck:staged\": \"react-router typegen && npx tsc --noEmit --skipLibCheck\",\n \"check-translation-completeness\": \"node scripts/check-translation-completeness.cjs\",\n \"build:app\": \"npm run make-i18n && react-router build\",\n \"build:lib\": \"npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true VITE_APP_ENV=production vite build && tsc -p tsconfig.lib.json\",\n \"build:docker\": \"node scripts/docker-build.mjs\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"src/**/*.{ts,tsx}\": [\n \"bash -c 'npm run typecheck:staged'\"\n ],\n \"src/**/*\": [\n \"npm run check-translation-completeness\"\n ]\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"3.3.1\",\n \"@eslint/js\": \"9.39.4\",\n \"@mswjs/socket.io-binding\": \"0.2.0\",\n \"@playwright/test\": \"1.59.1\",\n \"@react-router/dev\": \"7.14.2\",\n \"@tailwindcss/typography\": \"0.5.19\",\n \"@tanstack/eslint-plugin-query\": \"5.100.9\",\n \"@testing-library/dom\": \"10.4.1\",\n \"@testing-library/jest-dom\": \"6.9.1\",\n \"@testing-library/react\": \"16.3.2\",\n \"@testing-library/user-event\": \"14.6.1\",\n \"@types/mdast\": \"4.0.4\",\n \"@types/node\": \"25.6.0\",\n \"@types/react\": \"19.2.14\",\n \"@types/react-dom\": \"19.2.3\",\n \"@types/react-syntax-highlighter\": \"15.5.13\",\n \"@typescript-eslint/eslint-plugin\": \"8.59.2\",\n \"@typescript-eslint/parser\": \"8.59.2\",\n \"@vercel/react-router\": \"1.3.0\",\n \"@vitest/coverage-v8\": \"4.1.5\",\n \"cross-env\": \"10.1.0\",\n \"eslint\": \"9.39.4\",\n \"eslint-config-prettier\": \"10.1.8\",\n \"eslint-import-resolver-typescript\": \"4.4.4\",\n \"eslint-plugin-i18next\": \"6.1.4\",\n \"eslint-plugin-import-x\": \"4.16.2\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-prettier\": \"5.5.5\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-react-hooks\": \"7.1.1\",\n \"eslint-plugin-unused-imports\": \"4.4.1\",\n \"globals\": \"16.5.0\",\n \"husky\": \"9.1.7\",\n \"jsdom\": \"29.1.1\",\n \"lint-staged\": \"16.4.0\",\n \"msw\": \"2.14.2\",\n \"postcss-prefix-selector\": \"2.1.1\",\n \"prettier\": \"3.8.3\",\n \"tailwindcss\": \"4.2.4\",\n \"typescript\": \"6.0.3\",\n \"vite-plugin-svgr\": \"5.2.0\",\n \"vitest\": \"4.1.5\"\n },\n \"packageManager\": \"npm@10.5.0\",\n \"volta\": {\n \"node\": \"22.12.0\"\n },\n \"msw\": {\n \"workerDirectory\": [\n \"public\"\n ]\n },\n \"overrides\": {\n \"dompurify\": \"3.3.2\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"bin\",\n \"build\",\n \"config\",\n \"scripts\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./browser\": {\n \"types\": \"./dist/components/browser/index.d.ts\",\n \"import\": \"./dist/components/browser/index.js\",\n \"require\": \"./dist/components/browser/index.cjs\"\n },\n \"./conversation\": {\n \"types\": \"./dist/components/conversation/index.d.ts\",\n \"import\": \"./dist/components/conversation/index.js\",\n \"require\": \"./dist/components/conversation/index.cjs\"\n },\n \"./files\": {\n \"types\": \"./dist/components/files/index.d.ts\",\n \"import\": \"./dist/components/files/index.js\",\n \"require\": \"./dist/components/files/index.cjs\"\n },\n \"./settings\": {\n \"types\": \"./dist/components/settings/index.d.ts\",\n \"import\": \"./dist/components/settings/index.js\",\n \"require\": \"./dist/components/settings/index.cjs\"\n },\n \"./sidebar\": {\n \"types\": \"./dist/components/sidebar/index.d.ts\",\n \"import\": \"./dist/components/sidebar/index.js\",\n \"require\": \"./dist/components/sidebar/index.cjs\"\n },\n \"./terminal\": {\n \"types\": \"./dist/components/terminal/index.d.ts\",\n \"import\": \"./dist/components/terminal/index.js\",\n \"require\": \"./dist/components/terminal/index.cjs\"\n },\n \"./i18n\": {\n \"types\": \"./dist/i18n/index.d.ts\",\n \"import\": \"./dist/i18n/index.js\",\n \"require\": \"./dist/i18n/index.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"peerDependencies\": {\n \"react\": \"19.2.5\",\n \"react-dom\": \"19.2.5\",\n \"react-router\": \"7.14.2\"\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../node_modules/zustand/esm/react.cjs`);var t={errorMessage:null},n=e.create(e=>({...t,setErrorMessage:t=>e(()=>({errorMessage:t})),removeErrorMessage:()=>e(()=>({errorMessage:null}))}));exports.useErrorMessageStore=n;
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../node_modules/zustand/esm/react.cjs`);var t={errorMessage:null,errorType:null},n=e.create(e=>({...t,setErrorMessage:(t,n=`conversation`)=>e(()=>({errorMessage:t,errorType:n})),removeErrorMessage:()=>e(()=>({errorMessage:null,errorType:null})),clearConnectionError:()=>e(e=>e.errorType===`connection`?{errorMessage:null,errorType:null}:e)}));exports.useErrorMessageStore=n;
|
|
2
2
|
//# sourceMappingURL=error-message-store.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-message-store.cjs","names":[],"sources":["../../src/stores/error-message-store.ts"],"sourcesContent":["import { create } from \"zustand\";\n\ninterface ErrorMessageState {\n errorMessage: string | null;\n}\n\ninterface ErrorMessageActions {\n setErrorMessage: (message: string) => void;\n removeErrorMessage: () => void;\n}\n\ntype ErrorMessageStore = ErrorMessageState & ErrorMessageActions;\n\nconst initialState: ErrorMessageState = {\n errorMessage: null,\n};\n\nexport const useErrorMessageStore = create<ErrorMessageStore>((set) => ({\n ...initialState,\n\n setErrorMessage: (message: string) =>\n set(() => ({\n errorMessage: message,\n })),\n\n removeErrorMessage: () =>\n set(() => ({\n errorMessage: null,\n })),\n}));\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"error-message-store.cjs","names":[],"sources":["../../src/stores/error-message-store.ts"],"sourcesContent":["import { create } from \"zustand\";\n\n/**\n * \"connection\" errors auto-clear once connectivity recovers; \"conversation\"\n * errors (e.g. a wrong API key) are sticky and clear only on an explicit user\n * action (dismiss, retry, new message).\n */\nexport type ErrorMessageType = \"connection\" | \"conversation\";\n\ninterface ErrorMessageState {\n errorMessage: string | null;\n errorType: ErrorMessageType | null;\n}\n\ninterface ErrorMessageActions {\n setErrorMessage: (message: string, type?: ErrorMessageType) => void;\n removeErrorMessage: () => void;\n /** Clears the error only when it is a transient connection error. */\n clearConnectionError: () => void;\n}\n\ntype ErrorMessageStore = ErrorMessageState & ErrorMessageActions;\n\nconst initialState: ErrorMessageState = {\n errorMessage: null,\n errorType: null,\n};\n\nexport const useErrorMessageStore = create<ErrorMessageStore>((set) => ({\n ...initialState,\n\n setErrorMessage: (message: string, type: ErrorMessageType = \"conversation\") =>\n set(() => ({\n errorMessage: message,\n errorType: type,\n })),\n\n removeErrorMessage: () =>\n set(() => ({\n errorMessage: null,\n errorType: null,\n })),\n\n clearConnectionError: () =>\n set((state) =>\n state.errorType === \"connection\"\n ? { errorMessage: null, errorType: null }\n : state,\n ),\n}));\n"],"mappings":"sGAuBA,IAAM,EAAkC,CACtC,aAAc,KACd,UAAW,KACZ,CAEY,EAAuB,EAAA,OAA2B,IAAS,CACtE,GAAG,EAEH,iBAAkB,EAAiB,EAAyB,iBAC1D,OAAW,CACT,aAAc,EACd,UAAW,EACZ,EAAE,CAEL,uBACE,OAAW,CACT,aAAc,KACd,UAAW,KACZ,EAAE,CAEL,yBACE,EAAK,GACH,EAAM,YAAc,aAChB,CAAE,aAAc,KAAM,UAAW,KAAM,CACvC,EACL,CACJ,EAAE"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "connection" errors auto-clear once connectivity recovers; "conversation"
|
|
3
|
+
* errors (e.g. a wrong API key) are sticky and clear only on an explicit user
|
|
4
|
+
* action (dismiss, retry, new message).
|
|
5
|
+
*/
|
|
6
|
+
export type ErrorMessageType = "connection" | "conversation";
|
|
1
7
|
interface ErrorMessageState {
|
|
2
8
|
errorMessage: string | null;
|
|
9
|
+
errorType: ErrorMessageType | null;
|
|
3
10
|
}
|
|
4
11
|
interface ErrorMessageActions {
|
|
5
|
-
setErrorMessage: (message: string) => void;
|
|
12
|
+
setErrorMessage: (message: string, type?: ErrorMessageType) => void;
|
|
6
13
|
removeErrorMessage: () => void;
|
|
14
|
+
/** Clears the error only when it is a transient connection error. */
|
|
15
|
+
clearConnectionError: () => void;
|
|
7
16
|
}
|
|
8
17
|
type ErrorMessageStore = ErrorMessageState & ErrorMessageActions;
|
|
9
18
|
export declare const useErrorMessageStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ErrorMessageStore>>;
|
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import { create as e } from "../node_modules/zustand/esm/react.js";
|
|
2
2
|
//#region src/stores/error-message-store.ts
|
|
3
|
-
var t = {
|
|
3
|
+
var t = {
|
|
4
|
+
errorMessage: null,
|
|
5
|
+
errorType: null
|
|
6
|
+
}, n = e((e) => ({
|
|
4
7
|
...t,
|
|
5
|
-
setErrorMessage: (t) => e(() => ({
|
|
6
|
-
|
|
8
|
+
setErrorMessage: (t, n = "conversation") => e(() => ({
|
|
9
|
+
errorMessage: t,
|
|
10
|
+
errorType: n
|
|
11
|
+
})),
|
|
12
|
+
removeErrorMessage: () => e(() => ({
|
|
13
|
+
errorMessage: null,
|
|
14
|
+
errorType: null
|
|
15
|
+
})),
|
|
16
|
+
clearConnectionError: () => e((e) => e.errorType === "connection" ? {
|
|
17
|
+
errorMessage: null,
|
|
18
|
+
errorType: null
|
|
19
|
+
} : e)
|
|
7
20
|
}));
|
|
8
21
|
//#endregion
|
|
9
22
|
export { n as useErrorMessageStore };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-message-store.js","names":[],"sources":["../../src/stores/error-message-store.ts"],"sourcesContent":["import { create } from \"zustand\";\n\ninterface ErrorMessageState {\n errorMessage: string | null;\n}\n\ninterface ErrorMessageActions {\n setErrorMessage: (message: string) => void;\n removeErrorMessage: () => void;\n}\n\ntype ErrorMessageStore = ErrorMessageState & ErrorMessageActions;\n\nconst initialState: ErrorMessageState = {\n errorMessage: null,\n};\n\nexport const useErrorMessageStore = create<ErrorMessageStore>((set) => ({\n ...initialState,\n\n setErrorMessage: (message: string) =>\n set(() => ({\n errorMessage: message,\n })),\n\n removeErrorMessage: () =>\n set(() => ({\n errorMessage: null,\n })),\n}));\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"error-message-store.js","names":[],"sources":["../../src/stores/error-message-store.ts"],"sourcesContent":["import { create } from \"zustand\";\n\n/**\n * \"connection\" errors auto-clear once connectivity recovers; \"conversation\"\n * errors (e.g. a wrong API key) are sticky and clear only on an explicit user\n * action (dismiss, retry, new message).\n */\nexport type ErrorMessageType = \"connection\" | \"conversation\";\n\ninterface ErrorMessageState {\n errorMessage: string | null;\n errorType: ErrorMessageType | null;\n}\n\ninterface ErrorMessageActions {\n setErrorMessage: (message: string, type?: ErrorMessageType) => void;\n removeErrorMessage: () => void;\n /** Clears the error only when it is a transient connection error. */\n clearConnectionError: () => void;\n}\n\ntype ErrorMessageStore = ErrorMessageState & ErrorMessageActions;\n\nconst initialState: ErrorMessageState = {\n errorMessage: null,\n errorType: null,\n};\n\nexport const useErrorMessageStore = create<ErrorMessageStore>((set) => ({\n ...initialState,\n\n setErrorMessage: (message: string, type: ErrorMessageType = \"conversation\") =>\n set(() => ({\n errorMessage: message,\n errorType: type,\n })),\n\n removeErrorMessage: () =>\n set(() => ({\n errorMessage: null,\n errorType: null,\n })),\n\n clearConnectionError: () =>\n set((state) =>\n state.errorType === \"connection\"\n ? { errorMessage: null, errorType: null }\n : state,\n ),\n}));\n"],"mappings":";;AAuBA,IAAM,IAAkC;CACtC,cAAc;CACd,WAAW;CACZ,EAEY,IAAuB,GAA2B,OAAS;CACtE,GAAG;CAEH,kBAAkB,GAAiB,IAAyB,mBAC1D,SAAW;EACT,cAAc;EACd,WAAW;EACZ,EAAE;CAEL,0BACE,SAAW;EACT,cAAc;EACd,WAAW;EACZ,EAAE;CAEL,4BACE,GAAK,MACH,EAAM,cAAc,eAChB;EAAE,cAAc;EAAM,WAAW;EAAM,GACvC,EACL;CACJ,EAAE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openhands/agent-canvas",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.7",
|
|
4
4
|
"description": "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -172,6 +172,7 @@
|
|
|
172
172
|
"dist",
|
|
173
173
|
"bin",
|
|
174
174
|
"build",
|
|
175
|
+
"config",
|
|
175
176
|
"scripts"
|
|
176
177
|
],
|
|
177
178
|
"exports": {
|
package/scripts/dev-static.mjs
CHANGED
|
@@ -324,13 +324,14 @@ function startAgentServer(config) {
|
|
|
324
324
|
}
|
|
325
325
|
|
|
326
326
|
function buildAutomationBackendEnv(config) {
|
|
327
|
+
// Both backends share the same session API key value.
|
|
327
328
|
return {
|
|
328
329
|
AUTOMATION_AGENT_SERVER_URL: `http://localhost:${config.agentServerPort}`,
|
|
329
330
|
AUTOMATION_AGENT_SERVER_API_KEY: config.sessionApiKey,
|
|
330
331
|
AUTOMATION_DB_URL: `sqlite+aiosqlite:///${join(config.stateDir, "automations.db")}`,
|
|
331
332
|
AUTOMATION_BASE_URL: `http://localhost:${config.ingressPort}`,
|
|
332
333
|
AUTOMATION_WORKSPACE_BASE: join(config.stateDir, "workspaces"),
|
|
333
|
-
AUTOMATION_LOCAL_API_KEY: config.
|
|
334
|
+
AUTOMATION_LOCAL_API_KEY: config.sessionApiKey,
|
|
334
335
|
AUTOMATION_CORS_ORIGINS: `http://localhost:${config.ingressPort},http://127.0.0.1:${config.ingressPort},http://localhost:3001,http://127.0.0.1:3001`,
|
|
335
336
|
FILE_STORE: "local",
|
|
336
337
|
LOCAL_STORAGE_PATH: join(config.stateDir, "storage"),
|
|
@@ -387,6 +388,12 @@ function startStaticServer(config) {
|
|
|
387
388
|
"0.0.0.0",
|
|
388
389
|
"--port",
|
|
389
390
|
String(config.vitePort),
|
|
391
|
+
// Inject the runtime session key so the pre-built frontend can
|
|
392
|
+
// authenticate to agent-server without VITE_SESSION_API_KEY being baked
|
|
393
|
+
// into the bundle at publish time.
|
|
394
|
+
...(config.sessionApiKey
|
|
395
|
+
? ["--session-api-key", config.sessionApiKey]
|
|
396
|
+
: []),
|
|
390
397
|
"--route",
|
|
391
398
|
`/api/automation=http://localhost:${config.autoBackendPort}`,
|
|
392
399
|
"--route",
|
|
@@ -35,12 +35,11 @@
|
|
|
35
35
|
* openhands-tools and openhands-workspace as editable so source edits are
|
|
36
36
|
* picked up without manual reinstall.
|
|
37
37
|
* - OH_AGENT_SERVER_GIT_REF: Git ref for agent-server
|
|
38
|
-
* - AUTOMATION_LOCAL_API_KEY: Custom API key for automation backend auth
|
|
39
|
-
* - OH_AUTOMATION_API_KEY_PATH: Override persisted default automation key path
|
|
40
|
-
*
|
|
41
38
|
* Secrets:
|
|
42
|
-
* The
|
|
39
|
+
* The session API key is automatically seeded into agent-server secrets
|
|
43
40
|
* as OPENHANDS_AUTOMATION_API_KEY, making it available to agents in conversations.
|
|
41
|
+
* Both the agent-server and automation backend use the same key value
|
|
42
|
+
* and the same `X-Session-API-Key` header for authentication.
|
|
44
43
|
*/
|
|
45
44
|
|
|
46
45
|
import { spawn, spawnSync } from "node:child_process";
|
|
@@ -86,15 +85,6 @@ const DEFAULT_AUTOMATION_VERSION = SHARED_DEFAULTS.versions.automation;
|
|
|
86
85
|
const DEFAULT_AUTOMATION_SDK_VERSION = SHARED_DEFAULTS.versions.automationSdk;
|
|
87
86
|
const DEFAULT_BACKEND_PORT = SHARED_DEFAULTS.ports.agentServer;
|
|
88
87
|
const DEFAULT_AUTOMATION_PORT = SHARED_DEFAULTS.ports.automation;
|
|
89
|
-
// Where the auto-generated default automation API key is persisted. Static
|
|
90
|
-
// frontend builds bake VITE_AUTOMATION_API_KEY at build time, so the default
|
|
91
|
-
// must remain stable across restarts and --skip-build reuse.
|
|
92
|
-
const DEFAULT_AUTOMATION_API_KEY_PATH = join(
|
|
93
|
-
homedir(),
|
|
94
|
-
".openhands",
|
|
95
|
-
"agent-canvas",
|
|
96
|
-
"automation-api-key.txt",
|
|
97
|
-
);
|
|
98
88
|
|
|
99
89
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
100
90
|
// Terminal Styling
|
|
@@ -213,12 +203,11 @@ ENVIRONMENT VARIABLES:
|
|
|
213
203
|
OH_AGENT_SERVER_GIT_REF Git ref for agent-server SDK (overrides default version)
|
|
214
204
|
OH_AGENT_SERVER_VERSION Specific PyPI version for agent-server
|
|
215
205
|
OH_SECRET_KEY Secret key for sessions
|
|
216
|
-
AUTOMATION_LOCAL_API_KEY Custom API key for automation backend auth
|
|
217
|
-
OH_AUTOMATION_API_KEY_PATH Override persisted default automation key path
|
|
218
206
|
|
|
219
207
|
SECRETS:
|
|
220
|
-
The
|
|
208
|
+
The session API key is automatically seeded into agent-server secrets
|
|
221
209
|
as OPENHANDS_AUTOMATION_API_KEY, making it available to agents in conversations.
|
|
210
|
+
Both backends (agent-server and automation) share the same key value.
|
|
222
211
|
|
|
223
212
|
ACCESS POINTS:
|
|
224
213
|
Main UI: http://localhost:PORT/
|
|
@@ -339,17 +328,8 @@ async function buildConfig(args, env = process.env) {
|
|
|
339
328
|
|
|
340
329
|
const vscodePort = ports.backend + 1000;
|
|
341
330
|
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
const automationApiKeyPath =
|
|
345
|
-
env.OH_AUTOMATION_API_KEY_PATH || DEFAULT_AUTOMATION_API_KEY_PATH;
|
|
346
|
-
const localApiKey =
|
|
347
|
-
env.AUTOMATION_LOCAL_API_KEY ||
|
|
348
|
-
getOrCreatePersistedApiKey(automationApiKeyPath, "automation");
|
|
349
|
-
|
|
350
|
-
// Session API key for agent-server auth
|
|
351
|
-
// Build a preliminary safe config to get the auto-generated session key
|
|
352
|
-
// This ensures both agent-server and frontend use the same key
|
|
331
|
+
// Session API key — shared by both agent-server and automation backend.
|
|
332
|
+
// Both validate it via the `X-Session-API-Key` header.
|
|
353
333
|
const stateDir = join(homedir(), ".openhands", "agent-canvas");
|
|
354
334
|
const safeConfig = buildSafeDevConfig(projectRoot, {
|
|
355
335
|
...env,
|
|
@@ -375,8 +355,7 @@ async function buildConfig(args, env = process.env) {
|
|
|
375
355
|
// Data directories (same as dev-safe.mjs)
|
|
376
356
|
stateDir,
|
|
377
357
|
|
|
378
|
-
// Auth
|
|
379
|
-
localApiKey,
|
|
358
|
+
// Auth — single key for both backends
|
|
380
359
|
sessionApiKey,
|
|
381
360
|
|
|
382
361
|
verbose: args.verbose,
|
|
@@ -530,12 +509,13 @@ async function waitForService(name, url, timeoutMs = 30000) {
|
|
|
530
509
|
|
|
531
510
|
function buildAgentServerAutomationEnv(config) {
|
|
532
511
|
return {
|
|
533
|
-
// Make the
|
|
534
|
-
//
|
|
535
|
-
// > Secrets, but agents commonly create automations
|
|
536
|
-
// that references `$OPENHANDS_AUTOMATION_API_KEY`;
|
|
537
|
-
// that path working even before/without
|
|
538
|
-
|
|
512
|
+
// Make the session API key available to terminal commands spawned by the
|
|
513
|
+
// agent-server as OPENHANDS_AUTOMATION_API_KEY. The launcher also seeds
|
|
514
|
+
// this into Settings > Secrets, but agents commonly create automations
|
|
515
|
+
// with a curl command that references `$OPENHANDS_AUTOMATION_API_KEY`;
|
|
516
|
+
// exposing it here keeps that path working even before/without
|
|
517
|
+
// secret-registry env expansion.
|
|
518
|
+
OPENHANDS_AUTOMATION_API_KEY: config.sessionApiKey,
|
|
539
519
|
};
|
|
540
520
|
}
|
|
541
521
|
|
|
@@ -651,8 +631,8 @@ function startAutomationBackend(config) {
|
|
|
651
631
|
process.env.AUTOMATION_WORKSPACE_BASE ||
|
|
652
632
|
config.automationWorkspaceBase ||
|
|
653
633
|
join(config.stateDir, "workspaces"),
|
|
654
|
-
//
|
|
655
|
-
AUTOMATION_LOCAL_API_KEY: config.
|
|
634
|
+
// Session API key for self-hosted auth — shared with agent-server via X-Session-API-Key header
|
|
635
|
+
AUTOMATION_LOCAL_API_KEY: config.sessionApiKey,
|
|
656
636
|
// CORS: allow localhost origins for dev
|
|
657
637
|
AUTOMATION_CORS_ORIGINS: `http://localhost:${config.ingressPort},http://127.0.0.1:${config.ingressPort},http://localhost:3001,http://127.0.0.1:3001`,
|
|
658
638
|
FILE_STORE: "local",
|
|
@@ -775,29 +755,25 @@ function startVite(config) {
|
|
|
775
755
|
VITE_WORKING_DIR:
|
|
776
756
|
config.viteWorkingDir ?? join(config.stateDir, "workspaces"),
|
|
777
757
|
VITE_FRONTEND_PORT: config.vitePort.toString(),
|
|
778
|
-
// Session API key
|
|
758
|
+
// Session API key — used by the frontend for both agent-server and
|
|
759
|
+
// automation auth via the `X-Session-API-Key` header.
|
|
779
760
|
VITE_SESSION_API_KEY: config.sessionApiKey,
|
|
780
|
-
// Automation API key for frontend to authenticate with automation backend
|
|
781
|
-
VITE_AUTOMATION_API_KEY: config.localApiKey,
|
|
782
761
|
// Inform the frontend (and downstream, the agent's system prompt) about
|
|
783
762
|
// which services are available in this dev stack.
|
|
784
763
|
VITE_RUNTIME_SERVICES_INFO: JSON.stringify(runtimeServicesInfo),
|
|
785
|
-
// Session API key for agent-server auth (when SESSION_API_KEY is set)
|
|
786
|
-
...(config.sessionApiKey && {
|
|
787
|
-
VITE_SESSION_API_KEY: config.sessionApiKey,
|
|
788
|
-
}),
|
|
789
764
|
},
|
|
790
765
|
color: c.magenta,
|
|
791
766
|
});
|
|
792
767
|
}
|
|
793
768
|
|
|
794
769
|
/**
|
|
795
|
-
* Seed the
|
|
796
|
-
*
|
|
770
|
+
* Seed the session API key into agent-server's secrets store as
|
|
771
|
+
* OPENHANDS_AUTOMATION_API_KEY so agents can authenticate with the
|
|
772
|
+
* automation backend in curl commands during conversations.
|
|
797
773
|
*
|
|
798
774
|
* Includes retry logic to handle slow server startup or transient failures.
|
|
799
775
|
*
|
|
800
|
-
* @param {object} config - Configuration object with agentServerPort,
|
|
776
|
+
* @param {object} config - Configuration object with agentServerPort, sessionApiKey
|
|
801
777
|
* @param {object} options - Options for retry behavior
|
|
802
778
|
* @param {number} options.maxRetries - Maximum number of retry attempts (default: 5)
|
|
803
779
|
* @param {number} options.retryDelayMs - Delay between retries in ms (default: 2000)
|
|
@@ -816,7 +792,7 @@ async function seedAutomationSecret(config, options = {}) {
|
|
|
816
792
|
const url = `http://localhost:${config.agentServerPort}/api/settings/secrets`;
|
|
817
793
|
const body = JSON.stringify({
|
|
818
794
|
name: secretName,
|
|
819
|
-
value: config.
|
|
795
|
+
value: config.sessionApiKey,
|
|
820
796
|
description: secretDescription,
|
|
821
797
|
});
|
|
822
798
|
|
|
@@ -1085,6 +1061,12 @@ function startStaticFrontend(config, staticDir) {
|
|
|
1085
1061
|
"0.0.0.0",
|
|
1086
1062
|
"--port",
|
|
1087
1063
|
String(config.vitePort),
|
|
1064
|
+
// Inject the runtime session key so the pre-built frontend can
|
|
1065
|
+
// authenticate to agent-server without VITE_SESSION_API_KEY being baked
|
|
1066
|
+
// into the bundle at publish time.
|
|
1067
|
+
...(config.sessionApiKey
|
|
1068
|
+
? ["--session-api-key", config.sessionApiKey]
|
|
1069
|
+
: []),
|
|
1088
1070
|
// Proxy routes to backends (same as ingress but for direct access to vitePort)
|
|
1089
1071
|
"--route",
|
|
1090
1072
|
`/api/automation=http://localhost:${config.autoBackendPort}`,
|
|
@@ -1137,7 +1119,6 @@ export {
|
|
|
1137
1119
|
DEFAULT_AUTOMATION_SDK_VERSION,
|
|
1138
1120
|
DEFAULT_BACKEND_PORT,
|
|
1139
1121
|
DEFAULT_AUTOMATION_PORT,
|
|
1140
|
-
DEFAULT_AUTOMATION_API_KEY_PATH,
|
|
1141
1122
|
};
|
|
1142
1123
|
|
|
1143
1124
|
// ═══════════════════════════════════════════════════════════════════════════
|
package/scripts/static-build.mjs
CHANGED
|
@@ -49,12 +49,8 @@ export function buildFrontend(config, args = {}) {
|
|
|
49
49
|
// to Vite.
|
|
50
50
|
VITE_WORKING_DIR:
|
|
51
51
|
config.viteWorkingDir ?? join(config.stateDir, "workspaces"),
|
|
52
|
-
// Bake the
|
|
53
|
-
//
|
|
54
|
-
VITE_AUTOMATION_API_KEY: config.localApiKey,
|
|
55
|
-
// Bake the same session key the agent-server accepts. Without this,
|
|
56
|
-
// a fresh browser session seeds the Local backend with an empty key and
|
|
57
|
-
// all authenticated agent-server calls fail with 401.
|
|
52
|
+
// Bake the session API key — used by the frontend for both agent-server
|
|
53
|
+
// and automation auth via the `X-Session-API-Key` header.
|
|
58
54
|
VITE_SESSION_API_KEY: config.sessionApiKey,
|
|
59
55
|
// Bake a description of the runtime services in this dev stack so the
|
|
60
56
|
// frontend can populate the agent's <RUNTIME_SERVICES> system-prompt
|