@wrongstack/core 0.3.3 → 0.3.4

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.
@@ -3,7 +3,7 @@ export { AbandonedSession, AttachmentStoreOptions, ConfigLoaderOptions, ConfigMi
3
3
  export { D as DefaultSessionReader } from '../session-reader-CcPi4BQ8.js';
4
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';
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-DY0iSXYf.js';
7
7
  export { AutoCompactionMiddleware, AutonomousRunner, AutonomousRunnerOptions, DefaultSkillLoader, DoneCheckResult, DoneConditionChecker, IntelligentCompactor, IntelligentCompactorOptions, SelectiveCompactor, SelectiveCompactorOptions, SkillLoaderOptions } from '../execution/index.js';
8
8
  import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-B39miKRw.js';
9
9
  import { j as Response } from '../context-IovtuTf8.js';
@@ -14,19 +14,19 @@ export { D as DefaultModelsRegistry, a as DefaultModelsRegistryOptions, c as cla
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-zGiC1lQc.js';
18
18
  import '../logger-BMQgxvdy.js';
19
19
  import '../events-BHIQs4o1.js';
20
20
  import '../memory-CEXuo7sz.js';
21
21
  import '../wstack-paths-BGu2INTm.js';
22
- import '../config-D2qvAxVd.js';
22
+ import '../config-DgE3JslD.js';
23
23
  import '../models-registry-Y2xbog0E.js';
24
24
  import '../secret-vault-DoISxaKO.js';
25
25
  import '../secret-scrubber-CgG2tV2B.js';
26
26
  import '../input-reader-E-ffP2ee.js';
27
27
  import '../compactor-DpJBI1YH.js';
28
28
  import '../skill-C_7znCIC.js';
29
- import '../index-hWNybrNZ.js';
29
+ import '../index-DedY4Euf.js';
30
30
  import '../system-prompt-Dk1qm8ey.js';
31
31
  import '../observability-BhnVLBLS.js';
32
32
  import '../selector-wT2fv9Fg.js';
@@ -1480,6 +1480,42 @@ function defaultIsPidAlive(pid) {
1480
1480
  }
1481
1481
  }
1482
1482
 
1483
+ // src/utils/regex-guard.ts
1484
+ var MAX_PATTERN_LEN = 512;
1485
+ var DANGEROUS_PATTERNS = [
1486
+ /(\([^)]*[+*][^)]*\))[+*]/,
1487
+ // (a+)+, (.*)+, etc
1488
+ /(\(\?:[^)]*[+*][^)]*\))[+*]/
1489
+ // same, with non-capturing group
1490
+ ];
1491
+ function compileUserRegex(pattern, flags) {
1492
+ if (typeof pattern !== "string") {
1493
+ return { ok: false, reason: "pattern must be a string" };
1494
+ }
1495
+ if (pattern.length === 0) {
1496
+ return { ok: false, reason: "pattern is empty" };
1497
+ }
1498
+ if (pattern.length > MAX_PATTERN_LEN) {
1499
+ return { ok: false, reason: `pattern exceeds ${MAX_PATTERN_LEN} characters` };
1500
+ }
1501
+ for (const rx of DANGEROUS_PATTERNS) {
1502
+ if (rx.test(pattern)) {
1503
+ return {
1504
+ ok: false,
1505
+ reason: "pattern looks vulnerable to catastrophic backtracking \u2014 rewrite without nested quantifiers"
1506
+ };
1507
+ }
1508
+ }
1509
+ try {
1510
+ return { ok: true, regex: new RegExp(pattern, flags) };
1511
+ } catch (err) {
1512
+ return {
1513
+ ok: false,
1514
+ reason: err instanceof Error ? err.message : "invalid regex"
1515
+ };
1516
+ }
1517
+ }
1518
+
1483
1519
  // src/storage/session-reader.ts
