reasonix 0.27.3 → 0.28.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.
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  CODE_SYSTEM_PROMPT,
4
4
  codeSystemPrompt
5
- } from "./chunk-R2L5YEEF.js";
5
+ } from "./chunk-COFBA5FV.js";
6
6
  export {
7
7
  CODE_SYSTEM_PROMPT,
8
8
  codeSystemPrompt
9
9
  };
10
- //# sourceMappingURL=prompt-YUL7CYKY.js.map
10
+ //# sourceMappingURL=prompt-VF7B6BWR.js.map
package/dist/index.js CHANGED
@@ -3636,6 +3636,11 @@ function parseFrontmatter(raw) {
3636
3636
  function isValidSkillName(name) {
3637
3637
  return VALID_SKILL_NAME.test(name);
3638
3638
  }
3639
+ function parseAllowedTools(raw) {
3640
+ if (raw === void 0) return void 0;
3641
+ const names = raw.split(",").map((s) => s.trim()).filter(Boolean);
3642
+ return names.length > 0 ? Object.freeze(names) : void 0;
3643
+ }
3639
3644
  var SkillStore = class {
3640
3645
  homeDir;
3641
3646
  projectRoot;
@@ -3735,7 +3740,7 @@ var SkillStore = class {
3735
3740
  body: body.trim(),
3736
3741
  scope,
3737
3742
  path: path2,
3738
- allowedTools: data["allowed-tools"],
3743
+ allowedTools: parseAllowedTools(data["allowed-tools"]),
3739
3744
  runAs: parseRunAs(data.runAs),
3740
3745
  model: data.model?.startsWith("deepseek-") ? data.model : void 0
3741
3746
  };
@@ -5408,6 +5413,50 @@ function registerPlanTool(registry, opts = {}) {
5408
5413
  return registry;
5409
5414
  }
5410
5415
 
5416
+ // src/tools/subagent-types.ts
5417
+ var EXPLORE_SYSTEM = `You are an exploration subagent. Wide-net read-only investigation; return one distilled answer.
5418
+
5419
+ How to operate:
5420
+ - Read-only tools only (read_file, search_files, search_content, directory_tree, list_directory, get_file_info).
5421
+ - For "find all places that call / reference / use X" \u2014 use search_content (content grep), NOT search_files (which only matches names).
5422
+ - Cast a wide net first to map the territory, then read the 3-10 most relevant files in full. Stop as soon as you can answer.
5423
+ - The parent does not see your tool calls \u2014 over-exploration is pure waste.
5424
+
5425
+ Final answer:
5426
+ - One paragraph or short bullets; lead with the conclusion.
5427
+ - Cite file:line ranges when they back the claim.
5428
+ - No follow-up offers, no "let me know if you need more" \u2014 the parent will ask again.
5429
+
5430
+ ${NEGATIVE_CLAIM_RULE}
5431
+
5432
+ ${TUI_FORMATTING_RULES}`;
5433
+ var VERIFY_SYSTEM = `You are a verify subagent. Narrow check \u2014 return YES / NO / INCONCLUSIVE with evidence. Do not expand scope.
5434
+
5435
+ How to operate:
5436
+ - Read only what's needed to verify the specific claim. No exploration past the claim.
5437
+ - Use search_content / read_file to confirm the exact behavior, type, or call site in question.
5438
+ - Cap at 6-8 tool calls. If you can't verify in that, return INCONCLUSIVE plus what's missing.
5439
+
5440
+ Final answer:
5441
+ - Lead with VERIFIED / NOT VERIFIED / INCONCLUSIVE.
5442
+ - Cite file:line for the evidence.
5443
+ - One paragraph or a few bullets. No follow-up offers.
5444
+
5445
+ ${NEGATIVE_CLAIM_RULE}
5446
+
5447
+ ${TUI_FORMATTING_RULES}`;
5448
+ var TYPES = {
5449
+ explore: { system: EXPLORE_SYSTEM, maxToolIters: 20 },
5450
+ verify: { system: VERIFY_SYSTEM, maxToolIters: 8 }
5451
+ };
5452
+ var SUBAGENT_TYPE_NAMES = Object.freeze(
5453
+ Object.keys(TYPES)
5454
+ );
5455
+ function getSubagentType(name) {
5456
+ if (typeof name !== "string") return void 0;
5457
+ return TYPES[name];
5458
+ }
5459
+
5411
5460
  // src/tools/subagent.ts
5412
5461
  var DEFAULT_SUBAGENT_SYSTEM = `You are a Reasonix subagent. The parent agent spawned you to handle one focused subtask, then return.
5413
5462
 
@@ -5424,6 +5473,8 @@ ${ESCALATION_CONTRACT}
5424
5473
  ${TUI_FORMATTING_RULES}`;
5425
5474
  var DEFAULT_MAX_RESULT_CHARS2 = 8e3;
5426
5475
  var DEFAULT_MAX_ITERS = 16;
5476
+ var MIN_MAX_ITERS = 1;
5477
+ var MAX_MAX_ITERS = 32;
5427
5478
  var DEFAULT_SUBAGENT_MODEL = "deepseek-v4-flash";
5428
5479
  var DEFAULT_SUBAGENT_EFFORT = "high";
5429
5480
  var SUBAGENT_TOOL_NAME = "spawn_subagent";
@@ -5444,7 +5495,41 @@ async function spawnSubagent(opts) {
5444
5495
  iter: 0,
5445
5496
  elapsedMs: 0
5446
5497
  });
5447
- const childTools = forkRegistryExcluding(opts.parentRegistry, NEVER_INHERITED_TOOLS);
5498
+ if (opts.allowedTools) {
5499
+ const missing = opts.allowedTools.filter((n) => !opts.parentRegistry.has(n));
5500
+ if (missing.length > 0) {
5501
+ const errorMessage2 = `subagent allow-list names tool(s) not registered in the parent: ${missing.join(", ")}. Fix the skill's \`allowed-tools\` frontmatter or check spelling.`;
5502
+ sink?.current?.({
5503
+ kind: "end",
5504
+ task: taskPreview,
5505
+ skillName,
5506
+ model,
5507
+ iter: 0,
5508
+ elapsedMs: Date.now() - startedAt,
5509
+ error: errorMessage2,
5510
+ turns: 0,
5511
+ costUsd: 0,
5512
+ usage: new Usage()
5513
+ });
5514
+ return {
5515
+ success: false,
5516
+ output: "",
5517
+ error: errorMessage2,
5518
+ turns: 0,
5519
+ toolIters: 0,
5520
+ elapsedMs: Date.now() - startedAt,
5521
+ costUsd: 0,
5522
+ model,
5523
+ skillName,
5524
+ usage: new Usage()
5525
+ };
5526
+ }
5527
+ }
5528
+ const childTools = opts.allowedTools ? forkRegistryWithAllowList(
5529
+ opts.parentRegistry,
5530
+ new Set(opts.allowedTools),
5531
+ NEVER_INHERITED_TOOLS
5532
+ ) : forkRegistryExcluding(opts.parentRegistry, NEVER_INHERITED_TOOLS);
5448
5533
  const childPrefix = new ImmutablePrefix({
5449
5534
  system: opts.system,
5450
5535
  toolSpecs: childTools.specs()
@@ -5609,6 +5694,17 @@ function registerSubagentTool(parentRegistry, opts) {
5609
5694
  type: "string",
5610
5695
  enum: ["deepseek-v4-flash", "deepseek-v4-pro"],
5611
5696
  description: "Which DeepSeek model the subagent runs on. Default is 'deepseek-v4-flash' \u2014 cheap and fast, fine for explore/research-style subtasks. Override to 'deepseek-v4-pro' (~12\xD7 more expensive) when the subtask genuinely needs the stronger model: cross-file architecture, subtle bug hunts, anything where flash has empirically underperformed."
5697
+ },
5698
+ max_iters: {
5699
+ type: "integer",
5700
+ minimum: MIN_MAX_ITERS,
5701
+ maximum: MAX_MAX_ITERS,
5702
+ description: `Cap on the subagent's tool-call iterations. Default 16 (or the type's default when 'type' is set). Hard range: ${MIN_MAX_ITERS}-${MAX_MAX_ITERS}; out-of-range values are clamped to the nearest end.`
5703
+ },
5704
+ type: {
5705
+ type: "string",
5706
+ enum: [...SUBAGENT_TYPE_NAMES],
5707
+ description: "Optional persona shaping the system prompt and default iter budget. 'explore' = wide-net read-only investigation (20-iter budget, returns a distilled answer). 'verify' = narrow yes/no check with evidence (8-iter budget). Omit when supplying your own 'system' prompt or when the default generic persona fits. Caller-supplied 'system' / 'max_iters' override the type's defaults."
5612
5708
  }
5613
5709
  },
5614
5710
  required: ["task"]
@@ -5620,15 +5716,17 @@ function registerSubagentTool(parentRegistry, opts) {
5620
5716
  error: "spawn_subagent requires a non-empty 'task' argument."
5621
5717
  });
5622
5718
  }
