@wrongstack/core 0.68.0 → 0.73.1

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 (55) hide show
  1. package/dist/{agent-bridge-D-j6OOBT.d.ts → agent-bridge-C0Ze7Ldm.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-DRZ9-NnR.d.ts → agent-subagent-runner-BmITbs1Q.d.ts} +13 -5
  3. package/dist/{config--86aHSln.d.ts → config-Dy0CK_o6.d.ts} +44 -1
  4. package/dist/coordination/index.d.ts +10 -10
  5. package/dist/coordination/index.js +10 -4
  6. package/dist/coordination/index.js.map +1 -1
  7. package/dist/defaults/index.d.ts +15 -15
  8. package/dist/defaults/index.js +53 -22
  9. package/dist/defaults/index.js.map +1 -1
  10. package/dist/{events-CIplI98R.d.ts → events-BBAlxBuw.d.ts} +8 -0
  11. package/dist/execution/index.d.ts +8 -8
  12. package/dist/execution/index.js +4 -4
  13. package/dist/execution/index.js.map +1 -1
  14. package/dist/extension/index.d.ts +5 -5
  15. package/dist/{index-DKUvyTvV.d.ts → index-BN6i2Nfg.d.ts} +4 -4
  16. package/dist/{index-b5uhfTSl.d.ts → index-yQbZ2NQx.d.ts} +6 -6
  17. package/dist/index.d.ts +29 -27
  18. package/dist/index.js +154 -33
  19. package/dist/index.js.map +1 -1
  20. package/dist/infrastructure/index.d.ts +4 -4
  21. package/dist/kernel/index.d.ts +7 -7
  22. package/dist/kernel/index.js.map +1 -1
  23. package/dist/{mcp-servers-DwoNBf6r.d.ts → mcp-servers-T0O6UN_w.d.ts} +1 -1
  24. package/dist/{mode-CV077NjV.d.ts → mode-BO4SEUIv.d.ts} +7 -0
  25. package/dist/models/index.d.ts +1 -1
  26. package/dist/models/index.js +18 -9
  27. package/dist/models/index.js.map +1 -1
  28. package/dist/{multi-agent-coordinator-CWnH-CiX.d.ts → multi-agent-coordinator-BSBbZt0e.d.ts} +1 -1
  29. package/dist/{null-fleet-bus-CuN0ObJr.d.ts → null-fleet-bus-BCIRT_nV.d.ts} +19 -9
  30. package/dist/observability/index.d.ts +1 -1
  31. package/dist/{parallel-eternal-engine-0UwotoSx.d.ts → parallel-eternal-engine-CjAYGaCw.d.ts} +3 -3
  32. package/dist/{path-resolver-DVkEcIw8.d.ts → path-resolver-BnqXa9Ze.d.ts} +1 -1
  33. package/dist/{permission-C1A5whY5.d.ts → permission-V5BLOrY6.d.ts} +0 -4
  34. package/dist/{permission-policy-B2dK-T5N.d.ts → permission-policy-CBVx-d-8.d.ts} +1 -5
  35. package/dist/{plan-templates-Bprrzhbu.d.ts → plan-templates-DBgrTGPu.d.ts} +2 -2
  36. package/dist/{provider-runner-mXvXGSIw.d.ts → provider-runner-n3KkHT_w.d.ts} +1 -1
  37. package/dist/sdd/index.d.ts +6 -6
  38. package/dist/sdd/index.js +3 -3
  39. package/dist/sdd/index.js.map +1 -1
  40. package/dist/security/index.d.ts +2 -2
  41. package/dist/security/index.js +0 -8
  42. package/dist/security/index.js.map +1 -1
  43. package/dist/skills/index.js +1 -0
  44. package/dist/skills/index.js.map +1 -1
  45. package/dist/storage/index.d.ts +3 -3
  46. package/dist/storage/index.js +26 -2
  47. package/dist/storage/index.js.map +1 -1
  48. package/dist/{system-prompt-b61lOd49.d.ts → system-prompt-CA11g6Jo.d.ts} +1 -1
  49. package/dist/types/index.d.ts +13 -13
  50. package/dist/types/index.js +19 -10
  51. package/dist/types/index.js.map +1 -1
  52. package/dist/utils/index.d.ts +1 -1
  53. package/dist/utils/index.js +2 -1
  54. package/dist/utils/index.js.map +1 -1
  55. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2677,7 +2677,8 @@ When reviewing code:
