genaicode 2.7.0 → 2.9.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +47 -2
  3. package/dist/agents/defaults.d.ts +7 -0
  4. package/dist/agents/defaults.js +18 -0
  5. package/dist/agents/defaults.js.map +1 -0
  6. package/dist/agents/drivers/claude.js +9 -1
  7. package/dist/agents/drivers/claude.js.map +1 -1
  8. package/dist/agents/drivers/codex.js +4 -1
  9. package/dist/agents/drivers/codex.js.map +1 -1
  10. package/dist/agents/drivers/copilot.js +4 -0
  11. package/dist/agents/drivers/copilot.js.map +1 -1
  12. package/dist/agents/drivers/cursor.js +4 -1
  13. package/dist/agents/drivers/cursor.js.map +1 -1
  14. package/dist/agents/drivers/opencode.js +10 -1
  15. package/dist/agents/drivers/opencode.js.map +1 -1
  16. package/dist/agents/prepare.js +4 -0
  17. package/dist/agents/prepare.js.map +1 -1
  18. package/dist/agents/session.d.ts +108 -0
  19. package/dist/agents/session.js +329 -0
  20. package/dist/agents/session.js.map +1 -0
  21. package/dist/agents/types.d.ts +7 -0
  22. package/dist/agents.d.ts +2 -0
  23. package/dist/agents.js +1 -0
  24. package/dist/agents.js.map +1 -1
  25. package/dist/cli/args.d.ts +11 -0
  26. package/dist/cli/args.js +32 -0
  27. package/dist/cli/args.js.map +1 -1
  28. package/dist/cli/main.d.ts +32 -1
  29. package/dist/cli/main.js +57 -1
  30. package/dist/cli/main.js.map +1 -1
  31. package/dist/cli.js +1 -0
  32. package/dist/cli.js.map +1 -1
  33. package/dist/ui/assets/bark.mp3 +0 -0
  34. package/dist/ui/assets/wolf-64.png +0 -0
  35. package/dist/ui/assets/wolf-dark.webp +0 -0
  36. package/dist/ui/assets/wolf.webp +0 -0
  37. package/dist/ui/index.js +218 -0
  38. package/dist/ui/index.js.LEGAL.txt +56 -0
  39. package/dist/ui/web-client.js +14 -0
  40. package/dist/ui/web-client.js.LEGAL.txt +56 -0
  41. package/dist/vite/overlay.d.ts +19 -0
  42. package/dist/vite/overlay.js +180 -0
  43. package/dist/vite/overlay.js.map +1 -0
  44. package/dist/vite/plugin.d.ts +57 -0
  45. package/dist/vite/plugin.js +214 -0
  46. package/dist/vite/plugin.js.map +1 -0
  47. package/dist/vite.d.ts +11 -0
  48. package/dist/vite.js +12 -0
  49. package/dist/vite.js.map +1 -0
  50. package/docs/agents.md +40 -0
  51. package/docs/pivot.md +6 -3
  52. package/package.json +25 -5
  53. package/dist/cli/agents.d.ts +0 -6
  54. package/dist/cli/agents.js +0 -17
  55. package/dist/cli/agents.js.map +0 -1
@@ -0,0 +1,56 @@
1
+ Bundled license information:
2
+
3
+ react/cjs/react.production.js:
4
+ /**
5
+ * @license React
6
+ * react.production.js
7
+ *
8
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
9
+ *
10
+ * This source code is licensed under the MIT license found in the
11
+ * LICENSE file in the root directory of this source tree.
12
+ */
13
+
14
+ scheduler/cjs/scheduler.production.js:
15
+ /**
16
+ * @license React
17
+ * scheduler.production.js
18
+ *
19
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
20
+ *
21
+ * This source code is licensed under the MIT license found in the
22
+ * LICENSE file in the root directory of this source tree.
23
+ */
24
+
25
+ react-dom/cjs/react-dom.production.js:
26
+ /**
27
+ * @license React
28
+ * react-dom.production.js
29
+ *
30
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
31
+ *
32
+ * This source code is licensed under the MIT license found in the
33
+ * LICENSE file in the root directory of this source tree.
34
+ */
35
+
36
+ react-dom/cjs/react-dom-client.production.js:
37
+ /**
38
+ * @license React
39
+ * react-dom-client.production.js
40
+ *
41
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
42
+ *
43
+ * This source code is licensed under the MIT license found in the
44
+ * LICENSE file in the root directory of this source tree.
45
+ */
46
+
47
+ react/cjs/react-jsx-runtime.production.js:
48
+ /**
49
+ * @license React
50
+ * react-jsx-runtime.production.js
51
+ *
52
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
53
+ *
54
+ * This source code is licensed under the MIT license found in the
55
+ * LICENSE file in the root directory of this source tree.
56
+ */
@@ -0,0 +1,19 @@
1
+ /** What the plugin tells the overlay. */
2
+ export interface OverlayConfig {
3
+ /** Path of the plugin's endpoints on the dev server, e.g. `/__genaicode`. */
4
+ api: string;
5
+ /** Collect errors from the page and offer to send them to the agent. */
6
+ captureErrors: boolean;
7
+ }
8
+ /** The part of Vite's `import.meta.hot` the overlay listens to. */
9
+ export interface OverlayHot {
10
+ on(event: string, callback: (payload: unknown) => void): void;
11
+ }
12
+ /**
13
+ * The dev-server overlay: a wolf in the corner of the app that opens the genaicode UI in a
14
+ * panel, and collects the page's errors so one click sends them to the agent.
15
+ *
16
+ * The plugin serves this function's source (`mountOverlay.toString()`) as a module, so it must
17
+ * not use anything from outside its own body.
18
+ */
19
+ export declare function mountOverlay(config: OverlayConfig, hot: OverlayHot | undefined): void;
@@ -0,0 +1,180 @@
1
+ /**
2
+ * The dev-server overlay: a wolf in the corner of the app that opens the genaicode UI in a
3
+ * panel, and collects the page's errors so one click sends them to the agent.
4
+ *
5
+ * The plugin serves this function's source (`mountOverlay.toString()`) as a module, so it must
6
+ * not use anything from outside its own body.
7
+ */
8
+ export function mountOverlay(config, hot) {
9
+ if (document.querySelector('genaicode-overlay'))
10
+ return;
11
+ const MAX_ERRORS = 20;
12
+ const MAX_TEXT = 4000;
13
+ let errors = [];
14
+ let session;
15
+ const host = document.createElement('genaicode-overlay');
16
+ host.style.cssText = 'position:fixed;z-index:2147483647;right:0;bottom:0;';
17
+ const root = host.attachShadow({ mode: 'open' });
18
+ root.innerHTML = `<style>
19
+ :host { all: initial; }
20
+ * { box-sizing: border-box; font: 13px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
21
+ .wolf { position: fixed; right: 18px; bottom: 18px; width: 52px; height: 52px; border-radius: 50%; border: 1px solid #e4e4df;
22
+ background: #fff center / 34px no-repeat; box-shadow: 0 2px 10px rgba(0,0,0,.18); cursor: pointer; padding: 0; font-size: 26px; }
23
+ .wolf:hover { transform: scale(1.06); }
24
+ .badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px;
25
+ background: #c92a2a; color: #fff; font-size: 11px; font-weight: 700; line-height: 20px; text-align: center; }
26
+ .badge[hidden], .panel[hidden], .fix[hidden] { display: none; }
27
+ .panel { position: fixed; right: 18px; bottom: 82px; width: min(460px, calc(100vw - 36px)); height: min(680px, calc(100vh - 110px));
28
+ display: flex; flex-direction: column; background: #fff; border: 1px solid #e4e4df; border-radius: 14px; overflow: hidden;
29
+ box-shadow: 0 8px 40px rgba(0,0,0,.22); }
30
+ .head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid #e4e4df; background: #f7f7f5; color: #1d1d1b; }
31
+ .head b { flex: 1; }
32
+ .head button { border: 1px solid #e4e4df; background: #fff; color: #1d1d1b; border-radius: 8px; padding: 4px 10px; cursor: pointer; }
33
+ .head .fix { background: #c92a2a; border-color: #c92a2a; color: #fff; font-weight: 600; }
34
+ iframe { flex: 1; width: 100%; border: 0; background: #f7f7f5; }
35
+ .note { padding: 16px; color: #6b6b66; }
36
+ @media (prefers-color-scheme: dark) {
37
+ .wolf, .panel { background-color: #1d1d1c; border-color: #2e2e2c; }
38
+ .head { background: #141414; border-color: #2e2e2c; color: #ececea; }
39
+ .head button { background: #1d1d1c; border-color: #2e2e2c; color: #ececea; }
40
+ iframe { background: #141414; }
41
+ }
42
+ </style>
43
+ <div class="panel" hidden>
44
+ <div class="head"><b>genaicode</b><button class="fix" hidden></button><button class="close" title="Hide">✕</button></div>
45
+ </div>
46
+ <button class="wolf" title="genaicode"><span class="badge" hidden></span></button>`;
47
+ const $ = (selector) => root.querySelector(selector);
48
+ const wolf = $('.wolf');
49
+ const badge = $('.badge');
50
+ const panel = $('.panel');
51
+ const fix = $('.fix');
52
+ let frame;
53
+ const render = () => {
54
+ badge.hidden = errors.length === 0;
55
+ badge.textContent = String(errors.length);
56
+ fix.hidden = errors.length === 0;
57
+ fix.textContent = `Fix ${errors.length} error${errors.length === 1 ? '' : 's'}`;
58
+ const label = errors.length
59
+ ? `genaicode: ${errors.length} error${errors.length === 1 ? '' : 's'} on this page`
60
+ : `genaicode${session ? ` (${session.agent})` : ''}`;
61
+ wolf.title = label;
62
+ wolf.setAttribute('aria-label', label);
63
+ };
64
+ const loadSession = async () => {
65
+ if (session)
66
+ return session;
67
+ const response = await fetch(`${config.api}/session`, { credentials: 'same-origin' });
68
+ if (!response.ok)
69
+ throw new Error(`genaicode: ${response.status}`);
70
+ session = (await response.json());
71
+ wolf.style.backgroundImage = `url(${new URL('/assets/wolf-64.png', session.url).href})`;
72
+ render();
73
+ return session;
74
+ };
75
+ // One frame, even when the wolf and "Fix" are clicked before the session has loaded.
76
+ const open = () => {
77
+ panel.hidden = false;
78
+ frame ??= loadSession().then(({ url }) => {
79
+ const iframe = document.createElement('iframe');
80
+ iframe.src = url;
81
+ iframe.title = 'genaicode';
82
+ panel.append(iframe);
83
+ }, (error) => {
84
+ const note = document.createElement('div');
85
+ note.className = 'note';
86
+ note.textContent = `The genaicode UI is not available: ${error.message}. See the dev server's terminal.`;
87
+ panel.append(note);
88
+ });
89
+ return frame;
90
+ };
91
+ wolf.addEventListener('click', () => (panel.hidden ? void open() : (panel.hidden = true)));
92
+ $('.close').addEventListener('click', () => (panel.hidden = true));
93
+ fix.addEventListener('click', async () => {
94
+ const sent = errors;
95
+ errors = [];
96
+ render();
97
+ await open();
98
+ const response = await fetch(`${config.api}/fix`, {
99
+ method: 'POST',
100
+ credentials: 'same-origin',
101
+ headers: { 'content-type': 'application/json' },
102
+ body: JSON.stringify({ page: location.origin + location.pathname, errors: sent }),
103
+ }).catch(() => undefined);
104
+ if (!response?.ok) {
105
+ errors = [...sent, ...errors].slice(-MAX_ERRORS);
106
+ render();
107
+ }
108
+ });
109
+ const text = (value) => {
110
+ if (value instanceof Error)
111
+ return value.message;
112
+ if (typeof value === 'string')
113
+ return value;
114
+ try {
115
+ return JSON.stringify(value) ?? String(value);
116
+ }
117
+ catch {
118
+ try {
119
+ return String(value);
120
+ }
121
+ catch {
122
+ return Object.prototype.toString.call(value);
123
+ }
124
+ }
125
+ };
126
+ const add = (error) => {
127
+ error.message = error.message.slice(0, MAX_TEXT);
128
+ if (error.stack)
129
+ error.stack = error.stack.slice(0, MAX_TEXT);
130
+ if (errors.some((seen) => seen.message === error.message && seen.source === error.source))
131
+ return;
132
+ errors = [...errors, error].slice(-MAX_ERRORS);
133
+ render();
134
+ };
135
+ if (config.captureErrors) {
136
+ window.addEventListener('error', (event) => {
137
+ const where = event.filename ? ` (${event.filename}:${event.lineno}:${event.colno})` : '';
138
+ add({ source: 'error', message: `${event.message}${where}`, stack: event.error?.stack });
139
+ });
140
+ window.addEventListener('unhandledrejection', (event) => {
141
+ add({ source: 'rejection', message: text(event.reason), stack: event.reason?.stack });
142
+ });
143
+ const consoleError = console.error.bind(console);
144
+ console.error = (...args) => {
145
+ consoleError(...args);
146
+ // Collecting the error must never break the app's own logging.
147
+ try {
148
+ add({
149
+ source: 'console',
150
+ message: args.map(text).join(' '),
151
+ stack: args.find((arg) => arg instanceof Error)?.stack,
152
+ });
153
+ }
154
+ catch {
155
+ // Ignore values that cannot be described.
156
+ }
157
+ };
158
+ hot?.on('vite:error', (payload) => {
159
+ const err = payload.err;
160
+ if (!err)
161
+ return;
162
+ const file = err.id ? `\n${err.id}` : '';
163
+ add({ source: 'vite', message: `${err.message ?? 'Vite error'}${file}${err.frame ? `\n${err.frame}` : ''}` });
164
+ });
165
+ // A successful update means the build errors are gone; keep what the running page reported.
166
+ hot?.on('vite:afterUpdate', () => {
167
+ const before = errors.length;
168
+ errors = errors.filter((error) => error.source !== 'vite');
169
+ if (errors.length !== before)
170
+ render();
171
+ });
172
+ }
173
+ document.body.append(host);
174
+ render();
175
+ void loadSession().catch(() => {
176
+ wolf.textContent = '🐺';
177
+ wolf.append(badge);
178
+ });
179
+ }
180
+ //# sourceMappingURL=overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/vite/overlay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { Plugin } from 'vite';
2
+ import type { CodingAgent } from '../agents/types.js';
3
+ export interface GenaicodeViteOptions {
4
+ /** Agent to start with. Default: the first installed one. */
5
+ agent?: string;
6
+ model?: string;
7
+ effort?: string;
8
+ /** Approve every permission request without asking. */
9
+ approveAll?: boolean;
10
+ /** Agents to offer. Default: the same headless drivers as `genaicode ui`. */
11
+ agents?: readonly CodingAgent[];
12
+ /** Collect the page's errors and offer to send them to the agent. Default true. */
13
+ captureErrors?: boolean;
14
+ /** Port of the genaicode UI on 127.0.0.1. Default: a free port. */
15
+ port?: number;
16
+ /** Loads the bundled front ends. Defaults to `dist/ui/index.js`; tests pass the sources. */
17
+ loadUi?(): Promise<EmbeddedUiModule>;
18
+ }
19
+ /** What the plugin needs from the bundled front ends (see `startEmbeddedWeb` in src/ui/index.tsx). */
20
+ export interface EmbeddedUiModule {
21
+ NoAgentError: new (...args: never[]) => Error;
22
+ startEmbeddedWeb(options: {
23
+ agents: readonly CodingAgent[];
24
+ agent?: string;
25
+ cwd: string;
26
+ model?: string;
27
+ effort?: string;
28
+ approveAll?: boolean;
29
+ version: string;
30
+ port?: number;
31
+ frameAncestors: () => readonly string[];
32
+ }): Promise<{
33
+ url: string;
34
+ controller: {
35
+ submit(text: string): unknown;
36
+ get(): {
37
+ session: {
38
+ agent: string;
39
+ };
40
+ };
41
+ };
42
+ close(): Promise<void>;
43
+ }>;
44
+ }
45
+ /**
46
+ * `genaicode/vite`: the genaicode UI inside a Vite dev server. The page gets a wolf in the
47
+ * corner that opens the chat with a coding agent working in the project, and its errors
48
+ * (build errors, uncaught exceptions, console.error) go to the agent with one click.
49
+ *
50
+ * Only `vite dev`: builds are untouched. The UI runs on its own port on 127.0.0.1, so a dev
51
+ * server started with `--host` does not expose the agent to the network.
52
+ */
53
+ export declare function genaicode(options?: GenaicodeViteOptions): Plugin;
54
+ /** The prompt for "Fix N errors", or undefined when the body is not a list of errors. */
55
+ export declare function fixPrompt(body: unknown): string | undefined;
56
+ /** 127.0.0.0/8 and ::1, also as IPv4-mapped IPv6 addresses. */
57
+ export declare function isLoopback(address: string | undefined): boolean;
@@ -0,0 +1,214 @@
1
+ import { createRequire } from 'node:module';
2
+ import { defaultAgents } from '../agents/defaults.js';
3
+ import { mountOverlay } from './overlay.js';
4
+ const API = '/__genaicode';
5
+ const OVERLAY_ID = 'virtual:genaicode-overlay';
6
+ const MAX_BODY = 256 * 1024;
7
+ /**
8
+ * `genaicode/vite`: the genaicode UI inside a Vite dev server. The page gets a wolf in the
9
+ * corner that opens the chat with a coding agent working in the project, and its errors
10
+ * (build errors, uncaught exceptions, console.error) go to the agent with one click.
11
+ *
12
+ * Only `vite dev`: builds are untouched. The UI runs on its own port on 127.0.0.1, so a dev
13
+ * server started with `--host` does not expose the agent to the network.
14
+ */
15
+ export function genaicode(options = {}) {
16
+ let started;
17
+ let base = '/';
18
+ // Origins the app's pages were actually opened at (e.g. app.localhost), for frame-ancestors.
19
+ const seen = new Set();
20
+ return {
21
+ name: 'genaicode',
22
+ apply: 'serve',
23
+ configResolved(config) {
24
+ base = config.base;
25
+ },
26
+ configureServer(server) {
27
+ const log = server.config.logger;
28
+ started = (async () => {
29
+ const ui = await (options.loadUi ?? loadBundledUi)();
30
+ try {
31
+ return await ui.startEmbeddedWeb({
32
+ agents: options.agents ?? defaultAgents(),
33
+ agent: options.agent,
34
+ cwd: server.config.root,
35
+ model: options.model,
36
+ effort: options.effort,
37
+ approveAll: options.approveAll,
38
+ version: packageVersion(),
39
+ port: options.port,
40
+ frameAncestors: () => pageOrigins(server, seen),
41
+ });
42
+ }
43
+ catch (error) {
44
+ if (!(error instanceof ui.NoAgentError))
45
+ throw error;
46
+ log.warn(`[genaicode] ${error.message} The overlay is off.`);
47
+ return undefined;
48
+ }
49
+ })().then((ui) => {
50
+ if (ui)
51
+ log.info(` ➜ genaicode: ${ui.controller.get().session.agent} in the page, or open ${ui.url}`);
52
+ return ui;
53
+ }, (error) => {
54
+ log.error(`[genaicode] The UI did not start: ${error.message}`);
55
+ return undefined;
56
+ });
57
+ server.middlewares.use(API, (req, res, next) => {
58
+ handleApi(req, res, started, (origin) => seen.add(origin), !!server.config.server.https).catch(next);
59
+ });
60
+ },
61
+ resolveId(id) {
62
+ if (id === OVERLAY_ID)
63
+ return `\0${OVERLAY_ID}`;
64
+ },
65
+ load(id) {
66
+ if (id !== `\0${OVERLAY_ID}`)
67
+ return;
68
+ const config = { api: API, captureErrors: options.captureErrors ?? true };
69
+ return `(${mountOverlay.toString()})(${JSON.stringify(config)}, import.meta.hot);\n`;
70
+ },
71
+ async transformIndexHtml() {
72
+ if (!(await started))
73
+ return;
74
+ return [
75
+ {
76
+ tag: 'script',
77
+ attrs: { type: 'module', src: `${base}@id/__x00__${OVERLAY_ID}` },
78
+ // First, so the app's own startup errors are caught too. Module scripts are deferred.
79
+ injectTo: 'head-prepend',
80
+ },
81
+ ];
82
+ },
83
+ // Vite calls this when the dev server closes or restarts.
84
+ async buildEnd() {
85
+ const ui = await started;
86
+ started = undefined;
87
+ await ui?.close();
88
+ },
89
+ };
90
+ }
91
+ /** The dev server's own endpoints for the overlay: the UI link, and "fix these errors". */
92
+ async function handleApi(req, res, started, onPage, https) {
93
+ const send = (status, body) => {
94
+ res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store' });
95
+ res.end(JSON.stringify(body));
96
+ };
97
+ // Only this machine: with --host the dev server also answers the network, and Sec-Fetch-Site
98
+ // is just a header a client there could send. Then only the app's own pages: another site
99
+ // open in the browser must not read the UI's token or start the agent.
100
+ if (!isLoopback(req.socket.remoteAddress))
101
+ return send(403, { error: 'this machine only' });
102
+ if (req.headers['sec-fetch-site'] !== 'same-origin')
103
+ return send(403, { error: 'same-origin only' });
104
+ const ui = await started;
105
+ if (!ui)
106
+ return send(503, { error: 'genaicode is off; see the dev server terminal' });
107
+ const path = (req.url ?? '/').split('?')[0];
108
+ if (req.method === 'GET' && path === '/session') {
109
+ const origin = pageOrigin(req.headers.host, https);
110
+ if (origin)
111
+ onPage(origin);
112
+ return send(200, { url: ui.url, agent: ui.controller.get().session.agent });
113
+ }
114
+ if (req.method === 'POST' && path === '/fix') {
115
+ if (!String(req.headers['content-type'] ?? '').startsWith('application/json')) {
116
+ return send(415, { error: 'expected JSON' });
117
+ }
118
+ let prompt;
119
+ try {
120
+ prompt = fixPrompt(JSON.parse(await readBody(req)));
121
+ }
122
+ catch {
123
+ prompt = undefined;
124
+ }
125
+ if (!prompt)
126
+ return send(400, { error: 'bad request' });
127
+ ui.controller.submit(prompt);
128
+ return send(200, { ok: true });
129
+ }
130
+ send(404, { error: 'not found' });
131
+ }
132
+ const SOURCES = {
133
+ vite: 'build error',
134
+ error: 'uncaught error',
135
+ rejection: 'unhandled rejection',
136
+ console: 'console.error',
137
+ };
138
+ /** The prompt for "Fix N errors", or undefined when the body is not a list of errors. */
139
+ export function fixPrompt(body) {
140
+ if (!body || typeof body !== 'object')
141
+ return undefined;
142
+ const { page, errors } = body;
143
+ if (!Array.isArray(errors) || errors.length === 0)
144
+ return undefined;
145
+ const items = [];
146
+ for (const error of errors.slice(0, 20)) {
147
+ if (!error || typeof error !== 'object')
148
+ return undefined;
149
+ const { source, message, stack } = error;
150
+ if (typeof message !== 'string' || typeof source !== 'string' || !Object.hasOwn(SOURCES, source))
151
+ return undefined;
152
+ const trace = typeof stack === 'string' && stack && !message.includes(stack) ? `\n${stack.slice(0, 4000)}` : '';
153
+ items.push(`${items.length + 1}. [${SOURCES[source]}] ${message.slice(0, 4000)}${trace}`);
154
+ }
155
+ const where = typeof page === 'string' && /^https?:\/\//.test(page) ? ` at ${page.slice(0, 500)}` : '';
156
+ return (`The app running in the Vite dev server${where} reports ${items.length === 1 ? 'this error' : 'these errors'} ` +
157
+ `in the browser. Find the cause in the code and fix it.\n\n` +
158
+ '```\n' +
159
+ items.join('\n\n').replace(/```/g, "'''") +
160
+ '\n```');
161
+ }
162
+ /** 127.0.0.0/8 and ::1, also as IPv4-mapped IPv6 addresses. */
163
+ export function isLoopback(address) {
164
+ if (!address)
165
+ return false;
166
+ const v4 = address.startsWith('::ffff:') ? address.slice(7) : address;
167
+ return address === '::1' || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(v4);
168
+ }
169
+ /** The origin a same-origin request came from, by its Host header. */
170
+ function pageOrigin(host, https) {
171
+ if (!host || !/^[\w.-]+(:\d+)?$|^\[[\da-f:.]+\](:\d+)?$/i.test(host))
172
+ return undefined;
173
+ return `${https ? 'https' : 'http'}://${host.toLowerCase()}`;
174
+ }
175
+ /** Where the app's pages come from, allowed to show the UI in a frame. */
176
+ function pageOrigins(server, seen) {
177
+ const urls = [...(server.resolvedUrls?.local ?? []), ...(server.resolvedUrls?.network ?? [])];
178
+ const origins = new Set(seen);
179
+ for (const url of urls) {
180
+ try {
181
+ origins.add(new URL(url).origin);
182
+ }
183
+ catch {
184
+ // Not a URL: skip it.
185
+ }
186
+ }
187
+ if (origins.size === 0) {
188
+ // Middleware mode, or not listening yet: any local port.
189
+ for (const origin of ['http://localhost:*', 'http://127.0.0.1:*', 'http://[::1]:*'])
190
+ origins.add(origin);
191
+ }
192
+ return [...origins];
193
+ }
194
+ async function readBody(req) {
195
+ let size = 0;
196
+ const chunks = [];
197
+ for await (const chunk of req) {
198
+ size += chunk.length;
199
+ if (size > MAX_BODY)
200
+ throw new Error('Request too large');
201
+ chunks.push(chunk);
202
+ }
203
+ return Buffer.concat(chunks).toString('utf8');
204
+ }
205
+ /** The front ends are bundled into dist/ui by scripts/build-ui.mjs; the path is kept opaque to tsc. */
206
+ function loadBundledUi() {
207
+ const bundle = new URL('../ui/index.js', import.meta.url).href;
208
+ return import(bundle);
209
+ }
210
+ function packageVersion() {
211
+ const require = createRequire(import.meta.url);
212
+ return require('../../package.json').version;
213
+ }
214
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"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"}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `genaicode/vite`: chat with a coding agent from inside the app in `vite dev`.
3
+ *
4
+ * ```ts
5
+ * import { defineConfig } from 'vite';
6
+ * import genaicode from 'genaicode/vite';
7
+ *
8
+ * export default defineConfig({ plugins: [genaicode()] });
9
+ * ```
10
+ */
11
+ export { genaicode, genaicode as default, type GenaicodeViteOptions } from './vite/plugin.js';
package/dist/vite.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `genaicode/vite`: chat with a coding agent from inside the app in `vite dev`.
3
+ *
4
+ * ```ts
5
+ * import { defineConfig } from 'vite';
6
+ * import genaicode from 'genaicode/vite';
7
+ *
8
+ * export default defineConfig({ plugins: [genaicode()] });
9
+ * ```
10
+ */
11
+ export { genaicode, genaicode as default } from './vite/plugin.js';
12
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,SAAS,EAAE,SAAS,IAAI,OAAO,EAA6B,MAAM,kBAAkB,CAAC"}
package/docs/agents.md CHANGED
@@ -74,6 +74,46 @@ failure of its own. A zero exit alone is not treated as success.
74
74
 
75
75
  Vendor events that have no mapping are dropped.
76
76
 
77
+ ## Follow-up turns
78
+
79
+ `result.sessionId` names the agent's own session. Pass it as `resume` to continue that
80
+ session with a new prompt; the agent keeps the earlier turns as context:
81
+
82
+ ```ts
83
+ const agent = claude();
84
+ const first = await agent.run({ prompt: 'Add a --dry-run flag', cwd }).result;
85
+ const next = await agent.run({ prompt: 'Now cover it with a test', cwd, resume: first.sessionId }).result;
86
+ ```
87
+
88
+ `claude`, `codex`, `cursor`, `opencode` and `copilot` support it (`capabilities.resume`).
89
+ Other drivers fail the task before spawning anything rather than starting a fresh session.
90
+
91
+ ## Chat sessions
92
+
93
+ `createAgentSession` keeps a conversation with one agent for chat front ends; the
94
+ `genaicode chat` and `genaicode ui` commands are built on it:
95
+
96
+ ```ts
97
+ import { claude, createAgentSession } from 'genaicode/agents';
98
+
99
+ const session = createAgentSession({ agent: claude(), cwd: '/work/repo' });
100
+ session.subscribe((state) => render(state)); // a new immutable snapshot on every change
101
+ session.send('Add a --dry-run flag');
102
+ await session.idle();
103
+ session.send('Now cover it with a test'); // resumes the same agent session
104
+ ```
105
+
106
+ - `state.turns[]` holds each prompt with its transcript: `text` (streamed, then final),
107
+ `tool` (input, clipped output, error flag), `files`, `approval`, `input` (steered text)
108
+ and `error` entries, plus the turn's `AgentResult`. Usage and cost add up in `state`.
109
+ - `send()` while a turn runs steers the agent when it supports `steer()`, and otherwise
110
+ queues the prompt; queued prompts run in order. `stop()` aborts the turn and clears the
111
+ queue.
112
+ - Approval requests wait in `state.approvals` until `approve(id, decision)`, unless
113
+ `autoApprove` decides them. `stop()` denies whatever is pending.
114
+ - `setAgent()` switches agents between turns and starts a fresh agent session; `reset()`
115
+ does the same for the current agent.
116
+
77
117
  ## Drivers
78
118
 
79
119
  | Driver | Command | Mode | Notes |
package/docs/pivot.md CHANGED
@@ -44,9 +44,12 @@ The following 1.x capabilities are intentionally removed:
44
44
  The 2.x `genaicode/agents` subpath does not restore these. It drives _external_
45
45
  coding-agent CLIs behind one task/event interface, the same way providers wrap model APIs,
46
46
  and it adds no agent loop, prompts, or repository tools of its own. See [agents.md](./agents.md).
47
- The `genaicode` bin (`npx genaicode run`) is a thin command-line front end to those drivers,
48
- under the same rule: it parses flags, prints events, and adds nothing the library does not
49
- already do.
47
+ The `genaicode` bin (`npx genaicode run`, `chat`, `ui`) is a thin front end to those drivers,
48
+ under the same rule: it parses flags, shows events, and adds nothing the library does not
49
+ already do. Its terminal and browser chat are bundled (Ink, React) into `dist/ui` and load
50
+ only for those commands, so the library keeps no UI dependencies. `genaicode/vite` brings
51
+ back a Vite dev plugin in the same shape: it shows that browser chat inside the app and
52
+ hands the page's errors to the external agent as a prompt; it does not generate code itself.
50
53
 
51
54
  This is a major-version break. The old implementation remains available in git history
52
55
  and in the 1.x npm line.