instar 1.3.330 → 1.3.332

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 (54) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +145 -17
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/AnthropicSubscriptionRouter.d.ts +68 -0
  5. package/dist/core/AnthropicSubscriptionRouter.d.ts.map +1 -0
  6. package/dist/core/AnthropicSubscriptionRouter.js +82 -0
  7. package/dist/core/AnthropicSubscriptionRouter.js.map +1 -0
  8. package/dist/core/InteractivePoolIntelligenceProvider.d.ts +38 -0
  9. package/dist/core/InteractivePoolIntelligenceProvider.d.ts.map +1 -0
  10. package/dist/core/InteractivePoolIntelligenceProvider.js +61 -0
  11. package/dist/core/InteractivePoolIntelligenceProvider.js.map +1 -0
  12. package/dist/core/LiveTailSource.d.ts +19 -0
  13. package/dist/core/LiveTailSource.d.ts.map +1 -1
  14. package/dist/core/LiveTailSource.js +21 -0
  15. package/dist/core/LiveTailSource.js.map +1 -1
  16. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  17. package/dist/core/PostUpdateMigrator.js +17 -0
  18. package/dist/core/PostUpdateMigrator.js.map +1 -1
  19. package/dist/core/intelligenceProviderFactory.d.ts +21 -0
  20. package/dist/core/intelligenceProviderFactory.d.ts.map +1 -1
  21. package/dist/core/intelligenceProviderFactory.js +24 -1
  22. package/dist/core/intelligenceProviderFactory.js.map +1 -1
  23. package/dist/core/types.d.ts +38 -0
  24. package/dist/core/types.d.ts.map +1 -1
  25. package/dist/core/types.js.map +1 -1
  26. package/dist/providers/adapters/anthropic-interactive-pool/config.d.ts +17 -0
  27. package/dist/providers/adapters/anthropic-interactive-pool/config.d.ts.map +1 -1
  28. package/dist/providers/adapters/anthropic-interactive-pool/config.js +1 -0
  29. package/dist/providers/adapters/anthropic-interactive-pool/config.js.map +1 -1
  30. package/dist/providers/adapters/anthropic-interactive-pool/pool.d.ts +16 -2
  31. package/dist/providers/adapters/anthropic-interactive-pool/pool.d.ts.map +1 -1
  32. package/dist/providers/adapters/anthropic-interactive-pool/pool.js +95 -5
  33. package/dist/providers/adapters/anthropic-interactive-pool/pool.js.map +1 -1
  34. package/dist/providers/bootRegistration.d.ts +83 -0
  35. package/dist/providers/bootRegistration.d.ts.map +1 -0
  36. package/dist/providers/bootRegistration.js +158 -0
  37. package/dist/providers/bootRegistration.js.map +1 -0
  38. package/dist/providers/costAwareRouting.d.ts +16 -0
  39. package/dist/providers/costAwareRouting.d.ts.map +1 -1
  40. package/dist/providers/costAwareRouting.js +37 -21
  41. package/dist/providers/costAwareRouting.js.map +1 -1
  42. package/dist/scaffold/templates.d.ts.map +1 -1
  43. package/dist/scaffold/templates.js +5 -0
  44. package/dist/scaffold/templates.js.map +1 -1
  45. package/dist/server/routes.d.ts.map +1 -1
  46. package/dist/server/routes.js +26 -1
  47. package/dist/server/routes.js.map +1 -1
  48. package/package.json +1 -1
  49. package/src/data/builtin-manifest.json +63 -63
  50. package/src/scaffold/templates.ts +5 -0
  51. package/upgrades/1.3.331.md +77 -0
  52. package/upgrades/1.3.332.md +42 -0
  53. package/upgrades/side-effects/livetail-stale-signal.md +43 -0
  54. package/upgrades/side-effects/provider-substrate-live-wiring.md +145 -0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6SH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuxDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA4mRtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6SH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuxDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA4uRtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -2191,22 +2191,56 @@ export async function startServer(options) {
2191
2191
  // ELOCKED errors from concurrent agent startups are transient.
2192
2192
  console.log(pc.yellow(` Registry heartbeat failed to start (non-critical): ${err instanceof Error ? err.message : err}`));
2193
2193
  }
