@compilr-dev/agents 0.3.14 → 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/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.js +2 -0
- 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 +3 -1
|
@@ -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';
|
|
@@ -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: {
|
|
@@ -228,6 +228,7 @@ export const todoWriteTool = defineTool({
|
|
|
228
228
|
*/
|
|
229
229
|
export const todoReadTool = defineTool({
|
|
230
230
|
name: 'todo_read',
|
|
231
|
+
readonly: true,
|
|
231
232
|
description: 'Get the SESSION todo list (shown in CLI footer). These are ephemeral session tasks - ' +
|
|
232
233
|
'for persistent project backlog, use workitem_query. Optionally filter by status or owner.',
|
|
233
234
|
inputSchema: {
|
|
@@ -340,6 +341,7 @@ export function createTodoTools(store) {
|
|
|
340
341
|
});
|
|
341
342
|
const todoRead = defineTool({
|
|
342
343
|
name: 'todo_read',
|
|
344
|
+
readonly: true,
|
|
343
345
|
description: 'Get the SESSION todo list (shown in CLI footer). These are ephemeral session tasks - ' +
|
|
344
346
|
'for persistent project backlog, use workitem_query.',
|
|
345
347
|
inputSchema: {
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native OpenTelemetry Hooks
|
|
3
|
+
*
|
|
4
|
+
* Creates real OTel spans during agent execution with proper context propagation
|
|
5
|
+
* and gen_ai semantic conventions. Unlike the post-hoc `createOTelExporter()`,
|
|
6
|
+
* these hooks create spans in real time with correct parent-child relationships.
|
|
7
|
+
*
|
|
8
|
+
* Requires `@opentelemetry/api` (regular dependency, no-ops without SDK registered).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { createOTelHooks } from '@compilr-dev/agents';
|
|
13
|
+
*
|
|
14
|
+
* const hooks = createOTelHooks({
|
|
15
|
+
* providerName: 'claude',
|
|
16
|
+
* tracerName: 'my-agent',
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* const agent = new Agent({ provider, hooks });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { HooksConfig } from '../hooks/types.js';
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for OTel hooks
|
|
25
|
+
*/
|
|
26
|
+
export interface OTelHooksConfig {
|
|
27
|
+
/** Tracer name (default: '@compilr-dev/agents') */
|
|
28
|
+
tracerName?: string;
|
|
29
|
+
/** Tracer version */
|
|
30
|
+
tracerVersion?: string;
|
|
31
|
+
/** Provider name for gen_ai.system mapping (e.g. 'claude', 'openai') */
|
|
32
|
+
providerName?: string;
|
|
33
|
+
/** Trace iteration spans (default: true) */
|
|
34
|
+
traceIterations?: boolean;
|
|
35
|
+
/** Trace LLM call spans (default: true) */
|
|
36
|
+
traceLLM?: boolean;
|
|
37
|
+
/** Trace tool execution spans (default: true) */
|
|
38
|
+
traceTools?: boolean;
|
|
39
|
+
/** Include input/output content in span attributes (default: false) */
|
|
40
|
+
includeIO?: boolean;
|
|
41
|
+
/** Truncate attribute values at this length (default: 1000) */
|
|
42
|
+
truncateAt?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create native OpenTelemetry hooks for agent instrumentation.
|
|
46
|
+
*
|
|
47
|
+
* These hooks create real OTel spans during execution, as opposed to the
|
|
48
|
+
* post-hoc `createOTelExporter()` which recreates spans after the fact.
|
|
49
|
+
*
|
|
50
|
+
* Span hierarchy:
|
|
51
|
+
* ```
|
|
52
|
+
* agent.iteration [INTERNAL]
|
|
53
|
+
* ├── gen_ai.chat [CLIENT] (gen_ai.system, tokens, model)
|
|
54
|
+
* ├── agent.tool.read_file [INTERNAL] (tool.name, success, duration)
|
|
55
|
+
* └── agent.tool.bash [INTERNAL]
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @param config - Optional configuration
|
|
59
|
+
* @returns HooksConfig ready to pass to Agent constructor
|
|
60
|
+
*/
|
|
61
|
+
export declare function createOTelHooks(config?: OTelHooksConfig): HooksConfig;
|