Ship Paseo-equivalent provider snapshot, AgentComposerBar, ACP dispatch rewrite with streaming/persist, permission prompts, and agent commands. Follow-up: pane-scoped chat resolution, CoderMessageList tool timeline, WS user-delta replace, and inference orphan tool_call stripping. Archive openspec v2-2; update CHANGELOG and CURRENT. Co-authored-by: Cursor <cursoragent@cursor.com>
69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
import type { ToolCall, ToolResult } from '@/api/types';
|
|
import type { ToolRun } from '@/components/ToolCallLine';
|
|
|
|
export interface AcpWireMeta {
|
|
status?: 'running' | 'completed' | 'failed' | 'canceled';
|
|
kind?: string | null;
|
|
title?: string;
|
|
output?: unknown;
|
|
error?: string;
|
|
}
|
|
|
|
export interface CoderToolCallWire {
|
|
id: string;
|
|
function: { name: string; arguments: string };
|
|
}
|
|
|
|
function parseArgs(raw: string): Record<string, unknown> {
|
|
try {
|
|
const parsed = JSON.parse(raw) as Record<string, unknown>;
|
|
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
} catch {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
export function wireToolCallToRun(wire: CoderToolCallWire): ToolRun {
|
|
const args = parseArgs(wire.function.arguments);
|
|
const acp = args._acp as AcpWireMeta | undefined;
|
|
const { _acp: _ignored, ...rest } = args;
|
|
const lifecycle = acp?.status ?? 'running';
|
|
const call: ToolCall = {
|
|
id: wire.id,
|
|
name: wire.function.name,
|
|
args: rest,
|
|
};
|
|
if (lifecycle === 'running') {
|
|
return { call, result: null };
|
|
}
|
|
const result: ToolResult = {
|
|
tool_call_id: wire.id,
|
|
output: acp?.output ?? null,
|
|
truncated: false,
|
|
...(acp?.error ? { error: acp.error } : {}),
|
|
};
|
|
return { call, result };
|
|
}
|
|
|
|
export function mergeWireToolCall(
|
|
existing: CoderToolCallWire[] | undefined,
|
|
incoming: { id: string; name: string; args: Record<string, unknown> },
|
|
): CoderToolCallWire[] {
|
|
const entry: CoderToolCallWire = {
|
|
id: incoming.id,
|
|
function: { name: incoming.name, arguments: JSON.stringify(incoming.args) },
|
|
};
|
|
const list = existing ?? [];
|
|
const idx = list.findIndex((tc) => tc.id === incoming.id);
|
|
if (idx >= 0) {
|
|
const next = [...list];
|
|
next[idx] = entry;
|
|
return next;
|
|
}
|
|
return [...list, entry];
|
|
}
|
|
|
|
export function wireToolCallsToRuns(wires: CoderToolCallWire[] | undefined): ToolRun[] {
|
|
return (wires ?? []).map(wireToolCallToRun);
|
|
}
|