@wrongstack/core 0.3.3 → 0.3.7

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 (52) hide show
  1. package/dist/{agent-bridge-C3DUGjSb.d.ts → agent-bridge-DaOnnHNW.d.ts} +1 -1
  2. package/dist/{compactor-DpJBI1YH.d.ts → compactor-CFky6JKM.d.ts} +1 -1
  3. package/dist/{config-D2qvAxVd.d.ts → config-RlhKLjme.d.ts} +2 -1
  4. package/dist/{context-IovtuTf8.d.ts → context-B1kBj1lY.d.ts} +4 -3
  5. package/dist/coordination/index.d.ts +12 -10
  6. package/dist/coordination/index.js +50 -9
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +16 -16
  9. package/dist/defaults/index.js +213 -17
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{events-BHIQs4o1.d.ts → events-BBaKeMfb.d.ts} +11 -1
  12. package/dist/execution/index.d.ts +11 -11
  13. package/dist/execution/index.js +54 -1
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/extension/index.d.ts +6 -6
  16. package/dist/{index-hWNybrNZ.d.ts → index-meJRuQtc.d.ts} +26 -5
  17. package/dist/index.d.ts +26 -26
  18. package/dist/index.js +306 -39
  19. package/dist/index.js.map +1 -1
  20. package/dist/infrastructure/index.d.ts +6 -6
  21. package/dist/kernel/index.d.ts +9 -9
  22. package/dist/kernel/index.js.map +1 -1
  23. package/dist/{mcp-servers-C2OopXOn.d.ts → mcp-servers-Cf4-bJnd.d.ts} +3 -3
  24. package/dist/models/index.d.ts +2 -2
  25. package/dist/models/index.js +1 -0
  26. package/dist/models/index.js.map +1 -1
  27. package/dist/{multi-agent-B9a6sflH.d.ts → multi-agent-D5m66hzB.d.ts} +1 -1
  28. package/dist/observability/index.d.ts +2 -2
  29. package/dist/{path-resolver--59rCou3.d.ts → path-resolver-Bg4OP5fi.d.ts} +2 -2
  30. package/dist/{provider-runner-B39miKRw.d.ts → provider-runner-CU9gnU2E.d.ts} +3 -3
  31. package/dist/sdd/index.d.ts +3 -3
  32. package/dist/secret-scrubber-DyUAWS09.d.ts +54 -0
  33. package/dist/{secret-scrubber-Cuy5afaQ.d.ts → secret-scrubber-Dyh5LVYL.d.ts} +1 -1
  34. package/dist/security/index.d.ts +58 -5
  35. package/dist/security/index.js +95 -6
  36. package/dist/security/index.js.map +1 -1
  37. package/dist/{selector-wT2fv9Fg.d.ts → selector-DBEiwXBk.d.ts} +1 -1
  38. package/dist/{session-reader-CcPi4BQ8.d.ts → session-reader-D-z0AgHs.d.ts} +1 -1
  39. package/dist/{skill-C_7znCIC.d.ts → skill-DayhFUBb.d.ts} +1 -1
  40. package/dist/storage/index.d.ts +5 -5
  41. package/dist/storage/index.js +53 -1
  42. package/dist/storage/index.js.map +1 -1
  43. package/dist/{system-prompt-Dk1qm8ey.d.ts → system-prompt-DNetCecu.d.ts} +1 -1
  44. package/dist/{tool-executor-HsBLGRaA.d.ts → tool-executor-B5bgmEgE.d.ts} +12 -5
  45. package/dist/types/index.d.ts +15 -15
  46. package/dist/types/index.js +59 -2
  47. package/dist/types/index.js.map +1 -1
  48. package/dist/utils/index.d.ts +23 -2
  49. package/dist/utils/index.js +41 -1
  50. package/dist/utils/index.js.map +1 -1
  51. package/package.json +1 -1
  52. package/dist/secret-scrubber-CgG2tV2B.d.ts +0 -31
@@ -1,35 +1,35 @@
1
1
  export { D as DefaultLogger, a as DefaultLoggerOptions } from '../logger-BH6AE0W9.js';
2
2
  export { AbandonedSession, AttachmentStoreOptions, ConfigLoaderOptions, ConfigMigration, ConfigMigrationError, ConfigSource, DEFAULT_CONFIG_MIGRATIONS, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultMemoryStore, DefaultSessionStore, DirectorStateCheckpoint, DirectorStateSnapshot, DirectorSubagentState, DirectorTaskState, MemoryStoreOptions, MigrationContext, MigrationResult, PersistedQueueItem, PlanFile, PlanItem, QueueStore, RecoveryLock, RecoveryLockOptions, SessionAnalyzer, SessionStoreOptions, TodosCheckpointFile, addPlanItem, attachPlanCheckpoint, attachTodosCheckpoint, clearPlan, emptyPlan, formatPlan, loadDirectorState, loadPlan, loadTodosCheckpoint, removePlanItem, runConfigMigrations, savePlan, saveTodosCheckpoint, setPlanItemStatus } from '../storage/index.js';
3
- export { D as DefaultSessionReader } from '../session-reader-CcPi4BQ8.js';
4
- export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-scrubber-Cuy5afaQ.js';
3
+ export { D as DefaultSessionReader } from '../session-reader-D-z0AgHs.js';
4
+ export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-scrubber-Dyh5LVYL.js';
5
5
  export { AutoApprovePermissionPolicy, DefaultPermissionPolicy, PermissionPolicyOptions } from '../security/index.js';
6
- export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-HsBLGRaA.js';
6
+ export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-B5bgmEgE.js';
7
7
  export { AutoCompactionMiddleware, AutonomousRunner, AutonomousRunnerOptions, DefaultSkillLoader, DoneCheckResult, DoneConditionChecker, IntelligentCompactor, IntelligentCompactorOptions, SelectiveCompactor, SelectiveCompactorOptions, SkillLoaderOptions } from '../execution/index.js';
8
- import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-B39miKRw.js';
9
- import { j as Response } from '../context-IovtuTf8.js';
8
+ import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-CU9gnU2E.js';
9
+ import { j as Response } from '../context-B1kBj1lY.js';
10
10
  export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AgentFactory, AgentFactoryResult, AgentRunnerOptions, BUG_HUNTER_AGENT, CreateDelegateToolOptions, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, DelegateHost, Director, DirectorBudgetError, DirectorPromptParts, DirectorSessionFactory, DirectorSessionFactoryOptions, FLEET_ROSTER, FleetBus, FleetEvent, FleetHandler, FleetUsage, FleetUsageAggregator, MultiAgentCoordinatorOptions, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, SubagentPromptParts, SubagentUsageSnapshot, composeDirectorPrompt, composeSubagentPrompt, createDelegateTool, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs } from '../coordination/index.js';
11
- export { n as BudgetExceededError, o as BudgetKind, p as BudgetLimits, q as BudgetUsage, r as SubagentBudget } from '../multi-agent-B9a6sflH.js';
12
- export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-C3DUGjSb.js';
11
+ export { n as BudgetExceededError, o as BudgetKind, p as BudgetLimits, q as BudgetUsage, r as SubagentBudget } from '../multi-agent-D5m66hzB.js';
12
+ export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-DaOnnHNW.js';
13
13
  export { D as DefaultModelsRegistry, a as DefaultModelsRegistryOptions, c as classifyFamily } from '../models-registry-DqzwpBQy.js';
14
14
  export { DefaultModeStore, LLMSelector, LLMSelectorOptions, ModeLoaderOptions, loadProjectModes, loadUserModes } from '../models/index.js';
15
15
  export { DefaultTaskStore, GeneratedTask, SpecDrivenDev, SpecDrivenDevOptions, SpecParser, TaskFlow, TaskFlowEventMap, TaskFlowEventName, TaskFlowExecutionContext, TaskFlowOptions, TaskFlowPhase, TaskGenerator, TaskGeneratorOptions, TaskStore, TaskTracker, TaskTrackerOptions, TaskTransition } from '../sdd/index.js';
16
16
  export { DefaultHealthRegistry, InMemoryMetricsSink, MetricsServerHandle, MetricsServerOptions, NoopMetricsSink, NoopTracer, OTelTracer, OtlpMetricsExporterHandle, OtlpMetricsExporterOptions, OtlpTraceExporterHandle, OtlpTraceExporterOptions, PROMETHEUS_CONTENT_TYPE, buildOtlpMetricsRequest, buildOtlpTracesRequest, renderPrometheus, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, wireMetricsToEvents } from '../observability/index.js';