1484
1520
  var DefaultSessionReader = class {
1485
1521
  store;
@@ -1574,7 +1610,11 @@ function buildMatcher(q) {
1574
1610
  const ci = q.caseInsensitive ?? true;
1575
1611
  if (q.regex) {
1576
1612
  const flags = ci ? "i" : "";
1577
- const re = new RegExp(q.query, flags);
1613
+ const compiled = compileUserRegex(q.query, flags);
1614
+ if (!compiled.ok) {
1615
+ throw new Error(`Invalid search regex "${q.query}": ${compiled.reason}`);
1616
+ }
1617
+ const re = compiled.regex;
1578
1618
  return (text) => {
1579
1619
  const m = re.exec(text);
1580
1620
  return m ? { start: m.index, end: m.index + m[0].length } : null;
@@ -2299,7 +2339,7 @@ function walk2(node, vault, transform) {
2299
2339
  if (Array.isArray(node)) {
2300
2340
  return node.map((item) => walk2(item, vault, transform));
2301
2341
  }
2302
- const out = {};
2342
+ const out = /* @__PURE__ */ Object.create(null);
2303
2343
  for (const [k, v] of Object.entries(node)) {
2304
2344
  if (typeof v === "string" && isSecretField2(k)) {
2305
2345
  out[k] = transform(v, k);
@@ -2410,7 +2450,11 @@ function getCachedGlob(pattern) {
2410
2450
  COMPILED_GLOB_CACHE.set(pattern, re);
2411
2451
  return re;
2412
2452
  }
2453
+ var MAX_GLOB_PATTERN_LEN = 1024;
2413
2454
  function compileGlob(pattern) {
2455
+ if (pattern.length > MAX_GLOB_PATTERN_LEN) {
2456
+ throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);
2457
+ }
2414
2458
  let i = 0;
2415
2459
  let re = "^";
2416
2460
  while (i < pattern.length) {
@@ -4419,7 +4463,15 @@ var ToolExecutor = class {
4419
4463
  var DoneConditionChecker = class {
4420
4464
  constructor(condition) {
4421
4465
  this.condition = condition;
4422
- this.compiledRegex = condition.type === "output_match" && condition.pattern ? new RegExp(condition.pattern) : null;
4466
+ if (condition.type === "output_match" && condition.pattern) {
4467
+ const result = compileUserRegex(condition.pattern, "");
4468
+ this.compiledRegex = result.ok ? result.regex : null;
4469
+ if (!result.ok) {
4470
+ console.warn(`[DoneConditionChecker] Invalid regex pattern "${condition.pattern}": ${result.reason}`);
4471
+ }
4472
+ } else {
4473
+ this.compiledRegex = null;
4474
+ }
4423
4475
  }
4424
4476
  condition;
4425
4477
  compiledRegex;
@@ -5176,8 +5228,8 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5176
5228
  // --- internal dispatching ---------------------------------------------
5177
5229
  tryDispatchNext() {
5178
5230
  while (this.canDispatch()) {
5179
- const subagentId = this.findIdleSubagent();
5180
- if (!subagentId) {
5231
+ const dispatchable = this.takeNextDispatchableTask();
5232
+ if (!dispatchable) {
5181
5233
  if (this.pendingTasks.length > 0 && !this.hasLiveSubagent()) {
5182
5234
  this.drainPendingAsAborted(
5183
5235
  "No live subagent available \u2014 all stopped or mid-termination"
@@ -5185,8 +5237,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5185
5237
  }
5186
5238
  return;
5187
5239
  }
5188
- const task = this.pendingTasks.shift();
5189
- if (!task) return;
5240
+ const { subagentId, task } = dispatchable;
5190
5241
  this.runDispatched(subagentId, task).catch((err) => {
5191
5242
  this.recordCompletion({
5192
5243
  subagentId,
@@ -5204,12 +5255,26 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5204
5255
  const max = this.config.maxConcurrent ?? 4;
5205
5256
  return this.inFlight < max && this.pendingTasks.length > 0;
5206
5257
  }
5258
+ takeNextDispatchableTask() {
5259
+ for (let i = 0; i < this.pendingTasks.length; i++) {
5260
+ const task = this.pendingTasks[i];
5261
+ const subagentId = task.subagentId ? this.isIdleSubagent(task.subagentId) ? task.subagentId : null : this.findIdleSubagent();
5262
+ if (!subagentId) continue;
5263
+ this.pendingTasks.splice(i, 1);
5264
+ return { subagentId, task };
5265
+ }
5266
+ return null;
5267
+ }
5207
5268
  findIdleSubagent() {
5208
5269
  for (const [id, s] of this.subagents) {
5209
5270
  if (s.status === "idle" && !this.terminating.has(id)) return id;
5210
5271
  }
5211
5272
  return null;
5212
5273
  }
5274
+ isIdleSubagent(id) {
5275
+ const subagent = this.subagents.get(id);
5276
+ return !!subagent && subagent.status === "idle" && !this.terminating.has(id);
5277
+ }
5213
5278
  /**
5214
5279
  * Returns true iff at least one spawned subagent could still
5215
5280
  * process a task. A "live" subagent is one that is not stopped
@@ -5394,10 +5459,11 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
5394
5459
  };
5395
5460
  function classifySubagentError(err, hints = {}) {
5396
5461
  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
5462
  if (err instanceof ProviderError) {
5399
- return providerErrorToSubagentError(err, baseMessage, cause);
5463
+ const baseMessage2 = err.describe();
5464
+ return providerErrorToSubagentError(err, baseMessage2, cause);
5400
5465
  }
5466
+ const baseMessage = err instanceof Error ? err.message : String(err);
5401
5467
  if (err instanceof BudgetExceededError) {
5402
5468
  const map = {
5403
5469
  iterations: "budget_iterations",
@@ -5514,7 +5580,7 @@ function makeSpawnTool(director, roster) {
5514
5580
  if (role && !base) {
5515
5581
  return { error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}` };
5516
5582
  }
5517
- const cfg = { ...base ?? { name: i.name ?? "subagent" } };
5583
+ const cfg = base ? instantiateRosterConfig(role, base) : { name: i.name ?? "subagent" };
5518
5584
  if (typeof i.name === "string") cfg.name = i.name;
5519
5585
  if (typeof i.provider === "string") cfg.provider = i.provider;
5520
5586
  if (typeof i.model === "string") cfg.model = i.model;
@@ -5534,6 +5600,14 @@ function makeSpawnTool(director, roster) {
5534
5600
  }
5535
5601
  };
5536
5602
  }
5603
+ function instantiateRosterConfig(role, base) {
5604
+ return {
5605
+ ...base,
5606
+ // Roster entries are templates. A director may spawn several
5607
+ // workers with the same role, so never reuse the template id.
5608
+ id: `${role}-${randomUUID().slice(0, 8)}`
5609
+ };
5610
+ }
5537
5611
  function makeAssignTool(director) {
5538
5612
  const inputSchema = {
5539
5613
  type: "object",
@@ -6295,7 +6369,7 @@ function createDelegateTool(opts) {
6295
6369
  error: `Unknown role "${i.role}". Available: ${rosterIds.join(", ") || "(no roster configured)"}.`
6296
6370
  };
6297
6371
  }
6298
- cfg = { ...base };
6372
+ cfg = instantiateRosterConfig2(i.role, base);
6299
6373
  if (i.systemPromptOverride) cfg.systemPromptOverride = i.systemPromptOverride;
6300
6374
  if (i.provider) cfg.provider = i.provider;
6301
6375
  if (i.model) cfg.model = i.model;
@@ -6381,6 +6455,14 @@ function createDelegateTool(opts) {
6381
6455
  }
6382
6456
  };
6383
6457
  }
6458
+ function instantiateRosterConfig2(role, base) {
6459
+ return {
6460
+ ...base,
6461
+ // Roster entries are templates. Give each spawn a fresh id so
6462
+ // parallel or repeated delegates can use the same role safely.
6463
+ id: `${role}-${randomUUID().slice(0, 8)}`
6464
+ };
6465
+ }
6384
6466
  function hintForKind(kind, retryable, backoffMs) {
6385
6467
  if (!kind) return void 0;
6386
6468
  switch (kind) {
@@ -6789,6 +6871,7 @@ var FAMILY_BY_NPM = {
6789
6871
  "@ai-sdk/xai": "openai-compatible",
6790
6872
  "@ai-sdk/cerebras": "openai-compatible",
6791
6873
  "@ai-sdk/togetherai": "openai-compatible",
6874
+ "@ai-sdk/mistral": "openai-compatible",
6792
6875
  "@ai-sdk/perplexity": "openai-compatible",
6793
6876
  "@ai-sdk/deepinfra": "openai-compatible",
6794
6877
  "@openrouter/ai-sdk-provider": "openai-compatible",