@bluecopa/harness 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +212 -117
  2. package/dist/arc/index.d.ts +796 -0
  3. package/dist/arc/index.js +2863 -0
  4. package/dist/arc/index.js.map +1 -0
  5. package/dist/observability/otel.d.ts +36 -0
  6. package/dist/observability/otel.js +73 -0
  7. package/dist/observability/otel.js.map +1 -0
  8. package/dist/shared-types-DRxnerLT.d.ts +138 -0
  9. package/dist/skills/index.d.ts +67 -0
  10. package/dist/skills/index.js +282 -0
  11. package/dist/skills/index.js.map +1 -0
  12. package/package.json +26 -2
  13. package/AGENTS.md +0 -18
  14. package/docs/guides/observability.md +0 -32
  15. package/docs/guides/providers.md +0 -51
  16. package/docs/guides/skills.md +0 -25
  17. package/docs/security/skill-sandbox-threat-model.md +0 -20
  18. package/src/agent/create-agent.ts +0 -884
  19. package/src/agent/create-tools.ts +0 -33
  20. package/src/agent/step-executor.ts +0 -15
  21. package/src/agent/types.ts +0 -57
  22. package/src/context/llm-compaction-strategy.ts +0 -37
  23. package/src/context/prepare-step.ts +0 -65
  24. package/src/context/token-tracker.ts +0 -26
  25. package/src/extracted/manifest.json +0 -10
  26. package/src/extracted/prompts/compaction.md +0 -5
  27. package/src/extracted/prompts/system.md +0 -5
  28. package/src/extracted/tools.json +0 -82
  29. package/src/hooks/hook-runner.ts +0 -22
  30. package/src/hooks/tool-wrappers.ts +0 -64
  31. package/src/interfaces/compaction-strategy.ts +0 -18
  32. package/src/interfaces/hooks.ts +0 -24
  33. package/src/interfaces/sandbox-provider.ts +0 -29
  34. package/src/interfaces/session-store.ts +0 -48
  35. package/src/interfaces/tool-provider.ts +0 -70
  36. package/src/loop/bridge.ts +0 -363
  37. package/src/loop/context-store.ts +0 -207
  38. package/src/loop/lcm-tool-loop.ts +0 -163
  39. package/src/loop/vercel-agent-loop.ts +0 -279
  40. package/src/observability/context.ts +0 -17
  41. package/src/observability/metrics.ts +0 -27
  42. package/src/observability/otel.ts +0 -105
  43. package/src/observability/tracing.ts +0 -13
  44. package/src/optimization/agent-evaluator.ts +0 -40
  45. package/src/optimization/config-serializer.ts +0 -16
  46. package/src/optimization/optimization-runner.ts +0 -39
  47. package/src/optimization/trace-collector.ts +0 -33
  48. package/src/permissions/permission-manager.ts +0 -34
  49. package/src/providers/composite-tool-provider.ts +0 -72
  50. package/src/providers/control-plane-e2b-executor.ts +0 -218
  51. package/src/providers/e2b-tool-provider.ts +0 -68
  52. package/src/providers/local-tool-provider.ts +0 -190
  53. package/src/providers/skill-sandbox-provider.ts +0 -46
  54. package/src/sessions/file-session-store.ts +0 -61
  55. package/src/sessions/in-memory-session-store.ts +0 -39
  56. package/src/sessions/session-manager.ts +0 -44
  57. package/src/skills/skill-loader.ts +0 -52
  58. package/src/skills/skill-manager.ts +0 -175
  59. package/src/skills/skill-router.ts +0 -99
  60. package/src/skills/skill-types.ts +0 -26
  61. package/src/subagents/subagent-manager.ts +0 -22
  62. package/src/subagents/task-tool.ts +0 -13
  63. package/tests/integration/agent-loop-basic.spec.ts +0 -56
  64. package/tests/integration/agent-skill-default-from-sandbox.spec.ts +0 -66
  65. package/tests/integration/concurrency-single-turn.spec.ts +0 -35
  66. package/tests/integration/otel-metrics-emission.spec.ts +0 -62
  67. package/tests/integration/otel-trace-propagation.spec.ts +0 -48
  68. package/tests/integration/parity-benchmark.spec.ts +0 -45
  69. package/tests/integration/provider-local-smoke.spec.ts +0 -63
  70. package/tests/integration/session-resume.spec.ts +0 -30
  71. package/tests/integration/skill-install-rollback.spec.ts +0 -64
  72. package/tests/integration/skill-sandbox-file-blob.spec.ts +0 -54
  73. package/tests/integration/skills-progressive-disclosure.spec.ts +0 -61
  74. package/tests/integration/streaming-compaction-boundary.spec.ts +0 -43
  75. package/tests/integration/structured-messages-agent.spec.ts +0 -265
  76. package/tests/integration/subagent-isolation.spec.ts +0 -24
  77. package/tests/security/skill-sandbox-isolation.spec.ts +0 -51
  78. package/tests/unit/create-tools-schema-parity.spec.ts +0 -22
  79. package/tests/unit/extracted-manifest.spec.ts +0 -41
  80. package/tests/unit/interfaces-contract.spec.ts +0 -101
  81. package/tests/unit/structured-messages.spec.ts +0 -176
  82. package/tests/unit/token-tracker.spec.ts +0 -22
  83. package/tsconfig.json +0 -14
  84. package/vitest.config.ts +0 -7
