mini-coder 0.0.5 → 0.0.7
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 +8 -0
- package/better-errors.md +96 -0
- package/dist/mc.js +340 -295
- package/docs/configs.md +77 -0
- package/docs/tool-hooks.md +142 -0
- package/package.json +2 -1
- package/code-quality-issues.md +0 -135
package/README.md
CHANGED
|
@@ -158,4 +158,12 @@ I believe the best tools disappear into your workflow. I don't want to be the st
|
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
161
|
+
## 💬 What People Are Saying
|
|
162
|
+
|
|
163
|
+
> "sean this is fucking sick"
|
|
164
|
+
> — [vpr99](https://github.com/vpr99) (eric)
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
|
|
161
169
|
*Built with ❤️ and a healthy obsession with terminal aesthetics.*
|
package/better-errors.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Better Errors — Implementation Plan
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Add structured error logging to file and friendly error parsing for display. Three concerns: (1) log full error details to `~/.config/mini-coder/errors.log`, (2) map known AI SDK errors to terse user-facing messages, (3) wire both into existing error surfaces.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Files to Create
|
|
10
|
+
|
|
11
|
+
| File | Purpose |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `src/cli/error-log.ts` | `initErrorLog()`, `logError()` |
|
|
14
|
+
| `src/cli/error-parse.ts` | `parseAppError()` |
|
|
15
|
+
|
|
16
|
+
## Files to Modify
|
|
17
|
+
|
|
18
|
+
| File | Change |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `src/index.ts` | Call `initErrorLog()` at startup; use `logError` + `parseAppError` in top-level catch and `main().catch()` |
|
|
21
|
+
| `src/cli/output.ts` | Update `renderError(err: unknown)` to call log + parse; update `turn-error` branch in `renderTurn()` |
|
|
22
|
+
| `src/agent/agent.ts` | Pass `unknown` to `renderError()` — no logic change needed if signature widens correctly |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Implementation Steps
|
|
27
|
+
|
|
28
|
+
1. **Create `src/cli/error-log.ts`**
|
|
29
|
+
- Module-level `let writer: ReturnType<ReturnType<typeof Bun.file>['writer']> | null = null`
|
|
30
|
+
- `initErrorLog()`: if `writer` is not null, return early (idempotency). Otherwise resolve path `~/.config/mini-coder/errors.log`, open with `Bun.file(path).writer()` (truncates on open), assign to `writer`. Register `process.on('uncaughtException', (err) => { logError(err, 'uncaught'); process.exit(1) })`.
|
|
31
|
+
- `logError(err: unknown, context?: string)`: if `writer` is null, return. Build log entry string (see Log Format), call `writer.write(entry)`. Keep sync-ish by not awaiting — `write()` on a Bun file writer is buffered; call `writer.flush()` after each write so data lands before a crash.
|
|
32
|
+
- Extract error fields via type-narrowing helpers (not exported): `isObject(err)`, read `.name`, `.message`, `.stack`, `.statusCode`, `.url`, `.isRetryable` defensively.
|
|
33
|
+
|
|
34
|
+
2. **Create `src/cli/error-parse.ts`**
|
|
35
|
+
- Import AI SDK error classes: `APICallError`, `RetryError`, `NoContentGeneratedError`, `LoadAPIKeyError`, `NoSuchModelError` from `ai`.
|
|
36
|
+
- Export `parseAppError(err: unknown): { headline: string; hint?: string }`.
|
|
37
|
+
- Implement as a chain of `instanceof` checks (see Error Parse Table). For `RetryError`, recurse on `.lastError` and prepend `"Retries exhausted: "` to `headline`.
|
|
38
|
+
- Fallback: extract first non-empty line of `(err as any)?.message ?? String(err)`, no hint.
|
|
39
|
+
- Network check: before the fallback, check if `(err as any)?.code === 'ECONNREFUSED'` or message includes `'ECONNREFUSED'`.
|
|
40
|
+
|
|
41
|
+
3. **Update `src/cli/output.ts`**
|
|
42
|
+
- Change `renderError` signature from `(msg: string)` to `(err: unknown)`. Inside: call `logError(err, 'render')`, call `parseAppError(err)`, print `✖ red(headline)`, if `hint` print a dim indented hint line (e.g. ` dim(hint)`).
|
|
43
|
+
- In `renderTurn()` `turn-error` branch (non-abort path): replace raw `event.error.message` display with `logError(event.error, 'turn')` then `parseAppError(event.error)` → print `✖ red(headline)`, optional dim hint. Keep the abort quiet-note branch unchanged.
|
|
44
|
+
- All callers of `renderError` that currently pass a string (e.g. in `agent.ts`) — check each call site; if passing a plain string, wrap in `new Error(string)` or let `parseAppError` fallback handle a string gracefully (add string branch at top of `parseAppError`: `if (typeof err === 'string') return { headline: err }`).
|
|
45
|
+
|
|
46
|
+
4. **Update `src/index.ts`**
|
|
47
|
+
- After `registerTerminalCleanup()` (or equivalent startup call), add `initErrorLog()`.
|
|
48
|
+
- Top-level `catch` around `runAgent()`: replace any raw print with `logError(err, 'agent')` + `parseAppError(err)` → print `✖ red(headline)` + dim hint, then `process.exit(1)`.
|
|
49
|
+
- `main().catch()`: same pattern — `logError(err, 'main')` + parse + print + `process.exit(1)`. Remove bare `console.error(err)`.
|
|
50
|
+
|
|
51
|
+
5. **Tests (`src/cli/error-parse.test.ts`)**
|
|
52
|
+
- Test `parseAppError` for each mapped error type.
|
|
53
|
+
- Construct real instances where possible (e.g. `new APICallError({ ... })`); check `headline` and `hint` values.
|
|
54
|
+
- Test `RetryError` unwrapping.
|
|
55
|
+
- Test fallback for plain `Error` and plain string.
|
|
56
|
+
- No mocks, no file I/O, no server calls.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Error Parse Table
|
|
61
|
+
|
|
62
|
+
| Condition | `headline` | `hint` |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `APICallError` with `statusCode === 429` | `"Rate limit hit"` | `"Wait a moment and retry, or switch model with /model"` |
|
|
65
|
+
| `APICallError` with `statusCode === 401 \|\| 403` | `"Auth failed"` | `"Check the relevant provider API key env var"` |
|
|
66
|
+
| `APICallError` other | `"API error \${statusCode}"` | `url` if present |
|
|
67
|
+
| `RetryError` | `"Retries exhausted: \${inner.headline}"` | inner `hint` |
|
|
68
|
+
| `NoContentGeneratedError` | `"Model returned empty response"` | `"Try rephrasing or switching model with /model"` |
|
|
69
|
+
| `LoadAPIKeyError` | `"API key not found"` | `"Set the relevant provider env var"` |
|
|
70
|
+
| `NoSuchModelError` | `"Model not found"` | `"Use /model to pick a valid model"` |
|
|
71
|
+
| `code === 'ECONNREFUSED'` or message contains `'ECONNREFUSED'` | `"Connection failed"` | `"Check network or local server"` |
|
|
72
|
+
| `string` input | string value | — |
|
|
73
|
+
| fallback | first line of `err.message` | — |
|
|
74
|
+
|
|
75
|
+
> `AbortError` is never passed to `parseAppError` — abort is handled at the call sites before reaching these functions.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Log Format
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
[2026-02-25T22:38:53.123Z] context=turn
|
|
83
|
+
name: APICallError
|
|
84
|
+
message: 429 Too Many Requests
|
|
85
|
+
statusCode: 429
|
|
86
|
+
url: https://api.anthropic.com/v1/messages
|
|
87
|
+
isRetryable: true
|
|
88
|
+
stack: APICallError: 429 Too Many Requests
|
|
89
|
+
at ...
|
|
90
|
+
---
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- Each entry ends with `---\n`.
|
|
94
|
+
- Extra fields (`statusCode`, `url`, `isRetryable`) are only emitted if present on the error object.
|
|
95
|
+
- Stack is indented two spaces per line.
|
|
96
|
+
- File is truncated on each app start (writer opened without append flag).
|