@heyamiko/amiko-cli 0.4.9 → 0.4.11

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
@@ -19,6 +19,7 @@
19
19
  "@types/react-dom": "^18.2.0",
20
20
  "tsx": "^4.7.0",
21
21
  "typescript": "^5.4.0",
22
+ "vitest": "^4.1.3",
22
23
  },
23
24
  },
24
25
  },
@@ -97,6 +98,12 @@
97
98
 
98
99
  "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="],
99
100
 
101
+ "@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
102
+
103
+ "@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
104
+
105
+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
106
+
100
107
  "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
101
108
 
102
109
  "@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="],
@@ -153,6 +160,8 @@
153
160
 
154
161
  "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "5.1.2", "string-width-cjs": "npm:string-width@4.2.3", "strip-ansi": "7.1.2", "strip-ansi-cjs": "npm:strip-ansi@6.0.1", "wrap-ansi": "8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
155
162
 
163
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
164
+
156
165
  "@mariozechner/pi-agent-core": ["@mariozechner/pi-agent-core@0.50.1", "", { "dependencies": { "@mariozechner/pi-ai": "0.50.1", "@mariozechner/pi-tui": "0.50.1" } }, "sha512-rW/CwANMGjqXcDvOT09ljHeNxfPHp/1hWamJrk9JamzkqVS+UHrFTJdc5qPv+O0naNDRUGBr6woer22C6F8BOA=="],
157
166
 
158
167
  "@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.50.1", "", { "dependencies": { "@anthropic-ai/sdk": "0.71.2", "@aws-sdk/client-bedrock-runtime": "3.975.0", "@google/genai": "1.34.0", "@mistralai/mistralai": "1.10.0", "@sinclair/typebox": "0.34.48", "ajv": "8.17.1", "ajv-formats": "3.0.1", "chalk": "5.6.2", "openai": "6.10.0", "partial-json": "0.1.7", "proxy-agent": "6.5.0", "undici": "7.19.2", "zod-to-json-schema": "3.25.1" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-t8qUHHqz3tgK4r3f/msRKK2QbhvlDjBCjOJlTn7iJDwVAWABO8EYwf0BzkB0RGrGkiIOKhDwEVbB4jD3VxaKnA=="],
@@ -161,8 +170,44 @@
161
170
 
162
171
  "@mistralai/mistralai": ["@mistralai/mistralai@1.10.0", "", { "dependencies": { "zod": "3.25.76", "zod-to-json-schema": "3.25.1" } }, "sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg=="],
163
172
 
173
+ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ=="],
174
+
175
+ "@oxc-project/types": ["@oxc-project/types@0.123.0", "", {}, "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew=="],
176
+
164
177
  "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
165
178
 
179
+ "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.13", "", { "os": "android", "cpu": "arm64" }, "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g=="],
180
+
181
+ "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA=="],
182
+
183
+ "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug=="],
184
+
185
+ "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.13", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA=="],
186
+
187
+ "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm" }, "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw=="],
188
+
189
+ "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg=="],
190
+
191
+ "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA=="],
192
+
193
+ "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "ppc64" }, "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ=="],
194
+
195
+ "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "s390x" }, "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg=="],
196
+
197
+ "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA=="],
198
+
199
+ "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w=="],
200
+
201
+ "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.13", "", { "os": "none", "cpu": "arm64" }, "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w=="],
202
+
203
+ "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.13", "", { "dependencies": { "@emnapi/core": "1.9.1", "@emnapi/runtime": "1.9.1", "@napi-rs/wasm-runtime": "^1.1.2" }, "cpu": "none" }, "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g=="],
204
+
205
+ "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ=="],
206
+
207
+ "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "x64" }, "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ=="],
208
+
209
+ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.13", "", {}, "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA=="],
210
+
166
211
  "@sinclair/typebox": ["@sinclair/typebox@0.34.48", "", {}, "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA=="],
167
212
 
168
213
  "@smithy/abort-controller": ["@smithy/abort-controller@4.2.8", "", { "dependencies": { "@smithy/types": "4.12.0", "tslib": "2.8.1" } }, "sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw=="],
@@ -255,8 +300,18 @@
255
300
 
256
301
  "@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="],
257
302
 
303
+ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
304
+
258
305
  "@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="],
259
306
 
307
+ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
308
+
309
+ "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
310
+
311
+ "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
312
+
313
+ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
314
+
260
315
  "@types/mime-types": ["@types/mime-types@2.1.4", "", {}, "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w=="],
261
316
 
262
317
  "@types/node": ["@types/node@20.19.30", "", { "dependencies": { "undici-types": "6.21.0" } }, "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g=="],
@@ -267,6 +322,20 @@
267
322
 
268
323
  "@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "18.3.27" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="],
269
324
 
