chainlesschain 0.166.59 → 0.166.63
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 +38 -8
- package/package.json +4 -1
- package/src/assets/web-panel/assets/{AIOps-B9i3kk5f.js → AIOps-CfPrpABR.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DGMs1wBm.js → ActionButton-Bkv1erki.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-D-JGeynM.js → Analytics-fY_7epoU.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DLECnXlP.js → AppLayout-DegaN-aa.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CwaTiXN4.js → Artifacts-90-UNTVE.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BCb7s5Ky.js → Audit-BRQ1F4sA.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D4IOzvKs.js → BackgroundAgents-Cb85uP7O.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cknunk10.js → Backup-CrLBSWQK.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DnU8pbUh.js → BaseInput-DditUW5B.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DOouYIhz.js → Chat-0XozleDQ.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-8QXBJvgy.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-BrumNw6V.js → Checkbox-C2Ck_3ju.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B4E_uI_N.js → Codegen-Chjw-MS7.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C7H2sdaL.js → Col-B_w8_Oka.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BFdzcMSl.js → Community-XAqxPnXq.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BzVXohrg.js → Compact-BX_3GJ3m.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-B_4QcuSH.js → Compliance-DE3kIC9z.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DjuQzJx8.js → Cowork-DPBYp1ey.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Bf2iY-1-.js → Cron-D9cknqzn.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CY9QW7IT.js → Crosschain-BzHrGWY9.js} +1 -1
- package/src/assets/web-panel/assets/{DID-kDZBvaKr.js → DID-BuD8TkZl.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DoYboS3g.js → Dashboard-BbxMuZVK.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-LLEzI6l1.js → Dropdown-jq0ki-tE.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D2kmSvkg.js → EmailListRenderer-RiMvINxT.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DHj2yUGZ.js → EvolutionSettings-DE-URi9i.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-B7Hg7fR0.js → FamilyGuardDashboard-DV3ao62-.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CUdwU6aH.js → Federation-BF6BmBPg.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D1KrwjwY.js → FormItemContext-CKTX59j2.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CXGLoHfw.js → GenericCardRenderer-DZkH-CTs.js} +1 -1
- package/src/assets/web-panel/assets/{Git-TG3Q9JWG.js → Git-B5JYb-w-.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BJD7h_fv.js → Governance-D3WfDZ6W.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Dky4l_bZ.js → Inference-DoSvfDUk.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CCx9aXBV.js → KnowledgeGraph-DUDIzN97.js} +1 -1
- package/src/assets/web-panel/assets/Logs-JfJerfFD.js +2 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-DXgA7cZm.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BzL6KJMX.js → Marketplace-BpVrOM_V.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BReSRzEU.js → McpTools-CFnQdiSv.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BhmkkCxd.js → Memory-Dxv81cNl.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BeQMHr_n.js → MobileBridge-C92eX7PB.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CphEwj_l.js → MobileProjects-BUHw7Wox.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CFk1ibuN.js → Mtc-D-G9H4A1.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-CU9qrmbH.js → MtcAudit-CAEaEtAz.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-CKR-Gh0Y.js → Multisig-Cx_-X9HD.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D1qWY6Mx.js → NLProgramming-DRIKG4Xy.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-B4CM0C65.js → Notes-CmL0vKUv.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-BTQYWveR.js → NotificationSettings-D2cQ5aQn.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DxN6fAn8.js → OrderTableRenderer-CPfd7PNy.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-scgboNfd.js → Organization-EKqO46hz.js} +2 -2
- package/src/assets/web-panel/assets/{Overflow-BP4aQhid.js → Overflow-BOHjBwJo.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-65jIo6MY.js → P2P-Dx4LdCE0.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Bfi4-tDQ.js → PdhVaultBrowser-CgCt2xdT.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DWtxT7bE.js → Permissions-DWjDeO7O.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Bilmr8BR.js → PersonalDataHub-Bx4Od8pG.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-IPIMM-1y.js → Pipeline-oKxws_Ch.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DFB8RiVK.js → Privacy-Df1HVRKR.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DxZksvu1.js → ProjectInit-BraLwZT4.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DsjPsnYN.js → ProjectSettings-CKru54M0.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-CC5FBLLq.js → Projects-BEr7cJcS.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Dk3ViPuF.js → Providers-C8v30DU3.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CJ8R6-bF.js → QrScannerModal-CPyNV-O5.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DJfCPORc.js → QuickAsk-BLIew7A5.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DjDygXeb.js → Recommend-DVjWmsPs.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BJiJ1YHw.js → RemoteSession-B4PNTaEf.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-fYE8jPcc.js → Reputation-D5HOV6oI.js} +1 -1
- package/src/assets/web-panel/assets/{Row-vcvsjMm4.js → Row-DgCQom2M.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CZnKliwn.js → RssFeed-zvIcGHgz.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DEStiFGI.js → Search-C-KbJP_z.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BPb_szxS.js → Security-CasnI-Ld.js} +3 -3
- package/src/assets/web-panel/assets/{Services-TR0xZhSF.js → Services-CR-pSlFv.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BSPu9boC.js → Skeleton-BB5On1b5.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CXEj9pC6.js → Skills-CC-wdQi-.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-jlOlDGMA.js → Sla-CPX5QKEu.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C8oPE_HQ.js → SpeechSettings-Bifkl6Zz.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DZNUx8zt.js → SyncSettings-CdUVeB-S.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-B4T6aoOl.js → Tasks-BttwN3fs.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DeRgtwZ5.js → Templates-CBHNbpQ7.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DDVoXGxa.js → Tenant-B90lEwSQ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DGAUoJMz.js → Terminal-u8KqitsA.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Co4Nkpjm.js → TimelineRenderer-CnEJMkJo.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DaMLa0Fm.js → Tokens-CTM2OOJ_.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-C7iLr-Ik.js → Trigger-Ca8NmmgU.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CxX_tQqi.js → Trust-CI9GpUj2.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-ClrdckEx.js → UkeySign-BlMLGqKK.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DgTVhaoK.js → VideoEditing-C8yCZrH0.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-SIbwES0O.js → Wallet-BpuYrz8o.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-YNqVnhZF.js → WebAuthn-DFpNfLG_.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BvynT9mj.js → WorkflowEditor-BWhLoeU4.js} +1 -1
- package/src/assets/web-panel/assets/{chat-X79b2tVy.js → chat-Dwo4LC7E.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DioWDCbu.js → colors-DkdGvKBf.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DpAXXaqu.js → compact-item-1gI0lfs3.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BYq8bCQX.js → createContext-O9iHirtr.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-axBqv361.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CDJNMJ_n.js → hasIn-DY1jo9BQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUe-hFGb.js → index-1AnBwAoM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CS3QdYDW.js → index-B-kbagPi.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZysaS5T.js → index-B0TX-bLV.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx0_WiSe.js → index-B5l7eb6E.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJEFd0QJ.js → index-BDwV_V5g.js} +1 -1
- package/src/assets/web-panel/assets/{index-D88MWTOx.js → index-BgHG4f2K.js} +1 -1
- package/src/assets/web-panel/assets/{index-BK53HyEP.js → index-BgVO1aXv.js} +1 -1
- package/src/assets/web-panel/assets/{index-COqkDiRU.js → index-Bl6GfsQZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUbuCFWb.js → index-BmAK4o9I.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7cXBJcM.js → index-BsQkwBu2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Byt1ny7l.js → index-BumRAO-7.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bh9la-GL.js → index-Bx4MNNMY.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8_grEFP.js → index-C4c0XaiT.js} +1 -1
- package/src/assets/web-panel/assets/index-CAsOttsq.js +1 -0
- package/src/assets/web-panel/assets/{index-YviHYMA2.js → index-CBqSTwY9.js} +1 -1
- package/src/assets/web-panel/assets/{index-00kVj4me.js → index-D8fqsTHW.js} +1 -1
- package/src/assets/web-panel/assets/{index-Wl55a61D.js → index-DCqPIE3G.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLSt7mOy.js → index-DNnaEzC5.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4xggKQp.js → index-DTppQua6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbxqdIzD.js → index-DfFzjnA0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BwHEGjR7.js → index-DskEFn8M.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3J9FKFr.js → index-DvRvwzc-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGEXGr9g.js → index-DwBcFhcc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6wxVEIZ.js → index-DwJBbK3Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-mHAPEcPi.js → index-DwhJqZqM.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1-NqghD.js → index-Dx51Am-0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DP9ZLjra.js → index-E5Ar6dNV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSFkmRvK.js → index-ETHEhWvI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmNspbVU.js → index-KUrBWzIM.js} +1 -1
- package/src/assets/web-panel/assets/index-MgEKheCh.js +1 -0
- package/src/assets/web-panel/assets/{index-TqLyy6IR.js → index-YnGvCu0P.js} +3 -3
- package/src/assets/web-panel/assets/{index-Q3WQ5Zhr.js → index-hRtVittm.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAnXSg0r.js → index-nXoV4OCZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBvA7Hxj.js → index-qUbrqzvO.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIO8EVHt.js → index-rIJqtLz-.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8ChecWd.js → index-rkkMl4Lb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DwG9khVs.js → index-tXjOuLZm.js} +1 -1
- package/src/assets/web-panel/assets/{index-V6l3ia83.js → index-zLOzCcxM.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bt0zcD5R.js → index-zPpssHXA.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-18rmGkik.js → initDefaultProps-Du5HHTVt.js} +1 -1
- package/src/assets/web-panel/assets/{motion-3kvGzSgV.js → motion-D9mAVPKP.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dx3DiVHc.js → move-DPO_sFtt.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-VX1dFJEI.js → mtc-parser-CnezVcXi.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CniSeCOA.js → omit-DNpYMbet.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-RPggmcOd.js → pickAttrs-BUFm_slL.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B45YBykr.js → placementArrow-DvwJtnzY.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D0nciAEn.js → responsiveObserve-CUWOh_KI.js} +1 -1
- package/src/assets/web-panel/assets/{slide-UxLNWqjI.js → slide-bVHCUsdj.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CukpV_uI.js → statusUtils-FlOzOrxf.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BIcEZk6Y.js → styleChecker-C6CFXutA.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Zah-xvV3.js → useFlexGapSupport-BNGqO_E0.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BA7ihKFN.js → useFs-DyKOrA27.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-C64CsyY3.js → usePersonalDataHub-DZAqeMAJ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-Datcekgj.js → vnode-Do7fVasi.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CaFQv1KF.js → zoom-DYkEmOT2.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/data/changelog.json +52 -0
- package/src/lib/background-agent-supervisor.js +10 -1
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +119 -12
- package/src/lib/evolution/evolution-artifact-ports.js +6 -0
- package/src/lib/evolution/evolution-deployment-loader.js +139 -0
- package/src/lib/evolution/evolution-eval-gate.js +5 -0
- package/src/lib/evolution/evolution-ledger-ports.js +41 -17
- package/src/lib/evolution/pm-exploration-benchmark.js +253 -0
- package/src/lib/evolution/pm-exploration-budget-executor.js +346 -0
- package/src/lib/evolution/pm-exploration-business-grader.js +581 -0
- package/src/lib/evolution/pm-exploration-evidence-bundle.js +613 -0
- package/src/lib/evolution/pm-exploration-execution-host.js +946 -0
- package/src/lib/evolution/pm-exploration-ledger-adapter.js +860 -0
- package/src/lib/evolution/pm-exploration-provider-settlement-adapter.js +420 -0
- package/src/lib/evolution/pm-exploration-receipts.js +626 -0
- package/src/lib/evolution/pm-exploration-recovery-snapshot-store.js +521 -0
- package/src/lib/evolution/pm-exploration-rounds.js +842 -0
- package/src/lib/evolution/pm-exploration-transition-committer.js +541 -0
- package/src/lib/evolution/pm-exploration-volcengine-provider.js +724 -0
- package/src/lib/evolution/pm-result-grader.cjs +287 -0
- package/src/lib/read-file-loop-guard.js +36 -5
- package/src/lib/secure-fs.js +51 -4
- package/src/lib/task-progress-tracker.js +29 -7
- package/src/lib/text-file-search.js +1 -0
- package/src/runtime/agent-core.js +46 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-C4tdSms8.js +0 -1
- package/src/assets/web-panel/assets/Logs-BtesccPB.js +0 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-DoN7oE2J.js +0 -1
- package/src/assets/web-panel/assets/devWarning-ONeWC5dH.js +0 -1
- package/src/assets/web-panel/assets/index--QLnQuO9.js +0 -1
- package/src/assets/web-panel/assets/index-CkgeII0e.js +0 -1
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/** PM dataset tooling and launch preflight. No runtime or promotion authority. */
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { isProxy } from "node:util/types";
|
|
4
|
+
import {
|
|
5
|
+
buildEvolutionEvalSuite,
|
|
6
|
+
computeEvolutionEvalTrainingPartitionDigest,
|
|
7
|
+
verifyEvolutionEvalSuite,
|
|
8
|
+
} from "./evolution-eval-gate.js";
|
|
9
|
+
import { createPmExplorationPlan } from "./pm-exploration-rounds.js";
|
|
10
|
+
import grader from "./pm-result-grader.cjs";
|
|
11
|
+
|
|
12
|
+
const GROUPS = ["template", "project", "principal", "timeWindow"];
|
|
13
|
+
const PREFIXES = ["template", "project", "principal", "time-window"];
|
|
14
|
+
const GROUP_DIGEST = /^[a-f0-9]{64}$/u;
|
|
15
|
+
const REQUIRED_ENV = Object.freeze({
|
|
16
|
+
NODE_ENV: "production",
|
|
17
|
+
MOCK_LLM: "false",
|
|
18
|
+
MOCK_HARDWARE: "false",
|
|
19
|
+
SKIP_SLOW_INIT: "false",
|
|
20
|
+
CHAINLESSCHAIN_DISABLE_NATIVE_DB: "0",
|
|
21
|
+
CHAINLESSCHAIN_DISABLE_DB_PERSISTENCE: "0",
|
|
22
|
+
CC_IPC_ACTOR_GUARD: "enforce",
|
|
23
|
+
CC_IPC_RBAC_GUARD: "enforce",
|
|
24
|
+
});
|
|
25
|
+
const PM_GRADER = "pm-objective-outcome-v1";
|
|
26
|
+
|
|
27
|
+
function exact(value, keys, label) {
|
|
28
|
+
if (
|
|
29
|
+
!value ||
|
|
30
|
+
typeof value !== "object" ||
|
|
31
|
+
isProxy(value) ||
|
|
32
|
+
Object.getPrototypeOf(value) !== Object.prototype
|
|
33
|
+
)
|
|
34
|
+
throw new TypeError(`${label} must be plain data`);
|
|
35
|
+
const actual = Reflect.ownKeys(value);
|
|
36
|
+
if (
|
|
37
|
+
actual.length !== keys.length ||
|
|
38
|
+
actual.some((key) => {
|
|
39
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
40
|
+
return (
|
|
41
|
+
!keys.includes(key) ||
|
|
42
|
+
!descriptor.enumerable ||
|
|
43
|
+
!("value" in descriptor)
|
|
44
|
+
);
|
|
45
|
+
})
|
|
46
|
+
)
|
|
47
|
+
throw new TypeError(`${label} has unexpected or missing fields`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function groupKey(kind, value) {
|
|
51
|
+
if (
|
|
52
|
+
typeof value !== "string" ||
|
|
53
|
+
value.trim() !== value ||
|
|
54
|
+
!value ||
|
|
55
|
+
value.length > 256
|
|
56
|
+
)
|
|
57
|
+
throw new TypeError(`invalid ${kind} group`);
|
|
58
|
+
return `${kind}-${createHash("sha256").update(value).digest("hex")}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Trusted dataset-author input; store the result outside the Actor workspace. */
|
|
62
|
+
export function buildPmExplorationSuite(input) {
|
|
63
|
+
exact(input, ["suiteId", "datasetVersion", "tasks"], "PM suite input");
|
|
64
|
+
if (
|
|
65
|
+
!Array.isArray(input.tasks) ||
|
|
66
|
+
input.tasks.length < 3 ||
|
|
67
|
+
input.tasks.length > 10_000
|
|
68
|
+
)
|
|
69
|
+
throw new TypeError(
|
|
70
|
+
"PM suite requires bounded training, validation and test tasks",
|
|
71
|
+
);
|
|
72
|
+
const tasks = input.tasks.map((task) => {
|
|
73
|
+
exact(task, ["id", "split", "groups", "prompt", "expected"], "PM task");
|
|
74
|
+
exact(task.groups, GROUPS, "PM task groups");
|
|
75
|
+
if (
|
|
76
|
+
typeof task.prompt !== "string" ||
|
|
77
|
+
!task.prompt.trim() ||
|
|
78
|
+
task.prompt.length > 16_384
|
|
79
|
+
)
|
|
80
|
+
throw new TypeError("PM task prompt is required and bounded");
|
|
81
|
+
const expected = grader.normalizePmExpectation(task.expected);
|
|
82
|
+
return {
|
|
83
|
+
id: task.id,
|
|
84
|
+
split: task.split,
|
|
85
|
+
groupKeys: GROUPS.map((key, i) =>
|
|
86
|
+
groupKey(PREFIXES[i], task.groups[key]),
|
|
87
|
+
),
|
|
88
|
+
taskType: expected.kind === "file-export" ? "file" : "retrieval",
|
|
89
|
+
publicInput: { prompt: task.prompt },
|
|
90
|
+
graderId: PM_GRADER,
|
|
91
|
+
privateExpected: expected,
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
return verifyPmSuite(
|
|
95
|
+
buildEvolutionEvalSuite({
|
|
96
|
+
suiteId: input.suiteId,
|
|
97
|
+
datasetVersion: input.datasetVersion,
|
|
98
|
+
tasks,
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function verifyPmSuite(value) {
|
|
104
|
+
const suite = verifyEvolutionEvalSuite(value);
|
|
105
|
+
if (
|
|
106
|
+
!["training", "validation", "test"].every((split) =>
|
|
107
|
+
suite.tasks.some((task) => task.split === split),
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
throw new TypeError("PM suite must include all three partitions");
|
|
111
|
+
for (const task of suite.tasks) {
|
|
112
|
+
exact(task.publicInput, ["prompt"], "PM public input");
|
|
113
|
+
if (
|
|
114
|
+
typeof task.publicInput.prompt !== "string" ||
|
|
115
|
+
!task.publicInput.prompt.trim() ||
|
|
116
|
+
task.publicInput.prompt.length > 16_384
|
|
117
|
+
)
|
|
118
|
+
throw new TypeError("invalid PM public prompt");
|
|
119
|
+
const expected = grader.normalizePmExpectation(task.privateExpected);
|
|
120
|
+
if (
|
|
121
|
+
task.graderId !== PM_GRADER ||
|
|
122
|
+
task.taskType !==
|
|
123
|
+
(expected.kind === "file-export" ? "file" : "retrieval") ||
|
|
124
|
+
!task.groupKeys.every(
|
|
125
|
+
(key, index) =>
|
|
126
|
+
key.startsWith(`${PREFIXES[index]}-`) &&
|
|
127
|
+
GROUP_DIGEST.test(key.slice(PREFIXES[index].length + 1)),
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
throw new TypeError("suite is not a PM exploration dataset");
|
|
131
|
+
}
|
|
132
|
+
return suite;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Explicit projection: no validation/test tasks, expected answers or grader IDs. */
|
|
136
|
+
export function projectPmExplorationTrainingView(value) {
|
|
137
|
+
const suite = verifyPmSuite(value);
|
|
138
|
+
return Object.freeze({
|
|
139
|
+
suiteDigest: suite.suiteDigest,
|
|
140
|
+
trainingPartitionDigest: computeEvolutionEvalTrainingPartitionDigest(suite),
|
|
141
|
+
tasks: Object.freeze(
|
|
142
|
+
suite.tasks
|
|
143
|
+
.filter((task) => task.split === "training")
|
|
144
|
+
.map((task) =>
|
|
145
|
+
Object.freeze({ id: task.id, publicInput: task.publicInput }),
|
|
146
|
+
),
|
|
147
|
+
),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Structural check only; signed provenance is still verified by EvolutionEvalGate. */
|
|
152
|
+
export function assertPmExplorationTrainingSources(value, input) {
|
|
153
|
+
exact(
|
|
154
|
+
input,
|
|
155
|
+
["trainingPartitionDigest", "sourceTaskIds"],
|
|
156
|
+
"PM memory sources",
|
|
157
|
+
);
|
|
158
|
+
const view = projectPmExplorationTrainingView(value);
|
|
159
|
+
if (input.trainingPartitionDigest !== view.trainingPartitionDigest)
|
|
160
|
+
throw new Error("PM training partition binding mismatch");
|
|
161
|
+
const ids = input.sourceTaskIds;
|
|
162
|
+
if (
|
|
163
|
+
!Array.isArray(ids) ||
|
|
164
|
+
ids.length === 0 ||
|
|
165
|
+
ids.length > view.tasks.length ||
|
|
166
|
+
new Set(ids).size !== ids.length
|
|
167
|
+
)
|
|
168
|
+
throw new TypeError("PM source task IDs must be nonempty and unique");
|
|
169
|
+
const allowed = new Set(view.tasks.map((task) => task.id));
|
|
170
|
+
if (ids.some((id) => !allowed.has(id)))
|
|
171
|
+
throw new Error("PM memory source is outside the training partition");
|
|
172
|
+
return Object.freeze({
|
|
173
|
+
trainingPartitionDigest: view.trainingPartitionDigest,
|
|
174
|
+
sourceTaskIds: Object.freeze([...ids]),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Builds the round protocol from the verified training-only projection. */
|
|
179
|
+
export function buildPmExplorationRoundPlan(value, input) {
|
|
180
|
+
exact(
|
|
181
|
+
input,
|
|
182
|
+
[
|
|
183
|
+
"planId",
|
|
184
|
+
"environmentDigest",
|
|
185
|
+
"initialMemoryDigest",
|
|
186
|
+
"broadBranchIds",
|
|
187
|
+
"maxRounds",
|
|
188
|
+
"maxTokens",
|
|
189
|
+
"maxToolCalls",
|
|
190
|
+
"maxWallClockMs",
|
|
191
|
+
"maxConsecutiveNoGain",
|
|
192
|
+
],
|
|
193
|
+
"PM round plan input",
|
|
194
|
+
);
|
|
195
|
+
const training = projectPmExplorationTrainingView(value);
|
|
196
|
+
return createPmExplorationPlan({
|
|
197
|
+
...input,
|
|
198
|
+
suiteDigest: training.suiteDigest,
|
|
199
|
+
trainingPartitionDigest: training.trainingPartitionDigest,
|
|
200
|
+
trainingTaskIds: training.tasks.map((task) => task.id),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function buildPmExplorationLaunchProfile(budget) {
|
|
205
|
+
exact(budget, ["maxTokens", "maxToolCalls", "maxWallClockMs"], "PM budget");
|
|
206
|
+
for (const key of Object.keys(budget)) {
|
|
207
|
+
if (!Number.isSafeInteger(budget[key]) || budget[key] <= 0)
|
|
208
|
+
throw new TypeError(`${key} must be a positive safe integer`);
|
|
209
|
+
}
|
|
210
|
+
return Object.freeze({
|
|
211
|
+
schema: "chainlesschain.pm-exploration-launch-profile/v1",
|
|
212
|
+
environment: REQUIRED_ENV,
|
|
213
|
+
budget: Object.freeze({ ...budget }),
|
|
214
|
+
budgetEnforced: false,
|
|
215
|
+
runtimeVerified: false,
|
|
216
|
+
productionQualified: false,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** No secrets or raw environment values are copied to diagnostics. */
|
|
221
|
+
export function inspectPmExplorationEnvironment(environment = process.env) {
|
|
222
|
+
if (!environment || typeof environment !== "object" || isProxy(environment))
|
|
223
|
+
throw new TypeError("environment must be a data object");
|
|
224
|
+
const issues = Object.entries(REQUIRED_ENV).flatMap(([key, required]) => {
|
|
225
|
+
const prop = Object.getOwnPropertyDescriptor(environment, key);
|
|
226
|
+
return prop && "value" in prop && prop.value === required
|
|
227
|
+
? []
|
|
228
|
+
: [
|
|
229
|
+
Object.freeze({
|
|
230
|
+
code: "PM_RUNTIME_CONFIGURATION_MISMATCH",
|
|
231
|
+
variable: key,
|
|
232
|
+
required,
|
|
233
|
+
}),
|
|
234
|
+
];
|
|
235
|
+
});
|
|
236
|
+
return Object.freeze({
|
|
237
|
+
schema: "chainlesschain.pm-exploration-preflight/v1",
|
|
238
|
+
status: issues.length ? "blocked" : "requires-host-verification",
|
|
239
|
+
configurationCompatible: issues.length === 0,
|
|
240
|
+
issues: Object.freeze(issues),
|
|
241
|
+
missingEvidence: Object.freeze([
|
|
242
|
+
"authenticated-model-ingress",
|
|
243
|
+
"unlocked-real-identity",
|
|
244
|
+
"enforced-tool-and-workspace-isolation",
|
|
245
|
+
"host-enforced-budget",
|
|
246
|
+
"independent-read-only-grader",
|
|
247
|
+
"reset-and-restart-persistence",
|
|
248
|
+
]),
|
|
249
|
+
launchAllowed: false,
|
|
250
|
+
runtimeVerified: false,
|
|
251
|
+
productionQualified: false,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { performance } from "node:perf_hooks";
|
|
3
|
+
import { isProxy } from "node:util/types";
|
|
4
|
+
|
|
5
|
+
export const PM_EXPLORATION_BUDGET_OUTCOME_SCHEMA =
|
|
6
|
+
"chainlesschain.pm-exploration-budget-outcome/v1";
|
|
7
|
+
|
|
8
|
+
const TOOL_ID = /^[a-z][a-z0-9]*(?:[._:-][a-z0-9]+)*$/u;
|
|
9
|
+
|
|
10
|
+
function exact(value, keys, label) {
|
|
11
|
+
if (
|
|
12
|
+
!value ||
|
|
13
|
+
typeof value !== "object" ||
|
|
14
|
+
Array.isArray(value) ||
|
|
15
|
+
isProxy(value) ||
|
|
16
|
+
Object.getPrototypeOf(value) !== Object.prototype
|
|
17
|
+
) {
|
|
18
|
+
throw new TypeError(`${label} must be a plain object`);
|
|
19
|
+
}
|
|
20
|
+
const actual = Reflect.ownKeys(value);
|
|
21
|
+
if (
|
|
22
|
+
actual.length !== keys.length ||
|
|
23
|
+
actual.some((key) => {
|
|
24
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
25
|
+
return (
|
|
26
|
+
typeof key !== "string" ||
|
|
27
|
+
!keys.includes(key) ||
|
|
28
|
+
!descriptor ||
|
|
29
|
+
!descriptor.enumerable ||
|
|
30
|
+
!("value" in descriptor)
|
|
31
|
+
);
|
|
32
|
+
})
|
|
33
|
+
) {
|
|
34
|
+
throw new TypeError(`${label} has unexpected or accessor fields`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function integer(value, label) {
|
|
39
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
40
|
+
throw new TypeError(`${label} must be a non-negative safe integer`);
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function copyJson(
|
|
45
|
+
value,
|
|
46
|
+
label,
|
|
47
|
+
context = { bytes: 0, nodes: 0, seen: new WeakSet() },
|
|
48
|
+
) {
|
|
49
|
+
if (
|
|
50
|
+
value === null ||
|
|
51
|
+
typeof value === "string" ||
|
|
52
|
+
typeof value === "boolean"
|
|
53
|
+
) {
|
|
54
|
+
context.bytes += Buffer.byteLength(JSON.stringify(value));
|
|
55
|
+
if (context.bytes > 1024 * 1024)
|
|
56
|
+
throw new TypeError(`${label} exceeds its byte bound`);
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
60
|
+
if (
|
|
61
|
+
!value ||
|
|
62
|
+
typeof value !== "object" ||
|
|
63
|
+
isProxy(value) ||
|
|
64
|
+
context.seen.has(value) ||
|
|
65
|
+
context.nodes >= 20_000
|
|
66
|
+
) {
|
|
67
|
+
throw new TypeError(`${label} must be bounded acyclic JSON data`);
|
|
68
|
+
}
|
|
69
|
+
context.seen.add(value);
|
|
70
|
+
context.nodes += 1;
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
if (
|
|
73
|
+
Object.getPrototypeOf(value) !== Array.prototype ||
|
|
74
|
+
Reflect.ownKeys(value).length !== value.length + 1
|
|
75
|
+
) {
|
|
76
|
+
throw new TypeError(`${label} must be a dense plain array`);
|
|
77
|
+
}
|
|
78
|
+
const result = [];
|
|
79
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
80
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
81
|
+
if (!descriptor || !descriptor.enumerable || !("value" in descriptor))
|
|
82
|
+
throw new TypeError(`${label} contains a hole or accessor`);
|
|
83
|
+
result.push(copyJson(descriptor.value, label, context));
|
|
84
|
+
}
|
|
85
|
+
context.seen.delete(value);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
if (Object.getPrototypeOf(value) !== Object.prototype)
|
|
89
|
+
throw new TypeError(`${label} must use the default object prototype`);
|
|
90
|
+
const result = {};
|
|
91
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
92
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
93
|
+
if (
|
|
94
|
+
typeof key !== "string" ||
|
|
95
|
+
!descriptor ||
|
|
96
|
+
!descriptor.enumerable ||
|
|
97
|
+
!("value" in descriptor)
|
|
98
|
+
) {
|
|
99
|
+
throw new TypeError(`${label} contains a symbol or accessor`);
|
|
100
|
+
}
|
|
101
|
+
context.bytes += Buffer.byteLength(key);
|
|
102
|
+
if (context.bytes > 1024 * 1024)
|
|
103
|
+
throw new TypeError(`${label} exceeds its byte bound`);
|
|
104
|
+
Object.defineProperty(result, key, {
|
|
105
|
+
value: copyJson(descriptor.value, label, context),
|
|
106
|
+
enumerable: true,
|
|
107
|
+
configurable: true,
|
|
108
|
+
writable: true,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
context.seen.delete(value);
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function traceDigest(reason, failureClass) {
|
|
116
|
+
return `sha256:${createHash("sha256")
|
|
117
|
+
.update(PM_EXPLORATION_BUDGET_OUTCOME_SCHEMA)
|
|
118
|
+
.update("\0")
|
|
119
|
+
.update(reason)
|
|
120
|
+
.update("\0")
|
|
121
|
+
.update(failureClass)
|
|
122
|
+
.digest("hex")}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function abortReason(signal) {
|
|
126
|
+
const reason = signal?.reason;
|
|
127
|
+
if (reason instanceof PmExplorationBudgetError) return reason.reason;
|
|
128
|
+
return "parent-aborted";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export class PmExplorationBudgetError extends Error {
|
|
132
|
+
constructor(reason) {
|
|
133
|
+
super(`PM exploration execution stopped: ${reason}`);
|
|
134
|
+
this.name = "AbortError";
|
|
135
|
+
this.code = "CC_PM_EXPLORATION_BUDGET_EXHAUSTED";
|
|
136
|
+
this.reason = reason;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function executePmExplorationBudgetedOperation({
|
|
141
|
+
limits,
|
|
142
|
+
operation,
|
|
143
|
+
allowedToolIds = [],
|
|
144
|
+
invokeTool = null,
|
|
145
|
+
parentSignal = null,
|
|
146
|
+
now = performance.now.bind(performance),
|
|
147
|
+
setTimer = setTimeout,
|
|
148
|
+
clearTimer = clearTimeout,
|
|
149
|
+
} = {}) {
|
|
150
|
+
exact(
|
|
151
|
+
limits,
|
|
152
|
+
["maxTokens", "maxToolCalls", "maxWallClockMs"],
|
|
153
|
+
"PM exploration budget limits",
|
|
154
|
+
);
|
|
155
|
+
const maximum = Object.freeze({
|
|
156
|
+
tokens: integer(limits.maxTokens, "maxTokens"),
|
|
157
|
+
toolCalls: integer(limits.maxToolCalls, "maxToolCalls"),
|
|
158
|
+
wallClockMs: integer(limits.maxWallClockMs, "maxWallClockMs"),
|
|
159
|
+
});
|
|
160
|
+
if (typeof operation !== "function" || isProxy(operation))
|
|
161
|
+
throw new TypeError(
|
|
162
|
+
"PM exploration budget operation must be a direct function",
|
|
163
|
+
);
|
|
164
|
+
if (
|
|
165
|
+
invokeTool !== null &&
|
|
166
|
+
(typeof invokeTool !== "function" || isProxy(invokeTool))
|
|
167
|
+
)
|
|
168
|
+
throw new TypeError("PM exploration tool broker must be a direct function");
|
|
169
|
+
if (!Array.isArray(allowedToolIds) || isProxy(allowedToolIds))
|
|
170
|
+
throw new TypeError("allowedToolIds must be an array");
|
|
171
|
+
const toolIds = new Set();
|
|
172
|
+
for (const toolId of allowedToolIds) {
|
|
173
|
+
if (
|
|
174
|
+
typeof toolId !== "string" ||
|
|
175
|
+
toolId.length > 256 ||
|
|
176
|
+
!TOOL_ID.test(toolId) ||
|
|
177
|
+
toolIds.has(toolId)
|
|
178
|
+
) {
|
|
179
|
+
throw new TypeError("allowedToolIds contains an invalid or duplicate ID");
|
|
180
|
+
}
|
|
181
|
+
toolIds.add(toolId);
|
|
182
|
+
}
|
|
183
|
+
if (
|
|
184
|
+
(parentSignal !== null && !(parentSignal instanceof AbortSignal)) ||
|
|
185
|
+
typeof now !== "function" ||
|
|
186
|
+
typeof setTimer !== "function" ||
|
|
187
|
+
typeof clearTimer !== "function"
|
|
188
|
+
) {
|
|
189
|
+
throw new TypeError(
|
|
190
|
+
"PM exploration budget runtime dependencies are invalid",
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const controller = new AbortController();
|
|
195
|
+
const totals = { tokens: 0, toolCalls: 0 };
|
|
196
|
+
let activeTools = 0;
|
|
197
|
+
let closed = false;
|
|
198
|
+
let stoppedReason = null;
|
|
199
|
+
const startedAt = Number(now());
|
|
200
|
+
if (!Number.isFinite(startedAt))
|
|
201
|
+
throw new TypeError("PM exploration monotonic clock is invalid");
|
|
202
|
+
|
|
203
|
+
const stop = (reason) => {
|
|
204
|
+
if (stoppedReason === null) stoppedReason = reason;
|
|
205
|
+
if (!controller.signal.aborted)
|
|
206
|
+
controller.abort(new PmExplorationBudgetError(stoppedReason));
|
|
207
|
+
};
|
|
208
|
+
const assertOpen = () => {
|
|
209
|
+
if (closed) throw new Error("PM exploration budget runtime is closed");
|
|
210
|
+
if (controller.signal.aborted)
|
|
211
|
+
throw (
|
|
212
|
+
controller.signal.reason ?? new PmExplorationBudgetError(stoppedReason)
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const runtime = Object.freeze({
|
|
217
|
+
signal: controller.signal,
|
|
218
|
+
recordTokens(count) {
|
|
219
|
+
assertOpen();
|
|
220
|
+
const delta = integer(count, "token count");
|
|
221
|
+
if (!Number.isSafeInteger(totals.tokens + delta))
|
|
222
|
+
throw new TypeError("token total exceeds the safe integer range");
|
|
223
|
+
totals.tokens += delta;
|
|
224
|
+
if (totals.tokens > maximum.tokens) {
|
|
225
|
+
stop("max-tokens");
|
|
226
|
+
throw controller.signal.reason;
|
|
227
|
+
}
|
|
228
|
+
return totals.tokens;
|
|
229
|
+
},
|
|
230
|
+
async invokeTool(toolId, input) {
|
|
231
|
+
assertOpen();
|
|
232
|
+
if (!toolIds.has(toolId)) {
|
|
233
|
+
stop("tool-not-allowed");
|
|
234
|
+
throw controller.signal.reason;
|
|
235
|
+
}
|
|
236
|
+
totals.toolCalls += 1;
|
|
237
|
+
if (totals.toolCalls > maximum.toolCalls) {
|
|
238
|
+
stop("max-tool-calls");
|
|
239
|
+
throw controller.signal.reason;
|
|
240
|
+
}
|
|
241
|
+
if (invokeTool === null) {
|
|
242
|
+
stop("tool-broker-unavailable");
|
|
243
|
+
throw controller.signal.reason;
|
|
244
|
+
}
|
|
245
|
+
const safeInput = copyJson(input, "tool input");
|
|
246
|
+
activeTools += 1;
|
|
247
|
+
try {
|
|
248
|
+
const output = await invokeTool(
|
|
249
|
+
Object.freeze({
|
|
250
|
+
toolId,
|
|
251
|
+
input: safeInput,
|
|
252
|
+
signal: controller.signal,
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
assertOpen();
|
|
256
|
+
return copyJson(output, "tool output");
|
|
257
|
+
} finally {
|
|
258
|
+
activeTools -= 1;
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
snapshot() {
|
|
262
|
+
const current = Number(now());
|
|
263
|
+
if (!Number.isFinite(current) || current < startedAt)
|
|
264
|
+
throw new TypeError("PM exploration monotonic clock moved backwards");
|
|
265
|
+
return Object.freeze({
|
|
266
|
+
tokens: totals.tokens,
|
|
267
|
+
toolCalls: totals.toolCalls,
|
|
268
|
+
wallClockMs: Math.ceil(current - startedAt),
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const parentAbort = () => stop(abortReason(parentSignal));
|
|
274
|
+
if (parentSignal) {
|
|
275
|
+
if (parentSignal.aborted) parentAbort();
|
|
276
|
+
else parentSignal.addEventListener("abort", parentAbort, { once: true });
|
|
277
|
+
}
|
|
278
|
+
if (maximum.wallClockMs === 0) stop("max-wall-clock-ms");
|
|
279
|
+
|
|
280
|
+
let timer = null;
|
|
281
|
+
const timeout = new Promise((resolve) => {
|
|
282
|
+
timer = setTimer(() => {
|
|
283
|
+
stop("max-wall-clock-ms");
|
|
284
|
+
resolve(Object.freeze({ kind: "stopped" }));
|
|
285
|
+
}, maximum.wallClockMs);
|
|
286
|
+
});
|
|
287
|
+
const attempted = Promise.resolve()
|
|
288
|
+
.then(() => {
|
|
289
|
+
if (controller.signal.aborted)
|
|
290
|
+
throw (
|
|
291
|
+
controller.signal.reason ??
|
|
292
|
+
new PmExplorationBudgetError(stoppedReason)
|
|
293
|
+
);
|
|
294
|
+
return operation(runtime);
|
|
295
|
+
})
|
|
296
|
+
.then(
|
|
297
|
+
(value) => Object.freeze({ kind: "value", value }),
|
|
298
|
+
() => Object.freeze({ kind: "error" }),
|
|
299
|
+
);
|
|
300
|
+
const winner = controller.signal.aborted
|
|
301
|
+
? Object.freeze({ kind: "stopped" })
|
|
302
|
+
: await Promise.race([attempted, timeout]);
|
|
303
|
+
|
|
304
|
+
if (timer !== null) clearTimer(timer);
|
|
305
|
+
if (parentSignal && !parentSignal.aborted)
|
|
306
|
+
parentSignal.removeEventListener("abort", parentAbort);
|
|
307
|
+
let current = Number(now());
|
|
308
|
+
if (!Number.isFinite(current) || current < startedAt) current = startedAt;
|
|
309
|
+
const wallClockMs = Math.ceil(current - startedAt);
|
|
310
|
+
if (wallClockMs > maximum.wallClockMs) stop("max-wall-clock-ms");
|
|
311
|
+
if (activeTools !== 0) stop("unsettled-tools");
|
|
312
|
+
closed = true;
|
|
313
|
+
|
|
314
|
+
const metrics = Object.freeze({
|
|
315
|
+
tokens: totals.tokens,
|
|
316
|
+
toolCalls: totals.toolCalls,
|
|
317
|
+
wallClockMs,
|
|
318
|
+
});
|
|
319
|
+
let status;
|
|
320
|
+
let failureClass;
|
|
321
|
+
let reason;
|
|
322
|
+
let value = null;
|
|
323
|
+
if (stoppedReason !== null || winner.kind === "stopped") {
|
|
324
|
+
status = "aborted";
|
|
325
|
+
reason = stoppedReason ?? "parent-aborted";
|
|
326
|
+
failureClass = reason.startsWith("max-") ? "budget" : "sandbox";
|
|
327
|
+
} else if (winner.kind === "error") {
|
|
328
|
+
status = "failed";
|
|
329
|
+
reason = "operation-failed";
|
|
330
|
+
failureClass = "infrastructure";
|
|
331
|
+
} else {
|
|
332
|
+
status = "succeeded";
|
|
333
|
+
reason = "completed";
|
|
334
|
+
failureClass = "none";
|
|
335
|
+
value = winner.value;
|
|
336
|
+
}
|
|
337
|
+
return Object.freeze({
|
|
338
|
+
schema: PM_EXPLORATION_BUDGET_OUTCOME_SCHEMA,
|
|
339
|
+
status,
|
|
340
|
+
failureClass,
|
|
341
|
+
reason,
|
|
342
|
+
metrics,
|
|
343
|
+
traceDigest: traceDigest(reason, failureClass),
|
|
344
|
+
value,
|
|
345
|
+
});
|
|
346
|
+
}
|