2677
2677
  - Verify test coverage for critical paths
2678
2678
  - Ensure naming conventions are followed`,
2679
2679
  tags: ["review", "quality", "security"],
2680
- toolPreferences: ["read", "grep", "git", "diff", "test"]
2680
+ toolPreferences: ["read", "grep", "git", "diff", "test"],
2681
+ suggestedSkills: ["bug-hunter", "security-scanner", "typescript-strict", "testing"]
2681
2682
  },
2682
2683
  {
2683
2684
  id: "code-auditor",
@@ -2694,7 +2695,8 @@ When auditing code for security:
2694
2695
  - Assess input validation and output encoding
2695
2696
  - Look for timing attacks and information leakage`,
2696
2697
  tags: ["security", "audit", "compliance"],
2697
- toolPreferences: ["grep", "read", "audit", "bash"]
2698
+ toolPreferences: ["grep", "read", "audit", "bash"],
2699
+ suggestedSkills: ["security-scanner", "bug-hunter", "audit-log"]
2698
2700
  },
2699
2701
  {
2700
2702
  id: "architect",
@@ -2712,7 +2714,8 @@ When designing or reviewing architecture:
2712
2714
  - Assess API design and contract stability
2713
2715
  - Consider operational aspects (monitoring, logging, deployment)`,
2714
2716
  tags: ["architecture", "design", "scalability"],
2715
- toolPreferences: ["read", "glob", "tree", "diff"]
2717
+ toolPreferences: ["read", "glob", "tree", "diff"],
2718
+ suggestedSkills: ["api-design", "refactor-planner", "node-modern", "docker-deploy"]
2716
2719
  },
2717
2720
  {
2718
2721
  id: "debugger",
@@ -2730,7 +2733,8 @@ When investigating bugs:
2730
2733
  - Use binary search to isolate the root cause
2731
2734
  - Verify fixes with tests before considering done`,
2732
2735
  tags: ["debug", "investigation", "error-resolution"],
2733
- toolPreferences: ["read", "grep", "bash", "logs", "test"]
2736
+ toolPreferences: ["read", "grep", "bash", "logs", "test"],
2737
+ suggestedSkills: ["bug-hunter", "audit-log", "observability"]
2734
2738
  },
2735
2739
  {
2736
2740
  id: "tester",
@@ -2748,7 +2752,8 @@ When testing or writing tests:
2748
2752
  - Check for integration test gaps
2749
2753
  - Verify test isolation and cleanup`,
2750
2754
  tags: ["testing", "qa", "quality"],
2751
- toolPreferences: ["read", "grep", "test", "bash"]
2755
+ toolPreferences: ["read", "grep", "test", "bash"],
2756
+ suggestedSkills: ["testing", "bug-hunter", "typescript-strict"]
2752
2757
  },
2753
2758
  {
2754
2759
  id: "devops",
@@ -2766,7 +2771,8 @@ When working on infrastructure:
2766
2771
  - Assess secrets management
2767
2772
  - Check for resource limits and quotas`,
2768
2773
  tags: ["devops", "infrastructure", "operations"],
2769
- toolPreferences: ["read", "bash", "grep", "logs", "git"]
2774
+ toolPreferences: ["read", "bash", "grep", "logs", "git"],
2775
+ suggestedSkills: ["docker-deploy", "observability", "security-scanner"]
2770
2776
  },
2771
2777
  {
2772
2778
  id: "refactorer",
@@ -2784,7 +2790,8 @@ When refactoring code:
2784
2790
  - Don't mix formatting changes with logic changes
2785
2791
  - Keep performance in mind \u2014 don't regress`,
2786
2792
  tags: ["refactor", "modernization", "improvement"],
2787
- toolPreferences: ["read", "edit", "test", "git", "grep"]
2793
+ toolPreferences: ["read", "edit", "test", "git", "grep"],
2794
+ suggestedSkills: ["refactor-planner", "typescript-strict", "node-modern", "testing"]
2788
2795
  },
