genaicode 2.18.2 → 2.18.4

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
@@ -129,8 +129,10 @@ Each prompt after the first continues the agent's own session (`AgentTask.resume
129
129
  can say "now add a test for that". Prompts sent while the agent works wait in a queue and
130
130
  run next; Esc stops the agent. When the agent asks for permission, `y` approves, `n`
131
131
  denies and `a` approves everything from then on (`/auto`, or the Auto-approve chip in the
132
- browser; `-y` starts that way). `/agent`, `/model` and `/new` switch agent, model and
133
- session; `/help` lists the rest.
132
+ browser; `-y` starts that way). `!` on an empty prompt switches to shell mode, as in Claude
133
+ Code: `!npm run dev` runs in the project with its output in the transcript, and `/stop` (or
134
+ Esc) ends it. `/agent`, `/model` and `/new` switch agent,
135
+ model and session; `/help` lists the rest.
134
136
 
135
137
  <p align="center">
136
138
  <picture>
@@ -178,8 +180,8 @@ npx genaicode embed --print | pbcopy # just the instructions, for any other
178
180
  `genaicode embed` does not inspect your project itself. It starts your agent with
179
181
  instructions on how to embed genaicode, and the agent reads the project and picks the way
180
182
  in: the Vite overlay below for an app on Vite; for any other Node dev server (webpack,
181
- Next.js, Express...) a development-only panel that shows the same chat through
182
- `startEmbeddedWeb` from `genaicode/ui`; the in-app agent (`genaicode/app-agent` with
183
+ Next.js, Express...) the same overlay through `createDevOverlay` from `genaicode/ui`; for
184
+ 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
183
185
  `<AppAgentChat>`) when the agent should act on the app itself; and `npx genaicode ui` next
184
186
  to the dev server when there is no Node process to host it. Words after `embed` go to the
185
187
  agent as your request. You watch and answer in the same chat as `genaicode chat` (`--ui`
@@ -187,11 +189,11 @@ for the browser); without a terminal it runs headless like `run`. The agent inst
187
189
  package, edits the config, runs your checks and reports; it does not commit.
188
190
 
189
191
  The instructions are also a Claude Code skill. Copy
190
- [`skills/genaicode-embed`](skills/genaicode-embed/SKILL.md) into `.claude/skills/` (or
192
+ [`docs/skills/genaicode-embed`](docs/skills/genaicode-embed/SKILL.md) into `.claude/skills/` (or
191
193
  `~/.claude/skills/`) and ask Claude to "embed genaicode":
192
194
 
193
195
  ```bash
194
- mkdir -p .claude/skills && cp -r node_modules/genaicode/skills/genaicode-embed .claude/skills/
196
+ mkdir -p .claude/skills && cp -r node_modules/genaicode/docs/skills/genaicode-embed .claude/skills/
195
197
  ```
196
198
 
197
199
  ### Inside a Vite app
@@ -221,6 +223,20 @@ Builds are untouched. The chat runs on its own port on 127.0.0.1 even when Vite
221
223
  `--host`, lets only the app's origins frame it, and hands its token (and takes "fix" requests)
222
224
  only from the app's own pages on this machine.
223
225
 
226
+ Any other Node dev server (Express, webpack-dev-server, a script that serves static files)
227
+ gets the same overlay from `createDevOverlay` in `genaicode/ui`:
228
+
229
+ ```ts
230
+ import { createDevOverlay } from 'genaicode/ui';
231
+
232
+ const overlay = createDevOverlay(); // same options as the plugin, plus `cwd`
233
+ app.use(overlay.middleware); // Express; or `if (await overlay.handle(req, res)) return;`
234
+ // ...and in the HTML it serves: overlay.injectHtml(html), or the overlay.script tag.
235
+ ```
236
+
237
+ Development only. The token goes only to pages opened at `localhost`, `*.localhost`,
238
+ `127.0.0.1` or `[::1]`, and without an agent CLI the overlay stays off.
239
+
224
240
  ### In your own React app
225
241
 
226
242
  `genaicode/react` is the same chat as a component. It draws a `SessionState` your app gives
@@ -12,5 +12,5 @@ export declare function embedPrompt(instructions: string, { cwd, version, reques
12
12
  }): string;
13
13
  /** The skill file without its YAML header. */
14
14
  export declare function stripFrontmatter(text: string): string;
15
- /** The instructions as shipped: `skills/genaicode-embed/SKILL.md` in the package. */
15
+ /** The instructions as shipped: `docs/skills/genaicode-embed/SKILL.md` in the package. */
16
16
  export declare function readEmbedInstructions(): string;
package/dist/cli/embed.js CHANGED
@@ -25,8 +25,8 @@ export function stripFrontmatter(text) {
25
25
  const match = /^---\r?\n[\s\S]*?\r?\n---\r?\n/.exec(text);
26
26
  return match ? text.slice(match[0].length) : text;
27
27
  }
28
- /** The instructions as shipped: `skills/genaicode-embed/SKILL.md` in the package. */
28
+ /** The instructions as shipped: `docs/skills/genaicode-embed/SKILL.md` in the package. */
29
29
  export function readEmbedInstructions() {
30
- return readFileSync(new URL('../../skills/genaicode-embed/SKILL.md', import.meta.url), 'utf8');
30
+ return readFileSync(new URL('../../docs/skills/genaicode-embed/SKILL.md', import.meta.url), 'utf8');
31
31
  }
32
32
  //# sourceMappingURL=embed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"embed.js","sourceRoot":"","sources":["../../src/cli/embed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;GAGG;AAEH,wFAAwF;AACxF,MAAM,UAAU,YAAY,CAAC,OAA2B;IACtD,OAAO,OAAO,CAAC,CAAC,CAAC,oCAAoC,OAAO,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC;AACtG,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,WAAW,CACzB,YAAoB,EACpB,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAsD;IAE7E,OAAO;QACL,gBAAgB,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE;QACrC,cAAc;QACd;YACE,qCAAqC,GAAG,GAAG;YAC3C,oCAAoC,OAAO,kBAAkB,OAAO,KAAK;YACzE,OAAO,CAAC,CAAC,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC,CAAC,oEAAoE;YAC7G,qGAAqG;SACtG,CAAC,IAAI,CAAC,IAAI,CAAC;KACb,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,gCAAgC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,qBAAqB;IACnC,OAAO,YAAY,CAAC,IAAI,GAAG,CAAC,uCAAuC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACjG,CAAC"}
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../../src/cli/embed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;GAGG;AAEH,wFAAwF;AACxF,MAAM,UAAU,YAAY,CAAC,OAA2B;IACtD,OAAO,OAAO,CAAC,CAAC,CAAC,oCAAoC,OAAO,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC;AACtG,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,WAAW,CACzB,YAAoB,EACpB,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAsD;IAE7E,OAAO;QACL,gBAAgB,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE;QACrC,cAAc;QACd;YACE,qCAAqC,GAAG,GAAG;YAC3C,oCAAoC,OAAO,kBAAkB,OAAO,KAAK;YACzE,OAAO,CAAC,CAAC,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC,CAAC,oEAAoE;YAC7G,qGAAqG;SACtG,CAAC,IAAI,CAAC,IAAI,CAAC;KACb,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,gCAAgC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,qBAAqB;IACnC,OAAO,YAAY,CAAC,IAAI,GAAG,CAAC,4CAA4C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACtG,CAAC"}
@@ -60,6 +60,6 @@ export declare const EXIT_OK = 0;
60
60
  export declare const EXIT_FAILED = 1;
61
61
  export declare const EXIT_USAGE = 2;
62
62
  export declare const EXIT_ABORTED = 130;
63
- export declare const helpText = "genaicode: run the coding-agent CLIs installed on this machine behind one interface.\n\nUsage:\n genaicode Chat with an agent in this terminal (same as \"chat\")\n genaicode chat [options] Chat with an agent in this terminal\n genaicode ui [options] Chat with an agent in the browser (local server)\n genaicode agents [--json] List supported agents and whether each is installed\n genaicode run [options] <prompt...> Run one task (reads the prompt from stdin if omitted)\n genaicode embed [options] [request] Have an agent add genaicode to the project here\n\nChat and UI options:\n -a, --agent <name> Agent to start with (default: the first installed one)\n -C, --cwd <dir> Directory the agent works in (default: current directory)\n -m, --model <id> Model id passed to the agent CLI\n --effort <level> Reasoning effort, in the agent's own vocabulary\n -r, --resume <id> Continue this agent session\n -y, --yes Approve every permission request the agent asks for\n --web (chat) Also open the session in the browser\n --port <n> Port for the browser UI, on 127.0.0.1 (default: a free port)\n --no-open (ui) Print the link instead of opening a browser\n\n Each prompt after the first continues the agent's session (claude, codex, cursor,\n opencode, copilot). Prompts sent while the agent works wait in a queue. Type /help in\n the chat for commands. The terminal and the browser can show one session: /web in the\n chat opens it in the browser, and Enter in \"genaicode ui\" brings it into the terminal.\n\nRun options:\n -a, --agent <name> Agent to use (default: the first installed one, see \"agents\")\n -C, --cwd <dir> Directory the agent works in (default: current directory)\n -m, --model <id> Model id passed to the agent CLI\n --effort <level> Reasoning effort, in the agent's own vocabulary\n --max-turns <n> Turn limit, where the agent supports one\n -r, --resume <id> Continue the agent session with this id (printed after each run)\n --timeout <sec> Stop the agent after this many seconds\n --verify <command> Shell command that checks the work; on failure its output goes\n back to the agent for another attempt\n --max-repairs <n> Repair attempts after a failed check (default 2)\n --json Print agent events as JSON lines instead of text\n\nEmbed options:\n --print Print the agent's instructions instead of starting one\n --ui Follow the agent in the browser instead of this terminal\n -a, -C, -m, --effort, -y, --port, --no-open: as for chat and ui\n\n The agent reads the project and chooses how to wire genaicode in; [request] steers it,\n e.g. \"only the dev panel\". Without a terminal it runs headless like \"run\". The\n instructions also ship as a Claude Code skill: skills/genaicode-embed/SKILL.md.\n\nThe agent uses its own login, billing, and permission defaults. GenAIcode adds no agent\nloop or sandbox of its own, and no prompts but embed's instructions.\nLibrary API: https://github.com/gtanczyk/genaicode#readme\n\nLooking for the legacy 1.x coding agent?\n Run it: npx genaicode@1\n Source: https://github.com/gtanczyk/genaicode/tree/1.x\n";
63
+ export declare const helpText = "genaicode: run the coding-agent CLIs installed on this machine behind one interface.\n\nUsage:\n genaicode Chat with an agent in this terminal (same as \"chat\")\n genaicode chat [options] Chat with an agent in this terminal\n genaicode ui [options] Chat with an agent in the browser (local server)\n genaicode agents [--json] List supported agents and whether each is installed\n genaicode run [options] <prompt...> Run one task (reads the prompt from stdin if omitted)\n genaicode embed [options] [request] Have an agent add genaicode to the project here\n\nChat and UI options:\n -a, --agent <name> Agent to start with (default: the first installed one)\n -C, --cwd <dir> Directory the agent works in (default: current directory)\n -m, --model <id> Model id passed to the agent CLI\n --effort <level> Reasoning effort, in the agent's own vocabulary\n -r, --resume <id> Continue this agent session\n -y, --yes Approve every permission request the agent asks for\n --web (chat) Also open the session in the browser\n --port <n> Port for the browser UI, on 127.0.0.1 (default: a free port)\n --no-open (ui) Print the link instead of opening a browser\n\n Each prompt after the first continues the agent's session (claude, codex, cursor,\n opencode, copilot). Prompts sent while the agent works wait in a queue. Type /help in\n the chat for commands. The terminal and the browser can show one session: /web in the\n chat opens it in the browser, and Enter in \"genaicode ui\" brings it into the terminal.\n\nRun options:\n -a, --agent <name> Agent to use (default: the first installed one, see \"agents\")\n -C, --cwd <dir> Directory the agent works in (default: current directory)\n -m, --model <id> Model id passed to the agent CLI\n --effort <level> Reasoning effort, in the agent's own vocabulary\n --max-turns <n> Turn limit, where the agent supports one\n -r, --resume <id> Continue the agent session with this id (printed after each run)\n --timeout <sec> Stop the agent after this many seconds\n --verify <command> Shell command that checks the work; on failure its output goes\n back to the agent for another attempt\n --max-repairs <n> Repair attempts after a failed check (default 2)\n --json Print agent events as JSON lines instead of text\n\nEmbed options:\n --print Print the agent's instructions instead of starting one\n --ui Follow the agent in the browser instead of this terminal\n -a, -C, -m, --effort, -y, --port, --no-open: as for chat and ui\n\n The agent reads the project and chooses how to wire genaicode in; [request] steers it,\n e.g. \"only the dev panel\". Without a terminal it runs headless like \"run\". The\n instructions also ship as a Claude Code skill: docs/skills/genaicode-embed/SKILL.md.\n\nThe agent uses its own login, billing, and permission defaults. GenAIcode adds no agent\nloop or sandbox of its own, and no prompts but embed's instructions.\nLibrary API: https://github.com/gtanczyk/genaicode#readme\n\nLooking for the legacy 1.x coding agent?\n Run it: npx genaicode@1\n Source: https://github.com/gtanczyk/genaicode/tree/1.x\n";
64
64
  /** Run the CLI and return its exit code. */
65
65
  export declare function main(cli: CliEnvironment): Promise<number>;
package/dist/cli/main.js CHANGED
@@ -57,7 +57,7 @@ Embed options:
57
57
 
58
58
  The agent reads the project and chooses how to wire genaicode in; [request] steers it,
59
59
  e.g. "only the dev panel". Without a terminal it runs headless like "run". The
60
- instructions also ship as a Claude Code skill: skills/genaicode-embed/SKILL.md.
60
+ instructions also ship as a Claude Code skill: docs/skills/genaicode-embed/SKILL.md.
61
61
 
62
62
  The agent uses its own login, billing, and permission defaults. GenAIcode adds no agent
63
63
  loop or sandbox of its own, and no prompts but embed's instructions.
@@ -0,0 +1,25 @@
1
+ /** What the dev server tells the overlay. */
2
+ export interface OverlayConfig {
3
+ /** Path of the overlay'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
+ * Runs as a classic inline script ahead of the page's own scripts, which run before any
14
+ * module (the overlay is one), and keeps their errors for the overlay to pick up. Served as
15
+ * source like `mountOverlay`, so it must not use anything from outside its own body.
16
+ */
17
+ export declare function collectEarlyErrors(): void;
18
+ /**
19
+ * The dev-server overlay: a wolf in the corner of the app that opens the genaicode UI in a
20
+ * panel, and collects the page's errors so one click sends them to the agent.
21
+ *
22
+ * The dev server serves this function's source (`mountOverlay.toString()`) as a module (see
23
+ * `overlayModule` in ./server.ts), so it must not use anything from outside its own body.
24
+ */
25
+ export declare function mountOverlay(config: OverlayConfig, hot: OverlayHot | undefined): void;
@@ -1,9 +1,65 @@
1
+ /**
2
+ * Runs as a classic inline script ahead of the page's own scripts, which run before any
3
+ * module (the overlay is one), and keeps their errors for the overlay to pick up. Served as
4
+ * source like `mountOverlay`, so it must not use anything from outside its own body.
5
+ */
6
+ export function collectEarlyErrors() {
7
+ const target = window;
8
+ if (target.__genaicodeEarly)
9
+ return;
10
+ const consoleError = console.error;
11
+ const early = {
12
+ errors: [],
13
+ restore: () => {
14
+ if (console.error === report)
15
+ console.error = consoleError;
16
+ },
17
+ };
18
+ target.__genaicodeEarly = early;
19
+ const keep = (error) => {
20
+ if (!early.done && early.errors.length < 20)
21
+ early.errors.push(error);
22
+ };
23
+ const text = (value) => {
24
+ if (value instanceof Error)
25
+ return value.message;
26
+ if (typeof value === 'string')
27
+ return value;
28
+ try {
29
+ return JSON.stringify(value) ?? String(value);
30
+ }
31
+ catch {
32
+ return Object.prototype.toString.call(value);
33
+ }
34
+ };
35
+ window.addEventListener('error', (event) => {
36
+ const where = event.filename ? ` (${event.filename}:${event.lineno}:${event.colno})` : '';
37
+ keep({ source: 'error', message: `${event.message}${where}`, stack: event.error?.stack });
38
+ });
39
+ window.addEventListener('unhandledrejection', (event) => {
40
+ keep({ source: 'rejection', message: text(event.reason), stack: event.reason?.stack });
41
+ });
42
+ const report = (...args) => {
43
+ consoleError.apply(console, args);
44
+ try {
45
+ keep({
46
+ source: 'console',
47
+ message: args.map(text).join(' '),
48
+ stack: args.find((arg) => arg instanceof Error)?.stack,
49
+ });
50
+ }
51
+ catch {
52
+ // Ignore values that cannot be described.
53
+ }
54
+ };
55
+ console.error = report;
56
+ }
1
57
  /**
2
58
  * The dev-server overlay: a wolf in the corner of the app that opens the genaicode UI in a
3
59
  * panel, and collects the page's errors so one click sends them to the agent.
4
60
  *
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.
61
+ * The dev server serves this function's source (`mountOverlay.toString()`) as a module (see
62
+ * `overlayModule` in ./server.ts), so it must not use anything from outside its own body.
7
63
  */
8
64
  export function mountOverlay(config, hot) {
9
65
  if (document.querySelector('genaicode-overlay'))
@@ -39,7 +95,9 @@ iframe { flex: 1; width: 100%; border: 0; background: #f7f7f5; }
39
95
  .resizing iframe { pointer-events: none; }
40
96
  .note { padding: 16px; color: #6b6b66; }
41
97
  @media (prefers-color-scheme: dark) {
42
- .wolf, .panel { background-color: #1d1d1c; border-color: #2e2e2c; }
98
+ /* The wolf stays light: a dark circle disappears on a dark page. */
99
+ .wolf { border-color: #fff; box-shadow: 0 0 0 3px rgba(255,255,255,.22), 0 4px 18px rgba(0,0,0,.65); }
100
+ .panel { background-color: #1d1d1c; border-color: #2e2e2c; }
43
101
  .head { background: #141414; border-color: #2e2e2c; color: #ececea; }
44
102
  .head button { background: #1d1d1c; border-color: #2e2e2c; color: #ececea; }
45
103
  iframe { background: #141414; }
@@ -262,7 +320,17 @@ iframe { flex: 1; width: 100%; border: 0; background: #f7f7f5; }
262
320
  errors = [...errors, error].slice(-MAX_ERRORS);
263
321
  render();
264
322
  };
323
+ // What `collectEarlyErrors` caught before this module ran: the page's classic scripts.
324
+ const early = window.__genaicodeEarly;
325
+ if (early) {
326
+ early.done = true;
327
+ early.restore();
328
+ }
265
329
  if (config.captureErrors) {
330
+ for (const error of early?.errors ?? []) {
331
+ if (error && typeof error.message === 'string' && typeof error.source === 'string')
332
+ add(error);
333
+ }
266
334
  window.addEventListener('error', (event) => {
267
335
  const where = event.filename ? ` (${event.filename}:${event.lineno}:${event.colno})` : '';
268
336
  add({ source: 'error', message: `${event.message}${where}`, stack: event.error?.stack });
@@ -311,4 +379,4 @@ iframe { flex: 1; width: 100%; border: 0; background: #f7f7f5; }
311
379
  wolf.append(badge);
312
380
  });
313
381
  }
314
- //# sourceMappingURL=overlay.js.map
382
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/overlay/client.ts"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,MAA4C,CAAC;IAC5D,IAAI,MAAM,CAAC,gBAAgB;QAAE,OAAO;IACpC,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;IACnC,MAAM,KAAK,GAAgB;QACzB,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,GAAG,EAAE;YACZ,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM;gBAAE,OAAO,CAAC,KAAK,GAAG,YAAY,CAAC;QAC7D,CAAC;KACF,CAAC;IACF,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAChC,MAAM,IAAI,GAAG,CAAC,KAAoC,EAAE,EAAE;QACpD,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE;YAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE;QACtC,IAAI,KAAK,YAAY,KAAK;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC;QACjD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC;IACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACzC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,KAAK,EAAE,EAAE,KAAK,EAAG,KAAK,CAAC,KAA2B,EAAE,KAAK,EAAE,CAAC,CAAC;IACnH,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;QACtD,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAG,KAAK,CAAC,MAA4B,EAAE,KAAK,EAAE,CAAC,CAAC;IAChH,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;QACpC,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,IAAI,CAAC;gBACH,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACjC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAgB,EAAE,CAAC,GAAG,YAAY,KAAK,CAAC,EAAE,KAAK;aACrE,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;IACH,CAAC,CAAC;IACF,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC;AACzB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,MAAqB,EAAE,GAA2B;IAC7E,IAAI,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC;QAAE,OAAO;IAOxD,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,MAAM,QAAQ,GAAG,IAAI,CAAC;IACtB,IAAI,MAAM,GAAgB,EAAE,CAAC;IAC7B,IAAI,OAAmD,CAAC;IAExD,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACzD,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,qDAAqD,CAAC;IAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCZ,CAAC;IACN,MAAM,CAAC,GAAG,CAAoB,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAM,CAAC;IACrF,MAAM,IAAI,GAAG,CAAC,CAAoB,OAAO,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,CAAc,QAAQ,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,CAAc,QAAQ,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,CAAC,CAAoB,MAAM,CAAC,CAAC;IACzC,IAAI,KAAgC,CAAC;IAErC,0FAA0F;IAC1F,MAAM,QAAQ,GAAG,wBAAwB,CAAC;IAC1C,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAC7C,MAAM,IAAI,GAAG,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAgC,CAAC;QAClG,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAU,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACpH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;IACD,4FAA4F;IAC5F,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC;QACrB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,EAAE,CAAC;QACnC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,GAAG,CAAC;KACvC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,CAAC,IAAwB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACtF,MAAM,KAAK,GAAG;QACZ,KAAK,EAAE,CAAC,CAAc,aAAa,CAAC;QACpC,MAAM,EAAE,CAAC,CAAc,cAAc,CAAC;KACvC,CAAC;IACF,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAU,EAAE,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC/D,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7D,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,IAAwB,EAAE,KAAa,EAAE,IAAa,EAAE,EAAE;QACxE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QACjF,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,IAAI,EAAE,CAAC;QACP,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC;YACH,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC,CAAC;IACF,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,KAAK;QAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;IAC7F,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM;QAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;IACjG,IAAI,EAAE,CAAC;IACP,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAU,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,CAAC,KAA2C,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAClH,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;YAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC/B,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC1C,qDAAqD;YACrD,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAChC,MAAM,IAAI,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;YACvF,MAAM,GAAG,GAAG,GAAG,EAAE;gBACf,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;gBAC9C,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;gBAC3C,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;gBAC/C,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBACnC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YACjC,CAAC,CAAC;YACF,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,gBAAgB,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,EAAE,CAAC;YACP,IAAI,CAAC;gBACH,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YACvD,CAAC;YAAC,MAAM,CAAC;gBACP,kCAAkC;YACpC,CAAC;QACH,CAAC,CAAC;QACF,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACzC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;gBAC1B,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,KAAK,EAAE,CAAC;gBACR,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GACR,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1F,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;QACnC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1C,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;QACjC,GAAG,CAAC,WAAW,GAAG,OAAO,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QAChF,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM;YACzB,CAAC,CAAC,cAAc,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,eAAe;YACnF,CAAC,CAAC,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,GAAG,UAAU,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC;QACtF,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,cAAc,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmC,CAAC;QACpE,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,OAAO,IAAI,GAAG,CAAC,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC;QACxF,MAAM,EAAE,CAAC;QACT,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,OAAgB,EAAE,EAAE;QAChC,KAAK,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC;QACxB,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC;IACF,qFAAqF;IACrF,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,CAAC,IAAI,CAAC,CAAC;QACX,KAAK,KAAK,WAAW,EAAE,CAAC,IAAI,CAC1B,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;YACV,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAChD,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;YACjB,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;YACxB,IAAI,CAAC,WAAW,GAAG,sCAAuC,KAAe,CAAC,OAAO,kCAAkC,CAAC;YACpH,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC,CACF,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjF,+EAA+E;IAC/E,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,CAAC,KAAK,CAAC,CAAC;QACZ,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC,CAAC;IACF,CAAC,CAAoB,QAAQ,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAChE,6FAA6F;IAC7F,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;QACzC,IAAK,KAAuB,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO;QACtE,+EAA+E;QAC/E,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,KAAK,EAAE,CAAC;IACV,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC;QACpB,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,EAAE,CAAC;QACT,MAAM,IAAI,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,WAAW,EAAE,aAAa;YAC1B,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SAClF,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1B,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;YAClB,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;YACjD,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE;QACtC,IAAI,KAAK,YAAY,KAAK;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC;QACjD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,GAAG,GAAG,CAAC,KAAgB,EAAE,EAAE;QAC/B,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,KAAK;YAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC;YAAE,OAAO;QAClG,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,EAAE,CAAC;IACX,CAAC,CAAC;IAEF,uFAAuF;IACvF,MAAM,KAAK,GAAI,MAA6C,CAAC,gBAAgB,CAAC;IAC9E,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,KAAK,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC;IACD,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACzB,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;YACxC,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;gBAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QACjG,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACzC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1F,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,KAAK,EAAE,EAAE,KAAK,EAAG,KAAK,CAAC,KAA2B,EAAE,KAAK,EAAE,CAAC,CAAC;QAClH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;YACtD,GAAG,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAG,KAAK,CAAC,MAA4B,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/G,CAAC,CAAC,CAAC;QACH,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,CAAC,KAAK,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;YACrC,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,+DAA+D;YAC/D,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACzC,6FAA6F;gBAC7F,IAAI,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,gCAAgC,CAAC;oBAAE,OAAO;gBACxE,GAAG,CAAC;oBACF,MAAM,EAAE,SAAS;oBACjB,OAAO;oBACP,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAgB,EAAE,CAAC,GAAG,YAAY,KAAK,CAAC,EAAE,KAAK;iBACrE,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,0CAA0C;YAC5C,CAAC;QACH,CAAC,CAAC;QACF,GAAG,EAAE,EAAE,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE;YAChC,MAAM,GAAG,GAAI,OAAuF,CAAC,GAAG,CAAC;YACzG,IAAI,CAAC,GAAG;gBAAE,OAAO;YACjB,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,IAAI,YAAY,GAAG,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAChH,CAAC,CAAC,CAAC;QACH,4FAA4F;QAC5F,GAAG,EAAE,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;YAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC7B,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;YAC3D,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;gBAAE,MAAM,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,EAAE,CAAC;IACT,KAAK,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;QAC5B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,89 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { type OverlayConfig } from './client.js';
3
+ /**
4
+ * The server side of the dev overlay (the wolf in the page's corner), shared by the Vite
5
+ * plugin (`genaicode/vite`) and `createDevOverlay` (`genaicode/ui`) for any other dev server.
6
+ */
7
+ /** Where the overlay's endpoints live on the dev server. */
8
+ export declare const API = "/__genaicode";
9
+ /** The genaicode UI the overlay shows: what `startEmbeddedWeb` returns. */
10
+ export interface OverlayUi {
11
+ url: string;
12
+ controller: {
13
+ submit(text: string): unknown;
14
+ get(): {
15
+ session: {
16
+ agent: string;
17
+ };
18
+ };
19
+ };
20
+ close(): Promise<void>;
21
+ }
22
+ export interface OverlayLog {
23
+ info(message: string): void;
24
+ warn(message: string): void;
25
+ error(message: string): void;
26
+ }
27
+ /**
28
+ * Start the UI for the overlay. Never rejects: without an agent CLI, or when the UI fails to
29
+ * start, it says so in the log and resolves to undefined, and the app runs on without it.
30
+ */
31
+ export declare function startOverlayUi<Ui extends OverlayUi>(start: () => Promise<Ui>, log: OverlayLog): Promise<Ui | undefined>;
32
+ /** The overlay for a dev server: its routes, and the tag that puts it in a page. */
33
+ export interface Overlay<Ui extends OverlayUi = OverlayUi> {
34
+ /** The chat once it runs; undefined when no agent CLI is installed or it failed (see `log`). */
35
+ readonly ready: Promise<Ui | undefined>;
36
+ /**
37
+ * Answers the overlay's routes under `/__genaicode/`; resolves to false for anything else,
38
+ * so the server goes on to its own routes. Mount it before them.
39
+ */
40
+ handle(req: IncomingMessage, res: ServerResponse): Promise<boolean>;
41
+ /** `handle` as Express / Connect middleware. */
42
+ middleware(req: IncomingMessage, res: ServerResponse, next: (error?: unknown) => void): void;
43
+ /**
44
+ * The overlay's tags for the app's HTML: an inline error collector for the page's own
45
+ * scripts, then `<script type="module" src="/__genaicode/overlay.js">`.
46
+ */
47
+ readonly script: string;
48
+ /** Adds `script` to an HTML page, as early as possible; unchanged when the overlay is off. */
49
+ injectHtml(html: string): string;
50
+ close(): Promise<void>;
51
+ }
52
+ /**
53
+ * The overlay for any Node dev server (`createDevOverlay` in src/ui.ts). `start` gets the
54
+ * origins that may frame the chat: the app's pages that asked for the session.
55
+ */
56
+ export declare function createOverlay<Ui extends OverlayUi>(start: (frameAncestors: () => readonly string[]) => Promise<Ui>, { captureErrors, log }: {
57
+ captureErrors: boolean;
58
+ log: OverlayLog;
59
+ }): Overlay<Ui>;
60
+ export interface OverlayRequestContext {
61
+ /** The UI, or undefined when it is off. */
62
+ ui: Promise<OverlayUi | undefined> | undefined;
63
+ /** Called with the origin of each app page that asks for the session, for frame-ancestors. */
64
+ onPage(origin: string): void;
65
+ /** Serve the overlay module at `/__genaicode/overlay.js` with these settings. */
66
+ overlay: OverlayConfig;
67
+ /** Whether the app is served over https. Default: whether this request came over TLS. */
68
+ https?: boolean;
69
+ /**
70
+ * Hand the UI's token only to pages opened at a loopback name (localhost, *.localhost,
71
+ * 127.0.0.1, [::1]), which stops DNS-rebinding pages. Vite checks the Host itself.
72
+ */
73
+ loopbackHosts: boolean;
74
+ }
75
+ /**
76
+ * The overlay's endpoints: the overlay module, the UI link, and "fix these errors". Resolves
77
+ * to false for any other URL, so the dev server goes on to its own routes.
78
+ */
79
+ export declare function handleOverlayRequest(req: IncomingMessage, res: ServerResponse, context: OverlayRequestContext): Promise<boolean>;
80
+ /** The overlay as an ES module. `hot` is the expression for Vite's HMR client, if any. */
81
+ export declare function overlayModule(config: OverlayConfig, hot?: string): string;
82
+ /** The prompt for "Fix N errors", or undefined when the body is not a list of errors. */
83
+ export declare function fixPrompt(body: unknown): string | undefined;
84
+ /** 127.0.0.0/8 and ::1, also as IPv4-mapped IPv6 addresses. */
85
+ export declare function isLoopback(address: string | undefined): boolean;
86
+ /** A Host header naming this machine: localhost, *.localhost, 127.x.x.x or [::1], any port. */
87
+ export declare function isLoopbackHost(host: string | undefined): boolean;
88
+ /** The origin a same-origin request came from, by its Host header. */
89
+ export declare function pageOrigin(host: string | undefined, https: boolean): string | undefined;
@@ -0,0 +1,197 @@
1
+ import { collectEarlyErrors, mountOverlay } from './client.js';
2
+ /**
3
+ * The server side of the dev overlay (the wolf in the page's corner), shared by the Vite
4
+ * plugin (`genaicode/vite`) and `createDevOverlay` (`genaicode/ui`) for any other dev server.
5
+ */
6
+ /** Where the overlay's endpoints live on the dev server. */
7
+ export const API = '/__genaicode';
8
+ const MAX_BODY = 256 * 1024;
9
+ /**
10
+ * Start the UI for the overlay. Never rejects: without an agent CLI, or when the UI fails to
11
+ * start, it says so in the log and resolves to undefined, and the app runs on without it.
12
+ */
13
+ export async function startOverlayUi(start, log) {
14
+ try {
15
+ const ui = await start();
16
+ log.info(` ➜ genaicode: ${ui.controller.get().session.agent} in the page, or open ${ui.url}`);
17
+ return ui;
18
+ }
19
+ catch (error) {
20
+ // By name: the error class lives in the lazily loaded UI bundle.
21
+ if (error?.name === 'NoAgentError') {
22
+ log.warn(`[genaicode] ${error.message} The overlay is off.`);
23
+ }
24
+ else {
25
+ log.error(`[genaicode] The UI did not start: ${error?.message ?? String(error)}`);
26
+ }
27
+ return undefined;
28
+ }
29
+ }
30
+ /**
31
+ * The overlay for any Node dev server (`createDevOverlay` in src/ui.ts). `start` gets the
32
+ * origins that may frame the chat: the app's pages that asked for the session.
33
+ */
34
+ export function createOverlay(start, { captureErrors, log }) {
35
+ const seen = new Set();
36
+ let ui = startOverlayUi(() => start(() => [...seen]), log);
37
+ let off = false;
38
+ void ui.then((started) => (off = !started));
39
+ // The page's classic scripts run before any module: an inline collector keeps their errors.
40
+ const script = (captureErrors ? `<script>(${collectEarlyErrors.toString()})()</script>` : '') +
41
+ `<script type="module" src="${API}/overlay.js"></script>`;
42
+ const handle = (req, res) => handleOverlayRequest(req, res, {
43
+ ui,
44
+ onPage: (origin) => seen.add(origin),
45
+ overlay: { api: API, captureErrors },
46
+ loopbackHosts: true,
47
+ });
48
+ return {
49
+ get ready() {
50
+ return ui ?? Promise.resolve(undefined);
51
+ },
52
+ handle,
53
+ middleware(req, res, next) {
54
+ handle(req, res).then((done) => done || next(), next);
55
+ },
56
+ script,
57
+ injectHtml(html) {
58
+ if (off || html.includes(script))
59
+ return html;
60
+ // In <head> (else <body>, else <html>), so it loads before the app's own modules.
61
+ const open = ['head', 'body', 'html']
62
+ .map((tag) => new RegExp(`<${tag}(\\s[^>]*)?>`, 'i').exec(html))
63
+ .find((match) => match);
64
+ // Without those optional tags, after the doctype: before it, the page would be in quirks mode.
65
+ const at = open ? open.index + open[0].length : (/^\s*<!doctype[^>]*>/i.exec(html)?.[0].length ?? 0);
66
+ return html.slice(0, at) + script + html.slice(at);
67
+ },
68
+ async close() {
69
+ const started = await ui;
70
+ ui = undefined;
71
+ off = true;
72
+ await started?.close();
73
+ },
74
+ };
75
+ }
76
+ /**
77
+ * The overlay's endpoints: the overlay module, the UI link, and "fix these errors". Resolves
78
+ * to false for any other URL, so the dev server goes on to its own routes.
79
+ */
80
+ export async function handleOverlayRequest(req, res, context) {
81
+ const path = (req.url ?? '/').split('?')[0];
82
+ if (path !== API && !path.startsWith(`${API}/`))
83
+ return false;
84
+ const send = (status, body) => {
85
+ res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store' });
86
+ res.end(JSON.stringify(body));
87
+ return true;
88
+ };
89
+ // The overlay itself holds nothing secret.
90
+ if (req.method === 'GET' && path === `${API}/overlay.js`) {
91
+ res.writeHead(200, { 'content-type': 'text/javascript', 'cache-control': 'no-store' });
92
+ res.end(overlayModule(context.overlay));
93
+ return true;
94
+ }
95
+ // Only this machine: a dev server listening beyond loopback also answers the network, and
96
+ // Sec-Fetch-Site is just a header a client there could send. Then only the app's own pages:
97
+ // another site open in the browser must not read the UI's token or start the agent.
98
+ if (!isLoopback(req.socket.remoteAddress))
99
+ return send(403, { error: 'this machine only' });
100
+ if (context.loopbackHosts && !isLoopbackHost(req.headers.host))
101
+ return send(403, { error: 'localhost only' });
102
+ if (req.headers['sec-fetch-site'] !== 'same-origin')
103
+ return send(403, { error: 'same-origin only' });
104
+ const ui = await context.ui;
105
+ if (!ui)
106
+ return send(503, { error: 'genaicode is off; see the dev server terminal' });
107
+ if (req.method === 'GET' && path === `${API}/session`) {
108
+ const origin = pageOrigin(req.headers.host, context.https ?? !!req.socket.encrypted);
109
+ if (origin)
110
+ context.onPage(origin);
111
+ return send(200, { url: ui.url, agent: ui.controller.get().session.agent });
112
+ }
113
+ if (req.method === 'POST' && path === `${API}/fix`) {
114
+ if (!String(req.headers['content-type'] ?? '').startsWith('application/json')) {
115
+ return send(415, { error: 'expected JSON' });
116
+ }
117
+ let prompt;
118
+ try {
119
+ prompt = fixPrompt(JSON.parse(await readBody(req)));
120
+ }
121
+ catch {
122
+ prompt = undefined;
123
+ }
124
+ if (!prompt)
125
+ return send(400, { error: 'bad request' });
126
+ ui.controller.submit(prompt);
127
+ return send(200, { ok: true });
128
+ }
129
+ return send(404, { error: 'not found' });
130
+ }
131
+ /** The overlay as an ES module. `hot` is the expression for Vite's HMR client, if any. */
132
+ export function overlayModule(config, hot = 'undefined') {
133
+ return `(${mountOverlay.toString()})(${JSON.stringify(config)}, ${hot});\n`;
134
+ }
135
+ const SOURCES = {
136
+ vite: 'build error',
137
+ error: 'uncaught error',
138
+ rejection: 'unhandled rejection',
139
+ console: 'console.error',
140
+ };
141
+ /** The prompt for "Fix N errors", or undefined when the body is not a list of errors. */
142
+ export function fixPrompt(body) {
143
+ if (!body || typeof body !== 'object')
144
+ return undefined;
145
+ const { page, errors } = body;
146
+ if (!Array.isArray(errors) || errors.length === 0)
147
+ return undefined;
148
+ const items = [];
149
+ for (const error of errors.slice(0, 20)) {
150
+ if (!error || typeof error !== 'object')
151
+ return undefined;
152
+ const { source, message, stack } = error;
153
+ if (typeof message !== 'string' || typeof source !== 'string' || !Object.hasOwn(SOURCES, source))
154
+ return undefined;
155
+ const trace = typeof stack === 'string' && stack && !message.includes(stack) ? `\n${stack.slice(0, 4000)}` : '';
156
+ items.push(`${items.length + 1}. [${SOURCES[source]}] ${message.slice(0, 4000)}${trace}`);
157
+ }
158
+ const where = typeof page === 'string' && /^https?:\/\//.test(page) ? ` at ${page.slice(0, 500)}` : '';
159
+ return (`The app running in the dev server${where} reports ${items.length === 1 ? 'this error' : 'these errors'} ` +
160
+ `in the browser. Find the cause in the code and fix it.\n\n` +
161
+ '```\n' +
162
+ items.join('\n\n').replace(/```/g, "'''") +
163
+ '\n```');
164
+ }
165
+ /** 127.0.0.0/8 and ::1, also as IPv4-mapped IPv6 addresses. */
166
+ export function isLoopback(address) {
167
+ if (!address)
168
+ return false;
169
+ const v4 = address.startsWith('::ffff:') ? address.slice(7) : address;
170
+ return address === '::1' || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(v4);
171
+ }
172
+ /** A Host header naming this machine: localhost, *.localhost, 127.x.x.x or [::1], any port. */
173
+ export function isLoopbackHost(host) {
174
+ const match = /^(\[::1\]|[\w.-]+)(:\d+)?$/.exec(host ?? '');
175
+ if (!match)
176
+ return false;
177
+ const name = match[1].toLowerCase();
178
+ return name === '[::1]' || name === 'localhost' || name.endsWith('.localhost') || isLoopback(name);
179
+ }
180
+ /** The origin a same-origin request came from, by its Host header. */
181
+ export function pageOrigin(host, https) {
182
+ if (!host || !/^[\w.-]+(:\d+)?$|^\[[\da-f:.]+\](:\d+)?$/i.test(host))
183
+ return undefined;
184
+ return `${https ? 'https' : 'http'}://${host.toLowerCase()}`;
185
+ }
186
+ async function readBody(req) {
187
+ let size = 0;
188
+ const chunks = [];
189
+ for await (const chunk of req) {
190
+ size += chunk.length;
191
+ if (size > MAX_BODY)
192
+ throw new Error('Request too large');
193
+ chunks.push(chunk);
194
+ }
195
+ return Buffer.concat(chunks).toString('utf8');
196
+ }
197
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/overlay/server.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,8 @@ export interface AgentChatProps {
20
20
  onSend(text: string): void;
21
21
  /** The user pressed Stop or Esc while the agent works. Without it there is no Stop button. */
22
22
  onStop?(): void;
23
+ /** Offer Stop (button and Esc) while the agent is idle too: the host runs something of its own. */
24
+ canStop?: boolean;
23
25
  /**
24
26
  * Answer an approval the agent asked for (`state.approvals`). Without it pending approvals
25
27
  * show as waiting, with no buttons.
@@ -36,7 +36,7 @@ export function AgentChat(props) {
36
36
  event.preventDefault();
37
37
  send();
38
38
  }
39
- if (event.key === 'Escape' && running && props.onStop)
39
+ if (event.key === 'Escape' && (running || props.canStop) && props.onStop)
40
40
  props.onStop();
41
41
  };
42
42
  // Notices sit after the turn that was last when they were posted.
@@ -72,7 +72,7 @@ export function AgentChat(props) {
72
72
  : null, items, footer !== undefined && footer !== null && footer !== false ? (_jsx("div", { className: "gc-footer-slot", children: footer })) : null] }) }), _jsxs("div", { className: "gc-composer", children: [state.queued.length ? (_jsx("div", { className: "gc-queued", children: state.queued.map((prompt, i) => {
73
73
  const shown = props.renderPrompt ? props.renderPrompt(prompt) : prompt;
74
74
  return shown === null || shown === undefined || shown === false ? null : _jsxs("span", { children: ["\u23F8 ", shown] }, i);
75
- }) })) : null, _jsxs("div", { className: "gc-box", children: [_jsx("textarea", { ref: input, rows: 1, autoFocus: props.autoFocus, value: draft, placeholder: placeholder, "aria-label": "Message", onChange: (event) => setDraft(event.target.value), onKeyDown: onKeyDown }), running && props.onStop ? (_jsx("button", { type: "button", className: "gc-btn gc-danger", onClick: () => props.onStop?.(), children: "Stop" })) : null, _jsx("button", { type: "button", className: "gc-btn gc-primary", disabled: !draft.trim() || props.disabled, onClick: send, children: running ? (state.canSteer ? 'Steer' : 'Queue') : 'Send' })] }), props.hint === null ? null : (_jsx("div", { className: "gc-hint", children: props.hint ?? `Enter to send · Shift+Enter for a new line${props.onStop ? ' · Esc stops' : ''}` }))] })] }));
75
+ }) })) : null, _jsxs("div", { className: "gc-box", children: [_jsx("textarea", { ref: input, rows: 1, autoFocus: props.autoFocus, value: draft, placeholder: placeholder, "aria-label": "Message", onChange: (event) => setDraft(event.target.value), onKeyDown: onKeyDown }), (running || props.canStop) && props.onStop ? (_jsx("button", { type: "button", className: "gc-btn gc-danger", onClick: () => props.onStop?.(), children: "Stop" })) : null, _jsx("button", { type: "button", className: "gc-btn gc-primary", disabled: !draft.trim() || props.disabled, onClick: send, children: running ? (state.canSteer ? 'Steer' : 'Queue') : 'Send' })] }), props.hint === null ? null : (_jsx("div", { className: "gc-hint", children: props.hint ?? `Enter to send · Shift+Enter for a new line${props.onStop ? ' · Esc stops' : ''}` }))] })] }));
76
76
  }
77
77
  const NO_SESSION = {
78
78
  agent: '',