@skaile/workspaces 0.39.0 → 0.40.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/dist/{asset-feeds-W6JNAGNQ.js → asset-feeds-NOHUJ4XZ.js} +24 -6
  3. package/dist/asset-feeds-NOHUJ4XZ.js.map +1 -0
  4. package/dist/asset-manager/index.js +1 -1
  5. package/dist/{chunk-LJIE3PGF.js → chunk-23WP47VA.js} +2 -2
  6. package/dist/{chunk-LJIE3PGF.js.map → chunk-23WP47VA.js.map} +1 -1
  7. package/dist/{chunk-6LW7Q53Z.js → chunk-6BEGKO2Q.js} +3 -3
  8. package/dist/{chunk-6LW7Q53Z.js.map → chunk-6BEGKO2Q.js.map} +1 -1
  9. package/dist/{chunk-P7CIT445.js → chunk-C5UK3JK7.js} +21 -14
  10. package/dist/chunk-C5UK3JK7.js.map +1 -0
  11. package/dist/{chunk-FZL6QOM7.js → chunk-DBL3X6V4.js} +3 -3
  12. package/dist/{chunk-FZL6QOM7.js.map → chunk-DBL3X6V4.js.map} +1 -1
  13. package/dist/{chunk-CMZWYMGD.js → chunk-EAWENE2K.js} +45 -3
  14. package/dist/chunk-EAWENE2K.js.map +1 -0
  15. package/dist/{chunk-ZDKJHQY2.js → chunk-JXT46QFC.js} +2 -2
  16. package/dist/{chunk-ZDKJHQY2.js.map → chunk-JXT46QFC.js.map} +1 -1
  17. package/dist/{chunk-UAYAK7N4.js → chunk-O66LT7UI.js} +49 -3
  18. package/dist/chunk-O66LT7UI.js.map +1 -0
  19. package/dist/{chunk-W23HDR6W.js → chunk-PBHLDLVU.js} +210 -59
  20. package/dist/chunk-PBHLDLVU.js.map +1 -0
  21. package/dist/{chunk-WVWX76IB.js → chunk-USEFGACS.js} +2 -2
  22. package/dist/{chunk-WVWX76IB.js.map → chunk-USEFGACS.js.map} +1 -1
  23. package/dist/{chunk-O4PANZI2.js → chunk-XNMABEHH.js} +3 -3
  24. package/dist/{chunk-O4PANZI2.js.map → chunk-XNMABEHH.js.map} +1 -1
  25. package/dist/{chunk-6KKNROBU.js → chunk-XZNPKJXU.js} +4 -4
  26. package/dist/{chunk-6KKNROBU.js.map → chunk-XZNPKJXU.js.map} +1 -1
  27. package/dist/cli/index.js +30 -26
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/cli/src/asset-feeds.d.ts +8 -5
  30. package/dist/cli/src/asset-feeds.d.ts.map +1 -1
  31. package/dist/cli/src/commands/manage.d.ts +6 -5
  32. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  33. package/dist/cli/src/commands/source.d.ts +8 -0
  34. package/dist/cli/src/commands/source.d.ts.map +1 -1
  35. package/dist/connectors/index.js +2 -2
  36. package/dist/connectors/rclone.js +1 -1
  37. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  38. package/dist/connectors/src/mount-placeholder.d.ts +29 -4
  39. package/dist/connectors/src/mount-placeholder.d.ts.map +1 -1
  40. package/dist/connectors/src/rclone-process-manager.d.ts +9 -0
  41. package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
  42. package/dist/discovery/index.js +2 -2
  43. package/dist/{ensure-sources-AGORTKJC.js → ensure-sources-XITKRBLU.js} +5 -5
  44. package/dist/{ensure-sources-AGORTKJC.js.map → ensure-sources-XITKRBLU.js.map} +1 -1
  45. package/dist/factory-assets/connectors/deploy.js +2 -2
  46. package/dist/factory-assets/connectors/devserver.js +2 -2
  47. package/dist/factory-assets/connectors/flow/adapter.js +2 -2
  48. package/dist/factory-assets/connectors/flow/run-flow.js +3 -3
  49. package/dist/factory-assets/connectors/flow.js +2 -2
  50. package/dist/factory-assets/connectors/git.js +2 -2
  51. package/dist/factory-assets/connectors/gmail.js +2 -2
  52. package/dist/factory-assets/connectors/googledrive.js +2 -2
  53. package/dist/factory-assets/connectors/local.js +2 -2
  54. package/dist/factory-assets/connectors/mattermost.js +2 -2
  55. package/dist/factory-assets/connectors/memory.js +2 -2
  56. package/dist/factory-assets/connectors/minio.js +2 -2
  57. package/dist/factory-assets/connectors/postgres.js +2 -2
  58. package/dist/factory-assets/connectors/s3.js +2 -2
  59. package/dist/factory-assets/connectors/sharepoint.js +2 -2
  60. package/dist/factory-assets/connectors/sqlite.js +2 -2
  61. package/dist/factory-assets/connectors/static-server.js +2 -2
  62. package/dist/factory-assets/connectors/tunnel.js +2 -2
  63. package/dist/factory-assets/connectors/webdav.js +2 -2
  64. package/dist/factory-assets/connectors/xstate-store.js +2 -2
  65. package/dist/factory-assets/connectors/xstate.js +2 -2
  66. package/dist/library/index.js +3 -3
  67. package/dist/library/src/remote/remote-catalog-source.d.ts +11 -1
  68. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  69. package/dist/{open-library-WTN7QLN7.js → open-library-5KJOZHG7.js} +6 -6
  70. package/dist/{open-library-WTN7QLN7.js.map → open-library-5KJOZHG7.js.map} +1 -1
  71. package/dist/plugins/index.js +1 -1
  72. package/dist/plugins/src/catalog-source.d.ts +52 -0
  73. package/dist/plugins/src/catalog-source.d.ts.map +1 -1
  74. package/dist/plugins/src/index.d.ts +1 -1
  75. package/dist/plugins/src/index.d.ts.map +1 -1
  76. package/dist/runner/index.js +4 -4
  77. package/dist/runner/src/ai-credential-refresh.d.ts +55 -23
  78. package/dist/runner/src/ai-credential-refresh.d.ts.map +1 -1
  79. package/dist/runner/src/ai-credential-retry.d.ts +79 -0
  80. package/dist/runner/src/ai-credential-retry.d.ts.map +1 -0
  81. package/dist/runner/src/credential-rotated.d.ts +33 -0
  82. package/dist/runner/src/credential-rotated.d.ts.map +1 -0
  83. package/dist/runner/src/resource-handler.d.ts.map +1 -1
  84. package/dist/runner/src/serve-credentials.d.ts +14 -0
  85. package/dist/runner/src/serve-credentials.d.ts.map +1 -1
  86. package/dist/runner/src/serve.d.ts.map +1 -1
  87. package/dist/sdk/asset-manager.js +1 -1
  88. package/dist/sdk/index.js +4 -4
  89. package/dist/sdk/runner.js +4 -4
  90. package/dist/secrets/index.js +2 -2
  91. package/dist/tui/index.js +4 -4
  92. package/dist/workspace-plugin/index.js +1 -1
  93. package/package.json +1 -1
  94. package/dist/asset-feeds-W6JNAGNQ.js.map +0 -1
  95. package/dist/chunk-CMZWYMGD.js.map +0 -1
  96. package/dist/chunk-P7CIT445.js.map +0 -1
  97. package/dist/chunk-UAYAK7N4.js.map +0 -1
  98. package/dist/chunk-W23HDR6W.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { WorkspacePlugin } from './chunk-LJIE3PGF.js';
