poe-code 3.0.99 → 3.0.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  mod
32
32
  ));
33
33
 
34
- // packages/poe-auth/src/encrypted-file-auth-store.ts
34
+ // packages/auth-store/src/encrypted-file-store.ts
35
35
  import { createCipheriv, createDecipheriv, randomBytes, scrypt } from "node:crypto";
36
36
  import { promises as fs } from "node:fs";
37
37
  import { homedir, hostname, userInfo } from "node:os";
@@ -42,11 +42,11 @@ function defaultMachineIdentity() {
42
42
  username: userInfo().username
43
43
  };
44
44
  }
45
- async function deriveEncryptionKey(getMachineIdentity) {
45
+ async function deriveEncryptionKey(getMachineIdentity, salt) {
46
46
  const machineIdentity = await getMachineIdentity();
47
47
  const secret = `${machineIdentity.hostname}:${machineIdentity.username}`;
48
48
  return await new Promise((resolve, reject) => {
49
- scrypt(secret, ENCRYPTION_SALT, ENCRYPTION_KEY_BYTES, (error2, derivedKey) => {
49
+ scrypt(secret, salt, ENCRYPTION_KEY_BYTES, (error2, derivedKey) => {
50
50
  if (error2) {
51
51
  reject(error2);
52
52
  return;
@@ -85,34 +85,35 @@ function isNotFoundError(error2) {
85
85
  error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT"
86
86
  );
87
87
  }
88
- var ENCRYPTION_ALGORITHM, ENCRYPTION_VERSION, ENCRYPTION_KEY_BYTES, ENCRYPTION_IV_BYTES, ENCRYPTION_AUTH_TAG_BYTES, ENCRYPTION_SALT, ENCRYPTION_FILE_MODE, EncryptedFileAuthStore;
89
- var init_encrypted_file_auth_store = __esm({
90
- "packages/poe-auth/src/encrypted-file-auth-store.ts"() {
88
+ var ENCRYPTION_ALGORITHM, ENCRYPTION_VERSION, ENCRYPTION_KEY_BYTES, ENCRYPTION_IV_BYTES, ENCRYPTION_AUTH_TAG_BYTES, ENCRYPTION_FILE_MODE, EncryptedFileStore;
89
+ var init_encrypted_file_store = __esm({
90
+ "packages/auth-store/src/encrypted-file-store.ts"() {
91
91
  "use strict";
92
92
  ENCRYPTION_ALGORITHM = "aes-256-gcm";
93
93
  ENCRYPTION_VERSION = 1;
94
94
  ENCRYPTION_KEY_BYTES = 32;
95
95
  ENCRYPTION_IV_BYTES = 12;
96
96
  ENCRYPTION_AUTH_TAG_BYTES = 16;
97
- ENCRYPTION_SALT = "poe-code:encrypted-file-auth-store:v1";
98
97
  ENCRYPTION_FILE_MODE = 384;
99
- EncryptedFileAuthStore = class {
98
+ EncryptedFileStore = class {
100
99
  fs;
101
100
  filePath;
101
+ salt;
102
102
  getMachineIdentity;
103
103
  getRandomBytes;
104
104
  keyPromise = null;
105
- constructor(input = {}) {
105
+ constructor(input) {
106
106
  this.fs = input.fs ?? fs;
107
+ this.salt = input.salt;
107
108
  this.filePath = input.filePath ?? path.join(
108
109
  (input.getHomeDirectory ?? homedir)(),
109
- ".poe-code",
110
- "credentials.enc"
110
+ input.defaultDirectory ?? ".auth-store",
111
+ input.defaultFileName ?? "credentials.enc"
111
112
  );
112
113
  this.getMachineIdentity = input.getMachineIdentity ?? defaultMachineIdentity;
113
114
  this.getRandomBytes = input.getRandomBytes ?? randomBytes;
114
115
  }
115
- async getApiKey() {
116
+ async get() {
116
117
  let rawDocument;
117
118
  try {
118
119
  rawDocument = await this.fs.readFile(this.filePath, "utf8");
@@ -142,12 +143,12 @@ var init_encrypted_file_auth_store = __esm({
142
143
  return null;
143
144
  }
144
145
  }
145
- async setApiKey(apiKey) {
146
+ async set(value) {
146
147
  const key = await this.getEncryptionKey();
147
148
  const iv = this.getRandomBytes(ENCRYPTION_IV_BYTES);
148
149
  const cipher = createCipheriv(ENCRYPTION_ALGORITHM, key, iv);
149
150
  const ciphertext = Buffer.concat([
150
- cipher.update(apiKey, "utf8"),
151
+ cipher.update(value, "utf8"),
151
152
  cipher.final()
152
153
  ]);
153
154
  const authTag = cipher.getAuthTag();
@@ -163,7 +164,7 @@ var init_encrypted_file_auth_store = __esm({
163
164
  });
164
165
  await this.fs.chmod(this.filePath, ENCRYPTION_FILE_MODE);
165
166
  }
166
- async deleteApiKey() {
167
+ async delete() {
167
168
  try {
168
169
  await this.fs.unlink(this.filePath);
169
170
  } catch (error2) {
@@ -174,7 +175,7 @@ var init_encrypted_file_auth_store = __esm({
174
175
  }
175
176
  getEncryptionKey() {
176
177
  if (!this.keyPromise) {
177
- this.keyPromise = deriveEncryptionKey(this.getMachineIdentity);
178
+ this.keyPromise = deriveEncryptionKey(this.getMachineIdentity, this.salt);
178
179
  }
179
180
  return this.keyPromise;
180
181
  }
@@ -182,7 +183,7 @@ var init_encrypted_file_auth_store = __esm({
182
183
  }
183
184
  });
184
185
 
185
- // packages/poe-auth/src/keychain-auth-store.ts
186
+ // packages/auth-store/src/keychain-store.ts
186
187
  import { spawn } from "node:child_process";
187
188
  function runSecurityCommand(command, args) {
188
189
  return new Promise((resolve) => {
@@ -242,27 +243,25 @@ function createSecurityCliFailure(operation, result) {
242
243
  }
243
244
  return new Error(`Failed to ${operation}: security exited with code ${result.exitCode}`);
244
245
  }
245
- var SECURITY_CLI, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE, KeychainAuthStore;
246
- var init_keychain_auth_store = __esm({
247
- "packages/poe-auth/src/keychain-auth-store.ts"() {
246
+ var SECURITY_CLI, KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE, KeychainStore;
247
+ var init_keychain_store = __esm({
248
+ "packages/auth-store/src/keychain-store.ts"() {
248
249
  "use strict";
249
250
  SECURITY_CLI = "security";
250
- KEYCHAIN_SERVICE = "poe-code";
251
- KEYCHAIN_ACCOUNT = "api-key";
252
251
  KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE = 44;
253
- KeychainAuthStore = class {
252
+ KeychainStore = class {
254
253
  runCommand;
255
254
  service;
256
255
  account;
257
- constructor(input = {}) {
256
+ constructor(input) {
258
257
  this.runCommand = input.runCommand ?? runSecurityCommand;
259
- this.service = input.service ?? KEYCHAIN_SERVICE;
260
- this.account = input.account ?? KEYCHAIN_ACCOUNT;
258
+ this.service = input.service;
259
+ this.account = input.account;
261
260
  }
262
- async getApiKey() {
261
+ async get() {
263
262
  const result = await this.executeSecurityCommand(
264
263
  ["find-generic-password", "-s", this.service, "-a", this.account, "-w"],
265
- "read API key from macOS Keychain"
264
+ "read secret from macOS Keychain"
266
265
  );
267
266
  if (result.exitCode === 0) {
268
267
  return stripTrailingLineBreak(result.stdout);
@@ -270,9 +269,9 @@ var init_keychain_auth_store = __esm({
270
269
  if (isKeychainEntryNotFound(result)) {
271
270
  return null;
272
271
  }
273
- throw createSecurityCliFailure("read API key from macOS Keychain", result);
272
+ throw createSecurityCliFailure("read secret from macOS Keychain", result);
274
273
  }
275
- async setApiKey(apiKey) {
274
+ async set(value) {
276
275
  const result = await this.executeSecurityCommand(
277
276
  [
278
277
  "add-generic-password",
@@ -281,24 +280,24 @@ var init_keychain_auth_store = __esm({
281
280
  "-a",
282
281
  this.account,
283
282
  "-w",
284
- apiKey,
283
+ value,
285
284
  "-U"
286
285
  ],
287
- "store API key in macOS Keychain"
286
+ "store secret in macOS Keychain"
288
287
  );
289
288
  if (result.exitCode !== 0) {
290
- throw createSecurityCliFailure("store API key in macOS Keychain", result);
289
+ throw createSecurityCliFailure("store secret in macOS Keychain", result);
291
290
  }
292
291
  }
293
- async deleteApiKey() {
292
+ async delete() {
294
293
  const result = await this.executeSecurityCommand(
295
294
  ["delete-generic-password", "-s", this.service, "-a", this.account],
296
- "delete API key from macOS Keychain"
295
+ "delete secret from macOS Keychain"
297
296
  );
298
297
  if (result.exitCode === 0 || isKeychainEntryNotFound(result)) {
299
298
  return;
300
299
  }
301
- throw createSecurityCliFailure("delete API key from macOS Keychain", result);
300
+ throw createSecurityCliFailure("delete secret from macOS Keychain", result);
302
301
  }
303
302
  async executeSecurityCommand(args, operation) {
304
303
  try {
@@ -312,382 +311,58 @@ var init_keychain_auth_store = __esm({
312
311
  }
313
312
  });
314
313
 
315
- // packages/poe-auth/src/create-auth-store.ts
316
- import { promises as nodeFs } from "node:fs";
317
- import { homedir as homedir2 } from "node:os";
318
- import path2 from "node:path";
319
- function createAuthStore(input = {}) {
314
+ // packages/auth-store/src/create-secret-store.ts
315
+ function createSecretStore(input) {
320
316
  const backend = resolveBackend(input);
321
317
  const platform = input.platform ?? process.platform;
322
318
  if (backend === "keychain" && platform !== MACOS_PLATFORM) {
323
319
  throw new Error(
324
- `POE_AUTH_BACKEND=keychain is only supported on macOS. Current platform: ${platform}`
320
+ `Keychain backend is only supported on macOS. Current platform: ${platform}`
325
321
  );
326
322
  }
327
- const store = authStoreFactories[backend](input);
328
- return {
329
- backend,
330
- store: enableLegacyCredentialsMigration(store, input)
331
- };
323
+ const store = storeFactories[backend](input);
324
+ return { backend, store };
332
325
  }
333
326
  function resolveBackend(input) {
334
- const configuredBackend = input.backend ?? input.env?.[AUTH_BACKEND_ENV_VAR] ?? process.env[AUTH_BACKEND_ENV_VAR];
327
+ const envVar = input.backendEnvVar ?? DEFAULT_BACKEND_ENV_VAR;
328
+ const configuredBackend = input.backend ?? input.env?.[envVar] ?? process.env[envVar];
335
329
  if (configuredBackend === "keychain") {
336
330
  return "keychain";
337
331
  }
338
332
  return "file";
339
333
  }
340
- function enableLegacyCredentialsMigration(store, input) {
341
- const migrationContext = createLegacyMigrationContext(input);
342
- const readApiKeyFromStore = store.getApiKey.bind(store);
343
- let hasCheckedLegacyCredentials = false;
344
- let legacyMigrationPromise = null;
345
- store.getApiKey = async () => {
346
- const storedApiKey = await readApiKeyFromStore();
347
- if (isNonEmptyString(storedApiKey)) {
348
- return storedApiKey;
349
- }
350
- if (hasCheckedLegacyCredentials) {
351
- return null;
352
- }
353
- if (!legacyMigrationPromise) {
354
- legacyMigrationPromise = migrateLegacyApiKey(store, migrationContext).finally(() => {
355
- hasCheckedLegacyCredentials = true;
356
- legacyMigrationPromise = null;
357
- });
358
- }
359
- return legacyMigrationPromise;
360
- };
361
- return store;
362
- }
363
- async function migrateLegacyApiKey(store, migrationContext) {
364
- const legacyCredentials = await loadLegacyCredentials(
365
- migrationContext.fs,
366
- migrationContext.filePath
367
- );
368
- if (!legacyCredentials || !isNonEmptyString(legacyCredentials.apiKey)) {
369
- return null;
370
- }
371
- const plaintextApiKey = legacyCredentials.apiKey;
372
- try {
373
- await store.setApiKey(plaintextApiKey);
374
- delete legacyCredentials.apiKey;
375
- await saveLegacyCredentials(
376
- migrationContext.fs,
377
- migrationContext.filePath,
378
- legacyCredentials
379
- );
380
- } catch (error2) {
381
- migrationContext.logWarning(
382
- `Failed to migrate plaintext API key from ${migrationContext.filePath}.`,
383
- error2
384
- );
385
- }
386
- return plaintextApiKey;
387
- }
388
- function createLegacyMigrationContext(input) {
389
- const legacyCredentialsInput = input.legacyCredentials;
390
- const getHomeDirectory = legacyCredentialsInput?.getHomeDirectory ?? homedir2;
391
- return {
392
- fs: legacyCredentialsInput?.fs ?? input.fileStore?.fs ?? nodeFs,
393
- filePath: legacyCredentialsInput?.filePath ?? path2.join(
394
- getHomeDirectory(),
395
- LEGACY_CREDENTIALS_RELATIVE_PATH
396
- ),
397
- logWarning: legacyCredentialsInput?.logWarning ?? defaultMigrationWarning
398
- };
399
- }
400
- async function loadLegacyCredentials(fs3, filePath) {
401
- let raw;
402
- try {
403
- raw = await fs3.readFile(filePath, "utf8");
404
- } catch (error2) {
405
- if (isNotFoundError2(error2)) {
406
- return null;
407
- }
408
- return null;
409
- }
410
- try {
411
- const parsed = JSON.parse(raw);
412
- if (!isRecord2(parsed)) {
413
- return null;
414
- }
415
- return parsed;
416
- } catch {
417
- return null;
418
- }
419
- }
420
- async function saveLegacyCredentials(fs3, filePath, document) {
421
- await fs3.mkdir(path2.dirname(filePath), { recursive: true });
422
- await fs3.writeFile(filePath, `${JSON.stringify(document, null, 2)}
423
- `, {
424
- encoding: "utf8"
425
- });
426
- }
427
- function defaultMigrationWarning(message, error2) {
428
- const details = toErrorDetails(error2);
429
- if (details.length > 0) {
430
- console.warn(`${message} ${details}`);
431
- return;
432
- }
433
- console.warn(message);
434
- }
435
- function toErrorDetails(error2) {
436
- if (error2 instanceof Error) {
437
- return error2.message;
438
- }
439
- return typeof error2 === "string" ? error2 : "";
440
- }
441
- function isNonEmptyString(value) {
442
- return typeof value === "string" && value.length > 0;
443
- }
444
- function isRecord2(value) {
445
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
446
- }
447
- function isNotFoundError2(error2) {
448
- return Boolean(
449
- error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT"
450
- );
451
- }
452
- var AUTH_BACKEND_ENV_VAR, MACOS_PLATFORM, LEGACY_CREDENTIALS_RELATIVE_PATH, authStoreFactories;
453
- var init_create_auth_store = __esm({
454
- "packages/poe-auth/src/create-auth-store.ts"() {
334
+ var DEFAULT_BACKEND_ENV_VAR, MACOS_PLATFORM, storeFactories;
335
+ var init_create_secret_store = __esm({
336
+ "packages/auth-store/src/create-secret-store.ts"() {
455
337
  "use strict";
456
- init_encrypted_file_auth_store();
457
- init_keychain_auth_store();
458
- AUTH_BACKEND_ENV_VAR = "POE_AUTH_BACKEND";
338
+ init_encrypted_file_store();
339
+ init_keychain_store();
340
+ DEFAULT_BACKEND_ENV_VAR = "AUTH_BACKEND";
459
341
  MACOS_PLATFORM = "darwin";
460
- LEGACY_CREDENTIALS_RELATIVE_PATH = ".poe-code/credentials.json";
461
- authStoreFactories = {
462
- file: (input) => new EncryptedFileAuthStore(input.fileStore),
463
- keychain: (input) => new KeychainAuthStore(input.keychainStore)
464
- };
465
- }
466
- });
467
-
468
- // packages/poe-auth/src/check-auth.ts
469
- var init_check_auth = __esm({
470
- "packages/poe-auth/src/check-auth.ts"() {
471
- "use strict";
472
- init_create_auth_store();
473
- }
474
- });
475
-
476
- // packages/poe-auth/src/get-token.ts
477
- var init_get_token = __esm({
478
- "packages/poe-auth/src/get-token.ts"() {
479
- "use strict";
480
- init_create_auth_store();
481
- }
482
- });
483
-
484
- // packages/poe-auth/src/api-key-validation.ts
485
- var init_api_key_validation = __esm({
486
- "packages/poe-auth/src/api-key-validation.ts"() {
487
- "use strict";
488
- }
489
- });
490
-
491
- // packages/poe-auth/src/oauth-client.ts
492
- import http from "node:http";
493
- import crypto from "node:crypto";
494
- function createOAuthClient(config2) {
495
- const fetchFn = config2.fetch ?? globalThis.fetch;
496
- return {
497
- authorize: () => startAuthorization(config2, fetchFn)
498
- };
499
- }
500
- function generateCodeVerifier() {
501
- return crypto.randomBytes(32).toString("base64url");
502
- }
503
- function generateCodeChallenge(verifier) {
504
- return crypto.createHash("sha256").update(verifier).digest("base64url");
505
- }
506
- async function startAuthorization(config2, fetchFn) {
507
- const codeVerifier = generateCodeVerifier();
508
- const codeChallenge = generateCodeChallenge(codeVerifier);
509
- const server = config2.createServer ? config2.createServer() : http.createServer();
510
- const port = await startServer(server);
511
- const redirectUri = `http://127.0.0.1:${port}/callback`;
512
- const authorizationUrl = buildAuthorizationUrl({
513
- endpoint: config2.authorizationEndpoint,
514
- clientId: config2.clientId,
515
- redirectUri,
516
- codeChallenge
517
- });
518
- const waitForResult = async () => {
519
- try {
520
- const code = await waitForAuthorizationCode(server, config2, authorizationUrl);
521
- return await exchangeCodeForApiKey({
522
- tokenEndpoint: config2.tokenEndpoint,
523
- code,
524
- codeVerifier,
525
- clientId: config2.clientId,
526
- redirectUri,
527
- fetchFn
528
- });
529
- } finally {
530
- server.closeAllConnections?.();
531
- server.close();
532
- }
533
- };
534
- return { authorizationUrl, waitForResult };
535
- }
536
- function startServer(server) {
537
- return new Promise((resolve) => {
538
- server.listen(0, "127.0.0.1", () => {
539
- const address = server.address();
540
- resolve(address.port);
541
- });
542
- });
543
- }
544
- function buildAuthorizationUrl(params) {
545
- const url2 = new URL(params.endpoint);
546
- url2.searchParams.set("response_type", "code");
547
- url2.searchParams.set("client_id", params.clientId);
548
- url2.searchParams.set("scope", "apikey:create");
549
- url2.searchParams.set("code_challenge", params.codeChallenge);
550
- url2.searchParams.set("code_challenge_method", "S256");
551
- url2.searchParams.set("redirect_uri", params.redirectUri);
552
- return url2.toString();
553
- }
554
- function waitForAuthorizationCode(server, config2, authorizationUrl) {
555
- return new Promise((resolve, reject) => {
556
- let settled = false;
557
- const settle = (fn) => {
558
- if (!settled) {
559
- settled = true;
560
- fn();
342
+ storeFactories = {
343
+ file: (input) => {
344
+ if (!input.fileStore) {
345
+ throw new Error("fileStore configuration is required for file backend");
346
+ }
347
+ return new EncryptedFileStore(input.fileStore);
348
+ },
349
+ keychain: (input) => {
350
+ if (!input.keychainStore) {
351
+ throw new Error("keychainStore configuration is required for keychain backend");
352
+ }
353
+ return new KeychainStore(input.keychainStore);
561
354
  }
562
355
  };
563
- server.on("request", (req, res) => {
564
- const url2 = new URL(req.url, `http://127.0.0.1`);
565
- if (url2.pathname !== "/callback") {
566
- res.writeHead(404);
567
- res.end("Not found");
568
- return;
569
- }
570
- const error2 = url2.searchParams.get("error");
571
- if (error2) {
572
- const description = url2.searchParams.get("error_description") ?? error2;
573
- res.writeHead(400);
574
- res.end(`Authorization failed: ${description}`);
575
- settle(() => reject(new Error(`OAuth authorization failed: ${error2} \u2014 ${description}`)));
576
- return;
577
- }
578
- const code = url2.searchParams.get("code");
579
- if (!code) {
580
- res.writeHead(400);
581
- res.end("Missing authorization code");
582
- settle(() => reject(new Error("OAuth callback missing authorization code")));
583
- return;
584
- }
585
- res.writeHead(200, { "Content-Type": "text/html" });
586
- res.end(buildSuccessPage());
587
- settle(() => resolve(code));
588
- });
589
- if (config2.readLine) {
590
- config2.readLine().then((input) => {
591
- const code = extractCodeFromInput(input);
592
- if (code) {
593
- settle(() => resolve(code));
594
- }
595
- }).catch(() => {
596
- });
597
- }
598
- if (config2.openBrowser) {
599
- config2.openBrowser(authorizationUrl).catch(
600
- (err) => settle(() => reject(err))
601
- );
602
- }
603
- });
604
- }
605
- function extractCodeFromInput(input) {
606
- const trimmed = input.replace(/[\r\n]/g, "").trim();
607
- if (trimmed.length === 0) {
608
- return null;
609
- }
610
- try {
611
- const url2 = new URL(trimmed);
612
- return url2.searchParams.get("code");
613
- } catch {
614
- return trimmed;
615
- }
616
- }
617
- async function exchangeCodeForApiKey(params) {
618
- const body = new URLSearchParams({
619
- grant_type: "authorization_code",
620
- code: params.code,
621
- code_verifier: params.codeVerifier,
622
- client_id: params.clientId,
623
- redirect_uri: params.redirectUri
624
- });
625
- const response = await params.fetchFn(params.tokenEndpoint, {
626
- method: "POST",
627
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
628
- body: body.toString()
629
- });
630
- if (!response.ok) {
631
- const text4 = await response.text();
632
- throw new Error(`Token exchange failed (${response.status}): ${text4}`);
633
- }
634
- const data = await response.json();
635
- if (typeof data.api_key !== "string" || data.api_key.length === 0) {
636
- throw new Error("Token response missing api_key field");
637
- }
638
- return {
639
- apiKey: data.api_key,
640
- expiresIn: typeof data.api_key_expires_in === "number" ? data.api_key_expires_in : null
641
- };
642
- }
643
- function buildSuccessPage() {
644
- return [
645
- "<!DOCTYPE html>",
646
- "<html><head><meta charset=utf-8><title>Connected to Poe</title></head>",
647
- '<body style="font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0">',
648
- '<div style="text-align:center">',
649
- "<h1>Connected to Poe</h1>",
650
- '<p style="color:#666">You can close this tab and return to your terminal.</p>',
651
- "</div></body></html>"
652
- ].join("");
653
- }
654
- var init_oauth_client = __esm({
655
- "packages/poe-auth/src/oauth-client.ts"() {
656
- "use strict";
657
- }
658
- });
659
-
660
- // packages/poe-auth/src/login.ts
661
- var init_login = __esm({
662
- "packages/poe-auth/src/login.ts"() {
663
- "use strict";
664
- init_api_key_validation();
665
- init_create_auth_store();
666
- init_oauth_client();
667
- }
668
- });
669
-
670
- // packages/poe-auth/src/logout.ts
671
- var init_logout = __esm({
672
- "packages/poe-auth/src/logout.ts"() {
673
- "use strict";
674
- init_create_auth_store();
675
356
  }
676
357
  });
677
358
 
678
- // packages/poe-auth/src/index.ts
359
+ // packages/auth-store/src/index.ts
679
360
  var init_src = __esm({
680
- "packages/poe-auth/src/index.ts"() {
361
+ "packages/auth-store/src/index.ts"() {
681
362
  "use strict";
682
- init_create_auth_store();
683
- init_check_auth();
684
- init_get_token();
685
- init_api_key_validation();
686
- init_login();
687
- init_logout();
688
- init_oauth_client();
689
- init_encrypted_file_auth_store();
690
- init_keychain_auth_store();
363
+ init_create_secret_store();
364
+ init_encrypted_file_store();
365
+ init_keychain_store();
691
366
  }
692
367
  });
693
368
 
@@ -697,8 +372,15 @@ async function getPoeApiKey() {
697
372
  if (typeof envKey === "string" && envKey.trim().length > 0) {
698
373
  return envKey.trim();
699
374
  }
700
- const { store } = createAuthStore();
701
- const storedKey = await store.getApiKey();
375
+ const { store } = createSecretStore({
376
+ backendEnvVar: "POE_AUTH_BACKEND",
377
+ fileStore: {
378
+ salt: "poe-code:encrypted-file-auth-store:v1",
379
+ defaultDirectory: ".poe-code",
380
+ defaultFileName: "credentials.enc"
381
+ }
382
+ });
383
+ const storedKey = await store.get();
702
384
  if (typeof storedKey === "string" && storedKey.trim().length > 0) {
703
385
  return storedKey.trim();
704
386
  }
@@ -1032,16 +714,16 @@ function getConfigFormat(pathOrFormat) {
1032
714
  }
1033
715
  return formatRegistry[formatName];
1034
716
  }
1035
- function detectFormat(path25) {
1036
- const ext = getExtension(path25);
717
+ function detectFormat(path24) {
718
+ const ext = getExtension(path24);
1037
719
  return extensionMap[ext];
1038
720
  }
1039
- function getExtension(path25) {
1040
- const lastDot = path25.lastIndexOf(".");
721
+ function getExtension(path24) {
722
+ const lastDot = path24.lastIndexOf(".");
1041
723
  if (lastDot === -1) {
1042
724
  return "";
1043
725
  }
1044
- return path25.slice(lastDot).toLowerCase();
726
+ return path24.slice(lastDot).toLowerCase();
1045
727
  }
1046
728
  var formatRegistry, extensionMap;
1047
729
  var init_formats = __esm({
@@ -1063,7 +745,7 @@ var init_formats = __esm({
1063
745
  });
1064
746
 
1065
747
  // packages/config-mutations/src/execution/path-utils.ts
1066
- import path3 from "node:path";
748
+ import path2 from "node:path";
1067
749
  function expandHome(targetPath, homeDir) {
1068
750
  if (!targetPath?.startsWith("~")) {
1069
751
  return targetPath;
@@ -1080,7 +762,7 @@ function expandHome(targetPath, homeDir) {
1080
762
  remainder = remainder.slice(1);
1081
763
  }
1082
764
  }
1083
- return remainder.length === 0 ? homeDir : path3.join(homeDir, remainder);
765
+ return remainder.length === 0 ? homeDir : path2.join(homeDir, remainder);
1084
766
  }
1085
767
  function validateHomePath(targetPath) {
1086
768
  if (typeof targetPath !== "string" || targetPath.length === 0) {
@@ -1098,12 +780,12 @@ function resolvePath(rawPath, homeDir, pathMapper) {
1098
780
  if (!pathMapper) {
1099
781
  return expanded;
1100
782
  }
1101
- const rawDirectory = path3.dirname(expanded);
783
+ const rawDirectory = path2.dirname(expanded);
1102
784
  const mappedDirectory = pathMapper.mapTargetDirectory({
1103
785
  targetDirectory: rawDirectory
1104
786
  });
1105
- const filename = path3.basename(expanded);
1106
- return filename.length === 0 ? mappedDirectory : path3.join(mappedDirectory, filename);
787
+ const filename = path2.basename(expanded);
788
+ return filename.length === 0 ? mappedDirectory : path2.join(mappedDirectory, filename);
1107
789
  }
1108
790
  var init_path_utils = __esm({
1109
791
  "packages/config-mutations/src/execution/path-utils.ts"() {
@@ -1768,38 +1450,38 @@ import { createTwoFilesPatch } from "diff";
1768
1450
  import chalk from "chalk";
1769
1451
  function createDryRunFileSystem(base, recorder) {
1770
1452
  const proxy = {
1771
- async readFile(path25, encoding) {
1453
+ async readFile(path24, encoding) {
1772
1454
  if (encoding) {
1773
- return base.readFile(path25, encoding);
1455
+ return base.readFile(path24, encoding);
1774
1456
  }
1775
- return base.readFile(path25);
1457
+ return base.readFile(path24);
1776
1458
  },
1777
- async writeFile(path25, data, options) {
1778
- const previousContent = await tryReadText(base, path25);
1459
+ async writeFile(path24, data, options) {
1460
+ const previousContent = await tryReadText(base, path24);
1779
1461
  const nextContent = formatData(data, options?.encoding);
1780
1462
  recorder.record({
1781
1463
  type: "writeFile",
1782
- path: path25,
1464
+ path: path24,
1783
1465
  nextContent,
1784
1466
  previousContent
1785
1467
  });
1786
1468
  },
1787
- async mkdir(path25, options) {
1788
- recorder.record({ type: "mkdir", path: path25, options });
1469
+ async mkdir(path24, options) {
1470
+ recorder.record({ type: "mkdir", path: path24, options });
1789
1471
  },
1790
- async stat(path25) {
1791
- return base.stat(path25);
1472
+ async stat(path24) {
1473
+ return base.stat(path24);
1792
1474
  },
1793
- async unlink(path25) {
1794
- recorder.record({ type: "unlink", path: path25 });
1475
+ async unlink(path24) {
1476
+ recorder.record({ type: "unlink", path: path24 });
1795
1477
  },
1796
- async readdir(path25) {
1797
- return base.readdir(path25);
1478
+ async readdir(path24) {
1479
+ return base.readdir(path24);
1798
1480
  }
1799
1481
  };
1800
1482
  if (typeof base.rm === "function") {
1801
- proxy.rm = async (path25, options) => {
1802
- recorder.record({ type: "rm", path: path25, options });
1483
+ proxy.rm = async (path24, options) => {
1484
+ recorder.record({ type: "rm", path: path24, options });
1803
1485
  };
1804
1486
  }
1805
1487
  if (typeof base.copyFile === "function") {
@@ -1889,8 +1571,8 @@ function describeWriteChange(previous, next) {
1889
1571
  }
1890
1572
  return "update";
1891
1573
  }
1892
- function renderWriteCommand(path25, change) {
1893
- const command = `cat > ${path25}`;
1574
+ function renderWriteCommand(path24, change) {
1575
+ const command = `cat > ${path24}`;
1894
1576
  if (change === "create") {
1895
1577
  return renderOperationCommand(command, chalk.green, "# create");
1896
1578
  }
@@ -2052,9 +1734,9 @@ function redactTomlLine(line) {
2052
1734
  }
2053
1735
  return line;
2054
1736
  }
2055
- async function tryReadText(base, path25) {
1737
+ async function tryReadText(base, path24) {
2056
1738
  try {
2057
- return await base.readFile(path25, "utf8");
1739
+ return await base.readFile(path24, "utf8");
2058
1740
  } catch (error2) {
2059
1741
  if (isNotFound(error2)) {
2060
1742
  return null;
@@ -2236,7 +1918,7 @@ var init_context = __esm({
2236
1918
  });
2237
1919
 
2238
1920
  // src/cli/isolated-env.ts
2239
- import path4 from "node:path";
1921
+ import path3 from "node:path";
2240
1922
  async function resolveIsolatedEnvDetails(env, isolated, providerName, readApiKey) {
2241
1923
  if (!providerName) {
2242
1924
  throw new Error("resolveIsolatedEnvDetails requires providerName.");
@@ -2258,7 +1940,7 @@ function resolveIsolatedTargetDirectory(input) {
2258
1940
  const expanded = expandHomeShortcut(input.env, input.targetDirectory);
2259
1941
  const baseDir = resolveIsolatedBaseDir(input.env, input.providerName);
2260
1942
  const homeDir = input.env.homeDir;
2261
- const homeDirWithSep = `${homeDir}${path4.sep}`;
1943
+ const homeDirWithSep = `${homeDir}${path3.sep}`;
2262
1944
  if (expanded !== homeDir && !expanded.startsWith(homeDirWithSep)) {
2263
1945
  throw new Error(
2264
1946
  `Isolated config targets must live under the user's home directory (received "${input.targetDirectory}").`
@@ -2273,7 +1955,7 @@ function resolveIsolatedTargetDirectory(input) {
2273
1955
  if (!expanded.startsWith(homeDirWithSep)) {
2274
1956
  return expanded;
2275
1957
  }
2276
- const mapped = path4.join(baseDir, expanded.slice(homeDirWithSep.length));
1958
+ const mapped = path3.join(baseDir, expanded.slice(homeDirWithSep.length));
2277
1959
  return stripAgentHome(mapped, baseDir, input.isolated.agentBinary);
2278
1960
  }
2279
1961
  function resolveIsolatedBaseDir(env, providerName) {
@@ -2322,9 +2004,9 @@ async function resolveIsolatedEnvValue(env, baseDir, value, readApiKey) {
2322
2004
  function resolveIsolatedEnvPath(env, baseDir, value) {
2323
2005
  switch (value.kind) {
2324
2006
  case "isolatedDir":
2325
- return value.relativePath ? path4.join(baseDir, value.relativePath) : baseDir;
2007
+ return value.relativePath ? path3.join(baseDir, value.relativePath) : baseDir;
2326
2008
  case "isolatedFile":
2327
- return path4.join(baseDir, value.relativePath);
2009
+ return path3.join(baseDir, value.relativePath);
2328
2010
  }
2329
2011
  }
2330
2012
  function isEnvVarReference(value) {
@@ -2366,10 +2048,10 @@ async function applyIsolatedEnvRepairs(input) {
2366
2048
  if (repair.kind !== "chmod") {
2367
2049
  continue;
2368
2050
  }
2369
- if (path4.isAbsolute(repair.relativePath)) {
2051
+ if (path3.isAbsolute(repair.relativePath)) {
2370
2052
  continue;
2371
2053
  }
2372
- const repairPath = path4.join(baseDir, repair.relativePath);
2054
+ const repairPath = path3.join(baseDir, repair.relativePath);
2373
2055
  try {
2374
2056
  await input.fs.chmod(repairPath, repair.mode);
2375
2057
  } catch (error2) {
@@ -2420,13 +2102,13 @@ async function resolveCliSettingValue(value, env, readApiKey) {
2420
2102
  }
2421
2103
  function stripAgentHome(mapped, baseDir, agentBinary) {
2422
2104
  const agentDir = `.${agentBinary}`;
2423
- const prefix = path4.join(baseDir, agentDir);
2105
+ const prefix = path3.join(baseDir, agentDir);
2424
2106
  if (mapped === prefix) {
2425
2107
  return baseDir;
2426
2108
  }
2427
- const withSep = `${prefix}${path4.sep}`;
2109
+ const withSep = `${prefix}${path3.sep}`;
2428
2110
  if (mapped.startsWith(withSep)) {
2429
- return path4.join(baseDir, mapped.slice(withSep.length));
2111
+ return path3.join(baseDir, mapped.slice(withSep.length));
2430
2112
  }
2431
2113
  return mapped;
2432
2114
  }
@@ -2437,11 +2119,11 @@ function expandHomeShortcut(env, input) {
2437
2119
  if (input === "~") {
2438
2120
  return env.homeDir;
2439
2121
  }
2440
- if (input.startsWith("~/") || input.startsWith(`~${path4.sep}`)) {
2441
- return path4.join(env.homeDir, input.slice(2));
2122
+ if (input.startsWith("~/") || input.startsWith(`~${path3.sep}`)) {
2123
+ return path3.join(env.homeDir, input.slice(2));
2442
2124
  }
2443
- if (input.startsWith("~./") || input.startsWith(`~.${path4.sep}`)) {
2444
- return path4.join(env.homeDir, `.${input.slice(3)}`);
2125
+ if (input.startsWith("~./") || input.startsWith(`~.${path3.sep}`)) {
2126
+ return path3.join(env.homeDir, `.${input.slice(3)}`);
2445
2127
  }
2446
2128
  return input;
2447
2129
  }
@@ -3946,13 +3628,13 @@ function truncate2(text4, maxLength) {
3946
3628
  if (maxLength <= 3) return text4.slice(0, maxLength);
3947
3629
  return `${text4.slice(0, maxLength - 3)}...`;
3948
3630
  }
3949
- function isNonEmptyString2(value) {
3631
+ function isNonEmptyString(value) {
3950
3632
  return typeof value === "string" && value.length > 0;
3951
3633
  }
3952
3634
  function extractThreadId(value) {
3953
3635
  if (!value || typeof value !== "object") return;
3954
3636
  const obj = value;
3955
- const maybeThreadId = isNonEmptyString2(obj.thread_id) && obj.thread_id || isNonEmptyString2(obj.threadId) && obj.threadId || isNonEmptyString2(obj.threadID) && obj.threadID || isNonEmptyString2(obj.session_id) && obj.session_id || isNonEmptyString2(obj.sessionId) && obj.sessionId || isNonEmptyString2(obj.sessionID) && obj.sessionID;
3637
+ const maybeThreadId = isNonEmptyString(obj.thread_id) && obj.thread_id || isNonEmptyString(obj.threadId) && obj.threadId || isNonEmptyString(obj.threadID) && obj.threadID || isNonEmptyString(obj.session_id) && obj.session_id || isNonEmptyString(obj.sessionId) && obj.sessionId || isNonEmptyString(obj.sessionID) && obj.sessionID;
3956
3638
  return maybeThreadId || void 0;
3957
3639
  }
3958
3640
  var init_utils = __esm({
@@ -3998,7 +3680,7 @@ async function* adaptClaude(lines) {
3998
3680
  continue;
3999
3681
  }
4000
3682
  const eventType = event.type;
4001
- if (!isNonEmptyString2(eventType)) continue;
3683
+ if (!isNonEmptyString(eventType)) continue;
4002
3684
  if (!emittedSessionStart) {
4003
3685
  const threadId = extractThreadId(event);
4004
3686
  emittedSessionStart = true;
@@ -4021,16 +3703,16 @@ async function* adaptClaude(lines) {
4021
3703
  const item = block;
4022
3704
  if (!item || typeof item !== "object") continue;
4023
3705
  const blockType = item.type;
4024
- if (!isNonEmptyString2(blockType)) continue;
3706
+ if (!isNonEmptyString(blockType)) continue;
4025
3707
  if (eventType === "assistant") {
4026
- if (blockType === "text" && isNonEmptyString2(item.text)) {
3708
+ if (blockType === "text" && isNonEmptyString(item.text)) {
4027
3709
  yield {
4028
3710
  event: "agent_message",
4029
3711
  text: item.text
4030
3712
  };
4031
3713
  continue;
4032
3714
  }
4033
- if (blockType === "tool_use" && isNonEmptyString2(item.id) && isNonEmptyString2(item.name)) {
3715
+ if (blockType === "tool_use" && isNonEmptyString(item.id) && isNonEmptyString(item.name)) {
4034
3716
  const kind = TOOL_KIND_MAP[item.name] ?? "other";
4035
3717
  toolKindsById.set(item.id, kind);
4036
3718
  yield {
@@ -4044,25 +3726,25 @@ async function* adaptClaude(lines) {
4044
3726
  continue;
4045
3727
  }
4046
3728
  if (eventType === "user") {
4047
- if (!isNonEmptyString2(item.tool_use_id)) continue;
3729
+ if (!isNonEmptyString(item.tool_use_id)) continue;
4048
3730
  if (blockType !== "tool_result") continue;
4049
3731
  const kind = toolKindsById.get(item.tool_use_id);
4050
3732
  toolKindsById.delete(item.tool_use_id);
4051
- let path25;
3733
+ let path24;
4052
3734
  if (typeof item.content === "string") {
4053
- path25 = item.content;
3735
+ path24 = item.content;
4054
3736
  } else {
4055
3737
  try {
4056
- path25 = JSON.stringify(item.content);
3738
+ path24 = JSON.stringify(item.content);
4057
3739
  } catch {
4058
- path25 = String(item.content);
3740
+ path24 = String(item.content);
4059
3741
  }
4060
3742
  }
4061
3743
  yield {
4062
3744
  event: "tool_complete",
4063
3745
  id: item.tool_use_id,
4064
3746
  kind,
4065
- path: path25
3747
+ path: path24
4066
3748
  };
4067
3749
  }
4068
3750
  }
@@ -4116,7 +3798,7 @@ async function* adaptCodex(lines) {
4116
3798
  continue;
4117
3799
  }
4118
3800
  const eventType = event.type;
4119
- if (!isNonEmptyString2(eventType)) continue;
3801
+ if (!isNonEmptyString(eventType)) continue;
4120
3802
  if (eventType === "thread.started") {
4121
3803
  const maybeThreadId = extractThreadId(event);
4122
3804
  yield { event: "session_start", threadId: maybeThreadId };
@@ -4140,23 +3822,23 @@ async function* adaptCodex(lines) {
4140
3822
  const item = event.item ?? null;
4141
3823
  if (!item || typeof item !== "object") continue;
4142
3824
  const itemType = item.type;
4143
- if (!isNonEmptyString2(itemType)) continue;
3825
+ if (!isNonEmptyString(itemType)) continue;
4144
3826
  if (eventType === "item.started") {
4145
- if (!isNonEmptyString2(item.id)) continue;
3827
+ if (!isNonEmptyString(item.id)) continue;
4146
3828
  let kind;
4147
3829
  let title;
4148
3830
  if (itemType === "command_execution") {
4149
3831
  kind = "exec";
4150
- title = truncate2(isNonEmptyString2(item.command) ? item.command : "", 80);
3832
+ title = truncate2(isNonEmptyString(item.command) ? item.command : "", 80);
4151
3833
  } else if (itemType === "file_edit") {
4152
3834
  kind = "edit";
4153
- title = isNonEmptyString2(item.path) ? item.path : "";
3835
+ title = isNonEmptyString(item.path) ? item.path : "";
4154
3836
  } else if (itemType === "thinking") {
4155
3837
  kind = "think";
4156
3838
  title = "thinking...";
4157
3839
  } else if (itemType === "mcp_tool_call") {
4158
- const server = isNonEmptyString2(item.server) ? item.server : "unknown";
4159
- const tool = isNonEmptyString2(item.tool) ? item.tool : "unknown";
3840
+ const server = isNonEmptyString(item.server) ? item.server : "unknown";
3841
+ const tool = isNonEmptyString(item.tool) ? item.tool : "unknown";
4160
3842
  kind = "other";
4161
3843
  title = `${server}.${tool}`;
4162
3844
  }
@@ -4169,25 +3851,25 @@ async function* adaptCodex(lines) {
4169
3851
  }
4170
3852
  if (eventType === "item.completed") {
4171
3853
  if (itemType === "agent_message") {
4172
- if (!isNonEmptyString2(item.text)) continue;
3854
+ if (!isNonEmptyString(item.text)) continue;
4173
3855
  yield { event: "agent_message", text: item.text };
4174
3856
  continue;
4175
3857
  }
4176
3858
  if (itemType === "reasoning") {
4177
- const text4 = isNonEmptyString2(item.text) ? item.text : isNonEmptyString2(item.content) ? item.content : isNonEmptyString2(item.summary) ? item.summary : void 0;
3859
+ const text4 = isNonEmptyString(item.text) ? item.text : isNonEmptyString(item.content) ? item.content : isNonEmptyString(item.summary) ? item.summary : void 0;
4178
3860
  if (!text4) continue;
4179
3861
  yield { event: "reasoning", text: text4 };
4180
3862
  continue;
4181
3863
  }
4182
- if (!isNonEmptyString2(item.id)) continue;
3864
+ if (!isNonEmptyString(item.id)) continue;
4183
3865
  if (itemType === "command_execution" || itemType === "file_edit" || itemType === "mcp_tool_call") {
4184
3866
  const kindFromStart = toolKindById.get(item.id);
4185
3867
  const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
4186
- const titleFromEvent = isNonEmptyString2(item.path) ? item.path : itemType === "mcp_tool_call" ? `${isNonEmptyString2(item.server) ? item.server : "unknown"}.${isNonEmptyString2(item.tool) ? item.tool : "unknown"}` : void 0;
4187
- const path25 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
3868
+ const titleFromEvent = isNonEmptyString(item.path) ? item.path : itemType === "mcp_tool_call" ? `${isNonEmptyString(item.server) ? item.server : "unknown"}.${isNonEmptyString(item.tool) ? item.tool : "unknown"}` : void 0;
3869
+ const path24 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
4188
3870
  toolTitleById.delete(item.id);
4189
3871
  toolKindById.delete(item.id);
4190
- yield { event: "tool_complete", id: item.id, kind, path: path25 };
3872
+ yield { event: "tool_complete", id: item.id, kind, path: path24 };
4191
3873
  }
4192
3874
  }
4193
3875
  }
@@ -4226,9 +3908,9 @@ async function* adaptKimi(lines) {
4226
3908
  }
4227
3909
  }
4228
3910
  const role = event.role;
4229
- if (!isNonEmptyString2(role) || role !== "assistant") continue;
3911
+ if (!isNonEmptyString(role) || role !== "assistant") continue;
4230
3912
  const content = event.content;
4231
- if (!isNonEmptyString2(content)) continue;
3913
+ if (!isNonEmptyString(content)) continue;
4232
3914
  yield { event: "agent_message", text: content };
4233
3915
  }
4234
3916
  }
@@ -4257,7 +3939,7 @@ async function* adaptNative(lines) {
4257
3939
  continue;
4258
3940
  }
4259
3941
  const maybeEventType = event?.event;
4260
- if (!isNonEmptyString2(maybeEventType)) {
3942
+ if (!isNonEmptyString(maybeEventType)) {
4261
3943
  yield {
4262
3944
  event: "error",
4263
3945
  message: `[adaptNative] Line missing string "event" field: ${truncate2(line, 200)}`
@@ -4316,23 +3998,23 @@ async function* adaptOpenCode(lines) {
4316
3998
  }
4317
3999
  if (!event || typeof event !== "object") continue;
4318
4000
  const sessionID = extractThreadId(event);
4319
- if (!emittedSessionStart && isNonEmptyString2(sessionID)) {
4001
+ if (!emittedSessionStart && isNonEmptyString(sessionID)) {
4320
4002
  emittedSessionStart = true;
4321
4003
  yield { event: "session_start", threadId: sessionID };
4322
4004
  }
4323
4005
  const eventType = event.type;
4324
- if (!isNonEmptyString2(eventType)) continue;
4006
+ if (!isNonEmptyString(eventType)) continue;
4325
4007
  if (eventType === "text") {
4326
4008
  const part = event.part ?? null;
4327
4009
  if (!part || typeof part !== "object") continue;
4328
- if (!isNonEmptyString2(part.text)) continue;
4010
+ if (!isNonEmptyString(part.text)) continue;
4329
4011
  yield { event: "agent_message", text: part.text };
4330
4012
  continue;
4331
4013
  }
4332
4014
  if (eventType === "tool_use") {
4333
4015
  const part = event.part ?? null;
4334
4016
  if (!part || typeof part !== "object") continue;
4335
- if (!isNonEmptyString2(part.callID) || !isNonEmptyString2(part.tool)) continue;
4017
+ if (!isNonEmptyString(part.callID) || !isNonEmptyString(part.tool)) continue;
4336
4018
  const state = part.state ?? null;
4337
4019
  if (!state || typeof state !== "object") continue;
4338
4020
  const kind = guessToolKind(part.tool);
@@ -4344,7 +4026,7 @@ async function* adaptOpenCode(lines) {
4344
4026
  const maybeInput = state.input;
4345
4027
  if (kind === "exec" && maybeInput && typeof maybeInput === "object") {
4346
4028
  const command = maybeInput.command;
4347
- if (isNonEmptyString2(command)) {
4029
+ if (isNonEmptyString(command)) {
4348
4030
  title = truncate2(command, 80);
4349
4031
  }
4350
4032
  }
@@ -4629,7 +4311,7 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
4629
4311
  }
4630
4312
  const id = readString(event.id);
4631
4313
  const kind = readString(event.kind);
4632
- const path25 = readString(event.path);
4314
+ const path24 = readString(event.path);
4633
4315
  let toolCall = id ? toolCallsById.get(id) : void 0;
4634
4316
  if (!toolCall) {
4635
4317
  toolCall = {};
@@ -4644,8 +4326,8 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
4644
4326
  if (kind) {
4645
4327
  toolCall.kind = kind;
4646
4328
  }
4647
- if (path25) {
4648
- toolCall.path = path25;
4329
+ if (path24) {
4330
+ toolCall.path = path24;
4649
4331
  }
4650
4332
  }
4651
4333
  var sessionCapture;
@@ -4731,8 +4413,8 @@ var init_usage_capture = __esm({
4731
4413
  });
4732
4414
 
4733
4415
  // packages/agent-spawn/src/acp/middlewares/spawn-log.ts
4734
- import path5 from "node:path";
4735
- import { homedir as homedir3 } from "node:os";
4416
+ import path4 from "node:path";
4417
+ import { homedir as homedir2 } from "node:os";
4736
4418
  import { mkdir, open } from "node:fs/promises";
4737
4419
  function pad(value, width) {
4738
4420
  return String(value).padStart(width, "0");
@@ -4765,11 +4447,11 @@ function resolveStartedAt(value) {
4765
4447
  return value;
4766
4448
  }
4767
4449
  function resolveLogFilePath(ctx) {
4768
- const baseDir = ctx.logDir ?? path5.join(homedir3(), ".poe-code", "spawn-logs");
4450
+ const baseDir = ctx.logDir ?? path4.join(homedir2(), ".poe-code", "spawn-logs");
4769
4451
  const startedAt = resolveStartedAt(ctx.startedAt);
4770
4452
  const { day, time: time3, milliseconds } = formatTimestamp(startedAt);
4771
4453
  const fileName = `${day}-${time3}-${milliseconds}-${normalizeAgent(ctx.agent)}.jsonl`;
4772
- return path5.join(baseDir, fileName);
4454
+ return path4.join(baseDir, fileName);
4773
4455
  }
4774
4456
  async function writePreloadedEvents(writer, events) {
4775
4457
  for (const event of events) {
@@ -4787,7 +4469,7 @@ var init_spawn_log = __esm({
4787
4469
  logDirPath;
4788
4470
  constructor(ctx) {
4789
4471
  this.logFilePath = resolveLogFilePath(ctx);
4790
- this.logDirPath = path5.dirname(this.logFilePath);
4472
+ this.logDirPath = path4.dirname(this.logFilePath);
4791
4473
  }
4792
4474
  async writeEvent(event) {
4793
4475
  if (this.isDisabled) {
@@ -4872,7 +4554,7 @@ var init_src5 = __esm({
4872
4554
  });
4873
4555
 
4874
4556
  // src/cli/commands/shared.ts
4875
- import path6 from "node:path";
4557
+ import path5 from "node:path";
4876
4558
  function resolveCommandFlags(program) {
4877
4559
  const opts = program.optsWithGlobals();
4878
4560
  return {
@@ -4945,7 +4627,7 @@ function buildResumeCommand(canonicalService, threadId, cwd) {
4945
4627
  if (!binaryName) {
4946
4628
  return void 0;
4947
4629
  }
4948
- const resumeCwd = path6.resolve(cwd);
4630
+ const resumeCwd = path5.resolve(cwd);
4949
4631
  const args = spawnConfig.resumeCommand(threadId, resumeCwd);
4950
4632
  const agentCommand = [binaryName, ...args.map(shlexQuote)].join(" ");
4951
4633
  const needsCdPrefix = !args.includes(resumeCwd);
@@ -5042,7 +4724,7 @@ var init_shared = __esm({
5042
4724
  });
5043
4725
 
5044
4726
  // src/sdk/spawn-core.ts
5045
- import path7 from "node:path";
4727
+ import path6 from "node:path";
5046
4728
  import chalk10 from "chalk";
5047
4729
  async function spawnCore(container, service, options, flags = { dryRun: false, verbose: false }) {
5048
4730
  const cwdOverride = resolveSpawnWorkingDirectory(
@@ -5141,10 +4823,10 @@ function resolveSpawnWorkingDirectory(baseDir, candidate) {
5141
4823
  if (!candidate || candidate.trim().length === 0) {
5142
4824
  return void 0;
5143
4825
  }
5144
- if (path7.isAbsolute(candidate)) {
4826
+ if (path6.isAbsolute(candidate)) {
5145
4827
  return candidate;
5146
4828
  }
5147
- return path7.resolve(baseDir, candidate);
4829
+ return path6.resolve(baseDir, candidate);
5148
4830
  }
5149
4831
  var init_spawn_core = __esm({
5150
4832
  "src/sdk/spawn-core.ts"() {
@@ -5154,14 +4836,14 @@ var init_spawn_core = __esm({
5154
4836
  });
5155
4837
 
5156
4838
  // src/cli/environment.ts
5157
- import path8 from "node:path";
4839
+ import path7 from "node:path";
5158
4840
  function createCliEnvironment(init) {
5159
4841
  const platform = init.platform ?? process.platform;
5160
4842
  const variables = init.variables ?? process.env;
5161
4843
  const configPath = resolveConfigPath(init.homeDir);
5162
4844
  const logDir = resolveLogDir(init.homeDir);
5163
4845
  const { poeApiBaseUrl, poeBaseUrl } = resolvePoeBaseUrls(variables);
5164
- const resolveHomePath = (...segments) => path8.join(init.homeDir, ...segments);
4846
+ const resolveHomePath = (...segments) => path7.join(init.homeDir, ...segments);
5165
4847
  const getVariable = (name) => variables[name];
5166
4848
  return {
5167
4849
  cwd: init.cwd,
@@ -5177,10 +4859,10 @@ function createCliEnvironment(init) {
5177
4859
  };
5178
4860
  }
5179
4861
  function resolveConfigPath(homeDir) {
5180
- return path8.join(homeDir, ".poe-code", "config.json");
4862
+ return path7.join(homeDir, ".poe-code", "config.json");
5181
4863
  }
5182
4864
  function resolveLogDir(homeDir) {
5183
- return path8.join(homeDir, ".poe-code", "logs");
4865
+ return path7.join(homeDir, ".poe-code", "logs");
5184
4866
  }
5185
4867
  function resolvePoeBaseUrls(variables) {
5186
4868
  const raw = variables.POE_BASE_URL;
@@ -5404,7 +5086,7 @@ var init_prompts2 = __esm({
5404
5086
  });
5405
5087
 
5406
5088
  // src/cli/options.ts
5407
- function stripBracketedPaste2(value) {
5089
+ function stripBracketedPaste(value) {
5408
5090
  return value.replace(/\x1b\[200~/g, "").replace(/\x1b\[201~/g, "").replace(/undefinedndefined$/, "").replace(/undefined$/, "").replace(/ndefined$/, "");
5409
5091
  }
5410
5092
  function isAlphanumericWithSeparators(value) {
@@ -5423,7 +5105,7 @@ function isAlphanumericWithSeparators(value) {
5423
5105
  function hasMinimumApiKeyLength(value) {
5424
5106
  return value.length >= MIN_API_KEY_LENGTH;
5425
5107
  }
5426
- function isValidApiKeyFormat2(key) {
5108
+ function isValidApiKeyFormat(key) {
5427
5109
  if (key.length === 0) return false;
5428
5110
  if (key.startsWith("sk-poe-")) {
5429
5111
  const hash2 = key.slice(7);
@@ -5447,7 +5129,7 @@ function createOptionResolvers(init) {
5447
5129
  return result;
5448
5130
  };
5449
5131
  const normalizeApiKey2 = (value) => {
5450
- const sanitized = stripBracketedPaste2(value);
5132
+ const sanitized = stripBracketedPaste(value);
5451
5133
  const trimmed = sanitized.trim();
5452
5134
  if (trimmed.length === 0) {
5453
5135
  throw new Error("POE API key cannot be empty.");
@@ -5455,7 +5137,7 @@ function createOptionResolvers(init) {
5455
5137
  return trimmed;
5456
5138
  };
5457
5139
  const confirmKeyFormat = async (apiKey, assumeYes) => {
5458
- if (isValidApiKeyFormat2(apiKey)) return true;
5140
+ if (isValidApiKeyFormat(apiKey)) return true;
5459
5141
  if (assumeYes) return false;
5460
5142
  return await init.confirm(
5461
5143
  "Key doesn't match expected API key format. Use it anyway?"
@@ -5614,7 +5296,7 @@ function isSilentError(error2) {
5614
5296
  }
5615
5297
  return error2.name === "SilentError" || error2.name === "OperationCancelledError";
5616
5298
  }
5617
- var CliError, SilentError, ApiError, ValidationError, OperationCancelledError;
5299
+ var CliError, SilentError, ApiError, ValidationError, AuthenticationError, OperationCancelledError;
5618
5300
  var init_errors = __esm({
5619
5301
  "src/cli/errors.ts"() {
5620
5302
  "use strict";
@@ -5654,6 +5336,11 @@ var init_errors = __esm({
5654
5336
  super(message, context, { isUserError: true });
5655
5337
  }
5656
5338
  };
5339
+ AuthenticationError = class extends CliError {
5340
+ constructor(message, context) {
5341
+ super(message, context, { isUserError: true });
5342
+ }
5343
+ };
5657
5344
  OperationCancelledError = class extends SilentError {
5658
5345
  constructor(message = "Operation cancelled.") {
5659
5346
  super(message, { isUserError: true });
@@ -5868,7 +5555,7 @@ var init_logger2 = __esm({
5868
5555
  });
5869
5556
 
5870
5557
  // src/cli/error-logger.ts
5871
- import path9 from "node:path";
5558
+ import path8 from "node:path";
5872
5559
  var DEFAULT_MAX_SIZE, DEFAULT_MAX_BACKUPS, ErrorLogger;
5873
5560
  var init_error_logger = __esm({
5874
5561
  "src/cli/error-logger.ts"() {
@@ -5885,7 +5572,7 @@ var init_error_logger = __esm({
5885
5572
  fileLoggingAvailable;
5886
5573
  constructor(options) {
5887
5574
  this.fs = options.fs;
5888
- this.logFilePath = path9.join(options.logDir, "errors.log");
5575
+ this.logFilePath = path8.join(options.logDir, "errors.log");
5889
5576
  this.logToStderr = options.logToStderr ?? true;
5890
5577
  this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;
5891
5578
  this.maxBackups = options.maxBackups ?? DEFAULT_MAX_BACKUPS;
@@ -6004,7 +5691,7 @@ ${entry.stack}`);
6004
5691
  return `${this.logFilePath}.${index}`;
6005
5692
  }
6006
5693
  ensureLogDirectory() {
6007
- const directory = path9.dirname(this.logFilePath);
5694
+ const directory = path8.dirname(this.logFilePath);
6008
5695
  try {
6009
5696
  if (!this.fs.existsSync(directory)) {
6010
5697
  this.fs.mkdirSync(directory, { recursive: true });
@@ -6022,7 +5709,7 @@ ${entry.stack}`);
6022
5709
  });
6023
5710
 
6024
5711
  // src/providers/index.ts
6025
- import path10 from "node:path";
5712
+ import path9 from "node:path";
6026
5713
  import { readdir } from "node:fs/promises";
6027
5714
  import { fileURLToPath, pathToFileURL } from "node:url";
6028
5715
  function isProviderModule(filename) {
@@ -6049,7 +5736,7 @@ async function loadProviders() {
6049
5736
  for (const entry of entries) {
6050
5737
  if (!entry.isFile()) continue;
6051
5738
  if (!isProviderModule(entry.name)) continue;
6052
- const moduleUrl = pathToFileURL(path10.join(currentDir, entry.name)).href;
5739
+ const moduleUrl = pathToFileURL(path9.join(currentDir, entry.name)).href;
6053
5740
  const moduleExports = await import(moduleUrl);
6054
5741
  if (!moduleExports.provider) {
6055
5742
  throw new Error(`Provider module "${entry.name}" must export "provider".`);
@@ -6065,8 +5752,8 @@ var moduleDir, currentDir, defaultProviders;
6065
5752
  var init_providers = __esm({
6066
5753
  async "src/providers/index.ts"() {
6067
5754
  "use strict";
6068
- moduleDir = path10.dirname(fileURLToPath(import.meta.url));
6069
- currentDir = path10.basename(moduleDir) === "providers" ? moduleDir : path10.join(moduleDir, "providers");
5755
+ moduleDir = path9.dirname(fileURLToPath(import.meta.url));
5756
+ currentDir = path9.basename(moduleDir) === "providers" ? moduleDir : path9.join(moduleDir, "providers");
6070
5757
  defaultProviders = await loadProviders();
6071
5758
  }
6072
5759
  });
@@ -6408,21 +6095,21 @@ function createSdkContainer(options) {
6408
6095
  });
6409
6096
  loggerFactory.setErrorLogger(errorLogger);
6410
6097
  const asyncFs = {
6411
- readFile: ((path25, encoding) => {
6098
+ readFile: ((path24, encoding) => {
6412
6099
  if (encoding) {
6413
- return fs2.readFile(path25, encoding);
6100
+ return fs2.readFile(path24, encoding);
6414
6101
  }
6415
- return fs2.readFile(path25);
6102
+ return fs2.readFile(path24);
6416
6103
  }),
6417
- writeFile: (path25, data, opts) => fs2.writeFile(path25, data, opts),
6418
- mkdir: (path25, opts) => fs2.mkdir(path25, opts).then(() => {
6104
+ writeFile: (path24, data, opts) => fs2.writeFile(path24, data, opts),
6105
+ mkdir: (path24, opts) => fs2.mkdir(path24, opts).then(() => {
6419
6106
  }),
6420
- stat: (path25) => fs2.stat(path25),
6421
- rm: (path25, opts) => fs2.rm(path25, opts),
6422
- unlink: (path25) => fs2.unlink(path25),
6423
- readdir: (path25) => fs2.readdir(path25),
6107
+ stat: (path24) => fs2.stat(path24),
6108
+ rm: (path24, opts) => fs2.rm(path24, opts),
6109
+ unlink: (path24) => fs2.unlink(path24),
6110
+ readdir: (path24) => fs2.readdir(path24),
6424
6111
  copyFile: (src, dest) => fs2.copyFile(src, dest),
6425
- chmod: (path25, mode) => fs2.chmod(path25, mode)
6112
+ chmod: (path24, mode) => fs2.chmod(path24, mode)
6426
6113
  };
6427
6114
  const contextFactory = createCommandContextFactory({ fs: asyncFs });
6428
6115
  const authFs = {
@@ -6432,21 +6119,21 @@ function createSdkContainer(options) {
6432
6119
  unlink: (filePath) => fs2.unlink(filePath),
6433
6120
  chmod: (filePath, mode) => fs2.chmod(filePath, mode)
6434
6121
  };
6435
- const { store: authStore } = createAuthStore({
6122
+ const { store: authStore } = createSecretStore({
6123
+ backendEnvVar: "POE_AUTH_BACKEND",
6436
6124
  env: variables,
6437
6125
  platform: process.platform,
6438
6126
  fileStore: {
6439
6127
  fs: authFs,
6440
- getHomeDirectory: () => homeDir
6441
- },
6442
- legacyCredentials: {
6443
- fs: authFs,
6128
+ salt: "poe-code:encrypted-file-auth-store:v1",
6129
+ defaultDirectory: ".poe-code",
6130
+ defaultFileName: "credentials.enc",
6444
6131
  getHomeDirectory: () => homeDir
6445
6132
  }
6446
6133
  });
6447
- const readApiKey = authStore.getApiKey.bind(authStore);
6448
- const writeApiKey = authStore.setApiKey.bind(authStore);
6449
- const deleteApiKey = authStore.deleteApiKey.bind(authStore);
6134
+ const readApiKey = authStore.get.bind(authStore);
6135
+ const writeApiKey = authStore.set.bind(authStore);
6136
+ const deleteApiKey = authStore.delete.bind(authStore);
6450
6137
  const noopPrompts = async () => {
6451
6138
  throw new Error("SDK does not support interactive prompts");
6452
6139
  };
@@ -7124,8 +6811,8 @@ function resourceNotFound(resource) {
7124
6811
  `Resource not found: ${resource}`
7125
6812
  );
7126
6813
  }
7127
- function assertAbsolutePath(path25) {
7128
- if (!isAbsolute(path25)) {
6814
+ function assertAbsolutePath(path24) {
6815
+ if (!isAbsolute(path24)) {
7129
6816
  throw invalidParams('"path" must be an absolute path');
7130
6817
  }
7131
6818
  }
@@ -7723,7 +7410,7 @@ var init_stream_helpers = __esm({
7723
7410
 
7724
7411
  // packages/poe-acp-client/src/run-report.ts
7725
7412
  import * as fsPromises from "node:fs/promises";
7726
- import { homedir as homedir5 } from "node:os";
7413
+ import { homedir as homedir4 } from "node:os";
7727
7414
  import { join } from "node:path";
7728
7415
  async function generateRunReportFromSessionUpdateStream(stream, options = {}) {
7729
7416
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
@@ -8886,7 +8573,7 @@ var init_acp_core = __esm({
8886
8573
  });
8887
8574
 
8888
8575
  // packages/poe-agent/src/plugins/plugin-args.ts
8889
- import path11 from "node:path";
8576
+ import path10 from "node:path";
8890
8577
  function isObjectRecord3(value) {
8891
8578
  return typeof value === "object" && value !== null && !Array.isArray(value);
8892
8579
  }
@@ -8917,13 +8604,13 @@ function getOptionalString(args, key) {
8917
8604
  return value;
8918
8605
  }
8919
8606
  function resolveAllowedPath(cwd, allowedPaths, inputPath) {
8920
- const resolvedPath = path11.resolve(cwd, inputPath);
8607
+ const resolvedPath = path10.resolve(cwd, inputPath);
8921
8608
  const isAllowed = allowedPaths.some((allowedPath) => {
8922
8609
  if (allowedPath === resolvedPath) {
8923
8610
  return true;
8924
8611
  }
8925
- const rel = path11.relative(allowedPath, resolvedPath);
8926
- return rel.length > 0 && !rel.startsWith("..") && !path11.isAbsolute(rel);
8612
+ const rel = path10.relative(allowedPath, resolvedPath);
8613
+ return rel.length > 0 && !rel.startsWith("..") && !path10.isAbsolute(rel);
8927
8614
  });
8928
8615
  if (!isAllowed) {
8929
8616
  throw new Error(`Path is outside allowed paths: ${inputPath}`);
@@ -8938,7 +8625,7 @@ var init_plugin_args = __esm({
8938
8625
 
8939
8626
  // packages/poe-agent/src/plugins/poe-agent-plugin-files.ts
8940
8627
  import fsPromises2 from "node:fs/promises";
8941
- import path12 from "node:path";
8628
+ import path11 from "node:path";
8942
8629
  async function fileExists(fs3, filePath) {
8943
8630
  try {
8944
8631
  await fs3.readFile(filePath, "utf8");
@@ -8962,9 +8649,9 @@ var init_poe_agent_plugin_files = __esm({
8962
8649
  "use strict";
8963
8650
  init_plugin_args();
8964
8651
  filesPlugin = (options = {}) => {
8965
- const cwd = path12.resolve(options.cwd ?? process.cwd());
8652
+ const cwd = path11.resolve(options.cwd ?? process.cwd());
8966
8653
  const allowedPaths = (options.allowedPaths ?? [cwd]).map(
8967
- (allowedPath) => path12.resolve(cwd, allowedPath)
8654
+ (allowedPath) => path11.resolve(cwd, allowedPath)
8968
8655
  );
8969
8656
  const fs3 = options.fs ?? fsPromises2;
8970
8657
  const readFileTool = {
@@ -9018,7 +8705,7 @@ var init_poe_agent_plugin_files = __esm({
9018
8705
  async call(args) {
9019
8706
  const command = getRequiredString(args, "command");
9020
8707
  const filePath = resolveAllowedPath(cwd, allowedPaths, getRequiredString(args, "path"));
9021
- const displayedPath = path12.relative(cwd, filePath) || path12.basename(filePath);
8708
+ const displayedPath = path11.relative(cwd, filePath) || path11.basename(filePath);
9022
8709
  if (command === "str_replace") {
9023
8710
  const oldStr = getRequiredString(args, "old_str", true);
9024
8711
  const newStr = getRequiredString(args, "new_str", true);
@@ -9038,7 +8725,7 @@ var init_poe_agent_plugin_files = __esm({
9038
8725
  if (await fileExists(fs3, filePath)) {
9039
8726
  throw new Error("File already exists \u2014 use str_replace to edit");
9040
8727
  }
9041
- await fs3.mkdir(path12.dirname(filePath), { recursive: true });
8728
+ await fs3.mkdir(path11.dirname(filePath), { recursive: true });
9042
8729
  await fs3.writeFile(filePath, fileText, "utf8");
9043
8730
  return `Created file: ${displayedPath}`;
9044
8731
  }
@@ -9079,7 +8766,7 @@ var init_poe_agent_plugin_files = __esm({
9079
8766
 
9080
8767
  // packages/poe-agent/src/plugins/poe-agent-plugin-shell.ts
9081
8768
  import { exec as execCallback } from "node:child_process";
9082
- import path13 from "node:path";
8769
+ import path12 from "node:path";
9083
8770
  import { promisify } from "node:util";
9084
8771
  async function defaultRunCommand(command, cwd) {
9085
8772
  try {
@@ -9112,9 +8799,9 @@ var init_poe_agent_plugin_shell = __esm({
9112
8799
  init_plugin_args();
9113
8800
  exec = promisify(execCallback);
9114
8801
  shellPlugin = (options = {}) => {
9115
- const cwd = path13.resolve(options.cwd ?? process.cwd());
8802
+ const cwd = path12.resolve(options.cwd ?? process.cwd());
9116
8803
  const allowedPaths = (options.allowedPaths ?? [cwd]).map(
9117
- (allowedPath) => path13.resolve(cwd, allowedPath)
8804
+ (allowedPath) => path12.resolve(cwd, allowedPath)
9118
8805
  );
9119
8806
  const runCommand2 = options.runCommand ?? defaultRunCommand;
9120
8807
  const runCommandTool = {
@@ -11441,8 +11128,15 @@ async function resolveApiKey(explicitApiKey) {
11441
11128
  if (normalizedExplicitApiKey) {
11442
11129
  return normalizedExplicitApiKey;
11443
11130
  }
11444
- const { store } = createAuthStore();
11445
- const storedApiKey = normalizeNonEmptyString(await store.getApiKey());
11131
+ const { store } = createSecretStore({
11132
+ backendEnvVar: "POE_AUTH_BACKEND",
11133
+ fileStore: {
11134
+ salt: "poe-code:encrypted-file-auth-store:v1",
11135
+ defaultDirectory: ".poe-code",
11136
+ defaultFileName: "credentials.enc"
11137
+ }
11138
+ });
11139
+ const storedApiKey = normalizeNonEmptyString(await store.get());
11446
11140
  if (storedApiKey) {
11447
11141
  return storedApiKey;
11448
11142
  }
@@ -12451,7 +12145,7 @@ var init_spawn3 = __esm({
12451
12145
  });
12452
12146
 
12453
12147
  // packages/pipeline/src/utils.ts
12454
- function isRecord3(value) {
12148
+ function isRecord2(value) {
12455
12149
  return typeof value === "object" && value !== null && !Array.isArray(value);
12456
12150
  }
12457
12151
  function isNotFound2(error2) {
@@ -12485,7 +12179,7 @@ var init_utils2 = __esm({
12485
12179
  });
12486
12180
 
12487
12181
  // packages/pipeline/src/config/loader.ts
12488
- import path14 from "node:path";
12182
+ import path13 from "node:path";
12489
12183
  import { parse as parse4 } from "yaml";
12490
12184
  function asStepMode(value) {
12491
12185
  if (value === void 0 || value === null) {
@@ -12509,19 +12203,19 @@ function parseStepConfigDocument(filePath, content) {
12509
12203
  if (document === null || document === void 0) {
12510
12204
  return {};
12511
12205
  }
12512
- if (!isRecord3(document)) {
12206
+ if (!isRecord2(document)) {
12513
12207
  throw new Error(`Invalid pipeline step config in "${filePath}": expected a top-level object.`);
12514
12208
  }
12515
12209
  const stepsValue = document.steps;
12516
12210
  if (stepsValue === void 0 || stepsValue === null) {
12517
12211
  return {};
12518
12212
  }
12519
- if (!isRecord3(stepsValue)) {
12213
+ if (!isRecord2(stepsValue)) {
12520
12214
  throw new Error(`Invalid pipeline step config in "${filePath}": "steps" must be an object.`);
12521
12215
  }
12522
12216
  const steps = {};
12523
12217
  for (const [stepName, value] of Object.entries(stepsValue)) {
12524
- if (!isRecord3(value)) {
12218
+ if (!isRecord2(value)) {
12525
12219
  throw new Error(`Invalid step "${stepName}" in "${filePath}": expected an object.`);
12526
12220
  }
12527
12221
  const instruction = value.instruction;
@@ -12543,7 +12237,7 @@ function parseConfigDocument(filePath, content) {
12543
12237
  if (document === null || document === void 0) {
12544
12238
  return {};
12545
12239
  }
12546
- if (!isRecord3(document)) {
12240
+ if (!isRecord2(document)) {
12547
12241
  throw new Error(`Invalid pipeline config in "${filePath}": expected a top-level object.`);
12548
12242
  }
12549
12243
  const planPath = document.planPath;
@@ -12569,8 +12263,8 @@ async function loadStepsFile(fs3, filePath) {
12569
12263
  return parseStepConfigDocument(filePath, content);
12570
12264
  }
12571
12265
  async function loadPipelineConfig(options) {
12572
- const globalPath = path14.join(options.homeDir, ".poe-code", "pipeline", "config.yaml");
12573
- const projectPath = path14.join(options.cwd, ".poe-code", "pipeline", "config.yaml");
12266
+ const globalPath = path13.join(options.homeDir, ".poe-code", "pipeline", "config.yaml");
12267
+ const projectPath = path13.join(options.cwd, ".poe-code", "pipeline", "config.yaml");
12574
12268
  const [globalConfig2, projectConfig] = await Promise.all([
12575
12269
  loadConfigFile(options.fs, globalPath),
12576
12270
  loadConfigFile(options.fs, projectPath)
@@ -12581,8 +12275,8 @@ async function loadPipelineConfig(options) {
12581
12275
  };
12582
12276
  }
12583
12277
  async function loadResolvedSteps(options) {
12584
- const globalPath = path14.join(options.homeDir, ".poe-code", "pipeline", "steps.yaml");
12585
- const projectPath = path14.join(options.cwd, ".poe-code", "pipeline", "steps.yaml");
12278
+ const globalPath = path13.join(options.homeDir, ".poe-code", "pipeline", "steps.yaml");
12279
+ const projectPath = path13.join(options.cwd, ".poe-code", "pipeline", "steps.yaml");
12586
12280
  const [globalSteps, projectSteps] = await Promise.all([
12587
12281
  loadStepsFile(options.fs, globalPath),
12588
12282
  loadStepsFile(options.fs, projectPath)
@@ -12621,7 +12315,7 @@ function parseTaskStatus(value, availableSteps, taskId) {
12621
12315
  if (typeof value === "string") {
12622
12316
  return normalizeStatus(value, "task status");
12623
12317
  }
12624
- if (!isRecord3(value)) {
12318
+ if (!isRecord2(value)) {
12625
12319
  throw new Error(`Invalid status for task "${taskId}": expected a string or step-status map.`);
12626
12320
  }
12627
12321
  const statusMap = {};
@@ -12641,7 +12335,7 @@ function parsePlan(yamlContent, options = {}) {
12641
12335
  const message = error2 instanceof Error ? error2.message : String(error2);
12642
12336
  throw new Error(`Invalid plan YAML: ${message}`);
12643
12337
  }
12644
- if (!isRecord3(document)) {
12338
+ if (!isRecord2(document)) {
12645
12339
  throw new Error("Invalid plan YAML: expected a top-level object.");
12646
12340
  }
12647
12341
  const tasksValue = document.tasks;
@@ -12650,7 +12344,7 @@ function parsePlan(yamlContent, options = {}) {
12650
12344
  }
12651
12345
  const ids = /* @__PURE__ */ new Set();
12652
12346
  const tasks = tasksValue.map((value, index) => {
12653
- if (!isRecord3(value)) {
12347
+ if (!isRecord2(value)) {
12654
12348
  throw new Error(`Invalid tasks[${index}]: expected an object.`);
12655
12349
  }
12656
12350
  const id = asRequiredString(value.id, `tasks[${index}].id`);
@@ -12675,7 +12369,7 @@ var init_parser = __esm({
12675
12369
  });
12676
12370
 
12677
12371
  // packages/pipeline/src/plan/discovery.ts
12678
- import path15 from "node:path";
12372
+ import path14 from "node:path";
12679
12373
  import * as fsPromises3 from "node:fs/promises";
12680
12374
  function createDefaultFs() {
12681
12375
  return {
@@ -12711,7 +12405,7 @@ function countCompletedTasks(planPath, content) {
12711
12405
  };
12712
12406
  }
12713
12407
  async function ensurePlanExists(fs3, cwd, planPath) {
12714
- const absolutePath = path15.isAbsolute(planPath) ? planPath : path15.resolve(cwd, planPath);
12408
+ const absolutePath = path14.isAbsolute(planPath) ? planPath : path14.resolve(cwd, planPath);
12715
12409
  try {
12716
12410
  const stat6 = await fs3.stat(absolutePath);
12717
12411
  if (!stat6.isFile()) {
@@ -12739,20 +12433,20 @@ async function scanPlansDir(fs3, plansDir, displayPrefix) {
12739
12433
  if (!isPlanCandidateFile(entry)) {
12740
12434
  continue;
12741
12435
  }
12742
- const absolutePath = path15.join(plansDir, entry);
12436
+ const absolutePath = path14.join(plansDir, entry);
12743
12437
  const stat6 = await fs3.stat(absolutePath);
12744
12438
  if (!stat6.isFile()) {
12745
12439
  continue;
12746
12440
  }
12747
- const displayPath = path15.join(displayPrefix, entry);
12441
+ const displayPath = path14.join(displayPrefix, entry);
12748
12442
  const content = await fs3.readFile(absolutePath, "utf8");
12749
12443
  candidates.push(countCompletedTasks(displayPath, content));
12750
12444
  }
12751
12445
  return candidates;
12752
12446
  }
12753
12447
  async function listPlanCandidates(fs3, cwd, homeDir) {
12754
- const projectDir = path15.join(cwd, ".poe-code", "pipeline", "plans");
12755
- const globalDir = path15.join(homeDir, ".poe-code", "pipeline", "plans");
12448
+ const projectDir = path14.join(cwd, ".poe-code", "pipeline", "plans");
12449
+ const globalDir = path14.join(homeDir, ".poe-code", "pipeline", "plans");
12756
12450
  const [projectCandidates, globalCandidates] = await Promise.all([
12757
12451
  scanPlansDir(fs3, projectDir, ".poe-code/pipeline/plans"),
12758
12452
  scanPlansDir(fs3, globalDir, "~/.poe-code/pipeline/plans")
@@ -12763,9 +12457,9 @@ async function listPlanCandidates(fs3, cwd, homeDir) {
12763
12457
  }
12764
12458
  function resolveAbsolutePlanPath(planPath, cwd, homeDir) {
12765
12459
  if (planPath.startsWith("~/")) {
12766
- return path15.join(homeDir, planPath.slice(2));
12460
+ return path14.join(homeDir, planPath.slice(2));
12767
12461
  }
12768
- return path15.isAbsolute(planPath) ? planPath : path15.resolve(cwd, planPath);
12462
+ return path14.isAbsolute(planPath) ? planPath : path14.resolve(cwd, planPath);
12769
12463
  }
12770
12464
  async function resolvePlanPath(options) {
12771
12465
  const fs3 = options.fs ?? createDefaultFs();
@@ -13008,7 +12702,7 @@ var init_lock = __esm({
13008
12702
  });
13009
12703
 
13010
12704
  // packages/pipeline/src/run/pipeline.ts
13011
- import path16 from "node:path";
12705
+ import path15 from "node:path";
13012
12706
  import * as fsPromises5 from "node:fs/promises";
13013
12707
  function createDefaultFs3() {
13014
12708
  return {
@@ -13044,9 +12738,9 @@ function resolveMode(stepName, steps) {
13044
12738
  return step.mode;
13045
12739
  }
13046
12740
  async function archivePlan(fs3, absolutePlanPath) {
13047
- const dir = path16.dirname(absolutePlanPath);
13048
- const archiveDir = path16.join(dir, "archive");
13049
- const archivePath = path16.join(archiveDir, path16.basename(absolutePlanPath));
12741
+ const dir = path15.dirname(absolutePlanPath);
12742
+ const archiveDir = path15.join(dir, "archive");
12743
+ const archivePath = path15.join(archiveDir, path15.basename(absolutePlanPath));
13050
12744
  await fs3.mkdir(archiveDir, { recursive: true });
13051
12745
  await fs3.rename(absolutePlanPath, archivePath);
13052
12746
  }
@@ -13383,13 +13077,13 @@ async function readErrorBody(response) {
13383
13077
  }
13384
13078
  }
13385
13079
  function extractTextContent(data) {
13386
- if (!isRecord4(data)) return void 0;
13080
+ if (!isRecord3(data)) return void 0;
13387
13081
  const choices = data.choices;
13388
13082
  if (!Array.isArray(choices) || choices.length === 0) return void 0;
13389
13083
  const first = choices[0];
13390
- if (!isRecord4(first)) return void 0;
13084
+ if (!isRecord3(first)) return void 0;
13391
13085
  const message = first.message;
13392
- if (!isRecord4(message)) return void 0;
13086
+ if (!isRecord3(message)) return void 0;
13393
13087
  return typeof message.content === "string" ? message.content : void 0;
13394
13088
  }
13395
13089
  function extractMediaFromCompletion(data) {
@@ -13397,14 +13091,14 @@ function extractMediaFromCompletion(data) {
13397
13091
  if (!content) return {};
13398
13092
  try {
13399
13093
  const parsed = JSON.parse(content);
13400
- if (isRecord4(parsed) && typeof parsed.url === "string") {
13094
+ if (isRecord3(parsed) && typeof parsed.url === "string") {
13401
13095
  return {
13402
13096
  url: parsed.url,
13403
13097
  mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0,
13404
13098
  data: typeof parsed.data === "string" ? parsed.data : void 0
13405
13099
  };
13406
13100
  }
13407
- if (isRecord4(parsed) && typeof parsed.data === "string") {
13101
+ if (isRecord3(parsed) && typeof parsed.data === "string") {
13408
13102
  return {
13409
13103
  data: parsed.data,
13410
13104
  mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0
@@ -13438,7 +13132,7 @@ function isValidUrl(value) {
13438
13132
  return false;
13439
13133
  }
13440
13134
  }
13441
- function isRecord4(value) {
13135
+ function isRecord3(value) {
13442
13136
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
13443
13137
  }
13444
13138
  var init_llm_client = __esm({
@@ -13478,6 +13172,213 @@ var init_client_instance = __esm({
13478
13172
  }
13479
13173
  });
13480
13174
 
13175
+ // packages/poe-oauth/src/check-auth.ts
13176
+ var init_check_auth = __esm({
13177
+ "packages/poe-oauth/src/check-auth.ts"() {
13178
+ "use strict";
13179
+ }
13180
+ });
13181
+
13182
+ // packages/poe-oauth/src/api-key-validation.ts
13183
+ var init_api_key_validation = __esm({
13184
+ "packages/poe-oauth/src/api-key-validation.ts"() {
13185
+ "use strict";
13186
+ }
13187
+ });
13188
+
13189
+ // packages/poe-oauth/src/oauth-client.ts
13190
+ import http from "node:http";
13191
+ import crypto from "node:crypto";
13192
+ function createOAuthClient(config2) {
13193
+ const fetchFn = config2.fetch ?? globalThis.fetch;
13194
+ return {
13195
+ authorize: () => startAuthorization(config2, fetchFn)
13196
+ };
13197
+ }
13198
+ function generateCodeVerifier() {
13199
+ return crypto.randomBytes(32).toString("base64url");
13200
+ }
13201
+ function generateCodeChallenge(verifier) {
13202
+ return crypto.createHash("sha256").update(verifier).digest("base64url");
13203
+ }
13204
+ async function startAuthorization(config2, fetchFn) {
13205
+ const codeVerifier = generateCodeVerifier();
13206
+ const codeChallenge = generateCodeChallenge(codeVerifier);
13207
+ const server = config2.createServer ? config2.createServer() : http.createServer();
13208
+ const port = await startServer(server);
13209
+ const redirectUri = `http://127.0.0.1:${port}/callback`;
13210
+ const authorizationUrl = buildAuthorizationUrl({
13211
+ endpoint: config2.authorizationEndpoint,
13212
+ clientId: config2.clientId,
13213
+ redirectUri,
13214
+ codeChallenge
13215
+ });
13216
+ const waitForResult = async () => {
13217
+ try {
13218
+ const code = await waitForAuthorizationCode(server, config2, authorizationUrl);
13219
+ return await exchangeCodeForApiKey({
13220
+ tokenEndpoint: config2.tokenEndpoint,
13221
+ code,
13222
+ codeVerifier,
13223
+ clientId: config2.clientId,
13224
+ redirectUri,
13225
+ fetchFn
13226
+ });
13227
+ } finally {
13228
+ server.closeAllConnections?.();
13229
+ server.close();
13230
+ }
13231
+ };
13232
+ return { authorizationUrl, waitForResult };
13233
+ }
13234
+ function startServer(server) {
13235
+ return new Promise((resolve) => {
13236
+ server.listen(0, "127.0.0.1", () => {
13237
+ const address = server.address();
13238
+ resolve(address.port);
13239
+ });
13240
+ });
13241
+ }
13242
+ function buildAuthorizationUrl(params) {
13243
+ const url2 = new URL(params.endpoint);
13244
+ url2.searchParams.set("response_type", "code");
13245
+ url2.searchParams.set("client_id", params.clientId);
13246
+ url2.searchParams.set("scope", "apikey:create");
13247
+ url2.searchParams.set("code_challenge", params.codeChallenge);
13248
+ url2.searchParams.set("code_challenge_method", "S256");
13249
+ url2.searchParams.set("redirect_uri", params.redirectUri);
13250
+ return url2.toString();
13251
+ }
13252
+ function waitForAuthorizationCode(server, config2, authorizationUrl) {
13253
+ return new Promise((resolve, reject) => {
13254
+ let settled = false;
13255
+ const settle = (fn) => {
13256
+ if (!settled) {
13257
+ settled = true;
13258
+ fn();
13259
+ }
13260
+ };
13261
+ server.on("request", (req, res) => {
13262
+ const url2 = new URL(req.url, `http://127.0.0.1`);
13263
+ if (url2.pathname !== "/callback") {
13264
+ res.writeHead(404);
13265
+ res.end("Not found");
13266
+ return;
13267
+ }
13268
+ const error2 = url2.searchParams.get("error");
13269
+ if (error2) {
13270
+ const description = url2.searchParams.get("error_description") ?? error2;
13271
+ res.writeHead(400);
13272
+ res.end(`Authorization failed: ${description}`);
13273
+ settle(() => reject(new Error(`OAuth authorization failed: ${error2} \u2014 ${description}`)));
13274
+ return;
13275
+ }
13276
+ const code = url2.searchParams.get("code");
13277
+ if (!code) {
13278
+ res.writeHead(400);
13279
+ res.end("Missing authorization code");
13280
+ settle(() => reject(new Error("OAuth callback missing authorization code")));
13281
+ return;
13282
+ }
13283
+ res.writeHead(200, { "Content-Type": "text/html" });
13284
+ res.end(buildSuccessPage());
13285
+ settle(() => resolve(code));
13286
+ });
13287
+ if (config2.readLine) {
13288
+ config2.readLine().then((input) => {
13289
+ const code = extractCodeFromInput(input);
13290
+ if (code) {
13291
+ settle(() => resolve(code));
13292
+ }
13293
+ }).catch(() => {
13294
+ });
13295
+ }
13296
+ if (config2.openBrowser) {
13297
+ config2.openBrowser(authorizationUrl).catch(
13298
+ (err) => settle(() => reject(err))
13299
+ );
13300
+ }
13301
+ });
13302
+ }
13303
+ function extractCodeFromInput(input) {
13304
+ const trimmed = input.replace(/[\r\n]/g, "").trim();
13305
+ if (trimmed.length === 0) {
13306
+ return null;
13307
+ }
13308
+ try {
13309
+ const url2 = new URL(trimmed);
13310
+ return url2.searchParams.get("code");
13311
+ } catch {
13312
+ return trimmed;
13313
+ }
13314
+ }
13315
+ async function exchangeCodeForApiKey(params) {
13316
+ const body = new URLSearchParams({
13317
+ grant_type: "authorization_code",
13318
+ code: params.code,
13319
+ code_verifier: params.codeVerifier,
13320
+ client_id: params.clientId,
13321
+ redirect_uri: params.redirectUri
13322
+ });
13323
+ const response = await params.fetchFn(params.tokenEndpoint, {
13324
+ method: "POST",
13325
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
13326
+ body: body.toString()
13327
+ });
13328
+ if (!response.ok) {
13329
+ const text4 = await response.text();
13330
+ const description = parseErrorDescription(text4);
13331
+ throw new Error(description ?? `Token exchange failed (${response.status}): ${text4}`);
13332
+ }
13333
+ const data = await response.json();
13334
+ if (typeof data.api_key !== "string" || data.api_key.length === 0) {
13335
+ throw new Error("Token response missing api_key field");
13336
+ }
13337
+ return {
13338
+ apiKey: data.api_key,
13339
+ expiresIn: typeof data.api_key_expires_in === "number" ? data.api_key_expires_in : null
13340
+ };
13341
+ }
13342
+ function parseErrorDescription(text4) {
13343
+ try {
13344
+ const data = JSON.parse(text4);
13345
+ if (typeof data.error_description === "string") {
13346
+ return data.error_description;
13347
+ }
13348
+ if (typeof data.error === "string") {
13349
+ return data.error;
13350
+ }
13351
+ } catch {
13352
+ }
13353
+ return null;
13354
+ }
13355
+ function buildSuccessPage() {
13356
+ return [
13357
+ "<!DOCTYPE html>",
13358
+ "<html><head><meta charset=utf-8><title>Connected to Poe</title></head>",
13359
+ '<body style="font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0">',
13360
+ '<div style="text-align:center">',
13361
+ "<h1>Connected to Poe</h1>",
13362
+ '<p style="color:#666">You can close this tab and return to your terminal.</p>',
13363
+ "</div></body></html>"
13364
+ ].join("");
13365
+ }
13366
+ var init_oauth_client = __esm({
13367
+ "packages/poe-oauth/src/oauth-client.ts"() {
13368
+ "use strict";
13369
+ }
13370
+ });
13371
+
13372
+ // packages/poe-oauth/src/index.ts
13373
+ var init_src10 = __esm({
13374
+ "packages/poe-oauth/src/index.ts"() {
13375
+ "use strict";
13376
+ init_check_auth();
13377
+ init_api_key_validation();
13378
+ init_oauth_client();
13379
+ }
13380
+ });
13381
+
13481
13382
  // src/cli/oauth-login.ts
13482
13383
  import { exec as exec2 } from "node:child_process";
13483
13384
  import readline from "node:readline";
@@ -13522,7 +13423,7 @@ function openInBrowser(url2) {
13522
13423
  var init_oauth_login = __esm({
13523
13424
  "src/cli/oauth-login.ts"() {
13524
13425
  "use strict";
13525
- init_src();
13426
+ init_src10();
13526
13427
  init_src4();
13527
13428
  }
13528
13429
  });
@@ -13569,21 +13470,21 @@ function createCliContainer(dependencies) {
13569
13470
  unlink: (filePath) => dependencies.fs.unlink(filePath),
13570
13471
  chmod: (filePath, mode) => dependencies.fs.chmod ? dependencies.fs.chmod(filePath, mode) : Promise.resolve()
13571
13472
  };
13572
- const { store: authStore } = createAuthStore({
13473
+ const { store: authStore } = createSecretStore({
13474
+ backendEnvVar: "POE_AUTH_BACKEND",
13573
13475
  env: dependencies.env.variables,
13574
13476
  platform: dependencies.env.platform,
13575
13477
  fileStore: {
13576
13478
  fs: authFs,
13577
- getHomeDirectory: () => dependencies.env.homeDir
13578
- },
13579
- legacyCredentials: {
13580
- fs: authFs,
13479
+ salt: "poe-code:encrypted-file-auth-store:v1",
13480
+ defaultDirectory: ".poe-code",
13481
+ defaultFileName: "credentials.enc",
13581
13482
  getHomeDirectory: () => dependencies.env.homeDir
13582
13483
  }
13583
13484
  });
13584
- const readApiKey = authStore.getApiKey.bind(authStore);
13585
- const writeApiKey = authStore.setApiKey.bind(authStore);
13586
- const deleteApiKey = authStore.deleteApiKey.bind(authStore);
13485
+ const readApiKey = authStore.get.bind(authStore);
13486
+ const writeApiKey = authStore.set.bind(authStore);
13487
+ const deleteApiKey = authStore.delete.bind(authStore);
13587
13488
  const oauthEnabled = (dependencies.env.variables ?? process.env).POE_CODE_OAUTH_LOGIN !== "0";
13588
13489
  const options = createOptionResolvers({
13589
13490
  prompts: dependencies.prompts,
@@ -13653,7 +13554,7 @@ var init_container2 = __esm({
13653
13554
  });
13654
13555
 
13655
13556
  // src/services/config.ts
13656
- import path18 from "node:path";
13557
+ import path17 from "node:path";
13657
13558
  async function deleteConfig(options) {
13658
13559
  const { fs: fs3, filePath } = options;
13659
13560
  try {
@@ -13723,7 +13624,7 @@ async function readConfigDocument(fs3, filePath) {
13723
13624
  }
13724
13625
  }
13725
13626
  async function migrateLegacyCredentialsFile(fs3, configPath) {
13726
- const legacyPath = path18.join(path18.dirname(configPath), "credentials.json");
13627
+ const legacyPath = path17.join(path17.dirname(configPath), "credentials.json");
13727
13628
  try {
13728
13629
  const raw = await fs3.readFile(legacyPath, "utf8");
13729
13630
  const document = await parseConfigDocument2(fs3, legacyPath, raw);
@@ -13747,7 +13648,7 @@ async function parseConfigDocument2(fs3, filePath, raw) {
13747
13648
  }
13748
13649
  }
13749
13650
  function normalizeConfigDocument(value) {
13750
- if (!isRecord5(value)) {
13651
+ if (!isRecord4(value)) {
13751
13652
  return {};
13752
13653
  }
13753
13654
  const document = {};
@@ -13761,12 +13662,12 @@ function normalizeConfigDocument(value) {
13761
13662
  return document;
13762
13663
  }
13763
13664
  function normalizeConfiguredServices(value) {
13764
- if (!isRecord5(value)) {
13665
+ if (!isRecord4(value)) {
13765
13666
  return {};
13766
13667
  }
13767
13668
  const entries = {};
13768
13669
  for (const [key, entry] of Object.entries(value)) {
13769
- if (!isRecord5(entry)) {
13670
+ if (!isRecord4(entry)) {
13770
13671
  continue;
13771
13672
  }
13772
13673
  const normalized = normalizeConfiguredServiceMetadata({
@@ -13777,7 +13678,7 @@ function normalizeConfiguredServices(value) {
13777
13678
  return entries;
13778
13679
  }
13779
13680
  async function writeConfigDocument(fs3, filePath, document) {
13780
- await fs3.mkdir(path18.dirname(filePath), { recursive: true });
13681
+ await fs3.mkdir(path17.dirname(filePath), { recursive: true });
13781
13682
  const payload = {};
13782
13683
  if (document.apiKey) {
13783
13684
  payload.apiKey = document.apiKey;
@@ -13797,11 +13698,11 @@ async function recoverInvalidConfig(fs3, filePath, content) {
13797
13698
  }
13798
13699
  function createInvalidBackupPath(filePath) {
13799
13700
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13800
- const dir = path18.dirname(filePath);
13801
- const base = path18.basename(filePath);
13802
- return path18.join(dir, `${base}.invalid-${timestamp}.json`);
13701
+ const dir = path17.dirname(filePath);
13702
+ const base = path17.basename(filePath);
13703
+ return path17.join(dir, `${base}.invalid-${timestamp}.json`);
13803
13704
  }
13804
- function isRecord5(value) {
13705
+ function isRecord4(value) {
13805
13706
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
13806
13707
  }
13807
13708
  var EMPTY_DOCUMENT;
@@ -14061,7 +13962,7 @@ var init_agent2 = __esm({
14061
13962
  });
14062
13963
 
14063
13964
  // src/cli/commands/spawn.ts
14064
- import path19 from "node:path";
13965
+ import path18 from "node:path";
14065
13966
  function registerSpawnCommand(program, container, options = {}) {
14066
13967
  const spawnServices = container.registry.list().filter((service) => typeof service.spawn === "function" || getSpawnConfig(service.name)).map((service) => service.name);
14067
13968
  const extraServices = options.extraServices ?? [];
@@ -14272,10 +14173,10 @@ function resolveSpawnWorkingDirectory2(baseDir, candidate) {
14272
14173
  if (!candidate || candidate.trim().length === 0) {
14273
14174
  return void 0;
14274
14175
  }
14275
- if (path19.isAbsolute(candidate)) {
14176
+ if (path18.isAbsolute(candidate)) {
14276
14177
  return candidate;
14277
14178
  }
14278
- return path19.resolve(baseDir, candidate);
14179
+ return path18.resolve(baseDir, candidate);
14279
14180
  }
14280
14181
  function parseMcpSpawnConfig2(input) {
14281
14182
  if (!input) {
@@ -14395,7 +14296,7 @@ var init_spawn4 = __esm({
14395
14296
  });
14396
14297
 
14397
14298
  // src/sdk/research.ts
14398
- import path20 from "node:path";
14299
+ import path19 from "node:path";
14399
14300
  async function research(container, options) {
14400
14301
  const logger2 = options.logger;
14401
14302
  const source = await resolveSource({
@@ -14430,7 +14331,7 @@ async function research(container, options) {
14430
14331
  markdown: markdownOutput
14431
14332
  });
14432
14333
  outputPath = buildOutputPath(container.env.homeDir, options.prompt);
14433
- await ensureDirectory2(container.fs, path20.dirname(outputPath));
14334
+ await ensureDirectory2(container.fs, path19.dirname(outputPath));
14434
14335
  await container.fs.writeFile(outputPath, document, {
14435
14336
  encoding: "utf8"
14436
14337
  });
@@ -14505,7 +14406,7 @@ function buildResearchDocument(input) {
14505
14406
  }
14506
14407
  function buildClonePath(homeDir, github) {
14507
14408
  const slug = extractRepoSlug(github);
14508
- return path20.join(homeDir, ".poe-code", "repos", slug);
14409
+ return path19.join(homeDir, ".poe-code", "repos", slug);
14509
14410
  }
14510
14411
  function extractRepoSlug(value) {
14511
14412
  const trimmed = value.trim();
@@ -14543,7 +14444,7 @@ function extractRepoSlug(value) {
14543
14444
  function buildOutputPath(homeDir, prompt, now = /* @__PURE__ */ new Date()) {
14544
14445
  const timestamp = formatTimestamp2(now);
14545
14446
  const slug = buildSlug(prompt);
14546
- return path20.join(
14447
+ return path19.join(
14547
14448
  homeDir,
14548
14449
  ".poe-code",
14549
14450
  "research",
@@ -14564,7 +14465,7 @@ async function resolveSource(input) {
14564
14465
  if (options.github) {
14565
14466
  const cloneUrl = resolveGithubCloneUrl(options.github);
14566
14467
  const clonePath = buildClonePath(container.env.homeDir, options.github);
14567
- await ensureDirectory2(container.fs, path20.dirname(clonePath));
14468
+ await ensureDirectory2(container.fs, path19.dirname(clonePath));
14568
14469
  const exists = await pathExists2(container.fs, clonePath);
14569
14470
  if (!exists) {
14570
14471
  const cloneResult = await container.commandRunner(
@@ -14662,10 +14563,10 @@ function formatYamlString(value) {
14662
14563
  return JSON.stringify(value);
14663
14564
  }
14664
14565
  function resolvePath2(baseDir, candidate) {
14665
- if (path20.isAbsolute(candidate)) {
14566
+ if (path19.isAbsolute(candidate)) {
14666
14567
  return candidate;
14667
14568
  }
14668
- return path20.resolve(baseDir, candidate);
14569
+ return path19.resolve(baseDir, candidate);
14669
14570
  }
14670
14571
  function teeAcpStream(events) {
14671
14572
  const chunks = [];
@@ -14725,7 +14626,7 @@ async function removePathFallback(fs3, target) {
14725
14626
  if (stats && typeof stats.isDirectory === "function" && stats.isDirectory()) {
14726
14627
  const entries = await fs3.readdir(target);
14727
14628
  for (const entry of entries) {
14728
- await removePathFallback(fs3, path20.join(target, entry));
14629
+ await removePathFallback(fs3, path19.join(target, entry));
14729
14630
  }
14730
14631
  }
14731
14632
  try {
@@ -15064,10 +14965,7 @@ async function executeLogin(program, container, options) {
15064
14965
  resources.context.finalize();
15065
14966
  } catch (error2) {
15066
14967
  if (error2 instanceof Error) {
15067
- resources.logger.logException(error2, "login command", {
15068
- operation: "login",
15069
- configPath: container.env.configPath
15070
- });
14968
+ throw new AuthenticationError(error2.message);
15071
14969
  }
15072
14970
  throw error2;
15073
14971
  }
@@ -15120,10 +15018,11 @@ async function reconfigureServices(input) {
15120
15018
  });
15121
15019
  }
15122
15020
  }
15123
- var init_login2 = __esm({
15021
+ var init_login = __esm({
15124
15022
  "src/cli/commands/login.ts"() {
15125
15023
  "use strict";
15126
15024
  init_shared();
15025
+ init_errors();
15127
15026
  init_config2();
15128
15027
  init_mutation_events();
15129
15028
  }
@@ -15300,7 +15199,7 @@ async function executeLogout(program, container) {
15300
15199
  });
15301
15200
  resources.context.finalize();
15302
15201
  }
15303
- var init_logout2 = __esm({
15202
+ var init_logout = __esm({
15304
15203
  "src/cli/commands/logout.ts"() {
15305
15204
  "use strict";
15306
15205
  init_config2();
@@ -15405,8 +15304,8 @@ var init_auth = __esm({
15405
15304
  init_errors();
15406
15305
  init_config2();
15407
15306
  init_shared();
15408
- init_login2();
15409
- init_logout2();
15307
+ init_login();
15308
+ init_logout();
15410
15309
  }
15411
15310
  });
15412
15311
 
@@ -15606,7 +15505,7 @@ var init_media_download = __esm({
15606
15505
  });
15607
15506
 
15608
15507
  // src/cli/commands/generate.ts
15609
- import path21 from "node:path";
15508
+ import path20 from "node:path";
15610
15509
  function registerGenerateCommand(program, container) {
15611
15510
  const generate2 = program.command("generate").description("Generate content via Poe API").option("--model <model>", `Model identifier (default: ${DEFAULT_TEXT_MODEL})`).option(
15612
15511
  "--param <key=value>",
@@ -15872,11 +15771,11 @@ function getDefaultMimeType(type) {
15872
15771
  return defaults[type];
15873
15772
  }
15874
15773
  function resolveOutputPath(filename, cwd) {
15875
- if (path21.isAbsolute(filename)) {
15774
+ if (path20.isAbsolute(filename)) {
15876
15775
  return { path: filename, label: filename };
15877
15776
  }
15878
15777
  return {
15879
- path: path21.join(cwd, filename),
15778
+ path: path20.join(cwd, filename),
15880
15779
  label: `./${filename}`
15881
15780
  };
15882
15781
  }
@@ -16980,8 +16879,8 @@ var init_parseUtil = __esm({
16980
16879
  init_errors3();
16981
16880
  init_en();
16982
16881
  makeIssue = (params) => {
16983
- const { data, path: path25, errorMaps, issueData } = params;
16984
- const fullPath = [...path25, ...issueData.path || []];
16882
+ const { data, path: path24, errorMaps, issueData } = params;
16883
+ const fullPath = [...path24, ...issueData.path || []];
16985
16884
  const fullIssue = {
16986
16885
  ...issueData,
16987
16886
  path: fullPath
@@ -17261,11 +17160,11 @@ var init_types4 = __esm({
17261
17160
  init_parseUtil();
17262
17161
  init_util();
17263
17162
  ParseInputLazyPath = class {
17264
- constructor(parent, value, path25, key) {
17163
+ constructor(parent, value, path24, key) {
17265
17164
  this._cachedPath = [];
17266
17165
  this.parent = parent;
17267
17166
  this.data = value;
17268
- this._path = path25;
17167
+ this._path = path24;
17269
17168
  this._key = key;
17270
17169
  }
17271
17170
  get path() {
@@ -20769,10 +20668,10 @@ function mergeDefs(...defs) {
20769
20668
  function cloneDef(schema) {
20770
20669
  return mergeDefs(schema._zod.def);
20771
20670
  }
20772
- function getElementAtPath(obj, path25) {
20773
- if (!path25)
20671
+ function getElementAtPath(obj, path24) {
20672
+ if (!path24)
20774
20673
  return obj;
20775
- return path25.reduce((acc, key) => acc?.[key], obj);
20674
+ return path24.reduce((acc, key) => acc?.[key], obj);
20776
20675
  }
20777
20676
  function promiseAllObject(promisesObj) {
20778
20677
  const keys = Object.keys(promisesObj);
@@ -21084,11 +20983,11 @@ function aborted(x, startIndex = 0) {
21084
20983
  }
21085
20984
  return false;
21086
20985
  }
21087
- function prefixIssues(path25, issues) {
20986
+ function prefixIssues(path24, issues) {
21088
20987
  return issues.map((iss) => {
21089
20988
  var _a2;
21090
20989
  (_a2 = iss).path ?? (_a2.path = []);
21091
- iss.path.unshift(path25);
20990
+ iss.path.unshift(path24);
21092
20991
  return iss;
21093
20992
  });
21094
20993
  }
@@ -33249,8 +33148,8 @@ var require_utils = __commonJS({
33249
33148
  }
33250
33149
  return ind;
33251
33150
  }
33252
- function removeDotSegments(path25) {
33253
- let input = path25;
33151
+ function removeDotSegments(path24) {
33152
+ let input = path24;
33254
33153
  const output = [];
33255
33154
  let nextSlash = -1;
33256
33155
  let len = 0;
@@ -33449,8 +33348,8 @@ var require_schemes = __commonJS({
33449
33348
  wsComponent.secure = void 0;
33450
33349
  }
33451
33350
  if (wsComponent.resourceName) {
33452
- const [path25, query] = wsComponent.resourceName.split("?");
33453
- wsComponent.path = path25 && path25 !== "/" ? path25 : void 0;
33351
+ const [path24, query] = wsComponent.resourceName.split("?");
33352
+ wsComponent.path = path24 && path24 !== "/" ? path24 : void 0;
33454
33353
  wsComponent.query = query;
33455
33354
  wsComponent.resourceName = void 0;
33456
33355
  }
@@ -36683,7 +36582,7 @@ var init_content = __esm({
36683
36582
  });
36684
36583
 
36685
36584
  // packages/tiny-stdio-mcp-server/src/index.ts
36686
- var init_src10 = __esm({
36585
+ var init_src11 = __esm({
36687
36586
  "packages/tiny-stdio-mcp-server/src/index.ts"() {
36688
36587
  "use strict";
36689
36588
  init_server();
@@ -36987,7 +36886,7 @@ var generateTextSchema, generateImageSchema, generateVideoSchema, generateAudioS
36987
36886
  var init_mcp_server = __esm({
36988
36887
  "src/cli/mcp-server.ts"() {
36989
36888
  "use strict";
36990
- init_src10();
36889
+ init_src11();
36991
36890
  init_client_instance();
36992
36891
  init_constants();
36993
36892
  generateTextSchema = defineSchema({
@@ -37393,9 +37292,9 @@ var init_shapes = __esm({
37393
37292
  });
37394
37293
 
37395
37294
  // packages/agent-mcp-config/src/apply.ts
37396
- import path22 from "node:path";
37295
+ import path21 from "node:path";
37397
37296
  function getConfigDirectory(configPath) {
37398
- return path22.dirname(configPath);
37297
+ return path21.dirname(configPath);
37399
37298
  }
37400
37299
  function isConfigObject5(value) {
37401
37300
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -37497,7 +37396,7 @@ var init_apply = __esm({
37497
37396
  });
37498
37397
 
37499
37398
  // packages/agent-mcp-config/src/index.ts
37500
- var init_src11 = __esm({
37399
+ var init_src12 = __esm({
37501
37400
  "packages/agent-mcp-config/src/index.ts"() {
37502
37401
  "use strict";
37503
37402
  init_configs2();
@@ -37677,7 +37576,7 @@ var init_mcp2 = __esm({
37677
37576
  init_shared();
37678
37577
  init_mcp_output_format();
37679
37578
  init_command_not_found();
37680
- init_src11();
37579
+ init_src12();
37681
37580
  init_execution_context();
37682
37581
  DEFAULT_MCP_AGENT = "claude-code";
37683
37582
  }
@@ -37685,7 +37584,7 @@ var init_mcp2 = __esm({
37685
37584
 
37686
37585
  // packages/agent-skill-config/src/configs.ts
37687
37586
  import os2 from "node:os";
37688
- import path23 from "node:path";
37587
+ import path22 from "node:path";
37689
37588
  function resolveAgentSupport2(input, registry2 = agentSkillConfigs) {
37690
37589
  const resolvedId = resolveAgentId(input);
37691
37590
  if (!resolvedId) {
@@ -37877,7 +37776,7 @@ var init_apply2 = __esm({
37877
37776
  });
37878
37777
 
37879
37778
  // packages/agent-skill-config/src/index.ts
37880
- var init_src12 = __esm({
37779
+ var init_src13 = __esm({
37881
37780
  "packages/agent-skill-config/src/index.ts"() {
37882
37781
  "use strict";
37883
37782
  init_configs3();
@@ -38102,7 +38001,7 @@ var init_skill = __esm({
38102
38001
  "src/cli/commands/skill.ts"() {
38103
38002
  "use strict";
38104
38003
  init_src4();
38105
- init_src12();
38004
+ init_src13();
38106
38005
  init_shared();
38107
38006
  init_command_not_found();
38108
38007
  DEFAULT_SKILL_AGENT = "claude-code";
@@ -38696,7 +38595,7 @@ var init_models = __esm({
38696
38595
  });
38697
38596
 
38698
38597
  // src/cli/commands/pipeline.ts
38699
- import path24 from "node:path";
38598
+ import path23 from "node:path";
38700
38599
  import { readFile as readFile6, stat as stat5 } from "node:fs/promises";
38701
38600
  import { fileURLToPath as fileURLToPath4 } from "node:url";
38702
38601
  function formatDuration(ms) {
@@ -38728,11 +38627,11 @@ function resolveMaxRuns(value) {
38728
38627
  return parsed;
38729
38628
  }
38730
38629
  function resolvePipelinePaths(scope, cwd, homeDir) {
38731
- const rootPath = scope === "global" ? path24.join(homeDir, ".poe-code", "pipeline") : path24.join(cwd, ".poe-code", "pipeline");
38630
+ const rootPath = scope === "global" ? path23.join(homeDir, ".poe-code", "pipeline") : path23.join(cwd, ".poe-code", "pipeline");
38732
38631
  const displayRoot = scope === "global" ? "~/.poe-code/pipeline" : ".poe-code/pipeline";
38733
38632
  return {
38734
- plansPath: path24.join(rootPath, "plans"),
38735
- stepsPath: path24.join(rootPath, "steps.yaml"),
38633
+ plansPath: path23.join(rootPath, "plans"),
38634
+ stepsPath: path23.join(rootPath, "steps.yaml"),
38736
38635
  displayPlansPath: `${displayRoot}/plans`,
38737
38636
  displayStepsPath: `${displayRoot}/steps.yaml`
38738
38637
  };
@@ -38743,16 +38642,16 @@ async function loadPipelineTemplates() {
38743
38642
  }
38744
38643
  const packageRoot = await findPackageRoot(fileURLToPath4(import.meta.url));
38745
38644
  const templateRoots = [
38746
- path24.join(packageRoot, "src", "templates", "pipeline"),
38747
- path24.join(packageRoot, "dist", "templates", "pipeline")
38645
+ path23.join(packageRoot, "src", "templates", "pipeline"),
38646
+ path23.join(packageRoot, "dist", "templates", "pipeline")
38748
38647
  ];
38749
38648
  for (const templateRoot of templateRoots) {
38750
38649
  if (!await pathExistsOnDisk(templateRoot)) {
38751
38650
  continue;
38752
38651
  }
38753
38652
  const [skillPlan, steps] = await Promise.all([
38754
- readFile6(path24.join(templateRoot, "SKILL_plan.md"), "utf8"),
38755
- readFile6(path24.join(templateRoot, "steps.yaml.hbs"), "utf8")
38653
+ readFile6(path23.join(templateRoot, "SKILL_plan.md"), "utf8"),
38654
+ readFile6(path23.join(templateRoot, "steps.yaml.hbs"), "utf8")
38756
38655
  ]);
38757
38656
  pipelineTemplatesCache = { skillPlan, steps };
38758
38657
  return pipelineTemplatesCache;
@@ -38771,12 +38670,12 @@ async function pathExistsOnDisk(targetPath) {
38771
38670
  }
38772
38671
  }
38773
38672
  async function findPackageRoot(entryFilePath) {
38774
- let currentPath = path24.dirname(entryFilePath);
38673
+ let currentPath = path23.dirname(entryFilePath);
38775
38674
  while (true) {
38776
- if (await pathExistsOnDisk(path24.join(currentPath, "package.json"))) {
38675
+ if (await pathExistsOnDisk(path23.join(currentPath, "package.json"))) {
38777
38676
  return currentPath;
38778
38677
  }
38779
- const parentPath = path24.dirname(currentPath);
38678
+ const parentPath = path23.dirname(currentPath);
38780
38679
  if (parentPath === currentPath) {
38781
38680
  throw new Error("Unable to locate package root for Pipeline templates.");
38782
38681
  }
@@ -39054,7 +38953,7 @@ function registerPipelineCommand(program, container) {
39054
38953
  `Would ${stepsExists ? "overwrite" : "create"}: ${pipelinePaths.displayStepsPath}`
39055
38954
  );
39056
38955
  } else {
39057
- await container.fs.mkdir(path24.dirname(pipelinePaths.stepsPath), {
38956
+ await container.fs.mkdir(path23.dirname(pipelinePaths.stepsPath), {
39058
38957
  recursive: true
39059
38958
  });
39060
38959
  await container.fs.writeFile(pipelinePaths.stepsPath, templates.steps, {
@@ -39079,7 +38978,7 @@ var init_pipeline4 = __esm({
39079
38978
  "use strict";
39080
38979
  init_src4();
39081
38980
  init_src3();
39082
- init_src12();
38981
+ init_src13();
39083
38982
  init_errors();
39084
38983
  init_shared();
39085
38984
  await init_pipeline2();
@@ -39096,7 +38995,7 @@ var init_package = __esm({
39096
38995
  "package.json"() {
39097
38996
  package_default = {
39098
38997
  name: "poe-code",
39099
- version: "3.0.99",
38998
+ version: "3.0.100",
39100
38999
  description: "CLI tool to configure Poe API for developer workflows.",
39101
39000
  type: "module",
39102
39001
  main: "./dist/index.js",
@@ -39180,7 +39079,8 @@ var init_package = __esm({
39180
39079
  devDependencies: {
39181
39080
  "@eslint/js": "^9.0.0",
39182
39081
  "@modelcontextprotocol/sdk": "^1.26.0",
39183
- "@poe-code/poe-auth": "*",
39082
+ "auth-store": "*",
39083
+ "poe-oauth": "*",
39184
39084
  "@poe-code/agent-spawn": "*",
39185
39085
  "@poe-code/config-mutations": "*",
39186
39086
  "@poe-code/design-system": "*",
@@ -39518,8 +39418,8 @@ var init_program = __esm({
39518
39418
  await init_spawn4();
39519
39419
  await init_research2();
39520
39420
  init_wrap();
39521
- init_login2();
39522
- init_logout2();
39421
+ init_login();
39422
+ init_logout();
39523
39423
  init_auth();
39524
39424
  init_install();
39525
39425
  init_unconfigure();
@@ -39622,16 +39522,16 @@ __export(bootstrap_exports, {
39622
39522
  createCliMain: () => createCliMain,
39623
39523
  isCliInvocation: () => isCliInvocation
39624
39524
  });
39625
- import * as nodeFs2 from "node:fs/promises";
39525
+ import * as nodeFs from "node:fs/promises";
39626
39526
  import * as nodeFsSync3 from "node:fs";
39627
39527
  import { realpathSync } from "node:fs";
39628
- import { homedir as homedir6 } from "node:os";
39528
+ import { homedir as homedir5 } from "node:os";
39629
39529
  import { pathToFileURL as pathToFileURL2 } from "node:url";
39630
39530
  import { join as join2 } from "node:path";
39631
39531
  import chalk13 from "chalk";
39632
39532
  function createCliMain(programFactory) {
39633
39533
  return async function runCli() {
39634
- const homeDir = homedir6();
39534
+ const homeDir = homedir5();
39635
39535
  const logDir = join2(homeDir, ".poe-code", "logs");
39636
39536
  const promptRunner = createPromptRunner();
39637
39537
  const shouldLogToStderr = process.env.POE_CODE_STDERR_LOGS === "1" || process.env.POE_CODE_STDERR_LOGS === "true";
@@ -39697,7 +39597,7 @@ var init_bootstrap = __esm({
39697
39597
  init_error_logger();
39698
39598
  init_errors();
39699
39599
  init_prompt_runner();
39700
- fsAdapter = nodeFs2;
39600
+ fsAdapter = nodeFs;
39701
39601
  }
39702
39602
  });
39703
39603
 
@@ -39812,7 +39712,7 @@ init_src5();
39812
39712
  init_src4();
39813
39713
  init_constants();
39814
39714
  init_errors();
39815
- import path17 from "node:path";
39715
+ import path16 from "node:path";
39816
39716
  import { Command } from "commander";
39817
39717
  function parseMcpSpawnConfig(input) {
39818
39718
  if (!input) {
@@ -39883,10 +39783,10 @@ function resolveWorkingDirectory(baseDir, candidate) {
39883
39783
  if (!candidate || candidate.trim().length === 0) {
39884
39784
  return void 0;
39885
39785
  }
39886
- if (path17.isAbsolute(candidate)) {
39786
+ if (path16.isAbsolute(candidate)) {
39887
39787
  return candidate;
39888
39788
  }
39889
- return path17.resolve(baseDir, candidate);
39789
+ return path16.resolve(baseDir, candidate);
39890
39790
  }
39891
39791
  function createPoeAgentProgram() {
39892
39792
  const program = new Command();