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 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.5.0",
9
- "@cel-tui/core": "^0.5.0",
10
- "@cel-tui/types": "^0.5.0",
11
- "@mariozechner/pi-ai": "^0.65.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.6",
16
- "@types/bun": "latest",
17
- "lefthook": "^2.1.4",
18
- "prettier": "^3.8.1",
19
- "typescript": "^5.9.3",
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.10", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.10", "@biomejs/cli-darwin-x64": "2.4.10", "@biomejs/cli-linux-arm64": "2.4.10", "@biomejs/cli-linux-arm64-musl": "2.4.10", "@biomejs/cli-linux-x64": "2.4.10", "@biomejs/cli-linux-x64-musl": "2.4.10", "@biomejs/cli-win32-arm64": "2.4.10", "@biomejs/cli-win32-x64": "2.4.10" }, "bin": { "biome": "bin/biome" } }, "sha512-xxA3AphFQ1geij4JTHXv4EeSTda1IFn22ye9LdyVPoJU19fNVl0uzfEuhsfQ4Yue/0FaLs2/ccVi4UDiE7R30w=="],
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.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vuzzI1cWqDVzOMIkYyHbKqp+AkQq4K7k+UCXWpkYcY/HDn1UxdsbsfgtVpa40shem8Kax4TLDLlx8kMAecgqiw=="],
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.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-14fzASRo+BPotwp7nWULy2W5xeUyFnTaq1V13Etrrxkrih+ez/2QfgFm5Ehtf5vSjtgx/IJycMMpn5kPd5ZNaA=="],
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.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-7MH1CMW5uuxQ/s7FLST63qF8B3Hgu2HRdZ7tA1X1+mk+St4JOuIrqdhIBnnyqeyWJNI+Bww7Es5QZ0wIc1Cmkw=="],
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.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-WrJY6UuiSD/Dh+nwK2qOTu8kdMDlLV3dLMmychIghHPAysWFq1/DGC1pVZx8POE3ZkzKR3PUUnVrtZfMfaJjyQ=="],
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.10", "", { "os": "linux", "cpu": "x64" }, "sha512-tZLvEEi2u9Xu1zAqRjTcpIDGVtldigVvzug2fTuPG0ME/g8/mXpRPcNgLB22bGn6FvLJpHHnqLnwliOu8xjYrg=="],
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.10", "", { "os": "linux", "cpu": "x64" }, "sha512-kDTi3pI6PBN6CiczsWYOyP2zk0IJI08EWEQyDMQWW221rPaaEz6FvjLhnU07KMzLv8q3qSuoB93ua6inSQ55Tw=="],
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.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-umwQU6qPzH+ISTf/eHyJ/QoQnJs3V9Vpjz2OjZXe9MVBZ7prgGafMy7yYeRGnlmDAn87AKTF3Q6weLoMGpeqdQ=="],
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.10", "", { "os": "win32", "cpu": "x64" }, "sha512-aW/JU5GuyH4uxMrNYpoC2kjaHlyJGLgIa3XkhPEZI0uKhZhJZU8BuEyJmvgzSPQNGozBwWjC972RaNdcJ9KyJg=="],
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.5.0", "", { "dependencies": { "@cel-tui/core": "0.5.0", "@cel-tui/types": "0.5.0", "yoctomarkdown": "^0.1.0" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-lfCAjJeu7mQOVWTkEbSqO8LStKvZ4O//I6TJekVIJuA6k0Bf3UO+tTXm0QV4Pm2TS7JaudLiuhv4ZKdXhxKfhA=="],
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.5.0", "", { "dependencies": { "@cel-tui/types": "0.5.0", "get-east-asian-width": "^1.5.0" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-mIFwP+GUrjOEuDjhSxxnpZs95HfohgfueZfHHk3qTlcfh/Ari1c5MCpRILp60EnftaBuVjiff5iq0RWs6RpRHQ=="],
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.5.0", "", { "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-E+nPq7ZgMAtTeCQydz9JVzhLlAP3ah4ecHeoa99+DreeXmm61Yhy/9APO8m6GEzLIvGC4beZs1oK/7PBhfR9mg=="],
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.65.0", "", { "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-MsCsCHlHIlBYbg6jB2PJBeCNKbjzVZge7ddBNUJN2gsFY8sdjFh482+GB+r5Ou6k9Fnhi3nO779YDymo5+t89w=="],
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.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
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.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
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.4", "", { "optionalDependencies": { "lefthook-darwin-arm64": "2.1.4", "lefthook-darwin-x64": "2.1.4", "lefthook-freebsd-arm64": "2.1.4", "lefthook-freebsd-x64": "2.1.4", "lefthook-linux-arm64": "2.1.4", "lefthook-linux-x64": "2.1.4", "lefthook-openbsd-arm64": "2.1.4", "lefthook-openbsd-x64": "2.1.4", "lefthook-windows-arm64": "2.1.4", "lefthook-windows-x64": "2.1.4" }, "bin": { "lefthook": "bin/index.js" } }, "sha512-JNfJ5gAn0KADvJ1I6/xMcx70+/6TL6U9gqGkKvPw5RNMfatC7jIg0Evl97HN846xmfz959BV70l8r3QsBJk30w=="],
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-arm64": ["lefthook-darwin-arm64@2.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BUAAE9+rUrjr39a+wH/1zHmGrDdwUQ2Yq/z6BQbM/yUb9qtXBRcQ5eOXxApqWW177VhGBpX31aqIlfAZ5Q7wzw=="],
327
+ "lefthook-darwin-x64": ["lefthook-darwin-x64@2.1.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-AvtjYiW0BSGHBGrdvL313seUymrW9FxI+6JJwJ+ZSaa2sH81etrTB0wAwlH1L9VfFwK9+gWvatZBvLfF3L4fPw=="],
329
328
 
