@ggui-ai/cli 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +96 -0
  3. package/dist/agent-resolution.d.ts +41 -0
  4. package/dist/agent-resolution.d.ts.map +1 -0
  5. package/dist/agent-resolution.js +80 -0
  6. package/dist/api-client.d.ts +59 -0
  7. package/dist/api-client.d.ts.map +1 -0
  8. package/dist/api-client.js +145 -0
  9. package/dist/auth-keys.d.ts +10 -0
  10. package/dist/auth-keys.d.ts.map +1 -0
  11. package/dist/auth-keys.js +382 -0
  12. package/dist/auth-login.d.ts +11 -0
  13. package/dist/auth-login.d.ts.map +1 -0
  14. package/dist/auth-login.js +231 -0
  15. package/dist/auth-logout.d.ts +3 -0
  16. package/dist/auth-logout.d.ts.map +1 -0
  17. package/dist/auth-logout.js +32 -0
  18. package/dist/auth-store.d.ts +67 -0
  19. package/dist/auth-store.d.ts.map +1 -0
  20. package/dist/auth-store.js +150 -0
  21. package/dist/auth-whoami.d.ts +3 -0
  22. package/dist/auth-whoami.d.ts.map +1 -0
  23. package/dist/auth-whoami.js +52 -0
  24. package/dist/blueprint-command.d.ts +3 -0
  25. package/dist/blueprint-command.d.ts.map +1 -0
  26. package/dist/blueprint-command.js +203 -0
  27. package/dist/blueprint-create.d.ts +71 -0
  28. package/dist/blueprint-create.d.ts.map +1 -0
  29. package/dist/blueprint-create.js +377 -0
  30. package/dist/byok-resolver.d.ts +141 -0
  31. package/dist/byok-resolver.d.ts.map +1 -0
  32. package/dist/byok-resolver.js +89 -0
  33. package/dist/cli.d.ts +3 -0
  34. package/dist/cli.d.ts.map +1 -0
  35. package/dist/cli.js +1066 -0
  36. package/dist/dev-command.d.ts +169 -0
  37. package/dist/dev-command.d.ts.map +1 -0
  38. package/dist/dev-command.js +222 -0
  39. package/dist/gadget-command.d.ts +3 -0
  40. package/dist/gadget-command.d.ts.map +1 -0
  41. package/dist/gadget-command.js +181 -0
  42. package/dist/gadget-create.d.ts +106 -0
  43. package/dist/gadget-create.d.ts.map +1 -0
  44. package/dist/gadget-create.js +492 -0
  45. package/dist/generation-probe.d.ts +135 -0
  46. package/dist/generation-probe.d.ts.map +1 -0
  47. package/dist/generation-probe.js +132 -0
  48. package/dist/internal/artifact-install.d.ts +150 -0
  49. package/dist/internal/artifact-install.d.ts.map +1 -0
  50. package/dist/internal/artifact-install.js +1019 -0
  51. package/dist/internal/artifact-publish.d.ts +204 -0
  52. package/dist/internal/artifact-publish.d.ts.map +1 -0
  53. package/dist/internal/artifact-publish.js +1141 -0
  54. package/dist/internal/artifact-search.d.ts +155 -0
  55. package/dist/internal/artifact-search.d.ts.map +1 -0
  56. package/dist/internal/artifact-search.js +539 -0
  57. package/dist/internal/artifact-uninstall.d.ts +30 -0
  58. package/dist/internal/artifact-uninstall.d.ts.map +1 -0
  59. package/dist/internal/artifact-uninstall.js +205 -0
  60. package/dist/internal/auth-cache.d.ts +40 -0
  61. package/dist/internal/auth-cache.d.ts.map +1 -0
  62. package/dist/internal/auth-cache.js +133 -0
  63. package/dist/internal/auth-strategy.d.ts +89 -0
  64. package/dist/internal/auth-strategy.d.ts.map +1 -0
  65. package/dist/internal/auth-strategy.js +132 -0
  66. package/dist/internal/ggui-json.d.ts +53 -0
  67. package/dist/internal/ggui-json.d.ts.map +1 -0
  68. package/dist/internal/ggui-json.js +92 -0
  69. package/dist/internal/key-store.d.ts +43 -0
  70. package/dist/internal/key-store.d.ts.map +1 -0
  71. package/dist/internal/key-store.js +128 -0
  72. package/dist/internal/oidc-token.d.ts +52 -0
  73. package/dist/internal/oidc-token.d.ts.map +1 -0
  74. package/dist/internal/oidc-token.js +351 -0
  75. package/dist/internal/register-author-key.d.ts +44 -0
  76. package/dist/internal/register-author-key.d.ts.map +1 -0
  77. package/dist/internal/register-author-key.js +212 -0
  78. package/dist/local-keys.d.ts +47 -0
  79. package/dist/local-keys.d.ts.map +1 -0
  80. package/dist/local-keys.js +115 -0
  81. package/dist/mcp-backend.d.ts +356 -0
  82. package/dist/mcp-backend.d.ts.map +1 -0
  83. package/dist/mcp-backend.js +668 -0
  84. package/dist/paths.d.ts +77 -0
  85. package/dist/paths.d.ts.map +1 -0
  86. package/dist/paths.js +119 -0
  87. package/dist/persistent-secrets.d.ts +28 -0
  88. package/dist/persistent-secrets.d.ts.map +1 -0
  89. package/dist/persistent-secrets.js +94 -0
  90. package/dist/persistent-short-code-index.d.ts +14 -0
  91. package/dist/persistent-short-code-index.d.ts.map +1 -0
  92. package/dist/persistent-short-code-index.js +39 -0
  93. package/dist/persistent-stores.d.ts +12 -0
  94. package/dist/persistent-stores.d.ts.map +1 -0
  95. package/dist/persistent-stores.js +42 -0
  96. package/dist/serve-command.d.ts +500 -0
  97. package/dist/serve-command.d.ts.map +1 -0
  98. package/dist/serve-command.js +616 -0
  99. package/dist/serve-fallback.d.ts +64 -0
  100. package/dist/serve-fallback.d.ts.map +1 -0
  101. package/dist/serve-fallback.js +122 -0
  102. package/dist/spawn-cloudflared.d.ts +61 -0
  103. package/dist/spawn-cloudflared.d.ts.map +1 -0
  104. package/dist/spawn-cloudflared.js +167 -0
  105. package/dist/theme-command.d.ts +4 -0
  106. package/dist/theme-command.d.ts.map +1 -0
  107. package/dist/theme-command.js +154 -0
  108. package/dist/theme-file-uploader.d.ts +8 -0
  109. package/dist/theme-file-uploader.d.ts.map +1 -0
  110. package/dist/theme-file-uploader.js +58 -0
  111. package/dist/theme-writer.d.ts +8 -0
  112. package/dist/theme-writer.d.ts.map +1 -0
  113. package/dist/theme-writer.js +103 -0
  114. package/dist/tunnel-provider.d.ts +273 -0
  115. package/dist/tunnel-provider.d.ts.map +1 -0
  116. package/dist/tunnel-provider.js +142 -0
  117. package/package.json +81 -0