1
+ import { WorkspacePlugin } from './chunk-23WP47VA.js';
2
2
  import { WebSocketServerTransport } from './chunk-WQ7DE5UC.js';
3
3
  import { assembleSystemPrompt, buildCapabilitiesPromptSection } from './chunk-W3UDISS2.js';
4
4
  import { PROTOCOL_VERSION } from './chunk-TDSRLMDB.js';
@@ -6,7 +6,7 @@ import { EventNormalizer } from './chunk-5IXCNMMU.js';
6
6
  import { classifyClaudeSdkError } from './chunk-GAH4YRCI.js';
7
7
  import { createDriver } from './chunk-KM6DCR7A.js';
8
8
  import { deployCatalogEntry, undeployCatalogEntry } from './chunk-LV2HPH3C.js';
9
- import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools } from './chunk-CMZWYMGD.js';
9
+ import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools } from './chunk-EAWENE2K.js';
10
10
  import { loadConnectorDeclarations, SecretProviderChain, PreMintedSecretProvider, InMemorySecretProvider, deriveSingleMaterializedConnectorDeclaration } from './chunk-WLWHOA3S.js';
11
11
  import { renderStimulusPrompt, buildOrchestratorPrompt } from './chunk-DEYYRFQU.js';
12
12
  import { resolveSettings, resolveApiKey, providerEnvKey } from './chunk-FBIQ4QPF.js';
