workermill 0.4.0 → 0.4.1

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.
@@ -3162,6 +3162,42 @@ var CostTracker = class {
3162
3162
  }
3163
3163
  };
3164
3164
 
3165
+ // src/logger.ts
3166
+ init_esm_shims();
3167
+ import fs9 from "fs";
3168
+ import path11 from "path";
3169
+ var LOG_DIR = path11.join(process.cwd(), ".workermill");
3170
+ var LOG_FILE = path11.join(LOG_DIR, "cli.log");
3171
+ var logStream = null;
3172
+ function ensureLogDir() {
3173
+ if (!fs9.existsSync(LOG_DIR)) {
3174
+ fs9.mkdirSync(LOG_DIR, { recursive: true });
3175
+ }
3176
+ }
3177
+ function getStream() {
3178
+ if (!logStream) {
3179
+ ensureLogDir();
3180
+ logStream = fs9.createWriteStream(LOG_FILE, { flags: "a" });
3181
+ }
3182
+ return logStream;
3183
+ }
3184
+ function timestamp() {
3185
+ return (/* @__PURE__ */ new Date()).toISOString();
3186
+ }
3187
+ function log(level, message, data) {
3188
+ const entry = data ? `[${timestamp()}] ${level}: ${message} ${JSON.stringify(data)}` : `[${timestamp()}] ${level}: ${message}`;
3189
+ getStream().write(entry + "\n");
3190
+ }
3191
+ function info(message, data) {
3192
+ log("INFO", message, data);
3193
+ }
3194
+ function error(message, data) {
3195
+ log("ERROR", message, data);
3196
+ }
3197
+ function debug(message, data) {
3198
+ log("DEBUG", message, data);
3199
+ }
3200
+
3165
3201
  export {
3166
3202
  __dirname,
3167
3203
  init_esm_shims,
@@ -3172,5 +3208,8 @@ export {
3172
3208
  createModel,
3173
3209
  killActiveProcess,
3174
3210
  createToolDefinitions,
3175
- CostTracker
3211
+ CostTracker,
3212
+ info,
3213
+ error,
3214
+ debug
3176
3215
  };
package/dist/index.js CHANGED
@@ -4,12 +4,15 @@ import {
4
4
  buildOllamaOptions,
5
5
  createModel,
6
6
  createToolDefinitions,
7
+ debug,
8
+ error,
7
9
  getProviderForPersona,
10
+ info,
8
11
  init_esm_shims,
9
12
  killActiveProcess,
10
13
  loadConfig,
11
14
  saveConfig
12
- } from "./chunk-KL7SFKGG.js";
15
+ } from "./chunk-77CAVW3Y.js";
13
16
 
14
17
  // src/index.ts
15
18
  init_esm_shims();
@@ -49,8 +52,8 @@ var PROVIDERS = [
49
52
  needsKey: true,
50
53
  envVar: "OPENAI_API_KEY",
51
54
  models: [
52
- { id: "gpt-5.2-codex", label: "GPT-5.2 Codex (built for code)" },
53
- { id: "gpt-5", label: "GPT-5 (general flagship)" }
55
+ { id: "gpt-5.4", label: "GPT-5.4 (latest flagship)" },
56
+ { id: "gpt-5.3-codex", label: "GPT-5.3 Codex (built for code)" }
54
57
  ]
55
58
  },
