chainlesschain 0.166.76 → 0.166.78
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 +19 -8
- package/completions/_cc +1 -1
- package/completions/cc.bash +1 -1
- package/completions/cc.fish +1 -1
- package/completions/cc.ps1 +1 -1
- package/package.json +1 -1
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +10 -0
- package/src/assets/linux-subreaper/linux-arm64/supervisor +0 -0
- package/src/assets/linux-subreaper/linux-x64/manifest.json +10 -0
- package/src/assets/linux-subreaper/linux-x64/supervisor +0 -0
- package/src/assets/web-panel/assets/{AIOps-CNaejClV.js → AIOps-DSyZEY2G.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CF_CVKT_.js → ActionButton-DhNyZ577.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-a3Z6J7gv.js → Analytics-HMMpxmyi.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BFtWEnct.js → AppLayout-CwKMM5Ie.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-BQ8oeMvX.js → Artifacts-CNzDmph7.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-NOo9bmgk.js → Audit-DxWpUW3V.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-QRc7F3Tp.js → BackgroundAgents-C1R2ST-P.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-UlVgLn2P.js → Backup-B6biTaEV.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BER9LJAr.js → BaseInput-CVnkD2Z5.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Z8z2Fdfz.js → Chat-Dbewl4Je.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-DdmuBrdQ.js → ChatBubbleRenderer-DVZ6SwC5.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-CXPgyB8L.js → Checkbox-BqqiF1JE.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-D1vOsLJ7.js → Codegen-BVMkGumc.js} +1 -1
- package/src/assets/web-panel/assets/{Col-ucLnUJC7.js → Col-DmiRHy96.js} +1 -1
- package/src/assets/web-panel/assets/{Community-COsV9n9t.js → Community-BDlpygqA.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-D0EkBEYh.js → Compact-B2NME_m-.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-C8w9SUjt.js → Compliance-BlzDLE-R.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CmVaKEJS.js → Cowork-C8raPybB.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-B_FiMMV2.js → Cron-DA8Py0zP.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-ByO3YL8N.js → Crosschain-DU2XyHqB.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DwpsLM9r.js → DID-Df098fT_.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-B_8IUvM_.js → Dashboard-D1rT702x.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Bo6WQkuX.js → Dropdown-BweXGo1O.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C9LiQesx.js → EmailListRenderer-B9ShbgJH.js} +1 -1
- package/src/assets/web-panel/assets/EvolutionSettings-D75_iBoc.js +1 -0
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dst6VUnO.js → FamilyGuardDashboard-DrznZFVs.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Ci7CoLkJ.js → Federation-DQZ2adIA.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-bdDyUhUM.js → FormItemContext-DN30Dowh.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CrRwOUVi.js → GenericCardRenderer-DRdt0j1e.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Dis8h-Z-.js → Git-wwRgStzk.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DX7OH5w2.js → Governance-CI4Uw0Nh.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Cavv_Q_Z.js → Inference-5TuE2AJI.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Cck8tnZn.js → KnowledgeGraph-oXyvmFSR.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BQt3aGMu.js → Logs-ewudSWuv.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-Cz5nyufm.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-CdmAKNSN.js → Marketplace-DcZeWFrs.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BUlJdyPY.js → McpTools-BcV9p1RS.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-DQRTQDr-.js → Memory-CMhYvugt.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C0dnxgsl.js → MobileBridge-5RP2uwvT.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DQ5Gy7fa.js → MobileProjects-BIuM9Ze4.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Xl7u2isS.js → Mtc-DmBszTDe.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-C3KX0574.js → MtcAudit-Czdp5ZGt.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-CHEhfkn8.js → Multisig-DRWUuNr-.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Ce38mH-8.js → NLProgramming-IRQQN0-c.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-C7nuTd7c.js → Notes-CGhD1lW9.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-BcoEcyq8.js → NotificationSettings-BtyPgQAh.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-D-t5hKkx.js → OrderTableRenderer-yUaqwCty.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-C_BGi4xi.js → Organization-C3kTVn5i.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BodhraDq.js → Overflow-C2-0iZhq.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BTa3sAIy.js → P2P-CISoEUxA.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BjZslP9T.js → PdhVaultBrowser-NfTVtvKQ.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-u3UDzGef.js → Permissions-CfK0jJhm.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-Cb7ybv65.js → PersonalDataHub-OsVxxh_j.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-CS24k-P7.js → Pipeline-DEmK_Ch2.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Ddj6Kqs7.js → Privacy-D61s73b0.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Bg5uQIgg.js → ProjectInit-DkLF5gHb.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-AmPR8T12.js → ProjectSettings-BA7odTrI.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DGSbAyTK.js → Projects-CdI1GcAG.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Dc1C3lbB.js → Providers-D9BYyP1r.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-Cv3HXpce.js → QrScannerModal-CXMItUDD.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-3dpbXARb.js → QuickAsk-8-tF9ffZ.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-5aGRVnJK.js → Recommend-C2QGWOSi.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-CTS2jx0p.js → RemoteSession-B1M_v1lx.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BxaKI0hY.js → Reputation-D0WZHgv1.js} +1 -1
- package/src/assets/web-panel/assets/{Row-C23uQdwd.js → Row-D6nf9-c-.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-ssX9YOhm.js → RssFeed-ClZ6M-mN.js} +3 -3
- package/src/assets/web-panel/assets/{Search-C24GogII.js → Search-ZWkt8vuO.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DdAcGKkk.js → Security-BUlQut2m.js} +3 -3
- package/src/assets/web-panel/assets/{Services-D0dCiEuq.js → Services-Cd_3xJOc.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DEY44o0v.js → Skeleton-C8e2-cHW.js} +1 -1
- package/src/assets/web-panel/assets/Skills-DucVRJp1.js +1 -0
- package/src/assets/web-panel/assets/{Sla-B_bbo2vB.js → Sla-Csr5pUwI.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-CXvyaRAT.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-CpIXql0Z.js → SyncSettings-KdsIcV5h.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-B-eHmJm9.js +1 -0
- package/src/assets/web-panel/assets/{Templates-C_44nVPq.js → Templates-BglVeaLK.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CyZ2ey2P.js → Tenant-BBbQ8qan.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DwGNHWnp.js → Terminal-Ca_pCVBi.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BTAHNkqU.js → TimelineRenderer-YD6XG_vZ.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DCJWkUwc.js → Tokens-2lRoeVli.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BCjDO9-E.js → Trigger-C-3XNAU9.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-_YS8WbRb.js → Trust-k-1PxdLG.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-m6R8xGq7.js → UkeySign-FG-qW646.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-xOfk29c4.js → VideoEditing-BNOe1cmd.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-B1Gw0awc.js → Wallet-D5C3i2Kw.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CHK5ft18.js → WebAuthn-BOpztqd3.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-DEp1ukQQ.js → WorkflowEditor-BpVrpUEv.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B2sFizun.js → chat-DIuMHb38.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DJ17YV1E.js → colors-CTFJPyzQ.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CBhJJgEC.js → compact-item-CONfmJcW.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BZkpvNJy.js → createContext-RkW5CRrz.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DaEBln_q.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-C0ZKo6Ei.js → hasIn-CW4XOjDC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bc3vVG2X.js → index-7wMSBCU7.js} +1 -1
- package/src/assets/web-panel/assets/{index-vFMwiAN4.js → index-Akmg1WdH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOBXNMdh.js → index-B54qoVff.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLo8Ls9u.js → index-B8r2t0Ch.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7gv9dvb.js → index-B9XoBoty.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHtpMr1G.js → index-B9aS2VLu.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dxe0YlZe.js → index-BFs1Tznc.js} +1 -1
- package/src/assets/web-panel/assets/{index-DumLgj1t.js → index-BKgaRT0b.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNp6HKFh.js → index-BM7bOUvu.js} +1 -1
- package/src/assets/web-panel/assets/{index-DM0rWF6z.js → index-BMg2JFmW.js} +1 -1
- package/src/assets/web-panel/assets/{index-4oULtRqE.js → index-BRZsPxNn.js} +1 -1
- package/src/assets/web-panel/assets/{index-LPPe0val.js → index-Bf19fKef.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ctguam0K.js → index-BkAbfBF-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DrU5xVpF.js → index-CBjb2A5R.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCOr6Q27.js → index-CEZWQthY.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9gYiACH.js → index-CFGLf88d.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZW84cEf.js → index-CLUa68JH.js} +3 -3
- package/src/assets/web-panel/assets/{index-BoDUYyuo.js → index-CM2X25Er.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyiCbHeL.js → index-CX4T2uKN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW5o1Gar.js → index-CixqfdRk.js} +1 -1
- package/src/assets/web-panel/assets/{index-5K2z_tgO.js → index-CkRojEip.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOfPp5OV.js → index-Cvmc3f25.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdxJm-HB.js → index-D-lpTPS8.js} +1 -1
- package/src/assets/web-panel/assets/{index-8ueG48gl.js → index-D59GbWCN.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMxOoITz.js → index-DAESljiJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLMr5KMd.js → index-DDHUx4Yz.js} +1 -1
- package/src/assets/web-panel/assets/index-DG1mcYTa.js +1 -0
- package/src/assets/web-panel/assets/{index-BGIvhCPl.js → index-DP5pPedy.js} +1 -1
- package/src/assets/web-panel/assets/index-DRs5Pe8u.js +1 -0
- package/src/assets/web-panel/assets/{index-DjdSFO0d.js → index-DSlXL6Ju.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cn5UzvgR.js → index-DWCJnn2O.js} +1 -1
- package/src/assets/web-panel/assets/{index-Chct9tL8.js → index-DWY7YwDu.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEnd5fiz.js → index-DZTwP364.js} +1 -1
- package/src/assets/web-panel/assets/{index-KzNhWykP.js → index-DidrMvOx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BpyrhOeh.js → index-Dj3K5kHs.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZlkPrxb.js → index-YaeGscSw.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dfgxe-fw.js → index-YlMnFNOi.js} +1 -1
- package/src/assets/web-panel/assets/{index-IHgzfc1u.js → index-asWsB34i.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJkoJzTU.js → index-gkjiFjQd.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Cqfoq0TJ.js → initDefaultProps-BOr4igh3.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CIiVJHNu.js → motion-CK469n2j.js} +1 -1
- package/src/assets/web-panel/assets/{move-CFl1o_A8.js → move-DzjudlYQ.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DYoCxcZ1.js → mtc-parser-BQaKUxC6.js} +1 -1
- package/src/assets/web-panel/assets/{omit-C1P2q5TY.js → omit-MciovCFD.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BtTRpJtC.js → pickAttrs-DDPJ4zAz.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Cst2PcNM.js → placementArrow-Cznyb-jI.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CF5kalV2.js → responsiveObserve-AJK3SLzJ.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CtHGqpXN.js → slide-CPQ28wu7.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-N__biHXf.js → statusUtils-CFjzvqf_.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DR8V_H-i.js → styleChecker-BPyFfTuR.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D274dqun.js → useFlexGapSupport-Dq7N6R05.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BwHLYU5b.js → useFs-C3GS0uTc.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BiA-hVqt.js → usePersonalDataHub-BhgIVzP_.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-Bugl94dy.js → vnode-4ZD9-MDr.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DEFl8GCu.js → zoom-Bx4MRVNW.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/command-manifest.json +1 -1
- package/src/commands/checkpoint.js +42 -7
- package/src/commands/orchestrate.js +85 -25
- package/src/commands/session-location.js +5 -0
- package/src/commands/session-show.js +109 -1
- package/src/commands/session.js +26 -2
- package/src/commands/tokens.js +9 -4
- package/src/data/changelog.json +26 -0
- package/src/generated/cc-agent-protocol.schema.json +71 -0
- package/src/harness/jsonl-session-store.js +357 -114
- package/src/harness/mcp-client.js +44 -1
- package/src/lib/agent-router.js +35 -7
- package/src/lib/app-server/server.js +14 -0
- package/src/lib/background-agent-supervisor.js +14 -4
- package/src/lib/causal-observability.js +64 -1
- package/src/lib/checkpoint-summary-projection.js +98 -0
- package/src/lib/checkpoint-timeline-authority.js +15 -51
- package/src/lib/claude-code-bridge.js +302 -60
- package/src/lib/codex-app-server-adapter.js +161 -35
- package/src/lib/cost-budget.js +4 -0
- package/src/lib/decision-layer/providers.js +84 -9
- package/src/lib/decision-layer/runtime.js +86 -49
- package/src/lib/direct-model-usage.js +14 -3
- package/src/lib/doctor-checkup.js +31 -2
- package/src/lib/durable-security-store.js +6 -1
- package/src/lib/evolution/evolution-artifact-identity.js +21 -0
- package/src/lib/evolution/evolution-artifact-ports.js +5 -11
- package/src/lib/evolution/evolution-eval-cohort-receipt-reconciliation.js +389 -0
- package/src/lib/execution-location-failure-site.js +63 -0
- package/src/lib/execution-location-target.js +102 -8
- package/src/lib/external-agent-adapters.js +2 -0
- package/src/lib/image-file-boundary.js +154 -0
- package/src/lib/image-input.js +16 -3
- package/src/lib/llm-pricing.js +114 -8
- package/src/lib/mcp-call-ledger-store.js +7 -2
- package/src/lib/model-capabilities.js +21 -10
- package/src/lib/model-context-catalog.js +60 -1
- package/src/lib/openai-responses.js +7 -1
- package/src/lib/orchestrator.js +8 -2
- package/src/lib/process-execution-broker/index.js +93 -1
- package/src/lib/process-execution-broker/linux-subreaper-artifact.js +120 -0
- package/src/lib/process-execution-broker/linux-subreaper-helper.js +344 -0
- package/src/lib/process-execution-broker/linux-subreaper-process.js +326 -0
- package/src/lib/process-execution-broker/linux-subreaper-supervisor.c +360 -0
- package/src/lib/process-execution-broker/owned-posix-process-group-worker.mjs +131 -0
- package/src/lib/process-execution-broker/owned-posix-process-group.js +267 -0
- package/src/lib/process-execution-broker/process-ownership-journal.js +297 -0
- package/src/lib/process-execution-broker/process-ownership-quarantine.js +91 -0
- package/src/lib/runtime-usage-ledger.js +3 -0
- package/src/lib/secure-fs.js +158 -42
- package/src/lib/session-branch-history.js +240 -0
- package/src/lib/session-history-origins.js +285 -0
- package/src/lib/session-input-receipt.js +110 -0
- package/src/lib/session-resource-budget.js +8 -8
- package/src/lib/session-transcript-history.js +456 -0
- package/src/lib/session-transcript-page.js +164 -0
- package/src/lib/session-transcript-reference.js +38 -0
- package/src/lib/session-usage.js +8 -0
- package/src/lib/token-tracker.js +32 -54
- package/src/lib/usage-pricing-context.js +93 -0
- package/src/runtime/headless-runner.js +8 -0
- package/src/runtime/headless-stream.js +202 -4
- package/src/assets/web-panel/assets/EvolutionSettings-Pc1IpRfk.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-BIUeeiVA.js +0 -1
- package/src/assets/web-panel/assets/Skills-CYt0Mu2W.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-a2BBjtTL.js +0 -1
- package/src/assets/web-panel/assets/Tasks-BYQKU-GL.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DZhu13vj.js +0 -1
- package/src/assets/web-panel/assets/index-C6iFyQYz.js +0 -1
- package/src/assets/web-panel/assets/index-CztThH9f.js +0 -1
|
@@ -2,6 +2,7 @@ import { canonicalDigest } from "@chainlesschain/context-memory-kernel";
|
|
|
2
2
|
import {
|
|
3
3
|
CONTEXT_WINDOWS,
|
|
4
4
|
DOCUMENTED_OPENAI_MODELS,
|
|
5
|
+
DOCUMENTED_ANTHROPIC_MODELS,
|
|
5
6
|
LEGACY_MODEL_PROVIDERS,
|
|
6
7
|
MODEL_CAPABILITY_CATALOG_VERSION,
|
|
7
8
|
} from "./model-context-catalog.js";
|
|
@@ -61,7 +62,7 @@ function deepFreeze(value) {
|
|
|
61
62
|
return Object.freeze(value);
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
function
|
|
65
|
+
function isOfficialModelBaseUrl(provider, baseUrl) {
|
|
65
66
|
if (baseUrl == null || baseUrl === "") return true;
|
|
66
67
|
if (typeof baseUrl !== "string") {
|
|
67
68
|
throw new TypeError("baseUrl must be a string when provided");
|
|
@@ -71,7 +72,10 @@ function isOfficialOpenAIBaseUrl(baseUrl) {
|
|
|
71
72
|
// decorations and non-default ports. Never return or hash the input URL.
|
|
72
73
|
return (
|
|
73
74
|
baseUrl === baseUrl.trim() &&
|
|
74
|
-
new URL(baseUrl).href ===
|
|
75
|
+
new URL(baseUrl).href ===
|
|
76
|
+
(provider === "openai"
|
|
77
|
+
? "https://api.openai.com/v1"
|
|
78
|
+
: "https://api.anthropic.com/v1")
|
|
75
79
|
);
|
|
76
80
|
} catch {
|
|
77
81
|
return false;
|
|
@@ -137,13 +141,17 @@ export function resolveModelCapabilityProfile({
|
|
|
137
141
|
"contextMemoryModelWindowTokens",
|
|
138
142
|
{ min: 1024, max: MAX_CONTEXT_WINDOW_TOKENS },
|
|
139
143
|
);
|
|
144
|
+
const catalog =
|
|
145
|
+
selectedProvider === "openai"
|
|
146
|
+
? DOCUMENTED_OPENAI_MODELS
|
|
147
|
+
: selectedProvider === "anthropic"
|
|
148
|
+
? DOCUMENTED_ANTHROPIC_MODELS
|
|
149
|
+
: null;
|
|
140
150
|
const officialEndpoint =
|
|
141
|
-
|
|
151
|
+
Boolean(catalog) && isOfficialModelBaseUrl(selectedProvider, baseUrl);
|
|
142
152
|
const documented =
|
|
143
|
-
officialEndpoint &&
|
|
144
|
-
|
|
145
|
-
Object.hasOwn(DOCUMENTED_OPENAI_MODELS, selectedModel)
|
|
146
|
-
? DOCUMENTED_OPENAI_MODELS[selectedModel]
|
|
153
|
+
officialEndpoint && selectedModel && Object.hasOwn(catalog, selectedModel)
|
|
154
|
+
? catalog[selectedModel]
|
|
147
155
|
: null;
|
|
148
156
|
const legacyOwner =
|
|
149
157
|
selectedModel && Object.hasOwn(LEGACY_MODEL_PROVIDERS, selectedModel)
|
|
@@ -213,9 +221,9 @@ export function resolveModelCapabilityProfile({
|
|
|
213
221
|
"The model's legacy catalog entry belongs to another provider and was not applied.",
|
|
214
222
|
);
|
|
215
223
|
}
|
|
216
|
-
if (
|
|
224
|
+
if (catalog && !officialEndpoint) {
|
|
217
225
|
limitations.push(
|
|
218
|
-
|
|
226
|
+
`Official ${selectedProvider === "openai" ? "OpenAI" : "Anthropic"} model specifications are not applied to a custom endpoint.`,
|
|
219
227
|
);
|
|
220
228
|
}
|
|
221
229
|
if (output.requestMaxOutputTokens === null) {
|
|
@@ -234,7 +242,7 @@ export function resolveModelCapabilityProfile({
|
|
|
234
242
|
);
|
|
235
243
|
}
|
|
236
244
|
if (
|
|
237
|
-
documented &&
|
|
245
|
+
documented?.advertisedMaxOutputTokens != null &&
|
|
238
246
|
output.requestMaxOutputTokens > documented.advertisedMaxOutputTokens
|
|
239
247
|
) {
|
|
240
248
|
limitations.push(
|
|
@@ -263,6 +271,9 @@ export function resolveModelCapabilityProfile({
|
|
|
263
271
|
runtimeVerified: false,
|
|
264
272
|
...output,
|
|
265
273
|
advertisedMaxOutputTokens: documented?.advertisedMaxOutputTokens ?? null,
|
|
274
|
+
...(documented?.reasoningEfforts
|
|
275
|
+
? { reasoningEfforts: [...documented.reasoningEfforts] }
|
|
276
|
+
: {}),
|
|
266
277
|
sources: documented ? [...documented.sources] : [],
|
|
267
278
|
limitations,
|
|
268
279
|
};
|
|
@@ -45,7 +45,7 @@ export const CONTEXT_WINDOWS = Object.freeze({
|
|
|
45
45
|
}),
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
export const MODEL_CAPABILITY_CATALOG_VERSION = "2026-09-
|
|
48
|
+
export const MODEL_CAPABILITY_CATALOG_VERSION = "2026-09-27";
|
|
49
49
|
|
|
50
50
|
// Explicit ownership prevents a model name served by an unrelated provider
|
|
51
51
|
// from silently inheriting another provider's catalog window.
|
|
@@ -97,9 +97,68 @@ export const DOCUMENTED_OPENAI_MODELS = Object.freeze({
|
|
|
97
97
|
contextWindowTokens: 1050000,
|
|
98
98
|
advertisedMaxOutputTokens: 128000,
|
|
99
99
|
requiresResponsesForTools: true,
|
|
100
|
+
reasoningEfforts: Object.freeze(["low", "medium", "high", "xhigh", "max"]),
|
|
101
|
+
pricing: Object.freeze({ in: 10, out: 50 }),
|
|
100
102
|
sources: Object.freeze([
|
|
101
103
|
"https://developers.openai.com/api/docs/models/gpt-6-astra",
|
|
102
104
|
"https://developers.openai.com/api/docs/guides/migrate-to-responses",
|
|
103
105
|
]),
|
|
104
106
|
}),
|
|
107
|
+
...Object.fromEntries(
|
|
108
|
+
[
|
|
109
|
+
["gpt-6-sol", 2, 10],
|
|
110
|
+
["gpt-6-luna", 0.1, 0.5],
|
|
111
|
+
].map(([model, input, output]) => [
|
|
112
|
+
model,
|
|
113
|
+
Object.freeze({
|
|
114
|
+
contextWindowTokens: 1050000,
|
|
115
|
+
advertisedMaxOutputTokens: 128000,
|
|
116
|
+
requiresResponsesForTools: true,
|
|
117
|
+
reasoningEfforts: Object.freeze([
|
|
118
|
+
"none",
|
|
119
|
+
"low",
|
|
120
|
+
"medium",
|
|
121
|
+
"high",
|
|
122
|
+
"xhigh",
|
|
123
|
+
"max",
|
|
124
|
+
]),
|
|
125
|
+
pricing: Object.freeze({ in: input, out: output }),
|
|
126
|
+
sources: Object.freeze([
|
|
127
|
+
`https://developers.openai.com/api/docs/models/${model}`,
|
|
128
|
+
]),
|
|
129
|
+
}),
|
|
130
|
+
]),
|
|
131
|
+
),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
export const DOCUMENTED_ANTHROPIC_MODELS = Object.freeze({
|
|
135
|
+
"claude-opus-5-5": Object.freeze({
|
|
136
|
+
contextWindowTokens: 1000000,
|
|
137
|
+
// The release notes establish the window and pricing, not an output cap.
|
|
138
|
+
advertisedMaxOutputTokens: null,
|
|
139
|
+
pricing: Object.freeze({ in: 4, out: 20 }),
|
|
140
|
+
sources: Object.freeze([
|
|
141
|
+
"https://code.claude.com/docs/en/changelog#2-1-280",
|
|
142
|
+
]),
|
|
143
|
+
}),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Request-level pricing terms shared by cost reporting and hard budget gates.
|
|
147
|
+
// Never apply these tiers to a sum of multiple requests.
|
|
148
|
+
export const GPT6_PRICING_TERMS = Object.freeze({
|
|
149
|
+
cacheReadMultiplier: 0.1,
|
|
150
|
+
cacheWriteMultiplier: 1.25,
|
|
151
|
+
longContext: Object.freeze({
|
|
152
|
+
threshold: 272000,
|
|
153
|
+
inputMultiplier: 2,
|
|
154
|
+
outputMultiplier: 1.5,
|
|
155
|
+
}),
|
|
156
|
+
serviceMultipliers: Object.freeze({
|
|
157
|
+
standard: 1,
|
|
158
|
+
default: 1,
|
|
159
|
+
auto: 1,
|
|
160
|
+
batch: 0.5,
|
|
161
|
+
flex: 0.5,
|
|
162
|
+
fast: 2,
|
|
163
|
+
}),
|
|
105
164
|
});
|
|
@@ -300,7 +300,13 @@ export function normalizeOpenAIResponsesResponse(data) {
|
|
|
300
300
|
responseId: printableString(data.id) || null,
|
|
301
301
|
};
|
|
302
302
|
const usage = normalizeOpenAIResponsesUsage(data.usage);
|
|
303
|
-
if (usage)
|
|
303
|
+
if (usage)
|
|
304
|
+
result.usage = {
|
|
305
|
+
...usage,
|
|
306
|
+
...(typeof data.service_tier === "string"
|
|
307
|
+
? { service_tier: data.service_tier }
|
|
308
|
+
: {}),
|
|
309
|
+
};
|
|
304
310
|
return result;
|
|
305
311
|
}
|
|
306
312
|
|
package/src/lib/orchestrator.js
CHANGED
|
@@ -141,13 +141,16 @@ export class Orchestrator extends EventEmitter {
|
|
|
141
141
|
// Multi-path agent router
|
|
142
142
|
this._router =
|
|
143
143
|
options.agentRouter ||
|
|
144
|
-
(options.agents
|
|
144
|
+
(Array.isArray(options.agents?.backends)
|
|
145
145
|
? new AgentRouter({
|
|
146
146
|
backends: options.agents.backends || [],
|
|
147
147
|
strategy: options.agents.strategy || "round-robin",
|
|
148
148
|
maxParallel: this.maxParallel,
|
|
149
149
|
})
|
|
150
|
-
: AgentRouter.autoDetect({
|
|
150
|
+
: AgentRouter.autoDetect({
|
|
151
|
+
maxParallel: this.maxParallel,
|
|
152
|
+
strategy: options.agents?.strategy,
|
|
153
|
+
}));
|
|
151
154
|
|
|
152
155
|
// Multi-channel notification manager
|
|
153
156
|
this.notifier =
|
|
@@ -188,6 +191,9 @@ export class Orchestrator extends EventEmitter {
|
|
|
188
191
|
*/
|
|
189
192
|
async addTask(description, opts = {}) {
|
|
190
193
|
assertCLILegacyMutationAllowed("Orchestrator.addTask");
|
|
194
|
+
// Reject opaque external CLIs before notifications, Run creation or paid
|
|
195
|
+
// decomposition. This preflight never replaces the dispatch ingress gate.
|
|
196
|
+
this._router.assertDispatchAvailable?.();
|
|
191
197
|
const task = {
|
|
192
198
|
id: generateId("task"),
|
|
193
199
|
description,
|
|
@@ -46,6 +46,14 @@ import {
|
|
|
46
46
|
SANDBOX_BOUNDARIES,
|
|
47
47
|
} from "./platform-sandbox.js";
|
|
48
48
|
import { normalizeLinuxCgroupPolicy } from "./linux-cgroup-v2.js";
|
|
49
|
+
import { acquireLinuxSubreaperHelper } from "./linux-subreaper-helper.js";
|
|
50
|
+
import { spawnLinuxSubreaperChild } from "./linux-subreaper-process.js";
|
|
51
|
+
import {
|
|
52
|
+
assertProcessOwnershipAvailable,
|
|
53
|
+
getProcessOwnershipStatus,
|
|
54
|
+
observeProcessOwnership,
|
|
55
|
+
prepareProcessOwnership,
|
|
56
|
+
} from "./process-ownership-quarantine.js";
|
|
49
57
|
import {
|
|
50
58
|
MACOS_MCP_LAUNCHER_INPUTS,
|
|
51
59
|
isMacosMcpLauncherPackageVersion,
|
|
@@ -1187,6 +1195,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1187
1195
|
_sanitizeOptions(options) {
|
|
1188
1196
|
if (!options) return {};
|
|
1189
1197
|
const safe = { ...options };
|
|
1198
|
+
delete safe.linuxSubreaper;
|
|
1190
1199
|
if (process.platform === "win32" && safe.shell === true) {
|
|
1191
1200
|
safe.windowsHide = true;
|
|
1192
1201
|
}
|
|
@@ -4479,6 +4488,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4479
4488
|
* and durable evidence APIs.
|
|
4480
4489
|
*/
|
|
4481
4490
|
beginWorkspaceTransaction(options = {}) {
|
|
4491
|
+
assertProcessOwnershipAvailable();
|
|
4482
4492
|
return this._workspaceTransactionManager(
|
|
4483
4493
|
options.stateDir,
|
|
4484
4494
|
options.lockDir,
|
|
@@ -4486,6 +4496,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4486
4496
|
}
|
|
4487
4497
|
|
|
4488
4498
|
recoverWorkspaceTransactions(options = {}) {
|
|
4499
|
+
assertProcessOwnershipAvailable();
|
|
4489
4500
|
return this._workspaceTransactionManager(
|
|
4490
4501
|
options.stateDir,
|
|
4491
4502
|
options.lockDir,
|
|
@@ -4499,6 +4510,10 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4499
4510
|
).inspect(id);
|
|
4500
4511
|
}
|
|
4501
4512
|
|
|
4513
|
+
getProcessOwnershipStatus() {
|
|
4514
|
+
return getProcessOwnershipStatus();
|
|
4515
|
+
}
|
|
4516
|
+
|
|
4502
4517
|
listWorkspaceTransactions(options = {}) {
|
|
4503
4518
|
return this._workspaceTransactionManager(
|
|
4504
4519
|
options.stateDir,
|
|
@@ -4507,6 +4522,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4507
4522
|
}
|
|
4508
4523
|
|
|
4509
4524
|
restoreWorkspaceTransaction(id, options = {}) {
|
|
4525
|
+
assertProcessOwnershipAvailable();
|
|
4510
4526
|
return this._workspaceTransactionManager(
|
|
4511
4527
|
options.stateDir,
|
|
4512
4528
|
options.lockDir,
|
|
@@ -4514,6 +4530,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4514
4530
|
}
|
|
4515
4531
|
|
|
4516
4532
|
undoWorkspaceTransactionRestore(id, options = {}) {
|
|
4533
|
+
assertProcessOwnershipAvailable();
|
|
4517
4534
|
return this._workspaceTransactionManager(
|
|
4518
4535
|
options.stateDir,
|
|
4519
4536
|
options.lockDir,
|
|
@@ -4569,6 +4586,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4569
4586
|
}
|
|
4570
4587
|
|
|
4571
4588
|
spawn(command, args, options = {}) {
|
|
4589
|
+
assertProcessOwnershipAvailable();
|
|
4572
4590
|
options = this._withAmbientProcessContext(command, options);
|
|
4573
4591
|
const executionId = crypto.randomUUID();
|
|
4574
4592
|
const startTime = Date.now();
|
|
@@ -4800,7 +4818,71 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4800
4818
|
);
|
|
4801
4819
|
auditEntry.mcpStdioExecutableIdentityDigest = admitted.identityDigest;
|
|
4802
4820
|
}
|
|
4803
|
-
|
|
4821
|
+
if (
|
|
4822
|
+
process.platform === "linux" &&
|
|
4823
|
+
options.linuxSubreaper &&
|
|
4824
|
+
!sandboxPlan.guarantees.includes(SANDBOX_BOUNDARIES.PROCESS_TREE)
|
|
4825
|
+
) {
|
|
4826
|
+
const request = options.linuxSubreaper;
|
|
4827
|
+
const stdio = optsForSpawn.stdio;
|
|
4828
|
+
if (
|
|
4829
|
+
!request ||
|
|
4830
|
+
typeof request !== "object" ||
|
|
4831
|
+
Array.isArray(request) ||
|
|
4832
|
+
Object.keys(request).some((key) => key !== "graceMs") ||
|
|
4833
|
+
!Number.isSafeInteger(request.graceMs) ||
|
|
4834
|
+
request.graceMs < 0 ||
|
|
4835
|
+
request.graceMs > 2147483647 ||
|
|
4836
|
+
sandboxPlan.postSpawn.required ||
|
|
4837
|
+
options.shell ||
|
|
4838
|
+
optsForSpawn.shell ||
|
|
4839
|
+
optsForSpawn.detached ||
|
|
4840
|
+
(stdio !== undefined && stdio !== "pipe") ||
|
|
4841
|
+
["uid", "gid", "signal", "timeout", "input", "argv0"].some(
|
|
4842
|
+
(key) => optsForSpawn[key] !== undefined,
|
|
4843
|
+
) ||
|
|
4844
|
+
(sandboxPlan.applied && sandboxPlan.backend !== "linux-prlimit")
|
|
4845
|
+
) {
|
|
4846
|
+
const error = new Error(
|
|
4847
|
+
"Linux external-agent supervision cannot preserve this launch plan",
|
|
4848
|
+
);
|
|
4849
|
+
error.code = "EXTERNAL_AGENT_SUPERVISION_UNSUPPORTED_PLAN";
|
|
4850
|
+
throw error;
|
|
4851
|
+
}
|
|
4852
|
+
const ownershipLease = prepareProcessOwnership(executionId);
|
|
4853
|
+
let nativeEntered = false;
|
|
4854
|
+
try {
|
|
4855
|
+
const helper = acquireLinuxSubreaperHelper({
|
|
4856
|
+
spawnSync: this._native?.spawnSync || nativeSpawnSync,
|
|
4857
|
+
});
|
|
4858
|
+
proc = spawnLinuxSubreaperChild(
|
|
4859
|
+
command,
|
|
4860
|
+
args,
|
|
4861
|
+
{
|
|
4862
|
+
cwd: path.resolve(optsForSpawn.cwd || cwd),
|
|
4863
|
+
env: optsForSpawn.env || process.env,
|
|
4864
|
+
graceMs: request.graceMs,
|
|
4865
|
+
helper,
|
|
4866
|
+
},
|
|
4867
|
+
{
|
|
4868
|
+
spawn: (...nativeArgs) => {
|
|
4869
|
+
nativeEntered = true;
|
|
4870
|
+
return nativeSpawnFn(...nativeArgs);
|
|
4871
|
+
},
|
|
4872
|
+
},
|
|
4873
|
+
);
|
|
4874
|
+
} catch (error) {
|
|
4875
|
+
// Before native entry no process could exist. Once entered, retain
|
|
4876
|
+
// the durable record even if a synchronous exception hides its handle.
|
|
4877
|
+
if (!nativeEntered) ownershipLease?.settle();
|
|
4878
|
+
else ownershipLease?.retain();
|
|
4879
|
+
throw error;
|
|
4880
|
+
}
|
|
4881
|
+
auditEntry.processLifecycleOwner = "linux-subreaper";
|
|
4882
|
+
observeProcessOwnership(proc, executionId, ownershipLease);
|
|
4883
|
+
} else {
|
|
4884
|
+
proc = nativeSpawnFn(command, args, optsForSpawn);
|
|
4885
|
+
}
|
|
4804
4886
|
if (builtInMacMcpPlan) {
|
|
4805
4887
|
const callerLifeline = proc?.stdio?.[8];
|
|
4806
4888
|
if (
|
|
@@ -4912,6 +4994,10 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4912
4994
|
|
|
4913
4995
|
proc.on("exit", (code, signal) => {
|
|
4914
4996
|
const endTime = Date.now();
|
|
4997
|
+
if (proc.ownedProcessTreeEvidence) {
|
|
4998
|
+
auditEntry.processLifecycleReceipt = proc.ownedProcessTreeEvidence;
|
|
4999
|
+
auditEntry.sandboxTargetPid = proc.sandboxTargetPid;
|
|
5000
|
+
}
|
|
4915
5001
|
auditEntry.exitCode = code;
|
|
4916
5002
|
auditEntry.signal = signal;
|
|
4917
5003
|
auditEntry.endTime = endTime;
|
|
@@ -4929,6 +5015,10 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4929
5015
|
this.emit("exit", auditEntry);
|
|
4930
5016
|
});
|
|
4931
5017
|
proc.on("error", (err) => {
|
|
5018
|
+
if (proc.ownedProcessTreeEvidence) {
|
|
5019
|
+
auditEntry.processLifecycleReceipt = proc.ownedProcessTreeEvidence;
|
|
5020
|
+
auditEntry.sandboxTargetPid = proc.sandboxTargetPid;
|
|
5021
|
+
}
|
|
4932
5022
|
auditEntry.error = err.message;
|
|
4933
5023
|
auditEntry.endTime = Date.now();
|
|
4934
5024
|
auditEntry.durationMs = auditEntry.endTime - startTime;
|
|
@@ -4957,6 +5047,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
4957
5047
|
}
|
|
4958
5048
|
|
|
4959
5049
|
spawnSync(command, args, options = {}) {
|
|
5050
|
+
assertProcessOwnershipAvailable();
|
|
4960
5051
|
options = this._withAmbientProcessContext(command, options);
|
|
4961
5052
|
const executionId = crypto.randomUUID();
|
|
4962
5053
|
const startTime = Date.now();
|
|
@@ -5203,6 +5294,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
5203
5294
|
* together with the descriptor-pinned generic bwrap plan.
|
|
5204
5295
|
*/
|
|
5205
5296
|
spawnPty(ptyModule, command, args = [], options = {}) {
|
|
5297
|
+
assertProcessOwnershipAvailable();
|
|
5206
5298
|
if (!ptyModule || typeof ptyModule.spawn !== "function") {
|
|
5207
5299
|
throw new TypeError("pty_module_spawn_unavailable");
|
|
5208
5300
|
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export const LINUX_SUBREAPER_SOURCE_DIGEST =
|
|
4
|
+
"sha256:e920e24b4a79121484f2e8e97886755f88eaa1af93b55326dfa68c7a7f571424";
|
|
5
|
+
export const LINUX_SUBREAPER_ARCHITECTURES = Object.freeze(["x64", "arm64"]);
|
|
6
|
+
export const MAX_SUBREAPER_IMAGE_BYTES = 4 * 1024 * 1024;
|
|
7
|
+
export const MAX_SUBREAPER_MANIFEST_BYTES = 4096;
|
|
8
|
+
|
|
9
|
+
export function subreaperDigest(bytes) {
|
|
10
|
+
return "sha256:" + crypto.createHash("sha256").update(bytes).digest("hex");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function invalid(reason) {
|
|
14
|
+
const error = new Error(
|
|
15
|
+
`Linux process supervision helper unavailable: ${reason}`,
|
|
16
|
+
);
|
|
17
|
+
error.code = "EXTERNAL_AGENT_HELPER_UNAVAILABLE";
|
|
18
|
+
return error;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Bounded ELF64 inspection; release images have no dynamic loader dependency. */
|
|
22
|
+
export function validateLinuxSubreaperElf(bytes, { arch, staticOnly = false }) {
|
|
23
|
+
const machine = arch === "x64" ? 62 : arch === "arm64" ? 183 : null;
|
|
24
|
+
if (
|
|
25
|
+
!machine ||
|
|
26
|
+
!Buffer.isBuffer(bytes) ||
|
|
27
|
+
bytes.length < 64 ||
|
|
28
|
+
bytes.length > MAX_SUBREAPER_IMAGE_BYTES ||
|
|
29
|
+
!bytes.subarray(0, 4).equals(Buffer.from([0x7f, 0x45, 0x4c, 0x46])) ||
|
|
30
|
+
bytes[4] !== 2 ||
|
|
31
|
+
bytes[5] !== 1 ||
|
|
32
|
+
bytes[6] !== 1 ||
|
|
33
|
+
bytes.readUInt16LE(18) !== machine ||
|
|
34
|
+
![2, 3].includes(bytes.readUInt16LE(16)) ||
|
|
35
|
+
bytes.readUInt32LE(20) !== 1 ||
|
|
36
|
+
bytes.readUInt16LE(52) !== 64 ||
|
|
37
|
+
bytes.readUInt16LE(54) !== 56
|
|
38
|
+
)
|
|
39
|
+
throw invalid("unexpected-helper-image");
|
|
40
|
+
const offset = bytes.readBigUInt64LE(32);
|
|
41
|
+
const count = bytes.readUInt16LE(56);
|
|
42
|
+
if (
|
|
43
|
+
offset < 64n ||
|
|
44
|
+
count < 1 ||
|
|
45
|
+
count > 128 ||
|
|
46
|
+
offset + BigInt(count * 56) > BigInt(bytes.length)
|
|
47
|
+
)
|
|
48
|
+
throw invalid("invalid-helper-program-headers");
|
|
49
|
+
const entry = bytes.readBigUInt64LE(24);
|
|
50
|
+
let executableEntry = false;
|
|
51
|
+
for (let index = 0; index < count; index++) {
|
|
52
|
+
const at = Number(offset) + index * 56;
|
|
53
|
+
const type = bytes.readUInt32LE(at);
|
|
54
|
+
if (staticOnly && [2, 3].includes(type))
|
|
55
|
+
throw invalid("helper-is-not-static");
|
|
56
|
+
if (type !== 1) continue;
|
|
57
|
+
const fileOffset = bytes.readBigUInt64LE(at + 8);
|
|
58
|
+
const address = bytes.readBigUInt64LE(at + 16);
|
|
59
|
+
const fileSize = bytes.readBigUInt64LE(at + 32);
|
|
60
|
+
const memorySize = bytes.readBigUInt64LE(at + 40);
|
|
61
|
+
if (fileSize > memorySize || fileOffset + fileSize > BigInt(bytes.length))
|
|
62
|
+
throw invalid("invalid-helper-load-segment");
|
|
63
|
+
if (
|
|
64
|
+
bytes.readUInt32LE(at + 4) & 1 &&
|
|
65
|
+
entry >= address &&
|
|
66
|
+
entry < address + fileSize
|
|
67
|
+
)
|
|
68
|
+
executableEntry = true;
|
|
69
|
+
}
|
|
70
|
+
if (!executableEntry || (staticOnly && bytes.readUInt16LE(16) !== 2))
|
|
71
|
+
throw invalid("invalid-helper-entry");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function validateLinuxSubreaperArtifact(
|
|
75
|
+
manifestBytes,
|
|
76
|
+
imageBytes,
|
|
77
|
+
{ arch, commit } = {},
|
|
78
|
+
) {
|
|
79
|
+
if (
|
|
80
|
+
!Buffer.isBuffer(manifestBytes) ||
|
|
81
|
+
manifestBytes.length > MAX_SUBREAPER_MANIFEST_BYTES
|
|
82
|
+
)
|
|
83
|
+
throw invalid("invalid-packaged-manifest");
|
|
84
|
+
let manifest;
|
|
85
|
+
try {
|
|
86
|
+
manifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
87
|
+
} catch {
|
|
88
|
+
throw invalid("invalid-packaged-manifest");
|
|
89
|
+
}
|
|
90
|
+
const keys = [
|
|
91
|
+
"schema",
|
|
92
|
+
"platform",
|
|
93
|
+
"arch",
|
|
94
|
+
"sourceDigest",
|
|
95
|
+
"imageDigest",
|
|
96
|
+
"bytes",
|
|
97
|
+
"linkage",
|
|
98
|
+
"commit",
|
|
99
|
+
];
|
|
100
|
+
if (
|
|
101
|
+
!manifest ||
|
|
102
|
+
typeof manifest !== "object" ||
|
|
103
|
+
Array.isArray(manifest) ||
|
|
104
|
+
Object.keys(manifest).length !== keys.length ||
|
|
105
|
+
Object.keys(manifest).some((key) => !keys.includes(key)) ||
|
|
106
|
+
manifest.schema !== "chainlesschain.linux-subreaper-artifact/v1" ||
|
|
107
|
+
manifest.platform !== "linux" ||
|
|
108
|
+
!LINUX_SUBREAPER_ARCHITECTURES.includes(arch) ||
|
|
109
|
+
manifest.arch !== arch ||
|
|
110
|
+
manifest.sourceDigest !== LINUX_SUBREAPER_SOURCE_DIGEST ||
|
|
111
|
+
manifest.linkage !== "static" ||
|
|
112
|
+
!/^[a-f0-9]{40}$/.test(manifest.commit) ||
|
|
113
|
+
(commit !== undefined && manifest.commit !== commit) ||
|
|
114
|
+
manifest.bytes !== imageBytes.length ||
|
|
115
|
+
manifest.imageDigest !== subreaperDigest(imageBytes)
|
|
116
|
+
)
|
|
117
|
+
throw invalid("packaged-identity-mismatch");
|
|
118
|
+
validateLinuxSubreaperElf(imageBytes, { arch, staticOnly: true });
|
|
119
|
+
return Object.freeze({ ...manifest });
|
|
120
|
+
}
|