@wrongstack/core 0.63.4 → 0.68.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 (57) hide show
  1. package/dist/{agent-bridge-B5rxWrg3.d.ts → agent-bridge-D-j6OOBT.d.ts} +1 -1
  2. package/dist/agent-subagent-runner-DRZ9-NnR.d.ts +1042 -0
  3. package/dist/{compactor-0vjZ8KTk.d.ts → compactor-D_ExJajC.d.ts} +1 -1
  4. package/dist/{config-BdDuaZmB.d.ts → config--86aHSln.d.ts} +1 -1
  5. package/dist/{context-iFMEO2rN.d.ts → context-y87Jc5ei.d.ts} +3 -3
  6. package/dist/coordination/index.d.ts +12 -12
  7. package/dist/coordination/index.js +265 -275
  8. package/dist/coordination/index.js.map +1 -1
  9. package/dist/defaults/index.d.ts +22 -22
  10. package/dist/defaults/index.js +181 -180
  11. package/dist/defaults/index.js.map +1 -1
  12. package/dist/{events-k8CHjcrN.d.ts → events-CIplI98R.d.ts} +1 -1
  13. package/dist/execution/index.d.ts +16 -385
  14. package/dist/execution/index.js +124 -146
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/extension/index.d.ts +6 -6
  17. package/dist/goal-store-C7jcumEh.d.ts +96 -0
  18. package/dist/{index-Bc6BiP5q.d.ts → index-DKUvyTvV.d.ts} +28 -442
  19. package/dist/{index-CWdW_CJt.d.ts → index-b5uhfTSl.d.ts} +8 -8
  20. package/dist/index.d.ts +34 -32
  21. package/dist/index.js +692 -750
  22. package/dist/index.js.map +1 -1
  23. package/dist/infrastructure/index.d.ts +6 -6
  24. package/dist/kernel/index.d.ts +9 -9
  25. package/dist/{mcp-servers-CwqQDMYy.d.ts → mcp-servers-DwoNBf6r.d.ts} +3 -3
  26. package/dist/models/index.d.ts +2 -2
  27. package/dist/{multi-agent-coordinator-CNUJYq7U.d.ts → multi-agent-coordinator-CWnH-CiX.d.ts} +10 -2
  28. package/dist/{null-fleet-bus-DRoJ0uOY.d.ts → null-fleet-bus-CuN0ObJr.d.ts} +24 -31
  29. package/dist/observability/index.d.ts +2 -2
  30. package/dist/parallel-eternal-engine-0UwotoSx.d.ts +483 -0
  31. package/dist/{path-resolver-C5sPVne8.d.ts → path-resolver-DVkEcIw8.d.ts} +2 -2
  32. package/dist/{permission-Ld-i5ugf.d.ts → permission-C1A5whY5.d.ts} +5 -1
  33. package/dist/{permission-policy-CL-mPufp.d.ts → permission-policy-B2dK-T5N.d.ts} +19 -5
  34. package/dist/{plan-templates-ThBHOjaM.d.ts → plan-templates-Bprrzhbu.d.ts} +4 -4
  35. package/dist/{provider-runner-DJQa211J.d.ts → provider-runner-mXvXGSIw.d.ts} +3 -3
  36. package/dist/{retry-policy-BfBScewS.d.ts → retry-policy-CG3qvH_e.d.ts} +1 -1
  37. package/dist/sdd/index.d.ts +8 -8
  38. package/dist/sdd/index.js +123 -146
  39. package/dist/sdd/index.js.map +1 -1
  40. package/dist/security/index.d.ts +3 -3
  41. package/dist/security/index.js +31 -22
  42. package/dist/security/index.js.map +1 -1
  43. package/dist/{selector-DxhW7ML3.d.ts → selector-RvBR_YRW.d.ts} +1 -1
  44. package/dist/session-event-bridge-CDHxcmQU.d.ts +93 -0
  45. package/dist/{session-reader-q2ThszgG.d.ts → session-reader-BIpwM60D.d.ts} +1 -1
  46. package/dist/storage/index.d.ts +7 -6
  47. package/dist/{system-prompt-7LHyBbIf.d.ts → system-prompt-b61lOd49.d.ts} +2 -2
  48. package/dist/types/index.d.ts +23 -14
  49. package/dist/types/index.js.map +1 -1
  50. package/dist/utils/index.d.ts +2 -2
  51. package/dist/utils/index.js.map +1 -1
  52. package/package.json +1 -1
  53. package/skills/multi-agent/SKILL.md +0 -2
  54. package/dist/agent-subagent-runner-Zc3f37Sg.d.ts +0 -182
  55. package/dist/goal-store-iHltMi5n.d.ts +0 -188
  56. package/dist/multi-agent-SASYOrWA.d.ts +0 -554
  57. package/dist/tool-executor-CIjpGaRA.d.ts +0 -111