56
59
  {
@@ -338,8 +341,8 @@ init_esm_shims();
338
341
  import { useState as useState5, useCallback as useCallback3, useRef as useRef3, useEffect as useEffect2 } from "react";
339
342
  import { useApp as useApp2 } from "ink";
340
343
  import { execSync as execSync2 } from "child_process";
341
- import fs3 from "fs";
342
- import path3 from "path";
344
+ import fs2 from "fs";
345
+ import path2 from "path";
343
346
  import os from "os";
344
347
 
345
348
  // src/ui/useAgent.ts
@@ -474,42 +477,6 @@ ${result.text}` },
474
477
  }
475
478
  }
476
479
 
477
- // src/logger.ts
478
- init_esm_shims();
479
- import fs2 from "fs";
480
- import path2 from "path";
481
- var LOG_DIR = path2.join(process.cwd(), ".workermill");
482
- var LOG_FILE = path2.join(LOG_DIR, "cli.log");
483
- var logStream = null;
484
- function ensureLogDir() {
485
- if (!fs2.existsSync(LOG_DIR)) {
486
- fs2.mkdirSync(LOG_DIR, { recursive: true });
487
- }
488
- }
489
- function getStream() {
490
- if (!logStream) {
491
- ensureLogDir();
492
- logStream = fs2.createWriteStream(LOG_FILE, { flags: "a" });
493
- }
494
- return logStream;
495
- }
496
- function timestamp() {
497
- return (/* @__PURE__ */ new Date()).toISOString();
498
- }
499
- function log(level, message, data) {
500
- const entry = data ? `[${timestamp()}] ${level}: ${message} ${JSON.stringify(data)}` : `[${timestamp()}] ${level}: ${message}`;
501
- getStream().write(entry + "\n");
502
- }
503
- function info(message, data) {
504
- log("INFO", message, data);
505
- }
506
- function error(message, data) {
507
- log("ERROR", message, data);
508
- }
509
- function debug(message, data) {
510
- log("DEBUG", message, data);
511
- }
512
-
513
480
  // src/ui/useAgent.ts
514
481
  var DANGEROUS_PATTERNS = [
515
482
  {
@@ -1028,7 +995,7 @@ function useOrchestrator(addMessage2, setCost) {
1028
995
  setRunning(false);
1029
996
  return;
1030
997
  }
1031
- const { classifyComplexity, runOrchestration } = await import("./orchestrator-VRGIOUHT.js");
998
+ const { classifyComplexity, runOrchestration } = await import("./orchestrator-L5LDQYO7.js");
1032
999
  const output = {
1033
1000
  log(persona, message) {
1034
1001
  const emoji = getEmoji(persona);
@@ -1785,13 +1752,13 @@ function App(props) {
1785
1752
 
1786
1753
  // src/ui/Root.tsx
1787
1754
  import { jsx as jsx7 } from "react/jsx-runtime";
1788
- var HISTORY_DIR = path3.join(os.homedir(), ".workermill");
1789
- var HISTORY_FILE = path3.join(HISTORY_DIR, "history");
1755
+ var HISTORY_DIR = path2.join(os.homedir(), ".workermill");
1756
+ var HISTORY_FILE = path2.join(HISTORY_DIR, "history");
1790
1757
  var MAX_HISTORY = 1e3;
1791
1758
  function loadHistory() {
1792
1759
  try {
1793
- if (fs3.existsSync(HISTORY_FILE)) {
1794
- const raw = fs3.readFileSync(HISTORY_FILE, "utf-8").trim();
1760
+ if (fs2.existsSync(HISTORY_FILE)) {
1761
+ const raw = fs2.readFileSync(HISTORY_FILE, "utf-8").trim();
1795
1762
  if (!raw) return [];
1796
1763
  return raw.split("\n").slice(-MAX_HISTORY);
1797
1764
  }
@@ -1801,10 +1768,10 @@ function loadHistory() {
1801
1768
  }
1802
1769
  function appendHistory(line) {
1803
1770
  try {
1804
- if (!fs3.existsSync(HISTORY_DIR)) {
1805
- fs3.mkdirSync(HISTORY_DIR, { recursive: true });
1771
+ if (!fs2.existsSync(HISTORY_DIR)) {
1772
+ fs2.mkdirSync(HISTORY_DIR, { recursive: true });
1806
1773
  }
1807
- fs3.appendFileSync(HISTORY_FILE, line + "\n", "utf-8");
1774
+ fs2.appendFileSync(HISTORY_FILE, line + "\n", "utf-8");
1808
1775
  } catch {
1809
1776
  }
1810
1777
  }
@@ -2046,15 +2013,15 @@ To change: edit \`~/.workermill/cli.json\` or restart with \`--provider\` / \`--
2046
2013
  // ---- /editor ----
2047
2014
  case "editor": {
2048
2015
  const editor = process.env.EDITOR || process.env.VISUAL || "vi";
2049
- const tmpFile = path3.join(os.tmpdir(), `workermill-${Date.now()}.md`);
2016
+ const tmpFile = path2.join(os.tmpdir(), `workermill-${Date.now()}.md`);
2050
2017
  try {
2051
- fs3.writeFileSync(tmpFile, "", "utf-8");
2018
+ fs2.writeFileSync(tmpFile, "", "utf-8");
2052
2019
  execSync2(`${editor} ${tmpFile}`, {
2053
2020
  cwd: props.workingDir,
2054
2021
  stdio: "inherit",
2055
2022
  timeout: 5 * 60 * 1e3
2056
2023
  });
2057
- const contents = fs3.readFileSync(tmpFile, "utf-8").trim();
2024
+ const contents = fs2.readFileSync(tmpFile, "utf-8").trim();
2058
2025
  if (contents) {
2059
2026
  agent.addUserMessage(contents);
2060
2027
  agent.submit(contents);
@@ -2066,7 +2033,7 @@ To change: edit \`~/.workermill/cli.json\` or restart with \`--provider\` / \`--
2066
2033
  agent.addSystemMessage(`Failed to open editor (\`${editor}\`): ${errMsg}`);
2067
2034
  } finally {
2068
2035
  try {
2069
- fs3.unlinkSync(tmpFile);
2036
+ fs2.unlinkSync(tmpFile);
2070
2037
  } catch {
2071
2038
  }
2072
2039
  }
@@ -2208,7 +2175,7 @@ function printWelcome(provider, model, workingDir) {
2208
2175
  console.log(dim(" Type ") + white("/help") + dim(" for all commands."));
2209
2176
  console.log();
2210
2177
  }
2211
- var VERSION = "0.4.0";
2178
+ var VERSION = "0.4.1";
2212
2179
  function addSharedOptions(cmd) {
2213
2180
  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");
2214
2181
  }
