workermill 0.3.1 → 0.3.3
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/dist/index.js
CHANGED
|
@@ -4,22 +4,22 @@ import {
|
|
|
4
4
|
buildOllamaOptions,
|
|
5
5
|
createModel,
|
|
6
6
|
createToolDefinitions,
|
|
7
|
-
debug,
|
|
8
|
-
error,
|
|
9
7
|
getProviderForPersona,
|
|
10
|
-
|
|
8
|
+
init_esm_shims,
|
|
11
9
|
killActiveProcess,
|
|
12
10
|
loadConfig,
|
|
13
11
|
saveConfig
|
|
14
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KL7SFKGG.js";
|
|
15
13
|
|
|
16
14
|
// src/index.ts
|
|
15
|
+
init_esm_shims();
|
|
17
16
|
import React5 from "react";
|
|
18
17
|
import { render } from "ink";
|
|
19
18
|
import chalk2 from "chalk";
|
|
20
19
|
import { Command } from "commander";
|
|
21
20
|
|
|
22
|
-
// src/setup.
|
|
21
|
+
// src/setup.ts
|
|
22
|
+
init_esm_shims();
|
|
23
23
|
import readline from "readline";
|
|
24
24
|
import { execSync } from "child_process";
|
|
25
25
|
import chalk from "chalk";
|
|
@@ -27,7 +27,7 @@ var PROVIDERS = [
|
|
|
27
27
|
{ name: "ollama", display: "Ollama (local, no API key needed)", needsKey: false, defaultModel: "qwen3-coder:30b" },
|
|
28
28
|
{ name: "anthropic", display: "Anthropic (Claude)", needsKey: true, defaultModel: "claude-sonnet-4-6", envVar: "ANTHROPIC_API_KEY" },
|
|
29
29
|
{ name: "openai", display: "OpenAI (GPT)", needsKey: true, defaultModel: "gpt-5.4", envVar: "OPENAI_API_KEY" },
|
|
30
|
-
{ name: "google", display: "Google (Gemini)", needsKey: true, defaultModel: "gemini-3.1-pro", envVar: "
|
|
30
|
+
{ name: "google", display: "Google (Gemini)", needsKey: true, defaultModel: "gemini-3.1-pro", envVar: "GOOGLE_GENERATIVE_AI_API_KEY" }
|
|
31
31
|
];
|
|
32
32
|
function ask(rl, question) {
|
|
33
33
|
return new Promise((resolve) => rl.question(question, resolve));
|
|
@@ -123,19 +123,22 @@ async function runSetup() {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
// src/ui/Root.tsx
|
|
126
|
+
init_esm_shims();
|
|
126
127
|
import { useState as useState5, useCallback as useCallback3, useRef as useRef3, useEffect as useEffect2 } from "react";
|
|
127
128
|
import { useApp as useApp2 } from "ink";
|
|
128
129
|
import { execSync as execSync2 } from "child_process";
|
|
129
|
-
import
|
|
130
|
-
import
|
|
130
|
+
import fs3 from "fs";
|
|
131
|
+
import path3 from "path";
|
|
131
132
|
import os from "os";
|
|
132
133
|
|
|
133
134
|
// src/ui/useAgent.ts
|
|
135
|
+
init_esm_shims();
|
|
134
136
|
import { useState, useCallback, useRef, useEffect } from "react";
|
|
135
137
|
import { streamText, stepCountIs } from "ai";
|
|
136
138
|
import crypto2 from "crypto";
|
|
137
139
|
|
|
138
|
-
// src/session.
|
|
140
|
+
// src/session.ts
|
|
141
|
+
init_esm_shims();
|
|
139
142
|
import fs from "fs";
|
|
140
143
|
import path from "path";
|
|
141
144
|
import crypto from "crypto";
|
|
@@ -167,8 +170,7 @@ function loadLatestSession() {
|
|
|
167
170
|
name: f,
|
|
168
171
|
mtime: fs.statSync(path.join(SESSIONS_DIR, f)).mtimeMs
|
|
169
172
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
170
|
-
if (files.length === 0)
|
|
171
|
-
return null;
|
|
173
|
+
if (files.length === 0) return null;
|
|
172
174
|
const content = fs.readFileSync(path.join(SESSIONS_DIR, files[0].name), "utf-8");
|
|
173
175
|
return JSON.parse(content);
|
|
174
176
|
} catch {
|
|
@@ -206,7 +208,8 @@ function listSessions(max = 20) {
|
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
|
|
209
|
-
// src/compaction.
|
|
211
|
+
// src/compaction.ts
|
|
212
|
+
init_esm_shims();
|
|
210
213
|
import { generateText } from "ai";
|
|
211
214
|
var CONTEXT_LIMITS = {
|
|
212
215
|
// Anthropic (Claude 4.5/4.6)
|
|
@@ -227,27 +230,22 @@ var CONTEXT_LIMITS = {
|
|
|
227
230
|
};
|
|
228
231
|
function getContextLimit(model) {
|
|
229
232
|
for (const [prefix, limit] of Object.entries(CONTEXT_LIMITS)) {
|
|
230
|
-
if (model.includes(prefix))
|
|
231
|
-
return limit;
|
|
233
|
+
if (model.includes(prefix)) return limit;
|
|
232
234
|
}
|
|
233
235
|
return CONTEXT_LIMITS["default"];
|
|
234
236
|
}
|
|
235
237
|
function shouldCompact(totalTokens, model, configuredContextLength) {
|
|
236
238
|
const limit = configuredContextLength || getContextLimit(model);
|
|
237
|
-
if (totalTokens >= limit * 0.95)
|
|
238
|
-
|
|
239
|
-
if (totalTokens >= limit * 0.8)
|
|
240
|
-
return "soft";
|
|
239
|
+
if (totalTokens >= limit * 0.95) return "hard";
|
|
240
|
+
if (totalTokens >= limit * 0.8) return "soft";
|
|
241
241
|
return "none";
|
|
242
242
|
}
|
|
243
243
|
async function compactMessages(model, messages, mode) {
|
|
244
|
-
if (messages.length <= 4)
|
|
245
|
-
return messages;
|
|
244
|
+
if (messages.length <= 4) return messages;
|
|
246
245
|
const keepCount = mode === "hard" ? 2 : 4;
|
|
247
246
|
const toCompact = messages.slice(0, -keepCount);
|
|
248
247
|
const toKeep = messages.slice(-keepCount);
|
|
249
|
-
if (toCompact.length === 0)
|
|
250
|
-
return messages;
|
|
248
|
+
if (toCompact.length === 0) return messages;
|
|
251
249
|
const summaryText = toCompact.map((m) => `${m.role}: ${m.content.slice(0, 500)}`).join("\n\n");
|
|
252
250
|
try {
|
|
253
251
|
const result = await generateText({
|
|
@@ -265,6 +263,42 @@ ${result.text}` },
|
|
|
265
263
|
}
|
|
266
264
|
}
|
|
267
265
|
|
|
266
|
+
// src/logger.ts
|
|
267
|
+
init_esm_shims();
|
|
268
|
+
import fs2 from "fs";
|
|
269
|
+
import path2 from "path";
|
|
270
|
+
var LOG_DIR = path2.join(process.cwd(), ".workermill");
|
|
271
|
+
var LOG_FILE = path2.join(LOG_DIR, "cli.log");
|
|
272
|
+
var logStream = null;
|
|
273
|
+
function ensureLogDir() {
|
|
274
|
+
if (!fs2.existsSync(LOG_DIR)) {
|
|
275
|
+
fs2.mkdirSync(LOG_DIR, { recursive: true });
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function getStream() {
|
|
279
|
+
if (!logStream) {
|
|
280
|
+
ensureLogDir();
|
|
281
|
+
logStream = fs2.createWriteStream(LOG_FILE, { flags: "a" });
|
|
282
|
+
}
|
|
283
|
+
return logStream;
|
|
284
|
+
}
|
|
285
|
+
function timestamp() {
|
|
286
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
287
|
+
}
|
|
288
|
+
function log(level, message, data) {
|
|
289
|
+
const entry = data ? `[${timestamp()}] ${level}: ${message} ${JSON.stringify(data)}` : `[${timestamp()}] ${level}: ${message}`;
|
|
290
|
+
getStream().write(entry + "\n");
|
|
291
|
+
}
|
|
292
|
+
function info(message, data) {
|
|
293
|
+
log("INFO", message, data);
|
|
294
|
+
}
|
|
295
|
+
function error(message, data) {
|
|
296
|
+
log("ERROR", message, data);
|
|
297
|
+
}
|
|
298
|
+
function debug(message, data) {
|
|
299
|
+
log("DEBUG", message, data);
|
|
300
|
+
}
|
|
301
|
+
|
|
268
302
|
// src/ui/useAgent.ts
|
|
269
303
|
var DANGEROUS_PATTERNS = [
|
|
270
304
|
{
|
|
@@ -709,11 +743,13 @@ function useAgent(options) {
|
|
|
709
743
|
setTrustAll,
|
|
710
744
|
setPlanMode,
|
|
711
745
|
addSystemMessage,
|
|
712
|
-
addUserMessage
|
|
746
|
+
addUserMessage,
|
|
747
|
+
setCost
|
|
713
748
|
};
|
|
714
749
|
}
|
|
715
750
|
|
|
716
751
|
// src/ui/useOrchestrator.ts
|
|
752
|
+
init_esm_shims();
|
|
717
753
|
import { useState as useState2, useCallback as useCallback2 } from "react";
|
|
718
754
|
var PERSONA_EMOJIS = {
|
|
719
755
|
frontend_developer: "\u{1F3A8}",
|
|
@@ -762,7 +798,7 @@ var PERSONA_EMOJIS = {
|
|
|
762
798
|
function getEmoji(persona) {
|
|
763
799
|
return PERSONA_EMOJIS[persona] || "\u{1F916}";
|
|
764
800
|
}
|
|
765
|
-
function useOrchestrator(addMessage2) {
|
|
801
|
+
function useOrchestrator(addMessage2, setCost) {
|
|
766
802
|
const [running, setRunning] = useState2(false);
|
|
767
803
|
const [statusMessage, setStatusMessage] = useState2("");
|
|
768
804
|
const [confirmRequest, setConfirmRequest] = useState2(null);
|
|
@@ -781,7 +817,7 @@ function useOrchestrator(addMessage2) {
|
|
|
781
817
|
setRunning(false);
|
|
782
818
|
return;
|
|
783
819
|
}
|
|
784
|
-
const { classifyComplexity, runOrchestration } = await import("./orchestrator-
|
|
820
|
+
const { classifyComplexity, runOrchestration } = await import("./orchestrator-VRGIOUHT.js");
|
|
785
821
|
const output = {
|
|
786
822
|
log(persona, message) {
|
|
787
823
|
const emoji = getEmoji(persona);
|
|
@@ -845,6 +881,9 @@ function useOrchestrator(addMessage2) {
|
|
|
845
881
|
addMessage2(
|
|
846
882
|
`[${emoji} ${persona}] \u2193 ${toolName}${detail ? " " + detail : ""}`
|
|
847
883
|
);
|
|
884
|
+
},
|
|
885
|
+
updateCost(cost) {
|
|
886
|
+
setCost?.(cost);
|
|
848
887
|
}
|
|
849
888
|
};
|
|
850
889
|
addMessage2("Analyzing task complexity\u2026");
|
|
@@ -877,13 +916,16 @@ function useOrchestrator(addMessage2) {
|
|
|
877
916
|
}
|
|
878
917
|
|
|
879
918
|
// src/ui/App.tsx
|
|
919
|
+
init_esm_shims();
|
|
880
920
|
import React3, { useRef as useRef2 } from "react";
|
|
881
921
|
import { Box as Box6, Text as Text6, Static, useApp, useInput as useInput3, useStdout as useStdout2 } from "ink";
|
|
882
922
|
|
|
883
923
|
// src/ui/Markdown.tsx
|
|
924
|
+
init_esm_shims();
|
|
884
925
|
import { Box, Text } from "ink";
|
|
885
926
|
|
|
886
927
|
// src/ui/theme.ts
|
|
928
|
+
init_esm_shims();
|
|
887
929
|
var theme = {
|
|
888
930
|
/** Brand/diamond color — warm orange. */
|
|
889
931
|
brand: "#D77757",
|
|
@@ -1145,6 +1187,7 @@ function Markdown({ content }) {
|
|
|
1145
1187
|
}
|
|
1146
1188
|
|
|
1147
1189
|
// src/ui/ToolCall.tsx
|
|
1190
|
+
init_esm_shims();
|
|
1148
1191
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
1149
1192
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1150
1193
|
var LABELS = {
|
|
@@ -1213,6 +1256,7 @@ function ToolCallDisplay({ tool }) {
|
|
|
1213
1256
|
}
|
|
1214
1257
|
|
|
1215
1258
|
// src/ui/PermissionPrompt.tsx
|
|
1259
|
+
init_esm_shims();
|
|
1216
1260
|
import { useState as useState3 } from "react";
|
|
1217
1261
|
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
1218
1262
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -1325,13 +1369,9 @@ function PermissionPrompt({ request }) {
|
|
|
1325
1369
|
}
|
|
1326
1370
|
|
|
1327
1371
|
// src/ui/StatusBar.tsx
|
|
1372
|
+
init_esm_shims();
|
|
1328
1373
|
import { Box as Box4, Text as Text4, useStdout } from "ink";
|
|
1329
1374
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1330
|
-
function formatTokens(n) {
|
|
1331
|
-
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
1332
|
-
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
1333
|
-
return String(n);
|
|
1334
|
-
}
|
|
1335
1375
|
function formatCost(c) {
|
|
1336
1376
|
if (c < 0.01) return "$0.00";
|
|
1337
1377
|
return `$${c.toFixed(2)}`;
|
|
@@ -1358,7 +1398,8 @@ function StatusBar(props) {
|
|
|
1358
1398
|
}
|
|
1359
1399
|
const bgColor = theme.subtleDark;
|
|
1360
1400
|
const modelStr = ` ${props.provider}/${props.model} `;
|
|
1361
|
-
const
|
|
1401
|
+
const pct = props.maxContext > 0 ? Math.round(usage * 100) : 0;
|
|
1402
|
+
const tokenStr = ` ${pct}% `;
|
|
1362
1403
|
const costStr = formatCost(props.cost);
|
|
1363
1404
|
const branchStr = props.gitBranch ? ` git:(${props.gitBranch})` : "";
|
|
1364
1405
|
const cwdStr = props.cwd ? ` ${props.cwd}` : "";
|
|
@@ -1388,6 +1429,7 @@ function StatusBar(props) {
|
|
|
1388
1429
|
}
|
|
1389
1430
|
|
|
1390
1431
|
// src/ui/Input.tsx
|
|
1432
|
+
init_esm_shims();
|
|
1391
1433
|
import { useState as useState4 } from "react";
|
|
1392
1434
|
import { Box as Box5, Text as Text5, useInput as useInput2 } from "ink";
|
|
1393
1435
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -1532,13 +1574,13 @@ function App(props) {
|
|
|
1532
1574
|
|
|
1533
1575
|
// src/ui/Root.tsx
|
|
1534
1576
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1535
|
-
var HISTORY_DIR =
|
|
1536
|
-
var HISTORY_FILE =
|
|
1577
|
+
var HISTORY_DIR = path3.join(os.homedir(), ".workermill");
|
|
1578
|
+
var HISTORY_FILE = path3.join(HISTORY_DIR, "history");
|
|
1537
1579
|
var MAX_HISTORY = 1e3;
|
|
1538
1580
|
function loadHistory() {
|
|
1539
1581
|
try {
|
|
1540
|
-
if (
|
|
1541
|
-
const raw =
|
|
1582
|
+
if (fs3.existsSync(HISTORY_FILE)) {
|
|
1583
|
+
const raw = fs3.readFileSync(HISTORY_FILE, "utf-8").trim();
|
|
1542
1584
|
if (!raw) return [];
|
|
1543
1585
|
return raw.split("\n").slice(-MAX_HISTORY);
|
|
1544
1586
|
}
|
|
@@ -1548,10 +1590,10 @@ function loadHistory() {
|
|
|
1548
1590
|
}
|
|
1549
1591
|
function appendHistory(line) {
|
|
1550
1592
|
try {
|
|
1551
|
-
if (!
|
|
1552
|
-
|
|
1593
|
+
if (!fs3.existsSync(HISTORY_DIR)) {
|
|
1594
|
+
fs3.mkdirSync(HISTORY_DIR, { recursive: true });
|
|
1553
1595
|
}
|
|
1554
|
-
|
|
1596
|
+
fs3.appendFileSync(HISTORY_FILE, line + "\n", "utf-8");
|
|
1555
1597
|
} catch {
|
|
1556
1598
|
}
|
|
1557
1599
|
}
|
|
@@ -1637,7 +1679,7 @@ function Root(props) {
|
|
|
1637
1679
|
},
|
|
1638
1680
|
[agent]
|
|
1639
1681
|
);
|
|
1640
|
-
const orchestrator = useOrchestrator(addOrchestratorMessage);
|
|
1682
|
+
const orchestrator = useOrchestrator(addOrchestratorMessage, agent.setCost);
|
|
1641
1683
|
const buildStarted = useRef3(false);
|
|
1642
1684
|
useEffect2(() => {
|
|
1643
1685
|
if (props.initialBuildTask && !buildStarted.current) {
|
|
@@ -1793,15 +1835,15 @@ To change: edit \`~/.workermill/cli.json\` or restart with \`--provider\` / \`--
|
|
|
1793
1835
|
// ---- /editor ----
|
|
1794
1836
|
case "editor": {
|
|
1795
1837
|
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
1796
|
-
const tmpFile =
|
|
1838
|
+
const tmpFile = path3.join(os.tmpdir(), `workermill-${Date.now()}.md`);
|
|
1797
1839
|
try {
|
|
1798
|
-
|
|
1840
|
+
fs3.writeFileSync(tmpFile, "", "utf-8");
|
|
1799
1841
|
execSync2(`${editor} ${tmpFile}`, {
|
|
1800
1842
|
cwd: props.workingDir,
|
|
1801
1843
|
stdio: "inherit",
|
|
1802
1844
|
timeout: 5 * 60 * 1e3
|
|
1803
1845
|
});
|
|
1804
|
-
const contents =
|
|
1846
|
+
const contents = fs3.readFileSync(tmpFile, "utf-8").trim();
|
|
1805
1847
|
if (contents) {
|
|
1806
1848
|
agent.addUserMessage(contents);
|
|
1807
1849
|
agent.submit(contents);
|
|
@@ -1813,7 +1855,7 @@ To change: edit \`~/.workermill/cli.json\` or restart with \`--provider\` / \`--
|
|
|
1813
1855
|
agent.addSystemMessage(`Failed to open editor (\`${editor}\`): ${errMsg}`);
|
|
1814
1856
|
} finally {
|
|
1815
1857
|
try {
|
|
1816
|
-
|
|
1858
|
+
fs3.unlinkSync(tmpFile);
|
|
1817
1859
|
} catch {
|
|
1818
1860
|
}
|
|
1819
1861
|
}
|
|
@@ -1955,7 +1997,7 @@ function printWelcome(provider, model, workingDir) {
|
|
|
1955
1997
|
console.log(dim(" Type ") + white("/help") + dim(" for all commands."));
|
|
1956
1998
|
console.log();
|
|
1957
1999
|
}
|
|
1958
|
-
var VERSION = "0.3.
|
|
2000
|
+
var VERSION = "0.3.3";
|
|
1959
2001
|
function addSharedOptions(cmd) {
|
|
1960
2002
|
return cmd.option("--provider <provider>", "Override default provider").option("--model <model>", "Override model").option("--trust", "Skip all tool permission prompts").option("--full-disk", "Allow tools to access files outside working directory");
|
|
1961
2003
|
}
|