@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.
Files changed (80) hide show
  1. package/README.md +38 -7
  2. package/dist/api-client.d.ts +42 -1
  3. package/dist/api-client.d.ts.map +1 -1
  4. package/dist/api-client.js +30 -2
  5. package/dist/auth-keys.d.ts +1 -1
  6. package/dist/auth-keys.d.ts.map +1 -1
  7. package/dist/auth-keys.js +22 -7
  8. package/dist/auth-store.d.ts +1 -1
  9. package/dist/auth-store.d.ts.map +1 -1
  10. package/dist/cli.js +112 -30
  11. package/dist/config-push.d.ts +79 -0
  12. package/dist/config-push.d.ts.map +1 -0
  13. package/dist/config-push.js +301 -0
  14. package/dist/create-app-command.d.ts +17 -0
  15. package/dist/create-app-command.d.ts.map +1 -0
  16. package/dist/create-app-command.js +58 -0
  17. package/dist/deploy-command.d.ts +67 -0
  18. package/dist/deploy-command.d.ts.map +1 -0
  19. package/dist/deploy-command.js +386 -0
  20. package/dist/dev-command.d.ts +5 -1
  21. package/dist/dev-command.d.ts.map +1 -1
  22. package/dist/dev-command.js +31 -1
  23. package/dist/export-pool-command.d.ts +25 -0
  24. package/dist/export-pool-command.d.ts.map +1 -0
  25. package/dist/export-pool-command.js +116 -0
  26. package/dist/filesystem-seed-pool-source.d.ts +13 -0
  27. package/dist/filesystem-seed-pool-source.d.ts.map +1 -0
  28. package/dist/filesystem-seed-pool-source.js +22 -0
  29. package/dist/generation-probe.d.ts +53 -7
  30. package/dist/generation-probe.d.ts.map +1 -1
  31. package/dist/generation-probe.js +37 -1
  32. package/dist/internal/artifact-install.d.ts +4 -2
  33. package/dist/internal/artifact-install.d.ts.map +1 -1
  34. package/dist/internal/artifact-install.js +11 -10
  35. package/dist/internal/artifact-publish.d.ts +34 -31
  36. package/dist/internal/artifact-publish.d.ts.map +1 -1
  37. package/dist/internal/artifact-publish.js +133 -241
  38. package/dist/internal/artifact-search.d.ts +2 -28
  39. package/dist/internal/artifact-search.d.ts.map +1 -1
  40. package/dist/internal/artifact-search.js +5 -4
  41. package/dist/internal/auth-strategy.d.ts +21 -31
  42. package/dist/internal/auth-strategy.d.ts.map +1 -1
  43. package/dist/internal/auth-strategy.js +15 -23
  44. package/dist/internal/register-author-key.d.ts +7 -1
  45. package/dist/internal/register-author-key.d.ts.map +1 -1
  46. package/dist/internal/register-author-key.js +56 -19
  47. package/dist/mcp-backend.d.ts +25 -25
  48. package/dist/mcp-backend.d.ts.map +1 -1
  49. package/dist/mcp-backend.js +65 -61
  50. package/dist/paths.d.ts +3 -3
  51. package/dist/paths.js +3 -3
  52. package/dist/persistent-secrets.js +1 -1
  53. package/dist/persistent-stores.d.ts +2 -2
  54. package/dist/persistent-stores.d.ts.map +1 -1
  55. package/dist/persistent-stores.js +5 -5
  56. package/dist/pool-artifact.d.ts +19 -0
  57. package/dist/pool-artifact.d.ts.map +1 -0
  58. package/dist/pool-artifact.js +59 -0
  59. package/dist/provider-key-command.d.ts +51 -0
  60. package/dist/provider-key-command.d.ts.map +1 -0
  61. package/dist/provider-key-command.js +222 -0
  62. package/dist/push-command.d.ts +47 -0
  63. package/dist/push-command.d.ts.map +1 -0
  64. package/dist/push-command.js +230 -0
  65. package/dist/serve-command.d.ts +23 -19
  66. package/dist/serve-command.d.ts.map +1 -1
  67. package/dist/serve-command.js +13 -26
  68. package/dist/theme-command.js +0 -2
  69. package/dist/tunnel-provider.d.ts +8 -7
  70. package/dist/tunnel-provider.d.ts.map +1 -1
  71. package/package.json +25 -21
  72. package/dist/internal/auth-cache.d.ts +0 -40
  73. package/dist/internal/auth-cache.d.ts.map +0 -1
  74. package/dist/internal/auth-cache.js +0 -133
  75. package/dist/persistent-short-code-index.d.ts +0 -14
  76. package/dist/persistent-short-code-index.d.ts.map +0 -1
  77. package/dist/persistent-short-code-index.js +0 -39
  78. package/dist/spawn-cloudflared.d.ts +0 -61
  79. package/dist/spawn-cloudflared.d.ts.map +0 -1
  80. package/dist/spawn-cloudflared.js +0 -167
