chainlesschain 0.162.151 → 0.162.152
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/README.md +1 -1
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-DuEOzebi.js → AIOps-CVLVJS-Q.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C6GiJa5H.js → ActionButton-CJ2_GJsI.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BBIiL_pO.js → Analytics-CZsmlTF8.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-CuI2gZRy.js → AppLayout-DREvMZ62.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-CbUjfr-K.js → Audit-B4NR42w_.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CsSW9ljf.js → Backup-CJFmf3In.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-kM3rLe7F.js → BaseInput-Bh8_iUZY.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-kfE51YN3.js → Chat-DEwKjIxV.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BOqHkxK_.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-jYb1uj-M.js → Checkbox-DYWCqYI9.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-X9XiD5Lj.js → Codegen-BlXrfZAJ.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BfbHu1xI.js → Col-DLPM22eX.js} +1 -1
- package/src/assets/web-panel/assets/{Community-c4oJMFS-.js → Community-PFyzqijs.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BFmnZpH7.js → Compact-7DIfY5Wp.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-s9shVHBS.js → Compliance-DF4CinPU.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-C5da--TC.js → Cowork-B1J80Vcj.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-9kNbyNE4.js → Cron-B7sx2OXX.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-C1k3NJD4.js → Crosschain-omLkxmu-.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DkheEvNK.js → DID-B_7r7b5F.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C3FuSGmJ.js → Dashboard-Cp7k3GZg.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CAV6FMFD.js → Dropdown-BCKO89Y8.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-Cc-Ulc4l.js → EmailListRenderer-CNgTSsFZ.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-8CitHEtv.js → FamilyGuardDashboard-DobM83JP.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DFSZ5KDt.js → Federation-XVAYQIeu.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CEWCtnG2.js → FormItemContext-DV5ka1KQ.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CwRzNzmX.js → GenericCardRenderer-Dg5q-KpC.js} +1 -1
- package/src/assets/web-panel/assets/{Git-0rgDM7cJ.js → Git-Dsn3Xhxf.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CfBKtK9F.js → Governance-D06S4Qow.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CzcUVvud.js → Inference-nAvwxUXy.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Dwc4YL4A.js → KnowledgeGraph-CtqRP_rF.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DgFPwR2F.js → Logs-J5aGAyfY.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-DnpPTbGU.js → Marketplace-CaeY23Kj.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DRxxINyW.js → McpTools-C2HHnwnE.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-OhmW_6Z3.js → Memory-CWBrdKlR.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DkTW-RK5.js → MobileBridge-CBLQ8uCY.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DpCGV_lI.js → MobileProjects-Q_Cy_W4_.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc--vmkL0AS.js → Mtc-BXur-euo.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-DGoFWjD4.js → MtcAudit-CpQSlOQC.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-B4kWgq95.js → Multisig-DlFwdEOA.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-YQwvommE.js → NLProgramming-DSh7fevc.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CgjtUADJ.js → Notes-Bv4NOVxg.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-6JDrpBG5.js → NotificationSettings-CzHNnIfa.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-PM6IlxjO.js → OrderTableRenderer-D7pHfKK4.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-8McOT_OF.js → Organization-COzV01ed.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DAZpSCGc.js → Overflow-CYRZJb2_.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-B7l2ZWLy.js → P2P-DFm49FE0.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-W1Ud-NAL.js → PdhVaultBrowser-Ctr-6k5B.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-Czm_w9u_.js → Permissions-DXVrhFyv.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B4F0_ZVM.js → PersonalDataHub-BO5utpLK.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-B37aFiWv.js → Pipeline-C9irYCg7.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-94KBnRrD.js → Privacy-r13hrvoF.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B5h8_dlh.js → ProjectInit-PRKNPZZC.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-lmeI3Lpm.js → ProjectSettings-QvxM1ZDO.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-D5AYOasl.js → Projects-DfgmsN3j.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-B3cNWwJg.js → Providers-DxbrccZ7.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CHRvOw1R.js → QrScannerModal-BMHVRxBX.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D1JMgFEd.js → QuickAsk-Co3_ndAH.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-EYWGR79p.js → Recommend-Cv3UWR6s.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BAMC2pJt.js → RemoteSession-CSDsO2zA.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-X2Hk1XG_.js → Reputation-Bdj59vzM.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Eq98LRtU.js → Row-CejfUjmo.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-i76s6z_o.js → RssFeed-C83yKkvU.js} +2 -2
- package/src/assets/web-panel/assets/{Search-D_Es7CAI.js → Search-Ck4l_VI3.js} +1 -1
- package/src/assets/web-panel/assets/{Security-kayD2e94.js → Security-DGIIEx6K.js} +3 -3
- package/src/assets/web-panel/assets/{Services-Ctsm6ul8.js → Services-Cj2aNAy3.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CRNYlfdf.js → Skeleton-Dlyy8akb.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DkZYpF4-.js → Skills-C4aDa9Zh.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DXkoBcOP.js → Sla-tHd_Bauo.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DXi_GI1d.js → SpeechSettings-DI7R0Qgd.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-rNKpfomn.js → SyncSettings-OOxiPdsE.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-XF4uPtG-.js → Tasks-Nro_Ltg5.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-i0Hzfeyu.js → Templates-Bm7eSMWH.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-sMpHAi27.js → Tenant-B8F8eFvD.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-2oWhR7QF.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-yuC6K7Rf.js → TimelineRenderer-GLnecmpd.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B8O8i0s6.js → Tokens-CtpFyati.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Bv6yrlCr.js → Trigger-DGkXZzbN.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-C4mW95Ev.js → Trust-ClYZMkXN.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DV6yKaHn.js → UkeySign-C1AuEW5-.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-UI479-sD.js → VideoEditing-DHa9ekSK.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-M5oV9EVP.js → Wallet-CyQv8ZAN.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DDyDHPDR.js → WebAuthn-DPxEEb5Y.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-RoBv4rqk.js → WorkflowEditor-C-fCM8Si.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Cw1mE5LS.js → chat-BMu1Pk8B.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BFP62Gwf.js → colors-DYPOXyWQ.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-17HL6pyC.js → compact-item-C5r_plPk.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D55X4fZX.js → createContext-9fWrWmuJ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DmRz5Pet.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D3E5mNsP.js → hasIn-CjZM2-qE.js} +1 -1
- package/src/assets/web-panel/assets/{index-KtLJXn4s.js → index-0DVMoDzF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzG7mkgW.js → index-B1iUe3Ba.js} +1 -1
- package/src/assets/web-panel/assets/{index-Da27u6j0.js → index-B56CI20h.js} +1 -1
- package/src/assets/web-panel/assets/{index-uSsiwgZ2.js → index-BBVCXmJV.js} +1 -1
- package/src/assets/web-panel/assets/{index-tUH_6bdJ.js → index-BPucc_ES.js} +1 -1
- package/src/assets/web-panel/assets/{index-DD_qGBrt.js → index-BVFtY8Y4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjCwi7we.js → index-BW-x3mUK.js} +1 -1
- package/src/assets/web-panel/assets/{index-gAVxDiTZ.js → index-B_bTdeou.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW6LLoJO.js → index-Bglw_kmu.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkBVYlE4.js → index-BsHmE__1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BY_xZ2jy.js → index-Bti4lpw5.js} +1 -1
- package/src/assets/web-panel/assets/{index-H9_X1Cg_.js → index-ByVDaARk.js} +1 -1
- package/src/assets/web-panel/assets/{index--44J50mc.js → index-C3E7xVl1.js} +1 -1
- package/src/assets/web-panel/assets/{index-CR9rNUvi.js → index-CDaA4A0b.js} +1 -1
- package/src/assets/web-panel/assets/{index-BgN5G5vF.js → index-CGqrVLWe.js} +27 -27
- package/src/assets/web-panel/assets/{index-D4LHSde4.js → index-CJJx0kbR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cdvk2_2q.js → index-CTnaRErh.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCLu84x-.js → index-CYoS2cwK.js} +1 -1
- package/src/assets/web-panel/assets/{index-paVubXzn.js → index-CcDGi9U1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQmZg5si.js → index-Cd9_KCPs.js} +1 -1
- package/src/assets/web-panel/assets/{index-tVRPgYGr.js → index-Co9kBFxY.js} +1 -1
- package/src/assets/web-panel/assets/index-CrsL7YBW.js +1 -0
- package/src/assets/web-panel/assets/{index-DIRvdwBX.js → index-CvUR6l7C.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq83UBDr.js → index-CyUtBxnC.js} +1 -1
- package/src/assets/web-panel/assets/{index-CvCFKojj.js → index-D0rFX-xN.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bzpp2z2S.js → index-D6zyUpD6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnGpft-Z.js → index-DJk9cPrs.js} +1 -1
- package/src/assets/web-panel/assets/{index-ITeEHb8L.js → index-DLCoKst9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFYGn88j.js → index-DNxR1CHs.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOjA8bvj.js → index-DWwI0Jjd.js} +1 -1
- package/src/assets/web-panel/assets/{index-RYZgFIwo.js → index-DjTB4wPn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLEzsZ8A.js → index-Du-w2i6G.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtAnPBWP.js → index-HJdfPSMz.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEa1RW4c.js → index-I3Qdrfcf.js} +1 -1
- package/src/assets/web-panel/assets/{index-ASPYTzMK.js → index-Mipa7XgU.js} +1 -1
- package/src/assets/web-panel/assets/{index-BC6zxOlU.js → index-jO4lIpFE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGyTos4p.js → index-oerotzoq.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_MfcrLf.js → index-phHPSXlV.js} +1 -1
- package/src/assets/web-panel/assets/index-zW69WSDA.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-Ckp7xVZS.js → initDefaultProps-B7tpABc_.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DUZgCpn6.js → motion-DmvaRoVv.js} +1 -1
- package/src/assets/web-panel/assets/{move-B2rttglH.js → move-DF4X29Wf.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BYWcLTuN.js → mtc-parser-C0cbg4PO.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DhHqKeFx.js → omit-DZzcYy0l.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-ANpJaWMO.js → pickAttrs-DaZWfzuH.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CfZWe7CA.js → placementArrow-CBxOEyvn.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D7Xz2y-R.js → responsiveObserve-CGl8NIlO.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DekqCBY9.js → slide-Bv330MSZ.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BET6XU7h.js → statusUtils-DJVy5oEM.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-qHmJjV62.js → styleChecker-BiY1H5ST.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BoMCTNyu.js → useFlexGapSupport-D1sN2OlQ.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-TdW-NgFC.js → useFs-DxxHawzW.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-Dyox7wCu.js → usePersonalDataHub-C1HblLrD.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-XUn5S8CP.js → vnode-Dex0jy4T.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Ls77i8hn.js → zoom-Bk1MScAD.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +8 -1
- package/src/commands/eval.js +88 -23
- package/src/commands/plugin.js +10 -0
- package/src/commands/team.js +26 -3
- package/src/data/changelog.json +12 -2
- package/src/harness/remote-command-ledger.js +60 -10
- package/src/lib/agent-sandbox.js +11 -5
- package/src/lib/agent-team/task-lease.js +28 -0
- package/src/lib/agent-team/team-runner.js +25 -0
- package/src/lib/eval/tasks.js +62 -41
- package/src/lib/eval/trend.js +7 -1
- package/src/lib/lsp/__tests__/lsp-client.test.js +12 -6
- package/src/lib/lsp/code-intelligence.js +55 -17
- package/src/lib/lsp/lsp-client.js +7 -1
- package/src/lib/plugin-runtime/install.js +20 -1
- package/src/lib/plugin-runtime/policy.js +13 -0
- package/src/lib/plugin-runtime/remote-source.js +34 -0
- package/src/lib/plugin-runtime/signature.js +79 -22
- package/src/lib/plugin-security.js +13 -14
- package/src/lib/telemetry/span-recorder.js +17 -6
- package/src/repl/agent-repl.js +12 -8
- package/src/runtime/__tests__/auto-pin.test.js +27 -4
- package/src/runtime/auto-pin.js +19 -0
- package/src/runtime/headless-runner.js +23 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Bg2FTW6A.js +0 -1
- package/src/assets/web-panel/assets/Terminal-BoZvaYAl.js +0 -3
- package/src/assets/web-panel/assets/devWarning-CqbHYuRc.js +0 -1
- package/src/assets/web-panel/assets/index-CKBI1U5K.js +0 -1
- package/src/assets/web-panel/assets/index-CkLp6DTO.js +0 -1
|
@@ -7,20 +7,24 @@
|
|
|
7
7
|
* install records the verification result in a `.plugin-lock.json` inside the
|
|
8
8
|
* immutable version dir; discovery then re-checks it fail-closed.
|
|
9
9
|
*
|
|
10
|
-
* The lock
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* The lock persists the DETACHED SIGNATURE + PUBLIC KEY themselves (lockVersion
|
|
11
|
+
* 2), and load-time verification re-runs the actual Ed25519 verify over the
|
|
12
|
+
* on-disk manifest bytes. The lock file lives in a writable plugin dir, so
|
|
13
|
+
* nothing in it can be TRUSTED — a recorded boolean or fingerprint could simply
|
|
14
|
+
* be forged by whoever authored the plugin. What a forger CANNOT do is produce a
|
|
15
|
+
* signature that verifies under a key the org has pinned via
|
|
16
|
+
* trustedPluginKeySha256 — which is why the key fingerprint used for the trust
|
|
17
|
+
* check is COMPUTED from the embedded public key, never read from the lock.
|
|
18
|
+
* The signature covers only the manifest file, not every component file — a
|
|
14
19
|
* known limitation (documented), an integrity anchor rather than a full
|
|
15
|
-
* supply-chain seal; the
|
|
16
|
-
* tampering, which is where the component wiring is declared.
|
|
20
|
+
* supply-chain seal; the manifest is where the component wiring is declared.
|
|
17
21
|
*/
|
|
18
22
|
|
|
19
|
-
import { createHash } from "node:crypto";
|
|
23
|
+
import { createHash, createPublicKey, verify } from "node:crypto";
|
|
20
24
|
import fs from "fs";
|
|
21
25
|
import path from "path";
|
|
22
26
|
|
|
23
|
-
const
|
|
27
|
+
export const LOCK_FILENAME = ".plugin-lock.json";
|
|
24
28
|
|
|
25
29
|
export const _deps = {
|
|
26
30
|
readFileSync: fs.readFileSync,
|
|
@@ -31,18 +35,29 @@ export const _deps = {
|
|
|
31
35
|
/** Record a verified signature into the version dir. */
|
|
32
36
|
export function writePluginLock(
|
|
33
37
|
versionDir,
|
|
34
|
-
{
|
|
38
|
+
{
|
|
39
|
+
manifestFile,
|
|
40
|
+
sha256,
|
|
41
|
+
publicKeySha256,
|
|
42
|
+
signatureVerified,
|
|
43
|
+
signatureBase64,
|
|
44
|
+
publicKeyPem,
|
|
45
|
+
},
|
|
35
46
|
) {
|
|
36
47
|
const rel = path.relative(versionDir, manifestFile).replace(/\\/g, "/");
|
|
37
48
|
const lock = {
|
|
38
|
-
lockVersion:
|
|
49
|
+
lockVersion: 2,
|
|
39
50
|
manifest: rel || "plugin.json",
|
|
40
51
|
sha256,
|
|
41
52
|
publicKeySha256: publicKeySha256 || null,
|
|
42
53
|
signatureVerified: signatureVerified === true,
|
|
54
|
+
// The material load-time enforcement actually re-verifies. Without these a
|
|
55
|
+
// lock is just self-asserted JSON and counts as unsigned.
|
|
56
|
+
signatureBase64: signatureBase64 || null,
|
|
57
|
+
publicKeyPem: publicKeyPem || null,
|
|
43
58
|
};
|
|
44
59
|
_deps.writeFileSync(
|
|
45
|
-
path.join(versionDir,
|
|
60
|
+
path.join(versionDir, LOCK_FILENAME),
|
|
46
61
|
JSON.stringify(lock, null, 2),
|
|
47
62
|
"utf8",
|
|
48
63
|
);
|
|
@@ -51,7 +66,7 @@ export function writePluginLock(
|
|
|
51
66
|
|
|
52
67
|
/** Read a version dir's signature lock, or null when absent/unreadable. */
|
|
53
68
|
export function readPluginLock(versionDir) {
|
|
54
|
-
const p = path.join(versionDir,
|
|
69
|
+
const p = path.join(versionDir, LOCK_FILENAME);
|
|
55
70
|
if (!_deps.existsSync(p)) return null;
|
|
56
71
|
try {
|
|
57
72
|
return JSON.parse(_deps.readFileSync(p, "utf8"));
|
|
@@ -62,9 +77,11 @@ export function readPluginLock(versionDir) {
|
|
|
62
77
|
|
|
63
78
|
/**
|
|
64
79
|
* Verify an installed plugin's recorded signature against its on-disk manifest.
|
|
65
|
-
* `signed:true` ONLY when a lock exists,
|
|
66
|
-
*
|
|
67
|
-
* is a non-empty Set — the signing key fingerprint
|
|
80
|
+
* `signed:true` ONLY when a lock exists, carries real signature material, the
|
|
81
|
+
* embedded Ed25519 signature VERIFIES over the on-disk manifest bytes, and —
|
|
82
|
+
* when trustedKeys is a non-empty Set — the signing key's COMPUTED fingerprint
|
|
83
|
+
* is among them. Every field of the lock is treated as attacker-writable; the
|
|
84
|
+
* only trust anchors are the cryptographic verify and the caller's trustedKeys.
|
|
68
85
|
*
|
|
69
86
|
* @param {{root:string}} plugin
|
|
70
87
|
* @param {object} [opts] { trustedKeys?: Set<string> }
|
|
@@ -96,28 +113,68 @@ export function verifyInstalledSignature(plugin, opts = {}) {
|
|
|
96
113
|
if (!_deps.existsSync(manifestFile)) {
|
|
97
114
|
return { signed: false, reason: "locked manifest file is missing" };
|
|
98
115
|
}
|
|
99
|
-
let
|
|
116
|
+
let bytes;
|
|
100
117
|
try {
|
|
101
|
-
|
|
102
|
-
.update(_deps.readFileSync(manifestFile))
|
|
103
|
-
.digest("hex");
|
|
118
|
+
bytes = _deps.readFileSync(manifestFile);
|
|
104
119
|
} catch {
|
|
105
120
|
return { signed: false, reason: "manifest unreadable" };
|
|
106
121
|
}
|
|
122
|
+
const sha = createHash("sha256").update(bytes).digest("hex");
|
|
107
123
|
if (sha.toLowerCase() !== String(lock.sha256 || "").toLowerCase()) {
|
|
108
124
|
return {
|
|
109
125
|
signed: false,
|
|
110
126
|
reason: "manifest tampered since install (sha256 mismatch)",
|
|
111
127
|
};
|
|
112
128
|
}
|
|
129
|
+
// A lock without real signature material is unverifiable, and therefore
|
|
130
|
+
// worthless as a signing gate: `signatureVerified:true` is just a JSON field
|
|
131
|
+
// anyone can write. Legacy (lockVersion 1) locks land here too — reinstalling
|
|
132
|
+
// the plugin with --signature re-records a verifiable lock.
|
|
133
|
+
if (!lock.signatureBase64 || !lock.publicKeyPem) {
|
|
134
|
+
return {
|
|
135
|
+
signed: false,
|
|
136
|
+
reason:
|
|
137
|
+
"lock lacks signature material (legacy or hand-written lock — " +
|
|
138
|
+
"reinstall the plugin with --signature to re-record it)",
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
let keyObject;
|
|
142
|
+
let publicKeySha256;
|
|
143
|
+
try {
|
|
144
|
+
keyObject = createPublicKey(lock.publicKeyPem);
|
|
145
|
+
// Fingerprint is COMPUTED from the embedded key — the lock's own
|
|
146
|
+
// publicKeySha256 field is attacker-writable and never used for trust.
|
|
147
|
+
publicKeySha256 = createHash("sha256")
|
|
148
|
+
.update(keyObject.export({ type: "spki", format: "der" }))
|
|
149
|
+
.digest("hex");
|
|
150
|
+
} catch {
|
|
151
|
+
return { signed: false, reason: "lock public key is not a valid key" };
|
|
152
|
+
}
|
|
153
|
+
let sigOk = false;
|
|
154
|
+
try {
|
|
155
|
+
sigOk = verify(
|
|
156
|
+
null,
|
|
157
|
+
bytes,
|
|
158
|
+
keyObject,
|
|
159
|
+
Buffer.from(String(lock.signatureBase64), "base64"),
|
|
160
|
+
);
|
|
161
|
+
} catch {
|
|
162
|
+
sigOk = false;
|
|
163
|
+
}
|
|
164
|
+
if (!sigOk) {
|
|
165
|
+
return {
|
|
166
|
+
signed: false,
|
|
167
|
+
reason: "recorded signature does not verify over the on-disk manifest",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
113
170
|
const trustedKeys = opts.trustedKeys;
|
|
114
171
|
if (trustedKeys && trustedKeys.size > 0) {
|
|
115
|
-
if (!
|
|
172
|
+
if (!trustedKeys.has(publicKeySha256)) {
|
|
116
173
|
return {
|
|
117
174
|
signed: false,
|
|
118
|
-
reason: `signing key not trusted (${
|
|
175
|
+
reason: `signing key not trusted (${publicKeySha256})`,
|
|
119
176
|
};
|
|
120
177
|
}
|
|
121
178
|
}
|
|
122
|
-
return { signed: true, publicKeySha256
|
|
179
|
+
return { signed: true, publicKeySha256 };
|
|
123
180
|
}
|
|
@@ -80,16 +80,19 @@ export function verifyPluginManifest({
|
|
|
80
80
|
|
|
81
81
|
const wantsSignature = requireSignature || signatureFile || publicKeyFile;
|
|
82
82
|
let signatureVerified = false;
|
|
83
|
+
let signature = null;
|
|
84
|
+
let publicKeyPem = null;
|
|
85
|
+
let publicKeySha256 = null;
|
|
83
86
|
if (wantsSignature) {
|
|
84
87
|
if (!signatureFile || !publicKeyFile) {
|
|
85
88
|
throw new Error(
|
|
86
89
|
"plugin signature verification requires --signature and --public-key",
|
|
87
90
|
);
|
|
88
91
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const keyObject = createPublicKey(
|
|
92
|
-
|
|
92
|
+
signature = readFileSync(signatureFile);
|
|
93
|
+
publicKeyPem = readFileSync(publicKeyFile, "utf8");
|
|
94
|
+
const keyObject = createPublicKey(publicKeyPem);
|
|
95
|
+
publicKeySha256 = createHash("sha256")
|
|
93
96
|
.update(keyObject.export({ type: "spki", format: "der" }))
|
|
94
97
|
.digest("hex");
|
|
95
98
|
const trusted = stringSet(trustedKeySha256);
|
|
@@ -110,16 +113,12 @@ export function verifyPluginManifest({
|
|
|
110
113
|
bytes,
|
|
111
114
|
sha256,
|
|
112
115
|
signatureVerified,
|
|
113
|
-
publicKeySha256: signatureVerified
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}),
|
|
120
|
-
)
|
|
121
|
-
.digest("hex")
|
|
122
|
-
: null,
|
|
116
|
+
publicKeySha256: signatureVerified ? publicKeySha256 : null,
|
|
117
|
+
// The raw signature material, so the installer can persist it and load-time
|
|
118
|
+
// enforcement can CRYPTOGRAPHICALLY re-verify (not merely trust a recorded
|
|
119
|
+
// boolean, which a hand-written lock file could forge).
|
|
120
|
+
signatureBase64: signatureVerified ? signature.toString("base64") : null,
|
|
121
|
+
publicKeyPem: signatureVerified ? publicKeyPem : null,
|
|
123
122
|
};
|
|
124
123
|
}
|
|
125
124
|
|
|
@@ -22,12 +22,19 @@ function spanId() {
|
|
|
22
22
|
|
|
23
23
|
// One trace per recorder (a "run"). The OTLP/OTel spec treats an ALL-ZERO
|
|
24
24
|
// traceId as INVALID, so a strict collector would drop every span exported with
|
|
25
|
-
// `"0".repeat(32)` — defeating toOtlp()'s purpose.
|
|
26
|
-
//
|
|
25
|
+
// `"0".repeat(32)` — defeating toOtlp()'s purpose. A bare counter is non-zero
|
|
26
|
+
// but resets every PROCESS, so successive CLI runs all exported trace
|
|
27
|
+
// `000…001` and a collector merged them into one giant trace. Prefix the
|
|
28
|
+
// counter with per-process entropy (start time + pid — RNG-free, so ids stay
|
|
29
|
+
// deterministic WITHIN a run) to make traces practically unique ACROSS runs.
|
|
30
|
+
const _traceBase = (
|
|
31
|
+
Date.now().toString(16).padStart(12, "0") +
|
|
32
|
+
(process.pid >>> 0).toString(16).padStart(8, "0")
|
|
33
|
+
).slice(0, 20);
|
|
27
34
|
let _traceSeq = 0;
|
|
28
35
|
function newTraceId() {
|
|
29
36
|
_traceSeq = (_traceSeq + 1) % Number.MAX_SAFE_INTEGER;
|
|
30
|
-
return _traceSeq.toString(16).padStart(
|
|
37
|
+
return _traceBase + _traceSeq.toString(16).padStart(12, "0"); // 32 hex, never all-zero
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
export class TelemetryRecorder {
|
|
@@ -186,8 +193,12 @@ export class TelemetryRecorder {
|
|
|
186
193
|
spanId: s.id,
|
|
187
194
|
parentSpanId: s.parentId || "",
|
|
188
195
|
name: s.name,
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
// proto3 JSON mapping: (s)fixed64/(u)int64 fields MUST be
|
|
197
|
+
// decimal STRINGS — ms×1e6 ≈ 1.8e18 exceeds 2^53, so a JSON
|
|
198
|
+
// number both violates the OTLP/JSON spec (strict collectors
|
|
199
|
+
// reject the span) and quantizes (~256 ns spacing).
|
|
200
|
+
startTimeUnixNano: String(Math.round(s.startTime * 1e6)),
|
|
201
|
+
endTimeUnixNano: String(Math.round(s.endTime * 1e6)),
|
|
191
202
|
status: { code: s.status === "error" ? 2 : 1 },
|
|
192
203
|
attributes: Object.entries(s.attributes).map(([k, v]) => ({
|
|
193
204
|
key: k,
|
|
@@ -200,7 +211,7 @@ export class TelemetryRecorder {
|
|
|
200
211
|
})),
|
|
201
212
|
events: s.events.map((e) => ({
|
|
202
213
|
name: e.name,
|
|
203
|
-
timeUnixNano: e.time * 1e6,
|
|
214
|
+
timeUnixNano: String(Math.round(e.time * 1e6)),
|
|
204
215
|
attributes: Object.entries(e.attributes).map(([k, v]) => ({
|
|
205
216
|
key: k,
|
|
206
217
|
value: { stringValue: String(v) },
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -64,7 +64,10 @@ import {
|
|
|
64
64
|
PromptCompressor,
|
|
65
65
|
getContextWindow,
|
|
66
66
|
} from "../harness/prompt-compressor.js";
|
|
67
|
-
import {
|
|
67
|
+
import {
|
|
68
|
+
buildAutoPinPredicate,
|
|
69
|
+
resolveAutoPinOption,
|
|
70
|
+
} from "../runtime/auto-pin.js";
|
|
68
71
|
import { feature } from "../lib/feature-flags.js";
|
|
69
72
|
import { recordCompressionMetric } from "../lib/compression-telemetry.js";
|
|
70
73
|
import {
|
|
@@ -417,15 +420,16 @@ export async function startAgentRepl(options = {}) {
|
|
|
417
420
|
// Unset → agent-core's 180s default (matches cc chat/ask). Set to 0 to
|
|
418
421
|
// disable. Left undefined here means "use the default".
|
|
419
422
|
let _streamStallTimeoutMs;
|
|
420
|
-
// Auto-pin (
|
|
421
|
-
//
|
|
422
|
-
//
|
|
423
|
-
|
|
423
|
+
// Auto-pin (default ON since 2026-07-07): compaction pins the original task
|
|
424
|
+
// (first user turn) so it survives context compression. Resolution order:
|
|
425
|
+
// CC_AUTO_PIN env ("1"/"0") > config `context.autoPin` (true/false/object) >
|
|
426
|
+
// default on. See resolveAutoPinOption.
|
|
427
|
+
let _autoPinCfgValue;
|
|
424
428
|
try {
|
|
425
429
|
const { loadConfig } = await import("../lib/config-manager.js");
|
|
426
430
|
const _cfg = loadConfig();
|
|
427
431
|
_visionModel = _cfg?.llm?.visionModel || undefined;
|
|
428
|
-
|
|
432
|
+
_autoPinCfgValue = _cfg?.context?.autoPin;
|
|
429
433
|
const raw = _cfg?.llm?.streamStallTimeoutMs;
|
|
430
434
|
const t = Number(raw);
|
|
431
435
|
// Accept 0 (explicit disable) — only ignore absent/invalid values.
|
|
@@ -483,8 +487,8 @@ export async function startAgentRepl(options = {}) {
|
|
|
483
487
|
if (feature("PROMPT_COMPRESSOR")) {
|
|
484
488
|
_compressor = new PromptCompressor({ model, provider });
|
|
485
489
|
}
|
|
486
|
-
|
|
487
|
-
// Compaction options shared by /compact + auto-compact. Adds the
|
|
490
|
+
const _autoPinOpt = resolveAutoPinOption({ config: _autoPinCfgValue });
|
|
491
|
+
// Compaction options shared by /compact + auto-compact. Adds the
|
|
488
492
|
// pin predicate only when auto-pin is enabled; otherwise byte-identical.
|
|
489
493
|
const _compactOpts = (msgs) => {
|
|
490
494
|
const base = { preserveToolPairs: true };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* auto-pin policy tests
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* auto-pin policy tests. The PREDICATE layer stays opt-valued (null when the
|
|
3
|
+
* resolved option is falsy → byte-identical compaction); the EFFECTIVE default
|
|
4
|
+
* is decided by resolveAutoPinOption — ON since 2026-07-07, opt out via
|
|
5
|
+
* CC_AUTO_PIN=0 or config context.autoPin=false.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { describe, it, expect } from "vitest";
|
|
9
9
|
import {
|
|
10
10
|
resolveAutoPinConfig,
|
|
11
|
+
resolveAutoPinOption,
|
|
11
12
|
buildAutoPinPredicate,
|
|
12
13
|
describeAutoPin,
|
|
13
14
|
} from "../auto-pin.js";
|
|
@@ -102,3 +103,25 @@ describe("describeAutoPin", () => {
|
|
|
102
103
|
);
|
|
103
104
|
});
|
|
104
105
|
});
|
|
106
|
+
|
|
107
|
+
describe("resolveAutoPinOption (effective default — ON since 2026-07-07)", () => {
|
|
108
|
+
it("defaults ON when nothing is set", () => {
|
|
109
|
+
expect(resolveAutoPinOption({ env: undefined, config: undefined })).toBe(
|
|
110
|
+
true,
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
it("CC_AUTO_PIN=0 opts out; =1 forces on over a config false", () => {
|
|
114
|
+
expect(resolveAutoPinOption({ env: "0", config: true })).toBe(false);
|
|
115
|
+
expect(resolveAutoPinOption({ env: "1", config: false })).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
it("config false opts out; a config object passes through", () => {
|
|
118
|
+
expect(resolveAutoPinOption({ env: undefined, config: false })).toBe(false);
|
|
119
|
+
const cfg = { maxPinTokens: 99 };
|
|
120
|
+
expect(resolveAutoPinOption({ env: undefined, config: cfg })).toBe(cfg);
|
|
121
|
+
});
|
|
122
|
+
it("an explicit --auto-pin flag wins over everything", () => {
|
|
123
|
+
expect(resolveAutoPinOption({ flag: true, env: "0", config: false })).toBe(
|
|
124
|
+
true,
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
});
|
package/src/runtime/auto-pin.js
CHANGED
|
@@ -23,6 +23,25 @@
|
|
|
23
23
|
|
|
24
24
|
const DEFAULT_MAX_PIN_TOKENS = 2000;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the EFFECTIVE auto-pin setting from (highest precedence first):
|
|
28
|
+
* 1. an explicit CLI flag (`--auto-pin` → force on),
|
|
29
|
+
* 2. the CC_AUTO_PIN env var ("1" on / "0" off),
|
|
30
|
+
* 3. the config value (`context.autoPin`: true | false | {…}),
|
|
31
|
+
* 4. the default — **ON** (product decision 2026-07-07): pinning the
|
|
32
|
+
* original task through compaction costs a bounded slice of context
|
|
33
|
+
* (maxPinTokens, default 2000) but prevents goal drift in long sessions.
|
|
34
|
+
* Opt out with CC_AUTO_PIN=0 or `context.autoPin: false` in config.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveAutoPinOption({ flag, env, config } = {}) {
|
|
37
|
+
if (flag === true) return true;
|
|
38
|
+
const e = env !== undefined ? env : process.env.CC_AUTO_PIN;
|
|
39
|
+
if (e === "0") return false;
|
|
40
|
+
if (e === "1") return true;
|
|
41
|
+
if (config !== undefined && config !== null) return config;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
26
45
|
/**
|
|
27
46
|
* Normalize the opt-in value into a config object, or null when auto-pin is off.
|
|
28
47
|
* Accepts: falsy (off), `true` (defaults on), or a config object
|
|
@@ -890,6 +890,24 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
890
890
|
}
|
|
891
891
|
}
|
|
892
892
|
|
|
893
|
+
// Resolve auto-pin (flag > env > config > default-on). Config read is
|
|
894
|
+
// best-effort — a broken config file must not take headless down.
|
|
895
|
+
let _autoPinResolved;
|
|
896
|
+
{
|
|
897
|
+
const { resolveAutoPinOption } = await import("./auto-pin.js");
|
|
898
|
+
let _autoPinCfg;
|
|
899
|
+
try {
|
|
900
|
+
const { loadConfig } = await import("../lib/config-manager.js");
|
|
901
|
+
_autoPinCfg = loadConfig()?.context?.autoPin;
|
|
902
|
+
} catch {
|
|
903
|
+
_autoPinCfg = undefined;
|
|
904
|
+
}
|
|
905
|
+
_autoPinResolved = resolveAutoPinOption({
|
|
906
|
+
flag: options.autoPin === true,
|
|
907
|
+
config: _autoPinCfg,
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
|
|
893
911
|
const loopOptions = {
|
|
894
912
|
model,
|
|
895
913
|
provider,
|
|
@@ -906,11 +924,11 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
906
924
|
additionalDirectories,
|
|
907
925
|
sandbox: options.sandbox || null,
|
|
908
926
|
sessionId,
|
|
909
|
-
// Auto-pin (
|
|
910
|
-
// compaction.
|
|
911
|
-
//
|
|
912
|
-
|
|
913
|
-
|
|
927
|
+
// Auto-pin (default ON since 2026-07-07): pin the original task through
|
|
928
|
+
// compaction. Precedence: --auto-pin flag > CC_AUTO_PIN ("1"/"0") >
|
|
929
|
+
// config context.autoPin > default on. Falsy → agent-core passes no pin
|
|
930
|
+
// predicate and compaction is byte-identical.
|
|
931
|
+
autoPin: _autoPinResolved,
|
|
914
932
|
autoCheckpoint: options.autoCheckpoint || false,
|
|
915
933
|
checkpointSession: options.checkpointSession || sessionId,
|
|
916
934
|
hookDb: db,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as h,P as u,J as S,U as n,R as a,S as y,K as C,Q as w,V as x,_ as B,b as s}from"./vendor-BMxUs6UX.js";import{_ as k}from"./index-BgN5G5vF.js";import"./icons-BsDmGpcT.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=s(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=s(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=s(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=s(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=s(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),f=String(e.getMonth()+1).padStart(2,"0"),g=String(e.getDate()).padStart(2,"0"),b=String(e.getHours()).padStart(2,"0"),v=String(e.getMinutes()).padStart(2,"0");return`${p}-${f}-${g} ${b}:${v}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:s};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},T={class:"bubble"},q={class:"meta"},M={class:"actor"},R={class:"time"},V={class:"body"};function D(c,d,t,r,i,l){const o=h("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[n("div",T,[n("div",q,[n("span",M,a(r.actorLabel),1),n("span",R,a(r.formattedTime),1)]),n("div",V,a(r.messageText),1),t.event.source.adapter?(u(),y(o,{key:0,class:"src",color:r.adapterColor},{default:C(()=>[w(a(t.event.source.adapter),1)]),_:1},8,["color"])):x("v-if",!0)])],2)}const A=k(N,[["render",D],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-v9Hwrq/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{A 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-BgN5G5vF.js";import{I as z,J as x,U as _,Q as q,S as K,K as T,V as R,c as A,F as Q,Z as Y,R as E,o as Z,f as G,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-BMxUs6UX.js";import{R as ye,b as pe,as as ge}from"./icons-BsDmGpcT.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 B(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 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 H=new ResizeObserver(()=>{try{P.fit(),s.resize(t.id,m.cols,m.rows).catch(()=>{})}catch{}});H.observe(b);const ue=t.offs;t.offs=()=>{try{H.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,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 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}}Z(async()=>{await X()}),G(()=>{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:B,onCreate:re,onClose:se,removeSession:W,activate:le,refreshList:X,ref:S,computed:ee,onMounted:Z,onBeforeUnmount:G,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"},qe={key:1,class:"terminal-footer"},De={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]=q(" 桌面端托管的 PTY 会话;Android 端可远程操控同一通道 ",-1)),e.warning?(y(),K(u,{key:0,color:"orange",style:{"margin-left":"8px"}},{default:T(()=>[q(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]=q(" 新会话 ",-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]=q(" 刷新 ",-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"])):R("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",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(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)])])):R("v-if",!0)])]),e.active?(y(),x("div",qe,[_("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",Be],["__scopeId","data-v-65366a29"],["__file","/tmp/cc-web-panel-v9Hwrq/repo/packages/web-panel/src/views/Terminal.vue"]]);export{Fe as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Q as r}from"./index-BgN5G5vF.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-Eq98LRtU.js";import{a0 as t}from"./index-BgN5G5vF.js";import"./vendor-BMxUs6UX.js";import"./responsiveObserve-D7Xz2y-R.js";import"./useFlexGapSupport-BoMCTNyu.js";import"./styleChecker-qHmJjV62.js";import"./index-C_MfcrLf.js";import"./icons-BsDmGpcT.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-BfbHu1xI.js";import{a0 as t}from"./index-BgN5G5vF.js";import"./vendor-BMxUs6UX.js";import"./index-C_MfcrLf.js";import"./icons-BsDmGpcT.js";const s=t(o);export{s as default};
|