2789
2796
  {
2790
2797
  id: "brief",
@@ -2814,7 +2821,8 @@ Get to the point \u2014 read files, run commands, make changes.
2814
2821
  - One-liner sufficient? One liner.
2815
2822
  - Max 3 sentences per paragraph.`,
2816
2823
  tags: ["fast", "concise", "direct"],
2817
- toolPreferences: ["read", "edit", "bash"]
2824
+ toolPreferences: ["read", "edit", "bash"],
2825
+ suggestedSkills: []
2818
2826
  },
2819
2827
  {
2820
2828
  id: "teach",
@@ -2879,7 +2887,8 @@ You follow these principles, but always with explanation:
2879
2887
 
2880
2888
  Remember: your job is to make the user a better developer, not just to complete tasks faster.`,
2881
2889
  tags: ["teaching", "mentor", "learning"],
2882
- toolPreferences: ["read", "edit", "explain"]
2890
+ toolPreferences: ["read", "edit", "explain"],
2891
+ suggestedSkills: ["prompt-engineering", "skill-creator", "node-modern", "typescript-strict"]
2883
2892
  }
2884
2893
  ];
2885
2894
 
@@ -3512,7 +3521,7 @@ ${errorDetails}`,
3512
3521
  const decision = await this.opts.permissionPolicy.evaluate(tool, use.input, ctx);
3513
3522
  let effectivePermission = decision.permission;
3514
3523
  const policy = this.opts.permissionPolicy;
3515
- const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true || policy.getForceAllYolo?.() === true;
3524
+ const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true;
3516
3525
  if (toolDangerousCaps.length > 0 && effectivePermission === "auto" && !yolo) {
3517
3526
  effectivePermission = "confirm";
3518
3527
  }
@@ -4654,7 +4663,8 @@ function isGlob(p) {
4654
4663
  return false;
4655
4664
  }
4656
4665
  function globToRegex(pat) {
4657
- let i = 0, re = "^";
4666
+ let i = 0;
4667
+ let re = "^";
4658
4668
  while (i < pat.length) {
4659
4669
  const c = pat[i];
4660
4670
  if (c === "*") {
@@ -5922,8 +5932,17 @@ var BEHAVIOR_DEFAULTS = {
5922
5932
  modelsRegistry: true,
5923
5933
  skills: true
5924
5934
  },
5935
+ indexing: {
5936
+ onSessionStart: true,
5937
+ onEdit: true,
5938
+ watchExternal: true,
5939
+ debounceMs: 400
5940
+ },
5925
5941
  session: { ...DEFAULT_SESSION_LOGGING_CONFIG }
5926
5942
  };
5943
+ function envBool(v) {
5944
+ return !/^(0|false|no|off)$/i.test(v.trim());
5945
+ }
5927
5946
  var ENV_MAP = {
5928
5947
  WRONGSTACK_PROVIDER: (c, v) => {
5929
5948
  c.provider = v;
@@ -5948,8 +5967,23 @@ var ENV_MAP = {
5948
5967
  WRONGSTACK_LOG_LEVEL: (c, v) => {
5949
5968
  if (!c.log) c.log = { level: "info" };
5950
5969
  c.log.level = v;
5970
+ },
5971
+ WRONGSTACK_INDEX_ON_START: (c, v) => {
5972
+ c.indexing = { ...defaultIndexing, ...c.indexing, onSessionStart: envBool(v) };
5973
+ },
5974
+ WRONGSTACK_INDEX_ON_EDIT: (c, v) => {
5975
+ c.indexing = { ...defaultIndexing, ...c.indexing, onEdit: envBool(v) };
5976
+ },
5977
+ WRONGSTACK_INDEX_WATCH: (c, v) => {
5978
+ c.indexing = { ...defaultIndexing, ...c.indexing, watchExternal: envBool(v) };
5951
5979
  }
5952
5980
  };
5981
+ var defaultIndexing = {
5982
+ onSessionStart: true,
5983
+ onEdit: true,
5984
+ watchExternal: true,
5985
+ debounceMs: 400
5986
+ };
5953
5987
  function isPrimitiveArray(a) {
5954
5988
  return a.every((v) => v === null || typeof v !== "object");
5955
5989
  }
@@ -7174,14 +7208,6 @@ var DefaultPermissionPolicy = class {
7174
7208
  getConfirmDestructive() {
7175
7209
  return this.confirmDestructive;
7176
7210
  }
7177
- /** @deprecated Use `setYoloDestructive`. */
7178
- setForceAllYolo(enabled) {
7179
- this.setYoloDestructive(enabled);
7180
- }
7181
- /** @deprecated Use `getYoloDestructive`. */
7182
- getForceAllYolo() {
7183
- return this.getYoloDestructive();
7184
- }
7185
7211
  async reload() {
7186
7212
  try {
7187
7213
  const raw = await fsp3.readFile(this.trustFile, "utf8");
@@ -12899,7 +12925,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
12899
12925
  }
12900
12926
  async spawn(subagent) {
12901
12927
  const id = subagent.id || randomUUID();
12902
- subagent = this.withNickname(subagent, id);
12928
+ const cfg = this.withNickname(subagent, id);
12903
12929
  if (this.subagents.has(id)) {
12904
12930
  throw new Error(`Subagent id "${id}" already exists \u2014 refusing to overwrite`);
12905
12931
  }
@@ -12914,12 +12940,12 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
12914
12940
  maxConcurrent: this.config.maxConcurrent ?? 16
12915
12941
  };
12916
12942
  this.subagents.set(id, {
12917
- config: { ...subagent, id },
12943
+ config: { ...cfg, id },
12918
12944
  context,
12919
12945
  status: "idle",
12920
12946
  abortController: new AbortController()
12921
12947
  });
12922
- this.emit("subagent.started", { subagent: { ...subagent, id } });
12948
+ this.emit("subagent.started", { subagent: { ...cfg, id } });
12923
12949
  this.fleetBus?.emit({
12924
12950
  subagentId: id,
12925
12951
  ts: Date.now(),
@@ -14604,6 +14630,10 @@ A scratchpad shared with the rest of the fleet is mounted at \`${parts.sharedScr
14604
14630
  - Use stable filenames (one file per concern); overwrite instead of appending so the Director sees the latest state.`
