opencode-usage-coach 0.2.5 → 0.3.0
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 +34 -30
- package/dist/tui.js +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ function setStateDir(dir) {
|
|
|
25
25
|
}
|
|
26
26
|
var NOOP_HOOKS = {};
|
|
27
27
|
function log(msg) {
|
|
28
|
-
|
|
28
|
+
try {
|
|
29
29
|
appendFileSync(LOG_FILE, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
30
30
|
`);
|
|
31
31
|
} catch {
|
|
@@ -80,50 +80,53 @@ async function runModel(client, model, prompt, directory) {
|
|
|
80
80
|
const providerID = slash >= 0 ? model.slice(0, slash) : model;
|
|
81
81
|
const modelID = slash >= 0 ? model.slice(slash + 1) : "";
|
|
82
82
|
const s = await client.session.create({ body: { title: "uc-harness-sub" }, query: { directory } });
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
83
|
+
log(`runModel(${model}): create resp = ${JSON.stringify(s?.data ?? s).slice(0, 500)}`);
|
|
84
|
+
const id = s?.data?.info?.id ?? s?.data?.id ?? s?.id;
|
|
85
|
+
if (!id) return `ERROR: session.create returned no id (response: ${JSON.stringify(s?.data ?? s).slice(0, 200)})`;
|
|
88
86
|
log(`runModel(${model}): session ${id} created, prompt ${prompt.length} chars`);
|
|
89
87
|
await client.session.prompt({
|
|
90
88
|
path: { id },
|
|
91
89
|
body: { model: { providerID, modelID }, parts: [{ type: "text", text: prompt }] }
|
|
92
90
|
});
|
|
93
|
-
|
|
91
|
+
log(`runModel(${model}): prompt sent to ${id}`);
|
|
92
|
+
let lastMsgCount = -1;
|
|
94
93
|
let timedOut = false;
|
|
94
|
+
let text = "";
|
|
95
95
|
for (let i = 0; i < 600; i++) {
|
|
96
96
|
await sleep(1e3);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
97
|
+
try {
|
|
98
|
+
const msgs = await client.session.messages({ path: { id } });
|
|
99
|
+
const all = msgs?.data ?? msgs ?? [];
|
|
100
|
+
if (all.length !== lastMsgCount) {
|
|
101
|
+
log(`runModel(${model}): poll[${i}] msgs=${all.length}`);
|
|
102
|
+
lastMsgCount = all.length;
|
|
103
|
+
}
|
|
104
|
+
const lastAssistant = all.filter((m) => (m?.info?.role ?? m?.role) === "assistant").pop();
|
|
105
|
+
const parts = lastAssistant?.parts ?? lastAssistant?.info?.parts ?? [];
|
|
106
|
+
const t = parts.filter((p) => p?.type === "text").map((p) => p?.text ?? "").join("").trim();
|
|
107
|
+
if (t) {
|
|
108
|
+
text = t;
|
|
109
|
+
log(`runModel(${model}): got assistant text at poll[${i}] (${t.length} chars)`);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
} catch (e) {
|
|
113
|
+
log(`runModel(${model}): poll[${i}] messages err: ${String(e).slice(0, 120)}`);
|
|
107
114
|
}
|
|
108
115
|
if (i === 599) timedOut = true;
|
|
109
116
|
}
|
|
110
117
|
const elapsed = Math.round((Date.now() - t0) / 1e3);
|
|
111
|
-
const msgs = await client.session.messages({ path: { id } });
|
|
112
|
-
const all = msgs?.data ?? [];
|
|
113
|
-
const lastAssistant = all.filter((m) => m?.info?.role === "assistant").pop();
|
|
114
|
-
const parts = lastAssistant?.parts ?? [];
|
|
115
|
-
const text = parts.filter((p) => p?.type === "text").map((p) => p?.text ?? "").join("");
|
|
116
118
|
try {
|
|
117
119
|
await client.session.remove?.({ path: { id } });
|
|
118
120
|
} catch {
|
|
119
121
|
}
|
|
120
122
|
log(`runModel(${model}): done ${elapsed}s, ${text.length} chars${timedOut ? " [TIMEOUT]" : ""}`);
|
|
121
|
-
if (timedOut) return `[runModel TIMEOUT after ${elapsed}s \u2014
|
|
122
|
-
${text
|
|
123
|
-
return text
|
|
123
|
+
if (timedOut) return `[runModel TIMEOUT after ${elapsed}s \u2014 no assistant text appeared]
|
|
124
|
+
${text}`;
|
|
125
|
+
return text || `ERROR: no assistant text after ${elapsed}s (${lastMsgCount} messages seen)`;
|
|
124
126
|
} catch (e) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
const elapsed = Math.round((Date.now() - t0) / 1e3);
|
|
128
|
+
log(`runModel err (${model}, ${elapsed}s): ${String(e)}`);
|
|
129
|
+
return `ERROR: runModel exception after ${elapsed}s: ${String(e)}`;
|
|
127
130
|
}
|
|
128
131
|
}
|
|
129
132
|
var num = (e, d) => {
|
|
@@ -380,7 +383,7 @@ async function UsageCoachPlugin(input) {
|
|
|
380
383
|
const cfg = readHarnessCfg(ctx.directory);
|
|
381
384
|
if (!cfg.generator) return 'ERROR: no generator model configured. Set "generator" in harness.config.json (see harness.config.example.json).';
|
|
382
385
|
const out = await runModel(input.client, cfg.generator, args.prompt, ctx.directory);
|
|
383
|
-
return out
|
|
386
|
+
return out;
|
|
384
387
|
}
|
|
385
388
|
}),
|
|
386
389
|
generate_batch: tool({
|
|
@@ -391,7 +394,7 @@ async function UsageCoachPlugin(input) {
|
|
|
391
394
|
if (!cfg.generator) return 'ERROR: no generator model configured. Set "generator" in harness.config.json (see harness.config.example.json).';
|
|
392
395
|
const results = await Promise.all(args.tasks.map(async (t) => {
|
|
393
396
|
const out = await runModel(input.client, cfg.generator, t.prompt, ctx.directory);
|
|
394
|
-
return `[task ${t.id}] ${out
|
|
397
|
+
return `[task ${t.id}] ${out}`;
|
|
395
398
|
}));
|
|
396
399
|
return results.join("\n\n");
|
|
397
400
|
}
|
|
@@ -404,7 +407,8 @@ async function UsageCoachPlugin(input) {
|
|
|
404
407
|
const model = cfg.grader ?? cfg.generator;
|
|
405
408
|
if (!model) return 'FAIL\n(ERROR: no grader/generator model configured. Set "grader" and "generator" in harness.config.json.)';
|
|
406
409
|
const out = await runModel(input.client, model, args.prompt, ctx.directory);
|
|
407
|
-
if (
|
|
410
|
+
if (out.startsWith("ERROR:")) return `FAIL
|
|
411
|
+
(${out})`;
|
|
408
412
|
const firstLine = out.split("\n").find((l) => l.trim()) ?? "";
|
|
409
413
|
const f = firstLine.trim();
|
|
410
414
|
const isPass = /^pass\b/i.test(f);
|
package/dist/tui.js
CHANGED
|
@@ -173,6 +173,7 @@ function initializeTui(api, disposeRoot) {
|
|
|
173
173
|
const hf = join(STATE_DIR, sid, "harness.json");
|
|
174
174
|
if (existsSync(hf)) h = JSON.parse(readFileSync(hf, "utf8"));
|
|
175
175
|
}
|
|
176
|
+
if (!h || h.active === false) h = readHarness();
|
|
176
177
|
} catch {
|
|
177
178
|
h = null;
|
|
178
179
|
}
|
package/package.json
CHANGED