17
- export { C as ContextManagerAction, a as ContextManagerInput, b as ContextManagerResult, c as ContextManagerToolOptions, d as allServers, e as awsServer, f as blockServer, g as braveSearchServer, h as context7Server, i as contextManagerTool, j as createContextManagerTool, k as everArtServer, l as filesystemServer, m as githubServer, n as googleMapsServer, o as miniMaxVisionServer, s as sentinelServer, p as slackServer, z as zaiVisionServer } from '../mcp-servers-C2OopXOn.js';
17
+ export { C as ContextManagerAction, a as ContextManagerInput, b as ContextManagerResult, c as ContextManagerToolOptions, d as allServers, e as awsServer, f as blockServer, g as braveSearchServer, h as context7Server, i as contextManagerTool, j as createContextManagerTool, k as everArtServer, l as filesystemServer, m as githubServer, n as googleMapsServer, o as miniMaxVisionServer, s as sentinelServer, p as slackServer, z as zaiVisionServer } from '../mcp-servers-Cf4-bJnd.js';
18
18
  import '../logger-BMQgxvdy.js';
19
- import '../events-BHIQs4o1.js';
19
+ import '../events-BBaKeMfb.js';
20
20
  import '../memory-CEXuo7sz.js';
21
21
  import '../wstack-paths-BGu2INTm.js';
22
- import '../config-D2qvAxVd.js';
22
+ import '../config-RlhKLjme.js';
23
23
  import '../models-registry-Y2xbog0E.js';
24
24
  import '../secret-vault-DoISxaKO.js';
25
- import '../secret-scrubber-CgG2tV2B.js';
25
+ import '../secret-scrubber-DyUAWS09.js';
26
26
  import '../input-reader-E-ffP2ee.js';
27
- import '../compactor-DpJBI1YH.js';
28
- import '../skill-C_7znCIC.js';
29
- import '../index-hWNybrNZ.js';
30
- import '../system-prompt-Dk1qm8ey.js';
27
+ import '../compactor-CFky6JKM.js';
28
+ import '../skill-DayhFUBb.js';
29
+ import '../index-meJRuQtc.js';
30
+ import '../system-prompt-DNetCecu.js';
31
31
  import '../observability-BhnVLBLS.js';
32
- import '../selector-wT2fv9Fg.js';
32
+ import '../selector-DBEiwXBk.js';
33
33
  import 'node:events';
34
34
  import '../mode-CV077NjV.js';
35
35
  import '../task-graph-BITvWt4t.js';
@@ -638,6 +638,7 @@ var QueueStore = class {
638
638
  } catch (err) {
639
639
  const code = err.code;
640
640
  if (code === "ENOENT") return [];
641
+ console.warn(`[QueueStore] failed to read queue file "${this.file}":`, err instanceof Error ? err.message : String(err));
641
642
  return [];
642
643
  }
643
644
  let parsed;
@@ -737,6 +738,13 @@ var DefaultAttachmentStore = class {
737
738
  return mergeAdjacentText(blocks);
738
739
  }
739
740
  async clear() {
741
+ if (this.spoolDir) {
742
+ const toDelete = [];
743
+ for (const att of this.items.values()) {
744
+ if (att.path) toDelete.push(att.path);
745
+ }
746
+ await Promise.all(toDelete.map((p) => fsp.unlink(p).catch(() => void 0)));
747
+ }
740
748
  this.items.clear();
741
749
  this.refs.length = 0;
742
750
  this.nextSeq = { text: 0, image: 0, file: 0 };
@@ -1480,6 +1488,42 @@ function defaultIsPidAlive(pid) {
1480
1488
  }
1481
1489
  }
1482
1490
 
