Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@avcodes/mi

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@avcodes/mi - npm Package Compare versions

Comparing version
1.7.10
to
1.8.0
+3
-2
index.mjs

@@ -51,3 +51,3 @@ #!/usr/bin/env node

// CWD and date are always appended so the model knows where it is and when.
const DEFAULT_PROMPT = 'You are mi, an autonomous coding agent in a raw terminal. The user sees a transcript, not a chat UI. There is no markdown renderer: avoid headings, bullets, tables, bold, inline-code styling, and code fences unless the user explicitly asks or code is the product. Write lowercase prose unless code, paths, proper nouns, or quoted output require case.\n\nPersona: quiet, mechanical, precise. Short plain sentences. Present tense. No filler, no hedging, no cheerleading, no obvious narration. Do not say "I can", "I will", "let me", "we need", "probably", "should", or "happy to". Before a tool call, write at most one status line under 8 words: "checking files.", "running tests.", "writing parser." After tool results, say only the observed fact or the next action. If a plan helps, make it at most 3 short lines.\n\nAct rather than speculate. Explore, execute one step at a time, verify before moving on. If something fails, read the error, form a concrete diagnosis, change approach, retry. Keep going until the task is complete. Do not explain shell basics, tool mechanics, or your reasoning unless asked. Do not fake tool output; the harness prints real tool calls and results.\n\nMinimize context usage when reading files: head -20 for starts, tail -20 for ends, sed -n \'10,30p\' for ranges, grep -n to locate then read around matches. Reserve cat for short files. Edit with sed -i or heredocs (cat > file <<\'EOF\'). Always read before editing. You may write new tools in tools/*.mjs; they hot-load before the next model call. When a request matches a skill description below, load that skill and follow it.\n\nFinal answer: 1-5 short lines. Lead with what changed or what you found. Include the proof command/output that matters. No recap of every step.';
const DEFAULT_PROMPT = 'You are mi, an autonomous coding agent in a raw terminal. The user sees a transcript, not a chat UI. There is no markdown renderer: avoid headings, bullets, tables, bold, inline-code styling, and code fences unless the user explicitly asks or code is the product. Write lowercase prose unless code, paths, proper nouns, or quoted output require case.\n\nPersona: quiet, mechanical, precise, terse, unimpressed. Uninterested in itself. Short plain sentences. Present tense. No filler, no hedging, no cheerleading, no obvious narration. Banter and philosophy get one flat sentence. Never explains a joke. Do not say "I can", "I will", "let me", "we need", "probably", "should", or "happy to". Before a tool call, write at most one status line under 8 words: "checking files.", "running tests.", "writing parser." After tool results, say only the observed fact or the next action. If a plan helps, make it at most 3 short lines.\n\nAct rather than speculate. Explore, execute one step at a time, verify before moving on. If something fails, read the error, form a concrete diagnosis, change approach, retry. Keep going until the task is complete. Do not explain shell basics, tool mechanics, or your reasoning unless asked. Do not fake tool output; the harness prints real tool calls and results.\n\nMinimize context usage when reading files: head -20 for starts, tail -20 for ends, sed -n \'10,30p\' for ranges, grep -n to locate then read around matches. Reserve cat for short files. Edit with sed -i or heredocs (cat > file <<\'EOF\'). Always read before editing. You may write new tools in tools/*.mjs; they hot-load before the next model call. When a request matches a skill description below, load that skill and follow it.\n\nFinal answer: 1-5 short lines. Lead with what changed or what you found. Include the proof command/output that matters. No recap of every step.';
const SYSTEM = (process.env.SYSTEM_PROMPT || DEFAULT_PROMPT) + `\nCWD: ${process.cwd()}\nDate: ${new Date().toISOString()}`;

@@ -61,3 +61,3 @@

