@agi-cli/server 0.1.95 → 0.1.96
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/package.json +3 -3
- package/src/runtime/tool-context.ts +1 -0
- package/src/tools/adapter.ts +52 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi-cli/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.96",
|
|
4
4
|
"description": "HTTP API server for AGI CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"typecheck": "tsc --noEmit"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@agi-cli/sdk": "0.1.
|
|
33
|
-
"@agi-cli/database": "0.1.
|
|
32
|
+
"@agi-cli/sdk": "0.1.96",
|
|
33
|
+
"@agi-cli/database": "0.1.96",
|
|
34
34
|
"drizzle-orm": "^0.44.5",
|
|
35
35
|
"hono": "^4.9.9",
|
|
36
36
|
"zod": "^4.1.8"
|
package/src/tools/adapter.ts
CHANGED
|
@@ -10,6 +10,13 @@ import type {
|
|
|
10
10
|
} from '../runtime/tool-context.ts';
|
|
11
11
|
import { isToolError } from '@agi-cli/sdk/tools/error';
|
|
12
12
|
|
|
13
|
+
function isSkippedToolCallError(error: unknown): boolean {
|
|
14
|
+
if (!isToolError(error)) return false;
|
|
15
|
+
const details = (error as { details?: unknown }).details;
|
|
16
|
+
if (!details || typeof details !== 'object') return false;
|
|
17
|
+
return 'skippedTool' in (details as Record<string, unknown>);
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
export type { ToolAdapterContext } from '../runtime/tool-context.ts';
|
|
14
21
|
|
|
15
22
|
type ToolExecuteSignature = Tool['execute'] extends (
|
|
@@ -50,6 +57,10 @@ export function adaptTools(
|
|
|
50
57
|
) {
|
|
51
58
|
const out: Record<string, Tool> = {};
|
|
52
59
|
const pendingCalls = new Map<string, PendingCallMeta[]>();
|
|
60
|
+
const failureState: { active: boolean; toolName?: string } = {
|
|
61
|
+
active: false,
|
|
62
|
+
toolName: undefined,
|
|
63
|
+
};
|
|
53
64
|
let firstToolCallReported = false;
|
|
54
65
|
|
|
55
66
|
if (!ctx.stepExecution) {
|
|
@@ -289,19 +300,32 @@ export function adaptTools(
|
|
|
289
300
|
: 0;
|
|
290
301
|
let stepState = stepStates.get(stepKey);
|
|
291
302
|
if (!stepState) {
|
|
292
|
-
stepState = {
|
|
303
|
+
stepState = {
|
|
304
|
+
chain: Promise.resolve(),
|
|
305
|
+
failed: false,
|
|
306
|
+
failedToolName: undefined,
|
|
307
|
+
};
|
|
293
308
|
stepStates.set(stepKey, stepState);
|
|
294
309
|
}
|
|
295
310
|
|
|
296
311
|
const executeWithGuards = async (): Promise<ToolExecuteReturn> => {
|
|
297
312
|
try {
|
|
298
|
-
if (
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
313
|
+
if (failureState.active) {
|
|
314
|
+
const expectedTool = failureState.toolName;
|
|
315
|
+
if (!expectedTool || expectedTool !== name) {
|
|
316
|
+
const skipError = {
|
|
317
|
+
ok: false,
|
|
318
|
+
error: expectedTool
|
|
319
|
+
? `Cannot execute "${name}" because "${expectedTool}" failed earlier in this step. Retry "${expectedTool}" before using other tools.`
|
|
320
|
+
: `Cannot execute "${name}" because a previous tool call in this session failed. Retry that tool before continuing with "${name}".`,
|
|
321
|
+
details: {
|
|
322
|
+
skippedTool: name,
|
|
323
|
+
reason: 'previous_tool_failed',
|
|
324
|
+
expectedTool,
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
throw skipError;
|
|
328
|
+
}
|
|
305
329
|
}
|
|
306
330
|
// Handle session-relative paths and cwd tools
|
|
307
331
|
let res: ToolExecuteReturn | { cwd: string } | null | undefined;
|
|
@@ -415,6 +439,12 @@ export function adaptTools(
|
|
|
415
439
|
|
|
416
440
|
// Special-case: keep progress_update result lightweight; publish first, persist best-effort
|
|
417
441
|
if (name === 'progress_update') {
|
|
442
|
+
stepState.failed = false;
|
|
443
|
+
stepState.failedToolName = undefined;
|
|
444
|
+
if (failureState.active && failureState.toolName === name) {
|
|
445
|
+
failureState.active = false;
|
|
446
|
+
failureState.toolName = undefined;
|
|
447
|
+
}
|
|
418
448
|
publish({
|
|
419
449
|
type: 'tool.result',
|
|
420
450
|
sessionId: ctx.sessionId,
|
|
@@ -444,6 +474,13 @@ export function adaptTools(
|
|
|
444
474
|
return result as ToolExecuteReturn;
|
|
445
475
|
}
|
|
446
476
|
|
|
477
|
+
stepState.failed = false;
|
|
478
|
+
stepState.failedToolName = undefined;
|
|
479
|
+
if (failureState.active && failureState.toolName === name) {
|
|
480
|
+
failureState.active = false;
|
|
481
|
+
failureState.toolName = undefined;
|
|
482
|
+
}
|
|
483
|
+
|
|
447
484
|
await ctx.db.insert(messageParts).values({
|
|
448
485
|
id: resultPartId,
|
|
449
486
|
messageId: ctx.messageId,
|
|
@@ -510,7 +547,14 @@ export function adaptTools(
|
|
|
510
547
|
}
|
|
511
548
|
return result as ToolExecuteReturn;
|
|
512
549
|
} catch (error) {
|
|
550
|
+
if (isSkippedToolCallError(error)) {
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
|
|
513
554
|
stepState.failed = true;
|
|
555
|
+
stepState.failedToolName = name;
|
|
556
|
+
failureState.active = true;
|
|
557
|
+
failureState.toolName = name;
|
|
514
558
|
|
|
515
559
|
// Tool execution failed
|
|
516
560
|
if (
|