chainlesschain 0.162.155 → 0.162.157
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 +1 -1
- package/package.json +2 -2
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-Cth_zZeA.js → AIOps-CfMP2Oud.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-zfwA3Oxn.js → ActionButton-Zu0N8BQL.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-FeKc4aU2.js → Analytics-DZTwj5T_.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-CVFJh47v.js +9 -0
- package/src/assets/web-panel/assets/Artifacts-BbN5V7au.js +1 -0
- package/src/assets/web-panel/assets/Artifacts-CRkepl4t.css +1 -0
- package/src/assets/web-panel/assets/{Audit-C2gRq5Qi.js → Audit-BMfiLj7T.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-TeTIFiW-.js → BackgroundAgents-BslPCdGF.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CLJk3k6i.js → Backup-CQ_fMC1r.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-5ms537NY.js → BaseInput-CsFsARiC.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-4Nr5U9PJ.js → Chat-CwfBobco.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-K6Nf3xeN.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-B2Bca5ev.js → Checkbox-DkSyjjPp.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-D6Uysdbv.js → Codegen-B7Fx3zZ6.js} +1 -1
- package/src/assets/web-panel/assets/{Col-B3XQ8xc7.js → Col-Dzfqn8Ep.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CqwKtoPz.js → Community-DhHPdzMM.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BZZINTus.js → Compact-Ct18_8y7.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dr3BXkWA.js → Compliance-CY64IqBi.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-rx_x9Wqc.js → Cowork-BYSmWlUl.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BpZr7rHc.js → Cron-_4xtP3Ug.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CeV5EYVg.js → Crosschain-B4qY-Ycr.js} +1 -1
- package/src/assets/web-panel/assets/{DID-fe2Qaowz.js → DID-CkCzWkx1.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Fh_EdWVa.js → Dashboard-C1scT7Ke.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-N1PIwWYf.js → Dropdown-DBnQ2EWd.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-B6vK93Ed.js → EmailListRenderer-C9JhOTq0.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-e3iUZhAg.js → FamilyGuardDashboard-CWXv5RUv.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-uInc9YcN.js → Federation-fYdcbz9W.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DmQZSX0z.js → FormItemContext-CJqOT3Yj.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CV_Z8OAo.js → GenericCardRenderer-DGCsHc5K.js} +1 -1
- package/src/assets/web-panel/assets/{Git-jXAhNN8d.js → Git-EH2K-H0Q.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Blw1esBB.js → Governance-DJn1X2pR.js} +1 -1
- package/src/assets/web-panel/assets/Inference-Dch1E8qd.js +1 -0
- package/src/assets/web-panel/assets/{KnowledgeGraph-5xrglMTK.js → KnowledgeGraph-QIur8j8-.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BGIG9798.js → Logs-DUgHldPg.js} +2 -2
- package/src/assets/web-panel/assets/Marketplace-DafrSfvd.js +1 -0
- package/src/assets/web-panel/assets/{McpTools-7U8tEhwK.js → McpTools-D2xRbfJx.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-BrvboPLE.js → Memory-C6RbVHAo.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-nzcd7d1H.js → MobileBridge-BPtVBKqn.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DETVNKa7.js → MobileProjects-Cuw832cr.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-SZcCYec3.js → Mtc-D6O9fWFa.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-Cx_d3N17.js → MtcAudit-CWZcXIH1.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-DtcmSUo-.js → Multisig-DhIBxTFd.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Dgx2QHl-.js → NLProgramming-wkBFS33e.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-oHTGEHoJ.js → Notes-B09FxncA.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-qKD-IlOl.js → NotificationSettings-oQwtH6-9.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CiU4Sy1J.js → OrderTableRenderer-iFKeNf6Y.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BBNXnltP.js → Organization-CsF-NIjz.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Df2fDbvT.js → Overflow-bLxv9Dqi.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DUHj6zjO.js → P2P-DVwQtm4q.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-B2nWgdoV.js → PdhVaultBrowser-Bgic3QKm.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CiW0afny.js → Permissions-as80-9ep.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-cc1mHU_D.js → PersonalDataHub-BGmUw36a.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-B93zTapU.js → Pipeline-BM96zBxG.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Db1jXWfd.js → Privacy-BBOzBSWe.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DFoZ1h9U.js → ProjectInit-GHX41V28.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BkkUnmYs.js → ProjectSettings-DraqzxKD.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Xa779XLC.js → Projects-BzzdUml4.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DOF01IEN.js → Providers-CSeYNAtW.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-TohRsKd0.js → QrScannerModal-DlzBCdXh.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DjLcr1ZU.js → QuickAsk-p8iB7od_.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend--Ism6bMx.js → Recommend-DjOVXacd.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-B8CL3YHM.js → RemoteSession-CIGk7gk-.js} +2 -2
- package/src/assets/web-panel/assets/Reputation-CjT3M0Di.js +1 -0
- package/src/assets/web-panel/assets/{Row-BioxZBBH.js → Row-tw8m6T0c.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B2LipwH3.js → RssFeed-B47KBx_f.js} +2 -2
- package/src/assets/web-panel/assets/Search-D2sx1PBe.js +1 -0
- package/src/assets/web-panel/assets/{Security-TibHuJWP.js → Security-JmtL8g7D.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DtkuWseW.js → Services-BxrNqjin.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BIcPQae6.js → Skeleton-udk8L18t.js} +1 -1
- package/src/assets/web-panel/assets/Skills-DooLT9of.js +1 -0
- package/src/assets/web-panel/assets/{Sla-uUSU185m.js → Sla-ITVZE1xI.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-B7Bgc9mk.js → SpeechSettings-DCkfqY1n.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-K-XrJ2s9.js → SyncSettings-CkNlgFjM.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-BMAoyCM_.js +1 -0
- package/src/assets/web-panel/assets/{Templates-CaFnyGDK.js → Templates-BnrFTlrz.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-C2X0PtEC.js → Tenant-BjNsy3-i.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CKU5yVsT.js → Terminal-C0gxLL7V.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-8trZeYDC.js → TimelineRenderer-CUtj_KHA.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BUEEe9US.js → Tokens-DOg61zlq.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-COU97I7Y.js → Trigger-D4ldCewj.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DNWQChaP.js → Trust-3lk_Zd8j.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DWX_VtCp.js → UkeySign-kWhFR6Li.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-D9eIDhsp.js → VideoEditing-D3GOFVWg.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BOnCCgIL.js → Wallet-DzrZfBuh.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DN4dD-W8.js → WebAuthn-CyVJVp_g.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-ClvDb_jX.js → WorkflowEditor-i_b0wi9b.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DIxQ_Eeb.js → chat-DwPCK8I7.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BOX3WKcP.js → colors-D0vaVqZU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Bny82VDi.js → compact-item-Don7nGW2.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-Cnoy3enS.js → createContext-D84R5qy2.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BBwWehQ7.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BJ7fkx3F.js → hasIn-BeUqVVKU.js} +1 -1
- package/src/assets/web-panel/assets/{icons-DEmcnxBf.js → icons-DG5UD-6K.js} +4 -4
- package/src/assets/web-panel/assets/{index-CZ6CHiCQ.js → index-4MkfPLGv.js} +1 -1
- package/src/assets/web-panel/assets/{index-7GLXvG8p.js → index-7QUwcGTg.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1nHEOFE.js → index-B57al0Z5.js} +1 -1
- package/src/assets/web-panel/assets/{index-Kio1ekYg.js → index-BER98o4P.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9QEc7Tq.js → index-BNpJf-sf.js} +1 -1
- package/src/assets/web-panel/assets/{index--CcGiwAI.js → index-BZ1N07Sp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWPey0Uf.js → index-BlfTf0ka.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7Fah_BX.js → index-BohrJpBf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJ8-oLHI.js → index-Br3SOdER.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2qNdrNW.js → index-C0_sKVi7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQ-xLCVb.js → index-CAdCTTBC.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSRIjAWO.js → index-CExWtm98.js} +1 -1
- package/src/assets/web-panel/assets/{index--Xb2lq6E.js → index-CL71rIwo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDkN6YOI.js → index-CfYRv-zA.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bk5yST66.js → index-CnnxzIx0.js} +1 -1
- package/src/assets/web-panel/assets/{index-2N9Y1cLx.js → index-CrnVEEQO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW6n-y1L.js → index-CzT56x-_.js} +1 -1
- package/src/assets/web-panel/assets/{index-OaNFXV8N.js → index-D4b5XqIy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEPTiBWy.js → index-D84BnuFg.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZCTan8Q.js → index-D8r7WKk-.js} +1 -1
- package/src/assets/web-panel/assets/{index-rn6xd12s.js → index-DA0-EJKx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcmXbIwv.js → index-DBzBLX-K.js} +3 -3
- package/src/assets/web-panel/assets/{index-C--PPqwi.js → index-DFFzwrNs.js} +1 -1
- package/src/assets/web-panel/assets/index-DJ8etkBT.js +1 -0
- package/src/assets/web-panel/assets/{index-Ty4w18mR.js → index-DMT8n9vB.js} +4 -4
- package/src/assets/web-panel/assets/{index-qOBKrw-g.js → index-DQor_7NF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CN6emwbq.js → index-DT40zd7K.js} +1 -1
- package/src/assets/web-panel/assets/{index-BM0mQhVv.js → index-De85D9Pc.js} +1 -1
- package/src/assets/web-panel/assets/{index-ceH9DsAi.js → index-IGGttsCv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBhkJqVF.js → index-L73NrmlW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbZynivw.js → index-LMo9bBLJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bvheiep2.js → index-MKZrJrP_.js} +1 -1
- package/src/assets/web-panel/assets/index-OeaK-zXZ.js +1 -0
- package/src/assets/web-panel/assets/{index-DxX8hhmL.js → index-WRw1pM5E.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6WoW8DJ.js → index-YKLCotoo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BP7HFsAK.js → index-hjgrIX5I.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnjtAKdw.js → index-m9bn0F1p.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEq5Vh0i.js → index-wesQQ2cH.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1-h2QrC.js → index-x7VYlV41.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BmxMBuUZ.js → initDefaultProps-DGeU4vPS.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DnXNwo2k.js → motion-Dgqj9ab3.js} +1 -1
- package/src/assets/web-panel/assets/{move-WnIJwmZN.js → move-BFyEU6Lr.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DAto-c2w.js → mtc-parser-CueCXXPC.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BtvW9W0H.js → omit-D2pU5OyE.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DFqI9-_C.js → pickAttrs-CKTf6zD6.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Dax6wOK3.js → placementArrow-DieJaGCN.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BUFWWC83.js → responsiveObserve-Bxr-rmU6.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DyARyuSz.js → slide-CDEDk3Se.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BZSDugpi.js → statusUtils-icf2eCTx.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B7o_K-4R.js → styleChecker-qKvgmBhE.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Dg7Bg8VG.js → useFlexGapSupport-1_UhiyJZ.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DQYXo5Rk.js → useFs-CFGLXDWh.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-E8NBAnkq.js → usePersonalDataHub-UafOXvQ6.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DD71_w1b.js → vnode-BfPqSx79.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-zc9EMd3q.js → zoom-CXsVcRB6.js} +1 -1
- package/src/assets/web-panel/index.html +2 -2
- package/src/command-manifest.json +22 -1
- package/src/commands/agenda.js +228 -0
- package/src/commands/agent.js +45 -4
- package/src/commands/artifacts.js +161 -0
- package/src/commands/batch.js +345 -0
- package/src/commands/browse.js +204 -2
- package/src/data/changelog.json +13 -2
- package/src/gateways/ws/artifact-protocol.js +219 -0
- package/src/gateways/ws/message-dispatcher.js +6 -0
- package/src/gateways/ws/ws-server.js +32 -0
- package/src/index.js +18 -0
- package/src/lib/accessibility.js +55 -0
- package/src/lib/agent-batch.js +235 -0
- package/src/lib/agent-notify.js +66 -0
- package/src/lib/agent-schedule-store.js +330 -0
- package/src/lib/artifact-store.js +236 -0
- package/src/lib/chrome-connector.js +314 -0
- package/src/lib/hook-runner.cjs +47 -7
- package/src/lib/ide-context.js +84 -0
- package/src/lib/permission-rules.cjs +26 -3
- package/src/lib/plugin-runtime/scopes.js +12 -0
- package/src/lib/safe-mode.js +40 -0
- package/src/lib/shell-selector.cjs +203 -0
- package/src/lib/skill-loader.js +19 -0
- package/src/lib/slash-dispatch.js +34 -0
- package/src/repl/agent-repl.js +99 -58
- package/src/runtime/agent-core.js +197 -8
- package/src/runtime/coding-agent-contract-shared.cjs +156 -0
- package/src/runtime/coding-agent-policy.cjs +43 -0
- package/src/runtime/headless-stream.js +51 -1
- package/src/runtime/policies/agent-policy.js +1 -0
- package/src/assets/web-panel/assets/AppLayout-C6WIrDZk.js +0 -9
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BFEnA8LN.js +0 -1
- package/src/assets/web-panel/assets/Inference-CoK8Ia0Z.js +0 -1
- package/src/assets/web-panel/assets/Marketplace-DFqhJMuY.js +0 -1
- package/src/assets/web-panel/assets/Reputation-CaRxB3Ep.js +0 -1
- package/src/assets/web-panel/assets/Search-BpjLBV8u.js +0 -1
- package/src/assets/web-panel/assets/Skills-DoTWIQOX.js +0 -1
- package/src/assets/web-panel/assets/Tasks-B3hEXNcI.js +0 -1
- package/src/assets/web-panel/assets/devWarning-Dr9dzlQ5.js +0 -1
- package/src/assets/web-panel/assets/index-B92M3t6B.js +0 -1
- package/src/assets/web-panel/assets/index-d2UcGpK-.js +0 -1
|
@@ -1041,6 +1041,7 @@ async function tryIdeDiffApprovalForEdit(
|
|
|
1041
1041
|
hasIdeOpenDiff,
|
|
1042
1042
|
requestIdeDiffApproval,
|
|
1043
1043
|
formatReviewComments,
|
|
1044
|
+
summarizeUserAmendments,
|
|
1044
1045
|
} = await import("../lib/ide-context.js");
|
|
1045
1046
|
const mcpLike = {
|
|
1046
1047
|
mcpClient: context.mcpClient,
|
|
@@ -1056,15 +1057,22 @@ async function tryIdeDiffApprovalForEdit(
|
|
|
1056
1057
|
title: `cc agent: ${name} ${path.basename(proposal.filePath)}`,
|
|
1057
1058
|
});
|
|
1058
1059
|
if (verdict?.outcome === "accepted") {
|
|
1060
|
+
// When the reviewer amended the proposal in the diff before accepting,
|
|
1061
|
+
// hand the agent the actual -/+ delta — not just a flag — so its model
|
|
1062
|
+
// of the file matches what was really written (gap #4: the agent
|
|
1063
|
+
// perceives the user's edits).
|
|
1064
|
+
const amendments =
|
|
1065
|
+
verdict.finalText != null && verdict.finalText !== proposal.newContent
|
|
1066
|
+
? summarizeUserAmendments(proposal.newContent, verdict.finalText)
|
|
1067
|
+
: null;
|
|
1059
1068
|
return {
|
|
1060
1069
|
outcome: "accepted",
|
|
1061
1070
|
result: {
|
|
1062
1071
|
success: true,
|
|
1063
1072
|
path: proposal.filePath,
|
|
1064
1073
|
appliedVia: "ide-diff",
|
|
1065
|
-
...(
|
|
1066
|
-
|
|
1067
|
-
? { userEdited: true }
|
|
1074
|
+
...(amendments
|
|
1075
|
+
? { userEdited: true, userAmendments: amendments }
|
|
1068
1076
|
: {}),
|
|
1069
1077
|
policy: { decision: "allow", rule, via: "ide-diff" },
|
|
1070
1078
|
},
|
|
@@ -2431,6 +2439,24 @@ async function executeToolInner(
|
|
|
2431
2439
|
}
|
|
2432
2440
|
}
|
|
2433
2441
|
|
|
2442
|
+
// P1 #8 Windows/PowerShell first-class: per-call args.shell or the
|
|
2443
|
+
// configured settings `shell.windowsDefault` may route this command
|
|
2444
|
+
// through PowerShell via explicit argv (`powershell.exe -NoProfile
|
|
2445
|
+
// [-ExecutionPolicy <p>] -Command <cmd>`). The unconfigured path keeps
|
|
2446
|
+
// the historical default shell byte-identical (useDefaultShell=true).
|
|
2447
|
+
const { resolveShellInvocation } =
|
|
2448
|
+
await import("../lib/shell-selector.cjs");
|
|
2449
|
+
const shellInv = resolveShellInvocation({
|
|
2450
|
+
command: args.command,
|
|
2451
|
+
requested: args.shell,
|
|
2452
|
+
cwd: args.cwd || cwd,
|
|
2453
|
+
});
|
|
2454
|
+
const shellMeta = shellInv.useDefaultShell
|
|
2455
|
+
? shellInv.note
|
|
2456
|
+
? { shell_note: shellInv.note }
|
|
2457
|
+
: {}
|
|
2458
|
+
: { shell: shellInv.kind };
|
|
2459
|
+
|
|
2434
2460
|
// Background: spawn, register, return a task_id immediately. The agent
|
|
2435
2461
|
// polls output + completion via check_shell. No timeout — that's the whole
|
|
2436
2462
|
// point of backgrounding (builds, test suites, dev servers).
|
|
@@ -2463,9 +2489,9 @@ async function executeToolInner(
|
|
|
2463
2489
|
child: null,
|
|
2464
2490
|
};
|
|
2465
2491
|
try {
|
|
2466
|
-
const
|
|
2492
|
+
const bgSpawnOpts = {
|
|
2467
2493
|
cwd: task.cwd,
|
|
2468
|
-
shell:
|
|
2494
|
+
shell: shellInv.useDefaultShell,
|
|
2469
2495
|
windowsHide: true,
|
|
2470
2496
|
// Same agent-identity env as the foreground path: CLAUDECODE marks
|
|
2471
2497
|
// "running under the agent"; the session id correlates work to the
|
|
@@ -2484,7 +2510,12 @@ async function executeToolInner(
|
|
|
2484
2510
|
// the whole tree (shell + its grandchild command). No-op on Windows
|
|
2485
2511
|
// where the tree is killed via taskkill /T instead.
|
|
2486
2512
|
detached: process.platform !== "win32",
|
|
2487
|
-
}
|
|
2513
|
+
};
|
|
2514
|
+
// PowerShell route: explicit argv (shell:false above); default route
|
|
2515
|
+
// is the historical spawn(command, {shell:true}) byte-for-byte.
|
|
2516
|
+
const child = shellInv.useDefaultShell
|
|
2517
|
+
? spawn(args.command, bgSpawnOpts)
|
|
2518
|
+
: spawn(shellInv.file, shellInv.argv, bgSpawnOpts);
|
|
2488
2519
|
task.child = child;
|
|
2489
2520
|
if (child.stdout) {
|
|
2490
2521
|
child.stdout.setEncoding("utf8");
|
|
@@ -2532,6 +2563,7 @@ async function executeToolInner(
|
|
|
2532
2563
|
task_id: id,
|
|
2533
2564
|
status: task.status,
|
|
2534
2565
|
command: task.command,
|
|
2566
|
+
...shellMeta,
|
|
2535
2567
|
hint: "Poll output and completion with the check_shell tool using this task_id. Kill long-lived servers with check_shell { task_id, kill: true } when done.",
|
|
2536
2568
|
shellCommandPolicy: shellPolicy,
|
|
2537
2569
|
approval: approvalOutcome,
|
|
@@ -2630,7 +2662,7 @@ async function executeToolInner(
|
|
|
2630
2662
|
}
|
|
2631
2663
|
|
|
2632
2664
|
try {
|
|
2633
|
-
const
|
|
2665
|
+
const fgExecOpts = {
|
|
2634
2666
|
cwd: args.cwd || cwd,
|
|
2635
2667
|
encoding: "utf8",
|
|
2636
2668
|
timeout: _resolveShellTimeout(args.timeout),
|
|
@@ -2649,10 +2681,35 @@ async function executeToolInner(
|
|
|
2649
2681
|
}
|
|
2650
2682
|
: {}),
|
|
2651
2683
|
},
|
|
2652
|
-
}
|
|
2684
|
+
};
|
|
2685
|
+
let output;
|
|
2686
|
+
if (shellInv.useDefaultShell) {
|
|
2687
|
+
output = execSync(args.command, fgExecOpts);
|
|
2688
|
+
} else {
|
|
2689
|
+
// PowerShell route: explicit argv, no intermediate default shell.
|
|
2690
|
+
// Reproduce execSync's contract so the shared catch shapes errors
|
|
2691
|
+
// identically: throw on spawn error; throw an Error carrying
|
|
2692
|
+
// status/stdout/stderr on non-zero exit.
|
|
2693
|
+
const res = spawnSync(shellInv.file, shellInv.argv, {
|
|
2694
|
+
...fgExecOpts,
|
|
2695
|
+
windowsHide: true,
|
|
2696
|
+
});
|
|
2697
|
+
if (res.error) throw res.error;
|
|
2698
|
+
if (res.status !== 0) {
|
|
2699
|
+
const e = new Error(
|
|
2700
|
+
`Command failed (${shellInv.kind}, exit ${res.status}): ${args.command}`,
|
|
2701
|
+
);
|
|
2702
|
+
e.status = res.status;
|
|
2703
|
+
e.stdout = res.stdout;
|
|
2704
|
+
e.stderr = res.stderr;
|
|
2705
|
+
throw e;
|
|
2706
|
+
}
|
|
2707
|
+
output = res.stdout ?? "";
|
|
2708
|
+
}
|
|
2653
2709
|
return attachDescriptor(
|
|
2654
2710
|
{
|
|
2655
2711
|
stdout: output.substring(0, 30000),
|
|
2712
|
+
...shellMeta,
|
|
2656
2713
|
shellCommandPolicy: shellPolicy,
|
|
2657
2714
|
approval: approvalOutcome,
|
|
2658
2715
|
},
|
|
@@ -2672,6 +2729,7 @@ async function executeToolInner(
|
|
|
2672
2729
|
: {}),
|
|
2673
2730
|
stderr: (err.stderr || "").substring(0, 2000),
|
|
2674
2731
|
exitCode: err.status,
|
|
2732
|
+
...shellMeta,
|
|
2675
2733
|
shellCommandPolicy: shellPolicy,
|
|
2676
2734
|
approval: approvalOutcome,
|
|
2677
2735
|
},
|
|
@@ -3010,6 +3068,125 @@ async function executeToolInner(
|
|
|
3010
3068
|
}
|
|
3011
3069
|
}
|
|
3012
3070
|
|
|
3071
|
+
case "notify": {
|
|
3072
|
+
try {
|
|
3073
|
+
const { sendAgentNotification } =
|
|
3074
|
+
await import("../lib/agent-notify.js");
|
|
3075
|
+
const outcome = await sendAgentNotification({
|
|
3076
|
+
title: args.title,
|
|
3077
|
+
body: args.body,
|
|
3078
|
+
level: args.level,
|
|
3079
|
+
});
|
|
3080
|
+
return attachDescriptor(outcome);
|
|
3081
|
+
} catch (err) {
|
|
3082
|
+
return attachDescriptor({ error: `notify failed: ${err.message}` });
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
case "schedule": {
|
|
3087
|
+
try {
|
|
3088
|
+
const { AgentScheduleStore } =
|
|
3089
|
+
await import("../lib/agent-schedule-store.js");
|
|
3090
|
+
const { parseDuration } = await import("../lib/loop.js");
|
|
3091
|
+
const store = new AgentScheduleStore();
|
|
3092
|
+
const action = String(args.action || "").toLowerCase();
|
|
3093
|
+
if (action === "wakeup") {
|
|
3094
|
+
if (!args.prompt) {
|
|
3095
|
+
return attachDescriptor({
|
|
3096
|
+
error: "schedule wakeup requires a prompt",
|
|
3097
|
+
});
|
|
3098
|
+
}
|
|
3099
|
+
const delayMs = args.delay ? parseDuration(args.delay) : 0;
|
|
3100
|
+
const entry = store.scheduleWakeup({
|
|
3101
|
+
prompt: args.prompt,
|
|
3102
|
+
delayMs,
|
|
3103
|
+
label: args.label || null,
|
|
3104
|
+
});
|
|
3105
|
+
return attachDescriptor({
|
|
3106
|
+
scheduled: entry,
|
|
3107
|
+
hint: "Run `cc agenda run` (e.g. via cron or `cc loop`) to fire due entries.",
|
|
3108
|
+
});
|
|
3109
|
+
}
|
|
3110
|
+
if (action === "cron") {
|
|
3111
|
+
if (!args.prompt || !args.cron) {
|
|
3112
|
+
return attachDescriptor({
|
|
3113
|
+
error: "schedule cron requires a prompt and a cron expression",
|
|
3114
|
+
});
|
|
3115
|
+
}
|
|
3116
|
+
const entry = store.createCron({
|
|
3117
|
+
prompt: args.prompt,
|
|
3118
|
+
cron: args.cron,
|
|
3119
|
+
label: args.label || null,
|
|
3120
|
+
});
|
|
3121
|
+
return attachDescriptor({ scheduled: entry });
|
|
3122
|
+
}
|
|
3123
|
+
if (action === "monitor") {
|
|
3124
|
+
if (!args.command) {
|
|
3125
|
+
return attachDescriptor({
|
|
3126
|
+
error: "schedule monitor requires a command",
|
|
3127
|
+
});
|
|
3128
|
+
}
|
|
3129
|
+
const intervalMs = args.interval
|
|
3130
|
+
? parseDuration(args.interval)
|
|
3131
|
+
: 60000;
|
|
3132
|
+
const entry = store.createMonitor({
|
|
3133
|
+
command: args.command,
|
|
3134
|
+
intervalMs,
|
|
3135
|
+
stopWhen: args.stop_when || null,
|
|
3136
|
+
notify: args.notify_title ? { title: args.notify_title } : null,
|
|
3137
|
+
maxChecks: args.max_checks ?? null,
|
|
3138
|
+
label: args.label || null,
|
|
3139
|
+
});
|
|
3140
|
+
return attachDescriptor({ scheduled: entry });
|
|
3141
|
+
}
|
|
3142
|
+
if (action === "list") {
|
|
3143
|
+
return attachDescriptor({ entries: store.list() });
|
|
3144
|
+
}
|
|
3145
|
+
if (action === "cancel") {
|
|
3146
|
+
if (!args.id) {
|
|
3147
|
+
return attachDescriptor({
|
|
3148
|
+
error: "schedule cancel requires an id",
|
|
3149
|
+
});
|
|
3150
|
+
}
|
|
3151
|
+
const removed = store.cancel(args.id);
|
|
3152
|
+
return attachDescriptor({
|
|
3153
|
+
cancelled: removed ? removed.id : null,
|
|
3154
|
+
found: Boolean(removed),
|
|
3155
|
+
});
|
|
3156
|
+
}
|
|
3157
|
+
return attachDescriptor({
|
|
3158
|
+
error: `unknown schedule action "${args.action}". Valid: wakeup, cron, monitor, list, cancel.`,
|
|
3159
|
+
});
|
|
3160
|
+
} catch (err) {
|
|
3161
|
+
return attachDescriptor({ error: `schedule failed: ${err.message}` });
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
|
|
3165
|
+
case "publish_artifact": {
|
|
3166
|
+
// P1 #10: copy a finished deliverable into the user's artifact store.
|
|
3167
|
+
// Only METADATA returns to the conversation (the transcript never
|
|
3168
|
+
// carries the file body); `cc artifacts` lists/inspects/cleans.
|
|
3169
|
+
try {
|
|
3170
|
+
const { ArtifactStore } = await import("../lib/artifact-store.js");
|
|
3171
|
+
const store = new ArtifactStore();
|
|
3172
|
+
const entry = store.publish({
|
|
3173
|
+
filePath: path.resolve(cwd, String(args.path || "")),
|
|
3174
|
+
title: args.title,
|
|
3175
|
+
kind: args.kind,
|
|
3176
|
+
ttlDays: args.ttl_days,
|
|
3177
|
+
sessionId: sessionId ? String(sessionId) : null,
|
|
3178
|
+
});
|
|
3179
|
+
return attachDescriptor({
|
|
3180
|
+
published: entry,
|
|
3181
|
+
hint: "The user can browse this with `cc artifacts list` / `cc artifacts show <id>`.",
|
|
3182
|
+
});
|
|
3183
|
+
} catch (err) {
|
|
3184
|
+
return attachDescriptor({
|
|
3185
|
+
error: `publish_artifact failed: ${err.message}`,
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3013
3190
|
case "search_files": {
|
|
3014
3191
|
// An explicit directory scopes the search to one root; otherwise span
|
|
3015
3192
|
// cwd plus any --add-dir roots so cross-package searches find matches.
|
|
@@ -6342,6 +6519,18 @@ export function formatToolArgs(name, args) {
|
|
|
6342
6519
|
return `[${args.role}] ${(args.task || "").substring(0, 60)}`;
|
|
6343
6520
|
case "search_sessions":
|
|
6344
6521
|
return `"${(args.query || "").substring(0, 60)}"`;
|
|
6522
|
+
case "notify":
|
|
6523
|
+
return `${args.level || "info"}: ${(args.title || "").substring(0, 50)}`;
|
|
6524
|
+
case "publish_artifact":
|
|
6525
|
+
return `${args.kind || "other"}: ${(args.title || args.path || "").substring(0, 60)}`;
|
|
6526
|
+
case "schedule":
|
|
6527
|
+
return args.action === "cron"
|
|
6528
|
+
? `cron ${args.cron || ""}`.trim()
|
|
6529
|
+
: args.action === "monitor"
|
|
6530
|
+
? `monitor ${(args.command || "").substring(0, 40)}`.trim()
|
|
6531
|
+
: args.action === "wakeup"
|
|
6532
|
+
? `wakeup +${args.delay || "0s"}`
|
|
6533
|
+
: String(args.action || "");
|
|
6345
6534
|
default:
|
|
6346
6535
|
return JSON.stringify(args).substring(0, 60);
|
|
6347
6536
|
}
|
|
@@ -238,6 +238,12 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
238
238
|
description:
|
|
239
239
|
"Foreground (synchronous) timeout in milliseconds. Default 60000, max 600000. Ignored when run_in_background is true.",
|
|
240
240
|
},
|
|
241
|
+
shell: {
|
|
242
|
+
type: "string",
|
|
243
|
+
enum: ["default", "cmd", "powershell", "pwsh"],
|
|
244
|
+
description:
|
|
245
|
+
"Shell to run the command with (optional). default = the platform shell (cmd.exe on Windows, /bin/sh elsewhere) or the configured settings shell.windowsDefault. Use powershell (Windows PowerShell 5.1) or pwsh (PowerShell 7+) when the command uses PowerShell syntax: cmdlets, object pipelines, $variables.",
|
|
246
|
+
},
|
|
241
247
|
},
|
|
242
248
|
required: ["command"],
|
|
243
249
|
},
|
|
@@ -849,6 +855,156 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
849
855
|
tags: ["tool:search_sessions", "contract:coding-agent", "tier:extension"],
|
|
850
856
|
},
|
|
851
857
|
},
|
|
858
|
+
{
|
|
859
|
+
name: "notify",
|
|
860
|
+
title: "Send Notification",
|
|
861
|
+
kind: "notify",
|
|
862
|
+
tier: "extension",
|
|
863
|
+
description:
|
|
864
|
+
"Push a notification to the user's configured channels (Telegram / WeCom / DingTalk / Feishu) and/or a paired mobile device. Use for long-running tasks: report completion, flag that you need a human decision, or surface an error. Best-effort: reports which channels delivered.",
|
|
865
|
+
inputSchema: {
|
|
866
|
+
type: "object",
|
|
867
|
+
properties: {
|
|
868
|
+
title: { type: "string", description: "Short notification title" },
|
|
869
|
+
body: { type: "string", description: "Notification body text" },
|
|
870
|
+
level: {
|
|
871
|
+
type: "string",
|
|
872
|
+
enum: ["info", "success", "failure"],
|
|
873
|
+
description: "Severity (default: info)",
|
|
874
|
+
},
|
|
875
|
+
},
|
|
876
|
+
required: ["title"],
|
|
877
|
+
},
|
|
878
|
+
...TOOL_POLICY_METADATA.notify,
|
|
879
|
+
permissions: {
|
|
880
|
+
level: "standard",
|
|
881
|
+
scopes: ["network:notify"],
|
|
882
|
+
},
|
|
883
|
+
telemetry: {
|
|
884
|
+
category: "notify",
|
|
885
|
+
tags: ["tool:notify", "contract:coding-agent", "tier:extension"],
|
|
886
|
+
},
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
name: "schedule",
|
|
890
|
+
title: "Schedule / Monitor",
|
|
891
|
+
kind: "schedule",
|
|
892
|
+
tier: "extension",
|
|
893
|
+
description:
|
|
894
|
+
"Set up work that outlives this turn (persisted for `cc agenda run` to execute). Actions: `wakeup` — run a prompt once after a delay; `cron` — run a prompt on a 5-field cron schedule; `monitor` — run a shell command every interval and notify when its output matches a regex; `list` — show scheduled items; `cancel` — remove one by id.",
|
|
895
|
+
inputSchema: {
|
|
896
|
+
type: "object",
|
|
897
|
+
properties: {
|
|
898
|
+
action: {
|
|
899
|
+
type: "string",
|
|
900
|
+
enum: ["wakeup", "cron", "monitor", "list", "cancel"],
|
|
901
|
+
description: "What to do",
|
|
902
|
+
},
|
|
903
|
+
prompt: {
|
|
904
|
+
type: "string",
|
|
905
|
+
description:
|
|
906
|
+
"For wakeup/cron: the agent prompt to run (via `cc agent -p`) when it fires",
|
|
907
|
+
},
|
|
908
|
+
delay: {
|
|
909
|
+
type: "string",
|
|
910
|
+
description:
|
|
911
|
+
"For wakeup: how long from now before it fires (e.g. 30s, 5m, 1h)",
|
|
912
|
+
},
|
|
913
|
+
cron: {
|
|
914
|
+
type: "string",
|
|
915
|
+
description:
|
|
916
|
+
'For cron: a 5-field cron expression, e.g. "0 9 * * 1" (09:00 every Monday)',
|
|
917
|
+
},
|
|
918
|
+
command: {
|
|
919
|
+
type: "string",
|
|
920
|
+
description: "For monitor: the shell command to run each interval",
|
|
921
|
+
},
|
|
922
|
+
interval: {
|
|
923
|
+
type: "string",
|
|
924
|
+
description:
|
|
925
|
+
"For monitor: how often to run the command (e.g. 30s, 5m)",
|
|
926
|
+
},
|
|
927
|
+
stop_when: {
|
|
928
|
+
type: "string",
|
|
929
|
+
description:
|
|
930
|
+
"For monitor: a regex; when the command output matches, the monitor fires its notification and stops",
|
|
931
|
+
},
|
|
932
|
+
notify_title: {
|
|
933
|
+
type: "string",
|
|
934
|
+
description: "For monitor: notification title sent when it matches",
|
|
935
|
+
},
|
|
936
|
+
max_checks: {
|
|
937
|
+
type: "number",
|
|
938
|
+
description:
|
|
939
|
+
"For monitor: give up after this many checks (optional safety cap)",
|
|
940
|
+
},
|
|
941
|
+
label: {
|
|
942
|
+
type: "string",
|
|
943
|
+
description: "Optional human label for list/cancel",
|
|
944
|
+
},
|
|
945
|
+
id: {
|
|
946
|
+
type: "string",
|
|
947
|
+
description: "For cancel: the schedule entry id to remove",
|
|
948
|
+
},
|
|
949
|
+
},
|
|
950
|
+
required: ["action"],
|
|
951
|
+
},
|
|
952
|
+
...TOOL_POLICY_METADATA.schedule,
|
|
953
|
+
permissions: {
|
|
954
|
+
level: "standard",
|
|
955
|
+
scopes: ["schedule:write"],
|
|
956
|
+
},
|
|
957
|
+
telemetry: {
|
|
958
|
+
category: "schedule",
|
|
959
|
+
tags: ["tool:schedule", "contract:coding-agent", "tier:extension"],
|
|
960
|
+
},
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
name: "publish_artifact",
|
|
964
|
+
title: "Publish Artifact",
|
|
965
|
+
kind: "artifact",
|
|
966
|
+
tier: "extension",
|
|
967
|
+
description:
|
|
968
|
+
"Publish a finished deliverable file (Markdown report, patch, screenshot, test log, findings JSON) as a durable artifact the user can find later with `cc artifacts`. The file is copied into the user's artifact store with metadata; only the metadata enters the conversation. Use at the END of a task for its key outputs — not for intermediate scratch files.",
|
|
969
|
+
inputSchema: {
|
|
970
|
+
type: "object",
|
|
971
|
+
properties: {
|
|
972
|
+
path: {
|
|
973
|
+
type: "string",
|
|
974
|
+
description:
|
|
975
|
+
"Path of the file to publish (relative to cwd or absolute)",
|
|
976
|
+
},
|
|
977
|
+
title: {
|
|
978
|
+
type: "string",
|
|
979
|
+
description: "Human title for the artifact (default: the file name)",
|
|
980
|
+
},
|
|
981
|
+
kind: {
|
|
982
|
+
type: "string",
|
|
983
|
+
enum: ["report", "patch", "screenshot", "log", "data", "other"],
|
|
984
|
+
description: "What kind of deliverable this is (default: other)",
|
|
985
|
+
},
|
|
986
|
+
ttl_days: {
|
|
987
|
+
type: "number",
|
|
988
|
+
description:
|
|
989
|
+
"Days to retain before `cc artifacts clean` may remove it (default 30)",
|
|
990
|
+
},
|
|
991
|
+
},
|
|
992
|
+
required: ["path"],
|
|
993
|
+
},
|
|
994
|
+
...TOOL_POLICY_METADATA.publish_artifact,
|
|
995
|
+
permissions: {
|
|
996
|
+
level: "standard",
|
|
997
|
+
scopes: ["filesystem:read", "artifact:write"],
|
|
998
|
+
},
|
|
999
|
+
telemetry: {
|
|
1000
|
+
category: "artifact",
|
|
1001
|
+
tags: [
|
|
1002
|
+
"tool:publish_artifact",
|
|
1003
|
+
"contract:coding-agent",
|
|
1004
|
+
"tier:extension",
|
|
1005
|
+
],
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
852
1008
|
]);
|
|
853
1009
|
|
|
854
1010
|
const CODING_AGENT_MVP_TOOL_NAMES = Object.freeze(
|
|
@@ -261,6 +261,49 @@ const TOOL_POLICY_METADATA = Object.freeze({
|
|
|
261
261
|
approvalFlow: "auto",
|
|
262
262
|
isReadOnly: true,
|
|
263
263
|
},
|
|
264
|
+
// Sends an outbound notification to the user's own channels/device. No
|
|
265
|
+
// workspace mutation and no un-gated shell; blocked in plan mode (an
|
|
266
|
+
// external side effect) but otherwise auto — it targets the user, not a
|
|
267
|
+
// third party.
|
|
268
|
+
notify: {
|
|
269
|
+
riskLevel: RISK_LEVELS.LOW,
|
|
270
|
+
category: TOOL_CATEGORIES.WRITE,
|
|
271
|
+
availableInPlanMode: false,
|
|
272
|
+
planModeBehavior: "blocked",
|
|
273
|
+
requiresPlanApproval: false,
|
|
274
|
+
requiresConfirmation: false,
|
|
275
|
+
approvalFlow: "auto",
|
|
276
|
+
isReadOnly: false,
|
|
277
|
+
},
|
|
278
|
+
// Persists a wakeup/cron/monitor entry for `cc agenda run` to execute later.
|
|
279
|
+
// Writing the schedule is itself harmless (a JSONL row under the user's
|
|
280
|
+
// config dir); the eventual `cc agent`/shell run is gated when the agenda
|
|
281
|
+
// consumer executes it. Blocked in plan mode (schedules future side effects).
|
|
282
|
+
schedule: {
|
|
283
|
+
riskLevel: RISK_LEVELS.LOW,
|
|
284
|
+
category: TOOL_CATEGORIES.WRITE,
|
|
285
|
+
availableInPlanMode: false,
|
|
286
|
+
planModeBehavior: "blocked",
|
|
287
|
+
requiresPlanApproval: false,
|
|
288
|
+
requiresConfirmation: false,
|
|
289
|
+
approvalFlow: "auto",
|
|
290
|
+
isReadOnly: false,
|
|
291
|
+
},
|
|
292
|
+
// Copies a finished deliverable (report/patch/screenshot/log) into the
|
|
293
|
+
// user's own ~/.chainlesschain/artifacts store with metadata. Reads a
|
|
294
|
+
// workspace file, writes only under the user's config dir — no third-party
|
|
295
|
+
// egress. Blocked in plan mode (publishing is a side effect of DONE work,
|
|
296
|
+
// not analysis).
|
|
297
|
+
publish_artifact: {
|
|
298
|
+
riskLevel: RISK_LEVELS.LOW,
|
|
299
|
+
category: TOOL_CATEGORIES.WRITE,
|
|
300
|
+
availableInPlanMode: false,
|
|
301
|
+
planModeBehavior: "blocked",
|
|
302
|
+
requiresPlanApproval: false,
|
|
303
|
+
requiresConfirmation: false,
|
|
304
|
+
approvalFlow: "auto",
|
|
305
|
+
isReadOnly: false,
|
|
306
|
+
},
|
|
264
307
|
});
|
|
265
308
|
|
|
266
309
|
function normalizeGitCommand(command) {
|
|
@@ -181,6 +181,47 @@ export function planSnapshot(pm) {
|
|
|
181
181
|
}
|
|
182
182
|
return { active: pm.isActive(), state: pm.state || null, items, risk };
|
|
183
183
|
}
|
|
184
|
+
|
|
185
|
+
const MAX_PLAN_REVIEW_SNAPSHOT_CHARS = 24000;
|
|
186
|
+
|
|
187
|
+
function planReviewFromInput(obj) {
|
|
188
|
+
const review =
|
|
189
|
+
obj && obj.review && typeof obj.review === "object" ? obj.review : null;
|
|
190
|
+
const snapshot =
|
|
191
|
+
typeof obj?.snapshot === "string"
|
|
192
|
+
? obj.snapshot
|
|
193
|
+
: typeof review?.snapshot === "string"
|
|
194
|
+
? review.snapshot
|
|
195
|
+
: "";
|
|
196
|
+
if (!snapshot.trim()) return null;
|
|
197
|
+
const text =
|
|
198
|
+
snapshot.length > MAX_PLAN_REVIEW_SNAPSHOT_CHARS
|
|
199
|
+
? snapshot.slice(0, MAX_PLAN_REVIEW_SNAPSHOT_CHARS) +
|
|
200
|
+
`\n\n[review snapshot truncated: ${snapshot.length - MAX_PLAN_REVIEW_SNAPSHOT_CHARS} chars omitted]`
|
|
201
|
+
: snapshot;
|
|
202
|
+
return {
|
|
203
|
+
action: String(review?.action || obj.action || "").toLowerCase(),
|
|
204
|
+
reviewedAt:
|
|
205
|
+
typeof review?.reviewedAt === "string" ? review.reviewedAt : null,
|
|
206
|
+
conversationId:
|
|
207
|
+
typeof review?.conversationId === "string" ? review.conversationId : null,
|
|
208
|
+
snapshot: text,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function planReviewSystemMessage(review) {
|
|
213
|
+
if (!review?.snapshot) return null;
|
|
214
|
+
const meta = [
|
|
215
|
+
review.action ? `action=${review.action}` : null,
|
|
216
|
+
review.reviewedAt ? `reviewedAt=${review.reviewedAt}` : null,
|
|
217
|
+
review.conversationId ? `conversationId=${review.conversationId}` : null,
|
|
218
|
+
]
|
|
219
|
+
.filter(Boolean)
|
|
220
|
+
.join(" ");
|
|
221
|
+
return (
|
|
222
|
+
"[PLAN REVIEW SNAPSHOT]" + (meta ? ` ${meta}` : "") + "\n" + review.snapshot
|
|
223
|
+
);
|
|
224
|
+
}
|
|
184
225
|
import { withQuietStdout } from "./quiet-stdout.js";
|
|
185
226
|
|
|
186
227
|
/**
|
|
@@ -199,7 +240,9 @@ export function parseInputEvent(line) {
|
|
|
199
240
|
// {"type":"plan","action":"enter"|"approve"|"reject"}
|
|
200
241
|
if (obj && typeof obj === "object" && obj.type === "plan") {
|
|
201
242
|
const action = String(obj.action || "").toLowerCase();
|
|
202
|
-
|
|
243
|
+
if (!action) return null;
|
|
244
|
+
const planReview = planReviewFromInput(obj);
|
|
245
|
+
return planReview ? { plan: action, planReview } : { plan: action };
|
|
203
246
|
}
|
|
204
247
|
// Turn interrupt (panel Stop / Claude-Code Esc parity): aborts the
|
|
205
248
|
// in-flight turn without ending the conversation. {"type":"interrupt"}
|
|
@@ -1304,6 +1347,13 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1304
1347
|
// exits plan mode. Every control answers with a `plan_update` event.
|
|
1305
1348
|
if (parsed.plan) {
|
|
1306
1349
|
const pm = getPlanModeManager();
|
|
1350
|
+
const reviewMessage =
|
|
1351
|
+
parsed.plan === "approve" || parsed.plan === "reject"
|
|
1352
|
+
? planReviewSystemMessage(parsed.planReview)
|
|
1353
|
+
: null;
|
|
1354
|
+
if (reviewMessage) {
|
|
1355
|
+
messages.push({ role: "system", content: reviewMessage });
|
|
1356
|
+
}
|
|
1307
1357
|
if (parsed.plan === "enter") {
|
|
1308
1358
|
if (!pm.isActive()) {
|
|
1309
1359
|
pm.enterPlanMode({ title: "Agent Plan" });
|