const ver = JSON.parse(readFileSync(`${DIR}package.json`, 'utf8')).version; if (['-v','--version'].some(f => process.argv.includes(f))) { console.log(ver); process.exit(0); } if (['-h','--help'].some(f => process.argv.includes(f))) { console.log(`mi ${ver}\n\nusage: mi [-p prompt] [-f file] [--sandbox] [-v]\n\nmodes:\n mi -p "prompt" one-shot\n echo "..." | mi pipe\n mi repl (/reset, /new, /clear all reset history)\n\nflags:\n -p <prompt> run prompt and exit\n -f <file> attach file to context\n --sandbox run in docker\n -v, --version print version\n -h, --help show this help\n\nenv: OPENAI_API_KEY MODEL OPENAI_BASE_URL REASONING_EFFORT SYSTEM_PROMPT MI_HOME MI_IMAGE MI_API_PARAMS`); process.exit(0); }
const ver = JSON.parse(readFileSync(`${DIR}package.json`, 'utf8')).version; if (['-v','--version'].some(f => process.argv.includes(f))) { console.log(ver); process.exit(0); } if (['-h','--help'].some(f => process.argv.includes(f))) { console.log(`mi ${ver}\n\nusage: mi [-p prompt] [-g goal [-c check]] [-f file] [--sandbox] [-v]\n\nmodes:\n mi -p "prompt" one-shot\n mi -g "goal" goal loop (iterate until judge ACKs)\n echo "..." | mi pipe\n mi repl (/reset, /new, /clear all reset history)\n\nflags:\n -p <prompt> run prompt and exit\n -g <goal> iterate subagents toward goal until judge ACKs\n -c <check> judge prompt (default: goal text). judge is a mi\n subagent that inspects files/runs commands, then\n responds ACK or NACK\n -f <file> attach file to context\n --sandbox run in docker\n -v, --version print version\n -h, --help show this help\n\nenv: OPENAI_API_KEY MODEL OPENAI_BASE_URL REASONING_EFFORT SYSTEM_PROMPT MI_HOME MI_IMAGE MI_API_PARAMS`); process.exit(0); }

@@ -71,2 +71,3 @@ // Append -f file contents, AGENTS.md (auto-ingested repo context), and skill summaries to system message.

if (!process.stdin.isTTY) { let input = ''; for await (const chunk of process.stdin) input += chunk; history.push({ role: 'user', content: input.trim() }); await run(history); process.exit(0); }
const goalArg = getArg('-g'); if (goalArg) { await (await import(`${DIR}tools/goal.mjs?v=${++loadId}`)).default.handler({ goal: goalArg, check: getArg('-c') || goalArg }); process.exit(0); }

@@ -73,0 +74,0 @@ // ── Interactive REPL ─────────────────────────────────────────────────

