@tekmidian/pai 0.39.0 → 0.39.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.
@@ -162,7 +162,8 @@ function defaultWorkersConfig() {
162
162
  ...DEFAULT_ROUTING,
163
163
  order: []
164
164
  },
165
- tree: { ...DEFAULT_TREE }
165
+ tree: { ...DEFAULT_TREE },
166
+ fallback: null
166
167
  };
167
168
  }
168
169
  var WorkersConfigError = class extends Error {};
@@ -350,6 +351,29 @@ function parseWorkersConfig(raw) {
350
351
  }
351
352
  const active = w.active === void 0 || w.active === null ? null : str(w.active);
352
353
  if (active !== null && active !== "auto" && !(active in providers)) {}
354
+ let fallback = null;
355
+ if (w.fallback !== void 0 && w.fallback !== null) {
356
+ if (typeof w.fallback !== "object" || Array.isArray(w.fallback)) bad(".fallback", "must be an object (written by `pai worker fallback on`)");
357
+ const f = w.fallback;
358
+ const provider = str(f.provider);
359
+ if (!provider) bad(".fallback.provider", "is required");
360
+ const savedRaw = f.saved;
361
+ if (typeof savedRaw !== "object" || savedRaw === null || Array.isArray(savedRaw)) bad(".fallback.saved", "must be an object");
362
+ const s = savedRaw;
363
+ if (typeof s.env !== "object" || s.env === null || Array.isArray(s.env)) bad(".fallback.saved.env", "must be an object of env key → previous value or null");
364
+ const env = {};
365
+ for (const [k, v] of Object.entries(s.env)) env[k] = v === null || typeof v === "string" ? v : null;
366
+ if (s.model !== null && s.model !== void 0 && typeof s.model !== "string") bad(".fallback.saved.model", "must be a string or null");
367
+ fallback = {
368
+ provider,
369
+ saved: {
370
+ env,
371
+ model: typeof s.model === "string" ? s.model : null,
372
+ envExisted: s.envExisted === true
373
+ },
374
+ on: str(f.on) || (/* @__PURE__ */ new Date(0)).toISOString()
375
+ };
376
+ }
353
377
  return {
354
378
  enabled: w.enabled === void 0 ? d.enabled : w.enabled === true,
355
379
  active,
@@ -359,25 +383,31 @@ function parseWorkersConfig(raw) {
359
383
  pane,
360
384
  logDir: str(w.logDir) || d.logDir,
361
385
  routing,
362
- tree
386
+ tree,
387
+ fallback
363
388
  };
364
389
  }
365
390
  /**
366
391
  * Read the whole config file and return (raw, workers) — the raw record so
367
392
  * callers can rewrite it preserving every other section, the parsed+validated
368
393
  * workers section. Unreadable config throws (readJsonStrict), missing is fine.
394
+ * `path` overrides the config location (tests, CLAUDE_SETTINGS_PATH-style
395
+ * dry runs); default ~/.config/pai/config.json.
369
396
  */
370
- function readWorkersSection() {
371
- const raw = readJsonStrict(CONFIG_FILE, "~/.config/pai/config.json");
397
+ function readWorkersSection(path = CONFIG_FILE) {
398
+ const raw = readJsonStrict(path, "~/.config/pai/config.json");
372
399
  return {
373
400
  raw,
374
401
  workers: parseWorkersConfig(raw.workers)
375
402
  };
376
403
  }
377
404
  /** Write the workers section back into the config file, atomically. */
378
- function writeWorkersSection(raw, workers) {
379
- raw.workers = workers;
380
- writeJsonAtomic(CONFIG_FILE, raw, { label: "~/.config/pai/config.json" });
405
+ function writeWorkersSection(raw, workers, path = CONFIG_FILE) {
406
+ raw.workers = workers.fallback ? workers : {
407
+ ...workers,
408
+ fallback: void 0
409
+ };
410
+ writeJsonAtomic(path, raw, { label: "~/.config/pai/config.json" });
381
411
  }
382
412
  /** Expand a leading ~ (config values are written with `~` to stay portable). */
383
413
  function expandHome(p) {
@@ -2500,7 +2530,7 @@ async function runWorker(opts) {
2500
2530
  const logDir = workersLogDir(config);
2501
2531
  mkdirSync(logDir, { recursive: true });
2502
2532
  if (opts.className === "plan" && !opts._planner) {
2503
- const { runPlanner } = await import("./planner-BDI7bE9B.mjs");
2533
+ const { runPlanner } = await import("./planner-DGV8VFib.mjs");
2504
2534
  return runPlanner(opts);
2505
2535
  }
2506
2536
  const parent = launchParent(opts.parent);
@@ -3321,5 +3351,5 @@ async function runChain(opts, deps = {}) {
3321
3351
  }
3322
3352
 
3323
3353
  //#endregion
3324
- export { contextPercent as A, workersLogDir as B, quotaSkipThreshold as C, workerInScope as D, sessionTag as E, ledgerSummary as F, keysDir as G, PROVIDER_TAGS as H, parseRunnerArgs as I, readWorkersSection as J, parseWorkersConfig as K, shortText as L, loadStatuses as M, newWorkerId as N, ageOf as O, appendLedger as P, eventsPath as R, probeQuota as S, resolveSession as T, WorkersConfigError as U, DEFAULT_LOG_DIR as V, expandHome as W, readJsonStrict as X, writeWorkersSection as Y, writeJsonAtomic as Z, workerDepth as _, testProvider as a, openPaneForWorker as b, stopProxy as c, renderReport as d, discardWorker as f, sayToWorker as g, readInbox as h, runWorker as i, loadStatus as j, alive as k, describeMcp as l, handoffFromInside as m, swapPromptArg as n, DEFAULT_PROXY_PORT as o, mergeWorker as p, providerCostTier as q, printResult as r, ensureProxyRunning as s, runChain as t, parseWorkerReport as u, checkPaneForWorker as v, currentTabKey as w, clearCooldown as x, openFollowPane as y, ledgerPath as z };
3325
- //# sourceMappingURL=chain-CTtHligI.mjs.map
3354
+ export { writeJsonAtomic as $, alive as A, ledgerPath as B, quotaSkipThreshold as C, sessionTag as D, resolveSession as E, appendLedger as F, expandHome as G, DEFAULT_LOG_DIR as H, ledgerSummary as I, providerCostTier as J, keysDir as K, parseRunnerArgs as L, loadStatus as M, loadStatuses as N, workerInScope as O, newWorkerId as P, readJsonStrict as Q, shortText as R, probeQuota as S, currentTabKey as T, PROVIDER_TAGS as U, workersLogDir as V, WorkersConfigError as W, readWorkersSection as X, providerKeyPath as Y, writeWorkersSection as Z, workerDepth as _, testProvider as a, openPaneForWorker as b, stopProxy as c, renderReport as d, discardWorker as f, sayToWorker as g, readInbox as h, runWorker as i, contextPercent as j, ageOf as k, describeMcp as l, handoffFromInside as m, swapPromptArg as n, DEFAULT_PROXY_PORT as o, mergeWorker as p, parseWorkersConfig as q, printResult as r, ensureProxyRunning as s, runChain as t, parseWorkerReport as u, checkPaneForWorker as v, resolveTarget as w, clearCooldown as x, openFollowPane as y, eventsPath as z };
3355
+ //# sourceMappingURL=chain-CqlgL7uH.mjs.map