330
- "lefthook-darwin-x64": ["lefthook-darwin-x64@2.1.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-K1ncIMEe84fe+ss1hQNO7rIvqiKy2TJvTFpkypvqFodT7mJXZn7GLKYTIXdIuyPAYthRa9DwFnx5uMoHwD2F1Q=="],
329
+ "lefthook-freebsd-arm64": ["lefthook-freebsd-arm64@2.1.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-mXjJwe8jKGWGiBYUxfQY1ab3Nn5NhafqT9q3KJz8m5joGGQj4JD0cbWxF1nVBLBWsDGbWZRZunTCMGcIScT2bQ=="],
331
330
 
332
- "lefthook-freebsd-arm64": ["lefthook-freebsd-arm64@2.1.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-PVUhjOhVN71YaYsVdQyNbFZ4a2jFB2Tg5hKrrn9kaWpx64aLz/XivLjwr8sEuTaP1GRlEWBpW6Bhrcsyo39qFw=="],
331
+ "lefthook-freebsd-x64": ["lefthook-freebsd-x64@2.1.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-exD69dCjc1K45BxatDPGoH4NmEvgLKPm4kJLOWn1fTeHRKZwWiFPwnjknEoG2OemlCDHmCU++5X40kMEG0WBlA=="],
333
332
 
334
- "lefthook-freebsd-x64": ["lefthook-freebsd-x64@2.1.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ZWV9o/LeyWNEBoVO+BhLqxH3rGTba05nkm5NvMjEFSj7LbUNUDbQmupZwtHl1OMGJO66eZP0CalzRfUH6GhBxQ=="],
333
+ "lefthook-linux-arm64": ["lefthook-linux-arm64@2.1.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-57TDKC5ewWpsCLZQKIJMHumFEObYKVundmPpiWhX491hINRZYYOL/26yrnVnNcidThRzTiTC+HLcuplLcaXtbA=="],
335
334
 
336
- "lefthook-linux-arm64": ["lefthook-linux-arm64@2.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-iWN0pGnTjrIvNIcSI1vQBJXUbybTqJ5CLMniPA0olabMXQfPDrdMKVQe+mgdwHK+E3/Y0H0ZNL3lnOj6Sk6szA=="],
335
+ "lefthook-linux-x64": ["lefthook-linux-x64@2.1.5", "", { "os": "linux", "cpu": "x64" }, "sha512-bqK3LrAB5l5YaCaoHk6qRWlITrGWzP4FbwRxA31elbxjd0wgNWZ2Sn3zEfSEcxz442g7/PPkEwqqsTx0kSFzpg=="],
337
336
 