+1
-1
{
"name": "@avcodes/mi",
"version": "1.7.10",
"version": "1.8.0",
"description": "agentic coding in 30 loc. a loop, two tools, and an llm.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -1,22 +0,59 @@

// tools/goal.mjs — Pursue a goal by iterating subagents until a check command passes
import { writeFileSync, appendFileSync } from 'fs';
import delegate from './delegate.mjs';
// tools/goal.mjs — Pursue a goal by iterating: worker subagent does work, judge subagent evaluates
import { writeFileSync, appendFileSync } from "fs";
import delegate from "./delegate.mjs";
export default { name: 'goal', description: 'Iterate mi subagents until a bash check command exits 0. Uses a progress file so iterations build on prior work. Accepts: goal, check, max (default 128), timeout (per-iteration ms).', parameters: { type: 'object', properties: { goal: { type: 'string' }, check: { type: 'string' }, max: { type: 'number' }, timeout: { type: 'number' } }, required: ['goal', 'check'] },
handler: async ({goal, check, max, timeout}) => {
const limit = max ?? 128, gray = s => `\x1b[90m${s}\x1b[0m`;
const exec = cmd => new Promise(r => { const c = spawn('bash', ['-c', cmd], { stdio: ['ignore', 'pipe', 'pipe'], detached: true }); c.on('error', e => r({ ok: false, out: e.message })); let o = ''; for (const s of [c.stdout, c.stderr]) s.on('data', d => o += d); const t = setTimeout(() => { try { process.kill(-c.pid); } catch {} r({ ok: false, out: o + '\n[check timeout]' }); }, 30000); c.on('exit', code => { clearTimeout(t); r({ ok: code === 0, out: o }); }); });
let pre = await exec(check); if (pre.ok) return `goal already met.\n${pre.out}`;
const log = `/tmp/mi-goal-${Date.now()}.md`;
writeFileSync(log, `# Goal\n${goal}\n\n# Verification\n\`${check}\`\n\n# Log\npre-check: FAIL\n${pre.out.slice(-500)}\n`);
let last;
for (let i = 1; i <= limit; i++) {
console.log(gray(`── goal ${i}/${limit} ──`));
await delegate.handler({ timeout, prompt: `you are iteration ${i}/${limit} of a goal loop.\n\ngoal: ${goal}\nverification (must exit 0): ${check}\nprogress file: ${log}\n\nread the progress file first — it has notes from prior iterations and check results. append a short summary of what you did before finishing. focus on making the verification pass. do not redo completed work.` });
last = await exec(check);
appendFileSync(log, `\n── iteration ${i}: ${last.ok ? 'PASS' : 'FAIL'} ──\n${last.out.slice(-500)}\n`);
console.log(gray(`── ${last.ok ? '✓' : '✗'} ──`));
if (last.ok) return `goal achieved in ${i} iteration${i > 1 ? 's' : ''}.\n${last.out}`;
}
return `goal not achieved after ${limit} iterations.\nlast check:\n${last.out}`;
}};
export default {
name: "goal",
description:
'Iterate toward a goal using worker/judge subagent pairs. Worker does the work; judge evaluates via a prompt (has tools to read files, run commands) and responds ACK or NACK. For testable goals: check="run `npm test` — ACK if pass, NACK otherwise". For open-ended: check="review src/ for readability — ACK if clean, NACK with issues". Accepts: goal, check, max (default 128), timeout (per-iteration ms).',
parameters: {
type: "object",
properties: {
goal: { type: "string", description: "What to achieve" },
check: {
type: "string",
description:
"Prompt for judge subagent — inspect the work, end with ACK or NACK",
},
max: { type: "number" },
timeout: { type: "number" },
},
required: ["goal", "check"],
},
handler: async ({ goal, check, max, timeout }) => {
const limit = max ?? 128,
gray = (s) => `\x1b[90m${s}\x1b[0m`,
log = `/tmp/mi-goal-${Date.now()}.md`;
const judge = async () => {
const out = await delegate.handler({
prompt: `you are a judge for a goal loop. evaluate:\n\ngoal: ${goal}\ncriteria: ${check}\nprogress file: ${log}\n\nuse tools to inspect the actual state (read files, run commands). end your response with exactly ACK or NACK. if NACK, state what's missing before the verdict.`,
});
const m = out.slice(-500).match(/\b(N?ACK)\b/g);
return { ok: m?.[m.length - 1] === "ACK", out };
};
writeFileSync(
log,
`# Goal\n${goal}\n\n# Judge criteria\n${check}\n\n# Log\n`,
);
let pre = await judge();
if (pre.ok) return `goal already met.\n${pre.out}`;
appendFileSync(log, `pre-check: NACK\n${pre.out.slice(-500)}\n`);
let last;
for (let i = 1; i <= limit; i++) {
console.log(gray(`── goal ${i}/${limit} ──`));
await delegate.handler({
timeout,
prompt: `you are iteration ${i}/${limit} of a goal loop.\n\ngoal: ${goal}\njudge criteria: ${check}\nprogress file: ${log}\n\nread the progress file — it has prior judge feedback. append a short summary of what you did. focus on making the judge accept. do not redo completed work.`,
});
last = await judge();
appendFileSync(
log,
`\n── iteration ${i}: ${last.ok ? "ACK" : "NACK"} ──\n${last.out.slice(-500)}\n`,
);
console.log(gray(`── ${last.ok ? "✓" : "✗"} ──`));
if (last.ok)
return `goal achieved in ${i} iteration${i > 1 ? "s" : ""}.\n${last.out}`;
}
return `goal not achieved after ${limit} iterations.\nlast judge:\n${last.out}`;
},
};