5623
- const system = typeof args.system === "string" && args.system.trim().length > 0 ? args.system.trim() : defaultSystem;
5719
+ const typeSpec = getSubagentType(args.type);
5720
+ const system = typeof args.system === "string" && args.system.trim().length > 0 ? args.system.trim() : typeSpec?.system ?? defaultSystem;
5624
5721
  const model = typeof args.model === "string" && args.model.startsWith("deepseek-") ? args.model : defaultModel;
5722
+ const callerIters = clampMaxIters(args.max_iters);
5625
5723
  const result = await spawnSubagent({
5626
5724
  client: opts.client,
5627
5725
  parentRegistry,
5628
5726
  system,
5629
5727
  task,
5630
5728
  model,
5631
- maxToolIters,
5729
+ maxToolIters: callerIters ?? typeSpec?.maxToolIters ?? maxToolIters,
5632
5730
  maxResultChars,
5633
5731
  sink,
5634
5732
  parentSignal: ctx?.signal
@@ -5638,6 +5736,13 @@ function registerSubagentTool(parentRegistry, opts) {
5638
5736
  });
5639
5737
  return parentRegistry;
5640
5738
  }
5739
+ function clampMaxIters(raw) {
5740
+ if (typeof raw !== "number" || !Number.isFinite(raw)) return void 0;
5741
+ const n = Math.floor(raw);
5742
+ if (n < MIN_MAX_ITERS) return MIN_MAX_ITERS;
5743
+ if (n > MAX_MAX_ITERS) return MAX_MAX_ITERS;
5744
+ return n;
5745
+ }
5641
5746
  function forkRegistryExcluding(parent, exclude) {
5642
5747
  const child = new ToolRegistry();
5643
5748
  for (const spec of parent.specs()) {
@@ -5650,6 +5755,19 @@ function forkRegistryExcluding(parent, exclude) {
5650
5755
  if (parent.planMode) child.setPlanMode(true);
5651
5756
  return child;
5652
5757
  }
5758
+ function forkRegistryWithAllowList(parent, allow, alsoExclude) {
5759
+ const child = new ToolRegistry();
5760
+ for (const spec of parent.specs()) {
5761
+ const name = spec.function.name;
5762
+ if (!allow.has(name)) continue;
5763
+ if (alsoExclude.has(name)) continue;
5764
+ const def = parent.get(name);
5765
+ if (!def) continue;
5766
+ child.register(def);
5767
+ }
5768
+ if (parent.planMode) child.setPlanMode(true);
5769
+ return child;
5770
+ }
5653
5771
 
5654
5772
  // src/tools/shell.ts
5655
5773
  import * as pathMod7 from "path";