@agentuity/cli 2.0.10 → 2.0.12
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/dist/cache/resource-region.d.ts.map +1 -1
- package/dist/cache/resource-region.js +48 -25
- package/dist/cache/resource-region.js.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.js +4 -4
- package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +20 -0
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +62 -4
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/index.d.ts +0 -1
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +0 -1
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/static-renderer.d.ts +17 -0
- package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
- package/dist/cmd/build/vite/static-renderer.js +18 -6
- package/dist/cmd/build/vite/static-renderer.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.js +34 -27
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.d.ts +9 -0
- package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.js +5 -1
- package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +12 -1
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite/ws-proxy.d.ts +15 -1
- package/dist/cmd/build/vite/ws-proxy.d.ts.map +1 -1
- package/dist/cmd/build/vite/ws-proxy.js +33 -0
- package/dist/cmd/build/vite/ws-proxy.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +98 -39
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/create.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/delete.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/list.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/restore.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/restore.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/restore.js.map +1 -1
- package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/create.js +13 -4
- package/dist/cmd/cloud/sandbox/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.js +3 -4
- package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/env.js +3 -5
- package/dist/cmd/cloud/sandbox/env.js.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +114 -41
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.js +3 -5
- package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/cp.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/cp.js +61 -113
- package/dist/cmd/cloud/sandbox/fs/cp.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/download.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/download.js +11 -22
- package/dist/cmd/cloud/sandbox/fs/download.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/ls.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/ls.js +3 -5
- package/dist/cmd/cloud/sandbox/fs/ls.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/mkdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/mkdir.js +3 -5
- package/dist/cmd/cloud/sandbox/fs/mkdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rm.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rm.js +3 -5
- package/dist/cmd/cloud/sandbox/fs/rm.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rmdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rmdir.js +3 -5
- package/dist/cmd/cloud/sandbox/fs/rmdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/upload.js +7 -8
- package/dist/cmd/cloud/sandbox/fs/upload.js.map +1 -1
- package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/get.js +21 -7
- package/dist/cmd/cloud/sandbox/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/create.js +3 -4
- package/dist/cmd/cloud/sandbox/job/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/destroy.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/destroy.js +3 -4
- package/dist/cmd/cloud/sandbox/job/destroy.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/get.js +3 -4
- package/dist/cmd/cloud/sandbox/job/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/list.js +3 -4
- package/dist/cmd/cloud/sandbox/job/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/logs.js +4 -4
- package/dist/cmd/cloud/sandbox/job/logs.js.map +1 -1
- package/dist/cmd/cloud/sandbox/pause.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/pause.js +21 -5
- package/dist/cmd/cloud/sandbox/pause.js.map +1 -1
- package/dist/cmd/cloud/sandbox/resume.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/resume.js +3 -4
- package/dist/cmd/cloud/sandbox/resume.js.map +1 -1
- package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/run.js +36 -7
- package/dist/cmd/cloud/sandbox/run.js.map +1 -1
- package/dist/cmd/cloud/sandbox/util.d.ts +19 -0
- package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/util.js +40 -2
- package/dist/cmd/cloud/sandbox/util.js.map +1 -1
- package/dist/cmd/coder/create.d.ts.map +1 -1
- package/dist/cmd/coder/create.js +18 -0
- package/dist/cmd/coder/create.js.map +1 -1
- package/dist/cmd/coder/index.d.ts.map +1 -1
- package/dist/cmd/coder/index.js +4 -0
- package/dist/cmd/coder/index.js.map +1 -1
- package/dist/cmd/coder/start.d.ts.map +1 -1
- package/dist/cmd/coder/start.js +52 -1
- package/dist/cmd/coder/start.js.map +1 -1
- package/dist/cmd/coder/tui-init.js +1 -1
- package/dist/cmd/coder/tui-init.js.map +1 -1
- package/dist/cmd/coder/update.d.ts.map +1 -1
- package/dist/cmd/coder/update.js +21 -1
- package/dist/cmd/coder/update.js.map +1 -1
- package/dist/cmd/coder/workspace/create.d.ts.map +1 -1
- package/dist/cmd/coder/workspace/create.js +57 -13
- package/dist/cmd/coder/workspace/create.js.map +1 -1
- package/dist/cmd/coder/workspace/index.d.ts.map +1 -1
- package/dist/cmd/coder/workspace/index.js +1 -1
- package/dist/cmd/coder/workspace/index.js.map +1 -1
- package/dist/cmd/coder/workspace/list.js +2 -2
- package/dist/cmd/coder/workspace/list.js.map +1 -1
- package/dist/cmd/dev/dev-lock.d.ts.map +1 -1
- package/dist/cmd/dev/dev-lock.js +43 -17
- package/dist/cmd/dev/dev-lock.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +211 -125
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/process-manager.d.ts +41 -1
- package/dist/cmd/dev/process-manager.d.ts.map +1 -1
- package/dist/cmd/dev/process-manager.js +160 -31
- package/dist/cmd/dev/process-manager.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +0 -2
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/cmd/project/index.d.ts.map +1 -1
- package/dist/cmd/project/index.js +0 -3
- package/dist/cmd/project/index.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +0 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +1 -124
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +7 -7
- package/src/cache/resource-region.ts +68 -44
- package/src/cmd/ai/prompt/web.md +43 -17
- package/src/cmd/build/vite/agent-discovery.ts +4 -4
- package/src/cmd/build/vite/bun-dev-server.ts +92 -6
- package/src/cmd/build/vite/index.ts +0 -1
- package/src/cmd/build/vite/static-renderer.ts +18 -7
- package/src/cmd/build/vite/vite-asset-server-config.ts +37 -27
- package/src/cmd/build/vite/vite-asset-server.ts +5 -1
- package/src/cmd/build/vite/vite-builder.ts +12 -1
- package/src/cmd/build/vite/ws-proxy.ts +52 -3
- package/src/cmd/cloud/deploy.ts +117 -49
- package/src/cmd/cloud/sandbox/checkpoint/create.ts +10 -4
- package/src/cmd/cloud/sandbox/checkpoint/delete.ts +10 -4
- package/src/cmd/cloud/sandbox/checkpoint/list.ts +10 -4
- package/src/cmd/cloud/sandbox/checkpoint/restore.ts +10 -4
- package/src/cmd/cloud/sandbox/create.ts +14 -4
- package/src/cmd/cloud/sandbox/delete.ts +10 -4
- package/src/cmd/cloud/sandbox/env.ts +10 -5
- package/src/cmd/cloud/sandbox/exec.ts +157 -42
- package/src/cmd/cloud/sandbox/execution/list.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/cp.ts +94 -126
- package/src/cmd/cloud/sandbox/fs/download.ts +18 -25
- package/src/cmd/cloud/sandbox/fs/ls.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/mkdir.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/rm.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/rmdir.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/upload.ts +14 -8
- package/src/cmd/cloud/sandbox/get.ts +28 -7
- package/src/cmd/cloud/sandbox/job/create.ts +10 -4
- package/src/cmd/cloud/sandbox/job/destroy.ts +10 -4
- package/src/cmd/cloud/sandbox/job/get.ts +10 -4
- package/src/cmd/cloud/sandbox/job/list.ts +10 -4
- package/src/cmd/cloud/sandbox/job/logs.ts +11 -4
- package/src/cmd/cloud/sandbox/pause.ts +31 -5
- package/src/cmd/cloud/sandbox/resume.ts +10 -4
- package/src/cmd/cloud/sandbox/run.ts +49 -11
- package/src/cmd/cloud/sandbox/util.ts +63 -2
- package/src/cmd/coder/create.ts +24 -1
- package/src/cmd/coder/index.ts +4 -0
- package/src/cmd/coder/start.ts +63 -1
- package/src/cmd/coder/tui-init.ts +1 -1
- package/src/cmd/coder/update.ts +18 -1
- package/src/cmd/coder/workspace/create.ts +84 -15
- package/src/cmd/coder/workspace/index.ts +3 -1
- package/src/cmd/coder/workspace/list.ts +2 -2
- package/src/cmd/dev/dev-lock.ts +50 -16
- package/src/cmd/dev/index.ts +249 -134
- package/src/cmd/dev/process-manager.ts +173 -33
- package/src/cmd/project/create.ts +0 -2
- package/src/cmd/project/index.ts +0 -3
- package/src/cmd/project/template-flow.ts +0 -147
- package/dist/cmd/build/vite/public-asset-path-plugin.d.ts +0 -45
- package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +0 -1
- package/dist/cmd/build/vite/public-asset-path-plugin.js +0 -166
- package/dist/cmd/build/vite/public-asset-path-plugin.js.map +0 -1
- package/dist/cmd/project/auth/generate.d.ts +0 -5
- package/dist/cmd/project/auth/generate.d.ts.map +0 -1
- package/dist/cmd/project/auth/generate.js +0 -102
- package/dist/cmd/project/auth/generate.js.map +0 -1
- package/dist/cmd/project/auth/index.d.ts +0 -2
- package/dist/cmd/project/auth/index.d.ts.map +0 -1
- package/dist/cmd/project/auth/index.js +0 -21
- package/dist/cmd/project/auth/index.js.map +0 -1
- package/dist/cmd/project/auth/init.d.ts +0 -2
- package/dist/cmd/project/auth/init.d.ts.map +0 -1
- package/dist/cmd/project/auth/init.js +0 -213
- package/dist/cmd/project/auth/init.js.map +0 -1
- package/dist/cmd/project/auth/shared.d.ts +0 -93
- package/dist/cmd/project/auth/shared.d.ts.map +0 -1
- package/dist/cmd/project/auth/shared.js +0 -475
- package/dist/cmd/project/auth/shared.js.map +0 -1
- package/src/cmd/build/vite/public-asset-path-plugin.ts +0 -209
- package/src/cmd/project/auth/generate.ts +0 -116
- package/src/cmd/project/auth/index.ts +0 -21
- package/src/cmd/project/auth/init.ts +0 -256
- package/src/cmd/project/auth/shared.ts +0 -591
|
@@ -17,14 +17,35 @@ import type { Logger } from '../../../types';
|
|
|
17
17
|
import { getAgentEnv } from '../../../agent-detection';
|
|
18
18
|
import { createServer as createNetServer } from 'node:net';
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Minimal handle for the spawned Bun subprocess. Mirrors the shape used
|
|
22
|
+
* elsewhere (procManager, killBunSubprocess) so callers can register
|
|
23
|
+
* the process with their tracking layer without depending on Bun-specific
|
|
24
|
+
* Subprocess types.
|
|
25
|
+
*/
|
|
26
|
+
export interface BunSubprocessHandle {
|
|
27
|
+
kill: (signal?: number | NodeJS.Signals) => void;
|
|
28
|
+
exitCode: number | null;
|
|
29
|
+
pid?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
export interface BunDevServerOptions {
|
|
21
33
|
rootDir: string;
|
|
22
34
|
port?: number;
|
|
23
35
|
logger: Logger;
|
|
24
|
-
vitePort: number;
|
|
36
|
+
vitePort: number; // Kept for backward compatibility — no longer used internally
|
|
25
37
|
inspect?: boolean;
|
|
26
38
|
inspectWait?: boolean;
|
|
27
39
|
inspectBrk?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Optional callback fired the moment `Bun.spawn` returns, BEFORE the
|
|
42
|
+
* readiness wait. Lets callers register the subprocess with a process
|
|
43
|
+
* manager / shutdown handler immediately, eliminating the multi-second
|
|
44
|
+
* window during which a SIGINT could orphan the child.
|
|
45
|
+
*
|
|
46
|
+
* If this throws, the subprocess is killed and the error is rethrown.
|
|
47
|
+
*/
|
|
48
|
+
onSpawn?: (proc: BunSubprocessHandle) => void;
|
|
28
49
|
}
|
|
29
50
|
|
|
30
51
|
export interface BunDevServerResult {
|
|
@@ -311,9 +332,17 @@ export function buildStartupErrorMessage(
|
|
|
311
332
|
* are re-evaluated.
|
|
312
333
|
*/
|
|
313
334
|
export async function startBunDevServer(options: BunDevServerOptions): Promise<BunDevServerResult> {
|
|
314
|
-
const {
|
|
315
|
-
|
|
316
|
-
|
|
335
|
+
const {
|
|
336
|
+
rootDir,
|
|
337
|
+
port = 3500,
|
|
338
|
+
logger,
|
|
339
|
+
vitePort: _vitePort,
|
|
340
|
+
inspect,
|
|
341
|
+
inspectWait,
|
|
342
|
+
inspectBrk,
|
|
343
|
+
} = options;
|
|
344
|
+
|
|
345
|
+
logger.debug('Starting Bun dev server (port %d)...', port);
|
|
317
346
|
|
|
318
347
|
const appPath = `${rootDir}/app.ts`;
|
|
319
348
|
|
|
@@ -391,6 +420,15 @@ export async function startBunDevServer(options: BunDevServerOptions): Promise<B
|
|
|
391
420
|
PORT: String(port),
|
|
392
421
|
FORCE_COLOR: '1', // Enable colors even though stdout is piped
|
|
393
422
|
},
|
|
423
|
+
// Make the child a process-group leader so the CLI's procManager /
|
|
424
|
+
// killBunSubprocess() can signal the whole tree via process.kill(-pid, ...).
|
|
425
|
+
// Without detached:true, bun --hot and any workers it spawns share our
|
|
426
|
+
// process group, process.kill(-pid) fails with EPERM (not a group leader),
|
|
427
|
+
// and we fall back to a direct PID kill that leaves children orphaned.
|
|
428
|
+
//
|
|
429
|
+
// We intentionally do NOT call .unref() here — the parent still tracks
|
|
430
|
+
// and drives the child's lifecycle, and piped stdio is unaffected.
|
|
431
|
+
detached: true,
|
|
394
432
|
});
|
|
395
433
|
|
|
396
434
|
// Start capturing streams in the background (don't await, we need to check server readiness)
|
|
@@ -404,6 +442,35 @@ export async function startBunDevServer(options: BunDevServerOptions): Promise<B
|
|
|
404
442
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
405
443
|
(globalThis as any).__AGENTUITY_BUN_SUBPROCESS__ = bunProcess;
|
|
406
444
|
|
|
445
|
+
// Notify caller IMMEDIATELY so the subprocess can be registered with the
|
|
446
|
+
// process manager before the readiness wait below. Without this, a SIGINT
|
|
447
|
+
// during the up-to-5s readiness wait would leave the subprocess unmanaged
|
|
448
|
+
// (only the synchronous exit-handler safety net would catch it).
|
|
449
|
+
if (options.onSpawn) {
|
|
450
|
+
try {
|
|
451
|
+
options.onSpawn(bunProcess as BunSubprocessHandle);
|
|
452
|
+
} catch (err) {
|
|
453
|
+
logger.debug('onSpawn callback threw, killing subprocess: %s', err);
|
|
454
|
+
const pid = bunProcess.pid;
|
|
455
|
+
try {
|
|
456
|
+
if (typeof pid === 'number' && pid > 1 && process.platform !== 'win32') {
|
|
457
|
+
try {
|
|
458
|
+
process.kill(-pid, 'SIGKILL');
|
|
459
|
+
} catch {
|
|
460
|
+
bunProcess.kill('SIGKILL');
|
|
461
|
+
}
|
|
462
|
+
} else {
|
|
463
|
+
bunProcess.kill('SIGKILL');
|
|
464
|
+
}
|
|
465
|
+
} catch {
|
|
466
|
+
// Best effort
|
|
467
|
+
}
|
|
468
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
469
|
+
(globalThis as any).__AGENTUITY_BUN_SUBPROCESS__ = undefined;
|
|
470
|
+
throw err;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
407
474
|
// Wait for server to start listening
|
|
408
475
|
const maxRetries = 50;
|
|
409
476
|
const retryDelay = 100;
|
|
@@ -436,8 +503,28 @@ export async function startBunDevServer(options: BunDevServerOptions): Promise<B
|
|
|
436
503
|
}
|
|
437
504
|
|
|
438
505
|
if (!serverReady) {
|
|
506
|
+
// The subprocess is spawned with detached:true and is therefore the
|
|
507
|
+
// leader of its own process group. bunProcess.kill() only targets the
|
|
508
|
+
// direct PID, which would leave any workers/grandchildren orphaned.
|
|
509
|
+
// Signal the whole process group with SIGKILL and fall back to the
|
|
510
|
+
// handle's kill() if the group-kill fails (EPERM, not-group-leader,
|
|
511
|
+
// or Windows where negative PIDs aren't supported).
|
|
512
|
+
const pid = bunProcess.pid;
|
|
439
513
|
try {
|
|
440
|
-
|
|
514
|
+
if (typeof pid === 'number' && pid > 1 && process.platform !== 'win32') {
|
|
515
|
+
try {
|
|
516
|
+
process.kill(-pid, 'SIGKILL');
|
|
517
|
+
} catch (groupErr) {
|
|
518
|
+
logger.debug(
|
|
519
|
+
'Process-group SIGKILL failed for pid %d (%s), falling back to direct kill',
|
|
520
|
+
pid,
|
|
521
|
+
(groupErr as NodeJS.ErrnoException).code ?? groupErr
|
|
522
|
+
);
|
|
523
|
+
bunProcess.kill('SIGKILL');
|
|
524
|
+
}
|
|
525
|
+
} else {
|
|
526
|
+
bunProcess.kill('SIGKILL');
|
|
527
|
+
}
|
|
441
528
|
} catch (err) {
|
|
442
529
|
logger.debug('Error killing subprocess during startup failure: %s', err);
|
|
443
530
|
}
|
|
@@ -452,7 +539,6 @@ export async function startBunDevServer(options: BunDevServerOptions): Promise<B
|
|
|
452
539
|
}
|
|
453
540
|
|
|
454
541
|
logger.debug(`Bun dev server started on http://127.0.0.1:${port} (--hot mode)`);
|
|
455
|
-
logger.debug(`Proxied to Vite:${vitePort}`);
|
|
456
542
|
|
|
457
543
|
return { bunServerPort: port };
|
|
458
544
|
}
|
|
@@ -18,7 +18,7 @@ import { mkdirSync, writeFileSync, readFileSync, existsSync, rmSync } from 'node
|
|
|
18
18
|
import type { Logger } from '../../../types';
|
|
19
19
|
|
|
20
20
|
/** Minimal shape of a TanStack Router route tree node. */
|
|
21
|
-
interface RouteTreeNode {
|
|
21
|
+
export interface RouteTreeNode {
|
|
22
22
|
path?: string;
|
|
23
23
|
options?: { path?: string };
|
|
24
24
|
children?: Record<string, RouteTreeNode>;
|
|
@@ -32,7 +32,7 @@ interface RouteTreeNode {
|
|
|
32
32
|
* under layout routes have relative paths (e.g., '/key-value' under a
|
|
33
33
|
* '/reference/api' layout should resolve to '/reference/api/key-value').
|
|
34
34
|
*/
|
|
35
|
-
function extractRoutePaths(node: RouteTreeNode): string[] {
|
|
35
|
+
export function extractRoutePaths(node: RouteTreeNode): string[] {
|
|
36
36
|
const paths = new Set<string>();
|
|
37
37
|
|
|
38
38
|
function walk(route: RouteTreeNode, parentPath: string) {
|
|
@@ -40,18 +40,29 @@ function extractRoutePaths(node: RouteTreeNode): string[] {
|
|
|
40
40
|
|
|
41
41
|
// Build the full path by accumulating segments from parent routes.
|
|
42
42
|
// - Layout routes have no path (undefined) and don't contribute to the URL.
|
|
43
|
-
// - Index routes have path '/' and resolve to the parent path itself
|
|
43
|
+
// - Index routes have path '/' and resolve to the parent path itself
|
|
44
|
+
// (e.g., the '/' child of the root is the landing page; the '/' child
|
|
45
|
+
// of a '/docs' layout is '/docs'). They do not append anything.
|
|
44
46
|
// - Leaf/layout routes have paths like '/reference/api' or '/key-value'.
|
|
45
47
|
let currentPath = parentPath;
|
|
46
|
-
|
|
48
|
+
let isIndexRoute = false;
|
|
49
|
+
if (segment === '/') {
|
|
50
|
+
isIndexRoute = true;
|
|
51
|
+
} else if (segment) {
|
|
47
52
|
// Non-root segment: append to parent path.
|
|
48
53
|
// Segments always start with '/' (TanStack Router convention).
|
|
49
54
|
currentPath = parentPath === '/' ? segment : parentPath + segment;
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
// Decide which URL, if any, to emit for this node.
|
|
58
|
+
// - Index routes emit the parent URL, defaulting to '/' when the parent
|
|
59
|
+
// itself is pathless (i.e., the site root). Without this, a
|
|
60
|
+
// `createFileRoute('/')` route is never pre-rendered and the
|
|
61
|
+
// landing page ships with the unreplaced <!--app-html--> placeholder.
|
|
62
|
+
// - Non-index routes emit their own accumulated path.
|
|
63
|
+
const emit = isIndexRoute ? parentPath || '/' : currentPath;
|
|
64
|
+
if (emit && !emit.includes('$')) {
|
|
65
|
+
const normalized = emit === '/' ? '/' : emit.replace(/\/+$/, '');
|
|
55
66
|
if (normalized) {
|
|
56
67
|
paths.add(normalized);
|
|
57
68
|
}
|
|
@@ -22,6 +22,37 @@ export interface GenerateAssetServerConfigOptions {
|
|
|
22
22
|
liveHostname?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Shared proxy configuration for backend routes.
|
|
27
|
+
*
|
|
28
|
+
* Includes `configure` callback that gracefully handles ECONNREFUSED errors
|
|
29
|
+
* when the Bun backend isn't ready yet (startup race condition or brief
|
|
30
|
+
* disconnect during --hot reload). Instead of logging noisy errors, the
|
|
31
|
+
* proxy returns 503 Service Unavailable with a retry hint.
|
|
32
|
+
*/
|
|
33
|
+
function backendProxyOptions(backendPort: number) {
|
|
34
|
+
return {
|
|
35
|
+
target: `http://127.0.0.1:${backendPort}`,
|
|
36
|
+
changeOrigin: true,
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
configure: (proxy: any, _options: any) => {
|
|
39
|
+
proxy.on('error', (err: Error & { code?: string }, _req: any, res: any) => {
|
|
40
|
+
if (err.code === 'ECONNREFUSED' && res && !res.writableEnded) {
|
|
41
|
+
res.statusCode = 503;
|
|
42
|
+
res.setHeader('Content-Type', 'application/json');
|
|
43
|
+
res.end(
|
|
44
|
+
JSON.stringify({
|
|
45
|
+
error: 'Backend unavailable',
|
|
46
|
+
message: 'The Bun backend is not ready yet. Retrying shortly...',
|
|
47
|
+
retry: true,
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
25
56
|
/**
|
|
26
57
|
* Vite plugin that injects analytics scripts in dev mode.
|
|
27
58
|
*
|
|
@@ -95,7 +126,7 @@ function spaFallbackPlugin(rootDir: string, routePaths: string[], workbenchPath?
|
|
|
95
126
|
const isDocumentRequest = secFetchDest === 'document' || accept.includes('text/html');
|
|
96
127
|
|
|
97
128
|
// Skip file requests (have an extension)
|
|
98
|
-
if (pathname !== '/' && /\.[
|
|
129
|
+
if (pathname !== '/' && /\.[\w-]+$/.test(pathname)) return next();
|
|
99
130
|
|
|
100
131
|
// For non-document requests, only allow root path fallback.
|
|
101
132
|
// (e.g. don't turn module/script fetches into HTML accidentally)
|
|
@@ -241,37 +272,19 @@ export async function generateAssetServerConfig(
|
|
|
241
272
|
proxy: {
|
|
242
273
|
// User-defined route mounts (from createApp({ router }))
|
|
243
274
|
...Object.fromEntries(
|
|
244
|
-
routePaths.map((routePath) => [
|
|
245
|
-
routePath,
|
|
246
|
-
{
|
|
247
|
-
target: `http://127.0.0.1:${backendPort}`,
|
|
248
|
-
changeOrigin: true,
|
|
249
|
-
},
|
|
250
|
-
])
|
|
275
|
+
routePaths.map((routePath) => [routePath, backendProxyOptions(backendPort)])
|
|
251
276
|
),
|
|
252
277
|
// Agentuity system routes (workbench API, health, analytics, etc.)
|
|
253
|
-
'/_agentuity':
|
|
254
|
-
target: `http://127.0.0.1:${backendPort}`,
|
|
255
|
-
changeOrigin: true,
|
|
256
|
-
},
|
|
278
|
+
'/_agentuity': backendProxyOptions(backendPort),
|
|
257
279
|
// Workbench UI route (served by Bun, references /@fs/* paths handled by Vite)
|
|
258
280
|
...(workbenchPath
|
|
259
281
|
? {
|
|
260
|
-
[workbenchPath]:
|
|
261
|
-
target: `http://127.0.0.1:${backendPort}`,
|
|
262
|
-
changeOrigin: true,
|
|
263
|
-
},
|
|
282
|
+
[workbenchPath]: backendProxyOptions(backendPort),
|
|
264
283
|
}
|
|
265
284
|
: {}),
|
|
266
285
|
// Legacy health check routes
|
|
267
|
-
'/_health':
|
|
268
|
-
|
|
269
|
-
changeOrigin: true,
|
|
270
|
-
},
|
|
271
|
-
'/_idle': {
|
|
272
|
-
target: `http://127.0.0.1:${backendPort}`,
|
|
273
|
-
changeOrigin: true,
|
|
274
|
-
},
|
|
286
|
+
'/_health': backendProxyOptions(backendPort),
|
|
287
|
+
'/_idle': backendProxyOptions(backendPort),
|
|
275
288
|
},
|
|
276
289
|
|
|
277
290
|
// HMR works natively — Vite is the primary server, no proxy needed
|
|
@@ -296,13 +309,10 @@ export async function generateAssetServerConfig(
|
|
|
296
309
|
// Agentuity-specific plugins (Vite loads user plugins from vite.config.ts automatically)
|
|
297
310
|
plugins: await (async () => {
|
|
298
311
|
const { browserEnvPlugin } = await import('./browser-env-plugin');
|
|
299
|
-
const { publicAssetPathPlugin } = await import('./public-asset-path-plugin');
|
|
300
312
|
|
|
301
313
|
return [
|
|
302
314
|
// Browser env plugin to map process.env to import.meta.env
|
|
303
315
|
browserEnvPlugin(),
|
|
304
|
-
// Warn about incorrect public asset paths in dev mode
|
|
305
|
-
publicAssetPathPlugin({ warnInDev: true }),
|
|
306
316
|
// Inject analytics scripts in dev HTML
|
|
307
317
|
devAnalyticsPlugin(),
|
|
308
318
|
// SPA fallback: serve src/web/index.html for navigation requests
|
|
@@ -50,8 +50,12 @@ function isPortAvailable(port: number, host: string): Promise<boolean> {
|
|
|
50
50
|
/**
|
|
51
51
|
* Find an available port starting from the preferred port.
|
|
52
52
|
* Tries incrementing ports up to maxAttempts times.
|
|
53
|
+
*
|
|
54
|
+
* Exported so the dev command can pre-resolve the Vite port before
|
|
55
|
+
* starting the Bun backend (env vars like AGENTUITY_BASE_URL need
|
|
56
|
+
* the real port before Bun initializes CORS).
|
|
53
57
|
*/
|
|
54
|
-
async function findAvailablePort(
|
|
58
|
+
export async function findAvailablePort(
|
|
55
59
|
preferredPort: number,
|
|
56
60
|
host: string = '127.0.0.1',
|
|
57
61
|
maxAttempts: number = 20
|
|
@@ -227,6 +227,7 @@ import { join } from 'node:path';
|
|
|
227
227
|
export default defineConfig({
|
|
228
228
|
plugins: [react()],
|
|
229
229
|
root: '.',
|
|
230
|
+
publicDir: 'src/web/public',
|
|
230
231
|
build: {
|
|
231
232
|
rollupOptions: {
|
|
232
233
|
input: join(__dirname, 'src/web/index.html'),
|
|
@@ -244,17 +245,27 @@ export default defineConfig({
|
|
|
244
245
|
? `https://${options.region === 'local' ? 'localstack-static-assets.t3.storageapi.dev' : 'cdn.agentuity.com'}/${options.deploymentId}/client/`
|
|
245
246
|
: undefined;
|
|
246
247
|
|
|
248
|
+
// Pass the user's vite.config.ts directly to the subprocess. We used to
|
|
249
|
+
// wrap it in an auto-generated `.agentuity/vite.client.config.ts` to
|
|
250
|
+
// merge a lint plugin in, but that wrapper added complexity (plugin-path
|
|
251
|
+
// resolution, a junk file in the deploy bundle) for a warning-only
|
|
252
|
+
// linter. If we need to inject plugins again, expose them as a published
|
|
253
|
+
// CLI export and have users add them in their own vite.config.ts.
|
|
247
254
|
const args = [
|
|
248
255
|
'bun',
|
|
249
256
|
'x',
|
|
250
257
|
'vite',
|
|
251
258
|
'build',
|
|
259
|
+
'--config',
|
|
260
|
+
viteConfigPath,
|
|
252
261
|
'--mode',
|
|
253
262
|
buildMode,
|
|
254
263
|
'--outDir',
|
|
255
264
|
clientOutDir,
|
|
265
|
+
// `warn` surfaces Vite warnings (e.g. large-chunk notices) without
|
|
266
|
+
// adding its own info-level chatter.
|
|
256
267
|
'--logLevel',
|
|
257
|
-
'
|
|
268
|
+
'warn',
|
|
258
269
|
'--clearScreen',
|
|
259
270
|
'false',
|
|
260
271
|
];
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
|
-
import { createServer, connect, type Server } from 'node:net';
|
|
36
|
+
import { createServer, connect, type Server, type Socket } from 'node:net';
|
|
37
37
|
import type { Logger } from '../../../types';
|
|
38
38
|
|
|
39
39
|
export interface WsProxyOptions {
|
|
@@ -48,18 +48,44 @@ export interface WsProxyOptions {
|
|
|
48
48
|
logger: Logger;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Front-door TCP proxy server.
|
|
53
|
+
*
|
|
54
|
+
* Extends `net.Server` with a `closeAll()` method that destroys all live
|
|
55
|
+
* client + upstream sockets and waits for the listening socket to close.
|
|
56
|
+
* The native `Server.close()` only stops accepting new connections — long-
|
|
57
|
+
* lived piped sockets (Vite HMR WebSocket, backend WS) keep the listener
|
|
58
|
+
* bound until they close on their own. During dev-mode shutdown we want
|
|
59
|
+
* the user-facing port released immediately, so cleanup paths should
|
|
60
|
+
* prefer `closeAll()` over `close()`.
|
|
61
|
+
*/
|
|
62
|
+
export interface WsProxyServer extends Server {
|
|
63
|
+
closeAll(): Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
|
|
51
66
|
/**
|
|
52
67
|
* Start a front-door TCP proxy that routes WebSocket upgrades to the Bun
|
|
53
68
|
* backend and everything else to Vite. Returns the `net.Server` instance.
|
|
54
69
|
*/
|
|
55
|
-
export function startWsProxy(options: WsProxyOptions): Promise<
|
|
70
|
+
export function startWsProxy(options: WsProxyOptions): Promise<WsProxyServer> {
|
|
56
71
|
const { port, vitePort, backendPort, routePaths, logger } = options;
|
|
57
72
|
|
|
58
73
|
// Prefixes whose WebSocket upgrades go to Bun instead of Vite
|
|
59
74
|
const wsPathPrefixes = ['/_agentuity', ...routePaths];
|
|
60
75
|
|
|
76
|
+
// Track every live socket pair so shutdown can drop them. Without this,
|
|
77
|
+
// `server.close()` waits for active connections to terminate by themselves
|
|
78
|
+
// (e.g. browser HMR WebSockets), which can keep the user-facing port bound
|
|
79
|
+
// for many seconds after dev mode exits.
|
|
80
|
+
const liveSockets = new Set<Socket>();
|
|
81
|
+
const trackSocket = (sock: Socket) => {
|
|
82
|
+
liveSockets.add(sock);
|
|
83
|
+
sock.once('close', () => liveSockets.delete(sock));
|
|
84
|
+
};
|
|
85
|
+
|
|
61
86
|
return new Promise((resolve, reject) => {
|
|
62
87
|
const server = createServer((socket) => {
|
|
88
|
+
trackSocket(socket);
|
|
63
89
|
let handled = false;
|
|
64
90
|
|
|
65
91
|
// Peek at the first chunk to decide where to route
|
|
@@ -87,6 +113,7 @@ export function startWsProxy(options: WsProxyOptions): Promise<Server> {
|
|
|
87
113
|
}
|
|
88
114
|
|
|
89
115
|
const target = connect(targetPort, '127.0.0.1');
|
|
116
|
+
trackSocket(target);
|
|
90
117
|
|
|
91
118
|
target.on('connect', () => {
|
|
92
119
|
target.write(firstChunk);
|
|
@@ -109,7 +136,29 @@ export function startWsProxy(options: WsProxyOptions): Promise<Server> {
|
|
|
109
136
|
socket.on('error', () => {
|
|
110
137
|
if (!handled) socket.destroy();
|
|
111
138
|
});
|
|
112
|
-
});
|
|
139
|
+
}) as WsProxyServer;
|
|
140
|
+
|
|
141
|
+
// Async close that destroys live sockets first, then waits for the
|
|
142
|
+
// listener to close. Idempotent: safe to call after the server has
|
|
143
|
+
// already been closed by other means.
|
|
144
|
+
server.closeAll = () => {
|
|
145
|
+
return new Promise<void>((resolveClose) => {
|
|
146
|
+
for (const sock of liveSockets) {
|
|
147
|
+
try {
|
|
148
|
+
if (!sock.destroyed) sock.destroy();
|
|
149
|
+
} catch {
|
|
150
|
+
// Best effort
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
liveSockets.clear();
|
|
154
|
+
|
|
155
|
+
if (!server.listening) {
|
|
156
|
+
resolveClose();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
server.close(() => resolveClose());
|
|
160
|
+
});
|
|
161
|
+
};
|
|
113
162
|
|
|
114
163
|
server.on('error', reject);
|
|
115
164
|
|