opencode-swarm-plugin 0.44.0 → 0.44.2
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.
- package/bin/swarm.serve.test.ts +6 -4
- package/bin/swarm.ts +18 -12
- package/dist/compaction-prompt-scoring.js +139 -0
- package/dist/eval-capture.js +12811 -0
- package/dist/hive.d.ts.map +1 -1
- package/dist/hive.js +14834 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7743 -62593
- package/dist/plugin.js +24052 -78907
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm-prompts.js +39407 -0
- package/dist/swarm-review.d.ts.map +1 -1
- package/dist/swarm-validation.d.ts +127 -0
- package/dist/swarm-validation.d.ts.map +1 -0
- package/dist/validators/index.d.ts +7 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/schema-validator.d.ts +58 -0
- package/dist/validators/schema-validator.d.ts.map +1 -0
- package/package.json +17 -5
- package/.changeset/swarm-insights-data-layer.md +0 -63
- package/.hive/analysis/eval-failure-analysis-2025-12-25.md +0 -331
- package/.hive/analysis/session-data-quality-audit.md +0 -320
- package/.hive/eval-results.json +0 -483
- package/.hive/issues.jsonl +0 -138
- package/.hive/memories.jsonl +0 -729
- package/.opencode/eval-history.jsonl +0 -327
- package/.turbo/turbo-build.log +0 -9
- package/CHANGELOG.md +0 -2286
- package/SCORER-ANALYSIS.md +0 -598
- package/docs/analysis/subagent-coordination-patterns.md +0 -902
- package/docs/analysis-socratic-planner-pattern.md +0 -504
- package/docs/planning/ADR-001-monorepo-structure.md +0 -171
- package/docs/planning/ADR-002-package-extraction.md +0 -393
- package/docs/planning/ADR-003-performance-improvements.md +0 -451
- package/docs/planning/ADR-004-message-queue-features.md +0 -187
- package/docs/planning/ADR-005-devtools-observability.md +0 -202
- package/docs/planning/ADR-007-swarm-enhancements-worktree-review.md +0 -168
- package/docs/planning/ADR-008-worker-handoff-protocol.md +0 -293
- package/docs/planning/ADR-009-oh-my-opencode-patterns.md +0 -353
- package/docs/planning/ADR-010-cass-inhousing.md +0 -1215
- package/docs/planning/ROADMAP.md +0 -368
- package/docs/semantic-memory-cli-syntax.md +0 -123
- package/docs/swarm-mail-architecture.md +0 -1147
- package/docs/testing/context-recovery-test.md +0 -470
- package/evals/ARCHITECTURE.md +0 -1189
- package/evals/README.md +0 -768
- package/evals/compaction-prompt.eval.ts +0 -149
- package/evals/compaction-resumption.eval.ts +0 -289
- package/evals/coordinator-behavior.eval.ts +0 -307
- package/evals/coordinator-session.eval.ts +0 -154
- package/evals/evalite.config.ts.bak +0 -15
- package/evals/example.eval.ts +0 -31
- package/evals/fixtures/cass-baseline.ts +0 -217
- package/evals/fixtures/compaction-cases.ts +0 -350
- package/evals/fixtures/compaction-prompt-cases.ts +0 -311
- package/evals/fixtures/coordinator-sessions.ts +0 -328
- package/evals/fixtures/decomposition-cases.ts +0 -105
- package/evals/lib/compaction-loader.test.ts +0 -248
- package/evals/lib/compaction-loader.ts +0 -320
- package/evals/lib/data-loader.evalite-test.ts +0 -289
- package/evals/lib/data-loader.test.ts +0 -345
- package/evals/lib/data-loader.ts +0 -281
- package/evals/lib/llm.ts +0 -115
- package/evals/scorers/compaction-prompt-scorers.ts +0 -145
- package/evals/scorers/compaction-scorers.ts +0 -305
- package/evals/scorers/coordinator-discipline.evalite-test.ts +0 -539
- package/evals/scorers/coordinator-discipline.ts +0 -325
- package/evals/scorers/index.test.ts +0 -146
- package/evals/scorers/index.ts +0 -328
- package/evals/scorers/outcome-scorers.evalite-test.ts +0 -27
- package/evals/scorers/outcome-scorers.ts +0 -349
- package/evals/swarm-decomposition.eval.ts +0 -121
- package/examples/commands/swarm.md +0 -745
- package/examples/plugin-wrapper-template.ts +0 -2515
- package/examples/skills/hive-workflow/SKILL.md +0 -212
- package/examples/skills/skill-creator/SKILL.md +0 -223
- package/examples/skills/swarm-coordination/SKILL.md +0 -292
- package/global-skills/cli-builder/SKILL.md +0 -344
- package/global-skills/cli-builder/references/advanced-patterns.md +0 -244
- package/global-skills/learning-systems/SKILL.md +0 -644
- package/global-skills/skill-creator/LICENSE.txt +0 -202
- package/global-skills/skill-creator/SKILL.md +0 -352
- package/global-skills/skill-creator/references/output-patterns.md +0 -82
- package/global-skills/skill-creator/references/workflows.md +0 -28
- package/global-skills/swarm-coordination/SKILL.md +0 -995
- package/global-skills/swarm-coordination/references/coordinator-patterns.md +0 -235
- package/global-skills/swarm-coordination/references/strategies.md +0 -138
- package/global-skills/system-design/SKILL.md +0 -213
- package/global-skills/testing-patterns/SKILL.md +0 -430
- package/global-skills/testing-patterns/references/dependency-breaking-catalog.md +0 -586
- package/opencode-swarm-plugin-0.30.7.tgz +0 -0
- package/opencode-swarm-plugin-0.31.0.tgz +0 -0
- package/scripts/cleanup-test-memories.ts +0 -346
- package/scripts/init-skill.ts +0 -222
- package/scripts/migrate-unknown-sessions.ts +0 -349
- package/scripts/validate-skill.ts +0 -204
- package/src/agent-mail.ts +0 -1724
- package/src/anti-patterns.test.ts +0 -1167
- package/src/anti-patterns.ts +0 -448
- package/src/compaction-capture.integration.test.ts +0 -257
- package/src/compaction-hook.test.ts +0 -838
- package/src/compaction-hook.ts +0 -1204
- package/src/compaction-observability.integration.test.ts +0 -139
- package/src/compaction-observability.test.ts +0 -187
- package/src/compaction-observability.ts +0 -324
- package/src/compaction-prompt-scorers.test.ts +0 -475
- package/src/compaction-prompt-scoring.ts +0 -300
- package/src/contributor-tools.test.ts +0 -133
- package/src/contributor-tools.ts +0 -201
- package/src/dashboard.test.ts +0 -611
- package/src/dashboard.ts +0 -462
- package/src/error-enrichment.test.ts +0 -403
- package/src/error-enrichment.ts +0 -219
- package/src/eval-capture.test.ts +0 -1015
- package/src/eval-capture.ts +0 -929
- package/src/eval-gates.test.ts +0 -306
- package/src/eval-gates.ts +0 -218
- package/src/eval-history.test.ts +0 -508
- package/src/eval-history.ts +0 -214
- package/src/eval-learning.test.ts +0 -378
- package/src/eval-learning.ts +0 -360
- package/src/eval-runner.test.ts +0 -223
- package/src/eval-runner.ts +0 -402
- package/src/export-tools.test.ts +0 -476
- package/src/export-tools.ts +0 -257
- package/src/hive.integration.test.ts +0 -2241
- package/src/hive.ts +0 -1628
- package/src/index.ts +0 -940
- package/src/learning.integration.test.ts +0 -1815
- package/src/learning.ts +0 -1079
- package/src/logger.test.ts +0 -189
- package/src/logger.ts +0 -135
- package/src/mandate-promotion.test.ts +0 -473
- package/src/mandate-promotion.ts +0 -239
- package/src/mandate-storage.integration.test.ts +0 -601
- package/src/mandate-storage.test.ts +0 -578
- package/src/mandate-storage.ts +0 -794
- package/src/mandates.ts +0 -540
- package/src/memory-tools.test.ts +0 -195
- package/src/memory-tools.ts +0 -344
- package/src/memory.integration.test.ts +0 -334
- package/src/memory.test.ts +0 -158
- package/src/memory.ts +0 -527
- package/src/model-selection.test.ts +0 -188
- package/src/model-selection.ts +0 -68
- package/src/observability-tools.test.ts +0 -359
- package/src/observability-tools.ts +0 -871
- package/src/output-guardrails.test.ts +0 -438
- package/src/output-guardrails.ts +0 -381
- package/src/pattern-maturity.test.ts +0 -1160
- package/src/pattern-maturity.ts +0 -525
- package/src/planning-guardrails.test.ts +0 -491
- package/src/planning-guardrails.ts +0 -438
- package/src/plugin.ts +0 -23
- package/src/post-compaction-tracker.test.ts +0 -251
- package/src/post-compaction-tracker.ts +0 -237
- package/src/query-tools.test.ts +0 -636
- package/src/query-tools.ts +0 -324
- package/src/rate-limiter.integration.test.ts +0 -466
- package/src/rate-limiter.ts +0 -774
- package/src/replay-tools.test.ts +0 -496
- package/src/replay-tools.ts +0 -240
- package/src/repo-crawl.integration.test.ts +0 -441
- package/src/repo-crawl.ts +0 -610
- package/src/schemas/cell-events.test.ts +0 -347
- package/src/schemas/cell-events.ts +0 -807
- package/src/schemas/cell.ts +0 -257
- package/src/schemas/evaluation.ts +0 -166
- package/src/schemas/index.test.ts +0 -199
- package/src/schemas/index.ts +0 -286
- package/src/schemas/mandate.ts +0 -232
- package/src/schemas/swarm-context.ts +0 -115
- package/src/schemas/task.ts +0 -161
- package/src/schemas/worker-handoff.test.ts +0 -302
- package/src/schemas/worker-handoff.ts +0 -131
- package/src/sessions/agent-discovery.test.ts +0 -137
- package/src/sessions/agent-discovery.ts +0 -112
- package/src/sessions/index.ts +0 -15
- package/src/skills.integration.test.ts +0 -1192
- package/src/skills.test.ts +0 -643
- package/src/skills.ts +0 -1549
- package/src/storage.integration.test.ts +0 -341
- package/src/storage.ts +0 -884
- package/src/structured.integration.test.ts +0 -817
- package/src/structured.test.ts +0 -1046
- package/src/structured.ts +0 -762
- package/src/swarm-decompose.test.ts +0 -188
- package/src/swarm-decompose.ts +0 -1302
- package/src/swarm-deferred.integration.test.ts +0 -157
- package/src/swarm-deferred.test.ts +0 -38
- package/src/swarm-insights.test.ts +0 -214
- package/src/swarm-insights.ts +0 -459
- package/src/swarm-mail.integration.test.ts +0 -970
- package/src/swarm-mail.ts +0 -739
- package/src/swarm-orchestrate.integration.test.ts +0 -282
- package/src/swarm-orchestrate.test.ts +0 -548
- package/src/swarm-orchestrate.ts +0 -3084
- package/src/swarm-prompts.test.ts +0 -1270
- package/src/swarm-prompts.ts +0 -2077
- package/src/swarm-research.integration.test.ts +0 -701
- package/src/swarm-research.test.ts +0 -698
- package/src/swarm-research.ts +0 -472
- package/src/swarm-review.integration.test.ts +0 -285
- package/src/swarm-review.test.ts +0 -879
- package/src/swarm-review.ts +0 -709
- package/src/swarm-strategies.ts +0 -407
- package/src/swarm-worktree.test.ts +0 -501
- package/src/swarm-worktree.ts +0 -575
- package/src/swarm.integration.test.ts +0 -2377
- package/src/swarm.ts +0 -38
- package/src/tool-adapter.integration.test.ts +0 -1221
- package/src/tool-availability.ts +0 -461
- package/tsconfig.json +0 -28
package/src/output-guardrails.ts
DELETED
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Output Guardrails for MCP Tool Response Truncation
|
|
3
|
-
*
|
|
4
|
-
* Prevents MCP tools from blowing out context with massive responses.
|
|
5
|
-
* Provides smart truncation that preserves JSON, code blocks, and markdown structure.
|
|
6
|
-
*
|
|
7
|
-
* @module output-guardrails
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* import { guardrailOutput, DEFAULT_GUARDRAIL_CONFIG } from "./output-guardrails"
|
|
12
|
-
*
|
|
13
|
-
* const result = guardrailOutput("context7_get-library-docs", hugeOutput)
|
|
14
|
-
* if (result.truncated) {
|
|
15
|
-
* console.log(`Truncated ${result.originalLength - result.truncatedLength} chars`)
|
|
16
|
-
* }
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Guardrail configuration for tool output limits
|
|
22
|
-
*
|
|
23
|
-
* Controls per-tool character limits and skip rules.
|
|
24
|
-
*/
|
|
25
|
-
export interface GuardrailConfig {
|
|
26
|
-
/**
|
|
27
|
-
* Default max characters for tool output
|
|
28
|
-
* Default: 32000 chars (~8000 tokens at 4 chars/token)
|
|
29
|
-
*/
|
|
30
|
-
defaultMaxChars: number;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Per-tool character limit overrides
|
|
34
|
-
*
|
|
35
|
-
* Higher limits for code/doc tools that commonly return large outputs.
|
|
36
|
-
*/
|
|
37
|
-
toolLimits: Record<string, number>;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Tools that should never be truncated
|
|
41
|
-
*
|
|
42
|
-
* Internal coordination tools (beads_*, swarmmail_*, structured_*)
|
|
43
|
-
* should always return complete output.
|
|
44
|
-
*/
|
|
45
|
-
skipTools: string[];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Result of guardrail output processing
|
|
50
|
-
*/
|
|
51
|
-
export interface GuardrailResult {
|
|
52
|
-
/** Processed output (truncated if needed) */
|
|
53
|
-
output: string;
|
|
54
|
-
|
|
55
|
-
/** Whether truncation occurred */
|
|
56
|
-
truncated: boolean;
|
|
57
|
-
|
|
58
|
-
/** Original output length in characters */
|
|
59
|
-
originalLength: number;
|
|
60
|
-
|
|
61
|
-
/** Final output length in characters */
|
|
62
|
-
truncatedLength: number;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Metrics for guardrail analytics
|
|
67
|
-
*
|
|
68
|
-
* Used to track truncation patterns and adjust limits.
|
|
69
|
-
*/
|
|
70
|
-
export interface GuardrailMetrics {
|
|
71
|
-
/** Tool that produced the output */
|
|
72
|
-
toolName: string;
|
|
73
|
-
|
|
74
|
-
/** Original output length */
|
|
75
|
-
originalLength: number;
|
|
76
|
-
|
|
77
|
-
/** Truncated output length */
|
|
78
|
-
truncatedLength: number;
|
|
79
|
-
|
|
80
|
-
/** Timestamp of truncation */
|
|
81
|
-
timestamp: number;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Default guardrail configuration
|
|
86
|
-
*
|
|
87
|
-
* - defaultMaxChars: 32000 (~8000 tokens)
|
|
88
|
-
* - Higher limits for code/doc tools (64000)
|
|
89
|
-
* - Skip internal coordination tools
|
|
90
|
-
*/
|
|
91
|
-
export const DEFAULT_GUARDRAIL_CONFIG: GuardrailConfig = {
|
|
92
|
-
defaultMaxChars: 32000,
|
|
93
|
-
|
|
94
|
-
toolLimits: {
|
|
95
|
-
// Higher limits for code/doc tools that commonly return large outputs
|
|
96
|
-
"repo-autopsy_file": 64000,
|
|
97
|
-
"repo-autopsy_search": 64000,
|
|
98
|
-
"repo-autopsy_exports_map": 64000,
|
|
99
|
-
"context7_get-library-docs": 64000,
|
|
100
|
-
cass_view: 64000,
|
|
101
|
-
cass_search: 48000,
|
|
102
|
-
skills_read: 48000,
|
|
103
|
-
|
|
104
|
-
// Lower limits for list/stats tools
|
|
105
|
-
"repo-autopsy_structure": 24000,
|
|
106
|
-
"repo-autopsy_stats": 16000,
|
|
107
|
-
cass_stats: 8000,
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
skipTools: [
|
|
111
|
-
// Beads tools - always return full output
|
|
112
|
-
"hive_create",
|
|
113
|
-
"hive_create_epic",
|
|
114
|
-
"hive_query",
|
|
115
|
-
"hive_update",
|
|
116
|
-
"hive_close",
|
|
117
|
-
"hive_start",
|
|
118
|
-
"hive_ready",
|
|
119
|
-
"hive_sync",
|
|
120
|
-
|
|
121
|
-
// Agent Mail tools - always return full output
|
|
122
|
-
"agentmail_init",
|
|
123
|
-
"agentmail_send",
|
|
124
|
-
"agentmail_inbox",
|
|
125
|
-
"agentmail_read_message",
|
|
126
|
-
"agentmail_summarize_thread",
|
|
127
|
-
"agentmail_reserve",
|
|
128
|
-
"agentmail_release",
|
|
129
|
-
"agentmail_ack",
|
|
130
|
-
|
|
131
|
-
// Swarm Mail tools - always return full output
|
|
132
|
-
"swarmmail_init",
|
|
133
|
-
"swarmmail_send",
|
|
134
|
-
"swarmmail_inbox",
|
|
135
|
-
"swarmmail_read_message",
|
|
136
|
-
"swarmmail_reserve",
|
|
137
|
-
"swarmmail_release",
|
|
138
|
-
"swarmmail_ack",
|
|
139
|
-
|
|
140
|
-
// Structured output tools - always return full output
|
|
141
|
-
"structured_extract_json",
|
|
142
|
-
"structured_validate",
|
|
143
|
-
"structured_parse_evaluation",
|
|
144
|
-
"structured_parse_decomposition",
|
|
145
|
-
"structured_parse_cell_tree",
|
|
146
|
-
|
|
147
|
-
// Swarm orchestration tools - always return full output
|
|
148
|
-
"swarm_select_strategy",
|
|
149
|
-
"swarm_plan_prompt",
|
|
150
|
-
"swarm_decompose",
|
|
151
|
-
"swarm_validate_decomposition",
|
|
152
|
-
"swarm_status",
|
|
153
|
-
"swarm_progress",
|
|
154
|
-
"swarm_complete",
|
|
155
|
-
"swarm_record_outcome",
|
|
156
|
-
"swarm_subtask_prompt",
|
|
157
|
-
"swarm_spawn_subtask",
|
|
158
|
-
"swarm_complete_subtask",
|
|
159
|
-
"swarm_evaluation_prompt",
|
|
160
|
-
|
|
161
|
-
// Mandate tools - always return full output
|
|
162
|
-
"mandate_file",
|
|
163
|
-
"mandate_vote",
|
|
164
|
-
"mandate_query",
|
|
165
|
-
"mandate_list",
|
|
166
|
-
"mandate_stats",
|
|
167
|
-
],
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Find matching closing brace for JSON truncation
|
|
172
|
-
*
|
|
173
|
-
* Walks forward from startIdx to find the matching closing brace,
|
|
174
|
-
* respecting nested braces and brackets.
|
|
175
|
-
*
|
|
176
|
-
* @param text - Text to search
|
|
177
|
-
* @param startIdx - Index of opening brace
|
|
178
|
-
* @returns Index of matching closing brace, or -1 if not found
|
|
179
|
-
*/
|
|
180
|
-
function findMatchingBrace(text: string, startIdx: number): number {
|
|
181
|
-
const openChar = text[startIdx];
|
|
182
|
-
const closeChar = openChar === "{" ? "}" : "]";
|
|
183
|
-
let depth = 1;
|
|
184
|
-
|
|
185
|
-
for (let i = startIdx + 1; i < text.length; i++) {
|
|
186
|
-
if (text[i] === openChar) {
|
|
187
|
-
depth++;
|
|
188
|
-
} else if (text[i] === closeChar) {
|
|
189
|
-
depth--;
|
|
190
|
-
if (depth === 0) {
|
|
191
|
-
return i;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return -1;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Smart truncation preserving structure boundaries
|
|
201
|
-
*
|
|
202
|
-
* Truncates text while preserving:
|
|
203
|
-
* - JSON structure (finds matching braces, doesn't cut mid-object)
|
|
204
|
-
* - Code blocks (preserves ``` boundaries)
|
|
205
|
-
* - Markdown headers (cuts at ## boundaries when possible)
|
|
206
|
-
*
|
|
207
|
-
* @param text - Text to truncate
|
|
208
|
-
* @param maxChars - Maximum character count
|
|
209
|
-
* @returns Truncated text with "[TRUNCATED - X chars removed]" suffix
|
|
210
|
-
*/
|
|
211
|
-
export function truncateWithBoundaries(text: string, maxChars: number): string {
|
|
212
|
-
if (text.length <= maxChars) {
|
|
213
|
-
return text;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Try to find a good truncation point
|
|
217
|
-
let truncateAt = maxChars;
|
|
218
|
-
|
|
219
|
-
// Check if we're in the middle of a JSON structure
|
|
220
|
-
const beforeTruncate = text.slice(0, maxChars);
|
|
221
|
-
const lastOpenBrace = Math.max(
|
|
222
|
-
beforeTruncate.lastIndexOf("{"),
|
|
223
|
-
beforeTruncate.lastIndexOf("["),
|
|
224
|
-
);
|
|
225
|
-
const lastCloseBrace = Math.max(
|
|
226
|
-
beforeTruncate.lastIndexOf("}"),
|
|
227
|
-
beforeTruncate.lastIndexOf("]"),
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
// If we have an unclosed brace/bracket, try to find the matching close
|
|
231
|
-
if (lastOpenBrace > lastCloseBrace) {
|
|
232
|
-
const matchingClose = findMatchingBrace(text, lastOpenBrace);
|
|
233
|
-
if (matchingClose !== -1 && matchingClose < maxChars * 1.2) {
|
|
234
|
-
// If the matching close is within 20% of maxChars, include it
|
|
235
|
-
truncateAt = matchingClose + 1;
|
|
236
|
-
} else {
|
|
237
|
-
// Otherwise, truncate before the unclosed brace
|
|
238
|
-
truncateAt = lastOpenBrace;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Check for code block boundaries (```)
|
|
243
|
-
const codeBlockMarker = "```";
|
|
244
|
-
const beforeTruncateForCode = text.slice(0, truncateAt);
|
|
245
|
-
const codeBlockCount = (beforeTruncateForCode.match(/```/g) || []).length;
|
|
246
|
-
|
|
247
|
-
// If we have an odd number of ``` markers, we're inside a code block
|
|
248
|
-
if (codeBlockCount % 2 === 1) {
|
|
249
|
-
// Try to find the closing ```
|
|
250
|
-
const closeMarkerIdx = text.indexOf(codeBlockMarker, truncateAt);
|
|
251
|
-
if (closeMarkerIdx !== -1 && closeMarkerIdx < maxChars * 1.2) {
|
|
252
|
-
// If close marker is within 20% of maxChars, include it
|
|
253
|
-
truncateAt = closeMarkerIdx + codeBlockMarker.length;
|
|
254
|
-
} else {
|
|
255
|
-
// Otherwise, truncate before the opening ```
|
|
256
|
-
const lastOpenMarker = beforeTruncateForCode.lastIndexOf(codeBlockMarker);
|
|
257
|
-
if (lastOpenMarker !== -1) {
|
|
258
|
-
truncateAt = lastOpenMarker;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Try to find a markdown header boundary (## or ###)
|
|
264
|
-
const headerMatch = text.slice(0, truncateAt).match(/\n#{1,6}\s/g);
|
|
265
|
-
if (headerMatch && headerMatch.length > 0) {
|
|
266
|
-
const lastHeaderIdx = beforeTruncateForCode.lastIndexOf("\n##");
|
|
267
|
-
if (lastHeaderIdx !== -1 && lastHeaderIdx > maxChars * 0.8) {
|
|
268
|
-
// If we have a header within 80% of maxChars, truncate there
|
|
269
|
-
truncateAt = lastHeaderIdx;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Ensure we don't truncate in the middle of a word
|
|
274
|
-
// Walk back to the last whitespace
|
|
275
|
-
while (truncateAt > 0 && !/\s/.test(text[truncateAt])) {
|
|
276
|
-
truncateAt--;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const truncated = text.slice(0, truncateAt).trimEnd();
|
|
280
|
-
const charsRemoved = text.length - truncated.length;
|
|
281
|
-
|
|
282
|
-
return `${truncated}\n\n[TRUNCATED - ${charsRemoved.toLocaleString()} chars removed]`;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Get the character limit for a specific tool
|
|
287
|
-
*
|
|
288
|
-
* @param toolName - Name of the tool
|
|
289
|
-
* @param config - Guardrail configuration
|
|
290
|
-
* @returns Character limit for the tool
|
|
291
|
-
*/
|
|
292
|
-
function getToolLimit(
|
|
293
|
-
toolName: string,
|
|
294
|
-
config: GuardrailConfig = DEFAULT_GUARDRAIL_CONFIG,
|
|
295
|
-
): number {
|
|
296
|
-
return config.toolLimits[toolName] ?? config.defaultMaxChars;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Apply guardrails to tool output
|
|
301
|
-
*
|
|
302
|
-
* Main entry point for guardrail processing:
|
|
303
|
-
* 1. Check if tool is in skipTools → return unchanged
|
|
304
|
-
* 2. Check if output.length > getToolLimit(toolName) → truncate
|
|
305
|
-
* 3. Return { output, truncated, originalLength, truncatedLength }
|
|
306
|
-
*
|
|
307
|
-
* @param toolName - Name of the tool that produced the output
|
|
308
|
-
* @param output - Tool output to process
|
|
309
|
-
* @param config - Optional guardrail configuration (defaults to DEFAULT_GUARDRAIL_CONFIG)
|
|
310
|
-
* @returns Guardrail result with truncated output and metadata
|
|
311
|
-
*
|
|
312
|
-
* @example
|
|
313
|
-
* ```typescript
|
|
314
|
-
* const result = guardrailOutput("context7_get-library-docs", hugeOutput)
|
|
315
|
-
* console.log(result.output) // Truncated or original
|
|
316
|
-
* console.log(result.truncated) // true if truncated
|
|
317
|
-
* console.log(`${result.originalLength} → ${result.truncatedLength} chars`)
|
|
318
|
-
* ```
|
|
319
|
-
*/
|
|
320
|
-
export function guardrailOutput(
|
|
321
|
-
toolName: string,
|
|
322
|
-
output: string,
|
|
323
|
-
config: GuardrailConfig = DEFAULT_GUARDRAIL_CONFIG,
|
|
324
|
-
): GuardrailResult {
|
|
325
|
-
const originalLength = output.length;
|
|
326
|
-
|
|
327
|
-
// Check if tool should be skipped
|
|
328
|
-
if (config.skipTools.includes(toolName)) {
|
|
329
|
-
return {
|
|
330
|
-
output,
|
|
331
|
-
truncated: false,
|
|
332
|
-
originalLength,
|
|
333
|
-
truncatedLength: originalLength,
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// Get the limit for this tool
|
|
338
|
-
const limit = getToolLimit(toolName, config);
|
|
339
|
-
|
|
340
|
-
// Check if truncation is needed
|
|
341
|
-
if (originalLength <= limit) {
|
|
342
|
-
return {
|
|
343
|
-
output,
|
|
344
|
-
truncated: false,
|
|
345
|
-
originalLength,
|
|
346
|
-
truncatedLength: originalLength,
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// Truncate with smart boundaries
|
|
351
|
-
const truncatedOutput = truncateWithBoundaries(output, limit);
|
|
352
|
-
const truncatedLength = truncatedOutput.length;
|
|
353
|
-
|
|
354
|
-
return {
|
|
355
|
-
output: truncatedOutput,
|
|
356
|
-
truncated: true,
|
|
357
|
-
originalLength,
|
|
358
|
-
truncatedLength,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Create a guardrail metrics entry
|
|
364
|
-
*
|
|
365
|
-
* Used for analytics and learning about truncation patterns.
|
|
366
|
-
*
|
|
367
|
-
* @param result - Guardrail result from guardrailOutput
|
|
368
|
-
* @param toolName - Name of the tool
|
|
369
|
-
* @returns Metrics entry
|
|
370
|
-
*/
|
|
371
|
-
export function createMetrics(
|
|
372
|
-
result: GuardrailResult,
|
|
373
|
-
toolName: string,
|
|
374
|
-
): GuardrailMetrics {
|
|
375
|
-
return {
|
|
376
|
-
toolName,
|
|
377
|
-
originalLength: result.originalLength,
|
|
378
|
-
truncatedLength: result.truncatedLength,
|
|
379
|
-
timestamp: Date.now(),
|
|
380
|
-
};
|
|
381
|
-
}
|