@crouton-kit/crouter 0.3.40 → 0.3.42

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 (195) hide show
  1. package/dist/build-root.js +1 -0
  2. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +472 -9
  3. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +284 -76
  4. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/strip-skills-docs.ts +31 -24
  5. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +52 -15
  6. package/dist/clients/attach/attach-cmd.js +720 -747
  7. package/dist/clients/attach/chat-view.js +11 -0
  8. package/dist/clients/attach/view-socket.d.ts +8 -1
  9. package/dist/clients/attach/view-socket.js +15 -1
  10. package/dist/clients/web/server.js +5 -28
  11. package/dist/clients/web/web-cmd.js +1 -1
  12. package/dist/commands/__tests__/revive-now-gate.test.js +60 -0
  13. package/dist/commands/canvas-rebuild-index.js +5 -5
  14. package/dist/commands/memory/shared.d.ts +7 -3
  15. package/dist/commands/memory/shared.js +35 -5
  16. package/dist/commands/memory/write.js +5 -3
  17. package/dist/commands/node-snapshot.js +9 -1
  18. package/dist/commands/node.js +37 -17
  19. package/dist/commands/push.js +8 -0
  20. package/dist/commands/revive.d.ts +10 -0
  21. package/dist/commands/revive.js +28 -10
  22. package/dist/commands/sys/__tests__/setup-core.test.js +19 -0
  23. package/dist/commands/sys/doctor.js +1 -1
  24. package/dist/commands/sys/setup-core.js +3 -2
  25. package/dist/commands/sys/setup.js +1 -1
  26. package/dist/commands/worktree.d.ts +2 -0
  27. package/dist/commands/worktree.js +94 -0
  28. package/dist/core/__tests__/boot.test.js +4 -4
  29. package/dist/core/__tests__/canvas.test.js +19 -7
  30. package/dist/core/__tests__/child-followup.test.js +15 -5
  31. package/dist/core/__tests__/daemon-boot.test.js +6 -1
  32. package/dist/core/__tests__/daemon-wedge.test.js +18 -1
  33. package/dist/core/__tests__/fault-classifier.test.js +30 -0
  34. package/dist/core/__tests__/fixtures/fake-engine.d.ts +13 -0
  35. package/dist/core/__tests__/fixtures/fake-engine.js +20 -0
  36. package/dist/core/__tests__/full/spike-harness.test.js +8 -5
  37. package/dist/core/__tests__/grace-clock.test.js +18 -2
  38. package/dist/core/__tests__/host-teardown-process-group.test.js +465 -0
  39. package/dist/core/__tests__/prune-to-limit.test.js +14 -0
  40. package/dist/core/__tests__/review-model-floor.test.js +32 -0
  41. package/dist/core/__tests__/revive.test.js +18 -4
  42. package/dist/core/__tests__/session-cycles.test.js +77 -0
  43. package/dist/core/__tests__/worktree.test.js +85 -0
  44. package/dist/core/canvas/boot.js +12 -7
  45. package/dist/core/canvas/canvas.d.ts +27 -8
  46. package/dist/core/canvas/canvas.js +54 -26
  47. package/dist/core/canvas/db.js +14 -0
  48. package/dist/core/canvas/history.js +1 -0
  49. package/dist/core/canvas/paths.d.ts +10 -9
  50. package/dist/core/canvas/paths.js +10 -9
  51. package/dist/core/canvas/pid.d.ts +155 -1
  52. package/dist/core/canvas/pid.js +306 -1
  53. package/dist/core/canvas/status-glyph.d.ts +7 -0
  54. package/dist/core/canvas/status-glyph.js +10 -1
  55. package/dist/core/canvas/types.d.ts +34 -0
  56. package/dist/core/fault-classifier.js +5 -1
  57. package/dist/core/profiles/select.d.ts +4 -2
  58. package/dist/core/profiles/select.js +30 -4
  59. package/dist/core/runtime/bearings.js +4 -0
  60. package/dist/core/runtime/branded-host.d.ts +7 -0
  61. package/dist/core/runtime/branded-host.js +44 -17
  62. package/dist/core/runtime/broker-sdk.js +28 -68
  63. package/dist/core/runtime/broker.js +35 -4
  64. package/dist/core/runtime/host.d.ts +3 -3
  65. package/dist/core/runtime/host.js +148 -33
  66. package/dist/core/runtime/launch.d.ts +15 -15
  67. package/dist/core/runtime/launch.js +58 -4
  68. package/dist/core/runtime/naming.js +3 -2
  69. package/dist/core/runtime/nodes.d.ts +3 -1
  70. package/dist/core/runtime/nodes.js +1 -0
  71. package/dist/core/runtime/pi-cli.d.ts +2 -0
  72. package/dist/core/runtime/pi-cli.js +51 -0
  73. package/dist/core/runtime/placement.d.ts +1 -1
  74. package/dist/core/runtime/placement.js +5 -2
  75. package/dist/core/runtime/recap.js +2 -1
  76. package/dist/core/runtime/revive.d.ts +21 -15
  77. package/dist/core/runtime/revive.js +87 -52
  78. package/dist/core/runtime/session-cycles.d.ts +30 -0
  79. package/dist/core/runtime/session-cycles.js +77 -0
  80. package/dist/core/runtime/spawn.d.ts +4 -0
  81. package/dist/core/runtime/spawn.js +152 -100
  82. package/dist/core/runtime/tmux.d.ts +7 -10
  83. package/dist/core/runtime/tmux.js +9 -11
  84. package/dist/core/worktree.d.ts +35 -0
  85. package/dist/core/worktree.js +158 -0
  86. package/dist/daemon/crtrd.d.ts +17 -8
  87. package/dist/daemon/crtrd.js +191 -40
  88. package/dist/index.d.ts +3 -0
  89. package/dist/index.js +7 -0
  90. package/dist/pi-extensions/canvas-context-intro.d.ts +1 -0
  91. package/dist/pi-extensions/canvas-context-intro.js +34 -23
  92. package/dist/pi-extensions/canvas-stophook.js +11 -5
  93. package/dist/web-client/assets/{index-CbO8L0mN.js → index-B00YpRQ1.js} +20 -20
  94. package/dist/web-client/assets/index-DrkcvANq.css +2 -0
  95. package/dist/web-client/index.html +2 -2
  96. package/docs/compat/hearth-crtr-v1.md +191 -0
  97. package/docs/public-api.md +75 -0
  98. package/package.json +3 -4
  99. package/dist/core/__tests__/hearth-bootstrap.test.js +0 -136
  100. package/dist/core/hearth/__tests__/model-auth-guest.test.js +0 -151
  101. package/dist/core/hearth/config.d.ts +0 -3
  102. package/dist/core/hearth/config.js +0 -108
  103. package/dist/core/hearth/guest-env.d.ts +0 -9
  104. package/dist/core/hearth/guest-env.js +0 -27
  105. package/dist/core/hearth/index.d.ts +0 -4
  106. package/dist/core/hearth/index.js +0 -4
  107. package/dist/core/hearth/model-auth-guest.d.ts +0 -8
  108. package/dist/core/hearth/model-auth-guest.js +0 -430
  109. package/dist/core/hearth/provider.d.ts +0 -36
  110. package/dist/core/hearth/provider.js +0 -10
  111. package/dist/core/hearth/providers/__tests__/sweep-and-release.test.js +0 -362
  112. package/dist/core/hearth/providers/blaxel-bootstrap.d.ts +0 -12
  113. package/dist/core/hearth/providers/blaxel-bootstrap.js +0 -147
  114. package/dist/core/hearth/providers/blaxel-home.d.ts +0 -60
  115. package/dist/core/hearth/providers/blaxel-home.js +0 -405
  116. package/dist/core/hearth/providers/blaxel.d.ts +0 -36
  117. package/dist/core/hearth/providers/blaxel.js +0 -364
  118. package/dist/core/hearth/providers/types.d.ts +0 -93
  119. package/dist/core/hearth/types.d.ts +0 -155
  120. package/dist/hearth/control-plane/__tests__/error-serialization.test.js +0 -29
  121. package/dist/hearth/control-plane/__tests__/node-message.test.js +0 -60
  122. package/dist/hearth/control-plane/__tests__/oauth-serving-marker.test.d.ts +0 -1
  123. package/dist/hearth/control-plane/__tests__/oauth-serving-marker.test.js +0 -44
  124. package/dist/hearth/control-plane/__tests__/rate-limit-recurrence.test.d.ts +0 -1
  125. package/dist/hearth/control-plane/__tests__/rate-limit-recurrence.test.js +0 -49
  126. package/dist/hearth/control-plane/__tests__/relay-security.test.d.ts +0 -1
  127. package/dist/hearth/control-plane/__tests__/relay-security.test.js +0 -314
  128. package/dist/hearth/control-plane/__tests__/scheduler-scan-loop.test.d.ts +0 -1
  129. package/dist/hearth/control-plane/__tests__/scheduler-scan-loop.test.js +0 -133
  130. package/dist/hearth/control-plane/__tests__/trigger-delivery.test.d.ts +0 -1
  131. package/dist/hearth/control-plane/__tests__/trigger-delivery.test.js +0 -170
  132. package/dist/hearth/control-plane/__tests__/wake-roll.test.d.ts +0 -1
  133. package/dist/hearth/control-plane/__tests__/wake-roll.test.js +0 -230
  134. package/dist/hearth/control-plane/__tests__/webhook-ingress.test.d.ts +0 -1
  135. package/dist/hearth/control-plane/__tests__/webhook-ingress.test.js +0 -167
  136. package/dist/hearth/control-plane/config.d.ts +0 -21
  137. package/dist/hearth/control-plane/config.js +0 -77
  138. package/dist/hearth/control-plane/db.d.ts +0 -30
  139. package/dist/hearth/control-plane/db.js +0 -561
  140. package/dist/hearth/control-plane/hearth-target.d.ts +0 -23
  141. package/dist/hearth/control-plane/hearth-target.js +0 -68
  142. package/dist/hearth/control-plane/ingress/rate-limit.d.ts +0 -24
  143. package/dist/hearth/control-plane/ingress/rate-limit.js +0 -100
  144. package/dist/hearth/control-plane/ingress/route-store.d.ts +0 -31
  145. package/dist/hearth/control-plane/ingress/route-store.js +0 -61
  146. package/dist/hearth/control-plane/ingress/webhook-delivery-store.d.ts +0 -41
  147. package/dist/hearth/control-plane/ingress/webhook-delivery-store.js +0 -69
  148. package/dist/hearth/control-plane/ingress/webhook-route.d.ts +0 -55
  149. package/dist/hearth/control-plane/ingress/webhook-route.js +0 -285
  150. package/dist/hearth/control-plane/main.d.ts +0 -1
  151. package/dist/hearth/control-plane/main.js +0 -88
  152. package/dist/hearth/control-plane/node-message.d.ts +0 -31
  153. package/dist/hearth/control-plane/node-message.js +0 -98
  154. package/dist/hearth/control-plane/register.d.ts +0 -15
  155. package/dist/hearth/control-plane/register.js +0 -34
  156. package/dist/hearth/control-plane/registry.d.ts +0 -22
  157. package/dist/hearth/control-plane/registry.js +0 -168
  158. package/dist/hearth/control-plane/relay.d.ts +0 -44
  159. package/dist/hearth/control-plane/relay.js +0 -711
  160. package/dist/hearth/control-plane/scheduler/fire-store.d.ts +0 -36
  161. package/dist/hearth/control-plane/scheduler/fire-store.js +0 -73
  162. package/dist/hearth/control-plane/scheduler/recurrence.d.ts +0 -7
  163. package/dist/hearth/control-plane/scheduler/recurrence.js +0 -58
  164. package/dist/hearth/control-plane/scheduler/scan-loop.d.ts +0 -38
  165. package/dist/hearth/control-plane/scheduler/scan-loop.js +0 -138
  166. package/dist/hearth/control-plane/scheduler/schedule-store.d.ts +0 -32
  167. package/dist/hearth/control-plane/scheduler/schedule-store.js +0 -66
  168. package/dist/hearth/control-plane/secrets.d.ts +0 -31
  169. package/dist/hearth/control-plane/secrets.js +0 -134
  170. package/dist/hearth/control-plane/server.d.ts +0 -27
  171. package/dist/hearth/control-plane/server.js +0 -482
  172. package/dist/hearth/control-plane/serving.d.ts +0 -15
  173. package/dist/hearth/control-plane/serving.js +0 -106
  174. package/dist/hearth/control-plane/session.d.ts +0 -68
  175. package/dist/hearth/control-plane/session.js +0 -273
  176. package/dist/hearth/control-plane/triggers/acl.d.ts +0 -14
  177. package/dist/hearth/control-plane/triggers/acl.js +0 -52
  178. package/dist/hearth/control-plane/triggers/audit-store.d.ts +0 -38
  179. package/dist/hearth/control-plane/triggers/audit-store.js +0 -79
  180. package/dist/hearth/control-plane/triggers/deliver.d.ts +0 -43
  181. package/dist/hearth/control-plane/triggers/deliver.js +0 -76
  182. package/dist/hearth/control-plane/triggers/envelope.d.ts +0 -29
  183. package/dist/hearth/control-plane/triggers/envelope.js +0 -38
  184. package/dist/hearth/control-plane/types.d.ts +0 -86
  185. package/dist/hearth/control-plane/types.js +0 -1
  186. package/dist/hearth/control-plane/wake.d.ts +0 -86
  187. package/dist/hearth/control-plane/wake.js +0 -550
  188. package/dist/web-client/assets/index-DwO46Cs5.css +0 -2
  189. /package/dist/{core/__tests__/hearth-bootstrap.test.d.ts → commands/__tests__/revive-now-gate.test.d.ts} +0 -0
  190. /package/dist/{core/hearth/__tests__/model-auth-guest.test.d.ts → commands/sys/__tests__/setup-core.test.d.ts} +0 -0
  191. /package/dist/core/{hearth/providers/__tests__/sweep-and-release.test.d.ts → __tests__/fault-classifier.test.d.ts} +0 -0
  192. /package/dist/core/{hearth/providers/types.js → __tests__/host-teardown-process-group.test.d.ts} +0 -0
  193. /package/dist/core/{hearth/types.js → __tests__/review-model-floor.test.d.ts} +0 -0
  194. /package/dist/{hearth/control-plane/__tests__/error-serialization.test.d.ts → core/__tests__/session-cycles.test.d.ts} +0 -0
  195. /package/dist/{hearth/control-plane/__tests__/node-message.test.d.ts → core/__tests__/worktree.test.d.ts} +0 -0
