@agent-native/core 0.7.23 → 0.7.24

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 (137) hide show
  1. package/README.md +2 -2
  2. package/dist/a2a/client.d.ts +10 -4
  3. package/dist/a2a/client.d.ts.map +1 -1
  4. package/dist/a2a/client.js +16 -1
  5. package/dist/a2a/client.js.map +1 -1
  6. package/dist/a2a/handlers.d.ts.map +1 -1
  7. package/dist/a2a/handlers.js +20 -17
  8. package/dist/a2a/handlers.js.map +1 -1
  9. package/dist/cli/create.d.ts +2 -1
  10. package/dist/cli/create.d.ts.map +1 -1
  11. package/dist/cli/create.js +13 -19
  12. package/dist/cli/create.js.map +1 -1
  13. package/dist/cli/index.js +23 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/workspace-dev.d.ts +3 -0
  16. package/dist/cli/workspace-dev.d.ts.map +1 -0
  17. package/dist/cli/workspace-dev.js +323 -0
  18. package/dist/cli/workspace-dev.js.map +1 -0
  19. package/dist/cli/workspacify.d.ts +3 -3
  20. package/dist/cli/workspacify.js +4 -4
  21. package/dist/cli/workspacify.js.map +1 -1
  22. package/dist/client/AgentPanel.d.ts.map +1 -1
  23. package/dist/client/AgentPanel.js +10 -9
  24. package/dist/client/AgentPanel.js.map +1 -1
  25. package/dist/client/AssistantChat.d.ts.map +1 -1
  26. package/dist/client/AssistantChat.js +2 -1
  27. package/dist/client/AssistantChat.js.map +1 -1
  28. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  29. package/dist/client/MultiTabAssistantChat.js +2 -1
  30. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  31. package/dist/client/components/ui/tooltip.d.ts +8 -0
  32. package/dist/client/components/ui/tooltip.d.ts.map +1 -0
  33. package/dist/client/components/ui/tooltip.js +11 -0
  34. package/dist/client/components/ui/tooltip.js.map +1 -0
  35. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  36. package/dist/client/resources/ResourceTree.js +21 -17
  37. package/dist/client/resources/ResourceTree.js.map +1 -1
  38. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  39. package/dist/client/resources/ResourcesPanel.js +13 -11
  40. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  41. package/dist/deploy/workspace-core.d.ts +1 -1
  42. package/dist/deploy/workspace-core.d.ts.map +1 -1
  43. package/dist/deploy/workspace-core.js +14 -11
  44. package/dist/deploy/workspace-core.js.map +1 -1
  45. package/dist/integrations/a2a-continuation-processor.d.ts +10 -0
  46. package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -0
  47. package/dist/integrations/a2a-continuation-processor.js +150 -0
  48. package/dist/integrations/a2a-continuation-processor.js.map +1 -0
  49. package/dist/integrations/a2a-continuations-store.d.ts +41 -0
  50. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -0
  51. package/dist/integrations/a2a-continuations-store.js +214 -0
  52. package/dist/integrations/a2a-continuations-store.js.map +1 -0
  53. package/dist/integrations/plugin.d.ts.map +1 -1
  54. package/dist/integrations/plugin.js +52 -0
  55. package/dist/integrations/plugin.js.map +1 -1
  56. package/dist/integrations/types.d.ts +5 -0
  57. package/dist/integrations/types.d.ts.map +1 -1
  58. package/dist/integrations/types.js.map +1 -1
  59. package/dist/integrations/webhook-handler.d.ts +6 -0
  60. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  61. package/dist/integrations/webhook-handler.js +69 -15
  62. package/dist/integrations/webhook-handler.js.map +1 -1
  63. package/dist/org/handlers.d.ts.map +1 -1
  64. package/dist/org/handlers.js +22 -16
  65. package/dist/org/handlers.js.map +1 -1
  66. package/dist/scripts/call-agent.d.ts.map +1 -1
  67. package/dist/scripts/call-agent.js +91 -30
  68. package/dist/scripts/call-agent.js.map +1 -1
  69. package/dist/server/agent-discovery.d.ts.map +1 -1
  70. package/dist/server/agent-discovery.js +17 -105
  71. package/dist/server/agent-discovery.js.map +1 -1
  72. package/dist/server/agents-bundle.js +1 -1
  73. package/dist/server/agents-bundle.js.map +1 -1
  74. package/dist/server/auth.d.ts.map +1 -1
  75. package/dist/server/auth.js +29 -120
  76. package/dist/server/auth.js.map +1 -1
  77. package/dist/server/better-auth-instance.d.ts +1 -0
  78. package/dist/server/better-auth-instance.d.ts.map +1 -1
  79. package/dist/server/better-auth-instance.js.map +1 -1
  80. package/dist/server/builder-browser.d.ts.map +1 -1
  81. package/dist/server/builder-browser.js +7 -5
  82. package/dist/server/builder-browser.js.map +1 -1
  83. package/dist/server/framework-request-handler.js +1 -1
  84. package/dist/server/framework-request-handler.js.map +1 -1
  85. package/dist/server/onboarding-html.d.ts +1 -8
  86. package/dist/server/onboarding-html.d.ts.map +1 -1
  87. package/dist/server/onboarding-html.js +321 -152
  88. package/dist/server/onboarding-html.js.map +1 -1
  89. package/dist/server/request-context.d.ts +14 -3
  90. package/dist/server/request-context.d.ts.map +1 -1
  91. package/dist/server/request-context.js +3 -0
  92. package/dist/server/request-context.js.map +1 -1
  93. package/dist/templates/default/_gitignore +2 -0
  94. package/dist/templates/workspace-core/AGENTS.md +18 -71
  95. package/dist/templates/workspace-core/package.json +2 -20
  96. package/dist/templates/workspace-core/src/client/index.ts +2 -26
  97. package/dist/templates/workspace-core/src/index.ts +1 -21
  98. package/dist/templates/workspace-core/src/server/index.ts +3 -22
  99. package/dist/templates/workspace-root/README.md +17 -20
  100. package/dist/templates/workspace-root/_gitignore +3 -0
  101. package/dist/templates/workspace-root/package.json +6 -13
  102. package/dist/templates/workspace-root/pnpm-workspace.yaml +4 -2
  103. package/dist/vite/agents-bundle-plugin.js +2 -2
  104. package/dist/vite/agents-bundle-plugin.js.map +1 -1
  105. package/docs/content/authentication.md +3 -5
  106. package/docs/content/multi-app-workspace.md +38 -50
  107. package/package.json +1 -1
  108. package/src/templates/default/_gitignore +2 -0
  109. package/src/templates/workspace-core/AGENTS.md +18 -71
  110. package/src/templates/workspace-core/package.json +2 -20
  111. package/src/templates/workspace-core/src/client/index.ts +2 -26
  112. package/src/templates/workspace-core/src/index.ts +1 -21
  113. package/src/templates/workspace-core/src/server/index.ts +3 -22
  114. package/src/templates/workspace-root/README.md +17 -20
  115. package/src/templates/workspace-root/_gitignore +3 -0
  116. package/src/templates/workspace-root/package.json +6 -13
  117. package/src/templates/workspace-root/pnpm-workspace.yaml +4 -2
  118. package/dist/templates/default/.claude/settings.json +0 -100
  119. package/dist/templates/workspace-core/.agents/skills/company-policies/SKILL.md +0 -42
  120. package/dist/templates/workspace-core/actions/company-directory.ts +0 -38
  121. package/dist/templates/workspace-core/src/client/AuthenticatedLayout.tsx +0 -37
  122. package/dist/templates/workspace-core/src/credentials.ts +0 -67
  123. package/dist/templates/workspace-core/src/server/agent-chat-plugin.ts +0 -30
  124. package/dist/templates/workspace-core/src/server/auth-plugin.ts +0 -35
  125. package/dist/templates/workspace-core/styles/tokens.css +0 -22
  126. package/dist/templates/workspace-root/.github/workflows/ci.yml +0 -32
  127. package/dist/templates/workspace-root/scripts/workspace-dev.ts +0 -377
  128. package/src/templates/default/.claude/settings.json +0 -100
  129. package/src/templates/workspace-core/.agents/skills/company-policies/SKILL.md +0 -42
  130. package/src/templates/workspace-core/actions/company-directory.ts +0 -38
  131. package/src/templates/workspace-core/src/client/AuthenticatedLayout.tsx +0 -37
  132. package/src/templates/workspace-core/src/credentials.ts +0 -67
  133. package/src/templates/workspace-core/src/server/agent-chat-plugin.ts +0 -30
  134. package/src/templates/workspace-core/src/server/auth-plugin.ts +0 -35
  135. package/src/templates/workspace-core/styles/tokens.css +0 -22
  136. package/src/templates/workspace-root/.github/workflows/ci.yml +0 -32
  137. package/src/templates/workspace-root/scripts/workspace-dev.ts +0 -377
