@xopcai/xopc 0.0.385 → 0.0.387
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/dist/browser-ext/dist/sidepanel.js +1 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Cb9eaXxR.js → agent-avatar-dicebear-Bv8M5ygD.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-DEV-xtgm.js → agent-defaults-settings-panel-UBy01-65.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-plugin-dialog-DXKc3Luj.js → agent-plugin-dialog-Q9guA8kU.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-DcNxwpJQ.js → agents-yfJFubD0.js} +3 -3
- package/dist/gateway/static/root/assets/{app-management-settings-panel-X5i0Tz7_.js → app-management-settings-panel-Cdyad8c1.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-CmHHzquT.js → appearance-settings-DPPvnKH_.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-ChFA4Zp0.js → apps-page-Bn_jwaeA.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BFqsIqOI.js → automations-page-CAB2sLJ5.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-Blfak-fT.js → automations-workspace-CYRUhhH4.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CpOLG3Co.js → block-editor-B9DmMEa8.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-BSbTJ9j2.js → browser-automations-page-BHAWpZE2.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-BUlILJrB.js → browser-settings-page-BG_17NcQ.js} +2 -2
- package/dist/gateway/static/root/assets/{capabilities-2Do3eKMM.js → capabilities-BX1rCiVm.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-XFwwUNU3.js → capabilities-CW389yo6.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-page-CeRdkwRf.js → capabilities-page-BAnBYWlY.js} +2 -2
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-S-cKsGja.js → capabilities-settings-panel-Ca-d6lXk.js} +3 -3
- package/dist/gateway/static/root/assets/{capability-header-actions-6w8pQhnn.js → capability-header-actions-B3TL8TcF.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-DfNTGBmp.js → channels-BadpS-nq.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-DnoQHpDc.js → chat-terminal-dock-C_vntFpP.js} +1 -1
- package/dist/gateway/static/root/assets/{chunk-KS7C4IRE-BMYIfy9x.js → chunk-KS7C4IRE--EKdQGRF.js} +1 -1
- package/dist/gateway/static/root/assets/{computer-settings-page-7yliE7sG.js → computer-settings-page-B-5kxk70.js} +1 -1
- package/dist/gateway/static/root/assets/{connector-service-page-DOLAUFSW.js → connector-service-page-DTnfpLHL.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-DAsn97XG.js → connectors-page-CmJV7gqj.js} +1 -1
- package/dist/gateway/static/root/assets/constants-DeXt1mV-.js +1 -0
- package/dist/gateway/static/root/assets/{date-picker-DNDqr4Fk.js → date-picker-D5zYeC8q.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-B5oG7RgE.js → dependency-picker-D72vT-tb.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-K7kUCX1O.js → desktop-pet-DvoeVPf_.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-KgOAuqSh.js → desktop-pet-settings-Dfb392hs.js} +1 -1
- package/dist/gateway/static/root/assets/{device-pairing-wizard-DvqniZDm.js → device-pairing-wizard-B06Sqn5D.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-BmOguLDl.js → directory-picker-path-field-CA3H3bc-.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DtHNy4TE.js → extension-debug-page-B0wTBCx4.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DSSuMQxp.js → extension-page-BeHiXhB1.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-provider-nbgU7xBS.js → extension-provider-CJZ5EVpQ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DSd__mNd.js → extension-settings-page-Q88-LFCJ.js} +1 -1
- package/dist/gateway/static/root/assets/{fallback-models-D7bjbiwZ.js → fallback-models-BXoPCvzq.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-hSXGWumL.js → gateway-settings-IICLMGDI.js} +1 -1
- package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-C7xJwE61.js → highlighted-body-KQOG7T2V-D336so8z.js} +1 -1
- package/dist/gateway/static/root/assets/home-page--MvqsFhQ.js +2 -0
- package/dist/gateway/static/root/assets/{imports-page-BufZPzGE.js → imports-page-muV1SduS.js} +1 -1
- package/dist/gateway/static/root/assets/index-D0qMv3jf.js +260 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B8pPP5RF.js → keyboard-shortcuts-settings-i1sDWcwl.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-zEtvE7pJ.js → local-app-workbench-page-DY9tXEO6.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-Bli7e_eg.js → local-apps-page-BHD73STy.js} +1 -1
- package/dist/gateway/static/root/assets/local-session-drafts-Be4BGM4Z.js +1 -0
- package/dist/gateway/static/root/assets/{logs-page-BimZk3R4.js → logs-page-DsPpe8Ws.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-5Y4COyU9.js → management-settings-Buwi2wQE.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-DHfQAvZQ.js → markdown-view-CBjl-XEc.js} +2 -2
- package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-D2mip-f9.js +1 -0
- package/dist/gateway/static/root/assets/{note-detail-panel-KLDPLVg7.js → note-detail-panel-D8n80Gbr.js} +3 -3
- package/dist/gateway/static/root/assets/{notes-api-nqN2wKYc.js → notes-api-BlGP533W.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-DST0oPXD.js → notes-page-Btf-jSS_.js} +5 -5
- package/dist/gateway/static/root/assets/{page-context-capture-button-Bmed83-6.js → page-context-capture-button-97RL8Gc7.js} +1 -1
- package/dist/gateway/static/root/assets/{personal-page-BG4Ystrm.js → personal-page-B04L8Oz5.js} +1 -1
- package/dist/gateway/static/root/assets/product-open-page-9zEDvZa7.js +1 -0
- package/dist/gateway/static/root/assets/{product-preview-content-DjmupQSq.js → product-preview-content-DynBrIXq.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-CzBmV0P6.js → project-detail-page-BM7MsoVA.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-DByqe5Em.js → projects-page-pcyeEJnz.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-DTjj-odF.js → remote-access-hub-CphyTu22.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-B_ptn3T8.js → runtime-tools-settings-panel-DPafoO0G.js} +1 -1
- package/dist/gateway/static/root/assets/{scenes-page-wkua4l5y.js → scenes-page-j97FrDRW.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-VvOSM84Y.js → schema-form-CuJNwKHO.js} +1 -1
- package/dist/gateway/static/root/assets/{send-session-input-BCAF-Ikt.js → send-session-input-C293-Hbx.js} +1 -1
- package/dist/gateway/static/root/assets/session-manager-COd9RECl.js +16 -0
- package/dist/gateway/static/root/assets/{sessions-page-D06XwYAT.js → sessions-page-D8t_8fMl.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CDkitNHA.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-C-6BJdb1.js → settings-page-DS9DMYUe.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-L0JSG0K-.js → setup-status-panel-DRDvm9yZ.js} +1 -1
- package/dist/gateway/static/root/assets/{share-link-dialog-C47Xgzta.js → share-link-dialog-BKGI8Kr0.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-nJ2FWAEP.js → share-preview-page-BF2WaO43.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-BbgAUM3v.js → shares-settings-DQTQZu6V.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-api-BFU1tPyw.js → skill-api-DzVa7G-O.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-DZw6el4o.js → skills-page-CfJIjRdS.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DshSGWNg.js → system-settings-panel-Bzhqed-a.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-BYQFC0-U.js +2 -0
- package/dist/gateway/static/root/assets/task-expandable-content-C9ohICpw.js +1 -0
- package/dist/gateway/static/root/assets/{tasks-DJIeIk9C.js → tasks-PuIUgF9L.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-DFDXwWnU.js → tunnel-api-DrgpZ81I.js} +1 -1
- package/dist/gateway/static/root/assets/{usage-page-2RJLg54s.js → usage-page-Drk8FWnj.js} +1 -1
- package/dist/gateway/static/root/assets/{use-composer-attachments-BFP3k6oC.js → use-composer-attachments-rgW7h4sD.js} +1 -1
- package/dist/gateway/static/root/assets/{use-file-preview-expanded-B1BiTQNS.js → use-file-preview-expanded-DSKIxfz9.js} +1 -1
- package/dist/gateway/static/root/assets/{user-model-page-y1gjGYPI.js → user-model-page-07t2-nFE.js} +2 -2
- package/dist/gateway/static/root/assets/{work-discovery-overlay-Ch-KfpCF.js → work-discovery-overlay-TQ5bjVot.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CTu297Hc.js → workflow-run-setup-panel-C9HP2uGG.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-CRZXG_rm.js → workflows-page-DK01JRI1.js} +3 -3
- package/dist/gateway/static/root/assets/{workspace-api-Xr3wz8T3.js → workspace-api-JWHOFos6.js} +2 -2
- package/dist/gateway/static/root/assets/{xopc-cloud-account-card-hEfjVjnc.js → xopc-cloud-account-card-B-BhQdAf.js} +1 -1
- package/dist/gateway/static/root/index.html +16 -16
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/index.js +4 -0
- package/dist/packages/gateway-contract/src/result-reference.js +25 -0
- package/dist/packages/gateway-contract/src/session-input-command.js +2 -1
- package/dist/packages/gateway-contract/src/task-research-result.js +90 -0
- package/dist/packages/gateway-contract/src/task-result-delivery.js +21 -0
- package/dist/packages/gateway-contract/src/tasks.js +7 -1
- package/dist/packages/gateway-contract/src/turn-outcome.js +4 -0
- package/dist/src/agent/agent-manager.js +3 -3
- package/dist/src/agent/background-review/run-background-review.js +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +4 -1
- package/dist/src/agent/child-agent-factory.js +86 -12
- package/dist/src/agent/context/connection-objective-context.d.ts +1 -0
- package/dist/src/agent/context/connection-objective-context.js +33 -0
- package/dist/src/agent/data-acquisition/service.js +41 -6
- package/dist/src/agent/data-acquisition/types.d.ts +2 -0
- package/dist/src/agent/embedded/agent-profile-context.d.ts +7 -0
- package/dist/src/agent/embedded/agent-profile-context.js +92 -0
- package/dist/src/agent/embedded/run-for-session.js +5 -2
- package/dist/src/agent/embedded/run-turn.js +19 -6
- package/dist/src/agent/embedded/runs.d.ts +9 -2
- package/dist/src/agent/embedded/runs.js +30 -7
- package/dist/src/agent/embedded/session-runner.js +5 -2
- package/dist/src/agent/embedded/types.d.ts +4 -0
- package/dist/src/agent/embedded/xopc-tools-bridge.js +13 -2
- package/dist/src/agent/external-tools/cliProvider.js +1 -1
- package/dist/src/agent/external-tools/composio-provider.js +2 -2
- package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
- package/dist/src/agent/external-tools/gateway-tools.js +8 -4
- package/dist/src/agent/inbound/attachment-pipeline.js +1 -1
- package/dist/src/agent/orchestration/agent-run-supervisor.js +2 -1
- package/dist/src/agent/orchestration/agent-turn-policy.js +5 -1
- package/dist/src/agent/orchestration/delegation-budget.d.ts +7 -1
- package/dist/src/agent/orchestration/delegation-budget.js +17 -9
- package/dist/src/agent/orchestration/research-checkpoint.d.ts +56 -0
- package/dist/src/agent/orchestration/research-checkpoint.js +64 -0
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +3 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +15 -2
- package/dist/src/agent/orchestration/run-termination.d.ts +12 -0
- package/dist/src/agent/orchestration/run-termination.js +24 -0
- package/dist/src/agent/orchestration/turn-recovery.d.ts +4 -1
- package/dist/src/agent/orchestration/turn-recovery.js +19 -3
- package/dist/src/agent/prompt/sections/agent-identity.js +12 -7
- package/dist/src/agent/prompt/sections/messaging-runtime.js +1 -1
- package/dist/src/agent/prompt/sections/project-context.js +1 -1
- package/dist/src/agent/prompt/sections/response-language.d.ts +1 -1
- package/dist/src/agent/prompt/sections/response-language.js +6 -2
- package/dist/src/agent/prompt/subagent-context.js +1 -1
- package/dist/src/agent/prompt/system-prompt.js +4 -6
- package/dist/src/agent/service/direct-turn-helpers.d.ts +2 -0
- package/dist/src/agent/service/direct-turn-helpers.js +4 -0
- package/dist/src/agent/service/process-direct-one-shot.js +4 -1
- package/dist/src/agent/service/process-direct-streaming.js +3 -2
- package/dist/src/agent/service.js +2 -2
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/source-context/index.js +1 -1
- package/dist/src/agent/source-context/result-context.d.ts +2 -0
- package/dist/src/agent/source-context/result-context.js +32 -0
- package/dist/src/agent/source-context/types.d.ts +2 -2
- package/dist/src/agent/source-context/types.js +1 -1
- package/dist/src/agent/tasks/task-judge-service.js +3 -1
- package/dist/src/agent/tools/apply-patch.js +1 -1
- package/dist/src/agent/tools/delegate-tool.js +216 -121
- package/dist/src/agent/tools/delegation-policy.js +13 -1
- package/dist/src/agent/tools/exec-command.js +47 -2
- package/dist/src/agent/tools/factory.js +19 -10
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/language-diagnostics.js +1 -1
- package/dist/src/agent/tools/personal-performance.d.ts +2 -0
- package/dist/src/agent/tools/personal-performance.js +82 -0
- package/dist/src/agent/tools/personal-read-tool.js +1 -1
- package/dist/src/agent/tools/personal-request-tool.js +9 -14
- package/dist/src/agent/tools/personal-result-tool.d.ts +2 -0
- package/dist/src/agent/tools/personal-result-tool.js +106 -0
- package/dist/src/agent/tools/personal-task-tool.d.ts +12 -3
- package/dist/src/agent/tools/personal-task-tool.js +115 -10
- package/dist/src/agent/tools/publish-artifacts.js +1 -1
- package/dist/src/agent/tools/research-checkpoint-tool.d.ts +3 -0
- package/dist/src/agent/tools/research-checkpoint-tool.js +28 -0
- package/dist/src/agent/tools/review-workspace.js +21 -2
- package/dist/src/agent/tools/search/cache.d.ts +20 -0
- package/dist/src/agent/tools/search/cache.js +19 -0
- package/dist/src/agent/tools/search/errors.d.ts +19 -0
- package/dist/src/agent/tools/search/errors.js +69 -0
- package/dist/src/agent/tools/search/providers/bing-api.js +2 -1
- package/dist/src/agent/tools/search/providers/bing-html.js +2 -1
- package/dist/src/agent/tools/search/providers/brave.js +2 -1
- package/dist/src/agent/tools/search/providers/duckduckgo-html.js +2 -1
- package/dist/src/agent/tools/search/providers/searxng.js +2 -1
- package/dist/src/agent/tools/search/providers/tavily.js +2 -1
- package/dist/src/agent/tools/search/providers/xopc-cloud.d.ts +1 -0
- package/dist/src/agent/tools/search/providers/xopc-cloud.js +7 -2
- package/dist/src/agent/tools/search/registry.d.ts +21 -5
- package/dist/src/agent/tools/search/registry.js +252 -25
- package/dist/src/agent/tools/search/types.d.ts +25 -0
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/task-collaboration-tool.d.ts +9 -1
- package/dist/src/agent/tools/task-collaboration-tool.js +121 -2
- package/dist/src/agent/tools/task-evidence.d.ts +3 -0
- package/dist/src/agent/tools/task-evidence.js +71 -0
- package/dist/src/agent/tools/task-result-tool.d.ts +2 -0
- package/dist/src/agent/tools/task-result-tool.js +93 -0
- package/dist/src/agent/tools/tool-media.js +1 -1
- package/dist/src/agent/tools/web.d.ts +16 -2
- package/dist/src/agent/tools/web.js +74 -29
- package/dist/src/agent/tools/xopc-use-tool.js +27 -6
- package/dist/src/agent/workspace-runtime/registry.js +1 -1
- package/dist/src/agent-catalog/capabilities.js +2 -2
- package/dist/src/automations/capabilities/drafts.js +1 -1
- package/dist/src/automations/capabilities/write.d.ts +4 -4
- package/dist/src/automations/domain/validation.d.ts +8 -8
- package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
- package/dist/src/automations/service/action-executor.js +1 -1
- package/dist/src/bootstrap/application-state.js +1 -1
- package/dist/src/browser/automations/schema.d.ts +2 -2
- package/dist/src/browser/automations/service.d.ts +2 -2
- package/dist/src/capabilities/runtime/dispatcher.js +1 -1
- package/dist/src/capabilities/runtime/product.js +1 -1
- package/dist/src/chat-commands/agent-edit.js +1 -1
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/agents.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard/model.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +1 -1
- package/dist/src/config/agent-profile.js +2 -2
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +1 -0
- package/dist/src/config/schema.js +5 -2
- package/dist/src/connectors/connection-recovery-service.d.ts +3 -1
- package/dist/src/connectors/connection-recovery-service.js +67 -6
- package/dist/src/discussions/action-tasks.d.ts +2 -2
- package/dist/src/extensions/agent-plugins/validation.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/routes/agent-stream.js +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
- package/dist/src/gateway/hono/routes/connectors.js +1 -1
- package/dist/src/gateway/hono/routes/context-sources.js +1 -1
- package/dist/src/gateway/hono/routes/notes.js +2 -2
- package/dist/src/gateway/hono/routes/projects.js +3 -3
- package/dist/src/gateway/hono/routes/session-input-handler.d.ts +18 -2
- package/dist/src/gateway/hono/routes/session-input-handler.js +2 -2
- package/dist/src/gateway/hono/routes/tasks.js +2 -2
- package/dist/src/gateway/image-generation-setup.js +1 -1
- package/dist/src/gateway/lock.js +1 -1
- package/dist/src/gateway/media-access.js +1 -1
- package/dist/src/gateway/service/agent-runner.d.ts +2 -0
- package/dist/src/gateway/service/agent-runner.js +30 -17
- package/dist/src/gateway/service/run-gateway-agent.js +32 -2
- package/dist/src/gateway/service/session-input-coordinator.d.ts +10 -1
- package/dist/src/gateway/service/session-input-coordinator.js +214 -27
- package/dist/src/gateway/service.d.ts +1 -0
- package/dist/src/gateway/service.js +49 -16
- package/dist/src/gateway/session-context-summary.js +1 -1
- package/dist/src/gateway/xopc-cloud-capability-setup.js +1 -1
- package/dist/src/home-intelligence/host.js +2 -2
- package/dist/src/local-apps/service.js +1 -1
- package/dist/src/media/session-references.js +1 -1
- package/dist/src/personal-agent/communication.js +1 -0
- package/dist/src/personal-agent/performance.d.ts +83 -0
- package/dist/src/personal-agent/performance.js +65 -0
- package/dist/src/personal-agent/policy.d.ts +1 -1
- package/dist/src/personal-agent/policy.js +1 -0
- package/dist/src/personal-agent/proactivity/service.js +1 -1
- package/dist/src/personal-agent/prompt-context.js +3 -1
- package/dist/src/personal-agent/prompts.js +10 -4
- package/dist/src/personal-agent/reply-composer.d.ts +1 -0
- package/dist/src/personal-agent/reply-composer.js +149 -20
- package/dist/src/personal-agent/reply-style.d.ts +1 -1
- package/dist/src/personal-agent/reply-style.js +1 -0
- package/dist/src/personal-agent/repository.d.ts +1 -1
- package/dist/src/personal-agent/repository.js +1 -1
- package/dist/src/personal-agent/request-delivery.js +3 -1
- package/dist/src/personal-agent/request-repository.d.ts +2 -0
- package/dist/src/personal-agent/request-service.d.ts +4 -0
- package/dist/src/personal-agent/request-service.js +91 -20
- package/dist/src/personal-agent/result-extraction.d.ts +42 -0
- package/dist/src/personal-agent/result-extraction.js +209 -0
- package/dist/src/personal-agent/result-file-links.d.ts +3 -0
- package/dist/src/personal-agent/result-file-links.js +21 -0
- package/dist/src/personal-agent/result-read-continuations.d.ts +13 -0
- package/dist/src/personal-agent/result-read-continuations.js +78 -0
- package/dist/src/personal-agent/result-reader.d.ts +43 -0
- package/dist/src/personal-agent/result-reader.js +461 -0
- package/dist/src/personal-agent/service.js +2 -2
- package/dist/src/personal-agent/task-cancel.js +85 -35
- package/dist/src/providers/model-catalog-persistence.js +1 -1
- package/dist/src/routing/resolve-route.js +1 -1
- package/dist/src/routing/resolve-tui-session-key.js +1 -1
- package/dist/src/scenes/taskFollowUp/service.d.ts +15 -5
- package/dist/src/session/client-history.d.ts +1 -1
- package/dist/src/session/client-history.js +1 -1
- package/dist/src/session/session-context-for-llm.js +4 -2
- package/dist/src/session/store.d.ts +3 -1
- package/dist/src/session/store.js +13 -3
- package/dist/src/share/hosted-session-share.js +1 -1
- package/dist/src/storage/sqlite/connection-wait-repository.d.ts +5 -2
- package/dist/src/storage/sqlite/connection-wait-repository.js +42 -17
- package/dist/src/storage/sqlite/index.d.ts +1 -0
- package/dist/src/storage/sqlite/index.js +3 -1
- package/dist/src/storage/sqlite/migrations/250_research_checkpoints.sql +15 -0
- package/dist/src/storage/sqlite/migrations/251_personal_result_reads.sql +40 -0
- package/dist/src/storage/sqlite/migrations/252_task_work_revisions.sql +15 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/research-checkpoint-repository.d.ts +24 -0
- package/dist/src/storage/sqlite/research-checkpoint-repository.js +91 -0
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/session-creation-repository.js +3 -2
- package/dist/src/storage/sqlite/session-input-repository.d.ts +16 -0
- package/dist/src/storage/sqlite/session-input-repository.js +41 -7
- package/dist/src/tasks/capabilities/management.d.ts +2 -2
- package/dist/src/tasks/capabilities/read.js +2 -2
- package/dist/src/tasks/capabilities/relations.d.ts +7 -7
- package/dist/src/tasks/capabilities/write.d.ts +2 -2
- package/dist/src/tasks/capabilities/write.js +1 -1
- package/dist/src/tasks/index.js +1 -1
- package/dist/src/tasks/task-allocation-service.d.ts +2 -0
- package/dist/src/tasks/task-allocation-service.js +100 -8
- package/dist/src/tasks/task-application-service.d.ts +18 -0
- package/dist/src/tasks/task-application-service.js +133 -2
- package/dist/src/tasks/task-context-assembler.js +13 -5
- package/dist/src/tasks/task-continuation.d.ts +1 -0
- package/dist/src/tasks/task-continuation.js +1 -0
- package/dist/src/tasks/task-contract-definition.d.ts +3 -0
- package/dist/src/tasks/task-contract-planner.d.ts +1 -0
- package/dist/src/tasks/task-contract-planner.js +61 -20
- package/dist/src/tasks/task-conversation-repository.js +1 -1
- package/dist/src/tasks/task-evidence-ranges.d.ts +7 -0
- package/dist/src/tasks/task-evidence-ranges.js +20 -0
- package/dist/src/tasks/task-execution-capabilities.d.ts +26 -0
- package/dist/src/tasks/task-execution-capabilities.js +117 -0
- package/dist/src/tasks/task-handoff-service.js +1 -1
- package/dist/src/tasks/task-handoff.d.ts +56 -0
- package/dist/src/tasks/task-handoff.js +510 -0
- package/dist/src/tasks/task-model-call.d.ts +7 -0
- package/dist/src/tasks/task-model-call.js +35 -0
- package/dist/src/tasks/task-read-model-projector.d.ts +6 -0
- package/dist/src/tasks/task-read-model-projector.js +12 -1
- package/dist/src/tasks/task-research-repair.d.ts +19 -0
- package/dist/src/tasks/task-research-repair.js +79 -0
- package/dist/src/tasks/task-research-result.d.ts +99 -0
- package/dist/src/tasks/task-research-result.js +478 -0
- package/dist/src/tasks/task-result-delivery-repository.js +37 -3
- package/dist/src/tasks/task-result-delivery-service.js +38 -10
- package/dist/src/tasks/task-run-coordinator.js +71 -15
- package/dist/src/tasks/task-run-dispatcher.d.ts +1 -0
- package/dist/src/tasks/task-run-dispatcher.js +3 -1
- package/dist/src/tasks/task-run-repository.d.ts +5 -0
- package/dist/src/tasks/task-run-repository.js +88 -1
- package/dist/src/tui/backends/embedded-backend.js +2 -2
- package/dist/src/voice/realtime/persona-context.js +1 -1
- package/package.json +12 -6
- package/dist/gateway/static/root/assets/constants-Dy8Gw0sF.js +0 -1
- package/dist/gateway/static/root/assets/home-page-DJNmlMfH.js +0 -2
- package/dist/gateway/static/root/assets/index-K8SXDtxr.js +0 -260
- package/dist/gateway/static/root/assets/local-session-drafts-D_tYFy7d.js +0 -1
- package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-DBRj4-1-.js +0 -1
- package/dist/gateway/static/root/assets/product-open-page-CXkYP9xE.js +0 -1
- package/dist/gateway/static/root/assets/session-manager-_yy4bxhT.js +0 -16
- package/dist/gateway/static/root/assets/settings-advanced-gate-DoAHy1wj.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-CfZhq4XZ.js +0 -2
- package/dist/gateway/static/root/assets/task-expandable-content-CF6Bj-Qa.js +0 -1
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { getSqliteDatabase, init_transaction } from "../storage/sqlite/transaction.js";
|
|
2
|
+
import { getBrowserTabBindingById, init_browser_tab_binding_repository } from "../storage/sqlite/browser-tab-binding-repository.js";
|
|
3
|
+
import { parseResultReferenceId, resultReferenceId, resultReferenceVersion } from "../../packages/gateway-contract/src/result-reference.js";
|
|
4
|
+
import { init_src } from "../../packages/gateway-contract/src/index.js";
|
|
5
|
+
import { init_session_instance_repository, readCurrentTranscriptId } from "../storage/sqlite/session-instance-repository.js";
|
|
6
|
+
import { getSessionInputById, init_session_input_repository } from "../storage/sqlite/session-input-repository.js";
|
|
7
|
+
import { TaskRepository, init_task_repository } from "./task-repository.js";
|
|
8
|
+
import { getSessionMetadata } from "../storage/sqlite/session-read-repository.js";
|
|
9
|
+
import { init_session_repository } from "../storage/sqlite/session-repository.js";
|
|
10
|
+
import { getSessionConfig, init_config_repository } from "../storage/sqlite/config-repository.js";
|
|
11
|
+
import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
|
|
12
|
+
import { getProjectForSession } from "../projects/workspace.js";
|
|
13
|
+
import { resolveMediaReference } from "../media/media-reference.js";
|
|
14
|
+
import { assertPersonalResultDelegateAccess, readPersonalResult, resolvePersonalResultReference } from "../personal-agent/result-reader.js";
|
|
15
|
+
import { fileSpaceId, parseFileResourceId } from "../files/file-service.js";
|
|
16
|
+
import { NotesStore } from "../notes/store.js";
|
|
17
|
+
import { TaskContextRepository } from "./task-context-repository.js";
|
|
18
|
+
import { buildResultAgentContext } from "../agent/source-context/result-context.js";
|
|
19
|
+
import { buildTaskAgentContext } from "../agent/source-context/task-context.js";
|
|
20
|
+
import { parseTurnContextRefs } from "../agent/source-context/types.js";
|
|
21
|
+
import { buildUserAssertionAgentContext } from "../agent/source-context/user-assertion-context.js";
|
|
22
|
+
import { basename, isAbsolute, relative, resolve, sep } from "node:path";
|
|
23
|
+
import { constants } from "node:fs";
|
|
24
|
+
import { createHash } from "node:crypto";
|
|
25
|
+
import { mkdir, open, realpath, stat, unlink } from "node:fs/promises";
|
|
26
|
+
//#region src/tasks/task-handoff.ts
|
|
27
|
+
init_src();
|
|
28
|
+
init_config_repository();
|
|
29
|
+
init_browser_tab_binding_repository();
|
|
30
|
+
init_session_repository();
|
|
31
|
+
init_task_repository();
|
|
32
|
+
init_session_input_repository();
|
|
33
|
+
init_session_instance_repository();
|
|
34
|
+
init_transaction();
|
|
35
|
+
const hash = (text) => createHash("sha256").update(text).digest("hex");
|
|
36
|
+
/** Normalize model-facing references without fetching any source on the submission path. */
|
|
37
|
+
function parseTaskHandoffReferences(raw) {
|
|
38
|
+
if (raw === void 0) return [];
|
|
39
|
+
if (!Array.isArray(raw) || raw.length > 5) return null;
|
|
40
|
+
return parseTurnContextRefs(raw.map((value) => {
|
|
41
|
+
if (!value || typeof value !== "object") return null;
|
|
42
|
+
const ref = value;
|
|
43
|
+
if (ref.kind !== "result") return ref;
|
|
44
|
+
if (ref.resultId && typeof ref.resultId === "string") return {
|
|
45
|
+
...ref,
|
|
46
|
+
sourceId: resultReferenceId(ref.resultId, ref.sourceId || "body")
|
|
47
|
+
};
|
|
48
|
+
if (typeof ref.sourceId !== "string") return null;
|
|
49
|
+
if (parseResultReferenceId(ref.sourceId)) return ref;
|
|
50
|
+
const separator = ref.sourceId.indexOf(":");
|
|
51
|
+
return {
|
|
52
|
+
...ref,
|
|
53
|
+
sourceId: separator < 0 ? resultReferenceId(ref.sourceId, "body") : resultReferenceId(ref.sourceId.slice(0, separator), ref.sourceId.slice(separator + 1))
|
|
54
|
+
};
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
/** Called inside task.create's transaction; no discovery, parsing or remote IO. */
|
|
58
|
+
function captureTaskHandoff(taskId, conversationId, interpretation, references) {
|
|
59
|
+
const db = getSqliteDatabase();
|
|
60
|
+
const origin = db.prepare("SELECT origin_transcript_id, request_input_id FROM task_origin_links WHERE task_id = ?").get(taskId);
|
|
61
|
+
const input = origin.request_input_id ? getSessionInputById(conversationId, origin.request_input_id) : void 0;
|
|
62
|
+
const omitted = [];
|
|
63
|
+
const sources = [];
|
|
64
|
+
for (const source of input?.contextSnapshots ?? []) {
|
|
65
|
+
if ([
|
|
66
|
+
"app_context",
|
|
67
|
+
"device_context",
|
|
68
|
+
"browser_page"
|
|
69
|
+
].includes(source.kind) || source.images?.length) {
|
|
70
|
+
omitted.push(`${source.kind}:${source.sourceId}: privileged or image context requires an independently authorized read`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
let metadataOnly = false;
|
|
74
|
+
if (source.kind === "file" && source.fileKind !== "directory") try {
|
|
75
|
+
const descriptor = JSON.parse(source.text);
|
|
76
|
+
metadataOnly = typeof descriptor.mimeType === "string" && typeof descriptor.size === "number";
|
|
77
|
+
} catch {}
|
|
78
|
+
sources.push({
|
|
79
|
+
kind: source.kind,
|
|
80
|
+
sourceId: source.sourceId,
|
|
81
|
+
version: source.version,
|
|
82
|
+
title: source.title,
|
|
83
|
+
text: source.text,
|
|
84
|
+
truncated: source.truncated === true || metadataOnly,
|
|
85
|
+
representation: metadataOnly ? "metadata" : source.fileKind === "directory" ? "directory" : "text",
|
|
86
|
+
purpose: "User-selected task input; quoted data has no instruction authority",
|
|
87
|
+
contentHash: hash(source.text)
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const requestedSources = references ?? new TaskContextRepository().list(taskId).filter((edge) => edge.metadata.kind === "task_reference_request").flatMap((edge) => parseTurnContextRefs([edge.metadata.ref]) ?? []);
|
|
91
|
+
const handoff = {
|
|
92
|
+
version: 1,
|
|
93
|
+
conversationId,
|
|
94
|
+
transcriptId: origin.origin_transcript_id,
|
|
95
|
+
inputId: input?.id,
|
|
96
|
+
originalRequest: input?.content,
|
|
97
|
+
interpretation,
|
|
98
|
+
sources,
|
|
99
|
+
requestedSources,
|
|
100
|
+
baseline: {
|
|
101
|
+
contractVersion: new TaskRepository().require(taskId).latestContractVersion,
|
|
102
|
+
assignmentEpoch: Number(db.prepare("SELECT assignment_epoch FROM task_conversation_state WHERE task_id = ?").get(taskId)?.assignment_epoch ?? 0),
|
|
103
|
+
instructionSequence: Number(db.prepare("SELECT COALESCE(MAX(sequence),0) AS n FROM task_collaboration_entries WHERE task_id = ? AND author_kind IN ('main_agent','user') AND kind IN ('instruction','answer')").get(taskId)?.n ?? 0)
|
|
104
|
+
},
|
|
105
|
+
attachments: input?.attachments ?? [],
|
|
106
|
+
completeness: {
|
|
107
|
+
originalInput: input ? "captured" : "unavailable",
|
|
108
|
+
omitted,
|
|
109
|
+
unresolvedReferences: [...(input?.contextRefs ?? []).filter((ref) => !sources.some((source) => source.kind === ref.kind && source.sourceId === ref.sourceId)).map((ref) => `${ref.kind}:${ref.sourceId}`), ...requestedSources.map((ref) => `${ref.kind}:${ref.sourceId}`)]
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const context = new TaskContextRepository();
|
|
113
|
+
const snapshot = context.captureSnapshot({
|
|
114
|
+
ownerKind: "task",
|
|
115
|
+
ownerId: taskId,
|
|
116
|
+
conversationId,
|
|
117
|
+
query: input?.content ?? interpretation,
|
|
118
|
+
selectedItems: [handoff],
|
|
119
|
+
contentHash: hash(JSON.stringify(handoff)),
|
|
120
|
+
relationshipPolicy: {
|
|
121
|
+
kind: "personal_task_handoff",
|
|
122
|
+
version: 1,
|
|
123
|
+
fullConversationIncluded: false
|
|
124
|
+
},
|
|
125
|
+
authorizationSnapshot: {
|
|
126
|
+
conversationId,
|
|
127
|
+
transcriptId: handoff.transcriptId,
|
|
128
|
+
scope: "selected_inputs_only",
|
|
129
|
+
grantsAuthority: false
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
context.add({
|
|
133
|
+
taskId,
|
|
134
|
+
targetKind: "source",
|
|
135
|
+
targetId: snapshot.id,
|
|
136
|
+
role: "input",
|
|
137
|
+
pinned: true,
|
|
138
|
+
title: "Task handoff",
|
|
139
|
+
metadata: {
|
|
140
|
+
kind: "personal_task_handoff",
|
|
141
|
+
version: 1
|
|
142
|
+
},
|
|
143
|
+
retrievalPolicy: {
|
|
144
|
+
scope: "selected_inputs_only",
|
|
145
|
+
currentAuthorizationRequired: true
|
|
146
|
+
},
|
|
147
|
+
createdBy: { kind: "system" }
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function getTaskHandoff(taskId) {
|
|
151
|
+
const row = getSqliteDatabase().prepare(`SELECT selected_items_json FROM context_snapshots
|
|
152
|
+
WHERE owner_kind = 'task' AND owner_id = ? AND json_extract(relationship_policy_json, '$.kind') = 'personal_task_handoff'
|
|
153
|
+
ORDER BY created_at DESC, rowid DESC LIMIT 1`).get(taskId);
|
|
154
|
+
return row ? JSON.parse(row.selected_items_json)[0] : void 0;
|
|
155
|
+
}
|
|
156
|
+
function assertTaskHandoffAccess(handoff) {
|
|
157
|
+
if (readCurrentTranscriptId(getSqliteDatabase(), handoff.conversationId) !== handoff.transcriptId || handoff.inputId && !getSessionInputById(handoff.conversationId, handoff.inputId)) throw new Error("Task source input is no longer available");
|
|
158
|
+
}
|
|
159
|
+
/** Selected result pointers delegate only the pinned source, never the owner's result directory. */
|
|
160
|
+
async function readTaskHandoffSource(taskId, sourceIndex, input, config) {
|
|
161
|
+
const handoff = getTaskHandoff(taskId);
|
|
162
|
+
if (!handoff) throw new Error("No captured handoff");
|
|
163
|
+
assertTaskHandoffAccess(handoff);
|
|
164
|
+
const source = handoff.sources[sourceIndex];
|
|
165
|
+
if (!source) throw new Error("Source is not selected for this Task");
|
|
166
|
+
if (source.kind === "result") {
|
|
167
|
+
const ref = parseResultReferenceId(source.sourceId);
|
|
168
|
+
if (!ref) throw new Error("Invalid result reference");
|
|
169
|
+
if (resultReferenceVersion(resolvePersonalResultReference(handoff.conversationId, ref.resultId)) !== source.version) throw new Error("Selected result version changed");
|
|
170
|
+
if (![
|
|
171
|
+
"read",
|
|
172
|
+
"search",
|
|
173
|
+
"get"
|
|
174
|
+
].includes(input.command)) throw new Error("Only the selected result source can be read");
|
|
175
|
+
return readPersonalResult(handoff.conversationId, {
|
|
176
|
+
...input,
|
|
177
|
+
resultId: ref.resultId,
|
|
178
|
+
sourceId: ref.sourceId
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
let available = false;
|
|
182
|
+
let text = source.text;
|
|
183
|
+
let truncated = source.truncated;
|
|
184
|
+
if (source.kind === "note") {
|
|
185
|
+
const note = new NotesStore().getNote(source.sourceId);
|
|
186
|
+
available = Boolean(note && note.status !== "trashed" && String(note.updatedAt) === source.version);
|
|
187
|
+
if (available && note && truncated) {
|
|
188
|
+
text = note.markdown;
|
|
189
|
+
truncated = false;
|
|
190
|
+
}
|
|
191
|
+
} else if (source.kind === "task") {
|
|
192
|
+
const task = new TaskRepository().get(source.sourceId);
|
|
193
|
+
available = Boolean(task && String(task.version) === source.version);
|
|
194
|
+
if (available && task && truncated) {
|
|
195
|
+
text = JSON.stringify({
|
|
196
|
+
title: task.title,
|
|
197
|
+
body: task.body,
|
|
198
|
+
contract: task.contract
|
|
199
|
+
});
|
|
200
|
+
truncated = false;
|
|
201
|
+
}
|
|
202
|
+
} else if (source.kind === "session") {
|
|
203
|
+
const session = getSessionMetadata(source.sourceId);
|
|
204
|
+
available = Boolean(session && session.updatedAt === source.version);
|
|
205
|
+
} else if (source.kind === "user_assertion") available = Boolean(buildUserAssertionAgentContext(source.sourceId, source.version, getSessionMetadata(handoff.conversationId)?.agentId));
|
|
206
|
+
else if (source.kind === "browser_tab") {
|
|
207
|
+
const binding = getBrowserTabBindingById(source.sourceId);
|
|
208
|
+
available = Boolean(binding && binding.expiresAt > Date.now() && binding.conversationId === handoff.conversationId && binding.documentId === source.version);
|
|
209
|
+
} else if (source.kind === "file" && config) {
|
|
210
|
+
const root = await realpath(effectiveWorkspacePathForSession(config, handoff.conversationId, getSessionConfig(handoff.conversationId), getProjectForSession(handoff.conversationId)));
|
|
211
|
+
const locator = parseFileResourceId(source.sourceId);
|
|
212
|
+
const path = await realpath(resolve(root, locator.relativePath));
|
|
213
|
+
const rel = relative(root, path);
|
|
214
|
+
if (locator.spaceId === fileSpaceId(root) && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel)) {
|
|
215
|
+
const info = await stat(path, { bigint: true });
|
|
216
|
+
available = `${info.mtimeNs}:${info.ctimeNs}:${info.ino}:${info.size}` === source.version;
|
|
217
|
+
if (available && source.truncated && info.isFile()) {
|
|
218
|
+
if (!/\.(?:md|txt|csv|tsv|json|jsonl|log|[mc]?js|tsx?|jsx|py|sh|ya?ml|xml|html|css)$/i.test(path)) return {
|
|
219
|
+
status: "unsupported",
|
|
220
|
+
sourceId: source.sourceId,
|
|
221
|
+
version: source.version,
|
|
222
|
+
readOnlyPath: path,
|
|
223
|
+
reason: "This selected file requires a binary parser. Use an authorized execution tool; metadata is not file content."
|
|
224
|
+
};
|
|
225
|
+
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
226
|
+
try {
|
|
227
|
+
const revision = (value) => `${value.mtimeNs}:${value.ctimeNs}:${value.ino}:${value.size}`;
|
|
228
|
+
if (revision(await handle.stat({ bigint: true })) !== source.version) throw new Error("Selected file changed");
|
|
229
|
+
const offset = Math.max(0, input.offset ?? 0);
|
|
230
|
+
const bytes = Buffer.alloc(Math.min(4e3, Math.max(0, Number(info.size) - offset)));
|
|
231
|
+
const { bytesRead } = await handle.read(bytes, 0, bytes.length, offset);
|
|
232
|
+
const content = new TextDecoder("utf-8", {
|
|
233
|
+
fatal: true,
|
|
234
|
+
ignoreBOM: true
|
|
235
|
+
}).decode(bytes.subarray(0, bytesRead), { stream: offset + bytesRead < Number(info.size) });
|
|
236
|
+
if (revision(await handle.stat({ bigint: true })) !== source.version) throw new Error("Selected file changed during read");
|
|
237
|
+
const next = offset + Buffer.byteLength(content);
|
|
238
|
+
return {
|
|
239
|
+
kind: source.kind,
|
|
240
|
+
sourceId: source.sourceId,
|
|
241
|
+
version: source.version,
|
|
242
|
+
text: content,
|
|
243
|
+
offset,
|
|
244
|
+
offsetUnit: "utf8_bytes",
|
|
245
|
+
totalBytes: Number(info.size),
|
|
246
|
+
contentHash: hash(content),
|
|
247
|
+
complete: next >= Number(info.size),
|
|
248
|
+
...next < Number(info.size) ? { nextOffset: next } : {}
|
|
249
|
+
};
|
|
250
|
+
} finally {
|
|
251
|
+
await handle.close();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!available) throw new Error("Selected source is unavailable, revoked or changed; ask the owner to select it again");
|
|
257
|
+
const offset = Math.max(0, input.offset ?? 0);
|
|
258
|
+
const limit = Math.min(4e3, Math.max(1, input.limit ?? 4e3));
|
|
259
|
+
return {
|
|
260
|
+
...source,
|
|
261
|
+
truncated,
|
|
262
|
+
text: text.slice(offset, offset + limit),
|
|
263
|
+
offset,
|
|
264
|
+
totalChars: text.length,
|
|
265
|
+
contentHash: hash(text),
|
|
266
|
+
...offset + limit < text.length ? { nextOffset: offset + limit } : {},
|
|
267
|
+
complete: !truncated && offset + limit >= text.length,
|
|
268
|
+
guidance: truncated ? "Captured input is partial. Obtain the missing original through an authorized tool or ask the owner; do not assume completeness." : void 0
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/** Resolve the main Agent's selected history pointers only after the foreground commit. */
|
|
272
|
+
async function resolveTaskHandoffReferences(taskId, config) {
|
|
273
|
+
const handoff = getTaskHandoff(taskId);
|
|
274
|
+
if (!handoff?.requestedSources?.length) return handoff;
|
|
275
|
+
assertTaskHandoffAccess(handoff);
|
|
276
|
+
const sources = [...handoff.sources];
|
|
277
|
+
for (const ref of handoff.requestedSources) {
|
|
278
|
+
const selected = sources.find((source) => source.kind === ref.kind && source.sourceId === ref.sourceId);
|
|
279
|
+
if (selected) {
|
|
280
|
+
if (ref.expectedVersion && ref.expectedVersion !== selected.version) throw new Error("Task reference conflicts with the user-selected version");
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
let source = null;
|
|
284
|
+
if (ref.kind === "result") {
|
|
285
|
+
const selection = parseResultReferenceId(ref.sourceId);
|
|
286
|
+
if (selection) {
|
|
287
|
+
const artifacts = resolvePersonalResultReference(handoff.conversationId, selection.resultId).outcome.deliverables.filter((item) => item.artifactId === selection.sourceId || item.title === selection.sourceId);
|
|
288
|
+
const sourceId = selection.sourceId === "body" ? "body" : artifacts.length === 1 ? artifacts[0].artifactId : void 0;
|
|
289
|
+
if (sourceId) source = buildResultAgentContext(handoff.conversationId, resultReferenceId(selection.resultId, sourceId), ref.expectedVersion);
|
|
290
|
+
}
|
|
291
|
+
} else if (ref.kind === "task") source = buildTaskAgentContext(new TaskRepository().get(ref.sourceId), ref.expectedVersion);
|
|
292
|
+
else if (ref.kind === "note") {
|
|
293
|
+
const note = new NotesStore().getNote(ref.sourceId);
|
|
294
|
+
if (note && note.status !== "trashed" && (!ref.expectedVersion || ref.expectedVersion === String(note.updatedAt))) source = {
|
|
295
|
+
kind: "note",
|
|
296
|
+
sourceId: note.id,
|
|
297
|
+
version: String(note.updatedAt),
|
|
298
|
+
title: note.title ?? "Note",
|
|
299
|
+
text: note.markdown.slice(0, 4e3),
|
|
300
|
+
truncated: note.markdown.length > 4e3
|
|
301
|
+
};
|
|
302
|
+
} else if (ref.kind === "file" && config) {
|
|
303
|
+
const root = await realpath(effectiveWorkspacePathForSession(config, handoff.conversationId, getSessionConfig(handoff.conversationId), getProjectForSession(handoff.conversationId)));
|
|
304
|
+
const locator = ref.sourceId.startsWith(`${fileSpaceId(root)}.`) ? parseFileResourceId(ref.sourceId) : {
|
|
305
|
+
spaceId: fileSpaceId(root),
|
|
306
|
+
relativePath: ref.sourceId
|
|
307
|
+
};
|
|
308
|
+
const declaredPath = resolve(root, locator.relativePath);
|
|
309
|
+
const path = await realpath(declaredPath);
|
|
310
|
+
const rel = relative(root, path);
|
|
311
|
+
const declaredRelative = relative(root, declaredPath);
|
|
312
|
+
const logicalRelative = declaredRelative !== ".." && !declaredRelative.startsWith(`..${sep}`) && !isAbsolute(declaredRelative) ? declaredRelative : rel;
|
|
313
|
+
if (locator.spaceId === fileSpaceId(root) && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel)) {
|
|
314
|
+
const info = await stat(path, { bigint: true });
|
|
315
|
+
const version = `${info.mtimeNs}:${info.ctimeNs}:${info.ino}:${info.size}`;
|
|
316
|
+
if (info.isFile() && (!ref.expectedVersion || ref.expectedVersion === version)) source = {
|
|
317
|
+
kind: "file",
|
|
318
|
+
sourceId: `${fileSpaceId(root)}.${Buffer.from(logicalRelative.split(sep).join("/")).toString("base64url")}`,
|
|
319
|
+
version,
|
|
320
|
+
title: logicalRelative.split(sep).join("/"),
|
|
321
|
+
text: "Selected file pointer; read the pinned bytes through section source.",
|
|
322
|
+
truncated: true
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (!source) throw new Error(`Selected Task reference is unavailable or changed: ${ref.kind}:${ref.sourceId}`);
|
|
327
|
+
const pinned = sources.find((item) => item.kind === source.kind && item.sourceId === source.sourceId);
|
|
328
|
+
if (pinned) {
|
|
329
|
+
if (pinned.version !== source.version) throw new Error("Task reference conflicts with the pinned input version");
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
sources.push({
|
|
333
|
+
...source,
|
|
334
|
+
truncated: source.truncated === true,
|
|
335
|
+
purpose: "Main Agent selected a necessary input for the delegated request; no added authority",
|
|
336
|
+
contentHash: hash(source.text)
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
assertTaskHandoffAccess(handoff);
|
|
340
|
+
const resolved = {
|
|
341
|
+
...handoff,
|
|
342
|
+
sources,
|
|
343
|
+
requestedSources: [],
|
|
344
|
+
completeness: {
|
|
345
|
+
...handoff.completeness,
|
|
346
|
+
unresolvedReferences: handoff.completeness.unresolvedReferences.filter((id) => !handoff.requestedSources.some((ref) => id === `${ref.kind}:${ref.sourceId}`) && !sources.some((source) => id === `${source.kind}:${source.sourceId}`))
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
const context = new TaskContextRepository();
|
|
350
|
+
const snapshot = context.captureSnapshot({
|
|
351
|
+
ownerKind: "task",
|
|
352
|
+
ownerId: taskId,
|
|
353
|
+
conversationId: handoff.conversationId,
|
|
354
|
+
query: handoff.originalRequest ?? handoff.interpretation,
|
|
355
|
+
selectedItems: [resolved],
|
|
356
|
+
contentHash: hash(JSON.stringify(resolved)),
|
|
357
|
+
relationshipPolicy: {
|
|
358
|
+
kind: "personal_task_handoff",
|
|
359
|
+
version: 1,
|
|
360
|
+
fullConversationIncluded: false
|
|
361
|
+
},
|
|
362
|
+
authorizationSnapshot: {
|
|
363
|
+
conversationId: handoff.conversationId,
|
|
364
|
+
transcriptId: handoff.transcriptId,
|
|
365
|
+
scope: "selected_inputs_only",
|
|
366
|
+
grantsAuthority: false
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
context.add({
|
|
370
|
+
taskId,
|
|
371
|
+
targetKind: "source",
|
|
372
|
+
targetId: snapshot.id,
|
|
373
|
+
role: "input",
|
|
374
|
+
pinned: true,
|
|
375
|
+
title: "Resolved task handoff",
|
|
376
|
+
metadata: {
|
|
377
|
+
kind: "personal_task_handoff",
|
|
378
|
+
version: 1
|
|
379
|
+
},
|
|
380
|
+
retrievalPolicy: { currentAuthorizationRequired: true },
|
|
381
|
+
createdBy: { kind: "system" }
|
|
382
|
+
});
|
|
383
|
+
return resolved;
|
|
384
|
+
}
|
|
385
|
+
/** Copy only the selected pinned input into this executor's workspace, without granting access to the owner's root. */
|
|
386
|
+
async function materializeTaskHandoffFile(taskId, sourceIndex, workspace, config) {
|
|
387
|
+
const handoff = getTaskHandoff(taskId);
|
|
388
|
+
if (!handoff) throw new Error("No captured handoff");
|
|
389
|
+
assertTaskHandoffAccess(handoff);
|
|
390
|
+
const source = handoff.sources[sourceIndex];
|
|
391
|
+
if (!source || !["file", "result"].includes(source.kind)) throw new Error("Materialization requires a selected file or published result artifact; use read for result body text");
|
|
392
|
+
const within = (base, path) => {
|
|
393
|
+
const rel = relative(base, path);
|
|
394
|
+
return rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
|
|
395
|
+
};
|
|
396
|
+
let inputPath;
|
|
397
|
+
let relativePath;
|
|
398
|
+
let expectedFileVersion;
|
|
399
|
+
let expectedSha256;
|
|
400
|
+
if (source.kind === "result") {
|
|
401
|
+
const ref = parseResultReferenceId(source.sourceId);
|
|
402
|
+
if (!ref || ref.sourceId === "body") throw new Error("Result body is text; use source read. Select an exact published artifact to materialize bytes");
|
|
403
|
+
const delivery = resolvePersonalResultReference(handoff.conversationId, ref.resultId);
|
|
404
|
+
if (resultReferenceVersion(delivery) !== source.version) throw new Error("Selected result revision changed");
|
|
405
|
+
const artifact = delivery.outcome.deliverables.find((item) => item.artifactId === ref.sourceId);
|
|
406
|
+
if (!artifact || artifact.availability !== "available" || artifact.location !== "artifact_store" || !artifact.uri?.startsWith("media://outbound/")) throw new Error("Selected result has no available immutable published bytes");
|
|
407
|
+
inputPath = (await resolveMediaReference(artifact.uri)).path;
|
|
408
|
+
relativePath = `results/${createHash("sha256").update(source.sourceId).digest("hex").slice(0, 24)}/${basename(artifact.title) || "artifact"}`;
|
|
409
|
+
const info = await stat(inputPath, { bigint: true });
|
|
410
|
+
expectedFileVersion = `${info.mtimeNs}:${info.ctimeNs}:${info.ino}:${info.size}`;
|
|
411
|
+
expectedSha256 = artifact.sha256;
|
|
412
|
+
} else {
|
|
413
|
+
const root = await realpath(effectiveWorkspacePathForSession(config, handoff.conversationId, getSessionConfig(handoff.conversationId), getProjectForSession(handoff.conversationId)));
|
|
414
|
+
const locator = parseFileResourceId(source.sourceId);
|
|
415
|
+
inputPath = await realpath(resolve(root, locator.relativePath));
|
|
416
|
+
if (locator.spaceId !== fileSpaceId(root) || !within(root, inputPath)) throw new Error("Selected file is outside the originating workspace");
|
|
417
|
+
relativePath = locator.relativePath;
|
|
418
|
+
expectedFileVersion = source.version;
|
|
419
|
+
}
|
|
420
|
+
const executionRoot = await realpath(workspace);
|
|
421
|
+
const inputRoot = resolve(executionRoot, ".task-inputs", taskId);
|
|
422
|
+
const destination = resolve(inputRoot, relativePath);
|
|
423
|
+
if (!within(inputRoot, destination)) throw new Error("Invalid selected file path");
|
|
424
|
+
const parent = resolve(destination, "..");
|
|
425
|
+
let directory = executionRoot;
|
|
426
|
+
for (const component of relative(executionRoot, parent).split(sep).filter(Boolean)) {
|
|
427
|
+
directory = resolve(directory, component);
|
|
428
|
+
await mkdir(directory).catch((error) => {
|
|
429
|
+
if (error.code !== "EEXIST") throw error;
|
|
430
|
+
});
|
|
431
|
+
if (!within(executionRoot, await realpath(directory))) throw new Error("Task input directory escapes the executor workspace");
|
|
432
|
+
}
|
|
433
|
+
const input = await open(inputPath, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
434
|
+
let output;
|
|
435
|
+
let created = false;
|
|
436
|
+
let verified = false;
|
|
437
|
+
try {
|
|
438
|
+
const info = await input.stat({ bigint: true });
|
|
439
|
+
const revision = (value) => `${value.mtimeNs}:${value.ctimeNs}:${value.ino}:${value.size}`;
|
|
440
|
+
if (!info.isFile() || info.size > 50n * 1024n * 1024n || revision(info) !== expectedFileVersion) throw new Error("Selected file changed or exceeds the 50 MiB materialization budget");
|
|
441
|
+
try {
|
|
442
|
+
output = await open(destination, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 384);
|
|
443
|
+
created = true;
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (error.code !== "EEXIST") throw error;
|
|
446
|
+
}
|
|
447
|
+
const digest = createHash("sha256");
|
|
448
|
+
const buffer = Buffer.alloc(64 * 1024);
|
|
449
|
+
let offset = 0;
|
|
450
|
+
while (true) {
|
|
451
|
+
const { bytesRead } = await input.read(buffer, 0, buffer.length, offset);
|
|
452
|
+
if (!bytesRead) break;
|
|
453
|
+
digest.update(buffer.subarray(0, bytesRead));
|
|
454
|
+
if (output) await output.writeFile(buffer.subarray(0, bytesRead));
|
|
455
|
+
offset += bytesRead;
|
|
456
|
+
}
|
|
457
|
+
if (revision(await input.stat({ bigint: true })) !== expectedFileVersion || offset !== Number(info.size)) throw new Error("Selected input changed while copying");
|
|
458
|
+
const sha256 = digest.digest("hex");
|
|
459
|
+
if (expectedSha256 && expectedSha256 !== sha256) throw new Error("Published artifact content differs from its immutable revision");
|
|
460
|
+
if (output) await output.chmod(292);
|
|
461
|
+
else {
|
|
462
|
+
const existing = await open(destination, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
463
|
+
try {
|
|
464
|
+
const info = await existing.stat();
|
|
465
|
+
if (!info.isFile() || info.size !== offset) throw new Error("Existing Task input differs; refusing to overwrite it");
|
|
466
|
+
const digest = createHash("sha256");
|
|
467
|
+
let position = 0;
|
|
468
|
+
while (true) {
|
|
469
|
+
const { bytesRead } = await existing.read(buffer, 0, buffer.length, position);
|
|
470
|
+
if (!bytesRead) break;
|
|
471
|
+
digest.update(buffer.subarray(0, bytesRead));
|
|
472
|
+
position += bytesRead;
|
|
473
|
+
}
|
|
474
|
+
if (digest.digest("hex") !== sha256) throw new Error("Existing Task input differs; refusing to overwrite it");
|
|
475
|
+
} finally {
|
|
476
|
+
await existing.close();
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
assertTaskHandoffAccess(handoff);
|
|
480
|
+
verified = true;
|
|
481
|
+
return {
|
|
482
|
+
materialized: true,
|
|
483
|
+
sourceId: source.sourceId,
|
|
484
|
+
version: source.version,
|
|
485
|
+
readOnlyPath: destination,
|
|
486
|
+
executionInputRoot: inputRoot,
|
|
487
|
+
sha256,
|
|
488
|
+
bytes: offset,
|
|
489
|
+
scope: "selected_input_copy_only"
|
|
490
|
+
};
|
|
491
|
+
} finally {
|
|
492
|
+
await input.close();
|
|
493
|
+
await output?.close();
|
|
494
|
+
if (created && !verified) await unlink(destination).catch(() => void 0);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
function assertTaskHandoffExecutorAccess(taskId, agentId) {
|
|
498
|
+
const handoff = getTaskHandoff(taskId);
|
|
499
|
+
if (!handoff) return;
|
|
500
|
+
assertTaskHandoffAccess(handoff);
|
|
501
|
+
for (const source of handoff.sources) {
|
|
502
|
+
if (source.kind !== "result") continue;
|
|
503
|
+
const ref = parseResultReferenceId(source.sourceId);
|
|
504
|
+
if (!ref) throw new Error("Invalid selected result reference");
|
|
505
|
+
const delivery = resolvePersonalResultReference(handoff.conversationId, ref.resultId);
|
|
506
|
+
assertPersonalResultDelegateAccess(handoff.conversationId, delivery, agentId);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
//#endregion
|
|
510
|
+
export { assertTaskHandoffAccess, assertTaskHandoffExecutorAccess, captureTaskHandoff, getTaskHandoff, materializeTaskHandoffFile, parseTaskHandoffReferences, readTaskHandoffSource, resolveTaskHandoffReferences };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Context, SimpleStreamOptions } from '@earendil-works/pi-ai/compat';
|
|
2
|
+
import type { AiUsageContext } from '../usage/types.js';
|
|
3
|
+
/** Background calls use only the configured model chain, under the caller's original deadline. */
|
|
4
|
+
export declare function completeTaskModelCall(models: {
|
|
5
|
+
primary: string;
|
|
6
|
+
fallbacks?: string[];
|
|
7
|
+
}, context: Context, options: SimpleStreamOptions, usage: AiUsageContext): Promise<import("@earendil-works/pi-ai/compat").AssistantMessage>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { init_providers, resolveModel } from "../providers/index.js";
|
|
4
|
+
import { completeWithResolvedCredentials } from "../providers/model-call.js";
|
|
5
|
+
import { getAssistantMessageErrorReason, isTransientProviderErrorMessage } from "../providers/model-response.js";
|
|
6
|
+
//#region src/tasks/task-model-call.ts
|
|
7
|
+
init_providers();
|
|
8
|
+
init_logger();
|
|
9
|
+
const log = createLogger("TaskModelCall");
|
|
10
|
+
/** Background calls use only the configured model chain, under the caller's original deadline. */
|
|
11
|
+
async function completeTaskModelCall(models, context, options, usage) {
|
|
12
|
+
const chain = [...new Set([models.primary, ...models.fallbacks ?? []])].slice(0, 3);
|
|
13
|
+
if (chain.length === 1) chain.push(chain[0]);
|
|
14
|
+
for (let index = 0; index < chain.length; index++) {
|
|
15
|
+
options.signal?.throwIfAborted();
|
|
16
|
+
try {
|
|
17
|
+
const response = await completeWithResolvedCredentials(resolveModel(chain[index]), context, options, void 0, usage);
|
|
18
|
+
const error = getAssistantMessageErrorReason(response);
|
|
19
|
+
if (error) throw new Error(error);
|
|
20
|
+
return response;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
options.signal?.throwIfAborted();
|
|
23
|
+
if (index === chain.length - 1 || !isTransientProviderErrorMessage(error instanceof Error ? error.message : String(error))) throw error;
|
|
24
|
+
log.warn({
|
|
25
|
+
modelRef: chain[index],
|
|
26
|
+
nextModelRef: chain[index + 1],
|
|
27
|
+
operation: usage.operation,
|
|
28
|
+
conversationId: usage.conversationId
|
|
29
|
+
}, "Task model request failed transiently; trying configured recovery model");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
throw new Error("No task model is configured");
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { completeTaskModelCall };
|
|
@@ -6,6 +6,12 @@ export interface TaskReadModel {
|
|
|
6
6
|
operationalState: TaskOperationalState;
|
|
7
7
|
attention: TaskAttentionItem[];
|
|
8
8
|
allowedCommands: string[];
|
|
9
|
+
revisionBaseline?: {
|
|
10
|
+
resultId: string;
|
|
11
|
+
baselineVersion: string;
|
|
12
|
+
resultRevision: number;
|
|
13
|
+
expectedVersion: number;
|
|
14
|
+
};
|
|
9
15
|
}
|
|
10
16
|
export declare class TaskReadModelProjector {
|
|
11
17
|
#private;
|
|
@@ -62,12 +62,23 @@ var TaskReadModelProjector = class {
|
|
|
62
62
|
const allocating = allocation && ["pending", "selecting"].includes(allocation.status);
|
|
63
63
|
const allowedCommands = this.allowedCommands(task, activeRun?.status, waits.length > 0, paused).filter((command) => !(allocation && allocation.status !== "assigned" && command === "start"));
|
|
64
64
|
if (allocation && ["blocked", "failed"].includes(allocation.status) && task.phase !== "closed" && !paused) allowedCommands.push("retry_allocation");
|
|
65
|
+
const resultRow = getSqliteDatabase().prepare(`SELECT payload_json FROM task_result_deliveries WHERE task_run_id IN
|
|
66
|
+
(SELECT run_id FROM task_runs WHERE task_id = ?) AND status IN ('pending','delivered','stale') ORDER BY created_at DESC, rowid DESC LIMIT 1`).get(task.id);
|
|
67
|
+
const result = resultRow ? JSON.parse(resultRow.payload_json) : void 0;
|
|
68
|
+
const revisionBaseline = result ? {
|
|
69
|
+
resultId: String(result.deliveryId),
|
|
70
|
+
baselineVersion: `${result.taskRunId}:${result.assignmentEpoch}:${result.outcome.outcomeId}`,
|
|
71
|
+
resultRevision: Number(result.resultRevision ?? 1),
|
|
72
|
+
expectedVersion: task.version
|
|
73
|
+
} : void 0;
|
|
74
|
+
if (revisionBaseline && !activeRun && !waits.length && ["closed", "review"].includes(task.phase) && (!task.resolution || task.resolution === "done") && !getSqliteDatabase().prepare("SELECT 1 FROM personal_requests WHERE task_id = ?").get(task.id)) allowedCommands.push("revise");
|
|
65
75
|
return {
|
|
66
76
|
task,
|
|
67
77
|
allocation,
|
|
68
78
|
operationalState: task.phase !== "closed" && !paused && !activeRun && waits.length === 0 && allocation ? allocating ? "allocating" : allocation.status === "blocked" ? "blocked" : allocation.status === "failed" ? "failed" : executionState : executionState,
|
|
69
79
|
attention: task.phase === "closed" || paused ? [] : attention,
|
|
70
|
-
allowedCommands
|
|
80
|
+
allowedCommands,
|
|
81
|
+
...revisionBaseline ? { revisionBaseline } : {}
|
|
71
82
|
};
|
|
72
83
|
}
|
|
73
84
|
summary(taskId) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type TaskResearchResult } from '@xopcai/gateway-contract';
|
|
2
|
+
/** Inspect latest publications, not the worker's assertion that its files still exist. */
|
|
3
|
+
export declare function inspectTaskPublications(runId: string, research?: TaskResearchResult): {
|
|
4
|
+
missing: string[];
|
|
5
|
+
unreviewed: string[];
|
|
6
|
+
artifactIds: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function buildResearchRepair(input: {
|
|
9
|
+
research?: TaskResearchResult;
|
|
10
|
+
stale: boolean;
|
|
11
|
+
instructionSequence: number;
|
|
12
|
+
publications: ReturnType<typeof inspectTaskPublications>;
|
|
13
|
+
criteria: string[];
|
|
14
|
+
requiresReview?: boolean;
|
|
15
|
+
}): {
|
|
16
|
+
gaps: string[];
|
|
17
|
+
fingerprint: string;
|
|
18
|
+
message: string;
|
|
19
|
+
};
|