@wrongstack/cli 1.0.24 → 1.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/data/providers.json +44 -0
  2. package/dist/{acp-AJWSKWE5.js → acp-M4565YUW.js} +33 -20
  3. package/dist/ascii-mode-SG4PRNLP.js +7 -0
  4. package/dist/{auth-GRBZ7Y3D.js → auth-TE55JF4Z.js} +14 -14
  5. package/dist/{bench-N5K7Z5O3.js → bench-GTLPM22B.js} +2 -2
  6. package/dist/boot/append-system-prompt.d.ts +10 -0
  7. package/dist/boot/ascii-mode.d.ts +12 -0
  8. package/dist/boot/container-wiring.d.ts +4 -2
  9. package/dist/boot/dispatch-singleshot.d.ts +12 -1
  10. package/dist/boot/dispatch-webui.d.ts +2 -0
  11. package/dist/boot/goal-tui-default.d.ts +10 -0
  12. package/dist/boot/mcp-config-flag.d.ts +22 -0
  13. package/dist/boot/piped-stdin.d.ts +40 -0
  14. package/dist/boot/restricted-mode.d.ts +15 -0
  15. package/dist/boot/safe-mode.d.ts +30 -0
  16. package/dist/boot/single-shot-budget.d.ts +30 -0
  17. package/dist/boot/stream-json.d.ts +36 -0
  18. package/dist/boot/structured-output.d.ts +16 -0
  19. package/dist/boot/system-prompt-builder.d.ts +2 -0
  20. package/dist/boot/tool-restriction-flags.d.ts +36 -0
  21. package/dist/boot/worktree-sessions.d.ts +21 -0
  22. package/dist/boot-provider-selection.d.ts +67 -0
  23. package/dist/boot.d.ts +1 -38
  24. package/dist/{chunk-LFMVHT3R.js → chunk-2ERX3RPN.js} +11 -13
  25. package/dist/chunk-4TVYGG6G.js +62 -0
  26. package/dist/chunk-5JYDKG5B.js +154 -0
  27. package/dist/{chunk-3VXYY5JC.js → chunk-5UZBUV2H.js} +3 -19
  28. package/dist/chunk-CZTXF6HY.js +140 -0
  29. package/dist/{chunk-DRM7PSW7.js → chunk-ENRYW73H.js} +527 -381
  30. package/dist/{chunk-SKPDE62W.js → chunk-EPR42SWM.js} +36 -6
  31. package/dist/{chunk-YBUCXXYZ.js → chunk-F5DCFAKI.js} +1 -1
  32. package/dist/chunk-HDMFKTT3.js +157 -0
  33. package/dist/{chunk-PGKJ2OQP.js → chunk-HFZH2XJN.js} +5 -5
  34. package/dist/chunk-HLSHFXTO.js +97 -0
  35. package/dist/{chunk-QFPQXKCG.js → chunk-KOEO4CJG.js} +21 -6
  36. package/dist/chunk-LBPLTTZ6.js +105 -0
  37. package/dist/{chunk-3OCUS3VN.js → chunk-LDCGZJTC.js} +4 -4
  38. package/dist/chunk-LKPEBZBE.js +143 -0
  39. package/dist/chunk-N57IU5FG.js +58 -0
  40. package/dist/{chunk-2EBVTYJR.js → chunk-NRXWOMK7.js} +17 -3
  41. package/dist/chunk-PZQBGUVZ.js +18 -0
  42. package/dist/{chunk-MHEBWVXL.js → chunk-Q4INH2DG.js} +46 -2
  43. package/dist/{chunk-5SEYGOCH.js → chunk-RDGGWMTI.js} +2 -2
  44. package/dist/{chunk-BLD5DSVA.js → chunk-RGFWGUAB.js} +27 -15
  45. package/dist/{chunk-ZZRSG7VK.js → chunk-RZ4ZDRYA.js} +3 -3
  46. package/dist/{chunk-S4FFHDJG.js → chunk-SDJCLEK6.js} +6 -2
  47. package/dist/{chunk-U46QR4WR.js → chunk-TI7KLHYX.js} +132 -3
  48. package/dist/chunk-X756ZS72.js +329 -0
  49. package/dist/{chunk-JF2MULWF.js → chunk-YHYINL47.js} +47 -15
  50. package/dist/{cli-context-34Q5IJRA.js → cli-context-C7RBSWHF.js} +434 -327
  51. package/dist/{cli-main-AELJDBGU.js → cli-main-TQTH73ZK.js} +2948 -2315
  52. package/dist/cli-update-notice.d.ts +2 -1
  53. package/dist/config-doctor.d.ts +1 -1
  54. package/dist/{diag-doctor-WIFJH3XH.js → diag-doctor-BIZAFIAT.js} +2 -2
  55. package/dist/{execution-PYC5FCS4.js → execution-3STBD2U7.js} +2167 -1831
  56. package/dist/execution-chimera-review.d.ts +18 -1
  57. package/dist/fleet/host-types.d.ts +3 -1
  58. package/dist/goal-commands.d.ts +47 -0
  59. package/dist/goal-host.d.ts +1 -14
  60. package/dist/{hq-JTUTFI4L.js → hq-44F4OQH2.js} +9 -8
  61. package/dist/hq-fleet-control.d.ts +36 -0
  62. package/dist/hq-live-status.d.ts +22 -0
  63. package/dist/hq-publisher.d.ts +18 -0
  64. package/dist/hq-server/routes/command-handlers.d.ts +12 -1
  65. package/dist/hq-server/routes/data-handlers.d.ts +1 -1
  66. package/dist/hq-server/socket-credentials.d.ts +63 -0
  67. package/dist/hq-server/upgrade-handler.d.ts +2 -0
  68. package/dist/hq-server/ws.d.ts +24 -0
  69. package/dist/{hq-server-PC7GZMPT.js → hq-server-UIB24LU6.js} +2 -2
  70. package/dist/{hq-service-NW56MUP2.js → hq-service-BMMJAHRT.js} +4 -4
  71. package/dist/import-claude-code-AYG24RG2.js +268 -0
  72. package/dist/index.js +12 -8
  73. package/dist/live-settings-input.d.ts +1 -0
  74. package/dist/{mailbox-serve-WDOCH6KR.js → mailbox-serve-GNGXEQ2R.js} +3 -3
  75. package/dist/{modeldiag-36OGAL5C.js → modeldiag-W7XAE625.js} +9 -9
  76. package/dist/{per-subcommand-help-XE77MTGJ.js → per-subcommand-help-QDAQASPZ.js} +2 -2
  77. package/dist/permission-prompt.d.ts +14 -0
  78. package/dist/permission-rules-view.d.ts +18 -0
  79. package/dist/{permissions-CFDLXETM.js → permissions-PL27UHYD.js} +67 -45
  80. package/dist/{plugin-usage-S5LVGMBW.js → plugin-usage-CIGOOTX3.js} +2 -2
  81. package/dist/{plugins-RHBIVLI7.js → plugins-HQTXUD6A.js} +4 -2
  82. package/dist/preflight.d.ts +1 -1
  83. package/dist/{projects-LMNAGGEU.js → projects-T4CZCA25.js} +3 -6
  84. package/dist/provider-helpers.d.ts +7 -11
  85. package/dist/{providers-models-2CFG46RD.js → providers-models-5Z2PJTEW.js} +5 -5
  86. package/dist/release-asset-download.d.ts +10 -0
  87. package/dist/release-attestation.d.ts +28 -0
  88. package/dist/remote/remote-session.d.ts +64 -0
  89. package/dist/remote/remote-target.d.ts +69 -0
  90. package/dist/remote-GB5VXCCT.js +576 -0
  91. package/dist/{replay-Z3FTJEMM.js → replay-DEI566CW.js} +2 -2
  92. package/dist/services/commit-message.d.ts +2 -1
  93. package/dist/session-move-P2EC2COA.js +44 -0
  94. package/dist/session-move.d.ts +20 -0
  95. package/dist/session-stats.d.ts +10 -0
  96. package/dist/{sessions-config-IQUH2GXT.js → sessions-config-XHLXJ5C3.js} +109 -10
  97. package/dist/short-circuit-flags-5TNTJPQR.js +10 -0
  98. package/dist/slash-commands/command-context.d.ts +15 -5
  99. package/dist/slash-commands/goal-refiner.d.ts +4 -49
  100. package/dist/slash-commands/mcp.d.ts +2 -1
  101. package/dist/slash-commands/permissions.d.ts +4 -0
  102. package/dist/slash-commands/settings-context-mutations.d.ts +5 -0
  103. package/dist/slash-commands/settings-limits-mutations.d.ts +12 -0
  104. package/dist/slash-commands/theme.d.ts +15 -1
  105. package/dist/standalone-auto-update-TOTRGCSA.js +249 -0
  106. package/dist/standalone-auto-update.d.ts +65 -0
  107. package/dist/standalone-update-LZO3MNLH.js +24 -0
  108. package/dist/standalone-update.d.ts +37 -1
  109. package/dist/subcommands/handlers/import-claude-code.d.ts +52 -0
  110. package/dist/subcommands/handlers/permissions.d.ts +9 -3
  111. package/dist/subcommands/handlers/remote.d.ts +6 -0
  112. package/dist/subcommands/handlers/sessions-fleet.d.ts +0 -12
  113. package/dist/subcommands/handlers/version-help.d.ts +5 -0
  114. package/dist/{subcommands-ZTSIN7LG.js → subcommands-BHQYLDSD.js} +2 -2
  115. package/dist/tui-resume-callback.d.ts +18 -0
  116. package/dist/{typesafe-HVEVPA6R.js → typesafe-U7YB2RRV.js} +5 -5
  117. package/dist/{typesafe-topic-replay-4W73BOLV.js → typesafe-topic-replay-ZILIU3WS.js} +18 -2
  118. package/dist/{update-7XIOEXTD.js → update-TDZX4IL2.js} +4 -4
  119. package/dist/{update-check-2POMBHFB.js → update-check-J5ZVKS73.js} +3 -3
  120. package/dist/version-JB2UAV2A.js +11 -0
  121. package/dist/version-help-XJJQ7YSH.js +10 -0
  122. package/dist/webui-server/route-contexts.d.ts +1 -1
  123. package/dist/webui-server/session-start-payload.d.ts +5 -1
  124. package/dist/{webui-server-L2SICPTB.js → webui-server-GCXIO3JY.js} +515 -365
  125. package/dist/webui-server-lifecycle.d.ts +57 -0
  126. package/dist/webui-server-options.d.ts +10 -0
  127. package/dist/webui-server.d.ts +0 -14
  128. package/dist/wiring/brain-and-orchestration.d.ts +3 -1
  129. package/dist/wiring/cli-prompt-and-tools-setup.d.ts +9 -0
  130. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  131. package/dist/wiring/command-host-state.d.ts +2 -0
  132. package/dist/wiring/hq-telemetry.d.ts +12 -0
  133. package/dist/wiring/lifecycle-plugins.d.ts +4 -2
  134. package/dist/wiring/metrics.d.ts +9 -1
  135. package/dist/wiring/pipeline.d.ts +2 -7
  136. package/dist/wiring/plugins.d.ts +3 -0
  137. package/dist/wiring/provider-status.d.ts +1 -0
  138. package/dist/wiring/provider-utility-tools.d.ts +3 -1
  139. package/package.json +29 -28
  140. package/dist/chunk-2BKFWIER.js +0 -98
  141. package/dist/chunk-424ORSE7.js +0 -56
  142. package/dist/chunk-OWNC7LMD.js +0 -78
  143. package/dist/chunk-QBBF7GIK.js +0 -65
  144. package/dist/short-circuit-flags-SDT53OML.js +0 -10
  145. package/dist/standalone-update-MW47J3AK.js +0 -164
  146. package/dist/version-help-WZ623NWM.js +0 -10
