@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.
@@ -78,6 +78,7 @@ export default createCommand({
78
78
  console.log(`Archive uploaded: ${sha256} (${cached ? "cached" : "new"})`);
79
79
  console.log("Deploying...");
80
80
  client.deploy.subscribe({
81
+ type: "repo-deploy",
81
82
  sha256,
82
83
  agent,
83
84
  shedUrl,
@@ -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, proxy }) => {
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;
@@ -6,6 +6,5 @@ export interface RunCommandOptions {
6
6
  prompt?: string;
7
7
  port?: number;
8
8
  noSession?: boolean;
9
- proxy?: boolean;
10
9
  }
11
10
  export declare function runCommand(options: RunCommandOptions): Promise<void>;
@@ -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, browserPort, agentPath, logger, onExit, }) {
85
+ function GuiRunner({ agentProcess, guiProcess, agentPort, agentPath, logger, onExit, }) {
87
86
  const browserOpenedRef = useRef(false);
88
- const handlePortDetected = useCallback((processIndex, _port) => {
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 GUI is ready
90
+ // Open browser once we know the actual port
92
91
  if (!browserOpenedRef.current) {
93
92
  browserOpenedRef.current = true;
94
- const guiUrl = `http://localhost:${browserPort}`;
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, browserPort]);
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, proxy = false, } = options;
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
- if (proxy) {
538
- console.log(`Proxy server running on port ${proxyPort}`);
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 ?? agentUrl,
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
- // Start the reverse proxy server if enabled
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
- // Browser opens to proxy port if enabled, otherwise to GUI port
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.118",
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.110",
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.121",
29
- "@townco/apiclient": "0.0.33",
30
- "@townco/core": "0.0.91",
31
- "@townco/debugger": "0.1.69",
32
- "@townco/env": "0.1.63",
33
- "@townco/secret": "0.1.113",
34
- "@townco/ui": "0.1.113",
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": {