@@ -0,0 +1,500 @@
1
+ /**
2
+ * `ggui serve` argument parsing, banner rendering, and lifecycle
3
+ * driver.
4
+ *
5
+ * Runs the open self-hosted personal-mode path from `@ggui-ai/mcp-server`
6
+ * + an optional supervised agent. Default (no flags, with a valid
7
+ * `ggui.json` + `agent.entry`) is MCP + agent side by side. Opt-down
8
+ * is `--mcp-only`. Missing-or-incomplete config falls back to
9
+ * MCP-only with a warning; broken config is a `cli.ts`-level error
10
+ * surfaced separately.
11
+ *
12
+ * Deliberately distinct from `ggui dev`:
13
+ *
14
+ * - `ggui dev` — local dev loop: registry + hub + runtime supervision
15
+ * + preview + (optional) tunnel. Developer-facing.
16
+ * - `ggui serve` — personal-mode self-hosted runtime: MCP server +
17
+ * optional supervised agent. Operator-facing.
18
+ *
19
+ * Keep these separate. The only shared code between them is pure
20
+ * agent-entry resolution (`./agent-resolution.ts`) — no dev-loop
21
+ * concerns leak into serve.
22
+ *
23
+ * This module stays pure / testable — no `node:http` binds, no
24
+ * `createGguiServer()` import, no logger dep. `cli.ts` composes this
25
+ * logic with the real server package, agent adapter, and logger.
26
+ */
27
+ import type { AgentRuntimeAdapter, AgentRuntimeEvent, AgentRuntimeStartInput } from '@ggui-ai/agent-runtime';
28
+ import type { PairingService } from '@ggui-ai/mcp-server';
29
+ /**
30
+ * Default bind port. Distinct from `ggui dev`'s 6780 so both can run
31
+ * simultaneously without colliding. Not a registered port; chosen for
32
+ * memorability + non-collision with the dev hub.
33
+ */
34
+ export declare const DEFAULT_SERVE_PORT = 6781;
35
+ /** Default bind host. Loopback only — matches `ggui dev`. */
36
+ export declare const DEFAULT_SERVE_HOST = "127.0.0.1";
37
+ export interface ParsedServeFlags {
38
+ /** Port to bind. Defaults to {@link DEFAULT_SERVE_PORT}. `0` = OS-assigned. */
39
+ port: number;
40
+ /** Host to bind. Defaults to {@link DEFAULT_SERVE_HOST}. */
41
+ host: string;
42
+ /**
43
+ * When true, boot MCP server only — skip agent supervision even
44
+ * if `ggui.json` has `agent.entry`. Operator opt-down per the
45
+ * §10.2a lock.
46
+ */
47
+ mcpOnly: boolean;
48
+ /**
49
+ * When true, switch the in-memory auth adapter to `devAllowAll: true`
50
+ * — every non-empty bearer (including the no-bearer probe MCP custom
51
+ * connectors send) authenticates as builder. Strictly a local-dev /
52
+ * tunnel-smoke escape hatch; production uses pairing or a custom
53
+ * `AuthAdapter`.
54
+ *
55
+ * NEVER expose a `--dev-allow-all` server to the open internet
56
+ * outside an ephemeral tunnel — the banner prints an unmissable
57
+ * warning when this flag is set.
58
+ */
59
+ devAllowAll: boolean;
60
+ /**
61
+ * Override the public base URL used to compose `mcpApps.renderBaseUrl`,
62
+ * `mcpApps.wsUrl`, and `runtime.url`. Without this, the URLs derive
63
+ * from `--host:--port`, which only resolves from the same machine.
64
+ * Set to a tunnel URL (`https://<random>.trycloudflare.com`) when
65
+ * testing against a remote MCP host so iframe-runtime + `/r/<code>`
66
+ * links resolve from the host's perspective.
67
+ *
68
+ * Trailing slash is stripped on parse. Must include scheme
69
+ * (`http://` or `https://`); the `wsUrl` is derived by replacing the
70
+ * scheme with `ws`/`wss`.
71
+ */
72
+ publicBaseUrl?: string;
73
+ /**
74
+ * When true, auto-spawn a cloudflared quick-tunnel pointed at the
75
+ * local listen port and treat the assigned URL as
76
+ * {@link publicBaseUrl}. Mutually exclusive with `--public-base-url`
77
+ * (operator gets EITHER explicit URL OR auto-tunnel).
78
+ *
79
+ * `--public + --dev-allow-all` combination is rejected at parse
80
+ * time unless `--i-know-its-public` is also set — exposing
81
+ * any-bearer auth to the open internet via cloudflared takes a
82
+ * deliberate flag.
83
+ */
84
+ publicAutoTunnel?: boolean;
85
+ /** Acknowledgement flag — see {@link publicAutoTunnel}. */
86
+ iKnowItsPublic?: boolean;
87
+ /**
88
+ * Mount the OAuth 2.1 + PKCE + Dynamic Client Registration routes
89
+ * required by MCP custom-connector hosts (claude.ai, ChatGPT) whose
90
+ * "Add connector" form has no field for a pre-shared bearer token.
91
+ *
92
+ * Flow when on:
93
+ * 1. Host hits `/mcp` without auth → 401 + WWW-Authenticate
94
+ * pointing at `/.well-known/oauth-protected-resource`.
95
+ * 2. Host fetches discovery → finds `/oauth/authorize` +
96
+ * `/oauth/token` + `/oauth/register`.
97
+ * 3. Host registers a client via DCR (no pre-shared secrets) +
98
+ * redirects user-agent to `/oauth/authorize`.
99
+ * 4. Server renders a paste-key page; operator pastes the
100
+ * paired bearer (from the landing page or `POST /pair`).
101
+ * 5. Server validates against the active `AuthAdapter`, mints
102
+ * an authorization code, redirects back with `?code=...`.
103
+ * 6. Host exchanges code → access_token (= the paired bearer).
104
+ * 7. Subsequent `/mcp` calls authenticate normally.
105
+ *
106
+ * Without `--oauth`, OAuth-discovery clients bail with "couldn't
107
+ * reach MCP server" because the .well-known endpoints 404. Pure-
108
+ * bearer clients (Claude Desktop with bearer in config, console,
109
+ * etc.) keep working without it.
110
+ */
111
+ oauth: boolean;
112
+ /**
113
+ * When true, run a public-facing demo: every non-empty bearer
114
+ * authenticates as builder (same auth shape as {@link devAllowAll})
115
+ * but with three differences:
116
+ *
117
+ * 1. Banner copy is "PUBLIC DEMO" with a "operator pays for the
118
+ * LLM" cost note, instead of the "DEV ALLOW-ALL" warning.
119
+ * 2. A per-remote-IP `FixedWindowRateLimiter` is bound to the
120
+ * `ggui_push` handler so a single visitor can't burn the
121
+ * operator's budget. Default: 30 push calls per 10 minutes per IP.
122
+ * 3. The pair-code beacon is suppressed (same as devAllowAll —
123
+ * pair codes are meaningless under any-bearer-auth).
124
+ *
125
+ * Mutually exclusive with {@link devAllowAll}: both relax /mcp auth
126
+ * the same way, but they describe different operator intents and
127
+ * surface different banner copy. Using both at once is rejected at
128
+ * parse time so the banner stays truthful.
129
+ *
130
+ * Use case: a developer hosting a small ggui demo for an audience
131
+ * (Show HN, blog post, classroom) where unauthenticated end-users
132
+ * should be able to interact, paid for by the operator's single
133
+ * shared LLM key in `~/.ggui/credentials.json`.
134
+ */
135
+ publicDemo: boolean;
136
+ /**
137
+ * Multi-tenant posture. Switches the `/ggui/console/llm-keys` gate
138
+ * from admin-token to auth-adapter — each authenticated end-user
139
+ * manages their OWN provider keys (scope = `userId` for `kind:'user'`
140
+ * identities, `appId` for `kind:'app'`). `kind:'builder'` identities
141
+ * are rejected at the gate.
142
+ *
143
+ * Strict-auth shape — every bearer must clear the `AuthAdapter`.
144
+ * Mutually exclusive with {@link devAllowAll} and {@link publicDemo};
145
+ * those modes collapse every identity to `kind:'builder'` which the
146
+ * multi-tenant gate rejects, so the combination would produce a
147
+ * server that's wired multi-tenant but can't authenticate anyone.
148
+ *
149
+ * Use case: a single `ggui serve` instance fronting many users (a
150
+ * shared dev box, a small team server) where each user pastes their
151
+ * own LLM key via /settings using their paired bearer.
152
+ */
153
+ multiTenant: boolean;
154
+ /**
155
+ * Server-level MCP instructions preset (the string injected into
156
+ * the LLM's system prompt above the tool catalog). Operator-tunable
157
+ * advisory level for tool-use posture:
158
+ *
159
+ * - `default` — gentle "ggui first when UI fits, prose otherwise"
160
+ * - `aggressive` — render anything with structure (no-preset default)
161
+ * - `always` — every response renders via ggui_push
162
+ * - `minimal` — server identity only, no behavioral nudge
163
+ * - `off` — omit the field entirely
164
+ *
165
+ * Surface = `--mcp-instructions <preset>` or
166
+ * `GGUI_MCP_INSTRUCTIONS=<preset>` env var (CLI flag wins).
167
+ * Custom strings can only be passed via programmatic embed
168
+ * (`createGguiServer({mcpInstructions: '...'})`).
169
+ */
170
+ mcpInstructions?: 'default' | 'aggressive' | 'always' | 'minimal' | 'off';
171
+ /**
172
+ * Skip auto-opening the operator's browser at the base URL after
173
+ * boot. Without this flag, `ggui serve` opens the local HTTP URL
174
+ * after the banner — server-side redirect routes first-run
175
+ * operators (no LLM creds) to the admin onboarding flow. Auto-open
176
+ * is also skipped for `--mcp-only` (no UI surface) and non-TTY
177
+ * sessions (CI, supervised, piped output).
178
+ *
179
+ * Surface = `--no-open` flag.
180
+ */
181
+ noOpen?: boolean;
182
+ /**
183
+ * Path to a JSON file backing the pairing service. When set, paired
184
+ * bearers survive a server restart — claude.ai stays connected
185
+ * across `ggui serve` runs.
186
+ *
187
+ * Stored in plaintext at the path with `0600` perms; assume the
188
+ * file lives on operator-controlled disk (e.g. `~/.ggui/keys.json`).
189
+ *
190
+ * Surface = `--keys-file <path>`.
191
+ */
192
+ keysFile?: string;
193
+ /**
194
+ * Disable the cross-restart persistence bundle. Without this flag,
195
+ * `ggui serve` reads or mints the HMAC secrets (and, in later
196
+ * slices, SessionStore + ShortCodeIndex + VectorStore + paired
197
+ * bearers) under `getPersistentDir(projectRoot)` so a server
198
+ * restart doesn't invalidate cached `_meta.ggui.bootstrap.token` +
199
+ * `/r/<code>?sig=&exp=` URLs — claude.ai chat-history revisits
200
+ * keep working.
201
+ *
202
+ * With `--ephemeral`, every restart mints fresh HMAC secrets (the
203
+ * legacy behavior). Use for tests / CI loops that don't want files
204
+ * written under `~/.ggui/` or the project root, and for incident-
205
+ * response nuclear-revoke scenarios.
206
+ *
207
+ * Surface = `--ephemeral`.
208
+ */
209
+ ephemeral?: boolean;
210
+ /**
211
+ * Operator-pinned admin bearer for the console `/keys` gate. Absent
212
+ * = the server mints a fresh `ggui_admin_*` per boot. Pin a value
213
+ * here when the operator wants the bearer to survive restarts (e.g.
214
+ * the same value lives in a password manager + an MCP-host config).
215
+ *
216
+ * Surface = `--admin-token <token>`.
217
+ */
218
+ adminToken?: string;
219
+ /** Populated when parsing failed; caller renders + bails with exit code 1. */
220
+ error?: string;
221
+ }
222
+ /**
223
+ * Parse the raw `ggui serve` argv tail. Returns a discriminated
224
+ * shape — `error` field is non-undefined on malformed input.
225
+ *
226
+ * Flag surface per the §10.2a lock:
227
+ * - `--port <n>` / `--host <addr>`: bind target.
228
+ * - `--mcp-only`: opt-down to MCP-only.
229
+ * - `--all`: REJECTED with a pointer to the real default. See doc lock.
230
+ * - `--help` / `-h`: help sentinel.
231
+ */
232
+ export declare function parseServeFlags(args: readonly string[]): ParsedServeFlags;
233
+ /**
234
+ * Resolved agent-component status for the banner + lifecycle. The
235
+ * CLI layer computes this from (flags, ggui.json state, resolution
236
+ * result) before calling {@link runServe}.
237
+ */
238
+ export type AgentStatus = {
239
+ readonly kind: 'running';
240
+ /** Display-friendly entry path (relative to cwd is fine). */
241
+ readonly entry: string;
242
+ /** `js` → plain node; `ts` → node --import=tsx. */
243
+ readonly language: 'js' | 'ts';
244
+ } | {
245
+ readonly kind: 'disabled';
246
+ readonly reason: AgentDisabledReason;
247
+ };
248
+ export type AgentDisabledReason = '--mcp-only' | 'no ggui.json' | 'ggui.json has no agent.entry';
249
+ /**
250
+ * Shape the banner a `ggui serve` run prints AFTER the server is
251
+ * listening. Pure so tests can pin the exact copy.
252
+ *
253
+ * Honest about scope — the CLI now wires strict auth (any bearer that
254
+ * isn't pair-minted is rejected) and pre-mints an initial pair code
255
+ * via the `pairCode` field so the operator's first-run flow has a
256
+ * concrete starting point. The blueprint-read handler family is still
257
+ * what ships today; `pairCode` is optional for backward-compat with
258
+ * embedding hosts that opt out of pairing.
259
+ */
260
+ export interface ServeBannerInputs {
261
+ /** The actual bound port. May differ from requested when `--port 0`. */
262
+ readonly port: number;
263
+ /** The actual bound host. */
264
+ readonly host: string;
265
+ /** Number of registered MCP tools. */
266
+ readonly toolCount: number;
267
+ /** Server name echoed in `info`. */
268
+ readonly serverName: string;
269
+ /** Server version echoed in `info`. */
270
+ readonly serverVersion: string;
271
+ /** Agent component status at banner time. */
272
+ readonly agent: AgentStatus;
273
+ /**
274
+ * Pre-minted initial pairing code, when the backend has pairing
275
+ * wired. `undefined` when pairing is disabled (future embedding
276
+ * hosts). Always present for `ggui serve` runs today.
277
+ */
278
+ readonly pairCode?: string;
279
+ /**
280
+ * Unix-millis expiry of {@link pairCode}. Present iff `pairCode`
281
+ * is present.
282
+ */
283
+ readonly pairCodeExpiresAt?: number;
284
+ /**
285
+ * When true, the auth section becomes a "DEV ALLOW-ALL" warning
286
+ * instead of the strict-auth blurb. Set by `--dev-allow-all`.
287
+ */
288
+ readonly devAllowAll?: boolean;
289
+ /**
290
+ * When true, the auth section becomes a "PUBLIC DEMO" warning with
291
+ * a cost-attribution + rate-limit note instead of the strict-auth
292
+ * blurb. Set by `--public-demo`. Mutually exclusive with
293
+ * `devAllowAll` at parse time; the banner asserts the same shape.
294
+ */
295
+ readonly publicDemo?: boolean;
296
+ /**
297
+ * When true, the auth section adds a "MULTI-TENANT" line below the
298
+ * strict-auth blurb explaining that each user manages their own LLM
299
+ * keys via /settings under their paired bearer. Set by
300
+ * `--multi-tenant`. Mutually exclusive with `devAllowAll` and
301
+ * `publicDemo` at parse time.
302
+ */
303
+ readonly multiTenant?: boolean;
304
+ /**
305
+ * Public base URL displayed under the local URLs when set via
306
+ * `--public-base-url`. Reminds the operator which URL their tunnel
307
+ * is forwarding to without grepping the agent-emitted shortCode
308
+ * URLs.
309
+ */
310
+ readonly publicBaseUrl?: string;
311
+ /**
312
+ * When true, the auth section advertises OAuth discovery so the
313
+ * operator can see at a glance that custom-connector hosts will
314
+ * be able to complete the auth dance. Absent → no extra line.
315
+ */
316
+ readonly oauth?: boolean;
317
+ /**
318
+ * Admin token printed prominently in the banner so operators can
319
+ * paste it into the console `/admin-login` page. Absent → no line
320
+ * (e.g. an embedded host with no console wired).
321
+ */
322
+ readonly adminToken?: string;
323
+ /**
324
+ * When true, the banner adds an action line pointing the operator at
325
+ * the console `/settings` page so they can paste an LLM key without
326
+ * touching env vars or restarting. Set when `describeGenerationBinding`
327
+ * returned null (no env var + no credentials-file entry).
328
+ */
329
+ readonly noLlmKey?: boolean;
330
+ /**
331
+ * Embedding model id surfaced for the local RAG layer. When set,
332
+ * the banner shows a `rag` line so operators see which model is
333
+ * wired (and that bge-small downloads lazily on first push). Absent
334
+ * when no embedding is wired (e.g. tests, programmatic embeds that
335
+ * fall back to MockEmbeddingProvider).
336
+ */
337
+ readonly embeddingModel?: string;
338
+ }
339
+ export declare function describeServeBanner(input: ServeBannerInputs): string[];
340
+ /**
341
+ * Banner cell for the `agent` line. Pure — tests pin the copy.
342
+ */
343
+ export declare function describeAgentStatus(status: AgentStatus): string;
344
+ /**
345
+ * Minimal shape the CLI runner needs back from `@ggui-ai/mcp-server`.
346
+ * The real factory returns more (the Express app, plus lifecycle
347
+ * plumbing); we narrow here so tests can substitute without
348
+ * conjuring an `Express` instance or pulling node:http types into
349
+ * the pure module.
350
+ */
351
+ export interface ServeBackend {
352
+ /** Bind and accept connections. Resolves to the bound port. */
353
+ listen(port: number, host: string): Promise<number>;
354
+ /** Close all connections. Idempotent. */
355
+ close(): Promise<void>;
356
+ /** Number of MCP tools registered on this server. */
357
+ readonly toolCount: number;
358
+ /** Server name echoed in `info`. */
359
+ readonly serverName: string;
360
+ /** Server version echoed in `info`. */
361
+ readonly serverVersion: string;
362
+ /**
363
+ * Count of primitive catalogs the backend composed from
364
+ * `ggui.json#primitives.{packages,local}`. Surfaced narrow (count
365
+ * only, not the catalog shape) so the test narrowing stays tight
366
+ * — integration tests that need the full shape compose
367
+ * `createGguiServer` directly.
368
+ */
369
+ readonly primitiveCatalogCount: number;
370
+ /**
371
+ * Which theme source backs `server.theme` — `'default'` when the
372
+ * CLI passed nothing (server fell back to the shipped
373
+ * `@ggui-ai/design` lightTheme), `'file'` when the operator's
374
+ * `ggui.json#theme = { file: ... }` resolved cleanly, `'preset'`
375
+ * when the operator selected one of the registered DTCG presets
376
+ * (`ggui.json#theme = "claudic"` shorthand or
377
+ * `{ preset: 'claudic', mode: 'dark', overrides: {...} }`). Tests
378
+ * use this to prove the thread-through without reaching into the
379
+ * `GguiServer` shape.
380
+ */
381
+ readonly themeSource: 'default' | 'file' | 'preset';
382
+ /**
383
+ * Composed pairing service, or `null` when the backend was built
384
+ * without pairing. `ggui serve`'s default bundle always wires
385
+ * pairing on; this field is nullable to keep the `ServeBackend`
386
+ * contract truthful for future embedding hosts that opt out.
387
+ *
388
+ * `runServe` uses this to pre-mint an initial pair code after bind
389
+ * (so a fresh operator's first-run flow doesn't need a pre-existing
390
+ * bearer to trigger `/admin/pair/init`). Tests substitute `null` to
391
+ * exercise the "no pre-mint" branch.
392
+ */
393
+ readonly pairingService: PairingService | null;
394
+ /**
395
+ * Admin bearer that gates the console `/keys` plane (mint / list /
396
+ * revoke + admin-login). Either the operator-supplied value (via
397
+ * `--admin-token`) or a fresh `ggui_admin_*` minted on boot when
398
+ * that flag is absent. `null` when the backend has no console wired
399
+ * — the CLI bundle always does, so this is non-null in practice.
400
+ *
401
+ * Surfaced narrow on the `ServeBackend` contract so `runServe` can
402
+ * banner-print it next to PAIR_CODE without reaching into the
403
+ * `GguiServer` shape.
404
+ */
405
+ readonly adminToken: string | null;
406
+ /**
407
+ * Embedding model id for the local RAG layer. Set when the backend
408
+ * wired `createLocalEmbeddingProvider` (CLI default — bge-small-en-
409
+ * v1.5). Absent when the backend fell back to `MockEmbeddingProvider`
410
+ * (programmatic embeds / test paths). Used by `describeServeBanner`
411
+ * to surface the RAG model in the boot banner so operators see
412
+ * what's wired.
413
+ */
414
+ readonly embeddingModel?: string;
415
+ }
416
+ /**
417
+ * Factory that constructs the backend. Injectable so tests can
418
+ * provide a deterministic fake without booting a real HTTP server.
419
+ * Production wiring in `cli.ts` passes a factory that composes
420
+ * `@ggui-ai/mcp-server`'s `createGguiServer` + the package's `info`.
421
+ */
422
+ export type ServeBackendFactory = () => ServeBackend;
423
+ /**
424
+ * Supervised-agent plumbing. Only populated when `runServe` has been
425
+ * asked to run the agent (i.e. `status.kind === 'running'`). `cli.ts`
426
+ * assembles this from `./agent-resolution.ts` + the loaded `ggui.json`.
427
+ */
428
+ export interface ServeAgentSupervision {
429
+ readonly adapter: AgentRuntimeAdapter;
430
+ readonly startInput: AgentRuntimeStartInput;
431
+ /**
432
+ * Event sink — called for every `AgentRuntimeEvent` emitted by the
433
+ * adapter between start and stop. Production wires a logger;
434
+ * tests use a collector. Optional: omitting it silently discards
435
+ * the event stream (still valid for tests that only care about
436
+ * lifecycle, not logs).
437
+ */
438
+ readonly onEvent?: (event: AgentRuntimeEvent) => void;
439
+ }
440
+ /**
441
+ * Shape of the "await until shutdown" signal. Production uses an
442
+ * in-process SIGINT/SIGTERM listener; tests pass a manual AbortSignal
443
+ * to trigger a graceful close without raising real signals.
444
+ */
445
+ export interface ServeShutdownSignal {
446
+ readonly aborted: boolean;
447
+ addEventListener(event: 'abort', handler: () => void, opts?: {
448
+ once?: boolean;
449
+ }): void;
450
+ }
451
+ export interface RunServeOptions {
452
+ /** Parsed flags. The `error` field must already be handled upstream. */
453
+ readonly flags: Readonly<Omit<ParsedServeFlags, 'error'>>;
454
+ /** Build the backend. Called once, after flag parsing. */
455
+ readonly backendFactory: ServeBackendFactory;
456
+ /**
457
+ * Agent supervision plumbing. Populated iff `agentStatus.kind ===
458
+ * 'running'`. When undefined, `runServe` skips supervision entirely.
459
+ */
460
+ readonly agent?: ServeAgentSupervision;
461
+ /** Pre-resolved banner status — `cli.ts` picks this per the fallback matrix. */
462
+ readonly agentStatus: AgentStatus;
463
+ /**
464
+ * When true, the boot banner emits a "/settings to set your LLM key"
465
+ * action line so first-run operators know how to recover from
466
+ * `ggui_push` returning codeReady:false. Set by `cli.ts` when the
467
+ * generation probe returned null (no env + no credentials-file).
468
+ */
469
+ readonly noLlmKey?: boolean;
470
+ /** Where to write the banner. */
471
+ readonly stdout: {
472
+ write(chunk: string): void;
473
+ };
474
+ /**
475
+ * Signal that resolves the serve loop. Production composes this
476
+ * from SIGINT + SIGTERM; tests abort it manually.
477
+ */
478
+ readonly shutdownSignal: ServeShutdownSignal;
479
+ }
480
+ /**
481
+ * Boot the backend, start the agent (if any), print the banner, then
482
+ * block until the shutdown signal fires. On signal, stops both
483
+ * components gracefully and resolves.
484
+ *
485
+ * Agent-crash policy (§10.2a lock): a crash AFTER boot surfaces as
486
+ * an `onEvent({type:'status', status:'crashed'})` delivery — the
487
+ * serve loop keeps MCP running and waits for shutdown. No auto-
488
+ * restart in v1. Operators compose restart policies via their own
489
+ * supervisor.
490
+ *
491
+ * MCP failure surfaces as a thrown error from `backendFactory()` /
492
+ * `backend.listen()` and propagates to `cli.ts` (exit 1).
493
+ *
494
+ * Pure enough to unit-test: the HTTP binding, signal wiring, and
495
+ * banner render are all either injected or pinned by
496
+ * {@link describeServeBanner} / {@link describeAgentStatus}.
497
+ */
498
+ export declare function runServe(opts: RunServeOptions): Promise<number>;
499
+ export declare const SERVE_HELP = "ggui serve \u2014 run the open self-hosted personal-mode app\n\nBoots the @ggui-ai/mcp-server binding with persistent defaults AND\n(by default) supervises your agent alongside it. The current MCP\nhandler surface is the blueprint-read family (search / list_featured\n/ render); more tools come online as @ggui-ai/mcp-server-handlers\ngrows.\n\nFirst-run bundle (all on by default):\n - Landing page at / \u2014 operator opens a browser and sees\n server identity + pair-code card.\n - Session viewer at /r/<code> \u2014 same-origin viewer for sessions\n minted by ggui_push; same-origin\n HTTP-only cookie authenticates the\n live-channel /ws upgrade.\n - POST /pair + POST /admin/pair/init \u2014 pairing endpoint for MCP\n hosts and third-party clients.\n - Live-channel /ws \u2014 live session plane for MCP Apps\n iframes and the console.\n\nEmbedding hosts that want a different shape (no landing page, no\npairing, programmatic control) should compose createGguiServer()\ndirectly in code rather than invoking `ggui serve`.\n\nUsage:\n ggui serve [options]\n\nOptions:\n --port <n> Bind port (default: 6781, 0 = OS-assigned).\n --host <addr> Bind host (default: 127.0.0.1).\n --mcp-only Run just the MCP server; do not supervise an agent.\n --dev-allow-all Accept any non-empty bearer (incl. no bearer) as\n builder. Local-dev / tunnel smoke ONLY \u2014 never\n expose to the open internet.\n --public-demo Public-facing demo posture: same any-bearer auth\n as --dev-allow-all, plus per-IP rate limit on\n ggui_push (30 generations / 10 min) and a\n \"PUBLIC DEMO \u2014 operator pays\" banner. Mutually\n exclusive with --dev-allow-all.\n --multi-tenant Multi-tenant posture: switches the /settings LLM-\n keys gate from admin-token to auth-adapter so\n each authenticated end-user manages their OWN\n key plane (scope = userId/appId). kind:'builder'\n identities are rejected at the gate. Strict-auth\n only; mutually exclusive with --dev-allow-all\n and --public-demo. (Generation-time BYOK still\n resolves at the operator 'global' scope \u2014 a\n follow-up will thread per-user BYOK through\n ggui_push.)\n --public-base-url <u> Override the public base URL used to compose\n iframe-runtime + shortCode URLs. Set this to a\n tunnel URL (https://<random>.trycloudflare.com)\n when testing against a remote MCP host so URLs\n resolve from the host's perspective. Without\n this, URLs derive from --host:--port and only\n work from the same machine.\n --oauth Mount OAuth 2.1 + PKCE + Dynamic Client\n Registration routes (.well-known/oauth-* +\n /oauth/{authorize,token,register}). Required\n for MCP custom-connector hosts (claude.ai,\n ChatGPT) whose Add Connector form has no field\n for a pre-shared bearer; OAuth lets them do\n a discovery \u2192 DCR \u2192 consent dance ending in\n the same paired bearer the strict-auth flow\n already mints. Pure-bearer clients (Claude\n Desktop with bearer in config) work without it.\n --admin-token <t> Pin the admin bearer that gates the console\n /keys plane (list / mint / revoke pairings +\n /admin-login route). Without this, the server\n mints a fresh ggui_admin_* token per boot and\n prints it on the banner. Pin a stable value\n when you want the bearer to survive restarts\n (e.g. paste once into a password manager).\n --ephemeral Disable cross-restart persistence. Without\n this flag, the HMAC secrets that sign MCP\n Apps bootstrap tokens and signed render URLs\n are read or minted under .ggui/persistent/\n (project-local if a ggui.json was resolved,\n else ~/.ggui/persistent/) so cached tokens\n survive a server restart. Pass this flag to\n keep restarts ephemeral (tests / CI / nuclear-\n revoke). Override the dir via GGUI_PERSISTENT_DIR.\n --help, -h Show this help.\n\nAgent runtime:\n The default boots your agent alongside MCP. The agent's entry file\n comes from ggui.json:\n\n { \"agent\": { \"entry\": \"./agent.ts\" } }\n\n Supported extensions: .js / .mjs / .cjs (node), .ts / .tsx / .mts\n (node --import=tsx). No ggui.json, or no agent.entry, falls back\n to MCP-only with a warning. Malformed ggui.json or a bad entry\n is a hard error.\n\n Agent crashes after startup are logged; the MCP server keeps\n running. No auto-restart \u2014 compose that with your own supervisor.\n\nPersistent storage (default-on; opt-out via --ephemeral):\n By default `ggui serve` writes a small bundle under .ggui/persistent/\n (project-local if a ggui.json was resolved, else ~/.ggui/persistent/)\n so cached MCP Apps tokens, signed render URLs, shortCodes, sessions,\n vectors, and paired bearers survive a restart \u2014 claude.ai chat-history\n revisits keep working.\n\n Bundle layout:\n\n .ggui/persistent/\n \u251C\u2500\u2500 bootstrap-secret.hex (HMAC, 0600)\n \u251C\u2500\u2500 render-signer-secret.hex (HMAC, 0600)\n \u251C\u2500\u2500 short-codes.sqlite (/r/<code> + /api/bootstrap/<code> resolution)\n \u251C\u2500\u2500 sessions.sqlite (SessionStore \u2014 stack items + event history)\n \u251C\u2500\u2500 vectors.sqlite (RAG corpus)\n \u2514\u2500\u2500 keys.json (paired bearers)\n\n Override the dir with `GGUI_PERSISTENT_DIR`. Pass `--ephemeral` to\n skip the bundle entirely (tests, CI loops, nuclear-revoke).\n\n Explicit ggui.json#storage declarations always win \u2014 declare\n `{ \"sessions\": { \"driver\": \"memory\" } }` to opt sessions back to\n in-memory while keeping other surfaces persistent. Custom sqlite\n paths via ggui.json#storage are honored verbatim:\n\n {\n \"storage\": {\n \"sessions\": { \"driver\": \"sqlite\", \"path\": \"./ggui-sessions.sqlite\" },\n \"vectors\": { \"driver\": \"sqlite\", \"path\": \"./ggui-vectors.sqlite\" },\n \"threads\": { \"driver\": \"sqlite\", \"path\": \"./ggui-threads.sqlite\" }\n }\n }\n\n Threads: the persistent-chat route family (/threads) is opt-in.\n Absent `storage.threads` leaves the routes unmounted \u2014 pairs\n with Portal's self-hosted origins only when declared. Driver\n semantics:\n - `driver: \"sqlite\"` \u2014 durable. Threads survive restart.\n /ggui/health reports `threads.durability: \"durable\"`;\n Portal hides its non-durable caveat.\n - `driver: \"memory\"` \u2014 routes mount but data is lost on\n restart. /ggui/health reports `threads.durability:\n \"ephemeral\"`; Portal shows its caveat.\n\n Paths resolve relative to the ggui.json directory. The sqlite\n driver needs `better-sqlite3` installed in your project.\n\nRecommended setups:\n\n Local-only smoke (no tunnel, no remote MCP host):\n ggui serve\n\n claude.ai custom connector (over a public tunnel):\n 1. Tunnel: cloudflared tunnel --url http://localhost:6781\n 2. ggui serve --oauth \\\n --public-base-url https://<tunnel>.trycloudflare.com\n 3. Note PAIR_CODE from boot. Visit the landing page (the public URL\n above), complete pairing, save the bearer.\n 4. claude.ai \u2192 Settings \u2192 Connectors \u2192 Add custom connector.\n URL: https://<tunnel>.trycloudflare.com/mcp\n Client ID / Secret: leave empty (server uses Dynamic Client\n Registration; no pre-shared secret needed).\n 5. Click Connect \u2192 claude.ai redirects you to a paste-key page.\n Paste the bearer from step 3. Done.\n\n Quick local-dev WITHOUT auth (NEVER over a public tunnel):\n ggui serve --dev-allow-all\n\nCurrent limits:\n - Strict-auth only: /mcp rejects any bearer that isn't pair-minted.\n The CLI pre-mints one pairing code on boot (printed as\n `PAIR_CODE <code>` and shown in the banner + on the landing\n page). Complete `POST /pair {code, deviceName}` to receive a\n bearer you can use with MCP. Embed @ggui-ai/mcp-server in your\n own entrypoint to inject a different AuthAdapter (OIDC, Cognito,\n etc.) for production.\n - Single-tenant: every request scopes to one `builder` app id.\n";
500
+ //# sourceMappingURL=serve-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-command.d.ts","sourceRoot":"","sources":["../src/serve-command.ts"],"names":[],"mappings":"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"}