chainlesschain 0.162.45 → 0.162.47
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 +2 -2
- package/src/assets/web-panel/assets/{AIOps-D-W6s4eA.js → AIOps-BBjFOl4N.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-nPOyfwP_.js → ActionButton-B7A6lHz3.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DoX0H6wa.js → Analytics-DZgNxdvw.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BYNnmmUE.js → AppLayout-CFbPWVnh.js} +3 -3
- package/src/assets/web-panel/assets/{Audit-AjglOteL.js → Audit-Ao9RxevG.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DT38xAKk.js → Backup-B1AGqahI.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DT1pD4sT.js → BaseInput-M01bA2JM.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Z77BT13i.js → Chat-CC0Gmd9k.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DKe4yjqq.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-CVOMmTDm.js → Checkbox-CpEqAg5P.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Bqy11vCf.js → Codegen-9c1H2P_L.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C3A1d5Wt.js → Col-sH2Obo8q.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D2q6UNaX.js → Community-DyzjH37r.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-C2701nAm.js → Compact-DsNatLOG.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-SJnaA5oN.js → Compliance-B3ws7qwL.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BvTYuhJy.js → Cowork-odGfUMsv.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-sJ-9lLUV.js → Cron-bxO6NLDR.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CStGE_K9.js → Crosschain-xHCPQpE9.js} +1 -1
- package/src/assets/web-panel/assets/{DID-JY0Kx-7a.js → DID-3l7HvzNC.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BiZEZPRN.js → Dashboard-BNzT5YBj.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DK2BszlZ.js → Dropdown-DZynMYpG.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DtjOYS0Q.js → EmailListRenderer-6HZ2XA9g.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-D2EI2B5E.js → FamilyGuardDashboard-DqzqNzRP.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CebAtHrY.js → Federation-CI7lf1MF.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Bd8WNQLm.js → FormItemContext-D2m3YZ-k.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-tH3zcpN9.js → GenericCardRenderer-Bwcc-9EB.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DARoXdm7.js → Git-C7qN3bA1.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-gcKIyn7g.js → Governance-JfuugS1c.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Rh4pllPC.js → Inference-BNsHm2IH.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Cvh73WwA.js → KnowledgeGraph-CTH_FiL1.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BBZSagwy.js → Logs-CxcfBcmS.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-e5C7xHES.js → Marketplace-B9PU3qlx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BzfXvajQ.js → McpTools-BlvQpnvj.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-C3ZgSBrL.js → Memory-Diiig9gp.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BYVobYJJ.js → MobileBridge-CGfUn4xi.js} +2 -2
- package/src/assets/web-panel/assets/{MobileProjects-Bl8xCXs4.js → MobileProjects-CFvH6A9E.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BxNytLEb.js → Mtc-CT_1x1Gr.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-BUadScwJ.js → MtcAudit-DPAjU1Qn.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BWZmAn6M.js → Multisig-nks2HW0C.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B4eau0Yo.js → NLProgramming-BWd74a91.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-eHe1Jd1n.js → Notes-B342yG3u.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DFMSI_xu.js → NotificationSettings-C9kjn20B.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Ctejeurt.js → OrderTableRenderer-DKQ3FPUN.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-M_NYVPks.js → Organization-Ch-qkiyP.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bi-TzxkX.js → Overflow-DeV865TY.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-vtorIyuM.js → P2P-9pzyAAE1.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-D9I3WUUZ.js → PdhVaultBrowser-oGgQiWpR.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-YFbIKLZw.js → Permissions-MPDfvUva.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-JM8yN0w0.js → PersonalDataHub-Es8GFY4_.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-Cyvwlqpr.js → Pipeline-R10lJHtN.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CIKHwg7m.js → Privacy-8YMg8xrV.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Bj6-CmbC.js → ProjectInit-B-L3DMBv.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CBnTXhIt.js → ProjectSettings-pR4l7GCe.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-B3CwPTNd.js → Projects-5vaXw-7d.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-dtUZaXuY.js → Providers-C_E-G6Bh.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BWzt81Dm.js → QuickAsk-CM-FSYbK.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CToDb_n9.js → Recommend-DcwFptAP.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-B6MCFsXH.js → Reputation-DJKj97w-.js} +1 -1
- package/src/assets/web-panel/assets/{Row-CipchQUs.js → Row-BfI2mGUm.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CR3mpmuE.js → RssFeed-D6tzthT0.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DRvRD7_k.js → Search-CkxIxA5y.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Bv1bEvfO.js → Security-BeTfFgoX.js} +3 -3
- package/src/assets/web-panel/assets/{Services-BLAljjtu.js → Services-BahX89X1.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BRFNIS9s.js → Skeleton-55na3k97.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-B6dEwkkO.js → Skills-DZ-dxsiR.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-A97O6hQJ.js → Sla-BUTClrI0.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DNBeqO5l.js → SpeechSettings-C0c2AmSU.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-C61PTeaN.js → SyncSettings-Vr5zzdPz.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-C8q-8JXF.js → Tasks-BrouZA03.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-R-4ZBAPY.js → Templates-DnaU_7nb.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-dRpKvdmN.js → Tenant-1dw4SFBA.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-egMhD-wn.js → Terminal-Pe1vBvOm.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BbXUD3AZ.js → TimelineRenderer-dDxMvAvM.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CuYIAO1f.js → Tokens-CPJMLjkE.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-bt_5ffBh.js → Trigger-B1IWp6HK.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-rk4LCtlg.js → Trust-iswzFvfA.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Bgf8zhuS.js → UkeySign-CuMmDUvU.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-B_D_kcq5.js → VideoEditing-BguHSBQ5.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BuhroOcU.js → Wallet-CW4PFXSw.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DNVp_EWD.js → WebAuthn-YOO0lqjJ.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-C94Nr2Yq.js → WorkflowEditor-A_z3yLuG.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CqvcO82L.js → chat-BSHj9uiJ.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CiHv7zLX.js → colors-D7gA-kvN.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BbL_7DRy.js → compact-item-ChDt0wUv.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BcnUkPGe.js → createContext-5UAhDsNU.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-NW6VMT5L.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-bKZM79uJ.js → hasIn-7ysmGHSf.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0Dew6UJ.js → index--UCy6rsJ.js} +1 -1
- package/src/assets/web-panel/assets/index-A6oY6RQQ.js +1 -0
- package/src/assets/web-panel/assets/{index-sdSZZzwh.js → index-B6OX-6N1.js} +1 -1
- package/src/assets/web-panel/assets/{index-UrCGcZXp.js → index-BGlolJwU.js} +1 -1
- package/src/assets/web-panel/assets/{index-kHUuRAFp.js → index-BLoQ2FkI.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5X8cqw-.js → index-BTzZlYgQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Zxnsweba.js → index-B_xBUmAE.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dpb_Zh3w.js → index-BcPEgfGF.js} +1 -1
- package/src/assets/web-panel/assets/{index-ABAWaz7Y.js → index-BhsGGFa4.js} +1 -1
- package/src/assets/web-panel/assets/{index-Drdlb5iB.js → index-BoCy4bxa.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWPLkrPr.js → index-BzPxVTI2.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1b8TGYq.js → index-C4nXq9eB.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bfcq_Svy.js → index-C62SpQws.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bh9TSxy7.js → index-C93TfkpQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAayTu3W.js → index-CGVsJplV.js} +1 -1
- package/src/assets/web-panel/assets/{index-ByEejvcB.js → index-CHdEHlNY.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPJ4NWCv.js → index-COwKdUAS.js} +1 -1
- package/src/assets/web-panel/assets/{index-2nrwvHPn.js → index-Cl10KB1R.js} +1 -1
- package/src/assets/web-panel/assets/index-Cn2g4vqt.js +1 -0
- package/src/assets/web-panel/assets/{index-vzVBm4mg.js → index-CylU_ot3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNBdA_cQ.js → index-D-pJNNc5.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYH3St42.js → index-D9R6sJiP.js} +1 -1
- package/src/assets/web-panel/assets/{index-B76qMGe0.js → index-DSRnnGez.js} +3 -3
- package/src/assets/web-panel/assets/{index-Bd0u4iTg.js → index-Db4hf2WV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPHskdVZ.js → index-DcKVERvm.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlIYy94Y.js → index-DfjMbFZA.js} +1 -1
- package/src/assets/web-panel/assets/{index-J8Xba8Zt.js → index-Dj3IHF24.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1StZUmz.js → index-Dq4fd0cB.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cc48TfA8.js → index-DslmMjVo.js} +1 -1
- package/src/assets/web-panel/assets/{index-Kl_dtIkL.js → index-DttrXREN.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-jqR16_.js → index-HUiKkQOf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BySbK7vA.js → index-NtFFgW-x.js} +1 -1
- package/src/assets/web-panel/assets/{index-JteeOvFE.js → index-QPBJl4wk.js} +1 -1
- package/src/assets/web-panel/assets/{index-AJLQ9KfF.js → index-WM_jYoK8.js} +1 -1
- package/src/assets/web-panel/assets/{index-Csgtimo8.js → index-ZOmjAajS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQonLmOf.js → index-_8xZf-zU.js} +1 -1
- package/src/assets/web-panel/assets/{index-Kt6y6Hh5.js → index-pk9WOpeN.js} +1 -1
- package/src/assets/web-panel/assets/{index-SeP48n4C.js → index-s_MPIulF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSzQlPjx.js → index-trVj-RG1.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Cg2ZQCW2.js → initDefaultProps-BcWdcWH2.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CVup4XZf.js → motion-D-GC86LC.js} +1 -1
- package/src/assets/web-panel/assets/{move-0we4XeEJ.js → move-7N01T4vz.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DNvkWjsk.js → omit-B8_G8lAi.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DNGWkffo.js → pickAttrs-BeEwgLq8.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DdMP7Lk2.js → placementArrow-CiQwkkN_.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CgCiGZ6t.js → responsiveObserve-CtfIP2YM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CQxOWXtr.js → slide-DnA-Z3fK.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BVYop9K6.js → statusUtils-Ckaf7hg9.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BTkUPq_y.js → styleChecker-CE7d6-LQ.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CKncli3p.js → useFlexGapSupport-BBC2EqTi.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-B7k6cPxd.js → useFs-BWncdesy.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CiVRczRO.js → usePersonalDataHub-BVJgKdiT.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CPueAEhr.js → vnode-CdZoGwk8.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BhzuJF_P.js → zoom-8BsyiHWV.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +44 -30
- package/src/commands/hub.js +87 -0
- package/src/harness/mcp-client.js +86 -1
- package/src/lib/auto-checkpoint-default.js +49 -0
- package/src/lib/personal-data-hub-wiring.js +44 -2
- package/src/lib/repl-completer.js +6 -3
- package/src/lib/sensitive-file-guard.js +58 -0
- package/src/lib/skill-loader.js +43 -7
- package/src/lib/sub-agent-context.js +3 -0
- package/src/repl/agent-repl.js +27 -1
- package/src/runtime/agent-core.js +55 -0
- package/src/runtime/headless-stream.js +36 -4
- package/src/runtime/mcp-config.js +19 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-C1MKMzjB.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BSbU0obw.js +0 -1
- package/src/assets/web-panel/assets/index-DHgbmZ-Y.js +0 -1
- package/src/assets/web-panel/assets/index-pr3q7Jlo.js +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sensitive-file write guard — Claude-Code 2.1.160 parity ("prompts before
|
|
3
|
+
* writing to shell startup files").
|
|
4
|
+
*
|
|
5
|
+
* Writing a shell startup file, PowerShell profile, or git hook plants code
|
|
6
|
+
* that EXECUTES on the user's next shell/commit — a step up from a normal
|
|
7
|
+
* edit, so even pre-authorized edit flows must confirm first. The check is
|
|
8
|
+
* name-based (basename / well-known relative fragments), deliberately
|
|
9
|
+
* conservative: build configs like Makefile/package.json are everyday edits
|
|
10
|
+
* and are NOT flagged (false-positive fatigue would teach users to blind-OK).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const SHELL_STARTUP_NAMES = new Set([
|
|
14
|
+
".bashrc",
|
|
15
|
+
".bash_profile",
|
|
16
|
+
".bash_login",
|
|
17
|
+
".bash_logout",
|
|
18
|
+
".profile",
|
|
19
|
+
".zshrc",
|
|
20
|
+
".zshenv",
|
|
21
|
+
".zprofile",
|
|
22
|
+
".zlogin",
|
|
23
|
+
".zlogout",
|
|
24
|
+
".cshrc",
|
|
25
|
+
".tcshrc",
|
|
26
|
+
".kshrc",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
const POWERSHELL_PROFILE_RE = /(^|[\\/])(microsoft\.powershell_profile\.ps1|profile\.ps1)$/i;
|
|
30
|
+
const FISH_CONFIG_RE = /[\\/]fish[\\/]config\.fish$/i;
|
|
31
|
+
const GIT_HOOK_RE = /[\\/]\.git[\\/]hooks[\\/][^\\/]+$/i;
|
|
32
|
+
const HUSKY_HOOK_RE = /[\\/]\.husky[\\/](?!_)[^\\/]+$/i;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} targetPath path as the tool received it (rel or abs)
|
|
36
|
+
* @returns {string|null} human reason when sensitive, null otherwise
|
|
37
|
+
*/
|
|
38
|
+
export function sensitiveFileReason(targetPath) {
|
|
39
|
+
const p = String(targetPath || "");
|
|
40
|
+
if (!p) return null;
|
|
41
|
+
const base = p.replace(/\\/g, "/").split("/").pop() || "";
|
|
42
|
+
if (SHELL_STARTUP_NAMES.has(base)) {
|
|
43
|
+
return `shell startup file (${base}) — runs on the user's next shell`;
|
|
44
|
+
}
|
|
45
|
+
if (POWERSHELL_PROFILE_RE.test(p)) {
|
|
46
|
+
return "PowerShell profile — runs on the user's next PowerShell session";
|
|
47
|
+
}
|
|
48
|
+
if (FISH_CONFIG_RE.test(p)) {
|
|
49
|
+
return "fish shell config — runs on the user's next shell";
|
|
50
|
+
}
|
|
51
|
+
if (GIT_HOOK_RE.test(p)) {
|
|
52
|
+
return "git hook — executes on the user's next git operation";
|
|
53
|
+
}
|
|
54
|
+
if (HUSKY_HOOK_RE.test(p)) {
|
|
55
|
+
return "husky hook — executes on the user's next git operation";
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
package/src/lib/skill-loader.js
CHANGED
|
@@ -1,24 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Multi-layer skill loader for CLI
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 0 (lowest) bundled
|
|
6
|
-
* 1 marketplace
|
|
7
|
-
* 2 managed
|
|
8
|
-
* 3
|
|
4
|
+
* 6-layer priority system (highest wins on name collision):
|
|
5
|
+
* 0 (lowest) bundled — desktop-app-vue/.../skills/builtin/
|
|
6
|
+
* 1 marketplace — <userData>/marketplace/skills/
|
|
7
|
+
* 2 managed — <userData>/skills/
|
|
8
|
+
* 3 claude-user — ~/.claude/skills/ (Claude-Code 可移植)
|
|
9
|
+
* 4 claude-project — <projectRoot>/.claude/skills/ (Claude-Code 可移植)
|
|
10
|
+
* 5 (highest) workspace — <projectRoot>/.chainlesschain/skills/
|
|
11
|
+
*
|
|
12
|
+
* The two `claude-*` layers are Claude-Code portability (its 2.1.157
|
|
13
|
+
* ".claude/skills auto-load" behavior): a repo carrying Claude-Code skills
|
|
14
|
+
* works in cc unchanged — same SKILL.md format — while native
|
|
15
|
+
* `.chainlesschain/skills` still wins on name collisions.
|
|
9
16
|
*/
|
|
10
17
|
|
|
11
18
|
import fs from "fs";
|
|
19
|
+
import os from "os";
|
|
12
20
|
import path from "path";
|
|
13
21
|
import { fileURLToPath } from "url";
|
|
14
22
|
import { getElectronUserDataDir } from "./paths.js";
|
|
15
23
|
import { findProjectRoot } from "./project-detector.js";
|
|
24
|
+
import { findProjectRoot as findGitRoot } from "./project-instructions.js";
|
|
16
25
|
import { parseSkillMcpServers } from "./skill-mcp.js";
|
|
17
26
|
|
|
18
27
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
28
|
|
|
20
29
|
/** Layer names in priority order (lowest → highest) */
|
|
21
|
-
export const LAYER_NAMES = [
|
|
30
|
+
export const LAYER_NAMES = [
|
|
31
|
+
"bundled",
|
|
32
|
+
"marketplace",
|
|
33
|
+
"managed",
|
|
34
|
+
"claude-user",
|
|
35
|
+
"claude-project",
|
|
36
|
+
"workspace",
|
|
37
|
+
];
|
|
22
38
|
|
|
23
39
|
/**
|
|
24
40
|
* Simple YAML frontmatter parser (no dependencies)
|
|
@@ -230,7 +246,27 @@ export class CLISkillLoader {
|
|
|
230
246
|
exists: fs.existsSync(managedPath),
|
|
231
247
|
});
|
|
232
248
|
|
|
233
|
-
//
|
|
249
|
+
// Layers 3+4: Claude-Code portability — ~/.claude/skills + <root>/.claude/skills
|
|
250
|
+
const home = os.homedir() || "";
|
|
251
|
+
const claudeUserPath = home ? path.join(home, ".claude", "skills") : null;
|
|
252
|
+
layers.push({
|
|
253
|
+
layer: "claude-user",
|
|
254
|
+
path: claudeUserPath,
|
|
255
|
+
exists: Boolean(claudeUserPath && fs.existsSync(claudeUserPath)),
|
|
256
|
+
});
|
|
257
|
+
// Project base: .chainlesschain marker first, git root as fallback so a
|
|
258
|
+
// pure Claude-Code repo (no .chainlesschain/) still gets its skills.
|
|
259
|
+
const claudeBase = findProjectRoot() || findGitRoot(process.cwd());
|
|
260
|
+
const claudeProjectPath = claudeBase
|
|
261
|
+
? path.join(claudeBase, ".claude", "skills")
|
|
262
|
+
: null;
|
|
263
|
+
layers.push({
|
|
264
|
+
layer: "claude-project",
|
|
265
|
+
path: claudeProjectPath,
|
|
266
|
+
exists: Boolean(claudeProjectPath && fs.existsSync(claudeProjectPath)),
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Layer 5 (highest): workspace — <projectRoot>/.chainlesschain/skills/
|
|
234
270
|
const projectRoot = findProjectRoot();
|
|
235
271
|
if (projectRoot) {
|
|
236
272
|
const workspacePath = path.join(projectRoot, ".chainlesschain", "skills");
|
|
@@ -73,6 +73,7 @@ export class SubAgentContext {
|
|
|
73
73
|
this.tokenBudget = options.tokenBudget || null;
|
|
74
74
|
this.inheritedContext = options.inheritedContext || null;
|
|
75
75
|
this.allowedTools = options.allowedTools || null; // null = all
|
|
76
|
+
this.depth = options.depth || 1; // nesting level (parent main loop = 0)
|
|
76
77
|
this.cwd = options.cwd || process.cwd();
|
|
77
78
|
this.status = "active";
|
|
78
79
|
this.result = null;
|
|
@@ -249,6 +250,8 @@ export class SubAgentContext {
|
|
|
249
250
|
...this._llmOptions,
|
|
250
251
|
contextEngine: this.contextEngine,
|
|
251
252
|
cwd: this.cwd,
|
|
253
|
+
// Nesting level: lets a nested spawn_sub_agent see — and cap — its depth.
|
|
254
|
+
subAgentDepth: this.depth,
|
|
252
255
|
...loopOptions,
|
|
253
256
|
};
|
|
254
257
|
if (this.iterationBudget) {
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import readline from "readline";
|
|
21
21
|
import chalk from "chalk";
|
|
22
22
|
import fs from "fs";
|
|
23
|
+
import os from "os";
|
|
23
24
|
import path from "path";
|
|
24
25
|
import { logger } from "../lib/logger.js";
|
|
25
26
|
import { getPlanModeManager, PlanState } from "../lib/plan-mode.js";
|
|
@@ -748,10 +749,12 @@ export async function startAgentRepl(options = {}) {
|
|
|
748
749
|
// (when the IDE bridge is connected) the editor's open tabs ranked first.
|
|
749
750
|
const { makeAtCompleter } = await import("../lib/repl-completer.js");
|
|
750
751
|
const atCompleter = makeAtCompleter({
|
|
751
|
-
cwd: process.cwd()
|
|
752
|
+
// cwd left unset on purpose: the completer resolves process.cwd() lazily
|
|
753
|
+
// so it follows `/cd` mid-session.
|
|
752
754
|
// Keep in sync with the rl.on("line") handlers + /help below.
|
|
753
755
|
slashCommands: [
|
|
754
756
|
"/auto",
|
|
757
|
+
"/cd",
|
|
755
758
|
"/clear",
|
|
756
759
|
"/compact",
|
|
757
760
|
"/context",
|
|
@@ -1012,6 +1015,9 @@ export async function startAgentRepl(options = {}) {
|
|
|
1012
1015
|
logger.log(
|
|
1013
1016
|
` ${chalk.cyan("/rewind")} Rewind conversation to an earlier turn (double-Esc lists)`,
|
|
1014
1017
|
);
|
|
1018
|
+
logger.log(
|
|
1019
|
+
` ${chalk.cyan("/cd <dir>")} Change working directory mid-session (completion/memory follow)`,
|
|
1020
|
+
);
|
|
1015
1021
|
logger.log(
|
|
1016
1022
|
` ${chalk.cyan("/compact")} Smart compact (importance-based)`,
|
|
1017
1023
|
);
|
|
@@ -1250,6 +1256,26 @@ export async function startAgentRepl(options = {}) {
|
|
|
1250
1256
|
return;
|
|
1251
1257
|
}
|
|
1252
1258
|
|
|
1259
|
+
// `/cd` (Claude-Code 2.1.163 parity): relocate the session's working
|
|
1260
|
+
// directory mid-conversation. Everything that reads process.cwd() per
|
|
1261
|
+
// call follows automatically (agent cwd, @-completion, project memory).
|
|
1262
|
+
if (trimmed === "/cd" || trimmed.startsWith("/cd ")) {
|
|
1263
|
+
const target = trimmed.slice(3).trim();
|
|
1264
|
+
if (!target) {
|
|
1265
|
+
logger.info(`cwd: ${process.cwd()}`);
|
|
1266
|
+
} else {
|
|
1267
|
+
try {
|
|
1268
|
+
const expanded = target.replace(/^~(?=$|[\\/])/, os.homedir());
|
|
1269
|
+
process.chdir(path.resolve(process.cwd(), expanded));
|
|
1270
|
+
logger.log(chalk.green(`cwd → ${process.cwd()}`));
|
|
1271
|
+
} catch (err) {
|
|
1272
|
+
logger.error(`/cd failed: ${err.message}`);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
prompt();
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1253
1279
|
if (trimmed === "/rewind" || trimmed.startsWith("/rewind ")) {
|
|
1254
1280
|
try {
|
|
1255
1281
|
const { listUserTurns, rewindToTurn, renderTurnList } = await import(
|
|
@@ -901,6 +901,40 @@ export async function executeTool(name, args, context = {}) {
|
|
|
901
901
|
ruleAllowed = true;
|
|
902
902
|
}
|
|
903
903
|
|
|
904
|
+
// Sensitive-file write guard (Claude-Code 2.1.160 parity): shell startup
|
|
905
|
+
// files / PowerShell profiles / git+husky hooks execute code on the user's
|
|
906
|
+
// next shell or commit — even otherwise-permitted edit flows confirm first.
|
|
907
|
+
// An explicit settings `allow` rule is the only bypass (exact user
|
|
908
|
+
// pre-authorization); headless without a confirmer fails closed.
|
|
909
|
+
if (
|
|
910
|
+
(name === "write_file" || name === "edit_file") &&
|
|
911
|
+
settingsVerdict.decision !== "allow" &&
|
|
912
|
+
args?.path
|
|
913
|
+
) {
|
|
914
|
+
const { sensitiveFileReason } = await import(
|
|
915
|
+
"../lib/sensitive-file-guard.js"
|
|
916
|
+
);
|
|
917
|
+
const sensReason = sensitiveFileReason(args.path);
|
|
918
|
+
if (sensReason) {
|
|
919
|
+
const confirm = context.permissionConfirm || context.shellConfirm || null;
|
|
920
|
+
const ok =
|
|
921
|
+
typeof confirm === "function"
|
|
922
|
+
? await confirm({
|
|
923
|
+
tool: name,
|
|
924
|
+
args,
|
|
925
|
+
rule: null,
|
|
926
|
+
reason: `sensitive file: ${sensReason}`,
|
|
927
|
+
})
|
|
928
|
+
: false;
|
|
929
|
+
if (!ok) {
|
|
930
|
+
return {
|
|
931
|
+
error: `[Sensitive File] Writing "${args.path}" requires confirmation (${sensReason}) — denied. Add a settings allow rule to pre-authorize.`,
|
|
932
|
+
policy: { decision: "ask", via: "sensitive-file" },
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
904
938
|
// Plan mode: check if tool is allowed (a settings `allow` rule pre-authorizes)
|
|
905
939
|
if (
|
|
906
940
|
planManager.isActive() &&
|
|
@@ -980,6 +1014,7 @@ export async function executeTool(name, args, context = {}) {
|
|
|
980
1014
|
shellConfirm: context.shellConfirm || null,
|
|
981
1015
|
additionalDirectories: context.additionalDirectories || null,
|
|
982
1016
|
ruleAllowed,
|
|
1017
|
+
subAgentDepth: context.subAgentDepth || 0,
|
|
983
1018
|
});
|
|
984
1019
|
} catch (err) {
|
|
985
1020
|
if (hookDb) {
|
|
@@ -1150,6 +1185,7 @@ async function executeToolInner(
|
|
|
1150
1185
|
shellConfirm,
|
|
1151
1186
|
additionalDirectories,
|
|
1152
1187
|
ruleAllowed = false,
|
|
1188
|
+
subAgentDepth = 0,
|
|
1153
1189
|
},
|
|
1154
1190
|
) {
|
|
1155
1191
|
const localToolDescriptor =
|
|
@@ -1528,6 +1564,7 @@ async function executeToolInner(
|
|
|
1528
1564
|
interaction,
|
|
1529
1565
|
sessionId,
|
|
1530
1566
|
llmOptions,
|
|
1567
|
+
subAgentDepth,
|
|
1531
1568
|
}),
|
|
1532
1569
|
);
|
|
1533
1570
|
}
|
|
@@ -2186,6 +2223,13 @@ async function _executeRunCode(args, cwd) {
|
|
|
2186
2223
|
|
|
2187
2224
|
// ─── spawn_sub_agent implementation ──────────────────────────────────────
|
|
2188
2225
|
|
|
2226
|
+
/**
|
|
2227
|
+
* Max sub-agent nesting depth (Claude-Code 2.1.172 parity: sub-agents may
|
|
2228
|
+
* spawn their own sub-agents, capped at 5 levels so a runaway model cannot
|
|
2229
|
+
* recurse forever). Main loop = depth 0, its children = 1, …
|
|
2230
|
+
*/
|
|
2231
|
+
export const MAX_SUB_AGENT_DEPTH = 5;
|
|
2232
|
+
|
|
2189
2233
|
/**
|
|
2190
2234
|
* Execute a spawn_sub_agent tool call.
|
|
2191
2235
|
* Creates an isolated SubAgentContext, runs it, and returns only the summary.
|
|
@@ -2195,6 +2239,13 @@ async function _executeRunCode(args, cwd) {
|
|
|
2195
2239
|
* @returns {Promise<object>}
|
|
2196
2240
|
*/
|
|
2197
2241
|
async function _executeSpawnSubAgent(args, ctx) {
|
|
2242
|
+
// Nesting cap: refuse before any context/registry work.
|
|
2243
|
+
const currentDepth = ctx.subAgentDepth || 0;
|
|
2244
|
+
if (currentDepth >= MAX_SUB_AGENT_DEPTH) {
|
|
2245
|
+
return {
|
|
2246
|
+
error: `spawn_sub_agent: max nesting depth (${MAX_SUB_AGENT_DEPTH}) reached — complete the task directly instead of delegating further.`,
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2198
2249
|
let {
|
|
2199
2250
|
role,
|
|
2200
2251
|
task,
|
|
@@ -2296,6 +2347,7 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
2296
2347
|
cwd: ctx.cwd,
|
|
2297
2348
|
profile: profile || null,
|
|
2298
2349
|
llmOptions: subLlmOptions,
|
|
2350
|
+
depth: currentDepth + 1, // nested spawns see their own level
|
|
2299
2351
|
});
|
|
2300
2352
|
|
|
2301
2353
|
const emit = (type, payload) => {
|
|
@@ -3332,6 +3384,9 @@ export async function* agentLoop(messages, options) {
|
|
|
3332
3384
|
autoCheckpoint: options.autoCheckpoint || false,
|
|
3333
3385
|
checkpointSession:
|
|
3334
3386
|
options.checkpointSession || options.sessionId || "agent",
|
|
3387
|
+
// Sub-agent nesting level (0 = main loop); spawn_sub_agent caps at
|
|
3388
|
+
// MAX_SUB_AGENT_DEPTH using this.
|
|
3389
|
+
subAgentDepth: options.subAgentDepth || 0,
|
|
3335
3390
|
};
|
|
3336
3391
|
|
|
3337
3392
|
throwIfAborted(signal);
|
|
@@ -102,8 +102,19 @@ export function parseInputEvent(line) {
|
|
|
102
102
|
.map((b) => (typeof b === "string" ? b : b?.text || ""))
|
|
103
103
|
.join("");
|
|
104
104
|
}
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
// Vision input (chat-panel image paste): {"type":"user","text":…,
|
|
106
|
+
// "images":["/abs/file.png", …]} — file paths, resolved at turn build via
|
|
107
|
+
// the same image-input pipeline as `cc agent --image`.
|
|
108
|
+
const rawImages = obj && typeof obj === "object" ? obj.images || msg.images : null;
|
|
109
|
+
const images = Array.isArray(rawImages)
|
|
110
|
+
? rawImages.filter((p) => typeof p === "string" && p.trim()).slice(0, 8)
|
|
111
|
+
: [];
|
|
112
|
+
if (typeof content !== "string" || !content.trim()) {
|
|
113
|
+
// An image-only turn is valid — give the model something to act on.
|
|
114
|
+
if (images.length) return { text: "Please look at the attached image(s).", images };
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
return images.length ? { text: content, images } : { text: content };
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
/**
|
|
@@ -727,10 +738,31 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
727
738
|
// optional polish — never fail the turn over it
|
|
728
739
|
}
|
|
729
740
|
|
|
730
|
-
|
|
741
|
+
// Attach pasted/added images (panel parity with `--image`): file paths →
|
|
742
|
+
// data URLs → OpenAI-style multimodal content. buildUserContent returns
|
|
743
|
+
// the plain string when there are no images, so text turns are unchanged.
|
|
744
|
+
let turnContent = userContent;
|
|
745
|
+
if (parsed.images && parsed.images.length) {
|
|
746
|
+
try {
|
|
747
|
+
const { resolveImages, buildUserContent } =
|
|
748
|
+
await import("../lib/image-input.js");
|
|
749
|
+
turnContent = buildUserContent(userContent, resolveImages(parsed.images));
|
|
750
|
+
} catch (err) {
|
|
751
|
+
emit({
|
|
752
|
+
type: "result",
|
|
753
|
+
subtype: "error",
|
|
754
|
+
is_error: true,
|
|
755
|
+
result: `image attach failed: ${err.message}`,
|
|
756
|
+
session_id: sessionId,
|
|
757
|
+
});
|
|
758
|
+
continue; // bad attachment kills the turn, not the session
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
messages.push({ role: "user", content: turnContent });
|
|
731
763
|
if (persist) {
|
|
732
764
|
try {
|
|
733
|
-
store.appendUserMessage(sessionId,
|
|
765
|
+
store.appendUserMessage(sessionId, turnContent);
|
|
734
766
|
} catch {
|
|
735
767
|
/* best-effort */
|
|
736
768
|
}
|
|
@@ -347,7 +347,25 @@ export async function loadIdeMcp(opts = {}, deps = {}) {
|
|
|
347
347
|
}
|
|
348
348
|
const cfg = toCfg(lock);
|
|
349
349
|
if (!cfg) return deps.into || null;
|
|
350
|
-
|
|
350
|
+
const out = await setupMcpFromConfig({ ide: cfg }, deps);
|
|
351
|
+
// Hot reconnect: a window reload / extension update restarts the editor's
|
|
352
|
+
// MCP server on a NEW port with a NEW token. Register a reconnector so a
|
|
353
|
+
// failed mcp__ide__* call re-scans the lockfiles mid-session and retries,
|
|
354
|
+
// instead of the IDE tools (and selection/diagnostics injection) silently
|
|
355
|
+
// dying for the rest of the run. Note the stale CHAINLESSCHAIN_IDE_PORT in
|
|
356
|
+
// our env no longer matches any live lock, so discovery falls through to
|
|
357
|
+
// the workspace scan — exactly the path that finds the restarted instance.
|
|
358
|
+
if (out?.mcpClient?.setReconnector) {
|
|
359
|
+
out.mcpClient.setReconnector("ide", () => {
|
|
360
|
+
const fresh = discover({
|
|
361
|
+
cwd: opts.cwd,
|
|
362
|
+
env: opts.env,
|
|
363
|
+
force: opts.force === true,
|
|
364
|
+
});
|
|
365
|
+
return fresh ? toCfg(fresh) : null;
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
return out;
|
|
351
369
|
}
|
|
352
370
|
|
|
353
371
|
/**
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as v,P as u,J as S,U as n,R as a,S as y,K as C,Q as x,V as w,_ as B,b as s}from"./vendor-BvqAck49.js";import{_ as k}from"./index-B76qMGe0.js";import"./icons-DP3uiYxy.js";const M={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=s(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=s(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=s(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=s(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=s(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),f=String(e.getMonth()+1).padStart(2,"0"),b=String(e.getDate()).padStart(2,"0"),g=String(e.getHours()).padStart(2,"0"),h=String(e.getMinutes()).padStart(2,"0");return`${p}-${f}-${b} ${g}:${h}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:s};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},N={class:"bubble"},T={class:"meta"},R={class:"actor"},V={class:"time"},j={class:"body"};function q(c,d,t,r,i,l){const o=v("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[n("div",N,[n("div",T,[n("span",R,a(r.actorLabel),1),n("span",V,a(r.formattedTime),1)]),n("div",j,a(r.messageText),1),t.event.source.adapter?(u(),y(o,{key:0,class:"src",color:r.adapterColor},{default:C(()=>[x(a(t.event.source.adapter),1)]),_:1},8,["color"])):w("v-if",!0)])],2)}const A=k(M,[["render",q],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-MQBjbf/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{A as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as r}from"./index-B76qMGe0.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-CipchQUs.js";import{U as t}from"./index-B76qMGe0.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-CgCiGZ6t.js";import"./useFlexGapSupport-CKncli3p.js";import"./styleChecker-BTkUPq_y.js";import"./index-C1b8TGYq.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-C3A1d5Wt.js";import{U as t}from"./index-B76qMGe0.js";import"./vendor-BvqAck49.js";import"./index-C1b8TGYq.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
|