poe-code 4.0.19 → 4.0.21

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,2586 @@
1
+ // packages/auth-store/src/encrypted-file-store.ts
2
+ import { createCipheriv, createDecipheriv, randomBytes, randomUUID, scrypt } from "node:crypto";
3
+ import { promises as fs } from "node:fs";
4
+ import { homedir, hostname, userInfo } from "node:os";
5
+ import path from "node:path";
6
+
7
+ // packages/auth-store/src/error-codes.ts
8
+ function hasOwnErrorCode(error2, code) {
9
+ return error2 instanceof Error && Object.prototype.hasOwnProperty.call(error2, "code") && error2.code === code;
10
+ }
11
+
12
+ // packages/auth-store/src/encrypted-file-store.ts
13
+ var derivedKeyCache = /* @__PURE__ */ new Map();
14
+ var ENCRYPTION_ALGORITHM = "aes-256-gcm";
15
+ var ENCRYPTION_VERSION = 1;
16
+ var ENCRYPTION_KEY_BYTES = 32;
17
+ var ENCRYPTION_IV_BYTES = 12;
18
+ var ENCRYPTION_AUTH_TAG_BYTES = 16;
19
+ var ENCRYPTION_FILE_MODE = 384;
20
+ var EncryptedFileStore = class {
21
+ fs;
22
+ filePath;
23
+ symbolicLinkCheckStartPath;
24
+ salt;
25
+ getMachineIdentity;
26
+ getRandomBytes;
27
+ keyPromise = null;
28
+ constructor(input) {
29
+ this.fs = input.fs ?? fs;
30
+ this.salt = input.salt;
31
+ if (input.filePath === void 0) {
32
+ const homeDirectory = (input.getHomeDirectory ?? homedir)();
33
+ const defaultDirectory = input.defaultDirectory ?? ".auth-store";
34
+ const defaultFileName = input.defaultFileName ?? "credentials.enc";
35
+ assertSafeDefaultDirectory(defaultDirectory);
36
+ assertSafeDefaultFileName(defaultFileName);
37
+ this.filePath = path.join(
38
+ homeDirectory,
39
+ defaultDirectory,
40
+ defaultFileName
41
+ );
42
+ this.symbolicLinkCheckStartPath = resolveDefaultDirectoryCheckStart(
43
+ homeDirectory,
44
+ defaultDirectory
45
+ );
46
+ } else {
47
+ this.filePath = input.filePath;
48
+ this.symbolicLinkCheckStartPath = null;
49
+ }
50
+ this.getMachineIdentity = input.getMachineIdentity ?? defaultMachineIdentity;
51
+ this.getRandomBytes = input.getRandomBytes ?? randomBytes;
52
+ }
53
+ async get() {
54
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
55
+ let rawDocument;
56
+ try {
57
+ rawDocument = await this.fs.readFile(this.filePath, "utf8");
58
+ } catch (error2) {
59
+ if (isNotFoundError(error2)) {
60
+ return null;
61
+ }
62
+ throw error2;
63
+ }
64
+ const document = parseEncryptedDocument(rawDocument);
65
+ if (!document) {
66
+ return null;
67
+ }
68
+ const key2 = await this.getEncryptionKey();
69
+ try {
70
+ const iv = Buffer.from(document.iv, "base64");
71
+ const authTag = Buffer.from(document.authTag, "base64");
72
+ const ciphertext = Buffer.from(document.ciphertext, "base64");
73
+ if (iv.byteLength !== ENCRYPTION_IV_BYTES || authTag.byteLength !== ENCRYPTION_AUTH_TAG_BYTES) {
74
+ return null;
75
+ }
76
+ const decipher = createDecipheriv(ENCRYPTION_ALGORITHM, key2, iv);
77
+ decipher.setAuthTag(authTag);
78
+ const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
79
+ return plaintext.toString("utf8");
80
+ } catch {
81
+ return null;
82
+ }
83
+ }
84
+ async set(value) {
85
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
86
+ const key2 = await this.getEncryptionKey();
87
+ const iv = this.getRandomBytes(ENCRYPTION_IV_BYTES);
88
+ const cipher = createCipheriv(ENCRYPTION_ALGORITHM, key2, iv);
89
+ const ciphertext = Buffer.concat([
90
+ cipher.update(value, "utf8"),
91
+ cipher.final()
92
+ ]);
93
+ const authTag = cipher.getAuthTag();
94
+ const document = {
95
+ version: ENCRYPTION_VERSION,
96
+ iv: iv.toString("base64"),
97
+ authTag: authTag.toString("base64"),
98
+ ciphertext: ciphertext.toString("base64")
99
+ };
100
+ await this.fs.mkdir(path.dirname(this.filePath), { recursive: true });
101
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
102
+ const temporaryPath = `${this.filePath}.${process.pid}.${randomUUID()}.tmp`;
103
+ let temporaryCreated = false;
104
+ try {
105
+ await this.assertCredentialPathHasNoSymbolicLinks(temporaryPath);
106
+ await this.fs.writeFile(temporaryPath, JSON.stringify(document), {
107
+ encoding: "utf8",
108
+ flag: "wx",
109
+ mode: ENCRYPTION_FILE_MODE
110
+ });
111
+ temporaryCreated = true;
112
+ await this.fs.chmod(temporaryPath, ENCRYPTION_FILE_MODE);
113
+ await this.fs.rename(temporaryPath, this.filePath);
114
+ } catch (error2) {
115
+ if (temporaryCreated || !isAlreadyExistsError(error2)) {
116
+ await removeIfPresent(this.fs, temporaryPath).catch(() => void 0);
117
+ }
118
+ throw error2;
119
+ }
120
+ }
121
+ async delete() {
122
+ await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
123
+ try {
124
+ await this.fs.unlink(this.filePath);
125
+ } catch (error2) {
126
+ if (!isNotFoundError(error2)) {
127
+ throw error2;
128
+ }
129
+ }
130
+ }
131
+ async assertCredentialPathHasNoSymbolicLinks(targetPath) {
132
+ const resolvedPath = path.resolve(targetPath);
133
+ const protectedPaths = getProtectedCredentialPaths(
134
+ resolvedPath,
135
+ this.symbolicLinkCheckStartPath
136
+ );
137
+ for (const currentPath of protectedPaths) {
138
+ try {
139
+ const stats = await this.fs.lstat(currentPath);
140
+ if (stats.isSymbolicLink()) {
141
+ throw new Error(`Refusing to use encrypted credential path through symbolic link: ${currentPath}`);
142
+ }
143
+ } catch (error2) {
144
+ if (isNotFoundError(error2)) {
145
+ return;
146
+ }
147
+ throw error2;
148
+ }
149
+ }
150
+ }
151
+ getEncryptionKey() {
152
+ if (!this.keyPromise) {
153
+ const retryableKeyPromise = deriveEncryptionKey(this.getMachineIdentity, this.salt).catch((error2) => {
154
+ if (this.keyPromise === retryableKeyPromise) {
155
+ this.keyPromise = null;
156
+ }
157
+ throw error2;
158
+ });
159
+ this.keyPromise = retryableKeyPromise;
160
+ }
161
+ return this.keyPromise;
162
+ }
163
+ };
164
+ function resolveDefaultDirectoryCheckStart(homeDirectory, defaultDirectory) {
165
+ const [firstSegment] = defaultDirectory.split(/[\\/]+/).filter(Boolean);
166
+ return path.resolve(homeDirectory, firstSegment ?? ".");
167
+ }
168
+ function getProtectedCredentialPaths(resolvedPath, symbolicLinkCheckStartPath) {
169
+ if (symbolicLinkCheckStartPath === null) {
170
+ return getExplicitProtectedCredentialPaths(resolvedPath);
171
+ }
172
+ const resolvedStartPath = path.resolve(symbolicLinkCheckStartPath);
173
+ if (!isPathInsideOrEqual(resolvedPath, resolvedStartPath)) {
174
+ return [path.dirname(resolvedPath), resolvedPath];
175
+ }
176
+ const protectedPaths = [resolvedStartPath];
177
+ let currentPath = resolvedStartPath;
178
+ for (const segment of path.relative(resolvedStartPath, resolvedPath).split(path.sep).filter(Boolean)) {
179
+ currentPath = path.join(currentPath, segment);
180
+ protectedPaths.push(currentPath);
181
+ }
182
+ return protectedPaths;
183
+ }
184
+ function assertSafeDefaultDirectory(defaultDirectory) {
185
+ if (path.isAbsolute(defaultDirectory) || path.win32.isAbsolute(defaultDirectory)) {
186
+ throw new Error("defaultDirectory must be a relative path inside the home directory");
187
+ }
188
+ for (const segment of splitPathSegments(defaultDirectory)) {
189
+ if (segment === "..") {
190
+ throw new Error("defaultDirectory must be a relative path inside the home directory");
191
+ }
192
+ }
193
+ }
194
+ function assertSafeDefaultFileName(defaultFileName) {
195
+ if (defaultFileName.trim().length === 0 || defaultFileName === "." || defaultFileName === ".." || splitPathSegments(defaultFileName).length !== 1) {
196
+ throw new Error("defaultFileName must be a file name without path separators");
197
+ }
198
+ }
199
+ function splitPathSegments(value) {
200
+ return value.split("/").flatMap((segment) => segment.split("\\")).filter((segment) => segment.length > 0);
201
+ }
202
+ function getExplicitProtectedCredentialPaths(resolvedPath) {
203
+ const parsed = path.parse(resolvedPath);
204
+ const segments = resolvedPath.slice(parsed.root.length).split(path.sep).filter((segment) => segment.length > 0);
205
+ if (segments.length <= 1) {
206
+ return [resolvedPath];
207
+ }
208
+ const protectedPaths = [];
209
+ let currentPath = parsed.root;
210
+ for (const [index, segment] of segments.entries()) {
211
+ currentPath = path.join(currentPath, segment);
212
+ if (index === 0) {
213
+ continue;
214
+ }
215
+ protectedPaths.push(currentPath);
216
+ }
217
+ return protectedPaths;
218
+ }
219
+ function isPathInsideOrEqual(childPath, parentPath) {
220
+ const relativePath = path.relative(parentPath, childPath);
221
+ return relativePath === "" || !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
222
+ }
223
+ async function removeIfPresent(fileSystem, filePath) {
224
+ try {
225
+ await fileSystem.unlink(filePath);
226
+ } catch (error2) {
227
+ if (!isNotFoundError(error2)) {
228
+ throw error2;
229
+ }
230
+ }
231
+ }
232
+ function defaultMachineIdentity() {
233
+ return {
234
+ hostname: hostname(),
235
+ username: userInfo().username
236
+ };
237
+ }
238
+ async function deriveEncryptionKey(getMachineIdentity, salt) {
239
+ const machineIdentity = await getMachineIdentity();
240
+ const secret = `${machineIdentity.hostname}:${machineIdentity.username}`;
241
+ const cacheKey = JSON.stringify([machineIdentity.hostname, machineIdentity.username, salt]);
242
+ const cached2 = derivedKeyCache.get(cacheKey);
243
+ if (cached2) {
244
+ return cached2;
245
+ }
246
+ const keyPromise = new Promise((resolve2, reject) => {
247
+ scrypt(secret, salt, ENCRYPTION_KEY_BYTES, (error2, derivedKey) => {
248
+ if (error2) {
249
+ reject(error2);
250
+ return;
251
+ }
252
+ resolve2(Buffer.from(derivedKey));
253
+ });
254
+ });
255
+ derivedKeyCache.set(cacheKey, keyPromise);
256
+ return keyPromise.catch((error2) => {
257
+ if (derivedKeyCache.get(cacheKey) === keyPromise) {
258
+ derivedKeyCache.delete(cacheKey);
259
+ }
260
+ throw error2;
261
+ });
262
+ }
263
+ function parseEncryptedDocument(raw) {
264
+ try {
265
+ const parsed = JSON.parse(raw);
266
+ if (!isRecord(parsed)) {
267
+ return null;
268
+ }
269
+ const version = getOwnEntry(parsed, "version");
270
+ const iv = getOwnEntry(parsed, "iv");
271
+ const authTag = getOwnEntry(parsed, "authTag");
272
+ const ciphertext = getOwnEntry(parsed, "ciphertext");
273
+ if (version !== ENCRYPTION_VERSION) {
274
+ return null;
275
+ }
276
+ if (typeof iv !== "string" || typeof authTag !== "string" || typeof ciphertext !== "string") {
277
+ return null;
278
+ }
279
+ return {
280
+ version,
281
+ iv,
282
+ authTag,
283
+ ciphertext
284
+ };
285
+ } catch {
286
+ return null;
287
+ }
288
+ }
289
+ function isRecord(value) {
290
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
291
+ }
292
+ function getOwnEntry(record, key2) {
293
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
294
+ }
295
+ function isNotFoundError(error2) {
296
+ return hasOwnErrorCode(error2, "ENOENT");
297
+ }
298
+ function isAlreadyExistsError(error2) {
299
+ return hasOwnErrorCode(error2, "EEXIST");
300
+ }
301
+
302
+ // packages/auth-store/src/keychain-store.ts
303
+ import { spawn } from "node:child_process";
304
+ var SECURITY_CLI = "security";
305
+ var KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE = 44;
306
+ var KeychainStore = class {
307
+ runCommand;
308
+ service;
309
+ account;
310
+ constructor(input) {
311
+ this.runCommand = input.runCommand ?? runSecurityCommand;
312
+ this.service = input.service.trim();
313
+ this.account = input.account.trim();
314
+ if (this.service.length === 0) {
315
+ throw new Error("Keychain service must not be empty");
316
+ }
317
+ if (this.account.length === 0) {
318
+ throw new Error("Keychain account must not be empty");
319
+ }
320
+ }
321
+ async get() {
322
+ const result = await this.executeSecurityCommand(
323
+ ["find-generic-password", "-s", this.service, "-a", this.account, "-w"],
324
+ "read secret from macOS Keychain"
325
+ );
326
+ if (getCommandExitCode(result) === 0) {
327
+ return stripTrailingLineBreak(getCommandOutput(result, "stdout"));
328
+ }
329
+ if (isKeychainEntryNotFound(result)) {
330
+ return null;
331
+ }
332
+ throw createSecurityCliFailure("read secret from macOS Keychain", result);
333
+ }
334
+ async set(value) {
335
+ if (value.includes("\n") || value.includes("\r")) {
336
+ throw new Error("Keychain secrets cannot contain line breaks");
337
+ }
338
+ const result = await this.executeSecurityCommand(
339
+ [
340
+ "add-generic-password",
341
+ "-s",
342
+ this.service,
343
+ "-a",
344
+ this.account,
345
+ "-U",
346
+ "-w",
347
+ value
348
+ ],
349
+ "store secret in macOS Keychain"
350
+ );
351
+ if (getCommandExitCode(result) !== 0) {
352
+ throw createSecurityCliFailure("store secret in macOS Keychain", result);
353
+ }
354
+ }
355
+ async delete() {
356
+ const result = await this.executeSecurityCommand(
357
+ ["delete-generic-password", "-s", this.service, "-a", this.account],
358
+ "delete secret from macOS Keychain"
359
+ );
360
+ if (getCommandExitCode(result) === 0 || isKeychainEntryNotFound(result)) {
361
+ return;
362
+ }
363
+ throw createSecurityCliFailure("delete secret from macOS Keychain", result);
364
+ }
365
+ async executeSecurityCommand(args, operation, options) {
366
+ try {
367
+ if (options === void 0) {
368
+ return await this.runCommand(SECURITY_CLI, args);
369
+ }
370
+ return await this.runCommand(SECURITY_CLI, args, options);
371
+ } catch (error2) {
372
+ const message2 = error2 instanceof Error ? error2.message : String(error2);
373
+ throw new Error(`Failed to ${operation}: ${message2}`);
374
+ }
375
+ }
376
+ };
377
+ function runSecurityCommand(command, args, options) {
378
+ return new Promise((resolve2) => {
379
+ const child = spawn(command, args, {
380
+ stdio: [options?.stdin === void 0 ? "ignore" : "pipe", "pipe", "pipe"]
381
+ });
382
+ let stdout = "";
383
+ let stderr = "";
384
+ let stdinErrorMessage;
385
+ const appendStderr = (message2) => {
386
+ stderr = stderr.length === 0 ? message2 : `${stderr}${stderr.endsWith("\n") ? "" : "\n"}${message2}`;
387
+ };
388
+ const appendStdinError = () => {
389
+ if (stdinErrorMessage === void 0) {
390
+ return;
391
+ }
392
+ appendStderr(stdinErrorMessage);
393
+ stdinErrorMessage = void 0;
394
+ };
395
+ child.stdout?.setEncoding("utf8");
396
+ child.stdout?.on("data", (chunk) => {
397
+ stdout += chunk.toString();
398
+ });
399
+ child.stderr?.setEncoding("utf8");
400
+ child.stderr?.on("data", (chunk) => {
401
+ stderr += chunk.toString();
402
+ });
403
+ if (options?.stdin !== void 0) {
404
+ child.stdin?.once("error", (error2) => {
405
+ stdinErrorMessage = error2 instanceof Error ? error2.message : String(error2);
406
+ });
407
+ child.stdin?.end(options.stdin);
408
+ }
409
+ child.on("error", (error2) => {
410
+ const message2 = error2 instanceof Error ? error2.message : String(error2 ?? "Unknown error");
411
+ appendStdinError();
412
+ appendStderr(message2);
413
+ resolve2({
414
+ stdout,
415
+ stderr,
416
+ exitCode: 127
417
+ });
418
+ });
419
+ child.on("close", (code) => {
420
+ appendStdinError();
421
+ resolve2({
422
+ stdout,
423
+ stderr,
424
+ exitCode: code ?? 1
425
+ });
426
+ });
427
+ });
428
+ }
429
+ function stripTrailingLineBreak(value) {
430
+ if (value.endsWith("\r\n")) {
431
+ return value.slice(0, -2);
432
+ }
433
+ if (value.endsWith("\n") || value.endsWith("\r")) {
434
+ return value.slice(0, -1);
435
+ }
436
+ return value;
437
+ }
438
+ function isKeychainEntryNotFound(result) {
439
+ return getCommandExitCode(result) === KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE;
440
+ }
441
+ function createSecurityCliFailure(operation, result) {
442
+ const exitCode = getCommandExitCode(result);
443
+ const details = getCommandOutput(result, "stderr").trim() || getCommandOutput(result, "stdout").trim();
444
+ if (details) {
445
+ return new Error(
446
+ `Failed to ${operation}: security exited with code ${exitCode}: ${details}`
447
+ );
448
+ }
449
+ return new Error(`Failed to ${operation}: security exited with code ${exitCode}`);
450
+ }
451
+ function getCommandExitCode(result) {
452
+ const value = getOwnEntry2(result, "exitCode");
453
+ return typeof value === "number" && Number.isInteger(value) ? value : 1;
454
+ }
455
+ function getCommandOutput(result, key2) {
456
+ const value = getOwnEntry2(result, key2);
457
+ return typeof value === "string" ? value : "";
458
+ }
459
+ function getOwnEntry2(record, key2) {
460
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
461
+ }
462
+
463
+ // packages/auth-store/src/create-secret-store.ts
464
+ var DEFAULT_BACKEND_ENV_VAR = "AUTH_BACKEND";
465
+ var MACOS_PLATFORM = "darwin";
466
+ var storeFactories = {
467
+ file: (input) => {
468
+ if (!input.fileStore) {
469
+ throw new Error("fileStore configuration is required for file backend");
470
+ }
471
+ return new EncryptedFileStore(input.fileStore);
472
+ },
473
+ keychain: (input) => {
474
+ if (!input.keychainStore) {
475
+ throw new Error("keychainStore configuration is required for keychain backend");
476
+ }
477
+ return new KeychainStore(input.keychainStore);
478
+ }
479
+ };
480
+ function createSecretStore(input) {
481
+ const backend = resolveBackend(input);
482
+ const platform = input.platform ?? process.platform;
483
+ if (backend === "keychain" && platform !== MACOS_PLATFORM) {
484
+ throw new Error(
485
+ `Keychain backend is only supported on macOS. Current platform: ${platform}`
486
+ );
487
+ }
488
+ const store = storeFactories[backend](input);
489
+ return { backend, store };
490
+ }
491
+ function resolveBackend(input) {
492
+ const envVar = input.backendEnvVar ?? DEFAULT_BACKEND_ENV_VAR;
493
+ const configuredBackend = input.backend ?? getOwnEnvValue(input.env, envVar) ?? getOwnEnvValue(process.env, envVar);
494
+ const backend = configuredBackend?.trim();
495
+ if (backend === "keychain") {
496
+ return "keychain";
497
+ }
498
+ if (backend === void 0 || backend === "file") {
499
+ return "file";
500
+ }
501
+ throw new Error(`Unsupported auth store backend: ${backend}`);
502
+ }
503
+ function getOwnEnvValue(env, key2) {
504
+ return env !== void 0 && Object.prototype.hasOwnProperty.call(env, key2) ? env[key2] : void 0;
505
+ }
506
+
507
+ // src/cli/errors.ts
508
+ var CliError = class extends Error {
509
+ context;
510
+ isUserError;
511
+ constructor(message2, context, options) {
512
+ super(message2);
513
+ this.name = this.constructor.name;
514
+ this.context = context;
515
+ this.isUserError = options?.isUserError ?? false;
516
+ if (Error.captureStackTrace) {
517
+ Error.captureStackTrace(this, this.constructor);
518
+ }
519
+ }
520
+ };
521
+ var ApiError = class extends CliError {
522
+ httpStatus;
523
+ endpoint;
524
+ constructor(message2, options) {
525
+ super(message2, {
526
+ ...options?.context,
527
+ httpStatus: options?.httpStatus,
528
+ apiEndpoint: options?.endpoint
529
+ });
530
+ this.httpStatus = options?.httpStatus;
531
+ this.endpoint = options?.endpoint;
532
+ }
533
+ };
534
+ var AuthenticationError = class extends CliError {
535
+ constructor(message2, context) {
536
+ super(message2, context, { isUserError: true });
537
+ }
538
+ };
539
+
540
+ // src/cli/environment.ts
541
+ import path16 from "node:path";
542
+
543
+ // packages/poe-code-config/src/runtime.ts
544
+ import { existsSync, realpathSync } from "node:fs";
545
+ import path2 from "node:path";
546
+ var defaultWorkspaceExclude = [
547
+ ".git",
548
+ "node_modules",
549
+ "dist",
550
+ ".turbo",
551
+ ".next",
552
+ ".poe-code/state.json"
553
+ ];
554
+ var runtimeConfigScope = deepFreeze({
555
+ scope: "runtime",
556
+ schema: {
557
+ type: {
558
+ type: "string",
559
+ default: "host",
560
+ doc: "Runtime backend: host or docker"
561
+ },
562
+ build_args: {
563
+ type: "json",
564
+ default: {},
565
+ parse: parseBuildArgs,
566
+ doc: "Build arguments passed to the runtime image build"
567
+ },
568
+ mounts: {
569
+ type: "json",
570
+ default: [],
571
+ parse: parseMounts,
572
+ doc: "Additional runtime mounts"
573
+ },
574
+ runner: {
575
+ type: "json",
576
+ default: createDefaultRunnerScope(),
577
+ parse: parseRunner,
578
+ doc: "Runner process and workspace transfer settings"
579
+ },
580
+ link: {
581
+ type: "string",
582
+ default: "",
583
+ doc: "Informational link for the runtime definition"
584
+ },
585
+ image: {
586
+ type: "string",
587
+ default: "",
588
+ doc: "Prebuilt Docker image"
589
+ },
590
+ dockerfile: {
591
+ type: "string",
592
+ default: "",
593
+ doc: "Path to the Dockerfile used for Docker builds"
594
+ },
595
+ build_context: {
596
+ type: "string",
597
+ default: "",
598
+ doc: "Path to the Docker build context"
599
+ },
600
+ engine: {
601
+ type: "string",
602
+ default: "",
603
+ doc: "Container engine for Docker runtime"
604
+ },
605
+ network: {
606
+ type: "string",
607
+ default: "",
608
+ doc: "Docker network"
609
+ },
610
+ extra_args: {
611
+ type: "json",
612
+ default: void 0,
613
+ parse: parseOptionalStringArray,
614
+ doc: "Extra Docker runtime arguments"
615
+ }
616
+ }
617
+ });
618
+ function parseRunner(raw) {
619
+ if (raw === void 0) {
620
+ return createDefaultRunnerScope();
621
+ }
622
+ const record = asRecord(raw);
623
+ if (record === void 0) {
624
+ throw new Error("runner: expected an object.");
625
+ }
626
+ const uploadMaxFileMb = parseOptionalNumber(getOwnEntry3(record, "upload_max_file_mb"), "runner.upload_max_file_mb") ?? 100;
627
+ if (uploadMaxFileMb <= 0) {
628
+ throw new Error("runner.upload_max_file_mb: expected a positive finite number.");
629
+ }
630
+ return omitUndefined({
631
+ detach: parseOptionalBoolean(getOwnEntry3(record, "detach"), "runner.detach") ?? false,
632
+ upload_max_file_mb: uploadMaxFileMb,
633
+ download_conflict: parseDownloadConflict(getOwnEntry3(record, "download_conflict")),
634
+ sync: parseRunnerSync(getOwnEntry3(record, "sync")),
635
+ workspace: parseRunnerWorkspace(getOwnEntry3(record, "workspace"))
636
+ });
637
+ }
638
+ function createDefaultRunnerScope() {
639
+ return {
640
+ detach: false,
641
+ upload_max_file_mb: 100,
642
+ download_conflict: "refuse",
643
+ sync: "both",
644
+ workspace: {
645
+ exclude: [...defaultWorkspaceExclude]
646
+ }
647
+ };
648
+ }
649
+ function parseRunnerWorkspace(value) {
650
+ if (value === void 0) {
651
+ return {
652
+ exclude: [...defaultWorkspaceExclude]
653
+ };
654
+ }
655
+ const record = asRecord(value);
656
+ if (record === void 0) {
657
+ throw new Error("runner.workspace: expected an object.");
658
+ }
659
+ return {
660
+ exclude: parseOptionalStringArray(getOwnEntry3(record, "exclude"), "runner.workspace.exclude") ?? [...defaultWorkspaceExclude]
661
+ };
662
+ }
663
+ function parseDownloadConflict(value) {
664
+ if (value === void 0) {
665
+ return "refuse";
666
+ }
667
+ if (value === "refuse" || value === "overwrite") {
668
+ return value;
669
+ }
670
+ throw new Error('runner.download_conflict: expected "refuse" or "overwrite".');
671
+ }
672
+ function parseRunnerSync(value) {
673
+ if (value === void 0) {
674
+ return "both";
675
+ }
676
+ if (value === "both" || value === "upload" || value === "none") {
677
+ return value;
678
+ }
679
+ throw new Error('runner.sync: expected "both", "upload", or "none".');
680
+ }
681
+ function parseBuildArgs(value) {
682
+ if (value === void 0) {
683
+ return {};
684
+ }
685
+ const record = asRecord(value);
686
+ if (record === void 0) {
687
+ throw new Error("build_args: expected an object.");
688
+ }
689
+ const parsed = {};
690
+ for (const [key2, entry] of Object.entries(record)) {
691
+ assertBuildArgName(key2);
692
+ if (typeof entry !== "string") {
693
+ throw new Error(`build_args.${key2}: expected a string.`);
694
+ }
695
+ defineDataProperty(parsed, key2, entry);
696
+ }
697
+ return parsed;
698
+ }
699
+ function parseMounts(value) {
700
+ if (value === void 0) {
701
+ return [];
702
+ }
703
+ if (!Array.isArray(value)) {
704
+ throw new Error("mounts: expected an array.");
705
+ }
706
+ return value.map((entry, index) => {
707
+ const record = asRecord(entry);
708
+ if (record === void 0) {
709
+ throw new Error(`mounts[${index}]: expected an object.`);
710
+ }
711
+ const source = getOwnEntry3(record, "source");
712
+ const target = getOwnEntry3(record, "target");
713
+ if (typeof source !== "string") {
714
+ throw new Error(`mounts[${index}].source: expected a string.`);
715
+ }
716
+ if (source.trim().length === 0) {
717
+ throw new Error(`mounts[${index}].source: expected a non-empty string.`);
718
+ }
719
+ if (typeof target !== "string") {
720
+ throw new Error(`mounts[${index}].target: expected a string.`);
721
+ }
722
+ if (target.trim().length === 0 || target !== target.trim() || !path2.posix.isAbsolute(target)) {
723
+ throw new Error(`mounts[${index}].target: expected a non-empty absolute sandbox path.`);
724
+ }
725
+ return omitUndefined({
726
+ source,
727
+ target,
728
+ readonly: parseOptionalBoolean(getOwnEntry3(record, "readonly"), `mounts[${index}].readonly`)
729
+ });
730
+ });
731
+ }
732
+ function assertBuildArgName(key2) {
733
+ if (key2.length === 0 || key2 !== key2.trim()) {
734
+ throw new Error(`build_args.${key2}: expected an environment-style argument name.`);
735
+ }
736
+ for (let index = 0; index < key2.length; index += 1) {
737
+ const charCode = key2.charCodeAt(index);
738
+ const isUppercase = charCode >= 65 && charCode <= 90;
739
+ const isLowercase = charCode >= 97 && charCode <= 122;
740
+ const isDigit = charCode >= 48 && charCode <= 57;
741
+ const isUnderscore = charCode === 95;
742
+ if (!isUppercase && !isLowercase && !isDigit && !isUnderscore) {
743
+ throw new Error(`build_args.${key2}: expected an environment-style argument name.`);
744
+ }
745
+ }
746
+ }
747
+ function defineDataProperty(object, key2, value) {
748
+ Object.defineProperty(object, key2, {
749
+ configurable: true,
750
+ enumerable: true,
751
+ value,
752
+ writable: true
753
+ });
754
+ }
755
+ function deepFreeze(value) {
756
+ if (!value || typeof value !== "object" || Object.isFrozen(value)) {
757
+ return value;
758
+ }
759
+ for (const entry of Object.values(value)) {
760
+ deepFreeze(entry);
761
+ }
762
+ return Object.freeze(value);
763
+ }
764
+ function parseOptionalStringArray(value, key2 = "") {
765
+ if (value === void 0) {
766
+ return void 0;
767
+ }
768
+ if (!Array.isArray(value)) {
769
+ throw new Error(`${key2 ? `${key2}: ` : ""}expected an array.`);
770
+ }
771
+ return value.map((entry, index) => {
772
+ if (typeof entry !== "string") {
773
+ throw new Error(`${key2}[${index}]: expected a string.`);
774
+ }
775
+ return entry;
776
+ });
777
+ }
778
+ function parseOptionalNumber(value, key2 = "") {
779
+ if (value === void 0) {
780
+ return void 0;
781
+ }
782
+ if (typeof value !== "number" || !Number.isFinite(value)) {
783
+ throw new Error(`${key2 ? `${key2}: ` : ""}expected a finite number.`);
784
+ }
785
+ return value;
786
+ }
787
+ function parseOptionalBoolean(value, key2) {
788
+ if (value === void 0) {
789
+ return void 0;
790
+ }
791
+ if (typeof value !== "boolean") {
792
+ throw new Error(`${key2}: expected a boolean.`);
793
+ }
794
+ return value;
795
+ }
796
+ function asRecord(value) {
797
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
798
+ return void 0;
799
+ }
800
+ return value;
801
+ }
802
+ function getOwnEntry3(record, key2) {
803
+ return Object.prototype.hasOwnProperty.call(record, key2) ? record[key2] : void 0;
804
+ }
805
+ function omitUndefined(value) {
806
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
807
+ }
808
+
809
+ // packages/poe-code-config/src/schema.ts
810
+ function defineScope(scope, schema) {
811
+ return {
812
+ scope,
813
+ schema
814
+ };
815
+ }
816
+ var integrationsConfigScope = defineScope("integrations", {
817
+ braintrust: {
818
+ type: "json",
819
+ default: {
820
+ enabled: false
821
+ },
822
+ parse: parseBraintrustIntegrationConfig,
823
+ doc: "Braintrust integration configuration"
824
+ }
825
+ });
826
+ function parseBraintrustIntegrationConfig(value) {
827
+ if (!isRecord2(value)) {
828
+ throw new Error("expected an object");
829
+ }
830
+ const enabled = value.enabled === void 0 ? false : value.enabled;
831
+ if (typeof enabled !== "boolean") {
832
+ throw new Error("enabled must be a boolean");
833
+ }
834
+ return {
835
+ enabled,
836
+ ...optionalStringEntry("apiKey", value.apiKey),
837
+ ...optionalStringEntry("apiUrl", value.apiUrl),
838
+ ...optionalStringEntry("project", value.project)
839
+ };
840
+ }
841
+ function optionalStringEntry(key2, value) {
842
+ if (value === void 0) {
843
+ return {};
844
+ }
845
+ if (typeof value !== "string") {
846
+ throw new Error(`${key2} must be a string`);
847
+ }
848
+ return { [key2]: value };
849
+ }
850
+ function isRecord2(value) {
851
+ return typeof value === "object" && value !== null && !Array.isArray(value);
852
+ }
853
+
854
+ // packages/poe-code-config/src/compile/schema-compiler.ts
855
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
856
+ import path3 from "node:path";
857
+ import { Node, Project, ScriptKind, SyntaxKind, ts } from "ts-morph";
858
+
859
+ // packages/toolcraft-schema/src/json-schema/compiler.ts
860
+ var draftTypes = ["null", "boolean", "object", "array", "number", "integer", "string"];
861
+ var draftTypeSet = new Set(draftTypes);
862
+ var metaSchemaKeywordProperties = {
863
+ type: {
864
+ anyOf: [
865
+ { enum: draftTypes },
866
+ { type: "array", items: { enum: draftTypes }, minItems: 1, uniqueItems: true }
867
+ ]
868
+ },
869
+ minLength: { type: "integer", minimum: 0 },
870
+ maxLength: { type: "integer", minimum: 0 },
871
+ minItems: { type: "integer", minimum: 0 },
872
+ maxItems: { type: "integer", minimum: 0 },
873
+ minProperties: { type: "integer", minimum: 0 },
874
+ maxProperties: { type: "integer", minimum: 0 }
875
+ };
876
+ var builtInRegistry = {
877
+ "https://json-schema.org/draft/2020-12/schema": {
878
+ $id: "https://json-schema.org/draft/2020-12/schema",
879
+ type: ["object", "boolean"],
880
+ properties: {
881
+ ...metaSchemaKeywordProperties,
882
+ $defs: { type: "object", additionalProperties: { $ref: "#" } }
883
+ }
884
+ },
885
+ "http://json-schema.org/draft-07/schema": {
886
+ $id: "http://json-schema.org/draft-07/schema#",
887
+ type: ["object", "boolean"],
888
+ properties: {
889
+ ...metaSchemaKeywordProperties,
890
+ definitions: { type: "object", additionalProperties: { $ref: "#" } }
891
+ }
892
+ }
893
+ };
894
+
895
+ // packages/poe-code-config/src/plan-scope.ts
896
+ var planConfigScope = defineScope("plan", {
897
+ plan_directory: {
898
+ type: "string",
899
+ default: "docs/plans",
900
+ env: "POE_PLAN_DIRECTORY",
901
+ doc: "Directory where planning documents are stored"
902
+ }
903
+ });
904
+
905
+ // packages/poe-code-config/src/store.ts
906
+ import { randomUUID as randomUUID3 } from "node:crypto";
907
+ import path10 from "node:path";
908
+
909
+ // packages/config-extends/src/discover.ts
910
+ import path4 from "node:path";
911
+
912
+ // packages/config-extends/src/parse.ts
913
+ import path5 from "node:path";
914
+
915
+ // packages/frontmatter/src/parse.ts
916
+ import { LineCounter, parse, parseDocument } from "yaml";
917
+
918
+ // packages/frontmatter/src/stringify.ts
919
+ import { stringify } from "yaml";
920
+
921
+ // packages/config-extends/src/parse.ts
922
+ import { parse as parseYaml } from "yaml";
923
+
924
+ // packages/config-extends/src/resolve.ts
925
+ import path6 from "node:path";
926
+
927
+ // packages/toolcraft-design/src/internal/color-support.ts
928
+ function supportsColor(env = process.env, stream = process.stdout) {
929
+ if (env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "0") {
930
+ return true;
931
+ }
932
+ if (env.NO_COLOR !== void 0) {
933
+ return false;
934
+ }
935
+ if (stream.isTTY !== true) {
936
+ return false;
937
+ }
938
+ return typeof env.TERM === "string" && env.TERM.length > 0 && env.TERM !== "dumb";
939
+ }
940
+
941
+ // packages/toolcraft-design/src/components/color.ts
942
+ var reset = "\x1B[0m";
943
+ var ansiStyles = {
944
+ reset: { open: reset },
945
+ bold: { open: "\x1B[1m" },
946
+ dim: { open: "\x1B[2m" },
947
+ italic: { open: "\x1B[3m" },
948
+ underline: { open: "\x1B[4m" },
949
+ inverse: { open: "\x1B[7m" },
950
+ strikethrough: { open: "\x1B[9m" },
951
+ black: { open: "\x1B[30m" },
952
+ red: { open: "\x1B[31m" },
953
+ green: { open: "\x1B[32m" },
954
+ yellow: { open: "\x1B[33m" },
955
+ blue: { open: "\x1B[34m" },
956
+ magenta: { open: "\x1B[35m" },
957
+ cyan: { open: "\x1B[36m" },
958
+ white: { open: "\x1B[37m" },
959
+ gray: { open: "\x1B[90m" },
960
+ magentaBright: { open: "\x1B[95m" },
961
+ cyanBright: { open: "\x1B[96m" },
962
+ bgRed: { open: "\x1B[41m" },
963
+ bgGreen: { open: "\x1B[42m" },
964
+ bgYellow: { open: "\x1B[43m" },
965
+ bgBlue: { open: "\x1B[44m" },
966
+ bgMagenta: { open: "\x1B[45m" }
967
+ };
968
+ var styleNames = Object.keys(ansiStyles);
969
+ function replaceAll(value, search, replacement) {
970
+ return value.split(search).join(replacement);
971
+ }
972
+ function applyStyles(text3, styles) {
973
+ if (!supportsColor() || styles.length === 0) {
974
+ return text3;
975
+ }
976
+ const open = styles.map((style) => style.open).join("");
977
+ const output = text3.includes(reset) ? replaceAll(text3, reset, `${reset}${open}`) : text3;
978
+ return `${open}${output}${reset}`;
979
+ }
980
+ function clampRgb(value) {
981
+ if (Number.isNaN(value)) {
982
+ return 0;
983
+ }
984
+ return Math.min(255, Math.max(0, Math.round(value)));
985
+ }
986
+ function hexChannel(value, offset) {
987
+ return Number.parseInt(value.slice(offset, offset + 2), 16);
988
+ }
989
+ function normalizeHex(value) {
990
+ const normalized = value.startsWith("#") ? value.slice(1) : value;
991
+ if (normalized.length !== 3 && normalized.length !== 6 || Array.from(normalized).some((char) => !"0123456789abcdefABCDEF".includes(char))) {
992
+ throw new Error(`Invalid hexadecimal color: ${value}`);
993
+ }
994
+ if (normalized.length === 3) {
995
+ const red = normalized[0];
996
+ const green = normalized[1];
997
+ const blue = normalized[2];
998
+ return [
999
+ Number.parseInt(`${red}${red}`, 16),
1000
+ Number.parseInt(`${green}${green}`, 16),
1001
+ Number.parseInt(`${blue}${blue}`, 16)
1002
+ ];
1003
+ }
1004
+ return [
1005
+ hexChannel(normalized, 0),
1006
+ hexChannel(normalized, 2),
1007
+ hexChannel(normalized, 4)
1008
+ ];
1009
+ }
1010
+ function rgbStyle(red, green, blue) {
1011
+ return {
1012
+ open: `\x1B[38;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`
1013
+ };
1014
+ }
1015
+ function bgRgbStyle(red, green, blue) {
1016
+ return {
1017
+ open: `\x1B[48;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`
1018
+ };
1019
+ }
1020
+ function createColor(styles = []) {
1021
+ const builder = ((text3) => applyStyles(String(text3), styles));
1022
+ for (const name of styleNames) {
1023
+ Object.defineProperty(builder, name, {
1024
+ configurable: true,
1025
+ enumerable: true,
1026
+ get: () => createColor([...styles, ansiStyles[name]])
1027
+ });
1028
+ }
1029
+ builder.hex = (value) => {
1030
+ const [red, green, blue] = normalizeHex(value);
1031
+ return createColor([...styles, rgbStyle(red, green, blue)]);
1032
+ };
1033
+ builder.rgb = (red, green, blue) => createColor([...styles, rgbStyle(red, green, blue)]);
1034
+ builder.bgHex = (value) => {
1035
+ const [red, green, blue] = normalizeHex(value);
1036
+ return createColor([...styles, bgRgbStyle(red, green, blue)]);
1037
+ };
1038
+ builder.bgRgb = (red, green, blue) => createColor([...styles, bgRgbStyle(red, green, blue)]);
1039
+ return builder;
1040
+ }
1041
+ var color = createColor();
1042
+
1043
+ // packages/toolcraft-design/src/tokens/brand.ts
1044
+ var brands = {
1045
+ purple: { name: "purple", primary: "#a200ff" },
1046
+ blue: { name: "blue", primary: "#2f6fed" },
1047
+ green: { name: "green", primary: "#1f9d57" }
1048
+ };
1049
+
1050
+ // packages/toolcraft-design/src/internal/theme-state.ts
1051
+ var defaults = {
1052
+ brand: "purple",
1053
+ label: "Poe"
1054
+ };
1055
+ var config = { ...defaults };
1056
+ var revision = 0;
1057
+ var brandConfigured = false;
1058
+ function getThemeConfig() {
1059
+ return { ...config };
1060
+ }
1061
+ function getThemeRevision() {
1062
+ return revision;
1063
+ }
1064
+ function isThemeBrandConfigured() {
1065
+ return brandConfigured;
1066
+ }
1067
+
1068
+ // packages/toolcraft-design/src/tokens/colors.ts
1069
+ var brand = brands.purple.primary;
1070
+ function withStyles(palette, styles) {
1071
+ return Object.defineProperty(palette, "styles", {
1072
+ value: styles,
1073
+ enumerable: false
1074
+ });
1075
+ }
1076
+ function brandColor(activeBrand, purple) {
1077
+ return activeBrand.name === "purple" ? purple : color.hex(activeBrand.primary);
1078
+ }
1079
+ function brandBackground(activeBrand, purple) {
1080
+ return activeBrand.name === "purple" ? purple : color.bgHex(activeBrand.primary);
1081
+ }
1082
+ function createPalette(activeBrand, mode) {
1083
+ const isPurple = activeBrand.name === "purple";
1084
+ if (mode === "light") {
1085
+ const active2 = color.hex(activeBrand.primary);
1086
+ const prompt2 = isPurple ? color.hex("#006699") : active2;
1087
+ const number2 = isPurple ? color.hex("#0077cc") : active2;
1088
+ return withStyles(
1089
+ {
1090
+ header: (text3) => active2.bold(text3),
1091
+ divider: (text3) => color.hex("#666666")(text3),
1092
+ prompt: (text3) => prompt2.bold(text3),
1093
+ number: (text3) => number2.bold(text3),
1094
+ intro: (text3) => color.bgHex(activeBrand.primary).white(` ${getThemeConfig().label} - ${text3} `),
1095
+ get resolvedSymbol() {
1096
+ return active2("\u25C7");
1097
+ },
1098
+ get errorSymbol() {
1099
+ return color.hex("#cc0000")("\u25A0");
1100
+ },
1101
+ accent: (text3) => prompt2.bold(text3),
1102
+ muted: (text3) => color.hex("#666666")(text3),
1103
+ success: (text3) => color.hex("#008800")(text3),
1104
+ warning: (text3) => color.hex("#cc6600")(text3),
1105
+ error: (text3) => color.hex("#cc0000")(text3),
1106
+ info: (text3) => active2(text3),
1107
+ badge: (text3) => color.bgHex("#cc6600").white(` ${text3} `)
1108
+ },
1109
+ {
1110
+ accent: { fg: isPurple ? "#006699" : activeBrand.primary, bold: true },
1111
+ muted: { fg: "#666666" },
1112
+ success: { fg: "#008800" },
1113
+ warning: { fg: "#cc6600" },
1114
+ error: { fg: "#cc0000" },
1115
+ info: { fg: activeBrand.primary }
1116
+ }
1117
+ );
1118
+ }
1119
+ const active = brandColor(activeBrand, color.magenta);
1120
+ const activeBright = brandColor(activeBrand, color.magentaBright);
1121
+ const activeBackground = brandBackground(activeBrand, color.bgMagenta);
1122
+ const prompt = isPurple ? color.cyan : active;
1123
+ const number = isPurple ? color.cyanBright : active;
1124
+ return withStyles(
1125
+ {
1126
+ header: (text3) => activeBright.bold(text3),
1127
+ divider: (text3) => color.dim(text3),
1128
+ prompt: (text3) => prompt(text3),
1129
+ number: (text3) => number(text3),
1130
+ intro: (text3) => activeBackground.white(` ${getThemeConfig().label} - ${text3} `),
1131
+ get resolvedSymbol() {
1132
+ return active("\u25C7");
1133
+ },
1134
+ get errorSymbol() {
1135
+ return color.red("\u25A0");
1136
+ },
1137
+ accent: (text3) => prompt(text3),
1138
+ muted: (text3) => color.dim(text3),
1139
+ success: (text3) => color.green(text3),
1140
+ warning: (text3) => color.yellow(text3),
1141
+ error: (text3) => color.red(text3),
1142
+ info: (text3) => active(text3),
1143
+ badge: (text3) => color.bgYellow.black(` ${text3} `)
1144
+ },
1145
+ {
1146
+ accent: { fg: isPurple ? "cyan" : activeBrand.primary, bold: true },
1147
+ muted: { dim: true },
1148
+ success: { fg: "green" },
1149
+ warning: { fg: "yellow" },
1150
+ error: { fg: "red" },
1151
+ info: { fg: isPurple ? "magenta" : activeBrand.primary }
1152
+ }
1153
+ );
1154
+ }
1155
+ var dark = createPalette(brands.purple, "dark");
1156
+ var light = createPalette(brands.purple, "light");
1157
+
1158
+ // packages/toolcraft-design/src/internal/output-format.ts
1159
+ import { AsyncLocalStorage } from "node:async_hooks";
1160
+ var VALID_FORMATS = /* @__PURE__ */ new Set(["terminal", "markdown", "json"]);
1161
+ var formatStorage = new AsyncLocalStorage();
1162
+ var cached;
1163
+ function resolveOutputFormat(env = process.env) {
1164
+ const scoped = formatStorage.getStore();
1165
+ if (scoped) {
1166
+ return scoped;
1167
+ }
1168
+ if (cached) {
1169
+ return cached;
1170
+ }
1171
+ const raw = env.OUTPUT_FORMAT?.toLowerCase();
1172
+ cached = VALID_FORMATS.has(raw) ? raw : "terminal";
1173
+ return cached;
1174
+ }
1175
+
1176
+ // packages/toolcraft-design/src/internal/theme-detect.ts
1177
+ function detectThemeFromEnv(env) {
1178
+ const apple = env.APPLE_INTERFACE_STYLE;
1179
+ if (typeof apple === "string") {
1180
+ return apple.toLowerCase() === "dark" ? "dark" : "light";
1181
+ }
1182
+ const vscodeKind = env.VSCODE_COLOR_THEME_KIND;
1183
+ if (typeof vscodeKind === "string") {
1184
+ const normalized = vscodeKind.toLowerCase();
1185
+ if (normalized.includes("light")) {
1186
+ return "light";
1187
+ }
1188
+ if (normalized.includes("dark")) {
1189
+ return "dark";
1190
+ }
1191
+ }
1192
+ const colorFGBG = env.COLORFGBG;
1193
+ if (typeof colorFGBG === "string") {
1194
+ const parts = colorFGBG.split(";").map((part) => Number.parseInt(part, 10));
1195
+ const background = parts.at(-1);
1196
+ if (Number.isFinite(background)) {
1197
+ return background >= 8 ? "light" : "dark";
1198
+ }
1199
+ }
1200
+ return void 0;
1201
+ }
1202
+ function resolveThemeName(env = process.env) {
1203
+ const raw = (env.POE_CODE_THEME ?? env.POE_THEME)?.toLowerCase();
1204
+ if (raw === "light" || raw === "dark") {
1205
+ return raw;
1206
+ }
1207
+ const detected = detectThemeFromEnv(env);
1208
+ if (detected) {
1209
+ return detected;
1210
+ }
1211
+ return "dark";
1212
+ }
1213
+ var themeCache = /* @__PURE__ */ new Map();
1214
+ var cachedRevision = -1;
1215
+ function getTheme(env) {
1216
+ const themeName = resolveThemeName(env);
1217
+ const config2 = getThemeConfig();
1218
+ const requestedBrand = env?.POE_BRAND?.toLowerCase();
1219
+ const activeBrandName = !isThemeBrandConfigured() && requestedBrand && Object.hasOwn(brands, requestedBrand) ? requestedBrand : config2.brand;
1220
+ const revision2 = getThemeRevision();
1221
+ if (revision2 !== cachedRevision) {
1222
+ themeCache.clear();
1223
+ cachedRevision = revision2;
1224
+ }
1225
+ const cacheKey = `${activeBrandName}:${themeName}`;
1226
+ const cachedTheme = themeCache.get(cacheKey);
1227
+ if (cachedTheme) {
1228
+ return cachedTheme;
1229
+ }
1230
+ const activeBrand = brands[activeBrandName];
1231
+ const theme = activeBrandName === "purple" ? themeName === "light" ? light : dark : createPalette(activeBrand, themeName);
1232
+ themeCache.set(cacheKey, theme);
1233
+ return theme;
1234
+ }
1235
+
1236
+ // packages/toolcraft-design/src/components/symbols.ts
1237
+ var symbols = {
1238
+ get info() {
1239
+ const format = resolveOutputFormat();
1240
+ if (format === "json") return "info";
1241
+ if (format === "markdown") return "(i)";
1242
+ return color.magenta("\u25CF");
1243
+ },
1244
+ get success() {
1245
+ const format = resolveOutputFormat();
1246
+ if (format === "json") return "success";
1247
+ if (format === "markdown") return "[ok]";
1248
+ return color.magenta("\u25C6");
1249
+ },
1250
+ get resolved() {
1251
+ const format = resolveOutputFormat();
1252
+ if (format === "json") return "resolved";
1253
+ if (format === "markdown") return ">";
1254
+ return getTheme().resolvedSymbol;
1255
+ },
1256
+ get errorResolved() {
1257
+ const format = resolveOutputFormat();
1258
+ if (format === "json") return "error";
1259
+ if (format === "markdown") return "[!]";
1260
+ return getTheme().errorSymbol;
1261
+ },
1262
+ get bar() {
1263
+ const format = resolveOutputFormat();
1264
+ if (format === "json") return "";
1265
+ if (format === "markdown") return "|";
1266
+ return "\u2502";
1267
+ },
1268
+ cornerTopRight: "\u256E",
1269
+ cornerBottomRight: "\u256F",
1270
+ get warning() {
1271
+ const format = resolveOutputFormat();
1272
+ if (format === "json") return "warning";
1273
+ if (format === "markdown") return "[!]";
1274
+ return "\u25B2";
1275
+ },
1276
+ get active() {
1277
+ const format = resolveOutputFormat();
1278
+ if (format === "json") return "active";
1279
+ if (format === "markdown") return "[x]";
1280
+ return "\u25C6";
1281
+ },
1282
+ get inactive() {
1283
+ const format = resolveOutputFormat();
1284
+ if (format === "json") return "inactive";
1285
+ if (format === "markdown") return "[ ]";
1286
+ return "\u25CB";
1287
+ }
1288
+ };
1289
+
1290
+ // packages/toolcraft-design/src/internal/strip-ansi.ts
1291
+ function stripAnsi(value) {
1292
+ let output = "";
1293
+ let index = 0;
1294
+ while (index < value.length) {
1295
+ const char = value[index];
1296
+ if (char === "\x1B") {
1297
+ index = skipEscapeSequence(value, index);
1298
+ continue;
1299
+ }
1300
+ if (char === "\x9B") {
1301
+ index = skipCsiSequence(value, index + 1);
1302
+ continue;
1303
+ }
1304
+ output += char;
1305
+ index += char.length;
1306
+ }
1307
+ return output;
1308
+ }
1309
+ function skipEscapeSequence(value, index) {
1310
+ const next = value[index + 1];
1311
+ if (next === "[") {
1312
+ return skipCsiSequence(value, index + 2);
1313
+ }
1314
+ if (next === "]") {
1315
+ return skipOscSequence(value, index + 2);
1316
+ }
1317
+ return Math.min(value.length, index + 2);
1318
+ }
1319
+ function skipCsiSequence(value, index) {
1320
+ while (index < value.length) {
1321
+ const codePoint = value.charCodeAt(index);
1322
+ index += 1;
1323
+ if (codePoint >= 64 && codePoint <= 126) {
1324
+ break;
1325
+ }
1326
+ }
1327
+ return index;
1328
+ }
1329
+ function skipOscSequence(value, index) {
1330
+ while (index < value.length) {
1331
+ if (value[index] === "\x07") {
1332
+ return index + 1;
1333
+ }
1334
+ if (value[index] === "\x1B" && value[index + 1] === "\\") {
1335
+ return index + 2;
1336
+ }
1337
+ index += 1;
1338
+ }
1339
+ return index;
1340
+ }
1341
+
1342
+ // packages/toolcraft-design/src/prompts/primitives/log.ts
1343
+ function renderMarkdownInline(value) {
1344
+ return stripAnsi(value).replaceAll("\r\n", " ").replaceAll("\n", " ").replaceAll("\r", " ");
1345
+ }
1346
+ function writeTerminalMessage(msg, {
1347
+ symbol: symbol2 = color.gray("\u2502"),
1348
+ secondarySymbol = color.gray("\u2502"),
1349
+ spacing: spacing2 = 1,
1350
+ withGuide = true
1351
+ } = {}) {
1352
+ const lines = [];
1353
+ const showGuide = withGuide !== false;
1354
+ const contentLines = msg.split("\n");
1355
+ const prefix = showGuide ? `${symbol2} ` : "";
1356
+ const continuationPrefix = showGuide ? `${secondarySymbol} ` : "";
1357
+ const emptyGuide = showGuide ? secondarySymbol : "";
1358
+ for (let index = 0; index < spacing2; index += 1) {
1359
+ lines.push(emptyGuide);
1360
+ }
1361
+ if (contentLines.length === 0) {
1362
+ process.stdout.write("\n");
1363
+ return;
1364
+ }
1365
+ const [firstLine = "", ...continuationLines] = contentLines;
1366
+ if (firstLine.length > 0) {
1367
+ lines.push(`${prefix}${firstLine}`);
1368
+ } else {
1369
+ lines.push(showGuide ? symbol2 : "");
1370
+ }
1371
+ for (const line of continuationLines) {
1372
+ if (line.length > 0) {
1373
+ lines.push(`${continuationPrefix}${line}`);
1374
+ continue;
1375
+ }
1376
+ lines.push(emptyGuide);
1377
+ }
1378
+ process.stdout.write(`${lines.join("\n")}
1379
+ `);
1380
+ }
1381
+ function message(msg, options) {
1382
+ const format = resolveOutputFormat();
1383
+ if (format === "markdown") {
1384
+ process.stdout.write(`- ${renderMarkdownInline(msg)}
1385
+ `);
1386
+ return;
1387
+ }
1388
+ if (format === "json") {
1389
+ process.stdout.write(
1390
+ `${JSON.stringify({ level: "message", message: stripAnsi(msg) })}
1391
+ `
1392
+ );
1393
+ return;
1394
+ }
1395
+ writeTerminalMessage(msg, options);
1396
+ }
1397
+ function info(msg) {
1398
+ const format = resolveOutputFormat();
1399
+ if (format === "markdown") {
1400
+ process.stdout.write(`- **info:** ${renderMarkdownInline(msg)}
1401
+ `);
1402
+ return;
1403
+ }
1404
+ if (format === "json") {
1405
+ process.stdout.write(
1406
+ `${JSON.stringify({ level: "info", message: stripAnsi(msg) })}
1407
+ `
1408
+ );
1409
+ return;
1410
+ }
1411
+ message(msg, { symbol: symbols.info });
1412
+ }
1413
+ function success(msg) {
1414
+ const format = resolveOutputFormat();
1415
+ if (format === "markdown") {
1416
+ process.stdout.write(`- **success:** ${renderMarkdownInline(msg)}
1417
+ `);
1418
+ return;
1419
+ }
1420
+ if (format === "json") {
1421
+ process.stdout.write(
1422
+ `${JSON.stringify({ level: "success", message: stripAnsi(msg) })}
1423
+ `
1424
+ );
1425
+ return;
1426
+ }
1427
+ message(msg, { symbol: symbols.success });
1428
+ }
1429
+ function warn(msg) {
1430
+ const format = resolveOutputFormat();
1431
+ if (format === "markdown") {
1432
+ process.stdout.write(`- **warning:** ${renderMarkdownInline(msg)}
1433
+ `);
1434
+ return;
1435
+ }
1436
+ if (format === "json") {
1437
+ process.stdout.write(
1438
+ `${JSON.stringify({ level: "warn", message: stripAnsi(msg) })}
1439
+ `
1440
+ );
1441
+ return;
1442
+ }
1443
+ message(msg, { symbol: color.yellow("\u25B2") });
1444
+ }
1445
+ function error(msg) {
1446
+ const format = resolveOutputFormat();
1447
+ if (format === "markdown") {
1448
+ process.stdout.write(`- **error:** ${renderMarkdownInline(msg)}
1449
+ `);
1450
+ return;
1451
+ }
1452
+ if (format === "json") {
1453
+ process.stdout.write(
1454
+ `${JSON.stringify({ level: "error", message: stripAnsi(msg) })}
1455
+ `
1456
+ );
1457
+ return;
1458
+ }
1459
+ message(msg, { symbol: color.red("\u25A0") });
1460
+ }
1461
+ var log = {
1462
+ info,
1463
+ success,
1464
+ message,
1465
+ warn,
1466
+ error
1467
+ };
1468
+
1469
+ // packages/toolcraft-design/src/components/logger.ts
1470
+ function createLogger(emitter) {
1471
+ const emit = (level, message2) => {
1472
+ if (emitter) {
1473
+ emitter(message2);
1474
+ return;
1475
+ }
1476
+ if (level === "success") {
1477
+ log.success(message2);
1478
+ return;
1479
+ }
1480
+ if (level === "warn") {
1481
+ log.warn(message2);
1482
+ return;
1483
+ }
1484
+ if (level === "error") {
1485
+ log.error(message2);
1486
+ return;
1487
+ }
1488
+ log.info(message2);
1489
+ };
1490
+ return {
1491
+ info(message2) {
1492
+ emit("info", message2);
1493
+ },
1494
+ success(message2) {
1495
+ emit("success", message2);
1496
+ },
1497
+ warn(message2) {
1498
+ emit("warn", message2);
1499
+ },
1500
+ error(message2) {
1501
+ emit("error", message2);
1502
+ },
1503
+ resolved(label, value) {
1504
+ if (emitter) {
1505
+ emitter(`${label}: ${value}`);
1506
+ return;
1507
+ }
1508
+ log.message(`${label}
1509
+ ${value}`, { symbol: symbols.resolved });
1510
+ },
1511
+ errorResolved(label, value) {
1512
+ if (emitter) {
1513
+ emitter(`${label}: ${value}`);
1514
+ return;
1515
+ }
1516
+ log.message(`${label}
1517
+ ${value}`, { symbol: symbols.errorResolved });
1518
+ },
1519
+ message(message2, symbol2) {
1520
+ if (emitter) {
1521
+ emitter(message2);
1522
+ return;
1523
+ }
1524
+ log.message(message2, { symbol: symbol2 ?? color.gray("\u2502") });
1525
+ }
1526
+ };
1527
+ }
1528
+ var logger = createLogger();
1529
+
1530
+ // packages/toolcraft-design/src/components/help-formatter.ts
1531
+ var graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1532
+
1533
+ // packages/toolcraft-design/src/components/table.ts
1534
+ var graphemeSegmenter2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1535
+
1536
+ // packages/toolcraft-design/src/components/detail-card.ts
1537
+ import stringWidth from "fast-string-width";
1538
+ import { wrapAnsi } from "fast-wrap-ansi";
1539
+
1540
+ // packages/toolcraft-design/src/components/browser.ts
1541
+ import { spawn as spawn2 } from "node:child_process";
1542
+ import process2 from "node:process";
1543
+
1544
+ // packages/toolcraft-design/src/terminal-markdown/parser/code-highlight.ts
1545
+ var codeLanguages = [
1546
+ {
1547
+ id: "javascript",
1548
+ aliases: ["js", "javascript", "mjs", "cjs", "es6"],
1549
+ family: "lexical",
1550
+ spec: "javascript"
1551
+ },
1552
+ { id: "javascriptreact", aliases: ["jsx"], family: "lexical", spec: "javascript" },
1553
+ {
1554
+ id: "typescript",
1555
+ aliases: ["ts", "typescript", "mts", "cts"],
1556
+ family: "lexical",
1557
+ spec: "typescript"
1558
+ },
1559
+ { id: "typescriptreact", aliases: ["tsx"], family: "lexical", spec: "typescript" },
1560
+ { id: "json", aliases: ["json"], family: "data", spec: "json" },
1561
+ { id: "jsonc", aliases: ["jsonc"], family: "data", spec: "jsonc" },
1562
+ { id: "jsonl", aliases: ["jsonl"], family: "data", spec: "json" },
1563
+ { id: "yaml", aliases: ["yaml", "yml"], family: "data", spec: "yaml" },
1564
+ { id: "css", aliases: ["css"], family: "style", spec: "css" },
1565
+ { id: "scss", aliases: ["scss"], family: "style", spec: "css" },
1566
+ { id: "sass", aliases: ["sass"], family: "style", spec: "css" },
1567
+ { id: "less", aliases: ["less"], family: "style", spec: "css" },
1568
+ { id: "postcss", aliases: ["postcss"], family: "style", spec: "css" },
1569
+ { id: "shellscript", aliases: ["sh", "bash", "shell", "shellscript", "zsh", "fish"], family: "lexical", spec: "shell" },
1570
+ { id: "python", aliases: ["py", "python"], family: "lexical", spec: "python" },
1571
+ { id: "sql", aliases: ["sql", "ddl", "dml"], family: "lexical", spec: "sql" },
1572
+ { id: "html", aliases: ["html"], family: "markup", spec: "html" },
1573
+ { id: "xml", aliases: ["xml", "svg"], family: "markup", spec: "xml" },
1574
+ { id: "markdown", aliases: ["md", "markdown"], family: "line", spec: "markdown" },
1575
+ { id: "diff", aliases: ["diff", "patch"], family: "line", spec: "diff" },
1576
+ { id: "dockerfile", aliases: ["dockerfile", "docker"], family: "line", spec: "dockerfile" },
1577
+ { id: "ini", aliases: ["ini", "properties"], family: "data", spec: "ini" },
1578
+ { id: "toml", aliases: ["toml"], family: "data", spec: "toml" },
1579
+ { id: "plaintext", aliases: ["text", "txt", "plain", "plaintext"], plain: true },
1580
+ { id: "ruby", aliases: ["rb", "ruby"], family: "lexical", spec: "ruby" },
1581
+ { id: "go", aliases: ["go", "golang"], family: "lexical", spec: "go" },
1582
+ { id: "java", aliases: ["java"], family: "lexical", spec: "java" },
1583
+ { id: "kotlin", aliases: ["kt", "kotlin", "kts"], family: "lexical", spec: "kotlin" },
1584
+ { id: "swift", aliases: ["swift"], family: "lexical", spec: "swift" },
1585
+ { id: "dart", aliases: ["dart"], family: "lexical", spec: "dart" },
1586
+ { id: "scala", aliases: ["scala", "sc"], family: "lexical", spec: "scala" },
1587
+ { id: "groovy", aliases: ["groovy", "gvy", "gy", "gsp"], family: "lexical", spec: "groovy" },
1588
+ { id: "c", aliases: ["c"], family: "lexical", spec: "c" },
1589
+ { id: "cpp", aliases: ["cpp", "c++", "cc", "cxx"], family: "lexical", spec: "cpp" },
1590
+ { id: "csharp", aliases: ["cs", "csharp", "c#"], family: "lexical", spec: "csharp" },
1591
+ { id: "objective-c", aliases: ["objc", "objectivec", "objective-c", "m", "mm"], family: "lexical", spec: "objectivec" },
1592
+ { id: "rust", aliases: ["rs", "rust"], family: "lexical", spec: "rust" },
1593
+ { id: "php", aliases: ["php"], family: "lexical", spec: "php" },
1594
+ { id: "lua", aliases: ["lua"], family: "lexical", spec: "lua" },
1595
+ { id: "perl", aliases: ["pl", "perl", "pm"], family: "lexical", spec: "perl" },
1596
+ { id: "r", aliases: ["r", "rscript"], family: "lexical", spec: "r" },
1597
+ { id: "powershell", aliases: ["ps1", "powershell", "pwsh"], family: "lexical", spec: "powershell" },
1598
+ { id: "elixir", aliases: ["ex", "exs", "elixir"], family: "lexical", spec: "elixir" },
1599
+ { id: "erlang", aliases: ["erl", "erlang", "hrl"], family: "lexical", spec: "erlang" },
1600
+ { id: "haskell", aliases: ["hs", "haskell"], family: "lexical", spec: "haskell" },
1601
+ { id: "clojure", aliases: ["clj", "cljs", "cljc", "clojure"], family: "lexical", spec: "clojure" },
1602
+ { id: "fsharp", aliases: ["fs", "fsi", "fsx", "fsharp"], family: "lexical", spec: "fsharp" },
1603
+ { id: "vb", aliases: ["vb", "vbnet"], family: "lexical", spec: "vb" },
1604
+ { id: "graphql", aliases: ["graphql", "gql"], family: "lexical", spec: "graphql" },
1605
+ { id: "protobuf", aliases: ["proto", "protobuf"], family: "lexical", spec: "protobuf" },
1606
+ { id: "hcl", aliases: ["hcl", "tf", "terraform"], family: "lexical", spec: "hcl" },
1607
+ { id: "nginx", aliases: ["nginx", "nginxconf"], family: "lexical", spec: "nginx" },
1608
+ { id: "makefile", aliases: ["makefile", "mk"], family: "lexical", spec: "makefile" },
1609
+ { id: "cmake", aliases: ["cmake"], family: "lexical", spec: "cmake" },
1610
+ { id: "gradle", aliases: ["gradle"], family: "lexical", spec: "groovy" },
1611
+ { id: "env", aliases: ["env", "dotenv"], family: "data", spec: "ini" },
1612
+ { id: "vue", aliases: ["vue"], family: "markup", spec: "html" },
1613
+ { id: "svelte", aliases: ["svelte"], family: "markup", spec: "html" }
1614
+ ];
1615
+ var languageByAlias = /* @__PURE__ */ new Map();
1616
+ for (const language of codeLanguages) {
1617
+ languageByAlias.set(language.id.toLowerCase(), language);
1618
+ for (const alias of language.aliases) {
1619
+ languageByAlias.set(alias.toLowerCase(), language);
1620
+ }
1621
+ }
1622
+ var jsKeywords = /* @__PURE__ */ new Set([
1623
+ "as",
1624
+ "async",
1625
+ "await",
1626
+ "break",
1627
+ "case",
1628
+ "catch",
1629
+ "class",
1630
+ "const",
1631
+ "continue",
1632
+ "debugger",
1633
+ "default",
1634
+ "delete",
1635
+ "do",
1636
+ "else",
1637
+ "export",
1638
+ "extends",
1639
+ "finally",
1640
+ "for",
1641
+ "from",
1642
+ "function",
1643
+ "get",
1644
+ "if",
1645
+ "import",
1646
+ "in",
1647
+ "instanceof",
1648
+ "let",
1649
+ "new",
1650
+ "of",
1651
+ "return",
1652
+ "set",
1653
+ "static",
1654
+ "super",
1655
+ "switch",
1656
+ "throw",
1657
+ "try",
1658
+ "typeof",
1659
+ "var",
1660
+ "void",
1661
+ "while",
1662
+ "with",
1663
+ "yield"
1664
+ ]);
1665
+ var tsKeywords = /* @__PURE__ */ new Set([
1666
+ ...jsKeywords,
1667
+ "abstract",
1668
+ "declare",
1669
+ "enum",
1670
+ "implements",
1671
+ "interface",
1672
+ "keyof",
1673
+ "namespace",
1674
+ "private",
1675
+ "protected",
1676
+ "public",
1677
+ "readonly",
1678
+ "satisfies",
1679
+ "type"
1680
+ ]);
1681
+ var cKeywords = /* @__PURE__ */ new Set(["auto", "break", "case", "const", "continue", "default", "do", "else", "enum", "extern", "for", "goto", "if", "inline", "register", "restrict", "return", "sizeof", "static", "struct", "switch", "typedef", "union", "volatile", "while"]);
1682
+ var cTypes = /* @__PURE__ */ new Set(["bool", "char", "double", "float", "int", "int16_t", "int32_t", "int64_t", "int8_t", "long", "short", "size_t", "uint16_t", "uint32_t", "uint64_t", "uint8_t", "void"]);
1683
+ var cppKeywords = /* @__PURE__ */ new Set([...cKeywords, "alignas", "alignof", "and", "bitand", "bitor", "catch", "class", "concept", "constexpr", "consteval", "constinit", "decltype", "delete", "explicit", "export", "friend", "mutable", "namespace", "new", "noexcept", "not", "operator", "or", "private", "protected", "public", "requires", "template", "this", "throw", "try", "typename", "using", "virtual", "xor"]);
1684
+ var cppTypes = /* @__PURE__ */ new Set([...cTypes, "auto", "bool", "char16_t", "char32_t", "std", "string", "wstring"]);
1685
+ var objectiveCKeywords = /* @__PURE__ */ new Set([...cKeywords, "@autoreleasepool", "@catch", "@class", "@dynamic", "@end", "@finally", "@implementation", "@import", "@interface", "@optional", "@package", "@private", "@property", "@protected", "@protocol", "@public", "@selector", "@synthesize", "@throw", "@try", "YES", "NO", "nil", "self", "super"]);
1686
+ var objectiveCTypes = /* @__PURE__ */ new Set([...cTypes, "BOOL", "Class", "CGFloat", "NSInteger", "NSObject", "NSString", "NSUInteger", "SEL", "id"]);
1687
+
1688
+ // packages/toolcraft-design/src/dashboard/terminal-width.ts
1689
+ var graphemeSegmenter3 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1690
+
1691
+ // packages/toolcraft-design/src/acp/writer.ts
1692
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1693
+ var storage = new AsyncLocalStorage2();
1694
+
1695
+ // packages/toolcraft-design/src/dashboard/terminal.ts
1696
+ import readline from "node:readline";
1697
+ import { PassThrough } from "node:stream";
1698
+
1699
+ // packages/toolcraft-design/src/explorer/state.ts
1700
+ var REGION_HEADER = 1 << 0;
1701
+ var REGION_LIST = 1 << 1;
1702
+ var REGION_DETAIL = 1 << 2;
1703
+ var REGION_FOOTER = 1 << 3;
1704
+ var REGION_MODAL = 1 << 4;
1705
+ var REGION_TOAST = 1 << 5;
1706
+ var REGION_ALL = REGION_HEADER | REGION_LIST | REGION_DETAIL | REGION_FOOTER | REGION_MODAL | REGION_TOAST;
1707
+
1708
+ // packages/toolcraft-design/src/prompts/interactive/glyphs.ts
1709
+ function supportsUnicode() {
1710
+ if (!process.platform.startsWith("win")) {
1711
+ return process.env.TERM !== "linux";
1712
+ }
1713
+ return Boolean(
1714
+ process.env.CI || process.env.WT_SESSION || process.env.TERMINUS_SUBLIME || process.env.ConEmuTask === "{cmd::Cmder}" || process.env.TERM_PROGRAM === "Terminus-Sublime" || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty" || process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm"
1715
+ );
1716
+ }
1717
+ var UNICODE = supportsUnicode();
1718
+ function glyph(unicode, ascii) {
1719
+ return UNICODE ? unicode : ascii;
1720
+ }
1721
+ var GLYPHS = {
1722
+ stepActive: glyph("\u25C6", "*"),
1723
+ stepCancel: glyph("\u25A0", "x"),
1724
+ stepError: glyph("\u25B2", "x"),
1725
+ stepSubmit: glyph("\u25C7", "o"),
1726
+ barStart: glyph("\u250C", "T"),
1727
+ bar: glyph("\u2502", "|"),
1728
+ barEnd: glyph("\u2514", "-"),
1729
+ radioActive: glyph("\u25CF", ">"),
1730
+ radioInactive: glyph("\u25CB", " "),
1731
+ checkboxActive: "[ ]",
1732
+ checkboxSelected: "[x]",
1733
+ checkboxInactive: "[ ]",
1734
+ passwordMask: glyph("\u2022", "*"),
1735
+ ellipsis: "..."
1736
+ };
1737
+
1738
+ // packages/toolcraft-design/src/prompts/interactive/core.ts
1739
+ import { EventEmitter } from "node:events";
1740
+ import * as readline2 from "node:readline";
1741
+
1742
+ // packages/toolcraft-design/src/prompts/interactive/wrap.ts
1743
+ import { wrapAnsi as wrapAnsi2 } from "fast-wrap-ansi";
1744
+ import stringWidth2 from "fast-string-width";
1745
+
1746
+ // packages/toolcraft-design/src/prompts/interactive/pagination.ts
1747
+ import { wrapAnsi as wrapAnsi3 } from "fast-wrap-ansi";
1748
+
1749
+ // packages/toolcraft-design/src/static/spinner.ts
1750
+ var SPINNER_FRAMES = Object.freeze(["\u25D2", "\u25D0", "\u25D3", "\u25D1"]);
1751
+
1752
+ // packages/config-extends/src/prompt-document.ts
1753
+ import { readFile, realpath } from "node:fs/promises";
1754
+ import path7 from "node:path";
1755
+
1756
+ // packages/config-mutations/src/execution/apply-mutation.ts
1757
+ import { randomUUID as randomUUID2 } from "node:crypto";
1758
+ import path9 from "node:path";
1759
+
1760
+ // packages/config-mutations/src/formats/json.ts
1761
+ import * as jsonc from "jsonc-parser";
1762
+
1763
+ // packages/config-mutations/src/formats/toml.ts
1764
+ import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
1765
+
1766
+ // packages/config-mutations/src/formats/yaml.ts
1767
+ import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
1768
+
1769
+ // packages/config-mutations/src/execution/path-utils.ts
1770
+ import path8 from "node:path";
1771
+
1772
+ // packages/poe-code-config/src/store.ts
1773
+ var EMPTY_DOCUMENT = `${JSON.stringify({}, null, 2)}
1774
+ `;
1775
+
1776
+ // packages/poe-code-config/src/inspect.ts
1777
+ import path11 from "node:path";
1778
+ var EMPTY_DOCUMENT2 = `${JSON.stringify({}, null, 2)}
1779
+ `;
1780
+
1781
+ // packages/poe-code-config/src/configured-services.ts
1782
+ import { randomUUID as randomUUID4 } from "node:crypto";
1783
+ import path12 from "node:path";
1784
+
1785
+ // packages/agent-defs/src/agents/claude-code.ts
1786
+ var claudeCodeAgent = {
1787
+ id: "claude-code",
1788
+ name: "claude-code",
1789
+ label: "Claude Code",
1790
+ summary: "Anthropic's agentic coding tool for the terminal.",
1791
+ aliases: ["claude"],
1792
+ binaryName: "claude",
1793
+ apiShapes: ["anthropic-messages"],
1794
+ otelCapture: {
1795
+ env: {
1796
+ CLAUDE_CODE_ENABLE_TELEMETRY: "1"
1797
+ }
1798
+ },
1799
+ configPath: "~/.claude.json",
1800
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
1801
+ branding: {
1802
+ colors: {
1803
+ dark: "#C15F3C",
1804
+ light: "#C15F3C"
1805
+ }
1806
+ }
1807
+ };
1808
+
1809
+ // packages/agent-defs/src/agents/claude-desktop.ts
1810
+ var claudeDesktopAgent = {
1811
+ id: "claude-desktop",
1812
+ name: "claude-desktop",
1813
+ label: "Claude Desktop",
1814
+ summary: "Anthropic's official desktop application for Claude",
1815
+ configPath: "~/.config/Claude/claude_desktop_config.json",
1816
+ configPaths: {
1817
+ darwin: "~/Library/Application Support/Claude/claude_desktop_config.json",
1818
+ linux: "~/.config/Claude/claude_desktop_config.json",
1819
+ win32: "~/AppData/Roaming/Claude/claude_desktop_config.json"
1820
+ },
1821
+ capabilities: ["mcp"],
1822
+ branding: {
1823
+ colors: {
1824
+ dark: "#D97757",
1825
+ light: "#D97757"
1826
+ }
1827
+ }
1828
+ };
1829
+
1830
+ // packages/agent-defs/src/agents/codex.ts
1831
+ var codexAgent = {
1832
+ id: "codex",
1833
+ name: "codex",
1834
+ label: "Codex",
1835
+ summary: "OpenAI's coding agent for the terminal.",
1836
+ binaryName: "codex",
1837
+ apiShapes: ["openai-responses"],
1838
+ otelCapture: {
1839
+ args: (endpoint, content) => [
1840
+ "-c",
1841
+ `otel.trace_exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/traces`)},protocol="json"}}`,
1842
+ "-c",
1843
+ `otel.exporter={"otlp-http"={endpoint=${JSON.stringify(`${endpoint}/v1/logs`)},protocol="json"}}`,
1844
+ "-c",
1845
+ `otel.log_user_prompt=${content}`
1846
+ ]
1847
+ },
1848
+ configPath: "~/.codex/config.toml",
1849
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
1850
+ branding: {
1851
+ colors: {
1852
+ dark: "#D5D9DF",
1853
+ light: "#7A7F86"
1854
+ }
1855
+ }
1856
+ };
1857
+
1858
+ // packages/agent-defs/src/agents/cursor.ts
1859
+ var cursorAgent = {
1860
+ id: "cursor",
1861
+ name: "cursor",
1862
+ aliases: ["cursor-agent"],
1863
+ label: "Cursor",
1864
+ summary: "Cursor's CLI coding agent.",
1865
+ binaryName: "cursor-agent",
1866
+ configPath: "~/.cursor/mcp.json",
1867
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
1868
+ branding: {
1869
+ colors: {
1870
+ dark: "#FFFFFF",
1871
+ light: "#000000"
1872
+ }
1873
+ }
1874
+ };
1875
+
1876
+ // packages/agent-defs/src/agents/gemini-cli.ts
1877
+ var geminiCliAgent = {
1878
+ id: "gemini-cli",
1879
+ name: "gemini-cli",
1880
+ aliases: ["gemini"],
1881
+ label: "Gemini CLI",
1882
+ summary: "Google's open-source AI agent for the terminal.",
1883
+ binaryName: "gemini",
1884
+ configPath: "~/.gemini/settings.json",
1885
+ apiShapes: ["google-generations"],
1886
+ capabilities: ["spawn", "configure", "install", "test", "skill"],
1887
+ branding: {
1888
+ colors: {
1889
+ dark: "#8AB4F8",
1890
+ light: "#1A73E8"
1891
+ }
1892
+ }
1893
+ };
1894
+
1895
+ // packages/agent-defs/src/agents/opencode.ts
1896
+ var openCodeAgent = {
1897
+ id: "opencode",
1898
+ name: "opencode",
1899
+ label: "OpenCode CLI",
1900
+ summary: "Open-source AI coding agent for the terminal.",
1901
+ binaryName: "opencode",
1902
+ apiShapes: ["openai-chat-completions"],
1903
+ otelCapture: {
1904
+ env: {
1905
+ OPENCODE_CONFIG_CONTENT: '{"experimental":{"openTelemetry":true}}'
1906
+ }
1907
+ },
1908
+ configPath: "~/.config/opencode/opencode.json",
1909
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
1910
+ branding: {
1911
+ colors: {
1912
+ dark: "#4A4F55",
1913
+ light: "#2F3338"
1914
+ }
1915
+ }
1916
+ };
1917
+
1918
+ // packages/agent-defs/src/agents/kimi.ts
1919
+ var kimiAgent = {
1920
+ id: "kimi",
1921
+ name: "kimi",
1922
+ label: "Kimi",
1923
+ summary: "Moonshot AI's coding agent for the terminal.",
1924
+ aliases: ["kimi-cli"],
1925
+ binaryName: "kimi",
1926
+ apiShapes: ["openai-chat-completions"],
1927
+ configPath: "~/.kimi/mcp.json",
1928
+ capabilities: ["spawn", "configure", "install", "test", "mcp"],
1929
+ branding: {
1930
+ colors: {
1931
+ dark: "#7B68EE",
1932
+ light: "#6A5ACD"
1933
+ }
1934
+ }
1935
+ };
1936
+
1937
+ // packages/agent-defs/src/agents/goose.ts
1938
+ var gooseAgent = {
1939
+ id: "goose",
1940
+ name: "goose",
1941
+ label: "Goose",
1942
+ summary: "Block's open-source AI agent with ACP support.",
1943
+ binaryName: "goose",
1944
+ apiShapes: ["openai-chat-completions"],
1945
+ otelCapture: {},
1946
+ configPath: "~/.config/goose/config.yaml",
1947
+ capabilities: ["spawn", "configure", "install", "test", "skill", "mcp"],
1948
+ branding: {
1949
+ colors: {
1950
+ dark: "#FF6B35",
1951
+ light: "#E85D26"
1952
+ }
1953
+ }
1954
+ };
1955
+
1956
+ // packages/agent-defs/src/agents/pi.ts
1957
+ var piAgent = {
1958
+ id: "pi",
1959
+ name: "pi",
1960
+ aliases: ["pi-agent"],
1961
+ label: "Pi",
1962
+ summary: "Minimal AI coding agent for the terminal.",
1963
+ binaryName: "pi",
1964
+ capabilities: ["spawn"],
1965
+ branding: {
1966
+ colors: {
1967
+ dark: "#F2F2F2",
1968
+ light: "#242424"
1969
+ }
1970
+ }
1971
+ };
1972
+
1973
+ // packages/agent-defs/src/agents/poe-agent.ts
1974
+ var poeAgentAgent = {
1975
+ id: "poe-agent",
1976
+ name: "poe-agent",
1977
+ label: "Poe Agent",
1978
+ summary: "Run one-shot prompts with the built-in Poe agent runtime.",
1979
+ apiShapes: ["openai-responses", "openai-chat-completions"],
1980
+ configPath: "~/.poe-code/config.json",
1981
+ capabilities: ["configure"],
1982
+ branding: {
1983
+ colors: {
1984
+ dark: "#A465F7",
1985
+ light: "#7A3FD3"
1986
+ }
1987
+ }
1988
+ };
1989
+
1990
+ // packages/agent-defs/src/registry.ts
1991
+ function freezeAgent(agent) {
1992
+ if (agent.aliases !== void 0) {
1993
+ Object.freeze(agent.aliases);
1994
+ }
1995
+ if (agent.apiShapes !== void 0) {
1996
+ Object.freeze(agent.apiShapes);
1997
+ }
1998
+ if (agent.capabilities !== void 0) {
1999
+ Object.freeze(agent.capabilities);
2000
+ }
2001
+ if (agent.otelCapture?.env !== void 0) {
2002
+ Object.freeze(agent.otelCapture.env);
2003
+ }
2004
+ if (agent.otelCapture !== void 0) {
2005
+ Object.freeze(agent.otelCapture);
2006
+ }
2007
+ Object.freeze(agent.branding.colors);
2008
+ Object.freeze(agent.branding);
2009
+ return Object.freeze(agent);
2010
+ }
2011
+ var allAgents = Object.freeze([
2012
+ freezeAgent(claudeCodeAgent),
2013
+ freezeAgent(claudeDesktopAgent),
2014
+ freezeAgent(codexAgent),
2015
+ freezeAgent(cursorAgent),
2016
+ freezeAgent(geminiCliAgent),
2017
+ freezeAgent(openCodeAgent),
2018
+ freezeAgent(kimiAgent),
2019
+ freezeAgent(gooseAgent),
2020
+ freezeAgent(piAgent),
2021
+ freezeAgent(poeAgentAgent)
2022
+ ]);
2023
+ var lookup = /* @__PURE__ */ new Map();
2024
+ for (const agent of allAgents) {
2025
+ const values = [agent.id, agent.name, ...agent.aliases ?? []];
2026
+ for (const value of values) {
2027
+ const normalized = value.toLowerCase();
2028
+ if (!lookup.has(normalized)) {
2029
+ lookup.set(normalized, agent.id);
2030
+ }
2031
+ }
2032
+ }
2033
+
2034
+ // packages/providers/src/auth/api-key.ts
2035
+ function requireApiKeyAuth(provider) {
2036
+ if (provider.auth.kind !== "api-key") {
2037
+ throw new Error(
2038
+ `Provider ${provider.id} does not use api-key auth (got ${provider.auth.kind}).`
2039
+ );
2040
+ }
2041
+ return provider.auth;
2042
+ }
2043
+ async function acquireApiKey(provider, options, context) {
2044
+ const auth = requireApiKeyAuth(provider);
2045
+ const candidate = options.apiKey ?? await context.promptForSecret?.(auth.prompt);
2046
+ const trimmed = candidate?.trim();
2047
+ if (!trimmed) {
2048
+ throw new Error(
2049
+ `No API key available for provider "${provider.id}". Pass --api-key or run interactively.`
2050
+ );
2051
+ }
2052
+ return trimmed;
2053
+ }
2054
+ var apiKeyAuthStrategy = {
2055
+ async login(provider, options, context) {
2056
+ const apiKey = await acquireApiKey(provider, options, context);
2057
+ await context.secretStore.set(apiKey);
2058
+ return apiKey;
2059
+ },
2060
+ async logout(_provider, context) {
2061
+ await context.secretStore.delete();
2062
+ },
2063
+ async isLoggedIn(_provider, context) {
2064
+ const value = await context.secretStore.get({ readOnly: context.readOnly });
2065
+ return typeof value === "string" && value.trim().length > 0;
2066
+ },
2067
+ async resolveCredential(provider, context) {
2068
+ requireApiKeyAuth(provider);
2069
+ const value = await context.secretStore.get({ readOnly: context.readOnly });
2070
+ if (!value || value.trim().length === 0) {
2071
+ throw new Error(
2072
+ `No stored credential for provider "${provider.id}". Run \`poe-code provider login ${provider.id}\`.`
2073
+ );
2074
+ }
2075
+ return value.trim();
2076
+ }
2077
+ };
2078
+
2079
+ // packages/providers/src/compatibility.ts
2080
+ function resolveApiShape(provider, agent) {
2081
+ if (!provider.apiShapes || !agent.apiShapes) {
2082
+ return void 0;
2083
+ }
2084
+ for (const shapeId of agent.apiShapes) {
2085
+ if (provider.apiShapes.some((shape) => shape.id === shapeId)) {
2086
+ return shapeId;
2087
+ }
2088
+ }
2089
+ return void 0;
2090
+ }
2091
+
2092
+ // packages/providers/src/registry.ts
2093
+ var ProviderRegistry = class {
2094
+ providers;
2095
+ byId;
2096
+ storeFactory;
2097
+ envVars;
2098
+ constructor(providers, storeFactory, options) {
2099
+ const byId = /* @__PURE__ */ new Map();
2100
+ const storageKeys = /* @__PURE__ */ new Map();
2101
+ for (const provider of providers) {
2102
+ const providerId = provider.id.trim();
2103
+ if (providerId.length === 0) {
2104
+ throw new Error("Provider id must not be blank.");
2105
+ }
2106
+ if (provider.id !== providerId) {
2107
+ throw new Error(
2108
+ `Provider id must not include surrounding whitespace: ${JSON.stringify(provider.id)}`
2109
+ );
2110
+ }
2111
+ if (byId.has(providerId)) {
2112
+ throw new Error(`Duplicate provider id: ${providerId}`);
2113
+ }
2114
+ if (provider.auth.kind === "api-key") {
2115
+ if (storageKeys.has(provider.auth.storageKey)) {
2116
+ throw new Error(
2117
+ `Duplicate provider credential storage key: ${provider.auth.storageKey}`
2118
+ );
2119
+ }
2120
+ storageKeys.set(provider.auth.storageKey, providerId);
2121
+ }
2122
+ byId.set(providerId, provider);
2123
+ }
2124
+ this.providers = Object.freeze([...providers]);
2125
+ this.byId = byId;
2126
+ this.storeFactory = storeFactory;
2127
+ this.envVars = options?.envVars ?? {};
2128
+ }
2129
+ list() {
2130
+ return this.providers;
2131
+ }
2132
+ get(id) {
2133
+ return this.byId.get(id);
2134
+ }
2135
+ forAgent(agent) {
2136
+ return this.providers.filter((provider) => {
2137
+ return resolveApiShape(provider, agent) !== void 0;
2138
+ });
2139
+ }
2140
+ async isLoggedIn(id, options = {}) {
2141
+ const provider = this.requireProvider(id);
2142
+ if (provider.auth.kind === "api-key") {
2143
+ const envValue = readOwnEnvValue(this.envVars, provider.auth.envVar);
2144
+ if (typeof envValue === "string" && envValue.trim().length > 0) {
2145
+ return true;
2146
+ }
2147
+ }
2148
+ const store = this.requireStore(provider);
2149
+ const credential = await store.get({ readOnly: options.readOnly });
2150
+ return typeof credential === "string" && credential.trim().length > 0;
2151
+ }
2152
+ async login(id, options, context) {
2153
+ const provider = this.requireProvider(id);
2154
+ const store = context?.store ?? this.requireStore(provider);
2155
+ if (provider.auth.kind !== "api-key") {
2156
+ throw new Error(`Provider "${id}" does not use api-key auth.`);
2157
+ }
2158
+ const auth = provider.auth;
2159
+ const envApiKey = readOwnEnvValue(context?.envVars ?? this.envVars, auth.envVar);
2160
+ const resolvedApiKey = options.apiKey ?? (typeof envApiKey === "string" && envApiKey.trim() ? envApiKey : void 0);
2161
+ if (auth.preferredLogin && context?.resolvePreferredLogin) {
2162
+ const apiKey = normalizeRequiredCredential(provider.id, await context.resolvePreferredLogin({
2163
+ provider,
2164
+ apiKey: options.apiKey,
2165
+ envValue: typeof envApiKey === "string" ? envApiKey : void 0
2166
+ }));
2167
+ await store.set(apiKey);
2168
+ return;
2169
+ }
2170
+ await apiKeyAuthStrategy.login(
2171
+ provider,
2172
+ { apiKey: resolvedApiKey },
2173
+ { secretStore: store, promptForSecret: context?.promptForSecret }
2174
+ );
2175
+ }
2176
+ async resolveCredential(id, options = {}, context) {
2177
+ const provider = this.requireProvider(id);
2178
+ if (provider.auth.kind !== "api-key") {
2179
+ throw new Error(`Provider "${id}" does not use api-key auth.`);
2180
+ }
2181
+ if (options.apiKey !== void 0) {
2182
+ return normalizeRequiredCredential(provider.id, options.apiKey);
2183
+ }
2184
+ const envVars = context?.envVars ?? this.envVars;
2185
+ const envApiKey = readOwnEnvValue(envVars, provider.auth.envVar);
2186
+ if (typeof envApiKey === "string" && envApiKey.trim().length > 0) {
2187
+ return envApiKey.trim();
2188
+ }
2189
+ const store = this.requireStore(provider);
2190
+ return apiKeyAuthStrategy.resolveCredential(provider, {
2191
+ secretStore: store,
2192
+ readOnly: context?.readOnly
2193
+ });
2194
+ }
2195
+ async logout(id, options = {}) {
2196
+ const provider = this.requireProvider(id);
2197
+ const store = options.store ?? this.requireStore(provider);
2198
+ await store.delete();
2199
+ }
2200
+ requireProvider(id) {
2201
+ const provider = this.byId.get(id);
2202
+ if (!provider) {
2203
+ throw new Error(`Unknown provider: "${id}".`);
2204
+ }
2205
+ return provider;
2206
+ }
2207
+ requireStore(provider) {
2208
+ if (!this.storeFactory) {
2209
+ throw new Error(`No store factory configured for ProviderRegistry.`);
2210
+ }
2211
+ return this.storeFactory(provider);
2212
+ }
2213
+ };
2214
+ function normalizeRequiredCredential(providerId, value) {
2215
+ const trimmed = value.trim();
2216
+ if (trimmed.length === 0) {
2217
+ throw new Error(`No API key available for provider "${providerId}".`);
2218
+ }
2219
+ return trimmed;
2220
+ }
2221
+ function readOwnEnvValue(envVars, name) {
2222
+ return Object.prototype.hasOwnProperty.call(envVars, name) ? envVars[name] : void 0;
2223
+ }
2224
+
2225
+ // packages/providers/src/types.ts
2226
+ function defineProvider(provider) {
2227
+ if (provider.auth.kind === "api-key") {
2228
+ Object.freeze(provider.auth.prompt);
2229
+ }
2230
+ Object.freeze(provider.auth);
2231
+ for (const shape of provider.apiShapes ?? []) {
2232
+ Object.freeze(shape);
2233
+ }
2234
+ if (provider.apiShapes !== void 0) {
2235
+ Object.freeze(provider.apiShapes);
2236
+ }
2237
+ if (provider.modelInput !== void 0) {
2238
+ Object.freeze(provider.modelInput);
2239
+ }
2240
+ for (const source of Object.values(provider.env ?? {})) {
2241
+ Object.freeze(source);
2242
+ }
2243
+ if (provider.env !== void 0) {
2244
+ Object.freeze(provider.env);
2245
+ }
2246
+ return Object.freeze(provider);
2247
+ }
2248
+
2249
+ // packages/providers/src/providers/poe.ts
2250
+ var POE_PROVIDER_ID = "poe";
2251
+ var poeProvider = defineProvider({
2252
+ id: POE_PROVIDER_ID,
2253
+ label: "Poe",
2254
+ summary: "Route AI coding agents through Poe's API.",
2255
+ baseUrl: "https://api.poe.com",
2256
+ agentBaseUrl: "https://api.poe.com",
2257
+ baseUrlEnvVar: "POE_BASE_URL",
2258
+ baseUrlEnvPath: "v1",
2259
+ agentBaseUrlPath: "",
2260
+ auth: {
2261
+ kind: "api-key",
2262
+ envVar: "POE_API_KEY",
2263
+ storageKey: "provider:poe",
2264
+ prompt: { title: "Poe API key" },
2265
+ preferredLogin: "oauth"
2266
+ },
2267
+ env: {
2268
+ ANTHROPIC_CUSTOM_HEADERS: {
2269
+ kind: "providerCredential",
2270
+ prefix: "Authorization: Bearer "
2271
+ }
2272
+ },
2273
+ apiShapes: [
2274
+ {
2275
+ id: "openai-chat-completions",
2276
+ envBaseUrlPath: "v1"
2277
+ },
2278
+ {
2279
+ id: "openai-responses",
2280
+ envBaseUrlPath: "v1"
2281
+ },
2282
+ {
2283
+ id: "anthropic-messages",
2284
+ envBaseUrlPath: "anthropic"
2285
+ }
2286
+ ]
2287
+ });
2288
+
2289
+ // packages/providers/src/provider-order.ts
2290
+ function orderAuthProviders(providers) {
2291
+ return Object.freeze([...providers].sort(compareAuthProviders));
2292
+ }
2293
+ function compareAuthProviders(left, right) {
2294
+ const rankDifference = authProviderRank(left) - authProviderRank(right);
2295
+ if (rankDifference !== 0) {
2296
+ return rankDifference;
2297
+ }
2298
+ return left.id.localeCompare(right.id);
2299
+ }
2300
+ function authProviderRank(provider) {
2301
+ if (provider.auth.kind === "api-key" && provider.auth.preferredLogin === "oauth") {
2302
+ return 0;
2303
+ }
2304
+ if (provider.requiresBaseUrl === true) {
2305
+ return 2;
2306
+ }
2307
+ return 1;
2308
+ }
2309
+
2310
+ // packages/providers/src/providers/anthropic.ts
2311
+ var anthropicProvider = defineProvider({
2312
+ id: "anthropic",
2313
+ label: "Anthropic",
2314
+ summary: "Route AI coding agents through Anthropic's API.",
2315
+ baseUrl: "https://api.anthropic.com",
2316
+ auth: {
2317
+ kind: "api-key",
2318
+ envVar: "ANTHROPIC_API_KEY",
2319
+ storageKey: "provider:anthropic",
2320
+ prompt: { title: "Anthropic API key" }
2321
+ },
2322
+ env: {
2323
+ ANTHROPIC_API_KEY: { kind: "providerCredential" }
2324
+ },
2325
+ apiShapes: [
2326
+ {
2327
+ id: "anthropic-messages"
2328
+ }
2329
+ ]
2330
+ });
2331
+
2332
+ // packages/providers/src/providers/cloudflare.ts
2333
+ var cloudflareProvider = defineProvider({
2334
+ id: "cloudflare",
2335
+ label: "Cloudflare AI Gateway",
2336
+ summary: "Route coding agents through Cloudflare AI Gateway.",
2337
+ baseUrlEnvVar: "CF_AIG_BASE_URL",
2338
+ requiresBaseUrl: true,
2339
+ modelInput: { kind: "freeform" },
2340
+ auth: {
2341
+ kind: "api-key",
2342
+ envVar: "CF_AIG_TOKEN",
2343
+ storageKey: "provider:cloudflare",
2344
+ prompt: { title: "Cloudflare AI Gateway token" }
2345
+ },
2346
+ env: {
2347
+ ANTHROPIC_CUSTOM_HEADERS: {
2348
+ kind: "providerCredential",
2349
+ prefix: "Authorization: Bearer "
2350
+ }
2351
+ },
2352
+ apiShapes: [
2353
+ {
2354
+ id: "openai-chat-completions",
2355
+ baseUrlPath: "compat"
2356
+ },
2357
+ {
2358
+ id: "openai-responses",
2359
+ baseUrlPath: "openai"
2360
+ },
2361
+ {
2362
+ id: "anthropic-messages",
2363
+ baseUrlPath: "anthropic"
2364
+ },
2365
+ {
2366
+ id: "google-generations",
2367
+ baseUrlPath: "google-ai-studio"
2368
+ }
2369
+ ]
2370
+ });
2371
+
2372
+ // packages/providers/src/providers/openai.ts
2373
+ var openaiProvider = defineProvider({
2374
+ id: "openai",
2375
+ label: "OpenAI",
2376
+ summary: "Route AI coding agents through OpenAI's API.",
2377
+ baseUrl: "https://api.openai.com/v1",
2378
+ auth: {
2379
+ kind: "api-key",
2380
+ envVar: "OPENAI_API_KEY",
2381
+ storageKey: "provider:openai",
2382
+ prompt: { title: "OpenAI API key" }
2383
+ },
2384
+ apiShapes: [
2385
+ {
2386
+ id: "openai-responses"
2387
+ },
2388
+ {
2389
+ id: "openai-chat-completions"
2390
+ }
2391
+ ]
2392
+ });
2393
+
2394
+ // packages/providers/src/providers/generated.ts
2395
+ var allAuthProviders = orderAuthProviders([
2396
+ anthropicProvider,
2397
+ cloudflareProvider,
2398
+ openaiProvider,
2399
+ poeProvider
2400
+ ]);
2401
+
2402
+ // packages/poe-code-config/src/configured-services.ts
2403
+ var agentsById = new Map(allAgents.map((agent) => [agent.id, agent]));
2404
+ var defaultProviderRegistry = new ProviderRegistry(allAuthProviders);
2405
+ var EMPTY_DOCUMENT3 = `${JSON.stringify({}, null, 2)}
2406
+ `;
2407
+
2408
+ // packages/poe-code-config/src/state/index.ts
2409
+ import os from "node:os";
2410
+
2411
+ // packages/poe-code-config/src/state/jobs.ts
2412
+ import { randomUUID as randomUUID5 } from "node:crypto";
2413
+ import path14 from "node:path";
2414
+
2415
+ // packages/poe-code-config/src/state/fs.ts
2416
+ import * as nodeFs from "node:fs/promises";
2417
+ import path13 from "node:path";
2418
+
2419
+ // packages/poe-code-config/src/state/templates.ts
2420
+ import { randomUUID as randomUUID6 } from "node:crypto";
2421
+ import path15 from "node:path";
2422
+
2423
+ // src/cli/environment.ts
2424
+ var DEFAULT_POE_API_BASE_URL = "https://api.poe.com/v1";
2425
+ function resolvePoeApiBaseUrl(variables = process.env) {
2426
+ return resolvePoeBaseUrls(variables).poeApiBaseUrl;
2427
+ }
2428
+ function resolvePoeBaseUrls(variables) {
2429
+ const raw = Object.hasOwn(variables, "POE_BASE_URL") ? variables.POE_BASE_URL : void 0;
2430
+ const baseInput = typeof raw === "string" && raw.trim().length > 0 ? raw.trim() : DEFAULT_POE_API_BASE_URL;
2431
+ const parsed = parseUrl(baseInput);
2432
+ if (!parsed) {
2433
+ const trimmed = trimTrailingSlash(baseInput.trim());
2434
+ return {
2435
+ poeApiBaseUrl: ensureV1Suffix(trimmed),
2436
+ poeBaseUrl: stripV1Suffix(trimmed)
2437
+ };
2438
+ }
2439
+ const normalizedPath = normalizePath(parsed.pathname);
2440
+ return {
2441
+ poeApiBaseUrl: buildApiBaseUrl(parsed.origin, normalizedPath),
2442
+ poeBaseUrl: buildPoeBaseUrl(parsed.origin, normalizedPath)
2443
+ };
2444
+ }
2445
+ function parseUrl(value) {
2446
+ try {
2447
+ return new URL(value);
2448
+ } catch {
2449
+ return null;
2450
+ }
2451
+ }
2452
+ function normalizePath(pathname) {
2453
+ if (pathname === "/" || pathname === "") {
2454
+ return "";
2455
+ }
2456
+ if (pathname.endsWith("/")) {
2457
+ return pathname.slice(0, -1);
2458
+ }
2459
+ return pathname;
2460
+ }
2461
+ function buildApiBaseUrl(origin, pathname) {
2462
+ if (pathname === "" || pathname === "/") {
2463
+ return `${origin}/v1`;
2464
+ }
2465
+ if (pathname.endsWith("/v1")) {
2466
+ return `${origin}${pathname}`;
2467
+ }
2468
+ return `${origin}${pathname}/v1`;
2469
+ }
2470
+ function buildPoeBaseUrl(origin, pathname) {
2471
+ if (pathname.endsWith("/v1")) {
2472
+ const trimmed = pathname.slice(0, -3);
2473
+ return trimmed.length > 0 ? `${origin}${trimmed}` : origin;
2474
+ }
2475
+ return pathname.length > 0 ? `${origin}${pathname}` : origin;
2476
+ }
2477
+ function trimTrailingSlash(value) {
2478
+ if (value.length > 1 && value.endsWith("/")) {
2479
+ return value.slice(0, -1);
2480
+ }
2481
+ if (value === "/") {
2482
+ return "";
2483
+ }
2484
+ return value;
2485
+ }
2486
+ function ensureV1Suffix(value) {
2487
+ if (value.endsWith("/v1")) {
2488
+ return value;
2489
+ }
2490
+ if (value === "") {
2491
+ return "/v1";
2492
+ }
2493
+ return `${value}/v1`;
2494
+ }
2495
+ function stripV1Suffix(value) {
2496
+ if (value.endsWith("/v1")) {
2497
+ return value.slice(0, -3);
2498
+ }
2499
+ return value;
2500
+ }
2501
+
2502
+ // src/sdk/credentials.ts
2503
+ async function getPoeApiKey() {
2504
+ const envKey = Object.hasOwn(process.env, "POE_API_KEY") ? process.env.POE_API_KEY : void 0;
2505
+ if (typeof envKey === "string" && envKey.trim().length > 0) {
2506
+ return envKey.trim();
2507
+ }
2508
+ const { store } = createSecretStore({
2509
+ backendEnvVar: "POE_AUTH_BACKEND",
2510
+ fileStore: {
2511
+ salt: "poe-code:encrypted-file-auth-store:v1",
2512
+ defaultDirectory: ".poe-code",
2513
+ defaultFileName: "credentials.enc"
2514
+ }
2515
+ });
2516
+ const storedKey = await store.get();
2517
+ if (typeof storedKey === "string" && storedKey.trim().length > 0) {
2518
+ return storedKey.trim();
2519
+ }
2520
+ throw new AuthenticationError("No API key found. Set POE_API_KEY or run 'poe-code login'.");
2521
+ }
2522
+ async function ensurePoeApiKeyEnv() {
2523
+ const envKey = Object.hasOwn(process.env, "POE_API_KEY") ? process.env.POE_API_KEY : void 0;
2524
+ if (typeof envKey === "string" && envKey.trim().length > 0) {
2525
+ return;
2526
+ }
2527
+ process.env.POE_API_KEY = await getPoeApiKey();
2528
+ }
2529
+ async function getPoeAuthIdentity(options = {}) {
2530
+ const apiKey = options.apiKey ?? await getPoeApiKey();
2531
+ return fetchPoeAuthIdentity({
2532
+ apiKey,
2533
+ baseUrl: options.baseUrl ?? resolvePoeApiBaseUrl(options.variables),
2534
+ httpClient: options.httpClient
2535
+ });
2536
+ }
2537
+ async function fetchPoeAuthIdentity(options) {
2538
+ const httpClient = options.httpClient ?? createDefaultHttpClient();
2539
+ const response = await httpClient(`${trimTrailingSlashes(options.baseUrl ?? resolvePoeApiBaseUrl())}/whoami`, {
2540
+ method: "POST",
2541
+ headers: {
2542
+ Authorization: `Bearer ${options.apiKey}`
2543
+ }
2544
+ });
2545
+ if (!response.ok) {
2546
+ throw new ApiError(`Failed to fetch identity (HTTP ${response.status})`, {
2547
+ httpStatus: response.status,
2548
+ endpoint: "/v1/whoami"
2549
+ });
2550
+ }
2551
+ return parsePoeAuthIdentity(await response.json());
2552
+ }
2553
+ function parsePoeAuthIdentity(value) {
2554
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2555
+ throw new ApiError("Malformed identity response from Poe API.", {
2556
+ endpoint: "/v1/whoami"
2557
+ });
2558
+ }
2559
+ const identity = value;
2560
+ if (typeof identity.user_id !== "number" || !Number.isFinite(identity.user_id) || typeof identity.handle !== "string" || identity.handle.trim().length === 0 || typeof identity.name !== "string" || identity.name.trim().length === 0 || typeof identity.profile_picture !== "string") {
2561
+ throw new ApiError("Malformed identity response from Poe API.", {
2562
+ endpoint: "/v1/whoami"
2563
+ });
2564
+ }
2565
+ return value;
2566
+ }
2567
+ function createDefaultHttpClient() {
2568
+ return async (url, init) => {
2569
+ const response = await globalThis.fetch(url, init);
2570
+ return {
2571
+ ok: response.ok,
2572
+ status: response.status,
2573
+ json: () => response.json()
2574
+ };
2575
+ };
2576
+ }
2577
+ function trimTrailingSlashes(value) {
2578
+ return value.replace(/\/+$/, "");
2579
+ }
2580
+ export {
2581
+ ensurePoeApiKeyEnv,
2582
+ fetchPoeAuthIdentity,
2583
+ getPoeApiKey,
2584
+ getPoeAuthIdentity
2585
+ };
2586
+ //# sourceMappingURL=credentials.js.map