1491
+ // src/utils/regex-guard.ts
1492
+ var MAX_PATTERN_LEN = 512;
1493
+ var DANGEROUS_PATTERNS = [
1494
+ /(\([^)]*[+*][^)]*\))[+*]/,
1495
+ // (a+)+, (.*)+, etc
1496
+ /(\(\?:[^)]*[+*][^)]*\))[+*]/
1497
+ // same, with non-capturing group
1498
+ ];
1499
+ function compileUserRegex(pattern, flags) {
1500
+ if (typeof pattern !== "string") {
1501
+ return { ok: false, reason: "pattern must be a string" };
1502
+ }
1503
+ if (pattern.length === 0) {
1504
+ return { ok: false, reason: "pattern is empty" };
1505
+ }
1506
+ if (pattern.length > MAX_PATTERN_LEN) {
1507
+ return { ok: false, reason: `pattern exceeds ${MAX_PATTERN_LEN} characters` };
1508
+ }
1509
+ for (const rx of DANGEROUS_PATTERNS) {
1510
+ if (rx.test(pattern)) {
1511
+ return {
1512
+ ok: false,
1513
+ reason: "pattern looks vulnerable to catastrophic backtracking \u2014 rewrite without nested quantifiers"
1514
+ };
1515
+ }
1516
+ }
1517
+ try {
1518
+ return { ok: true, regex: new RegExp(pattern, flags) };
1519
+ } catch (err) {
1520
+ return {
1521
+ ok: false,
1522
+ reason: err instanceof Error ? err.message : "invalid regex"
1523
+ };
1524
+ }
1525
+ }
1526
+
1483
1527
  // src/storage/session-reader.ts
