@ggui-ai/cli 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 +38 -7
- package/dist/api-client.d.ts +42 -1
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +30 -2
- package/dist/auth-keys.d.ts +1 -1
- package/dist/auth-keys.d.ts.map +1 -1
- package/dist/auth-keys.js +22 -7
- package/dist/auth-store.d.ts +1 -1
- package/dist/auth-store.d.ts.map +1 -1
- package/dist/cli.js +112 -30
- package/dist/config-push.d.ts +79 -0
- package/dist/config-push.d.ts.map +1 -0
- package/dist/config-push.js +301 -0
- package/dist/create-app-command.d.ts +17 -0
- package/dist/create-app-command.d.ts.map +1 -0
- package/dist/create-app-command.js +58 -0
- package/dist/deploy-command.d.ts +67 -0
- package/dist/deploy-command.d.ts.map +1 -0
- package/dist/deploy-command.js +386 -0
- package/dist/dev-command.d.ts +5 -1
- package/dist/dev-command.d.ts.map +1 -1
- package/dist/dev-command.js +31 -1
- package/dist/export-pool-command.d.ts +25 -0
- package/dist/export-pool-command.d.ts.map +1 -0
- package/dist/export-pool-command.js +116 -0
- package/dist/filesystem-seed-pool-source.d.ts +13 -0
- package/dist/filesystem-seed-pool-source.d.ts.map +1 -0
- package/dist/filesystem-seed-pool-source.js +22 -0
- package/dist/generation-probe.d.ts +53 -7
- package/dist/generation-probe.d.ts.map +1 -1
- package/dist/generation-probe.js +37 -1
- package/dist/internal/artifact-install.d.ts +4 -2
- package/dist/internal/artifact-install.d.ts.map +1 -1
- package/dist/internal/artifact-install.js +11 -10
- package/dist/internal/artifact-publish.d.ts +34 -31
- package/dist/internal/artifact-publish.d.ts.map +1 -1
- package/dist/internal/artifact-publish.js +133 -241
- package/dist/internal/artifact-search.d.ts +2 -28
- package/dist/internal/artifact-search.d.ts.map +1 -1
- package/dist/internal/artifact-search.js +5 -4
- package/dist/internal/auth-strategy.d.ts +21 -31
- package/dist/internal/auth-strategy.d.ts.map +1 -1
- package/dist/internal/auth-strategy.js +15 -23
- package/dist/internal/register-author-key.d.ts +7 -1
- package/dist/internal/register-author-key.d.ts.map +1 -1
- package/dist/internal/register-author-key.js +56 -19
- package/dist/mcp-backend.d.ts +25 -25
- package/dist/mcp-backend.d.ts.map +1 -1
- package/dist/mcp-backend.js +65 -61
- package/dist/paths.d.ts +3 -3
- package/dist/paths.js +3 -3
- package/dist/persistent-secrets.js +1 -1
- package/dist/persistent-stores.d.ts +2 -2
- package/dist/persistent-stores.d.ts.map +1 -1
- package/dist/persistent-stores.js +5 -5
- package/dist/pool-artifact.d.ts +19 -0
- package/dist/pool-artifact.d.ts.map +1 -0
- package/dist/pool-artifact.js +59 -0
- package/dist/provider-key-command.d.ts +51 -0
- package/dist/provider-key-command.d.ts.map +1 -0
- package/dist/provider-key-command.js +222 -0
- package/dist/push-command.d.ts +47 -0
- package/dist/push-command.d.ts.map +1 -0
- package/dist/push-command.js +230 -0
- package/dist/serve-command.d.ts +23 -19
- package/dist/serve-command.d.ts.map +1 -1
- package/dist/serve-command.js +13 -26
- package/dist/theme-command.js +0 -2
- package/dist/tunnel-provider.d.ts +8 -7
- package/dist/tunnel-provider.d.ts.map +1 -1
- package/package.json +25 -21
- package/dist/internal/auth-cache.d.ts +0 -40
- package/dist/internal/auth-cache.d.ts.map +0 -1
- package/dist/internal/auth-cache.js +0 -133
- package/dist/persistent-short-code-index.d.ts +0 -14
- package/dist/persistent-short-code-index.d.ts.map +0 -1
- package/dist/persistent-short-code-index.js +0 -39
- package/dist/spawn-cloudflared.d.ts +0 -61
- package/dist/spawn-cloudflared.d.ts.map +0 -1
- package/dist/spawn-cloudflared.js +0 -167
package/dist/serve-command.js
CHANGED
|
@@ -26,6 +26,7 @@ export function parseServeFlags(args) {
|
|
|
26
26
|
publicDemo: false,
|
|
27
27
|
multiTenant: false,
|
|
28
28
|
oauth: false,
|
|
29
|
+
seedPools: [],
|
|
29
30
|
};
|
|
30
31
|
for (let i = 0; i < args.length; i++) {
|
|
31
32
|
const arg = args[i];
|
|
@@ -88,14 +89,6 @@ export function parseServeFlags(args) {
|
|
|
88
89
|
out.publicBaseUrl = v.replace(/\/+$/, '');
|
|
89
90
|
continue;
|
|
90
91
|
}
|
|
91
|
-
if (arg === '--public') {
|
|
92
|
-
out.publicAutoTunnel = true;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (arg === '--i-know-its-public') {
|
|
96
|
-
out.iKnowItsPublic = true;
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
92
|
if (arg === '--no-open') {
|
|
100
93
|
out.noOpen = true;
|
|
101
94
|
continue;
|
|
@@ -138,6 +131,13 @@ export function parseServeFlags(args) {
|
|
|
138
131
|
out.ephemeral = true;
|
|
139
132
|
continue;
|
|
140
133
|
}
|
|
134
|
+
if (arg === '--seed-pool') {
|
|
135
|
+
const value = args[++i];
|
|
136
|
+
if (value === undefined)
|
|
137
|
+
return { ...out, error: '--seed-pool requires a path' };
|
|
138
|
+
out.seedPools.push(value);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
141
|
if (arg === '--all') {
|
|
142
142
|
// §10.2a lock: --all is NOT a first-class flag. The default
|
|
143
143
|
// already runs everything. Reject with a pointer so users
|
|
@@ -171,22 +171,6 @@ export function parseServeFlags(args) {
|
|
|
171
171
|
'multi-tenant gate rejects. Drop the other flag and pair with real bearers.',
|
|
172
172
|
};
|
|
173
173
|
}
|
|
174
|
-
if (out.publicAutoTunnel && out.publicBaseUrl !== undefined) {
|
|
175
|
-
return {
|
|
176
|
-
...out,
|
|
177
|
-
error: '--public and --public-base-url are mutually exclusive. ' +
|
|
178
|
-
'--public auto-spawns a cloudflared quick-tunnel and sets the URL; ' +
|
|
179
|
-
'--public-base-url pins an explicit URL. Pick one.',
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
if (out.publicAutoTunnel && out.devAllowAll && !out.iKnowItsPublic) {
|
|
183
|
-
return {
|
|
184
|
-
...out,
|
|
185
|
-
error: '--public + --dev-allow-all exposes any-bearer auth to the open ' +
|
|
186
|
-
'internet via cloudflared. Add --i-know-its-public to acknowledge ' +
|
|
187
|
-
'this, or pair real bearers and drop --dev-allow-all.',
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
174
|
return out;
|
|
191
175
|
}
|
|
192
176
|
export function describeServeBanner(input) {
|
|
@@ -520,6 +504,9 @@ Options:
|
|
|
520
504
|
survive a server restart. Pass this flag to
|
|
521
505
|
keep restarts ephemeral (tests / CI / nuclear-
|
|
522
506
|
revoke). Override the dir via GGUI_PERSISTENT_DIR.
|
|
507
|
+
--seed-pool <dir> Load a read-only shared blueprint pool from a
|
|
508
|
+
directory artifact (repeatable). Blueprints in it
|
|
509
|
+
are reused by exact contract match, after your own.
|
|
523
510
|
--help, -h Show this help.
|
|
524
511
|
|
|
525
512
|
Agent runtime:
|
|
@@ -549,7 +536,7 @@ Persistent storage (default-on; opt-out via --ephemeral):
|
|
|
549
536
|
├── ws-token-secret.hex (HMAC, 0600)
|
|
550
537
|
├── render-signer-secret.hex (HMAC, 0600)
|
|
551
538
|
├── short-codes.sqlite (signed render-URL resolution)
|
|
552
|
-
├──
|
|
539
|
+
├── sessions.sqlite (GguiSessionStore — renders + event history)
|
|
553
540
|
├── vectors.sqlite (RAG corpus)
|
|
554
541
|
└── keys.json (paired bearers)
|
|
555
542
|
|
|
@@ -563,7 +550,7 @@ Persistent storage (default-on; opt-out via --ephemeral):
|
|
|
563
550
|
|
|
564
551
|
{
|
|
565
552
|
"storage": {
|
|
566
|
-
"renders": { "driver": "sqlite", "path": "./ggui-
|
|
553
|
+
"renders": { "driver": "sqlite", "path": "./ggui-sessions.sqlite" },
|
|
567
554
|
"vectors": { "driver": "sqlite", "path": "./ggui-vectors.sqlite" },
|
|
568
555
|
"threads": { "driver": "sqlite", "path": "./ggui-threads.sqlite" }
|
|
569
556
|
}
|
package/dist/theme-command.js
CHANGED
|
@@ -145,8 +145,6 @@ function describeValidTheme(absPath, theme) {
|
|
|
145
145
|
optional.push('accessibility');
|
|
146
146
|
if (theme.zIndex !== undefined)
|
|
147
147
|
optional.push('zIndex');
|
|
148
|
-
if (theme.canvas !== undefined)
|
|
149
|
-
optional.push('canvas');
|
|
150
148
|
lines.push(optional.length === 0
|
|
151
149
|
? ` optional blocks: none`
|
|
152
150
|
: ` optional blocks: ${optional.join(', ')}`);
|
|
@@ -183,12 +183,13 @@ export interface NullTunnelProviderOptions {
|
|
|
183
183
|
}
|
|
184
184
|
export declare function createNullTunnelProvider(options?: NullTunnelProviderOptions): TunnelProvider;
|
|
185
185
|
/**
|
|
186
|
-
* Contract a tunnel-provider module must satisfy for dynamic
|
|
187
|
-
* discovery.
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
186
|
+
* Contract a tunnel-provider plugin module must satisfy for dynamic
|
|
187
|
+
* discovery. Point `GGUI_TUNNEL_PROVIDER` at a module specifier; the
|
|
188
|
+
* module exports either a named `createTunnelProvider` factory or a
|
|
189
|
+
* default export (factory or provider instance) — both shapes are
|
|
190
|
+
* tried in that order. The factory takes no arguments today; if a
|
|
191
|
+
* future revision needs options (project identity, login snapshot)
|
|
192
|
+
* the contract version bumps with it.
|
|
192
193
|
*
|
|
193
194
|
* Kept as a module shape rather than a typed `require` because the
|
|
194
195
|
* target module path is controlled by the user's env, not by the
|
|
@@ -198,7 +199,7 @@ export declare function createNullTunnelProvider(options?: NullTunnelProviderOpt
|
|
|
198
199
|
export interface TunnelProviderModule {
|
|
199
200
|
/** Preferred shape. */
|
|
200
201
|
readonly createTunnelProvider?: () => TunnelProvider | Promise<TunnelProvider>;
|
|
201
|
-
/**
|
|
202
|
+
/** Alternate shape — default export returning the provider. */
|
|
202
203
|
readonly default?: TunnelProvider | (() => TunnelProvider | Promise<TunnelProvider>);
|
|
203
204
|
}
|
|
204
205
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunnel-provider.d.ts","sourceRoot":"","sources":["../src/tunnel-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG,wBAAwB,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,IAAI,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,yBAA8B,GACtC,cAAc,CAehB;AAED
|
|
1
|
+
{"version":3,"file":"tunnel-provider.d.ts","sourceRoot":"","sources":["../src/tunnel-provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-rc.0",
|
|
4
4
|
"description": "The `ggui` CLI — run the ggui protocol locally: dev server, self-hosted MCP server, and gadget / blueprint authoring. End-to-end OSS and self-hosted workflows; no account required.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ggui",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"types": "./dist/tunnel-provider.d.ts",
|
|
22
22
|
"import": "./dist/tunnel-provider.js",
|
|
23
23
|
"default": "./dist/tunnel-provider.js"
|
|
24
|
+
},
|
|
25
|
+
"./push": {
|
|
26
|
+
"types": "./dist/push-command.d.ts",
|
|
27
|
+
"import": "./dist/push-command.js",
|
|
28
|
+
"default": "./dist/push-command.js"
|
|
24
29
|
}
|
|
25
30
|
},
|
|
26
31
|
"files": [
|
|
@@ -28,32 +33,31 @@
|
|
|
28
33
|
"README.md"
|
|
29
34
|
],
|
|
30
35
|
"dependencies": {
|
|
31
|
-
"@aws-sdk/client-cognito-identity-provider": "^3.600.0",
|
|
32
36
|
"@huggingface/transformers": "^3.0.0",
|
|
33
37
|
"@noble/hashes": "^1.6.0",
|
|
34
38
|
"esbuild": "^0.25.12",
|
|
35
|
-
"
|
|
36
|
-
"@ggui-ai/
|
|
37
|
-
"@ggui-ai/
|
|
38
|
-
"@ggui-ai/
|
|
39
|
-
"@ggui-ai/gadget-signing": "0.
|
|
40
|
-
"@ggui-ai/
|
|
41
|
-
"@ggui-ai/
|
|
42
|
-
"@ggui-ai/mcp-server-
|
|
43
|
-
"@ggui-ai/
|
|
44
|
-
"@ggui-ai/mcp-server-
|
|
45
|
-
"@ggui-ai/
|
|
46
|
-
"@ggui-ai/
|
|
47
|
-
"@ggui-ai/
|
|
48
|
-
"@ggui-ai/
|
|
49
|
-
"@ggui-ai/
|
|
50
|
-
"@ggui-ai/
|
|
39
|
+
"zod": "^4.3.6",
|
|
40
|
+
"@ggui-ai/agent-runtime": "0.3.0-rc.0",
|
|
41
|
+
"@ggui-ai/dev-stack": "0.3.0-rc.0",
|
|
42
|
+
"@ggui-ai/design": "0.3.0-rc.0",
|
|
43
|
+
"@ggui-ai/gadget-signing": "0.3.0-rc.0",
|
|
44
|
+
"@ggui-ai/artifact-manifest": "0.3.0-rc.0",
|
|
45
|
+
"@ggui-ai/mcp-server": "0.3.0-rc.0",
|
|
46
|
+
"@ggui-ai/mcp-server-handlers": "0.3.0-rc.0",
|
|
47
|
+
"@ggui-ai/embedding-local": "0.3.0-rc.0",
|
|
48
|
+
"@ggui-ai/mcp-server-core": "0.3.0-rc.0",
|
|
49
|
+
"@ggui-ai/preview-a2ui": "0.3.0-rc.0",
|
|
50
|
+
"@ggui-ai/project-config": "0.3.0-rc.0",
|
|
51
|
+
"@ggui-ai/protocol": "0.3.0-rc.0",
|
|
52
|
+
"@ggui-ai/registry-core": "0.3.0-rc.0",
|
|
53
|
+
"@ggui-ai/iframe-runtime": "0.3.0-rc.0",
|
|
54
|
+
"@ggui-ai/ui-registry": "0.3.0-rc.0",
|
|
55
|
+
"@ggui-ai/ui-gen": "0.3.0-rc.0"
|
|
51
56
|
},
|
|
52
57
|
"devDependencies": {
|
|
53
58
|
"@types/node": "^24.0.0",
|
|
54
59
|
"typescript": "^5.0.0",
|
|
55
|
-
"vitest": "^3.0.0"
|
|
56
|
-
"zod": "^4.3.6"
|
|
60
|
+
"vitest": "^3.0.0"
|
|
57
61
|
},
|
|
58
62
|
"repository": {
|
|
59
63
|
"type": "git",
|
|
@@ -72,7 +76,7 @@
|
|
|
72
76
|
},
|
|
73
77
|
"author": "ggui contributors <hello@ggui.ai>",
|
|
74
78
|
"scripts": {
|
|
75
|
-
"build": "tsc -p tsconfig.build.json && chmod +x dist/cli.js",
|
|
79
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/cli.js",
|
|
76
80
|
"dev": "tsc --watch",
|
|
77
81
|
"typecheck": "tsc --noEmit",
|
|
78
82
|
"test": "vitest run --passWithNoTests",
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/** v1 on-disk shape. */
|
|
2
|
-
export interface RegistryTokenDocument {
|
|
3
|
-
readonly version: 1;
|
|
4
|
-
/** Full registry origin (e.g. `https://dev.registry.sandbox.ggui.ai`). */
|
|
5
|
-
readonly registry: string;
|
|
6
|
-
/** Cognito IdToken — sent as `Authorization: Bearer <idToken>`. */
|
|
7
|
-
readonly idToken: string;
|
|
8
|
-
/** Cognito AccessToken — surfaced separately for handlers that need it. */
|
|
9
|
-
readonly accessToken: string;
|
|
10
|
-
/** Cognito RefreshToken — used to mint fresh id/access tokens. */
|
|
11
|
-
readonly refreshToken: string;
|
|
12
|
-
/** Unix epoch SECONDS — past this, the id token is rejected by the registry. */
|
|
13
|
-
readonly expiresAt: number;
|
|
14
|
-
/** Username the tokens belong to (informational; for `--whoami` reuse). */
|
|
15
|
-
readonly username: string;
|
|
16
|
-
/** ISO 8601 timestamp this document was written. */
|
|
17
|
-
readonly writtenAt: string;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Compute the on-disk path for a registry's token cache. Pure (no
|
|
21
|
-
* IO) so callers can derive the path before existence checks.
|
|
22
|
-
*/
|
|
23
|
-
export declare function getRegistryTokenPath(registryUrl: string): string;
|
|
24
|
-
/**
|
|
25
|
-
* Load a cached token document. Returns null when missing OR
|
|
26
|
-
* malformed — callers treat both as "need to log in".
|
|
27
|
-
*/
|
|
28
|
-
export declare function loadRegistryToken(registryUrl: string): RegistryTokenDocument | null;
|
|
29
|
-
/**
|
|
30
|
-
* Atomically write the document with mode `0o600`. write-temp +
|
|
31
|
-
* rename pattern so a crash mid-write doesn't strand a partial doc.
|
|
32
|
-
*/
|
|
33
|
-
export declare function saveRegistryToken(doc: RegistryTokenDocument): void;
|
|
34
|
-
/**
|
|
35
|
-
* Decide whether a cached document is still usable for the next
|
|
36
|
-
* request. Subtracts a 60-second safety margin so we don't race a
|
|
37
|
-
* boundary expiry that the registry would refuse.
|
|
38
|
-
*/
|
|
39
|
-
export declare function isTokenFresh(doc: RegistryTokenDocument, nowSeconds?: number): boolean;
|
|
40
|
-
//# sourceMappingURL=auth-cache.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-cache.d.ts","sourceRoot":"","sources":["../../src/internal/auth-cache.ts"],"names":[],"mappings":"AA6BA,wBAAwB;AACxB,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,GAClB,qBAAqB,GAAG,IAAI,CAiB9B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CA4BlE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,qBAAqB,EAC1B,UAAU,GAAE,MAAsC,GACjD,OAAO,CAET"}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-registry JWT cache for `ggui gadget publish`.
|
|
3
|
-
*
|
|
4
|
-
* Layout: `~/.ggui/auth/<registry-hostname>/token.json`. One file per
|
|
5
|
-
* registry hostname so an operator who publishes to a dev sandbox
|
|
6
|
-
* AND production doesn't paper over one session with the other. The
|
|
7
|
-
* hostname is the directory name (no path component leaks into disk
|
|
8
|
-
* names) — full URL is captured inside the document.
|
|
9
|
-
*
|
|
10
|
-
* Document version is `1`. Bumped on breaking-change shape edits;
|
|
11
|
-
* loaders that see `version > 1` refuse rather than mis-parse.
|
|
12
|
-
*
|
|
13
|
-
* **Distinct from `~/.ggui/auth.json`.** That file holds the
|
|
14
|
-
* `api.ggui.ai` device-flow session for hosted-key management. The
|
|
15
|
-
* registry tokens here are a SEPARATE auth surface (different IdP,
|
|
16
|
-
* different audience), so they live in a parallel namespace.
|
|
17
|
-
*/
|
|
18
|
-
import { URL } from 'node:url';
|
|
19
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
|
|
20
|
-
import { dirname, join } from 'node:path';
|
|
21
|
-
import { getConfigDir } from '../paths.js';
|
|
22
|
-
/**
|
|
23
|
-
* Compute the on-disk path for a registry's token cache. Pure (no
|
|
24
|
-
* IO) so callers can derive the path before existence checks.
|
|
25
|
-
*/
|
|
26
|
-
export function getRegistryTokenPath(registryUrl) {
|
|
27
|
-
const host = safeHostname(registryUrl);
|
|
28
|
-
return join(getConfigDir(), 'auth', host, 'token.json');
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Load a cached token document. Returns null when missing OR
|
|
32
|
-
* malformed — callers treat both as "need to log in".
|
|
33
|
-
*/
|
|
34
|
-
export function loadRegistryToken(registryUrl) {
|
|
35
|
-
const path = getRegistryTokenPath(registryUrl);
|
|
36
|
-
if (!existsSync(path))
|
|
37
|
-
return null;
|
|
38
|
-
let raw;
|
|
39
|
-
try {
|
|
40
|
-
raw = readFileSync(path, 'utf8');
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
let decoded;
|
|
46
|
-
try {
|
|
47
|
-
decoded = JSON.parse(raw);
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
if (!isRegistryTokenDocument(decoded))
|
|
53
|
-
return null;
|
|
54
|
-
return decoded;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Atomically write the document with mode `0o600`. write-temp +
|
|
58
|
-
* rename pattern so a crash mid-write doesn't strand a partial doc.
|
|
59
|
-
*/
|
|
60
|
-
export function saveRegistryToken(doc) {
|
|
61
|
-
const target = getRegistryTokenPath(doc.registry);
|
|
62
|
-
const dir = dirname(target);
|
|
63
|
-
if (!existsSync(dir)) {
|
|
64
|
-
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
try {
|
|
68
|
-
chmodSync(dir, 0o700);
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
// best-effort on Windows
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
75
|
-
writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}\n`, {
|
|
76
|
-
encoding: 'utf8',
|
|
77
|
-
mode: 0o600,
|
|
78
|
-
});
|
|
79
|
-
try {
|
|
80
|
-
chmodSync(tmp, 0o600);
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
// best-effort
|
|
84
|
-
}
|
|
85
|
-
renameSync(tmp, target);
|
|
86
|
-
try {
|
|
87
|
-
chmodSync(target, 0o600);
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
// best-effort
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Decide whether a cached document is still usable for the next
|
|
95
|
-
* request. Subtracts a 60-second safety margin so we don't race a
|
|
96
|
-
* boundary expiry that the registry would refuse.
|
|
97
|
-
*/
|
|
98
|
-
export function isTokenFresh(doc, nowSeconds = Math.floor(Date.now() / 1000)) {
|
|
99
|
-
return doc.expiresAt - nowSeconds > 60;
|
|
100
|
-
}
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
|
-
// internal
|
|
103
|
-
// ---------------------------------------------------------------------------
|
|
104
|
-
function isRegistryTokenDocument(x) {
|
|
105
|
-
if (typeof x !== 'object' || x === null)
|
|
106
|
-
return false;
|
|
107
|
-
const r = x;
|
|
108
|
-
return (r['version'] === 1 &&
|
|
109
|
-
typeof r['registry'] === 'string' &&
|
|
110
|
-
typeof r['idToken'] === 'string' &&
|
|
111
|
-
typeof r['accessToken'] === 'string' &&
|
|
112
|
-
typeof r['refreshToken'] === 'string' &&
|
|
113
|
-
typeof r['expiresAt'] === 'number' &&
|
|
114
|
-
typeof r['username'] === 'string' &&
|
|
115
|
-
typeof r['writtenAt'] === 'string');
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Extract a filesystem-safe hostname from a registry URL. Replaces
|
|
119
|
-
* non-alphanumeric chars with `-` so the result is always a valid
|
|
120
|
-
* directory name on every supported OS.
|
|
121
|
-
*/
|
|
122
|
-
function safeHostname(registryUrl) {
|
|
123
|
-
let host;
|
|
124
|
-
try {
|
|
125
|
-
host = new URL(registryUrl).hostname;
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
// Caller validated earlier; if we got here with a bogus URL the
|
|
129
|
-
// cleanest thing is to refuse the path entirely.
|
|
130
|
-
throw new Error(`auth-cache: invalid registry URL: ${registryUrl}`);
|
|
131
|
-
}
|
|
132
|
-
return host.replace(/[^a-z0-9.-]/gi, '-');
|
|
133
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { ShortCodeIndex } from '@ggui-ai/mcp-server-core';
|
|
2
|
-
/**
|
|
3
|
-
* Construct the persistent ShortCodeIndex backed by `<persistentDir>/
|
|
4
|
-
* short-codes.sqlite`. Creates the parent dir if missing (the persistent
|
|
5
|
-
* dir always exists by the time this is called — the secrets helper
|
|
6
|
-
* already mkdir'd it — but mkdir is idempotent and cheap).
|
|
7
|
-
*
|
|
8
|
-
* Throws if `better-sqlite3` can't be loaded (e.g. native binding
|
|
9
|
-
* missing for the current platform). The CLI surfaces this as a fatal
|
|
10
|
-
* boot error so the operator can either install the binding or pass
|
|
11
|
-
* `--ephemeral`.
|
|
12
|
-
*/
|
|
13
|
-
export declare function createPersistentShortCodeIndex(persistentDir: string): Promise<ShortCodeIndex>;
|
|
14
|
-
//# sourceMappingURL=persistent-short-code-index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"persistent-short-code-index.d.ts","sourceRoot":"","sources":["../src/persistent-short-code-index.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D;;;;;;;;;;GAUG;AACH,wBAAsB,8BAA8B,CAClD,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,CAAC,CAQzB"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve a persistent `ShortCodeIndex` for `ggui serve`.
|
|
3
|
-
*
|
|
4
|
-
* The OSS default for `shortCodeIndex` is `InMemoryShortCodeIndex` —
|
|
5
|
-
* the mapping lives in process memory and a restart drops every
|
|
6
|
-
* binding, so `/r/<code>` + `/api/bootstrap/<code>` 404 on the cached
|
|
7
|
-
* envelopes claude.ai stored before the restart.
|
|
8
|
-
*
|
|
9
|
-
* When the CLI is running in persistent mode (no `--ephemeral`), this
|
|
10
|
-
* helper constructs a `SqliteShortCodeIndex` against
|
|
11
|
-
* `<persistentDir>/short-codes.sqlite` so the same lookups survive
|
|
12
|
-
* restart. better-sqlite3 is dynamic-imported (same pattern as
|
|
13
|
-
* `@ggui-ai/mcp-server::resolveStorageFromConfig`) so consumers that
|
|
14
|
-
* stay ephemeral don't pay the N-API binding load on boot.
|
|
15
|
-
*
|
|
16
|
-
* Caller composes the path; this module is pure construction over a
|
|
17
|
-
* given dir + better-sqlite3 dynamic-import, so tests can scope to a
|
|
18
|
-
* tmpdir.
|
|
19
|
-
*/
|
|
20
|
-
import { mkdirSync } from 'node:fs';
|
|
21
|
-
import { join } from 'node:path';
|
|
22
|
-
/**
|
|
23
|
-
* Construct the persistent ShortCodeIndex backed by `<persistentDir>/
|
|
24
|
-
* short-codes.sqlite`. Creates the parent dir if missing (the persistent
|
|
25
|
-
* dir always exists by the time this is called — the secrets helper
|
|
26
|
-
* already mkdir'd it — but mkdir is idempotent and cheap).
|
|
27
|
-
*
|
|
28
|
-
* Throws if `better-sqlite3` can't be loaded (e.g. native binding
|
|
29
|
-
* missing for the current platform). The CLI surfaces this as a fatal
|
|
30
|
-
* boot error so the operator can either install the binding or pass
|
|
31
|
-
* `--ephemeral`.
|
|
32
|
-
*/
|
|
33
|
-
export async function createPersistentShortCodeIndex(persistentDir) {
|
|
34
|
-
mkdirSync(persistentDir, { recursive: true });
|
|
35
|
-
const { SqliteShortCodeIndex } = await import('@ggui-ai/mcp-server-core/sqlite');
|
|
36
|
-
return new SqliteShortCodeIndex({
|
|
37
|
-
filename: join(persistentDir, 'short-codes.sqlite'),
|
|
38
|
-
});
|
|
39
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `spawnCloudflaredTunnel` — auto-tunnel helper for `ggui serve --public`.
|
|
3
|
-
*
|
|
4
|
-
* The local-dev → claude.ai integration loop has a well-known trap:
|
|
5
|
-
* every demo session would otherwise need to manually run
|
|
6
|
-
* `cloudflared tunnel --url http://localhost:6781`, grep the URL from
|
|
7
|
-
* its noisy stderr, then restart `ggui serve --public-base-url <url>`
|
|
8
|
-
* with that value pinned. `runtimeUrl` is auto-derived from
|
|
9
|
-
* `X-Forwarded-Host` and no longer depends on `publicBaseUrl`, but
|
|
10
|
-
* production deployments still need the URL pinned for OAuth callbacks
|
|
11
|
-
* and email magic-links. This helper closes the gap: one `--public`
|
|
12
|
-
* flag spawns cloudflared, parses its URL, and threads it into the
|
|
13
|
-
* boot config.
|
|
14
|
-
*
|
|
15
|
-
* **Trust posture.** This helper does NOT mask the public exposure. It
|
|
16
|
-
* is the operator's explicit opt-in (`--public`); when combined with
|
|
17
|
-
* `--dev-allow-all` the CLI front-end requires a second flag
|
|
18
|
-
* (`--i-know-its-public`) to prevent accidentally serving any-bearer
|
|
19
|
-
* auth over the internet.
|
|
20
|
-
*
|
|
21
|
-
* **Process management.** The spawned child is the operator's only
|
|
22
|
-
* dependency on the host's `cloudflared` binary; we don't bundle it.
|
|
23
|
-
* On `close()`, SIGTERM → SIGKILL fallback after 5s. AbortSignal
|
|
24
|
-
* support lets the CLI lifecycle (Ctrl-C handler in `runServe`)
|
|
25
|
-
* tear down cloudflared in lockstep with the server.
|
|
26
|
-
*/
|
|
27
|
-
export interface SpawnCloudflaredOptions {
|
|
28
|
-
/** Local port the tunnel forwards to. */
|
|
29
|
-
readonly port: number;
|
|
30
|
-
/** Optional override of the binary path. Defaults to `cloudflared`
|
|
31
|
-
* on PATH; operators wrap with `--cloudflared-bin <path>` when
|
|
32
|
-
* installed outside PATH. */
|
|
33
|
-
readonly binary?: string;
|
|
34
|
-
/** Optional AbortSignal — fires SIGTERM on the child when aborted. */
|
|
35
|
-
readonly signal?: AbortSignal;
|
|
36
|
-
/** Optional logger seam. Default no-op. */
|
|
37
|
-
readonly onLog?: (line: string) => void;
|
|
38
|
-
/** URL-detection timeout. */
|
|
39
|
-
readonly urlTimeoutMs?: number;
|
|
40
|
-
}
|
|
41
|
-
export interface SpawnCloudflaredResult {
|
|
42
|
-
/** Public `https://<random>.trycloudflare.com` URL extracted from
|
|
43
|
-
* cloudflared's stderr. */
|
|
44
|
-
readonly url: string;
|
|
45
|
-
/** Tear down the tunnel. Idempotent; safe to call multiple times. */
|
|
46
|
-
close(): Promise<void>;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Spawn `cloudflared tunnel --url http://localhost:<port>` and resolve
|
|
50
|
-
* with the assigned trycloudflare URL. Rejects when:
|
|
51
|
-
*
|
|
52
|
-
* - The binary can't be spawned (cloudflared not installed / wrong
|
|
53
|
-
* path / permission denied). Error message includes the install
|
|
54
|
-
* hint.
|
|
55
|
-
* - cloudflared exits before printing a URL. Error includes any
|
|
56
|
-
* captured stderr tail.
|
|
57
|
-
* - URL detection times out. Error includes elapsed time + last
|
|
58
|
-
* ~10 lines of stderr so the operator can diagnose.
|
|
59
|
-
*/
|
|
60
|
-
export declare function spawnCloudflaredTunnel(opts: SpawnCloudflaredOptions): Promise<SpawnCloudflaredResult>;
|
|
61
|
-
//# sourceMappingURL=spawn-cloudflared.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-cloudflared.d.ts","sourceRoot":"","sources":["../src/spawn-cloudflared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAeH,MAAM,WAAW,uBAAuB;IACtC,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;kCAE8B;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,6BAA6B;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC;gCAC4B;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,sBAAsB,CAAC,CA6IjC"}
|