chainlesschain 0.162.176 → 0.162.178
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 +10 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BDLu5Elz.js → AIOps-DRftcSue.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DH5us-CK.js → ActionButton-BFvUaMKR.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BZ0u8IFG.js → Analytics-C0-Rru4P.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-bx-BCljj.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-Br2YBbh_.js → Artifacts-DAJ8B3Un.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C3C6a482.js → Audit-hOk4L1lr.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CzHvebcj.js → BackgroundAgents-3pbDpM9z.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DZNHYDFd.js → Backup-BtziGDn9.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-VRiC4fIx.js → BaseInput-kmshphJ3.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Cm08WWAD.js → Chat-d7tGSosA.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CGHYrugQ.js → ChatBubbleRenderer-p-_PBpX_.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DtByk7d7.js → Checkbox-C4Eh4Tz5.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CphXXOfD.js → Codegen-r7gmhZyA.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Hz86TnLR.js → Col-U7mDaGlL.js} +1 -1
- package/src/assets/web-panel/assets/{Community-HP03ltpD.js → Community-Bpu8aH1T.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-B_N1mqQz.js → Compact-CHb2XBJe.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CVztRpi8.js → Compliance-Cn_r4dey.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-wUVOyZih.js → Cowork-CdMWfDcz.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DW5TLJKw.js → Cron-BtnREHWy.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CrAFGhWH.js → Crosschain-BKI9TSzr.js} +1 -1
- package/src/assets/web-panel/assets/{DID-pA-oD8ke.js → DID-pkNubzzJ.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-1rrz1snN.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-EweJcsek.js → Dropdown-DLyFVxDc.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C9xVLPG4.js → EmailListRenderer-CtUWfYVq.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CDcEEqlu.js → FamilyGuardDashboard-B8eX2Qe4.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DtZda9A_.js → Federation-D8lsDGus.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CiYdcVz3.js → FormItemContext-CRYt_aIw.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DA13uwA0.js → GenericCardRenderer-ClKzY8_N.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DzRhZD1O.js → Git-BXj5Dney.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-D5RMgOSb.js → Governance-Cm-I8RMz.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BgrPfSNk.js → Inference-CPvbhvgt.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DzjnD571.js → KnowledgeGraph-sYNDZaoi.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BhWzVDtN.js → Logs-BZY_3CRZ.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BDape9cx.js → MarkdownRenderer-up0BW6pv.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DJtL5GV7.js → Marketplace-C5MEJ2Qe.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CZcQygI7.js → McpTools-ihdrn43I.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-DUWSDUUu.js → Memory-Br8bPMlh.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BTwq2WKY.js → MobileBridge-BNntgrYW.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BdV915mw.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-BiGugEQm.js → Mtc-A3wDmlqL.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-DY7a6gUe.js → MtcAudit-CF-mBLWM.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BQbDu_w7.js → Multisig-Iy2k_MSo.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CM2wXTLv.js → NLProgramming-kk0W7HUb.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DI6gGs1v.js → Notes-B5u5t_4S.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BsZOLWAB.js → NotificationSettings-BN0POf6_.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CHkSUrXB.js +1 -0
- package/src/assets/web-panel/assets/{Organization-Cds0_tXr.js → Organization-DwWQESuN.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-WunYMD87.js → Overflow-DG6klrcC.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Bo6j4DDv.js → P2P-BwJcKkgZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Bh2XPD5f.js → PdhVaultBrowser-BwOHG0in.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-EMvMMC8N.js → Permissions-CGMXe4TX.js} +4 -4
- package/src/assets/web-panel/assets/PersonalDataHub-ziYqg7-A.js +8 -0
- package/src/assets/web-panel/assets/{Pipeline-BOx8HOgL.js → Pipeline-BzJfeoGt.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-tBeTVQVM.js → Privacy-DLh3Bblx.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CVYg1W4M.js → ProjectInit-USVWW36c.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Dvt5I7y1.js → ProjectSettings-CiiOn62h.js} +2 -2
- package/src/assets/web-panel/assets/Projects-6V-PNmcA.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Ct8xqY-E.js → Providers-CBPWWzpu.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-Cni8Ooja.js → QrScannerModal-QVwoRUq3.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BJVLKdxr.js → QuickAsk-CXnR-2Vn.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DPG8Rbbm.js → Recommend-ClaNzjmF.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DsdR7dCt.js → RemoteSession-C3rGw8vJ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-Csg1YM-b.js → Reputation-Ci-OWAoP.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D9DoFoEf.js → Row-DRhAwXOS.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BsvKrXMS.js → RssFeed-BQLJQ2_y.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DFUStfgQ.js → Search-QQUpkfFd.js} +1 -1
- package/src/assets/web-panel/assets/{Security-ILg1zxdK.js → Security-DdXKzuKT.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Dd41PCaY.js → Services-x2Zh62Qd.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Bzo1cN80.js → Skeleton-GdY4KwRz.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BDHh17P0.js → Skills-Bv4tY1Fd.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-jl7UTiRY.js → Sla-C3QnM-11.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BePa-RF6.js → SpeechSettings-Bl3ytvmI.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DiqqDKGZ.js → SyncSettings-Wp9IwTsP.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DYQ_6lxj.js → Tasks-CF3rIrDe.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-JiDeI06L.js → Templates-CGfvVVM9.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-hhgI6zwS.js → Tenant-CVXmwQ3U.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-bvwrt03E.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-B8uB5Llk.js → TimelineRenderer-D0g74KhH.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-C3b_6r2z.js → Tokens-BH4IwzlT.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-tIP7HKVe.js → Trigger-DJOpM533.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-vjoc11vJ.js → Trust-B43EPRLr.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DUPBnGuH.js → UkeySign-BmBFG-em.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CBvhUY5T.js → VideoEditing-n9oJwB8k.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DUaQ0uA5.js → Wallet-D5QeivHp.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DllSivjE.js → WebAuthn-DcNy7igO.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-xc8D3uO6.js → WorkflowEditor-BVjc7-5-.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BVicU7oA.js → chat-Dy5Tfj3m.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DJzLmhLm.js → colors-C4c2CNZU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BvYRfThE.js → compact-item-DPa3O5vN.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DGXxCBKR.js → createContext-TLcfNA6_.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BAwdDA_5.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-SBDJB1y4.js → hasIn-D41LVFkp.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7HimK0M.js → index-0oevYjfT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCdRAgjy.js → index-388pLGJ1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BO1itZaY.js → index-B8nLBZbv.js} +3 -3
- package/src/assets/web-panel/assets/{index-DvUTDYXX.js → index-BPTGAjee.js} +1 -1
- package/src/assets/web-panel/assets/{index-hxTODbM1.js → index-BPtrOBmW.js} +1 -1
- package/src/assets/web-panel/assets/{index-wcCL-miV.js → index-BQiIxHBy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CKyEivf8.js → index-BSM1cHVK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJZf9DhV.js → index-BYPr9fkz.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHVLJ8q0.js → index-BsQ7Ev6i.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cs2rmLFt.js → index-Btk9qLL2.js} +1 -1
- package/src/assets/web-panel/assets/{index-z1ZylsLq.js → index-BvmziZSG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf-O_g_8.js → index-BvopLC_T.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMarmfrv.js → index-C7xhTVyP.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoJAO1Lm.js → index-CNk_ZooP.js} +1 -1
- package/src/assets/web-panel/assets/{index-9gdI7uUW.js → index-CQrEHoOG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bf-ctERC.js → index-CSxex23J.js} +1 -1
- package/src/assets/web-panel/assets/{index-MjC4G09d.js → index-CVjgm992.js} +1 -1
- package/src/assets/web-panel/assets/{index-e4fXH_WO.js → index-CWK4zOPe.js} +1 -1
- package/src/assets/web-panel/assets/{index-xfluRkCT.js → index-CX0VsoP4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRfiXB_p.js → index-CXl0YPNG.js} +1 -1
- package/src/assets/web-panel/assets/{index-d5BVd-cL.js → index-Cip7LWml.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dm_77jgR.js → index-Cq_hlWNt.js} +1 -1
- package/src/assets/web-panel/assets/{index-YJkzy8ZF.js → index-CzZ49YZL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtwqO5qo.js → index-D2Nkivlm.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYqz4Wrr.js → index-DBUgRs4D.js} +1 -1
- package/src/assets/web-panel/assets/index-DEjVkdzq.js +1 -0
- package/src/assets/web-panel/assets/{index-CdGY9P8a.js → index-DNsBj2Ob.js} +1 -1
- package/src/assets/web-panel/assets/{index-DonCnfMr.js → index-Di4X8cfI.js} +1 -1
- package/src/assets/web-panel/assets/{index-1SdDS6lR.js → index-DljFsVGI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnjPdvR6.js → index-Korc3QIe.js} +1 -1
- package/src/assets/web-panel/assets/index-LMOc5xrS.js +1 -0
- package/src/assets/web-panel/assets/{index-VMfwIH5G.js → index-MKZDje0H.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKrvvWm4.js → index-OHAfRu_3.js} +1 -1
- package/src/assets/web-panel/assets/{index-FxZzRyE1.js → index-WEJr8PL5.js} +1 -1
- package/src/assets/web-panel/assets/{index-Crk5NTb0.js → index-WinCp6du.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCqRS6da.js → index-Yjr6cqSK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTrBGBJs.js → index-iQ6gtFih.js} +1 -1
- package/src/assets/web-panel/assets/{index-lpaGoTH3.js → index-pt3s7yvV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CloCgBUR.js → index-tQ3igERQ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C1zO1KnY.js → initDefaultProps-BFZu87WZ.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CWLtEGmC.js → motion-DJIo7qvt.js} +1 -1
- package/src/assets/web-panel/assets/{move-DzD_C3Vm.js → move-Cfr5qknL.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-D880PYJl.js → mtc-parser-Bgc-OadH.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CFR_z2ov.js → omit-X3WI-TNp.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-srIhgrSC.js → pickAttrs-pJhU9IxK.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-C1rXpibP.js → placementArrow-BNg_Vj3T.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C30gRcSS.js → responsiveObserve-TeSEGQ5-.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CvtKiMfV.js → slide-D_t_P0bv.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DNHO7ITG.js → statusUtils-DrrIMwAT.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Dt_Sl-g4.js → styleChecker-BjZCuFRm.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Cjev42Gh.js → useFlexGapSupport-rTFdlqdQ.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Baxglj2V.js → useFs-BidCpfLX.js} +1 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-C5mHttA9.js +1 -0
- package/src/assets/web-panel/assets/{vnode-mIRkdT7o.js → vnode-BrbcRiHZ.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-HzI5DlH_.js → zoom-PISX7AkR.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/__tests__/hub-wechat.test.js +45 -0
- package/src/commands/agenda.js +22 -6
- package/src/commands/agent.js +3 -3
- package/src/commands/background-session.js +16 -6
- package/src/commands/batch.js +79 -27
- package/src/commands/changelog.js +15 -4
- package/src/commands/context.js +33 -1
- package/src/commands/eval.js +21 -6
- package/src/commands/hook.js +2 -2
- package/src/commands/hub.js +473 -39
- package/src/commands/init.js +212 -110
- package/src/commands/llm.js +22 -6
- package/src/commands/loop.js +9 -2
- package/src/commands/skill.js +13 -1
- package/src/commands/statusline.js +3 -3
- package/src/data/changelog.json +53 -5
- package/src/gateways/ws/personal-data-hub-protocol.js +22 -2
- package/src/harness/background-task-manager.js +18 -6
- package/src/harness/background-task-worker.js +11 -18
- package/src/harness/golden-transcript.js +3 -0
- package/src/harness/mcp-client.js +9 -15
- package/src/harness/worktree-isolator.js +18 -21
- package/src/index.js +18 -7
- package/src/lib/agent-core.js +5 -0
- package/src/lib/agent-ipc-bus.js +12 -3
- package/src/lib/agent-team/team-worktree.js +28 -6
- package/src/lib/agent-worktree.js +20 -19
- package/src/lib/approval-authority-store.js +891 -0
- package/src/lib/async-hook-supervisor.cjs +134 -24
- package/src/lib/async-hook-supervisor.js +47 -0
- package/src/lib/background-agent-supervisor.js +35 -12
- package/src/lib/background-interaction-resolver.js +399 -54
- package/src/lib/background-session-transport.js +3 -1
- package/src/lib/background-task-manager.js +5 -1
- package/src/lib/changelog.js +57 -0
- package/src/lib/chrome-connector.js +6 -2
- package/src/lib/claude-code-bridge.js +24 -8
- package/src/lib/cli-anything-bridge.js +82 -25
- package/src/lib/context-breakdown.js +82 -3
- package/src/lib/doctor-checkup.js +18 -6
- package/src/lib/eval/tasks.js +25 -31
- package/src/lib/event-runtime-host.js +225 -0
- package/src/lib/event-runtime-store.js +102 -21
- package/src/lib/event-runtime-worker.js +70 -2
- package/src/lib/hook-runner.cjs +71 -36
- package/src/lib/hook-runner.js +55 -0
- package/src/lib/hooks-v2-producers.js +33 -8
- package/src/lib/hooks-v2-runtime.js +360 -40
- package/src/lib/host-adb-bridge.js +18 -3
- package/src/lib/interaction-adapter.js +66 -0
- package/src/lib/lsp/__tests__/benchmark.test.js +61 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
- package/src/lib/lsp/benchmark.js +20 -4
- package/src/lib/lsp/lsp-client.js +6 -4
- package/src/lib/lsp/lsp-server-registry.js +0 -2
- package/src/lib/operation-fingerprint.js +107 -2
- package/src/lib/orchestrator.js +8 -2
- package/src/lib/packer/pack-update-applier.js +14 -2
- package/src/lib/packer/smoke-runner.js +18 -5
- package/src/lib/paths.js +1 -1
- package/src/lib/pdh-dedicated-batch-collectors.js +124 -0
- package/src/lib/personal-data-hub-wiring.js +327 -52
- package/src/lib/plugin-monitor-supervisor.js +20 -13
- package/src/lib/plugin-runtime/install.js +10 -3
- package/src/lib/process-execution-broker/credential-agent.js +954 -111
- package/src/lib/process-execution-broker/index.js +369 -85
- package/src/lib/process-execution-broker/platform-sandbox.js +320 -140
- package/src/lib/provider-http-error.js +94 -0
- package/src/lib/remote-approval-bridge.js +222 -26
- package/src/lib/repl-bang-memorize.js +10 -2
- package/src/lib/repl-goal.js +19 -2
- package/src/lib/settings-hook-events.cjs +13 -8
- package/src/lib/settings-hook-events.js +20 -0
- package/src/lib/side-effect-ledger-store.js +65 -14
- package/src/lib/skill-loader.js +215 -12
- package/src/lib/skill-packs/generator.js +18 -9
- package/src/lib/skill-process-broker.js +85 -0
- package/src/lib/slash-commands.js +10 -2
- package/src/lib/status-line.cjs +28 -7
- package/src/lib/status-line.js +33 -0
- package/src/lib/sub-agent-context.js +42 -0
- package/src/lib/turn-binding-store.js +64 -15
- package/src/lib/turn-binding.js +85 -16
- package/src/repl/agent-repl.js +88 -49
- package/src/repl/remote-approval.js +13 -13
- package/src/repl/repl-turn-binding.js +46 -16
- package/src/runtime/agent-core.js +419 -84
- package/src/runtime/coding-agent-contract-shared.cjs +16 -0
- package/src/runtime/headless-runner.js +172 -44
- package/src/runtime/headless-stream.js +221 -11
- package/src/runtime/session-slash-commands.js +506 -0
- package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
- package/src/skills/video-editing/extractors/video-extractor.js +13 -3
- package/src/skills/video-editing/media-process.js +20 -0
- package/src/skills/video-editing/render/audio-mix.js +13 -3
- package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
- package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
- package/src/workers/background-agent-worker.js +76 -40
- package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +0 -9
- package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +0 -3
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-C48mu09U.js +0 -1
- package/src/assets/web-panel/assets/PersonalDataHub-AX3ypUDV.js +0 -9
- package/src/assets/web-panel/assets/Projects-Cc7FC9-e.js +0 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +0 -3
- package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +0 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +0 -1
- package/src/assets/web-panel/assets/index-ycwAfC-i.js +0 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-B4NkcLaP.js +0 -1
|
@@ -26,41 +26,82 @@ export const _deps = {
|
|
|
26
26
|
readEvents: storeReadEvents,
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
export class SideEffectLedgerPersistenceError extends Error {
|
|
30
|
+
constructor(operation, sessionId, cause) {
|
|
31
|
+
const detail = cause?.message || String(cause || "unknown persistence error");
|
|
32
|
+
super(`Side-effect ledger ${operation} failed for ${sessionId}: ${detail}`, {
|
|
33
|
+
cause,
|
|
34
|
+
});
|
|
35
|
+
this.name = "SideEffectLedgerPersistenceError";
|
|
36
|
+
this.code =
|
|
37
|
+
operation === "read"
|
|
38
|
+
? "SIDE_EFFECT_LEDGER_READ_FAILED"
|
|
39
|
+
: "SIDE_EFFECT_LEDGER_PERSIST_FAILED";
|
|
40
|
+
this.operation = operation;
|
|
41
|
+
this.sessionId = sessionId;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function persistenceFailure(operation, sessionId, cause, failIfUnavailable) {
|
|
46
|
+
if (!failIfUnavailable) return false;
|
|
47
|
+
throw new SideEffectLedgerPersistenceError(operation, sessionId, cause);
|
|
48
|
+
}
|
|
49
|
+
|
|
29
50
|
/**
|
|
30
|
-
* Append the current ledger as a chained event.
|
|
31
|
-
*
|
|
51
|
+
* Append the current ledger as a chained event. This is Critical state:
|
|
52
|
+
* persistence failures reject by default so the guarded operation cannot run.
|
|
53
|
+
* Diagnostic callers may explicitly request advisory best-effort behavior.
|
|
32
54
|
*
|
|
33
55
|
* @param {string} sessionId
|
|
34
56
|
* @param {SideEffectLedger|object} ledger
|
|
57
|
+
* @param {{failIfUnavailable?:boolean}} [opts]
|
|
35
58
|
* @returns {boolean}
|
|
36
59
|
*/
|
|
37
|
-
export function persistSideEffectLedger(sessionId, ledger) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
60
|
+
export function persistSideEffectLedger(sessionId, ledger, opts = {}) {
|
|
61
|
+
const failIfUnavailable = opts.failIfUnavailable !== false;
|
|
62
|
+
if (!sessionId || !ledger) {
|
|
63
|
+
return persistenceFailure(
|
|
64
|
+
"write",
|
|
65
|
+
sessionId || "<missing-session>",
|
|
66
|
+
new TypeError("sessionId and ledger are required"),
|
|
67
|
+
failIfUnavailable,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
42
71
|
try {
|
|
72
|
+
const snapshot =
|
|
73
|
+
ledger instanceof SideEffectLedger ? ledger.toJSON() : ledger;
|
|
74
|
+
if (!snapshot || !Array.isArray(snapshot.ops)) {
|
|
75
|
+
throw new TypeError("ledger snapshot must contain an ops array");
|
|
76
|
+
}
|
|
43
77
|
_deps.appendEvent(sessionId, SIDE_EFFECT_LEDGER_EVENT, snapshot);
|
|
44
78
|
return true;
|
|
45
|
-
} catch {
|
|
46
|
-
return
|
|
79
|
+
} catch (error) {
|
|
80
|
+
return persistenceFailure("write", sessionId, error, failIfUnavailable);
|
|
47
81
|
}
|
|
48
82
|
}
|
|
49
83
|
|
|
50
84
|
/**
|
|
51
85
|
* Rebuild the ledger from the LATEST persisted snapshot, or an empty ledger when
|
|
52
|
-
* the session never persisted one
|
|
86
|
+
* the session never persisted one. Read/corruption errors reject by default.
|
|
53
87
|
*
|
|
54
88
|
* @param {string} sessionId
|
|
55
|
-
* @param {{clock?:Function}} [opts]
|
|
89
|
+
* @param {{clock?:Function,failIfUnavailable?:boolean}} [opts]
|
|
56
90
|
* @returns {SideEffectLedger}
|
|
57
91
|
*/
|
|
58
92
|
export function loadSideEffectLedger(sessionId, opts = {}) {
|
|
93
|
+
const failIfUnavailable = opts.failIfUnavailable !== false;
|
|
59
94
|
let events = [];
|
|
60
95
|
try {
|
|
61
96
|
events = _deps.readEvents(sessionId) || [];
|
|
62
|
-
} catch {
|
|
63
|
-
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const fallback = persistenceFailure(
|
|
99
|
+
"read",
|
|
100
|
+
sessionId || "<missing-session>",
|
|
101
|
+
error,
|
|
102
|
+
failIfUnavailable,
|
|
103
|
+
);
|
|
104
|
+
if (fallback === false) return new SideEffectLedger(opts);
|
|
64
105
|
}
|
|
65
106
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
66
107
|
const e = events[i];
|
|
@@ -70,7 +111,17 @@ export function loadSideEffectLedger(sessionId, opts = {}) {
|
|
|
70
111
|
e.data &&
|
|
71
112
|
Array.isArray(e.data.ops)
|
|
72
113
|
) {
|
|
73
|
-
|
|
114
|
+
try {
|
|
115
|
+
return SideEffectLedger.fromJSON(e.data, opts);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
const fallback = persistenceFailure(
|
|
118
|
+
"read",
|
|
119
|
+
sessionId || "<missing-session>",
|
|
120
|
+
error,
|
|
121
|
+
failIfUnavailable,
|
|
122
|
+
);
|
|
123
|
+
if (fallback === false) return new SideEffectLedger(opts);
|
|
124
|
+
}
|
|
74
125
|
}
|
|
75
126
|
}
|
|
76
127
|
return new SideEffectLedger(opts);
|
package/src/lib/skill-loader.js
CHANGED
|
@@ -31,6 +31,7 @@ import { parseSkillMcpServers } from "./skill-mcp.js";
|
|
|
31
31
|
import { normalizeSkillPaths } from "./skill-path-scope.js";
|
|
32
32
|
import { discoverPluginSkillLayers } from "./plugin-runtime/skills.js";
|
|
33
33
|
import settingsLoader from "./settings-loader.cjs";
|
|
34
|
+
import contextSourceLedger from "./context-source-ledger.js";
|
|
34
35
|
|
|
35
36
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
36
37
|
|
|
@@ -218,6 +219,40 @@ export function parseSkillMd(content) {
|
|
|
218
219
|
return { data, body };
|
|
219
220
|
}
|
|
220
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Read only enough of SKILL.md to parse its YAML frontmatter. The markdown
|
|
224
|
+
* body is deliberately not retained during discovery; it is materialized by
|
|
225
|
+
* CLISkillLoader.materializeSkill() only when a persona or run_skill needs it.
|
|
226
|
+
*/
|
|
227
|
+
function readSkillFrontmatter(skillMd, maxBytes = 256 * 1024) {
|
|
228
|
+
const fd = fs.openSync(skillMd, "r");
|
|
229
|
+
const chunks = [];
|
|
230
|
+
let total = 0;
|
|
231
|
+
try {
|
|
232
|
+
while (total < maxBytes) {
|
|
233
|
+
const chunk = Buffer.allocUnsafe(Math.min(8192, maxBytes - total));
|
|
234
|
+
const read = fs.readSync(fd, chunk, 0, chunk.length, total);
|
|
235
|
+
if (read <= 0) break;
|
|
236
|
+
chunks.push(chunk.subarray(0, read));
|
|
237
|
+
total += read;
|
|
238
|
+
const prefix = Buffer.concat(chunks).toString("utf-8").replace(/^\uFEFF/, "");
|
|
239
|
+
const firstLineEnd = prefix.search(/\r?\n/);
|
|
240
|
+
if (firstLineEnd >= 0 && prefix.slice(0, firstLineEnd).trim() !== "---") {
|
|
241
|
+
return {};
|
|
242
|
+
}
|
|
243
|
+
const match = prefix.match(/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/);
|
|
244
|
+
if (match) return parseSkillMd(match[0]).data;
|
|
245
|
+
}
|
|
246
|
+
return {};
|
|
247
|
+
} finally {
|
|
248
|
+
fs.closeSync(fd);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function estimateSkillTokens(text) {
|
|
253
|
+
return Math.ceil(String(text || "").length / 4);
|
|
254
|
+
}
|
|
255
|
+
|
|
221
256
|
/**
|
|
222
257
|
* Substitute $ARGUMENTS / $1 / $2 / ... placeholders in a skill body.
|
|
223
258
|
* Inspired by open-agents substituteArguments.
|
|
@@ -290,8 +325,17 @@ export function prepareSkillBody(skill, args) {
|
|
|
290
325
|
* Multi-layer CLI skill loader
|
|
291
326
|
*/
|
|
292
327
|
export class CLISkillLoader {
|
|
293
|
-
constructor() {
|
|
328
|
+
constructor({ contextLedger = contextSourceLedger } = {}) {
|
|
294
329
|
this._cache = null;
|
|
330
|
+
this._bodyCache = new Map();
|
|
331
|
+
this._contextLedger = contextLedger;
|
|
332
|
+
this._cacheStats = {
|
|
333
|
+
descriptorScans: 0,
|
|
334
|
+
descriptorCacheHits: 0,
|
|
335
|
+
bodyCacheHits: 0,
|
|
336
|
+
bodyCacheMisses: 0,
|
|
337
|
+
bodyLoads: new Map(),
|
|
338
|
+
};
|
|
295
339
|
}
|
|
296
340
|
|
|
297
341
|
/**
|
|
@@ -449,8 +493,8 @@ export class CLISkillLoader {
|
|
|
449
493
|
continue;
|
|
450
494
|
}
|
|
451
495
|
try {
|
|
452
|
-
const
|
|
453
|
-
const
|
|
496
|
+
const data = readSkillFrontmatter(skillMd);
|
|
497
|
+
const stat = fs.statSync(skillMd);
|
|
454
498
|
|
|
455
499
|
out.push({
|
|
456
500
|
id: data.name || entry.name,
|
|
@@ -474,12 +518,17 @@ export class CLISkillLoader {
|
|
|
474
518
|
paths: normalizeSkillPaths(data),
|
|
475
519
|
dirName: entry.name,
|
|
476
520
|
hasHandler: fs.existsSync(path.join(skillDir, "handler.js")),
|
|
477
|
-
|
|
478
|
-
//
|
|
479
|
-
//
|
|
480
|
-
|
|
521
|
+
isolation: data.isolation === true,
|
|
522
|
+
// Two-tier loading: discovery retains only the descriptor. The body
|
|
523
|
+
// and embedded MCP declarations are populated on first use.
|
|
524
|
+
body: null,
|
|
525
|
+
bodyLoaded: false,
|
|
526
|
+
mcpServers: [],
|
|
481
527
|
source: layer,
|
|
482
528
|
skillDir,
|
|
529
|
+
skillMdPath: skillMd,
|
|
530
|
+
skillFileBytes: stat.size,
|
|
531
|
+
skillFileMtimeMs: stat.mtimeMs,
|
|
483
532
|
});
|
|
484
533
|
} catch {
|
|
485
534
|
// Skip malformed skill files
|
|
@@ -487,12 +536,149 @@ export class CLISkillLoader {
|
|
|
487
536
|
}
|
|
488
537
|
}
|
|
489
538
|
|
|
539
|
+
/**
|
|
540
|
+
* Materialize a descriptor's markdown body and embedded MCP declarations.
|
|
541
|
+
* Cache entries are invalidated by file size/mtime and never include content
|
|
542
|
+
* in provenance records.
|
|
543
|
+
*/
|
|
544
|
+
materializeSkill(skill, context = {}) {
|
|
545
|
+
if (!skill || !skill.skillMdPath) {
|
|
546
|
+
throw new TypeError("A discovered skill descriptor is required");
|
|
547
|
+
}
|
|
548
|
+
const stat = fs.statSync(skill.skillMdPath);
|
|
549
|
+
const signature = `${stat.size}:${stat.mtimeMs}`;
|
|
550
|
+
let cached = this._bodyCache.get(skill.skillMdPath);
|
|
551
|
+
let cacheRead = false;
|
|
552
|
+
if (cached?.signature === signature) {
|
|
553
|
+
this._cacheStats.bodyCacheHits += 1;
|
|
554
|
+
cacheRead = true;
|
|
555
|
+
} else {
|
|
556
|
+
const content = fs.readFileSync(skill.skillMdPath, "utf-8");
|
|
557
|
+
const { body } = parseSkillMd(content);
|
|
558
|
+
cached = {
|
|
559
|
+
signature,
|
|
560
|
+
body,
|
|
561
|
+
mcpServers: parseSkillMcpServers(body),
|
|
562
|
+
rawChars: body.length,
|
|
563
|
+
estimatedTokens: estimateSkillTokens(body),
|
|
564
|
+
};
|
|
565
|
+
this._bodyCache.set(skill.skillMdPath, cached);
|
|
566
|
+
this._cacheStats.bodyCacheMisses += 1;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
skill.body = cached.body;
|
|
570
|
+
skill.mcpServers = cached.mcpServers;
|
|
571
|
+
skill.bodyLoaded = true;
|
|
572
|
+
skill.skillFileBytes = stat.size;
|
|
573
|
+
skill.skillFileMtimeMs = stat.mtimeMs;
|
|
574
|
+
|
|
575
|
+
const prior = this._cacheStats.bodyLoads.get(skill.skillMdPath) || {
|
|
576
|
+
id: skill.id,
|
|
577
|
+
source: skill.source,
|
|
578
|
+
rawChars: cached.rawChars,
|
|
579
|
+
estimatedTokens: cached.estimatedTokens,
|
|
580
|
+
loads: 0,
|
|
581
|
+
cacheHits: 0,
|
|
582
|
+
loadedBecause: [],
|
|
583
|
+
};
|
|
584
|
+
prior.loads += 1;
|
|
585
|
+
if (cacheRead) prior.cacheHits += 1;
|
|
586
|
+
const reason = context.loadedBecause || "explicit";
|
|
587
|
+
if (!prior.loadedBecause.includes(reason)) prior.loadedBecause.push(reason);
|
|
588
|
+
this._cacheStats.bodyLoads.set(skill.skillMdPath, prior);
|
|
589
|
+
|
|
590
|
+
try {
|
|
591
|
+
this._contextLedger?.recordRead?.({
|
|
592
|
+
sessionId: context.sessionId || "unknown",
|
|
593
|
+
turnId: context.turnId || "unknown",
|
|
594
|
+
sourceType: "skill",
|
|
595
|
+
sourceId: skill.id,
|
|
596
|
+
permissionMode: context.permissionMode || "agent",
|
|
597
|
+
tokenCount: cached.estimatedTokens,
|
|
598
|
+
metadata: {
|
|
599
|
+
source: skill.source,
|
|
600
|
+
loadedBecause: reason,
|
|
601
|
+
cacheRead,
|
|
602
|
+
bodyIncluded: context.bodyIncluded === true,
|
|
603
|
+
},
|
|
604
|
+
});
|
|
605
|
+
} catch {
|
|
606
|
+
// Context observability must never make a valid skill unloadable.
|
|
607
|
+
}
|
|
608
|
+
return skill;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/** Record descriptor text that was actually returned to a model/tool caller. */
|
|
612
|
+
recordDescriptorUse(skills, context = {}) {
|
|
613
|
+
for (const skill of Array.isArray(skills) ? skills : []) {
|
|
614
|
+
const descriptorText = `${skill.id}\n${skill.description || ""}\n${skill.category || ""}`;
|
|
615
|
+
try {
|
|
616
|
+
this._contextLedger?.recordRead?.({
|
|
617
|
+
sessionId: context.sessionId || "unknown",
|
|
618
|
+
turnId: context.turnId || "unknown",
|
|
619
|
+
sourceType: "skill_descriptor",
|
|
620
|
+
sourceId: skill.id,
|
|
621
|
+
permissionMode: context.permissionMode || "agent",
|
|
622
|
+
tokenCount: estimateSkillTokens(descriptorText),
|
|
623
|
+
metadata: {
|
|
624
|
+
source: skill.source,
|
|
625
|
+
loadedBecause: context.loadedBecause || "list_skills",
|
|
626
|
+
bodyLoaded: skill.bodyLoaded === true,
|
|
627
|
+
},
|
|
628
|
+
});
|
|
629
|
+
} catch {
|
|
630
|
+
// Observability only.
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/** Content-free cache/cost snapshot for `cc context --sources`. */
|
|
636
|
+
getCacheLedger() {
|
|
637
|
+
const descriptors = Array.isArray(this._cache) ? this._cache : [];
|
|
638
|
+
const descriptorChars = descriptors.reduce(
|
|
639
|
+
(sum, skill) =>
|
|
640
|
+
sum +
|
|
641
|
+
`${skill.id}\n${skill.displayName}\n${skill.description}\n${skill.category}`.length,
|
|
642
|
+
0,
|
|
643
|
+
);
|
|
644
|
+
const residentPaths = new Set(this._bodyCache.keys());
|
|
645
|
+
const lazyFileBytes = descriptors.reduce(
|
|
646
|
+
(sum, skill) =>
|
|
647
|
+
sum +
|
|
648
|
+
(residentPaths.has(skill.skillMdPath) ? 0 : skill.skillFileBytes || 0),
|
|
649
|
+
0,
|
|
650
|
+
);
|
|
651
|
+
const bodyLoads = Array.from(this._cacheStats.bodyLoads.values()).map(
|
|
652
|
+
(entry) => ({ ...entry, loadedBecause: [...entry.loadedBecause] }),
|
|
653
|
+
);
|
|
654
|
+
return {
|
|
655
|
+
descriptors: {
|
|
656
|
+
resident: descriptors.length,
|
|
657
|
+
scans: this._cacheStats.descriptorScans,
|
|
658
|
+
cacheHits: this._cacheStats.descriptorCacheHits,
|
|
659
|
+
rawChars: descriptorChars,
|
|
660
|
+
estimatedTokens: estimateSkillTokens(descriptorChars),
|
|
661
|
+
},
|
|
662
|
+
bodies: {
|
|
663
|
+
resident: this._bodyCache.size,
|
|
664
|
+
cacheHits: this._cacheStats.bodyCacheHits,
|
|
665
|
+
cacheMisses: this._cacheStats.bodyCacheMisses,
|
|
666
|
+
entries: bodyLoads,
|
|
667
|
+
},
|
|
668
|
+
savings: {
|
|
669
|
+
lazyFileBytes,
|
|
670
|
+
estimatedTokensAvoided: estimateSkillTokens(lazyFileBytes),
|
|
671
|
+
},
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
490
675
|
/**
|
|
491
676
|
* Load all skills from all layers, applying priority override
|
|
492
677
|
* Higher-priority layers override same-name skills from lower layers.
|
|
493
678
|
* @returns {object[]} Resolved skill list
|
|
494
679
|
*/
|
|
495
680
|
loadAll(options = {}) {
|
|
681
|
+
this._cacheStats.descriptorScans += 1;
|
|
496
682
|
// `cc agent --bare` (CC_SKILLS=0): no skill layer loads at all — cache the
|
|
497
683
|
// empty result so getResolvedSkills stays cheap on every call.
|
|
498
684
|
if (allSkillsDisabled(options)) {
|
|
@@ -552,7 +738,10 @@ export class CLISkillLoader {
|
|
|
552
738
|
* @returns {object[]}
|
|
553
739
|
*/
|
|
554
740
|
getResolvedSkills() {
|
|
555
|
-
if (this._cache)
|
|
741
|
+
if (this._cache) {
|
|
742
|
+
this._cacheStats.descriptorCacheHits += 1;
|
|
743
|
+
return this._cache;
|
|
744
|
+
}
|
|
556
745
|
return this.loadAll();
|
|
557
746
|
}
|
|
558
747
|
|
|
@@ -560,10 +749,16 @@ export class CLISkillLoader {
|
|
|
560
749
|
* Get auto-activated persona skills
|
|
561
750
|
* @returns {object[]} skills with category "persona" and activation "auto"
|
|
562
751
|
*/
|
|
563
|
-
getAutoActivatedPersonas() {
|
|
564
|
-
return this.getResolvedSkills()
|
|
565
|
-
(s) => s.category === "persona" && s.activation === "auto"
|
|
566
|
-
|
|
752
|
+
getAutoActivatedPersonas(context = {}) {
|
|
753
|
+
return this.getResolvedSkills()
|
|
754
|
+
.filter((s) => s.category === "persona" && s.activation === "auto")
|
|
755
|
+
.map((skill) =>
|
|
756
|
+
this.materializeSkill(skill, {
|
|
757
|
+
...context,
|
|
758
|
+
loadedBecause: context.loadedBecause || "persona_auto",
|
|
759
|
+
bodyIncluded: true,
|
|
760
|
+
}),
|
|
761
|
+
);
|
|
567
762
|
}
|
|
568
763
|
|
|
569
764
|
/**
|
|
@@ -571,6 +766,14 @@ export class CLISkillLoader {
|
|
|
571
766
|
*/
|
|
572
767
|
clearCache() {
|
|
573
768
|
this._cache = null;
|
|
769
|
+
this._bodyCache.clear();
|
|
770
|
+
this._cacheStats = {
|
|
771
|
+
descriptorScans: 0,
|
|
772
|
+
descriptorCacheHits: 0,
|
|
773
|
+
bodyCacheHits: 0,
|
|
774
|
+
bodyCacheMisses: 0,
|
|
775
|
+
bodyLoads: new Map(),
|
|
776
|
+
};
|
|
574
777
|
}
|
|
575
778
|
}
|
|
576
779
|
|
|
@@ -115,6 +115,7 @@ cli-version-hash: "${hash}"
|
|
|
115
115
|
tags: [${allTags}]
|
|
116
116
|
user-invocable: true
|
|
117
117
|
handler: handler.js
|
|
118
|
+
capabilities: [shell-exec]
|
|
118
119
|
---
|
|
119
120
|
|
|
120
121
|
# ${domainDef.displayName}
|
|
@@ -176,7 +177,6 @@ export function generateDirectHandler(domainKey, domainDef) {
|
|
|
176
177
|
* 自动生成 — 请勿手动修改,运行 \`chainlesschain skill sync-cli\` 重新生成
|
|
177
178
|
*/
|
|
178
179
|
|
|
179
|
-
const { spawnSync } = require("child_process");
|
|
180
180
|
|
|
181
181
|
/** 解析输入字符串为指令+参数数组 */
|
|
182
182
|
function parseInput(input) {
|
|
@@ -241,7 +241,7 @@ ${commandGuide}
|
|
|
241
241
|
const useJson = JSON_SUPPORTED_COMMANDS.has(command) && !cliArgs.includes("--json");
|
|
242
242
|
if (useJson) cliArgs.push("--json");
|
|
243
243
|
|
|
244
|
-
// Security:
|
|
244
|
+
// Security: Broker execution uses shell:true (needed to run the chainlesschain.cmd
|
|
245
245
|
// shim on Windows), which joins cliArgs into a shell command. Reject shell
|
|
246
246
|
// metacharacters so a crafted skill input can't inject commands.
|
|
247
247
|
const unsafeArg = cliArgs.find((a) => /[;&|\`$<>()\\n\\r]/.test(a));
|
|
@@ -252,11 +252,16 @@ ${commandGuide}
|
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
|
|
255
|
+
const processBroker = context?.processBroker;
|
|
256
|
+
if (!processBroker || typeof processBroker.runSync !== "function") {
|
|
257
|
+
return { success: false, error: "Process Broker unavailable for skill execution." };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Execute via the host-scoped Process Broker facade.
|
|
261
|
+
const result = processBroker.runSync("chainlesschain", cliArgs, {
|
|
257
262
|
encoding: "utf-8",
|
|
258
263
|
shell: true,
|
|
259
|
-
cwd: context
|
|
264
|
+
cwd: context?.projectRoot || process.cwd(),
|
|
260
265
|
timeout: 30000,
|
|
261
266
|
env: { ...process.env },
|
|
262
267
|
});
|
|
@@ -407,7 +412,6 @@ export function generateHybridHandler(domainKey, domainDef) {
|
|
|
407
412
|
* 自动生成 — 请勿手动修改,运行 \`chainlesschain skill sync-cli\` 重新生成
|
|
408
413
|
*/
|
|
409
414
|
|
|
410
|
-
const { spawnSync } = require("child_process");
|
|
411
415
|
|
|
412
416
|
const AGENT_ONLY_COMMANDS = new Set([${agentCmds}]);
|
|
413
417
|
const VALID_COMMANDS = new Set(["${commandList}"]);
|
|
@@ -470,7 +474,7 @@ const handler = {
|
|
|
470
474
|
// Direct execution for other commands
|
|
471
475
|
const cliArgs = [...args, "--quiet"];
|
|
472
476
|
|
|
473
|
-
// Security:
|
|
477
|
+
// Security: Broker execution uses shell:true (needed to run the chainlesschain.cmd
|
|
474
478
|
// shim on Windows), which joins cliArgs into a shell command. Reject shell
|
|
475
479
|
// metacharacters so a crafted skill input can't inject commands.
|
|
476
480
|
const unsafeArg = cliArgs.find((a) => /[;&|\`$<>()\\n\\r]/.test(a));
|
|
@@ -481,10 +485,15 @@ const handler = {
|
|
|
481
485
|
};
|
|
482
486
|
}
|
|
483
487
|
|
|
484
|
-
const
|
|
488
|
+
const processBroker = context?.processBroker;
|
|
489
|
+
if (!processBroker || typeof processBroker.runSync !== "function") {
|
|
490
|
+
return { success: false, error: "Process Broker unavailable for skill execution." };
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const result = processBroker.runSync("chainlesschain", cliArgs, {
|
|
485
494
|
encoding: "utf-8",
|
|
486
495
|
shell: true,
|
|
487
|
-
cwd: context
|
|
496
|
+
cwd: context?.projectRoot || process.cwd(),
|
|
488
497
|
timeout: 30000,
|
|
489
498
|
env: { ...process.env },
|
|
490
499
|
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import executionBroker from "./process-execution-broker/index.js";
|
|
2
|
+
|
|
3
|
+
const defaultRunSync = executionBroker.spawnSync.bind(executionBroker);
|
|
4
|
+
const defaultRunFileSync = executionBroker.execFileSync.bind(executionBroker);
|
|
5
|
+
const defaultRun = executionBroker.spawn.bind(executionBroker);
|
|
6
|
+
|
|
7
|
+
function skillIdentity(skill = {}) {
|
|
8
|
+
const identity = String(
|
|
9
|
+
skill.id || skill.name || skill.skillName || "unknown",
|
|
10
|
+
)
|
|
11
|
+
.trim()
|
|
12
|
+
.replace(/[^a-zA-Z0-9._:-]+/g, "-")
|
|
13
|
+
.slice(0, 96);
|
|
14
|
+
return identity || "unknown";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function declaresShellExecution(skill = {}) {
|
|
18
|
+
return (
|
|
19
|
+
Array.isArray(skill.capabilities) &&
|
|
20
|
+
skill.capabilities.some(
|
|
21
|
+
(capability) => String(capability).toLowerCase() === "shell-exec",
|
|
22
|
+
)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create the narrow process facade exposed to a skill handler.
|
|
28
|
+
*
|
|
29
|
+
* The host, not the handler, owns provenance and permission metadata. Generated
|
|
30
|
+
* handlers can choose argv and ordinary process options, but cannot relabel the
|
|
31
|
+
* execution or bypass the Broker boundary.
|
|
32
|
+
*/
|
|
33
|
+
export function createSkillProcessBroker(
|
|
34
|
+
skill,
|
|
35
|
+
{
|
|
36
|
+
run = defaultRun,
|
|
37
|
+
runSync = defaultRunSync,
|
|
38
|
+
runFileSync = defaultRunFileSync,
|
|
39
|
+
} = {},
|
|
40
|
+
) {
|
|
41
|
+
if (!declaresShellExecution(skill)) return null;
|
|
42
|
+
|
|
43
|
+
const identity = skillIdentity(skill);
|
|
44
|
+
const metadata = Object.freeze({
|
|
45
|
+
origin: `skill:${identity}`,
|
|
46
|
+
policy: "allow",
|
|
47
|
+
scope: "skill",
|
|
48
|
+
pluginId: skill?.pluginId || skill?.plugin?.id || null,
|
|
49
|
+
pluginVersion: skill?.pluginVersion || skill?.plugin?.version || null,
|
|
50
|
+
pluginSource: skill?.pluginSource || skill?.plugin?.source || null,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return Object.freeze({
|
|
54
|
+
run(file, args = [], options = {}) {
|
|
55
|
+
return run(file, args, {
|
|
56
|
+
...options,
|
|
57
|
+
...metadata,
|
|
58
|
+
shell: false,
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
runSync(file, args = [], options = {}) {
|
|
63
|
+
return runSync(file, args, {
|
|
64
|
+
...options,
|
|
65
|
+
...metadata,
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
runFileSync(file, args = [], options = {}) {
|
|
70
|
+
return runFileSync(file, args, {
|
|
71
|
+
...options,
|
|
72
|
+
...metadata,
|
|
73
|
+
shell: false,
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const _skillProcessDefaults = {
|
|
80
|
+
run: defaultRun,
|
|
81
|
+
runSync: defaultRunSync,
|
|
82
|
+
runFileSync: defaultRunFileSync,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export { declaresShellExecution as skillDeclaresShellExecution };
|
|
@@ -21,11 +21,15 @@
|
|
|
21
21
|
import fsDefault from "node:fs";
|
|
22
22
|
import pathDefault from "node:path";
|
|
23
23
|
import { homedir } from "node:os";
|
|
24
|
-
import { execSync as execSyncDefault } from "node:child_process";
|
|
25
24
|
import { expandFileRefs } from "../runtime/file-ref-expander.js";
|
|
26
25
|
import { projectRootBase } from "./project-root.cjs";
|
|
26
|
+
import executionBroker from "./process-execution-broker/index.js";
|
|
27
27
|
|
|
28
|
-
const _deps = {
|
|
28
|
+
const _deps = {
|
|
29
|
+
fs: fsDefault,
|
|
30
|
+
path: pathDefault,
|
|
31
|
+
execSync: (...args) => executionBroker.execSync(...args),
|
|
32
|
+
};
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
35
|
* Split `--- ... ---` frontmatter from the body and camelCase the keys (so
|
|
@@ -191,6 +195,10 @@ function runBangs(text, { cwd, execSync }) {
|
|
|
191
195
|
encoding: "utf-8",
|
|
192
196
|
timeout: BANG_TIMEOUT_MS,
|
|
193
197
|
stdio: ["ignore", "pipe", "pipe"],
|
|
198
|
+
origin: "slash-command:bang",
|
|
199
|
+
policy: "allow",
|
|
200
|
+
scope: "slash-command",
|
|
201
|
+
shell: true,
|
|
194
202
|
});
|
|
195
203
|
return String(out).trim();
|
|
196
204
|
} catch (err) {
|
package/src/lib/status-line.cjs
CHANGED
|
@@ -13,15 +13,14 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Best-effort throughout: a missing config, a broken command, or a timeout just
|
|
15
15
|
* yields no status line — it never blocks or breaks the REPL. `_deps` injection
|
|
16
|
-
* (
|
|
16
|
+
* (process runner / settings reader) for tests.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
const cpDefault = require("node:child_process");
|
|
20
19
|
const path = require("node:path");
|
|
21
20
|
const { settingsPaths, readSettingsFile } = require("./settings-loader.cjs");
|
|
22
21
|
|
|
23
22
|
const _deps = {
|
|
24
|
-
|
|
23
|
+
runProcess: null,
|
|
25
24
|
// injectable so tests don't touch real settings files
|
|
26
25
|
readSettings: (cwd, settingsFile) => {
|
|
27
26
|
const out = [];
|
|
@@ -181,7 +180,7 @@ function isStatusLineDisabled({ cwd = process.cwd(), settingsFile } = {}) {
|
|
|
181
180
|
function renderStatusLine(
|
|
182
181
|
config,
|
|
183
182
|
context = {},
|
|
184
|
-
{ cwd, timeout = 5000, columns, rows } = {},
|
|
183
|
+
{ cwd, timeout = 5000, columns, rows, runProcess } = {},
|
|
185
184
|
) {
|
|
186
185
|
if (!config || !config.command) return null;
|
|
187
186
|
// Claude-Code parity (2.1.153): hand the command the terminal width/height so
|
|
@@ -194,7 +193,9 @@ function renderStatusLine(
|
|
|
194
193
|
if (rws != null) env.LINES = String(rws);
|
|
195
194
|
let res;
|
|
196
195
|
try {
|
|
197
|
-
|
|
196
|
+
const runner = runProcess || _deps.runProcess;
|
|
197
|
+
if (typeof runner !== "function") return null;
|
|
198
|
+
res = runner(config.command, [], {
|
|
198
199
|
input: JSON.stringify(context),
|
|
199
200
|
cwd: cwd || process.cwd(),
|
|
200
201
|
env,
|
|
@@ -202,6 +203,9 @@ function renderStatusLine(
|
|
|
202
203
|
timeout,
|
|
203
204
|
shell: true,
|
|
204
205
|
maxBuffer: 1024 * 1024,
|
|
206
|
+
origin: "status-line:command",
|
|
207
|
+
policy: "allow",
|
|
208
|
+
scope: "status-line",
|
|
205
209
|
});
|
|
206
210
|
} catch {
|
|
207
211
|
return null; // spawn failure → no status line
|
|
@@ -216,11 +220,28 @@ function renderStatusLine(
|
|
|
216
220
|
}
|
|
217
221
|
|
|
218
222
|
/** Convenience: load + render in one call (used by the REPL each turn). */
|
|
219
|
-
function getStatusLine({
|
|
223
|
+
function getStatusLine({
|
|
224
|
+
cwd,
|
|
225
|
+
settingsFile,
|
|
226
|
+
sessionId,
|
|
227
|
+
model,
|
|
228
|
+
provider,
|
|
229
|
+
projectDir,
|
|
230
|
+
timeout,
|
|
231
|
+
columns,
|
|
232
|
+
rows,
|
|
233
|
+
runProcess,
|
|
234
|
+
} = {}) {
|
|
220
235
|
const config = loadStatusLineConfig({ cwd, settingsFile });
|
|
221
236
|
if (!config) return null;
|
|
222
237
|
const context = buildContext({ sessionId, model, provider, cwd, projectDir });
|
|
223
|
-
return renderStatusLine(config, context, {
|
|
238
|
+
return renderStatusLine(config, context, {
|
|
239
|
+
cwd,
|
|
240
|
+
timeout,
|
|
241
|
+
columns,
|
|
242
|
+
rows,
|
|
243
|
+
runProcess,
|
|
244
|
+
});
|
|
224
245
|
}
|
|
225
246
|
|
|
226
247
|
module.exports = {
|