@@ -1,33 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
-
4
- export interface ExtractedToolSchema {
5
- name: string;
6
- description: string;
7
- input_schema: {
8
- type: string;
9
- properties?: Record<string, unknown>;
10
- required?: string[];
11
- additionalProperties?: boolean;
12
- };
13
- }
14
-
15
- export interface ExtractedToolsDocument {
16
- version: string;
17
- source: string;
18
- tools: ExtractedToolSchema[];
19
- }
20
-
21
- export function loadExtractedTools(docPath?: string): ExtractedToolsDocument {
22
- const path = docPath ?? resolve(import.meta.dirname, '../extracted/tools.json');
23
- return JSON.parse(readFileSync(path, 'utf8')) as ExtractedToolsDocument;
24
- }
25
-
26
- export function createToolRegistry(docPath?: string): Map<string, ExtractedToolSchema> {
27
- const extracted = loadExtractedTools(docPath);
28
- return new Map(extracted.tools.map((tool) => [tool.name, tool]));
29
- }
30
-
31
- export function extractedToolNames(docPath?: string): string[] {
32
- return loadExtractedTools(docPath).tools.map((tool) => tool.name);
33
- }
@@ -1,15 +0,0 @@
1
- export type StepTask<T> = () => Promise<T>;
2
-
3
- // Ensures only one step task executes at a time for deterministic turn ordering.
4
- export class SingleFlightStepExecutor {
5
- private queue = Promise.resolve();
6
-
7
- run<T>(task: StepTask<T>): Promise<T> {
8
- const next = this.queue.then(task, task);
9
- this.queue = next.then(
10
- () => undefined,
11
- () => undefined
12
- );
13
- return next;
14
- }
15
- }
@@ -1,57 +0,0 @@
1
- export interface ToolCallInfo {
2
- toolCallId: string;
3
- toolName: string;
4
- args: Record<string, unknown>;
5
- }
6
-
7
- export interface ToolResultInfo {
8
- toolCallId: string;
9
- toolName: string;
10
- result: string;
11
- isError?: boolean;
12
- }
13
-
14
- export interface AgentMessage {
15
- role: 'system' | 'user' | 'assistant' | 'tool';
16
- content: string;
17
- toolCalls?: ToolCallInfo[]; // assistant messages: what tools were called
18
- toolResults?: ToolResultInfo[]; // tool messages: results keyed by toolCallId
19
- }
20
-
21
- export interface ToolCallAction {
22
- type: 'tool';
23
- name: string;
24
- args: Record<string, unknown>;
25
- toolCallId?: string;
26
- }
27
-
28
- export interface FinalAction {
29
- type: 'final';
30
- content: string;
31
- }
32
-
33
- export interface ToolBatchAction {
34
- type: 'tool_batch';
35
- calls: ToolCallAction[];
36
- }
37
-
38
- export type AgentAction = ToolCallAction | FinalAction | ToolBatchAction;
39
-
40
- export interface AgentRunResult {
41
- messages: AgentMessage[];
42
- output: string;
43
- steps: number;
44
- }
45
-
46
- export type AgentStreamEvent =
47
- | { type: 'text_delta'; text: string }
48
- | { type: 'tool_start'; name: string; args: Record<string, unknown>; toolCallId?: string }
49
- | { type: 'tool_end'; name: string; result: { success: boolean; output: string; error?: string } }
50
- | { type: 'step_start'; step: number }
51
- | { type: 'step_end'; step: number }
52
- | { type: 'done'; output: string; steps: number };
53
-
54
- export interface AgentLoop {
55
- nextAction(messages: AgentMessage[]): Promise<AgentAction>;
56
- streamAction?(messages: AgentMessage[]): AsyncIterable<AgentStreamEvent>;
57
- }
@@ -1,37 +0,0 @@
1
- import type { CompactionInput, CompactionResult, CompactionStrategy } from '../interfaces/compaction-strategy';
2
- import type { Message } from '../interfaces/session-store';
3
-
4
- export class LLMCompactionStrategy implements CompactionStrategy {
5
- constructor(private readonly thresholdRatio = 0.85) {}
6
-
7
- shouldCompact(input: CompactionInput): boolean {
8
- return input.tokenCount >= Math.floor(input.maxTokens * this.thresholdRatio);
9
- }
10
-
11
- async compact(input: CompactionInput): Promise<CompactionResult> {
12
- const { messages } = input;
13
-
14
- if (messages.length <= 2) {
15
- return {
16
- compactedMessages: messages,
17
- summary: 'No compaction required',
18
- newBoundary: messages.length - 1
19
- };
20
- }
21
-
22
- const preserveTail = 2;
23
- const head = messages.slice(0, Math.max(0, messages.length - preserveTail));
24
- const tail = messages.slice(-preserveTail);
25
-
26
- const summary: Message = {
27
- role: 'system',
28
- content: `Compaction summary: condensed ${head.length} earlier message(s).`
29
- };
30
-
31
- return {
32
- compactedMessages: [summary, ...tail],
33
- summary: summary.content,
34
- newBoundary: head.length
35
- };
36
- }
37
- }
@@ -1,65 +0,0 @@
1
- import type { Message } from '../interfaces/session-store';
2
- import type { CompactionStrategy } from '../interfaces/compaction-strategy';
3
- import type { HarnessTelemetry } from '../observability/otel';
4
- import { recordCompaction } from '../observability/metrics';
5
- import { traceStep } from '../observability/tracing';
6
- import { TokenTracker } from './token-tracker';
7
-
8
- export interface PrepareStepState {
9
- pendingCompaction?: boolean;
10
- compactionBoundary?: number;
11
- }
12
-
13
- export interface PrepareStepInput {
14
- messages: Message[];
15
- maxTokens: number;
16
- isStreaming: boolean;
17
- state: PrepareStepState;
18
- tokenTracker: TokenTracker;
19
- compactionStrategy: CompactionStrategy;
20
- telemetry?: HarnessTelemetry;
21
- }
22
-
23
- export interface PrepareStepOutput {
24
- messages: Message[];
25
- state: PrepareStepState;
26
- }
27
-
28
- export async function prepareStep(input: PrepareStepInput): Promise<PrepareStepOutput> {
29
- const { messages, maxTokens, isStreaming, state, tokenTracker, compactionStrategy, telemetry } = input;
30
- const tokenCount = tokenTracker.countMessages(messages);
31
-
32
- const shouldCompactNow = state.pendingCompaction || compactionStrategy.shouldCompact({
33
- messages,
34
- tokenCount,
35
- maxTokens
36
- });
37
-
38
- if (!shouldCompactNow) {
39
- return { messages, state };
40
- }
41
-
42
- if (isStreaming) {
43
- return {
44
- messages,
45
- state: { ...state, pendingCompaction: true }
46
- };
47
- }
48
-
49
- const compacted = await traceStep(telemetry, 'context.compaction', { tokenCount, maxTokens }, () =>
50
- compactionStrategy.compact({
51
- messages,
52
- tokenCount,
53
- maxTokens
54
- })
55
- );
56
- recordCompaction(telemetry);
57
-
58
- return {
59
- messages: compacted.compactedMessages,
60
- state: {
61
- pendingCompaction: false,
62
- compactionBoundary: compacted.newBoundary
63
- }
64
- };
65
- }
@@ -1,26 +0,0 @@
1
- import type { Message } from '../interfaces/session-store';
2
-
3
- export interface TokenCountOptions {
4
- estimator?: (text: string) => number;
5
- }
6
-
7
- export class TokenTracker {
8
- constructor(private readonly options: TokenCountOptions = {}) {}
9
-
10
- private estimate(text: string): number {
11
- if (this.options.estimator) {
12
- return this.options.estimator(text);
13
- }
14
-
15
- // Fast fallback estimator for provider-agnostic usage.
16
- return Math.ceil(text.length / 4);
17
- }
18
-
19
- countText(text: string): number {
20
- return this.estimate(text);
21
- }
22
-
23
- countMessages(messages: Message[]): number {
24
- return messages.reduce((sum, message) => sum + this.estimate(message.content), 0);
25
- }
26
- }
@@ -1,10 +0,0 @@
1
- {
2
- "schemaVersion": "1.0.0",
3
- "sourceCommit": "pending-extraction",
4
- "extractedAt": "2026-02-22T19:42:33.319Z",
5
- "checksums": {
6
- "tools": "3f7794093f9dd302d3fd547b6a30f68242e183526ae608e32e5827c31a065083",
7
- "systemPrompt": "700b33b01a81750c7f0df34a6a8ad7665b994e53fd58a4b1f9e4591b4cece18c",
8
- "compactionPrompt": "89032b0b1b45bdfae86732b88fb0fca25e542b2e2c6efca5e2e6efbe9e785cb0"
9
- }
10
- }
@@ -1,5 +0,0 @@
1
- # Compaction Prompt Baseline
2
-
3
- This file contains the compaction prompt baseline used when context exceeds limits.
4
-
5
- Status: placeholder baseline captured from requirements doc. Replace with extracted prompt material from source repositories before production release.
@@ -1,5 +0,0 @@
1
- # System Prompt Baseline
2
-
3
- This file contains the extracted baseline system instructions used for parity testing.
4
-
5
- Status: placeholder baseline captured from requirements doc. Replace with extracted prompt material from source repositories before production release.
@@ -1,82 +0,0 @@
1
- {
2
- "version": "2026-02-22",
3
- "source": "claude-agent-sdk parity baseline",
4
- "tools": [
5
- {
6
- "name": "Bash",
7
- "description": "Run shell commands in the execution environment.",
8
- "input_schema": {
9
- "type": "object",
10
- "properties": {
11
- "command": { "type": "string" }
12
- },
13
- "required": ["command"],
14
- "additionalProperties": false
15
- }
16
- },
17
- {
18
- "name": "Read",
19
- "description": "Read a file from disk.",
20
- "input_schema": {
21
- "type": "object",
22
- "properties": {
23
- "path": { "type": "string" }
24
- },
25
- "required": ["path"],
26
- "additionalProperties": false
27
- }
28
- },
29
- {
30
- "name": "Write",
31
- "description": "Write content to a file.",
32
- "input_schema": {
33
- "type": "object",
34
- "properties": {
35
- "path": { "type": "string" },
36
- "content": { "type": "string" }
37
- },
38
- "required": ["path", "content"],
39
- "additionalProperties": false
40
- }
41
- },
42
- {
43
- "name": "Edit",
44
- "description": "Apply targeted text edits to a file.",
45
- "input_schema": {
46
- "type": "object",
47
- "properties": {
48
- "path": { "type": "string" },
49
- "old_text": { "type": "string" },
50
- "new_text": { "type": "string" }
51
- },
52
- "required": ["path", "old_text", "new_text"],
53
- "additionalProperties": false
54
- }
55
- },
56
- {
57
- "name": "Glob",
58
- "description": "Find files by glob pattern.",
59
- "input_schema": {
60
- "type": "object",
61
- "properties": {
62
- "pattern": { "type": "string" }
63
- },
64
- "required": ["pattern"],
65
- "additionalProperties": false
66
- }
67
- },
68
- {
69
- "name": "Grep",
70
- "description": "Search file contents with a pattern.",
71
- "input_schema": {
72
- "type": "object",
73
- "properties": {
74
- "pattern": { "type": "string" },
75
- "path": { "type": "string" }
76
- },
77
- "required": ["pattern"],
78
- "additionalProperties": false
79
- }
80
- }
81
- ]
82
- }
@@ -1,22 +0,0 @@
1
- import type { HookCallback, HookContext, HookDecision } from '../interfaces/hooks';
2
-
3
- export class HookRunner {
4
- private readonly hooks = new Map<string, HookCallback[]>();
5
-
6
- register(event: HookContext['event'], callback: HookCallback): void {
7
- const list = this.hooks.get(event) ?? [];
8
- list.push(callback);
9
- this.hooks.set(event, list);
10
- }
11
-
12
- async run(context: HookContext): Promise<HookDecision> {
13
- const list = this.hooks.get(context.event) ?? [];
14
- for (const hook of list) {
15
- const result = await hook(context);
16
- if (result && result.allow === false) {
17
- return result;
18
- }
19
- }
20
- return { allow: true };
21
- }
22
- }
@@ -1,64 +0,0 @@
1
- import type { ToolProvider, ToolResult } from '../interfaces/tool-provider';
2
- import { HookRunner } from './hook-runner';
3
- import { PermissionManager } from '../permissions/permission-manager';
4
- import type { HarnessTelemetry } from '../observability/otel';
5
- import { recordToolCallDuration } from '../observability/metrics';
6
- import { traceStep } from '../observability/tracing';
7
-
8
- export function withHooks(
9
- provider: ToolProvider,
10
- hookRunner: HookRunner,
11
- permissionManager: PermissionManager,
12
- telemetry?: HarnessTelemetry
13
- ): ToolProvider {
14
- async function guarded(
15
- toolName: string,
16
- input: Record<string, unknown>,
17
- execute: () => Promise<ToolResult>
18
- ): Promise<ToolResult> {
19
- return traceStep(telemetry, 'tool.call', { tool: toolName }, async () => {
20
- const started = Date.now();
21
- const pre = await hookRunner.run({ event: 'PreToolUse', toolName, input });
22
- if (!pre.allow) {
23
- const result = { success: false, output: '', error: pre.reason ?? 'blocked by pre-hook' };
24
- recordToolCallDuration(telemetry, toolName, Date.now() - started, false);
25
- return result;
26
- }
27
-
28
- const permission = await permissionManager.check({ toolName, input });
29
- if (!permission.allow) {
30
- const result = {
31
- success: false,
32
- output: '',
33
- error: permission.reason ?? 'blocked by permission manager'
34
- };
35
- recordToolCallDuration(telemetry, toolName, Date.now() - started, false);
36
- return result;
37
- }
38
-
39
- const result = await execute();
40
- await hookRunner.run({ event: 'PostToolUse', toolName, input, output: result });
41
- recordToolCallDuration(telemetry, toolName, Date.now() - started, result.success);
42
- return result;
43
- });
44
- }
45
-
46
- return {
47
- capabilities: () => provider.capabilities(),
48
- initialize: provider.initialize?.bind(provider),
49
- destroy: provider.destroy?.bind(provider),
50
- bash: (command, options) => guarded('Bash', { command }, () => provider.bash(command, options)),
51
- readFile: (path, options) => guarded('Read', { path }, () => provider.readFile(path, options)),
52
- writeFile: (path, content) => guarded('Write', { path }, () => provider.writeFile(path, content)),
53
- editFile: (path, oldText, newText) =>
54
- guarded('Edit', { path, oldText, newText }, () => provider.editFile(path, oldText, newText)),
55
- glob: (pattern, options) => guarded('Glob', { pattern }, () => provider.glob(pattern, options)),
56
- grep: (pattern, path, options) => guarded('Grep', { pattern, path }, () => provider.grep(pattern, path, options)),
57
- webFetch: provider.webFetch
58
- ? (options) => guarded('WebFetch', { url: options.url }, () => provider.webFetch!(options))
59
- : undefined,
60
- webSearch: provider.webSearch
61
- ? (query) => guarded('WebSearch', { query }, () => provider.webSearch!(query))
62
- : undefined
63
- };
64
- }
@@ -1,18 +0,0 @@
1
- import type { Message } from './session-store';
2
-
3
- export interface CompactionInput {
4
- messages: Message[];
5
- tokenCount: number;
6
- maxTokens: number;
7
- }
8
-
9
- export interface CompactionResult {
10
- compactedMessages: Message[];
11
- summary: string;
12
- newBoundary: number;
13
- }
14
-
15
- export interface CompactionStrategy {
16
- shouldCompact(input: CompactionInput): boolean;
17
- compact(input: CompactionInput): Promise<CompactionResult>;
18
- }
@@ -1,24 +0,0 @@
1
- import type { ToolResult } from './tool-provider';
2
-
3
- export type HookEventName =
4
- | 'PreToolUse'
5
- | 'PostToolUse'
6
- | 'SessionStart'
7
- | 'SessionEnd'
8
- | 'CompactionStart'
9
- | 'CompactionEnd';
10
-
11
- export interface HookContext {
12
- event: HookEventName;
13
- toolName?: string;
14
- input?: Record<string, unknown>;
15
- output?: ToolResult;
16
- metadata?: Record<string, unknown>;
17
- }
18
-
19
- export interface HookDecision {
20
- allow: boolean;
21
- reason?: string;
22
- }
23
-
24
- export type HookCallback = (context: HookContext) => Promise<HookDecision | void>;
@@ -1,29 +0,0 @@
1
- export interface SandboxExecResult {
2
- exitCode: number;
3
- stdout: string;
4
- stderr: string;
5
- }
6
-
7
- export interface SandboxExecOptions {
8
- cwd?: string | undefined;
9
- timeoutMs?: number | undefined;
10
- env?: Record<string, string> | undefined;
11
- }
12
-
13
- export interface SandboxFileBlob {
14
- data: Uint8Array;
15
- mimeType?: string | undefined;
16
- filename?: string | undefined;
17
- }
18
-
19
- export interface SandboxProvider {
20
- initialize?(): Promise<void>;
21
- destroy?(): Promise<void>;
22
- exec(command: string, options?: SandboxExecOptions): Promise<SandboxExecResult>;
23
- readSandboxFile(path: string): Promise<SandboxFileBlob>;
24
- writeSandboxFile(path: string, content: SandboxFileBlob): Promise<void>;
25
- upload?(localPath: string, remotePath: string): Promise<void>;
26
- listFiles?(path: string): Promise<string[]>;
27
- snapshot?(): Promise<string>;
28
- restore?(snapshotId: string): Promise<void>;
29
- }
@@ -1,48 +0,0 @@
1
- export type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
2
-
3
- export interface Message {
4
- role: MessageRole;
5
- content: string;
6
- createdAt?: string;
7
- }
8
-
9
- export interface ExecutionTrace {
10
- events: Array<Record<string, unknown>>;
11
- metadata?: Record<string, unknown>;
12
- }
13
-
14
- export interface AgentSession {
15
- id: string;
16
- createdAt: Date;
17
- updatedAt: Date;
18
- messages: Message[];
19
- compactionBoundary?: number;
20
- providerState?: string;
21
- metadata: Record<string, unknown>;
22
- trace?: ExecutionTrace;
23
- task?: { prompt: string; metadata?: Record<string, unknown> };
24
- status: 'running' | 'completed' | 'failed' | 'timeout';
25
- score?: number | Record<string, number>;
26
- configHash?: string;
27
- }
28
-
29
- export interface SessionFilter {
30
- status?: AgentSession['status'];
31
- scoredOnly?: boolean;
32
- scoreBelow?: number;
33
- scoreAbove?: number;
34
- configHash?: string;
35
- taskPromptContains?: string;
36
- after?: Date;
37
- before?: Date;
38
- limit?: number;
39
- orderBy?: 'score_asc' | 'score_desc' | 'created_asc' | 'created_desc';
40
- }
41
-
42
- export interface SessionStore {
43
- save(session: AgentSession): Promise<void>;
44
- get(id: string): Promise<AgentSession | null>;
45
- list(filter?: SessionFilter): Promise<AgentSession[]>;
46
- delete(id: string): Promise<void>;
47
- count?(filter?: SessionFilter): Promise<number>;
48
- }
@@ -1,70 +0,0 @@
1
- export interface ToolResult {
2
- success: boolean;
3
- output: string;
4
- error?: string | undefined;
5
- metadata?: Record<string, unknown> | undefined;
6
- }
7
-
8
- export interface BashOptions {
9
- timeout?: number | undefined;
10
- cwd?: string | undefined;
11
- }
12
-
13
- export interface ReadOptions {
14
- lineRange?: [number, number] | undefined;
15
- maxLines?: number | undefined;
16
- }
17
-
18
- export interface GlobOptions {
19
- ignore?: string[] | undefined;
20
- maxResults?: number | undefined;
21
- }
22
-
23
- export interface GrepOptions {
24
- caseInsensitive?: boolean | undefined;
25
- wholeWord?: boolean | undefined;
26
- maxResults?: number | undefined;
27
- include?: string | undefined;
28
- }
29
-
30
- export interface WebFetchOptions {
31
- url: string;
32
- selector?: string | undefined;
33
- maxContentLength?: number | undefined;
34
- headers?: Record<string, string> | undefined;
35
- }
36
-
37
- export type BatchOp =
38
- | { op: "exec"; command: string; cwd?: string; timeoutMs?: number }
39
- | { op: "write_file"; path: string; content: string; encoding?: "utf8" | "base64" }
40
- | { op: "read_file"; path: string; encoding?: "utf8" | "base64" };
41
-
42
- export type BatchResult =
43
- | { success: true; op: "exec"; exitCode: number; stdout: string; stderr: string }
44
- | { success: true; op: "write_file" }
45
- | { success: true; op: "read_file"; content: string }
46
- | { success: false; op: string; error: string };
47
-
48
- export interface ToolProviderCapabilities {
49
- bash: boolean;
50
- fileSystem: boolean;
51
- webFetch: boolean;
52
- webSearch: boolean;
53
- codeExecution: boolean;
54
- sandboxed: boolean;
55
- }
56
-
57
- export interface ToolProvider {
58
- bash(command: string, options?: BashOptions): Promise<ToolResult>;
59
- readFile(path: string, options?: ReadOptions): Promise<ToolResult>;
60
- writeFile(path: string, content: string): Promise<ToolResult>;
61
- editFile(path: string, oldText: string, newText: string): Promise<ToolResult>;
62
- glob(pattern: string, options?: GlobOptions): Promise<ToolResult>;
63
- grep(pattern: string, path?: string, options?: GrepOptions): Promise<ToolResult>;
64
- webFetch?: ((options: WebFetchOptions) => Promise<ToolResult>) | undefined;
65
- webSearch?: ((query: string) => Promise<ToolResult>) | undefined;
66
- batch?: ((ops: BatchOp[]) => Promise<BatchResult[]>) | undefined;
67
- initialize?: (() => Promise<void>) | undefined;
68
- destroy?: (() => Promise<void>) | undefined;
69
- capabilities(): ToolProviderCapabilities;
70
- }