@@ -3014,15 +3014,22 @@ var SubagentBudget = class _SubagentBudget {
3014
3014
  void this.checkLimits();
3015
3015
  }
3016
3016
  /**
3017
- * Wall-clock budget check. Unlike other limits, timeout is always a hard stop
3018
- * wall-clock time cannot be "extended" by the coordinator, so it throws
3019
- * synchronously rather than entering the negotiation flow.
3017
+ * Wall-clock / idle budget check. Delegates to `checkLimits(elapsed)`, so
3018
+ * `timeout` and `idle_timeout` follow the SAME negotiation path as the other
3019
+ * kinds they are NOT a special-cased hard stop. This is deliberate: a
3020
+ * heartbeat-aware policy (see `attachAutoExtend` and `CollabSession`) grants
3021
+ * a timeout extension only while the agent is making progress and denies it
3022
+ * once the agent is genuinely stuck, which is safer than an unconditional
3023
+ * hard kill of a long-but-working agent. The runner translates the resulting
3024
+ * `BudgetThresholdSignal` decision (`extend` → patch limits in place,
3025
+ * `stop` → abort) just like every other kind.
3020
3026
  *
3021
- * Decision table:
3022
- * - no `onThreshold` handler → throw `BudgetExceededError`
3023
- * - `mode === 'sync'` → throw `BudgetExceededError`
3024
- * - `mode === 'auto'` + no listener → throw `BudgetExceededError`
3025
- * - `mode === 'auto'` + listener → throw `BudgetExceededError` (timeout is not extendable)
3027
+ * Decision table (same as `checkLimits`):
3028
+ * - no `onThreshold` handler → throw `BudgetExceededError` (hard stop)
3029
+ * - `mode === 'sync'` → throw `BudgetExceededError` (hard stop)
3030
+ * - `mode === 'auto'` + no listener → throw `BudgetExceededError` (no one to ask)
3031
+ * - `mode === 'auto'` + listener → throw `BudgetThresholdSignal` (negotiated;
3032
+ * a heartbeat-aware policy may extend the timeout)
3026
3033
  */
