@ggui-ai/gadgets 0.2.0-alpha.4 → 0.3.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/index.d.mts +37 -29
- package/dist/index.d.ts +37 -29
- package/dist/index.js +3 -6
- package/dist/index.mjs +3 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Why
|
|
6
6
|
|
|
7
|
-
LLM-generated component code needs a stable, narrow API for the small set of browser capabilities that interactive UIs reach for: geolocation, clipboard read/write, notifications, file pickers, microphone, camera. Each capability has the same lifecycle shape —
|
|
7
|
+
LLM-generated component code needs a stable, narrow API for the small set of browser capabilities that interactive UIs reach for: geolocation, clipboard read/write, notifications, file pickers, microphone, camera. Each capability has the same lifecycle shape — idle → prompting → active → completed (or denied / error) — and the same permission-prompt UX. Encoding that shape once, in a typed React hook, keeps the generator's output:
|
|
8
8
|
|
|
9
9
|
- predictable across providers and prompts,
|
|
10
10
|
- testable by code-property assertions on the generated source (not just the rendered DOM),
|
|
@@ -22,7 +22,7 @@ Peer-dep: `react` ^18 || ^19.
|
|
|
22
22
|
|
|
23
23
|
## v1 stdlib catalog
|
|
24
24
|
|
|
25
|
-
Seven hooks ship in v1, all with a shared `{ status, error,
|
|
25
|
+
Seven hooks ship in v1, all with a shared `{ value, status, error?, start, stop? }` shape:
|
|
26
26
|
|
|
27
27
|
| Hook | Permission | Description |
|
|
28
28
|
| ------------------- | ----------------- | ------------------------------------------------------------ |
|
|
@@ -34,7 +34,7 @@ Seven hooks ship in v1, all with a shared `{ status, error, value | data | call
|
|
|
34
34
|
| `useMicrophone` | `microphone` | Stream access to the user's microphone via `getUserMedia`. |
|
|
35
35
|
| `useCamera` | `camera` | Stream access to the user's camera via `getUserMedia`. |
|
|
36
36
|
|
|
37
|
-
The same list is exported from `@ggui-ai/protocol` as `STDLIB_GADGETS` and
|
|
37
|
+
The same list is exported from `@ggui-ai/protocol` as `STDLIB_GADGETS` and forms the structural floor of every app's `ggui_list_gadgets` catalog — operator-declared packages (`ggui.json#app.gadgets`) layer on top, winning on a package-name collision.
|
|
38
38
|
|
|
39
39
|
## How a contract uses these hooks
|
|
40
40
|
|
|
@@ -59,8 +59,8 @@ export const photoCaptureContract = defineContract({
|
|
|
59
59
|
// `gadgets` is package-keyed: `Record<package, Record<exportName,
|
|
60
60
|
// { description?, usage? }>>`. The wire carries identity only —
|
|
61
61
|
// `version`, transport fields, and per-export registry metadata
|
|
62
|
-
// (`permission`, `example`, `gotchas
|
|
63
|
-
//
|
|
62
|
+
// (`permission`, `example`, `gotchas`) are NOT on the wire; the
|
|
63
|
+
// server resolves them from `App.gadgets` at render time.
|
|
64
64
|
gadgets: {
|
|
65
65
|
"@ggui-ai/gadgets": {
|
|
66
66
|
useCamera: {
|
package/dist/index.d.mts
CHANGED
|
@@ -10,11 +10,17 @@ export { GadgetError, GadgetHook, GadgetStatus } from '@ggui-ai/protocol';
|
|
|
10
10
|
* {@link GadgetHook}. The factory:
|
|
11
11
|
*
|
|
12
12
|
* 1. Strictly validates the spec at call time via
|
|
13
|
-
* `strictGadgetDescriptorSchema` —
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* `strictGadgetDescriptorSchema` — `package` (npm name) and a
|
|
14
|
+
* pin-only semver `version` are REQUIRED on every descriptor,
|
|
15
|
+
* teaching text (`description` / `usage` / `example`) is
|
|
16
|
+
* REQUIRED and non-empty, URL fields (`bundleUrl` / `styleUrl` /
|
|
17
|
+
* `typesUrl`) must be full URLs — plus a non-function `hookImpl`
|
|
18
|
+
* check the schema can't see. Throws
|
|
19
|
+
* {@link WrapperConformanceError} with field-level paths on any
|
|
20
|
+
* violation. (`typesUrl` is not required HERE — at author time
|
|
21
|
+
* the build hasn't emitted a `.d.ts` yet — but registration via
|
|
22
|
+
* `registeredGadgetDescriptorSchema` requires it for every
|
|
23
|
+
* non-stdlib package.)
|
|
18
24
|
* 2. Returns the React hook function as the primary export, with
|
|
19
25
|
* the serializable {@link GadgetDescriptor} descriptor attached
|
|
20
26
|
* as `.descriptor`. Single export, dual purpose:
|
|
@@ -26,7 +32,8 @@ export { GadgetError, GadgetHook, GadgetStatus } from '@ggui-ai/protocol';
|
|
|
26
32
|
* usage: '...',
|
|
27
33
|
* example: { ... },
|
|
28
34
|
* package: '@my-org/ggui-leaflet',
|
|
29
|
-
*
|
|
35
|
+
* version: '0.1.0',
|
|
36
|
+
* styleUrl: 'https://cdn.example.com/ggui-leaflet/leaflet.css',
|
|
30
37
|
* hookImpl: (options) => { …real React hook… },
|
|
31
38
|
* });
|
|
32
39
|
*
|
|
@@ -56,8 +63,8 @@ export { GadgetError, GadgetHook, GadgetStatus } from '@ggui-ai/protocol';
|
|
|
56
63
|
* Author input to {@link createGguiGadget}. A `createGguiGadget` call
|
|
57
64
|
* builds a gadget PACKAGE that exposes exactly one HOOK export — so
|
|
58
65
|
* the spec keeps the per-export teaching fields flat (`hook`,
|
|
59
|
-
* `description`, `usage`, `example`, `gotchas`, `permission
|
|
60
|
-
*
|
|
66
|
+
* `description`, `usage`, `example`, `gotchas`, `permission`)
|
|
67
|
+
* alongside the package identity + transport fields
|
|
61
68
|
* (`package`, `version`, `bundleUrl`, …) and a `hookImpl` runtime
|
|
62
69
|
* function. The factory assembles these into a
|
|
63
70
|
* {@link GadgetDescriptor} of the package+exports shape.
|
|
@@ -190,8 +197,6 @@ interface GadgetExportTeaching {
|
|
|
190
197
|
readonly gotchas?: string;
|
|
191
198
|
/** Optional Web-Permissions identifier the export gates on. */
|
|
192
199
|
readonly permission?: string;
|
|
193
|
-
/** Whether the UI MUST mount this export. Default `false`. */
|
|
194
|
-
readonly required?: boolean;
|
|
195
200
|
}
|
|
196
201
|
/** A hook export declaration — `use`-prefixed name + its impl. */
|
|
197
202
|
interface GadgetHookExportSpec extends GadgetExportTeaching {
|
|
@@ -256,7 +261,7 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
256
261
|
* gadget catalog. The wire-side `DataContract.clientCapabilities.gadgets`
|
|
257
262
|
* is intentionally narrow — it is package-keyed and carries identity
|
|
258
263
|
* only (`(package, export name)`, no `version`, no transport
|
|
259
|
-
* metadata), so
|
|
264
|
+
* metadata), so render-time resolution looks up the matching
|
|
260
265
|
* {@link GadgetDescriptor} descriptor by npm package name. This module
|
|
261
266
|
* declares the pluggable "where do descriptors come from?" port + ships
|
|
262
267
|
* two batteries-included implementations:
|
|
@@ -267,8 +272,8 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
267
272
|
*
|
|
268
273
|
* - {@link CachingGadgetCatalog} — decorator over any other adapter
|
|
269
274
|
* with per-appId TTL caching + single-flight deduplication. Right
|
|
270
|
-
* for production
|
|
271
|
-
* a registry service and re-fetching on every
|
|
275
|
+
* for production paths where descriptors live in a database /
|
|
276
|
+
* a registry service and re-fetching on every render would burn
|
|
272
277
|
* network round-trips. Caches are scoped per-appId so two apps
|
|
273
278
|
* never see each other's catalogs.
|
|
274
279
|
*
|
|
@@ -277,18 +282,18 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
277
282
|
* - One method: `list(appId)`. Single batch read — never an N+1
|
|
278
283
|
* "fetch descriptor for one package at a time" pattern. The
|
|
279
284
|
* resolution caller indexes the returned array by `package`
|
|
280
|
-
* itself. Single network call per
|
|
285
|
+
* itself. Single network call per render (with cache, often zero).
|
|
281
286
|
*
|
|
282
287
|
* - Return type is `readonly GadgetDescriptor[]` — the same shape the
|
|
283
|
-
* wire
|
|
288
|
+
* wire render-time resolution + downstream consumers (boilerplate
|
|
284
289
|
* generator, CSP builder, Permissions-Policy deriver, system
|
|
285
290
|
* prompt builder) already speak.
|
|
286
291
|
*
|
|
287
292
|
* - Errors propagate. Adapters MUST throw on retrieval failure
|
|
288
293
|
* rather than returning an empty array — silent "no gadgets"
|
|
289
|
-
* would let
|
|
294
|
+
* would let renders through with broken gadget refs and surface
|
|
290
295
|
* as render-time hook-resolution failures. The caller's job is
|
|
291
|
-
* to decide whether the
|
|
296
|
+
* to decide whether the render fails (gate fires) or proceeds
|
|
292
297
|
* ungated.
|
|
293
298
|
*
|
|
294
299
|
* ## Deployment-specific adapters
|
|
@@ -303,9 +308,9 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
303
308
|
/**
|
|
304
309
|
* Per-deployment source of registered gadget descriptors.
|
|
305
310
|
*
|
|
306
|
-
* Named parties: caller (
|
|
307
|
-
* (deployment-specific descriptor backing store, e.g., JSON,
|
|
308
|
-
* in-memory).
|
|
311
|
+
* Named parties: caller (render-time resolution / dev tools) ↔ adapter
|
|
312
|
+
* (deployment-specific descriptor backing store, e.g., JSON, a
|
|
313
|
+
* database, in-memory).
|
|
309
314
|
*
|
|
310
315
|
* Obligations:
|
|
311
316
|
* - `list(appId)` MUST return the full set of descriptors registered
|
|
@@ -315,7 +320,7 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
315
320
|
* returning `[]` is forbidden (it would mask broken catalogs).
|
|
316
321
|
*
|
|
317
322
|
* Failure mode: thrown error propagates to caller. Caller decides
|
|
318
|
-
* whether to fail the
|
|
323
|
+
* whether to fail the render (strict) or fall back to a default set
|
|
319
324
|
* (lenient).
|
|
320
325
|
*
|
|
321
326
|
* Observable violation: caller observes a thrown error or a
|
|
@@ -349,8 +354,8 @@ declare class InMemoryGadgetCatalog implements GadgetCatalogAdapter {
|
|
|
349
354
|
/**
|
|
350
355
|
* Decorator adapter — wraps any {@link GadgetCatalogAdapter} with
|
|
351
356
|
* per-appId TTL caching + single-flight deduplication. Right for
|
|
352
|
-
* production paths where the inner adapter hits
|
|
353
|
-
* service and per-
|
|
357
|
+
* production paths where the inner adapter hits a database / a
|
|
358
|
+
* registry service and per-render fetches would dominate latency.
|
|
354
359
|
*
|
|
355
360
|
* Concurrent `list(appId)` calls during a cache miss share ONE
|
|
356
361
|
* inflight Promise — no thundering herd against the inner adapter.
|
|
@@ -424,23 +429,23 @@ declare class CachingGadgetCatalog implements GadgetCatalogAdapter {
|
|
|
424
429
|
* without leaking the values themselves.
|
|
425
430
|
* - Pass `{ optional: true }` to get `undefined` for a missing key
|
|
426
431
|
* instead of throwing. Use when the wrapper has a sensible
|
|
427
|
-
* fallback (e.g., a default origin); the
|
|
432
|
+
* fallback (e.g., a default origin); the render gate enforces that
|
|
428
433
|
* declared `requires` keys are present, so the typical wrapper
|
|
429
434
|
* path uses the throwing default.
|
|
430
435
|
* - Empty-string values are returned verbatim (the operator may
|
|
431
436
|
* have intentionally configured a key with no value).
|
|
432
437
|
*
|
|
433
|
-
* The
|
|
438
|
+
* The render gate (`assertPublicEnvSatisfied`) verifies the
|
|
434
439
|
* `App.publicEnv` satisfies every declared wrapper's `requires` BEFORE
|
|
435
440
|
* the iframe boots. So in well-configured deployments, the only
|
|
436
441
|
* `getPublicEnv` throws are gadget authoring bugs (typoed key, key
|
|
437
|
-
* not declared in `requires`). In production, the
|
|
442
|
+
* not declared in `requires`). In production, the render gate catches
|
|
438
443
|
* the misconfiguration upstream.
|
|
439
444
|
*/
|
|
440
445
|
interface GetPublicEnvOptions {
|
|
441
446
|
/**
|
|
442
447
|
* When true, returns `undefined` for a missing key instead of
|
|
443
|
-
* throwing. Use sparingly — the
|
|
448
|
+
* throwing. Use sparingly — the render gate enforces declared
|
|
444
449
|
* `requires`, so a missing key usually indicates a wrapper bug
|
|
445
450
|
* (key not in `requires` array). The throwing default is the
|
|
446
451
|
* right call for keys that ARE declared in `requires`.
|
|
@@ -511,7 +516,8 @@ declare const useGeolocation: GadgetHook<GeolocationCoords, GeolocationOptions>;
|
|
|
511
516
|
* the system clipboard via `navigator.clipboard.writeText`. Satisfies
|
|
512
517
|
* `GadgetHook<string, ClipboardWriteOptions>`.
|
|
513
518
|
*
|
|
514
|
-
* One-shot semantics:
|
|
519
|
+
* One-shot semantics: pass `{text}` at hook-call time and call
|
|
520
|
+
* `start()` to write; status moves
|
|
515
521
|
* `idle → prompting → completed` on success or `idle → prompting →
|
|
516
522
|
* denied/error` on failure. The hook's `value` carries the most
|
|
517
523
|
* recently written text so component code can confirm what landed
|
|
@@ -523,7 +529,9 @@ declare const useGeolocation: GadgetHook<GeolocationCoords, GeolocationOptions>;
|
|
|
523
529
|
*/
|
|
524
530
|
|
|
525
531
|
interface ClipboardWriteOptions {
|
|
526
|
-
/** Text to write.
|
|
532
|
+
/** Text to write. Supplied at hook-call time; read when `start()`
|
|
533
|
+
* fires, so component code re-renders the hook call with the
|
|
534
|
+
* latest text rather than passing arguments to `start()`. */
|
|
527
535
|
readonly text: string;
|
|
528
536
|
}
|
|
529
537
|
declare const useClipboardWrite: GadgetHook<string, ClipboardWriteOptions>;
|
package/dist/index.d.ts
CHANGED
|
@@ -10,11 +10,17 @@ export { GadgetError, GadgetHook, GadgetStatus } from '@ggui-ai/protocol';
|
|
|
10
10
|
* {@link GadgetHook}. The factory:
|
|
11
11
|
*
|
|
12
12
|
* 1. Strictly validates the spec at call time via
|
|
13
|
-
* `strictGadgetDescriptorSchema` —
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* `strictGadgetDescriptorSchema` — `package` (npm name) and a
|
|
14
|
+
* pin-only semver `version` are REQUIRED on every descriptor,
|
|
15
|
+
* teaching text (`description` / `usage` / `example`) is
|
|
16
|
+
* REQUIRED and non-empty, URL fields (`bundleUrl` / `styleUrl` /
|
|
17
|
+
* `typesUrl`) must be full URLs — plus a non-function `hookImpl`
|
|
18
|
+
* check the schema can't see. Throws
|
|
19
|
+
* {@link WrapperConformanceError} with field-level paths on any
|
|
20
|
+
* violation. (`typesUrl` is not required HERE — at author time
|
|
21
|
+
* the build hasn't emitted a `.d.ts` yet — but registration via
|
|
22
|
+
* `registeredGadgetDescriptorSchema` requires it for every
|
|
23
|
+
* non-stdlib package.)
|
|
18
24
|
* 2. Returns the React hook function as the primary export, with
|
|
19
25
|
* the serializable {@link GadgetDescriptor} descriptor attached
|
|
20
26
|
* as `.descriptor`. Single export, dual purpose:
|
|
@@ -26,7 +32,8 @@ export { GadgetError, GadgetHook, GadgetStatus } from '@ggui-ai/protocol';
|
|
|
26
32
|
* usage: '...',
|
|
27
33
|
* example: { ... },
|
|
28
34
|
* package: '@my-org/ggui-leaflet',
|
|
29
|
-
*
|
|
35
|
+
* version: '0.1.0',
|
|
36
|
+
* styleUrl: 'https://cdn.example.com/ggui-leaflet/leaflet.css',
|
|
30
37
|
* hookImpl: (options) => { …real React hook… },
|
|
31
38
|
* });
|
|
32
39
|
*
|
|
@@ -56,8 +63,8 @@ export { GadgetError, GadgetHook, GadgetStatus } from '@ggui-ai/protocol';
|
|
|
56
63
|
* Author input to {@link createGguiGadget}. A `createGguiGadget` call
|
|
57
64
|
* builds a gadget PACKAGE that exposes exactly one HOOK export — so
|
|
58
65
|
* the spec keeps the per-export teaching fields flat (`hook`,
|
|
59
|
-
* `description`, `usage`, `example`, `gotchas`, `permission
|
|
60
|
-
*
|
|
66
|
+
* `description`, `usage`, `example`, `gotchas`, `permission`)
|
|
67
|
+
* alongside the package identity + transport fields
|
|
61
68
|
* (`package`, `version`, `bundleUrl`, …) and a `hookImpl` runtime
|
|
62
69
|
* function. The factory assembles these into a
|
|
63
70
|
* {@link GadgetDescriptor} of the package+exports shape.
|
|
@@ -190,8 +197,6 @@ interface GadgetExportTeaching {
|
|
|
190
197
|
readonly gotchas?: string;
|
|
191
198
|
/** Optional Web-Permissions identifier the export gates on. */
|
|
192
199
|
readonly permission?: string;
|
|
193
|
-
/** Whether the UI MUST mount this export. Default `false`. */
|
|
194
|
-
readonly required?: boolean;
|
|
195
200
|
}
|
|
196
201
|
/** A hook export declaration — `use`-prefixed name + its impl. */
|
|
197
202
|
interface GadgetHookExportSpec extends GadgetExportTeaching {
|
|
@@ -256,7 +261,7 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
256
261
|
* gadget catalog. The wire-side `DataContract.clientCapabilities.gadgets`
|
|
257
262
|
* is intentionally narrow — it is package-keyed and carries identity
|
|
258
263
|
* only (`(package, export name)`, no `version`, no transport
|
|
259
|
-
* metadata), so
|
|
264
|
+
* metadata), so render-time resolution looks up the matching
|
|
260
265
|
* {@link GadgetDescriptor} descriptor by npm package name. This module
|
|
261
266
|
* declares the pluggable "where do descriptors come from?" port + ships
|
|
262
267
|
* two batteries-included implementations:
|
|
@@ -267,8 +272,8 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
267
272
|
*
|
|
268
273
|
* - {@link CachingGadgetCatalog} — decorator over any other adapter
|
|
269
274
|
* with per-appId TTL caching + single-flight deduplication. Right
|
|
270
|
-
* for production
|
|
271
|
-
* a registry service and re-fetching on every
|
|
275
|
+
* for production paths where descriptors live in a database /
|
|
276
|
+
* a registry service and re-fetching on every render would burn
|
|
272
277
|
* network round-trips. Caches are scoped per-appId so two apps
|
|
273
278
|
* never see each other's catalogs.
|
|
274
279
|
*
|
|
@@ -277,18 +282,18 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
277
282
|
* - One method: `list(appId)`. Single batch read — never an N+1
|
|
278
283
|
* "fetch descriptor for one package at a time" pattern. The
|
|
279
284
|
* resolution caller indexes the returned array by `package`
|
|
280
|
-
* itself. Single network call per
|
|
285
|
+
* itself. Single network call per render (with cache, often zero).
|
|
281
286
|
*
|
|
282
287
|
* - Return type is `readonly GadgetDescriptor[]` — the same shape the
|
|
283
|
-
* wire
|
|
288
|
+
* wire render-time resolution + downstream consumers (boilerplate
|
|
284
289
|
* generator, CSP builder, Permissions-Policy deriver, system
|
|
285
290
|
* prompt builder) already speak.
|
|
286
291
|
*
|
|
287
292
|
* - Errors propagate. Adapters MUST throw on retrieval failure
|
|
288
293
|
* rather than returning an empty array — silent "no gadgets"
|
|
289
|
-
* would let
|
|
294
|
+
* would let renders through with broken gadget refs and surface
|
|
290
295
|
* as render-time hook-resolution failures. The caller's job is
|
|
291
|
-
* to decide whether the
|
|
296
|
+
* to decide whether the render fails (gate fires) or proceeds
|
|
292
297
|
* ungated.
|
|
293
298
|
*
|
|
294
299
|
* ## Deployment-specific adapters
|
|
@@ -303,9 +308,9 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
303
308
|
/**
|
|
304
309
|
* Per-deployment source of registered gadget descriptors.
|
|
305
310
|
*
|
|
306
|
-
* Named parties: caller (
|
|
307
|
-
* (deployment-specific descriptor backing store, e.g., JSON,
|
|
308
|
-
* in-memory).
|
|
311
|
+
* Named parties: caller (render-time resolution / dev tools) ↔ adapter
|
|
312
|
+
* (deployment-specific descriptor backing store, e.g., JSON, a
|
|
313
|
+
* database, in-memory).
|
|
309
314
|
*
|
|
310
315
|
* Obligations:
|
|
311
316
|
* - `list(appId)` MUST return the full set of descriptors registered
|
|
@@ -315,7 +320,7 @@ declare function defineGadgetPackage(spec: GadgetPackageSpec): GadgetDescriptor;
|
|
|
315
320
|
* returning `[]` is forbidden (it would mask broken catalogs).
|
|
316
321
|
*
|
|
317
322
|
* Failure mode: thrown error propagates to caller. Caller decides
|
|
318
|
-
* whether to fail the
|
|
323
|
+
* whether to fail the render (strict) or fall back to a default set
|
|
319
324
|
* (lenient).
|
|
320
325
|
*
|
|
321
326
|
* Observable violation: caller observes a thrown error or a
|
|
@@ -349,8 +354,8 @@ declare class InMemoryGadgetCatalog implements GadgetCatalogAdapter {
|
|
|
349
354
|
/**
|
|
350
355
|
* Decorator adapter — wraps any {@link GadgetCatalogAdapter} with
|
|
351
356
|
* per-appId TTL caching + single-flight deduplication. Right for
|
|
352
|
-
* production paths where the inner adapter hits
|
|
353
|
-
* service and per-
|
|
357
|
+
* production paths where the inner adapter hits a database / a
|
|
358
|
+
* registry service and per-render fetches would dominate latency.
|
|
354
359
|
*
|
|
355
360
|
* Concurrent `list(appId)` calls during a cache miss share ONE
|
|
356
361
|
* inflight Promise — no thundering herd against the inner adapter.
|
|
@@ -424,23 +429,23 @@ declare class CachingGadgetCatalog implements GadgetCatalogAdapter {
|
|
|
424
429
|
* without leaking the values themselves.
|
|
425
430
|
* - Pass `{ optional: true }` to get `undefined` for a missing key
|
|
426
431
|
* instead of throwing. Use when the wrapper has a sensible
|
|
427
|
-
* fallback (e.g., a default origin); the
|
|
432
|
+
* fallback (e.g., a default origin); the render gate enforces that
|
|
428
433
|
* declared `requires` keys are present, so the typical wrapper
|
|
429
434
|
* path uses the throwing default.
|
|
430
435
|
* - Empty-string values are returned verbatim (the operator may
|
|
431
436
|
* have intentionally configured a key with no value).
|
|
432
437
|
*
|
|
433
|
-
* The
|
|
438
|
+
* The render gate (`assertPublicEnvSatisfied`) verifies the
|
|
434
439
|
* `App.publicEnv` satisfies every declared wrapper's `requires` BEFORE
|
|
435
440
|
* the iframe boots. So in well-configured deployments, the only
|
|
436
441
|
* `getPublicEnv` throws are gadget authoring bugs (typoed key, key
|
|
437
|
-
* not declared in `requires`). In production, the
|
|
442
|
+
* not declared in `requires`). In production, the render gate catches
|
|
438
443
|
* the misconfiguration upstream.
|
|
439
444
|
*/
|
|
440
445
|
interface GetPublicEnvOptions {
|
|
441
446
|
/**
|
|
442
447
|
* When true, returns `undefined` for a missing key instead of
|
|
443
|
-
* throwing. Use sparingly — the
|
|
448
|
+
* throwing. Use sparingly — the render gate enforces declared
|
|
444
449
|
* `requires`, so a missing key usually indicates a wrapper bug
|
|
445
450
|
* (key not in `requires` array). The throwing default is the
|
|
446
451
|
* right call for keys that ARE declared in `requires`.
|
|
@@ -511,7 +516,8 @@ declare const useGeolocation: GadgetHook<GeolocationCoords, GeolocationOptions>;
|
|
|
511
516
|
* the system clipboard via `navigator.clipboard.writeText`. Satisfies
|
|
512
517
|
* `GadgetHook<string, ClipboardWriteOptions>`.
|
|
513
518
|
*
|
|
514
|
-
* One-shot semantics:
|
|
519
|
+
* One-shot semantics: pass `{text}` at hook-call time and call
|
|
520
|
+
* `start()` to write; status moves
|
|
515
521
|
* `idle → prompting → completed` on success or `idle → prompting →
|
|
516
522
|
* denied/error` on failure. The hook's `value` carries the most
|
|
517
523
|
* recently written text so component code can confirm what landed
|
|
@@ -523,7 +529,9 @@ declare const useGeolocation: GadgetHook<GeolocationCoords, GeolocationOptions>;
|
|
|
523
529
|
*/
|
|
524
530
|
|
|
525
531
|
interface ClipboardWriteOptions {
|
|
526
|
-
/** Text to write.
|
|
532
|
+
/** Text to write. Supplied at hook-call time; read when `start()`
|
|
533
|
+
* fires, so component code re-renders the hook call with the
|
|
534
|
+
* latest text rather than passing arguments to `start()`. */
|
|
527
535
|
readonly text: string;
|
|
528
536
|
}
|
|
529
537
|
declare const useClipboardWrite: GadgetHook<string, ClipboardWriteOptions>;
|
package/dist/index.js
CHANGED
|
@@ -59,7 +59,6 @@ function createGguiGadget(spec) {
|
|
|
59
59
|
example,
|
|
60
60
|
gotchas,
|
|
61
61
|
permission,
|
|
62
|
-
required,
|
|
63
62
|
...packageFields
|
|
64
63
|
} = spec;
|
|
65
64
|
const violations = [];
|
|
@@ -75,8 +74,7 @@ function createGguiGadget(spec) {
|
|
|
75
74
|
usage,
|
|
76
75
|
example,
|
|
77
76
|
...gotchas !== void 0 ? { gotchas } : {},
|
|
78
|
-
...permission !== void 0 ? { permission } : {}
|
|
79
|
-
...required !== void 0 ? { required } : {}
|
|
77
|
+
...permission !== void 0 ? { permission } : {}
|
|
80
78
|
};
|
|
81
79
|
const descriptorDraft = {
|
|
82
80
|
...packageFields,
|
|
@@ -131,8 +129,7 @@ function defineGadgetPackage(spec) {
|
|
|
131
129
|
usage: entry.usage,
|
|
132
130
|
example: entry.example,
|
|
133
131
|
...entry.gotchas !== void 0 ? { gotchas: entry.gotchas } : {},
|
|
134
|
-
...entry.permission !== void 0 ? { permission: entry.permission } : {}
|
|
135
|
-
...entry.required !== void 0 ? { required: entry.required } : {}
|
|
132
|
+
...entry.permission !== void 0 ? { permission: entry.permission } : {}
|
|
136
133
|
};
|
|
137
134
|
return "hook" in entry ? { hook: entry.hook, ...teaching } : { component: entry.component, ...teaching };
|
|
138
135
|
});
|
|
@@ -254,7 +251,7 @@ function getPublicEnv(key, opts, target = globalThis) {
|
|
|
254
251
|
if (opts?.optional) return void 0;
|
|
255
252
|
const available = Object.keys(env);
|
|
256
253
|
throw new Error(
|
|
257
|
-
`getPublicEnv('${key}'): not provided in App.publicEnv. Available: [${available.join(", ") || "(none)"}]. Operators set this on the App record; gadget authors declare the key in 'requires' so the
|
|
254
|
+
`getPublicEnv('${key}'): not provided in App.publicEnv. Available: [${available.join(", ") || "(none)"}]. Operators set this on the App record; gadget authors declare the key in 'requires' so the render gate verifies it before mount.`
|
|
258
255
|
);
|
|
259
256
|
}
|
|
260
257
|
|
package/dist/index.mjs
CHANGED
|
@@ -23,7 +23,6 @@ function createGguiGadget(spec) {
|
|
|
23
23
|
example,
|
|
24
24
|
gotchas,
|
|
25
25
|
permission,
|
|
26
|
-
required,
|
|
27
26
|
...packageFields
|
|
28
27
|
} = spec;
|
|
29
28
|
const violations = [];
|
|
@@ -39,8 +38,7 @@ function createGguiGadget(spec) {
|
|
|
39
38
|
usage,
|
|
40
39
|
example,
|
|
41
40
|
...gotchas !== void 0 ? { gotchas } : {},
|
|
42
|
-
...permission !== void 0 ? { permission } : {}
|
|
43
|
-
...required !== void 0 ? { required } : {}
|
|
41
|
+
...permission !== void 0 ? { permission } : {}
|
|
44
42
|
};
|
|
45
43
|
const descriptorDraft = {
|
|
46
44
|
...packageFields,
|
|
@@ -97,8 +95,7 @@ function defineGadgetPackage(spec) {
|
|
|
97
95
|
usage: entry.usage,
|
|
98
96
|
example: entry.example,
|
|
99
97
|
...entry.gotchas !== void 0 ? { gotchas: entry.gotchas } : {},
|
|
100
|
-
...entry.permission !== void 0 ? { permission: entry.permission } : {}
|
|
101
|
-
...entry.required !== void 0 ? { required: entry.required } : {}
|
|
98
|
+
...entry.permission !== void 0 ? { permission: entry.permission } : {}
|
|
102
99
|
};
|
|
103
100
|
return "hook" in entry ? { hook: entry.hook, ...teaching } : { component: entry.component, ...teaching };
|
|
104
101
|
});
|
|
@@ -220,7 +217,7 @@ function getPublicEnv(key, opts, target = globalThis) {
|
|
|
220
217
|
if (opts?.optional) return void 0;
|
|
221
218
|
const available = Object.keys(env);
|
|
222
219
|
throw new Error(
|
|
223
|
-
`getPublicEnv('${key}'): not provided in App.publicEnv. Available: [${available.join(", ") || "(none)"}]. Operators set this on the App record; gadget authors declare the key in 'requires' so the
|
|
220
|
+
`getPublicEnv('${key}'): not provided in App.publicEnv. Available: [${available.join(", ") || "(none)"}]. Operators set this on the App record; gadget authors declare the key in 'requires' so the render gate verifies it before mount.`
|
|
224
221
|
);
|
|
225
222
|
}
|
|
226
223
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/gadgets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-rc.0",
|
|
4
4
|
"description": "Browser-capability gadget hooks for ggui — declared via DataContract.clientCapabilities.gadgets, mounted by the UI generator's component code.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"vitest": "^2.0.0"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@ggui-ai/protocol": "0.
|
|
63
|
+
"@ggui-ai/protocol": "0.3.0-rc.0"
|
|
64
64
|
},
|
|
65
65
|
"engines": {
|
|
66
66
|
"node": ">=20.0.0"
|