@@ -0,0 +1,268 @@
1
+ import {
2
+ normalizeMcpServerEntry
3
+ } from "./chunk-HLSHFXTO.js";
4
+ import {
5
+ activeProfileConfigPath
6
+ } from "./chunk-YMXXOOFN.js";
7
+ import {
8
+ restoreFlags
9
+ } from "./chunk-CSAPOCBP.js";
10
+
11
+ // src/subcommands/handlers/import-claude-code.ts
12
+ import * as fs from "node:fs/promises";
13
+ import * as os from "node:os";
14
+ import * as path from "node:path";
15
+ import { readJsonObjectFile, setJsonPath, updateJsonObjectFile } from "@wrongstack/core/utils";
16
+ import { mcpEnvPlaceholders } from "@wrongstack/mcp";
17
+ function isRecord(value) {
18
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19
+ }
20
+ var REPOSITORY_STRIPPED_MCP_FIELDS = [
21
+ "permission",
22
+ "bearerTokenEnv",
23
+ "passthroughEnv",
24
+ "allowPrivateNetworks"
25
+ ];
26
+ function envReads(config) {
27
+ const reads = new Set(mcpEnvPlaceholders(config));
28
+ if (config.bearerTokenEnv) reads.add(config.bearerTokenEnv);
29
+ for (const name of config.passthroughEnv ?? []) reads.add(name);
30
+ return [...reads];
31
+ }
32
+ function describeTarget(config) {
33
+ if (typeof config.command === "string") {
34
+ return `runs: ${[config.command, ...config.args ?? []].join(" ")}`;
35
+ }
36
+ if (typeof config.url === "string") return `connects to: ${config.url}`;
37
+ return void 0;
38
+ }
39
+ function samePath(a, b) {
40
+ const norm = (p) => {
41
+ const resolved = path.resolve(p).replace(/[\\/]+$/, "");
42
+ return process.platform === "win32" ? resolved.toLowerCase() : resolved;
43
+ };
44
+ return norm(a) === norm(b);
45
+ }
46
+ function projectEntry(userState, projectRoot) {
47
+ const projects = userState?.["projects"];
48
+ if (!isRecord(projects)) return void 0;
49
+ for (const [key, value] of Object.entries(projects)) {
50
+ if (isRecord(value) && samePath(key, projectRoot)) return value;
51
+ }
52
+ return void 0;
53
+ }
54
+ function planClaudeCodeImport(opts) {
55
+ const { sources } = opts;
56
+ const mcp = [];
57
+ const seen = /* @__PURE__ */ new Set();
58
+ const collect = (servers, source) => {
59
+ if (!isRecord(servers)) return;
60
+ for (const [name, raw] of Object.entries(servers)) {
61
+ if (seen.has(name)) continue;
62
+ seen.add(name);
63
+ let config;
64
+ try {
65
+ config = normalizeMcpServerEntry(name, raw);
66
+ } catch (err) {
67
+ mcp.push({
68
+ name,
69
+ source,
70
+ config: {},
71
+ action: "skip-invalid",
72
+ enabled: false,
73
+ note: err.message
74
+ });
75
+ continue;
76
+ }
77
+ const exists2 = Object.hasOwn(opts.existingServers, name);
78
+ const repository = source === "repository";
79
+ const enabled = !repository || opts.enableProjectServers;
80
+ const stripped = [];
81
+ if (repository) {
82
+ for (const field of REPOSITORY_STRIPPED_MCP_FIELDS) {
83
+ if (config[field] === void 0) continue;
84
+ delete config[field];
85
+ stripped.push(field);
86
+ }
87
+ config.origin = "repository";
88
+ }
89
+ const reads = envReads(config);
90
+ const target = describeTarget(config);
91
+ const notes2 = [
92
+ target,
93
+ repository && !enabled ? "from the repository \u2014 imported disabled; review, then `/mcp enable`" : void 0,
94
+ reads.length > 0 ? `reads environment: ${reads.join(", ")}` : void 0,
95
+ stripped.length > 0 ? `not imported from the repository: ${stripped.join(", ")} (set them yourself after review)` : void 0
96
+ ].filter((note) => note !== void 0);
97
+ mcp.push({
98
+ name,
99
+ source,
100
+ config,
101
+ action: exists2 ? opts.overwrite ? "overwrite" : "skip-exists" : "add",
102
+ enabled,
103
+ ...notes2.length > 0 ? { note: notes2.join("; ") } : {}
104
+ });
105
+ }
106
+ };
107
+ collect(
108
+ projectEntry(sources.userState, opts.projectRoot)?.["mcpServers"],
109
+ "claude-project-local"
110
+ );
111
+ collect(sources.userState?.["mcpServers"], "claude-user");
112
+ collect(sources.projectMcp?.["mcpServers"] ?? sources.projectMcp, "repository");
113
+ const notes = [];
114
+ if (sources.skillDirs.length > 0) {
115
+ notes.push(
116
+ `Skills: ${sources.skillDirs.join(", ")} \u2014 already loaded in place (skills.readClaudeSkills); nothing to copy.`
117
+ );
118
+ }
119
+ let hookCount = 0;
120
+ let ruleCount = 0;
121
+ for (const { content } of sources.settings) {
122
+ const hooks = content["hooks"];
123
+ if (isRecord(hooks)) {
124
+ for (const list of Object.values(hooks)) if (Array.isArray(list)) hookCount += list.length;
125
+ }
126
+ const permissions = content["permissions"];
127
+ if (isRecord(permissions)) {
128
+ for (const key of ["allow", "deny", "ask"]) {
129
+ const list = permissions[key];
130
+ if (Array.isArray(list)) ruleCount += list.length;
131
+ }
132
+ }
133
+ }
134
+ if (hookCount > 0) {
135
+ notes.push(
136
+ `Hooks: ${hookCount} found \u2014 not imported (matcher semantics differ). Recreate under config.hooks; see docs/hooks.md.`
137
+ );
138
+ }
139
+ if (ruleCount > 0) {
140
+ notes.push(
141
+ `Permission rules: ${ruleCount} found \u2014 not imported (a mistranslated deny is worse than none). Use /permissions or --allowed-tools/--disallowed-tools.`
142
+ );
143
+ }
144
+ for (const file of sources.instructionFiles) {
145
+ notes.push(
146
+ `Instructions: ${file} \u2014 not imported. Project context lives in .wrongstack/AGENTS.md; merge what applies there.`
147
+ );
148
+ }
149
+ return { mcp, notes };
150
+ }
151
+ async function readJson(file) {
152
+ let raw;
153
+ try {
154
+ raw = await fs.readFile(file, "utf8");
155
+ } catch {
156
+ return void 0;
157
+ }
158
+ try {
159
+ const parsed = JSON.parse(raw);
160
+ return isRecord(parsed) ? parsed : void 0;
161
+ } catch {
162
+ throw new Error(`${file} is not valid JSON`);
163
+ }
164
+ }
165
+ async function exists(p) {
166
+ try {
167
+ await fs.access(p);
168
+ return true;
169
+ } catch {
170
+ return false;
171
+ }
172
+ }
173
+ async function readClaudeCodeSources(projectRoot, userHome = os.homedir()) {
174
+ const settingsFiles = [
175
+ path.join(userHome, ".claude", "settings.json"),
176
+ path.join(projectRoot, ".claude", "settings.json"),
177
+ path.join(projectRoot, ".claude", "settings.local.json")
178
+ ];
179
+ const settings = [];
180
+ for (const file of settingsFiles) {
181
+ const content = await readJson(file);
182
+ if (content) settings.push({ file, content });
183
+ }
184
+ const instructionCandidates = [
185
+ path.join(userHome, ".claude", "CLAUDE.md"),
186
+ path.join(projectRoot, "CLAUDE.md"),
187
+ path.join(projectRoot, ".claude", "CLAUDE.md")
188
+ ];
189
+ const skillCandidates = [
190
+ path.join(userHome, ".claude", "skills"),
191
+ path.join(projectRoot, ".claude", "skills")
192
+ ];
193
+ return {
194
+ userState: await readJson(path.join(userHome, ".claude.json")),
195
+ projectMcp: await readJson(path.join(projectRoot, ".mcp.json")),
196
+ settings,
197
+ instructionFiles: (await Promise.all(instructionCandidates.map(async (f) => await exists(f) ? f : null))).filter((f) => f !== null),
198
+ skillDirs: (await Promise.all(skillCandidates.map(async (d) => await exists(d) ? d : null))).filter((d) => d !== null)
199
+ };
200
+ }
201
+ var SOURCE_LABEL = {
202
+ "claude-user": "~/.claude.json (user)",
203
+ "claude-project-local": "~/.claude.json (this project)",
204
+ repository: ".mcp.json (repository)"
205
+ };
206
+ var importClaudeCodeCmd = async (args, deps) => {
207
+ args = restoreFlags(args, deps, ["apply", "overwrite", "enable-project-servers"]);
208
+ const apply = args.includes("--apply");
209
+ const overwrite = args.includes("--overwrite");
210
+ const enableProjectServers = args.includes("--enable-project-servers");
211
+ let sources;
212
+ try {
213
+ sources = await readClaudeCodeSources(deps.projectRoot, deps.userHome);
214
+ } catch (err) {
215
+ deps.renderer.writeError(`import-claude-code: ${err.message}`);
216
+ return 1;
217
+ }
218
+ const configPath = activeProfileConfigPath(deps.paths, deps.config);
219
+ const current = await readJsonObjectFile(configPath);
220
+ const existingServers = isRecord(current["mcpServers"]) ? current["mcpServers"] : {};
221
+ const plan = planClaudeCodeImport({
222
+ sources,
223
+ projectRoot: deps.projectRoot,
224
+ existingServers,
225
+ overwrite,
226
+ enableProjectServers
227
+ });
228
+ const out = (line) => deps.renderer.write(`${line}
229
+ `);
230
+ out(apply ? "Importing from Claude Code:" : "Claude Code import preview (nothing written):");
231
+ if (plan.mcp.length === 0) out(" MCP servers: none found");
232
+ for (const c of plan.mcp) {
233
+ const state = c.action.startsWith("skip") ? "" : c.enabled ? " [enabled]" : " [disabled]";
234
+ const verb = {
235
+ add: "add",
236
+ overwrite: "overwrite",
237
+ "skip-exists": "skip (exists; --overwrite to replace)",
238
+ "skip-invalid": "skip (invalid)"
239
+ }[c.action];
240
+ out(` MCP ${c.name} \u2014 ${verb}${state} \u2014 ${SOURCE_LABEL[c.source]}`);
241
+ if (c.note) out(` ${c.note}`);
242
+ }
243
+ for (const note of plan.notes) out(` ${note}`);
244
+ const writes = plan.mcp.filter((c) => c.action === "add" || c.action === "overwrite");
245
+ if (!apply) {
246
+ if (writes.length > 0)
247
+ out(`
248
+ Run with --apply to write ${writes.length} server(s) to ${configPath}.`);
249
+ return 0;
250
+ }
251
+ if (writes.length > 0) {
252
+ await updateJsonObjectFile(configPath, (config) => {
253
+ for (const c of writes) {
254
+ setJsonPath(config, ["mcpServers", c.name], { ...c.config, enabled: c.enabled });
255
+ }
256
+ });
257
+ }
258
+ out(`
259
+ Wrote ${writes.length} server(s) to ${configPath}.`);
260
+ return 0;
261
+ };
262
+ export {
263
+ REPOSITORY_STRIPPED_MCP_FIELDS,
264
+ importClaudeCodeCmd,
265
+ planClaudeCodeImport,
266
+ readClaudeCodeSources
267
+ };
268
+ //# sourceMappingURL=import-claude-code-AYG24RG2.js.map
package/dist/index.js CHANGED
@@ -2,28 +2,32 @@
2
2
  import {
3
3
  applyNodeEnvDefault,
4
4
  applySessionShellDefault
5
- } from "./chunk-QBBF7GIK.js";
6
- import {
7
- parseArgs
8
- } from "./chunk-MHEBWVXL.js";
5
+ } from "./chunk-LBPLTTZ6.js";
9
6
  import {
10
7
  CLI_VERSION
11
- } from "./chunk-YBUCXXYZ.js";
8
+ } from "./chunk-F5DCFAKI.js";
9
+ import {
10
+ parseArgs
11
+ } from "./chunk-Q4INH2DG.js";
12
12
 
