genaicode 2.17.0 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,89 +1,47 @@
1
1
  <p align="center">
2
2
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="media/logo-dark.png">
4
- <source media="(prefers-color-scheme: light)" srcset="media/logo.png">
5
- <img alt="GenAIcode Logo." src="media/logo.png" width="100%" height="auto">
3
+ <source media="(prefers-color-scheme: dark)" srcset="docs/media/logo-dark.png">
4
+ <source media="(prefers-color-scheme: light)" srcset="docs/media/logo.png">
5
+ <img alt="GenAIcode Logo." src="docs/media/logo.png" width="100%" height="auto">
6
6
  </picture>
7
7
  </p>
8
8
 
9
9
  # GenAIcode
10
10
 
11
- GenAIcode is a small TypeScript toolkit for using LLMs in backend code.
11
+ GenAIcode drives the coding-agent CLIs you already have (Claude Code, Codex, GitHub Copilot
12
+ CLI, Cursor, Gemini CLI, opencode, Muse, Mistral Vibe, Antigravity) behind one API and one
13
+ CLI. Script them, swap them with one flag, and let your tests decide when the job is done.
12
14
 
13
- It sits between raw provider SDKs and full agent frameworks: one prompt representation,
14
- thin provider adapters, a convenient request API, and lightweight conversation chains.
15
- The core does not inspect repositories, execute shell commands, edit files, or run an agent UI.
16
- The opt-in [`genaicode/agents`](#coding-agents) subpath drives the coding-agent CLIs you
17
- already have (Claude Code, Codex, GitHub Copilot CLI, Cursor, Gemini CLI, opencode, Muse,
18
- Mistral Vibe, Antigravity) behind one task and event API, so you can orchestrate them from
19
- backend code. The same drivers are on the command line as `npx genaicode run`.
20
-
21
- **Like jQuery**, the common case starts with one small function and becomes more specific
22
- through chaining—configure a request, follow up across multiple prompts, and keep history
23
- portable without adopting a full agent framework.
24
-
25
- GenAIcode 1.x was a coding agent; see [Migration from 1.x](#migration-from-1x) if you need
26
- the old product or the 2.0 scope decisions.
27
-
28
- ## Install
15
+ <p align="center">
16
+ <a href="docs/media/showcase.mp4">
17
+ <img alt="genaicode in 20 seconds: the Vite overlay fixes a broken page, run --verify sends a failed test back to the agent, and an agent inside an app waits for Approve." src="docs/media/screenshots/showcase.gif" width="100%">
18
+ </a>
19
+ <br>
20
+ <sub>Recorded live with Claude Code and Codex. <a href="docs/media/showcase.mp4">Full video (87 s)</a>.</sub>
21
+ </p>
29
22
 
30
23
  ```bash
31
- npm install genaicode
24
+ npx genaicode run --verify "npm test" "fix the failing tests"
32
25
  ```
33
26
 
34
- Node.js 20 or newer is required.
27
+ That runs the first agent CLI installed on your machine in the current directory, then runs
28
+ `npm test`. If the check fails, its output goes back to the agent for another attempt. Add
29
+ `-a codex` (or `claude`, `copilot`, `opencode`...) to pick the agent; the command stays the
30
+ same. From there, the same drivers are a TypeScript API, a chat in your terminal or browser,
31
+ a panel inside your Vite app, and an agent inside your own app.
35
32
 
36
- ## Why this vs a raw SDK
33
+ GenAIcode also ships [a thin LLM layer](#also-a-thin-llm-layer) for calling model providers
34
+ from backend code. The two halves are separate subpaths: importing `genaicode` never spawns an
35
+ agent, and `genaicode/agents` loads no provider SDK.
37
36
 
38
- Provider SDKs are the right tool when you call one vendor and own every request shape
39
- yourself. The cost shows up when the same backend needs a second provider, a test double,
40
- or shared policy (timeouts, JSON parsing, rate limits, fallback) without copying glue.
41
-
42
- GenAIcode is that thin shared layer:
43
-
44
- - One portable prompt/tool IR (`PromptItem`) instead of OpenAI messages vs Anthropic
45
- blocks vs Gemini contents.
46
- - One request API (`.text()`, `.json()`, `.stream()`, chains) over those adapters.
47
- - A tiny `ModelProvider` seam so tests and custom gateways do not mock vendor HTTP.
48
- - Opt-in middleware and retry helpers—no hidden tool runners, no silent retries, no
49
- agent loop.
50
-
51
- If you are happy importing one SDK and never swapping models or providers, stay on the
52
- SDK. If you want the call site to look the same while the edge stays replaceable, use
53
- GenAIcode.
54
-
55
- ## A prompt in three lines
56
-
57
- ```ts
58
- import { genaicode } from 'genaicode';
59
- import { openai } from 'genaicode/providers';
60
-
61
- const ai = genaicode(openai({ model: 'your-model-name' }));
62
- const answer = await ai('Explain why the sky is blue in two sentences.').text();
63
- ```
64
-
65
- The client is callable on purpose. Configuration is ordinary method chaining—system
66
- instructions, temperature, token limits, and more—without a separate options object or
67
- framework setup:
37
+ ## Install
68
38
 
69
- ```ts
70
- const result = await ai('Create a release note from these commits')
71
- .system('You are a concise technical writer.')
72
- .temperature(0.2)
73
- .maxOutputTokens(500)
74
- .text();
39
+ ```bash
40
+ npm install genaicode
75
41
  ```
76
42
 
77
- Builders are immutable, so a configured base request can be safely reused:
78
-
79
- ```ts
80
- const releaseNote = ai('Create a release note from these commits')
81
- .system('You are a concise technical writer.')
82
- .temperature(0.2);
83
-
84
- const short = await releaseNote.maxOutputTokens(200).text();
85
- const long = await releaseNote.maxOutputTokens(800).text();
86
- ```
43
+ Node.js 20 or newer is required. The agent CLIs are yours to install and log in to;
44
+ `npx genaicode agents` lists which ones it finds.
87
45
 
88
46
  ## Coding agents
89
47
 
@@ -168,15 +126,15 @@ session; `/help` lists the rest.
168
126
 
169
127
  <p align="center">
170
128
  <picture>
171
- <source media="(prefers-reduced-motion: reduce)" srcset="media/screenshots/chat-terminal.png">
172
- <img alt="genaicode chat in a terminal: the agent fixes a failing test, then takes queued follow-ups." src="media/screenshots/chat-terminal.gif" width="49%">
129
+ <source media="(prefers-reduced-motion: reduce)" srcset="docs/media/screenshots/chat-terminal.png">
130
+ <img alt="genaicode chat in a terminal: the agent fixes a failing test, then takes queued follow-ups." src="docs/media/screenshots/chat-terminal.gif" width="49%">
173
131
  </picture>
174
132
  <picture>
175
- <source media="(prefers-reduced-motion: reduce) and (prefers-color-scheme: dark)" srcset="media/screenshots/wolf-dark.png">
176
- <source media="(prefers-reduced-motion: reduce)" srcset="media/screenshots/wolf-light.png">
177
- <source media="(prefers-color-scheme: dark)" srcset="media/screenshots/chat-browser-dark.gif">
178
- <source media="(prefers-color-scheme: light)" srcset="media/screenshots/chat-browser-light.gif">
179
- <img alt="genaicode ui in a browser: the same fix and a follow-up." src="media/screenshots/chat-browser-light.gif" width="49%">
133
+ <source media="(prefers-reduced-motion: reduce) and (prefers-color-scheme: dark)" srcset="docs/media/screenshots/wolf-dark.png">
134
+ <source media="(prefers-reduced-motion: reduce)" srcset="docs/media/screenshots/wolf-light.png">
135
+ <source media="(prefers-color-scheme: dark)" srcset="docs/media/screenshots/chat-browser-dark.gif">
136
+ <source media="(prefers-color-scheme: light)" srcset="docs/media/screenshots/chat-browser-light.gif">
137
+ <img alt="genaicode ui in a browser: the same fix and a follow-up." src="docs/media/screenshots/chat-browser-light.gif" width="49%">
180
138
  </picture>
181
139
  </p>
182
140
 
@@ -186,9 +144,9 @@ The terminal UI rings the terminal bell instead. `/bark off` (or the Bark button
186
144
 
187
145
  <p align="center">
188
146
  <picture>
189
- <source media="(prefers-color-scheme: dark)" srcset="media/screenshots/wolf-dark.png">
190
- <source media="(prefers-color-scheme: light)" srcset="media/screenshots/wolf-light.png">
191
- <img alt="The browser UI with the wolf behind a finished turn." src="media/screenshots/wolf-light.png" width="80%">
147
+ <source media="(prefers-color-scheme: dark)" srcset="docs/media/screenshots/wolf-dark.png">
148
+ <source media="(prefers-color-scheme: light)" srcset="docs/media/screenshots/wolf-light.png">
149
+ <img alt="The browser UI with the wolf behind a finished turn." src="docs/media/screenshots/wolf-light.png" width="80%">
192
150
  </picture>
193
151
  </p>
194
152
 
@@ -213,9 +171,9 @@ export default defineConfig({ plugins: [genaicode()] });
213
171
 
214
172
  <p align="center">
215
173
  <picture>
216
- <source media="(prefers-color-scheme: dark)" srcset="media/screenshots/vite-dark.png">
217
- <source media="(prefers-color-scheme: light)" srcset="media/screenshots/vite-light.png">
218
- <img alt="The genaicode panel over a Vite app: the agent fixed the page's two errors." src="media/screenshots/vite-light.png" width="80%">
174
+ <source media="(prefers-color-scheme: dark)" srcset="docs/media/screenshots/vite-dark.png">
175
+ <source media="(prefers-color-scheme: light)" srcset="docs/media/screenshots/vite-light.png">
176
+ <img alt="The genaicode panel over a Vite app: the agent fixed the page's two errors." src="docs/media/screenshots/vite-light.png" width="80%">
219
177
  </picture>
220
178
  </p>
221
179
 
@@ -409,7 +367,7 @@ import 'genaicode/react/styles.css';
409
367
  ```
410
368
 
411
369
  <p align="center">
412
- <img alt="A shop admin with the agent drawer: the agent proposed a refund, waiting for Approve." src="media/screenshots/app-agent.png" width="80%">
370
+ <img alt="A shop admin with the agent drawer: the agent proposed a refund, waiting for Approve." src="docs/media/screenshots/app-agent.png" width="80%">
413
371
  </p>
414
372
 
415
373
  Under it, `/api/agent` serves `GET /events` (a stream of `AppAgentState`: the session, earlier
@@ -431,7 +389,70 @@ bearer and refuses browser requests; every other route asks `authorize` and refu
431
389
  cross-site requests. Without `authorize` only a loopback `Host` is accepted (add names with
432
390
  `allowedHosts`), so a DNS-rebinding page cannot reach the agent.
433
391
 
434
- ## Chaining prompts
392
+ ## Also: a thin LLM layer
393
+
394
+ Besides driving agents, GenAIcode is a small TypeScript toolkit for calling LLMs from backend
395
+ code. It sits between raw provider SDKs and full agent frameworks: one prompt representation,
396
+ thin provider adapters, a convenient request API, and lightweight conversation chains. This
397
+ layer does not inspect repositories, execute shell commands, edit files, or run an agent UI.
398
+
399
+ **Like jQuery**, the common case starts with one small function and becomes more specific
400
+ through chaining—configure a request, follow up across multiple prompts, and keep history
401
+ portable without adopting a full agent framework.
402
+
403
+ ### A prompt in three lines
404
+
405
+ ```ts
406
+ import { genaicode } from 'genaicode';
407
+ import { openai } from 'genaicode/providers';
408
+
409
+ const ai = genaicode(openai({ model: 'your-model-name' }));
410
+ const answer = await ai('Explain why the sky is blue in two sentences.').text();
411
+ ```
412
+
413
+ The client is callable on purpose. Configuration is ordinary method chaining—system
414
+ instructions, temperature, token limits, and more—without a separate options object or
415
+ framework setup:
416
+
417
+ ```ts
418
+ const result = await ai('Create a release note from these commits')
419
+ .system('You are a concise technical writer.')
420
+ .temperature(0.2)
421
+ .maxOutputTokens(500)
422
+ .text();
423
+ ```
424
+
425
+ Builders are immutable, so a configured base request can be safely reused:
426
+
427
+ ```ts
428
+ const releaseNote = ai('Create a release note from these commits')
429
+ .system('You are a concise technical writer.')
430
+ .temperature(0.2);
431
+
432
+ const short = await releaseNote.maxOutputTokens(200).text();
433
+ const long = await releaseNote.maxOutputTokens(800).text();
434
+ ```
435
+
436
+ ### Why this vs a raw SDK
437
+
438
+ Provider SDKs are the right tool when you call one vendor and own every request shape
439
+ yourself. The cost shows up when the same backend needs a second provider, a test double,
440
+ or shared policy (timeouts, JSON parsing, rate limits, fallback) without copying glue.
441
+
442
+ GenAIcode is that thin shared layer:
443
+
444
+ - One portable prompt/tool IR (`PromptItem`) instead of OpenAI messages vs Anthropic
445
+ blocks vs Gemini contents.
446
+ - One request API (`.text()`, `.json()`, `.stream()`, chains) over those adapters.
447
+ - A tiny `ModelProvider` seam so tests and custom gateways do not mock vendor HTTP.
448
+ - Opt-in middleware and retry helpers—no hidden tool runners, no silent retries, no
449
+ agent loop.
450
+
451
+ If you are happy importing one SDK and never swapping models or providers, stay on the
452
+ SDK. If you want the call site to look the same while the edge stays replaceable, use
453
+ GenAIcode.
454
+
455
+ ### Chaining prompts
435
456
 
436
457
  A chain remembers successful user and assistant turns. Each new prompt sees the complete
437
458
  history, so multi-step work stays in ordinary application code:
@@ -449,7 +470,7 @@ const answer3 = await chain.text('Prompt 3: summarize the final contract.');
449
470
  This is `prompt1 → response1 → prompt2 → response2 → prompt3 → response3`. The history
450
471
  is available as portable `PromptItem[]` through `chain.history()`.
451
472
 
452
- ## Using a chain in a loop
473
+ ### Using a chain in a loop
453
474
 
454
475
  A chain is ordinary application state, so normal control flow works:
455
476
 
@@ -492,7 +513,7 @@ for (let attempt = 1; attempt <= 3; attempt += 1) {
492
513
 
493
514
  The application owns validation, attempt limits, and failure policy.
494
515
 
495
- ## Schema adapters
516
+ ### Schema adapters
496
517
 
497
518
  `json(...)` and `parseJsonResult(...)` accept either a parser function or a schema adapter
498
519
  with a `parse(value)` method. This keeps schema validation library-agnostic:
@@ -512,7 +533,7 @@ Calling `.json()` also sets `responseFormat: { type: 'json' }` on the request wh
512
533
  not already chosen a format, so providers that support JSON mode (OpenAI, Gemini/Vertex)
513
534
  are asked for JSON rather than free text.
514
535
 
515
- ## Response format and thinking
536
+ ### Response format and thinking
516
537
 
517
538
  Portable request fields cover the two knobs backends usually poke through provider-specific
518
539
  config:
@@ -543,7 +564,7 @@ Providers map what they support and ignore the rest. `ProviderCapabilities.jsonR
543
564
  and `ProviderCapabilities.thinking` advertise support. Vendor-specific escapes such as
544
565
  Vertex `generationConfig` remain available for anything not covered here.
545
566
 
546
- ## PromptItem: the portable prompt IR
567
+ ### PromptItem: the portable prompt IR
547
568
 
548
569
  `PromptItem` is GenAIcode's provider-neutral intermediate representation:
549
570
 
@@ -576,7 +597,7 @@ const supportTicket = (ticket: Ticket) =>
576
597
  await ai(supportTicket(ticket)).text();
577
598
  ```
578
599
 
579
- ## Tools
600
+ ### Tools
580
601
 
581
602
  ```ts
582
603
  const calls = await ai('What is the weather in Warsaw?')
@@ -598,7 +619,7 @@ const calls = await ai('What is the weather in Warsaw?')
598
619
  GenAIcode normalizes tool calls but deliberately does not execute them. The application
599
620
  owns permissions, retries, and side effects.
600
621
 
601
- ## Streaming
622
+ ### Streaming
602
623
 
603
624
  Providers that support native streaming expose a provider-neutral `StreamEvent` IR.
604
625
  Request builders and chains offer `.stream()` and `.streamText()`. If a provider has no
@@ -618,7 +639,7 @@ ai.provider.capabilities;
618
639
  // { streaming: true, tools: true, images: 'input', systemPrompt: true }
619
640
  ```
620
641
 
621
- ## Middleware
642
+ ### Middleware
622
643
 
623
644
  Hook-style plugins remain the extension point. Built-in helpers cover common backend
624
645
  needs without restoring a global registry:
@@ -637,7 +658,7 @@ const ai = genaicode(openai({ model: 'your-model-name' }), {
637
658
  });
638
659
  ```
639
660
 
640
- ## Retries
661
+ ### Retries
641
662
 
642
663
  Retries stay in application code. Use `classifyError`, `isRetryable`, and `withRetry`
643
664
  when you want shared classification without hidden policy:
@@ -654,7 +675,7 @@ const text = await withRetry(() => ai('Summarize the deploy notes.').text(), {
654
675
  See [retry guidance](docs/retry.md), [semver policy](docs/semver.md), and the
655
676
  [provider package evaluation](docs/provider-packages.md).
656
677
 
657
- ## Providers
678
+ ### Providers
658
679
 
659
680
  Models are provided in the adapter, through `.model(...)`, or with environment variables:
660
681
 
@@ -718,7 +739,7 @@ const provider: ModelProvider = {
718
739
  All Anthropic, Google, and OpenAI conversion functions are public from
719
740
  `genaicode/providers`, so gateways and tests can reuse them without instantiating clients.
720
741
 
721
- ## Provider E2E tests
742
+ ### Provider E2E tests
722
743
 
723
744
  Run real-provider E2E tests locally with:
724
745
 
@@ -739,7 +760,7 @@ Beyond the smoke call, E2E also covers portable `responseFormat: { type: 'json'
739
760
  CI/CD is configured in `.github/workflows/provider-e2e.yaml`. Each provider runs in its own
740
761
  job and only starts when both required secrets are configured in GitHub Actions.
741
762
 
742
- ## Plugins and hooks
763
+ ### Plugins and hooks
743
764
 
744
765
  A provider plugin no longer needs registration in global configuration. It exports the
745
766
  same small `ModelProvider` contract as a built-in adapter:
@@ -787,7 +808,7 @@ Plugins run in registration order, and each plugin may call `next()` once. This
787
808
  extension mechanism compatible with npm packages and ordinary imports without restoring
788
809
  the 1.x runtime TypeScript loader or process-global plugin registry.
789
810
 
790
- Framework-shaped examples live under `examples/` (`http-handler`, `queue-worker`,
811
+ Framework-shaped examples live under [`docs/examples/`](docs/examples/) (`http-handler`, `queue-worker`,
791
812
  `cron-job`).
792
813
 
793
814
  ## Design boundaries
@@ -53,6 +53,9 @@
53
53
 
54
54
  ### Changed
55
55
 
56
+ - README and the package description lead with the coding agents: a 20-second demo, the
57
+ `npx genaicode run --verify` one-liner, then `genaicode/agents`. The LLM layer moved below
58
+ them as "Also: a thin LLM layer", and the 1.x note to the end.
56
59
  - `defaultAppAgents`: Claude cannot start subagents (`Task`, `Agent`) in either mode; one can
57
60
  outlive the turn, so its answer never reaches the user.
58
61
 
@@ -265,7 +268,7 @@
265
268
  ### Notes
266
269
 
267
270
  - Releases are published from GitHub Actions when a version tag is pushed. See
268
- [docs/releasing.md](docs/releasing.md).
271
+ [docs/releasing.md](releasing.md).
269
272
 
270
273
  ## 2.4.0 — 2026-09-24
271
274
 
@@ -275,7 +278,7 @@
275
278
  `CodingAgent` interface. Drivers `claude()`, `codex()`, `muse()`; agent-neutral
276
279
  `AgentEvent` stream and `AgentResult`; abort, timeout and process-group kill;
277
280
  `detectAgents` / `findExecutable`; `cliAgent()` for custom drivers. See
278
- [docs/agents.md](docs/agents.md).
281
+ [docs/agents.md](agents.md).
279
282
  - Live agent sessions over JSON-RPC: `codexLive()` (`codex app-server`) and `museLive()`
280
283
  (`muse serve`) with `AgentRun.steer()` and `AgentTask.onApproval`; `liveAgent()` and
281
284
  `RpcPeer` for custom live drivers; `approval-resolved` event.
@@ -316,7 +319,7 @@
316
319
 
317
320
  Publishes the Phase 3–4 work already on `master`. npm `2.0.0` shipped the 2.0
318
321
  kernel and provider adapters only; this minor adds the remaining public surface
319
- documented in the README and [semver policy](docs/semver.md).
322
+ documented in the README and [semver policy](semver.md).
320
323
 
321
324
  ### Added
322
325
 
@@ -324,12 +327,12 @@ documented in the README and [semver policy](docs/semver.md).
324
327
  native streams for OpenAI / Anthropic / Google with generate→stream fallback)
325
328
  - Built-in middleware: `timingPlugin`, `rateLimitPlugin`, `cachePlugin`,
326
329
  `fallbackPlugin`, `fallbackProvider`
327
- - Retry helpers: `classifyError`, `isRetryable`, `withRetry` (+ [docs/retry.md](docs/retry.md))
330
+ - Retry helpers: `classifyError`, `isRetryable`, `withRetry` (+ [docs/retry.md](retry.md))
328
331
  - `ProviderCapabilities` on `ModelProvider`
329
332
  - Compatibility fixtures for multimodal and tool-call round trips
330
333
  - Framework examples under `examples/` (HTTP handler, queue worker, cron job)
331
- - Written guidance: [docs/semver.md](docs/semver.md),
332
- [docs/provider-packages.md](docs/provider-packages.md)
334
+ - Written guidance: [docs/semver.md](semver.md),
335
+ [docs/provider-packages.md](provider-packages.md)
333
336
 
334
337
  ### Notes
335
338
 
package/docs/pivot.md CHANGED
@@ -91,7 +91,7 @@ and in the 1.x npm line.
91
91
  `fallbackProvider`).
92
92
  - First-class schema adapters without requiring a specific validation library — implemented.
93
93
  - Small framework examples for HTTP handlers, queues, and cron jobs — implemented
94
- under `examples/`.
94
+ under `docs/examples/`.
95
95
  - Re-evaluate separate provider packages if dependency size becomes material —
96
96
  evaluated; keep bundled for 2.x (see [provider-packages.md](./provider-packages.md)).
97
97
 
@@ -113,7 +113,7 @@ and in the 1.x npm line.
113
113
  helpers, fixtures, examples, and related docs).
114
114
  - `2.2.0` adds portable `responseFormat` and `thinking` request fields (so apps
115
115
  need fewer provider-specific `generationConfig` casts). See
116
- [CHANGELOG.md](../CHANGELOG.md).
116
+ [CHANGELOG.md](CHANGELOG.md).
117
117
 
118
118
  ## Success measures
119
119
 
package/docs/semver.md CHANGED
@@ -52,7 +52,7 @@ Require a new major version:
52
52
  - Timing of stream events beyond the `StreamEvent` discriminant
53
53
  - Dependency versions of underlying provider SDKs within a major (may bump in
54
54
  minors when needed for security or API drift)
55
- - Example apps under `examples/` (illustrative only)
55
+ - Example apps under `docs/examples/` (illustrative only)
56
56
 
57
57
  ## Plugin and provider authors
58
58
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "genaicode",
3
- "version": "2.17.0",
4
- "description": "A small, provider-neutral TypeScript toolkit for calling LLMs from backend code.",
3
+ "version": "2.17.1",
4
+ "description": "Drive the coding-agent CLIs you already have (Claude Code, Codex, Copilot, Cursor, Gemini, opencode...) behind one API and one CLI, plus a thin provider-neutral LLM layer.",
5
5
  "author": "Grzegorz Tańczyk",
6
6
  "repository": {
7
7
  "type": "git",
@@ -33,7 +33,8 @@
33
33
  "files": [
34
34
  "dist",
35
35
  "docs",
36
- "CHANGELOG.md",
36
+ "!docs/examples",
37
+ "!docs/media",
37
38
  "README.md",
38
39
  "LICENSE"
39
40
  ],
@@ -70,16 +71,17 @@
70
71
  },
71
72
  "scripts": {
72
73
  "clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
73
- "build": "npm run clean && tsc -p tsconfig.build.json && node scripts/build-ui.mjs",
74
+ "build": "npm run clean && tsc -p scripts/tsconfig.build.json && node scripts/build-ui.mjs",
74
75
  "lint": "eslint . --ext js,ts,tsx --report-unused-disable-directives --max-warnings 0",
75
- "test": "vitest --config vitest.unit.config.ts --run",
76
- "test:e2e": "vitest --config vitest.e2e.config.ts --run",
77
- "test:browser": "vitest --config vitest.browser.config.ts --run",
78
- "test:watch": "vitest --config vitest.unit.config.ts",
76
+ "test": "vitest --config scripts/vitest.config.ts --run --project unit",
77
+ "test:e2e": "vitest --config scripts/vitest.config.ts --run --project e2e",
78
+ "test:browser": "vitest --config scripts/vitest.config.ts --run --project browser",
79
+ "test:watch": "vitest --config scripts/vitest.config.ts --project unit",
79
80
  "type-check": "tsc --noEmit",
80
81
  "check": "npm run type-check && npm run lint && npm test && npm run build",
81
82
  "prepublishOnly": "npm run check",
82
- "prepare": "npm run build"
83
+ "prepare": "npm run build",
84
+ "format": "prettier --write ."
83
85
  },
84
86
  "dependencies": {
85
87
  "@anthropic-ai/sdk": "^0.74.0",
@@ -96,10 +98,8 @@
96
98
  "eslint": "^8.54.0",
97
99
  "eslint-config-prettier": "^9.0.0",
98
100
  "happy-dom": "^20.14.5",
99
- "husky": "^9.1.1",
100
101
  "ink": "^6.8.0",
101
102
  "ink-testing-library": "^4.0.0",
102
- "lint-staged": "^16.4.0",
103
103
  "playwright": "^1.56.1",
104
104
  "prettier": "^3.1.0",
105
105
  "react": "^19.3.0",
@@ -108,7 +108,29 @@
108
108
  "vite": "^6.4.3",
109
109
  "vitest": "^4.1.11"
110
110
  },
111
- "lint-staged": {
112
- "*.{js,ts,md}": "prettier --write"
111
+ "prettier": {
112
+ "trailingComma": "all",
113
+ "tabWidth": 2,
114
+ "semi": true,
115
+ "singleQuote": true,
116
+ "printWidth": 120,
117
+ "bracketSpacing": true,
118
+ "endOfLine": "lf"
119
+ },
120
+ "eslintConfig": {
121
+ "root": true,
122
+ "env": {
123
+ "node": true
124
+ },
125
+ "extends": [
126
+ "eslint:recommended",
127
+ "plugin:@typescript-eslint/recommended"
128
+ ],
129
+ "ignorePatterns": [
130
+ "docs/examples/**/*",
131
+ "dist",
132
+ "coverage"
133
+ ],
134
+ "parser": "@typescript-eslint/parser"
113
135
  }
114
136
  }