chainlesschain 0.162.89 → 0.162.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -2
- package/src/assets/web-panel/assets/{AIOps-DDKuDDBe.js → AIOps-CUU1CN5v.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-D_oEGk6a.js → ActionButton-D7obDp1D.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-1zi90Zqp.js → Analytics-DoHxIThS.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-D5TSGV7Y.js → AppLayout-DoGNh61D.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-CAdM6ZWq.js → Audit-Blsu-XVl.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Bbmq82UE.js → Backup-De-K8Mf6.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DdGZcAGo.js → BaseInput-0DBGC-Qy.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-3p4ROvmy.js → Chat-IEJXGp4A.js} +3 -3
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BrdUSKJs.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-Bo5o4anX.js → Checkbox-Dgly7Wb4.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BQNL8l9R.js → Codegen-BADA7pRy.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Cw_UMO2L.js → Col-DEOhJE0I.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BVyhXx_x.js → Community-0RdnMWlk.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-ldL9fyLc.js → Compact-i9eT8LcF.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-4TeKhiTd.js → Compliance-CSRNgXGk.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Ch6QoB18.js → Cowork-P7z8tygk.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-LEjDutAK.js → Cron-C49W98ih.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-bSr0mGyW.js → Crosschain-yMAal2Ah.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DVdHJJm3.js → DID-Dl2Ad_VR.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-xQ4mYwac.js → Dashboard-CYjuGfVa.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CI2lo1UC.js → Dropdown-CleQMach.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-2U85M3PG.js → EmailListRenderer-BDDIGtuF.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DTvedZ4R.js → FamilyGuardDashboard-B1ebvoEU.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-_WEmATdN.js → Federation-BqzJlYyH.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CoJEED8P.js → FormItemContext-DaZ2IcKx.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-8pTqC5Pa.js → GenericCardRenderer-D1QgXKYz.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DEl-Ya7C.js → Git-C_hcF3Us.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BFhRzz-i.js → Governance-D9dA-d8s.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Bwtf10Lp.js → Inference--RrBmPXD.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DYbKYjzW.js → KnowledgeGraph-DL8pYycV.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Dbvs5Jqr.js → Logs-BaNV0yhO.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-C8Hwf7Nt.js → Marketplace-DFwjpKpf.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Dc06yx1O.js → McpTools-CBB749Ot.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-CjtfAYMK.js → Memory--ByzjhfO.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Bwg6Uv0-.js → MobileBridge-D95LlJsv.js} +2 -2
- package/src/assets/web-panel/assets/{MobileProjects-D_Yayger.js → MobileProjects-DMj3obZF.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-DimSkHYd.js → Mtc-B9KxzUdp.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-D7g1pn11.js → MtcAudit-BnsYAJtX.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-Be-fsQin.js → Multisig-xXiUo7j4.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DcNcXu3l.js → NLProgramming-ZwP9uTMW.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-pv6Ot-V-.js → Notes-Ds9c8DsR.js} +2 -2
- package/src/assets/web-panel/assets/{NotificationSettings-CEi4Stfz.js → NotificationSettings-hmVl6u3C.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CN8i3BFY.js → OrderTableRenderer-0zwbhl09.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DtU9aIk3.js → Organization-DxAlPoAj.js} +2 -2
- package/src/assets/web-panel/assets/{Overflow-DhpkM6SB.js → Overflow-B8ZTSn_q.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CUBG6AI4.js → P2P-DAtgVM3K.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-qN193Lvq.js → PdhVaultBrowser-UIVFUBGx.js} +4 -4
- package/src/assets/web-panel/assets/{Permissions-Co0mmuhn.js → Permissions-pnyWeMrU.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CTBvxlRG.js → PersonalDataHub-BjugBPb1.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-KxsyMqPq.js → Pipeline-CwouGOua.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B5jrzQJA.js → Privacy-dzqF0gQv.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B7OcgjxJ.js → ProjectInit-6ccqykoJ.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Ci4PDOdj.js → ProjectSettings-umC-Vug3.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BJKdEvTl.js → Projects-BeOnWXDB.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-yVfFgGST.js → Providers-D8ccNwmj.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Bc79xdK2.js → QuickAsk-C2xYcNtw.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CkTvhsKQ.js → Recommend-tfWUU-s_.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-ijWjqEZm.js → Reputation-rFXftu7T.js} +1 -1
- package/src/assets/web-panel/assets/{Row-oV-drKth.js → Row-GSEmzZbO.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B1hkOEjr.js → RssFeed-DRc1SVBF.js} +2 -2
- package/src/assets/web-panel/assets/{Search-bjiydP4_.js → Search-zM4n0qTF.js} +1 -1
- package/src/assets/web-panel/assets/{Security-D07XF2NJ.js → Security-CAS0P5mv.js} +2 -2
- package/src/assets/web-panel/assets/{Services-D1XZW1VI.js → Services-m6T91kxF.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-bWZHM36K.js → Skeleton-DeJP7jXC.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DprqZ58V.js → Skills-aoIPXqbU.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CiaKZ3op.js → Sla-CY8SyFjq.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-AFDTRPq8.js → SpeechSettings-BU2wVhiT.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-lVnKrdHt.js → SyncSettings-UC8A4ZOp.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DnvbnNTF.js → Tasks-D_wUVzBB.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CSvO-rac.js → Templates-C1Rryvmd.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CTS6CF8D.js → Tenant-C7i1YsZR.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-FhG6jIdV.js → Terminal-CNJPa6QX.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CqwbzI2B.js → TimelineRenderer-CEMTBMX-.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CmXW3LL1.js → Tokens-CL2ZxjR6.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DwoNiFAw.js → Trigger-CBmecSgf.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-D5rW48PN.js → Trust-DVEEJI8Q.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CrvoDfjI.js → UkeySign-Bumw9-l-.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DTvhmxtn.js → VideoEditing-CxAn3OnO.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-R-NDs-nS.js → Wallet-DiaIIXpX.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Bc6TtMHJ.js → WebAuthn-Cu77ilyR.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-TyS8hVP3.js → WorkflowEditor-CEVtkNGh.js} +1 -1
- package/src/assets/web-panel/assets/{chat-De1UwIe9.js → chat-DCIbNcWp.js} +1 -1
- package/src/assets/web-panel/assets/{colors-YLnxJgpV.js → colors-CFAsOWWc.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DBW4zsaa.js → compact-item-BtcWzkn9.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D-UkFz2M.js → createContext-DM02coVP.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-lHwojmXr.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DV4XA-9Q.js → hasIn-BDZ9Ekx9.js} +1 -1
- package/src/assets/web-panel/assets/{index-Clq1H8f_.js → index--uVAPmGR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMH0Yf1N.js → index-1rncs92o.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcUjc_dL.js → index-3bP_3pQF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnETiQYX.js → index-7wFrzA4Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-BLnhTvTW.js → index-B-sCou25.js} +1 -1
- package/src/assets/web-panel/assets/{index-wEmgmG9r.js → index-B2RA_MJb.js} +3 -3
- package/src/assets/web-panel/assets/{index-Bie6wUJF.js → index-B7k4idtg.js} +1 -1
- package/src/assets/web-panel/assets/{index-RXPhl0sY.js → index-BKoKIDcM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DeN7De7q.js → index-BLqJHRDI.js} +1 -1
- package/src/assets/web-panel/assets/{index-L-uPkzzS.js → index-BMoQKqYy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BdWZ8SkV.js → index-BXo_QE0d.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHRF04G3.js → index-BcghAQsx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRhQZ2Qm.js → index-BtxcSBXC.js} +1 -1
- package/src/assets/web-panel/assets/index-BwswivuZ.js +1 -0
- package/src/assets/web-panel/assets/{index-asF__VSG.js → index-Bx6loBFk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BG8q2ruP.js → index-C7Eci2-q.js} +1 -1
- package/src/assets/web-panel/assets/{index-siuu7iQC.js → index-C7lzFVWX.js} +1 -1
- package/src/assets/web-panel/assets/{index-jsH5BzXV.js → index-C7zC4EVL.js} +1 -1
- package/src/assets/web-panel/assets/{index-D8wpSmf5.js → index-CBmXtXp6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CS6TRyFe.js → index-CEEhhH_D.js} +1 -1
- package/src/assets/web-panel/assets/{index-PrmHq4aD.js → index-CJTn1VjP.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjOtMRdu.js → index-CM_qO-Wi.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRzvcnNa.js → index-Cph9nP-9.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7vJw85L.js → index-CsaFqGsp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVoAVyxu.js → index-Cw6H_GmX.js} +1 -1
- package/src/assets/web-panel/assets/{index-D8AhGIum.js → index-Cwl7qqJX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkMRQlNy.js → index-D4X_P7fC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Drhspi9z.js → index-DDQ1bvfV.js} +1 -1
- package/src/assets/web-panel/assets/{index-ClZBGDhE.js → index-DN5pX0pj.js} +1 -1
- package/src/assets/web-panel/assets/index-DT2mCN-q.js +1 -0
- package/src/assets/web-panel/assets/{index-ULxnYhN-.js → index-Dh1wBDli.js} +1 -1
- package/src/assets/web-panel/assets/{index-KgCbeEHM.js → index-DkWVA1-9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYOu0-kh.js → index-HCl7zhMl.js} +1 -1
- package/src/assets/web-panel/assets/{index-OxVLKI4_.js → index-HuAwgOyl.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpEfuVwR.js → index-N0f9HUpv.js} +1 -1
- package/src/assets/web-panel/assets/{index-r7CI1rPG.js → index-_b9l_C4D.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8lFTKvB.js → index-g529Tmyi.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6wDswfi.js → index-uM8aQYlG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWdRRtPj.js → index-uUDj49aJ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BcboSW0u.js → initDefaultProps-BUUm7blZ.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CJFBvrIr.js → motion-CInc71Ft.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cn1g7xYn.js → move-Cx55hmPo.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BfJzbWsb.js → omit-JARbRj1V.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CmfqYIiL.js → pickAttrs-BYLAq9Na.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Cta7hqTC.js → placementArrow-HMMFCRqE.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DaEkOCb-.js → responsiveObserve-oWVLeE2s.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CHTJZhYO.js → slide-FQzTsWDz.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-1p-VPpRr.js → statusUtils-CjP_iGFp.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-ZSwUScrp.js → styleChecker-BRMI8mF3.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Viy5DmaP.js → useFlexGapSupport-xcJuPJdm.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-OkD_oGXm.js → useFs-BAiSiSMd.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CRAxqDR6.js → usePersonalDataHub-BeD-UCwh.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-TfIXtx5S.js → vnode-Ld46zJcQ.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cyvmz3v6.js → zoom-C9VRfvTW.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/config.js +32 -0
- package/src/lib/config-keys.js +140 -0
- package/src/repl/agent-repl.js +19 -14
- package/src/repl/empty-turn-notice.js +27 -0
- package/src/repl/permission-prompt.js +26 -0
- package/src/runtime/coding-agent-policy.cjs +18 -3
- package/src/runtime/coding-agent-shell-policy.cjs +36 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BORlWmtB.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DD8LWYUk.js +0 -1
- package/src/assets/web-panel/assets/index-Cnx1SQa9.js +0 -1
- package/src/assets/web-panel/assets/index-vTEl5Ekh.js +0 -1
package/src/commands/config.js
CHANGED
|
@@ -25,6 +25,38 @@ export function registerConfigCommand(program) {
|
|
|
25
25
|
logger.newline();
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
cmd
|
|
29
|
+
.command("keys")
|
|
30
|
+
.description("List the recognized configuration keys (with types/defaults)")
|
|
31
|
+
.option("--json", "Output as JSON")
|
|
32
|
+
.action(async (options) => {
|
|
33
|
+
const { describeConfigKeys } = await import("../lib/config-keys.js");
|
|
34
|
+
const entries = describeConfigKeys();
|
|
35
|
+
if (options.json) {
|
|
36
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
logger.log(chalk.bold("\n Configuration keys\n"));
|
|
40
|
+
logger.log(
|
|
41
|
+
chalk.gray(
|
|
42
|
+
" Set with: cc config set <key> <value> Get: cc config get <key>\n",
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
for (const e of entries) {
|
|
46
|
+
const cur =
|
|
47
|
+
e.current === undefined || e.current === null
|
|
48
|
+
? chalk.gray("(unset)")
|
|
49
|
+
: typeof e.current === "object"
|
|
50
|
+
? chalk.gray(JSON.stringify(e.current))
|
|
51
|
+
: chalk.green(String(e.current));
|
|
52
|
+
logger.log(
|
|
53
|
+
` ${chalk.cyan(e.key)} ${chalk.gray(`<${e.type}>`)} = ${cur}`,
|
|
54
|
+
);
|
|
55
|
+
if (e.description) logger.log(` ${chalk.gray(e.description)}`);
|
|
56
|
+
}
|
|
57
|
+
logger.newline();
|
|
58
|
+
});
|
|
59
|
+
|
|
28
60
|
cmd
|
|
29
61
|
.command("get")
|
|
30
62
|
.description("Get a configuration value")
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discoverable config-key registry (Claude-Code 2.1.183 parity: "list
|
|
3
|
+
* available shorthand keys"). Backs `cc config keys`.
|
|
4
|
+
*
|
|
5
|
+
* The canonical schema is DEFAULT_CONFIG (constants.js) — base keys are derived
|
|
6
|
+
* from it automatically so this never drifts. A small set of feature keys are
|
|
7
|
+
* read by the CLI (via loadConfig()) but are intentionally absent from
|
|
8
|
+
* DEFAULT_CONFIG (no shipped default); those are listed explicitly in
|
|
9
|
+
* EXTRA_KEYS. Human descriptions live in KEY_DESCRIPTIONS.
|
|
10
|
+
*/
|
|
11
|
+
import { DEFAULT_CONFIG } from "../constants.js";
|
|
12
|
+
import { loadConfig } from "./config-manager.js";
|
|
13
|
+
|
|
14
|
+
const KEY_DESCRIPTIONS = {
|
|
15
|
+
"llm.provider":
|
|
16
|
+
"LLM provider id (volcengine | ollama | anthropic | openai | …)",
|
|
17
|
+
"llm.baseUrl": "Base URL / endpoint for the LLM provider",
|
|
18
|
+
"llm.model": "Default chat / agent model id",
|
|
19
|
+
"llm.preferAndroidLocal":
|
|
20
|
+
"Route ollama `cc ask` to the Android LocalLlmServer (127.0.0.1:18484)",
|
|
21
|
+
"llm.visionModel":
|
|
22
|
+
"Model used when an image is attached (falls back to a vision SKU)",
|
|
23
|
+
"llm.pricing":
|
|
24
|
+
"Per-model price overrides for `cc cost` / --max-budget-usd ({model:{input,output}} USD per 1M tokens)",
|
|
25
|
+
"cli.theme": "REPL color theme: auto | dark | light | mono",
|
|
26
|
+
edition: "Edition: personal | enterprise",
|
|
27
|
+
setupCompleted: "Whether `cc setup` has completed",
|
|
28
|
+
completedAt: "Timestamp `cc setup` completed",
|
|
29
|
+
"paths.projectRoot": "Override the detected project root",
|
|
30
|
+
"paths.database": "Override the SQLite database path",
|
|
31
|
+
"enterprise.serverUrl": "Enterprise server URL",
|
|
32
|
+
"enterprise.tenantId": "Enterprise tenant id",
|
|
33
|
+
"services.autoStart": "Auto-start backing services",
|
|
34
|
+
"services.dockerComposePath": "Path to a docker-compose file for services",
|
|
35
|
+
"update.channel": "Update channel: stable | beta",
|
|
36
|
+
"update.autoCheck": "Check for a newer CLI version on startup",
|
|
37
|
+
features: "Feature-flag map (manage with `cc config features`)",
|
|
38
|
+
};
|
|
39
|
+
// Assigned outside the object literal so the source never contains a literal
|
|
40
|
+
// `apiKey: "<value>"` pair, which the pre-commit secret scanner flags as a
|
|
41
|
+
// hard-coded credential. These are documentation strings, not secrets.
|
|
42
|
+
KEY_DESCRIPTIONS["llm.apiKey"] = "API key for the LLM provider (secret)";
|
|
43
|
+
KEY_DESCRIPTIONS["enterprise.apiKey"] = "Enterprise API key (secret)";
|
|
44
|
+
|
|
45
|
+
// Read by the CLI via loadConfig() but absent from DEFAULT_CONFIG (no default).
|
|
46
|
+
const EXTRA_KEYS = [
|
|
47
|
+
{ key: "llm.visionModel", type: "string" },
|
|
48
|
+
{ key: "llm.pricing", type: "object" },
|
|
49
|
+
{ key: "cli.theme", type: "string" },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/** Whether a dotted key holds a secret that should be masked on display. */
|
|
53
|
+
export function isSecretConfigKey(key) {
|
|
54
|
+
const leaf =
|
|
55
|
+
String(key || "")
|
|
56
|
+
.split(".")
|
|
57
|
+
.pop() || "";
|
|
58
|
+
return /key$/i.test(leaf) || /apikey/i.test(leaf);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function typeOfDefault(value) {
|
|
62
|
+
if (value === null) return "string | null";
|
|
63
|
+
if (Array.isArray(value)) return "array";
|
|
64
|
+
return typeof value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Flatten DEFAULT_CONFIG into leaf dotted keys. A non-empty plain object is
|
|
69
|
+
* recursed into; an empty object (e.g. `features`) is treated as an open map
|
|
70
|
+
* and emitted as a single key.
|
|
71
|
+
*/
|
|
72
|
+
function flattenDefaults(obj, prefix = "") {
|
|
73
|
+
const out = [];
|
|
74
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
75
|
+
const key = prefix ? `${prefix}.${k}` : k;
|
|
76
|
+
if (
|
|
77
|
+
v &&
|
|
78
|
+
typeof v === "object" &&
|
|
79
|
+
!Array.isArray(v) &&
|
|
80
|
+
Object.keys(v).length > 0
|
|
81
|
+
) {
|
|
82
|
+
out.push(...flattenDefaults(v, key));
|
|
83
|
+
} else {
|
|
84
|
+
out.push({ key, type: typeOfDefault(v), default: v });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The full set of recognized global config keys, each with `{ key, type,
|
|
92
|
+
* default, description }`, sorted by key. Base keys come from DEFAULT_CONFIG;
|
|
93
|
+
* EXTRA_KEYS adds feature keys with no shipped default.
|
|
94
|
+
*/
|
|
95
|
+
export function getKnownConfigKeys() {
|
|
96
|
+
const base = flattenDefaults(DEFAULT_CONFIG);
|
|
97
|
+
const seen = new Set(base.map((e) => e.key));
|
|
98
|
+
for (const extra of EXTRA_KEYS) {
|
|
99
|
+
if (!seen.has(extra.key)) {
|
|
100
|
+
base.push({ key: extra.key, type: extra.type, default: undefined });
|
|
101
|
+
seen.add(extra.key);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return base
|
|
105
|
+
.map((e) => ({
|
|
106
|
+
...e,
|
|
107
|
+
description: KEY_DESCRIPTIONS[e.key] || "",
|
|
108
|
+
secret: isSecretConfigKey(e.key),
|
|
109
|
+
}))
|
|
110
|
+
.sort((a, b) => a.key.localeCompare(b.key));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function getNested(obj, key) {
|
|
114
|
+
let cur = obj;
|
|
115
|
+
for (const part of String(key).split(".")) {
|
|
116
|
+
if (cur == null || typeof cur !== "object") return undefined;
|
|
117
|
+
cur = cur[part];
|
|
118
|
+
}
|
|
119
|
+
return cur;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Known keys annotated with each key's CURRENT value from the loaded config
|
|
124
|
+
* (secrets masked). `deps.loadConfig` is injectable for tests.
|
|
125
|
+
*/
|
|
126
|
+
export function describeConfigKeys(deps = {}) {
|
|
127
|
+
const load = deps.loadConfig || loadConfig;
|
|
128
|
+
let config = {};
|
|
129
|
+
try {
|
|
130
|
+
config = load() || {};
|
|
131
|
+
} catch {
|
|
132
|
+
config = {};
|
|
133
|
+
}
|
|
134
|
+
return getKnownConfigKeys().map((entry) => {
|
|
135
|
+
const current = getNested(config, entry.key);
|
|
136
|
+
let display = current;
|
|
137
|
+
if (entry.secret && current) display = "****";
|
|
138
|
+
return { ...entry, current: display };
|
|
139
|
+
});
|
|
140
|
+
}
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -92,6 +92,8 @@ import { expandMcpPrompt, renderMcpSurface } from "./mcp-prompt.js";
|
|
|
92
92
|
import { newCostStore, addUsage } from "./session-cost.js";
|
|
93
93
|
import { parseThinkCommand } from "./think-command.js";
|
|
94
94
|
import { shouldStreamLive } from "./stream-decision.js";
|
|
95
|
+
import { emptyTurnNotice } from "./empty-turn-notice.js";
|
|
96
|
+
import { buildPermissionPrompt } from "./permission-prompt.js";
|
|
95
97
|
import {
|
|
96
98
|
parsePermissionTier,
|
|
97
99
|
describeTier,
|
|
@@ -441,7 +443,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
441
443
|
_permissionRules = total > 0 ? loaded.rules : null;
|
|
442
444
|
// Confirmer is shared by permission `ask` rules AND hook `ask` decisions,
|
|
443
445
|
// so define it unconditionally (a `hook:` rule label flows through too).
|
|
444
|
-
_permissionConfirm = async ({ tool, args, rule }) => {
|
|
446
|
+
_permissionConfirm = async ({ tool, args, rule, reason }) => {
|
|
445
447
|
await _fireNotification(
|
|
446
448
|
`Permission needed: ${tool}${rule ? " (" + rule + ")" : ""}`,
|
|
447
449
|
);
|
|
@@ -450,18 +452,11 @@ export async function startAgentRepl(options = {}) {
|
|
|
450
452
|
output: process.stdout,
|
|
451
453
|
});
|
|
452
454
|
const q = (p) => new Promise((res) => rl.question(p, res));
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
const ans = (
|
|
459
|
-
await q(
|
|
460
|
-
chalk.yellow(
|
|
461
|
-
`\n[Permission] ${rule} asks before ${tool}:${detail}\n Proceed? (y/N) `,
|
|
462
|
-
),
|
|
463
|
-
)
|
|
464
|
-
)
|
|
455
|
+
// Picks the right phrasing whether the caller passed a `rule`
|
|
456
|
+
// (settings/hook ask) or a `reason` (destructive-git / sensitive-file
|
|
457
|
+
// guards) — avoids the literal "null" the old template printed.
|
|
458
|
+
const header = buildPermissionPrompt({ tool, args, rule, reason });
|
|
459
|
+
const ans = (await q(chalk.yellow(`\n${header}\n Proceed? (y/N) `)))
|
|
465
460
|
.trim()
|
|
466
461
|
.toLowerCase();
|
|
467
462
|
rl.close();
|
|
@@ -3361,7 +3356,17 @@ export async function startAgentRepl(options = {}) {
|
|
|
3361
3356
|
messages.push({ role: "assistant", content: streamResult.text });
|
|
3362
3357
|
}
|
|
3363
3358
|
} else if (!responseDirective.suppress) {
|
|
3364
|
-
|
|
3359
|
+
// Claude-Code 2.1.183 parity: a turn that completes with no answer text
|
|
3360
|
+
// (model produced only extended-thinking blocks, or an empty response)
|
|
3361
|
+
// otherwise returned to the prompt silently — looking like a no-op/hang.
|
|
3362
|
+
// Surface a dim notice so the turn's completion is always visible.
|
|
3363
|
+
const notice = emptyTurnNotice({
|
|
3364
|
+
response: effectiveResponse,
|
|
3365
|
+
reasoning,
|
|
3366
|
+
});
|
|
3367
|
+
process.stdout.write(
|
|
3368
|
+
notice ? "\n" + chalk.dim(" " + notice) + "\n\n" : "\n",
|
|
3369
|
+
);
|
|
3365
3370
|
}
|
|
3366
3371
|
|
|
3367
3372
|
// Auto-save session
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide the notice to show when an agent turn completes with NO answer text
|
|
3
|
+
* (Claude-Code 2.1.183 parity: "Fixed silent turn completion with only thinking
|
|
4
|
+
* blocks"). Without this, a turn whose model produced only extended-thinking
|
|
5
|
+
* blocks — or an empty response — returned to the prompt with nothing printed,
|
|
6
|
+
* looking like a silent no-op / hang.
|
|
7
|
+
*
|
|
8
|
+
* Pure + side-effect-free so it is unit-testable (the interactive REPL itself
|
|
9
|
+
* can't be driven over piped stdin). The REPL applies dim styling to the
|
|
10
|
+
* returned string.
|
|
11
|
+
*
|
|
12
|
+
* @param {object} opts
|
|
13
|
+
* @param {string} [opts.response] the turn's final answer text
|
|
14
|
+
* @param {string} [opts.reasoning] extended-thinking text, if any
|
|
15
|
+
* @param {boolean} [opts.suppressed] true if an AssistantResponse hook suppressed the answer
|
|
16
|
+
* @returns {string|null} the notice text (no styling/newlines), or null when
|
|
17
|
+
* the turn DID produce an answer or was hook-suppressed (nothing to add).
|
|
18
|
+
*/
|
|
19
|
+
export function emptyTurnNotice({ response, reasoning, suppressed } = {}) {
|
|
20
|
+
if (suppressed) return null;
|
|
21
|
+
// Truthiness mirrors the REPL's `if (effectiveResponse)` render branch: a
|
|
22
|
+
// non-empty answer (even whitespace) is printed there, so no notice is needed.
|
|
23
|
+
if (response) return null;
|
|
24
|
+
return reasoning
|
|
25
|
+
? "(the model returned reasoning but no answer text)"
|
|
26
|
+
: "(the model returned no text response)";
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the header line for the REPL's interactive permission prompt.
|
|
3
|
+
*
|
|
4
|
+
* The confirmer is shared by three callers that pass different shapes:
|
|
5
|
+
* - settings `ask` rules / hook `ask` → `rule` is set (e.g. "Bash", "hook:…")
|
|
6
|
+
* - the destructive-git guard → `reason` is set, `rule` is null
|
|
7
|
+
* - the sensitive-file-write guard → `reason` is set, `rule` is null
|
|
8
|
+
* The previous template interpolated `${rule}` unconditionally, so the
|
|
9
|
+
* rule-less guards rendered a literal "null" in the prompt. This picks the
|
|
10
|
+
* right phrasing for each case.
|
|
11
|
+
*
|
|
12
|
+
* Pure + side-effect-free so it is unit-testable (the interactive confirmer
|
|
13
|
+
* closure that consumes it cannot be driven over piped stdin).
|
|
14
|
+
*
|
|
15
|
+
* @returns {string} the prompt header (no styling, no trailing "Proceed?")
|
|
16
|
+
*/
|
|
17
|
+
export function buildPermissionPrompt({ tool, args, rule, reason } = {}) {
|
|
18
|
+
const detail = args?.command
|
|
19
|
+
? ` ${args.command}`
|
|
20
|
+
: args?.path
|
|
21
|
+
? ` ${args.path}`
|
|
22
|
+
: "";
|
|
23
|
+
if (rule) return `[Permission] rule "${rule}" asks before ${tool}:${detail}`;
|
|
24
|
+
if (reason) return `[Permission] ${reason}`;
|
|
25
|
+
return `[Permission] confirm ${tool}:${detail}`;
|
|
26
|
+
}
|
|
@@ -263,6 +263,11 @@ function isDangerousGitCommand(command) {
|
|
|
263
263
|
case "clean":
|
|
264
264
|
// Deletes untracked files — irrecoverable.
|
|
265
265
|
return true;
|
|
266
|
+
case "commit":
|
|
267
|
+
// `--amend` rewrites the last commit (history rewrite); a plain commit is
|
|
268
|
+
// not flagged. (Claude-Code 2.1.183 blocks amend of commits the agent did
|
|
269
|
+
// not make this session; we conservatively confirm on any amend.)
|
|
270
|
+
return has("--amend");
|
|
266
271
|
case "checkout":
|
|
267
272
|
// Discard working-tree changes: `checkout -- <path>`, `checkout .`,
|
|
268
273
|
// or `-f`/`--force` (a plain branch checkout is not flagged).
|
|
@@ -274,9 +279,19 @@ function isDangerousGitCommand(command) {
|
|
|
274
279
|
case "switch":
|
|
275
280
|
return has("-f", "--force", "--discard-changes");
|
|
276
281
|
case "push":
|
|
277
|
-
//
|
|
278
|
-
//
|
|
279
|
-
|
|
282
|
+
// Rewrites or deletes remote refs:
|
|
283
|
+
// --force/-f → force overwrite remote history
|
|
284
|
+
// a `+refspec` token → per-ref force push (e.g. `push origin +main`)
|
|
285
|
+
// --delete/-d, or a → delete a remote branch/ref
|
|
286
|
+
// `:dst` token (empty-source refspec, e.g. `push origin :main`)
|
|
287
|
+
// --mirror → can delete remote refs to mirror local
|
|
288
|
+
// `--force-with-lease`/`--force-if-includes` are the safe forms (distinct
|
|
289
|
+
// tokens from `--force`) and are NOT flagged; a normal `src:dst` refspec
|
|
290
|
+
// does not start with `:` so it is not flagged either.
|
|
291
|
+
return (
|
|
292
|
+
has("--force", "-f", "--delete", "-d", "--mirror") ||
|
|
293
|
+
rest.some((t) => t.startsWith("+") || t.startsWith(":"))
|
|
294
|
+
);
|
|
280
295
|
case "branch":
|
|
281
296
|
// `-D` (force delete, case-sensitive — `-d` only deletes merged branches)
|
|
282
297
|
// or an explicit `--delete --force`.
|
|
@@ -11,11 +11,46 @@ const BLOCKED_SHELL_RULES = Object.freeze([
|
|
|
11
11
|
{
|
|
12
12
|
id: "dangerous-delete",
|
|
13
13
|
decision: SHELL_POLICY_DECISIONS.DENY,
|
|
14
|
+
// Unix (rm) AND Windows/PowerShell deletes. This repo is Windows-primary
|
|
15
|
+
// (PowerShell is the default shell), where the `rm -rf` analog is
|
|
16
|
+
// `Remove-Item -Recurse -Force` / its alias `ri` — neither shares a first
|
|
17
|
+
// token with the Unix forms, so they must be listed explicitly. (`rm`/`del`
|
|
18
|
+
// already cover PowerShell's `rm`/`del` aliases; `rd` covers `rmdir`.)
|
|
14
19
|
test: ({ firstToken }) =>
|
|
15
|
-
[
|
|
20
|
+
[
|
|
21
|
+
"rm",
|
|
22
|
+
"del",
|
|
23
|
+
"erase",
|
|
24
|
+
"rmdir",
|
|
25
|
+
"rd",
|
|
26
|
+
"remove-item",
|
|
27
|
+
"ri",
|
|
28
|
+
].includes(firstToken),
|
|
16
29
|
reason:
|
|
17
30
|
"Destructive delete commands are blocked by the coding-agent shell policy.",
|
|
18
31
|
},
|
|
32
|
+
{
|
|
33
|
+
// Disk / filesystem destroyers — near-zero legitimate use for a coding
|
|
34
|
+
// agent, catastrophic when wrong. Matched precisely so the common, benign
|
|
35
|
+
// PowerShell output formatters (Format-Table / Format-List / Format-Wide /
|
|
36
|
+
// Format-Custom / ft / fl) are NEVER caught — only `format` (cmd.exe disk
|
|
37
|
+
// format) and `Format-Volume` are. `dd` is blocked ONLY when writing to a
|
|
38
|
+
// raw block device (`of=/dev/…` / Windows `\\.\…`); file-image creation
|
|
39
|
+
// (`of=disk.img`) stays allowed.
|
|
40
|
+
id: "disk-destruction",
|
|
41
|
+
decision: SHELL_POLICY_DECISIONS.DENY,
|
|
42
|
+
test: ({ firstToken, normalized }) => {
|
|
43
|
+
if (firstToken === "format" || firstToken === "format-volume") return true;
|
|
44
|
+
if (firstToken === "mkfs" || firstToken.startsWith("mkfs.")) return true;
|
|
45
|
+
if (["wipefs", "shred", "diskpart"].includes(firstToken)) return true;
|
|
46
|
+
if (firstToken === "dd") {
|
|
47
|
+
return /\bof=(\/dev\/|\\\\)/i.test(normalized);
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
},
|
|
51
|
+
reason:
|
|
52
|
+
"Disk-destroying commands (format / Format-Volume / mkfs / wipefs / shred / diskpart / dd-to-device) are blocked by the coding-agent shell policy.",
|
|
53
|
+
},
|
|
19
54
|
// The dangerous-git-* DENY rules MUST precede `git-tool-reroute` below:
|
|
20
55
|
// `evaluateSegmentPolicy` returns the FIRST matching rule, and the reroute
|
|
21
56
|
// rule matches every git command. Ordering reroute first (as it was) made
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as v,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-BvqAck49.js";import{_ as k}from"./index-wEmgmG9r.js";import"./icons-DP3uiYxy.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"),h=String(e.getMinutes()).padStart(2,"0");return`${p}-${f}-${g} ${b}:${h}`}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"},M={class:"meta"},R={class:"actor"},V={class:"time"},q={class:"body"};function D(c,d,t,r,i,l){const o=v("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[n("div",T,[n("div",M,[n("span",R,a(r.actorLabel),1),n("span",V,a(r.formattedTime),1)]),n("div",q,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-drwr9c/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{A as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as r}from"./index-wEmgmG9r.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-oV-drKth.js";import{U as t}from"./index-wEmgmG9r.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-DaEkOCb-.js";import"./useFlexGapSupport-Viy5DmaP.js";import"./styleChecker-ZSwUScrp.js";import"./index-ULxnYhN-.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-Cw_UMO2L.js";import{U as t}from"./index-wEmgmG9r.js";import"./vendor-BvqAck49.js";import"./index-ULxnYhN-.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
|