13
13
  // src/cli-entry-main.ts
14
14
  async function main(argv) {
15
15
  applyNodeEnvDefault();
16
16
  applySessionShellDefault();
17
17
  const earlyFlags = parseArgs(argv).flags;
18
+ if (earlyFlags["ascii"] === true || process.env["WRONGSTACK_TUI_ICON_STYLE"]) {
19
+ const { applyAsciiMode } = await import("./ascii-mode-SG4PRNLP.js");
20
+ applyAsciiMode(earlyFlags);
21
+ }
18
22
  if (earlyFlags["help"] === true || earlyFlags["version"] === true) {
19
- const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-SDT53OML.js");
23
+ const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-5TNTJPQR.js");
20
24
  const earlyExit = await handleHelpVersionShortCircuit(argv);
21
25
  if (earlyExit !== null) return earlyExit;
22
26
  }
23
- const { initializeCli } = await import("./cli-context-34Q5IJRA.js");
27
+ const { initializeCli } = await import("./cli-context-C7RBSWHF.js");
24
28
  const cliCtx = await initializeCli(argv);
25
29
  if (typeof cliCtx === "number") return cliCtx;
26
- const { runInteractive } = await import("./cli-main-AELJDBGU.js");
30
+ const { runInteractive } = await import("./cli-main-TQTH73ZK.js");
27
31
  return runInteractive(cliCtx);
28
32
  }
