@townco/cli 0.1.118 → 0.1.120
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/commands/deploy.js
CHANGED
|
@@ -8,7 +8,6 @@ declare const _default: {
|
|
|
8
8
|
readonly prompt: string | undefined;
|
|
9
9
|
readonly port: number | undefined;
|
|
10
10
|
readonly noSession: true | undefined;
|
|
11
|
-
readonly proxy: true | undefined;
|
|
12
11
|
}, ["matched", string] | ["parsing", {
|
|
13
12
|
readonly command: "run";
|
|
14
13
|
readonly name: import("@optique/core").ValueParserResult<string> | undefined;
|
|
@@ -18,7 +17,6 @@ declare const _default: {
|
|
|
18
17
|
readonly prompt: [import("@optique/core").ValueParserResult<string> | undefined] | undefined;
|
|
19
18
|
readonly port: [import("@optique/core").ValueParserResult<number> | undefined] | undefined;
|
|
20
19
|
readonly noSession: [import("@optique/core").ValueParserResult<true> | undefined] | undefined;
|
|
21
|
-
readonly proxy: [import("@optique/core").ValueParserResult<true> | undefined] | undefined;
|
|
22
20
|
}] | undefined>;
|
|
23
21
|
impl: (def: {
|
|
24
22
|
readonly command: "run";
|
|
@@ -29,7 +27,6 @@ declare const _default: {
|
|
|
29
27
|
readonly prompt: string | undefined;
|
|
30
28
|
readonly port: number | undefined;
|
|
31
29
|
readonly noSession: true | undefined;
|
|
32
|
-
readonly proxy: true | undefined;
|
|
33
30
|
}) => unknown;
|
|
34
31
|
};
|
|
35
32
|
export default _default;
|
|
@@ -12,16 +12,14 @@ export default createCommand({
|
|
|
12
12
|
prompt: optional(argument(string({ metavar: "PROMPT" }))),
|
|
13
13
|
port: optional(option("-p", "--port", integer())),
|
|
14
14
|
noSession: optional(flag("--no-session")),
|
|
15
|
-
proxy: optional(flag("--proxy")),
|
|
16
15
|
}), { brief: message `Run an agent.` }),
|
|
17
|
-
impl: async ({ name, http, gui, cli, prompt, port, noSession
|
|
16
|
+
impl: async ({ name, http, gui, cli, prompt, port, noSession }) => {
|
|
18
17
|
const options = {
|
|
19
18
|
name,
|
|
20
19
|
http: http === true,
|
|
21
20
|
gui: gui === true,
|
|
22
21
|
cli: cli === true,
|
|
23
22
|
noSession: noSession === true,
|
|
24
|
-
proxy: proxy === true,
|
|
25
23
|
};
|
|
26
24
|
if (prompt !== null && prompt !== undefined) {
|
|
27
25
|
options.prompt = prompt;
|
package/dist/commands/run.d.ts
CHANGED
package/dist/commands/run.js
CHANGED
|
@@ -13,7 +13,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
13
13
|
import { LogsPane } from "../components/LogsPane.js";
|
|
14
14
|
import { TabbedOutput } from "../components/TabbedOutput.js";
|
|
15
15
|
import { ensurePortAvailable } from "../lib/port-utils.js";
|
|
16
|
-
import { createProxyServer } from "../lib/proxy-server.js";
|
|
17
16
|
function TuiRunner({ agentPath, workingDir, agentName, noSession, onExit, }) {
|
|
18
17
|
const [client, setClient] = useState(null);
|
|
19
18
|
const [error, setError] = useState(null);
|
|
@@ -83,15 +82,15 @@ function TuiRunner({ agentPath, workingDir, agentName, noSession, onExit, }) {
|
|
|
83
82
|
], [client, error, workingDir]);
|
|
84
83
|
return (_jsx(TabbedOutput, { processes: [], customTabs: customTabs, onExit: onExit }));
|
|
85
84
|
}
|
|
86
|
-
function GuiRunner({ agentProcess, guiProcess, agentPort,
|
|
85
|
+
function GuiRunner({ agentProcess, guiProcess, agentPort, agentPath, logger, onExit, }) {
|
|
87
86
|
const browserOpenedRef = useRef(false);
|
|
88
|
-
const handlePortDetected = useCallback((processIndex,
|
|
87
|
+
const handlePortDetected = useCallback((processIndex, port) => {
|
|
89
88
|
// Process index 1 is the GUI process
|
|
90
89
|
if (processIndex === 1) {
|
|
91
|
-
// Open browser once we know the
|
|
90
|
+
// Open browser once we know the actual port
|
|
92
91
|
if (!browserOpenedRef.current) {
|
|
93
92
|
browserOpenedRef.current = true;
|
|
94
|
-
const guiUrl = `http://localhost:${
|
|
93
|
+
const guiUrl = `http://localhost:${port}`;
|
|
95
94
|
logger.info("Opening browser", { url: guiUrl });
|
|
96
95
|
open(guiUrl).catch((error) => {
|
|
97
96
|
logger.warn("Could not automatically open browser", {
|
|
@@ -101,7 +100,7 @@ function GuiRunner({ agentProcess, guiProcess, agentPort, browserPort, agentPath
|
|
|
101
100
|
});
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
|
-
}, [logger
|
|
103
|
+
}, [logger]);
|
|
105
104
|
// Memoize processes array based only on actual process objects and initial ports
|
|
106
105
|
// Don't include guiPort as dependency to prevent re-creating array when port is detected
|
|
107
106
|
// TabbedOutput will update the displayed port internally via onPortDetected callback
|
|
@@ -375,7 +374,7 @@ async function runCliMode(options) {
|
|
|
375
374
|
}
|
|
376
375
|
}
|
|
377
376
|
export async function runCommand(options) {
|
|
378
|
-
const { name, http = false, gui = false, cli = false, prompt, port = 3100, noSession = false,
|
|
377
|
+
const { name, http = false, gui = false, cli = false, prompt, port = 3100, noSession = false, } = options;
|
|
379
378
|
// Check if we're inside a Town project
|
|
380
379
|
const projectRoot = await isInsideTownProject();
|
|
381
380
|
if (projectRoot === null) {
|
|
@@ -513,15 +512,9 @@ export async function runCommand(options) {
|
|
|
513
512
|
}
|
|
514
513
|
// Ensure agent and GUI ports are available (debugger ports already checked above)
|
|
515
514
|
const guiPort = 5173;
|
|
516
|
-
const proxyPort = process.env.TOWN_AGENT_PROXY_PORT
|
|
517
|
-
? Number.parseInt(process.env.TOWN_AGENT_PROXY_PORT, 10)
|
|
518
|
-
: 3500;
|
|
519
515
|
try {
|
|
520
516
|
await ensurePortAvailable(port, "agent HTTP server");
|
|
521
517
|
await ensurePortAvailable(guiPort, "GUI dev server");
|
|
522
|
-
if (proxy) {
|
|
523
|
-
await ensurePortAvailable(proxyPort, "reverse proxy");
|
|
524
|
-
}
|
|
525
518
|
}
|
|
526
519
|
catch (error) {
|
|
527
520
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -531,18 +524,10 @@ export async function runCommand(options) {
|
|
|
531
524
|
logger.info("Starting GUI mode", {
|
|
532
525
|
agentPort: port,
|
|
533
526
|
guiPort,
|
|
534
|
-
...(proxy ? { proxyPort } : {}),
|
|
535
527
|
});
|
|
536
528
|
console.log(`Starting agent "${name}" with GUI...`);
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
console.log(` - GUI: http://localhost:${proxyPort}/`);
|
|
540
|
-
console.log(` - Agent API: http://localhost:${proxyPort}/rpc\n`);
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
console.log(`GUI: http://localhost:${guiPort}/`);
|
|
544
|
-
console.log(`Agent API: http://localhost:${port}/rpc\n`);
|
|
545
|
-
}
|
|
529
|
+
console.log(`Agent HTTP server will run on port ${port}`);
|
|
530
|
+
console.log(`GUI dev server will run on port ${guiPort}\n`);
|
|
546
531
|
// Set stdin to raw mode for Ink
|
|
547
532
|
if (process.stdin.isTTY) {
|
|
548
533
|
process.stdin.setRawMode(true);
|
|
@@ -566,17 +551,13 @@ export async function runCommand(options) {
|
|
|
566
551
|
if (process.env.BIND_HOST) {
|
|
567
552
|
viteArgs.push("--host", process.env.BIND_HOST);
|
|
568
553
|
}
|
|
569
|
-
// When proxy is enabled, GUI talks to proxy; otherwise directly to agent
|
|
570
|
-
const agentUrl = proxy
|
|
571
|
-
? `http://localhost:${proxyPort}`
|
|
572
|
-
: `http://localhost:${port}`;
|
|
573
554
|
const guiProcess = spawn("bunx", viteArgs, {
|
|
574
555
|
cwd: guiPath,
|
|
575
556
|
stdio: ["ignore", "pipe", "pipe"], // Pipe stdout/stderr for capture
|
|
576
557
|
env: {
|
|
577
558
|
...process.env,
|
|
578
559
|
...configEnvVars,
|
|
579
|
-
VITE_AGENT_URL: process.env.EXT_HOST
|
|
560
|
+
VITE_AGENT_URL: `${process.env.EXT_HOST || "http://localhost"}:${port}`,
|
|
580
561
|
VITE_DEBUGGER_URL: `http://localhost:${debuggerUiPort}`,
|
|
581
562
|
// If agent uses library MCP, pass LIBRARY_API_URL to GUI for auth
|
|
582
563
|
...(usesLibraryMcp &&
|
|
@@ -586,32 +567,12 @@ export async function runCommand(options) {
|
|
|
586
567
|
}),
|
|
587
568
|
},
|
|
588
569
|
});
|
|
589
|
-
//
|
|
590
|
-
const proxyServer = proxy
|
|
591
|
-
? createProxyServer({
|
|
592
|
-
port: proxyPort,
|
|
593
|
-
vitePort: guiPort,
|
|
594
|
-
agentPort: port,
|
|
595
|
-
basicAuthUser: process.env.BASIC_AUTH_USER,
|
|
596
|
-
basicAuthPass: process.env.BASIC_AUTH_PASS,
|
|
597
|
-
logger,
|
|
598
|
-
})
|
|
599
|
-
: null;
|
|
600
|
-
// Setup cleanup handlers for agent, GUI, and proxy processes
|
|
570
|
+
// Setup cleanup handlers for agent and GUI processes
|
|
601
571
|
let isCleaningUp = false;
|
|
602
572
|
const cleanupProcesses = () => {
|
|
603
573
|
if (isCleaningUp)
|
|
604
574
|
return;
|
|
605
575
|
isCleaningUp = true;
|
|
606
|
-
// Stop proxy server if running
|
|
607
|
-
if (proxyServer) {
|
|
608
|
-
try {
|
|
609
|
-
proxyServer.stop();
|
|
610
|
-
}
|
|
611
|
-
catch (_e) {
|
|
612
|
-
// Proxy may already be stopped
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
576
|
// Kill child processes - since they're not detached, they're in our process group
|
|
616
577
|
try {
|
|
617
578
|
agentProcess.kill("SIGTERM");
|
|
@@ -639,9 +600,7 @@ export async function runCommand(options) {
|
|
|
639
600
|
cleanupDebugger?.();
|
|
640
601
|
};
|
|
641
602
|
// Render the tabbed UI with dynamic port detection
|
|
642
|
-
|
|
643
|
-
const browserPort = proxy ? proxyPort : guiPort;
|
|
644
|
-
const { waitUntilExit } = render(_jsx(GuiRunner, { agentProcess: agentProcess, guiProcess: guiProcess, agentPort: port, browserPort: browserPort, agentPath: agentPath, logger: logger, onExit: () => {
|
|
603
|
+
const { waitUntilExit } = render(_jsx(GuiRunner, { agentProcess: agentProcess, guiProcess: guiProcess, agentPort: port, agentPath: agentPath, logger: logger, onExit: () => {
|
|
645
604
|
cleanupProcesses();
|
|
646
605
|
} }));
|
|
647
606
|
// Register signal handlers AFTER Ink render to ensure they take precedence
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.120",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"town": "./dist/index.js"
|
|
@@ -15,23 +15,22 @@
|
|
|
15
15
|
"build": "tsgo"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@townco/tsconfig": "0.1.
|
|
18
|
+
"@townco/tsconfig": "0.1.112",
|
|
19
19
|
"@types/archiver": "^7.0.0",
|
|
20
20
|
"@types/bun": "^1.3.1",
|
|
21
|
-
"@types/http-proxy": "^1.17.14",
|
|
22
21
|
"@types/ignore-walk": "^4.0.3",
|
|
23
22
|
"@types/react": "^19.2.2"
|
|
24
23
|
},
|
|
25
24
|
"dependencies": {
|
|
26
25
|
"@optique/core": "^0.6.2",
|
|
27
26
|
"@optique/run": "^0.6.2",
|
|
28
|
-
"@townco/agent": "0.1.
|
|
29
|
-
"@townco/apiclient": "0.0.
|
|
30
|
-
"@townco/core": "0.0.
|
|
31
|
-
"@townco/debugger": "0.1.
|
|
32
|
-
"@townco/env": "0.1.
|
|
33
|
-
"@townco/secret": "0.1.
|
|
34
|
-
"@townco/ui": "0.1.
|
|
27
|
+
"@townco/agent": "0.1.123",
|
|
28
|
+
"@townco/apiclient": "0.0.35",
|
|
29
|
+
"@townco/core": "0.0.93",
|
|
30
|
+
"@townco/debugger": "0.1.71",
|
|
31
|
+
"@townco/env": "0.1.65",
|
|
32
|
+
"@townco/secret": "0.1.115",
|
|
33
|
+
"@townco/ui": "0.1.115",
|
|
35
34
|
"@trpc/client": "^11.7.2",
|
|
36
35
|
"archiver": "^7.0.1",
|
|
37
36
|
"eventsource": "^4.1.0",
|
|
@@ -42,7 +41,6 @@
|
|
|
42
41
|
"open": "^10.2.0",
|
|
43
42
|
"superjson": "^2.2.5",
|
|
44
43
|
"ts-pattern": "^5.9.0",
|
|
45
|
-
"http-proxy": "^1.18.1",
|
|
46
44
|
"zod": "^4.1.12"
|
|
47
45
|
},
|
|
48
46
|
"peerDependencies": {
|