@@ -325,22 +325,52 @@ function splitModelRef(ref: string): FallbackTarget {
325
325
  };
326
326
  }
327
327
 
328
- function readModelLadders(): ModelLaddersConfig | undefined {
328
+ // Vendored copy of crouter's `defaultModelLaddersConfig()` (src/types.ts).
329
+ // This package is synced from a standalone repo (pi-personal-extensions) and
330
+ // has no runtime import path into crouter's compiled internals, so the
331
+ // builtin rungs are duplicated here rather than imported; keep the two in
332
+ // sync by hand if either changes.
333
+ const BUILTIN_MODEL_LADDERS: Record<LadderProviderId, ModelLadderConfig> = {
334
+ anthropic: {
335
+ ultra: "anthropic/claude-fable-5:high",
336
+ strong: "anthropic/claude-opus-4-8:high",
337
+ medium: "anthropic/claude-sonnet-5:high",
338
+ light: "anthropic/claude-haiku-4-5:high",
339
+ },
340
+ openai: {
341
+ ultra: "openai-codex/gpt-5.5:xhigh",
342
+ strong: "openai-codex/gpt-5.5:high",
343
+ medium: "openai-codex/gpt-5.5:medium",
344
+ light: "openai-codex/gpt-5.3-codex-spark",
345
+ },
346
+ };
347
+
348
+ // Layers ~/.crouter/config.json's `modelLadders` (if any) OVER the builtin
349
+ // defaults above, per provider/strength — mirroring crouter's own
350
+ // `mergeModelLadders` (src/core/config.ts), which is what a node's launcher
351
+ // actually resolves models from. Without this fallback, a config-less user
352
+ // (the common case: fresh install, no ~/.crouter/config.json) saw an EMPTY
353
+ // ladder here while crtr itself launched them on the builtin defaults —
354
+ // rotation could then never resolve a strength tier or a cross-provider
355
+ // fallback for a model it was already running. Always returns a fully
356
+ // populated ladder for both providers; a config.json override only replaces
357
+ // the specific strengths it sets.
358
+ function readModelLadders(): ModelLaddersConfig {
329
359
  const config = readJsonFile<{ modelLadders?: Partial<Record<LadderProviderId, Partial<ModelLadderConfig>>> }>(CROUTER_CONFIG_FILE);
330
- const ladders = config?.modelLadders;
331
- if (!ladders) return undefined;
360
+ const overrides = config?.modelLadders;
332
361
  const result: ModelLaddersConfig = {};
333
362
  for (const provider of ["anthropic", "openai"] as const) {
334
- const source = ladders[provider];
335
- if (!source) continue;
336
- const normalized: ModelLadderConfig = {};
337
- for (const strength of ["ultra", "strong", "medium", "light"] as const) {
338
- const value = typeof source[strength] === "string" ? source[strength]?.trim() : "";
339
- if (value) normalized[strength] = value;
363
+ const normalized: ModelLadderConfig = { ...BUILTIN_MODEL_LADDERS[provider] };
364
+ const override = overrides?.[provider];
365
+ if (override) {
366
+ for (const strength of ["ultra", "strong", "medium", "light"] as const) {
367
+ const value = typeof override[strength] === "string" ? override[strength]?.trim() : "";
368
+ if (value) normalized[strength] = value;
369
+ }
340
370
  }
341
- if (Object.keys(normalized).length > 0) result[provider] = normalized;
371
+ result[provider] = normalized;
342
372
  }
343
- return Object.keys(result).length > 0 ? result : undefined;
373
+ return result;
344
374
  }
345
375
 
346
376
  function findStrengthForModelId(
@@ -402,12 +432,16 @@ export function rememberPreferredModel(model: ModelRef): RotationConfig {
402
432
  return writeRotationConfig({ preferredModel: model });
403
433
  }
404
434
 
435
+ // `readModelLadders()` always fills both providers from the builtin defaults, so this
436
+ // only returns undefined (never throws) in the defensive case where a rung is still
437
+ // genuinely missing; callers must treat that as a graceful "no fallback available" case
438
+ // rather than a config error to surface mid-turn.
405
439
  export function resolveFallbackTarget(
406
440
  currentProviderId: ManagedProviderId,
407
441
  currentModelId?: string,
408
442
  config = readRotationConfig(),
409
443
  currentThinkingLevel?: string,
410
- ): FallbackTarget {
444
+ ): FallbackTarget | undefined {
411
445
  const ladders = readModelLadders();
412
446
  const defaultStrength = config.defaultFallbackStrength ?? DEFAULT_FALLBACK_STRENGTH;
413
447
  const sourceStrength = findStrengthForModelId(currentProviderId, currentModelId, defaultStrength, ladders, currentThinkingLevel);
@@ -417,7 +451,7 @@ export function resolveFallbackTarget(
417
451
  const candidates = strength === defaultStrength ? [strength] : [strength, defaultStrength];
418
452
  const fallbackRef = candidates.map((candidate) => targetLadder?.[candidate]).find((ref): ref is string => typeof ref === "string" && ref.trim().length > 0);
419
453
  if (!fallbackRef) {
420
- throw new Error(`Unable to resolve fallback model for strength ${strength}; configure a ${PROVIDERS[targetProvider].ladderProviderId} ladder in ~/.crouter/config.json`);
454
+ return undefined;
421
455
  }
422
456
  const parsed = splitModelRef(fallbackRef);
423
457
  const resolvedStrength = candidates.find((candidate) => targetLadder?.[candidate] === fallbackRef) ?? strength;
@@ -458,6 +492,7 @@ export async function switchToFallbackIfPossible(
458
492
  rememberPreferredModel(preferredModel);
459
493
  const currentThinkingLevel = piApi.getThinkingLevel?.();
460
494
  const target = resolveFallbackTarget(preferredModel.providerId, preferredModel.modelId, readRotationConfig(), currentThinkingLevel);
495
+ if (!target) return undefined;
461
496
  const current = getCurrentModelRef(ctx.model);
462
497
  const model = ctx.modelRegistry.find(target.providerId, target.modelId);
463
498
  if (!model) return undefined;
@@ -471,9 +506,11 @@ export async function switchToFallbackIfPossible(
471
506
 
472
507
  export function formatStatusLine(providerId: ManagedProviderId, now = Date.now()): string {
473
508
  const pool = readSubscriptionPool(providerId);
474
- const fallback = resolveFallbackTarget(providerId, undefined, readRotationConfig());
475
509
  const ready = pool.filter((entry) => !entry.rateLimitedUntil || entry.rateLimitedUntil <= now);
476
510
  const label = getProviderLabel(providerId);
477
- if (ready.length === 0) return `${label} pool exhausted -> ${fallback.label}`;
511
+ if (ready.length === 0) {
512
+ const fallback = resolveFallbackTarget(providerId, undefined, readRotationConfig());
513
+ return fallback ? `${label} pool exhausted -> ${fallback.label}` : `${label} pool exhausted (no fallback configured)`;
514
+ }
478
515
  return `${label} ${ready[0]?.label ?? providerId} (${ready.length}/${pool.length} ready)`;
479
516
  }