chainlesschain 0.166.115 → 0.166.118
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 +43 -5
- package/package.json +4 -4
- 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/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BsoSoDNb.js → AIOps-BGySwMIP.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Dcx7Gm5t.js → ActionButton-Chn7fBLr.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-S1hsBIz3.js → Analytics-ORH7UkGa.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B2j067qM.js → AppLayout-8xV4jWjP.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-D5iGV9ic.js → Artifacts-26SBK-x-.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C8ChVvXu.js → Audit-CtXpqbXg.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Cg97AAJS.js → BackgroundAgents-C5zLvQis.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CyxU9IUg.js → Backup-C93xY4vO.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CKlWjA8I.js → BaseInput-DpVCHfAn.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-C-EqZza6.js → Chat-DM0LblR2.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BRFiXKPX.js → ChatBubbleRenderer-unlQUF1T.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-kkI13tSJ.js → Checkbox-BsAt3cKR.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-NlqEDwHK.js → Codegen-E_kp4KFd.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CfepEu79.js → Col-6msR3T6I.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BRo0qLXM.js → Community-PyX9c5D-.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BMu8TP0E.js → Compact-7G1bVDSH.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-B7Q3Moef.js → Compliance-DcHN7GlD.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BVwt7Xmc.js → Cowork-WUIHJYDx.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CgBv20Qy.js → Cron-CWgCbptg.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CwcSBJk2.js → Crosschain-BzKZ6roD.js} +1 -1
- package/src/assets/web-panel/assets/{DID-d20rCiIm.js → DID-r7zxeItn.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-PpZaUYpS.js → Dashboard-D3pBiN2H.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DjsLdX_Z.js → Dropdown-C4otRJlZ.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CaPkrtxn.js → EmailListRenderer-CzDTC8lm.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DDY8cQnE.js → EvolutionSettings-DGkXiIs-.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-VQavMjyj.js → FamilyGuardDashboard-BKdEyuiR.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D0GvKQgI.js → Federation-dsI-xcpf.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Dl_TWHmb.js → FormItemContext-CEEb1fMR.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bny2uagG.js → GenericCardRenderer-D_mfO3Ts.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B01KXq47.js → Git-CBwr2ZI3.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-F4c4Vwo1.js → Governance-D-Wy2Jjr.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-_025Q-8K.js → Inference-B4Yk_IRx.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DwbTmQb1.js → KnowledgeGraph-DoI7bi6m.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CnNo0hCm.js → Logs-Ce1IiKAj.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-GND_8y0V.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Dkz5bv7F.js → Marketplace-CsIEByzK.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CBtRwDW_.js → McpTools-_DRzjcIn.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-Y9jnyTb7.js → Memory-zvLpyi__.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Br1urkOz.js → MobileBridge-DXd1ik2Z.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DnsyuerX.js → MobileProjects-DKh2q-Y9.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-he3ZzieF.js → Mtc-Ct-fhtIx.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-BadphAuN.js → MtcAudit-J4zY3Oqk.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-3_pVLymK.js → Multisig-B2HJMCKe.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DmtmHfsI.js → NLProgramming-CwcSmU4q.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CE4L2O55.js → Notes-Da53L6wb.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-B7QmfJn9.js → NotificationSettings-BxhufdrA.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-O0wRSyJ0.js → OrderTableRenderer-BoFwohAi.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BrlMSsyT.js → Organization-MIsMrUes.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CY4ULPrZ.js → Overflow-Dy2P4v3q.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-kIANZYKd.js → P2P-CD9Sxn2y.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DEgB4rvF.js → PdhVaultBrowser-BvBWgfG0.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-CWxywRp5.js → Permissions-CwOlDRis.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DAg7iCbr.js → PersonalDataHub-CZYaxEpv.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-Brc6ONnR.js → Pipeline-kLU7PUbB.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CcinYTL8.js → Privacy-BVRycSiI.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Bz8XEsom.js → ProjectInit-DP3pr7uJ.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CsOMlSTZ.js → ProjectSettings-CACaDYjs.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CB1k4zTC.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CeunOQiH.js → Providers-D7Y9WHRE.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CN2a2_Fb.js → QrScannerModal-CeP8xzs1.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CVeLif3e.js → QuickAsk-iJVFrhZ2.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-1k9WOEGM.js → Recommend-DmTpnagw.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Q8UCqIMw.js → RemoteSession-C6ek8Uni.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CkrCgXKM.js → Reputation-CPfwc9de.js} +1 -1
- package/src/assets/web-panel/assets/{Row-JFdvuTzi.js → Row-C1wwtSMJ.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-C74JHCmk.js → RssFeed-BiDJsqaH.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DrJiVO1T.js → Search-BF6Aon95.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BJzNlSJq.js → Security-Bps0XnV4.js} +3 -3
- package/src/assets/web-panel/assets/{Services-D4TLMnJm.js → Services-uf92smGR.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-cswTDqhh.js → Skeleton-DQd4eVWW.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Bv0rM1BS.js → Skills-DgamiYa5.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-D9rE7hNh.js → Sla-CF1IVIrm.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-Bzxmjbpc.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-BwnMG8kq.js → SyncSettings-B8zKauiq.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-wJvU24cB.js → Tasks-DPKV_xSt.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CZbRU3tN.js → Templates-BikeSZIF.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-_jbpFJPZ.js → Tenant-CEaUaDkJ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BzNm5WKZ.js → Terminal-ZPgOSQ_q.js} +3 -3
- package/src/assets/web-panel/assets/{TimelineRenderer-bmybWjuS.js → TimelineRenderer-DmyB4Udk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-o1WDcqVQ.js → Tokens-g85Pm5TO.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BB1D6sIB.js → Trigger-D202hx9a.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CLxdCfy2.js → Trust-DzvQYVFy.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B9LS6vS0.js → UkeySign-KRzwddVg.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Bg0-wxjz.js → VideoEditing-IRBXLO2z.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Bw0G2F6P.js → Wallet-DSf5KPgQ.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-irEiNY9b.js → WebAuthn-DNPxLTCc.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-Bh08FbJs.js → WorkflowEditor-C3wAtVcK.js} +1 -1
- package/src/assets/web-panel/assets/{addon-fit-CK6X9sAG.js → addon-fit-CbkjSUJl.js} +1 -1
- package/src/assets/web-panel/assets/{chat-De-FPjVT.js → chat-q3XXUtv2.js} +1 -1
- package/src/assets/web-panel/assets/{colors-ygdyvinU.js → colors-CF54SNei.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BQ9jH9KV.js → compact-item-BaRkvZuT.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BFuVSyox.js → createContext-CDR9hsfs.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-1LO-NplX.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-i19GtR1P.js → hasIn-DlC--S8R.js} +1 -1
- package/src/assets/web-panel/assets/{index-DS1IwwGL.js → index-B0Ptc7yu.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1IsP_JO.js → index-B0V9rgdu.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWfgeaG4.js → index-BEiUlFKb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTY20pWu.js → index-BJO0n1LQ.js} +1 -1
- package/src/assets/web-panel/assets/index-BLaJsev4.js +1 -0
- package/src/assets/web-panel/assets/index-BLmviChG.js +1 -0
- package/src/assets/web-panel/assets/{index-IXkif6J_.js → index-BU5DJqk7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVhtukYX.js → index-BY-Tf3OM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKlU5VZy.js → index-BZrE0Go8.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bw5pTpnI.js → index-BizdX2X5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGMxK155.js → index-C87Yr3h1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVnFgasM.js → index-C9Wypz9e.js} +1 -1
- package/src/assets/web-panel/assets/{index-C61w3omz.js → index-CAoG_E-q.js} +1 -1
- package/src/assets/web-panel/assets/{index-l5-J0jHx.js → index-CAxSyMrF.js} +1 -1
- package/src/assets/web-panel/assets/{index-28DjsABm.js → index-CC5HjNM6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPUCvc8i.js → index-CNZQEZ9g.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpdXhhMY.js → index-CPvIhha6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAboGZTw.js → index-CR_wqMGy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DL7ewjD2.js → index-CSClXoB3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bhf-MuUh.js → index-CZ8azVgB.js} +3 -3
- package/src/assets/web-panel/assets/{index-BaaydJcC.js → index-Ccc5z8eJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2LieObB.js → index-CeiKbM3a.js} +1 -1
- package/src/assets/web-panel/assets/{index-We2nK3ju.js → index-Cl6av3X7.js} +1 -1
- package/src/assets/web-panel/assets/{index-m8waSAyv.js → index-CtGfeD7E.js} +1 -1
- package/src/assets/web-panel/assets/{index-cDJsyAkI.js → index-Ctid12Gq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlwxUZQL.js → index-D0H-N0uG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBYiCI1d.js → index-D0vIgprF.js} +1 -1
- package/src/assets/web-panel/assets/{index-_9tUBcLm.js → index-D4wUDFRg.js} +1 -1
- package/src/assets/web-panel/assets/{index-4HoFz1MA.js → index-DJFipyK7.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cq9k4-Ws.js → index-DX2REKNp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuuOX5u3.js → index-Dc3gD0cw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgjLaB7k.js → index-DiQzer2R.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMNjaSir.js → index-DntKLOs9.js} +1 -1
- package/src/assets/web-panel/assets/{index-vXtH3o6O.js → index-Dplhl6gh.js} +1 -1
- package/src/assets/web-panel/assets/{index-BLMtCKAY.js → index-Dq8q_PWB.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXrk8OYO.js → index-IVQdOBNN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBVcGaxk.js → index-Kerduyao.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKblSCL9.js → index-W6cLGjpW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgoSgmjK.js → index-qZDNFll9.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-B_EZHeqN.js → initDefaultProps-Ccz7v71u.js} +1 -1
- package/src/assets/web-panel/assets/{markdown-Yo_c6Krv.js → markdown-Bq2x0XsR.js} +1 -1
- package/src/assets/web-panel/assets/markdown-DUKxbhE4.js +51 -0
- package/src/assets/web-panel/assets/{motion-BrVb_Gy1.js → motion-BlCLpVDp.js} +1 -1
- package/src/assets/web-panel/assets/{move-CKxVRL_J.js → move-B80G7fLU.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-C80rvQ1J.js → mtc-parser-Djw08NJh.js} +1 -1
- package/src/assets/web-panel/assets/{omit-De5vD7BR.js → omit-Bg_G1eUr.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BTyEDjth.js → pickAttrs-Df9zYUg2.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BWR94AjR.js → placementArrow-DjCDLhJ4.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-1g-Vnibk.js → responsiveObserve--Naz7NgY.js} +1 -1
- package/src/assets/web-panel/assets/{slide-Dmg6dYuF.js → slide-CHn3ald-.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Ddj6rSab.js → statusUtils-BiGwoIK_.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DyP1mPDf.js → styleChecker-Zf2dQx1j.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D3d_0YuY.js → useFlexGapSupport-sLES8nyD.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-M3vq-gE2.js → useFs-DV1Hl4qu.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-GtP2TgtK.js → usePersonalDataHub-CZXr2Qxg.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BurE2ATQ.js → vnode-e8Eo3Oyl.js} +1 -1
- package/src/assets/web-panel/assets/{xterm-BZcWGsqw.js → xterm-zbskxxGA.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Ch-ViiDe.js → zoom-B8A6xKMF.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/compact.js +7 -2
- package/src/data/changelog.json +27 -1
- package/src/harness/jsonl-session-store.js +80 -74
- package/src/harness/prompt-compressor.js +57 -3
- package/src/lib/artifact-store.js +129 -20
- package/src/lib/bounded-artifact-file-read.js +128 -46
- package/src/lib/context-memory-kernel/context-image-transport.js +248 -0
- package/src/lib/context-memory-kernel/jsonl-session-context-port.js +4 -1
- package/src/lib/context-memory-kernel/live-compaction.js +40 -10
- package/src/lib/context-memory-kernel/message-adapter.js +80 -10
- package/src/lib/context-memory-kernel/message-bundle-store.js +1140 -0
- package/src/lib/context-memory-kernel/provider-context.js +23 -8
- package/src/lib/evolution/agent-evolution-ingress.js +103 -19
- package/src/lib/evolution/agent-evolution-runtime-composition.js +65 -27
- package/src/lib/evolution/agent-model-projection.js +90 -18
- package/src/lib/evolution/evidence-json-text.js +341 -42
- package/src/lib/evolution/evolution-artifact-ports.js +1005 -83
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +59 -15
- package/src/lib/evolution/evolution-evidence-projector.js +153 -16
- package/src/lib/evolution/evolution-evidence-storage-layout.js +115 -0
- package/src/lib/evolution/evolution-file-witness.js +7 -3
- package/src/lib/evolution/evolution-ledger-file-manifest-catalog.js +6 -2
- package/src/lib/evolution/evolution-ledger-file-manifest-head-store.js +6 -2
- package/src/lib/evolution/evolution-ledger.js +226 -55
- package/src/lib/evolution/evolution-private-storage.js +20 -0
- package/src/lib/evolution/evolution-run-ledger-adapter.js +298 -11
- package/src/lib/evolution/evolution-windows-directory-durability.js +215 -32
- package/src/lib/evolution/local-ui-evolution-runtime.js +3 -38
- package/src/lib/evolution/local-ui-signing-authority.js +69 -0
- package/src/lib/image-token-estimate.js +59 -0
- package/src/lib/ollama-provider-fetch.js +33 -0
- package/src/lib/provider-stream.js +14 -13
- package/src/lib/read-file-loop-guard.js +7 -4
- package/src/lib/session-history-origins.js +94 -35
- package/src/lib/session-message-provenance.js +26 -2
- package/src/lib/session-runtime-retention.js +10 -1
- package/src/lib/session-transcript-history.js +5 -1
- package/src/lib/session-transcript-migration.js +67 -12
- package/src/lib/storage-failure-cause-codes.js +449 -0
- package/src/lib/tool-result-preview.js +276 -0
- package/src/runtime/agent-core.js +111 -92
- package/src/runtime/headless-stream.js +121 -27
- package/src/assets/web-panel/assets/MarkdownRenderer-D8_iZief.js +0 -1
- package/src/assets/web-panel/assets/Projects-BeSOM6wi.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-Bfhvin8B.js +0 -1
- package/src/assets/web-panel/assets/devWarning-c2I2Rn4_.js +0 -1
- package/src/assets/web-panel/assets/index-CTs4dYcV.js +0 -1
- package/src/assets/web-panel/assets/index-DeuvaW15.js +0 -1
- package/src/assets/web-panel/assets/markdown-CsiA8-E5.js +0 -50
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
canonicalDigest,
|
|
3
|
+
canonicalJson,
|
|
4
|
+
} from "@chainlesschain/context-memory-kernel";
|
|
2
5
|
import {
|
|
3
6
|
contextItemsToMessages,
|
|
4
7
|
messagesToContextItems,
|
|
5
8
|
} from "./context-memory-kernel/message-adapter.js";
|
|
6
9
|
import {
|
|
7
10
|
decodeVerifiedPersistedMessage,
|
|
11
|
+
decodeVerifiedRawPersistedMessage,
|
|
8
12
|
encodePersistedMessage,
|
|
9
13
|
getDurableSystemMessageProvenance,
|
|
10
14
|
DURABLE_SYSTEM_MESSAGE_KINDS,
|
|
@@ -31,8 +35,28 @@ const historyBearing = (entry) =>
|
|
|
31
35
|
derivedSystemKinds.has(
|
|
32
36
|
getDurableSystemMessageProvenance(entry.message)?.kind,
|
|
33
37
|
);
|
|
38
|
+
// Compare conversation identity without dropping system messages, their private
|
|
39
|
+
// provenance, or unknown metadata. Raw receipt fields remain available below
|
|
40
|
+
// for authenticating historical ContextItem source digests.
|
|
41
|
+
const conversationMessages = (messages) =>
|
|
42
|
+
messages.map((message) =>
|
|
43
|
+
decodeVerifiedPersistedMessage(encodePersistedMessage(message)),
|
|
44
|
+
);
|
|
34
45
|
const fingerprint = (messages) =>
|
|
35
|
-
canonicalDigest(messages.map(encodePersistedMessage));
|
|
46
|
+
canonicalDigest(conversationMessages(messages).map(encodePersistedMessage));
|
|
47
|
+
const sameContextItemContent = (left, right) => {
|
|
48
|
+
if (typeof left?.content === "string" || typeof right?.content === "string") {
|
|
49
|
+
return (
|
|
50
|
+
typeof left?.content === "string" &&
|
|
51
|
+
typeof right?.content === "string" &&
|
|
52
|
+
left.content === right.content
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
if (left?.contentRef === undefined || right?.contentRef === undefined) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return canonicalJson(left.contentRef) === canonicalJson(right.contentRef);
|
|
59
|
+
};
|
|
36
60
|
|
|
37
61
|
/**
|
|
38
62
|
* Origins belong to positions in the current display history, never to equal
|
|
@@ -75,12 +99,12 @@ export function createSessionHistoryOrigins() {
|
|
|
75
99
|
appendPersisted(message, ordinal) {
|
|
76
100
|
if (!context) return;
|
|
77
101
|
append(
|
|
78
|
-
|
|
102
|
+
decodeVerifiedRawPersistedMessage(message),
|
|
79
103
|
displayable(message) ? { first: ordinal, last: ordinal } : null,
|
|
80
104
|
);
|
|
81
105
|
},
|
|
82
106
|
appendMappedPersisted(message, origin) {
|
|
83
|
-
append(
|
|
107
|
+
append(decodeVerifiedRawPersistedMessage(message), origin);
|
|
84
108
|
},
|
|
85
109
|
branchPrefix(messages, head, count) {
|
|
86
110
|
if (!context) return null;
|
|
@@ -114,7 +138,7 @@ export function createSessionHistoryOrigins() {
|
|
|
114
138
|
let ordinal = 0;
|
|
115
139
|
replace(
|
|
116
140
|
messages.map((message) => ({
|
|
117
|
-
message:
|
|
141
|
+
message: decodeVerifiedRawPersistedMessage(message),
|
|
118
142
|
origin: displayable(message)
|
|
119
143
|
? { first: ordinal, last: ordinal++ }
|
|
120
144
|
: null,
|
|
@@ -126,21 +150,41 @@ export function createSessionHistoryOrigins() {
|
|
|
126
150
|
let entries = null;
|
|
127
151
|
try {
|
|
128
152
|
if (context) {
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
const rawMessages = context.map((entry) => entry.message);
|
|
154
|
+
// Old compactions hashed raw receipt-bearing bundles; new ones hash
|
|
155
|
+
// conversation projections. Derive exactly these two representations
|
|
156
|
+
// from the same bounded verified context, never from output claims.
|
|
157
|
+
const representations = [rawMessages];
|
|
158
|
+
if (
|
|
159
|
+
rawMessages.some(
|
|
160
|
+
(message) =>
|
|
161
|
+
message.role === "user" &&
|
|
162
|
+
(Object.hasOwn(message, "clientMessageId") ||
|
|
163
|
+
Object.hasOwn(message, "inputDigest")),
|
|
164
|
+
)
|
|
165
|
+
) {
|
|
166
|
+
representations.push(conversationMessages(rawMessages));
|
|
167
|
+
}
|
|
168
|
+
const sources = representations.map((messages) => {
|
|
169
|
+
const items = messagesToContextItems(messages, {
|
|
170
|
+
sessionId: canonical.sessionId,
|
|
171
|
+
allowExternalization: true,
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
items,
|
|
175
|
+
byDigest: new Map(items.map((item) => [item.digest, item])),
|
|
176
|
+
bySequence: new Map(
|
|
177
|
+
items.map((item) => [item.sourceRef.eventSequence, item]),
|
|
178
|
+
),
|
|
179
|
+
};
|
|
180
|
+
});
|
|
139
181
|
const itemEntries = (item) =>
|
|
140
182
|
context.slice(
|
|
141
183
|
item.sourceRef.eventSequence,
|
|
142
184
|
item.sourceRef.eventSequence +
|
|
143
|
-
contextItemsToMessages([item]
|
|
185
|
+
contextItemsToMessages([item], {
|
|
186
|
+
sessionId: canonical.sessionId,
|
|
187
|
+
}).length,
|
|
144
188
|
);
|
|
145
189
|
entries = [...canonical.outputItems]
|
|
146
190
|
.sort(
|
|
@@ -150,13 +194,19 @@ export function createSessionHistoryOrigins() {
|
|
|
150
194
|
left.itemId.localeCompare(right.itemId, "en"),
|
|
151
195
|
)
|
|
152
196
|
.flatMap((item) => {
|
|
153
|
-
const messages = contextItemsToMessages([item]
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
197
|
+
const messages = contextItemsToMessages([item], {
|
|
198
|
+
sessionId: canonical.sessionId,
|
|
199
|
+
});
|
|
200
|
+
const source = sources
|
|
201
|
+
.map(({ bySequence }) =>
|
|
202
|
+
bySequence.get(item.sourceRef.eventSequence),
|
|
203
|
+
)
|
|
204
|
+
.find(
|
|
205
|
+
(candidate) =>
|
|
206
|
+
candidate?.sourceRef.digest === item.sourceRef.digest &&
|
|
207
|
+
sameContextItemContent(candidate, item),
|
|
208
|
+
);
|
|
209
|
+
if (item.sourceRef.store === "cli-jsonl-session" && source) {
|
|
160
210
|
return itemEntries(source);
|
|
161
211
|
}
|
|
162
212
|
let origin = null;
|
|
@@ -165,18 +215,26 @@ export function createSessionHistoryOrigins() {
|
|
|
165
215
|
item.provenance?.parentDigests?.length > 0
|
|
166
216
|
) {
|
|
167
217
|
const digests = item.provenance.parentDigests;
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
218
|
+
if (new Set(digests).size === digests.length) {
|
|
219
|
+
// A summary must name one complete representation. Mixing
|
|
220
|
+
// raw and projected aliases cannot manufacture extra parents.
|
|
221
|
+
for (const { items, byDigest } of sources) {
|
|
222
|
+
if (digests.length > items.length) continue;
|
|
223
|
+
const parents = digests.map((digest) =>
|
|
224
|
+
byDigest.get(digest),
|
|
225
|
+
);
|
|
226
|
+
if (parents.every(Boolean)) {
|
|
227
|
+
origin = span(parents.flatMap(itemEntries));
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
175
231
|
}
|
|
176
232
|
}
|
|
177
233
|
return messages.map((message) => ({ message, origin }));
|
|
178
234
|
});
|
|
179
|
-
const persisted = data.messages.map(
|
|
235
|
+
const persisted = data.messages.map(
|
|
236
|
+
decodeVerifiedRawPersistedMessage,
|
|
237
|
+
);
|
|
180
238
|
if (
|
|
181
239
|
fingerprint(entries.map((entry) => entry.message)) !==
|
|
182
240
|
fingerprint(persisted)
|
|
@@ -189,7 +247,7 @@ export function createSessionHistoryOrigins() {
|
|
|
189
247
|
replace(
|
|
190
248
|
entries ||
|
|
191
249
|
data.messages.map((message) => ({
|
|
192
|
-
message:
|
|
250
|
+
message: decodeVerifiedRawPersistedMessage(message),
|
|
193
251
|
origin: null,
|
|
194
252
|
})),
|
|
195
253
|
);
|
|
@@ -213,13 +271,14 @@ export function createSessionHistoryOrigins() {
|
|
|
213
271
|
start: certificate.start,
|
|
214
272
|
end: certificate.end,
|
|
215
273
|
});
|
|
274
|
+
const persisted = data.messages.map(decodeVerifiedRawPersistedMessage);
|
|
216
275
|
if (
|
|
217
276
|
fingerprint(projected.map((entry) => entry.message)) !==
|
|
218
|
-
fingerprint(
|
|
277
|
+
fingerprint(persisted)
|
|
219
278
|
)
|
|
220
279
|
return false;
|
|
221
|
-
const entries = projected.map(({
|
|
222
|
-
message,
|
|
280
|
+
const entries = projected.map(({ sourceIndexes }, index) => ({
|
|
281
|
+
message: persisted[index],
|
|
223
282
|
origin: span(sourceIndexes.map((index) => context[index])),
|
|
224
283
|
}));
|
|
225
284
|
replace(entries);
|
|
@@ -214,6 +214,18 @@ function cloneWithoutWireTag(snapshot) {
|
|
|
214
214
|
return clean;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
// Input acceptance belongs to the authenticated event, not the provider's
|
|
218
|
+
// conversation message. Keep encodePersistedMessage unchanged so receipt
|
|
219
|
+
// lookup/deduplication still verifies the original event and digest. Apply this
|
|
220
|
+
// only after the full JSON-safe clone, including for historical checkpoints.
|
|
221
|
+
function conversationMessage(clean) {
|
|
222
|
+
if (clean?.role === "user") {
|
|
223
|
+
delete clean.clientMessageId;
|
|
224
|
+
delete clean.inputDigest;
|
|
225
|
+
}
|
|
226
|
+
return clean;
|
|
227
|
+
}
|
|
228
|
+
|
|
217
229
|
function canonicalTag(kind) {
|
|
218
230
|
if (!DURABLE_KINDS.has(kind)) {
|
|
219
231
|
throw new TypeError(`Unsupported durable system message kind: ${kind}`);
|
|
@@ -314,7 +326,7 @@ export function encodePersistedMessage(message) {
|
|
|
314
326
|
* Decode provenance only after the caller has verified the JSONL hash chain
|
|
315
327
|
* and its independent head/count anchor while holding the session lock.
|
|
316
328
|
*/
|
|
317
|
-
export function
|
|
329
|
+
export function decodeVerifiedRawPersistedMessage(message) {
|
|
318
330
|
if (!message || typeof message !== "object") return message;
|
|
319
331
|
if (!isObjectMessage(message)) return null;
|
|
320
332
|
const snapshot = plainDataSnapshot(message);
|
|
@@ -332,6 +344,12 @@ export function decodeVerifiedPersistedMessage(message) {
|
|
|
332
344
|
return clean;
|
|
333
345
|
}
|
|
334
346
|
|
|
347
|
+
/** Verified message replay has a conversation projection distinct from the
|
|
348
|
+
* exact historical payload used to authenticate migration and lineage. */
|
|
349
|
+
export function decodeVerifiedPersistedMessage(message) {
|
|
350
|
+
return conversationMessage(decodeVerifiedRawPersistedMessage(message));
|
|
351
|
+
}
|
|
352
|
+
|
|
335
353
|
/** Strip an untrusted wire field without granting runtime replay authority. */
|
|
336
354
|
export function sanitizePersistedMessage(message) {
|
|
337
355
|
if (!message || typeof message !== "object") return message;
|
|
@@ -340,6 +358,12 @@ export function sanitizePersistedMessage(message) {
|
|
|
340
358
|
return snapshot ? cloneWithoutWireTag(snapshot) : null;
|
|
341
359
|
}
|
|
342
360
|
|
|
361
|
+
/** Conversation replay excludes receipt metadata; generic data sanitation and
|
|
362
|
+
* historical migration digests retain their original representation. */
|
|
363
|
+
export function sanitizeConversationMessage(message) {
|
|
364
|
+
return conversationMessage(sanitizePersistedMessage(message));
|
|
365
|
+
}
|
|
366
|
+
|
|
343
367
|
/** Deep-sanitize an untrusted persisted message array without granting replay. */
|
|
344
368
|
export function sanitizePersistedMessages(messages, options = {}) {
|
|
345
369
|
const strict = options?.strict === true;
|
|
@@ -442,7 +466,7 @@ export function projectCanonicalResumeMessages(messages, options = {}) {
|
|
|
442
466
|
}
|
|
443
467
|
if (isRuntimeOnlySessionMessage(raw)) continue;
|
|
444
468
|
if (role !== "system") {
|
|
445
|
-
projected.push(clean);
|
|
469
|
+
projected.push(conversationMessage(clean));
|
|
446
470
|
} else if (runtimeTag) {
|
|
447
471
|
projected.push(attachRuntimeTag(clean, canonicalTag(runtimeTag.kind)));
|
|
448
472
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/** Bounded live-state retention for long-running agent conversations. */
|
|
2
2
|
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
|
+
import {
|
|
5
|
+
isRuntimeOnlySessionMessage,
|
|
6
|
+
markRuntimeOnlySessionMessage,
|
|
7
|
+
} from "./session-message-provenance.js";
|
|
4
8
|
|
|
5
9
|
export const SESSION_RUNTIME_RETENTION_LIMITS = Object.freeze({
|
|
6
10
|
recentResults: 32,
|
|
@@ -136,7 +140,12 @@ export function releaseOldLiveSessionResults(messages, configured = {}) {
|
|
|
136
140
|
originalChars: content.length,
|
|
137
141
|
retainedChars: projection.content.length,
|
|
138
142
|
});
|
|
139
|
-
|
|
143
|
+
const retained = { ...message, content: projection.content };
|
|
144
|
+
// This is a trusted host clone. Preserve only authority already attached
|
|
145
|
+
// to its source; matching background-result text grants no authority.
|
|
146
|
+
return isRuntimeOnlySessionMessage(message)
|
|
147
|
+
? markRuntimeOnlySessionMessage(retained)
|
|
148
|
+
: retained;
|
|
140
149
|
});
|
|
141
150
|
return {
|
|
142
151
|
messages: output,
|
|
@@ -77,7 +77,11 @@ function isContextCompaction(data) {
|
|
|
77
77
|
}));
|
|
78
78
|
return (
|
|
79
79
|
canonicalDigest(
|
|
80
|
-
content(
|
|
80
|
+
content(
|
|
81
|
+
contextItemsToMessages(canonical.outputItems, {
|
|
82
|
+
sessionId: canonical.sessionId,
|
|
83
|
+
}),
|
|
84
|
+
),
|
|
81
85
|
) === canonicalDigest(content(data.messages))
|
|
82
86
|
);
|
|
83
87
|
} catch {
|
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
appendEvent,
|
|
5
|
+
appendAuthorityEventWithVerifiedProjection,
|
|
5
6
|
findLatestEvent,
|
|
6
7
|
listSessionAuthoritySummaries,
|
|
7
8
|
readVerifiedMessages,
|
|
@@ -12,7 +13,10 @@ import {
|
|
|
12
13
|
getSession as getDatabaseSession,
|
|
13
14
|
listSessions as listDatabaseSessions,
|
|
14
15
|
} from "./session-manager.js";
|
|
15
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
sanitizeConversationMessage,
|
|
18
|
+
sanitizePersistedMessages,
|
|
19
|
+
} from "./session-message-provenance.js";
|
|
16
20
|
|
|
17
21
|
export const SESSION_STORE_MIGRATION_EVENT = "session_store_migrated";
|
|
18
22
|
export const SESSION_STORE_MIGRATION_SCHEMA =
|
|
@@ -71,6 +75,7 @@ export function ensureCanonicalSessionTranscript(
|
|
|
71
75
|
) {
|
|
72
76
|
const deps = {
|
|
73
77
|
appendEvent,
|
|
78
|
+
appendAuthorityEventWithVerifiedProjection,
|
|
74
79
|
findLatestEvent,
|
|
75
80
|
readVerifiedMessages,
|
|
76
81
|
sessionHasPersistedEvidence,
|
|
@@ -113,14 +118,67 @@ export function ensureCanonicalSessionTranscript(
|
|
|
113
118
|
});
|
|
114
119
|
}
|
|
115
120
|
|
|
121
|
+
const migration = {
|
|
122
|
+
schema: SESSION_STORE_MIGRATION_SCHEMA,
|
|
123
|
+
source,
|
|
124
|
+
messagesDigest: digest,
|
|
125
|
+
messageCount: importedMessages.length,
|
|
126
|
+
};
|
|
127
|
+
const conflict = () =>
|
|
128
|
+
migrationError(
|
|
129
|
+
"CC_SESSION_MIGRATION_CONFLICT",
|
|
130
|
+
`canonical transcript already contains different messages: ${id}`,
|
|
131
|
+
{ sessionId: id },
|
|
132
|
+
);
|
|
116
133
|
const currentMessages = deps.readVerifiedMessages(id);
|
|
134
|
+
let recoveredImport = false;
|
|
117
135
|
if (currentMessages.length > 0) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
136
|
+
const snapshot = deps.findLatestEvent(id, "compact");
|
|
137
|
+
if (snapshot?.data?.reason === "physical-store-import") {
|
|
138
|
+
// Conversation replay omits input receipt metadata. Recover an interrupted
|
|
139
|
+
// import only from the exact raw snapshot, never normalized equality alone.
|
|
140
|
+
// Recheck both evidence and live replay under the marker's writer lock.
|
|
141
|
+
deps.appendAuthorityEventWithVerifiedProjection(
|
|
142
|
+
id,
|
|
143
|
+
SESSION_STORE_MIGRATION_EVENT,
|
|
144
|
+
migration,
|
|
145
|
+
{
|
|
146
|
+
createProjection: () => {
|
|
147
|
+
let latest = null;
|
|
148
|
+
let completed = false;
|
|
149
|
+
return {
|
|
150
|
+
accept(event) {
|
|
151
|
+
if (event.type === "compact") latest = event.data;
|
|
152
|
+
if (event.type === SESSION_STORE_MIGRATION_EVENT)
|
|
153
|
+
completed = true;
|
|
154
|
+
},
|
|
155
|
+
finish: () => ({ latest, completed }),
|
|
156
|
+
};
|
|
157
|
+
},
|
|
158
|
+
validateProjection({ latest, completed }, authority) {
|
|
159
|
+
if (
|
|
160
|
+
completed ||
|
|
161
|
+
latest?.reason !== "physical-store-import" ||
|
|
162
|
+
!Array.isArray(latest.messages) ||
|
|
163
|
+
messagesDigest(latest.messages) !== digest ||
|
|
164
|
+
// Old snapshots did not record a source label. Their exact raw
|
|
165
|
+
// source bytes remain the only available import identity proof.
|
|
166
|
+
(Object.hasOwn(latest, "migration") &&
|
|
167
|
+
(latest.migration?.schema !== migration.schema ||
|
|
168
|
+
latest.migration.source !== source ||
|
|
169
|
+
latest.migration.messagesDigest !== digest)) ||
|
|
170
|
+
messagesDigest(authority.readMessages()) !==
|
|
171
|
+
messagesDigest(
|
|
172
|
+
importedMessages.map(sanitizeConversationMessage),
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
throw conflict();
|
|
176
|
+
},
|
|
177
|
+
},
|
|
123
178
|
);
|
|
179
|
+
recoveredImport = true;
|
|
180
|
+
} else if (messagesDigest(currentMessages) !== digest) {
|
|
181
|
+
throw conflict();
|
|
124
182
|
}
|
|
125
183
|
} else if (importedMessages.length > 0) {
|
|
126
184
|
deps.appendEvent(id, "compact", {
|
|
@@ -128,15 +186,12 @@ export function ensureCanonicalSessionTranscript(
|
|
|
128
186
|
originalMessages: importedMessages.length,
|
|
129
187
|
compressedMessages: importedMessages.length,
|
|
130
188
|
reason: "physical-store-import",
|
|
189
|
+
migration,
|
|
131
190
|
});
|
|
132
191
|
}
|
|
133
192
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
source,
|
|
137
|
-
messagesDigest: digest,
|
|
138
|
-
messageCount: importedMessages.length,
|
|
139
|
-
});
|
|
193
|
+
if (!recoveredImport)
|
|
194
|
+
deps.appendEvent(id, SESSION_STORE_MIGRATION_EVENT, migration);
|
|
140
195
|
return Object.freeze({
|
|
141
196
|
sessionId: id,
|
|
142
197
|
migrated: true,
|