@compilr-dev/agents 0.3.13 → 0.3.15
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/README.md +3 -0
- package/dist/agent.js +85 -71
- package/dist/episodes/effort.d.ts +30 -0
- package/dist/episodes/effort.js +86 -0
- package/dist/episodes/index.d.ts +7 -0
- package/dist/episodes/index.js +7 -0
- package/dist/episodes/types.d.ts +158 -0
- package/dist/episodes/types.js +8 -0
- package/dist/guardrails/index.d.ts +2 -0
- package/dist/guardrails/index.js +1 -0
- package/dist/guardrails/manager.d.ts +21 -0
- package/dist/guardrails/manager.js +69 -1
- package/dist/guardrails/shell-parser.d.ts +36 -0
- package/dist/guardrails/shell-parser.js +103 -0
- package/dist/guardrails/types.d.ts +8 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +5 -1
- package/dist/mcp/client.js +6 -2
- package/dist/providers/gemini-native.js +8 -1
- package/dist/tools/builtin/glob.js +2 -0
- package/dist/tools/builtin/grep.js +2 -0
- package/dist/tools/builtin/read-file.js +2 -0
- package/dist/tools/builtin/todo.d.ts +8 -0
- package/dist/tools/builtin/todo.js +20 -2
- package/dist/tools/builtin/web-fetch.js +2 -0
- package/dist/tools/define.d.ts +7 -0
- package/dist/tools/define.js +1 -0
- package/dist/tools/types.d.ts +7 -0
- package/dist/tracing/index.d.ts +3 -0
- package/dist/tracing/index.js +4 -1
- package/dist/tracing/otel-attributes.d.ts +59 -0
- package/dist/tracing/otel-attributes.js +71 -0
- package/dist/tracing/otel-hooks.d.ts +61 -0
- package/dist/tracing/otel-hooks.js +220 -0
- package/package.json +7 -3
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell command tokenizer for guardrail compound command parsing
|
|
3
|
+
*
|
|
4
|
+
* Splits compound shell commands (cmd1 | cmd2 && cmd3) into individual
|
|
5
|
+
* subcommands so each can be validated independently against guardrails.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A parsed subcommand from a compound shell command
|
|
9
|
+
*/
|
|
10
|
+
export interface ShellToken {
|
|
11
|
+
/** Trimmed subcommand text */
|
|
12
|
+
command: string;
|
|
13
|
+
/** Operator that preceded this token (undefined for the first) */
|
|
14
|
+
operator?: '|' | '&&' | '||' | ';';
|
|
15
|
+
/** 0-based position in the command sequence */
|
|
16
|
+
index: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse a compound shell command into individual subcommands.
|
|
20
|
+
*
|
|
21
|
+
* Handles pipes, logical operators (&&, ||), semicolons, and respects
|
|
22
|
+
* single-quoted, double-quoted, and backtick-quoted strings.
|
|
23
|
+
*
|
|
24
|
+
* @param input - The full command string
|
|
25
|
+
* @returns Array of parsed subcommand tokens
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* parseShellCommand('ls && rm -rf /tmp')
|
|
30
|
+
* // => [
|
|
31
|
+
* // { command: 'ls', index: 0 },
|
|
32
|
+
* // { command: 'rm -rf /tmp', operator: '&&', index: 1 }
|
|
33
|
+
* // ]
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseShellCommand(input: string): ShellToken[];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell command tokenizer for guardrail compound command parsing
|
|
3
|
+
*
|
|
4
|
+
* Splits compound shell commands (cmd1 | cmd2 && cmd3) into individual
|
|
5
|
+
* subcommands so each can be validated independently against guardrails.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse a compound shell command into individual subcommands.
|
|
9
|
+
*
|
|
10
|
+
* Handles pipes, logical operators (&&, ||), semicolons, and respects
|
|
11
|
+
* single-quoted, double-quoted, and backtick-quoted strings.
|
|
12
|
+
*
|
|
13
|
+
* @param input - The full command string
|
|
14
|
+
* @returns Array of parsed subcommand tokens
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* parseShellCommand('ls && rm -rf /tmp')
|
|
19
|
+
* // => [
|
|
20
|
+
* // { command: 'ls', index: 0 },
|
|
21
|
+
* // { command: 'rm -rf /tmp', operator: '&&', index: 1 }
|
|
22
|
+
* // ]
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function parseShellCommand(input) {
|
|
26
|
+
const tokens = [];
|
|
27
|
+
let current = '';
|
|
28
|
+
let quote = null;
|
|
29
|
+
let i = 0;
|
|
30
|
+
let operator;
|
|
31
|
+
while (i < input.length) {
|
|
32
|
+
const ch = input[i];
|
|
33
|
+
// Handle escape sequences inside double quotes
|
|
34
|
+
if (ch === '\\' && quote === '"' && i + 1 < input.length) {
|
|
35
|
+
current += ch + input[i + 1];
|
|
36
|
+
i += 2;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// Toggle quote state
|
|
40
|
+
if ((ch === "'" || ch === '"' || ch === '`') && (quote === null || quote === ch)) {
|
|
41
|
+
quote = quote === ch ? null : ch;
|
|
42
|
+
current += ch;
|
|
43
|
+
i++;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
// Only split when outside quotes
|
|
47
|
+
if (quote === null) {
|
|
48
|
+
// && operator
|
|
49
|
+
if (ch === '&' && input[i + 1] === '&') {
|
|
50
|
+
pushToken(tokens, current, operator);
|
|
51
|
+
operator = '&&';
|
|
52
|
+
current = '';
|
|
53
|
+
i += 2;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// || operator (must check before single |)
|
|
57
|
+
if (ch === '|' && input[i + 1] === '|') {
|
|
58
|
+
pushToken(tokens, current, operator);
|
|
59
|
+
operator = '||';
|
|
60
|
+
current = '';
|
|
61
|
+
i += 2;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// | pipe (single)
|
|
65
|
+
if (ch === '|') {
|
|
66
|
+
pushToken(tokens, current, operator);
|
|
67
|
+
operator = '|';
|
|
68
|
+
current = '';
|
|
69
|
+
i++;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
// ; semicolon
|
|
73
|
+
if (ch === ';') {
|
|
74
|
+
pushToken(tokens, current, operator);
|
|
75
|
+
operator = ';';
|
|
76
|
+
current = '';
|
|
77
|
+
i++;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
current += ch;
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
// Push final segment
|
|
85
|
+
pushToken(tokens, current, operator);
|
|
86
|
+
return tokens;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Push a trimmed, non-empty token onto the array
|
|
90
|
+
*/
|
|
91
|
+
function pushToken(tokens, command, operator) {
|
|
92
|
+
const trimmed = command.trim();
|
|
93
|
+
if (trimmed.length === 0)
|
|
94
|
+
return;
|
|
95
|
+
const token = {
|
|
96
|
+
command: trimmed,
|
|
97
|
+
index: tokens.length,
|
|
98
|
+
};
|
|
99
|
+
if (operator !== undefined) {
|
|
100
|
+
token.operator = operator;
|
|
101
|
+
}
|
|
102
|
+
tokens.push(token);
|
|
103
|
+
}
|
|
@@ -94,6 +94,14 @@ export interface GuardrailResult {
|
|
|
94
94
|
* The input that triggered the guardrail
|
|
95
95
|
*/
|
|
96
96
|
input?: unknown;
|
|
97
|
+
/**
|
|
98
|
+
* The specific subcommand that triggered (compound commands only)
|
|
99
|
+
*/
|
|
100
|
+
subcommand?: string;
|
|
101
|
+
/**
|
|
102
|
+
* 0-based index of the subcommand in the compound command
|
|
103
|
+
*/
|
|
104
|
+
subcommandIndex?: number;
|
|
97
105
|
}
|
|
98
106
|
/**
|
|
99
107
|
* Context passed to guardrail handlers
|
package/dist/index.d.ts
CHANGED
|
@@ -60,9 +60,11 @@ export type { TokenUsage, UsageRecord, UsageStats, TokenBudgetConfig, BudgetStat
|
|
|
60
60
|
export { HooksManager } from './hooks/index.js';
|
|
61
61
|
export type { HooksManagerOptions } from './hooks/index.js';
|
|
62
62
|
export type { HooksConfig, HookRegistrationOptions, HookContext, IterationHookContext, LLMHookContext, AfterLLMHookContext, ToolHookContext, AfterToolHookContext, ErrorHookContext, BeforeIterationHook, AfterIterationHook, BeforeLLMHook, AfterLLMHook, BeforeToolHook, AfterToolHook, OnErrorHook, BeforeLLMHookResult, BeforeToolHookResult, AfterToolHookResult, ErrorHookResult, RegisteredHook, HookEventType, HookEvent, HookEventHandler, } from './hooks/index.js';
|
|
63
|
-
export { TracingManager, createTracingHooks, createLoggingHooks, mergeHooks, createStructuredLogger, createNoopLogger, createBufferedLogger, createTracingLogger, formatDuration, formatBytes, redactSensitive, createOTelExporter, createConsoleExporter, createBatchExporter, createMultiExporter, OTelNotInstalledError, isOTelNotInstalledError, SemanticAttributes, } from './tracing/index.js';
|
|
64
|
-
export type { Span, SpanStatus, SpanKind, SpanAttributes, SpanContext, SpanEvent, AttributeValue, Trace, TracingManagerOptions, StartSpanOptions, EndSpanOptions, TracingHooksConfig, TracingEvent, TracingEventHandler, OTelExporter, OTelSDK, OTelTracer, OTelSpan, LogLevel, LogEntry, StructuredLogger, StructuredLoggerOptions, TracingHookContext, TracingManagerInterface, } from './tracing/index.js';
|
|
63
|
+
export { TracingManager, createTracingHooks, createLoggingHooks, mergeHooks, createStructuredLogger, createNoopLogger, createBufferedLogger, createTracingLogger, formatDuration, formatBytes, redactSensitive, createOTelExporter, createConsoleExporter, createBatchExporter, createMultiExporter, OTelNotInstalledError, isOTelNotInstalledError, createOTelHooks, GenAIAttributes, AgentAttributes, PROVIDER_TO_SYSTEM, SemanticAttributes, } from './tracing/index.js';
|
|
64
|
+
export type { Span, SpanStatus, SpanKind, SpanAttributes, SpanContext, SpanEvent, AttributeValue, Trace, TracingManagerOptions, StartSpanOptions, EndSpanOptions, TracingHooksConfig, TracingEvent, TracingEventHandler, OTelExporter, OTelSDK, OTelTracer, OTelSpan, OTelHooksConfig, LogLevel, LogEntry, StructuredLogger, StructuredLoggerOptions, TracingHookContext, TracingManagerInterface, } from './tracing/index.js';
|
|
65
65
|
export { TokenBucketRateLimiter, createRateLimiter, createNoopRateLimiter, RateLimitExceededError, isRateLimitExceededError, withRetry, createRetryWithRateLimit, RetryPresets, RetryStats, RateLimitedProvider, wrapWithRateLimit, ProviderRateLimits, } from './rate-limit/index.js';
|
|
66
66
|
export type { RateLimiterConfig, RateLimiterStats, RetryConfig, RateLimitRetryConfig, AcquireResult, RateLimiter, } from './rate-limit/index.js';
|
|
67
67
|
export { RehearsalManager, createRehearsalManager, GitRehearsalAnalyzer, createGitAnalyzer, FileRehearsalAnalyzer, createFileAnalyzer, } from './rehearsal/index.js';
|
|
68
68
|
export type { ImpactSeverity, RehearsalRecommendation, OperationCategory, AffectedFile, RehearsalImpact, RehearsalResult, RehearsalContext, RehearsalAnalyzer, RehearsalManagerOptions, RehearsalEventType, RehearsalEvent, RehearsalEventHandler, } from './rehearsal/index.js';
|
|
69
|
+
export { estimateEffort, DEFAULT_WEIGHTS, EFFORT_ORDER } from './episodes/index.js';
|
|
70
|
+
export type { Effort, WorkEpisode, EffortSignals, EffortWeights, EffortSummary, ProjectWorkSummary, EpisodeStore, } from './episodes/index.js';
|
package/dist/index.js
CHANGED
|
@@ -83,8 +83,10 @@ TracingManager,
|
|
|
83
83
|
createTracingHooks, createLoggingHooks, mergeHooks,
|
|
84
84
|
// Structured logging
|
|
85
85
|
createStructuredLogger, createNoopLogger, createBufferedLogger, createTracingLogger, formatDuration, formatBytes, redactSensitive,
|
|
86
|
-
// OpenTelemetry integration
|
|
86
|
+
// OpenTelemetry integration (post-hoc exporter)
|
|
87
87
|
createOTelExporter, createConsoleExporter, createBatchExporter, createMultiExporter, OTelNotInstalledError, isOTelNotInstalledError,
|
|
88
|
+
// OpenTelemetry native hooks
|
|
89
|
+
createOTelHooks, GenAIAttributes, AgentAttributes, PROVIDER_TO_SYSTEM,
|
|
88
90
|
// Semantic conventions
|
|
89
91
|
SemanticAttributes, } from './tracing/index.js';
|
|
90
92
|
// Rate Limiting & Retry
|
|
@@ -97,3 +99,5 @@ withRetry, createRetryWithRateLimit, RetryPresets, RetryStats,
|
|
|
97
99
|
RateLimitedProvider, wrapWithRateLimit, ProviderRateLimits, } from './rate-limit/index.js';
|
|
98
100
|
// Rehearsal - Impact analysis for destructive operations
|
|
99
101
|
export { RehearsalManager, createRehearsalManager, GitRehearsalAnalyzer, createGitAnalyzer, FileRehearsalAnalyzer, createFileAnalyzer, } from './rehearsal/index.js';
|
|
102
|
+
// Episodes - Work history tracking with effort estimation
|
|
103
|
+
export { estimateEffort, DEFAULT_WEIGHTS, EFFORT_ORDER } from './episodes/index.js';
|
package/dist/mcp/client.js
CHANGED
|
@@ -20,15 +20,17 @@ async function getMCPSDK() {
|
|
|
20
20
|
return sdkCache;
|
|
21
21
|
try {
|
|
22
22
|
// Dynamic imports to keep SDK optional
|
|
23
|
-
const [clientModule, stdioModule, httpModule] = await Promise.all([
|
|
23
|
+
const [clientModule, stdioModule, httpModule, typesModule] = await Promise.all([
|
|
24
24
|
import('@modelcontextprotocol/sdk/client/index.js'),
|
|
25
25
|
import('@modelcontextprotocol/sdk/client/stdio.js'),
|
|
26
26
|
import('@modelcontextprotocol/sdk/client/streamableHttp.js'),
|
|
27
|
+
import('@modelcontextprotocol/sdk/types.js'),
|
|
27
28
|
]);
|
|
28
29
|
sdkCache = {
|
|
29
30
|
Client: clientModule.Client,
|
|
30
31
|
StdioClientTransport: stdioModule.StdioClientTransport,
|
|
31
32
|
StreamableHTTPClientTransport: httpModule.StreamableHTTPClientTransport,
|
|
33
|
+
ToolListChangedNotificationSchema: typesModule.ToolListChangedNotificationSchema,
|
|
32
34
|
};
|
|
33
35
|
// Non-null assertion safe: we just assigned sdkCache above
|
|
34
36
|
return sdkCache;
|
|
@@ -112,6 +114,7 @@ export class MCPClient {
|
|
|
112
114
|
args: this.config.stdio.args,
|
|
113
115
|
env: this.config.stdio.env,
|
|
114
116
|
cwd: this.config.stdio.cwd,
|
|
117
|
+
stderr: 'pipe', // Capture stderr to prevent bleeding into host terminal
|
|
115
118
|
});
|
|
116
119
|
}
|
|
117
120
|
else if (this.config.transport === 'http' && this.config.http) {
|
|
@@ -123,7 +126,8 @@ export class MCPClient {
|
|
|
123
126
|
version: this.config.clientVersion ?? '1.0.0',
|
|
124
127
|
});
|
|
125
128
|
// Set up notification handler for tools changed
|
|
126
|
-
|
|
129
|
+
// SDK 1.26+ requires Zod schema instead of string for notification handlers
|
|
130
|
+
this.client.setNotificationHandler(sdk.ToolListChangedNotificationSchema, () => {
|
|
127
131
|
this.cachedTools = null; // Invalidate cache
|
|
128
132
|
this.emit({ type: 'tools_changed', serverName: this.name });
|
|
129
133
|
});
|
|
@@ -199,9 +199,16 @@ export class GeminiNativeProvider {
|
|
|
199
199
|
case 'tool_result': {
|
|
200
200
|
// Convert to functionResponse
|
|
201
201
|
// block.content is a JSON string from the agent - parse it for the API
|
|
202
|
+
// Gemini requires response to be a Struct (object), never a string
|
|
202
203
|
let responseData;
|
|
203
204
|
try {
|
|
204
|
-
|
|
205
|
+
const parsed = JSON.parse(block.content);
|
|
206
|
+
// Ensure we always have an object — parse may return a string
|
|
207
|
+
// (double-encoded JSON) or a primitive
|
|
208
|
+
responseData =
|
|
209
|
+
typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)
|
|
210
|
+
? parsed
|
|
211
|
+
: { result: parsed };
|
|
205
212
|
}
|
|
206
213
|
catch {
|
|
207
214
|
// If not valid JSON, wrap the string in a result object
|
|
@@ -33,6 +33,7 @@ const DEFAULT_EXCLUDE_DIRS = [
|
|
|
33
33
|
*/
|
|
34
34
|
export const globTool = defineTool({
|
|
35
35
|
name: 'glob',
|
|
36
|
+
readonly: true,
|
|
36
37
|
description: 'Find files matching glob patterns. ' +
|
|
37
38
|
'Supports common patterns like **/*.ts for recursive matching. ' +
|
|
38
39
|
'Returns a list of matching file paths.',
|
|
@@ -222,6 +223,7 @@ function patternToRegex(pattern) {
|
|
|
222
223
|
export function createGlobTool(options) {
|
|
223
224
|
return defineTool({
|
|
224
225
|
name: 'glob',
|
|
226
|
+
readonly: true,
|
|
225
227
|
description: 'Find files matching glob patterns. ' +
|
|
226
228
|
'Supports common patterns like **/*.ts for recursive matching. ' +
|
|
227
229
|
'Returns a list of matching file paths.',
|
|
@@ -34,6 +34,7 @@ const DEFAULT_EXCLUDE_DIRS = [
|
|
|
34
34
|
*/
|
|
35
35
|
export const grepTool = defineTool({
|
|
36
36
|
name: 'grep',
|
|
37
|
+
readonly: true,
|
|
37
38
|
description: 'Search for patterns in files using regular expressions. ' +
|
|
38
39
|
'Can search a single file or recursively through directories. ' +
|
|
39
40
|
'Returns matching lines with optional context.',
|
|
@@ -319,6 +320,7 @@ function formatMatches(matches, options) {
|
|
|
319
320
|
export function createGrepTool(options) {
|
|
320
321
|
return defineTool({
|
|
321
322
|
name: 'grep',
|
|
323
|
+
readonly: true,
|
|
322
324
|
description: 'Search for patterns in files using regular expressions. ' +
|
|
323
325
|
'Can search a single file or recursively through directories. ' +
|
|
324
326
|
'Returns matching lines with optional context.',
|
|
@@ -18,6 +18,7 @@ const DEFAULT_MAX_CONTENT_SIZE = 100 * 1024;
|
|
|
18
18
|
*/
|
|
19
19
|
export const readFileTool = defineTool({
|
|
20
20
|
name: 'read_file',
|
|
21
|
+
readonly: true,
|
|
21
22
|
description: 'Read the contents of a file. Returns the file content as text. ' +
|
|
22
23
|
'Use maxLines and startLine to read specific portions of large files.',
|
|
23
24
|
inputSchema: {
|
|
@@ -137,6 +138,7 @@ function formatSize(bytes) {
|
|
|
137
138
|
export function createReadFileTool(options) {
|
|
138
139
|
return defineTool({
|
|
139
140
|
name: 'read_file',
|
|
141
|
+
readonly: true,
|
|
140
142
|
description: 'Read the contents of a file. Returns the file content as text. ' +
|
|
141
143
|
'Use maxLines and startLine to read specific portions of large files.',
|
|
142
144
|
inputSchema: {
|
|
@@ -38,6 +38,11 @@ export interface TodoItem {
|
|
|
38
38
|
* If undefined/null, the task is unassigned
|
|
39
39
|
*/
|
|
40
40
|
owner?: string;
|
|
41
|
+
/**
|
|
42
|
+
* 1-based task numbers this task is blocked by.
|
|
43
|
+
* References positions in the todo array.
|
|
44
|
+
*/
|
|
45
|
+
blockedBy?: number[];
|
|
41
46
|
/**
|
|
42
47
|
* Creation timestamp
|
|
43
48
|
*/
|
|
@@ -60,6 +65,7 @@ export interface TodoWriteInput {
|
|
|
60
65
|
activeForm?: string;
|
|
61
66
|
priority?: number;
|
|
62
67
|
owner?: string;
|
|
68
|
+
blockedBy?: number[];
|
|
63
69
|
}>;
|
|
64
70
|
}
|
|
65
71
|
/**
|
|
@@ -110,6 +116,7 @@ export declare class TodoStore {
|
|
|
110
116
|
activeForm?: string;
|
|
111
117
|
priority?: number;
|
|
112
118
|
owner?: string;
|
|
119
|
+
blockedBy?: number[];
|
|
113
120
|
}>): void;
|
|
114
121
|
/**
|
|
115
122
|
* Add a single todo
|
|
@@ -120,6 +127,7 @@ export declare class TodoStore {
|
|
|
120
127
|
activeForm?: string;
|
|
121
128
|
priority?: number;
|
|
122
129
|
owner?: string;
|
|
130
|
+
blockedBy?: number[];
|
|
123
131
|
}): TodoItem;
|
|
124
132
|
/**
|
|
125
133
|
* Update a todo by ID
|
|
@@ -64,6 +64,7 @@ export class TodoStore {
|
|
|
64
64
|
activeForm: todo.activeForm,
|
|
65
65
|
priority: todo.priority,
|
|
66
66
|
owner: todo.owner,
|
|
67
|
+
blockedBy: todo.blockedBy,
|
|
67
68
|
createdAt: now,
|
|
68
69
|
updatedAt: now,
|
|
69
70
|
});
|
|
@@ -82,6 +83,7 @@ export class TodoStore {
|
|
|
82
83
|
activeForm: todo.activeForm,
|
|
83
84
|
priority: todo.priority,
|
|
84
85
|
owner: todo.owner,
|
|
86
|
+
blockedBy: todo.blockedBy,
|
|
85
87
|
createdAt: now,
|
|
86
88
|
updatedAt: now,
|
|
87
89
|
};
|
|
@@ -158,7 +160,8 @@ export const todoWriteTool = defineTool({
|
|
|
158
160
|
name: 'todo_write',
|
|
159
161
|
description: 'Update the SESSION todo list (shown in CLI footer). These are ephemeral tasks for the current session only - ' +
|
|
160
162
|
'NOT persistent backlog items. For persistent project backlog, use workitem_* tools. ' +
|
|
161
|
-
'Provide the complete list to replace current todos.'
|
|
163
|
+
'Provide the complete list to replace current todos. ' +
|
|
164
|
+
'Use blockedBy to declare task dependencies (1-based positions in the array).',
|
|
162
165
|
inputSchema: {
|
|
163
166
|
type: 'object',
|
|
164
167
|
properties: {
|
|
@@ -189,6 +192,11 @@ export const todoWriteTool = defineTool({
|
|
|
189
192
|
type: 'string',
|
|
190
193
|
description: 'Owner agent ID (e.g., "dev", "pm", "arch"). Omit for unassigned tasks.',
|
|
191
194
|
},
|
|
195
|
+
blockedBy: {
|
|
196
|
+
type: 'array',
|
|
197
|
+
items: { type: 'number' },
|
|
198
|
+
description: 'Array of 1-based task numbers this task depends on (e.g., [3, 4] means blocked by task #3 and #4)',
|
|
199
|
+
},
|
|
192
200
|
},
|
|
193
201
|
required: ['content', 'status'],
|
|
194
202
|
},
|
|
@@ -220,6 +228,7 @@ export const todoWriteTool = defineTool({
|
|
|
220
228
|
*/
|
|
221
229
|
export const todoReadTool = defineTool({
|
|
222
230
|
name: 'todo_read',
|
|
231
|
+
readonly: true,
|
|
223
232
|
description: 'Get the SESSION todo list (shown in CLI footer). These are ephemeral session tasks - ' +
|
|
224
233
|
'for persistent project backlog, use workitem_query. Optionally filter by status or owner.',
|
|
225
234
|
inputSchema: {
|
|
@@ -268,6 +277,7 @@ export const todoReadTool = defineTool({
|
|
|
268
277
|
activeForm: t.activeForm,
|
|
269
278
|
priority: t.priority,
|
|
270
279
|
owner: t.owner,
|
|
280
|
+
blockedBy: t.blockedBy,
|
|
271
281
|
})),
|
|
272
282
|
counts,
|
|
273
283
|
total: todos.length,
|
|
@@ -282,7 +292,8 @@ export function createTodoTools(store) {
|
|
|
282
292
|
const todoWrite = defineTool({
|
|
283
293
|
name: 'todo_write',
|
|
284
294
|
description: 'Update the SESSION todo list (shown in CLI footer). These are ephemeral tasks for the current session only - ' +
|
|
285
|
-
'NOT persistent backlog items. For persistent project backlog, use workitem_* tools.'
|
|
295
|
+
'NOT persistent backlog items. For persistent project backlog, use workitem_* tools. ' +
|
|
296
|
+
'Use blockedBy to declare task dependencies (1-based positions in the array).',
|
|
286
297
|
inputSchema: {
|
|
287
298
|
type: 'object',
|
|
288
299
|
properties: {
|
|
@@ -297,6 +308,11 @@ export function createTodoTools(store) {
|
|
|
297
308
|
activeForm: { type: 'string' },
|
|
298
309
|
priority: { type: 'number' },
|
|
299
310
|
owner: { type: 'string' },
|
|
311
|
+
blockedBy: {
|
|
312
|
+
type: 'array',
|
|
313
|
+
items: { type: 'number' },
|
|
314
|
+
description: '1-based task numbers this task depends on',
|
|
315
|
+
},
|
|
300
316
|
},
|
|
301
317
|
required: ['content', 'status'],
|
|
302
318
|
},
|
|
@@ -325,6 +341,7 @@ export function createTodoTools(store) {
|
|
|
325
341
|
});
|
|
326
342
|
const todoRead = defineTool({
|
|
327
343
|
name: 'todo_read',
|
|
344
|
+
readonly: true,
|
|
328
345
|
description: 'Get the SESSION todo list (shown in CLI footer). These are ephemeral session tasks - ' +
|
|
329
346
|
'for persistent project backlog, use workitem_query.',
|
|
330
347
|
inputSchema: {
|
|
@@ -368,6 +385,7 @@ export function createTodoTools(store) {
|
|
|
368
385
|
activeForm: t.activeForm,
|
|
369
386
|
priority: t.priority,
|
|
370
387
|
owner: t.owner,
|
|
388
|
+
blockedBy: t.blockedBy,
|
|
371
389
|
})),
|
|
372
390
|
counts,
|
|
373
391
|
total: todos.length,
|
|
@@ -17,6 +17,7 @@ const DEFAULT_MAX_SIZE = 100 * 1024;
|
|
|
17
17
|
*/
|
|
18
18
|
export const webFetchTool = defineTool({
|
|
19
19
|
name: 'web_fetch',
|
|
20
|
+
readonly: true,
|
|
20
21
|
description: 'Fetch content from a URL. Returns the page content as text. ' +
|
|
21
22
|
'Use for retrieving documentation, API responses, or web pages. ' +
|
|
22
23
|
'HTTP URLs are automatically upgraded to HTTPS.',
|
|
@@ -168,6 +169,7 @@ export function createWebFetchTool(options) {
|
|
|
168
169
|
const { defaultTimeout = DEFAULT_TIMEOUT, defaultMaxSize = DEFAULT_MAX_SIZE, blockedDomains = [], allowedDomains, customHeaders = {}, } = options ?? {};
|
|
169
170
|
return defineTool({
|
|
170
171
|
name: 'web_fetch',
|
|
172
|
+
readonly: true,
|
|
171
173
|
description: 'Fetch content from a URL. Returns the page content as text. ' +
|
|
172
174
|
'Use for retrieving documentation, API responses, or web pages. ' +
|
|
173
175
|
'HTTP URLs are automatically upgraded to HTTPS.',
|
package/dist/tools/define.d.ts
CHANGED
|
@@ -35,6 +35,13 @@ export interface DefineToolOptions<T extends object> {
|
|
|
35
35
|
* Default: false (normal visibility)
|
|
36
36
|
*/
|
|
37
37
|
silent?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* If true, this tool performs no side effects (only reads data).
|
|
40
|
+
* Read-only tools are automatically batched for parallel execution
|
|
41
|
+
* even in a mixed batch with write tools.
|
|
42
|
+
* Default: false
|
|
43
|
+
*/
|
|
44
|
+
readonly?: boolean;
|
|
38
45
|
}
|
|
39
46
|
/**
|
|
40
47
|
* Define a tool with type-safe input handling
|
package/dist/tools/define.js
CHANGED
package/dist/tools/types.d.ts
CHANGED
|
@@ -78,6 +78,13 @@ export interface Tool<T = object> {
|
|
|
78
78
|
* Default: false (normal visibility)
|
|
79
79
|
*/
|
|
80
80
|
silent?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* If true, this tool performs no side effects (only reads data).
|
|
83
|
+
* Read-only tools are automatically batched for parallel execution
|
|
84
|
+
* even in a mixed batch with write tools.
|
|
85
|
+
* Default: false
|
|
86
|
+
*/
|
|
87
|
+
readonly?: boolean;
|
|
81
88
|
}
|
|
82
89
|
/**
|
|
83
90
|
* Fallback handler for tools not found in the primary registry.
|
package/dist/tracing/index.d.ts
CHANGED
|
@@ -47,5 +47,8 @@ export { TracingManager } from './manager.js';
|
|
|
47
47
|
export { createTracingHooks, createLoggingHooks, mergeHooks } from './hooks.js';
|
|
48
48
|
export { createStructuredLogger, createNoopLogger, createBufferedLogger, createTracingLogger, formatDuration, formatBytes, redactSensitive, } from './logging.js';
|
|
49
49
|
export { createOTelExporter, createConsoleExporter, createBatchExporter, createMultiExporter, OTelNotInstalledError, isOTelNotInstalledError, } from './otel.js';
|
|
50
|
+
export { createOTelHooks } from './otel-hooks.js';
|
|
51
|
+
export type { OTelHooksConfig } from './otel-hooks.js';
|
|
52
|
+
export { GenAIAttributes, AgentAttributes, PROVIDER_TO_SYSTEM } from './otel-attributes.js';
|
|
50
53
|
export type { Span, SpanStatus, SpanKind, SpanAttributes, SpanContext, SpanEvent, AttributeValue, Trace, TracingManagerOptions, StartSpanOptions, EndSpanOptions, TracingHooksConfig, TracingEvent, TracingEventHandler, OTelExporter, OTelSDK, OTelTracer, OTelSpan, LogLevel, LogEntry, StructuredLogger, StructuredLoggerOptions, TracingHookContext, TracingManagerInterface, } from './types.js';
|
|
51
54
|
export { SemanticAttributes } from './types.js';
|
package/dist/tracing/index.js
CHANGED
|
@@ -49,7 +49,10 @@ export { TracingManager } from './manager.js';
|
|
|
49
49
|
export { createTracingHooks, createLoggingHooks, mergeHooks } from './hooks.js';
|
|
50
50
|
// Structured logging
|
|
51
51
|
export { createStructuredLogger, createNoopLogger, createBufferedLogger, createTracingLogger, formatDuration, formatBytes, redactSensitive, } from './logging.js';
|
|
52
|
-
// OpenTelemetry integration
|
|
52
|
+
// OpenTelemetry integration (post-hoc exporter)
|
|
53
53
|
export { createOTelExporter, createConsoleExporter, createBatchExporter, createMultiExporter, OTelNotInstalledError, isOTelNotInstalledError, } from './otel.js';
|
|
54
|
+
// OpenTelemetry native hooks (real-time instrumentation)
|
|
55
|
+
export { createOTelHooks } from './otel-hooks.js';
|
|
56
|
+
export { GenAIAttributes, AgentAttributes, PROVIDER_TO_SYSTEM } from './otel-attributes.js';
|
|
54
57
|
// Semantic conventions
|
|
55
58
|
export { SemanticAttributes } from './types.js';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Semantic Convention Attributes
|
|
3
|
+
*
|
|
4
|
+
* Constants following the official OpenTelemetry gen_ai semantic conventions
|
|
5
|
+
* for LLM observability, plus agent-specific attributes.
|
|
6
|
+
*
|
|
7
|
+
* @see https://opentelemetry.io/docs/specs/semconv/gen-ai/
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* gen_ai.* semantic convention attributes for LLM operations
|
|
11
|
+
*/
|
|
12
|
+
export declare const GenAIAttributes: {
|
|
13
|
+
/** The AI system (e.g. 'anthropic', 'openai', 'google') */
|
|
14
|
+
readonly SYSTEM: "gen_ai.system";
|
|
15
|
+
/** The operation name (e.g. 'chat') */
|
|
16
|
+
readonly OPERATION_NAME: "gen_ai.operation.name";
|
|
17
|
+
/** The model requested */
|
|
18
|
+
readonly REQUEST_MODEL: "gen_ai.request.model";
|
|
19
|
+
/** Max tokens requested */
|
|
20
|
+
readonly REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens";
|
|
21
|
+
/** Temperature requested */
|
|
22
|
+
readonly REQUEST_TEMPERATURE: "gen_ai.request.temperature";
|
|
23
|
+
/** The model actually used in the response */
|
|
24
|
+
readonly RESPONSE_MODEL: "gen_ai.response.model";
|
|
25
|
+
/** Finish reasons (e.g. ['stop'], ['tool_calls']) */
|
|
26
|
+
readonly RESPONSE_FINISH_REASON: "gen_ai.response.finish_reasons";
|
|
27
|
+
/** Input token count */
|
|
28
|
+
readonly USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens";
|
|
29
|
+
/** Output token count */
|
|
30
|
+
readonly USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens";
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Agent-specific attributes for iteration and tool tracking
|
|
34
|
+
*/
|
|
35
|
+
export declare const AgentAttributes: {
|
|
36
|
+
/** Session ID for the agent run */
|
|
37
|
+
readonly SESSION_ID: "agent.session_id";
|
|
38
|
+
/** Current iteration number (1-indexed) */
|
|
39
|
+
readonly ITERATION_NUMBER: "agent.iteration.number";
|
|
40
|
+
/** Maximum allowed iterations */
|
|
41
|
+
readonly ITERATION_MAX: "agent.iteration.max";
|
|
42
|
+
/** Tool name being executed */
|
|
43
|
+
readonly TOOL_NAME: "agent.tool.name";
|
|
44
|
+
/** Whether the tool executed successfully */
|
|
45
|
+
readonly TOOL_SUCCESS: "agent.tool.success";
|
|
46
|
+
/** Tool execution duration in milliseconds */
|
|
47
|
+
readonly TOOL_DURATION_MS: "agent.tool.duration_ms";
|
|
48
|
+
/** Number of tool calls in the iteration */
|
|
49
|
+
readonly TOOL_CALL_COUNT: "agent.tool_call_count";
|
|
50
|
+
/** Number of messages in the conversation */
|
|
51
|
+
readonly MESSAGE_COUNT: "agent.message_count";
|
|
52
|
+
/** Whether the iteration completed with text (no tool calls) */
|
|
53
|
+
readonly COMPLETED_WITH_TEXT: "agent.completed_with_text";
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Maps provider names (as used in the agents library) to gen_ai.system values
|
|
57
|
+
* following OpenTelemetry semantic conventions.
|
|
58
|
+
*/
|
|
59
|
+
export declare const PROVIDER_TO_SYSTEM: Record<string, string>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Semantic Convention Attributes
|
|
3
|
+
*
|
|
4
|
+
* Constants following the official OpenTelemetry gen_ai semantic conventions
|
|
5
|
+
* for LLM observability, plus agent-specific attributes.
|
|
6
|
+
*
|
|
7
|
+
* @see https://opentelemetry.io/docs/specs/semconv/gen-ai/
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* gen_ai.* semantic convention attributes for LLM operations
|
|
11
|
+
*/
|
|
12
|
+
export const GenAIAttributes = {
|
|
13
|
+
/** The AI system (e.g. 'anthropic', 'openai', 'google') */
|
|
14
|
+
SYSTEM: 'gen_ai.system',
|
|
15
|
+
/** The operation name (e.g. 'chat') */
|
|
16
|
+
OPERATION_NAME: 'gen_ai.operation.name',
|
|
17
|
+
/** The model requested */
|
|
18
|
+
REQUEST_MODEL: 'gen_ai.request.model',
|
|
19
|
+
/** Max tokens requested */
|
|
20
|
+
REQUEST_MAX_TOKENS: 'gen_ai.request.max_tokens',
|
|
21
|
+
/** Temperature requested */
|
|
22
|
+
REQUEST_TEMPERATURE: 'gen_ai.request.temperature',
|
|
23
|
+
/** The model actually used in the response */
|
|
24
|
+
RESPONSE_MODEL: 'gen_ai.response.model',
|
|
25
|
+
/** Finish reasons (e.g. ['stop'], ['tool_calls']) */
|
|
26
|
+
RESPONSE_FINISH_REASON: 'gen_ai.response.finish_reasons',
|
|
27
|
+
/** Input token count */
|
|
28
|
+
USAGE_INPUT_TOKENS: 'gen_ai.usage.input_tokens',
|
|
29
|
+
/** Output token count */
|
|
30
|
+
USAGE_OUTPUT_TOKENS: 'gen_ai.usage.output_tokens',
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Agent-specific attributes for iteration and tool tracking
|
|
34
|
+
*/
|
|
35
|
+
export const AgentAttributes = {
|
|
36
|
+
/** Session ID for the agent run */
|
|
37
|
+
SESSION_ID: 'agent.session_id',
|
|
38
|
+
/** Current iteration number (1-indexed) */
|
|
39
|
+
ITERATION_NUMBER: 'agent.iteration.number',
|
|
40
|
+
/** Maximum allowed iterations */
|
|
41
|
+
ITERATION_MAX: 'agent.iteration.max',
|
|
42
|
+
/** Tool name being executed */
|
|
43
|
+
TOOL_NAME: 'agent.tool.name',
|
|
44
|
+
/** Whether the tool executed successfully */
|
|
45
|
+
TOOL_SUCCESS: 'agent.tool.success',
|
|
46
|
+
/** Tool execution duration in milliseconds */
|
|
47
|
+
TOOL_DURATION_MS: 'agent.tool.duration_ms',
|
|
48
|
+
/** Number of tool calls in the iteration */
|
|
49
|
+
TOOL_CALL_COUNT: 'agent.tool_call_count',
|
|
50
|
+
/** Number of messages in the conversation */
|
|
51
|
+
MESSAGE_COUNT: 'agent.message_count',
|
|
52
|
+
/** Whether the iteration completed with text (no tool calls) */
|
|
53
|
+
COMPLETED_WITH_TEXT: 'agent.completed_with_text',
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Maps provider names (as used in the agents library) to gen_ai.system values
|
|
57
|
+
* following OpenTelemetry semantic conventions.
|
|
58
|
+
*/
|
|
59
|
+
export const PROVIDER_TO_SYSTEM = {
|
|
60
|
+
claude: 'anthropic',
|
|
61
|
+
openai: 'openai',
|
|
62
|
+
gemini: 'google',
|
|
63
|
+
'gemini-native': 'google',
|
|
64
|
+
ollama: 'ollama',
|
|
65
|
+
groq: 'groq',
|
|
66
|
+
together: 'together_ai',
|
|
67
|
+
fireworks: 'fireworks_ai',
|
|
68
|
+
openrouter: 'openrouter',
|
|
69
|
+
perplexity: 'perplexity',
|
|
70
|
+
mock: 'mock',
|
|
71
|
+
};
|