goatchain 0.0.24 → 0.0.26
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 +247 -72
- package/dist/agent/agent.d.ts +4 -4
- package/dist/agent/hooks/index.d.ts +1 -1
- package/dist/agent/hooks/manager.d.ts +10 -3
- package/dist/agent/hooks/types.d.ts +95 -8
- package/dist/agent/index.d.ts +3 -2
- package/dist/agent/middleware.d.ts +31 -2
- package/dist/agent/tokenCounter.d.ts +48 -2
- package/dist/agent/types.d.ts +15 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.js +618 -467
- package/dist/lib/access-control/index.d.ts +1 -1
- package/dist/lib/access-control/policies.d.ts +10 -0
- package/dist/lib/session-blob.d.ts +50 -0
- package/dist/mcp-client/manager.d.ts +2 -0
- package/dist/middleware/attachmentMiddleware.d.ts +34 -0
- package/dist/middleware/commitModeMiddleware.d.ts +1 -1
- package/dist/middleware/contextCompressionMiddleware.d.ts +28 -2
- package/dist/middleware/envInfoMiddleware.d.ts +6 -0
- package/dist/middleware/gitUtils.d.ts +4 -0
- package/dist/middleware/longRunningMiddleware.d.ts +100 -0
- package/dist/middleware/parallelSubagentMiddleware.d.ts +2 -2
- package/dist/middleware/planModeMiddleware.d.ts +3 -3
- package/dist/middleware/reviewMiddleware.d.ts +1 -1
- package/dist/middleware/skillsMiddleware.d.ts +8 -0
- package/dist/model/anthropic/createAnthropicAdapter.d.ts +1 -1
- package/dist/model/codex/createCodexAdapter.d.ts +1 -1
- package/dist/model/index.d.ts +2 -0
- package/dist/model/openai/createOpenAIResponsesAdapter.d.ts +28 -0
- package/dist/session/completion/composite.d.ts +25 -0
- package/dist/session/completion/index.d.ts +8 -0
- package/dist/session/completion/strategies/reflection-decision-tool.d.ts +51 -0
- package/dist/session/completion/strategies/rule-based.d.ts +16 -0
- package/dist/session/completion/strategies/self-reflection.d.ts +54 -0
- package/dist/session/completion/strategies/todo-based.d.ts +17 -0
- package/dist/session/completion/types.d.ts +53 -0
- package/dist/session/executors/ToolExecutor.d.ts +4 -4
- package/dist/session/session.d.ts +9 -0
- package/dist/state/types.d.ts +3 -2
- package/dist/subagent/index.d.ts +1 -0
- package/dist/subagent/self-reflection-critic.d.ts +35 -0
- package/dist/tool/builtin/bash.d.ts +24 -0
- package/dist/tool/builtin/edit.d.ts +12 -0
- package/dist/tool/builtin/index.d.ts +2 -2
- package/dist/tool/builtin/pathProtection.d.ts +25 -0
- package/dist/tool/builtin/read.d.ts +69 -112
- package/dist/tool/builtin/task.d.ts +8 -0
- package/dist/tool/builtin/webFetch.d.ts +27 -4
- package/dist/tool/builtin/write.d.ts +15 -0
- package/dist/tool/index.d.ts +2 -2
- package/dist/types/common.d.ts +35 -0
- package/dist/types/event.d.ts +55 -3
- package/dist/types/snapshot.d.ts +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AgentLoopState } from '../../agent/types';
|
|
2
|
+
import type { MessageContent } from '../../types';
|
|
3
|
+
import type { TodoItem } from '../../tool/builtin/todoWrite';
|
|
4
|
+
/**
|
|
5
|
+
* Result of a completion assessment.
|
|
6
|
+
*
|
|
7
|
+
* Returned by a `CompletionAssessor` to indicate whether the current task
|
|
8
|
+
* is complete or if the loop should continue with a follow-up message.
|
|
9
|
+
*/
|
|
10
|
+
export interface CompletionAssessment {
|
|
11
|
+
/** Whether the task is considered complete */
|
|
12
|
+
isComplete: boolean;
|
|
13
|
+
/** Human-readable reason for the assessment */
|
|
14
|
+
reason?: string;
|
|
15
|
+
/** Message to inject as a user message if !isComplete */
|
|
16
|
+
followUpMessage?: string;
|
|
17
|
+
/** Confidence score (0-1) for the assessment */
|
|
18
|
+
confidence?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Context provided to completion assessors.
|
|
22
|
+
*
|
|
23
|
+
* Contains everything an assessor needs to judge whether the task is complete.
|
|
24
|
+
*/
|
|
25
|
+
export interface CompletionContext {
|
|
26
|
+
/** Current agent loop state (messages, response, iteration, etc.) */
|
|
27
|
+
state: AgentLoopState;
|
|
28
|
+
/** The original user input that started this session run */
|
|
29
|
+
originalInput: MessageContent;
|
|
30
|
+
/** Current todo items from TodoWriteTool (if available) */
|
|
31
|
+
todoItems?: TodoItem[];
|
|
32
|
+
/** Which follow-up round we are on (0 = first assessment) */
|
|
33
|
+
followUpRound: number;
|
|
34
|
+
/** Maximum follow-up rounds allowed */
|
|
35
|
+
maxFollowUpRounds: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Interface for completion assessment strategies.
|
|
39
|
+
*
|
|
40
|
+
* Implementations determine whether the agent's task is truly complete
|
|
41
|
+
* or if the loop should continue with additional instructions.
|
|
42
|
+
*/
|
|
43
|
+
export interface CompletionAssessor {
|
|
44
|
+
/** Name of this assessor (for logging and events) */
|
|
45
|
+
readonly name: string;
|
|
46
|
+
/**
|
|
47
|
+
* Assess whether the task is complete.
|
|
48
|
+
*
|
|
49
|
+
* @param context - Assessment context with state, todos, etc.
|
|
50
|
+
* @returns Assessment result indicating completion status
|
|
51
|
+
*/
|
|
52
|
+
assess(context: CompletionContext): Promise<CompletionAssessment>;
|
|
53
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AgentHooks } from '../../agent/hooks';
|
|
2
2
|
import type { AgentLoopState, ToolCallWithResult } from '../../agent/types';
|
|
3
3
|
import type { ToolExecutionContext, ToolExecutionContextInput, ToolRegistry } from '../../tool';
|
|
4
4
|
import type { AgentEvent, AgentLoopCheckpoint, CheckpointModelConfig, CheckpointRequestParams, ToolCall } from '../../types';
|
|
@@ -29,14 +29,14 @@ export declare class ToolExecutor {
|
|
|
29
29
|
constructor(options: ToolExecutorOptions);
|
|
30
30
|
private _log;
|
|
31
31
|
createToolExecutionContext(state: AgentLoopState, signal?: AbortSignal, toolCallId?: string, toolName?: string): ToolExecutionContext;
|
|
32
|
-
executeToolCall(tc: ToolCallWithResult, ctx: ToolExecutionContext, signal?: AbortSignal, hooks?:
|
|
32
|
+
executeToolCall(tc: ToolCallWithResult, ctx: ToolExecutionContext, signal?: AbortSignal, hooks?: AgentHooks, permissionRequestResult?: {
|
|
33
33
|
allow: boolean;
|
|
34
34
|
modifiedToolCall?: ToolCall;
|
|
35
|
-
}): Promise<AgentEvent>;
|
|
35
|
+
}, skipPreToolUseHook?: boolean): Promise<AgentEvent>;
|
|
36
36
|
handleToolCalls(state: AgentLoopState, toolContext: ToolExecutionContext, options?: {
|
|
37
37
|
signal?: AbortSignal;
|
|
38
38
|
toolContextInput?: ToolExecutionContextInput;
|
|
39
|
-
hooks?:
|
|
39
|
+
hooks?: AgentHooks;
|
|
40
40
|
checkpointModelConfig?: CheckpointModelConfig;
|
|
41
41
|
requestParams?: CheckpointRequestParams;
|
|
42
42
|
}): AsyncIterable<AgentEvent>;
|
|
@@ -63,6 +63,7 @@ export declare class Session extends EventEmitter {
|
|
|
63
63
|
private readonly _requestParams?;
|
|
64
64
|
private readonly _emitSessionCreatedEvent;
|
|
65
65
|
private _sessionCreatedEventEmitted;
|
|
66
|
+
private _sessionStartHookEmitted;
|
|
66
67
|
private _abortController;
|
|
67
68
|
private readonly _enableLogging;
|
|
68
69
|
private _checkpointOriginalMessages?;
|
|
@@ -163,8 +164,16 @@ export declare class Session extends EventEmitter {
|
|
|
163
164
|
* Check if there's an assistant message containing the tool call
|
|
164
165
|
*/
|
|
165
166
|
private hasAssistantToolCallMessage;
|
|
167
|
+
/**
|
|
168
|
+
* Get current todo items from the TodoWriteTool (if registered).
|
|
169
|
+
* Used to populate state.metadata._todoItems for middleware access.
|
|
170
|
+
* @internal
|
|
171
|
+
*/
|
|
172
|
+
private _getTodoItems;
|
|
166
173
|
private handleFinalResponse;
|
|
167
174
|
private _finalizeRun;
|
|
175
|
+
private _executeStopHook;
|
|
176
|
+
private getStopReasonForModelResponse;
|
|
168
177
|
/**
|
|
169
178
|
* Get preview of the last message (truncated for display)
|
|
170
179
|
*
|
package/dist/state/types.d.ts
CHANGED
|
@@ -81,9 +81,10 @@ export interface CompressionState {
|
|
|
81
81
|
*/
|
|
82
82
|
compressedRange?: {
|
|
83
83
|
/**
|
|
84
|
-
* Index
|
|
84
|
+
* Index where summarization starts (first non-system message).
|
|
85
|
+
* Messages before this index (system messages) are always kept.
|
|
85
86
|
*/
|
|
86
|
-
|
|
87
|
+
summarizeStart: number;
|
|
87
88
|
/**
|
|
88
89
|
* Index where protected turns start (messages from this onward are kept).
|
|
89
90
|
*/
|
package/dist/subagent/index.d.ts
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { SubagentDefinition } from '../tool/builtin/task';
|
|
2
|
+
/**
|
|
3
|
+
* System prompt for the Self-Reflection Critic subagent.
|
|
4
|
+
*
|
|
5
|
+
* This prompt defines the critic's role as the user's proxy / critical
|
|
6
|
+
* reviewer. It instructs the model to:
|
|
7
|
+
* 1. Act on behalf of the user
|
|
8
|
+
* 2. Search the codebase to verify the agent's claims
|
|
9
|
+
* 3. Identify potential issues, edge cases, and missing requirements
|
|
10
|
+
* 4. Generate follow-up questions the user would ask
|
|
11
|
+
* 5. Call the ReflectionDecision tool with its final verdict
|
|
12
|
+
* 6. Be progressively more lenient in later rounds to prevent infinite loops
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildCriticSystemPrompt(cwd: string, now?: Date): string;
|
|
15
|
+
export declare const criticSystemPrompt: string;
|
|
16
|
+
/**
|
|
17
|
+
* Self-Reflection Critic Subagent Definition
|
|
18
|
+
*
|
|
19
|
+
* A read-only reviewer agent that acts as the user's proxy.
|
|
20
|
+
* It verifies the main agent's work by searching the codebase,
|
|
21
|
+
* checking for issues, and generating follow-up questions the
|
|
22
|
+
* user would ask.
|
|
23
|
+
*
|
|
24
|
+
* Uses the ReflectionDecision tool to record a structured verdict.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* Task({
|
|
29
|
+
* subagent_type: 'SelfReflectionCritic',
|
|
30
|
+
* description: 'Review agent work',
|
|
31
|
+
* prompt: '## Original User Request\n...\n## Agent Response\n...'
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const selfReflectionCriticAgent: SubagentDefinition;
|
|
@@ -2,6 +2,7 @@ import type { ChildProcess } from 'node:child_process';
|
|
|
2
2
|
import type { CallToolResult, ToolInputSchema } from '../../types';
|
|
3
3
|
import type { ToolExecutionContext } from '../types';
|
|
4
4
|
import { BaseTool } from '../base';
|
|
5
|
+
import { type ReadOnlyPathEntry } from './pathProtection';
|
|
5
6
|
/**
|
|
6
7
|
* Information about a tracked background process
|
|
7
8
|
*/
|
|
@@ -95,9 +96,12 @@ export declare class BashTool extends BaseTool {
|
|
|
95
96
|
private cwd;
|
|
96
97
|
/** Shell to use for command execution */
|
|
97
98
|
private shell;
|
|
99
|
+
/** Optional read-only path rules */
|
|
100
|
+
private readOnlyPaths?;
|
|
98
101
|
constructor(options?: {
|
|
99
102
|
cwd?: string;
|
|
100
103
|
shell?: string;
|
|
104
|
+
readOnlyPaths?: ReadOnlyPathEntry[];
|
|
101
105
|
});
|
|
102
106
|
/**
|
|
103
107
|
* Set the current working directory
|
|
@@ -107,6 +111,14 @@ export declare class BashTool extends BaseTool {
|
|
|
107
111
|
* Get the current working directory
|
|
108
112
|
*/
|
|
109
113
|
getCwd(): string;
|
|
114
|
+
/**
|
|
115
|
+
* Set read-only paths for write-like shell commands.
|
|
116
|
+
*/
|
|
117
|
+
setReadOnlyPaths(paths: ReadonlyArray<ReadOnlyPathEntry> | undefined): void;
|
|
118
|
+
/**
|
|
119
|
+
* Get configured read-only paths.
|
|
120
|
+
*/
|
|
121
|
+
getReadOnlyPaths(): ReadonlyArray<ReadOnlyPathEntry> | undefined;
|
|
110
122
|
/**
|
|
111
123
|
* Execute a bash command
|
|
112
124
|
*
|
|
@@ -123,6 +135,18 @@ export declare class BashTool extends BaseTool {
|
|
|
123
135
|
* Validate and parse arguments
|
|
124
136
|
*/
|
|
125
137
|
private validateArgs;
|
|
138
|
+
/**
|
|
139
|
+
* Validate read-only path policy for write-like shell commands.
|
|
140
|
+
*
|
|
141
|
+
* This is intentionally heuristic: commands that appear read-only are skipped.
|
|
142
|
+
* For write-like commands, we block when:
|
|
143
|
+
* 1) effective cwd is under a protected path, or
|
|
144
|
+
* 2) command text explicitly references a protected path.
|
|
145
|
+
*/
|
|
146
|
+
private validateReadOnlyPathPolicy;
|
|
147
|
+
private findReferencedReadOnlyRule;
|
|
148
|
+
private buildCommandPathCandidates;
|
|
149
|
+
private commandMentionsPath;
|
|
126
150
|
/**
|
|
127
151
|
* Execute command synchronously with timeout
|
|
128
152
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CallToolResult, ToolInputSchema } from '../../types';
|
|
2
2
|
import type { ToolExecutionContext } from '../types';
|
|
3
3
|
import { BaseTool } from '../base';
|
|
4
|
+
import { type ReadOnlyPathEntry } from './pathProtection';
|
|
4
5
|
/**
|
|
5
6
|
* Result of an edit operation
|
|
6
7
|
*/
|
|
@@ -61,10 +62,13 @@ export declare class EditTool extends BaseTool {
|
|
|
61
62
|
private fileBlacklist?;
|
|
62
63
|
/** Disable file blacklist checks */
|
|
63
64
|
private disableBlacklist;
|
|
65
|
+
/** Optional read-only path rules */
|
|
66
|
+
private readOnlyPaths?;
|
|
64
67
|
constructor(options?: {
|
|
65
68
|
cwd?: string;
|
|
66
69
|
fileBlacklist?: string[];
|
|
67
70
|
disableBlacklist?: boolean;
|
|
71
|
+
readOnlyPaths?: ReadOnlyPathEntry[];
|
|
68
72
|
});
|
|
69
73
|
/**
|
|
70
74
|
* Set the current working directory
|
|
@@ -74,6 +78,14 @@ export declare class EditTool extends BaseTool {
|
|
|
74
78
|
* Get the current working directory
|
|
75
79
|
*/
|
|
76
80
|
getCwd(): string;
|
|
81
|
+
/**
|
|
82
|
+
* Set read-only paths for file operations.
|
|
83
|
+
*/
|
|
84
|
+
setReadOnlyPaths(paths: ReadonlyArray<ReadOnlyPathEntry> | undefined): void;
|
|
85
|
+
/**
|
|
86
|
+
* Get configured read-only paths.
|
|
87
|
+
*/
|
|
88
|
+
getReadOnlyPaths(): ReadonlyArray<ReadOnlyPathEntry> | undefined;
|
|
77
89
|
/**
|
|
78
90
|
* Execute file edit
|
|
79
91
|
*
|
|
@@ -20,8 +20,8 @@ export { TodoPlanTool } from './todoPlan';
|
|
|
20
20
|
export type { TodoPlanArgs, TodoPlanResult } from './todoPlan';
|
|
21
21
|
export { TodoWriteTool } from './todoWrite';
|
|
22
22
|
export type { TodoItem, TodoStatus, TodoWriteArgs, TodoWriteResult } from './todoWrite';
|
|
23
|
-
export { WebFetchTool } from './webFetch';
|
|
24
|
-
export type { FetchFormat, WebFetchArgs, WebFetchResult } from './webFetch';
|
|
23
|
+
export { softWrapLines, WebFetchTool } from './webFetch';
|
|
24
|
+
export type { DeliveryMode, FetchFormat, WebFetchArgs, WebFetchResult } from './webFetch';
|
|
25
25
|
export { WebSearchTool } from './webSearch';
|
|
26
26
|
export type { SearchResultItem, WebSearchArgs, WebSearchResult } from './webSearch';
|
|
27
27
|
export { WriteTool } from './write';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ReadOnlyPathRule {
|
|
2
|
+
path: string;
|
|
3
|
+
reason?: string;
|
|
4
|
+
}
|
|
5
|
+
export type ReadOnlyPathEntry = string | ReadOnlyPathRule;
|
|
6
|
+
export interface ResolvedReadOnlyPathRule {
|
|
7
|
+
path: string;
|
|
8
|
+
reason?: string;
|
|
9
|
+
absolutePath: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ReadOnlyPathCheckOptions {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
readOnlyPaths?: ReadonlyArray<ReadOnlyPathEntry>;
|
|
14
|
+
originalPath?: string;
|
|
15
|
+
action?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ReadOnlyPathCheckResult {
|
|
18
|
+
isBlocked: boolean;
|
|
19
|
+
rule?: ResolvedReadOnlyPathRule;
|
|
20
|
+
message?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function resolveReadOnlyPathRules(readOnlyPaths: ReadonlyArray<ReadOnlyPathEntry> | undefined, cwd?: string): ResolvedReadOnlyPathRule[];
|
|
23
|
+
export declare function findMatchingReadOnlyPath(targetPath: string, rules: ReadonlyArray<ResolvedReadOnlyPathRule>): ResolvedReadOnlyPathRule | undefined;
|
|
24
|
+
export declare function formatReadOnlyPathError(displayPath: string, rule?: Pick<ResolvedReadOnlyPathRule, 'path' | 'absolutePath' | 'reason'>, action?: string): string;
|
|
25
|
+
export declare function checkReadOnlyPath(targetPath: string, options?: ReadOnlyPathCheckOptions): Promise<ReadOnlyPathCheckResult>;
|
|
@@ -2,62 +2,33 @@ import type { CallToolResult, ToolInputSchema } from '../../types';
|
|
|
2
2
|
import type { ConversionMetadata } from '../converters/types';
|
|
3
3
|
import type { ToolExecutionContext } from '../types';
|
|
4
4
|
import { BaseTool } from '../base';
|
|
5
|
-
/**
|
|
6
|
-
* Result of a file read operation
|
|
7
|
-
*/
|
|
5
|
+
/** Result of a file read operation (text path) */
|
|
8
6
|
export interface ReadResult {
|
|
9
|
-
/** File content with line numbers */
|
|
10
7
|
content: string;
|
|
11
|
-
/** Total number of lines in file */
|
|
12
8
|
totalLines: number;
|
|
13
|
-
/** Number of lines returned */
|
|
14
9
|
linesReturned: number;
|
|
15
|
-
/** Starting line number (1-based) */
|
|
16
10
|
startLine: number;
|
|
17
|
-
/** Whether any
|
|
11
|
+
/** Whether any individual line was truncated (per-line length limit) */
|
|
18
12
|
truncated: boolean;
|
|
19
|
-
/** Whether
|
|
20
|
-
|
|
21
|
-
/** Total characters in full content (before truncation) */
|
|
22
|
-
totalChars?: number;
|
|
23
|
-
/** Actual characters returned (after truncation) */
|
|
24
|
-
charsReturned?: number;
|
|
25
|
-
/** File size in bytes */
|
|
13
|
+
/** Whether output was truncated because byte budget was exceeded */
|
|
14
|
+
truncatedByBytes?: boolean;
|
|
26
15
|
fileSize: number;
|
|
27
|
-
/** Whether this is a binary/image file */
|
|
28
16
|
isBinary: boolean;
|
|
29
|
-
/** MIME type if detected */
|
|
30
17
|
mimeType?: string;
|
|
31
|
-
/** Conversion metadata if file was converted from binary format */
|
|
32
18
|
conversionMetadata?: ConversionMetadata;
|
|
33
|
-
/** Whether binary content was suppressed */
|
|
34
|
-
binaryContentSuppressed?: boolean;
|
|
35
|
-
/** Reason binary content was suppressed */
|
|
36
|
-
binaryContentReason?: string;
|
|
37
19
|
}
|
|
38
|
-
/**
|
|
39
|
-
* Arguments for the Read tool
|
|
40
|
-
*/
|
|
20
|
+
/** Arguments accepted by the Read tool */
|
|
41
21
|
export interface ReadArgs {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/** The line number to start reading from (1-based) */
|
|
22
|
+
file_path?: string;
|
|
23
|
+
file_id?: string;
|
|
45
24
|
offset?: number;
|
|
46
|
-
/** The number of lines to read */
|
|
47
25
|
limit?: number;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/** Conversion options for binary files */
|
|
51
|
-
conversion_options?: Record<string, unknown>;
|
|
52
|
-
/** Allow raw binary (base64) output for binary files (default: false) */
|
|
53
|
-
allow_binary_content?: boolean;
|
|
26
|
+
start_line?: number;
|
|
27
|
+
end_line?: number;
|
|
54
28
|
}
|
|
55
29
|
/**
|
|
56
30
|
* Tool for reading files from the filesystem.
|
|
57
31
|
*
|
|
58
|
-
* This tool reads files with line number formatting, supporting
|
|
59
|
-
* offset/limit for large files and detecting binary content.
|
|
60
|
-
*
|
|
61
32
|
* @example
|
|
62
33
|
* ```typescript
|
|
63
34
|
* const readTool = new ReadTool()
|
|
@@ -67,106 +38,92 @@ export interface ReadArgs {
|
|
|
67
38
|
* limit: 50
|
|
68
39
|
* })
|
|
69
40
|
* ```
|
|
70
|
-
*
|
|
71
|
-
* @example Restrict reads to a specific directory
|
|
72
|
-
* ```typescript
|
|
73
|
-
* const readTool = new ReadTool({
|
|
74
|
-
* cwd: '/app/output',
|
|
75
|
-
* restrictToDirectory: true
|
|
76
|
-
* })
|
|
77
|
-
* // All paths will be resolved relative to /app/output
|
|
78
|
-
* // Absolute paths and path traversal (../) will be blocked
|
|
79
|
-
* ```
|
|
80
41
|
*/
|
|
81
42
|
export declare class ReadTool extends BaseTool {
|
|
82
43
|
readonly name = "Read";
|
|
83
|
-
/** Current working directory for resolving relative paths */
|
|
84
44
|
private _cwd;
|
|
85
|
-
/** Allowed directory for file operations (if set, restricts reads to this directory) */
|
|
86
45
|
private _allowedDirectory?;
|
|
87
|
-
/** Optional file blacklist override */
|
|
88
46
|
private _fileBlacklist?;
|
|
89
|
-
/** Disable file blacklist checks */
|
|
90
47
|
private _disableBlacklist;
|
|
91
|
-
/** Binary file processor for converting documents to Markdown */
|
|
92
48
|
private _processor;
|
|
49
|
+
private _converterAllowList;
|
|
50
|
+
private _supportsVision;
|
|
51
|
+
private _supportsPdfs;
|
|
93
52
|
constructor(options?: {
|
|
94
53
|
cwd?: string;
|
|
95
|
-
/** If set, restricts all file reads to this directory. Paths outside will be rejected. */
|
|
96
54
|
allowedDirectory?: string;
|
|
97
|
-
/** Optional file blacklist override (defaults to built-in blacklist). */
|
|
98
55
|
fileBlacklist?: string[];
|
|
99
|
-
/** Disable file blacklist checks entirely. */
|
|
100
56
|
disableBlacklist?: boolean;
|
|
101
|
-
/** Enable/disable binary file conversion (default: true) */
|
|
102
57
|
enableConversion?: boolean;
|
|
103
|
-
/** Custom binary file processor */
|
|
104
58
|
processor?: any;
|
|
59
|
+
/**
|
|
60
|
+
* Extensions allowed through the converter pipeline (e.g. `['.docx', '.pptx']`).
|
|
61
|
+
* Binary files whose extension is NOT in this list will skip conversion and
|
|
62
|
+
* return a binary-info result suggesting to use the Bash tool instead.
|
|
63
|
+
*
|
|
64
|
+
* @default ['.docx', '.pptx', '.pages', '.numbers', '.key']
|
|
65
|
+
*/
|
|
66
|
+
converterAllowList?: string[];
|
|
67
|
+
/**
|
|
68
|
+
* Model capabilities that determine how binary files are handled.
|
|
69
|
+
*
|
|
70
|
+
* - `vision` – whether the model can understand images (default: `false`)
|
|
71
|
+
* - `pdfs` – whether the model can read PDFs natively (default: `false`)
|
|
72
|
+
*
|
|
73
|
+
* When a capability is `false` the Read tool will **not** return native
|
|
74
|
+
* (base64) content for that file type. Instead it returns a short message
|
|
75
|
+
* explaining the file cannot be read by the current model, or attempts
|
|
76
|
+
* automatic conversion to Markdown (for PDFs).
|
|
77
|
+
*/
|
|
78
|
+
modelCapabilities?: {
|
|
79
|
+
vision?: boolean;
|
|
80
|
+
pdfs?: boolean;
|
|
81
|
+
};
|
|
105
82
|
});
|
|
106
|
-
private createDefaultProcessor;
|
|
107
|
-
/**
|
|
108
|
-
* Dynamic description that includes allowed directory info if configured
|
|
109
|
-
*/
|
|
110
83
|
get description(): string;
|
|
111
|
-
/**
|
|
112
|
-
* Dynamic parameters that include allowed directory info if configured
|
|
113
|
-
*/
|
|
114
84
|
get parameters(): ToolInputSchema;
|
|
115
|
-
/**
|
|
116
|
-
* Set the current working directory
|
|
117
|
-
*/
|
|
118
85
|
setCwd(cwd: string): void;
|
|
119
|
-
/**
|
|
120
|
-
* Get the current working directory
|
|
121
|
-
*/
|
|
122
86
|
getCwd(): string;
|
|
123
|
-
/**
|
|
124
|
-
* Set the allowed directory for file operations
|
|
125
|
-
*/
|
|
126
87
|
setAllowedDirectory(dir: string | undefined): void;
|
|
127
|
-
/**
|
|
128
|
-
* Get the allowed directory for file operations
|
|
129
|
-
*/
|
|
130
88
|
getAllowedDirectory(): string | undefined;
|
|
131
|
-
private isWithinDirectory;
|
|
132
89
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* @param args - Read arguments
|
|
136
|
-
* @param _ctx - Tool execution context (required, includes sessionId)
|
|
137
|
-
* @returns MCP-compliant CallToolResult with file content
|
|
90
|
+
* Replace the converter allow-list at runtime.
|
|
91
|
+
* Pass extensions with or without leading dot (e.g. `'.xlsx'` or `'xlsx'`).
|
|
138
92
|
*/
|
|
139
|
-
|
|
93
|
+
setConverterAllowList(extensions: string[]): void;
|
|
94
|
+
/** Return a copy of the current converter allow-list. */
|
|
95
|
+
getConverterAllowList(): string[];
|
|
140
96
|
/**
|
|
141
|
-
*
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
*
|
|
146
|
-
|
|
147
|
-
private handleImageFile;
|
|
148
|
-
/**
|
|
149
|
-
* Handle binary file (non-image)
|
|
150
|
-
*/
|
|
151
|
-
private handleBinaryFile;
|
|
152
|
-
/**
|
|
153
|
-
* Handle binary file with conversion to Markdown
|
|
154
|
-
*/
|
|
155
|
-
private handleBinaryFileWithConversion;
|
|
156
|
-
/**
|
|
157
|
-
* Handle Jupyter notebook file
|
|
158
|
-
*/
|
|
159
|
-
private handleJupyterNotebook;
|
|
160
|
-
/**
|
|
161
|
-
* Handle text file
|
|
162
|
-
*/
|
|
163
|
-
private handleTextFile;
|
|
164
|
-
/**
|
|
165
|
-
* Format output with line numbers and apply offset/limit
|
|
97
|
+
* Update model capabilities at runtime (e.g. when the user switches models).
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* readTool.setModelCapabilities({ vision: false, pdfs: false })
|
|
102
|
+
* ```
|
|
166
103
|
*/
|
|
167
|
-
|
|
104
|
+
setModelCapabilities(caps: {
|
|
105
|
+
vision?: boolean;
|
|
106
|
+
pdfs?: boolean;
|
|
107
|
+
}): void;
|
|
108
|
+
/** Return the current model capability flags. */
|
|
109
|
+
getModelCapabilities(): {
|
|
110
|
+
vision: boolean;
|
|
111
|
+
pdfs: boolean;
|
|
112
|
+
};
|
|
113
|
+
execute(args: Record<string, unknown>, ctx: ToolExecutionContext): Promise<CallToolResult>;
|
|
114
|
+
private _validateArgs;
|
|
115
|
+
private _isWithin;
|
|
116
|
+
private _checkSymlinkEscape;
|
|
117
|
+
/** Read a text file, return byte-budgeted line-numbered output. */
|
|
118
|
+
private _readText;
|
|
119
|
+
/** Read a Jupyter notebook, flatten cells into lines, then format. */
|
|
120
|
+
private _readNotebook;
|
|
168
121
|
/**
|
|
169
|
-
*
|
|
122
|
+
* Handle a binary file that is not an image or PDF.
|
|
123
|
+
* Try to convert via processor; on failure return an info result with
|
|
124
|
+
* file type & size so the model knows what it's dealing with.
|
|
170
125
|
*/
|
|
171
|
-
private
|
|
126
|
+
private _readBinary;
|
|
127
|
+
private _wrapText;
|
|
128
|
+
private _createDefaultProcessor;
|
|
172
129
|
}
|
|
@@ -14,6 +14,14 @@ export interface SubagentDefinition {
|
|
|
14
14
|
accessPolicy: ToolAccessPolicy;
|
|
15
15
|
/** System prompt for this subagent (optional) */
|
|
16
16
|
systemPrompt?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Extra tools to inject into this subagent (not sourced from global registry).
|
|
19
|
+
*
|
|
20
|
+
* Use this for subagent-specific tools that should not be registered
|
|
21
|
+
* globally. The middleware will add these tools to the subagent's registry
|
|
22
|
+
* after filtering global tools by the access policy.
|
|
23
|
+
*/
|
|
24
|
+
extraTools?: import('../base').BaseTool[];
|
|
17
25
|
/** Additional metadata (extensible for future use) */
|
|
18
26
|
[key: string]: unknown;
|
|
19
27
|
}
|
|
@@ -3,6 +3,8 @@ import type { ToolExecutionContext } from '../types';
|
|
|
3
3
|
import { BaseTool } from '../base';
|
|
4
4
|
/** Output format for web fetch */
|
|
5
5
|
export type FetchFormat = 'markdown' | 'html' | 'json' | 'text';
|
|
6
|
+
/** Delivery mode: inline (small content) or blob (large content stored to disk) */
|
|
7
|
+
export type DeliveryMode = 'inline' | 'blob';
|
|
6
8
|
/**
|
|
7
9
|
* Result of a web fetch operation
|
|
8
10
|
*/
|
|
@@ -13,7 +15,7 @@ export interface WebFetchResult {
|
|
|
13
15
|
url: string;
|
|
14
16
|
/** The output format used */
|
|
15
17
|
format: FetchFormat;
|
|
16
|
-
/** The content text */
|
|
18
|
+
/** The content text (full for inline, preview for blob) */
|
|
17
19
|
content: string;
|
|
18
20
|
/** Original content length in characters */
|
|
19
21
|
contentLength: number;
|
|
@@ -27,6 +29,16 @@ export interface WebFetchResult {
|
|
|
27
29
|
truncated: boolean;
|
|
28
30
|
/** Error message if fetch failed */
|
|
29
31
|
error?: string;
|
|
32
|
+
/** Delivery mode: "inline" or "blob" */
|
|
33
|
+
delivery?: DeliveryMode;
|
|
34
|
+
/** Session blob file_id (only when delivery is "blob") */
|
|
35
|
+
file_id?: string;
|
|
36
|
+
/** Total line count in blob (only when delivery is "blob") */
|
|
37
|
+
lineCount?: number;
|
|
38
|
+
/** SHA-256 hash of full content (only when delivery is "blob") */
|
|
39
|
+
sha256?: string;
|
|
40
|
+
/** Instructions for reading the full blob content (only when delivery is "blob") */
|
|
41
|
+
readInstructions?: string;
|
|
30
42
|
}
|
|
31
43
|
/**
|
|
32
44
|
* Arguments for the WebFetch tool
|
|
@@ -45,6 +57,12 @@ export interface WebFetchArgs {
|
|
|
45
57
|
/** Whether to use Jina Reader as fallback if direct fetch fails. Defaults to true (programmatic use only). */
|
|
46
58
|
use_jina_fallback?: boolean;
|
|
47
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Break lines longer than `maxLen` at word boundaries.
|
|
62
|
+
* Preserves content inside fenced code blocks (```) to avoid breaking
|
|
63
|
+
* indentation-sensitive code.
|
|
64
|
+
*/
|
|
65
|
+
export declare function softWrapLines(text: string, maxLen?: number): string;
|
|
48
66
|
/**
|
|
49
67
|
* Tool for fetching and converting web content.
|
|
50
68
|
*
|
|
@@ -64,7 +82,7 @@ export interface WebFetchArgs {
|
|
|
64
82
|
*/
|
|
65
83
|
export declare class WebFetchTool extends BaseTool {
|
|
66
84
|
readonly name = "WebFetch";
|
|
67
|
-
readonly description = "Fetches content from a specified URL and converts it to various formats.\n\nUsage notes:\n- Takes a URL as input\n- Supports multiple output formats: markdown (recommended), html, json, text\n- Markdown format is recommended for LLM processing\n- The URL must be a fully-formed valid URL\n- Supports custom HTTP headers (programmatic use only)\n- Content length can be limited with max_length parameter (default: 5000)\n- Pagination supported with start_index parameter\n- Hard limit: 10MB to prevent OOM\n- Private IP addresses are blocked for security\n- 30 second timeout, maximum 5 redirects\n- Automatically falls back to Jina Reader (r.jina.ai) if direct fetch fails (cannot be disabled)";
|
|
85
|
+
readonly description = "Fetches content from a specified URL and converts it to various formats.\n\nUsage notes:\n- Takes a URL as input\n- Supports multiple output formats: markdown (recommended), html, json, text\n- Markdown format is recommended for LLM processing\n- The URL must be a fully-formed valid URL\n- Supports custom HTTP headers (programmatic use only)\n- Content length can be limited with max_length parameter (default: 5000)\n- Pagination supported with start_index parameter\n- Hard limit: 10MB to prevent OOM\n- Private IP addresses are blocked for security\n- 30 second timeout, maximum 5 redirects\n- Automatically falls back to Jina Reader (r.jina.ai) if direct fetch fails (cannot be disabled)\n- For large pages: content is automatically saved to a session blob and returned with a file_id. Use the Read tool with that file_id and start_line/end_line to access the full content in chunks of ~200 lines.";
|
|
68
86
|
readonly parameters: ToolInputSchema;
|
|
69
87
|
readonly riskLevel = "medium";
|
|
70
88
|
private turndownService;
|
|
@@ -73,10 +91,15 @@ export declare class WebFetchTool extends BaseTool {
|
|
|
73
91
|
* Execute web fetch
|
|
74
92
|
*
|
|
75
93
|
* @param args - WebFetch arguments
|
|
76
|
-
* @param
|
|
94
|
+
* @param ctx - Tool execution context
|
|
77
95
|
* @returns MCP-compliant CallToolResult with fetched content
|
|
78
96
|
*/
|
|
79
|
-
execute(args: Record<string, unknown>,
|
|
97
|
+
execute(args: Record<string, unknown>, ctx: ToolExecutionContext): Promise<CallToolResult>;
|
|
98
|
+
/**
|
|
99
|
+
* Attempt to soft-wrap content and write to a session blob.
|
|
100
|
+
* Returns a CallToolResult with the blob reference on success, or null on failure.
|
|
101
|
+
*/
|
|
102
|
+
private tryWriteBlob;
|
|
80
103
|
/**
|
|
81
104
|
* Validate and parse arguments
|
|
82
105
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CallToolResult, ToolInputSchema } from '../../types';
|
|
2
2
|
import type { ToolExecutionContext } from '../types';
|
|
3
3
|
import { BaseTool } from '../base';
|
|
4
|
+
import { type ReadOnlyPathEntry } from './pathProtection';
|
|
4
5
|
/**
|
|
5
6
|
* Result of a write operation
|
|
6
7
|
*/
|
|
@@ -11,6 +12,8 @@ export interface WriteResult {
|
|
|
11
12
|
filePath: string;
|
|
12
13
|
/** Number of bytes written */
|
|
13
14
|
bytesWritten: number;
|
|
15
|
+
/** Number of lines written */
|
|
16
|
+
linesWritten: number;
|
|
14
17
|
/** Whether an existing file was overwritten */
|
|
15
18
|
overwritten: boolean;
|
|
16
19
|
/** Optional revert payload for undo/redo */
|
|
@@ -68,6 +71,8 @@ export declare class WriteTool extends BaseTool {
|
|
|
68
71
|
private _fileBlacklist?;
|
|
69
72
|
/** Disable file blacklist checks */
|
|
70
73
|
private _disableBlacklist;
|
|
74
|
+
/** Optional read-only path rules */
|
|
75
|
+
private _readOnlyPaths?;
|
|
71
76
|
constructor(options?: {
|
|
72
77
|
cwd?: string;
|
|
73
78
|
/** If set, restricts all file writes to this directory. Paths outside will be rejected. */
|
|
@@ -76,6 +81,8 @@ export declare class WriteTool extends BaseTool {
|
|
|
76
81
|
fileBlacklist?: string[];
|
|
77
82
|
/** Disable file blacklist checks entirely. */
|
|
78
83
|
disableBlacklist?: boolean;
|
|
84
|
+
/** Optional read-only path list. Writes into these paths will be rejected. */
|
|
85
|
+
readOnlyPaths?: ReadOnlyPathEntry[];
|
|
79
86
|
});
|
|
80
87
|
/**
|
|
81
88
|
* Dynamic description that includes allowed directory info if configured
|
|
@@ -101,6 +108,14 @@ export declare class WriteTool extends BaseTool {
|
|
|
101
108
|
* Get the allowed directory for file operations
|
|
102
109
|
*/
|
|
103
110
|
getAllowedDirectory(): string | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Set read-only paths for file operations.
|
|
113
|
+
*/
|
|
114
|
+
setReadOnlyPaths(paths: ReadonlyArray<ReadOnlyPathEntry> | undefined): void;
|
|
115
|
+
/**
|
|
116
|
+
* Get configured read-only paths.
|
|
117
|
+
*/
|
|
118
|
+
getReadOnlyPaths(): ReadonlyArray<ReadOnlyPathEntry> | undefined;
|
|
104
119
|
/**
|
|
105
120
|
* Execute file write
|
|
106
121
|
*
|