codemini-cli 0.5.12 → 0.6.1
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/codemini-web/dist/assets/{highlighted-body-OFNGDK62-B-G99D0A.js → highlighted-body-OFNGDK62-DaefZcrn.js} +1 -1
- package/codemini-web/dist/assets/{index-DIGUEzan.js → index-Bk_gka_s.js} +98 -93
- package/codemini-web/dist/assets/index-BzSHdGYY.css +2 -0
- package/codemini-web/dist/assets/mermaid-GHXKKRXX-BSt5tun0.js +1 -0
- package/codemini-web/dist/index.html +2 -2
- package/codemini-web/dist/logos/chatglm-color.svg +1 -0
- package/codemini-web/dist/logos/claude-color.svg +1 -0
- package/codemini-web/dist/logos/codemini-banner.png +0 -0
- package/codemini-web/dist/logos/codemini_banner.png +0 -0
- package/codemini-web/dist/logos/deepseek-color.svg +1 -0
- package/codemini-web/dist/logos/gemini-color.svg +1 -0
- package/codemini-web/dist/logos/glm-color.svg +1 -0
- package/codemini-web/dist/logos/google-color.svg +1 -0
- package/codemini-web/dist/logos/kimi-color.svg +1 -0
- package/codemini-web/dist/logos/minimax-color.svg +1 -0
- package/codemini-web/dist/logos/moonshot.svg +1 -0
- package/codemini-web/dist/logos/nvidia-color.svg +1 -0
- package/codemini-web/dist/logos/openai.svg +1 -0
- package/codemini-web/dist/logos/qwen-color.svg +1 -0
- package/codemini-web/dist/logos/zhipu-color.svg +1 -0
- package/codemini-web/lib/runtime-bridge.js +203 -63
- package/package.json +1 -1
- package/src/core/agent-loop.js +25 -22
- package/src/core/chat-runtime.js +382 -52
- package/src/core/config-store.js +24 -31
- package/src/core/provider/anthropic.js +12 -9
- package/src/core/provider/openai-compatible.js +80 -50
- package/src/core/session-store.js +63 -24
- package/src/core/tools.js +15 -18
- package/codemini-web/dist/assets/index-Dkq1DdDX.css +0 -2
- package/codemini-web/dist/assets/mermaid-GHXKKRXX-va2Kl89u.js +0 -1
- /package/codemini-web/dist/{codemini_logo.png → logos/codemini_logo.png} +0 -0
package/src/core/chat-runtime.js
CHANGED
|
@@ -83,11 +83,283 @@ function slugify(input) {
|
|
|
83
83
|
return base || 'untitled';
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
function nowStamp() {
|
|
87
|
-
return new Date().toISOString().replace(/[:.]/g, '-');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function
|
|
86
|
+
function nowStamp() {
|
|
87
|
+
return new Date().toISOString().replace(/[:.]/g, '-');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function numberFromPath(obj, pathParts) {
|
|
91
|
+
let current = obj;
|
|
92
|
+
for (const part of pathParts) {
|
|
93
|
+
if (!current || typeof current !== 'object') return null;
|
|
94
|
+
current = current[part];
|
|
95
|
+
}
|
|
96
|
+
const value = Number(current);
|
|
97
|
+
return Number.isFinite(value) ? Math.max(0, value) : null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function firstFiniteNumber(obj, paths) {
|
|
101
|
+
for (const pathParts of paths) {
|
|
102
|
+
const value = numberFromPath(obj, pathParts);
|
|
103
|
+
if (value != null) return value;
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function sumFiniteNumbers(obj, paths) {
|
|
109
|
+
let sum = 0;
|
|
110
|
+
let found = false;
|
|
111
|
+
for (const pathParts of paths) {
|
|
112
|
+
const value = numberFromPath(obj, pathParts);
|
|
113
|
+
if (value != null) {
|
|
114
|
+
sum += value;
|
|
115
|
+
found = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return found ? sum : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function collectRawUsage(usage) {
|
|
122
|
+
if (!usage || typeof usage !== 'object') return [];
|
|
123
|
+
if (Array.isArray(usage.raw)) {
|
|
124
|
+
return usage.raw
|
|
125
|
+
.filter((item) => item && typeof item === 'object')
|
|
126
|
+
.map((item) => ({ ...item }));
|
|
127
|
+
}
|
|
128
|
+
return [{ ...usage }];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function normalizeModelUsage(usage) {
|
|
132
|
+
if (!usage || typeof usage !== 'object') return null;
|
|
133
|
+
const promptCacheHitTokens = firstFiniteNumber(usage, [
|
|
134
|
+
['prompt_cache_hit_tokens'],
|
|
135
|
+
['promptCacheHitTokens'],
|
|
136
|
+
['cache_hit_tokens'],
|
|
137
|
+
['cacheHitTokens']
|
|
138
|
+
]);
|
|
139
|
+
const promptCacheMissTokens = firstFiniteNumber(usage, [
|
|
140
|
+
['prompt_cache_miss_tokens'],
|
|
141
|
+
['promptCacheMissTokens'],
|
|
142
|
+
['cache_miss_tokens'],
|
|
143
|
+
['cacheMissTokens']
|
|
144
|
+
]);
|
|
145
|
+
const explicitInputTokens = firstFiniteNumber(usage, [
|
|
146
|
+
['prompt_tokens'],
|
|
147
|
+
['input_tokens'],
|
|
148
|
+
['inputTokens'],
|
|
149
|
+
['promptTokens'],
|
|
150
|
+
['prompt_token_count'],
|
|
151
|
+
['promptTokenCount'],
|
|
152
|
+
['input_token_count'],
|
|
153
|
+
['inputTokenCount'],
|
|
154
|
+
['input_total_tokens'],
|
|
155
|
+
['total_input_tokens'],
|
|
156
|
+
['usage', 'prompt_tokens'],
|
|
157
|
+
['usage', 'input_tokens'],
|
|
158
|
+
['usage_metadata', 'prompt_token_count'],
|
|
159
|
+
['usage_metadata', 'input_token_count'],
|
|
160
|
+
['usageMetadata', 'promptTokenCount'],
|
|
161
|
+
['usageMetadata', 'inputTokenCount'],
|
|
162
|
+
['token_usage', 'prompt_tokens'],
|
|
163
|
+
['token_usage', 'input_tokens'],
|
|
164
|
+
['tokenUsage', 'promptTokens'],
|
|
165
|
+
['tokenUsage', 'inputTokens'],
|
|
166
|
+
['tokens', 'input_tokens'],
|
|
167
|
+
['tokens', 'inputTokens'],
|
|
168
|
+
['tokens', 'prompt_tokens'],
|
|
169
|
+
['tokens', 'promptTokens'],
|
|
170
|
+
['billed_units', 'input_tokens'],
|
|
171
|
+
['billedUnits', 'inputTokens']
|
|
172
|
+
]);
|
|
173
|
+
const cacheReadInputTokens = firstFiniteNumber(usage, [
|
|
174
|
+
['cache_read_input_tokens'],
|
|
175
|
+
['cacheReadInputTokens'],
|
|
176
|
+
['cache_read_tokens'],
|
|
177
|
+
['cacheReadTokens']
|
|
178
|
+
]);
|
|
179
|
+
const outputTokens = firstFiniteNumber(usage, [
|
|
180
|
+
['completion_tokens'],
|
|
181
|
+
['output_tokens'],
|
|
182
|
+
['outputTokens'],
|
|
183
|
+
['completionTokens'],
|
|
184
|
+
['completion_token_count'],
|
|
185
|
+
['completionTokenCount'],
|
|
186
|
+
['output_token_count'],
|
|
187
|
+
['outputTokenCount'],
|
|
188
|
+
['candidates_token_count'],
|
|
189
|
+
['candidatesTokenCount'],
|
|
190
|
+
['usage', 'completion_tokens'],
|
|
191
|
+
['usage', 'output_tokens'],
|
|
192
|
+
['usage_metadata', 'candidates_token_count'],
|
|
193
|
+
['usage_metadata', 'output_token_count'],
|
|
194
|
+
['usageMetadata', 'candidatesTokenCount'],
|
|
195
|
+
['usageMetadata', 'outputTokenCount'],
|
|
196
|
+
['token_usage', 'completion_tokens'],
|
|
197
|
+
['token_usage', 'output_tokens'],
|
|
198
|
+
['tokenUsage', 'completionTokens'],
|
|
199
|
+
['tokenUsage', 'outputTokens'],
|
|
200
|
+
['tokens', 'output_tokens'],
|
|
201
|
+
['tokens', 'outputTokens'],
|
|
202
|
+
['tokens', 'completion_tokens'],
|
|
203
|
+
['tokens', 'completionTokens'],
|
|
204
|
+
['billed_units', 'output_tokens'],
|
|
205
|
+
['billedUnits', 'outputTokens']
|
|
206
|
+
]);
|
|
207
|
+
const explicitTotal = firstFiniteNumber(usage, [
|
|
208
|
+
['total_tokens'],
|
|
209
|
+
['totalTokens'],
|
|
210
|
+
['total_token_count'],
|
|
211
|
+
['totalTokenCount'],
|
|
212
|
+
['usage', 'total_tokens'],
|
|
213
|
+
['usage_metadata', 'total_token_count'],
|
|
214
|
+
['usageMetadata', 'totalTokenCount'],
|
|
215
|
+
['token_usage', 'total_tokens'],
|
|
216
|
+
['tokenUsage', 'totalTokens'],
|
|
217
|
+
['tokens', 'total_tokens'],
|
|
218
|
+
['tokens', 'totalTokens']
|
|
219
|
+
]);
|
|
220
|
+
const cachedInputTokens = firstFiniteNumber(usage, [
|
|
221
|
+
['prompt_tokens_details', 'cached_tokens'],
|
|
222
|
+
['input_tokens_details', 'cached_tokens'],
|
|
223
|
+
['promptTokensDetails', 'cachedTokens'],
|
|
224
|
+
['inputTokensDetails', 'cachedTokens'],
|
|
225
|
+
['cache_read_input_tokens'],
|
|
226
|
+
['cacheReadInputTokens'],
|
|
227
|
+
['cache_read_tokens'],
|
|
228
|
+
['cacheReadTokens'],
|
|
229
|
+
['cached_tokens'],
|
|
230
|
+
['cachedTokens'],
|
|
231
|
+
['cached_input_tokens'],
|
|
232
|
+
['cachedInputTokens'],
|
|
233
|
+
['cached_content_token_count'],
|
|
234
|
+
['cachedContentTokenCount'],
|
|
235
|
+
['usage', 'prompt_tokens_details', 'cached_tokens'],
|
|
236
|
+
['usage', 'input_tokens_details', 'cached_tokens'],
|
|
237
|
+
['usage_metadata', 'cached_content_token_count'],
|
|
238
|
+
['usageMetadata', 'cachedContentTokenCount'],
|
|
239
|
+
['token_usage', 'prompt_tokens_details', 'cached_tokens'],
|
|
240
|
+
['tokenUsage', 'promptTokensDetails', 'cachedTokens'],
|
|
241
|
+
['tokens', 'cached_tokens'],
|
|
242
|
+
['tokens', 'cachedTokens'],
|
|
243
|
+
['prompt_cache_hit_tokens'],
|
|
244
|
+
['promptCacheHitTokens'],
|
|
245
|
+
['cache_hit_tokens'],
|
|
246
|
+
['cacheHitTokens']
|
|
247
|
+
]);
|
|
248
|
+
const explicitCacheMissInputTokens = firstFiniteNumber(usage, [
|
|
249
|
+
['prompt_cache_miss_tokens'],
|
|
250
|
+
['promptCacheMissTokens'],
|
|
251
|
+
['cache_miss_tokens'],
|
|
252
|
+
['cacheMissTokens']
|
|
253
|
+
]);
|
|
254
|
+
const cacheWriteInputTokens = firstFiniteNumber(usage, [
|
|
255
|
+
['cache_creation_input_tokens'],
|
|
256
|
+
['cacheCreationInputTokens'],
|
|
257
|
+
['cache_write_input_tokens'],
|
|
258
|
+
['cacheWriteInputTokens'],
|
|
259
|
+
['cache_creation_tokens'],
|
|
260
|
+
['cacheCreationTokens'],
|
|
261
|
+
['usage', 'cache_creation_input_tokens'],
|
|
262
|
+
['usage', 'cache_write_input_tokens'],
|
|
263
|
+
['token_usage', 'cache_creation_input_tokens'],
|
|
264
|
+
['tokenUsage', 'cacheCreationInputTokens']
|
|
265
|
+
]) ?? sumFiniteNumbers(usage, [
|
|
266
|
+
['cache_creation', 'ephemeral_5m_input_tokens'],
|
|
267
|
+
['cache_creation', 'ephemeral_1h_input_tokens'],
|
|
268
|
+
['cacheCreation', 'ephemeral5mInputTokens'],
|
|
269
|
+
['cacheCreation', 'ephemeral1hInputTokens'],
|
|
270
|
+
['usage', 'cache_creation', 'ephemeral_5m_input_tokens'],
|
|
271
|
+
['usage', 'cache_creation', 'ephemeral_1h_input_tokens']
|
|
272
|
+
]);
|
|
273
|
+
const hasAnthropicSplitCacheInput = explicitInputTokens != null
|
|
274
|
+
&& (cacheReadInputTokens != null || cacheWriteInputTokens != null)
|
|
275
|
+
&& promptCacheHitTokens == null;
|
|
276
|
+
const cacheMissInputTokens = explicitCacheMissInputTokens ?? (
|
|
277
|
+
hasAnthropicSplitCacheInput
|
|
278
|
+
? Number(explicitInputTokens || 0) + Number(cacheWriteInputTokens || 0)
|
|
279
|
+
: null
|
|
280
|
+
);
|
|
281
|
+
const inputTokens = explicitInputTokens != null
|
|
282
|
+
? Number(explicitInputTokens || 0)
|
|
283
|
+
+ (hasAnthropicSplitCacheInput ? Number(cacheReadInputTokens || 0) + Number(cacheWriteInputTokens || 0) : 0)
|
|
284
|
+
: (
|
|
285
|
+
promptCacheHitTokens != null || promptCacheMissTokens != null
|
|
286
|
+
? Number(promptCacheHitTokens || 0) + Number(promptCacheMissTokens || 0)
|
|
287
|
+
: null
|
|
288
|
+
);
|
|
289
|
+
const reasoningOutputTokens = firstFiniteNumber(usage, [
|
|
290
|
+
['completion_tokens_details', 'reasoning_tokens'],
|
|
291
|
+
['output_tokens_details', 'reasoning_tokens'],
|
|
292
|
+
['completionTokensDetails', 'reasoningTokens'],
|
|
293
|
+
['outputTokensDetails', 'reasoningTokens'],
|
|
294
|
+
['reasoning_tokens'],
|
|
295
|
+
['reasoningTokens'],
|
|
296
|
+
['thoughts_token_count'],
|
|
297
|
+
['thoughtsTokenCount'],
|
|
298
|
+
['usage', 'completion_tokens_details', 'reasoning_tokens'],
|
|
299
|
+
['usage_metadata', 'thoughts_token_count'],
|
|
300
|
+
['usageMetadata', 'thoughtsTokenCount']
|
|
301
|
+
]);
|
|
302
|
+
const totalTokens = explicitTotal ?? (
|
|
303
|
+
inputTokens != null || outputTokens != null
|
|
304
|
+
? Number(inputTokens || 0) + Number(outputTokens || 0)
|
|
305
|
+
: null
|
|
306
|
+
);
|
|
307
|
+
if (
|
|
308
|
+
inputTokens == null &&
|
|
309
|
+
outputTokens == null &&
|
|
310
|
+
totalTokens == null &&
|
|
311
|
+
cachedInputTokens == null &&
|
|
312
|
+
cacheWriteInputTokens == null
|
|
313
|
+
) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
inputTokens: Math.round(inputTokens || 0),
|
|
318
|
+
outputTokens: Math.round(outputTokens || 0),
|
|
319
|
+
totalTokens: Math.round(totalTokens || 0),
|
|
320
|
+
cachedInputTokens: Math.round(cachedInputTokens || 0),
|
|
321
|
+
cacheMissInputTokens: Math.round(cacheMissInputTokens || 0),
|
|
322
|
+
cacheWriteInputTokens: Math.round(cacheWriteInputTokens || 0),
|
|
323
|
+
reasoningOutputTokens: Math.round(reasoningOutputTokens || 0),
|
|
324
|
+
requests: 1,
|
|
325
|
+
raw: collectRawUsage(usage)
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function cloneModelUsage(usage) {
|
|
330
|
+
if (!usage || typeof usage !== 'object') return null;
|
|
331
|
+
return {
|
|
332
|
+
inputTokens: Math.max(0, Math.round(Number(usage.inputTokens || 0))),
|
|
333
|
+
outputTokens: Math.max(0, Math.round(Number(usage.outputTokens || 0))),
|
|
334
|
+
totalTokens: Math.max(0, Math.round(Number(usage.totalTokens || 0))),
|
|
335
|
+
cachedInputTokens: Math.max(0, Math.round(Number(usage.cachedInputTokens || 0))),
|
|
336
|
+
cacheMissInputTokens: Math.max(0, Math.round(Number(usage.cacheMissInputTokens || 0))),
|
|
337
|
+
cacheWriteInputTokens: Math.max(0, Math.round(Number(usage.cacheWriteInputTokens || 0))),
|
|
338
|
+
reasoningOutputTokens: Math.max(0, Math.round(Number(usage.reasoningOutputTokens || 0))),
|
|
339
|
+
requests: Math.max(0, Math.round(Number(usage.requests || 0))),
|
|
340
|
+
raw: Array.isArray(usage.raw) ? usage.raw.map((item) => ({ ...item })) : []
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function mergeModelUsage(left, right) {
|
|
345
|
+
const a = cloneModelUsage(left);
|
|
346
|
+
const b = cloneModelUsage(right);
|
|
347
|
+
if (!a) return b;
|
|
348
|
+
if (!b) return a;
|
|
349
|
+
return {
|
|
350
|
+
inputTokens: a.inputTokens + b.inputTokens,
|
|
351
|
+
outputTokens: a.outputTokens + b.outputTokens,
|
|
352
|
+
totalTokens: a.totalTokens + b.totalTokens,
|
|
353
|
+
cachedInputTokens: a.cachedInputTokens + b.cachedInputTokens,
|
|
354
|
+
cacheMissInputTokens: a.cacheMissInputTokens + b.cacheMissInputTokens,
|
|
355
|
+
cacheWriteInputTokens: a.cacheWriteInputTokens + b.cacheWriteInputTokens,
|
|
356
|
+
reasoningOutputTokens: a.reasoningOutputTokens + b.reasoningOutputTokens,
|
|
357
|
+
requests: a.requests + b.requests,
|
|
358
|
+
raw: [...a.raw, ...b.raw]
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function prioritizeByPreferredOrder(items, preferredOrder) {
|
|
91
363
|
const source = Array.isArray(items) ? items : [];
|
|
92
364
|
const priorities = new Map((Array.isArray(preferredOrder) ? preferredOrder : []).map((value, index) => [value, index]));
|
|
93
365
|
return [...source].sort((left, right) => {
|
|
@@ -2885,30 +3157,64 @@ async function askModel({
|
|
|
2885
3157
|
session.messages.push(stampedMessage('assistant', ''));
|
|
2886
3158
|
activeAssistantIndex = session.messages.length - 1;
|
|
2887
3159
|
if (persistSession) scheduleSessionSave();
|
|
2888
|
-
} else if (event?.type === 'assistant:delta') {
|
|
2889
|
-
if (activeAssistantIndex >= 0 && session.messages[activeAssistantIndex]) {
|
|
2890
|
-
const current = session.messages[activeAssistantIndex];
|
|
2891
|
-
|
|
2892
|
-
current.
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
3160
|
+
} else if (event?.type === 'assistant:delta') {
|
|
3161
|
+
if (activeAssistantIndex >= 0 && session.messages[activeAssistantIndex]) {
|
|
3162
|
+
const current = session.messages[activeAssistantIndex];
|
|
3163
|
+
const now = new Date();
|
|
3164
|
+
if (current.reasoning_started_at && !current.reasoning_ended_at) {
|
|
3165
|
+
current.reasoning_ended_at = now.toISOString();
|
|
3166
|
+
current.reasoning_duration_ms = Math.max(
|
|
3167
|
+
Number(current.reasoning_duration_ms || 0),
|
|
3168
|
+
Date.parse(current.reasoning_ended_at) - Date.parse(current.reasoning_started_at)
|
|
3169
|
+
);
|
|
3170
|
+
}
|
|
3171
|
+
current.content = `${current.content || ''}${event.text || ''}`;
|
|
3172
|
+
current.at = now.toISOString();
|
|
3173
|
+
if (persistSession) scheduleSessionSave();
|
|
3174
|
+
}
|
|
3175
|
+
} else if (event?.type === 'assistant:reasoning_delta') {
|
|
3176
|
+
if (activeAssistantIndex >= 0 && session.messages[activeAssistantIndex]) {
|
|
3177
|
+
const current = session.messages[activeAssistantIndex];
|
|
3178
|
+
const now = new Date();
|
|
3179
|
+
if (!current.reasoning_started_at) current.reasoning_started_at = now.toISOString();
|
|
3180
|
+
current.reasoning_content = `${current.reasoning_content || ''}${event.text || ''}`;
|
|
3181
|
+
current.reasoning_duration_ms = Math.max(
|
|
3182
|
+
0,
|
|
3183
|
+
now.getTime() - Date.parse(current.reasoning_started_at)
|
|
3184
|
+
);
|
|
3185
|
+
current.at = now.toISOString();
|
|
3186
|
+
if (persistSession) scheduleSessionSave();
|
|
3187
|
+
}
|
|
3188
|
+
} else if (event?.type === 'assistant:response') {
|
|
3189
|
+
const eventUsage = normalizeModelUsage(event.usage || event.assistantMessage?.usage);
|
|
3190
|
+
if (eventUsage) event.usage = eventUsage;
|
|
3191
|
+
if (activeAssistantIndex >= 0 && session.messages[activeAssistantIndex]) {
|
|
3192
|
+
const current = session.messages[activeAssistantIndex];
|
|
3193
|
+
const now = new Date();
|
|
3194
|
+
current.content = event.assistantMessage?.content ?? event.text ?? current.content;
|
|
3195
|
+
if (typeof event.assistantMessage?.reasoning_content === 'string' && event.assistantMessage.reasoning_content) {
|
|
3196
|
+
current.reasoning_content = event.assistantMessage.reasoning_content;
|
|
3197
|
+
}
|
|
2902
3198
|
if (Array.isArray(event.assistantMessage?.reasoning_details) && event.assistantMessage.reasoning_details.length > 0) {
|
|
2903
3199
|
current.reasoning_details = event.assistantMessage.reasoning_details;
|
|
2904
3200
|
}
|
|
2905
|
-
if (Array.isArray(event.assistantMessage?.tool_calls) && event.assistantMessage.tool_calls.length > 0) {
|
|
2906
|
-
current.tool_calls = event.assistantMessage.tool_calls;
|
|
2907
|
-
}
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
3201
|
+
if (Array.isArray(event.assistantMessage?.tool_calls) && event.assistantMessage.tool_calls.length > 0) {
|
|
3202
|
+
current.tool_calls = event.assistantMessage.tool_calls;
|
|
3203
|
+
}
|
|
3204
|
+
if (eventUsage) {
|
|
3205
|
+
current.usage = mergeModelUsage(current.usage, eventUsage);
|
|
3206
|
+
}
|
|
3207
|
+
if ((current.reasoning_content || current.reasoning_details) && current.reasoning_started_at) {
|
|
3208
|
+
current.reasoning_ended_at = current.reasoning_ended_at || now.toISOString();
|
|
3209
|
+
current.reasoning_duration_ms = Math.max(
|
|
3210
|
+
Number(current.reasoning_duration_ms || 0),
|
|
3211
|
+
Date.parse(current.reasoning_ended_at) - Date.parse(current.reasoning_started_at)
|
|
3212
|
+
);
|
|
3213
|
+
}
|
|
3214
|
+
current.at = now.toISOString();
|
|
3215
|
+
if (persistSession) scheduleSessionSave();
|
|
3216
|
+
} else {
|
|
3217
|
+
const assistantMessage = event.assistantMessage && typeof event.assistantMessage === 'object'
|
|
2912
3218
|
? event.assistantMessage
|
|
2913
3219
|
: { content: event.text || '' };
|
|
2914
3220
|
session.messages.push(stampedMessage('assistant', assistantMessage.content || event.text || '', {
|
|
@@ -2918,14 +3224,29 @@ async function askModel({
|
|
|
2918
3224
|
...(Array.isArray(assistantMessage.reasoning_details) && assistantMessage.reasoning_details.length > 0
|
|
2919
3225
|
? { reasoning_details: assistantMessage.reasoning_details }
|
|
2920
3226
|
: {}),
|
|
2921
|
-
...(Array.isArray(assistantMessage.tool_calls) && assistantMessage.tool_calls.length > 0
|
|
2922
|
-
? { tool_calls: assistantMessage.tool_calls }
|
|
2923
|
-
: {})
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
3227
|
+
...(Array.isArray(assistantMessage.tool_calls) && assistantMessage.tool_calls.length > 0
|
|
3228
|
+
? { tool_calls: assistantMessage.tool_calls }
|
|
3229
|
+
: {}),
|
|
3230
|
+
...(eventUsage ? { usage: eventUsage } : {})
|
|
3231
|
+
}));
|
|
3232
|
+
if (persistSession) scheduleSessionSave();
|
|
3233
|
+
}
|
|
2927
3234
|
activeAssistantIndex = -1;
|
|
2928
|
-
} else if (event?.type === 'tool:
|
|
3235
|
+
} else if (event?.type === 'tool:start') {
|
|
3236
|
+
if (activeAssistantIndex >= 0 && session.messages[activeAssistantIndex]) {
|
|
3237
|
+
const current = session.messages[activeAssistantIndex];
|
|
3238
|
+
const now = new Date();
|
|
3239
|
+
if (current.reasoning_started_at && !current.reasoning_ended_at) {
|
|
3240
|
+
current.reasoning_ended_at = now.toISOString();
|
|
3241
|
+
current.reasoning_duration_ms = Math.max(
|
|
3242
|
+
Number(current.reasoning_duration_ms || 0),
|
|
3243
|
+
Date.parse(current.reasoning_ended_at) - Date.parse(current.reasoning_started_at)
|
|
3244
|
+
);
|
|
3245
|
+
current.at = now.toISOString();
|
|
3246
|
+
if (persistSession) scheduleSessionSave();
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
} else if (event?.type === 'tool:end' || event?.type === 'tool:error' || event?.type === 'tool:blocked') {
|
|
2929
3250
|
const toolId = String(event.id || '');
|
|
2930
3251
|
if (toolId) {
|
|
2931
3252
|
const meta = {
|
|
@@ -3000,11 +3321,15 @@ async function askModel({
|
|
|
3000
3321
|
timeoutMs: config.gateway.timeout_ms || 1800000,
|
|
3001
3322
|
maxRetries: config.gateway.max_retries ?? 2,
|
|
3002
3323
|
signal,
|
|
3003
|
-
onTextDelta: (delta) => {
|
|
3004
|
-
startAssistantStream();
|
|
3005
|
-
wrappedAgentEvent({ type: 'assistant:delta', text: delta });
|
|
3006
|
-
},
|
|
3007
|
-
|
|
3324
|
+
onTextDelta: (delta) => {
|
|
3325
|
+
startAssistantStream();
|
|
3326
|
+
wrappedAgentEvent({ type: 'assistant:delta', text: delta });
|
|
3327
|
+
},
|
|
3328
|
+
onReasoningDelta: (delta) => {
|
|
3329
|
+
startAssistantStream();
|
|
3330
|
+
wrappedAgentEvent({ type: 'assistant:reasoning_delta', text: delta });
|
|
3331
|
+
},
|
|
3332
|
+
onToolCallDelta: (toolCall) => {
|
|
3008
3333
|
startAssistantStream();
|
|
3009
3334
|
wrappedAgentEvent({ type: 'assistant:tool_call_delta', toolCall });
|
|
3010
3335
|
}
|
|
@@ -3131,7 +3456,7 @@ async function runSubAgentTask({
|
|
|
3131
3456
|
}
|
|
3132
3457
|
if (
|
|
3133
3458
|
role !== 'summarizer' &&
|
|
3134
|
-
['assistant:start', 'assistant:delta', 'assistant:response', 'assistant:tool_call_delta'].includes(String(evt?.type || ''))
|
|
3459
|
+
['assistant:start', 'assistant:delta', 'assistant:reasoning_delta', 'assistant:response', 'assistant:tool_call_delta'].includes(String(evt?.type || ''))
|
|
3135
3460
|
) {
|
|
3136
3461
|
return;
|
|
3137
3462
|
}
|
|
@@ -3171,14 +3496,18 @@ async function runSubAgentTask({
|
|
|
3171
3496
|
};
|
|
3172
3497
|
}
|
|
3173
3498
|
|
|
3174
|
-
function buildPlanStepTranscript({ stepRecord, stepIndex, totalSteps, messages }) {
|
|
3175
|
-
const toolCardsById = new Map();
|
|
3176
|
-
const toolCards = [];
|
|
3177
|
-
const source = Array.isArray(messages) ? messages : [];
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3499
|
+
function buildPlanStepTranscript({ stepRecord, stepIndex, totalSteps, messages }) {
|
|
3500
|
+
const toolCardsById = new Map();
|
|
3501
|
+
const toolCards = [];
|
|
3502
|
+
const source = Array.isArray(messages) ? messages : [];
|
|
3503
|
+
let usage = null;
|
|
3504
|
+
|
|
3505
|
+
for (const msg of source) {
|
|
3506
|
+
if (msg?.role === 'assistant' && msg.usage) {
|
|
3507
|
+
usage = mergeModelUsage(usage, msg.usage);
|
|
3508
|
+
}
|
|
3509
|
+
if (msg?.role === 'assistant' && Array.isArray(msg.tool_calls)) {
|
|
3510
|
+
for (const tc of msg.tool_calls) {
|
|
3182
3511
|
const id = String(tc?.id || `tool-${toolCards.length + 1}`);
|
|
3183
3512
|
if (toolCardsById.has(id)) continue;
|
|
3184
3513
|
const card = {
|
|
@@ -3217,11 +3546,12 @@ function buildPlanStepTranscript({ stepRecord, stepIndex, totalSteps, messages }
|
|
|
3217
3546
|
total: totalSteps,
|
|
3218
3547
|
role: stepRecord.role || 'general',
|
|
3219
3548
|
title: stepRecord.title || '',
|
|
3220
|
-
status: stepRecord.failed ? 'failed' : 'done',
|
|
3221
|
-
summary: stepRecord.failed ? stepRecord.failureReason : trimInline(stepRecord.output || '', 160),
|
|
3222
|
-
segments
|
|
3223
|
-
|
|
3224
|
-
}
|
|
3549
|
+
status: stepRecord.failed ? 'failed' : 'done',
|
|
3550
|
+
summary: stepRecord.failed ? stepRecord.failureReason : trimInline(stepRecord.output || '', 160),
|
|
3551
|
+
segments,
|
|
3552
|
+
...(usage ? { usage } : {})
|
|
3553
|
+
};
|
|
3554
|
+
}
|
|
3225
3555
|
|
|
3226
3556
|
async function executePlanWithSubAgents({
|
|
3227
3557
|
planState,
|
package/src/core/config-store.js
CHANGED
|
@@ -40,22 +40,18 @@ const DEFAULT_CONFIG = {
|
|
|
40
40
|
project_instructions_enabled: true,
|
|
41
41
|
project_instructions_max_chars: 12000
|
|
42
42
|
},
|
|
43
|
-
execution: {
|
|
44
|
-
mode: 'normal',
|
|
45
|
-
always_allow_tools: [
|
|
46
|
-
'read',
|
|
47
|
-
'grep',
|
|
48
|
-
'glob',
|
|
49
|
-
'list',
|
|
50
|
-
'
|
|
51
|
-
'
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
'stop_background_task'
|
|
56
|
-
],
|
|
57
|
-
max_steps: 16
|
|
58
|
-
},
|
|
43
|
+
execution: {
|
|
44
|
+
mode: 'normal',
|
|
45
|
+
always_allow_tools: [
|
|
46
|
+
'read',
|
|
47
|
+
'grep',
|
|
48
|
+
'glob',
|
|
49
|
+
'list',
|
|
50
|
+
'list_background_tasks',
|
|
51
|
+
'get_background_task'
|
|
52
|
+
],
|
|
53
|
+
max_steps: 16
|
|
54
|
+
},
|
|
59
55
|
sessions: {
|
|
60
56
|
max_sessions: 100,
|
|
61
57
|
retention_days: 30
|
|
@@ -158,21 +154,18 @@ function normalizePolicyLists(config) {
|
|
|
158
154
|
const rawTools = Array.isArray(next.execution.always_allow_tools)
|
|
159
155
|
? next.execution.always_allow_tools
|
|
160
156
|
: [];
|
|
161
|
-
next.execution.always_allow_tools = uniqueStrings(
|
|
162
|
-
[
|
|
163
|
-
'read',
|
|
164
|
-
'grep',
|
|
165
|
-
'glob',
|
|
166
|
-
'list',
|
|
167
|
-
'
|
|
168
|
-
'
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
'
|
|
172
|
-
|
|
173
|
-
...rawTools
|
|
174
|
-
].filter((name) => String(name) !== 'list_files')
|
|
175
|
-
);
|
|
157
|
+
next.execution.always_allow_tools = uniqueStrings(
|
|
158
|
+
[
|
|
159
|
+
'read',
|
|
160
|
+
'grep',
|
|
161
|
+
'glob',
|
|
162
|
+
'list',
|
|
163
|
+
'list_background_tasks',
|
|
164
|
+
'get_background_task',
|
|
165
|
+
...rawTools
|
|
166
|
+
].filter((name) => String(name) !== 'list_files')
|
|
167
|
+
.filter((name) => !['edit', 'write', 'delete', 'run', 'stop_background_task'].includes(String(name)))
|
|
168
|
+
);
|
|
176
169
|
next.ui = next.ui || {};
|
|
177
170
|
next.ui.language = normalizeUiLanguage(next.ui.language);
|
|
178
171
|
next.ui.reply_language = normalizeReplyLanguage(next.ui.reply_language);
|
|
@@ -403,9 +403,10 @@ export async function createChatCompletionStream({
|
|
|
403
403
|
model,
|
|
404
404
|
messages,
|
|
405
405
|
temperature = 0.2,
|
|
406
|
-
tools,
|
|
407
|
-
onTextDelta,
|
|
408
|
-
|
|
406
|
+
tools,
|
|
407
|
+
onTextDelta,
|
|
408
|
+
onReasoningDelta,
|
|
409
|
+
onToolCallDelta,
|
|
409
410
|
timeoutMs = 1800000,
|
|
410
411
|
maxTokens = 4096,
|
|
411
412
|
signal: externalSignal
|
|
@@ -476,12 +477,14 @@ export async function createChatCompletionStream({
|
|
|
476
477
|
continue;
|
|
477
478
|
}
|
|
478
479
|
|
|
479
|
-
if (delta.type === 'thinking_delta') {
|
|
480
|
-
const current = thinkingBlocksByIndex.get(index) || { type: 'thinking', thinking: '' };
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
480
|
+
if (delta.type === 'thinking_delta') {
|
|
481
|
+
const current = thinkingBlocksByIndex.get(index) || { type: 'thinking', thinking: '' };
|
|
482
|
+
const thinkingDelta = String(delta.thinking || '');
|
|
483
|
+
current.thinking = `${current.thinking || ''}${thinkingDelta}`;
|
|
484
|
+
thinkingBlocksByIndex.set(index, current);
|
|
485
|
+
if (thinkingDelta && onReasoningDelta) onReasoningDelta(thinkingDelta);
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
485
488
|
|
|
486
489
|
if (delta.type === 'signature_delta') {
|
|
487
490
|
const current = thinkingBlocksByIndex.get(index) || { type: 'thinking', thinking: '' };
|