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.
Files changed (163) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-D1_eyrEP.js → AIOps-DHRc0Ie_.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-tnrMeU0Q.js → ActionButton-CgUXfXke.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-SmbOMqoN.js → Analytics-DIKHjclG.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-B4m4Ic3a.js → AppLayout-vX1r-6CY.js} +5 -5
  6. package/src/assets/web-panel/assets/{Audit-DTC34Qp6.js → Audit-DzJx-WeF.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-CU_llIBF.js → Backup-DZ4na4uj.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-vP66eF17.js → BaseInput-qUEPpz0X.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-B8-4iHVJ.js → Chat-DTZl8nH5.js} +6 -6
  10. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CFD0Xh5e.js → ChatBubbleRenderer-DD2tLmRr.js} +1 -1
  11. package/src/assets/web-panel/assets/{Checkbox-zV2Jzmv8.js → Checkbox-BQFF8-dn.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-C7kfk-rY.js → Codegen-DIQaC76u.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-t_vUszuS.js → Col-uy6MSNXM.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-pRCzzaCc.js → Community-DJSclfR8.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-7IgSGjnW.js → Compact-DS2_Cpq1.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-BqDi7iuY.js → Compliance-T6LqAmah.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-BL84ZaWT.js → Cowork-BrqyP337.js} +2 -2
  18. package/src/assets/web-panel/assets/{Cron-yzv32Scr.js → Cron-DYFCc-f1.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-6DTzS8P5.js → Crosschain-CnWNsqde.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-CKP63O4a.js → DID-Cno6plcv.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-CsV3eP9F.js → Dashboard-CsgzRLsJ.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-CByjFKzJ.js → Dropdown-BUKI1xuG.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-C6Hn7n75.js → EmailListRenderer-DuEOjlci.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard-e1c1vXTT.js → FamilyGuardDashboard-BfnUdEaU.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-D9oejCYY.js → Federation-CfeUTibi.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-DZ4d_-AT.js → FormItemContext-D14wwVsq.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-QoGFWBcP.js → GenericCardRenderer-CGx7VfKf.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-DVZHPXw8.js → Git-chaiL5nL.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-NwdvDPTB.js → Governance-Ca5rbA-N.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-BYz9MiEu.js → Inference-DA0DK7dc.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph-BUdGIZKt.js → KnowledgeGraph-BwaAK34_.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-CPGewhlD.js → Logs-FA4XPXuO.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-BgRk4ZMW.js → Marketplace-eOsO5rY3.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-DLY9Fd7m.js → McpTools-D88TlCnE.js} +5 -5
  35. package/src/assets/web-panel/assets/{Memory-B2QishHE.js → Memory-DsIN2Sv6.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-DXMQwB_y.js → MobileBridge--q60qDOY.js} +2 -2
  37. package/src/assets/web-panel/assets/MobileProjects-84NgjQck.js +1 -0
  38. package/src/assets/web-panel/assets/{Mtc-BVASCKUv.js → Mtc-BYfKH7WL.js} +2 -2
  39. package/src/assets/web-panel/assets/{MtcAudit-ByLFJ4Zu.js → MtcAudit-D35u_eyo.js} +4 -4
  40. package/src/assets/web-panel/assets/{Multisig-DRAZYcC6.js → Multisig-BksPgmCa.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-EiptSKn1.js → NLProgramming-D5cbMuDm.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-BHh5Akqh.js → Notes-Cu_pbWTB.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-XWFl4_3j.js → NotificationSettings-C81tVX8S.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-Bdc_O7wT.js → OrderTableRenderer-Ccx2Lxcc.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization--VWlMdKp.js → Organization-BIJzR15j.js} +4 -4
  46. package/src/assets/web-panel/assets/{Overflow-DuYUvyh7.js → Overflow-BKCASkRj.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-BnHaPvFP.js → P2P-Q4mb4TFL.js} +2 -2
  48. package/src/assets/web-panel/assets/{PdhVaultBrowser-WfbjffWL.js → PdhVaultBrowser-CPWIjtON.js} +3 -3
  49. package/src/assets/web-panel/assets/{Permissions-BIFhAsZO.js → Permissions-DCo0YoEd.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-Dt_m7YZ6.js → PersonalDataHub-CT-Efwnw.js} +3 -3
  51. package/src/assets/web-panel/assets/{Pipeline-BsNDbhs7.js → Pipeline-B5iEJ2T_.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-C1SJp30I.js → Privacy-BjOXW26f.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-DIOkwlK-.js → ProjectInit-DE6GZFCM.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings-BZIL8hvl.js → ProjectSettings-cHsBvsYo.js} +2 -2
  55. package/src/assets/web-panel/assets/{Projects-LHqWtiu2.js → Projects-Bi4Wv8m6.js} +1 -1
  56. package/src/assets/web-panel/assets/{Providers-DlC7SSJT.js → Providers-C0yVlpp5.js} +1 -1
  57. package/src/assets/web-panel/assets/{QuickAsk-DeaVcEma.js → QuickAsk-C6BQQUUw.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-BbQI1g_u.js → Recommend-Dz18iBwP.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-Cro6z2uR.js → Reputation-LagVnM_Q.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-D7LuPQVP.js → Row--IaheXkB.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-BowXZJOX.js → RssFeed-CDNYaijn.js} +3 -3
  62. package/src/assets/web-panel/assets/{Search-8oufqOmB.js → Search-D6DPr_Km.js} +1 -1
  63. package/src/assets/web-panel/assets/{Security-CRKFB58y.js → Security-a4-jIBqX.js} +3 -3
  64. package/src/assets/web-panel/assets/{Services-DzRJ4Kus.js → Services-Bmj4jr2Q.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-DtZmLaQr.js → Skeleton-BhKpCNqE.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skills-CPQFZvJ3.js → Skills-BqmheUDl.js} +1 -1
  67. package/src/assets/web-panel/assets/{Sla-C599OilU.js → Sla-D68DDW4T.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-VdhwHyYN.js → SpeechSettings-CxCF4E_o.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-BvX8fTlf.js → SyncSettings-pcetCirO.js} +2 -2
  70. package/src/assets/web-panel/assets/{Tasks-B63Y5zWj.js → Tasks-D3er3tkS.js} +1 -1
  71. package/src/assets/web-panel/assets/{Templates-DZtjohnP.js → Templates-6QfV55r3.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-C8WHv74j.js → Tenant-BOI2_4NB.js} +1 -1
  73. package/src/assets/web-panel/assets/Terminal-DSIv5Z7S.js +3 -0
  74. package/src/assets/web-panel/assets/{TimelineRenderer-C392mTJ7.js → TimelineRenderer-C4tC343-.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-BnmIK-7p.js → Tokens-CnNoHnJv.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-CLYUm45n.js → Trigger-BaRSXO70.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-DmKkB9n0.js → Trust-CWnKxwgN.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-Btsb1cq9.js → UkeySign-De8aN7WZ.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-KbSQiQ31.js → VideoEditing-Cu7XhMNZ.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-C7T1JpB8.js → Wallet-xfhJUu0f.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-B7fk675F.js → WebAuthn-Bt6sYYDk.js} +4 -4
  82. package/src/assets/web-panel/assets/{WorkflowEditor-BFEqg2-F.js → WorkflowEditor-C4LZ0x-0.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-CCONImPU.js → chat-33Oq8wz3.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-BO_usQco.js → colors-COL29MyD.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-DPYH8VmY.js → compact-item-D8hinshK.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-DuzinRx4.js → createContext-DVD4d6-0.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-CKV56AdO.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-CGE1laax.js → hasIn-CvLpycQb.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-CzJpaaYk.js → index-1HmyagUk.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-DhWFRGxq.js → index-3GhR2NdM.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-DPLKoezy.js → index-65FhG6v3.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-B6faWLbM.js → index-B2nqCkxx.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-BQieJh3P.js → index-B3Ja9sDO.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-Cjl3wd7u.js → index-B4L1oFlv.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BJrz4R1Q.js → index-BCJdqeDG.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-CLevxAAl.js → index-B_KT8dhv.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-C9a-SDrB.js → index-Bc1y36ct.js} +3 -3
  98. package/src/assets/web-panel/assets/{index-DEsKGcgq.js → index-BcqrzCOI.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CCFBPPL3.js → index-BmieBFpM.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-D7PjxVkg.js → index-BzJsjPb9.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CiJrDiUF.js → index-CAZl_jZJ.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-_6PfzLBb.js → index-CNTOYZQJ.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-WNRdmI1g.js → index-CSzLUjjZ.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CyNkEBra.js → index-CXFtAKWy.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-k_kmmJE3.js → index-Ctz762df.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CFMqyOfS.js → index-D4E97124.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BMvB7bwt.js → index-D50I92to.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Njlbk8o6.js → index-D72pZlFa.js} +1 -1
  109. package/src/assets/web-panel/assets/index-DBC8yuEG.js +1 -0
  110. package/src/assets/web-panel/assets/{index-BBdlh4S9.js → index-DD9PcRt3.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Djr_9TsG.js → index-DDzdST6b.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BxSrpYMm.js → index-DGDKCtU2.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-Dr_bswHZ.js → index-DUkg9C1d.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-C0J2olcT.js → index-DaXHhqHE.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CHBCKhGQ.js → index-DcSZkELE.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BhhReyyv.js → index-DdlzRBsd.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-VjWPHPNA.js → index-DhHsdI-s.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CsWempjh.js → index-DigxhXCh.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BoiTovAz.js → index-Dk6Mp5o3.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-DcDzDXuF.js → index-Dm47rSqn.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DFeaJhkI.js → index-DnxPhaUe.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BOrH71r5.js → index-DpAeo8Y1.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-C4OJtXb2.js → index-Dz_IGu03.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B5edbioK.js → index-JR5iJ3Nm.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C8E575em.js → index-cgs0nxzF.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-C6ORJpUJ.js → index-czxh_xOe.js} +1 -1
  127. package/src/assets/web-panel/assets/index-z9Rtlw7F.js +1 -0
  128. package/src/assets/web-panel/assets/{initDefaultProps-V7_xvS9N.js → initDefaultProps-DqSLMT1R.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-DRGZ-HPK.js → motion-DkdJz9l-.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-CZrcQSMV.js → move-oonN7lOc.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-pd-_NH99.js → omit-BeFyiGwR.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-CTupbn-v.js → pickAttrs-OePKGTKF.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-Bn7FYxHg.js → placementArrow-CjQXhAph.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-WfzZR_7N.js → responsiveObserve-Dmn9lUes.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-CYH80N3q.js → slide-Dfi_sykC.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-C4hqTJzV.js → statusUtils-Dl9mPVld.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-BQyUObAw.js → styleChecker-D3ay9a4W.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-BGDH_gNt.js → useFlexGapSupport-D07_5fY3.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-D_3Y1Yh6.js → useFs-D3axlil7.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-vnU0oI0p.js → usePersonalDataHub-CR53u77i.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-DnTqtAMj.js → vnode-DNOIJ4an.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-ChHcZlUk.js → zoom-MIAkyImQ.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/browse.js +2 -12
  145. package/src/commands/doctor.js +15 -0
  146. package/src/commands/hub.js +15 -91
  147. package/src/commands/note.js +13 -10
  148. package/src/lib/did-manager.js +9 -2
  149. package/src/lib/goal-store.js +23 -0
  150. package/src/lib/instinct-manager.js +8 -2
  151. package/src/lib/memory-manager.js +7 -3
  152. package/src/lib/sql-like.js +23 -0
  153. package/src/lib/update-notice.js +34 -10
  154. package/src/lib/version-skew.js +111 -0
  155. package/src/repl/agent-repl.js +39 -0
  156. package/src/runtime/agent-core.js +19 -3
  157. package/src/runtime/diagnostics.js +23 -1
  158. package/src/runtime/headless-stream.js +45 -0
  159. package/src/assets/web-panel/assets/MobileProjects-4uY4YbFm.js +0 -1
  160. package/src/assets/web-panel/assets/Terminal-D0IC-PsM.js +0 -3
  161. package/src/assets/web-panel/assets/devWarning-BJYFLmEO.js +0 -1
  162. package/src/assets/web-panel/assets/index-BznL1yIS.js +0 -1
  163. package/src/assets/web-panel/assets/index-SDk3qvNU.js +0 -1
@@ -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 = "https://registry.npmjs.org/chainlesschain/latest";
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
- const current = opts.currentVersion || VERSION;
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(current) &&
89
- semver.gt(cache.latest, current)
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 ${current} → ${cache.latest} (npm i -g chainlesschain · CC_UPDATE_NOTICE=0 to hide)`,
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
- process.execPath,
108
- [refresher, cachePath(deps)],
109
- { detached: true, stdio: "ignore", windowsHide: true },
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
+ }
@@ -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};