genaicode 2.18.4 → 2.20.0
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 +40 -858
- package/dist/react/agent-chat.css +39 -0
- package/dist/react/markdown.js +69 -7
- package/dist/react/markdown.js.map +1 -1
- package/dist/ui/web-client.js +50 -11
- package/docs/CHANGELOG.md +2 -0
- package/docs/agents.md +51 -0
- package/docs/app-agent.md +71 -0
- package/docs/cli.md +105 -0
- package/docs/llm.md +460 -0
- package/docs/react.md +134 -0
- package/docs/vite.md +42 -0
- package/package.json +1 -1
package/docs/CHANGELOG.md
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
(e.g. `!npm run dev` after `genaicode embed`), its output in the transcript; `/stop`, Esc
|
|
21
21
|
or the Stop button end it and what it started, `!!` sends a leading `!` to the agent.
|
|
22
22
|
`<AgentChat canStop>` offers Stop while the agent is idle.
|
|
23
|
+
- `Markdown` renders GFM tables (alignment, `\|` escapes, horizontal scroll when wide),
|
|
24
|
+
`~~strikethrough~~` and task lists (`- [x]`). A table may follow a paragraph line directly.
|
|
23
25
|
|
|
24
26
|
### Changed
|
|
25
27
|
|
package/docs/agents.md
CHANGED
|
@@ -7,6 +7,57 @@
|
|
|
7
7
|
behind one interface. It is the agent-side counterpart of `ModelProvider`. A driver
|
|
8
8
|
translates at the edge and does not own application policy.
|
|
9
9
|
|
|
10
|
+
## Quick look
|
|
11
|
+
|
|
12
|
+
`genaicode/agents` turns the coding-agent CLIs installed on a machine into one API. Give
|
|
13
|
+
any of them a task (a prompt and a working directory) and get back the same event stream
|
|
14
|
+
and result, whichever agent does the work. It is how you script, compare, or chain coding
|
|
15
|
+
agents from a job, a bot, or a CI step without writing a parser per vendor.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { claude, codex, copilot, cursor, detectAgents } from 'genaicode/agents';
|
|
19
|
+
|
|
20
|
+
const [found] = detectAgents([claude(), codex(), copilot(), cursor()]).filter(({ path }) => path);
|
|
21
|
+
if (!found) throw new Error('No coding agent installed.');
|
|
22
|
+
|
|
23
|
+
const run = found.agent.run({ prompt: 'Add a unit test for parseDate', cwd: '/path/to/repo', timeoutMs: 20 * 60_000 });
|
|
24
|
+
for await (const event of run) {
|
|
25
|
+
if (event.type === 'tool-start') console.log('⚙', event.name);
|
|
26
|
+
if (event.type === 'file-change') console.log('edited', event.paths.join(', '));
|
|
27
|
+
}
|
|
28
|
+
const result = await run.result; // { status, ok, text, sessionId, usage, error, ... }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| Agent | Driver | Extras |
|
|
32
|
+
| ---------------- | ----------------------------- | ----------------------------------------------- |
|
|
33
|
+
| Claude Code | `claude()` | MCP servers, approvals, max turns, effort, cost |
|
|
34
|
+
| Codex | `codex()`, `codexLive()` | MCP servers; live: `steer()`, approvals |
|
|
35
|
+
| GitHub Copilot | `copilot()` | MCP servers, allow/deny tool patterns |
|
|
36
|
+
| Cursor | `cursor()` | streamed text deltas |
|
|
37
|
+
| Gemini CLI | `gemini()` | approval mode |
|
|
38
|
+
| opencode | `opencode()` | `provider/model` ids, variants |
|
|
39
|
+
| Mistral Vibe | `vibe()` | agent profile, max turns, max price |
|
|
40
|
+
| Antigravity CLI | `antigravity()` | sandbox, effort, usage |
|
|
41
|
+
| Muse | `muse()`, `museLive()` | max turns; live: `steer()`, approvals |
|
|
42
|
+
| Your own CLI/API | `cliAgent()`, `hostedAgent()` | plug in any JSON-lines CLI or hosted agent |
|
|
43
|
+
|
|
44
|
+
On top of the drivers:
|
|
45
|
+
|
|
46
|
+
- **Steer a running task** with `run.steer(text)` (live drivers), and answer permission
|
|
47
|
+
prompts with `onApproval` (Claude, live Codex and Muse).
|
|
48
|
+
- **Pick approval and sandbox policy** with `permissions: { approval, sandbox }` (or
|
|
49
|
+
`'yolo'`); each driver maps it to the agent's own flags and refuses what it cannot honor.
|
|
50
|
+
- **Attach MCP servers per task** with `mcpServers`. Header secrets stay out of argv.
|
|
51
|
+
- **Verify and repair**: `runWithVerify` runs your check (tests, lint) after the agent and
|
|
52
|
+
sends failures back for another attempt.
|
|
53
|
+
- **Keep credentials apart**: `withoutProviderCredentials()` strips your app's LLM API keys
|
|
54
|
+
from the agent's environment, so it bills its own login.
|
|
55
|
+
|
|
56
|
+
Importing `genaicode` never spawns anything; only `genaicode/agents` does. The agent uses
|
|
57
|
+
its own credentials and billing, and its own permission settings unless `permissions` sets
|
|
58
|
+
them; any sandbox is the agent's own. GenAIcode does not choose a model or retry it. See the sections below for events, options per
|
|
59
|
+
driver, and writing your own driver.
|
|
60
|
+
|
|
10
61
|
## Scope
|
|
11
62
|
|
|
12
63
|
In scope:
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Agent inside your app (`genaicode/app-agent`)
|
|
2
|
+
|
|
3
|
+
[← README](../README.md)
|
|
4
|
+
|
|
5
|
+
`genaicode/app-agent` puts an agent in a local app you run on your machine (an admin
|
|
6
|
+
console, an internal tool, a game editor). The user chats with an agent CLI they already
|
|
7
|
+
have; the agent works the app through tools the app serves over MCP, changes wait for the
|
|
8
|
+
user's approval, and in `dev` mode the agent also edits the app's code and proposes a commit.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { createServer } from 'node:http';
|
|
12
|
+
import { createAppAgent, createAppAgentHandler } from 'genaicode/app-agent';
|
|
13
|
+
|
|
14
|
+
const agent = createAppAgent({
|
|
15
|
+
name: 'the shop admin',
|
|
16
|
+
mcpUrl: 'http://127.0.0.1:3000/api/agent/mcp',
|
|
17
|
+
tools: [
|
|
18
|
+
{ name: 'orders', description: 'List open orders.', run: () => JSON.stringify(listOrders()) },
|
|
19
|
+
{
|
|
20
|
+
name: 'refund',
|
|
21
|
+
description: 'Refund an order.',
|
|
22
|
+
write: true, // a card with Approve and Reject; runs only after Approve
|
|
23
|
+
inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
|
|
24
|
+
run: ({ id }) => refund(String(id)),
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
pages: () => ['/orders', '/customers'], // page context, link chips, "take me there"
|
|
28
|
+
dev: { cwd: process.cwd(), commands: ['npm test'] }, // optional: the agent edits the app
|
|
29
|
+
});
|
|
30
|
+
const handle = createAppAgentHandler(agent, { authorize: (req) => isSignedIn(req) });
|
|
31
|
+
|
|
32
|
+
createServer(async (req, res) => {
|
|
33
|
+
if (await handle(req, res)) return;
|
|
34
|
+
// ...the rest of the app
|
|
35
|
+
}).listen(3000, '127.0.0.1');
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
On the page, `AppAgentChat` from `genaicode/react` is the whole drawer: the chat, the agent's
|
|
39
|
+
page chips under its replies, Approve and Reject cards (with the diff of a proposed commit),
|
|
40
|
+
and the agent and mode pickers. It reports `currentPath` to the agent and calls `onNavigate`
|
|
41
|
+
when a chip is clicked or the agent is asked to go somewhere.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { AppAgentChat } from 'genaicode/react';
|
|
45
|
+
import 'genaicode/react/styles.css';
|
|
46
|
+
|
|
47
|
+
<AppAgentChat currentPath={location.pathname} onNavigate={(path) => router.push(path)} />;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
<p align="center">
|
|
51
|
+
<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%">
|
|
52
|
+
</p>
|
|
53
|
+
|
|
54
|
+
Under it, `/api/agent` serves `GET /events` (a stream of `AppAgentState`: the session, earlier
|
|
55
|
+
turns, pending actions, link chips, navigation requests) and `POST /send`, `/stop`, `/reset`,
|
|
56
|
+
`/config`, `/view`, `/actions/:id` and `/approvals/:id` (the agent CLI's own permission
|
|
57
|
+
prompts); `useAppAgent` wraps them for a page of your own. Switching agent or mode keeps the
|
|
58
|
+
conversation: the next agent gets a short transcript. `trace` receives every prompt, MCP call,
|
|
59
|
+
decision and finished turn, for a log. Default agents are Claude Code, Codex and
|
|
60
|
+
Copilot CLI, locked down per mode: in `use` mode they get only the app's tools (no shell, no
|
|
61
|
+
file edits); in `dev` mode they edit files and run the listed commands, never commit or push (Claude and
|
|
62
|
+
Copilot enforce the command list; Codex has no per-command allowlist, so it runs in its
|
|
63
|
+
`workspace-write` sandbox: writes only inside `cwd`, no network).
|
|
64
|
+
`propose_commit` snapshots the worktree, the user reviews that diff, and Approve commits
|
|
65
|
+
exactly that tree on the reviewed HEAD, or refuses if the files or HEAD changed since, a hook
|
|
66
|
+
changed the files, or a merge or rebase is in progress. The repository's commit hooks run.
|
|
67
|
+
The agent sees no MCP server but the app's: Claude runs with `--strict-mcp-config`, and Codex
|
|
68
|
+
and Copilot get the user's own configured servers switched off. The MCP endpoint takes a per-run
|
|
69
|
+
bearer and refuses browser requests; every other route asks `authorize` and refuses
|
|
70
|
+
cross-site requests. Without `authorize` only a loopback `Host` is accepted (add names with
|
|
71
|
+
`allowedHosts`), so a DNS-rebinding page cannot reach the agent.
|
package/docs/cli.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Command line: run, chat, ui, embed
|
|
2
|
+
|
|
3
|
+
[← README](../README.md)
|
|
4
|
+
|
|
5
|
+
## From the command line
|
|
6
|
+
|
|
7
|
+
The `genaicode` bin runs the same headless drivers without writing any code:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx genaicode agents # which agent CLIs are installed
|
|
11
|
+
npx genaicode run "Add a unit test for parseDate" # first installed agent, current dir
|
|
12
|
+
npx genaicode run -a codex -C ../api --verify "npm test" "Fix the failing date tests"
|
|
13
|
+
git diff | npx genaicode run --json -a claude - # prompt from stdin, JSON-lines events
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Assistant text goes to stdout and tool calls, edits, and the result line go to stderr.
|
|
17
|
+
`--verify` runs a shell command after the agent finishes and sends its output back for up
|
|
18
|
+
to `--max-repairs` more attempts (`runWithVerify`). The exit code is 0 on success, 1 when
|
|
19
|
+
the agent or the check fails, 2 on a usage error, and 130 when interrupted.
|
|
20
|
+
`npx genaicode --help` lists every option.
|
|
21
|
+
|
|
22
|
+
## Chat with an agent: terminal and browser
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx genaicode # chat in this terminal (same as "genaicode chat")
|
|
26
|
+
npx genaicode chat -a claude -C ../api
|
|
27
|
+
npx genaicode ui # the same chat in your browser, served on 127.0.0.1
|
|
28
|
+
npx genaicode chat --web # both: the terminal and the browser on one session
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The terminal and the browser can show one session. `/web` in the terminal chat opens it in
|
|
32
|
+
the browser (`/web off` stops the server), and Enter in the terminal that runs
|
|
33
|
+
`genaicode ui` brings it into that terminal. A prompt, an approval or a stop from either
|
|
34
|
+
side shows up in both.
|
|
35
|
+
|
|
36
|
+
Each prompt after the first continues the agent's own session (`AgentTask.resume`), so you
|
|
37
|
+
can say "now add a test for that". Prompts sent while the agent works wait in a queue and
|
|
38
|
+
run next; Esc stops the agent. When the agent asks for permission, `y` approves, `n`
|
|
39
|
+
denies and `a` approves everything from then on (`/auto`, or the Auto-approve chip in the
|
|
40
|
+
browser; `-y` starts that way). `!` on an empty prompt switches to shell mode, as in Claude
|
|
41
|
+
Code: `!npm run dev` runs in the project with its output in the transcript, and `/stop` (or
|
|
42
|
+
Esc) ends it. `/agent`, `/model` and `/new` switch agent,
|
|
43
|
+
model and session; `/help` lists the rest.
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<picture>
|
|
47
|
+
<source media="(prefers-reduced-motion: reduce)" srcset="media/screenshots/chat-terminal.png">
|
|
48
|
+
<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%">
|
|
49
|
+
</picture>
|
|
50
|
+
<picture>
|
|
51
|
+
<source media="(prefers-reduced-motion: reduce) and (prefers-color-scheme: dark)" srcset="media/screenshots/wolf-dark.png">
|
|
52
|
+
<source media="(prefers-reduced-motion: reduce)" srcset="media/screenshots/wolf-light.png">
|
|
53
|
+
<source media="(prefers-color-scheme: dark)" srcset="media/screenshots/chat-browser-dark.gif">
|
|
54
|
+
<source media="(prefers-color-scheme: light)" srcset="media/screenshots/chat-browser-light.gif">
|
|
55
|
+
<img alt="genaicode ui in a browser: the same fix and a follow-up." src="media/screenshots/chat-browser-light.gif" width="49%">
|
|
56
|
+
</picture>
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
The wolf from genaicode 1.0 is back. When the agent asks for approval or finishes, the
|
|
60
|
+
browser UI barks if its tab is in the background and counts those events in the tab title.
|
|
61
|
+
The terminal UI rings the terminal bell instead. `/bark off` (or the Bark button) quiets it.
|
|
62
|
+
|
|
63
|
+
<p align="center">
|
|
64
|
+
<picture>
|
|
65
|
+
<source media="(prefers-color-scheme: dark)" srcset="media/screenshots/wolf-dark.png">
|
|
66
|
+
<source media="(prefers-color-scheme: light)" srcset="media/screenshots/wolf-light.png">
|
|
67
|
+
<img alt="The browser UI with the wolf behind a finished turn." src="media/screenshots/wolf-light.png" width="80%">
|
|
68
|
+
</picture>
|
|
69
|
+
</p>
|
|
70
|
+
|
|
71
|
+
`genaicode ui` listens on the loopback address and prints a link with a random access
|
|
72
|
+
token. The page, the event stream and every command need that token; only the bundled
|
|
73
|
+
script and the four mascot files (`/app.js`, `/assets/…`) are served without it, since they
|
|
74
|
+
hold nothing about your session. Both front ends are bundled into the package and load
|
|
75
|
+
only for these commands; importing `genaicode` or `genaicode/agents` pulls in no UI code.
|
|
76
|
+
In code, the same conversation is `createAgentSession` from `genaicode/agents` (see
|
|
77
|
+
[agents.md](agents.md#chat-sessions)); with a live driver (`codexLive`,
|
|
78
|
+
`museLive`) it also steers the running agent and asks you about permission requests.
|
|
79
|
+
|
|
80
|
+
## Let your agent embed it
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx genaicode embed # in your project: your agent wires genaicode in
|
|
84
|
+
npx genaicode embed -a codex "only the dev panel"
|
|
85
|
+
npx genaicode embed --print | pbcopy # just the instructions, for any other agent
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`genaicode embed` does not inspect your project itself. It starts your agent with
|
|
89
|
+
instructions on how to embed genaicode, and the agent reads the project and picks the way
|
|
90
|
+
in: the [Vite overlay](vite.md) for an app on Vite; for any other Node dev server (webpack,
|
|
91
|
+
Next.js, Express...) the same overlay through `createDevOverlay` from `genaicode/ui`; for
|
|
92
|
+
pages with no dev server at all, a small dev-only server of its own with that overlay; the in-app agent (`genaicode/app-agent` with
|
|
93
|
+
`<AppAgentChat>`) when the agent should act on the app itself; and `npx genaicode ui` next
|
|
94
|
+
to the dev server when there is no Node process to host it. Words after `embed` go to the
|
|
95
|
+
agent as your request. You watch and answer in the same chat as `genaicode chat` (`--ui`
|
|
96
|
+
for the browser); without a terminal it runs headless like `run`. The agent installs the
|
|
97
|
+
package, edits the config, runs your checks and reports; it does not commit.
|
|
98
|
+
|
|
99
|
+
The instructions are also a Claude Code skill. Copy
|
|
100
|
+
[`skills/genaicode-embed`](skills/genaicode-embed/SKILL.md) into `.claude/skills/` (or
|
|
101
|
+
`~/.claude/skills/`) and ask Claude to "embed genaicode":
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
mkdir -p .claude/skills && cp -r node_modules/genaicode/docs/skills/genaicode-embed .claude/skills/
|
|
105
|
+
```
|