14605
14631
  );
14606
14632
  }
14633
+ if (parts.skills && parts.skills.trim().length > 0) {
14634
+ sections.push(`Domain knowledge:
14635
+ ${parts.skills.trim()}`);
14636
+ }
14607
14637
  if (parts.override && parts.override.trim().length > 0) {
14608
14638
  sections.push(parts.override.trim());
14609
14639
  }
@@ -16448,6 +16478,7 @@ var Director = class _Director {
16448
16478
  role: config.prompt,
16449
16479
  task: taskBrief,
16450
16480
  sharedScratchpad: this.sharedScratchpadPath ?? void 0,
16481
+ skills: config.skillContent,
16451
16482
  override: config.systemPromptOverride
16452
16483
  });
16453
16484
  }
@@ -20753,6 +20784,7 @@ var MAX_TARBALL_SIZE = 50 * 1024 * 1024;
20753
20784
  async function downloadGitHubTarball(parsed) {
20754
20785
  const url = `https://api.github.com/repos/${parsed.owner}/${parsed.repo}/tarball/${parsed.ref}`;
20755
20786
  const response = await fetch(url, {
20787
+ signal: AbortSignal.timeout(3e4),
20756
20788
  headers: {
20757
20789
  Accept: "application/vnd.github+json",
20758
20790
  "User-Agent": "wrongstack-skill-installer"
@@ -21588,7 +21620,6 @@ var SessionRecovery = class {
21588
21620
  }
21589
21621
  return null;
21590
21622
  } catch {
21591
- continue;
21592
21623
  }
21593
21624
  }
21594
21625
  return null;
@@ -21819,7 +21850,7 @@ var ToolAuditLog = class {
21819
21850
  await fsp3.appendFile(fp, line, "utf8");
21820
21851
  const count = (this.unSyncedWrites.get(sessionId) ?? 0) + 1;
21821
21852
  this.unSyncedWrites.set(sessionId, count);
21822
- if (this.fsyncEvery !== Infinity && count % this.fsyncEvery === 0) {
21853
+ if (this.fsyncEvery !== Number.POSITIVE_INFINITY && count % this.fsyncEvery === 0) {
21823
21854
  await this.sync(sessionId, fp);
21824
21855
  }
21825
21856
  }
@@ -22258,6 +22289,7 @@ var CloudSync = class {
22258
22289
  async githubFetch(token, owner, repo, method, pathSegment, body) {
22259
22290
  const url = `https://api.github.com/repos/${owner}/${repo}${pathSegment}`;
22260
22291
  const res = await fetch(url, {
22292
+ signal: AbortSignal.timeout(15e3),
22261
22293
  method,
22262
22294
  headers: {
22263
22295
  Authorization: `Bearer ${token}`,
@@ -26390,7 +26422,7 @@ var InputBuilder = class {
26390
26422
  meta: { label: paragraphLabel(text) }
26391
26423
  });
26392
26424
  this.refs.push(ref);
26393
- const lines = text.split("\n").length;
26425
+ const lines = text.split(/\r?\n|\r/).length;
26394
26426
  return `[pasted #${ref.seq}, ${lines} lines]`;
26395
26427
  }
26396
26428
  /**
@@ -26447,14 +26479,16 @@ var InputBuilder = class {
26447
26479
  if (text.length >= this.pasteCharThreshold) return true;
26448
26480
  let lines = 1;
26449
26481
  for (let i = 0; i < text.length; i++) {
26450
- if (text.charCodeAt(i) === 10) lines++;
26482
+ const c = text.charCodeAt(i);
26483
+ if (c === 10) lines++;
26484
+ else if (c === 13 && text.charCodeAt(i + 1) !== 10) lines++;
26451
26485
  if (lines >= this.pasteLineThreshold) return true;
26452
26486
  }
26453
26487
  return false;
26454
26488
  }
26455
26489
  };
26456
26490
  function paragraphLabel(text) {
26457
- const lines = text.split("\n").length;
26491
+ const lines = text.split(/\r?\n|\r/).length;
26458
26492
  const bytes = Buffer.byteLength(text, "utf8");
26459
26493
  if (bytes < 1024) return `${lines} lines, ${bytes} B`;
26460
26494
  return `${lines} lines, ${(bytes / 1024).toFixed(1)} KB`;
@@ -26465,23 +26499,34 @@ var PROMPT = `You are WrongStack, a command-line AI coding agent.
26465
26499
 
26466
26500
  You operate inside the user's terminal with direct read and write access to their working directory, the ability to run shell commands, and access to the web. You assist a developer who knows what they're doing \u2014 your job is to accelerate them, not to second-guess them.
26467
26501
 
26502
+ These are your baseline instructions. When an active mode prompt (Teach, Brief, Code Reviewer, etc.) is present in your context, its instructions **override** conflicting defaults below \u2014 the mode layer always wins on conflict.
26503
+
26468
26504
  ## Core principles
26469
26505
 
26470
26506
  1. **Read before you write.** Always inspect the relevant files before proposing changes. Assumptions about code you haven't read are bugs in waiting.
26471
26507
  2. **Prefer surgical edits over rewrites.** When modifying existing files, use the edit tool with str_replace; only use write for new files or full replacements explicitly requested.
26472
26508
  3. **Show your work.** Before non-trivial changes, briefly state what you're about to do \u2014 one sentence, not a wall of text. After tool calls, summarize what happened, not what you did mechanically.
26473
26509
  4. **Be honest about limits.** If you don't know, say so. If something failed, say what failed and what you'll try next. Never fabricate file contents, API responses, or test results.
26474
- 5. **Be concise.** The user is a developer in a terminal. No marketing language, no "great question!", no bullet-point lists when prose works. If a one-liner answers, a one-liner is the answer.
26510
+ 5. **Be concise.** The user is a developer in a terminal. No marketing language, no "great question!", no bullet-point lists when prose works. If a one-liner answers, a one-liner is the answer. (Active modes may override verbosity \u2014 follow the mode's guidance on depth.)
26475
26511
  6. **Ask when blocked, proceed when not.** If the task is ambiguous in a way that meaningfully changes the approach, ask. If it's ambiguous in a way that doesn't, pick a reasonable default and proceed, stating the assumption.
26476
26512
  7. **Trust the tools.** If a permission prompt is shown, the user will answer. Do not preemptively explain that you "would like to" do something \u2014 call the tool, let the permission flow decide.
26477
26513
  8. **Format for scanability.** Use code blocks for code, backticks for file paths, bold for key terms. One-liners stay one line. Paragraphs max 3 sentences.
26478
- 9. **Recover explicitly.** When a tool fails, state: (1) what failed, (2) what you tried, (3) what you'll attempt next. Never silently skip.
26514
+ 9. **Match the user's language.** Respond in the same language the user writes in. If they write in Turkish, reply in Turkish. If they mix languages, follow the dominant one.
26515
+ 10. **Recover explicitly.** When a tool fails, distinguish the failure type and respond accordingly:
26516
+
26517
+ | Failure type | Examples | Strategy |
26518
+ |---|---|---|
26519
+ | **Transient** | Timeout, rate limit, network hiccup | Retry once with adjusted params, then report |
26520
+ | **Permanent** | Syntax error, missing file, type error, permission denied | Do NOT retry \u2014 diagnose and report the root cause |
26521
+ | **Validation** | Invalid argument, out-of-range value, schema mismatch | State what was rejected and what range/format is accepted |
26522
+
26523
+ Never silently skip a failure \u2014 always report it, even when you choose not to retry.
26479
26524
 
26480
26525
  ## Decision heuristics
26481
26526
 
26482
26527
  - **Task is ambiguous** (unclear which file, conflicting requirements) \u2192 ask before proceeding
26483
26528
  - **Task is clear, approach is unknown** \u2192 try one approach, report what happened
26484
- - **Tool fails** \u2192 retry once with adjusted params, then report failure
26529
+ - **Tool fails** \u2192 classify the failure (transient/permanent/validation), then apply the appropriate recovery
26485
26530
  - **Permission prompt shown** \u2192 wait for user, do not act unilaterally
26486
26531
  - **Tool denied by user** \u2192 do NOT retry the same tool in the next iteration. If the user denies a write, bash, or any tool, respect that decision. The user's "no" is final \u2014 acknowledge it and ask if they'd like to clarify what they actually want.
26487
26532
  - **Context window filling up** \u2192 use context_manager proactively; don't wait to be told
@@ -26512,6 +26557,8 @@ var DefaultSystemPromptBuilder = class {
26512
26557
  */
26513
26558
  envCacheByRoot = /* @__PURE__ */ new Map();
26514
26559
  skillCache;
26560
+ /** Cached full skill bodies (after frontmatter), built once per session. */
26561
+ skillBodyCache;
26515
26562
  async build(ctx) {
26516
26563
  if (this.opts.skillLoader && !this.skillCache) {
26517
26564
  try {
@@ -26519,8 +26566,8 @@ var DefaultSystemPromptBuilder = class {
26519
26566
  if (entries.length > 0) {
26520
26567
  const lines = [];
26521
26568
  for (const e of entries) {
26522
- const scopeTag = e.scope.length > 0 ? ` \u2014 ${e.scope.slice(0, 4).join(", ")}` : "";
26523
- lines.push(`- **${e.name}**${scopeTag} (${e.trigger})`);
26569
+ const shortTrigger = compactTrigger(e.trigger);
26570
+ lines.push(`- **${e.name}** (${shortTrigger})`);
26524
26571
  }
26525
26572
  this.skillCache = lines.join("\n");
26526
26573
  }
@@ -26552,6 +26599,24 @@ var DefaultSystemPromptBuilder = class {
26552
26599
  cache_control: { type: "ephemeral" }
26553
26600
  });
26554
26601
  }
26602
+ if (this.opts.modeStore && this.opts.skillLoader) {
26603
+ try {
26604
+ const activeMode = await this.opts.modeStore.getActiveMode();
26605
+ if (activeMode?.suggestedSkills && activeMode.suggestedSkills.length > 0) {
26606
+ const skills = await this.opts.skillLoader.list();
26607
+ const loadedNames = new Set(skills.map((s) => s.name));
26608
+ const available = activeMode.suggestedSkills.filter((n) => loadedNames.has(n));
26609
+ if (available.length > 0) {
26610
+ blocks.push({
26611
+ type: "text",
26612
+ text: `Mode "${activeMode.id}" works best with these skills: ${available.join(", ")}. Their full instructions are in the Active Skills block above.`,
26613
+ cache_control: { type: "ephemeral" }
26614
+ });
26615
+ }
26616
+ }
26617
+ } catch {
26618
+ }
26619
+ }
26555
26620
  if (layer6.trim()) {
26556
26621
  blocks.push({
26557
26622
  type: "text",
@@ -26782,7 +26847,13 @@ summarize it, and let the tool result hold only the summary.`);
26782
26847
  );
26783
26848
  }
26784
26849
  if (this.skillCache) {
26785
- lines.push("", "## Skills in scope for this session", this.skillCache);
26850
+ lines.push(
26851
+ "",
26852
+ "## Skills in scope for this session",
26853
+ this.skillCache,
26854
+ "",
26855
+ "Full skill instructions are injected in the Active Skills block below."
26856
+ );
26786
26857
  }
26787
26858
  const text = lines.join("\n");
26788
26859
  this.envCacheByRoot.set(ctx.projectRoot, text);
@@ -26799,6 +26870,40 @@ ${mem}`);
26799
26870
  } catch {
26800
26871
  }
26801
26872
  }
26873
+ if (this.opts.skillLoader && this.skillBodyCache === void 0) {
26874
+ try {
26875
+ const skills = await this.opts.skillLoader.list();
26876
+ if (skills.length > 0) {
26877
+ const bodies = [];
26878
+ for (const s of skills) {
26879
+ try {
26880
+ const raw = await this.opts.skillLoader.readBody(s.name);
26881
+ const body = stripFrontmatter(raw);
26882
+ if (body.trim()) {
26883
+ bodies.push(`## Skill: ${s.name}
26884
+
26885
+ ${body.trim()}`);
26886
+ }
26887
+ } catch {
26888
+ }
26889
+ }
26890
+ if (bodies.length > 0) {
26891
+ this.skillBodyCache = bodies.join("\n\n---\n\n");
26892
+ } else {
26893
+ this.skillBodyCache = "";
26894
+ }
26895
+ } else {
26896
+ this.skillBodyCache = "";
26897
+ }
26898
+ } catch {
26899
+ this.skillBodyCache = "";
26900
+ }
26901
+ }
26902
+ if (this.skillBodyCache) {
26903
+ parts.push(`# Active Skills
26904
+
26905
+ ${this.skillBodyCache}`);
26906
+ }
26802
26907
  return parts.join("\n\n");
26803
26908
  }
26804
26909
  async buildMode() {
@@ -26888,6 +26993,22 @@ ${mem}`);
26888
26993
  return langs.size === 0 ? "unknown" : Array.from(langs).join(", ");
26889
26994
  }
26890
26995
  };
26996
+ function stripFrontmatter(raw) {
26997
+ if (!raw.startsWith("---")) return raw;
26998
+ const end = raw.indexOf("\n---", 4);
26999
+ if (end === -1) return raw;
27000
+ let body = raw.slice(end + 4);
27001
+ if (body.startsWith("\n")) body = body.slice(1);
27002
+ return body;
27003
+ }
27004
+ function compactTrigger(trigger) {
27005
+ let s = trigger.replace(/^Use this skill when /i, "").replace(/^Use this skill for /i, "").replace(/^Use when /i, "").replace(/\.$/, "");
27006
+ if (s.length > 72) {
27007
+ const cut = s.lastIndexOf(" ", 68);
27008
+ s = cut > 50 ? s.slice(0, cut) + "\u2026" : s.slice(0, 68) + "\u2026";
27009
+ }
27010
+ return s;
27011
+ }
26891
27012
 
26892
27013
  // src/registry/tool-registry.ts
26893
27014
  var ToolRegistry = class _ToolRegistry {