open-agents-ai 0.187.176 → 0.187.178

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 (2) hide show
  1. package/dist/index.js +1163 -307
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -124136,7 +124136,7 @@ var require_snapshot_recorder = __commonJS({
124136
124136
  "../node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
124137
124137
  "use strict";
124138
124138
  var { writeFile: writeFile21, readFile: readFile24, mkdir: mkdir16 } = __require("node:fs/promises");
124139
- var { dirname: dirname28, resolve: resolve39 } = __require("node:path");
124139
+ var { dirname: dirname29, resolve: resolve39 } = __require("node:path");
124140
124140
  var { setTimeout: setTimeout3, clearTimeout: clearTimeout3 } = __require("node:timers");
124141
124141
  var { InvalidArgumentError, UndiciError } = require_errors2();
124142
124142
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -124367,7 +124367,7 @@ var require_snapshot_recorder = __commonJS({
124367
124367
  throw new InvalidArgumentError("Snapshot path is required");
124368
124368
  }
124369
124369
  const resolvedPath = resolve39(path5);
124370
- await mkdir16(dirname28(resolvedPath), { recursive: true });
124370
+ await mkdir16(dirname29(resolvedPath), { recursive: true });
124371
124371
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
124372
124372
  hash,
124373
124373
  snapshot
@@ -238029,15 +238029,15 @@ var init_ls = __esm({
238029
238029
  });
238030
238030
 
238031
238031
  // ../node_modules/@helia/unixfs/dist/src/commands/mkdir.js
238032
- async function mkdir5(parentCid, dirname28, blockstore, options2 = {}) {
238033
- if (dirname28.includes("/")) {
238032
+ async function mkdir5(parentCid, dirname29, blockstore, options2 = {}) {
238033
+ if (dirname29.includes("/")) {
238034
238034
  throw new InvalidParametersError4("Path must not have slashes");
238035
238035
  }
238036
238036
  const entry = await exporter2(parentCid, blockstore, options2);
238037
238037
  if (entry.type !== "directory") {
238038
238038
  throw new NotADirectoryError(`${parentCid.toString()} was not a UnixFS directory`);
238039
238039
  }
238040
- log16("creating %s", dirname28);
238040
+ log16("creating %s", dirname29);
238041
238041
  const metadata = new UnixFS({
238042
238042
  type: "directory",
238043
238043
  mode: options2.mode,
@@ -238053,9 +238053,9 @@ async function mkdir5(parentCid, dirname28, blockstore, options2 = {}) {
238053
238053
  await blockstore.put(emptyDirCid, buf);
238054
238054
  const [directory, pblink] = await Promise.all([
238055
238055
  cidToDirectory(parentCid, blockstore, options2),
238056
- cidToPBLink(emptyDirCid, dirname28, blockstore, options2)
238056
+ cidToPBLink(emptyDirCid, dirname29, blockstore, options2)
238057
238057
  ]);
238058
- log16("adding empty dir called %s to %c", dirname28, parentCid);
238058
+ log16("adding empty dir called %s to %c", dirname29, parentCid);
238059
238059
  const result = await addLink(directory, pblink, blockstore, {
238060
238060
  ...options2,
238061
238061
  allowOverwriting: options2.force
@@ -238554,8 +238554,8 @@ var init_unixfs2 = __esm({
238554
238554
  async *ls(cid, options2 = {}) {
238555
238555
  yield* ls(cid, this.components.blockstore, options2);
238556
238556
  }
238557
- async mkdir(cid, dirname28, options2 = {}) {
238558
- return mkdir5(cid, dirname28, this.components.blockstore, options2);
238557
+ async mkdir(cid, dirname29, options2 = {}) {
238558
+ return mkdir5(cid, dirname29, this.components.blockstore, options2);
238559
238559
  }
238560
238560
  async rm(cid, path5, options2 = {}) {
238561
238561
  return rm2(cid, path5, this.components.blockstore, options2);
@@ -245799,9 +245799,9 @@ print("${sentinel}")
245799
245799
  if (!this.proc || this.proc.killed) {
245800
245800
  return { success: false, path: "" };
245801
245801
  }
245802
- const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync43 } = await import("node:fs");
245802
+ const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync44 } = await import("node:fs");
245803
245803
  const sessionDir = join24(this.cwd, ".oa", "rlm");
245804
- mkdirSync49(sessionDir, { recursive: true });
245804
+ mkdirSync50(sessionDir, { recursive: true });
245805
245805
  const sessionPath = join24(sessionDir, "session.json");
245806
245806
  try {
245807
245807
  const inspectCode = `
@@ -245825,7 +245825,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
245825
245825
  trajectoryCount: this.trajectory.length,
245826
245826
  subCallCount: this.subCallCount
245827
245827
  };
245828
- writeFileSync43(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
245828
+ writeFileSync44(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
245829
245829
  return { success: true, path: sessionPath };
245830
245830
  }
245831
245831
  } catch {
@@ -246434,7 +246434,7 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
246434
246434
  /** Update memory scores based on task outcome. Called after task completion.
246435
246435
  * Memories used in successful tasks get boosted. Memories present during failures get decayed. */
246436
246436
  updateFromOutcomeSync(surfacedMemoryText, succeeded) {
246437
- const { readFileSync: readFileSync62, writeFileSync: writeFileSync43, existsSync: existsSync80, mkdirSync: mkdirSync49 } = __require("node:fs");
246437
+ const { readFileSync: readFileSync62, writeFileSync: writeFileSync44, existsSync: existsSync80, mkdirSync: mkdirSync50 } = __require("node:fs");
246438
246438
  const metaDir = join25(this.cwd, ".oa", "memory", "metabolism");
246439
246439
  const storeFile = join25(metaDir, "store.json");
246440
246440
  if (!existsSync80(storeFile))
@@ -246465,8 +246465,8 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
246465
246465
  updated = true;
246466
246466
  }
246467
246467
  if (updated) {
246468
- mkdirSync49(metaDir, { recursive: true });
246469
- writeFileSync43(storeFile, JSON.stringify(store2, null, 2));
246468
+ mkdirSync50(metaDir, { recursive: true });
246469
+ writeFileSync44(storeFile, JSON.stringify(store2, null, 2));
246470
246470
  }
246471
246471
  }
246472
246472
  // ── Storage ──────────────────────────────────────────────────────────
@@ -246912,7 +246912,7 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
246912
246912
  }
246913
246913
  /** Archive a strategy variant synchronously (for task completion path) */
246914
246914
  archiveVariantSync(strategy, outcome, tags = []) {
246915
- const { readFileSync: readFileSync62, writeFileSync: writeFileSync43, existsSync: existsSync80, mkdirSync: mkdirSync49 } = __require("node:fs");
246915
+ const { readFileSync: readFileSync62, writeFileSync: writeFileSync44, existsSync: existsSync80, mkdirSync: mkdirSync50 } = __require("node:fs");
246916
246916
  const dir = join27(this.cwd, ".oa", "arche");
246917
246917
  const archiveFile = join27(dir, "variants.json");
246918
246918
  let variants = [];
@@ -246933,8 +246933,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
246933
246933
  });
246934
246934
  if (variants.length > 50)
246935
246935
  variants = variants.slice(-50);
246936
- mkdirSync49(dir, { recursive: true });
246937
- writeFileSync43(archiveFile, JSON.stringify(variants, null, 2));
246936
+ mkdirSync50(dir, { recursive: true });
246937
+ writeFileSync44(archiveFile, JSON.stringify(variants, null, 2));
246938
246938
  }
246939
246939
  async saveArchive(variants) {
246940
246940
  const dir = join27(this.cwd, ".oa", "arche");
@@ -259602,9 +259602,13 @@ var init_transport5 = __esm({
259602
259602
  buffer = "";
259603
259603
  _connected = false;
259604
259604
  stderr = [];
259605
+ notificationHandlers = [];
259605
259606
  get connected() {
259606
259607
  return this._connected;
259607
259608
  }
259609
+ onNotification(handler) {
259610
+ this.notificationHandlers.push(handler);
259611
+ }
259608
259612
  async connect(config) {
259609
259613
  const env2 = { ...process.env, ...config.env };
259610
259614
  const args = config.args ?? [];
@@ -259628,6 +259632,13 @@ var init_transport5 = __esm({
259628
259632
  clearTimeout(p2.timer);
259629
259633
  this.pending.delete(msg.id);
259630
259634
  p2.resolve(msg);
259635
+ } else if ("method" in msg && msg.id == null) {
259636
+ for (const h of this.notificationHandlers) {
259637
+ try {
259638
+ h(msg);
259639
+ } catch {
259640
+ }
259641
+ }
259631
259642
  }
259632
259643
  } catch {
259633
259644
  }
@@ -259711,6 +259722,8 @@ var init_transport5 = __esm({
259711
259722
  url;
259712
259723
  headers;
259713
259724
  _connected = true;
259725
+ sessionId = null;
259726
+ protocolVersion = null;
259714
259727
  get connected() {
259715
259728
  return this._connected;
259716
259729
  }
@@ -259718,26 +259731,57 @@ var init_transport5 = __esm({
259718
259731
  this.url = config.url;
259719
259732
  this.headers = config.headers ?? {};
259720
259733
  }
259734
+ /**
259735
+ * Called by McpClient after initialize negotiates a protocol version.
259736
+ * After this point all requests will include MCP-Protocol-Version.
259737
+ */
259738
+ setProtocolVersion(version4) {
259739
+ this.protocolVersion = version4;
259740
+ }
259741
+ /** Build the headers for every POST request */
259742
+ buildHeaders(extra) {
259743
+ const h = {
259744
+ "Content-Type": "application/json",
259745
+ // Spec: client MUST list both content types in Accept
259746
+ "Accept": "application/json, text/event-stream",
259747
+ ...this.headers
259748
+ };
259749
+ if (this.sessionId)
259750
+ h["Mcp-Session-Id"] = this.sessionId;
259751
+ if (this.protocolVersion)
259752
+ h["MCP-Protocol-Version"] = this.protocolVersion;
259753
+ if (extra)
259754
+ Object.assign(h, extra);
259755
+ return h;
259756
+ }
259721
259757
  async request(req2, timeoutMs = 3e4) {
259722
259758
  const controller = new AbortController();
259723
259759
  const timer = setTimeout(() => controller.abort(), timeoutMs);
259724
259760
  try {
259725
259761
  const resp = await fetch(this.url, {
259726
259762
  method: "POST",
259727
- headers: {
259728
- "Content-Type": "application/json",
259729
- "Accept": "application/json",
259730
- ...this.headers
259731
- },
259763
+ headers: this.buildHeaders(),
259732
259764
  body: JSON.stringify(req2),
259733
259765
  signal: controller.signal
259734
259766
  });
259735
259767
  clearTimeout(timer);
259768
+ const sessionHeader = resp.headers.get("Mcp-Session-Id") ?? resp.headers.get("mcp-session-id");
259769
+ if (sessionHeader && req2.method === "initialize") {
259770
+ this.sessionId = sessionHeader;
259771
+ }
259772
+ if (resp.status === 404 && this.sessionId) {
259773
+ this.sessionId = null;
259774
+ throw new Error(`MCP session expired (HTTP 404): ${req2.method}`);
259775
+ }
259736
259776
  if (!resp.ok) {
259737
- throw new Error(`MCP HTTP error: ${resp.status} ${resp.statusText}`);
259777
+ const text = await resp.text().catch(() => "");
259778
+ throw new Error(`MCP HTTP error: ${resp.status} ${resp.statusText}${text ? ` \u2014 ${text.slice(0, 200)}` : ""}`);
259779
+ }
259780
+ const ct = (resp.headers.get("Content-Type") ?? "").toLowerCase();
259781
+ if (ct.includes("text/event-stream")) {
259782
+ return await this.readSseResponse(resp, req2.id);
259738
259783
  }
259739
- const body = await resp.json();
259740
- return body;
259784
+ return await resp.json();
259741
259785
  } catch (err) {
259742
259786
  clearTimeout(timer);
259743
259787
  if (err instanceof Error && err.name === "AbortError") {
@@ -259746,19 +259790,71 @@ var init_transport5 = __esm({
259746
259790
  throw err;
259747
259791
  }
259748
259792
  }
259793
+ /**
259794
+ * Parse an SSE stream and return the first JSON-RPC response whose id matches.
259795
+ * Per spec, server SHOULD eventually emit the matching response on this stream.
259796
+ */
259797
+ async readSseResponse(resp, expectedId) {
259798
+ if (!resp.body)
259799
+ throw new Error("MCP SSE response has no body");
259800
+ const reader = resp.body.getReader();
259801
+ const decoder = new TextDecoder();
259802
+ let buf = "";
259803
+ try {
259804
+ while (true) {
259805
+ const { value: value2, done } = await reader.read();
259806
+ if (done)
259807
+ break;
259808
+ buf += decoder.decode(value2, { stream: true });
259809
+ let sep;
259810
+ while ((sep = buf.indexOf("\n\n")) !== -1) {
259811
+ const event = buf.slice(0, sep);
259812
+ buf = buf.slice(sep + 2);
259813
+ const dataLines = [];
259814
+ for (const line of event.split("\n")) {
259815
+ if (line.startsWith("data:"))
259816
+ dataLines.push(line.slice(5).trimStart());
259817
+ }
259818
+ if (dataLines.length === 0)
259819
+ continue;
259820
+ const dataStr = dataLines.join("\n");
259821
+ try {
259822
+ const msg = JSON.parse(dataStr);
259823
+ if (msg.id === expectedId || msg.id != null) {
259824
+ return msg;
259825
+ }
259826
+ } catch {
259827
+ }
259828
+ }
259829
+ }
259830
+ throw new Error("MCP SSE stream closed before response received");
259831
+ } finally {
259832
+ try {
259833
+ reader.releaseLock();
259834
+ } catch {
259835
+ }
259836
+ }
259837
+ }
259749
259838
  notify(notif) {
259750
259839
  fetch(this.url, {
259751
259840
  method: "POST",
259752
- headers: {
259753
- "Content-Type": "application/json",
259754
- ...this.headers
259755
- },
259841
+ headers: this.buildHeaders(),
259756
259842
  body: JSON.stringify(notif)
259757
259843
  }).catch(() => {
259758
259844
  });
259759
259845
  }
259760
259846
  async close() {
259847
+ if (this.sessionId) {
259848
+ try {
259849
+ await fetch(this.url, {
259850
+ method: "DELETE",
259851
+ headers: this.buildHeaders()
259852
+ });
259853
+ } catch {
259854
+ }
259855
+ }
259761
259856
  this._connected = false;
259857
+ this.sessionId = null;
259762
259858
  }
259763
259859
  };
259764
259860
  }
@@ -259780,14 +259876,15 @@ function parseMcpToolName(fullName) {
259780
259876
  return null;
259781
259877
  return { server: match[1], tool: match[2] };
259782
259878
  }
259783
- var MCP_PROTOCOL_VERSION, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, DEFAULT_TIMEOUT_MS, _nextId, McpClient;
259879
+ var MCP_PROTOCOL_VERSION, MCP_CLIENT_NAME, MCP_CLIENT_TITLE, MCP_CLIENT_VERSION, DEFAULT_TIMEOUT_MS, _nextId, McpClient;
259784
259880
  var init_client3 = __esm({
259785
259881
  "packages/execution/dist/mcp/client.js"() {
259786
259882
  "use strict";
259787
259883
  init_transport5();
259788
- MCP_PROTOCOL_VERSION = "2025-11-25";
259884
+ MCP_PROTOCOL_VERSION = "2025-06-18";
259789
259885
  MCP_CLIENT_NAME = "open-agents";
259790
- MCP_CLIENT_VERSION = "0.187.0";
259886
+ MCP_CLIENT_TITLE = "Open Agents";
259887
+ MCP_CLIENT_VERSION = "0.187.176";
259791
259888
  DEFAULT_TIMEOUT_MS = 3e4;
259792
259889
  _nextId = 1;
259793
259890
  McpClient = class {
@@ -259797,10 +259894,19 @@ var init_client3 = __esm({
259797
259894
  initResult = null;
259798
259895
  cachedTools = null;
259799
259896
  cachedResources = null;
259897
+ notificationHandlers = [];
259800
259898
  constructor(serverName, config) {
259801
259899
  this.serverName = serverName;
259802
259900
  this.config = config;
259803
259901
  }
259902
+ /**
259903
+ * Register a callback for server-sent JSON-RPC notifications.
259904
+ * Called for progress updates, log messages, list_changed events, etc.
259905
+ * Multiple handlers can be registered.
259906
+ */
259907
+ onNotification(handler) {
259908
+ this.notificationHandlers.push(handler);
259909
+ }
259804
259910
  /** Server name */
259805
259911
  get name() {
259806
259912
  return this.serverName;
@@ -259821,6 +259927,16 @@ var init_client3 = __esm({
259821
259927
  */
259822
259928
  async connect() {
259823
259929
  this.transport = await createTransport(this.config);
259930
+ if (typeof this.transport.onNotification === "function") {
259931
+ this.transport.onNotification((notif) => {
259932
+ for (const h of this.notificationHandlers) {
259933
+ try {
259934
+ h(notif.method, notif.params);
259935
+ } catch {
259936
+ }
259937
+ }
259938
+ });
259939
+ }
259824
259940
  const initReq = {
259825
259941
  jsonrpc: "2.0",
259826
259942
  id: nextId(),
@@ -259828,10 +259944,13 @@ var init_client3 = __esm({
259828
259944
  params: {
259829
259945
  protocolVersion: MCP_PROTOCOL_VERSION,
259830
259946
  capabilities: {
259831
- roots: {}
259947
+ // Open Agents currently advertises only roots; sampling and elicitation
259948
+ // would need additional client-side support to be honestly negotiated.
259949
+ roots: { listChanged: false }
259832
259950
  },
259833
259951
  clientInfo: {
259834
259952
  name: MCP_CLIENT_NAME,
259953
+ title: MCP_CLIENT_TITLE,
259835
259954
  version: MCP_CLIENT_VERSION
259836
259955
  }
259837
259956
  }
@@ -259842,6 +259961,16 @@ var init_client3 = __esm({
259842
259961
  }
259843
259962
  const result = initResp.result;
259844
259963
  this.initResult = result;
259964
+ if (result.protocolVersion && result.protocolVersion !== MCP_PROTOCOL_VERSION) {
259965
+ if (result.protocolVersion !== "2025-03-26" && result.protocolVersion !== "2024-11-05") {
259966
+ await this.transport.close().catch(() => {
259967
+ });
259968
+ throw new Error(`MCP server proposed unsupported protocol version: ${result.protocolVersion}`);
259969
+ }
259970
+ }
259971
+ if (typeof this.transport.setProtocolVersion === "function") {
259972
+ this.transport.setProtocolVersion(result.protocolVersion ?? MCP_PROTOCOL_VERSION);
259973
+ }
259845
259974
  this.transport.notify({
259846
259975
  jsonrpc: "2.0",
259847
259976
  method: "notifications/initialized"
@@ -259889,26 +260018,57 @@ var init_client3 = __esm({
259889
260018
  * @param toolName The tool name (as returned by listTools)
259890
260019
  * @param args Tool arguments matching the tool's inputSchema
259891
260020
  * @param timeoutMs Request timeout (default: 60s for tool calls)
260021
+ * @param options Optional: progressToken to opt-in to progress notifications,
260022
+ * onProgress callback receives every notifications/progress
260023
+ * event whose progressToken matches.
259892
260024
  */
259893
- async callTool(toolName, args, timeoutMs = 6e4) {
260025
+ async callTool(toolName, args, timeoutMs = 6e4, options2) {
259894
260026
  this.ensureConnected();
259895
- const resp = await this.transport.request({
259896
- jsonrpc: "2.0",
259897
- id: nextId(),
259898
- method: "tools/call",
259899
- params: {
259900
- name: toolName,
259901
- arguments: args
259902
- }
259903
- }, timeoutMs);
259904
- if (resp.error) {
259905
- return {
259906
- content: [{ type: "text", text: `MCP error: ${resp.error.message}` }],
259907
- isError: true
260027
+ let unsubscribe = null;
260028
+ if (options2?.progressToken !== void 0 && options2.onProgress) {
260029
+ const wantedToken = options2.progressToken;
260030
+ const handler = (method, params) => {
260031
+ if (method === "notifications/progress" && params?.progressToken === wantedToken) {
260032
+ options2.onProgress({
260033
+ progress: params.progress,
260034
+ total: params.total,
260035
+ message: params.message
260036
+ });
260037
+ }
260038
+ };
260039
+ this.notificationHandlers.push(handler);
260040
+ unsubscribe = () => {
260041
+ const idx = this.notificationHandlers.indexOf(handler);
260042
+ if (idx >= 0)
260043
+ this.notificationHandlers.splice(idx, 1);
259908
260044
  };
259909
260045
  }
259910
- const result = resp.result;
259911
- return result;
260046
+ const reqParams = {
260047
+ name: toolName,
260048
+ arguments: args
260049
+ };
260050
+ if (options2?.progressToken !== void 0) {
260051
+ reqParams._meta = { progressToken: options2.progressToken };
260052
+ }
260053
+ try {
260054
+ const resp = await this.transport.request({
260055
+ jsonrpc: "2.0",
260056
+ id: nextId(),
260057
+ method: "tools/call",
260058
+ params: reqParams
260059
+ }, timeoutMs);
260060
+ if (resp.error) {
260061
+ return {
260062
+ content: [{ type: "text", text: `MCP error: ${resp.error.message}` }],
260063
+ isError: true
260064
+ };
260065
+ }
260066
+ const result = resp.result;
260067
+ return result;
260068
+ } finally {
260069
+ if (unsubscribe)
260070
+ unsubscribe();
260071
+ }
259912
260072
  }
259913
260073
  // ─────────────────────────────────────────────────────────
259914
260074
  // Resource Operations
@@ -260003,8 +260163,8 @@ var init_client3 = __esm({
260003
260163
  });
260004
260164
 
260005
260165
  // packages/execution/dist/mcp/manager.js
260006
- import { existsSync as existsSync39, readFileSync as readFileSync29 } from "node:fs";
260007
- import { join as join54 } from "node:path";
260166
+ import { existsSync as existsSync39, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync20 } from "node:fs";
260167
+ import { join as join54, dirname as dirname14 } from "node:path";
260008
260168
  import { homedir as homedir17 } from "node:os";
260009
260169
  function loadMcpConfig(repoRoot) {
260010
260170
  const servers = {};
@@ -260055,6 +260215,38 @@ function expandEnvVars(str) {
260055
260215
  return process.env[name10] ?? "";
260056
260216
  });
260057
260217
  }
260218
+ function saveMcpServerToConfig(repoRoot, serverName, config, scope = "project") {
260219
+ const path5 = scope === "global" ? join54(homedir17(), ".open-agents", "mcp.json") : join54(repoRoot, ".oa", "mcp.json");
260220
+ let existing = { mcpServers: {} };
260221
+ if (existsSync39(path5)) {
260222
+ try {
260223
+ existing = JSON.parse(readFileSync29(path5, "utf8"));
260224
+ if (!existing.mcpServers)
260225
+ existing.mcpServers = {};
260226
+ } catch {
260227
+ }
260228
+ }
260229
+ existing.mcpServers[serverName] = config;
260230
+ mkdirSync20(dirname14(path5), { recursive: true });
260231
+ writeFileSync17(path5, JSON.stringify(existing, null, 2) + "\n");
260232
+ return path5;
260233
+ }
260234
+ function removeMcpServerFromConfig(repoRoot, serverName, scope = "project") {
260235
+ const path5 = scope === "global" ? join54(homedir17(), ".open-agents", "mcp.json") : join54(repoRoot, ".oa", "mcp.json");
260236
+ if (!existsSync39(path5))
260237
+ return false;
260238
+ let cfg;
260239
+ try {
260240
+ cfg = JSON.parse(readFileSync29(path5, "utf8"));
260241
+ } catch {
260242
+ return false;
260243
+ }
260244
+ if (!cfg.mcpServers || !cfg.mcpServers[serverName])
260245
+ return false;
260246
+ delete cfg.mcpServers[serverName];
260247
+ writeFileSync17(path5, JSON.stringify(cfg, null, 2) + "\n");
260248
+ return true;
260249
+ }
260058
260250
  var McpManager;
260059
260251
  var init_manager2 = __esm({
260060
260252
  "packages/execution/dist/mcp/manager.js"() {
@@ -260134,6 +260326,21 @@ var init_manager2 = __esm({
260134
260326
  this.clients.delete(name10);
260135
260327
  }
260136
260328
  }
260329
+ /**
260330
+ * Add a server at runtime: persist to mcp.json AND attempt to connect.
260331
+ * Returns the connection result.
260332
+ */
260333
+ async addServer(name10, config, scope = "project") {
260334
+ saveMcpServerToConfig(this.repoRoot, name10, config, scope);
260335
+ return this.connectOne(name10, config);
260336
+ }
260337
+ /**
260338
+ * Remove a server at runtime: disconnect AND delete from mcp.json.
260339
+ */
260340
+ async removeServer(name10, scope = "project") {
260341
+ await this.disconnect(name10);
260342
+ return removeMcpServerFromConfig(this.repoRoot, name10, scope);
260343
+ }
260137
260344
  /**
260138
260345
  * Get all connections.
260139
260346
  */
@@ -260173,7 +260380,8 @@ var init_manager2 = __esm({
260173
260380
  // ─────────────────────────────────────────────────────────
260174
260381
  wrapMcpTool(client, def) {
260175
260382
  const fullName = buildMcpToolName(client.name, def.name);
260176
- const description = def.description ? `[MCP: ${client.name}] ${def.description}` : `[MCP: ${client.name}] ${def.name}`;
260383
+ const displayTitle = def.title ?? def.annotations?.title ?? def.name;
260384
+ const description = def.description ? `[MCP: ${client.name}] ${def.description}` : `[MCP: ${client.name}] ${displayTitle}`;
260177
260385
  return {
260178
260386
  name: fullName,
260179
260387
  description: description.slice(0, 500),
@@ -260182,7 +260390,35 @@ var init_manager2 = __esm({
260182
260390
  const start2 = performance.now();
260183
260391
  try {
260184
260392
  const result = await client.callTool(def.name, args);
260185
- const text = result.content.filter((c7) => c7.type === "text").map((c7) => c7.text).join("\n");
260393
+ const parts = [];
260394
+ for (const block of result.content) {
260395
+ if (block.type === "text") {
260396
+ parts.push(block.text);
260397
+ } else if (block.type === "image") {
260398
+ parts.push(`[image: ${block.mimeType}, ${Math.round(block.data.length * 0.75 / 1024)}KB base64]`);
260399
+ } else if (block.type === "audio") {
260400
+ parts.push(`[audio: ${block.mimeType}, ${Math.round(block.data.length * 0.75 / 1024)}KB base64]`);
260401
+ } else if (block.type === "resource_link") {
260402
+ parts.push(`[resource_link: ${block.uri}${block.name ? ` (${block.name})` : ""}${block.mimeType ? ` ${block.mimeType}` : ""}]${block.description ? `
260403
+ ${block.description}` : ""}`);
260404
+ } else if (block.type === "resource") {
260405
+ const r2 = block.resource;
260406
+ if (r2.text) {
260407
+ parts.push(`[resource ${r2.uri}${r2.mimeType ? ` (${r2.mimeType})` : ""}]
260408
+ ${r2.text}`);
260409
+ } else if (r2.blob) {
260410
+ parts.push(`[resource ${r2.uri}${r2.mimeType ? ` (${r2.mimeType})` : ""}, ${Math.round(r2.blob.length * 0.75 / 1024)}KB binary]`);
260411
+ }
260412
+ }
260413
+ }
260414
+ if (result.structuredContent !== void 0) {
260415
+ try {
260416
+ parts.push(`[structuredContent]
260417
+ ${JSON.stringify(result.structuredContent, null, 2)}`);
260418
+ } catch {
260419
+ }
260420
+ }
260421
+ const text = parts.join("\n").trim();
260186
260422
  return {
260187
260423
  success: !result.isError,
260188
260424
  output: text || "(empty response)",
@@ -260299,6 +260535,232 @@ var init_manager2 = __esm({
260299
260535
  }
260300
260536
  });
260301
260537
 
260538
+ // packages/execution/dist/mcp/md-intake.js
260539
+ function slugify(s2) {
260540
+ return s2.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "mcp-server";
260541
+ }
260542
+ function extractCodeBlocks(md) {
260543
+ const blocks = [];
260544
+ const re = /^(?:```|~~~)([A-Za-z0-9_+\-]*)\r?\n([\s\S]*?)\r?\n(?:```|~~~)\s*$/gm;
260545
+ let m2;
260546
+ while ((m2 = re.exec(md)) !== null) {
260547
+ blocks.push({ lang: (m2[1] || "").toLowerCase(), code: m2[2] });
260548
+ }
260549
+ return blocks;
260550
+ }
260551
+ function isMcpMarkdown(md) {
260552
+ const lower = md.toLowerCase();
260553
+ let hits = 0;
260554
+ for (const k of MCP_KEYWORDS) {
260555
+ if (lower.includes(k.toLowerCase()))
260556
+ hits++;
260557
+ }
260558
+ if (hits >= 2)
260559
+ return true;
260560
+ if (/"mcpServers"/.test(md))
260561
+ return true;
260562
+ return false;
260563
+ }
260564
+ function tryParseJson(s2) {
260565
+ try {
260566
+ return JSON.parse(s2);
260567
+ } catch {
260568
+ try {
260569
+ const cleaned = s2.replace(/,(\s*[}\]])/g, "$1");
260570
+ return JSON.parse(cleaned);
260571
+ } catch {
260572
+ return null;
260573
+ }
260574
+ }
260575
+ }
260576
+ function coerceServerConfig(value2) {
260577
+ if (!value2 || typeof value2 !== "object")
260578
+ return null;
260579
+ const v = value2;
260580
+ if (typeof v.command === "string") {
260581
+ const cfg = {
260582
+ type: "stdio",
260583
+ command: v.command
260584
+ };
260585
+ if (Array.isArray(v.args) && v.args.every((a2) => typeof a2 === "string")) {
260586
+ cfg.args = v.args;
260587
+ }
260588
+ if (v.env && typeof v.env === "object" && !Array.isArray(v.env)) {
260589
+ const env2 = {};
260590
+ for (const [k, val] of Object.entries(v.env)) {
260591
+ if (typeof val === "string")
260592
+ env2[k] = val;
260593
+ }
260594
+ if (Object.keys(env2).length > 0)
260595
+ cfg.env = env2;
260596
+ }
260597
+ return cfg;
260598
+ }
260599
+ if (typeof v.url === "string" && /^https?:\/\//i.test(v.url)) {
260600
+ const type = v.type === "sse" ? "sse" : "http";
260601
+ const cfg = { type, url: v.url };
260602
+ if (v.headers && typeof v.headers === "object" && !Array.isArray(v.headers)) {
260603
+ const headers = {};
260604
+ for (const [k, val] of Object.entries(v.headers)) {
260605
+ if (typeof val === "string")
260606
+ headers[k] = val;
260607
+ }
260608
+ if (Object.keys(headers).length > 0)
260609
+ cfg.headers = headers;
260610
+ }
260611
+ return cfg;
260612
+ }
260613
+ return null;
260614
+ }
260615
+ function parseMcpServersBlock(json) {
260616
+ if (!json || typeof json !== "object")
260617
+ return [];
260618
+ const root = json;
260619
+ if (!root.mcpServers || typeof root.mcpServers !== "object")
260620
+ return [];
260621
+ const out = [];
260622
+ for (const [name10, raw] of Object.entries(root.mcpServers)) {
260623
+ const cfg = coerceServerConfig(raw);
260624
+ if (cfg) {
260625
+ out.push({
260626
+ name: slugify(name10),
260627
+ config: cfg,
260628
+ confidence: 1,
260629
+ source: "json-mcpServers"
260630
+ });
260631
+ }
260632
+ }
260633
+ return out;
260634
+ }
260635
+ function parseBareServerBlock(json, blockIdx) {
260636
+ const cfg = coerceServerConfig(json);
260637
+ if (!cfg)
260638
+ return null;
260639
+ let name10 = `mcp-server-${blockIdx + 1}`;
260640
+ if ("command" in cfg && cfg.command) {
260641
+ const args = cfg.args ?? [];
260642
+ const pkg = args.find((a2) => /^@?[\w-]+\/?[\w-]*-?mcp/.test(a2) || /server-/.test(a2));
260643
+ if (pkg)
260644
+ name10 = slugify(pkg.replace(/^@[^/]+\//, "").replace(/^-y$/, ""));
260645
+ else if (typeof cfg.command === "string")
260646
+ name10 = slugify(cfg.command.split("/").pop() || cfg.command);
260647
+ } else if ("url" in cfg && cfg.url) {
260648
+ try {
260649
+ const u = new URL(cfg.url);
260650
+ name10 = slugify(u.hostname.replace(/^www\./, "").replace(/\.(com|io|net|ai|app|dev)$/, ""));
260651
+ } catch {
260652
+ }
260653
+ }
260654
+ return { name: name10, config: cfg, confidence: 0.85, source: "json-bare-server" };
260655
+ }
260656
+ function parseNpxCommand(code8, blockIdx) {
260657
+ const m2 = code8.match(/\bnpx\s+(?:-y\s+|--yes\s+)?([@\w./-]+)(?:\s+(.+))?/);
260658
+ if (!m2)
260659
+ return null;
260660
+ const pkg = m2[1];
260661
+ const extraArgs = m2[2] ? m2[2].trim().split(/\s+/) : [];
260662
+ const isMcp = /mcp/i.test(pkg) || /^@modelcontextprotocol\//.test(pkg) || /server-/.test(pkg);
260663
+ if (!isMcp)
260664
+ return null;
260665
+ const args = ["-y", pkg, ...extraArgs];
260666
+ const name10 = slugify(pkg.replace(/^@[^/]+\//, "").replace(/^server-/, "").replace(/-mcp(-server)?$/, "").replace(/-server$/, ""));
260667
+ return {
260668
+ name: name10,
260669
+ config: { type: "stdio", command: "npx", args },
260670
+ confidence: /mcp/i.test(pkg) ? 0.9 : 0.7,
260671
+ source: "code-npx"
260672
+ };
260673
+ }
260674
+ function parseHttpUrlBlock(code8, hasMcpContext) {
260675
+ if (!hasMcpContext)
260676
+ return null;
260677
+ const m2 = code8.match(/(https?:\/\/[^\s"'`<>]+)/);
260678
+ if (!m2)
260679
+ return null;
260680
+ const url = m2[1];
260681
+ if (!/mcp/i.test(url) && !/sse$/.test(url))
260682
+ return null;
260683
+ let name10 = "mcp-http";
260684
+ try {
260685
+ const u = new URL(url);
260686
+ name10 = slugify(u.hostname.replace(/^www\./, "").replace(/\.(com|io|net|ai|app|dev)$/, ""));
260687
+ } catch {
260688
+ }
260689
+ return {
260690
+ name: name10,
260691
+ config: { type: "http", url },
260692
+ confidence: 0.6,
260693
+ source: "code-url"
260694
+ };
260695
+ }
260696
+ function parseMcpMarkdown(md) {
260697
+ const notes2 = [];
260698
+ const servers = [];
260699
+ const isMcp = isMcpMarkdown(md);
260700
+ const blocks = extractCodeBlocks(md);
260701
+ blocks.forEach((block, idx) => {
260702
+ const lang = block.lang;
260703
+ if (lang === "json" || lang === "jsonc" || lang === "json5" || lang === "" || lang === "text") {
260704
+ const parsed = tryParseJson(block.code);
260705
+ if (parsed) {
260706
+ const fromWrapper = parseMcpServersBlock(parsed);
260707
+ if (fromWrapper.length > 0) {
260708
+ servers.push(...fromWrapper);
260709
+ return;
260710
+ }
260711
+ const bare = parseBareServerBlock(parsed, idx);
260712
+ if (bare) {
260713
+ servers.push(bare);
260714
+ return;
260715
+ }
260716
+ }
260717
+ }
260718
+ if (lang === "sh" || lang === "bash" || lang === "shell" || lang === "console" || lang === "zsh" || lang === "") {
260719
+ const npx = parseNpxCommand(block.code, idx);
260720
+ if (npx) {
260721
+ servers.push(npx);
260722
+ return;
260723
+ }
260724
+ }
260725
+ if (isMcp) {
260726
+ const http6 = parseHttpUrlBlock(block.code, true);
260727
+ if (http6) {
260728
+ servers.push(http6);
260729
+ return;
260730
+ }
260731
+ }
260732
+ });
260733
+ const byName = /* @__PURE__ */ new Map();
260734
+ for (const s2 of servers) {
260735
+ const existing = byName.get(s2.name);
260736
+ if (!existing || s2.confidence > existing.confidence) {
260737
+ byName.set(s2.name, s2);
260738
+ }
260739
+ }
260740
+ const finalServers = Array.from(byName.values()).sort((a2, b) => b.confidence - a2.confidence);
260741
+ if (finalServers.length === 0 && isMcp) {
260742
+ notes2.push("Markdown looks MCP-related but no valid server config could be extracted from code blocks.");
260743
+ }
260744
+ return {
260745
+ servers: finalServers,
260746
+ isMcpDocument: isMcp,
260747
+ notes: notes2
260748
+ };
260749
+ }
260750
+ var MCP_KEYWORDS;
260751
+ var init_md_intake = __esm({
260752
+ "packages/execution/dist/mcp/md-intake.js"() {
260753
+ "use strict";
260754
+ MCP_KEYWORDS = [
260755
+ "mcp",
260756
+ "model context protocol",
260757
+ "modelcontextprotocol",
260758
+ "mcpServers",
260759
+ "MCP server"
260760
+ ];
260761
+ }
260762
+ });
260763
+
260302
260764
  // packages/execution/dist/mcp/index.js
260303
260765
  var init_mcp = __esm({
260304
260766
  "packages/execution/dist/mcp/index.js"() {
@@ -260306,6 +260768,7 @@ var init_mcp = __esm({
260306
260768
  init_client3();
260307
260769
  init_manager2();
260308
260770
  init_transport5();
260771
+ init_md_intake();
260309
260772
  }
260310
260773
  });
260311
260774
 
@@ -260470,7 +260933,7 @@ var init_plugin_system = __esm({
260470
260933
  });
260471
260934
 
260472
260935
  // packages/execution/dist/tools/notebook-edit.js
260473
- import { readFileSync as readFileSync31, writeFileSync as writeFileSync17, existsSync as existsSync41 } from "node:fs";
260936
+ import { readFileSync as readFileSync31, writeFileSync as writeFileSync18, existsSync as existsSync41 } from "node:fs";
260474
260937
  function readNotebook(path5) {
260475
260938
  if (!existsSync41(path5))
260476
260939
  return `File not found: ${path5}`;
@@ -260487,7 +260950,7 @@ function readNotebook(path5) {
260487
260950
  }
260488
260951
  }
260489
260952
  function writeNotebook(path5, nb) {
260490
- writeFileSync17(path5, JSON.stringify(nb, null, 1) + "\n", "utf8");
260953
+ writeFileSync18(path5, JSON.stringify(nb, null, 1) + "\n", "utf8");
260491
260954
  }
260492
260955
  function sourceToLines(source) {
260493
260956
  const lines = source.split("\n");
@@ -260771,7 +261234,7 @@ var init_environment_snapshot = __esm({
260771
261234
 
260772
261235
  // packages/execution/dist/tools/video-understand.js
260773
261236
  import { execSync as execSync42 } from "node:child_process";
260774
- import { existsSync as existsSync42, mkdirSync as mkdirSync20, writeFileSync as writeFileSync18, readFileSync as readFileSync32, readdirSync as readdirSync9, unlinkSync as unlinkSync9 } from "node:fs";
261237
+ import { existsSync as existsSync42, mkdirSync as mkdirSync21, writeFileSync as writeFileSync19, readFileSync as readFileSync32, readdirSync as readdirSync9, unlinkSync as unlinkSync9 } from "node:fs";
260775
261238
  import { join as join56, basename as basename11 } from "node:path";
260776
261239
  import { createHash as createHash2 } from "node:crypto";
260777
261240
  function isYouTubeUrl2(url) {
@@ -260859,9 +261322,9 @@ var init_video_understand = __esm({
260859
261322
  return { success: false, output: "", error: "url or path required", durationMs: performance.now() - start2 };
260860
261323
  }
260861
261324
  const outDir = join56(this.workingDir, ".oa", "video-analysis");
260862
- mkdirSync20(outDir, { recursive: true });
261325
+ mkdirSync21(outDir, { recursive: true });
260863
261326
  const tmpDir = join56(outDir, `tmp-${Date.now()}`);
260864
- mkdirSync20(tmpDir, { recursive: true });
261327
+ mkdirSync21(tmpDir, { recursive: true });
260865
261328
  try {
260866
261329
  let videoPath;
260867
261330
  let audioPath;
@@ -260916,7 +261379,7 @@ var init_video_understand = __esm({
260916
261379
  let frames = [];
260917
261380
  if (!skipFrames && ensureFfmpeg() && existsSync42(videoPath)) {
260918
261381
  const framesDir = join56(tmpDir, "frames");
260919
- mkdirSync20(framesDir, { recursive: true });
261382
+ mkdirSync21(framesDir, { recursive: true });
260920
261383
  const fps = 25;
260921
261384
  const intervalFrames = Math.max(1, frameInterval * fps);
260922
261385
  try {
@@ -260937,11 +261400,11 @@ var init_video_understand = __esm({
260937
261400
  }
260938
261401
  deduplicateFrames(frames);
260939
261402
  const permanentDir = join56(outDir, `frames-${Date.now()}`);
260940
- mkdirSync20(permanentDir, { recursive: true });
261403
+ mkdirSync21(permanentDir, { recursive: true });
260941
261404
  for (const frame of frames.filter((f2) => !f2.isDuplicate)) {
260942
261405
  const dest = join56(permanentDir, basename11(frame.path));
260943
261406
  try {
260944
- writeFileSync18(dest, readFileSync32(frame.path));
261407
+ writeFileSync19(dest, readFileSync32(frame.path));
260945
261408
  frame.path = dest;
260946
261409
  } catch {
260947
261410
  }
@@ -260978,10 +261441,10 @@ var init_video_understand = __esm({
260978
261441
  };
260979
261442
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
260980
261443
  const resultFile = join56(outDir, `understanding-${timestamp}.json`);
260981
- writeFileSync18(resultFile, JSON.stringify(result, null, 2), "utf-8");
261444
+ writeFileSync19(resultFile, JSON.stringify(result, null, 2), "utf-8");
260982
261445
  try {
260983
261446
  const memDir = join56(this.workingDir, ".oa", "memory");
260984
- mkdirSync20(memDir, { recursive: true });
261447
+ mkdirSync21(memDir, { recursive: true });
260985
261448
  const indexFile = join56(memDir, "video-analyses.json");
260986
261449
  let indexEntries = [];
260987
261450
  try {
@@ -261001,7 +261464,7 @@ var init_video_understand = __esm({
261001
261464
  });
261002
261465
  if (indexEntries.length > 30)
261003
261466
  indexEntries = indexEntries.slice(-30);
261004
- writeFileSync18(indexFile, JSON.stringify(indexEntries, null, 2), "utf-8");
261467
+ writeFileSync19(indexFile, JSON.stringify(indexEntries, null, 2), "utf-8");
261005
261468
  const CHUNK_WINDOW = 30;
261006
261469
  const transcriptFile = join56(memDir, "video-transcripts.json");
261007
261470
  let transcriptEntries = {};
@@ -261032,7 +261495,7 @@ var init_video_understand = __esm({
261032
261495
  Topic: ${segments.slice(0, 5).map((s2) => s2.text).join(" ").slice(0, 300)}`,
261033
261496
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
261034
261497
  };
261035
- writeFileSync18(transcriptFile, JSON.stringify(transcriptEntries, null, 2), "utf-8");
261498
+ writeFileSync19(transcriptFile, JSON.stringify(transcriptEntries, null, 2), "utf-8");
261036
261499
  } catch {
261037
261500
  }
261038
261501
  const lines = [];
@@ -261352,8 +261815,8 @@ var init_gitWorktree = __esm({
261352
261815
  });
261353
261816
 
261354
261817
  // packages/execution/dist/patchApplier.js
261355
- import { readFileSync as readFileSync34, writeFileSync as writeFileSync19, existsSync as existsSync44, mkdirSync as mkdirSync21 } from "node:fs";
261356
- import { dirname as dirname14 } from "node:path";
261818
+ import { readFileSync as readFileSync34, writeFileSync as writeFileSync20, existsSync as existsSync44, mkdirSync as mkdirSync22 } from "node:fs";
261819
+ import { dirname as dirname15 } from "node:path";
261357
261820
  import { spawn as spawn17 } from "node:child_process";
261358
261821
  async function applyPatch(patch) {
261359
261822
  switch (patch.type) {
@@ -261373,17 +261836,17 @@ function applyBlockReplace(patch) {
261373
261836
  throw new Error(`Block not found in "${patch.filePath}": the oldContent string was not found in the file.`);
261374
261837
  }
261375
261838
  const updated = original.replace(patch.oldContent, patch.newContent);
261376
- writeFileSync19(patch.filePath, updated, "utf-8");
261839
+ writeFileSync20(patch.filePath, updated, "utf-8");
261377
261840
  }
261378
261841
  function applyRewrite(patch) {
261379
- writeFileSync19(patch.filePath, patch.newContent, "utf-8");
261842
+ writeFileSync20(patch.filePath, patch.newContent, "utf-8");
261380
261843
  }
261381
261844
  function applyNewFile(patch) {
261382
261845
  if (existsSync44(patch.filePath)) {
261383
261846
  throw new Error(`Cannot create new file: "${patch.filePath}" already exists.`);
261384
261847
  }
261385
- mkdirSync21(dirname14(patch.filePath), { recursive: true });
261386
- writeFileSync19(patch.filePath, patch.newContent, "utf-8");
261848
+ mkdirSync22(dirname15(patch.filePath), { recursive: true });
261849
+ writeFileSync20(patch.filePath, patch.newContent, "utf-8");
261387
261850
  }
261388
261851
  async function applyUnifiedDiff(patch) {
261389
261852
  const { filePath, diff } = patch;
@@ -261394,7 +261857,7 @@ async function applyUnifiedDiff(patch) {
261394
261857
  "-p1",
261395
261858
  filePath
261396
261859
  ],
261397
- cwd: dirname14(filePath),
261860
+ cwd: dirname15(filePath),
261398
261861
  stdin: diff
261399
261862
  });
261400
261863
  if (!result.success) {
@@ -261740,7 +262203,7 @@ var init_buildRunner = __esm({
261740
262203
  });
261741
262204
 
261742
262205
  // packages/execution/dist/constraints.js
261743
- import { existsSync as existsSync45, readFileSync as readFileSync35, writeFileSync as writeFileSync20, mkdirSync as mkdirSync22 } from "node:fs";
262206
+ import { existsSync as existsSync45, readFileSync as readFileSync35, writeFileSync as writeFileSync21, mkdirSync as mkdirSync23 } from "node:fs";
261744
262207
  import { join as join59 } from "node:path";
261745
262208
  import { homedir as homedir19 } from "node:os";
261746
262209
  function loadConstraints(projectRoot) {
@@ -261771,8 +262234,8 @@ function addProjectConstraint(projectRoot, constraint) {
261771
262234
  } catch {
261772
262235
  }
261773
262236
  data.constraints.push(constraint);
261774
- mkdirSync22(join59(projectRoot, ".oa"), { recursive: true });
261775
- writeFileSync20(path5, JSON.stringify(data, null, 2), "utf-8");
262237
+ mkdirSync23(join59(projectRoot, ".oa"), { recursive: true });
262238
+ writeFileSync21(path5, JSON.stringify(data, null, 2), "utf-8");
261776
262239
  projectConstraints = data.constraints;
261777
262240
  }
261778
262241
  function getAllConstraints() {
@@ -262079,6 +262542,7 @@ __export(dist_exports, {
262079
262542
  getWorktreeSession: () => getWorktreeSession,
262080
262543
  isFortemiAvailable: () => isFortemiAvailable,
262081
262544
  isImagePath: () => isImagePath,
262545
+ isMcpMarkdown: () => isMcpMarkdown,
262082
262546
  isProcessAlive: () => isProcessAlive,
262083
262547
  killAllFullSubAgents: () => killAllFullSubAgents,
262084
262548
  killProcess: () => killProcess,
@@ -262095,11 +262559,13 @@ __export(dist_exports, {
262095
262559
  markReverted: () => markReverted,
262096
262560
  markSessionValidated: () => markSessionValidated,
262097
262561
  normalizeMcpName: () => normalizeMcpName,
262562
+ parseMcpMarkdown: () => parseMcpMarkdown,
262098
262563
  parseMcpToolName: () => parseMcpToolName,
262099
262564
  promoteWorkingNotes: () => promoteWorkingNotes,
262100
262565
  recordChange: () => recordChange,
262101
262566
  removeAgentWorktree: () => removeWorktree,
262102
262567
  removeFullSubAgent: () => removeFullSubAgent,
262568
+ removeMcpServerFromConfig: () => removeMcpServerFromConfig,
262103
262569
  removeWorktree: () => removeWorktree2,
262104
262570
  resetDepCache: () => resetDepCache,
262105
262571
  resetMoondreamClient: () => resetMoondreamClient,
@@ -262113,6 +262579,7 @@ __export(dist_exports, {
262113
262579
  runTypecheck: () => runTypecheck,
262114
262580
  runValidationPipeline: () => runValidationPipeline,
262115
262581
  saveCustomToolDefinition: () => saveCustomToolDefinition,
262582
+ saveMcpServerToConfig: () => saveMcpServerToConfig,
262116
262583
  serializeMap: () => serializeMap,
262117
262584
  setChangeLogSession: () => setChangeLogSession,
262118
262585
  setSudoPassword: () => setSudoPassword,
@@ -262903,7 +263370,7 @@ var init_dist5 = __esm({
262903
263370
 
262904
263371
  // packages/orchestrator/dist/promptLoader.js
262905
263372
  import { readFileSync as readFileSync36, existsSync as existsSync46 } from "node:fs";
262906
- import { join as join60, dirname as dirname15 } from "node:path";
263373
+ import { join as join60, dirname as dirname16 } from "node:path";
262907
263374
  import { fileURLToPath as fileURLToPath8 } from "node:url";
262908
263375
  function loadPrompt(promptPath, vars) {
262909
263376
  let content = cache4.get(promptPath);
@@ -262924,7 +263391,7 @@ var init_promptLoader = __esm({
262924
263391
  "packages/orchestrator/dist/promptLoader.js"() {
262925
263392
  "use strict";
262926
263393
  __filename3 = fileURLToPath8(import.meta.url);
262927
- __dirname5 = dirname15(__filename3);
263394
+ __dirname5 = dirname16(__filename3);
262928
263395
  PROMPTS_DIR = join60(__dirname5, "..", "prompts");
262929
263396
  cache4 = /* @__PURE__ */ new Map();
262930
263397
  }
@@ -265571,7 +266038,7 @@ var init_toolPatternStore = __esm({
265571
266038
 
265572
266039
  // packages/memory/dist/episodeStore.js
265573
266040
  import { join as join63 } from "node:path";
265574
- import { mkdirSync as mkdirSync23, existsSync as existsSync47 } from "node:fs";
266041
+ import { mkdirSync as mkdirSync24, existsSync as existsSync47 } from "node:fs";
265575
266042
  import { randomUUID as randomUUID5 } from "node:crypto";
265576
266043
  import { createHash as createHash3 } from "node:crypto";
265577
266044
  function autoImportance(toolName, modality, content) {
@@ -265637,7 +266104,7 @@ var init_episodeStore = __esm({
265637
266104
  constructor(dbPath) {
265638
266105
  const dir = dbPath === ":memory:" ? null : join63(dbPath, "..");
265639
266106
  if (dir && !existsSync47(dir))
265640
- mkdirSync23(dir, { recursive: true });
266107
+ mkdirSync24(dir, { recursive: true });
265641
266108
  this.db = initDb(dbPath);
265642
266109
  this.db.exec(`
265643
266110
  CREATE TABLE IF NOT EXISTS episodes (
@@ -265812,7 +266279,7 @@ var init_episodeStore = __esm({
265812
266279
 
265813
266280
  // packages/memory/dist/temporalGraph.js
265814
266281
  import { join as join64 } from "node:path";
265815
- import { mkdirSync as mkdirSync24, existsSync as existsSync48 } from "node:fs";
266282
+ import { mkdirSync as mkdirSync25, existsSync as existsSync48 } from "node:fs";
265816
266283
  import { randomUUID as randomUUID6 } from "node:crypto";
265817
266284
  var TemporalGraph;
265818
266285
  var init_temporalGraph = __esm({
@@ -265824,7 +266291,7 @@ var init_temporalGraph = __esm({
265824
266291
  constructor(dbPath) {
265825
266292
  const dir = dbPath === ":memory:" ? null : join64(dbPath, "..");
265826
266293
  if (dir && !existsSync48(dir))
265827
- mkdirSync24(dir, { recursive: true });
266294
+ mkdirSync25(dir, { recursive: true });
265828
266295
  this.db = initDb(dbPath);
265829
266296
  this.db.exec(`
265830
266297
  CREATE TABLE IF NOT EXISTS kg_nodes (
@@ -269717,11 +270184,11 @@ ${errOutput}`;
269717
270184
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
269718
270185
  });
269719
270186
  try {
269720
- const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync43 } = __require("node:fs");
270187
+ const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync44 } = __require("node:fs");
269721
270188
  const { join: join100 } = __require("node:path");
269722
270189
  const resultsDir = join100(process.cwd(), ".oa", "tool-results");
269723
- mkdirSync49(resultsDir, { recursive: true });
269724
- writeFileSync43(join100(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
270190
+ mkdirSync50(resultsDir, { recursive: true });
270191
+ writeFileSync44(join100(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
269725
270192
  # Turn: ${turn}
269726
270193
  # Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
269727
270194
  # Size: ${result.output.length} chars, ${lineCount} lines
@@ -269860,10 +270327,10 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
269860
270327
  if (!this._workingDirectory)
269861
270328
  return;
269862
270329
  try {
269863
- const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync43 } = __require("node:fs");
270330
+ const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync44 } = __require("node:fs");
269864
270331
  const { join: join100 } = __require("node:path");
269865
270332
  const sessionDir = join100(this._workingDirectory, ".oa", "session", this._sessionId);
269866
- mkdirSync49(sessionDir, { recursive: true });
270333
+ mkdirSync50(sessionDir, { recursive: true });
269867
270334
  const checkpoint = {
269868
270335
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
269869
270336
  sessionId: this._sessionId,
@@ -269875,7 +270342,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
269875
270342
  memexEntryCount: this._memexArchive.size,
269876
270343
  fileRegistrySize: this._fileRegistry.size
269877
270344
  };
269878
- writeFileSync43(join100(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
270345
+ writeFileSync44(join100(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
269879
270346
  } catch {
269880
270347
  }
269881
270348
  }
@@ -271296,12 +271763,12 @@ ${result}`
271296
271763
  let resizedBase64 = null;
271297
271764
  try {
271298
271765
  const { execSync: execSync56 } = await import("node:child_process");
271299
- const { writeFileSync: writeFileSync43, readFileSync: readFileSync62, unlinkSync: unlinkSync19 } = await import("node:fs");
271766
+ const { writeFileSync: writeFileSync44, readFileSync: readFileSync62, unlinkSync: unlinkSync19 } = await import("node:fs");
271300
271767
  const { join: join100 } = await import("node:path");
271301
271768
  const { tmpdir: tmpdir21 } = await import("node:os");
271302
271769
  const tmpIn = join100(tmpdir21(), `oa_img_in_${Date.now()}.png`);
271303
271770
  const tmpOut = join100(tmpdir21(), `oa_img_out_${Date.now()}.jpg`);
271304
- writeFileSync43(tmpIn, buffer2);
271771
+ writeFileSync44(tmpIn, buffer2);
271305
271772
  const pyBin = process.platform === "win32" ? "python" : "python3";
271306
271773
  const escapedIn = tmpIn.replace(/\\/g, "\\\\");
271307
271774
  const escapedOut = tmpOut.replace(/\\/g, "\\\\");
@@ -271949,7 +272416,7 @@ var init_constraint_learner = __esm({
271949
272416
  });
271950
272417
 
271951
272418
  // packages/orchestrator/dist/nexusBackend.js
271952
- import { existsSync as existsSync49, statSync as statSync14, openSync, readSync, closeSync, unlinkSync as unlinkSync10, writeFileSync as writeFileSync21 } from "node:fs";
272419
+ import { existsSync as existsSync49, statSync as statSync14, openSync, readSync, closeSync, unlinkSync as unlinkSync10, writeFileSync as writeFileSync22 } from "node:fs";
271953
272420
  import { watch as fsWatch } from "node:fs";
271954
272421
  import { join as join65 } from "node:path";
271955
272422
  import { tmpdir as tmpdir17 } from "node:os";
@@ -272102,7 +272569,7 @@ var init_nexusBackend = __esm({
272102
272569
  */
272103
272570
  async *chatCompletionStream(request) {
272104
272571
  const streamFile = join65(tmpdir17(), `nexus-stream-${randomBytes14(6).toString("hex")}.jsonl`);
272105
- writeFileSync21(streamFile, "", "utf8");
272572
+ writeFileSync22(streamFile, "", "utf8");
272106
272573
  const daemonArgs = {
272107
272574
  model: this.model,
272108
272575
  messages: JSON.stringify(request.messages),
@@ -273748,8 +274215,8 @@ __export(listen_exports, {
273748
274215
  waitForTranscribeCli: () => waitForTranscribeCli
273749
274216
  });
273750
274217
  import { spawn as spawn18, execSync as execSync44 } from "node:child_process";
273751
- import { existsSync as existsSync50, mkdirSync as mkdirSync25, writeFileSync as writeFileSync22, readdirSync as readdirSync10 } from "node:fs";
273752
- import { join as join66, dirname as dirname16 } from "node:path";
274218
+ import { existsSync as existsSync50, mkdirSync as mkdirSync26, writeFileSync as writeFileSync23, readdirSync as readdirSync10 } from "node:fs";
274219
+ import { join as join66, dirname as dirname17 } from "node:path";
273753
274220
  import { homedir as homedir20 } from "node:os";
273754
274221
  import { fileURLToPath as fileURLToPath9 } from "node:url";
273755
274222
  import { EventEmitter as EventEmitter3 } from "node:events";
@@ -273833,7 +274300,7 @@ function findMicCaptureCommand() {
273833
274300
  return null;
273834
274301
  }
273835
274302
  function findLiveWhisperScript() {
273836
- const thisDir = dirname16(fileURLToPath9(import.meta.url));
274303
+ const thisDir = dirname17(fileURLToPath9(import.meta.url));
273837
274304
  const candidates = [
273838
274305
  join66(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
273839
274306
  join66(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
@@ -274392,9 +274859,9 @@ transcribe-cli error: ${transcribeCliError}` : "";
274392
274859
  if (outputDir) {
274393
274860
  const { basename: basename19 } = await import("node:path");
274394
274861
  const transcriptDir = join66(outputDir, ".oa", "transcripts");
274395
- mkdirSync25(transcriptDir, { recursive: true });
274862
+ mkdirSync26(transcriptDir, { recursive: true });
274396
274863
  const outFile = join66(transcriptDir, `${basename19(filePath)}.txt`);
274397
- writeFileSync22(outFile, result.text, "utf-8");
274864
+ writeFileSync23(outFile, result.text, "utf-8");
274398
274865
  }
274399
274866
  return {
274400
274867
  text: result.text,
@@ -280420,7 +280887,7 @@ import { EventEmitter as EventEmitter5 } from "node:events";
280420
280887
  import { randomBytes as randomBytes15 } from "node:crypto";
280421
280888
  import { URL as URL2 } from "node:url";
280422
280889
  import { loadavg, cpus as cpus2, totalmem as totalmem2, freemem as freemem2 } from "node:os";
280423
- import { existsSync as existsSync51, readFileSync as readFileSync37, writeFileSync as writeFileSync23, unlinkSync as unlinkSync11, mkdirSync as mkdirSync26, readdirSync as readdirSync11, statSync as statSync15 } from "node:fs";
280890
+ import { existsSync as existsSync51, readFileSync as readFileSync37, writeFileSync as writeFileSync24, unlinkSync as unlinkSync11, mkdirSync as mkdirSync27, readdirSync as readdirSync11, statSync as statSync15 } from "node:fs";
280424
280891
  import { join as join67 } from "node:path";
280425
280892
  function cleanForwardHeaders(raw, targetHost) {
280426
280893
  const out = {};
@@ -280454,8 +280921,8 @@ function readExposeState(stateDir) {
280454
280921
  }
280455
280922
  function writeExposeState(stateDir, state) {
280456
280923
  try {
280457
- mkdirSync26(stateDir, { recursive: true });
280458
- writeFileSync23(join67(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
280924
+ mkdirSync27(stateDir, { recursive: true });
280925
+ writeFileSync24(join67(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
280459
280926
  } catch {
280460
280927
  }
280461
280928
  }
@@ -280570,8 +281037,8 @@ function readP2PExposeState(stateDir) {
280570
281037
  }
280571
281038
  function writeP2PExposeState(stateDir, state) {
280572
281039
  try {
280573
- mkdirSync26(stateDir, { recursive: true });
280574
- writeFileSync23(join67(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
281040
+ mkdirSync27(stateDir, { recursive: true });
281041
+ writeFileSync24(join67(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
280575
281042
  } catch {
280576
281043
  }
280577
281044
  }
@@ -281973,8 +282440,8 @@ var init_types = __esm({
281973
282440
 
281974
282441
  // packages/cli/src/tui/p2p/secret-vault.ts
281975
282442
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes16, scryptSync as scryptSync2, createHash as createHash4 } from "node:crypto";
281976
- import { readFileSync as readFileSync38, writeFileSync as writeFileSync24, existsSync as existsSync52, mkdirSync as mkdirSync27 } from "node:fs";
281977
- import { dirname as dirname17 } from "node:path";
282443
+ import { readFileSync as readFileSync38, writeFileSync as writeFileSync25, existsSync as existsSync52, mkdirSync as mkdirSync28 } from "node:fs";
282444
+ import { dirname as dirname18 } from "node:path";
281978
282445
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
281979
282446
  var init_secret_vault = __esm({
281980
282447
  "packages/cli/src/tui/p2p/secret-vault.ts"() {
@@ -282180,9 +282647,9 @@ var init_secret_vault = __esm({
282180
282647
  const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
282181
282648
  const tag = cipher.getAuthTag();
282182
282649
  const blob = Buffer.concat([salt, iv, tag, encrypted]);
282183
- const dir = dirname17(this.storePath);
282184
- if (!existsSync52(dir)) mkdirSync27(dir, { recursive: true });
282185
- writeFileSync24(this.storePath, blob, { mode: 384 });
282650
+ const dir = dirname18(this.storePath);
282651
+ if (!existsSync52(dir)) mkdirSync28(dir, { recursive: true });
282652
+ writeFileSync25(this.storePath, blob, { mode: 384 });
282186
282653
  }
282187
282654
  /**
282188
282655
  * Load vault from disk, decrypting with the given passphrase.
@@ -283749,7 +284216,7 @@ var init_render2 = __esm({
283749
284216
 
283750
284217
  // packages/prompts/dist/promptLoader.js
283751
284218
  import { readFileSync as readFileSync39, existsSync as existsSync53 } from "node:fs";
283752
- import { join as join69, dirname as dirname18 } from "node:path";
284219
+ import { join as join69, dirname as dirname19 } from "node:path";
283753
284220
  import { fileURLToPath as fileURLToPath10 } from "node:url";
283754
284221
  function loadPrompt2(promptPath, vars) {
283755
284222
  let content = cache5.get(promptPath);
@@ -283770,7 +284237,7 @@ var init_promptLoader2 = __esm({
283770
284237
  "packages/prompts/dist/promptLoader.js"() {
283771
284238
  "use strict";
283772
284239
  __filename4 = fileURLToPath10(import.meta.url);
283773
- __dirname6 = dirname18(__filename4);
284240
+ __dirname6 = dirname19(__filename4);
283774
284241
  devPath = join69(__dirname6, "..", "templates");
283775
284242
  publishedPath = join69(__dirname6, "..", "prompts", "templates");
283776
284243
  PROMPTS_DIR2 = existsSync53(devPath) ? devPath : publishedPath;
@@ -283884,7 +284351,7 @@ var init_task_templates = __esm({
283884
284351
  });
283885
284352
 
283886
284353
  // packages/prompts/dist/index.js
283887
- import { join as join70, dirname as dirname19 } from "node:path";
284354
+ import { join as join70, dirname as dirname20 } from "node:path";
283888
284355
  import { fileURLToPath as fileURLToPath11 } from "node:url";
283889
284356
  var _dir, _packageRoot;
283890
284357
  var init_dist9 = __esm({
@@ -283894,7 +284361,7 @@ var init_dist9 = __esm({
283894
284361
  init_render2();
283895
284362
  init_task_templates();
283896
284363
  init_render2();
283897
- _dir = dirname19(fileURLToPath11(import.meta.url));
284364
+ _dir = dirname20(fileURLToPath11(import.meta.url));
283898
284365
  _packageRoot = join70(_dir, "..");
283899
284366
  }
283900
284367
  });
@@ -283932,13 +284399,13 @@ __export(oa_directory_exports, {
283932
284399
  writeIndexData: () => writeIndexData,
283933
284400
  writeIndexMeta: () => writeIndexMeta
283934
284401
  });
283935
- import { existsSync as existsSync54, mkdirSync as mkdirSync28, readFileSync as readFileSync40, writeFileSync as writeFileSync25, readdirSync as readdirSync12, statSync as statSync16, unlinkSync as unlinkSync12 } from "node:fs";
284402
+ import { existsSync as existsSync54, mkdirSync as mkdirSync29, readFileSync as readFileSync40, writeFileSync as writeFileSync26, readdirSync as readdirSync12, statSync as statSync16, unlinkSync as unlinkSync12 } from "node:fs";
283936
284403
  import { join as join71, relative as relative4, basename as basename12 } from "node:path";
283937
284404
  import { homedir as homedir21 } from "node:os";
283938
284405
  function initOaDirectory(repoRoot) {
283939
284406
  const oaPath = join71(repoRoot, OA_DIR);
283940
284407
  for (const sub of SUBDIRS) {
283941
- mkdirSync28(join71(oaPath, sub), { recursive: true });
284408
+ mkdirSync29(join71(oaPath, sub), { recursive: true });
283942
284409
  }
283943
284410
  try {
283944
284411
  const gitignorePath = join71(repoRoot, ".gitignore");
@@ -283946,7 +284413,7 @@ function initOaDirectory(repoRoot) {
283946
284413
  if (existsSync54(gitignorePath)) {
283947
284414
  const content = readFileSync40(gitignorePath, "utf-8");
283948
284415
  if (!content.includes(settingsPattern)) {
283949
- writeFileSync25(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
284416
+ writeFileSync26(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
283950
284417
  }
283951
284418
  }
283952
284419
  } catch {
@@ -283968,10 +284435,10 @@ function loadProjectSettings(repoRoot) {
283968
284435
  }
283969
284436
  function saveProjectSettings(repoRoot, settings) {
283970
284437
  const oaPath = join71(repoRoot, OA_DIR);
283971
- mkdirSync28(oaPath, { recursive: true });
284438
+ mkdirSync29(oaPath, { recursive: true });
283972
284439
  const existing = loadProjectSettings(repoRoot);
283973
284440
  const merged = { ...existing, ...settings };
283974
- writeFileSync25(join71(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284441
+ writeFileSync26(join71(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
283975
284442
  }
283976
284443
  function loadGlobalSettings() {
283977
284444
  const settingsPath = join71(homedir21(), ".open-agents", "settings.json");
@@ -283985,10 +284452,10 @@ function loadGlobalSettings() {
283985
284452
  }
283986
284453
  function saveGlobalSettings(settings) {
283987
284454
  const dir = join71(homedir21(), ".open-agents");
283988
- mkdirSync28(dir, { recursive: true });
284455
+ mkdirSync29(dir, { recursive: true });
283989
284456
  const existing = loadGlobalSettings();
283990
284457
  const merged = { ...existing, ...settings };
283991
- writeFileSync25(join71(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284458
+ writeFileSync26(join71(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
283992
284459
  }
283993
284460
  function resolveSettings(repoRoot) {
283994
284461
  const global2 = loadGlobalSettings();
@@ -284064,8 +284531,8 @@ function readIndexMeta(repoRoot) {
284064
284531
  }
284065
284532
  function writeIndexMeta(repoRoot, meta) {
284066
284533
  const metaPath = join71(repoRoot, OA_DIR, "index", "meta.json");
284067
- mkdirSync28(join71(repoRoot, OA_DIR, "index"), { recursive: true });
284068
- writeFileSync25(metaPath, JSON.stringify(meta, null, 2), "utf-8");
284534
+ mkdirSync29(join71(repoRoot, OA_DIR, "index"), { recursive: true });
284535
+ writeFileSync26(metaPath, JSON.stringify(meta, null, 2), "utf-8");
284069
284536
  }
284070
284537
  function readIndexData(repoRoot, filename) {
284071
284538
  const filePath = join71(repoRoot, OA_DIR, "index", filename);
@@ -284077,8 +284544,8 @@ function readIndexData(repoRoot, filename) {
284077
284544
  }
284078
284545
  function writeIndexData(repoRoot, filename, data) {
284079
284546
  const filePath = join71(repoRoot, OA_DIR, "index", filename);
284080
- mkdirSync28(join71(repoRoot, OA_DIR, "index"), { recursive: true });
284081
- writeFileSync25(filePath, JSON.stringify(data, null, 2), "utf-8");
284547
+ mkdirSync29(join71(repoRoot, OA_DIR, "index"), { recursive: true });
284548
+ writeFileSync26(filePath, JSON.stringify(data, null, 2), "utf-8");
284082
284549
  }
284083
284550
  function generateProjectMap(repoRoot) {
284084
284551
  const sections = [];
@@ -284126,14 +284593,14 @@ ${tree2}\`\`\`
284126
284593
  }
284127
284594
  const content = sections.join("\n");
284128
284595
  const contextDir = join71(repoRoot, OA_DIR, "context");
284129
- mkdirSync28(contextDir, { recursive: true });
284130
- writeFileSync25(join71(contextDir, "project-map.md"), content, "utf-8");
284596
+ mkdirSync29(contextDir, { recursive: true });
284597
+ writeFileSync26(join71(contextDir, "project-map.md"), content, "utf-8");
284131
284598
  return content;
284132
284599
  }
284133
284600
  function saveSession(repoRoot, session) {
284134
284601
  const historyDir = join71(repoRoot, OA_DIR, "history");
284135
- mkdirSync28(historyDir, { recursive: true });
284136
- writeFileSync25(
284602
+ mkdirSync29(historyDir, { recursive: true });
284603
+ writeFileSync26(
284137
284604
  join71(historyDir, `${session.id}.json`),
284138
284605
  JSON.stringify(session, null, 2),
284139
284606
  "utf-8"
@@ -284162,8 +284629,8 @@ function loadRecentSessions(repoRoot, limit = 5) {
284162
284629
  }
284163
284630
  function savePendingTask(repoRoot, task) {
284164
284631
  const historyDir = join71(repoRoot, OA_DIR, "history");
284165
- mkdirSync28(historyDir, { recursive: true });
284166
- writeFileSync25(
284632
+ mkdirSync29(historyDir, { recursive: true });
284633
+ writeFileSync26(
284167
284634
  join71(historyDir, PENDING_TASK_FILE),
284168
284635
  JSON.stringify(task, null, 2) + "\n",
284169
284636
  "utf-8"
@@ -284185,7 +284652,7 @@ function loadPendingTask(repoRoot) {
284185
284652
  }
284186
284653
  function saveSessionContext(repoRoot, entry) {
284187
284654
  const contextDir = join71(repoRoot, OA_DIR, "context");
284188
- mkdirSync28(contextDir, { recursive: true });
284655
+ mkdirSync29(contextDir, { recursive: true });
284189
284656
  const filePath = join71(contextDir, CONTEXT_SAVE_FILE);
284190
284657
  let ctx3;
284191
284658
  try {
@@ -284202,7 +284669,7 @@ function saveSessionContext(repoRoot, entry) {
284202
284669
  ctx3.entries = ctx3.entries.slice(-ctx3.maxEntries);
284203
284670
  }
284204
284671
  ctx3.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
284205
- writeFileSync25(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
284672
+ writeFileSync26(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
284206
284673
  try {
284207
284674
  const diaryLines = ["# Session Diary", ""];
284208
284675
  for (const e2 of ctx3.entries.slice(-10)) {
@@ -284216,7 +284683,7 @@ function saveSessionContext(repoRoot, entry) {
284216
284683
  if (e2.summary) diaryLines.push(`Summary: ${e2.summary.slice(0, 200)}`);
284217
284684
  diaryLines.push("");
284218
284685
  }
284219
- writeFileSync25(join71(contextDir, "session-diary.md"), diaryLines.join("\n"), "utf-8");
284686
+ writeFileSync26(join71(contextDir, "session-diary.md"), diaryLines.join("\n"), "utf-8");
284220
284687
  } catch {
284221
284688
  }
284222
284689
  }
@@ -284252,14 +284719,14 @@ function getLastTaskSummary(repoRoot) {
284252
284719
  }
284253
284720
  function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
284254
284721
  const sessDir = join71(repoRoot, OA_DIR, SESSIONS_DIR);
284255
- mkdirSync28(sessDir, { recursive: true });
284722
+ mkdirSync29(sessDir, { recursive: true });
284256
284723
  const stripped = contentLines.map(
284257
284724
  (line) => typeof line === "string" ? line.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "") : ""
284258
284725
  );
284259
284726
  const autoName = meta.name || generateSessionName(stripped);
284260
284727
  const autoDesc = meta.description || generateSessionDescription(stripped);
284261
284728
  const contentPath = join71(sessDir, `${sessionId}.jsonl`);
284262
- writeFileSync25(contentPath, stripped.join("\n"), "utf-8");
284729
+ writeFileSync26(contentPath, stripped.join("\n"), "utf-8");
284263
284730
  const indexPath = join71(sessDir, SESSIONS_INDEX);
284264
284731
  let index = [];
284265
284732
  try {
@@ -284290,7 +284757,7 @@ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
284290
284757
  } catch {
284291
284758
  }
284292
284759
  }
284293
- writeFileSync25(indexPath, JSON.stringify(index, null, 2), "utf-8");
284760
+ writeFileSync26(indexPath, JSON.stringify(index, null, 2), "utf-8");
284294
284761
  }
284295
284762
  function listSessions(repoRoot) {
284296
284763
  const indexPath = join71(repoRoot, OA_DIR, SESSIONS_DIR, SESSIONS_INDEX);
@@ -284320,7 +284787,7 @@ function deleteSession(repoRoot, sessionId) {
284320
284787
  if (existsSync54(indexPath)) {
284321
284788
  let index = JSON.parse(readFileSync40(indexPath, "utf-8"));
284322
284789
  index = index.filter((s2) => s2.id !== sessionId);
284323
- writeFileSync25(indexPath, JSON.stringify(index, null, 2), "utf-8");
284790
+ writeFileSync26(indexPath, JSON.stringify(index, null, 2), "utf-8");
284324
284791
  }
284325
284792
  return true;
284326
284793
  } catch {
@@ -284454,8 +284921,8 @@ function loadUsageFile(filePath) {
284454
284921
  }
284455
284922
  function saveUsageFile(filePath, data) {
284456
284923
  const dir = join71(filePath, "..");
284457
- mkdirSync28(dir, { recursive: true });
284458
- writeFileSync25(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284924
+ mkdirSync29(dir, { recursive: true });
284925
+ writeFileSync26(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284459
284926
  }
284460
284927
  function recordUsage(kind, value2, opts) {
284461
284928
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -289073,8 +289540,8 @@ __export(personaplex_exports, {
289073
289540
  startPersonaPlexDaemon: () => startPersonaPlexDaemon,
289074
289541
  stopPersonaPlex: () => stopPersonaPlex
289075
289542
  });
289076
- import { existsSync as existsSync55, writeFileSync as writeFileSync26, readFileSync as readFileSync42, mkdirSync as mkdirSync29, copyFileSync as copyFileSync2, readdirSync as readdirSync13, statSync as statSync17 } from "node:fs";
289077
- import { join as join72, dirname as dirname20 } from "node:path";
289543
+ import { existsSync as existsSync55, writeFileSync as writeFileSync27, readFileSync as readFileSync42, mkdirSync as mkdirSync30, copyFileSync as copyFileSync2, readdirSync as readdirSync13, statSync as statSync17 } from "node:fs";
289544
+ import { join as join72, dirname as dirname21 } from "node:path";
289078
289545
  import { homedir as homedir22 } from "node:os";
289079
289546
  import { execSync as execSync47, spawn as spawn21 } from "node:child_process";
289080
289547
  import { fileURLToPath as fileURLToPath12 } from "node:url";
@@ -289211,7 +289678,7 @@ function getWeightTier() {
289211
289678
  if (saved in WEIGHT_REPOS) {
289212
289679
  const vram = detected.vramGB;
289213
289680
  if (saved === "nf4-distilled" && vram < 24) {
289214
- writeFileSync26(tierFile, "nf4");
289681
+ writeFileSync27(tierFile, "nf4");
289215
289682
  return "nf4";
289216
289683
  }
289217
289684
  return saved;
@@ -289225,7 +289692,7 @@ function getWeightRepoInfo(tier) {
289225
289692
  async function installPersonaPlex(onInfo, weightTier) {
289226
289693
  const log22 = onInfo ?? (() => {
289227
289694
  });
289228
- mkdirSync29(PERSONAPLEX_DIR, { recursive: true });
289695
+ mkdirSync30(PERSONAPLEX_DIR, { recursive: true });
289229
289696
  let arch2 = "";
289230
289697
  try {
289231
289698
  arch2 = execSync47("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
@@ -289341,7 +289808,7 @@ async function installPersonaPlex(onInfo, weightTier) {
289341
289808
  let src2 = readFileSync42(serverFile, "utf8");
289342
289809
  if (src2.includes('int(request["seed"])')) {
289343
289810
  src2 = src2.replace('int(request["seed"])', 'int(request.query["seed"])');
289344
- writeFileSync26(serverFile, src2);
289811
+ writeFileSync27(serverFile, src2);
289345
289812
  log22("Applied seed parameter bug fix to moshi server.");
289346
289813
  }
289347
289814
  }
@@ -289445,7 +289912,7 @@ $2if filename.endswith(".safetensors"):`
289445
289912
  ${patchPoint}`
289446
289913
  );
289447
289914
  }
289448
- writeFileSync26(loadersFile, src2);
289915
+ writeFileSync27(loadersFile, src2);
289449
289916
  log22("Patched loaders.py with 2-bit TurboQuant native dequant support.");
289450
289917
  }
289451
289918
  }
@@ -289543,7 +290010,7 @@ $2if filename.endswith(".safetensors"):`
289543
290010
  await execAsync(`"${python}" -c "from huggingface_hub import hf_hub_download; hf_hub_download('${nf4.repo}', '${nf4.file}', token=False)"`, {
289544
290011
  timeout: 6e5
289545
290012
  });
289546
- writeFileSync26(join72(PERSONAPLEX_DIR, "weight_tier"), "nf4");
290013
+ writeFileSync27(join72(PERSONAPLEX_DIR, "weight_tier"), "nf4");
289547
290014
  log22(`Downloaded INT4 weights instead (${nf4.sizeGB}GB, public).`);
289548
290015
  } catch {
289549
290016
  log22("Weight download failed.");
@@ -289555,8 +290022,8 @@ $2if filename.endswith(".safetensors"):`
289555
290022
  log22("Weights will download on first server launch.");
289556
290023
  }
289557
290024
  }
289558
- writeFileSync26(join72(PERSONAPLEX_DIR, "weight_tier"), tier);
289559
- writeFileSync26(join72(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
290025
+ writeFileSync27(join72(PERSONAPLEX_DIR, "weight_tier"), tier);
290026
+ writeFileSync27(join72(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
289560
290027
  log22(`PersonaPlex installed (${tier} tier). Use /call to start voice session.`);
289561
290028
  return true;
289562
290029
  }
@@ -289575,10 +290042,10 @@ async function startPersonaPlexDaemon(onInfo) {
289575
290042
  log22("PersonaPlex not installed. Run /voice personaplex to set up.");
289576
290043
  return null;
289577
290044
  }
289578
- mkdirSync29(PERSONAPLEX_DIR, { recursive: true });
290045
+ mkdirSync30(PERSONAPLEX_DIR, { recursive: true });
289579
290046
  const venvPython2 = process.platform === "win32" ? join72(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join72(PERSONAPLEX_DIR, "venv", "bin", "python3");
289580
290047
  const sslDir = join72(PERSONAPLEX_DIR, "ssl");
289581
- mkdirSync29(sslDir, { recursive: true });
290048
+ mkdirSync30(sslDir, { recursive: true });
289582
290049
  const tier = getWeightTier();
289583
290050
  const repoInfo = WEIGHT_REPOS[tier];
289584
290051
  const extraArgs = [];
@@ -289723,8 +290190,8 @@ print('Converted')
289723
290190
  cwd: PERSONAPLEX_DIR
289724
290191
  });
289725
290192
  if (child.pid) {
289726
- writeFileSync26(PID_FILE, String(child.pid));
289727
- writeFileSync26(PORT_FILE, String(PORT));
290193
+ writeFileSync27(PID_FILE, String(child.pid));
290194
+ writeFileSync27(PORT_FILE, String(PORT));
289728
290195
  registry2.register({
289729
290196
  name: "PersonaPlex",
289730
290197
  pid: child.pid,
@@ -289830,7 +290297,7 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
289830
290297
  log22(`Input WAV not found: ${inputWav}`);
289831
290298
  return null;
289832
290299
  }
289833
- mkdirSync29(CUSTOM_VOICES_DIR, { recursive: true });
290300
+ mkdirSync30(CUSTOM_VOICES_DIR, { recursive: true });
289834
290301
  const outputPt = join72(CUSTOM_VOICES_DIR, `${voiceName}.pt`);
289835
290302
  if (existsSync55(outputPt)) {
289836
290303
  log22(`Voice "${voiceName}" already exists. Delete ${outputPt} to re-clone.`);
@@ -289888,7 +290355,7 @@ function getShippedVoicesDir() {
289888
290355
  // repo root
289889
290356
  ];
289890
290357
  try {
289891
- const modDir = dirname20(fileURLToPath12(import.meta.url));
290358
+ const modDir = dirname21(fileURLToPath12(import.meta.url));
289892
290359
  candidates.push(join72(modDir, "..", "..", "..", "voices", "personaplex"));
289893
290360
  candidates.push(join72(modDir, "..", "..", "..", "..", "voices", "personaplex"));
289894
290361
  } catch {
@@ -289910,7 +290377,7 @@ function provisionShippedVoices(onInfo) {
289910
290377
  const shippedDir = getShippedVoicesDir();
289911
290378
  if (!shippedDir) return 0;
289912
290379
  const hfVoicesDir = getHFVoicesDir();
289913
- mkdirSync29(CUSTOM_VOICES_DIR, { recursive: true });
290380
+ mkdirSync30(CUSTOM_VOICES_DIR, { recursive: true });
289914
290381
  let deployed = 0;
289915
290382
  try {
289916
290383
  for (const f2 of readdirSync13(shippedDir)) {
@@ -289984,7 +290451,7 @@ function patchFrontendVoiceList(onInfo) {
289984
290451
  if (js.includes(needle)) {
289985
290452
  const additions = customVoices.map((v) => `"${v}"`).join(", ");
289986
290453
  js = js.replace(needle, `"VARM4.pt", ${additions}]`);
289987
- writeFileSync26(jsPath, js);
290454
+ writeFileSync27(jsPath, js);
289988
290455
  log22(`Added ${customVoices.length} custom voice(s) to frontend: ${customVoices.map((v) => v.replace(".pt", "")).join(", ")}`);
289989
290456
  }
289990
290457
  }
@@ -290080,7 +290547,7 @@ __export(setup_exports, {
290080
290547
  import * as readline from "node:readline";
290081
290548
  import { execSync as execSync48, spawn as spawn22, exec as exec4 } from "node:child_process";
290082
290549
  import { promisify as promisify7 } from "node:util";
290083
- import { existsSync as existsSync56, writeFileSync as writeFileSync27, readFileSync as readFileSync43, appendFileSync as appendFileSync2, mkdirSync as mkdirSync30 } from "node:fs";
290550
+ import { existsSync as existsSync56, writeFileSync as writeFileSync28, readFileSync as readFileSync43, appendFileSync as appendFileSync2, mkdirSync as mkdirSync31 } from "node:fs";
290084
290551
  import { join as join73 } from "node:path";
290085
290552
  import { homedir as homedir23, platform as platform3 } from "node:os";
290086
290553
  async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
@@ -291260,9 +291727,9 @@ async function doSetup(config, rl) {
291260
291727
  `PARAMETER stop "<|endoftext|>"`
291261
291728
  ].join("\n");
291262
291729
  const modelDir2 = join73(homedir23(), ".open-agents", "models");
291263
- mkdirSync30(modelDir2, { recursive: true });
291730
+ mkdirSync31(modelDir2, { recursive: true });
291264
291731
  const modelfilePath = join73(modelDir2, `Modelfile.${customName}`);
291265
- writeFileSync27(modelfilePath, modelfileContent + "\n", "utf8");
291732
+ writeFileSync28(modelfilePath, modelfileContent + "\n", "utf8");
291266
291733
  process.stdout.write(` ${c3.dim("Creating model...")} `);
291267
291734
  execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
291268
291735
  stdio: "pipe",
@@ -291402,7 +291869,7 @@ function ensureVenv(log22) {
291402
291869
  return null;
291403
291870
  }
291404
291871
  try {
291405
- mkdirSync30(join73(homedir23(), ".open-agents"), { recursive: true });
291872
+ mkdirSync31(join73(homedir23(), ".open-agents"), { recursive: true });
291406
291873
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
291407
291874
  execSync48(`${pyCmd} -m venv --clear "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
291408
291875
  try {
@@ -291629,8 +292096,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
291629
292096
  }
291630
292097
  }
291631
292098
  try {
291632
- mkdirSync30(_visionMarkerDir, { recursive: true });
291633
- writeFileSync27(_visionMarkerFile, JSON.stringify({
292099
+ mkdirSync31(_visionMarkerDir, { recursive: true });
292100
+ writeFileSync28(_visionMarkerFile, JSON.stringify({
291634
292101
  installed: [..._visionPreviouslyInstalled],
291635
292102
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
291636
292103
  }, null, 2));
@@ -291866,9 +292333,9 @@ function createExpandedVariant(baseModel, specs, sizeGB, kvBytesPerToken, archMa
291866
292333
  `PARAMETER stop "<|endoftext|>"`
291867
292334
  ].join("\n");
291868
292335
  const modelDir2 = join73(homedir23(), ".open-agents", "models");
291869
- mkdirSync30(modelDir2, { recursive: true });
292336
+ mkdirSync31(modelDir2, { recursive: true });
291870
292337
  const modelfilePath = join73(modelDir2, `Modelfile.${customName}`);
291871
- writeFileSync27(modelfilePath, modelfileContent + "\n", "utf8");
292338
+ writeFileSync28(modelfilePath, modelfileContent + "\n", "utf8");
291872
292339
  execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
291873
292340
  stdio: "pipe",
291874
292341
  timeout: 12e4
@@ -291891,9 +292358,9 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
291891
292358
  `PARAMETER stop "<|endoftext|>"`
291892
292359
  ].join("\n");
291893
292360
  const modelDir2 = join73(homedir23(), ".open-agents", "models");
291894
- mkdirSync30(modelDir2, { recursive: true });
292361
+ mkdirSync31(modelDir2, { recursive: true });
291895
292362
  const modelfilePath = join73(modelDir2, `Modelfile.${customName}`);
291896
- writeFileSync27(modelfilePath, modelfileContent + "\n", "utf8");
292363
+ writeFileSync28(modelfilePath, modelfileContent + "\n", "utf8");
291897
292364
  await execAsync2(`ollama create ${customName} -f ${modelfilePath}`, {
291898
292365
  timeout: 12e4
291899
292366
  });
@@ -291969,7 +292436,7 @@ async function ensureNeovim() {
291969
292436
  const binDir = join73(homedir23(), ".local", "bin");
291970
292437
  const nvimDest = join73(binDir, "nvim");
291971
292438
  try {
291972
- mkdirSync30(binDir, { recursive: true });
292439
+ mkdirSync31(binDir, { recursive: true });
291973
292440
  } catch {
291974
292441
  }
291975
292442
  const appImageName = arch2 === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
@@ -292779,11 +293246,11 @@ __export(daemon_exports, {
292779
293246
  stopDaemon: () => stopDaemon
292780
293247
  });
292781
293248
  import { spawn as spawn23 } from "node:child_process";
292782
- import { existsSync as existsSync59, readFileSync as readFileSync44, writeFileSync as writeFileSync28, mkdirSync as mkdirSync31, unlinkSync as unlinkSync14 } from "node:fs";
293249
+ import { existsSync as existsSync59, readFileSync as readFileSync44, writeFileSync as writeFileSync29, mkdirSync as mkdirSync32, unlinkSync as unlinkSync14 } from "node:fs";
292783
293250
  import { join as join75 } from "node:path";
292784
293251
  import { homedir as homedir24 } from "node:os";
292785
293252
  import { fileURLToPath as fileURLToPath13 } from "node:url";
292786
- import { dirname as dirname21 } from "node:path";
293253
+ import { dirname as dirname22 } from "node:path";
292787
293254
  function getDaemonPort() {
292788
293255
  const env2 = process.env["OA_HOST"];
292789
293256
  if (env2) {
@@ -292820,7 +293287,7 @@ function getDaemonPid() {
292820
293287
  }
292821
293288
  }
292822
293289
  async function startDaemon() {
292823
- mkdirSync31(OA_DIR2, { recursive: true });
293290
+ mkdirSync32(OA_DIR2, { recursive: true });
292824
293291
  const nodeExe = process.execPath;
292825
293292
  let oaScript = process.argv[1];
292826
293293
  if (!oaScript) {
@@ -292832,7 +293299,7 @@ async function startDaemon() {
292832
293299
  }
292833
293300
  }
292834
293301
  if (!oaScript) {
292835
- const thisDir = dirname21(fileURLToPath13(import.meta.url));
293302
+ const thisDir = dirname22(fileURLToPath13(import.meta.url));
292836
293303
  const indexJs = join75(thisDir, "index.js");
292837
293304
  if (existsSync59(indexJs)) oaScript = indexJs;
292838
293305
  }
@@ -292850,7 +293317,7 @@ async function startDaemon() {
292850
293317
  child.unref();
292851
293318
  const pid = child.pid ?? null;
292852
293319
  if (pid) {
292853
- writeFileSync28(PID_FILE2, String(pid), "utf8");
293320
+ writeFileSync29(PID_FILE2, String(pid), "utf8");
292854
293321
  }
292855
293322
  return pid;
292856
293323
  } catch {
@@ -293318,7 +293785,7 @@ __export(sponsor_wizard_exports, {
293318
293785
  saveSponsorConfig: () => saveSponsorConfig,
293319
293786
  showSponsorDashboard: () => showSponsorDashboard
293320
293787
  });
293321
- import { existsSync as existsSync60, readFileSync as readFileSync45, writeFileSync as writeFileSync29, mkdirSync as mkdirSync32 } from "node:fs";
293788
+ import { existsSync as existsSync60, readFileSync as readFileSync45, writeFileSync as writeFileSync30, mkdirSync as mkdirSync33 } from "node:fs";
293322
293789
  import { join as join76 } from "node:path";
293323
293790
  function colorPreview(code8) {
293324
293791
  return `\x1B[38;5;${code8}m\u2588\u2588\u2588\u2588\x1B[0m (${code8})`;
@@ -293348,9 +293815,9 @@ function loadSponsorConfig(projectDir) {
293348
293815
  }
293349
293816
  function saveSponsorConfig(projectDir, config) {
293350
293817
  const dir = sponsorDir(projectDir);
293351
- mkdirSync32(dir, { recursive: true });
293818
+ mkdirSync33(dir, { recursive: true });
293352
293819
  config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
293353
- writeFileSync29(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
293820
+ writeFileSync30(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
293354
293821
  }
293355
293822
  function defaultConfig2() {
293356
293823
  return {
@@ -294230,8 +294697,8 @@ __export(voice_exports, {
294230
294697
  registerCustomOnnxModel: () => registerCustomOnnxModel,
294231
294698
  resetNarrationContext: () => resetNarrationContext
294232
294699
  });
294233
- import { existsSync as existsSync61, mkdirSync as mkdirSync33, writeFileSync as writeFileSync30, readFileSync as readFileSync46, unlinkSync as unlinkSync15, readdirSync as readdirSync14, statSync as statSync18 } from "node:fs";
294234
- import { join as join77, dirname as dirname22 } from "node:path";
294700
+ import { existsSync as existsSync61, mkdirSync as mkdirSync34, writeFileSync as writeFileSync31, readFileSync as readFileSync46, unlinkSync as unlinkSync15, readdirSync as readdirSync14, statSync as statSync18 } from "node:fs";
294701
+ import { join as join77, dirname as dirname23 } from "node:path";
294235
294702
  import { homedir as homedir25, tmpdir as tmpdir19, platform as platform4 } from "node:os";
294236
294703
  import { execSync as execSync50, spawn as nodeSpawn } from "node:child_process";
294237
294704
  import { createRequire as createRequire3 } from "node:module";
@@ -294288,7 +294755,7 @@ function luxttsInferScript() {
294288
294755
  function writeDetectTorchScript(targetPath) {
294289
294756
  if (existsSync61(targetPath)) return;
294290
294757
  try {
294291
- mkdirSync33(dirname22(targetPath), { recursive: true });
294758
+ mkdirSync34(dirname23(targetPath), { recursive: true });
294292
294759
  } catch {
294293
294760
  }
294294
294761
  const script = `#!/usr/bin/env python3
@@ -294361,7 +294828,7 @@ def main():
294361
294828
  if __name__ == "__main__": main()
294362
294829
  `;
294363
294830
  try {
294364
- writeFileSync30(targetPath, script, { mode: 493 });
294831
+ writeFileSync31(targetPath, script, { mode: 493 });
294365
294832
  } catch {
294366
294833
  }
294367
294834
  }
@@ -295196,7 +295663,7 @@ var init_voice = __esm({
295196
295663
  }
295197
295664
  audioPath = p2;
295198
295665
  const refsDir = luxttsCloneRefsDir();
295199
- if (!existsSync61(refsDir)) mkdirSync33(refsDir, { recursive: true });
295666
+ if (!existsSync61(refsDir)) mkdirSync34(refsDir, { recursive: true });
295200
295667
  const ext = audioPath.split(".").pop() || "wav";
295201
295668
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
295202
295669
  const ts = Date.now().toString(36);
@@ -295204,7 +295671,7 @@ var init_voice = __esm({
295204
295671
  const destPath = join77(refsDir, destFilename);
295205
295672
  try {
295206
295673
  const data = readFileSync46(audioPath);
295207
- writeFileSync30(destPath, data);
295674
+ writeFileSync31(destPath, data);
295208
295675
  } catch (err) {
295209
295676
  return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
295210
295677
  }
@@ -295244,7 +295711,7 @@ var init_voice = __esm({
295244
295711
  return `Failed to synthesize reference audio from ${source.label}.`;
295245
295712
  }
295246
295713
  const refsDir = luxttsCloneRefsDir();
295247
- if (!existsSync61(refsDir)) mkdirSync33(refsDir, { recursive: true });
295714
+ if (!existsSync61(refsDir)) mkdirSync34(refsDir, { recursive: true });
295248
295715
  const destPath = join77(refsDir, `${sourceModelId}-ref.wav`);
295249
295716
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
295250
295717
  this.writeWav(audioData, sampleRate, destPath);
@@ -295274,8 +295741,8 @@ var init_voice = __esm({
295274
295741
  }
295275
295742
  saveCloneMeta(meta) {
295276
295743
  const dir = luxttsCloneRefsDir();
295277
- if (!existsSync61(dir)) mkdirSync33(dir, { recursive: true });
295278
- writeFileSync30(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
295744
+ if (!existsSync61(dir)) mkdirSync34(dir, { recursive: true });
295745
+ writeFileSync31(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
295279
295746
  }
295280
295747
  /** Audio file extensions recognized as clone references */
295281
295748
  static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
@@ -295801,7 +296268,7 @@ var init_voice = __esm({
295801
296268
  buffer2.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
295802
296269
  pos += 2;
295803
296270
  }
295804
- writeFileSync30(path5, buffer2);
296271
+ writeFileSync31(path5, buffer2);
295805
296272
  }
295806
296273
  // -------------------------------------------------------------------------
295807
296274
  // Phonemization
@@ -295875,7 +296342,7 @@ var init_voice = __esm({
295875
296342
  return buffer2;
295876
296343
  }
295877
296344
  writeWav(samples, sampleRate, path5) {
295878
- writeFileSync30(path5, this.buildWavBuffer(samples, sampleRate));
296345
+ writeFileSync31(path5, this.buildWavBuffer(samples, sampleRate));
295879
296346
  }
295880
296347
  // -------------------------------------------------------------------------
295881
296348
  // Audio playback (system default speakers)
@@ -296104,7 +296571,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
296104
296571
  samples[i2] = Math.round(samples[i2] * volume);
296105
296572
  }
296106
296573
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
296107
- writeFileSync30(wavPath, scaled);
296574
+ writeFileSync31(wavPath, scaled);
296108
296575
  }
296109
296576
  } catch {
296110
296577
  }
@@ -296585,8 +297052,8 @@ if __name__ == '__main__':
296585
297052
  main()
296586
297053
  `;
296587
297054
  const scriptPath2 = luxttsInferScript();
296588
- mkdirSync33(voiceDir(), { recursive: true });
296589
- writeFileSync30(scriptPath2, script);
297055
+ mkdirSync34(voiceDir(), { recursive: true });
297056
+ writeFileSync31(scriptPath2, script);
296590
297057
  }
296591
297058
  /** Ensure the LuxTTS daemon is running, spawn if needed */
296592
297059
  async ensureLuxttsDaemon() {
@@ -296726,7 +297193,7 @@ if __name__ == '__main__':
296726
297193
  }
296727
297194
  const header = wavData.subarray(0, 44);
296728
297195
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
296729
- writeFileSync30(wavPath, scaled);
297196
+ writeFileSync31(wavPath, scaled);
296730
297197
  }
296731
297198
  } catch {
296732
297199
  }
@@ -296833,7 +297300,7 @@ if __name__ == '__main__':
296833
297300
  async ensureRuntime() {
296834
297301
  if (this.ort) return;
296835
297302
  const arch2 = process.arch;
296836
- mkdirSync33(voiceDir(), { recursive: true });
297303
+ mkdirSync34(voiceDir(), { recursive: true });
296837
297304
  const pkgPath = join77(voiceDir(), "package.json");
296838
297305
  const expectedDeps = {
296839
297306
  "onnxruntime-node": "^1.21.0",
@@ -296844,13 +297311,13 @@ if __name__ == '__main__':
296844
297311
  const existing = JSON.parse(readFileSync46(pkgPath, "utf8"));
296845
297312
  if (!existing.dependencies?.["phonemizer"]) {
296846
297313
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
296847
- writeFileSync30(pkgPath, JSON.stringify(existing, null, 2));
297314
+ writeFileSync31(pkgPath, JSON.stringify(existing, null, 2));
296848
297315
  }
296849
297316
  } catch {
296850
297317
  }
296851
297318
  }
296852
297319
  if (!existsSync61(pkgPath)) {
296853
- writeFileSync30(pkgPath, JSON.stringify({
297320
+ writeFileSync31(pkgPath, JSON.stringify({
296854
297321
  name: "open-agents-voice",
296855
297322
  private: true,
296856
297323
  dependencies: expectedDeps
@@ -296929,13 +297396,13 @@ Error: ${err instanceof Error ? err.message : String(err)}`
296929
297396
  const onnxPath = modelOnnxPath(id);
296930
297397
  const configPath2 = modelConfigPath(id);
296931
297398
  if (existsSync61(onnxPath) && existsSync61(configPath2)) return;
296932
- mkdirSync33(dir, { recursive: true });
297399
+ mkdirSync34(dir, { recursive: true });
296933
297400
  if (!existsSync61(configPath2)) {
296934
297401
  renderInfo(`Downloading ${model.label} voice config...`);
296935
297402
  const configResp = await fetch(model.configUrl);
296936
297403
  if (!configResp.ok) throw new Error(`Failed to download config: HTTP ${configResp.status}`);
296937
297404
  const configText = await configResp.text();
296938
- writeFileSync30(configPath2, configText);
297405
+ writeFileSync31(configPath2, configText);
296939
297406
  }
296940
297407
  if (!existsSync61(onnxPath)) {
296941
297408
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
@@ -296959,7 +297426,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
296959
297426
  }
296960
297427
  }
296961
297428
  const fullBuffer = Buffer.concat(chunks);
296962
- writeFileSync30(onnxPath, fullBuffer);
297429
+ writeFileSync31(onnxPath, fullBuffer);
296963
297430
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
296964
297431
  }
296965
297432
  }
@@ -297000,7 +297467,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
297000
297467
  // packages/cli/src/tui/commands.ts
297001
297468
  import * as nodeOs from "node:os";
297002
297469
  import { execSync as nodeExecSync } from "node:child_process";
297003
- import { existsSync as existsSync62, readFileSync as readFileSync47, writeFileSync as writeFileSync31, mkdirSync as mkdirSync34, readdirSync as readdirSync15, statSync as statSync19, rmSync as rmSync2, appendFileSync as appendFileSync3 } from "node:fs";
297470
+ import { existsSync as existsSync62, readFileSync as readFileSync47, writeFileSync as writeFileSync32, mkdirSync as mkdirSync35, readdirSync as readdirSync15, statSync as statSync19, rmSync as rmSync2, appendFileSync as appendFileSync3 } from "node:fs";
297004
297471
  import { join as join78 } from "node:path";
297005
297472
  async function _immediateReregister(newUrl) {
297006
297473
  if (!_lastRegisteredSponsorPayload) return;
@@ -298150,7 +298617,7 @@ async function handleSlashCommand(input, ctx3) {
298150
298617
  try {
298151
298618
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
298152
298619
  const dbDir = join78(ctx3.repoRoot, ".oa", "memory");
298153
- mkdirSync34(dbDir, { recursive: true });
298620
+ mkdirSync35(dbDir, { recursive: true });
298154
298621
  const db = initDb2(join78(dbDir, "structured.db"));
298155
298622
  const memStore = new ProceduralMemoryStore2(db);
298156
298623
  if (isAudio) {
@@ -298251,8 +298718,8 @@ async function handleSlashCommand(input, ctx3) {
298251
298718
  nonce: Math.random().toString(36).slice(2, 10)
298252
298719
  };
298253
298720
  const jwtFile = join78(ctx3.repoRoot, ".oa", "fortemi-jwt.json");
298254
- mkdirSync34(join78(ctx3.repoRoot, ".oa"), { recursive: true });
298255
- writeFileSync31(jwtFile, JSON.stringify(jwtPayload, null, 2));
298721
+ mkdirSync35(join78(ctx3.repoRoot, ".oa"), { recursive: true });
298722
+ writeFileSync32(jwtFile, JSON.stringify(jwtPayload, null, 2));
298256
298723
  renderInfo(`Launching fortemi-react from ${fDir}...`);
298257
298724
  try {
298258
298725
  const { spawn: spawn27 } = __require("node:child_process");
@@ -298267,7 +298734,7 @@ async function handleSlashCommand(input, ctx3) {
298267
298734
  renderInfo(`JWT saved to ${jwtFile}`);
298268
298735
  renderInfo("Memory operations will proxy to fortemi when available.");
298269
298736
  const bridgeFile = join78(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
298270
- writeFileSync31(bridgeFile, JSON.stringify({
298737
+ writeFileSync32(bridgeFile, JSON.stringify({
298271
298738
  url: "http://localhost:3000",
298272
298739
  pid: child.pid,
298273
298740
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -298347,6 +298814,10 @@ async function handleSlashCommand(input, ctx3) {
298347
298814
  case "parallel":
298348
298815
  await handleParallel(arg, ctx3);
298349
298816
  return "handled";
298817
+ case "mcp":
298818
+ case "mcps":
298819
+ await handleMcp(arg, ctx3);
298820
+ return "handled";
298350
298821
  case "update":
298351
298822
  case "upgrade":
298352
298823
  await handleUpdate(arg, ctx3);
@@ -299119,7 +299590,7 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
299119
299590
  }
299120
299591
  }
299121
299592
  const _spLogDir = join78(projectDir, ".oa", "sponsor");
299122
- mkdirSync34(_spLogDir, { recursive: true });
299593
+ mkdirSync35(_spLogDir, { recursive: true });
299123
299594
  const _spLogFile = join78(_spLogDir, "sponsor-startup.log");
299124
299595
  const _spLog = (msg) => {
299125
299596
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
@@ -300717,11 +301188,11 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
300717
301188
  continue;
300718
301189
  }
300719
301190
  const { basename: basename19, join: pathJoin } = await import("node:path");
300720
- const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync49, existsSync: exists2 } = await import("node:fs");
301191
+ const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync50, existsSync: exists2 } = await import("node:fs");
300721
301192
  const { homedir: homedir32 } = await import("node:os");
300722
301193
  const modelName = basename19(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
300723
301194
  const destDir = pathJoin(homedir32(), ".open-agents", "voice", "models", modelName);
300724
- if (!exists2(destDir)) mkdirSync49(destDir, { recursive: true });
301195
+ if (!exists2(destDir)) mkdirSync50(destDir, { recursive: true });
300725
301196
  copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
300726
301197
  copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
300727
301198
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -301467,10 +301938,10 @@ async function handleSponsoredEndpoint(ctx3, local) {
301467
301938
  sponsors.push(...verified);
301468
301939
  if (verified.length > 0) {
301469
301940
  try {
301470
- const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync43 } = __require("node:fs");
301471
- mkdirSync49(sponsorDir2, { recursive: true });
301941
+ const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync44 } = __require("node:fs");
301942
+ mkdirSync50(sponsorDir2, { recursive: true });
301472
301943
  const cached = verified.map((s2) => ({ ...s2, lastVerified: Date.now() }));
301473
- writeFileSync43(knownFile, JSON.stringify(cached, null, 2));
301944
+ writeFileSync44(knownFile, JSON.stringify(cached, null, 2));
301474
301945
  } catch {
301475
301946
  }
301476
301947
  }
@@ -301563,11 +302034,11 @@ async function handleSponsoredEndpoint(ctx3, local) {
301563
302034
  }
301564
302035
  const saveKey = selected.url || selected.peerId || selected.name;
301565
302036
  try {
301566
- mkdirSync34(sponsorDir2, { recursive: true });
302037
+ mkdirSync35(sponsorDir2, { recursive: true });
301567
302038
  const existing = existsSync62(knownFile) ? JSON.parse(readFileSync47(knownFile, "utf8")) : [];
301568
302039
  const updated = existing.filter((s2) => (s2.url || s2.peerId || s2.name) !== saveKey);
301569
302040
  updated.push(selected);
301570
- writeFileSync31(knownFile, JSON.stringify(updated, null, 2), "utf8");
302041
+ writeFileSync32(knownFile, JSON.stringify(updated, null, 2), "utf8");
301571
302042
  } catch {
301572
302043
  }
301573
302044
  renderInfo(`Connected to sponsored endpoint: ${selected.name}`);
@@ -301635,11 +302106,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
301635
302106
  const models = await fetchModels(peerUrl, authKey);
301636
302107
  if (models.length > 0) {
301637
302108
  try {
301638
- const { writeFileSync: writeFileSync43, mkdirSync: mkdirSync49 } = await import("node:fs");
301639
- const { join: join100, dirname: dirname28 } = await import("node:path");
302109
+ const { writeFileSync: writeFileSync44, mkdirSync: mkdirSync50 } = await import("node:fs");
302110
+ const { join: join100, dirname: dirname29 } = await import("node:path");
301640
302111
  const cachePath = join100(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
301641
- mkdirSync49(dirname28(cachePath), { recursive: true });
301642
- writeFileSync43(cachePath, JSON.stringify({
302112
+ mkdirSync50(dirname29(cachePath), { recursive: true });
302113
+ writeFileSync44(cachePath, JSON.stringify({
301643
302114
  peerId,
301644
302115
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
301645
302116
  models: models.map((m2) => ({ name: m2.name, size: m2.size, parameterSize: m2.parameterSize }))
@@ -301815,6 +302286,343 @@ Environment="OLLAMA_NUM_PARALLEL=${n2}"
301815
302286
  }
301816
302287
  }
301817
302288
  }
302289
+ async function handleMcp(subcommand, ctx3) {
302290
+ const manager = ctx3.getMcpManager?.();
302291
+ if (!manager) {
302292
+ renderError("MCP manager not initialized");
302293
+ return;
302294
+ }
302295
+ if (subcommand === "status" || subcommand === "ls" || subcommand === "list") {
302296
+ const conns = manager.getConnections();
302297
+ if (conns.length === 0) {
302298
+ renderInfo("No MCP servers configured. Drop a markdown file with an MCP config block, or add to .oa/mcp.json");
302299
+ return;
302300
+ }
302301
+ renderInfo(`MCP servers (${conns.length}):`);
302302
+ for (const conn of conns) {
302303
+ const status = conn.status === "connected" ? c3.green("\u25CF") : c3.red("\u25CF");
302304
+ renderInfo(` ${status} ${conn.name} [${conn.tools.length} tools]`);
302305
+ }
302306
+ return;
302307
+ }
302308
+ if (subcommand === "reload" || subcommand === "refresh") {
302309
+ renderInfo("Reloading MCP servers from config...");
302310
+ await manager.disconnectAll().catch(() => {
302311
+ });
302312
+ const conns = await manager.connectAll();
302313
+ await ctx3.refreshMcpTools?.();
302314
+ const ok2 = conns.filter((c7) => c7.status === "connected").length;
302315
+ renderInfo(`Reloaded: ${ok2}/${conns.length} servers connected`);
302316
+ return;
302317
+ }
302318
+ await showMcpMainMenu(ctx3);
302319
+ }
302320
+ async function showMcpMainMenu(ctx3) {
302321
+ const manager = ctx3.getMcpManager?.();
302322
+ if (!manager) return;
302323
+ const { loadMcpConfig: loadMcpConfig2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
302324
+ const cfg = loadMcpConfig2(ctx3.repoRoot);
302325
+ const conns = manager.getConnections();
302326
+ const allNames = /* @__PURE__ */ new Set([
302327
+ ...Object.keys(cfg.mcpServers),
302328
+ ...conns.map((c7) => c7.name)
302329
+ ]);
302330
+ const items = [];
302331
+ const skipKeys = [];
302332
+ items.push({ key: "hdr_servers", label: selectColors.dim("\u2500\u2500\u2500 MCP Servers \u2500\u2500\u2500"), kind: "header" });
302333
+ skipKeys.push("hdr_servers");
302334
+ if (allNames.size === 0) {
302335
+ items.push({ key: "empty", label: selectColors.dim("(no servers configured)"), kind: "header" });
302336
+ skipKeys.push("empty");
302337
+ } else {
302338
+ for (const name10 of Array.from(allNames).sort()) {
302339
+ const conn = conns.find((c7) => c7.name === name10);
302340
+ const persisted = cfg.mcpServers[name10];
302341
+ const status = conn?.status ?? (persisted ? "disconnected" : "missing");
302342
+ const dot = status === "connected" ? c3.green("\u25CF") : status === "failed" ? c3.red("\u25CF") : c3.yellow("\u25CF");
302343
+ const toolCount = conn?.tools?.length ?? 0;
302344
+ const transport = persisted ? "command" in persisted ? "stdio" : persisted.type ?? "http" : "?";
302345
+ const detail = `${transport} ${toolCount} tools status: ${status}${conn?.error ? " \u2014 " + String(conn.error).slice(0, 40) : ""}`;
302346
+ items.push({
302347
+ key: `srv:${name10}`,
302348
+ label: `${dot} ${name10}`,
302349
+ detail,
302350
+ kind: "server",
302351
+ serverName: name10
302352
+ });
302353
+ }
302354
+ }
302355
+ items.push({ key: "hdr_actions", label: selectColors.dim("\u2500\u2500\u2500 Actions \u2500\u2500\u2500"), kind: "header" });
302356
+ skipKeys.push("hdr_actions");
302357
+ items.push({ key: "act_add", label: c3.cyan("\u2795 Add new server"), detail: "Paste/enter a config", kind: "action" });
302358
+ items.push({ key: "act_reload", label: c3.cyan("\u27F3 Reload all from config"), detail: "Re-read .oa/mcp.json + reconnect", kind: "action" });
302359
+ items.push({ key: "act_open", label: c3.cyan("\u{1F4DD} Open .oa/mcp.json in editor"), detail: "External edit", kind: "action" });
302360
+ const result = await tuiSelect({
302361
+ items,
302362
+ title: "MCP Server Registry",
302363
+ skipKeys
302364
+ });
302365
+ if (!result || !result.confirmed || !result.key) return;
302366
+ if (result.key === "act_add") {
302367
+ await mcpAddServerInteractive(ctx3);
302368
+ return;
302369
+ }
302370
+ if (result.key === "act_reload") {
302371
+ renderInfo("Reloading MCP servers...");
302372
+ await manager.disconnectAll().catch(() => {
302373
+ });
302374
+ const conns2 = await manager.connectAll();
302375
+ await ctx3.refreshMcpTools?.();
302376
+ const ok2 = conns2.filter((c7) => c7.status === "connected").length;
302377
+ renderInfo(`Reloaded: ${ok2}/${conns2.length} servers connected`);
302378
+ await showMcpMainMenu(ctx3);
302379
+ return;
302380
+ }
302381
+ if (result.key === "act_open") {
302382
+ const path5 = __require("node:path").join(ctx3.repoRoot, ".oa", "mcp.json");
302383
+ renderInfo(`Edit externally: ${path5}`);
302384
+ return;
302385
+ }
302386
+ if (result.key.startsWith("srv:")) {
302387
+ const name10 = result.key.slice(4);
302388
+ await showMcpDetailMenu(ctx3, name10);
302389
+ return;
302390
+ }
302391
+ }
302392
+ async function showMcpDetailMenu(ctx3, serverName) {
302393
+ const manager = ctx3.getMcpManager?.();
302394
+ if (!manager) return;
302395
+ const { loadMcpConfig: loadMcpConfig2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
302396
+ const cfg = loadMcpConfig2(ctx3.repoRoot);
302397
+ const persisted = cfg.mcpServers[serverName];
302398
+ const conns = manager.getConnections();
302399
+ const conn = conns.find((c7) => c7.name === serverName);
302400
+ if (!persisted && !conn) {
302401
+ renderWarning(`Server ${serverName} not found`);
302402
+ await showMcpMainMenu(ctx3);
302403
+ return;
302404
+ }
302405
+ const items = [];
302406
+ const skipKeys = [];
302407
+ items.push({ key: "hdr_name", label: c3.bold(`Server: ${serverName}`), kind: "header" });
302408
+ skipKeys.push("hdr_name");
302409
+ const status = conn?.status ?? "disconnected";
302410
+ const dot = status === "connected" ? c3.green("\u25CF") : status === "failed" ? c3.red("\u25CF") : c3.yellow("\u25CF");
302411
+ items.push({ key: "info_status", label: ` ${dot} status: ${status}${conn?.error ? " \u2014 " + String(conn.error).slice(0, 80) : ""}`, kind: "header" });
302412
+ skipKeys.push("info_status");
302413
+ if (persisted) {
302414
+ const transport = "command" in persisted ? "stdio" : persisted.type ?? "http";
302415
+ items.push({ key: "info_transport", label: ` transport: ${transport}`, kind: "header" });
302416
+ skipKeys.push("info_transport");
302417
+ if ("command" in persisted) {
302418
+ const argStr = (persisted.args ?? []).join(" ");
302419
+ items.push({ key: "info_cmd", label: ` command: ${persisted.command}${argStr ? " " + argStr : ""}`.slice(0, 100), kind: "header" });
302420
+ skipKeys.push("info_cmd");
302421
+ } else if ("url" in persisted) {
302422
+ items.push({ key: "info_url", label: ` url: ${persisted.url}`.slice(0, 100), kind: "header" });
302423
+ skipKeys.push("info_url");
302424
+ }
302425
+ }
302426
+ if (conn?.serverInfo) {
302427
+ items.push({ key: "info_srv", label: ` server: ${conn.serverInfo.name} v${conn.serverInfo.version}`, kind: "header" });
302428
+ skipKeys.push("info_srv");
302429
+ }
302430
+ if (conn && conn.tools && conn.tools.length > 0) {
302431
+ items.push({ key: "hdr_tools", label: selectColors.dim(`\u2500\u2500\u2500 Tools (${conn.tools.length}) \u2500\u2500\u2500`), kind: "header" });
302432
+ skipKeys.push("hdr_tools");
302433
+ for (const t2 of conn.tools.slice(0, 30)) {
302434
+ const desc = (t2.description || t2.title || "").slice(0, 70);
302435
+ items.push({
302436
+ key: `tool:${t2.name}`,
302437
+ label: ` ${t2.name}`,
302438
+ detail: desc,
302439
+ kind: "header"
302440
+ });
302441
+ skipKeys.push(`tool:${t2.name}`);
302442
+ }
302443
+ if (conn.tools.length > 30) {
302444
+ items.push({ key: "tools_more", label: selectColors.dim(` ... and ${conn.tools.length - 30} more`), kind: "header" });
302445
+ skipKeys.push("tools_more");
302446
+ }
302447
+ } else if (conn) {
302448
+ items.push({ key: "hdr_notools", label: selectColors.dim("\u2500\u2500\u2500 No tools advertised \u2500\u2500\u2500"), kind: "header" });
302449
+ skipKeys.push("hdr_notools");
302450
+ }
302451
+ items.push({ key: "hdr_actions", label: selectColors.dim("\u2500\u2500\u2500 Actions \u2500\u2500\u2500"), kind: "header" });
302452
+ skipKeys.push("hdr_actions");
302453
+ items.push({ key: "act_edit", label: c3.cyan("\u270E Edit config"), detail: "Modify command/args/env/url/headers", kind: "action" });
302454
+ items.push({ key: "act_reconnect", label: c3.cyan("\u27F3 Reconnect"), detail: "Disconnect + reconnect this server", kind: "action" });
302455
+ items.push({ key: "act_delete", label: c3.red("\u{1F5D1} Delete"), detail: "Remove from config + disconnect", kind: "action" });
302456
+ items.push({ key: "act_back", label: c3.dim("\u2190 Back to server list"), kind: "action" });
302457
+ const result = await tuiSelect({
302458
+ items,
302459
+ title: `MCP: ${serverName}`,
302460
+ skipKeys
302461
+ });
302462
+ if (!result || !result.confirmed || !result.key) {
302463
+ await showMcpMainMenu(ctx3);
302464
+ return;
302465
+ }
302466
+ if (result.key === "act_back") {
302467
+ await showMcpMainMenu(ctx3);
302468
+ return;
302469
+ }
302470
+ if (result.key === "act_edit") {
302471
+ await mcpEditServer(ctx3, serverName, persisted);
302472
+ return;
302473
+ }
302474
+ if (result.key === "act_reconnect") {
302475
+ renderInfo(`Reconnecting ${serverName}...`);
302476
+ try {
302477
+ await manager.disconnect(serverName);
302478
+ if (persisted) {
302479
+ const c22 = await manager.connectOne(serverName, persisted);
302480
+ await ctx3.refreshMcpTools?.();
302481
+ if (c22.status === "connected") {
302482
+ renderInfo(`\u2714 ${serverName} reconnected (${c22.tools.length} tools)`);
302483
+ } else {
302484
+ renderError(`\u2718 ${serverName} failed: ${c22.error}`);
302485
+ }
302486
+ }
302487
+ } catch (e2) {
302488
+ renderError(`Reconnect failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302489
+ }
302490
+ await showMcpDetailMenu(ctx3, serverName);
302491
+ return;
302492
+ }
302493
+ if (result.key === "act_delete") {
302494
+ renderInfo(`Deleting ${serverName}...`);
302495
+ try {
302496
+ await manager.removeServer(serverName);
302497
+ await ctx3.refreshMcpTools?.();
302498
+ renderInfo(`\u2714 ${serverName} removed from config`);
302499
+ } catch (e2) {
302500
+ renderError(`Delete failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302501
+ }
302502
+ await showMcpMainMenu(ctx3);
302503
+ return;
302504
+ }
302505
+ }
302506
+ async function mcpEditServer(ctx3, serverName, current) {
302507
+ const manager = ctx3.getMcpManager?.();
302508
+ if (!manager) return;
302509
+ const ask2 = (prompt) => new Promise((res) => {
302510
+ process.stdout.write(prompt);
302511
+ let buf = "";
302512
+ const onData = (d2) => {
302513
+ const s2 = d2.toString();
302514
+ if (s2.includes("\n")) {
302515
+ process.stdin.removeListener("data", onData);
302516
+ process.stdin.pause();
302517
+ res((buf + s2).split("\n")[0]);
302518
+ } else {
302519
+ buf += s2;
302520
+ }
302521
+ };
302522
+ process.stdin.resume();
302523
+ process.stdin.on("data", onData);
302524
+ });
302525
+ process.stdout.write(`
302526
+ ${c3.cyan("Current config for ")}${c3.bold(serverName)}:
302527
+ `);
302528
+ process.stdout.write(` ${c3.dim(JSON.stringify(current ?? {}, null, 2).split("\n").join("\n "))}
302529
+
302530
+ `);
302531
+ process.stdout.write(` ${c3.cyan("Paste a new JSON config (single line) or press Enter to keep current.")}
302532
+ `);
302533
+ const newConfigJson = await ask2(" > ");
302534
+ if (!newConfigJson || newConfigJson.trim().length === 0) {
302535
+ renderInfo("No change.");
302536
+ await showMcpDetailMenu(ctx3, serverName);
302537
+ return;
302538
+ }
302539
+ let parsed;
302540
+ try {
302541
+ parsed = JSON.parse(newConfigJson);
302542
+ } catch (e2) {
302543
+ renderError(`Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}`);
302544
+ await showMcpDetailMenu(ctx3, serverName);
302545
+ return;
302546
+ }
302547
+ if (!parsed || typeof parsed.command !== "string" && typeof parsed.url !== "string") {
302548
+ renderError("Config must have either 'command' (stdio) or 'url' (http)");
302549
+ await showMcpDetailMenu(ctx3, serverName);
302550
+ return;
302551
+ }
302552
+ try {
302553
+ await manager.disconnect(serverName);
302554
+ const c22 = await manager.addServer(serverName, parsed);
302555
+ await ctx3.refreshMcpTools?.();
302556
+ if (c22.status === "connected") {
302557
+ renderInfo(`\u2714 ${serverName} updated and reconnected (${c22.tools.length} tools)`);
302558
+ } else {
302559
+ renderWarning(`\u26A0 ${serverName} saved but not connected: ${c22.error}`);
302560
+ }
302561
+ } catch (e2) {
302562
+ renderError(`Save failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302563
+ }
302564
+ await showMcpMainMenu(ctx3);
302565
+ }
302566
+ async function mcpAddServerInteractive(ctx3) {
302567
+ const ask2 = (prompt) => new Promise((res) => {
302568
+ process.stdout.write(prompt);
302569
+ let buf = "";
302570
+ const onData = (d2) => {
302571
+ const s2 = d2.toString();
302572
+ if (s2.includes("\n")) {
302573
+ process.stdin.removeListener("data", onData);
302574
+ process.stdin.pause();
302575
+ res((buf + s2).split("\n")[0]);
302576
+ } else {
302577
+ buf += s2;
302578
+ }
302579
+ };
302580
+ process.stdin.resume();
302581
+ process.stdin.on("data", onData);
302582
+ });
302583
+ process.stdout.write(`
302584
+ ${c3.cyan("Add MCP server")}
302585
+ `);
302586
+ process.stdout.write(` ${c3.dim("Tip: drag-drop a markdown file with an MCP config block onto the terminal for auto-intake.")}
302587
+
302588
+ `);
302589
+ const name10 = await ask2(` ${c3.cyan("Server name:")} `);
302590
+ if (!name10 || name10.trim().length === 0) {
302591
+ renderInfo("Cancelled.");
302592
+ return;
302593
+ }
302594
+ process.stdout.write(` ${c3.cyan('Config JSON (one line, e.g. {"command":"npx","args":["-y","@modelcontextprotocol/server-memory"]}):')}
302595
+ `);
302596
+ const cfgStr = await ask2(" > ");
302597
+ let parsed;
302598
+ try {
302599
+ parsed = JSON.parse(cfgStr);
302600
+ } catch (e2) {
302601
+ renderError(`Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}`);
302602
+ return;
302603
+ }
302604
+ if (!parsed || typeof parsed.command !== "string" && typeof parsed.url !== "string") {
302605
+ renderError("Config must have either 'command' (stdio) or 'url' (http)");
302606
+ return;
302607
+ }
302608
+ const manager = ctx3.getMcpManager?.();
302609
+ if (!manager) {
302610
+ renderError("MCP manager not available");
302611
+ return;
302612
+ }
302613
+ try {
302614
+ const c22 = await manager.addServer(name10.trim(), parsed);
302615
+ await ctx3.refreshMcpTools?.();
302616
+ if (c22.status === "connected") {
302617
+ renderInfo(`\u2714 ${name10.trim()} added and connected (${c22.tools.length} tools)`);
302618
+ } else {
302619
+ renderWarning(`\u26A0 ${name10.trim()} saved but not connected: ${c22.error}`);
302620
+ }
302621
+ } catch (e2) {
302622
+ renderError(`Add failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302623
+ }
302624
+ await showMcpMainMenu(ctx3);
302625
+ }
301818
302626
  async function handleUpdate(subcommand, ctx3) {
301819
302627
  const repoRoot = ctx3.repoRoot;
301820
302628
  if (subcommand === "auto") {
@@ -301867,10 +302675,10 @@ async function handleUpdate(subcommand, ctx3) {
301867
302675
  try {
301868
302676
  const { createRequire: createRequire7 } = await import("node:module");
301869
302677
  const { fileURLToPath: fileURLToPath19 } = await import("node:url");
301870
- const { dirname: dirname28, join: join100 } = await import("node:path");
302678
+ const { dirname: dirname29, join: join100 } = await import("node:path");
301871
302679
  const { existsSync: existsSync80 } = await import("node:fs");
301872
302680
  const req2 = createRequire7(import.meta.url);
301873
- const thisDir = dirname28(fileURLToPath19(import.meta.url));
302681
+ const thisDir = dirname29(fileURLToPath19(import.meta.url));
301874
302682
  const candidates = [
301875
302683
  join100(thisDir, "..", "package.json"),
301876
302684
  join100(thisDir, "..", "..", "package.json"),
@@ -303567,7 +304375,7 @@ __export(banner_exports, {
303567
304375
  saveBannerDesign: () => saveBannerDesign,
303568
304376
  setGridText: () => setGridText
303569
304377
  });
303570
- import { existsSync as existsSync64, readFileSync as readFileSync49, writeFileSync as writeFileSync32, mkdirSync as mkdirSync35 } from "node:fs";
304378
+ import { existsSync as existsSync64, readFileSync as readFileSync49, writeFileSync as writeFileSync33, mkdirSync as mkdirSync36 } from "node:fs";
303571
304379
  import { join as join80 } from "node:path";
303572
304380
  function generateMnemonic(seed) {
303573
304381
  let h = 2166136261;
@@ -303699,8 +304507,8 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
303699
304507
  }
303700
304508
  function saveBannerDesign(workDir, design) {
303701
304509
  const dir = join80(workDir, ".oa", "banners");
303702
- mkdirSync35(dir, { recursive: true });
303703
- writeFileSync32(join80(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
304510
+ mkdirSync36(dir, { recursive: true });
304511
+ writeFileSync33(join80(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
303704
304512
  }
303705
304513
  function loadBannerDesign(workDir, id) {
303706
304514
  const file = join80(workDir, ".oa", "banners", `${id}.json`);
@@ -304020,7 +304828,7 @@ var init_banner = __esm({
304020
304828
  });
304021
304829
 
304022
304830
  // packages/cli/src/tui/carousel-descriptors.ts
304023
- import { existsSync as existsSync65, readFileSync as readFileSync50, writeFileSync as writeFileSync33, mkdirSync as mkdirSync36, readdirSync as readdirSync17 } from "node:fs";
304831
+ import { existsSync as existsSync65, readFileSync as readFileSync50, writeFileSync as writeFileSync34, mkdirSync as mkdirSync37, readdirSync as readdirSync17 } from "node:fs";
304024
304832
  import { join as join81, basename as basename14 } from "node:path";
304025
304833
  function loadToolProfile(repoRoot) {
304026
304834
  const filePath = join81(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
@@ -304033,8 +304841,8 @@ function loadToolProfile(repoRoot) {
304033
304841
  }
304034
304842
  function saveToolProfile(repoRoot, profile) {
304035
304843
  const contextDir = join81(repoRoot, OA_DIR, "context");
304036
- mkdirSync36(contextDir, { recursive: true });
304037
- writeFileSync33(join81(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
304844
+ mkdirSync37(contextDir, { recursive: true });
304845
+ writeFileSync34(join81(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
304038
304846
  }
304039
304847
  function categorizeToolCall(toolName) {
304040
304848
  for (const cat2 of TOOL_CATEGORIES) {
@@ -304100,13 +304908,13 @@ function loadCachedDescriptors(repoRoot) {
304100
304908
  }
304101
304909
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
304102
304910
  const contextDir = join81(repoRoot, OA_DIR, "context");
304103
- mkdirSync36(contextDir, { recursive: true });
304911
+ mkdirSync37(contextDir, { recursive: true });
304104
304912
  const cached = {
304105
304913
  phrases,
304106
304914
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
304107
304915
  sourceHash
304108
304916
  };
304109
- writeFileSync33(join81(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
304917
+ writeFileSync34(join81(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
304110
304918
  }
304111
304919
  function generateDescriptors(repoRoot) {
304112
304920
  const profile = loadToolProfile(repoRoot);
@@ -304921,13 +305729,13 @@ var init_stream_renderer = __esm({
304921
305729
  });
304922
305730
 
304923
305731
  // packages/cli/src/tui/edit-history.ts
304924
- import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync37 } from "node:fs";
305732
+ import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync38 } from "node:fs";
304925
305733
  import { join as join82 } from "node:path";
304926
305734
  function createEditHistoryLogger(repoRoot, sessionId) {
304927
305735
  const historyDir = join82(repoRoot, ".oa", "history");
304928
305736
  const logPath2 = join82(historyDir, "edits.jsonl");
304929
305737
  try {
304930
- mkdirSync37(historyDir, { recursive: true });
305738
+ mkdirSync38(historyDir, { recursive: true });
304931
305739
  } catch {
304932
305740
  }
304933
305741
  function logToolCall(toolName, toolArgs, success) {
@@ -305036,7 +305844,7 @@ var init_edit_history = __esm({
305036
305844
 
305037
305845
  // packages/cli/src/tui/promptLoader.ts
305038
305846
  import { readFileSync as readFileSync51, existsSync as existsSync66 } from "node:fs";
305039
- import { join as join83, dirname as dirname23 } from "node:path";
305847
+ import { join as join83, dirname as dirname24 } from "node:path";
305040
305848
  import { fileURLToPath as fileURLToPath14 } from "node:url";
305041
305849
  function loadPrompt3(promptPath, vars) {
305042
305850
  let content = cache6.get(promptPath);
@@ -305056,7 +305864,7 @@ var init_promptLoader3 = __esm({
305056
305864
  "packages/cli/src/tui/promptLoader.ts"() {
305057
305865
  "use strict";
305058
305866
  __filename5 = fileURLToPath14(import.meta.url);
305059
- __dirname7 = dirname23(__filename5);
305867
+ __dirname7 = dirname24(__filename5);
305060
305868
  devPath2 = join83(__dirname7, "..", "..", "prompts");
305061
305869
  publishedPath2 = join83(__dirname7, "..", "prompts");
305062
305870
  PROMPTS_DIR3 = existsSync66(devPath2) ? devPath2 : publishedPath2;
@@ -305065,7 +305873,7 @@ var init_promptLoader3 = __esm({
305065
305873
  });
305066
305874
 
305067
305875
  // packages/cli/src/tui/dream-engine.ts
305068
- import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync34, readFileSync as readFileSync52, existsSync as existsSync67, readdirSync as readdirSync18 } from "node:fs";
305876
+ import { mkdirSync as mkdirSync39, writeFileSync as writeFileSync35, readFileSync as readFileSync52, existsSync as existsSync67, readdirSync as readdirSync18 } from "node:fs";
305069
305877
  import { join as join84, basename as basename15 } from "node:path";
305070
305878
  import { execSync as execSync52 } from "node:child_process";
305071
305879
  function setDreamWriteContent(fn) {
@@ -305284,8 +306092,8 @@ var init_dream_engine = __esm({
305284
306092
  }
305285
306093
  try {
305286
306094
  const dir = join84(targetPath, "..");
305287
- mkdirSync38(dir, { recursive: true });
305288
- writeFileSync34(targetPath, content, "utf-8");
306095
+ mkdirSync39(dir, { recursive: true });
306096
+ writeFileSync35(targetPath, content, "utf-8");
305289
306097
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
305290
306098
  } catch (err) {
305291
306099
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305325,7 +306133,7 @@ var init_dream_engine = __esm({
305325
306133
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
305326
306134
  }
305327
306135
  content = content.replace(oldStr, newStr);
305328
- writeFileSync34(targetPath, content, "utf-8");
306136
+ writeFileSync35(targetPath, content, "utf-8");
305329
306137
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start2 };
305330
306138
  } catch (err) {
305331
306139
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305370,8 +306178,8 @@ var init_dream_engine = __esm({
305370
306178
  }
305371
306179
  try {
305372
306180
  const dir = join84(targetPath, "..");
305373
- mkdirSync38(dir, { recursive: true });
305374
- writeFileSync34(targetPath, content, "utf-8");
306181
+ mkdirSync39(dir, { recursive: true });
306182
+ writeFileSync35(targetPath, content, "utf-8");
305375
306183
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
305376
306184
  } catch (err) {
305377
306185
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305411,7 +306219,7 @@ var init_dream_engine = __esm({
305411
306219
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
305412
306220
  }
305413
306221
  content = content.replace(oldStr, newStr);
305414
- writeFileSync34(targetPath, content, "utf-8");
306222
+ writeFileSync35(targetPath, content, "utf-8");
305415
306223
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start2 };
305416
306224
  } catch (err) {
305417
306225
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305496,7 +306304,7 @@ var init_dream_engine = __esm({
305496
306304
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
305497
306305
  results: []
305498
306306
  };
305499
- mkdirSync38(this.dreamsDir, { recursive: true });
306307
+ mkdirSync39(this.dreamsDir, { recursive: true });
305500
306308
  this.saveDreamState();
305501
306309
  try {
305502
306310
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -305569,7 +306377,7 @@ ${result.summary}`;
305569
306377
  renderDreamContraction(cycle);
305570
306378
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
305571
306379
  const summaryPath = join84(this.dreamsDir, `cycle-${cycle}-summary.md`);
305572
- writeFileSync34(summaryPath, cycleSummary, "utf-8");
306380
+ writeFileSync35(summaryPath, cycleSummary, "utf-8");
305573
306381
  }
305574
306382
  if (mode === "lucid" && !this.abortController.signal.aborted) {
305575
306383
  this.saveVersionCheckpoint(cycle);
@@ -306229,8 +307037,8 @@ ${summaryResult}
306229
307037
  *Generated by open-agents autoresearch swarm*
306230
307038
  `;
306231
307039
  try {
306232
- mkdirSync38(this.dreamsDir, { recursive: true });
306233
- writeFileSync34(reportPath, report, "utf-8");
307040
+ mkdirSync39(this.dreamsDir, { recursive: true });
307041
+ writeFileSync35(reportPath, report, "utf-8");
306234
307042
  } catch {
306235
307043
  }
306236
307044
  renderSwarmComplete(workspace);
@@ -306298,7 +307106,7 @@ ${summaryResult}
306298
307106
  saveVersionCheckpoint(cycle) {
306299
307107
  const checkpointDir = join84(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
306300
307108
  try {
306301
- mkdirSync38(checkpointDir, { recursive: true });
307109
+ mkdirSync39(checkpointDir, { recursive: true });
306302
307110
  try {
306303
307111
  const gitStatus = execSync52("git status --porcelain", {
306304
307112
  cwd: this.repoRoot,
@@ -306315,10 +307123,10 @@ ${summaryResult}
306315
307123
  encoding: "utf-8",
306316
307124
  timeout: 5e3
306317
307125
  }).trim();
306318
- writeFileSync34(join84(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
306319
- writeFileSync34(join84(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
306320
- writeFileSync34(join84(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
306321
- writeFileSync34(
307126
+ writeFileSync35(join84(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
307127
+ writeFileSync35(join84(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
307128
+ writeFileSync35(join84(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
307129
+ writeFileSync35(
306322
307130
  join84(checkpointDir, "checkpoint.json"),
306323
307131
  JSON.stringify({
306324
307132
  cycle,
@@ -306330,7 +307138,7 @@ ${summaryResult}
306330
307138
  );
306331
307139
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
306332
307140
  } catch {
306333
- writeFileSync34(
307141
+ writeFileSync35(
306334
307142
  join84(checkpointDir, "checkpoint.json"),
306335
307143
  JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2),
306336
307144
  "utf-8"
@@ -306392,7 +307200,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306392
307200
  ---
306393
307201
  *Auto-generated by open-agents dream engine*
306394
307202
  `;
306395
- writeFileSync34(join84(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
307203
+ writeFileSync35(join84(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
306396
307204
  } catch {
306397
307205
  }
306398
307206
  }
@@ -306414,7 +307222,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306414
307222
  };
306415
307223
  renderInfo("Memory consolidation starting \u2014 Phase 1: Orient \u2192 Phase 2: Gather \u2192 Phase 3: Consolidate \u2192 Phase 4: Prune");
306416
307224
  const memoryDir = join84(this.repoRoot, ".oa", "memory");
306417
- mkdirSync38(memoryDir, { recursive: true });
307225
+ mkdirSync39(memoryDir, { recursive: true });
306418
307226
  let prompt;
306419
307227
  try {
306420
307228
  prompt = loadPrompt3("tui/dream-consolidate.md", {
@@ -306478,7 +307286,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306478
307286
  durationMs
306479
307287
  });
306480
307288
  try {
306481
- writeFileSync34(
307289
+ writeFileSync35(
306482
307290
  join84(memoryDir, ".last-consolidation"),
306483
307291
  JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), summary: result.summary?.slice(0, 500) }) + "\n"
306484
307292
  );
@@ -306496,7 +307304,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306496
307304
  /** Save dream state for resume/inspection */
306497
307305
  saveDreamState() {
306498
307306
  try {
306499
- writeFileSync34(
307307
+ writeFileSync35(
306500
307308
  join84(this.dreamsDir, "dream-state.json"),
306501
307309
  JSON.stringify(this.state, null, 2) + "\n",
306502
307310
  "utf-8"
@@ -306867,7 +307675,7 @@ var init_bless_engine = __esm({
306867
307675
  });
306868
307676
 
306869
307677
  // packages/cli/src/tui/dmn-engine.ts
306870
- import { existsSync as existsSync68, readFileSync as readFileSync53, writeFileSync as writeFileSync35, mkdirSync as mkdirSync39, readdirSync as readdirSync19, unlinkSync as unlinkSync16 } from "node:fs";
307678
+ import { existsSync as existsSync68, readFileSync as readFileSync53, writeFileSync as writeFileSync36, mkdirSync as mkdirSync40, readdirSync as readdirSync19, unlinkSync as unlinkSync16 } from "node:fs";
306871
307679
  import { join as join85, basename as basename16 } from "node:path";
306872
307680
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
306873
307681
  const competenceReport = competence.length > 0 ? competence.map((c7) => {
@@ -306974,7 +307782,7 @@ var init_dmn_engine = __esm({
306974
307782
  this.repoRoot = repoRoot;
306975
307783
  this.stateDir = join85(repoRoot, ".oa", "dmn");
306976
307784
  this.historyDir = join85(repoRoot, ".oa", "dmn", "cycles");
306977
- mkdirSync39(this.historyDir, { recursive: true });
307785
+ mkdirSync40(this.historyDir, { recursive: true });
306978
307786
  this.loadState();
306979
307787
  }
306980
307788
  state = {
@@ -307634,7 +308442,7 @@ OUTPUT: Call task_complete with JSON:
307634
308442
  }
307635
308443
  saveState() {
307636
308444
  try {
307637
- writeFileSync35(
308445
+ writeFileSync36(
307638
308446
  join85(this.stateDir, "state.json"),
307639
308447
  JSON.stringify(this.state, null, 2) + "\n",
307640
308448
  "utf-8"
@@ -307645,7 +308453,7 @@ OUTPUT: Call task_complete with JSON:
307645
308453
  saveCycleResult(result) {
307646
308454
  try {
307647
308455
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
307648
- writeFileSync35(
308456
+ writeFileSync36(
307649
308457
  join85(this.historyDir, filename),
307650
308458
  JSON.stringify(result, null, 2) + "\n",
307651
308459
  "utf-8"
@@ -308507,7 +309315,7 @@ var init_tool_policy = __esm({
308507
309315
  });
308508
309316
 
308509
309317
  // packages/cli/src/tui/telegram-bridge.ts
308510
- import { mkdirSync as mkdirSync40, unlinkSync as unlinkSync17 } from "node:fs";
309318
+ import { mkdirSync as mkdirSync41, unlinkSync as unlinkSync17 } from "node:fs";
308511
309319
  import { join as join87, resolve as resolve32 } from "node:path";
308512
309320
  import { writeFile as writeFileAsync } from "node:fs/promises";
308513
309321
  function convertMarkdownToTelegramHTML(md) {
@@ -308831,7 +309639,7 @@ with summary "no_reply" to silently skip without responding.
308831
309639
  this.polling = true;
308832
309640
  this.abortController = new AbortController();
308833
309641
  try {
308834
- mkdirSync40(this.mediaCacheDir, { recursive: true });
309642
+ mkdirSync41(this.mediaCacheDir, { recursive: true });
308835
309643
  } catch {
308836
309644
  }
308837
309645
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -310179,13 +310987,13 @@ var init_direct_input = __esm({
310179
310987
  });
310180
310988
 
310181
310989
  // packages/cli/src/api/audit-log.ts
310182
- import { mkdirSync as mkdirSync41, appendFileSync as appendFileSync5, readFileSync as readFileSync55, existsSync as existsSync71 } from "node:fs";
310990
+ import { mkdirSync as mkdirSync42, appendFileSync as appendFileSync5, readFileSync as readFileSync55, existsSync as existsSync71 } from "node:fs";
310183
310991
  import { join as join88 } from "node:path";
310184
310992
  function initAuditLog(oaDir) {
310185
310993
  auditDir = join88(oaDir, "audit");
310186
310994
  auditFile = join88(auditDir, "audit.jsonl");
310187
310995
  try {
310188
- mkdirSync41(auditDir, { recursive: true });
310996
+ mkdirSync42(auditDir, { recursive: true });
310189
310997
  initialized = true;
310190
310998
  } catch {
310191
310999
  }
@@ -311637,11 +312445,11 @@ var init_chat_session = __esm({
311637
312445
  });
311638
312446
 
311639
312447
  // packages/cli/src/api/usage-tracker.ts
311640
- import { mkdirSync as mkdirSync42, readFileSync as readFileSync57, writeFileSync as writeFileSync36, existsSync as existsSync73 } from "node:fs";
312448
+ import { mkdirSync as mkdirSync43, readFileSync as readFileSync57, writeFileSync as writeFileSync37, existsSync as existsSync73 } from "node:fs";
311641
312449
  import { join as join90 } from "node:path";
311642
312450
  function initUsageTracker(oaDir) {
311643
312451
  const dir = join90(oaDir, "usage");
311644
- mkdirSync42(dir, { recursive: true });
312452
+ mkdirSync43(dir, { recursive: true });
311645
312453
  usageFile = join90(dir, "token-usage.json");
311646
312454
  try {
311647
312455
  if (existsSync73(usageFile)) {
@@ -311681,7 +312489,7 @@ function flush2() {
311681
312489
  if (!initialized2 || !dirty) return;
311682
312490
  try {
311683
312491
  store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
311684
- writeFileSync36(usageFile, JSON.stringify(store, null, 2), "utf-8");
312492
+ writeFileSync37(usageFile, JSON.stringify(store, null, 2), "utf-8");
311685
312493
  dirty = false;
311686
312494
  } catch {
311687
312495
  }
@@ -311709,7 +312517,7 @@ var init_usage_tracker = __esm({
311709
312517
  });
311710
312518
 
311711
312519
  // packages/cli/src/api/profiles.ts
311712
- import { existsSync as existsSync74, readFileSync as readFileSync58, writeFileSync as writeFileSync37, mkdirSync as mkdirSync43, readdirSync as readdirSync23, unlinkSync as unlinkSync18 } from "node:fs";
312520
+ import { existsSync as existsSync74, readFileSync as readFileSync58, writeFileSync as writeFileSync38, mkdirSync as mkdirSync44, readdirSync as readdirSync23, unlinkSync as unlinkSync18 } from "node:fs";
311713
312521
  import { join as join91 } from "node:path";
311714
312522
  import { homedir as homedir28 } from "node:os";
311715
312523
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes18, scryptSync as scryptSync3 } from "node:crypto";
@@ -311773,16 +312581,16 @@ function loadProfile(name10, password, projectDir) {
311773
312581
  }
311774
312582
  function saveProfile(profile, password, scope = "global", projectDir) {
311775
312583
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
311776
- mkdirSync43(dir, { recursive: true });
312584
+ mkdirSync44(dir, { recursive: true });
311777
312585
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
311778
312586
  const filePath = join91(dir, `${sanitized}.json`);
311779
312587
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
311780
312588
  if (password) {
311781
312589
  const encrypted = encryptProfile(profile, password);
311782
- writeFileSync37(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
312590
+ writeFileSync38(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
311783
312591
  } else {
311784
312592
  profile.encrypted = false;
311785
- writeFileSync37(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
312593
+ writeFileSync38(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
311786
312594
  }
311787
312595
  }
311788
312596
  function deleteProfile(name10, scope = "global", projectDir) {
@@ -311904,8 +312712,8 @@ var init_profiles = __esm({
311904
312712
 
311905
312713
  // packages/cli/src/docker.ts
311906
312714
  import { execSync as execSync53, spawn as spawn24 } from "node:child_process";
311907
- import { existsSync as existsSync75, mkdirSync as mkdirSync44, writeFileSync as writeFileSync38 } from "node:fs";
311908
- import { join as join92, resolve as resolve33, dirname as dirname24 } from "node:path";
312715
+ import { existsSync as existsSync75, mkdirSync as mkdirSync45, writeFileSync as writeFileSync39 } from "node:fs";
312716
+ import { join as join92, resolve as resolve33, dirname as dirname25 } from "node:path";
311909
312717
  import { homedir as homedir29 } from "node:os";
311910
312718
  import { fileURLToPath as fileURLToPath15 } from "node:url";
311911
312719
  function getDockerDir() {
@@ -311916,7 +312724,7 @@ function getDockerDir() {
311916
312724
  } catch {
311917
312725
  }
311918
312726
  try {
311919
- const thisDir = dirname24(fileURLToPath15(import.meta.url));
312727
+ const thisDir = dirname25(fileURLToPath15(import.meta.url));
311920
312728
  return join92(thisDir, "..", "..", "..", "docker");
311921
312729
  } catch {
311922
312730
  }
@@ -312055,7 +312863,7 @@ async function ensureOaImage(force = false) {
312055
312863
  buildContext = dockerDir;
312056
312864
  } else {
312057
312865
  buildContext = join92(homedir29(), ".oa", "docker-build");
312058
- mkdirSync44(buildContext, { recursive: true });
312866
+ mkdirSync45(buildContext, { recursive: true });
312059
312867
  writeDockerfiles(buildContext);
312060
312868
  }
312061
312869
  try {
@@ -312129,8 +312937,8 @@ chown -R node:node /workspace /home/node/.oa /home/node/.open-agents 2>/dev/null
312129
312937
  if [ "$1" = "oa" ]; then shift; exec su - node -c "cd /workspace && oa $*"; fi
312130
312938
  exec "$@"
312131
312939
  `;
312132
- writeFileSync38(join92(dir, "Dockerfile"), dockerfile);
312133
- writeFileSync38(join92(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
312940
+ writeFileSync39(join92(dir, "Dockerfile"), dockerfile);
312941
+ writeFileSync39(join92(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
312134
312942
  }
312135
312943
  function hasNvidiaGpu() {
312136
312944
  try {
@@ -312207,14 +313015,14 @@ import * as http5 from "node:http";
312207
313015
  import * as https3 from "node:https";
312208
313016
  import { createRequire as createRequire4 } from "node:module";
312209
313017
  import { fileURLToPath as fileURLToPath16 } from "node:url";
312210
- import { dirname as dirname25, join as join93, resolve as resolve34 } from "node:path";
313018
+ import { dirname as dirname26, join as join93, resolve as resolve34 } from "node:path";
312211
313019
  import { spawn as spawn25, execSync as execSync54 } from "node:child_process";
312212
- import { mkdirSync as mkdirSync45, writeFileSync as writeFileSync39, readFileSync as readFileSync59, readdirSync as readdirSync24, existsSync as existsSync76 } from "node:fs";
313020
+ import { mkdirSync as mkdirSync46, writeFileSync as writeFileSync40, readFileSync as readFileSync59, readdirSync as readdirSync24, existsSync as existsSync76 } from "node:fs";
312213
313021
  import { randomBytes as randomBytes19, randomUUID as randomUUID8 } from "node:crypto";
312214
313022
  function getVersion3() {
312215
313023
  try {
312216
313024
  const require3 = createRequire4(import.meta.url);
312217
- const thisDir = dirname25(fileURLToPath16(import.meta.url));
313025
+ const thisDir = dirname26(fileURLToPath16(import.meta.url));
312218
313026
  const candidates = [
312219
313027
  join93(thisDir, "..", "package.json"),
312220
313028
  join93(thisDir, "..", "..", "package.json"),
@@ -312512,7 +313320,7 @@ function ollamaStream(ollamaUrl, path5, method, body, onData, onEnd, onError) {
312512
313320
  function jobsDir() {
312513
313321
  const root = resolve34(process.cwd());
312514
313322
  const dir = join93(root, ".oa", "jobs");
312515
- mkdirSync45(dir, { recursive: true });
313323
+ mkdirSync46(dir, { recursive: true });
312516
313324
  return dir;
312517
313325
  }
312518
313326
  function loadJob(id) {
@@ -313006,7 +313814,7 @@ async function handleV1Run(req2, res) {
313006
313814
  cwd4 = resolve34(workingDir);
313007
313815
  } else if (isolate) {
313008
313816
  const wsDir = join93(dir, "..", "workspaces", id);
313009
- mkdirSync45(wsDir, { recursive: true });
313817
+ mkdirSync46(wsDir, { recursive: true });
313010
313818
  cwd4 = wsDir;
313011
313819
  } else {
313012
313820
  cwd4 = resolve34(process.cwd());
@@ -313090,7 +313898,7 @@ async function handleV1Run(req2, res) {
313090
313898
  job.sandbox = sandbox;
313091
313899
  }
313092
313900
  job.pid = child.pid ?? 0;
313093
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313901
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313094
313902
  runningProcesses.set(id, child);
313095
313903
  if (streamMode) {
313096
313904
  res.writeHead(200, {
@@ -313117,7 +313925,7 @@ async function handleV1Run(req2, res) {
313117
313925
  job.status = code8 === 0 ? "completed" : "failed";
313118
313926
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
313119
313927
  try {
313120
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313928
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313121
313929
  } catch {
313122
313930
  }
313123
313931
  runningProcesses.delete(id);
@@ -313157,7 +313965,7 @@ async function handleV1Run(req2, res) {
313157
313965
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
313158
313966
  }
313159
313967
  try {
313160
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313968
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313161
313969
  } catch {
313162
313970
  }
313163
313971
  runningProcesses.delete(id);
@@ -313225,7 +314033,7 @@ function handleV1RunsDelete(res, id) {
313225
314033
  job.error = "Aborted via API";
313226
314034
  const dir = jobsDir();
313227
314035
  try {
313228
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
314036
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313229
314037
  } catch {
313230
314038
  }
313231
314039
  runningProcesses.delete(id);
@@ -314121,10 +314929,10 @@ var init_serve = __esm({
314121
314929
 
314122
314930
  // packages/cli/src/tui/interactive.ts
314123
314931
  import { cwd } from "node:process";
314124
- import { resolve as resolve35, join as join94, dirname as dirname26, extname as extname11 } from "node:path";
314932
+ import { resolve as resolve35, join as join94, dirname as dirname27, extname as extname11 } from "node:path";
314125
314933
  import { createRequire as createRequire5 } from "node:module";
314126
314934
  import { fileURLToPath as fileURLToPath17 } from "node:url";
314127
- import { readFileSync as readFileSync60, writeFileSync as writeFileSync40, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync25, mkdirSync as mkdirSync46 } from "node:fs";
314935
+ import { readFileSync as readFileSync60, writeFileSync as writeFileSync41, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync25, mkdirSync as mkdirSync47 } from "node:fs";
314128
314936
  import { existsSync as existsSync77 } from "node:fs";
314129
314937
  import { execSync as execSync55 } from "node:child_process";
314130
314938
  import { homedir as homedir30 } from "node:os";
@@ -314141,7 +314949,7 @@ function formatTimeAgo(date) {
314141
314949
  function getVersion4() {
314142
314950
  try {
314143
314951
  const require3 = createRequire5(import.meta.url);
314144
- const thisDir = dirname26(fileURLToPath17(import.meta.url));
314952
+ const thisDir = dirname27(fileURLToPath17(import.meta.url));
314145
314953
  const candidates = [
314146
314954
  join94(thisDir, "..", "package.json"),
314147
314955
  join94(thisDir, "..", "..", "package.json"),
@@ -315722,7 +316530,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
315722
316530
  if (existsSync77(ikFile)) {
315723
316531
  ikState = JSON.parse(readFileSync60(ikFile, "utf8"));
315724
316532
  } else {
315725
- mkdirSync46(ikDir, { recursive: true });
316533
+ mkdirSync47(ikDir, { recursive: true });
315726
316534
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
315727
316535
  ikState = {
315728
316536
  self_id: `oa-${machineId}`,
@@ -315778,7 +316586,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
315778
316586
  }
315779
316587
  ikState.session_count = (ikState.session_count || 0) + 1;
315780
316588
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
315781
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
316589
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
315782
316590
  } catch (ikErr) {
315783
316591
  try {
315784
316592
  console.error("[IK-OBSERVE]", ikErr);
@@ -315810,7 +316618,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
315810
316618
  if (ikState.version_history.length > 200) ikState.version_history = ikState.version_history.slice(-200);
315811
316619
  ikState.session_count = (ikState.session_count || 0) + 1;
315812
316620
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
315813
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
316621
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
315814
316622
  }
315815
316623
  } catch {
315816
316624
  }
@@ -316823,12 +317631,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
316823
317631
  function persistHistoryLine(line) {
316824
317632
  if (!line.trim()) return;
316825
317633
  try {
316826
- mkdirSync46(HISTORY_DIR, { recursive: true });
317634
+ mkdirSync47(HISTORY_DIR, { recursive: true });
316827
317635
  appendFileSync6(HISTORY_FILE, line + "\n", "utf8");
316828
317636
  if (Math.random() < 0.02) {
316829
317637
  const all2 = readFileSync60(HISTORY_FILE, "utf8").trim().split("\n");
316830
317638
  if (all2.length > MAX_HISTORY_LINES) {
316831
- writeFileSync40(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
317639
+ writeFileSync41(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
316832
317640
  }
316833
317641
  }
316834
317642
  } catch {
@@ -317380,6 +318188,15 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
317380
318188
  repoRoot,
317381
318189
  costTracker,
317382
318190
  workEvaluator,
318191
+ getMcpManager: () => _mcpManager,
318192
+ refreshMcpTools: async () => {
318193
+ if (_mcpManager) {
318194
+ try {
318195
+ _mcpTools = await _mcpManager.buildTools();
318196
+ } catch {
318197
+ }
318198
+ }
318199
+ },
317383
318200
  get lastTask() {
317384
318201
  return lastSubmittedPrompt;
317385
318202
  },
@@ -318946,6 +319763,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
318946
319763
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
318947
319764
  const isImage = isImagePath(cleanPath) && existsSync77(resolve35(repoRoot, cleanPath));
318948
319765
  const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync77(resolve35(repoRoot, cleanPath));
319766
+ const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) && existsSync77(resolve35(repoRoot, cleanPath));
318949
319767
  if (activeTask) {
318950
319768
  if (activeTask.runner.isPaused) {
318951
319769
  activeTask.runner.resume();
@@ -319119,6 +319937,44 @@ ${result.text}`;
319119
319937
  return;
319120
319938
  }
319121
319939
  }
319940
+ if (isMarkdown && fullInput === input) {
319941
+ try {
319942
+ const mdPath = resolve35(repoRoot, cleanPath);
319943
+ const mdContent = readFileSync60(mdPath, "utf8");
319944
+ const { parseMcpMarkdown: parseMcpMarkdown2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
319945
+ const result = parseMcpMarkdown2(mdContent);
319946
+ if (result.servers.length > 0) {
319947
+ writeContent(() => renderInfo(`Detected ${result.servers.length} MCP server config(s) in ${cleanPath} \u2014 adding to .oa/mcp.json`));
319948
+ const added = [];
319949
+ for (const s2 of result.servers) {
319950
+ try {
319951
+ if (_mcpManager) {
319952
+ const conn = await _mcpManager.addServer(s2.name, s2.config, "project");
319953
+ const tag = conn.status === "connected" ? `${c3.green("\u2714")} ${s2.name} (connected, ${conn.tools.length} tools)` : `${c3.yellow("\u26A0")} ${s2.name} (saved but ${conn.status}: ${conn.error ?? "unknown"})`;
319954
+ writeContent(() => renderInfo(` ${tag}`));
319955
+ added.push(s2.name);
319956
+ }
319957
+ } catch (e2) {
319958
+ writeContent(() => renderError(` \u2718 ${s2.name}: ${e2 instanceof Error ? e2.message : String(e2)}`));
319959
+ }
319960
+ }
319961
+ if (_mcpManager && added.length > 0) {
319962
+ try {
319963
+ _mcpTools = await _mcpManager.buildTools();
319964
+ writeContent(() => renderInfo(`MCP tool list refreshed (${_mcpTools.length} total MCP tools available)`));
319965
+ } catch {
319966
+ }
319967
+ }
319968
+ showPrompt();
319969
+ return;
319970
+ } else if (result.isMcpDocument) {
319971
+ writeContent(() => renderWarning(`${cleanPath} mentions MCP but no valid server config could be extracted from code blocks.`));
319972
+ for (const note of result.notes) writeContent(() => renderInfo(` ${note}`));
319973
+ }
319974
+ } catch (e2) {
319975
+ writeContent(() => renderError(`Failed to parse ${cleanPath}: ${e2 instanceof Error ? e2.message : String(e2)}`));
319976
+ }
319977
+ }
319122
319978
  if (isMedia && fullInput === input) {
319123
319979
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
319124
319980
  const engine = getListenEngine();
@@ -319513,7 +320369,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319513
320369
  if (existsSync77(ikFile)) {
319514
320370
  ikState = JSON.parse(readFileSync60(ikFile, "utf8"));
319515
320371
  } else {
319516
- mkdirSync46(ikDir, { recursive: true });
320372
+ mkdirSync47(ikDir, { recursive: true });
319517
320373
  ikState = {
319518
320374
  self_id: `oa-${Date.now().toString(36)}`,
319519
320375
  version: 1,
@@ -319535,7 +320391,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319535
320391
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
319536
320392
  ikState.session_count = (ikState.session_count || 0) + 1;
319537
320393
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
319538
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
320394
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
319539
320395
  } catch (ikErr) {
319540
320396
  }
319541
320397
  try {
@@ -319566,8 +320422,8 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319566
320422
  tags: ["general"]
319567
320423
  });
319568
320424
  if (variants.length > 50) variants = variants.slice(-50);
319569
- mkdirSync46(archeDir, { recursive: true });
319570
- writeFileSync40(archeFile, JSON.stringify(variants, null, 2));
320425
+ mkdirSync47(archeDir, { recursive: true });
320426
+ writeFileSync41(archeFile, JSON.stringify(variants, null, 2));
319571
320427
  } catch {
319572
320428
  }
319573
320429
  }
@@ -319585,7 +320441,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319585
320441
  updated = true;
319586
320442
  }
319587
320443
  if (updated) {
319588
- writeFileSync40(metaFile, JSON.stringify(store2, null, 2));
320444
+ writeFileSync41(metaFile, JSON.stringify(store2, null, 2));
319589
320445
  }
319590
320446
  }
319591
320447
  } catch {
@@ -319639,7 +320495,7 @@ Rules:
319639
320495
  const { initDb: initDb2 } = __require("@open-agents/memory");
319640
320496
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
319641
320497
  const dbDir = join94(repoRoot, ".oa", "memory");
319642
- mkdirSync46(dbDir, { recursive: true });
320498
+ mkdirSync47(dbDir, { recursive: true });
319643
320499
  const db = initDb2(join94(dbDir, "structured.db"));
319644
320500
  const memStore = new ProceduralMemoryStore2(db);
319645
320501
  memStore.createWithEmbedding({
@@ -319674,8 +320530,8 @@ Rules:
319674
320530
  accessCount: 0
319675
320531
  });
319676
320532
  if (store2.length > 100) store2 = store2.slice(-100);
319677
- mkdirSync46(metaDir, { recursive: true });
319678
- writeFileSync40(storeFile, JSON.stringify(store2, null, 2));
320533
+ mkdirSync47(metaDir, { recursive: true });
320534
+ writeFileSync41(storeFile, JSON.stringify(store2, null, 2));
319679
320535
  }
319680
320536
  }
319681
320537
  } catch {
@@ -319725,7 +320581,7 @@ Rules:
319725
320581
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
319726
320582
  ikState.session_count = (ikState.session_count || 0) + 1;
319727
320583
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
319728
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
320584
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
319729
320585
  }
319730
320586
  const metaFile = join94(repoRoot, ".oa", "memory", "metabolism", "store.json");
319731
320587
  if (existsSync77(metaFile)) {
@@ -319737,7 +320593,7 @@ Rules:
319737
320593
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
319738
320594
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
319739
320595
  }
319740
- writeFileSync40(metaFile, JSON.stringify(store2, null, 2));
320596
+ writeFileSync41(metaFile, JSON.stringify(store2, null, 2));
319741
320597
  }
319742
320598
  try {
319743
320599
  const archeDir = join94(repoRoot, ".oa", "arche");
@@ -319758,8 +320614,8 @@ Rules:
319758
320614
  tags: ["general"]
319759
320615
  });
319760
320616
  if (variants.length > 50) variants = variants.slice(-50);
319761
- mkdirSync46(archeDir, { recursive: true });
319762
- writeFileSync40(archeFile, JSON.stringify(variants, null, 2));
320617
+ mkdirSync47(archeDir, { recursive: true });
320618
+ writeFileSync41(archeFile, JSON.stringify(variants, null, 2));
319763
320619
  } catch {
319764
320620
  }
319765
320621
  } catch {
@@ -319841,13 +320697,13 @@ __export(run_exports, {
319841
320697
  });
319842
320698
  import { resolve as resolve36 } from "node:path";
319843
320699
  import { spawn as spawn26 } from "node:child_process";
319844
- import { mkdirSync as mkdirSync47, writeFileSync as writeFileSync41, readFileSync as readFileSync61, readdirSync as readdirSync26, existsSync as existsSync78 } from "node:fs";
320700
+ import { mkdirSync as mkdirSync48, writeFileSync as writeFileSync42, readFileSync as readFileSync61, readdirSync as readdirSync26, existsSync as existsSync78 } from "node:fs";
319845
320701
  import { randomBytes as randomBytes20 } from "node:crypto";
319846
320702
  import { join as join95 } from "node:path";
319847
320703
  function jobsDir2(repoPath) {
319848
320704
  const root = resolve36(repoPath ?? process.cwd());
319849
320705
  const dir = join95(root, ".oa", "jobs");
319850
- mkdirSync47(dir, { recursive: true });
320706
+ mkdirSync48(dir, { recursive: true });
319851
320707
  return dir;
319852
320708
  }
319853
320709
  async function runCommand(opts, config) {
@@ -319962,7 +320818,7 @@ async function runBackground(task, config, opts) {
319962
320818
  }
319963
320819
  });
319964
320820
  job.pid = child.pid ?? 0;
319965
- writeFileSync41(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
320821
+ writeFileSync42(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
319966
320822
  let output = "";
319967
320823
  child.stdout?.on("data", (chunk) => {
319968
320824
  output += chunk.toString();
@@ -319978,7 +320834,7 @@ async function runBackground(task, config, opts) {
319978
320834
  job.summary = result.summary;
319979
320835
  job.durationMs = result.durationMs;
319980
320836
  job.error = result.error;
319981
- writeFileSync41(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
320837
+ writeFileSync42(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
319982
320838
  } catch {
319983
320839
  }
319984
320840
  });
@@ -320801,7 +321657,7 @@ __export(eval_exports, {
320801
321657
  evalCommand: () => evalCommand
320802
321658
  });
320803
321659
  import { tmpdir as tmpdir20 } from "node:os";
320804
- import { mkdirSync as mkdirSync48, writeFileSync as writeFileSync42 } from "node:fs";
321660
+ import { mkdirSync as mkdirSync49, writeFileSync as writeFileSync43 } from "node:fs";
320805
321661
  import { join as join98 } from "node:path";
320806
321662
  async function evalCommand(opts, config) {
320807
321663
  const suiteName = opts.suite ?? "basic";
@@ -320932,8 +321788,8 @@ async function evalCommand(opts, config) {
320932
321788
  }
320933
321789
  function createTempEvalRepo() {
320934
321790
  const dir = join98(tmpdir20(), `open-agents-eval-${Date.now()}`);
320935
- mkdirSync48(dir, { recursive: true });
320936
- writeFileSync42(
321791
+ mkdirSync49(dir, { recursive: true });
321792
+ writeFileSync43(
320937
321793
  join98(dir, "package.json"),
320938
321794
  JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n",
320939
321795
  "utf8"
@@ -320997,7 +321853,7 @@ init_updater();
320997
321853
  import { parseArgs as nodeParseArgs2 } from "node:util";
320998
321854
  import { createRequire as createRequire6 } from "node:module";
320999
321855
  import { fileURLToPath as fileURLToPath18 } from "node:url";
321000
- import { dirname as dirname27, join as join99 } from "node:path";
321856
+ import { dirname as dirname28, join as join99 } from "node:path";
321001
321857
 
321002
321858
  // packages/cli/src/cli.ts
321003
321859
  import { createInterface } from "node:readline";
@@ -321104,7 +321960,7 @@ init_output();
321104
321960
  function getVersion5() {
321105
321961
  try {
321106
321962
  const require3 = createRequire6(import.meta.url);
321107
- const pkgPath = join99(dirname27(fileURLToPath18(import.meta.url)), "..", "package.json");
321963
+ const pkgPath = join99(dirname28(fileURLToPath18(import.meta.url)), "..", "package.json");
321108
321964
  const pkg = require3(pkgPath);
321109
321965
  return pkg.version;
321110
321966
  } catch {
@@ -321396,11 +322252,11 @@ function crashLog(label, err) {
321396
322252
  const logLine = `[${timestamp}] ${label}: ${msg}
321397
322253
  `;
321398
322254
  try {
321399
- const { appendFileSync: appendFileSync7, mkdirSync: mkdirSync49 } = __require("node:fs");
322255
+ const { appendFileSync: appendFileSync7, mkdirSync: mkdirSync50 } = __require("node:fs");
321400
322256
  const { join: join100 } = __require("node:path");
321401
322257
  const { homedir: homedir32 } = __require("node:os");
321402
322258
  const logDir = join100(homedir32(), ".open-agents");
321403
- mkdirSync49(logDir, { recursive: true });
322259
+ mkdirSync50(logDir, { recursive: true });
321404
322260
  appendFileSync7(join100(logDir, "crash.log"), logLine);
321405
322261
  } catch {
321406
322262
  }