@agi-cli/server 0.1.97 → 0.1.99
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/db-operations.ts +4 -1
- package/src/runtime/runner.ts +3 -43
- package/src/tools/adapter.ts +38 -67
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi-cli/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.99",
|
|
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.99",
|
|
33
|
+
"@agi-cli/database": "0.1.99",
|
|
34
34
|
"drizzle-orm": "^0.44.5",
|
|
35
35
|
"hono": "^4.9.9",
|
|
36
36
|
"zod": "^4.1.8"
|
|
@@ -76,12 +76,15 @@ export async function updateSessionTokensIncremental(
|
|
|
76
76
|
: priorCachedMsg;
|
|
77
77
|
|
|
78
78
|
// Compute deltas for this step; clamp to 0 in case provider reports smaller values
|
|
79
|
+
// Cached tokens reduce the billable input, so we subtract them from the delta
|
|
79
80
|
const deltaInput = Math.max(0, cumPrompt - priorPromptMsg);
|
|
80
81
|
const deltaOutput = Math.max(0, cumCompletion - priorCompletionMsg);
|
|
81
82
|
const deltaCached = Math.max(0, cumCached - priorCachedMsg);
|
|
82
83
|
const deltaReasoning = Math.max(0, cumReasoning - priorReasoningMsg);
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
// Session input should only count non-cached tokens
|
|
86
|
+
// Total cached tokens are tracked separately for reference
|
|
87
|
+
const nextInputSess = priorInputSess + deltaInput - deltaCached;
|
|
85
88
|
const nextOutputSess = priorOutputSess + deltaOutput;
|
|
86
89
|
const nextCachedSess = priorCachedSess + deltaCached;
|
|
87
90
|
const nextReasoningSess = priorReasoningSess + deltaReasoning;
|
package/src/runtime/runner.ts
CHANGED
|
@@ -275,49 +275,9 @@ async function runAssistant(opts: RunOpts) {
|
|
|
275
275
|
|
|
276
276
|
const onFinish = createFinishHandler(opts, db, completeAssistantMessage);
|
|
277
277
|
|
|
278
|
-
//
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
);
|
|
282
|
-
const { optimizeContext } = await import('./context-optimizer.ts');
|
|
283
|
-
|
|
284
|
-
// 1. Optimize context (deduplicate file reads, prune old tool results)
|
|
285
|
-
const contextOptimized = optimizeContext(messagesWithSystemInstructions, {
|
|
286
|
-
deduplicateFiles: true,
|
|
287
|
-
maxToolResults: 30,
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
debugLog(
|
|
291
|
-
`[RUNNER] After optimizeContext: ${contextOptimized.length} messages`,
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
// 2. Truncate history
|
|
295
|
-
const truncatedMessages = truncateHistory(contextOptimized, 20);
|
|
296
|
-
|
|
297
|
-
debugLog(
|
|
298
|
-
`[RUNNER] After truncateHistory: ${truncatedMessages.length} messages`,
|
|
299
|
-
);
|
|
300
|
-
if (truncatedMessages.length > 0 && truncatedMessages[0].role === 'system') {
|
|
301
|
-
debugLog('[RUNNER] ✅ First message is system message');
|
|
302
|
-
} else if (truncatedMessages.length > 0) {
|
|
303
|
-
debugLog(
|
|
304
|
-
`[RUNNER] ⚠️ First message is NOT system (it's ${truncatedMessages[0].role})`,
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// 3. Add cache control
|
|
309
|
-
const { system: cachedSystem, messages: optimizedMessages } = addCacheControl(
|
|
310
|
-
opts.provider,
|
|
311
|
-
system,
|
|
312
|
-
truncatedMessages,
|
|
313
|
-
);
|
|
314
|
-
|
|
315
|
-
debugLog(
|
|
316
|
-
`[RUNNER] Final optimizedMessages: ${optimizedMessages.length} messages`,
|
|
317
|
-
);
|
|
318
|
-
debugLog(
|
|
319
|
-
`[RUNNER] cachedSystem (spoof): ${typeof cachedSystem === 'string' ? cachedSystem.substring(0, 100) : JSON.stringify(cachedSystem).substring(0, 100)}`,
|
|
320
|
-
);
|
|
278
|
+
// Use messages directly without truncation or optimization
|
|
279
|
+
const optimizedMessages = messagesWithSystemInstructions;
|
|
280
|
+
const cachedSystem = system;
|
|
321
281
|
|
|
322
282
|
// Part tracking - will be created on first text-delta
|
|
323
283
|
let currentPartId: string | null = null;
|
package/src/tools/adapter.ts
CHANGED
|
@@ -10,13 +10,6 @@ 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
|
-
|
|
20
13
|
export type { ToolAdapterContext } from '../runtime/tool-context.ts';
|
|
21
14
|
|
|
22
15
|
type ToolExecuteSignature = Tool['execute'] extends (
|
|
@@ -227,41 +220,7 @@ export function adaptTools(
|
|
|
227
220
|
stepIndex: ctx.stepIndex,
|
|
228
221
|
},
|
|
229
222
|
});
|
|
230
|
-
//
|
|
231
|
-
(async () => {
|
|
232
|
-
try {
|
|
233
|
-
const index = await ctx.nextIndex();
|
|
234
|
-
await ctx.db.insert(messageParts).values({
|
|
235
|
-
id: callPartId,
|
|
236
|
-
messageId: ctx.messageId,
|
|
237
|
-
index,
|
|
238
|
-
stepIndex: ctx.stepIndex,
|
|
239
|
-
type: 'tool_call',
|
|
240
|
-
content: JSON.stringify({ name, args, callId }),
|
|
241
|
-
agent: ctx.agent,
|
|
242
|
-
provider: ctx.provider,
|
|
243
|
-
model: ctx.model,
|
|
244
|
-
startedAt: startTs,
|
|
245
|
-
toolName: name,
|
|
246
|
-
toolCallId: callId,
|
|
247
|
-
});
|
|
248
|
-
} catch {}
|
|
249
|
-
})();
|
|
250
|
-
if (typeof base.onInputAvailable === 'function') {
|
|
251
|
-
// biome-ignore lint/suspicious/noExplicitAny: AI SDK types are complex
|
|
252
|
-
await base.onInputAvailable(options as any);
|
|
253
|
-
}
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Publish promptly so UI shows the call header before results
|
|
258
|
-
publish({
|
|
259
|
-
type: 'tool.call',
|
|
260
|
-
sessionId: ctx.sessionId,
|
|
261
|
-
payload: { name, args, callId, stepIndex: ctx.stepIndex },
|
|
262
|
-
});
|
|
263
|
-
// Persist best-effort in the background to avoid delaying output
|
|
264
|
-
(async () => {
|
|
223
|
+
// Persist synchronously to maintain correct ordering
|
|
265
224
|
try {
|
|
266
225
|
const index = await ctx.nextIndex();
|
|
267
226
|
await ctx.db.insert(messageParts).values({
|
|
@@ -279,7 +238,37 @@ export function adaptTools(
|
|
|
279
238
|
toolCallId: callId,
|
|
280
239
|
});
|
|
281
240
|
} catch {}
|
|
282
|
-
|
|
241
|
+
if (typeof base.onInputAvailable === 'function') {
|
|
242
|
+
// biome-ignore lint/suspicious/noExplicitAny: AI SDK types are complex
|
|
243
|
+
await base.onInputAvailable(options as any);
|
|
244
|
+
}
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Publish promptly so UI shows the call header before results
|
|
249
|
+
publish({
|
|
250
|
+
type: 'tool.call',
|
|
251
|
+
sessionId: ctx.sessionId,
|
|
252
|
+
payload: { name, args, callId, stepIndex: ctx.stepIndex },
|
|
253
|
+
});
|
|
254
|
+
// Persist synchronously to maintain correct ordering
|
|
255
|
+
try {
|
|
256
|
+
const index = await ctx.nextIndex();
|
|
257
|
+
await ctx.db.insert(messageParts).values({
|
|
258
|
+
id: callPartId,
|
|
259
|
+
messageId: ctx.messageId,
|
|
260
|
+
index,
|
|
261
|
+
stepIndex: ctx.stepIndex,
|
|
262
|
+
type: 'tool_call',
|
|
263
|
+
content: JSON.stringify({ name, args, callId }),
|
|
264
|
+
agent: ctx.agent,
|
|
265
|
+
provider: ctx.provider,
|
|
266
|
+
model: ctx.model,
|
|
267
|
+
startedAt: startTs,
|
|
268
|
+
toolName: name,
|
|
269
|
+
toolCallId: callId,
|
|
270
|
+
});
|
|
271
|
+
} catch {}
|
|
283
272
|
if (typeof base.onInputAvailable === 'function') {
|
|
284
273
|
// biome-ignore lint/suspicious/noExplicitAny: AI SDK types are complex
|
|
285
274
|
await base.onInputAvailable(options as any);
|
|
@@ -310,23 +299,6 @@ export function adaptTools(
|
|
|
310
299
|
|
|
311
300
|
const executeWithGuards = async (): Promise<ToolExecuteReturn> => {
|
|
312
301
|
try {
|
|
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
|
-
}
|
|
329
|
-
}
|
|
330
302
|
// Handle session-relative paths and cwd tools
|
|
331
303
|
let res: ToolExecuteReturn | { cwd: string } | null | undefined;
|
|
332
304
|
const cwd = getCwd(ctx.sessionId);
|
|
@@ -396,6 +368,10 @@ export function adaptTools(
|
|
|
396
368
|
|
|
397
369
|
if (isToolError(result)) {
|
|
398
370
|
stepState.failed = true;
|
|
371
|
+
stepState.failedToolName = name;
|
|
372
|
+
failureState.active = true;
|
|
373
|
+
failureState.toolName = name;
|
|
374
|
+
|
|
399
375
|
await persistToolErrorResult(result, {
|
|
400
376
|
callId: callIdFromQueue,
|
|
401
377
|
startTs: startTsFromQueue,
|
|
@@ -403,7 +379,7 @@ export function adaptTools(
|
|
|
403
379
|
args: meta?.args,
|
|
404
380
|
});
|
|
405
381
|
processedToolErrors.add(result as object);
|
|
406
|
-
|
|
382
|
+
return result as ToolExecuteReturn;
|
|
407
383
|
}
|
|
408
384
|
|
|
409
385
|
const resultPartId = crypto.randomUUID();
|
|
@@ -547,10 +523,6 @@ export function adaptTools(
|
|
|
547
523
|
}
|
|
548
524
|
return result as ToolExecuteReturn;
|
|
549
525
|
} catch (error) {
|
|
550
|
-
if (isSkippedToolCallError(error)) {
|
|
551
|
-
throw error;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
526
|
stepState.failed = true;
|
|
555
527
|
stepState.failedToolName = name;
|
|
556
528
|
failureState.active = true;
|
|
@@ -589,8 +561,7 @@ export function adaptTools(
|
|
|
589
561
|
processedToolErrors.add(error as object);
|
|
590
562
|
}
|
|
591
563
|
|
|
592
|
-
|
|
593
|
-
throw error;
|
|
564
|
+
return errorResult as ToolExecuteReturn;
|
|
594
565
|
}
|
|
595
566
|
};
|
|
596
567
|
|