chainlesschain 0.163.2 → 0.163.3
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/assets/{AIOps-DnGsmsqJ.js → AIOps-DIY6KxV-.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CrO6fcQ7.js → ActionButton-BXH0muPt.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DsBdOaP2.js → Analytics-D39w8vmg.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DmQslKUB.js → AppLayout-CUU1zvLs.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-BvyrT_QQ.js → Artifacts-D8azHO3T.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-prndoLiC.js → Audit-D0tAwXTg.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DOTFyA55.js → BackgroundAgents-C29mhJll.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-9zOnPp_8.js → Backup-D6Aa1Gro.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C4PC6sAG.js → BaseInput-B1uoHbPQ.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BBAF-W9v.js → Chat-Bs4DLOR5.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CWhvvloO.js → ChatBubbleRenderer-DUYIBSle.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-BI9iculd.js → Checkbox-CNcBPEa4.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-3DP9BCKb.js → Codegen-CIY89763.js} +1 -1
- package/src/assets/web-panel/assets/{Col-df-2TnJX.js → Col-CsPYFmgo.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CHs8gG_A.js → Community-BBocEge4.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CDfF6q7V.js → Compact-TQ8Ux0Lf.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CthrDnO7.js → Compliance-DfBsZTft.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-HjIqsWJw.js → Cowork-Cg-I6FVH.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-BKc196fb.js → Cron-DTQzfRTp.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CJnjdc8W.js → Crosschain-DGxEKGpR.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BHUy-8Q2.js → DID-DLZ1RDSr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-QDB7sKeY.js → Dashboard-XneICKNI.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DStcVK11.js → Dropdown-BRU00J1-.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BwSUskMJ.js → EmailListRenderer-BzCbJuAy.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DgF_kurT.js → FamilyGuardDashboard-D7BRyNBG.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-k8wvv-wN.js → Federation-D9DeFIhW.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C11qoq2r.js → FormItemContext-6rAtA9Ko.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BIIpr9kg.js → GenericCardRenderer-8Hqy80pU.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BlA1exTe.js → Git-Cmvkj1rt.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CYa1ZYM4.js → Governance-BRiQUjjw.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-6_kKVIt6.js → Inference-CKN_EzVf.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CB4AwxYy.js → KnowledgeGraph-BCDHwpwQ.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-xf7nHFAe.js → Logs-DK9ovhaB.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-D53pHiHy.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-aPg8e4Jt.js → Marketplace-BILPGakp.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-C-TNlVUf.js → McpTools-DTVCOr9-.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-DMTPIpGa.js → Memory-Hzc1iow4.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BxyvveRq.js → MobileBridge-GXfgnGYV.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DyPCrAyQ.js → MobileProjects-B-3TJWsS.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BdhqNXp6.js → Mtc-DwSJMWtK.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-Cz-HFxzW.js → MtcAudit-D2uxf-DA.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-CIUaFNsx.js → Multisig-DG6kbKK0.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CWe6-J17.js → NLProgramming-f5p49EDU.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-vYAKeviU.js → Notes-FUgHyzSD.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DQL9-2d7.js → NotificationSettings-DCHGee7e.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DnXj1jBn.js → OrderTableRenderer-Dm6LlIoa.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-B3spU8AN.js → Organization-BawA7qAg.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DgEwo7vm.js → Overflow-D6a5wZU1.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-hujMRH8X.js → P2P-K8WavwnA.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-C_qhdg9h.js → PdhVaultBrowser-4JAJYaqx.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-vp7LMcSf.js → Permissions-BDWvi8PD.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Dxr5Hgnq.js → PersonalDataHub-DF_K4E9i.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DEPZqqH4.js → Pipeline-BYeZlesI.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DTpDiKPe.js → Privacy-BIHlgnIc.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-jDJsRWmF.js → ProjectInit-Cvf-6B5P.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Dhor5RWH.js → ProjectSettings-CnwfJrRz.js} +2 -2
- package/src/assets/web-panel/assets/Projects-b-jPXzF4.js +1 -0
- package/src/assets/web-panel/assets/{Providers-BGs47s1a.js → Providers-CxC7JuYv.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CjIw-wIb.js → QrScannerModal-VLf3gAfL.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DX6jcqoi.js → QuickAsk-B5vGjRiF.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DopXkhar.js → Recommend--UW4iYs-.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BLvqJE9c.js → RemoteSession-DMSPcfKR.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-DhRj2Me7.js → Reputation-kQXlEHmj.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DQ53vuPq.js → Row-CxGu3pit.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BslvwiBD.js → RssFeed-Bi5lo8MZ.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DJKBDNKZ.js → Search-Cq_H5RTh.js} +1 -1
- package/src/assets/web-panel/assets/{Security-COhpxHER.js → Security-YFbmkaQS.js} +3 -3
- package/src/assets/web-panel/assets/{Services-dbulD6cI.js → Services-DLOGdaLm.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-ciIVNfhC.js → Skeleton-CteIxb3D.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-AiRTkTCk.js → Skills-CccopaIZ.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DDMcWYBc.js → Sla-AzfEQKX1.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BPxWbpXO.js → SpeechSettings-ekGo5l77.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BoEOXCyg.js → SyncSettings-BmZmAgYH.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-D7q3Z4uL.js +1 -0
- package/src/assets/web-panel/assets/{Templates-UowY8Ixe.js → Templates-CX1Tgeka.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DauSLQXN.js → Tenant-Zc59jF4i.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DBj7Jneq.js → Terminal-CXOD7y83.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-UMrPwoZC.js → TimelineRenderer-B1aBHPBo.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-4ea96-bn.js → Tokens-zALlOq_U.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger--ISCqt4b.js → Trigger-CQfJMXaq.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-D4GVimRJ.js → Trust-BU0RcM-w.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Ci-nXRQc.js → UkeySign-IFZ3HsbH.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Cjk7mKPw.js → VideoEditing-BzslgW0v.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BgOLOO3Z.js → Wallet-BZAcQNS6.js} +2 -2
- package/src/assets/web-panel/assets/{WebAuthn-CCX0K29i.js → WebAuthn-CBK1DMi0.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-Ch3zgIsE.js → WorkflowEditor-BlMTPzO-.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DKOU_2Vb.js → chat-B51-8QVn.js} +1 -1
- package/src/assets/web-panel/assets/{colors-6OVo4u3C.js → colors-504RTByU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BH78Hlsq.js → compact-item-C-GP6IQM.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CFRpSbbC.js → createContext-DOkIj7ID.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-kB0nCNwN.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DNQhgcVi.js → hasIn-DN7V-_FW.js} +1 -1
- package/src/assets/web-panel/assets/{index-dDkoL4Pe.js → index--n-ZciV3.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaYqY35Z.js → index-7jIqHbzw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYrnm5Ob.js → index-B2-x9bS8.js} +1 -1
- package/src/assets/web-panel/assets/{index-sm7W8AXy.js → index-BFIFJ5Dr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKN2noIF.js → index-B_vGU-Js.js} +1 -1
- package/src/assets/web-panel/assets/{index--rq90rL9.js → index-Bkxhaeta.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFPJ8yzF.js → index-By6u5IV1.js} +1 -1
- package/src/assets/web-panel/assets/index-Bya64sZE.js +1 -0
- package/src/assets/web-panel/assets/{index-caye7AOE.js → index-C0k_Nqg9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxRy5LPR.js → index-C3TSohzc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BepBTpa8.js → index-C4DV_5uA.js} +1 -1
- package/src/assets/web-panel/assets/{index-D84id2Y4.js → index-C8UltbXK.js} +1 -1
- package/src/assets/web-panel/assets/{index-Y9MJv28e.js → index-C9_48OzU.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bb6kDrUx.js → index-CKTfZyfU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrcLHN2F.js → index-CP2A226L.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkNEMANR.js → index-CUhQpiYv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cu3L4r5l.js → index-CX78k-qf.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaDgdJYj.js → index-CYopNjcJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Du0rnksC.js → index-Cao5DZy7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BaVE6E8y.js → index-CfiEM64n.js} +3 -3
- package/src/assets/web-panel/assets/{index-BujsOZfc.js → index-ConjaJro.js} +1 -1
- package/src/assets/web-panel/assets/{index-hPY0fFrd.js → index-CqcLo5WV.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDSR7ecX.js → index-CySTJKeq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHa4WyTZ.js → index-D1phyca8.js} +1 -1
- package/src/assets/web-panel/assets/{index-nbfHl1oV.js → index-D9LyiN-L.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkqHgG-b.js → index-DA2f1UV3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Eag8e_mA.js → index-DAOpQvl_.js} +1 -1
- package/src/assets/web-panel/assets/{index-cdf7fd7d.js → index-DE-hmI2l.js} +1 -1
- package/src/assets/web-panel/assets/{index-bKm3TUDp.js → index-DEMPUVa3.js} +1 -1
- package/src/assets/web-panel/assets/index-D_FWpDZM.js +1 -0
- package/src/assets/web-panel/assets/{index-7TC3S8SN.js → index-DaA__-q1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvHGtNnF.js → index-FcV8J_Qz.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_Z-YoxX.js → index-P2mfY27Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-AuBhLqOm.js → index-et5JIPHO.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3RtTT4K.js → index-f4Bo4KXm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNuCHHQT.js → index-kAqQXfP6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BkN3iTTp.js → index-kt_5rfcZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnnXQot_.js → index-so8eIIxF.js} +1 -1
- package/src/assets/web-panel/assets/{index-HNGGVF6o.js → index-yYTQZypF.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BZ9w6jPL.js → initDefaultProps-CPYEIdpV.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BnwUiOho.js → motion-Cjim9pxs.js} +1 -1
- package/src/assets/web-panel/assets/{move-ByUKJnNm.js → move-DuU-cgz3.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-V7yK1KEl.js → mtc-parser-DJHNAkta.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BEXBBt4j.js → omit-DSQBgdBj.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-qDm_46Gi.js → pickAttrs-CTmT_j5m.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BIbhEo_0.js → placementArrow-Lfm6v-r4.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-NbPbDgA_.js → responsiveObserve-CgrcPcDi.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BnUWglZ0.js → slide-CuE3110i.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BX8_wZI5.js → statusUtils-DiK5nbpf.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BV4OycQX.js → styleChecker-DPEJdQaZ.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Od_H5llY.js → useFlexGapSupport-CnnodGmp.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BWI-PyiX.js → useFs-DWF84Yav.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BqMuhG3g.js → usePersonalDataHub-a5b5Dw2f.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DNd23z6f.js → vnode-DAluzXOq.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cjaxnm7l.js → zoom-Dokg7uAZ.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/agenda.js +6 -5
- package/src/commands/agent.js +237 -75
- package/src/commands/agents.js +6 -0
- package/src/commands/background-session.js +11 -1
- package/src/commands/mcp.js +217 -30
- package/src/data/changelog.json +14 -1
- package/src/harness/mcp-client.js +242 -42
- package/src/harness/worktree-isolator.js +26 -3
- package/src/lib/agent-worktree.js +41 -2
- package/src/lib/background-agent-supervisor.js +790 -186
- package/src/lib/background-command-argv.js +318 -0
- package/src/lib/background-launch-profile.js +1 -0
- package/src/lib/background-phase-reporter.js +22 -2
- package/src/lib/background-worktree-policy.js +109 -0
- package/src/lib/cowork-mcp-tools.js +51 -6
- package/src/lib/cowork-task-runner.js +1 -0
- package/src/lib/mcp-headers-helper.js +76 -8
- package/src/lib/mcp-sandbox-policy.js +155 -0
- package/src/lib/mcp-stdio-execution-authority.js +163 -0
- package/src/lib/mcp-stdio-workspace-authority.js +252 -0
- package/src/lib/plugin-runtime/sandbox-policy.js +42 -2
- package/src/lib/process-execution-broker/index.js +179 -104
- package/src/lib/process-execution-broker/platform-sandbox.js +942 -168
- package/src/lib/process-tree-termination.js +17 -1
- package/src/lib/skill-mcp.js +65 -4
- package/src/lib/web-fetch.js +4 -4
- package/src/runtime/agent-runtime.js +61 -8
- package/src/runtime/mcp-config.js +235 -28
- package/src/workers/background-agent-worker.js +492 -71
- package/src/assets/web-panel/assets/MarkdownRenderer-Bf3DEqP6.js +0 -1
- package/src/assets/web-panel/assets/Projects-08xUDZGt.js +0 -1
- package/src/assets/web-panel/assets/Tasks-CEYFJwmr.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DEMblAIm.js +0 -1
- package/src/assets/web-panel/assets/index-BTvq-36D.js +0 -1
- package/src/assets/web-panel/assets/index-hUpvk6Jl.js +0 -1
package/src/commands/agent.js
CHANGED
|
@@ -22,24 +22,89 @@ import {
|
|
|
22
22
|
enforceSandboxFailClosed,
|
|
23
23
|
} from "../lib/agent-sandbox.js";
|
|
24
24
|
import { appendSecurityAuditEvent } from "../lib/security-audit.js";
|
|
25
|
+
import {
|
|
26
|
+
agentPrintArgument,
|
|
27
|
+
canonicalizeBackgroundSessionArgv,
|
|
28
|
+
captureCommandArgvGrammar,
|
|
29
|
+
transformBackgroundLaunchArgv,
|
|
30
|
+
} from "../lib/background-command-argv.js";
|
|
25
31
|
|
|
26
32
|
/**
|
|
27
33
|
* Resolve + validate `--add-dir` values into absolute, existing, de-duped
|
|
28
|
-
* directories.
|
|
29
|
-
*
|
|
34
|
+
* directories. Relative paths resolve against the invocation cwd. When the
|
|
35
|
+
* session owns a worktree, paths inside the original repository are remapped
|
|
36
|
+
* to the same repo-relative location in that worktree; explicit external roots
|
|
37
|
+
* remain shared and can be surfaced with a warning.
|
|
30
38
|
*
|
|
31
39
|
* @param {string[]} [rawDirs]
|
|
40
|
+
* @param {{cwd?:string, worktree?:object|null, warnOnExternalShare?:boolean}} [options]
|
|
32
41
|
* @returns {string[]} absolute directory paths
|
|
33
42
|
*/
|
|
34
|
-
export function resolveAddDirs(rawDirs) {
|
|
43
|
+
export function resolveAddDirs(rawDirs, options = {}) {
|
|
44
|
+
const cwd = options.cwd || process.cwd();
|
|
45
|
+
const worktree = options.worktree || null;
|
|
46
|
+
const realpath = fs.realpathSync.native || fs.realpathSync;
|
|
47
|
+
const within = (root, candidate) => {
|
|
48
|
+
const relative = path.relative(root, candidate);
|
|
49
|
+
return (
|
|
50
|
+
relative === "" ||
|
|
51
|
+
(relative !== ".." &&
|
|
52
|
+
!relative.startsWith(`..${path.sep}`) &&
|
|
53
|
+
!path.isAbsolute(relative))
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
let worktreeScope = null;
|
|
57
|
+
if (worktree) {
|
|
58
|
+
try {
|
|
59
|
+
worktreeScope = {
|
|
60
|
+
repoRoot: realpath(worktree.repoRoot),
|
|
61
|
+
path: realpath(worktree.path),
|
|
62
|
+
};
|
|
63
|
+
} catch (error) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`--add-dir: background worktree identity is unavailable (${error.message})`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
35
69
|
const out = [];
|
|
70
|
+
const seen = new Set();
|
|
36
71
|
for (const d of rawDirs || []) {
|
|
37
|
-
const abs = path.resolve(
|
|
72
|
+
const abs = path.resolve(cwd, d);
|
|
38
73
|
try {
|
|
39
|
-
if (fs.existsSync(abs)
|
|
40
|
-
if (!out.includes(abs)) out.push(abs);
|
|
41
|
-
} else {
|
|
74
|
+
if (!fs.existsSync(abs) || !fs.statSync(abs).isDirectory()) {
|
|
42
75
|
process.stderr.write(`--add-dir: skipping non-directory "${d}"\n`);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
let target = realpath(abs);
|
|
79
|
+
let sharedExternal = false;
|
|
80
|
+
if (worktreeScope) {
|
|
81
|
+
const sourceReal = target;
|
|
82
|
+
if (within(worktreeScope.repoRoot, sourceReal)) {
|
|
83
|
+
const relative = path.relative(worktreeScope.repoRoot, sourceReal);
|
|
84
|
+
const mapped = path.resolve(worktree.path, relative);
|
|
85
|
+
if (!fs.existsSync(mapped) || !fs.statSync(mapped).isDirectory()) {
|
|
86
|
+
process.stderr.write(
|
|
87
|
+
`--add-dir: skipping "${d}" because its isolated worktree path does not exist\n`,
|
|
88
|
+
);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const mappedReal = realpath(mapped);
|
|
92
|
+
target = mappedReal;
|
|
93
|
+
sharedExternal = !within(worktreeScope.path, mappedReal);
|
|
94
|
+
} else {
|
|
95
|
+
sharedExternal = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (sharedExternal && options.warnOnExternalShare) {
|
|
99
|
+
process.stderr.write(
|
|
100
|
+
`warning: --add-dir "${d}" remains a shared external root outside the background worktree.\n`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const identity =
|
|
104
|
+
process.platform === "win32" ? target.toLowerCase() : target;
|
|
105
|
+
if (!seen.has(identity)) {
|
|
106
|
+
seen.add(identity);
|
|
107
|
+
out.push(target);
|
|
43
108
|
}
|
|
44
109
|
} catch {
|
|
45
110
|
process.stderr.write(`--add-dir: skipping unreadable "${d}"\n`);
|
|
@@ -220,6 +285,10 @@ export function registerAgentCommand(program) {
|
|
|
220
285
|
"--worktree",
|
|
221
286
|
"Run this session in a fresh git worktree (isolated branch; auto-removed when the session changes nothing)",
|
|
222
287
|
)
|
|
288
|
+
.option(
|
|
289
|
+
"--no-worktree",
|
|
290
|
+
"Background Git task: explicitly share the current work tree (intended for read-only tasks; writable runs are not isolated)",
|
|
291
|
+
)
|
|
223
292
|
.option(
|
|
224
293
|
"--unattended",
|
|
225
294
|
"Enable fail-closed shell action policy for scheduled/event-driven runs",
|
|
@@ -554,6 +623,43 @@ export function registerAgentCommand(program) {
|
|
|
554
623
|
if (options.projectMcp === true) {
|
|
555
624
|
process.env.CC_PROJECT_MCP = "1";
|
|
556
625
|
}
|
|
626
|
+
const backgroundRequested =
|
|
627
|
+
options.background === true || options.bg === true;
|
|
628
|
+
const invocationCwd = process.cwd();
|
|
629
|
+
let worktreeDecision = {
|
|
630
|
+
enabled: false,
|
|
631
|
+
source: "foreground-default",
|
|
632
|
+
reason: "worktree not requested",
|
|
633
|
+
repoRoot: null,
|
|
634
|
+
};
|
|
635
|
+
if (options.worktree !== undefined || backgroundRequested) {
|
|
636
|
+
try {
|
|
637
|
+
const { resolveBackgroundWorktreePolicy } =
|
|
638
|
+
await import("../lib/background-worktree-policy.js");
|
|
639
|
+
worktreeDecision = resolveBackgroundWorktreePolicy({
|
|
640
|
+
background: backgroundRequested,
|
|
641
|
+
worktree: options.worktree,
|
|
642
|
+
inputFormat: options.inputFormat,
|
|
643
|
+
permissionMode: options.permissionMode,
|
|
644
|
+
cwd: invocationCwd,
|
|
645
|
+
});
|
|
646
|
+
} catch (error) {
|
|
647
|
+
process.stderr.write(
|
|
648
|
+
`background worktree policy failed: ${error.message}\n`,
|
|
649
|
+
);
|
|
650
|
+
process.exit(1);
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if (
|
|
655
|
+
backgroundRequested &&
|
|
656
|
+
worktreeDecision.source === "explicit-disable" &&
|
|
657
|
+
String(options.inputFormat || "text").toLowerCase() !== "stream-json"
|
|
658
|
+
) {
|
|
659
|
+
process.stderr.write(
|
|
660
|
+
"warning: --no-worktree shares the current work tree with a background agent; worktree isolation is disabled.\n",
|
|
661
|
+
);
|
|
662
|
+
}
|
|
557
663
|
// --worktree (Claude-Code 2.1.171 parity): run THIS session in a fresh
|
|
558
664
|
// git worktree — edits land on an isolated branch, the main working
|
|
559
665
|
// tree (and parallel sessions) stay untouched. chdir BEFORE everything
|
|
@@ -567,19 +673,39 @@ export function registerAgentCommand(program) {
|
|
|
567
673
|
// _finishWorktree(). Null unless --worktree is active + hooks loaded.
|
|
568
674
|
let _worktreeSettingsHooks = null;
|
|
569
675
|
let _worktreeAsyncSupervisor = null;
|
|
570
|
-
|
|
676
|
+
const _finishWorktreeSync = () => {
|
|
677
|
+
if (!_worktree || _worktreeFinished || _worktreeTransferred) {
|
|
678
|
+
return null;
|
|
679
|
+
}
|
|
680
|
+
_worktreeFinished = true;
|
|
681
|
+
try {
|
|
682
|
+
process.chdir(_worktree.repoRoot); // release the dir before removal
|
|
683
|
+
return _finishAgentWorktreeFn(_worktree);
|
|
684
|
+
} catch {
|
|
685
|
+
return null; // keep silently — never block exit/error reporting
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
if (worktreeDecision.enabled) {
|
|
571
689
|
try {
|
|
572
690
|
const { setupAgentWorktree, finishAgentWorktree } =
|
|
573
691
|
await import("../lib/agent-worktree.js");
|
|
574
692
|
_finishAgentWorktreeFn = finishAgentWorktree;
|
|
693
|
+
const detectedRepoRoot = worktreeDecision.repoRoot || invocationCwd;
|
|
575
694
|
const worktreeCwd =
|
|
576
695
|
process.platform === "darwin"
|
|
577
|
-
?
|
|
578
|
-
:
|
|
579
|
-
_worktree = setupAgentWorktree({
|
|
696
|
+
? detectedRepoRoot.replace(/^\/private\//, "/")
|
|
697
|
+
: detectedRepoRoot;
|
|
698
|
+
_worktree = setupAgentWorktree({
|
|
699
|
+
cwd: worktreeCwd,
|
|
700
|
+
...(backgroundRequested ? { requireCleanSource: true } : {}),
|
|
701
|
+
});
|
|
702
|
+
// Register cleanup immediately after creation. In particular,
|
|
703
|
+
// process.chdir() can fail on Windows when the new path is raced,
|
|
704
|
+
// locked, or denied; that must not leak the worktree + branch.
|
|
705
|
+
process.on("exit", _finishWorktreeSync);
|
|
580
706
|
process.chdir(_worktree.path);
|
|
581
707
|
process.stderr.write(
|
|
582
|
-
|
|
708
|
+
`${worktreeDecision.source === "background-git-default" ? "worktree (background default)" : "worktree"}: ${_worktree.path} (branch ${_worktree.branch})\n`,
|
|
583
709
|
);
|
|
584
710
|
// WorktreeCreate lifecycle hook (observe-only, best-effort): a fresh
|
|
585
711
|
// isolated worktree just appeared — let automation react (register it
|
|
@@ -618,37 +744,28 @@ export function registerAgentCommand(program) {
|
|
|
618
744
|
} catch {
|
|
619
745
|
/* worktree lifecycle hooks are best-effort — never block */
|
|
620
746
|
}
|
|
621
|
-
// The worktree is created BEFORE flag validation, and several
|
|
622
|
-
// `process.exit(1)` guards below (plus any future ones) would skip the
|
|
623
|
-
// normal cleanup and orphan an empty worktree + branch on disk. A sync
|
|
624
|
-
// exit handler guarantees the auto-removable worktree is cleaned up on
|
|
625
|
-
// EVERY exit path (finishAgentWorktree is synchronous). Deduped with
|
|
626
|
-
// the normal async _finishWorktree() via _worktreeFinished.
|
|
627
|
-
process.on("exit", () => {
|
|
628
|
-
if (!_worktree || _worktreeFinished || _worktreeTransferred) {
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
_worktreeFinished = true;
|
|
632
|
-
try {
|
|
633
|
-
process.chdir(_worktree.repoRoot);
|
|
634
|
-
_finishAgentWorktreeFn(_worktree);
|
|
635
|
-
} catch {
|
|
636
|
-
/* never block exit */
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
747
|
} catch (err) {
|
|
748
|
+
const fin = _finishWorktreeSync();
|
|
640
749
|
process.stderr.write(`--worktree failed: ${err.message}\n`);
|
|
750
|
+
if (err.retainedWorktree?.path) {
|
|
751
|
+
process.stderr.write(
|
|
752
|
+
`worktree recovery required: retained ${err.retainedWorktree.path} ` +
|
|
753
|
+
`(branch ${err.retainedWorktree.branch || "unknown"}); ` +
|
|
754
|
+
`cleanup failed: ${err.worktreeCleanupError?.message || "unknown error"}. ` +
|
|
755
|
+
`Inspect it with git -C "${err.retainedWorktree.repoRoot}" worktree list before manual cleanup.\n`,
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
if (fin?.removed) {
|
|
759
|
+
process.stderr.write(`worktree removed (${fin.reason}).\n`);
|
|
760
|
+
}
|
|
641
761
|
process.exit(1);
|
|
762
|
+
return;
|
|
642
763
|
}
|
|
643
764
|
}
|
|
644
765
|
const _finishWorktree = async () => {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
}
|
|
648
|
-
_worktreeFinished = true;
|
|
766
|
+
const fin = _finishWorktreeSync();
|
|
767
|
+
if (!fin) return;
|
|
649
768
|
try {
|
|
650
|
-
process.chdir(_worktree.repoRoot); // release the dir before removal
|
|
651
|
-
const fin = _finishAgentWorktreeFn(_worktree);
|
|
652
769
|
process.stderr.write(
|
|
653
770
|
fin.removed
|
|
654
771
|
? `worktree removed (${fin.reason}).\n`
|
|
@@ -738,6 +855,7 @@ export function registerAgentCommand(program) {
|
|
|
738
855
|
process.stderr.write(
|
|
739
856
|
"No previous session to continue. Start one with `cc agent`.\n",
|
|
740
857
|
);
|
|
858
|
+
await _finishWorktree();
|
|
741
859
|
process.exit(1);
|
|
742
860
|
}
|
|
743
861
|
}
|
|
@@ -784,6 +902,7 @@ export function registerAgentCommand(program) {
|
|
|
784
902
|
process.stderr.write(
|
|
785
903
|
"--include-partial-messages requires --output-format stream-json.\n",
|
|
786
904
|
);
|
|
905
|
+
await _finishWorktree();
|
|
787
906
|
process.exit(1);
|
|
788
907
|
}
|
|
789
908
|
|
|
@@ -885,8 +1004,22 @@ export function registerAgentCommand(program) {
|
|
|
885
1004
|
process.exit(6);
|
|
886
1005
|
}
|
|
887
1006
|
|
|
888
|
-
// Extra workspace roots (--add-dir)
|
|
889
|
-
|
|
1007
|
+
// Extra workspace roots (--add-dir) — shared by headless + interactive.
|
|
1008
|
+
// Resolve against the invocation cwd (before chdir), then remap any path
|
|
1009
|
+
// inside the original repository to the isolated worktree counterpart.
|
|
1010
|
+
let additionalDirectories;
|
|
1011
|
+
try {
|
|
1012
|
+
additionalDirectories = resolveAddDirs(options.addDir, {
|
|
1013
|
+
cwd: invocationCwd,
|
|
1014
|
+
worktree: _worktree,
|
|
1015
|
+
warnOnExternalShare: backgroundRequested && Boolean(_worktree),
|
|
1016
|
+
});
|
|
1017
|
+
} catch (error) {
|
|
1018
|
+
process.stderr.write(`Error: ${error.message}\n`);
|
|
1019
|
+
await _finishWorktree();
|
|
1020
|
+
process.exit(1);
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
890
1023
|
|
|
891
1024
|
// --image <path> (repeatable): read into {mediaType, base64} for the
|
|
892
1025
|
// headless prompt's vision input. A bad extension fails loudly here
|
|
@@ -897,6 +1030,7 @@ export function registerAgentCommand(program) {
|
|
|
897
1030
|
images = resolveImages(options.image);
|
|
898
1031
|
} catch (err) {
|
|
899
1032
|
process.stderr.write(`Error: ${err.message}\n`);
|
|
1033
|
+
await _finishWorktree();
|
|
900
1034
|
process.exit(1);
|
|
901
1035
|
}
|
|
902
1036
|
}
|
|
@@ -1137,6 +1271,7 @@ export function registerAgentCommand(program) {
|
|
|
1137
1271
|
process.stderr.write(
|
|
1138
1272
|
`Invalid --input-format "${options.inputFormat}". Expected: text | stream-json.\n`,
|
|
1139
1273
|
);
|
|
1274
|
+
await _finishWorktree();
|
|
1140
1275
|
process.exit(1);
|
|
1141
1276
|
}
|
|
1142
1277
|
|
|
@@ -1164,39 +1299,39 @@ export function registerAgentCommand(program) {
|
|
|
1164
1299
|
// Commander canonicalizes the dual long-option declaration
|
|
1165
1300
|
// `--bg, --background` to `options.background`; retain `options.bg` for
|
|
1166
1301
|
// callers/tests that invoke the action with a pre-normalized object.
|
|
1167
|
-
const background =
|
|
1302
|
+
const background = backgroundRequested;
|
|
1168
1303
|
if (background && !prompt) {
|
|
1169
1304
|
process.stderr.write(
|
|
1170
1305
|
"--bg requires a task via positional text, -p, or piped stdin.\n",
|
|
1171
1306
|
);
|
|
1307
|
+
await _finishWorktree();
|
|
1172
1308
|
process.exitCode = 1;
|
|
1173
1309
|
return;
|
|
1174
1310
|
}
|
|
1175
1311
|
|
|
1176
1312
|
if (prompt) {
|
|
1177
1313
|
if (background) {
|
|
1178
|
-
const {
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
arg === "--session" ||
|
|
1192
|
-
arg === "--resume" ||
|
|
1193
|
-
arg === "--continue" ||
|
|
1194
|
-
arg === "-c",
|
|
1195
|
-
);
|
|
1314
|
+
const {
|
|
1315
|
+
launchBackgroundAgent,
|
|
1316
|
+
buildFollowUpArgv,
|
|
1317
|
+
insertArgumentsBeforeOptionTerminator,
|
|
1318
|
+
isBackgroundWorkerStartedError,
|
|
1319
|
+
} = await import("../lib/background-agent-supervisor.js");
|
|
1320
|
+
const { optionSpecs, commandNames } =
|
|
1321
|
+
captureCommandArgvGrammar(command);
|
|
1322
|
+
let childArgv = transformBackgroundLaunchArgv(process.argv.slice(2), {
|
|
1323
|
+
directories: additionalDirectories,
|
|
1324
|
+
optionSpecs,
|
|
1325
|
+
commandNames,
|
|
1326
|
+
});
|
|
1196
1327
|
const sessionId =
|
|
1197
1328
|
options.session ||
|
|
1198
1329
|
`session-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
|
|
1199
|
-
|
|
1330
|
+
childArgv = canonicalizeBackgroundSessionArgv(childArgv, {
|
|
1331
|
+
sessionId,
|
|
1332
|
+
optionSpecs,
|
|
1333
|
+
commandNames,
|
|
1334
|
+
});
|
|
1200
1335
|
// Follow-up template for interactive attach: same flags/session,
|
|
1201
1336
|
// minus the first turn's prompt tokens (built BEFORE any piped
|
|
1202
1337
|
// prompt is appended below). The worker appends -p <text> per turn.
|
|
@@ -1204,28 +1339,55 @@ export function registerAgentCommand(program) {
|
|
|
1204
1339
|
positionalTokens: Array.isArray(task) ? task : [],
|
|
1205
1340
|
printValue:
|
|
1206
1341
|
typeof options.print === "string" ? options.print : null,
|
|
1342
|
+
optionSpecs,
|
|
1343
|
+
commandNames,
|
|
1207
1344
|
});
|
|
1208
1345
|
const promptWasPiped =
|
|
1209
1346
|
positional.length === 0 &&
|
|
1210
1347
|
!(typeof options.print === "string" && options.print.trim());
|
|
1211
|
-
if (promptWasPiped)
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1348
|
+
if (promptWasPiped) {
|
|
1349
|
+
// A piped prompt beginning with `-` must remain data, never become
|
|
1350
|
+
// a second-pass Commander option in the detached child.
|
|
1351
|
+
childArgv = insertArgumentsBeforeOptionTerminator(followUpArgv, [
|
|
1352
|
+
agentPrintArgument(prompt),
|
|
1353
|
+
]);
|
|
1354
|
+
}
|
|
1355
|
+
let state;
|
|
1356
|
+
try {
|
|
1357
|
+
state = launchBackgroundAgent({
|
|
1358
|
+
argv: childArgv,
|
|
1359
|
+
cwd: _worktree ? _worktree.path : process.cwd(),
|
|
1360
|
+
sessionId,
|
|
1361
|
+
title: prompt.slice(0, 100),
|
|
1362
|
+
followUpArgv,
|
|
1363
|
+
worktree: _worktree,
|
|
1364
|
+
governance: {
|
|
1365
|
+
permissionMode: options.permissionMode || "default",
|
|
1366
|
+
resourceBudget: {
|
|
1367
|
+
maxTurns: options.maxTurns
|
|
1368
|
+
? parseInt(options.maxTurns, 10)
|
|
1369
|
+
: null,
|
|
1370
|
+
maxCostUsd,
|
|
1371
|
+
},
|
|
1226
1372
|
},
|
|
1227
|
-
}
|
|
1228
|
-
})
|
|
1373
|
+
});
|
|
1374
|
+
} catch (error) {
|
|
1375
|
+
if (_worktree && isBackgroundWorkerStartedError(error)) {
|
|
1376
|
+
// Spawn succeeded: the worker may already have this path as cwd.
|
|
1377
|
+
// Transfer ownership and retain it even though the launcher's
|
|
1378
|
+
// final state write/listener setup failed.
|
|
1379
|
+
_worktreeTransferred = true;
|
|
1380
|
+
_worktreeFinished = true;
|
|
1381
|
+
try {
|
|
1382
|
+
process.chdir(_worktree.repoRoot);
|
|
1383
|
+
} catch {
|
|
1384
|
+
/* ownership is transferred; never race-delete a live cwd */
|
|
1385
|
+
}
|
|
1386
|
+
} else {
|
|
1387
|
+
await _finishWorktree();
|
|
1388
|
+
}
|
|
1389
|
+
throw error;
|
|
1390
|
+
}
|
|
1229
1391
|
if (_worktree) {
|
|
1230
1392
|
// Ownership moves to the persisted background session only after
|
|
1231
1393
|
// the detached worker launched successfully. The parent exit hook
|
package/src/commands/agents.js
CHANGED
|
@@ -118,6 +118,12 @@ export function registerAgentsCommand(program) {
|
|
|
118
118
|
if (options.json) console.log(JSON.stringify(state, null, 2));
|
|
119
119
|
else if (state.stopped)
|
|
120
120
|
logger.log(chalk.green(`Stopped background agent ${id}`));
|
|
121
|
+
else if (state.stopPending)
|
|
122
|
+
logger.log(
|
|
123
|
+
chalk.yellow(
|
|
124
|
+
`Stop pending for background agent ${id} (${state.stopPendingReason})`,
|
|
125
|
+
),
|
|
126
|
+
);
|
|
121
127
|
else logger.log(chalk.gray(`${id} is already ${state.status}`));
|
|
122
128
|
} catch (error) {
|
|
123
129
|
logger.error(chalk.red(error.message));
|
|
@@ -10,6 +10,10 @@ import {
|
|
|
10
10
|
import { readSessionHostResumeState } from "../lib/session-host-snapshot.js";
|
|
11
11
|
import executionBroker from "../lib/process-execution-broker/index.js";
|
|
12
12
|
|
|
13
|
+
export function buildBackgroundDispatchArgs(prompt) {
|
|
14
|
+
return ["agent", "--bg", `--print=${prompt}`];
|
|
15
|
+
}
|
|
16
|
+
|
|
13
17
|
function formatAge(ms) {
|
|
14
18
|
const n = Math.max(0, Math.round(Number(ms || 0) / 1000));
|
|
15
19
|
if (n < 60) return `${n}s`;
|
|
@@ -746,7 +750,7 @@ async function runDashboardView(options = {}) {
|
|
|
746
750
|
dispatchAgent: async (text) => {
|
|
747
751
|
const child = executionBroker.spawn(
|
|
748
752
|
process.execPath,
|
|
749
|
-
[BIN_PATH,
|
|
753
|
+
[BIN_PATH, ...buildBackgroundDispatchArgs(text)],
|
|
750
754
|
{
|
|
751
755
|
detached: true,
|
|
752
756
|
stdio: "ignore",
|
|
@@ -1038,6 +1042,12 @@ export function registerBackgroundSessionCommands(program) {
|
|
|
1038
1042
|
for (const result of results) {
|
|
1039
1043
|
if (result.stopped) {
|
|
1040
1044
|
logger.log(chalk.green(`Stopped background agent ${result.id}`));
|
|
1045
|
+
} else if (result.stopPending) {
|
|
1046
|
+
logger.log(
|
|
1047
|
+
chalk.yellow(
|
|
1048
|
+
`Stop pending for background agent ${result.id} (${result.stopPendingReason})`,
|
|
1049
|
+
),
|
|
1050
|
+
);
|
|
1041
1051
|
} else {
|
|
1042
1052
|
logger.log(chalk.gray(`${result.id} is already ${result.status}`));
|
|
1043
1053
|
}
|