338
- "lefthook-linux-x64": ["lefthook-linux-x64@2.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-96bTBE/JdYgqWYAJDh+/e/0MaxJ25XTOAk7iy/fKoZ1ugf6S0W9bEFbnCFNooXOcxNVTan5xWKfcjJmPIKtsJA=="],
337
+ "lefthook-openbsd-arm64": ["lefthook-openbsd-arm64@2.1.5", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5aSwK7vV3A6t0w9PnxCMiVjQlcvopBP50BtmnnLnNJyAYHnFbZ0Baq5M0WkE9IsUkWSux0fe6fd0jDkuG711MA=="],
339
338
 
340
- "lefthook-openbsd-arm64": ["lefthook-openbsd-arm64@2.1.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-oYUoK6AIJNEr9lUSpIMj6g7sWzotvtc3ryw7yoOyQM6uqmEduw73URV/qGoUcm4nqqmR93ZalZwR2r3Gd61zvw=="],
339
+ "lefthook-openbsd-x64": ["lefthook-openbsd-x64@2.1.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Y+pPdDuENJ8qWnUgL02xxhpjblc0WnwXvWGfqnl3WZrAgHzQpwx3G6469RID/wlNVdHYAlw3a8UkFSMYsTzXvA=="],
341
340
 
342
- "lefthook-openbsd-x64": ["lefthook-openbsd-x64@2.1.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/Dv9Jcm68y9cggr1PhyUhOabBGP9+hzQPoiyOhKks7y9qrJl79A8XfG6LHekSuYc2VpiSu5wdnnrE1cj2nfTg=="],
341
+ "lefthook-windows-arm64": ["lefthook-windows-arm64@2.1.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-2PlcFBjTzJaMufw0c28kfhB/0zmaRCU0TRPPsil/HU2YNOExod4upPGLk9qjgsOmb2YVWFz6zq6u7+D1yqmzTQ=="],
343
342
 
344
- "lefthook-windows-arm64": ["lefthook-windows-arm64@2.1.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-hSww7z+QX4YMnw2lK7DMrs3+w7NtxksuMKOkCKGyxUAC/0m1LAICo0ZbtdDtZ7agxRQQQ/SEbzFRhU5ysNcbjA=="],
343
+ "lefthook-windows-x64": ["lefthook-windows-x64@2.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-yiAh8qxml6uqy10jDxOdN9fOQpyLxBFY1fgCEAhn7sVJYmJKRhjqSBwZX6LG5MQjzr29KStrIdw7TR3lf3rT7Q=="],
345
344
 
346
- "lefthook-windows-x64": ["lefthook-windows-x64@2.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-eE68LwnogxwcPgGsbVGPGxmghyMGmU9SdGwcc+uhGnUxPz1jL89oECMWJNc36zjVK24umNeDAzB5KA3lw1MuWw=="],
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.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
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@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
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.0",
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.5.0",
22
- "@cel-tui/core": "^0.5.0",
23
- "@cel-tui/types": "^0.5.0",
24
- "@mariozechner/pi-ai": "^0.65.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.6",
29
- "@types/bun": "latest",
30
- "lefthook": "^2.1.4",
31
- "prettier": "^3.8.1",
32
- "typescript": "^5.9.3"
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 ?? (await eventStream.result());
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 parseStatus(output: string): {
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(cwd: string): Promise<GitState | null> {
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 run(["rev-parse", "--show-toplevel"], cwd);
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
- run(["branch", "--show-current"], cwd),
140
- run(["status", "--porcelain"], cwd, false),
141
- run(["rev-list", "--left-right", "--count", "HEAD...@{upstream}"], cwd),
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 } = parseStatus(status ?? "");
145
-
146
- // Parse ahead/behind from rev-list output (format: "ahead\tbehind")
147
- let ahead = 0;
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,