opencode-usage-coach 0.13.3 → 0.13.4

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/cli.js CHANGED
@@ -350,7 +350,8 @@ var DEFAULT_HARNESS_CONFIG = {
350
350
  generator: "opencode/deepseek-v4-flash-free",
351
351
  grader: "opencode/mimo-v2.5-free",
352
352
  provider: "",
353
- lighterModel: ""
353
+ lighterModel: "",
354
+ maxSteps: 30
354
355
  };
355
356
  function resolveAgentSourceFile() {
356
357
  const scriptDir = dirname(fileURLToPath(import.meta.url));
package/dist/index.js CHANGED
@@ -434,6 +434,9 @@ async function searchContext(query, frameworks, keyDeps, timeoutMs) {
434
434
  var PLUGIN_NAME = "opencode-usage-coach";
435
435
  var TTL_MS = Number(process.env.UC_TTL_MS ?? 6e4);
436
436
  var DEFAULT_MAX_STEPS = Number(process.env.UC_MAX_STEPS ?? 30) || 30;
437
+ function resolveMaxSteps(cfg, explicit) {
438
+ return explicit ?? cfg.maxSteps ?? DEFAULT_MAX_STEPS;
439
+ }
437
440
  var WATCHDOG_POLL_MS = Math.max(1e3, Number(process.env.UC_WATCHDOG_POLL_MS ?? 3e3) || 3e3);
438
441
  var WALL_TIMEOUT_MS = Math.max(1, Number(process.env.UC_WALL_TIMEOUT_MIN ?? 30) || 30) * 60 * 1e3;
439
442
  var DEFAULT_MAX_QUESTIONS = Math.max(1, Math.round(Number(process.env.UC_MAX_QUESTIONS ?? 7)) || 7);
@@ -2340,7 +2343,7 @@ ${gate.summary}
2340
2343
  ` + prefix;
2341
2344
  }
2342
2345
  const genTaskId = findActiveTaskId(ctx.sessionID, "generating");
2343
- const maxSteps = args.max_steps ?? DEFAULT_MAX_STEPS;
2346
+ const maxSteps = resolveMaxSteps(cfg, args.max_steps);
2344
2347
  const out = await runModel(
2345
2348
  input.client,
2346
2349
  model,
@@ -2401,7 +2404,7 @@ ${gate.summary}
2401
2404
  const limit = decision === "THROTTLE" ? 2 : args.tasks.length;
2402
2405
  const rules = readRules();
2403
2406
  const priorNotes = readImplNotes(5);
2404
- const maxSteps = args.max_steps ?? DEFAULT_MAX_STEPS;
2407
+ const maxSteps = resolveMaxSteps(cfg, args.max_steps);
2405
2408
  const gate = checkScanGate(ctx.sessionID);
2406
2409
  const gatePrefix = gate.warning ? `${gate.warning}
2407
2410
 
@@ -2743,21 +2746,23 @@ If the task is already well-specified with no significant ambiguities, return {"
2743
2746
  }
2744
2747
  }),
2745
2748
  coach_config: tool({
2746
- description: 'View or update harness model configuration (generator, grader, lighterModel, provider). Call with no args to view current config. Pass any combination of generator/grader/lighterModel/provider to update. Example: coach_config({ generator: "anthropic/claude-sonnet-4-20250514", grader: "opencode/mimo-v2.5-free" })',
2749
+ description: 'View or update harness model configuration (generator, grader, lighterModel, provider, maxSteps). Call with no args to view current config. Pass any combination of fields to update. Example: coach_config({ generator: "anthropic/claude-sonnet-4-20250514", grader: "opencode/mimo-v2.5-free", maxSteps: 15 })',
2747
2750
  args: {
2748
2751
  generator: tool.schema.string().optional(),
2749
2752
  grader: tool.schema.string().optional(),
2750
2753
  lighterModel: tool.schema.string().optional(),
2751
- provider: tool.schema.string().optional()
2754
+ provider: tool.schema.string().optional(),
2755
+ maxSteps: tool.schema.number().optional().describe("Max steps per generate/grade sub-session (default 30). Lower = faster but may timeout on complex tasks.")
2752
2756
  },
2753
2757
  async execute(args, ctx) {
2754
2758
  const dir = ctx?.directory ?? input.directory;
2755
2759
  const current2 = readHarnessCfg(dir);
2756
- const hasUpdates = args.generator !== void 0 || args.grader !== void 0 || args.lighterModel !== void 0 || args.provider !== void 0;
2760
+ const hasUpdates = args.generator !== void 0 || args.grader !== void 0 || args.lighterModel !== void 0 || args.provider !== void 0 || args.maxSteps !== void 0;
2757
2761
  if (!hasUpdates) {
2758
2762
  const envOverrides = [];
2759
2763
  if (process.env.UC_PROVIDER) envOverrides.push(`UC_PROVIDER=${process.env.UC_PROVIDER}`);
2760
2764
  if (process.env.UC_LIGHTER_MODEL) envOverrides.push(`UC_LIGHTER_MODEL=${process.env.UC_LIGHTER_MODEL}`);
2765
+ if (process.env.UC_MAX_STEPS) envOverrides.push(`UC_MAX_STEPS=${process.env.UC_MAX_STEPS}`);
2761
2766
  return [
2762
2767
  `Harness Configuration`,
2763
2768
  `\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`,
@@ -2765,6 +2770,7 @@ If the task is already well-specified with no significant ambiguities, return {"
2765
2770
  ` grader: ${current2.grader ?? "(defaults to generator)"}`,
2766
2771
  ` lighterModel: ${current2.lighterModel ?? "(not set \u2014 no THROTTLE fallback)"}`,
2767
2772
  ` provider: ${current2.provider ?? "(auto-detected from model)"}`,
2773
+ ` maxSteps: ${current2.maxSteps ?? 30} (env: UC_MAX_STEPS)`,
2768
2774
  `\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`,
2769
2775
  envOverrides.length > 0 ? `
2770
2776
  Environment overrides (take precedence):
@@ -2772,7 +2778,7 @@ Environment overrides (take precedence):
2772
2778
  `
2773
2779
  Config file: ~/.config/opencode-usage-coach/harness.config.json`,
2774
2780
  `
2775
- To update, call: coach_config({ generator: "provider/model-id", ... })`
2781
+ To update, call: coach_config({ generator: "provider/model-id", maxSteps: 15, ... })`
2776
2782
  ].filter(Boolean).join("\n");
2777
2783
  }
2778
2784
  const updates = {};
@@ -2780,6 +2786,7 @@ To update, call: coach_config({ generator: "provider/model-id", ... })`
2780
2786
  if (args.grader !== void 0) updates.grader = args.grader.trim();
2781
2787
  if (args.lighterModel !== void 0) updates.lighterModel = args.lighterModel.trim();
2782
2788
  if (args.provider !== void 0) updates.provider = args.provider.trim();
2789
+ if (args.maxSteps !== void 0) updates.maxSteps = args.maxSteps;
2783
2790
  const writtenPath = writeHarnessCfg(updates);
2784
2791
  const updated = readHarnessCfg(dir);
2785
2792
  return [
@@ -2789,6 +2796,7 @@ To update, call: coach_config({ generator: "provider/model-id", ... })`
2789
2796
  ` grader: ${updated.grader ?? "(defaults to generator)"}`,
2790
2797
  ` lighterModel: ${updated.lighterModel ?? "(not set)"}`,
2791
2798
  ` provider: ${updated.provider ?? "(auto-detected)"}`,
2799
+ ` maxSteps: ${updated.maxSteps ?? 30}`,
2792
2800
  `\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`,
2793
2801
  `
2794
2802
  Saved to: ${writtenPath}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-usage-coach",
3
- "version": "0.13.3",
3
+ "version": "0.13.4",
4
4
  "description": "opencode closed-loop usage coach — quota SENSE -> coaching DECIDE -> loop ACT + TUI integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",