chainlesschain 0.166.103 → 0.166.104
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 +1 -1
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-BLrXpdnP.js → AIOps-Bah3HREy.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C0xy9uFy.js → ActionButton-DY2aeZMc.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-C6EephQP.js → Analytics-BFly8Xaa.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-ZCXdOD9y.js → AppLayout-dp0Zz-JM.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-D4MfZ-pl.js → Artifacts-DcIg09ai.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BQ8c3bBu.js → Audit-DkN-lsjZ.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BOA7_ljM.js → BackgroundAgents-BjzgusLx.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-60uiQjGT.js → Backup-CU8S6qu9.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BDvEbGs_.js → BaseInput-B1pC2gjL.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-B3IkAuFQ.js → Chat-B6xFp6gD.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DxNCLZ_X.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-njGbfJWq.js → Checkbox-QHw7Vc4U.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CF7DtdxC.js → Codegen-gdecsfjg.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C_3Zix40.js → Col-B0_JmAmc.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CzU-ZC2d.js → Community-DRCcP5xR.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BgeqsPRh.js → Compact-DZtoGzhX.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-6l7cwiqp.js → Compliance-BfNTvEnT.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-D4s905fI.js → Cowork-CDXTLm84.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CGTYSxRS.js → Cron-Big35CbN.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BnSo-Yt3.js → Crosschain-C8ArrAVr.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Dm4vk2X1.js → DID-D_77BI2O.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-D7H-PZ_N.js → Dashboard-D2SxTzEp.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-COslkgxn.js → Dropdown-mR1-b9ud.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CJWEetmk.js → EmailListRenderer-DPl7TE1c.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-BbzebAWe.js → EvolutionSettings-BxRYLRSH.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BsoTOXwk.js → FamilyGuardDashboard-rnGtXJ5Z.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Ck5kM_5H.js → Federation-BpxenYK8.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-gShxCqtF.js → FormItemContext-Cz1kDf6l.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DarN1G-z.js → GenericCardRenderer-CGV3KN6U.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CJfpLyP5.js → Git-CIRP4UTx.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CVcJmpQz.js → Governance-DX4r8Vmt.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-ComU_ig8.js → Inference-DQKk02Hl.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-35hprFJy.js → KnowledgeGraph-DdD6J-By.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BQDqBTz0.js → Logs-DA2w-1_m.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BpdGAVCC.js → MarkdownRenderer-C9aSGETh.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-B9O9OKnn.js → Marketplace-BsJ6_6KW.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-VMKxA4Wc.js → McpTools-_6k30z6u.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CcBbf3Bc.js → Memory-C0_dYY0A.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-D7myz46N.js → MobileBridge-CCTnVqiC.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-Da5KBXyx.js → MobileProjects-RZdxDSwC.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-x3NPZfuL.js → Mtc-D4Ys8lvX.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-CwnzptEC.js → MtcAudit-BKTC--a2.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-CCAxf4Ye.js → Multisig-CGR1qOe1.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CptHKz-Q.js → NLProgramming-hKKD4qWb.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-0uEp4DCJ.js → Notes-pCn7Ec40.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DthvrOLd.js → NotificationSettings-B9eEJXEs.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CmJuhaT2.js +1 -0
- package/src/assets/web-panel/assets/{Organization-BWf2tmQQ.js → Organization-CcQbrnwW.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BbvAtEth.js → Overflow-HmD4Mn72.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-zBo6enit.js → P2P-B7LIgx5H.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-D_LMQ4A4.js → PdhVaultBrowser-CXiHnBfX.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-C1ucb2ck.js → Permissions-CQRI3y_l.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Bz64RddJ.js → PersonalDataHub-1EeHmsy5.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-DXJt3y3_.js → Pipeline-BFyoIdn8.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DiZ8b_ut.js → Privacy-BxWthXMF.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DfLKKrJ4.js → ProjectInit-DfigBilu.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Ct6kJuIY.js → ProjectSettings-CFmIcVc-.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BBUMlZ3m.js → Projects-CR7H59v3.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DYVQPHvc.js → Providers-2ulom-76.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-23Il7iPp.js → QrScannerModal-BwhO07b_.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-WgOZKrv1.js → QuickAsk-_Wg34OwF.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CRIka6xT.js → Recommend-D_jq6Svg.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DOy3GjVZ.js → RemoteSession-BlzvEfsa.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BXyi6xeR.js → Reputation-9CTXHfL4.js} +1 -1
- package/src/assets/web-panel/assets/{Row-CoMxuIcR.js → Row-DlCYCN-t.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-87hPkoM6.js → RssFeed-BvlInFCH.js} +3 -3
- package/src/assets/web-panel/assets/{Search-B1EqFCO4.js → Search-CfaUzKuL.js} +1 -1
- package/src/assets/web-panel/assets/{Security-HcC41eGs.js → Security-bAWgLyve.js} +3 -3
- package/src/assets/web-panel/assets/{Services-BqLwmvCM.js → Services-C4LOGACW.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CIMmjW4r.js → Skeleton-Dd0Uwh3_.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CgurezJU.js → Skills-ZYF1kYCU.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CJuRuqPE.js → Sla-DpsmIaEo.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BUwsbd1o.js → SpeechSettings-BBXoJ4yc.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-qo04TOX-.js → SyncSettings-SOnROi2Y.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-HFA_ZlDk.js +1 -0
- package/src/assets/web-panel/assets/{Templates-D1PTczPW.js → Templates-fsK-RCEc.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-Bi0FkEPR.js → Tenant-CuqYxamb.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DfSt3bIF.js → Terminal-GKlI2R5F.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-B7bIVs4R.js → TimelineRenderer-DMDMHLeY.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B6w5XrMb.js → Tokens-BoV60rh3.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-XXVSDWiF.js → Trigger-CE344-Ws.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DYvlgcK-.js → Trust-DENwgkVc.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-XyYwJMBM.js → UkeySign-FrcM7yfm.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C47WbtHH.js → VideoEditing-DAY9WaC2.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CYfqTj_C.js → Wallet-BuUR5i82.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-3AduFn1l.js → WebAuthn-nfSQuq85.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-DHYEHjMJ.js → WorkflowEditor-DHhPOp9l.js} +1 -1
- package/src/assets/web-panel/assets/{chat-AeehErSw.js → chat-C4nsLzYy.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DKXJ8paX.js → colors-BwXH0Wjn.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BOlCiomD.js → compact-item-uApFG30S.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BAP6U85b.js → createContext-BpyYs4fe.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Bk6HGn3N.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BLmeL1Xe.js → hasIn-MXCLi00p.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdNSmvog.js → index-1LxX2IwJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dv8-g1pY.js → index-61CBBrHE.js} +1 -1
- package/src/assets/web-panel/assets/{index-ClpwxOXo.js → index-B0P1Z_oa.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgtaOzMo.js → index-B7jojVc7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRcJlKSa.js → index-BEGMfaOo.js} +1 -1
- package/src/assets/web-panel/assets/{index-wyKpTsGM.js → index-BOhjapd5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuUwKmEI.js → index-BaBwXpAp.js} +1 -1
- package/src/assets/web-panel/assets/index-Bb1LPYdi.js +1 -0
- package/src/assets/web-panel/assets/{index-Co7pjF53.js → index-Btv--Nnt.js} +1 -1
- package/src/assets/web-panel/assets/index-C-FsTuFG.js +1 -0
- package/src/assets/web-panel/assets/{index-CFKzWIo8.js → index-CF0bUOP4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaHhfpBi.js → index-CNjUPfJP.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZMbXl5lo.js → index-CRmNdEk_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTnp4Nt3.js → index-C_oOpXhP.js} +1 -1
- package/src/assets/web-panel/assets/{index-OLKhib9T.js → index-ChUTKrOq.js} +1 -1
- package/src/assets/web-panel/assets/{index-T28naovw.js → index-CiIpIYhs.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bpx54vfs.js → index-CwVvk2i7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BAS2QqLn.js → index-D3_tj06B.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRa4pAaM.js → index-DE4W4vLO.js} +3 -3
- package/src/assets/web-panel/assets/{index-BSOenF5s.js → index-DLxKx5_J.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE7cbDDe.js → index-DTXi_gQh.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWYqOI1A.js → index-Daco83me.js} +1 -1
- package/src/assets/web-panel/assets/{index-DQLQuwpA.js → index-DffWVpZv.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiqeF0Pf.js → index-Dkncxel3.js} +1 -1
- package/src/assets/web-panel/assets/{index-IlzfIRNh.js → index-Dn12gJJU.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bn54FU3i.js → index-Dt-nq2eF.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bt-FCVzh.js → index-Du01X9N9.js} +1 -1
- package/src/assets/web-panel/assets/{index-EKNODw4P.js → index-DucLR6YX.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5AKY6bJ.js → index-Gz2rGWef.js} +1 -1
- package/src/assets/web-panel/assets/{index-C8qi53Ki.js → index-IvgszJ3C.js} +1 -1
- package/src/assets/web-panel/assets/{index-urPvyUVk.js → index-S80LLjdx.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bs2O3f81.js → index-WKbnwbKa.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpZqbc4w.js → index-XHBXtvqp.js} +1 -1
- package/src/assets/web-panel/assets/{index-De2fPxdb.js → index-nn22NSDK.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0IjlB9m.js → index-pCIAE2yS.js} +1 -1
- package/src/assets/web-panel/assets/{index-PEe9OWEQ.js → index-pRpMLhMt.js} +1 -1
- package/src/assets/web-panel/assets/{index-FPXLIXoy.js → index-pgHGBAoF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhcpWl5z.js → index-ugIUt5TL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsQ38fVY.js → index-xLGf7f9K.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CDWa1rnn.js → initDefaultProps-C58CkKEo.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CX2Cnsd5.js → motion-BLWPO2NV.js} +1 -1
- package/src/assets/web-panel/assets/{move-Bfe1NcEF.js → move-BgrFMwYp.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DbdqleHE.js → mtc-parser-Cq2AuGzl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CE2K7NVv.js → omit-Bb-9L7if.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-y_bZgxWG.js → pickAttrs-vLmOxYr1.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BOHR4zwr.js → placementArrow-BNySU_dJ.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-B8Jwq05-.js → responsiveObserve-xnbwagnm.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BD7RJ3Kn.js → slide-BccbY5Cn.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BuxDJeDx.js → statusUtils-DOp9d2-w.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DgYQ2Q0o.js → styleChecker-Bu1w6ho9.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DAHF0Fwi.js → useFlexGapSupport-ZsUOrVdL.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-D4kDyLFp.js → useFs-C0zpzKtO.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BHtSxW4A.js → usePersonalDataHub-DO1OdgXK.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CHKtdqW0.js → vnode-jTIRyhR5.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CIZAMma9.js → zoom-DKvS7-Qs.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +56 -20
- package/src/commands/batch.js +17 -12
- package/src/commands/eval.js +24 -8
- package/src/data/changelog.json +13 -0
- package/src/harness/mcp-client.js +187 -26
- package/src/lib/background-session-transport.js +21 -5
- package/src/lib/decision-layer/runtime.js +180 -10
- package/src/lib/direct-model-usage.js +34 -0
- package/src/lib/evolution/agent-evolution-ingress.js +63 -7
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +10 -0
- package/src/lib/evolution/evolution-evidence-projector.js +46 -7
- package/src/lib/evolution/skill-decision-projection.js +211 -0
- package/src/lib/evolution/skill-retrieval-revocation-authority.js +17 -2
- package/src/lib/skill-loader.js +16 -0
- package/src/repl/agent-repl.js +86 -7
- package/src/runtime/agent-core.js +111 -13
- package/src/runtime/headless-runner.js +212 -22
- package/src/runtime/headless-stream.js +189 -25
- package/src/runtime/mcp-config.js +26 -17
- package/src/runtime/mcp-tool-search.js +44 -14
- package/src/assets/web-panel/assets/ChatBubbleRenderer-n6BVStHf.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CxXuPzZg.js +0 -1
- package/src/assets/web-panel/assets/Tasks-QEFENVsp.js +0 -1
- package/src/assets/web-panel/assets/devWarning-rGldFhxo.js +0 -1
- package/src/assets/web-panel/assets/index-Cw-lfvvV.js +0 -1
- package/src/assets/web-panel/assets/index-QBXRSyoZ.js +0 -1
|
@@ -12,12 +12,17 @@ import {
|
|
|
12
12
|
SKILL_DECISION_OBSERVATION_SCHEMA,
|
|
13
13
|
} from "./contracts.js";
|
|
14
14
|
import { captureDecisionProviderAuthority } from "./provider-authority.js";
|
|
15
|
+
import {
|
|
16
|
+
AGENT_EVOLUTION_INGRESS_FAILED_CODE,
|
|
17
|
+
captureAgentEvolutionIngress,
|
|
18
|
+
} from "../evolution/agent-evolution-ingress.js";
|
|
15
19
|
|
|
16
20
|
export const SKILL_DECISION_RUNTIME_SCHEMA =
|
|
17
21
|
"chainlesschain.skill-decision-runtime/v1";
|
|
18
22
|
|
|
19
23
|
const RUNTIMES = new WeakSet();
|
|
20
24
|
const DEFAULT_TIMEOUT_MS = 800;
|
|
25
|
+
const DEFAULT_BOUNDARY_TIMEOUT_MS = 30_000;
|
|
21
26
|
|
|
22
27
|
function requiredText(value, label, maximum = 256) {
|
|
23
28
|
if (
|
|
@@ -36,6 +41,53 @@ function timeoutSignal(signal, timeoutMs) {
|
|
|
36
41
|
return signal ? AbortSignal.any([signal, deadline]) : deadline;
|
|
37
42
|
}
|
|
38
43
|
|
|
44
|
+
function settleBeforeAbort(value, signal) {
|
|
45
|
+
const pending = Promise.resolve(value);
|
|
46
|
+
if (!signal) return pending;
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
let settled = false;
|
|
49
|
+
const finish = (settle, result) => {
|
|
50
|
+
if (settled) return;
|
|
51
|
+
settled = true;
|
|
52
|
+
signal.removeEventListener("abort", onAbort);
|
|
53
|
+
settle(result);
|
|
54
|
+
};
|
|
55
|
+
const onAbort = () => finish(reject, signal.reason);
|
|
56
|
+
pending.then(
|
|
57
|
+
(result) => finish(resolve, result),
|
|
58
|
+
(error) => finish(reject, error),
|
|
59
|
+
);
|
|
60
|
+
if (signal.aborted) {
|
|
61
|
+
onAbort();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function waitForGovernedPhase(value, signal, timeoutMs, onTimeout) {
|
|
69
|
+
const phaseSignal = timeoutSignal(signal, timeoutMs);
|
|
70
|
+
try {
|
|
71
|
+
return await settleBeforeAbort(value, phaseSignal);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (signal?.aborted) throw signal.reason;
|
|
74
|
+
if (
|
|
75
|
+
phaseSignal.aborted &&
|
|
76
|
+
phaseSignal.reason === error &&
|
|
77
|
+
error?.name === "TimeoutError"
|
|
78
|
+
) {
|
|
79
|
+
throw onTimeout(error);
|
|
80
|
+
}
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function admissionTimeoutError(cause) {
|
|
86
|
+
const error = new Error("Skill decision admission timed out", { cause });
|
|
87
|
+
error.code = AGENT_EVOLUTION_INGRESS_FAILED_CODE;
|
|
88
|
+
return error;
|
|
89
|
+
}
|
|
90
|
+
|
|
39
91
|
function projectUnavailable(error) {
|
|
40
92
|
if (error?.name === "TimeoutError") return "provider-timeout";
|
|
41
93
|
if (error?.code === "CC_DECISION_USAGE_UNKNOWN_BLOCKED") {
|
|
@@ -66,7 +118,7 @@ function asPersistenceError(error) {
|
|
|
66
118
|
return markRuntimeLedgerPersistenceError(error);
|
|
67
119
|
} catch {
|
|
68
120
|
return markRuntimeLedgerPersistenceError(
|
|
69
|
-
new Error("decision
|
|
121
|
+
new Error("decision persistence failed", { cause: error }),
|
|
70
122
|
);
|
|
71
123
|
}
|
|
72
124
|
}
|
|
@@ -76,12 +128,14 @@ export function createSkillDecisionRuntime({
|
|
|
76
128
|
tenantId = null,
|
|
77
129
|
sessionId = null,
|
|
78
130
|
provider = null,
|
|
131
|
+
evolutionIngress = null,
|
|
79
132
|
persist = null,
|
|
80
133
|
observe = null,
|
|
81
134
|
sessionBudget = null,
|
|
82
135
|
initialUsageUnknown = false,
|
|
83
136
|
thresholds = {},
|
|
84
137
|
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
138
|
+
boundaryTimeoutMs = DEFAULT_BOUNDARY_TIMEOUT_MS,
|
|
85
139
|
idGenerator = () => randomUUID(),
|
|
86
140
|
now = () => new Date(),
|
|
87
141
|
} = {}) {
|
|
@@ -95,17 +149,36 @@ export function createSkillDecisionRuntime({
|
|
|
95
149
|
"decision timeout must be an integer from 50 to 30000 ms",
|
|
96
150
|
);
|
|
97
151
|
}
|
|
152
|
+
if (
|
|
153
|
+
!Number.isSafeInteger(boundaryTimeoutMs) ||
|
|
154
|
+
boundaryTimeoutMs < 50 ||
|
|
155
|
+
boundaryTimeoutMs > 30_000
|
|
156
|
+
) {
|
|
157
|
+
throw new TypeError(
|
|
158
|
+
"decision boundary timeout must be an integer from 50 to 30000 ms",
|
|
159
|
+
);
|
|
160
|
+
}
|
|
98
161
|
if (typeof idGenerator !== "function" || typeof now !== "function") {
|
|
99
162
|
throw new TypeError("decision runtime generators must be functions");
|
|
100
163
|
}
|
|
101
164
|
let providerAuthority = null;
|
|
102
165
|
let boundTenantId = null;
|
|
103
166
|
let boundSessionId = null;
|
|
167
|
+
let ingress = null;
|
|
104
168
|
let unknownUsageSeen = initialUsageUnknown === true;
|
|
169
|
+
const unsettledUsageCalls = new Set();
|
|
170
|
+
let usageCallInFlight = false;
|
|
171
|
+
let usagePersistenceFailure = null;
|
|
172
|
+
let observationPersistenceFailure = null;
|
|
105
173
|
if (normalizedMode !== "off") {
|
|
106
174
|
providerAuthority = captureDecisionProviderAuthority(provider);
|
|
107
175
|
boundTenantId = requiredText(tenantId, "tenantId");
|
|
108
176
|
boundSessionId = requiredText(sessionId, "sessionId");
|
|
177
|
+
if (evolutionIngress !== null) {
|
|
178
|
+
ingress = captureAgentEvolutionIngress(evolutionIngress, {
|
|
179
|
+
tenantId: boundTenantId,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
109
182
|
if (typeof persist !== "function" || typeof observe !== "function") {
|
|
110
183
|
throw new TypeError(
|
|
111
184
|
"enabled decision runtime requires usage and observation persistence",
|
|
@@ -118,13 +191,33 @@ export function createSkillDecisionRuntime({
|
|
|
118
191
|
try {
|
|
119
192
|
await observe(observation);
|
|
120
193
|
} catch (error) {
|
|
121
|
-
|
|
194
|
+
observationPersistenceFailure ??= asPersistenceError(error);
|
|
195
|
+
throw observationPersistenceFailure;
|
|
122
196
|
}
|
|
123
197
|
};
|
|
124
198
|
|
|
125
199
|
const persistDecisionUsage = async (type, event) => {
|
|
126
|
-
|
|
127
|
-
|
|
200
|
+
if (usagePersistenceFailure !== null) throw usagePersistenceFailure;
|
|
201
|
+
try {
|
|
202
|
+
await waitForGovernedPhase(
|
|
203
|
+
persist(type, event),
|
|
204
|
+
null,
|
|
205
|
+
boundaryTimeoutMs,
|
|
206
|
+
(cause) =>
|
|
207
|
+
new Error("Skill decision usage persistence timed out", { cause }),
|
|
208
|
+
);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
usagePersistenceFailure ??= asPersistenceError(error);
|
|
211
|
+
throw usagePersistenceFailure;
|
|
212
|
+
}
|
|
213
|
+
if (type === "model_usage_started") {
|
|
214
|
+
unsettledUsageCalls.add(event.callId);
|
|
215
|
+
} else if (type === "model_usage_unknown") {
|
|
216
|
+
unknownUsageSeen = true;
|
|
217
|
+
unsettledUsageCalls.delete(event.callId);
|
|
218
|
+
} else if (type === "token_usage") {
|
|
219
|
+
unsettledUsageCalls.delete(event.callId);
|
|
220
|
+
}
|
|
128
221
|
};
|
|
129
222
|
|
|
130
223
|
const runtime = Object.freeze({
|
|
@@ -148,6 +241,10 @@ export function createSkillDecisionRuntime({
|
|
|
148
241
|
});
|
|
149
242
|
}
|
|
150
243
|
if (signal?.aborted) throw signal.reason;
|
|
244
|
+
if (usagePersistenceFailure !== null) throw usagePersistenceFailure;
|
|
245
|
+
if (observationPersistenceFailure !== null) {
|
|
246
|
+
throw observationPersistenceFailure;
|
|
247
|
+
}
|
|
151
248
|
const decisionId = `skill-${requiredText(idGenerator(), "decisionId")}`;
|
|
152
249
|
const request = createSkillDecisionRequest({
|
|
153
250
|
decisionId,
|
|
@@ -167,11 +264,41 @@ export function createSkillDecisionRuntime({
|
|
|
167
264
|
}
|
|
168
265
|
let outcome;
|
|
169
266
|
let requestSignal = null;
|
|
170
|
-
|
|
267
|
+
let admissionReceipt = null;
|
|
268
|
+
if (unknownUsageSeen || unsettledUsageCalls.size > 0) {
|
|
171
269
|
outcome = unavailableOutcome("provider-usage-unknown-blocked");
|
|
172
270
|
} else {
|
|
173
271
|
try {
|
|
174
|
-
|
|
272
|
+
// Admission is not provider work: a refusal must not create an
|
|
273
|
+
// unknown-charge ledger row or consume the provider's budget turn.
|
|
274
|
+
const admission =
|
|
275
|
+
ingress === null
|
|
276
|
+
? null
|
|
277
|
+
: await waitForGovernedPhase(
|
|
278
|
+
ingress.prepareSkillDecisionRequest(request),
|
|
279
|
+
signal,
|
|
280
|
+
boundaryTimeoutMs,
|
|
281
|
+
admissionTimeoutError,
|
|
282
|
+
);
|
|
283
|
+
signal?.throwIfAborted();
|
|
284
|
+
admissionReceipt = admission?.receipt ?? null;
|
|
285
|
+
// Keep local content identities out of the provider capability. Only
|
|
286
|
+
// the authenticated projection is available for governed dispatch.
|
|
287
|
+
const providerRequest =
|
|
288
|
+
admission === null
|
|
289
|
+
? request
|
|
290
|
+
: Object.freeze({ payload: admission.payload });
|
|
291
|
+
if (
|
|
292
|
+
unknownUsageSeen ||
|
|
293
|
+
unsettledUsageCalls.size > 0 ||
|
|
294
|
+
usageCallInFlight
|
|
295
|
+
) {
|
|
296
|
+
const error = new Error("decision usage recovery is required");
|
|
297
|
+
error.code = "CC_DECISION_USAGE_UNKNOWN_BLOCKED";
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
usageCallInFlight = true;
|
|
301
|
+
const meteredCall = runMeteredDirectModelCall({
|
|
175
302
|
sessionId: boundSessionId,
|
|
176
303
|
persist: persistDecisionUsage,
|
|
177
304
|
provider: providerAuthority.provider,
|
|
@@ -180,18 +307,36 @@ export function createSkillDecisionRuntime({
|
|
|
180
307
|
operationId: `decision:${decisionId}`,
|
|
181
308
|
sessionBudget,
|
|
182
309
|
includeSettlement: true,
|
|
310
|
+
dispatchSignal: signal ?? null,
|
|
183
311
|
call: () => {
|
|
184
312
|
if (unknownUsageSeen) {
|
|
185
313
|
const error = new Error("decision usage recovery is required");
|
|
186
314
|
error.code = "CC_DECISION_USAGE_UNKNOWN_BLOCKED";
|
|
187
315
|
throw error;
|
|
188
316
|
}
|
|
317
|
+
// timeoutMs remains the provider-call deadline. Admission uses
|
|
318
|
+
// its own authority lifecycle and checks caller cancellation.
|
|
189
319
|
requestSignal = timeoutSignal(signal, timeoutMs);
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
320
|
+
requestSignal.throwIfAborted();
|
|
321
|
+
return settleBeforeAbort(
|
|
322
|
+
providerAuthority.decide(providerRequest, {
|
|
323
|
+
signal: requestSignal,
|
|
324
|
+
}),
|
|
325
|
+
requestSignal,
|
|
326
|
+
);
|
|
193
327
|
},
|
|
194
328
|
});
|
|
329
|
+
let meteredResult;
|
|
330
|
+
try {
|
|
331
|
+
meteredResult = await meteredCall;
|
|
332
|
+
} finally {
|
|
333
|
+
usageCallInFlight = false;
|
|
334
|
+
}
|
|
335
|
+
const { result: raw, settlement } = meteredResult;
|
|
336
|
+
// A provider may resolve successfully after ignoring cancellation or
|
|
337
|
+
// its deadline. Usage is settled above; the late answer is unusable.
|
|
338
|
+
signal?.throwIfAborted();
|
|
339
|
+
requestSignal?.throwIfAborted();
|
|
195
340
|
if (settlement !== "known") {
|
|
196
341
|
// The metered call already persisted model_usage_unknown. Without a
|
|
197
342
|
// budget root it may return the answer; never expose that answer.
|
|
@@ -254,6 +399,7 @@ export function createSkillDecisionRuntime({
|
|
|
254
399
|
reasonCode: outcome.reasonCode,
|
|
255
400
|
selectedDigest: outcome.selectedDigest,
|
|
256
401
|
resultDigest: outcome.resultDigest,
|
|
402
|
+
...(admissionReceipt === null ? {} : { admissionReceipt }),
|
|
257
403
|
startedAt: startedAt.toISOString(),
|
|
258
404
|
finishedAt: finishedAt.toISOString(),
|
|
259
405
|
latencyMs: Math.max(0, finishedAt.getTime() - startedAt.getTime()),
|
|
@@ -265,7 +411,31 @@ export function createSkillDecisionRuntime({
|
|
|
265
411
|
observationCore,
|
|
266
412
|
),
|
|
267
413
|
});
|
|
268
|
-
|
|
414
|
+
try {
|
|
415
|
+
await waitForGovernedPhase(
|
|
416
|
+
writeObservation(observation),
|
|
417
|
+
signal,
|
|
418
|
+
boundaryTimeoutMs,
|
|
419
|
+
(cause) =>
|
|
420
|
+
asPersistenceError(
|
|
421
|
+
new Error("Skill decision observation timed out", { cause }),
|
|
422
|
+
),
|
|
423
|
+
);
|
|
424
|
+
} catch (error) {
|
|
425
|
+
if (error?.runtimeLedgerPersistence === true) {
|
|
426
|
+
observationPersistenceFailure ??= error;
|
|
427
|
+
} else if (signal?.aborted) {
|
|
428
|
+
// The caller stops waiting before the durable observer acknowledges
|
|
429
|
+
// the write. Its eventual outcome is unknown to this runtime.
|
|
430
|
+
observationPersistenceFailure ??= asPersistenceError(
|
|
431
|
+
new Error("Skill decision observation completion is unknown", {
|
|
432
|
+
cause: error,
|
|
433
|
+
}),
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
signal?.throwIfAborted();
|
|
269
439
|
return Object.freeze({
|
|
270
440
|
schema: SKILL_DECISION_OBSERVATION_SCHEMA,
|
|
271
441
|
decisionId,
|
|
@@ -54,6 +54,8 @@ function unknownUsageEvent({
|
|
|
54
54
|
* Meter one direct provider call that runs outside agentLoop. The started row is
|
|
55
55
|
* durable before the callback resumes into provider work; every outcome then
|
|
56
56
|
* settles known or unknown without persisting prompts, responses, or errors.
|
|
57
|
+
* A dispatch signal closes an acknowledged, canceled pre-dispatch intent with
|
|
58
|
+
* locally proven zero usage; cancellation after dispatch remains unknown.
|
|
57
59
|
* Opt-in includeSettlement returns that persisted status with the raw result.
|
|
58
60
|
*/
|
|
59
61
|
export async function runMeteredDirectModelCall({
|
|
@@ -65,11 +67,20 @@ export async function runMeteredDirectModelCall({
|
|
|
65
67
|
operationId = undefined,
|
|
66
68
|
sessionBudget = null,
|
|
67
69
|
includeSettlement = false,
|
|
70
|
+
dispatchSignal = null,
|
|
68
71
|
call,
|
|
69
72
|
}) {
|
|
70
73
|
if (typeof call !== "function") {
|
|
71
74
|
throw new TypeError("metered direct model call requires a callback");
|
|
72
75
|
}
|
|
76
|
+
if (
|
|
77
|
+
dispatchSignal !== null &&
|
|
78
|
+
(typeof dispatchSignal.aborted !== "boolean" ||
|
|
79
|
+
typeof dispatchSignal.throwIfAborted !== "function")
|
|
80
|
+
) {
|
|
81
|
+
throw new TypeError("metered direct model dispatch signal is invalid");
|
|
82
|
+
}
|
|
83
|
+
dispatchSignal?.throwIfAborted();
|
|
73
84
|
const callId = `direct-${randomUUID()}`;
|
|
74
85
|
if (typeof sessionBudget?.consumeTurn === "function") {
|
|
75
86
|
const admission = sessionBudget.consumeTurn({ id: callId });
|
|
@@ -84,6 +95,7 @@ export async function runMeteredDirectModelCall({
|
|
|
84
95
|
if (includeSettlement) {
|
|
85
96
|
throw new TypeError("direct model settlement requires a session");
|
|
86
97
|
}
|
|
98
|
+
dispatchSignal?.throwIfAborted();
|
|
87
99
|
return call();
|
|
88
100
|
}
|
|
89
101
|
if (typeof persist !== "function") {
|
|
@@ -102,6 +114,28 @@ export async function runMeteredDirectModelCall({
|
|
|
102
114
|
{ callId, provider, model, source, operationId },
|
|
103
115
|
`direct model call ${source}`,
|
|
104
116
|
);
|
|
117
|
+
if (dispatchSignal?.aborted) {
|
|
118
|
+
// A durable intent exists, but no provider callback has run. Close it as
|
|
119
|
+
// a locally proven zero-charge call instead of inventing unknown usage.
|
|
120
|
+
const notDispatched = {
|
|
121
|
+
...projectRuntimeTokenUsage({
|
|
122
|
+
callId,
|
|
123
|
+
provider,
|
|
124
|
+
model,
|
|
125
|
+
source,
|
|
126
|
+
operationId,
|
|
127
|
+
usage: { input_tokens: 0, output_tokens: 0 },
|
|
128
|
+
}),
|
|
129
|
+
settlementOrigin: "local-no-dispatch",
|
|
130
|
+
};
|
|
131
|
+
await persistUsageEvent(persist, "token_usage", notDispatched);
|
|
132
|
+
recordSessionBudgetUsage(
|
|
133
|
+
sessionBudget,
|
|
134
|
+
{ callId, usage: null },
|
|
135
|
+
`direct model call ${source} canceled before dispatch`,
|
|
136
|
+
);
|
|
137
|
+
throw dispatchSignal.reason;
|
|
138
|
+
}
|
|
105
139
|
let result;
|
|
106
140
|
let settlement = "unknown";
|
|
107
141
|
const returnSettled = (status) =>
|
|
@@ -5,6 +5,7 @@ import evolutionRun from "@chainlesschain/session-core/evolution-run";
|
|
|
5
5
|
import { EvolutionEvidenceArtifactAdapter } from "./evolution-evidence-artifact-adapter.js";
|
|
6
6
|
import {
|
|
7
7
|
EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST,
|
|
8
|
+
EVOLUTION_SKILL_DECISION_PROJECTION_RULESET_DIGEST,
|
|
8
9
|
EVOLUTION_PROJECTION_RULESET_DIGEST,
|
|
9
10
|
} from "./evolution-evidence-projector.js";
|
|
10
11
|
import { EvolutionRunLedgerAdapter } from "./evolution-run-ledger-adapter.js";
|
|
@@ -15,6 +16,10 @@ import {
|
|
|
15
16
|
snapshotAgentModelRequest,
|
|
16
17
|
buildAgentModelRequest,
|
|
17
18
|
} from "./agent-model-projection.js";
|
|
19
|
+
import {
|
|
20
|
+
snapshotSkillDecisionRequest,
|
|
21
|
+
buildSkillDecisionPayload,
|
|
22
|
+
} from "./skill-decision-projection.js";
|
|
18
23
|
|
|
19
24
|
const { EVOLUTION_RUN_EVENT_SCHEMA, EVENT_TYPES } = evolutionRun;
|
|
20
25
|
|
|
@@ -265,6 +270,7 @@ export function createAgentEvolutionIngress({
|
|
|
265
270
|
options = {},
|
|
266
271
|
modelRequest = null,
|
|
267
272
|
cacheRecord = false,
|
|
273
|
+
skillDecisionRequest = null,
|
|
268
274
|
) =>
|
|
269
275
|
guardIngress(
|
|
270
276
|
serialize(async () => {
|
|
@@ -304,7 +310,7 @@ export function createAgentEvolutionIngress({
|
|
|
304
310
|
),
|
|
305
311
|
responseEvent: clone(lastModelResponse.event),
|
|
306
312
|
}
|
|
307
|
-
: (modelRequest ?? clone(evidence));
|
|
313
|
+
: (skillDecisionRequest?.payload ?? modelRequest ?? clone(evidence));
|
|
308
314
|
const sourceEnvelope = await issueSourceEnvelope(
|
|
309
315
|
Object.freeze({
|
|
310
316
|
schema: AGENT_EVOLUTION_INGRESS_SCHEMA,
|
|
@@ -321,12 +327,17 @@ export function createAgentEvolutionIngress({
|
|
|
321
327
|
payload,
|
|
322
328
|
};
|
|
323
329
|
const persisted =
|
|
324
|
-
|
|
325
|
-
? await
|
|
326
|
-
: await EvolutionEvidenceArtifactAdapter.prototype.projectAndPersistAgentModelRequest.call(
|
|
330
|
+
skillDecisionRequest !== null
|
|
331
|
+
? await EvolutionEvidenceArtifactAdapter.prototype.projectAndPersistSkillDecisionRequest.call(
|
|
327
332
|
evidenceAdapter,
|
|
328
333
|
projectionInput,
|
|
329
|
-
)
|
|
334
|
+
)
|
|
335
|
+
: modelRequest === null
|
|
336
|
+
? await evidenceAdapter.projectAndPersist(projectionInput)
|
|
337
|
+
: await EvolutionEvidenceArtifactAdapter.prototype.projectAndPersistAgentModelRequest.call(
|
|
338
|
+
evidenceAdapter,
|
|
339
|
+
projectionInput,
|
|
340
|
+
);
|
|
330
341
|
if (
|
|
331
342
|
persisted?.tenantId !== descriptor.tenantId ||
|
|
332
343
|
persisted.evidenceId == null ||
|
|
@@ -353,6 +364,13 @@ export function createAgentEvolutionIngress({
|
|
|
353
364
|
evidenceKind: kind,
|
|
354
365
|
occurredAt,
|
|
355
366
|
derivationManifestDigest: persisted.manifest.digest,
|
|
367
|
+
...(skillDecisionRequest === null
|
|
368
|
+
? {}
|
|
369
|
+
: {
|
|
370
|
+
decisionId: skillDecisionRequest.decisionId,
|
|
371
|
+
requestDigest: skillDecisionRequest.requestDigest,
|
|
372
|
+
candidateSetDigest: skillDecisionRequest.candidateSetDigest,
|
|
373
|
+
}),
|
|
356
374
|
},
|
|
357
375
|
});
|
|
358
376
|
if (kind === "model-input") {
|
|
@@ -370,7 +388,8 @@ export function createAgentEvolutionIngress({
|
|
|
370
388
|
eventId,
|
|
371
389
|
artifact: persisted,
|
|
372
390
|
});
|
|
373
|
-
if (modelRequest === null
|
|
391
|
+
if (modelRequest === null && skillDecisionRequest === null)
|
|
392
|
+
return appended;
|
|
374
393
|
// Resolve the published manifest and every attested component afresh.
|
|
375
394
|
// The prototype call requires the real adapter's private state; an
|
|
376
395
|
// instance-shaped facade cannot mint model-visible input.
|
|
@@ -383,7 +402,9 @@ export function createAgentEvolutionIngress({
|
|
|
383
402
|
resolved.verification.verified !== true ||
|
|
384
403
|
resolved.verification.tenantId !== descriptor.tenantId ||
|
|
385
404
|
resolved.bundle.modelProjection.rulesetDigest !==
|
|
386
|
-
|
|
405
|
+
(skillDecisionRequest === null
|
|
406
|
+
? EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST
|
|
407
|
+
: EVOLUTION_SKILL_DECISION_PROJECTION_RULESET_DIGEST) ||
|
|
387
408
|
resolved.bundle.modelProjection.evidenceId !== persisted.evidenceId
|
|
388
409
|
) {
|
|
389
410
|
throw new Error("Agent model projection readback is unbound");
|
|
@@ -396,6 +417,26 @@ export function createAgentEvolutionIngress({
|
|
|
396
417
|
throw new Error("Agent model projection Run frontier changed");
|
|
397
418
|
}
|
|
398
419
|
if (admissionFailure !== null) throw admissionFailure;
|
|
420
|
+
if (skillDecisionRequest !== null) {
|
|
421
|
+
return Object.freeze({
|
|
422
|
+
payload: buildSkillDecisionPayload(
|
|
423
|
+
skillDecisionRequest.payload,
|
|
424
|
+
resolved.bundle.modelProjection,
|
|
425
|
+
),
|
|
426
|
+
receipt: Object.freeze({
|
|
427
|
+
tenantId: descriptor.tenantId,
|
|
428
|
+
runId: descriptor.runId,
|
|
429
|
+
eventId,
|
|
430
|
+
evidenceId: persisted.evidenceId,
|
|
431
|
+
requestDigest: skillDecisionRequest.requestDigest,
|
|
432
|
+
candidateSetDigest: skillDecisionRequest.candidateSetDigest,
|
|
433
|
+
manifestDigest: persisted.manifest.digest,
|
|
434
|
+
projectionDigest:
|
|
435
|
+
resolved.bundle.modelProjection.projectionDigest,
|
|
436
|
+
rulesetDigest: resolved.bundle.modelProjection.rulesetDigest,
|
|
437
|
+
}),
|
|
438
|
+
});
|
|
439
|
+
}
|
|
399
440
|
return buildAgentModelRequest(
|
|
400
441
|
modelRequest,
|
|
401
442
|
resolved.bundle.modelProjection,
|
|
@@ -522,6 +563,21 @@ export function createAgentEvolutionIngress({
|
|
|
522
563
|
return response;
|
|
523
564
|
},
|
|
524
565
|
start: () => guardIngress(serialize(() => appendStarted())),
|
|
566
|
+
prepareSkillDecisionRequest: (request) => {
|
|
567
|
+
if (admissionFailure !== null) return Promise.reject(admissionFailure);
|
|
568
|
+
let snapshot;
|
|
569
|
+
try {
|
|
570
|
+
snapshot = snapshotSkillDecisionRequest(request);
|
|
571
|
+
if (snapshot.binding.tenantId !== descriptor.tenantId)
|
|
572
|
+
throw new TypeError(
|
|
573
|
+
"Skill decision request belongs to another tenant",
|
|
574
|
+
);
|
|
575
|
+
} catch (error) {
|
|
576
|
+
admissionFailure = ingressFailure(error);
|
|
577
|
+
return Promise.reject(admissionFailure);
|
|
578
|
+
}
|
|
579
|
+
return ingest("skill-decision-input", null, {}, null, false, snapshot);
|
|
580
|
+
},
|
|
525
581
|
prepareModelRequest: (request) => {
|
|
526
582
|
if (admissionFailure !== null) return Promise.reject(admissionFailure);
|
|
527
583
|
let snapshot;
|
|
@@ -340,6 +340,7 @@ export class EvolutionEvidenceArtifactAdapter {
|
|
|
340
340
|
#ttlMs;
|
|
341
341
|
#project;
|
|
342
342
|
#projectAgentModel;
|
|
343
|
+
#projectSkillDecision;
|
|
343
344
|
#verify;
|
|
344
345
|
#ports;
|
|
345
346
|
#resolveManifestRef;
|
|
@@ -385,6 +386,11 @@ export class EvolutionEvidenceArtifactAdapter {
|
|
|
385
386
|
"projectAgentModelRequest",
|
|
386
387
|
"projector",
|
|
387
388
|
);
|
|
389
|
+
this.#projectSkillDecision = captureMethod(
|
|
390
|
+
projector,
|
|
391
|
+
"projectSkillDecisionRequest",
|
|
392
|
+
"projector",
|
|
393
|
+
);
|
|
388
394
|
this.#verify = captureMethod(bundleVerifier, "verify", "bundleVerifier");
|
|
389
395
|
this.#ports = artifactPorts;
|
|
390
396
|
this.#resolveManifestRef =
|
|
@@ -411,6 +417,10 @@ export class EvolutionEvidenceArtifactAdapter {
|
|
|
411
417
|
return this.#persist(await this.#projectAgentModel(input));
|
|
412
418
|
}
|
|
413
419
|
|
|
420
|
+
async projectAndPersistSkillDecisionRequest(input) {
|
|
421
|
+
return this.#persist(await this.#projectSkillDecision(input));
|
|
422
|
+
}
|
|
423
|
+
|
|
414
424
|
async #persist(bundle) {
|
|
415
425
|
const verification = await this.#verify(bundle);
|
|
416
426
|
if (
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
projectAgentOpaqueTransportBlock,
|
|
15
15
|
snapshotAgentModelRequest,
|
|
16
16
|
} from "./agent-model-projection.js";
|
|
17
|
+
import { snapshotSkillDecisionPayload } from "./skill-decision-projection.js";
|
|
17
18
|
import {
|
|
18
19
|
createEvidenceJsonTextBoundary,
|
|
19
20
|
EVIDENCE_JSON_POLICY,
|
|
@@ -523,7 +524,24 @@ export const EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST = `sha256:${createH
|
|
|
523
524
|
"utf8",
|
|
524
525
|
)
|
|
525
526
|
.digest("hex")}`;
|
|
527
|
+
const SKILL_DECISION_RULESET = Object.freeze({
|
|
528
|
+
...AGENT_MODEL_RULESET_V2,
|
|
529
|
+
schema: "chainlesschain.evolution-skill-decision-projection-rules/v1",
|
|
530
|
+
version: 1,
|
|
531
|
+
protocol: "skill-routing-state-and-questions/v1",
|
|
532
|
+
maxInputBytes: 256 * 1024,
|
|
533
|
+
});
|
|
534
|
+
export const EVOLUTION_SKILL_DECISION_PROJECTION_RULESET_DIGEST = `sha256:${createHash(
|
|
535
|
+
"sha256",
|
|
536
|
+
)
|
|
537
|
+
.update(
|
|
538
|
+
`${SKILL_DECISION_RULESET.schema}\0${JSON.stringify(SKILL_DECISION_RULESET)}`,
|
|
539
|
+
"utf8",
|
|
540
|
+
)
|
|
541
|
+
.digest("hex")}`;
|
|
542
|
+
|
|
526
543
|
const SUPPORTED_RULESETS = new Map([
|
|
544
|
+
[EVOLUTION_SKILL_DECISION_PROJECTION_RULESET_DIGEST, SKILL_DECISION_RULESET],
|
|
527
545
|
[RULESET_DIGEST, RULESET],
|
|
528
546
|
[RAW_RULESET_V3_DIGEST, RAW_RULESET_V3],
|
|
529
547
|
[AGENT_MODEL_RULESET_V1_DIGEST, AGENT_MODEL_RULESET_V1],
|
|
@@ -601,7 +619,8 @@ const AGENT_VALUE_PATTERNS = Object.freeze([
|
|
|
601
619
|
]);
|
|
602
620
|
|
|
603
621
|
function valuePatterns(ruleset) {
|
|
604
|
-
return ruleset ===
|
|
622
|
+
return ruleset === SKILL_DECISION_RULESET ||
|
|
623
|
+
ruleset === AGENT_MODEL_RULESET ||
|
|
605
624
|
ruleset === AGENT_MODEL_RULESET_V2 ||
|
|
606
625
|
ruleset === AGENT_MODEL_RULESET_V1
|
|
607
626
|
? AGENT_VALUE_PATTERNS
|
|
@@ -3101,6 +3120,18 @@ function validateBundleIntegrity(bundle) {
|
|
|
3101
3120
|
);
|
|
3102
3121
|
}
|
|
3103
3122
|
if (model.content !== null) {
|
|
3123
|
+
if (ruleset === SKILL_DECISION_RULESET) {
|
|
3124
|
+
snapshotSkillDecisionPayload(model.content);
|
|
3125
|
+
if (
|
|
3126
|
+
model.truncated ||
|
|
3127
|
+
(model.redactionSummary.byType["content-truncation"] ?? 0) > 0
|
|
3128
|
+
) {
|
|
3129
|
+
throw projectionError(
|
|
3130
|
+
EVOLUTION_PROJECTION_INVALID_CODE,
|
|
3131
|
+
"Skill decision projection cannot be truncated",
|
|
3132
|
+
);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3104
3135
|
if (
|
|
3105
3136
|
ruleset === AGENT_MODEL_RULESET ||
|
|
3106
3137
|
ruleset === AGENT_MODEL_RULESET_V2 ||
|
|
@@ -3368,6 +3399,10 @@ export class EvolutionEvidenceProjector {
|
|
|
3368
3399
|
return this.#project(input, AGENT_MODEL_RULESET);
|
|
3369
3400
|
}
|
|
3370
3401
|
|
|
3402
|
+
projectSkillDecisionRequest(input) {
|
|
3403
|
+
return this.#project(input, SKILL_DECISION_RULESET);
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3371
3406
|
async #project(input, ruleset) {
|
|
3372
3407
|
assertExactRecord(input, INPUT_KEYS, "evidence projection input");
|
|
3373
3408
|
if (
|
|
@@ -3381,9 +3416,11 @@ export class EvolutionEvidenceProjector {
|
|
|
3381
3416
|
);
|
|
3382
3417
|
}
|
|
3383
3418
|
const payload =
|
|
3384
|
-
ruleset ===
|
|
3385
|
-
?
|
|
3386
|
-
:
|
|
3419
|
+
ruleset === SKILL_DECISION_RULESET
|
|
3420
|
+
? snapshotSkillDecisionPayload(input.payload)
|
|
3421
|
+
: ruleset === AGENT_MODEL_RULESET
|
|
3422
|
+
? snapshotAgentModelRequest(input.payload)
|
|
3423
|
+
: cloneCanonical(input.payload);
|
|
3387
3424
|
const sourceInputDigest = digest(
|
|
3388
3425
|
payload,
|
|
3389
3426
|
"chainlesschain.evolution-raw-plaintext/v2",
|
|
@@ -3627,9 +3664,11 @@ export class EvolutionEvidenceProjector {
|
|
|
3627
3664
|
const modelProjection = buildModelProjection(
|
|
3628
3665
|
rawRecord,
|
|
3629
3666
|
sanitized,
|
|
3630
|
-
ruleset ===
|
|
3631
|
-
?
|
|
3632
|
-
:
|
|
3667
|
+
ruleset === SKILL_DECISION_RULESET
|
|
3668
|
+
? EVOLUTION_SKILL_DECISION_PROJECTION_RULESET_DIGEST
|
|
3669
|
+
: ruleset === AGENT_MODEL_RULESET
|
|
3670
|
+
? EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST
|
|
3671
|
+
: RAW_RULESET_V3_DIGEST,
|
|
3633
3672
|
);
|
|
3634
3673
|
const trustedSanitized = source.compilable
|
|
3635
3674
|
? sanitizePayload(
|