@wrongstack/core 0.9.19 → 0.10.0

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 (73) hide show
  1. package/README.md +37 -33
  2. package/dist/{agent-bridge-DMVOX0cF.d.ts → agent-bridge-DBBGP5O4.d.ts} +1 -1
  3. package/dist/{agent-subagent-runner-C4qt9e5Y.d.ts → agent-subagent-runner-KwufTWwn.d.ts} +3 -4
  4. package/dist/compactor-D1RHFRmF.d.ts +41 -0
  5. package/dist/{config-CWva0qoL.d.ts → config-CJXBka2r.d.ts} +38 -2
  6. package/dist/{context-BRNbHmRM.d.ts → context-7u93AcGD.d.ts} +140 -0
  7. package/dist/coordination/index.d.ts +13 -13
  8. package/dist/coordination/index.js +786 -200
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/{default-config-Uzla85H-.d.ts → default-config-DEXI4jsl.d.ts} +10 -1
  11. package/dist/defaults/index.d.ts +24 -24
  12. package/dist/defaults/index.js +1612 -528
  13. package/dist/defaults/index.js.map +1 -1
  14. package/dist/{events-CiG9qUM_.d.ts → events-Bw1K5E6K.d.ts} +49 -1
  15. package/dist/execution/index.d.ts +46 -32
  16. package/dist/execution/index.js +663 -169
  17. package/dist/execution/index.js.map +1 -1
  18. package/dist/extension/index.d.ts +6 -6
  19. package/dist/extension/index.js.map +1 -1
  20. package/dist/goal-store-BeRsj7YX.d.ts +188 -0
  21. package/dist/{index-p95HQ22A.d.ts → index-DIt5TIaF.d.ts} +8 -8
  22. package/dist/{index-aizK8olO.d.ts → index-DgQWnZxP.d.ts} +11 -8
  23. package/dist/index.d.ts +338 -41
  24. package/dist/index.js +2747 -787
  25. package/dist/index.js.map +1 -1
  26. package/dist/infrastructure/index.d.ts +6 -6
  27. package/dist/infrastructure/index.js +36 -0
  28. package/dist/infrastructure/index.js.map +1 -1
  29. package/dist/kernel/index.d.ts +9 -9
  30. package/dist/kernel/index.js +57 -8
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mcp-servers-BkVEqkRe.d.ts → mcp-servers-BgINZzuo.d.ts} +25 -3
  33. package/dist/models/index.d.ts +3 -3
  34. package/dist/models/index.js +164 -11
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/models-registry-gwMAo6E3.d.ts +86 -0
  37. package/dist/{multi-agent-3ZnTB1aT.d.ts → multi-agent-C1O8EFzb.d.ts} +77 -24
  38. package/dist/{multi-agent-coordinator-bRaI_aD1.d.ts → multi-agent-coordinator-DoVSBFNx.d.ts} +20 -2
  39. package/dist/{null-fleet-bus-DKM3Iy9d.d.ts → null-fleet-bus-T-s3JaOt.d.ts} +413 -110
  40. package/dist/observability/index.d.ts +2 -2
  41. package/dist/{path-resolver-TcJfc29Y.d.ts → path-resolver-BfyK-I7w.d.ts} +2 -2
  42. package/dist/{permission-bPuzAy4x.d.ts → permission-B6sldrSp.d.ts} +1 -1
  43. package/dist/{permission-policy-BUQSutpl.d.ts → permission-policy-CtNscWOA.d.ts} +10 -9
  44. package/dist/{plan-templates-fkQTyz3U.d.ts → plan-templates-BWs6Je7j.d.ts} +8 -8
  45. package/dist/{provider-runner-BEpikbbN.d.ts → provider-runner-BmPe2RuU.d.ts} +3 -3
  46. package/dist/{retry-policy-BYkq0ugs.d.ts → retry-policy-KF18W4dg.d.ts} +1 -1
  47. package/dist/sdd/index.d.ts +9 -10
  48. package/dist/sdd/index.js +350 -122
  49. package/dist/sdd/index.js.map +1 -1
  50. package/dist/security/index.d.ts +65 -4
  51. package/dist/security/index.js +67 -19
  52. package/dist/security/index.js.map +1 -1
  53. package/dist/{selector-pox8abg0.d.ts → selector-DmXxpFyM.d.ts} +1 -1
  54. package/dist/{session-reader-CSWcb5Ga.d.ts → session-reader-CCSBfQmd.d.ts} +2 -2
  55. package/dist/skills/index.d.ts +1 -1
  56. package/dist/skills/index.js +1 -1
  57. package/dist/skills/index.js.map +1 -1
  58. package/dist/storage/index.d.ts +392 -8
  59. package/dist/storage/index.js +796 -40
  60. package/dist/storage/index.js.map +1 -1
  61. package/dist/{system-prompt-Bs-Wliab.d.ts → system-prompt-CM6zOhd2.d.ts} +19 -1
  62. package/dist/{tool-executor-Boo3dekH.d.ts → tool-executor-D7RxLtg4.d.ts} +9 -4
  63. package/dist/types/index.d.ts +16 -16
  64. package/dist/types/index.js +404 -14
  65. package/dist/types/index.js.map +1 -1
  66. package/dist/utils/index.d.ts +40 -8
  67. package/dist/utils/index.js +127 -57
  68. package/dist/utils/index.js.map +1 -1
  69. package/dist/{wstack-paths-BCgmTNlG.d.ts → wstack-paths-eMXnY1_X.d.ts} +8 -0
  70. package/package.json +1 -1
  71. package/dist/compactor-DVTKL7XD.d.ts +0 -23
  72. package/dist/goal-store-C7jcumEh.d.ts +0 -96
  73. package/dist/models-registry-OG_30xqZ.d.ts +0 -46