325
+ "@vitest/expect": ["@vitest/expect@4.1.3", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.3", "@vitest/utils": "4.1.3", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-CW8Q9KMtXDGHj0vCsqui0M5KqRsu0zm0GNDW7Gd3U7nZ2RFpPKSCpeCXoT+/+5zr1TNlsoQRDEz+LzZUyq6gnQ=="],
326
+
327
+ "@vitest/mocker": ["@vitest/mocker@4.1.3", "", { "dependencies": { "@vitest/spy": "4.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-XN3TrycitDQSzGRnec/YWgoofkYRhouyVQj4YNsJ5r/STCUFqMrP4+oxEv3e7ZbLi4og5kIHrZwekDJgw6hcjw=="],
328
+
329
+ "@vitest/pretty-format": ["@vitest/pretty-format@4.1.3", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-hYqqwuMbpkkBodpRh4k4cQSOELxXky1NfMmQvOfKvV8zQHz8x8Dla+2wzElkMkBvSAJX5TRGHJAQvK0TcOafwg=="],
330
+
331
+ "@vitest/runner": ["@vitest/runner@4.1.3", "", { "dependencies": { "@vitest/utils": "4.1.3", "pathe": "^2.0.3" } }, "sha512-VwgOz5MmT0KhlUj40h02LWDpUBVpflZ/b7xZFA25F29AJzIrE+SMuwzFf0b7t4EXdwRNX61C3B6auIXQTR3ttA=="],
332
+
333
+ "@vitest/snapshot": ["@vitest/snapshot@4.1.3", "", { "dependencies": { "@vitest/pretty-format": "4.1.3", "@vitest/utils": "4.1.3", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-9l+k/J9KG5wPJDX9BcFFzhhwNjwkRb8RsnYhaT1vPY7OufxmQFc9sZzScRCPTiETzl37mrIWVY9zxzmdVeJwDQ=="],
334
+
335
+ "@vitest/spy": ["@vitest/spy@4.1.3", "", {}, "sha512-ujj5Uwxagg4XUIfAUyRQxAg631BP6e9joRiN99mr48Bg9fRs+5mdUElhOoZ6rP5mBr8Bs3lmrREnkrQWkrsTCw=="],
336
+
337
+ "@vitest/utils": ["@vitest/utils@4.1.3", "", { "dependencies": { "@vitest/pretty-format": "4.1.3", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-Pc/Oexse/khOWsGB+w3q4yzA4te7W4gpZZAvk+fr8qXfTURZUMj5i7kuxsNK5mP/dEB6ao3jfr0rs17fHhbHdw=="],
338
+
270
339
  "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
271
340
 
272
341
  "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "3.1.3", "fast-uri": "3.1.0", "json-schema-traverse": "1.0.0", "require-from-string": "2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
@@ -281,6 +350,8 @@
281
350
 
282
351
  "arr-rotate": ["arr-rotate@1.0.0", "", {}, "sha512-yOzOZcR9Tn7enTF66bqKorGGH0F36vcPaSWg8fO0c0UYb3LX3VMXj5ZxEqQLNOecAhlRJ7wYZja5i4jTlnbIfQ=="],
283
352
 
353
+ "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
354
+
284
355
  "ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="],
285
356
 
286
357
  "auto-bind": ["auto-bind@5.0.1", "", {}, "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg=="],
@@ -299,6 +370,8 @@
299
370
 
300
371
  "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
301
372
 
373
+ "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
374
+
302
375
  "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
303
376
 
304
377
  "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
@@ -315,6 +388,8 @@
315
388
 
316
389
  "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
317
390
 
391
+ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
392
+
318
393
  "convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
319
394
 
320
395
  "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "3.1.1", "shebang-command": "2.0.0", "which": "2.0.2" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
@@ -327,12 +402,16 @@
327
402
 
328
403
  "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=="],
329
404
 
405
+ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
406
+
330
407
  "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
331
408
 
332
409
  "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
333
410
 
334
411
  "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
335
412
 
413
+ "es-module-lexer": ["es-module-lexer@2.0.0", "", {}, "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw=="],
414
+
336
415
  "esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
337
416
 
338
417
  "escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
@@ -343,8 +422,12 @@
343
422
 
344
423
  "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
345
424
 
425
+ "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
426
+
346
427
  "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
347
428
 
429
+ "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
430
+
348
431
  "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
349
432
 
350
433
  "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
@@ -353,6 +436,8 @@
353
436
 
354
437
  "fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "2.1.2" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="],
355
438
 
439
+ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
440
+
356
441
  "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "3.3.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
357
442
 
358
443
  "figures": ["figures@5.0.0", "", { "dependencies": { "escape-string-regexp": "5.0.0", "is-unicode-supported": "1.3.0" } }, "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg=="],
@@ -419,6 +504,30 @@
419
504
 
420
505
  "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "2.0.1", "safe-buffer": "5.2.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
421
506
 
507
+ "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
508
+
509
+ "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
510
+
511
+ "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
512
+
513
+ "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
514
+
515
+ "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
516
+
517
+ "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
518
+
519
+ "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
520
+
521
+ "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
522
+
523
+ "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
524
+
525
+ "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
526
+
527
+ "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
528
+
529
+ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
530
+
422
531
  "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
423
532
 
424
533
  "lodash.isequal": ["lodash.isequal@4.5.0", "", {}, "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="],
@@ -427,6 +536,8 @@
427
536
 
428
537
  "lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
429
538
 
539
+ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
540
+
430
541
  "marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="],
431
542
 
432
543
  "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
@@ -441,12 +552,16 @@
441
552
 
442
553
  "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
443
554
 
555
+ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
556
+
444
557
  "netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],
445
558
 
446
559
  "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
447
560
 
448
561
  "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "4.0.1", "fetch-blob": "3.2.0", "formdata-polyfill": "4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
449
562
 
563
+ "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
564
+
450
565
  "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
451
566
 
452
567
  "openai": ["openai@6.10.0", "", { "optionalDependencies": { "ws": "8.19.0", "zod": "3.25.76" }, "bin": { "openai": "bin/cli" } }, "sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A=="],
@@ -465,6 +580,14 @@
465
580
 
466
581
  "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "10.4.3", "minipass": "7.1.2" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
467
582
 
583
+ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
584
+
585
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
586
+
587
+ "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
588
+
589
+ "postcss": ["postcss@8.5.9", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw=="],
590
+
468
591
  "proxy-agent": ["proxy-agent@6.5.0", "", { "dependencies": { "agent-base": "7.1.4", "debug": "4.4.3", "http-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.6", "lru-cache": "7.18.3", "pac-proxy-agent": "7.2.0", "proxy-from-env": "1.1.0", "socks-proxy-agent": "8.0.5" } }, "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A=="],
469
592
 
470
593
  "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
@@ -483,6 +606,8 @@
483
606
 
484
607
  "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "10.5.0" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="],
485
608
 
609
+ "rolldown": ["rolldown@1.0.0-rc.13", "", { "dependencies": { "@oxc-project/types": "=0.123.0", "@rolldown/pluginutils": "1.0.0-rc.13" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-x64": "1.0.0-rc.13", "@rolldown/binding-freebsd-x64": "1.0.0-rc.13", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw=="],
610
+
486
611
  "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
487
612
 
488
613
  "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "1.4.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
@@ -491,6 +616,8 @@
491
616
 
492
617
  "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
493
618
 
619
+ "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
620
+
494
621
  "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
495
622
 
496
623
  "slice-ansi": ["slice-ansi@6.0.0", "", { "dependencies": { "ansi-styles": "6.2.3", "is-fullwidth-code-point": "4.0.0" } }, "sha512-6bn4hRfkTvDfUoEQYkERg0BVF1D0vrX9HEkMl08uDiNWvVvjylLHvZFZWkDo6wjT8tUctbYl1nCOuE66ZTaUtA=="],
@@ -503,8 +630,14 @@
503
630
 
504
631
  "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
505
632
 
633
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
634
+
506
635
  "stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
507
636
 
637
+ "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
638
+
639
+ "std-env": ["std-env@4.0.0", "", {}, "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ=="],
640
+
508
641
  "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "0.2.0", "emoji-regex": "9.2.2", "strip-ansi": "7.1.2" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
509
642
 
510
643
  "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "8.0.0", "is-fullwidth-code-point": "3.0.0", "strip-ansi": "6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
@@ -515,6 +648,14 @@
515
648
 
516
649
  "strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="],
517
650
 
651
+ "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
652
+
653
+ "tinyexec": ["tinyexec@1.1.1", "", {}, "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg=="],
654
+
655
+ "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
656
+
657
+ "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="],
658
+
518
659
  "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="],
519
660
 
520
661
  "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
@@ -529,10 +670,16 @@
529
670
 
530
671
  "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
531
672
 
673
+ "vite": ["vite@8.0.7", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.13", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw=="],
674
+
675
+ "vitest": ["vitest@4.1.3", "", { "dependencies": { "@vitest/expect": "4.1.3", "@vitest/mocker": "4.1.3", "@vitest/pretty-format": "4.1.3", "@vitest/runner": "4.1.3", "@vitest/snapshot": "4.1.3", "@vitest/spy": "4.1.3", "@vitest/utils": "4.1.3", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.3", "@vitest/browser-preview": "4.1.3", "@vitest/browser-webdriverio": "4.1.3", "@vitest/coverage-istanbul": "4.1.3", "@vitest/coverage-v8": "4.1.3", "@vitest/ui": "4.1.3", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-DBc4Tx0MPNsqb9isoyOq00lHftVx/KIU44QOm2q59npZyLUkENn8TMFsuzuO+4U2FUa9rgbbPt3udrP25GcjXw=="],
676
+
532
677
  "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
533
678
 
534
679
  "which": ["which@2.0.2", "", { "dependencies": { "isexe": "2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
535
680
 
681
+ "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
682
+
536
683
  "widest-line": ["widest-line@4.0.1", "", { "dependencies": { "string-width": "5.1.2" } }, "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig=="],
537
684
 
538
685
  "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "6.2.3", "string-width": "5.1.2", "strip-ansi": "7.1.2" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
@@ -0,0 +1,74 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { execFile } from "node:child_process";
3
+ import { join, dirname } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const CLI_PATH = join(__dirname, "..", "..", "dist", "cli.js");
7
+ function runCli(args = [], stdin) {
8
+ return new Promise((resolve) => {
9
+ const child = execFile("node", [CLI_PATH, ...args], {
10
+ timeout: 10000,
11
+ env: { ...process.env, HOME: "/tmp/amiko-cli-test" },
12
+ }, (error, stdout, stderr) => {
13
+ resolve({
14
+ stdout: stdout || "",
15
+ stderr: stderr || "",
16
+ code: error?.code === "ETIMEDOUT" ? 0 : error?.status ?? 0,
17
+ });
18
+ });
19
+ if (stdin !== undefined) {
20
+ child.stdin?.write(stdin);
21
+ }
22
+ child.stdin?.end();
23
+ });
24
+ }
25
+ describe("amiko-cli non-TTY behavior", () => {
26
+ it("does not crash with RangeError in piped mode", async () => {
27
+ const result = await runCli();
28
+ const combined = result.stdout + result.stderr;
29
+ expect(combined).not.toContain("RangeError");
30
+ expect(combined).not.toContain("Invalid count value");
31
+ });
32
+ it("enters headless mode when stdin is not a TTY", async () => {
33
+ const result = await runCli([], "/help\n");
34
+ const combined = result.stdout + result.stderr;
35
+ expect(combined).toContain("headless");
36
+ expect(combined).toContain("Commands:");
37
+ });
38
+ it("--headless flag is recognized", async () => {
39
+ const result = await runCli(["--headless"], "/help\n");
40
+ const combined = result.stdout + result.stderr;
41
+ expect(combined).toContain("headless");
42
+ expect(combined).toContain("Commands:");
43
+ });
44
+ it("headless /help lists available commands", async () => {
45
+ const result = await runCli([], "/help\n");
46
+ expect(result.stdout).toContain("/exit");
47
+ expect(result.stdout).toContain("/memory");
48
+ expect(result.stdout).toContain("/model");
49
+ expect(result.stdout).toContain("/search");
50
+ });
51
+ });
52
+ describe("String.repeat patch", () => {
53
+ it("clamps negative values to empty string", () => {
54
+ const origRepeat = String.prototype.repeat;
55
+ String.prototype.repeat = function (count) {
56
+ return origRepeat.call(this, Math.max(0, Math.floor(count)));
57
+ };
58
+ try {
59
+ expect("─".repeat(-2)).toBe("");
60
+ expect("─".repeat(-1)).toBe("");
61
+ expect("─".repeat(0)).toBe("");
62
+ expect("─".repeat(1)).toBe("─");
63
+ expect("─".repeat(3)).toBe("───");
64
+ expect("x".repeat(2.9)).toBe("xx");
65
+ }
66
+ finally {
67
+ String.prototype.repeat = origRepeat;
68
+ }
69
+ });
70
+ it("original String.repeat throws on negative values", () => {
71
+ expect(() => "x".repeat(-2)).toThrow(RangeError);
72
+ expect(() => "x".repeat(-1)).toThrow(RangeError);
73
+ });
74
+ });
package/dist/cli.js CHANGED
@@ -6,11 +6,15 @@ import { initWorkspace } from "./workspace.js";
6
6
  import { createSessionFile } from "./session.js";
7
7
  import { App } from "./app.js";
8
8
  import { loadConfigFile } from "./configFile.js";
9
+ import { runHeadless } from "./headless.js";
9
10
  function parseArgs(argv) {
10
11
  const overrides = {};
11
12
  for (let i = 0; i < argv.length; i += 1) {
12
13
  const arg = argv[i];
13
14
  switch (arg) {
15
+ case "--headless":
16
+ overrides.headless = true;
17
+ break;
14
18
  case "--workspace":
15
19
  case "-w":
16
20
  overrides.workspacePath = argv[i + 1];
@@ -61,44 +65,26 @@ function parseArgs(argv) {
61
65
  return overrides;
62
66
  }
63
67
  async function main() {
64
- const argv = process.argv.slice(2);
65
- // Non-TTY: Ink cannot render without a real terminal.
66
- // Print version/help as plain text and exit.
67
- if (!process.stdout.isTTY) {
68
- const flag = argv[0];
69
- if (flag === "-h" || flag === "--help") {
70
- console.log("amiko-cli — interactive AI agent (requires a terminal)");
71
- console.log("Usage: amiko [options]");
72
- console.log(" --workspace, -w <path> Workspace directory");
73
- console.log(" --model <provider/model> Model override");
74
- console.log(" --session <id> Resume session");
75
- console.log(" --thinking <level> off|minimal|low|medium|high|xhigh");
76
- process.exit(0);
77
- }
78
- if (flag === "-v" || flag === "--version") {
79
- const { readFileSync } = await import("node:fs");
80
- const { fileURLToPath } = await import("node:url");
81
- const { dirname, join } = await import("node:path");
82
- try {
83
- const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
84
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
85
- console.log(pkg.version);
86
- }
87
- catch {
88
- console.log("unknown");
89
- }
90
- process.exit(0);
91
- }
92
- console.error("amiko-cli requires an interactive terminal (TTY). Cannot render UI in piped/non-TTY mode.");
93
- process.exit(1);
94
- }
68
+ // Ink's render-border.js calls box.top.repeat(contentWidth) where
69
+ // contentWidth = width - 2. When yoga computes a zero-width node (common
70
+ // in non-TTY / piped environments), contentWidth goes negative and
71
+ // String.repeat() throws. Patch String.repeat to clamp to 0.
72
+ const origRepeat = String.prototype.repeat;
73
+ String.prototype.repeat = function (count) {
74
+ return origRepeat.call(this, Math.max(0, Math.floor(count)));
75
+ };
95
76
  const config = loadConfig();
96
- const overrides = parseArgs(argv);
77
+ const overrides = parseArgs(process.argv.slice(2));
97
78
  const finalConfig = { ...config, ...overrides };
98
79
  const workspace = await initWorkspace(finalConfig.workspacePath);
99
80
  const persisted = await loadConfigFile(workspace.root);
100
81
  const mergedConfig = { ...finalConfig, ...persisted, ...overrides };
101
82
  const sessionFile = await createSessionFile(workspace.sessionsDir, finalConfig.sessionId);
83
+ // Auto-detect non-TTY or explicit --headless flag
84
+ if (overrides.headless || !process.stdout.isTTY) {
85
+ await runHeadless(mergedConfig, workspace, sessionFile.path);
86
+ return;
87
+ }
102
88
  render(_jsx(App, { config: mergedConfig, workspace: workspace, sessionPath: sessionFile.path }));
103
89
  }
104
90
  main().catch((error) => {
@@ -0,0 +1,218 @@
1
+ import { createInterface } from "node:readline";
2
+ import { parseCommand } from "./commands.js";
3
+ import { buildPrompt } from "./prompt.js";
4
+ import { appendSession } from "./session.js";
5
+ import { readWorkspaceFiles } from "./workspace.js";
6
+ import { createPiAgent } from "./agent/piAgent.js";
7
+ import { qmdSearch, qmdGet, qmdCollectionAdd, qmdEmbed } from "./memory/qmd.js";
8
+ import { saveConfigFile } from "./configFile.js";
9
+ import { getModels, getProviders } from "@mariozechner/pi-ai";
10
+ export async function runHeadless(config, workspace, sessionPath) {
11
+ const agent = await createPiAgent(config);
12
+ let currentModel = config.model
13
+ ?? (config.modelProvider && config.modelId ? `${config.modelProvider}/${config.modelId}` : "auto");
14
+ if (currentModel === "auto") {
15
+ const value = agent.getCurrentModel?.();
16
+ if (value)
17
+ currentModel = value;
18
+ }
19
+ if (agent.onEvent) {
20
+ agent.onEvent((event) => {
21
+ if (event?.type === "tool_execution_start") {
22
+ const lines = [`[tool] ${event.toolName} start`];
23
+ if (event.args?.command)
24
+ lines.push(` command: ${event.args.command}`);
25
+ console.log(lines.join("\n"));
26
+ }
27
+ if (event?.type === "tool_execution_end") {
28
+ const resultText = event.result?.content
29
+ ? event.result.content.map((c) => (c.text ? c.text : "")).join("\n")
30
+ : "";
31
+ const summary = resultText.trim() || "(no output)";
32
+ console.log(`[tool] ${event.toolName} done\n${summary}`);
33
+ }
34
+ });
35
+ }
36
+ console.log(`amiko-cli (headless) | model: ${currentModel} | workspace: ${workspace.root}`);
37
+ console.log("Type a message or /command. Press Ctrl+D to exit.");
38
+ const rl = createInterface({
39
+ input: process.stdin,
40
+ output: process.stdout,
41
+ prompt: "> ",
42
+ terminal: false,
43
+ });
44
+ rl.prompt();
45
+ for await (const line of rl) {
46
+ const trimmed = line.trim();
47
+ if (!trimmed) {
48
+ rl.prompt();
49
+ continue;
50
+ }
51
+ const command = parseCommand(trimmed);
52
+ if (command) {
53
+ await handleCommand(command.name, command.args, {
54
+ config, workspace, sessionPath, agent, currentModel,
55
+ setModel: (m) => { currentModel = m; },
56
+ });
57
+ rl.prompt();
58
+ continue;
59
+ }
60
+ console.log(`[user] ${trimmed}`);
61
+ await appendSession(sessionPath, "user", trimmed);
62
+ const workspaceData = await readWorkspaceFiles(workspace);
63
+ let hits = [];
64
+ if (config.qmdEnabled) {
65
+ hits = await qmdSearch({
66
+ qmdBin: config.qmdBin,
67
+ query: trimmed,
68
+ limit: config.qmdLimit,
69
+ collection: config.qmdCollection,
70
+ });
71
+ }
72
+ if (config.qmdFull && hits.length > 0) {
73
+ const expanded = [];
74
+ for (const hit of hits) {
75
+ const docId = hit.path || hit.id;
76
+ if (!docId) {
77
+ expanded.push(hit);
78
+ continue;
79
+ }
80
+ const text = await qmdGet({ qmdBin: config.qmdBin, docId, full: true });
81
+ expanded.push({ ...hit, snippet: text || hit.snippet });
82
+ }
83
+ hits = expanded;
84
+ }
85
+ const prompt = buildPrompt({
86
+ identity: workspaceData.identity,
87
+ personality: workspaceData.personality,
88
+ memory: workspaceData.memory,
89
+ hits,
90
+ });
91
+ let assistantText = "";
92
+ try {
93
+ for await (const chunk of agent.streamReply({ prompt, userMessage: trimmed })) {
94
+ process.stdout.write(chunk);
95
+ assistantText += chunk;
96
+ }
97
+ }
98
+ catch (error) {
99
+ const message = error.message || "unknown error";
100
+ assistantText += `\n[error] ${message}\n`;
101
+ console.error(`[error] ${message}`);
102
+ }
103
+ if (!assistantText.endsWith("\n"))
104
+ process.stdout.write("\n");
105
+ if (assistantText) {
106
+ await appendSession(sessionPath, "assistant", assistantText);
107
+ }
108
+ rl.prompt();
109
+ }
110
+ process.exit(0);
111
+ }
112
+ async function handleCommand(name, args, ctx) {
113
+ switch (name) {
114
+ case "exit":
115
+ process.exit(0);
116
+ case "help":
117
+ console.log("Commands: /help /exit /search <query> /memory /session /plan /identity /personality /index [collection] /model [provider[/id]]");
118
+ return;
119
+ case "memory": {
120
+ const data = await readWorkspaceFiles(ctx.workspace);
121
+ console.log(`MEMORY.md:\n\n${data.memory.trim() || "(empty)"}`);
122
+ return;
123
+ }
124
+ case "session":
125
+ console.log(`Session file: ${ctx.sessionPath}`);
126
+ return;
127
+ case "plan":
128
+ console.log("Plan file: PLAN.md");
129
+ return;
130
+ case "identity": {
131
+ const data = await readWorkspaceFiles(ctx.workspace);
132
+ console.log(`IDENTITY.md:\n\n${data.identity.trim() || "(empty)"}`);
133
+ return;
134
+ }
135
+ case "personality": {
136
+ const data = await readWorkspaceFiles(ctx.workspace);
137
+ console.log(`PERSONALITY.md:\n\n${data.personality.trim() || "(empty)"}`);
138
+ return;
139
+ }
140
+ case "index": {
141
+ if (!ctx.config.qmdEnabled) {
142
+ console.log("QMD is disabled.");
143
+ return;
144
+ }
145
+ const collName = args || ctx.config.qmdCollection || "amiko";
146
+ const added = await qmdCollectionAdd({ qmdBin: ctx.config.qmdBin, name: collName, path: ctx.workspace.root });
147
+ if (!added) {
148
+ console.log("Failed to add QMD collection.");
149
+ return;
150
+ }
151
+ const embedded = await qmdEmbed({ qmdBin: ctx.config.qmdBin, collection: collName });
152
+ console.log(embedded ? `Indexed QMD collection "${collName}".` : `Collection "${collName}" added, but embedding failed.`);
153
+ return;
154
+ }
155
+ case "search": {
156
+ if (!args) {
157
+ console.log("Usage: /search <query>");
158
+ return;
159
+ }
160
+ if (!ctx.config.qmdEnabled) {
161
+ console.log("QMD is disabled.");
162
+ return;
163
+ }
164
+ const hits = await qmdSearch({ qmdBin: ctx.config.qmdBin, query: args, limit: ctx.config.qmdLimit, collection: ctx.config.qmdCollection });
165
+ if (hits.length === 0) {
166
+ console.log("No memory hits.");
167
+ return;
168
+ }
169
+ const formatted = hits.map((hit, i) => {
170
+ const label = hit.title || hit.path || hit.id;
171
+ const score = hit.score ? ` (${hit.score.toFixed(2)})` : "";
172
+ return `${i + 1}. ${label}${score}`;
173
+ }).join("\n");
174
+ console.log(formatted);
175
+ return;
176
+ }
177
+ case "model": {
178
+ if (!args) {
179
+ const providers = getProviders().sort();
180
+ console.log(`Current model: ${ctx.currentModel}\nProviders:\n${providers.map((p, i) => ` ${i + 1}. ${p}`).join("\n")}`);
181
+ return;
182
+ }
183
+ const slashParts = args.includes("/") ? args.split("/") : [];
184
+ let provider = args.split(" ")[0];
185
+ let modelId = args.split(" ")[1];
186
+ if (slashParts.length >= 2) {
187
+ provider = slashParts[0]?.trim();
188
+ modelId = slashParts.slice(1).join("/").trim();
189
+ }
190
+ if (provider && !modelId) {
191
+ const models = getModels(provider);
192
+ if (models.length === 0) {
193
+ console.log(`Unknown provider: ${provider}`);
194
+ return;
195
+ }
196
+ console.log(`Models for ${provider}:\n${models.map((m) => m.id).sort().join("\n")}`);
197
+ return;
198
+ }
199
+ if (!provider || !modelId) {
200
+ console.log("Usage: /model <provider>/<modelId>");
201
+ return;
202
+ }
203
+ if (!ctx.agent.setModel) {
204
+ console.log("Agent does not support model switching.");
205
+ return;
206
+ }
207
+ const result = ctx.agent.setModel(provider, modelId);
208
+ console.log(result.message);
209
+ if (result.ok) {
210
+ ctx.setModel(`${provider}/${modelId}`);
211
+ await saveConfigFile(ctx.workspace.root, { model: `${provider}/${modelId}`, modelProvider: provider, modelId });
212
+ }
213
+ return;
214
+ }
215
+ default:
216
+ console.log(`Unknown command: ${name}`);
217
+ }
218
+ }
package/package.json CHANGED
@@ -1,20 +1,22 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "amiko": "dist/cli.js"
7
7
  },
8
8
  "scripts": {
9
9
  "dev": "tsx src/cli.tsx",
10
- "build": "tsc -p tsconfig.json"
10
+ "build": "tsc -p tsconfig.json",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest"
11
13
  },
12
14
  "dependencies": {
13
15
  "@mariozechner/pi-agent-core": "*",
14
16
  "@mariozechner/pi-ai": "*",
17
+ "@sinclair/typebox": "^0.34.41",
15
18
  "ink": "^4.4.1",
16
19
  "ink-select-input": "^5.0.0",
17
- "@sinclair/typebox": "^0.34.41",
18
20
  "react": "^18.2.0",
19
21
  "react-dom": "^18.2.0"
20
22
  },
@@ -23,6 +25,7 @@
23
25
  "@types/react": "^18.2.0",
24
26
  "@types/react-dom": "^18.2.0",
25
27
  "tsx": "^4.7.0",
26
- "typescript": "^5.4.0"
28
+ "typescript": "^5.4.0",
29
+ "vitest": "^4.1.3"
27
30
  }
28
31
  }
@@ -0,0 +1,86 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { execFile } from "node:child_process";
3
+ import { join, dirname } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const CLI_PATH = join(__dirname, "..", "..", "dist", "cli.js");
8
+
9
+ function runCli(args: string[] = [], stdin?: string): Promise<{ stdout: string; stderr: string; code: number | null }> {
10
+ return new Promise((resolve) => {
11
+ const child = execFile("node", [CLI_PATH, ...args], {
12
+ timeout: 10000,
13
+ env: { ...process.env, HOME: "/tmp/amiko-cli-test" },
14
+ }, (error, stdout, stderr) => {
15
+ resolve({
16
+ stdout: stdout || "",
17
+ stderr: stderr || "",
18
+ code: error?.code === "ETIMEDOUT" ? 0 : (error as any)?.status ?? 0,
19
+ });
20
+ });
21
+ if (stdin !== undefined) {
22
+ child.stdin?.write(stdin);
23
+ }
24
+ child.stdin?.end();
25
+ });
26
+ }
27
+
28
+ describe("amiko-cli non-TTY behavior", () => {
29
+ it("does not crash with RangeError in piped mode", async () => {
30
+ const result = await runCli();
31
+ const combined = result.stdout + result.stderr;
32
+
33
+ expect(combined).not.toContain("RangeError");
34
+ expect(combined).not.toContain("Invalid count value");
35
+ });
36
+
37
+ it("enters headless mode when stdin is not a TTY", async () => {
38
+ const result = await runCli([], "/help\n");
39
+ const combined = result.stdout + result.stderr;
40
+
41
+ expect(combined).toContain("headless");
42
+ expect(combined).toContain("Commands:");
43
+ });
44
+
45
+ it("--headless flag is recognized", async () => {
46
+ const result = await runCli(["--headless"], "/help\n");
47
+ const combined = result.stdout + result.stderr;
48
+
49
+ expect(combined).toContain("headless");
50
+ expect(combined).toContain("Commands:");
51
+ });
52
+
53
+ it("headless /help lists available commands", async () => {
54
+ const result = await runCli([], "/help\n");
55
+
56
+ expect(result.stdout).toContain("/exit");
57
+ expect(result.stdout).toContain("/memory");
58
+ expect(result.stdout).toContain("/model");
59
+ expect(result.stdout).toContain("/search");
60
+ });
61
+ });
62
+
63
+ describe("String.repeat patch", () => {
64
+ it("clamps negative values to empty string", () => {
65
+ const origRepeat = String.prototype.repeat;
66
+ String.prototype.repeat = function (count: number) {
67
+ return origRepeat.call(this, Math.max(0, Math.floor(count)));
68
+ };
69
+
70
+ try {
71
+ expect("─".repeat(-2)).toBe("");
72
+ expect("─".repeat(-1)).toBe("");
73
+ expect("─".repeat(0)).toBe("");
74
+ expect("─".repeat(1)).toBe("─");
75
+ expect("─".repeat(3)).toBe("───");
76
+ expect("x".repeat(2.9)).toBe("xx");
77
+ } finally {
78
+ String.prototype.repeat = origRepeat;
79
+ }
80
+ });
81
+
82
+ it("original String.repeat throws on negative values", () => {
83
+ expect(() => "x".repeat(-2)).toThrow(RangeError);
84
+ expect(() => "x".repeat(-1)).toThrow(RangeError);
85
+ });
86
+ });
package/src/cli.tsx CHANGED
@@ -6,6 +6,7 @@ import { initWorkspace } from "./workspace.js";
6
6
  import { createSessionFile } from "./session.js";
7
7
  import { App } from "./app.js";
8
8
  import { loadConfigFile } from "./configFile.js";
9
+ import { runHeadless } from "./headless.js";
9
10
 
10
11
  type ArgOverrides = Partial<{
11
12
  workspacePath: string;
@@ -19,6 +20,7 @@ type ArgOverrides = Partial<{
19
20
  modelProvider?: string;
20
21
  modelId?: string;
21
22
  thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
23
+ headless?: boolean;
22
24
  }>;
23
25
 
24
26
  function parseArgs(argv: string[]): ArgOverrides {
@@ -26,6 +28,9 @@ function parseArgs(argv: string[]): ArgOverrides {
26
28
  for (let i = 0; i < argv.length; i += 1) {
27
29
  const arg = argv[i];
28
30
  switch (arg) {
31
+ case "--headless":
32
+ overrides.headless = true;
33
+ break;
29
34
  case "--workspace":
30
35
  case "-w":
31
36
  overrides.workspacePath = argv[i + 1];
@@ -77,46 +82,29 @@ function parseArgs(argv: string[]): ArgOverrides {
77
82
  }
78
83
 
79
84
  async function main() {
80
- const argv = process.argv.slice(2);
81
-
82
- // Non-TTY: Ink cannot render without a real terminal.
83
- // Print version/help as plain text and exit.
84
- if (!process.stdout.isTTY) {
85
- const flag = argv[0];
86
- if (flag === "-h" || flag === "--help") {
87
- console.log("amiko-cli — interactive AI agent (requires a terminal)");
88
- console.log("Usage: amiko [options]");
89
- console.log(" --workspace, -w <path> Workspace directory");
90
- console.log(" --model <provider/model> Model override");
91
- console.log(" --session <id> Resume session");
92
- console.log(" --thinking <level> off|minimal|low|medium|high|xhigh");
93
- process.exit(0);
94
- }
95
- if (flag === "-v" || flag === "--version") {
96
- const { readFileSync } = await import("node:fs");
97
- const { fileURLToPath } = await import("node:url");
98
- const { dirname, join } = await import("node:path");
99
- try {
100
- const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
101
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
102
- console.log(pkg.version);
103
- } catch {
104
- console.log("unknown");
105
- }
106
- process.exit(0);
107
- }
108
- console.error("amiko-cli requires an interactive terminal (TTY). Cannot render UI in piped/non-TTY mode.");
109
- process.exit(1);
110
- }
85
+ // Ink's render-border.js calls box.top.repeat(contentWidth) where
86
+ // contentWidth = width - 2. When yoga computes a zero-width node (common
87
+ // in non-TTY / piped environments), contentWidth goes negative and
88
+ // String.repeat() throws. Patch String.repeat to clamp to 0.
89
+ const origRepeat = String.prototype.repeat;
90
+ String.prototype.repeat = function (count: number) {
91
+ return origRepeat.call(this, Math.max(0, Math.floor(count)));
92
+ };
111
93
 
112
94
  const config = loadConfig();
113
- const overrides = parseArgs(argv);
95
+ const overrides = parseArgs(process.argv.slice(2));
114
96
  const finalConfig = { ...config, ...overrides };
115
97
  const workspace = await initWorkspace(finalConfig.workspacePath);
116
98
  const persisted = await loadConfigFile(workspace.root);
117
99
  const mergedConfig = { ...finalConfig, ...persisted, ...overrides };
118
100
  const sessionFile = await createSessionFile(workspace.sessionsDir, finalConfig.sessionId);
119
101
 
102
+ // Auto-detect non-TTY or explicit --headless flag
103
+ if (overrides.headless || !process.stdout.isTTY) {
104
+ await runHeadless(mergedConfig, workspace, sessionFile.path);
105
+ return;
106
+ }
107
+
120
108
  render(<App config={mergedConfig} workspace={workspace} sessionPath={sessionFile.path} />);
121
109
  }
122
110
 
@@ -0,0 +1,222 @@
1
+ import { createInterface } from "node:readline";
2
+ import { AppConfig, Message, MemoryHit } from "./types.js";
3
+ import { parseCommand } from "./commands.js";
4
+ import { buildPrompt } from "./prompt.js";
5
+ import { appendSession } from "./session.js";
6
+ import { readWorkspaceFiles, WorkspaceFiles } from "./workspace.js";
7
+ import { createPiAgent } from "./agent/piAgent.js";
8
+ import { qmdSearch, qmdGet, qmdCollectionAdd, qmdEmbed } from "./memory/qmd.js";
9
+ import { saveConfigFile } from "./configFile.js";
10
+ import { getModels, getProviders, type KnownProvider } from "@mariozechner/pi-ai";
11
+
12
+ export async function runHeadless(
13
+ config: AppConfig,
14
+ workspace: WorkspaceFiles,
15
+ sessionPath: string,
16
+ ) {
17
+ const agent = await createPiAgent(config);
18
+ let currentModel = config.model
19
+ ?? (config.modelProvider && config.modelId ? `${config.modelProvider}/${config.modelId}` : "auto");
20
+
21
+ if (currentModel === "auto") {
22
+ const value = agent.getCurrentModel?.();
23
+ if (value) currentModel = value;
24
+ }
25
+
26
+ if (agent.onEvent) {
27
+ agent.onEvent((event) => {
28
+ if (event?.type === "tool_execution_start") {
29
+ const lines = [`[tool] ${event.toolName} start`];
30
+ if (event.args?.command) lines.push(` command: ${event.args.command}`);
31
+ console.log(lines.join("\n"));
32
+ }
33
+ if (event?.type === "tool_execution_end") {
34
+ const resultText = event.result?.content
35
+ ? event.result.content.map((c: any) => (c.text ? c.text : "")).join("\n")
36
+ : "";
37
+ const summary = resultText.trim() || "(no output)";
38
+ console.log(`[tool] ${event.toolName} done\n${summary}`);
39
+ }
40
+ });
41
+ }
42
+
43
+ console.log(`amiko-cli (headless) | model: ${currentModel} | workspace: ${workspace.root}`);
44
+ console.log("Type a message or /command. Press Ctrl+D to exit.");
45
+
46
+ const rl = createInterface({
47
+ input: process.stdin,
48
+ output: process.stdout,
49
+ prompt: "> ",
50
+ terminal: false,
51
+ });
52
+
53
+ rl.prompt();
54
+
55
+ for await (const line of rl) {
56
+ const trimmed = line.trim();
57
+ if (!trimmed) {
58
+ rl.prompt();
59
+ continue;
60
+ }
61
+
62
+ const command = parseCommand(trimmed);
63
+ if (command) {
64
+ await handleCommand(command.name, command.args, {
65
+ config, workspace, sessionPath, agent, currentModel,
66
+ setModel: (m: string) => { currentModel = m; },
67
+ });
68
+ rl.prompt();
69
+ continue;
70
+ }
71
+
72
+ console.log(`[user] ${trimmed}`);
73
+ await appendSession(sessionPath, "user", trimmed);
74
+
75
+ const workspaceData = await readWorkspaceFiles(workspace);
76
+
77
+ let hits: MemoryHit[] = [];
78
+ if (config.qmdEnabled) {
79
+ hits = await qmdSearch({
80
+ qmdBin: config.qmdBin,
81
+ query: trimmed,
82
+ limit: config.qmdLimit,
83
+ collection: config.qmdCollection,
84
+ });
85
+ }
86
+
87
+ if (config.qmdFull && hits.length > 0) {
88
+ const expanded: MemoryHit[] = [];
89
+ for (const hit of hits) {
90
+ const docId = hit.path || hit.id;
91
+ if (!docId) { expanded.push(hit); continue; }
92
+ const text = await qmdGet({ qmdBin: config.qmdBin, docId, full: true });
93
+ expanded.push({ ...hit, snippet: text || hit.snippet });
94
+ }
95
+ hits = expanded;
96
+ }
97
+
98
+ const prompt = buildPrompt({
99
+ identity: workspaceData.identity,
100
+ personality: workspaceData.personality,
101
+ memory: workspaceData.memory,
102
+ hits,
103
+ });
104
+
105
+ let assistantText = "";
106
+ try {
107
+ for await (const chunk of agent.streamReply({ prompt, userMessage: trimmed })) {
108
+ process.stdout.write(chunk);
109
+ assistantText += chunk;
110
+ }
111
+ } catch (error) {
112
+ const message = (error as Error).message || "unknown error";
113
+ assistantText += `\n[error] ${message}\n`;
114
+ console.error(`[error] ${message}`);
115
+ }
116
+
117
+ if (!assistantText.endsWith("\n")) process.stdout.write("\n");
118
+
119
+ if (assistantText) {
120
+ await appendSession(sessionPath, "assistant", assistantText);
121
+ }
122
+
123
+ rl.prompt();
124
+ }
125
+
126
+ process.exit(0);
127
+ }
128
+
129
+ async function handleCommand(
130
+ name: string,
131
+ args: string,
132
+ ctx: {
133
+ config: AppConfig;
134
+ workspace: WorkspaceFiles;
135
+ sessionPath: string;
136
+ agent: any;
137
+ currentModel: string;
138
+ setModel: (m: string) => void;
139
+ },
140
+ ) {
141
+ switch (name) {
142
+ case "exit":
143
+ process.exit(0);
144
+ case "help":
145
+ console.log("Commands: /help /exit /search <query> /memory /session /plan /identity /personality /index [collection] /model [provider[/id]]");
146
+ return;
147
+ case "memory": {
148
+ const data = await readWorkspaceFiles(ctx.workspace);
149
+ console.log(`MEMORY.md:\n\n${data.memory.trim() || "(empty)"}`);
150
+ return;
151
+ }
152
+ case "session":
153
+ console.log(`Session file: ${ctx.sessionPath}`);
154
+ return;
155
+ case "plan":
156
+ console.log("Plan file: PLAN.md");
157
+ return;
158
+ case "identity": {
159
+ const data = await readWorkspaceFiles(ctx.workspace);
160
+ console.log(`IDENTITY.md:\n\n${data.identity.trim() || "(empty)"}`);
161
+ return;
162
+ }
163
+ case "personality": {
164
+ const data = await readWorkspaceFiles(ctx.workspace);
165
+ console.log(`PERSONALITY.md:\n\n${data.personality.trim() || "(empty)"}`);
166
+ return;
167
+ }
168
+ case "index": {
169
+ if (!ctx.config.qmdEnabled) { console.log("QMD is disabled."); return; }
170
+ const collName = args || ctx.config.qmdCollection || "amiko";
171
+ const added = await qmdCollectionAdd({ qmdBin: ctx.config.qmdBin, name: collName, path: ctx.workspace.root });
172
+ if (!added) { console.log("Failed to add QMD collection."); return; }
173
+ const embedded = await qmdEmbed({ qmdBin: ctx.config.qmdBin, collection: collName });
174
+ console.log(embedded ? `Indexed QMD collection "${collName}".` : `Collection "${collName}" added, but embedding failed.`);
175
+ return;
176
+ }
177
+ case "search": {
178
+ if (!args) { console.log("Usage: /search <query>"); return; }
179
+ if (!ctx.config.qmdEnabled) { console.log("QMD is disabled."); return; }
180
+ const hits = await qmdSearch({ qmdBin: ctx.config.qmdBin, query: args, limit: ctx.config.qmdLimit, collection: ctx.config.qmdCollection });
181
+ if (hits.length === 0) { console.log("No memory hits."); return; }
182
+ const formatted = hits.map((hit, i) => {
183
+ const label = hit.title || hit.path || hit.id;
184
+ const score = hit.score ? ` (${hit.score.toFixed(2)})` : "";
185
+ return `${i + 1}. ${label}${score}`;
186
+ }).join("\n");
187
+ console.log(formatted);
188
+ return;
189
+ }
190
+ case "model": {
191
+ if (!args) {
192
+ const providers = getProviders().sort();
193
+ console.log(`Current model: ${ctx.currentModel}\nProviders:\n${providers.map((p, i) => ` ${i + 1}. ${p}`).join("\n")}`);
194
+ return;
195
+ }
196
+ const slashParts = args.includes("/") ? args.split("/") : [];
197
+ let provider = args.split(" ")[0];
198
+ let modelId = args.split(" ")[1];
199
+ if (slashParts.length >= 2) {
200
+ provider = slashParts[0]?.trim();
201
+ modelId = slashParts.slice(1).join("/").trim();
202
+ }
203
+ if (provider && !modelId) {
204
+ const models = getModels(provider as KnownProvider);
205
+ if (models.length === 0) { console.log(`Unknown provider: ${provider}`); return; }
206
+ console.log(`Models for ${provider}:\n${models.map((m) => m.id).sort().join("\n")}`);
207
+ return;
208
+ }
209
+ if (!provider || !modelId) { console.log("Usage: /model <provider>/<modelId>"); return; }
210
+ if (!ctx.agent.setModel) { console.log("Agent does not support model switching."); return; }
211
+ const result = ctx.agent.setModel(provider, modelId);
212
+ console.log(result.message);
213
+ if (result.ok) {
214
+ ctx.setModel(`${provider}/${modelId}`);
215
+ await saveConfigFile(ctx.workspace.root, { model: `${provider}/${modelId}`, modelProvider: provider, modelId });
216
+ }
217
+ return;
218
+ }
219
+ default:
220
+ console.log(`Unknown command: ${name}`);
221
+ }
222
+ }