@@ -19,7 +19,7 @@ import { __require } from './chunk-NSBPE2FW.js';
19
19
  import pc from 'picocolors';
20
20
  import { Marked } from 'marked';
21
21
  import { markedTerminal } from 'marked-terminal';
22
- import { readdirSync, existsSync, readFileSync, unlinkSync, mkdirSync, writeFileSync, statSync, watch, chmodSync, openSync, readSync, closeSync } from 'fs';
22
+ import { readdirSync, existsSync, readFileSync, statSync, rmSync, unlinkSync, mkdirSync, writeFileSync, watch, chmodSync, openSync, readSync, closeSync } from 'fs';
23
23
  import path4, { join, resolve, relative, sep, isAbsolute, dirname, basename } from 'path';
24
24
  import { homedir } from 'os';
25
25
  import * as z5 from 'zod';
@@ -2421,7 +2421,7 @@ function isBinaryFile(filePath) {
2421
2421
  }
2422
2422
  }
2423
2423
  function handleMountResourceRequest(command, manager, emit) {
2424
- const { requestId, connectorId: mountId, operation, path: reqPath, content } = command;
2424
+ const { requestId, connectorId: mountId, operation, path: reqPath, options, content } = command;
2425
2425
  try {
2426
2426
  const entry = manager.get(mountId);
2427
2427
  const mountPath = entry.handle.mountPath;
@@ -2436,22 +2436,30 @@ function handleMountResourceRequest(command, manager, emit) {
2436
2436
  let data;
2437
2437
  switch (operation) {
2438
2438
  case "list": {
2439
- const entries = readdirSync(targetPath, { withFileTypes: true });
2440
- data = entries.filter((e) => !e.name.startsWith(".")).map((e) => {
2441
- const entryPath = reqPath ? join(reqPath, e.name) : e.name;
2442
- const result = {
2443
- name: e.name,
2444
- path: entryPath,
2445
- type: e.isDirectory() ? "directory" : "file"
2446
- };
2447
- if (!e.isDirectory()) {
2448
- try {
2449
- result.size = statSync(join(targetPath, e.name)).size;
2450
- } catch {
2439
+ const recursive = Boolean(options?.recursive);
2440
+ const collected = [];
2441
+ const walk = (absDir, relDir) => {
2442
+ for (const e of readdirSync(absDir, { withFileTypes: true })) {
2443
+ if (e.name.startsWith(".")) continue;
2444
+ const entryRel = relDir ? `${relDir}/${e.name}` : e.name;
2445
+ const isDir = e.isDirectory();
2446
+ const result = {
2447
+ name: e.name,
2448
+ path: entryRel,
2449
+ type: isDir ? "directory" : "file"
2450
+ };
2451
+ if (!isDir) {
2452
+ try {
2453
+ result.size = statSync(join(absDir, e.name)).size;
2454
+ } catch {
2455
+ }
2451
2456
  }
2457
+ collected.push(result);
2458
+ if (isDir && recursive) walk(join(absDir, e.name), entryRel);
2452
2459
  }
2453
- return result;
2454
- });
2460
+ };
2461
+ walk(targetPath, reqPath ?? "");
2462
+ data = collected;
2455
2463
  break;
2456
2464
  }
2457
2465
  case "read": {
@@ -2485,7 +2493,11 @@ function handleMountResourceRequest(command, manager, emit) {
2485
2493
  break;
2486
2494
  }
2487
2495
  case "delete": {
2488
- unlinkSync(targetPath);
2496
+ if (statSync(targetPath).isDirectory()) {
2497
+ rmSync(targetPath, { recursive: true, force: true });
2498
+ } else {
2499
+ unlinkSync(targetPath);
2500
+ }
2489
2501
  data = true;
2490
2502
  break;
2491
2503
  }
@@ -2503,9 +2515,46 @@ function handleMountResourceRequest(command, manager, emit) {
2503
2515
  });
2504
2516
  }
2505
2517
  }
2518
+ var MINT_RETRY_MAX_ATTEMPTS = 3;
2519
+ var MINT_RETRY_BASE_DELAY_MS = 2e3;
2520
+ var MINT_RETRY_MAX_DELAY_MS = 5e3;
2521
+ function isTransientMintFailure(code) {
2522
+ return code === "backend-error";
2523
+ }
2524
+ function mintRetryDelayMs(retryNumber) {
2525
+ const delay = MINT_RETRY_BASE_DELAY_MS * 2 ** Math.max(0, retryNumber - 1);
2526
+ return Math.min(delay, MINT_RETRY_MAX_DELAY_MS);
2527
+ }
2528
+ async function retryTransientMint(attempt, deps) {
2529
+ const maxAttempts = deps.maxAttempts ?? MINT_RETRY_MAX_ATTEMPTS;
2530
+ let result = await attempt();
2531
+ for (let n = 1; n < maxAttempts; n++) {
2532
+ if (result.ok || !isTransientMintFailure(result.code)) return result;
2533
+ const nextDelayMs = mintRetryDelayMs(n);
2534
+ deps.onRetry?.({ attempt: n, nextDelayMs, code: result.code });
2535
+ await deps.sleep(nextDelayMs);
2536
+ result = await attempt();
2537
+ }
2538
+ return result;
2539
+ }
2540
+ function computeRejectedFingerprint(accessToken) {
2541
+ if (!accessToken) return void 0;
2542
+ return createHash("sha256").update(accessToken).digest("hex").slice(0, 16);
2543
+ }
2544
+ function buildRefreshCredentialInput(args) {
2545
+ const base = {
2546
+ kind: "ai-credentials",
2547
+ id: args.configId,
2548
+ reason: args.reason
2549
+ };
2550
+ if (args.reason !== "retry-401") return base;
2551
+ const rejectedFingerprint = computeRejectedFingerprint(args.rejectedToken);
2552
+ return rejectedFingerprint ? { ...base, rejectedFingerprint } : base;
2553
+ }
2506
2554
 
2507
2555
  // runner/src/ai-credential-refresh.ts
2508
2556
  var PROACTIVE_AI_REFRESH_MARGIN_MS = 5 * 60 * 1e3;
2557
+ var STALE_REARM_MS = 9 * 60 * 60 * 1e3;
2509
2558
  function createAiCredentialRefreshScheduler(deps) {
2510
2559
  const now = deps.now ?? (() => Date.now());
2511
2560
  const setTimeoutImpl = deps.setTimeoutImpl ?? ((handler, ms) => {
@@ -2516,64 +2565,135 @@ function createAiCredentialRefreshScheduler(deps) {
2516
2565
  clearTimeout(handle);
2517
2566
  });
2518
2567
  const marginMs = deps.marginMs ?? PROACTIVE_AI_REFRESH_MARGIN_MS;
2568
+ const logError = deps.logError ?? deps.log;
2519
2569
  let timer = null;
2570
+ let transientRetryCount = 0;
2571
+ let lastSuccessAt = null;
2572
+ let isStatic = false;
2573
+ let inStaleGuard = false;
2520
2574
  function cancel() {
2521
2575
  if (timer !== null) {
2522
2576
  clearTimeoutImpl(timer);
2523
2577
  timer = null;
2524
2578
  }
2525
2579
  }
2580
+ function armTimer(handler, ms) {
2581
+ cancel();
2582
+ timer = setTimeoutImpl(handler, ms);
2583
+ timer.unref?.();
2584
+ }
2585
+ function isStale() {
2586
+ return lastSuccessAt !== null && now() - lastSuccessAt > STALE_REARM_MS;
2587
+ }
2526
2588
  async function fire() {
2527
2589
  timer = null;
2528
- let next;
2590
+ let outcome;
2529
2591
  try {
2530
- next = await deps.refresh();
2592
+ outcome = await deps.refresh();
2531
2593
  } catch (err) {
2532
- deps.log(
2533
- `[ai-credential-refresh] refresh threw: ${err instanceof Error ? err.message : String(err)}; reactive 401 path remains as safety net`
2594
+ logError(
2595
+ `[ai-credential-refresh] refresh threw: ${err instanceof Error ? err.message : String(err)}; treating as transient`
2596
+ );
2597
+ outcome = { status: "transient" };
2598
+ }
2599
+ if (outcome.status === "ok") {
2600
+ schedule(outcome.expiresAt);
2601
+ return;
2602
+ }
2603
+ if (outcome.status === "terminal") {
2604
+ transientRetryCount = 0;
2605
+ inStaleGuard = false;
2606
+ logError(
2607
+ "[ai-credential-refresh] proactive refresh hit a terminal failure; not re-arming (reactive 401 path remains the safety net)"
2534
2608
  );
2535
2609
  return;
2536
2610
  }
2537
- if (next === void 0) {
2538
- deps.log(
2539
- "[ai-credential-refresh] refresh returned no expiry; reactive 401 path remains as safety net"
2611
+ if (transientRetryCount < MINT_RETRY_MAX_ATTEMPTS - 1) {
2612
+ transientRetryCount += 1;
2613
+ inStaleGuard = false;
2614
+ const delayMs = mintRetryDelayMs(transientRetryCount);
2615
+ logError(
2616
+ `[ai-credential-refresh] proactive refresh transient failure; bounded retry ${transientRetryCount}/${MINT_RETRY_MAX_ATTEMPTS - 1} in ${Math.round(delayMs / 1e3)}s`
2540
2617
  );
2618
+ armTimer(() => void fire(), delayMs);
2541
2619
  return;
2542
2620
  }
2543
- schedule(next);
2621
+ transientRetryCount = 0;
2622
+ inStaleGuard = true;
2623
+ logError(
2624
+ `[ai-credential-refresh] proactive refresh failed after ${MINT_RETRY_MAX_ATTEMPTS} attempts; reactive 401 path is the fallback, re-checking in ${Math.round(STALE_REARM_MS / 36e5)}h`
2625
+ );
2626
+ armTimer(() => void fire(), STALE_REARM_MS);
2544
2627
  }
2545
2628
  function schedule(expiresAtIso) {
2546
2629
  cancel();
2630
+ inStaleGuard = false;
2547
2631
  if (!expiresAtIso) {
2632
+ isStatic = true;
2633
+ transientRetryCount = 0;
2634
+ lastSuccessAt = now();
2548
2635
  return;
2549
2636
  }
2550
2637
  const expiresAtMs = Date.parse(expiresAtIso);
2551
2638
  if (!Number.isFinite(expiresAtMs)) return;
2639
+ isStatic = false;
2640
+ transientRetryCount = 0;
2641
+ lastSuccessAt = now();
2552
2642
  const delayMs = expiresAtMs - now() - marginMs;
2553
2643
  if (delayMs <= 0) {
2554
2644
  deps.log(
2555
2645
  `[ai-credential-refresh] token within ${marginMs / 1e3}s of expiry; refreshing now`
2556
2646
  );
2557
- timer = setTimeoutImpl(() => {
2558
- void fire();
2559
- }, 0);
2647
+ armTimer(() => void fire(), 0);
2560
2648
  } else {
2561
2649
  deps.log(
2562
2650
  `[ai-credential-refresh] scheduled in ${Math.round(delayMs / 1e3)}s (expiresAt=${expiresAtIso})`
2563
2651
  );
2564
- timer = setTimeoutImpl(() => {
2565
- void fire();
2566
- }, delayMs);
2652
+ armTimer(() => void fire(), delayMs);
2567
2653
  }
2568
- timer.unref?.();
2654
+ }
2655
+ function ensureArmed() {
2656
+ if (isStatic) return;
2657
+ if (timer !== null && !inStaleGuard && !isStale()) return;
2658
+ deps.log("[ai-credential-refresh] ensureArmed: reviving idle/stale schedule");
2659
+ transientRetryCount = 0;
2660
+ inStaleGuard = false;
2661
+ armTimer(() => void fire(), 0);
2569
2662
  }
2570
2663
  return {
2571
2664
  schedule,
2665
+ ensureArmed,
2572
2666
  cancel,
2573
2667
  isPending: () => timer !== null
2574
2668
  };
2575
2669
  }
2576
2670
 
2671
+ // runner/src/credential-rotated.ts
2672
+ var AI_PROVIDER_CREDENTIAL_SUBKIND = "ai-provider-credential";
2673
+ function isCredentialRotatedSignal(msg) {
2674
+ if (!msg || typeof msg !== "object") return false;
2675
+ const m = msg;
2676
+ if (m.type !== "log_entry") return false;
2677
+ const entry = m.entry;
2678
+ if (!entry || typeof entry !== "object") return false;
2679
+ return entry.source?.subkind === AI_PROVIDER_CREDENTIAL_SUBKIND && entry.data?.credentialRotated === true;
2680
+ }
2681
+ async function handleCredentialRotatedSignal(deps) {
2682
+ deps.log("[serve] credentialRotated broadcast received; re-pulling ai-credentials");
2683
+ try {
2684
+ const result = await deps.repull();
2685
+ if (result.ok) {
2686
+ deps.log("[serve] credentialRotated: re-pulled fresh token and rewrote .credentials.json");
2687
+ } else {
2688
+ deps.logError(`[serve] credentialRotated: re-pull failed (code=${result.code})`);
2689
+ }
2690
+ } catch (err) {
2691
+ deps.logError(
2692
+ `[serve] credentialRotated: re-pull threw: ${err instanceof Error ? err.message : String(err)}`
2693
+ );
2694
+ }
2695
+ }
2696
+
2577
2697
  // runner/src/compaction/prompt.ts
2578
2698
  var DEFAULT_COMPACTION_PROMPT = `You are being asked to compact this conversation into a structured summary.
2579
2699
  This summary will replace the full conversation history when the session
@@ -3499,6 +3619,20 @@ function extractClaudeAiOauthExpiresAt(json) {
3499
3619
  }
3500
3620
  return null;
3501
3621
  }
3622
+ function readCurrentClaudeAccessToken(home) {
3623
+ const credPath = join(home, ".claude", ".credentials.json");
3624
+ if (!existsSync(credPath)) return null;
3625
+ let parsed;
3626
+ try {
3627
+ parsed = JSON.parse(readFileSync(credPath, "utf-8"));
3628
+ } catch {
3629
+ return null;
3630
+ }
3631
+ if (!parsed || typeof parsed !== "object") return null;
3632
+ const obj = parsed;
3633
+ const raw = obj.claudeAiOauth?.accessToken ?? obj.accessToken;
3634
+ return typeof raw === "string" && raw.length > 0 ? raw : null;
3635
+ }
3502
3636
 
3503
3637
  // runner/src/session-stimulus.ts
3504
3638
  var DEFAULT_COALESCE_MS = 50;
@@ -3772,6 +3906,10 @@ async function startAgentServer(opts) {
3772
3906
  });
3773
3907
  };
3774
3908
  let aiProviderConfigId;
3909
+ const sleep = (ms) => new Promise((resolve3) => {
3910
+ const t = setTimeout(resolve3, ms);
3911
+ t.unref?.();
3912
+ });
3775
3913
  async function mintAndPersistAiCredential(args) {
3776
3914
  if (!transport.connected || aiProviderConfigId === void 0) {
3777
3915
  return {
@@ -3782,22 +3920,19 @@ async function startAgentServer(opts) {
3782
3920
  }
3783
3921
  const targetConfigId = args.configId || aiProviderConfigId;
3784
3922
  try {
3785
- const result = await capabilityRegistry.invokeRemote("host.refresh_credential", {
3786
- kind: "ai-credentials",
3787
- id: targetConfigId,
3788
- reason: args.reason
3923
+ const home = process.env.HOME || homedir();
3924
+ const refreshInput = buildRefreshCredentialInput({
3925
+ configId: targetConfigId,
3926
+ reason: args.reason,
3927
+ rejectedToken: args.reason === "retry-401" ? readCurrentClaudeAccessToken(home) : null
3789
3928
  });
3929
+ const result = await capabilityRegistry.invokeRemote(
3930
+ "host.refresh_credential",
3931
+ refreshInput
3932
+ );
3790
3933
  if (!result?.ok) {
3791
3934
  return result ?? { ok: false, code: "backend-error", message: "no result from host" };
3792
3935
  }
3793
- const home = process.env.HOME ?? homedir();
3794
- if (!home) {
3795
- return {
3796
- ok: false,
3797
- code: "backend-error",
3798
- message: "HOME env var unset; cannot rewrite credentials file"
3799
- };
3800
- }
3801
3936
  await mergeAndRewriteCredentialsFile(home, result.token, result.expiresAt ?? null);
3802
3937
  aiCredentialRefreshScheduler.schedule(result.expiresAt ?? null);
3803
3938
  return result;
@@ -3809,22 +3944,27 @@ async function startAgentServer(opts) {
3809
3944
  const aiCredentialRefreshScheduler = createAiCredentialRefreshScheduler({
3810
3945
  refresh: async () => {
3811
3946
  const result = await mintAndPersistAiCredential({ reason: "refresh" });
3812
- if (!result.ok) {
3813
- log(
3814
- `[serve] proactive AI refresh failed (code=${result.code}); leaving reactive path as fallback`
3815
- );
3816
- return void 0;
3947
+ if (result.ok) {
3948
+ return { status: "ok", expiresAt: result.expiresAt ?? null };
3817
3949
  }
3818
- return result.expiresAt ?? null;
3950
+ return isTransientMintFailure(result.code) ? { status: "transient" } : { status: "terminal" };
3819
3951
  },
3820
- log
3952
+ log,
3953
+ // Scheduler/refresh failures must be visible in `skaile session logs` and
3954
+ // the debug panel, so route them through the error-level structured logger.
3955
+ logError: (line) => serverLog.error(line)
3821
3956
  });
3822
3957
  const onAuthError = async (args) => {
3823
3958
  log("[serve] auth error: invoking host.refresh_credential capability");
3824
- const result = await mintAndPersistAiCredential({
3825
- configId: args.configId,
3826
- reason: "retry-401"
3827
- });
3959
+ const result = await retryTransientMint(
3960
+ () => mintAndPersistAiCredential({ configId: args.configId, reason: "retry-401" }),
3961
+ {
3962
+ sleep,
3963
+ onRetry: ({ attempt, nextDelayMs, code }) => serverLog.error(
3964
+ `[serve] auth error: transient mint failure (code=${code}); retry ${attempt} in ${Math.round(nextDelayMs / 1e3)}s`
3965
+ )
3966
+ }
3967
+ );
3828
3968
  if (!result.ok) {
3829
3969
  log(`[serve] auth error: mint failed (code=${result.code}); surfacing`);
3830
3970
  } else {
@@ -4711,6 +4851,9 @@ async function startAgentServer(opts) {
4711
4851
  log(
4712
4852
  `[serve] configure cfg keys=${Object.keys(cfg).join(",")} sharedState=${cfg.sharedState ? cfg.sharedState.length : "undefined"} resourceManager=${resourceManager ? "set" : "null"}`
4713
4853
  );
4854
+ if (aiProviderConfigId) {
4855
+ aiCredentialRefreshScheduler.ensureArmed();
4856
+ }
4714
4857
  let pendingResumeSessionId;
4715
4858
  const cfgResumeSessionId = cfg.resumeSessionId;
4716
4859
  const cfgExpectedSig = cfg.expectedCapabilitySignature;
@@ -5072,6 +5215,14 @@ async function startAgentServer(opts) {
5072
5215
  }
5073
5216
  async function handleCommand(cmd) {
5074
5217
  const inbound = cmd;
5218
+ if (isCredentialRotatedSignal(cmd)) {
5219
+ await handleCredentialRotatedSignal({
5220
+ repull: () => mintAndPersistAiCredential({ reason: "refresh" }),
5221
+ log,
5222
+ logError: (line) => serverLog.error(line)
5223
+ });
5224
+ return;
5225
+ }
5075
5226
  if (inbound.type === "capability_invoked") {
5076
5227
  await dispatchRunnerCapabilityInvocation(
5077
5228
  { callId: inbound.callId ?? "", name: inbound.name ?? "", input: inbound.input },
@@ -5352,5 +5503,5 @@ function touchSession(state) {
5352
5503
  }
5353
5504
 
5354
5505
  export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, builtinCapabilities, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, createAgentSession, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, installPreInitRingSink, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveMixin, runAgentChat, saveSession, setCurrentSession, startAgentServer, stripStaleHtmlTail, touchSession, writeClaudeCodeCredentialsFile };
5355
- //# sourceMappingURL=chunk-W23HDR6W.js.map
5356
- //# sourceMappingURL=chunk-W23HDR6W.js.map
5506
+ //# sourceMappingURL=chunk-PBHLDLVU.js.map
5507
+ //# sourceMappingURL=chunk-PBHLDLVU.js.map