@@ -0,0 +1,86 @@
1
+ import { b as ModelsRegistry, M as ModelsDevPayload, c as ResolvedProvider, R as ResolvedModel, W as WireFamily } from './models-registry-BcYJDKLm.js';
2
+
3
+ interface DefaultModelsRegistryOptions {
4
+ cacheFile: string;
5
+ url?: string;
6
+ ttlSeconds?: number;
7
+ fetchImpl?: typeof fetch;
8
+ /** Pre-seeded payload — useful for offline scenarios and tests. */
9
+ seed?: ModelsDevPayload;
10
+ /**
11
+ * Maximum age in seconds for stale cache fallback when network fails.
12
+ * Defaults to 7 days. Set to `Infinity` for full offline resilience
13
+ * (risk: deprecated models, wrong pricing). Set to `0` to disable
14
+ * stale fallback entirely.
15
+ */
16
+ maxStaleAgeSeconds?: number;
17
+ /**
18
+ * Curated override payload deep-merged ON TOP of the models.dev base via
19
+ * `mergeModelsPayload` — adds providers/models the base lacks and overrides
20
+ * fields it gets wrong. Resolution order (first non-empty wins): this
21
+ * in-memory `overlay` → `overlayUrl` (fetched, cached) → `overlayFile`
22
+ * (bundled, read from disk). A missing/broken overlay degrades to `{}` and
23
+ * never throws, so the base alone still works.
24
+ */
25
+ overlay?: ModelsDevPayload;
26
+ /** GitHub-raw (or any) URL serving the curated overlay `providers.json`. */
27
+ overlayUrl?: string;
28
+ /** Path to the bundled overlay `providers.json` (offline floor). */
29
+ overlayFile?: string;
30
+ /** Cache file for the fetched `overlayUrl`. Defaults next to `cacheFile`. */
31
+ overlayCacheFile?: string;
32
+ }
33
+ declare function classifyFamily(npm: string | undefined): WireFamily;
34
+ declare class DefaultModelsRegistry implements ModelsRegistry {
35
+ /** Merged (base + overlay) payload — what every reader sees. */
36
+ private payload?;
37
+ /** Memoised overlay payload (in-memory / fetched / file). */
38
+ private overlayPayload?;
39
+ private fetchedAt?;
40
+ private readonly cacheFile;
41
+ private readonly url;
42
+ private readonly ttlMs;
43
+ private readonly fetchImpl;
44
+ private readonly seed?;
45
+ private readonly maxStaleAgeMs;
46
+ private readonly overlay?;
47
+ private readonly overlayUrl?;
48
+ private readonly overlayFile?;
49
+ private readonly overlayCacheFile?;
50
+ constructor(opts: DefaultModelsRegistryOptions);
51
+ load(opts?: {
52
+ force?: boolean;
53
+ }): Promise<ModelsDevPayload>;
54
+ /**
55
+ * Load the models.dev base payload: fresh cache → network → stale cache.
56
+ * On total failure, degrade to `{}` (so a non-empty overlay still drives
57
+ * the catalog) rather than throwing — unless there's no curated overlay to
58
+ * fall back on, in which case the original error propagates so pure-
59
+ * models.dev setups still surface the problem.
60
+ */
61
+ private loadBase;
62
+ /** Fetch + cache the models.dev base. Throws on failure (used by `refresh`). */
63
+ private refreshBase;
64
+ /**
65
+ * Resolve the curated overlay, memoised. Order: in-memory `overlay` →
66
+ * fetched `overlayUrl` (cached, same TTL/stale rules) → `overlayFile` on
67
+ * disk. Never throws — a missing/broken overlay yields `{}`.
68
+ */
69
+ private loadOverlay;
70
+ private loadOverlayFromUrl;
71
+ private readOverlayFile;
72
+ refresh(): Promise<ModelsDevPayload>;
73
+ listProviders(): Promise<ResolvedProvider[]>;
74
+ getProvider(id: string): Promise<ResolvedProvider | undefined>;
75
+ getModel(providerId: string, modelId: string): Promise<ResolvedModel | undefined>;
76
+ suggestModel(providerId: string): Promise<string | undefined>;
77
+ ageSeconds(): Promise<number>;
78
+ private resolveProvider;
79
+ private isFresh;
80
+ private isWithinMaxStaleAge;
81
+ private readCacheAt;
82
+ /** Used by `wstack models refresh` to expose where the cache lives. */
83
+ cacheLocation(): string;
84
+ }
85
+
86
+ export { DefaultModelsRegistry as D, type DefaultModelsRegistryOptions as a, classifyFamily as c };
@@ -1,5 +1,5 @@
1
- import { $ as Usage } from './context-BRNbHmRM.js';
2
- import { E as EventBus } from './events-CiG9qUM_.js';
1
+ import { $ as Usage } from './context-7u93AcGD.js';
2
+ import { E as EventBus } from './events-Bw1K5E6K.js';
3
3
 
