@tekmidian/pai 0.66.48 → 0.66.49

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 (76) hide show
  1. package/dist/auto-route-CMARQbQ4.mjs +8 -0
  2. package/dist/{auto-route-DrncbMaz.mjs → auto-route-Dpm6nZ6X.mjs} +2 -2
  3. package/dist/{auto-route-DrncbMaz.mjs.map → auto-route-Dpm6nZ6X.mjs.map} +1 -1
  4. package/dist/{chain-Bba4Y8A8.mjs → chain-xSc3-u0X.mjs} +5 -5
  5. package/dist/{chain-Bba4Y8A8.mjs.map → chain-xSc3-u0X.mjs.map} +1 -1
  6. package/dist/cli/index.mjs +14 -14
  7. package/dist/cli/program.mjs +14 -14
  8. package/dist/{config-2pR0RqHM.mjs → config-CYjjGSWq.mjs} +41 -4
  9. package/dist/config-CYjjGSWq.mjs.map +1 -0
  10. package/dist/config-IuOG1W92.mjs +4 -0
  11. package/dist/daemon/index.mjs +10 -10
  12. package/dist/{daemon-C25MKGD8.mjs → daemon-BIG7XcqE.mjs} +10 -10
  13. package/dist/{daemon-C6K3kikA.mjs → daemon-CiSmbylJ.mjs} +7 -7
  14. package/dist/{daemon-C6K3kikA.mjs.map → daemon-CiSmbylJ.mjs.map} +1 -1
  15. package/dist/daemon-mcp/index.mjs +8 -8
  16. package/dist/{fallback-DyhAZAOe.mjs → fallback-BgAukP8r.mjs} +6 -5
  17. package/dist/fallback-BgAukP8r.mjs.map +1 -0
  18. package/dist/hooks/block-sleep-poll.mjs.map +2 -2
  19. package/dist/hooks/load-project-context.mjs +26 -2
  20. package/dist/hooks/load-project-context.mjs.map +2 -2
  21. package/dist/hooks/route-agents-to-worker.mjs +26 -2
  22. package/dist/hooks/route-agents-to-worker.mjs.map +2 -2
  23. package/dist/hooks/security-validator.mjs +26 -2
  24. package/dist/hooks/security-validator.mjs.map +2 -2
  25. package/dist/hooks/worker-guard.mjs +26 -2
  26. package/dist/hooks/worker-guard.mjs.map +2 -2
  27. package/dist/hooks/worker-pool-host.mjs +242 -14
  28. package/dist/hooks/worker-pool-host.mjs.map +4 -4
  29. package/dist/hooks/worker-proxy.mjs +26 -2
  30. package/dist/hooks/worker-proxy.mjs.map +2 -2
  31. package/dist/hooks/worker-status-line.mjs +26 -2
  32. package/dist/hooks/worker-status-line.mjs.map +2 -2
  33. package/dist/hooks/worker-supervision.mjs +26 -2
  34. package/dist/hooks/worker-supervision.mjs.map +2 -2
  35. package/dist/index.mjs +4 -4
  36. package/dist/{local-EmOjw5jq.mjs → local-Bt-7L0oB.mjs} +3 -3
  37. package/dist/{local-EmOjw5jq.mjs.map → local-Bt-7L0oB.mjs.map} +1 -1
  38. package/dist/local-oqPQEmhb.mjs +7 -0
  39. package/dist/{local-tiers-BIINbhkY.mjs → local-tiers-C0QSQcP1.mjs} +2 -2
  40. package/dist/{local-tiers-8fmjiySw.mjs → local-tiers-_ZOTbjeP.mjs} +2 -2
  41. package/dist/{local-tiers-8fmjiySw.mjs.map → local-tiers-_ZOTbjeP.mjs.map} +1 -1
  42. package/dist/{main-resolver-DBXvnYKp.mjs → main-resolver-BwjexuSA.mjs} +3 -3
  43. package/dist/{main-resolver-B10-lsU0.mjs → main-resolver-CVo0ab7j.mjs} +3 -3
  44. package/dist/{main-resolver-B10-lsU0.mjs.map → main-resolver-CVo0ab7j.mjs.map} +1 -1
  45. package/dist/{pai-marker-CDwQOpQ8.mjs → pai-marker-CJ6WMt05.mjs} +4 -4
  46. package/dist/{pai-marker-CDwQOpQ8.mjs.map → pai-marker-CJ6WMt05.mjs.map} +1 -1
  47. package/dist/{planner-dO-3PLjD.mjs → planner-ZKXZf9JS.mjs} +8 -8
  48. package/dist/{planner-dO-3PLjD.mjs.map → planner-ZKXZf9JS.mjs.map} +1 -1
  49. package/dist/{pool-DLhqOY3P.mjs → pool-CgsnP3La.mjs} +3 -3
  50. package/dist/{pool-DLhqOY3P.mjs.map → pool-CgsnP3La.mjs.map} +1 -1
  51. package/dist/{pool-cli-DerrWWpP.mjs → pool-cli-kGGuZCzJ.mjs} +4 -4
  52. package/dist/{pool-cli-DerrWWpP.mjs.map → pool-cli-kGGuZCzJ.mjs.map} +1 -1
  53. package/dist/{program-B7gVKc-u.mjs → program-DgcwJN6Z.mjs} +25 -463
  54. package/dist/program-DgcwJN6Z.mjs.map +1 -0
  55. package/dist/{run-a_JzcVwv.mjs → run-CsrBbtj_.mjs} +686 -21
  56. package/dist/run-CsrBbtj_.mjs.map +1 -0
  57. package/dist/{run-env-DyFZ8C1s.mjs → run-env-Cyw2iwBh.mjs} +15 -5
  58. package/dist/{run-env-DyFZ8C1s.mjs.map → run-env-Cyw2iwBh.mjs.map} +1 -1
  59. package/dist/{status-C3fBJKU_.mjs → status-B0br9zV0.mjs} +2 -2
  60. package/dist/status-B0br9zV0.mjs.map +1 -0
  61. package/dist/{supervisor-B_2JKYxe.mjs → supervisor-BZA0KICt.mjs} +7 -7
  62. package/dist/{supervisor-B_2JKYxe.mjs.map → supervisor-BZA0KICt.mjs.map} +1 -1
  63. package/dist/workers-config-BifEz8ns.mjs +4 -0
  64. package/dist/{worktree-lnmAOFQv.mjs → worktree-B6d-1uIn.mjs} +2 -2
  65. package/dist/{worktree-lnmAOFQv.mjs.map → worktree-B6d-1uIn.mjs.map} +1 -1
  66. package/docs/worker.md +22 -0
  67. package/package.json +1 -1
  68. package/dist/auto-route-DYuVfXwc.mjs +0 -8
  69. package/dist/config-2pR0RqHM.mjs.map +0 -1
  70. package/dist/config-CQWpEdXb.mjs +0 -4
  71. package/dist/fallback-DyhAZAOe.mjs.map +0 -1
  72. package/dist/local-B5SekWOC.mjs +0 -7
  73. package/dist/program-B7gVKc-u.mjs.map +0 -1
  74. package/dist/run-a_JzcVwv.mjs.map +0 -1
  75. package/dist/status-C3fBJKU_.mjs.map +0 -1
  76. package/dist/workers-config-nXSiW07z.mjs +0 -4
