chainlesschain 0.162.142 → 0.162.147
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/bin/chainlesschain.js +5 -3
- package/package.json +2 -2
- package/src/assets/web-panel/assets/{AIOps-Dc6fWgoa.js → AIOps-DywJ7xTv.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DzMx25vJ.js → ActionButton-BTlqcY-q.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-eDC3KNht.js → Analytics-FdG1Mvwy.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-uA1TOtNp.js → AppLayout-CVsnbvN1.js} +3 -3
- package/src/assets/web-panel/assets/{Audit-Bq3QX9Cj.js → Audit-ITdpJ7vR.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B1V3Jfyv.js → Backup-BfXqnXo1.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DMFwddIF.js → BaseInput-C09ip3_E.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CKWQDH5j.js → Chat-qdkhB42l.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CStSBCnk.js → ChatBubbleRenderer-D2KfETZD.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DepIzI7G.js → Checkbox-j6WZCuff.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-ClanWll2.js → Codegen-CGZ-K3uK.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CFBzsL4W.js → Col-CIlPOAu6.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CaAyZ_Pt.js → Community-sY-i-hic.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-3dCHRSVe.js → Compact-DcoEfyL8.js} +1 -1
- package/src/assets/web-panel/assets/Compliance-T8EtTecW.js +1 -0
- package/src/assets/web-panel/assets/{Cowork-DkJmdQaU.js → Cowork-DLY_fkLv.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DKfNf6J2.js → Cron-D049pZBC.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-COu1aQIO.js → Crosschain-DCXdE8M9.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CkAgFLkI.js → DID-JCvPZtjW.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CfaKWZCU.js → Dashboard-Cg2xu3iE.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Cjw97sdb.js → Dropdown-DjJLjbLh.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DROLQgOn.js → EmailListRenderer-DugNcSLR.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-o_cYzlLq.js → FamilyGuardDashboard-J6Nb-E30.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Boex3ljt.js → Federation-CQ3Ttpbl.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BQQ05T_3.js → FormItemContext-Cz0NKag4.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CdfL8PBd.js → GenericCardRenderer-NYcMP6iz.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CfZ07qJy.js → Git-B4hYN18N.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-B21ISudq.js → Governance-DOQPCcC0.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CGIK4Im1.js → Inference-HtLF746W.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CI1kmfdT.js → KnowledgeGraph-BXrk8rMm.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Dpc1-__h.js → Logs-DS0JnD3-.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-BpMtMWyK.js → Marketplace-Cqnjihrz.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-B94WvOOS.js → McpTools-Cx3Psk-U.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-DODsAxZf.js → Memory-BjyysPtj.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C3Bjshem.js → MobileBridge-CYaITZ7w.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-Bi8IHDv_.js → MobileProjects-Xwf-fdOQ.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CH5BSuWG.js → Mtc-Djkql5m5.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-DN3MzNtL.js → MtcAudit-D2BAZlu0.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-CO6GWQOh.js → Multisig-ByqP1ZzH.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DhIr3V_u.js → NLProgramming-C_kn0nE2.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CNgrvZCJ.js → Notes-7l7eXHPq.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-Crr4LPjQ.js → NotificationSettings-BrCDoitw.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-C8q-kK2z.js → OrderTableRenderer-CmtqIdwr.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-hWhCmeUn.js → Organization-DdoNAxsM.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-t_EBxns-.js → Overflow-Bw7R6dE3.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-B8fqfwis.js → P2P-DJNtBugA.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-d-wlJw3R.js → PdhVaultBrowser-Dwhd5_ue.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-Ch13YpBo.js → Permissions-BYoSfhPR.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DW7LlLbS.js → PersonalDataHub-aYCYJbnH.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-BHh3HqOQ.js → Pipeline-DJp6CprF.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DAhlJDSC.js → Privacy-Cq9HZweR.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BRtddAM_.js → ProjectInit-CmF0HsSt.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CzR1EC7b.js → ProjectSettings-P8V5Aea2.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DSavX602.js → Projects-DPd5-lNS.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D55_kGZs.js → Providers-D589v0q2.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BR5qDIaT.js → QuickAsk-lvRV2osB.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CTFAM97K.js → Recommend-sb84MTpY.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-Z7pvEha9.js → Reputation-d9Y3vy-W.js} +1 -1
- package/src/assets/web-panel/assets/{Row-MqKcIsjP.js → Row-DMdhLUTp.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DdLDjRpk.js → RssFeed-OL-SMDkz.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CeOzh2hz.js → Search-BjStLKq1.js} +1 -1
- package/src/assets/web-panel/assets/{Security-gHrXaf4o.js → Security-MeI411qr.js} +3 -3
- package/src/assets/web-panel/assets/{Services-B8Y7pmY1.js → Services-UajosuhT.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CRS0WNut.js → Skeleton-CGpG-QJ1.js} +1 -1
- package/src/assets/web-panel/assets/{Skills--a5_Pdxx.js → Skills-C6P2RPY-.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-EcTyL6EM.js → Sla-B_fPprgw.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-QpfvOiJr.js → SpeechSettings-CqxLjSlQ.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DaLBBzlE.js → SyncSettings-DixSfFOQ.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Ca6xvO-I.js → Tasks-PavzPBxc.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CWguiCoE.js → Templates-BYdGRnfX.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BGLLZulu.js → Tenant-BQLgnarD.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-BzOHpq-B.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-CLjvjbmr.js → TimelineRenderer-Bv7uZRM7.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-De5mmw_a.js → Tokens-DxhgszRJ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Chbq6U0N.js → Trigger-nQYHayuc.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CYxUO2lv.js → Trust-CvqZDuZ4.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-iyoZXXF6.js → UkeySign-DaR8GV2I.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CHg3ifJs.js → VideoEditing-C6Mpsokw.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DfjqObsO.js → Wallet-B57VRrWc.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-0FI6xfud.js → WebAuthn-BbtEEtpq.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CJgGcctS.js → WorkflowEditor-C5LwvKmH.js} +1 -1
- package/src/assets/web-panel/assets/{chat-fH-E4vhY.js → chat-MzuPR5jh.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CuxsOD6d.js → colors-HyW8mi_y.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-AfVcFrFU.js → compact-item-DvUSzWAp.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DTsD7sPO.js → createContext-4MppZl7X.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-6YJJMjSH.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DJR763M6.js → hasIn-D9q3CJ-u.js} +1 -1
- package/src/assets/web-panel/assets/{index-DhM9FZUH.js → index--Bm6OqmU.js} +1 -1
- package/src/assets/web-panel/assets/{index-OZwLoscJ.js → index-B5E4DhVc.js} +1 -1
- package/src/assets/web-panel/assets/{index-CF8OSTin.js → index-B994UQfE.js} +1 -1
- package/src/assets/web-panel/assets/{index-9cryBBzh.js → index-BF2JsbiX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMVULNUC.js → index-BFGfC5RS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dj1_lz3M.js → index-BGQtFso0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBPAH7rp.js → index-BcunsBIx.js} +1 -1
- package/src/assets/web-panel/assets/{index-mLAfJXAf.js → index-Bl-E4W4q.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cfppli6E.js → index-BmCo2Xdp.js} +1 -1
- package/src/assets/web-panel/assets/{index-_hP8-Y2F.js → index-Btz8pU68.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvlzcX3Q.js → index-C0DiL97c.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBBStCbO.js → index-C9I5MuJ0.js} +1 -1
- package/src/assets/web-panel/assets/{index-SuJ2_OzM.js → index-CLAZs1Vd.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8DLT-F4.js → index-Caqtu6Et.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cm4cHE5_.js → index-CgIfXOD9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbQX0Zbf.js → index-Ci6adKh8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEGMojUg.js → index-CifKUNtV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdV7a6-K.js → index-Cs-RKRUM.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dswd93W4.js → index-CucRo4Vz.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2KdGSMa.js → index-CvAqCAo9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqflTl_b.js → index-D2jrnaq3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cl7chKuM.js → index-D7TDMMfu.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAbZ3dW9.js → index-DDZ6fP5Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-BD4-kWQY.js → index-DFqvWeGc.js} +1 -1
- package/src/assets/web-panel/assets/{index-DejUsZOw.js → index-DNYqw0MO.js} +1 -1
- package/src/assets/web-panel/assets/index-D_oeGLr6.js +1 -0
- package/src/assets/web-panel/assets/{index-DH-dA4pG.js → index-DcMkjb92.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMcYdHhK.js → index-DmZ6-suL.js} +1 -1
- package/src/assets/web-panel/assets/{index-85iIi3qF.js → index-Dv7ffI2g.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJIFQ-Ay.js → index-Dvg5xYuP.js} +1 -1
- package/src/assets/web-panel/assets/index-Qa57YG19.js +1 -0
- package/src/assets/web-panel/assets/{index-DxD03TL7.js → index-SDblbKj6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmUxSTNy.js → index-UUMCA2Sq.js} +3 -3
- package/src/assets/web-panel/assets/{index-BJl6Ob-o.js → index-Zvtru2oE.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPHYW3IK.js → index-eOQO6KnV.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-rcowKd.js → index-m0b6Fj9q.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTtL2Qkb.js → index-ryFLxB1p.js} +1 -1
- package/src/assets/web-panel/assets/{index-fj3ZXgiy.js → index-xvUVuFnA.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbpuFc8C.js → index-zLwYpvX0.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BGoLJP6T.js → initDefaultProps-CC--PMsC.js} +1 -1
- package/src/assets/web-panel/assets/{motion-23xdoVi0.js → motion-DdrBjRF1.js} +1 -1
- package/src/assets/web-panel/assets/{move-C3Bnnft-.js → move-D712Gwl2.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-Dv0C3a90.js → mtc-parser-39y-keKO.js} +1 -1
- package/src/assets/web-panel/assets/{omit-C3r9qzDO.js → omit-6Y51gDB9.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-B4bJOcNp.js → pickAttrs-Cy6EHbq9.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Dxf48wcO.js → placementArrow-BYxdAm0p.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Rq9U2hbz.js → responsiveObserve-C9R6q_cr.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BeWiqbdF.js → slide-CXUJlilB.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-yX9N1cEc.js → statusUtils-DOtrOeql.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-5Ko9NorO.js → styleChecker-D5r39o92.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-WKpkTLok.js → useFlexGapSupport-DfAD5U4Z.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BV4X0JOG.js → useFs-BkrT-Zbc.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-g41wq_2p.js → usePersonalDataHub-BwnnnZjU.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BAurbOH8.js → vnode-SU-N4pum.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cl5XniRg.js → zoom-DHScfpTP.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/auth/npm-auth.js +65 -0
- package/src/command-manifest.json +1126 -0
- package/src/commands/agent.js +92 -0
- package/src/commands/agents.js +68 -0
- package/src/commands/note.js +2 -1
- package/src/commands/permissions.js +66 -10
- package/src/commands/plugin.js +50 -3
- package/src/commands/search.js +2 -1
- package/src/harness/worktree-isolator.js +14 -7
- package/src/index.js +4 -12
- package/src/lazy-dispatch.js +107 -0
- package/src/lib/agent-sandbox.js +72 -0
- package/src/lib/background-agent-supervisor.js +197 -0
- package/src/lib/code-review.js +72 -0
- package/src/lib/ensure-utf8.js +25 -7
- package/src/lib/knowledge-exporter.js +3 -2
- package/src/lib/permission-engine.js +1 -1
- package/src/lib/plugin-security.js +128 -0
- package/src/lib/pr-create.js +108 -0
- package/src/lib/publish-workspace.js +107 -0
- package/src/lib/resume-session.js +111 -0
- package/src/lib/session-manager.js +2 -1
- package/src/lib/settings-hooks.cjs +68 -25
- package/src/lib/settings-loader.cjs +115 -2
- package/src/lib/task-list.js +53 -0
- package/src/program-base.js +24 -0
- package/src/repl/agent-repl.js +108 -3
- package/src/repl/agents-status.js +8 -2
- package/src/repl/btw-command.js +56 -0
- package/src/repl/chat-repl.js +52 -1
- package/src/repl/hooks-status.js +1 -2
- package/src/repl/slash-command-registry.js +197 -0
- package/src/repl/think-command.js +31 -0
- package/src/runtime/agent-core.js +137 -1
- package/src/runtime/coding-agent-contract-shared.cjs +37 -0
- package/src/runtime/coding-agent-policy.cjs +14 -0
- package/src/runtime/file-ref-expander.js +100 -14
- package/src/runtime/headless-runner.js +26 -6
- package/src/runtime/headless-stream.js +25 -6
- package/src/runtime/mcp-config.js +46 -2
- package/src/runtime/policies/agent-policy.js +1 -0
- package/src/workers/background-agent-worker.js +60 -0
- package/src/assets/web-panel/assets/Compliance-BKYHHTdq.js +0 -1
- package/src/assets/web-panel/assets/Terminal-Bryzb1Rm.js +0 -3
- package/src/assets/web-panel/assets/devWarning-DffbPlEe.js +0 -1
- package/src/assets/web-panel/assets/index-BAHgOh3h.js +0 -1
- package/src/assets/web-panel/assets/index-zfkDb9FC.js +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Publish workspace packages to npm (ESM)
|
|
3
|
+
* Mirrors Claude Code /publish behavior
|
|
4
|
+
* @module lib/publish-workspace
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync } from "child_process";
|
|
8
|
+
import { logger } from "./logger.js";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get all workspace packages
|
|
14
|
+
* @returns {Array<{name: string, path: string, version: string}>}
|
|
15
|
+
*/
|
|
16
|
+
export function getWorkspacePackages() {
|
|
17
|
+
try {
|
|
18
|
+
const rootPkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
|
19
|
+
const packages = [];
|
|
20
|
+
|
|
21
|
+
// Handle workspaces config
|
|
22
|
+
const workspaces = rootPkg.workspaces?.packages || rootPkg.workspaces || [];
|
|
23
|
+
for (const pattern of workspaces) {
|
|
24
|
+
// Simple glob handling for basic patterns
|
|
25
|
+
const dir = pattern.replace(/\*+/g, "");
|
|
26
|
+
if (fs.existsSync(dir)) {
|
|
27
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
const pkgPath = path.join(dir, entry.name);
|
|
31
|
+
const pkgFile = path.join(pkgPath, "package.json");
|
|
32
|
+
if (fs.existsSync(pkgFile)) {
|
|
33
|
+
const pkg = JSON.parse(fs.readFileSync(pkgFile, "utf8"));
|
|
34
|
+
if (pkg.name && !pkg.private) {
|
|
35
|
+
packages.push({
|
|
36
|
+
name: pkg.name,
|
|
37
|
+
path: pkgPath,
|
|
38
|
+
version: pkg.version,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return packages;
|
|
48
|
+
} catch (err) {
|
|
49
|
+
logger.error(`Failed to get workspace packages: ${err.message}`);
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Publish a single package
|
|
56
|
+
* @param {Object} pkg Package info
|
|
57
|
+
* @param {Object} options Publish options
|
|
58
|
+
* @returns {boolean} success
|
|
59
|
+
*/
|
|
60
|
+
export function publishPackage(pkg, options = {}) {
|
|
61
|
+
try {
|
|
62
|
+
logger.info(`Publishing ${pkg.name}@${pkg.version}...`);
|
|
63
|
+
let cmd = "npm publish";
|
|
64
|
+
if (options.tag) cmd += ` --tag ${options.tag}`;
|
|
65
|
+
if (options.access) cmd += ` --access ${options.access}`;
|
|
66
|
+
|
|
67
|
+
execSync(cmd, {
|
|
68
|
+
cwd: pkg.path,
|
|
69
|
+
stdio: "inherit",
|
|
70
|
+
encoding: "utf8",
|
|
71
|
+
});
|
|
72
|
+
logger.succeed(`Published ${pkg.name}@${pkg.version}`);
|
|
73
|
+
return true;
|
|
74
|
+
} catch (err) {
|
|
75
|
+
logger.error(`Failed to publish ${pkg.name}: ${err.message}`);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Publish all changed workspace packages
|
|
82
|
+
* @param {Object} options Options
|
|
83
|
+
* @returns {Promise<boolean>} success
|
|
84
|
+
*/
|
|
85
|
+
export async function publishWorkspace(options = {}) {
|
|
86
|
+
const packages = getWorkspacePackages();
|
|
87
|
+
if (packages.length === 0) {
|
|
88
|
+
logger.info("No publishable packages found");
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
logger.info(`Found ${packages.length} publishable packages`);
|
|
93
|
+
let allSucceeded = true;
|
|
94
|
+
|
|
95
|
+
for (const pkg of packages) {
|
|
96
|
+
if (options.dryRun) {
|
|
97
|
+
logger.info(`[dry-run] Would publish ${pkg.name}@${pkg.version}`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const ok = publishPackage(pkg, options);
|
|
101
|
+
if (!ok) allSucceeded = false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return allSucceeded;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export default { getWorkspacePackages, publishPackage, publishWorkspace };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session resume utilities (ESM)
|
|
3
|
+
* Mirrors Claude Code /resume behavior
|
|
4
|
+
* @module lib/resume-session
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import path from "path";
|
|
9
|
+
import os from "os";
|
|
10
|
+
import { logger } from "./logger.js";
|
|
11
|
+
|
|
12
|
+
const SESSION_DIR = path.join(os.homedir(), ".chainlesschain", "sessions");
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* List recent chat sessions
|
|
16
|
+
* @param {number} limit Maximum sessions to return
|
|
17
|
+
* @returns {Array<Object>} list of sessions
|
|
18
|
+
*/
|
|
19
|
+
export function listSessions(limit = 10) {
|
|
20
|
+
try {
|
|
21
|
+
if (!fs.existsSync(SESSION_DIR)) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const files = fs
|
|
26
|
+
.readdirSync(SESSION_DIR)
|
|
27
|
+
.filter((f) => f.endsWith(".json"))
|
|
28
|
+
.map((f) => {
|
|
29
|
+
const filePath = path.join(SESSION_DIR, f);
|
|
30
|
+
const stat = fs.statSync(filePath);
|
|
31
|
+
let summary = "";
|
|
32
|
+
try {
|
|
33
|
+
const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
34
|
+
summary = data.summary || data.title || f.replace(".json", "");
|
|
35
|
+
} catch {
|
|
36
|
+
summary = f.replace(".json", "");
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
id: f.replace(".json", ""),
|
|
40
|
+
file: filePath,
|
|
41
|
+
mtime: stat.mtimeMs,
|
|
42
|
+
summary,
|
|
43
|
+
};
|
|
44
|
+
})
|
|
45
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
46
|
+
.slice(0, limit);
|
|
47
|
+
|
|
48
|
+
return files;
|
|
49
|
+
} catch (err) {
|
|
50
|
+
logger.debug(`Error listing sessions: ${err.message}`);
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Load a session by ID
|
|
57
|
+
* @param {string} sessionId
|
|
58
|
+
* @returns {Object|null} session data
|
|
59
|
+
*/
|
|
60
|
+
export function loadSession(sessionId) {
|
|
61
|
+
try {
|
|
62
|
+
const filePath = path.join(SESSION_DIR, `${sessionId}.json`);
|
|
63
|
+
if (!fs.existsSync(filePath)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
67
|
+
} catch (err) {
|
|
68
|
+
logger.error(`Error loading session ${sessionId}: ${err.message}`);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get the most recent session
|
|
75
|
+
* @returns {Object|null}
|
|
76
|
+
*/
|
|
77
|
+
export function getLatestSession() {
|
|
78
|
+
const sessions = listSessions(1);
|
|
79
|
+
return sessions.length > 0 ? loadSession(sessions[0].id) : null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Resume a chat session
|
|
84
|
+
* @param {string} [sessionId] Optional session ID (resumes latest if not provided)
|
|
85
|
+
* @returns {Promise<Object>} resume result
|
|
86
|
+
*/
|
|
87
|
+
export async function resumeSession(sessionId) {
|
|
88
|
+
let session;
|
|
89
|
+
if (sessionId) {
|
|
90
|
+
session = loadSession(sessionId);
|
|
91
|
+
if (!session) {
|
|
92
|
+
return { success: false, message: `Session ${sessionId} not found` };
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
session = getLatestSession();
|
|
96
|
+
if (!session) {
|
|
97
|
+
return { success: false, message: "No previous sessions found" };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
success: true,
|
|
103
|
+
sessionId: session.id || sessionId,
|
|
104
|
+
messageCount: session.messages?.length || 0,
|
|
105
|
+
summary: session.summary,
|
|
106
|
+
session,
|
|
107
|
+
message: "Session loaded. Continue chatting to resume the conversation.",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export default { listSessions, loadSession, getLatestSession, resumeSession };
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { createHash } from "crypto";
|
|
9
|
+
import { safeJsonParse } from "./safe-json.js";
|
|
9
10
|
|
|
10
11
|
function ensureSessionsTable(db) {
|
|
11
12
|
db.exec(`
|
|
@@ -153,7 +154,7 @@ export function listSessions(db, options = {}) {
|
|
|
153
154
|
...session,
|
|
154
155
|
metadata:
|
|
155
156
|
typeof session.metadata === "string"
|
|
156
|
-
?
|
|
157
|
+
? safeJsonParse(session.metadata, {})
|
|
157
158
|
: session.metadata || {},
|
|
158
159
|
}));
|
|
159
160
|
}
|
|
@@ -82,20 +82,66 @@ function readJson(file, onWarn) {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
function managedSettingsFile(env = process.env) {
|
|
86
|
+
if (env.CC_MANAGED_SETTINGS) return path.resolve(env.CC_MANAGED_SETTINGS);
|
|
87
|
+
if (process.platform === "win32") {
|
|
88
|
+
const base = env.ProgramData || env.PROGRAMDATA || "C:\\ProgramData";
|
|
89
|
+
return path.join(base, "ChainlessChain", "managed-settings.json");
|
|
90
|
+
}
|
|
91
|
+
return "/etc/chainlesschain/managed-settings.json";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function appendHookBlock(merged, data) {
|
|
95
|
+
const block =
|
|
96
|
+
data && data.hooks && typeof data.hooks === "object" ? data.hooks : null;
|
|
97
|
+
if (!block) return false;
|
|
98
|
+
let contributed = false;
|
|
99
|
+
for (const [event, groups] of Object.entries(block)) {
|
|
100
|
+
if (!Array.isArray(groups)) continue;
|
|
101
|
+
for (const g of groups) {
|
|
102
|
+
if (!g || typeof g !== "object" || !Array.isArray(g.hooks)) continue;
|
|
103
|
+
const cmds = g.hooks.filter(
|
|
104
|
+
(h) => h && h.type === "command" && h.command,
|
|
105
|
+
);
|
|
106
|
+
if (cmds.length === 0) continue;
|
|
107
|
+
if (!merged[event]) merged[event] = [];
|
|
108
|
+
merged[event].push({ matcher: g.matcher ?? null, hooks: cmds });
|
|
109
|
+
contributed = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return contributed;
|
|
113
|
+
}
|
|
114
|
+
|
|
85
115
|
/**
|
|
86
116
|
* Load + concatenate the `hooks` blocks across the hierarchy.
|
|
87
117
|
* @returns {{ hooks: Record<string, Array<{matcher:string|null, hooks:Array<{type,command,timeout}>}>>, files:string[] }}
|
|
88
118
|
*/
|
|
89
|
-
function loadHooks({
|
|
119
|
+
function loadHooks({
|
|
120
|
+
cwd = process.cwd(),
|
|
121
|
+
settingsFile,
|
|
122
|
+
onWarn,
|
|
123
|
+
env = process.env,
|
|
124
|
+
} = {}) {
|
|
90
125
|
const merged = {};
|
|
91
126
|
const files = [];
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
|
|
127
|
+
const managedFile = managedSettingsFile(env);
|
|
128
|
+
let managed = null;
|
|
129
|
+
if (_deps.fs.existsSync(managedFile)) {
|
|
130
|
+
managed = readJson(managedFile, onWarn);
|
|
131
|
+
if (!managed) {
|
|
132
|
+
const error = new Error(
|
|
133
|
+
`managed settings are unreadable or malformed: ${managedFile}`,
|
|
134
|
+
);
|
|
135
|
+
error.code = "CC_MANAGED_SETTINGS_INVALID";
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
96
138
|
}
|
|
139
|
+
// Safe-mode kill switch (`cc agent --safe-mode` sets CC_SETTINGS_HOOKS=0):
|
|
140
|
+
// user/project hooks are disabled, but administrator hooks remain active.
|
|
141
|
+
const managedOnly = managed?.allowManagedHooksOnly === true;
|
|
142
|
+
const skipUnmanaged = env.CC_SETTINGS_HOOKS === "0" || managedOnly;
|
|
97
143
|
const seenPaths = new Set();
|
|
98
|
-
for (const file of settingsFiles(cwd, settingsFile)) {
|
|
144
|
+
for (const file of skipUnmanaged ? [] : settingsFiles(cwd, settingsFile)) {
|
|
99
145
|
// Dedup by RESOLVED path so the SAME physical file is never read twice — e.g.
|
|
100
146
|
// `--settings .claude/settings.json` from the project root aliases the
|
|
101
147
|
// auto-loaded cwd file, which would otherwise CONCATENATE its hook groups a
|
|
@@ -106,26 +152,16 @@ function loadHooks({ cwd = process.cwd(), settingsFile, onWarn } = {}) {
|
|
|
106
152
|
if (seenPaths.has(resolved)) continue;
|
|
107
153
|
seenPaths.add(resolved);
|
|
108
154
|
const data = readJson(file, onWarn);
|
|
109
|
-
const
|
|
110
|
-
data && data.hooks && typeof data.hooks === "object" ? data.hooks : null;
|
|
111
|
-
if (!block) continue;
|
|
112
|
-
let contributed = false;
|
|
113
|
-
for (const [event, groups] of Object.entries(block)) {
|
|
114
|
-
if (!Array.isArray(groups)) continue;
|
|
115
|
-
for (const g of groups) {
|
|
116
|
-
if (!g || typeof g !== "object" || !Array.isArray(g.hooks)) continue;
|
|
117
|
-
const cmds = g.hooks.filter(
|
|
118
|
-
(h) => h && h.type === "command" && h.command,
|
|
119
|
-
);
|
|
120
|
-
if (cmds.length === 0) continue;
|
|
121
|
-
if (!merged[event]) merged[event] = [];
|
|
122
|
-
merged[event].push({ matcher: g.matcher ?? null, hooks: cmds });
|
|
123
|
-
contributed = true;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
155
|
+
const contributed = appendHookBlock(merged, data);
|
|
126
156
|
if (contributed) files.push(file);
|
|
127
157
|
}
|
|
128
|
-
|
|
158
|
+
if (managed && appendHookBlock(merged, managed)) files.push(managedFile);
|
|
159
|
+
const result = { hooks: merged, files };
|
|
160
|
+
if (managed) {
|
|
161
|
+
result.managed = managed;
|
|
162
|
+
result.managedFile = managedFile;
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
129
165
|
}
|
|
130
166
|
|
|
131
167
|
/**
|
|
@@ -184,7 +220,8 @@ function collectHooks(hooksBlock, event, toolName) {
|
|
|
184
220
|
for (const g of groups) {
|
|
185
221
|
const fn = compileMatcher(g.matcher);
|
|
186
222
|
if (fn(umbrella) || (raw && fn(raw))) {
|
|
187
|
-
for (const h of g.hooks)
|
|
223
|
+
for (const h of g.hooks)
|
|
224
|
+
out.push({ command: h.command, timeout: h.timeout });
|
|
188
225
|
}
|
|
189
226
|
}
|
|
190
227
|
return out;
|
|
@@ -265,6 +302,11 @@ function writeHookTrustStore(store) {
|
|
|
265
302
|
function projectHookTrustNotice({ cwd = process.cwd(), settingsFile } = {}) {
|
|
266
303
|
if (process.env.CC_HOOK_TRUST_NOTICE === "0") return null;
|
|
267
304
|
if (process.env.CC_SETTINGS_HOOKS === "0") return null; // hooks won't run anyway
|
|
305
|
+
const managedFile = managedSettingsFile(process.env);
|
|
306
|
+
if (_deps.fs.existsSync(managedFile)) {
|
|
307
|
+
const managed = readJson(managedFile);
|
|
308
|
+
if (managed?.allowManagedHooksOnly === true) return null;
|
|
309
|
+
}
|
|
268
310
|
const home = path.join(_deps.homedir(), ".claude", "settings.json");
|
|
269
311
|
const explicit = settingsFile ? path.resolve(cwd, settingsFile) : null;
|
|
270
312
|
const trusted = new Set([home, explicit].filter(Boolean));
|
|
@@ -328,6 +370,7 @@ module.exports = {
|
|
|
328
370
|
compileMatcher,
|
|
329
371
|
umbrellaFor,
|
|
330
372
|
settingsFiles,
|
|
373
|
+
managedSettingsFile,
|
|
331
374
|
HOOK_EVENTS,
|
|
332
375
|
_deps,
|
|
333
376
|
};
|
|
@@ -88,6 +88,69 @@ function settingsPaths(cwd, explicitFile) {
|
|
|
88
88
|
return list;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/** Organization-controlled settings file. This layer is always highest. */
|
|
92
|
+
function managedSettingsPath(opts = {}) {
|
|
93
|
+
if (opts.managedSettingsFile) return path.resolve(opts.managedSettingsFile);
|
|
94
|
+
const env = opts.env || process.env;
|
|
95
|
+
if (env.CC_MANAGED_SETTINGS) return path.resolve(env.CC_MANAGED_SETTINGS);
|
|
96
|
+
if (process.platform === "win32") {
|
|
97
|
+
const base = env.ProgramData || env.PROGRAMDATA || "C:\\ProgramData";
|
|
98
|
+
return path.join(base, "ChainlessChain", "managed-settings.json");
|
|
99
|
+
}
|
|
100
|
+
return "/etc/chainlesschain/managed-settings.json";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function loadManagedSettings(opts = {}) {
|
|
104
|
+
const file = managedSettingsPath(opts);
|
|
105
|
+
if (!_deps.fs.existsSync(file)) return { file, settings: null };
|
|
106
|
+
const data = readSettingsFile(file, { onWarn: opts.onWarn });
|
|
107
|
+
if (!data) {
|
|
108
|
+
const error = new Error(
|
|
109
|
+
`managed settings are unreadable or malformed: ${file}`,
|
|
110
|
+
);
|
|
111
|
+
error.code = "CC_MANAGED_SETTINGS_INVALID";
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
return { file, settings: data };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function emptyRules() {
|
|
118
|
+
return { allow: [], ask: [], deny: [] };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Apply the non-bypassable permission portion of managed settings. */
|
|
122
|
+
function applyManagedPermissionPolicy(baseRules, managed, sources = {}) {
|
|
123
|
+
const policy = managed && typeof managed === "object" ? managed : {};
|
|
124
|
+
const rules = policy.allowManagedPermissionRulesOnly
|
|
125
|
+
? emptyRules()
|
|
126
|
+
: {
|
|
127
|
+
allow: [...(baseRules?.allow || [])],
|
|
128
|
+
ask: [...(baseRules?.ask || [])],
|
|
129
|
+
deny: [...(baseRules?.deny || [])],
|
|
130
|
+
};
|
|
131
|
+
const perms =
|
|
132
|
+
policy.permissions && typeof policy.permissions === "object"
|
|
133
|
+
? policy.permissions
|
|
134
|
+
: {};
|
|
135
|
+
for (const kind of KINDS) {
|
|
136
|
+
accrete(rules[kind], sources, perms[kind], "<managed>", kind);
|
|
137
|
+
}
|
|
138
|
+
return rules;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function assertManagedPermissionMode(mode, managed) {
|
|
142
|
+
if (
|
|
143
|
+
mode === "bypassPermissions" &&
|
|
144
|
+
(managed?.disableBypassPermissionsMode === true ||
|
|
145
|
+
managed?.disableBypassPermissionsMode === "disable")
|
|
146
|
+
) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
'permission mode "bypassPermissions" is disabled by managed settings',
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
return mode;
|
|
152
|
+
}
|
|
153
|
+
|
|
91
154
|
/** Parse a comma/space separated env override into a string[]. */
|
|
92
155
|
function parseEnvList(value) {
|
|
93
156
|
if (!value) return [];
|
|
@@ -116,7 +179,7 @@ function loadSettings(opts = {}) {
|
|
|
116
179
|
const env = opts.env || process.env;
|
|
117
180
|
const onWarn = opts.onWarn;
|
|
118
181
|
|
|
119
|
-
|
|
182
|
+
let rules = emptyRules();
|
|
120
183
|
const sources = {};
|
|
121
184
|
const files = [];
|
|
122
185
|
|
|
@@ -150,7 +213,27 @@ function loadSettings(opts = {}) {
|
|
|
150
213
|
}
|
|
151
214
|
if (envContributed) files.push("<env>");
|
|
152
215
|
|
|
153
|
-
|
|
216
|
+
const managedLoaded = loadManagedSettings({
|
|
217
|
+
env,
|
|
218
|
+
managedSettingsFile: opts.managedSettingsFile,
|
|
219
|
+
onWarn,
|
|
220
|
+
});
|
|
221
|
+
if (managedLoaded.settings) {
|
|
222
|
+
rules = applyManagedPermissionPolicy(
|
|
223
|
+
rules,
|
|
224
|
+
managedLoaded.settings,
|
|
225
|
+
sources,
|
|
226
|
+
);
|
|
227
|
+
files.push(managedLoaded.file);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
rules,
|
|
232
|
+
sources,
|
|
233
|
+
files,
|
|
234
|
+
managed: managedLoaded.settings,
|
|
235
|
+
managedFile: managedLoaded.settings ? managedLoaded.file : null,
|
|
236
|
+
};
|
|
154
237
|
}
|
|
155
238
|
|
|
156
239
|
/** Look up the source file a matched `{ kind, rule }` came from. */
|
|
@@ -236,6 +319,24 @@ function loadSettingsConfig(opts = {}) {
|
|
|
236
319
|
}
|
|
237
320
|
if (contributed) files.push(file);
|
|
238
321
|
}
|
|
322
|
+
const managed = loadManagedSettings(opts);
|
|
323
|
+
if (managed.settings) {
|
|
324
|
+
const data = managed.settings;
|
|
325
|
+
let contributed = false;
|
|
326
|
+
if (typeof data.model === "string" && data.model.trim()) {
|
|
327
|
+
model = data.model.trim();
|
|
328
|
+
contributed = true;
|
|
329
|
+
}
|
|
330
|
+
if (data.env && typeof data.env === "object" && !Array.isArray(data.env)) {
|
|
331
|
+
for (const [k, v] of Object.entries(data.env)) {
|
|
332
|
+
if (typeof v === "string") {
|
|
333
|
+
env[k] = v;
|
|
334
|
+
contributed = true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (contributed) files.push(managed.file);
|
|
339
|
+
}
|
|
239
340
|
return { model, env, files };
|
|
240
341
|
}
|
|
241
342
|
|
|
@@ -270,6 +371,14 @@ function readBooleanSetting(key, opts = {}) {
|
|
|
270
371
|
value = node; // last (closest) layer wins
|
|
271
372
|
}
|
|
272
373
|
}
|
|
374
|
+
const managed = loadManagedSettings(opts);
|
|
375
|
+
if (managed.settings) {
|
|
376
|
+
let node = managed.settings;
|
|
377
|
+
for (const p of parts) {
|
|
378
|
+
node = node && typeof node === "object" ? node[p] : undefined;
|
|
379
|
+
}
|
|
380
|
+
if (typeof node === "boolean") value = node;
|
|
381
|
+
}
|
|
273
382
|
return value;
|
|
274
383
|
}
|
|
275
384
|
|
|
@@ -279,6 +388,10 @@ module.exports = {
|
|
|
279
388
|
readSettingsFile,
|
|
280
389
|
readBooleanSetting,
|
|
281
390
|
settingsPaths,
|
|
391
|
+
managedSettingsPath,
|
|
392
|
+
loadManagedSettings,
|
|
393
|
+
applyManagedPermissionPolicy,
|
|
394
|
+
assertManagedPermissionMode,
|
|
282
395
|
parseEnvList,
|
|
283
396
|
ruleSource,
|
|
284
397
|
addRule,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background task listing utilities (ESM)
|
|
3
|
+
* Mirrors Claude Code /tasks behavior
|
|
4
|
+
* @module lib/task-list
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { listBackgroundShellTasks } from "../runtime/agent-core.js";
|
|
8
|
+
import { formatBackgroundTasks } from "../repl/tasks-status.js";
|
|
9
|
+
import { logger } from "./logger.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* List all background tasks
|
|
13
|
+
* @param {Object} options List options
|
|
14
|
+
* @returns {Promise<Object>} task list result
|
|
15
|
+
*/
|
|
16
|
+
export async function listTasks(options = {}) {
|
|
17
|
+
const tasks = listBackgroundShellTasks();
|
|
18
|
+
const active = tasks.filter((t) => t.status === "running");
|
|
19
|
+
const completed = tasks.filter((t) => t.status !== "running");
|
|
20
|
+
|
|
21
|
+
if (tasks.length === 0) {
|
|
22
|
+
logger.info("No background tasks");
|
|
23
|
+
return { count: 0, active: 0, completed: 0, tasks: [] };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!options.quiet) {
|
|
27
|
+
logger.info(formatBackgroundTasks(tasks));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
logger.info(
|
|
31
|
+
` ${active.length} active, ${completed.length} completed (total: ${tasks.length})`,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
count: tasks.length,
|
|
36
|
+
active: active.length,
|
|
37
|
+
completed: completed.length,
|
|
38
|
+
tasks,
|
|
39
|
+
formatted: formatBackgroundTasks(tasks),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get a specific task by ID
|
|
45
|
+
* @param {string} taskId
|
|
46
|
+
* @returns {Object|null}
|
|
47
|
+
*/
|
|
48
|
+
export function getTask(taskId) {
|
|
49
|
+
const tasks = listBackgroundShellTasks();
|
|
50
|
+
return tasks.find((t) => t.id === taskId) || null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default { listTasks, getTask };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared base Commander program factory.
|
|
3
|
+
*
|
|
4
|
+
* Both the eager path (src/index.js `createProgram`, used by tests, help, and
|
|
5
|
+
* the unknown-command fallback) and the lazy fast path (src/lazy-dispatch.js,
|
|
6
|
+
* used by the bin for a resolved `cc <cmd>`) build their program from this so
|
|
7
|
+
* the program name, version flag, and global options can never drift between
|
|
8
|
+
* the two code paths.
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import { VERSION } from "./constants.js";
|
|
12
|
+
|
|
13
|
+
export function createBaseProgram() {
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name("chainlesschain")
|
|
17
|
+
.description(
|
|
18
|
+
"CLI for ChainlessChain - install, configure, and manage your personal AI management system",
|
|
19
|
+
)
|
|
20
|
+
.version(VERSION, "-v, --version")
|
|
21
|
+
.option("--verbose", "Enable verbose output")
|
|
22
|
+
.option("--quiet", "Suppress non-essential output");
|
|
23
|
+
return program;
|
|
24
|
+
}
|