@wrongstack/core 0.264.0 → 0.265.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 (87) hide show
  1. package/dist/{agent-bridge-D8sa1vtv.d.ts → agent-bridge-DrkBxszZ.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-c9DLkaas.d.ts → agent-subagent-runner-DM2pP-B6.d.ts} +113 -11
  3. package/dist/{brain-O1IdKPaK.d.ts → brain-BXd_61kQ.d.ts} +31 -2
  4. package/dist/{compactor-BBy0rCtB.d.ts → compactor-B8pOf45Y.d.ts} +1 -1
  5. package/dist/{config-Dz2F3H2K.d.ts → config-BMCj_XDs.d.ts} +80 -12
  6. package/dist/{context-BGSpZNSE.d.ts → context-MRk5PhNv.d.ts} +26 -12
  7. package/dist/coordination/index.d.ts +77 -21
  8. package/dist/coordination/index.js +557 -159
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/{default-config-CXsDvOmP.d.ts → default-config-B0cj-Hry.d.ts} +11 -1
  11. package/dist/defaults/index.d.ts +28 -28
  12. package/dist/defaults/index.js +609 -195
  13. package/dist/defaults/index.js.map +1 -1
  14. package/dist/execution/index.d.ts +16 -16
  15. package/dist/execution/index.js +394 -155
  16. package/dist/execution/index.js.map +1 -1
  17. package/dist/execution/prompt-enhancer.d.ts +2 -2
  18. package/dist/execution/prompt-enhancer.js +1 -1
  19. package/dist/execution/prompt-enhancer.js.map +1 -1
  20. package/dist/extension/index.d.ts +6 -6
  21. package/dist/{goal-preamble-DzjFuN3p.d.ts → goal-preamble-DvHDSKSe.d.ts} +14 -10
  22. package/dist/{goal-store-CxWmCGbH.d.ts → goal-store-DtLMySNb.d.ts} +1 -1
  23. package/dist/{index-CYIQrXVF.d.ts → index-B-ch8K9C.d.ts} +8 -8
  24. package/dist/{index-CbLSI66_.d.ts → index-CEDeNodM.d.ts} +5 -5
  25. package/dist/index.d.ts +183 -52
  26. package/dist/index.js +1779 -673
  27. package/dist/index.js.map +1 -1
  28. package/dist/infrastructure/index.d.ts +6 -6
  29. package/dist/infrastructure/index.js +12 -8
  30. package/dist/infrastructure/index.js.map +1 -1
  31. package/dist/kernel/index.d.ts +9 -9
  32. package/dist/kernel/index.js +1 -1
  33. package/dist/kernel/index.js.map +1 -1
  34. package/dist/{llm-selector-DzxuZnNz.d.ts → llm-selector-C0tfTCUe.d.ts} +14 -2
  35. package/dist/{mcp-servers-DC4QRPUI.d.ts → mcp-servers-2x4w6Jn9.d.ts} +3 -3
  36. package/dist/models/index.d.ts +5 -5
  37. package/dist/models/index.js +74 -30
  38. package/dist/models/index.js.map +1 -1
  39. package/dist/{models-registry-B_siPxqN.d.ts → models-registry-DmJlKuNp.d.ts} +1 -1
  40. package/dist/{multi-agent-coordinator-CK5Jdj9K.d.ts → multi-agent-coordinator-DyCkCZnU.d.ts} +1 -1
  41. package/dist/{null-fleet-bus-DgvD4SCO.d.ts → null-fleet-bus-CG9QY2aP.d.ts} +6 -6
  42. package/dist/observability/index.d.ts +2 -2
  43. package/dist/{parallel-eternal-engine-bK0JQBR_.d.ts → parallel-eternal-engine-Jw9uhEoT.d.ts} +9 -9
  44. package/dist/{path-resolver-BPEDlN38.d.ts → path-resolver-Dy2ej-gE.d.ts} +3 -3
  45. package/dist/{permission-4yvGmMRB.d.ts → permission-B9SB45lp.d.ts} +1 -1
  46. package/dist/{permission-policy-C6XpsBOy.d.ts → permission-policy-CkjSXabK.d.ts} +2 -2
  47. package/dist/{pipeline-CXCeMz8J.d.ts → pipeline-DPDxH_7m.d.ts} +3 -3
  48. package/dist/{plan-templates-BvzRBkJc.d.ts → plan-templates-CzD9GnAU.d.ts} +32 -8
  49. package/dist/{provider-runner-C5aQpDWE.d.ts → provider-runner-DMa70ODu.d.ts} +3 -3
  50. package/dist/{retry-policy-CFhdtRzz.d.ts → retry-policy-CN0khdlj.d.ts} +1 -1
  51. package/dist/sdd/index.d.ts +8 -8
  52. package/dist/sdd/index.js +274 -93
  53. package/dist/sdd/index.js.map +1 -1
  54. package/dist/{secret-vault-CxiVLbt1.d.ts → secret-vault-B2yw84VT.d.ts} +43 -4
  55. package/dist/secret-vault-BAKpgFw_.d.ts +57 -0
  56. package/dist/security/index.d.ts +5 -5
  57. package/dist/security/index.js +204 -23
  58. package/dist/security/index.js.map +1 -1
  59. package/dist/{selector-gIuhRTkN.d.ts → selector-CzHh_igB.d.ts} +1 -1
  60. package/dist/{session-event-bridge-DkvvrpDt.d.ts → session-event-bridge-BUI6Jf-4.d.ts} +1 -1
  61. package/dist/{session-reader-KdfVwkKP.d.ts → session-reader-CMgdMSRP.d.ts} +1 -1
  62. package/dist/storage/index.d.ts +112 -15
  63. package/dist/storage/index.js +419 -81
  64. package/dist/storage/index.js.map +1 -1
  65. package/dist/tools/index.d.ts +2 -2
  66. package/dist/types/index.d.ts +21 -21
  67. package/dist/types/index.js +261 -53
  68. package/dist/types/index.js.map +1 -1
  69. package/dist/utils/index.d.ts +3 -3
  70. package/dist/utils/index.js +3 -5
  71. package/dist/utils/index.js.map +1 -1
  72. package/dist/{wstack-paths-CJjEwPXn.d.ts → wstack-paths-hOpNLmvf.d.ts} +2 -0
  73. package/package.json +1 -1
  74. package/skills/api-design/SKILL.md +1 -1
  75. package/skills/audit-log/SKILL.md +6 -6
  76. package/skills/bug-hunter/SKILL.md +5 -5
  77. package/skills/chimera/SKILL.md +4 -4
  78. package/skills/docker-deploy/SKILL.md +1 -1
  79. package/skills/git-flow/SKILL.md +3 -3
  80. package/skills/multi-agent/SKILL.md +3 -3
  81. package/skills/node-modern/SKILL.md +1 -0
  82. package/skills/observability/SKILL.md +2 -2
  83. package/skills/output-standards/SKILL.md +51 -28
  84. package/skills/refactor-planner/SKILL.md +3 -3
  85. package/skills/security-scanner/SKILL.md +4 -3
  86. package/skills/tech-stack/SKILL.md +1 -2
  87. package/dist/secret-vault-BJDY28ev.d.ts +0 -25