@@ -2,27 +2,27 @@ import { a as fmtDate, c as ok$1, d as scaffoldProjectDirs, f as shortenPath, g
2
2
  import { a as slugify$1, i as parseSessionFilename } from "./migrate-CYccXTAA.mjs";
3
3
  import { S as UNROUTED, b as writeJsonAtomic, c as loadConfig, d as paiConfigYamlFilePath, f as readMainConfigRaw, g as resolvedMainConfigPath, h as migrateMainConfigToYaml, l as migrateConfigFile, m as MainConfigError, n as CONFIG_FILE$2, p as writeMainConfigRaw, s as expandHome, t as CONFIG_DIR, u as paiConfigFilePath, x as OWNER_LABEL_PREFIX, y as readJsonStrict } from "./config-DSdCEcHS.mjs";
4
4
  import { a as schedulerLogPath, c as migratePaiFile, d as resolvePaiFile, i as paiSocketPath, l as paiHomeDir, n as daemonLogPath, o as PaiFileMigrationError, s as migratePaiDir, u as paiHomePath } from "./runtime-paths-DkZoxofH.mjs";
5
- import { C as isModelCapability, F as readWorkersSection, G as needsWorkersYamlRelocation, H as initWorkersYaml, J as relocateWorkersYaml, K as parseWorkersYamlDocument, R as resolveProviderKey, S as hasProviderKey, U as inlineWorkersYamlKeys, W as migrateWorkersToYaml, X as workersYamlLegacyNotice, Z as workersYamlPath, b as expandHome$1, et as DEFAULT_CONTEXT_WINDOW, g as WorkersConfigError, m as PROVIDER_TAGS, nt as contextWindowFromModelId, rt as stripModelVariant, t as ANTHROPIC_NATIVE, x as getProviderOrNative } from "./config-2pR0RqHM.mjs";
6
- import { B as parseRunnerArgs, C as formatStale, E as loadStatusConfig, G as ledgerPath, U as ensureNoMcpConfig, W as eventsPath, Y as workersLogDir, b as waitForTerminalStatus, d as isLive, f as loadStatus, g as ownsPid, j as writeSectionToForge, k as upsertSection, p as loadStatuses, t as UNLABELED, u as isChatPane, v as saveStatus, y as setWorkerLabel, z as longInlinePromptHint } from "./status-C3fBJKU_.mjs";
7
- import { _ as formatPending, b as appendLedger, i as gcWorktrees, l as mergeWorker, p as verifyWorker, r as discardWorker, v as pendingGate, y as pendingResults } from "./worktree-lnmAOFQv.mjs";
8
- import { a as unregistrableReason, n as ensurePaiMarker, o as worktreeReason } from "./pai-marker-CDwQOpQ8.mjs";
5
+ import { $ as workersYamlLegacyNotice, C as expandHome$1, E as isModelCapability, G as initWorkersYaml, J as needsWorkersYamlRelocation, K as inlineWorkersYamlKeys, R as readWorkersSection, T as hasProviderKey, Y as parseWorkersYamlDocument, Z as relocateWorkersYaml, _ as PROVIDER_TAGS, at as contextWindowFromModelId, et as workersYamlPath, ot as stripModelVariant, q as migrateWorkersToYaml, rt as DEFAULT_CONTEXT_WINDOW, t as ANTHROPIC_NATIVE, w as getProviderOrNative, y as WorkersConfigError } from "./config-CYjjGSWq.mjs";
6
+ import { B as parseRunnerArgs, C as formatStale, E as loadStatusConfig, G as ledgerPath, U as ensureNoMcpConfig, W as eventsPath, Y as workersLogDir, b as waitForTerminalStatus, d as isLive, f as loadStatus, g as ownsPid, j as writeSectionToForge, k as upsertSection, p as loadStatuses, t as UNLABELED, u as isChatPane, v as saveStatus, y as setWorkerLabel, z as longInlinePromptHint } from "./status-B0br9zV0.mjs";
7
+ import { _ as formatPending, b as appendLedger, i as gcWorktrees, l as mergeWorker, p as verifyWorker, r as discardWorker, v as pendingGate, y as pendingResults } from "./worktree-B6d-1uIn.mjs";
8
+ import { a as unregistrableReason, n as ensurePaiMarker, o as worktreeReason } from "./pai-marker-CJ6WMt05.mjs";
9
9
  import { t as STOP_WORDS } from "./stop-words-Hfu8u22w.mjs";
10
10
  import { t as applyRecencyBoost } from "./search-qLyvfhwY.mjs";
11
11
  import { c as resolveFromModule, i as retryTransient, n as embedChunksWithBackend, r as indexProjectWithBackend, s as packageRoot } from "./postgres-P567vfbi.mjs";
12
12
  import { a as getStorageBackend, c as MergeError, f as humanDuration, i as getRegistryBackend, l as federationDbPath, o as oldRegistryPath, r as createStorageBackend, s as registryDbPath, u as oldFederationPath } from "./factory-DRAEDNKV.mjs";
13
13
  import { c as detectBackends, d as OLLAMA_DEFAULT_MODEL, f as OLLAMA_DEFAULT_URL, i as measureThroughput, o as BACKEND_IDS, p as OLLAMA_ID, s as createBackend, u as provisionOllama } from "./embedding-gate-BwkbwfIL.mjs";
14
- import { Bt as findMovedProjects, D as migrateWorkQueue, Et as migrateIdentityFile, Ft as resolveHome, Gt as formatDetectionJson, Ht as transcriptFiles, It as saveScanConfig, Lt as upsertProject, M as migrateSummaryCooldowns, Mt as loadScanConfig, Nt as migrateScanConfig, Rt as upsertSession, Ut as detectProject, Vt as scanTranscriptFolders, Wt as formatDetection, _ as resolveDaemonPid, _t as findNotesDir$1, a as routerRunningPid, d as loadSessionKeepaliveState, dt as extractAndStoreTriples, gt as findLatestNote, h as totalUsageTokens, ht as applyContinue, jt as cmdScan, kt as reexecBackground, l as readContextHandoverCache, m as parseSessionUsage, mt as appendCheckpointToNote, n as ROUTER_PID_FILE, p as sessionKeepaliveLedgerSummary, s as spawnRouter, t as ROUTER_LOG_FILE, vt as readBodyFile, zt as claudeProjectsDir } from "./supervisor-B_2JKYxe.mjs";
15
- import { a as poolMetricsPath, d as readPoolMetrics, m as expandMcpNames, p as describeMcp, t as poolCarry } from "./pool-DLhqOY3P.mjs";
16
- import { $ as ensureProxyRunning, A as routeRun, B as detectCurrentProviderName, D as onBattery, E as findLocal, H as maskLaunchEnv, I as requestKill, J as parseSince, K as errorsTable, L as buildLaunchPlan, M as clickrControlsArgv, N as markControlsHeld, O as parseDuration, P as callerDescription, Q as DEFAULT_PROXY_PORT, R as buildLaunchRows, S as sayToWorker, T as clearPolicy, V as launchableProviderNames, Y as readToolErrors, at as pinNotices, b as handoffFromInside, ct as checkPaneForWorker, d as realDeps, et as stopProxy, f as statusMarker, ft as openFollowPane, ht as resolveHostSession, i as usageContextTokens, j as writePolicy, k as readPolicy, l as parseWorkerReport, lt as closeEndedPanes, n as runWorker, ot as projectLaunchConfig, p as waitOn, pt as openPaneForWorker, q as groupToolErrors, r as testProvider, st as assertPaneNotDisabled, w as POLICY_MODES, z as detectCurrentModel } from "./run-a_JzcVwv.mjs";
17
- import { A as useProvider, B as projectChecks, C as setClass, D as unsetCapabilityPreference, E as setWorkersEnabled, F as setConfigValueOp, I as unsetConfigValueOp, L as formatCheck, M as formatConfigGetOutput, N as getConfigValueOp, O as unsetClass, P as listConfigOp, R as initProject, S as setCapabilityPreference, T as setProviderModel, _ as describeModels, a as followWorkers, b as removeProvider, c as statusLineOutput, d as issueClaim, f as issueClaims, g as describeCapabilities, h as classTargetText, i as fallbackStatusText, j as MainConfigOpsError, k as updateProvider, l as readSpecPrompt, m as addProvider, n as fallbackOn, o as psOutput, p as issueStale, r as fallbackStatus, s as replayOutput, t as fallbackOff, u as resolveSpecPath, v as describeProviders, w as setProviderEnabled, x as resolveProviderName, y as modelPrefsText, z as isGitProject } from "./fallback-DyhAZAOe.mjs";
14
+ import { Bt as findMovedProjects, D as migrateWorkQueue, Et as migrateIdentityFile, Ft as resolveHome, Gt as formatDetectionJson, Ht as transcriptFiles, It as saveScanConfig, Lt as upsertProject, M as migrateSummaryCooldowns, Mt as loadScanConfig, Nt as migrateScanConfig, Rt as upsertSession, Ut as detectProject, Vt as scanTranscriptFolders, Wt as formatDetection, _ as resolveDaemonPid, _t as findNotesDir$1, a as routerRunningPid, d as loadSessionKeepaliveState, dt as extractAndStoreTriples, gt as findLatestNote, h as totalUsageTokens, ht as applyContinue, jt as cmdScan, kt as reexecBackground, l as readContextHandoverCache, m as parseSessionUsage, mt as appendCheckpointToNote, n as ROUTER_PID_FILE, p as sessionKeepaliveLedgerSummary, s as spawnRouter, t as ROUTER_LOG_FILE, vt as readBodyFile, zt as claudeProjectsDir } from "./supervisor-BZA0KICt.mjs";
15
+ import { a as poolMetricsPath, d as readPoolMetrics, m as expandMcpNames, p as describeMcp, t as poolCarry } from "./pool-CgsnP3La.mjs";
16
+ import { $ as ensureProxyRunning, A as routeRun, B as detectCurrentProviderName, D as onBattery, E as findLocal, H as maskLaunchEnv, I as requestKill, J as parseSince, K as errorsTable, L as buildLaunchPlan, M as clickrControlsArgv, N as markControlsHeld, O as parseDuration, P as callerDescription, Q as DEFAULT_PROXY_PORT, R as buildLaunchRows, S as sayToWorker, T as clearPolicy, V as launchableProviderNames, Y as readToolErrors, at as LimitsCache, b as handoffFromInside, ct as assertPaneNotDisabled, d as realDeps, et as stopProxy, f as statusMarker, gt as resolveHostSession, i as usageContextTokens, j as writePolicy, k as readPolicy, l as parseWorkerReport, lt as checkPaneForWorker, mt as openPaneForWorker, n as runWorker, ot as pinNotices, p as waitOn, pt as openFollowPane, q as groupToolErrors, r as testProvider, st as projectLaunchConfig, ut as closeEndedPanes, w as POLICY_MODES, z as detectCurrentModel } from "./run-CsrBbtj_.mjs";
17
+ import { A as useProvider, B as projectChecks, C as setClass, D as unsetCapabilityPreference, E as setWorkersEnabled, F as setConfigValueOp, I as unsetConfigValueOp, L as formatCheck, M as formatConfigGetOutput, N as getConfigValueOp, O as unsetClass, P as listConfigOp, R as initProject, S as setCapabilityPreference, T as setProviderModel, _ as describeModels, a as followWorkers, b as removeProvider, c as statusLineOutput, d as issueClaim, f as issueClaims, g as describeCapabilities, h as classTargetText, i as fallbackStatusText, j as MainConfigOpsError, k as updateProvider, l as readSpecPrompt, m as addProvider, n as fallbackOn, o as psOutput, p as issueStale, r as fallbackStatus, s as replayOutput, t as fallbackOff, u as resolveSpecPath, v as describeProviders, w as setProviderEnabled, x as resolveProviderName, y as modelPrefsText, z as isGitProject } from "./fallback-BgAukP8r.mjs";
18
18
  import { n as PaiClient } from "./ipc-client-vK3fmbwc.mjs";
19
- import { _ as resolveSessionByNameOrId, a as buildDeduped, c as hasConversation, d as providerResumePlan, f as restoreTopLevel, g as migrateSessionScanCache, h as fmtAge, l as launchInDir, m as printExitDir, o as normalizeName$2, p as resumeArgvText, s as renderDedupedSessions, t as cmdMain, u as launchPrompt, v as scanCacheFilePath, y as scanSessions } from "./main-resolver-B10-lsU0.mjs";
19
+ import { _ as resolveSessionByNameOrId, a as buildDeduped, c as hasConversation, d as providerResumePlan, f as restoreTopLevel, g as migrateSessionScanCache, h as fmtAge, l as launchInDir, m as printExitDir, o as normalizeName$2, p as resumeArgvText, s as renderDedupedSessions, t as cmdMain, u as launchPrompt, v as scanCacheFilePath, y as scanSessions } from "./main-resolver-CVo0ab7j.mjs";
20
20
  import { n as queriesDirPath, t as migrateQueriesDir } from "./query-feedback-C_sRUNju.mjs";
21
- import { a as routerHandler, c as aggregateBySession, d as formatStats, f as parseSince$1, i as ROUTER_PORT, l as appendUsage, m as splitBySessionKind, o as USAGE_LOG_FILE, p as readUsage, s as aggregate$1, u as formatSessionStats } from "./run-env-DyFZ8C1s.mjs";
21
+ import { a as routerHandler, c as aggregateBySession, d as formatStats, f as parseSince$1, i as ROUTER_PORT, l as appendUsage, m as splitBySessionKind, o as USAGE_LOG_FILE, p as readUsage, s as aggregate$1, u as formatSessionStats } from "./run-env-Cyw2iwBh.mjs";
22
22
  import { a as revealItermSession, n as callAiBroker, o as sendToSession, r as fetchLiveSessions } from "./aibroker-client-Dome-XV2.mjs";
23
- import { t as runChain } from "./chain-Bba4Y8A8.mjs";
24
- import { a as fmtRss, f as resolveModelPath } from "./local-tiers-8fmjiySw.mjs";
25
- import { r as registerWorkerLocalCommand } from "./local-EmOjw5jq.mjs";
23
+ import { t as runChain } from "./chain-xSc3-u0X.mjs";
24
+ import { a as fmtRss, f as resolveModelPath } from "./local-tiers-_ZOTbjeP.mjs";
25
+ import { r as registerWorkerLocalCommand } from "./local-Bt-7L0oB.mjs";
26
26
  import { appendFileSync, chmodSync, closeSync, copyFileSync, cpSync, createReadStream, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, readlinkSync, realpathSync, renameSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
27
27
  import { homedir, loadavg, networkInterfaces, platform, tmpdir, userInfo } from "node:os";
28
28
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
@@ -33,10 +33,8 @@ import { createHash, randomUUID } from "node:crypto";
33
33
  import { Command, InvalidArgumentError } from "commander";
34
34
  import { fileURLToPath } from "node:url";
35
35
  import pg from "pg";
36
- import net from "node:net";
37
36
  import BetterSqlite3 from "better-sqlite3";
38
37
  import http from "node:http";
39
- import https from "node:https";
40
38
  import { createInterface } from "node:readline";
41
39
  import { createConnection } from "net";
42
40
  import { getEncoding } from "js-tiktoken";
@@ -2022,7 +2020,7 @@ async function cmdUnregister(slug, opts = {}) {
2022
2020
  //#region src/cli/commands/project/projects-index.ts
2023
2021
  function registerProjectsCommands(projectsCmd) {
2024
2022
  projectsCmd.command("list", { isDefault: true }).description("Show the unified deduped listing (same as `pai`).\nUse --all to include cold / zero-session / archived projects.").option("--all", "Show all entries including cold / zero-session / archived projects").option("-n, --n <count>", "Max rows to show", "20").action(async (opts) => {
2025
- const { cmdMain } = await import("./main-resolver-DBXvnYKp.mjs");
2023
+ const { cmdMain } = await import("./main-resolver-BwjexuSA.mjs");
2026
2024
  await cmdMain(void 0, void 0, opts);
2027
2025
  });
2028
2026
  projectsCmd.command("list-raw").description("Raw registry listing with slug, path, status, last_active columns").option("--all", "Include archived projects (default: active only)").option("--status <status>", "Filter by status: active | archived").option("--tag <tag>", "Filter by tag").option("--type <type>", "Filter by type").action(async (opts) => {
@@ -7232,7 +7230,7 @@ function cmdLogs(opts) {
7232
7230
  }
7233
7231
  function registerDaemonCommands(daemonCmd) {
7234
7232
  daemonCmd.command("serve").description("Start the PAI daemon in the foreground").action(async () => {
7235
- const { serve } = await import("./daemon-C25MKGD8.mjs");
7233
+ const { serve } = await import("./daemon-BIG7XcqE.mjs");
7236
7234
  const { loadConfig: lc, ensureConfigDir } = await import("./config-DhgOr-uB.mjs");
7237
7235
  ensureConfigDir();
7238
7236
  await serve(lc());
@@ -17406,7 +17404,7 @@ async function cmdActive(opts) {
17406
17404
  ], rows));
17407
17405
  }
17408
17406
  async function cmdAutoRoute(opts) {
17409
- const { autoRoute, formatAutoRouteJson } = await import("./auto-route-DYuVfXwc.mjs");
17407
+ const { autoRoute, formatAutoRouteJson } = await import("./auto-route-CMARQbQ4.mjs");
17410
17408
  const { getRegistryBackend, createStorageBackend } = await import("./factory-qDkL0z7K.mjs");
17411
17409
  const { loadConfig } = await import("./config-DhgOr-uB.mjs");
17412
17410
  const config = loadConfig();
@@ -19450,7 +19448,7 @@ function readThermal() {
19450
19448
  return "?";
19451
19449
  }
19452
19450
  }
19453
- function sh$2(script, args, cwd, env) {
19451
+ function sh$1(script, args, cwd, env) {
19454
19452
  return new Promise((resolve) => {
19455
19453
  const p = spawn("sh", [script, ...args], {
19456
19454
  cwd,
@@ -19491,11 +19489,11 @@ async function runBench(o) {
19491
19489
  ...process.env,
19492
19490
  PROMPT: arm.prompt
19493
19491
  };
19494
- const started = await sh$2(join(o.suite, "run.sh"), [arm.task, arm.provider], o.suite, env);
19492
+ const started = await sh$1(join(o.suite, "run.sh"), [arm.task, arm.provider], o.suite, env);
19495
19493
  const id = /^arm (\S+) ended/m.exec(started)?.[1];
19496
19494
  if (!id) return o.log(`${arm.task}/${arm.provider}: no arm id in run.sh output`);
19497
19495
  appendFileSync(envFile, `${id}\t${load}\t${thermal}\n`);
19498
- const row = parseRow((await sh$2(join(o.suite, "grade.sh"), [arm.task, id], o.suite, process.env)).trim().split("\n").pop() ?? "");
19496
+ const row = parseRow((await sh$1(join(o.suite, "grade.sh"), [arm.task, id], o.suite, process.env)).trim().split("\n").pop() ?? "");
19499
19497
  if (row) rows.push(row);
19500
19498
  o.log(`${id}: ${row?.verdict ?? "ungraded"} (load ${load}, thermal ${thermal})`);
19501
19499
  } finally {
@@ -20254,7 +20252,7 @@ function registerWorkerCommands(workerCmd) {
20254
20252
  });
20255
20253
  workerCmd.command("pool [action]").description("Worker session pool: long-lived headless claude slots that successive small\nruns talk to instead of each spawning a fresh claude, so the provider\nprompt cache carries over (src/workers/pool.ts).\non starts the detached host and enables routing, off stops both, status\nshows slots, tasks served and the cache-carry total. Default off.").action(async (action) => {
20256
20254
  try {
20257
- const { poolOn, poolOff, poolStatusText } = await import("./pool-cli-DerrWWpP.mjs");
20255
+ const { poolOn, poolOff, poolStatusText } = await import("./pool-cli-kGGuZCzJ.mjs");
20258
20256
  if (action === void 0 || action === "status") {
20259
20257
  console.log(await poolStatusText(currentLogDir()));
20260
20258
  return;
@@ -20942,442 +20940,6 @@ function handleCockpit(req, res, limits, readRows = readUsage, sessionMap = load
20942
20940
  return true;
20943
20941
  }
20944
20942
 
20945
- //#endregion
20946
- //#region src/router/limits.ts
20947
- /**
20948
- * limits.ts — per-provider plan limits for the cockpit. Polled at most once a
20949
- * minute and cached; keys and tokens stay in this process and never reach the
20950
- * page or the JSON it is served.
20951
- *
20952
- * anthropic Max plan 5h/7d via the OAuth usage endpoint (token from the
20953
- * keychain, as the statusline does); on a failed poll (http 429)
20954
- * the last good reading is served with its age and the poll backs
20955
- * off, advisor-mode.json only when no last good reading exists
20956
- * others the provider's workers.yaml `usage` block (jq expressions)
20957
- * local up/down (TCP), RSS of the listener, tokens/s from accounting
20958
- * rest counted requests vs a configured limit, labelled "estimated"
20959
- */
20960
- const ESTIMATE_FILE = join(homedir(), ".claude", "pai", "router-limits.json");
20961
- const ADVISOR_FILE = join(homedir(), ".claude", "pai", "advisor-mode.json");
20962
- /** Last good plan reading per provider, so a rate-limited poll shows an age, not "reset unknown". */
20963
- const LASTGOOD_FILE = join(homedir(), ".claude", "pai", "logs", "router-limits-last.json");
20964
- /** A last good reading older than this is too stale to serve when the endpoint fails. */
20965
- const PLAN_LASTGOOD_MAX_AGE = 2 * 36e5;
20966
- /** Upper bound for the poll delay after repeated 429s. */
20967
- const BACKOFF_MAX = 30 * 6e4;
20968
- function readLastGood(file = LASTGOOD_FILE) {
20969
- try {
20970
- const j = JSON.parse(readFileSync(file, "utf8"));
20971
- const out = {};
20972
- for (const [k, v] of Object.entries(j)) if (v && Array.isArray(v.windows) && typeof v.fetchedAt === "number") out[k] = {
20973
- windows: v.windows,
20974
- fetchedAt: v.fetchedAt
20975
- };
20976
- return out;
20977
- } catch {
20978
- return {};
20979
- }
20980
- }
20981
- function writeLastGood(file, entries) {
20982
- try {
20983
- mkdirSync(dirname(file), { recursive: true });
20984
- writeFileSync(file, JSON.stringify(entries, null, 1));
20985
- } catch {}
20986
- }
20987
- /**
20988
- * The reading to show when a poll failed: the last good one, with its age in
20989
- * the error field, while it is fresh enough to trust; undefined otherwise.
20990
- */
20991
- function staleReading(provider, entry, cause, now, maxAge = PLAN_LASTGOOD_MAX_AGE) {
20992
- if (!entry || !entry.windows.length || now - entry.fetchedAt >= maxAge) return void 0;
20993
- const min = Math.round((now - entry.fetchedAt) / 6e4);
20994
- return {
20995
- provider,
20996
- kind: "plan",
20997
- windows: entry.windows,
20998
- fetchedAt: entry.fetchedAt,
20999
- error: `stale ${min}min (${cause})`
21000
- };
21001
- }
21002
- /** Per-provider poll backoff after a http 429: the interval doubles per strike, resets on success. */
21003
- var Backoff = class {
21004
- mult = /* @__PURE__ */ new Map();
21005
- until = /* @__PURE__ */ new Map();
21006
- constructor(baseMs, maxMs = BACKOFF_MAX) {
21007
- this.baseMs = baseMs;
21008
- this.maxMs = maxMs;
21009
- }
21010
- /** Record a 429 seen for `provider` at `now`; returns the delay before its next poll. */
21011
- penalize(provider, now) {
21012
- const m = Math.min((this.mult.get(provider) ?? 1) * 2, this.maxMs / this.baseMs);
21013
- this.mult.set(provider, m);
21014
- this.until.set(provider, now + m * this.baseMs);
21015
- return m * this.baseMs;
21016
- }
21017
- /** ms until `provider` is due again; 0 when it may be polled now. */
21018
- remaining(provider, now) {
21019
- return Math.max(0, (this.until.get(provider) ?? 0) - now);
21020
- }
21021
- /** A poll succeeded: forget the strikes. */
21022
- reset(provider) {
21023
- this.mult.delete(provider);
21024
- this.until.delete(provider);
21025
- }
21026
- };
21027
- function toMs(v, unit) {
21028
- if (v === null || v === void 0 || v === "") return void 0;
21029
- if (unit === "iso" || unit === void 0 && typeof v === "string" && !/^\d+(\.\d+)?$/.test(v)) {
21030
- const t = Date.parse(String(v));
21031
- return Number.isFinite(t) ? t : void 0;
21032
- }
21033
- const n = Number(v);
21034
- if (!Number.isFinite(n)) return void 0;
21035
- return unit === "s" ? n * 1e3 : n;
21036
- }
21037
- function jq(expr, input) {
21038
- const r = spawnSync("jq", ["-r", expr], {
21039
- input,
21040
- encoding: "utf8",
21041
- timeout: 3e3
21042
- });
21043
- if (r.status !== 0) return void 0;
21044
- const out = r.stdout.trim().split("\n")[0];
21045
- return out === void 0 || out === "" || out === "null" ? void 0 : out;
21046
- }
21047
- /** Windows of a provider usage response, using its configured jq expressions. */
21048
- function windowsFromJson(body, cfg) {
21049
- const out = [];
21050
- for (const w of cfg.windows) {
21051
- const pct = Number(jq(w.percent, body));
21052
- if (!Number.isFinite(pct) || jq(w.percent, body) === void 0) continue;
21053
- const reset = w.resetAt ? toMs(jq(w.resetAt, body), w.resetUnit) : void 0;
21054
- out.push({
21055
- name: w.name,
21056
- percent: Math.round(pct * 10) / 10,
21057
- ...reset ? { resetAt: reset } : {}
21058
- });
21059
- }
21060
- return out;
21061
- }
21062
- /** Anthropic OAuth usage response: five_hour / seven_day {utilization, resets_at ISO}. */
21063
- function parseAnthropicUsage(body) {
21064
- let j;
21065
- try {
21066
- j = JSON.parse(body);
21067
- } catch {
21068
- return [];
21069
- }
21070
- const out = [];
21071
- for (const [key, name] of [["five_hour", "5h"], ["seven_day", "7d"]]) {
21072
- const w = j[key];
21073
- if (!w || typeof w.utilization !== "number") continue;
21074
- const reset = toMs(w.resets_at, "iso");
21075
- out.push({
21076
- name,
21077
- percent: w.utilization,
21078
- ...reset ? { resetAt: reset } : {}
21079
- });
21080
- }
21081
- return out;
21082
- }
21083
- /** Counted requests inside each window vs a configured cap: labelled estimated. */
21084
- function estimateWindows(rows, provider, caps, now) {
21085
- const spans = {
21086
- "5h": 5 * 36e5,
21087
- "7d": 7 * 864e5
21088
- };
21089
- const out = [];
21090
- for (const [name, span] of Object.entries(spans)) {
21091
- const cap = caps[name];
21092
- if (!cap) continue;
21093
- const inWin = rows.filter((r) => r.provider === provider && Date.parse(r.ts) >= now - span);
21094
- const first = inWin.reduce((m, r) => Math.min(m, Date.parse(r.ts)), Infinity);
21095
- out.push({
21096
- name,
21097
- percent: Math.round(inWin.length / cap * 1e3) / 10,
21098
- ...Number.isFinite(first) ? { resetAt: first + span } : {},
21099
- estimated: true
21100
- });
21101
- }
21102
- return out;
21103
- }
21104
- function readEstimateCaps(file = ESTIMATE_FILE) {
21105
- try {
21106
- return existsSync(file) ? JSON.parse(readFileSync(file, "utf8")) : {};
21107
- } catch {
21108
- return {};
21109
- }
21110
- }
21111
- function getJson(url, headers) {
21112
- return new Promise((resolve, reject) => {
21113
- const rq = (url.protocol === "https:" ? https : http).get(url, {
21114
- headers,
21115
- timeout: 5e3
21116
- }, (res) => {
21117
- let t = "";
21118
- res.on("data", (c) => t += c);
21119
- res.on("end", () => res.statusCode === 200 ? resolve(t) : reject(/* @__PURE__ */ new Error(`http ${res.statusCode}`)));
21120
- });
21121
- rq.on("timeout", () => rq.destroy(/* @__PURE__ */ new Error("timeout")));
21122
- rq.on("error", reject);
21123
- });
21124
- }
21125
- function sh$1(cmd, args) {
21126
- return new Promise((resolve) => execFile(cmd, args, { timeout: 4e3 }, (_e, out) => resolve(String(out ?? "").trim())));
21127
- }
21128
- async function anthropicToken() {
21129
- for (const args of [["-a", process.env.USER ?? ""], []]) {
21130
- const raw = await sh$1("security", [
21131
- "find-generic-password",
21132
- "-s",
21133
- "Claude Code-credentials",
21134
- ...args,
21135
- "-w"
21136
- ]);
21137
- try {
21138
- const t = JSON.parse(raw).claudeAiOauth?.accessToken;
21139
- if (t) return t;
21140
- } catch {}
21141
- }
21142
- }
21143
- async function anthropicLimits(now, advisorFile, lastGood) {
21144
- const base = {
21145
- provider: "anthropic",
21146
- kind: "plan",
21147
- fetchedAt: now
21148
- };
21149
- try {
21150
- const token = await anthropicToken();
21151
- if (!token) throw new Error("no OAuth token in keychain");
21152
- const windows = parseAnthropicUsage(await getJson(new URL("https://api.anthropic.com/api/oauth/usage"), {
21153
- authorization: `Bearer ${token}`,
21154
- "anthropic-beta": "oauth-2025-04-20"
21155
- }));
21156
- if (windows.length) return {
21157
- ...base,
21158
- windows
21159
- };
21160
- throw new Error("no usage windows in response");
21161
- } catch (e) {
21162
- const stale = staleReading("anthropic", lastGood, e.message, now);
21163
- if (stale) return stale;
21164
- try {
21165
- const a = JSON.parse(readFileSync(advisorFile, "utf8"));
21166
- if (typeof a.weeklyBudgetPercent === "number" && a.asOf && now / 1e3 - a.asOf < 6 * 3600) return {
21167
- ...base,
21168
- windows: [{
21169
- name: "7d",
21170
- percent: a.weeklyBudgetPercent
21171
- }],
21172
- error: `${e.message}; advisor-mode fallback`
21173
- };
21174
- } catch {}
21175
- return {
21176
- ...base,
21177
- windows: [],
21178
- error: e.message
21179
- };
21180
- }
21181
- }
21182
- async function providerPlanLimits(name, p, now, lastGood) {
21183
- const base = {
21184
- provider: name,
21185
- kind: "plan",
21186
- fetchedAt: now
21187
- };
21188
- const u = p.usage;
21189
- try {
21190
- const key = resolveProviderKey(p);
21191
- const [hn, ...pre] = (u.authHeader ?? "Authorization: Bearer").split(/:\s*/);
21192
- const prefix = pre.join(": ");
21193
- const headers = { [hn.toLowerCase()]: prefix ? `${prefix} ${key}` : String(key) };
21194
- const windows = windowsFromJson(await getJson(new URL(u.url), headers), u);
21195
- return windows.length ? {
21196
- ...base,
21197
- windows
21198
- } : {
21199
- ...base,
21200
- windows,
21201
- error: "no windows parsed"
21202
- };
21203
- } catch (e) {
21204
- const msg = e.message.replace(/Bearer\s+\S+/g, "Bearer ***");
21205
- return staleReading(name, lastGood, msg, now) ?? {
21206
- ...base,
21207
- windows: [],
21208
- error: msg
21209
- };
21210
- }
21211
- }
21212
- function probeTcp(port, host) {
21213
- return new Promise((resolve) => {
21214
- const s = net.connect({
21215
- port,
21216
- host,
21217
- timeout: 800
21218
- });
21219
- s.on("connect", () => (s.destroy(), resolve(true)));
21220
- s.on("timeout", () => (s.destroy(), resolve(false)));
21221
- s.on("error", () => resolve(false));
21222
- });
21223
- }
21224
- async function localLimits(name, p, rows, now) {
21225
- const u = new URL(p.baseUrl);
21226
- const port = Number(u.port) || 80;
21227
- const listening = await probeTcp(port, u.hostname);
21228
- const served = listening ? await servedModels(u) : void 0;
21229
- const up = listening && modelServed(served, Object.values(p.models).filter((m) => typeof m === "string"));
21230
- let rssMb;
21231
- if (up) {
21232
- const pid = (await sh$1("lsof", [
21233
- "-ti",
21234
- `tcp:${port}`,
21235
- "-sTCP:LISTEN"
21236
- ])).split("\n")[0];
21237
- const rss = pid ? Number(await sh$1("ps", [
21238
- "-o",
21239
- "rss=",
21240
- "-p",
21241
- pid
21242
- ])) : NaN;
21243
- if (Number.isFinite(rss) && rss > 0) rssMb = Math.round(rss / 1024);
21244
- }
21245
- return {
21246
- provider: name,
21247
- kind: "local",
21248
- windows: [],
21249
- up,
21250
- ...rssMb ? { rssMb } : {},
21251
- ...served ? { served } : {},
21252
- ...tokensPerSec(rows, name, now),
21253
- fetchedAt: now
21254
- };
21255
- }
21256
- /** Model ids the server at this base URL lists on GET /v1/models; undefined when it cannot say. */
21257
- async function servedModels(base) {
21258
- try {
21259
- const ids = (JSON.parse(await getJson(new URL("/v1/models", base), {})).data ?? []).map((m) => m.id).filter((i) => typeof i === "string");
21260
- return ids.length ? ids : void 0;
21261
- } catch {
21262
- return;
21263
- }
21264
- }
21265
- /** Several providers can share one port: the provider is up only if its model is the one served. Unknown list = port decides. */
21266
- function modelServed(served, wanted) {
21267
- if (!served) return true;
21268
- return wanted.some((w) => served.includes(w));
21269
- }
21270
- /** output tokens / generation seconds over the last hour (slow-path requests only). */
21271
- function tokensPerSec(rows, provider, now) {
21272
- let out = 0;
21273
- let ms = 0;
21274
- for (const r of rows) {
21275
- if (r.provider !== provider || Date.parse(r.ts) < now - 36e5 || r.status !== 200 || !r.output_tokens) continue;
21276
- out += r.output_tokens;
21277
- ms += r.ms;
21278
- }
21279
- return ms ? { tokensPerSec: Math.round(out / (ms / 1e3) * 10) / 10 } : {};
21280
- }
21281
- function isLocalUrl$1(u) {
21282
- try {
21283
- const h = new URL(u).hostname;
21284
- return h === "127.0.0.1" || h === "localhost";
21285
- } catch {
21286
- return false;
21287
- }
21288
- }
21289
- /**
21290
- * Polls all providers at most once per `ttlMs`; concurrent callers share one
21291
- * poll. A provider whose poll answered http 429 is not fetched again until its
21292
- * backoff (the interval doubled per strike, capped) has run out — its last
21293
- * good reading is served with the current age instead.
21294
- */
21295
- var LimitsCache = class {
21296
- value = [];
21297
- at = 0;
21298
- inflight;
21299
- backoff;
21300
- constructor(deps, ttlMs = 6e4) {
21301
- this.deps = deps;
21302
- this.ttlMs = ttlMs;
21303
- this.backoff = new Backoff(ttlMs);
21304
- }
21305
- get(now = Date.now()) {
21306
- if (this.value.length && now - this.at < this.ttlMs) return Promise.resolve(this.value);
21307
- this.inflight ??= this.poll(now).then((v) => {
21308
- this.value = v;
21309
- this.at = now;
21310
- this.inflight = void 0;
21311
- return v;
21312
- });
21313
- return this.inflight;
21314
- }
21315
- async poll(now) {
21316
- const rows = this.deps.rows();
21317
- let providers = {};
21318
- try {
21319
- providers = this.deps.providers();
21320
- } catch {}
21321
- const caps = readEstimateCaps(this.deps.estimateFile);
21322
- const lastGoodFile = this.deps.lastGoodFile ?? LASTGOOD_FILE;
21323
- const lastGood = readLastGood(lastGoodFile);
21324
- const previous = new Map(this.value.map((v) => [v.provider, v]));
21325
- const jobs = [];
21326
- const skipped = [];
21327
- /** Queue a plan poll unless the provider is backing off from a 429. */
21328
- const plan = (name, fn) => {
21329
- if (this.backoff.remaining(name, now) > 0) {
21330
- skipped.push(name);
21331
- return;
21332
- }
21333
- jobs.push(fn(lastGood[name]));
21334
- };
21335
- plan("anthropic", (lg) => anthropicLimits(now, this.deps.advisorFile ?? ADVISOR_FILE, lg));
21336
- for (const [name, p] of Object.entries(providers)) {
21337
- if (p.native || name === "anthropic" || p.enabled === false || !p.baseUrl) continue;
21338
- if (isLocalUrl$1(p.baseUrl)) jobs.push(localLimits(name, p, rows, now));
21339
- else if (p.usage) plan(name, (lg) => providerPlanLimits(name, p, now, lg));
21340
- else if (caps[name]) jobs.push(Promise.resolve({
21341
- provider: name,
21342
- kind: "estimated",
21343
- windows: estimateWindows(rows, name, caps[name], now),
21344
- fetchedAt: now
21345
- }));
21346
- }
21347
- const results = await Promise.all(jobs);
21348
- const store = { ...lastGood };
21349
- let dirty = false;
21350
- for (const r of results) if (r.error) {
21351
- if (r.error.includes("http 429")) this.backoff.penalize(r.provider, now);
21352
- } else {
21353
- this.backoff.reset(r.provider);
21354
- if (r.windows.length) {
21355
- store[r.provider] = {
21356
- windows: r.windows,
21357
- fetchedAt: r.fetchedAt
21358
- };
21359
- dirty = true;
21360
- }
21361
- }
21362
- if (dirty) writeLastGood(lastGoodFile, store);
21363
- for (const name of skipped) {
21364
- const prev = previous.get(name);
21365
- const cause = prev?.error?.includes("http 429") ? "http 429" : prev?.error ?? "http 429";
21366
- results.push(prev ? {
21367
- ...prev,
21368
- error: `stale ${Math.max(0, Math.round((now - prev.fetchedAt) / 6e4))}min (${cause})`
21369
- } : {
21370
- provider: name,
21371
- kind: "plan",
21372
- windows: [],
21373
- error: cause,
21374
- fetchedAt: now
21375
- });
21376
- }
21377
- return results;
21378
- }
21379
- };
21380
-
21381
20943
  //#endregion
21382
20944
  //#region src/router/system.ts
21383
20945
  /**
@@ -23944,13 +23506,13 @@ function recentMarkdown(root, limit) {
23944
23506
  async function pickModel(name, dryRun) {
23945
23507
  let workers;
23946
23508
  try {
23947
- workers = (await import("./config-CQWpEdXb.mjs")).readWorkersSection().workers;
23509
+ workers = (await import("./config-IuOG1W92.mjs")).readWorkersSection().workers;
23948
23510
  } catch {
23949
23511
  return;
23950
23512
  }
23951
- const { readLocalConfig, planStart, findModelPath } = await import("./local-tiers-BIINbhkY.mjs");
23952
- const { workersYamlPath } = await import("./workers-config-nXSiW07z.mjs");
23953
- const { listServers, startTier, isUp } = await import("./local-B5SekWOC.mjs");
23513
+ const { readLocalConfig, planStart, findModelPath } = await import("./local-tiers-C0QSQcP1.mjs");
23514
+ const { workersYamlPath } = await import("./workers-config-BifEz8ns.mjs");
23515
+ const { listServers, startTier, isUp } = await import("./local-oqPQEmhb.mjs");
23954
23516
  let local = null;
23955
23517
  let running = [];
23956
23518
  try {
@@ -24323,4 +23885,4 @@ claude() {
24323
23885
 
24324
23886
  //#endregion
24325
23887
  export { drainStdio as n, buildProgram as t };
24326
- //# sourceMappingURL=program-B7gVKc-u.mjs.map
23888
+ //# sourceMappingURL=program-DgcwJN6Z.mjs.map