3027
3034
  checkTimeout() {
3028
3035
  if (this.startTime === null) return;
@@ -5553,6 +5560,71 @@ function providerStatusToCode(status, type) {
5553
5560
  if (status >= 500) return ERROR_CODES.PROVIDER_SERVER_ERROR;
5554
5561
  return ERROR_CODES.PROVIDER_INVALID_REQUEST;
5555
5562
  }
5563
+
5564
+ // src/coordination/coordinator/error-classifier.ts
5565
+ function classifySubagentError(err, hints = {}) {
5566
+ const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
5567
+ if (err instanceof ProviderError) {
5568
+ const baseMessage2 = err.describe();
5569
+ return providerErrorToSubagentError(err, baseMessage2, cause);
5570
+ }
5571
+ const baseMessage = err instanceof Error ? err.message : String(err);
5572
+ if (err instanceof BudgetExceededError) {
5573
+ const map = {
5574
+ iterations: "budget_iterations",
5575
+ tool_calls: "budget_tool_calls",
5576
+ tokens: "budget_tokens",
5577
+ cost: "budget_cost",
5578
+ timeout: "budget_timeout",
5579
+ idle_timeout: "budget_timeout"
5580
+ };
5581
+ return {
5582
+ kind: map[err.kind],
5583
+ message: baseMessage,
5584
+ retryable: false,
5585
+ cause
5586
+ };
5587
+ }
5588
+ if (hints.parentAborted) {
5589
+ return { kind: "aborted_by_parent", message: baseMessage, retryable: false, cause };
5590
+ }
5591
+ const lower = baseMessage.toLowerCase();
5592
+ if (/agent aborted$/i.test(baseMessage)) {
5593
+ return { kind: "aborted_by_parent", message: baseMessage, retryable: false, cause };
5594
+ }
5595
+ if (/agent exhausted iteration limit$/i.test(baseMessage)) {
5596
+ return { kind: "budget_iterations", message: baseMessage, retryable: false, cause };
5597
+ }
5598
+ if (/empty response$/i.test(baseMessage)) {
5599
+ return { kind: "empty_response", message: baseMessage, retryable: false, cause };
5600
+ }
5601
+ if (/^tool failed: /i.test(baseMessage)) {
5602
+ return { kind: "tool_failed", message: baseMessage, retryable: false, cause };
5603
+ }
5604
+ if (lower.includes("bridge transport") || /bridge.*(closed|disconnect)/i.test(baseMessage)) {
5605
+ return { kind: "bridge_failed", message: baseMessage, retryable: false, cause };
5606
+ }
5607
+ if (/context length|max.*tokens?.*exceeded|prompt is too long/i.test(baseMessage)) {
5608
+ return { kind: "context_overflow", message: baseMessage, retryable: false, cause };
5609
+ }
5610
+ return { kind: "unknown", message: baseMessage, retryable: false, cause };
5611
+ }
5612
+ function providerErrorToSubagentError(err, message, cause) {
5613
+ const status = err.status;
5614
+ if (status === 429 || err.body?.type === "rate_limit_error") {
5615
+ return { kind: "provider_rate_limit", message, retryable: true, backoffMs: 5e3, cause };
5616
+ }
5617
+ if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
5618
+ return { kind: "provider_auth", message, retryable: false, cause };
5619
+ }
5620
+ if (status === 408 || status === 0) {
5621
+ return { kind: "provider_timeout", message, retryable: true, cause };
5622
+ }
5623
+ if (status >= 500 && status < 600) {
5624
+ return { kind: "provider_5xx", message, retryable: true, backoffMs: 3e3, cause };
5625
+ }
5626
+ return { kind: "unknown", message, retryable: err.retryable, cause };
5627
+ }
5556
5628
  ({
5557
5629
  ...Object.fromEntries(
5558
5630
  ALL_AGENT_DEFINITIONS.map((d) => [d.config.role, d.config])
@@ -5710,7 +5782,10 @@ var NICKNAME_POOL = {
5710
5782
  "lavoisier": { name: "Lavoisier", domain: "chemistry" },
5711
5783
  "mendeleev": { name: "Mendeleev", domain: "chemistry" }
5712
5784
  };
5713
- var ALL_NICKNAMES = Object.values(NICKNAME_POOL);
5785
+ var ALL_NICKNAMES = Object.entries(NICKNAME_POOL);
5786
+ Object.fromEntries(
5787
+ ALL_NICKNAMES.map(([key, entry]) => [entry.name, key])
5788
+ );
5714
5789
  var DOMAIN_PREFERENCES = {
5715
5790
  "security": ["shannon", "turing", "lamarr", "stallman"],
5716
5791
  "bug-hunter": ["darwin", "curie", "feynman", "fermi"],
@@ -5743,17 +5818,16 @@ function assignNickname(role, used) {
5743
5818
  for (const key of preferences) {
5744
5819
  const entry = NICKNAME_POOL[key];
5745
5820
  if (entry && !used.has(key)) {
5746
- return `${entry.name} (${formatRole(role)})`;
5821
+ return { key, display: `${entry.name} (${formatRole(role)})` };
5747
5822
  }
5748
5823
  }
5749
- for (const entry of ALL_NICKNAMES) {
5750
- const key = Object.entries(NICKNAME_POOL).find(([, v]) => v.name === entry.name)?.[0];
5751
- if (key && !used.has(key)) {
5752
- return `${entry.name} (${formatRole(role)})`;
5824
+ for (const [key, entry] of ALL_NICKNAMES) {
5825
+ if (!used.has(key)) {
5826
+ return { key, display: `${entry.name} (${formatRole(role)})` };
5753
5827
  }
5754
5828
  }
5755
5829
  const counter = used.size + 1;
5756
- return `Scientist #${counter} (${formatRole(role)})`;
5830
+ return { key: `scientist-${counter}`, display: `Scientist #${counter} (${formatRole(role)})` };
5757
5831
  }
5758
5832
  function formatRole(role) {
5759
5833
  return role.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
@@ -5840,11 +5914,10 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
5840
5914
  const name = subagent.name?.trim() ?? "";
5841
5915
  const isPlaceholder = name === "" || name.toLowerCase() === role.toLowerCase() || name === "subagent" || name === "adhoc" || name === "generic" || /^slot-/.test(name);
5842
5916
  if (!isPlaceholder) return subagent;
5843
- const nickname = assignNickname(role, this.usedNicknames);
5844
- const baseKey = nickname.split(" ")[0].toLowerCase().replace(/[^a-z0-9-]/g, "-");
5845
- this.usedNicknames.add(baseKey);
5846
- this.subagentNicknames.set(subagentId, baseKey);
5847
- return { ...subagent, name: nickname };
5917
+ const { key, display } = assignNickname(role, this.usedNicknames);
5918
+ this.usedNicknames.add(key);
5919
+ this.subagentNicknames.set(subagentId, key);
5920
+ return { ...subagent, name: display };
5848
5921
  }
5849
5922
  async spawn(subagent) {
5850
5923
  const id = subagent.id || randomUUID();
@@ -6096,23 +6169,32 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
6096
6169
  */
6097
6170
  drainPendingAsAborted(message) {
6098
6171
  const dropped = this.pendingTasks.splice(0, this.pendingTasks.length);
6099
- for (const t of dropped) {
6100
- const synthetic = {
6101
- subagentId: t.subagentId ?? "unassigned",
6102
- taskId: t.id,
6103
- status: "stopped",
6104
- error: {
6105
- kind: "aborted_by_parent",
6106
- message,
6107
- retryable: false
6108
- },
6109
- iterations: 0,
6110
- toolCalls: 0,
6111
- durationMs: 0
6112
- };
6113
- this.completedResults.push(synthetic);
6114
- this.emit("task.completed", { task: t, result: synthetic });
6115
- }
6172
+ for (const t of dropped) this.emitPendingAborted(t, message);
6173
+ }
6174
+ /**
6175
+ * Emit a synthetic `stopped`/`aborted_by_parent` completion for a single
6176
+ * PENDING task — one that was never counted in `inFlight`. This MUST bypass
6177
+ * `recordCompletion`: that path does `inFlight--`, which for a pending task
6178
+ * steals a decrement from a genuinely in-flight task and trips the underflow
6179
+ * guard — suppressing that real task's `task.completed` and hanging its
6180
+ * `awaitTasks()` caller. Pushes the result and fires the event directly.
6181
+ */
6182
+ emitPendingAborted(task, message) {
6183
+ const synthetic = {
6184
+ subagentId: task.subagentId ?? "unassigned",
6185
+ taskId: task.id,
6186
+ status: "stopped",
6187
+ error: {
6188
+ kind: "aborted_by_parent",
6189
+ message,
6190
+ retryable: false
6191
+ },
6192
+ iterations: 0,
6193
+ toolCalls: 0,
6194
+ durationMs: 0
6195
+ };
6196
+ this.completedResults.push(synthetic);
6197
+ this.emit("task.completed", { task, result: synthetic });
6116
6198
  }
6117
6199
  async runDispatched(subagentId, task) {
6118
6200
  const subagent = this.subagents.get(subagentId);
@@ -6373,20 +6455,10 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
6373
6455
  const orphaned = this.pendingTasks.filter((t) => t.subagentId === subagentId);
6374
6456
  this.pendingTasks = this.pendingTasks.filter((t) => t.subagentId !== subagentId);
6375
6457
  for (const t of orphaned) {
6376
- const synthetic = {
6377
- subagentId,
6378
- taskId: t.id,
6379
- status: "stopped",
6380
- error: {
6381
- kind: "aborted_by_parent",
6382
- message: `Subagent "${subagentId}" was removed while task "${t.id}" was pending`,
6383
- retryable: false
6384
- },
6385
- iterations: 0,
6386
- toolCalls: 0,
6387
- durationMs: 0
6388
- };
6389
- this.recordCompletion(synthetic);
6458
+ this.emitPendingAborted(
6459
+ t,
6460
+ `Subagent "${subagentId}" was removed while task "${t.id}" was pending`
6461
+ );
6390
6462
  }
6391
6463
  this.fleetBus?.emit({
6392
6464
  subagentId,
@@ -6406,101 +6478,6 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
6406
6478
  return false;
6407
6479
  }
6408
6480
  };
6409
- function classifySubagentError(err, hints = {}) {
6410
- const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
6411
- if (err instanceof ProviderError) {
6412
- const baseMessage2 = err.describe();
6413
- return providerErrorToSubagentError(err, baseMessage2, cause);
6414
- }
6415
- const baseMessage = err instanceof Error ? err.message : String(err);
6416
- if (err instanceof BudgetExceededError) {
6417
- const map = {
6418
- iterations: "budget_iterations",
6419
- tool_calls: "budget_tool_calls",
6420
- tokens: "budget_tokens",
6421
- cost: "budget_cost",
6422
- timeout: "budget_timeout",
6423
- idle_timeout: "budget_timeout"
6424
- };
6425
- return {
6426
- kind: map[err.kind],
6427
- message: baseMessage,
6428
- // Budgets are user-configured ceilings, not transient failures —
6429
- // retrying with the same budget will hit the same ceiling. The
6430
- // orchestrator must raise the budget or narrow the task first.
6431
- retryable: false,
6432
- cause
6433
- };
6434
- }
6435
- if (hints.parentAborted) {
6436
- return {
6437
- kind: "aborted_by_parent",
6438
- message: baseMessage,
6439
- retryable: false,
6440
- cause
6441
- };
6442
- }
6443
- const lower = baseMessage.toLowerCase();
6444
- if (/agent aborted$/i.test(baseMessage)) {
6445
- return {
6446
- kind: "aborted_by_parent",
6447
- message: baseMessage,
6448
- retryable: false,
6449
- cause
6450
- };
6451
- }
6452
- if (/agent exhausted iteration limit$/i.test(baseMessage)) {
6453
- return { kind: "budget_iterations", message: baseMessage, retryable: false, cause };
6454
- }
6455
- if (/empty response$/i.test(baseMessage)) {
6456
- return { kind: "empty_response", message: baseMessage, retryable: false, cause };
6457
- }
6458
- if (/^tool failed: /i.test(baseMessage)) {
6459
- return { kind: "tool_failed", message: baseMessage, retryable: false, cause };
6460
- }
6461
- if (lower.includes("bridge transport") || /bridge.*(closed|disconnect)/i.test(baseMessage)) {
6462
- return { kind: "bridge_failed", message: baseMessage, retryable: false, cause };
6463
- }
6464
- if (/context length|max.*tokens?.*exceeded|prompt is too long/i.test(baseMessage)) {
6465
- return { kind: "context_overflow", message: baseMessage, retryable: false, cause };
6466
- }
6467
- return {
6468
- kind: "unknown",
6469
- message: baseMessage,
6470
- retryable: false,
6471
- cause
6472
- };
6473
- }
6474
- function providerErrorToSubagentError(err, message, cause) {
6475
- const status = err.status;
6476
- if (status === 429 || err.body?.type === "rate_limit_error") {
6477
- return {
6478
- kind: "provider_rate_limit",
6479
- message,
6480
- retryable: true,
6481
- // Conservative default: 5s. Provider-specific code can override
6482
- // by emitting an error whose body carries an explicit hint.
6483
- backoffMs: 5e3,
6484
- cause
6485
- };
6486
- }
6487
- if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
6488
- return { kind: "provider_auth", message, retryable: false, cause };
6489
- }
6490
- if (status === 408 || status === 0) {
6491
- return { kind: "provider_timeout", message, retryable: true, cause };
6492
- }
6493
- if (status >= 500 && status < 600) {
6494
- return {
6495
- kind: "provider_5xx",
6496
- message,
6497
- retryable: true,
6498
- backoffMs: 3e3,
6499
- cause
6500
- };
6501
- }
6502
- return { kind: "unknown", message, retryable: err.retryable, cause };
6503
- }
6504
6481
 
6505
6482
  // src/execution/parallel-eternal-engine.ts
6506
6483
  function sleep2(ms) {
@@ -6764,6 +6741,7 @@ ${personaLine}Task: ${task}
6764
6741
  } catch {
6765
6742
  results = coordinator.results().slice(-taskIds.length);
6766
6743
  }
6744
+ await Promise.allSettled(subagentIds.map((id) => coordinator.remove(id)));
6767
6745
  const allSuccessful = results.length > 0 && results.every((r) => r.status === "success");
6768
6746
  const goalComplete = results.some(
6769
6747
  (r) => r.status === "success" && typeof r.result === "string" && GOAL_COMPLETE_MARKER2.test(r.result)