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.1
to
1.7.2
+12
-5
index.mjs

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

// DIR = package root (for tool/skill discovery); MI_DIR/MI_PATH = env vars so tools can locate project assets.
Object.assign(global, { spawn, readFileSync, existsSync, readdirSync, homedir }); const DIR = new URL('.', import.meta.url).pathname; Object.assign(process.env, { MI_DIR: DIR, MI_PATH: new URL(import.meta.url).pathname }); const rc = `${homedir()}/.mirc`; if (existsSync(rc)) Object.entries(JSON.parse(readFileSync(rc, 'utf8'))).forEach(([k, v]) => process.env[k] ||= v); if (!process.env.OPENAI_API_KEY && !process.argv.includes('-h') && !process.argv.includes('--help')) { console.error('OPENAI_API_KEY required'); process.exit(1); }
Object.assign(global, { spawn, readFileSync, existsSync, readdirSync, homedir }); const DIR = new URL('.', import.meta.url).pathname; Object.assign(process.env, { MI_DIR: DIR, MI_PATH: new URL(import.meta.url).pathname });
const MI_HOME = process.env.MI_HOME || `${homedir()}/.mi`, rc = `${MI_HOME}/config.json`; if (existsSync(rc)) Object.entries(JSON.parse(readFileSync(rc, 'utf8'))).forEach(([k, v]) => process.env[k] ||= v);
if (!process.env.OPENAI_API_KEY && !process.argv.includes('-h') && !process.argv.includes('--help')) { console.error('OPENAI_API_KEY required'); process.exit(1); }

@@ -16,3 +18,5 @@ // ── Tool discovery ───────────────────────────────────────────────────

const gray = s => `\x1b[90m${s}\x1b[0m`, red = s => `\x1b[31m${s}\x1b[0m`, orange = s => `\x1b[38;5;208m${s}\x1b[0m`;
let tools, toolSchemas, listSkills, loadId = 0; async function loadTools() { const toolMods = await Promise.all(readdirSync(`${DIR}tools`).filter(file => file.endsWith('.mjs')).map(file => import(`${DIR}tools/${file}?v=${++loadId}`))), defs = toolMods.map(mod => mod.default); tools = Object.fromEntries(defs.map(def => [def.name, def.handler])); toolSchemas = defs.map(def => ({ type: 'function', function: { name: def.name, description: def.description, parameters: def.parameters } })); listSkills = toolMods.find(mod => mod.listSkills)?.listSkills; } await loadTools();
let tools, toolSchemas, listSkills, loadId = 0;
async function loadTools() { const toolMods = await Promise.all(readdirSync(`${DIR}tools`).filter(file => file.endsWith('.mjs')).map(file => import(`${DIR}tools/${file}?v=${++loadId}`))), defs = toolMods.map(mod => mod.default); tools = Object.fromEntries(defs.map(def => [def.name, def.handler])); toolSchemas = defs.map(def => ({ type: 'function', function: { name: def.name, description: def.description, parameters: def.parameters } })); listSkills = toolMods.find(mod => mod.listSkills)?.listSkills; }
await loadTools();

@@ -55,3 +59,4 @@ // ── Agent loop: chat → stream → execute tools → repeat ──────────────

// Uses short-circuit: indexOf returns -1 when missing, so `i >= 0 && argv[i + 1]` is false without a flag.
const history = [{ role: 'system', content: SYSTEM }], getArg = key => { const i = process.argv.indexOf(key); return i >= 0 && process.argv[i + 1]; };
const history = [{ role: 'system', content: SYSTEM }];
const getArg = key => { const i = process.argv.indexOf(key); return i >= 0 && process.argv[i + 1]; };

@@ -61,6 +66,8 @@ if (process.argv.includes('-h') || process.argv.includes('--help')) { console.log('usage: mi [-p prompt] [-f file] [-h]\n pipe: echo "..." | mi repl: /reset clears history\nenv: OPENAI_API_KEY, MODEL, OPENAI_BASE_URL, REASONING_EFFORT, SYSTEM_PROMPT\nbash tool args: timeout=<ms> kills after delay · bg=truthy detaches and returns pid+log'); process.exit(0); }

// Append -f file contents, AGENTS.md (auto-ingested repo context), and skill summaries to system message.
const sysMsg = history[0], fileArg = getArg('-f'); if (fileArg) sysMsg.content += `\n\nFile (${fileArg}):\n${readFileSync(fileArg, 'utf8')}`; if (existsSync('AGENTS.md')) sysMsg.content += `\n${readFileSync('AGENTS.md', 'utf8')}`; const skills = listSkills(); if (skills.length) sysMsg.content += `\n\nSkill descriptions:\n${skills.join('\n')}`;
const sysMsg = history[0], fileArg = getArg('-f'); if (fileArg) sysMsg.content += `\n\nFile (${fileArg}):\n${readFileSync(fileArg, 'utf8')}`;
if (existsSync('AGENTS.md')) sysMsg.content += `\n${readFileSync('AGENTS.md', 'utf8')}`; const skills = listSkills(); if (skills.length) sysMsg.content += `\n\nSkill descriptions:\n${skills.join('\n')}`;
// ── One-shot modes: -p flag and stdin pipe ───────────────────────────
const prompt = getArg('-p'); if (prompt) { history.push({ role: 'user', content: prompt }); await run(history); process.exit(0); } if (!process.stdin.isTTY) { let input = ''; for await (const chunk of process.stdin) input += chunk; /* Buffer auto-coerces to string via += */ history.push({ role: 'user', content: input.trim() }); await run(history); process.exit(0); }
const prompt = getArg('-p'); if (prompt) { history.push({ role: 'user', content: prompt }); await run(history); process.exit(0); }
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); }

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

{
"name": "@avcodes/mi",
"version": "1.7.1",
"version": "1.7.2",
"description": "agentic coding in 30 loc. a loop, two tools, and an llm.",

@@ -25,3 +25,3 @@ "type": "module",

"test": "node --test tests/test.js",
"lines": "node scripts/count-lines.mjs index.mjs tools/*.mjs"
"lines": "node scripts/count-lines.mjs index.mjs"
},

@@ -28,0 +28,0 @@ "license": "MIT",

@@ -21,3 +21,3 @@ [![mi video](https://img.youtube.com/vi/JdMBn7FXilg/maxresdefault.jpg)](https://www.youtube.com/watch?v=JdMBn7FXilg)

- graceful `SIGINT` handling for bash child processes
- optional `~/.mirc` JSON config file (env vars always override)
- optional `~/.mi/config.json` config file (env vars always override)

@@ -56,3 +56,3 @@ ## install

`~/.mirc` is an optional JSON config file. keys become env var defaults — your shell env always wins.
`~/.mi/config.json` is an optional JSON config file. keys become env var defaults — your shell env always wins.

@@ -67,3 +67,3 @@ ```json

any env var that mi reads can be set here: `OPENAI_API_KEY`, `MODEL`, `OPENAI_BASE_URL`, `REASONING_EFFORT`, `SYSTEM_PROMPT`.
any env var that mi reads can be set here: `OPENAI_API_KEY`, `MODEL`, `OPENAI_BASE_URL`, `REASONING_EFFORT`, `SYSTEM_PROMPT`. the config directory can be overridden with `MI_HOME`.

@@ -79,2 +79,3 @@ ## env

| `SYSTEM_PROMPT` | built-in agent prompt | override the system prompt entirely |
| `MI_HOME` | `~/.mi` | config directory (reads `config.json`) |

@@ -81,0 +82,0 @@ ## deep dive