2194
- // Phase 5 — install the cost-aware routing policy on the global
2195
- // providers registry. The policy itself decides nothing today because
2196
- // no adapters are registered against the providers registry yet
2197
- // (adapter-registration at startup is tracked as a separate cycle —
2198
- // depends on per-machine credential discovery), but installing the
2199
- // policy now ensures any future call to `registry.resolve()` flows
2200
- // through the chain (CostAware FirstAvailable; PinHonoringPolicy
2201
- // pending recommended by the spec but not yet built) instead of
2202
- // defaulting to first-by-registration.
2194
+ // Phase 5 — register the Anthropic adapters and install the cost-aware
2195
+ // routing policy on the global providers registry. Registration is the
2196
+ // formerly-deferred "separate cycle" (src/providers/bootRegistration.ts):
2197
+ // gated (codex-only agents register nothing), idempotent, and LAZY (no
2198
+ // tmux/claude spawns at boot the pool only spawns on first use). With
2199
+ // adapters actually registered, `registry.resolve()` decisions are real,
2200
+ // and the policy's `readSdkCredit` is plumbed from the headless adapter's
2201
+ // UsageMeterProvider instead of the old `() => null` stub.
2203
2202
  //
2204
2203
  // Idempotent: only installs when no policy has been set yet on the
2205
2204
  // module-singleton registry. Re-entering `startServer` in the same
2206
2205
  // process (test harnesses, in-proc respawn) won't clobber a policy
2207
2206
  // a caller (test or production wiring) installed first.
