mini-coder 0.5.13 → 0.6.0
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 +25 -108
- package/bin/mc.ts +8 -11
- package/bun.lock +79 -269
- package/package.json +17 -22
- package/src/agent.ts +242 -915
- package/src/args.ts +289 -0
- package/src/headless.ts +43 -385
- package/src/index.ts +29 -836
- package/src/oauth.ts +117 -0
- package/src/prompt.ts +227 -276
- package/src/session.ts +57 -961
- package/src/shared.ts +117 -38
- package/src/tool-bash.ts +110 -0
- package/src/tool-edit.ts +133 -0
- package/src/tool-task.ts +114 -0
- package/src/tui-components.ts +150 -0
- package/src/tui-conversation.ts +262 -0
- package/src/tui-editor.ts +29 -0
- package/src/tui-overlay.ts +403 -0
- package/src/tui.ts +236 -0
- package/src/types.ts +160 -0
- package/tsconfig.json +17 -0
- package/BENCHMARK.md +0 -107
- package/LICENSE +0 -9
- package/PROGRESS.md +0 -4
- package/assets/icon-1-minimal.svg +0 -31
- package/assets/icon-2-dark-terminal.svg +0 -48
- package/assets/icon-3-gradient-modern.svg +0 -45
- package/assets/icon-4-filled-bold.svg +0 -54
- package/assets/icon-5-community-badge.svg +0 -63
- package/assets/mc-claude-smart.png +0 -0
- package/assets/mc-gpt-smart.png +0 -0
- package/assets/preview-0-5-0.png +0 -0
- package/assets/preview.gif +0 -0
- package/benchmark-baseline.sh +0 -15
- package/benchmark-loop.sh +0 -19
- package/skills-lock.json +0 -15
- package/src/cli.ts +0 -134
- package/src/errors.ts +0 -15
- package/src/git.ts +0 -247
- package/src/input.ts +0 -168
- package/src/mcp.ts +0 -609
- package/src/paths.ts +0 -37
- package/src/session-message.ts +0 -393
- package/src/settings.ts +0 -449
- package/src/skills.ts +0 -271
- package/src/submit.ts +0 -371
- package/src/text.ts +0 -71
- package/src/theme.ts +0 -330
- package/src/tool-common.ts +0 -93
- package/src/tool-grep.ts +0 -606
- package/src/tool-read.ts +0 -313
- package/src/tool-shell.ts +0 -1001
- package/src/tools.ts +0 -854
- package/src/ui/agent.ts +0 -317
- package/src/ui/commands.test.ts +0 -913
- package/src/ui/commands.ts +0 -834
- package/src/ui/conversation.test.ts +0 -585
- package/src/ui/conversation.ts +0 -1836
- package/src/ui/help.ts +0 -158
- package/src/ui/input.test.ts +0 -64
- package/src/ui/input.ts +0 -138
- package/src/ui/overlay.ts +0 -59
- package/src/ui/runtime.ts +0 -69
- package/src/ui/status.ts +0 -220
- package/src/ui.ts +0 -1190
- package/src/version.ts +0 -48
package/src/tui.ts
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { cel, HStack, ProcessTerminal, VStack } from "@cel-tui/core";
|
|
2
|
+
import simpleGit from "simple-git";
|
|
3
|
+
import { compactContext, streamAgent } from "./agent";
|
|
4
|
+
import {
|
|
5
|
+
buildSystemPrompt,
|
|
6
|
+
injectEnvReminder,
|
|
7
|
+
insertToolUsageReminder,
|
|
8
|
+
MAIN_PROMPT,
|
|
9
|
+
} from "./prompt";
|
|
10
|
+
import { updateSession } from "./session";
|
|
11
|
+
import { estimateTokens, secureRandomString } from "./shared";
|
|
12
|
+
import { bash, runBashTool } from "./tool-bash";
|
|
13
|
+
import { edit, runEditTool } from "./tool-edit";
|
|
14
|
+
import { runTaskTool, task } from "./tool-task";
|
|
15
|
+
import {
|
|
16
|
+
ActivityPill,
|
|
17
|
+
ContextPill,
|
|
18
|
+
GitPill,
|
|
19
|
+
ModelPill,
|
|
20
|
+
Spinner,
|
|
21
|
+
TextPill,
|
|
22
|
+
theme,
|
|
23
|
+
} from "./tui-components";
|
|
24
|
+
import { Conversation, emptyState } from "./tui-conversation";
|
|
25
|
+
import { Editor } from "./tui-editor";
|
|
26
|
+
import { mainMenu } from "./tui-overlay";
|
|
27
|
+
import type { AgentContex, ToolAndRunner, TUIState } from "./types";
|
|
28
|
+
|
|
29
|
+
// TODO: move all git things to `git.ts`
|
|
30
|
+
const git = simpleGit();
|
|
31
|
+
|
|
32
|
+
function clearOrAbort(state: TUIState) {
|
|
33
|
+
// Are we mid stream? Abort it.
|
|
34
|
+
if (state.streaming) {
|
|
35
|
+
state.abortController?.abort();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Is the user clearing a state prompt?
|
|
39
|
+
if (state.prompt?.length) {
|
|
40
|
+
state.prompt = "";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function initTUI(state: TUIState, leave: (s: string) => void) {
|
|
45
|
+
// TODO: Cleanup accumulated sessions for this cwd.
|
|
46
|
+
|
|
47
|
+
const { spinnerEvery, currentSpinner } = Spinner();
|
|
48
|
+
|
|
49
|
+
// Stable 60fps rendering.
|
|
50
|
+
// This ensure Xfps, and excessive calls get coalesced in cel-tui.
|
|
51
|
+
const fps = 60;
|
|
52
|
+
const baseFramerateIntervalId = setInterval(() => {
|
|
53
|
+
if (state.streaming) {
|
|
54
|
+
spinnerEvery();
|
|
55
|
+
}
|
|
56
|
+
cel.setTitle(
|
|
57
|
+
`mc ${state.streaming ? currentSpinner() : ">"} ../${state.cwd}`,
|
|
58
|
+
);
|
|
59
|
+
cel.render();
|
|
60
|
+
}, 1000 / fps);
|
|
61
|
+
|
|
62
|
+
const onWindowKeyPress = (key: string) => {
|
|
63
|
+
if (key === "ctrl+q" || key === "ctrl+c" || key === "ctrl+d") {
|
|
64
|
+
// Quit
|
|
65
|
+
clearInterval(baseFramerateIntervalId);
|
|
66
|
+
cel.stop();
|
|
67
|
+
leave("Done.");
|
|
68
|
+
} else if (key === "escape") {
|
|
69
|
+
// Abort or clear prompt
|
|
70
|
+
clearOrAbort(state);
|
|
71
|
+
} else if (key === "ctrl+p") {
|
|
72
|
+
state.overlay = true;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const onChange = (value: string) => {
|
|
77
|
+
state.prompt = value;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const onEditorKeyPress = (key: string) => {
|
|
81
|
+
// onKeyPress
|
|
82
|
+
if (key === "enter") {
|
|
83
|
+
if (state.prompt === ":q") {
|
|
84
|
+
clearInterval(baseFramerateIntervalId);
|
|
85
|
+
cel.stop();
|
|
86
|
+
leave("Done. I like vim too.");
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (state.prompt === ":n" || state.prompt === "/new") {
|
|
90
|
+
state.sessionId = undefined;
|
|
91
|
+
state.messages = [];
|
|
92
|
+
state.prompt = "";
|
|
93
|
+
state.contextSize = 0;
|
|
94
|
+
state.scrollOffset = 0;
|
|
95
|
+
state.stickToBottom = true;
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const submit = async () => {
|
|
99
|
+
await streamAgentTUI(state);
|
|
100
|
+
};
|
|
101
|
+
if (state.prompt && !state.streaming) submit();
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const menu = mainMenu(state);
|
|
107
|
+
|
|
108
|
+
cel.init(new ProcessTerminal());
|
|
109
|
+
cel.viewport(() => {
|
|
110
|
+
const layers = [
|
|
111
|
+
VStack(
|
|
112
|
+
{
|
|
113
|
+
height: "100%",
|
|
114
|
+
gap: 1,
|
|
115
|
+
padding: { x: 1, y: 1 },
|
|
116
|
+
onKeyPress: onWindowKeyPress,
|
|
117
|
+
},
|
|
118
|
+
[
|
|
119
|
+
state.messages.length ? Conversation(state) : emptyState(),
|
|
120
|
+
HStack({ gap: 1 }, [
|
|
121
|
+
ModelPill(state),
|
|
122
|
+
TextPill(`../${state.cwd}`, theme.bwhite, theme.bblack),
|
|
123
|
+
GitPill(state),
|
|
124
|
+
VStack({ flex: 1 }, []),
|
|
125
|
+
ActivityPill(state, currentSpinner()),
|
|
126
|
+
ContextPill(state),
|
|
127
|
+
]),
|
|
128
|
+
|
|
129
|
+
Editor(state, onChange, onEditorKeyPress),
|
|
130
|
+
],
|
|
131
|
+
),
|
|
132
|
+
];
|
|
133
|
+
if (state.overlay) {
|
|
134
|
+
layers.push(menu());
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return layers;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function streamAgentTUI(state: TUIState) {
|
|
142
|
+
state.streaming = true;
|
|
143
|
+
|
|
144
|
+
const abortController = new AbortController();
|
|
145
|
+
state.abortController = abortController;
|
|
146
|
+
|
|
147
|
+
const tools: ToolAndRunner[] = [
|
|
148
|
+
{ tool: bash, runner: runBashTool },
|
|
149
|
+
{ tool: edit, runner: runEditTool },
|
|
150
|
+
{
|
|
151
|
+
tool: task,
|
|
152
|
+
runner: (args, signal) => runTaskTool(state.options, args, signal),
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
let userContent = state.prompt;
|
|
157
|
+
if (state.messages.length === 0) {
|
|
158
|
+
const envReminder = await injectEnvReminder();
|
|
159
|
+
userContent = `${envReminder}\n\n${userContent}`;
|
|
160
|
+
}
|
|
161
|
+
state.messages.push({
|
|
162
|
+
role: "user",
|
|
163
|
+
content: userContent,
|
|
164
|
+
timestamp: Date.now(),
|
|
165
|
+
});
|
|
166
|
+
state.prompt = "";
|
|
167
|
+
|
|
168
|
+
const systemPrompt = await buildSystemPrompt(MAIN_PROMPT);
|
|
169
|
+
const ctx: AgentContex = {
|
|
170
|
+
systemPrompt,
|
|
171
|
+
tools,
|
|
172
|
+
messages: state.messages,
|
|
173
|
+
options: state.options,
|
|
174
|
+
signal: state.abortController?.signal,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// We send a reference to state.messages, so things just render.
|
|
178
|
+
// We just need to react to some updates.
|
|
179
|
+
const agent = streamAgent(ctx);
|
|
180
|
+
try {
|
|
181
|
+
for await (const ev of agent) {
|
|
182
|
+
switch (ev.type) {
|
|
183
|
+
case "message_start":
|
|
184
|
+
case "message_update":
|
|
185
|
+
break;
|
|
186
|
+
|
|
187
|
+
case "message_end":
|
|
188
|
+
state.contextSize = estimateTokens(JSON.stringify(ctx));
|
|
189
|
+
break;
|
|
190
|
+
|
|
191
|
+
case "tool_message_start":
|
|
192
|
+
case "tool_message_update":
|
|
193
|
+
break;
|
|
194
|
+
|
|
195
|
+
case "tool_message_end": {
|
|
196
|
+
const withReminder = insertToolUsageReminder(
|
|
197
|
+
state.messages,
|
|
198
|
+
ev.message,
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
const idx = state.messages.findIndex(
|
|
202
|
+
(m) =>
|
|
203
|
+
m.role === "toolResult" &&
|
|
204
|
+
m.toolCallId === withReminder.toolCallId,
|
|
205
|
+
);
|
|
206
|
+
if (idx >= 0) {
|
|
207
|
+
state.messages[idx] = withReminder;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
state.contextSize = estimateTokens(JSON.stringify(ctx));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} finally {
|
|
215
|
+
state.streaming = false;
|
|
216
|
+
if (!state.sessionId) {
|
|
217
|
+
const id = secureRandomString(10);
|
|
218
|
+
state.sessionId = id;
|
|
219
|
+
}
|
|
220
|
+
// TODO: Should we make this delta only so compaction doesn;t affect saves?
|
|
221
|
+
// I'm not sure since it we do, there is no trace in logs about compaction
|
|
222
|
+
// and that would mean the logs don't repesent the truth. Confusing decision.
|
|
223
|
+
await updateSession(state.sessionId, state.messages);
|
|
224
|
+
|
|
225
|
+
// Compact after saving, if the next turn fails because of compaction, the session is recoverable.
|
|
226
|
+
// Compact at 80k tokens, the dumb zone threshold.
|
|
227
|
+
if (estimateTokens(JSON.stringify(state.messages)) > 80000)
|
|
228
|
+
compactContext(state.messages);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
const gitStatus = (await git.status()).isClean() ? "" : "*";
|
|
233
|
+
const gitBranch = (await git.branch()).current;
|
|
234
|
+
state.gitBranch = `${gitBranch}${gitStatus}`;
|
|
235
|
+
} catch (_) {}
|
|
236
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Api,
|
|
3
|
+
type AssistantMessage,
|
|
4
|
+
type Message,
|
|
5
|
+
type Model,
|
|
6
|
+
type Static,
|
|
7
|
+
type ThinkingLevel,
|
|
8
|
+
type Tool,
|
|
9
|
+
type ToolResultMessage,
|
|
10
|
+
Type,
|
|
11
|
+
} from "@mariozechner/pi-ai";
|
|
12
|
+
import type { OAuthCredentials } from "@mariozechner/pi-ai/oauth";
|
|
13
|
+
|
|
14
|
+
const ThinkingLevelSchema = Type.Unsafe<ThinkingLevel>(
|
|
15
|
+
Type.Union([
|
|
16
|
+
Type.Literal("minimal"),
|
|
17
|
+
Type.Literal("low"),
|
|
18
|
+
Type.Literal("medium"),
|
|
19
|
+
Type.Literal("high"),
|
|
20
|
+
Type.Literal("xhigh"),
|
|
21
|
+
]),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const ModelSchema = Type.Unsafe<Model<Api>>(
|
|
25
|
+
Type.Object({
|
|
26
|
+
id: Type.String(),
|
|
27
|
+
name: Type.String(),
|
|
28
|
+
api: Type.String(),
|
|
29
|
+
provider: Type.String(),
|
|
30
|
+
baseUrl: Type.String(),
|
|
31
|
+
reasoning: Type.Boolean(),
|
|
32
|
+
input: Type.Array(
|
|
33
|
+
Type.Union([Type.Literal("text"), Type.Literal("image")]),
|
|
34
|
+
),
|
|
35
|
+
cost: Type.Object({
|
|
36
|
+
input: Type.Number(),
|
|
37
|
+
output: Type.Number(),
|
|
38
|
+
cacheRead: Type.Number(),
|
|
39
|
+
cacheWrite: Type.Number(),
|
|
40
|
+
}),
|
|
41
|
+
contextWindow: Type.Number(),
|
|
42
|
+
maxTokens: Type.Number(),
|
|
43
|
+
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
44
|
+
compat: Type.Optional(Type.Unknown()),
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export const SettingsSchema = Type.Object({
|
|
49
|
+
provider: Type.String(),
|
|
50
|
+
model: Type.String(),
|
|
51
|
+
effort: ThinkingLevelSchema,
|
|
52
|
+
customProviders: Type.Optional(Type.Array(ModelSchema)),
|
|
53
|
+
});
|
|
54
|
+
export type Settings = Static<typeof SettingsSchema>;
|
|
55
|
+
|
|
56
|
+
export const CliOptionsSchema = Type.Object({
|
|
57
|
+
provider: Type.String(),
|
|
58
|
+
model: ModelSchema,
|
|
59
|
+
effort: ThinkingLevelSchema,
|
|
60
|
+
prompt: Type.Optional(Type.String()),
|
|
61
|
+
customProviders: Type.Optional(Type.Array(ModelSchema)),
|
|
62
|
+
});
|
|
63
|
+
export type CliOptions = Static<typeof CliOptionsSchema>;
|
|
64
|
+
|
|
65
|
+
type SavedOAuthAuth = OAuthCredentials & {
|
|
66
|
+
type: "oauth";
|
|
67
|
+
};
|
|
68
|
+
export type SavedOAuthCreds = Record<string, SavedOAuthAuth>;
|
|
69
|
+
|
|
70
|
+
export const MessageSchema = Type.Unsafe<Message>({});
|
|
71
|
+
export const SessionSchema = Type.Object({
|
|
72
|
+
id: Type.String(),
|
|
73
|
+
cwd: Type.String(),
|
|
74
|
+
messages: Type.Array(MessageSchema),
|
|
75
|
+
});
|
|
76
|
+
export type Session = Static<typeof SessionSchema>;
|
|
77
|
+
export type Sessions = Session[];
|
|
78
|
+
|
|
79
|
+
export type TUIState = {
|
|
80
|
+
options: CliOptions;
|
|
81
|
+
prompt: string;
|
|
82
|
+
messages: Message[];
|
|
83
|
+
contextSize?: number;
|
|
84
|
+
stickToBottom: boolean;
|
|
85
|
+
scrollOffset: number;
|
|
86
|
+
streaming: boolean;
|
|
87
|
+
abortController?: AbortController;
|
|
88
|
+
cwd: string;
|
|
89
|
+
gitBranch?: string;
|
|
90
|
+
overlay?: boolean | undefined;
|
|
91
|
+
sessionId?: string | undefined;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type AgentContex = {
|
|
95
|
+
systemPrompt: string;
|
|
96
|
+
tools: ToolAndRunner[];
|
|
97
|
+
messages: Message[];
|
|
98
|
+
options: CliOptions;
|
|
99
|
+
signal?: AbortSignal | undefined;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export type AgentEvent =
|
|
103
|
+
| {
|
|
104
|
+
type: "message_start" | "message_update";
|
|
105
|
+
partial: AssistantMessage;
|
|
106
|
+
}
|
|
107
|
+
| {
|
|
108
|
+
type: "message_end";
|
|
109
|
+
message: AssistantMessage;
|
|
110
|
+
}
|
|
111
|
+
| {
|
|
112
|
+
type: "tool_message_start" | "tool_message_update";
|
|
113
|
+
partial: ToolResultMessage;
|
|
114
|
+
}
|
|
115
|
+
| {
|
|
116
|
+
type: "tool_message_end";
|
|
117
|
+
message: ToolResultMessage;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export type AgentToolEvent =
|
|
121
|
+
| {
|
|
122
|
+
type: "tool_update";
|
|
123
|
+
partial: ToolResultMessage;
|
|
124
|
+
}
|
|
125
|
+
| {
|
|
126
|
+
type: "tool_result";
|
|
127
|
+
message: ToolResultMessage;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export type ToolRunnerEvent =
|
|
131
|
+
| { type: "output"; text: string }
|
|
132
|
+
| { type: "result"; text: string };
|
|
133
|
+
|
|
134
|
+
export type ToolAndRunner = {
|
|
135
|
+
tool: Tool;
|
|
136
|
+
runner: (
|
|
137
|
+
args: Record<string, any>,
|
|
138
|
+
signal?: AbortSignal,
|
|
139
|
+
) => AsyncGenerator<ToolRunnerEvent>;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export type SelectListItem = {
|
|
143
|
+
label: string;
|
|
144
|
+
value: string;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export type SelectState = {
|
|
148
|
+
value: string;
|
|
149
|
+
selected: string;
|
|
150
|
+
label: string;
|
|
151
|
+
list: SelectListItem[];
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export type SelectOptions = {
|
|
155
|
+
filter: string;
|
|
156
|
+
list: { label: string; value: string }[];
|
|
157
|
+
label?: string | undefined;
|
|
158
|
+
onSelect: (s: SelectState) => void | Promise<void>;
|
|
159
|
+
onCancel: () => void;
|
|
160
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ESNext"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"moduleDetection": "force",
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"types": ["bun"]
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*.ts", "bin/**/*.ts"]
|
|
17
|
+
}
|
package/BENCHMARK.md
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# CORE GOAL
|
|
2
|
-
|
|
3
|
-
**Terminal-Bench is a signal, not the product. The target is a better coding agent, not a higher benchmark score from benchmark-shaped patches.**
|
|
4
|
-
|
|
5
|
-
- Do not add fixes to fix an issue with specific terminal bench evals, focus on improving the agent's behaviour.
|
|
6
|
-
- Benchmarks run headless mode in one shot. Make sure you use `tmux` often to check that the TUI and multiturn UX is still
|
|
7
|
-
good.
|
|
8
|
-
|
|
9
|
-
# Benchmark workflow
|
|
10
|
-
|
|
11
|
-
Use this as the default tuning loop for `mini-coder` on Terminal-Bench.
|
|
12
|
-
|
|
13
|
-
The goal is not to rerun the whole benchmark after every change. The goal is to get fast enough feedback that small changes can be judged quickly, then promote only the promising ones to bigger runs.
|
|
14
|
-
|
|
15
|
-
## Principles
|
|
16
|
-
|
|
17
|
-
- Keep changes small.
|
|
18
|
-
- Change one thing at a time.
|
|
19
|
-
- Compare against a fresh baseline, not an old leaderboard run.
|
|
20
|
-
- Use fast suites for iteration, broad suites for promotion.
|
|
21
|
-
- Keep structured `mc --json` logs in trial artifacts so behavior can be analyzed.
|
|
22
|
-
- Optimize for general coding-agent behavior first.
|
|
23
|
-
- Use benchmark failures to extract general behavior gaps, not to encode benchmark lore into the agent.
|
|
24
|
-
- Prefer generic improvements over task-named patches, reminders, or stop-time nudges.
|
|
25
|
-
|
|
26
|
-
## Suites
|
|
27
|
-
|
|
28
|
-
There is a full 89 test baseline run with 2 attemps in the teminal-bench folder. Use the evals in it
|
|
29
|
-
to determine your fast evals to start your optimization process and iterations.
|
|
30
|
-
|
|
31
|
-
Settings:
|
|
32
|
-
|
|
33
|
-
- `2` attempts
|
|
34
|
-
- `2` concurrent
|
|
35
|
-
- `0` retries
|
|
36
|
-
|
|
37
|
-
## Experiment quality bar
|
|
38
|
-
|
|
39
|
-
Before changing code, write the hypothesis in two layers:
|
|
40
|
-
|
|
41
|
-
1. the benchmark symptom
|
|
42
|
-
2. the general coding-agent behavior gap behind it
|
|
43
|
-
|
|
44
|
-
Only run an experiment if you can answer all of these:
|
|
45
|
-
|
|
46
|
-
- what general behavior is being improved?
|
|
47
|
-
- why should that help outside Terminal-Bench?
|
|
48
|
-
- what would make this change obviously overfit?
|
|
49
|
-
|
|
50
|
-
Reject or redesign experiments that:
|
|
51
|
-
|
|
52
|
-
- depend on benchmark-specific task names, file names, package names, or tool names in product logic
|
|
53
|
-
- inject reminders or guards keyed to one benchmark noun unless that rule maps cleanly to a real product behavior
|
|
54
|
-
- only make sense because a particular verifier is known
|
|
55
|
-
- cannot be explained without citing a single task transcript
|
|
56
|
-
|
|
57
|
-
Hard rule:
|
|
58
|
-
|
|
59
|
-
- no task-specific nouns in agent logic unless they map to a real product feature
|
|
60
|
-
|
|
61
|
-
## Iteration loop
|
|
62
|
-
|
|
63
|
-
For each change:
|
|
64
|
-
|
|
65
|
-
1. inspect the last fast / focused failures
|
|
66
|
-
2. translate them into **one** general behavior gap
|
|
67
|
-
3. reject benchmark-shaped ideas; if you cannot phrase the change without task-specific nouns, keep diagnosing
|
|
68
|
-
4. if the change depends on a dynamic trigger, confirm that the trigger actually appears in the target failures
|
|
69
|
-
5. form **one** narrow hypothesis
|
|
70
|
-
6. make **one** small change
|
|
71
|
-
7. run:
|
|
72
|
-
- fast suite
|
|
73
|
-
8. compare to baseline or your reference run
|
|
74
|
-
9. decide:
|
|
75
|
-
- keep
|
|
76
|
-
- revert
|
|
77
|
-
- refine
|
|
78
|
-
|
|
79
|
-
## Behavior analysis requirements
|
|
80
|
-
|
|
81
|
-
Behavior analysis depends on structured agent logs.
|
|
82
|
-
|
|
83
|
-
Keep wrappers on:
|
|
84
|
-
|
|
85
|
-
- `mc --json -p ...`
|
|
86
|
-
|
|
87
|
-
Per trial, keep:
|
|
88
|
-
|
|
89
|
-
- result JSON
|
|
90
|
-
- verifier output
|
|
91
|
-
- exception type
|
|
92
|
-
- agent stderr
|
|
93
|
-
- structured `agent/mini-coder.ndjson`
|
|
94
|
-
- timestamps
|
|
95
|
-
|
|
96
|
-
## Minimal experiment log format
|
|
97
|
-
|
|
98
|
-
You are running in a loop, make sure to keep your progress tracked so you
|
|
99
|
-
can continue between loop iterations, this is to avoid context pressure.:w
|
|
100
|
-
Keep this in `PROGRESS.md`, a final summary for each completed change:
|
|
101
|
-
|
|
102
|
-
- benchmark symptom
|
|
103
|
-
- general behavior gap
|
|
104
|
-
- why this should help outside Terminal-Bench
|
|
105
|
-
- hypothesis
|
|
106
|
-
- verification method
|
|
107
|
-
- keep / revert / refine (Make the decision very visible in the file).
|
package/LICENSE
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Sean Caetano Martin
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
-
|
|
7
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/PROGRESS.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<!-- Mini Coder Icon v1: Minimal / Clean
|
|
2
|
-
Thin brackets, sharp lightning bolt. No fills — pure outline.
|
|
3
|
-
Inspired by: "small and fast, doesn't get in the way" -->
|
|
4
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
|
|
5
|
-
<!-- Left bracket { -->
|
|
6
|
-
<path
|
|
7
|
-
d="M38 12 C28 12 24 17 24 25 L24 40 C24 46 20 48 16 50 C20 52 24 54 24 60 L24 75 C24 83 28 88 38 88"
|
|
8
|
-
fill="none"
|
|
9
|
-
stroke="#1a1a2e"
|
|
10
|
-
stroke-width="5"
|
|
11
|
-
stroke-linecap="round"
|
|
12
|
-
stroke-linejoin="round"
|
|
13
|
-
/>
|
|
14
|
-
<!-- Right bracket } -->
|
|
15
|
-
<path
|
|
16
|
-
d="M62 12 C72 12 76 17 76 25 L76 40 C76 46 80 48 84 50 C80 52 76 54 76 60 L76 75 C76 83 72 88 62 88"
|
|
17
|
-
fill="none"
|
|
18
|
-
stroke="#1a1a2e"
|
|
19
|
-
stroke-width="5"
|
|
20
|
-
stroke-linecap="round"
|
|
21
|
-
stroke-linejoin="round"
|
|
22
|
-
/>
|
|
23
|
-
<!-- Lightning bolt -->
|
|
24
|
-
<path
|
|
25
|
-
d="M56 22 L43 52 L52 52 L44 78 L62 44 L52 44 Z"
|
|
26
|
-
fill="#f5c518"
|
|
27
|
-
stroke="#1a1a2e"
|
|
28
|
-
stroke-width="1.5"
|
|
29
|
-
stroke-linejoin="round"
|
|
30
|
-
/>
|
|
31
|
-
</svg>
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
<!-- Mini Coder Icon v2: Dark Terminal
|
|
2
|
-
Dark background, neon bolt and glowing brackets.
|
|
3
|
-
Inspired by: terminal aesthetic, ANSI colors, claude code dark UI -->
|
|
4
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
|
|
5
|
-
<defs>
|
|
6
|
-
<radialGradient id="bgGlow" cx="50%" cy="50%" r="50%">
|
|
7
|
-
<stop offset="0%" stop-color="#0d1117"/>
|
|
8
|
-
<stop offset="100%" stop-color="#010409"/>
|
|
9
|
-
</radialGradient>
|
|
10
|
-
<filter id="glow">
|
|
11
|
-
<feGaussianBlur stdDeviation="2.5" result="coloredBlur"/>
|
|
12
|
-
<feMerge>
|
|
13
|
-
<feMergeNode in="coloredBlur"/>
|
|
14
|
-
<feMergeNode in="SourceGraphic"/>
|
|
15
|
-
</feMerge>
|
|
16
|
-
</filter>
|
|
17
|
-
</defs>
|
|
18
|
-
|
|
19
|
-
<!-- Background rounded square -->
|
|
20
|
-
<rect x="4" y="4" width="92" height="92" rx="18" fill="url(#bgGlow)"/>
|
|
21
|
-
|
|
22
|
-
<!-- Left bracket { — neon cyan -->
|
|
23
|
-
<path
|
|
24
|
-
d="M38 14 C29 14 26 19 26 27 L26 41 C26 47 22 49 18 51 C22 53 26 55 26 61 L26 74 C26 82 29 87 38 87"
|
|
25
|
-
fill="none"
|
|
26
|
-
stroke="#00d4ff"
|
|
27
|
-
stroke-width="4.5"
|
|
28
|
-
stroke-linecap="round"
|
|
29
|
-
stroke-linejoin="round"
|
|
30
|
-
filter="url(#glow)"
|
|
31
|
-
/>
|
|
32
|
-
<!-- Right bracket } — neon cyan -->
|
|
33
|
-
<path
|
|
34
|
-
d="M62 14 C71 14 74 19 74 27 L74 41 C74 47 78 49 82 51 C78 53 74 55 74 61 L74 74 C74 82 71 87 62 87"
|
|
35
|
-
fill="none"
|
|
36
|
-
stroke="#00d4ff"
|
|
37
|
-
stroke-width="4.5"
|
|
38
|
-
stroke-linecap="round"
|
|
39
|
-
stroke-linejoin="round"
|
|
40
|
-
filter="url(#glow)"
|
|
41
|
-
/>
|
|
42
|
-
<!-- Lightning bolt — electric yellow -->
|
|
43
|
-
<path
|
|
44
|
-
d="M57 20 L42 53 L52 53 L43 80 L63 45 L53 45 Z"
|
|
45
|
-
fill="#ffe600"
|
|
46
|
-
filter="url(#glow)"
|
|
47
|
-
/>
|
|
48
|
-
</svg>
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<!-- Mini Coder Icon v3: Gradient Modern
|
|
2
|
-
Purple-to-blue gradient background, white brackets, gradient bolt.
|
|
3
|
-
Inspired by: "fast and performant", speed gradient feeling -->
|
|
4
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
|
|
5
|
-
<defs>
|
|
6
|
-
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
7
|
-
<stop offset="0%" stop-color="#6c3de8"/>
|
|
8
|
-
<stop offset="100%" stop-color="#1a73e8"/>
|
|
9
|
-
</linearGradient>
|
|
10
|
-
<linearGradient id="boltGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
11
|
-
<stop offset="0%" stop-color="#fff176"/>
|
|
12
|
-
<stop offset="100%" stop-color="#ff8c00"/>
|
|
13
|
-
</linearGradient>
|
|
14
|
-
</defs>
|
|
15
|
-
|
|
16
|
-
<!-- Background pill/squircle -->
|
|
17
|
-
<rect x="2" y="2" width="96" height="96" rx="22" fill="url(#bgGrad)"/>
|
|
18
|
-
|
|
19
|
-
<!-- Left bracket { — white -->
|
|
20
|
-
<path
|
|
21
|
-
d="M37 13 C27 13 24 18 24 26 L24 41 C24 47 20 49 16 51 C20 53 24 55 24 61 L24 75 C24 83 27 88 37 88"
|
|
22
|
-
fill="none"
|
|
23
|
-
stroke="rgba(255,255,255,0.92)"
|
|
24
|
-
stroke-width="5"
|
|
25
|
-
stroke-linecap="round"
|
|
26
|
-
stroke-linejoin="round"
|
|
27
|
-
/>
|
|
28
|
-
<!-- Right bracket } — white -->
|
|
29
|
-
<path
|
|
30
|
-
d="M63 13 C73 13 76 18 76 26 L76 41 C76 47 80 49 84 51 C80 53 76 55 76 61 L76 75 C76 83 73 88 63 88"
|
|
31
|
-
fill="none"
|
|
32
|
-
stroke="rgba(255,255,255,0.92)"
|
|
33
|
-
stroke-width="5"
|
|
34
|
-
stroke-linecap="round"
|
|
35
|
-
stroke-linejoin="round"
|
|
36
|
-
/>
|
|
37
|
-
<!-- Lightning bolt — warm gradient -->
|
|
38
|
-
<path
|
|
39
|
-
d="M57 19 L42 52 L52 52 L44 81 L63 45 L52 45 Z"
|
|
40
|
-
fill="url(#boltGrad)"
|
|
41
|
-
stroke="rgba(255,255,255,0.3)"
|
|
42
|
-
stroke-width="1"
|
|
43
|
-
stroke-linejoin="round"
|
|
44
|
-
/>
|
|
45
|
-
</svg>
|