mini-coder 0.5.1 → 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/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.1",
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/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
@@ -83,7 +83,7 @@ function hasTrackedChange(status: string): boolean {
83
83
  * @param output - Raw `git status --porcelain` output.
84
84
  * @returns Counts of staged, modified, and untracked files.
85
85
  */
86
- function parseStatus(output: string): {
86
+ export function parseGitStatus(output: string): {
87
87
  staged: number;
88
88
  modified: number;
89
89
  untracked: number;
@@ -117,6 +117,26 @@ function parseStatus(output: string): {
117
117
  return { staged, modified, untracked };
118
118
  }
119
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
+
120
140
  // ---------------------------------------------------------------------------
121
141
  // Public API
122
142
  // ---------------------------------------------------------------------------
@@ -129,34 +149,40 @@ function parseStatus(output: string): {
129
149
  * is not inside a git repository.
130
150
  *
131
151
  * @param cwd - The directory to query (can be a subdirectory of the repo).
152
+ * @param opts - Optional runtime overrides used by tests.
132
153
  * @returns A {@link GitState} snapshot, or `null` if not in a git repo.
133
154
  */
134
- 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
+
135
167
  // Check if we're in a repo and get the root
136
- const root = await run(["rev-parse", "--show-toplevel"], cwd);
168
+ const root = await exec(["rev-parse", "--show-toplevel"], cwd);
137
169
  if (root === null) return null;
138
170
 
139
171
  // Run remaining commands in parallel
140
172
  const [branch, upstream, status, revList] = await Promise.all([
141
- run(["branch", "--show-current"], cwd),
142
- run(
173
+ exec(["branch", "--show-current"], cwd),
174
+ exec(
143
175
  ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
144
176
  cwd,
145
177
  ),
146
- run(["status", "--porcelain"], cwd, false),
147
- run(["rev-list", "--left-right", "--count", "HEAD...@{upstream}"], cwd),
178
+ exec(["status", "--porcelain"], cwd, false),
179
+ exec(["rev-list", "--left-right", "--count", "HEAD...@{upstream}"], cwd),
148
180
  ]);
149
181
 
150
- const { staged, modified, untracked } = parseStatus(status ?? "");
151
-
152
- // Parse ahead/behind from rev-list output (format: "ahead\tbehind")
153
- let ahead = 0;
154
- let behind = 0;
155
- if (revList) {
156
- const parts = revList.split(/\s+/);
157
- ahead = parseInt(parts[0] ?? "0", 10) || 0;
158
- behind = parseInt(parts[1] ?? "0", 10) || 0;
159
- }
182
+ const { staged, modified, untracked } = parseGitStatus(status ?? "");
183
+ const { ahead, behind } = revList
184
+ ? parseGitAheadBehind(revList)
185
+ : { ahead: 0, behind: 0 };
160
186
 
161
187
  return {
162
188
  root,
package/src/index.ts CHANGED
@@ -28,6 +28,7 @@ import {
28
28
  resolveHeadlessPrompt,
29
29
  shouldUseHeadlessMode,
30
30
  } from "./cli.ts";
31
+ import { getErrorMessage } from "./errors.ts";
31
32
  import { type GitState, getGitState } from "./git.ts";
32
33
  import { canonicalizePath } from "./paths.ts";
33
34
  import {
@@ -56,6 +57,7 @@ import {
56
57
  truncateSessions,
57
58
  } from "./session.ts";
58
59
  import {
60
+ type CustomProvider,
59
61
  loadSettings,
60
62
  resolveStartupSettings,
61
63
  type UserSettings,
@@ -70,6 +72,7 @@ import {
70
72
  readImageTool,
71
73
  shellTool,
72
74
  } from "./tools.ts";
75
+ import { resolveAppVersionLabel } from "./version.ts";
73
76
 
74
77
  // ---------------------------------------------------------------------------
75
78
  // Constants
@@ -98,10 +101,6 @@ export const MAX_SESSIONS_PER_CWD = 20;
98
101
  /** Maximum raw prompt-history entries to retain globally. */
99
102
  export const MAX_PROMPT_HISTORY = 1_000;
100
103
 
101
- function getErrorMessage(error: unknown): string {
102
- return error instanceof Error ? error.message : String(error);
103
- }
104
-
105
104
  // ---------------------------------------------------------------------------
106
105
  // OAuth credential persistence
107
106
  // ---------------------------------------------------------------------------
@@ -211,6 +210,101 @@ async function discoverProviders(): Promise<DiscoveryResult> {
211
210
  return { providers, oauthCredentials };
212
211
  }
213
212
 
213
+ // ---------------------------------------------------------------------------
214
+ // Custom provider discovery
215
+ // ---------------------------------------------------------------------------
216
+
217
+ /** Timeout for custom provider model discovery requests. */
218
+ const CUSTOM_PROVIDER_TIMEOUT_MS = 3_000;
219
+
220
+ /** Default API key for custom providers that don't require authentication. */
221
+ const CUSTOM_PROVIDER_DEFAULT_KEY = "no-key";
222
+
223
+ /** Result of custom provider discovery. */
224
+ interface CustomDiscoveryResult {
225
+ /** Discovered models from all reachable custom providers. */
226
+ models: Model<"openai-completions">[];
227
+ /** Provider name → API key for discovered providers. */
228
+ providers: Map<string, string>;
229
+ /** Warning messages for unreachable or invalid providers. */
230
+ warnings: string[];
231
+ }
232
+
233
+ /**
234
+ * Discover models from user-configured OpenAI-compatible endpoints.
235
+ *
236
+ * Queries each provider's `/models` endpoint and constructs pi-ai Model
237
+ * objects from the response. Unreachable endpoints produce a warning
238
+ * instead of failing startup.
239
+ *
240
+ * @param customProviders - Configured custom provider entries.
241
+ * @param builtInProviderNames - Names of built-in providers (to detect collisions).
242
+ * @returns Discovered models, provider credentials, and warnings.
243
+ */
244
+ export async function discoverCustomProviders(
245
+ customProviders: readonly CustomProvider[],
246
+ builtInProviderNames: ReadonlySet<string>,
247
+ ): Promise<CustomDiscoveryResult> {
248
+ const models: Model<"openai-completions">[] = [];
249
+ const providers = new Map<string, string>();
250
+ const warnings: string[] = [];
251
+
252
+ for (const entry of customProviders) {
253
+ if (builtInProviderNames.has(entry.name)) {
254
+ warnings.push(
255
+ `Custom provider "${entry.name}" skipped: name conflicts with a built-in provider.`,
256
+ );
257
+ continue;
258
+ }
259
+
260
+ const apiKey = entry.apiKey ?? CUSTOM_PROVIDER_DEFAULT_KEY;
261
+ const modelsUrl = `${entry.baseUrl}/models`;
262
+
263
+ try {
264
+ const response = await fetch(modelsUrl, {
265
+ signal: AbortSignal.timeout(CUSTOM_PROVIDER_TIMEOUT_MS),
266
+ });
267
+
268
+ if (!response.ok) {
269
+ warnings.push(
270
+ `Custom provider "${entry.name}": ${response.status} ${response.statusText} (${modelsUrl})`,
271
+ );
272
+ continue;
273
+ }
274
+
275
+ const body = (await response.json()) as {
276
+ data?: { id: string }[];
277
+ };
278
+ const modelList = body.data ?? [];
279
+
280
+ for (const item of modelList) {
281
+ if (typeof item.id !== "string" || !item.id) continue;
282
+
283
+ models.push({
284
+ id: item.id,
285
+ name: item.id,
286
+ api: "openai-completions",
287
+ provider: entry.name,
288
+ baseUrl: entry.baseUrl,
289
+ reasoning: false,
290
+ input: ["text"],
291
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
292
+ contextWindow: 131072,
293
+ maxTokens: 8192,
294
+ });
295
+ }
296
+
297
+ providers.set(entry.name, apiKey);
298
+ } catch (error) {
299
+ warnings.push(
300
+ `Custom provider "${entry.name}": ${getErrorMessage(error)} (${modelsUrl})`,
301
+ );
302
+ }
303
+ }
304
+
305
+ return { models, providers, warnings };
306
+ }
307
+
214
308
  // ---------------------------------------------------------------------------
215
309
  // Model selection
216
310
  // ---------------------------------------------------------------------------
@@ -440,8 +534,12 @@ export interface AppState {
440
534
  plugins: LoadedPlugin[];
441
535
  /** Active theme (default + plugin overrides). */
442
536
  theme: Theme;
537
+ /** Version label shown in the empty conversation banner. */
538
+ versionLabel: string;
443
539
  /** Current git state (null if not in a repo). */
444
540
  git: GitState | null;
541
+ /** Optional git state loader override used by tests. */
542
+ loadGitState?: (cwd: string) => Promise<GitState | null>;
445
543
  /** Available provider credentials (provider → API key). */
446
544
  providers: Map<string, string>;
447
545
  /** OAuth credentials on disk. */
@@ -464,6 +562,10 @@ export interface AppState {
464
562
  showReasoning: boolean;
465
563
  /** Whether to show full (un-truncated) tool output. */
466
564
  verbose: boolean;
565
+ /** Models discovered from custom OpenAI-compatible providers. */
566
+ customModels: Model<string>[];
567
+ /** Warnings from startup (e.g. unreachable custom providers). */
568
+ startupWarnings: string[];
467
569
  }
468
570
 
469
571
  // ---------------------------------------------------------------------------
@@ -482,7 +584,21 @@ export async function init(): Promise<AppState> {
482
584
 
483
585
  // Load user settings and resolve startup defaults
484
586
  const settings = loadSettings(SETTINGS_PATH);
485
- const availableModels = listAvailableModels(providers);
587
+
588
+ // Discover custom providers from settings
589
+ const builtInProviderNames = new Set(providers.keys());
590
+ const customResult = await discoverCustomProviders(
591
+ settings.customProviders ?? [],
592
+ builtInProviderNames,
593
+ );
594
+
595
+ // Merge custom provider credentials
596
+ for (const [name, key] of customResult.providers) {
597
+ providers.set(name, key);
598
+ }
599
+
600
+ const builtInModels = listAvailableModels(providers);
601
+ const availableModels = [...builtInModels, ...customResult.models];
486
602
  const startup = resolveStartupSettings(
487
603
  settings,
488
604
  availableModels.map((model) => `${model.provider}/${model.id}`),
@@ -509,6 +625,7 @@ export async function init(): Promise<AppState> {
509
625
  skills: promptContext.skills,
510
626
  plugins: promptContext.plugins,
511
627
  theme: promptContext.theme,
628
+ versionLabel: resolveAppVersionLabel(),
512
629
  git: promptContext.git,
513
630
  providers,
514
631
  oauthCredentials,
@@ -521,6 +638,8 @@ export async function init(): Promise<AppState> {
521
638
  activeTurnPromise: null,
522
639
  showReasoning: startup.showReasoning,
523
640
  verbose: startup.verbose,
641
+ customModels: customResult.models,
642
+ startupWarnings: customResult.warnings,
524
643
  };
525
644
  }
526
645
 
@@ -593,7 +712,7 @@ export function ensureSession(
593
712
  * for, suitable for the `/model` selector.
594
713
  */
595
714
  export function getAvailableModels(state: AppState): Model<string>[] {
596
- return listAvailableModels(state.providers);
715
+ return [...listAvailableModels(state.providers), ...state.customModels];
597
716
  }
598
717
 
599
718
  /** Clean up resources on shutdown. */
package/src/prompt.ts CHANGED
@@ -192,14 +192,14 @@ const BASE_INSTRUCTIONS = `You are mini-coder, a coding agent running in the use
192
192
 
193
193
  # Role
194
194
 
195
- You are an autonomous, senior-level coding assistant. When the user gives a direction, proactively gather context, plan with the user, implement, and verify. Bias toward action: use planning first to clear any assumptions with the user, then implement the plan. Deliver working code, unless you are genuinely blocked.
195
+ You are an autonomous, senior-level coding assistant. When the user gives a direction, proactively gather context, plan with the user, implement, and verify. Bias toward action: plan briefly when needed to clear important assumptions, then continue into implementation. First identify the task contract: required files, names, interfaces, output format, and checks for success. Treat those details as part of correctness, not as polish. Deliver working code, unless you are genuinely blocked.
196
196
 
197
197
  # Tools
198
198
 
199
199
  You have these core tools:
200
200
 
201
- - \`shell\` — run commands in the user's shell. Use this to explore the codebase (rg, find, ls, cat), run tests, build, git, and any other command. Prefer \`rg\` over \`grep\` for speed.
202
- - \`edit\` — make exact-text replacements in files. Provide the file path, the exact text to find, and the replacement text. The old text must match exactly one location in the file. To create a new file, use an empty old text and the full file content as new text.
201
+ - \`shell\` — run commands in the user's shell. Use this to explore the codebase, read tests/verifiers/examples, inspect required outputs, and run targeted checks, builds, or git commands. Prefer \`rg\` over \`grep\` for speed.
202
+ - \`edit\` — make exact-text replacements in files. Provide the file path, the exact text to find, and the replacement text. The old text must match exactly one location in the file. To create a new file, use an empty old text and the full file content as new text. Use this to write the exact final file content the task requires.
203
203
 
204
204
  You may also have additional tools provided by plugins. Use them when they match the task.
205
205
 
@@ -208,7 +208,7 @@ Workflow: **inspect with shell → mutate with edit → verify with shell**.
208
208
  # Code quality
209
209
 
210
210
  - Conform to the codebase's existing conventions: patterns, naming, formatting, language idioms.
211
- - Write correct, clear, minimal code. Don't over-engineer, don't add abstractions for hypothetical futures.
211
+ - Write correct, clear, minimal code. Prefer the simplest solution that satisfies the task's checks exactly. Don't over-engineer, don't add abstractions for hypothetical futures.
212
212
  - Reuse before creating. Search for existing helpers before writing new ones.
213
213
  - Tight error handling: no broad try/catch, no silent failures, no swallowed errors.
214
214
  - Keep type safety. Avoid \`any\` casts. Use proper types and guards.
@@ -224,6 +224,7 @@ Workflow: **inspect with shell → mutate with edit → verify with shell**.
224
224
  # Exploring the codebase
225
225
 
226
226
  - Think first: before any tool call, decide all files and information you need.
227
+ - Early in the task, look for acceptance criteria in tests, verifier scripts, eval scripts, examples, and expected-output files. Do not rely on the task text alone when machine-checkable criteria are available.
227
228
  - Batch reads: if you need multiple files, read them together in parallel rather than one at a time.
228
229
  - Only make sequential calls when a later call genuinely depends on an earlier result.
229
230
 
@@ -238,7 +239,9 @@ Workflow: **inspect with shell → mutate with edit → verify with shell**.
238
239
  # Persistence
239
240
 
240
241
  - Carry work through to completion within the current turn. Don't stop at analysis or partial fixes.
242
+ - Once the contract is clear, create the required artifact early, then iterate and improve it. Do not spend most of the turn exploring.
241
243
  - If you encounter an error, diagnose and fix it rather than reporting it and stopping.
244
+ - Before concluding, run the smallest targeted verification that checks the exact contract: required files exist, names and signatures match, outputs are in the required format, and no forbidden extra artifacts were left behind.
242
245
  - Avoid excessive looping: if you're re-reading or re-editing the same files without progress, stop and ask the user.`;
243
246
 
244
247
  // ---------------------------------------------------------------------------