@auto-ai/agent 2.1.212 → 2.1.213

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 (43) hide show
  1. package/dist/safe-a/404/index.html +1 -1
  2. package/dist/safe-a/404.html +1 -1
  3. package/dist/safe-a/index.html +2 -2
  4. package/dist/safe-a/index.txt +1 -1
  5. package/dist/safe-a/manage/about/index.html +2 -2
  6. package/dist/safe-a/manage/about/index.txt +1 -1
  7. package/dist/safe-a/manage/env/index.html +2 -2
  8. package/dist/safe-a/manage/env/index.txt +1 -1
  9. package/dist/safe-a/manage/geelib/index.html +2 -2
  10. package/dist/safe-a/manage/geelib/index.txt +1 -1
  11. package/dist/safe-a/manage/general/index.html +2 -2
  12. package/dist/safe-a/manage/general/index.txt +1 -1
  13. package/dist/safe-a/manage/git/index.html +2 -2
  14. package/dist/safe-a/manage/git/index.txt +1 -1
  15. package/dist/safe-a/manage/im/index.html +2 -2
  16. package/dist/safe-a/manage/im/index.txt +1 -1
  17. package/dist/safe-a/manage/index.html +2 -2
  18. package/dist/safe-a/manage/index.txt +1 -1
  19. package/dist/safe-a/manage/library/index.html +2 -2
  20. package/dist/safe-a/manage/library/index.txt +1 -1
  21. package/dist/safe-a/manage/mcp/index.html +2 -2
  22. package/dist/safe-a/manage/mcp/index.txt +1 -1
  23. package/dist/safe-a/manage/permissions/index.html +2 -2
  24. package/dist/safe-a/manage/permissions/index.txt +1 -1
  25. package/dist/safe-a/manage/skills/index.html +2 -2
  26. package/dist/safe-a/manage/skills/index.txt +1 -1
  27. package/dist/safe-a/manage/task/index.html +2 -2
  28. package/dist/safe-a/manage/task/index.txt +1 -1
  29. package/dist/safe-a/manage/teams/index.html +2 -2
  30. package/dist/safe-a/manage/teams/index.txt +1 -1
  31. package/dist/safe-a/manage/tools/index.html +2 -2
  32. package/dist/safe-a/manage/tools/index.txt +1 -1
  33. package/dist/ws-test/vendor/xterm-addon-fit.js +2 -0
  34. package/dist/ws-test/vendor/xterm.css +285 -0
  35. package/dist/ws-test/vendor/xterm.js +2 -0
  36. package/dist/ws-test/ws-test.css +43 -0
  37. package/dist/ws-test/ws-test.html +17 -0
  38. package/dist/ws-test/ws-test.js +244 -0
  39. package/mcps-runtime/claude-ws-channel/server/gateway.bundle.mjs +275 -45
  40. package/package.json +6 -6
  41. /package/dist/safe-a/_next/static/{AY06zpWQV0yfK_fQwZZ5t → ydg1pWMUiUWUhsV4OnPd9}/_buildManifest.js +0 -0
  42. /package/dist/safe-a/_next/static/{AY06zpWQV0yfK_fQwZZ5t → ydg1pWMUiUWUhsV4OnPd9}/_clientMiddlewareManifest.json +0 -0
  43. /package/dist/safe-a/_next/static/{AY06zpWQV0yfK_fQwZZ5t → ydg1pWMUiUWUhsV4OnPd9}/_ssgManifest.js +0 -0
