opencode-usage-coach 0.13.3 → 0.13.5

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
@@ -16,7 +16,7 @@ function initDomain(stateDir) {
16
16
  if (basename(dirname(stateDir)) === "projects") {
17
17
  SHARED_DIR = join(dirname(dirname(stateDir)), "shared");
18
18
  } else {
19
- SHARED_DIR = join(stateDir, "_shared");
19
+ SHARED_DIR = join(stateDir, "shared");
20
20
  }
21
21
  }
22
22
  var nodesFile = () => join(BASE_DIR, "nodes.ndjson");
@@ -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);
@@ -2304,6 +2307,9 @@ ${rules}
2304
2307
  ---
2305
2308
 
2306
2309
  ` + prefix;
2310
+ log(`generate domain HIT: ${nodes.length} nodes, ${edges.length} edges (kw=[${keywords.join(",")}])`);
2311
+ } else {
2312
+ log(`generate domain MISS: 0 nodes (kw=[${keywords.join(",")}])`);
2307
2313
  }
2308
2314
  }
2309
2315
  } catch (e) {
@@ -2340,7 +2346,7 @@ ${gate.summary}
2340
2346
  ` + prefix;
2341
2347
  }
2342
2348
  const genTaskId = findActiveTaskId(ctx.sessionID, "generating");
2343
- const maxSteps = args.max_steps ?? DEFAULT_MAX_STEPS;
2349
+ const maxSteps = resolveMaxSteps(cfg, args.max_steps);
2344
2350
  const out = await runModel(
2345
2351
  input.client,
2346
2352
  model,
@@ -2401,7 +2407,7 @@ ${gate.summary}
2401
2407
  const limit = decision === "THROTTLE" ? 2 : args.tasks.length;
2402
2408
  const rules = readRules();
2403
2409
  const priorNotes = readImplNotes(5);
2404
- const maxSteps = args.max_steps ?? DEFAULT_MAX_STEPS;
2410
+ const maxSteps = resolveMaxSteps(cfg, args.max_steps);
2405
2411
  const gate = checkScanGate(ctx.sessionID);
2406
2412
  const gatePrefix = gate.warning ? `${gate.warning}
2407
2413
 
@@ -2743,21 +2749,23 @@ If the task is already well-specified with no significant ambiguities, return {"
2743
2749
  }
2744
2750
  }),
2745
2751
  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" })',
2752
+ 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
2753
  args: {
2748
2754
  generator: tool.schema.string().optional(),
2749
2755
  grader: tool.schema.string().optional(),
2750
2756
  lighterModel: tool.schema.string().optional(),
2751
- provider: tool.schema.string().optional()
2757
+ provider: tool.schema.string().optional(),
2758
+ maxSteps: tool.schema.number().optional().describe("Max steps per generate/grade sub-session (default 30). Lower = faster but may timeout on complex tasks.")
2752
2759
  },
2753
2760
  async execute(args, ctx) {
2754
2761
  const dir = ctx?.directory ?? input.directory;
2755
2762
  const current2 = readHarnessCfg(dir);
2756
- const hasUpdates = args.generator !== void 0 || args.grader !== void 0 || args.lighterModel !== void 0 || args.provider !== void 0;
2763
+ const hasUpdates = args.generator !== void 0 || args.grader !== void 0 || args.lighterModel !== void 0 || args.provider !== void 0 || args.maxSteps !== void 0;
2757
2764
  if (!hasUpdates) {
2758
2765
  const envOverrides = [];
2759
2766
  if (process.env.UC_PROVIDER) envOverrides.push(`UC_PROVIDER=${process.env.UC_PROVIDER}`);
2760
2767
  if (process.env.UC_LIGHTER_MODEL) envOverrides.push(`UC_LIGHTER_MODEL=${process.env.UC_LIGHTER_MODEL}`);
2768
+ if (process.env.UC_MAX_STEPS) envOverrides.push(`UC_MAX_STEPS=${process.env.UC_MAX_STEPS}`);
2761
2769
  return [
2762
2770
  `Harness Configuration`,
2763
2771
  `\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 +2773,7 @@ If the task is already well-specified with no significant ambiguities, return {"
2765
2773
  ` grader: ${current2.grader ?? "(defaults to generator)"}`,
2766
2774
  ` lighterModel: ${current2.lighterModel ?? "(not set \u2014 no THROTTLE fallback)"}`,
2767
2775
  ` provider: ${current2.provider ?? "(auto-detected from model)"}`,
2776
+ ` maxSteps: ${current2.maxSteps ?? 30} (env: UC_MAX_STEPS)`,
2768
2777
  `\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
2778
  envOverrides.length > 0 ? `
2770
2779
  Environment overrides (take precedence):
@@ -2772,7 +2781,7 @@ Environment overrides (take precedence):
2772
2781
  `
2773
2782
  Config file: ~/.config/opencode-usage-coach/harness.config.json`,
2774
2783
  `
2775
- To update, call: coach_config({ generator: "provider/model-id", ... })`
2784
+ To update, call: coach_config({ generator: "provider/model-id", maxSteps: 15, ... })`
2776
2785
  ].filter(Boolean).join("\n");
2777
2786
  }
2778
2787
  const updates = {};
@@ -2780,6 +2789,7 @@ To update, call: coach_config({ generator: "provider/model-id", ... })`
2780
2789
  if (args.grader !== void 0) updates.grader = args.grader.trim();
2781
2790
  if (args.lighterModel !== void 0) updates.lighterModel = args.lighterModel.trim();
2782
2791
  if (args.provider !== void 0) updates.provider = args.provider.trim();
2792
+ if (args.maxSteps !== void 0) updates.maxSteps = args.maxSteps;
2783
2793
  const writtenPath = writeHarnessCfg(updates);
2784
2794
  const updated = readHarnessCfg(dir);
2785
2795
  return [
@@ -2789,6 +2799,7 @@ To update, call: coach_config({ generator: "provider/model-id", ... })`
2789
2799
  ` grader: ${updated.grader ?? "(defaults to generator)"}`,
2790
2800
  ` lighterModel: ${updated.lighterModel ?? "(not set)"}`,
2791
2801
  ` provider: ${updated.provider ?? "(auto-detected)"}`,
2802
+ ` maxSteps: ${updated.maxSteps ?? 30}`,
2792
2803
  `\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
2804
  `
2794
2805
  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.5",
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",