@librechat/agents 4.0.2 → 4.0.4
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/dist/cjs/agents/AgentContext.cjs +3 -2
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/decisions/structuredChat.cjs +2 -8
- package/dist/cjs/decisions/structuredChat.cjs.map +1 -1
- package/dist/cjs/decisions/structuredOutput.cjs +18 -0
- package/dist/cjs/decisions/structuredOutput.cjs.map +1 -0
- package/dist/cjs/graphs/Graph.cjs +25 -9
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs +1 -1
- package/dist/cjs/llm/invoke.cjs +34 -12
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +7 -0
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/providerTextBoundary.cjs +355 -0
- package/dist/cjs/llm/providerTextBoundary.cjs.map +1 -0
- package/dist/cjs/llm/providerTextChunk.cjs +14 -0
- package/dist/cjs/llm/providerTextChunk.cjs.map +1 -0
- package/dist/cjs/llm/providerTextControls.cjs +236 -0
- package/dist/cjs/llm/providerTextControls.cjs.map +1 -0
- package/dist/cjs/llm/stream/smoother.cjs +2 -1
- package/dist/cjs/llm/stream/smoother.cjs.map +1 -1
- package/dist/cjs/main.cjs +18 -1
- package/dist/cjs/protection/providerText.cjs +224 -0
- package/dist/cjs/protection/providerText.cjs.map +1 -0
- package/dist/cjs/protection/providerTextInput.cjs +25 -0
- package/dist/cjs/protection/providerTextInput.cjs.map +1 -0
- package/dist/cjs/run.cjs +7 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +42 -14
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +26 -8
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/GitHubCompare.cjs +181 -0
- package/dist/cjs/tools/GitHubCompare.cjs.map +1 -0
- package/dist/cjs/tools/SubagentTool.cjs +11 -3
- package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +6 -5
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs +2 -2
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +66 -16
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs +4 -2
- package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
- package/dist/cjs/tools/subagent/childGraphConfig.cjs +3 -1
- package/dist/cjs/tools/subagent/childGraphConfig.cjs.map +1 -1
- package/dist/cjs/tools/subagent/diagnostics.cjs +48 -5
- package/dist/cjs/tools/subagent/diagnostics.cjs.map +1 -1
- package/dist/cjs/tools/subagent/hostArgs.cjs +214 -0
- package/dist/cjs/tools/subagent/hostArgs.cjs.map +1 -0
- package/dist/cjs/tools/subagent/index.cjs +1 -0
- package/dist/cjs/tools/toolErrorContent.cjs +1 -1
- package/dist/esm/agents/AgentContext.mjs +3 -2
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/decisions/structuredChat.mjs +2 -8
- package/dist/esm/decisions/structuredChat.mjs.map +1 -1
- package/dist/esm/decisions/structuredOutput.mjs +18 -0
- package/dist/esm/decisions/structuredOutput.mjs.map +1 -0
- package/dist/esm/graphs/Graph.mjs +25 -9
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs +1 -1
- package/dist/esm/llm/invoke.mjs +34 -12
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +7 -0
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/providerTextBoundary.mjs +355 -0
- package/dist/esm/llm/providerTextBoundary.mjs.map +1 -0
- package/dist/esm/llm/providerTextChunk.mjs +13 -0
- package/dist/esm/llm/providerTextChunk.mjs.map +1 -0
- package/dist/esm/llm/providerTextControls.mjs +230 -0
- package/dist/esm/llm/providerTextControls.mjs.map +1 -0
- package/dist/esm/llm/stream/smoother.mjs +2 -1
- package/dist/esm/llm/stream/smoother.mjs.map +1 -1
- package/dist/esm/main.mjs +6 -3
- package/dist/esm/protection/providerText.mjs +218 -0
- package/dist/esm/protection/providerText.mjs.map +1 -0
- package/dist/esm/protection/providerTextInput.mjs +24 -0
- package/dist/esm/protection/providerTextInput.mjs.map +1 -0
- package/dist/esm/run.mjs +7 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +42 -14
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +26 -8
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/GitHubCompare.mjs +175 -0
- package/dist/esm/tools/GitHubCompare.mjs.map +1 -0
- package/dist/esm/tools/SubagentTool.mjs +11 -3
- package/dist/esm/tools/SubagentTool.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +6 -5
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs +2 -2
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +66 -16
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs +4 -2
- package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
- package/dist/esm/tools/subagent/childGraphConfig.mjs +3 -1
- package/dist/esm/tools/subagent/childGraphConfig.mjs.map +1 -1
- package/dist/esm/tools/subagent/diagnostics.mjs +46 -6
- package/dist/esm/tools/subagent/diagnostics.mjs.map +1 -1
- package/dist/esm/tools/subagent/hostArgs.mjs +207 -0
- package/dist/esm/tools/subagent/hostArgs.mjs.map +1 -0
- package/dist/esm/tools/subagent/index.mjs +1 -0
- package/dist/esm/tools/toolErrorContent.mjs +1 -1
- package/dist/types/decisions/structuredChat.d.ts +3 -2
- package/dist/types/decisions/structuredOutput.d.ts +4 -0
- package/dist/types/graphs/Graph.d.ts +6 -3
- package/dist/types/index.d.ts +3 -0
- package/dist/types/llm/invoke.d.ts +4 -1
- package/dist/types/llm/providerTextBoundary.d.ts +4 -0
- package/dist/types/llm/providerTextChunk.d.ts +7 -0
- package/dist/types/llm/providerTextControls.d.ts +18 -0
- package/dist/types/protection/providerText.d.ts +77 -0
- package/dist/types/protection/providerTextInput.d.ts +3 -0
- package/dist/types/run.d.ts +1 -0
- package/dist/types/tools/BashExecutor.d.ts +4 -0
- package/dist/types/tools/CodeExecutor.d.ts +4 -0
- package/dist/types/tools/GitHubCompare.d.ts +104 -0
- package/dist/types/tools/ReadFile.d.ts +4 -0
- package/dist/types/tools/SkillTool.d.ts +4 -0
- package/dist/types/tools/SubagentTool.d.ts +2 -0
- package/dist/types/tools/ToolSearch.d.ts +4 -0
- package/dist/types/tools/search/schema.d.ts +4 -0
- package/dist/types/tools/subagent/SubagentExecutionRegistry.d.ts +2 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +10 -2
- package/dist/types/tools/subagent/SubagentReplay.d.ts +3 -1
- package/dist/types/tools/subagent/diagnostics.d.ts +27 -3
- package/dist/types/tools/subagent/hostArgs.d.ts +57 -0
- package/dist/types/tools/subagent/index.d.ts +3 -2
- package/dist/types/types/graph.d.ts +36 -0
- package/dist/types/types/run.d.ts +4 -2
- package/dist/types/types/tools.d.ts +2 -0
- package/package.json +4 -4
- package/src/agents/AgentContext.ts +3 -2
- package/src/decisions/structuredChat.ts +9 -15
- package/src/decisions/structuredOutput.ts +25 -0
- package/src/graphs/Graph.ts +53 -9
- package/src/index.ts +8 -0
- package/src/llm/invoke.ts +48 -7
- package/src/llm/openai/index.ts +8 -0
- package/src/llm/providerTextBoundary.ts +446 -0
- package/src/llm/providerTextChunk.ts +15 -0
- package/src/llm/providerTextControls.ts +173 -0
- package/src/llm/stream/smoother.ts +4 -2
- package/src/protection/providerText.ts +325 -0
- package/src/protection/providerTextInput.ts +21 -0
- package/src/run.ts +9 -0
- package/src/stream.ts +33 -7
- package/src/summarization/node.ts +32 -14
- package/src/tools/GitHubCompare.ts +319 -0
- package/src/tools/SubagentTool.ts +14 -3
- package/src/tools/ToolNode.ts +7 -3
- package/src/tools/subagent/SubagentExecutionRegistry.ts +6 -2
- package/src/tools/subagent/SubagentExecutor.ts +145 -18
- package/src/tools/subagent/SubagentReplay.ts +10 -3
- package/src/tools/subagent/childGraphConfig.ts +12 -1
- package/src/tools/subagent/diagnostics.ts +98 -6
- package/src/tools/subagent/hostArgs.ts +413 -0
- package/src/tools/subagent/index.ts +9 -0
- package/src/types/graph.ts +41 -0
- package/src/types/run.ts +4 -2
- package/src/types/tools.ts +6 -1
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
2
|
+
import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
3
|
+
|
|
4
|
+
export const GitHubCompareToolName = 'github_compare';
|
|
5
|
+
export const GitHubCompareToolDescription =
|
|
6
|
+
'Read-only GitHub comparison of two full commit SHAs in a public repository. Returns the merge-base, relation and commit counts without Git, a worktree, or worker admission. Does not fetch code or execute commands. Private repositories and arbitrary URLs are not supported.';
|
|
7
|
+
export const GitHubCompareToolSchema = {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
intent: { ...INTENT_PROPERTY },
|
|
11
|
+
owner: { type: 'string', description: 'GitHub repository owner.' },
|
|
12
|
+
repo: { type: 'string', description: 'GitHub repository name.' },
|
|
13
|
+
base: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Full lowercase base commit SHA, not a moving branch.',
|
|
16
|
+
},
|
|
17
|
+
head: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
description: 'Full lowercase head commit SHA, not a moving branch.',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: ['owner', 'repo', 'base', 'head'],
|
|
23
|
+
} as const;
|
|
24
|
+
export const GitHubCompareToolDefinition = {
|
|
25
|
+
name: GitHubCompareToolName,
|
|
26
|
+
description: GitHubCompareToolDescription,
|
|
27
|
+
parameters: GitHubCompareToolSchema,
|
|
28
|
+
} as const;
|
|
29
|
+
|
|
30
|
+
export interface GitHubComparisonInput {
|
|
31
|
+
owner: string;
|
|
32
|
+
repo: string;
|
|
33
|
+
base: string;
|
|
34
|
+
head: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface GitHubComparison {
|
|
38
|
+
base: string;
|
|
39
|
+
head: string;
|
|
40
|
+
mergeBase: string;
|
|
41
|
+
status: 'ahead' | 'behind' | 'identical' | 'diverged';
|
|
42
|
+
aheadBy: number;
|
|
43
|
+
behindBy: number;
|
|
44
|
+
totalCommits: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface GitHubCompareOptions {
|
|
48
|
+
/** Caller-owned transport, including proxy and instrumentation policy. */
|
|
49
|
+
fetch: typeof fetch;
|
|
50
|
+
/** Entire request budget, including body reads. Defaults to 10 seconds; maximum 30 seconds. */
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type GitHubComparisonErrorCode =
|
|
55
|
+
| 'INVALID_INPUT'
|
|
56
|
+
| 'INVALID_CONFIGURATION'
|
|
57
|
+
| 'HTTP_ERROR'
|
|
58
|
+
| 'INVALID_RESPONSE'
|
|
59
|
+
| 'RESPONSE_TOO_LARGE'
|
|
60
|
+
| 'TRANSPORT_ERROR';
|
|
61
|
+
|
|
62
|
+
export class GitHubComparisonError extends Error {
|
|
63
|
+
constructor(
|
|
64
|
+
public readonly code: GitHubComparisonErrorCode,
|
|
65
|
+
message: string,
|
|
66
|
+
public readonly status?: number
|
|
67
|
+
) {
|
|
68
|
+
super(message);
|
|
69
|
+
this.name = 'GitHubComparisonError';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface GitHubComparisonResponse {
|
|
74
|
+
base_commit?: { sha?: string };
|
|
75
|
+
merge_base_commit?: { sha?: string };
|
|
76
|
+
status?: GitHubComparison['status'];
|
|
77
|
+
ahead_by?: number;
|
|
78
|
+
behind_by?: number;
|
|
79
|
+
total_commits?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const SHA = /^[a-f0-9]{40}$/;
|
|
83
|
+
const REPO = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,99}$/;
|
|
84
|
+
const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
85
|
+
|
|
86
|
+
function awaitWithSignal<T>(
|
|
87
|
+
operation: () => Promise<T>,
|
|
88
|
+
signal: AbortSignal
|
|
89
|
+
): Promise<T> {
|
|
90
|
+
signal.throwIfAborted();
|
|
91
|
+
return new Promise<T>((resolve, reject) => {
|
|
92
|
+
const onAbort = (): void => {
|
|
93
|
+
signal.removeEventListener('abort', onAbort);
|
|
94
|
+
reject(signal.reason);
|
|
95
|
+
};
|
|
96
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
97
|
+
try {
|
|
98
|
+
operation().then(
|
|
99
|
+
(value) => {
|
|
100
|
+
signal.removeEventListener('abort', onAbort);
|
|
101
|
+
resolve(value);
|
|
102
|
+
},
|
|
103
|
+
(error) => {
|
|
104
|
+
signal.removeEventListener('abort', onAbort);
|
|
105
|
+
reject(error);
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
signal.removeEventListener('abort', onAbort);
|
|
110
|
+
reject(error);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function cancelBody(response: Response): void {
|
|
116
|
+
void response.body?.cancel().catch(() => undefined);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function readResponse(
|
|
120
|
+
response: Response,
|
|
121
|
+
signal: AbortSignal
|
|
122
|
+
): Promise<string> {
|
|
123
|
+
const reader = response.body?.getReader();
|
|
124
|
+
if (reader == null) {
|
|
125
|
+
throw new GitHubComparisonError(
|
|
126
|
+
'INVALID_RESPONSE',
|
|
127
|
+
'GitHub comparison returned an invalid response.'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
const chunks: Uint8Array[] = [];
|
|
131
|
+
let bytes = 0;
|
|
132
|
+
try {
|
|
133
|
+
for (;;) {
|
|
134
|
+
const item = await awaitWithSignal(() => reader.read(), signal);
|
|
135
|
+
if (item.done) {
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
bytes += item.value.byteLength;
|
|
139
|
+
if (bytes > MAX_RESPONSE_BYTES) {
|
|
140
|
+
throw new GitHubComparisonError(
|
|
141
|
+
'RESPONSE_TOO_LARGE',
|
|
142
|
+
'GitHub comparison response exceeded its bound.'
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
chunks.push(item.value);
|
|
146
|
+
}
|
|
147
|
+
return Buffer.concat(chunks, bytes).toString('utf8');
|
|
148
|
+
} finally {
|
|
149
|
+
void reader.cancel().catch(() => undefined);
|
|
150
|
+
reader.releaseLock();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function parseComparison(
|
|
155
|
+
text: string,
|
|
156
|
+
input: GitHubComparisonInput
|
|
157
|
+
): GitHubComparison {
|
|
158
|
+
let data: GitHubComparisonResponse | null;
|
|
159
|
+
try {
|
|
160
|
+
data = JSON.parse(text) as GitHubComparisonResponse | null;
|
|
161
|
+
} catch {
|
|
162
|
+
throw new GitHubComparisonError(
|
|
163
|
+
'INVALID_RESPONSE',
|
|
164
|
+
'GitHub comparison returned an invalid response.'
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
const mergeBase = data?.merge_base_commit?.sha;
|
|
168
|
+
const status = data?.status;
|
|
169
|
+
const aheadBy = data?.ahead_by;
|
|
170
|
+
const behindBy = data?.behind_by;
|
|
171
|
+
const totalCommits = data?.total_commits;
|
|
172
|
+
if (
|
|
173
|
+
data?.base_commit?.sha !== input.base ||
|
|
174
|
+
typeof mergeBase !== 'string' ||
|
|
175
|
+
!SHA.test(mergeBase) ||
|
|
176
|
+
(status !== 'ahead' &&
|
|
177
|
+
status !== 'behind' &&
|
|
178
|
+
status !== 'identical' &&
|
|
179
|
+
status !== 'diverged') ||
|
|
180
|
+
typeof aheadBy !== 'number' ||
|
|
181
|
+
!Number.isSafeInteger(aheadBy) ||
|
|
182
|
+
aheadBy < 0 ||
|
|
183
|
+
typeof behindBy !== 'number' ||
|
|
184
|
+
!Number.isSafeInteger(behindBy) ||
|
|
185
|
+
behindBy < 0 ||
|
|
186
|
+
typeof totalCommits !== 'number' ||
|
|
187
|
+
!Number.isSafeInteger(totalCommits) ||
|
|
188
|
+
totalCommits < 0
|
|
189
|
+
) {
|
|
190
|
+
throw new GitHubComparisonError(
|
|
191
|
+
'INVALID_RESPONSE',
|
|
192
|
+
'GitHub comparison returned an invalid response.'
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
base: input.base,
|
|
197
|
+
head: input.head,
|
|
198
|
+
mergeBase,
|
|
199
|
+
status,
|
|
200
|
+
aheadBy,
|
|
201
|
+
behindBy,
|
|
202
|
+
totalCommits,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export async function compareGitHubCommits(
|
|
207
|
+
input: GitHubComparisonInput,
|
|
208
|
+
options: GitHubCompareOptions,
|
|
209
|
+
signal?: AbortSignal
|
|
210
|
+
): Promise<GitHubComparison> {
|
|
211
|
+
signal?.throwIfAborted();
|
|
212
|
+
if (
|
|
213
|
+
typeof input.owner !== 'string' ||
|
|
214
|
+
!REPO.test(input.owner) ||
|
|
215
|
+
typeof input.repo !== 'string' ||
|
|
216
|
+
!REPO.test(input.repo) ||
|
|
217
|
+
typeof input.base !== 'string' ||
|
|
218
|
+
!SHA.test(input.base) ||
|
|
219
|
+
typeof input.head !== 'string' ||
|
|
220
|
+
!SHA.test(input.head)
|
|
221
|
+
) {
|
|
222
|
+
throw new GitHubComparisonError(
|
|
223
|
+
'INVALID_INPUT',
|
|
224
|
+
'Supply a repository and full lowercase commit SHAs.'
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const timeoutMs = options.timeoutMs ?? 10000;
|
|
228
|
+
if (
|
|
229
|
+
typeof options.fetch !== 'function' ||
|
|
230
|
+
!Number.isSafeInteger(timeoutMs) ||
|
|
231
|
+
timeoutMs < 1 ||
|
|
232
|
+
timeoutMs > 30000
|
|
233
|
+
) {
|
|
234
|
+
throw new GitHubComparisonError(
|
|
235
|
+
'INVALID_CONFIGURATION',
|
|
236
|
+
'Supply a GitHub transport and a timeout between 1 and 30000 ms.'
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
const timeout = new AbortController();
|
|
240
|
+
const timer = setTimeout(
|
|
241
|
+
() =>
|
|
242
|
+
timeout.abort(
|
|
243
|
+
new DOMException('GitHub comparison timed out.', 'TimeoutError')
|
|
244
|
+
),
|
|
245
|
+
timeoutMs
|
|
246
|
+
);
|
|
247
|
+
timer.unref();
|
|
248
|
+
let pendingResponse: Response | undefined;
|
|
249
|
+
const requestSignal =
|
|
250
|
+
signal == null ? timeout.signal : AbortSignal.any([signal, timeout.signal]);
|
|
251
|
+
try {
|
|
252
|
+
const response = await awaitWithSignal(
|
|
253
|
+
() =>
|
|
254
|
+
options
|
|
255
|
+
.fetch(
|
|
256
|
+
`https://api.github.com/repos/${encodeURIComponent(input.owner)}/${encodeURIComponent(input.repo)}/compare/${input.base}...${input.head}?per_page=1&page=2`,
|
|
257
|
+
{
|
|
258
|
+
method: 'GET',
|
|
259
|
+
redirect: 'error',
|
|
260
|
+
credentials: 'omit',
|
|
261
|
+
signal: requestSignal,
|
|
262
|
+
headers: {
|
|
263
|
+
Accept: 'application/vnd.github+json',
|
|
264
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
265
|
+
},
|
|
266
|
+
}
|
|
267
|
+
)
|
|
268
|
+
.then((response) => {
|
|
269
|
+
pendingResponse = response;
|
|
270
|
+
if (requestSignal.aborted) {
|
|
271
|
+
pendingResponse = undefined;
|
|
272
|
+
cancelBody(response);
|
|
273
|
+
requestSignal.throwIfAborted();
|
|
274
|
+
}
|
|
275
|
+
return response;
|
|
276
|
+
}),
|
|
277
|
+
requestSignal
|
|
278
|
+
);
|
|
279
|
+
if (!response.ok) {
|
|
280
|
+
throw new GitHubComparisonError(
|
|
281
|
+
'HTTP_ERROR',
|
|
282
|
+
`GitHub comparison unavailable (HTTP ${response.status}).`,
|
|
283
|
+
response.status
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
pendingResponse = undefined;
|
|
287
|
+
const text = await readResponse(response, requestSignal);
|
|
288
|
+
requestSignal.throwIfAborted();
|
|
289
|
+
return parseComparison(text, input);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
requestSignal.throwIfAborted();
|
|
292
|
+
if (error instanceof GitHubComparisonError) {
|
|
293
|
+
throw error;
|
|
294
|
+
}
|
|
295
|
+
throw new GitHubComparisonError(
|
|
296
|
+
'TRANSPORT_ERROR',
|
|
297
|
+
'GitHub comparison transport failed.'
|
|
298
|
+
);
|
|
299
|
+
} finally {
|
|
300
|
+
if (pendingResponse != null) {
|
|
301
|
+
cancelBody(pendingResponse);
|
|
302
|
+
}
|
|
303
|
+
clearTimeout(timer);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export class GitHubCompareTool extends DynamicStructuredTool {
|
|
308
|
+
constructor(options: GitHubCompareOptions) {
|
|
309
|
+
super({
|
|
310
|
+
name: GitHubCompareToolName,
|
|
311
|
+
description: GitHubCompareToolDescription,
|
|
312
|
+
schema: structuredClone(GitHubCompareToolSchema),
|
|
313
|
+
func: async (input: GitHubComparisonInput, _manager, config) =>
|
|
314
|
+
JSON.stringify(
|
|
315
|
+
await compareGitHubCommits(input, options, config?.signal)
|
|
316
|
+
),
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JsonSchemaType, LCTool } from '@/types/tools';
|
|
2
2
|
import type { SubagentConfig } from '@/types';
|
|
3
|
+
import { buildSubagentHostArgProperties } from '@/tools/subagent/hostArgs';
|
|
3
4
|
import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
4
5
|
import { Constants } from '@/common';
|
|
5
6
|
|
|
@@ -33,6 +34,9 @@ const RUN_IN_BACKGROUND_PROP_DESCRIPTION =
|
|
|
33
34
|
const SUBAGENT_THREAD_PROP_DESCRIPTION =
|
|
34
35
|
'Continue a host-owned child thread using a fresh execution lease. The saved thread must belong to this scope and subagent type. Only available with run_in_background.';
|
|
35
36
|
|
|
37
|
+
const HOST_ARGS_DESCRIPTION =
|
|
38
|
+
'\n\nOPTIONAL ARGUMENTS:\n- Some types accept extra arguments, listed in brackets after the type. Each is optional: omit it to let the host choose. Where values are listed, pass one listed for the selected type; where it says any text, pass a short value of your own.';
|
|
39
|
+
|
|
36
40
|
export const SubagentToolSchema = {
|
|
37
41
|
type: 'object',
|
|
38
42
|
properties: {
|
|
@@ -69,8 +73,13 @@ export function buildSubagentToolParams(
|
|
|
69
73
|
description: string;
|
|
70
74
|
} {
|
|
71
75
|
const types = configs.map((c) => c.type);
|
|
76
|
+
const hostArgs = buildSubagentHostArgProperties(configs);
|
|
72
77
|
const typeDescriptions = configs
|
|
73
|
-
.map((c) =>
|
|
78
|
+
.map((c) => {
|
|
79
|
+
const summary = hostArgs.summaries.get(c.type);
|
|
80
|
+
const line = `- "${c.type}" (${c.name}): ${c.description}`;
|
|
81
|
+
return summary == null ? line : `${line} [optional ${summary}]`;
|
|
82
|
+
})
|
|
74
83
|
.join('\n');
|
|
75
84
|
|
|
76
85
|
return {
|
|
@@ -96,8 +105,7 @@ export function buildSubagentToolParams(
|
|
|
96
105
|
},
|
|
97
106
|
}
|
|
98
107
|
: {}),
|
|
99
|
-
...(options.background === true &&
|
|
100
|
-
options.threadContinuation === true
|
|
108
|
+
...(options.background === true && options.threadContinuation === true
|
|
101
109
|
? {
|
|
102
110
|
subagent_thread_id: {
|
|
103
111
|
type: 'string',
|
|
@@ -105,10 +113,13 @@ export function buildSubagentToolParams(
|
|
|
105
113
|
},
|
|
106
114
|
}
|
|
107
115
|
: {}),
|
|
116
|
+
...hostArgs.properties,
|
|
108
117
|
},
|
|
109
118
|
required: ['description', 'subagent_type'],
|
|
110
119
|
},
|
|
111
120
|
description: `${SubagentToolDescription}${
|
|
121
|
+
hostArgs.summaries.size > 0 ? HOST_ARGS_DESCRIPTION : ''
|
|
122
|
+
}${
|
|
112
123
|
options.background === true
|
|
113
124
|
? '\n\nBACKGROUND EXECUTION:\n- Set run_in_background to true when you do not need the result immediately. The call returns a background_task_id; use the host background-task tools to poll, steer, queue, interrupt, or cancel it.'
|
|
114
125
|
: ''
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -130,6 +130,7 @@ import {
|
|
|
130
130
|
} from '@/tools/local';
|
|
131
131
|
import { stripCodeSessionFileSummary } from '@/tools/CodeSessionFileSummary';
|
|
132
132
|
import { Constants, GraphEvents, CODE_EXECUTION_TOOLS } from '@/common';
|
|
133
|
+
import { ProviderTextProtectionError } from '@/protection/providerText';
|
|
133
134
|
import { formatToolErrorContent } from '@/tools/toolErrorContent';
|
|
134
135
|
import { PreparedSubagentError } from '@/tools/preparedSubagents';
|
|
135
136
|
import { attachRunStepResumeState } from '@/tools/runStepResume';
|
|
@@ -2146,7 +2147,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
2146
2147
|
*/
|
|
2147
2148
|
if (
|
|
2148
2149
|
e instanceof StreamLimitExceededError ||
|
|
2149
|
-
e instanceof PreparedSubagentError
|
|
2150
|
+
e instanceof PreparedSubagentError ||
|
|
2151
|
+
e instanceof ProviderTextProtectionError
|
|
2150
2152
|
) {
|
|
2151
2153
|
throw e;
|
|
2152
2154
|
}
|
|
@@ -3486,7 +3488,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
3486
3488
|
if (
|
|
3487
3489
|
signal?.aborted === true &&
|
|
3488
3490
|
(signal.reason instanceof StreamLimitExceededError ||
|
|
3489
|
-
signal.reason instanceof PreparedSubagentError
|
|
3491
|
+
signal.reason instanceof PreparedSubagentError ||
|
|
3492
|
+
signal.reason instanceof ProviderTextProtectionError)
|
|
3490
3493
|
) {
|
|
3491
3494
|
throw signal.reason;
|
|
3492
3495
|
}
|
|
@@ -5467,7 +5470,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
5467
5470
|
if (
|
|
5468
5471
|
composedSignal?.aborted === true &&
|
|
5469
5472
|
(composedSignal.reason instanceof StreamLimitExceededError ||
|
|
5470
|
-
composedSignal.reason instanceof PreparedSubagentError
|
|
5473
|
+
composedSignal.reason instanceof PreparedSubagentError ||
|
|
5474
|
+
composedSignal.reason instanceof ProviderTextProtectionError)
|
|
5471
5475
|
) {
|
|
5472
5476
|
throw composedSignal.reason;
|
|
5473
5477
|
}
|
|
@@ -63,6 +63,8 @@ export type SubagentInvocationBinding = Readonly<{
|
|
|
63
63
|
description: string;
|
|
64
64
|
subagentType: string;
|
|
65
65
|
configId?: string;
|
|
66
|
+
/** Value-free identity of the call's validated host arguments. */
|
|
67
|
+
hostArgsDigest?: string;
|
|
66
68
|
}>;
|
|
67
69
|
|
|
68
70
|
export type SubagentSettlementBinding = Readonly<{
|
|
@@ -340,7 +342,8 @@ function assertCompatibleResumeExecution(
|
|
|
340
342
|
current.parentToolCallId === next.parentToolCallId &&
|
|
341
343
|
current.childRunId === next.childRunId &&
|
|
342
344
|
current.subagentType === next.subagentType &&
|
|
343
|
-
current.configId === next.configId
|
|
345
|
+
current.configId === next.configId &&
|
|
346
|
+
current.hostArgsDigest === next.hostArgsDigest
|
|
344
347
|
) {
|
|
345
348
|
return;
|
|
346
349
|
}
|
|
@@ -354,7 +357,8 @@ function assertSameInvocation(
|
|
|
354
357
|
if (
|
|
355
358
|
current.description === next.description &&
|
|
356
359
|
current.subagentType === next.subagentType &&
|
|
357
|
-
current.configId === next.configId
|
|
360
|
+
current.configId === next.configId &&
|
|
361
|
+
current.hostArgsDigest === next.hostArgsDigest
|
|
358
362
|
) {
|
|
359
363
|
return;
|
|
360
364
|
}
|