@compilr-dev/sdk 0.7.23 → 0.7.25
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/dist/platform/tools/artifact-tools.js +7 -1
- package/dist/platform/tools/document-tools.js +12 -2
- package/dist/platform/tools/plan-tools.d.ts +1 -0
- package/dist/platform/tools/plan-tools.js +38 -2
- package/dist/platform/tools/truncate.d.ts +17 -0
- package/dist/platform/tools/truncate.js +27 -0
- package/dist/platform/tools/workitem-tools.js +18 -5
- package/dist/system-prompt/modules.js +28 -18
- package/dist/team/tool-config.js +7 -0
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - getTeamCheckpointer()/recordTeamActivity()/getCurrentProject() → artifacts.*
|
|
8
8
|
*/
|
|
9
9
|
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
10
|
+
import { truncateContent } from './truncate.js';
|
|
10
11
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
11
12
|
export function createArtifactTools(config) {
|
|
12
13
|
// Safe: callers guard with `if (config.context.artifacts)` before calling
|
|
@@ -131,6 +132,8 @@ export function createArtifactTools(config) {
|
|
|
131
132
|
}
|
|
132
133
|
return createErrorResult(message);
|
|
133
134
|
}
|
|
135
|
+
// Auto-truncate large artifact content
|
|
136
|
+
const tc = truncateContent(artifact.content);
|
|
134
137
|
const output = [
|
|
135
138
|
`Artifact: ${artifact.name}`,
|
|
136
139
|
``,
|
|
@@ -140,9 +143,12 @@ export function createArtifactTools(config) {
|
|
|
140
143
|
`Summary: ${artifact.summary}`,
|
|
141
144
|
`Created: ${artifact.createdAt.toISOString()}`,
|
|
142
145
|
`Updated: ${artifact.updatedAt.toISOString()}`,
|
|
146
|
+
...(tc.truncated
|
|
147
|
+
? [``, `[Content truncated: ${String(tc.originalChars)} chars total]`]
|
|
148
|
+
: []),
|
|
143
149
|
``,
|
|
144
150
|
`--- Content ---`,
|
|
145
|
-
|
|
151
|
+
tc.content,
|
|
146
152
|
].join('\n');
|
|
147
153
|
return createSuccessResult(output);
|
|
148
154
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* Ported from CLI's src/tools/document-db.ts.
|
|
9
9
|
*/
|
|
10
10
|
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
11
|
+
import { truncateContent } from './truncate.js';
|
|
11
12
|
/** All valid document types — keep in sync with DocumentType in types.ts. */
|
|
12
13
|
const DOC_TYPE_ENUM = [
|
|
13
14
|
// Software
|
|
@@ -253,15 +254,24 @@ export function createDocumentTools(config) {
|
|
|
253
254
|
content = allLines.slice(start, end).join('\n');
|
|
254
255
|
truncated = end < allLines.length;
|
|
255
256
|
}
|
|
257
|
+
// Auto-truncate large full reads to prevent context blowup
|
|
258
|
+
const tc = truncateContent(content);
|
|
259
|
+
if (tc.truncated)
|
|
260
|
+
truncated = true;
|
|
256
261
|
return createSuccessResult({
|
|
257
262
|
success: true,
|
|
258
263
|
document: {
|
|
259
264
|
id: doc.id,
|
|
260
265
|
docType: doc.docType,
|
|
261
266
|
title: doc.title,
|
|
262
|
-
content,
|
|
267
|
+
content: tc.content,
|
|
263
268
|
totalLines,
|
|
264
|
-
...(truncated
|
|
269
|
+
...(truncated
|
|
270
|
+
? {
|
|
271
|
+
truncated: true,
|
|
272
|
+
hint: 'Use summary_only, section, or startLine/maxLines for targeted reads',
|
|
273
|
+
}
|
|
274
|
+
: {}),
|
|
265
275
|
createdAt: doc.createdAt.toISOString(),
|
|
266
276
|
updatedAt: doc.updatedAt.toISOString(),
|
|
267
277
|
},
|
|
@@ -19,6 +19,7 @@ export declare function createPlanTools(config: PlatformToolsConfig): (import("@
|
|
|
19
19
|
}> | import("@compilr-dev/agents").Tool<{
|
|
20
20
|
plan_id?: number;
|
|
21
21
|
name?: string;
|
|
22
|
+
summary_only?: boolean;
|
|
22
23
|
project_id?: number;
|
|
23
24
|
}> | import("@compilr-dev/agents").Tool<{
|
|
24
25
|
project_id?: number;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Ported from CLI's src/tools/plan-tools.ts.
|
|
7
7
|
*/
|
|
8
8
|
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
9
|
+
import { truncateContent } from './truncate.js';
|
|
9
10
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
10
11
|
export function createPlanTools(config) {
|
|
11
12
|
const { context: ctx } = config;
|
|
@@ -140,7 +141,7 @@ export function createPlanTools(config) {
|
|
|
140
141
|
// ---------------------------------------------------------------------------
|
|
141
142
|
const planGetTool = defineTool({
|
|
142
143
|
name: 'plan_get',
|
|
143
|
-
description: 'Get a plan by ID or name. Returns
|
|
144
|
+
description: 'Get a plan by ID or name. Returns plan content and linked work item. Large plans are auto-truncated.',
|
|
144
145
|
inputSchema: {
|
|
145
146
|
type: 'object',
|
|
146
147
|
properties: {
|
|
@@ -152,6 +153,10 @@ export function createPlanTools(config) {
|
|
|
152
153
|
type: 'string',
|
|
153
154
|
description: 'Plan name (alternative to ID)',
|
|
154
155
|
},
|
|
156
|
+
summary_only: {
|
|
157
|
+
type: 'boolean',
|
|
158
|
+
description: 'If true, returns plan metadata and headings without full content.',
|
|
159
|
+
},
|
|
155
160
|
project_id: {
|
|
156
161
|
type: 'number',
|
|
157
162
|
description: 'Override active project (required for name lookup).',
|
|
@@ -185,13 +190,44 @@ export function createPlanTools(config) {
|
|
|
185
190
|
message: 'Plan not found',
|
|
186
191
|
});
|
|
187
192
|
}
|
|
193
|
+
// summary_only: return metadata + headings without full content
|
|
194
|
+
if (input.summary_only) {
|
|
195
|
+
const lines = plan.content.split('\n');
|
|
196
|
+
const headings = lines
|
|
197
|
+
.map((l, i) => ({ line: i + 1, heading: l.trim() }))
|
|
198
|
+
.filter((h) => h.heading.match(/^#{1,6}\s/));
|
|
199
|
+
return createSuccessResult({
|
|
200
|
+
success: true,
|
|
201
|
+
plan: {
|
|
202
|
+
id: plan.id,
|
|
203
|
+
name: plan.name,
|
|
204
|
+
status: plan.status,
|
|
205
|
+
totalChars: plan.content.length,
|
|
206
|
+
headings,
|
|
207
|
+
workItemId: plan.workItemId,
|
|
208
|
+
workItem: plan.workItem
|
|
209
|
+
? {
|
|
210
|
+
id: plan.workItem.id,
|
|
211
|
+
itemId: plan.workItem.itemId,
|
|
212
|
+
title: plan.workItem.title,
|
|
213
|
+
status: plan.workItem.status,
|
|
214
|
+
}
|
|
215
|
+
: null,
|
|
216
|
+
createdAt: plan.createdAt.toISOString(),
|
|
217
|
+
updatedAt: plan.updatedAt.toISOString(),
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// Auto-truncate large plans
|
|
222
|
+
const tc = truncateContent(plan.content);
|
|
188
223
|
return createSuccessResult({
|
|
189
224
|
success: true,
|
|
190
225
|
plan: {
|
|
191
226
|
id: plan.id,
|
|
192
227
|
name: plan.name,
|
|
193
|
-
content:
|
|
228
|
+
content: tc.content,
|
|
194
229
|
status: plan.status,
|
|
230
|
+
...(tc.truncated ? { truncated: true, originalChars: tc.originalChars } : {}),
|
|
195
231
|
workItemId: plan.workItemId,
|
|
196
232
|
workItem: plan.workItem
|
|
197
233
|
? {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared output truncation for platform tools.
|
|
3
|
+
*
|
|
4
|
+
* Uses head-and-tail strategy (70% head / 20% tail) matching
|
|
5
|
+
* the pattern used by read_file and bash in the agents library.
|
|
6
|
+
*/
|
|
7
|
+
/** Default max content size for tool output (~25K chars ≈ 6K tokens) */
|
|
8
|
+
export declare const DEFAULT_MAX_CONTENT_CHARS = 25000;
|
|
9
|
+
/**
|
|
10
|
+
* Truncate content using head-and-tail strategy.
|
|
11
|
+
* Returns the original content if under the limit.
|
|
12
|
+
*/
|
|
13
|
+
export declare function truncateContent(content: string, maxChars?: number): {
|
|
14
|
+
content: string;
|
|
15
|
+
truncated: boolean;
|
|
16
|
+
originalChars: number;
|
|
17
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared output truncation for platform tools.
|
|
3
|
+
*
|
|
4
|
+
* Uses head-and-tail strategy (70% head / 20% tail) matching
|
|
5
|
+
* the pattern used by read_file and bash in the agents library.
|
|
6
|
+
*/
|
|
7
|
+
/** Default max content size for tool output (~25K chars ≈ 6K tokens) */
|
|
8
|
+
export const DEFAULT_MAX_CONTENT_CHARS = 25_000;
|
|
9
|
+
/**
|
|
10
|
+
* Truncate content using head-and-tail strategy.
|
|
11
|
+
* Returns the original content if under the limit.
|
|
12
|
+
*/
|
|
13
|
+
export function truncateContent(content, maxChars = DEFAULT_MAX_CONTENT_CHARS) {
|
|
14
|
+
if (content.length <= maxChars) {
|
|
15
|
+
return { content, truncated: false, originalChars: content.length };
|
|
16
|
+
}
|
|
17
|
+
const headSize = Math.floor(maxChars * 0.7);
|
|
18
|
+
const tailSize = Math.floor(maxChars * 0.2);
|
|
19
|
+
const omitted = content.length - headSize - tailSize;
|
|
20
|
+
const head = content.slice(0, headSize);
|
|
21
|
+
const tail = content.slice(-tailSize);
|
|
22
|
+
return {
|
|
23
|
+
content: `${head}\n\n... [${String(omitted)} chars truncated — use startLine/maxLines or section for targeted reads] ...\n\n${tail}`,
|
|
24
|
+
truncated: true,
|
|
25
|
+
originalChars: content.length,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -102,15 +102,21 @@ export function createWorkItemTools(config) {
|
|
|
102
102
|
commitHash: item.commitHash,
|
|
103
103
|
createdAt: item.createdAt.toISOString(),
|
|
104
104
|
};
|
|
105
|
-
//
|
|
105
|
+
// Include recent comments for single-item lookup (max 10)
|
|
106
106
|
if (comments) {
|
|
107
107
|
const itemComments = await comments.listByWorkItem(item.id);
|
|
108
|
-
|
|
108
|
+
const MAX_COMMENTS = 10;
|
|
109
|
+
const limited = itemComments.slice(-MAX_COMMENTS);
|
|
110
|
+
itemData.comments = limited.map((c) => ({
|
|
109
111
|
id: c.id,
|
|
110
112
|
author: c.author,
|
|
111
|
-
content: c.content,
|
|
113
|
+
content: c.content.length > 2000 ? c.content.slice(0, 2000) + '... [truncated]' : c.content,
|
|
112
114
|
createdAt: c.createdAt.toISOString(),
|
|
113
115
|
}));
|
|
116
|
+
if (itemComments.length > MAX_COMMENTS) {
|
|
117
|
+
itemData.totalComments = itemComments.length;
|
|
118
|
+
itemData.commentsShown = MAX_COMMENTS;
|
|
119
|
+
}
|
|
114
120
|
}
|
|
115
121
|
return createSuccessResult({
|
|
116
122
|
success: true,
|
|
@@ -157,12 +163,19 @@ export function createWorkItemTools(config) {
|
|
|
157
163
|
return base;
|
|
158
164
|
if (wantFullComments) {
|
|
159
165
|
const itemComments = await comments.listByWorkItem(item.id);
|
|
160
|
-
|
|
166
|
+
const MAX_COMMENTS_PER_ITEM = 5;
|
|
167
|
+
const limited = itemComments.slice(-MAX_COMMENTS_PER_ITEM);
|
|
168
|
+
base.comments = limited.map((c) => ({
|
|
161
169
|
id: c.id,
|
|
162
170
|
author: c.author,
|
|
163
|
-
content: c.content
|
|
171
|
+
content: c.content.length > 2000
|
|
172
|
+
? c.content.slice(0, 2000) + '... [truncated]'
|
|
173
|
+
: c.content,
|
|
164
174
|
createdAt: c.createdAt.toISOString(),
|
|
165
175
|
}));
|
|
176
|
+
if (itemComments.length > MAX_COMMENTS_PER_ITEM) {
|
|
177
|
+
base.totalComments = itemComments.length;
|
|
178
|
+
}
|
|
166
179
|
}
|
|
167
180
|
else {
|
|
168
181
|
base.commentCount = await comments.countByWorkItem(item.id);
|
|
@@ -243,21 +243,31 @@ Project documents (drafts, outlines, analyses, plans) are stored in the **databa
|
|
|
243
243
|
export const DELEGATION_MODULE = {
|
|
244
244
|
id: 'delegation',
|
|
245
245
|
name: 'Token Efficiency & Delegation',
|
|
246
|
-
estimatedTokens:
|
|
247
|
-
content: `##
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
246
|
+
estimatedTokens: 350,
|
|
247
|
+
content: `## CRITICAL: Subagent Delegation
|
|
248
|
+
|
|
249
|
+
The **task** tool spawns a subagent that works in isolated context and returns a summary. This is your primary tool for exploration, search, and analysis.
|
|
250
|
+
|
|
251
|
+
**Why this matters:** Reading 5 files directly costs ~25,000 tokens in YOUR context. Delegating to a subagent costs ~200 tokens (tool call + summary). The subagent sees the full content but only the summary enters your history. This 100x reduction keeps your context clean for the actual work.
|
|
252
|
+
|
|
253
|
+
### ALWAYS delegate these:
|
|
254
|
+
- **File exploration**: "find files", "what's in this directory", "explore the codebase" → \`task(explore)\`
|
|
255
|
+
- **Code search**: "where is X defined", "find usages of Y", "how does Z work" → \`task(explore)\`
|
|
256
|
+
- **Analysis**: "analyze this module", "understand the architecture", "review this code" → \`task(code-review)\`
|
|
257
|
+
- **Multi-file reads**: Any task requiring 3+ file reads → \`task(explore)\`
|
|
258
|
+
- **Research**: web searches, documentation lookups → \`task(explore)\`
|
|
259
|
+
|
|
260
|
+
### NEVER delegate these:
|
|
261
|
+
- **Code edits**: Writing/editing files — do it yourself
|
|
262
|
+
- **Simple answers**: Questions you can answer from memory
|
|
263
|
+
- **User interaction**: Asking the user questions
|
|
264
|
+
- **Single file reads**: Reading 1-2 specific files the user pointed to
|
|
265
|
+
|
|
266
|
+
### Examples
|
|
267
|
+
- User: "What files implement the auth system?" → \`task({ type: "explore", message: "Find all files related to authentication..." })\`
|
|
268
|
+
- User: "How does the payment module work?" → \`task({ type: "explore", message: "Analyze the payment module..." })\`
|
|
269
|
+
- User: "Fix the bug in login.tsx" → Read login.tsx yourself, then edit it
|
|
270
|
+
- User: "Add a logout button" → Read the relevant file yourself, then edit it`,
|
|
261
271
|
};
|
|
262
272
|
/**
|
|
263
273
|
* Git safety module - only if hasGit=true
|
|
@@ -326,9 +336,9 @@ export const IMPORTANT_RULES_MODULE = {
|
|
|
326
336
|
4. Use todo_write for multi-step tasks (3+ steps)
|
|
327
337
|
5. Don't over-engineer - implement exactly what was asked
|
|
328
338
|
6. Check for security issues - fix insecure code immediately
|
|
329
|
-
7. **DELEGATE exploration to sub-agents** - use task(explore) for
|
|
330
|
-
8.
|
|
331
|
-
9.
|
|
339
|
+
7. **DELEGATE exploration to sub-agents** - use task(explore) for searches, analysis, and multi-file reads. Each file you read directly costs thousands of tokens in YOUR context. A subagent reads files in isolation and returns a compact summary.
|
|
340
|
+
8. When user asks "what files...", "where is...", "find...", "how does X work..." → ALWAYS use task(explore), never read files directly to answer
|
|
341
|
+
9. Call suggest tool after completing tasks (don't write "suggest:" as text)`,
|
|
332
342
|
};
|
|
333
343
|
/**
|
|
334
344
|
* Environment module - always included
|
package/dist/team/tool-config.js
CHANGED
|
@@ -431,6 +431,7 @@ export const TOOL_PROFILES = {
|
|
|
431
431
|
'interaction',
|
|
432
432
|
'handoff',
|
|
433
433
|
'guide',
|
|
434
|
+
'subagents',
|
|
434
435
|
'meta',
|
|
435
436
|
'git_read',
|
|
436
437
|
'project',
|
|
@@ -444,6 +445,7 @@ export const TOOL_PROFILES = {
|
|
|
444
445
|
'interaction',
|
|
445
446
|
'handoff',
|
|
446
447
|
'guide',
|
|
448
|
+
'subagents',
|
|
447
449
|
'meta',
|
|
448
450
|
'project',
|
|
449
451
|
'search',
|
|
@@ -460,6 +462,7 @@ export const TOOL_PROFILES = {
|
|
|
460
462
|
'interaction',
|
|
461
463
|
'handoff',
|
|
462
464
|
'guide',
|
|
465
|
+
'subagents',
|
|
463
466
|
'meta',
|
|
464
467
|
'git_read',
|
|
465
468
|
'git_write',
|
|
@@ -476,6 +479,7 @@ export const TOOL_PROFILES = {
|
|
|
476
479
|
'interaction',
|
|
477
480
|
'handoff',
|
|
478
481
|
'guide',
|
|
482
|
+
'subagents',
|
|
479
483
|
'meta',
|
|
480
484
|
'git_read',
|
|
481
485
|
'project',
|
|
@@ -490,6 +494,7 @@ export const TOOL_PROFILES = {
|
|
|
490
494
|
'interaction',
|
|
491
495
|
'handoff',
|
|
492
496
|
'guide',
|
|
497
|
+
'subagents',
|
|
493
498
|
'meta',
|
|
494
499
|
'git_read',
|
|
495
500
|
'project',
|
|
@@ -511,6 +516,7 @@ export const TOOL_PROFILES = {
|
|
|
511
516
|
'interaction',
|
|
512
517
|
'handoff',
|
|
513
518
|
'guide',
|
|
519
|
+
'subagents',
|
|
514
520
|
'meta',
|
|
515
521
|
'git_read',
|
|
516
522
|
'project',
|
|
@@ -532,6 +538,7 @@ export const TOOL_PROFILES = {
|
|
|
532
538
|
'interaction',
|
|
533
539
|
'handoff',
|
|
534
540
|
'guide',
|
|
541
|
+
'subagents',
|
|
535
542
|
'meta',
|
|
536
543
|
'project',
|
|
537
544
|
'backlog_read',
|