poe-code 3.0.168 → 3.0.170

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.
@@ -0,0 +1,2514 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // node_modules/sisteransi/src/index.js
28
+ var require_src = __commonJS({
29
+ "node_modules/sisteransi/src/index.js"(exports, module) {
30
+ "use strict";
31
+ var ESC = "\x1B";
32
+ var CSI = `${ESC}[`;
33
+ var beep = "\x07";
34
+ var cursor = {
35
+ to(x, y) {
36
+ if (!y) return `${CSI}${x + 1}G`;
37
+ return `${CSI}${y + 1};${x + 1}H`;
38
+ },
39
+ move(x, y) {
40
+ let ret = "";
41
+ if (x < 0) ret += `${CSI}${-x}D`;
42
+ else if (x > 0) ret += `${CSI}${x}C`;
43
+ if (y < 0) ret += `${CSI}${-y}A`;
44
+ else if (y > 0) ret += `${CSI}${y}B`;
45
+ return ret;
46
+ },
47
+ up: (count = 1) => `${CSI}${count}A`,
48
+ down: (count = 1) => `${CSI}${count}B`,
49
+ forward: (count = 1) => `${CSI}${count}C`,
50
+ backward: (count = 1) => `${CSI}${count}D`,
51
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
52
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
53
+ left: `${CSI}G`,
54
+ hide: `${CSI}?25l`,
55
+ show: `${CSI}?25h`,
56
+ save: `${ESC}7`,
57
+ restore: `${ESC}8`
58
+ };
59
+ var scroll = {
60
+ up: (count = 1) => `${CSI}S`.repeat(count),
61
+ down: (count = 1) => `${CSI}T`.repeat(count)
62
+ };
63
+ var erase = {
64
+ screen: `${CSI}2J`,
65
+ up: (count = 1) => `${CSI}1J`.repeat(count),
66
+ down: (count = 1) => `${CSI}J`.repeat(count),
67
+ line: `${CSI}2K`,
68
+ lineEnd: `${CSI}K`,
69
+ lineStart: `${CSI}1K`,
70
+ lines(count) {
71
+ let clear = "";
72
+ for (let i = 0; i < count; i++)
73
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
74
+ if (count)
75
+ clear += cursor.left;
76
+ return clear;
77
+ }
78
+ };
79
+ module.exports = { cursor, scroll, erase, beep };
80
+ }
81
+ });
82
+
83
+ // src/templates/py-poe-spawn/env.hbs
84
+ var require_env = __commonJS({
85
+ "src/templates/py-poe-spawn/env.hbs"(exports, module) {
86
+ module.exports = "POE_API_KEY={{apiKey}}\nPOE_BASE_URL=https://api.poe.com/v1\nMODEL={{model}}\n";
87
+ }
88
+ });
89
+
90
+ // src/templates/py-poe-spawn/main.py.hbs
91
+ var require_main_py = __commonJS({
92
+ "src/templates/py-poe-spawn/main.py.hbs"(exports, module) {
93
+ module.exports = 'import os\nfrom openai import OpenAI\nfrom dotenv import load_dotenv\n\nload_dotenv()\n\nclient = OpenAI(\n api_key=os.getenv("POE_API_KEY"),\n base_url=os.getenv("POE_BASE_URL")\n)\n\nresponse = client.chat.completions.create(\n model=os.getenv("MODEL", "{{model}}"),\n messages=[{"role": "user", "content": "Tell me a joke"}]\n)\n\nprint(response.choices[0].message.content)\n';
94
+ }
95
+ });
96
+
97
+ // src/templates/py-poe-spawn/requirements.txt.hbs
98
+ var require_requirements_txt = __commonJS({
99
+ "src/templates/py-poe-spawn/requirements.txt.hbs"(exports, module) {
100
+ module.exports = "openai>=1.0.0\npython-dotenv>=1.0.0\n";
101
+ }
102
+ });
103
+
104
+ // src/templates/codex/config.toml.hbs
105
+ var require_config_toml = __commonJS({
106
+ "src/templates/codex/config.toml.hbs"(exports, module) {
107
+ module.exports = 'model_provider = "poe"\n\n[profiles."{{{profileName}}}"]\nmodel = "{{{model}}}"\nmodel_provider = "poe"\nmodel_reasoning_effort = "{{reasoningEffort}}"\nmodel_verbosity = "medium"\n\n[model_providers.poe]\nname = "poe"\nbase_url = "{{{baseUrl}}}"\nwire_api = "responses"\nexperimental_bearer_token = "{{apiKey}}"\nrequires_openai_auth = false\nsupports_websockets = false\n';
108
+ }
109
+ });
110
+
111
+ // packages/agent-spawn/src/run-command.ts
112
+ import { spawn } from "node:child_process";
113
+
114
+ // packages/agent-defs/src/agents/claude-code.ts
115
+ var claudeCodeAgent = {
116
+ id: "claude-code",
117
+ name: "claude-code",
118
+ label: "Claude Code",
119
+ summary: "Configure Claude Code to route through Poe.",
120
+ aliases: ["claude"],
121
+ binaryName: "claude",
122
+ configPath: "~/.claude/settings.json",
123
+ branding: {
124
+ colors: {
125
+ dark: "#C15F3C",
126
+ light: "#C15F3C"
127
+ }
128
+ }
129
+ };
130
+
131
+ // packages/agent-defs/src/agents/claude-desktop.ts
132
+ var claudeDesktopAgent = {
133
+ id: "claude-desktop",
134
+ name: "claude-desktop",
135
+ label: "Claude Desktop",
136
+ summary: "Anthropic's official desktop application for Claude",
137
+ configPath: "~/.claude/settings.json",
138
+ branding: {
139
+ colors: {
140
+ dark: "#D97757",
141
+ light: "#D97757"
142
+ }
143
+ }
144
+ };
145
+
146
+ // packages/agent-defs/src/agents/codex.ts
147
+ var codexAgent = {
148
+ id: "codex",
149
+ name: "codex",
150
+ label: "Codex",
151
+ summary: "Configure Codex to use Poe as the model provider.",
152
+ binaryName: "codex",
153
+ configPath: "~/.codex/config.toml",
154
+ branding: {
155
+ colors: {
156
+ dark: "#D5D9DF",
157
+ light: "#7A7F86"
158
+ }
159
+ }
160
+ };
161
+
162
+ // packages/agent-defs/src/agents/opencode.ts
163
+ var openCodeAgent = {
164
+ id: "opencode",
165
+ name: "opencode",
166
+ label: "OpenCode CLI",
167
+ summary: "Configure OpenCode CLI to use the Poe API.",
168
+ binaryName: "opencode",
169
+ configPath: "~/.config/opencode/config.json",
170
+ branding: {
171
+ colors: {
172
+ dark: "#4A4F55",
173
+ light: "#2F3338"
174
+ }
175
+ }
176
+ };
177
+
178
+ // packages/agent-defs/src/agents/kimi.ts
179
+ var kimiAgent = {
180
+ id: "kimi",
181
+ name: "kimi",
182
+ label: "Kimi",
183
+ summary: "Configure Kimi CLI to use Poe API",
184
+ aliases: ["kimi-cli"],
185
+ binaryName: "kimi",
186
+ configPath: "~/.kimi/config.toml",
187
+ branding: {
188
+ colors: {
189
+ dark: "#7B68EE",
190
+ light: "#6A5ACD"
191
+ }
192
+ }
193
+ };
194
+
195
+ // packages/agent-defs/src/agents/goose.ts
196
+ var gooseAgent = {
197
+ id: "goose",
198
+ name: "goose",
199
+ label: "Goose",
200
+ summary: "Block's open-source AI agent with ACP support.",
201
+ binaryName: "goose",
202
+ configPath: "~/.config/goose/config.yaml",
203
+ branding: {
204
+ colors: {
205
+ dark: "#FF6B35",
206
+ light: "#E85D26"
207
+ }
208
+ }
209
+ };
210
+
211
+ // packages/agent-defs/src/registry.ts
212
+ var allAgents = [
213
+ claudeCodeAgent,
214
+ claudeDesktopAgent,
215
+ codexAgent,
216
+ openCodeAgent,
217
+ kimiAgent,
218
+ gooseAgent
219
+ ];
220
+ var lookup = /* @__PURE__ */ new Map();
221
+ for (const agent of allAgents) {
222
+ const values = [agent.id, agent.name, ...agent.aliases ?? []];
223
+ for (const value of values) {
224
+ const normalized = value.toLowerCase();
225
+ if (!lookup.has(normalized)) {
226
+ lookup.set(normalized, agent.id);
227
+ }
228
+ }
229
+ }
230
+
231
+ // packages/agent-spawn/src/configs/mcp.ts
232
+ function toJsonMcpServers(servers) {
233
+ const out = {};
234
+ for (const [name, server] of Object.entries(servers)) {
235
+ const mapped = { command: server.command };
236
+ if (server.args && server.args.length > 0) {
237
+ mapped.args = server.args;
238
+ }
239
+ if (server.env && Object.keys(server.env).length > 0) {
240
+ mapped.env = server.env;
241
+ }
242
+ out[name] = mapped;
243
+ }
244
+ return out;
245
+ }
246
+ function toTomlString(value) {
247
+ return JSON.stringify(value);
248
+ }
249
+ function toTomlArray(values) {
250
+ const serialized = values.map((value) => toTomlString(value));
251
+ return `[${serialized.join(", ")}]`;
252
+ }
253
+ function toTomlInlineTable(values) {
254
+ const parts = [];
255
+ for (const [key, value] of Object.entries(values)) {
256
+ parts.push(`${JSON.stringify(key)}=${toTomlString(value)}`);
257
+ }
258
+ return `{${parts.join(", ")}}`;
259
+ }
260
+ function serializeJsonMcpArgs(servers) {
261
+ return ["--mcp-config", JSON.stringify({ mcpServers: toJsonMcpServers(servers) })];
262
+ }
263
+ function serializeOpenCodeMcpEnv(servers) {
264
+ const mcp = {};
265
+ for (const [name, server] of Object.entries(servers)) {
266
+ const entry = { type: "local", command: [server.command, ...server.args ?? []] };
267
+ if (server.env && Object.keys(server.env).length > 0) {
268
+ entry.environment = server.env;
269
+ }
270
+ mcp[name] = entry;
271
+ }
272
+ return { OPENCODE_CONFIG_CONTENT: JSON.stringify({ mcp }) };
273
+ }
274
+ function serializeCodexMcpArgs(servers) {
275
+ const args = [];
276
+ for (const [name, server] of Object.entries(servers)) {
277
+ const prefix = `mcp_servers.${name}`;
278
+ args.push("-c", `${prefix}.command=${toTomlString(server.command)}`);
279
+ if (server.args && server.args.length > 0) {
280
+ args.push("-c", `${prefix}.args=${toTomlArray(server.args)}`);
281
+ }
282
+ if (server.env && Object.keys(server.env).length > 0) {
283
+ args.push("-c", `${prefix}.env=${toTomlInlineTable(server.env)}`);
284
+ }
285
+ }
286
+ return args;
287
+ }
288
+ function serializeGooseMcpArgs(servers) {
289
+ return Object.values(servers).flatMap((server) => [
290
+ "--with-extension",
291
+ [server.command, ...server.args ?? []].join(" ")
292
+ ]);
293
+ }
294
+
295
+ // packages/agent-spawn/src/configs/claude-code.ts
296
+ var claudeCodeSpawnConfig = {
297
+ kind: "cli",
298
+ agentId: "claude-code",
299
+ // ACP adapter support: yes (adapter: "claude")
300
+ adapter: "claude",
301
+ promptFlag: "-p",
302
+ modelFlag: "--model",
303
+ modelStripProviderPrefix: true,
304
+ modelTransform: (model) => model.replaceAll(".", "-"),
305
+ defaultArgs: [
306
+ "--output-format",
307
+ "stream-json",
308
+ "--verbose"
309
+ ],
310
+ mcpArgs: serializeJsonMcpArgs,
311
+ modes: {
312
+ yolo: ["--dangerously-skip-permissions"],
313
+ edit: ["--permission-mode", "acceptEdits", "--allowedTools", "Bash,Read,Write,Edit,Glob,Grep,NotebookEdit"],
314
+ read: ["--permission-mode", "plan"]
315
+ },
316
+ stdinMode: {
317
+ omitPrompt: true,
318
+ extraArgs: ["--input-format", "text"]
319
+ },
320
+ interactive: {
321
+ defaultArgs: []
322
+ },
323
+ resumeCommand: (threadId) => ["--resume", threadId]
324
+ };
325
+
326
+ // packages/agent-spawn/src/configs/codex.ts
327
+ var codexSpawnConfig = {
328
+ kind: "cli",
329
+ agentId: "codex",
330
+ // ACP adapter support: yes (adapter: "codex")
331
+ adapter: "codex",
332
+ promptFlag: "exec",
333
+ modelFlag: "--model",
334
+ modelStripProviderPrefix: true,
335
+ defaultArgs: ["--skip-git-repo-check", "--json"],
336
+ mcpArgs: serializeCodexMcpArgs,
337
+ mcpArgsBeforeCommand: true,
338
+ modes: {
339
+ yolo: ["-s", "danger-full-access"],
340
+ edit: ["-s", "workspace-write"],
341
+ read: ["-s", "read-only"]
342
+ },
343
+ stdinMode: {
344
+ omitPrompt: true,
345
+ extraArgs: ["-"]
346
+ },
347
+ interactive: {
348
+ defaultArgs: ["-a", "never"]
349
+ },
350
+ resumeCommand: (threadId, cwd) => ["resume", "-C", cwd, threadId]
351
+ };
352
+
353
+ // packages/agent-spawn/src/configs/opencode.ts
354
+ var openCodeSpawnConfig = {
355
+ kind: "cli",
356
+ agentId: "opencode",
357
+ // ACP adapter support: yes (adapter: "opencode").
358
+ // OpenCode's `--format json` emits NDJSON events with `{ type, sessionID, part }`
359
+ // (no `{ event, ... }` field), so it needs the OpenCode adapter (not "native").
360
+ adapter: "opencode",
361
+ promptFlag: "run",
362
+ modelFlag: "--model",
363
+ modelStripProviderPrefix: false,
364
+ modelTransform: (model) => {
365
+ return model.startsWith("poe/") ? model : `poe/${model}`;
366
+ },
367
+ defaultArgs: ["--format", "json"],
368
+ modes: {
369
+ yolo: [],
370
+ edit: [],
371
+ read: ["--agent", "plan"]
372
+ },
373
+ interactive: {
374
+ defaultArgs: [],
375
+ promptFlag: "--prompt"
376
+ },
377
+ resumeCommand: (threadId, cwd) => [cwd, "--session", threadId],
378
+ mcpEnv: serializeOpenCodeMcpEnv
379
+ };
380
+ var openCodeAcpSpawnConfig = {
381
+ kind: "acp",
382
+ agentId: "opencode",
383
+ acpArgs: ["acp"],
384
+ skipAuth: true,
385
+ mcpEnv: serializeOpenCodeMcpEnv
386
+ };
387
+
388
+ // packages/agent-spawn/src/configs/kimi.ts
389
+ var kimiSpawnConfig = {
390
+ kind: "cli",
391
+ agentId: "kimi",
392
+ // ACP adapter support: yes (adapter: "kimi").
393
+ // Kimi's `--output-format stream-json` emits OpenAI-style `{ role, content }` JSON
394
+ // (no `{ event, ... }` field), so it needs the Kimi adapter (not "native").
395
+ adapter: "kimi",
396
+ promptFlag: "-p",
397
+ modelStripProviderPrefix: true,
398
+ defaultArgs: ["--print", "--output-format", "stream-json"],
399
+ mcpArgs: serializeJsonMcpArgs,
400
+ modes: {
401
+ yolo: ["--yolo"],
402
+ edit: [],
403
+ read: []
404
+ },
405
+ stdinMode: {
406
+ omitPrompt: true,
407
+ extraArgs: ["--input-format", "stream-json"]
408
+ },
409
+ interactive: {
410
+ defaultArgs: [],
411
+ promptFlag: "-p"
412
+ },
413
+ resumeCommand: (threadId, cwd) => ["--session", threadId, "--work-dir", cwd]
414
+ };
415
+ var kimiAcpSpawnConfig = {
416
+ kind: "acp",
417
+ agentId: "kimi",
418
+ acpArgs: ["acp"]
419
+ };
420
+
421
+ // packages/agent-spawn/src/configs/goose.ts
422
+ var gooseSpawnConfig = {
423
+ kind: "cli",
424
+ agentId: "goose",
425
+ adapter: "native",
426
+ promptFlag: "--text",
427
+ modelFlag: "--model",
428
+ modelStripProviderPrefix: false,
429
+ defaultArgs: ["run", "--output-format", "stream-json"],
430
+ defaultArgsPosition: "beforePrompt",
431
+ mcpArgs: serializeGooseMcpArgs,
432
+ mcpArgsPosition: "beforePrompt",
433
+ modes: {
434
+ yolo: { env: { GOOSE_MODE: "auto" } },
435
+ edit: { env: { GOOSE_MODE: "smart_approve" } },
436
+ read: { env: { GOOSE_MODE: "chat" } }
437
+ },
438
+ stdinMode: {
439
+ omitPrompt: true,
440
+ extraArgs: ["--instructions", "-"]
441
+ },
442
+ interactive: {
443
+ defaultArgs: ["session"],
444
+ defaultArgsPosition: "beforePrompt"
445
+ },
446
+ resumeCommand: () => ["run", "--resume", "--text", "continue"]
447
+ };
448
+ var gooseAcpSpawnConfig = {
449
+ kind: "acp",
450
+ agentId: "goose",
451
+ acpArgs: ["acp"],
452
+ skipAuth: true
453
+ };
454
+
455
+ // packages/agent-spawn/src/configs/index.ts
456
+ var allSpawnConfigs = [
457
+ claudeCodeSpawnConfig,
458
+ codexSpawnConfig,
459
+ openCodeSpawnConfig,
460
+ kimiSpawnConfig,
461
+ gooseSpawnConfig
462
+ ];
463
+ var lookup2 = /* @__PURE__ */ new Map();
464
+ for (const config of allSpawnConfigs) {
465
+ lookup2.set(config.agentId, config);
466
+ }
467
+ var acpLookup = /* @__PURE__ */ new Map();
468
+ acpLookup.set(openCodeAcpSpawnConfig.agentId, openCodeAcpSpawnConfig);
469
+ acpLookup.set(kimiAcpSpawnConfig.agentId, kimiAcpSpawnConfig);
470
+ acpLookup.set(gooseAcpSpawnConfig.agentId, gooseAcpSpawnConfig);
471
+
472
+ // packages/agent-spawn/src/spawn.ts
473
+ import { spawn as spawnChildProcess } from "node:child_process";
474
+
475
+ // packages/agent-spawn/src/spawn-interactive.ts
476
+ import { spawn as spawnChildProcess2 } from "node:child_process";
477
+
478
+ // packages/design-system/src/tokens/colors.ts
479
+ import chalk from "chalk";
480
+ var dark = {
481
+ header: (text4) => chalk.magentaBright.bold(text4),
482
+ divider: (text4) => chalk.dim(text4),
483
+ prompt: (text4) => chalk.cyan(text4),
484
+ number: (text4) => chalk.cyanBright(text4),
485
+ intro: (text4) => chalk.bgMagenta.white(` Poe - ${text4} `),
486
+ resolvedSymbol: chalk.magenta("\u25C7"),
487
+ errorSymbol: chalk.red("\u25A0"),
488
+ accent: (text4) => chalk.cyan(text4),
489
+ muted: (text4) => chalk.dim(text4),
490
+ success: (text4) => chalk.green(text4),
491
+ warning: (text4) => chalk.yellow(text4),
492
+ error: (text4) => chalk.red(text4),
493
+ info: (text4) => chalk.magenta(text4),
494
+ badge: (text4) => chalk.bgYellow.black(` ${text4} `)
495
+ };
496
+ var light = {
497
+ header: (text4) => chalk.hex("#a200ff").bold(text4),
498
+ divider: (text4) => chalk.hex("#666666")(text4),
499
+ prompt: (text4) => chalk.hex("#006699").bold(text4),
500
+ number: (text4) => chalk.hex("#0077cc").bold(text4),
501
+ intro: (text4) => chalk.bgHex("#a200ff").white(` Poe - ${text4} `),
502
+ resolvedSymbol: chalk.hex("#a200ff")("\u25C7"),
503
+ errorSymbol: chalk.hex("#cc0000")("\u25A0"),
504
+ accent: (text4) => chalk.hex("#006699").bold(text4),
505
+ muted: (text4) => chalk.hex("#666666")(text4),
506
+ success: (text4) => chalk.hex("#008800")(text4),
507
+ warning: (text4) => chalk.hex("#cc6600")(text4),
508
+ error: (text4) => chalk.hex("#cc0000")(text4),
509
+ info: (text4) => chalk.hex("#a200ff")(text4),
510
+ badge: (text4) => chalk.bgHex("#cc6600").white(` ${text4} `)
511
+ };
512
+
513
+ // packages/design-system/src/tokens/typography.ts
514
+ import chalk2 from "chalk";
515
+
516
+ // packages/design-system/src/components/text.ts
517
+ import chalk3 from "chalk";
518
+
519
+ // packages/design-system/src/internal/output-format.ts
520
+ import { AsyncLocalStorage } from "node:async_hooks";
521
+ var VALID_FORMATS = /* @__PURE__ */ new Set(["terminal", "markdown", "json"]);
522
+ var formatStorage = new AsyncLocalStorage();
523
+ var cached;
524
+ function resolveOutputFormat(env = process.env) {
525
+ const scoped = formatStorage.getStore();
526
+ if (scoped) {
527
+ return scoped;
528
+ }
529
+ if (cached) {
530
+ return cached;
531
+ }
532
+ const raw = env.OUTPUT_FORMAT?.toLowerCase();
533
+ cached = VALID_FORMATS.has(raw) ? raw : "terminal";
534
+ return cached;
535
+ }
536
+
537
+ // packages/design-system/src/internal/theme-detect.ts
538
+ function detectThemeFromEnv(env) {
539
+ const apple = env.APPLE_INTERFACE_STYLE;
540
+ if (typeof apple === "string") {
541
+ return apple.toLowerCase() === "dark" ? "dark" : "light";
542
+ }
543
+ const vscodeKind = env.VSCODE_COLOR_THEME_KIND;
544
+ if (typeof vscodeKind === "string") {
545
+ const normalized = vscodeKind.toLowerCase();
546
+ if (normalized.includes("light")) {
547
+ return "light";
548
+ }
549
+ if (normalized.includes("dark")) {
550
+ return "dark";
551
+ }
552
+ }
553
+ const colorFGBG = env.COLORFGBG;
554
+ if (typeof colorFGBG === "string") {
555
+ const parts = colorFGBG.split(";").map((part) => Number.parseInt(part, 10));
556
+ const background = parts.at(-1);
557
+ if (Number.isFinite(background)) {
558
+ return background >= 8 ? "light" : "dark";
559
+ }
560
+ }
561
+ return void 0;
562
+ }
563
+ function resolveThemeName(env = process.env) {
564
+ const raw = (env.POE_CODE_THEME ?? env.POE_THEME)?.toLowerCase();
565
+ if (raw === "light" || raw === "dark") {
566
+ return raw;
567
+ }
568
+ const detected = detectThemeFromEnv(env);
569
+ if (detected) {
570
+ return detected;
571
+ }
572
+ return "dark";
573
+ }
574
+ var cachedTheme;
575
+ function getTheme(env) {
576
+ if (cachedTheme) {
577
+ return cachedTheme;
578
+ }
579
+ const themeName = resolveThemeName(env);
580
+ cachedTheme = themeName === "light" ? light : dark;
581
+ return cachedTheme;
582
+ }
583
+
584
+ // packages/design-system/src/components/symbols.ts
585
+ import chalk4 from "chalk";
586
+ var symbols = {
587
+ get info() {
588
+ const format = resolveOutputFormat();
589
+ if (format === "json") return "info";
590
+ if (format === "markdown") return "(i)";
591
+ return chalk4.magenta("\u25CF");
592
+ },
593
+ get success() {
594
+ const format = resolveOutputFormat();
595
+ if (format === "json") return "success";
596
+ if (format === "markdown") return "[ok]";
597
+ return chalk4.magenta("\u25C6");
598
+ },
599
+ get resolved() {
600
+ const format = resolveOutputFormat();
601
+ if (format === "json") return "resolved";
602
+ if (format === "markdown") return ">";
603
+ return getTheme().resolvedSymbol;
604
+ },
605
+ get errorResolved() {
606
+ const format = resolveOutputFormat();
607
+ if (format === "json") return "error";
608
+ if (format === "markdown") return "[!]";
609
+ return getTheme().errorSymbol;
610
+ },
611
+ get bar() {
612
+ const format = resolveOutputFormat();
613
+ if (format === "json") return "";
614
+ if (format === "markdown") return "|";
615
+ return "\u2502";
616
+ },
617
+ cornerTopRight: "\u256E",
618
+ cornerBottomRight: "\u256F",
619
+ get warning() {
620
+ const format = resolveOutputFormat();
621
+ if (format === "json") return "warning";
622
+ if (format === "markdown") return "[!]";
623
+ return "\u25B2";
624
+ },
625
+ get active() {
626
+ const format = resolveOutputFormat();
627
+ if (format === "json") return "active";
628
+ if (format === "markdown") return "[x]";
629
+ return "\u25C6";
630
+ },
631
+ get inactive() {
632
+ const format = resolveOutputFormat();
633
+ if (format === "json") return "inactive";
634
+ if (format === "markdown") return "[ ]";
635
+ return "\u25CB";
636
+ }
637
+ };
638
+
639
+ // packages/design-system/src/components/logger.ts
640
+ import chalk6 from "chalk";
641
+
642
+ // packages/design-system/src/prompts/primitives/log.ts
643
+ import chalk5 from "chalk";
644
+
645
+ // packages/design-system/src/internal/strip-ansi.ts
646
+ function stripAnsi(value) {
647
+ return value.replace(/\u001b\[[0-9;]*m/g, "");
648
+ }
649
+
650
+ // packages/design-system/src/prompts/primitives/log.ts
651
+ function writeTerminalMessage(msg, {
652
+ symbol = chalk5.gray("\u2502"),
653
+ secondarySymbol = chalk5.gray("\u2502"),
654
+ spacing: spacing2 = 1,
655
+ withGuide = true
656
+ } = {}) {
657
+ const lines = [];
658
+ const showGuide = withGuide !== false;
659
+ const contentLines = msg.split("\n");
660
+ const prefix = showGuide ? `${symbol} ` : "";
661
+ const continuationPrefix = showGuide ? `${secondarySymbol} ` : "";
662
+ const emptyGuide = showGuide ? secondarySymbol : "";
663
+ for (let index = 0; index < spacing2; index += 1) {
664
+ lines.push(emptyGuide);
665
+ }
666
+ if (contentLines.length === 0) {
667
+ process.stdout.write("\n");
668
+ return;
669
+ }
670
+ const [firstLine = "", ...continuationLines] = contentLines;
671
+ if (firstLine.length > 0) {
672
+ lines.push(`${prefix}${firstLine}`);
673
+ } else {
674
+ lines.push(showGuide ? symbol : "");
675
+ }
676
+ for (const line of continuationLines) {
677
+ if (line.length > 0) {
678
+ lines.push(`${continuationPrefix}${line}`);
679
+ continue;
680
+ }
681
+ lines.push(emptyGuide);
682
+ }
683
+ process.stdout.write(`${lines.join("\n")}
684
+ `);
685
+ }
686
+ function message(msg, options) {
687
+ const format = resolveOutputFormat();
688
+ if (format === "markdown") {
689
+ process.stdout.write(`- ${stripAnsi(msg)}
690
+ `);
691
+ return;
692
+ }
693
+ if (format === "json") {
694
+ process.stdout.write(
695
+ `${JSON.stringify({ level: "message", message: stripAnsi(msg) })}
696
+ `
697
+ );
698
+ return;
699
+ }
700
+ writeTerminalMessage(msg, options);
701
+ }
702
+ function info(msg) {
703
+ const format = resolveOutputFormat();
704
+ if (format === "markdown") {
705
+ process.stdout.write(`- **info:** ${stripAnsi(msg)}
706
+ `);
707
+ return;
708
+ }
709
+ if (format === "json") {
710
+ process.stdout.write(
711
+ `${JSON.stringify({ level: "info", message: stripAnsi(msg) })}
712
+ `
713
+ );
714
+ return;
715
+ }
716
+ message(msg, { symbol: symbols.info });
717
+ }
718
+ function success(msg) {
719
+ const format = resolveOutputFormat();
720
+ if (format === "markdown") {
721
+ process.stdout.write(`- **success:** ${stripAnsi(msg)}
722
+ `);
723
+ return;
724
+ }
725
+ if (format === "json") {
726
+ process.stdout.write(
727
+ `${JSON.stringify({ level: "success", message: stripAnsi(msg) })}
728
+ `
729
+ );
730
+ return;
731
+ }
732
+ message(msg, { symbol: symbols.success });
733
+ }
734
+ function warn(msg) {
735
+ const format = resolveOutputFormat();
736
+ if (format === "markdown") {
737
+ process.stdout.write(`- **warning:** ${stripAnsi(msg)}
738
+ `);
739
+ return;
740
+ }
741
+ if (format === "json") {
742
+ process.stdout.write(
743
+ `${JSON.stringify({ level: "warn", message: stripAnsi(msg) })}
744
+ `
745
+ );
746
+ return;
747
+ }
748
+ message(msg, { symbol: chalk5.yellow("\u25B2") });
749
+ }
750
+ function error(msg) {
751
+ const format = resolveOutputFormat();
752
+ if (format === "markdown") {
753
+ process.stdout.write(`- **error:** ${stripAnsi(msg)}
754
+ `);
755
+ return;
756
+ }
757
+ if (format === "json") {
758
+ process.stdout.write(
759
+ `${JSON.stringify({ level: "error", message: stripAnsi(msg) })}
760
+ `
761
+ );
762
+ return;
763
+ }
764
+ message(msg, { symbol: chalk5.red("\u25A0") });
765
+ }
766
+ var log = {
767
+ info,
768
+ success,
769
+ message,
770
+ warn,
771
+ error
772
+ };
773
+
774
+ // packages/design-system/src/components/logger.ts
775
+ function createLogger(emitter) {
776
+ const emit = (level, message2) => {
777
+ if (emitter) {
778
+ emitter(message2);
779
+ return;
780
+ }
781
+ if (level === "success") {
782
+ log.success(message2);
783
+ return;
784
+ }
785
+ if (level === "warn") {
786
+ log.warn(message2);
787
+ return;
788
+ }
789
+ if (level === "error") {
790
+ log.error(message2);
791
+ return;
792
+ }
793
+ log.info(message2);
794
+ };
795
+ return {
796
+ info(message2) {
797
+ emit("info", message2);
798
+ },
799
+ success(message2) {
800
+ emit("success", message2);
801
+ },
802
+ warn(message2) {
803
+ emit("warn", message2);
804
+ },
805
+ error(message2) {
806
+ emit("error", message2);
807
+ },
808
+ resolved(label, value) {
809
+ if (emitter) {
810
+ emitter(`${label}: ${value}`);
811
+ return;
812
+ }
813
+ log.message(`${label}
814
+ ${value}`, { symbol: symbols.resolved });
815
+ },
816
+ errorResolved(label, value) {
817
+ if (emitter) {
818
+ emitter(`${label}: ${value}`);
819
+ return;
820
+ }
821
+ log.message(`${label}
822
+ ${value}`, { symbol: symbols.errorResolved });
823
+ },
824
+ message(message2, symbol) {
825
+ if (emitter) {
826
+ emitter(message2);
827
+ return;
828
+ }
829
+ log.message(message2, { symbol: symbol ?? chalk6.gray("\u2502") });
830
+ }
831
+ };
832
+ }
833
+ var logger = createLogger();
834
+
835
+ // packages/design-system/src/components/table.ts
836
+ import { Table } from "console-table-printer";
837
+
838
+ // packages/design-system/src/acp/components.ts
839
+ import chalk7 from "chalk";
840
+ var AGENT_PREFIX = `${chalk7.green.bold("\u2713")} agent: `;
841
+
842
+ // packages/design-system/src/dashboard/buffer.ts
843
+ import chalk8 from "chalk";
844
+
845
+ // packages/design-system/src/dashboard/terminal.ts
846
+ import readline from "node:readline";
847
+ import { PassThrough } from "node:stream";
848
+
849
+ // packages/design-system/src/prompts/index.ts
850
+ import chalk15 from "chalk";
851
+ import * as clack from "@clack/prompts";
852
+
853
+ // packages/design-system/src/prompts/primitives/cancel.ts
854
+ import chalk9 from "chalk";
855
+
856
+ // node_modules/@clack/core/dist/index.mjs
857
+ var import_sisteransi = __toESM(require_src(), 1);
858
+ import { stdout as R, stdin as q } from "node:process";
859
+ import * as k from "node:readline";
860
+ import ot from "node:readline";
861
+ import { ReadStream as J } from "node:tty";
862
+ var P = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
863
+ var ct = new RegExp("\\p{M}+", "gu");
864
+ var pt = { limit: 1 / 0, ellipsis: "" };
865
+ var ft = { limit: 1 / 0, ellipsis: "", ellipsisWidth: 0 };
866
+ var j = "\x07";
867
+ var Q = "[";
868
+ var dt = "]";
869
+ var U = `${dt}8;;`;
870
+ var et = new RegExp(`(?:\\${Q}(?<code>\\d+)m|\\${U}(?<uri>.*)${j})`, "y");
871
+ var At = ["up", "down", "left", "right", "space", "enter", "cancel"];
872
+ var _ = { actions: new Set(At), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]), messages: { cancel: "Canceled", error: "Something went wrong" }, withGuide: true };
873
+ var bt = globalThis.process.platform.startsWith("win");
874
+
875
+ // packages/design-system/src/prompts/primitives/intro.ts
876
+ import chalk10 from "chalk";
877
+
878
+ // packages/design-system/src/prompts/primitives/note.ts
879
+ import chalk11 from "chalk";
880
+
881
+ // packages/design-system/src/prompts/primitives/outro.ts
882
+ import chalk12 from "chalk";
883
+
884
+ // packages/design-system/src/prompts/primitives/spinner.ts
885
+ import chalk14 from "chalk";
886
+
887
+ // packages/design-system/src/static/spinner.ts
888
+ import chalk13 from "chalk";
889
+
890
+ // packages/design-system/src/static/menu.ts
891
+ import chalk16 from "chalk";
892
+
893
+ // packages/agent-spawn/src/acp/replay.ts
894
+ import path from "node:path";
895
+ import { homedir } from "node:os";
896
+ import { open, readdir } from "node:fs/promises";
897
+ import { createInterface as createInterface2 } from "node:readline";
898
+
899
+ // packages/agent-spawn/src/acp/spawn.ts
900
+ import { spawn as spawnChildProcess3 } from "node:child_process";
901
+
902
+ // packages/poe-acp-client/src/acp-client.ts
903
+ import { isAbsolute } from "node:path";
904
+
905
+ // packages/poe-acp-client/src/acp-transport.ts
906
+ import {
907
+ spawn as spawnChildProcess4
908
+ } from "node:child_process";
909
+
910
+ // packages/poe-acp-client/src/run-report.ts
911
+ import * as fsPromises from "node:fs/promises";
912
+ import { homedir as homedir2 } from "node:os";
913
+ import { join } from "node:path";
914
+
915
+ // packages/agent-spawn/src/acp/middlewares/spawn-log.ts
916
+ import path2 from "node:path";
917
+ import { homedir as homedir3 } from "node:os";
918
+ import { mkdir, open as open2 } from "node:fs/promises";
919
+
920
+ // src/utils/command-checks.ts
921
+ function formatCommandRunnerResult(result) {
922
+ const stdout = result.stdout.length > 0 ? result.stdout : "<empty>";
923
+ const stderr = result.stderr.length > 0 ? result.stderr : "<empty>";
924
+ return `stdout:
925
+ ${stdout}
926
+ stderr:
927
+ ${stderr}`;
928
+ }
929
+ function describeCommandExpectation(command, args, expectedOutput) {
930
+ return `${renderCommandLine(command, args)} (expecting "${expectedOutput}")`;
931
+ }
932
+ function createCommandExpectationCheck(options) {
933
+ return {
934
+ id: options.id,
935
+ description: describeCommandExpectation(
936
+ options.command,
937
+ options.args,
938
+ options.expectedOutput
939
+ ),
940
+ async run(context) {
941
+ await runAndMatchOutput(context, options);
942
+ }
943
+ };
944
+ }
945
+ async function runAndMatchOutput(context, options) {
946
+ const rendered = renderCommandLine(options.command, options.args);
947
+ if (options.skipOnDryRun !== false && context.isDryRun) {
948
+ if (context.logDryRun) {
949
+ context.logDryRun(
950
+ `Dry run: ${rendered} (expecting "${options.expectedOutput}")`
951
+ );
952
+ }
953
+ return;
954
+ }
955
+ const result = await context.runCommand(options.command, options.args);
956
+ if (result.exitCode !== 0) {
957
+ const detail = formatCommandRunnerResult(result);
958
+ throw new Error(
959
+ [`Command ${rendered} failed with exit code ${result.exitCode}.`, detail].join("\n")
960
+ );
961
+ }
962
+ if (!stdoutMatchesExpected(result.stdout, options.expectedOutput)) {
963
+ const detail = formatCommandRunnerResult(result);
964
+ const received = result.stdout.trim();
965
+ throw new Error(
966
+ [
967
+ `Command ${rendered} failed: expected "${options.expectedOutput}" but received "${received}".`,
968
+ detail
969
+ ].join("\n")
970
+ );
971
+ }
972
+ }
973
+ function stdoutMatchesExpected(stdout, expected) {
974
+ const trimmed = stdout.trim();
975
+ if (trimmed === expected) {
976
+ return true;
977
+ }
978
+ const lines = stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
979
+ if (lines.some((line) => line === expected)) {
980
+ return true;
981
+ }
982
+ for (const line of lines) {
983
+ if (line[0] !== "{") continue;
984
+ try {
985
+ const parsed = JSON.parse(line);
986
+ if (parsed.type === "result" && parsed.result === expected) {
987
+ return true;
988
+ }
989
+ } catch {
990
+ continue;
991
+ }
992
+ }
993
+ return false;
994
+ }
995
+ function renderCommandLine(command, args) {
996
+ return [command, ...args].map(quoteIfNeeded).join(" ").trim();
997
+ }
998
+ function quoteIfNeeded(value) {
999
+ if (value.length === 0) {
1000
+ return '""';
1001
+ }
1002
+ if (needsQuoting(value)) {
1003
+ return `"${value.replaceAll('"', '\\"')}"`;
1004
+ }
1005
+ return value;
1006
+ }
1007
+ function needsQuoting(value) {
1008
+ return value.includes(" ") || value.includes(" ") || value.includes("\n");
1009
+ }
1010
+ function createBinaryExistsCheck(binaryName, id, description) {
1011
+ return {
1012
+ id,
1013
+ description,
1014
+ async run({ runCommand: runCommand2 }) {
1015
+ const commonPaths = [
1016
+ `/usr/local/bin/${binaryName}`,
1017
+ `/usr/bin/${binaryName}`,
1018
+ `$HOME/.local/bin/${binaryName}`,
1019
+ `$HOME/.claude/local/bin/${binaryName}`
1020
+ ];
1021
+ const detectors = [
1022
+ {
1023
+ command: "which",
1024
+ args: [binaryName],
1025
+ validate: (result) => result.exitCode === 0
1026
+ },
1027
+ {
1028
+ command: "where",
1029
+ args: [binaryName],
1030
+ validate: (result) => result.exitCode === 0 && result.stdout.trim().length > 0
1031
+ },
1032
+ // Check common installation paths using shell expansion for $HOME
1033
+ {
1034
+ command: "sh",
1035
+ args: [
1036
+ "-c",
1037
+ commonPaths.map((p) => `test -f "${p}"`).join(" || ")
1038
+ ],
1039
+ validate: (result) => result.exitCode === 0
1040
+ }
1041
+ ];
1042
+ for (const detector of detectors) {
1043
+ const result = await runCommand2(detector.command, detector.args);
1044
+ if (detector.validate(result)) {
1045
+ return;
1046
+ }
1047
+ }
1048
+ throw new Error(`${binaryName} CLI binary not found on PATH.`);
1049
+ }
1050
+ };
1051
+ }
1052
+
1053
+ // packages/config-mutations/src/mutations/config-mutation.ts
1054
+ function merge(options) {
1055
+ return {
1056
+ kind: "configMerge",
1057
+ target: options.target,
1058
+ value: options.value,
1059
+ format: options.format,
1060
+ pruneByPrefix: options.pruneByPrefix,
1061
+ label: options.label
1062
+ };
1063
+ }
1064
+ function prune(options) {
1065
+ return {
1066
+ kind: "configPrune",
1067
+ target: options.target,
1068
+ shape: options.shape,
1069
+ format: options.format,
1070
+ onlyIf: options.onlyIf,
1071
+ label: options.label
1072
+ };
1073
+ }
1074
+ function transform(options) {
1075
+ return {
1076
+ kind: "configTransform",
1077
+ target: options.target,
1078
+ format: options.format,
1079
+ transform: options.transform,
1080
+ label: options.label
1081
+ };
1082
+ }
1083
+ var configMutation = {
1084
+ merge,
1085
+ prune,
1086
+ transform
1087
+ };
1088
+
1089
+ // packages/config-mutations/src/mutations/file-mutation.ts
1090
+ function ensureDirectory(options) {
1091
+ return {
1092
+ kind: "ensureDirectory",
1093
+ path: options.path,
1094
+ label: options.label
1095
+ };
1096
+ }
1097
+ function remove(options) {
1098
+ return {
1099
+ kind: "removeFile",
1100
+ target: options.target,
1101
+ whenEmpty: options.whenEmpty,
1102
+ whenContentMatches: options.whenContentMatches,
1103
+ label: options.label
1104
+ };
1105
+ }
1106
+ function removeDirectory(options) {
1107
+ return {
1108
+ kind: "removeDirectory",
1109
+ path: options.path,
1110
+ force: options.force,
1111
+ label: options.label
1112
+ };
1113
+ }
1114
+ function chmod(options) {
1115
+ return {
1116
+ kind: "chmod",
1117
+ target: options.target,
1118
+ mode: options.mode,
1119
+ label: options.label
1120
+ };
1121
+ }
1122
+ function backup(options) {
1123
+ return {
1124
+ kind: "backup",
1125
+ target: options.target,
1126
+ label: options.label
1127
+ };
1128
+ }
1129
+ var fileMutation = {
1130
+ ensureDirectory,
1131
+ remove,
1132
+ removeDirectory,
1133
+ chmod,
1134
+ backup
1135
+ };
1136
+
1137
+ // packages/config-mutations/src/execution/apply-mutation.ts
1138
+ import Mustache from "mustache";
1139
+
1140
+ // packages/config-mutations/src/formats/json.ts
1141
+ import * as jsonc from "jsonc-parser";
1142
+ function isConfigObject(value) {
1143
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1144
+ }
1145
+ function parse3(content) {
1146
+ if (!content || content.trim() === "") {
1147
+ return {};
1148
+ }
1149
+ const errors = [];
1150
+ const parsed = jsonc.parse(content, errors, {
1151
+ allowTrailingComma: true,
1152
+ disallowComments: false
1153
+ });
1154
+ if (errors.length > 0) {
1155
+ throw new Error(`JSON parse error: ${jsonc.printParseErrorCode(errors[0].error)}`);
1156
+ }
1157
+ if (parsed === null || parsed === void 0) {
1158
+ return {};
1159
+ }
1160
+ if (!isConfigObject(parsed)) {
1161
+ throw new Error("Expected JSON object.");
1162
+ }
1163
+ return parsed;
1164
+ }
1165
+ function serialize(obj) {
1166
+ return `${JSON.stringify(obj, null, 2)}
1167
+ `;
1168
+ }
1169
+ function merge2(base, patch) {
1170
+ const result = { ...base };
1171
+ for (const [key, value] of Object.entries(patch)) {
1172
+ if (value === void 0) {
1173
+ continue;
1174
+ }
1175
+ const existing = result[key];
1176
+ if (isConfigObject(existing) && isConfigObject(value)) {
1177
+ result[key] = merge2(existing, value);
1178
+ continue;
1179
+ }
1180
+ result[key] = value;
1181
+ }
1182
+ return result;
1183
+ }
1184
+ function prune2(obj, shape) {
1185
+ let changed = false;
1186
+ const result = { ...obj };
1187
+ for (const [key, pattern] of Object.entries(shape)) {
1188
+ if (!(key in result)) {
1189
+ continue;
1190
+ }
1191
+ const current = result[key];
1192
+ if (isConfigObject(pattern) && Object.keys(pattern).length === 0) {
1193
+ delete result[key];
1194
+ changed = true;
1195
+ continue;
1196
+ }
1197
+ if (isConfigObject(pattern) && isConfigObject(current)) {
1198
+ const { changed: childChanged, result: childResult } = prune2(
1199
+ current,
1200
+ pattern
1201
+ );
1202
+ if (childChanged) {
1203
+ changed = true;
1204
+ }
1205
+ if (Object.keys(childResult).length === 0) {
1206
+ delete result[key];
1207
+ } else {
1208
+ result[key] = childResult;
1209
+ }
1210
+ continue;
1211
+ }
1212
+ delete result[key];
1213
+ changed = true;
1214
+ }
1215
+ return { changed, result };
1216
+ }
1217
+ var jsonFormat = {
1218
+ parse: parse3,
1219
+ serialize,
1220
+ merge: merge2,
1221
+ prune: prune2
1222
+ };
1223
+
1224
+ // packages/config-mutations/src/formats/toml.ts
1225
+ import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
1226
+ function isConfigObject2(value) {
1227
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1228
+ }
1229
+ function parse4(content) {
1230
+ if (!content || content.trim() === "") {
1231
+ return {};
1232
+ }
1233
+ const parsed = parseToml(content);
1234
+ if (!isConfigObject2(parsed)) {
1235
+ throw new Error("Expected TOML document to be a table.");
1236
+ }
1237
+ return parsed;
1238
+ }
1239
+ function serialize2(obj) {
1240
+ const serialized = stringifyToml(obj);
1241
+ return serialized.endsWith("\n") ? serialized : `${serialized}
1242
+ `;
1243
+ }
1244
+ function merge3(base, patch) {
1245
+ const result = { ...base };
1246
+ for (const [key, value] of Object.entries(patch)) {
1247
+ if (value === void 0) {
1248
+ continue;
1249
+ }
1250
+ const existing = result[key];
1251
+ if (isConfigObject2(existing) && isConfigObject2(value)) {
1252
+ result[key] = merge3(existing, value);
1253
+ continue;
1254
+ }
1255
+ result[key] = value;
1256
+ }
1257
+ return result;
1258
+ }
1259
+ function prune3(obj, shape) {
1260
+ let changed = false;
1261
+ const result = { ...obj };
1262
+ for (const [key, pattern] of Object.entries(shape)) {
1263
+ if (!(key in result)) {
1264
+ continue;
1265
+ }
1266
+ const current = result[key];
1267
+ if (isConfigObject2(pattern) && Object.keys(pattern).length === 0) {
1268
+ delete result[key];
1269
+ changed = true;
1270
+ continue;
1271
+ }
1272
+ if (isConfigObject2(pattern) && isConfigObject2(current)) {
1273
+ const { changed: childChanged, result: childResult } = prune3(
1274
+ current,
1275
+ pattern
1276
+ );
1277
+ if (childChanged) {
1278
+ changed = true;
1279
+ }
1280
+ if (Object.keys(childResult).length === 0) {
1281
+ delete result[key];
1282
+ } else {
1283
+ result[key] = childResult;
1284
+ }
1285
+ continue;
1286
+ }
1287
+ delete result[key];
1288
+ changed = true;
1289
+ }
1290
+ return { changed, result };
1291
+ }
1292
+ var tomlFormat = {
1293
+ parse: parse4,
1294
+ serialize: serialize2,
1295
+ merge: merge3,
1296
+ prune: prune3
1297
+ };
1298
+
1299
+ // packages/config-mutations/src/formats/yaml.ts
1300
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
1301
+ function isConfigObject3(value) {
1302
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1303
+ }
1304
+ function parse5(content) {
1305
+ if (!content || content.trim() === "") {
1306
+ return {};
1307
+ }
1308
+ const parsed = parseYaml(content);
1309
+ if (parsed === null || parsed === void 0) {
1310
+ return {};
1311
+ }
1312
+ if (!isConfigObject3(parsed)) {
1313
+ throw new Error("Expected YAML object.");
1314
+ }
1315
+ return parsed;
1316
+ }
1317
+ function serialize3(obj) {
1318
+ const serialized = stringifyYaml(obj);
1319
+ return serialized.endsWith("\n") ? serialized : `${serialized}
1320
+ `;
1321
+ }
1322
+ function merge4(base, patch) {
1323
+ const result = { ...base };
1324
+ for (const [key, value] of Object.entries(patch)) {
1325
+ if (value === void 0) {
1326
+ continue;
1327
+ }
1328
+ const existing = result[key];
1329
+ if (isConfigObject3(existing) && isConfigObject3(value)) {
1330
+ result[key] = merge4(existing, value);
1331
+ continue;
1332
+ }
1333
+ result[key] = value;
1334
+ }
1335
+ return result;
1336
+ }
1337
+ function prune4(obj, shape) {
1338
+ let changed = false;
1339
+ const result = { ...obj };
1340
+ for (const [key, pattern] of Object.entries(shape)) {
1341
+ if (!(key in result)) {
1342
+ continue;
1343
+ }
1344
+ const current = result[key];
1345
+ if (isConfigObject3(pattern) && Object.keys(pattern).length === 0) {
1346
+ delete result[key];
1347
+ changed = true;
1348
+ continue;
1349
+ }
1350
+ if (isConfigObject3(pattern) && isConfigObject3(current)) {
1351
+ const { changed: childChanged, result: childResult } = prune4(current, pattern);
1352
+ if (childChanged) {
1353
+ changed = true;
1354
+ }
1355
+ if (Object.keys(childResult).length === 0) {
1356
+ delete result[key];
1357
+ } else {
1358
+ result[key] = childResult;
1359
+ }
1360
+ continue;
1361
+ }
1362
+ delete result[key];
1363
+ changed = true;
1364
+ }
1365
+ return { changed, result };
1366
+ }
1367
+ var yamlFormat = {
1368
+ parse: parse5,
1369
+ serialize: serialize3,
1370
+ merge: merge4,
1371
+ prune: prune4
1372
+ };
1373
+
1374
+ // packages/config-mutations/src/formats/index.ts
1375
+ var formatRegistry = {
1376
+ json: jsonFormat,
1377
+ toml: tomlFormat,
1378
+ yaml: yamlFormat
1379
+ };
1380
+ var extensionMap = {
1381
+ ".json": "json",
1382
+ ".toml": "toml",
1383
+ ".yaml": "yaml",
1384
+ ".yml": "yaml"
1385
+ };
1386
+ function getConfigFormat(pathOrFormat) {
1387
+ if (pathOrFormat in formatRegistry) {
1388
+ return formatRegistry[pathOrFormat];
1389
+ }
1390
+ const ext = getExtension(pathOrFormat);
1391
+ const formatName = extensionMap[ext];
1392
+ if (!formatName) {
1393
+ throw new Error(
1394
+ `Unsupported config format. Cannot detect format from "${pathOrFormat}". Supported extensions: ${Object.keys(extensionMap).join(", ")}. Supported format names: ${Object.keys(formatRegistry).join(", ")}.`
1395
+ );
1396
+ }
1397
+ return formatRegistry[formatName];
1398
+ }
1399
+ function detectFormat(path4) {
1400
+ const ext = getExtension(path4);
1401
+ return extensionMap[ext];
1402
+ }
1403
+ function getExtension(path4) {
1404
+ const lastDot = path4.lastIndexOf(".");
1405
+ if (lastDot === -1) {
1406
+ return "";
1407
+ }
1408
+ return path4.slice(lastDot).toLowerCase();
1409
+ }
1410
+
1411
+ // packages/config-mutations/src/execution/path-utils.ts
1412
+ import path3 from "node:path";
1413
+ function expandHome(targetPath, homeDir) {
1414
+ if (!targetPath?.startsWith("~")) {
1415
+ return targetPath;
1416
+ }
1417
+ if (targetPath.startsWith("~./")) {
1418
+ targetPath = `~/.${targetPath.slice(3)}`;
1419
+ }
1420
+ let remainder = targetPath.slice(1);
1421
+ if (remainder.startsWith("/") || remainder.startsWith("\\")) {
1422
+ remainder = remainder.slice(1);
1423
+ } else if (remainder.startsWith(".")) {
1424
+ remainder = remainder.slice(1);
1425
+ if (remainder.startsWith("/") || remainder.startsWith("\\")) {
1426
+ remainder = remainder.slice(1);
1427
+ }
1428
+ }
1429
+ return remainder.length === 0 ? homeDir : path3.join(homeDir, remainder);
1430
+ }
1431
+ function validateHomePath(targetPath) {
1432
+ if (typeof targetPath !== "string" || targetPath.length === 0) {
1433
+ throw new Error("Target path must be a non-empty string.");
1434
+ }
1435
+ if (!targetPath.startsWith("~")) {
1436
+ throw new Error(
1437
+ `All target paths must be home-relative (start with ~). Received: "${targetPath}"`
1438
+ );
1439
+ }
1440
+ }
1441
+ function resolvePath(rawPath, homeDir, pathMapper) {
1442
+ validateHomePath(rawPath);
1443
+ const expanded = expandHome(rawPath, homeDir);
1444
+ if (!pathMapper) {
1445
+ return expanded;
1446
+ }
1447
+ const rawDirectory = path3.dirname(expanded);
1448
+ const mappedDirectory = pathMapper.mapTargetDirectory({
1449
+ targetDirectory: rawDirectory
1450
+ });
1451
+ const filename = path3.basename(expanded);
1452
+ return filename.length === 0 ? mappedDirectory : path3.join(mappedDirectory, filename);
1453
+ }
1454
+
1455
+ // packages/config-mutations/src/fs-utils.ts
1456
+ function isNotFound(error2) {
1457
+ return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
1458
+ }
1459
+ async function readFileIfExists(fs, target) {
1460
+ try {
1461
+ return await fs.readFile(target, "utf8");
1462
+ } catch (error2) {
1463
+ if (isNotFound(error2)) {
1464
+ return null;
1465
+ }
1466
+ throw error2;
1467
+ }
1468
+ }
1469
+ async function pathExists(fs, target) {
1470
+ try {
1471
+ await fs.stat(target);
1472
+ return true;
1473
+ } catch (error2) {
1474
+ if (isNotFound(error2)) {
1475
+ return false;
1476
+ }
1477
+ throw error2;
1478
+ }
1479
+ }
1480
+ function createTimestamp() {
1481
+ return (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-").replaceAll(".", "-");
1482
+ }
1483
+
1484
+ // packages/config-mutations/src/execution/apply-mutation.ts
1485
+ function resolveValue(resolver, options) {
1486
+ if (typeof resolver === "function") {
1487
+ return resolver(options);
1488
+ }
1489
+ return resolver;
1490
+ }
1491
+ function createInvalidDocumentBackupPath(targetPath) {
1492
+ const ext = targetPath.includes(".") ? targetPath.split(".").pop() : "bak";
1493
+ return `${targetPath}.invalid-${createTimestamp()}.${ext}`;
1494
+ }
1495
+ async function backupInvalidDocument(fs, targetPath, content) {
1496
+ const backupPath = createInvalidDocumentBackupPath(targetPath);
1497
+ await fs.writeFile(backupPath, content, { encoding: "utf8" });
1498
+ }
1499
+ function describeMutation(kind, targetPath) {
1500
+ const displayPath = targetPath ?? "target";
1501
+ switch (kind) {
1502
+ case "ensureDirectory":
1503
+ return `Create ${displayPath}`;
1504
+ case "removeDirectory":
1505
+ return `Remove directory ${displayPath}`;
1506
+ case "backup":
1507
+ return `Backup ${displayPath}`;
1508
+ case "templateWrite":
1509
+ return `Write ${displayPath}`;
1510
+ case "chmod":
1511
+ return `Set permissions on ${displayPath}`;
1512
+ case "removeFile":
1513
+ return `Remove ${displayPath}`;
1514
+ case "configMerge":
1515
+ case "configPrune":
1516
+ case "configTransform":
1517
+ case "templateMergeToml":
1518
+ case "templateMergeJson":
1519
+ return `Update ${displayPath}`;
1520
+ default:
1521
+ return "Operation";
1522
+ }
1523
+ }
1524
+ function pruneKeysByPrefix(table, prefix) {
1525
+ const result = {};
1526
+ for (const [key, value] of Object.entries(table)) {
1527
+ if (!key.startsWith(prefix)) {
1528
+ result[key] = value;
1529
+ }
1530
+ }
1531
+ return result;
1532
+ }
1533
+ function isConfigObject4(value) {
1534
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1535
+ }
1536
+ function mergeWithPruneByPrefix(base, patch, pruneByPrefix) {
1537
+ const result = { ...base };
1538
+ const prefixMap = pruneByPrefix ?? {};
1539
+ for (const [key, value] of Object.entries(patch)) {
1540
+ const current = result[key];
1541
+ const prefix = prefixMap[key];
1542
+ if (isConfigObject4(current) && isConfigObject4(value)) {
1543
+ if (prefix) {
1544
+ const pruned = pruneKeysByPrefix(current, prefix);
1545
+ result[key] = { ...pruned, ...value };
1546
+ } else {
1547
+ result[key] = mergeWithPruneByPrefix(
1548
+ current,
1549
+ value,
1550
+ prefixMap
1551
+ );
1552
+ }
1553
+ continue;
1554
+ }
1555
+ result[key] = value;
1556
+ }
1557
+ return result;
1558
+ }
1559
+ async function applyMutation(mutation, context, options) {
1560
+ switch (mutation.kind) {
1561
+ case "ensureDirectory":
1562
+ return applyEnsureDirectory(mutation, context, options);
1563
+ case "removeDirectory":
1564
+ return applyRemoveDirectory(mutation, context, options);
1565
+ case "removeFile":
1566
+ return applyRemoveFile(mutation, context, options);
1567
+ case "chmod":
1568
+ return applyChmod(mutation, context, options);
1569
+ case "backup":
1570
+ return applyBackup(mutation, context, options);
1571
+ case "configMerge":
1572
+ return applyConfigMerge(mutation, context, options);
1573
+ case "configPrune":
1574
+ return applyConfigPrune(mutation, context, options);
1575
+ case "configTransform":
1576
+ return applyConfigTransform(mutation, context, options);
1577
+ case "templateWrite":
1578
+ return applyTemplateWrite(mutation, context, options);
1579
+ case "templateMergeToml":
1580
+ return applyTemplateMerge(mutation, context, options, "toml");
1581
+ case "templateMergeJson":
1582
+ return applyTemplateMerge(mutation, context, options, "json");
1583
+ default: {
1584
+ const never = mutation;
1585
+ throw new Error(`Unknown mutation kind: ${never.kind}`);
1586
+ }
1587
+ }
1588
+ }
1589
+ async function applyEnsureDirectory(mutation, context, options) {
1590
+ const rawPath = resolveValue(mutation.path, options);
1591
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1592
+ const details = {
1593
+ kind: mutation.kind,
1594
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1595
+ targetPath
1596
+ };
1597
+ const existed = await pathExists(context.fs, targetPath);
1598
+ if (!context.dryRun) {
1599
+ await context.fs.mkdir(targetPath, { recursive: true });
1600
+ }
1601
+ return {
1602
+ outcome: {
1603
+ changed: !existed,
1604
+ effect: "mkdir",
1605
+ detail: existed ? "noop" : "create"
1606
+ },
1607
+ details
1608
+ };
1609
+ }
1610
+ async function applyRemoveDirectory(mutation, context, options) {
1611
+ const rawPath = resolveValue(mutation.path, options);
1612
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1613
+ const details = {
1614
+ kind: mutation.kind,
1615
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1616
+ targetPath
1617
+ };
1618
+ const existed = await pathExists(context.fs, targetPath);
1619
+ if (!existed) {
1620
+ return {
1621
+ outcome: { changed: false, effect: "none", detail: "noop" },
1622
+ details
1623
+ };
1624
+ }
1625
+ if (typeof context.fs.rm !== "function") {
1626
+ return {
1627
+ outcome: { changed: false, effect: "none", detail: "noop" },
1628
+ details
1629
+ };
1630
+ }
1631
+ if (mutation.force) {
1632
+ if (!context.dryRun) {
1633
+ await context.fs.rm(targetPath, { recursive: true, force: true });
1634
+ }
1635
+ return {
1636
+ outcome: { changed: true, effect: "delete", detail: "delete" },
1637
+ details
1638
+ };
1639
+ }
1640
+ const entries = await context.fs.readdir(targetPath);
1641
+ if (entries.length > 0) {
1642
+ return {
1643
+ outcome: { changed: false, effect: "none", detail: "noop" },
1644
+ details
1645
+ };
1646
+ }
1647
+ if (!context.dryRun) {
1648
+ await context.fs.rm(targetPath, { recursive: true, force: true });
1649
+ }
1650
+ return {
1651
+ outcome: { changed: true, effect: "delete", detail: "delete" },
1652
+ details
1653
+ };
1654
+ }
1655
+ async function applyRemoveFile(mutation, context, options) {
1656
+ const rawPath = resolveValue(mutation.target, options);
1657
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1658
+ const details = {
1659
+ kind: mutation.kind,
1660
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1661
+ targetPath
1662
+ };
1663
+ try {
1664
+ const content = await context.fs.readFile(targetPath, "utf8");
1665
+ const trimmed = content.trim();
1666
+ if (mutation.whenContentMatches && !mutation.whenContentMatches.test(trimmed)) {
1667
+ return {
1668
+ outcome: { changed: false, effect: "none", detail: "noop" },
1669
+ details
1670
+ };
1671
+ }
1672
+ if (mutation.whenEmpty && trimmed.length > 0) {
1673
+ return {
1674
+ outcome: { changed: false, effect: "none", detail: "noop" },
1675
+ details
1676
+ };
1677
+ }
1678
+ if (!context.dryRun) {
1679
+ await context.fs.unlink(targetPath);
1680
+ }
1681
+ return {
1682
+ outcome: { changed: true, effect: "delete", detail: "delete" },
1683
+ details
1684
+ };
1685
+ } catch (error2) {
1686
+ if (isNotFound(error2)) {
1687
+ return {
1688
+ outcome: { changed: false, effect: "none", detail: "noop" },
1689
+ details
1690
+ };
1691
+ }
1692
+ throw error2;
1693
+ }
1694
+ }
1695
+ async function applyChmod(mutation, context, options) {
1696
+ const rawPath = resolveValue(mutation.target, options);
1697
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1698
+ const details = {
1699
+ kind: mutation.kind,
1700
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1701
+ targetPath
1702
+ };
1703
+ if (typeof context.fs.chmod !== "function") {
1704
+ return {
1705
+ outcome: { changed: false, effect: "none", detail: "noop" },
1706
+ details
1707
+ };
1708
+ }
1709
+ try {
1710
+ const stat = await context.fs.stat(targetPath);
1711
+ const currentMode = typeof stat.mode === "number" ? stat.mode & 511 : null;
1712
+ if (currentMode === mutation.mode) {
1713
+ return {
1714
+ outcome: { changed: false, effect: "none", detail: "noop" },
1715
+ details
1716
+ };
1717
+ }
1718
+ if (!context.dryRun) {
1719
+ await context.fs.chmod(targetPath, mutation.mode);
1720
+ }
1721
+ return {
1722
+ outcome: { changed: true, effect: "chmod", detail: "update" },
1723
+ details
1724
+ };
1725
+ } catch (error2) {
1726
+ if (isNotFound(error2)) {
1727
+ return {
1728
+ outcome: { changed: false, effect: "none", detail: "noop" },
1729
+ details
1730
+ };
1731
+ }
1732
+ throw error2;
1733
+ }
1734
+ }
1735
+ async function applyBackup(mutation, context, options) {
1736
+ const rawPath = resolveValue(mutation.target, options);
1737
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1738
+ const details = {
1739
+ kind: mutation.kind,
1740
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1741
+ targetPath
1742
+ };
1743
+ const content = await readFileIfExists(context.fs, targetPath);
1744
+ if (content === null) {
1745
+ return {
1746
+ outcome: { changed: false, effect: "none", detail: "noop" },
1747
+ details
1748
+ };
1749
+ }
1750
+ if (!context.dryRun) {
1751
+ const backupPath = `${targetPath}.backup-${createTimestamp()}`;
1752
+ await context.fs.writeFile(backupPath, content, { encoding: "utf8" });
1753
+ }
1754
+ return {
1755
+ outcome: { changed: true, effect: "copy", detail: "backup" },
1756
+ details
1757
+ };
1758
+ }
1759
+ async function applyConfigMerge(mutation, context, options) {
1760
+ const rawPath = resolveValue(mutation.target, options);
1761
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1762
+ const details = {
1763
+ kind: mutation.kind,
1764
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1765
+ targetPath
1766
+ };
1767
+ const formatName = mutation.format ?? detectFormat(rawPath);
1768
+ if (!formatName) {
1769
+ throw new Error(
1770
+ `Cannot detect config format for "${rawPath}". Provide explicit format option.`
1771
+ );
1772
+ }
1773
+ const format = getConfigFormat(formatName);
1774
+ const rawContent = await readFileIfExists(context.fs, targetPath);
1775
+ let current;
1776
+ try {
1777
+ current = rawContent === null ? {} : format.parse(rawContent);
1778
+ } catch {
1779
+ if (rawContent !== null) {
1780
+ await backupInvalidDocument(context.fs, targetPath, rawContent);
1781
+ }
1782
+ current = {};
1783
+ }
1784
+ const value = resolveValue(mutation.value, options);
1785
+ let merged;
1786
+ if (mutation.pruneByPrefix) {
1787
+ merged = mergeWithPruneByPrefix(current, value, mutation.pruneByPrefix);
1788
+ } else {
1789
+ merged = format.merge(current, value);
1790
+ }
1791
+ const serialized = format.serialize(merged);
1792
+ const changed = serialized !== rawContent;
1793
+ if (changed && !context.dryRun) {
1794
+ await context.fs.writeFile(targetPath, serialized, { encoding: "utf8" });
1795
+ }
1796
+ return {
1797
+ outcome: {
1798
+ changed,
1799
+ effect: changed ? "write" : "none",
1800
+ detail: changed ? rawContent === null ? "create" : "update" : "noop"
1801
+ },
1802
+ details
1803
+ };
1804
+ }
1805
+ async function applyConfigPrune(mutation, context, options) {
1806
+ const rawPath = resolveValue(mutation.target, options);
1807
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1808
+ const details = {
1809
+ kind: mutation.kind,
1810
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1811
+ targetPath
1812
+ };
1813
+ const rawContent = await readFileIfExists(context.fs, targetPath);
1814
+ if (rawContent === null) {
1815
+ return {
1816
+ outcome: { changed: false, effect: "none", detail: "noop" },
1817
+ details
1818
+ };
1819
+ }
1820
+ const formatName = mutation.format ?? detectFormat(rawPath);
1821
+ if (!formatName) {
1822
+ throw new Error(
1823
+ `Cannot detect config format for "${rawPath}". Provide explicit format option.`
1824
+ );
1825
+ }
1826
+ const format = getConfigFormat(formatName);
1827
+ let current;
1828
+ try {
1829
+ current = format.parse(rawContent);
1830
+ } catch {
1831
+ return {
1832
+ outcome: { changed: false, effect: "none", detail: "noop" },
1833
+ details
1834
+ };
1835
+ }
1836
+ if (mutation.onlyIf && !mutation.onlyIf(current, options)) {
1837
+ return {
1838
+ outcome: { changed: false, effect: "none", detail: "noop" },
1839
+ details
1840
+ };
1841
+ }
1842
+ const shape = resolveValue(mutation.shape, options);
1843
+ const { changed, result } = format.prune(current, shape);
1844
+ if (!changed) {
1845
+ return {
1846
+ outcome: { changed: false, effect: "none", detail: "noop" },
1847
+ details
1848
+ };
1849
+ }
1850
+ if (Object.keys(result).length === 0) {
1851
+ if (!context.dryRun) {
1852
+ await context.fs.unlink(targetPath);
1853
+ }
1854
+ return {
1855
+ outcome: { changed: true, effect: "delete", detail: "delete" },
1856
+ details
1857
+ };
1858
+ }
1859
+ const serialized = format.serialize(result);
1860
+ if (!context.dryRun) {
1861
+ await context.fs.writeFile(targetPath, serialized, { encoding: "utf8" });
1862
+ }
1863
+ return {
1864
+ outcome: { changed: true, effect: "write", detail: "update" },
1865
+ details
1866
+ };
1867
+ }
1868
+ async function applyConfigTransform(mutation, context, options) {
1869
+ const rawPath = resolveValue(mutation.target, options);
1870
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1871
+ const details = {
1872
+ kind: mutation.kind,
1873
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1874
+ targetPath
1875
+ };
1876
+ const formatName = mutation.format ?? detectFormat(rawPath);
1877
+ if (!formatName) {
1878
+ throw new Error(
1879
+ `Cannot detect config format for "${rawPath}". Provide explicit format option.`
1880
+ );
1881
+ }
1882
+ const format = getConfigFormat(formatName);
1883
+ const rawContent = await readFileIfExists(context.fs, targetPath);
1884
+ let current;
1885
+ try {
1886
+ current = rawContent === null ? {} : format.parse(rawContent);
1887
+ } catch {
1888
+ if (rawContent !== null) {
1889
+ await backupInvalidDocument(context.fs, targetPath, rawContent);
1890
+ }
1891
+ current = {};
1892
+ }
1893
+ const { content: transformed, changed } = mutation.transform(current, options);
1894
+ if (!changed) {
1895
+ return {
1896
+ outcome: { changed: false, effect: "none", detail: "noop" },
1897
+ details
1898
+ };
1899
+ }
1900
+ if (transformed === null) {
1901
+ if (rawContent === null) {
1902
+ return {
1903
+ outcome: { changed: false, effect: "none", detail: "noop" },
1904
+ details
1905
+ };
1906
+ }
1907
+ if (!context.dryRun) {
1908
+ await context.fs.unlink(targetPath);
1909
+ }
1910
+ return {
1911
+ outcome: { changed: true, effect: "delete", detail: "delete" },
1912
+ details
1913
+ };
1914
+ }
1915
+ const serialized = format.serialize(transformed);
1916
+ if (!context.dryRun) {
1917
+ await context.fs.writeFile(targetPath, serialized, { encoding: "utf8" });
1918
+ }
1919
+ return {
1920
+ outcome: {
1921
+ changed: true,
1922
+ effect: "write",
1923
+ detail: rawContent === null ? "create" : "update"
1924
+ },
1925
+ details
1926
+ };
1927
+ }
1928
+ async function applyTemplateWrite(mutation, context, options) {
1929
+ if (!context.templates) {
1930
+ throw new Error(
1931
+ "Template mutations require a templates loader. Provide templates function to runMutations context."
1932
+ );
1933
+ }
1934
+ const rawPath = resolveValue(mutation.target, options);
1935
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1936
+ const details = {
1937
+ kind: mutation.kind,
1938
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1939
+ targetPath
1940
+ };
1941
+ const template = await context.templates(mutation.templateId);
1942
+ const templateContext = mutation.context ? resolveValue(mutation.context, options) : {};
1943
+ const rendered = Mustache.render(template, templateContext);
1944
+ const existed = await pathExists(context.fs, targetPath);
1945
+ if (!context.dryRun) {
1946
+ await context.fs.writeFile(targetPath, rendered, { encoding: "utf8" });
1947
+ }
1948
+ return {
1949
+ outcome: {
1950
+ changed: true,
1951
+ effect: "write",
1952
+ detail: existed ? "update" : "create"
1953
+ },
1954
+ details
1955
+ };
1956
+ }
1957
+ async function applyTemplateMerge(mutation, context, options, formatName) {
1958
+ if (!context.templates) {
1959
+ throw new Error(
1960
+ "Template mutations require a templates loader. Provide templates function to runMutations context."
1961
+ );
1962
+ }
1963
+ const rawPath = resolveValue(mutation.target, options);
1964
+ const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);
1965
+ const details = {
1966
+ kind: mutation.kind,
1967
+ label: mutation.label ?? describeMutation(mutation.kind, targetPath),
1968
+ targetPath
1969
+ };
1970
+ const format = getConfigFormat(formatName);
1971
+ const template = await context.templates(mutation.templateId);
1972
+ const templateContext = mutation.context ? resolveValue(mutation.context, options) : {};
1973
+ const rendered = Mustache.render(template, templateContext);
1974
+ let templateDoc;
1975
+ try {
1976
+ templateDoc = format.parse(rendered);
1977
+ } catch (error2) {
1978
+ throw new Error(
1979
+ `Failed to parse rendered template "${mutation.templateId}" as ${formatName.toUpperCase()}: ${error2}`,
1980
+ { cause: error2 }
1981
+ );
1982
+ }
1983
+ const rawContent = await readFileIfExists(context.fs, targetPath);
1984
+ let current;
1985
+ try {
1986
+ current = rawContent === null ? {} : format.parse(rawContent);
1987
+ } catch {
1988
+ if (rawContent !== null) {
1989
+ await backupInvalidDocument(context.fs, targetPath, rawContent);
1990
+ }
1991
+ current = {};
1992
+ }
1993
+ const merged = format.merge(current, templateDoc);
1994
+ const serialized = format.serialize(merged);
1995
+ const changed = serialized !== rawContent;
1996
+ if (changed && !context.dryRun) {
1997
+ await context.fs.writeFile(targetPath, serialized, { encoding: "utf8" });
1998
+ }
1999
+ return {
2000
+ outcome: {
2001
+ changed,
2002
+ effect: changed ? "write" : "none",
2003
+ detail: changed ? rawContent === null ? "create" : "update" : "noop"
2004
+ },
2005
+ details
2006
+ };
2007
+ }
2008
+
2009
+ // packages/config-mutations/src/execution/run-mutations.ts
2010
+ async function runMutations(mutations, context, options) {
2011
+ const effects = [];
2012
+ let anyChanged = false;
2013
+ const resolverOptions = options ?? {};
2014
+ for (const mutation of mutations) {
2015
+ const { outcome } = await executeMutation(
2016
+ mutation,
2017
+ context,
2018
+ resolverOptions
2019
+ );
2020
+ effects.push(outcome);
2021
+ if (outcome.changed) {
2022
+ anyChanged = true;
2023
+ }
2024
+ }
2025
+ return {
2026
+ changed: anyChanged,
2027
+ effects
2028
+ };
2029
+ }
2030
+ async function executeMutation(mutation, context, options) {
2031
+ context.observers?.onStart?.({
2032
+ kind: mutation.kind,
2033
+ label: mutation.label ?? mutation.kind,
2034
+ targetPath: void 0
2035
+ // Will be resolved during apply
2036
+ });
2037
+ try {
2038
+ const { outcome, details } = await applyMutation(mutation, context, options);
2039
+ context.observers?.onComplete?.(details, outcome);
2040
+ return { outcome, details };
2041
+ } catch (error2) {
2042
+ context.observers?.onError?.(
2043
+ {
2044
+ kind: mutation.kind,
2045
+ label: mutation.label ?? mutation.kind,
2046
+ targetPath: void 0
2047
+ },
2048
+ error2
2049
+ );
2050
+ throw error2;
2051
+ }
2052
+ }
2053
+
2054
+ // packages/config-mutations/src/template/render.ts
2055
+ import Mustache2 from "mustache";
2056
+ var originalEscape = Mustache2.escape;
2057
+
2058
+ // src/services/service-install.ts
2059
+ async function runServiceInstall(definition, context) {
2060
+ const checkContext = {
2061
+ isDryRun: context.isDryRun,
2062
+ runCommand: context.runCommand
2063
+ };
2064
+ let needsInstall = false;
2065
+ try {
2066
+ await definition.check.run(checkContext);
2067
+ context.logger(`${definition.summary} already installed.`);
2068
+ } catch (error2) {
2069
+ const detail = error2 instanceof Error ? error2.message : String(error2);
2070
+ context.logger(`${definition.summary} not detected: ${detail}`);
2071
+ needsInstall = true;
2072
+ }
2073
+ if (!needsInstall) {
2074
+ return false;
2075
+ }
2076
+ if (context.isDryRun) {
2077
+ logInstallDryRun(definition, context);
2078
+ return true;
2079
+ }
2080
+ const platformSteps = filterStepsByPlatform(definition.steps, context.platform);
2081
+ for (const step of platformSteps) {
2082
+ await runInstallStep(step, context);
2083
+ }
2084
+ await definition.check.run(checkContext);
2085
+ if (definition.postChecks) {
2086
+ for (const postCheck of definition.postChecks) {
2087
+ await postCheck.run(checkContext);
2088
+ }
2089
+ }
2090
+ context.logger(
2091
+ definition.successMessage ?? `${definition.summary} installed.`
2092
+ );
2093
+ return true;
2094
+ }
2095
+ function describeInstallCommand(step) {
2096
+ return `[${step.id}] ${formatCommand2(step.command, step.args)}`;
2097
+ }
2098
+ function formatCommand2(command, args) {
2099
+ return [command, ...args.map(quoteIfNeeded2)].join(" ");
2100
+ }
2101
+ function quoteIfNeeded2(value) {
2102
+ if (value.length === 0) {
2103
+ return '""';
2104
+ }
2105
+ if (value.includes(" ") || value.includes(" ") || value.includes("\n")) {
2106
+ return `"${value.replaceAll('"', '\\"')}"`;
2107
+ }
2108
+ return value;
2109
+ }
2110
+ function filterStepsByPlatform(steps, platform) {
2111
+ return steps.filter(
2112
+ (step) => !step.platforms || step.platforms.includes(platform)
2113
+ );
2114
+ }
2115
+ function logInstallDryRun(definition, context) {
2116
+ context.logger(`Dry run: would install ${definition.summary}.`);
2117
+ const platformSteps = filterStepsByPlatform(definition.steps, context.platform);
2118
+ for (const step of platformSteps) {
2119
+ context.logger(`Dry run: ${describeInstallCommand(step)}`);
2120
+ }
2121
+ }
2122
+ async function runInstallStep(step, context) {
2123
+ context.logger(`Running ${describeInstallCommand(step)}`);
2124
+ const result = await context.runCommand(step.command, step.args);
2125
+ if (result.exitCode !== 0) {
2126
+ const stderr = result.stderr.trim();
2127
+ const suffix = stderr.length > 0 ? `: ${stderr}` : "";
2128
+ throw new Error(
2129
+ `${describeInstallCommand(step)} failed with exit code ${result.exitCode}${suffix}`
2130
+ );
2131
+ }
2132
+ }
2133
+
2134
+ // src/providers/create-provider.ts
2135
+ var templateImports = {
2136
+ "py-poe-spawn/env.hbs": () => Promise.resolve().then(() => __toESM(require_env(), 1)),
2137
+ "py-poe-spawn/main.py.hbs": () => Promise.resolve().then(() => __toESM(require_main_py(), 1)),
2138
+ "py-poe-spawn/requirements.txt.hbs": () => Promise.resolve().then(() => __toESM(require_requirements_txt(), 1)),
2139
+ "codex/config.toml.hbs": () => Promise.resolve().then(() => __toESM(require_config_toml(), 1))
2140
+ };
2141
+ async function loadTemplate(templateId) {
2142
+ const loader = templateImports[templateId];
2143
+ if (!loader) {
2144
+ throw new Error(`Template not found: ${templateId}`);
2145
+ }
2146
+ const module = await loader();
2147
+ return module.default;
2148
+ }
2149
+ function createProvider(opts) {
2150
+ const provider2 = {
2151
+ id: opts.id,
2152
+ summary: opts.summary,
2153
+ name: opts.name,
2154
+ aliases: opts.aliases,
2155
+ label: opts.label,
2156
+ branding: opts.branding,
2157
+ disabled: opts.disabled,
2158
+ supportsStdinPrompt: opts.supportsStdinPrompt,
2159
+ supportsMcpSpawn: opts.supportsMcpSpawn,
2160
+ configurePrompts: opts.configurePrompts,
2161
+ postConfigureMessages: opts.postConfigureMessages,
2162
+ extendConfigurePayload: opts.extendConfigurePayload,
2163
+ isolatedEnv: opts.isolatedEnv,
2164
+ async configure(context, runOptions) {
2165
+ await runMutations(opts.manifest.configure, {
2166
+ fs: context.fs,
2167
+ homeDir: context.env.homeDir,
2168
+ observers: runOptions?.observers,
2169
+ templates: loadTemplate,
2170
+ pathMapper: context.pathMapper
2171
+ }, context.options);
2172
+ context.command.flushDryRun({ emitIfEmpty: false });
2173
+ },
2174
+ async unconfigure(context, runOptions) {
2175
+ if (!opts.manifest.unconfigure) {
2176
+ return false;
2177
+ }
2178
+ const result = await runMutations(opts.manifest.unconfigure, {
2179
+ fs: context.fs,
2180
+ homeDir: context.env.homeDir,
2181
+ observers: runOptions?.observers,
2182
+ templates: loadTemplate,
2183
+ pathMapper: context.pathMapper
2184
+ }, context.options);
2185
+ context.command.flushDryRun({ emitIfEmpty: false });
2186
+ return result.changed;
2187
+ }
2188
+ };
2189
+ if (opts.install) {
2190
+ provider2.install = createInstallRunner(opts.install);
2191
+ }
2192
+ if (opts.test) {
2193
+ provider2.test = opts.test;
2194
+ }
2195
+ if (opts.spawn) {
2196
+ provider2.spawn = opts.spawn;
2197
+ }
2198
+ return provider2;
2199
+ }
2200
+ function createInstallRunner(definition) {
2201
+ return async (context) => {
2202
+ await runServiceInstall(definition, {
2203
+ isDryRun: context.logger.context.dryRun,
2204
+ runCommand: context.command.runCommand,
2205
+ logger: (message2) => context.logger.verbose(message2),
2206
+ platform: context.env.platform
2207
+ });
2208
+ };
2209
+ }
2210
+
2211
+ // src/cli/constants.ts
2212
+ var FRONTIER_MODELS = [
2213
+ "anthropic/claude-opus-4.6",
2214
+ "anthropic/claude-sonnet-4.6",
2215
+ "openai/gpt-5.3-codex",
2216
+ "openai/gpt-5.4",
2217
+ "google/gemini-3.1-pro"
2218
+ ];
2219
+ var DEFAULT_FRONTIER_MODEL = "anthropic/claude-sonnet-4.6";
2220
+ var CLAUDE_CODE_VARIANTS = {
2221
+ haiku: "anthropic/claude-haiku-4.5",
2222
+ sonnet: "anthropic/claude-sonnet-4.6",
2223
+ opus: "anthropic/claude-opus-4.6"
2224
+ };
2225
+ var DEFAULT_CLAUDE_CODE_MODEL = CLAUDE_CODE_VARIANTS.sonnet;
2226
+ function stripModelNamespace2(model) {
2227
+ const slashIndex = model.indexOf("/");
2228
+ const id = slashIndex === -1 ? model : model.slice(slashIndex + 1);
2229
+ return id.toLowerCase();
2230
+ }
2231
+ var CODEX_MODELS = [
2232
+ "openai/gpt-5.4",
2233
+ "openai/gpt-5.3-codex",
2234
+ "openai/gpt-5.3-codex-spark",
2235
+ "openai/gpt-5.2-codex",
2236
+ "openai/gpt-5.2",
2237
+ "openai/gpt-5.2-chat",
2238
+ "openai/gpt-5.2-pro",
2239
+ "openai/gpt-5.1",
2240
+ "openai/gpt-5.1-codex-mini",
2241
+ "anthropic/claude-opus-4.6"
2242
+ ];
2243
+ var DEFAULT_CODEX_MODEL = CODEX_MODELS[0];
2244
+ var KIMI_MODELS = [
2245
+ "novitaai/kimi-k2.5",
2246
+ "novitaai/kimi-k2-thinking",
2247
+ "novitaai/kimi-k2.5-fw"
2248
+ ];
2249
+ var DEFAULT_KIMI_MODEL = KIMI_MODELS[0];
2250
+ var GOOSE_MODELS = FRONTIER_MODELS;
2251
+ var DEFAULT_GOOSE_MODEL = DEFAULT_FRONTIER_MODEL;
2252
+
2253
+ // src/providers/goose.ts
2254
+ var CUSTOM_PROVIDER_ID = "custom_poe";
2255
+ var CUSTOM_PROVIDER_FILE = "~/.config/goose/custom_providers/custom_poe.json";
2256
+ var GOOSE_CONFIG_FILE = "~/.config/goose/config.yaml";
2257
+ var GOOSE_SECRETS_FILE = "~/.config/goose/secrets.yaml";
2258
+ var CUSTOM_PROVIDER_API_KEY_ENV = "CUSTOM_POE_API_KEY";
2259
+ var HEALTH_CHECK_PROMPT = "Reply with exactly: GOOSE_OK";
2260
+ var GOOSE_INSTALL_DEFINITION = {
2261
+ id: "goose",
2262
+ summary: "Goose CLI",
2263
+ check: createBinaryExistsCheck(
2264
+ "goose",
2265
+ "goose-cli-binary",
2266
+ "Goose CLI binary must exist"
2267
+ ),
2268
+ steps: [
2269
+ {
2270
+ id: "install-goose-cli-homebrew-or-script",
2271
+ command: "sh",
2272
+ args: [
2273
+ "-c",
2274
+ [
2275
+ "if command -v brew >/dev/null 2>&1; then",
2276
+ " brew install block-goose-cli || curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash;",
2277
+ "else",
2278
+ " curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash;",
2279
+ "fi"
2280
+ ].join(" ")
2281
+ ],
2282
+ platforms: ["darwin"]
2283
+ },
2284
+ {
2285
+ id: "install-goose-cli-script-unix",
2286
+ command: "sh",
2287
+ args: [
2288
+ "-c",
2289
+ "curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash"
2290
+ ],
2291
+ platforms: ["linux"]
2292
+ },
2293
+ {
2294
+ id: "install-goose-cli-script-windows",
2295
+ command: "powershell",
2296
+ args: [
2297
+ "-Command",
2298
+ "irm https://github.com/block/goose/releases/download/stable/download_cli.ps1 | iex"
2299
+ ],
2300
+ platforms: ["win32"]
2301
+ }
2302
+ ],
2303
+ successMessage: "Installed Goose CLI."
2304
+ };
2305
+ function buildCustomProvider(baseUrl, modelContextLimits = {}) {
2306
+ return {
2307
+ name: CUSTOM_PROVIDER_ID,
2308
+ engine: "openai",
2309
+ display_name: "Poe",
2310
+ description: "Poe OpenAI-compatible API",
2311
+ api_key_env: CUSTOM_PROVIDER_API_KEY_ENV,
2312
+ base_url: `${baseUrl}/chat/completions`,
2313
+ models: GOOSE_MODELS.map((name) => ({
2314
+ name,
2315
+ context_limit: resolveGooseModelContextLimit(name, modelContextLimits)
2316
+ })),
2317
+ supports_streaming: true,
2318
+ requires_auth: true
2319
+ };
2320
+ }
2321
+ function resolveGooseModelContextLimit(model, modelContextLimits) {
2322
+ const stripped = stripModelNamespace2(model);
2323
+ const dynamicValue = modelContextLimits[model] ?? modelContextLimits[stripped];
2324
+ if (typeof dynamicValue === "number" && Number.isFinite(dynamicValue) && dynamicValue > 0) {
2325
+ return dynamicValue;
2326
+ }
2327
+ throw new Error(`Missing Goose model context limit for ${model}.`);
2328
+ }
2329
+ function extractGooseModelContextLimits(response) {
2330
+ const entries = Array.isArray(response.data) ? response.data : [];
2331
+ const wanted = new Map(GOOSE_MODELS.map((model) => [stripModelNamespace2(model), model]));
2332
+ const limits = {};
2333
+ for (const entry of entries) {
2334
+ if (!entry || typeof entry !== "object") {
2335
+ continue;
2336
+ }
2337
+ const rawId = entry.id;
2338
+ const resolvedModel = typeof rawId === "string" ? wanted.get(rawId) : void 0;
2339
+ if (!resolvedModel) {
2340
+ continue;
2341
+ }
2342
+ const rawContextLength = entry.context_window?.context_length;
2343
+ if (typeof rawContextLength !== "number" || !Number.isFinite(rawContextLength) || rawContextLength <= 0) {
2344
+ continue;
2345
+ }
2346
+ limits[resolvedModel] = rawContextLength;
2347
+ }
2348
+ return limits;
2349
+ }
2350
+ async function fetchGooseModelContextLimits(input) {
2351
+ const response = await input.httpClient(`${input.apiBaseUrl}/models`, {
2352
+ headers: {
2353
+ Authorization: `Bearer ${input.apiKey}`
2354
+ }
2355
+ });
2356
+ if (!response.ok) {
2357
+ throw new Error(
2358
+ `Failed to fetch Poe model catalog for Goose configuration (status ${response.status}).`
2359
+ );
2360
+ }
2361
+ const modelContextLimits = extractGooseModelContextLimits(
2362
+ await response.json()
2363
+ );
2364
+ const missing = GOOSE_MODELS.filter((model) => modelContextLimits[model] == null);
2365
+ if (missing.length > 0) {
2366
+ throw new Error(
2367
+ `Missing Goose model context limit for ${missing[0]}.`
2368
+ );
2369
+ }
2370
+ return modelContextLimits;
2371
+ }
2372
+ var GOOSE_MODE_ENV = {
2373
+ yolo: "auto",
2374
+ edit: "smart_approve",
2375
+ read: "chat"
2376
+ };
2377
+ function buildRunOptions(options, model) {
2378
+ const baseArgs = [
2379
+ "run",
2380
+ "--provider",
2381
+ CUSTOM_PROVIDER_ID,
2382
+ "--model",
2383
+ model,
2384
+ "--output-format",
2385
+ "text"
2386
+ ];
2387
+ const mcpArgs = options.mcpServers ? serializeGooseMcpArgs(options.mcpServers) : [];
2388
+ const modeEnv = options.mode && GOOSE_MODE_ENV[options.mode] ? { GOOSE_MODE: GOOSE_MODE_ENV[options.mode] } : void 0;
2389
+ if (options.useStdin) {
2390
+ return {
2391
+ args: [...baseArgs, ...mcpArgs, "--instructions", "-", ...options.args ?? []],
2392
+ commandOptions: {
2393
+ ...options.cwd ? { cwd: options.cwd } : {},
2394
+ ...modeEnv ? { env: modeEnv } : {},
2395
+ stdin: options.prompt
2396
+ }
2397
+ };
2398
+ }
2399
+ return {
2400
+ args: [...baseArgs, ...mcpArgs, "--text", options.prompt, ...options.args ?? []],
2401
+ commandOptions: options.cwd || modeEnv ? { ...options.cwd ? { cwd: options.cwd } : {}, ...modeEnv ? { env: modeEnv } : {} } : void 0
2402
+ };
2403
+ }
2404
+ var gooseService = createProvider({
2405
+ ...gooseAgent,
2406
+ supportsStdinPrompt: true,
2407
+ supportsMcpSpawn: true,
2408
+ configurePrompts: {
2409
+ model: {
2410
+ label: "Goose default model",
2411
+ defaultValue: DEFAULT_GOOSE_MODEL,
2412
+ choices: GOOSE_MODELS.map((id) => ({
2413
+ title: id,
2414
+ value: id
2415
+ }))
2416
+ }
2417
+ },
2418
+ async extendConfigurePayload(context) {
2419
+ const { apiKey } = context.payload;
2420
+ const modelContextLimits = await fetchGooseModelContextLimits({
2421
+ apiBaseUrl: context.env.poeApiBaseUrl,
2422
+ apiKey,
2423
+ httpClient: context.httpClient
2424
+ });
2425
+ return {
2426
+ modelContextLimits
2427
+ };
2428
+ },
2429
+ isolatedEnv: {
2430
+ agentBinary: gooseAgent.binaryName,
2431
+ configProbe: { kind: "isolatedFile", relativePath: ".config/goose/config.yaml" },
2432
+ env: {
2433
+ HOME: { kind: "isolatedDir", relativePath: "" },
2434
+ XDG_CONFIG_HOME: { kind: "isolatedDir", relativePath: ".config" }
2435
+ }
2436
+ },
2437
+ manifest: {
2438
+ configure: [
2439
+ fileMutation.ensureDirectory({ path: "~/.config/goose/custom_providers" }),
2440
+ configMutation.merge({
2441
+ target: CUSTOM_PROVIDER_FILE,
2442
+ value: (ctx) => {
2443
+ const { env, modelContextLimits } = ctx ?? {};
2444
+ return buildCustomProvider(env.poeApiBaseUrl, modelContextLimits);
2445
+ }
2446
+ }),
2447
+ configMutation.merge({
2448
+ target: GOOSE_CONFIG_FILE,
2449
+ format: "yaml",
2450
+ value: (ctx) => {
2451
+ const { model } = ctx ?? {};
2452
+ return {
2453
+ GOOSE_PROVIDER: CUSTOM_PROVIDER_ID,
2454
+ GOOSE_MODEL: model ?? DEFAULT_GOOSE_MODEL,
2455
+ GOOSE_DISABLE_KEYRING: true
2456
+ };
2457
+ }
2458
+ }),
2459
+ configMutation.merge({
2460
+ target: GOOSE_SECRETS_FILE,
2461
+ format: "yaml",
2462
+ value: (ctx) => {
2463
+ const { apiKey } = ctx ?? {};
2464
+ return {
2465
+ [CUSTOM_PROVIDER_API_KEY_ENV]: apiKey
2466
+ };
2467
+ }
2468
+ })
2469
+ ],
2470
+ unconfigure: [
2471
+ fileMutation.remove({ target: CUSTOM_PROVIDER_FILE }),
2472
+ configMutation.prune({
2473
+ target: GOOSE_CONFIG_FILE,
2474
+ format: "yaml",
2475
+ onlyIf: (document) => document.GOOSE_PROVIDER === CUSTOM_PROVIDER_ID,
2476
+ shape: {
2477
+ GOOSE_PROVIDER: true,
2478
+ GOOSE_MODEL: true,
2479
+ GOOSE_DISABLE_KEYRING: true
2480
+ }
2481
+ }),
2482
+ configMutation.prune({
2483
+ target: GOOSE_SECRETS_FILE,
2484
+ format: "yaml",
2485
+ shape: {
2486
+ [CUSTOM_PROVIDER_API_KEY_ENV]: true
2487
+ }
2488
+ })
2489
+ ]
2490
+ },
2491
+ install: GOOSE_INSTALL_DEFINITION,
2492
+ test(context) {
2493
+ return context.runCheck(
2494
+ createCommandExpectationCheck({
2495
+ id: "goose-cli-health",
2496
+ command: "goose",
2497
+ args: ["run", "--text", HEALTH_CHECK_PROMPT, "--output-format", "text"],
2498
+ expectedOutput: "GOOSE_OK"
2499
+ })
2500
+ );
2501
+ },
2502
+ spawn(context, options) {
2503
+ const model = options.model ?? DEFAULT_GOOSE_MODEL;
2504
+ const { args, commandOptions } = buildRunOptions(options, model);
2505
+ return commandOptions ? context.command.runCommand("goose", args, commandOptions) : context.command.runCommand("goose", args);
2506
+ }
2507
+ });
2508
+ var provider = gooseService;
2509
+ export {
2510
+ GOOSE_INSTALL_DEFINITION,
2511
+ gooseService,
2512
+ provider
2513
+ };
2514
+ //# sourceMappingURL=goose.js.map