@@ -4,9 +4,11 @@ import {
4
4
  buildOllamaOptions,
5
5
  createModel,
6
6
  createToolDefinitions,
7
+ error,
7
8
  getProviderForPersona,
9
+ info,
8
10
  init_esm_shims
9
- } from "./chunk-KL7SFKGG.js";
11
+ } from "./chunk-77CAVW3Y.js";
10
12
 
11
13
  // src/orchestrator.ts
12
14
  init_esm_shims();
@@ -153,9 +155,9 @@ function buildReasoningOptions(provider, modelName) {
153
155
  return {};
154
156
  }
155
157
  }
156
- function isTransientError(error) {
157
- if (!error || typeof error !== "object") return false;
158
- const msg = error instanceof Error ? error.message : String(error);
158
+ function isTransientError(error2) {
159
+ if (!error2 || typeof error2 !== "object") return false;
160
+ const msg = error2 instanceof Error ? error2.message : String(error2);
159
161
  if (/status code (502|503|504)|socket hang up|ECONNRESET|ETIMEDOUT|network error|ECONNREFUSED/i.test(msg)) {
160
162
  return true;
161
163
  }
@@ -219,6 +221,7 @@ function formatToolCallDisplay(toolName, toolInput) {
219
221
  return msg;
220
222
  }
221
223
  async function classifyComplexity(config, userInput, output) {
224
+ info("Classifying complexity", { input: userInput.slice(0, 200) });
222
225
  const resolvedInput = resolveTaskInput(userInput, process.cwd());
223
226
  const { provider, model: modelName, apiKey, host, contextLength } = getProviderForPersona(config);
224
227
  if (apiKey) {
@@ -635,6 +638,7 @@ ${plannerStories.map((s) => `- ${s.id}: ${s.title} (${s.persona}) \u2014 ${s.des
635
638
  output.coordinatorLog(`Task claimed by orchestrator`);
636
639
  output.log(story.persona, `Starting ${story.title}`);
637
640
  output.log(story.persona, `Executing story with AIClient (model: ${modelName})...`);
641
+ info(`Story ${i + 1}/${sorted.length} started`, { persona: story.persona, title: story.title, provider, model: modelName });
638
642
  output.status("");
639
643
  const model = createModel(provider, modelName, host, contextLength);
640
644
  const allTools = createToolDefinitions(workingDir, model, sandboxed);
@@ -765,13 +769,16 @@ ${revisionFeedback}` : ""}`;
765
769
  costTracker.addUsage(persona.name, provider, modelName, inTokens, outTokens);
766
770
  output.updateCost?.(costTracker.getTotalCost());
767
771
  output.log(story.persona, `${story.title} \u2014 completed! (${i + 1}/${sorted.length})`);
772
+ info(`Story ${i + 1} completed`, { persona: story.persona, inputTokens: inTokens, outputTokens: outTokens });
768
773
  output.log("system", "");
769
774
  break;
770
775
  } catch (err) {
771
776
  output.statusDone();
772
777
  const errMsg = err instanceof Error ? err.message : String(err);
778
+ error(`Story ${i + 1} error`, { persona: story.persona, error: errMsg, revision });
773
779
  if (isTransientError(err) && revision < 2) {
774
780
  output.log(story.persona, `Transient error: ${errMsg} \u2014 retrying...`);
781
+ info(`Story ${i + 1} retrying (transient)`, { revision });
775
782
  continue;
776
783
  }
777
784
  output.error(`Story ${i + 1} failed: ${errMsg}`);
@@ -812,8 +819,10 @@ ${revisionFeedback}` : ""}`;
812
819
  }
813
820
  }
814
821
  let previousReviewFeedback = "";
822
+ info("Starting review loop", { maxRevisions, approvalThreshold, provider: revProvider, model: revModel });
815
823
  for (let reviewRound = 0; reviewRound <= maxRevisions; reviewRound++) {
816
824
  const isRevision = reviewRound > 0;
825
+ info(`Review round ${reviewRound}`, { isRevision, maxRevisions });
817
826
  output.coordinatorLog(isRevision ? `Starting Tech Lead review (revision ${reviewRound}/${maxRevisions})...` : "Starting Tech Lead review...");
818
827
  output.log("tech_lead", `Starting agent execution (model: ${revModel})`);
819
828
  output.status(isRevision ? "Reviewer -- Re-checking after revisions" : "Reviewer -- Checking code quality");
@@ -907,6 +916,7 @@ AFFECTED_REASONS: {"2": "Missing error handling in auth controller", "3": "Front
907
916
  output.statusDone();
908
917
  const score = extractScore(reviewText);
909
918
  const approved = score >= approvalThreshold;
919
+ info(`Review round ${reviewRound} result`, { score, approved, threshold: approvalThreshold, reviewTextLength: reviewText.length });
910
920
  output.log("tech_lead", `::code_quality_score::${score}`);
911
921
  output.log("tech_lead", `::review_decision::${approved ? "approved" : "needs_revision"}`);
912
922
  output.coordinatorLog(approved ? `Review approved (score: ${score}/100)` : `Review needs revision (score: ${score}/100)`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workermill",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "AI coding agent with multi-expert orchestration. Works with any LLM provider.",
5
5
  "type": "module",
6
6
  "bin": {