@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,1248 @@
|
|
|
1
|
+
// WebSocket chat handler — wires together the tenant context, the
|
|
2
|
+
// message store, pi-agent-core's runAgentLoop, and the plugin tool
|
|
3
|
+
// surface.
|
|
4
|
+
//
|
|
5
|
+
// Per-turn flow:
|
|
6
|
+
// 1. user prompt arrives → maybe-compact → persist user message
|
|
7
|
+
// 2. hand the prompt to piRunAgentLoop with the tenant's tools
|
|
8
|
+
// and skills, plus a config that caps assistant turns at
|
|
9
|
+
// MAX_TURNS
|
|
10
|
+
// 3. emit() callback bridges pi events to the WS protocol:
|
|
11
|
+
// text_delta deltas → stream_delta
|
|
12
|
+
// toolcall_start → tool_call (UI shows chips early)
|
|
13
|
+
// message_end (assistant) → persist + message_added
|
|
14
|
+
// message_end (toolResult) → persist + tool_result + message_added
|
|
15
|
+
// agent_end → stream_end
|
|
16
|
+
//
|
|
17
|
+
// MAX_TURNS exists because a model that decides to call its tools
|
|
18
|
+
// in a loop with no productive progress would otherwise burn budget
|
|
19
|
+
// forever. shouldStopAfterTurn enforces it.
|
|
20
|
+
import { AgentHarness, DEFAULT_COMPACTION_SETTINGS, Session as PiSession, estimateContextTokens, shouldCompact, } from "@earendil-works/pi-agent-core";
|
|
21
|
+
import fs from "node:fs";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { buildModel, findModel, getDefaultModel, resolveApiKey, } from "../core/index.js";
|
|
24
|
+
import { buildToolset } from "../tools/index.js";
|
|
25
|
+
import { adaptToolset } from "./agent-tool-adapter.js";
|
|
26
|
+
import { dumpSystemPrompt } from "./dump-system-prompt.js";
|
|
27
|
+
import { SqliteSessionRepo } from "./sqlite-session-repo.js";
|
|
28
|
+
import { drainPending as drainInbox, renderForPrompt as renderInboxForPrompt, markDeliveredFromMessage, } from "./session-inbox.js";
|
|
29
|
+
import { registerActiveHarness, registerUserSendChannel, } from "./active-harnesses.js";
|
|
30
|
+
import { SqliteSessionStorage } from "./sqlite-session-storage.js";
|
|
31
|
+
import { makeStubExecutionEnv } from "./stub-execution-env.js";
|
|
32
|
+
import { filterSkillsForTenant, loadSkillsForPlugin, } from "../core/plugins/skills.js";
|
|
33
|
+
import { loadTenantSkills } from "../core/tenant-skills.js";
|
|
34
|
+
import { fileURLToPath } from "node:url";
|
|
35
|
+
import { ensureActiveSession, listMessagesForUserPage, loadAgentHistoryForSession, } from "./messages.js";
|
|
36
|
+
import { CompactSkippedError, compactSession } from "./compact.js";
|
|
37
|
+
import { toWire, } from "./ws-protocol.js";
|
|
38
|
+
import { cacheGet, cachePut, fitToLimit, imageFitCacheKey, } from "./image-fit.js";
|
|
39
|
+
const MAX_TURNS = 16;
|
|
40
|
+
export function attachChatHandler(opts) {
|
|
41
|
+
const { ctx, userId, socket, pluginRegistry, homeDir } = opts;
|
|
42
|
+
const send = (msg) => {
|
|
43
|
+
if (socket.readyState !== socket.OPEN)
|
|
44
|
+
return;
|
|
45
|
+
socket.send(JSON.stringify(msg));
|
|
46
|
+
};
|
|
47
|
+
send({ type: "connected", tenantId: ctx.tenantId, userId });
|
|
48
|
+
// Register this socket's send thunk so the session-inbox idle
|
|
49
|
+
// runner can broadcast a background turn's stream to every
|
|
50
|
+
// tab the user has open. unregister fires on `close` below.
|
|
51
|
+
const unregisterUserChannel = registerUserSendChannel(userId, send);
|
|
52
|
+
let aborter = null;
|
|
53
|
+
socket.on("message", (raw) => {
|
|
54
|
+
let parsed;
|
|
55
|
+
try {
|
|
56
|
+
parsed = JSON.parse(raw.toString());
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
switch (parsed.type) {
|
|
62
|
+
case "hello":
|
|
63
|
+
send({ type: "connected", tenantId: ctx.tenantId, userId });
|
|
64
|
+
return;
|
|
65
|
+
case "history": {
|
|
66
|
+
const opts = makeWireOpts(ctx);
|
|
67
|
+
const page = listMessagesForUserPage(ctx, userId, {
|
|
68
|
+
limit: parsed.limit,
|
|
69
|
+
});
|
|
70
|
+
send({
|
|
71
|
+
type: "history",
|
|
72
|
+
messages: page.messages.map((m) => toWire(m, opts)),
|
|
73
|
+
hasMore: page.hasMore,
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
case "history_more": {
|
|
78
|
+
const opts = makeWireOpts(ctx);
|
|
79
|
+
const page = listMessagesForUserPage(ctx, userId, {
|
|
80
|
+
limit: parsed.limit,
|
|
81
|
+
before: parsed.before,
|
|
82
|
+
});
|
|
83
|
+
send({
|
|
84
|
+
type: "history_page",
|
|
85
|
+
messages: page.messages.map((m) => toWire(m, opts)),
|
|
86
|
+
hasMore: page.hasMore,
|
|
87
|
+
before: parsed.before,
|
|
88
|
+
});
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
case "prompt": {
|
|
92
|
+
if (aborter)
|
|
93
|
+
aborter.abort(); // single in-flight prompt per socket
|
|
94
|
+
aborter = new AbortController();
|
|
95
|
+
// Slash-command: `/compact` runs an immediate compaction
|
|
96
|
+
// pass without sending a fresh user prompt. Recognised when
|
|
97
|
+
// the typed body is exactly the marker plus optional
|
|
98
|
+
// whitespace and (for parity with the legacy CLI) `!`.
|
|
99
|
+
const trimmed = parsed.content.trim();
|
|
100
|
+
if (trimmed === "/compact" || trimmed === "/compact!") {
|
|
101
|
+
runManualCompact({
|
|
102
|
+
ctx,
|
|
103
|
+
userId,
|
|
104
|
+
send,
|
|
105
|
+
modelId: parsed.modelId,
|
|
106
|
+
signal: aborter.signal,
|
|
107
|
+
}).catch((err) => {
|
|
108
|
+
send({
|
|
109
|
+
type: "stream_error",
|
|
110
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
runPrompt({
|
|
116
|
+
ctx,
|
|
117
|
+
userId,
|
|
118
|
+
send,
|
|
119
|
+
content: parsed.content,
|
|
120
|
+
modelId: parsed.modelId,
|
|
121
|
+
attachments: parsed.attachments,
|
|
122
|
+
signal: aborter.signal,
|
|
123
|
+
pluginRegistry,
|
|
124
|
+
homeDir,
|
|
125
|
+
}).catch((err) => {
|
|
126
|
+
send({
|
|
127
|
+
type: "stream_error",
|
|
128
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
case "abort": {
|
|
134
|
+
aborter?.abort();
|
|
135
|
+
aborter = null;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
socket.on("close", () => {
|
|
141
|
+
aborter?.abort();
|
|
142
|
+
aborter = null;
|
|
143
|
+
unregisterUserChannel();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
export async function runPrompt(args) {
|
|
147
|
+
const { ctx, userId, send, content, modelId, attachments, signal, pluginRegistry, homeDir } = args;
|
|
148
|
+
const wireOpts = makeWireOpts(ctx);
|
|
149
|
+
const repo = new SqliteSessionRepo(ctx);
|
|
150
|
+
let session = ensureActiveSession(ctx, userId);
|
|
151
|
+
// Resolve the model up front — we need imageMaxBytes / context
|
|
152
|
+
// window for both auto-compact and the LLM call below.
|
|
153
|
+
const modelInfo = (modelId ? findModel(ctx.config, modelId) : undefined) ?? getDefaultModel(ctx.config);
|
|
154
|
+
if (!modelInfo) {
|
|
155
|
+
send({
|
|
156
|
+
type: "stream_error",
|
|
157
|
+
reason: "no models configured (set models in ~/.tianshu/config.json)",
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const piModel = buildModel(modelInfo);
|
|
162
|
+
const apiKey = resolveApiKey(modelInfo);
|
|
163
|
+
const userHome = ctx.userHomeDir(userId);
|
|
164
|
+
// MCP toolsets (e.g. plugin-microsandbox's Playwright server)
|
|
165
|
+
// expose a `tools/list` only after the upstream is reachable.
|
|
166
|
+
// Plugin activation kicks off a fire-and-forget initial refresh,
|
|
167
|
+
// but the upstream often isn't ready yet (sandbox still booting,
|
|
168
|
+
// user-configured server still being saved). Without a per-turn
|
|
169
|
+
// warmup the agent never sees these tools until someone hits
|
|
170
|
+
// `/admin/mcp` to refresh by hand. Run the same opportunistic
|
|
171
|
+
// refresh the admin route does, but with a tighter deadline so
|
|
172
|
+
// we don't block a chat turn for too long when an upstream is
|
|
173
|
+
// genuinely down.
|
|
174
|
+
if (pluginRegistry) {
|
|
175
|
+
try {
|
|
176
|
+
await pluginRegistry.refreshStaleToolsets(ctx.tenantId, 1500);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// refreshStaleToolsets already swallows per-toolset errors;
|
|
180
|
+
// a thrown one would mean the registry itself faulted, which
|
|
181
|
+
// we don't want to surface as a chat failure either — the
|
|
182
|
+
// agent will simply see whatever toolset state we already
|
|
183
|
+
// had.
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const pluginTools = pluginRegistry?.toolsForTenant(ctx.tenantId) ?? [];
|
|
187
|
+
// Skill priority (later wins on the dedup key, which is the
|
|
188
|
+
// directory name for tenant skills and the contribution id for
|
|
189
|
+
// host/plugin skills): host+plugin (mirrored) → tenant scope.
|
|
190
|
+
// Tenant scope wins by design — the user can override or shadow a
|
|
191
|
+
// shipped skill by dropping a same-named directory under
|
|
192
|
+
// `_tenant/config/{skills,main/skills}/`. The mirrored copies
|
|
193
|
+
// live under `_tenant/config/skills/_host/<pid>/<id>/SKILL.md`
|
|
194
|
+
// and carry tenant-config:/// filePaths so the system prompt's
|
|
195
|
+
// <available_skills> block can advertise them in the same shape
|
|
196
|
+
// as user-authored skills.
|
|
197
|
+
const allSkills = [
|
|
198
|
+
...(pluginRegistry?.mirroredSkillsForTenant(ctx.tenantId) ?? []),
|
|
199
|
+
...loadTenantSkills({
|
|
200
|
+
tenantId: ctx.tenantId,
|
|
201
|
+
scope: { kind: "main" },
|
|
202
|
+
onFailure: (f) => console.warn(`[tenant-skills:${f.scope}] ${f.filePath}: ${f.reason}`),
|
|
203
|
+
}),
|
|
204
|
+
];
|
|
205
|
+
// Build a set of registered tool names from pluginTools' schemas.
|
|
206
|
+
// We don't yet know what `available()` will say, so we use the
|
|
207
|
+
// schema name; this slightly over-includes skills that depend on
|
|
208
|
+
// a tool that ends up hidden, but the agent simply won't reach
|
|
209
|
+
// for those. Conservative on the side of more visibility.
|
|
210
|
+
const declaredToolNames = new Set(pluginTools.map(({ tool }) => tool.schema.name));
|
|
211
|
+
const hostCaps = pluginRegistry?.hostCapabilities(ctx.tenantId) ?? emptyHostCapabilities();
|
|
212
|
+
const skills = filterSkillsForTenant(allSkills, {
|
|
213
|
+
hasTool: (n) => declaredToolNames.has(n),
|
|
214
|
+
hasCapability: (n) => hostCaps.has(n),
|
|
215
|
+
agentScope: "main",
|
|
216
|
+
});
|
|
217
|
+
// Plugin-contributed prompt fragments: short imperative
|
|
218
|
+
// sentences declared in `manifest.contributes.systemPromptFragments`,
|
|
219
|
+
// injected on every turn for every active plugin in the tenant.
|
|
220
|
+
// Workers don't get these (the agent-loop's worker path uses a
|
|
221
|
+
// separate prompt path).
|
|
222
|
+
const pluginFragments = pluginRegistry?.systemPromptFragmentsForTenant(ctx.tenantId) ?? [];
|
|
223
|
+
const toolset = await buildToolset({
|
|
224
|
+
pluginTools,
|
|
225
|
+
toolContext: {
|
|
226
|
+
tenantId: ctx.tenantId,
|
|
227
|
+
userId,
|
|
228
|
+
capabilities: hostCaps,
|
|
229
|
+
userHomeDir: userHome,
|
|
230
|
+
tenantHomeDir: homeDir ?? "",
|
|
231
|
+
// Main chat agent. Drives `tenant_config_write` boundary in
|
|
232
|
+
// the files plugin: main may write to `main/skills/` and
|
|
233
|
+
// shared `skills/`.
|
|
234
|
+
agentScope: { kind: "main" },
|
|
235
|
+
log: makeLogger(ctx.tenantId, userId, send),
|
|
236
|
+
sessionId: session.id,
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
// Convert wire attachments into:
|
|
240
|
+
// * `images` — base64 ImageContent[] for vision-capable models
|
|
241
|
+
// * `prompt prefix` — a short text note for non-image files
|
|
242
|
+
// pointing the agent at the path
|
|
243
|
+
//
|
|
244
|
+
// Non-image bytes never reach the LLM directly; the agent reads
|
|
245
|
+
// them via tools (`read_file`, or shell `pdftotext` for pdfs).
|
|
246
|
+
const { promptText: rawPromptText, images, originalAttachments } = await prepareUserInput(content, attachments, ctx.userHomeDir(userId), modelInfo);
|
|
247
|
+
// Drain the session inbox before the agent sees the user's
|
|
248
|
+
// prompt. Anything dropped here while the session was idle
|
|
249
|
+
// (e.g. a worker pool reporting task_done) is rendered as a
|
|
250
|
+
// system-note prefix above the user's text. The agent thus
|
|
251
|
+
// gets full context: "these messages arrived for you while
|
|
252
|
+
// you were idle, AND here's the next thing the user said".
|
|
253
|
+
const inboxDelivered = drainInbox(ctx, session.id);
|
|
254
|
+
const inboxPrefix = renderInboxForPrompt(inboxDelivered);
|
|
255
|
+
const promptText = inboxPrefix
|
|
256
|
+
? `${inboxPrefix}<user>\n${rawPromptText}\n</user>`
|
|
257
|
+
: rawPromptText;
|
|
258
|
+
// Build the harness session ourselves so we can keep a handle
|
|
259
|
+
// on the storage — we need to stash sibling attachments on it
|
|
260
|
+
// before the harness's user-message persistence fires, and we
|
|
261
|
+
// hand it the model's vision profile so its `getPathToRoot`
|
|
262
|
+
// reads + base64-encodes images on demand at LLM-call time.
|
|
263
|
+
const storage = new SqliteSessionStorage(ctx, session.id, {
|
|
264
|
+
imageInflate: {
|
|
265
|
+
userHome,
|
|
266
|
+
imageMaxBytes: modelInfo.imageMaxBytes,
|
|
267
|
+
supportsImages: modelInfo.supportsImages,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
const piSession = new PiSession(storage);
|
|
271
|
+
if (originalAttachments && originalAttachments.length > 0) {
|
|
272
|
+
storage.pendingUserAttachments = {
|
|
273
|
+
attachments: originalAttachments,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
void repo;
|
|
277
|
+
send({ type: "stream_start" });
|
|
278
|
+
const adapted = adaptToolset(toolset);
|
|
279
|
+
const systemPrompt = defaultSystemPrompt(ctx, userId, skills, pluginFragments);
|
|
280
|
+
dumpSystemPrompt({ ctx, role: "main", userId, systemPrompt });
|
|
281
|
+
const harness = new AgentHarness({
|
|
282
|
+
env: makeStubExecutionEnv(ctx.userHomeDir(userId)),
|
|
283
|
+
session: piSession,
|
|
284
|
+
tools: adapted.tools,
|
|
285
|
+
systemPrompt,
|
|
286
|
+
model: piModel,
|
|
287
|
+
getApiKeyAndHeaders: async () => ({ apiKey }),
|
|
288
|
+
});
|
|
289
|
+
// External abort → harness.abort()
|
|
290
|
+
const onAbort = () => void harness.abort();
|
|
291
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
292
|
+
// Register this harness in the process-local registry so the
|
|
293
|
+
// session inbox can route a live `enqueue()` through
|
|
294
|
+
// `harness.followUp(...)` instead of leaving the message stuck
|
|
295
|
+
// in `pending` until the user types again. Cleared in finally.
|
|
296
|
+
const unregisterHarness = registerActiveHarness(session.id, harness);
|
|
297
|
+
let lastAssistantRow = null;
|
|
298
|
+
let assistantTurns = 0;
|
|
299
|
+
let streamErrorSent = false;
|
|
300
|
+
// Track tool calls the agent emitted but never produced a
|
|
301
|
+
// tool_result for. Provider terminations / aborts can leave a
|
|
302
|
+
// toolCall hanging — the UI shows a perpetual spinner. We
|
|
303
|
+
// synthesise a failed tool_result for any leftover entry in
|
|
304
|
+
// the finally block so the chip resolves.
|
|
305
|
+
const outstandingToolCalls = new Map();
|
|
306
|
+
const unsubscribe = harness.subscribe((event) => {
|
|
307
|
+
const ev = event;
|
|
308
|
+
if (ev.type === "tool_execution_start") {
|
|
309
|
+
const tc = event;
|
|
310
|
+
outstandingToolCalls.set(tc.toolCallId, { name: tc.toolName });
|
|
311
|
+
}
|
|
312
|
+
else if (ev.type === "tool_execution_end") {
|
|
313
|
+
const te = event;
|
|
314
|
+
outstandingToolCalls.delete(te.toolCallId);
|
|
315
|
+
}
|
|
316
|
+
bridgeHarnessEventToWs(event, {
|
|
317
|
+
ctx,
|
|
318
|
+
session,
|
|
319
|
+
send,
|
|
320
|
+
wireOpts,
|
|
321
|
+
onAssistantPersisted: (row) => {
|
|
322
|
+
lastAssistantRow = row;
|
|
323
|
+
assistantTurns++;
|
|
324
|
+
if (assistantTurns >= MAX_TURNS) {
|
|
325
|
+
void harness.abort();
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
onStreamError: () => {
|
|
329
|
+
streamErrorSent = true;
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
try {
|
|
334
|
+
await harness.prompt(promptText, images.length > 0 ? { images } : undefined);
|
|
335
|
+
await harness.waitForIdle();
|
|
336
|
+
}
|
|
337
|
+
catch (err) {
|
|
338
|
+
if (!streamErrorSent) {
|
|
339
|
+
send({
|
|
340
|
+
type: "stream_error",
|
|
341
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
342
|
+
});
|
|
343
|
+
streamErrorSent = true;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
finally {
|
|
347
|
+
// Resolve any tool-call chip the UI is still showing as
|
|
348
|
+
// running. Provider termination after a `tool_call` event
|
|
349
|
+
// but before the matching `tool_execution_end` strands the
|
|
350
|
+
// chip in `running` state forever; emit a synthetic failed
|
|
351
|
+
// result so the bubble renders an error and the run can
|
|
352
|
+
// visually move on.
|
|
353
|
+
for (const [callId, info] of outstandingToolCalls) {
|
|
354
|
+
send({
|
|
355
|
+
type: "tool_result",
|
|
356
|
+
callId,
|
|
357
|
+
name: info.name,
|
|
358
|
+
ok: false,
|
|
359
|
+
text: streamErrorSent
|
|
360
|
+
? "Tool call interrupted by stream error."
|
|
361
|
+
: "Tool call did not return before the run ended.",
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
outstandingToolCalls.clear();
|
|
365
|
+
unsubscribe();
|
|
366
|
+
unregisterHarness();
|
|
367
|
+
signal.removeEventListener("abort", onAbort);
|
|
368
|
+
if (storage)
|
|
369
|
+
storage.pendingUserAttachments = null;
|
|
370
|
+
}
|
|
371
|
+
// Auto-compact: pi-agent-core ships compact() but no auto-trigger.
|
|
372
|
+
// After every successful turn, decide whether to fire it.
|
|
373
|
+
if (!streamErrorSent) {
|
|
374
|
+
await maybeAutoCompact({
|
|
375
|
+
session,
|
|
376
|
+
piSession,
|
|
377
|
+
harness,
|
|
378
|
+
modelInfo,
|
|
379
|
+
send,
|
|
380
|
+
onSuccessRefresh: () => {
|
|
381
|
+
// Refresh after compaction: same default page size as the
|
|
382
|
+
// initial fetch. The compacted session is what the client
|
|
383
|
+
// wants to see; we don't try to preserve the older paged-in
|
|
384
|
+
// window because compaction logically replaces it.
|
|
385
|
+
const page = listMessagesForUserPage(ctx, userId);
|
|
386
|
+
send({
|
|
387
|
+
type: "history",
|
|
388
|
+
messages: page.messages.map((m) => toWire(m, makeWireOpts(ctx))),
|
|
389
|
+
hasMore: page.hasMore,
|
|
390
|
+
});
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
// Emit stream_end so the UI re-enables the send button.
|
|
395
|
+
//
|
|
396
|
+
// Skip the persisted row when its rendered text is empty —
|
|
397
|
+
// those happen when the agent only emitted tool calls in the
|
|
398
|
+
// final turn and never said anything user-facing. Showing
|
|
399
|
+
// them produces a content-less bubble ("…") that just
|
|
400
|
+
// confuses the user; the tool result chips above already
|
|
401
|
+
// tell the story. Synthesise the placeholder branch instead
|
|
402
|
+
// so the UI re-enables the send button without rendering an
|
|
403
|
+
// empty bubble.
|
|
404
|
+
const lastWire = lastAssistantRow ? toWire(lastAssistantRow, wireOpts) : null;
|
|
405
|
+
const lastIsEmpty = !!lastWire && !hasVisibleAssistantText(lastWire);
|
|
406
|
+
if (!streamErrorSent) {
|
|
407
|
+
if (lastWire && !lastIsEmpty) {
|
|
408
|
+
send({ type: "stream_end", message: lastWire });
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
// Synthetic placeholder so the UI doesn't get stuck.
|
|
412
|
+
send({
|
|
413
|
+
type: "stream_end",
|
|
414
|
+
message: toWire({
|
|
415
|
+
id: `msg_empty_${Date.now()}`,
|
|
416
|
+
sessionId: session.id,
|
|
417
|
+
role: "assistant",
|
|
418
|
+
content: "",
|
|
419
|
+
createdAt: Date.now(),
|
|
420
|
+
}, wireOpts),
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* True iff the wire-encoded assistant message has at least one
|
|
427
|
+
* visible text segment. Tool calls / tool results don't count
|
|
428
|
+
* — they render as their own chips elsewhere; an assistant
|
|
429
|
+
* "message" with only those segments is a content-less bubble
|
|
430
|
+
* we should suppress.
|
|
431
|
+
*/
|
|
432
|
+
function hasVisibleAssistantText(m) {
|
|
433
|
+
if (m.role !== "assistant")
|
|
434
|
+
return true;
|
|
435
|
+
if (typeof m.text === "string" && m.text.trim().length > 0)
|
|
436
|
+
return true;
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Translate (text, wire-attachments) → a single text + ImageContent[]
|
|
441
|
+
* suitable for `harness.prompt(text, { images })`.
|
|
442
|
+
*
|
|
443
|
+
* * Image attachments → fitted to the model's byte budget +
|
|
444
|
+
* emitted as ImageContent[].
|
|
445
|
+
* * Non-image attachments → a one-liner prepended to the user
|
|
446
|
+
* text pointing the agent at the file path.
|
|
447
|
+
* * Vision-incapable model → every image is replaced by a
|
|
448
|
+
* [Attached image: name (no vision support)] note.
|
|
449
|
+
*/
|
|
450
|
+
async function prepareUserInput(content, attachments, userHome, modelInfo) {
|
|
451
|
+
const atts = attachments ?? [];
|
|
452
|
+
if (atts.length === 0) {
|
|
453
|
+
return { promptText: content, images: [], originalAttachments: atts };
|
|
454
|
+
}
|
|
455
|
+
const fileLines = [];
|
|
456
|
+
const images = [];
|
|
457
|
+
for (const att of atts) {
|
|
458
|
+
const isImage = att.mimeType.startsWith("image/");
|
|
459
|
+
if (!isImage) {
|
|
460
|
+
fileLines.push(`[Attached file: ${att.name ?? att.path} (${att.mimeType}) — readable at .${att.path}]`);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (!modelInfo.supportsImages) {
|
|
464
|
+
fileLines.push(`[Attached image (current model has no vision support): ${att.name ?? att.path}]`);
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
const abs = path.join(userHome, att.path.startsWith("/") ? att.path.slice(1) : att.path);
|
|
468
|
+
try {
|
|
469
|
+
const stat = fs.statSync(abs);
|
|
470
|
+
const cacheKey = imageFitCacheKey(abs, stat.mtimeMs, modelInfo.imageMaxBytes);
|
|
471
|
+
const cached = cacheGet(cacheKey);
|
|
472
|
+
let buf;
|
|
473
|
+
let mimeType;
|
|
474
|
+
if (cached) {
|
|
475
|
+
buf = cached.buf;
|
|
476
|
+
mimeType = cached.mimeType;
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
const raw = fs.readFileSync(abs);
|
|
480
|
+
const fitted = await fitToLimit(raw, att.mimeType, modelInfo.imageMaxBytes);
|
|
481
|
+
buf = fitted.buf;
|
|
482
|
+
mimeType = fitted.mimeType;
|
|
483
|
+
cachePut(cacheKey, buf, mimeType);
|
|
484
|
+
}
|
|
485
|
+
images.push({
|
|
486
|
+
type: "image",
|
|
487
|
+
data: buf.toString("base64"),
|
|
488
|
+
mimeType,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
catch (err) {
|
|
492
|
+
const reason = err?.message ?? "read failed";
|
|
493
|
+
fileLines.push(`[Attached image: ${att.name ?? att.path} — read failed: ${reason}]`);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
const prefix = fileLines.length > 0 ? fileLines.join("\n") + "\n\n" : "";
|
|
497
|
+
return {
|
|
498
|
+
promptText: prefix + content,
|
|
499
|
+
images,
|
|
500
|
+
originalAttachments: atts,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Translate one harness event into the legacy chat WS protocol.
|
|
505
|
+
* Every assistant / toolResult message that lands in the harness
|
|
506
|
+
* session is re-broadcast here so the existing UI flow keeps
|
|
507
|
+
* working unchanged.
|
|
508
|
+
*/
|
|
509
|
+
function bridgeHarnessEventToWs(event, args) {
|
|
510
|
+
const { ctx, session, send, wireOpts, onAssistantPersisted, onStreamError } = args;
|
|
511
|
+
const e = event;
|
|
512
|
+
// Pi-low-level events first (text_delta etc).
|
|
513
|
+
const lowType = event.type;
|
|
514
|
+
if (lowType === "message_update") {
|
|
515
|
+
const upd = event;
|
|
516
|
+
if (upd.assistantMessageEvent.type === "text_delta" &&
|
|
517
|
+
typeof upd.assistantMessageEvent.delta === "string") {
|
|
518
|
+
send({ type: "stream_delta", delta: upd.assistantMessageEvent.delta });
|
|
519
|
+
}
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
if (lowType === "message_end") {
|
|
523
|
+
const m = event.message;
|
|
524
|
+
if (m.role === "assistant") {
|
|
525
|
+
const row = readBackLatestMessage(ctx, session.id, "assistant");
|
|
526
|
+
if (row) {
|
|
527
|
+
// Always notify the run controller (lastAssistantRow gets
|
|
528
|
+
// tracked here) so MAX_TURNS counting and the stream_end
|
|
529
|
+
// selection in the caller stay correct, even if we
|
|
530
|
+
// suppress the wire message below.
|
|
531
|
+
onAssistantPersisted(row);
|
|
532
|
+
const wire = toWire(row, wireOpts);
|
|
533
|
+
// Suppress empty assistant messages (no user-visible
|
|
534
|
+
// text segments). They show up as bare "…" bubbles
|
|
535
|
+
// when the agent's final turn was tool-only — the tool
|
|
536
|
+
// result chips above already tell the story. The same
|
|
537
|
+
// filter is applied at stream_end below.
|
|
538
|
+
if (hasVisibleAssistantText(wire)) {
|
|
539
|
+
send({ type: "message_added", message: wire });
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
else if (m.role === "user") {
|
|
544
|
+
const row = readBackLatestMessage(ctx, session.id, "user");
|
|
545
|
+
if (row) {
|
|
546
|
+
// pi just persisted a user message. If it carries inbox
|
|
547
|
+
// markers, this is the proof we needed that the inbox
|
|
548
|
+
// followUp was actually consumed — mark those rows
|
|
549
|
+
// delivered now so they don't get redelivered as a
|
|
550
|
+
// prefix on the next user prompt. See
|
|
551
|
+
// session-inbox.ts's markDeliveredFromMessage.
|
|
552
|
+
try {
|
|
553
|
+
markDeliveredFromMessage(ctx, row.content);
|
|
554
|
+
}
|
|
555
|
+
catch (err) {
|
|
556
|
+
// eslint-disable-next-line no-console
|
|
557
|
+
console.warn("[handler] markDeliveredFromMessage failed:", err instanceof Error ? err.message : err);
|
|
558
|
+
}
|
|
559
|
+
send({ type: "message_added", message: toWire(row, wireOpts) });
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
else if (m.role === "toolResult") {
|
|
563
|
+
// SqliteSessionStorage just wrote the tool-result row;
|
|
564
|
+
// forward it to the UI so the chip materialises into a
|
|
565
|
+
// proper message in the transcript.
|
|
566
|
+
const row = readBackLatestMessage(ctx, session.id, "tool");
|
|
567
|
+
if (row) {
|
|
568
|
+
send({ type: "message_added", message: toWire(row, wireOpts) });
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
// Pi's low-level tool events: tool_execution_start fires when
|
|
574
|
+
// the harness begins running a tool, tool_execution_end after
|
|
575
|
+
// it completes. We emit the legacy tianshu chip events around
|
|
576
|
+
// them so the existing UI flow keeps working.
|
|
577
|
+
if (lowType === "tool_execution_start") {
|
|
578
|
+
const tc = event;
|
|
579
|
+
send({
|
|
580
|
+
type: "tool_call",
|
|
581
|
+
callId: tc.toolCallId,
|
|
582
|
+
name: tc.toolName,
|
|
583
|
+
arguments: tc.args ?? {},
|
|
584
|
+
});
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
if (lowType === "tool_execution_end") {
|
|
588
|
+
const te = event;
|
|
589
|
+
const blocks = te.result?.content ?? [];
|
|
590
|
+
const text = blocks
|
|
591
|
+
.map((c) => (c.type === "text" && typeof c.text === "string" ? c.text : ""))
|
|
592
|
+
.join("");
|
|
593
|
+
send({
|
|
594
|
+
type: "tool_result",
|
|
595
|
+
callId: te.toolCallId,
|
|
596
|
+
name: te.toolName,
|
|
597
|
+
ok: !te.isError,
|
|
598
|
+
text,
|
|
599
|
+
});
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
// Surface stream-level errors as the legacy stream_error so the
|
|
603
|
+
// UI handles them the same way it always has.
|
|
604
|
+
//
|
|
605
|
+
// pi-agent-core encodes LLM failures (401, rate limit, network,
|
|
606
|
+
// anything thrown by the streamFn) by setting stopReason="error"
|
|
607
|
+
// + errorMessage on the final AssistantMessage — then it emits
|
|
608
|
+
// a normal `agent_end`. If we don't introspect agent_end, the
|
|
609
|
+
// server happily reports stream_end with an empty assistant body,
|
|
610
|
+
// the UI re-enables the send button, and the user can't tell
|
|
611
|
+
// why nothing came back. Caught 2026-06-21 on a tenant whose
|
|
612
|
+
// qwen apiKey was placeholder text (`sk-4e8…581e`); dashscope
|
|
613
|
+
// 401'd, pi flagged the assistant with stopReason="error", server
|
|
614
|
+
// returned a silent empty bubble.
|
|
615
|
+
if (lowType === "agent_end") {
|
|
616
|
+
const messages = event.messages;
|
|
617
|
+
const last = messages[messages.length - 1];
|
|
618
|
+
if (last &&
|
|
619
|
+
last.role === "assistant" &&
|
|
620
|
+
(last.stopReason === "error" || last.stopReason === "aborted")) {
|
|
621
|
+
const reason = last.errorMessage ??
|
|
622
|
+
`assistant turn ended with stopReason=${last.stopReason}`;
|
|
623
|
+
send({ type: "stream_error", reason });
|
|
624
|
+
onStreamError();
|
|
625
|
+
}
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
if (lowType === "settled") {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
/** Read the most recently persisted message of a given role from
|
|
633
|
+
* `messages`. Used by the WS bridge to pick up the row the harness
|
|
634
|
+
* just wrote (so we can `toWire` it for the client). */
|
|
635
|
+
function readBackLatestMessage(ctx, sessionId, role) {
|
|
636
|
+
const row = ctx.db
|
|
637
|
+
.prepare(`SELECT id, session_id, role, content, created_at
|
|
638
|
+
FROM messages
|
|
639
|
+
WHERE session_id = ? AND role = ? AND entry_type = 'message'
|
|
640
|
+
ORDER BY created_at DESC, rowid DESC
|
|
641
|
+
LIMIT 1`)
|
|
642
|
+
.get(sessionId, role);
|
|
643
|
+
if (!row)
|
|
644
|
+
return null;
|
|
645
|
+
return {
|
|
646
|
+
id: row.id,
|
|
647
|
+
sessionId: row.session_id,
|
|
648
|
+
role: row.role,
|
|
649
|
+
content: row.content,
|
|
650
|
+
createdAt: row.created_at,
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
/** Build a `ToWireOpts` bound to the current tenant config. The
|
|
654
|
+
* resolver lets `toWire` stamp `meta.contextWindow` on every
|
|
655
|
+
* assistant row without each caller having to do the lookup. */
|
|
656
|
+
function makeWireOpts(ctx) {
|
|
657
|
+
return {
|
|
658
|
+
contextWindowFor: (modelId) => {
|
|
659
|
+
const info = findModel(ctx.config, modelId);
|
|
660
|
+
return info?.contextWindow;
|
|
661
|
+
},
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Pure decision function: given a branch (the entries pi's
|
|
666
|
+
* harness sees as the active turn history) and the model's
|
|
667
|
+
* context window, return whether the next turn should run
|
|
668
|
+
* compaction first.
|
|
669
|
+
*
|
|
670
|
+
* Exported for tests; runtime callers go through
|
|
671
|
+
* `maybeAutoCompact` which folds storage + harness in.
|
|
672
|
+
*/
|
|
673
|
+
export function shouldCompactBranch(input) {
|
|
674
|
+
const settings = input.settings ?? DEFAULT_COMPACTION_SETTINGS;
|
|
675
|
+
if (!settings.enabled)
|
|
676
|
+
return false;
|
|
677
|
+
if (!input.contextWindow || input.contextWindow <= 0)
|
|
678
|
+
return false;
|
|
679
|
+
const messages = [];
|
|
680
|
+
for (const entry of input.branch) {
|
|
681
|
+
if (entry.type === "message")
|
|
682
|
+
messages.push(entry.message);
|
|
683
|
+
}
|
|
684
|
+
if (messages.length === 0)
|
|
685
|
+
return false;
|
|
686
|
+
const usage = estimateContextTokens(messages);
|
|
687
|
+
return shouldCompact(usage.tokens, input.contextWindow, settings);
|
|
688
|
+
}
|
|
689
|
+
export async function tryAutoCompact(args) {
|
|
690
|
+
const { piSession, harness, contextWindow } = args;
|
|
691
|
+
let branch;
|
|
692
|
+
try {
|
|
693
|
+
branch = await piSession.getBranch();
|
|
694
|
+
}
|
|
695
|
+
catch (err) {
|
|
696
|
+
console.warn(`[chat] auto-compact decision failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
697
|
+
return { compacted: false };
|
|
698
|
+
}
|
|
699
|
+
if (!shouldCompactBranch({ branch, contextWindow })) {
|
|
700
|
+
return { compacted: false };
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
const result = await harness.compact();
|
|
704
|
+
return { compacted: true, tokensBefore: result.tokensBefore };
|
|
705
|
+
}
|
|
706
|
+
catch (err) {
|
|
707
|
+
return {
|
|
708
|
+
compacted: false,
|
|
709
|
+
error: err instanceof Error ? err.message : String(err),
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
async function maybeAutoCompact(args) {
|
|
714
|
+
const { session, piSession, harness, modelInfo, send, onSuccessRefresh } = args;
|
|
715
|
+
const decision = await tryAutoCompact({
|
|
716
|
+
piSession,
|
|
717
|
+
harness,
|
|
718
|
+
contextWindow: modelInfo.contextWindow,
|
|
719
|
+
});
|
|
720
|
+
if (decision.error) {
|
|
721
|
+
// Auto-compact failure on the chat path: surface as a
|
|
722
|
+
// stream_error so the user knows next turn may be expensive.
|
|
723
|
+
send({
|
|
724
|
+
type: "stream_error",
|
|
725
|
+
reason: `auto-compact failed: ${decision.error} (continuing without compact)`,
|
|
726
|
+
});
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
if (!decision.compacted)
|
|
730
|
+
return;
|
|
731
|
+
send({
|
|
732
|
+
type: "history_compacted",
|
|
733
|
+
reason: "auto",
|
|
734
|
+
// Old protocol carried oldSessionId/newSessionId because
|
|
735
|
+
// the legacy compactSession forked. pi's compact() writes
|
|
736
|
+
// a compaction entry into the SAME session — no fork — so
|
|
737
|
+
// both ids point at the current one.
|
|
738
|
+
oldSessionId: session.id,
|
|
739
|
+
newSessionId: session.id,
|
|
740
|
+
// Pi's compact() doesn't tell us how many entries it
|
|
741
|
+
// summarised / kept. The UI uses these counts for a small
|
|
742
|
+
// "📌 N messages compressed" badge; we leave them at 0
|
|
743
|
+
// until pi exposes the figures.
|
|
744
|
+
summarisedCount: 0,
|
|
745
|
+
keptCount: 0,
|
|
746
|
+
durationMs: 0,
|
|
747
|
+
tokensBefore: decision.tokensBefore,
|
|
748
|
+
});
|
|
749
|
+
onSuccessRefresh();
|
|
750
|
+
}
|
|
751
|
+
async function runManualCompact(args) {
|
|
752
|
+
const { ctx, userId, send, modelId, signal } = args;
|
|
753
|
+
const session = ensureActiveSession(ctx, userId);
|
|
754
|
+
const modelInfo = (modelId ? findModel(ctx.config, modelId) : undefined) ??
|
|
755
|
+
getDefaultModel(ctx.config);
|
|
756
|
+
if (!modelInfo) {
|
|
757
|
+
send({
|
|
758
|
+
type: "stream_error",
|
|
759
|
+
reason: "no models configured",
|
|
760
|
+
});
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
const { messages, rows } = loadAgentHistoryForSession(ctx, session.id, {
|
|
764
|
+
api: modelInfo.api,
|
|
765
|
+
provider: modelInfo.providerId,
|
|
766
|
+
model: modelInfo.modelId,
|
|
767
|
+
});
|
|
768
|
+
if (messages.length === 0) {
|
|
769
|
+
send({
|
|
770
|
+
type: "stream_error",
|
|
771
|
+
reason: "nothing to compact (no messages yet)",
|
|
772
|
+
});
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
try {
|
|
776
|
+
const result = await compactSession({
|
|
777
|
+
ctx,
|
|
778
|
+
userId,
|
|
779
|
+
oldSession: session,
|
|
780
|
+
pi: messages,
|
|
781
|
+
rows,
|
|
782
|
+
modelInfo,
|
|
783
|
+
signal,
|
|
784
|
+
});
|
|
785
|
+
send({
|
|
786
|
+
type: "history_compacted",
|
|
787
|
+
reason: "manual",
|
|
788
|
+
oldSessionId: result.oldSessionId,
|
|
789
|
+
newSessionId: result.newSession.id,
|
|
790
|
+
summarisedCount: result.summarisedCount,
|
|
791
|
+
keptCount: result.keptCount,
|
|
792
|
+
durationMs: result.durationMs,
|
|
793
|
+
});
|
|
794
|
+
// Push a refreshed history so the UI swaps to the new session
|
|
795
|
+
// immediately (the fork ack + summary stub plus any kept tail).
|
|
796
|
+
const page = listMessagesForUserPage(ctx, userId);
|
|
797
|
+
send({
|
|
798
|
+
type: "history",
|
|
799
|
+
messages: page.messages.map((m) => toWire(m, makeWireOpts(ctx))),
|
|
800
|
+
hasMore: page.hasMore,
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
catch (err) {
|
|
804
|
+
if (err instanceof CompactSkippedError) {
|
|
805
|
+
send({ type: "stream_error", reason: `compact skipped: ${err.message}` });
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
send({
|
|
809
|
+
type: "stream_error",
|
|
810
|
+
reason: `compact failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
export function defaultSystemPrompt(ctx, userId, skills = [], pluginFragments = []) {
|
|
815
|
+
const brand = ctx.config.branding?.name ?? "Tianshu";
|
|
816
|
+
const lines = [
|
|
817
|
+
`You are ${brand}, an open-source AI assistant.`,
|
|
818
|
+
`Tenant: "${ctx.tenantId}". User: "${userId}".`,
|
|
819
|
+
];
|
|
820
|
+
// Workspace layout / directory conventions / file-reference
|
|
821
|
+
// rules used to live here as a host-hardcoded block. Per
|
|
822
|
+
// ADR-0006 they now belong to the `files` plugin's
|
|
823
|
+
// `manifest.contributes.systemPromptFragments` and reach the
|
|
824
|
+
// prompt via `formatPluginPromptFragments(pluginFragments)`
|
|
825
|
+
// below — same path as every other plugin's guidance, and the
|
|
826
|
+
// same path workers already take. Disabling the `files` plugin
|
|
827
|
+
// cleanly drops its guidance from the prompt.
|
|
828
|
+
//
|
|
829
|
+
// The host stays plugin-agnostic, and main + worker prompts
|
|
830
|
+
// reach symmetric layout text without the host having to inject
|
|
831
|
+
// a separate workspace block on each side.
|
|
832
|
+
// Execution Bias — host-level behaviour rules that shape every
|
|
833
|
+
// turn, regardless of which plugins are loaded. Borrowed from
|
|
834
|
+
// OpenClaw's main prompt because the failure modes it prevents
|
|
835
|
+
// ("finish with a plan/promise instead of doing the work",
|
|
836
|
+
// "weak tool result → give up rather than vary the query")
|
|
837
|
+
// matched real stalls we saw on long task runs (PR #141
|
|
838
|
+
// workboard tasks ending without task_complete being a typical
|
|
839
|
+
// case). Phrasing kept tight on purpose: the LLM only needs the
|
|
840
|
+
// rule, not a long argument for it.
|
|
841
|
+
lines.push(``, formatExecutionBiasBlock());
|
|
842
|
+
// Workspace context files. Each is optional; missing files emit
|
|
843
|
+
// nothing. We inject content (not paths) so the agent has them
|
|
844
|
+
// in context without having to read_file first.
|
|
845
|
+
//
|
|
846
|
+
// Layout:
|
|
847
|
+
// _tenant/AGENTS.md — tenant working agreements (main agent)
|
|
848
|
+
// _tenant/SOUL.md — main agent persona
|
|
849
|
+
// _tenant/MEMORY.md — tenant long-term memory
|
|
850
|
+
// users/<userId>/USER.md — per-user preferences
|
|
851
|
+
//
|
|
852
|
+
// Files larger than the per-file cap get a head + tail snippet
|
|
853
|
+
// with a [… truncated …] marker so a runaway log can't blow the
|
|
854
|
+
// prompt budget.
|
|
855
|
+
const userHomeDir = ctx.userHomeDir(userId);
|
|
856
|
+
const ctxBlock = formatMainAgentContextBlock(ctx.workspaceDir, userHomeDir);
|
|
857
|
+
if (ctxBlock)
|
|
858
|
+
lines.push("", ctxBlock);
|
|
859
|
+
// Plugin guidance + skills first; the User Profile rule lands
|
|
860
|
+
// last on purpose because it overrides the "reply concisely"
|
|
861
|
+
// / "delegate to a worker" defaults on the very first turn
|
|
862
|
+
// when USER.md is still scaffold.
|
|
863
|
+
lines.push(``, `Reply concisely. When you make changes, briefly say what you changed.`);
|
|
864
|
+
const fragmentBlock = formatPluginPromptFragments(pluginFragments);
|
|
865
|
+
if (fragmentBlock)
|
|
866
|
+
lines.push("", fragmentBlock);
|
|
867
|
+
const skillBlock = formatAvailableSkillsBlock(skills);
|
|
868
|
+
if (skillBlock)
|
|
869
|
+
lines.push("", skillBlock);
|
|
870
|
+
// User onboarding rule — placed last so it wins recency-bias
|
|
871
|
+
// over the brevity / delegate-to-worker rules above. Without
|
|
872
|
+
// this position the LLM responds to a one-word "hi" by replying
|
|
873
|
+
// "hi" back instead of capturing the user's profile.
|
|
874
|
+
const hasUserFile = userMdExists(userHomeDir);
|
|
875
|
+
lines.push(``, formatUserOnboardingBlock(hasUserFile));
|
|
876
|
+
// Final pass: bind `<self>` / `<userId>` placeholders that
|
|
877
|
+
// appear anywhere in the assembled prompt (manifest fragments,
|
|
878
|
+
// tool descriptions, context-block labels, our own onboarding
|
|
879
|
+
// text) to the caller's actual userId. Plugin authors can't
|
|
880
|
+
// know the runtime value, so they ship the placeholder; we
|
|
881
|
+
// substitute here. Without this the LLM has been observed to
|
|
882
|
+
// hallucinate a userId (`user1`, `user3`, `user_x`) and burn a
|
|
883
|
+
// run on a path that doesn't exist.
|
|
884
|
+
return substituteUserIdPlaceholders(lines.join("\n"), userId);
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Whether `users/<self>/USER.md` already exists for the caller.
|
|
888
|
+
* Wraps the same fs check the context block uses, but exported
|
|
889
|
+
* separately so the onboarding prompt can branch its wording
|
|
890
|
+
* without re-reading the file content.
|
|
891
|
+
*/
|
|
892
|
+
function userMdExists(userHomeDir) {
|
|
893
|
+
try {
|
|
894
|
+
const p = path.join(userHomeDir, "USER.md");
|
|
895
|
+
return fs.existsSync(p) && fs.statSync(p).size > 0;
|
|
896
|
+
}
|
|
897
|
+
catch {
|
|
898
|
+
return false;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* User onboarding block. Tells main agents to actively curate the
|
|
903
|
+
* per-user USER.md — ask before going off-script, then write what
|
|
904
|
+
* was learnt back so future runs start with concrete preferences.
|
|
905
|
+
*
|
|
906
|
+
* Branches on whether USER.md exists today. The cold-start wording
|
|
907
|
+
* is more proactive ("propose to start one"); the populated
|
|
908
|
+
* wording skips the proposal step and only nudges on missing /
|
|
909
|
+
* stale facts. Both versions are short — the LLM doesn't need a
|
|
910
|
+
* lecture, just the rule + the file path to write to.
|
|
911
|
+
*/
|
|
912
|
+
function formatUserOnboardingBlock(userMdPresent) {
|
|
913
|
+
// Same prompt regardless of whether the file exists — the LLM
|
|
914
|
+
// makes the call by inspecting the Workspace Context block above.
|
|
915
|
+
// (We tried branching on `userMdExists` but a USER.md that's
|
|
916
|
+
// just the empty template scaffolding got treated as "populated"
|
|
917
|
+
// and the cold-start questions never fired. Pushing the
|
|
918
|
+
// "populated vs scaffold" judgement into the LLM is more robust
|
|
919
|
+
// than parsing markdown templates here.)
|
|
920
|
+
void userMdPresent;
|
|
921
|
+
return [
|
|
922
|
+
`## User Profile (USER.md) — read this first`,
|
|
923
|
+
`Look at \`### users/<self>/USER.md\` in the Workspace Context block above and decide right now whether it's POPULATED or a SCAFFOLD.`,
|
|
924
|
+
`- POPULATED = real concrete entries (real name, the user's actual projects, communication preferences they've stated, etc.)`,
|
|
925
|
+
`- SCAFFOLD = mostly headings + italics hints + empty form fields like \`**Name:**\` / \`**Pronouns:**\` / a single seeded value (e.g. a default time zone) with everything else blank.`,
|
|
926
|
+
`On a fresh conversation where USER.md is missing OR a scaffold:`,
|
|
927
|
+
`1. Even if the user just says "hi", do NOT just reply hi back. First proactively ask 3-5 short questions to fill USER.md (preferred name, current projects, communication style, anything that should never be forgotten). Keep it conversational, not a form.`,
|
|
928
|
+
`2. When they answer, immediately \`write_file({ path: "USER.md", content: ... })\` (relative path resolves to their workspace home) with what you learnt, plus a one-line ack like "saved that to your profile".`,
|
|
929
|
+
`3. If they explicitly decline, drop it for this run — don't re-ask the same session.`,
|
|
930
|
+
`On a populated USER.md: don't ask the intro questions again. Just keep it accurate during normal work — when a durable new fact surfaces, \`edit_file\` it in. Fix stale entries when contradicted. Don't announce these edits unless they're material.`,
|
|
931
|
+
`This rule wins over any "reply concisely" or "delegate first" guidance above — first-time profile capture is more valuable than a short hi.`,
|
|
932
|
+
].join("\n");
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Host-level Execution Bias block. Exported so the worker
|
|
936
|
+
* agent-loop path (which builds its own systemPrompt by
|
|
937
|
+
* concatenating SOUL + fragments + skills, bypassing
|
|
938
|
+
* defaultSystemPrompt) can include the same rules without copying
|
|
939
|
+
* the strings.
|
|
940
|
+
*/
|
|
941
|
+
export function formatExecutionBiasBlock() {
|
|
942
|
+
return [
|
|
943
|
+
`## Execution Bias`,
|
|
944
|
+
`- Actionable request: act in this turn.`,
|
|
945
|
+
`- Non-final turn: use tools to advance, or ask for the one missing decision that blocks safe progress.`,
|
|
946
|
+
`- Continue until done or genuinely blocked; do not finish with a plan/promise when tools can move it forward.`,
|
|
947
|
+
`- Weak/empty tool result: vary query, path, command, or source before concluding.`,
|
|
948
|
+
`- Mutable facts need live checks: files, git, clocks, versions, services, processes, package state.`,
|
|
949
|
+
`- Final answer needs evidence: test/build/lint, screenshot, inspection, tool output, or a named blocker.`,
|
|
950
|
+
`- Longer work: brief progress update, then keep going; use background work or sub-agents when they fit.`,
|
|
951
|
+
].join("\n");
|
|
952
|
+
}
|
|
953
|
+
// Per-file cap (in bytes). Files bigger than this get truncated
|
|
954
|
+
// with a head + tail snippet so the prompt stays bounded even
|
|
955
|
+
// when AGENTS.md / SOUL.md / MEMORY.md grow into multi-page docs.
|
|
956
|
+
const WORKSPACE_FILE_HEAD_BYTES = 4_000;
|
|
957
|
+
const WORKSPACE_FILE_TAIL_BYTES = 1_000;
|
|
958
|
+
const WORKSPACE_FILE_FULL_CAP_BYTES = 6_000;
|
|
959
|
+
/**
|
|
960
|
+
* Read a workspace file from `userHome`, returning its (possibly
|
|
961
|
+
* truncated) content or null when the file doesn't exist or is
|
|
962
|
+
* unreadable. We swallow read errors deliberately — missing files
|
|
963
|
+
* are the steady state and an unreadable file should never break
|
|
964
|
+
* prompt assembly.
|
|
965
|
+
*/
|
|
966
|
+
function readWorkspaceFile(filePath) {
|
|
967
|
+
try {
|
|
968
|
+
if (!fs.existsSync(filePath))
|
|
969
|
+
return null;
|
|
970
|
+
const stat = fs.statSync(filePath);
|
|
971
|
+
if (!stat.isFile() || stat.size === 0)
|
|
972
|
+
return null;
|
|
973
|
+
if (stat.size <= WORKSPACE_FILE_FULL_CAP_BYTES) {
|
|
974
|
+
return fs.readFileSync(filePath, "utf8");
|
|
975
|
+
}
|
|
976
|
+
// Big file: head + tail.
|
|
977
|
+
const fd = fs.openSync(filePath, "r");
|
|
978
|
+
try {
|
|
979
|
+
const headBuf = Buffer.alloc(WORKSPACE_FILE_HEAD_BYTES);
|
|
980
|
+
fs.readSync(fd, headBuf, 0, headBuf.length, 0);
|
|
981
|
+
const tailBuf = Buffer.alloc(WORKSPACE_FILE_TAIL_BYTES);
|
|
982
|
+
fs.readSync(fd, tailBuf, 0, tailBuf.length, Math.max(0, stat.size - tailBuf.length));
|
|
983
|
+
const omitted = stat.size - headBuf.length - tailBuf.length;
|
|
984
|
+
return [
|
|
985
|
+
headBuf.toString("utf8"),
|
|
986
|
+
``,
|
|
987
|
+
`[… ${omitted} bytes truncated …]`,
|
|
988
|
+
``,
|
|
989
|
+
tailBuf.toString("utf8"),
|
|
990
|
+
].join("\n");
|
|
991
|
+
}
|
|
992
|
+
finally {
|
|
993
|
+
fs.closeSync(fd);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
catch {
|
|
997
|
+
return null;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Render a Workspace Context section from a list of files. Each
|
|
1002
|
+
* present file becomes a `### <label>` block so the agent can
|
|
1003
|
+
* attribute statements ("per `_tenant/AGENTS.md` the team
|
|
1004
|
+
* prefers X"). Returns an empty string when none of the files
|
|
1005
|
+
* exist on disk.
|
|
1006
|
+
*/
|
|
1007
|
+
function renderContextBlock(specs) {
|
|
1008
|
+
const sections = [];
|
|
1009
|
+
for (const spec of specs) {
|
|
1010
|
+
const content = readWorkspaceFile(spec.absPath);
|
|
1011
|
+
if (content === null)
|
|
1012
|
+
continue;
|
|
1013
|
+
sections.push(`### ${spec.label}`, content.trimEnd());
|
|
1014
|
+
}
|
|
1015
|
+
if (sections.length === 0)
|
|
1016
|
+
return "";
|
|
1017
|
+
return [`## Workspace Context`, ``, ...sections].join("\n");
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Main-agent context: tenant-shared working files plus the
|
|
1021
|
+
* caller's per-user USER.md. SOUL / MEMORY / AGENTS live at the
|
|
1022
|
+
* tenant root because they're team-wide; USER.md is the only
|
|
1023
|
+
* per-user file because it captures preferences that don't
|
|
1024
|
+
* generalise.
|
|
1025
|
+
*/
|
|
1026
|
+
export function formatMainAgentContextBlock(workspaceDir, userHome) {
|
|
1027
|
+
const tenantRoot = path.join(workspaceDir, "_tenant");
|
|
1028
|
+
return renderContextBlock([
|
|
1029
|
+
{ absPath: path.join(tenantRoot, "AGENTS.md"), label: "_tenant/AGENTS.md" },
|
|
1030
|
+
{ absPath: path.join(tenantRoot, "SOUL.md"), label: "_tenant/SOUL.md" },
|
|
1031
|
+
{ absPath: path.join(tenantRoot, "MEMORY.md"), label: "_tenant/MEMORY.md" },
|
|
1032
|
+
{ absPath: path.join(userHome, "USER.md"), label: "users/<self>/USER.md" },
|
|
1033
|
+
]);
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Worker-agent context: the worker's own bundle (AGENTS.md /
|
|
1037
|
+
* MEMORY.md — SOUL.md is already injected upstream via
|
|
1038
|
+
* req.systemPrompt) plus the caller's USER.md. Workers don't
|
|
1039
|
+
* read the tenant-shared SOUL/AGENTS/MEMORY because each worker
|
|
1040
|
+
* has its own personality + own long-term notes scoped to its
|
|
1041
|
+
* specialisation.
|
|
1042
|
+
*/
|
|
1043
|
+
export function formatWorkerAgentContextBlock(workspaceDir, userHome, workerSlug) {
|
|
1044
|
+
const bundleRoot = path.join(workspaceDir, "_tenant", "config", "workers", workerSlug);
|
|
1045
|
+
return renderContextBlock([
|
|
1046
|
+
{
|
|
1047
|
+
absPath: path.join(bundleRoot, "AGENTS.md"),
|
|
1048
|
+
label: `_tenant/config/workers/${workerSlug}/AGENTS.md`,
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
absPath: path.join(bundleRoot, "MEMORY.md"),
|
|
1052
|
+
label: `_tenant/config/workers/${workerSlug}/MEMORY.md`,
|
|
1053
|
+
},
|
|
1054
|
+
{ absPath: path.join(userHome, "USER.md"), label: "users/<self>/USER.md" },
|
|
1055
|
+
]);
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Backwards-compatible thin wrapper. The previous shape pointed
|
|
1059
|
+
* to user home only; kept as an alias for tests / external
|
|
1060
|
+
* callers but new code should use formatMainAgentContextBlock.
|
|
1061
|
+
*/
|
|
1062
|
+
export function formatWorkspaceContextBlock(userHome) {
|
|
1063
|
+
return renderContextBlock([
|
|
1064
|
+
{ absPath: path.join(userHome, "AGENTS.md"), label: "AGENTS.md" },
|
|
1065
|
+
{ absPath: path.join(userHome, "SOUL.md"), label: "SOUL.md" },
|
|
1066
|
+
{ absPath: path.join(userHome, "USER.md"), label: "USER.md" },
|
|
1067
|
+
]);
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Replace `<self>` and `<userId>` placeholders with the caller's
|
|
1071
|
+
* concrete userId throughout an assembled system prompt.
|
|
1072
|
+
*
|
|
1073
|
+
* Plugin manifests + tool descriptions write paths like
|
|
1074
|
+
* `/workspace/users/<self>/...` because the plugin author can't
|
|
1075
|
+
* know the runtime userId. Without substitution the LLM sees a
|
|
1076
|
+
* literal `<self>` and either invents a userId (we caught
|
|
1077
|
+
* `user1` / `user3` / `user_x` in production) or just guesses
|
|
1078
|
+
* wrong. Substituting at the very end of prompt assembly — after
|
|
1079
|
+
* SOUL, plugin fragments, context block, skills are all stitched
|
|
1080
|
+
* together — means every appearance of these placeholders
|
|
1081
|
+
* resolves to the right value, regardless of which layer wrote
|
|
1082
|
+
* it.
|
|
1083
|
+
*
|
|
1084
|
+
* Idempotent and safe to call on prompts that don't contain
|
|
1085
|
+
* either placeholder.
|
|
1086
|
+
*/
|
|
1087
|
+
export function substituteUserIdPlaceholders(prompt, userId) {
|
|
1088
|
+
if (!userId)
|
|
1089
|
+
return prompt;
|
|
1090
|
+
return prompt
|
|
1091
|
+
.replace(/<self>/g, userId)
|
|
1092
|
+
.replace(/<userId>/g, userId);
|
|
1093
|
+
}
|
|
1094
|
+
/** Render plugin-contributed system-prompt fragments. Grouped by
|
|
1095
|
+
* plugin so the agent sees one section per plugin (workboard
|
|
1096
|
+
* rules in one block, microsandbox rules in another, etc), and
|
|
1097
|
+
* so debugging prompts is straightforward ("this guidance came
|
|
1098
|
+
* from plugin X"). Returns an empty string when no fragments
|
|
1099
|
+
* are contributed. */
|
|
1100
|
+
export function formatPluginPromptFragments(fragments) {
|
|
1101
|
+
if (fragments.length === 0)
|
|
1102
|
+
return "";
|
|
1103
|
+
const byPlugin = new Map();
|
|
1104
|
+
for (const f of fragments) {
|
|
1105
|
+
const slot = byPlugin.get(f.pluginId);
|
|
1106
|
+
if (slot) {
|
|
1107
|
+
slot.texts.push(f.text);
|
|
1108
|
+
}
|
|
1109
|
+
else {
|
|
1110
|
+
byPlugin.set(f.pluginId, {
|
|
1111
|
+
displayName: f.pluginDisplayName,
|
|
1112
|
+
texts: [f.text],
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
const lines = ["## Plugin guidance"];
|
|
1117
|
+
for (const [pid, slot] of byPlugin) {
|
|
1118
|
+
lines.push(``, `### ${slot.displayName} (${pid})`);
|
|
1119
|
+
for (const t of slot.texts) {
|
|
1120
|
+
lines.push(t.trim());
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return lines.join("\n");
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Render the `<available_skills>` block that's appended to every
|
|
1127
|
+
* system prompt — the host default prompt for the main chat agent,
|
|
1128
|
+
* AND any custom worker prompt coming from `worker_agents.system_prompt`.
|
|
1129
|
+
*
|
|
1130
|
+
* Worker LLMs need this just as badly as the main agent: without
|
|
1131
|
+
* it they only see plugin-shipped skills via `tenant_config_list`,
|
|
1132
|
+
* not their per-tenant ones. Workers ship a kind-specific
|
|
1133
|
+
* `system_prompt` in the worker_agents table, and the agent-loop
|
|
1134
|
+
* bypasses `defaultSystemPrompt` when that's set; so we expose the
|
|
1135
|
+
* skill block as a reusable helper and the loop appends it after
|
|
1136
|
+
* the kind-specific prompt.
|
|
1137
|
+
*
|
|
1138
|
+
* Returns "" when the skills list is empty so callers can drop the
|
|
1139
|
+
* block entirely (no leading blank lines, no half-empty XML).
|
|
1140
|
+
*/
|
|
1141
|
+
export function formatAvailableSkillsBlock(skills) {
|
|
1142
|
+
if (skills.length === 0)
|
|
1143
|
+
return "";
|
|
1144
|
+
const lines = [
|
|
1145
|
+
`## Skills`,
|
|
1146
|
+
`Scan <available_skills>. If one clearly applies, read its SKILL.md at the exact <location> with \`tenant_config_read\`, then follow it. All skill locations are tenant-config:/// URIs — host / plugin skills are mirrored into the tenant config tree at boot, so one tool reads them all.`,
|
|
1147
|
+
`If several apply, choose the most specific. If none clearly apply, read none.`,
|
|
1148
|
+
`One skill up front max. Never guess/fabricate skill paths.`,
|
|
1149
|
+
`Skill bundles may ship sibling files (\`scripts/\`, \`references/\`, \`assets/\`) next to SKILL.md — those still go through the regular file tools (\`read_file\` for workspace paths, \`tenant_config_read\` for tenant-config paths) using the relative paths SKILL.md mentions.`,
|
|
1150
|
+
``,
|
|
1151
|
+
`<available_skills>`,
|
|
1152
|
+
];
|
|
1153
|
+
for (const skill of skills) {
|
|
1154
|
+
lines.push(` <skill>`, ` <name>${skill.name}</name>`, ` <description>${skill.description}</description>`, ` <location>${skillLocationUri(skill)}</location>`, ` </skill>`);
|
|
1155
|
+
}
|
|
1156
|
+
lines.push(`</available_skills>`);
|
|
1157
|
+
return lines.join("\n");
|
|
1158
|
+
}
|
|
1159
|
+
/** Build the location URI we expose to the agent for a skill.
|
|
1160
|
+
*
|
|
1161
|
+
* - Tenant skills (loaded via `loadTenantSkills`) get a
|
|
1162
|
+
* `tenant-config:///...` URI rooted at `_tenant/config/`.
|
|
1163
|
+
* - Host + plugin skills (read-only, shipped on disk under host
|
|
1164
|
+
* or plugin dirs) fall back to their absolute filePath — the
|
|
1165
|
+
* agent can't read them anyway through `tenant_config_read`,
|
|
1166
|
+
* but the URI gives it a stable identifier to mention.
|
|
1167
|
+
*/
|
|
1168
|
+
function skillLocationUri(skill) {
|
|
1169
|
+
// Every skill that lives under a tenant config tree — user-
|
|
1170
|
+
// authored, plugin-mirrored, host-mirrored — emits a portable
|
|
1171
|
+
// `tenant-config:///<rest>` URI. The pluginId no longer
|
|
1172
|
+
// matters here; the mirror layer in the registry stamps
|
|
1173
|
+
// plugin/host skills with `_tenant/config/skills/_host/...`
|
|
1174
|
+
// filePaths just like user skills.
|
|
1175
|
+
const idx = skill.filePath.indexOf("_tenant/config/");
|
|
1176
|
+
if (idx >= 0) {
|
|
1177
|
+
const rel = skill.filePath
|
|
1178
|
+
.slice(idx + "_tenant/config/".length)
|
|
1179
|
+
.replace(/\\/g, "/");
|
|
1180
|
+
return `tenant-config:///${rel}`;
|
|
1181
|
+
}
|
|
1182
|
+
// Fall-through: a skill whose filePath isn't under _tenant/
|
|
1183
|
+
// config/. This shouldn't happen post-mirror; if it does, we'd
|
|
1184
|
+
// rather surface the absolute path than silently hide the
|
|
1185
|
+
// skill, so the agent can at least diagnose the gap.
|
|
1186
|
+
return skill.filePath;
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Load skills shipped with the host repo (under `<repoRoot>/skills/`).
|
|
1190
|
+
* These are surfaced to every tenant alongside plugin-contributed
|
|
1191
|
+
* skills. Any with `when:` predicates are filtered later by
|
|
1192
|
+
* `filterSkillsForTenant`.
|
|
1193
|
+
*
|
|
1194
|
+
* Result is cached per process — host skills are read-only at
|
|
1195
|
+
* runtime, no need to re-stat per request.
|
|
1196
|
+
*/
|
|
1197
|
+
let hostSkillsCache = null;
|
|
1198
|
+
export function loadHostSkills() {
|
|
1199
|
+
if (hostSkillsCache)
|
|
1200
|
+
return hostSkillsCache;
|
|
1201
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
1202
|
+
// dist/chat/handler.js → ../../../skills, source/chat/handler.ts
|
|
1203
|
+
// → ../../../skills. Either way, three levels up gets us to the
|
|
1204
|
+
// server package root, which contains a `skills/` dir at build
|
|
1205
|
+
// time. We override via TIANSHU_HOST_SKILLS_DIR for tests.
|
|
1206
|
+
const fromEnv = process.env.TIANSHU_HOST_SKILLS_DIR;
|
|
1207
|
+
const skillsDir = fromEnv
|
|
1208
|
+
? path.resolve(fromEnv)
|
|
1209
|
+
: path.resolve(here, "..", "..", "skills");
|
|
1210
|
+
if (!fs.existsSync(skillsDir)) {
|
|
1211
|
+
hostSkillsCache = [];
|
|
1212
|
+
return hostSkillsCache;
|
|
1213
|
+
}
|
|
1214
|
+
// Treat host skills as if they came from a synthetic `tianshu`
|
|
1215
|
+
// plugin so log lines and plugin-id-derived names stay readable.
|
|
1216
|
+
const contributions = fs
|
|
1217
|
+
.readdirSync(skillsDir, { withFileTypes: true })
|
|
1218
|
+
.filter((d) => d.isFile() && d.name.endsWith(".md"))
|
|
1219
|
+
.map((d) => ({ id: d.name.replace(/\.md$/, ""), path: d.name }));
|
|
1220
|
+
const result = loadSkillsForPlugin({
|
|
1221
|
+
pluginId: "tianshu",
|
|
1222
|
+
pluginDir: skillsDir,
|
|
1223
|
+
contributions,
|
|
1224
|
+
});
|
|
1225
|
+
for (const f of result.failures) {
|
|
1226
|
+
// eslint-disable-next-line no-console
|
|
1227
|
+
console.warn(`[host-skills] ${f.source.contributionId} (${f.filePath}): ${f.reason}`);
|
|
1228
|
+
}
|
|
1229
|
+
hostSkillsCache = result.skills;
|
|
1230
|
+
return hostSkillsCache;
|
|
1231
|
+
}
|
|
1232
|
+
function emptyHostCapabilities() {
|
|
1233
|
+
return {
|
|
1234
|
+
get: () => undefined,
|
|
1235
|
+
has: () => false,
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
function makeLogger(tenantId, userId, _send) {
|
|
1239
|
+
// Tools log to the server console for now; future PR can route
|
|
1240
|
+
// structured tool logs to the chat UI as separate events.
|
|
1241
|
+
const prefix = `[tenant:${tenantId}][user:${userId}][tool]`;
|
|
1242
|
+
return {
|
|
1243
|
+
info: (msg, meta) => console.log(`${prefix} ${msg}`, meta ?? ""),
|
|
1244
|
+
warn: (msg, meta) => console.warn(`${prefix} ${msg}`, meta ?? ""),
|
|
1245
|
+
error: (msg, meta) => console.error(`${prefix} ${msg}`, meta ?? ""),
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
//# sourceMappingURL=handler.js.map
|