@@ -1,35 +0,0 @@
1
- /**
2
- * Workspace-wide auth plugin for @{{APP_NAME}}/core-module.
3
- *
4
- * Today this just re-uses the framework default, which already does the
5
- * right thing for most enterprises (Better Auth with Google SSO when
6
- * GOOGLE_CLIENT_ID/SECRET are set, email/password otherwise, local dev
7
- * bypass via AUTH_MODE=local). Customize it here when your enterprise
8
- * needs specific behavior — e.g.:
9
- *
10
- * - Wrap the default to force a specific SSO provider
11
- * - Add a callback that provisions users into your directory
12
- * - Pre-register organizations / role mappings from Okta groups
13
- * - Fail closed on unauthenticated requests outside dev
14
- *
15
- * Every app in the workspace inherits this automatically (as long as the
16
- * root package.json has `"agent-native": { "workspaceCore": "@{{APP_NAME}}/core-module" }`).
17
- */
18
- import { defaultAuthPlugin } from "@agent-native/core/server";
19
-
20
- export const authPlugin = async (nitroApp: any): Promise<void> => {
21
- // Run the framework default first so Better Auth, org tables, and session
22
- // middleware are all set up.
23
- await defaultAuthPlugin(nitroApp);
24
-
25
- // Add enterprise-specific post-auth behavior here. Examples:
26
- //
27
- // const h3 = getH3App(nitroApp);
28
- // h3.use(defineEventHandler(async (event) => {
29
- // const session = await getSession(event);
30
- // if (session?.email && !session.email.endsWith("@{{APP_NAME}}.com")) {
31
- // setResponseStatus(event, 403);
32
- // return { error: "Only @{{APP_NAME}}.com accounts allowed" };
33
- // }
34
- // }));
35
- };
@@ -1,22 +0,0 @@
1
- /**
2
- * Workspace-wide Tailwind v4 design tokens for @{{APP_NAME}}/core-module.
3
- *
4
- * Every app in the workspace should import this from its own
5
- * `app/global.css` so brand updates in one place propagate to all apps:
6
- *
7
- * @import "tailwindcss";
8
- * @import "@{{APP_NAME}}/core-module/styles/tokens.css";
9
- *
10
- * Replace the values below with your real brand palette.
11
- */
12
-
13
- /* Re-export the framework's standard token mappings (color-background,
14
- color-foreground, color-border, …) so apps don't need a second import. */
15
- @import "@agent-native/core/styles/agent-native.css";
16
-
17
- @theme {
18
- /* Add enterprise brand colors here. They become utility classes:
19
- `bg-brand`, `text-brand-foreground`, etc. */
20
- --color-brand: #4f46e5;
21
- --color-brand-foreground: #ffffff;
22
- }
@@ -1,32 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- pull_request:
5
- push:
6
- branches: [main]
7
-
8
- permissions:
9
- contents: read
10
-
11
- jobs:
12
- checks:
13
- name: Lint, typecheck, build
14
- runs-on: ubuntu-latest
15
-
16
- steps:
17
- - uses: actions/checkout@v4
18
-
19
- - uses: pnpm/action-setup@v4
20
-
21
- - uses: actions/setup-node@v4
22
- with:
23
- node-version: "22"
24
- cache: "pnpm"
25
-
26
- - run: pnpm install --no-frozen-lockfile
27
-
28
- - run: pnpm lint
29
-
30
- - run: pnpm typecheck
31
-
32
- - run: pnpm build
@@ -1,377 +0,0 @@
1
- #!/usr/bin/env tsx
2
- import { spawn, type ChildProcess } from "node:child_process";
3
- import fs from "node:fs";
4
- import http from "node:http";
5
- import net from "node:net";
6
- import path from "node:path";
7
-
8
- interface WorkspaceApp {
9
- id: string;
10
- name: string;
11
- dir: string;
12
- port: number;
13
- process?: ChildProcess;
14
- }
15
-
16
- const root = process.cwd();
17
- const appsDir = path.join(root, "apps");
18
- fs.mkdirSync(path.join(root, "data"), { recursive: true });
19
- const gatewayHost = process.env.WORKSPACE_HOST || "127.0.0.1";
20
- const requestedPort = Number(
21
- process.env.WORKSPACE_PORT || process.env.PORT || 8080,
22
- );
23
- const appPortStart = Number(process.env.WORKSPACE_APP_PORT_START || 8100);
24
- const forceVite = process.env.WORKSPACE_VITE_FORCE === "1";
25
- let gatewayUrl = `http://${gatewayHost}:${requestedPort}`;
26
-
27
- function readJson(file: string): any {
28
- try {
29
- return JSON.parse(fs.readFileSync(file, "utf8"));
30
- } catch {
31
- return null;
32
- }
33
- }
34
-
35
- function discoverApps(): WorkspaceApp[] {
36
- if (!fs.existsSync(appsDir)) return [];
37
- return fs
38
- .readdirSync(appsDir, { withFileTypes: true })
39
- .filter((entry) => entry.isDirectory())
40
- .map((entry) => {
41
- const dir = path.join(appsDir, entry.name);
42
- const pkg = readJson(path.join(dir, "package.json"));
43
- if (!pkg) return null;
44
- return {
45
- id: entry.name,
46
- name: pkg.displayName || pkg.name || entry.name,
47
- dir,
48
- port: appPortStart,
49
- } satisfies WorkspaceApp;
50
- })
51
- .filter((app): app is WorkspaceApp => !!app)
52
- .sort((a, b) => {
53
- if (a.id === "dispatch") return -1;
54
- if (b.id === "dispatch") return 1;
55
- return a.id.localeCompare(b.id);
56
- })
57
- .map((app, index) => ({ ...app, port: appPortStart + index }));
58
- }
59
-
60
- const apps = discoverApps();
61
- if (apps.length === 0) {
62
- console.error("[workspace] No apps found under ./apps");
63
- process.exit(1);
64
- }
65
-
66
- const appById = new Map(apps.map((app) => [app.id, app]));
67
- const defaultApp =
68
- process.env.WORKSPACE_DEFAULT_APP &&
69
- appById.has(process.env.WORKSPACE_DEFAULT_APP)
70
- ? process.env.WORKSPACE_DEFAULT_APP
71
- : appById.has("dispatch")
72
- ? "dispatch"
73
- : apps[0].id;
74
-
75
- function syncApps(): void {
76
- const discovered = discoverApps();
77
- for (const app of discovered) {
78
- if (appById.has(app.id)) continue;
79
- const usedPorts = new Set(apps.map((existing) => existing.port));
80
- let port = appPortStart;
81
- while (usedPorts.has(port)) port++;
82
- const next = { ...app, port };
83
- apps.push(next);
84
- apps.sort((a, b) => {
85
- if (a.id === "dispatch") return -1;
86
- if (b.id === "dispatch") return 1;
87
- return a.id.localeCompare(b.id);
88
- });
89
- appById.set(next.id, next);
90
- console.log(`[workspace] Detected new app: /${next.id}`);
91
- startApp(next);
92
- }
93
- }
94
-
95
- let syncTimer: NodeJS.Timeout | undefined;
96
- function scheduleSync(): void {
97
- if (syncTimer) clearTimeout(syncTimer);
98
- syncTimer = setTimeout(syncApps, 400);
99
- }
100
-
101
- function firstPathSegment(url: string | undefined): string | null {
102
- if (!url) return null;
103
- try {
104
- const parsed = new URL(url, "http://workspace.local");
105
- const [segment] = parsed.pathname.split("/").filter(Boolean);
106
- return segment || null;
107
- } catch {
108
- return null;
109
- }
110
- }
111
-
112
- function appForRequest(req: http.IncomingMessage): WorkspaceApp | null {
113
- const direct = firstPathSegment(req.url);
114
- if (direct && appById.has(direct)) return appById.get(direct) ?? null;
115
- const referer = req.headers.referer;
116
- const fromReferer =
117
- typeof referer === "string" ? firstPathSegment(referer) : null;
118
- return fromReferer && appById.has(fromReferer)
119
- ? (appById.get(fromReferer) ?? null)
120
- : null;
121
- }
122
-
123
- function startApp(app: WorkspaceApp): void {
124
- const basePath = `/${app.id}`;
125
- const child = spawn(
126
- "pnpm",
127
- [
128
- "--dir",
129
- app.dir,
130
- "exec",
131
- "vite",
132
- "--host",
133
- "127.0.0.1",
134
- "--port",
135
- String(app.port),
136
- "--strictPort",
137
- ...(forceVite ? ["--force"] : []),
138
- ],
139
- {
140
- cwd: root,
141
- stdio: ["ignore", "pipe", "pipe"],
142
- env: {
143
- ...process.env,
144
- APP_NAME: app.id,
145
- APP_BASE_PATH: basePath,
146
- VITE_APP_BASE_PATH: basePath,
147
- PORT: String(app.port),
148
- WORKSPACE_GATEWAY_URL: gatewayUrl,
149
- },
150
- },
151
- );
152
- app.process = child;
153
-
154
- const prefix = `[${app.id}]`;
155
- child.stdout?.on("data", (chunk) => {
156
- process.stdout.write(
157
- String(chunk)
158
- .split(/\r?\n/)
159
- .filter(Boolean)
160
- .map((line) => `${prefix} ${line}`)
161
- .join("\n") + "\n",
162
- );
163
- });
164
- child.stderr?.on("data", (chunk) => {
165
- process.stderr.write(
166
- String(chunk)
167
- .split(/\r?\n/)
168
- .filter(Boolean)
169
- .map((line) => `${prefix} ${line}`)
170
- .join("\n") + "\n",
171
- );
172
- });
173
- child.on("exit", (code) => {
174
- if (code === 0 || shuttingDown) return;
175
- console.error(`${prefix} exited with code ${code}`);
176
- });
177
- }
178
-
179
- function renderIndex(): string {
180
- return `<!doctype html>
181
- <html>
182
- <head>
183
- <meta charset="utf-8" />
184
- <meta name="viewport" content="width=device-width, initial-scale=1" />
185
- <title>Agent-Native Workspace</title>
186
- <style>
187
- body { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; margin: 0; padding: 32px; background: #fafafa; color: #171717; }
188
- main { max-width: 760px; margin: 0 auto; }
189
- a { color: inherit; text-decoration: none; }
190
- .grid { display: grid; gap: 12px; margin-top: 20px; }
191
- .card { display: flex; justify-content: space-between; border: 1px solid #d4d4d4; border-radius: 8px; padding: 14px 16px; background: white; }
192
- .muted { color: #737373; }
193
- </style>
194
- </head>
195
- <body>
196
- <main>
197
- <h1>Agent-Native Workspace</h1>
198
- <p class="muted">Open an app below. Dispatch is the workspace control plane.</p>
199
- <div class="grid">
200
- ${apps
201
- .map(
202
- (app) =>
203
- `<a class="card" href="/${app.id}"><strong>${app.name}</strong><span class="muted">/${app.id}</span></a>`,
204
- )
205
- .join("")}
206
- </div>
207
- </main>
208
- </body>
209
- </html>`;
210
- }
211
-
212
- function proxyHttp(
213
- app: WorkspaceApp,
214
- req: http.IncomingMessage,
215
- res: http.ServerResponse,
216
- ): void {
217
- const headers = { ...req.headers, host: `127.0.0.1:${app.port}` };
218
- const proxyReq = http.request(
219
- {
220
- hostname: "127.0.0.1",
221
- port: app.port,
222
- method: req.method,
223
- path: req.url,
224
- headers,
225
- },
226
- (proxyRes) => {
227
- res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
228
- proxyRes.pipe(res);
229
- },
230
- );
231
-
232
- proxyReq.on("error", (err) => {
233
- res.writeHead(502, { "content-type": "text/plain" });
234
- res.end(`App "${app.id}" is not ready yet: ${err.message}`);
235
- });
236
-
237
- req.pipe(proxyReq);
238
- }
239
-
240
- function proxyUpgrade(
241
- app: WorkspaceApp,
242
- req: http.IncomingMessage,
243
- socket: net.Socket,
244
- head: Buffer,
245
- ): void {
246
- const target = net.connect(app.port, "127.0.0.1", () => {
247
- const headers = Object.entries({
248
- ...req.headers,
249
- host: `127.0.0.1:${app.port}`,
250
- })
251
- .flatMap(([key, value]) =>
252
- Array.isArray(value)
253
- ? value.map((item) => `${key}: ${item}`)
254
- : [`${key}: ${value ?? ""}`],
255
- )
256
- .join("\r\n");
257
- target.write(
258
- `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n${headers}\r\n\r\n`,
259
- );
260
- if (head.length) target.write(head);
261
- socket.pipe(target).pipe(socket);
262
- });
263
-
264
- target.on("error", () => socket.destroy());
265
- }
266
-
267
- let shuttingDown = false;
268
- let workspaceStarted = false;
269
-
270
- function startWorkspaceProcesses(): void {
271
- if (workspaceStarted) return;
272
- workspaceStarted = true;
273
- for (const app of apps) startApp(app);
274
- try {
275
- fs.watch(appsDir, { recursive: true }, scheduleSync);
276
- } catch {
277
- // Some platforms do not support recursive directory watches.
278
- }
279
- setInterval(syncApps, 2_000).unref();
280
- }
281
-
282
- function openBrowser(url: string): void {
283
- if (process.env.WORKSPACE_NO_OPEN === "1") return;
284
- const command =
285
- process.platform === "darwin"
286
- ? "open"
287
- : process.platform === "win32"
288
- ? "cmd"
289
- : "xdg-open";
290
- const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
291
- const child = spawn(command, args, {
292
- stdio: "ignore",
293
- detached: true,
294
- });
295
- child.unref();
296
- }
297
-
298
- const server = http.createServer((req, res) => {
299
- if (req.url === "/" || req.url === "/index.html") {
300
- res.writeHead(302, { location: `/${defaultApp}` });
301
- res.end();
302
- return;
303
- }
304
-
305
- if (req.url === "/_workspace/apps") {
306
- res.writeHead(200, { "content-type": "application/json" });
307
- res.end(
308
- JSON.stringify(
309
- apps.map((app) => ({
310
- id: app.id,
311
- name: app.name,
312
- path: `/${app.id}`,
313
- port: app.port,
314
- })),
315
- ),
316
- );
317
- return;
318
- }
319
-
320
- const app = appForRequest(req);
321
- if (!app) {
322
- res.writeHead(404, { "content-type": "text/html" });
323
- res.end(renderIndex());
324
- return;
325
- }
326
- proxyHttp(app, req, res);
327
- });
328
-
329
- server.on("upgrade", (req, socket, head) => {
330
- const app = appForRequest(req);
331
- if (!app) {
332
- socket.destroy();
333
- return;
334
- }
335
- proxyUpgrade(app, req, socket, head);
336
- });
337
-
338
- function listen(port: number, attempts = 20): void {
339
- server.once("error", (err: NodeJS.ErrnoException) => {
340
- if (err.code === "EADDRINUSE" && attempts > 0) {
341
- listen(port + 1, attempts - 1);
342
- return;
343
- }
344
- console.error(`[workspace] Could not start gateway: ${err.message}`);
345
- process.exit(1);
346
- });
347
- server.listen(port, gatewayHost, () => {
348
- const address = server.address();
349
- const actualPort =
350
- typeof address === "object" && address ? address.port : port;
351
- gatewayUrl = `http://${gatewayHost}:${actualPort}`;
352
- console.log(`[workspace] Gateway: http://${gatewayHost}:${actualPort}`);
353
- console.log(
354
- `[workspace] Default: http://${gatewayHost}:${actualPort}/${defaultApp}`,
355
- );
356
- for (const app of apps) {
357
- console.log(`[workspace] ${app.id}: /${app.id} -> 127.0.0.1:${app.port}`);
358
- }
359
- startWorkspaceProcesses();
360
- openBrowser(`http://${gatewayHost}:${actualPort}/${defaultApp}`);
361
- });
362
- }
363
-
364
- function shutdown(): void {
365
- if (shuttingDown) return;
366
- shuttingDown = true;
367
- server.close();
368
- for (const app of apps) {
369
- app.process?.kill("SIGTERM");
370
- }
371
- setTimeout(() => process.exit(0), 300).unref();
372
- }
373
-
374
- process.on("SIGINT", shutdown);
375
- process.on("SIGTERM", shutdown);
376
-
377
- listen(requestedPort);