codemini-cli 0.4.2 → 0.4.3
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/README.md +4 -2
- package/deployment.md +5 -5
- package/package.json +1 -2
- package/skills/grill-me/SKILL.md +30 -0
- package/skills/project-requirements/SKILL.md +245 -0
- package/skills/superpowers-lite/SKILL.md +5 -1
- package/src/commands/run.js +5 -4
- package/src/core/agent-loop.js +8 -8
- package/src/core/chat-runtime.js +220 -31
- package/src/core/config-store.js +6 -3
- package/src/core/fff-adapter.js +1 -1
- package/src/core/provider/anthropic.js +2 -2
- package/src/core/provider/openai-compatible.js +2 -2
- package/src/core/shell.js +1 -1
- package/src/core/tools.js +116 -39
- package/src/tui/chat-app.js +52 -22
- package/src/tui/tool-activity/presenters/system.js +6 -0
package/src/core/tools.js
CHANGED
|
@@ -345,30 +345,107 @@ async function webSearchQuery(config, args = {}) {
|
|
|
345
345
|
if (!query) throw new Error('web_search requires query');
|
|
346
346
|
|
|
347
347
|
const maxResults = clampNumber(normalizedArgs.max_results, 1, 20, 8);
|
|
348
|
-
const
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
348
|
+
const locale = String(normalizedArgs.locale || config?.web?.search_locale || 'en-US').trim() || 'en-US';
|
|
349
|
+
const region = String(normalizedArgs.region || normalizedArgs.cc || config?.web?.search_region || (locale.toLowerCase().endsWith('-cn') ? 'CN' : 'US')).trim() || 'US';
|
|
350
|
+
const searchUrl = buildBingRssSearchUrl({
|
|
351
|
+
baseUrl: config?.web?.search_base_url,
|
|
352
|
+
query,
|
|
353
|
+
locale,
|
|
354
|
+
region
|
|
353
355
|
});
|
|
356
|
+
const timeoutMs = clampNumber(normalizedArgs.timeout_ms || config?.web?.search_timeout_ms, 1_000, 60_000, 15_000);
|
|
357
|
+
const controller = new AbortController();
|
|
358
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
359
|
+
let response;
|
|
360
|
+
try {
|
|
361
|
+
response = await fetch(searchUrl, {
|
|
362
|
+
redirect: 'follow',
|
|
363
|
+
signal: controller.signal,
|
|
364
|
+
headers: {
|
|
365
|
+
'user-agent': 'CodeMiniCLI/0.4 web_search',
|
|
366
|
+
accept: 'application/rss+xml, application/xml;q=0.9, text/xml;q=0.8, */*;q=0.5',
|
|
367
|
+
'accept-language': `${locale},en;q=0.8`
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
} finally {
|
|
371
|
+
clearTimeout(timeout);
|
|
372
|
+
}
|
|
373
|
+
if (!response.ok) {
|
|
374
|
+
throw new Error(`web_search Bing RSS request failed: HTTP ${response.status}`);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const xml = await response.text();
|
|
378
|
+
const cheerio = await import('cheerio');
|
|
379
|
+
const parsed = parseBingRssResults(cheerio, xml, maxResults);
|
|
354
380
|
|
|
355
381
|
return {
|
|
356
382
|
query,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
description: normalizeWhitespace(item?.description || item?.rawDescription || ''),
|
|
363
|
-
hostname: String(item?.hostname || '').trim()
|
|
364
|
-
}))
|
|
365
|
-
: [],
|
|
366
|
-
related: Array.isArray(response?.related)
|
|
367
|
-
? response.related.slice(0, 8).map((item) => String(item?.text || item?.raw || '').trim()).filter(Boolean)
|
|
368
|
-
: []
|
|
383
|
+
engine: 'bing_rss',
|
|
384
|
+
source_url: response.url || searchUrl,
|
|
385
|
+
no_results: parsed.results.length === 0,
|
|
386
|
+
results: parsed.results,
|
|
387
|
+
related: []
|
|
369
388
|
};
|
|
370
389
|
}
|
|
371
390
|
|
|
391
|
+
function buildBingRssSearchUrl({ baseUrl, query, locale, region }) {
|
|
392
|
+
const url = new URL(String(baseUrl || 'https://cn.bing.com/search'));
|
|
393
|
+
url.searchParams.set('q', query);
|
|
394
|
+
url.searchParams.set('mkt', locale);
|
|
395
|
+
url.searchParams.set('setlang', locale);
|
|
396
|
+
url.searchParams.set('cc', region);
|
|
397
|
+
url.searchParams.set('format', 'rss');
|
|
398
|
+
return url.toString();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function parseBingRssResults(cheerio, xml, maxResults) {
|
|
402
|
+
const $ = cheerio.load(xml, { xmlMode: true });
|
|
403
|
+
const results = [];
|
|
404
|
+
const seenUrls = new Set();
|
|
405
|
+
$('item').each((_, element) => {
|
|
406
|
+
if (results.length >= maxResults) return false;
|
|
407
|
+
const title = normalizeWhitespace($(element).find('title').first().text());
|
|
408
|
+
const url = normalizeSearchResultUrl($(element).find('link').first().text());
|
|
409
|
+
if (!title || !url || seenUrls.has(url)) return undefined;
|
|
410
|
+
seenUrls.add(url);
|
|
411
|
+
results.push({
|
|
412
|
+
title,
|
|
413
|
+
url,
|
|
414
|
+
description: normalizeRssDescription(cheerio, $(element).find('description').first().text()),
|
|
415
|
+
hostname: hostnameFromUrl(url),
|
|
416
|
+
published_at: normalizeWhitespace($(element).find('pubDate').first().text())
|
|
417
|
+
});
|
|
418
|
+
return undefined;
|
|
419
|
+
});
|
|
420
|
+
return { results };
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function normalizeSearchResultUrl(value) {
|
|
424
|
+
const text = String(value || '').trim();
|
|
425
|
+
if (!text) return '';
|
|
426
|
+
try {
|
|
427
|
+
const parsed = new URL(text);
|
|
428
|
+
if (!['http:', 'https:'].includes(parsed.protocol)) return '';
|
|
429
|
+
return parsed.toString();
|
|
430
|
+
} catch {
|
|
431
|
+
return '';
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function normalizeRssDescription(cheerio, value) {
|
|
436
|
+
const text = String(value || '').trim();
|
|
437
|
+
if (!text) return '';
|
|
438
|
+
return normalizeWhitespace(cheerio.load(text).text() || text);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function hostnameFromUrl(value) {
|
|
442
|
+
try {
|
|
443
|
+
return new URL(value).hostname;
|
|
444
|
+
} catch {
|
|
445
|
+
return '';
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
372
449
|
function findUniqueLineBlock(lines, blockContent) {
|
|
373
450
|
const probeLines = splitLines(blockContent);
|
|
374
451
|
if (probeLines.length === 0 || (probeLines.length === 1 && probeLines[0] === '')) return null;
|
|
@@ -967,7 +1044,7 @@ async function runCommand(root, config, args) {
|
|
|
967
1044
|
command,
|
|
968
1045
|
cwd: root,
|
|
969
1046
|
shell: config.shell.default,
|
|
970
|
-
timeoutMs: config.shell.timeout_ms
|
|
1047
|
+
timeoutMs: Number(args?.timeout || args?.timeout_ms || args?.timeoutMs || config.shell.timeout_ms)
|
|
971
1048
|
});
|
|
972
1049
|
return { ...result, command };
|
|
973
1050
|
}
|
|
@@ -1842,24 +1919,6 @@ export function getBuiltinTools({ workspaceRoot = process.cwd(), config, onSyste
|
|
|
1842
1919
|
}
|
|
1843
1920
|
}
|
|
1844
1921
|
},
|
|
1845
|
-
{
|
|
1846
|
-
type: 'function',
|
|
1847
|
-
function: {
|
|
1848
|
-
name: 'glob',
|
|
1849
|
-
description:
|
|
1850
|
-
'Find files by glob pattern. Use this when you already know a filename pattern such as src/**/*.ts.',
|
|
1851
|
-
parameters: {
|
|
1852
|
-
type: 'object',
|
|
1853
|
-
properties: {
|
|
1854
|
-
pattern: { type: 'string', description: 'Glob pattern' },
|
|
1855
|
-
path: { type: 'string', description: 'Directory to search' },
|
|
1856
|
-
include_hidden: { type: 'boolean', description: 'Include dotfiles' },
|
|
1857
|
-
max_results: { type: 'number', description: 'Max results' }
|
|
1858
|
-
},
|
|
1859
|
-
required: ['pattern']
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
|
-
},
|
|
1863
1922
|
{
|
|
1864
1923
|
type: 'function',
|
|
1865
1924
|
function: {
|
|
@@ -2085,6 +2144,24 @@ export function getBuiltinTools({ workspaceRoot = process.cwd(), config, onSyste
|
|
|
2085
2144
|
];
|
|
2086
2145
|
|
|
2087
2146
|
const deferredDefinitions = {
|
|
2147
|
+
glob: {
|
|
2148
|
+
type: 'function',
|
|
2149
|
+
function: {
|
|
2150
|
+
name: 'glob',
|
|
2151
|
+
description:
|
|
2152
|
+
'Find files by glob pattern. Use this when you already know a filename pattern such as src/**/*.ts.',
|
|
2153
|
+
parameters: {
|
|
2154
|
+
type: 'object',
|
|
2155
|
+
properties: {
|
|
2156
|
+
pattern: { type: 'string', description: 'Glob pattern' },
|
|
2157
|
+
path: { type: 'string', description: 'Directory to search' },
|
|
2158
|
+
include_hidden: { type: 'boolean', description: 'Include dotfiles' },
|
|
2159
|
+
max_results: { type: 'number', description: 'Max results' }
|
|
2160
|
+
},
|
|
2161
|
+
required: ['pattern']
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
},
|
|
2088
2165
|
ast_query: {
|
|
2089
2166
|
type: 'function',
|
|
2090
2167
|
function: {
|
|
@@ -2145,15 +2222,15 @@ export function getBuiltinTools({ workspaceRoot = process.cwd(), config, onSyste
|
|
|
2145
2222
|
function: {
|
|
2146
2223
|
name: 'web_search',
|
|
2147
2224
|
description:
|
|
2148
|
-
'Run a live web search
|
|
2225
|
+
'Run a live web search by fetching Bing RSS results. Use this for keyword-based internet search. This tool respects config.web.search_enabled and will fail when network search is disabled.',
|
|
2149
2226
|
parameters: {
|
|
2150
2227
|
type: 'object',
|
|
2151
2228
|
properties: {
|
|
2152
2229
|
query: { type: 'string', description: 'Search query' },
|
|
2153
2230
|
q: { type: 'string', description: 'Alias for query' },
|
|
2154
2231
|
max_results: { type: 'number', description: 'Max results to return' },
|
|
2155
|
-
locale: { type: 'string', description: '
|
|
2156
|
-
region: { type: 'string', description: '
|
|
2232
|
+
locale: { type: 'string', description: 'Bing market and language such as en-US or zh-CN' },
|
|
2233
|
+
region: { type: 'string', description: 'Bing country code such as US or CN' }
|
|
2157
2234
|
},
|
|
2158
2235
|
required: ['query']
|
|
2159
2236
|
}
|
package/src/tui/chat-app.js
CHANGED
|
@@ -45,6 +45,22 @@ const ROLE_STYLES = {
|
|
|
45
45
|
badgeText: 'black',
|
|
46
46
|
chrome: 'gray'
|
|
47
47
|
},
|
|
48
|
+
general: {
|
|
49
|
+
accent: 'greenBright',
|
|
50
|
+
border: 'green',
|
|
51
|
+
text: 'greenBright',
|
|
52
|
+
badgeBg: 'green',
|
|
53
|
+
badgeText: 'black',
|
|
54
|
+
chrome: 'gray'
|
|
55
|
+
},
|
|
56
|
+
advisor: {
|
|
57
|
+
accent: 'blueBright',
|
|
58
|
+
border: 'blue',
|
|
59
|
+
text: 'blueBright',
|
|
60
|
+
badgeBg: 'blue',
|
|
61
|
+
badgeText: 'white',
|
|
62
|
+
chrome: 'gray'
|
|
63
|
+
},
|
|
48
64
|
planner: {
|
|
49
65
|
accent: 'magentaBright',
|
|
50
66
|
border: 'magenta',
|
|
@@ -105,7 +121,7 @@ const ROLE_STYLES = {
|
|
|
105
121
|
|
|
106
122
|
const TUI_COPY = {
|
|
107
123
|
zh: {
|
|
108
|
-
roleLabels: { you: '👤 你', coder: '💻 CODER', planner: '📋 PLANNER', reviewer: '🔍 REVIEWER', tester: '🧪 TESTER', summarizer: '📝 SUMMARIZER', system: '⚙️ 系统', error: '❌ 错误', pending: '⏳ 等待中' },
|
|
124
|
+
roleLabels: { you: '👤 你', general: 'GENERAL', advisor: '💡 ADVISOR', coder: '💻 CODER', planner: '📋 PLANNER', reviewer: '🔍 REVIEWER', tester: '🧪 TESTER', summarizer: '📝 SUMMARIZER', system: '⚙️ 系统', error: '❌ 错误', pending: '⏳ 等待中' },
|
|
109
125
|
generic: {
|
|
110
126
|
waitingForInput: '等待输入',
|
|
111
127
|
ready: '就绪',
|
|
@@ -219,6 +235,8 @@ const TUI_COPY = {
|
|
|
219
235
|
doingProjectIndex: '正在初始化项目索引',
|
|
220
236
|
doneFileIndex: '已刷新文件索引',
|
|
221
237
|
doingFileIndex: '正在刷新文件索引',
|
|
238
|
+
donePromptBudget: '已测量 Prompt 预算',
|
|
239
|
+
doingPromptBudget: '正在测量 Prompt 预算',
|
|
222
240
|
toolFailed: (name) => `工具执行失败: ${name}`,
|
|
223
241
|
waitingModelContinue: (detail) => `${detail},等待模型继续`,
|
|
224
242
|
waitingModelAdjust: (detail) => `${detail},等待模型调整`
|
|
@@ -330,7 +348,7 @@ const TUI_COPY = {
|
|
|
330
348
|
}
|
|
331
349
|
},
|
|
332
350
|
en: {
|
|
333
|
-
roleLabels: { you: 'YOU', coder: 'CODER', planner: 'PLANNER', reviewer: 'REVIEWER', tester: 'TESTER', summarizer: 'SUMMARIZER', system: 'SYSTEM', error: 'ERROR', pending: 'PENDING' },
|
|
351
|
+
roleLabels: { you: 'YOU', general: 'GENERAL', advisor: 'ADVISOR', coder: 'CODER', planner: 'PLANNER', reviewer: 'REVIEWER', tester: 'TESTER', summarizer: 'SUMMARIZER', system: 'SYSTEM', error: 'ERROR', pending: 'PENDING' },
|
|
334
352
|
generic: {
|
|
335
353
|
waitingForInput: 'waiting for input',
|
|
336
354
|
ready: 'ready',
|
|
@@ -444,6 +462,8 @@ const TUI_COPY = {
|
|
|
444
462
|
doingProjectIndex: 'Initializing project index',
|
|
445
463
|
doneFileIndex: 'File index refreshed',
|
|
446
464
|
doingFileIndex: 'Refreshing file index',
|
|
465
|
+
donePromptBudget: 'Prompt budget measured',
|
|
466
|
+
doingPromptBudget: 'Measuring prompt budget',
|
|
447
467
|
toolFailed: (name) => `Tool failed: ${name}`,
|
|
448
468
|
waitingModelContinue: (detail) => `${detail}, waiting for model to continue`,
|
|
449
469
|
waitingModelAdjust: (detail) => `${detail}, waiting for model to adjust`
|
|
@@ -572,7 +592,7 @@ function roleStyle(label) {
|
|
|
572
592
|
return ROLE_STYLES[label] || ROLE_STYLES.system;
|
|
573
593
|
}
|
|
574
594
|
|
|
575
|
-
const PLAN_AGENT_ROLES = new Set(['planner', 'coder', 'reviewer', 'tester', 'summarizer']);
|
|
595
|
+
const PLAN_AGENT_ROLES = new Set(['planner', 'advisor', 'coder', 'reviewer', 'tester', 'summarizer']);
|
|
576
596
|
|
|
577
597
|
function normalizePlanAgentRole(role) {
|
|
578
598
|
const roleKey = String(role || '').trim().toLowerCase();
|
|
@@ -945,7 +965,7 @@ export function buildUiMessagesFromSessionHistory(sessionMessages, nextId) {
|
|
|
945
965
|
continue;
|
|
946
966
|
}
|
|
947
967
|
if (message.role === 'assistant') {
|
|
948
|
-
out.push({ id: nextId(), label: '
|
|
968
|
+
out.push({ id: nextId(), label: 'general', text, color: 'greenBright' });
|
|
949
969
|
continue;
|
|
950
970
|
}
|
|
951
971
|
if (message.role === 'system') {
|
|
@@ -1325,7 +1345,7 @@ export function isIndexSystemToolName(name) {
|
|
|
1325
1345
|
export function shouldShowCompletionFooter(msg) {
|
|
1326
1346
|
if (!msg || msg.loading || (msg.phase || '').trim()) return false;
|
|
1327
1347
|
const label = (msg.label || '').toLowerCase();
|
|
1328
|
-
return label === 'coder' || label === 'planner' || label === 'reviewer' || label === 'tester';
|
|
1348
|
+
return label === 'general' || label === 'advisor' || label === 'coder' || label === 'planner' || label === 'reviewer' || label === 'tester';
|
|
1329
1349
|
}
|
|
1330
1350
|
|
|
1331
1351
|
function describeToolActivity(name, copy, { done = false, blocked = false } = {}) {
|
|
@@ -2506,13 +2526,27 @@ export function buildMessageRows(msg, showToolDetails, contentWidth = 72, copy)
|
|
|
2506
2526
|
}
|
|
2507
2527
|
};
|
|
2508
2528
|
|
|
2529
|
+
const visiblePendingToolCalls = (existingCalls = []) => {
|
|
2530
|
+
const pendingToolCalls = Array.isArray(msg?.pendingToolCalls) ? msg.pendingToolCalls : [];
|
|
2531
|
+
return pendingToolCalls.filter((pending) => {
|
|
2532
|
+
if (!pending) return false;
|
|
2533
|
+
if (pending.id && existingCalls.some((tool) => tool?.id && tool.id === pending.id)) return false;
|
|
2534
|
+
const pendingBase = parseToolDisplayName(pending.name).base;
|
|
2535
|
+
return !existingCalls.some(
|
|
2536
|
+
(tool) => parseToolDisplayName(tool?.name).base === pendingBase && tool?.status === 'running'
|
|
2537
|
+
);
|
|
2538
|
+
});
|
|
2539
|
+
};
|
|
2540
|
+
|
|
2509
2541
|
if (Array.isArray(msg?.segments) && msg.segments.length > 0) {
|
|
2510
|
-
const
|
|
2542
|
+
const segmentTools = msg.segments.filter(
|
|
2511
2543
|
(segment) =>
|
|
2512
2544
|
segment.type === 'tool' ||
|
|
2513
2545
|
segment.type === 'skill' ||
|
|
2514
2546
|
(segment.type === 'system_tool' && (showToolDetails || !isIndexSystemToolName(segment.name)))
|
|
2515
|
-
)
|
|
2547
|
+
);
|
|
2548
|
+
const pendingToolCalls = visiblePendingToolCalls(segmentTools);
|
|
2549
|
+
const totalTools = segmentTools.length + pendingToolCalls.length;
|
|
2516
2550
|
let toolIndex = 0;
|
|
2517
2551
|
for (const segment of msg.segments) {
|
|
2518
2552
|
if (segment.type === 'tool' || segment.type === 'skill' || segment.type === 'system_tool') {
|
|
@@ -2525,19 +2559,14 @@ export function buildMessageRows(msg, showToolDetails, contentWidth = 72, copy)
|
|
|
2525
2559
|
pushTextRows(segment.text || '');
|
|
2526
2560
|
}
|
|
2527
2561
|
}
|
|
2562
|
+
pendingToolCalls.forEach((tool) => {
|
|
2563
|
+
pushActivityRows(tool, toolIndex, totalTools);
|
|
2564
|
+
toolIndex += 1;
|
|
2565
|
+
});
|
|
2528
2566
|
} else {
|
|
2529
2567
|
pushTextRows(msg?.text || '');
|
|
2530
2568
|
const toolCalls = Array.isArray(msg?.toolCalls) ? msg.toolCalls : [];
|
|
2531
|
-
const
|
|
2532
|
-
const visibleCalls = [
|
|
2533
|
-
...toolCalls,
|
|
2534
|
-
...pendingToolCalls.filter((pending) => {
|
|
2535
|
-
if (!pending) return false;
|
|
2536
|
-
if (pending.id && toolCalls.some((tool) => tool?.id && tool.id === pending.id)) return false;
|
|
2537
|
-
const pendingBase = parseToolDisplayName(pending.name).base;
|
|
2538
|
-
return !toolCalls.some((tool) => parseToolDisplayName(tool?.name).base === pendingBase && tool?.status === 'running');
|
|
2539
|
-
})
|
|
2540
|
-
];
|
|
2569
|
+
const visibleCalls = [...toolCalls, ...visiblePendingToolCalls(toolCalls)];
|
|
2541
2570
|
visibleCalls.forEach((tool, idx) => pushActivityRows(tool, idx, visibleCalls.length));
|
|
2542
2571
|
}
|
|
2543
2572
|
|
|
@@ -3324,6 +3353,7 @@ function formatRuntimeSnapshot(snapshot) {
|
|
|
3324
3353
|
if (!snapshot || typeof snapshot !== 'object') return '';
|
|
3325
3354
|
return [
|
|
3326
3355
|
`mode=${snapshot.mode || '-'}`,
|
|
3356
|
+
`role=${snapshot.agentRole || 'general'}`,
|
|
3327
3357
|
`model=${snapshot.model || '-'}`,
|
|
3328
3358
|
`max_ctx=${snapshot.maxContextTokens || '-'}`,
|
|
3329
3359
|
`session=${snapshot.sessionId || '-'}`
|
|
@@ -3553,7 +3583,7 @@ export function ChatApp({ runtime, sessionId, model, sdkProvider = 'openai-compa
|
|
|
3553
3583
|
const current = Number(last[1]);
|
|
3554
3584
|
const total = Number(last[2]);
|
|
3555
3585
|
const role = String(last[3] || '').trim().toLowerCase();
|
|
3556
|
-
const normalizedRole =
|
|
3586
|
+
const normalizedRole = PLAN_AGENT_ROLES.has(role) ? role : 'coder';
|
|
3557
3587
|
const title = String(last[4] || '').trim();
|
|
3558
3588
|
|
|
3559
3589
|
// Detect step transition — finalize old assistant and create a new one
|
|
@@ -3761,7 +3791,7 @@ export function ChatApp({ runtime, sessionId, model, sdkProvider = 'openai-compa
|
|
|
3761
3791
|
...prev,
|
|
3762
3792
|
{
|
|
3763
3793
|
id: nextId(),
|
|
3764
|
-
label: '
|
|
3794
|
+
label: 'general',
|
|
3765
3795
|
text: sanitizeRenderableText(displayText),
|
|
3766
3796
|
color: 'greenBright',
|
|
3767
3797
|
autoSkillNames: activeAssistantAutoSkillNamesRef.current
|
|
@@ -3901,8 +3931,8 @@ export function ChatApp({ runtime, sessionId, model, sdkProvider = 'openai-compa
|
|
|
3901
3931
|
const aid = nextId();
|
|
3902
3932
|
activeAssistantIdRef.current = aid;
|
|
3903
3933
|
const planRole = activePlanStepRoleRef.current;
|
|
3904
|
-
const label = planRole || '
|
|
3905
|
-
const style = ROLE_STYLES[label] || ROLE_STYLES.
|
|
3934
|
+
const label = planRole || 'general';
|
|
3935
|
+
const style = ROLE_STYLES[label] || ROLE_STYLES.general;
|
|
3906
3936
|
const planStepInfo = activePlanStepInfoRef.current;
|
|
3907
3937
|
const planStepTitle = activePlanStepTitleRef.current;
|
|
3908
3938
|
const planStepDisplay = planStepInfo ? `${planStepInfo.current}/${planStepInfo.total} · ${planStepTitle}` : undefined;
|
|
@@ -4090,7 +4120,7 @@ export function ChatApp({ runtime, sessionId, model, sdkProvider = 'openai-compa
|
|
|
4090
4120
|
const cleanedStandaloneText = stripPlanExecutionResult(String(displayText || event.text)).trim();
|
|
4091
4121
|
setMessages((prev) => [
|
|
4092
4122
|
...prev,
|
|
4093
|
-
{ id: nextId(), label: '
|
|
4123
|
+
{ id: nextId(), label: 'general', text: cleanedStandaloneText, color: 'greenBright' }
|
|
4094
4124
|
]);
|
|
4095
4125
|
}
|
|
4096
4126
|
}
|
|
@@ -10,5 +10,11 @@ export function describeSystemToolActivity(copy, parsed, { done = false, blocked
|
|
|
10
10
|
if (blocked) return makeBlocked(copy, safeTarget);
|
|
11
11
|
return done ? `${copy.toolActivity.doneFileIndex}: ${safeTarget}` : `${copy.toolActivity.doingFileIndex}: ${safeTarget}`;
|
|
12
12
|
}
|
|
13
|
+
if (parsed.base === 'prompt_budget') {
|
|
14
|
+
if (blocked) return makeBlocked(copy, 'prompt_budget');
|
|
15
|
+
return done
|
|
16
|
+
? (copy.toolActivity.donePromptBudget || 'Prompt budget measured')
|
|
17
|
+
: (copy.toolActivity.doingPromptBudget || 'Measuring prompt budget');
|
|
18
|
+
}
|
|
13
19
|
return '';
|
|
14
20
|
}
|