mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 15:31:27 +00:00
refactor: remove read_many_files tool, add readManyFiles utility for user @-commands
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
bd900d3668
commit
7e5c1ae43a
26 changed files with 1118 additions and 2121 deletions
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import * as path from 'node:path';
|
||||
import type { Part, FunctionCall } from '@google/genai';
|
||||
import type {
|
||||
ResumedSessionData,
|
||||
|
|
@ -12,8 +13,13 @@ import type {
|
|||
AnyDeclarativeTool,
|
||||
ToolResultDisplay,
|
||||
SlashCommandRecordPayload,
|
||||
AtCommandRecordPayload,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import type { HistoryItem, HistoryItemWithoutId } from '../types.js';
|
||||
import type {
|
||||
HistoryItem,
|
||||
HistoryItemWithoutId,
|
||||
IndividualToolCallDisplay,
|
||||
} from '../types.js';
|
||||
import { ToolCallStatus } from '../types.js';
|
||||
|
||||
/**
|
||||
|
|
@ -137,6 +143,8 @@ function convertToHistoryItems(
|
|||
config: Config,
|
||||
): HistoryItemWithoutId[] {
|
||||
const items: HistoryItemWithoutId[] = [];
|
||||
const pendingAtCommands: AtCommandRecordPayload[] = [];
|
||||
let atCommandCounter = 0;
|
||||
|
||||
// Track pending tool calls for grouping with results
|
||||
const pendingToolCalls = new Map<
|
||||
|
|
@ -152,6 +160,59 @@ function convertToHistoryItems(
|
|||
confirmationDetails: undefined;
|
||||
}> = [];
|
||||
|
||||
const buildAtCommandDisplays = (
|
||||
payload: AtCommandRecordPayload,
|
||||
): IndividualToolCallDisplay[] => {
|
||||
// Error case: single "Read File(s)" with error message
|
||||
if (payload.status === 'error') {
|
||||
atCommandCounter += 1;
|
||||
const filesLabel = payload.filesRead?.length
|
||||
? payload.filesRead.join(', ')
|
||||
: 'files';
|
||||
return [
|
||||
{
|
||||
callId: `at-command-${atCommandCounter}`,
|
||||
name: 'Read File(s)',
|
||||
description: 'Error attempting to read files',
|
||||
status: ToolCallStatus.Error,
|
||||
resultDisplay:
|
||||
payload.message || `Error reading files (${filesLabel})`,
|
||||
confirmationDetails: undefined,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Success case: individual tool calls for each file
|
||||
if (!payload.filesRead?.length) {
|
||||
atCommandCounter += 1;
|
||||
return [
|
||||
{
|
||||
callId: `at-command-${atCommandCounter}`,
|
||||
name: 'Read File',
|
||||
description: 'Read File(s)',
|
||||
status: ToolCallStatus.Success,
|
||||
resultDisplay: undefined,
|
||||
confirmationDetails: undefined,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return payload.filesRead.map((filePath) => {
|
||||
atCommandCounter += 1;
|
||||
const isDir = filePath.endsWith('/');
|
||||
return {
|
||||
callId: `at-command-${atCommandCounter}`,
|
||||
name: isDir ? 'Read Directory' : 'Read File',
|
||||
description: isDir
|
||||
? `Read directory ${path.basename(filePath)}`
|
||||
: `Read file ${path.basename(filePath)}`,
|
||||
status: ToolCallStatus.Success,
|
||||
resultDisplay: undefined,
|
||||
confirmationDetails: undefined,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
for (const record of conversation.messages) {
|
||||
if (record.type === 'system') {
|
||||
if (record.subtype === 'slash_command') {
|
||||
|
|
@ -180,10 +241,44 @@ function convertToHistoryItems(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (record.subtype === 'at_command') {
|
||||
const payload = record.systemPayload as
|
||||
| AtCommandRecordPayload
|
||||
| undefined;
|
||||
if (!payload) continue;
|
||||
pendingAtCommands.push(payload);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
switch (record.type) {
|
||||
case 'user': {
|
||||
if (pendingAtCommands.length > 0) {
|
||||
// Flush any pending tool group before user message
|
||||
if (currentToolGroup.length > 0) {
|
||||
items.push({
|
||||
type: 'tool_group',
|
||||
tools: [...currentToolGroup],
|
||||
});
|
||||
currentToolGroup = [];
|
||||
}
|
||||
|
||||
const payload = pendingAtCommands.shift()!;
|
||||
const text =
|
||||
payload.userText ||
|
||||
extractTextFromParts(record.message?.parts as Part[]);
|
||||
if (text) {
|
||||
items.push({ type: 'user', text });
|
||||
}
|
||||
|
||||
const toolDisplays = buildAtCommandDisplays(payload);
|
||||
if (toolDisplays.length > 0) {
|
||||
items.push({
|
||||
type: 'tool_group',
|
||||
tools: toolDisplays,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Flush any pending tool group before user message
|
||||
if (currentToolGroup.length > 0) {
|
||||
items.push({
|
||||
|
|
@ -290,6 +385,31 @@ function convertToHistoryItems(
|
|||
}
|
||||
}
|
||||
|
||||
if (pendingAtCommands.length > 0) {
|
||||
for (const payload of pendingAtCommands) {
|
||||
// Flush any pending tool group before standalone @-command
|
||||
if (currentToolGroup.length > 0) {
|
||||
items.push({
|
||||
type: 'tool_group',
|
||||
tools: [...currentToolGroup],
|
||||
});
|
||||
currentToolGroup = [];
|
||||
}
|
||||
|
||||
const text = payload.userText;
|
||||
if (text) {
|
||||
items.push({ type: 'user', text });
|
||||
}
|
||||
const toolDisplays = buildAtCommandDisplays(payload);
|
||||
if (toolDisplays.length > 0) {
|
||||
items.push({
|
||||
type: 'tool_group',
|
||||
tools: toolDisplays,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flush any remaining tool group
|
||||
if (currentToolGroup.length > 0) {
|
||||
items.push({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue