/**
* Tool calls that arrive as text instead of as structured `tool_calls`.
*
* Several local models — Qwen's coder line especially, and anything served through Ollama's
* generic chat template — answer a tool-calling request by writing the call out in the content
* stream rather than attaching it to the response:
*
*
*
* src/main.py
* ...
*
*
*
* The model is doing exactly what was asked; only the envelope is wrong. Discarding it produced
* the worst possible outcome: a run that printed a wall of markup, wrote nothing, and then told
* the user their model was "ignoring tool calls" when it plainly was not.
*
* Only explicitly marked calls are parsed. Bare JSON in a reply is left alone however much it
* looks like a call, because a model explaining an API — or writing a file that happens to be
* JSON — must never be mistaken for one asking to run something.
*/
export interface TextToolCall {
name: string;
/** JSON, matching what the structured field would have carried. */
arguments: string;
}
export interface TextToolCallResult {
calls: TextToolCall[];
/** The reply with the call markup removed, for the transcript. */
cleaned: string;
}
/**
* The declared type of each parameter of a tool, or null if the tool is unknown.
*
* Needed because the text form carries no types: every value arrives as a string. Guessing by
* trying to parse each one as JSON would corrupt the most important case there is — writing a
* file whose contents are themselves JSON would turn the text into an object and lose it.
*/
export type ParamTypes = (toolName: string) => Record | null;
/**
* Tool calls a model wrote into its reply, and that reply with the markup taken out.
*
* Returns no calls at all when nothing is explicitly marked, so ordinary prose is untouched.
*/
export declare function parseTextToolCalls(content: string, paramTypes: ParamTypes): TextToolCallResult;
/** Builds the type lookup from the tool list the engine already assembles for the provider. */
export declare function paramTypesFrom(tools: ReadonlyArray<{
function?: {
name?: string;
parameters?: unknown;
};
}>): ParamTypes;
/**
* Whether a reply has started writing a tool call, cheap enough to run on every streamed chunk.
*
* Deliberately looser than the parser: the point is to stop putting markup on the screen as soon
* as it begins, before enough has arrived to parse.
*/
export declare function looksLikeTextToolCall(sofar: string): boolean;
/** The reply without those tokens, and without the blank space they leave behind. */
export declare function stripTemplateTokens(text: string): string;
/**
* Whether the reply so far could still turn out to be a bare JSON tool call.
*
* `looksLikeTextToolCall` needs the whole `{"name"` before it can say so, and a stream does not
* deliver it in one piece: the chunks arrive as `{`, then `"`, then `name`. Each was put on screen
* as it came, so a local model answering with a bare call printed `{"name` before anything
* suppressed the rest. Reported from an Ollama model, and visible in the screenshot as exactly
* that fragment sitting above the reply.
*
* True only while the reply is nothing but a possible opening — six or seven characters, at the
* very start. A `{` in the middle of prose is a `{`, and once the text stops being a prefix of one
* of these it flows straight through, having lost nothing but a few frames of delay.
*/
export declare function mightBeginTextToolCall(sofar: string): boolean;
/**
* Splits streamed text into the part safe to display and a tail that might begin a tool call.
*
* Suppression can only start once a marker is complete, and a chunk boundary falls wherever the
* provider put it — so a reply ended visibly with a bare ";
}
export type ToolShapes = (name: string) => ToolShape | null;
/** Tool names and their parameters, from the same array sent to the provider. */
export declare function toolShapesFrom(tools: ReadonlyArray<{
function?: {
name?: string;
parameters?: unknown;
};
}>): ToolShapes;
/**
* One line as a call, or null.
*
* Three shapes, all seen from local models: `read_file package.json`, `read_file("package.json")`
* and `read_file(path="package.json")`. Anything needing more than one value is only accepted in
* the named form — guessing which of two arguments a bare word belongs to is how a write ends up
* with its path and its contents the wrong way round.
*/
export declare function parseCommandStyleLine(line: string, shapes: ToolShapes, resolveAlias?: (name: string) => string | null): TextToolCall | null;
/**
* Calls written as commands inside fenced blocks.
*
* Only fenced blocks, and only fences whose language is one a model reaches for when it thinks it
* is issuing a command. A bare line in prose is not read as a call: "you can read_file anything"
* is a sentence.
*/
export declare function parseCommandStyleCalls(content: string, shapes: ToolShapes, resolveAlias?: (name: string) => string | null): TextToolCallResult;
//# sourceMappingURL=tool-call-text.d.ts.map