4
4
  type BridgeMessageType = 'task' | 'result' | 'progress' | 'error' | 'heartbeat' | 'stop' | 'delegate' | 'budget_threshold';
5
5
  interface BridgeMessage<T = unknown> {
@@ -45,8 +45,21 @@ interface BudgetLimits {
45
45
  maxTokens?: number;
46
46
  /** Estimated USD cost ceiling. */
47
47
  maxCostUsd?: number;
48
- /** Wall-clock timeout from start() to checkTimeout(). */
48
+ /**
49
+ * Hard wall-clock timeout measured from `start()`. Off by default — set it
50
+ * explicitly only when a task must finish within an absolute window. For
51
+ * the everyday "don't kill an agent that's still working" guard, prefer
52
+ * `idleTimeoutMs`, which resets on activity.
53
+ */
49
54
  timeoutMs?: number;
55
+ /**
56
+ * Idle timeout: the maximum gap (ms) between activity signals (iterations,
57
+ * tool calls, token usage, streamed progress) before the subagent is
58
+ * considered hung and reaped. Unlike `timeoutMs`, an actively-working
59
+ * agent continuously resets this clock via `markActivity()`, so it never
60
+ * trips on a long-but-productive run — only on a genuine stall.
61
+ */
62
+ idleTimeoutMs?: number;
50
63
  }
51
64
  /**
52
65
  * Controls how the budget behaves when `onThreshold` is set and a limit is hit.
@@ -133,19 +146,16 @@ declare class SubagentBudget {
133
146
  private tokenOutput;
134
147
  private costUsd;
135
148
  private startTime;
136
- private _onThreshold;
137
149
  /**
138
- * Tracks which budget kinds currently have an extension request
139
- * in flight. While a kind is here, further `checkLimit` calls for the
140
- * same kind are no-ops without this dedup, every `recordIteration`
141
- * after the limit is reached spawns a fresh decision Promise (until
142
- * the first one lands and patches limits), flooding the FleetBus
143
- * with redundant threshold events. Cleared in `negotiateExtension`'s
144
- * `finally`.
150
+ * Timestamp of the most recent activity (iteration / tool call / token
151
+ * usage / streamed progress). Drives the idle timeout reset by
152
+ * `markActivity()`. Initialised to `start()` time so a never-active agent
153
+ * still eventually trips its idle window.
145
154
  */
146
- private readonly pendingExtensions;
155
+ private lastActivityTime;
156
+ private _onThreshold;
147
157
  /**
148
- * Hard cap on how long `negotiateExtension` waits for the coordinator to
158
+ * Hard cap on how long `_negotiateExtension` waits for the coordinator to
149
159
  * respond before defaulting to 'stop'. Without this fallback an absent
150
160
  * or hung listener (Director not built / event filter detached mid-run)
151
161
  * leaves the budget over-limit and never enforces anything.
@@ -176,6 +186,18 @@ declare class SubagentBudget {
176
186
  get mode(): BudgetNegotiationMode;
177
187
  constructor(limits?: BudgetLimits, mode?: BudgetNegotiationMode);
178
188
  start(): void;
189
+ /**
190
+ * Reset the idle clock. Called on any sign of forward progress —
191
+ * iterations, tool calls, token usage, and streamed tool/text progress —
192
+ * so a long-but-productive subagent never trips its `idleTimeoutMs`.
193
+ */
194
+ markActivity(): void;
195
+ /**
196
+ * Milliseconds since the last activity signal. Returns 0 before `start()`
197
+ * (nothing to measure yet). Used by the coordinator watchdog to decide
198
+ * whether to re-arm (still active) or reap (genuinely idle).
199
+ */
200
+ idleMs(): number;
179
201
  /** Returns true if we're within 10% of any limit — useful for pre-flight checks. */
180
202
  isNearLimit(): boolean;
181
203
  /**
@@ -189,31 +211,53 @@ declare class SubagentBudget {
189
211
  * - `mode === 'auto'` + no listener → throw `BudgetExceededError` (hard stop; no one to ask)
190
212
  * - `mode === 'auto'` + listener → throw `BudgetThresholdSignal` with async decision promise
191
213
  */
192
- private checkLimit;
214
+ /**
215
+ * Collects all exceeded budget kinds into a single NOOP-free negotiation.
216
+ * Called by recordIteration / recordToolCall / recordUsage — each may call
217
+ * this for its own kind. The first call starts the negotiation and stores
218
+ * the Promise in _pendingNegotiation. Subsequent calls for DIFFERENT
219
+ * kinds (while a negotiation is in flight) are NOOPs — they don't start
220
+ * new conversations with the coordinator. This prevents an EventBus flood
221
+ * when multiple budget kinds are exceeded simultaneously in one iteration.
222
+ *
223
+ * Returns the kinds that were found to be exceeded (for logging/debugging).
224
+ */
225
+ private checkLimits;
226
+ /**
227
+ * Per-kind in-flight negotiation Promises. Each budget kind can have its
228
+ * own concurrent negotiation — e.g. iterations and timeout can both
229
+ * be exceeded simultaneously without blocking each other. The same kind
230
+ * cannot start two concurrent negotiations (dedup guard).
231
+ * Cleared in `_negotiateExtension`'s `finally` block.
232
+ */
233
+ private _pendingNegotiations;
193
234
  /**
194
235
  * Drive the threshold handler to a decision. Resolves with `'stop'`
195
236
  * (signal the runner to abort) or `{ extend: ... }` (limits already
196
- * patched in-place; the runner should not abort). Always releases the
197
- * `pendingExtensions` slot in `finally`.
237
+ * patched in-place; the runner should not abort). Clears the
238
+ * per-kind slot in `_pendingNegotiations` in `finally`.
198
239
  *
199
240
  * The 'continue' return from a sync handler is treated as
200
241
  * `{ extend: {} }` — keep going without patching; next overrun fires
201
242
  * a fresh signal.
202
243
  */
203
- private negotiateExtension;
244
+ private _negotiateExtension;
204
245
  recordIteration(): void;
205
246
  recordToolCall(): void;
206
247
  recordUsage(usage: Usage, costUsd?: number): void;
207
248
  /**
208
- * Wall-clock budget check. Unlike other limits, timeout check passes through
209
- * `checkLimit` and is subject to the same negotiation-mode decision table.
210
- * In practice, `'sync'` mode (the usual test configuration) means a timeout
211
- * immediately throws `BudgetExceededError`. In production with a coordinator,
212
- * a timeout emits `budget.threshold_reached` so the Director can decide whether
213
- * to extend or abort.
249
+ * Wall-clock budget check. Unlike other limits, timeout is always a hard stop
250
+ * wall-clock time cannot be "extended" by the coordinator, so it throws
251
+ * synchronously rather than entering the negotiation flow.
252
+ *
253
+ * Decision table:
254
+ * - no `onThreshold` handler → throw `BudgetExceededError`
255
+ * - `mode === 'sync'` → throw `BudgetExceededError`
256
+ * - `mode === 'auto'` + no listener → throw `BudgetExceededError`
257
+ * - `mode === 'auto'` + listener → throw `BudgetExceededError` (timeout is not extendable)
214
258
  */
215
259
  checkTimeout(): void;
216
- /** Returns true if a timeout has occurred without throwing. Useful for races. */
260
+ /** Returns true if a wall-clock or idle timeout has occurred without throwing. */
217
261
  isTimedOut(): boolean;
218
262
  usage(): BudgetUsage;
219
263
  }
@@ -227,7 +271,15 @@ interface SubagentConfig {
227
271
  maxToolCalls?: number;
228
272
  maxTokens?: number;
229
273
  maxCostUsd?: number;
274
+ /** Hard wall-clock cap (ms) from start. Opt-in; prefer `idleTimeoutMs`. */
230
275
  timeoutMs?: number;
276
+ /**
277
+ * Idle timeout (ms): reap the subagent only after this long with no
278
+ * activity. Resets on every iteration / tool call / streamed progress, so
279
+ * an actively-working agent runs until its task naturally ends. This is the
280
+ * default reaper for delegated subagents (see `applyRosterBudget`).
281
+ */
282
+ idleTimeoutMs?: number;
231
283
  tools?: string[];
232
284
  model?: string;
233
285
  priority?: number;
@@ -391,6 +443,7 @@ interface MultiAgentConfig {
391
443
  maxTokens?: number;
392
444
  maxCostUsd?: number;
393
445
  timeoutMs?: number;
446
+ idleTimeoutMs?: number;
394
447
  };
395
448
  }
396
449
  interface SpawnResult {
@@ -1,5 +1,5 @@
1
- import { n as SubagentConfig, l as MultiAgentCoordinator, M as MultiAgentConfig, t as SubagentRunner, S as SpawnResult, v as TaskSpec, B as BridgeMessage, A as AgentBridge, k as CoordinatorStatus, u as TaskResult } from './multi-agent-3ZnTB1aT.js';
2
- import { F as FleetBus } from './agent-subagent-runner-C4qt9e5Y.js';
1
+ import { n as SubagentConfig, l as MultiAgentCoordinator, M as MultiAgentConfig, t as SubagentRunner, S as SpawnResult, v as TaskSpec, B as BridgeMessage, A as AgentBridge, k as CoordinatorStatus, u as TaskResult } from './multi-agent-C1O8EFzb.js';
2
+ import { F as FleetBus } from './agent-subagent-runner-KwufTWwn.js';
3
3
  import { EventEmitter } from 'node:events';
4
4
 
5
5
  /**
@@ -178,6 +178,15 @@ declare class DefaultMultiAgentCoordinator extends EventEmitter implements Multi
178
178
  private runner?;
179
179
  private fleetBus?;
180
180
  private readonly subagents;
181
+ /**
182
+ * Base nickname keys already handed out this run (e.g. `einstein`, `tesla`).
183
+ * Prevents two workers sharing a name. Direct `coordinator.spawn()` callers
184
+ * (parallel/eternal engine, SDD parallel run) don't go through
185
+ * `Director.spawn()` where nicknames are normally assigned, so the
186
+ * coordinator upgrades placeholder names ("Executor", "slot-ab12cd", role
187
+ * names) to memorable ones here — that's what surfaces in the fleet monitor.
188
+ */
189
+ private readonly usedNicknames;
181
190
  private pendingTasks;
182
191
  private completedResults;
183
192
  private totalIterations;
@@ -211,6 +220,15 @@ declare class DefaultMultiAgentCoordinator extends EventEmitter implements Multi
211
220
  * immediately tries to fill the freed slots from the pending queue.
212
221
  */
213
222
  setMaxConcurrent(n: number): void;
223
+ /**
224
+ * Upgrade a placeholder/role-derived name to a memorable scientist nickname
225
+ * (e.g. "Einstein (Executor)"). A name is treated as a placeholder when it is
226
+ * empty, equals the role (case-insensitive), is a generic default
227
+ * ("subagent"/"adhoc"/"generic"), or is an auto-generated `slot-…` id.
228
+ * Explicit, human-chosen names — including nicknames already assigned by
229
+ * `Director.spawn()` — are left untouched, so this never double-assigns.
230
+ */
231
+ private withNickname;
214
232
  spawn(subagent: SubagentConfig): Promise<SpawnResult>;
215
233
  assign(task: TaskSpec): Promise<void>;
216
234
  delegate(to: string, msg: BridgeMessage): Promise<void>;