opencode-usage-coach 0.8.3 → 0.8.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/README.md +62 -238
- package/dist/index.js +22 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,269 +1,93 @@
|
|
|
1
1
|
# opencode-usage-coach
|
|
2
2
|
|
|
3
|
-
A closed-loop usage coach and harness for [OpenCode](https://opencode.ai). Built for
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
**
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
explicitly ask "run this through the harness" or "use the harness for this". The harness
|
|
29
|
-
tools are only available when the harness agent mode is active (see Install).
|
|
30
|
-
|
|
31
|
-
**Learning from failures (learning loop):**
|
|
32
|
-
- When `grade` returns FAIL, the harness enters a learning cycle: `record_failure` → `investigate` (root-cause analysis) → `verify_diagnosis` → `generalize` (extract a reusable rule).
|
|
33
|
-
- Rules accumulate in `rules.md` → the next `generate` call automatically includes them → the harness avoids repeating the same mistake.
|
|
34
|
-
- Tools: `record_failure`, `investigate`, `verify_diagnosis`, `generalize`.
|
|
35
|
-
|
|
36
|
-
**Domain knowledge base:**
|
|
37
|
-
- `investigate` and `generate` query a local domain DB before running — known facts are injected into the prompt ("Known facts from domain DB: ...").
|
|
38
|
-
- Unknown domains are investigated (webfetch/docs) and stored as graph nodes/edges → accumulates over time → evidence-based judgments instead of speculation.
|
|
39
|
-
- Storage: `nodes.ndjson` + `edges.ndjson` under the project state dir.
|
|
40
|
-
|
|
41
|
-
## Requirements
|
|
42
|
-
- opencode (tested on 1.17.13) with a quota-metered provider configured.
|
|
43
|
-
- `codexbar` CLI with your provider key wired (e.g. `codexbar config set-api-key --provider zai --stdin`).
|
|
44
|
-
|
|
45
|
-
## Install (from npm)
|
|
3
|
+
A closed-loop usage coach and harness for [OpenCode](https://opencode.ai). Built for flat-rate / quota-metered coding plans — it **senses quota → coaches → stops/advances the loop**. Provider-agnostic, configurable via `harness.config.json`.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/opencode-usage-coach) [](./LICENSE) [](#) [](https://ko-fi.com/lhjnano) [](https://github.com/sponsors/lhjnano)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Quota guardian** — senses provider quota windows (5h / weekly / monthly) via the `codexbar` CLI.
|
|
10
|
+
- **Automatic loop control** — STOP threshold blocks tool calls so the agent self-stops; throttle advice downshifts models.
|
|
11
|
+
- **Coaching injection** — real-time guidance on how to use remaining quota, injected into the system prompt.
|
|
12
|
+
- **Sidebar panel** — per-provider quota meters + live harness task states (SolidJS, `Alt+H` to toggle).
|
|
13
|
+
- **Harness agent mode** — triages requests and runs a generate → grade → revise loop, multi-model in one terminal.
|
|
14
|
+
- **Learning loop** — failures are investigated, verified, and generalized into reusable rules (`rules.md`).
|
|
15
|
+
- **Domain knowledge base** — a local graph store that injects known facts into prompts, reducing speculation.
|
|
16
|
+
- **Pre-flight gap analysis** — inspired by Anthropic's Unknowns Matrix; surfaces blind spots before generation starts.
|
|
17
|
+
- **Provider-agnostic** — any provider `codexbar` knows; configure once in `harness.config.json`.
|
|
18
|
+
- **Session isolation** — per-session harness state; no cross-session leakage.
|
|
19
|
+
|
|
20
|
+
## How it works
|
|
21
|
+
|
|
22
|
+
The plugin runs in two parts inside a single opencode terminal. The **server module** senses quota, decides GO/THROTTLE/STOP, and exposes custom harness tools (`generate`, `grade`, `record_failure`, …). The **TUI module** renders quota meters and live task states into the sidebar. The **harness agent** triages each request — trivial work is done directly; substantive work enters the generate→grade→revise loop.
|
|
23
|
+
|
|
24
|
+
See **[docs/architecture.md](docs/architecture.md)** for the full design.
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
46
28
|
```jsonc
|
|
47
|
-
// ~/.config/opencode/opencode.json
|
|
29
|
+
// ~/.config/opencode/opencode.json — server plugin
|
|
48
30
|
{ "plugin": ["opencode-usage-coach"] }
|
|
49
31
|
|
|
50
|
-
// ~/.config/opencode/tui.json (
|
|
32
|
+
// ~/.config/opencode/tui.json — sidebar panel (point at built dist/tui.js)
|
|
51
33
|
{ "$schema": "https://opencode.ai/tui.json", "plugin": ["opencode-usage-coach/tui"] }
|
|
52
34
|
```
|
|
53
|
-
Drop `agents/usage-coach-harness.md` into `~/.config/opencode/agents/` for the agent mode.
|
|
54
35
|
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
bun install
|
|
58
|
-
bun run build # -> dist/index.js, dist/tui.js (solid external)
|
|
59
|
-
# server plugin
|
|
60
|
-
cp dist/index.js ~/.config/opencode/plugins/opencode-usage-coach.js
|
|
61
|
-
# TUI plugin — point tui.json at the built file (NOT the plugins/ dir)
|
|
62
|
-
# ~/.config/opencode/tui.json: { "plugin": ["/abs/path/dist/tui.js"] }
|
|
63
|
-
```
|
|
36
|
+
Then wire `codexbar` and drop `agents/usage-coach-harness.md` into `~/.config/opencode/agents/` for agent mode:
|
|
64
37
|
|
|
65
|
-
|
|
38
|
+
```bash
|
|
39
|
+
# provider quota data source
|
|
40
|
+
printf '%s' "$YOUR_PROVIDER_API_KEY" | codexbar config set-api-key --provider <id> --stdin
|
|
66
41
|
|
|
67
|
-
|
|
42
|
+
# harness role → model mapping (place in your work directory)
|
|
43
|
+
cp harness.config.example.json harness.config.json # edit generator/grader
|
|
44
|
+
```
|
|
68
45
|
|
|
69
|
-
|
|
70
|
-
With the harness agent mode active (`agents/usage-coach-harness.md` installed), ask for substantive work — explicitly or just describe a multi-step task:
|
|
71
|
-
- `"run this through the harness: write CONTRIBUTING.md from git log"`
|
|
72
|
-
- `"harness: add TypeScript strict mode across the repo"`
|
|
73
|
-
- Or just describe the work; the agent triages and enters the loop.
|
|
46
|
+
For local dev without npm: `bun install && bun run build`, then point both configs at the `dist/` files.
|
|
74
47
|
|
|
75
|
-
|
|
48
|
+
## Configuration
|
|
76
49
|
|
|
77
|
-
|
|
78
|
-
The harness picks the loop path based on task dependency:
|
|
79
|
-
- **Independent** (task B doesn't need A's output) → `generate_batch` runs all tasks in **parallel** (faster). Example: `"CONTRIBUTING.md, PR template, issue template"` — three separate docs.
|
|
80
|
-
- **Dependent** (B needs A) → **sequential** `generate` calls. Example: `"1) schema, 2) migration, 3) API"` — each needs the prior.
|
|
50
|
+
Four config surfaces; only the first two (install config + codexbar) are required to run. The **harness config** (`harness.config.json`) maps roles to models so per-model quota is tracked — set `generator` (required) and optionally `grader`, `lighterModel`, and `provider`. Thresholds and tuning live in env vars (`UC_STOP_5H`, `UC_THROTTLE_5H`, …).
|
|
81
51
|
|
|
82
|
-
|
|
83
|
-
Each tool appends a `[usage-coach NEXT]` line to its return value, telling the agent exactly what to call next:
|
|
84
|
-
- `generate` → NEXT: grade the work
|
|
85
|
-
- `grade` PASS → NEXT: mark completed, proceed
|
|
86
|
-
- `grade` FAIL → NEXT: revise (up to 2x) or mark failed
|
|
52
|
+
See **[docs/configuration.md](docs/configuration.md)** for the full reference (env var table, harness config fields, agent-mode scoping, local dev setup).
|
|
87
53
|
|
|
88
|
-
|
|
54
|
+
## Harness Loop
|
|
89
55
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
56
|
+
```
|
|
57
|
+
request → triage → trivial? → done directly
|
|
58
|
+
substantive? → generate → grade ─┬─ PASS → completed
|
|
59
|
+
│
|
|
60
|
+
┌── (FAIL, up to 2×) ──────┘
|
|
61
|
+
▼
|
|
62
|
+
record_failure → investigate → verify → generalize → rules.md
|
|
63
|
+
│
|
|
64
|
+
next generate call includes rules ◄─┘
|
|
65
|
+
```
|
|
95
66
|
|
|
96
|
-
|
|
67
|
+
Independent tasks run in parallel (`generate_batch`); dependent tasks run sequentially. The loop is quota-aware: **GO** → full power, **THROTTLE** → lighter model + capped concurrency, **STOP** → halt.
|
|
97
68
|
|
|
98
|
-
|
|
69
|
+
See **[docs/architecture.md](docs/architecture.md)** for details on the loop, NEXT directives, and quota-aware switching.
|
|
99
70
|
|
|
100
|
-
|
|
71
|
+
## Troubleshooting
|
|
101
72
|
|
|
102
|
-
|
|
103
|
-
```jsonc
|
|
104
|
-
// ~/.config/opencode/opencode.json — server plugin (guardian + harness tools)
|
|
105
|
-
{ "plugin": ["opencode-usage-coach"] } // from npm, OR a local path:
|
|
106
|
-
// { "plugin": ["/abs/path/dist/index.js"] }
|
|
73
|
+
Common issues: TUI panel missing (check `tui.json` points at `dist/tui.js`, never install `solid-js` in the config dir), model selection errors (`generator` is required), and tool-abort timeouts (platform limit — split large tasks).
|
|
107
74
|
|
|
108
|
-
|
|
109
|
-
{ "$schema": "https://opencode.ai/tui.json",
|
|
110
|
-
"plugin": ["/abs/path/dist/tui.js"] }
|
|
75
|
+
See **[docs/troubleshooting.md](docs/troubleshooting.md)** for full diagnoses and fixes.
|
|
111
76
|
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
> The TUI file MUST be loaded via `tui.json` file path (not the `plugins/` dir), and MUST be
|
|
115
|
-
> the compiled `dist/tui.js` (raw `.tsx` / installing `solid-js` crashes opencode).
|
|
77
|
+
## Contributing
|
|
116
78
|
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
printf '%s' "$YOUR_PROVIDER_API_KEY" | codexbar config set-api-key --provider <id> --stdin
|
|
120
|
-
```
|
|
79
|
+
Bug reports and pull requests are welcome. Run `bun run build` before submitting, and keep `lint` + `typecheck` clean:
|
|
121
80
|
|
|
122
|
-
### 3. Harness config — `harness.config.json` (role → model) ★ the main one
|
|
123
|
-
Place in the **work directory**. Each role runs on its model, so per-model quota is tracked
|
|
124
|
-
(works for local LLMs — they show 0%).
|
|
125
|
-
```jsonc
|
|
126
|
-
{
|
|
127
|
-
"generator": "opencode/deepseek-v4-flash-free", // model that produces the work
|
|
128
|
-
"grader": "opencode/mimo-v2.5-free", // model that grades it
|
|
129
|
-
"provider": "", // codexbar quota provider ("" = default)
|
|
130
|
-
"lighterModel": "" // suggested when throttling
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
| Field | Default | Notes |
|
|
134
|
-
|---|---|---|
|
|
135
|
-
| `generator` | **required** | any `provider/model` opencode knows |
|
|
136
|
-
| `grader` | falls back to `generator` | can differ (multi-model) |
|
|
137
|
-
| `provider` | `""` (codexbar default) | which provider's quota the guardian watches |
|
|
138
|
-
| `lighterModel` | `""` | shown in throttle advice; env `UC_LIGHTER_MODEL` overrides |
|
|
139
|
-
|
|
140
|
-
`generator` is **required** — the tools return a clear error if missing. Copy
|
|
141
|
-
`harness.config.example.json` to get started (both example models are free → never gated).
|
|
142
|
-
|
|
143
|
-
### 4. Env vars (thresholds / tuning)
|
|
144
|
-
| Var | Default | Meaning |
|
|
145
|
-
|---|---|---|
|
|
146
|
-
| `UC_STOP_5H` | 92 | 5h window STOP % (blocks tools) |
|
|
147
|
-
| `UC_THROTTLE_5H` | 70 | 5h window throttle % |
|
|
148
|
-
| `UC_STOP_WEEKLY` | 95 | weekly STOP % |
|
|
149
|
-
| `UC_THROTTLE_WEEKLY` | 85 | weekly throttle % |
|
|
150
|
-
| `UC_STOP_MONTHLY` | 98 | monthly STOP % |
|
|
151
|
-
| `UC_LIGHTER_MODEL` | (config `lighterModel`) | suggested model when throttling |
|
|
152
|
-
| `UC_PROVIDER` | (config `provider`) | codexbar provider for the guardian |
|
|
153
|
-
| `UC_TTL_MS` | 60000 | quota cache TTL (ms) |
|
|
154
|
-
| `UC_DEBUG` | 0 | set to `1` for a diagnostic log at `~/.cache/opencode-usage-coach/coach.log` |
|
|
155
|
-
| `UC_HARNESS_AGENT` | `Usage-Coach-Harness` | comma-separated agent modes allowed to use harness tools + receive quota coaching (case-insensitive; must match the agent id, e.g. `usage-coach-harness` from `agents/usage-coach-harness.md`) |
|
|
156
|
-
| `UC_WORM_MAX_AGE_DAYS` | 180 | domain DB worm (GC): drop nodes not accessed in N days (~6 months) |
|
|
157
|
-
| `UC_WORM_MAX_NODES` | 100000 | domain DB worm (GC): cap node count, evict oldest-accessed beyond this |
|
|
158
|
-
|
|
159
|
-
## Agent-mode scoping
|
|
160
|
-
|
|
161
|
-
Harness tools (`generate`, `grade`, `harness_start`, …) and quota coaching are **scoped to
|
|
162
|
-
the `usage-coach-harness` agent mode**. Other modes (build, general, your custom agents) stay
|
|
163
|
-
completely clean — no harness tools in their tool list, no quota coaching injected into their
|
|
164
|
-
system prompt.
|
|
165
|
-
|
|
166
|
-
This is enforced on two independent layers (defense in depth):
|
|
167
|
-
|
|
168
|
-
1. **Agent definition** (`agents/usage-coach-harness.md`) — its `permission` allowlist names the
|
|
169
|
-
harness tools, so they only appear in this mode. Other agents' permission lists don't name
|
|
170
|
-
them, so they're hidden from those modes automatically (this is the standard opencode
|
|
171
|
-
mechanism — tool visibility is the agent definition's responsibility).
|
|
172
|
-
2. **Plugin runtime gate** (`tool.execute.before`) — even if a harness tool were somehow
|
|
173
|
-
invoked, the plugin resolves the current session's agent (`client.session.get` → `info.agent`,
|
|
174
|
-
60s-cached) and throws unless it matches `UC_HARNESS_AGENT` (default `Usage-Coach-Harness`,
|
|
175
|
-
case-insensitive). The quota system-prompt injection is gated the same way.
|
|
176
|
-
|
|
177
|
-
**To use the harness tools**, switch to the `usage-coach-harness` agent mode.
|
|
178
|
-
|
|
179
|
-
**To allow additional modes**, set `UC_HARNESS_AGENT` to a comma-separated list:
|
|
180
81
|
```bash
|
|
181
|
-
|
|
82
|
+
bun run lint && bun run typecheck
|
|
182
83
|
```
|
|
183
84
|
|
|
184
|
-
|
|
185
|
-
> custom tools (like this one) cannot be fully rewritten in v2. Agent `permission` allowlists +
|
|
186
|
-
> the v1 runtime gate is the structurally correct way to scope tool visibility.
|
|
85
|
+
## License
|
|
187
86
|
|
|
188
|
-
|
|
189
|
-
- **Server module** (`src/index.ts`) — SENSE/DECIDE/ACT + custom harness tools. Loaded via `opencode.json`.
|
|
190
|
-
- **TUI module** (`src/tui.tsx`) — SolidJS, reads a state file, renders into `sidebar_footer`/`home_footer`. Loaded via `tui.json`. Bundled with `tsup` + `esbuild-plugin-solid`, solid kept **external** (resolves to opencode's bundle — avoids the duplicate-instance crash). Exports `{ tui }` (a bare function is misread as a server plugin).
|
|
191
|
-
- server↔TUI communicate via a state file (`~/.cache/opencode-usage-coach/*.json`) — they are separate processes.
|
|
87
|
+
[MIT](./LICENSE) © opencode-usage-coach contributors
|
|
192
88
|
|
|
193
|
-
|
|
194
|
-
opencode's bundled solid); TUI plugins must be compiled + loaded via `tui.json` file path;
|
|
195
|
-
`codexbar` must be called via `spawn` (the `$` BunShell leaks output to the TUI).
|
|
89
|
+
## Sponsor
|
|
196
90
|
|
|
197
|
-
|
|
91
|
+
If this saves your quota budget, consider supporting development:
|
|
198
92
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
### TUI panel missing or harness not shown
|
|
202
|
-
- **Check `tui.json` points at the `dist/tui.js` file path** — not the `plugins/` directory.
|
|
203
|
-
```jsonc
|
|
204
|
-
// ~/.config/opencode/tui.json
|
|
205
|
-
{ "$schema": "https://opencode.ai/tui.json", "plugin": ["/abs/path/dist/tui.js"] }
|
|
206
|
-
```
|
|
207
|
-
- **Do NOT install `solid-js` in the config dir** — conflicts with opencode's bundled solid, causes a crash. Keep it peer + external only.
|
|
208
|
-
- **Export must be `{ tui }`** (an object) — a bare function is misread as a server plugin.
|
|
209
|
-
- **Color prop is `fg`** (not `foreground`): `style={{ fg: theme.current.success }}`.
|
|
210
|
-
- **Call `codexbar` via `spawn`** — the `$` BunShell leaks command output into the TUI.
|
|
211
|
-
- **Harness not visible?** The TUI shows the **current session's** harness only. A finished harness (`active:false`) is hidden. A harness started in another session won't appear here — switch to that session to see it.
|
|
212
|
-
|
|
213
|
-
### LLM model selection (generate/grade)
|
|
214
|
-
- **`generator` is required in `harness.config.json`** — the tools return a clear error if missing (the old z.ai fallback was removed in v0.2.4).
|
|
215
|
-
- Format: `"provider/model"` (e.g. `"opencode/deepseek-v4-flash-free"`, `"opencode/mimo-v2.5-free"` — see `harness.config.example.json`).
|
|
216
|
-
- **Config precedence**: workdir `harness.config.json` > global `~/.config/opencode-usage-coach/harness.config.json`.
|
|
217
|
-
- Omitting `grader` falls back to `generator`. If neither is set, the grade tool returns FAIL + guidance.
|
|
218
|
-
- `provider` (quota source) and `lighterModel` (suggested on throttle) are also configurable in the same file.
|
|
219
|
-
|
|
220
|
-
### Parallel harness execution (generate_batch)
|
|
221
|
-
- **Only INDEPENDENT tasks should be batched** — dependent tasks (B needs A) require sequential `generate` calls.
|
|
222
|
-
- `generate_batch` runs each task in a separate sub-session on the same server (shared model config).
|
|
223
|
-
- runModel polls the sub-session until `idle`/`completed` (max 10 min). Trace with `UC_DEBUG=1`:
|
|
224
|
-
```
|
|
225
|
-
runModel(<generator>): session xxx created, prompt 142 chars
|
|
226
|
-
runModel(<generator>): poll 3s status="running"
|
|
227
|
-
runModel(<generator>): done 48s, 1203 chars
|
|
228
|
-
```
|
|
229
|
-
- `(no output)` means the sub-session returned no text. Check `~/.cache/opencode-usage-coach/coach.log` for the runModel trace (requires `UC_DEBUG=1`).
|
|
230
|
-
- **Note**: runModel only terminates on explicit `idle`/`completed` status. An earlier bug broke on `!status` (undefined) immediately — fixed.
|
|
231
|
-
|
|
232
|
-
### generate / generate_batch returns "Tool execution aborted"
|
|
233
|
-
- **Cause:** opencode imposes a tool execution timeout (~60–120s, not configurable). `runModel` polls the sub-session for up to 10 min; if the generator model takes longer than the tool timeout, opencode aborts the call.
|
|
234
|
-
- **This is a platform limit, not a plugin bug** — there is no config key to extend it.
|
|
235
|
-
- **Mitigation:** split large tasks into smaller ones that finish within the timeout. The NEXT directives + revise loop help — a FAIL triggers a focused revise rather than a monolithic retry.
|
|
236
|
-
- The sub-session keeps running in the background after abort; its file writes are preserved. Only the tool's return value is lost.
|
|
237
|
-
|
|
238
|
-
### Multi-session (per-session state isolation)
|
|
239
|
-
- Each opencode session has a unique sessionID; harness state is isolated per-session:
|
|
240
|
-
```
|
|
241
|
-
~/.cache/opencode-usage-coach/projects/<dir-hash>/<sessionID>/harness.json
|
|
242
|
-
```
|
|
243
|
-
- Different working directories get separate project state (keyed by path hash).
|
|
244
|
-
- The TUI shows the **current session's** harness only (per-session isolation) — no cross-session leakage. A harness running in session B does not appear in session A's panel.
|
|
245
|
-
- Harness completion sets `active:false` → hidden from the TUI.
|
|
246
|
-
- Override the state path with `UC_STATE_DIR` (forces global state).
|
|
247
|
-
|
|
248
|
-
**Key gotcha — opencode TUI `ctx` does NOT carry `session_id`.**
|
|
249
|
-
The slot context passed to `panel(ctx)` contains only `{ theme }`. There is no `session_id`/`sessionID` field. The current session ID lives in **`api.route.current.params.sessionID`** instead — the panel reads it from there. If you ever see harnesses from other sessions leaking in, the cause is almost certainly that `sid` resolved to empty (→ fallback broad scan).
|
|
250
|
-
|
|
251
|
-
**Debugging session isolation** (if it breaks again):
|
|
252
|
-
1. Check `~/.cache/opencode-usage-coach/projects/<hash>/tui-debug.log` — is `panel` being called? What `routeSid` value?
|
|
253
|
-
2. `api.route.current.params.sessionID` — populated? (Empty → panel falls back to scanning all sessions.)
|
|
254
|
-
3. New TUI code loaded? `tui-loaded.txt` (MARKER) should show `loaded-v2 ...`. If it still says `loaded`, the new dist isn't being picked up.
|
|
255
|
-
4. `appendFileSync` imported in `src/tui.tsx`? If missing, **all TUI debug logging silently fails** (ReferenceError swallowed by try/catch) — this wasted a lot of debugging time once.
|
|
256
|
-
|
|
257
|
-
**Past issue (fixed v0.3.4):** panel read `ctx.session_id` which was always `undefined` → fallback scanned every session → another session's active harness leaked in. Fixed by reading `api.route.current.params.sessionID`.
|
|
258
|
-
|
|
259
|
-
## Status
|
|
260
|
-
- ✅ Quota guardian + TUI panel (per-provider coach view, 5h/1w gauges, collapsible Alt+H)
|
|
261
|
-
- ✅ Harness: agent mode with generate/grade tools (multi-model, 1 terminal)
|
|
262
|
-
- ✅ Deterministic loop via NEXT directives (parallel PATH A / sequential PATH B)
|
|
263
|
-
- ✅ Quota-aware tools (GO/THROTTLE/STOP drive model selection + concurrency)
|
|
264
|
-
- ✅ Learning loop (record_failure → investigate → verify_diagnosis → generalize → rules.md)
|
|
265
|
-
- ✅ Domain knowledge base (graph store, investigate/generate injection)
|
|
266
|
-
- ✅ Session isolation (api.route, per-session harness state)
|
|
267
|
-
- ✅ npm packaging (`opencode plugin install opencode-usage-coach`)
|
|
268
|
-
|
|
269
|
-
License: MIT.
|
|
93
|
+
[](https://ko-fi.com/lhjnano) [](https://github.com/sponsors/lhjnano)
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, appendFileSync as appendFileSync2, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
3
|
-
import { spawn } from "child_process";
|
|
3
|
+
import { spawn, spawnSync } from "child_process";
|
|
4
4
|
import { createHash } from "crypto";
|
|
5
5
|
import { homedir } from "os";
|
|
6
6
|
import { join as join2, resolve, dirname } from "path";
|
|
@@ -1359,8 +1359,27 @@ Then: harness_done(). Follow the [usage-coach NEXT] directive each tool returns.
|
|
|
1359
1359
|
profile = { skipped: true, reason: "skip_scan requested", language: "unknown", frameworks: [], structure: [], manifestFiles: [], keyDeps: [], configFiles: [], totalFiles: 0 };
|
|
1360
1360
|
} else {
|
|
1361
1361
|
try {
|
|
1362
|
-
const
|
|
1363
|
-
const
|
|
1362
|
+
const dir = ctx.directory || ".";
|
|
1363
|
+
const result2 = spawnSync("find", [
|
|
1364
|
+
dir,
|
|
1365
|
+
"-maxdepth",
|
|
1366
|
+
"4",
|
|
1367
|
+
"-type",
|
|
1368
|
+
"f",
|
|
1369
|
+
"-not",
|
|
1370
|
+
"-path",
|
|
1371
|
+
"*/node_modules/*",
|
|
1372
|
+
"-not",
|
|
1373
|
+
"-path",
|
|
1374
|
+
"*/.git/*",
|
|
1375
|
+
"-not",
|
|
1376
|
+
"-path",
|
|
1377
|
+
"*/dist/*",
|
|
1378
|
+
"-not",
|
|
1379
|
+
"-path",
|
|
1380
|
+
"*/.cache/*"
|
|
1381
|
+
], { encoding: "utf8", timeout: 1e4, maxBuffer: 1024 * 1024 });
|
|
1382
|
+
const fileList = result2.stdout || "";
|
|
1364
1383
|
profile = parseFileList(fileList, ctx.directory);
|
|
1365
1384
|
if (profile.totalFiles < 5) {
|
|
1366
1385
|
profile = { ...profile, skipped: true, reason: `directory nearly empty (${profile.totalFiles} files)` };
|
package/package.json
CHANGED