29
33
 
@@ -19,6 +19,7 @@ export interface LiveSettingsInput {
19
19
  featureMemory?: boolean | undefined;
20
20
  featureSkills?: boolean | undefined;
21
21
  featureModelsRegistry?: boolean | undefined;
22
+ featureToolCoach?: boolean | undefined;
22
23
  featureTokenSaving?: TokenSavingTier | undefined;
23
24
  allowOutsideProjectRoot?: boolean | undefined;
24
25
  contextAutoCompact?: boolean | undefined;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  startCliHqConnection
3
- } from "./chunk-BLD5DSVA.js";
4
- import "./chunk-YBUCXXYZ.js";
3
+ } from "./chunk-RGFWGUAB.js";
4
+ import "./chunk-F5DCFAKI.js";
5
5
 
6
6
  // src/subcommands/handlers/mailbox-serve.ts
7
7
  import { createServer } from "node:http";
@@ -361,4 +361,4 @@ function printHelp(deps) {
361
361
  export {
362
362
  mailboxServeCmd
363
363
  };
364
- //# sourceMappingURL=mailbox-serve-WDOCH6KR.js.map
364
+ //# sourceMappingURL=mailbox-serve-GNGXEQ2R.js.map
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  applyProviderOAuthRefresh
3
- } from "./chunk-3OCUS3VN.js";
3
+ } from "./chunk-LDCGZJTC.js";
4
+ import {
5
+ discoverAndMergeProviders
6
+ } from "./chunk-D5GB5MHA.js";
4
7
  import {
5
8
  checkMark,
6
9
  costLabel,
@@ -15,18 +18,15 @@ import {
15
18
  scoreBar,
16
19
  speedLabel
17
20
  } from "./chunk-BBHWW6LR.js";
18
- import {
19
- discoverAndMergeProviders
20
- } from "./chunk-D5GB5MHA.js";
21
- import {
22
- activeProfileConfigPath
23
- } from "./chunk-YMXXOOFN.js";
24
21
  import {
25
22
  resolveRawProviderConnection
26
- } from "./chunk-S4FFHDJG.js";
23
+ } from "./chunk-SDJCLEK6.js";
27
24
  import {
28
25
  mutateConfigProviders
29
26
  } from "./chunk-LUMETJFO.js";
