@ggui-ai/project-config 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.
@@ -0,0 +1,520 @@
1
+ /**
2
+ * `ggui.json` v1 — the OSS `ggui` server's runtime source of truth.
3
+ *
4
+ * When a developer runs `ggui serve`, the OSS server reads this file
5
+ * to discover everything it needs: app identity, protocol version,
6
+ * blueprint manifests, primitive packages, theme tokens, declared
7
+ * adapter intent. The schema is framework-neutral — it describes
8
+ * *the ggui app*, never the internal orchestration of any specific
9
+ * agent runtime. LLM choice, system prompt, framework-specific tool
10
+ * inventory belong in each framework's own config, not here.
11
+ *
12
+ * The manifest surface model:
13
+ *
14
+ * - `ggui.json` — this file. Open. Root manifest.
15
+ * - `ggui.ui.json` — one per authored UI, colocated with source.
16
+ * Indexed via `blueprints.include` globs.
17
+ *
18
+ * **Rules for extending:**
19
+ *
20
+ * 1. **Additive only within `schema: '1'`.** Optional fields with
21
+ * defaults are safe. New top-level fields MUST default to
22
+ * behavioural no-ops so older tooling can ignore them.
23
+ * 2. **Framework-neutral.** If a field is meaningful only to one
24
+ * agent framework (Claude SDK, Vercel AI SDK, LangGraph, ADK,
25
+ * CrewAI, Mastra, etc.), it does NOT belong here. Same manifest
26
+ * describes the same ggui app across all frameworks.
27
+ * 3. **Host-neutral.** Build / runtime / deploy / sizing fields live
28
+ * in a hosting-vendor overlay, never here.
29
+ * 4. **No vendor names in enum values.** `residency: 'acme-cloud'`
30
+ * is the exact mistake a previous draft made. If an enum needs
31
+ * to name a hosting provider, it belongs in that provider's
32
+ * overlay.
33
+ *
34
+ * **Strictness (locked 2026-04-18):**
35
+ *
36
+ * Root object is strict — unknown top-level keys cause parse to
37
+ * fail. This catches typos (`"blueprint"` singular, `"component"`
38
+ * for `"primitives"`, etc.) and prevents silent drift toward the
39
+ * agent-runtime-centric shape we explicitly rejected. Nested
40
+ * objects are also strict for v1; additive fields are a coordinated
41
+ * schema change, not a drive-by.
42
+ */
43
+ import { z } from 'zod';
44
+ /**
45
+ * Operator identity — who's running this server. Surfaced on the
46
+ * public welcome page at `/` so visitors see "operated by X" instead
47
+ * of unbranded server chrome.
48
+ *
49
+ * **Privacy-first by default.** Every field is optional. Nothing is
50
+ * shown when nothing is set — no "anonymous" placeholder, no
51
+ * hostname-derived fallback. The visitor sees just server identity
52
+ * and public-surface affordances (login link, share-link hints).
53
+ *
54
+ * Distinct from `app` (which identifies the *server*) — `operator`
55
+ * identifies the *human/entity* running the server. A single
56
+ * operator can run multiple `app`s, but the welcome page always
57
+ * shows ONE operator block (one server = one ggui.json).
58
+ *
59
+ * **What this is NOT:**
60
+ * - Not auth (the admin token is its own credential)
61
+ * - Not telemetry (server doesn't phone home with operator info)
62
+ * - Not user/builder identity (those are MCP-pairing concerns)
63
+ */
64
+ declare const OperatorSchema: z.ZodObject<{
65
+ /** Display name shown on the welcome page. e.g. "Wanseob Lim" or
66
+ * "Loqu Inc.". Free-form — no slug constraint. */
67
+ name: z.ZodOptional<z.ZodString>;
68
+ /** Operator's homepage / brand URL. Linkified on the welcome page
69
+ * if set. Must be a valid http(s) URL. */
70
+ url: z.ZodOptional<z.ZodURL>;
71
+ /** One-line description shown under the operator name. e.g.
72
+ * "personal ggui server — tinkering only" or "Loqu's hosted ggui
73
+ * for friends + family". Plain text, no markup. */
74
+ tagline: z.ZodOptional<z.ZodString>;
75
+ /** mailto-eligible contact address. Linkified as `mailto:` on the
76
+ * welcome page if set. Operators uncomfortable putting this on a
77
+ * public page should leave it unset — `name` and `url` carry the
78
+ * "how to reach me" load just as well. */
79
+ contact: z.ZodOptional<z.ZodEmail>;
80
+ }, z.core.$strict>;
81
+ /** Public type alias for the operator block. */
82
+ export type OperatorConfig = z.infer<typeof OperatorSchema>;
83
+ /**
84
+ * Discriminated theme selection. Three accepted shapes:
85
+ *
86
+ * 1. `string` — preset id shorthand (`theme: 'claudic'` ≡
87
+ * `theme: { preset: 'claudic' }`)
88
+ * 2. `{ preset, mode?, overrides? }` — registered preset with
89
+ * optional mode + override layer
90
+ * 3. `{ file, mode? }` — DTCG JSON file
91
+ *
92
+ * Strict objects on shapes 2 and 3 reject unknown keys to catch
93
+ * typos at parse (`{ presset: 'claudic' }` fails, not silently
94
+ * loads default).
95
+ */
96
+ export declare const ThemeConfigSchema: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
97
+ preset: z.ZodString;
98
+ mode: z.ZodOptional<z.ZodEnum<{
99
+ light: "light";
100
+ dark: "dark";
101
+ }>>;
102
+ overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
103
+ }, z.core.$strict>, z.ZodObject<{
104
+ file: z.ZodString;
105
+ mode: z.ZodOptional<z.ZodEnum<{
106
+ light: "light";
107
+ dark: "dark";
108
+ }>>;
109
+ }, z.core.$strict>]>;
110
+ /**
111
+ * Discriminated union over storage drivers. Add new drivers as
112
+ * additive siblings under the same discriminator — never widen an
113
+ * existing variant, since that would silently change what older
114
+ * manifests mean.
115
+ */
116
+ declare const StorageSurfaceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
117
+ driver: z.ZodLiteral<"memory">;
118
+ }, z.core.$strict>, z.ZodObject<{
119
+ driver: z.ZodLiteral<"sqlite">;
120
+ /** Filesystem path to the SQLite database file. Relative paths
121
+ * resolve from the ggui.json directory at adapter-instantiation
122
+ * time. Empty strings are rejected at parse. */
123
+ path: z.ZodString;
124
+ }, z.core.$strict>], "driver">;
125
+ declare const StorageSchema: z.ZodObject<{
126
+ /** Session persistence (events + stack + identity). Absent =
127
+ * in-memory (sessions reset on restart). */
128
+ sessions: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
129
+ driver: z.ZodLiteral<"memory">;
130
+ }, z.core.$strict>, z.ZodObject<{
131
+ driver: z.ZodLiteral<"sqlite">;
132
+ /** Filesystem path to the SQLite database file. Relative paths
133
+ * resolve from the ggui.json directory at adapter-instantiation
134
+ * time. Empty strings are rejected at parse. */
135
+ path: z.ZodString;
136
+ }, z.core.$strict>], "driver">>;
137
+ /** Vector index persistence (RAG, blueprint embeddings). Absent =
138
+ * in-memory (index rebuilds on restart). */
139
+ vectors: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
140
+ driver: z.ZodLiteral<"memory">;
141
+ }, z.core.$strict>, z.ZodObject<{
142
+ driver: z.ZodLiteral<"sqlite">;
143
+ /** Filesystem path to the SQLite database file. Relative paths
144
+ * resolve from the ggui.json directory at adapter-instantiation
145
+ * time. Empty strings are rejected at parse. */
146
+ path: z.ZodString;
147
+ }, z.core.$strict>], "driver">>;
148
+ /** Persistent-chat thread + message persistence. Absent = in-memory
149
+ * (threads vanish on restart — correct for dev, unsafe for any
150
+ * deployment Portal's self-hosted flow talks to). Pair with
151
+ * `driver: 'sqlite'` + a `path` for durable local storage; the
152
+ * `@ggui-ai/mcp-server-core/sqlite#SqliteThreadStore` reference
153
+ * impl consumes the same file-per-surface layout the sessions/
154
+ * vectors drivers already use. */
155
+ threads: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
156
+ driver: z.ZodLiteral<"memory">;
157
+ }, z.core.$strict>, z.ZodObject<{
158
+ driver: z.ZodLiteral<"sqlite">;
159
+ /** Filesystem path to the SQLite database file. Relative paths
160
+ * resolve from the ggui.json directory at adapter-instantiation
161
+ * time. Empty strings are rejected at parse. */
162
+ path: z.ZodString;
163
+ }, z.core.$strict>], "driver">>;
164
+ }, z.core.$strict>;
165
+ /**
166
+ * Public type alias for one storage surface's config (sessions or
167
+ * vectors). Callers instantiating adapters from a parsed manifest
168
+ * pattern-match on `driver`.
169
+ */
170
+ export type StorageSurfaceConfig = z.infer<typeof StorageSurfaceSchema>;
171
+ /** Public type alias for the full storage block. */
172
+ export type StorageConfig = z.infer<typeof StorageSchema>;
173
+ /**
174
+ * Public type alias for the resolved theme selection (post-parse).
175
+ *
176
+ * `theme` in `ggui.json` accepts a string shorthand, a preset
177
+ * config object, or a file config object. Consumers reading a
178
+ * parsed `GguiJsonV1` pattern-match on shape (`typeof === 'string'`,
179
+ * `'preset' in value`, `'file' in value`).
180
+ */
181
+ export type ThemeConfig = z.infer<typeof ThemeConfigSchema>;
182
+ /**
183
+ * The authoritative v1 schema. `z.infer<typeof GguiJsonV1>` yields
184
+ * the static TypeScript type. A valid document round-trips cleanly:
185
+ * parse → `JSON.stringify` → re-parse produces an equivalent value.
186
+ *
187
+ * **Required fields:** `schema`, `protocol`, `app`.
188
+ * **Optional fields with defaults:** `blueprints`, `primitives`,
189
+ * `adapters`. A zero-config `ggui.json` is just the three required
190
+ * fields — the OSS server boots with defaults for everything else.
191
+ * **Optional without default:** `theme` (absent = shipped default
192
+ * tokens), `agent` (absent = `ggui serve` runs MCP-only).
193
+ *
194
+ * **Strict root:** unknown top-level keys are rejected.
195
+ */
196
+ export declare const GguiJsonV1: z.ZodObject<{
197
+ /** File-format version — always `"1"` for v1. Distinct from
198
+ * `protocol` (which versions the wire contract the app speaks). */
199
+ schema: z.ZodLiteral<"1">;
200
+ /** ggui wire protocol version the app speaks. */
201
+ protocol: z.ZodString;
202
+ /** App identity. */
203
+ app: z.ZodObject<{
204
+ slug: z.ZodString;
205
+ name: z.ZodString;
206
+ /**
207
+ * Per-app gadget catalog. The CLI
208
+ * passes these through to `InMemoryAppMetadataStore` so the
209
+ * handshake / push / ops handlers can validate every
210
+ * `clientCapabilities.gadgets[*]` ref against the registered
211
+ * set's package identity + export names. Each entry is a gadget
212
+ * PACKAGE and MUST satisfy the strict
213
+ * `strictGadgetDescriptorSchema` from `@ggui-ai/protocol`
214
+ * (a non-empty `exports[]` array, each export carrying required
215
+ * description / usage / example).
216
+ *
217
+ * Omitting this field falls back to the protocol's
218
+ * `STDLIB_GADGETS` defaults (the 7 first-party hooks).
219
+ * Declared 3rd-party wrappers (Leaflet, Mapbox, Stripe, …) land
220
+ * here.
221
+ */
222
+ gadgets: z.ZodOptional<z.ZodArray<z.ZodObject<{
223
+ exports: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
224
+ description: z.ZodString;
225
+ usage: z.ZodString;
226
+ example: z.ZodType<import("@ggui-ai/protocol").JsonValue, unknown, z.core.$ZodTypeInternals<import("@ggui-ai/protocol").JsonValue, unknown>>;
227
+ permission: z.ZodOptional<z.ZodEnum<{
228
+ camera: "camera";
229
+ "clipboard-read": "clipboard-read";
230
+ "clipboard-write": "clipboard-write";
231
+ geolocation: "geolocation";
232
+ microphone: "microphone";
233
+ notifications: "notifications";
234
+ "persistent-storage": "persistent-storage";
235
+ midi: "midi";
236
+ "speaker-selection": "speaker-selection";
237
+ "storage-access": "storage-access";
238
+ "background-sync": "background-sync";
239
+ accelerometer: "accelerometer";
240
+ gyroscope: "gyroscope";
241
+ magnetometer: "magnetometer";
242
+ "ambient-light-sensor": "ambient-light-sensor";
243
+ "screen-wake-lock": "screen-wake-lock";
244
+ }>>;
245
+ gotchas: z.ZodOptional<z.ZodString>;
246
+ required: z.ZodOptional<z.ZodBoolean>;
247
+ hook: z.ZodString;
248
+ }, z.core.$strict>, z.ZodObject<{
249
+ description: z.ZodString;
250
+ usage: z.ZodString;
251
+ example: z.ZodType<import("@ggui-ai/protocol").JsonValue, unknown, z.core.$ZodTypeInternals<import("@ggui-ai/protocol").JsonValue, unknown>>;
252
+ permission: z.ZodOptional<z.ZodEnum<{
253
+ camera: "camera";
254
+ "clipboard-read": "clipboard-read";
255
+ "clipboard-write": "clipboard-write";
256
+ geolocation: "geolocation";
257
+ microphone: "microphone";
258
+ notifications: "notifications";
259
+ "persistent-storage": "persistent-storage";
260
+ midi: "midi";
261
+ "speaker-selection": "speaker-selection";
262
+ "storage-access": "storage-access";
263
+ "background-sync": "background-sync";
264
+ accelerometer: "accelerometer";
265
+ gyroscope: "gyroscope";
266
+ magnetometer: "magnetometer";
267
+ "ambient-light-sensor": "ambient-light-sensor";
268
+ "screen-wake-lock": "screen-wake-lock";
269
+ }>>;
270
+ gotchas: z.ZodOptional<z.ZodString>;
271
+ required: z.ZodOptional<z.ZodBoolean>;
272
+ component: z.ZodString;
273
+ }, z.core.$strict>]>>;
274
+ version: z.ZodString;
275
+ package: z.ZodString;
276
+ bundleUrl: z.ZodOptional<z.ZodURL>;
277
+ bundleHost: z.ZodOptional<z.ZodString>;
278
+ bundleSri: z.ZodOptional<z.ZodString>;
279
+ styleUrl: z.ZodOptional<z.ZodURL>;
280
+ connect: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodURL>>>;
281
+ requires: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
282
+ typesUrl: z.ZodOptional<z.ZodURL>;
283
+ typesSri: z.ZodOptional<z.ZodString>;
284
+ }, z.core.$strict>>>;
285
+ /**
286
+ * Public env channel. Operator-stamped key→value map that
287
+ * the server projects (filtered to declared wrappers' `requires`)
288
+ * onto `globalThis.__ggui__.publicEnv` so wrapper hooks can read
289
+ * values via `getPublicEnv(key)`.
290
+ *
291
+ * Keys MUST match `GGUI_PUBLIC_APP_[A-Z0-9_]+` — the `GGUI_PUBLIC_USER_`
292
+ * namespace is reserved for a future per-user channel. Values are
293
+ * arbitrary strings; the server projects only keys whose values are
294
+ * declared in some registered wrapper's `requires`. Operators who
295
+ * declare a key without a value can use the empty string (the
296
+ * Mapbox SDK will surface "Invalid token" on first request rather
297
+ * than a missing-key error from the push gate).
298
+ *
299
+ * Omitting this field is equivalent to `{}` — wrappers without
300
+ * `requires` work unchanged; wrappers that declare `requires` will
301
+ * fail at push-gate validation if their required keys are missing.
302
+ */
303
+ publicEnv: z.ZodOptional<z.ZodReadonly<z.ZodRecord<z.ZodString, z.ZodString>>>;
304
+ /**
305
+ * MCP-Apps presentation mode (canvas slice). `'canvas'` makes
306
+ * `ggui_new_session` mint a session-scoped iframe
307
+ * (`ui://ggui/session/<sessionId>`) and route subsequent pushes
308
+ * through the session WebSocket channel instead of returning a
309
+ * per-push `ui://ggui/render/<shortCode>` resource. `'inline'`
310
+ * (default when omitted) preserves the per-push iframe behavior
311
+ * that flagship MCP-Apps hosts already expect.
312
+ */
313
+ defaultMcpAppsMode: z.ZodOptional<z.ZodEnum<{
314
+ inline: "inline";
315
+ canvas: "canvas";
316
+ }>>;
317
+ }, z.core.$strict>;
318
+ /** Operator identity — who's running this server. Optional;
319
+ * surfaced on the public welcome page at `/` when set. Privacy-
320
+ * first: nothing renders when nothing is set, no "anonymous"
321
+ * placeholder. See {@link OperatorConfig}. */
322
+ operator: z.ZodOptional<z.ZodObject<{
323
+ /** Display name shown on the welcome page. e.g. "Wanseob Lim" or
324
+ * "Loqu Inc.". Free-form — no slug constraint. */
325
+ name: z.ZodOptional<z.ZodString>;
326
+ /** Operator's homepage / brand URL. Linkified on the welcome page
327
+ * if set. Must be a valid http(s) URL. */
328
+ url: z.ZodOptional<z.ZodURL>;
329
+ /** One-line description shown under the operator name. e.g.
330
+ * "personal ggui server — tinkering only" or "Loqu's hosted ggui
331
+ * for friends + family". Plain text, no markup. */
332
+ tagline: z.ZodOptional<z.ZodString>;
333
+ /** mailto-eligible contact address. Linkified as `mailto:` on the
334
+ * welcome page if set. Operators uncomfortable putting this on a
335
+ * public page should leave it unset — `name` and `url` carry the
336
+ * "how to reach me" load just as well. */
337
+ contact: z.ZodOptional<z.ZodEmail>;
338
+ }, z.core.$strict>>;
339
+ /** Blueprint discovery. Defaults to no custom UIs declared. */
340
+ blueprints: z.ZodDefault<z.ZodObject<{
341
+ /** Glob patterns relative to the `ggui.json` directory. Each match
342
+ * should resolve to a `ggui.ui.json` file. */
343
+ include: z.ZodDefault<z.ZodArray<z.ZodString>>;
344
+ }, z.core.$strict>>;
345
+ /** Primitive discovery. Defaults to the shipped
346
+ * `@ggui-ai/design/primitives` package + no local primitives. */
347
+ primitives: z.ZodDefault<z.ZodObject<{
348
+ packages: z.ZodDefault<z.ZodArray<z.ZodString>>;
349
+ local: z.ZodDefault<z.ZodArray<z.ZodString>>;
350
+ }, z.core.$strict>>;
351
+ /**
352
+ * Theme selection. Three accepted shapes:
353
+ *
354
+ * - **Shorthand string** — `theme: "claudic"`. Picks a preset from
355
+ * the `@ggui-ai/design` registry. Default mode is `'light'`.
356
+ * - **Preset object** — `theme: { preset: "claudic", mode: "dark",
357
+ * overrides: { "color.primary.500": "#cc785c" } }`. Picks a
358
+ * registered preset, optional explicit mode, optional flat
359
+ * dot-path token overrides applied on top of the preset's
360
+ * tokens before CSS emission.
361
+ * - **File object** — `theme: { file: "./theme.json", mode: "dark" }`.
362
+ * Loads tokens from a project-relative DTCG JSON file. The
363
+ * `mode` is metadata only — the file's tokens are the resolved
364
+ * theme; mode propagates to consumers that vary based on it
365
+ * (e.g. `color-scheme: dark` injection).
366
+ *
367
+ * Absent (`theme: undefined`) means use the shipped default tokens
368
+ * from `@ggui-ai/design` (currently `lightTheme`).
369
+ */
370
+ theme: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
371
+ preset: z.ZodString;
372
+ mode: z.ZodOptional<z.ZodEnum<{
373
+ light: "light";
374
+ dark: "dark";
375
+ }>>;
376
+ overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
377
+ }, z.core.$strict>, z.ZodObject<{
378
+ file: z.ZodString;
379
+ mode: z.ZodOptional<z.ZodEnum<{
380
+ light: "light";
381
+ dark: "dark";
382
+ }>>;
383
+ }, z.core.$strict>]>>;
384
+ /** Agent-runtime config for `ggui serve`. Absent means the
385
+ * command boots MCP-only (no agent loop attached). */
386
+ agent: z.ZodOptional<z.ZodObject<{
387
+ /** Path to the agent's entry file, relative to the ggui.json
388
+ * directory. Supported extensions: .js, .mjs, .cjs, .ts, .tsx,
389
+ * .mts. Validation of extension happens at `ggui serve` time —
390
+ * the schema stays permissive so malformed entries surface with
391
+ * the CLI's error message (which can list supported extensions +
392
+ * remediation), not a zod issue trace. */
393
+ entry: z.ZodString;
394
+ }, z.core.$strict>>;
395
+ /** Explicit storage adapter declarations. Absent means every
396
+ * persistence surface stays in-memory (the zero-config OSS
397
+ * default). Present means the operator has opted in per surface
398
+ * — no surface silently creates a file on disk. See
399
+ * {@link StorageConfig}. */
400
+ storage: z.ZodOptional<z.ZodObject<{
401
+ /** Session persistence (events + stack + identity). Absent =
402
+ * in-memory (sessions reset on restart). */
403
+ sessions: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
404
+ driver: z.ZodLiteral<"memory">;
405
+ }, z.core.$strict>, z.ZodObject<{
406
+ driver: z.ZodLiteral<"sqlite">;
407
+ /** Filesystem path to the SQLite database file. Relative paths
408
+ * resolve from the ggui.json directory at adapter-instantiation
409
+ * time. Empty strings are rejected at parse. */
410
+ path: z.ZodString;
411
+ }, z.core.$strict>], "driver">>;
412
+ /** Vector index persistence (RAG, blueprint embeddings). Absent =
413
+ * in-memory (index rebuilds on restart). */
414
+ vectors: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
415
+ driver: z.ZodLiteral<"memory">;
416
+ }, z.core.$strict>, z.ZodObject<{
417
+ driver: z.ZodLiteral<"sqlite">;
418
+ /** Filesystem path to the SQLite database file. Relative paths
419
+ * resolve from the ggui.json directory at adapter-instantiation
420
+ * time. Empty strings are rejected at parse. */
421
+ path: z.ZodString;
422
+ }, z.core.$strict>], "driver">>;
423
+ /** Persistent-chat thread + message persistence. Absent = in-memory
424
+ * (threads vanish on restart — correct for dev, unsafe for any
425
+ * deployment Portal's self-hosted flow talks to). Pair with
426
+ * `driver: 'sqlite'` + a `path` for durable local storage; the
427
+ * `@ggui-ai/mcp-server-core/sqlite#SqliteThreadStore` reference
428
+ * impl consumes the same file-per-surface layout the sessions/
429
+ * vectors drivers already use. */
430
+ threads: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
431
+ driver: z.ZodLiteral<"memory">;
432
+ }, z.core.$strict>, z.ZodObject<{
433
+ driver: z.ZodLiteral<"sqlite">;
434
+ /** Filesystem path to the SQLite database file. Relative paths
435
+ * resolve from the ggui.json directory at adapter-instantiation
436
+ * time. Empty strings are rejected at parse. */
437
+ path: z.ZodString;
438
+ }, z.core.$strict>], "driver">>;
439
+ }, z.core.$strict>>;
440
+ /**
441
+ * Default plugin-registry URL for this app.
442
+ *
443
+ * When the user runs `ggui install <scope/name@version>` or `ggui
444
+ * publish` from this project, the CLI resolves the target registry
445
+ * via a three-layer chain (highest priority wins):
446
+ *
447
+ * 1. Explicit `--registry=<url>` flag passed to the CLI.
448
+ * 2. `GGUI_REGISTRY` environment variable.
449
+ * 3. This `registry` field in `ggui.json`.
450
+ * 4. (none → error) The CLI ships with NO hard-coded default;
451
+ * operators MUST pick a registry per app.
452
+ *
453
+ * Mirrors the npm `--registry` / `npm_config_registry` / `.npmrc`
454
+ * resolution pattern but anchored on `ggui.json` for the project-
455
+ * local layer (instead of a dotfile) — the same file that holds
456
+ * `app.gadgets` is the natural place to declare which
457
+ * marketplace those libraries come from.
458
+ *
459
+ * Validated as a URL at schema-parse time; the CLI does not
460
+ * second-guess scheme / host beyond URL-shape (HTTPS recommendation
461
+ * is enforced at install-time, not here, so dev fixtures pointing
462
+ * at `http://localhost:<port>` parse cleanly).
463
+ *
464
+ * Absent = no project-local default; the CLI falls through to env
465
+ * var or flag, and errors if neither is set.
466
+ */
467
+ registry: z.ZodOptional<z.ZodURL>;
468
+ /**
469
+ * Local MCP tool mounts — the operator-facing seam for declaring
470
+ * additional tool surfaces that aggregate onto `/mcp` alongside
471
+ * ggui-native tools (`ggui_push`, etc.). Each entry is a module
472
+ * specifier:
473
+ *
474
+ * - Relative paths (`./path/to/mount.js`, `../local/mcp.mjs`)
475
+ * resolve against the directory containing `ggui.json`. Must
476
+ * include the file extension — we do not guess `.js` vs
477
+ * `.mjs`. File must exist.
478
+ * - Bare npm specifiers (`@my-org/mcp-mount`, `some-pkg/entry`)
479
+ * resolve through Node's module resolver anchored at the
480
+ * project root.
481
+ *
482
+ * Each resolved module must export a `createGguiMcpMount` function
483
+ * (or a default export) returning `{ name: string; handlers:
484
+ * SharedHandler[] }` — i.e., an `McpServerMount` from
485
+ * `@ggui-ai/mcp-server`. The factory owns its own state (backing
486
+ * store, seed, etc.). Zero-argument today; arguments are a future
487
+ * additive (widen the entry to `string | { module, options? }`).
488
+ *
489
+ * Default: `[]` (no mounts). Collisions between mount tool names
490
+ * and ggui-native tool names (or between two mounts) are rejected
491
+ * at `createGguiServer` composition time, not silently — see
492
+ * `packages/mcp-server/src/mcp-mounts.ts::composeHandlersWithMounts`. */
493
+ mcpMounts: z.ZodDefault<z.ZodArray<z.ZodString>>;
494
+ }, z.core.$strict>;
495
+ /** Static TypeScript type derived from the v1 schema. */
496
+ export type GguiJsonV1 = z.infer<typeof GguiJsonV1>;
497
+ /**
498
+ * Canonical filename — always at the project root, always this
499
+ * name. Exported so tooling uses the constant instead of
500
+ * hard-coding the string.
501
+ */
502
+ export declare const GGUI_JSON_FILENAME = "ggui.json";
503
+ /**
504
+ * Parse a raw JSON value into a validated {@link GguiJsonV1}.
505
+ * Throws a `ZodError` with human-readable issues on invalid input.
506
+ *
507
+ * Accepts any `unknown` — callers are expected to have already
508
+ * decoded the JSON (`JSON.parse(source)`). Applies defaults for
509
+ * absent optional fields.
510
+ */
511
+ export declare function parseGguiJson(raw: unknown): GguiJsonV1;
512
+ /**
513
+ * Safe-parse variant — returns a discriminated `z.safeParse` result
514
+ * (`{ success: true, data }` vs `{ success: false, error }`). Prefer
515
+ * this inside CLI tooling where you want to render the issue list
516
+ * without try/catch.
517
+ */
518
+ export declare function safeParseGguiJson(raw: unknown): ReturnType<typeof GguiJsonV1.safeParse>;
519
+ export {};
520
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyGxB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,cAAc;IAClB;sDACkD;;IAElD;8CAC0C;;IAI1C;;uDAEmD;;IAEnD;;;8CAG0C;;kBAI1C,CAAC;AAEH,gDAAgD;AAChD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AA+H5D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;oBAI5B,CAAC;AAqEH;;;;;GAKG;AACH,QAAA,MAAM,oBAAoB;;;;IAZxB;;oDAEgD;;8BAahD,CAAC;AAEH,QAAA,MAAM,aAAa;IACjB;gDAC4C;;;;;QAnB5C;;wDAEgD;;;IAmBhD;gDAC4C;;;;;QAtB5C;;wDAEgD;;;IAsBhD;;;;;;sCAMkC;;;;;QA9BlC;;wDAEgD;;;kBA8BhD,CAAC;AAEH;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU;IACrB;uEACmE;;IAOnE,iDAAiD;;IAKjD,oBAAoB;;;;QA9XpB;;;;;;;;;;;;;;;WAeG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAIH;;;;;;;;;;;;;;;;;WAiBG;;QAEH;;;;;;;;WAQG;;;;;;IAqVH;;;kDAG8C;;QA/T9C;0DACkD;;QAElD;kDAC0C;;QAI1C;;2DAEmD;;QAEnD;;;kDAG0C;;;IAqT1C,+DAA+D;;QAhS/D;sDAC8C;;;IAoS9C;qEACiE;;;;;IAQjE;;;;;;;;;;;;;;;;;;OAkBG;;;;;;;;;;;;;;;IAKH;0DACsD;;QAhRtD;;;;;kDAK0C;;;IAgR1C;;;;gCAI4B;;QA5H5B;oDAC4C;;;;;YAnB5C;;4DAEgD;;;QAmBhD;oDAC4C;;;;;YAtB5C;;4DAEgD;;;QAsBhD;;;;;;0CAMkC;;;;;YA9BlC;;4DAEgD;;;;IAiJhD;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;;IAQH;;;;;;;;;;;;;;;;;;;;;;;;6EAwByE;;kBASzE,CAAC;AAEH,yDAAyD;AACzD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAE9C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,UAAU,CAAC,SAAS,CAAC,CAEzC"}