@agi-cli/server 0.1.101 → 0.1.102

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agi-cli/server",
3
- "version": "0.1.101",
3
+ "version": "0.1.102",
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.101",
33
- "@agi-cli/database": "0.1.101",
32
+ "@agi-cli/sdk": "0.1.102",
33
+ "@agi-cli/database": "0.1.102",
34
34
  "drizzle-orm": "^0.44.5",
35
35
  "hono": "^4.9.9",
36
36
  "zod": "^4.1.8"
@@ -110,57 +110,50 @@ export async function buildHistoryMessages(
110
110
  toolResults.map((result) => [result.callId, result]),
111
111
  );
112
112
 
113
- const hasIncompleteTools = toolCalls.some(
114
- (call) => !toolResultsById.has(call.callId),
115
- );
116
-
117
- if (hasIncompleteTools) {
118
- const pendingCalls = toolCalls
119
- .filter((call) => !toolResultsById.has(call.callId))
120
- .map((call) => `${call.name}#${call.callId}`)
121
- .join(', ');
122
- debugLog(
123
- `[buildHistoryMessages] Incomplete tool calls for assistant message ${m.id}, skipping tool data (pending: ${pendingCalls || 'unknown'})`,
124
- );
125
- if (assistantParts.length) {
126
- ui.push({ id: m.id, role: 'assistant', parts: assistantParts });
127
- }
128
- continue;
129
- }
130
-
131
113
  for (const call of toolCalls) {
132
114
  // Skip finish tool from history - it's internal loop control
133
115
  if (call.name === 'finish') continue;
134
116
 
135
117
  const toolType = `tool-${call.name}` as `tool-${string}`;
136
- const result = toolResultsById.get(call.callId);
137
-
138
- if (result) {
139
- const part = {
140
- type: toolType,
141
- state: 'output-available',
142
- toolCallId: call.callId,
143
- input: call.args,
144
- output: (() => {
145
- const r = result.result;
146
- if (typeof r === 'string') return r;
147
- try {
148
- return JSON.stringify(r);
149
- } catch {
150
- return String(r);
151
- }
152
- })(),
118
+ let result = toolResultsById.get(call.callId);
119
+
120
+ if (!result) {
121
+ // Synthesize a result for incomplete tool calls to preserve history
122
+ debugLog(
123
+ `[buildHistoryMessages] Synthesizing error result for incomplete tool call ${call.name}#${call.callId}`,
124
+ );
125
+ result = {
126
+ name: call.name,
127
+ callId: call.callId,
128
+ result:
129
+ 'Error: The tool execution was interrupted or failed to return a result. You may need to retry this operation.',
153
130
  };
131
+ }
154
132
 
155
- toolHistory.register(part, {
156
- toolName: call.name,
157
- callId: call.callId,
158
- args: call.args,
159
- result: result.result,
160
- });
133
+ const part = {
134
+ type: toolType,
135
+ state: 'output-available',
136
+ toolCallId: call.callId,
137
+ input: call.args,
138
+ output: (() => {
139
+ const r = result.result;
140
+ if (typeof r === 'string') return r;
141
+ try {
142
+ return JSON.stringify(r);
143
+ } catch {
144
+ return String(r);
145
+ }
146
+ })(),
147
+ };
161
148
 
162
- assistantParts.push(part as never);
163
- }
149
+ toolHistory.register(part, {
150
+ toolName: call.name,
151
+ callId: call.callId,
152
+ args: call.args,
153
+ result: result.result,
154
+ });
155
+
156
+ assistantParts.push(part as never);
164
157
  }
165
158
 
166
159
  if (assistantParts.length) {
@@ -8,7 +8,7 @@ import {
8
8
  } from '@agi-cli/sdk';
9
9
  import { openai, createOpenAI } from '@ai-sdk/openai';
10
10
  import { anthropic, createAnthropic } from '@ai-sdk/anthropic';
11
- import { google } from '@ai-sdk/google';
11
+ import { google, createGoogleGenerativeAI } from '@ai-sdk/google';
12
12
  import { createOpenRouter } from '@openrouter/ai-sdk-provider';
13
13
  import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
14
14
 
@@ -110,7 +110,14 @@ export async function resolveModel(
110
110
  const instance = await getAnthropicInstance(cfg);
111
111
  return instance(model);
112
112
  }
113
- if (provider === 'google') return google(model);
113
+ if (provider === 'google') {
114
+ const auth = await getAuth('google', cfg.projectRoot);
115
+ if (auth?.type === 'api' && auth.key) {
116
+ const instance = createGoogleGenerativeAI({ apiKey: auth.key });
117
+ return instance(model);
118
+ }
119
+ return google(model);
120
+ }
114
121
  if (provider === 'openrouter') {
115
122
  const openrouter = getOpenRouterInstance();
116
123
  return openrouter.chat(model);
@@ -178,11 +178,21 @@ async function runAssistant(opts: RunOpts) {
178
178
 
179
179
  // FIX: For OAuth, ALWAYS prepend the system message because it's never in history
180
180
  // For API key mode, only add on first message (when additionalSystemMessages is empty)
181
- const messagesWithSystemInstructions = [
181
+ const messagesWithSystemInstructions: any[] = [
182
182
  ...additionalSystemMessages, // Always add for OAuth, empty for API key mode
183
183
  ...history,
184
184
  ];
185
185
 
186
+ // Inject a reminder for subsequent turns to prevent "abrupt stops"
187
+ // This reinforces the instruction to call finish and maintain context
188
+ if (!isFirstMessage) {
189
+ messagesWithSystemInstructions.push({
190
+ role: 'user',
191
+ content:
192
+ 'SYSTEM REMINDER: You are continuing an existing session. When you have completed the task, you MUST stream a text summary of what you did to the user, and THEN call the `finish` tool. Do not call `finish` without a summary.',
193
+ });
194
+ }
195
+
186
196
  debugLog(`[RUNNER] About to create model with provider: ${opts.provider}`);
187
197
  debugLog(`[RUNNER] About to create model ID: ${opts.model}`);
188
198
  debugLog(
@@ -285,7 +295,6 @@ async function runAssistant(opts: RunOpts) {
285
295
  let stepIndex = 0;
286
296
 
287
297
  try {
288
- // @ts-expect-error this is fine 🔥
289
298
  const result = streamText({
290
299
  model,
291
300
  tools: toolset,