@@ -299490,8 +299490,12 @@ var init_wsSubprocess = __esm(() => {
299490
299490
 
299491
299491
  // src/server/session/wsTeammateDispatcher.ts
299492
299492
  import { randomUUID as randomUUID12 } from "crypto";
299493
- function setWsPermissionRequestSink(sink) {
299494
- emitPermissionRequestEvent = sink;
299493
+ function clearPendingTeammatePermissionsForRun(runId) {
299494
+ for (const [requestId, pending] of pendingTeammatePermissionByRequestId) {
299495
+ if (pending.runId === runId) {
299496
+ pendingTeammatePermissionByRequestId.delete(requestId);
299497
+ }
299498
+ }
299495
299499
  }
299496
299500
  function emit2(event) {
299497
299501
  emitWsAgentEvent?.(event);
@@ -299632,6 +299636,7 @@ function abortTeammateRunOnIdleTimeout(correlationId) {
299632
299636
  return;
299633
299637
  }
299634
299638
  state.stopped = true;
299639
+ clearPendingTeammatePermissionsForRun(task.runId);
299635
299640
  state.permissionRelay.rejectAll(task.runId, "idle_timeout");
299636
299641
  state.channel?.destroy();
299637
299642
  state.channel = null;
@@ -299783,9 +299788,6 @@ async function dispatchWsTeammateTask(params) {
299783
299788
  stopped: false,
299784
299789
  permissionRelay: createWsPermissionRelay()
299785
299790
  };
299786
- setWsPermissionRequestSink((event) => {
299787
- emitPermissionRequestEvent?.(event);
299788
- });
299789
299791
  let latestFinalAssistantText = "";
299790
299792
  let emittedTerminal = false;
299791
299793
  const emitTerminal = (status, reason, resultText) => {
@@ -299822,6 +299824,7 @@ async function dispatchWsTeammateTask(params) {
299822
299824
  return;
299823
299825
  }
299824
299826
  state.stopped = true;
299827
+ clearPendingTeammatePermissionsForRun(runId);
299825
299828
  state.permissionRelay.rejectAll(runId, "subprocess_stopped");
299826
299829
  state.channel?.destroy();
299827
299830
  state.channel = null;
@@ -299840,7 +299843,11 @@ async function dispatchWsTeammateTask(params) {
299840
299843
  touchTaskActivity(correlationId);
299841
299844
  if (parsed.type === "permission.request") {
299842
299845
  const req = parsed;
299843
- if (typeof req.requestId === "string" && typeof req.toolName === "string") {
299846
+ if (typeof req.requestId === "string" && typeof req.toolName === "string" && state.channel) {
299847
+ pendingTeammatePermissionByRequestId.set(req.requestId, {
299848
+ runId: state.runId,
299849
+ channel: state.channel
299850
+ });
299844
299851
  const event = {
299845
299852
  runId: state.runId,
299846
299853
  payload: {
@@ -299987,7 +299994,7 @@ async function dispatchWsTeammateTask(params) {
299987
299994
  logForDebugging(`[wsTeammateDispatcher] dispatch started corr=${correlationId} run=${runId} sourceAgent=${sourceAgent} sessionId=${sessionId ?? ""} promptLen=${prompt.length}`);
299988
299995
  return { runId, correlationId };
299989
299996
  }
299990
- var activeRuns, taskByCorrelationId, taskByDedupeKey, taskAwaiters, DEFAULT_IDLE_TIMEOUT_MS = 60000, IDLE_CHECK_INTERVAL_MS = 1000, emitWsAgentEvent, emitPermissionRequestEvent;
299997
+ var activeRuns, taskByCorrelationId, taskByDedupeKey, taskAwaiters, pendingTeammatePermissionByRequestId, DEFAULT_IDLE_TIMEOUT_MS = 60000, IDLE_CHECK_INTERVAL_MS = 1000, emitWsAgentEvent, emitPermissionRequestEvent;
299991
299998
  var init_wsTeammateDispatcher = __esm(() => {
299992
299999
  init_wsSessionOverrides();
299993
300000
  init_wsAgentWorkspace();
@@ -299998,6 +300005,7 @@ var init_wsTeammateDispatcher = __esm(() => {
299998
300005
  taskByCorrelationId = new Map;
299999
300006
  taskByDedupeKey = new Map;
300000
300007
  taskAwaiters = new Map;
300008
+ pendingTeammatePermissionByRequestId = new Map;
300001
300009
  });
300002
300010
 
300003
300011
  // src/server/session/wsSpawnTeammate.ts
@@ -405620,7 +405628,7 @@ var init_wsAgentScheduleRun = __esm(() => {
405620
405628
 
405621
405629
  // src/server/wsMcp/httpGateway.ts
405622
405630
  import { existsSync as existsSync15 } from "fs";
405623
- import { join as join121 } from "path";
405631
+ import { join as join122 } from "path";
405624
405632
 
405625
405633
  // src/server/api/modelsController.ts
405626
405634
  init_llmProviders();
@@ -407682,6 +407690,9 @@ var activeChannelManagerService = null;
407682
407690
  function getChannelManagerService() {
407683
407691
  return activeChannelManagerService;
407684
407692
  }
407693
+ function reloadAgentConfigForAgent(agentId) {
407694
+ activeChannelManagerService?.reloadAgentConfigForAgent(agentId);
407695
+ }
407685
407696
 
407686
407697
  class ChannelManagerService {
407687
407698
  sessionRuntimes = new Map;
@@ -407704,6 +407715,23 @@ class ChannelManagerService {
407704
407715
  getChannelManager() {
407705
407716
  return this.channelManager;
407706
407717
  }
407718
+ reloadAgentConfigForAgent(agentId) {
407719
+ const trimmed = agentId.trim();
407720
+ if (!trimmed) {
407721
+ return;
407722
+ }
407723
+ for (const runtime of this.sessionRuntimes.values()) {
407724
+ if (runtime.agent !== trimmed || !runtime.sessionChannel) {
407725
+ continue;
407726
+ }
407727
+ this.writeChildMessage(runtime.sessionChannel, {
407728
+ jsonrpc: "2.0",
407729
+ id: null,
407730
+ method: "reloadAgentConfig",
407731
+ params: {}
407732
+ });
407733
+ }
407734
+ }
407707
407735
  async start() {
407708
407736
  startWsScheduleDispatcher();
407709
407737
  configureWsScheduleWsBridge(createMainProcessWsBrowserPush({
@@ -408172,6 +408200,7 @@ class ChannelManagerService {
408172
408200
  this.unregisterBrowserSession(agent, sessionId);
408173
408201
  const cfg = await readWsAgentConfigFile(workspaceDir);
408174
408202
  const browserData = {
408203
+ kind: "session",
408175
408204
  agent: rawAgent,
408176
408205
  sessionId: nextSid,
408177
408206
  workspaceDir,
@@ -408206,6 +408235,13 @@ class ChannelManagerService {
408206
408235
  method: "reloadAgentPrompt",
408207
408236
  params: {}
408208
408237
  });
408238
+ } else if (type === "reloadAgentConfig") {
408239
+ this.writeChildMessage(runtime.sessionChannel, {
408240
+ jsonrpc: "2.0",
408241
+ id: null,
408242
+ method: "reloadAgentConfig",
408243
+ params: {}
408244
+ });
408209
408245
  } else if (type === "reloadSessionOverrides") {
408210
408246
  this.writeChildMessage(runtime.sessionChannel, {
408211
408247
  jsonrpc: "2.0",
@@ -408614,6 +408650,7 @@ class ChannelManagerService {
408614
408650
  }
408615
408651
 
408616
408652
  // src/server/api/agentController.ts
408653
+ init_wsAgentTeamsValidation();
408617
408654
  function agentsCors() {
408618
408655
  return {
408619
408656
  "Access-Control-Allow-Origin": "*",
@@ -408781,6 +408818,9 @@ async function handleAgentsApi(req, url3) {
408781
408818
  }
408782
408819
  try {
408783
408820
  const { config: config7, added } = await addAgentTeamMember(agentCwd, leaderId, agentType);
408821
+ if (added) {
408822
+ reloadAgentConfigForAgent(leaderId);
408823
+ }
408784
408824
  const row = await withAgentTeamListFields({
408785
408825
  id: leaderId,
408786
408826
  cwd: agentCwd
@@ -408806,6 +408846,7 @@ async function handleAgentsApi(req, url3) {
408806
408846
  }
408807
408847
  try {
408808
408848
  const config7 = await removeAgentTeamMember(agentCwd, agentType);
408849
+ reloadAgentConfigForAgent(leaderId);
408809
408850
  const row = await withAgentTeamListFields({
408810
408851
  id: leaderId,
408811
408852
  cwd: agentCwd
@@ -408917,6 +408958,7 @@ async function handleAgentsApi(req, url3) {
408917
408958
  nextCfg.llmProviders = mergedProviders.providers;
408918
408959
  }
408919
408960
  const mcpServersChanged = oldCfg.mcpServers.join("\x00") !== nextCfg.mcpServers.join("\x00");
408961
+ const agentTeamsChanged = normalizeWsAgentTeamTypes(oldCfg.agentTeams).join("\x00") !== normalizeWsAgentTeamTypes(nextCfg.agentTeams).join("\x00");
408920
408962
  await writeWsAgentConfigFile(agentCwd, nextCfg);
408921
408963
  if (mcpServersChanged) {
408922
408964
  const channelManager = getChannelManagerService();
@@ -408924,6 +408966,9 @@ async function handleAgentsApi(req, url3) {
408924
408966
  channelManager.reconcileChannelPairSessions();
408925
408967
  }
408926
408968
  }
408969
+ if (agentTeamsChanged) {
408970
+ reloadAgentConfigForAgent(singleName);
408971
+ }
408927
408972
  }
408928
408973
  let st;
408929
408974
  try {
@@ -412430,6 +412475,155 @@ async function handleRepoApi(req, url3) {
412430
412475
  return;
412431
412476
  }
412432
412477
 
412478
+ // src/server/api/terminalController.ts
412479
+ init_wsAgentWorkspace();
412480
+ import { join as join119 } from "path";
412481
+ var AGENT_WORKSPACE_SUBDIR2 = "workspace";
412482
+ var DEFAULT_COLS = 80;
412483
+ var DEFAULT_ROWS = 24;
412484
+ var terminalSessions = new WeakMap;
412485
+ function isTerminalWs(ws) {
412486
+ return ws.data.kind === "terminal";
412487
+ }
412488
+ function pushTerminalExit(ws, code) {
412489
+ if (ws.readyState !== WebSocket.OPEN) {
412490
+ return;
412491
+ }
412492
+ try {
412493
+ ws.send(JSON.stringify({ type: "exit", code }));
412494
+ } catch {}
412495
+ }
412496
+ function teardownTerminalSession(ws) {
412497
+ const session2 = terminalSessions.get(ws);
412498
+ if (!session2 || session2.closed) {
412499
+ return;
412500
+ }
412501
+ session2.closed = true;
412502
+ terminalSessions.delete(ws);
412503
+ try {
412504
+ session2.proc.kill();
412505
+ } catch {}
412506
+ try {
412507
+ session2.proc.terminal?.close();
412508
+ } catch {}
412509
+ }
412510
+ async function handleTerminalWsUpgrade(req, server) {
412511
+ const url3 = new URL(req.url);
412512
+ const agentParam = url3.searchParams.get("agent");
412513
+ let cwd2;
412514
+ let agent;
412515
+ try {
412516
+ const r4 = resolveWsAgentWorkspace({ agentParam });
412517
+ agent = r4.agent;
412518
+ await requireAgentWorkspaceExists(r4.agentDir, agent);
412519
+ await ensureAgentOperWorkspaceDir(r4.agentDir);
412520
+ cwd2 = join119(r4.operWorkspaceDir, AGENT_WORKSPACE_SUBDIR2);
412521
+ } catch (e5) {
412522
+ return new Response(JSON.stringify({ error: true, message: String(e5) }), {
412523
+ status: 400,
412524
+ headers: { "content-type": "application/json; charset=utf-8" }
412525
+ });
412526
+ }
412527
+ const ok = server.upgrade(req, {
412528
+ data: {
412529
+ kind: "terminal",
412530
+ agent,
412531
+ cwd: cwd2
412532
+ }
412533
+ });
412534
+ if (!ok) {
412535
+ return new Response("WebSocket upgrade failed", { status: 400 });
412536
+ }
412537
+ return;
412538
+ }
412539
+ function handleTerminalWsOpen(ws) {
412540
+ if (!isTerminalWs(ws)) {
412541
+ return;
412542
+ }
412543
+ const { cwd: cwd2 } = ws.data;
412544
+ const cols = DEFAULT_COLS;
412545
+ const rows = DEFAULT_ROWS;
412546
+ const bashPath = Bun.which("bash");
412547
+ if (!bashPath) {
412548
+ try {
412549
+ ws.send(JSON.stringify({ type: "error", message: "bash not found in PATH" }));
412550
+ ws.close();
412551
+ } catch {}
412552
+ return;
412553
+ }
412554
+ let proc;
412555
+ try {
412556
+ proc = Bun.spawn([bashPath], {
412557
+ cwd: cwd2,
412558
+ env: {
412559
+ ...process.env,
412560
+ TERM: "xterm-256color"
412561
+ },
412562
+ terminal: {
412563
+ cols,
412564
+ rows,
412565
+ data(_term, data) {
412566
+ if (ws.readyState !== WebSocket.OPEN) {
412567
+ return;
412568
+ }
412569
+ try {
412570
+ ws.send(data);
412571
+ } catch {}
412572
+ }
412573
+ }
412574
+ });
412575
+ } catch (e5) {
412576
+ try {
412577
+ ws.send(JSON.stringify({ type: "error", message: String(e5) }));
412578
+ ws.close();
412579
+ } catch {}
412580
+ return;
412581
+ }
412582
+ terminalSessions.set(ws, { proc, closed: false });
412583
+ proc.exited.then((code) => {
412584
+ pushTerminalExit(ws, code);
412585
+ teardownTerminalSession(ws);
412586
+ try {
412587
+ ws.close();
412588
+ } catch {}
412589
+ });
412590
+ }
412591
+ function handleTerminalWsMessage(ws, message) {
412592
+ if (!isTerminalWs(ws)) {
412593
+ return;
412594
+ }
412595
+ const session2 = terminalSessions.get(ws);
412596
+ if (!session2 || session2.closed) {
412597
+ return;
412598
+ }
412599
+ const term = session2.proc.terminal;
412600
+ if (!term) {
412601
+ return;
412602
+ }
412603
+ if (typeof message !== "string") {
412604
+ term.write(message);
412605
+ return;
412606
+ }
412607
+ let parsed;
412608
+ try {
412609
+ parsed = JSON.parse(message);
412610
+ } catch {
412611
+ return;
412612
+ }
412613
+ if (parsed.type !== "resize") {
412614
+ return;
412615
+ }
412616
+ const cols = Number(parsed.cols);
412617
+ const rows = Number(parsed.rows);
412618
+ if (!Number.isFinite(cols) || !Number.isFinite(rows) || cols < 1 || rows < 1) {
412619
+ return;
412620
+ }
412621
+ term.resize(Math.floor(cols), Math.floor(rows));
412622
+ }
412623
+ function handleTerminalWsClose(ws) {
412624
+ teardownTerminalSession(ws);
412625
+ }
412626
+
412433
412627
  // src/server/api/runtimePackage/mcpItemConfigController.ts
412434
412628
  init_wsAgentMcpOverlay();
412435
412629
 
@@ -412549,7 +412743,7 @@ init_zip();
412549
412743
  init_wsRuntimeCompiled();
412550
412744
  init_wsRuntimeLayout();
412551
412745
  import { mkdir as mkdir35, readdir as readdir33, readFile as readFile49, rm as rm11, stat as stat38, writeFile as writeFile36 } from "fs/promises";
412552
- import { extname as extname11, join as join119 } from "path";
412746
+ import { extname as extname11, join as join120 } from "path";
412553
412747
  import { pathToFileURL as pathToFileURL6 } from "url";
412554
412748
  var TOOL_ALLOWED_EXT = new Set([".js", ".mjs", ".cjs"]);
412555
412749
  var MCP_COMPILED_FILES = [".mcp.json", "index.js"];
@@ -412593,7 +412787,7 @@ function extractToolNamesFromModule(moduleValue) {
412593
412787
  return [...new Set(collected)];
412594
412788
  }
412595
412789
  async function collectToolPackageFiles(rootAbs, relativeDir) {
412596
- const current2 = relativeDir ? join119(rootAbs, relativeDir) : rootAbs;
412790
+ const current2 = relativeDir ? join120(rootAbs, relativeDir) : rootAbs;
412597
412791
  let entries;
412598
412792
  try {
412599
412793
  entries = await readdir33(current2, { withFileTypes: true });
@@ -412617,7 +412811,7 @@ async function collectToolPackageFiles(rootAbs, relativeDir) {
412617
412811
  return out;
412618
412812
  }
412619
412813
  async function readMcpServerNames(packageRoot) {
412620
- const filePath = join119(packageRoot, ".mcp.json");
412814
+ const filePath = join120(packageRoot, ".mcp.json");
412621
412815
  const { config: config7, errors: errors8 } = parseMcpConfigFromFilePath({
412622
412816
  filePath,
412623
412817
  expandVars: true,
@@ -412631,7 +412825,7 @@ async function readMcpServerNames(packageRoot) {
412631
412825
  async function collectMcpExportRels(rootAbs) {
412632
412826
  const out = [];
412633
412827
  for (const fileName of MCP_COMPILED_FILES) {
412634
- const st = await stat38(join119(rootAbs, fileName)).catch(() => null);
412828
+ const st = await stat38(join120(rootAbs, fileName)).catch(() => null);
412635
412829
  if (st?.isFile()) {
412636
412830
  out.push(fileName);
412637
412831
  }
@@ -412679,7 +412873,7 @@ async function listMcpsRuntimePackages() {
412679
412873
  return items;
412680
412874
  }
412681
412875
  async function collectToolsExportEntries(packageId) {
412682
- const entryAbs = join119(agentRuntimeDir("tools"), packageId);
412876
+ const entryAbs = join120(agentRuntimeDir("tools"), packageId);
412683
412877
  const entrySt = await stat38(entryAbs).catch(() => null);
412684
412878
  if (!entrySt?.isDirectory()) {
412685
412879
  return null;
@@ -412690,13 +412884,13 @@ async function collectToolsExportEntries(packageId) {
412690
412884
  }
412691
412885
  const zipEntries = {};
412692
412886
  for (const rel of rels) {
412693
- const buf = await readFile49(join119(entryAbs, rel));
412887
+ const buf = await readFile49(join120(entryAbs, rel));
412694
412888
  zipEntries[`${packageId}/${rel}`] = new Uint8Array(buf);
412695
412889
  }
412696
412890
  return zipEntries;
412697
412891
  }
412698
412892
  async function collectMcpsExportEntries(packageId) {
412699
- const entryAbs = join119(agentRuntimeDir("mcps"), packageId);
412893
+ const entryAbs = join120(agentRuntimeDir("mcps"), packageId);
412700
412894
  const entrySt = await stat38(entryAbs).catch(() => null);
412701
412895
  if (!entrySt?.isDirectory()) {
412702
412896
  return null;
@@ -412707,7 +412901,7 @@ async function collectMcpsExportEntries(packageId) {
412707
412901
  }
412708
412902
  const zipEntries = {};
412709
412903
  for (const rel of rels) {
412710
- const buf = await readFile49(join119(entryAbs, rel));
412904
+ const buf = await readFile49(join120(entryAbs, rel));
412711
412905
  zipEntries[`${packageId}/${rel}`] = new Uint8Array(buf);
412712
412906
  }
412713
412907
  return zipEntries;
@@ -412718,7 +412912,7 @@ async function deleteToolsRuntimePackage(packageId) {
412718
412912
  if (pkg?.layer === "system") {
412719
412913
  return { ok: false, message: "system runtime package cannot be deleted" };
412720
412914
  }
412721
- const target = join119(agentRuntimeDir("tools"), packageId);
412915
+ const target = join120(agentRuntimeDir("tools"), packageId);
412722
412916
  try {
412723
412917
  const st = await stat38(target);
412724
412918
  if (!st.isDirectory()) {
@@ -412739,7 +412933,7 @@ async function resolveMcpPackageIdByServerName(serverName) {
412739
412933
  return pkg.packageId;
412740
412934
  }
412741
412935
  }
412742
- const direct = join119(dir, serverName);
412936
+ const direct = join120(dir, serverName);
412743
412937
  const st = await stat38(direct).catch(() => null);
412744
412938
  if (st?.isDirectory()) {
412745
412939
  return serverName;
@@ -412749,13 +412943,13 @@ async function resolveMcpPackageIdByServerName(serverName) {
412749
412943
  async function deleteMcpsRuntimePackage(packageIdOrServer) {
412750
412944
  const runtimeDir = agentRuntimeDir("mcps");
412751
412945
  let targetName = packageIdOrServer;
412752
- let target = join119(runtimeDir, targetName);
412946
+ let target = join120(runtimeDir, targetName);
412753
412947
  let st = await stat38(target).catch(() => null);
412754
412948
  if (!st?.isDirectory()) {
412755
412949
  const byServer = await resolveMcpPackageIdByServerName(packageIdOrServer);
412756
412950
  if (byServer) {
412757
412951
  targetName = byServer;
412758
- target = join119(runtimeDir, targetName);
412952
+ target = join120(runtimeDir, targetName);
412759
412953
  st = await stat38(target).catch(() => null);
412760
412954
  }
412761
412955
  }
@@ -412832,8 +413026,8 @@ async function importToolsRuntimeZip(zipBuffer) {
412832
413026
  continue;
412833
413027
  }
412834
413028
  const relativeTarget = [rootDir, ...rest].join("/");
412835
- const target = join119(dir, relativeTarget);
412836
- await mkdir35(join119(dir, rootDir, ...mid), { recursive: true });
413029
+ const target = join120(dir, relativeTarget);
413030
+ await mkdir35(join120(dir, rootDir, ...mid), { recursive: true });
412837
413031
  let existed = false;
412838
413032
  try {
412839
413033
  await readFile49(target);
@@ -412903,8 +413097,8 @@ async function importMcpsRuntimeZip(zipBuffer) {
412903
413097
  continue;
412904
413098
  }
412905
413099
  const relativeTarget = [rootDir, ...rest].join("/");
412906
- const target = join119(dir, relativeTarget);
412907
- await mkdir35(join119(dir, rootDir, ...rest.slice(0, -1)), { recursive: true });
413100
+ const target = join120(dir, relativeTarget);
413101
+ await mkdir35(join120(dir, rootDir, ...rest.slice(0, -1)), { recursive: true });
412908
413102
  let existed = false;
412909
413103
  try {
412910
413104
  await readFile49(target);
@@ -413112,9 +413306,17 @@ init_wsSessionId();
413112
413306
  init_wsSessionOverrides();
413113
413307
  init_wsAgentWorkspace();
413114
413308
 
413309
+ // src/server/wsMcp/wsBrowserTypes.ts
413310
+ function isSessionGatewayData(data) {
413311
+ return data.kind === "session";
413312
+ }
413313
+
413115
413314
  // src/server/wsMcp/wsBrowserProtocol.ts
413116
413315
  import { randomUUID as randomUUID38 } from "crypto";
413117
413316
  function emitBootstrapSessionMeta(ws) {
413317
+ if (!isSessionGatewayData(ws.data)) {
413318
+ return;
413319
+ }
413118
413320
  const sid = ws.data.sessionId?.trim();
413119
413321
  if (!sid) {
413120
413322
  return;
@@ -413148,26 +413350,26 @@ function pushBrowserJson(ws, payload) {
413148
413350
 
413149
413351
  // src/server/wsMcp/staticAssets.ts
413150
413352
  import { existsSync as existsSync14 } from "fs";
413151
- import { join as join120, relative as relative21, resolve as resolve37 } from "path";
413353
+ import { join as join121, relative as relative21, resolve as resolve37 } from "path";
413152
413354
  import { stat as stat39 } from "fs/promises";
413153
413355
  var SAFE_A_DIST_SUBDIR = "safe-a";
413154
413356
  var WS_TEST_DIST_SUBDIR = "ws-test";
413155
413357
  function resolveSafeADistDir() {
413156
413358
  const fromDistDir = process.env.WS_DIST_DIR?.trim();
413157
- if (fromDistDir && existsSync14(join120(fromDistDir, "index.html"))) {
413359
+ if (fromDistDir && existsSync14(join121(fromDistDir, "index.html"))) {
413158
413360
  return fromDistDir;
413159
413361
  }
413160
413362
  const projectRoot = process.env.WS_PROJECT_ROOT?.trim();
413161
413363
  if (projectRoot) {
413162
- const candidate = join120(projectRoot, "dist", SAFE_A_DIST_SUBDIR);
413163
- if (existsSync14(join120(candidate, "index.html"))) {
413364
+ const candidate = join121(projectRoot, "dist", SAFE_A_DIST_SUBDIR);
413365
+ if (existsSync14(join121(candidate, "index.html"))) {
413164
413366
  return candidate;
413165
413367
  }
413166
413368
  }
413167
413369
  let dir = resolve37(import.meta.dir, "../..");
413168
413370
  for (let depth = 0;depth < 8; depth += 1) {
413169
- const safeADir = join120(dir, "dist", SAFE_A_DIST_SUBDIR);
413170
- if (existsSync14(join120(safeADir, "index.html"))) {
413371
+ const safeADir = join121(dir, "dist", SAFE_A_DIST_SUBDIR);
413372
+ if (existsSync14(join121(safeADir, "index.html"))) {
413171
413373
  return safeADir;
413172
413374
  }
413173
413375
  const parent = resolve37(dir, "..");
@@ -413176,24 +413378,24 @@ function resolveSafeADistDir() {
413176
413378
  }
413177
413379
  dir = parent;
413178
413380
  }
413179
- return join120(import.meta.dir, "../../..", "dist", SAFE_A_DIST_SUBDIR);
413381
+ return join121(import.meta.dir, "../../..", "dist", SAFE_A_DIST_SUBDIR);
413180
413382
  }
413181
413383
  function resolveWsTestDistDir() {
413182
413384
  const fromDir = process.env.WS_WS_TEST_DIR?.trim();
413183
- if (fromDir && existsSync14(join120(fromDir, "ws-test.html"))) {
413385
+ if (fromDir && existsSync14(join121(fromDir, "ws-test.html"))) {
413184
413386
  return fromDir;
413185
413387
  }
413186
413388
  const projectRoot = process.env.WS_PROJECT_ROOT?.trim();
413187
413389
  if (projectRoot) {
413188
- const candidate = join120(projectRoot, "dist", WS_TEST_DIST_SUBDIR);
413189
- if (existsSync14(join120(candidate, "ws-test.html"))) {
413390
+ const candidate = join121(projectRoot, "dist", WS_TEST_DIST_SUBDIR);
413391
+ if (existsSync14(join121(candidate, "ws-test.html"))) {
413190
413392
  return candidate;
413191
413393
  }
413192
413394
  }
413193
413395
  let dir = resolve37(import.meta.dir, "../..");
413194
413396
  for (let depth = 0;depth < 8; depth += 1) {
413195
- const wsTestDir = join120(dir, "dist", WS_TEST_DIST_SUBDIR);
413196
- if (existsSync14(join120(wsTestDir, "ws-test.html"))) {
413397
+ const wsTestDir = join121(dir, "dist", WS_TEST_DIST_SUBDIR);
413398
+ if (existsSync14(join121(wsTestDir, "ws-test.html"))) {
413197
413399
  return wsTestDir;
413198
413400
  }
413199
413401
  const parent = resolve37(dir, "..");
@@ -413202,7 +413404,7 @@ function resolveWsTestDistDir() {
413202
413404
  }
413203
413405
  dir = parent;
413204
413406
  }
413205
- return join120(import.meta.dir, "../../..", "dist", WS_TEST_DIST_SUBDIR);
413407
+ return join121(import.meta.dir, "../../..", "dist", WS_TEST_DIST_SUBDIR);
413206
413408
  }
413207
413409
  var safeADistDir = resolveSafeADistDir();
413208
413410
  var wsTestDistDir = resolveWsTestDistDir();
@@ -413254,7 +413456,7 @@ function decodeDistRel(rel) {
413254
413456
  return decoded;
413255
413457
  }
413256
413458
  function safeResolveDistAbs(decodedRel) {
413257
- const abs = resolve37(join120(safeADistDir, decodedRel));
413459
+ const abs = resolve37(join121(safeADistDir, decodedRel));
413258
413460
  const root3 = resolve37(safeADistDir);
413259
413461
  const relToRoot = relative21(root3, abs);
413260
413462
  if (relToRoot.startsWith("..") || relToRoot === "") {
@@ -413307,7 +413509,7 @@ async function resolvedDistAsset(pathname) {
413307
413509
  var SLASH_CMD_PATCH_JS = "slash-command-ui-patch.js";
413308
413510
  var SLASH_CMD_PATCH_CSS = "slash-command-ui-patch.css";
413309
413511
  function slashCommandPatchAssetPath(name3) {
413310
- return join120(safeADistDir, name3);
413512
+ return join121(safeADistDir, name3);
413311
413513
  }
413312
413514
  async function trySlashCommandUiPatchStatic(req, pathname) {
413313
413515
  if (req.method !== "GET" && req.method !== "HEAD")
@@ -413328,14 +413530,19 @@ async function trySlashCommandUiPatchStatic(req, pathname) {
413328
413530
  async function tryWsTestAssetStatic(req, pathname) {
413329
413531
  if (req.method !== "GET" && req.method !== "HEAD")
413330
413532
  return;
413331
- if (pathname !== "/ws-test.css" && pathname !== "/ws-test.js")
413533
+ let rel = null;
413534
+ if (pathname === "/ws-test.css" || pathname === "/ws-test.js") {
413535
+ rel = pathname.slice(1);
413536
+ } else if (pathname.startsWith("/vendor/")) {
413537
+ rel = pathname.slice(1);
413538
+ }
413539
+ if (!rel)
413332
413540
  return;
413333
- const fileName = pathname === "/ws-test.css" ? "ws-test.css" : "ws-test.js";
413334
- const abs = join120(wsTestDistDir, fileName);
413541
+ const abs = join121(wsTestDistDir, rel);
413335
413542
  if (!existsSync14(abs))
413336
413543
  return;
413337
413544
  const file2 = Bun.file(abs);
413338
- const mime = fileName.endsWith(".css") ? "text/css; charset=utf-8" : "application/javascript; charset=utf-8";
413545
+ const mime = rel.endsWith(".css") ? "text/css; charset=utf-8" : "application/javascript; charset=utf-8";
413339
413546
  return new Response(req.method === "HEAD" ? null : file2, {
413340
413547
  headers: { "content-type": mime }
413341
413548
  });
@@ -413388,7 +413595,7 @@ async function tryStaticHtmlResponse(pathname) {
413388
413595
  const fileName = STATIC_HTML_ROUTES[pathname];
413389
413596
  if (!fileName)
413390
413597
  return;
413391
- const abs = join120(wsTestDistDir, fileName);
413598
+ const abs = join121(wsTestDistDir, fileName);
413392
413599
  const file2 = Bun.file(abs);
413393
413600
  if (!await file2.exists())
413394
413601
  return;
@@ -413431,7 +413638,7 @@ function startWsMcpGateway(opts) {
413431
413638
  if (staticHtml !== undefined) {
413432
413639
  return staticHtml;
413433
413640
  }
413434
- if ((req.method === "GET" || req.method === "HEAD") && url3.pathname === wsDistHttpPrefix && existsSync15(join121(safeADistDir, "index.html"))) {
413641
+ if ((req.method === "GET" || req.method === "HEAD") && url3.pathname === wsDistHttpPrefix && existsSync15(join122(safeADistDir, "index.html"))) {
413435
413642
  return Response.redirect(new URL(`${wsDistHttpPrefix}/`, url3).href, 302);
413436
413643
  }
413437
413644
  const distRes = await tryDistStatic(req, url3.pathname);
@@ -413504,6 +413711,9 @@ function startWsMcpGateway(opts) {
413504
413711
  const repoRes = await handleRepoApi(req, url3);
413505
413712
  if (repoRes !== undefined)
413506
413713
  return repoRes;
413714
+ if (url3.pathname === "/ws/terminal") {
413715
+ return handleTerminalWsUpgrade(req, bunServer);
413716
+ }
413507
413717
  if (url3.pathname === "/ws") {
413508
413718
  return handleWsUpgrade(req, bunServer);
413509
413719
  }
@@ -413512,6 +413722,10 @@ function startWsMcpGateway(opts) {
413512
413722
  },
413513
413723
  websocket: {
413514
413724
  open(ws) {
413725
+ if (ws.data.kind === "terminal") {
413726
+ handleTerminalWsOpen(ws);
413727
+ return;
413728
+ }
413515
413729
  emitBootstrapSessionMeta(ws);
413516
413730
  const sid = ws.data.sessionId?.trim();
413517
413731
  if (sid) {
@@ -413520,9 +413734,17 @@ function startWsMcpGateway(opts) {
413520
413734
  hooks2.onControl({ type: "open", data: { ...ws.data } });
413521
413735
  },
413522
413736
  message(ws, message) {
413737
+ if (ws.data.kind === "terminal") {
413738
+ handleTerminalWsMessage(ws, message);
413739
+ return;
413740
+ }
413523
413741
  handleWsMessage(ws, message, hooks2, sessionSockets);
413524
413742
  },
413525
413743
  close(ws) {
413744
+ if (ws.data.kind === "terminal") {
413745
+ handleTerminalWsClose(ws);
413746
+ return;
413747
+ }
413526
413748
  const sid = ws.data.sessionId?.trim();
413527
413749
  if (sid) {
413528
413750
  sessionSockets.delete(sid);
@@ -413600,6 +413822,7 @@ async function handleWsUpgrade(req, server) {
413600
413822
  }
413601
413823
  const ok = server.upgrade(req, {
413602
413824
  data: {
413825
+ kind: "session",
413603
413826
  workspaceDir,
413604
413827
  sessionId,
413605
413828
  agent,
@@ -413615,6 +413838,9 @@ async function handleWsUpgrade(req, server) {
413615
413838
  return;
413616
413839
  }
413617
413840
  async function rebindBrowserWsSession(ws, sessionSockets, parsed) {
413841
+ if (!isSessionGatewayData(ws.data)) {
413842
+ return;
413843
+ }
413618
413844
  const rawAgent = typeof parsed.agent === "string" && parsed.agent.trim().length > 0 ? parsed.agent.trim() : ws.data.agent;
413619
413845
  const rawSid = typeof parsed.sessionId === "string" ? parsed.sessionId.trim() : "";
413620
413846
  const nextSid = rawSid.length > 0 ? rawSid : createWsUserSessionId();
@@ -413642,6 +413868,7 @@ async function rebindBrowserWsSession(ws, sessionSockets, parsed) {
413642
413868
  sessionSockets.delete(oldSid);
413643
413869
  }
413644
413870
  ws.data = {
413871
+ kind: "session",
413645
413872
  workspaceDir: r4.agentDir,
413646
413873
  sessionId: nextSid,
413647
413874
  agent: r4.agent,
@@ -413655,6 +413882,9 @@ async function rebindBrowserWsSession(ws, sessionSockets, parsed) {
413655
413882
  return oldSid;
413656
413883
  }
413657
413884
  async function handleWsMessage(ws, message, hooks2, sessionSockets) {
413885
+ if (!isSessionGatewayData(ws.data)) {
413886
+ return;
413887
+ }
413658
413888
  let parsed;
413659
413889
  try {
413660
413890
  parsed = typeof message === "string" ? JSON.parse(message) : message;