cuelo 0.7.0 → 0.7.1
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 +7 -6
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.js +1 -1
- package/.next/required-server-files.json +1 -1
- package/.next/routes-manifest.json +6 -0
- package/.next/server/app/_global-error/page.js +3 -3
- 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/_global-error.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +2 -2
- 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 +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/api/agent/[id]/account/route.js +1 -1
- package/.next/server/app/api/agent/[id]/bash-output/route.js +1 -1
- package/.next/server/app/api/agent/[id]/events/route.js +2 -2
- package/.next/server/app/api/agent/[id]/route.js +1 -1
- package/.next/server/app/api/agent/new/route.js +1 -1
- package/.next/server/app/api/agent/running/route.js +1 -1
- package/.next/server/app/api/attachments/route.js +1 -1
- package/.next/server/app/api/auth/all-providers/route.js +1 -1
- package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -1
- package/.next/server/app/api/auth/login/[provider]/route.js +2 -2
- package/.next/server/app/api/auth/logout/[provider]/route.js +1 -1
- package/.next/server/app/api/auth/providers/route.js +1 -1
- package/.next/server/app/api/cwd/browse/route.js +1 -1
- package/.next/server/app/api/cwd/validate/route.js +1 -1
- package/.next/server/app/api/default-cwd/route.js +1 -1
- package/.next/server/app/api/display-settings/route.js +1 -1
- package/.next/server/app/api/document-text/route.js +1 -1
- package/.next/server/app/api/experiments/route.js +1 -1
- package/.next/server/app/api/file-index/route.js +1 -1
- package/.next/server/app/api/files/[...path]/route.js +1 -1
- package/.next/server/app/api/git/diff/route.js +2 -2
- package/.next/server/app/api/git/status/route.js +2 -2
- package/.next/server/app/api/gpt6/handles/route.js +1 -1
- package/.next/server/app/api/gpt6/reply/route.js +1 -1
- package/.next/server/app/api/gpt6/token/route.js +1 -1
- package/.next/server/app/api/gpt6/web6-session/route.js +1 -1
- package/.next/server/app/api/home/route.js +1 -1
- package/.next/server/app/api/live/call/[callId]/route.js +1 -1
- package/.next/server/app/api/live/call/[callId]/route.js.nft.json +1 -1
- package/.next/server/app/api/live/character-voice/route.js +1 -0
- package/.next/server/app/api/live/character-voice/route.js.nft.json +1 -0
- package/.next/server/app/api/live/character-voice/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/live/events/route.js +2 -2
- package/.next/server/app/api/live/events/route.js.nft.json +1 -1
- package/.next/server/app/api/live/offer/route.js +1 -1
- package/.next/server/app/api/live/offer/route.js.nft.json +1 -1
- package/.next/server/app/api/live/voices/route.js +1 -1
- package/.next/server/app/api/live/voices/route.js.nft.json +1 -1
- package/.next/server/app/api/lounge/events/route.js +2 -2
- package/.next/server/app/api/lounge/events/route.js.nft.json +1 -1
- package/.next/server/app/api/lounge/route.js +1 -1
- package/.next/server/app/api/lounge/route.js.nft.json +1 -1
- package/.next/server/app/api/mcp/route.js +2 -2
- package/.next/server/app/api/model-roles/route.js +1 -1
- package/.next/server/app/api/models/route.js +1 -1
- package/.next/server/app/api/models-config/catalog/route.js +1 -1
- package/.next/server/app/api/models-config/discover/route.js +1 -1
- package/.next/server/app/api/models-config/route.js +3 -3
- package/.next/server/app/api/models-config/test/route.js +1 -1
- package/.next/server/app/api/plugins/route.js +1 -1
- package/.next/server/app/api/plugins/route.js.nft.json +1 -1
- package/.next/server/app/api/project-trust/route.js +1 -1
- package/.next/server/app/api/projects/route.js +1 -1
- package/.next/server/app/api/runs/[runId]/route.js +1 -1
- package/.next/server/app/api/runs/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/auto-name/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/state/route.js +1 -1
- package/.next/server/app/api/sessions/route.js +1 -1
- package/.next/server/app/api/sessions/search/route.js +1 -1
- package/.next/server/app/api/settings/route.js +1 -1
- package/.next/server/app/api/sidecars/[service]/[...path]/route.js +1 -1
- package/.next/server/app/api/skills/check/route.js +1 -1
- package/.next/server/app/api/skills/install/route.js +2 -2
- package/.next/server/app/api/skills/route.js +1 -1
- package/.next/server/app/api/skills/search/route.js +1 -1
- package/.next/server/app/api/skills/update/route.js +1 -1
- package/.next/server/app/api/theme/route.js +1 -1
- package/.next/server/app/api/tool-image/route.js +1 -1
- package/.next/server/app/api/update-maintenance/route.js +3 -3
- package/.next/server/app/api/updates/route.js +1 -1
- package/.next/server/app/api/web-access/recovery/route.js +1 -1
- package/.next/server/app/api/web-access/route.js +1 -1
- package/.next/server/app/api/web6/consults/route.js +1 -1
- package/.next/server/app/api/worktrees/route.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 +4 -4
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/manifest.webmanifest/route.js +2 -2
- package/.next/server/app/page.js +10 -10
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/recover/page.js +2 -2
- package/.next/server/app/recover/page_client-reference-manifest.js +1 -1
- package/.next/server/app/recover.html +1 -1
- package/.next/server/app/recover.rsc +2 -2
- package/.next/server/app/recover.segments/_full.segment.rsc +2 -2
- package/.next/server/app/recover.segments/_head.segment.rsc +1 -1
- package/.next/server/app/recover.segments/_index.segment.rsc +2 -2
- package/.next/server/app/recover.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/recover.segments/recover/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/recover.segments/recover.segment.rsc +1 -1
- package/.next/server/app-paths-manifest.json +7 -6
- package/.next/server/chunks/205.js +6 -0
- package/.next/server/chunks/424.js +3 -0
- package/.next/server/chunks/4649.js +1 -0
- package/.next/server/chunks/5582.js +1 -1
- package/.next/server/chunks/6429.js +2 -2
- package/.next/server/chunks/7310.js +5 -0
- package/.next/server/chunks/9108.js +1 -1
- package/.next/server/chunks/9280.js +4 -4
- package/.next/server/middleware-build-manifest.js +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/app/_global-error/{page-701a3390117d7557.js → page-2bfa6c2cae0dc17e.js} +1 -1
- package/.next/static/chunks/app/api/agent/[id]/account/{route-701a3390117d7557.js → route-2bfa6c2cae0dc17e.js} +1 -1
- package/.next/static/chunks/app/api/agent/[id]/bash-output/{route-701a3390117d7557.js → route-2bfa6c2cae0dc17e.js} +1 -1
- package/.next/static/chunks/app/api/agent/[id]/events/{route-701a3390117d7557.js → route-2bfa6c2cae0dc17e.js} +1 -1
- package/.next/static/chunks/app/api/agent/[id]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/agent/running/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/attachments/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/auth/all-providers/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/auth/login/[provider]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/auth/providers/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/cwd/browse/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/cwd/validate/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/default-cwd/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/display-settings/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/document-text/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/experiments/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/file-index/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/files/[...path]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/git/diff/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/git/status/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/gpt6/handles/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/gpt6/reply/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/gpt6/token/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/gpt6/web6-session/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/home/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/live/call/[callId]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/live/character-voice/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/live/events/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/live/offer/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/live/voices/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/lounge/events/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/lounge/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/mcp/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/model-roles/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/models/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/models-config/catalog/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/models-config/discover/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/models-config/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/models-config/test/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/plugins/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/project-trust/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/projects/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/runs/[runId]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/runs/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/context/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/export/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/state/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sessions/search/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/settings/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/sidecars/[service]/[...path]/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/skills/check/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/skills/install/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/skills/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/skills/search/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/skills/update/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/theme/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/tool-image/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/update-maintenance/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/updates/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/web-access/recovery/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/web-access/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/web6/consults/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/{layout-89b7963cbc4da94d.js → layout-ca001f1e875e854c.js} +1 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/app/page-ce1990eb55a57ad6.js +22 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2bfa6c2cae0dc17e.js +1 -0
- package/.next/static/vl7SKOdL2Zksd2mJ3tjOQ/_buildManifest.js +1 -0
- package/.next/trace +105 -105
- package/.next/trace-build +1 -1
- package/.next/types/app/api/live/character-voice/route.ts +351 -0
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/README.md +2 -2
- package/Tools/CUELO_Setup/files/native-runtime-patch.js +1 -1
- package/Tools/OMP_Global_Config/agent/extensions/jev-runtime.ts +277 -63
- package/Tools/OMP_Global_Config/agent/extensions/lib/maker-routing.ts +68 -17
- package/Tools/OMP_Global_Config/agent/extensions/lib/routing-ledger.ts +25 -1
- package/Tools/OMP_Global_Config/agent/rules/subagent.md +12 -1
- package/Tools/OMP_Global_Config/patches/apply-core-patch.mjs +21 -0
- package/package.json +1 -1
- package/public/audio/live/ACML-1.0.txt +85 -0
- package/public/audio/live/hikari-reference.wav +0 -0
- package/public/audio/live/isana-reference.wav +0 -0
- package/public/audio/live/mio-reference.wav +0 -0
- package/public/audio/live/nova-reference.wav +0 -0
- package/public/audio/live/rin-reference.wav +0 -0
- package/public/audio/live/shion-reference.wav +0 -0
- package/public/audio/live/voices.json +275 -0
- package/public/audio/live/yuki-reference.wav +0 -0
- package/.next/server/chunks/3707.js +0 -5
- package/.next/server/chunks/6775.js +0 -6
- package/.next/static/JfkwRK2BKBsxwumh964am/_buildManifest.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/agent/new/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/agent/running/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/attachments/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/auth/all-providers/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/auth/login/[provider]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/auth/providers/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/cwd/browse/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/cwd/validate/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/default-cwd/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/display-settings/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/document-text/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/experiments/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/file-index/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/files/[...path]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/git/diff/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/git/status/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/gpt6/handles/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/gpt6/reply/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/gpt6/token/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/gpt6/web6-session/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/home/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/live/call/[callId]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/live/events/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/live/offer/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/live/voices/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/lounge/events/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/lounge/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/mcp/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/model-roles/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/models/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/models-config/catalog/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/models-config/discover/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/models-config/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/models-config/test/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/plugins/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/project-trust/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/projects/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/runs/[runId]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/runs/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/context/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/export/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/state/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sessions/search/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/settings/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/sidecars/[service]/[...path]/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/skills/check/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/skills/install/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/skills/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/skills/search/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/skills/update/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/theme/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/tool-image/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/update-maintenance/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/updates/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/web-access/recovery/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/web-access/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/web6/consults/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/api/worktrees/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-701a3390117d7557.js +0 -1
- package/.next/static/chunks/app/page-042cc56cc090bf73.js +0 -22
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-701a3390117d7557.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-701a3390117d7557.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-701a3390117d7557.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-701a3390117d7557.js +0 -1
- /package/.next/static/{JfkwRK2BKBsxwumh964am → vl7SKOdL2Zksd2mJ3tjOQ}/_ssgManifest.js +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { ExtensionAPI, ExtensionContext } from "@oh-my-pi/pi-coding-agent";
|
|
3
3
|
import { registerMakerRouting, workspaceOf, type Owner } from "./lib/maker-routing";
|
|
4
4
|
import { clearPreparedTaskSession } from "./lib/prepared-task";
|
|
5
|
-
import { createRoutingLedger, DEFAULT_LEDGER_PATH, scopedAttempts, type AttemptIdentity, type DispatchOwnership, type DispatchRecord, type OutcomeRecord, type VerdictRecord } from "./lib/routing-ledger";
|
|
5
|
+
import { createRoutingLedger, DEFAULT_LEDGER_PATH, scopedAttempts, type AttemptIdentity, type DispatchOwnership, type DispatchRecord, type OutcomeRecord, type RevisionRelation, type VerdictRecord } from "./lib/routing-ledger";
|
|
6
6
|
import {
|
|
7
7
|
advanceTodoProgressState,
|
|
8
8
|
assessTodoProgress,
|
|
@@ -335,8 +335,8 @@ interface SettledJobMeta {
|
|
|
335
335
|
agentId?: string;
|
|
336
336
|
label?: string;
|
|
337
337
|
durationMs?: number;
|
|
338
|
-
/** async job
|
|
339
|
-
status?:
|
|
338
|
+
/** 실제 async job terminal 상태. 관측한 값이 completed|failed|cancelled일 때만 있고, 없으면 미상이다(성공으로 추정하지 않는다). */
|
|
339
|
+
status?: OutcomeRecord["status"];
|
|
340
340
|
schemaStatus?: string;
|
|
341
341
|
hasData: boolean;
|
|
342
342
|
/** data.validation 맵에서 state가 unverified/pending 계열인 항목 수. */
|
|
@@ -463,7 +463,7 @@ function readSettledTaskJobs(details: unknown, content?: unknown): SettledJobMet
|
|
|
463
463
|
...(typeof record.agentId === "string" && record.agentId ? { agentId: record.agentId } : {}),
|
|
464
464
|
...(typeof record.label === "string" ? { label: record.label } : {}),
|
|
465
465
|
...(typeof record.durationMs === "number" ? { durationMs: record.durationMs } : {}),
|
|
466
|
-
...(
|
|
466
|
+
...(record.status === "completed" || record.status === "failed" || record.status === "cancelled" ? { status: record.status } : {}),
|
|
467
467
|
...(typeof schema?.status === "string" ? { schemaStatus: schema.status } : {}),
|
|
468
468
|
hasData: data !== undefined,
|
|
469
469
|
hasError: typeof schema?.error === "string" || record.status === "failed",
|
|
@@ -767,7 +767,10 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
767
767
|
const liveMakers = new Map<string, SpawnedTaskMeta[]>();
|
|
768
768
|
/** jobId → {callId, taskIndex}. settle 시 해당 child만 liveMakers에서 닫는다. */
|
|
769
769
|
const jobIndex = new Map<string, { callId: string; taskIndex: number }>();
|
|
770
|
-
/**
|
|
770
|
+
/**
|
|
771
|
+
* 완료/parked 뒤에도 같은 session에서 `write agent://` 대상으로 식별할 수 있었던 maker. 표시 이름은 별도 task 호출에서 재사용되고
|
|
772
|
+
* core가 실제 child를 Fix·Fix-2처럼 구분하므로, 키는 이름이 아니라 그 spawn(assignment)이다. 각 child의 소유 경로·identity를 따로 보존한다.
|
|
773
|
+
*/
|
|
771
774
|
const knownMakers = new Map<string, SpawnedTaskMeta>();
|
|
772
775
|
/** 이미 판정한 경계. */
|
|
773
776
|
// 발주 판정은 maker_route 한 곳에서만 수행한다.
|
|
@@ -781,11 +784,14 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
781
784
|
/** 미회신 advisory를 이미 낸 체크포인트 id. */
|
|
782
785
|
const advisedCheckpoints = new Set<string>();
|
|
783
786
|
|
|
787
|
+
/** canonical agentId가 정확히 같은 child가 우선이다. 일치하는 agentId가 없을 때만 표시 이름으로 가장 최근 child를 찾는다. */
|
|
784
788
|
function knownMakerForTarget(target: string): SpawnedTaskMeta | undefined {
|
|
789
|
+
let byName: SpawnedTaskMeta | undefined;
|
|
785
790
|
for (const owner of knownMakers.values()) {
|
|
786
791
|
if (owner.agentId === target) return owner;
|
|
792
|
+
if (owner.name === target) byName = owner;
|
|
787
793
|
}
|
|
788
|
-
return
|
|
794
|
+
return byName;
|
|
789
795
|
}
|
|
790
796
|
|
|
791
797
|
function noteCheckpoint(record: unknown): void {
|
|
@@ -862,17 +868,35 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
862
868
|
// spawn으로 실제 관측된 attempt. routing_verdict는 여기 있는 identity만 받는다.
|
|
863
869
|
// 상태를 함께 두어 실행 중 attempt를 완료로 오인하지 않게 하고, session_start에서 원장 scoped 기록으로 복원한다.
|
|
864
870
|
// ownership은 그 attempt dispatch의 소유 계약(과거 row는 null=미상), restored는 session_start 원장 복원 계열이다.
|
|
871
|
+
// sourceRevision은 그 attempt의 terminal report가 실제로 낸 revision이며, 관측하지 못했으면 null(미상)이다. 추정으로 채우지 않는다.
|
|
865
872
|
type ObservedAttempt = AttemptIdentity & {
|
|
866
873
|
name: string;
|
|
867
874
|
status: "running" | OutcomeRecord["status"];
|
|
868
875
|
ownership: DispatchOwnership | null;
|
|
869
876
|
restored: boolean;
|
|
877
|
+
sourceRevision: string | null;
|
|
870
878
|
};
|
|
871
879
|
const observedAttempts = new Map<string, ObservedAttempt>();
|
|
872
880
|
/** outcome을 이미 기록한 attempt. 같은 attempt를 두 번 소비하지 않는다. */
|
|
873
881
|
const settledAttempts = new Set<string>();
|
|
874
882
|
/** settle로 이미 소비한 async jobId. 채널(via)과 무관하게 중복 소비하지 않는다. */
|
|
875
883
|
const consumedJobs = new Set<string>();
|
|
884
|
+
/**
|
|
885
|
+
* terminal status를 싣지 못한 관측으로 정산을 보류한 job: jobId → 그 attempt와 그 실행의 시작 시각. 첫 관측의 dedupe가 뒤이은
|
|
886
|
+
* wait·`read proc://`의 권위 status 관측을 막지 않게 한다. 같은 실행 근거(snapshot row 시작 시각 일치)가 있을 때만 그 attempt에
|
|
887
|
+
* outcome을 한 번 남긴다. core는 evict 뒤 같은 jobId를 재사용하므로 jobId만으로 옛 attempt에 status를 붙이지 않는다.
|
|
888
|
+
*/
|
|
889
|
+
const statusPending = new Map<string, { attemptId: string; runStart?: number; terminalRevision?: string; durationMs?: number }>();
|
|
890
|
+
/** attempt 실행의 시작 시각: spawn·재개 binding 때 core snapshot의 exact jobId row에서 본 값. 같은 실행 판정의 근거다. */
|
|
891
|
+
const runStarts = new Map<string, number>();
|
|
892
|
+
/** 끝났지만 terminal status를 관측하지 못한 attempt. 실행 중이 아니므로 REWORK 재개를 연다. outcome은 미상으로 남는다. */
|
|
893
|
+
const unobservedEnds = new Set<string>();
|
|
894
|
+
/**
|
|
895
|
+
* 성공한 `write proc://<jobId>/kill` receipt가 가리킨 실행 중 attempt: jobId → attempt와 그 실행의 시작 시각.
|
|
896
|
+
* core cancel은 abort 요청 직후 반환하고 cancelled job은 async-result를 보내지 않는다. receipt는 종료가 아니므로, 같은 실행의
|
|
897
|
+
* snapshot row가 cancelled이고 endTime이 생긴 뒤에만 owner 경계에서 cancelled로 정산한다. 그 전에는 owner 보호를 유지한다.
|
|
898
|
+
*/
|
|
899
|
+
const pendingCancels = new Map<string, { attemptId: string; runStart: number }>();
|
|
876
900
|
/** 명시 REWORK 전송이 성공해 열린 재개 attempt. agentId → 그 전송 직후 관측한 정확한 새 jobId와 전송 시각. */
|
|
877
901
|
const resumeByAgent = new Map<string, { attemptId: string; jobId: string; sentAt: number }>();
|
|
878
902
|
/** 전송별 snapshot을 보존해 같은 actor로 겹친 DM도 서로의 기준선을 덮지 않는다. */
|
|
@@ -884,7 +908,7 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
884
908
|
const VERDICTS = ["accepted", "rework", "held"] as const;
|
|
885
909
|
type VerdictInput = {
|
|
886
910
|
sessionId: string; assignmentId: string; attemptId: string; verdict: string;
|
|
887
|
-
reason: string; revision?: string; evidenceLocators?: string[]; appliedLessons?: string[];
|
|
911
|
+
reason: string; revision?: string; integratedFrom?: string; evidenceLocators?: string[]; appliedLessons?: string[];
|
|
888
912
|
};
|
|
889
913
|
/**
|
|
890
914
|
* Main 명시 수용 판정 기록. advisory 원장에 한 줄 append할 뿐 gate도 LLM 호출도 아니다.
|
|
@@ -900,6 +924,7 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
900
924
|
const revision = (request.revision ?? "").trim();
|
|
901
925
|
const evidenceLocators = (request.evidenceLocators ?? []).map((value) => value.trim()).filter(Boolean);
|
|
902
926
|
const appliedLessons = [...new Set((request.appliedLessons ?? []).map((value) => value.trim()).filter(Boolean))];
|
|
927
|
+
const integratedFrom = (request.integratedFrom ?? "").trim();
|
|
903
928
|
if (!sessionId || !assignmentId || !attemptId) {
|
|
904
929
|
return { ok: false, error: "sessionId·assignmentId·attemptId가 모두 필요합니다. maker_route 결과가 아니라 spawn advisory의 실제 triple을 쓰세요.", knownAttemptIds: [] };
|
|
905
930
|
}
|
|
@@ -926,6 +951,19 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
926
951
|
if (request.verdict === "accepted" && observed.status !== "completed") {
|
|
927
952
|
return { ok: false, error: `accepted는 완료가 관측된 attempt에만 쓸 수 있습니다. 현재 실행 상태: ${observed.status}`, knownAttemptIds: [] };
|
|
928
953
|
}
|
|
954
|
+
// 원 revision과 검수 revision의 관계는 advisory 기록이다. 다르거나 미상이어도 막지 않고, 조용히 같은 결과로 취급하지 않도록
|
|
955
|
+
// 관계와 진단을 남긴다. integratedFrom은 Main의 명시 연결 주장일 뿐이며 실제 검수 근거는 reason·evidenceLocators가 담당한다.
|
|
956
|
+
const sourceRevision = observed.sourceRevision;
|
|
957
|
+
const revisionRelation: RevisionRelation = !sourceRevision || !revision ? "unknown"
|
|
958
|
+
: revision === sourceRevision ? "same"
|
|
959
|
+
: integratedFrom === sourceRevision ? "integrated" : "mismatch";
|
|
960
|
+
const diagnostic = revisionRelation === "mismatch"
|
|
961
|
+
? integratedFrom
|
|
962
|
+
? `integratedFrom '${integratedFrom}'이 이 attempt에서 관측한 Maker 원 revision '${sourceRevision}'과 다릅니다. 검수 revision '${revision}'은 mismatch로 기록했습니다. 이 attempt의 원 revision을 통합한 검수라면 integratedFrom='${sourceRevision}'로 다시 기록하고, 다른 attempt의 결과라면 그 attempt identity로 기록하세요.`
|
|
963
|
+
: `Maker 원 revision '${sourceRevision}'과 검수 revision '${revision}'이 다르고 연결 주장이 없어 mismatch로 기록했습니다. 통합 뒤 새 revision을 직접 검수했다면 integratedFrom='${sourceRevision}'로 연결을 명시하고 그 검수 근거를 reason·evidenceLocators에 남기세요.`
|
|
964
|
+
: revisionRelation === "unknown" && revision
|
|
965
|
+
? `이 attempt의 terminal report revision이 미관측이라 검수 revision '${revision}'과의 관계를 unknown으로 기록했습니다. 원 revision을 추정해 채우지 않습니다.`
|
|
966
|
+
: undefined;
|
|
929
967
|
const record: VerdictRecord = {
|
|
930
968
|
type: "verdict",
|
|
931
969
|
ts: new Date().toISOString(),
|
|
@@ -937,6 +975,9 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
937
975
|
jobId: observed.jobId,
|
|
938
976
|
verdict: request.verdict as VerdictRecord["verdict"],
|
|
939
977
|
revision: revision || null,
|
|
978
|
+
sourceRevision,
|
|
979
|
+
revisionRelation,
|
|
980
|
+
...(integratedFrom ? { integratedFrom } : {}),
|
|
940
981
|
evidenceLocators,
|
|
941
982
|
reason,
|
|
942
983
|
...(appliedLessons.length > 0 ? { appliedLessons } : {}),
|
|
@@ -944,20 +985,37 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
944
985
|
if (!baseLedger.append(record)) {
|
|
945
986
|
return { ok: false, error: "원장 기록에 실패했습니다(저장 오류). 판정은 남지 않았습니다.", knownAttemptIds: [] };
|
|
946
987
|
}
|
|
947
|
-
return { ok: true, record };
|
|
988
|
+
return { ok: true, record, ...(diagnostic ? { diagnostic } : {}) };
|
|
948
989
|
}
|
|
949
990
|
const routing = registerMakerRouting(pi, {
|
|
950
991
|
ledger: baseLedger,
|
|
951
992
|
owners: (ctx) => {
|
|
993
|
+
// 취소 요청 뒤 실제로 끝난 실행은 추가 조회 없이 여기서 cancelled로 정산해 그 child만 owner에서 해제한다.
|
|
994
|
+
reconcileEndedCancels(ctx);
|
|
995
|
+
// active는 그 child 자체로 판정한다. 같은 표시 이름의 다른 child가 실행 중이라는 이유로 끝난 child를 잠그지 않는다.
|
|
952
996
|
const activeTasks = [...liveMakers.values()].flat();
|
|
953
|
-
const
|
|
954
|
-
|
|
955
|
-
|
|
997
|
+
const liveTasks = new Set(activeTasks);
|
|
998
|
+
// 원장 running은 프로세스 재시작으로 끝나지 못한 row일 수 있다. core async snapshot에 지금 실행 중인
|
|
999
|
+
// job이 있을 때만 active로 보아, 끝난·죽은 attempt가 영구 잠금이 되지 않게 한다.
|
|
1000
|
+
const running = ctx.getAsyncJobSnapshot?.()?.running ?? [];
|
|
1001
|
+
// 완료로 live 목록에서 닫힌 known maker도 REWORK·후속 지시로 다시 실행 중이면 같은 소유 경로의 writer다.
|
|
1002
|
+
// 그 canonical agentId(또는 이 runtime이 관측한 그 agent attempt의 jobId)가 지금 실행 중일 때만 active다.
|
|
1003
|
+
const runningJobs = new Set(running.map((job) => job.id));
|
|
1004
|
+
const runningAgents = new Set(running.flatMap((job) => typeof job.agentId === "string" && job.agentId ? [job.agentId] : []));
|
|
1005
|
+
for (const entry of observedAttempts.values()) {
|
|
1006
|
+
if (entry.agentId && entry.jobId !== "" && runningJobs.has(entry.jobId)) runningAgents.add(entry.agentId);
|
|
1007
|
+
}
|
|
1008
|
+
// core는 cancel 즉시 그 job을 running에서 뺀다. 취소 요청 뒤 아직 끝나지 않은 실행(재개·REWORK 포함)은 계속 writer다.
|
|
1009
|
+
for (const [jobId, pending] of pendingCancels) {
|
|
1010
|
+
runningJobs.add(jobId);
|
|
1011
|
+
const agentId = observedAttempts.get(pending.attemptId)?.agentId;
|
|
1012
|
+
if (agentId) runningAgents.add(agentId);
|
|
1013
|
+
}
|
|
956
1014
|
const owners: Owner[] = [...knownMakers.values()].map((task) => ({
|
|
957
1015
|
name: task.name ?? null,
|
|
958
1016
|
primaryDeliverable: task.guard.primaryDeliverable ?? null,
|
|
959
1017
|
ownedPaths: task.guard.ownedPaths,
|
|
960
|
-
active: Boolean(task.
|
|
1018
|
+
active: liveTasks.has(task) || Boolean(task.agentId && runningAgents.has(task.agentId)),
|
|
961
1019
|
workspace: task.workspace,
|
|
962
1020
|
}));
|
|
963
1021
|
for (const task of activeTasks) {
|
|
@@ -970,19 +1028,16 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
970
1028
|
workspace: task.workspace,
|
|
971
1029
|
});
|
|
972
1030
|
}
|
|
973
|
-
// reload 전 spawn은 원장 복원 attempt로만 남는다. 이 runtime이
|
|
974
|
-
//
|
|
1031
|
+
// reload 전 spawn은 원장 복원 attempt로만 남는다. 복원 attempt는 이 runtime이 spawn한 child와 같은 child가 아니다.
|
|
1032
|
+
// assignment별 최신 attempt 하나만 owner로 두어 재작업이 소유를 중복 주장하지 않게 한다.
|
|
975
1033
|
const restored = new Map<string, ObservedAttempt>();
|
|
976
1034
|
for (const entry of observedAttempts.values()) {
|
|
977
|
-
if (
|
|
978
|
-
restored.set(entry.name || entry.assignmentId, entry);
|
|
1035
|
+
if (entry.restored) restored.set(entry.assignmentId, entry);
|
|
979
1036
|
}
|
|
980
|
-
// 원장 running은 프로세스 재시작으로 끝나지 못한 row일 수 있다. core async snapshot에 지금 실행 중인
|
|
981
|
-
// job이 있을 때만 active로 보아, 끝난·죽은 attempt가 영구 잠금이 되지 않게 한다.
|
|
982
|
-
const running = ctx.getAsyncJobSnapshot?.()?.running ?? [];
|
|
983
1037
|
for (const entry of restored.values()) {
|
|
984
|
-
|
|
985
|
-
|
|
1038
|
+
// 원장 status가 아니라 실제 snapshot이 권위다. 완료로 복원된 owner도 REWORK·후속 지시로 그 canonical agent의 job이
|
|
1039
|
+
// 지금 실행 중이면 active이고, running row라도 snapshot에 없으면 inactive다.
|
|
1040
|
+
const active = Boolean(entry.agentId && runningAgents.has(entry.agentId)) || (entry.jobId !== "" && runningJobs.has(entry.jobId));
|
|
986
1041
|
if (entry.ownership) {
|
|
987
1042
|
if (!entry.name && !active) continue;
|
|
988
1043
|
owners.push({
|
|
@@ -997,7 +1052,15 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
997
1052
|
owners.push({ name: entry.name || null, primaryDeliverable: null, ownedPaths: [], active, ownershipUnknown: true });
|
|
998
1053
|
}
|
|
999
1054
|
}
|
|
1000
|
-
|
|
1055
|
+
// placement 표시용 목록만 접는다: 실행 중 owner는 실제 child마다 모두 남기고, 실행 중인 것이 없는 이름은 가장 최근
|
|
1056
|
+
// child 하나만 후보로 보인다(복원 owner보다 이 runtime의 spawn이 최근이다). knownMakers의 child별 정보는 그대로다.
|
|
1057
|
+
const activeNames = new Set(owners.flatMap((owner) => owner.active && owner.name ? [owner.name] : []));
|
|
1058
|
+
const latestInactive = new Map<string, Owner>();
|
|
1059
|
+
for (const owner of [...owners.slice(knownMakers.size), ...owners.slice(0, knownMakers.size)]) {
|
|
1060
|
+
if (!owner.active && owner.name) latestInactive.set(owner.name, owner);
|
|
1061
|
+
}
|
|
1062
|
+
return owners.filter((owner) => owner.active || !owner.name
|
|
1063
|
+
|| (!activeNames.has(owner.name) && latestInactive.get(owner.name) === owner));
|
|
1001
1064
|
},
|
|
1002
1065
|
// legacy-pi loader가 host SDK specifier를 재작성하므로 미러의 static runtime import는 불가하다.
|
|
1003
1066
|
settings: async (ctx) => deps.findScopedSettings?.(ctx.cwd) ??
|
|
@@ -1015,7 +1078,7 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1015
1078
|
const z = pi.zod;
|
|
1016
1079
|
pi.registerTool({
|
|
1017
1080
|
name: "routing_verdict", label: "Routing Verdict", loadMode: "essential", approval: "read",
|
|
1018
|
-
description: "Main 전용 발주 수용 판정 기록(advisory). 실행 상태와 분리해 accepted·rework·held만 남기며 gate도 LLM 호출도 아니다. identity는 spawn/pre-review advisory와 maker_route 결과의 plan이 아니라 실제 spawn triple(sessionId·assignmentId·attemptId)을 쓴다. accepted·rework는 비어 있지 않은 revision과 evidenceLocators 최소 1개, reason이 필요하고 held는 revision·evidence를 생략할 수 있다. accepted는 완료가 관측된 attempt에만 쓸 수 있다. 선택 appliedLessons에는 그 attempt가 실제로 적용한 교훈의 기억 id(`<memories>`·recall·learn 결과의 `id:`)를 넣으며, 적용 근거는 evidenceLocators로 남긴다. spawn으로 관측되지 않은 attempt, stale identity, 현재 session이 아닌 identity는 기록하지 않고 오류와 알려진 attemptId 목록으로 알린다.",
|
|
1081
|
+
description: "Main 전용 발주 수용 판정 기록(advisory). 실행 상태와 분리해 accepted·rework·held만 남기며 gate도 LLM 호출도 아니다. identity는 spawn/pre-review advisory와 maker_route 결과의 plan이 아니라 실제 spawn triple(sessionId·assignmentId·attemptId)을 쓴다. accepted·rework는 비어 있지 않은 revision과 evidenceLocators 최소 1개, reason이 필요하고 held는 revision·evidence를 생략할 수 있다. accepted는 완료가 관측된 attempt에만 쓸 수 있다. revision은 Main이 실제로 검수한 revision이다. 원장은 그 attempt의 terminal report revision(sourceRevision, 미관측이면 null)과의 관계를 same·integrated·mismatch·unknown으로 함께 남기고, mismatch·unknown이면 기록한 뒤 diagnostic으로 알린다. 통합 뒤 새 revision을 검수했다면 선택 integratedFrom에 이 attempt의 원 revision을 적어 연결을 명시한다. integratedFrom은 연결 주장일 뿐이며 검수 근거는 reason·evidenceLocators가 담당한다. 선택 appliedLessons에는 그 attempt가 실제로 적용한 교훈의 기억 id(`<memories>`·recall·learn 결과의 `id:`)를 넣으며, 적용 근거는 evidenceLocators로 남긴다. spawn으로 관측되지 않은 attempt, stale identity, 현재 session이 아닌 identity는 기록하지 않고 오류와 알려진 attemptId 목록으로 알린다.",
|
|
1019
1082
|
parameters: z.object({
|
|
1020
1083
|
sessionId: z.string(),
|
|
1021
1084
|
assignmentId: z.string(),
|
|
@@ -1023,6 +1086,7 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1023
1086
|
verdict: z.string(),
|
|
1024
1087
|
reason: z.string(),
|
|
1025
1088
|
revision: z.string().optional(),
|
|
1089
|
+
integratedFrom: z.string().optional(),
|
|
1026
1090
|
evidenceLocators: z.array(z.string()).optional(),
|
|
1027
1091
|
appliedLessons: z.array(z.string()).optional(),
|
|
1028
1092
|
}) as never,
|
|
@@ -1060,6 +1124,83 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1060
1124
|
else liveMakers.delete(ref.callId);
|
|
1061
1125
|
}
|
|
1062
1126
|
}
|
|
1127
|
+
/**
|
|
1128
|
+
* attempt 하나의 실행 상태를 원장에 한 번 남기고 관측 상태를 맞춘다. 정산 jobId를 durable outcome에 남겨 reload 뒤에도 중복 소비를 막는다.
|
|
1129
|
+
* 실행 상태일 뿐 품질 판정이 아니다. sourceRevision은 Maker terminal report가 낸 원 revision을 관측한 경우에만 남긴다.
|
|
1130
|
+
*/
|
|
1131
|
+
function appendOutcome(identity: AttemptIdentity, jobId: string, status: OutcomeRecord["status"], durationMs: number | undefined, terminalRevision: string | undefined): ObservedAttempt | undefined {
|
|
1132
|
+
statusPending.delete(jobId);
|
|
1133
|
+
pendingCancels.delete(jobId);
|
|
1134
|
+
unobservedEnds.delete(identity.attemptId);
|
|
1135
|
+
consumedJobs.add(jobId);
|
|
1136
|
+
settledAttempts.add(identity.attemptId);
|
|
1137
|
+
baseLedger.append({
|
|
1138
|
+
type: "outcome",
|
|
1139
|
+
ts: new Date().toISOString(),
|
|
1140
|
+
sessionId: identity.sessionId,
|
|
1141
|
+
assignmentId: identity.assignmentId,
|
|
1142
|
+
attempt: identity.attempt,
|
|
1143
|
+
attemptId: identity.attemptId,
|
|
1144
|
+
agentId: identity.agentId,
|
|
1145
|
+
jobId,
|
|
1146
|
+
status,
|
|
1147
|
+
durationSec: durationMs === undefined ? null : Math.round(durationMs / 1000),
|
|
1148
|
+
...(terminalRevision ? { sourceRevision: terminalRevision } : {}),
|
|
1149
|
+
});
|
|
1150
|
+
const observed = observedAttempts.get(identity.attemptId);
|
|
1151
|
+
if (observed) {
|
|
1152
|
+
observed.status = status;
|
|
1153
|
+
observed.sourceRevision = terminalRevision ?? null;
|
|
1154
|
+
}
|
|
1155
|
+
return observed;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* 취소 요청한 실행의 실제 종료 여부. 같은 jobId·같은 실행(startTime 일치)의 core snapshot row가 cancelled이고 endTime이 있을 때만
|
|
1159
|
+
* 끝난 것이다. row가 없거나 다른 실행이면 판단하지 않는다(종료로 추정하지 않고 보호를 유지한다).
|
|
1160
|
+
*/
|
|
1161
|
+
function cancelEndedRow(jobId: string, ctx: ExtensionContext): { startTime: number; endTime: number } | undefined {
|
|
1162
|
+
const pending = pendingCancels.get(jobId);
|
|
1163
|
+
if (!pending) return undefined;
|
|
1164
|
+
const snapshot = ctx.getAsyncJobSnapshot?.();
|
|
1165
|
+
const row = [...(snapshot?.running ?? []), ...(snapshot?.recent ?? [])].find((entry) => entry.id === jobId);
|
|
1166
|
+
if (!row || row.startTime !== pending.runStart || row.status !== "cancelled" || typeof row.endTime !== "number") return undefined;
|
|
1167
|
+
return { startTime: row.startTime, endTime: row.endTime };
|
|
1168
|
+
}
|
|
1169
|
+
/** owner·admission 경계: 취소 요청 뒤 실제로 끝난 실행만 cancelled로 한 번 정산하고 그 child만 live owner에서 닫는다. */
|
|
1170
|
+
function reconcileEndedCancels(ctx: ExtensionContext): void {
|
|
1171
|
+
for (const [jobId, pending] of [...pendingCancels]) {
|
|
1172
|
+
const ended = cancelEndedRow(jobId, ctx);
|
|
1173
|
+
if (!ended) continue;
|
|
1174
|
+
const observed = observedAttempts.get(pending.attemptId);
|
|
1175
|
+
if (!observed || settledAttempts.has(pending.attemptId)) {
|
|
1176
|
+
pendingCancels.delete(jobId);
|
|
1177
|
+
continue;
|
|
1178
|
+
}
|
|
1179
|
+
appendOutcome(observed, jobId, "cancelled", ended.endTime - ended.startTime, undefined);
|
|
1180
|
+
// 같은 실행의 뒤 wait·read proc:// 관측은 이미 정산한 결과다.
|
|
1181
|
+
judgedReviews.add(jobId);
|
|
1182
|
+
if (resumeByAgent.get(observed.agentId)?.attemptId === pending.attemptId) resumeByAgent.delete(observed.agentId);
|
|
1183
|
+
closeSettledMakers([jobId]);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* 성공한 proc kill receipt가 가리킨 실행 중 Maker attempt를 종료 대기로 둔다. attempt는 그 jobId의 live spawn, 재개 binding,
|
|
1188
|
+
* 실행 중 관측 attempt 순으로 찾는다. 실행 시작 시각은 spawn·재개 때 기록한 값이 정본이고, 없으면 지금 exact row의 값을 쓴다.
|
|
1189
|
+
* 기록한 시작 시각과 지금 row가 다르면 다른 실행이므로 두지 않는다. 시작 시각을 모르면 같은 실행을 확인할 수 없어 두지 않는다.
|
|
1190
|
+
*/
|
|
1191
|
+
function noteCancelRequested(jobId: string, ctx: ExtensionContext): void {
|
|
1192
|
+
const ref = jobIndex.get(jobId);
|
|
1193
|
+
const spawned = ref ? liveMakers.get(ref.callId)?.find((task) => task.index === ref.taskIndex) : undefined;
|
|
1194
|
+
const attemptId = spawned?.identity?.attemptId
|
|
1195
|
+
?? [...resumeByAgent.values()].find((binding) => binding.jobId === jobId)?.attemptId
|
|
1196
|
+
?? [...observedAttempts.values()].filter((entry) => entry.status === "running" && entry.jobId === jobId).at(-1)?.attemptId;
|
|
1197
|
+
if (!attemptId || settledAttempts.has(attemptId) || observedAttempts.get(attemptId)?.status !== "running") return;
|
|
1198
|
+
const rowStart = snapshotRunStart(jobId, ctx);
|
|
1199
|
+
const recorded = runStarts.get(attemptId);
|
|
1200
|
+
const runStart = recorded ?? rowStart;
|
|
1201
|
+
if (runStart === undefined || (rowStart !== undefined && rowStart !== runStart)) return;
|
|
1202
|
+
pendingCancels.set(jobId, { attemptId, runStart });
|
|
1203
|
+
}
|
|
1063
1204
|
/**
|
|
1064
1205
|
* core는 task job을 `id: agentId`로 등록하고 소비된 row를 곧 evict하므로 재개(IRC wake) 실행이 같은 jobId를 다시 받는다.
|
|
1065
1206
|
* async-result에는 agentId도 없다. 그래서 agentId는 현재 snapshot row(id 정확 일치)에서만 읽고, 열린 REWORK receipt의
|
|
@@ -1075,9 +1216,35 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1075
1216
|
? { agentId, resumeKey: `${job.jobId}@${row.startTime}` }
|
|
1076
1217
|
: { agentId };
|
|
1077
1218
|
}
|
|
1078
|
-
/**
|
|
1219
|
+
/** 이 jobId의 현재 core snapshot row 시작 시각. core가 같은 jobId를 재사용해도 실행마다 다르다. */
|
|
1220
|
+
function snapshotRunStart(jobId: string, ctx: ExtensionContext): number | undefined {
|
|
1221
|
+
const snapshot = ctx.getAsyncJobSnapshot?.();
|
|
1222
|
+
const row = [...(snapshot?.running ?? []), ...(snapshot?.recent ?? [])].find((entry) => entry.id === jobId);
|
|
1223
|
+
return typeof row?.startTime === "number" ? row.startTime : undefined;
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* 그 실행의 실제 terminal 상태. 관측 결과의 status가 정본이다. 없으면 core snapshot의 exact jobId settled row를 쓰되,
|
|
1227
|
+
* 그 attempt 실행의 시작 시각(runStart)과 row 시작 시각이 같을 때만 같은 실행으로 본다. 아니면 undefined이며 완료로 추정하지 않는다.
|
|
1228
|
+
*/
|
|
1229
|
+
function settledStatus(job: SettledJobMeta, ctx: ExtensionContext, runStart: number | undefined): OutcomeRecord["status"] | undefined {
|
|
1230
|
+
if (job.status) return job.status;
|
|
1231
|
+
const row = ctx.getAsyncJobSnapshot?.()?.recent?.find((entry) => entry.id === job.jobId);
|
|
1232
|
+
if (!row || runStart === undefined || row.startTime !== runStart || (row.type !== undefined && row.type !== "task")) return undefined;
|
|
1233
|
+
return row.status === "completed" || row.status === "failed" || row.status === "cancelled" ? row.status : undefined;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* 처음 보는 jobId이거나, 재사용 jobId라도 아직 검수하지 않은 재개 실행이면 검수 대상이다.
|
|
1237
|
+
* status 미상으로 정산을 보류한 job은 권위 status 관측이 오면 한 번 더 통과시킨다. 어느 실행의 관측인지는 runPreReview가 가린다.
|
|
1238
|
+
*/
|
|
1079
1239
|
function takeUnjudged(jobs: SettledJobMeta[], ctx: ExtensionContext): SettledJobMeta[] {
|
|
1080
1240
|
return jobs.filter((job) => {
|
|
1241
|
+
// 취소 요청한 실행은 실제로 끝나기 전 wait·read proc://가 cancelled를 보여 줘도 정산하지 않는다(owner 보호 유지).
|
|
1242
|
+
// 끝난 뒤의 관측은 아직 owner 경계에서 정산되지 않았으면 통과시켜 같은 실행을 한 번 정산한다.
|
|
1243
|
+
if (pendingCancels.has(job.jobId)) {
|
|
1244
|
+
if (!cancelEndedRow(job.jobId, ctx)) return false;
|
|
1245
|
+
judgedReviews.add(job.jobId);
|
|
1246
|
+
return true;
|
|
1247
|
+
}
|
|
1081
1248
|
if (!judgedReviews.has(job.jobId)) {
|
|
1082
1249
|
judgedReviews.add(job.jobId);
|
|
1083
1250
|
const { resumeKey } = settledRun(job, ctx);
|
|
@@ -1085,9 +1252,12 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1085
1252
|
return true;
|
|
1086
1253
|
}
|
|
1087
1254
|
const { resumeKey } = settledRun(job, ctx);
|
|
1088
|
-
if (
|
|
1089
|
-
|
|
1090
|
-
|
|
1255
|
+
if (resumeKey && !judgedResumeRuns.has(resumeKey)) {
|
|
1256
|
+
judgedResumeRuns.add(resumeKey);
|
|
1257
|
+
return true;
|
|
1258
|
+
}
|
|
1259
|
+
const pending = statusPending.get(job.jobId);
|
|
1260
|
+
return pending !== undefined && settledStatus(job, ctx, pending.runStart) !== undefined;
|
|
1091
1261
|
});
|
|
1092
1262
|
}
|
|
1093
1263
|
async function runPreReview(
|
|
@@ -1111,8 +1281,14 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1111
1281
|
const newRun = !consumedJobs.has(job.jobId) || run.resumeKey !== undefined;
|
|
1112
1282
|
const binding = agentId ? resumeByAgent.get(agentId) : undefined;
|
|
1113
1283
|
let resumeAttemptId = binding && binding.jobId === job.jobId && newRun ? binding.attemptId : undefined;
|
|
1284
|
+
// status 미상으로 보류한 attempt는 같은 실행 근거가 있을 때만 이 관측으로 정산한다: 보류 때 기록한 그 attempt 실행의
|
|
1285
|
+
// 시작 시각과 지금 이 jobId snapshot row의 시작 시각이 같아야 한다. core는 evict 뒤 같은 jobId를 새 실행에 다시 쓴다.
|
|
1286
|
+
const pendingEntry = statusPending.get(job.jobId);
|
|
1287
|
+
const rowStart = snapshotRunStart(job.jobId, ctx);
|
|
1288
|
+
const deferred = !resumeAttemptId && pendingEntry?.runStart !== undefined && rowStart === pendingEntry.runStart
|
|
1289
|
+
? pendingEntry : undefined;
|
|
1114
1290
|
// 늦은 이벤트 자체를 새 실행으로 간주하지 않는다. 현재 snapshot에서 확인한 유일한 새 job만 잇는다.
|
|
1115
|
-
if (!resumeAttemptId && agentId && !spawned?.identity && newRun) {
|
|
1291
|
+
if (!resumeAttemptId && agentId && !spawned?.identity && newRun && !deferred) {
|
|
1116
1292
|
const pending = pendingResume.get(agentId);
|
|
1117
1293
|
const source = pending ? observedAttempts.get(pending.sourceAttemptId) : undefined;
|
|
1118
1294
|
const snapshot = pending ? ctx.getAsyncJobSnapshot?.() : undefined;
|
|
@@ -1151,38 +1327,41 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1151
1327
|
// 재개 attempt는 원 attempt의 소유 계약을 그대로 잇는다. 미상이면 필드를 만들지 않는다.
|
|
1152
1328
|
...(source.ownership ? { ownership: source.ownership } : {}),
|
|
1153
1329
|
});
|
|
1154
|
-
observedAttempts.set(identity.attemptId, { ...identity, name: source.name, status: "running", ownership: source.ownership, restored: source.restored });
|
|
1330
|
+
observedAttempts.set(identity.attemptId, { ...identity, name: source.name, status: "running", ownership: source.ownership, restored: source.restored, sourceRevision: null });
|
|
1331
|
+
if (rowStart !== undefined) runStarts.set(identity.attemptId, rowStart);
|
|
1155
1332
|
pendingResume.delete(agentId);
|
|
1156
1333
|
resumeAttemptId = identity.attemptId;
|
|
1157
1334
|
}
|
|
1158
1335
|
}
|
|
1159
|
-
// session_start에서 복원한 in-flight dispatch도 실제 jobId·agentId로 정산한다.
|
|
1336
|
+
// session_start에서 복원한 in-flight dispatch도 실제 jobId·agentId로 정산한다. 재개 binding이 자기 실행에 우선하고,
|
|
1337
|
+
// 같은 실행으로 확인된 보류 attempt가 그다음이다. 같은 실행 근거가 없는 보류 attempt에는 이 관측의 status를 붙이지 않는다.
|
|
1160
1338
|
const identity = resumeAttemptId ? observedAttempts.get(resumeAttemptId)
|
|
1339
|
+
: deferred ? observedAttempts.get(deferred.attemptId)
|
|
1161
1340
|
: spawned?.identity ?? [...observedAttempts.values()].find((entry) =>
|
|
1162
|
-
entry.status === "running" && entry.jobId === job.jobId && entry.agentId === agentId
|
|
1341
|
+
entry.status === "running" && entry.jobId === job.jobId && entry.agentId === agentId
|
|
1342
|
+
&& entry.attemptId !== pendingEntry?.attemptId);
|
|
1343
|
+
// 이 jobId의 다른 실행 row가 보이면 옛 보류는 더는 정산할 수 없다. 그 attempt의 outcome은 미상으로 남는다.
|
|
1344
|
+
if (pendingEntry && !deferred && rowStart !== undefined && rowStart !== pendingEntry.runStart) statusPending.delete(job.jobId);
|
|
1163
1345
|
// 채널과 무관하게 이미 소비한 jobId는 다시 처리하지 않고, 같은 attempt도 한 번만 소비한다.
|
|
1164
|
-
if (identity && (!consumedJobs.has(job.jobId) || resumeAttemptId !== undefined) && !settledAttempts.has(identity.attemptId)
|
|
1346
|
+
if (identity && (deferred !== undefined || !consumedJobs.has(job.jobId) || resumeAttemptId !== undefined) && !settledAttempts.has(identity.attemptId)
|
|
1165
1347
|
&& (spawned?.agent === undefined || spawned.agent === "maker")) {
|
|
1166
|
-
consumedJobs.add(job.jobId);
|
|
1167
|
-
settledAttempts.add(identity.attemptId);
|
|
1168
1348
|
if (resumeAttemptId && agentId) resumeByAgent.delete(agentId);
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
status,
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
identityNotes.push(`${spawned?.name ?? observed?.name ?? job.label ?? job.jobId} ${identity.sessionId}|${identity.assignmentId}|${identity.attemptId}`);
|
|
1349
|
+
const runStart = runStarts.get(identity.attemptId);
|
|
1350
|
+
const terminal = settledStatus(job, ctx, runStart);
|
|
1351
|
+
// schema.error는 status가 없어도 실패다. 그 밖에는 관측한 terminal 상태만 쓰고 status 부재를 완료로 읽지 않는다.
|
|
1352
|
+
const status: OutcomeRecord["status"] | undefined = terminal === "cancelled" ? "cancelled"
|
|
1353
|
+
: job.hasError || terminal === "failed" ? "failed"
|
|
1354
|
+
: terminal === "completed" ? "completed" : undefined;
|
|
1355
|
+
const terminalRevision = job.terminalRevision ?? deferred?.terminalRevision;
|
|
1356
|
+
const durationMs = job.durationMs ?? deferred?.durationMs;
|
|
1357
|
+
if (!status) {
|
|
1358
|
+
statusPending.set(job.jobId, { attemptId: identity.attemptId, ...(runStart !== undefined ? { runStart } : {}), terminalRevision, durationMs });
|
|
1359
|
+
unobservedEnds.add(identity.attemptId);
|
|
1360
|
+
identityNotes.push(`${spawned?.name ?? job.label ?? job.jobId} ${identity.sessionId}|${identity.assignmentId}|${identity.attemptId} terminal status 미관측: outcome 보류(완료로 추정하지 않음), 같은 실행으로 확인된 wait·read proc:// 관측으로만 정산`);
|
|
1361
|
+
} else {
|
|
1362
|
+
const observed = appendOutcome(identity, job.jobId, status, durationMs, terminalRevision);
|
|
1363
|
+
identityNotes.push(`${spawned?.name ?? observed?.name ?? job.label ?? job.jobId} ${identity.sessionId}|${identity.assignmentId}|${identity.attemptId}`);
|
|
1364
|
+
}
|
|
1186
1365
|
}
|
|
1187
1366
|
const todoRevisionKey = spawned && job.terminalRevision
|
|
1188
1367
|
? `${spawned.name ?? job.jobId}:${job.terminalRevision}`
|
|
@@ -1289,11 +1468,15 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1289
1468
|
observedAttempts.clear();
|
|
1290
1469
|
settledAttempts.clear();
|
|
1291
1470
|
consumedJobs.clear();
|
|
1471
|
+
pendingCancels.clear();
|
|
1472
|
+
statusPending.clear();
|
|
1473
|
+
runStarts.clear();
|
|
1474
|
+
unobservedEnds.clear();
|
|
1292
1475
|
resumeByAgent.clear();
|
|
1293
1476
|
preWriteJobs.clear();
|
|
1294
1477
|
pendingResume.clear();
|
|
1295
1478
|
for (const entry of scopedAttempts(baseLedger.read(), typeof sessionId === "string" ? sessionId : "")) {
|
|
1296
|
-
observedAttempts.set(entry.identity.attemptId, { ...entry.identity, name: entry.name, status: entry.status, ownership: entry.ownership, restored: true });
|
|
1479
|
+
observedAttempts.set(entry.identity.attemptId, { ...entry.identity, name: entry.name, status: entry.status, ownership: entry.ownership, restored: true, sourceRevision: entry.sourceRevision });
|
|
1297
1480
|
if (entry.status !== "running") settledAttempts.add(entry.identity.attemptId);
|
|
1298
1481
|
}
|
|
1299
1482
|
// durable outcome이 남긴 jobId는 reload 뒤에도 중복 소비를 막는다.
|
|
@@ -1371,7 +1554,7 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1371
1554
|
});
|
|
1372
1555
|
|
|
1373
1556
|
pi.on("tool_call", async (event, ctx) => {
|
|
1374
|
-
if (event.toolName === "task") return routing.beforeTask(event.input, ctx);
|
|
1557
|
+
if (event.toolName === "task") return routing.beforeTask(event.input, ctx, event.toolCallId);
|
|
1375
1558
|
|
|
1376
1559
|
if (event.toolName === "wait") {
|
|
1377
1560
|
const unadvised = [...pendingCheckpoints].filter(([, id]) => !advisedCheckpoints.has(id));
|
|
@@ -1531,6 +1714,12 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1531
1714
|
);
|
|
1532
1715
|
});
|
|
1533
1716
|
|
|
1717
|
+
// core는 실행한 호출·block·승인 거부·abort·skip 모두에 tool_execution_end를 낸다. 하류 guard 거절처럼 tool_result가 없는
|
|
1718
|
+
// task 호출의 예약은 여기서 그 호출 것만 푼다. spawn 성공은 tool_result(wrapper 안)가 먼저 끝나 이미 owner로 넘어갔다.
|
|
1719
|
+
pi.on("tool_execution_end", (event) => {
|
|
1720
|
+
if (event.toolName === "task") routing.releaseCall(event.toolCallId);
|
|
1721
|
+
});
|
|
1722
|
+
|
|
1534
1723
|
|
|
1535
1724
|
pi.on("tool_result", async (event, ctx) => {
|
|
1536
1725
|
if (event.toolName === "bash") {
|
|
@@ -1578,10 +1767,13 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1578
1767
|
}
|
|
1579
1768
|
}
|
|
1580
1769
|
const cancelled = fieldOf(proc, "cancelled");
|
|
1770
|
+
const killedJobId = event.toolName === "write" ? PROC_KILL_URL.exec(path.trim())?.[1] : undefined;
|
|
1581
1771
|
if (Array.isArray(cancelled)) {
|
|
1582
1772
|
for (const item of cancelled) {
|
|
1583
1773
|
const id = fieldOf(item, "id");
|
|
1584
1774
|
if (typeof id === "string") bashJobs.delete(id);
|
|
1775
|
+
// 이 호출이 직접 취소한 실행 중 Maker attempt만 종료 대기로 둔다. 거부(already_completed 등)·다른 job·read 관측은 대상이 아니다.
|
|
1776
|
+
if (id === killedJobId && fieldOf(item, "status") === "cancelled") noteCancelRequested(id, ctx);
|
|
1585
1777
|
}
|
|
1586
1778
|
}
|
|
1587
1779
|
}
|
|
@@ -1597,8 +1789,10 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1597
1789
|
const previous = targetAgentId
|
|
1598
1790
|
? [...observedAttempts.values()].filter((entry) => entry.agentId === targetAgentId).at(-1)
|
|
1599
1791
|
: undefined;
|
|
1792
|
+
// status를 관측하지 못하고 끝난 attempt도 실행 중이 아니다. 재개는 그 attempt의 outcome을 추정하지 않고 새 attempt로 연다.
|
|
1600
1793
|
if (targetAgentId && previous && /(?:^|\n)\s*REWORK\s+task_id=\S+/i.test(message)
|
|
1601
|
-
&& previous.status !== "running"
|
|
1794
|
+
&& (previous.status !== "running" || unobservedEnds.has(previous.attemptId))
|
|
1795
|
+
&& !resumeByAgent.has(targetAgentId) && !pendingResume.has(targetAgentId) && beforeWrite) {
|
|
1602
1796
|
// 성공 receipt와 전송 전 snapshot이 있는 경우에만 실제 새 job을 바인딩한다.
|
|
1603
1797
|
const { known: prior, sentAt } = beforeWrite;
|
|
1604
1798
|
const snapshot = ctx.getAsyncJobSnapshot?.();
|
|
@@ -1642,7 +1836,9 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1642
1836
|
purpose: source?.purpose ?? null,
|
|
1643
1837
|
...(previous.ownership ? { ownership: previous.ownership } : {}),
|
|
1644
1838
|
});
|
|
1645
|
-
observedAttempts.set(identity.attemptId, { ...identity, name: previous.name, status: "running", ownership: previous.ownership, restored: previous.restored });
|
|
1839
|
+
observedAttempts.set(identity.attemptId, { ...identity, name: previous.name, status: "running", ownership: previous.ownership, restored: previous.restored, sourceRevision: null });
|
|
1840
|
+
const freshStart = snapshotRunStart(fresh[0]!, ctx);
|
|
1841
|
+
if (freshStart !== undefined) runStarts.set(identity.attemptId, freshStart);
|
|
1646
1842
|
// 바인딩에 전송 직후 관측한 정확한 새 jobId를 둔다. 다른 job이 먼저 정산돼도 이 attempt를 소비하지 않는다.
|
|
1647
1843
|
resumeByAgent.set(targetAgentId, { attemptId: identity.attemptId, jobId: fresh[0]!, sentAt });
|
|
1648
1844
|
sendAdvisory(
|
|
@@ -1663,20 +1859,27 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1663
1859
|
|
|
1664
1860
|
// task 호출은 pre-dispatch 경계가 따로 있으므로 재시도 문맥을 세우지 않는다.
|
|
1665
1861
|
if (event.toolName === "task") {
|
|
1666
|
-
if (event.isError)
|
|
1862
|
+
if (event.isError) {
|
|
1863
|
+
// spawn하지 못한 task 실행 오류. 이 호출의 예약만 푼다.
|
|
1864
|
+
routing.releaseCall(event.toolCallId);
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1667
1867
|
// task spawn 성공: 여기서 live maker로 등록한다. tool_call 시점에 등록하면
|
|
1668
1868
|
// 다른 guard의 block으로 spawn이 없는데도 phantom maker가 남는다.
|
|
1669
1869
|
// 실제 attempt identity는 이 spawn의 task 호출 id·index·session으로, canonical child id는 progress row에서 캡처한다.
|
|
1670
1870
|
const sessionId = (ctx.sessionManager?.getSessionId?.() ?? "").trim();
|
|
1671
|
-
const details = event.details as { progress?: unknown; async?: { jobId?: unknown } } | undefined;
|
|
1871
|
+
const details = event.details as { progress?: unknown; async?: { jobId?: unknown }; results?: unknown } | undefined;
|
|
1672
1872
|
// progress row의 index가 tasks[] 위치와 대응한다(AgentProgress.index). row.id가 canonical child id(= agent:// target)다.
|
|
1673
1873
|
const progressAgentIds = new Map<number, string>();
|
|
1874
|
+
const failedRows = new Set<number>();
|
|
1674
1875
|
if (Array.isArray(details?.progress)) {
|
|
1675
1876
|
for (const [position, row] of details.progress.entries()) {
|
|
1676
1877
|
if (!row || typeof row !== "object") continue;
|
|
1677
|
-
const record = row as { id?: unknown; index?: unknown };
|
|
1878
|
+
const record = row as { id?: unknown; index?: unknown; status?: unknown };
|
|
1678
1879
|
if (typeof record.id !== "string" || !record.id) continue;
|
|
1679
|
-
|
|
1880
|
+
const index = typeof record.index === "number" ? record.index : position;
|
|
1881
|
+
progressAgentIds.set(index, record.id);
|
|
1882
|
+
if (record.status === "failed") failedRows.add(index);
|
|
1680
1883
|
}
|
|
1681
1884
|
}
|
|
1682
1885
|
const spawned = extractSpawnedTasks(event.input, todoProgressState.currentTodos);
|
|
@@ -1708,7 +1911,9 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1708
1911
|
task.identity = identity;
|
|
1709
1912
|
if (identity.agentId) task.agentId = identity.agentId;
|
|
1710
1913
|
if (identity.jobId) task.jobId = identity.jobId;
|
|
1711
|
-
observedAttempts.set(identity.attemptId, { ...identity, name: task.name ?? "", status: "running", ownership, restored: false });
|
|
1914
|
+
observedAttempts.set(identity.attemptId, { ...identity, name: task.name ?? "", status: "running", ownership, restored: false, sourceRevision: null });
|
|
1915
|
+
const spawnStart = identity.jobId ? snapshotRunStart(identity.jobId, ctx) : undefined;
|
|
1916
|
+
if (spawnStart !== undefined) runStarts.set(identity.attemptId, spawnStart);
|
|
1712
1917
|
identities.push(`${task.name ?? "<unnamed>"} agentId=${identity.agentId || "<unobserved>"} jobId=${identity.jobId || "<unobserved>"} ${identity.sessionId}|${identity.assignmentId}|${identity.attemptId}`);
|
|
1713
1918
|
}
|
|
1714
1919
|
if (identities.length > 0) {
|
|
@@ -1722,9 +1927,18 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1722
1927
|
),
|
|
1723
1928
|
);
|
|
1724
1929
|
}
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1930
|
+
// core는 child job을 등록한 뒤 반환하므로 시작한 child의 job은 snapshot에 있다. schedule에 실패한 child는 progress가
|
|
1931
|
+
// failed이고 job이 없다. 둘 다일 때만 시작하지 않은 child로 보고 owner에서 뺀다. snapshot 부재만으로는 빼지 않는다.
|
|
1932
|
+
// 하나도 시작하지 못하면 core는 오류가 아닌 결과에 progress·async 없이 빈 results만 싣는다(task/index.ts).
|
|
1933
|
+
const noneStarted = !Array.isArray(details?.progress) && details?.async === undefined
|
|
1934
|
+
&& Array.isArray(details?.results) && details.results.length === 0;
|
|
1935
|
+
const started = noneStarted ? [] : spawned.filter((task) => !(failedRows.has(task.index) && !ids.get(task.index)?.jobId));
|
|
1936
|
+
liveMakers.set(event.toolCallId, started);
|
|
1937
|
+
for (const task of started) {
|
|
1938
|
+
// 별도 호출이 같은 이름을 다시 써도 앞 child를 덮지 않는다. 키는 그 spawn identity다.
|
|
1939
|
+
if (task.name && (task.agent === undefined || task.agent === "maker")) {
|
|
1940
|
+
knownMakers.set(task.identity?.assignmentId ?? `${event.toolCallId}#${task.index}`, task);
|
|
1941
|
+
}
|
|
1728
1942
|
}
|
|
1729
1943
|
return;
|
|
1730
1944
|
}
|