27
+ import {
28
+ activeProfileConfigPath
29
+ } from "./chunk-YMXXOOFN.js";
30
30
 
31
31
  // src/subcommands/handlers/modeldiag.ts
32
32
  import * as fs from "node:fs/promises";
@@ -825,4 +825,4 @@ var modeldiagCmd = async (args, deps) => {
825
825
  export {
826
826
  modeldiagCmd
827
827
  };
828
- //# sourceMappingURL=modeldiag-36OGAL5C.js.map
828
+ //# sourceMappingURL=modeldiag-W7XAE625.js.map
@@ -7,7 +7,7 @@ import {
7
7
  renderFocusedHelpToString,
8
8
  renderGenericHelp,
9
9
  subcommandsWithFocusedHelp
10
- } from "./chunk-SKPDE62W.js";
10
+ } from "./chunk-EPR42SWM.js";
11
11
  import "./chunk-YTEOAWOJ.js";
12
12
  export {
13
13
  deepSubcommandsWithFocusedHelp,
@@ -19,4 +19,4 @@ export {
19
19
  renderGenericHelp,
20
20
  subcommandsWithFocusedHelp
21
21
  };
22
- //# sourceMappingURL=per-subcommand-help-XE77MTGJ.js.map
22
+ //# sourceMappingURL=per-subcommand-help-QDAQASPZ.js.map
@@ -2,6 +2,14 @@ import type { InputReader, Tool } from '@wrongstack/core/types';
2
2
  type PromptDecision = 'yes' | 'no' | 'always' | 'always-exact' | 'always-command' | 'always-tool' | 'deny';
3
3
  /** Signature the Agent expects for confirming tool calls. */
4
4
  export type ConfirmAwaiter = (tool: Tool, input: unknown, toolUseId: string, suggestedPattern: string) => Promise<'yes' | 'no' | 'always' | 'always-exact' | 'always-command' | 'always-tool' | 'deny'>;
5
+ /**
6
+ * Approval "prompt" for a process with no terminal on stdin — a script, CI,
7
+ * `wstack "task" < /dev/null`, piped input. Nobody can answer, and the
8
+ * terminal prompt used to wait for a key that never came, so the run hung
9
+ * until it was killed. Refuse instead, and say on stderr (stdout may be a
10
+ * JSON payload) how to grant it up front.
11
+ */
12
+ export declare function makeHeadlessPromptDelegate(write?: (text: string) => void): (tool: Tool) => Promise<PromptDecision>;
5
13
  /**
6
14
  * The terminal approval prompt.
7
15
  *
@@ -16,6 +24,12 @@ export declare function makePromptDelegate(reader: InputReader): (tool: Tool, in
16
24
  * Create a ConfirmAwaiter for the CLI path. Wraps makePromptDelegate
17
25
  * with the ConfirmAwaiter type signature expected by the Agent.
18
26
  */
27
+ /**
28
+ * The terminal prompt when stdin is a terminal, the headless refusal
29
+ * otherwise. Both approval paths (policy prompt and executor confirm) go
30
+ * through this, so neither can wait on a keypress nobody can make.
31
+ */
32
+ export declare function makeStdinPromptDelegate(reader: InputReader, stdinIsTTY?: boolean): ReturnType<typeof makePromptDelegate>;
19
33
  export declare function makeConfirmAwaiter(reader: InputReader): ConfirmAwaiter;
20
34
  export {};
21
35
  //# sourceMappingURL=permission-prompt.d.ts.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Text views of the permission rule list and of one explained call, shared by
3
+ * `wstack permissions` and the in-session `/permissions` command.
4
+ */
5
+ import type { Context } from '@wrongstack/core/agent';
6
+ import type { PermissionPolicy, PermissionRule, PermissionTrace, Tool } from '@wrongstack/core/types';
7
+ export interface ExplainedCall {
8
+ trace: PermissionTrace;
9
+ rules: PermissionRule[];
10
+ /** The rule that decided the call. */
11
+ rule: PermissionRule | undefined;
12
+ }
13
+ /** Trace one call through the policy and the executor's gate, and name its rule. */
14
+ export declare function explainCall(policy: Pick<PermissionPolicy, 'explain' | 'listRules'>, tool: Tool, input: unknown, ctx: Context, yolo: boolean): Promise<ExplainedCall>;
15
+ export declare function describePermissionRule(rule: PermissionRule): string;
16
+ export declare function formatPermissionRules(rules: readonly PermissionRule[]): string;
17
+ export declare function formatExplainedCall({ trace, rule }: ExplainedCall): string;
18
+ //# sourceMappingURL=permission-rules-view.d.ts.map
@@ -1,23 +1,45 @@
1
+ import {
2
+ explainCall,
3
+ formatExplainedCall,
4
+ formatPermissionRules
5
+ } from "./chunk-4TVYGG6G.js";
1
6
 
2
7
  // src/subcommands/handlers/permissions.ts
3
- import { DefaultPermissionPolicy } from "@wrongstack/core/security";
8
+ import { compilePermissionRules } from "@wrongstack/core/security";
4
9
  import { resolveWstackPaths } from "@wrongstack/core/utils";
10
+ import { createProjectPermissionPolicy } from "@wrongstack/runtime";
5
11
  var permissionsCmd = async (args, deps) => {
6
12
  const subCmd = args[0];
7
13
  if (subCmd === "help" || subCmd === "--help" || subCmd === "-h" || !subCmd || subCmd === "explain" && !args[1]) {
8
- if (subCmd !== "explain" && subCmd !== "help" && subCmd !== void 0) {
9
- deps.renderer.writeError(`Unknown permissions subcommand: ${subCmd}
10
- `);
11
- }
12
14
  deps.renderer.write(usage());
13
- return subCmd && subCmd !== "explain" && subCmd !== "help" && subCmd !== void 0 ? 1 : 0;
15
+ return 0;
14
16
  }
15
- if (subCmd !== "explain") {
17
+ if (subCmd !== "explain" && subCmd !== "rules") {
16
18
  deps.renderer.writeError(`Unknown permissions subcommand: ${subCmd}
17
19
  `);
18
20
  deps.renderer.write(usage());
19
21
  return 1;
20
22
  }
23
+ const jsonOutput = deps.flags?.["json"] === true || args.includes("--json");
24
+ const built = buildPolicy(deps);
25
+ if (typeof built === "string") {
26
+ deps.renderer.writeError(`${built}
27
+ `);
28
+ return 1;
29
+ }
30
+ const { policy, ctx, yolo, yoloSource } = built;
31
+ if (subCmd === "rules") {
32
+ const rules = await compilePermissionRules(policy, ctx, { yolo });
33
+ if (jsonOutput) deps.renderer.write(`${JSON.stringify(rules, null, 2)}
34
+ `);
35
+ else
36
+ deps.renderer.writeLine(
37
+ `YOLO: ${yolo ? "on" : "off"} (${yoloSource})
38
+
39
+ ${formatPermissionRules(rules)}`
40
+ );
41
+ return 0;
42
+ }
21
43
  const toolName = args[1];
22
44
  if (!toolName) {
23
45
  deps.renderer.writeError("Missing tool name.\n");
@@ -27,7 +49,6 @@ var permissionsCmd = async (args, deps) => {
27
49
  const inputIdx = args.indexOf("--input");
28
50
  const flagInput = deps.flags?.["input"];
29
51
  const rawInput = typeof flagInput === "string" ? flagInput : inputIdx >= 0 && inputIdx + 1 < args.length ? args[inputIdx + 1] : void 0;
30
- const jsonOutput = deps.flags?.["json"] === true || args.includes("--json");
31
52
  let input = {};
32
53
  if (rawInput) {
33
54
  try {
@@ -50,67 +71,68 @@ var permissionsCmd = async (args, deps) => {
50
71
  );
51
72
  return 1;
52
73
  }
74
+ const explained = await explainCall(policy, tool, input, ctx, yolo);
75
+ if (jsonOutput) {
76
+ deps.renderer.write(
77
+ `${JSON.stringify({ ...explained.trace, rule: explained.rule }, null, 2)}
78
+ `
79
+ );
80
+ } else {
81
+ deps.renderer.writeLine(
82
+ `YOLO: ${yolo ? "on" : "off"} (${yoloSource})
83
+
84
+ ${formatExplainedCall(explained)}`
85
+ );
86
+ }
87
+ return 0;
88
+ };
89
+ function buildPolicy(deps) {
53
90
  const paths = resolveWstackPaths({ projectRoot: deps.projectRoot, userHome: deps.userHome });
54
- const trustFile = paths.projectTrust;
55
91
  const readSubjects = /* @__PURE__ */ new Set();
56
92
  const ctx = {
57
93
  projectRoot: deps.projectRoot,
58
94
  cwd: deps.cwd,
95
+ workingDir: deps.cwd,
96
+ meta: {},
97
+ provider: { id: deps.config.provider },
59
98
  hasRead(subject) {
60
99
  return readSubjects.has(subject);
61
100
  }
62
101
  };
63
- const policy = new DefaultPermissionPolicy({
64
- trustFile,
65
- yolo: deps.flags?.["yolo"] ?? false
66
- });
67
- await policy.reload();
68
- const trace = await policy.explain(tool, input, ctx);
69
- if (jsonOutput) {
70
- deps.renderer.write(JSON.stringify(trace, null, 2) + "\n");
71
- } else {
72
- deps.renderer.write(formatTrace(trace) + "\n");
102
+ const yoloFlag = deps.flags?.["yolo"];
103
+ const yolo = typeof yoloFlag === "boolean" ? yoloFlag : deps.config.yolo === true;
104
+ try {
105
+ const policy = createProjectPermissionPolicy({
106
+ projectRoot: deps.projectRoot,
107
+ trustFile: paths.projectTrust,
108
+ config: deps.config,
109
+ permission: { yolo }
110
+ })();
111
+ return { policy, ctx, yolo, yoloSource: typeof yoloFlag === "boolean" ? "--yolo" : "config" };
112
+ } catch (error) {
113
+ return error instanceof Error ? error.message : String(error);
73
114
  }
74
- return 0;
75
- };
76
- function formatTrace(trace) {
77
- const lines = [];
78
- lines.push(`Permission trace for "${trace.toolName}"`);
79
- lines.push(`Subject: ${trace.subject ?? "(none)"}`);
80
- lines.push("");
81
- for (let i = 0; i < trace.steps.length; i++) {
82
- const step = trace.steps[i];
83
- const winner = i === trace.winnerIndex ? " \u2190 WINNER" : "";
84
- const matched = step.matched ? "\u2713" : " ";
85
- lines.push(` ${matched} [${i}] ${step.rule}${winner}`);
86
- lines.push(` decision: ${step.decision} source: ${step.source}`);
87
- lines.push(` ${step.detail}`);
88
- if (i < trace.steps.length - 1) lines.push("");
89
- }
90
- lines.push("");
91
- lines.push(`Effective: ${trace.decision.permission} (source: ${trace.decision.source})`);
92
- if (trace.decision.reason) {
93
- lines.push(`Reason: ${trace.decision.reason}`);
94
- }
95
- if (trace.decision.riskTier) {
96
- lines.push(`Risk tier: ${trace.decision.riskTier}`);
97
- }
98
- return lines.join("\n");
99
115
  }
100
116
  function usage() {
101
117
  return `Usage:
118
+ wstack permissions rules [--json]
102
119
  wstack permissions explain <tool> --input '<json>' [--json]
103
120
 
104
121
  Examples:
122
+ wstack permissions rules
105
123
  wstack permissions explain bash --input '{"command":"rm -rf /"}'
106
124
  wstack permissions explain read --input '{"path":".env"}' --json
107
125
 
108
126
  Flags:
109
127
  --input <json> Tool input arguments as a JSON object
110
128
  --json Output as structured JSON instead of human-readable text
129
+ --yolo Show the rules as they apply with YOLO on
130
+
131
+ Inside a session, /permissions shows the same with that session\u2019s YOLO,
132
+ answers and /permissions allow|deny rules.
111
133
  `;
112
134
  }
113
135
  export {
114
136
  permissionsCmd
115
137
  };
116
- //# sourceMappingURL=permissions-CFDLXETM.js.map
138
+ //# sourceMappingURL=permissions-PL27UHYD.js.map
@@ -4,10 +4,10 @@ import {
4
4
  import {
5
5
  activeProfileConfigPath
6
6
  } from "./chunk-YMXXOOFN.js";
7
- import "./chunk-WSTVGC2C.js";
8
7
  import {
9
8
  restoreFlags
10
9
  } from "./chunk-CSAPOCBP.js";
10
+ import "./chunk-WSTVGC2C.js";
11
11
 
12
12
  // src/subcommands/handlers/plugin-usage.ts
13
13
  var pluginCmd = async (args, deps) => {
@@ -41,4 +41,4 @@ export {
41
41
  pluginCmd,
42
42
  usageCmd
43
43
  };
44
- //# sourceMappingURL=plugin-usage-S5LVGMBW.js.map
44
+ //# sourceMappingURL=plugin-usage-CIGOOTX3.js.map
@@ -1,17 +1,19 @@
1
1
  import {
2
2
  BUILTIN_PLUGIN_FACTORIES,
3
+ BUILTIN_PLUGIN_NAME_HINTS,
3
4
  DEPRECATED_PLUGIN_NAMES,
4
5
  _resetDeprecatedWarningsForTests,
5
6
  builtinPluginNameFromSpec,
6
7
  pluginNameFromSpec,
7
8
  setupPlugins,
8
9
  warnIfDeprecatedPluginName
9
- } from "./chunk-JF2MULWF.js";
10
+ } from "./chunk-YHYINL47.js";
10
11
  import "./chunk-EWKESL4L.js";
11
12
  import "./chunk-L2RVEQWO.js";
12
13
  import "./chunk-WSTVGC2C.js";
13
14
  export {
14
15
  BUILTIN_PLUGIN_FACTORIES,
16
+ BUILTIN_PLUGIN_NAME_HINTS,
15
17
  DEPRECATED_PLUGIN_NAMES,
16
18
  _resetDeprecatedWarningsForTests,
17
19
  builtinPluginNameFromSpec,
@@ -19,4 +21,4 @@ export {
19
21
  setupPlugins,
20
22
  warnIfDeprecatedPluginName
21
23
  };
22
- //# sourceMappingURL=plugins-RHBIVLI7.js.map
24
+ //# sourceMappingURL=plugins-HQTXUD6A.js.map
@@ -39,7 +39,7 @@ export declare function applySessionShellDefault(): void;
39
39
  * callers get back the (possibly refreshed) `UpdateInfo`
40
40
  * so version-aware UI can render without re-fetching.
41
41
  */
42
- export declare function applyPrintUpdateNotice(initialUpdateInfo: UpdateInfo | undefined): Promise<UpdateInfo | undefined>;
42
+ export declare function applyPrintUpdateNotice(initialUpdateInfo: UpdateInfo | undefined, config?: Config | undefined): Promise<UpdateInfo | undefined>;
43
43
  /**
44
44
  * Seed the stream-debug singleton from persisted config so
45
45
  * `WireAdapter` picks it up on construction. Runtime toggles