mini-coder 0.5.0 → 0.5.2
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 +2 -0
- package/bun.lock +39 -40
- package/package.json +10 -11
- package/src/agent.ts +49 -1
- package/src/errors.ts +15 -0
- package/src/git.ts +50 -17
- package/src/index.ts +151 -11
- package/src/prompt.ts +19 -9
- package/src/session.ts +211 -6
- package/src/settings.ts +72 -3
- package/src/skills.ts +11 -7
- package/src/submit.ts +4 -6
- package/src/tools.ts +3 -2
- package/src/ui/agent.ts +1 -4
- package/src/ui/commands.test.ts +3 -0
- package/src/ui/commands.ts +1 -4
- package/src/ui/conversation.test.ts +165 -1
- package/src/ui/conversation.ts +268 -36
- package/src/ui/help.test.ts +18 -0
- package/src/ui/help.ts +6 -0
- package/src/ui/input.test.ts +5 -1
- package/src/ui/input.ts +7 -1
- package/src/ui/status.test.ts +4 -0
- package/src/ui.ts +96 -11
- package/src/version.ts +48 -0
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ Plugins can add more tools, but the core stays intentionally small.
|
|
|
83
83
|
| `Tab` | File path autocomplete (or command filter on `/`) |
|
|
84
84
|
| `Ctrl+R` | Search global raw input history |
|
|
85
85
|
| `Ctrl+C` | Graceful exit |
|
|
86
|
+
| `Ctrl+D` | Graceful exit (EOF, when input is empty) |
|
|
87
|
+
| `:q` | Graceful exit |
|
|
86
88
|
|
|
87
89
|
## Headless one-shot mode
|
|
88
90
|
|
package/bun.lock
CHANGED
|
@@ -5,18 +5,17 @@
|
|
|
5
5
|
"": {
|
|
6
6
|
"name": "mini-coder",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@cel-tui/components": "^0.
|
|
9
|
-
"@cel-tui/core": "^0.
|
|
10
|
-
"@cel-tui/types": "^0.
|
|
11
|
-
"@mariozechner/pi-ai": "^0.
|
|
12
|
-
"diff": "^8.0.4",
|
|
8
|
+
"@cel-tui/components": "^0.6.2",
|
|
9
|
+
"@cel-tui/core": "^0.6.2",
|
|
10
|
+
"@cel-tui/types": "^0.6.2",
|
|
11
|
+
"@mariozechner/pi-ai": "^0.66.1",
|
|
13
12
|
},
|
|
14
13
|
"devDependencies": {
|
|
15
|
-
"@biomejs/biome": "^2.4.
|
|
16
|
-
"@types/bun": "
|
|
17
|
-
"lefthook": "^2.1.
|
|
18
|
-
"prettier": "^3.8.
|
|
19
|
-
"typescript": "^
|
|
14
|
+
"@biomejs/biome": "^2.4.11",
|
|
15
|
+
"@types/bun": "^1.3.12",
|
|
16
|
+
"lefthook": "^2.1.5",
|
|
17
|
+
"prettier": "^3.8.2",
|
|
18
|
+
"typescript": "^6.0.2",
|
|
20
19
|
},
|
|
21
20
|
},
|
|
22
21
|
},
|
|
@@ -91,33 +90,33 @@
|
|
|
91
90
|
|
|
92
91
|
"@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
|
|
93
92
|
|
|
94
|
-
"@biomejs/biome": ["@biomejs/biome@2.4.
|
|
93
|
+
"@biomejs/biome": ["@biomejs/biome@2.4.11", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.11", "@biomejs/cli-darwin-x64": "2.4.11", "@biomejs/cli-linux-arm64": "2.4.11", "@biomejs/cli-linux-arm64-musl": "2.4.11", "@biomejs/cli-linux-x64": "2.4.11", "@biomejs/cli-linux-x64-musl": "2.4.11", "@biomejs/cli-win32-arm64": "2.4.11", "@biomejs/cli-win32-x64": "2.4.11" }, "bin": { "biome": "bin/biome" } }, "sha512-nWxHX8tf3Opb/qRgZpBbsTOqOodkbrkJ7S+JxJAruxOReaDPPmPuLBAGQ8vigyUgo0QBB+oQltNEAvalLcjggA=="],
|
|
95
94
|
|
|
96
|
-
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.
|
|
95
|
+
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wOt+ed+L2dgZanWyL6i29qlXMc088N11optzpo10peayObBaAshbTcxKUchzEMp9QSY8rh5h6VfAFE3WTS1rqg=="],
|
|
97
96
|
|
|
98
|
-
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.
|
|
97
|
+
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-gZ6zR8XmZlExfi/Pz/PffmdpWOQ8Qhy7oBztgkR8/ylSRyLwfRPSadmiVCV8WQ8PoJ2MWUy2fgID9zmtgUUJmw=="],
|
|
99
98
|
|
|
100
|
-
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.
|
|
99
|
+
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-avdJaEElXrKceK0va9FkJ4P5ci3N01TGkc6ni3P8l3BElqbOz42Wg2IyX3gbh0ZLEd4HVKEIrmuVu/AMuSeFFA=="],
|
|
101
100
|
|
|
102
|
-
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.
|
|
101
|
+
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-+Sbo1OAmlegtdwqFE8iOxFIWLh1B3OEgsuZfBpyyN/kWuqZ8dx9ZEes6zVnDMo+zRHF2wLynRVhoQmV7ohxl2Q=="],
|
|
103
102
|
|
|
104
|
-
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.
|
|
103
|
+
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.11", "", { "os": "linux", "cpu": "x64" }, "sha512-TagWV0iomp5LnEnxWFg4nQO+e52Fow349vaX0Q/PIcX6Zhk4GGBgp3qqZ8PVkpC+cuehRctMf3+6+FgQ8jCEFQ=="],
|
|
105
104
|
|
|
106
|
-
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.
|
|
105
|
+
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.11", "", { "os": "linux", "cpu": "x64" }, "sha512-bexd2IklK7ZgPhrz6jXzpIL6dEAH9MlJU1xGTrypx+FICxrXUp4CqtwfiuoDKse+UlgAlWtzML3jrMqeEAHEhA=="],
|
|
107
106
|
|
|
108
|
-
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.
|
|
107
|
+
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-RJhaTnY8byzxDt4bDVb7AFPHkPcjOPK3xBip4ZRTrN3TEfyhjLRm3r3mqknqydgVTB74XG8l4jMLwEACEeihVg=="],
|
|
109
108
|
|
|
110
|
-
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.
|
|
109
|
+
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.11", "", { "os": "win32", "cpu": "x64" }, "sha512-A8D3JM/00C2KQgUV3oj8Ba15EHEYwebAGCy5Sf9GAjr5Y3+kJIYOiESoqRDeuRZueuMdCsbLZIUqmPhpYXJE9A=="],
|
|
111
110
|
|
|
112
|
-
"@cel-tui/components": ["@cel-tui/components@0.
|
|
111
|
+
"@cel-tui/components": ["@cel-tui/components@0.6.2", "", { "dependencies": { "@cel-tui/core": "0.6.2", "@cel-tui/types": "0.6.2", "lextide": "^0.1.0", "yoctomarkdown": "^0.1.0" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-FYR7lX3/gPAyEkfMuyVapdxfO0e9OIw4lmdIUF2Tw7QszkpV4MAkEoB3G2oUY6UZyxJCSCKLBPvLzwu5uxaDgw=="],
|
|
113
112
|
|
|
114
|
-
"@cel-tui/core": ["@cel-tui/core@0.
|
|
113
|
+
"@cel-tui/core": ["@cel-tui/core@0.6.2", "", { "dependencies": { "@cel-tui/types": "0.6.2", "get-east-asian-width": "^1.5.0" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-KJQdDMPbwLE211Hvn75jUKEvHiKTtQ7iVGJiiOpG+s4DjhnpySBXWO0hReMxe5NR2NPls7wmze1dBZ8/MXqVXA=="],
|
|
115
114
|
|
|
116
|
-
"@cel-tui/types": ["@cel-tui/types@0.
|
|
115
|
+
"@cel-tui/types": ["@cel-tui/types@0.6.2", "", { "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-JsJdo20KmgtC67QlG/ZrZyGi0xNJBKd3G6kM/yN/6/hk8a86P+1k1jqtSUjcZ4E9x1v9IXqPk6QelU7kLyOV1A=="],
|
|
117
116
|
|
|
118
117
|
"@google/genai": ["@google/genai@1.48.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-plonYK4ML2PrxsRD9SeqmFt76eREWkQdPCglOA6aYDzL1AAbE+7PUnT54SvpWGfws13L0AZEqGSpL7+1IPnTxQ=="],
|
|
119
118
|
|
|
120
|
-
"@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.
|
|
119
|
+
"@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.66.1", "", { "dependencies": { "@anthropic-ai/sdk": "^0.73.0", "@aws-sdk/client-bedrock-runtime": "^3.983.0", "@google/genai": "^1.40.0", "@mistralai/mistralai": "1.14.1", "@sinclair/typebox": "^0.34.41", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "chalk": "^5.6.2", "openai": "6.26.0", "partial-json": "^0.1.7", "proxy-agent": "^6.5.0", "undici": "^7.19.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-7IZHvpsFdKEBkTmjNrdVL7JLUJVIpha6bwTr12cZ5XyDrxij06wP6Ncpnf4HT5BXAzD5w2JnoqTOSbMEIZj3dg=="],
|
|
121
120
|
|
|
122
121
|
"@mistralai/mistralai": ["@mistralai/mistralai@1.14.1", "", { "dependencies": { "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.24.1" } }, "sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ=="],
|
|
123
122
|
|
|
@@ -233,7 +232,7 @@
|
|
|
233
232
|
|
|
234
233
|
"@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="],
|
|
235
234
|
|
|
236
|
-
"@types/bun": ["@types/bun@1.3.
|
|
235
|
+
"@types/bun": ["@types/bun@1.3.12", "", { "dependencies": { "bun-types": "1.3.12" } }, "sha512-DBv81elK+/VSwXHDlnH3Qduw+KxkTIWi7TXkAeh24zpi5l0B2kUg9Ga3tb4nJaPcOFswflgi/yAvMVBPrxMB+A=="],
|
|
237
236
|
|
|
238
237
|
"@types/node": ["@types/node@25.5.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg=="],
|
|
239
238
|
|
|
@@ -259,7 +258,7 @@
|
|
|
259
258
|
|
|
260
259
|
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
|
|
261
260
|
|
|
262
|
-
"bun-types": ["bun-types@1.3.
|
|
261
|
+
"bun-types": ["bun-types@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA=="],
|
|
263
262
|
|
|
264
263
|
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
|
265
264
|
|
|
@@ -269,8 +268,6 @@
|
|
|
269
268
|
|
|
270
269
|
"degenerator": ["degenerator@5.0.1", "", { "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", "esprima": "^4.0.1" } }, "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ=="],
|
|
271
270
|
|
|
272
|
-
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
|
273
|
-
|
|
274
271
|
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
|
275
272
|
|
|
276
273
|
"escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="],
|
|
@@ -323,27 +320,29 @@
|
|
|
323
320
|
|
|
324
321
|
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
|
325
322
|
|
|
326
|
-
"lefthook": ["lefthook@2.1.
|
|
323
|
+
"lefthook": ["lefthook@2.1.5", "", { "optionalDependencies": { "lefthook-darwin-arm64": "2.1.5", "lefthook-darwin-x64": "2.1.5", "lefthook-freebsd-arm64": "2.1.5", "lefthook-freebsd-x64": "2.1.5", "lefthook-linux-arm64": "2.1.5", "lefthook-linux-x64": "2.1.5", "lefthook-openbsd-arm64": "2.1.5", "lefthook-openbsd-x64": "2.1.5", "lefthook-windows-arm64": "2.1.5", "lefthook-windows-x64": "2.1.5" }, "bin": { "lefthook": "bin/index.js" } }, "sha512-yB9IFWurFllusbPZqvG0EavTmpNXPya2MuO7Li7YT78xAj3uCQ3AgmW9TVUbTTsSMhsegbiAMRpwfEk2TP1P0A=="],
|
|
324
|
+
|
|
325
|
+
"lefthook-darwin-arm64": ["lefthook-darwin-arm64@2.1.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VITTaw8PxxyE26gkZ8UcwIa5ZrWnKNRGLeeSrqri40cQdXvLTEoMq2tjjw7eiL9UcB0waRReDdzydevy9GOPUQ=="],
|
|
327
326
|
|
|
328
|
-
"lefthook-darwin-
|
|
327
|
+
"lefthook-darwin-x64": ["lefthook-darwin-x64@2.1.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-AvtjYiW0BSGHBGrdvL313seUymrW9FxI+6JJwJ+ZSaa2sH81etrTB0wAwlH1L9VfFwK9+gWvatZBvLfF3L4fPw=="],
|
|
329
328
|
|
|
330
|
-
"lefthook-
|
|
329
|
+
"lefthook-freebsd-arm64": ["lefthook-freebsd-arm64@2.1.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-mXjJwe8jKGWGiBYUxfQY1ab3Nn5NhafqT9q3KJz8m5joGGQj4JD0cbWxF1nVBLBWsDGbWZRZunTCMGcIScT2bQ=="],
|
|
331
330
|
|
|
332
|
-
"lefthook-freebsd-
|
|
331
|
+
"lefthook-freebsd-x64": ["lefthook-freebsd-x64@2.1.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-exD69dCjc1K45BxatDPGoH4NmEvgLKPm4kJLOWn1fTeHRKZwWiFPwnjknEoG2OemlCDHmCU++5X40kMEG0WBlA=="],
|
|
333
332
|
|
|
334
|
-
"lefthook-
|
|
333
|
+
"lefthook-linux-arm64": ["lefthook-linux-arm64@2.1.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-57TDKC5ewWpsCLZQKIJMHumFEObYKVundmPpiWhX491hINRZYYOL/26yrnVnNcidThRzTiTC+HLcuplLcaXtbA=="],
|
|
335
334
|
|
|
336
|
-
"lefthook-linux-
|
|
335
|
+
"lefthook-linux-x64": ["lefthook-linux-x64@2.1.5", "", { "os": "linux", "cpu": "x64" }, "sha512-bqK3LrAB5l5YaCaoHk6qRWlITrGWzP4FbwRxA31elbxjd0wgNWZ2Sn3zEfSEcxz442g7/PPkEwqqsTx0kSFzpg=="],
|
|
337
336
|
|
|
338
|
-
"lefthook-
|
|
337
|
+
"lefthook-openbsd-arm64": ["lefthook-openbsd-arm64@2.1.5", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5aSwK7vV3A6t0w9PnxCMiVjQlcvopBP50BtmnnLnNJyAYHnFbZ0Baq5M0WkE9IsUkWSux0fe6fd0jDkuG711MA=="],
|
|
339
338
|
|
|
340
|
-
"lefthook-openbsd-
|
|
339
|
+
"lefthook-openbsd-x64": ["lefthook-openbsd-x64@2.1.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Y+pPdDuENJ8qWnUgL02xxhpjblc0WnwXvWGfqnl3WZrAgHzQpwx3G6469RID/wlNVdHYAlw3a8UkFSMYsTzXvA=="],
|
|
341
340
|
|
|
342
|
-
"lefthook-
|
|
341
|
+
"lefthook-windows-arm64": ["lefthook-windows-arm64@2.1.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-2PlcFBjTzJaMufw0c28kfhB/0zmaRCU0TRPPsil/HU2YNOExod4upPGLk9qjgsOmb2YVWFz6zq6u7+D1yqmzTQ=="],
|
|
343
342
|
|
|
344
|
-
"lefthook-windows-
|
|
343
|
+
"lefthook-windows-x64": ["lefthook-windows-x64@2.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-yiAh8qxml6uqy10jDxOdN9fOQpyLxBFY1fgCEAhn7sVJYmJKRhjqSBwZX6LG5MQjzr29KStrIdw7TR3lf3rT7Q=="],
|
|
345
344
|
|
|
346
|
-
"
|
|
345
|
+
"lextide": ["lextide@0.1.0", "", {}, "sha512-i1fx9SzultDOIgVtFt/vBOeyFaGYCNLT6OcdqOLRfWL9p6aTQsq8JQ+8LpJ4T7znWNjfjLqUU6dK5g2kXhSq3A=="],
|
|
347
346
|
|
|
348
347
|
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
|
349
348
|
|
|
@@ -369,7 +368,7 @@
|
|
|
369
368
|
|
|
370
369
|
"path-expression-matcher": ["path-expression-matcher@1.2.1", "", {}, "sha512-d7gQQmLvAKXKXE2GeP9apIGbMYKz88zWdsn/BN2HRWVQsDFdUY36WSLTY0Jvd4HWi7Fb30gQ62oAOzdgJA6fZw=="],
|
|
371
370
|
|
|
372
|
-
"prettier": ["prettier@3.8.
|
|
371
|
+
"prettier": ["prettier@3.8.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q=="],
|
|
373
372
|
|
|
374
373
|
"protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
|
375
374
|
|
|
@@ -401,7 +400,7 @@
|
|
|
401
400
|
|
|
402
401
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
403
402
|
|
|
404
|
-
"typescript": ["typescript@
|
|
403
|
+
"typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
|
|
405
404
|
|
|
406
405
|
"undici": ["undici@7.24.7", "", {}, "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ=="],
|
|
407
406
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mini-coder",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "A small, fast CLI coding agent",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -18,18 +18,17 @@
|
|
|
18
18
|
"test": "bun test"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@cel-tui/components": "^0.
|
|
22
|
-
"@cel-tui/core": "^0.
|
|
23
|
-
"@cel-tui/types": "^0.
|
|
24
|
-
"@mariozechner/pi-ai": "^0.
|
|
25
|
-
"diff": "^8.0.4"
|
|
21
|
+
"@cel-tui/components": "^0.6.2",
|
|
22
|
+
"@cel-tui/core": "^0.6.2",
|
|
23
|
+
"@cel-tui/types": "^0.6.2",
|
|
24
|
+
"@mariozechner/pi-ai": "^0.66.1"
|
|
26
25
|
},
|
|
27
26
|
"devDependencies": {
|
|
28
|
-
"@biomejs/biome": "^2.4.
|
|
29
|
-
"@types/bun": "
|
|
30
|
-
"lefthook": "^2.1.
|
|
31
|
-
"prettier": "^3.8.
|
|
32
|
-
"typescript": "^
|
|
27
|
+
"@biomejs/biome": "^2.4.11",
|
|
28
|
+
"@types/bun": "^1.3.12",
|
|
29
|
+
"lefthook": "^2.1.5",
|
|
30
|
+
"prettier": "^3.8.2",
|
|
31
|
+
"typescript": "^6.0.2"
|
|
33
32
|
},
|
|
34
33
|
"license": "MIT"
|
|
35
34
|
}
|
package/src/agent.ts
CHANGED
|
@@ -376,6 +376,44 @@ function handleAssistantStreamEvent(
|
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
+
function buildIncompleteAssistantMessage(
|
|
380
|
+
opts: Pick<RunAgentOpts, "model" | "signal">,
|
|
381
|
+
partialAssistantMessage?: AssistantMessage,
|
|
382
|
+
): AssistantMessage {
|
|
383
|
+
const stopReason = opts.signal?.aborted ? "aborted" : "error";
|
|
384
|
+
const errorMessage =
|
|
385
|
+
stopReason === "aborted"
|
|
386
|
+
? "Request was aborted"
|
|
387
|
+
: "Stream ended without a final assistant message";
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
role: "assistant",
|
|
391
|
+
content: partialAssistantMessage
|
|
392
|
+
? cloneAssistantContent(partialAssistantMessage.content)
|
|
393
|
+
: [],
|
|
394
|
+
api: partialAssistantMessage?.api ?? opts.model.api,
|
|
395
|
+
provider: partialAssistantMessage?.provider ?? opts.model.provider,
|
|
396
|
+
model: partialAssistantMessage?.model ?? opts.model.id,
|
|
397
|
+
usage: partialAssistantMessage?.usage ?? {
|
|
398
|
+
input: 0,
|
|
399
|
+
output: 0,
|
|
400
|
+
cacheRead: 0,
|
|
401
|
+
cacheWrite: 0,
|
|
402
|
+
totalTokens: 0,
|
|
403
|
+
cost: {
|
|
404
|
+
input: 0,
|
|
405
|
+
output: 0,
|
|
406
|
+
cacheRead: 0,
|
|
407
|
+
cacheWrite: 0,
|
|
408
|
+
total: 0,
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
stopReason,
|
|
412
|
+
errorMessage,
|
|
413
|
+
timestamp: Date.now(),
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
379
417
|
async function streamAssistantMessage(
|
|
380
418
|
opts: Pick<
|
|
381
419
|
RunAgentOpts,
|
|
@@ -394,6 +432,12 @@ async function streamAssistantMessage(
|
|
|
394
432
|
buildAgentContext(opts.systemPrompt, opts.messages, opts.tools),
|
|
395
433
|
buildStreamOptions(opts.apiKey, opts.effort, opts.signal),
|
|
396
434
|
);
|
|
435
|
+
const streamResult = eventStream.result();
|
|
436
|
+
let settledStreamResult: AssistantMessage | undefined;
|
|
437
|
+
void streamResult.then((message) => {
|
|
438
|
+
settledStreamResult = message;
|
|
439
|
+
});
|
|
440
|
+
|
|
397
441
|
let assistantMessage: AssistantMessage | undefined;
|
|
398
442
|
let partialAssistantMessage: AssistantMessage | undefined;
|
|
399
443
|
|
|
@@ -406,8 +450,12 @@ async function streamAssistantMessage(
|
|
|
406
450
|
handleAssistantStreamEvent(event, opts.onEvent) ?? assistantMessage;
|
|
407
451
|
}
|
|
408
452
|
|
|
453
|
+
// `end(result)` resolves the final result without emitting a terminal event.
|
|
454
|
+
await Promise.resolve();
|
|
409
455
|
const finalAssistantMessage =
|
|
410
|
-
assistantMessage ??
|
|
456
|
+
assistantMessage ??
|
|
457
|
+
settledStreamResult ??
|
|
458
|
+
buildIncompleteAssistantMessage(opts, partialAssistantMessage);
|
|
411
459
|
if (!partialAssistantMessage) {
|
|
412
460
|
return finalAssistantMessage;
|
|
413
461
|
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared error-formatting helpers.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Convert an unknown thrown value into a readable message string.
|
|
9
|
+
*
|
|
10
|
+
* @param error - The thrown value to format.
|
|
11
|
+
* @returns The error message when available, otherwise the stringified value.
|
|
12
|
+
*/
|
|
13
|
+
export function getErrorMessage(error: unknown): string {
|
|
14
|
+
return error instanceof Error ? error.message : String(error);
|
|
15
|
+
}
|
package/src/git.ts
CHANGED
|
@@ -23,6 +23,8 @@ export interface GitState {
|
|
|
23
23
|
root: string;
|
|
24
24
|
/** Current branch name (empty string for detached HEAD). */
|
|
25
25
|
branch: string;
|
|
26
|
+
/** Upstream tracking ref such as `origin/main`, or `null` when none exists. */
|
|
27
|
+
upstream: string | null;
|
|
26
28
|
/** Number of staged (index) changes. */
|
|
27
29
|
staged: number;
|
|
28
30
|
/** Number of unstaged working-tree modifications. */
|
|
@@ -81,7 +83,7 @@ function hasTrackedChange(status: string): boolean {
|
|
|
81
83
|
* @param output - Raw `git status --porcelain` output.
|
|
82
84
|
* @returns Counts of staged, modified, and untracked files.
|
|
83
85
|
*/
|
|
84
|
-
function
|
|
86
|
+
export function parseGitStatus(output: string): {
|
|
85
87
|
staged: number;
|
|
86
88
|
modified: number;
|
|
87
89
|
untracked: number;
|
|
@@ -115,6 +117,26 @@ function parseStatus(output: string): {
|
|
|
115
117
|
return { staged, modified, untracked };
|
|
116
118
|
}
|
|
117
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Parse `git rev-list --left-right --count HEAD...@{upstream}` output.
|
|
122
|
+
*
|
|
123
|
+
* The command returns two whitespace-separated integers: ahead then behind.
|
|
124
|
+
* Invalid or missing values are treated as `0`.
|
|
125
|
+
*
|
|
126
|
+
* @param output - Raw `git rev-list --left-right --count` output.
|
|
127
|
+
* @returns Parsed ahead and behind counts.
|
|
128
|
+
*/
|
|
129
|
+
export function parseGitAheadBehind(output: string): {
|
|
130
|
+
ahead: number;
|
|
131
|
+
behind: number;
|
|
132
|
+
} {
|
|
133
|
+
const parts = output.trim().split(/\s+/);
|
|
134
|
+
return {
|
|
135
|
+
ahead: parseInt(parts[0] ?? "0", 10) || 0,
|
|
136
|
+
behind: parseInt(parts[1] ?? "0", 10) || 0,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
118
140
|
// ---------------------------------------------------------------------------
|
|
119
141
|
// Public API
|
|
120
142
|
// ---------------------------------------------------------------------------
|
|
@@ -127,34 +149,45 @@ function parseStatus(output: string): {
|
|
|
127
149
|
* is not inside a git repository.
|
|
128
150
|
*
|
|
129
151
|
* @param cwd - The directory to query (can be a subdirectory of the repo).
|
|
152
|
+
* @param opts - Optional runtime overrides used by tests.
|
|
130
153
|
* @returns A {@link GitState} snapshot, or `null` if not in a git repo.
|
|
131
154
|
*/
|
|
132
|
-
export async function getGitState(
|
|
155
|
+
export async function getGitState(
|
|
156
|
+
cwd: string,
|
|
157
|
+
opts?: {
|
|
158
|
+
run?: (
|
|
159
|
+
args: string[],
|
|
160
|
+
cwd: string,
|
|
161
|
+
trim?: boolean,
|
|
162
|
+
) => Promise<string | null>;
|
|
163
|
+
},
|
|
164
|
+
): Promise<GitState | null> {
|
|
165
|
+
const exec = opts?.run ?? run;
|
|
166
|
+
|
|
133
167
|
// Check if we're in a repo and get the root
|
|
134
|
-
const root = await
|
|
168
|
+
const root = await exec(["rev-parse", "--show-toplevel"], cwd);
|
|
135
169
|
if (root === null) return null;
|
|
136
170
|
|
|
137
171
|
// Run remaining commands in parallel
|
|
138
|
-
const [branch, status, revList] = await Promise.all([
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
172
|
+
const [branch, upstream, status, revList] = await Promise.all([
|
|
173
|
+
exec(["branch", "--show-current"], cwd),
|
|
174
|
+
exec(
|
|
175
|
+
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
|
|
176
|
+
cwd,
|
|
177
|
+
),
|
|
178
|
+
exec(["status", "--porcelain"], cwd, false),
|
|
179
|
+
exec(["rev-list", "--left-right", "--count", "HEAD...@{upstream}"], cwd),
|
|
142
180
|
]);
|
|
143
181
|
|
|
144
|
-
const { staged, modified, untracked } =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
let behind = 0;
|
|
149
|
-
if (revList) {
|
|
150
|
-
const parts = revList.split(/\s+/);
|
|
151
|
-
ahead = parseInt(parts[0] ?? "0", 10) || 0;
|
|
152
|
-
behind = parseInt(parts[1] ?? "0", 10) || 0;
|
|
153
|
-
}
|
|
182
|
+
const { staged, modified, untracked } = parseGitStatus(status ?? "");
|
|
183
|
+
const { ahead, behind } = revList
|
|
184
|
+
? parseGitAheadBehind(revList)
|
|
185
|
+
: { ahead: 0, behind: 0 };
|
|
154
186
|
|
|
155
187
|
return {
|
|
156
188
|
root,
|
|
157
189
|
branch: branch ?? "",
|
|
190
|
+
upstream,
|
|
158
191
|
staged,
|
|
159
192
|
modified,
|
|
160
193
|
untracked,
|