@@ -842,12 +842,9 @@ function getCachedEstimate(key, compute) {
842
842
  const existing = ESTIMATE_CACHE.get(key);
843
843
  if (existing !== void 0) return existing;
844
844
  if (ESTIMATE_CACHE.size >= ESTIMATE_CACHE_MAX_SIZE) {
845
- let evicted = 0;
846
- const maxEvict = Math.floor(ESTIMATE_CACHE_MAX_SIZE / 4);
847
845
  for (const k of ESTIMATE_CACHE.keys()) {
848
- if (evicted >= maxEvict) break;
846
+ if (ESTIMATE_CACHE.size <= Math.floor(ESTIMATE_CACHE_MAX_SIZE / 2)) break;
849
847
  ESTIMATE_CACHE.delete(k);
850
- evicted++;
851
848
  }
852
849
  }
853
850
  const estimate = compute(key);
@@ -919,9 +916,9 @@ Rules:
919
916
  - If unsure, keep rather than collapse (errors are more costly than waste)
920
917
 
921
918
  Return ONLY the JSON object, no markdown, no explanation outside the JSON.`;
922
- function formatMessages(messages, maxChars = 8e3) {
919
+ function formatMessages(messages, maxTokens = 2048) {
923
920
  const lines = [];
924
- let used = 0;
921
+ let usedTokens = 0;
925
922
  for (let i = 0; i < messages.length; i++) {
926
923
  const m = expectDefined(messages[i]);
927
924
  const role = m.role.padEnd(10, " ");
@@ -933,13 +930,14 @@ function formatMessages(messages, maxChars = 8e3) {
933
930
  text = content.filter(isTextBlock).map((b) => b.text).join(" ");
934
931
  const toolUses = content.filter((b) => b.type === "tool_use");
935
932
  if (toolUses.length > 0) {
936
- text += ` [tools: ${toolUses.map((b) => b.name).join(", ")}]`;
933
+ text += ` [tools: ${toolUses.map((b) => b.name).filter(Boolean).join(", ")}]`;
937
934
  }
938
935
  }
939
936
  const line = `[${i}][${role}]: ${text}`;
940
- if (used + line.length > maxChars) break;
937
+ const lineTokens = estimateTextTokens(line);
938
+ if (usedTokens + lineTokens > maxTokens) break;
941
939
  lines.push(line);
942
- used += line.length;
940
+ usedTokens += lineTokens;
943
941
  }
944
942
  return lines.join("\n");
945
943
  }
@@ -948,20 +946,29 @@ var LLMSelector = class {
948
946
  model;
949
947
  maxContextTokens;
950
948
  systemPrompt;
949
+ maxOutputTokens;
951
950
  constructor(opts) {
952
951
  this.provider = opts.provider;
953
952
  this.model = opts.model ?? "unknown";
953
+ if (this.model === "unknown" && (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1")) {
954
+ console.warn(
955
+ "[LLMSelector] model not set \u2014 selector will use the provider default. Set `model` explicitly in LLMSelectorOptions to silence this warning."
956
+ );
957
+ }
954
958
  this.maxContextTokens = opts.maxContextTokens ?? 4e4;
955
959
  this.systemPrompt = opts.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
960
+ this.maxOutputTokens = opts.maxOutputTokens ?? 1024;
956
961
  }
957
962
  async select(messages, maxToKeep) {
958
963
  const effectiveBudget = Math.min(maxToKeep, this.maxContextTokens);
959
- const historyText = formatMessages(messages);
960
964
  const totalTokens = estimateMessageTokens(messages);
961
965
  const systemText = `${this.systemPrompt}
962
966
 
963
967
  Conversation (${messages.length} messages, ~${totalTokens} tokens, budget: ${effectiveBudget}):
964
968
  `;
969
+ const systemTokens = estimateTextTokens(systemText);
970
+ const historyBudget = Math.max(512, effectiveBudget - systemTokens - this.maxOutputTokens);
971
+ const historyText = formatMessages(messages, historyBudget);
965
972
  const budgetInstruction = totalTokens > effectiveBudget ? `
966
973
 
967
974
  IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiveBudget}). You MUST collapse enough to fit. Prefer collapsing older/lower-importance ranges.` : "";
@@ -969,18 +976,26 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
969
976
  model: this.model,
970
977
  system: [{ type: "text", text: systemText + budgetInstruction }],
971
978
  messages: [{ role: "user", content: historyText }],
972
- maxTokens: 1024
979
+ maxTokens: this.maxOutputTokens
973
980
  };
974
981
  let raw;
982
+ const ac = new AbortController();
975
983
  try {
976
- const ac = new AbortController();
977
- const res = await this.provider.complete(req, { signal: ac.signal });
984
+ const timeoutSignal = AbortSignal.timeout(3e4);
985
+ const res = await this.provider.complete(req, {
986
+ signal: AbortSignal.any([ac.signal, timeoutSignal])
987
+ });
978
988
  const textBlocks = res.content.filter(isTextBlock);
979
989
  raw = textBlocks.map((b) => b.text).join("\n").trim();
980
- } catch (_err) {
990
+ } catch (err) {
991
+ if (err instanceof Error) {
992
+ console.warn("[LLMSelector] selector call failed, using recency fallback:", err.message);
993
+ }
981
994
  return this.fallbackSelect(messages, effectiveBudget);
995
+ } finally {
996
+ ac.abort();
982
997
  }
983
- return this.parseSelectorOutput(raw, messages.length);
998
+ return this.parseSelectorOutput(raw, messages);
984
999
  }
985
1000
  fallbackSelect(messages, budget) {
986
1001
  const toKeep = [];
@@ -1007,34 +1022,63 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
1007
1022
  reasoning: `Fallback: kept last ${messages.length - startIdx} messages within ${budget} token budget`
1008
1023
  };
1009
1024
  }
1010
- parseSelectorOutput(raw, messageCount) {
1025
+ /**
1026
+ * Parse and validate the raw LLM output into a SelectorResult.
1027
+ * Falls back to recency-based selection if the LLM output is malformed,
1028
+ * out-of-bounds, or internally inconsistent.
1029
+ */
1030
+ parseSelectorOutput(raw, messages) {
1031
+ const messageCount = messages.length;
1032
+ if (messageCount === 0) {
1033
+ return { kept: [], collapsed: [], reasoning: "empty session" };
1034
+ }
1011
1035
  const jsonStart = raw.indexOf("{");
1012
1036
  const jsonEnd = raw.lastIndexOf("}");
1013
1037
  if (jsonStart === -1 || jsonEnd === -1) {
1014
- return this.fallbackSelect(
1015
- Array.from({ length: messageCount }, () => ({ role: "user", content: "" })),
1016
- this.maxContextTokens
1017
- );
1038
+ return this.fallbackSelect(messages, this.maxContextTokens);
1018
1039
  }
1019
1040
  let parsed;
1020
1041
  try {
1021
1042
  parsed = JSON.parse(raw.slice(jsonStart, jsonEnd + 1));
1022
1043
  } catch {
1023
- return this.fallbackSelect(
1024
- Array.from({ length: messageCount }, () => ({ role: "user", content: "" })),
1025
- this.maxContextTokens
1026
- );
1044
+ return this.fallbackSelect(messages, this.maxContextTokens);
1027
1045
  }
1028
1046
  const obj = parsed;
1029
- const kept = obj.kept ?? [];
1030
- const collapsed = obj.collapsed ?? [];
1031
- return {
1032
- kept: kept.map((k) => ({
1047
+ const keptRaw = obj.kept ?? [];
1048
+ const collapsedRaw = obj.collapsed ?? [];
1049
+ const kept = [];
1050
+ for (const k of keptRaw) {
1051
+ if (typeof k.from !== "number" || typeof k.to !== "number" || k.from < 0 || k.to >= messageCount || k.from > k.to) {
1052
+ return this.fallbackSelect(messages, this.maxContextTokens);
1053
+ }
1054
+ kept.push({
1033
1055
  from: k.from,
1034
1056
  to: k.to,
1035
1057
  importance: k.importance ?? "medium"
1036
- })),
1037
- collapsed: collapsed.map((c) => ({ from: c.from, to: c.to, summary: c.summary })),
1058
+ });
1059
+ }
1060
+ const collapsed = [];
1061
+ for (const c of collapsedRaw) {
1062
+ if (typeof c.from !== "number" || typeof c.to !== "number" || c.from < 0 || c.to >= messageCount || c.from > c.to) {
1063
+ return this.fallbackSelect(messages, this.maxContextTokens);
1064
+ }
1065
+ collapsed.push({ from: c.from, to: c.to, summary: c.summary });
1066
+ }
1067
+ const allRanges = [...kept, ...collapsed];
1068
+ for (let i = 0; i < allRanges.length; i++) {
1069
+ const a = allRanges[i];
1070
+ if (!a) continue;
1071
+ for (let j = i + 1; j < allRanges.length; j++) {
1072
+ const b = allRanges[j];
1073
+ if (!b) continue;
1074
+ if (a.from <= b.to && a.to >= b.from) {
1075
+ return this.fallbackSelect(messages, this.maxContextTokens);
1076
+ }
1077
+ }
1078
+ }
1079
+ return {
1080
+ kept,
1081
+ collapsed,
1038
1082
  reasoning: typeof obj.reasoning === "string" ? obj.reasoning : ""
1039
1083
  };
1040
1084
  }