chainlesschain 0.162.117 → 0.162.119
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-D1_eyrEP.js → AIOps-DHRc0Ie_.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-tnrMeU0Q.js → ActionButton-CgUXfXke.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-SmbOMqoN.js → Analytics-DIKHjclG.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B4m4Ic3a.js → AppLayout-vX1r-6CY.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-DTC34Qp6.js → Audit-DzJx-WeF.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CU_llIBF.js → Backup-DZ4na4uj.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-vP66eF17.js → BaseInput-qUEPpz0X.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-B8-4iHVJ.js → Chat-DTZl8nH5.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CFD0Xh5e.js → ChatBubbleRenderer-DD2tLmRr.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-zV2Jzmv8.js → Checkbox-BQFF8-dn.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-C7kfk-rY.js → Codegen-DIQaC76u.js} +1 -1
- package/src/assets/web-panel/assets/{Col-t_vUszuS.js → Col-uy6MSNXM.js} +1 -1
- package/src/assets/web-panel/assets/{Community-pRCzzaCc.js → Community-DJSclfR8.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-7IgSGjnW.js → Compact-DS2_Cpq1.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BqDi7iuY.js → Compliance-T6LqAmah.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BL84ZaWT.js → Cowork-BrqyP337.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-yzv32Scr.js → Cron-DYFCc-f1.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-6DTzS8P5.js → Crosschain-CnWNsqde.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CKP63O4a.js → DID-Cno6plcv.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CsV3eP9F.js → Dashboard-CsgzRLsJ.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CByjFKzJ.js → Dropdown-BUKI1xuG.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C6Hn7n75.js → EmailListRenderer-DuEOjlci.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-e1c1vXTT.js → FamilyGuardDashboard-BfnUdEaU.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D9oejCYY.js → Federation-CfeUTibi.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DZ4d_-AT.js → FormItemContext-D14wwVsq.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-QoGFWBcP.js → GenericCardRenderer-CGx7VfKf.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DVZHPXw8.js → Git-chaiL5nL.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-NwdvDPTB.js → Governance-Ca5rbA-N.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BYz9MiEu.js → Inference-DA0DK7dc.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BUdGIZKt.js → KnowledgeGraph-BwaAK34_.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CPGewhlD.js → Logs-FA4XPXuO.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-BgRk4ZMW.js → Marketplace-eOsO5rY3.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DLY9Fd7m.js → McpTools-D88TlCnE.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-B2QishHE.js → Memory-DsIN2Sv6.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DXMQwB_y.js → MobileBridge--q60qDOY.js} +2 -2
- package/src/assets/web-panel/assets/MobileProjects-84NgjQck.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-BVASCKUv.js → Mtc-BYfKH7WL.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-ByLFJ4Zu.js → MtcAudit-D35u_eyo.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-DRAZYcC6.js → Multisig-BksPgmCa.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-EiptSKn1.js → NLProgramming-D5cbMuDm.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BHh5Akqh.js → Notes-Cu_pbWTB.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-XWFl4_3j.js → NotificationSettings-C81tVX8S.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Bdc_O7wT.js → OrderTableRenderer-Ccx2Lxcc.js} +1 -1
- package/src/assets/web-panel/assets/{Organization--VWlMdKp.js → Organization-BIJzR15j.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DuYUvyh7.js → Overflow-BKCASkRj.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BnHaPvFP.js → P2P-Q4mb4TFL.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-WfbjffWL.js → PdhVaultBrowser-CPWIjtON.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BIFhAsZO.js → Permissions-DCo0YoEd.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Dt_m7YZ6.js → PersonalDataHub-CT-Efwnw.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-BsNDbhs7.js → Pipeline-B5iEJ2T_.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-C1SJp30I.js → Privacy-BjOXW26f.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DIOkwlK-.js → ProjectInit-DE6GZFCM.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BZIL8hvl.js → ProjectSettings-cHsBvsYo.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-LHqWtiu2.js → Projects-Bi4Wv8m6.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DlC7SSJT.js → Providers-C0yVlpp5.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DeaVcEma.js → QuickAsk-C6BQQUUw.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BbQI1g_u.js → Recommend-Dz18iBwP.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-Cro6z2uR.js → Reputation-LagVnM_Q.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D7LuPQVP.js → Row--IaheXkB.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BowXZJOX.js → RssFeed-CDNYaijn.js} +3 -3
- package/src/assets/web-panel/assets/{Search-8oufqOmB.js → Search-D6DPr_Km.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CRKFB58y.js → Security-a4-jIBqX.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DzRJ4Kus.js → Services-Bmj4jr2Q.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DtZmLaQr.js → Skeleton-BhKpCNqE.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CPQFZvJ3.js → Skills-BqmheUDl.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-C599OilU.js → Sla-D68DDW4T.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-VdhwHyYN.js → SpeechSettings-CxCF4E_o.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BvX8fTlf.js → SyncSettings-pcetCirO.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-B63Y5zWj.js → Tasks-D3er3tkS.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DZtjohnP.js → Templates-6QfV55r3.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-C8WHv74j.js → Tenant-BOI2_4NB.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-DSIv5Z7S.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-C392mTJ7.js → TimelineRenderer-C4tC343-.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BnmIK-7p.js → Tokens-CnNoHnJv.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-CLYUm45n.js → Trigger-BaRSXO70.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DmKkB9n0.js → Trust-CWnKxwgN.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Btsb1cq9.js → UkeySign-De8aN7WZ.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-KbSQiQ31.js → VideoEditing-Cu7XhMNZ.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-C7T1JpB8.js → Wallet-xfhJUu0f.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-B7fk675F.js → WebAuthn-Bt6sYYDk.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BFEqg2-F.js → WorkflowEditor-C4LZ0x-0.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CCONImPU.js → chat-33Oq8wz3.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BO_usQco.js → colors-COL29MyD.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DPYH8VmY.js → compact-item-D8hinshK.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DuzinRx4.js → createContext-DVD4d6-0.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CKV56AdO.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CGE1laax.js → hasIn-CvLpycQb.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzJpaaYk.js → index-1HmyagUk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DhWFRGxq.js → index-3GhR2NdM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPLKoezy.js → index-65FhG6v3.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6faWLbM.js → index-B2nqCkxx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQieJh3P.js → index-B3Ja9sDO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cjl3wd7u.js → index-B4L1oFlv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJrz4R1Q.js → index-BCJdqeDG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLevxAAl.js → index-B_KT8dhv.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9a-SDrB.js → index-Bc1y36ct.js} +3 -3
- package/src/assets/web-panel/assets/{index-DEsKGcgq.js → index-BcqrzCOI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCFBPPL3.js → index-BmieBFpM.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7PjxVkg.js → index-BzJsjPb9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiJrDiUF.js → index-CAZl_jZJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-_6PfzLBb.js → index-CNTOYZQJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-WNRdmI1g.js → index-CSzLUjjZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CyNkEBra.js → index-CXFtAKWy.js} +1 -1
- package/src/assets/web-panel/assets/{index-k_kmmJE3.js → index-Ctz762df.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFMqyOfS.js → index-D4E97124.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMvB7bwt.js → index-D50I92to.js} +1 -1
- package/src/assets/web-panel/assets/{index-Njlbk8o6.js → index-D72pZlFa.js} +1 -1
- package/src/assets/web-panel/assets/index-DBC8yuEG.js +1 -0
- package/src/assets/web-panel/assets/{index-BBdlh4S9.js → index-DD9PcRt3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Djr_9TsG.js → index-DDzdST6b.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxSrpYMm.js → index-DGDKCtU2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dr_bswHZ.js → index-DUkg9C1d.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0J2olcT.js → index-DaXHhqHE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHBCKhGQ.js → index-DcSZkELE.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhhReyyv.js → index-DdlzRBsd.js} +1 -1
- package/src/assets/web-panel/assets/{index-VjWPHPNA.js → index-DhHsdI-s.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsWempjh.js → index-DigxhXCh.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoiTovAz.js → index-Dk6Mp5o3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcDzDXuF.js → index-Dm47rSqn.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFeaJhkI.js → index-DnxPhaUe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOrH71r5.js → index-DpAeo8Y1.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4OJtXb2.js → index-Dz_IGu03.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5edbioK.js → index-JR5iJ3Nm.js} +1 -1
- package/src/assets/web-panel/assets/{index-C8E575em.js → index-cgs0nxzF.js} +1 -1
- package/src/assets/web-panel/assets/{index-C6ORJpUJ.js → index-czxh_xOe.js} +1 -1
- package/src/assets/web-panel/assets/index-z9Rtlw7F.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-V7_xvS9N.js → initDefaultProps-DqSLMT1R.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DRGZ-HPK.js → motion-DkdJz9l-.js} +1 -1
- package/src/assets/web-panel/assets/{move-CZrcQSMV.js → move-oonN7lOc.js} +1 -1
- package/src/assets/web-panel/assets/{omit-pd-_NH99.js → omit-BeFyiGwR.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CTupbn-v.js → pickAttrs-OePKGTKF.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Bn7FYxHg.js → placementArrow-CjQXhAph.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-WfzZR_7N.js → responsiveObserve-Dmn9lUes.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CYH80N3q.js → slide-Dfi_sykC.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C4hqTJzV.js → statusUtils-Dl9mPVld.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BQyUObAw.js → styleChecker-D3ay9a4W.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BGDH_gNt.js → useFlexGapSupport-D07_5fY3.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-D_3Y1Yh6.js → useFs-D3axlil7.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-vnU0oI0p.js → usePersonalDataHub-CR53u77i.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DnTqtAMj.js → vnode-DNOIJ4an.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-ChHcZlUk.js → zoom-MIAkyImQ.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/browse.js +2 -12
- package/src/commands/doctor.js +15 -0
- package/src/commands/hub.js +15 -91
- package/src/commands/note.js +13 -10
- package/src/lib/did-manager.js +9 -2
- package/src/lib/goal-store.js +23 -0
- package/src/lib/instinct-manager.js +8 -2
- package/src/lib/memory-manager.js +7 -3
- package/src/lib/sql-like.js +23 -0
- package/src/lib/update-notice.js +34 -10
- package/src/lib/version-skew.js +111 -0
- package/src/repl/agent-repl.js +39 -0
- package/src/runtime/agent-core.js +19 -3
- package/src/runtime/diagnostics.js +23 -1
- package/src/runtime/headless-stream.js +45 -0
- package/src/assets/web-panel/assets/MobileProjects-4uY4YbFm.js +0 -1
- package/src/assets/web-panel/assets/Terminal-D0IC-PsM.js +0 -3
- package/src/assets/web-panel/assets/devWarning-BJYFLmEO.js +0 -1
- package/src/assets/web-panel/assets/index-BznL1yIS.js +0 -1
- package/src/assets/web-panel/assets/index-SDk3qvNU.js +0 -1
package/src/lib/update-notice.js
CHANGED
|
@@ -23,9 +23,11 @@ import { fileURLToPath } from "url";
|
|
|
23
23
|
import chalk from "chalk";
|
|
24
24
|
import semver from "semver";
|
|
25
25
|
import { VERSION } from "../constants.js";
|
|
26
|
+
import { readDiskVersion } from "./version-skew.js";
|
|
26
27
|
|
|
27
28
|
export const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
28
|
-
export const NPM_LATEST_URL =
|
|
29
|
+
export const NPM_LATEST_URL =
|
|
30
|
+
"https://registry.npmjs.org/chainlesschain/latest";
|
|
29
31
|
|
|
30
32
|
export const _deps = {
|
|
31
33
|
fs: fsDefault,
|
|
@@ -71,7 +73,15 @@ export function maybeNotifyUpdate(opts = {}) {
|
|
|
71
73
|
const env = opts.env || process.env;
|
|
72
74
|
const now = opts.now ?? Date.now();
|
|
73
75
|
const isTTY = opts.isTTY ?? Boolean(process.stderr.isTTY);
|
|
74
|
-
|
|
76
|
+
// `running` = the version THIS process loaded at spawn (baked VERSION).
|
|
77
|
+
// `installed` = the version on disk RIGHT NOW (a fresh package.json read).
|
|
78
|
+
// They diverge after `npm i -g` runs under a long-lived process: the files
|
|
79
|
+
// update but the running process keeps the old code. We therefore compare the
|
|
80
|
+
// INSTALLED version against npm latest (so a stale process never nags
|
|
81
|
+
// "npm i -g" when disk is already current), and separately flag a
|
|
82
|
+
// running<installed skew as "restart to apply" (re-installing wouldn't help).
|
|
83
|
+
const running = opts.currentVersion || VERSION;
|
|
84
|
+
const installed = opts.installedVersion ?? readDiskVersion() ?? running;
|
|
75
85
|
const print =
|
|
76
86
|
opts.print || ((line) => process.stderr.write(chalk.gray(line) + "\n"));
|
|
77
87
|
|
|
@@ -85,11 +95,25 @@ export function maybeNotifyUpdate(opts = {}) {
|
|
|
85
95
|
isTTY &&
|
|
86
96
|
cache?.latest &&
|
|
87
97
|
semver.valid(cache.latest) &&
|
|
88
|
-
semver.valid(
|
|
89
|
-
semver.gt(cache.latest,
|
|
98
|
+
semver.valid(installed) &&
|
|
99
|
+
semver.gt(cache.latest, installed)
|
|
90
100
|
) {
|
|
101
|
+
// A newer release exists on npm → a real upgrade is available.
|
|
91
102
|
print(
|
|
92
|
-
`Update available: chainlesschain ${
|
|
103
|
+
`Update available: chainlesschain ${installed} → ${cache.latest} (npm i -g chainlesschain · CC_UPDATE_NOTICE=0 to hide)`,
|
|
104
|
+
);
|
|
105
|
+
out.printed = true;
|
|
106
|
+
} else if (
|
|
107
|
+
isTTY &&
|
|
108
|
+
semver.valid(installed) &&
|
|
109
|
+
semver.valid(running) &&
|
|
110
|
+
semver.gt(installed, running)
|
|
111
|
+
) {
|
|
112
|
+
// Already updated on disk, but this process is older → restart to apply.
|
|
113
|
+
// Re-running `npm i -g` would be a no-op; the fix is to relaunch cc / the
|
|
114
|
+
// IDE panel so the new code loads.
|
|
115
|
+
print(
|
|
116
|
+
`cc was updated ${running} → ${installed} on disk — restart cc (or reload your IDE panel) to apply (CC_UPDATE_NOTICE=0 to hide)`,
|
|
93
117
|
);
|
|
94
118
|
out.printed = true;
|
|
95
119
|
}
|
|
@@ -103,11 +127,11 @@ export function maybeNotifyUpdate(opts = {}) {
|
|
|
103
127
|
deps.path.dirname(fileURLToPath(import.meta.url)),
|
|
104
128
|
"update-notice-refresh.mjs",
|
|
105
129
|
);
|
|
106
|
-
const child = deps.spawn(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
);
|
|
130
|
+
const child = deps.spawn(process.execPath, [refresher, cachePath(deps)], {
|
|
131
|
+
detached: true,
|
|
132
|
+
stdio: "ignore",
|
|
133
|
+
windowsHide: true,
|
|
134
|
+
});
|
|
111
135
|
if (child && typeof child.unref === "function") child.unref();
|
|
112
136
|
out.spawned = true;
|
|
113
137
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect when the cc package was updated on disk AFTER this process spawned.
|
|
3
|
+
*
|
|
4
|
+
* A long-lived cc process — an IDE chat-panel `cc agent --input-format
|
|
5
|
+
* stream-json` session, or an interactive REPL — loads its JavaScript into
|
|
6
|
+
* memory at spawn time. `npm i -g chainlesschain@latest` only rewrites the
|
|
7
|
+
* files on disk; it does NOT reload an already-running process. So after an
|
|
8
|
+
* update the still-running session keeps executing the OLD in-memory code.
|
|
9
|
+
*
|
|
10
|
+
* This is exactly how a fixed bug looks "not fixed": the user updates cc, but
|
|
11
|
+
* the IDE panel's persistent agent process never restarted, so it keeps the old
|
|
12
|
+
* behaviour (e.g. the provider-auth-hijack → haiku). We surface a friendly,
|
|
13
|
+
* one-time notice telling them to reload the IDE window / restart the session.
|
|
14
|
+
*
|
|
15
|
+
* `VERSION` (constants.js) is baked at module load (a cached `require()` of
|
|
16
|
+
* package.json) → the SPAWN-TIME version. A FRESH read of package.json from
|
|
17
|
+
* disk → the CURRENTLY-INSTALLED version. Disk strictly newer ⇒ skew.
|
|
18
|
+
*/
|
|
19
|
+
import fs from "node:fs";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
import { dirname, join } from "node:path";
|
|
22
|
+
import semver from "semver";
|
|
23
|
+
import { VERSION } from "../constants.js";
|
|
24
|
+
|
|
25
|
+
const PKG_PATH = join(
|
|
26
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
27
|
+
"..",
|
|
28
|
+
"..",
|
|
29
|
+
"package.json",
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Currently-installed version — a FRESH read of package.json from disk that
|
|
34
|
+
* bypasses the require cache (so it reflects a post-update file). Returns null
|
|
35
|
+
* on any error (missing/unreadable/invalid file → "no skew, stay quiet").
|
|
36
|
+
*
|
|
37
|
+
* @param {(p: string) => string} [readFile] injectable for tests
|
|
38
|
+
*/
|
|
39
|
+
export function readDiskVersion(readFile = (p) => fs.readFileSync(p, "utf-8")) {
|
|
40
|
+
try {
|
|
41
|
+
const v = JSON.parse(readFile(PKG_PATH))?.version;
|
|
42
|
+
return typeof v === "string" && v.trim() ? v.trim() : null;
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Pure skew check. Returns `{ loaded, installed }` ONLY when `installed` is a
|
|
50
|
+
* valid semver STRICTLY GREATER than `loaded` (an update landed under a running
|
|
51
|
+
* process). Returns null otherwise — same version, a downgrade, or anything
|
|
52
|
+
* unparseable — so we never nag spuriously.
|
|
53
|
+
*
|
|
54
|
+
* @param {object} [o]
|
|
55
|
+
* @param {string} [o.loaded] version this process is running (default: VERSION)
|
|
56
|
+
* @param {string} [o.installed] version on disk now (default: fresh disk read)
|
|
57
|
+
*/
|
|
58
|
+
export function detectVersionSkew({
|
|
59
|
+
loaded = VERSION,
|
|
60
|
+
installed = readDiskVersion(),
|
|
61
|
+
} = {}) {
|
|
62
|
+
if (!loaded || !installed || loaded === installed) return null;
|
|
63
|
+
let newer = false;
|
|
64
|
+
try {
|
|
65
|
+
newer =
|
|
66
|
+
semver.valid(installed) != null &&
|
|
67
|
+
semver.valid(loaded) != null &&
|
|
68
|
+
semver.gt(installed, loaded);
|
|
69
|
+
} catch {
|
|
70
|
+
newer = false;
|
|
71
|
+
}
|
|
72
|
+
return newer ? { loaded, installed } : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Three-way version diagnosis for `cc doctor`: the version this process is
|
|
77
|
+
* RUNNING, the version INSTALLED on disk, and the LATEST published on npm.
|
|
78
|
+
* Distinguishes the two distinct "you're behind" cases:
|
|
79
|
+
* - installed < latest → a real upgrade exists → `npm i -g`
|
|
80
|
+
* - running < installed → already updated on disk → restart to apply
|
|
81
|
+
* Otherwise "current". Pure; unknown/invalid inputs degrade gracefully.
|
|
82
|
+
*
|
|
83
|
+
* @param {object} o { running, installed, latest } (any may be null/invalid)
|
|
84
|
+
* @returns {{running:string|null, installed:string|null, latest:string|null,
|
|
85
|
+
* status:"current"|"outdated"|"skew", message:string}}
|
|
86
|
+
*/
|
|
87
|
+
export function versionDiagnosis({ running, installed, latest } = {}) {
|
|
88
|
+
const ok = (v) => (typeof v === "string" && semver.valid(v) ? v : null);
|
|
89
|
+
const r = ok(running);
|
|
90
|
+
const i = ok(installed) || r; // fall back to running when disk read failed
|
|
91
|
+
const l = ok(latest);
|
|
92
|
+
let status = "current";
|
|
93
|
+
let message = "cc is up to date.";
|
|
94
|
+
if (l && i && semver.gt(l, i)) {
|
|
95
|
+
status = "outdated";
|
|
96
|
+
message = `A newer cc is available: ${i} → ${l}. Upgrade: npm i -g chainlesschain`;
|
|
97
|
+
} else if (r && i && semver.gt(i, r)) {
|
|
98
|
+
status = "skew";
|
|
99
|
+
message = `cc was updated ${r} → ${i} on disk — restart cc (or reload your IDE panel) to apply.`;
|
|
100
|
+
}
|
|
101
|
+
return { running: r, installed: i, latest: l, status, message };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Friendly one-line notice (Chinese) for a detected skew. */
|
|
105
|
+
export function versionSkewMessage({ loaded, installed } = {}) {
|
|
106
|
+
return (
|
|
107
|
+
`cc 已更新到 ${installed}(当前会话仍在运行 ${loaded})。` +
|
|
108
|
+
`请重新加载 IDE 窗口(VS Code: 命令面板 → Developer: Reload Window)` +
|
|
109
|
+
`或重启此会话,以应用更新。`
|
|
110
|
+
);
|
|
111
|
+
}
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -186,12 +186,25 @@ async function executeTool(name, args) {
|
|
|
186
186
|
*/
|
|
187
187
|
async function agentLoop(messages, options) {
|
|
188
188
|
const usageEvents = [];
|
|
189
|
+
// Visible cross-vendor fallback notice: a silent switch from the configured
|
|
190
|
+
// provider onto another vendor (or a baseUrl relabel) is surfaced as a yellow
|
|
191
|
+
// line, so "configured X but it ran Y" never happens quietly. Callers may
|
|
192
|
+
// override; default prints to the REPL.
|
|
193
|
+
const onProviderFallback =
|
|
194
|
+
options.onProviderFallback ||
|
|
195
|
+
((info) =>
|
|
196
|
+
process.stdout.write(
|
|
197
|
+
chalk.yellow(
|
|
198
|
+
`\n ⚠️ ${info.message || `已从 "${info.from}" 切换到 "${info.to}"`}\n`,
|
|
199
|
+
),
|
|
200
|
+
));
|
|
189
201
|
// The REPL runs its own auto-compaction (after each turn, with metrics +
|
|
190
202
|
// persisted compact events), so opt out of the agent loop's in-loop
|
|
191
203
|
// compaction to avoid compacting the same history twice.
|
|
192
204
|
for await (const event of coreAgentLoop(messages, {
|
|
193
205
|
autoCompact: false,
|
|
194
206
|
...options,
|
|
207
|
+
onProviderFallback,
|
|
195
208
|
})) {
|
|
196
209
|
if (event.type === "checkpoint") {
|
|
197
210
|
// Remember which file snapshot lines up with the live conversation so
|
|
@@ -1161,6 +1174,28 @@ export async function startAgentRepl(options = {}) {
|
|
|
1161
1174
|
);
|
|
1162
1175
|
logger.log(chalk.gray("Type /exit to quit, /help for commands\n"));
|
|
1163
1176
|
|
|
1177
|
+
// Version-skew reminder: if cc was updated on disk after this REPL spawned, it
|
|
1178
|
+
// is still running the old in-memory code (a fixed bug then looks "not fixed").
|
|
1179
|
+
// Tell the user to restart so the update takes effect. Checked at startup AND
|
|
1180
|
+
// again before each turn (see handleLine) so a mid-session `npm i -g` is
|
|
1181
|
+
// caught on the next prompt; emitted at most once. Best-effort.
|
|
1182
|
+
let _versionSkewNotified = false;
|
|
1183
|
+
const _notifyVersionSkew = async () => {
|
|
1184
|
+
if (_versionSkewNotified) return;
|
|
1185
|
+
try {
|
|
1186
|
+
const { detectVersionSkew, versionSkewMessage } =
|
|
1187
|
+
await import("../lib/version-skew.js");
|
|
1188
|
+
const skew = detectVersionSkew();
|
|
1189
|
+
if (skew) {
|
|
1190
|
+
_versionSkewNotified = true;
|
|
1191
|
+
logger.log(chalk.yellow(`⚠️ ${versionSkewMessage(skew)}\n`));
|
|
1192
|
+
}
|
|
1193
|
+
} catch {
|
|
1194
|
+
/* version-skew notice is best-effort */
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
await _notifyVersionSkew();
|
|
1198
|
+
|
|
1164
1199
|
// statusLine (Claude-Code parity): a line above the prompt each turn.
|
|
1165
1200
|
// - A user-configured `.claude/settings.json` `statusLine` command wins
|
|
1166
1201
|
// (model / branch / cost / … — first stdout line; best-effort, sync).
|
|
@@ -1258,6 +1293,10 @@ export async function startAgentRepl(options = {}) {
|
|
|
1258
1293
|
return;
|
|
1259
1294
|
}
|
|
1260
1295
|
|
|
1296
|
+
// Per-turn version-skew check (one-time): catches an `npm i -g` that landed
|
|
1297
|
+
// while this REPL kept running — the next prompt nudges a restart.
|
|
1298
|
+
await _notifyVersionSkew();
|
|
1299
|
+
|
|
1261
1300
|
// `!` bash passthrough (Claude-Code parity): run the command right here —
|
|
1262
1301
|
// no LLM round-trip — and fold the output into the conversation context.
|
|
1263
1302
|
if (trimmed.startsWith("!") && trimmed.slice(1).trim()) {
|
|
@@ -4294,10 +4294,26 @@ export async function* agentLoop(messages, options) {
|
|
|
4294
4294
|
await import("../lib/runnable-provider.js");
|
|
4295
4295
|
llmCall = makeRunnableProviderFallback(llmCall, {
|
|
4296
4296
|
onFallback: ({ from, to, reason }) => {
|
|
4297
|
+
// Switching VENDORS (or relabelling via baseUrl) must NEVER be silent —
|
|
4298
|
+
// a user who configured volcengine deserves to know it ran on another
|
|
4299
|
+
// provider/model. Build a human message and hand it to the driver's
|
|
4300
|
+
// visible surfacer (IDE panel → a rendered `raw` line; REPL → a yellow
|
|
4301
|
+
// line) when provided; otherwise fall back to a clear stderr notice.
|
|
4302
|
+
const message =
|
|
4303
|
+
reason === "env-key"
|
|
4304
|
+
? `"${from}" 鉴权失败,已临时切换到不同厂商 "${to}"(请检查 ${from} 的 API key:cc config set llm.apiKey …)。`
|
|
4305
|
+
: `provider 配置与 baseUrl 不一致,已按 baseUrl 切换到 "${to}"。`;
|
|
4306
|
+
const info = { from, to, reason, message };
|
|
4307
|
+
if (typeof options.onProviderFallback === "function") {
|
|
4308
|
+
try {
|
|
4309
|
+
options.onProviderFallback(info);
|
|
4310
|
+
} catch {
|
|
4311
|
+
/* surfacing is best-effort */
|
|
4312
|
+
}
|
|
4313
|
+
return;
|
|
4314
|
+
}
|
|
4297
4315
|
try {
|
|
4298
|
-
process.stderr.write(
|
|
4299
|
-
`\x1b[2m[provider] "${from}" auth failed (${reason}) — retrying with "${to}"\x1b[0m\n`,
|
|
4300
|
-
);
|
|
4316
|
+
process.stderr.write(`\x1b[33m[provider] ${message}\x1b[0m\n`);
|
|
4301
4317
|
} catch {
|
|
4302
4318
|
/* notice is best-effort */
|
|
4303
4319
|
}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { execSync } from "node:child_process";
|
|
16
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
16
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
17
|
+
import { join as pathJoin } from "node:path";
|
|
17
18
|
import { createRequire } from "node:module";
|
|
18
19
|
import { createConnection } from "node:net";
|
|
19
20
|
import semver from "semver";
|
|
@@ -28,6 +29,17 @@ import {
|
|
|
28
29
|
} from "../lib/service-manager.js";
|
|
29
30
|
import { loadConfig } from "../lib/config-manager.js";
|
|
30
31
|
import { isAppRunning, getAppPid } from "../lib/process-manager.js";
|
|
32
|
+
import { readDiskVersion, versionDiagnosis } from "../lib/version-skew.js";
|
|
33
|
+
|
|
34
|
+
/** Best-effort read of the npm `latest` cached by the startup update notice. */
|
|
35
|
+
function readCachedLatest() {
|
|
36
|
+
try {
|
|
37
|
+
const p = pathJoin(getHomeDir() || "", "update-check.json");
|
|
38
|
+
return JSON.parse(readFileSync(p, "utf-8"))?.latest || null;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
31
43
|
|
|
32
44
|
/**
|
|
33
45
|
* Probe a TCP port. Resolves true if something is listening.
|
|
@@ -250,9 +262,19 @@ export async function collectDoctorReport() {
|
|
|
250
262
|
const failed = checks.filter((c) => !c.ok);
|
|
251
263
|
const criticalFailed = failed.filter((c) => !c.optional);
|
|
252
264
|
|
|
265
|
+
// Three-way version check: running (this process) vs installed (on disk) vs
|
|
266
|
+
// latest (npm, from the update-notice cache). Tells the user whether they need
|
|
267
|
+
// `npm i -g` (a new release) or just a restart (already updated on disk).
|
|
268
|
+
const versionCheck = versionDiagnosis({
|
|
269
|
+
running: VERSION,
|
|
270
|
+
installed: readDiskVersion(),
|
|
271
|
+
latest: readCachedLatest(),
|
|
272
|
+
});
|
|
273
|
+
|
|
253
274
|
return {
|
|
254
275
|
schema: "chainlesschain.doctor.v1",
|
|
255
276
|
version: VERSION,
|
|
277
|
+
versionCheck,
|
|
256
278
|
generatedAt: new Date().toISOString(),
|
|
257
279
|
checks,
|
|
258
280
|
ports,
|
|
@@ -21,6 +21,7 @@ import { buildSystemPrompt, agentLoop as coreAgentLoop } from "./agent-core.js";
|
|
|
21
21
|
import { composeSystemPrompt } from "./system-prompt.js";
|
|
22
22
|
import { expandFileRefsAsync } from "./file-ref-expander.js";
|
|
23
23
|
import { detectImagePaths } from "../lib/image-input.js";
|
|
24
|
+
import { detectVersionSkew, versionSkewMessage } from "../lib/version-skew.js";
|
|
24
25
|
import {
|
|
25
26
|
resolveAgentMcp,
|
|
26
27
|
resolvePermissionPromptTool,
|
|
@@ -821,6 +822,20 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
821
822
|
attempt,
|
|
822
823
|
message: "API connection dropped — retrying",
|
|
823
824
|
}),
|
|
825
|
+
// Visible cross-vendor fallback notice: when the configured provider hits an
|
|
826
|
+
// auth error and the loop falls back to another vendor (or relabels via
|
|
827
|
+
// baseUrl), surface it as a `raw` info line the panel renders instead of a
|
|
828
|
+
// silent vendor switch. Structured fields carry the machine-readable detail.
|
|
829
|
+
onProviderFallback: (info) =>
|
|
830
|
+
emit({
|
|
831
|
+
type: "raw",
|
|
832
|
+
subtype: "provider_fallback",
|
|
833
|
+
text: `⚠️ ${info.message || `已从 "${info.from}" 切换到 "${info.to}"`}`,
|
|
834
|
+
from: info.from,
|
|
835
|
+
to: info.to,
|
|
836
|
+
reason: info.reason,
|
|
837
|
+
session_id: sessionId,
|
|
838
|
+
}),
|
|
824
839
|
};
|
|
825
840
|
|
|
826
841
|
// --max-budget-usd: a SESSION-WIDE USD spend cap across all turns. Folded
|
|
@@ -835,6 +850,12 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
835
850
|
|
|
836
851
|
let turns = 0;
|
|
837
852
|
let sawError = false;
|
|
853
|
+
// Version-skew notice (friendly reminder): a chat-panel agent process is
|
|
854
|
+
// long-lived, so if cc was updated on disk while it kept running, it's still
|
|
855
|
+
// executing stale in-memory code (a fixed bug then looks "not fixed"). Checked
|
|
856
|
+
// each turn until detected so a mid-session `npm i -g` is caught on the next
|
|
857
|
+
// message; emitted ONCE as a `raw` line the panel already renders.
|
|
858
|
+
let versionSkewNotified = false;
|
|
838
859
|
// Once any turn attaches an image, the image stays in the conversation
|
|
839
860
|
// history — so every later turn (even a text-only follow-up like "what colour
|
|
840
861
|
// is it?") must keep using the vision LLM, otherwise a text-only default model
|
|
@@ -915,6 +936,30 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
915
936
|
for (;;) {
|
|
916
937
|
const parsed = await nextEvent();
|
|
917
938
|
if (parsed == null) break; // stdin closed
|
|
939
|
+
|
|
940
|
+
// One-time version-skew reminder (see flag declaration above). Best-effort;
|
|
941
|
+
// never blocks a turn. detectVersionSkew() returns null when this process is
|
|
942
|
+
// running the currently-installed version, so a fresh/up-to-date session
|
|
943
|
+
// stays quiet.
|
|
944
|
+
if (!versionSkewNotified) {
|
|
945
|
+
try {
|
|
946
|
+
const skew = detectVersionSkew();
|
|
947
|
+
if (skew) {
|
|
948
|
+
versionSkewNotified = true;
|
|
949
|
+
emit({
|
|
950
|
+
type: "raw",
|
|
951
|
+
subtype: "version_skew",
|
|
952
|
+
text: `⚠️ ${versionSkewMessage(skew)}`,
|
|
953
|
+
running_version: skew.loaded,
|
|
954
|
+
installed_version: skew.installed,
|
|
955
|
+
session_id: sessionId,
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
} catch {
|
|
959
|
+
/* version-skew notice is best-effort */
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
918
963
|
if (parsed.error) {
|
|
919
964
|
emit({
|
|
920
965
|
type: "result",
|
|
@@ -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-C9a-SDrB.js";import{a7 as M,M as y}from"./icons-DP3uiYxy.js";const B={__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 y},get FolderOutlined(){return M}};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 I=v(B,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-WMeFZn/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{I 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-C9a-SDrB.js";import{I as z,J as x,U as _,Q as D,S as K,K as T,V as M,c as A,F as Q,Z as Y,R as E,o as G,f as H,w as $,n as q,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,F=new Set,N=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)),F.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)),N.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)}):(F.add(a),()=>F.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)}):(N.add(a),()=>N.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,R=null;async function I(){if(O)return{xtermMod:O,fitAddonMod:R};try{O=await U(()=>import("./xterm-BZcWGsqw.js").then(t=>t.x),__vite__mapDeps([0,1,2]),import.meta.url),R=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:R}}async function B(t){await q();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 J of v)m.write(J.data),t.lastSeq=J.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 B(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,q(()=>{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 B(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,()=>{q(()=>{const t=h.value;try{t?.fitAddon?.fit()}catch{}})});const Z={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 R},set fitAddonMod(t){R=t},loadXterm:I,mountXterm:B,onCreate:re,onClose:se,removeSession:W,activate:le,refreshList:X,ref:S,computed:ee,onMounted:G,onBeforeUnmount:H,nextTick:q,watch:$,get message(){return V},get PlusOutlined(){return ge},get CloseOutlined(){return pe},get ReloadOutlined(){return ye},get useTerminal(){return oe}};return Object.defineProperty(Z,"__isScriptSetup",{enumerable:!1,value:!0}),Z}},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"},Me={class:"session-id"},Re={key:0,class:"session-empty"},ze={class:"xterm-host"},Le=["data-session-id"],Pe={key:0,class:"xterm-placeholder"},De={key:1,class:"terminal-footer"},qe={key:0,class:"footer-exit"};function Be(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]=D(" 桌面端托管的 PTY 会话;Android 端可远程操控同一通道 ",-1)),e.warning?(y(),K(u,{key:0,color:"orange",style:{"margin-left":"8px"}},{default:T(()=>[D(E(e.warning),1)]),_:1})):M("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]=D(" 新会话 ",-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]=D(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.error?(y(),K(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"])):M("v-if",!0),_("div",Ae,[_("div",Ee,[(y(!0),x(Q,null,Y(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",Me,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",Re,' 点击 "新会话" 创建第一个终端 ')):M("v-if",!0)]),_("div",ze,[(y(!0),x(Q,null,Y(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)])])):M("v-if",!0)])]),e.active?(y(),x("div",De,[_("span",null,E(e.active.shell)+" · "+E(e.active.cwd||"(默认 cwd)")+" · seq "+E(e.active.lastSeq),1),e.active.alive?M("v-if",!0):(y(),x("span",qe,"已退出 (code="+E(e.active.exitCode??"-")+")",1))])):M("v-if",!0)])}const Ne=me(Se,[["render",Be],["__scopeId","data-v-65366a29"],["__file","/tmp/cc-web-panel-WMeFZn/repo/packages/web-panel/src/views/Terminal.vue"]]);export{Ne as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as r}from"./index-C9a-SDrB.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-t_vUszuS.js";import{U as t}from"./index-C9a-SDrB.js";import"./vendor-BvqAck49.js";import"./index-C6ORJpUJ.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-D7LuPQVP.js";import{U as t}from"./index-C9a-SDrB.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-WfzZR_7N.js";import"./useFlexGapSupport-BGDH_gNt.js";import"./styleChecker-BQyUObAw.js";import"./index-C6ORJpUJ.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
|