@@ -1,167 +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
- import { spawn } from 'node:child_process';
28
- /** Configured upper bound on how long we wait for cloudflared to
29
- * print its public URL. Cold quick-tunnel typically takes 2-5s;
30
- * setting too low surfaces a flaky "no URL detected" error to the
31
- * operator before the tunnel actually fails. 30s is generous. */
32
- const DEFAULT_URL_TIMEOUT_MS = 30_000;
33
- /** Matcher for the trycloudflare URL inside cloudflared's stderr.
34
- * cloudflared's exact log format has been stable since 2023; if it
35
- * changes, this regex is the single point of impact. */
36
- const TRYCLOUDFLARE_URL_RE = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/i;
37
- /**
38
- * Spawn `cloudflared tunnel --url http://localhost:<port>` and resolve
39
- * with the assigned trycloudflare URL. Rejects when:
40
- *
41
- * - The binary can't be spawned (cloudflared not installed / wrong
42
- * path / permission denied). Error message includes the install
43
- * hint.
44
- * - cloudflared exits before printing a URL. Error includes any
45
- * captured stderr tail.
46
- * - URL detection times out. Error includes elapsed time + last
47
- * ~10 lines of stderr so the operator can diagnose.
48
- */
49
- export function spawnCloudflaredTunnel(opts) {
50
- const binary = opts.binary ?? 'cloudflared';
51
- const port = opts.port;
52
- const timeout = opts.urlTimeoutMs ?? DEFAULT_URL_TIMEOUT_MS;
53
- const log = opts.onLog ?? (() => { });
54
- return new Promise((resolve, reject) => {
55
- let child;
56
- try {
57
- child = spawn(binary, ['tunnel', '--url', `http://localhost:${port}`, '--no-autoupdate'], { stdio: ['ignore', 'pipe', 'pipe'] });
58
- }
59
- catch (err) {
60
- reject(new Error(`Failed to spawn ${binary}: ${err.message}. ` +
61
- `Install cloudflared from https://github.com/cloudflare/cloudflared/releases.`));
62
- return;
63
- }
64
- // Tail buffer for error context — cap so a chatty cloudflared
65
- // version doesn't balloon memory.
66
- const stderrTail = [];
67
- const MAX_TAIL = 50;
68
- let url;
69
- let urlResolved = false;
70
- let closed = false;
71
- const startedAt = Date.now();
72
- const timer = setTimeout(() => {
73
- if (!urlResolved) {
74
- reject(new Error(`cloudflared did not emit a tunnel URL within ${timeout}ms. ` +
75
- `Last stderr lines:\n${stderrTail.slice(-10).join('\n')}`));
76
- void close();
77
- }
78
- }, timeout);
79
- function handleLine(line) {
80
- log(line);
81
- stderrTail.push(line);
82
- if (stderrTail.length > MAX_TAIL) {
83
- stderrTail.shift();
84
- }
85
- if (urlResolved)
86
- return;
87
- const match = line.match(TRYCLOUDFLARE_URL_RE);
88
- if (match) {
89
- url = match[0];
90
- urlResolved = true;
91
- clearTimeout(timer);
92
- resolve({
93
- url,
94
- close,
95
- });
96
- }
97
- }
98
- // cloudflared logs to BOTH stdout and stderr depending on version
99
- // — wire both through the same line-handler so the regex catches
100
- // wherever it lands.
101
- function attachLineReader(stream) {
102
- let buf = '';
103
- stream.setEncoding('utf8');
104
- stream.on('data', (chunk) => {
105
- buf += chunk;
106
- let nl = buf.indexOf('\n');
107
- while (nl !== -1) {
108
- const line = buf.slice(0, nl).trimEnd();
109
- buf = buf.slice(nl + 1);
110
- if (line.length > 0)
111
- handleLine(line);
112
- nl = buf.indexOf('\n');
113
- }
114
- });
115
- }
116
- if (child.stderr)
117
- attachLineReader(child.stderr);
118
- if (child.stdout)
119
- attachLineReader(child.stdout);
120
- child.on('error', (err) => {
121
- clearTimeout(timer);
122
- if (!urlResolved) {
123
- reject(new Error(`cloudflared spawn error: ${err.message}. ` +
124
- `Verify the binary is installed and executable.`));
125
- }
126
- });
127
- child.on('exit', (code, sig) => {
128
- clearTimeout(timer);
129
- if (!urlResolved) {
130
- reject(new Error(`cloudflared exited (code=${code}, signal=${sig}) before ` +
131
- `emitting a tunnel URL (elapsed ${Date.now() - startedAt}ms). ` +
132
- `Last stderr lines:\n${stderrTail.slice(-10).join('\n')}`));
133
- }
134
- });
135
- function close() {
136
- if (closed)
137
- return Promise.resolve();
138
- closed = true;
139
- return new Promise((resolveClose) => {
140
- if (child.killed || child.exitCode !== null) {
141
- resolveClose();
142
- return;
143
- }
144
- const killTimer = setTimeout(() => {
145
- if (!child.killed && child.exitCode === null) {
146
- child.kill('SIGKILL');
147
- }
148
- }, 5000);
149
- child.once('exit', () => {
150
- clearTimeout(killTimer);
151
- resolveClose();
152
- });
153
- child.kill('SIGTERM');
154
- });
155
- }
156
- if (opts.signal) {
157
- if (opts.signal.aborted) {
158
- void close();
159
- }
160
- else {
161
- opts.signal.addEventListener('abort', () => void close(), {
162
- once: true,
163
- });
164
- }
165
- }
166
- });
167
- }