chainlesschain 0.162.47 → 0.162.49
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-BBjFOl4N.js → AIOps-DmdtNmWd.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-B7A6lHz3.js → ActionButton-DkuYVafg.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DZgNxdvw.js → Analytics-Ba_h8Tub.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CFbPWVnh.js → AppLayout-yb8Zm9MX.js} +4 -4
- package/src/assets/web-panel/assets/{Audit-Ao9RxevG.js → Audit-BGjex2fm.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B1AGqahI.js → Backup-IFQ2hOF2.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-M01bA2JM.js → BaseInput-W8AkPkrV.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CC0Gmd9k.js → Chat-BgI7t-iW.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CfpKEQUF.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-CpEqAg5P.js → Checkbox-DuWsZP4g.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-9c1H2P_L.js → Codegen-DyoTNmYg.js} +1 -1
- package/src/assets/web-panel/assets/{Col-sH2Obo8q.js → Col-DttmlDRk.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DyzjH37r.js → Community-D9nnIdKn.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DsNatLOG.js → Compact-C8KVQaHb.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-B3ws7qwL.js → Compliance-R2owqgjj.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-odGfUMsv.js → Cowork-DwGMMjRn.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-bxO6NLDR.js → Cron-BSTcN_lK.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-xHCPQpE9.js → Crosschain-CTNuIbFD.js} +1 -1
- package/src/assets/web-panel/assets/{DID-3l7HvzNC.js → DID-CgApGsFP.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BNzT5YBj.js → Dashboard-D_OJ3UN5.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DZynMYpG.js → Dropdown-B84Jwra_.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-6HZ2XA9g.js → EmailListRenderer-Bv-YO-6y.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DqzqNzRP.js → FamilyGuardDashboard-drgZ408Y.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CI7lf1MF.js → Federation-CtzFkdW2.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D2m3YZ-k.js → FormItemContext-BFAvNhl9.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bwcc-9EB.js → GenericCardRenderer-DnuEyz_l.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C7qN3bA1.js → Git-jlHajmRJ.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-JfuugS1c.js → Governance-DmJC7PGL.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BNsHm2IH.js → Inference-B-u7xD2n.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CTH_FiL1.js → KnowledgeGraph-BaYCA2Cd.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CxcfBcmS.js → Logs-DTNYQWfp.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-B9PU3qlx.js → Marketplace-CUu1xYvo.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BlvQpnvj.js → McpTools-BmoeTyrC.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-Diiig9gp.js → Memory-DxTU3QU7.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CGfUn4xi.js → MobileBridge-CpcOlKAD.js} +2 -2
- package/src/assets/web-panel/assets/MobileProjects-Bjh_z16l.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CT_1x1Gr.js → Mtc-LfxwOm0x.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-DPAjU1Qn.js → MtcAudit-D6A9Gjkh.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-nks2HW0C.js → Multisig-Ch_jofPV.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BWd74a91.js → NLProgramming-Bkvogg0I.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-B342yG3u.js → Notes-C5t5Xihm.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C9kjn20B.js → NotificationSettings-CTpDUNCb.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-ST2lr-Bi.js +1 -0
- package/src/assets/web-panel/assets/{Organization-Ch-qkiyP.js → Organization-Dr37BaXa.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DeV865TY.js → Overflow-ZGjsdP7N.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-9pzyAAE1.js → P2P-bWJU5Vxd.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-oGgQiWpR.js → PdhVaultBrowser-BRVoW-ye.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-MPDfvUva.js → Permissions-BOSnFZaC.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Es8GFY4_.js → PersonalDataHub-X4SgjP6P.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-R10lJHtN.js → Pipeline-DoJhB9bj.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-8YMg8xrV.js → Privacy-OM9lDj-R.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B-L3DMBv.js → ProjectInit-BXQEOmLn.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-pR4l7GCe.js → ProjectSettings-DBXo3K5u.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-5vaXw-7d.js → Projects-CJ4DBJlS.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-C_E-G6Bh.js → Providers-Tk9SawmO.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CM-FSYbK.js → QuickAsk-DRI1-nTC.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DcwFptAP.js → Recommend-DtrIVTu9.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-DJKj97w-.js → Reputation-DkH8ImwZ.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BfI2mGUm.js → Row-DpA9dlvi.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-D6tzthT0.js → RssFeed-DV3OhxWd.js} +2 -2
- package/src/assets/web-panel/assets/{Search-CkxIxA5y.js → Search-QxdntiQx.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BeTfFgoX.js → Security-CGuEnrD2.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BahX89X1.js → Services-BvwSSD8b.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-55na3k97.js → Skeleton-sx_8L3-5.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DZ-dxsiR.js → Skills-dWOwxRsu.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BUTClrI0.js → Sla-zxXnfKrT.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C0c2AmSU.js → SpeechSettings-CmFlcNjr.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Vr5zzdPz.js → SyncSettings-BeXeqURL.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BrouZA03.js → Tasks-iImd8xSO.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DnaU_7nb.js → Templates-DlgR3XFH.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-1dw4SFBA.js → Tenant-0P8HgQaM.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-B5VDEEHD.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-dDxMvAvM.js → TimelineRenderer-hbO7agZs.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CPJMLjkE.js → Tokens-CsmhgTBO.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-B1IWp6HK.js → Trigger-DnaF_2PP.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-iswzFvfA.js → Trust-C1oafGj1.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CuMmDUvU.js → UkeySign-eLL4DOmC.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BguHSBQ5.js → VideoEditing-CX45sVq7.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CW4PFXSw.js → Wallet-aWPqpHdQ.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-YOO0lqjJ.js → WebAuthn-DMYV1MAo.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-A_z3yLuG.js → WorkflowEditor-D9uRIJvH.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BSHj9uiJ.js → chat-BmWYfCxG.js} +1 -1
- package/src/assets/web-panel/assets/{colors-D7gA-kvN.js → colors-DqvTCkBe.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-ChDt0wUv.js → compact-item-Bh0L0ejI.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-5UAhDsNU.js → createContext-r2qgp1mn.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CusWDjWW.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-7ysmGHSf.js → hasIn-BcffXa-S.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dj3IHF24.js → index-585fuGAN.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6OX-6N1.js → index-B3mmDuOv.js} +1 -1
- package/src/assets/web-panel/assets/{index-WM_jYoK8.js → index-B6pAm1iJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-s_MPIulF.js → index-B7z0qK1W.js} +1 -1
- package/src/assets/web-panel/assets/{index-DslmMjVo.js → index-BCBqTRWH.js} +1 -1
- package/src/assets/web-panel/assets/{index-HUiKkQOf.js → index-BLN-neIf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dq4fd0cB.js → index-BMn_luHQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-NtFFgW-x.js → index-BQlAPNSU.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoCy4bxa.js → index-BXXxkeij.js} +1 -1
- package/src/assets/web-panel/assets/{index-Db4hf2WV.js → index-BXae4ZyX.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9R6sJiP.js → index-BbMox24t.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_xBUmAE.js → index-BeV-KoQl.js} +1 -1
- package/src/assets/web-panel/assets/index-BhYltBvN.js +1 -0
- package/src/assets/web-panel/assets/{index-BGlolJwU.js → index-Bma_yHcC.js} +1 -1
- package/src/assets/web-panel/assets/{index-pk9WOpeN.js → index-BtyXyl3t.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGVsJplV.js → index-C2-02rrp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BzPxVTI2.js → index-C9nh3ANl.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cl10KB1R.js → index-CAlxkpnv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSRnnGez.js → index-CCyB-RK5.js} +3 -3
- package/src/assets/web-panel/assets/{index-DttrXREN.js → index-CDR3GmaO.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhsGGFa4.js → index-CJt0iuep.js} +1 -1
- package/src/assets/web-panel/assets/{index--UCy6rsJ.js → index-CKnEtlZD.js} +1 -1
- package/src/assets/web-panel/assets/{index-C62SpQws.js → index-COrfHebA.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-pJNNc5.js → index-CY8RXaZR.js} +1 -1
- package/src/assets/web-panel/assets/index-CZiIHw4e.js +1 -0
- package/src/assets/web-panel/assets/{index-CylU_ot3.js → index-Cbj6C3pA.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4nXq9eB.js → index-Ct8qhPZe.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHdEHlNY.js → index-DPFT7J7I.js} +1 -1
- package/src/assets/web-panel/assets/{index-COwKdUAS.js → index-DRXcGa5y.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcPEgfGF.js → index-DW1y18GR.js} +1 -1
- package/src/assets/web-panel/assets/{index-trVj-RG1.js → index-DWlDSE0F.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfjMbFZA.js → index-Dcjol7ot.js} +1 -1
- package/src/assets/web-panel/assets/{index-_8xZf-zU.js → index-De36_UgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZOmjAajS.js → index-DutDlDUF.js} +1 -1
- package/src/assets/web-panel/assets/{index-C93TfkpQ.js → index-DxajFkK2.js} +1 -1
- package/src/assets/web-panel/assets/{index-QPBJl4wk.js → index-S4E77Aer.js} +1 -1
- package/src/assets/web-panel/assets/{index-BLoQ2FkI.js → index-U86pxDyR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcKVERvm.js → index-XwbSqOB2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTzZlYgQ.js → index-h4O0AcBt.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BcWdcWH2.js → initDefaultProps-C1d8I-BX.js} +1 -1
- package/src/assets/web-panel/assets/{motion-D-GC86LC.js → motion-Dq7fiy4Y.js} +1 -1
- package/src/assets/web-panel/assets/{move-7N01T4vz.js → move-Bqb2dySM.js} +1 -1
- package/src/assets/web-panel/assets/{omit-B8_G8lAi.js → omit-BUYqb4My.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BeEwgLq8.js → pickAttrs-DeytiKlZ.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CiQwkkN_.js → placementArrow-xrXZWCqG.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CtfIP2YM.js → responsiveObserve-CcL2K-YY.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DnA-Z3fK.js → slide-DmCWaic7.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Ckaf7hg9.js → statusUtils-CqNrFif7.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CE7d6-LQ.js → styleChecker-C436m5Xy.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BBC2EqTi.js → useFlexGapSupport-CVhutCN8.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BWncdesy.js → useFs-DUd49Bui.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BVJgKdiT.js → usePersonalDataHub-fuS9raic.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CdZoGwk8.js → vnode-C3kmDmk-.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-8BsyiHWV.js → zoom-hX-F1dT-.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +62 -0
- package/src/lib/agent-core.js +2 -0
- package/src/lib/agent-worktree.js +78 -0
- package/src/lib/ide-context.js +168 -0
- package/src/lib/mcp-client.js +1 -0
- package/src/lib/memory-injection.js +2 -0
- package/src/lib/safe-mode.js +31 -0
- package/src/lib/settings-hooks.cjs +5 -0
- package/src/repl/agent-repl.js +251 -18
- package/src/repl/config-summary.js +59 -0
- package/src/repl/conversation-export.js +133 -0
- package/src/repl/doctor-status.js +114 -0
- package/src/repl/ide-status.js +76 -0
- package/src/repl/memory-status.js +45 -0
- package/src/repl/permissions-status.js +51 -0
- package/src/repl/recent-sessions.js +46 -0
- package/src/repl/session-cost.js +119 -0
- package/src/runtime/agent-core.js +21 -0
- package/src/runtime/headless-runner.js +11 -2
- package/src/runtime/headless-stream.js +15 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DKe4yjqq.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-CFvH6A9E.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-DKQ3FPUN.js +0 -1
- package/src/assets/web-panel/assets/Terminal-Pe1vBvOm.js +0 -3
- package/src/assets/web-panel/assets/devWarning-NW6VMT5L.js +0 -1
- package/src/assets/web-panel/assets/index-A6oY6RQQ.js +0 -1
- package/src/assets/web-panel/assets/index-Cn2g4vqt.js +0 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/doctor` REPL command (Claude-Code parity) — a consolidated session-health
|
|
3
|
+
* readout. Where /config, /ide, /mcp, /permissions each show one subsystem,
|
|
4
|
+
* /doctor rolls them into a single pass/warn view and flags the common reasons
|
|
5
|
+
* a chat silently fails (no provider, provider set but no key, …).
|
|
6
|
+
*
|
|
7
|
+
* Pure and dependency-free: `buildDoctorChecks` turns already-resolved session
|
|
8
|
+
* state into a check list, `renderDoctor` formats it. The REPL gathers inputs.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Providers whose models run locally and need no API key. */
|
|
12
|
+
const FREE_PROVIDERS = ["ollama", "local", "llamacpp", "mediapipe"];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {object} input
|
|
16
|
+
* { config, ideTools?: string[], mcpServers?: Array, permissionRules?, settingsHooks? }
|
|
17
|
+
* @returns {Array<{level:'ok'|'warn'|'info'|'err', name:string, detail:string}>}
|
|
18
|
+
*/
|
|
19
|
+
export function buildDoctorChecks(input = {}) {
|
|
20
|
+
const { config, ideTools, mcpServers, permissionRules, settingsHooks } =
|
|
21
|
+
input;
|
|
22
|
+
const llm = (config && config.llm) || {};
|
|
23
|
+
const checks = [];
|
|
24
|
+
|
|
25
|
+
// LLM provider / model
|
|
26
|
+
if (!llm.provider) {
|
|
27
|
+
checks.push({
|
|
28
|
+
level: "warn",
|
|
29
|
+
name: "LLM provider",
|
|
30
|
+
detail:
|
|
31
|
+
"unset → defaults to ollama (local); set llm.provider or --provider",
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
checks.push({
|
|
35
|
+
level: "ok",
|
|
36
|
+
name: "LLM provider",
|
|
37
|
+
detail: `${llm.provider}${llm.model ? " · " + llm.model : " (no model set)"}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// API key for non-local providers
|
|
42
|
+
if (
|
|
43
|
+
llm.provider &&
|
|
44
|
+
!FREE_PROVIDERS.includes(String(llm.provider).toLowerCase()) &&
|
|
45
|
+
!llm.apiKey
|
|
46
|
+
) {
|
|
47
|
+
checks.push({
|
|
48
|
+
level: "warn",
|
|
49
|
+
name: "API key",
|
|
50
|
+
detail: `${llm.provider} has no apiKey set (config llm.apiKey or a *_API_KEY env var)`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// IDE bridge
|
|
55
|
+
const ideCount = Array.isArray(ideTools) ? ideTools.length : 0;
|
|
56
|
+
checks.push(
|
|
57
|
+
ideCount > 0
|
|
58
|
+
? {
|
|
59
|
+
level: "ok",
|
|
60
|
+
name: "IDE bridge",
|
|
61
|
+
detail: `${ideCount} tools connected`,
|
|
62
|
+
}
|
|
63
|
+
: { level: "info", name: "IDE bridge", detail: "not connected" },
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// MCP servers
|
|
67
|
+
const mcpCount = Array.isArray(mcpServers) ? mcpServers.length : 0;
|
|
68
|
+
checks.push(
|
|
69
|
+
mcpCount > 0
|
|
70
|
+
? { level: "ok", name: "MCP servers", detail: `${mcpCount} connected` }
|
|
71
|
+
: { level: "info", name: "MCP servers", detail: "none" },
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Permission rules
|
|
75
|
+
const ruleCount = permissionRules
|
|
76
|
+
? (permissionRules.allow?.length || 0) +
|
|
77
|
+
(permissionRules.ask?.length || 0) +
|
|
78
|
+
(permissionRules.deny?.length || 0)
|
|
79
|
+
: 0;
|
|
80
|
+
checks.push({
|
|
81
|
+
level: "info",
|
|
82
|
+
name: "Permission rules",
|
|
83
|
+
detail: ruleCount > 0 ? `${ruleCount} rule(s)` : "none (default gate)",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// settings.json hooks
|
|
87
|
+
checks.push({
|
|
88
|
+
level: "info",
|
|
89
|
+
name: "settings.json hooks",
|
|
90
|
+
detail: settingsHooks ? "loaded" : "none",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return checks;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const ICON = { ok: "✓", warn: "⚠", err: "✗", info: "·" };
|
|
97
|
+
|
|
98
|
+
/** Render the check list as a readable health block. */
|
|
99
|
+
export function renderDoctor(checks) {
|
|
100
|
+
const list = Array.isArray(checks) ? checks : [];
|
|
101
|
+
const lines = ["Session health (/doctor):"];
|
|
102
|
+
for (const c of list) {
|
|
103
|
+
lines.push(` ${ICON[c.level] || "·"} ${c.name}: ${c.detail}`);
|
|
104
|
+
}
|
|
105
|
+
const problems = list.filter(
|
|
106
|
+
(c) => c.level === "warn" || c.level === "err",
|
|
107
|
+
).length;
|
|
108
|
+
lines.push(
|
|
109
|
+
problems === 0
|
|
110
|
+
? " no problems detected"
|
|
111
|
+
: ` ${problems} item(s) need attention`,
|
|
112
|
+
);
|
|
113
|
+
return lines.join("\n");
|
|
114
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/ide` REPL command renderer (Claude-Code parity) — report whether an IDE
|
|
3
|
+
* bridge is connected to THIS agent session, which editor/port/workspace it
|
|
4
|
+
* is, the IDE tools the agent can call, and — when nothing is connected — why
|
|
5
|
+
* discovery came up empty plus how to fix it.
|
|
6
|
+
*
|
|
7
|
+
* Pure and dependency-free: takes the resolved MCP bundle (for the live,
|
|
8
|
+
* in-session connection) and an optional `diagnoseIde()` result (for lockfile
|
|
9
|
+
* details), returns plain text. The REPL does the I/O.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const IDE_PREFIX = "mcp__ide__";
|
|
13
|
+
|
|
14
|
+
/** Sorted bare IDE tool names connected in this session (e.g. ["getSelection"]). */
|
|
15
|
+
export function ideToolNames(mcp) {
|
|
16
|
+
const ex = (mcp && mcp.externalToolExecutors) || {};
|
|
17
|
+
return Object.keys(ex)
|
|
18
|
+
.filter((k) => k.startsWith(IDE_PREFIX) && ex[k] && ex[k].kind === "mcp")
|
|
19
|
+
.map((k) => k.slice(IDE_PREFIX.length))
|
|
20
|
+
.sort();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {object|null} mcp resolved bundle from resolveAgentMcp (or null)
|
|
25
|
+
* @param {object|null} diag diagnoseIde() result, or null when unavailable
|
|
26
|
+
* @returns {string}
|
|
27
|
+
*/
|
|
28
|
+
export function renderIdeStatus(mcp, diag = null) {
|
|
29
|
+
const tools = ideToolNames(mcp);
|
|
30
|
+
const chosen = diag && diag.chosen ? diag.chosen : null;
|
|
31
|
+
const lines = [];
|
|
32
|
+
|
|
33
|
+
if (tools.length > 0) {
|
|
34
|
+
const where = chosen
|
|
35
|
+
? `${chosen.ide || "ide"} on 127.0.0.1:${chosen.port} (${chosen.transport})`
|
|
36
|
+
: "an editor extension";
|
|
37
|
+
lines.push(`● IDE bridge connected — ${where}`);
|
|
38
|
+
if (
|
|
39
|
+
chosen &&
|
|
40
|
+
Array.isArray(chosen.workspaceFolders) &&
|
|
41
|
+
chosen.workspaceFolders.length
|
|
42
|
+
) {
|
|
43
|
+
lines.push(` workspace: ${chosen.workspaceFolders.join(", ")}`);
|
|
44
|
+
}
|
|
45
|
+
lines.push(` tools: ${tools.map((t) => IDE_PREFIX + t).join(", ")}`);
|
|
46
|
+
lines.push(
|
|
47
|
+
" selection/diagnostics auto-share each turn · " +
|
|
48
|
+
"@selection / @diagnostics expand on demand",
|
|
49
|
+
);
|
|
50
|
+
return lines.join("\n");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
lines.push("○ IDE bridge not connected to this session");
|
|
54
|
+
if (diag) {
|
|
55
|
+
if (diag.reason) lines.push(` ${diag.reason}`);
|
|
56
|
+
if (Array.isArray(diag.locks) && diag.locks.length) {
|
|
57
|
+
lines.push(` ${diag.locks.length} lockfile(s) in ${diag.lockDir}:`);
|
|
58
|
+
for (const l of diag.locks.slice(0, 5)) {
|
|
59
|
+
lines.push(
|
|
60
|
+
` - ${l.ide || "?"} :${l.port} ${l.transport} ` +
|
|
61
|
+
`(matchScore ${l.matchScore})`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
lines.push(
|
|
66
|
+
diag.inIdeTerminal
|
|
67
|
+
? " you're in an IDE terminal — restart the agent so it re-discovers the bridge"
|
|
68
|
+
: " launch `cc` from your IDE's integrated terminal, or pass --ide to force-connect",
|
|
69
|
+
);
|
|
70
|
+
} else {
|
|
71
|
+
lines.push(
|
|
72
|
+
" install the ChainlessChain IDE extension, then launch cc from its terminal",
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return lines.join("\n");
|
|
76
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/memory` REPL command (Claude-Code parity) — show the project-memory files
|
|
3
|
+
* the agent auto-loads into its system prompt (the cc.md > CLAUDE.md > AGENTS.md
|
|
4
|
+
* hierarchy + @imports + path-scoped rules), so "why does it know/behave like
|
|
5
|
+
* this?" is answerable in-session. Distinct from `#` (append a note to cc.md)
|
|
6
|
+
* and `cc memory recall` (the scoped MemoryStore).
|
|
7
|
+
*
|
|
8
|
+
* Pure: renders a loadProjectInstructions() result. The REPL does the I/O.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {{files?:Array<{path:string,scope:string,bytes?:number,truncated?:boolean}>,warnings?:string[]}} loaded
|
|
13
|
+
* @param {{enabled?:boolean}} [opts] enabled=false when CC_PROJECT_MEMORY=0
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
export function renderMemoryFiles(loaded, { enabled = true } = {}) {
|
|
17
|
+
const files = Array.isArray(loaded?.files) ? loaded.files : [];
|
|
18
|
+
const warnings = Array.isArray(loaded?.warnings) ? loaded.warnings : [];
|
|
19
|
+
const lines = ["Project memory (auto-loaded into the system prompt):"];
|
|
20
|
+
|
|
21
|
+
if (!enabled) {
|
|
22
|
+
lines.push(
|
|
23
|
+
" ⚠ disabled via CC_PROJECT_MEMORY=0 — the files below are NOT loaded this session",
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (files.length === 0) {
|
|
28
|
+
lines.push(" (none found — run `cc init` to generate a cc.md)");
|
|
29
|
+
return lines.join("\n");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let total = 0;
|
|
33
|
+
for (const f of files) {
|
|
34
|
+
const bytes = Number(f.bytes) || 0;
|
|
35
|
+
total += bytes;
|
|
36
|
+
lines.push(
|
|
37
|
+
` [${String(f.scope || "?").padEnd(7)}] ${f.path} ${bytes}B${f.truncated ? " (truncated)" : ""}`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
lines.push(
|
|
41
|
+
` ${files.length} file(s), ${total}B total · precedence cc.md > CLAUDE.md > AGENTS.md`,
|
|
42
|
+
);
|
|
43
|
+
for (const w of warnings) lines.push(` ⚠ ${w}`);
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/permissions` REPL command (Claude-Code parity) — show the allow / ask /
|
|
3
|
+
* deny rules in effect for THIS session (loaded from .claude/settings.json by
|
|
4
|
+
* settings-loader, applied by permission-rules in agent-core's executeTool).
|
|
5
|
+
* These rules are otherwise invisible mid-session; surfacing them tells the
|
|
6
|
+
* user exactly what the agent can do unprompted, what it asks about, and what
|
|
7
|
+
* is blocked.
|
|
8
|
+
*
|
|
9
|
+
* Pure: takes the effective rules ({allow,ask,deny}) + the contributing source
|
|
10
|
+
* files, returns plain text. The REPL does the I/O.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
function pushGroup(lines, label, marker, rules) {
|
|
14
|
+
const list = Array.isArray(rules) ? rules : [];
|
|
15
|
+
if (list.length === 0) return;
|
|
16
|
+
lines.push(` ${label}:`);
|
|
17
|
+
for (const r of list) lines.push(` ${marker} ${r}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {{allow?:string[],ask?:string[],deny?:string[]}|null} rules
|
|
22
|
+
* @param {{files?:string[]}} [opts]
|
|
23
|
+
* @returns {string}
|
|
24
|
+
*/
|
|
25
|
+
export function renderPermissions(rules, { files = [] } = {}) {
|
|
26
|
+
const r = rules || { allow: [], ask: [], deny: [] };
|
|
27
|
+
const count =
|
|
28
|
+
(r.allow?.length || 0) + (r.ask?.length || 0) + (r.deny?.length || 0);
|
|
29
|
+
|
|
30
|
+
if (count === 0) {
|
|
31
|
+
return [
|
|
32
|
+
"Permission rules: none configured.",
|
|
33
|
+
" Tools run under the default gate — dangerous shell commands still",
|
|
34
|
+
" always require approval. Add rules in .claude/settings.json or via",
|
|
35
|
+
" `cc permissions add`.",
|
|
36
|
+
].join("\n");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const lines = ["Permission rules (effective this session):"];
|
|
40
|
+
// Render most-restrictive first to mirror the deny > ask > allow precedence.
|
|
41
|
+
pushGroup(lines, "deny (blocked)", "✗", r.deny);
|
|
42
|
+
pushGroup(lines, "ask (prompt first)", "?", r.ask);
|
|
43
|
+
pushGroup(lines, "allow (auto-approved)", "✓", r.allow);
|
|
44
|
+
if (Array.isArray(files) && files.length) {
|
|
45
|
+
lines.push(` sources: ${files.join(", ")}`);
|
|
46
|
+
}
|
|
47
|
+
lines.push(
|
|
48
|
+
" precedence: deny > ask > allow · dangerous shell commands are always denied",
|
|
49
|
+
);
|
|
50
|
+
return lines.join("\n");
|
|
51
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/sessions` REPL command — list recent RESUMABLE conversations (Claude-Code
|
|
3
|
+
* `/resume` parity, read-only half + mirrors the VS Code panel's /sessions).
|
|
4
|
+
* Where `/session` shows the CURRENT session, this lists past ones (across the
|
|
5
|
+
* DB + JSONL stores, via lib/recent-session.js listRecentSessions) with the
|
|
6
|
+
* ids you can pass to `cc agent --resume <id>`.
|
|
7
|
+
*
|
|
8
|
+
* Pure: renders the listRecentSessions row shape
|
|
9
|
+
* { id, title?, message_count?, updated_at?, _store? }
|
|
10
|
+
* The REPL gathers the rows + supplies the current id.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Array} sessions listRecentSessions() rows
|
|
15
|
+
* @param {{currentId?:string, limit?:number}} [opts]
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
export function renderRecentSessions(sessions, opts = {}) {
|
|
19
|
+
const limit = opts.limit || 15;
|
|
20
|
+
const list = Array.isArray(sessions) ? sessions : [];
|
|
21
|
+
if (list.length === 0) {
|
|
22
|
+
return "No recent sessions found. Start chatting, or resume one later with `cc agent --resume <id>`.";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const lines = ["Recent sessions (resume with `cc agent --resume <id>`):"];
|
|
26
|
+
for (const s of list.slice(0, limit)) {
|
|
27
|
+
const id = String(s?.id || "");
|
|
28
|
+
if (!id) continue;
|
|
29
|
+
const current =
|
|
30
|
+
opts.currentId && id === opts.currentId ? " ← current" : "";
|
|
31
|
+
const store = s._store ? `[${s._store}]` : "";
|
|
32
|
+
const msgs = Number.isFinite(s.message_count)
|
|
33
|
+
? `${s.message_count} msgs`
|
|
34
|
+
: "";
|
|
35
|
+
const when = s.updated_at
|
|
36
|
+
? String(s.updated_at).slice(0, 19).replace("T", " ")
|
|
37
|
+
: "";
|
|
38
|
+
const title = s.title && s.title !== "Untitled" ? ` — ${s.title}` : "";
|
|
39
|
+
const meta = [store, msgs, when].filter(Boolean).join(" · ");
|
|
40
|
+
lines.push(` ${id.slice(0, 12)}${current} ${meta}${title}`);
|
|
41
|
+
}
|
|
42
|
+
if (list.length > limit) {
|
|
43
|
+
lines.push(` … +${list.length - limit} more`);
|
|
44
|
+
}
|
|
45
|
+
return lines.join("\n");
|
|
46
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/cost` REPL command — running token spend + estimated $ for the LIVE agent
|
|
3
|
+
* session (Claude-Code parity). Where `cc cost` reads persisted JSONL usage,
|
|
4
|
+
* this accumulates each turn's usage events IN MEMORY, so it reflects exactly
|
|
5
|
+
* this conversation and works even for anonymous (non-persisted) sessions.
|
|
6
|
+
*
|
|
7
|
+
* Pure and dependency-light (only the shared pricing lib); the REPL feeds it
|
|
8
|
+
* usage events and prints the rendered string.
|
|
9
|
+
*/
|
|
10
|
+
import { priceRollup, mergePricing } from "../lib/llm-pricing.js";
|
|
11
|
+
|
|
12
|
+
function num(n) {
|
|
13
|
+
const v = Number(n);
|
|
14
|
+
return Number.isFinite(v) ? v : 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function fmtUsd(n) {
|
|
18
|
+
const v = Number(n) || 0;
|
|
19
|
+
if (v === 0) return "$0.00";
|
|
20
|
+
if (v < 0.01) return `$${v.toFixed(6)}`;
|
|
21
|
+
return `$${v.toFixed(4)}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A fresh accumulator: running totals + per provider/model rows. */
|
|
25
|
+
export function newCostStore() {
|
|
26
|
+
return {
|
|
27
|
+
total: { inputTokens: 0, outputTokens: 0, totalTokens: 0, calls: 0 },
|
|
28
|
+
byKey: new Map(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Fold the REPL's per-turn usage events ([{ provider, model, usage }]) into the
|
|
34
|
+
* store. Each `usage` is the raw LLM usage object (input_tokens/output_tokens/…
|
|
35
|
+
* with provider-variant aliases). Zero-token events are ignored. Mutates and
|
|
36
|
+
* returns the store.
|
|
37
|
+
*/
|
|
38
|
+
export function addUsage(store, events) {
|
|
39
|
+
const s = store || newCostStore();
|
|
40
|
+
for (const ev of Array.isArray(events) ? events : []) {
|
|
41
|
+
const u = ev && ev.usage ? ev.usage : null;
|
|
42
|
+
if (!u) continue;
|
|
43
|
+
const inT = num(u.input_tokens ?? u.prompt_tokens ?? u.inputTokens);
|
|
44
|
+
const outT = num(u.output_tokens ?? u.completion_tokens ?? u.outputTokens);
|
|
45
|
+
const totT = num(u.total_tokens ?? u.totalTokens ?? inT + outT);
|
|
46
|
+
if (inT === 0 && outT === 0 && totT === 0) continue;
|
|
47
|
+
s.total.inputTokens += inT;
|
|
48
|
+
s.total.outputTokens += outT;
|
|
49
|
+
s.total.totalTokens += totT;
|
|
50
|
+
s.total.calls += 1;
|
|
51
|
+
const key = `${ev.provider || "?"}/${ev.model || "?"}`;
|
|
52
|
+
let row = s.byKey.get(key);
|
|
53
|
+
if (!row) {
|
|
54
|
+
row = {
|
|
55
|
+
provider: ev.provider || null,
|
|
56
|
+
model: ev.model || null,
|
|
57
|
+
inputTokens: 0,
|
|
58
|
+
outputTokens: 0,
|
|
59
|
+
totalTokens: 0,
|
|
60
|
+
calls: 0,
|
|
61
|
+
};
|
|
62
|
+
s.byKey.set(key, row);
|
|
63
|
+
}
|
|
64
|
+
row.inputTokens += inT;
|
|
65
|
+
row.outputTokens += outT;
|
|
66
|
+
row.totalTokens += totT;
|
|
67
|
+
row.calls += 1;
|
|
68
|
+
}
|
|
69
|
+
return s;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Snapshot the store as the `{ total, byModel[] }` aggregate priceRollup wants. */
|
|
73
|
+
export function costAggregate(store) {
|
|
74
|
+
const s = store || newCostStore();
|
|
75
|
+
return {
|
|
76
|
+
total: { ...s.total },
|
|
77
|
+
byModel: Array.from(s.byKey.values()).sort(
|
|
78
|
+
(a, b) => b.totalTokens - a.totalTokens,
|
|
79
|
+
),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Render the live session cost. `pricingOverrides` is typically
|
|
85
|
+
* `config.llm.pricing`. Returns plain text (the REPL does the I/O).
|
|
86
|
+
*/
|
|
87
|
+
export function renderSessionCost(store, { pricingOverrides } = {}) {
|
|
88
|
+
const agg = costAggregate(store);
|
|
89
|
+
if (agg.total.calls === 0) {
|
|
90
|
+
return "Session cost: no LLM calls yet this session.";
|
|
91
|
+
}
|
|
92
|
+
const table = mergePricing(pricingOverrides);
|
|
93
|
+
const result = priceRollup(agg, { table });
|
|
94
|
+
const lines = [];
|
|
95
|
+
lines.push("Session cost (estimated):");
|
|
96
|
+
lines.push(
|
|
97
|
+
` total: ${fmtUsd(result.cost.totalCost)} USD ` +
|
|
98
|
+
`(${result.total.totalTokens.toLocaleString()} tokens, ${result.total.calls} calls)`,
|
|
99
|
+
);
|
|
100
|
+
for (const row of result.byModel) {
|
|
101
|
+
const provider = (row.provider || "?").padEnd(10);
|
|
102
|
+
const model = (row.model || "?").padEnd(24);
|
|
103
|
+
const tokens = `in=${row.inputTokens} out=${row.outputTokens}`;
|
|
104
|
+
const price = row.free
|
|
105
|
+
? "free (local)"
|
|
106
|
+
: row.matched
|
|
107
|
+
? fmtUsd(row.cost)
|
|
108
|
+
: "unpriced";
|
|
109
|
+
lines.push(` ${provider} ${model} ${price} ${tokens}`);
|
|
110
|
+
}
|
|
111
|
+
if (result.unpriced.length > 0) {
|
|
112
|
+
lines.push(
|
|
113
|
+
` note: ${result.unpriced.length} model(s) have no rate — ` +
|
|
114
|
+
"tokens excluded from total. Add rates via config: llm.pricing.",
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
lines.push(" prices are estimates of public list rates (USD/1M tokens).");
|
|
118
|
+
return lines.join("\n");
|
|
119
|
+
}
|
|
@@ -334,6 +334,16 @@ export function getAgentToolDescriptors(options = {}) {
|
|
|
334
334
|
|
|
335
335
|
const _defaultSkillLoader = new CLISkillLoader();
|
|
336
336
|
|
|
337
|
+
/**
|
|
338
|
+
* Re-scan all skill layers (Claude-Code `/reload-skills` parity): drops the
|
|
339
|
+
* default loader's cache so newly added/edited SKILL.md dirs are picked up
|
|
340
|
+
* without restarting the session. Returns the resolved skill count.
|
|
341
|
+
*/
|
|
342
|
+
export function reloadSkills() {
|
|
343
|
+
_defaultSkillLoader.clearCache();
|
|
344
|
+
return _defaultSkillLoader.loadAll().length;
|
|
345
|
+
}
|
|
346
|
+
|
|
337
347
|
// ─── Cached environment detection ────────────────────────────────────────
|
|
338
348
|
|
|
339
349
|
let _cachedPython = null;
|
|
@@ -1399,6 +1409,11 @@ async function executeToolInner(
|
|
|
1399
1409
|
cwd: task.cwd,
|
|
1400
1410
|
shell: true,
|
|
1401
1411
|
windowsHide: true,
|
|
1412
|
+
// Same CC_SESSION_ID correlation as the foreground path.
|
|
1413
|
+
env: {
|
|
1414
|
+
...process.env,
|
|
1415
|
+
...(sessionId ? { CC_SESSION_ID: String(sessionId) } : {}),
|
|
1416
|
+
},
|
|
1402
1417
|
// POSIX: own process group so check_shell{kill}/teardown can signal
|
|
1403
1418
|
// the whole tree (shell + its grandchild command). No-op on Windows
|
|
1404
1419
|
// where the tree is killed via taskkill /T instead.
|
|
@@ -1456,6 +1471,12 @@ async function executeToolInner(
|
|
|
1456
1471
|
encoding: "utf8",
|
|
1457
1472
|
timeout: _resolveShellTimeout(args.timeout),
|
|
1458
1473
|
maxBuffer: 1024 * 1024,
|
|
1474
|
+
// CC_SESSION_ID (Claude-Code CLAUDE_CODE_SESSION_ID parity,
|
|
1475
|
+
// 2.1.132): lets scripts/hooks correlate work to the agent session.
|
|
1476
|
+
env: {
|
|
1477
|
+
...process.env,
|
|
1478
|
+
...(sessionId ? { CC_SESSION_ID: String(sessionId) } : {}),
|
|
1479
|
+
},
|
|
1459
1480
|
});
|
|
1460
1481
|
return attachDescriptor(
|
|
1461
1482
|
{
|
|
@@ -552,15 +552,24 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
552
552
|
// session replays the prompt, not a stale editor snapshot. Best-effort with
|
|
553
553
|
// a short timeout; CC_IDE_CONTEXT=0 disables.
|
|
554
554
|
try {
|
|
555
|
-
const { buildIdePromptContext, appendTextToContent } =
|
|
555
|
+
const { buildIdePromptContext, appendTextToContent, expandIdeMentions } =
|
|
556
556
|
await import("../lib/ide-context.js");
|
|
557
|
+
const last = messages[messages.length - 1];
|
|
557
558
|
const ideCtx = await (deps.buildIdePromptContext || buildIdePromptContext)(
|
|
558
559
|
mcp,
|
|
559
560
|
);
|
|
560
561
|
if (ideCtx) {
|
|
561
|
-
const last = messages[messages.length - 1];
|
|
562
562
|
last.content = appendTextToContent(last.content, ideCtx);
|
|
563
563
|
}
|
|
564
|
+
// Explicit @selection / @diagnostics mentions in the user's prompt
|
|
565
|
+
// (Claude-Code parity). Scan the ORIGINAL prompt so injected file-ref
|
|
566
|
+
// blocks can't spoof a mention; append the expansion to the in-flight
|
|
567
|
+
// message only (ephemeral, like the ambient block above).
|
|
568
|
+
const mentioned = await expandIdeMentions(prompt, mcp);
|
|
569
|
+
for (const w of mentioned.warnings) writeErr(` @ide: ${w}\n`);
|
|
570
|
+
if (mentioned.block) {
|
|
571
|
+
last.content = appendTextToContent(last.content, mentioned.block);
|
|
572
|
+
}
|
|
564
573
|
} catch {
|
|
565
574
|
// IDE context is optional polish — never fail the run over it.
|
|
566
575
|
}
|
|
@@ -105,13 +105,15 @@ export function parseInputEvent(line) {
|
|
|
105
105
|
// Vision input (chat-panel image paste): {"type":"user","text":…,
|
|
106
106
|
// "images":["/abs/file.png", …]} — file paths, resolved at turn build via
|
|
107
107
|
// the same image-input pipeline as `cc agent --image`.
|
|
108
|
-
const rawImages =
|
|
108
|
+
const rawImages =
|
|
109
|
+
obj && typeof obj === "object" ? obj.images || msg.images : null;
|
|
109
110
|
const images = Array.isArray(rawImages)
|
|
110
111
|
? rawImages.filter((p) => typeof p === "string" && p.trim()).slice(0, 8)
|
|
111
112
|
: [];
|
|
112
113
|
if (typeof content !== "string" || !content.trim()) {
|
|
113
114
|
// An image-only turn is valid — give the model something to act on.
|
|
114
|
-
if (images.length)
|
|
115
|
+
if (images.length)
|
|
116
|
+
return { text: "Please look at the attached image(s).", images };
|
|
115
117
|
return null;
|
|
116
118
|
}
|
|
117
119
|
return images.length ? { text: content, images } : { text: content };
|
|
@@ -729,11 +731,17 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
729
731
|
// IDE bridge is connected — the user's selection moves between prompts.
|
|
730
732
|
// Best-effort; CC_IDE_CONTEXT=0 disables.
|
|
731
733
|
try {
|
|
732
|
-
const { buildIdePromptContext } =
|
|
734
|
+
const { buildIdePromptContext, expandIdeMentions } =
|
|
735
|
+
await import("../lib/ide-context.js");
|
|
733
736
|
const ideCtx = await (
|
|
734
737
|
deps.buildIdePromptContext || buildIdePromptContext
|
|
735
738
|
)(mcp);
|
|
736
739
|
if (ideCtx) userContent += `\n\n${ideCtx}`;
|
|
740
|
+
// Explicit @selection / @diagnostics mentions (Claude-Code parity);
|
|
741
|
+
// scan the original user event text, append the expansion ephemerally.
|
|
742
|
+
const mentioned = await expandIdeMentions(parsed.text, mcp);
|
|
743
|
+
for (const w of mentioned.warnings) writeErr(` @ide: ${w}\n`);
|
|
744
|
+
if (mentioned.block) userContent += `\n\n${mentioned.block}`;
|
|
737
745
|
} catch {
|
|
738
746
|
// optional polish — never fail the turn over it
|
|
739
747
|
}
|
|
@@ -746,7 +754,10 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
746
754
|
try {
|
|
747
755
|
const { resolveImages, buildUserContent } =
|
|
748
756
|
await import("../lib/image-input.js");
|
|
749
|
-
turnContent = buildUserContent(
|
|
757
|
+
turnContent = buildUserContent(
|
|
758
|
+
userContent,
|
|
759
|
+
resolveImages(parsed.images),
|
|
760
|
+
);
|
|
750
761
|
} catch (err) {
|
|
751
762
|
emit({
|
|
752
763
|
type: "result",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as v,P as u,J as S,U as s,R as a,S as y,K as C,Q as x,V as w,_ as B,b as n}from"./vendor-BvqAck49.js";import{_ as k}from"./index-DSRnnGez.js";import"./icons-DP3uiYxy.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=n(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=n(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=n(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=n(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=n(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),b=String(e.getMonth()+1).padStart(2,"0"),f=String(e.getDate()).padStart(2,"0"),g=String(e.getHours()).padStart(2,"0"),h=String(e.getMinutes()).padStart(2,"0");return`${p}-${b}-${f} ${g}:${h}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:n};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},T={class:"bubble"},M={class:"meta"},R={class:"actor"},V={class:"time"},q={class:"body"};function D(c,d,t,r,i,l){const o=v("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[s("div",T,[s("div",M,[s("span",R,a(r.actorLabel),1),s("span",V,a(r.formattedTime),1)]),s("div",q,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(N,[["render",D],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-6n5bBX/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{A as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as n,J as g,c as l,K as r,N as u,P as h,U as o,R as t,Q as b}from"./vendor-BvqAck49.js";import{_ as v,b as m}from"./index-DSRnnGez.js";import{a7 as y,M as B}from"./icons-DP3uiYxy.js";const M={__name:"MobileProjects",setup(p,{expose:i}){i();const c=u(),{t:e}=m();function a(){c.push("/projects")}function _(){c.push("/mobile-bridge")}const s={router:c,t:e,goToProjects:a,goToMobileBridge:_,get useRouter(){return u},get useI18n(){return m},get MobileOutlined(){return B},get FolderOutlined(){return y}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},x={class:"mobile-projects-placeholder"},O={class:"title"},k={class:"subtitle"},w={class:"explainer"};function T(p,i,c,e,a,_){const s=n("a-alert"),d=n("a-button"),f=n("a-space"),P=n("a-empty"),j=n("a-card");return h(),g("div",x,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",O,t(e.t("mobileProjects.title")),1),o("p",k,t(e.t("mobileProjects.subtitle")),1),l(s,{message:e.t("mobileProjects.v02Banner"),type:"info","show-icon":"",class:"banner"},null,8,["message"]),o("div",w,[o("h3",null,t(e.t("mobileProjects.currentDirection")),1),o("p",null,t(e.t("mobileProjects.currentDirectionBody")),1),o("ul",null,[o("li",null,t(e.t("mobileProjects.stepPhone")),1),o("li",null,t(e.t("mobileProjects.stepTap")),1),o("li",null,t(e.t("mobileProjects.stepPull")),1)]),o("h3",null,t(e.t("mobileProjects.reverseDirection")),1),o("p",null,t(e.t("mobileProjects.reverseDirectionBody")),1)]),l(f,{class:"actions"},{default:r(()=>[l(d,{type:"primary",onClick:e.goToProjects},{default:r(()=>[l(e.FolderOutlined),b(" "+t(e.t("mobileProjects.viewLocalProjects")),1)]),_:1}),l(d,{onClick:e.goToMobileBridge},{default:r(()=>[l(e.MobileOutlined),b(" "+t(e.t("mobileProjects.checkBridge")),1)]),_:1})]),_:1})]),_:1})]),_:1})])}const N=v(M,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-6n5bBX/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{N as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as w,P as l,J as u,U as s,R as n,c as i,K as v,Q as _,V as g,b as a}from"./vendor-BvqAck49.js";import{_ as S}from"./index-DSRnnGez.js";import"./icons-DP3uiYxy.js";const k={__name:"OrderTableRenderer",props:{event:{type:Object,required:!0}},setup(p,{expose:r}){r();const o=p,e=a(()=>o.event.content||{}),d=a(()=>o.event.extra||{}),m=a(()=>d.value.merchant||e.value.merchant||e.value.counterparty||"—"),c=a(()=>e.value.title||e.value.name||e.value.itemName||e.value.text||"—"),y=a(()=>{const t=e.value.amount??e.value.price??e.value.total;return t==null?"—":`${e.value.currency||"¥"} ${typeof t=="number"?t.toFixed(2):t}`}),T=a(()=>d.value.orderNo||e.value.orderNo||e.value.orderId),f=a(()=>e.value.status||e.value.state),b=a(()=>{const t=(f.value||"").toLowerCase();return t.includes("成功")||t.includes("succe")||t.includes("paid")?"green":t.includes("退")||t.includes("refund")?"orange":t.includes("失败")||t.includes("fail")?"red":"default"}),h=a(()=>{if(!o.event.occurredAt)return"";const t=new Date(o.event.occurredAt);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}),x={props:o,c:e,e:d,merchantText:m,itemText:c,amountText:y,orderNo:T,statusText:f,statusColor:b,formattedTime:h,computed:a};return Object.defineProperty(x,"__isScriptSetup",{enumerable:!1,value:!0}),x}},N={class:"order-card"},C={class:"head"},O={class:"time"},V={class:"row"},B={class:"val"},R={class:"row"},D={class:"val"},I={class:"row amount-row"},j={class:"val amount"},A={key:0,class:"row"},F={class:"val mono"},M={key:1,class:"row"};function P(p,r,o,e,d,m){const c=w("a-tag");return l(),u("div",N,[s("div",C,[s("span",O,n(e.formattedTime),1),i(c,{color:"gold"},{default:v(()=>[_(n(o.event.source.adapter),1)]),_:1}),i(c,null,{default:v(()=>[_(n(o.event.subtype),1)]),_:1})]),s("div",V,[r[0]||(r[0]=s("span",{class:"key"},"商户",-1)),s("span",B,n(e.merchantText),1)]),s("div",R,[r[1]||(r[1]=s("span",{class:"key"},"商品/项目",-1)),s("span",D,n(e.itemText),1)]),s("div",I,[r[2]||(r[2]=s("span",{class:"key"},"金额",-1)),s("span",j,n(e.amountText),1)]),e.orderNo?(l(),u("div",A,[r[3]||(r[3]=s("span",{class:"key"},"单号",-1)),s("span",F,n(e.orderNo),1)])):g("v-if",!0),e.statusText?(l(),u("div",M,[r[4]||(r[4]=s("span",{class:"key"},"状态",-1)),i(c,{color:e.statusColor},{default:v(()=>[_(n(e.statusText),1)]),_:1},8,["color"])])):g("v-if",!0)])}const K=S(k,[["render",P],["__scopeId","data-v-5ed5524d"],["__file","/tmp/cc-web-panel-6n5bBX/repo/packages/web-panel/src/components/pdh/renderers/OrderTableRenderer.vue"]]);export{K as default};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./xterm-BZcWGsqw.js","./markdown-CsiA8-E5.js","./markdown-Dfs9RUU9.css","./addon-fit-CK6X9sAG.js","./xterm-DFuMZ0ql.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{u as fe,_ as me,d as V,e as U}from"./index-DSRnnGez.js";import{I as z,J as x,U as _,Q as B,S as Q,K as T,V as R,c as A,F as Y,Z,R as E,o as G,f as H,w as $,n as D,b as ee,r as S,P as y,_ as ve,a2 as we,a3 as he,a4 as _e}from"./vendor-BvqAck49.js";import{R as ye,b as pe,as as ge}from"./icons-DP3uiYxy.js";const k=new Map,C=new Map,N=new Set,F=new Set;let te=!1;function xe(c){te||(te=!0,c.onMessage(o=>{if(!(!o||typeof o.type!="string")){if(o.type==="terminal.stdout"){const{sessionId:s,data:e,seq:i}=o.payload||{};if(!s)return;let w;try{const d=atob(e||""),f=new Uint8Array(d.length);for(let n=0;n<d.length;n++)f[n]=d.charCodeAt(n);w=new TextDecoder("utf-8").decode(f)}catch{w=""}const u={sessionId:s,data:w,seq:i};k.get(s)?.forEach(d=>d(u)),N.forEach(d=>d(u))}else if(o.type==="terminal.exit"){const{sessionId:s,exitCode:e,signal:i}=o.payload||{};if(!s)return;const w={sessionId:s,exitCode:e,signal:i};C.get(s)?.forEach(u=>u(w)),F.forEach(u=>u(w))}}}))}function ne(c){const o=new TextEncoder().encode(c);let s="";for(let e=0;e<o.length;e++)s+=String.fromCharCode(o[e]);return btoa(s)}function ae(c){const o=atob(c||""),s=new Uint8Array(o.length);for(let e=0;e<o.length;e++)s[e]=o.charCodeAt(e);return new TextDecoder("utf-8").decode(s)}function oe(){const c=fe();xe(c);async function o(n={}){const a=await c.sendRaw({type:"terminal.create",payload:{shell:n.shell,cwd:n.cwd,env:n.env,cols:n.cols,rows:n.rows}});if(a.ok===!1)throw new Error(a.error||"terminal_create_failed");return a.result??a}async function s(){const n=await c.sendRaw({type:"terminal.list",payload:{}});if(n.ok===!1)throw new Error(n.error||"terminal_list_failed");const a=n.result??n;return Array.isArray(a.sessions)?a.sessions:[]}async function e(n,a){const r=await c.sendRaw({type:"terminal.stdin",payload:{sessionId:n,data:ne(String(a))}});if(r.ok===!1)throw new Error(r.error||"terminal_stdin_failed");return r.result??r}async function i(n,a,r){const h=await c.sendRaw({type:"terminal.resize",payload:{sessionId:n,cols:a,rows:r}});if(h.ok===!1)throw new Error(h.error||"terminal_resize_failed");return h.result??h}async function w(n){const a=await c.sendRaw({type:"terminal.close",payload:{sessionId:n}});if(a.ok===!1)throw new Error(a.error||"terminal_close_failed");return a.result??a}async function u(n,a=0){const r=await c.sendRaw({type:"terminal.history",payload:{sessionId:n,fromSeq:a}});if(r.ok===!1)throw new Error(r.error||"terminal_history_failed");const h=r.result??r;return{truncated:!!h.truncated,chunks:(h.chunks||[]).map(L=>({seq:L.seq,data:ae(L.data)}))}}function d(n,a){return n?(k.has(n)||k.set(n,new Set),k.get(n).add(a),()=>{k.get(n)?.delete(a),k.get(n)?.size===0&&k.delete(n)}):(N.add(a),()=>N.delete(a))}function f(n,a){return n?(C.has(n)||C.set(n,new Set),C.get(n).add(a),()=>{C.get(n)?.delete(a),C.get(n)?.size===0&&C.delete(n)}):(F.add(a),()=>F.delete(a))}return{create:o,list:s,stdin:e,resize:i,close:w,history:u,onStdout:d,onExit:f,_internal:{stdoutSubs:k,exitSubs:C,toBase64Utf8:ne,fromBase64Utf8:ae}}}const Se={__name:"Terminal",setup(c,{expose:o}){o();const s=oe(),e=S([]),i=S(null),w=S("pwsh"),u=S(!1),d=S(!1),f=S(""),n=S(""),a=S([]),r=[{value:"pwsh",label:"PowerShell"},{value:"cmd",label:"CMD"},{value:"bash",label:"Bash"},{value:"wsl",label:"WSL"}],h=ee(()=>e.value.find(t=>t.id===i.value));function L(t){return t?t.slice(0,8):""}let O=null,M=null;async function I(){if(O)return{xtermMod:O,fitAddonMod:M};try{O=await U(()=>import("./xterm-BZcWGsqw.js").then(t=>t.x),__vite__mapDeps([0,1,2]),import.meta.url),M=await U(()=>import("./addon-fit-CK6X9sAG.js").then(t=>t.a),__vite__mapDeps([3,1,2]),import.meta.url),await U(()=>Promise.resolve({}),__vite__mapDeps([4]),import.meta.url)}catch(t){throw n.value="xterm 资源加载失败:"+(t?.message||"未知错误"),t}return{xtermMod:O,fitAddonMod:M}}async function q(t){await D();const{xtermMod:l,fitAddonMod:p}=await I(),b=a.value.find(v=>v?.dataset?.sessionId===t.id);if(!b)return;const m=new l.Terminal({cursorBlink:!0,fontFamily:'Consolas, "Courier New", monospace',fontSize:13,theme:{background:"#1e1e1e",foreground:"#d4d4d4"},convertEol:!1}),P=new p.FitAddon;m.loadAddon(P),m.open(b);try{P.fit()}catch{}t.xterm=m,t.fitAddon=P;const ie=m.onData(v=>{s.stdin(t.id,v).catch(g=>{String(g?.message||"").includes("dangerous_keyword_blocked")?V.warning("该命令被桌面端拦截(高危关键字)"):V.error("stdin 失败: "+(g?.message||g))})}),ce=s.onStdout(t.id,({data:v,seq:g})=>{t.lastSeq=g,m.write(v)}),de=s.onExit(t.id,({exitCode:v,signal:g})=>{t.alive=!1,t.exitCode=v,t.signal=g,m.writeln(`\r
|
|
3
|
-
\x1B[33m[session exited, code=${v}, signal=${g??"-"}]\x1B[0m`)});t.offs=()=>{try{ie.dispose?.()}catch{}ce(),de()};try{const{chunks:v,truncated:g}=await s.history(t.id,0);g&&m.writeln("\x1B[2m[history truncated — earlier output was evicted]\x1B[0m");for(const K of v)m.write(K.data),t.lastSeq=K.seq}catch(v){m.writeln(`\x1B[31m[history fetch failed: ${v?.message||v}]\x1B[0m`)}const J=new ResizeObserver(()=>{try{P.fit(),s.resize(t.id,m.cols,m.rows).catch(()=>{})}catch{}});J.observe(b);const ue=t.offs;t.offs=()=>{try{J.disconnect()}catch{}ue()}}async function re(){u.value=!0,f.value="";try{const t=await s.create({shell:w.value,cols:80,rows:24}),l={id:t.sessionId,shell:t.shell,cwd:"",alive:!0,lastSeq:0,exitCode:null,xterm:null,fitAddon:null,offs:()=>{}};e.value.push(l),i.value=l.id,await q(l)}catch(t){f.value=t?.message||String(t)}finally{u.value=!1}}async function se(t){try{await s.close(t)}catch(l){f.value=l?.message||String(l)}setTimeout(()=>W(t),500)}function W(t){const l=e.value.findIndex(b=>b.id===t);if(l===-1)return;const p=e.value[l];try{p.offs?.()}catch{}try{p.xterm?.dispose?.()}catch{}e.value.splice(l,1),i.value===t&&(i.value=e.value[0]?.id||null)}function le(t){i.value=t,D(()=>{const l=e.value.find(p=>p.id===t);try{l?.fitAddon?.fit()}catch{}})}async function X(){d.value=!0,f.value="";try{const t=await s.list();for(const l of t){const p=e.value.find(m=>m.id===l.id);if(p){p.alive=l.alive,p.lastSeq=l.lastSeq;continue}const b={id:l.id,shell:l.shell,cwd:l.cwd,alive:l.alive,lastSeq:l.lastSeq,exitCode:null,xterm:null,fitAddon:null,offs:()=>{}};e.value.push(b),await q(b)}!i.value&&e.value.length>0&&(i.value=e.value[0].id)}catch(t){f.value=t?.message||String(t)}finally{d.value=!1}}G(async()=>{await X()}),H(()=>{for(const t of e.value){try{t.offs?.()}catch{}try{t.xterm?.dispose?.()}catch{}}}),$(i,()=>{D(()=>{const t=h.value;try{t?.fitAddon?.fit()}catch{}})});const j={term:s,sessions:e,activeId:i,newShell:w,creating:u,loadingList:d,error:f,warning:n,xtermContainers:a,shellOptions:r,active:h,shortId:L,get xtermMod(){return O},set xtermMod(t){O=t},get fitAddonMod(){return M},set fitAddonMod(t){M=t},loadXterm:I,mountXterm:q,onCreate:re,onClose:se,removeSession:W,activate:le,refreshList:X,ref:S,computed:ee,onMounted:G,onBeforeUnmount:H,nextTick:D,watch:$,get message(){return V},get PlusOutlined(){return ge},get CloseOutlined(){return pe},get ReloadOutlined(){return ye},get useTerminal(){return oe}};return Object.defineProperty(j,"__isScriptSetup",{enumerable:!1,value:!0}),j}},be={class:"terminal-page"},ke={class:"terminal-header"},Ce={class:"page-sub"},Ae={class:"terminal-body"},Ee={class:"session-tabs"},Oe=["onClick"],Te={class:"session-shell"},Re={class:"session-id"},Me={key:0,class:"session-empty"},ze={class:"xterm-host"},Le=["data-session-id"],Pe={key:0,class:"xterm-placeholder"},Be={key:1,class:"terminal-footer"},De={key:0,class:"footer-exit"};function qe(c,o,s,e,i,w){const u=z("a-tag"),d=z("a-select"),f=z("a-button"),n=z("a-space"),a=z("a-alert");return y(),x("div",be,[_("div",ke,[_("div",null,[o[3]||(o[3]=_("h2",{class:"page-title"},"远程终端",-1)),_("p",Ce,[o[2]||(o[2]=B(" 桌面端托管的 PTY 会话;Android 端可远程操控同一通道 ",-1)),e.warning?(y(),Q(u,{key:0,color:"orange",style:{"margin-left":"8px"}},{default:T(()=>[B(E(e.warning),1)]),_:1})):R("v-if",!0)])]),A(n,null,{default:T(()=>[A(d,{value:e.newShell,"onUpdate:value":o[0]||(o[0]=r=>e.newShell=r),style:{width:"130px"},size:"small",options:e.shellOptions},null,8,["value"]),A(f,{type:"primary",size:"small",loading:e.creating,onClick:e.onCreate},{icon:T(()=>[A(e.PlusOutlined)]),default:T(()=>[o[4]||(o[4]=B(" 新会话 ",-1))]),_:1},8,["loading"]),A(f,{size:"small",loading:e.loadingList,onClick:e.refreshList},{icon:T(()=>[A(e.ReloadOutlined)]),default:T(()=>[o[5]||(o[5]=B(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.error?(y(),Q(a,{key:0,message:e.error,type:"error","show-icon":"",closable:"",style:{"margin-bottom":"12px"},onClose:o[1]||(o[1]=r=>e.error="")},null,8,["message"])):R("v-if",!0),_("div",Ae,[_("div",Ee,[(y(!0),x(Y,null,Z(e.sessions,r=>(y(),x("div",{key:r.id,class:ve(["session-tab",{active:r.id===e.activeId,dead:!r.alive}]),onClick:h=>e.activate(r.id)},[_("span",Te,E(r.shell),1),_("span",Re,E(e.shortId(r.id)),1),A(e.CloseOutlined,{class:"session-close",onClick:we(h=>e.onClose(r.id),["stop"])},null,8,["onClick"])],10,Oe))),128)),e.sessions.length===0?(y(),x("div",Me,' 点击 "新会话" 创建第一个终端 ')):R("v-if",!0)]),_("div",ze,[(y(!0),x(Y,null,Z(e.sessions,r=>he((y(),x("div",{key:r.id,ref_for:!0,ref:"xtermContainers","data-session-id":r.id,class:"xterm-container"},null,8,Le)),[[_e,r.id===e.activeId]])),128)),e.sessions.length===0?(y(),x("div",Pe,[...o[6]||(o[6]=[_("span",null,"无活跃会话",-1)])])):R("v-if",!0)])]),e.active?(y(),x("div",Be,[_("span",null,E(e.active.shell)+" · "+E(e.active.cwd||"(默认 cwd)")+" · seq "+E(e.active.lastSeq),1),e.active.alive?R("v-if",!0):(y(),x("span",De,"已退出 (code="+E(e.active.exitCode??"-")+")",1))])):R("v-if",!0)])}const Fe=me(Se,[["render",qe],["__scopeId","data-v-65366a29"],["__file","/tmp/cc-web-panel-6n5bBX/repo/packages/web-panel/src/views/Terminal.vue"]]);export{Fe as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as r}from"./index-DSRnnGez.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-BfI2mGUm.js";import{U as t}from"./index-DSRnnGez.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-CtfIP2YM.js";import"./useFlexGapSupport-BBC2EqTi.js";import"./styleChecker-CE7d6-LQ.js";import"./index-C4nXq9eB.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-sH2Obo8q.js";import{U as t}from"./index-DSRnnGez.js";import"./vendor-BvqAck49.js";import"./index-C4nXq9eB.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
|