2207
+ let anthropicRegistration = null;
2208
2208
  try {
2209
2209
  const { registry } = await import('../providers/registry.js');
2210
+ const { registerAnthropicAdapters } = await import('../providers/bootRegistration.js');
2211
+ // Scratch working dir for intelligence-pool sessions (context
2212
+ // decontamination — no project CLAUDE.md/MCP in judgment calls).
2213
+ const subscriptionPathConfig = config.intelligence?.subscriptionPath;
2214
+ const poolWorkdir = subscriptionPathConfig?.workingDirectory
2215
+ ?? path.join(config.stateDir, 'intelligence-pool');
2216
+ try {
2217
+ fs.mkdirSync(poolWorkdir, { recursive: true });
2218
+ }
2219
+ catch { /* spawn-time failure surfaces loudly */ }
2220
+ anthropicRegistration = await registerAnthropicAdapters({
2221
+ ...(config.enabledFrameworks ? { enabledFrameworks: config.enabledFrameworks } : {}),
2222
+ ...(config.sessions?.claudePath ? { claudePath: config.sessions.claudePath } : {}),
2223
+ ...(config.sessions?.tmuxPath ? { tmuxPath: config.sessions.tmuxPath } : {}),
2224
+ pool: {
2225
+ poolSize: subscriptionPathConfig?.poolSize ?? 2,
2226
+ // One model per pool; 'haiku' default keeps sentinel chatter off
2227
+ // the subscription's large-model quota (types.ts rationale).
2228
+ model: subscriptionPathConfig?.model ?? 'haiku',
2229
+ workingDirectory: poolWorkdir,
2230
+ // Agent-scoped prefix — pool.start()'s orphan recovery kills
2231
+ // stale `<prefix>-*` tmux sessions from a crashed previous
2232
+ // process, so the prefix MUST be unique per agent on a shared
2233
+ // machine (an unscoped prefix would reap another agent's pool).
2234
+ sessionPrefix: `instar-pool-${String(config.projectName ?? 'agent').toLowerCase().replace(/[^a-z0-9-]/g, '-')}`,
2235
+ },
2236
+ });
2237
+ if (anthropicRegistration.skippedReason) {
2238
+ console.log(pc.dim(` Providers registry: Anthropic adapters skipped (${anthropicRegistration.skippedReason})`));
2239
+ }
2240
+ else {
2241
+ const ids = [...anthropicRegistration.registered, ...anthropicRegistration.alreadyRegistered];
2242
+ console.log(pc.green(` Providers registry: ${ids.join(', ')} registered`));
2243
+ }
2210
2244
  // Read-only probe — `getRoutingPolicy` isn't on the public surface,
2211
2245
  // so we test by attempting a no-op resolve and seeing whether the
2212
2246
  // chain fires. Cheaper proxy: a private convention — set a marker
@@ -2222,10 +2256,10 @@ export async function startServer(options) {
2222
2256
  const { CostAwareRoutingPolicy } = await import('../providers/costAwareRouting.js');
2223
2257
  registry.setRoutingPolicy(new ChainPolicy([
2224
2258
  new CostAwareRoutingPolicy({
2225
- // Tier 3.C will plumb a real UsageMeterProvider here. Until
2226
- // then, `null` means "state unknown"policy falls to
2227
- // subscription floor (conservative).
2228
- readSdkCredit: async () => null,
2259
+ // Real credit reader from the headless adapter's usage meter
2260
+ // (TTL-cached; null = unknown → subscription floor). On a
2261
+ // skipped registration this stays a null-reader by contract.
2262
+ readSdkCredit: anthropicRegistration.readSdkCredit,
2229
2263
  sdkCreditAdapterId: 'anthropic-headless',
2230
2264
  subscriptionAdapterId: 'anthropic-interactive-pool',
2231
2265
  }),
@@ -2236,9 +2270,18 @@ export async function startServer(options) {
2236
2270
  }
2237
2271
  }
2238
2272
  catch (err) {
2239
- // Policy install is non-critical — sessions still resolve adapters
2240
- // via the registry's first-match-by-registration fallback.
2241
- console.log(pc.yellow(` Routing policy install failed (non-critical): ${err instanceof Error ? err.message : err}`));
2273
+ // Registration/policy install is non-critical — sessions still resolve
2274
+ // adapters via the registry's first-match-by-registration fallback.
2275
+ // But it IS a degradation: the June-15 subscription-path routing is
2276
+ // not live in this process, so report it rather than only logging.
2277
+ console.log(pc.yellow(` Providers registration/policy install failed (non-critical): ${err instanceof Error ? err.message : err}`));
2278
+ DegradationReporter.getInstance().report({
2279
+ feature: 'serverBoot.anthropicProviderRegistration',
2280
+ primary: 'both Anthropic adapters registered + cost-aware routing policy installed at boot',
2281
+ fallback: 'empty providers registry — internal LLM calls stay on the legacy claude -p path with no SDK-pot-vs-subscription routing',
2282
+ reason: `registration/policy install threw: ${err instanceof Error ? err.message : String(err)}`,
2283
+ impact: 'subscription-path routing (June-15 readiness) is unavailable for this server process until restart',
2284
+ });
2242
2285
  }
2243
2286
  // Warn if no auth token configured — server allows unauthenticated access
2244
2287
  if (!config.authToken) {
@@ -2659,6 +2702,10 @@ export async function startServer(options) {
2659
2702
  enabled: config.intelligence?.circuitBreaker?.enabled,
2660
2703
  openMs: config.intelligence?.circuitBreaker?.openMs,
2661
2704
  });
2705
+ // Hoisted out of the provider-build try block: the per-component
2706
+ // IntelligenceRouter below (outside that try) reuses the same
2707
+ // subscription-path option for its claude-code builds.
2708
+ let subscriptionPathOption;
2662
2709
  // Provider-portability v1.0.0: pick the IntelligenceProvider that
2663
2710
  // matches the configured framework. Defaults to claude-code for
2664
2711
  // backwards-compat; INSTAR_FRAMEWORK=codex-cli routes through Codex.
@@ -2719,9 +2766,55 @@ export async function startServer(options) {
2719
2766
  catch (err) {
2720
2767
  console.warn(`[server] TopicLocalModelStore failed to initialize: ${err}`);
2721
2768
  }
2769
+ // June-15 subscription-path routing (spec 04 Rule 1). Built ONCE here;
2770
+ // reused by the main provider below AND the per-component
2771
+ // IntelligenceRouter's claude-code builds, so a component routed to
2772
+ // claude-code while the default framework is codex still gets the
2773
+ // same SDK-pot-vs-subscription routing. Mode 'off'/unset ⇒ option
2774
+ // stays undefined ⇒ claude path byte-for-byte unchanged.
2775
+ const spMode = config.intelligence?.subscriptionPath?.mode ?? 'off';
2776
+ if ((spMode === 'auto' || spMode === 'force') && anthropicRegistration?.pool) {
2777
+ // (string | undefined, not `= null` — a `= null;` initializer inside
2778
+ // the preceding catch's 20-line scan window false-flags the unrelated
2779
+ // TopicLocalModelStore catch in no-silent-fallbacks.test.ts.)
2780
+ let lastRoutedPath;
2781
+ subscriptionPathOption = {
2782
+ mode: spMode,
2783
+ poolAdapter: anthropicRegistration.pool,
2784
+ readSdkCredit: anthropicRegistration.readSdkCredit,
2785
+ // Transition-only logging (reaper-audit pattern): a line when the
2786
+ // serving path CHANGES, not per call — ~1k internal calls/day must
2787
+ // not become 1k log lines.
2788
+ onRoute: (info) => {
2789
+ if (info.path !== lastRoutedPath) {
2790
+ lastRoutedPath = info.path;
2791
+ console.log(pc.gray(` [subscription-path] serving internal intelligence via ${info.path} (${info.reason})`));
2792
+ }
2793
+ },
2794
+ onDegrade: (info) => {
2795
+ try {
2796
+ DegradationReporter.getInstance().report({
2797
+ feature: 'AnthropicSubscriptionRouter',
2798
+ primary: `internal intelligence on ${info.from}`,
2799
+ fallback: `fell back to ${info.to}`,
2800
+ reason: info.reason,
2801
+ impact: `Internal LLM call${info.component ? ` (${info.component})` : ''} served by ${info.to} after ${info.from} failed.`,
2802
+ });
2803
+ }
2804
+ catch { /* never break the LLM path on a degradation report */ }
2805
+ },
2806
+ };
2807
+ console.log(pc.green(` Subscription-path routing: mode '${spMode}' (pool model: ${config.intelligence?.subscriptionPath?.model ?? 'haiku'})`));
2808
+ }
2809
+ else if (spMode !== 'off') {
2810
+ // Configured but unusable (codex-only gate, registration failure) —
2811
+ // say so loudly rather than silently running the SDK path.
2812
+ console.log(pc.yellow(` Subscription-path routing: mode '${spMode}' configured but the interactive-pool adapter is unavailable — internal calls stay on the default claude -p path`));
2813
+ }
2722
2814
  const built = buildIntelligenceProvider({
2723
2815
  framework,
2724
2816
  binaryPath: framework === 'claude-code' ? config.sessions.claudePath : undefined,
2817
+ ...(subscriptionPathOption ? { subscriptionPath: subscriptionPathOption } : {}),
2725
2818
  ...(framework === 'gemini-cli' && config.monitoring?.quotaTracking
2726
2819
  ? {
2727
2820
  quotaStateFile: config.monitoring.quotaStateFile
@@ -2768,7 +2861,16 @@ export async function startServer(options) {
2768
2861
  resolveConfig: () => config.sessions?.componentFrameworks,
2769
2862
  // Each non-default framework gets its OWN breaker → a Claude trip can't
2770
2863
  // pause Codex (the whole point). Default framework keeps the shared one.
2771
- buildProvider: (fw) => buildIP({ framework: fw, breaker: new LlmCircuitBreaker() }),
2864
+ // claude-code builds inherit the subscription-path routing so a
2865
+ // component routed to Claude under a codex default still honors
2866
+ // the June-15 SDK-pot-vs-subscription decision.
2867
+ buildProvider: (fw) => buildIP({
2868
+ framework: fw,
2869
+ breaker: new LlmCircuitBreaker(),
2870
+ ...(fw === 'claude-code' && subscriptionPathOption
2871
+ ? { subscriptionPath: subscriptionPathOption }
2872
+ : {}),
2873
+ }),
2772
2874
  onDegrade: (info) => {
2773
2875
  try {
2774
2876
  DegradationReporter.getInstance().report({
@@ -8958,6 +9060,18 @@ export async function startServer(options) {
8958
9060
  // topics with no new messages instead of rebuilding every topic's
8959
9061
  // history every tick (the 2026-06-05 event-loop-stall fix).
8960
9062
  getTopicVersion: (topic) => telegram.getTopicContentVersion(Number(topic)),
9063
+ // Eternal Sentinel condition 4 (P19): a topic whose standby copy has
9064
+ // been stale past the threshold surfaces ONCE per episode through the
9065
+ // standard degradation channel (housekeeping — never a user ping).
9066
+ reportStaleStandby: ({ topic, failingForMs, consecutiveFailures }) => {
9067
+ DegradationReporter.getInstance().report({
9068
+ feature: 'LiveTail.standbyFreshness',
9069
+ primary: 'Standby machine receives a fresh copy of each conversation tail',
9070
+ fallback: `Topic ${telegram.getTopicName?.(Number(topic)) ?? topic}'s standby copy is stale (flushes failing ~${Math.round(failingForMs / 60_000)}min, ${consecutiveFailures} consecutive); retries continue on capped backoff`,
9071
+ reason: 'Live-tail flushes to the standby peer are persistently rejected or unreachable',
9072
+ impact: 'A failover during this window would resume that conversation from an older tail (bounded by the outage start).',
9073
+ });
9074
+ },
8961
9075
  transport: sendTransport,
8962
9076
  logger: (m) => console.log(pc.dim(m)),
8963
9077
  });
@@ -10164,6 +10278,20 @@ export async function startServer(options) {
10164
10278
  return;
10165
10279
  _shuttingDown = true;
10166
10280
  console.log('\nShutting down...');
10281
+ // Dispose the interactive-pool adapter (kills its tmux REPL sessions
10282
+ // so they don't orphan). No-op when registration was skipped or the
10283
+ // pool never spawned (lazy). Must run before process exit — orphaned
10284
+ // pool sessions would silently keep drawing subscription quota.
10285
+ if (anthropicRegistration?.pool) {
10286
+ try {
10287
+ const { registry: providersRegistry } = await import('../providers/registry.js');
10288
+ await providersRegistry.unregister(anthropicRegistration.pool.id);
10289
+ console.log('[shutdown] Interactive-pool adapter disposed');
10290
+ }
10291
+ catch (err) {
10292
+ console.error('[shutdown] Interactive-pool dispose failed:', err);
10293
+ }
10294
+ }
10167
10295
  // Save resume UUIDs for ALL active topic-linked sessions before exit.
10168
10296
  // Without this, server restarts lose all resume mappings because:
10169
10297
  // 1. Resume entries are consumed (removed) on spawn