@baique/pi-web-sky 0.1.54 → 0.1.56
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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +14 -10
- package/.next/build-manifest.json +4 -4
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +6 -6
- package/.next/react-loadable-manifest.json +3 -3
- package/.next/required-server-files.js +6 -6
- package/.next/required-server-files.json +6 -6
- package/.next/routes-manifest.json +28 -0
- package/.next/server/app/_global-error/page.js +2 -2
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +4 -3
- package/.next/server/app/_not-found.segments/_full.segment.rsc +4 -3
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +4 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +3 -2
- package/.next/server/app/api/agent/[id]/bash-output/route.js +2 -2
- package/.next/server/app/api/agent/[id]/bash-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agent/[id]/events/route.js +2 -2
- package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/events/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agent/[id]/route.js +1 -1
- package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agent/new/route.js +1 -1
- package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/new/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agent/running/route.js +1 -1
- package/.next/server/app/api/agent/running/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/running/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app-update/route.js +1 -1
- package/.next/server/app/api/app-update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/all-providers/route.js +1 -1
- package/.next/server/app/api/auth/all-providers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -1
- package/.next/server/app/api/auth/api-key/[provider]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/[provider]/route.js +1 -1
- package/.next/server/app/api/auth/login/[provider]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/[provider]/route.js +1 -1
- package/.next/server/app/api/auth/logout/[provider]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/providers/route.js +1 -1
- package/.next/server/app/api/auth/providers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/board-assets/[...path]/route.js +2 -2
- package/.next/server/app/api/board-assets/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/board-assets/route.js +2 -2
- package/.next/server/app/api/board-assets/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/boards/[id]/add-session/route.js +1 -0
- package/.next/server/app/api/boards/[id]/add-session/route.js.nft.json +1 -0
- package/.next/server/app/api/boards/[id]/add-session/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/boards/[id]/reconcile/route.js +1 -1
- package/.next/server/app/api/boards/[id]/reconcile/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/boards/[id]/route.js +1 -1
- package/.next/server/app/api/boards/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/boards/reorder/route.js +2 -2
- package/.next/server/app/api/boards/reorder/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/boards/route.js +2 -2
- package/.next/server/app/api/boards/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/cwd/browse/route.js +1 -1
- package/.next/server/app/api/cwd/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/cwd/validate/route.js +2 -2
- package/.next/server/app/api/cwd/validate/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/default-cwd/route.js +2 -2
- package/.next/server/app/api/default-cwd/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/file-index/route.js +2 -2
- package/.next/server/app/api/file-index/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/files/[...path]/route.js +3 -3
- package/.next/server/app/api/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/git/diff/route.js +1 -1
- package/.next/server/app/api/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/git/status/route.js +1 -1
- package/.next/server/app/api/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/home/route.js +1 -1
- package/.next/server/app/api/home/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/mcp/route.js +2 -2
- package/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/models/route.js +2 -2
- package/.next/server/app/api/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/models-config/catalog/route.js +1 -1
- package/.next/server/app/api/models-config/catalog/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/models-config/discover/route.js +1 -1
- package/.next/server/app/api/models-config/discover/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/models-config/route.js +1 -1
- package/.next/server/app/api/models-config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/models-config/test/route.js +1 -1
- package/.next/server/app/api/models-config/test/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/plugins/route.js +2 -2
- package/.next/server/app/api/plugins/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/project-trust/route.js +1 -1
- package/.next/server/app/api/project-trust/route.js.nft.json +1 -1
- package/.next/server/app/api/project-trust/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/quota/route.js +1 -1
- package/.next/server/app/api/quota/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/search/route.js +2 -2
- package/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/auto-name/route.js +2 -2
- package/.next/server/app/api/sessions/[id]/auto-name/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/auto-name/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/context/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/context/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js +2 -2
- package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js +3 -3
- package/.next/server/app/api/sessions/[id]/export/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/minimap/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/minimap/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/minimap/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/state/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/state/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/state/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/[id]/todos/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/todos/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/route.js +1 -1
- package/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sessions/summary/route.js +2 -2
- package/.next/server/app/api/sessions/summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/check/route.js +1 -1
- package/.next/server/app/api/skills/check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/install/route.js +2 -2
- package/.next/server/app/api/skills/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/search/route.js +1 -1
- package/.next/server/app/api/skills/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/update/route.js +1 -1
- package/.next/server/app/api/skills/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/subagents/[id]/route.js +1 -0
- package/.next/server/app/api/subagents/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/subagents/[id]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/subagents/profiles/route.js +30 -0
- package/.next/server/app/api/subagents/profiles/route.js.nft.json +1 -0
- package/.next/server/app/api/subagents/profiles/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/subagents/settings/route.js +1 -0
- package/.next/server/app/api/subagents/settings/route.js.nft.json +1 -0
- package/.next/server/app/api/subagents/settings/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/task-card-questions/[id]/answer/route.js +2 -2
- package/.next/server/app/api/task-card-questions/[id]/answer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/task-card-questions/route.js +2 -2
- package/.next/server/app/api/task-card-questions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/task-cards/[id]/route.js +1 -1
- package/.next/server/app/api/task-cards/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/task-cards/route.js +1 -1
- package/.next/server/app/api/task-cards/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/task-cards/unbind/route.js +3 -3
- package/.next/server/app/api/task-cards/unbind/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/task-scheduler/status/route.js +1 -1
- package/.next/server/app/api/task-scheduler/status/route.js.nft.json +1 -1
- package/.next/server/app/api/task-scheduler/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[id]/assign-session/route.js +12 -12
- package/.next/server/app/api/tasks/[id]/assign-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[id]/board/route.js +1 -1
- package/.next/server/app/api/tasks/[id]/board/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[id]/route.js +1 -1
- package/.next/server/app/api/tasks/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/tasks/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/reorder/route.js +12 -12
- package/.next/server/app/api/tasks/reorder/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/route.js +12 -12
- package/.next/server/app/api/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/terminal/[id]/events/route.js +3 -3
- package/.next/server/app/api/terminal/[id]/events/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/terminal/[id]/route.js +2 -2
- package/.next/server/app/api/terminal/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/terminal/route.js +2 -2
- package/.next/server/app/api/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +2 -2
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/yjs-version/route.js +1 -1
- package/.next/server/app/api/yjs-version/route_client-reference-manifest.js +1 -1
- package/.next/server/app/favicon.ico/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +6 -5
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +6 -5
- package/.next/server/app/index.segments/_full.segment.rsc +6 -5
- package/.next/server/app/index.segments/_tree.segment.rsc +3 -2
- package/.next/server/app/manifest.webmanifest/route.js +2 -2
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +175 -8
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +14 -10
- package/.next/server/chunks/1937.js +1 -1
- package/.next/server/chunks/2430.js +4 -4
- package/.next/server/chunks/3500.js +1 -1
- package/.next/server/chunks/402.js +13 -3
- package/.next/server/chunks/426.js +14 -0
- package/.next/server/chunks/4457.js +13 -13
- package/.next/server/chunks/542.js +23 -4
- package/.next/server/chunks/5794.js +2 -2
- package/.next/server/chunks/5940.js +1 -1
- package/.next/server/chunks/6429.js +15 -2
- package/.next/server/chunks/6525.js +12 -2
- package/.next/server/chunks/6583.js +1 -1
- package/.next/server/chunks/7048.js +6 -0
- package/.next/server/instrumentation.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/middleware.js +3 -3
- package/.next/server/next-font-manifest.js +1 -1
- package/.next/server/next-font-manifest.json +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/752.adce8bc3ebbaf4b6.js +1 -0
- package/.next/static/chunks/8088.0cad1ff2e09fd8ff.js +1 -0
- package/.next/static/chunks/app/_global-error/page-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/_not-found/page-63a39396532d2582.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/bash-output/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/agent/running/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/app-update/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/auth/all-providers/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/auth/login/[provider]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/auth/providers/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/board-assets/[...path]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/board-assets/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/boards/[id]/add-session/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/boards/[id]/reconcile/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/boards/[id]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/boards/reorder/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/boards/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/cwd/browse/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/cwd/validate/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/default-cwd/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/file-index/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/files/[...path]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/git/diff/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/git/status/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/home/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/mcp/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/models/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/models-config/catalog/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/models-config/discover/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/models-config/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/models-config/test/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/plugins/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/project-trust/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/quota/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/search/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/context/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/export/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/minimap/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/state/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/todos/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/sessions/summary/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/skills/check/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/skills/install/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/skills/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/skills/search/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/skills/update/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/subagents/[id]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/subagents/profiles/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/subagents/settings/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/task-card-questions/[id]/answer/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/task-card-questions/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/task-cards/[id]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/task-cards/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/task-cards/unbind/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/task-scheduler/status/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/tasks/[id]/assign-session/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/tasks/[id]/board/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/tasks/[id]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/tasks/reorder/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/tasks/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/terminal/[id]/events/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/terminal/[id]/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/terminal/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/api/yjs-version/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/layout-87087b955e0c9507.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/app/page-efca6bf51a5f8ccb.js +256 -0
- package/.next/static/chunks/main-app-1f89e7ad7ae1ff87.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-d3784ab2e32f3c6e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-ad6e695deb9de65c.js +1 -0
- package/.next/static/chunks/{webpack-3df5ae3897959c33.js → webpack-4de8e8dd9f2f3173.js} +1 -1
- package/.next/static/css/bb9361c7f832a89d.css +1 -0
- package/.next/static/css/c6d32b6031181be7.css +1 -0
- package/.next/static/k8ZFqwz7d-bnK0ZiUVgCc/_buildManifest.js +1 -0
- package/.next/trace +7 -8
- package/.next/trace-build +1 -1
- package/.next/types/app/api/agent/[id]/bash-output/route.ts +1 -1
- package/.next/types/app/api/agent/[id]/events/route.ts +1 -1
- package/.next/types/app/api/agent/[id]/route.ts +1 -1
- package/.next/types/app/api/agent/new/route.ts +1 -1
- package/.next/types/app/api/agent/running/route.ts +1 -1
- package/.next/types/app/api/app-update/route.ts +1 -1
- package/.next/types/app/api/auth/all-providers/route.ts +1 -1
- package/.next/types/app/api/auth/api-key/[provider]/route.ts +1 -1
- package/.next/types/app/api/auth/login/[provider]/route.ts +1 -1
- package/.next/types/app/api/auth/logout/[provider]/route.ts +1 -1
- package/.next/types/app/api/auth/providers/route.ts +1 -1
- package/.next/types/app/api/board-assets/[...path]/route.ts +1 -1
- package/.next/types/app/api/board-assets/route.ts +1 -1
- package/.next/types/app/api/boards/[id]/add-session/route.ts +353 -0
- package/.next/types/app/api/boards/[id]/reconcile/route.ts +1 -1
- package/.next/types/app/api/boards/[id]/route.ts +1 -1
- package/.next/types/app/api/boards/reorder/route.ts +1 -1
- package/.next/types/app/api/boards/route.ts +1 -1
- package/.next/types/app/api/cwd/browse/route.ts +1 -1
- package/.next/types/app/api/cwd/validate/route.ts +1 -1
- package/.next/types/app/api/default-cwd/route.ts +1 -1
- package/.next/types/app/api/file-index/route.ts +1 -1
- package/.next/types/app/api/files/[...path]/route.ts +1 -1
- package/.next/types/app/api/git/diff/route.ts +1 -1
- package/.next/types/app/api/git/status/route.ts +1 -1
- package/.next/types/app/api/home/route.ts +1 -1
- package/.next/types/app/api/mcp/route.ts +1 -1
- package/.next/types/app/api/models/route.ts +1 -1
- package/.next/types/app/api/models-config/catalog/route.ts +1 -1
- package/.next/types/app/api/models-config/discover/route.ts +1 -1
- package/.next/types/app/api/models-config/route.ts +1 -1
- package/.next/types/app/api/models-config/test/route.ts +1 -1
- package/.next/types/app/api/plugins/route.ts +1 -1
- package/.next/types/app/api/project-trust/route.ts +1 -1
- package/.next/types/app/api/quota/route.ts +1 -1
- package/.next/types/app/api/search/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/auto-name/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/context/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/entries/[entryId]/thinking/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/export/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/minimap/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/state/route.ts +1 -1
- package/.next/types/app/api/sessions/[id]/todos/route.ts +1 -1
- package/.next/types/app/api/sessions/route.ts +1 -1
- package/.next/types/app/api/sessions/summary/route.ts +1 -1
- package/.next/types/app/api/skills/check/route.ts +1 -1
- package/.next/types/app/api/skills/install/route.ts +1 -1
- package/.next/types/app/api/skills/route.ts +1 -1
- package/.next/types/app/api/skills/search/route.ts +1 -1
- package/.next/types/app/api/skills/update/route.ts +1 -1
- package/.next/types/app/api/subagents/[id]/route.ts +353 -0
- package/.next/types/app/api/subagents/profiles/route.ts +353 -0
- package/.next/types/app/api/subagents/settings/route.ts +353 -0
- package/.next/types/app/api/task-card-questions/[id]/answer/route.ts +1 -1
- package/.next/types/app/api/task-card-questions/route.ts +1 -1
- package/.next/types/app/api/task-cards/[id]/route.ts +1 -1
- package/.next/types/app/api/task-cards/route.ts +1 -1
- package/.next/types/app/api/task-cards/unbind/route.ts +1 -1
- package/.next/types/app/api/task-scheduler/status/route.ts +1 -1
- package/.next/types/app/api/tasks/[id]/assign-session/route.ts +1 -1
- package/.next/types/app/api/tasks/[id]/board/route.ts +1 -1
- package/.next/types/app/api/tasks/[id]/route.ts +1 -1
- package/.next/types/app/api/tasks/reorder/route.ts +1 -1
- package/.next/types/app/api/tasks/route.ts +1 -1
- package/.next/types/app/api/terminal/[id]/events/route.ts +1 -1
- package/.next/types/app/api/terminal/[id]/route.ts +1 -1
- package/.next/types/app/api/terminal/route.ts +1 -1
- package/.next/types/app/api/worktrees/route.ts +1 -1
- package/.next/types/app/api/yjs-version/route.ts +1 -1
- package/.next/types/app/layout.ts +1 -1
- package/.next/types/app/page.ts +1 -1
- package/.next/types/routes.d.ts +5 -1
- package/.next/types/validator.ts +36 -0
- package/lib/api-types.ts +10 -0
- package/lib/board-events.rename.test.mjs +39 -0
- package/lib/board-events.ts +17 -0
- package/lib/board-reconcile.test.mjs +20 -0
- package/lib/board-reconcile.ts +54 -0
- package/lib/chat-lazy-load.test.mjs +0 -62
- package/lib/chat-lazy-load.ts +0 -13
- package/lib/chat-only.ts +23 -0
- package/lib/draft-stash.ts +4 -5
- package/lib/file-types.ts +16 -1
- package/lib/i18n/messages/en.ts +91 -0
- package/lib/i18n/messages/zh-CN.ts +91 -0
- package/lib/id.test.mjs +38 -0
- package/lib/id.ts +17 -0
- package/lib/message-text.ts +24 -0
- package/lib/models-cache.ts +1 -1
- package/lib/pi-types.ts +19 -1
- package/lib/pin-store.ts +85 -0
- package/lib/powershell-settings.ts +106 -0
- package/lib/quoted-selection.ts +4 -0
- package/lib/rpc-manager.ts +208 -22
- package/lib/session-family.test.mjs +49 -0
- package/lib/session-family.ts +80 -0
- package/lib/session-index-scanner.ts +39 -0
- package/lib/session-time-group.test.mjs +38 -0
- package/lib/session-time-group.ts +55 -0
- package/lib/settings-navigation.ts +124 -0
- package/lib/subagent-extension.test.mjs +424 -0
- package/lib/subagent-extension.ts +309 -0
- package/lib/subagent-input.test.mjs +63 -0
- package/lib/subagent-input.ts +71 -0
- package/lib/subagent-isolation.test.mjs +51 -0
- package/lib/subagent-profile-precedence.ts +20 -0
- package/lib/subagent-prompt.test.mjs +64 -0
- package/lib/subagent-prompt.ts +31 -0
- package/lib/subagent-queue.test.mjs +35 -0
- package/lib/subagent-queue.ts +74 -0
- package/lib/subagent-runtime.test.mjs +150 -0
- package/lib/subagent-runtime.ts +587 -0
- package/lib/subagent-settings.test.mjs +50 -0
- package/lib/subagent-settings.ts +93 -0
- package/lib/subagents.test.mjs +601 -0
- package/lib/subagents.ts +602 -0
- package/lib/tool-presets.ts +4 -0
- package/lib/types.ts +19 -0
- package/package.json +1 -1
- package/.next/static/chunks/752.3119700876725f3b.js +0 -1
- package/.next/static/chunks/7975.95edcabc69eee4eb.js +0 -1
- package/.next/static/chunks/app/_global-error/page-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/_not-found/page-af4fe23994cb3d66.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/bash-output/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/events/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/agent/new/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/agent/running/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/app-update/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/auth/all-providers/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/auth/login/[provider]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/auth/providers/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/board-assets/[...path]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/board-assets/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/boards/[id]/reconcile/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/boards/[id]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/boards/reorder/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/boards/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/cwd/browse/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/cwd/validate/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/default-cwd/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/file-index/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/files/[...path]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/git/diff/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/git/status/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/home/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/mcp/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/models/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/models-config/catalog/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/models-config/discover/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/models-config/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/models-config/test/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/plugins/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/project-trust/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/quota/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/search/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/context/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/export/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/minimap/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/state/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/todos/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/sessions/summary/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/skills/check/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/skills/install/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/skills/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/skills/search/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/skills/update/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/task-card-questions/[id]/answer/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/task-card-questions/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/task-cards/[id]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/task-cards/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/task-cards/unbind/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/task-scheduler/status/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/tasks/[id]/assign-session/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/tasks/[id]/board/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/tasks/[id]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/tasks/reorder/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/tasks/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/terminal/[id]/events/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/terminal/[id]/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/terminal/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/worktrees/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/api/yjs-version/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/layout-636e9e756d0734c7.js +0 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/app/page-44daed9dcf9134eb.js +0 -89
- package/.next/static/chunks/main-app-b3e8a8d15d83e1f0.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-00a4badaccb388e6.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-2d5f6296c7e693c6.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2d5f6296c7e693c6.js +0 -1
- package/.next/static/css/4a609fb185e7cff1.css +0 -1
- package/.next/static/h-hr7x0pqNUx3TyuarqWJ/_buildManifest.js +0 -1
- package/lib/extension-command.test.mjs +0 -63
- package/lib/extension-command.ts +0 -81
- package/lib/subagent-widget.test.mjs +0 -87
- package/lib/subagent-widget.ts +0 -109
- /package/.next/static/{h-hr7x0pqNUx3TyuarqWJ → k8ZFqwz7d-bnK0ZiUVgCc}/_ssgManifest.js +0 -0
package/lib/subagents.ts
ADDED
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { dump as stringifyYaml } from "js-yaml";
|
|
4
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync } from "fs";
|
|
5
|
+
import { basename, dirname, join, resolve } from "path";
|
|
6
|
+
import { parseFrontmatter } from "./frontmatter";
|
|
7
|
+
import { writePrivateFileAtomicSync } from "./atomic-file";
|
|
8
|
+
import { isExistingPathWithinRoots } from "./path-security";
|
|
9
|
+
import { PRESET_READ_ONLY, DEFAULT_TOOLS } from "./tool-presets";
|
|
10
|
+
import type { SessionEntry, SubagentSessionStatus } from "./types";
|
|
11
|
+
|
|
12
|
+
export const SUBAGENT_META_TYPE = "pi-web:subagent";
|
|
13
|
+
export const SUBAGENT_STATUS_TYPE = "pi-web:subagent-status";
|
|
14
|
+
export const SUBAGENT_RESULT_TYPE = "pi-web:subagent-result";
|
|
15
|
+
export const SUBAGENT_CONTROL_TOOL_NAMES = ["Agent", "get_subagent_result", "steer_subagent"] as const;
|
|
16
|
+
|
|
17
|
+
export type SubagentStatus = SubagentSessionStatus;
|
|
18
|
+
export type SubagentScope = "builtin" | "global" | "workspace" | "project";
|
|
19
|
+
export type SubagentWritableScope = Extract<SubagentScope, "global" | "project">;
|
|
20
|
+
|
|
21
|
+
export interface SubagentProfile {
|
|
22
|
+
name: string;
|
|
23
|
+
displayName: string;
|
|
24
|
+
description: string;
|
|
25
|
+
systemPrompt: string;
|
|
26
|
+
tools: string[];
|
|
27
|
+
extensionTools?: string[];
|
|
28
|
+
loadSkills: boolean;
|
|
29
|
+
loadExtensions: boolean;
|
|
30
|
+
model?: string;
|
|
31
|
+
thinking?: ThinkingLevel;
|
|
32
|
+
maxTurns?: number;
|
|
33
|
+
inheritContext: boolean;
|
|
34
|
+
runInBackground: boolean;
|
|
35
|
+
promptMode: "replace" | "append";
|
|
36
|
+
color?: string;
|
|
37
|
+
isolation?: "worktree" | "off";
|
|
38
|
+
persistSession?: boolean;
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
scope: SubagentScope;
|
|
41
|
+
filePath?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SubagentMetadata {
|
|
45
|
+
version: 1;
|
|
46
|
+
parentSessionId: string;
|
|
47
|
+
parentSessionPath: string;
|
|
48
|
+
parentToolCallId: string;
|
|
49
|
+
profile: string;
|
|
50
|
+
description: string;
|
|
51
|
+
task: string;
|
|
52
|
+
runInBackground: boolean;
|
|
53
|
+
createdAt: string;
|
|
54
|
+
resourceSnapshot: SubagentResourceSnapshot;
|
|
55
|
+
worktreePath?: string;
|
|
56
|
+
worktreeBranch?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface SubagentResourceSnapshot {
|
|
60
|
+
version: 1;
|
|
61
|
+
appendSystemPrompt: string[];
|
|
62
|
+
tools: string[];
|
|
63
|
+
loadSkills: boolean;
|
|
64
|
+
loadExtensions: boolean;
|
|
65
|
+
exactSystemPrompt?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface SubagentSessionResources {
|
|
69
|
+
appendSystemPrompt: string[];
|
|
70
|
+
tools: string[];
|
|
71
|
+
loadSkills: boolean;
|
|
72
|
+
loadExtensions: boolean;
|
|
73
|
+
exactSystemPrompt?: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface SubagentResultMetadata {
|
|
77
|
+
version: 1;
|
|
78
|
+
status: Exclude<SubagentStatus, "starting" | "running" | "queued" | "interrupted">;
|
|
79
|
+
completedAt: string;
|
|
80
|
+
result?: string;
|
|
81
|
+
error?: string;
|
|
82
|
+
worktreeCleanupError?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface SubagentStatusMetadata {
|
|
86
|
+
version: 1;
|
|
87
|
+
status: Extract<SubagentStatus, "queued" | "running">;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface SubagentRunInfo {
|
|
91
|
+
sessionId: string;
|
|
92
|
+
sessionPath: string;
|
|
93
|
+
parentSessionId: string;
|
|
94
|
+
parentToolCallId: string;
|
|
95
|
+
profile: string;
|
|
96
|
+
description: string;
|
|
97
|
+
task: string;
|
|
98
|
+
runInBackground: boolean;
|
|
99
|
+
status: SubagentStatus;
|
|
100
|
+
createdAt: string;
|
|
101
|
+
completedAt?: string;
|
|
102
|
+
result?: string;
|
|
103
|
+
error?: string;
|
|
104
|
+
worktreePath?: string;
|
|
105
|
+
worktreeBranch?: string;
|
|
106
|
+
worktreeCleanupError?: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const BUILTIN_TOOLS = new Set(DEFAULT_TOOLS);
|
|
110
|
+
const SUBAGENT_CONTROL_TOOLS = new Set<string>(SUBAGENT_CONTROL_TOOL_NAMES);
|
|
111
|
+
const THINKING_LEVELS = new Set<ThinkingLevel>(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Frontmatter keys the web UI owns. Everything else in a profile file belongs to
|
|
115
|
+
* whichever runtime reads it (pi-subagents and friends), so a save from this app must
|
|
116
|
+
* carry those keys through untouched. Dropping them silently changed behaviour:
|
|
117
|
+
* `allowed_subagents` was lost and an orchestrator could no longer spawn anything,
|
|
118
|
+
* `exclude_extensions` was lost and an opt-out became an opt-in.
|
|
119
|
+
*/
|
|
120
|
+
const MANAGED_FRONTMATTER_KEYS = new Set([
|
|
121
|
+
"description",
|
|
122
|
+
"display_name",
|
|
123
|
+
"tools",
|
|
124
|
+
"load_skills",
|
|
125
|
+
"load_extensions",
|
|
126
|
+
"enabled",
|
|
127
|
+
"inherit_context",
|
|
128
|
+
"run_in_background",
|
|
129
|
+
"model",
|
|
130
|
+
"thinking",
|
|
131
|
+
"max_turns",
|
|
132
|
+
"prompt_mode",
|
|
133
|
+
"color",
|
|
134
|
+
"isolation",
|
|
135
|
+
"persist_session",
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
const FRONTMATTER_OPEN_RE = /^(?:\uFEFF)?---[ \t]*(?:\r\n|\n|\r)/;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The UI exposes two booleans (`load_skills` / `load_extensions`); pi-subagents reads
|
|
142
|
+
* the aliases `skills` / `extensions`, which also accept a whitelist. Aliases are
|
|
143
|
+
* carried through by `unmanagedFrontmatter` and only rewritten once we own them.
|
|
144
|
+
*/
|
|
145
|
+
const OWNED_ALIAS_VALUES = new Set(["none", "all", "true", "false"]);
|
|
146
|
+
|
|
147
|
+
const BUILTIN_PROFILES: SubagentProfile[] = [
|
|
148
|
+
{
|
|
149
|
+
name: "general-purpose",
|
|
150
|
+
displayName: "General purpose",
|
|
151
|
+
description: "Handle a focused implementation or investigation task",
|
|
152
|
+
systemPrompt: "Work autonomously on the delegated task. Keep the final answer concise and include important files, decisions, and remaining risks.",
|
|
153
|
+
tools: DEFAULT_TOOLS,
|
|
154
|
+
loadSkills: false,
|
|
155
|
+
loadExtensions: false,
|
|
156
|
+
promptMode: "append",
|
|
157
|
+
inheritContext: false,
|
|
158
|
+
runInBackground: false,
|
|
159
|
+
enabled: true,
|
|
160
|
+
scope: "builtin",
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "explore",
|
|
164
|
+
displayName: "Explore",
|
|
165
|
+
description: "Quickly inspect a codebase without modifying it",
|
|
166
|
+
systemPrompt: "Explore the codebase to answer the delegated question. Do not modify files. Report concrete findings with file paths and relevant symbols.",
|
|
167
|
+
tools: [...PRESET_READ_ONLY],
|
|
168
|
+
loadSkills: false,
|
|
169
|
+
loadExtensions: false,
|
|
170
|
+
promptMode: "append",
|
|
171
|
+
inheritContext: false,
|
|
172
|
+
runInBackground: false,
|
|
173
|
+
enabled: true,
|
|
174
|
+
scope: "builtin",
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "plan",
|
|
178
|
+
displayName: "Plan",
|
|
179
|
+
description: "Design an implementation plan without modifying files",
|
|
180
|
+
systemPrompt: "Produce an implementation-ready plan for the delegated task. Inspect the repository as needed, do not modify files, and call out dependencies, risks, and verification steps.",
|
|
181
|
+
tools: [...PRESET_READ_ONLY],
|
|
182
|
+
loadSkills: false,
|
|
183
|
+
loadExtensions: false,
|
|
184
|
+
promptMode: "append",
|
|
185
|
+
inheritContext: false,
|
|
186
|
+
runInBackground: false,
|
|
187
|
+
enabled: true,
|
|
188
|
+
scope: "builtin",
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
function stringValue(value: unknown): string | undefined {
|
|
193
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function booleanValue(value: unknown, fallback: boolean): boolean {
|
|
197
|
+
return typeof value === "boolean" ? value : fallback;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function resourceBoolean(value: unknown, fallback: boolean): boolean {
|
|
201
|
+
if (typeof value === "boolean") return value;
|
|
202
|
+
return Array.isArray(value) || typeof value === "string" ? true : fallback;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function stringList(value: unknown): string[] {
|
|
206
|
+
const values = Array.isArray(value)
|
|
207
|
+
? value
|
|
208
|
+
: typeof value === "string"
|
|
209
|
+
? value.split(",")
|
|
210
|
+
: [];
|
|
211
|
+
return values.map((item) => String(item).trim()).filter(Boolean);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function parseTools(value: unknown, fallback: string[]): string[] {
|
|
215
|
+
const tools = stringList(value);
|
|
216
|
+
if (tools.includes("none")) return [];
|
|
217
|
+
if (tools.includes("all") || tools.includes("*")) return [...DEFAULT_TOOLS];
|
|
218
|
+
if (tools.length === 0) return [...fallback];
|
|
219
|
+
return [...new Set(tools.filter((tool) => BUILTIN_TOOLS.has(tool)))];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function rawToolValues(value: unknown): string[] {
|
|
223
|
+
return stringList(value);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function parseExtensionToolSelectors(value: unknown): string[] {
|
|
227
|
+
return [...new Set(rawToolValues(value).filter((tool) => tool.toLowerCase().startsWith("ext:")))];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Read existing frontmatter without allowing malformed metadata to be overwritten. */
|
|
231
|
+
function readStoredFrontmatter(filePath: string): Record<string, unknown> {
|
|
232
|
+
if (!existsSync(filePath)) return {};
|
|
233
|
+
const source = readFileSync(filePath, "utf8");
|
|
234
|
+
const { data } = parseFrontmatter(source);
|
|
235
|
+
if (data) return data;
|
|
236
|
+
if (FRONTMATTER_OPEN_RE.test(source)) {
|
|
237
|
+
throw new Error("Cannot save agent profile: existing frontmatter is invalid");
|
|
238
|
+
}
|
|
239
|
+
return {};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Keys another runtime owns, in file order, so a save round-trips them. */
|
|
243
|
+
function unmanagedFrontmatter(stored: Record<string, unknown>): Record<string, unknown> {
|
|
244
|
+
const preserved: Record<string, unknown> = {};
|
|
245
|
+
for (const [key, value] of Object.entries(stored)) {
|
|
246
|
+
if (!MANAGED_FRONTMATTER_KEYS.has(key)) preserved[key] = value;
|
|
247
|
+
}
|
|
248
|
+
return preserved;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* pi-web filters `tools` down to the built-ins it can dispatch, which would drop
|
|
253
|
+
* another runtime's `ext:<name>` selectors on every save — carry them through.
|
|
254
|
+
*/
|
|
255
|
+
function composeToolsField(tools: string[], storedTools: unknown): string {
|
|
256
|
+
const selectors = stringList(storedTools).filter((tool) => tool.startsWith("ext:"));
|
|
257
|
+
const combined = [...tools, ...selectors.filter((selector) => !tools.includes(selector))];
|
|
258
|
+
return combined.length > 0 ? combined.join(", ") : "none";
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Keep the alias in step with the boolean the UI owns. A boolean (or a "none" /
|
|
263
|
+
* "all" spelling) is ours to rewrite; a whitelist such as `extensions:
|
|
264
|
+
* pi-advisor-flow` expresses scoping the UI cannot show, so it stays as authored.
|
|
265
|
+
*/
|
|
266
|
+
function syncFlagAlias(
|
|
267
|
+
frontmatter: Record<string, unknown>,
|
|
268
|
+
alias: string,
|
|
269
|
+
storedValue: unknown,
|
|
270
|
+
flag: boolean,
|
|
271
|
+
): void {
|
|
272
|
+
const owned = storedValue === undefined
|
|
273
|
+
|| typeof storedValue === "boolean"
|
|
274
|
+
|| (typeof storedValue === "string" && OWNED_ALIAS_VALUES.has(storedValue.trim().toLowerCase()));
|
|
275
|
+
if (owned) frontmatter[alias] = flag;
|
|
276
|
+
}
|
|
277
|
+
function parseProfileFile(filePath: string, scope: SubagentScope): SubagentProfile | null {
|
|
278
|
+
try {
|
|
279
|
+
const source = readFileSync(filePath, "utf8");
|
|
280
|
+
const { data, rest } = parseFrontmatter(source);
|
|
281
|
+
const name = stringValue(data?.name) ?? basename(filePath, ".md");
|
|
282
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name)) return null;
|
|
283
|
+
const thinkingValue = stringValue(data?.thinking) as ThinkingLevel | undefined;
|
|
284
|
+
const maxTurnsValue = typeof data?.max_turns === "number" ? Math.floor(data.max_turns) : undefined;
|
|
285
|
+
const tools = parseTools(data?.tools, DEFAULT_TOOLS);
|
|
286
|
+
const disallowedTools = new Set(parseTools(data?.disallowed_tools, []));
|
|
287
|
+
const disallowedExtensionTools = new Set(parseExtensionToolSelectors(data?.disallowed_tools).map((tool) => tool.toLowerCase()));
|
|
288
|
+
const extensionTools = parseExtensionToolSelectors(data?.tools)
|
|
289
|
+
.filter((tool) => !disallowedExtensionTools.has(tool.toLowerCase()));
|
|
290
|
+
return {
|
|
291
|
+
name,
|
|
292
|
+
displayName: stringValue(data?.display_name) ?? name,
|
|
293
|
+
description: stringValue(data?.description) ?? name,
|
|
294
|
+
systemPrompt: rest.trim(),
|
|
295
|
+
tools: tools.filter((tool) => !disallowedTools.has(tool)),
|
|
296
|
+
...(extensionTools.length > 0 ? { extensionTools } : {}),
|
|
297
|
+
loadSkills: resourceBoolean(data?.load_skills ?? data?.skills, false),
|
|
298
|
+
loadExtensions: resourceBoolean(data?.load_extensions ?? data?.extensions, extensionTools.length > 0),
|
|
299
|
+
...(stringValue(data?.model) ? { model: stringValue(data?.model) } : {}),
|
|
300
|
+
...(thinkingValue && THINKING_LEVELS.has(thinkingValue) ? { thinking: thinkingValue } : {}),
|
|
301
|
+
...(maxTurnsValue && maxTurnsValue > 0 ? { maxTurns: maxTurnsValue } : {}),
|
|
302
|
+
inheritContext: booleanValue(data?.inherit_context, false),
|
|
303
|
+
runInBackground: booleanValue(data?.run_in_background, false),
|
|
304
|
+
promptMode: data?.prompt_mode === "replace" ? "replace" : "append",
|
|
305
|
+
...(stringValue(data?.color) ? { color: stringValue(data?.color) } : {}),
|
|
306
|
+
...(data?.isolation === "worktree" || data?.isolation === "off" ? { isolation: data.isolation } : {}),
|
|
307
|
+
...(typeof data?.persist_session === "boolean" ? { persistSession: data.persist_session } : {}),
|
|
308
|
+
enabled: booleanValue(data?.enabled, true),
|
|
309
|
+
scope,
|
|
310
|
+
filePath,
|
|
311
|
+
};
|
|
312
|
+
} catch {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function isProjectProfilePathAllowed(cwd: string, target: string): boolean {
|
|
318
|
+
return isExistingPathWithinRoots(target, new Set([cwd]));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function readProfileDirectory(dir: string, scope: SubagentScope, cwd: string): SubagentProfile[] {
|
|
322
|
+
if (!existsSync(dir)) return [];
|
|
323
|
+
if (scope !== "global" && !isProjectProfilePathAllowed(cwd, dir)) return [];
|
|
324
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
325
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith(".md"))
|
|
326
|
+
.map((entry) => parseProfileFile(join(dir, entry.name), scope))
|
|
327
|
+
.filter((profile): profile is SubagentProfile => profile !== null);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function profileDirectories(cwd: string): Array<[string, Exclude<SubagentScope, "builtin">]> {
|
|
331
|
+
return [
|
|
332
|
+
[join(getAgentDir(), "agents"), "global"],
|
|
333
|
+
[join(resolve(cwd), ".agents", "agents"), "workspace"],
|
|
334
|
+
[join(resolve(cwd), ".pi", "agents"), "project"],
|
|
335
|
+
];
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** Every configured source, including profiles shadowed by a higher-precedence scope. */
|
|
339
|
+
export function listSubagentProfileSources(cwd: string): SubagentProfile[] {
|
|
340
|
+
const profiles = BUILTIN_PROFILES.map((profile) => ({ ...profile, tools: [...profile.tools] }));
|
|
341
|
+
for (const [dir, scope] of profileDirectories(cwd)) {
|
|
342
|
+
profiles.push(...readProfileDirectory(dir, scope, cwd));
|
|
343
|
+
}
|
|
344
|
+
return profiles.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function listSubagentProfiles(cwd: string): SubagentProfile[] {
|
|
348
|
+
const byName = new Map(BUILTIN_PROFILES.map((profile) => [profile.name.toLowerCase(), { ...profile, tools: [...profile.tools] }]));
|
|
349
|
+
for (const [dir, scope] of profileDirectories(cwd)) {
|
|
350
|
+
for (const profile of readProfileDirectory(dir, scope, cwd)) byName.set(profile.name.toLowerCase(), profile);
|
|
351
|
+
}
|
|
352
|
+
return [...byName.values()].sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export function resolveSubagentProfile(cwd: string, name: string): SubagentProfile | undefined {
|
|
356
|
+
return listSubagentProfiles(cwd).find((profile) => profile.name.toLowerCase() === name.trim().toLowerCase() && profile.enabled);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function assertProfileName(name: string): string {
|
|
360
|
+
const normalized = name.trim();
|
|
361
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(normalized)) {
|
|
362
|
+
throw new Error("Agent name may contain only letters, numbers, dots, underscores, and hyphens");
|
|
363
|
+
}
|
|
364
|
+
return normalized;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function writableProfileDirectory(cwd: string, scope: SubagentWritableScope): string {
|
|
368
|
+
if (scope === "global") return join(getAgentDir(), "agents");
|
|
369
|
+
if (scope === "project") return join(resolve(cwd), ".pi", "agents");
|
|
370
|
+
throw new Error("Agent scope must be global or project");
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function assertWritableProfileDirectory(cwd: string, scope: SubagentWritableScope): string {
|
|
374
|
+
const dir = writableProfileDirectory(cwd, scope);
|
|
375
|
+
if (scope === "global") return dir;
|
|
376
|
+
|
|
377
|
+
let existingAncestor = dir;
|
|
378
|
+
while (!existsSync(existingAncestor)) {
|
|
379
|
+
const parent = dirname(existingAncestor);
|
|
380
|
+
if (parent === existingAncestor) throw new Error("Agent profile directory is outside the project root");
|
|
381
|
+
existingAncestor = parent;
|
|
382
|
+
}
|
|
383
|
+
if (!isProjectProfilePathAllowed(cwd, existingAncestor)) {
|
|
384
|
+
throw new Error("Agent profile directory is outside the project root");
|
|
385
|
+
}
|
|
386
|
+
return dir;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export function saveSubagentProfile(
|
|
390
|
+
cwd: string,
|
|
391
|
+
scope: SubagentWritableScope,
|
|
392
|
+
profile: Omit<SubagentProfile, "scope" | "filePath">,
|
|
393
|
+
): SubagentProfile {
|
|
394
|
+
const name = assertProfileName(profile.name);
|
|
395
|
+
const tools = [...new Set(profile.tools.filter((tool) => BUILTIN_TOOLS.has(tool)))];
|
|
396
|
+
const extensionTools = [...new Set(profile.extensionTools ?? [])];
|
|
397
|
+
if (profile.thinking && !THINKING_LEVELS.has(profile.thinking)) {
|
|
398
|
+
throw new Error(`Invalid thinking level: ${profile.thinking}`);
|
|
399
|
+
}
|
|
400
|
+
if (profile.maxTurns !== undefined && (!Number.isFinite(profile.maxTurns) || profile.maxTurns < 0)) {
|
|
401
|
+
throw new Error("Max turns must be a non-negative number");
|
|
402
|
+
}
|
|
403
|
+
const maxTurns = profile.maxTurns && profile.maxTurns > 0
|
|
404
|
+
? Math.floor(profile.maxTurns)
|
|
405
|
+
: undefined;
|
|
406
|
+
const displayName = profile.displayName.trim() || name;
|
|
407
|
+
const description = profile.description.trim() || name;
|
|
408
|
+
const systemPrompt = profile.systemPrompt.trim();
|
|
409
|
+
const model = profile.model?.trim() || undefined;
|
|
410
|
+
const loadSkills = profile.loadSkills === true;
|
|
411
|
+
const loadExtensions = profile.loadExtensions === true;
|
|
412
|
+
const promptMode = profile.promptMode === "replace" ? "replace" : "append";
|
|
413
|
+
const dir = assertWritableProfileDirectory(cwd, scope);
|
|
414
|
+
mkdirSync(dir, { recursive: true });
|
|
415
|
+
if (scope === "project" && !isProjectProfilePathAllowed(cwd, dir)) {
|
|
416
|
+
throw new Error("Agent profile directory is outside the project root");
|
|
417
|
+
}
|
|
418
|
+
const filePath = join(dir, `${name}.md`);
|
|
419
|
+
const stored = readStoredFrontmatter(filePath);
|
|
420
|
+
const managed: Record<string, unknown> = {
|
|
421
|
+
description,
|
|
422
|
+
display_name: displayName,
|
|
423
|
+
tools: composeToolsField([...tools, ...extensionTools], stored.tools),
|
|
424
|
+
load_skills: loadSkills,
|
|
425
|
+
load_extensions: loadExtensions,
|
|
426
|
+
enabled: profile.enabled,
|
|
427
|
+
inherit_context: profile.inheritContext,
|
|
428
|
+
run_in_background: profile.runInBackground,
|
|
429
|
+
prompt_mode: promptMode,
|
|
430
|
+
};
|
|
431
|
+
syncFlagAlias(managed, "skills", stored.skills, loadSkills);
|
|
432
|
+
syncFlagAlias(managed, "extensions", stored.extensions, loadExtensions);
|
|
433
|
+
if (model) managed.model = model;
|
|
434
|
+
if (profile.thinking) managed.thinking = profile.thinking;
|
|
435
|
+
if (maxTurns) managed.max_turns = maxTurns;
|
|
436
|
+
if (profile.color?.trim()) managed.color = profile.color.trim();
|
|
437
|
+
if (profile.isolation) managed.isolation = profile.isolation;
|
|
438
|
+
if (profile.persistSession !== undefined) managed.persist_session = profile.persistSession;
|
|
439
|
+
// Managed keys win; keys this app does not own follow in their original order.
|
|
440
|
+
const frontmatter: Record<string, unknown> = { ...managed };
|
|
441
|
+
for (const [key, value] of Object.entries(unmanagedFrontmatter(stored))) {
|
|
442
|
+
if (!(key in frontmatter)) frontmatter[key] = value;
|
|
443
|
+
}
|
|
444
|
+
const yaml = stringifyYaml(frontmatter, { noRefs: true, lineWidth: 1000 }).trimEnd();
|
|
445
|
+
writePrivateFileAtomicSync(filePath, `---\n${yaml}\n---\n\n${systemPrompt}\n`);
|
|
446
|
+
return {
|
|
447
|
+
...profile,
|
|
448
|
+
name,
|
|
449
|
+
displayName,
|
|
450
|
+
description,
|
|
451
|
+
systemPrompt,
|
|
452
|
+
tools,
|
|
453
|
+
...(extensionTools.length > 0 ? { extensionTools } : {}),
|
|
454
|
+
loadSkills,
|
|
455
|
+
loadExtensions,
|
|
456
|
+
...(model ? { model } : { model: undefined }),
|
|
457
|
+
...(maxTurns ? { maxTurns } : { maxTurns: undefined }),
|
|
458
|
+
promptMode,
|
|
459
|
+
...(profile.color ? { color: profile.color } : {}),
|
|
460
|
+
...(profile.isolation ? { isolation: profile.isolation } : {}),
|
|
461
|
+
...(profile.persistSession !== undefined ? { persistSession: profile.persistSession } : {}),
|
|
462
|
+
scope,
|
|
463
|
+
filePath,
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export function deleteSubagentProfile(cwd: string, scope: SubagentWritableScope, name: string): void {
|
|
468
|
+
const safeName = assertProfileName(name);
|
|
469
|
+
const filePath = join(assertWritableProfileDirectory(cwd, scope), `${safeName}.md`);
|
|
470
|
+
if (existsSync(filePath)) unlinkSync(filePath);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export function saveProjectSubagentProfile(cwd: string, profile: Omit<SubagentProfile, "scope" | "filePath">): SubagentProfile {
|
|
474
|
+
return saveSubagentProfile(cwd, "project", profile);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export function deleteProjectSubagentProfile(cwd: string, name: string): void {
|
|
478
|
+
deleteSubagentProfile(cwd, "project", name);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
482
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
type ValidSubagentMetadataData = Record<string, unknown> & {
|
|
486
|
+
version: 1;
|
|
487
|
+
parentSessionId: string;
|
|
488
|
+
parentSessionPath: string;
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
function subagentMetadataData(entries: readonly SessionEntry[]): ValidSubagentMetadataData | null {
|
|
492
|
+
const metaEntry = entries.find((entry) => entry.type === "custom" && entry.customType === SUBAGENT_META_TYPE);
|
|
493
|
+
if (!metaEntry || metaEntry.type !== "custom" || !isRecord(metaEntry.data)) return null;
|
|
494
|
+
const data = metaEntry.data;
|
|
495
|
+
if (data.version !== 1 || typeof data.parentSessionId !== "string" || typeof data.parentSessionPath !== "string") return null;
|
|
496
|
+
return data as ValidSubagentMetadataData;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/** Restore the isolated prompt and tool scope used by a persisted subagent session. */
|
|
500
|
+
export function readSubagentSessionResources(
|
|
501
|
+
entries: readonly SessionEntry[],
|
|
502
|
+
): SubagentSessionResources | null {
|
|
503
|
+
const data = subagentMetadataData(entries);
|
|
504
|
+
if (!data) return null;
|
|
505
|
+
const snapshot = data.resourceSnapshot;
|
|
506
|
+
const loadSkills = isRecord(snapshot) && snapshot.loadSkills === true;
|
|
507
|
+
const loadExtensions = isRecord(snapshot) && snapshot.loadExtensions === true;
|
|
508
|
+
if (
|
|
509
|
+
isRecord(snapshot)
|
|
510
|
+
&& snapshot.version === 1
|
|
511
|
+
&& Array.isArray(snapshot.appendSystemPrompt)
|
|
512
|
+
&& snapshot.appendSystemPrompt.every((item) => typeof item === "string")
|
|
513
|
+
&& Array.isArray(snapshot.tools)
|
|
514
|
+
&& snapshot.tools.every((item) =>
|
|
515
|
+
typeof item === "string"
|
|
516
|
+
&& item.length > 0
|
|
517
|
+
&& !SUBAGENT_CONTROL_TOOLS.has(item)
|
|
518
|
+
&& (BUILTIN_TOOLS.has(item) || loadExtensions)
|
|
519
|
+
)
|
|
520
|
+
) {
|
|
521
|
+
return {
|
|
522
|
+
appendSystemPrompt: [...snapshot.appendSystemPrompt],
|
|
523
|
+
tools: [...new Set(snapshot.tools)],
|
|
524
|
+
loadSkills,
|
|
525
|
+
loadExtensions,
|
|
526
|
+
...(typeof snapshot.exactSystemPrompt === "string" ? { exactSystemPrompt: snapshot.exactSystemPrompt } : {}),
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
return null;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
export function withSubagentExtensionTools(
|
|
533
|
+
profileTools: readonly string[],
|
|
534
|
+
extensionToolNames: Iterable<string>,
|
|
535
|
+
): string[] {
|
|
536
|
+
return [...new Set([
|
|
537
|
+
...profileTools,
|
|
538
|
+
...[...extensionToolNames].filter((name) => !SUBAGENT_CONTROL_TOOLS.has(name)),
|
|
539
|
+
])];
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export function selectSubagentExtensionTools(
|
|
543
|
+
extensions: Iterable<{ path: string; sourceInfo?: { source?: string }; tools: Map<string, unknown> }>,
|
|
544
|
+
selectors: readonly string[],
|
|
545
|
+
): string[] {
|
|
546
|
+
const wanted = selectors.map((selector) => selector.slice(4).toLowerCase());
|
|
547
|
+
return [...extensions].flatMap((extension) => {
|
|
548
|
+
const pathName = extension.path.replaceAll("\\", "/").split("/").at(-2) ?? extension.path;
|
|
549
|
+
const sourceName = (extension.sourceInfo?.source ?? "").replace(/^npm:/, "");
|
|
550
|
+
const extensionNames = new Set([pathName.toLowerCase(), sourceName.toLowerCase()]);
|
|
551
|
+
const selected = wanted.some((selector) => {
|
|
552
|
+
if (selector === "*") return true;
|
|
553
|
+
const [extensionName, toolName] = selector.split("/", 2);
|
|
554
|
+
return extensionNames.has(extensionName) && (!toolName || extension.tools.has(toolName));
|
|
555
|
+
});
|
|
556
|
+
if (!selected) return [];
|
|
557
|
+
return [...extension.tools.keys()].filter((toolName) => wanted.some((selector) => {
|
|
558
|
+
if (selector === "*" || selector.endsWith("/*")) return selector === "*" || extensionNames.has(selector.slice(0, -2));
|
|
559
|
+
const [extensionName, selectedTool] = selector.split("/", 2);
|
|
560
|
+
return extensionNames.has(extensionName) && (!selectedTool || selectedTool === toolName);
|
|
561
|
+
}));
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
export function readSubagentRun(entries: readonly SessionEntry[], sessionId: string, sessionPath: string): SubagentRunInfo | null {
|
|
566
|
+
const data = subagentMetadataData(entries);
|
|
567
|
+
if (!data) return null;
|
|
568
|
+
const lifecycleEntry = [...entries].reverse().find((entry) =>
|
|
569
|
+
entry.type === "custom" && (entry.customType === SUBAGENT_RESULT_TYPE || entry.customType === SUBAGENT_STATUS_TYPE)
|
|
570
|
+
);
|
|
571
|
+
const resultEntry = lifecycleEntry?.type === "custom" && lifecycleEntry.customType === SUBAGENT_RESULT_TYPE
|
|
572
|
+
? lifecycleEntry
|
|
573
|
+
: undefined;
|
|
574
|
+
const result = resultEntry?.type === "custom" && isRecord(resultEntry.data) ? resultEntry.data : undefined;
|
|
575
|
+
const statusEntry = lifecycleEntry?.type === "custom" && lifecycleEntry.customType === SUBAGENT_STATUS_TYPE
|
|
576
|
+
? lifecycleEntry
|
|
577
|
+
: undefined;
|
|
578
|
+
const statusData = statusEntry?.type === "custom" && isRecord(statusEntry.data) ? statusEntry.data : undefined;
|
|
579
|
+
const persistedStatus = result && (result.status === "completed" || result.status === "failed" || result.status === "aborted")
|
|
580
|
+
? result.status
|
|
581
|
+
: statusData?.version === 1 && (statusData.status === "queued" || statusData.status === "running")
|
|
582
|
+
? statusData.status
|
|
583
|
+
: "interrupted";
|
|
584
|
+
return {
|
|
585
|
+
sessionId,
|
|
586
|
+
sessionPath,
|
|
587
|
+
parentSessionId: data.parentSessionId,
|
|
588
|
+
parentToolCallId: typeof data.parentToolCallId === "string" ? data.parentToolCallId : "",
|
|
589
|
+
profile: typeof data.profile === "string" ? data.profile : "general-purpose",
|
|
590
|
+
description: typeof data.description === "string" ? data.description : "Subagent",
|
|
591
|
+
task: typeof data.task === "string" ? data.task : "",
|
|
592
|
+
runInBackground: data.runInBackground === true,
|
|
593
|
+
status: persistedStatus,
|
|
594
|
+
createdAt: typeof data.createdAt === "string" ? data.createdAt : "",
|
|
595
|
+
...(result && typeof result.completedAt === "string" ? { completedAt: result.completedAt } : {}),
|
|
596
|
+
...(result && typeof result.result === "string" ? { result: result.result } : {}),
|
|
597
|
+
...(result && typeof result.error === "string" ? { error: result.error } : {}),
|
|
598
|
+
...(typeof data.worktreePath === "string" ? { worktreePath: data.worktreePath } : {}),
|
|
599
|
+
...(typeof data.worktreeBranch === "string" ? { worktreeBranch: data.worktreeBranch } : {}),
|
|
600
|
+
...(result && typeof result.worktreeCleanupError === "string" ? { worktreeCleanupError: result.worktreeCleanupError } : {}),
|
|
601
|
+
};
|
|
602
|
+
}
|
package/lib/tool-presets.ts
CHANGED
|
@@ -2,6 +2,8 @@ export interface ToolEntry {
|
|
|
2
2
|
name: string;
|
|
3
3
|
description: string;
|
|
4
4
|
active: boolean;
|
|
5
|
+
parameters?: Record<string, unknown>;
|
|
6
|
+
promptGuidelines?: string[];
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
export const TOOL_PRESET_VALUES = ["none", "read-only", "default", "full"] as const;
|
|
@@ -11,6 +13,8 @@ export const PRESET_NONE: string[] = [];
|
|
|
11
13
|
export const PRESET_READ_ONLY: string[] = ["read", "grep", "find", "ls"];
|
|
12
14
|
export const PRESET_DEFAULT: string[] = ["read", "bash", "edit", "write"];
|
|
13
15
|
export const PRESET_FULL: string[] = ["bash", "read", "edit", "write", "grep", "find", "ls"];
|
|
16
|
+
/** 子代理默认工具集(subagents.ts 与 AgentsConfig 共用,客户端安全模块)。 */
|
|
17
|
+
export const DEFAULT_TOOLS: string[] = ["read", "bash", "edit", "write", "grep", "find", "ls"];
|
|
14
18
|
|
|
15
19
|
const BUILTIN_TOOL_NAMES = new Set(PRESET_FULL);
|
|
16
20
|
|
package/lib/types.ts
CHANGED
|
@@ -271,6 +271,15 @@ export interface SessionInfoEntry extends SessionEntryBase {
|
|
|
271
271
|
name?: string;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
export type SubagentSessionStatus =
|
|
275
|
+
| "starting"
|
|
276
|
+
| "queued"
|
|
277
|
+
| "running"
|
|
278
|
+
| "completed"
|
|
279
|
+
| "failed"
|
|
280
|
+
| "aborted"
|
|
281
|
+
| "interrupted";
|
|
282
|
+
|
|
274
283
|
export type SessionEntry =
|
|
275
284
|
| SessionMessageEntry
|
|
276
285
|
| ThinkingLevelChangeEntry
|
|
@@ -309,6 +318,16 @@ export interface SessionInfo {
|
|
|
309
318
|
/** 最后一条 assistant 回复文本(看板卡片中间区展示用,截断),无则为空串 */
|
|
310
319
|
lastReply?: string;
|
|
311
320
|
parentSessionId?: string; // set if this session was forked from another
|
|
321
|
+
/** 会话间关系:fork 在 UI 保持顶层;仅 subagent 关系形成可见的父子树。 */
|
|
322
|
+
relation?:
|
|
323
|
+
| { kind: "fork"; originSessionId?: string }
|
|
324
|
+
| {
|
|
325
|
+
kind: "subagent";
|
|
326
|
+
parentSessionId: string;
|
|
327
|
+
profile: string;
|
|
328
|
+
description: string;
|
|
329
|
+
status: SubagentSessionStatus;
|
|
330
|
+
};
|
|
312
331
|
/** Main repo root shared by all worktrees of this cwd (cwd itself for non-git dirs).
|
|
313
332
|
* Always set by the server; optional because the client builds transient
|
|
314
333
|
* SessionInfo objects before the first refresh. Fall back to cwd. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baique/pi-web-sky",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.56",
|
|
4
4
|
"description": "Web UI for the pi coding agent — Sky skin edition (fork of @agegr/pi-web / earendil-labs pi-web, MIT)",
|
|
5
5
|
"homepage": "https://github.com/baique/pi-web-sky#readme",
|
|
6
6
|
"repository": {
|