chainlesschain 0.166.106 → 0.166.108
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/README.md +187 -8
- package/package.json +2 -2
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-CKwEku2e.js → AIOps-B5HWUFaS.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BSUOuTpW.js → ActionButton-DCIKpxoQ.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CGxvL_FI.js → Analytics-dsgvjCEQ.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-bCPwz-5w.js → AppLayout-DWDH5Qbm.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-2_BOWo6e.js → Artifacts-BD8S8kzU.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CBOruzgW.js → Audit-CDXv4Aoj.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-lg0IU5HN.js → BackgroundAgents-BLAQ5Uy0.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-OspCi452.js → Backup-moPac6tF.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BMkliqlz.js → BaseInput-C_6nzsLU.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BfoiUZwp.js → Chat-cYuslkFG.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BjnfMwep.js → ChatBubbleRenderer-Ceh3MG6M.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-jTMlkNQZ.js → Checkbox-Qjb-XOX_.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CycyJcnU.js → Codegen-IYRWXlMA.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BVWlReQj.js → Col-CsQ9jv8M.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CKRHl4xK.js → Community-BbNmfTwe.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BtpfMdhT.js → Compact-SShDx-nr.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DtHB1Ct1.js → Compliance-CLWhKIJp.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-D_8X7-RK.js → Cowork-D4tK9_s3.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-DMCOyvEa.js → Cron-D7GnfQ1z.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CeHdsu7m.js → Crosschain-TG86SH3X.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CL6mR6zX.js → DID-6pue0NCO.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-oz9n6DC7.js → Dashboard-BwkJ29du.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CbWm8mWu.js → Dropdown-DEvpYDof.js} +1 -1
- package/src/assets/web-panel/assets/EmailListRenderer-CQj7UlKJ.js +1 -0
- package/src/assets/web-panel/assets/{EvolutionSettings-DPwqgRYm.js → EvolutionSettings-tpvPMM9W.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DkV4YMFj.js → FamilyGuardDashboard-CWYFW75O.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CpUKHIOH.js → Federation-gRIi96rM.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C6KXRgjR.js → FormItemContext-B7Nr3YkV.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-C5Y4L5E3.js → GenericCardRenderer-b1BgGgLT.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CBwKdF8s.js → Git-Dis1jjO7.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Dt-OR7Aa.js → Governance-C4Yg99Am.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Czkl-Lhl.js → Inference-D4UQRbGu.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-C7NE4949.js → KnowledgeGraph-Co_kLMAq.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CoAuZiMG.js → Logs-D4BRp7bg.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DTkjTwGI.js → MarkdownRenderer-Dgy8arQI.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-IzrV-7zH.js → Marketplace-ys0j1vr9.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DYEea7aS.js → McpTools-B3ZvRZe_.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-Uqe7ZrV6.js → Memory-BOa0jbr-.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-D092EGyM.js → MobileBridge-CWJRmUbj.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-7ty8vTpj.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-gg4jzfB-.js → Mtc-CCcOk5m5.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BibGfs71.js → MtcAudit-vlrrScbQ.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BmB5yRXP.js → Multisig-C8K59S_8.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BBSlPDyY.js → NLProgramming-oTpFYVme.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Bui3-KiC.js → Notes-BhqAJWiz.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-ovXtbHe5.js → NotificationSettings-DCnV1CJM.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Bq-qD7eG.js → OrderTableRenderer-CZGnsrVW.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DacIY9oJ.js → Organization-DX1LuQlJ.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CX8osheZ.js → Overflow-CbfKrFdT.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-1lnikqVp.js → P2P-BEwYZuHL.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DCrU-V6A.js → PdhVaultBrowser-YNmWbwd7.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-Dfcb6kM2.js → Permissions-DyZ18LiA.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-dvgai4hf.js → PersonalDataHub-B2J3aw2g.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-nymAEtnK.js → Pipeline-CXl2ZlhQ.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D0Vd91oM.js → Privacy-I5SDmgAp.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BpUBcu7o.js → ProjectInit-Crl9tXw3.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DIzwTT-M.js → ProjectSettings-DCFtFlSK.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Den4RUw6.js → Projects-Do5BQq1i.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Cq8p-M0d.js → Providers-Cb7OWa3y.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DSmqOfYk.js → QrScannerModal-CJmhAU-s.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BDHCeSnA.js → QuickAsk-Cu6lEWou.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-B_9M8oF4.js → Recommend-Crip3jLB.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-5ot4leHy.js → RemoteSession-KxYY-2CB.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-B3F013PY.js → Reputation-D0vN-htI.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BMyBJnZw.js → Row-wqzd_xCD.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-WmV0l52g.js → RssFeed-8lsPfb0a.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Wl80yXnR.js → Search-C-e8qAeU.js} +1 -1
- package/src/assets/web-panel/assets/{Security-gbDMKb5m.js → Security-CMM9WgFy.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Bx2Bjhah.js → Services-CZdxjN2B.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BvJNybjV.js → Skeleton-BI3XNk35.js} +1 -1
- package/src/assets/web-panel/assets/Skills-DMlsh9It.js +1 -0
- package/src/assets/web-panel/assets/{Sla-BM9gyZwc.js → Sla-HQruznKY.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Bu9FL9Tz.js → SpeechSettings-Dl-MFq3w.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-D8ICJsMt.js → SyncSettings-BU224vDm.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-DESg3yCs.js +1 -0
- package/src/assets/web-panel/assets/{Templates-BJzpTD0W.js → Templates-Jb3TPz4Q.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BN8eX4R2.js → Tenant-CQ-GTrfa.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CjtP9bpq.js → Terminal-BbMl3Rue.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CpNRa4XW.js → TimelineRenderer-CS_vstKF.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-2lNNvNAH.js → Tokens-BaopVl1f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DxtxXyPg.js → Trigger-DtnD4WUN.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CakzGeF9.js → Trust-CsvG4Tmf.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CvJeRXwV.js → UkeySign-C1-A-cOV.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-D80pMzcO.js → VideoEditing-CNgJPdSL.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BF-VOBmZ.js → Wallet-CdF41501.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DXyoAzE_.js → WebAuthn-D-JmxD5g.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-X6CDxzrF.js → WorkflowEditor-C0XunR13.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BcUhqjeA.js → chat-BBAZpD_G.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Dw4bKaCm.js → colors-BxSxO5BX.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BWhu5Eri.js → compact-item-BoxL8pg5.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BLJ9JKoN.js → createContext-W5JAyZmY.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BI5TZ7EX.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DIkCiJbt.js → hasIn-HpiKDPVC.js} +1 -1
- package/src/assets/web-panel/assets/index-9-JLDK5n.js +1 -0
- package/src/assets/web-panel/assets/{index-BAwcMKaD.js → index-9caMEwQ-.js} +1 -1
- package/src/assets/web-panel/assets/{index-0mHbawfQ.js → index-B05_YRHZ.js} +1 -1
- package/src/assets/web-panel/assets/index-B7m8ioaQ.js +1 -0
- package/src/assets/web-panel/assets/{index-D3wp_jgy.js → index-B9VxE1C-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BotMuGS2.js → index-BA3WWQAT.js} +1 -1
- package/src/assets/web-panel/assets/{index-LOsZYbic.js → index-BSJ0cAle.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5qms36i.js → index-BW4PP5GN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDfB6hWf.js → index-BZAbaY64.js} +1 -1
- package/src/assets/web-panel/assets/{index-BipG-tDs.js → index-Ba4usRFM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgsVg5Up.js → index-BgMViZIY.js} +1 -1
- package/src/assets/web-panel/assets/{index-CTPoBbIR.js → index-BtFAEG08.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKzG3kBM.js → index-Bwn6k_qw.js} +1 -1
- package/src/assets/web-panel/assets/{index-PRYboDFm.js → index-C4uI7WCB.js} +1 -1
- package/src/assets/web-panel/assets/{index-DQbWGvE4.js → index-C5kqii-G.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1fufz1A.js → index-C7GIUWWF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjEP26Te.js → index-CM_gdohF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcTch6Fp.js → index-CRg3aOoj.js} +1 -1
- package/src/assets/web-panel/assets/{index-04SKBH8l.js → index-CcyzZloJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHLW27Je.js → index-CehxfRUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-5vzPcr1g.js → index-D6m6B4Wy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV4FSjmI.js → index-DSyfxxQS.js} +3 -3
- package/src/assets/web-panel/assets/{index-D5vFJmmX.js → index-DaJk9U9V.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxLDNxEQ.js → index-DcmAiq_Y.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-Erv8A9.js → index-DdEcQ1rp.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqGqoID5.js → index-DinY7IQa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGMzh2oj.js → index-DkSnlgK_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxfimJOH.js → index-DlPvZgv8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOjQi7oU.js → index-DuM9I1If.js} +1 -1
- package/src/assets/web-panel/assets/{index-uMtx6e3D.js → index-DwidpDEE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXJ8t1hK.js → index-IO2I7nzu.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cmc7qH2C.js → index-JrMBRi62.js} +1 -1
- package/src/assets/web-panel/assets/{index-BaStonJm.js → index-QzlEbtRL.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cr05twNa.js → index-V6VIJe2N.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGFqk1-E.js → index-_38IJqoP.js} +1 -1
- package/src/assets/web-panel/assets/{index-u0tqS0iq.js → index-_p4e3KfB.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1r2R4a-.js → index-gvfIRZxJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFGOV-YT.js → index-ooP1pQCt.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUC4TZWg.js → index-p6rNtYud.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Bx6Hj_FG.js → initDefaultProps-Dfn6M05J.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BSWivB70.js → motion-BRRwFqGO.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dv1Pg9R7.js → move-DpDPN6zR.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-Bqtl8fsk.js → mtc-parser-BHlSE87F.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DpOBjOSQ.js → omit-CEOri_L5.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D-M-dz48.js → pickAttrs-DqICh-ad.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DsTLAifk.js → placementArrow-DQizFFiV.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BVTetMpc.js → responsiveObserve-DmFHPdvC.js} +1 -1
- package/src/assets/web-panel/assets/{slide-abEcz-Cv.js → slide-s2s1XS3T.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CBhrdU2G.js → statusUtils-IwEIbBan.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CFq8ZCKa.js → styleChecker-CIFLlbXH.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-o4eE7fDV.js → useFlexGapSupport-CFkN2Cgh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Hs9W8ihi.js → useFs-BSY6O48s.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-Bnet5Jho.js → usePersonalDataHub-iJl3VnU0.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DJfN4kWs.js → vnode-vu8ReMs7.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BzV-2e7X.js → zoom-CeSrYAHp.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +2 -2
- package/src/commands/agent.js +20 -20
- package/src/commands/goal.js +299 -1
- package/src/commands/plugin.js +129 -68
- package/src/constants.js +2 -2
- package/src/data/changelog.json +29 -3
- package/src/harness/jsonl-session-store.js +128 -5
- package/src/harness/prompt-compressor.js +18 -10
- package/src/harness/structured-handoff.js +151 -13
- package/src/lib/agent-session-export.js +20 -0
- package/src/lib/background-agent-supervisor.js +54 -0
- package/src/lib/cli-goal-catalog.js +129 -0
- package/src/lib/cli-goal-source.js +119 -0
- package/src/lib/coding-task-guidance.js +2 -1
- package/src/lib/config-schema.js +1 -1
- package/src/lib/context-memory-kernel/live-compaction.js +75 -12
- package/src/lib/eval/stream-terminal.js +27 -2
- package/src/lib/evolution/evolution-artifact-ports.js +22 -11
- package/src/lib/evolution/evolution-file-witness.js +86 -63
- package/src/lib/evolution/evolution-ledger-file-backend.js +22 -0
- package/src/lib/evolution/evolution-ledger-file-manifest-catalog.js +34 -35
- package/src/lib/evolution/evolution-ledger-file-manifest-head-store.js +32 -39
- package/src/lib/evolution/evolution-ledger.js +367 -169
- package/src/lib/evolution/evolution-manifest-state-reader.js +58 -0
- package/src/lib/evolution/evolution-physical-state-reader.js +308 -0
- package/src/lib/evolution/evolution-witness-segments.js +12 -13
- package/src/lib/evolution/governed-wiki-pruning-ledger-adapter.js +82 -56
- package/src/lib/evolution/rrsi-observed-text-index.js +17 -1
- package/src/lib/evolution/rrsi-tenant-index-anchor-history.js +5 -0
- package/src/lib/execution-location-failure-site.js +20 -3
- package/src/lib/goal-store.js +8 -1
- package/src/lib/image-input.js +43 -14
- package/src/lib/llm-providers.js +1 -0
- package/src/lib/plugin-runtime/capabilities.js +10 -0
- package/src/lib/plugin-runtime/cli-goal-draft-request.js +138 -0
- package/src/lib/plugin-runtime/cli-goal-drafts.js +413 -0
- package/src/lib/plugin-runtime/cli-goal-extension-host.js +234 -0
- package/src/lib/plugin-runtime/examples/goal-description-drafter/plugin.json +17 -0
- package/src/lib/plugin-runtime/examples/goal-evidence-viewer/plugin.json +25 -0
- package/src/lib/plugin-runtime/examples/goal-progress-viewer/plugin.json +21 -0
- package/src/lib/plugin-runtime/examples/project-delivery-assistant/plugin.json +38 -0
- package/src/lib/plugin-runtime/goal-extension-contract.js +190 -0
- package/src/lib/plugin-runtime/goal-extensions.js +277 -0
- package/src/lib/plugin-runtime/install.js +40 -40
- package/src/lib/plugin-runtime/manifest.js +12 -0
- package/src/lib/plugin-runtime/policy.js +1 -0
- package/src/lib/project-goal-connection.js +225 -0
- package/src/lib/project-goal-draft-connection.js +217 -0
- package/src/lib/read-file-loop-guard.js +124 -8
- package/src/lib/session-host-snapshot.js +3 -0
- package/src/lib/session-message-provenance.js +24 -5
- package/src/lib/session-tool-round.js +39 -0
- package/src/lib/session-transcript-history.js +2 -0
- package/src/lib/session-transcript-page.js +4 -1
- package/src/lib/session-transcript-structure.js +4 -0
- package/src/lib/task-model-selector.js +1 -1
- package/src/repl/agent-repl.js +14 -7
- package/src/repl/config-summary.js +1 -1
- package/src/runtime/__tests__/message-roles.test.js +29 -0
- package/src/runtime/agent-core.js +116 -44
- package/src/runtime/headless-runner.js +191 -34
- package/src/runtime/headless-stream.js +144 -48
- package/src/runtime/message-roles.js +43 -0
- package/src/runtime/policies/agent-policy.js +1 -0
- package/src/workers/background-agent-worker.js +146 -47
- package/src/assets/web-panel/assets/EmailListRenderer-DXlmbC45.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-CwA1VoVJ.js +0 -1
- package/src/assets/web-panel/assets/Skills-Tz4rQcDp.js +0 -1
- package/src/assets/web-panel/assets/Tasks-B6MowBDo.js +0 -1
- package/src/assets/web-panel/assets/devWarning-D_MJgDGJ.js +0 -1
- package/src/assets/web-panel/assets/index-BP8log78.js +0 -1
- package/src/assets/web-panel/assets/index-PexF9zYf.js +0 -1
|
@@ -66,14 +66,17 @@ import {
|
|
|
66
66
|
agentLoop as coreAgentLoop,
|
|
67
67
|
} from "./agent-core.js";
|
|
68
68
|
import { composeSystemPrompt } from "./system-prompt.js";
|
|
69
|
-
import {
|
|
69
|
+
import { createResumeRoleProjection } from "./message-roles.js";
|
|
70
70
|
import {
|
|
71
71
|
estimateMessagesTokens,
|
|
72
72
|
sanitizeToolPairs,
|
|
73
73
|
} from "../harness/prompt-compressor.js";
|
|
74
74
|
import { compactConversationWithProvider } from "../harness/provider-backed-compaction.js";
|
|
75
75
|
import { HostResourceBudget } from "../lib/host-resource-budget.js";
|
|
76
|
-
import {
|
|
76
|
+
import {
|
|
77
|
+
projectCanonicalResumeMessages,
|
|
78
|
+
markRuntimeOnlySessionMessage,
|
|
79
|
+
} from "../lib/session-message-provenance.js";
|
|
77
80
|
import { isAbortError } from "../lib/abort-utils.js";
|
|
78
81
|
import { expandFileRefsAsync } from "./file-ref-expander.js";
|
|
79
82
|
// Per-turn helpers resolved at module load (not re-`await import`ed inside the
|
|
@@ -137,6 +140,7 @@ import {
|
|
|
137
140
|
appendToolCallCompact as jsonlAppendToolCallCompact,
|
|
138
141
|
appendLlmRetryCompact as jsonlAppendLlmRetryCompact,
|
|
139
142
|
appendCompactEventIfMessagesMatch as jsonlAppendCompactEventIfMessagesMatch,
|
|
143
|
+
appendToolRoundsIfMessagesMatch as jsonlAppendToolRoundsIfMessagesMatch,
|
|
140
144
|
appendEvent as jsonlAppendEvent,
|
|
141
145
|
appendAuthorityEvent as jsonlAppendAuthorityEvent,
|
|
142
146
|
readEvents as jsonlReadEvents,
|
|
@@ -965,28 +969,6 @@ async function runTurn(
|
|
|
965
969
|
sideEffects?.ledger,
|
|
966
970
|
);
|
|
967
971
|
|
|
968
|
-
// Collapse consecutive same-role turns before the model call ONLY when the
|
|
969
|
-
// caller flags a resume-degenerate transcript (`mergeRoles`): a resumed
|
|
970
|
-
// session whose previous run produced NO assistant response leaves a trailing
|
|
971
|
-
// bare `user` turn, so splicing the first live prompt after it sends two
|
|
972
|
-
// adjacent `user` messages — which Anthropic/Bedrock reject as "roles must
|
|
973
|
-
// alternate" (Claude Code 2.1.187 parity). It is GATED rather than applied
|
|
974
|
-
// every turn because the live turn loop legitimately produces consecutive
|
|
975
|
-
// `user` messages — an interrupted turn's dangling prompt, a PDH feedback
|
|
976
|
-
// note (§3.5.13) — that must reach the model distinctly and must not be
|
|
977
|
-
// folded (folding the interrupt-dangling turn even resurrects the abandoned
|
|
978
|
-
// request).
|
|
979
|
-
//
|
|
980
|
-
// Collapse IN PLACE (not a folded copy): the persistent `messages` array is
|
|
981
|
-
// reused for every later turn, so leaving the `[user, user]` pair in it would
|
|
982
|
-
// re-break the SECOND live turn (which re-sends the lingering pair). The gated
|
|
983
|
-
// turn is the first after resume, still tool-free (resumed history is
|
|
984
|
-
// user/assistant/system only), so an in-place fold is safe and the helper
|
|
985
|
-
// never folds `tool` turns regardless. Un-gated later turns are untouched, so
|
|
986
|
-
// the intentional interrupt/feedback consecutive-`user` states are preserved.
|
|
987
|
-
if (loopOptions.mergeRoles) {
|
|
988
|
-
collapseConsecutiveMessagesInPlace(messages);
|
|
989
|
-
}
|
|
990
972
|
for await (const event of runLoop(messages, loopOptions)) {
|
|
991
973
|
if (evolutionIngress !== null) {
|
|
992
974
|
await evolutionIngress.ingestAgentEvent(event);
|
|
@@ -2079,10 +2061,8 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
2079
2061
|
return { exitCode: 1, turns: 0 };
|
|
2080
2062
|
}
|
|
2081
2063
|
}
|
|
2082
|
-
// Vision
|
|
2083
|
-
//
|
|
2084
|
-
// pasted/typed image is read by a vision-capable model even though the
|
|
2085
|
-
// session's default model is text-only.
|
|
2064
|
+
// Vision fallback for a text-only main model. Multimodal main models keep
|
|
2065
|
+
// handling both image turns and follow-ups themselves.
|
|
2086
2066
|
let visionModel = options.visionModel;
|
|
2087
2067
|
if (!visionModel) {
|
|
2088
2068
|
try {
|
|
@@ -2294,6 +2274,11 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
2294
2274
|
? () => null
|
|
2295
2275
|
: jsonlFindLatestEvent);
|
|
2296
2276
|
const store = {
|
|
2277
|
+
appendToolRoundsIfMessagesMatch:
|
|
2278
|
+
deps.appendToolRoundsIfMessagesMatch ||
|
|
2279
|
+
(hasInjectedSessionStore
|
|
2280
|
+
? unavailableAuthorityCapability("appendToolRoundsIfMessagesMatch")
|
|
2281
|
+
: jsonlAppendToolRoundsIfMessagesMatch),
|
|
2297
2282
|
sessionExists: deps.sessionExists || jsonlSessionExists,
|
|
2298
2283
|
startSession: deps.startSession || jsonlStartSession,
|
|
2299
2284
|
appendUserMessage: deps.appendUserMessage || jsonlAppendUserMessage,
|
|
@@ -3282,14 +3267,12 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
3282
3267
|
}
|
|
3283
3268
|
}
|
|
3284
3269
|
|
|
3285
|
-
//
|
|
3286
|
-
//
|
|
3287
|
-
//
|
|
3288
|
-
// messages. Arm a one-shot flag consumed by the first model call so the merge
|
|
3289
|
-
// fires exactly once — the live turn loop's intentional consecutive-`user`
|
|
3290
|
-
// states (interrupt-dangling turn, PDH feedback note) are never folded.
|
|
3270
|
+
// Capture the first resumed request's adjacent role pairs, then normalize
|
|
3271
|
+
// those pairs in provider projections across later turns. Canonical history
|
|
3272
|
+
// and new feedback/interrupt message pairs retain their original structure.
|
|
3291
3273
|
let sanitizeRolesNextTurn =
|
|
3292
3274
|
resumedMessages > 0 && messages[messages.length - 1]?.role === "user";
|
|
3275
|
+
let projectProviderMessages;
|
|
3293
3276
|
|
|
3294
3277
|
if (
|
|
3295
3278
|
options.taskWorklog === true ||
|
|
@@ -3780,6 +3763,63 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
3780
3763
|
};
|
|
3781
3764
|
}
|
|
3782
3765
|
|
|
3766
|
+
const settleToolRounds = () => {
|
|
3767
|
+
if (
|
|
3768
|
+
!persist ||
|
|
3769
|
+
!messages.some(
|
|
3770
|
+
(message) => message.role === "assistant" && message.tool_calls?.length,
|
|
3771
|
+
)
|
|
3772
|
+
)
|
|
3773
|
+
return;
|
|
3774
|
+
sessionHostLease?.assert?.();
|
|
3775
|
+
const expected = requireSynchronousRecoveryResult(
|
|
3776
|
+
store.readVerifiedProjection(sessionId, () => ({
|
|
3777
|
+
accept() {},
|
|
3778
|
+
finish(authority) {
|
|
3779
|
+
return authority.readMessages();
|
|
3780
|
+
},
|
|
3781
|
+
})),
|
|
3782
|
+
"readVerifiedProjection",
|
|
3783
|
+
);
|
|
3784
|
+
return requireSynchronousRecoveryResult(
|
|
3785
|
+
store.appendToolRoundsIfMessagesMatch(sessionId, messages, expected),
|
|
3786
|
+
"appendToolRoundsIfMessagesMatch",
|
|
3787
|
+
);
|
|
3788
|
+
};
|
|
3789
|
+
const settleToolRoundsForHost = (phase, clientMessageId = null) => {
|
|
3790
|
+
try {
|
|
3791
|
+
settleToolRounds();
|
|
3792
|
+
return true;
|
|
3793
|
+
} catch (error) {
|
|
3794
|
+
const persistence = projectSessionPersistenceFailure(
|
|
3795
|
+
createSessionPersistenceFailure(error, {
|
|
3796
|
+
sessionId,
|
|
3797
|
+
operation: "append-event",
|
|
3798
|
+
}),
|
|
3799
|
+
{ phase },
|
|
3800
|
+
);
|
|
3801
|
+
if (persistence) terminalPersistenceFailure = persistence;
|
|
3802
|
+
emit({
|
|
3803
|
+
type: "result",
|
|
3804
|
+
is_error: true,
|
|
3805
|
+
session_id: sessionId,
|
|
3806
|
+
subtype: clientMessageId
|
|
3807
|
+
? "error_input_receipt"
|
|
3808
|
+
: persistence
|
|
3809
|
+
? "error_persistence"
|
|
3810
|
+
: "error_session_persistence",
|
|
3811
|
+
code: error?.code || "CC_SESSION_TOOL_ROUND_PERSISTENCE_FAILED",
|
|
3812
|
+
error:
|
|
3813
|
+
"Cannot settle completed tool rounds; refresh the session before continuing",
|
|
3814
|
+
...(clientMessageId
|
|
3815
|
+
? { client_message_id: clientMessageId, acceptance: "unknown" }
|
|
3816
|
+
: {}),
|
|
3817
|
+
...(persistence ? { persistence } : {}),
|
|
3818
|
+
});
|
|
3819
|
+
sawError = true;
|
|
3820
|
+
return false;
|
|
3821
|
+
}
|
|
3822
|
+
};
|
|
3783
3823
|
const loopOptionsBase = {
|
|
3784
3824
|
...(evolutionIngress === null ? {} : { evolutionIngress }),
|
|
3785
3825
|
model,
|
|
@@ -3850,8 +3890,14 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
3850
3890
|
mcpCallLedger: mcpRecoveryRuntime.ledger,
|
|
3851
3891
|
mcpDispatchAdmission: sessionHostLease?.admitMcpDispatch || null,
|
|
3852
3892
|
getTaskWorklogContext: () => taskWorklog?.context() || null,
|
|
3853
|
-
onBeforeCompaction: () =>
|
|
3854
|
-
updateWorklog((log) => log.record({ type: "before-compaction" }))
|
|
3893
|
+
onBeforeCompaction: () => {
|
|
3894
|
+
updateWorklog((log) => log.record({ type: "before-compaction" }));
|
|
3895
|
+
try {
|
|
3896
|
+
settleToolRounds();
|
|
3897
|
+
} catch (error) {
|
|
3898
|
+
throw markRuntimeLedgerPersistenceError(error);
|
|
3899
|
+
}
|
|
3900
|
+
},
|
|
3855
3901
|
onCompaction: persist
|
|
3856
3902
|
? (stats, compacted, settlement = {}) => {
|
|
3857
3903
|
sessionHostLease?.assert?.();
|
|
@@ -4451,6 +4497,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
4451
4497
|
continue;
|
|
4452
4498
|
}
|
|
4453
4499
|
if (parsed.compact) {
|
|
4500
|
+
if (!settleToolRoundsForHost("before-model")) break;
|
|
4454
4501
|
updateWorklog((log) => log.record({ type: "before-compaction" }));
|
|
4455
4502
|
const before = messages.length;
|
|
4456
4503
|
const expectedMessages = [...messages];
|
|
@@ -5078,10 +5125,42 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5078
5125
|
// fall through into the normal turn machinery with the correction prompt
|
|
5079
5126
|
} else {
|
|
5080
5127
|
const tag = kind === "positive" ? "认可" : "不满意";
|
|
5081
|
-
|
|
5128
|
+
const feedbackMessage = {
|
|
5082
5129
|
role: "user",
|
|
5083
5130
|
content: `(用户反馈:对上一轮回复表示${tag}。请在后续回复中延续/修正此偏好。)`,
|
|
5084
|
-
}
|
|
5131
|
+
};
|
|
5132
|
+
if (persist) {
|
|
5133
|
+
if (!settleToolRoundsForHost("before-model")) break;
|
|
5134
|
+
try {
|
|
5135
|
+
sessionHostLease?.assert?.();
|
|
5136
|
+
requireSynchronousRecoveryResult(
|
|
5137
|
+
store.appendUserMessage(sessionId, feedbackMessage.content),
|
|
5138
|
+
"appendUserMessage",
|
|
5139
|
+
);
|
|
5140
|
+
} catch (error) {
|
|
5141
|
+
const persistence = projectSessionPersistenceFailure(
|
|
5142
|
+
createSessionPersistenceFailure(error, {
|
|
5143
|
+
sessionId,
|
|
5144
|
+
operation: "user-turn-append",
|
|
5145
|
+
}),
|
|
5146
|
+
{ phase: "before-model" },
|
|
5147
|
+
);
|
|
5148
|
+
if (persistence) terminalPersistenceFailure = persistence;
|
|
5149
|
+
emit({
|
|
5150
|
+
type: "result",
|
|
5151
|
+
subtype: "error_persistence",
|
|
5152
|
+
is_error: true,
|
|
5153
|
+
session_id: sessionId,
|
|
5154
|
+
code: error?.code || "CC_SESSION_FEEDBACK_PERSISTENCE_FAILED",
|
|
5155
|
+
error:
|
|
5156
|
+
"Feedback could not be saved; refresh the session before retrying",
|
|
5157
|
+
...(persistence ? { persistence } : {}),
|
|
5158
|
+
});
|
|
5159
|
+
sawError = true;
|
|
5160
|
+
break;
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
messages.push(feedbackMessage);
|
|
5085
5164
|
continue;
|
|
5086
5165
|
}
|
|
5087
5166
|
}
|
|
@@ -5313,8 +5392,8 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5313
5392
|
if (conversationHasImages) {
|
|
5314
5393
|
turnVisionLlm = resolveVisionLlm({
|
|
5315
5394
|
hasImage: true,
|
|
5316
|
-
flags: {},
|
|
5317
|
-
llm: { provider, baseUrl, apiKey, visionModel },
|
|
5395
|
+
flags: { visionModel: options.visionModel },
|
|
5396
|
+
llm: { provider, model, baseUrl, apiKey, visionModel },
|
|
5318
5397
|
});
|
|
5319
5398
|
if (parsed.images && parsed.images.length) {
|
|
5320
5399
|
writeErr(
|
|
@@ -5359,6 +5438,8 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5359
5438
|
let inputReceipt = null;
|
|
5360
5439
|
let userEventId = null;
|
|
5361
5440
|
if (persist) {
|
|
5441
|
+
if (!settleToolRoundsForHost("before-model", parsed.clientMessageId))
|
|
5442
|
+
break;
|
|
5362
5443
|
try {
|
|
5363
5444
|
if (parsed.clientMessageId) {
|
|
5364
5445
|
if (!store.appendInputWithReceipt)
|
|
@@ -5453,11 +5534,12 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5453
5534
|
? AbortSignal.any([options.signal, currentAbort.signal])
|
|
5454
5535
|
: currentAbort.signal;
|
|
5455
5536
|
|
|
5456
|
-
//
|
|
5457
|
-
//
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5537
|
+
// Capture the resumed pairs once, then normalize those same pairs only in
|
|
5538
|
+
// every provider request. The live authority array retains separate turns.
|
|
5539
|
+
if (sanitizeRolesNextTurn) {
|
|
5540
|
+
projectProviderMessages = createResumeRoleProjection(messages);
|
|
5541
|
+
sanitizeRolesNextTurn = false;
|
|
5542
|
+
}
|
|
5461
5543
|
|
|
5462
5544
|
let outcome;
|
|
5463
5545
|
try {
|
|
@@ -5524,8 +5606,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5524
5606
|
event.text.trim().length > 0 &&
|
|
5525
5607
|
!event.text.trimStart().startsWith("/")),
|
|
5526
5608
|
),
|
|
5527
|
-
|
|
5528
|
-
mergeRoles: mergeRolesThisTurn,
|
|
5609
|
+
projectProviderMessages,
|
|
5529
5610
|
},
|
|
5530
5611
|
{
|
|
5531
5612
|
runLoop,
|
|
@@ -5642,9 +5723,21 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5642
5723
|
// the array length unchanged. sanitizeToolPairs is idempotent on an
|
|
5643
5724
|
// already-balanced array and leaves user/text turns untouched, so the
|
|
5644
5725
|
// intentional dangling-user state above is preserved.
|
|
5726
|
+
const originalMessages = new Set(messages);
|
|
5645
5727
|
const balanced = sanitizeToolPairs(messages);
|
|
5728
|
+
// Only the sanitizer's newly-created commentary for discarded calls
|
|
5729
|
+
// is ephemeral. Existing real messages retain their authority.
|
|
5730
|
+
for (const message of balanced) {
|
|
5731
|
+
if (
|
|
5732
|
+
!originalMessages.has(message) &&
|
|
5733
|
+
message.role === "assistant" &&
|
|
5734
|
+
!message.tool_calls?.length
|
|
5735
|
+
)
|
|
5736
|
+
markRuntimeOnlySessionMessage(message);
|
|
5737
|
+
}
|
|
5646
5738
|
messages.length = 0;
|
|
5647
5739
|
messages.push(...balanced);
|
|
5740
|
+
if (!settleToolRoundsForHost("after-model")) break;
|
|
5648
5741
|
emit({
|
|
5649
5742
|
type: "result",
|
|
5650
5743
|
subtype: "interrupted",
|
|
@@ -5656,6 +5749,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5656
5749
|
continue;
|
|
5657
5750
|
}
|
|
5658
5751
|
if (isAbort) break; // outer options.signal — caller is shutting down
|
|
5752
|
+
if (!settleToolRoundsForHost("after-model")) break;
|
|
5659
5753
|
const transportDetails = transportErrorDetails(err);
|
|
5660
5754
|
emit({
|
|
5661
5755
|
type: "result",
|
|
@@ -5678,6 +5772,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5678
5772
|
currentAbort = null;
|
|
5679
5773
|
|
|
5680
5774
|
if (outcome.endReason === "user-input-pending") {
|
|
5775
|
+
if (!settleToolRoundsForHost("after-model")) break;
|
|
5681
5776
|
emit({
|
|
5682
5777
|
type: "result",
|
|
5683
5778
|
subtype: "interrupted",
|
|
@@ -5740,9 +5835,9 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5740
5835
|
}
|
|
5741
5836
|
|
|
5742
5837
|
// Grow the conversation so the next turn has context.
|
|
5743
|
-
messages.push({ role: "assistant", content: outcome.finalText });
|
|
5744
5838
|
let assistantEventId = null;
|
|
5745
5839
|
if (persist) {
|
|
5840
|
+
if (!settleToolRoundsForHost("after-model")) break;
|
|
5746
5841
|
try {
|
|
5747
5842
|
assistantEventId = transcriptMessageEventId(
|
|
5748
5843
|
store.appendAssistantMessage(sessionId, outcome.finalText),
|
|
@@ -5766,6 +5861,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5766
5861
|
}
|
|
5767
5862
|
}
|
|
5768
5863
|
}
|
|
5864
|
+
messages.push({ role: "assistant", content: outcome.finalText });
|
|
5769
5865
|
|
|
5770
5866
|
const exhausted =
|
|
5771
5867
|
outcome.endReason === "budget-exhausted" ||
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { canonicalJson } from "@chainlesschain/context-memory-kernel";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Conversation role sanitation shared by the headless runner and the
|
|
3
5
|
* stream-json runtime.
|
|
@@ -111,6 +113,47 @@ export function mergeConsecutiveMessages(messages) {
|
|
|
111
113
|
return out;
|
|
112
114
|
}
|
|
113
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Capture only the adjacent plain-role pairs present at resume. Reapply their
|
|
118
|
+
* provider normalization on later requests without mutating canonical history
|
|
119
|
+
* or folding newly added interrupt/feedback turns. Canonical fingerprints also
|
|
120
|
+
* recognize the same retained messages after compaction recreates objects.
|
|
121
|
+
*/
|
|
122
|
+
export function createResumeRoleProjection(messages) {
|
|
123
|
+
const pairs = new Map();
|
|
124
|
+
const pairKey = (left, right) => canonicalJson([left, right]);
|
|
125
|
+
for (let index = 1; index < messages.length; index++) {
|
|
126
|
+
const left = messages[index - 1];
|
|
127
|
+
const right = messages[index];
|
|
128
|
+
if (
|
|
129
|
+
left &&
|
|
130
|
+
right &&
|
|
131
|
+
MERGEABLE_ROLES.has(left.role) &&
|
|
132
|
+
left.role === right.role &&
|
|
133
|
+
!hasToolCalls(left) &&
|
|
134
|
+
!hasToolCalls(right)
|
|
135
|
+
) {
|
|
136
|
+
const key = pairKey(left, right);
|
|
137
|
+
pairs.set(key, (pairs.get(key) || 0) + 1);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return (requestMessages) => {
|
|
141
|
+
const remaining = new Map(pairs);
|
|
142
|
+
const projected = [];
|
|
143
|
+
for (let index = 0; index < requestMessages.length; index++) {
|
|
144
|
+
const message = requestMessages[index];
|
|
145
|
+
const key =
|
|
146
|
+
index > 0 ? pairKey(requestMessages[index - 1], message) : null;
|
|
147
|
+
if (key && remaining.get(key) > 0) {
|
|
148
|
+
const previous = projected.pop();
|
|
149
|
+
projected.push(...mergeConsecutiveMessages([previous, message]));
|
|
150
|
+
remaining.set(key, remaining.get(key) - 1);
|
|
151
|
+
} else projected.push(message);
|
|
152
|
+
}
|
|
153
|
+
return projected;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
114
157
|
/**
|
|
115
158
|
* In-place variant: collapse consecutive mergeable-role turns by mutating the
|
|
116
159
|
* given array (same reference is kept, so closures over it stay valid). Used by
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
deliverBackgroundNeedsInputNotification,
|
|
25
25
|
insertArgumentsBeforeOptionTerminator,
|
|
26
26
|
mutateBackgroundAgentState,
|
|
27
|
+
mutateBackgroundAgentStateWithLockRetry,
|
|
27
28
|
openBackgroundLogFile,
|
|
28
29
|
readBackgroundAgentState,
|
|
29
30
|
removeJobFile,
|
|
@@ -88,6 +89,7 @@ let server = null;
|
|
|
88
89
|
let child = null;
|
|
89
90
|
let heartbeat = null;
|
|
90
91
|
let finalized = false;
|
|
92
|
+
let finalizing = false;
|
|
91
93
|
let phase = "turn";
|
|
92
94
|
let turnCount = 0;
|
|
93
95
|
let lastExit = { code: 0, signal: null };
|
|
@@ -112,6 +114,79 @@ const pendingInteractions = new Map();
|
|
|
112
114
|
// relays the throw as {type:"error", message}) instead of silently queued.
|
|
113
115
|
const MAX_PROMPT_QUEUE = 100;
|
|
114
116
|
|
|
117
|
+
export function isBackgroundAgentWorkerClosing(isFinalized, isFinalizing) {
|
|
118
|
+
return isFinalized === true || isFinalizing === true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function assertBackgroundAgentWorkerAcceptsPrompt(
|
|
122
|
+
isFinalized,
|
|
123
|
+
isFinalizing,
|
|
124
|
+
) {
|
|
125
|
+
if (isBackgroundAgentWorkerClosing(isFinalized, isFinalizing)) {
|
|
126
|
+
throw new Error("this background session is closing");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function ownsBackgroundAgentWorkerRecord(current, workerPid, workerGeneration) {
|
|
131
|
+
return Boolean(
|
|
132
|
+
current &&
|
|
133
|
+
(!current.workerGeneration ||
|
|
134
|
+
current.workerGeneration === workerGeneration) &&
|
|
135
|
+
(Number(current.workerClaimedPid) === workerPid ||
|
|
136
|
+
(current.workerClaimedPid == null &&
|
|
137
|
+
Number(current.workerPid ?? current.pid) === workerPid)),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function createBackgroundAgentWorkerFinalStateUpdater({
|
|
142
|
+
id,
|
|
143
|
+
workerPid,
|
|
144
|
+
workerGeneration,
|
|
145
|
+
code,
|
|
146
|
+
signal,
|
|
147
|
+
errorMessage,
|
|
148
|
+
now = Date.now,
|
|
149
|
+
}) {
|
|
150
|
+
return (current) => {
|
|
151
|
+
if (!current || !ownsBackgroundAgentWorkerRecord(
|
|
152
|
+
current,
|
|
153
|
+
workerPid,
|
|
154
|
+
workerGeneration,
|
|
155
|
+
)) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
if (current.status !== "running") {
|
|
159
|
+
return { ...current, phase: null, transport: null };
|
|
160
|
+
}
|
|
161
|
+
if (current.stopRequestedAt) return null;
|
|
162
|
+
return {
|
|
163
|
+
...current,
|
|
164
|
+
id,
|
|
165
|
+
status: errorMessage ? "failed" : code === 0 ? "completed" : "failed",
|
|
166
|
+
endedAt: now(),
|
|
167
|
+
exitCode: errorMessage ? (code ?? 1) : code,
|
|
168
|
+
signal: signal || null,
|
|
169
|
+
...(errorMessage ? { error: errorMessage } : {}),
|
|
170
|
+
phase: null,
|
|
171
|
+
transport: null,
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function isBackgroundAgentWorkerFinalStateSettledOrSuperseded(
|
|
177
|
+
mutation,
|
|
178
|
+
{ workerPid, workerGeneration },
|
|
179
|
+
) {
|
|
180
|
+
if (mutation.applied) return true;
|
|
181
|
+
const current = mutation.state;
|
|
182
|
+
return (
|
|
183
|
+
!current ||
|
|
184
|
+
current.status !== "running" ||
|
|
185
|
+
Boolean(current.stopRequestedAt) ||
|
|
186
|
+
!ownsBackgroundAgentWorkerRecord(current, workerPid, workerGeneration)
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
115
190
|
/**
|
|
116
191
|
* Bind one idempotent termination settlement to a turn child.
|
|
117
192
|
*
|
|
@@ -576,36 +651,38 @@ function finalize(code, signal, errorMessage) {
|
|
|
576
651
|
// worker and heartbeat alive until its fresh-lease reload either settles
|
|
577
652
|
// every disk-visible pending request or persists retry evidence.
|
|
578
653
|
if (interactionFinalSweep) return;
|
|
579
|
-
if (finalized) return;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
654
|
+
if (finalized || finalizing) return;
|
|
655
|
+
finalizing = true;
|
|
656
|
+
|
|
657
|
+
const workerIdentity = {
|
|
658
|
+
workerPid: process.pid,
|
|
659
|
+
workerGeneration: job.workerGeneration,
|
|
660
|
+
};
|
|
661
|
+
const finish = (persistenceFailed) => {
|
|
662
|
+
finalized = true;
|
|
663
|
+
finalizing = false;
|
|
664
|
+
clearInterval(heartbeat);
|
|
665
|
+
const done = () => {
|
|
666
|
+
keeperClient?.close();
|
|
667
|
+
keeperClient = null;
|
|
668
|
+
try {
|
|
669
|
+
log?.close();
|
|
670
|
+
} catch {
|
|
671
|
+
/* log fd already closed */
|
|
595
672
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
673
|
+
const originalExitCode = errorMessage ? 1 : (code ?? 1);
|
|
674
|
+
process.exit(
|
|
675
|
+
persistenceFailed && originalExitCode === 0 ? 1 : originalExitCode,
|
|
676
|
+
);
|
|
677
|
+
};
|
|
678
|
+
if (server) {
|
|
679
|
+
server.broadcast({ type: "closing" });
|
|
680
|
+
server.close().then(done, done);
|
|
681
|
+
} else {
|
|
682
|
+
done();
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
const reportPersistenceFailure = (error) => {
|
|
609
686
|
try {
|
|
610
687
|
writeSync(
|
|
611
688
|
2,
|
|
@@ -616,23 +693,39 @@ function finalize(code, signal, errorMessage) {
|
|
|
616
693
|
} catch {
|
|
617
694
|
/* inherited stderr may already be closed */
|
|
618
695
|
}
|
|
619
|
-
}
|
|
620
|
-
const done = () => {
|
|
621
|
-
keeperClient?.close();
|
|
622
|
-
keeperClient = null;
|
|
623
|
-
try {
|
|
624
|
-
log?.close();
|
|
625
|
-
} catch {
|
|
626
|
-
/* log fd already closed */
|
|
627
|
-
}
|
|
628
|
-
process.exit(errorMessage ? 1 : (code ?? 1));
|
|
629
696
|
};
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
697
|
+
|
|
698
|
+
void mutateBackgroundAgentStateWithLockRetry(
|
|
699
|
+
job.id,
|
|
700
|
+
createBackgroundAgentWorkerFinalStateUpdater({
|
|
701
|
+
id: job.id,
|
|
702
|
+
...workerIdentity,
|
|
703
|
+
code,
|
|
704
|
+
signal,
|
|
705
|
+
errorMessage,
|
|
706
|
+
}),
|
|
707
|
+
)
|
|
708
|
+
.then((mutation) => {
|
|
709
|
+
if (
|
|
710
|
+
isBackgroundAgentWorkerFinalStateSettledOrSuperseded(
|
|
711
|
+
mutation,
|
|
712
|
+
workerIdentity,
|
|
713
|
+
)
|
|
714
|
+
) {
|
|
715
|
+
finish(false);
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
const error = new Error(
|
|
719
|
+
"The active worker still owns a nonterminal state after finalization",
|
|
720
|
+
);
|
|
721
|
+
error.code = "BACKGROUND_AGENT_FINAL_STATE_UNRESOLVED";
|
|
722
|
+
reportPersistenceFailure(error);
|
|
723
|
+
finish(true);
|
|
724
|
+
})
|
|
725
|
+
.catch((error) => {
|
|
726
|
+
reportPersistenceFailure(error);
|
|
727
|
+
finish(true);
|
|
728
|
+
});
|
|
636
729
|
}
|
|
637
730
|
|
|
638
731
|
function scheduleTurnLaunchSettlementRetry(context, delayMs = 250) {
|
|
@@ -946,7 +1039,12 @@ function beginTurnLaunchSettlement({
|
|
|
946
1039
|
}
|
|
947
1040
|
|
|
948
1041
|
function startTurn(argv, promptText) {
|
|
949
|
-
if (
|
|
1042
|
+
if (
|
|
1043
|
+
isBackgroundAgentWorkerClosing(finalized, finalizing) ||
|
|
1044
|
+
!writeHeartbeat()
|
|
1045
|
+
) {
|
|
1046
|
+
return false;
|
|
1047
|
+
}
|
|
950
1048
|
const nextTurn = turnCount + 1;
|
|
951
1049
|
const turnLaunchToken = randomBytes(16).toString("hex");
|
|
952
1050
|
// Private spawn-generation binding for the dedicated child IPC channel.
|
|
@@ -1483,7 +1581,7 @@ function startTurn(argv, promptText) {
|
|
|
1483
1581
|
}
|
|
1484
1582
|
|
|
1485
1583
|
function maybeContinue() {
|
|
1486
|
-
if (finalized) return;
|
|
1584
|
+
if (isBackgroundAgentWorkerClosing(finalized, finalizing)) return;
|
|
1487
1585
|
// External stop marked the session terminal while a turn was in flight —
|
|
1488
1586
|
// don't start another turn against a stopped session.
|
|
1489
1587
|
const current = readBackgroundAgentState(job.id);
|
|
@@ -1696,6 +1794,7 @@ async function main() {
|
|
|
1696
1794
|
token,
|
|
1697
1795
|
getStatus,
|
|
1698
1796
|
onPrompt: (text) => {
|
|
1797
|
+
assertBackgroundAgentWorkerAcceptsPrompt(finalized, finalizing);
|
|
1699
1798
|
if (!Array.isArray(job.followUpArgv)) {
|
|
1700
1799
|
throw new Error(
|
|
1701
1800
|
"this session was launched without follow-up support — start a new one with cc agent --bg",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as C,P as c,J as f,U as r,c as h,_ as k,R as n,V as l,K as d,Q as u,S as g,b as t}from"./vendor-Bn1JzzAn.js";import{_ as j}from"./index-DV4FSjmI.js";import{aH as w}from"./icons-DG5UD-6K.js";const M={__name:"EmailListRenderer",props:{event:{type:Object,required:!0}},setup(_,{expose:m}){m();const a=_,e=t(()=>a.event.content||{}),i=t(()=>a.event.extra||{}),p=t(()=>e.value.from||e.value.sender||e.value.fromName||a.event.actor||"(未知发件人)"),s=t(()=>e.value.subject||e.value.title||"(无主题)"),y=t(()=>e.value.snippet||e.value.preview||e.value.body?.slice(0,100)||null),b=t(()=>Array.isArray(e.value.attachments)?e.value.attachments.length:typeof e.value.attachmentCount=="number"?e.value.attachmentCount:0),x=t(()=>i.value.category||e.value.category),S=t(()=>e.value.unread===!0),T=t(()=>{if(!a.event.occurredAt)return"";const o=new Date(a.event.occurredAt);return`${o.getFullYear()}-${String(o.getMonth()+1).padStart(2,"0")}-${String(o.getDate()).padStart(2,"0")} ${String(o.getHours()).padStart(2,"0")}:${String(o.getMinutes()).padStart(2,"0")}`}),v={props:a,c:e,e:i,fromText:p,subjectText:s,snippetText:y,attachmentCount:b,category:x,isUnread:S,formattedTime:T,computed:t,get MailOutlined(){return w}};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}},N={class:"email-row"},O={class:"left"},V={class:"body"},A={class:"head"},B={class:"from"},E={class:"time"},L={class:"subject"},R={key:0,class:"snippet"},D={class:"meta"};function H(_,m,a,e,i,p){const s=C("a-tag");return c(),f("div",N,[r("div",O,[h(e.MailOutlined,{class:k(["icon",{unread:e.isUnread}])},null,8,["class"])]),r("div",V,[r("div",A,[r("span",B,n(e.fromText),1),r("span",E,n(e.formattedTime),1)]),r("div",L,n(e.subjectText),1),e.snippetText?(c(),f("div",R,n(e.snippetText),1)):l("v-if",!0),r("div",D,[h(s,{color:"blue",class:"src"},{default:d(()=>[u(n(a.event.source.adapter),1)]),_:1}),e.attachmentCount>0?(c(),g(s,{key:0,color:"orange"},{default:d(()=>[u(" 📎 "+n(e.attachmentCount),1)]),_:1})):l("v-if",!0),e.category?(c(),g(s,{key:1},{default:d(()=>[u(n(e.category),1)]),_:1})):l("v-if",!0)])])])}const P=j(M,[["render",H],["__scopeId","data-v-e4ddf632"],["__file","/tmp/cc-web-panel-HKM6TL/repo/packages/web-panel/src/components/pdh/renderers/EmailListRenderer.vue"]]);export{P as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as n,J as g,c as l,K as r,N as u,P as h,U as o,R as t,Q as b}from"./vendor-Bn1JzzAn.js";import{_ as v,b as m}from"./index-DV4FSjmI.js";import{a8 as M,M as y}from"./icons-DG5UD-6K.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const c=u(),{t:e}=m();function a(){c.push("/projects")}function _(){c.push("/mobile-bridge")}const s={router:c,t:e,goToProjects:a,goToMobileBridge:_,get useRouter(){return u},get useI18n(){return m},get MobileOutlined(){return y},get FolderOutlined(){return M}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},x={class:"mobile-projects-placeholder"},O={class:"title"},T={class:"subtitle"},k={class:"explainer"};function w(p,i,c,e,a,_){const s=n("a-alert"),d=n("a-button"),f=n("a-space"),P=n("a-empty"),j=n("a-card");return h(),g("div",x,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",O,t(e.t("mobileProjects.title")),1),o("p",T,t(e.t("mobileProjects.subtitle")),1),l(s,{message:e.t("mobileProjects.v02Banner"),type:"info","show-icon":"",class:"banner"},null,8,["message"]),o("div",k,[o("h3",null,t(e.t("mobileProjects.currentDirection")),1),o("p",null,t(e.t("mobileProjects.currentDirectionBody")),1),o("ul",null,[o("li",null,t(e.t("mobileProjects.stepPhone")),1),o("li",null,t(e.t("mobileProjects.stepTap")),1),o("li",null,t(e.t("mobileProjects.stepPull")),1)]),o("h3",null,t(e.t("mobileProjects.reverseDirection")),1),o("p",null,t(e.t("mobileProjects.reverseDirectionBody")),1)]),l(f,{class:"actions"},{default:r(()=>[l(d,{type:"primary",onClick:e.goToProjects},{default:r(()=>[l(e.FolderOutlined),b(" "+t(e.t("mobileProjects.viewLocalProjects")),1)]),_:1}),l(d,{onClick:e.goToMobileBridge},{default:r(()=>[l(e.MobileOutlined),b(" "+t(e.t("mobileProjects.checkBridge")),1)]),_:1})]),_:1})]),_:1})]),_:1})])}const N=v(B,[["render",w],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-HKM6TL/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{N as default};
|