chainlesschain 0.166.34 → 0.166.37
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/package.json +2 -2
- package/src/assets/web-panel/assets/{AIOps-D8PJmSrh.js → AIOps-B_Nt1Qe4.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DG6DqHA3.js → ActionButton-CHQbie4X.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DiLleeWs.js → Analytics-Bm9364Lw.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DxYkhlHK.js → AppLayout-DTwlIh2v.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-BAW3Kdsi.js → Artifacts-OibP0qB4.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DBr4uY6E.js → Audit-B8Fwavkg.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Dw0r-bHX.js → BackgroundAgents-p1Vb2K2B.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-AyhwYsio.js → Backup-BI3QT-wI.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Cj8qJotr.js → BaseInput-BW_VRWWu.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DcvimQ0u.js → Chat-CUEhDQfq.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer--joJ1e2f.js → ChatBubbleRenderer-C5UVXdVE.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C2mlU77l.js → Checkbox-URYsaaxv.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CAfc3YaV.js → Codegen-DJAwC80a.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CIxoxtJI.js → Col-DfRKFzc9.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DvufZoRg.js → Community-GOkGHuly.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-55JTa99J.js → Compact-CIMs13NC.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BllWog6P.js → Compliance-BE-TQIxV.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-ThsFGc5p.js → Cowork-CYmbJiWw.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-CZjl5Ig2.js → Cron-Be3OIWyM.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DIAKAoQT.js → Crosschain-2xB2HS2D.js} +1 -1
- package/src/assets/web-panel/assets/{DID-ayygwEil.js → DID-B_lJO2yF.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C3Xjm2UO.js → Dashboard-DnVWqUER.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-C1S3zf-j.js → Dropdown-C7ZJvHVa.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DRvriU-H.js → EmailListRenderer-DLevT-0F.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-iSX2bmsD.js → FamilyGuardDashboard-BwhQ5BRU.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Dk0Stkv-.js → Federation-BkGI-Xkq.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DasXSGff.js → FormItemContext-BgIIbMd7.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Dv9XGlxI.js → GenericCardRenderer-qL-qN8Nb.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B5PgXL3Z.js → Git-BTzgrC4U.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-B78x11e_.js → Governance-p28vdCN4.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-b7CX1RqW.js → Inference-Cqephrur.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph--MgBzMVp.js → KnowledgeGraph-C3v5Q4Zp.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CYCiGmVc.js → Logs-T6f0w32w.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-yrl10SWw.js → MarkdownRenderer-Dj5XPm3S.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CsbwQ0eM.js → Marketplace-ClDsvHDH.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-0GBWHVra.js → McpTools-C4P-_snx.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-fAywmAYr.js → Memory-BZZfG6y6.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BeNEyy3s.js → MobileBridge-DpIv_BLs.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-Buz3NIQg.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CqRhJB70.js → Mtc-HS2PJB79.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-BEyGZflc.js → MtcAudit-UmBrcU27.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-luz3EBT2.js → Multisig-C00sXiZf.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Dkbvp8IX.js → NLProgramming-Dj1ng_ph.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Cf9I2K8j.js → Notes-C4LEVKlk.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-BTfuzynL.js → NotificationSettings-BWXwnekv.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CZHfK8Nn.js +1 -0
- package/src/assets/web-panel/assets/{Organization-BbG3-vDy.js → Organization-CFEtFPrV.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CMtFKEIQ.js → Overflow-DSz4MJK1.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-6SAEb_lU.js → P2P-DyTEytwG.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-B5QNGLVx.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-ClZxZKZl.js → Permissions-wEC_X7x4.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BYkyoZDT.js → PersonalDataHub-If5GZlGZ.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-B28ZgADI.js → Pipeline-LB4gqqmX.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BxtZywbB.js → Privacy-QVLhoxcN.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DPqoRnxK.js → ProjectInit-FaAbTYTo.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-QjKvMkau.js → ProjectSettings-DhMeNA21.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Cp0Z8ZG0.js → Projects-5L4lkWAZ.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-CrS-rbyb.js → Providers-DhZFp8fO.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-xTrhbVAU.js → QrScannerModal-BZuJ7_xi.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DFOqJoq-.js → QuickAsk-TXddPYYb.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DXlKqu2-.js → Recommend-DDuXIKYt.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BLLaZH8K.js → RemoteSession-CDrTXImv.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-CUgAdJ11.js → Reputation-B2xKaKzt.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DzOO3wP-.js → Row-DzAjWAOX.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B6GrRvh8.js → RssFeed-CKH38BLF.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Cj3zKLb3.js → Search-CuPqJYoQ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-LnktzidI.js → Security-DmAd2hxz.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BQ6sIc2K.js → Services-Bt3nljnY.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CCSV3Jbw.js → Skeleton-CP7RH093.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CpoQ4SNk.js → Skills-DKNeMBTx.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DbAbgRPq.js → Sla-CbpM8Nrd.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C4cJ_hoD.js → SpeechSettings-DTk-vTzF.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BKFzjN9Z.js → SyncSettings-DKiplwmc.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-z-lOm8fx.js +1 -0
- package/src/assets/web-panel/assets/{Templates-DTEQfFAQ.js → Templates-Rb-Q0DGX.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-wToJWKXB.js → Tenant-C2sqDUnR.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-1s3c7kmF.js → Terminal-DcyzskEE.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BcfsYW3u.js → TimelineRenderer-lg0Eam7N.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Byez6FY0.js → Tokens-D9USIMIA.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Cq8mZO88.js → Trigger-BQpaQJ5k.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DUrMmEwR.js → Trust-C-Mik04s.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CVHwXrVU.js → UkeySign-DrnZ_o56.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CDKbTRUS.js → VideoEditing-BDOsoZi0.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BqnEBIOy.js → Wallet-Ct_bleI7.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CeTMpj7_.js → WebAuthn-B6b6FDao.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-F6OgjV3C.js → WorkflowEditor-ZUJMaIHr.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CMHUCwq3.js → chat-BII20OJy.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DzVM_fpJ.js → colors-DEsJRV3n.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Hhmg51yT.js → compact-item-DoDYAzN9.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-SwHt7x3Q.js → createContext-o_nofnVW.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-0tgDCszN.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-HGNKkn9A.js → hasIn-CAsABTHC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cc-d6f0F.js → index-B0ApxOMw.js} +1 -1
- package/src/assets/web-panel/assets/{index-E-bI8HpV.js → index-B4SfcwZA.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJqNTF1S.js → index-B9Z75LfA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgoefbLs.js → index-B9hYHPhs.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDtzUt75.js → index-BDRh3v44.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_HgLPC5.js → index-BcYbQoY7.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1QJxiOL.js → index-Bmwo5wQG.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChLHLBkF.js → index-Bn2ZPUXO.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5dcWBqg.js → index-BnbnmRqg.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq9MMKno.js → index-Bqyg3PME.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ba2Kszdy.js → index-BrIIJ2s-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDt4wSl6.js → index-BxT8yTwS.js} +1 -1
- package/src/assets/web-panel/assets/{index-COOcGOyK.js → index-Bycj011d.js} +1 -1
- package/src/assets/web-panel/assets/{index-DQT5thlV.js → index-BzMA6Ra3.js} +1 -1
- package/src/assets/web-panel/assets/{index-F7Grz3-G.js → index-C1YDdyQ1.js} +1 -1
- package/src/assets/web-panel/assets/{index-jrRtmiUh.js → index-CE2J04dA.js} +1 -1
- package/src/assets/web-panel/assets/index-CFF8XEFE.js +1 -0
- package/src/assets/web-panel/assets/{index-BDE-WiE5.js → index-CQE-WMEU.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6YQN5_R.js → index-CVQSl1uY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlHB5eax.js → index-CeJSTcXw.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-YkiVyL.js → index-CeWJqXNX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRikmONJ.js → index-Cf3sFEoE.js} +1 -1
- package/src/assets/web-panel/assets/{index-MDdTkUpA.js → index-D5Fd4tdL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMG_2fK2.js → index-DDQzBK3l.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co4RcBua.js → index-DQmX_-hk.js} +1 -1
- package/src/assets/web-panel/assets/{index--iOqM_AI.js → index-DRAA2McB.js} +1 -1
- package/src/assets/web-panel/assets/{index-pwLuJGFh.js → index-DU2Rpx1m.js} +1 -1
- package/src/assets/web-panel/assets/index-DVUEISry.js +1 -0
- package/src/assets/web-panel/assets/{index-AQcDW8bB.js → index-DWZNYecl.js} +3 -3
- package/src/assets/web-panel/assets/{index-oz0Xxs8D.js → index-D_CMB_wC.js} +1 -1
- package/src/assets/web-panel/assets/{index-aKV4Py_2.js → index-Dbb34cAr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BstLYy9q.js → index-DciLb_Ww.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyZUrnje.js → index-Dgt1mKby.js} +1 -1
- package/src/assets/web-panel/assets/{index-sYkFp9A4.js → index-Dhnau6uw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDhCx17_.js → index-DrsAF-Ar.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dcg7nQDe.js → index-DsoFTdA2.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWkWh48N.js → index-TSwbtCYG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cnm4zroJ.js → index-kIyLNyoF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BmPYmoY3.js → index-tCeNfxv4.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C_2QM45F.js → initDefaultProps-CNjeeoKE.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DkxY04tR.js → motion-CBT8IZDm.js} +1 -1
- package/src/assets/web-panel/assets/{move-D0CJlA7D.js → move-h1MOxjqv.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DjP38YUD.js → mtc-parser-C_3pqNmn.js} +1 -1
- package/src/assets/web-panel/assets/{omit-C9CJDaGT.js → omit-CMUnPFDk.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D5Wq2fa8.js → pickAttrs-p8_c1xq0.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DJ6Dixs7.js → placementArrow-D6O67r23.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DMmM0Dee.js → responsiveObserve-DquhepAK.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DipmpYA-.js → slide-CZ-m6gmS.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DSqw6_nU.js → statusUtils-k9ejZFtd.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-t828MYjI.js → styleChecker-NX6_137R.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-COsSNzDQ.js → useFlexGapSupport-bCqR70lP.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Bq5IEzv_.js → useFs-2l0vSqyY.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CUKM0HdW.js → usePersonalDataHub-1yccm4O7.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-l-JwAt2M.js → vnode-CxQzajDo.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-D7xkW-gD.js → zoom-CrTKwFyb.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/hub.js +21 -6
- package/src/commands/llm.js +4 -3
- package/src/commands/stream.js +28 -7
- package/src/commands/ui.js +10 -2
- package/src/data/changelog.json +39 -0
- package/src/gateways/ws/chat-intent-protocol.js +4 -1
- package/src/gateways/ws/llm-chat-protocol.js +29 -3
- package/src/gateways/ws/message-dispatcher.js +3 -1
- package/src/gateways/ws/personal-data-hub-protocol.js +24 -10
- package/src/gateways/ws/session-core-protocol.js +23 -6
- package/src/gateways/ws/session-protocol.js +1 -0
- package/src/lib/__tests__/provider-stream.test.js +6 -8
- package/src/lib/chat-core.js +67 -9
- package/src/lib/chat-intent-service.js +138 -39
- package/src/lib/evolution/evolution-artifact-ports.js +40 -3
- package/src/lib/evolution/evolution-deployment-loader.js +7 -1
- package/src/lib/evolution/evolution-file-identity.js +50 -0
- package/src/lib/evolution/evolution-file-witness.js +206 -91
- package/src/lib/evolution/evolution-ledger-file-backend.js +4 -0
- package/src/lib/evolution/evolution-ledger.js +37 -5
- package/src/lib/evolution/evolution-witness-segments.js +330 -0
- package/src/lib/evolution/governed-hub-llm.js +56 -0
- package/src/lib/evolution/governed-hub-resolver.js +65 -0
- package/src/lib/evolution/governed-hub-skill.js +36 -0
- package/src/lib/evolution/governed-model-turn.js +88 -0
- package/src/lib/evolution/progressive-canary-external-watchdog.js +6 -4
- package/src/lib/evolution/skill-candidate-registry.js +45 -11
- package/src/lib/evolution/skill-release-registry.js +46 -12
- package/src/lib/llm-connection-probe.js +21 -4
- package/src/lib/personal-data-hub-wiring.js +49 -0
- package/src/lib/provider-stream.js +94 -45
- package/src/lib/ws-chat-handler.js +19 -2
- package/src/assets/web-panel/assets/MobileProjects-Zt1cpErd.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-DBmCtl2H.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-CWG2OLvh.js +0 -7
- package/src/assets/web-panel/assets/Tasks-Cf4bl7NS.js +0 -1
- package/src/assets/web-panel/assets/devWarning-5q_Y0E88.js +0 -1
- package/src/assets/web-panel/assets/index-dl9TJMh5.js +0 -1
- package/src/assets/web-panel/assets/index-x0DDgUaT.js +0 -1
|
@@ -321,13 +321,29 @@ async function streamRun(message, sender, signal, context) {
|
|
|
321
321
|
const { buildProviderSource } = await import("../../lib/provider-stream.js");
|
|
322
322
|
const { createStreamRouter } = await loadSingletons();
|
|
323
323
|
const router = createStreamRouter();
|
|
324
|
-
const
|
|
325
|
-
model
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
324
|
+
const { prepareGovernedModelTurn, governModelTokenSource } =
|
|
325
|
+
await import("../../lib/evolution/governed-model-turn.js");
|
|
326
|
+
const turn = await prepareGovernedModelTurn(
|
|
327
|
+
context?.server?.evolutionCompositionFactory ?? null,
|
|
328
|
+
{
|
|
329
|
+
mode: "ws-stream",
|
|
330
|
+
messages: [{ role: "user", content: message.prompt }],
|
|
331
|
+
signal,
|
|
332
|
+
},
|
|
333
|
+
);
|
|
334
|
+
const source = governModelTokenSource(
|
|
335
|
+
buildProviderSource(provider, {
|
|
336
|
+
model: message.model,
|
|
337
|
+
baseUrl: message.baseUrl,
|
|
338
|
+
apiKey: message.apiKey,
|
|
339
|
+
prompt: message.prompt,
|
|
340
|
+
messages: turn.governed ? turn.messages : undefined,
|
|
341
|
+
requireCompletion: turn.governed,
|
|
342
|
+
signal,
|
|
343
|
+
}),
|
|
344
|
+
turn,
|
|
329
345
|
signal,
|
|
330
|
-
|
|
346
|
+
);
|
|
331
347
|
|
|
332
348
|
let envelopeHelper = null;
|
|
333
349
|
if (context?.server?.envelopeBus && message.sessionId) {
|
|
@@ -368,6 +384,7 @@ async function streamRun(message, sender, signal, context) {
|
|
|
368
384
|
}
|
|
369
385
|
}
|
|
370
386
|
if (errored) return fail("STREAM_ERROR", errorMsg);
|
|
387
|
+
signal?.throwIfAborted();
|
|
371
388
|
return ok({ text });
|
|
372
389
|
}
|
|
373
390
|
|
|
@@ -592,6 +592,7 @@ async function ensureSessionHandler(
|
|
|
592
592
|
handler = new WSChatHandler({
|
|
593
593
|
session,
|
|
594
594
|
interaction: session.interaction,
|
|
595
|
+
evolutionCompositionFactory: server.evolutionCompositionFactory ?? null,
|
|
595
596
|
});
|
|
596
597
|
} else {
|
|
597
598
|
const { WSAgentHandler } = await import("./ws-agent-handler.js");
|
|
@@ -34,14 +34,12 @@ function mockFetch(
|
|
|
34
34
|
ok,
|
|
35
35
|
status,
|
|
36
36
|
statusText,
|
|
37
|
-
body: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}),
|
|
44
|
-
},
|
|
37
|
+
body: new ReadableStream({
|
|
38
|
+
pull(controller) {
|
|
39
|
+
if (i < chunks.length) controller.enqueue(enc.encode(chunks[i++]));
|
|
40
|
+
else controller.close();
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
45
43
|
};
|
|
46
44
|
});
|
|
47
45
|
}
|
package/src/lib/chat-core.js
CHANGED
|
@@ -98,7 +98,11 @@ async function _deliverToken(onToken, token, guard) {
|
|
|
98
98
|
try {
|
|
99
99
|
await onToken(token);
|
|
100
100
|
} catch (error) {
|
|
101
|
-
if (
|
|
101
|
+
if (
|
|
102
|
+
options.requireCompletion ||
|
|
103
|
+
error?.isOutputBackpressureFailure === true
|
|
104
|
+
)
|
|
105
|
+
throw error;
|
|
102
106
|
// Generic UI callbacks retain their historical best-effort semantics.
|
|
103
107
|
} finally {
|
|
104
108
|
guard.bump();
|
|
@@ -117,6 +121,7 @@ export async function streamOllama(
|
|
|
117
121
|
onToken,
|
|
118
122
|
onUsage,
|
|
119
123
|
onStall,
|
|
124
|
+
options = {},
|
|
120
125
|
) {
|
|
121
126
|
const guard = makeStallGuard(STREAM_STALL_MS, { onHint: onStall });
|
|
122
127
|
guard.bump();
|
|
@@ -130,7 +135,9 @@ export async function streamOllama(
|
|
|
130
135
|
messages,
|
|
131
136
|
stream: true,
|
|
132
137
|
}),
|
|
133
|
-
signal:
|
|
138
|
+
signal: options.signal
|
|
139
|
+
? AbortSignal.any([guard.signal, options.signal])
|
|
140
|
+
: guard.signal,
|
|
134
141
|
});
|
|
135
142
|
} catch (e) {
|
|
136
143
|
guard.stop();
|
|
@@ -149,6 +156,7 @@ export async function streamOllama(
|
|
|
149
156
|
const reader = response.body.getReader();
|
|
150
157
|
const decoder = new TextDecoder();
|
|
151
158
|
let fullResponse = "";
|
|
159
|
+
let completed = false;
|
|
152
160
|
// Buffer incomplete lines across reads: an NDJSON line can be split across two
|
|
153
161
|
// stream chunks (TCP doesn't align to '\n'), so parsing each chunk in
|
|
154
162
|
// isolation would drop the split line entirely (both halves fail JSON.parse).
|
|
@@ -169,6 +177,9 @@ export async function streamOllama(
|
|
|
169
177
|
if (!line) continue;
|
|
170
178
|
try {
|
|
171
179
|
const json = JSON.parse(line);
|
|
180
|
+
if (options.requireCompletion && json.error)
|
|
181
|
+
throw new Error("Ollama stream returned an error");
|
|
182
|
+
if (json.done === true) completed = true;
|
|
172
183
|
if (json.message?.content) {
|
|
173
184
|
fullResponse += json.message.content;
|
|
174
185
|
await _deliverToken(onToken, json.message.content, guard);
|
|
@@ -181,7 +192,11 @@ export async function streamOllama(
|
|
|
181
192
|
}
|
|
182
193
|
}
|
|
183
194
|
} catch (error) {
|
|
184
|
-
if (
|
|
195
|
+
if (
|
|
196
|
+
options.requireCompletion ||
|
|
197
|
+
error?.isOutputBackpressureFailure === true
|
|
198
|
+
)
|
|
199
|
+
throw error;
|
|
185
200
|
// Partial JSON, skip
|
|
186
201
|
}
|
|
187
202
|
}
|
|
@@ -196,6 +211,9 @@ export async function streamOllama(
|
|
|
196
211
|
guard.stop();
|
|
197
212
|
}
|
|
198
213
|
|
|
214
|
+
options.signal?.throwIfAborted();
|
|
215
|
+
if (options.requireCompletion && !completed)
|
|
216
|
+
throw new Error("Model stream ended before its completion marker");
|
|
199
217
|
return fullResponse;
|
|
200
218
|
}
|
|
201
219
|
|
|
@@ -210,6 +228,7 @@ export async function streamOpenAI(
|
|
|
210
228
|
onToken,
|
|
211
229
|
onUsage,
|
|
212
230
|
onStall,
|
|
231
|
+
options = {},
|
|
213
232
|
) {
|
|
214
233
|
const guard = makeStallGuard(STREAM_STALL_MS, { onHint: onStall });
|
|
215
234
|
guard.bump();
|
|
@@ -229,7 +248,9 @@ export async function streamOpenAI(
|
|
|
229
248
|
// Servers that don't understand it simply ignore it.
|
|
230
249
|
stream_options: { include_usage: true },
|
|
231
250
|
}),
|
|
232
|
-
signal:
|
|
251
|
+
signal: options.signal
|
|
252
|
+
? AbortSignal.any([guard.signal, options.signal])
|
|
253
|
+
: guard.signal,
|
|
233
254
|
});
|
|
234
255
|
} catch (e) {
|
|
235
256
|
guard.stop();
|
|
@@ -248,6 +269,7 @@ export async function streamOpenAI(
|
|
|
248
269
|
const reader = response.body.getReader();
|
|
249
270
|
const decoder = new TextDecoder();
|
|
250
271
|
let fullResponse = "";
|
|
272
|
+
let completed = false;
|
|
251
273
|
// Buffer incomplete lines across reads: an SSE `data:` line can be split
|
|
252
274
|
// across two stream chunks, so parsing each chunk in isolation would drop the
|
|
253
275
|
// split line (both halves fail JSON.parse) — losing content and usage. Keep
|
|
@@ -267,9 +289,14 @@ export async function streamOpenAI(
|
|
|
267
289
|
for (const line of lines) {
|
|
268
290
|
if (line.startsWith("data: ")) {
|
|
269
291
|
const data = line.slice(6);
|
|
270
|
-
if (data === "[DONE]")
|
|
292
|
+
if (data === "[DONE]") {
|
|
293
|
+
completed = true;
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
271
296
|
try {
|
|
272
297
|
const json = JSON.parse(data);
|
|
298
|
+
if (options.requireCompletion && json.error)
|
|
299
|
+
throw new Error("OpenAI stream returned an error");
|
|
273
300
|
const content = json.choices?.[0]?.delta?.content;
|
|
274
301
|
if (content) {
|
|
275
302
|
fullResponse += content;
|
|
@@ -287,7 +314,11 @@ export async function streamOpenAI(
|
|
|
287
314
|
}
|
|
288
315
|
}
|
|
289
316
|
} catch (error) {
|
|
290
|
-
if (
|
|
317
|
+
if (
|
|
318
|
+
options.requireCompletion ||
|
|
319
|
+
error?.isOutputBackpressureFailure === true
|
|
320
|
+
)
|
|
321
|
+
throw error;
|
|
291
322
|
// Partial data
|
|
292
323
|
}
|
|
293
324
|
}
|
|
@@ -301,6 +332,9 @@ export async function streamOpenAI(
|
|
|
301
332
|
guard.stop();
|
|
302
333
|
}
|
|
303
334
|
|
|
335
|
+
options.signal?.throwIfAborted();
|
|
336
|
+
if (options.requireCompletion && !completed)
|
|
337
|
+
throw new Error("Model stream ended before its completion marker");
|
|
304
338
|
return fullResponse;
|
|
305
339
|
}
|
|
306
340
|
|
|
@@ -317,6 +351,7 @@ export async function streamAnthropic(
|
|
|
317
351
|
onToken,
|
|
318
352
|
onUsage,
|
|
319
353
|
onStall,
|
|
354
|
+
options = {},
|
|
320
355
|
) {
|
|
321
356
|
// Split out a leading system prompt (Anthropic requires it as top-level
|
|
322
357
|
// `system`, not an OpenAI-style role=system message).
|
|
@@ -348,7 +383,9 @@ export async function streamAnthropic(
|
|
|
348
383
|
...(system ? { system } : {}),
|
|
349
384
|
messages: convo,
|
|
350
385
|
}),
|
|
351
|
-
signal:
|
|
386
|
+
signal: options.signal
|
|
387
|
+
? AbortSignal.any([guard.signal, options.signal])
|
|
388
|
+
: guard.signal,
|
|
352
389
|
});
|
|
353
390
|
} catch (e) {
|
|
354
391
|
guard.stop();
|
|
@@ -369,6 +406,7 @@ export async function streamAnthropic(
|
|
|
369
406
|
const reader = response.body.getReader();
|
|
370
407
|
const decoder = new TextDecoder();
|
|
371
408
|
let fullResponse = "";
|
|
409
|
+
let completed = false;
|
|
372
410
|
let buf = "";
|
|
373
411
|
let inputTokens = 0;
|
|
374
412
|
let outputTokens = 0;
|
|
@@ -390,6 +428,9 @@ export async function streamAnthropic(
|
|
|
390
428
|
if (!payload) continue;
|
|
391
429
|
try {
|
|
392
430
|
const obj = JSON.parse(payload);
|
|
431
|
+
if (options.requireCompletion && (obj.error || obj.type === "error"))
|
|
432
|
+
throw new Error("Anthropic stream returned an error");
|
|
433
|
+
if (obj.type === "message_stop") completed = true;
|
|
393
434
|
if (obj.type === "content_block_delta") {
|
|
394
435
|
const delta = obj.delta?.text;
|
|
395
436
|
if (delta) {
|
|
@@ -408,7 +449,11 @@ export async function streamAnthropic(
|
|
|
408
449
|
outputTokens = Number(obj.usage?.output_tokens) || outputTokens;
|
|
409
450
|
}
|
|
410
451
|
} catch (error) {
|
|
411
|
-
if (
|
|
452
|
+
if (
|
|
453
|
+
options.requireCompletion ||
|
|
454
|
+
error?.isOutputBackpressureFailure === true
|
|
455
|
+
)
|
|
456
|
+
throw error;
|
|
412
457
|
/* skip malformed */
|
|
413
458
|
}
|
|
414
459
|
}
|
|
@@ -435,6 +480,9 @@ export async function streamAnthropic(
|
|
|
435
480
|
});
|
|
436
481
|
}
|
|
437
482
|
|
|
483
|
+
options.signal?.throwIfAborted();
|
|
484
|
+
if (options.requireCompletion && !completed)
|
|
485
|
+
throw new Error("Model stream ended before its completion marker");
|
|
438
486
|
return fullResponse;
|
|
439
487
|
}
|
|
440
488
|
|
|
@@ -488,7 +536,15 @@ export async function* chatStream(messages, options) {
|
|
|
488
536
|
let providerCall;
|
|
489
537
|
if (provider === "ollama") {
|
|
490
538
|
providerCall = () =>
|
|
491
|
-
streamOllama(
|
|
539
|
+
streamOllama(
|
|
540
|
+
messages,
|
|
541
|
+
model,
|
|
542
|
+
baseUrl,
|
|
543
|
+
onToken,
|
|
544
|
+
onUsage,
|
|
545
|
+
options.onStall,
|
|
546
|
+
options,
|
|
547
|
+
);
|
|
492
548
|
} else if (provider === "anthropic") {
|
|
493
549
|
const providerDef = BUILT_IN_PROVIDERS.anthropic;
|
|
494
550
|
const url =
|
|
@@ -512,6 +568,7 @@ export async function* chatStream(messages, options) {
|
|
|
512
568
|
onToken,
|
|
513
569
|
onUsage,
|
|
514
570
|
options.onStall,
|
|
571
|
+
options,
|
|
515
572
|
);
|
|
516
573
|
} else {
|
|
517
574
|
const providerDef = BUILT_IN_PROVIDERS[provider];
|
|
@@ -536,6 +593,7 @@ export async function* chatStream(messages, options) {
|
|
|
536
593
|
onToken,
|
|
537
594
|
onUsage,
|
|
538
595
|
options.onStall,
|
|
596
|
+
options,
|
|
539
597
|
);
|
|
540
598
|
}
|
|
541
599
|
|
|
@@ -19,9 +19,97 @@
|
|
|
19
19
|
|
|
20
20
|
import { chatWithStreaming, chatStream } from "./chat-core.js";
|
|
21
21
|
import { firstBalancedJson } from "./json-schema-output.js";
|
|
22
|
+
import { prepareGovernedModelTurn } from "./evolution/governed-model-turn.js";
|
|
22
23
|
|
|
23
24
|
const DEFAULT_INTENT_TIMEOUT_MS = 15000;
|
|
24
25
|
|
|
26
|
+
async function waitForIntentOperation(operation, signal) {
|
|
27
|
+
if (signal.aborted) {
|
|
28
|
+
void Promise.resolve(operation).catch(() => {});
|
|
29
|
+
throw signal.reason;
|
|
30
|
+
}
|
|
31
|
+
let abort;
|
|
32
|
+
const cancelled = new Promise((_resolve, reject) => {
|
|
33
|
+
abort = () => reject(signal.reason);
|
|
34
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
return await Promise.race([operation, cancelled]);
|
|
38
|
+
} finally {
|
|
39
|
+
signal.removeEventListener("abort", abort);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function* intentModelStream(messages, options, factory, mode) {
|
|
44
|
+
if (factory === null) {
|
|
45
|
+
yield* chatStream(messages, options);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const controller = new AbortController();
|
|
49
|
+
const timeoutMs = resolveIntentTimeout(options);
|
|
50
|
+
const timer =
|
|
51
|
+
timeoutMs > 0
|
|
52
|
+
? setTimeout(
|
|
53
|
+
() =>
|
|
54
|
+
controller.abort(
|
|
55
|
+
new Error(`intent LLM call timed out after ${timeoutMs}ms`),
|
|
56
|
+
),
|
|
57
|
+
timeoutMs,
|
|
58
|
+
)
|
|
59
|
+
: null;
|
|
60
|
+
timer?.unref?.();
|
|
61
|
+
let completed = false;
|
|
62
|
+
try {
|
|
63
|
+
const turn = await waitForIntentOperation(
|
|
64
|
+
prepareGovernedModelTurn(factory, {
|
|
65
|
+
mode,
|
|
66
|
+
messages,
|
|
67
|
+
signal: controller.signal,
|
|
68
|
+
}),
|
|
69
|
+
controller.signal,
|
|
70
|
+
);
|
|
71
|
+
let content = "";
|
|
72
|
+
for await (const event of chatStream(turn.messages, {
|
|
73
|
+
...options,
|
|
74
|
+
signal: controller.signal,
|
|
75
|
+
requireCompletion: true,
|
|
76
|
+
})) {
|
|
77
|
+
controller.signal.throwIfAborted();
|
|
78
|
+
if (event.type === "response-token") {
|
|
79
|
+
content += event.token;
|
|
80
|
+
yield event;
|
|
81
|
+
} else if (event.type === "response-complete") {
|
|
82
|
+
content = event.content;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await waitForIntentOperation(turn.complete(content), controller.signal);
|
|
86
|
+
completed = true;
|
|
87
|
+
yield { type: "response-complete", content };
|
|
88
|
+
} finally {
|
|
89
|
+
clearTimeout(timer);
|
|
90
|
+
if (!completed) controller.abort(new Error("Intent stream cancelled"));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function intentModelText(messages, options, factory, mode) {
|
|
95
|
+
if (factory === null) {
|
|
96
|
+
return withIntentTimeout(
|
|
97
|
+
chatWithStreaming(messages, options),
|
|
98
|
+
resolveIntentTimeout(options),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
let content = "";
|
|
102
|
+
for await (const event of intentModelStream(
|
|
103
|
+
messages,
|
|
104
|
+
options,
|
|
105
|
+
factory,
|
|
106
|
+
mode,
|
|
107
|
+
)) {
|
|
108
|
+
if (event.type === "response-complete") content = event.content;
|
|
109
|
+
}
|
|
110
|
+
return content;
|
|
111
|
+
}
|
|
112
|
+
|
|
25
113
|
/**
|
|
26
114
|
* Resolve the per-call intent-classification budget. `llmOptions.intentTimeoutMs`
|
|
27
115
|
* overrides the default; an explicit 0 disables the cap; NaN/negative/absent →
|
|
@@ -40,8 +128,8 @@ function resolveIntentTimeout(llmOptions) {
|
|
|
40
128
|
* trips it, so without this the declared 15s intent budget was never enforced
|
|
41
129
|
* and classification could block for minutes. Racing the deadline makes it fail
|
|
42
130
|
* fast into the caller's graceful rule/verbatim fallback. `ms <= 0` disables.
|
|
43
|
-
*
|
|
44
|
-
* the timer is unref'd
|
|
131
|
+
* This helper is used only for the unconfigured legacy path; governed requests
|
|
132
|
+
* use the abortable intentModelStream deadline. The timer is unref'd.
|
|
45
133
|
*/
|
|
46
134
|
function withIntentTimeout(promise, ms) {
|
|
47
135
|
if (!(Number(ms) > 0)) return promise;
|
|
@@ -134,6 +222,7 @@ export async function understandIntent({
|
|
|
134
222
|
contextMode = "global",
|
|
135
223
|
history,
|
|
136
224
|
llmOptions,
|
|
225
|
+
evolutionCompositionFactory = null,
|
|
137
226
|
}) {
|
|
138
227
|
if (!userInput || !userInput.trim()) {
|
|
139
228
|
throw new Error("userInput required");
|
|
@@ -157,20 +246,19 @@ export async function understandIntent({
|
|
|
157
246
|
);
|
|
158
247
|
|
|
159
248
|
try {
|
|
160
|
-
const fullContent = await
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
resolveIntentTimeout(llmOptions),
|
|
249
|
+
const fullContent = await intentModelText(
|
|
250
|
+
[
|
|
251
|
+
{ role: "system", content: systemPrompt },
|
|
252
|
+
{ role: "user", content: userPrompt },
|
|
253
|
+
],
|
|
254
|
+
{
|
|
255
|
+
...llmOptions,
|
|
256
|
+
// Lower temperature → more deterministic JSON output.
|
|
257
|
+
temperature: 0.3,
|
|
258
|
+
maxTokens: 500,
|
|
259
|
+
},
|
|
260
|
+
evolutionCompositionFactory,
|
|
261
|
+
"intent-understand",
|
|
174
262
|
);
|
|
175
263
|
|
|
176
264
|
const jsonText = extractJson(fullContent);
|
|
@@ -218,6 +306,7 @@ export async function* understandIntentStream({
|
|
|
218
306
|
contextMode = "global",
|
|
219
307
|
history,
|
|
220
308
|
llmOptions,
|
|
309
|
+
evolutionCompositionFactory = null,
|
|
221
310
|
}) {
|
|
222
311
|
if (!userInput || !userInput.trim()) {
|
|
223
312
|
throw new Error("userInput required");
|
|
@@ -241,17 +330,16 @@ export async function* understandIntentStream({
|
|
|
241
330
|
);
|
|
242
331
|
let buffer = "";
|
|
243
332
|
try {
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
// understandIntent / classifyFollowupIntent paths enforce the tighter
|
|
248
|
-
// intent budget (resolveIntentTimeout) directly.
|
|
249
|
-
for await (const event of chatStream(
|
|
333
|
+
// Governed streams use an abortable per-call intent deadline. The legacy
|
|
334
|
+
// unconfigured stream retains chat-core's silence-based stall guard.
|
|
335
|
+
for await (const event of intentModelStream(
|
|
250
336
|
[
|
|
251
337
|
{ role: "system", content: systemPrompt },
|
|
252
338
|
{ role: "user", content: userPrompt },
|
|
253
339
|
],
|
|
254
340
|
{ ...llmOptions, temperature: 0.3, maxTokens: 500 },
|
|
341
|
+
evolutionCompositionFactory,
|
|
342
|
+
"intent-understand-stream",
|
|
255
343
|
)) {
|
|
256
344
|
if (event.type === "response-token") {
|
|
257
345
|
buffer += event.token;
|
|
@@ -461,10 +549,10 @@ function buildFollowupPrompts(userInput, context = {}) {
|
|
|
461
549
|
- 示例: "算了"、"不用了"、"停止"、"先不做了"
|
|
462
550
|
|
|
463
551
|
# 输出格式
|
|
464
|
-
严格返回 JSON
|
|
552
|
+
严格返回 JSON 格式,confidence 为 0 到 1 之间的数值:
|
|
465
553
|
{
|
|
466
554
|
"intent": "CONTINUE_EXECUTION | MODIFY_REQUIREMENT | CLARIFICATION | CANCEL_TASK",
|
|
467
|
-
"confidence": 0.
|
|
555
|
+
"confidence": 0.8,
|
|
468
556
|
"reason": "判断理由(1-2句话)",
|
|
469
557
|
"extractedInfo": "如果是 MODIFY_REQUIREMENT 或 CLARIFICATION,提取关键信息"
|
|
470
558
|
}`;
|
|
@@ -492,21 +580,25 @@ ${
|
|
|
492
580
|
return { systemPrompt, userPrompt };
|
|
493
581
|
}
|
|
494
582
|
|
|
495
|
-
async function llmBasedClassify(
|
|
583
|
+
async function llmBasedClassify(
|
|
584
|
+
userInput,
|
|
585
|
+
context,
|
|
586
|
+
llmOptions,
|
|
587
|
+
evolutionCompositionFactory,
|
|
588
|
+
) {
|
|
496
589
|
const { systemPrompt, userPrompt } = buildFollowupPrompts(userInput, context);
|
|
497
|
-
const fullContent = await
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
resolveIntentTimeout(llmOptions),
|
|
590
|
+
const fullContent = await intentModelText(
|
|
591
|
+
[
|
|
592
|
+
{ role: "system", content: systemPrompt },
|
|
593
|
+
{ role: "user", content: userPrompt },
|
|
594
|
+
],
|
|
595
|
+
{
|
|
596
|
+
...llmOptions,
|
|
597
|
+
temperature: 0.1,
|
|
598
|
+
maxTokens: 300,
|
|
599
|
+
},
|
|
600
|
+
evolutionCompositionFactory,
|
|
601
|
+
"intent-classify",
|
|
510
602
|
);
|
|
511
603
|
const jsonText = extractJson(fullContent);
|
|
512
604
|
if (!jsonText) throw new Error("LLM response missing JSON");
|
|
@@ -535,6 +627,7 @@ export async function classifyFollowupIntent({
|
|
|
535
627
|
input,
|
|
536
628
|
context = {},
|
|
537
629
|
llmOptions,
|
|
630
|
+
evolutionCompositionFactory = null,
|
|
538
631
|
}) {
|
|
539
632
|
const startTime = Date.now();
|
|
540
633
|
const ruleResult = ruleBasedClassify(input);
|
|
@@ -556,13 +649,19 @@ export async function classifyFollowupIntent({
|
|
|
556
649
|
}
|
|
557
650
|
|
|
558
651
|
try {
|
|
559
|
-
const llmResult = await llmBasedClassify(
|
|
652
|
+
const llmResult = await llmBasedClassify(
|
|
653
|
+
input,
|
|
654
|
+
context,
|
|
655
|
+
llmOptions,
|
|
656
|
+
evolutionCompositionFactory,
|
|
657
|
+
);
|
|
560
658
|
return {
|
|
561
659
|
...llmResult,
|
|
562
660
|
method: "llm",
|
|
563
661
|
latency: Date.now() - startTime,
|
|
564
662
|
};
|
|
565
663
|
} catch (_err) {
|
|
664
|
+
if (evolutionCompositionFactory !== null) throw _err;
|
|
566
665
|
return ruleResult.confidence > 0
|
|
567
666
|
? {
|
|
568
667
|
...ruleResult,
|
|
@@ -13,6 +13,7 @@ import fs from "node:fs";
|
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
import { types as utilTypes } from "node:util";
|
|
15
15
|
import { ArtifactStore } from "../artifact-store.js";
|
|
16
|
+
import { withEvolutionFileIdentity } from "./evolution-file-identity.js";
|
|
16
17
|
import {
|
|
17
18
|
EVOLUTION_ARTIFACT_REF_SCHEMA,
|
|
18
19
|
EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
|
|
@@ -1106,6 +1107,16 @@ function inspectPhysicalDirectory(directory, label) {
|
|
|
1106
1107
|
}
|
|
1107
1108
|
|
|
1108
1109
|
function inspectPhysicalIndex(indexPath, rootRealPath) {
|
|
1110
|
+
return withEvolutionFileIdentity(fs, indexPath, (samePathHandle) =>
|
|
1111
|
+
inspectPhysicalIndexWithIdentity(indexPath, rootRealPath, samePathHandle),
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
function inspectPhysicalIndexWithIdentity(
|
|
1116
|
+
indexPath,
|
|
1117
|
+
rootRealPath,
|
|
1118
|
+
samePathHandle,
|
|
1119
|
+
) {
|
|
1109
1120
|
let pathStat;
|
|
1110
1121
|
let realPath;
|
|
1111
1122
|
let descriptor = null;
|
|
@@ -1128,7 +1139,7 @@ function inspectPhysicalIndex(indexPath, rootRealPath) {
|
|
|
1128
1139
|
);
|
|
1129
1140
|
const descriptorStat = fs.fstatSync(descriptor);
|
|
1130
1141
|
assertRegularSingleLink(descriptorStat, "ArtifactStore index descriptor");
|
|
1131
|
-
if (!
|
|
1142
|
+
if (!samePathHandle(pathStat, descriptorStat)) {
|
|
1132
1143
|
throw artifactError(
|
|
1133
1144
|
EVOLUTION_ARTIFACT_INTEGRITY_FAILED_CODE,
|
|
1134
1145
|
"ArtifactStore index pathname and descriptor identities differ",
|
|
@@ -1375,6 +1386,12 @@ function parseTrustedIndexBytes(bytes) {
|
|
|
1375
1386
|
}
|
|
1376
1387
|
|
|
1377
1388
|
function readTrustedIndexSnapshot(layout) {
|
|
1389
|
+
return withEvolutionFileIdentity(fs, layout.indexPath, (samePathHandle) =>
|
|
1390
|
+
readTrustedIndexSnapshotWithIdentity(layout, samePathHandle),
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
function readTrustedIndexSnapshotWithIdentity(layout, samePathHandle) {
|
|
1378
1395
|
attestStoreDirectories(layout);
|
|
1379
1396
|
let beforePathStat;
|
|
1380
1397
|
let beforeDescriptorStat;
|
|
@@ -1412,7 +1429,7 @@ function readTrustedIndexSnapshot(layout) {
|
|
|
1412
1429
|
"ArtifactStore index descriptor",
|
|
1413
1430
|
);
|
|
1414
1431
|
if (
|
|
1415
|
-
!
|
|
1432
|
+
!samePathHandle(beforePathStat, beforeDescriptorStat) ||
|
|
1416
1433
|
beforeDescriptorStat.size > EVOLUTION_ARTIFACT_MAX_INDEX_BYTES
|
|
1417
1434
|
) {
|
|
1418
1435
|
throw artifactError(
|
|
@@ -2311,6 +2328,26 @@ export class EvolutionArtifactPorts {
|
|
|
2311
2328
|
}
|
|
2312
2329
|
|
|
2313
2330
|
#readStoredBytes(entry, normalizedEntry, expectedDigest) {
|
|
2331
|
+
const expectedPath = path.resolve(
|
|
2332
|
+
this.#store.layout.filesDir,
|
|
2333
|
+
normalizedEntry.file,
|
|
2334
|
+
);
|
|
2335
|
+
return withEvolutionFileIdentity(fs, expectedPath, (samePathHandle) =>
|
|
2336
|
+
this.#readStoredBytesWithIdentity(
|
|
2337
|
+
entry,
|
|
2338
|
+
normalizedEntry,
|
|
2339
|
+
expectedDigest,
|
|
2340
|
+
samePathHandle,
|
|
2341
|
+
),
|
|
2342
|
+
);
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
#readStoredBytesWithIdentity(
|
|
2346
|
+
entry,
|
|
2347
|
+
normalizedEntry,
|
|
2348
|
+
expectedDigest,
|
|
2349
|
+
samePathHandle,
|
|
2350
|
+
) {
|
|
2314
2351
|
attestStoreDirectories(this.#store.layout);
|
|
2315
2352
|
const expectedHex = expectedDigest.slice("sha256:".length);
|
|
2316
2353
|
let storedPath;
|
|
@@ -2387,7 +2424,7 @@ export class EvolutionArtifactPorts {
|
|
|
2387
2424
|
beforeDescriptorStat,
|
|
2388
2425
|
"stored artifact descriptor",
|
|
2389
2426
|
);
|
|
2390
|
-
if (!
|
|
2427
|
+
if (!samePathHandle(beforePathStat, beforeDescriptorStat)) {
|
|
2391
2428
|
throw artifactError(
|
|
2392
2429
|
EVOLUTION_ARTIFACT_INTEGRITY_FAILED_CODE,
|
|
2393
2430
|
"stored artifact pathname and descriptor identities differ",
|
|
@@ -16,9 +16,12 @@ const SUPPORTED_COMMANDS = new Set([
|
|
|
16
16
|
"cowork",
|
|
17
17
|
"desktop",
|
|
18
18
|
"evolution",
|
|
19
|
+
"hub",
|
|
19
20
|
"marketplace",
|
|
20
21
|
"orchestrate",
|
|
21
22
|
"serve",
|
|
23
|
+
"stream",
|
|
24
|
+
"ui",
|
|
22
25
|
]);
|
|
23
26
|
|
|
24
27
|
function canonical(value) {
|
|
@@ -285,10 +288,13 @@ async function loadBuiltInFactories(commandName) {
|
|
|
285
288
|
commandName === "chat" ||
|
|
286
289
|
commandName === "compact" ||
|
|
287
290
|
commandName === "complete" ||
|
|
291
|
+
commandName === "hub" ||
|
|
288
292
|
commandName === "desktop" ||
|
|
289
293
|
commandName === "cowork" ||
|
|
290
294
|
commandName === "orchestrate" ||
|
|
291
|
-
commandName === "serve"
|
|
295
|
+
commandName === "serve" ||
|
|
296
|
+
commandName === "stream" ||
|
|
297
|
+
commandName === "ui"
|
|
292
298
|
) {
|
|
293
299
|
const { createAgentEvolutionRuntimeComposition } =
|
|
294
300
|
await import("./agent-evolution-runtime-composition.js");
|