chainlesschain 0.166.41 → 0.166.43
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/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-CK9AMSXc.js → AIOps-BIl-Z62M.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-B_PARoec.js → ActionButton-BgPi_Te6.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-kB2GmWlI.js → Analytics-CaNIzlAG.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-D9GSx2hl.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-C30LufT9.js → Artifacts-Kq7kotzv.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Dx477PoD.js → Audit-e1RTJLco.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-ClvsCYCT.js → BackgroundAgents-BfyNT0BW.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Bx9uCsgt.js → Backup-BEAq7i6S.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Br_ecv7G.js → BaseInput-BHuP82DF.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Dzr-d6NV.js → Chat-BLPgCQsB.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DWXPJh-J.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-C9O-E90A.js → Checkbox-DDJrOqEh.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CTRBkb29.js → Codegen-CxyKcM6S.js} +1 -1
- package/src/assets/web-panel/assets/{Col--50unLLP.js → Col-BYFh9rE1.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CFtrKGE_.js → Community-D8JPppoh.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DFoxxofh.js → Compact-B5VGSqZe.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CTpxqxpc.js → Compliance-C7KiFcUK.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Dr-56gcV.js → Cowork-D-F2fgA_.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-B4xZgO5G.js → Cron-B6TmPqRO.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Da7BQ7f3.js → Crosschain-BeGcBXhk.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DRsk74D5.js → DID-9QklLcmQ.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DqtAeCxK.js → Dashboard-DIadmsuS.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CvWZp7Kk.js → Dropdown-0I5gks3i.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D2gWVD3O.js → EmailListRenderer-BdTAjT2q.js} +1 -1
- package/src/assets/web-panel/assets/EvolutionSettings-Bdw8ApoT.css +1 -0
- package/src/assets/web-panel/assets/EvolutionSettings-C7_tq643.js +1 -0
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BFrROP-5.js → FamilyGuardDashboard-DQUQWwUY.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CNMTv4_n.js → Federation-Drgi--Zn.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Ct_saU8n.js → FormItemContext-BOf-9P8n.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CrBn2s3P.js → GenericCardRenderer-CBBnIDaW.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CufnJCrr.js → Git-BKimGd5P.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DKS1J5P5.js → Governance-DoXCXppu.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CxB7n-T4.js → Inference-DzOhGhOE.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-uaO_yOid.js → KnowledgeGraph-DawgmU58.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DnR-CXn3.js → Logs-Co3EJL2Y.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DdkDiGUd.js → MarkdownRenderer-VUfiDRZN.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-ePcCe7m1.js → Marketplace-BqpMHnMW.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CAR6PCH2.js → McpTools-C7ZSokcR.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-Bl_H1aqs.js → Memory-DuJrpeDx.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BjMD_o0K.js → MobileBridge-CaM744NU.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-Bd78jDwm.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-DxN4oBCy.js → Mtc-5oUB7lPh.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-CZg_CONT.js → MtcAudit-D9DNF6DB.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-D3nrsJvN.js → Multisig-CfMpFQSr.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DfffM-fH.js → NLProgramming-CuhPZQ7q.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-QE3VQe9j.js → Notes-NtSeMoyM.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-CYGciq5y.js → NotificationSettings-CB4e7V83.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Cx5IwZLp.js → OrderTableRenderer-Bu8C6Qlj.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-C8RQZUBu.js → Organization-K_0bjm7y.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Dg6cVFza.js → Overflow-D2vwxiPv.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DjRkujm6.js → P2P-WQMHBu8q.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CMpEtOjE.js → PdhVaultBrowser-CTZVBMZZ.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-jOoYkoQU.js → Permissions-DcLy9Nfp.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CfArs3Fo.js → PersonalDataHub-zc-cm-02.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-DBaHyX1b.js → Pipeline-CCnI8peM.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Wv2VD4nl.js → Privacy-DO1Xor8L.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CiJPc1_A.js → ProjectInit-CZqC-jyt.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Dw1cWjEG.js → ProjectSettings-DqJtyavX.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-CWtB5sqm.js → Projects-Dx14NAO3.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DSn6SDyz.js → Providers-DH13a6ro.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-ft3b2Qpr.js → QrScannerModal-C9bwzVfA.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-GE6AQSq7.js → QuickAsk-Cbt-oIPf.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DMSEq8uY.js → Recommend-BYIimGcY.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Uu-HSEai.js → RemoteSession-C8OWTG1H.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CIcpi3_V.js → Reputation-DpUGT_jD.js} +1 -1
- package/src/assets/web-panel/assets/{Row-UVMeD3Wm.js → Row-DZ5Izi2A.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CD4MNI1l.js → RssFeed-CAn94No1.js} +3 -3
- package/src/assets/web-panel/assets/{Search-AlxcFL5q.js → Search-BqNaxcgj.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Du5J0dDR.js → Security-Ck6vFTWn.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CGDVJAoN.js → Services-Y3RdvvDj.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CCQDNIXk.js → Skeleton-Cx9Iqcp7.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-4BRwqGQe.js → Skills-Oiqz7wLM.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CgG0JuJh.js → Sla-DaKJQADm.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-qgkTz2pO.js → SpeechSettings-BWoOpPW4.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DRTuKcuZ.js → SyncSettings-CgFle8GX.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-C1tQNvWx.js +1 -0
- package/src/assets/web-panel/assets/{Templates-d78d-BZI.js → Templates-CvvycaWi.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-XwKmfX8F.js → Tenant-D1FwaD12.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Wqr2Kcev.js → Terminal-oorFjObO.js} +2 -2
- package/src/assets/web-panel/assets/TimelineRenderer-BjMs48Sj.js +1 -0
- package/src/assets/web-panel/assets/{Tokens-DWRgtMpW.js → Tokens-BkRb95xG.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BCDWY1I7.js → Trigger-B94RYYAF.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CI47nsTZ.js → Trust-DnBVpOWt.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BxxUVNJf.js → UkeySign-DouHO6Up.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-K6atXnE3.js → VideoEditing-DDgRerWV.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DALnM69L.js → Wallet-CQN9Un7X.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DiDAUHrG.js → WebAuthn-DyHl2G3J.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CCYTnfUH.js → WorkflowEditor-BQlN77Ey.js} +1 -1
- package/src/assets/web-panel/assets/{chat-0oQNEtRw.js → chat-0jOqe7ZD.js} +1 -1
- package/src/assets/web-panel/assets/{colors-C1A1ekPG.js → colors-kp5TAaKx.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Bm5w8Q--.js → compact-item-DqF6Rml7.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-VzW0CVyb.js → createContext-lDyLBjy5.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-IfrMTwCK.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-B8u-fCyP.js → hasIn-CkiF91kH.js} +1 -1
- package/src/assets/web-panel/assets/{index-5dKHibv1.js → index-8Hxbv1SG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOrjt98B.js → index-B6V9l2P-.js} +1 -1
- package/src/assets/web-panel/assets/{index-CflXFLrN.js → index-BAtpuJQ7.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dj0yOalO.js → index-BKFL4DfP.js} +1 -1
- package/src/assets/web-panel/assets/{index-NzJz9-49.js → index-BPcjLn2w.js} +1 -1
- package/src/assets/web-panel/assets/{index-BicVNOi5.js → index-BPwtIqRo.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4_ABRMS.js → index-BRu6Pe98.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5LAh2pw.js → index-BSAeSPQe.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtMiuJK-.js → index-BUqE17wu.js} +1 -1
- package/src/assets/web-panel/assets/{index-k5exH2qO.js → index-BnU8hi3c.js} +1 -1
- package/src/assets/web-panel/assets/{index-KCmGGWAT.js → index-Bq2s5obn.js} +5 -5
- package/src/assets/web-panel/assets/{index-DBE3blUA.js → index-Bu14YcwM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIYC0OR5.js → index-BvFFY-2V.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dxx4WU96.js → index-ByggSxTQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEQNF8dD.js → index-C-CS_-jC.js} +1 -1
- package/src/assets/web-panel/assets/index-C7nsIbMa.js +1 -0
- package/src/assets/web-panel/assets/{index-lE4Q1Goz.js → index-CI-H0ljO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dy85cPQr.js → index-CLchRTsS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXEOVGeZ.js → index-CNPCAYHk.js} +1 -1
- package/src/assets/web-panel/assets/index-DFXFLdKN.js +1 -0
- package/src/assets/web-panel/assets/{index-BVcRk2yF.js → index-DHVNtkrR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CX4GAKgB.js → index-DHnFhMOL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BdhglNFh.js → index-DK47iA2d.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7q2TsaJ.js → index-DPHmcQWh.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcLZlcMA.js → index-DQGk8bV8.js} +1 -1
- package/src/assets/web-panel/assets/{index-SmhdgbaR.js → index-DSDM-VNz.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0m5PpMV.js → index-DTA_B9gU.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV_Pfu-b.js → index-DX40v3aL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcmUqRug.js → index-DZU13W4o.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzTQseVr.js → index-DduPk1RS.js} +1 -1
- package/src/assets/web-panel/assets/{index-DW-aGHSh.js → index-DgGNW2ep.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbFi-5C6.js → index-DnI__Fwu.js} +1 -1
- package/src/assets/web-panel/assets/{index-jMjP2tFO.js → index-DrVVi5jX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjMG0Vw9.js → index-DzU_SfdF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpZdwtCH.js → index-INxX1TMz.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfKBL8PY.js → index-X1l5-ive.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bg-LBQME.js → index-aHKeys8c.js} +1 -1
- package/src/assets/web-panel/assets/{index-CicT_guC.js → index-kenTha3h.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6ou7QIj.js → index-mkwJZMBT.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DbZ3dIR7.js → initDefaultProps-CYYQ0SI1.js} +1 -1
- package/src/assets/web-panel/assets/{motion-ATVJwqzT.js → motion--Tyo36te.js} +1 -1
- package/src/assets/web-panel/assets/{move-Bxj0ZywY.js → move-D2BjgQv7.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-0j7iOj1h.js → mtc-parser-dyIu5RU_.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DsAzx9jL.js → omit-CDEAhC5H.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CIyAoQIB.js → pickAttrs-DLKDlIQs.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-KU51oLwW.js → placementArrow-BveC8fe2.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CCmx1m3K.js → responsiveObserve-51urgYrW.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CoxSb_UP.js → slide-CCHbhZg-.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-B-3-3uWm.js → statusUtils-W4mtUXRP.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BT1IFFpw.js → styleChecker-D4Drrz2a.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CEKYnxGt.js → useFlexGapSupport-BBCd4kCM.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-B_UyzZK-.js → useFs-4Khxvw5Y.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-B7fGu-O1.js → usePersonalDataHub-7c72tleZ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BLOmOgkK.js → vnode-DzZ7Y0LN.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-8yzckhp-.js → zoom-C5jhaET3.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/evolution-deployment.js +95 -0
- package/src/commands/evolution.js +2 -0
- package/src/data/changelog.json +26 -0
- package/src/gateways/ws/evolution-deployment-topic-handlers.js +53 -0
- package/src/lib/evolution/evolution-deployment-config.js +81 -0
- package/src/lib/evolution/evolution-deployment-loader.js +62 -13
- package/src/lib/evolution/evolution-deployment-profile.js +114 -0
- package/src/lib/pr-investigation-policy.js +42 -0
- package/src/lib/public-ide-capability-manifest.js +2 -0
- package/src/lib/read-file-loop-guard.js +36 -3
- package/src/lib/remote-read-loop-guard.js +65 -6
- package/src/lib/task-progress-tracker.js +97 -3
- package/src/lib/text-file-search.js +11 -0
- package/src/runtime/agent-core.js +130 -23
- package/src/runtime/agent-runtime.js +2 -0
- package/src/assets/web-panel/assets/AppLayout-SnniLCL6.js +0 -9
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BQ7pUK2c.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects--CKxaWJC.js +0 -1
- package/src/assets/web-panel/assets/Tasks-BfOq9EqX.js +0 -1
- package/src/assets/web-panel/assets/TimelineRenderer-BjzPNKDr.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BuusI785.js +0 -1
- package/src/assets/web-panel/assets/index-BiH_a1Cv.js +0 -1
- package/src/assets/web-panel/assets/index-t3MTPSt6.js +0 -1
|
@@ -67,7 +67,7 @@ function urlTarget(value) {
|
|
|
67
67
|
}
|
|
68
68
|
if (url.hostname === "github.com") {
|
|
69
69
|
const pr =
|
|
70
|
-
/^\/([^/]+\/[^/]+)\/(?:pulls\/?|pull\/(\d+)(?:\/(?:files|commits))?\/?|pull\/(\d+)\.(?:diff|patch))$/.exec(
|
|
70
|
+
/^\/([^/]+\/[^/]+)\/(?:pulls\/?|pull\/(\d+)(?:\/(?:files|commits|checks))?\/?|pull\/(\d+)\.(?:diff|patch))$/.exec(
|
|
71
71
|
url.pathname,
|
|
72
72
|
);
|
|
73
73
|
if (pr) return pullRequestTarget(pr[1], pr[2] || pr[3]);
|
|
@@ -221,6 +221,19 @@ export class RemoteReadLoopGuard {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
record(tool, result, args = {}) {
|
|
224
|
+
if (result?.code === "CC_TOOL_RECOVERY_PAUSED") {
|
|
225
|
+
// A provider can ignore omitted tool definitions. Count that attempt
|
|
226
|
+
// without replacing the actual failure/evidence with our own denial.
|
|
227
|
+
const key = remoteReadTarget(tool, args)?.key || this.activeKey;
|
|
228
|
+
const entry = this.targets.get(key);
|
|
229
|
+
if (entry?.tool === tool && entry.repeats >= RECOVERY_AFTER) {
|
|
230
|
+
entry.repeats++;
|
|
231
|
+
entry.recoveryOffered = true;
|
|
232
|
+
this.activeKey = key;
|
|
233
|
+
this.revision++;
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
224
237
|
const failed = failedResult(result);
|
|
225
238
|
const policy = result?.shellCommandPolicy;
|
|
226
239
|
const gitRepositoryKey = `git-repository:${createHash("sha256")
|
|
@@ -302,15 +315,37 @@ export class RemoteReadLoopGuard {
|
|
|
302
315
|
highWater: result.offset + content.length,
|
|
303
316
|
}
|
|
304
317
|
: null;
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
318
|
+
// Keep coverage per snapshot: rotating PR details/files/checks or changing
|
|
319
|
+
// an already-read window's length does not produce new evidence. Intervals
|
|
320
|
+
// (not just a high-water mark) still allow reading previously skipped gaps.
|
|
321
|
+
const snapshots = previous?.snapshots || new Map();
|
|
322
|
+
const ranges = page ? snapshots.get(page.snapshotId) : null;
|
|
323
|
+
const covered =
|
|
324
|
+
page &&
|
|
325
|
+
ranges?.some(
|
|
326
|
+
([start, end]) => start <= page.offset && end >= page.highWater,
|
|
327
|
+
);
|
|
328
|
+
const advanced = page && ranges && !covered;
|
|
329
|
+
if (page) {
|
|
330
|
+
const merged = [];
|
|
331
|
+
for (const range of [
|
|
332
|
+
...(ranges || []),
|
|
333
|
+
[page.offset, page.highWater],
|
|
334
|
+
].sort((a, b) => a[0] - b[0])) {
|
|
335
|
+
const last = merged.at(-1);
|
|
336
|
+
if (last && last[1] >= range[0]) last[1] = Math.max(last[1], range[1]);
|
|
337
|
+
else merged.push([...range]);
|
|
338
|
+
}
|
|
339
|
+
snapshots.delete(page.snapshotId);
|
|
340
|
+
snapshots.set(page.snapshotId, merged.slice(-32));
|
|
341
|
+
while (snapshots.size > 16)
|
|
342
|
+
snapshots.delete(snapshots.keys().next().value);
|
|
343
|
+
}
|
|
309
344
|
// Changed error wording or switching web/gh must not buy another retry
|
|
310
345
|
// budget for the same failed target. Successful fresh evidence resets it.
|
|
311
346
|
const repeats = failed
|
|
312
347
|
? (previous?.repeats || 0) + 1
|
|
313
|
-
: target.github && digests.has(digest) && !advanced
|
|
348
|
+
: target.github && (covered || (digests.has(digest) && !advanced))
|
|
314
349
|
? previous.repeats + 1
|
|
315
350
|
: 0;
|
|
316
351
|
if (!failed) {
|
|
@@ -325,6 +360,7 @@ export class RemoteReadLoopGuard {
|
|
|
325
360
|
repeats,
|
|
326
361
|
digest,
|
|
327
362
|
digests,
|
|
363
|
+
snapshots,
|
|
328
364
|
page,
|
|
329
365
|
recoveryOffered: repeats > 0 && previous?.recoveryOffered === true,
|
|
330
366
|
evidence: excerpt(
|
|
@@ -393,11 +429,34 @@ export class RemoteReadLoopGuard {
|
|
|
393
429
|
this.offeredRevision = this.revision;
|
|
394
430
|
const entry = this.targets.get(this.activeKey);
|
|
395
431
|
entry.recoveryOffered = true;
|
|
432
|
+
// Keep the shell available for local reproduction and validation. Only
|
|
433
|
+
// repeated reads of the stalled remote target are narrowed below.
|
|
434
|
+
if (entry.tool === "run_shell" && entry.github) return [];
|
|
396
435
|
return [entry.tool];
|
|
397
436
|
}
|
|
398
437
|
|
|
438
|
+
shouldPause(tool, args = {}) {
|
|
439
|
+
const target = remoteReadTarget(tool, args);
|
|
440
|
+
const entry = target && this.targets.get(target.key);
|
|
441
|
+
return !!(
|
|
442
|
+
entry?.github &&
|
|
443
|
+
entry.recoveryOffered &&
|
|
444
|
+
entry.repeats >= RECOVERY_AFTER
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
|
|
399
448
|
get workflowHint() {
|
|
400
449
|
const active = this.targets.get(this.activeKey);
|
|
450
|
+
if (active?.github && !active.pullRequest) {
|
|
451
|
+
return (
|
|
452
|
+
"GitHub Actions investigation: use the retained run/job facts to identify the first failed step and its relevant local implementation. " +
|
|
453
|
+
"An aggregate or incomplete-matrix gate can be a downstream symptom; inspect the dependency jobs' conclusions before assuming that the gate itself is wrong. " +
|
|
454
|
+
"When a job is cancelled or logs are unavailable, record that fact and the command error; do not cycle through the same web page and log downloads. " +
|
|
455
|
+
"Use one focused run/job metadata query to resolve the missing status or cancellation reason, then inspect the relevant workflow and make the justified, authorized fix with validation. " +
|
|
456
|
+
"If available evidence cannot establish a fix, report the specific missing evidence and what was verified. Do not disable a release or safety gate just to make CI pass. " +
|
|
457
|
+
"For a research/review request, synthesize the findings without unsolicited edits; for monitoring, use status queries instead of repeated logs."
|
|
458
|
+
);
|
|
459
|
+
}
|
|
401
460
|
if (
|
|
402
461
|
!active?.pullRequest &&
|
|
403
462
|
!(
|
|
@@ -24,6 +24,8 @@ export const TASK_RECOVERY_TOOLS = [
|
|
|
24
24
|
"todo_write",
|
|
25
25
|
"spawn_sub_agent",
|
|
26
26
|
"tool_search",
|
|
27
|
+
"web_fetch",
|
|
28
|
+
"web_search",
|
|
27
29
|
];
|
|
28
30
|
|
|
29
31
|
// The runtime admits at most 32 spawned agents plus the root. Keep bounded
|
|
@@ -34,6 +36,27 @@ function boundedText(value, limit) {
|
|
|
34
36
|
return typeof value === "string" ? value.slice(0, limit) : "";
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
// Status queries remain executable (including intentional monitoring), but
|
|
40
|
+
// fetching a different status page is not an implementation or verification.
|
|
41
|
+
// Classification affects progress guidance only, never command authorization.
|
|
42
|
+
function isRemoteInspectionCommand(command) {
|
|
43
|
+
if (typeof command !== "string") return false;
|
|
44
|
+
if (
|
|
45
|
+
/(?:^|[\s;&|])gh(?:\.exe)?\s+(?:run\s+(?:view|list|watch)|pr\s+(?:view|list|diff|checks)|auth\s+status)\b/i.test(
|
|
46
|
+
command,
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
return true;
|
|
50
|
+
return (
|
|
51
|
+
/(?:^|[\s;&|])gh(?:\.exe)?\s+api\s/i.test(command) &&
|
|
52
|
+
/(?:https:\/\/api\.github\.com\/)?\/?repos\/[\w.-]+\/[\w.-]+\/(?:actions|pulls|compare|releases|commits|check-runs|check-suites)\b/i.test(
|
|
53
|
+
command,
|
|
54
|
+
) &&
|
|
55
|
+
!/(?:^|\s)(?:--method|-X)(?:=|\s*)["']?(?!GET\b)\w+/i.test(command) &&
|
|
56
|
+
!/(?:^|\s)(?:(?:--field|--raw-field|--input)(?:=|\s)|-[fF])/.test(command)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
37
60
|
function remember(map, key, value, limit) {
|
|
38
61
|
map.delete(key);
|
|
39
62
|
map.set(key, value);
|
|
@@ -44,7 +67,7 @@ function remember(map, key, value, limit) {
|
|
|
44
67
|
* Run-tree exploration accounting, separate from file coverage and permissions.
|
|
45
68
|
* This object is shared by parent/child loops, not serialized into model input.
|
|
46
69
|
* New file pages advance coverage but do not reset the exploration counter.
|
|
47
|
-
* Interventions are advisory /
|
|
70
|
+
* Interventions are advisory / progress-scoped tool narrowing, never completion
|
|
48
71
|
* verdicts or a hard deadline for legitimate research and monitoring tasks.
|
|
49
72
|
*/
|
|
50
73
|
export class TaskProgressTracker {
|
|
@@ -57,6 +80,8 @@ export class TaskProgressTracker {
|
|
|
57
80
|
this.plans = new Map();
|
|
58
81
|
this.childFindings = new Map();
|
|
59
82
|
this.lastActions = [];
|
|
83
|
+
this.remoteInspections = [];
|
|
84
|
+
this.localFindings = [];
|
|
60
85
|
}
|
|
61
86
|
|
|
62
87
|
retainChildResult(id, result, owner = "root") {
|
|
@@ -96,6 +121,32 @@ export class TaskProgressTracker {
|
|
|
96
121
|
typeof args.old_string === "string" &&
|
|
97
122
|
args.old_string === args.new_string);
|
|
98
123
|
|
|
124
|
+
if (!failed && (tool === "search_files" || tool === "read_file")) {
|
|
125
|
+
const evidence = result.content ?? result.matches ?? result.output;
|
|
126
|
+
const excerpt = boundedText(
|
|
127
|
+
typeof evidence === "string" ? evidence : JSON.stringify(evidence),
|
|
128
|
+
1000,
|
|
129
|
+
);
|
|
130
|
+
if (excerpt) {
|
|
131
|
+
const entry = {
|
|
132
|
+
owner,
|
|
133
|
+
tool,
|
|
134
|
+
path: boundedText(args.path || result.path, 320),
|
|
135
|
+
query: boundedText(args.pattern, 200),
|
|
136
|
+
range: result.range,
|
|
137
|
+
excerpt,
|
|
138
|
+
};
|
|
139
|
+
const owned = [
|
|
140
|
+
...this.localFindings.filter((item) => item.owner === owner),
|
|
141
|
+
entry,
|
|
142
|
+
].slice(-4);
|
|
143
|
+
this.localFindings = [
|
|
144
|
+
...this.localFindings.filter((item) => item.owner !== owner),
|
|
145
|
+
...owned,
|
|
146
|
+
].slice(-MAX_CHECKPOINT_OWNERS * 4);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
99
150
|
if (tool === "spawn_sub_agent")
|
|
100
151
|
this.retainChildResult(result?.subAgentId, result, owner);
|
|
101
152
|
if (tool === "todo_write" && !failed && Array.isArray(args.todos)) {
|
|
@@ -120,8 +171,29 @@ export class TaskProgressTracker {
|
|
|
120
171
|
// fingerprints affect guidance only: every authorized command still runs.
|
|
121
172
|
const output = boundedText(result?.output ?? result?.stdout, 30000);
|
|
122
173
|
const digest = createHash("sha256").update(output).digest("hex");
|
|
174
|
+
const remoteInspection =
|
|
175
|
+
tool === "run_shell" && isRemoteInspectionCommand(args.command);
|
|
176
|
+
if (remoteInspection) {
|
|
177
|
+
// A status observation is still useful evidence after compaction. Keep
|
|
178
|
+
// it apart from actions so remembering it never resets recovery.
|
|
179
|
+
const owned = [
|
|
180
|
+
...this.remoteInspections.filter((entry) => entry.owner === owner),
|
|
181
|
+
{
|
|
182
|
+
owner,
|
|
183
|
+
command: boundedText(args.command, 320),
|
|
184
|
+
output: boundedText(output, 1200),
|
|
185
|
+
error: boundedText(result?.error || result?.stderr, 400),
|
|
186
|
+
failed,
|
|
187
|
+
},
|
|
188
|
+
].slice(-4);
|
|
189
|
+
this.remoteInspections = [
|
|
190
|
+
...this.remoteInspections.filter((entry) => entry.owner !== owner),
|
|
191
|
+
...owned,
|
|
192
|
+
].slice(-MAX_CHECKPOINT_OWNERS * 4);
|
|
193
|
+
}
|
|
123
194
|
exploration =
|
|
124
195
|
!!remoteReadTarget(tool, args) ||
|
|
196
|
+
remoteInspection ||
|
|
125
197
|
output.length >= 8000 ||
|
|
126
198
|
this.commandOutputs.has(digest);
|
|
127
199
|
if (!failed) remember(this.commandOutputs, digest, true, 64);
|
|
@@ -179,11 +251,14 @@ export class TaskProgressTracker {
|
|
|
179
251
|
guidance:
|
|
180
252
|
message +
|
|
181
253
|
" For an implementation task, make the smallest justified, authorized change and validate it. " +
|
|
254
|
+
"For a bug fix, state the observed failure, your leading root-cause hypothesis and the smallest test that can disprove it. Run that focused reproduction or diagnostic next; use its actual output to choose the next step. Do not keep reading adjacent files without naming the specific missing fact. A timeout alone does not establish that increasing the timeout is the fix. " +
|
|
182
255
|
"For research/review, synthesize evidence-backed findings; do not write files merely to clear this warning. " +
|
|
183
256
|
"If evidence is insufficient, name the exact missing fact and use a focused search or bounded computation. " +
|
|
184
257
|
"Do not restart general investigation, rewrite the plan, or delegate the same research. " +
|
|
185
258
|
"A child exhausting its budget is not task completion. Preserve useful partial findings and continue the original task. " +
|
|
186
|
-
"
|
|
259
|
+
"During recovery, broad discovery stays paused until an actionable tool outcome; a focused search, another status query or a failed command does not end recovery. " +
|
|
260
|
+
"Use search_files for an exact missing local fact or run a bounded computation/verification, then act on the result. " +
|
|
261
|
+
"Never claim completion without satisfying the user's request.",
|
|
187
262
|
};
|
|
188
263
|
}
|
|
189
264
|
|
|
@@ -191,14 +266,27 @@ export class TaskProgressTracker {
|
|
|
191
266
|
if (
|
|
192
267
|
!this.plans.size &&
|
|
193
268
|
!this.childFindings.size &&
|
|
194
|
-
!this.lastActions.length
|
|
269
|
+
!this.lastActions.length &&
|
|
270
|
+
!this.remoteInspections.length &&
|
|
271
|
+
!this.localFindings.length
|
|
195
272
|
)
|
|
196
273
|
return null;
|
|
197
274
|
const checkpoint = {
|
|
198
275
|
bounded: true,
|
|
276
|
+
recentLocalFindings: this.localFindings
|
|
277
|
+
.filter((entry) => entry.owner === owner)
|
|
278
|
+
.map(({ owner: _owner, ...entry }) => entry),
|
|
199
279
|
recentToolOutcomes: this.lastActions
|
|
200
280
|
.filter((entry) => entry.owner === owner)
|
|
201
281
|
.map(({ tool, path, output }) => ({ tool, path, output })),
|
|
282
|
+
recentRemoteInspections: this.remoteInspections
|
|
283
|
+
.filter((entry) => entry.owner === owner)
|
|
284
|
+
.map(({ command, output, error, failed }) => ({
|
|
285
|
+
command,
|
|
286
|
+
output,
|
|
287
|
+
error,
|
|
288
|
+
failed,
|
|
289
|
+
})),
|
|
202
290
|
reportedPlans: this.plans.has(owner)
|
|
203
291
|
? [{ todos: this.plans.get(owner) }]
|
|
204
292
|
: [],
|
|
@@ -209,7 +297,9 @@ export class TaskProgressTracker {
|
|
|
209
297
|
// Only counters are inherited across isolated child contracts. Source
|
|
210
298
|
// material belongs to the loop that observed it or received the child result.
|
|
211
299
|
if (
|
|
300
|
+
!checkpoint.recentLocalFindings.length &&
|
|
212
301
|
!checkpoint.recentToolOutcomes.length &&
|
|
302
|
+
!checkpoint.recentRemoteInspections.length &&
|
|
213
303
|
!checkpoint.reportedPlans.length &&
|
|
214
304
|
!checkpoint.childFindings.length
|
|
215
305
|
)
|
|
@@ -218,6 +308,10 @@ export class TaskProgressTracker {
|
|
|
218
308
|
if (checkpoint.reportedPlans.length > 1) checkpoint.reportedPlans.pop();
|
|
219
309
|
else if (checkpoint.childFindings.length)
|
|
220
310
|
checkpoint.childFindings.shift();
|
|
311
|
+
else if (checkpoint.recentLocalFindings.length)
|
|
312
|
+
checkpoint.recentLocalFindings.shift();
|
|
313
|
+
else if (checkpoint.recentRemoteInspections.length)
|
|
314
|
+
checkpoint.recentRemoteInspections.shift();
|
|
221
315
|
else if (checkpoint.recentToolOutcomes.length)
|
|
222
316
|
checkpoint.recentToolOutcomes.shift();
|
|
223
317
|
else checkpoint.reportedPlans.pop();
|
|
@@ -54,6 +54,17 @@ export function searchTextFile(file, options = {}) {
|
|
|
54
54
|
const finish = (result) => {
|
|
55
55
|
if (settled) return;
|
|
56
56
|
settled = true;
|
|
57
|
+
if (
|
|
58
|
+
!result.error &&
|
|
59
|
+
!regex &&
|
|
60
|
+
result.matches?.length === 0 &&
|
|
61
|
+
/[|^$]|\\[bdsw]|\.\*/i.test(pattern)
|
|
62
|
+
) {
|
|
63
|
+
result = {
|
|
64
|
+
...result,
|
|
65
|
+
hint: "No literal matches. This pattern contains regex syntax, but this search used literal matching. If alternation or regex was intended, set regex: true; otherwise search one exact symbol. Do not infer that the symbols are absent from this result.",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
57
68
|
clearTimeout(timer);
|
|
58
69
|
Promise.resolve(worker?.terminate())
|
|
59
70
|
.catch(() => {})
|
|
@@ -22,6 +22,12 @@ import {
|
|
|
22
22
|
} from "../lib/read-file-page.js";
|
|
23
23
|
import { ReadFileLoopGuard } from "../lib/read-file-loop-guard.js";
|
|
24
24
|
import { RemoteReadLoopGuard } from "../lib/remote-read-loop-guard.js";
|
|
25
|
+
import {
|
|
26
|
+
isPrActionRequest,
|
|
27
|
+
PR_ACTION_GUIDANCE,
|
|
28
|
+
PR_INVESTIGATION_LIMIT,
|
|
29
|
+
PR_INVESTIGATION_EXIT_GUIDANCE,
|
|
30
|
+
} from "../lib/pr-investigation-policy.js";
|
|
25
31
|
import {
|
|
26
32
|
findExplicitPrCloseIntent,
|
|
27
33
|
prCloseActionDirective,
|
|
@@ -1098,6 +1104,8 @@ Key behaviors:
|
|
|
1098
1104
|
- When asked to create something, use write_file to create it
|
|
1099
1105
|
- When asked to remove or rename a file, use delete_file or move_file so the filesystem intent is explicit and reviewable
|
|
1100
1106
|
- When asked to run/test something, use run_shell to execute it
|
|
1107
|
+
- For a bug fix, retain the failing test/file and exact error, inspect the relevant code, then state a root-cause hypothesis and run the smallest reproduction or diagnostic that can disprove it. Base the next step on actual output. Do not repeatedly read adjacent files without identifying a specific missing fact. Validate the fix with the failing case and report what remains unverified.
|
|
1108
|
+
- For CI log retrieval, inspect command stderr before retrying. Match syntax to the actual shell: Windows PowerShell 5 does not support &&, cmd treats single quotes literally, and head is not a Windows builtin. Prefer a plain gh metadata/log command without jq or pipelines first, then inspect the saved output. Never switch shells to bypass a policy denial.
|
|
1101
1109
|
- For long-running commands (builds, full test suites, dev servers) set run_shell { run_in_background: true } to get a task_id back immediately, then poll output and completion with check_shell { task_id }. Kill a backgrounded server with check_shell { task_id, kill: true } when finished
|
|
1102
1110
|
- When asked about git status, diff, log, or other repository operations, use the git tool instead of run_shell
|
|
1103
1111
|
- When asked about files or code, use search_files to locate relevant sections, then read_file with offset/limit. Follow nextRead for large files. Reuse unchanged content already in context instead of repeatedly reading the same page; re-read when the file changes or the earlier content is no longer available.
|
|
@@ -13936,6 +13944,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13936
13944
|
let emptyThinkingReprompted = false;
|
|
13937
13945
|
const readFileLoopGuard = new ReadFileLoopGuard();
|
|
13938
13946
|
const remoteReadLoopGuard = new RemoteReadLoopGuard();
|
|
13947
|
+
const prActionTask = isPrActionRequest(messages);
|
|
13939
13948
|
// Keep an explicit user-requested PR close action alive even if the
|
|
13940
13949
|
// conversation is compacted down to tool evidence. It is guidance only;
|
|
13941
13950
|
// the ordinary execution approval remains mandatory for every close.
|
|
@@ -14550,8 +14559,15 @@ export async function* agentLoop(messages, options) {
|
|
|
14550
14559
|
const newProgressIntervention =
|
|
14551
14560
|
progressIntervention &&
|
|
14552
14561
|
progressIntervention.key !== lastTaskProgressIntervention;
|
|
14553
|
-
|
|
14554
|
-
|
|
14562
|
+
// Warnings are deduplicated, recovery is not. A search or failed command
|
|
14563
|
+
// must not restore broad discovery on the very next model request.
|
|
14564
|
+
const taskRecoveryTurn = progressIntervention?.recovery === true;
|
|
14565
|
+
const prInvestigationExhausted =
|
|
14566
|
+
prActionTask &&
|
|
14567
|
+
taskProgressTracker.explorationCalls >= PR_INVESTIGATION_LIMIT;
|
|
14568
|
+
const taskRecoveryTools = TASK_RECOVERY_TOOLS.filter(
|
|
14569
|
+
(tool) => tool !== "read_file" || !readFileLoopGuard.hasRecoveryReads,
|
|
14570
|
+
);
|
|
14555
14571
|
if (newProgressIntervention) {
|
|
14556
14572
|
lastTaskProgressIntervention = progressIntervention.key;
|
|
14557
14573
|
// Reuse the existing warning event so CLI, REPL and IDE clients all show
|
|
@@ -14561,24 +14577,31 @@ export async function* agentLoop(messages, options) {
|
|
|
14561
14577
|
message:
|
|
14562
14578
|
progressIntervention.message +
|
|
14563
14579
|
(taskRecoveryTurn
|
|
14564
|
-
? " Broad reading and new delegation
|
|
14580
|
+
? " Broad reading, web discovery and new delegation remain paused until an actionable tool outcome."
|
|
14565
14581
|
: ""),
|
|
14566
14582
|
};
|
|
14567
14583
|
}
|
|
14568
|
-
const
|
|
14569
|
-
readRecoveryTurn
|
|
14570
|
-
|
|
14571
|
-
|
|
14572
|
-
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
|
|
14576
|
-
|
|
14577
|
-
|
|
14578
|
-
|
|
14579
|
-
|
|
14580
|
-
|
|
14581
|
-
|
|
14584
|
+
const pausedTools = new Set([
|
|
14585
|
+
...(readRecoveryTurn ? ["read_file"] : []),
|
|
14586
|
+
...(taskRecoveryTurn ? taskRecoveryTools : []),
|
|
14587
|
+
...remoteRecoveryTools,
|
|
14588
|
+
...(prInvestigationExhausted
|
|
14589
|
+
? getEffectiveToolDefinitions(effectiveToolOptions).map(
|
|
14590
|
+
(tool) => tool.function.name,
|
|
14591
|
+
)
|
|
14592
|
+
: []),
|
|
14593
|
+
]);
|
|
14594
|
+
const iterationToolOptions = pausedTools.size
|
|
14595
|
+
? {
|
|
14596
|
+
...effectiveToolOptions,
|
|
14597
|
+
disabledTools: [
|
|
14598
|
+
...new Set([
|
|
14599
|
+
...(effectiveToolOptions.disabledTools || []),
|
|
14600
|
+
...pausedTools,
|
|
14601
|
+
]),
|
|
14602
|
+
],
|
|
14603
|
+
}
|
|
14604
|
+
: effectiveToolOptions;
|
|
14582
14605
|
const readContext = [
|
|
14583
14606
|
readFileLoopGuard.findingsHint,
|
|
14584
14607
|
readFileLoopGuard.progressHint,
|
|
@@ -14628,7 +14651,20 @@ export async function* agentLoop(messages, options) {
|
|
|
14628
14651
|
}
|
|
14629
14652
|
}
|
|
14630
14653
|
const contextMemoryTrustedSystemIndexes = [];
|
|
14631
|
-
if (
|
|
14654
|
+
if (prActionTask && !prInvestigationExhausted) {
|
|
14655
|
+
callMessages = [
|
|
14656
|
+
...callMessages,
|
|
14657
|
+
{
|
|
14658
|
+
role: "system",
|
|
14659
|
+
content: PR_ACTION_GUIDANCE,
|
|
14660
|
+
},
|
|
14661
|
+
];
|
|
14662
|
+
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
14663
|
+
}
|
|
14664
|
+
if (
|
|
14665
|
+
!prInvestigationExhausted &&
|
|
14666
|
+
(remoteReadLoopGuard.recoveryHint || remoteReadLoopGuard.workflowHint)
|
|
14667
|
+
) {
|
|
14632
14668
|
callMessages = [
|
|
14633
14669
|
...callMessages,
|
|
14634
14670
|
{
|
|
@@ -14643,14 +14679,14 @@ export async function* agentLoop(messages, options) {
|
|
|
14643
14679
|
];
|
|
14644
14680
|
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
14645
14681
|
}
|
|
14646
|
-
if (prCloseDirective) {
|
|
14682
|
+
if (prCloseDirective && !prInvestigationExhausted) {
|
|
14647
14683
|
callMessages = [
|
|
14648
14684
|
...callMessages,
|
|
14649
14685
|
{ role: "system", content: prCloseDirective },
|
|
14650
14686
|
];
|
|
14651
14687
|
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
14652
14688
|
}
|
|
14653
|
-
if (progressIntervention) {
|
|
14689
|
+
if (progressIntervention && !prInvestigationExhausted) {
|
|
14654
14690
|
callMessages = [
|
|
14655
14691
|
...callMessages,
|
|
14656
14692
|
{
|
|
@@ -14658,13 +14694,13 @@ export async function* agentLoop(messages, options) {
|
|
|
14658
14694
|
content:
|
|
14659
14695
|
progressIntervention.guidance +
|
|
14660
14696
|
(taskRecoveryTurn
|
|
14661
|
-
?
|
|
14697
|
+
? ` Recovery remains active: ${taskRecoveryTools.join(", ")} are omitted until an actionable tool outcome. Only unfinished, already-started file scans may continue; new whole-file discovery is paused. Focused search, authorized changes and verification remain available.`
|
|
14662
14698
|
: ""),
|
|
14663
14699
|
},
|
|
14664
14700
|
];
|
|
14665
14701
|
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
14666
14702
|
}
|
|
14667
|
-
if (readRecoveryTurn) {
|
|
14703
|
+
if (readRecoveryTurn && !prInvestigationExhausted) {
|
|
14668
14704
|
callMessages = [
|
|
14669
14705
|
...callMessages,
|
|
14670
14706
|
{
|
|
@@ -14675,7 +14711,7 @@ export async function* agentLoop(messages, options) {
|
|
|
14675
14711
|
];
|
|
14676
14712
|
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
14677
14713
|
}
|
|
14678
|
-
if (readFileLoopGuard.recoveryHint) {
|
|
14714
|
+
if (readFileLoopGuard.recoveryHint && !prInvestigationExhausted) {
|
|
14679
14715
|
callMessages = [
|
|
14680
14716
|
...callMessages,
|
|
14681
14717
|
{ role: "system", content: readFileLoopGuard.recoveryHint },
|
|
@@ -14705,6 +14741,14 @@ export async function* agentLoop(messages, options) {
|
|
|
14705
14741
|
}
|
|
14706
14742
|
}
|
|
14707
14743
|
|
|
14744
|
+
if (prInvestigationExhausted) {
|
|
14745
|
+
callMessages = [
|
|
14746
|
+
...callMessages,
|
|
14747
|
+
{ role: "system", content: PR_INVESTIGATION_EXIT_GUIDANCE },
|
|
14748
|
+
];
|
|
14749
|
+
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
14750
|
+
}
|
|
14751
|
+
|
|
14708
14752
|
// Per-span unified ids (P2 observability): the run-level default attributes
|
|
14709
14753
|
// stamp session/agent/workflow ids on every span, but turn/prompt ids are
|
|
14710
14754
|
// per-iteration. A "turn" is one model iteration of the run; "prompt" is the
|
|
@@ -14930,6 +14974,38 @@ export async function* agentLoop(messages, options) {
|
|
|
14930
14974
|
}
|
|
14931
14975
|
|
|
14932
14976
|
const toolCalls = msg.tool_calls;
|
|
14977
|
+
if (prInvestigationExhausted) {
|
|
14978
|
+
// Exactly one synthesis request, even if the provider ignores the empty
|
|
14979
|
+
// tool set or a Stop hook normally asks to continue. Settle usage first;
|
|
14980
|
+
// do not insert unexecuted calls or turn a safety stop into completion.
|
|
14981
|
+
await _awaitBackgroundUsageSettlement(
|
|
14982
|
+
backgroundSubAgents,
|
|
14983
|
+
backgroundUsageFailureState,
|
|
14984
|
+
);
|
|
14985
|
+
yield* _drainSubAgentUsage(subAgentUsageSink);
|
|
14986
|
+
if (toolCalls?.length) {
|
|
14987
|
+
const error = new Error(
|
|
14988
|
+
"PR investigation stopped after repeated exploration without an actionable outcome; the task is incomplete. " +
|
|
14989
|
+
"The model requested more tools after the final synthesis instruction. Retained evidence: " +
|
|
14990
|
+
(
|
|
14991
|
+
taskProgressTracker.checkpointFor(runId) ||
|
|
14992
|
+
remoteReadLoopGuard.findingsHint ||
|
|
14993
|
+
"No verified findings."
|
|
14994
|
+
).slice(0, 2000),
|
|
14995
|
+
);
|
|
14996
|
+
error.code = "CC_AGENT_PR_INVESTIGATION_STALLED";
|
|
14997
|
+
throw error;
|
|
14998
|
+
}
|
|
14999
|
+
yield {
|
|
15000
|
+
type: "response-complete",
|
|
15001
|
+
content:
|
|
15002
|
+
"PR investigation stopped without completing the task.\n\n" +
|
|
15003
|
+
(msg.content ||
|
|
15004
|
+
"No actionable outcome was produced; use the retained findings to identify the missing prerequisite."),
|
|
15005
|
+
};
|
|
15006
|
+
yield { type: "run-ended", runId, reason: "pr-investigation-stalled" };
|
|
15007
|
+
return;
|
|
15008
|
+
}
|
|
14933
15009
|
if (Array.isArray(toolCalls) && toolCalls.length > 0) {
|
|
14934
15010
|
// Allocate missing provider IDs once, before transcript insertion and
|
|
14935
15011
|
// any evidence or execution boundary. This is only local correlation,
|
|
@@ -15131,12 +15207,15 @@ export async function* agentLoop(messages, options) {
|
|
|
15131
15207
|
// session (concurrent prompts would race), or `parallelReadOnlyTools: false`
|
|
15132
15208
|
// falls through to the strictly sequential loop below.
|
|
15133
15209
|
const parallelReads =
|
|
15210
|
+
!remoteReadLoopGuard.recoveryHint &&
|
|
15134
15211
|
options.parallelReadOnlyTools !== false &&
|
|
15212
|
+
!taskRecoveryTurn &&
|
|
15135
15213
|
toolCalls.length > 1 &&
|
|
15136
15214
|
!toolContext.permissionConfirm &&
|
|
15137
15215
|
toolCalls.every(
|
|
15138
15216
|
(c) =>
|
|
15139
15217
|
typeof c?.function?.name === "string" &&
|
|
15218
|
+
!pausedTools.has(c.function.name) &&
|
|
15140
15219
|
_CHECKPOINT_READ_ONLY.has(c.function.name),
|
|
15141
15220
|
);
|
|
15142
15221
|
if (parallelReads) {
|
|
@@ -15363,9 +15442,37 @@ export async function* agentLoop(messages, options) {
|
|
|
15363
15442
|
// hook, or observationally stronger `tool-executing` event. The same
|
|
15364
15443
|
// preflight runs again inside executeTool to prevent call-site drift.
|
|
15365
15444
|
const earlyAuthorityDenial =
|
|
15445
|
+
(pausedTools.has(toolName) ||
|
|
15446
|
+
remoteReadLoopGuard.shouldPause(toolName, toolArgs) ||
|
|
15447
|
+
(taskRecoveryTurn &&
|
|
15448
|
+
toolName === "read_file" &&
|
|
15449
|
+
!(
|
|
15450
|
+
typeof toolArgs?.path === "string" &&
|
|
15451
|
+
readFileLoopGuard.canContinue(
|
|
15452
|
+
path.resolve(toolContext.cwd || process.cwd(), toolArgs.path),
|
|
15453
|
+
toolArgs,
|
|
15454
|
+
)
|
|
15455
|
+
))
|
|
15456
|
+
? {
|
|
15457
|
+
success: false,
|
|
15458
|
+
code: "CC_TOOL_RECOVERY_PAUSED",
|
|
15459
|
+
error: `${toolName} is paused for loop recovery and was not executed. Use retained findings for an authorized action or report the specific blocker; do not repeat or disguise this call.`,
|
|
15460
|
+
}
|
|
15461
|
+
: null) ||
|
|
15366
15462
|
explicitPrCloseActionGuard.admission(toolName, toolArgs) ||
|
|
15367
15463
|
preflightToolExecutionAuthority(toolName, toolArgs, toolContext);
|
|
15368
15464
|
if (earlyAuthorityDenial) {
|
|
15465
|
+
remoteReadLoopGuard.record(toolName, earlyAuthorityDenial, toolArgs);
|
|
15466
|
+
readFileLoopGuard.record(
|
|
15467
|
+
toolName,
|
|
15468
|
+
earlyAuthorityDenial,
|
|
15469
|
+
taskProgressTracker.record(
|
|
15470
|
+
toolName,
|
|
15471
|
+
earlyAuthorityDenial,
|
|
15472
|
+
toolArgs,
|
|
15473
|
+
runId,
|
|
15474
|
+
),
|
|
15475
|
+
);
|
|
15369
15476
|
const resultStr = capToolResultString(
|
|
15370
15477
|
safeStringifyToolResult(earlyAuthorityDenial),
|
|
15371
15478
|
);
|
|
@@ -17,6 +17,7 @@ import { ChainlessChainWSServer } from "../gateways/ws/ws-server.js";
|
|
|
17
17
|
import { WSSessionManager } from "../gateways/ws/ws-session-gateway.js";
|
|
18
18
|
import { attachTopicHandlers } from "../gateways/ws/topic-handler-attachment.js";
|
|
19
19
|
import { createMcpTopicHandlers } from "../gateways/ws/mcp-topic-handlers.js";
|
|
20
|
+
import { createEvolutionDeploymentTopicHandlers } from "../gateways/ws/evolution-deployment-topic-handlers.js";
|
|
20
21
|
import { PtyManager } from "../gateways/terminal/PtyManager.js";
|
|
21
22
|
import { createTerminalHandlers } from "../gateways/terminal/terminal-handlers.js";
|
|
22
23
|
import { createWebUIServer } from "../gateways/ui/web-ui-server.js";
|
|
@@ -807,6 +808,7 @@ export class AgentRuntime {
|
|
|
807
808
|
configStore: mcpConfigStore,
|
|
808
809
|
cwd: workspacePolicyCwd,
|
|
809
810
|
}),
|
|
811
|
+
...createEvolutionDeploymentTopicHandlers(),
|
|
810
812
|
},
|
|
811
813
|
});
|
|
812
814
|
wsBroadcastRef.current = attached.broadcast;
|