1484
1528
  var DefaultSessionReader = class {
1485
1529
  store;
@@ -1574,7 +1618,11 @@ function buildMatcher(q) {
1574
1618
  const ci = q.caseInsensitive ?? true;
1575
1619
  if (q.regex) {
1576
1620
  const flags = ci ? "i" : "";
1577
- const re = new RegExp(q.query, flags);
1621
+ const compiled = compileUserRegex(q.query, flags);
1622
+ if (!compiled.ok) {
1623
+ throw new Error(`Invalid search regex "${q.query}": ${compiled.reason}`);
1624
+ }
1625
+ const re = compiled.regex;
1578
1626
  return (text) => {
1579
1627
  const m = re.exec(text);
1580
1628
  return m ? { start: m.index, end: m.index + m[0].length } : null;
@@ -2074,6 +2122,10 @@ var DirectorStateCheckpoint = class {
2074
2122
  this.timer = null;
2075
2123
  }
2076
2124
  await this.persist();
2125
+ if (this.rewriteRequested) {
2126
+ this.rewriteRequested = false;
2127
+ await this.persist();
2128
+ }
2077
2129
  }
2078
2130
  bumpUpdatedAt() {
2079
2131
  this.snapshot = { ...this.snapshot, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
@@ -2299,7 +2351,7 @@ function walk2(node, vault, transform) {
2299
2351
  if (Array.isArray(node)) {
2300
2352
  return node.map((item) => walk2(item, vault, transform));
2301
2353
  }
2302
- const out = {};
2354
+ const out = /* @__PURE__ */ Object.create(null);
2303
2355
  for (const [k, v] of Object.entries(node)) {
2304
2356
  if (typeof v === "string" && isSecretField2(k)) {
2305
2357
  out[k] = transform(v, k);
@@ -2410,7 +2462,11 @@ function getCachedGlob(pattern) {
2410
2462
  COMPILED_GLOB_CACHE.set(pattern, re);
2411
2463
  return re;
2412
2464
  }
2465
+ var MAX_GLOB_PATTERN_LEN = 1024;
2413
2466
  function compileGlob(pattern) {
2467
+ if (pattern.length > MAX_GLOB_PATTERN_LEN) {
2468
+ throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);
2469
+ }
2414
2470
  let i = 0;
2415
2471
  let re = "^";
2416
2472
  while (i < pattern.length) {
@@ -2469,12 +2525,49 @@ var DefaultPermissionPolicy = class {
2469
2525
  loaded = false;
2470
2526
  trustFile;
2471
2527
  yolo;
2528
+ /**
2529
+ * Session-scoped "soft deny" map. When the user presses 'n' (block once),
2530
+ * the tool+pattern is added here. If the LLM retries in the same session,
2531
+ * we return deny directly without asking again.
2532
+ *
2533
+ * Cleared on reload() since reload = fresh trust file snapshot.
2534
+ */
2535
+ sessionDenied = /* @__PURE__ */ new Map();
2536
+ /**
2537
+ * Session-scoped "soft trust" map. When the user presses 'a' (allow once),
2538
+ * the tool+pattern is added here. If the LLM retries in the same session,
2539
+ * we return auto directly without asking again.
2540
+ *
2541
+ * Cleared on reload().
2542
+ */
2543
+ sessionAllowed = /* @__PURE__ */ new Map();
2544
+ /**
2545
+ * Interactive prompt delegate. When set, `evaluate()` calls it to get a
2546
+ * user decision synchronously (CLI REPL path). When cleared (TUI / WebUI),
2547
+ * `evaluate()` returns `confirm` so the caller can emit
2548
+ * `tool.confirm_needed` for the UI layer to handle.
2549
+ *
2550
+ * Mutable so the host can switch from CLI-prompt to event-driven
2551
+ * confirmation at runtime (e.g. when `--goal` forces TUI mode after
2552
+ * the agent was already constructed).
2553
+ */
2472
2554
  promptDelegate;
2555
+ /** Pre-compiled wildcard patterns — rebuilt on reload for O(1) lookup. */
2556
+ wildcardEntries = [];
2473
2557
  constructor(opts) {
2474
2558
  this.trustFile = opts.trustFile;
2475
2559
  this.yolo = opts.yolo ?? false;
2476
2560
  this.promptDelegate = opts.promptDelegate;
2477
2561
  }
2562
+ /**
2563
+ * Replace (or clear) the interactive prompt delegate at runtime.
2564
+ * Used by the CLI to switch from inline prompts (REPL) to event-driven
2565
+ * confirmation (TUI) when the run mode is determined after the policy
2566
+ * was constructed (e.g. `--goal` auto-flipping to TUI).
2567
+ */
2568
+ setPromptDelegate(delegate) {
2569
+ this.promptDelegate = delegate;
2570
+ }
2478
2571
  async reload() {
2479
2572
  try {
2480
2573
  const raw = await fsp.readFile(this.trustFile, "utf8");
@@ -2483,13 +2576,26 @@ var DefaultPermissionPolicy = class {
2483
2576
  } catch {
2484
2577
  this.policy = {};
2485
2578
  }
2579
+ this.wildcardEntries = [];
2580
+ for (const [key, val] of Object.entries(this.policy)) {
2581
+ if (key.includes("*")) this.wildcardEntries.push({ pattern: key, value: val });
2582
+ }
2583
+ this.sessionDenied.clear();
2584
+ this.sessionAllowed.clear();
2486
2585
  this.loaded = true;
2487
2586
  }
2488
- async evaluate(tool, input, _ctx) {
2587
+ async evaluate(tool, input, ctx) {
2489
2588
  if (!this.loaded) await this.reload();
2490
2589
  const namespaceEntry = this.findNamespaceEntry(tool.name);
2491
2590
  const entry = this.policy[tool.name] ?? namespaceEntry;
2492
2591
  const subject = this.subjectFor(tool.name, input, tool.subjectKey);
2592
+ const subjectKey = `${tool.name}::${subject ?? tool.name}`;
2593
+ if (this.sessionDenied.has(subjectKey)) {
2594
+ return { permission: "deny", source: "deny", reason: "session soft deny (user pressed no)" };
2595
+ }
2596
+ if (this.sessionAllowed.has(subjectKey)) {
2597
+ return { permission: "auto", source: "trust", reason: "session soft allow (user pressed yes)" };
2598
+ }
2493
2599
  if (entry?.deny && subject && matchAny(entry.deny, subject)) {
2494
2600
  return { permission: "deny", source: "deny", reason: "matched deny pattern" };
2495
2601
  }
@@ -2505,6 +2611,11 @@ var DefaultPermissionPolicy = class {
2505
2611
  if (this.yolo) {
2506
2612
  return { permission: "auto", source: "yolo" };
2507
2613
  }
2614
+ if (tool.name === "write" && subject) {
2615
+ if (ctx.hasRead(subject)) {
2616
+ return { permission: "auto", source: "context", reason: "file already read in this session" };
2617
+ }
2618
+ }
2508
2619
  if (tool.permission === "auto") {
2509
2620
  return { permission: "auto", source: "default" };
2510
2621
  }
@@ -2515,6 +2626,7 @@ var DefaultPermissionPolicy = class {
2515
2626
  return { permission: "auto", source: "user", reason: "user always-allowed" };
2516
2627
  }
2517
2628
  if (decision === "deny") {
2629
+ await this.deny({ tool: tool.name, pattern: subject ?? tool.name });
2518
2630
  return { permission: "deny", source: "user", reason: "user denied" };
2519
2631
  }
2520
2632
  return { permission: decision === "yes" ? "auto" : "deny", source: "user" };
@@ -2537,6 +2649,31 @@ var DefaultPermissionPolicy = class {
2537
2649
  throw err;
2538
2650
  }
2539
2651
  }
2652
+ /** Persist a deny rule — this tool+pattern pair is permanently blocked. */
2653
+ async deny(rule) {
2654
+ if (!this.loaded) await this.reload();
2655
+ const entry = this.policy[rule.tool] ?? {};
2656
+ entry.deny = Array.from(/* @__PURE__ */ new Set([...entry.deny ?? [], rule.pattern]));
2657
+ this.policy[rule.tool] = entry;
2658
+ try {
2659
+ await atomicWrite(this.trustFile, JSON.stringify(this.policy, null, 2));
2660
+ } catch (err) {
2661
+ const existing = this.policy[rule.tool];
2662
+ if (existing?.deny) {
2663
+ const idx = existing.deny.indexOf(rule.pattern);
2664
+ if (idx !== -1) existing.deny.splice(idx, 1);
2665
+ }
2666
+ throw err;
2667
+ }
2668
+ }
2669
+ /** Block this tool+pattern for the rest of this session (no trust file). */
2670
+ denyOnce(rule) {
2671
+ this.sessionDenied.set(`${rule.tool}::${rule.pattern}`, true);
2672
+ }
2673
+ /** Auto-approve this tool+pattern for the rest of this session (no trust file). */
2674
+ allowOnce(rule) {
2675
+ this.sessionAllowed.set(`${rule.tool}::${rule.pattern}`, true);
2676
+ }
2540
2677
  subjectFor(toolName, input, subjectKey) {
2541
2678
  if (!input || typeof input !== "object") return void 0;
2542
2679
  const obj = input;
@@ -2564,10 +2701,8 @@ var DefaultPermissionPolicy = class {
2564
2701
  return void 0;
2565
2702
  }
2566
2703
  findNamespaceEntry(toolName) {
2567
- for (const key of Object.keys(this.policy)) {
2568
- if (key.includes("*") && matchGlob(key, toolName)) {
2569
- return this.policy[key];
2570
- }
2704
+ for (const { pattern, value } of this.wildcardEntries) {
2705
+ if (matchGlob(pattern, toolName)) return value;
2571
2706
  }
2572
2707
  return void 0;
2573
2708
  }
@@ -2581,6 +2716,12 @@ var AutoApprovePermissionPolicy = class {
2581
2716
  }
2582
2717
  async trust() {
2583
2718
  }
2719
+ async deny() {
2720
+ }
2721
+ denyOnce() {
2722
+ }
2723
+ allowOnce() {
2724
+ }
2584
2725
  async reload() {
2585
2726
  }
2586
2727
  };
@@ -4167,6 +4308,15 @@ var ToolExecutor = class {
4167
4308
  opts;
4168
4309
  serializer;
4169
4310
  iterationTimeoutMs;
4311
+ /**
4312
+ * Clear the interactive confirm awaiter so the executor returns
4313
+ * `ToolConfirmPendingResult` instead of blocking on stdin. Used by
4314
+ * the CLI to switch from inline prompts (REPL) to event-driven
4315
+ * confirmation (TUI) at runtime.
4316
+ */
4317
+ clearConfirmAwaiter() {
4318
+ this.opts.confirmAwaiter = void 0;
4319
+ }
4170
4320
  /**
4171
4321
  * Execute a batch of tool uses using the configured strategy.
4172
4322
  * Returns the execution results and the remaining output budget.
@@ -4419,7 +4569,15 @@ var ToolExecutor = class {
4419
4569
  var DoneConditionChecker = class {
4420
4570
  constructor(condition) {
4421
4571
  this.condition = condition;
4422
- this.compiledRegex = condition.type === "output_match" && condition.pattern ? new RegExp(condition.pattern) : null;
4572
+ if (condition.type === "output_match" && condition.pattern) {
4573
+ const result = compileUserRegex(condition.pattern, "");
4574
+ this.compiledRegex = result.ok ? result.regex : null;
4575
+ if (!result.ok) {
4576
+ console.warn(`[DoneConditionChecker] Invalid regex pattern "${condition.pattern}": ${result.reason}`);
4577
+ }
4578
+ } else {
4579
+ this.compiledRegex = null;
4580
+ }
4423
4581
  }
4424
4582
  condition;
4425
4583
  compiledRegex;
@@ -4657,6 +4815,13 @@ var InMemoryAgentBridge = class {
4657
4815
  this.pendingRequests.delete(correlationId);
4658
4816
  reject(new Error(`Request ${correlationId} timed out after ${timeout}ms`));
4659
4817
  }, timeout);
4818
+ if (this.stopped) {
4819
+ clearTimeout(timer);
4820
+ this.inflightGuards.delete(correlationId);
4821
+ this.pendingRequests.delete(correlationId);
4822
+ reject(new Error("Bridge stopped"));
4823
+ return;
4824
+ }
4660
4825
  this.pendingRequests.set(correlationId, {
4661
4826
  resolve: resolve2,
4662
4827
  reject,
@@ -5176,8 +5341,8 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5176
5341
  // --- internal dispatching ---------------------------------------------
5177
5342
  tryDispatchNext() {
5178
5343
  while (this.canDispatch()) {
5179
- const subagentId = this.findIdleSubagent();
5180
- if (!subagentId) {
5344
+ const dispatchable = this.takeNextDispatchableTask();
5345
+ if (!dispatchable) {
5181
5346
  if (this.pendingTasks.length > 0 && !this.hasLiveSubagent()) {
5182
5347
  this.drainPendingAsAborted(
5183
5348
  "No live subagent available \u2014 all stopped or mid-termination"
@@ -5185,8 +5350,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5185
5350
  }
5186
5351
  return;
5187
5352
  }
5188
- const task = this.pendingTasks.shift();
5189
- if (!task) return;
5353
+ const { subagentId, task } = dispatchable;
5190
5354
  this.runDispatched(subagentId, task).catch((err) => {
5191
5355
  this.recordCompletion({
5192
5356
  subagentId,
@@ -5204,12 +5368,26 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5204
5368
  const max = this.config.maxConcurrent ?? 4;
5205
5369
  return this.inFlight < max && this.pendingTasks.length > 0;
5206
5370
  }
5371
+ takeNextDispatchableTask() {
5372
+ for (let i = 0; i < this.pendingTasks.length; i++) {
5373
+ const task = this.pendingTasks[i];
5374
+ const subagentId = task.subagentId ? this.isIdleSubagent(task.subagentId) ? task.subagentId : null : this.findIdleSubagent();
5375
+ if (!subagentId) continue;
5376
+ this.pendingTasks.splice(i, 1);
5377
+ return { subagentId, task };
5378
+ }
5379
+ return null;
5380
+ }
5207
5381
  findIdleSubagent() {
5208
5382
  for (const [id, s] of this.subagents) {
5209
5383
  if (s.status === "idle" && !this.terminating.has(id)) return id;
5210
5384
  }
5211
5385
  return null;
5212
5386
  }
5387
+ isIdleSubagent(id) {
5388
+ const subagent = this.subagents.get(id);
5389
+ return !!subagent && subagent.status === "idle" && !this.terminating.has(id);
5390
+ }
5213
5391
  /**
5214
5392
  * Returns true iff at least one spawned subagent could still
5215
5393
  * process a task. A "live" subagent is one that is not stopped
@@ -5394,10 +5572,11 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5394
5572
  };
5395
5573
  function classifySubagentError(err, hints = {}) {
5396
5574
  const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
5397
- const baseMessage = err instanceof Error ? err.message : String(err);
5398
5575
  if (err instanceof ProviderError) {
5399
- return providerErrorToSubagentError(err, baseMessage, cause);
5576
+ const baseMessage2 = err.describe();
5577
+ return providerErrorToSubagentError(err, baseMessage2, cause);
5400
5578
  }
5579
+ const baseMessage = err instanceof Error ? err.message : String(err);
5401
5580
  if (err instanceof BudgetExceededError) {
5402
5581
  const map = {
5403
5582
  iterations: "budget_iterations",
@@ -5514,7 +5693,7 @@ function makeSpawnTool(director, roster) {
5514
5693
  if (role && !base) {
5515
5694
  return { error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}` };
5516
5695
  }
5517
- const cfg = { ...base ?? { name: i.name ?? "subagent" } };
5696
+ const cfg = base ? instantiateRosterConfig(role, base) : { name: i.name ?? "subagent" };
5518
5697
  if (typeof i.name === "string") cfg.name = i.name;
5519
5698
  if (typeof i.provider === "string") cfg.provider = i.provider;
5520
5699
  if (typeof i.model === "string") cfg.model = i.model;
@@ -5534,6 +5713,14 @@ function makeSpawnTool(director, roster) {
5534
5713
  }
5535
5714
  };
5536
5715
  }
5716
+ function instantiateRosterConfig(role, base) {
5717
+ return {
5718
+ ...base,
5719
+ // Roster entries are templates. A director may spawn several
5720
+ // workers with the same role, so never reuse the template id.
5721
+ id: `${role}-${randomUUID().slice(0, 8)}`
5722
+ };
5723
+ }
5537
5724
  function makeAssignTool(director) {
5538
5725
  const inputSchema = {
5539
5726
  type: "object",
@@ -5851,8 +6038,8 @@ var Director = class {
5851
6038
  if (this.spawnCount >= this.maxSpawns) {
5852
6039
  throw new DirectorBudgetError("max_spawns", this.maxSpawns, this.spawnCount + 1);
5853
6040
  }
5854
- this.spawnCount += 1;
5855
6041
  const result = await this.coordinator.spawn(config);
6042
+ this.spawnCount += 1;
5856
6043
  this.subagentMeta.set(result.subagentId, {
5857
6044
  provider: config.provider,
5858
6045
  model: config.model
@@ -6295,7 +6482,7 @@ function createDelegateTool(opts) {
6295
6482
  error: `Unknown role "${i.role}". Available: ${rosterIds.join(", ") || "(no roster configured)"}.`
6296
6483
  };
6297
6484
  }
6298
- cfg = { ...base };
6485
+ cfg = instantiateRosterConfig2(i.role, base);
6299
6486
  if (i.systemPromptOverride) cfg.systemPromptOverride = i.systemPromptOverride;
6300
6487
  if (i.provider) cfg.provider = i.provider;
6301
6488
  if (i.model) cfg.model = i.model;
@@ -6381,6 +6568,14 @@ function createDelegateTool(opts) {
6381
6568
  }
6382
6569
  };
6383
6570
  }
6571
+ function instantiateRosterConfig2(role, base) {
6572
+ return {
6573
+ ...base,
6574
+ // Roster entries are templates. Give each spawn a fresh id so
6575
+ // parallel or repeated delegates can use the same role safely.
6576
+ id: `${role}-${randomUUID().slice(0, 8)}`
6577
+ };
6578
+ }
6384
6579
  function hintForKind(kind, retryable, backoffMs) {
6385
6580
  if (!kind) return void 0;
6386
6581
  switch (kind) {
@@ -6789,6 +6984,7 @@ var FAMILY_BY_NPM = {
6789
6984
  "@ai-sdk/xai": "openai-compatible",
6790
6985
  "@ai-sdk/cerebras": "openai-compatible",
6791
6986
  "@ai-sdk/togetherai": "openai-compatible",
6987
+ "@ai-sdk/mistral": "openai-compatible",
6792
6988
  "@ai-sdk/perplexity": "openai-compatible",
6793
6989
  "@ai-sdk/deepinfra": "openai-compatible",
6794
6990
  "@openrouter/ai-sdk-provider": "openai-compatible",