@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.
- package/README.md +212 -117
- package/dist/arc/index.d.ts +796 -0
- package/dist/arc/index.js +2863 -0
- package/dist/arc/index.js.map +1 -0
- package/dist/observability/otel.d.ts +36 -0
- package/dist/observability/otel.js +73 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/shared-types-DRxnerLT.d.ts +138 -0
- package/dist/skills/index.d.ts +67 -0
- package/dist/skills/index.js +282 -0
- package/dist/skills/index.js.map +1 -0
- package/package.json +26 -2
- package/AGENTS.md +0 -18
- package/docs/guides/observability.md +0 -32
- package/docs/guides/providers.md +0 -51
- package/docs/guides/skills.md +0 -25
- package/docs/security/skill-sandbox-threat-model.md +0 -20
- package/src/agent/create-agent.ts +0 -884
- package/src/agent/create-tools.ts +0 -33
- package/src/agent/step-executor.ts +0 -15
- package/src/agent/types.ts +0 -57
- package/src/context/llm-compaction-strategy.ts +0 -37
- package/src/context/prepare-step.ts +0 -65
- package/src/context/token-tracker.ts +0 -26
- package/src/extracted/manifest.json +0 -10
- package/src/extracted/prompts/compaction.md +0 -5
- package/src/extracted/prompts/system.md +0 -5
- package/src/extracted/tools.json +0 -82
- package/src/hooks/hook-runner.ts +0 -22
- package/src/hooks/tool-wrappers.ts +0 -64
- package/src/interfaces/compaction-strategy.ts +0 -18
- package/src/interfaces/hooks.ts +0 -24
- package/src/interfaces/sandbox-provider.ts +0 -29
- package/src/interfaces/session-store.ts +0 -48
- package/src/interfaces/tool-provider.ts +0 -70
- package/src/loop/bridge.ts +0 -363
- package/src/loop/context-store.ts +0 -207
- package/src/loop/lcm-tool-loop.ts +0 -163
- package/src/loop/vercel-agent-loop.ts +0 -279
- package/src/observability/context.ts +0 -17
- package/src/observability/metrics.ts +0 -27
- package/src/observability/otel.ts +0 -105
- package/src/observability/tracing.ts +0 -13
- package/src/optimization/agent-evaluator.ts +0 -40
- package/src/optimization/config-serializer.ts +0 -16
- package/src/optimization/optimization-runner.ts +0 -39
- package/src/optimization/trace-collector.ts +0 -33
- package/src/permissions/permission-manager.ts +0 -34
- package/src/providers/composite-tool-provider.ts +0 -72
- package/src/providers/control-plane-e2b-executor.ts +0 -218
- package/src/providers/e2b-tool-provider.ts +0 -68
- package/src/providers/local-tool-provider.ts +0 -190
- package/src/providers/skill-sandbox-provider.ts +0 -46
- package/src/sessions/file-session-store.ts +0 -61
- package/src/sessions/in-memory-session-store.ts +0 -39
- package/src/sessions/session-manager.ts +0 -44
- package/src/skills/skill-loader.ts +0 -52
- package/src/skills/skill-manager.ts +0 -175
- package/src/skills/skill-router.ts +0 -99
- package/src/skills/skill-types.ts +0 -26
- package/src/subagents/subagent-manager.ts +0 -22
- package/src/subagents/task-tool.ts +0 -13
- package/tests/integration/agent-loop-basic.spec.ts +0 -56
- package/tests/integration/agent-skill-default-from-sandbox.spec.ts +0 -66
- package/tests/integration/concurrency-single-turn.spec.ts +0 -35
- package/tests/integration/otel-metrics-emission.spec.ts +0 -62
- package/tests/integration/otel-trace-propagation.spec.ts +0 -48
- package/tests/integration/parity-benchmark.spec.ts +0 -45
- package/tests/integration/provider-local-smoke.spec.ts +0 -63
- package/tests/integration/session-resume.spec.ts +0 -30
- package/tests/integration/skill-install-rollback.spec.ts +0 -64
- package/tests/integration/skill-sandbox-file-blob.spec.ts +0 -54
- package/tests/integration/skills-progressive-disclosure.spec.ts +0 -61
- package/tests/integration/streaming-compaction-boundary.spec.ts +0 -43
- package/tests/integration/structured-messages-agent.spec.ts +0 -265
- package/tests/integration/subagent-isolation.spec.ts +0 -24
- package/tests/security/skill-sandbox-isolation.spec.ts +0 -51
- package/tests/unit/create-tools-schema-parity.spec.ts +0 -22
- package/tests/unit/extracted-manifest.spec.ts +0 -41
- package/tests/unit/interfaces-contract.spec.ts +0 -101
- package/tests/unit/structured-messages.spec.ts +0 -176
- package/tests/unit/token-tracker.spec.ts +0 -22
- package/tsconfig.json +0 -14
- 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
|
-
}
|
package/src/agent/types.ts
DELETED
|
@@ -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.
|
package/src/extracted/tools.json
DELETED
|
@@ -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
|
-
}
|
package/src/hooks/hook-runner.ts
DELETED
|
@@ -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
|
-
}
|
package/src/interfaces/hooks.ts
DELETED
|
@@ -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
|
-
}
|