@tianshu-ai/tianshu 0.3.0
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/LICENSE +200 -0
- package/README.md +284 -0
- package/README.zh-CN.md +136 -0
- package/bin/tianshu.mjs +32 -0
- package/package.json +60 -0
- package/packages/plugin-sdk/dist/agent-loop.d.ts +96 -0
- package/packages/plugin-sdk/dist/agent-loop.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/agent-loop.js +11 -0
- package/packages/plugin-sdk/dist/agent-loop.js.map +1 -0
- package/packages/plugin-sdk/dist/capabilities.d.ts +48 -0
- package/packages/plugin-sdk/dist/capabilities.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/capabilities.js +61 -0
- package/packages/plugin-sdk/dist/capabilities.js.map +1 -0
- package/packages/plugin-sdk/dist/catalog.d.ts +60 -0
- package/packages/plugin-sdk/dist/catalog.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/catalog.js +11 -0
- package/packages/plugin-sdk/dist/catalog.js.map +1 -0
- package/packages/plugin-sdk/dist/client.d.ts +171 -0
- package/packages/plugin-sdk/dist/client.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/client.js +96 -0
- package/packages/plugin-sdk/dist/client.js.map +1 -0
- package/packages/plugin-sdk/dist/index.d.ts +9 -0
- package/packages/plugin-sdk/dist/index.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/index.js +19 -0
- package/packages/plugin-sdk/dist/index.js.map +1 -0
- package/packages/plugin-sdk/dist/lsp.d.ts +32 -0
- package/packages/plugin-sdk/dist/lsp.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/lsp.js +19 -0
- package/packages/plugin-sdk/dist/lsp.js.map +1 -0
- package/packages/plugin-sdk/dist/manifest.d.ts +423 -0
- package/packages/plugin-sdk/dist/manifest.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/manifest.js +7 -0
- package/packages/plugin-sdk/dist/manifest.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-client.d.ts +74 -0
- package/packages/plugin-sdk/dist/mcp-client.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-client.js +226 -0
- package/packages/plugin-sdk/dist/mcp-client.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-fetch.d.ts +10 -0
- package/packages/plugin-sdk/dist/mcp-fetch.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-fetch.js +130 -0
- package/packages/plugin-sdk/dist/mcp-fetch.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-toolset.d.ts +128 -0
- package/packages/plugin-sdk/dist/mcp-toolset.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-toolset.js +246 -0
- package/packages/plugin-sdk/dist/mcp-toolset.js.map +1 -0
- package/packages/plugin-sdk/dist/server.d.ts +486 -0
- package/packages/plugin-sdk/dist/server.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/server.js +10 -0
- package/packages/plugin-sdk/dist/server.js.map +1 -0
- package/packages/plugin-sdk/dist/session-inbox.d.ts +56 -0
- package/packages/plugin-sdk/dist/session-inbox.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/session-inbox.js +12 -0
- package/packages/plugin-sdk/dist/session-inbox.js.map +1 -0
- package/packages/plugin-sdk/package.json +36 -0
- package/packages/server/builtinConfig/plugins/README.md +1 -0
- package/packages/server/builtinConfig/plugins/files/manifest.json +100 -0
- package/packages/server/builtinConfig/plugins/files/skills/files-workspace-layout.md +29 -0
- package/packages/server/builtinConfig/plugins/microsandbox/manifest.json +177 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-browser-howto.md +155 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-build-use.md +201 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-config.md +38 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-exec-howto.md +144 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-libreoffice.md +159 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-main-orchestration.md +75 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/README.md +26 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/browser.yaml +105 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/task-runner-with-browser.yaml +80 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/task-runner.yaml +80 -0
- package/packages/server/builtinConfig/plugins/web-search/manifest.json +65 -0
- package/packages/server/builtinConfig/plugins/web-search/skills/web-search-howto.md +69 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/echo-demo/agent.json +7 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/llm-default/SOUL.md +53 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/llm-default/agent.json +7 -0
- package/packages/server/builtinConfig/plugins/workboard/manifest.json +180 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/large-input-large-output.md +185 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/workboard-howto.md +166 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/worker-creator.md +267 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/worker-fleet.md +431 -0
- package/packages/server/dist/catalog.d.ts +52 -0
- package/packages/server/dist/catalog.d.ts.map +1 -0
- package/packages/server/dist/catalog.js +189 -0
- package/packages/server/dist/catalog.js.map +1 -0
- package/packages/server/dist/chat/active-harnesses.d.ts +34 -0
- package/packages/server/dist/chat/active-harnesses.d.ts.map +1 -0
- package/packages/server/dist/chat/active-harnesses.js +118 -0
- package/packages/server/dist/chat/active-harnesses.js.map +1 -0
- package/packages/server/dist/chat/agent-loop.d.ts +64 -0
- package/packages/server/dist/chat/agent-loop.d.ts.map +1 -0
- package/packages/server/dist/chat/agent-loop.js +597 -0
- package/packages/server/dist/chat/agent-loop.js.map +1 -0
- package/packages/server/dist/chat/agent-tool-adapter.d.ts +33 -0
- package/packages/server/dist/chat/agent-tool-adapter.d.ts.map +1 -0
- package/packages/server/dist/chat/agent-tool-adapter.js +260 -0
- package/packages/server/dist/chat/agent-tool-adapter.js.map +1 -0
- package/packages/server/dist/chat/compact.d.ts +52 -0
- package/packages/server/dist/chat/compact.d.ts.map +1 -0
- package/packages/server/dist/chat/compact.js +248 -0
- package/packages/server/dist/chat/compact.js.map +1 -0
- package/packages/server/dist/chat/dump-system-prompt.d.ts +17 -0
- package/packages/server/dist/chat/dump-system-prompt.d.ts.map +1 -0
- package/packages/server/dist/chat/dump-system-prompt.js +58 -0
- package/packages/server/dist/chat/dump-system-prompt.js.map +1 -0
- package/packages/server/dist/chat/handler.d.ts +186 -0
- package/packages/server/dist/chat/handler.d.ts.map +1 -0
- package/packages/server/dist/chat/handler.js +1248 -0
- package/packages/server/dist/chat/handler.js.map +1 -0
- package/packages/server/dist/chat/image-fit.d.ts +34 -0
- package/packages/server/dist/chat/image-fit.d.ts.map +1 -0
- package/packages/server/dist/chat/image-fit.js +157 -0
- package/packages/server/dist/chat/image-fit.js.map +1 -0
- package/packages/server/dist/chat/messages.d.ts +118 -0
- package/packages/server/dist/chat/messages.d.ts.map +1 -0
- package/packages/server/dist/chat/messages.js +341 -0
- package/packages/server/dist/chat/messages.js.map +1 -0
- package/packages/server/dist/chat/session-inbox.d.ts +114 -0
- package/packages/server/dist/chat/session-inbox.d.ts.map +1 -0
- package/packages/server/dist/chat/session-inbox.js +418 -0
- package/packages/server/dist/chat/session-inbox.js.map +1 -0
- package/packages/server/dist/chat/sqlite-session-repo.d.ts +26 -0
- package/packages/server/dist/chat/sqlite-session-repo.d.ts.map +1 -0
- package/packages/server/dist/chat/sqlite-session-repo.js +132 -0
- package/packages/server/dist/chat/sqlite-session-repo.js.map +1 -0
- package/packages/server/dist/chat/sqlite-session-storage.d.ts +83 -0
- package/packages/server/dist/chat/sqlite-session-storage.d.ts.map +1 -0
- package/packages/server/dist/chat/sqlite-session-storage.js +418 -0
- package/packages/server/dist/chat/sqlite-session-storage.js.map +1 -0
- package/packages/server/dist/chat/stub-execution-env.d.ts +3 -0
- package/packages/server/dist/chat/stub-execution-env.d.ts.map +1 -0
- package/packages/server/dist/chat/stub-execution-env.js +87 -0
- package/packages/server/dist/chat/stub-execution-env.js.map +1 -0
- package/packages/server/dist/chat/token-estimate.d.ts +11 -0
- package/packages/server/dist/chat/token-estimate.d.ts.map +1 -0
- package/packages/server/dist/chat/token-estimate.js +67 -0
- package/packages/server/dist/chat/token-estimate.js.map +1 -0
- package/packages/server/dist/chat/ws-protocol.d.ts +244 -0
- package/packages/server/dist/chat/ws-protocol.d.ts.map +1 -0
- package/packages/server/dist/chat/ws-protocol.js +193 -0
- package/packages/server/dist/chat/ws-protocol.js.map +1 -0
- package/packages/server/dist/cli.d.ts +9 -0
- package/packages/server/dist/cli.d.ts.map +1 -0
- package/packages/server/dist/cli.js +329 -0
- package/packages/server/dist/cli.js.map +1 -0
- package/packages/server/dist/core/agent-seeds.d.ts +25 -0
- package/packages/server/dist/core/agent-seeds.d.ts.map +1 -0
- package/packages/server/dist/core/agent-seeds.js +69 -0
- package/packages/server/dist/core/agent-seeds.js.map +1 -0
- package/packages/server/dist/core/config.d.ts +172 -0
- package/packages/server/dist/core/config.d.ts.map +1 -0
- package/packages/server/dist/core/config.js +155 -0
- package/packages/server/dist/core/config.js.map +1 -0
- package/packages/server/dist/core/db-pool.d.ts +32 -0
- package/packages/server/dist/core/db-pool.d.ts.map +1 -0
- package/packages/server/dist/core/db-pool.js +108 -0
- package/packages/server/dist/core/db-pool.js.map +1 -0
- package/packages/server/dist/core/dev-mode.d.ts +13 -0
- package/packages/server/dist/core/dev-mode.d.ts.map +1 -0
- package/packages/server/dist/core/dev-mode.js +51 -0
- package/packages/server/dist/core/dev-mode.js.map +1 -0
- package/packages/server/dist/core/global-ops.d.ts +54 -0
- package/packages/server/dist/core/global-ops.d.ts.map +1 -0
- package/packages/server/dist/core/global-ops.js +143 -0
- package/packages/server/dist/core/global-ops.js.map +1 -0
- package/packages/server/dist/core/identity-resolvers.d.ts +102 -0
- package/packages/server/dist/core/identity-resolvers.d.ts.map +1 -0
- package/packages/server/dist/core/identity-resolvers.js +176 -0
- package/packages/server/dist/core/identity-resolvers.js.map +1 -0
- package/packages/server/dist/core/index.d.ts +13 -0
- package/packages/server/dist/core/index.d.ts.map +1 -0
- package/packages/server/dist/core/index.js +18 -0
- package/packages/server/dist/core/index.js.map +1 -0
- package/packages/server/dist/core/llm.d.ts +45 -0
- package/packages/server/dist/core/llm.d.ts.map +1 -0
- package/packages/server/dist/core/llm.js +140 -0
- package/packages/server/dist/core/llm.js.map +1 -0
- package/packages/server/dist/core/mcp-manager.d.ts +47 -0
- package/packages/server/dist/core/mcp-manager.d.ts.map +1 -0
- package/packages/server/dist/core/mcp-manager.js +129 -0
- package/packages/server/dist/core/mcp-manager.js.map +1 -0
- package/packages/server/dist/core/middleware.d.ts +31 -0
- package/packages/server/dist/core/middleware.d.ts.map +1 -0
- package/packages/server/dist/core/middleware.js +102 -0
- package/packages/server/dist/core/middleware.js.map +1 -0
- package/packages/server/dist/core/migrations/001-initial.d.ts +4 -0
- package/packages/server/dist/core/migrations/001-initial.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/001-initial.js +66 -0
- package/packages/server/dist/core/migrations/001-initial.js.map +1 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.d.ts +4 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.js +20 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.js.map +1 -0
- package/packages/server/dist/core/migrations/003-session-tree.d.ts +4 -0
- package/packages/server/dist/core/migrations/003-session-tree.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/003-session-tree.js +96 -0
- package/packages/server/dist/core/migrations/003-session-tree.js.map +1 -0
- package/packages/server/dist/core/migrations/003-worker-agents.d.ts +4 -0
- package/packages/server/dist/core/migrations/003-worker-agents.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/003-worker-agents.js +65 -0
- package/packages/server/dist/core/migrations/003-worker-agents.js.map +1 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.d.ts +4 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.js +52 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.js.map +1 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.d.ts +4 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.js +64 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.js.map +1 -0
- package/packages/server/dist/core/migrations/006-task-labels.d.ts +4 -0
- package/packages/server/dist/core/migrations/006-task-labels.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/006-task-labels.js +43 -0
- package/packages/server/dist/core/migrations/006-task-labels.js.map +1 -0
- package/packages/server/dist/core/migrations/007-session-inbox.d.ts +4 -0
- package/packages/server/dist/core/migrations/007-session-inbox.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/007-session-inbox.js +67 -0
- package/packages/server/dist/core/migrations/007-session-inbox.js.map +1 -0
- package/packages/server/dist/core/migrations/008-task-intervention.d.ts +4 -0
- package/packages/server/dist/core/migrations/008-task-intervention.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/008-task-intervention.js +60 -0
- package/packages/server/dist/core/migrations/008-task-intervention.js.map +1 -0
- package/packages/server/dist/core/migrations/index.d.ts +12 -0
- package/packages/server/dist/core/migrations/index.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/index.js +58 -0
- package/packages/server/dist/core/migrations/index.js.map +1 -0
- package/packages/server/dist/core/paths.d.ts +53 -0
- package/packages/server/dist/core/paths.d.ts.map +1 -0
- package/packages/server/dist/core/paths.js +125 -0
- package/packages/server/dist/core/paths.js.map +1 -0
- package/packages/server/dist/core/plugins/builtin-loader.d.ts +56 -0
- package/packages/server/dist/core/plugins/builtin-loader.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/builtin-loader.js +153 -0
- package/packages/server/dist/core/plugins/builtin-loader.js.map +1 -0
- package/packages/server/dist/core/plugins/discovery.d.ts +28 -0
- package/packages/server/dist/core/plugins/discovery.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/discovery.js +97 -0
- package/packages/server/dist/core/plugins/discovery.js.map +1 -0
- package/packages/server/dist/core/plugins/index.d.ts +6 -0
- package/packages/server/dist/core/plugins/index.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/index.js +6 -0
- package/packages/server/dist/core/plugins/index.js.map +1 -0
- package/packages/server/dist/core/plugins/manifest.d.ts +9 -0
- package/packages/server/dist/core/plugins/manifest.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/manifest.js +584 -0
- package/packages/server/dist/core/plugins/manifest.js.map +1 -0
- package/packages/server/dist/core/plugins/registry.d.ts +269 -0
- package/packages/server/dist/core/plugins/registry.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/registry.js +1003 -0
- package/packages/server/dist/core/plugins/registry.js.map +1 -0
- package/packages/server/dist/core/plugins/secrets.d.ts +46 -0
- package/packages/server/dist/core/plugins/secrets.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/secrets.js +174 -0
- package/packages/server/dist/core/plugins/secrets.js.map +1 -0
- package/packages/server/dist/core/plugins/skills.d.ts +131 -0
- package/packages/server/dist/core/plugins/skills.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/skills.js +389 -0
- package/packages/server/dist/core/plugins/skills.js.map +1 -0
- package/packages/server/dist/core/templates.d.ts +28 -0
- package/packages/server/dist/core/templates.d.ts.map +1 -0
- package/packages/server/dist/core/templates.js +103 -0
- package/packages/server/dist/core/templates.js.map +1 -0
- package/packages/server/dist/core/tenant-context.d.ts +18 -0
- package/packages/server/dist/core/tenant-context.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-context.js +42 -0
- package/packages/server/dist/core/tenant-context.js.map +1 -0
- package/packages/server/dist/core/tenant-id.d.ts +8 -0
- package/packages/server/dist/core/tenant-id.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-id.js +53 -0
- package/packages/server/dist/core/tenant-id.js.map +1 -0
- package/packages/server/dist/core/tenant-skills.d.ts +29 -0
- package/packages/server/dist/core/tenant-skills.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-skills.js +77 -0
- package/packages/server/dist/core/tenant-skills.js.map +1 -0
- package/packages/server/dist/core/worker-agents-fs.d.ts +44 -0
- package/packages/server/dist/core/worker-agents-fs.d.ts.map +1 -0
- package/packages/server/dist/core/worker-agents-fs.js +86 -0
- package/packages/server/dist/core/worker-agents-fs.js.map +1 -0
- package/packages/server/dist/core/worker-agents.d.ts +77 -0
- package/packages/server/dist/core/worker-agents.d.ts.map +1 -0
- package/packages/server/dist/core/worker-agents.js +191 -0
- package/packages/server/dist/core/worker-agents.js.map +1 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.d.ts.map +1 -0
- package/packages/server/dist/index.js +623 -0
- package/packages/server/dist/index.js.map +1 -0
- package/packages/server/dist/lsp/client.d.ts +53 -0
- package/packages/server/dist/lsp/client.d.ts.map +1 -0
- package/packages/server/dist/lsp/client.js +258 -0
- package/packages/server/dist/lsp/client.js.map +1 -0
- package/packages/server/dist/lsp/format.d.ts +13 -0
- package/packages/server/dist/lsp/format.d.ts.map +1 -0
- package/packages/server/dist/lsp/format.js +55 -0
- package/packages/server/dist/lsp/format.js.map +1 -0
- package/packages/server/dist/lsp/index.d.ts +20 -0
- package/packages/server/dist/lsp/index.d.ts.map +1 -0
- package/packages/server/dist/lsp/index.js +32 -0
- package/packages/server/dist/lsp/index.js.map +1 -0
- package/packages/server/dist/lsp/language-registry.d.ts +29 -0
- package/packages/server/dist/lsp/language-registry.d.ts.map +1 -0
- package/packages/server/dist/lsp/language-registry.js +62 -0
- package/packages/server/dist/lsp/language-registry.js.map +1 -0
- package/packages/server/dist/lsp/manager.d.ts +77 -0
- package/packages/server/dist/lsp/manager.d.ts.map +1 -0
- package/packages/server/dist/lsp/manager.js +300 -0
- package/packages/server/dist/lsp/manager.js.map +1 -0
- package/packages/server/dist/plugins-routes.d.ts +96 -0
- package/packages/server/dist/plugins-routes.d.ts.map +1 -0
- package/packages/server/dist/plugins-routes.js +627 -0
- package/packages/server/dist/plugins-routes.js.map +1 -0
- package/packages/server/dist/setup/checks/config.d.ts +9 -0
- package/packages/server/dist/setup/checks/config.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/config.js +66 -0
- package/packages/server/dist/setup/checks/config.js.map +1 -0
- package/packages/server/dist/setup/checks/db.d.ts +6 -0
- package/packages/server/dist/setup/checks/db.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/db.js +79 -0
- package/packages/server/dist/setup/checks/db.js.map +1 -0
- package/packages/server/dist/setup/checks/known-models.d.ts +18 -0
- package/packages/server/dist/setup/checks/known-models.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/known-models.js +119 -0
- package/packages/server/dist/setup/checks/known-models.js.map +1 -0
- package/packages/server/dist/setup/checks/network.d.ts +11 -0
- package/packages/server/dist/setup/checks/network.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/network.js +176 -0
- package/packages/server/dist/setup/checks/network.js.map +1 -0
- package/packages/server/dist/setup/checks/plugins.d.ts +9 -0
- package/packages/server/dist/setup/checks/plugins.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/plugins.js +194 -0
- package/packages/server/dist/setup/checks/plugins.js.map +1 -0
- package/packages/server/dist/setup/checks/providers.d.ts +12 -0
- package/packages/server/dist/setup/checks/providers.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/providers.js +368 -0
- package/packages/server/dist/setup/checks/providers.js.map +1 -0
- package/packages/server/dist/setup/checks/runtime.d.ts +3 -0
- package/packages/server/dist/setup/checks/runtime.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/runtime.js +44 -0
- package/packages/server/dist/setup/checks/runtime.js.map +1 -0
- package/packages/server/dist/setup/checks/sandbox.d.ts +9 -0
- package/packages/server/dist/setup/checks/sandbox.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/sandbox.js +110 -0
- package/packages/server/dist/setup/checks/sandbox.js.map +1 -0
- package/packages/server/dist/setup/checks/tenants.d.ts +9 -0
- package/packages/server/dist/setup/checks/tenants.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/tenants.js +509 -0
- package/packages/server/dist/setup/checks/tenants.js.map +1 -0
- package/packages/server/dist/setup/cli-agent.d.ts +39 -0
- package/packages/server/dist/setup/cli-agent.d.ts.map +1 -0
- package/packages/server/dist/setup/cli-agent.js +1353 -0
- package/packages/server/dist/setup/cli-agent.js.map +1 -0
- package/packages/server/dist/setup/doctor.d.ts +32 -0
- package/packages/server/dist/setup/doctor.d.ts.map +1 -0
- package/packages/server/dist/setup/doctor.js +80 -0
- package/packages/server/dist/setup/doctor.js.map +1 -0
- package/packages/server/dist/setup/launchd.d.ts +107 -0
- package/packages/server/dist/setup/launchd.d.ts.map +1 -0
- package/packages/server/dist/setup/launchd.js +309 -0
- package/packages/server/dist/setup/launchd.js.map +1 -0
- package/packages/server/dist/setup/load-env.d.ts +21 -0
- package/packages/server/dist/setup/load-env.d.ts.map +1 -0
- package/packages/server/dist/setup/load-env.js +88 -0
- package/packages/server/dist/setup/load-env.js.map +1 -0
- package/packages/server/dist/setup/probe-default-model.d.ts +28 -0
- package/packages/server/dist/setup/probe-default-model.d.ts.map +1 -0
- package/packages/server/dist/setup/probe-default-model.js +133 -0
- package/packages/server/dist/setup/probe-default-model.js.map +1 -0
- package/packages/server/dist/setup/render.d.ts +28 -0
- package/packages/server/dist/setup/render.d.ts.map +1 -0
- package/packages/server/dist/setup/render.js +60 -0
- package/packages/server/dist/setup/render.js.map +1 -0
- package/packages/server/dist/setup/repo-root.d.ts +3 -0
- package/packages/server/dist/setup/repo-root.d.ts.map +1 -0
- package/packages/server/dist/setup/repo-root.js +43 -0
- package/packages/server/dist/setup/repo-root.js.map +1 -0
- package/packages/server/dist/setup/service.d.ts +60 -0
- package/packages/server/dist/setup/service.d.ts.map +1 -0
- package/packages/server/dist/setup/service.js +345 -0
- package/packages/server/dist/setup/service.js.map +1 -0
- package/packages/server/dist/setup/start-server.d.ts +23 -0
- package/packages/server/dist/setup/start-server.d.ts.map +1 -0
- package/packages/server/dist/setup/start-server.js +465 -0
- package/packages/server/dist/setup/start-server.js.map +1 -0
- package/packages/server/dist/setup/wizard.d.ts +59 -0
- package/packages/server/dist/setup/wizard.d.ts.map +1 -0
- package/packages/server/dist/setup/wizard.js +556 -0
- package/packages/server/dist/setup/wizard.js.map +1 -0
- package/packages/server/dist/tools/edit-file.d.ts +13 -0
- package/packages/server/dist/tools/edit-file.d.ts.map +1 -0
- package/packages/server/dist/tools/edit-file.js +90 -0
- package/packages/server/dist/tools/edit-file.js.map +1 -0
- package/packages/server/dist/tools/glob.d.ts +12 -0
- package/packages/server/dist/tools/glob.d.ts.map +1 -0
- package/packages/server/dist/tools/glob.js +82 -0
- package/packages/server/dist/tools/glob.js.map +1 -0
- package/packages/server/dist/tools/index.d.ts +82 -0
- package/packages/server/dist/tools/index.d.ts.map +1 -0
- package/packages/server/dist/tools/index.js +72 -0
- package/packages/server/dist/tools/index.js.map +1 -0
- package/packages/server/dist/tools/list-dir.d.ts +24 -0
- package/packages/server/dist/tools/list-dir.d.ts.map +1 -0
- package/packages/server/dist/tools/list-dir.js +99 -0
- package/packages/server/dist/tools/list-dir.js.map +1 -0
- package/packages/server/dist/tools/path-helper.d.ts +15 -0
- package/packages/server/dist/tools/path-helper.d.ts.map +1 -0
- package/packages/server/dist/tools/path-helper.js +72 -0
- package/packages/server/dist/tools/path-helper.js.map +1 -0
- package/packages/server/dist/tools/read-file.d.ts +17 -0
- package/packages/server/dist/tools/read-file.d.ts.map +1 -0
- package/packages/server/dist/tools/read-file.js +94 -0
- package/packages/server/dist/tools/read-file.js.map +1 -0
- package/packages/server/dist/tools/sandbox.d.ts +57 -0
- package/packages/server/dist/tools/sandbox.d.ts.map +1 -0
- package/packages/server/dist/tools/sandbox.js +291 -0
- package/packages/server/dist/tools/sandbox.js.map +1 -0
- package/packages/server/dist/tools/write-file.d.ts +12 -0
- package/packages/server/dist/tools/write-file.d.ts.map +1 -0
- package/packages/server/dist/tools/write-file.js +67 -0
- package/packages/server/dist/tools/write-file.js.map +1 -0
- package/packages/server/dist/worker-agents-routes.d.ts +11 -0
- package/packages/server/dist/worker-agents-routes.d.ts.map +1 -0
- package/packages/server/dist/worker-agents-routes.js +253 -0
- package/packages/server/dist/worker-agents-routes.js.map +1 -0
- package/packages/server/package.json +41 -0
- package/packages/web/dist/assets/index-DH-gJ09_.js +60 -0
- package/packages/web/dist/assets/index-xU4lYYqY.css +2 -0
- package/packages/web/dist/index.html +14 -0
- package/packages/web/package.json +36 -0
- package/plugins/README.md +64 -0
- package/plugins/files/dist/client.d.ts +5 -0
- package/plugins/files/dist/client.d.ts.map +1 -0
- package/plugins/files/dist/client.js +354 -0
- package/plugins/files/dist/client.js.map +1 -0
- package/plugins/files/dist/server.d.ts +32 -0
- package/plugins/files/dist/server.d.ts.map +1 -0
- package/plugins/files/dist/server.js +514 -0
- package/plugins/files/dist/server.js.map +1 -0
- package/plugins/files/dist/tools/edit-file.d.ts +29 -0
- package/plugins/files/dist/tools/edit-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/edit-file.js +230 -0
- package/plugins/files/dist/tools/edit-file.js.map +1 -0
- package/plugins/files/dist/tools/edit-file.prompt.md +36 -0
- package/plugins/files/dist/tools/glob.d.ts +12 -0
- package/plugins/files/dist/tools/glob.d.ts.map +1 -0
- package/plugins/files/dist/tools/glob.js +84 -0
- package/plugins/files/dist/tools/glob.js.map +1 -0
- package/plugins/files/dist/tools/index.d.ts +13 -0
- package/plugins/files/dist/tools/index.d.ts.map +1 -0
- package/plugins/files/dist/tools/index.js +158 -0
- package/plugins/files/dist/tools/index.js.map +1 -0
- package/plugins/files/dist/tools/list-dir.d.ts +24 -0
- package/plugins/files/dist/tools/list-dir.d.ts.map +1 -0
- package/plugins/files/dist/tools/list-dir.js +104 -0
- package/plugins/files/dist/tools/list-dir.js.map +1 -0
- package/plugins/files/dist/tools/load-prompt.d.ts +5 -0
- package/plugins/files/dist/tools/load-prompt.d.ts.map +1 -0
- package/plugins/files/dist/tools/load-prompt.js +39 -0
- package/plugins/files/dist/tools/load-prompt.js.map +1 -0
- package/plugins/files/dist/tools/path-helper.d.ts +32 -0
- package/plugins/files/dist/tools/path-helper.d.ts.map +1 -0
- package/plugins/files/dist/tools/path-helper.js +113 -0
- package/plugins/files/dist/tools/path-helper.js.map +1 -0
- package/plugins/files/dist/tools/read-file.d.ts +17 -0
- package/plugins/files/dist/tools/read-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/read-file.js +109 -0
- package/plugins/files/dist/tools/read-file.js.map +1 -0
- package/plugins/files/dist/tools/read-tracker.d.ts +28 -0
- package/plugins/files/dist/tools/read-tracker.d.ts.map +1 -0
- package/plugins/files/dist/tools/read-tracker.js +135 -0
- package/plugins/files/dist/tools/read-tracker.js.map +1 -0
- package/plugins/files/dist/tools/replacers.d.ts +27 -0
- package/plugins/files/dist/tools/replacers.d.ts.map +1 -0
- package/plugins/files/dist/tools/replacers.js +221 -0
- package/plugins/files/dist/tools/replacers.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-delete.d.ts +12 -0
- package/plugins/files/dist/tools/tenant-config-delete.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-delete.js +70 -0
- package/plugins/files/dist/tools/tenant-config-delete.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-edit.d.ts +25 -0
- package/plugins/files/dist/tools/tenant-config-edit.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-edit.js +142 -0
- package/plugins/files/dist/tools/tenant-config-edit.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-glob.d.ts +12 -0
- package/plugins/files/dist/tools/tenant-config-glob.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-glob.js +64 -0
- package/plugins/files/dist/tools/tenant-config-glob.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-helper.d.ts +64 -0
- package/plugins/files/dist/tools/tenant-config-helper.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-helper.js +162 -0
- package/plugins/files/dist/tools/tenant-config-helper.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-list.d.ts +20 -0
- package/plugins/files/dist/tools/tenant-config-list.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-list.js +95 -0
- package/plugins/files/dist/tools/tenant-config-list.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-read.d.ts +17 -0
- package/plugins/files/dist/tools/tenant-config-read.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-read.js +87 -0
- package/plugins/files/dist/tools/tenant-config-read.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-write.d.ts +14 -0
- package/plugins/files/dist/tools/tenant-config-write.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-write.js +78 -0
- package/plugins/files/dist/tools/tenant-config-write.js.map +1 -0
- package/plugins/files/dist/tools/text-shape.d.ts +20 -0
- package/plugins/files/dist/tools/text-shape.d.ts.map +1 -0
- package/plugins/files/dist/tools/text-shape.js +57 -0
- package/plugins/files/dist/tools/text-shape.js.map +1 -0
- package/plugins/files/dist/tools/write-file.d.ts +12 -0
- package/plugins/files/dist/tools/write-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/write-file.js +89 -0
- package/plugins/files/dist/tools/write-file.js.map +1 -0
- package/plugins/files/dist/tools/write-file.prompt.md +14 -0
- package/plugins/files/manifest.json +100 -0
- package/plugins/files/package.json +39 -0
- package/plugins/files/skills/files-workspace-layout.md +29 -0
- package/plugins/microsandbox/dist/admin/browser-routes.d.ts +41 -0
- package/plugins/microsandbox/dist/admin/browser-routes.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/browser-routes.js +208 -0
- package/plugins/microsandbox/dist/admin/browser-routes.js.map +1 -0
- package/plugins/microsandbox/dist/admin/preview-exec.d.ts +38 -0
- package/plugins/microsandbox/dist/admin/preview-exec.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/preview-exec.js +185 -0
- package/plugins/microsandbox/dist/admin/preview-exec.js.map +1 -0
- package/plugins/microsandbox/dist/admin/routes.d.ts +35 -0
- package/plugins/microsandbox/dist/admin/routes.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/routes.js +728 -0
- package/plugins/microsandbox/dist/admin/routes.js.map +1 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.d.ts +11 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.js +72 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.js.map +1 -0
- package/plugins/microsandbox/dist/admin/templates.d.ts +16 -0
- package/plugins/microsandbox/dist/admin/templates.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/templates.js +66 -0
- package/plugins/microsandbox/dist/admin/templates.js.map +1 -0
- package/plugins/microsandbox/dist/admin.d.ts +5 -0
- package/plugins/microsandbox/dist/admin.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin.js +256 -0
- package/plugins/microsandbox/dist/admin.js.map +1 -0
- package/plugins/microsandbox/dist/build/builder.d.ts +69 -0
- package/plugins/microsandbox/dist/build/builder.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/builder.js +257 -0
- package/plugins/microsandbox/dist/build/builder.js.map +1 -0
- package/plugins/microsandbox/dist/build/metadata.d.ts +27 -0
- package/plugins/microsandbox/dist/build/metadata.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/metadata.js +55 -0
- package/plugins/microsandbox/dist/build/metadata.js.map +1 -0
- package/plugins/microsandbox/dist/build/pointer.d.ts +51 -0
- package/plugins/microsandbox/dist/build/pointer.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/pointer.js +130 -0
- package/plugins/microsandbox/dist/build/pointer.js.map +1 -0
- package/plugins/microsandbox/dist/build/sandboxfile.d.ts +15 -0
- package/plugins/microsandbox/dist/build/sandboxfile.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/sandboxfile.js +176 -0
- package/plugins/microsandbox/dist/build/sandboxfile.js.map +1 -0
- package/plugins/microsandbox/dist/client.d.ts +5 -0
- package/plugins/microsandbox/dist/client.d.ts.map +1 -0
- package/plugins/microsandbox/dist/client.js +941 -0
- package/plugins/microsandbox/dist/client.js.map +1 -0
- package/plugins/microsandbox/dist/runner/browser.d.ts +50 -0
- package/plugins/microsandbox/dist/runner/browser.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/browser.js +142 -0
- package/plugins/microsandbox/dist/runner/browser.js.map +1 -0
- package/plugins/microsandbox/dist/runner/free-port.d.ts +6 -0
- package/plugins/microsandbox/dist/runner/free-port.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/free-port.js +53 -0
- package/plugins/microsandbox/dist/runner/free-port.js.map +1 -0
- package/plugins/microsandbox/dist/runner/index.d.ts +28 -0
- package/plugins/microsandbox/dist/runner/index.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/index.js +72 -0
- package/plugins/microsandbox/dist/runner/index.js.map +1 -0
- package/plugins/microsandbox/dist/runner/microsandbox.d.ts +64 -0
- package/plugins/microsandbox/dist/runner/microsandbox.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/microsandbox.js +668 -0
- package/plugins/microsandbox/dist/runner/microsandbox.js.map +1 -0
- package/plugins/microsandbox/dist/runner/nullable.d.ts +36 -0
- package/plugins/microsandbox/dist/runner/nullable.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/nullable.js +82 -0
- package/plugins/microsandbox/dist/runner/nullable.js.map +1 -0
- package/plugins/microsandbox/dist/runner/pool.d.ts +97 -0
- package/plugins/microsandbox/dist/runner/pool.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/pool.js +494 -0
- package/plugins/microsandbox/dist/runner/pool.js.map +1 -0
- package/plugins/microsandbox/dist/runner/types.d.ts +33 -0
- package/plugins/microsandbox/dist/runner/types.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/types.js +79 -0
- package/plugins/microsandbox/dist/runner/types.js.map +1 -0
- package/plugins/microsandbox/dist/server.d.ts +7 -0
- package/plugins/microsandbox/dist/server.d.ts.map +1 -0
- package/plugins/microsandbox/dist/server.js +276 -0
- package/plugins/microsandbox/dist/server.js.map +1 -0
- package/plugins/microsandbox/dist/tools/browser.d.ts +25 -0
- package/plugins/microsandbox/dist/tools/browser.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/browser.js +78 -0
- package/plugins/microsandbox/dist/tools/browser.js.map +1 -0
- package/plugins/microsandbox/dist/tools/build.d.ts +5 -0
- package/plugins/microsandbox/dist/tools/build.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/build.js +243 -0
- package/plugins/microsandbox/dist/tools/build.js.map +1 -0
- package/plugins/microsandbox/dist/tools/index.d.ts +9 -0
- package/plugins/microsandbox/dist/tools/index.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/index.js +430 -0
- package/plugins/microsandbox/dist/tools/index.js.map +1 -0
- package/plugins/microsandbox/dist/tools/mcp-client.d.ts +63 -0
- package/plugins/microsandbox/dist/tools/mcp-client.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/mcp-client.js +226 -0
- package/plugins/microsandbox/dist/tools/mcp-client.js.map +1 -0
- package/plugins/microsandbox/manifest.json +177 -0
- package/plugins/microsandbox/package.json +38 -0
- package/plugins/microsandbox/skills/microsandbox-browser-howto.md +155 -0
- package/plugins/microsandbox/skills/microsandbox-build-use.md +201 -0
- package/plugins/microsandbox/skills/microsandbox-config.md +38 -0
- package/plugins/microsandbox/skills/microsandbox-exec-howto.md +144 -0
- package/plugins/microsandbox/skills/microsandbox-libreoffice.md +159 -0
- package/plugins/microsandbox/templates/README.md +26 -0
- package/plugins/web-search/dist/server.d.ts +4 -0
- package/plugins/web-search/dist/server.d.ts.map +1 -0
- package/plugins/web-search/dist/server.js +73 -0
- package/plugins/web-search/dist/server.js.map +1 -0
- package/plugins/web-search/dist/tools/health.d.ts +31 -0
- package/plugins/web-search/dist/tools/health.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/health.js +59 -0
- package/plugins/web-search/dist/tools/health.js.map +1 -0
- package/plugins/web-search/dist/tools/index.d.ts +3 -0
- package/plugins/web-search/dist/tools/index.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/index.js +2 -0
- package/plugins/web-search/dist/tools/index.js.map +1 -0
- package/plugins/web-search/dist/tools/providers.d.ts +43 -0
- package/plugins/web-search/dist/tools/providers.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/providers.js +140 -0
- package/plugins/web-search/dist/tools/providers.js.map +1 -0
- package/plugins/web-search/dist/tools/web-search.d.ts +15 -0
- package/plugins/web-search/dist/tools/web-search.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/web-search.js +244 -0
- package/plugins/web-search/dist/tools/web-search.js.map +1 -0
- package/plugins/web-search/manifest.json +65 -0
- package/plugins/web-search/node_modules/@esbuild/darwin-arm64/README.md +3 -0
- package/plugins/web-search/node_modules/@esbuild/darwin-arm64/package.json +20 -0
- package/plugins/web-search/node_modules/@vitest/expect/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/expect/README.md +21 -0
- package/plugins/web-search/node_modules/@vitest/expect/dist/index.d.ts +808 -0
- package/plugins/web-search/node_modules/@vitest/expect/dist/index.js +1799 -0
- package/plugins/web-search/node_modules/@vitest/expect/package.json +46 -0
- package/plugins/web-search/node_modules/@vitest/mocker/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/mocker/README.md +5 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/auto-register.d.ts +2 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/auto-register.js +9 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/browser.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/browser.js +91 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-interceptor-native.js +15 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-mocker.js +1602 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-pathe.M-eThtNZ.js +174 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-registry.js +182 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-utils.js +16 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/index.d.ts +21 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/index.js +174 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/mocker.d-Ce9_ySj5.d.ts +83 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/node.d.ts +821 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/node.js +1306 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/redirect.d.ts +3 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/redirect.js +75 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/register.d.ts +9 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/register.js +41 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/registry.d-D765pazg.d.ts +87 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/types.d-D_aRZRdy.d.ts +8 -0
- package/plugins/web-search/node_modules/@vitest/mocker/package.json +82 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/dist/index.d.ts +119 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/dist/index.js +1387 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/package.json +44 -0
- package/plugins/web-search/node_modules/@vitest/runner/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/runner/README.md +5 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/chunk-hooks.js +2254 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/index.d.ts +261 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/index.js +6 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/tasks.d-CkscK4of.d.ts +558 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/types.d.ts +163 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/types.js +1 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/utils.d.ts +47 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/utils.js +6 -0
- package/plugins/web-search/node_modules/@vitest/runner/package.json +49 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/README.md +84 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.d-DHdQ1Csl.d.ts +22 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.d.ts +16 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.js +40 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/index.d.ts +137 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/index.js +2305 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/manager.d.ts +18 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/manager.js +73 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/rawSnapshot.d-lFsMJFUd.d.ts +61 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/package.json +54 -0
- package/plugins/web-search/node_modules/@vitest/spy/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/spy/README.md +3 -0
- package/plugins/web-search/node_modules/@vitest/spy/dist/index.d.ts +356 -0
- package/plugins/web-search/node_modules/@vitest/spy/dist/index.js +191 -0
- package/plugins/web-search/node_modules/@vitest/spy/package.json +38 -0
- package/plugins/web-search/node_modules/@vitest/utils/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js +158 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/diff.d.ts +104 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/diff.js +2185 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/error.d.ts +9 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/error.js +162 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/helpers.d.ts +56 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/helpers.js +251 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/index.d.ts +57 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/index.js +633 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/source-map.d.ts +139 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/source-map.js +996 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.js +1 -0
- package/plugins/web-search/node_modules/@vitest/utils/package.json +77 -0
- package/plugins/web-search/node_modules/chai/LICENSE +21 -0
- package/plugins/web-search/node_modules/chai/README.md +162 -0
- package/plugins/web-search/node_modules/chai/package.json +74 -0
- package/plugins/web-search/node_modules/esbuild/README.md +3 -0
- package/plugins/web-search/node_modules/esbuild/package.json +49 -0
- package/plugins/web-search/node_modules/std-env/README.md +118 -0
- package/plugins/web-search/node_modules/std-env/dist/index.cjs +1 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.cts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.mts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.ts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.mjs +1 -0
- package/plugins/web-search/node_modules/std-env/package.json +46 -0
- package/plugins/web-search/node_modules/tinyexec/LICENSE +21 -0
- package/plugins/web-search/node_modules/tinyexec/README.md +256 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.cjs +575 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.d.cts +70 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.d.ts +70 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.js +578 -0
- package/plugins/web-search/node_modules/tinyexec/package.json +66 -0
- package/plugins/web-search/node_modules/tinyrainbow/README.md +28 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/browser.d.ts +8 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/browser.js +20 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js +90 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/index-8b61d5bc.d.ts +59 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/node.d.ts +8 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/node.js +22 -0
- package/plugins/web-search/node_modules/tinyrainbow/package.json +37 -0
- package/plugins/web-search/node_modules/typescript/README.md +50 -0
- package/plugins/web-search/node_modules/typescript/package.json +120 -0
- package/plugins/web-search/node_modules/vite/README.md +20 -0
- package/plugins/web-search/node_modules/vite/dist/client/client.mjs +1106 -0
- package/plugins/web-search/node_modules/vite/dist/client/env.mjs +19 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/build.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/build2.js +5538 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/chunk.js +48 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/config.js +36065 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/config2.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/dist.js +6758 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/lib.js +377 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/logger.js +329 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/moduleRunnerTransport.d.ts +96 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/optimizer.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/postcss-import.js +479 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/preview.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/server.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/cli.js +698 -0
- package/plugins/web-search/node_modules/vite/dist/node/index.d.ts +3717 -0
- package/plugins/web-search/node_modules/vite/dist/node/index.js +30 -0
- package/plugins/web-search/node_modules/vite/dist/node/module-runner.d.ts +311 -0
- package/plugins/web-search/node_modules/vite/dist/node/module-runner.js +1160 -0
- package/plugins/web-search/node_modules/vite/package.json +199 -0
- package/plugins/web-search/node_modules/vite/types/package.json +4 -0
- package/plugins/web-search/node_modules/vitest/README.md +7 -0
- package/plugins/web-search/node_modules/vitest/dist/browser.d.ts +34 -0
- package/plugins/web-search/node_modules/vitest/dist/browser.js +8 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js +7 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/base.DfmxU-tU.js +38 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/benchmark.CYdenmiT.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/benchmark.d.BwvBVTda.d.ts +24 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/cac.0BJqEUeA.js +1469 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/cli-api.DWGBtMmz.js +10660 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/config.d.BKdhh7Zx.d.ts +224 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/console.CtFJOzRO.js +153 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/constants.DnKduX2e.js +44 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.DVF1vEu8.js +25 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.DfSpMS-b.js +4350 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.d.S9RMNXIe.d.ts +35 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/creator.GK6I-cL4.js +640 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/date.Bq6ZW5rf.js +73 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/defaults.B7q_naMc.js +115 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/env.D4Lgay0q.js +8 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/environment.d.cL3nLXbE.d.ts +119 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js +708 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/git.BVQ8w_Sw.js +72 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/global.d.MAmajcmJ.d.ts +136 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/globals.DEHgCU4V.js +26 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.B521nVV-.js +157 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.BCWujgDG.js +231 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CdQS2e2Q.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CmSc2RE5.js +587 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CwejwG0H.js +105 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.D3XRDfWc.js +213 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.VByaPkjc.js +2183 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.X0nbfr6-.js +6584 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/inspector.C914Efll.js +57 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/mocker.d.BE_2ls6u.d.ts +17 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/node.fjCdwEIl.js +15 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/reporters.d.BuRON0I0.d.ts +3168 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/rpc.-pEldfrD.js +83 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/runBaseTests.9Ij9_de-.js +129 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/setup-common.Dd054P77.js +60 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/suite.d.FvehnV49.d.ts +10 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/typechecker.DRKU1-1g.js +874 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/utils.CAioKnHs.js +61 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/utils.XdZDrNZV.js +65 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js +4015 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vite.d.BnOPPc46.d.ts +25 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vm.BThCzidc.js +756 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/worker.d.CUgIPz9V.d.ts +176 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/worker.d.uzWsCv9X.d.ts +8 -0
- package/plugins/web-search/node_modules/vitest/dist/cli.js +27 -0
- package/plugins/web-search/node_modules/vitest/dist/config.cjs +148 -0
- package/plugins/web-search/node_modules/vitest/dist/config.d.ts +100 -0
- package/plugins/web-search/node_modules/vitest/dist/config.js +21 -0
- package/plugins/web-search/node_modules/vitest/dist/coverage.d.ts +108 -0
- package/plugins/web-search/node_modules/vitest/dist/coverage.js +34 -0
- package/plugins/web-search/node_modules/vitest/dist/environments.d.ts +26 -0
- package/plugins/web-search/node_modules/vitest/dist/environments.js +2 -0
- package/plugins/web-search/node_modules/vitest/dist/execute.d.ts +150 -0
- package/plugins/web-search/node_modules/vitest/dist/execute.js +13 -0
- package/plugins/web-search/node_modules/vitest/dist/index.d.ts +651 -0
- package/plugins/web-search/node_modules/vitest/dist/index.js +18 -0
- package/plugins/web-search/node_modules/vitest/dist/mocker.d.ts +1 -0
- package/plugins/web-search/node_modules/vitest/dist/mocker.js +1 -0
- package/plugins/web-search/node_modules/vitest/dist/node.d.ts +158 -0
- package/plugins/web-search/node_modules/vitest/dist/node.js +105 -0
- package/plugins/web-search/node_modules/vitest/dist/path.js +7 -0
- package/plugins/web-search/node_modules/vitest/dist/reporters.d.ts +25 -0
- package/plugins/web-search/node_modules/vitest/dist/reporters.js +23 -0
- package/plugins/web-search/node_modules/vitest/dist/runners.d.ts +46 -0
- package/plugins/web-search/node_modules/vitest/dist/runners.js +235 -0
- package/plugins/web-search/node_modules/vitest/dist/snapshot.d.ts +9 -0
- package/plugins/web-search/node_modules/vitest/dist/snapshot.js +4 -0
- package/plugins/web-search/node_modules/vitest/dist/spy.js +1 -0
- package/plugins/web-search/node_modules/vitest/dist/suite.d.ts +5 -0
- package/plugins/web-search/node_modules/vitest/dist/suite.js +5 -0
- package/plugins/web-search/node_modules/vitest/dist/worker.js +124 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/forks.js +43 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/runVmTests.js +90 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/threads.js +31 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/vmForks.js +47 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/vmThreads.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/workers.d.ts +40 -0
- package/plugins/web-search/node_modules/vitest/dist/workers.js +30 -0
- package/plugins/web-search/node_modules/vitest/package.json +207 -0
- package/plugins/web-search/package.json +30 -0
- package/plugins/web-search/skills/web-search-howto.md +69 -0
- package/plugins/workboard/agent-seeds/echo-demo/agent.json +7 -0
- package/plugins/workboard/agent-seeds/llm-default/SOUL.md +53 -0
- package/plugins/workboard/agent-seeds/llm-default/agent.json +7 -0
- package/plugins/workboard/dist/client.d.ts +5 -0
- package/plugins/workboard/dist/client.d.ts.map +1 -0
- package/plugins/workboard/dist/client.js +895 -0
- package/plugins/workboard/dist/client.js.map +1 -0
- package/plugins/workboard/dist/db/agents.d.ts +100 -0
- package/plugins/workboard/dist/db/agents.d.ts.map +1 -0
- package/plugins/workboard/dist/db/agents.js +280 -0
- package/plugins/workboard/dist/db/agents.js.map +1 -0
- package/plugins/workboard/dist/db/schema.d.ts +3 -0
- package/plugins/workboard/dist/db/schema.d.ts.map +1 -0
- package/plugins/workboard/dist/db/schema.js +31 -0
- package/plugins/workboard/dist/db/schema.js.map +1 -0
- package/plugins/workboard/dist/db/session-history.d.ts +28 -0
- package/plugins/workboard/dist/db/session-history.d.ts.map +1 -0
- package/plugins/workboard/dist/db/session-history.js +224 -0
- package/plugins/workboard/dist/db/session-history.js.map +1 -0
- package/plugins/workboard/dist/db/tasks.d.ts +260 -0
- package/plugins/workboard/dist/db/tasks.d.ts.map +1 -0
- package/plugins/workboard/dist/db/tasks.js +451 -0
- package/plugins/workboard/dist/db/tasks.js.map +1 -0
- package/plugins/workboard/dist/db/worker-agents.d.ts +16 -0
- package/plugins/workboard/dist/db/worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/db/worker-agents.js +62 -0
- package/plugins/workboard/dist/db/worker-agents.js.map +1 -0
- package/plugins/workboard/dist/effective-skills.d.ts +13 -0
- package/plugins/workboard/dist/effective-skills.d.ts.map +1 -0
- package/plugins/workboard/dist/effective-skills.js +126 -0
- package/plugins/workboard/dist/effective-skills.js.map +1 -0
- package/plugins/workboard/dist/fs-worker-agents.d.ts +35 -0
- package/plugins/workboard/dist/fs-worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/fs-worker-agents.js +199 -0
- package/plugins/workboard/dist/fs-worker-agents.js.map +1 -0
- package/plugins/workboard/dist/migrate-worker-agents.d.ts +11 -0
- package/plugins/workboard/dist/migrate-worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/migrate-worker-agents.js +89 -0
- package/plugins/workboard/dist/migrate-worker-agents.js.map +1 -0
- package/plugins/workboard/dist/routes/handlers.d.ts +106 -0
- package/plugins/workboard/dist/routes/handlers.d.ts.map +1 -0
- package/plugins/workboard/dist/routes/handlers.js +668 -0
- package/plugins/workboard/dist/routes/handlers.js.map +1 -0
- package/plugins/workboard/dist/server.d.ts +6 -0
- package/plugins/workboard/dist/server.d.ts.map +1 -0
- package/plugins/workboard/dist/server.js +368 -0
- package/plugins/workboard/dist/server.js.map +1 -0
- package/plugins/workboard/dist/tools/index.d.ts +70 -0
- package/plugins/workboard/dist/tools/index.d.ts.map +1 -0
- package/plugins/workboard/dist/tools/index.js +963 -0
- package/plugins/workboard/dist/tools/index.js.map +1 -0
- package/plugins/workboard/dist/types.d.ts +27 -0
- package/plugins/workboard/dist/types.d.ts.map +1 -0
- package/plugins/workboard/dist/types.js +16 -0
- package/plugins/workboard/dist/types.js.map +1 -0
- package/plugins/workboard/dist/worker/pool.d.ts +220 -0
- package/plugins/workboard/dist/worker/pool.d.ts.map +1 -0
- package/plugins/workboard/dist/worker/pool.js +866 -0
- package/plugins/workboard/dist/worker/pool.js.map +1 -0
- package/plugins/workboard/dist/worker/tool-policy.d.ts +27 -0
- package/plugins/workboard/dist/worker/tool-policy.d.ts.map +1 -0
- package/plugins/workboard/dist/worker/tool-policy.js +76 -0
- package/plugins/workboard/dist/worker/tool-policy.js.map +1 -0
- package/plugins/workboard/dist/worker-agents-page.d.ts +4 -0
- package/plugins/workboard/dist/worker-agents-page.d.ts.map +1 -0
- package/plugins/workboard/dist/worker-agents-page.js +193 -0
- package/plugins/workboard/dist/worker-agents-page.js.map +1 -0
- package/plugins/workboard/manifest.json +180 -0
- package/plugins/workboard/package.json +37 -0
- package/plugins/workboard/skills/large-input-large-output.md +185 -0
- package/plugins/workboard/skills/workboard-howto.md +166 -0
- package/plugins/workboard/skills/worker-creator.md +267 -0
- package/plugins/workboard/skills/worker-fleet.md +431 -0
|
@@ -0,0 +1,1353 @@
|
|
|
1
|
+
// CLI agent — runs an interactive chat loop in the terminal after
|
|
2
|
+
// `tianshu setup --wizard` finishes provisioning the LLM. Lets the
|
|
3
|
+
// user finish the rest of setup (enabling plugins, creating
|
|
4
|
+
// tenants, configuring web-search keys, etc.) by talking to the
|
|
5
|
+
// agent rather than learning a CLI surface.
|
|
6
|
+
//
|
|
7
|
+
// Why CLI rather than browser:
|
|
8
|
+
// the user is already in a terminal having just run the wizard;
|
|
9
|
+
// jumping to a browser breaks the flow. The CLI agent shares a
|
|
10
|
+
// minimal toolset (tenant / config / doctor) but does NOT spin up
|
|
11
|
+
// the full plugin runtime — those tools cover everything the
|
|
12
|
+
// post-setup phase needs.
|
|
13
|
+
//
|
|
14
|
+
// Out of scope:
|
|
15
|
+
// - full chat history (this is a one-shot setup conversation)
|
|
16
|
+
// - sandbox exec (microsandbox lives in plugin-land; if the user
|
|
17
|
+
// needs the microsandbox npm dep installed, the agent tells
|
|
18
|
+
// them which `npm install` step likely failed)
|
|
19
|
+
// - workboard (worker spawn is overkill for setup)
|
|
20
|
+
//
|
|
21
|
+
// Tools shipped (12): tenant_list, tenant_create, user_create,
|
|
22
|
+
// plugin_enable, plugin_disable, config_read, config_write,
|
|
23
|
+
// run_doctor, read_service_logs, read_env_file,
|
|
24
|
+
// build_sandbox, use_sandbox_build. Plus the implicit "done"
|
|
25
|
+
// sentinel.
|
|
26
|
+
import * as p from "@clack/prompts";
|
|
27
|
+
import fs from "node:fs";
|
|
28
|
+
import os from "node:os";
|
|
29
|
+
import path from "node:path";
|
|
30
|
+
import { complete } from "@earendil-works/pi-ai";
|
|
31
|
+
import { GlobalOps } from "../core/global-ops.js";
|
|
32
|
+
import { buildModel, getDefaultModel, resolveApiKey, } from "../core/llm.js";
|
|
33
|
+
import { loadGlobalConfig, writeGlobalConfig, writeTenantConfig, TenantConfigForbiddenFieldError, } from "../core/config.js";
|
|
34
|
+
import { getTenantsRoot, getTianshuHome, getGlobalConfigPath, } from "../core/paths.js";
|
|
35
|
+
import { applyPluginSecretPatch, loadPluginSecrets, } from "../core/plugins/index.js";
|
|
36
|
+
import { collectDoctorReport } from "./doctor.js";
|
|
37
|
+
import * as launchd from "./launchd.js";
|
|
38
|
+
import { findRepoRoot } from "./repo-root.js";
|
|
39
|
+
const SETUP_SYSTEM_PROMPT = `You are the tianshu setup assistant.
|
|
40
|
+
|
|
41
|
+
The user just finished configuring an LLM provider. Your job is
|
|
42
|
+
to walk them through the remaining setup decisions — not to
|
|
43
|
+
silently auto-configure things behind their back. Every state-
|
|
44
|
+
changing tool call (tenant_create, user_create, plugin_enable,
|
|
45
|
+
plugin_disable, config_write) is intercepted by the CLI and the
|
|
46
|
+
user is asked to confirm before it runs. Plan accordingly: don't
|
|
47
|
+
batch 10 actions in one turn; propose a small, named change,
|
|
48
|
+
call the tool, then continue based on what the user accepts.
|
|
49
|
+
|
|
50
|
+
Workflow on the FIRST turn:
|
|
51
|
+
|
|
52
|
+
1. Call run_doctor to see what's set up. If doctor reports the server isn't running or isn't responding, call read_service_logs to see *why* before suggesting fixes.
|
|
53
|
+
2. Look at the report and write ONE message to the user:
|
|
54
|
+
- In plain language, summarise what's already working.
|
|
55
|
+
- List what looks like it should be set up next (e.g.
|
|
56
|
+
'workboard plugin is disabled', 'microsandbox runtime
|
|
57
|
+
binary not found', 'no Tavily API key for web-search').
|
|
58
|
+
- For each item, propose the action you'd like to take and
|
|
59
|
+
which tool call you'd run. Don't run them yet.
|
|
60
|
+
- End by asking the user which they want to do first, or
|
|
61
|
+
whether to skip ahead.
|
|
62
|
+
|
|
63
|
+
From turn 2 onward:
|
|
64
|
+
- Run one tool at a time, narrate why before each one (the CLI
|
|
65
|
+
will pop a confirmation — the user already sees the
|
|
66
|
+
one-liner you described, but your message gives the reason).
|
|
67
|
+
- After a tool runs, narrate what happened (one short line)
|
|
68
|
+
and propose the next step.
|
|
69
|
+
- If the user declines a confirmation, drop that idea and
|
|
70
|
+
move on — don't retry the same tool with the same args.
|
|
71
|
+
|
|
72
|
+
Style: brief, direct, no fluff. Don't ask the user to copy-paste
|
|
73
|
+
shell commands; either run a tool, or tell them clearly what
|
|
74
|
+
they need to do outside this CLI (e.g. 'run \`npx microsandbox
|
|
75
|
+
install\` in another terminal then re-run setup').
|
|
76
|
+
|
|
77
|
+
Domain knowledge you must apply when relevant:
|
|
78
|
+
|
|
79
|
+
GLOBAL VS TENANT CONFIG (config_read / config_write):
|
|
80
|
+
- Two scopes live side by side:
|
|
81
|
+
* GLOBAL = ~/.tianshu/config.json. System-wide. Controls server port,
|
|
82
|
+
logging, the *baseline* provider catalog (models.providers), the
|
|
83
|
+
baseline default model, autoCreateDefault. New tenants inherit
|
|
84
|
+
everything in here unless they override.
|
|
85
|
+
* TENANT = ~/.tianshu/tenants/<id>/config.json. Per-tenant. Can
|
|
86
|
+
override the overridable subset: plugins (enable/disable per
|
|
87
|
+
tenant), models (a tenant-specific catalog that wholesale-
|
|
88
|
+
replaces global's), defaultModel, branding, apiKeys, mcp.
|
|
89
|
+
Tenants CAN'T set server.port / logging / autoCreateDefault —
|
|
90
|
+
those are GlobalOnlyConfig; writeTenantConfig rejects them.
|
|
91
|
+
- Which one to write to when a user asks for something:
|
|
92
|
+
* "add a provider" / "set the default model" / "server settings"
|
|
93
|
+
→ GLOBAL, unless the user explicitly says "for tenant X".
|
|
94
|
+
GLOBAL is the right default for first-time setup and most
|
|
95
|
+
config changes; new tenants will inherit from there.
|
|
96
|
+
* "enable / disable a plugin for me" or "for my tenant"
|
|
97
|
+
→ TENANT. Plugin enablement is per-tenant.
|
|
98
|
+
* "my tenant should use a different model than everyone else"
|
|
99
|
+
→ TENANT. Set defaultModel on the tenant; also set
|
|
100
|
+
models.providers on the tenant if the model isn't in global.
|
|
101
|
+
* Bad \`api\` value flagged by run_doctor: the doctor output
|
|
102
|
+
tells you which scope ('LLM providers' section = global,
|
|
103
|
+
'Tenants & plugins' section = tenant) — fix it at the same
|
|
104
|
+
scope it was reported.
|
|
105
|
+
- Both scopes use shallow top-level merge: \`config_write\` reads the
|
|
106
|
+
existing file, spreads it, overlays your patch, writes back. So
|
|
107
|
+
a patch like \`{"defaultModel": "x"}\` only touches that one key.
|
|
108
|
+
- Trying to set a global-only field on a tenant returns
|
|
109
|
+
\`error: tenant_forbidden_field\` with a hint. Switch to
|
|
110
|
+
which='global' and retry.
|
|
111
|
+
|
|
112
|
+
WEB SEARCH (web-search plugin):
|
|
113
|
+
- API keys go to SECRETS, not regular config. Use \`secret_write\`
|
|
114
|
+
with pluginId='web-search' and key='tavilyApiKey' (Tavily) or
|
|
115
|
+
'braveApiKey' (Brave). DO NOT use \`config_write\` for these.
|
|
116
|
+
config.json is committable, secrets/ is not.
|
|
117
|
+
- Check \`secret_list\` first to see what's already configured
|
|
118
|
+
before asking the user for a key.
|
|
119
|
+
|
|
120
|
+
PROVIDERS / MODELS (config.json's \`models.providers\` map):
|
|
121
|
+
- The \`api\` field MUST be a value pi-ai recognises. The only
|
|
122
|
+
ones in current use are:
|
|
123
|
+
* \`openai-completions\` — use for OpenAI itself AND for any
|
|
124
|
+
OpenAI-compatible vendor: dashscope, deepseek, moonshot,
|
|
125
|
+
siliconflow, together, groq, llama-server, ollama, anything
|
|
126
|
+
that exposes \`/v1/chat/completions\`. The name is
|
|
127
|
+
confusingly historical — it points at \`/v1/chat/completions\`
|
|
128
|
+
not the legacy \`/v1/completions\`. Use this whenever the
|
|
129
|
+
upstream advertises "OpenAI-compatible".
|
|
130
|
+
* \`anthropic-messages\` — Anthropic native API (\`/v1/messages\`).
|
|
131
|
+
* \`google-generative-ai\` — Google Gemini native API.
|
|
132
|
+
* \`openai-responses\` — OpenAI's newer Responses API. Only
|
|
133
|
+
use when the user explicitly wants it; the default for
|
|
134
|
+
OpenAI itself is still \`openai-completions\`.
|
|
135
|
+
Common typos to NEVER write: "openai-chat" (does not exist),
|
|
136
|
+
"chat-completions" (does not exist), "openai" (no api type).
|
|
137
|
+
- A typical OpenAI-compatible provider entry looks like:
|
|
138
|
+
"qwen": {
|
|
139
|
+
"api": "openai-completions",
|
|
140
|
+
"baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
141
|
+
"apiKey": "sk-...",
|
|
142
|
+
"group": "Cloud",
|
|
143
|
+
"models": [
|
|
144
|
+
{ "id": "qwen3-max-preview", "name": "Qwen3 Max Preview",
|
|
145
|
+
"contextWindow": 256000, "maxTokens": 8192 }
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
baseUrl is the *prefix* before /chat/completions — NOT the full
|
|
149
|
+
endpoint URL. pi-ai appends the path itself.
|
|
150
|
+
- defaultModel must point at a model that exists in the catalog:
|
|
151
|
+
"defaultModel": "qwen/qwen3-max-preview" matches
|
|
152
|
+
models.providers.qwen.models[].id = "qwen3-max-preview".
|
|
153
|
+
If the tenant overrides \`models\` but doesn't set defaultModel,
|
|
154
|
+
the server auto-picks the first provider's first model, but
|
|
155
|
+
setting defaultModel explicitly is clearer and survives catalog
|
|
156
|
+
edits.
|
|
157
|
+
- apiKey can be a literal string (default since 2026-06; lands
|
|
158
|
+
in config.json which is chmod 600) or a \`\${ENV_VAR}\`
|
|
159
|
+
placeholder if the user opted into --use-env mode.
|
|
160
|
+
- Each model entry SHOULD carry \`contextWindow\` and \`maxTokens\`
|
|
161
|
+
(both in tokens). Meaning:
|
|
162
|
+
* \`contextWindow\` = total token budget for the request
|
|
163
|
+
(system prompt + history + tools + the new response). The
|
|
164
|
+
server uses this for context-overflow detection.
|
|
165
|
+
* \`maxTokens\` = the per-response output cap sent to the
|
|
166
|
+
provider as max_tokens / generation_config.max_output_tokens.
|
|
167
|
+
Truncates generation at this many tokens.
|
|
168
|
+
Rules:
|
|
169
|
+
* maxTokens MUST be ≤ contextWindow (doctor flags inversion
|
|
170
|
+
as a blocker).
|
|
171
|
+
* If either field is missing the server falls back to 128_000 /
|
|
172
|
+
4_096 (see core/llm.ts buildModelInfoFromEntry). Modern
|
|
173
|
+
models support much more on both axes — leaving them blank
|
|
174
|
+
silently caps real capability.
|
|
175
|
+
* When the user asks to "set them to the max" or when doctor
|
|
176
|
+
flags either field as missing / suspiciously low / below the
|
|
177
|
+
known ceiling: FIRST look at \`docs/known-models.md\` in the
|
|
178
|
+
tianshu repo. That file is a curated reference with source
|
|
179
|
+
URLs and lastVerified dates; if it has the model id, use
|
|
180
|
+
those values. If the model id isn't in the table, fall back
|
|
181
|
+
to fetching the provider's docs (web_fetch / web_search
|
|
182
|
+
when available) and PR the new row into known-models.md
|
|
183
|
+
along with the catalog update so the next setup gets the
|
|
184
|
+
benefit.
|
|
185
|
+
* Do NOT guess from memory — these limits drift release-over-
|
|
186
|
+
release (we've seen qwen3-max-preview ship at maxTokens=8192
|
|
187
|
+
in catalogs while the provider already supported 32k).
|
|
188
|
+
* If you can't reach the docs in this session, ask the user
|
|
189
|
+
to paste them, or fill in conservative round numbers and
|
|
190
|
+
note in the response that these are placeholders to verify
|
|
191
|
+
against the provider's docs.
|
|
192
|
+
* Doctor's "below known ceiling" warning is a *suggestion*,
|
|
193
|
+
not a blocker. If the user picked a lower cap deliberately
|
|
194
|
+
(cost control, slow models, etc.), respect their choice —
|
|
195
|
+
don't auto-bump on their behalf, just confirm they meant it.
|
|
196
|
+
|
|
197
|
+
WORKBOARD WORKERS (workboard plugin):
|
|
198
|
+
- When the user enables workboard, the LLM worker pool starts up
|
|
199
|
+
with one worker per enabled \`agent.json\` in the tenant's
|
|
200
|
+
agent-seeds bundle. There is no "worker count" setting at the
|
|
201
|
+
config level — if the user wants more workers, they add more
|
|
202
|
+
agent.json files. The cli-agent doesn't manage agent files
|
|
203
|
+
directly; that's the user / chat agent's job.
|
|
204
|
+
- Each LLM worker picks its model in this order:
|
|
205
|
+
1. \`modelId\` field in the worker's own agent.json (per-worker
|
|
206
|
+
override; rare)
|
|
207
|
+
2. resolved tenant defaultModel (\`tenant.defaultModel\` else
|
|
208
|
+
auto-pick from tenant.models else global.defaultModel)
|
|
209
|
+
- If \`run_doctor\` says "workboard: no defaultModel resolvable",
|
|
210
|
+
set tenant.defaultModel (via \`config_write\` which='tenant')
|
|
211
|
+
or global.defaultModel (which='global'). Don't try to find a
|
|
212
|
+
worker-specific setting; there isn't one.
|
|
213
|
+
- The schema still carries a \`worker: { count, pollMs, model }\`
|
|
214
|
+
field for backwards compat. It has NO runtime effect; doctor
|
|
215
|
+
flags it as deprecated. Do not write to it. If a user asks to
|
|
216
|
+
"configure worker count / polling / model", explain that those
|
|
217
|
+
are not real settings in this build, and steer them toward
|
|
218
|
+
what actually matters: tenant.defaultModel for which model the
|
|
219
|
+
workers use, and the agent-seeds bundle for how many workers
|
|
220
|
+
there are.
|
|
221
|
+
|
|
222
|
+
MICROSANDBOX (sandbox-based plugins: microsandbox, browser):
|
|
223
|
+
- microsandbox uses TWO sandbox role pointers: 'task' (per-task
|
|
224
|
+
ephemeral sandboxes for the workboard's exec/coding work) and
|
|
225
|
+
'browser' (the long-lived sandbox hosting the headless Chromium
|
|
226
|
+
+ playwright-mcp sidecar). They share an underlying snapshot —
|
|
227
|
+
one snapshot can serve both roles.
|
|
228
|
+
- The two relevant tools — build_sandbox and use_sandbox_build —
|
|
229
|
+
ARE available here in the setup wizard. Use them when the user
|
|
230
|
+
asks to set up / rebuild / refresh sandboxes. Don't tell them
|
|
231
|
+
they have to go to the chat shell.
|
|
232
|
+
- Standard setup flow when a user wants sandboxes ready. This
|
|
233
|
+
is a TWO-snapshot layered build, NOT one big monolith. Why:
|
|
234
|
+
the task pool runs lots of short-lived sandboxes and shouldn't
|
|
235
|
+
carry Chromium's ~2.5 GB; the browser sandbox is long-lived
|
|
236
|
+
and DOES need Chromium. Layering also reuses apt cache between
|
|
237
|
+
the two builds, saving the second pull.
|
|
238
|
+
1. build_sandbox(template='task-runner') → returns
|
|
239
|
+
{buildId: B1, snapshotName: S1}. WARN THE USER FIRST: this
|
|
240
|
+
takes 5-7 min; the wizard's UI hangs on a single spinner.
|
|
241
|
+
2. use_sandbox_build(buildId=B1, role='task') → publishes
|
|
242
|
+
S1 as the task-pool snapshot.
|
|
243
|
+
3. build_sandbox(template='task-runner-with-browser',
|
|
244
|
+
fromSnapshot=S1) → returns {buildId: B2, snapshotName: S2}.
|
|
245
|
+
Another 3-5 min spinner. Skipping fromSnapshot here is a
|
|
246
|
+
hard error; the build_sandbox tool guards against it but
|
|
247
|
+
you should know.
|
|
248
|
+
4. use_sandbox_build(buildId=B2, role='browser') → publishes
|
|
249
|
+
S2 as the long-lived browser sandbox.
|
|
250
|
+
After step 4 the user can immediately use the chat / workboard.
|
|
251
|
+
If the user explicitly wants a no-browser setup, stop after
|
|
252
|
+
step 2 and tell them they can build the browser layer later.
|
|
253
|
+
- If \`run_doctor\` reports "microsandbox SDK not available" or
|
|
254
|
+
"Sandbox class missing", the platform-specific NAPI binding
|
|
255
|
+
didn't install. You can NOT build sandboxes yet. Tell the user:
|
|
256
|
+
'run \`npm install\` from the tianshu checkout root and watch
|
|
257
|
+
for any error in the output — the binding ships as an optional
|
|
258
|
+
dependency (\`@superradcompany/microsandbox-<triple>\`), and
|
|
259
|
+
optional dep failures are silent by default.' Do NOT recommend
|
|
260
|
+
\`npx microsandbox install\` — in current msb versions that's
|
|
261
|
+
\`msb install <image>\` (a different command, different purpose)
|
|
262
|
+
and will fail with a missing-argument error. Don't try to call
|
|
263
|
+
build_sandbox before the SDK is present; the server will return
|
|
264
|
+
runner_not_ready (503).
|
|
265
|
+
- Template choice cheat-sheet:
|
|
266
|
+
* task-runner → first build in the standard layered flow.
|
|
267
|
+
Also the only build needed if the user wants no browser.
|
|
268
|
+
* task-runner-with-browser → second build, layered on top of
|
|
269
|
+
the task-runner snapshot via fromSnapshot=<S1's snapshotName>.
|
|
270
|
+
Without fromSnapshot it errors out (build_sandbox catches
|
|
271
|
+
that and returns missing_from_snapshot).
|
|
272
|
+
* browser → the monolithic alternative (full stack, ~3.2 GB,
|
|
273
|
+
no layering). Use only if the user specifically wants a
|
|
274
|
+
single-snapshot setup; the layered flow is preferred.
|
|
275
|
+
- If the wizard installed a launchd agent but the server isn't
|
|
276
|
+
responding (run_doctor reports "Server port free" or "port in
|
|
277
|
+
use, no HTTP response", or the user says "server didn't come
|
|
278
|
+
up"), call \`read_service_logs\` *first*. The actual error
|
|
279
|
+
message from npm/node will be in there. Don't guess; don't
|
|
280
|
+
ask the user to run \`tail\`. Common patterns to look for:
|
|
281
|
+
* "command not found: npm" → launchd's PATH doesn't have npm.
|
|
282
|
+
Check whether \`which npm\` from the user's shell points
|
|
283
|
+
somewhere unusual (volta, fnm, asdf). The fix is to bump
|
|
284
|
+
PATH in the plist's EnvironmentVariables and reinstall via
|
|
285
|
+
\`tianshu setup --wizard\`.
|
|
286
|
+
* "EADDRINUSE" → port collision. Run \`run_doctor\` to confirm
|
|
287
|
+
and ask the user to pick a different PORT/WEB_PORT in .env.
|
|
288
|
+
* "Cannot find module" / "ENOENT package.json" → wizard
|
|
289
|
+
captured the wrong WorkingDirectory. Check
|
|
290
|
+
\`~/Library/LaunchAgents/ai.tianshu.dev*.plist\`.
|
|
291
|
+
* "API key not set" / "references env var but it's empty"
|
|
292
|
+
→ first call \`config_read\` and check the providers'
|
|
293
|
+
apiKey field. As of 2026-06 the wizard's default is to
|
|
294
|
+
write the literal key into config.json (chmod 600), NOT
|
|
295
|
+
into .env. So if config.json shows a placeholder like
|
|
296
|
+
\`"\${ANTHROPIC_API_KEY}"\` and the user expected the key
|
|
297
|
+
to just work, propose the fix: edit config.json directly
|
|
298
|
+
(use the \`config_write\` tool) with the actual key. Only
|
|
299
|
+
fall back to \`read_env_file\` if the user explicitly
|
|
300
|
+
chose --use-env mode (apiKey is a placeholder by design)
|
|
301
|
+
or the config shows a literal key but doctor still says
|
|
302
|
+
it's empty (config.json malformed).
|
|
303
|
+
Don't ask the user to grep their own files.
|
|
304
|
+
* Empty logs but lastExitStatus \!= 0 → the process was
|
|
305
|
+
killed pre-stdio (signal). The hint field in
|
|
306
|
+
read_service_logs's result will spell this out.
|
|
307
|
+
Then propose the *specific* fix to the user before mutating
|
|
308
|
+
anything.
|
|
309
|
+
|
|
310
|
+
When the user says they're done / satisfied / wants to exit, run
|
|
311
|
+
run_doctor one last time, summarise, then end with:
|
|
312
|
+
"All set. Run 'tianshu dev' (or 'npm run dev' in a checkout)
|
|
313
|
+
to start the server."`;
|
|
314
|
+
/**
|
|
315
|
+
* The user's identity for HTTP calls. The server-side dev
|
|
316
|
+
* resolver chain accepts a `tianshu_identity=<tenant>/<user>`
|
|
317
|
+
* cookie, so we forge one matching whatever tenant the agent is
|
|
318
|
+
* targeting in each call. We always go in as the tenant's `dev`
|
|
319
|
+
* user (the bootstrap user) since the wizard hasn't created
|
|
320
|
+
* anyone else yet.
|
|
321
|
+
*/
|
|
322
|
+
function identityCookie(tenantId) {
|
|
323
|
+
return `tianshu_identity=${encodeURIComponent(`${tenantId}/dev`)}`;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Make an HTTP request against the running server, returning the
|
|
327
|
+
* parsed JSON body or throwing an Error with the response text.
|
|
328
|
+
* Used by the HTTP-backed tools when the wizard has spun up a
|
|
329
|
+
* server already.
|
|
330
|
+
*/
|
|
331
|
+
async function serverFetch(serverUrl, method, pathSegment, tenantId, body, timeoutMs = 30_000) {
|
|
332
|
+
const ac = new AbortController();
|
|
333
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
334
|
+
try {
|
|
335
|
+
const res = await fetch(`${serverUrl}${pathSegment}`, {
|
|
336
|
+
method,
|
|
337
|
+
headers: {
|
|
338
|
+
"content-type": "application/json",
|
|
339
|
+
cookie: identityCookie(tenantId),
|
|
340
|
+
},
|
|
341
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
342
|
+
signal: ac.signal,
|
|
343
|
+
});
|
|
344
|
+
const text = await res.text();
|
|
345
|
+
let parsed;
|
|
346
|
+
try {
|
|
347
|
+
parsed = text ? JSON.parse(text) : {};
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
parsed = { raw: text };
|
|
351
|
+
}
|
|
352
|
+
if (!res.ok) {
|
|
353
|
+
throw new Error(`${method} ${pathSegment} → HTTP ${res.status}: ${text.slice(0, 400)}`);
|
|
354
|
+
}
|
|
355
|
+
return parsed;
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
clearTimeout(timer);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Exported for tests only — production callers go through
|
|
363
|
+
* runSetupAgent, which constructs tools and the system prompt
|
|
364
|
+
* together. Tests can grab a single tool's `execute` to verify
|
|
365
|
+
* its behaviour in isolation.
|
|
366
|
+
*/
|
|
367
|
+
export function buildTools(home, serverUrl) {
|
|
368
|
+
const ops = new GlobalOps({ home });
|
|
369
|
+
return {
|
|
370
|
+
tenant_list: {
|
|
371
|
+
schema: {
|
|
372
|
+
name: "tenant_list",
|
|
373
|
+
description: "List all tenants on disk under ~/.tianshu/tenants/. Returns an array of tenant ids.",
|
|
374
|
+
parameters: {
|
|
375
|
+
type: "object",
|
|
376
|
+
properties: {},
|
|
377
|
+
required: [],
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
execute: async () => {
|
|
381
|
+
const ids = ops.list();
|
|
382
|
+
return JSON.stringify({ tenants: ids });
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
tenant_create: {
|
|
386
|
+
mutating: true,
|
|
387
|
+
describe: (args) => `Create new tenant '${String(args.id ?? "?")}'`,
|
|
388
|
+
schema: {
|
|
389
|
+
name: "tenant_create",
|
|
390
|
+
description: "Create a new tenant with the given id. Tenant ids must be a-z, 0-9, hyphen. Idempotent: returns the tenant whether or not it pre-existed.",
|
|
391
|
+
parameters: {
|
|
392
|
+
type: "object",
|
|
393
|
+
properties: {
|
|
394
|
+
id: {
|
|
395
|
+
type: "string",
|
|
396
|
+
description: "Tenant id (a-z 0-9 hyphen). Examples: 'work', 'sandbox', 'team-foo'.",
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
required: ["id"],
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
execute: async (args) => {
|
|
403
|
+
const id = String(args.id ?? "");
|
|
404
|
+
const ctx = ops.exists(id) ? ops.open(id) : ops.create(id);
|
|
405
|
+
return JSON.stringify({
|
|
406
|
+
tenantId: ctx.tenantId,
|
|
407
|
+
root: ctx.root,
|
|
408
|
+
alreadyExisted: ops.exists(id),
|
|
409
|
+
});
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
user_create: {
|
|
413
|
+
mutating: true,
|
|
414
|
+
describe: (args) => `Create user '${String(args.userId ?? "?")}' in tenant '${String(args.tenantId ?? "?")}'`,
|
|
415
|
+
schema: {
|
|
416
|
+
name: "user_create",
|
|
417
|
+
description: "Create a user inside an existing tenant. Idempotent (re-creating a user is a no-op).",
|
|
418
|
+
parameters: {
|
|
419
|
+
type: "object",
|
|
420
|
+
properties: {
|
|
421
|
+
tenantId: { type: "string", description: "Tenant id." },
|
|
422
|
+
userId: {
|
|
423
|
+
type: "string",
|
|
424
|
+
description: "User id (a-z 0-9 hyphen).",
|
|
425
|
+
},
|
|
426
|
+
displayName: {
|
|
427
|
+
type: "string",
|
|
428
|
+
description: "Optional display name.",
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
required: ["tenantId", "userId"],
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
execute: async (args) => {
|
|
435
|
+
const tenantId = String(args.tenantId);
|
|
436
|
+
const userId = String(args.userId);
|
|
437
|
+
const ctx = ops.open(tenantId);
|
|
438
|
+
ops.ensureUser(ctx, {
|
|
439
|
+
userId,
|
|
440
|
+
provider: "dev",
|
|
441
|
+
externalId: `${userId}@local`,
|
|
442
|
+
displayName: args.displayName ? String(args.displayName) : undefined,
|
|
443
|
+
});
|
|
444
|
+
return JSON.stringify({ tenantId, userId });
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
plugin_enable: {
|
|
448
|
+
mutating: true,
|
|
449
|
+
describe: (args) => `Enable plugin '${String(args.pluginId ?? "?")}' in tenant '${String(args.tenantId ?? "?")}'`,
|
|
450
|
+
schema: {
|
|
451
|
+
name: "plugin_enable",
|
|
452
|
+
description: "Enable a built-in plugin (files | workboard | microsandbox | web-search) inside a tenant. When the wizard has a running server, this routes through PATCH /api/plugins/:id so plugin lifecycle hooks fire (activation, registry refresh, plugins_changed broadcast) — the same path the admin UI uses. Without a server we fall back to editing the config.json directly; the plugin will activate next time the server boots.",
|
|
453
|
+
parameters: {
|
|
454
|
+
type: "object",
|
|
455
|
+
properties: {
|
|
456
|
+
tenantId: { type: "string" },
|
|
457
|
+
pluginId: {
|
|
458
|
+
type: "string",
|
|
459
|
+
enum: ["files", "workboard", "microsandbox", "web-search"],
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
required: ["tenantId", "pluginId"],
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
execute: async (args) => {
|
|
466
|
+
const tenantId = String(args.tenantId);
|
|
467
|
+
const pluginId = String(args.pluginId);
|
|
468
|
+
if (serverUrl) {
|
|
469
|
+
const r = await serverFetch(serverUrl, "PATCH", `/api/plugins/${encodeURIComponent(pluginId)}`, tenantId, { enabled: true });
|
|
470
|
+
return JSON.stringify({
|
|
471
|
+
tenantId,
|
|
472
|
+
pluginId,
|
|
473
|
+
enabled: true,
|
|
474
|
+
via: "http",
|
|
475
|
+
response: r,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
const cfgPath = path.join(getTenantsRoot(home), tenantId, "config.json");
|
|
479
|
+
const cfg = readJsonOrEmpty(cfgPath);
|
|
480
|
+
cfg.plugins = cfg.plugins ?? {};
|
|
481
|
+
const existing = cfg.plugins[pluginId] ?? {};
|
|
482
|
+
cfg.plugins[pluginId] = {
|
|
483
|
+
...existing,
|
|
484
|
+
enabled: true,
|
|
485
|
+
};
|
|
486
|
+
writeJsonAtomic(cfgPath, cfg);
|
|
487
|
+
return JSON.stringify({
|
|
488
|
+
tenantId,
|
|
489
|
+
pluginId,
|
|
490
|
+
enabled: true,
|
|
491
|
+
via: "file",
|
|
492
|
+
});
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
plugin_disable: {
|
|
496
|
+
mutating: true,
|
|
497
|
+
describe: (args) => `Disable plugin '${String(args.pluginId ?? "?")}' in tenant '${String(args.tenantId ?? "?")}'`,
|
|
498
|
+
schema: {
|
|
499
|
+
name: "plugin_disable",
|
|
500
|
+
description: "Disable a plugin in the given tenant. Routes through PATCH /api/plugins/:id when a server is running so the plugin's deactivate hook fires; otherwise edits config.json directly.",
|
|
501
|
+
parameters: {
|
|
502
|
+
type: "object",
|
|
503
|
+
properties: {
|
|
504
|
+
tenantId: { type: "string" },
|
|
505
|
+
pluginId: { type: "string" },
|
|
506
|
+
},
|
|
507
|
+
required: ["tenantId", "pluginId"],
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
execute: async (args) => {
|
|
511
|
+
const tenantId = String(args.tenantId);
|
|
512
|
+
const pluginId = String(args.pluginId);
|
|
513
|
+
if (serverUrl) {
|
|
514
|
+
const r = await serverFetch(serverUrl, "PATCH", `/api/plugins/${encodeURIComponent(pluginId)}`, tenantId, { enabled: false });
|
|
515
|
+
return JSON.stringify({
|
|
516
|
+
tenantId,
|
|
517
|
+
pluginId,
|
|
518
|
+
enabled: false,
|
|
519
|
+
via: "http",
|
|
520
|
+
response: r,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
const cfgPath = path.join(getTenantsRoot(home), tenantId, "config.json");
|
|
524
|
+
const cfg = readJsonOrEmpty(cfgPath);
|
|
525
|
+
cfg.plugins = cfg.plugins ?? {};
|
|
526
|
+
const existing = cfg.plugins[pluginId] ?? {};
|
|
527
|
+
cfg.plugins[pluginId] = {
|
|
528
|
+
...existing,
|
|
529
|
+
enabled: false,
|
|
530
|
+
};
|
|
531
|
+
writeJsonAtomic(cfgPath, cfg);
|
|
532
|
+
return JSON.stringify({
|
|
533
|
+
tenantId,
|
|
534
|
+
pluginId,
|
|
535
|
+
enabled: false,
|
|
536
|
+
via: "file",
|
|
537
|
+
});
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
config_read: {
|
|
541
|
+
schema: {
|
|
542
|
+
name: "config_read",
|
|
543
|
+
description: "Read a config file. `which='global'` for ~/.tianshu/config.json; `which='tenant'` requires `tenantId` and reads ~/.tianshu/tenants/<id>/config.json.",
|
|
544
|
+
parameters: {
|
|
545
|
+
type: "object",
|
|
546
|
+
properties: {
|
|
547
|
+
which: { type: "string", enum: ["global", "tenant"] },
|
|
548
|
+
tenantId: { type: "string" },
|
|
549
|
+
},
|
|
550
|
+
required: ["which"],
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
execute: async (args) => {
|
|
554
|
+
const which = String(args.which);
|
|
555
|
+
if (which === "global") {
|
|
556
|
+
const cfg = readJsonOrEmpty(getGlobalConfigPath(home));
|
|
557
|
+
return JSON.stringify(cfg);
|
|
558
|
+
}
|
|
559
|
+
const tenantId = String(args.tenantId ?? "");
|
|
560
|
+
if (!tenantId)
|
|
561
|
+
return JSON.stringify({ error: "tenantId required" });
|
|
562
|
+
const cfg = readJsonOrEmpty(path.join(getTenantsRoot(home), tenantId, "config.json"));
|
|
563
|
+
return JSON.stringify(cfg);
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
config_write: {
|
|
567
|
+
mutating: true,
|
|
568
|
+
describe: (args) => {
|
|
569
|
+
const which = String(args.which ?? "tenant");
|
|
570
|
+
const patch = args.patch ?? {};
|
|
571
|
+
const keys = Object.keys(patch).join(", ") || "(empty patch)";
|
|
572
|
+
if (which === "global") {
|
|
573
|
+
return `Patch ~/.tianshu/config.json (keys: ${keys})`;
|
|
574
|
+
}
|
|
575
|
+
return `Patch tenant '${String(args.tenantId ?? "?")}' config (keys: ${keys})`;
|
|
576
|
+
},
|
|
577
|
+
schema: {
|
|
578
|
+
name: "config_write",
|
|
579
|
+
description: "Write a config file by merging the supplied object into the existing file. Top-level keys in the patch overwrite existing values; non-mentioned keys are preserved (shallow merge).\n\n which='global' → ~/.tianshu/config.json. Use this for cross-tenant settings: the server-wide provider catalog (models.providers), the default model, server-only fields (server.port, logging.level, autoCreateDefault), or to fix a bad `api` value doctor flagged on the global pass.\n which='tenant' → ~/.tianshu/tenants/<id>/config.json. Use for per-tenant overrides: enabling/disabling plugins for one tenant, giving one tenant a different defaultModel, swapping in a tenant-specific provider catalog. Requires `tenantId`.\n\nGoes through the same write path the server uses (writeGlobalConfig / writeTenantConfig), so the tenant write enforces the OverridableConfig whitelist: trying to set server.port / logging on a tenant returns a TenantConfigForbiddenFieldError and the patch is rejected.",
|
|
580
|
+
parameters: {
|
|
581
|
+
type: "object",
|
|
582
|
+
properties: {
|
|
583
|
+
which: {
|
|
584
|
+
type: "string",
|
|
585
|
+
enum: ["global", "tenant"],
|
|
586
|
+
description: "'global' = ~/.tianshu/config.json (system-wide). 'tenant' = ~/.tianshu/tenants/<id>/config.json (per-tenant). Defaults to 'tenant' for backward compatibility, but be explicit — the agent's earlier behaviour silently assumed tenant which was wrong when the user wanted a global change.",
|
|
587
|
+
},
|
|
588
|
+
tenantId: {
|
|
589
|
+
type: "string",
|
|
590
|
+
description: "Required when which='tenant'.",
|
|
591
|
+
},
|
|
592
|
+
patch: {
|
|
593
|
+
type: "object",
|
|
594
|
+
description: "Object to merge into the existing config (top-level shallow merge).",
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
required: ["patch"],
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
execute: async (args) => {
|
|
601
|
+
const which = String(args.which ?? "tenant");
|
|
602
|
+
const patch = args.patch ?? {};
|
|
603
|
+
if (which === "global") {
|
|
604
|
+
// Read-merge-write so partial patches don't drop
|
|
605
|
+
// existing keys (preserves the documented shallow-
|
|
606
|
+
// merge semantics).
|
|
607
|
+
const cfg = readJsonOrEmpty(getGlobalConfigPath(home));
|
|
608
|
+
const merged = { ...cfg, ...patch };
|
|
609
|
+
writeGlobalConfig(merged, home);
|
|
610
|
+
return JSON.stringify({
|
|
611
|
+
which: "global",
|
|
612
|
+
path: getGlobalConfigPath(home),
|
|
613
|
+
patched: Object.keys(patch),
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
// tenant
|
|
617
|
+
const tenantId = String(args.tenantId ?? "");
|
|
618
|
+
if (!tenantId) {
|
|
619
|
+
return JSON.stringify({
|
|
620
|
+
error: "missing_tenant_id",
|
|
621
|
+
message: "which='tenant' requires tenantId. Pass which='global' if you meant the global config.",
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
const cfgPath = path.join(getTenantsRoot(home), tenantId, "config.json");
|
|
625
|
+
const cfg = readJsonOrEmpty(cfgPath);
|
|
626
|
+
const merged = { ...cfg, ...patch };
|
|
627
|
+
try {
|
|
628
|
+
writeTenantConfig(tenantId, merged, home);
|
|
629
|
+
}
|
|
630
|
+
catch (err) {
|
|
631
|
+
if (err instanceof TenantConfigForbiddenFieldError) {
|
|
632
|
+
return JSON.stringify({
|
|
633
|
+
error: "tenant_forbidden_field",
|
|
634
|
+
message: err.message,
|
|
635
|
+
hint: "That field can only be set on the global config (which='global'). Tenants override the catalog of models / plugins / branding only.",
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
throw err;
|
|
639
|
+
}
|
|
640
|
+
return JSON.stringify({
|
|
641
|
+
which: "tenant",
|
|
642
|
+
tenantId,
|
|
643
|
+
patched: Object.keys(patch),
|
|
644
|
+
});
|
|
645
|
+
},
|
|
646
|
+
},
|
|
647
|
+
secret_list: {
|
|
648
|
+
schema: {
|
|
649
|
+
name: "secret_list",
|
|
650
|
+
description: "List secret keys configured for a plugin in a tenant. Returns key names only — NEVER values. Reads via the same plugin-secrets module the plugin runtime uses at activation time, so what you see matches what the plugin will see.",
|
|
651
|
+
parameters: {
|
|
652
|
+
type: "object",
|
|
653
|
+
properties: {
|
|
654
|
+
tenantId: { type: "string" },
|
|
655
|
+
pluginId: { type: "string" },
|
|
656
|
+
},
|
|
657
|
+
required: ["tenantId", "pluginId"],
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
execute: async (args) => {
|
|
661
|
+
const tenantId = String(args.tenantId);
|
|
662
|
+
const pluginId = String(args.pluginId);
|
|
663
|
+
if (!ops.exists(tenantId)) {
|
|
664
|
+
return JSON.stringify({
|
|
665
|
+
tenantId,
|
|
666
|
+
pluginId,
|
|
667
|
+
keys: [],
|
|
668
|
+
error: `tenant ${tenantId} does not exist`,
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
const ctx = ops.open(tenantId);
|
|
672
|
+
const secrets = loadPluginSecrets(ctx.secretsDir, pluginId);
|
|
673
|
+
return JSON.stringify({
|
|
674
|
+
tenantId,
|
|
675
|
+
pluginId,
|
|
676
|
+
keys: Object.keys(secrets),
|
|
677
|
+
});
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
secret_write: {
|
|
681
|
+
mutating: true,
|
|
682
|
+
describe: (args) => `Set secret '${String(args.key ?? "?")}' for plugin '${String(args.pluginId ?? "?")}' in tenant '${String(args.tenantId ?? "?")}'`,
|
|
683
|
+
schema: {
|
|
684
|
+
name: "secret_write",
|
|
685
|
+
description: "Set a plugin secret (API key, token) for a tenant. Goes through the same applyPluginSecretPatch the PATCH /api/plugins/:id route uses, so the file format, mode 0600, and atomic write semantics all match what the plugin runtime expects. Do NOT use config_write for API keys.\n\nWeb-search keys go here:\n pluginId='web-search', key='tavilyApiKey' or 'braveApiKey'.\n\nNew secrets merge with existing ones; other keys for the same plugin are preserved.",
|
|
686
|
+
parameters: {
|
|
687
|
+
type: "object",
|
|
688
|
+
properties: {
|
|
689
|
+
tenantId: { type: "string" },
|
|
690
|
+
pluginId: { type: "string" },
|
|
691
|
+
key: {
|
|
692
|
+
type: "string",
|
|
693
|
+
description: "Dotted secret name. For web-search use 'tavilyApiKey' or 'braveApiKey'.",
|
|
694
|
+
},
|
|
695
|
+
value: { type: "string" },
|
|
696
|
+
},
|
|
697
|
+
required: ["tenantId", "pluginId", "key", "value"],
|
|
698
|
+
},
|
|
699
|
+
},
|
|
700
|
+
execute: async (args) => {
|
|
701
|
+
const tenantId = String(args.tenantId);
|
|
702
|
+
const pluginId = String(args.pluginId);
|
|
703
|
+
const key = String(args.key);
|
|
704
|
+
const value = String(args.value);
|
|
705
|
+
if (serverUrl) {
|
|
706
|
+
// PATCH /api/plugins/:id with { config: { <key>: <value> } }.
|
|
707
|
+
// The route checks the plugin's manifest configSchema and
|
|
708
|
+
// routes secret-typed fields to <tenant>/secrets/...
|
|
709
|
+
// automatically. We send a patch with just our key; other
|
|
710
|
+
// existing secrets / cleartext config are preserved.
|
|
711
|
+
const r = await serverFetch(serverUrl, "PATCH", `/api/plugins/${encodeURIComponent(pluginId)}`, tenantId, { config: { [key]: value } });
|
|
712
|
+
return JSON.stringify({
|
|
713
|
+
tenantId,
|
|
714
|
+
pluginId,
|
|
715
|
+
key,
|
|
716
|
+
via: "http",
|
|
717
|
+
response: r,
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
const ctx = ops.exists(tenantId)
|
|
721
|
+
? ops.open(tenantId)
|
|
722
|
+
: ops.create(tenantId);
|
|
723
|
+
const result = applyPluginSecretPatch(ctx.secretsDir, pluginId, {
|
|
724
|
+
[key]: value,
|
|
725
|
+
});
|
|
726
|
+
return JSON.stringify({
|
|
727
|
+
tenantId,
|
|
728
|
+
pluginId,
|
|
729
|
+
keysAfter: Object.keys(result.secrets),
|
|
730
|
+
changed: result.changed,
|
|
731
|
+
via: "file",
|
|
732
|
+
});
|
|
733
|
+
},
|
|
734
|
+
},
|
|
735
|
+
run_doctor: {
|
|
736
|
+
schema: {
|
|
737
|
+
name: "run_doctor",
|
|
738
|
+
description: "Run `tianshu doctor` and return the structured report. Use this to check setup state before suggesting next steps.",
|
|
739
|
+
parameters: {
|
|
740
|
+
type: "object",
|
|
741
|
+
properties: {},
|
|
742
|
+
required: [],
|
|
743
|
+
},
|
|
744
|
+
},
|
|
745
|
+
execute: async () => {
|
|
746
|
+
const r = await collectDoctorReport({});
|
|
747
|
+
return JSON.stringify({
|
|
748
|
+
ok: r.blocker === 0,
|
|
749
|
+
tally: { ok: r.ok, warning: r.warning, blocker: r.blocker },
|
|
750
|
+
groups: r.groups.map((g) => ({
|
|
751
|
+
title: g.title,
|
|
752
|
+
lines: g.lines.map((l) => ({
|
|
753
|
+
severity: l.severity,
|
|
754
|
+
text: l.text,
|
|
755
|
+
detail: l.detail,
|
|
756
|
+
})),
|
|
757
|
+
})),
|
|
758
|
+
});
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
read_service_logs: {
|
|
762
|
+
schema: {
|
|
763
|
+
name: "read_service_logs",
|
|
764
|
+
description: "Read the launchd-managed dev server's stdout/stderr logs. " +
|
|
765
|
+
"Use this when the wizard installed a launchd agent but the server " +
|
|
766
|
+
"didn't pass the health check, or when `run_doctor` reports the " +
|
|
767
|
+
"server isn't responding. Returns the most recent log lines along " +
|
|
768
|
+
"with the agent's installed/loaded/pid status so you can correlate. " +
|
|
769
|
+
"This is your *primary diagnostic tool* for boot failures — call it " +
|
|
770
|
+
"before guessing what went wrong.",
|
|
771
|
+
parameters: {
|
|
772
|
+
type: "object",
|
|
773
|
+
properties: {
|
|
774
|
+
lines: {
|
|
775
|
+
type: "number",
|
|
776
|
+
description: "How many trailing lines to return per stream. Default 80. Bump to 200+ if you don't see the error in 80.",
|
|
777
|
+
},
|
|
778
|
+
stream: {
|
|
779
|
+
type: "string",
|
|
780
|
+
enum: ["err", "out", "both"],
|
|
781
|
+
description: "Which stream(s) to read. Boot errors usually land in 'err' first; 'out' carries normal startup messages. Default 'both'.",
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
required: [],
|
|
785
|
+
},
|
|
786
|
+
},
|
|
787
|
+
execute: async (args) => {
|
|
788
|
+
const repoRoot = findRepoRoot();
|
|
789
|
+
const label = launchd.resolveLabel(repoRoot);
|
|
790
|
+
const status = launchd.readStatus(label);
|
|
791
|
+
const { out, err } = launchd.logPathsFor(label);
|
|
792
|
+
const linesArg = Number(args.lines);
|
|
793
|
+
const lines = Number.isFinite(linesArg) && linesArg > 0 ? Math.min(linesArg, 1000) : 80;
|
|
794
|
+
const streamArg = String(args.stream ?? "both");
|
|
795
|
+
const stream = streamArg === "out" || streamArg === "err" || streamArg === "both"
|
|
796
|
+
? streamArg
|
|
797
|
+
: "both";
|
|
798
|
+
const result = {
|
|
799
|
+
label,
|
|
800
|
+
installed: status.installed,
|
|
801
|
+
loaded: status.loaded,
|
|
802
|
+
pid: status.pid,
|
|
803
|
+
lastExitStatus: status.lastExitStatus,
|
|
804
|
+
};
|
|
805
|
+
const tail = (file) => {
|
|
806
|
+
if (!fs.existsSync(file))
|
|
807
|
+
return [];
|
|
808
|
+
try {
|
|
809
|
+
const body = fs.readFileSync(file, "utf8");
|
|
810
|
+
return body.split(/\r?\n/).slice(-lines).filter((l) => l.length > 0);
|
|
811
|
+
}
|
|
812
|
+
catch {
|
|
813
|
+
return [];
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
if (stream === "err" || stream === "both") {
|
|
817
|
+
result.stderr = { path: err, lines: tail(err) };
|
|
818
|
+
}
|
|
819
|
+
if (stream === "out" || stream === "both") {
|
|
820
|
+
result.stdout = { path: out, lines: tail(out) };
|
|
821
|
+
}
|
|
822
|
+
// If both streams are empty, give the agent an explicit
|
|
823
|
+
// hint about what that means — saves it from guessing.
|
|
824
|
+
const stdoutEmpty = !result.stdout || result.stdout.lines.length === 0;
|
|
825
|
+
const stderrEmpty = !result.stderr || result.stderr.lines.length === 0;
|
|
826
|
+
if (stdoutEmpty && stderrEmpty) {
|
|
827
|
+
if (!status.installed) {
|
|
828
|
+
result.hint =
|
|
829
|
+
"Service isn't installed (no plist on disk). Tell the user to run `tianshu setup --wizard` and walk them through it.";
|
|
830
|
+
}
|
|
831
|
+
else if (!status.loaded) {
|
|
832
|
+
result.hint =
|
|
833
|
+
"Plist exists but launchd hasn't loaded it. Run `tianshu start` (or have the user run it). If start fails, the launchctl error is itself the diagnostic.";
|
|
834
|
+
}
|
|
835
|
+
else if (status.pid !== null) {
|
|
836
|
+
result.hint =
|
|
837
|
+
"Service is running (loaded + pid present) but logs are empty. Most likely the service just started and hasn't flushed yet — wait 10s and call read_service_logs again. If logs stay empty for a minute, the process may be wedged on something pre-stdio (e.g. waiting for stdin).";
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
result.hint =
|
|
841
|
+
"Service is loaded but no pid — it crashed and launchd is between restarts (ThrottleInterval=30s). Wait, then read again, and look for the actual exit reason in lastExitStatus.";
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
else if (stderrEmpty &&
|
|
845
|
+
status.loaded &&
|
|
846
|
+
status.pid === null &&
|
|
847
|
+
status.lastExitStatus !== null &&
|
|
848
|
+
status.lastExitStatus !== 0) {
|
|
849
|
+
result.hint = `Service exited (lastExitStatus=${status.lastExitStatus}) and stderr is empty. Look in stdout for the last messages before the exit; if those don't explain it, the process may have been killed by a signal (e.g. OOM → 137; SIGTERM → 143) rather than crashing with output.`;
|
|
850
|
+
}
|
|
851
|
+
return JSON.stringify(result);
|
|
852
|
+
},
|
|
853
|
+
},
|
|
854
|
+
read_env_file: {
|
|
855
|
+
schema: {
|
|
856
|
+
name: "read_env_file",
|
|
857
|
+
description: "List the keys (and value lengths, NOT values) in the .env file the dev server actually loads. Use this when run_doctor or read_service_logs reports a missing env var (e.g. 'ANTHROPIC_API_KEY references env var but it's empty') — you can see directly whether the key is present, whether the user accidentally put it in `~/.env` instead of the repo's `.env`, and whether the value is suspiciously short (<8 chars) or empty.\n\nReturns ONLY key names + length + a 4-char prefix for sanity, NEVER the full value, so it's safe to print to the user. The file path returned is the canonical path the server reads from (resolved by the same logic loadEnv() uses, so what you see matches what the running server sees).",
|
|
858
|
+
parameters: {
|
|
859
|
+
type: "object",
|
|
860
|
+
properties: {
|
|
861
|
+
keyFilter: {
|
|
862
|
+
type: "string",
|
|
863
|
+
description: "Optional substring — only return keys containing this string (case-insensitive). Example: 'API_KEY' to filter to provider keys.",
|
|
864
|
+
},
|
|
865
|
+
},
|
|
866
|
+
required: [],
|
|
867
|
+
},
|
|
868
|
+
},
|
|
869
|
+
execute: async (args) => {
|
|
870
|
+
const repoRoot = findRepoRoot();
|
|
871
|
+
const envPath = path.join(repoRoot, ".env");
|
|
872
|
+
const homeEnvPath = path.join(os.homedir(), ".env");
|
|
873
|
+
const filter = args.keyFilter
|
|
874
|
+
? String(args.keyFilter).toLowerCase()
|
|
875
|
+
: null;
|
|
876
|
+
const summarize = (filepath) => {
|
|
877
|
+
if (!fs.existsSync(filepath)) {
|
|
878
|
+
return { path: filepath, exists: false, keys: [] };
|
|
879
|
+
}
|
|
880
|
+
let body;
|
|
881
|
+
try {
|
|
882
|
+
body = fs.readFileSync(filepath, "utf8");
|
|
883
|
+
}
|
|
884
|
+
catch (e) {
|
|
885
|
+
return {
|
|
886
|
+
path: filepath,
|
|
887
|
+
exists: true,
|
|
888
|
+
error: e.message,
|
|
889
|
+
keys: [],
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
const keys = [];
|
|
893
|
+
for (const rawLine of body.split(/\r?\n/)) {
|
|
894
|
+
const line = rawLine.trim();
|
|
895
|
+
if (!line || line.startsWith("#"))
|
|
896
|
+
continue;
|
|
897
|
+
const eq = line.indexOf("=");
|
|
898
|
+
if (eq < 1)
|
|
899
|
+
continue;
|
|
900
|
+
const key = line.slice(0, eq).trim();
|
|
901
|
+
// Strip surrounding quotes (single, double) so length
|
|
902
|
+
// reflects what dotenv actually parses.
|
|
903
|
+
let raw = line.slice(eq + 1).trim();
|
|
904
|
+
if ((raw.startsWith('"') && raw.endsWith('"')) ||
|
|
905
|
+
(raw.startsWith("'") && raw.endsWith("'"))) {
|
|
906
|
+
raw = raw.slice(1, -1);
|
|
907
|
+
}
|
|
908
|
+
if (filter && !key.toLowerCase().includes(filter))
|
|
909
|
+
continue;
|
|
910
|
+
keys.push({
|
|
911
|
+
key,
|
|
912
|
+
length: raw.length,
|
|
913
|
+
prefix: raw.slice(0, 4),
|
|
914
|
+
empty: raw.length === 0,
|
|
915
|
+
suspicious: raw.length > 0 && raw.length < 8,
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
return { path: filepath, exists: true, keys };
|
|
919
|
+
};
|
|
920
|
+
const result = {
|
|
921
|
+
// The canonical path the server *should* be reading.
|
|
922
|
+
// This matches the wizard's writePath, which matches
|
|
923
|
+
// load-env.ts's repo-root walk.
|
|
924
|
+
serverEnv: summarize(envPath),
|
|
925
|
+
// Common user mistake: put keys in ~/.env. We surface
|
|
926
|
+
// it so the agent can spot it and tell the user to
|
|
927
|
+
// move/copy the line.
|
|
928
|
+
homeEnv: envPath === homeEnvPath ? null : summarize(homeEnvPath),
|
|
929
|
+
note: "Values are NEVER returned. `length` and `prefix` are for diagnostic sanity only. If `serverEnv.keys` doesn't include the key the user expects but `homeEnv.keys` does, the user put it in the wrong file — tell them to move/copy the line into serverEnv.path.",
|
|
930
|
+
};
|
|
931
|
+
return JSON.stringify(result);
|
|
932
|
+
},
|
|
933
|
+
},
|
|
934
|
+
build_sandbox: {
|
|
935
|
+
mutating: true,
|
|
936
|
+
describe: (args) => {
|
|
937
|
+
const tpl = String(args.template ?? "task-runner-with-browser");
|
|
938
|
+
const tenantId = String(args.tenantId ?? "default");
|
|
939
|
+
return `Build a microsandbox snapshot from the '${tpl}' template (tenant '${tenantId}'). This downloads the base image, installs Chromium / LibreOffice / Node / Python inside the VM, and saves a snapshot. Cold builds take 5-10 min, cache hits 3-5 min. The wizard will block on this call until done.`;
|
|
940
|
+
},
|
|
941
|
+
schema: {
|
|
942
|
+
name: "build_sandbox",
|
|
943
|
+
description: "Build a microsandbox snapshot from a packaged template ('browser' or 'task-runner') and return its build id. This is the one-shot equivalent of the chat-shell `build_sandbox` tool: it (1) writes the chosen template into the user's Sandboxfile via PUT /api/p/microsandbox/sandboxfile, then (2) calls POST /api/p/microsandbox/builds to actually build the snapshot.\n\nUse this when the user asks to set up sandboxes during initial install. Cold build = 5-10 min (apt + Chromium + Playwright + LibreOffice tarball pulls); the wizard's whole UI will hang on the spinner. Tell the user that up front.\n\nAfter build, call use_sandbox_build with the returned buildId to publish the snapshot to a role pointer (browser / task / both).",
|
|
944
|
+
parameters: {
|
|
945
|
+
type: "object",
|
|
946
|
+
properties: {
|
|
947
|
+
tenantId: {
|
|
948
|
+
type: "string",
|
|
949
|
+
description: "Tenant whose Sandboxfile to write. Defaults to 'default'. The build runs against this tenant's user-home Sandboxfile.",
|
|
950
|
+
},
|
|
951
|
+
template: {
|
|
952
|
+
type: "string",
|
|
953
|
+
enum: ["task-runner", "browser", "task-runner-with-browser"],
|
|
954
|
+
description: "Which packaged template to write into the Sandboxfile before building.\n\n* 'task-runner' — Node + Python + LibreOffice + office libs, no browser. ~700 MB. Foundation for the layered approach below; also the right choice for users who explicitly don't need a browser.\n* 'task-runner-with-browser' — *layered* template that adds Chromium + Playwright MCP + noVNC on top of an existing task-runner snapshot. MUST be built with `fromSnapshot` set to the snapshotName of a previously-built 'task-runner' (otherwise the build fails at the first apt step). This is the recommended browser-role snapshot for the standard two-step setup flow.\n* 'browser' — monolithic full-stack template (task-runner contents + browser stack from scratch). ~3.2 GB. Builds standalone with no fromSnapshot, but you pay the apt + LibreOffice install twice across builds. Generally avoid in setup; prefer the layered task-runner → task-runner-with-browser sequence.",
|
|
955
|
+
},
|
|
956
|
+
fromSnapshot: {
|
|
957
|
+
type: "string",
|
|
958
|
+
description: "Snapshot name (NOT buildId) to layer this build on top of. Required for template='task-runner-with-browser'; ignored otherwise. Get this from the `snapshotName` field of a previous build_sandbox(template='task-runner') response.",
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
required: ["template"],
|
|
962
|
+
},
|
|
963
|
+
},
|
|
964
|
+
execute: async (args) => {
|
|
965
|
+
if (!serverUrl) {
|
|
966
|
+
return JSON.stringify({
|
|
967
|
+
error: "server_not_running",
|
|
968
|
+
message: "build_sandbox needs a running server (the wizard's HTTP plugin API). The wizard normally starts the server before running the agent; if you got here without a server, run `tianshu start` first.",
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
const tenantId = String(args.tenantId ?? "default");
|
|
972
|
+
const template = String(args.template);
|
|
973
|
+
const fromSnapshot = typeof args.fromSnapshot === "string" && args.fromSnapshot.length > 0
|
|
974
|
+
? args.fromSnapshot
|
|
975
|
+
: undefined;
|
|
976
|
+
// Guardrail: task-runner-with-browser is layered. Without
|
|
977
|
+
// fromSnapshot it will fail at the first apt step. Catch
|
|
978
|
+
// that here so the agent gets an actionable error instead
|
|
979
|
+
// of a generic BuildFailedError after 30 seconds of pulling.
|
|
980
|
+
if (template === "task-runner-with-browser" && !fromSnapshot) {
|
|
981
|
+
return JSON.stringify({
|
|
982
|
+
error: "missing_from_snapshot",
|
|
983
|
+
message: "template 'task-runner-with-browser' is layered — it must be built on top of an existing task-runner snapshot. First call build_sandbox(template='task-runner'), then call build_sandbox(template='task-runner-with-browser', fromSnapshot=<snapshotName from step 1>).",
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
// Step 1: read the requested template body, write it into
|
|
987
|
+
// the tenant's Sandboxfile. The plugin's PUT /sandboxfile
|
|
988
|
+
// accepts the raw text and validates it. We resolve the
|
|
989
|
+
// template path relative to the plugin's installed
|
|
990
|
+
// location, which the server has already loaded.
|
|
991
|
+
const templateBody = await fetchSandboxfileTemplate(serverUrl, tenantId, template);
|
|
992
|
+
if (typeof templateBody !== "string") {
|
|
993
|
+
return JSON.stringify({
|
|
994
|
+
error: "template_not_found",
|
|
995
|
+
template,
|
|
996
|
+
available: templateBody,
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
await serverFetch(serverUrl, "PUT", "/api/p/microsandbox/sandboxfile", tenantId, { content: templateBody });
|
|
1000
|
+
// Step 2: kick the build. We DON'T use the streaming
|
|
1001
|
+
// (?stream=1) endpoint here — the agent runs in a CLI
|
|
1002
|
+
// wizard and reading NDJSON line-by-line through fetch
|
|
1003
|
+
// doesn't buy anything; we just wait for the final
|
|
1004
|
+
// {type:"done"} or HTTP 500. Timeout is 20 min, well
|
|
1005
|
+
// above the worst observed cold build.
|
|
1006
|
+
const buildResp = await serverFetch(serverUrl, "POST", "/api/p/microsandbox/builds", tenantId, fromSnapshot ? { from_snapshot: fromSnapshot } : {}, 20 * 60_000);
|
|
1007
|
+
// Non-streaming response shape: { build: { buildId, snapshotName, ... } }
|
|
1008
|
+
// (or { error, message } on failure, which serverFetch turns into a thrown Error)
|
|
1009
|
+
const build = buildResp?.build;
|
|
1010
|
+
if (!build || !build.buildId) {
|
|
1011
|
+
return JSON.stringify({
|
|
1012
|
+
error: "build_response_unexpected",
|
|
1013
|
+
response: buildResp,
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
// Suggest the right next step based on which template
|
|
1017
|
+
// we just built. The standard layered flow is:
|
|
1018
|
+
// task-runner → publish to role='task', then build
|
|
1019
|
+
// task-runner-with-browser fromSnapshot=<task snapshot>
|
|
1020
|
+
// → publish to role='browser'.
|
|
1021
|
+
let nextStep;
|
|
1022
|
+
if (template === "task-runner") {
|
|
1023
|
+
nextStep = `Call use_sandbox_build with buildId='${build.buildId}' and role='task' to publish this as the task-pool snapshot. Then call build_sandbox again with template='task-runner-with-browser' and fromSnapshot='${build.snapshotName}' to layer the browser stack on top.`;
|
|
1024
|
+
}
|
|
1025
|
+
else if (template === "task-runner-with-browser") {
|
|
1026
|
+
nextStep = `Call use_sandbox_build with buildId='${build.buildId}' and role='browser' to publish this as the long-lived browser sandbox snapshot. The task pointer should already be set from the task-runner step.`;
|
|
1027
|
+
}
|
|
1028
|
+
else {
|
|
1029
|
+
// monolithic 'browser'
|
|
1030
|
+
nextStep = `Call use_sandbox_build with buildId='${build.buildId}' and role='both' to publish this snapshot to both pointers.`;
|
|
1031
|
+
}
|
|
1032
|
+
return JSON.stringify({
|
|
1033
|
+
ok: true,
|
|
1034
|
+
buildId: build.buildId,
|
|
1035
|
+
snapshotName: build.snapshotName,
|
|
1036
|
+
baseImage: build.baseImage,
|
|
1037
|
+
durationMs: build.durationMs,
|
|
1038
|
+
template,
|
|
1039
|
+
fromSnapshot: fromSnapshot ?? null,
|
|
1040
|
+
tenantId,
|
|
1041
|
+
nextStep,
|
|
1042
|
+
});
|
|
1043
|
+
},
|
|
1044
|
+
},
|
|
1045
|
+
use_sandbox_build: {
|
|
1046
|
+
mutating: true,
|
|
1047
|
+
describe: (args) => `Publish snapshot from build '${String(args.buildId ?? "?")}' to role '${String(args.role ?? "both")}' (tenant '${String(args.tenantId ?? "default")}')`,
|
|
1048
|
+
schema: {
|
|
1049
|
+
name: "use_sandbox_build",
|
|
1050
|
+
description: "Publish a built snapshot to a sandbox role pointer. Roles: 'browser' (long-lived chat sandbox with the Chromium sidecar), 'task' (per-task workboard runner pool), or 'both' (recommended when the user just wants everything to work).\n\nUnder the hood: POST /api/p/microsandbox/builds/use?build_id=...&role=...&reset=1. The reset flag bounces the live VM so it boots from the new snapshot — without it the pointer is durable but the running browser sandbox stays on the old snapshot until the next manual restart.\n\nCall this *after* build_sandbox returns a buildId. If the user asked you to 'set up sandboxes' or similar, the natural sequence is build_sandbox → use_sandbox_build with role='both'.",
|
|
1051
|
+
parameters: {
|
|
1052
|
+
type: "object",
|
|
1053
|
+
properties: {
|
|
1054
|
+
tenantId: {
|
|
1055
|
+
type: "string",
|
|
1056
|
+
description: "Tenant whose pointers to update. Defaults to 'default'.",
|
|
1057
|
+
},
|
|
1058
|
+
buildId: {
|
|
1059
|
+
type: "string",
|
|
1060
|
+
description: "Build id returned by build_sandbox. Looks like 'build-20260620-abc123'.",
|
|
1061
|
+
},
|
|
1062
|
+
role: {
|
|
1063
|
+
type: "string",
|
|
1064
|
+
enum: ["browser", "task", "both"],
|
|
1065
|
+
description: "Which role pointer(s) to update. 'browser' = the long-lived browser sandbox. 'task' = the per-task runner pool. 'both' = both, recommended unless the user is doing something specific.",
|
|
1066
|
+
},
|
|
1067
|
+
reset: {
|
|
1068
|
+
type: "boolean",
|
|
1069
|
+
description: "If true (default), bounce the live VM so it boots from the new snapshot immediately. Set false only if you want the pointer change without disrupting an in-flight session.",
|
|
1070
|
+
},
|
|
1071
|
+
},
|
|
1072
|
+
required: ["buildId", "role"],
|
|
1073
|
+
},
|
|
1074
|
+
},
|
|
1075
|
+
execute: async (args) => {
|
|
1076
|
+
if (!serverUrl) {
|
|
1077
|
+
return JSON.stringify({
|
|
1078
|
+
error: "server_not_running",
|
|
1079
|
+
message: "use_sandbox_build needs a running server.",
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
const tenantId = String(args.tenantId ?? "default");
|
|
1083
|
+
const buildId = String(args.buildId);
|
|
1084
|
+
const role = String(args.role);
|
|
1085
|
+
const reset = args.reset !== false; // default true
|
|
1086
|
+
if (!buildId) {
|
|
1087
|
+
return JSON.stringify({
|
|
1088
|
+
error: "missing_build_id",
|
|
1089
|
+
message: "buildId is required.",
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
const qs = new URLSearchParams({
|
|
1093
|
+
build_id: buildId,
|
|
1094
|
+
role,
|
|
1095
|
+
...(reset ? { reset: "1" } : {}),
|
|
1096
|
+
});
|
|
1097
|
+
const resp = await serverFetch(serverUrl, "POST", `/api/p/microsandbox/builds/use?${qs.toString()}`, tenantId, {},
|
|
1098
|
+
// VM bounce can take 20-40s; give it 90s for safety.
|
|
1099
|
+
90_000);
|
|
1100
|
+
return JSON.stringify({
|
|
1101
|
+
ok: true,
|
|
1102
|
+
buildId,
|
|
1103
|
+
role,
|
|
1104
|
+
reset,
|
|
1105
|
+
tenantId,
|
|
1106
|
+
response: resp,
|
|
1107
|
+
});
|
|
1108
|
+
},
|
|
1109
|
+
},
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Fetch a packaged Sandboxfile template body from the running
|
|
1114
|
+
* server. The microsandbox plugin exposes this via
|
|
1115
|
+
* GET /sandboxfile/templates, returning a record of
|
|
1116
|
+
* { name → content }. We look up the requested name and return
|
|
1117
|
+
* its content (or, on miss, the list of available names so the
|
|
1118
|
+
* agent can correct itself).
|
|
1119
|
+
*/
|
|
1120
|
+
async function fetchSandboxfileTemplate(serverUrl, tenantId, name) {
|
|
1121
|
+
const resp = (await serverFetch(serverUrl, "GET", "/api/p/microsandbox/sandboxfile/templates", tenantId));
|
|
1122
|
+
const list = resp.templates ?? [];
|
|
1123
|
+
const hit = list.find((t) => t.id === name);
|
|
1124
|
+
if (hit)
|
|
1125
|
+
return hit.content;
|
|
1126
|
+
return { available: list.map((t) => t.id) };
|
|
1127
|
+
}
|
|
1128
|
+
function readJsonOrEmpty(filepath) {
|
|
1129
|
+
try {
|
|
1130
|
+
return JSON.parse(fs.readFileSync(filepath, "utf8"));
|
|
1131
|
+
}
|
|
1132
|
+
catch {
|
|
1133
|
+
return {};
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
function writeJsonAtomic(filepath, payload) {
|
|
1137
|
+
fs.mkdirSync(path.dirname(filepath), { recursive: true });
|
|
1138
|
+
const tmp = `${filepath}.tmp.${process.pid}`;
|
|
1139
|
+
fs.writeFileSync(tmp, JSON.stringify(payload, null, 2) + "\n");
|
|
1140
|
+
fs.renameSync(tmp, filepath);
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Run the post-wizard CLI agent loop. Resolves when the user exits
|
|
1144
|
+
* (Ctrl-C / "done" / "exit" / "bye") or when the configured turn cap
|
|
1145
|
+
* is hit.
|
|
1146
|
+
*/
|
|
1147
|
+
export async function runCliAgent(opts = {}) {
|
|
1148
|
+
const home = opts.home ?? getTianshuHome();
|
|
1149
|
+
const maxTurns = opts.maxTurns ?? 25;
|
|
1150
|
+
let config;
|
|
1151
|
+
try {
|
|
1152
|
+
config = loadGlobalConfig(home);
|
|
1153
|
+
}
|
|
1154
|
+
catch {
|
|
1155
|
+
p.log.error("Could not load ~/.tianshu/config.json; finish the wizard first.");
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
const info = getDefaultModel(config);
|
|
1159
|
+
if (!info) {
|
|
1160
|
+
p.log.error("No default model configured; finish the wizard first.");
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
const apiKey = resolveApiKey(info);
|
|
1164
|
+
let model;
|
|
1165
|
+
try {
|
|
1166
|
+
model = buildModel(info);
|
|
1167
|
+
}
|
|
1168
|
+
catch (err) {
|
|
1169
|
+
p.log.error(`buildModel failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
const tools = buildTools(home, opts.serverUrl);
|
|
1173
|
+
const toolSchemas = Object.values(tools).map((t) => t.schema);
|
|
1174
|
+
const messages = [];
|
|
1175
|
+
p.log.info(`Setup assistant running on ${info.id}. Every state-changing action will ask for your confirmation. Type 'exit' / Ctrl-C any time.`);
|
|
1176
|
+
// Kick the agent off with the diagnose-and-propose workflow
|
|
1177
|
+
// described in the system prompt. Agent runs run_doctor and
|
|
1178
|
+
// proposes next actions; nothing state-changing happens until
|
|
1179
|
+
// the user explicitly confirms each one.
|
|
1180
|
+
messages.push({
|
|
1181
|
+
role: "user",
|
|
1182
|
+
content: [
|
|
1183
|
+
{
|
|
1184
|
+
type: "text",
|
|
1185
|
+
text: "Begin: run run_doctor, then summarise what's working and propose the next setup decisions for me to choose from. Don't run any state-changing tools yet — wait for me to pick.",
|
|
1186
|
+
},
|
|
1187
|
+
],
|
|
1188
|
+
timestamp: Date.now(),
|
|
1189
|
+
});
|
|
1190
|
+
let turns = 0;
|
|
1191
|
+
while (turns < maxTurns) {
|
|
1192
|
+
turns += 1;
|
|
1193
|
+
let assistant;
|
|
1194
|
+
const ctx = {
|
|
1195
|
+
systemPrompt: SETUP_SYSTEM_PROMPT,
|
|
1196
|
+
messages,
|
|
1197
|
+
tools: toolSchemas,
|
|
1198
|
+
};
|
|
1199
|
+
try {
|
|
1200
|
+
assistant = await complete(model, ctx, { apiKey });
|
|
1201
|
+
}
|
|
1202
|
+
catch (err) {
|
|
1203
|
+
p.log.error(`LLM call failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1206
|
+
messages.push(assistant);
|
|
1207
|
+
// Print any text the assistant emitted.
|
|
1208
|
+
const textParts = assistant.content.filter((c) => c.type === "text");
|
|
1209
|
+
if (textParts.length > 0) {
|
|
1210
|
+
p.log.message(textParts.map((c) => c.text).join("\n"), {
|
|
1211
|
+
symbol: "🌱",
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
else {
|
|
1215
|
+
// Agent returned no text. Either the model short-circuited
|
|
1216
|
+
// the turn or it only emitted tool calls. Surface a
|
|
1217
|
+
// breadcrumb so the operator knows the turn happened.
|
|
1218
|
+
const toolNames = assistant.content
|
|
1219
|
+
.filter((c) => c.type === "toolCall")
|
|
1220
|
+
.map((c) => c.name);
|
|
1221
|
+
if (toolNames.length === 0) {
|
|
1222
|
+
const debug = `stopReason=${assistant.stopReason}` +
|
|
1223
|
+
(assistant.errorMessage ? `, errorMessage=${assistant.errorMessage}` : "") +
|
|
1224
|
+
`, content=${JSON.stringify(assistant.content)}`;
|
|
1225
|
+
p.log.warn(`(model returned an empty turn; ${debug})`);
|
|
1226
|
+
// No useful response. Bail rather than spinning silently.
|
|
1227
|
+
p.outro("The model didn't respond \u2014 it returned an empty message. " +
|
|
1228
|
+
"This usually means the proxy / endpoint stripped the response. " +
|
|
1229
|
+
"Try a different default model, or check the proxy logs.");
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
// Resolve any tool calls.
|
|
1234
|
+
const toolCalls = assistant.content.filter((c) => c.type === "toolCall");
|
|
1235
|
+
if (toolCalls.length === 0) {
|
|
1236
|
+
// No tool calls → wait for user input.
|
|
1237
|
+
const reply = await p.text({
|
|
1238
|
+
message: "you:",
|
|
1239
|
+
placeholder: "(type your reply, or 'exit' to leave)",
|
|
1240
|
+
});
|
|
1241
|
+
if (p.isCancel(reply) || /^(exit|quit|bye|done)$/i.test(String(reply).trim())) {
|
|
1242
|
+
p.outro("All set. Start the server with `tianshu dev` or `npm run dev`.");
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
messages.push({
|
|
1246
|
+
role: "user",
|
|
1247
|
+
content: [{ type: "text", text: String(reply) }],
|
|
1248
|
+
timestamp: Date.now(),
|
|
1249
|
+
});
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
1252
|
+
// Execute every tool call in order.
|
|
1253
|
+
for (const call of toolCalls) {
|
|
1254
|
+
const handler = tools[call.name];
|
|
1255
|
+
let result;
|
|
1256
|
+
if (!handler) {
|
|
1257
|
+
result = {
|
|
1258
|
+
role: "toolResult",
|
|
1259
|
+
toolCallId: call.id,
|
|
1260
|
+
toolName: call.name,
|
|
1261
|
+
content: [
|
|
1262
|
+
{
|
|
1263
|
+
type: "text",
|
|
1264
|
+
text: `unknown tool: ${call.name}`,
|
|
1265
|
+
},
|
|
1266
|
+
],
|
|
1267
|
+
isError: true,
|
|
1268
|
+
timestamp: Date.now(),
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
else {
|
|
1272
|
+
// For mutating tools, surface the intent and ask the user
|
|
1273
|
+
// for explicit confirmation before running. Read-only
|
|
1274
|
+
// tools (run_doctor, tenant_list, config_read) execute
|
|
1275
|
+
// silently — they don't change state.
|
|
1276
|
+
if (handler.mutating) {
|
|
1277
|
+
const summary = handler.describe
|
|
1278
|
+
? handler.describe(call.arguments)
|
|
1279
|
+
: `${call.name}(${shortArgs(call.arguments)})`;
|
|
1280
|
+
const ok = await p.confirm({
|
|
1281
|
+
message: `\ud83d\udd11 Agent wants to: ${summary}`,
|
|
1282
|
+
initialValue: true,
|
|
1283
|
+
});
|
|
1284
|
+
if (p.isCancel(ok) || ok === false) {
|
|
1285
|
+
result = {
|
|
1286
|
+
role: "toolResult",
|
|
1287
|
+
toolCallId: call.id,
|
|
1288
|
+
toolName: call.name,
|
|
1289
|
+
content: [
|
|
1290
|
+
{
|
|
1291
|
+
type: "text",
|
|
1292
|
+
text: `User declined this action. Do not retry without asking. Move on or ask the user what to do instead.`,
|
|
1293
|
+
},
|
|
1294
|
+
],
|
|
1295
|
+
isError: false,
|
|
1296
|
+
timestamp: Date.now(),
|
|
1297
|
+
};
|
|
1298
|
+
p.log.warn(`declined: ${summary}`);
|
|
1299
|
+
messages.push(result);
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
try {
|
|
1304
|
+
const out = await handler.execute(call.arguments);
|
|
1305
|
+
result = {
|
|
1306
|
+
role: "toolResult",
|
|
1307
|
+
toolCallId: call.id,
|
|
1308
|
+
toolName: call.name,
|
|
1309
|
+
content: [{ type: "text", text: out }],
|
|
1310
|
+
isError: false,
|
|
1311
|
+
timestamp: Date.now(),
|
|
1312
|
+
};
|
|
1313
|
+
// Surface what the agent did with enough context that
|
|
1314
|
+
// the user can audit it. Read-only tools just show
|
|
1315
|
+
// name + args; mutating tools were already confirmed
|
|
1316
|
+
// above, so we just confirm completion.
|
|
1317
|
+
if (handler.mutating) {
|
|
1318
|
+
const summary = handler.describe
|
|
1319
|
+
? handler.describe(call.arguments)
|
|
1320
|
+
: `${call.name}(${shortArgs(call.arguments)})`;
|
|
1321
|
+
p.log.success(`done: ${summary}`);
|
|
1322
|
+
}
|
|
1323
|
+
else {
|
|
1324
|
+
p.log.step(`${call.name}(${shortArgs(call.arguments)})`);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
catch (err) {
|
|
1328
|
+
result = {
|
|
1329
|
+
role: "toolResult",
|
|
1330
|
+
toolCallId: call.id,
|
|
1331
|
+
toolName: call.name,
|
|
1332
|
+
content: [
|
|
1333
|
+
{
|
|
1334
|
+
type: "text",
|
|
1335
|
+
text: err instanceof Error ? err.message : String(err),
|
|
1336
|
+
},
|
|
1337
|
+
],
|
|
1338
|
+
isError: true,
|
|
1339
|
+
timestamp: Date.now(),
|
|
1340
|
+
};
|
|
1341
|
+
p.log.warn(`${call.name} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
messages.push(result);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
p.log.warn(`Reached ${maxTurns}-turn cap; exiting. You can re-enter with \`tianshu setup --wizard\`.`);
|
|
1348
|
+
}
|
|
1349
|
+
function shortArgs(args) {
|
|
1350
|
+
const s = JSON.stringify(args);
|
|
1351
|
+
return s.length > 80 ? s.slice(0, 77) + "..." : s;
|
|
1352
|
+
}
|
|
1353
|
+
//# sourceMappingURL=cli-agent.js.map
|