mini-coder 0.5.11 → 0.5.12
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/BENCHMARK.md +408 -0
- package/PROGRESS.md +5 -0
- package/README.md +14 -1
- package/assets/mc-claude-smart.png +0 -0
- package/assets/mc-gpt-smart.png +0 -0
- package/benchmark-loop.sh +19 -0
- package/package.json +1 -1
- package/src/headless.ts +62 -21
- package/src/index.ts +35 -56
- package/src/prompt.ts +8 -0
- package/src/session-message.ts +393 -0
- package/src/session.ts +102 -396
- package/src/settings.ts +19 -15
- package/src/shared.ts +39 -0
- package/src/submit.ts +3 -25
- package/src/text.ts +71 -0
- package/src/tool-common.ts +91 -0
- package/src/tool-grep.ts +606 -0
- package/src/tool-read.ts +313 -0
- package/src/tool-shell.ts +869 -0
- package/src/tools.ts +186 -995
- package/src/ui/agent.ts +199 -110
- package/src/ui/commands.test.ts +14 -13
- package/src/ui/commands.ts +21 -47
- package/src/ui/conversation.test.ts +360 -0
- package/src/ui/conversation.ts +496 -151
- package/src/ui/input.test.ts +1 -43
- package/src/ui/runtime.ts +69 -0
- package/src/ui.ts +196 -114
package/src/submit.ts
CHANGED
|
@@ -18,8 +18,7 @@ import {
|
|
|
18
18
|
} from "./index.ts";
|
|
19
19
|
import { parseInput } from "./input.ts";
|
|
20
20
|
import {
|
|
21
|
-
|
|
22
|
-
addMessageToStats,
|
|
21
|
+
appendConversationMessage,
|
|
23
22
|
appendMessage,
|
|
24
23
|
appendPromptHistory,
|
|
25
24
|
filterModelMessages,
|
|
@@ -254,26 +253,9 @@ export function queueResolvedInput(
|
|
|
254
253
|
function handleAgentEvent(event: AgentEvent, state: AppState): void {
|
|
255
254
|
switch (event.type) {
|
|
256
255
|
case "user_message":
|
|
257
|
-
state.messages.push(event.message);
|
|
258
|
-
state.contextTokens = addMessageToContextTokens(
|
|
259
|
-
state.contextTokens,
|
|
260
|
-
event.message,
|
|
261
|
-
);
|
|
262
|
-
break;
|
|
263
256
|
case "assistant_message":
|
|
264
|
-
state.messages.push(event.message);
|
|
265
|
-
state.stats = addMessageToStats(state.stats, event.message);
|
|
266
|
-
state.contextTokens = addMessageToContextTokens(
|
|
267
|
-
state.contextTokens,
|
|
268
|
-
event.message,
|
|
269
|
-
);
|
|
270
|
-
break;
|
|
271
257
|
case "tool_result":
|
|
272
|
-
state
|
|
273
|
-
state.contextTokens = addMessageToContextTokens(
|
|
274
|
-
state.contextTokens,
|
|
275
|
-
event.message,
|
|
276
|
-
);
|
|
258
|
+
appendConversationMessage(state, event.message);
|
|
277
259
|
break;
|
|
278
260
|
case "text_delta":
|
|
279
261
|
case "thinking_delta":
|
|
@@ -329,11 +311,7 @@ export async function submitResolvedInput(
|
|
|
329
311
|
} satisfies UserMessage;
|
|
330
312
|
|
|
331
313
|
const turn = appendMessage(state.db, session.id, userMessage);
|
|
332
|
-
state
|
|
333
|
-
state.contextTokens = addMessageToContextTokens(
|
|
334
|
-
state.contextTokens,
|
|
335
|
-
userMessage,
|
|
336
|
-
);
|
|
314
|
+
appendConversationMessage(state, userMessage);
|
|
337
315
|
hooks?.onUserMessage?.(state);
|
|
338
316
|
|
|
339
317
|
const systemPrompt = buildPrompt(state);
|
package/src/text.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared text-shaping helpers.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Collapse whitespace runs to single spaces and trim the ends.
|
|
9
|
+
*
|
|
10
|
+
* @param text - Raw text to normalize.
|
|
11
|
+
* @returns The collapsed single-line text.
|
|
12
|
+
*/
|
|
13
|
+
export function collapseWhitespace(text: string): string {
|
|
14
|
+
return text.replace(/\s+/g, " ").trim();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Collapse whitespace into a single line, returning `null` when nothing remains.
|
|
19
|
+
*
|
|
20
|
+
* @param text - Raw text to normalize.
|
|
21
|
+
* @returns Collapsed text, or `null` when the result is empty.
|
|
22
|
+
*/
|
|
23
|
+
export function collapseWhitespaceToNull(text: string): string | null {
|
|
24
|
+
const collapsed = collapseWhitespace(text);
|
|
25
|
+
return collapsed.length > 0 ? collapsed : null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Join only `text` blocks from multipart content into one space-separated string.
|
|
30
|
+
*
|
|
31
|
+
* @param content - Multipart content blocks.
|
|
32
|
+
* @returns Concatenated text-block content.
|
|
33
|
+
*/
|
|
34
|
+
export function joinTextBlocks<T extends { type: string }>(
|
|
35
|
+
content: readonly T[],
|
|
36
|
+
): string {
|
|
37
|
+
return content
|
|
38
|
+
.flatMap((block) => {
|
|
39
|
+
return block.type === "text" &&
|
|
40
|
+
"text" in block &&
|
|
41
|
+
typeof block.text === "string"
|
|
42
|
+
? [block.text]
|
|
43
|
+
: [];
|
|
44
|
+
})
|
|
45
|
+
.join(" ");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Truncate text with an ellipsis from the start or end.
|
|
50
|
+
*
|
|
51
|
+
* @param text - Text to truncate.
|
|
52
|
+
* @param maxChars - Maximum visible characters including the ellipsis.
|
|
53
|
+
* @param side - Which side to truncate from.
|
|
54
|
+
* @returns Truncated text when needed.
|
|
55
|
+
*/
|
|
56
|
+
export function truncateText(
|
|
57
|
+
text: string,
|
|
58
|
+
maxChars: number,
|
|
59
|
+
side: "start" | "end" = "end",
|
|
60
|
+
): string {
|
|
61
|
+
if (text.length <= maxChars) {
|
|
62
|
+
return text;
|
|
63
|
+
}
|
|
64
|
+
if (maxChars <= 1) {
|
|
65
|
+
return "…";
|
|
66
|
+
}
|
|
67
|
+
if (side === "start") {
|
|
68
|
+
return `…${text.slice(text.length - (maxChars - 1))}`;
|
|
69
|
+
}
|
|
70
|
+
return `${text.slice(0, maxChars - 1)}…`;
|
|
71
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for built-in tool implementations.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
ImageContent,
|
|
9
|
+
Static,
|
|
10
|
+
TextContent,
|
|
11
|
+
Tool,
|
|
12
|
+
ToolCall,
|
|
13
|
+
TSchema,
|
|
14
|
+
} from "@mariozechner/pi-ai";
|
|
15
|
+
import { validateToolArguments } from "@mariozechner/pi-ai";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Result from executing a tool.
|
|
19
|
+
*
|
|
20
|
+
* Content blocks carry either text or image data. The agent loop maps these
|
|
21
|
+
* directly into pi-ai tool-result content.
|
|
22
|
+
*/
|
|
23
|
+
export interface ToolExecResult {
|
|
24
|
+
/** Content blocks for the tool result. */
|
|
25
|
+
content: (TextContent | ImageContent)[];
|
|
26
|
+
/** Whether the execution encountered an error. */
|
|
27
|
+
isError: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build a text-only tool result.
|
|
32
|
+
*
|
|
33
|
+
* @param text - Message text to return in the tool result.
|
|
34
|
+
* @param isError - Whether the result represents a tool error.
|
|
35
|
+
* @returns Text-only tool result content.
|
|
36
|
+
*/
|
|
37
|
+
export function textResult(text: string, isError: boolean): ToolExecResult {
|
|
38
|
+
return { content: [{ type: "text", text }], isError };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Detect which line ending a text blob uses.
|
|
43
|
+
*
|
|
44
|
+
* @param content - Text to inspect.
|
|
45
|
+
* @returns The first detected line ending, or `null` when the text is single-line.
|
|
46
|
+
*/
|
|
47
|
+
export function detectLineEnding(content: string): "\n" | "\r\n" | null {
|
|
48
|
+
if (content.includes("\r\n")) {
|
|
49
|
+
return "\r\n";
|
|
50
|
+
}
|
|
51
|
+
if (content.includes("\n")) {
|
|
52
|
+
return "\n";
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Normalize line endings to a specific style.
|
|
59
|
+
*
|
|
60
|
+
* @param content - Text to normalize.
|
|
61
|
+
* @param lineEnding - Target line ending sequence.
|
|
62
|
+
* @returns Text using only the requested line ending style.
|
|
63
|
+
*/
|
|
64
|
+
export function normalizeLineEndings(
|
|
65
|
+
content: string,
|
|
66
|
+
lineEnding: "\n" | "\r\n",
|
|
67
|
+
): string {
|
|
68
|
+
if (lineEnding === "\r\n") {
|
|
69
|
+
return content.replace(/\r?\n/g, "\r\n");
|
|
70
|
+
}
|
|
71
|
+
return content.replace(/\r\n/g, "\n");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Validate and coerce built-in tool arguments against a typed TypeBox schema.
|
|
76
|
+
*
|
|
77
|
+
* @param tool - Built-in tool definition.
|
|
78
|
+
* @param args - Raw parsed tool-call arguments from the model.
|
|
79
|
+
* @returns Validated arguments typed from the tool schema.
|
|
80
|
+
*/
|
|
81
|
+
export function validateBuiltinToolArgs<TParameters extends TSchema>(
|
|
82
|
+
tool: Tool<TParameters>,
|
|
83
|
+
args: Record<string, unknown>,
|
|
84
|
+
): Static<TParameters> {
|
|
85
|
+
return validateToolArguments(tool, {
|
|
86
|
+
type: "toolCall",
|
|
87
|
+
id: tool.name,
|
|
88
|
+
name: tool.name,
|
|
89
|
+
arguments: args,
|
|
90
|
+
} satisfies ToolCall) as Static<TParameters>;
|
|
91
|
+
}
|