open-agents-ai 0.187.175 → 0.187.177

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 +1210 -305
  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");
@@ -259711,6 +259711,8 @@ var init_transport5 = __esm({
259711
259711
  url;
259712
259712
  headers;
259713
259713
  _connected = true;
259714
+ sessionId = null;
259715
+ protocolVersion = null;
259714
259716
  get connected() {
259715
259717
  return this._connected;
259716
259718
  }
@@ -259718,26 +259720,57 @@ var init_transport5 = __esm({
259718
259720
  this.url = config.url;
259719
259721
  this.headers = config.headers ?? {};
259720
259722
  }
259723
+ /**
259724
+ * Called by McpClient after initialize negotiates a protocol version.
259725
+ * After this point all requests will include MCP-Protocol-Version.
259726
+ */
259727
+ setProtocolVersion(version4) {
259728
+ this.protocolVersion = version4;
259729
+ }
259730
+ /** Build the headers for every POST request */
259731
+ buildHeaders(extra) {
259732
+ const h = {
259733
+ "Content-Type": "application/json",
259734
+ // Spec: client MUST list both content types in Accept
259735
+ "Accept": "application/json, text/event-stream",
259736
+ ...this.headers
259737
+ };
259738
+ if (this.sessionId)
259739
+ h["Mcp-Session-Id"] = this.sessionId;
259740
+ if (this.protocolVersion)
259741
+ h["MCP-Protocol-Version"] = this.protocolVersion;
259742
+ if (extra)
259743
+ Object.assign(h, extra);
259744
+ return h;
259745
+ }
259721
259746
  async request(req2, timeoutMs = 3e4) {
259722
259747
  const controller = new AbortController();
259723
259748
  const timer = setTimeout(() => controller.abort(), timeoutMs);
259724
259749
  try {
259725
259750
  const resp = await fetch(this.url, {
259726
259751
  method: "POST",
259727
- headers: {
259728
- "Content-Type": "application/json",
259729
- "Accept": "application/json",
259730
- ...this.headers
259731
- },
259752
+ headers: this.buildHeaders(),
259732
259753
  body: JSON.stringify(req2),
259733
259754
  signal: controller.signal
259734
259755
  });
259735
259756
  clearTimeout(timer);
259757
+ const sessionHeader = resp.headers.get("Mcp-Session-Id") ?? resp.headers.get("mcp-session-id");
259758
+ if (sessionHeader && req2.method === "initialize") {
259759
+ this.sessionId = sessionHeader;
259760
+ }
259761
+ if (resp.status === 404 && this.sessionId) {
259762
+ this.sessionId = null;
259763
+ throw new Error(`MCP session expired (HTTP 404): ${req2.method}`);
259764
+ }
259736
259765
  if (!resp.ok) {
259737
- throw new Error(`MCP HTTP error: ${resp.status} ${resp.statusText}`);
259766
+ const text = await resp.text().catch(() => "");
259767
+ throw new Error(`MCP HTTP error: ${resp.status} ${resp.statusText}${text ? ` \u2014 ${text.slice(0, 200)}` : ""}`);
259768
+ }
259769
+ const ct = (resp.headers.get("Content-Type") ?? "").toLowerCase();
259770
+ if (ct.includes("text/event-stream")) {
259771
+ return await this.readSseResponse(resp, req2.id);
259738
259772
  }
259739
- const body = await resp.json();
259740
- return body;
259773
+ return await resp.json();
259741
259774
  } catch (err) {
259742
259775
  clearTimeout(timer);
259743
259776
  if (err instanceof Error && err.name === "AbortError") {
@@ -259746,19 +259779,71 @@ var init_transport5 = __esm({
259746
259779
  throw err;
259747
259780
  }
259748
259781
  }
259782
+ /**
259783
+ * Parse an SSE stream and return the first JSON-RPC response whose id matches.
259784
+ * Per spec, server SHOULD eventually emit the matching response on this stream.
259785
+ */
259786
+ async readSseResponse(resp, expectedId) {
259787
+ if (!resp.body)
259788
+ throw new Error("MCP SSE response has no body");
259789
+ const reader = resp.body.getReader();
259790
+ const decoder = new TextDecoder();
259791
+ let buf = "";
259792
+ try {
259793
+ while (true) {
259794
+ const { value: value2, done } = await reader.read();
259795
+ if (done)
259796
+ break;
259797
+ buf += decoder.decode(value2, { stream: true });
259798
+ let sep;
259799
+ while ((sep = buf.indexOf("\n\n")) !== -1) {
259800
+ const event = buf.slice(0, sep);
259801
+ buf = buf.slice(sep + 2);
259802
+ const dataLines = [];
259803
+ for (const line of event.split("\n")) {
259804
+ if (line.startsWith("data:"))
259805
+ dataLines.push(line.slice(5).trimStart());
259806
+ }
259807
+ if (dataLines.length === 0)
259808
+ continue;
259809
+ const dataStr = dataLines.join("\n");
259810
+ try {
259811
+ const msg = JSON.parse(dataStr);
259812
+ if (msg.id === expectedId || msg.id != null) {
259813
+ return msg;
259814
+ }
259815
+ } catch {
259816
+ }
259817
+ }
259818
+ }
259819
+ throw new Error("MCP SSE stream closed before response received");
259820
+ } finally {
259821
+ try {
259822
+ reader.releaseLock();
259823
+ } catch {
259824
+ }
259825
+ }
259826
+ }
259749
259827
  notify(notif) {
259750
259828
  fetch(this.url, {
259751
259829
  method: "POST",
259752
- headers: {
259753
- "Content-Type": "application/json",
259754
- ...this.headers
259755
- },
259830
+ headers: this.buildHeaders(),
259756
259831
  body: JSON.stringify(notif)
259757
259832
  }).catch(() => {
259758
259833
  });
259759
259834
  }
259760
259835
  async close() {
259836
+ if (this.sessionId) {
259837
+ try {
259838
+ await fetch(this.url, {
259839
+ method: "DELETE",
259840
+ headers: this.buildHeaders()
259841
+ });
259842
+ } catch {
259843
+ }
259844
+ }
259761
259845
  this._connected = false;
259846
+ this.sessionId = null;
259762
259847
  }
259763
259848
  };
259764
259849
  }
@@ -259780,14 +259865,15 @@ function parseMcpToolName(fullName) {
259780
259865
  return null;
259781
259866
  return { server: match[1], tool: match[2] };
259782
259867
  }
259783
- var MCP_PROTOCOL_VERSION, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, DEFAULT_TIMEOUT_MS, _nextId, McpClient;
259868
+ var MCP_PROTOCOL_VERSION, MCP_CLIENT_NAME, MCP_CLIENT_TITLE, MCP_CLIENT_VERSION, DEFAULT_TIMEOUT_MS, _nextId, McpClient;
259784
259869
  var init_client3 = __esm({
259785
259870
  "packages/execution/dist/mcp/client.js"() {
259786
259871
  "use strict";
259787
259872
  init_transport5();
259788
- MCP_PROTOCOL_VERSION = "2025-11-25";
259873
+ MCP_PROTOCOL_VERSION = "2025-06-18";
259789
259874
  MCP_CLIENT_NAME = "open-agents";
259790
- MCP_CLIENT_VERSION = "0.187.0";
259875
+ MCP_CLIENT_TITLE = "Open Agents";
259876
+ MCP_CLIENT_VERSION = "0.187.176";
259791
259877
  DEFAULT_TIMEOUT_MS = 3e4;
259792
259878
  _nextId = 1;
259793
259879
  McpClient = class {
@@ -259828,10 +259914,13 @@ var init_client3 = __esm({
259828
259914
  params: {
259829
259915
  protocolVersion: MCP_PROTOCOL_VERSION,
259830
259916
  capabilities: {
259831
- roots: {}
259917
+ // Open Agents currently advertises only roots; sampling and elicitation
259918
+ // would need additional client-side support to be honestly negotiated.
259919
+ roots: { listChanged: false }
259832
259920
  },
259833
259921
  clientInfo: {
259834
259922
  name: MCP_CLIENT_NAME,
259923
+ title: MCP_CLIENT_TITLE,
259835
259924
  version: MCP_CLIENT_VERSION
259836
259925
  }
259837
259926
  }
@@ -259842,6 +259931,16 @@ var init_client3 = __esm({
259842
259931
  }
259843
259932
  const result = initResp.result;
259844
259933
  this.initResult = result;
259934
+ if (result.protocolVersion && result.protocolVersion !== MCP_PROTOCOL_VERSION) {
259935
+ if (result.protocolVersion !== "2025-03-26" && result.protocolVersion !== "2024-11-05") {
259936
+ await this.transport.close().catch(() => {
259937
+ });
259938
+ throw new Error(`MCP server proposed unsupported protocol version: ${result.protocolVersion}`);
259939
+ }
259940
+ }
259941
+ if (typeof this.transport.setProtocolVersion === "function") {
259942
+ this.transport.setProtocolVersion(result.protocolVersion ?? MCP_PROTOCOL_VERSION);
259943
+ }
259845
259944
  this.transport.notify({
259846
259945
  jsonrpc: "2.0",
259847
259946
  method: "notifications/initialized"
@@ -260003,8 +260102,8 @@ var init_client3 = __esm({
260003
260102
  });
260004
260103
 
260005
260104
  // 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";
260105
+ import { existsSync as existsSync39, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync20 } from "node:fs";
260106
+ import { join as join54, dirname as dirname14 } from "node:path";
260008
260107
  import { homedir as homedir17 } from "node:os";
260009
260108
  function loadMcpConfig(repoRoot) {
260010
260109
  const servers = {};
@@ -260055,6 +260154,38 @@ function expandEnvVars(str) {
260055
260154
  return process.env[name10] ?? "";
260056
260155
  });
260057
260156
  }
260157
+ function saveMcpServerToConfig(repoRoot, serverName, config, scope = "project") {
260158
+ const path5 = scope === "global" ? join54(homedir17(), ".open-agents", "mcp.json") : join54(repoRoot, ".oa", "mcp.json");
260159
+ let existing = { mcpServers: {} };
260160
+ if (existsSync39(path5)) {
260161
+ try {
260162
+ existing = JSON.parse(readFileSync29(path5, "utf8"));
260163
+ if (!existing.mcpServers)
260164
+ existing.mcpServers = {};
260165
+ } catch {
260166
+ }
260167
+ }
260168
+ existing.mcpServers[serverName] = config;
260169
+ mkdirSync20(dirname14(path5), { recursive: true });
260170
+ writeFileSync17(path5, JSON.stringify(existing, null, 2) + "\n");
260171
+ return path5;
260172
+ }
260173
+ function removeMcpServerFromConfig(repoRoot, serverName, scope = "project") {
260174
+ const path5 = scope === "global" ? join54(homedir17(), ".open-agents", "mcp.json") : join54(repoRoot, ".oa", "mcp.json");
260175
+ if (!existsSync39(path5))
260176
+ return false;
260177
+ let cfg;
260178
+ try {
260179
+ cfg = JSON.parse(readFileSync29(path5, "utf8"));
260180
+ } catch {
260181
+ return false;
260182
+ }
260183
+ if (!cfg.mcpServers || !cfg.mcpServers[serverName])
260184
+ return false;
260185
+ delete cfg.mcpServers[serverName];
260186
+ writeFileSync17(path5, JSON.stringify(cfg, null, 2) + "\n");
260187
+ return true;
260188
+ }
260058
260189
  var McpManager;
260059
260190
  var init_manager2 = __esm({
260060
260191
  "packages/execution/dist/mcp/manager.js"() {
@@ -260134,6 +260265,21 @@ var init_manager2 = __esm({
260134
260265
  this.clients.delete(name10);
260135
260266
  }
260136
260267
  }
260268
+ /**
260269
+ * Add a server at runtime: persist to mcp.json AND attempt to connect.
260270
+ * Returns the connection result.
260271
+ */
260272
+ async addServer(name10, config, scope = "project") {
260273
+ saveMcpServerToConfig(this.repoRoot, name10, config, scope);
260274
+ return this.connectOne(name10, config);
260275
+ }
260276
+ /**
260277
+ * Remove a server at runtime: disconnect AND delete from mcp.json.
260278
+ */
260279
+ async removeServer(name10, scope = "project") {
260280
+ await this.disconnect(name10);
260281
+ return removeMcpServerFromConfig(this.repoRoot, name10, scope);
260282
+ }
260137
260283
  /**
260138
260284
  * Get all connections.
260139
260285
  */
@@ -260173,7 +260319,8 @@ var init_manager2 = __esm({
260173
260319
  // ─────────────────────────────────────────────────────────
260174
260320
  wrapMcpTool(client, def) {
260175
260321
  const fullName = buildMcpToolName(client.name, def.name);
260176
- const description = def.description ? `[MCP: ${client.name}] ${def.description}` : `[MCP: ${client.name}] ${def.name}`;
260322
+ const displayTitle = def.title ?? def.annotations?.title ?? def.name;
260323
+ const description = def.description ? `[MCP: ${client.name}] ${def.description}` : `[MCP: ${client.name}] ${displayTitle}`;
260177
260324
  return {
260178
260325
  name: fullName,
260179
260326
  description: description.slice(0, 500),
@@ -260182,7 +260329,35 @@ var init_manager2 = __esm({
260182
260329
  const start2 = performance.now();
260183
260330
  try {
260184
260331
  const result = await client.callTool(def.name, args);
260185
- const text = result.content.filter((c7) => c7.type === "text").map((c7) => c7.text).join("\n");
260332
+ const parts = [];
260333
+ for (const block of result.content) {
260334
+ if (block.type === "text") {
260335
+ parts.push(block.text);
260336
+ } else if (block.type === "image") {
260337
+ parts.push(`[image: ${block.mimeType}, ${Math.round(block.data.length * 0.75 / 1024)}KB base64]`);
260338
+ } else if (block.type === "audio") {
260339
+ parts.push(`[audio: ${block.mimeType}, ${Math.round(block.data.length * 0.75 / 1024)}KB base64]`);
260340
+ } else if (block.type === "resource_link") {
260341
+ parts.push(`[resource_link: ${block.uri}${block.name ? ` (${block.name})` : ""}${block.mimeType ? ` ${block.mimeType}` : ""}]${block.description ? `
260342
+ ${block.description}` : ""}`);
260343
+ } else if (block.type === "resource") {
260344
+ const r2 = block.resource;
260345
+ if (r2.text) {
260346
+ parts.push(`[resource ${r2.uri}${r2.mimeType ? ` (${r2.mimeType})` : ""}]
260347
+ ${r2.text}`);
260348
+ } else if (r2.blob) {
260349
+ parts.push(`[resource ${r2.uri}${r2.mimeType ? ` (${r2.mimeType})` : ""}, ${Math.round(r2.blob.length * 0.75 / 1024)}KB binary]`);
260350
+ }
260351
+ }
260352
+ }
260353
+ if (result.structuredContent !== void 0) {
260354
+ try {
260355
+ parts.push(`[structuredContent]
260356
+ ${JSON.stringify(result.structuredContent, null, 2)}`);
260357
+ } catch {
260358
+ }
260359
+ }
260360
+ const text = parts.join("\n").trim();
260186
260361
  return {
260187
260362
  success: !result.isError,
260188
260363
  output: text || "(empty response)",
@@ -260299,6 +260474,232 @@ var init_manager2 = __esm({
260299
260474
  }
260300
260475
  });
260301
260476
 
260477
+ // packages/execution/dist/mcp/md-intake.js
260478
+ function slugify(s2) {
260479
+ return s2.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "mcp-server";
260480
+ }
260481
+ function extractCodeBlocks(md) {
260482
+ const blocks = [];
260483
+ const re = /^(?:```|~~~)([A-Za-z0-9_+\-]*)\r?\n([\s\S]*?)\r?\n(?:```|~~~)\s*$/gm;
260484
+ let m2;
260485
+ while ((m2 = re.exec(md)) !== null) {
260486
+ blocks.push({ lang: (m2[1] || "").toLowerCase(), code: m2[2] });
260487
+ }
260488
+ return blocks;
260489
+ }
260490
+ function isMcpMarkdown(md) {
260491
+ const lower = md.toLowerCase();
260492
+ let hits = 0;
260493
+ for (const k of MCP_KEYWORDS) {
260494
+ if (lower.includes(k.toLowerCase()))
260495
+ hits++;
260496
+ }
260497
+ if (hits >= 2)
260498
+ return true;
260499
+ if (/"mcpServers"/.test(md))
260500
+ return true;
260501
+ return false;
260502
+ }
260503
+ function tryParseJson(s2) {
260504
+ try {
260505
+ return JSON.parse(s2);
260506
+ } catch {
260507
+ try {
260508
+ const cleaned = s2.replace(/,(\s*[}\]])/g, "$1");
260509
+ return JSON.parse(cleaned);
260510
+ } catch {
260511
+ return null;
260512
+ }
260513
+ }
260514
+ }
260515
+ function coerceServerConfig(value2) {
260516
+ if (!value2 || typeof value2 !== "object")
260517
+ return null;
260518
+ const v = value2;
260519
+ if (typeof v.command === "string") {
260520
+ const cfg = {
260521
+ type: "stdio",
260522
+ command: v.command
260523
+ };
260524
+ if (Array.isArray(v.args) && v.args.every((a2) => typeof a2 === "string")) {
260525
+ cfg.args = v.args;
260526
+ }
260527
+ if (v.env && typeof v.env === "object" && !Array.isArray(v.env)) {
260528
+ const env2 = {};
260529
+ for (const [k, val] of Object.entries(v.env)) {
260530
+ if (typeof val === "string")
260531
+ env2[k] = val;
260532
+ }
260533
+ if (Object.keys(env2).length > 0)
260534
+ cfg.env = env2;
260535
+ }
260536
+ return cfg;
260537
+ }
260538
+ if (typeof v.url === "string" && /^https?:\/\//i.test(v.url)) {
260539
+ const type = v.type === "sse" ? "sse" : "http";
260540
+ const cfg = { type, url: v.url };
260541
+ if (v.headers && typeof v.headers === "object" && !Array.isArray(v.headers)) {
260542
+ const headers = {};
260543
+ for (const [k, val] of Object.entries(v.headers)) {
260544
+ if (typeof val === "string")
260545
+ headers[k] = val;
260546
+ }
260547
+ if (Object.keys(headers).length > 0)
260548
+ cfg.headers = headers;
260549
+ }
260550
+ return cfg;
260551
+ }
260552
+ return null;
260553
+ }
260554
+ function parseMcpServersBlock(json) {
260555
+ if (!json || typeof json !== "object")
260556
+ return [];
260557
+ const root = json;
260558
+ if (!root.mcpServers || typeof root.mcpServers !== "object")
260559
+ return [];
260560
+ const out = [];
260561
+ for (const [name10, raw] of Object.entries(root.mcpServers)) {
260562
+ const cfg = coerceServerConfig(raw);
260563
+ if (cfg) {
260564
+ out.push({
260565
+ name: slugify(name10),
260566
+ config: cfg,
260567
+ confidence: 1,
260568
+ source: "json-mcpServers"
260569
+ });
260570
+ }
260571
+ }
260572
+ return out;
260573
+ }
260574
+ function parseBareServerBlock(json, blockIdx) {
260575
+ const cfg = coerceServerConfig(json);
260576
+ if (!cfg)
260577
+ return null;
260578
+ let name10 = `mcp-server-${blockIdx + 1}`;
260579
+ if ("command" in cfg && cfg.command) {
260580
+ const args = cfg.args ?? [];
260581
+ const pkg = args.find((a2) => /^@?[\w-]+\/?[\w-]*-?mcp/.test(a2) || /server-/.test(a2));
260582
+ if (pkg)
260583
+ name10 = slugify(pkg.replace(/^@[^/]+\//, "").replace(/^-y$/, ""));
260584
+ else if (typeof cfg.command === "string")
260585
+ name10 = slugify(cfg.command.split("/").pop() || cfg.command);
260586
+ } else if ("url" in cfg && cfg.url) {
260587
+ try {
260588
+ const u = new URL(cfg.url);
260589
+ name10 = slugify(u.hostname.replace(/^www\./, "").replace(/\.(com|io|net|ai|app|dev)$/, ""));
260590
+ } catch {
260591
+ }
260592
+ }
260593
+ return { name: name10, config: cfg, confidence: 0.85, source: "json-bare-server" };
260594
+ }
260595
+ function parseNpxCommand(code8, blockIdx) {
260596
+ const m2 = code8.match(/\bnpx\s+(?:-y\s+|--yes\s+)?([@\w./-]+)(?:\s+(.+))?/);
260597
+ if (!m2)
260598
+ return null;
260599
+ const pkg = m2[1];
260600
+ const extraArgs = m2[2] ? m2[2].trim().split(/\s+/) : [];
260601
+ const isMcp = /mcp/i.test(pkg) || /^@modelcontextprotocol\//.test(pkg) || /server-/.test(pkg);
260602
+ if (!isMcp)
260603
+ return null;
260604
+ const args = ["-y", pkg, ...extraArgs];
260605
+ const name10 = slugify(pkg.replace(/^@[^/]+\//, "").replace(/^server-/, "").replace(/-mcp(-server)?$/, "").replace(/-server$/, ""));
260606
+ return {
260607
+ name: name10,
260608
+ config: { type: "stdio", command: "npx", args },
260609
+ confidence: /mcp/i.test(pkg) ? 0.9 : 0.7,
260610
+ source: "code-npx"
260611
+ };
260612
+ }
260613
+ function parseHttpUrlBlock(code8, hasMcpContext) {
260614
+ if (!hasMcpContext)
260615
+ return null;
260616
+ const m2 = code8.match(/(https?:\/\/[^\s"'`<>]+)/);
260617
+ if (!m2)
260618
+ return null;
260619
+ const url = m2[1];
260620
+ if (!/mcp/i.test(url) && !/sse$/.test(url))
260621
+ return null;
260622
+ let name10 = "mcp-http";
260623
+ try {
260624
+ const u = new URL(url);
260625
+ name10 = slugify(u.hostname.replace(/^www\./, "").replace(/\.(com|io|net|ai|app|dev)$/, ""));
260626
+ } catch {
260627
+ }
260628
+ return {
260629
+ name: name10,
260630
+ config: { type: "http", url },
260631
+ confidence: 0.6,
260632
+ source: "code-url"
260633
+ };
260634
+ }
260635
+ function parseMcpMarkdown(md) {
260636
+ const notes2 = [];
260637
+ const servers = [];
260638
+ const isMcp = isMcpMarkdown(md);
260639
+ const blocks = extractCodeBlocks(md);
260640
+ blocks.forEach((block, idx) => {
260641
+ const lang = block.lang;
260642
+ if (lang === "json" || lang === "jsonc" || lang === "json5" || lang === "" || lang === "text") {
260643
+ const parsed = tryParseJson(block.code);
260644
+ if (parsed) {
260645
+ const fromWrapper = parseMcpServersBlock(parsed);
260646
+ if (fromWrapper.length > 0) {
260647
+ servers.push(...fromWrapper);
260648
+ return;
260649
+ }
260650
+ const bare = parseBareServerBlock(parsed, idx);
260651
+ if (bare) {
260652
+ servers.push(bare);
260653
+ return;
260654
+ }
260655
+ }
260656
+ }
260657
+ if (lang === "sh" || lang === "bash" || lang === "shell" || lang === "console" || lang === "zsh" || lang === "") {
260658
+ const npx = parseNpxCommand(block.code, idx);
260659
+ if (npx) {
260660
+ servers.push(npx);
260661
+ return;
260662
+ }
260663
+ }
260664
+ if (isMcp) {
260665
+ const http6 = parseHttpUrlBlock(block.code, true);
260666
+ if (http6) {
260667
+ servers.push(http6);
260668
+ return;
260669
+ }
260670
+ }
260671
+ });
260672
+ const byName = /* @__PURE__ */ new Map();
260673
+ for (const s2 of servers) {
260674
+ const existing = byName.get(s2.name);
260675
+ if (!existing || s2.confidence > existing.confidence) {
260676
+ byName.set(s2.name, s2);
260677
+ }
260678
+ }
260679
+ const finalServers = Array.from(byName.values()).sort((a2, b) => b.confidence - a2.confidence);
260680
+ if (finalServers.length === 0 && isMcp) {
260681
+ notes2.push("Markdown looks MCP-related but no valid server config could be extracted from code blocks.");
260682
+ }
260683
+ return {
260684
+ servers: finalServers,
260685
+ isMcpDocument: isMcp,
260686
+ notes: notes2
260687
+ };
260688
+ }
260689
+ var MCP_KEYWORDS;
260690
+ var init_md_intake = __esm({
260691
+ "packages/execution/dist/mcp/md-intake.js"() {
260692
+ "use strict";
260693
+ MCP_KEYWORDS = [
260694
+ "mcp",
260695
+ "model context protocol",
260696
+ "modelcontextprotocol",
260697
+ "mcpServers",
260698
+ "MCP server"
260699
+ ];
260700
+ }
260701
+ });
260702
+
260302
260703
  // packages/execution/dist/mcp/index.js
260303
260704
  var init_mcp = __esm({
260304
260705
  "packages/execution/dist/mcp/index.js"() {
@@ -260306,6 +260707,7 @@ var init_mcp = __esm({
260306
260707
  init_client3();
260307
260708
  init_manager2();
260308
260709
  init_transport5();
260710
+ init_md_intake();
260309
260711
  }
260310
260712
  });
260311
260713
 
@@ -260470,7 +260872,7 @@ var init_plugin_system = __esm({
260470
260872
  });
260471
260873
 
260472
260874
  // packages/execution/dist/tools/notebook-edit.js
260473
- import { readFileSync as readFileSync31, writeFileSync as writeFileSync17, existsSync as existsSync41 } from "node:fs";
260875
+ import { readFileSync as readFileSync31, writeFileSync as writeFileSync18, existsSync as existsSync41 } from "node:fs";
260474
260876
  function readNotebook(path5) {
260475
260877
  if (!existsSync41(path5))
260476
260878
  return `File not found: ${path5}`;
@@ -260487,7 +260889,7 @@ function readNotebook(path5) {
260487
260889
  }
260488
260890
  }
260489
260891
  function writeNotebook(path5, nb) {
260490
- writeFileSync17(path5, JSON.stringify(nb, null, 1) + "\n", "utf8");
260892
+ writeFileSync18(path5, JSON.stringify(nb, null, 1) + "\n", "utf8");
260491
260893
  }
260492
260894
  function sourceToLines(source) {
260493
260895
  const lines = source.split("\n");
@@ -260771,7 +261173,7 @@ var init_environment_snapshot = __esm({
260771
261173
 
260772
261174
  // packages/execution/dist/tools/video-understand.js
260773
261175
  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";
261176
+ import { existsSync as existsSync42, mkdirSync as mkdirSync21, writeFileSync as writeFileSync19, readFileSync as readFileSync32, readdirSync as readdirSync9, unlinkSync as unlinkSync9 } from "node:fs";
260775
261177
  import { join as join56, basename as basename11 } from "node:path";
260776
261178
  import { createHash as createHash2 } from "node:crypto";
260777
261179
  function isYouTubeUrl2(url) {
@@ -260859,9 +261261,9 @@ var init_video_understand = __esm({
260859
261261
  return { success: false, output: "", error: "url or path required", durationMs: performance.now() - start2 };
260860
261262
  }
260861
261263
  const outDir = join56(this.workingDir, ".oa", "video-analysis");
260862
- mkdirSync20(outDir, { recursive: true });
261264
+ mkdirSync21(outDir, { recursive: true });
260863
261265
  const tmpDir = join56(outDir, `tmp-${Date.now()}`);
260864
- mkdirSync20(tmpDir, { recursive: true });
261266
+ mkdirSync21(tmpDir, { recursive: true });
260865
261267
  try {
260866
261268
  let videoPath;
260867
261269
  let audioPath;
@@ -260916,7 +261318,7 @@ var init_video_understand = __esm({
260916
261318
  let frames = [];
260917
261319
  if (!skipFrames && ensureFfmpeg() && existsSync42(videoPath)) {
260918
261320
  const framesDir = join56(tmpDir, "frames");
260919
- mkdirSync20(framesDir, { recursive: true });
261321
+ mkdirSync21(framesDir, { recursive: true });
260920
261322
  const fps = 25;
260921
261323
  const intervalFrames = Math.max(1, frameInterval * fps);
260922
261324
  try {
@@ -260937,11 +261339,11 @@ var init_video_understand = __esm({
260937
261339
  }
260938
261340
  deduplicateFrames(frames);
260939
261341
  const permanentDir = join56(outDir, `frames-${Date.now()}`);
260940
- mkdirSync20(permanentDir, { recursive: true });
261342
+ mkdirSync21(permanentDir, { recursive: true });
260941
261343
  for (const frame of frames.filter((f2) => !f2.isDuplicate)) {
260942
261344
  const dest = join56(permanentDir, basename11(frame.path));
260943
261345
  try {
260944
- writeFileSync18(dest, readFileSync32(frame.path));
261346
+ writeFileSync19(dest, readFileSync32(frame.path));
260945
261347
  frame.path = dest;
260946
261348
  } catch {
260947
261349
  }
@@ -260978,10 +261380,10 @@ var init_video_understand = __esm({
260978
261380
  };
260979
261381
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
260980
261382
  const resultFile = join56(outDir, `understanding-${timestamp}.json`);
260981
- writeFileSync18(resultFile, JSON.stringify(result, null, 2), "utf-8");
261383
+ writeFileSync19(resultFile, JSON.stringify(result, null, 2), "utf-8");
260982
261384
  try {
260983
261385
  const memDir = join56(this.workingDir, ".oa", "memory");
260984
- mkdirSync20(memDir, { recursive: true });
261386
+ mkdirSync21(memDir, { recursive: true });
260985
261387
  const indexFile = join56(memDir, "video-analyses.json");
260986
261388
  let indexEntries = [];
260987
261389
  try {
@@ -261001,7 +261403,7 @@ var init_video_understand = __esm({
261001
261403
  });
261002
261404
  if (indexEntries.length > 30)
261003
261405
  indexEntries = indexEntries.slice(-30);
261004
- writeFileSync18(indexFile, JSON.stringify(indexEntries, null, 2), "utf-8");
261406
+ writeFileSync19(indexFile, JSON.stringify(indexEntries, null, 2), "utf-8");
261005
261407
  const CHUNK_WINDOW = 30;
261006
261408
  const transcriptFile = join56(memDir, "video-transcripts.json");
261007
261409
  let transcriptEntries = {};
@@ -261032,7 +261434,7 @@ var init_video_understand = __esm({
261032
261434
  Topic: ${segments.slice(0, 5).map((s2) => s2.text).join(" ").slice(0, 300)}`,
261033
261435
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
261034
261436
  };
261035
- writeFileSync18(transcriptFile, JSON.stringify(transcriptEntries, null, 2), "utf-8");
261437
+ writeFileSync19(transcriptFile, JSON.stringify(transcriptEntries, null, 2), "utf-8");
261036
261438
  } catch {
261037
261439
  }
261038
261440
  const lines = [];
@@ -261352,8 +261754,8 @@ var init_gitWorktree = __esm({
261352
261754
  });
261353
261755
 
261354
261756
  // 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";
261757
+ import { readFileSync as readFileSync34, writeFileSync as writeFileSync20, existsSync as existsSync44, mkdirSync as mkdirSync22 } from "node:fs";
261758
+ import { dirname as dirname15 } from "node:path";
261357
261759
  import { spawn as spawn17 } from "node:child_process";
261358
261760
  async function applyPatch(patch) {
261359
261761
  switch (patch.type) {
@@ -261373,17 +261775,17 @@ function applyBlockReplace(patch) {
261373
261775
  throw new Error(`Block not found in "${patch.filePath}": the oldContent string was not found in the file.`);
261374
261776
  }
261375
261777
  const updated = original.replace(patch.oldContent, patch.newContent);
261376
- writeFileSync19(patch.filePath, updated, "utf-8");
261778
+ writeFileSync20(patch.filePath, updated, "utf-8");
261377
261779
  }
261378
261780
  function applyRewrite(patch) {
261379
- writeFileSync19(patch.filePath, patch.newContent, "utf-8");
261781
+ writeFileSync20(patch.filePath, patch.newContent, "utf-8");
261380
261782
  }
261381
261783
  function applyNewFile(patch) {
261382
261784
  if (existsSync44(patch.filePath)) {
261383
261785
  throw new Error(`Cannot create new file: "${patch.filePath}" already exists.`);
261384
261786
  }
261385
- mkdirSync21(dirname14(patch.filePath), { recursive: true });
261386
- writeFileSync19(patch.filePath, patch.newContent, "utf-8");
261787
+ mkdirSync22(dirname15(patch.filePath), { recursive: true });
261788
+ writeFileSync20(patch.filePath, patch.newContent, "utf-8");
261387
261789
  }
261388
261790
  async function applyUnifiedDiff(patch) {
261389
261791
  const { filePath, diff } = patch;
@@ -261394,7 +261796,7 @@ async function applyUnifiedDiff(patch) {
261394
261796
  "-p1",
261395
261797
  filePath
261396
261798
  ],
261397
- cwd: dirname14(filePath),
261799
+ cwd: dirname15(filePath),
261398
261800
  stdin: diff
261399
261801
  });
261400
261802
  if (!result.success) {
@@ -261740,7 +262142,7 @@ var init_buildRunner = __esm({
261740
262142
  });
261741
262143
 
261742
262144
  // packages/execution/dist/constraints.js
261743
- import { existsSync as existsSync45, readFileSync as readFileSync35, writeFileSync as writeFileSync20, mkdirSync as mkdirSync22 } from "node:fs";
262145
+ import { existsSync as existsSync45, readFileSync as readFileSync35, writeFileSync as writeFileSync21, mkdirSync as mkdirSync23 } from "node:fs";
261744
262146
  import { join as join59 } from "node:path";
261745
262147
  import { homedir as homedir19 } from "node:os";
261746
262148
  function loadConstraints(projectRoot) {
@@ -261771,8 +262173,8 @@ function addProjectConstraint(projectRoot, constraint) {
261771
262173
  } catch {
261772
262174
  }
261773
262175
  data.constraints.push(constraint);
261774
- mkdirSync22(join59(projectRoot, ".oa"), { recursive: true });
261775
- writeFileSync20(path5, JSON.stringify(data, null, 2), "utf-8");
262176
+ mkdirSync23(join59(projectRoot, ".oa"), { recursive: true });
262177
+ writeFileSync21(path5, JSON.stringify(data, null, 2), "utf-8");
261776
262178
  projectConstraints = data.constraints;
261777
262179
  }
261778
262180
  function getAllConstraints() {
@@ -262079,6 +262481,7 @@ __export(dist_exports, {
262079
262481
  getWorktreeSession: () => getWorktreeSession,
262080
262482
  isFortemiAvailable: () => isFortemiAvailable,
262081
262483
  isImagePath: () => isImagePath,
262484
+ isMcpMarkdown: () => isMcpMarkdown,
262082
262485
  isProcessAlive: () => isProcessAlive,
262083
262486
  killAllFullSubAgents: () => killAllFullSubAgents,
262084
262487
  killProcess: () => killProcess,
@@ -262095,11 +262498,13 @@ __export(dist_exports, {
262095
262498
  markReverted: () => markReverted,
262096
262499
  markSessionValidated: () => markSessionValidated,
262097
262500
  normalizeMcpName: () => normalizeMcpName,
262501
+ parseMcpMarkdown: () => parseMcpMarkdown,
262098
262502
  parseMcpToolName: () => parseMcpToolName,
262099
262503
  promoteWorkingNotes: () => promoteWorkingNotes,
262100
262504
  recordChange: () => recordChange,
262101
262505
  removeAgentWorktree: () => removeWorktree,
262102
262506
  removeFullSubAgent: () => removeFullSubAgent,
262507
+ removeMcpServerFromConfig: () => removeMcpServerFromConfig,
262103
262508
  removeWorktree: () => removeWorktree2,
262104
262509
  resetDepCache: () => resetDepCache,
262105
262510
  resetMoondreamClient: () => resetMoondreamClient,
@@ -262113,6 +262518,7 @@ __export(dist_exports, {
262113
262518
  runTypecheck: () => runTypecheck,
262114
262519
  runValidationPipeline: () => runValidationPipeline,
262115
262520
  saveCustomToolDefinition: () => saveCustomToolDefinition,
262521
+ saveMcpServerToConfig: () => saveMcpServerToConfig,
262116
262522
  serializeMap: () => serializeMap,
262117
262523
  setChangeLogSession: () => setChangeLogSession,
262118
262524
  setSudoPassword: () => setSudoPassword,
@@ -262903,7 +263309,7 @@ var init_dist5 = __esm({
262903
263309
 
262904
263310
  // packages/orchestrator/dist/promptLoader.js
262905
263311
  import { readFileSync as readFileSync36, existsSync as existsSync46 } from "node:fs";
262906
- import { join as join60, dirname as dirname15 } from "node:path";
263312
+ import { join as join60, dirname as dirname16 } from "node:path";
262907
263313
  import { fileURLToPath as fileURLToPath8 } from "node:url";
262908
263314
  function loadPrompt(promptPath, vars) {
262909
263315
  let content = cache4.get(promptPath);
@@ -262924,7 +263330,7 @@ var init_promptLoader = __esm({
262924
263330
  "packages/orchestrator/dist/promptLoader.js"() {
262925
263331
  "use strict";
262926
263332
  __filename3 = fileURLToPath8(import.meta.url);
262927
- __dirname5 = dirname15(__filename3);
263333
+ __dirname5 = dirname16(__filename3);
262928
263334
  PROMPTS_DIR = join60(__dirname5, "..", "prompts");
262929
263335
  cache4 = /* @__PURE__ */ new Map();
262930
263336
  }
@@ -265571,7 +265977,7 @@ var init_toolPatternStore = __esm({
265571
265977
 
265572
265978
  // packages/memory/dist/episodeStore.js
265573
265979
  import { join as join63 } from "node:path";
265574
- import { mkdirSync as mkdirSync23, existsSync as existsSync47 } from "node:fs";
265980
+ import { mkdirSync as mkdirSync24, existsSync as existsSync47 } from "node:fs";
265575
265981
  import { randomUUID as randomUUID5 } from "node:crypto";
265576
265982
  import { createHash as createHash3 } from "node:crypto";
265577
265983
  function autoImportance(toolName, modality, content) {
@@ -265637,7 +266043,7 @@ var init_episodeStore = __esm({
265637
266043
  constructor(dbPath) {
265638
266044
  const dir = dbPath === ":memory:" ? null : join63(dbPath, "..");
265639
266045
  if (dir && !existsSync47(dir))
265640
- mkdirSync23(dir, { recursive: true });
266046
+ mkdirSync24(dir, { recursive: true });
265641
266047
  this.db = initDb(dbPath);
265642
266048
  this.db.exec(`
265643
266049
  CREATE TABLE IF NOT EXISTS episodes (
@@ -265812,7 +266218,7 @@ var init_episodeStore = __esm({
265812
266218
 
265813
266219
  // packages/memory/dist/temporalGraph.js
265814
266220
  import { join as join64 } from "node:path";
265815
- import { mkdirSync as mkdirSync24, existsSync as existsSync48 } from "node:fs";
266221
+ import { mkdirSync as mkdirSync25, existsSync as existsSync48 } from "node:fs";
265816
266222
  import { randomUUID as randomUUID6 } from "node:crypto";
265817
266223
  var TemporalGraph;
265818
266224
  var init_temporalGraph = __esm({
@@ -265824,7 +266230,7 @@ var init_temporalGraph = __esm({
265824
266230
  constructor(dbPath) {
265825
266231
  const dir = dbPath === ":memory:" ? null : join64(dbPath, "..");
265826
266232
  if (dir && !existsSync48(dir))
265827
- mkdirSync24(dir, { recursive: true });
266233
+ mkdirSync25(dir, { recursive: true });
265828
266234
  this.db = initDb(dbPath);
265829
266235
  this.db.exec(`
265830
266236
  CREATE TABLE IF NOT EXISTS kg_nodes (
@@ -269717,11 +270123,11 @@ ${errOutput}`;
269717
270123
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
269718
270124
  });
269719
270125
  try {
269720
- const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync43 } = __require("node:fs");
270126
+ const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync44 } = __require("node:fs");
269721
270127
  const { join: join100 } = __require("node:path");
269722
270128
  const resultsDir = join100(process.cwd(), ".oa", "tool-results");
269723
- mkdirSync49(resultsDir, { recursive: true });
269724
- writeFileSync43(join100(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
270129
+ mkdirSync50(resultsDir, { recursive: true });
270130
+ writeFileSync44(join100(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
269725
270131
  # Turn: ${turn}
269726
270132
  # Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
269727
270133
  # Size: ${result.output.length} chars, ${lineCount} lines
@@ -269860,10 +270266,10 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
269860
270266
  if (!this._workingDirectory)
269861
270267
  return;
269862
270268
  try {
269863
- const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync43 } = __require("node:fs");
270269
+ const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync44 } = __require("node:fs");
269864
270270
  const { join: join100 } = __require("node:path");
269865
270271
  const sessionDir = join100(this._workingDirectory, ".oa", "session", this._sessionId);
269866
- mkdirSync49(sessionDir, { recursive: true });
270272
+ mkdirSync50(sessionDir, { recursive: true });
269867
270273
  const checkpoint = {
269868
270274
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
269869
270275
  sessionId: this._sessionId,
@@ -269875,7 +270281,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
269875
270281
  memexEntryCount: this._memexArchive.size,
269876
270282
  fileRegistrySize: this._fileRegistry.size
269877
270283
  };
269878
- writeFileSync43(join100(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
270284
+ writeFileSync44(join100(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
269879
270285
  } catch {
269880
270286
  }
269881
270287
  }
@@ -271296,12 +271702,12 @@ ${result}`
271296
271702
  let resizedBase64 = null;
271297
271703
  try {
271298
271704
  const { execSync: execSync56 } = await import("node:child_process");
271299
- const { writeFileSync: writeFileSync43, readFileSync: readFileSync62, unlinkSync: unlinkSync19 } = await import("node:fs");
271705
+ const { writeFileSync: writeFileSync44, readFileSync: readFileSync62, unlinkSync: unlinkSync19 } = await import("node:fs");
271300
271706
  const { join: join100 } = await import("node:path");
271301
271707
  const { tmpdir: tmpdir21 } = await import("node:os");
271302
271708
  const tmpIn = join100(tmpdir21(), `oa_img_in_${Date.now()}.png`);
271303
271709
  const tmpOut = join100(tmpdir21(), `oa_img_out_${Date.now()}.jpg`);
271304
- writeFileSync43(tmpIn, buffer2);
271710
+ writeFileSync44(tmpIn, buffer2);
271305
271711
  const pyBin = process.platform === "win32" ? "python" : "python3";
271306
271712
  const escapedIn = tmpIn.replace(/\\/g, "\\\\");
271307
271713
  const escapedOut = tmpOut.replace(/\\/g, "\\\\");
@@ -271949,7 +272355,7 @@ var init_constraint_learner = __esm({
271949
272355
  });
271950
272356
 
271951
272357
  // 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";
272358
+ import { existsSync as existsSync49, statSync as statSync14, openSync, readSync, closeSync, unlinkSync as unlinkSync10, writeFileSync as writeFileSync22 } from "node:fs";
271953
272359
  import { watch as fsWatch } from "node:fs";
271954
272360
  import { join as join65 } from "node:path";
271955
272361
  import { tmpdir as tmpdir17 } from "node:os";
@@ -272102,7 +272508,7 @@ var init_nexusBackend = __esm({
272102
272508
  */
272103
272509
  async *chatCompletionStream(request) {
272104
272510
  const streamFile = join65(tmpdir17(), `nexus-stream-${randomBytes14(6).toString("hex")}.jsonl`);
272105
- writeFileSync21(streamFile, "", "utf8");
272511
+ writeFileSync22(streamFile, "", "utf8");
272106
272512
  const daemonArgs = {
272107
272513
  model: this.model,
272108
272514
  messages: JSON.stringify(request.messages),
@@ -273748,8 +274154,8 @@ __export(listen_exports, {
273748
274154
  waitForTranscribeCli: () => waitForTranscribeCli
273749
274155
  });
273750
274156
  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";
274157
+ import { existsSync as existsSync50, mkdirSync as mkdirSync26, writeFileSync as writeFileSync23, readdirSync as readdirSync10 } from "node:fs";
274158
+ import { join as join66, dirname as dirname17 } from "node:path";
273753
274159
  import { homedir as homedir20 } from "node:os";
273754
274160
  import { fileURLToPath as fileURLToPath9 } from "node:url";
273755
274161
  import { EventEmitter as EventEmitter3 } from "node:events";
@@ -273833,7 +274239,7 @@ function findMicCaptureCommand() {
273833
274239
  return null;
273834
274240
  }
273835
274241
  function findLiveWhisperScript() {
273836
- const thisDir = dirname16(fileURLToPath9(import.meta.url));
274242
+ const thisDir = dirname17(fileURLToPath9(import.meta.url));
273837
274243
  const candidates = [
273838
274244
  join66(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
273839
274245
  join66(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
@@ -274392,9 +274798,9 @@ transcribe-cli error: ${transcribeCliError}` : "";
274392
274798
  if (outputDir) {
274393
274799
  const { basename: basename19 } = await import("node:path");
274394
274800
  const transcriptDir = join66(outputDir, ".oa", "transcripts");
274395
- mkdirSync25(transcriptDir, { recursive: true });
274801
+ mkdirSync26(transcriptDir, { recursive: true });
274396
274802
  const outFile = join66(transcriptDir, `${basename19(filePath)}.txt`);
274397
- writeFileSync22(outFile, result.text, "utf-8");
274803
+ writeFileSync23(outFile, result.text, "utf-8");
274398
274804
  }
274399
274805
  return {
274400
274806
  text: result.text,
@@ -280420,7 +280826,7 @@ import { EventEmitter as EventEmitter5 } from "node:events";
280420
280826
  import { randomBytes as randomBytes15 } from "node:crypto";
280421
280827
  import { URL as URL2 } from "node:url";
280422
280828
  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";
280829
+ 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
280830
  import { join as join67 } from "node:path";
280425
280831
  function cleanForwardHeaders(raw, targetHost) {
280426
280832
  const out = {};
@@ -280454,8 +280860,8 @@ function readExposeState(stateDir) {
280454
280860
  }
280455
280861
  function writeExposeState(stateDir, state) {
280456
280862
  try {
280457
- mkdirSync26(stateDir, { recursive: true });
280458
- writeFileSync23(join67(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
280863
+ mkdirSync27(stateDir, { recursive: true });
280864
+ writeFileSync24(join67(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
280459
280865
  } catch {
280460
280866
  }
280461
280867
  }
@@ -280570,8 +280976,8 @@ function readP2PExposeState(stateDir) {
280570
280976
  }
280571
280977
  function writeP2PExposeState(stateDir, state) {
280572
280978
  try {
280573
- mkdirSync26(stateDir, { recursive: true });
280574
- writeFileSync23(join67(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
280979
+ mkdirSync27(stateDir, { recursive: true });
280980
+ writeFileSync24(join67(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
280575
280981
  } catch {
280576
280982
  }
280577
280983
  }
@@ -281973,8 +282379,8 @@ var init_types = __esm({
281973
282379
 
281974
282380
  // packages/cli/src/tui/p2p/secret-vault.ts
281975
282381
  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";
282382
+ import { readFileSync as readFileSync38, writeFileSync as writeFileSync25, existsSync as existsSync52, mkdirSync as mkdirSync28 } from "node:fs";
282383
+ import { dirname as dirname18 } from "node:path";
281978
282384
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
281979
282385
  var init_secret_vault = __esm({
281980
282386
  "packages/cli/src/tui/p2p/secret-vault.ts"() {
@@ -282180,9 +282586,9 @@ var init_secret_vault = __esm({
282180
282586
  const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
282181
282587
  const tag = cipher.getAuthTag();
282182
282588
  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 });
282589
+ const dir = dirname18(this.storePath);
282590
+ if (!existsSync52(dir)) mkdirSync28(dir, { recursive: true });
282591
+ writeFileSync25(this.storePath, blob, { mode: 384 });
282186
282592
  }
282187
282593
  /**
282188
282594
  * Load vault from disk, decrypting with the given passphrase.
@@ -283749,7 +284155,7 @@ var init_render2 = __esm({
283749
284155
 
283750
284156
  // packages/prompts/dist/promptLoader.js
283751
284157
  import { readFileSync as readFileSync39, existsSync as existsSync53 } from "node:fs";
283752
- import { join as join69, dirname as dirname18 } from "node:path";
284158
+ import { join as join69, dirname as dirname19 } from "node:path";
283753
284159
  import { fileURLToPath as fileURLToPath10 } from "node:url";
283754
284160
  function loadPrompt2(promptPath, vars) {
283755
284161
  let content = cache5.get(promptPath);
@@ -283770,7 +284176,7 @@ var init_promptLoader2 = __esm({
283770
284176
  "packages/prompts/dist/promptLoader.js"() {
283771
284177
  "use strict";
283772
284178
  __filename4 = fileURLToPath10(import.meta.url);
283773
- __dirname6 = dirname18(__filename4);
284179
+ __dirname6 = dirname19(__filename4);
283774
284180
  devPath = join69(__dirname6, "..", "templates");
283775
284181
  publishedPath = join69(__dirname6, "..", "prompts", "templates");
283776
284182
  PROMPTS_DIR2 = existsSync53(devPath) ? devPath : publishedPath;
@@ -283884,7 +284290,7 @@ var init_task_templates = __esm({
283884
284290
  });
283885
284291
 
283886
284292
  // packages/prompts/dist/index.js
283887
- import { join as join70, dirname as dirname19 } from "node:path";
284293
+ import { join as join70, dirname as dirname20 } from "node:path";
283888
284294
  import { fileURLToPath as fileURLToPath11 } from "node:url";
283889
284295
  var _dir, _packageRoot;
283890
284296
  var init_dist9 = __esm({
@@ -283894,7 +284300,7 @@ var init_dist9 = __esm({
283894
284300
  init_render2();
283895
284301
  init_task_templates();
283896
284302
  init_render2();
283897
- _dir = dirname19(fileURLToPath11(import.meta.url));
284303
+ _dir = dirname20(fileURLToPath11(import.meta.url));
283898
284304
  _packageRoot = join70(_dir, "..");
283899
284305
  }
283900
284306
  });
@@ -283932,13 +284338,13 @@ __export(oa_directory_exports, {
283932
284338
  writeIndexData: () => writeIndexData,
283933
284339
  writeIndexMeta: () => writeIndexMeta
283934
284340
  });
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";
284341
+ 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
284342
  import { join as join71, relative as relative4, basename as basename12 } from "node:path";
283937
284343
  import { homedir as homedir21 } from "node:os";
283938
284344
  function initOaDirectory(repoRoot) {
283939
284345
  const oaPath = join71(repoRoot, OA_DIR);
283940
284346
  for (const sub of SUBDIRS) {
283941
- mkdirSync28(join71(oaPath, sub), { recursive: true });
284347
+ mkdirSync29(join71(oaPath, sub), { recursive: true });
283942
284348
  }
283943
284349
  try {
283944
284350
  const gitignorePath = join71(repoRoot, ".gitignore");
@@ -283946,7 +284352,7 @@ function initOaDirectory(repoRoot) {
283946
284352
  if (existsSync54(gitignorePath)) {
283947
284353
  const content = readFileSync40(gitignorePath, "utf-8");
283948
284354
  if (!content.includes(settingsPattern)) {
283949
- writeFileSync25(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
284355
+ writeFileSync26(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
283950
284356
  }
283951
284357
  }
283952
284358
  } catch {
@@ -283968,10 +284374,10 @@ function loadProjectSettings(repoRoot) {
283968
284374
  }
283969
284375
  function saveProjectSettings(repoRoot, settings) {
283970
284376
  const oaPath = join71(repoRoot, OA_DIR);
283971
- mkdirSync28(oaPath, { recursive: true });
284377
+ mkdirSync29(oaPath, { recursive: true });
283972
284378
  const existing = loadProjectSettings(repoRoot);
283973
284379
  const merged = { ...existing, ...settings };
283974
- writeFileSync25(join71(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284380
+ writeFileSync26(join71(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
283975
284381
  }
283976
284382
  function loadGlobalSettings() {
283977
284383
  const settingsPath = join71(homedir21(), ".open-agents", "settings.json");
@@ -283985,10 +284391,10 @@ function loadGlobalSettings() {
283985
284391
  }
283986
284392
  function saveGlobalSettings(settings) {
283987
284393
  const dir = join71(homedir21(), ".open-agents");
283988
- mkdirSync28(dir, { recursive: true });
284394
+ mkdirSync29(dir, { recursive: true });
283989
284395
  const existing = loadGlobalSettings();
283990
284396
  const merged = { ...existing, ...settings };
283991
- writeFileSync25(join71(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284397
+ writeFileSync26(join71(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
283992
284398
  }
283993
284399
  function resolveSettings(repoRoot) {
283994
284400
  const global2 = loadGlobalSettings();
@@ -284064,8 +284470,8 @@ function readIndexMeta(repoRoot) {
284064
284470
  }
284065
284471
  function writeIndexMeta(repoRoot, meta) {
284066
284472
  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");
284473
+ mkdirSync29(join71(repoRoot, OA_DIR, "index"), { recursive: true });
284474
+ writeFileSync26(metaPath, JSON.stringify(meta, null, 2), "utf-8");
284069
284475
  }
284070
284476
  function readIndexData(repoRoot, filename) {
284071
284477
  const filePath = join71(repoRoot, OA_DIR, "index", filename);
@@ -284077,8 +284483,8 @@ function readIndexData(repoRoot, filename) {
284077
284483
  }
284078
284484
  function writeIndexData(repoRoot, filename, data) {
284079
284485
  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");
284486
+ mkdirSync29(join71(repoRoot, OA_DIR, "index"), { recursive: true });
284487
+ writeFileSync26(filePath, JSON.stringify(data, null, 2), "utf-8");
284082
284488
  }
284083
284489
  function generateProjectMap(repoRoot) {
284084
284490
  const sections = [];
@@ -284126,14 +284532,14 @@ ${tree2}\`\`\`
284126
284532
  }
284127
284533
  const content = sections.join("\n");
284128
284534
  const contextDir = join71(repoRoot, OA_DIR, "context");
284129
- mkdirSync28(contextDir, { recursive: true });
284130
- writeFileSync25(join71(contextDir, "project-map.md"), content, "utf-8");
284535
+ mkdirSync29(contextDir, { recursive: true });
284536
+ writeFileSync26(join71(contextDir, "project-map.md"), content, "utf-8");
284131
284537
  return content;
284132
284538
  }
284133
284539
  function saveSession(repoRoot, session) {
284134
284540
  const historyDir = join71(repoRoot, OA_DIR, "history");
284135
- mkdirSync28(historyDir, { recursive: true });
284136
- writeFileSync25(
284541
+ mkdirSync29(historyDir, { recursive: true });
284542
+ writeFileSync26(
284137
284543
  join71(historyDir, `${session.id}.json`),
284138
284544
  JSON.stringify(session, null, 2),
284139
284545
  "utf-8"
@@ -284162,8 +284568,8 @@ function loadRecentSessions(repoRoot, limit = 5) {
284162
284568
  }
284163
284569
  function savePendingTask(repoRoot, task) {
284164
284570
  const historyDir = join71(repoRoot, OA_DIR, "history");
284165
- mkdirSync28(historyDir, { recursive: true });
284166
- writeFileSync25(
284571
+ mkdirSync29(historyDir, { recursive: true });
284572
+ writeFileSync26(
284167
284573
  join71(historyDir, PENDING_TASK_FILE),
284168
284574
  JSON.stringify(task, null, 2) + "\n",
284169
284575
  "utf-8"
@@ -284185,7 +284591,7 @@ function loadPendingTask(repoRoot) {
284185
284591
  }
284186
284592
  function saveSessionContext(repoRoot, entry) {
284187
284593
  const contextDir = join71(repoRoot, OA_DIR, "context");
284188
- mkdirSync28(contextDir, { recursive: true });
284594
+ mkdirSync29(contextDir, { recursive: true });
284189
284595
  const filePath = join71(contextDir, CONTEXT_SAVE_FILE);
284190
284596
  let ctx3;
284191
284597
  try {
@@ -284202,7 +284608,7 @@ function saveSessionContext(repoRoot, entry) {
284202
284608
  ctx3.entries = ctx3.entries.slice(-ctx3.maxEntries);
284203
284609
  }
284204
284610
  ctx3.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
284205
- writeFileSync25(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
284611
+ writeFileSync26(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
284206
284612
  try {
284207
284613
  const diaryLines = ["# Session Diary", ""];
284208
284614
  for (const e2 of ctx3.entries.slice(-10)) {
@@ -284216,7 +284622,7 @@ function saveSessionContext(repoRoot, entry) {
284216
284622
  if (e2.summary) diaryLines.push(`Summary: ${e2.summary.slice(0, 200)}`);
284217
284623
  diaryLines.push("");
284218
284624
  }
284219
- writeFileSync25(join71(contextDir, "session-diary.md"), diaryLines.join("\n"), "utf-8");
284625
+ writeFileSync26(join71(contextDir, "session-diary.md"), diaryLines.join("\n"), "utf-8");
284220
284626
  } catch {
284221
284627
  }
284222
284628
  }
@@ -284252,14 +284658,14 @@ function getLastTaskSummary(repoRoot) {
284252
284658
  }
284253
284659
  function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
284254
284660
  const sessDir = join71(repoRoot, OA_DIR, SESSIONS_DIR);
284255
- mkdirSync28(sessDir, { recursive: true });
284661
+ mkdirSync29(sessDir, { recursive: true });
284256
284662
  const stripped = contentLines.map(
284257
284663
  (line) => typeof line === "string" ? line.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "") : ""
284258
284664
  );
284259
284665
  const autoName = meta.name || generateSessionName(stripped);
284260
284666
  const autoDesc = meta.description || generateSessionDescription(stripped);
284261
284667
  const contentPath = join71(sessDir, `${sessionId}.jsonl`);
284262
- writeFileSync25(contentPath, stripped.join("\n"), "utf-8");
284668
+ writeFileSync26(contentPath, stripped.join("\n"), "utf-8");
284263
284669
  const indexPath = join71(sessDir, SESSIONS_INDEX);
284264
284670
  let index = [];
284265
284671
  try {
@@ -284290,7 +284696,7 @@ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
284290
284696
  } catch {
284291
284697
  }
284292
284698
  }
284293
- writeFileSync25(indexPath, JSON.stringify(index, null, 2), "utf-8");
284699
+ writeFileSync26(indexPath, JSON.stringify(index, null, 2), "utf-8");
284294
284700
  }
284295
284701
  function listSessions(repoRoot) {
284296
284702
  const indexPath = join71(repoRoot, OA_DIR, SESSIONS_DIR, SESSIONS_INDEX);
@@ -284320,7 +284726,7 @@ function deleteSession(repoRoot, sessionId) {
284320
284726
  if (existsSync54(indexPath)) {
284321
284727
  let index = JSON.parse(readFileSync40(indexPath, "utf-8"));
284322
284728
  index = index.filter((s2) => s2.id !== sessionId);
284323
- writeFileSync25(indexPath, JSON.stringify(index, null, 2), "utf-8");
284729
+ writeFileSync26(indexPath, JSON.stringify(index, null, 2), "utf-8");
284324
284730
  }
284325
284731
  return true;
284326
284732
  } catch {
@@ -284454,8 +284860,8 @@ function loadUsageFile(filePath) {
284454
284860
  }
284455
284861
  function saveUsageFile(filePath, data) {
284456
284862
  const dir = join71(filePath, "..");
284457
- mkdirSync28(dir, { recursive: true });
284458
- writeFileSync25(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284863
+ mkdirSync29(dir, { recursive: true });
284864
+ writeFileSync26(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
284459
284865
  }
284460
284866
  function recordUsage(kind, value2, opts) {
284461
284867
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -289073,8 +289479,8 @@ __export(personaplex_exports, {
289073
289479
  startPersonaPlexDaemon: () => startPersonaPlexDaemon,
289074
289480
  stopPersonaPlex: () => stopPersonaPlex
289075
289481
  });
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";
289482
+ 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";
289483
+ import { join as join72, dirname as dirname21 } from "node:path";
289078
289484
  import { homedir as homedir22 } from "node:os";
289079
289485
  import { execSync as execSync47, spawn as spawn21 } from "node:child_process";
289080
289486
  import { fileURLToPath as fileURLToPath12 } from "node:url";
@@ -289211,7 +289617,7 @@ function getWeightTier() {
289211
289617
  if (saved in WEIGHT_REPOS) {
289212
289618
  const vram = detected.vramGB;
289213
289619
  if (saved === "nf4-distilled" && vram < 24) {
289214
- writeFileSync26(tierFile, "nf4");
289620
+ writeFileSync27(tierFile, "nf4");
289215
289621
  return "nf4";
289216
289622
  }
289217
289623
  return saved;
@@ -289225,7 +289631,7 @@ function getWeightRepoInfo(tier) {
289225
289631
  async function installPersonaPlex(onInfo, weightTier) {
289226
289632
  const log22 = onInfo ?? (() => {
289227
289633
  });
289228
- mkdirSync29(PERSONAPLEX_DIR, { recursive: true });
289634
+ mkdirSync30(PERSONAPLEX_DIR, { recursive: true });
289229
289635
  let arch2 = "";
289230
289636
  try {
289231
289637
  arch2 = execSync47("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
@@ -289341,7 +289747,7 @@ async function installPersonaPlex(onInfo, weightTier) {
289341
289747
  let src2 = readFileSync42(serverFile, "utf8");
289342
289748
  if (src2.includes('int(request["seed"])')) {
289343
289749
  src2 = src2.replace('int(request["seed"])', 'int(request.query["seed"])');
289344
- writeFileSync26(serverFile, src2);
289750
+ writeFileSync27(serverFile, src2);
289345
289751
  log22("Applied seed parameter bug fix to moshi server.");
289346
289752
  }
289347
289753
  }
@@ -289445,7 +289851,7 @@ $2if filename.endswith(".safetensors"):`
289445
289851
  ${patchPoint}`
289446
289852
  );
289447
289853
  }
289448
- writeFileSync26(loadersFile, src2);
289854
+ writeFileSync27(loadersFile, src2);
289449
289855
  log22("Patched loaders.py with 2-bit TurboQuant native dequant support.");
289450
289856
  }
289451
289857
  }
@@ -289543,7 +289949,7 @@ $2if filename.endswith(".safetensors"):`
289543
289949
  await execAsync(`"${python}" -c "from huggingface_hub import hf_hub_download; hf_hub_download('${nf4.repo}', '${nf4.file}', token=False)"`, {
289544
289950
  timeout: 6e5
289545
289951
  });
289546
- writeFileSync26(join72(PERSONAPLEX_DIR, "weight_tier"), "nf4");
289952
+ writeFileSync27(join72(PERSONAPLEX_DIR, "weight_tier"), "nf4");
289547
289953
  log22(`Downloaded INT4 weights instead (${nf4.sizeGB}GB, public).`);
289548
289954
  } catch {
289549
289955
  log22("Weight download failed.");
@@ -289555,8 +289961,8 @@ $2if filename.endswith(".safetensors"):`
289555
289961
  log22("Weights will download on first server launch.");
289556
289962
  }
289557
289963
  }
289558
- writeFileSync26(join72(PERSONAPLEX_DIR, "weight_tier"), tier);
289559
- writeFileSync26(join72(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
289964
+ writeFileSync27(join72(PERSONAPLEX_DIR, "weight_tier"), tier);
289965
+ writeFileSync27(join72(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
289560
289966
  log22(`PersonaPlex installed (${tier} tier). Use /call to start voice session.`);
289561
289967
  return true;
289562
289968
  }
@@ -289575,10 +289981,10 @@ async function startPersonaPlexDaemon(onInfo) {
289575
289981
  log22("PersonaPlex not installed. Run /voice personaplex to set up.");
289576
289982
  return null;
289577
289983
  }
289578
- mkdirSync29(PERSONAPLEX_DIR, { recursive: true });
289984
+ mkdirSync30(PERSONAPLEX_DIR, { recursive: true });
289579
289985
  const venvPython2 = process.platform === "win32" ? join72(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join72(PERSONAPLEX_DIR, "venv", "bin", "python3");
289580
289986
  const sslDir = join72(PERSONAPLEX_DIR, "ssl");
289581
- mkdirSync29(sslDir, { recursive: true });
289987
+ mkdirSync30(sslDir, { recursive: true });
289582
289988
  const tier = getWeightTier();
289583
289989
  const repoInfo = WEIGHT_REPOS[tier];
289584
289990
  const extraArgs = [];
@@ -289723,8 +290129,8 @@ print('Converted')
289723
290129
  cwd: PERSONAPLEX_DIR
289724
290130
  });
289725
290131
  if (child.pid) {
289726
- writeFileSync26(PID_FILE, String(child.pid));
289727
- writeFileSync26(PORT_FILE, String(PORT));
290132
+ writeFileSync27(PID_FILE, String(child.pid));
290133
+ writeFileSync27(PORT_FILE, String(PORT));
289728
290134
  registry2.register({
289729
290135
  name: "PersonaPlex",
289730
290136
  pid: child.pid,
@@ -289830,7 +290236,7 @@ async function clonePersonaPlexVoice(inputWav, voiceName, onInfo) {
289830
290236
  log22(`Input WAV not found: ${inputWav}`);
289831
290237
  return null;
289832
290238
  }
289833
- mkdirSync29(CUSTOM_VOICES_DIR, { recursive: true });
290239
+ mkdirSync30(CUSTOM_VOICES_DIR, { recursive: true });
289834
290240
  const outputPt = join72(CUSTOM_VOICES_DIR, `${voiceName}.pt`);
289835
290241
  if (existsSync55(outputPt)) {
289836
290242
  log22(`Voice "${voiceName}" already exists. Delete ${outputPt} to re-clone.`);
@@ -289888,7 +290294,7 @@ function getShippedVoicesDir() {
289888
290294
  // repo root
289889
290295
  ];
289890
290296
  try {
289891
- const modDir = dirname20(fileURLToPath12(import.meta.url));
290297
+ const modDir = dirname21(fileURLToPath12(import.meta.url));
289892
290298
  candidates.push(join72(modDir, "..", "..", "..", "voices", "personaplex"));
289893
290299
  candidates.push(join72(modDir, "..", "..", "..", "..", "voices", "personaplex"));
289894
290300
  } catch {
@@ -289910,7 +290316,7 @@ function provisionShippedVoices(onInfo) {
289910
290316
  const shippedDir = getShippedVoicesDir();
289911
290317
  if (!shippedDir) return 0;
289912
290318
  const hfVoicesDir = getHFVoicesDir();
289913
- mkdirSync29(CUSTOM_VOICES_DIR, { recursive: true });
290319
+ mkdirSync30(CUSTOM_VOICES_DIR, { recursive: true });
289914
290320
  let deployed = 0;
289915
290321
  try {
289916
290322
  for (const f2 of readdirSync13(shippedDir)) {
@@ -289984,7 +290390,7 @@ function patchFrontendVoiceList(onInfo) {
289984
290390
  if (js.includes(needle)) {
289985
290391
  const additions = customVoices.map((v) => `"${v}"`).join(", ");
289986
290392
  js = js.replace(needle, `"VARM4.pt", ${additions}]`);
289987
- writeFileSync26(jsPath, js);
290393
+ writeFileSync27(jsPath, js);
289988
290394
  log22(`Added ${customVoices.length} custom voice(s) to frontend: ${customVoices.map((v) => v.replace(".pt", "")).join(", ")}`);
289989
290395
  }
289990
290396
  }
@@ -290080,7 +290486,7 @@ __export(setup_exports, {
290080
290486
  import * as readline from "node:readline";
290081
290487
  import { execSync as execSync48, spawn as spawn22, exec as exec4 } from "node:child_process";
290082
290488
  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";
290489
+ import { existsSync as existsSync56, writeFileSync as writeFileSync28, readFileSync as readFileSync43, appendFileSync as appendFileSync2, mkdirSync as mkdirSync31 } from "node:fs";
290084
290490
  import { join as join73 } from "node:path";
290085
290491
  import { homedir as homedir23, platform as platform3 } from "node:os";
290086
290492
  async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
@@ -290333,6 +290739,91 @@ function ensureCurl() {
290333
290739
  `);
290334
290740
  return false;
290335
290741
  }
290742
+ function ensureZstd() {
290743
+ if (hasCmd("zstd")) return true;
290744
+ if (process.platform === "darwin") {
290745
+ if (!hasCmd("brew")) return false;
290746
+ try {
290747
+ execSync48("brew install zstd", { stdio: "inherit", timeout: 12e4 });
290748
+ return hasCmd("zstd");
290749
+ } catch {
290750
+ return false;
290751
+ }
290752
+ }
290753
+ if (process.platform !== "linux") return false;
290754
+ let installCmd = "";
290755
+ if (hasCmd("apt-get")) installCmd = "apt-get install -y zstd";
290756
+ else if (hasCmd("dnf")) installCmd = "dnf install -y zstd";
290757
+ else if (hasCmd("yum")) installCmd = "yum install -y zstd";
290758
+ else if (hasCmd("pacman")) installCmd = "pacman -S --noconfirm zstd";
290759
+ else if (hasCmd("zypper")) installCmd = "zypper install -y zstd";
290760
+ else if (hasCmd("apk")) installCmd = "apk add --no-cache zstd";
290761
+ if (!installCmd) {
290762
+ process.stdout.write(`
290763
+ ${c3.yellow("\u26A0")} Could not detect package manager to install zstd.
290764
+ `);
290765
+ return false;
290766
+ }
290767
+ process.stdout.write(`
290768
+ ${c3.cyan("\u25CF")} Installing zstd (required by ollama install.sh)...
290769
+ `);
290770
+ const candidates = [
290771
+ `pkexec sh -c "${installCmd}"`,
290772
+ `sudo ${installCmd}`,
290773
+ installCmd
290774
+ // bare (works if already root)
290775
+ ];
290776
+ for (const cmd of candidates) {
290777
+ try {
290778
+ execSync48(cmd, { stdio: "inherit", timeout: 18e4 });
290779
+ if (hasCmd("zstd")) {
290780
+ process.stdout.write(` ${c3.green("\u2714")} zstd installed.
290781
+ `);
290782
+ return true;
290783
+ }
290784
+ } catch {
290785
+ }
290786
+ }
290787
+ process.stdout.write(` ${c3.red("\u2716")} Failed to install zstd. Please install manually and retry.
290788
+ `);
290789
+ return false;
290790
+ }
290791
+ function runOllamaInstallScript() {
290792
+ const zstdReady = ensureZstd();
290793
+ if (!zstdReady) {
290794
+ process.stdout.write(` ${c3.yellow("\u26A0")} Proceeding without zstd \u2014 install may fail if the script requires it.
290795
+ `);
290796
+ }
290797
+ const cmd = "curl -fsSL https://ollama.com/install.sh | sh";
290798
+ const runOnce = () => {
290799
+ execSync48(cmd, {
290800
+ stdio: ["inherit", "inherit", "pipe"],
290801
+ timeout: 3e5
290802
+ });
290803
+ };
290804
+ try {
290805
+ runOnce();
290806
+ } catch (err) {
290807
+ const stderrBuf = err?.stderr;
290808
+ const stderr = typeof stderrBuf === "string" ? stderrBuf : stderrBuf?.toString?.() ?? "";
290809
+ const message2 = err instanceof Error ? err.message : String(err);
290810
+ if (stderr) process.stderr.write(stderr);
290811
+ const combined = stderr + "\n" + message2;
290812
+ if (combined.includes("requires zstd") || combined.includes("install zstd")) {
290813
+ process.stdout.write(`
290814
+ ${c3.yellow("\u26A0")} Ollama install script requires zstd. Attempting to install it...
290815
+ `);
290816
+ if (ensureZstd()) {
290817
+ runOnce();
290818
+ return;
290819
+ }
290820
+ throw new Error(
290821
+ "Ollama install failed: zstd is required but could not be installed automatically. Please install zstd manually and retry."
290822
+ );
290823
+ }
290824
+ throw err;
290825
+ }
290826
+ }
290336
290827
  async function autoInstallOllama(rl) {
290337
290828
  const plat = platform3();
290338
290829
  if (plat !== "win32" && !ensureCurl()) {
@@ -290358,10 +290849,7 @@ function installOllamaLinux() {
290358
290849
 
290359
290850
  `);
290360
290851
  try {
290361
- execSync48("curl -fsSL https://ollama.com/install.sh | sh", {
290362
- stdio: "inherit",
290363
- timeout: 3e5
290364
- });
290852
+ runOllamaInstallScript();
290365
290853
  if (hasCmd("ollama")) {
290366
290854
  process.stdout.write(`
290367
290855
  ${c3.green("\u2714")} Ollama installed successfully.
@@ -290575,12 +291063,12 @@ function updateOllama() {
290575
291063
  return false;
290576
291064
  }
290577
291065
  try {
290578
- execSync48("curl -fsSL https://ollama.com/install.sh | sh", {
290579
- stdio: "inherit",
290580
- timeout: 3e5
290581
- });
291066
+ runOllamaInstallScript();
290582
291067
  return true;
290583
- } catch {
291068
+ } catch (err) {
291069
+ process.stdout.write(`
291070
+ ${c3.red("\u2716")} Ollama update failed: ${err instanceof Error ? err.message : String(err)}
291071
+ `);
290584
291072
  return false;
290585
291073
  }
290586
291074
  }
@@ -290606,11 +291094,7 @@ function pullModelWithAutoUpdate(tag) {
290606
291094
 
290607
291095
  `);
290608
291096
  try {
290609
- execSync48("curl -fsSL https://ollama.com/install.sh | sh", {
290610
- stdio: "inherit",
290611
- timeout: 3e5
290612
- // 5 min max for install
290613
- });
291097
+ runOllamaInstallScript();
290614
291098
  process.stdout.write(`
290615
291099
  ${c3.green("\u2714")} Ollama updated successfully.
290616
291100
  `);
@@ -291182,9 +291666,9 @@ async function doSetup(config, rl) {
291182
291666
  `PARAMETER stop "<|endoftext|>"`
291183
291667
  ].join("\n");
291184
291668
  const modelDir2 = join73(homedir23(), ".open-agents", "models");
291185
- mkdirSync30(modelDir2, { recursive: true });
291669
+ mkdirSync31(modelDir2, { recursive: true });
291186
291670
  const modelfilePath = join73(modelDir2, `Modelfile.${customName}`);
291187
- writeFileSync27(modelfilePath, modelfileContent + "\n", "utf8");
291671
+ writeFileSync28(modelfilePath, modelfileContent + "\n", "utf8");
291188
291672
  process.stdout.write(` ${c3.dim("Creating model...")} `);
291189
291673
  execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
291190
291674
  stdio: "pipe",
@@ -291324,7 +291808,7 @@ function ensureVenv(log22) {
291324
291808
  return null;
291325
291809
  }
291326
291810
  try {
291327
- mkdirSync30(join73(homedir23(), ".open-agents"), { recursive: true });
291811
+ mkdirSync31(join73(homedir23(), ".open-agents"), { recursive: true });
291328
291812
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
291329
291813
  execSync48(`${pyCmd} -m venv --clear "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
291330
291814
  try {
@@ -291551,8 +292035,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
291551
292035
  }
291552
292036
  }
291553
292037
  try {
291554
- mkdirSync30(_visionMarkerDir, { recursive: true });
291555
- writeFileSync27(_visionMarkerFile, JSON.stringify({
292038
+ mkdirSync31(_visionMarkerDir, { recursive: true });
292039
+ writeFileSync28(_visionMarkerFile, JSON.stringify({
291556
292040
  installed: [..._visionPreviouslyInstalled],
291557
292041
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
291558
292042
  }, null, 2));
@@ -291788,9 +292272,9 @@ function createExpandedVariant(baseModel, specs, sizeGB, kvBytesPerToken, archMa
291788
292272
  `PARAMETER stop "<|endoftext|>"`
291789
292273
  ].join("\n");
291790
292274
  const modelDir2 = join73(homedir23(), ".open-agents", "models");
291791
- mkdirSync30(modelDir2, { recursive: true });
292275
+ mkdirSync31(modelDir2, { recursive: true });
291792
292276
  const modelfilePath = join73(modelDir2, `Modelfile.${customName}`);
291793
- writeFileSync27(modelfilePath, modelfileContent + "\n", "utf8");
292277
+ writeFileSync28(modelfilePath, modelfileContent + "\n", "utf8");
291794
292278
  execSync48(`ollama create ${customName} -f ${modelfilePath}`, {
291795
292279
  stdio: "pipe",
291796
292280
  timeout: 12e4
@@ -291813,9 +292297,9 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
291813
292297
  `PARAMETER stop "<|endoftext|>"`
291814
292298
  ].join("\n");
291815
292299
  const modelDir2 = join73(homedir23(), ".open-agents", "models");
291816
- mkdirSync30(modelDir2, { recursive: true });
292300
+ mkdirSync31(modelDir2, { recursive: true });
291817
292301
  const modelfilePath = join73(modelDir2, `Modelfile.${customName}`);
291818
- writeFileSync27(modelfilePath, modelfileContent + "\n", "utf8");
292302
+ writeFileSync28(modelfilePath, modelfileContent + "\n", "utf8");
291819
292303
  await execAsync2(`ollama create ${customName} -f ${modelfilePath}`, {
291820
292304
  timeout: 12e4
291821
292305
  });
@@ -291891,7 +292375,7 @@ async function ensureNeovim() {
291891
292375
  const binDir = join73(homedir23(), ".local", "bin");
291892
292376
  const nvimDest = join73(binDir, "nvim");
291893
292377
  try {
291894
- mkdirSync30(binDir, { recursive: true });
292378
+ mkdirSync31(binDir, { recursive: true });
291895
292379
  } catch {
291896
292380
  }
291897
292381
  const appImageName = arch2 === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
@@ -292701,11 +293185,11 @@ __export(daemon_exports, {
292701
293185
  stopDaemon: () => stopDaemon
292702
293186
  });
292703
293187
  import { spawn as spawn23 } from "node:child_process";
292704
- import { existsSync as existsSync59, readFileSync as readFileSync44, writeFileSync as writeFileSync28, mkdirSync as mkdirSync31, unlinkSync as unlinkSync14 } from "node:fs";
293188
+ import { existsSync as existsSync59, readFileSync as readFileSync44, writeFileSync as writeFileSync29, mkdirSync as mkdirSync32, unlinkSync as unlinkSync14 } from "node:fs";
292705
293189
  import { join as join75 } from "node:path";
292706
293190
  import { homedir as homedir24 } from "node:os";
292707
293191
  import { fileURLToPath as fileURLToPath13 } from "node:url";
292708
- import { dirname as dirname21 } from "node:path";
293192
+ import { dirname as dirname22 } from "node:path";
292709
293193
  function getDaemonPort() {
292710
293194
  const env2 = process.env["OA_HOST"];
292711
293195
  if (env2) {
@@ -292742,7 +293226,7 @@ function getDaemonPid() {
292742
293226
  }
292743
293227
  }
292744
293228
  async function startDaemon() {
292745
- mkdirSync31(OA_DIR2, { recursive: true });
293229
+ mkdirSync32(OA_DIR2, { recursive: true });
292746
293230
  const nodeExe = process.execPath;
292747
293231
  let oaScript = process.argv[1];
292748
293232
  if (!oaScript) {
@@ -292754,7 +293238,7 @@ async function startDaemon() {
292754
293238
  }
292755
293239
  }
292756
293240
  if (!oaScript) {
292757
- const thisDir = dirname21(fileURLToPath13(import.meta.url));
293241
+ const thisDir = dirname22(fileURLToPath13(import.meta.url));
292758
293242
  const indexJs = join75(thisDir, "index.js");
292759
293243
  if (existsSync59(indexJs)) oaScript = indexJs;
292760
293244
  }
@@ -292772,7 +293256,7 @@ async function startDaemon() {
292772
293256
  child.unref();
292773
293257
  const pid = child.pid ?? null;
292774
293258
  if (pid) {
292775
- writeFileSync28(PID_FILE2, String(pid), "utf8");
293259
+ writeFileSync29(PID_FILE2, String(pid), "utf8");
292776
293260
  }
292777
293261
  return pid;
292778
293262
  } catch {
@@ -293240,7 +293724,7 @@ __export(sponsor_wizard_exports, {
293240
293724
  saveSponsorConfig: () => saveSponsorConfig,
293241
293725
  showSponsorDashboard: () => showSponsorDashboard
293242
293726
  });
293243
- import { existsSync as existsSync60, readFileSync as readFileSync45, writeFileSync as writeFileSync29, mkdirSync as mkdirSync32 } from "node:fs";
293727
+ import { existsSync as existsSync60, readFileSync as readFileSync45, writeFileSync as writeFileSync30, mkdirSync as mkdirSync33 } from "node:fs";
293244
293728
  import { join as join76 } from "node:path";
293245
293729
  function colorPreview(code8) {
293246
293730
  return `\x1B[38;5;${code8}m\u2588\u2588\u2588\u2588\x1B[0m (${code8})`;
@@ -293270,9 +293754,9 @@ function loadSponsorConfig(projectDir) {
293270
293754
  }
293271
293755
  function saveSponsorConfig(projectDir, config) {
293272
293756
  const dir = sponsorDir(projectDir);
293273
- mkdirSync32(dir, { recursive: true });
293757
+ mkdirSync33(dir, { recursive: true });
293274
293758
  config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
293275
- writeFileSync29(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
293759
+ writeFileSync30(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
293276
293760
  }
293277
293761
  function defaultConfig2() {
293278
293762
  return {
@@ -294152,8 +294636,8 @@ __export(voice_exports, {
294152
294636
  registerCustomOnnxModel: () => registerCustomOnnxModel,
294153
294637
  resetNarrationContext: () => resetNarrationContext
294154
294638
  });
294155
- 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";
294156
- import { join as join77, dirname as dirname22 } from "node:path";
294639
+ 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";
294640
+ import { join as join77, dirname as dirname23 } from "node:path";
294157
294641
  import { homedir as homedir25, tmpdir as tmpdir19, platform as platform4 } from "node:os";
294158
294642
  import { execSync as execSync50, spawn as nodeSpawn } from "node:child_process";
294159
294643
  import { createRequire as createRequire3 } from "node:module";
@@ -294210,7 +294694,7 @@ function luxttsInferScript() {
294210
294694
  function writeDetectTorchScript(targetPath) {
294211
294695
  if (existsSync61(targetPath)) return;
294212
294696
  try {
294213
- mkdirSync33(dirname22(targetPath), { recursive: true });
294697
+ mkdirSync34(dirname23(targetPath), { recursive: true });
294214
294698
  } catch {
294215
294699
  }
294216
294700
  const script = `#!/usr/bin/env python3
@@ -294283,7 +294767,7 @@ def main():
294283
294767
  if __name__ == "__main__": main()
294284
294768
  `;
294285
294769
  try {
294286
- writeFileSync30(targetPath, script, { mode: 493 });
294770
+ writeFileSync31(targetPath, script, { mode: 493 });
294287
294771
  } catch {
294288
294772
  }
294289
294773
  }
@@ -295118,7 +295602,7 @@ var init_voice = __esm({
295118
295602
  }
295119
295603
  audioPath = p2;
295120
295604
  const refsDir = luxttsCloneRefsDir();
295121
- if (!existsSync61(refsDir)) mkdirSync33(refsDir, { recursive: true });
295605
+ if (!existsSync61(refsDir)) mkdirSync34(refsDir, { recursive: true });
295122
295606
  const ext = audioPath.split(".").pop() || "wav";
295123
295607
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
295124
295608
  const ts = Date.now().toString(36);
@@ -295126,7 +295610,7 @@ var init_voice = __esm({
295126
295610
  const destPath = join77(refsDir, destFilename);
295127
295611
  try {
295128
295612
  const data = readFileSync46(audioPath);
295129
- writeFileSync30(destPath, data);
295613
+ writeFileSync31(destPath, data);
295130
295614
  } catch (err) {
295131
295615
  return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
295132
295616
  }
@@ -295166,7 +295650,7 @@ var init_voice = __esm({
295166
295650
  return `Failed to synthesize reference audio from ${source.label}.`;
295167
295651
  }
295168
295652
  const refsDir = luxttsCloneRefsDir();
295169
- if (!existsSync61(refsDir)) mkdirSync33(refsDir, { recursive: true });
295653
+ if (!existsSync61(refsDir)) mkdirSync34(refsDir, { recursive: true });
295170
295654
  const destPath = join77(refsDir, `${sourceModelId}-ref.wav`);
295171
295655
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
295172
295656
  this.writeWav(audioData, sampleRate, destPath);
@@ -295196,8 +295680,8 @@ var init_voice = __esm({
295196
295680
  }
295197
295681
  saveCloneMeta(meta) {
295198
295682
  const dir = luxttsCloneRefsDir();
295199
- if (!existsSync61(dir)) mkdirSync33(dir, { recursive: true });
295200
- writeFileSync30(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
295683
+ if (!existsSync61(dir)) mkdirSync34(dir, { recursive: true });
295684
+ writeFileSync31(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
295201
295685
  }
295202
295686
  /** Audio file extensions recognized as clone references */
295203
295687
  static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
@@ -295723,7 +296207,7 @@ var init_voice = __esm({
295723
296207
  buffer2.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
295724
296208
  pos += 2;
295725
296209
  }
295726
- writeFileSync30(path5, buffer2);
296210
+ writeFileSync31(path5, buffer2);
295727
296211
  }
295728
296212
  // -------------------------------------------------------------------------
295729
296213
  // Phonemization
@@ -295797,7 +296281,7 @@ var init_voice = __esm({
295797
296281
  return buffer2;
295798
296282
  }
295799
296283
  writeWav(samples, sampleRate, path5) {
295800
- writeFileSync30(path5, this.buildWavBuffer(samples, sampleRate));
296284
+ writeFileSync31(path5, this.buildWavBuffer(samples, sampleRate));
295801
296285
  }
295802
296286
  // -------------------------------------------------------------------------
295803
296287
  // Audio playback (system default speakers)
@@ -296026,7 +296510,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
296026
296510
  samples[i2] = Math.round(samples[i2] * volume);
296027
296511
  }
296028
296512
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
296029
- writeFileSync30(wavPath, scaled);
296513
+ writeFileSync31(wavPath, scaled);
296030
296514
  }
296031
296515
  } catch {
296032
296516
  }
@@ -296507,8 +296991,8 @@ if __name__ == '__main__':
296507
296991
  main()
296508
296992
  `;
296509
296993
  const scriptPath2 = luxttsInferScript();
296510
- mkdirSync33(voiceDir(), { recursive: true });
296511
- writeFileSync30(scriptPath2, script);
296994
+ mkdirSync34(voiceDir(), { recursive: true });
296995
+ writeFileSync31(scriptPath2, script);
296512
296996
  }
296513
296997
  /** Ensure the LuxTTS daemon is running, spawn if needed */
296514
296998
  async ensureLuxttsDaemon() {
@@ -296648,7 +297132,7 @@ if __name__ == '__main__':
296648
297132
  }
296649
297133
  const header = wavData.subarray(0, 44);
296650
297134
  const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
296651
- writeFileSync30(wavPath, scaled);
297135
+ writeFileSync31(wavPath, scaled);
296652
297136
  }
296653
297137
  } catch {
296654
297138
  }
@@ -296755,7 +297239,7 @@ if __name__ == '__main__':
296755
297239
  async ensureRuntime() {
296756
297240
  if (this.ort) return;
296757
297241
  const arch2 = process.arch;
296758
- mkdirSync33(voiceDir(), { recursive: true });
297242
+ mkdirSync34(voiceDir(), { recursive: true });
296759
297243
  const pkgPath = join77(voiceDir(), "package.json");
296760
297244
  const expectedDeps = {
296761
297245
  "onnxruntime-node": "^1.21.0",
@@ -296766,13 +297250,13 @@ if __name__ == '__main__':
296766
297250
  const existing = JSON.parse(readFileSync46(pkgPath, "utf8"));
296767
297251
  if (!existing.dependencies?.["phonemizer"]) {
296768
297252
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
296769
- writeFileSync30(pkgPath, JSON.stringify(existing, null, 2));
297253
+ writeFileSync31(pkgPath, JSON.stringify(existing, null, 2));
296770
297254
  }
296771
297255
  } catch {
296772
297256
  }
296773
297257
  }
296774
297258
  if (!existsSync61(pkgPath)) {
296775
- writeFileSync30(pkgPath, JSON.stringify({
297259
+ writeFileSync31(pkgPath, JSON.stringify({
296776
297260
  name: "open-agents-voice",
296777
297261
  private: true,
296778
297262
  dependencies: expectedDeps
@@ -296851,13 +297335,13 @@ Error: ${err instanceof Error ? err.message : String(err)}`
296851
297335
  const onnxPath = modelOnnxPath(id);
296852
297336
  const configPath2 = modelConfigPath(id);
296853
297337
  if (existsSync61(onnxPath) && existsSync61(configPath2)) return;
296854
- mkdirSync33(dir, { recursive: true });
297338
+ mkdirSync34(dir, { recursive: true });
296855
297339
  if (!existsSync61(configPath2)) {
296856
297340
  renderInfo(`Downloading ${model.label} voice config...`);
296857
297341
  const configResp = await fetch(model.configUrl);
296858
297342
  if (!configResp.ok) throw new Error(`Failed to download config: HTTP ${configResp.status}`);
296859
297343
  const configText = await configResp.text();
296860
- writeFileSync30(configPath2, configText);
297344
+ writeFileSync31(configPath2, configText);
296861
297345
  }
296862
297346
  if (!existsSync61(onnxPath)) {
296863
297347
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
@@ -296881,7 +297365,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
296881
297365
  }
296882
297366
  }
296883
297367
  const fullBuffer = Buffer.concat(chunks);
296884
- writeFileSync30(onnxPath, fullBuffer);
297368
+ writeFileSync31(onnxPath, fullBuffer);
296885
297369
  renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
296886
297370
  }
296887
297371
  }
@@ -296922,7 +297406,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
296922
297406
  // packages/cli/src/tui/commands.ts
296923
297407
  import * as nodeOs from "node:os";
296924
297408
  import { execSync as nodeExecSync } from "node:child_process";
296925
- 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";
297409
+ 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";
296926
297410
  import { join as join78 } from "node:path";
296927
297411
  async function _immediateReregister(newUrl) {
296928
297412
  if (!_lastRegisteredSponsorPayload) return;
@@ -298072,7 +298556,7 @@ async function handleSlashCommand(input, ctx3) {
298072
298556
  try {
298073
298557
  const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
298074
298558
  const dbDir = join78(ctx3.repoRoot, ".oa", "memory");
298075
- mkdirSync34(dbDir, { recursive: true });
298559
+ mkdirSync35(dbDir, { recursive: true });
298076
298560
  const db = initDb2(join78(dbDir, "structured.db"));
298077
298561
  const memStore = new ProceduralMemoryStore2(db);
298078
298562
  if (isAudio) {
@@ -298173,8 +298657,8 @@ async function handleSlashCommand(input, ctx3) {
298173
298657
  nonce: Math.random().toString(36).slice(2, 10)
298174
298658
  };
298175
298659
  const jwtFile = join78(ctx3.repoRoot, ".oa", "fortemi-jwt.json");
298176
- mkdirSync34(join78(ctx3.repoRoot, ".oa"), { recursive: true });
298177
- writeFileSync31(jwtFile, JSON.stringify(jwtPayload, null, 2));
298660
+ mkdirSync35(join78(ctx3.repoRoot, ".oa"), { recursive: true });
298661
+ writeFileSync32(jwtFile, JSON.stringify(jwtPayload, null, 2));
298178
298662
  renderInfo(`Launching fortemi-react from ${fDir}...`);
298179
298663
  try {
298180
298664
  const { spawn: spawn27 } = __require("node:child_process");
@@ -298189,7 +298673,7 @@ async function handleSlashCommand(input, ctx3) {
298189
298673
  renderInfo(`JWT saved to ${jwtFile}`);
298190
298674
  renderInfo("Memory operations will proxy to fortemi when available.");
298191
298675
  const bridgeFile = join78(ctx3.repoRoot, ".oa", "fortemi-bridge.json");
298192
- writeFileSync31(bridgeFile, JSON.stringify({
298676
+ writeFileSync32(bridgeFile, JSON.stringify({
298193
298677
  url: "http://localhost:3000",
298194
298678
  pid: child.pid,
298195
298679
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -298269,6 +298753,10 @@ async function handleSlashCommand(input, ctx3) {
298269
298753
  case "parallel":
298270
298754
  await handleParallel(arg, ctx3);
298271
298755
  return "handled";
298756
+ case "mcp":
298757
+ case "mcps":
298758
+ await handleMcp(arg, ctx3);
298759
+ return "handled";
298272
298760
  case "update":
298273
298761
  case "upgrade":
298274
298762
  await handleUpdate(arg, ctx3);
@@ -299041,7 +299529,7 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
299041
299529
  }
299042
299530
  }
299043
299531
  const _spLogDir = join78(projectDir, ".oa", "sponsor");
299044
- mkdirSync34(_spLogDir, { recursive: true });
299532
+ mkdirSync35(_spLogDir, { recursive: true });
299045
299533
  const _spLogFile = join78(_spLogDir, "sponsor-startup.log");
299046
299534
  const _spLog = (msg) => {
299047
299535
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
@@ -300639,11 +301127,11 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
300639
301127
  continue;
300640
301128
  }
300641
301129
  const { basename: basename19, join: pathJoin } = await import("node:path");
300642
- const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync49, existsSync: exists2 } = await import("node:fs");
301130
+ const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync50, existsSync: exists2 } = await import("node:fs");
300643
301131
  const { homedir: homedir32 } = await import("node:os");
300644
301132
  const modelName = basename19(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
300645
301133
  const destDir = pathJoin(homedir32(), ".open-agents", "voice", "models", modelName);
300646
- if (!exists2(destDir)) mkdirSync49(destDir, { recursive: true });
301134
+ if (!exists2(destDir)) mkdirSync50(destDir, { recursive: true });
300647
301135
  copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
300648
301136
  copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
300649
301137
  const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
@@ -301389,10 +301877,10 @@ async function handleSponsoredEndpoint(ctx3, local) {
301389
301877
  sponsors.push(...verified);
301390
301878
  if (verified.length > 0) {
301391
301879
  try {
301392
- const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync43 } = __require("node:fs");
301393
- mkdirSync49(sponsorDir2, { recursive: true });
301880
+ const { mkdirSync: mkdirSync50, writeFileSync: writeFileSync44 } = __require("node:fs");
301881
+ mkdirSync50(sponsorDir2, { recursive: true });
301394
301882
  const cached = verified.map((s2) => ({ ...s2, lastVerified: Date.now() }));
301395
- writeFileSync43(knownFile, JSON.stringify(cached, null, 2));
301883
+ writeFileSync44(knownFile, JSON.stringify(cached, null, 2));
301396
301884
  } catch {
301397
301885
  }
301398
301886
  }
@@ -301485,11 +301973,11 @@ async function handleSponsoredEndpoint(ctx3, local) {
301485
301973
  }
301486
301974
  const saveKey = selected.url || selected.peerId || selected.name;
301487
301975
  try {
301488
- mkdirSync34(sponsorDir2, { recursive: true });
301976
+ mkdirSync35(sponsorDir2, { recursive: true });
301489
301977
  const existing = existsSync62(knownFile) ? JSON.parse(readFileSync47(knownFile, "utf8")) : [];
301490
301978
  const updated = existing.filter((s2) => (s2.url || s2.peerId || s2.name) !== saveKey);
301491
301979
  updated.push(selected);
301492
- writeFileSync31(knownFile, JSON.stringify(updated, null, 2), "utf8");
301980
+ writeFileSync32(knownFile, JSON.stringify(updated, null, 2), "utf8");
301493
301981
  } catch {
301494
301982
  }
301495
301983
  renderInfo(`Connected to sponsored endpoint: ${selected.name}`);
@@ -301557,11 +302045,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
301557
302045
  const models = await fetchModels(peerUrl, authKey);
301558
302046
  if (models.length > 0) {
301559
302047
  try {
301560
- const { writeFileSync: writeFileSync43, mkdirSync: mkdirSync49 } = await import("node:fs");
301561
- const { join: join100, dirname: dirname28 } = await import("node:path");
302048
+ const { writeFileSync: writeFileSync44, mkdirSync: mkdirSync50 } = await import("node:fs");
302049
+ const { join: join100, dirname: dirname29 } = await import("node:path");
301562
302050
  const cachePath = join100(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
301563
- mkdirSync49(dirname28(cachePath), { recursive: true });
301564
- writeFileSync43(cachePath, JSON.stringify({
302051
+ mkdirSync50(dirname29(cachePath), { recursive: true });
302052
+ writeFileSync44(cachePath, JSON.stringify({
301565
302053
  peerId,
301566
302054
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
301567
302055
  models: models.map((m2) => ({ name: m2.name, size: m2.size, parameterSize: m2.parameterSize }))
@@ -301737,6 +302225,343 @@ Environment="OLLAMA_NUM_PARALLEL=${n2}"
301737
302225
  }
301738
302226
  }
301739
302227
  }
302228
+ async function handleMcp(subcommand, ctx3) {
302229
+ const manager = ctx3.getMcpManager?.();
302230
+ if (!manager) {
302231
+ renderError("MCP manager not initialized");
302232
+ return;
302233
+ }
302234
+ if (subcommand === "status" || subcommand === "ls" || subcommand === "list") {
302235
+ const conns = manager.getConnections();
302236
+ if (conns.length === 0) {
302237
+ renderInfo("No MCP servers configured. Drop a markdown file with an MCP config block, or add to .oa/mcp.json");
302238
+ return;
302239
+ }
302240
+ renderInfo(`MCP servers (${conns.length}):`);
302241
+ for (const conn of conns) {
302242
+ const status = conn.status === "connected" ? c3.green("\u25CF") : c3.red("\u25CF");
302243
+ renderInfo(` ${status} ${conn.name} [${conn.tools.length} tools]`);
302244
+ }
302245
+ return;
302246
+ }
302247
+ if (subcommand === "reload" || subcommand === "refresh") {
302248
+ renderInfo("Reloading MCP servers from config...");
302249
+ await manager.disconnectAll().catch(() => {
302250
+ });
302251
+ const conns = await manager.connectAll();
302252
+ await ctx3.refreshMcpTools?.();
302253
+ const ok2 = conns.filter((c7) => c7.status === "connected").length;
302254
+ renderInfo(`Reloaded: ${ok2}/${conns.length} servers connected`);
302255
+ return;
302256
+ }
302257
+ await showMcpMainMenu(ctx3);
302258
+ }
302259
+ async function showMcpMainMenu(ctx3) {
302260
+ const manager = ctx3.getMcpManager?.();
302261
+ if (!manager) return;
302262
+ const { loadMcpConfig: loadMcpConfig2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
302263
+ const cfg = loadMcpConfig2(ctx3.repoRoot);
302264
+ const conns = manager.getConnections();
302265
+ const allNames = /* @__PURE__ */ new Set([
302266
+ ...Object.keys(cfg.mcpServers),
302267
+ ...conns.map((c7) => c7.name)
302268
+ ]);
302269
+ const items = [];
302270
+ const skipKeys = [];
302271
+ items.push({ key: "hdr_servers", label: selectColors.dim("\u2500\u2500\u2500 MCP Servers \u2500\u2500\u2500"), kind: "header" });
302272
+ skipKeys.push("hdr_servers");
302273
+ if (allNames.size === 0) {
302274
+ items.push({ key: "empty", label: selectColors.dim("(no servers configured)"), kind: "header" });
302275
+ skipKeys.push("empty");
302276
+ } else {
302277
+ for (const name10 of Array.from(allNames).sort()) {
302278
+ const conn = conns.find((c7) => c7.name === name10);
302279
+ const persisted = cfg.mcpServers[name10];
302280
+ const status = conn?.status ?? (persisted ? "disconnected" : "missing");
302281
+ const dot = status === "connected" ? c3.green("\u25CF") : status === "failed" ? c3.red("\u25CF") : c3.yellow("\u25CF");
302282
+ const toolCount = conn?.tools?.length ?? 0;
302283
+ const transport = persisted ? "command" in persisted ? "stdio" : persisted.type ?? "http" : "?";
302284
+ const detail = `${transport} ${toolCount} tools status: ${status}${conn?.error ? " \u2014 " + String(conn.error).slice(0, 40) : ""}`;
302285
+ items.push({
302286
+ key: `srv:${name10}`,
302287
+ label: `${dot} ${name10}`,
302288
+ detail,
302289
+ kind: "server",
302290
+ serverName: name10
302291
+ });
302292
+ }
302293
+ }
302294
+ items.push({ key: "hdr_actions", label: selectColors.dim("\u2500\u2500\u2500 Actions \u2500\u2500\u2500"), kind: "header" });
302295
+ skipKeys.push("hdr_actions");
302296
+ items.push({ key: "act_add", label: c3.cyan("\u2795 Add new server"), detail: "Paste/enter a config", kind: "action" });
302297
+ items.push({ key: "act_reload", label: c3.cyan("\u27F3 Reload all from config"), detail: "Re-read .oa/mcp.json + reconnect", kind: "action" });
302298
+ items.push({ key: "act_open", label: c3.cyan("\u{1F4DD} Open .oa/mcp.json in editor"), detail: "External edit", kind: "action" });
302299
+ const result = await tuiSelect({
302300
+ items,
302301
+ title: "MCP Server Registry",
302302
+ skipKeys
302303
+ });
302304
+ if (!result || !result.confirmed || !result.key) return;
302305
+ if (result.key === "act_add") {
302306
+ await mcpAddServerInteractive(ctx3);
302307
+ return;
302308
+ }
302309
+ if (result.key === "act_reload") {
302310
+ renderInfo("Reloading MCP servers...");
302311
+ await manager.disconnectAll().catch(() => {
302312
+ });
302313
+ const conns2 = await manager.connectAll();
302314
+ await ctx3.refreshMcpTools?.();
302315
+ const ok2 = conns2.filter((c7) => c7.status === "connected").length;
302316
+ renderInfo(`Reloaded: ${ok2}/${conns2.length} servers connected`);
302317
+ await showMcpMainMenu(ctx3);
302318
+ return;
302319
+ }
302320
+ if (result.key === "act_open") {
302321
+ const path5 = __require("node:path").join(ctx3.repoRoot, ".oa", "mcp.json");
302322
+ renderInfo(`Edit externally: ${path5}`);
302323
+ return;
302324
+ }
302325
+ if (result.key.startsWith("srv:")) {
302326
+ const name10 = result.key.slice(4);
302327
+ await showMcpDetailMenu(ctx3, name10);
302328
+ return;
302329
+ }
302330
+ }
302331
+ async function showMcpDetailMenu(ctx3, serverName) {
302332
+ const manager = ctx3.getMcpManager?.();
302333
+ if (!manager) return;
302334
+ const { loadMcpConfig: loadMcpConfig2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
302335
+ const cfg = loadMcpConfig2(ctx3.repoRoot);
302336
+ const persisted = cfg.mcpServers[serverName];
302337
+ const conns = manager.getConnections();
302338
+ const conn = conns.find((c7) => c7.name === serverName);
302339
+ if (!persisted && !conn) {
302340
+ renderWarning(`Server ${serverName} not found`);
302341
+ await showMcpMainMenu(ctx3);
302342
+ return;
302343
+ }
302344
+ const items = [];
302345
+ const skipKeys = [];
302346
+ items.push({ key: "hdr_name", label: c3.bold(`Server: ${serverName}`), kind: "header" });
302347
+ skipKeys.push("hdr_name");
302348
+ const status = conn?.status ?? "disconnected";
302349
+ const dot = status === "connected" ? c3.green("\u25CF") : status === "failed" ? c3.red("\u25CF") : c3.yellow("\u25CF");
302350
+ items.push({ key: "info_status", label: ` ${dot} status: ${status}${conn?.error ? " \u2014 " + String(conn.error).slice(0, 80) : ""}`, kind: "header" });
302351
+ skipKeys.push("info_status");
302352
+ if (persisted) {
302353
+ const transport = "command" in persisted ? "stdio" : persisted.type ?? "http";
302354
+ items.push({ key: "info_transport", label: ` transport: ${transport}`, kind: "header" });
302355
+ skipKeys.push("info_transport");
302356
+ if ("command" in persisted) {
302357
+ const argStr = (persisted.args ?? []).join(" ");
302358
+ items.push({ key: "info_cmd", label: ` command: ${persisted.command}${argStr ? " " + argStr : ""}`.slice(0, 100), kind: "header" });
302359
+ skipKeys.push("info_cmd");
302360
+ } else if ("url" in persisted) {
302361
+ items.push({ key: "info_url", label: ` url: ${persisted.url}`.slice(0, 100), kind: "header" });
302362
+ skipKeys.push("info_url");
302363
+ }
302364
+ }
302365
+ if (conn?.serverInfo) {
302366
+ items.push({ key: "info_srv", label: ` server: ${conn.serverInfo.name} v${conn.serverInfo.version}`, kind: "header" });
302367
+ skipKeys.push("info_srv");
302368
+ }
302369
+ if (conn && conn.tools && conn.tools.length > 0) {
302370
+ items.push({ key: "hdr_tools", label: selectColors.dim(`\u2500\u2500\u2500 Tools (${conn.tools.length}) \u2500\u2500\u2500`), kind: "header" });
302371
+ skipKeys.push("hdr_tools");
302372
+ for (const t2 of conn.tools.slice(0, 30)) {
302373
+ const desc = (t2.description || t2.title || "").slice(0, 70);
302374
+ items.push({
302375
+ key: `tool:${t2.name}`,
302376
+ label: ` ${t2.name}`,
302377
+ detail: desc,
302378
+ kind: "header"
302379
+ });
302380
+ skipKeys.push(`tool:${t2.name}`);
302381
+ }
302382
+ if (conn.tools.length > 30) {
302383
+ items.push({ key: "tools_more", label: selectColors.dim(` ... and ${conn.tools.length - 30} more`), kind: "header" });
302384
+ skipKeys.push("tools_more");
302385
+ }
302386
+ } else if (conn) {
302387
+ items.push({ key: "hdr_notools", label: selectColors.dim("\u2500\u2500\u2500 No tools advertised \u2500\u2500\u2500"), kind: "header" });
302388
+ skipKeys.push("hdr_notools");
302389
+ }
302390
+ items.push({ key: "hdr_actions", label: selectColors.dim("\u2500\u2500\u2500 Actions \u2500\u2500\u2500"), kind: "header" });
302391
+ skipKeys.push("hdr_actions");
302392
+ items.push({ key: "act_edit", label: c3.cyan("\u270E Edit config"), detail: "Modify command/args/env/url/headers", kind: "action" });
302393
+ items.push({ key: "act_reconnect", label: c3.cyan("\u27F3 Reconnect"), detail: "Disconnect + reconnect this server", kind: "action" });
302394
+ items.push({ key: "act_delete", label: c3.red("\u{1F5D1} Delete"), detail: "Remove from config + disconnect", kind: "action" });
302395
+ items.push({ key: "act_back", label: c3.dim("\u2190 Back to server list"), kind: "action" });
302396
+ const result = await tuiSelect({
302397
+ items,
302398
+ title: `MCP: ${serverName}`,
302399
+ skipKeys
302400
+ });
302401
+ if (!result || !result.confirmed || !result.key) {
302402
+ await showMcpMainMenu(ctx3);
302403
+ return;
302404
+ }
302405
+ if (result.key === "act_back") {
302406
+ await showMcpMainMenu(ctx3);
302407
+ return;
302408
+ }
302409
+ if (result.key === "act_edit") {
302410
+ await mcpEditServer(ctx3, serverName, persisted);
302411
+ return;
302412
+ }
302413
+ if (result.key === "act_reconnect") {
302414
+ renderInfo(`Reconnecting ${serverName}...`);
302415
+ try {
302416
+ await manager.disconnect(serverName);
302417
+ if (persisted) {
302418
+ const c22 = await manager.connectOne(serverName, persisted);
302419
+ await ctx3.refreshMcpTools?.();
302420
+ if (c22.status === "connected") {
302421
+ renderInfo(`\u2714 ${serverName} reconnected (${c22.tools.length} tools)`);
302422
+ } else {
302423
+ renderError(`\u2718 ${serverName} failed: ${c22.error}`);
302424
+ }
302425
+ }
302426
+ } catch (e2) {
302427
+ renderError(`Reconnect failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302428
+ }
302429
+ await showMcpDetailMenu(ctx3, serverName);
302430
+ return;
302431
+ }
302432
+ if (result.key === "act_delete") {
302433
+ renderInfo(`Deleting ${serverName}...`);
302434
+ try {
302435
+ await manager.removeServer(serverName);
302436
+ await ctx3.refreshMcpTools?.();
302437
+ renderInfo(`\u2714 ${serverName} removed from config`);
302438
+ } catch (e2) {
302439
+ renderError(`Delete failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302440
+ }
302441
+ await showMcpMainMenu(ctx3);
302442
+ return;
302443
+ }
302444
+ }
302445
+ async function mcpEditServer(ctx3, serverName, current) {
302446
+ const manager = ctx3.getMcpManager?.();
302447
+ if (!manager) return;
302448
+ const ask2 = (prompt) => new Promise((res) => {
302449
+ process.stdout.write(prompt);
302450
+ let buf = "";
302451
+ const onData = (d2) => {
302452
+ const s2 = d2.toString();
302453
+ if (s2.includes("\n")) {
302454
+ process.stdin.removeListener("data", onData);
302455
+ process.stdin.pause();
302456
+ res((buf + s2).split("\n")[0]);
302457
+ } else {
302458
+ buf += s2;
302459
+ }
302460
+ };
302461
+ process.stdin.resume();
302462
+ process.stdin.on("data", onData);
302463
+ });
302464
+ process.stdout.write(`
302465
+ ${c3.cyan("Current config for ")}${c3.bold(serverName)}:
302466
+ `);
302467
+ process.stdout.write(` ${c3.dim(JSON.stringify(current ?? {}, null, 2).split("\n").join("\n "))}
302468
+
302469
+ `);
302470
+ process.stdout.write(` ${c3.cyan("Paste a new JSON config (single line) or press Enter to keep current.")}
302471
+ `);
302472
+ const newConfigJson = await ask2(" > ");
302473
+ if (!newConfigJson || newConfigJson.trim().length === 0) {
302474
+ renderInfo("No change.");
302475
+ await showMcpDetailMenu(ctx3, serverName);
302476
+ return;
302477
+ }
302478
+ let parsed;
302479
+ try {
302480
+ parsed = JSON.parse(newConfigJson);
302481
+ } catch (e2) {
302482
+ renderError(`Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}`);
302483
+ await showMcpDetailMenu(ctx3, serverName);
302484
+ return;
302485
+ }
302486
+ if (!parsed || typeof parsed.command !== "string" && typeof parsed.url !== "string") {
302487
+ renderError("Config must have either 'command' (stdio) or 'url' (http)");
302488
+ await showMcpDetailMenu(ctx3, serverName);
302489
+ return;
302490
+ }
302491
+ try {
302492
+ await manager.disconnect(serverName);
302493
+ const c22 = await manager.addServer(serverName, parsed);
302494
+ await ctx3.refreshMcpTools?.();
302495
+ if (c22.status === "connected") {
302496
+ renderInfo(`\u2714 ${serverName} updated and reconnected (${c22.tools.length} tools)`);
302497
+ } else {
302498
+ renderWarning(`\u26A0 ${serverName} saved but not connected: ${c22.error}`);
302499
+ }
302500
+ } catch (e2) {
302501
+ renderError(`Save failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302502
+ }
302503
+ await showMcpMainMenu(ctx3);
302504
+ }
302505
+ async function mcpAddServerInteractive(ctx3) {
302506
+ const ask2 = (prompt) => new Promise((res) => {
302507
+ process.stdout.write(prompt);
302508
+ let buf = "";
302509
+ const onData = (d2) => {
302510
+ const s2 = d2.toString();
302511
+ if (s2.includes("\n")) {
302512
+ process.stdin.removeListener("data", onData);
302513
+ process.stdin.pause();
302514
+ res((buf + s2).split("\n")[0]);
302515
+ } else {
302516
+ buf += s2;
302517
+ }
302518
+ };
302519
+ process.stdin.resume();
302520
+ process.stdin.on("data", onData);
302521
+ });
302522
+ process.stdout.write(`
302523
+ ${c3.cyan("Add MCP server")}
302524
+ `);
302525
+ process.stdout.write(` ${c3.dim("Tip: drag-drop a markdown file with an MCP config block onto the terminal for auto-intake.")}
302526
+
302527
+ `);
302528
+ const name10 = await ask2(` ${c3.cyan("Server name:")} `);
302529
+ if (!name10 || name10.trim().length === 0) {
302530
+ renderInfo("Cancelled.");
302531
+ return;
302532
+ }
302533
+ process.stdout.write(` ${c3.cyan('Config JSON (one line, e.g. {"command":"npx","args":["-y","@modelcontextprotocol/server-memory"]}):')}
302534
+ `);
302535
+ const cfgStr = await ask2(" > ");
302536
+ let parsed;
302537
+ try {
302538
+ parsed = JSON.parse(cfgStr);
302539
+ } catch (e2) {
302540
+ renderError(`Invalid JSON: ${e2 instanceof Error ? e2.message : String(e2)}`);
302541
+ return;
302542
+ }
302543
+ if (!parsed || typeof parsed.command !== "string" && typeof parsed.url !== "string") {
302544
+ renderError("Config must have either 'command' (stdio) or 'url' (http)");
302545
+ return;
302546
+ }
302547
+ const manager = ctx3.getMcpManager?.();
302548
+ if (!manager) {
302549
+ renderError("MCP manager not available");
302550
+ return;
302551
+ }
302552
+ try {
302553
+ const c22 = await manager.addServer(name10.trim(), parsed);
302554
+ await ctx3.refreshMcpTools?.();
302555
+ if (c22.status === "connected") {
302556
+ renderInfo(`\u2714 ${name10.trim()} added and connected (${c22.tools.length} tools)`);
302557
+ } else {
302558
+ renderWarning(`\u26A0 ${name10.trim()} saved but not connected: ${c22.error}`);
302559
+ }
302560
+ } catch (e2) {
302561
+ renderError(`Add failed: ${e2 instanceof Error ? e2.message : String(e2)}`);
302562
+ }
302563
+ await showMcpMainMenu(ctx3);
302564
+ }
301740
302565
  async function handleUpdate(subcommand, ctx3) {
301741
302566
  const repoRoot = ctx3.repoRoot;
301742
302567
  if (subcommand === "auto") {
@@ -301753,14 +302578,46 @@ async function handleUpdate(subcommand, ctx3) {
301753
302578
  renderInfo("Update mode: manual \u2014 updates only install when you run /update.");
301754
302579
  return;
301755
302580
  }
302581
+ if (subcommand === "ollama") {
302582
+ const { checkOllamaUpdate: checkOU, updateOllama: doUpdateOllama } = await Promise.resolve().then(() => (init_setup(), setup_exports));
302583
+ let ollamaInfo = null;
302584
+ try {
302585
+ ollamaInfo = await checkOU();
302586
+ } catch {
302587
+ }
302588
+ if (ollamaInfo && !ollamaInfo.needsUpdate) {
302589
+ renderInfo(`Ollama is up to date (${ollamaInfo.current}).`);
302590
+ return;
302591
+ }
302592
+ if (ollamaInfo) {
302593
+ renderInfo(`Updating Ollama: ${ollamaInfo.current} \u2192 ${ollamaInfo.latest}...`);
302594
+ } else {
302595
+ renderInfo("Updating Ollama to the latest version...");
302596
+ }
302597
+ try {
302598
+ if (doUpdateOllama()) {
302599
+ renderInfo("Ollama updated successfully.");
302600
+ try {
302601
+ const { execSync: es } = await import("node:child_process");
302602
+ es("sudo systemctl restart ollama 2>/dev/null || true", { timeout: 1e4, stdio: "pipe" });
302603
+ } catch {
302604
+ }
302605
+ } else {
302606
+ renderError("Ollama update failed. Try manually: curl -fsSL https://ollama.com/install.sh | sh");
302607
+ }
302608
+ } catch (e2) {
302609
+ renderError(`Ollama update error: ${e2 instanceof Error ? e2.message : String(e2)}`);
302610
+ }
302611
+ return;
302612
+ }
301756
302613
  let currentVersion = "0.0.0";
301757
302614
  try {
301758
302615
  const { createRequire: createRequire7 } = await import("node:module");
301759
302616
  const { fileURLToPath: fileURLToPath19 } = await import("node:url");
301760
- const { dirname: dirname28, join: join100 } = await import("node:path");
302617
+ const { dirname: dirname29, join: join100 } = await import("node:path");
301761
302618
  const { existsSync: existsSync80 } = await import("node:fs");
301762
302619
  const req2 = createRequire7(import.meta.url);
301763
- const thisDir = dirname28(fileURLToPath19(import.meta.url));
302620
+ const thisDir = dirname29(fileURLToPath19(import.meta.url));
301764
302621
  const candidates = [
301765
302622
  join100(thisDir, "..", "package.json"),
301766
302623
  join100(thisDir, "..", "..", "package.json"),
@@ -303457,7 +304314,7 @@ __export(banner_exports, {
303457
304314
  saveBannerDesign: () => saveBannerDesign,
303458
304315
  setGridText: () => setGridText
303459
304316
  });
303460
- import { existsSync as existsSync64, readFileSync as readFileSync49, writeFileSync as writeFileSync32, mkdirSync as mkdirSync35 } from "node:fs";
304317
+ import { existsSync as existsSync64, readFileSync as readFileSync49, writeFileSync as writeFileSync33, mkdirSync as mkdirSync36 } from "node:fs";
303461
304318
  import { join as join80 } from "node:path";
303462
304319
  function generateMnemonic(seed) {
303463
304320
  let h = 2166136261;
@@ -303589,8 +304446,8 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
303589
304446
  }
303590
304447
  function saveBannerDesign(workDir, design) {
303591
304448
  const dir = join80(workDir, ".oa", "banners");
303592
- mkdirSync35(dir, { recursive: true });
303593
- writeFileSync32(join80(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
304449
+ mkdirSync36(dir, { recursive: true });
304450
+ writeFileSync33(join80(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
303594
304451
  }
303595
304452
  function loadBannerDesign(workDir, id) {
303596
304453
  const file = join80(workDir, ".oa", "banners", `${id}.json`);
@@ -303910,7 +304767,7 @@ var init_banner = __esm({
303910
304767
  });
303911
304768
 
303912
304769
  // packages/cli/src/tui/carousel-descriptors.ts
303913
- import { existsSync as existsSync65, readFileSync as readFileSync50, writeFileSync as writeFileSync33, mkdirSync as mkdirSync36, readdirSync as readdirSync17 } from "node:fs";
304770
+ import { existsSync as existsSync65, readFileSync as readFileSync50, writeFileSync as writeFileSync34, mkdirSync as mkdirSync37, readdirSync as readdirSync17 } from "node:fs";
303914
304771
  import { join as join81, basename as basename14 } from "node:path";
303915
304772
  function loadToolProfile(repoRoot) {
303916
304773
  const filePath = join81(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
@@ -303923,8 +304780,8 @@ function loadToolProfile(repoRoot) {
303923
304780
  }
303924
304781
  function saveToolProfile(repoRoot, profile) {
303925
304782
  const contextDir = join81(repoRoot, OA_DIR, "context");
303926
- mkdirSync36(contextDir, { recursive: true });
303927
- writeFileSync33(join81(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
304783
+ mkdirSync37(contextDir, { recursive: true });
304784
+ writeFileSync34(join81(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
303928
304785
  }
303929
304786
  function categorizeToolCall(toolName) {
303930
304787
  for (const cat2 of TOOL_CATEGORIES) {
@@ -303990,13 +304847,13 @@ function loadCachedDescriptors(repoRoot) {
303990
304847
  }
303991
304848
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
303992
304849
  const contextDir = join81(repoRoot, OA_DIR, "context");
303993
- mkdirSync36(contextDir, { recursive: true });
304850
+ mkdirSync37(contextDir, { recursive: true });
303994
304851
  const cached = {
303995
304852
  phrases,
303996
304853
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
303997
304854
  sourceHash
303998
304855
  };
303999
- writeFileSync33(join81(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
304856
+ writeFileSync34(join81(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
304000
304857
  }
304001
304858
  function generateDescriptors(repoRoot) {
304002
304859
  const profile = loadToolProfile(repoRoot);
@@ -304811,13 +305668,13 @@ var init_stream_renderer = __esm({
304811
305668
  });
304812
305669
 
304813
305670
  // packages/cli/src/tui/edit-history.ts
304814
- import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync37 } from "node:fs";
305671
+ import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync38 } from "node:fs";
304815
305672
  import { join as join82 } from "node:path";
304816
305673
  function createEditHistoryLogger(repoRoot, sessionId) {
304817
305674
  const historyDir = join82(repoRoot, ".oa", "history");
304818
305675
  const logPath2 = join82(historyDir, "edits.jsonl");
304819
305676
  try {
304820
- mkdirSync37(historyDir, { recursive: true });
305677
+ mkdirSync38(historyDir, { recursive: true });
304821
305678
  } catch {
304822
305679
  }
304823
305680
  function logToolCall(toolName, toolArgs, success) {
@@ -304926,7 +305783,7 @@ var init_edit_history = __esm({
304926
305783
 
304927
305784
  // packages/cli/src/tui/promptLoader.ts
304928
305785
  import { readFileSync as readFileSync51, existsSync as existsSync66 } from "node:fs";
304929
- import { join as join83, dirname as dirname23 } from "node:path";
305786
+ import { join as join83, dirname as dirname24 } from "node:path";
304930
305787
  import { fileURLToPath as fileURLToPath14 } from "node:url";
304931
305788
  function loadPrompt3(promptPath, vars) {
304932
305789
  let content = cache6.get(promptPath);
@@ -304946,7 +305803,7 @@ var init_promptLoader3 = __esm({
304946
305803
  "packages/cli/src/tui/promptLoader.ts"() {
304947
305804
  "use strict";
304948
305805
  __filename5 = fileURLToPath14(import.meta.url);
304949
- __dirname7 = dirname23(__filename5);
305806
+ __dirname7 = dirname24(__filename5);
304950
305807
  devPath2 = join83(__dirname7, "..", "..", "prompts");
304951
305808
  publishedPath2 = join83(__dirname7, "..", "prompts");
304952
305809
  PROMPTS_DIR3 = existsSync66(devPath2) ? devPath2 : publishedPath2;
@@ -304955,7 +305812,7 @@ var init_promptLoader3 = __esm({
304955
305812
  });
304956
305813
 
304957
305814
  // packages/cli/src/tui/dream-engine.ts
304958
- import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync34, readFileSync as readFileSync52, existsSync as existsSync67, readdirSync as readdirSync18 } from "node:fs";
305815
+ import { mkdirSync as mkdirSync39, writeFileSync as writeFileSync35, readFileSync as readFileSync52, existsSync as existsSync67, readdirSync as readdirSync18 } from "node:fs";
304959
305816
  import { join as join84, basename as basename15 } from "node:path";
304960
305817
  import { execSync as execSync52 } from "node:child_process";
304961
305818
  function setDreamWriteContent(fn) {
@@ -305174,8 +306031,8 @@ var init_dream_engine = __esm({
305174
306031
  }
305175
306032
  try {
305176
306033
  const dir = join84(targetPath, "..");
305177
- mkdirSync38(dir, { recursive: true });
305178
- writeFileSync34(targetPath, content, "utf-8");
306034
+ mkdirSync39(dir, { recursive: true });
306035
+ writeFileSync35(targetPath, content, "utf-8");
305179
306036
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
305180
306037
  } catch (err) {
305181
306038
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305215,7 +306072,7 @@ var init_dream_engine = __esm({
305215
306072
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
305216
306073
  }
305217
306074
  content = content.replace(oldStr, newStr);
305218
- writeFileSync34(targetPath, content, "utf-8");
306075
+ writeFileSync35(targetPath, content, "utf-8");
305219
306076
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start2 };
305220
306077
  } catch (err) {
305221
306078
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305260,8 +306117,8 @@ var init_dream_engine = __esm({
305260
306117
  }
305261
306118
  try {
305262
306119
  const dir = join84(targetPath, "..");
305263
- mkdirSync38(dir, { recursive: true });
305264
- writeFileSync34(targetPath, content, "utf-8");
306120
+ mkdirSync39(dir, { recursive: true });
306121
+ writeFileSync35(targetPath, content, "utf-8");
305265
306122
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start2 };
305266
306123
  } catch (err) {
305267
306124
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305301,7 +306158,7 @@ var init_dream_engine = __esm({
305301
306158
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start2 };
305302
306159
  }
305303
306160
  content = content.replace(oldStr, newStr);
305304
- writeFileSync34(targetPath, content, "utf-8");
306161
+ writeFileSync35(targetPath, content, "utf-8");
305305
306162
  return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start2 };
305306
306163
  } catch (err) {
305307
306164
  return { success: false, output: "", error: String(err), durationMs: Date.now() - start2 };
@@ -305386,7 +306243,7 @@ var init_dream_engine = __esm({
305386
306243
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
305387
306244
  results: []
305388
306245
  };
305389
- mkdirSync38(this.dreamsDir, { recursive: true });
306246
+ mkdirSync39(this.dreamsDir, { recursive: true });
305390
306247
  this.saveDreamState();
305391
306248
  try {
305392
306249
  for (let cycle = 1; cycle <= totalCycles; cycle++) {
@@ -305459,7 +306316,7 @@ ${result.summary}`;
305459
306316
  renderDreamContraction(cycle);
305460
306317
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
305461
306318
  const summaryPath = join84(this.dreamsDir, `cycle-${cycle}-summary.md`);
305462
- writeFileSync34(summaryPath, cycleSummary, "utf-8");
306319
+ writeFileSync35(summaryPath, cycleSummary, "utf-8");
305463
306320
  }
305464
306321
  if (mode === "lucid" && !this.abortController.signal.aborted) {
305465
306322
  this.saveVersionCheckpoint(cycle);
@@ -306119,8 +306976,8 @@ ${summaryResult}
306119
306976
  *Generated by open-agents autoresearch swarm*
306120
306977
  `;
306121
306978
  try {
306122
- mkdirSync38(this.dreamsDir, { recursive: true });
306123
- writeFileSync34(reportPath, report, "utf-8");
306979
+ mkdirSync39(this.dreamsDir, { recursive: true });
306980
+ writeFileSync35(reportPath, report, "utf-8");
306124
306981
  } catch {
306125
306982
  }
306126
306983
  renderSwarmComplete(workspace);
@@ -306188,7 +307045,7 @@ ${summaryResult}
306188
307045
  saveVersionCheckpoint(cycle) {
306189
307046
  const checkpointDir = join84(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
306190
307047
  try {
306191
- mkdirSync38(checkpointDir, { recursive: true });
307048
+ mkdirSync39(checkpointDir, { recursive: true });
306192
307049
  try {
306193
307050
  const gitStatus = execSync52("git status --porcelain", {
306194
307051
  cwd: this.repoRoot,
@@ -306205,10 +307062,10 @@ ${summaryResult}
306205
307062
  encoding: "utf-8",
306206
307063
  timeout: 5e3
306207
307064
  }).trim();
306208
- writeFileSync34(join84(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
306209
- writeFileSync34(join84(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
306210
- writeFileSync34(join84(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
306211
- writeFileSync34(
307065
+ writeFileSync35(join84(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
307066
+ writeFileSync35(join84(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
307067
+ writeFileSync35(join84(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
307068
+ writeFileSync35(
306212
307069
  join84(checkpointDir, "checkpoint.json"),
306213
307070
  JSON.stringify({
306214
307071
  cycle,
@@ -306220,7 +307077,7 @@ ${summaryResult}
306220
307077
  );
306221
307078
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
306222
307079
  } catch {
306223
- writeFileSync34(
307080
+ writeFileSync35(
306224
307081
  join84(checkpointDir, "checkpoint.json"),
306225
307082
  JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2),
306226
307083
  "utf-8"
@@ -306282,7 +307139,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306282
307139
  ---
306283
307140
  *Auto-generated by open-agents dream engine*
306284
307141
  `;
306285
- writeFileSync34(join84(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
307142
+ writeFileSync35(join84(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
306286
307143
  } catch {
306287
307144
  }
306288
307145
  }
@@ -306304,7 +307161,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306304
307161
  };
306305
307162
  renderInfo("Memory consolidation starting \u2014 Phase 1: Orient \u2192 Phase 2: Gather \u2192 Phase 3: Consolidate \u2192 Phase 4: Prune");
306306
307163
  const memoryDir = join84(this.repoRoot, ".oa", "memory");
306307
- mkdirSync38(memoryDir, { recursive: true });
307164
+ mkdirSync39(memoryDir, { recursive: true });
306308
307165
  let prompt;
306309
307166
  try {
306310
307167
  prompt = loadPrompt3("tui/dream-consolidate.md", {
@@ -306368,7 +307225,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306368
307225
  durationMs
306369
307226
  });
306370
307227
  try {
306371
- writeFileSync34(
307228
+ writeFileSync35(
306372
307229
  join84(memoryDir, ".last-consolidation"),
306373
307230
  JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), summary: result.summary?.slice(0, 500) }) + "\n"
306374
307231
  );
@@ -306386,7 +307243,7 @@ ${files.map((f2) => `- [\`${f2}\`](./${f2})`).join("\n")}
306386
307243
  /** Save dream state for resume/inspection */
306387
307244
  saveDreamState() {
306388
307245
  try {
306389
- writeFileSync34(
307246
+ writeFileSync35(
306390
307247
  join84(this.dreamsDir, "dream-state.json"),
306391
307248
  JSON.stringify(this.state, null, 2) + "\n",
306392
307249
  "utf-8"
@@ -306757,7 +307614,7 @@ var init_bless_engine = __esm({
306757
307614
  });
306758
307615
 
306759
307616
  // packages/cli/src/tui/dmn-engine.ts
306760
- import { existsSync as existsSync68, readFileSync as readFileSync53, writeFileSync as writeFileSync35, mkdirSync as mkdirSync39, readdirSync as readdirSync19, unlinkSync as unlinkSync16 } from "node:fs";
307617
+ import { existsSync as existsSync68, readFileSync as readFileSync53, writeFileSync as writeFileSync36, mkdirSync as mkdirSync40, readdirSync as readdirSync19, unlinkSync as unlinkSync16 } from "node:fs";
306761
307618
  import { join as join85, basename as basename16 } from "node:path";
306762
307619
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
306763
307620
  const competenceReport = competence.length > 0 ? competence.map((c7) => {
@@ -306864,7 +307721,7 @@ var init_dmn_engine = __esm({
306864
307721
  this.repoRoot = repoRoot;
306865
307722
  this.stateDir = join85(repoRoot, ".oa", "dmn");
306866
307723
  this.historyDir = join85(repoRoot, ".oa", "dmn", "cycles");
306867
- mkdirSync39(this.historyDir, { recursive: true });
307724
+ mkdirSync40(this.historyDir, { recursive: true });
306868
307725
  this.loadState();
306869
307726
  }
306870
307727
  state = {
@@ -307524,7 +308381,7 @@ OUTPUT: Call task_complete with JSON:
307524
308381
  }
307525
308382
  saveState() {
307526
308383
  try {
307527
- writeFileSync35(
308384
+ writeFileSync36(
307528
308385
  join85(this.stateDir, "state.json"),
307529
308386
  JSON.stringify(this.state, null, 2) + "\n",
307530
308387
  "utf-8"
@@ -307535,7 +308392,7 @@ OUTPUT: Call task_complete with JSON:
307535
308392
  saveCycleResult(result) {
307536
308393
  try {
307537
308394
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
307538
- writeFileSync35(
308395
+ writeFileSync36(
307539
308396
  join85(this.historyDir, filename),
307540
308397
  JSON.stringify(result, null, 2) + "\n",
307541
308398
  "utf-8"
@@ -308397,7 +309254,7 @@ var init_tool_policy = __esm({
308397
309254
  });
308398
309255
 
308399
309256
  // packages/cli/src/tui/telegram-bridge.ts
308400
- import { mkdirSync as mkdirSync40, unlinkSync as unlinkSync17 } from "node:fs";
309257
+ import { mkdirSync as mkdirSync41, unlinkSync as unlinkSync17 } from "node:fs";
308401
309258
  import { join as join87, resolve as resolve32 } from "node:path";
308402
309259
  import { writeFile as writeFileAsync } from "node:fs/promises";
308403
309260
  function convertMarkdownToTelegramHTML(md) {
@@ -308721,7 +309578,7 @@ with summary "no_reply" to silently skip without responding.
308721
309578
  this.polling = true;
308722
309579
  this.abortController = new AbortController();
308723
309580
  try {
308724
- mkdirSync40(this.mediaCacheDir, { recursive: true });
309581
+ mkdirSync41(this.mediaCacheDir, { recursive: true });
308725
309582
  } catch {
308726
309583
  }
308727
309584
  this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
@@ -310069,13 +310926,13 @@ var init_direct_input = __esm({
310069
310926
  });
310070
310927
 
310071
310928
  // packages/cli/src/api/audit-log.ts
310072
- import { mkdirSync as mkdirSync41, appendFileSync as appendFileSync5, readFileSync as readFileSync55, existsSync as existsSync71 } from "node:fs";
310929
+ import { mkdirSync as mkdirSync42, appendFileSync as appendFileSync5, readFileSync as readFileSync55, existsSync as existsSync71 } from "node:fs";
310073
310930
  import { join as join88 } from "node:path";
310074
310931
  function initAuditLog(oaDir) {
310075
310932
  auditDir = join88(oaDir, "audit");
310076
310933
  auditFile = join88(auditDir, "audit.jsonl");
310077
310934
  try {
310078
- mkdirSync41(auditDir, { recursive: true });
310935
+ mkdirSync42(auditDir, { recursive: true });
310079
310936
  initialized = true;
310080
310937
  } catch {
310081
310938
  }
@@ -311527,11 +312384,11 @@ var init_chat_session = __esm({
311527
312384
  });
311528
312385
 
311529
312386
  // packages/cli/src/api/usage-tracker.ts
311530
- import { mkdirSync as mkdirSync42, readFileSync as readFileSync57, writeFileSync as writeFileSync36, existsSync as existsSync73 } from "node:fs";
312387
+ import { mkdirSync as mkdirSync43, readFileSync as readFileSync57, writeFileSync as writeFileSync37, existsSync as existsSync73 } from "node:fs";
311531
312388
  import { join as join90 } from "node:path";
311532
312389
  function initUsageTracker(oaDir) {
311533
312390
  const dir = join90(oaDir, "usage");
311534
- mkdirSync42(dir, { recursive: true });
312391
+ mkdirSync43(dir, { recursive: true });
311535
312392
  usageFile = join90(dir, "token-usage.json");
311536
312393
  try {
311537
312394
  if (existsSync73(usageFile)) {
@@ -311571,7 +312428,7 @@ function flush2() {
311571
312428
  if (!initialized2 || !dirty) return;
311572
312429
  try {
311573
312430
  store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
311574
- writeFileSync36(usageFile, JSON.stringify(store, null, 2), "utf-8");
312431
+ writeFileSync37(usageFile, JSON.stringify(store, null, 2), "utf-8");
311575
312432
  dirty = false;
311576
312433
  } catch {
311577
312434
  }
@@ -311599,7 +312456,7 @@ var init_usage_tracker = __esm({
311599
312456
  });
311600
312457
 
311601
312458
  // packages/cli/src/api/profiles.ts
311602
- import { existsSync as existsSync74, readFileSync as readFileSync58, writeFileSync as writeFileSync37, mkdirSync as mkdirSync43, readdirSync as readdirSync23, unlinkSync as unlinkSync18 } from "node:fs";
312459
+ import { existsSync as existsSync74, readFileSync as readFileSync58, writeFileSync as writeFileSync38, mkdirSync as mkdirSync44, readdirSync as readdirSync23, unlinkSync as unlinkSync18 } from "node:fs";
311603
312460
  import { join as join91 } from "node:path";
311604
312461
  import { homedir as homedir28 } from "node:os";
311605
312462
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes18, scryptSync as scryptSync3 } from "node:crypto";
@@ -311663,16 +312520,16 @@ function loadProfile(name10, password, projectDir) {
311663
312520
  }
311664
312521
  function saveProfile(profile, password, scope = "global", projectDir) {
311665
312522
  const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
311666
- mkdirSync43(dir, { recursive: true });
312523
+ mkdirSync44(dir, { recursive: true });
311667
312524
  const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
311668
312525
  const filePath = join91(dir, `${sanitized}.json`);
311669
312526
  profile.modified = (/* @__PURE__ */ new Date()).toISOString();
311670
312527
  if (password) {
311671
312528
  const encrypted = encryptProfile(profile, password);
311672
- writeFileSync37(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
312529
+ writeFileSync38(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
311673
312530
  } else {
311674
312531
  profile.encrypted = false;
311675
- writeFileSync37(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
312532
+ writeFileSync38(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
311676
312533
  }
311677
312534
  }
311678
312535
  function deleteProfile(name10, scope = "global", projectDir) {
@@ -311794,8 +312651,8 @@ var init_profiles = __esm({
311794
312651
 
311795
312652
  // packages/cli/src/docker.ts
311796
312653
  import { execSync as execSync53, spawn as spawn24 } from "node:child_process";
311797
- import { existsSync as existsSync75, mkdirSync as mkdirSync44, writeFileSync as writeFileSync38 } from "node:fs";
311798
- import { join as join92, resolve as resolve33, dirname as dirname24 } from "node:path";
312654
+ import { existsSync as existsSync75, mkdirSync as mkdirSync45, writeFileSync as writeFileSync39 } from "node:fs";
312655
+ import { join as join92, resolve as resolve33, dirname as dirname25 } from "node:path";
311799
312656
  import { homedir as homedir29 } from "node:os";
311800
312657
  import { fileURLToPath as fileURLToPath15 } from "node:url";
311801
312658
  function getDockerDir() {
@@ -311806,7 +312663,7 @@ function getDockerDir() {
311806
312663
  } catch {
311807
312664
  }
311808
312665
  try {
311809
- const thisDir = dirname24(fileURLToPath15(import.meta.url));
312666
+ const thisDir = dirname25(fileURLToPath15(import.meta.url));
311810
312667
  return join92(thisDir, "..", "..", "..", "docker");
311811
312668
  } catch {
311812
312669
  }
@@ -311945,7 +312802,7 @@ async function ensureOaImage(force = false) {
311945
312802
  buildContext = dockerDir;
311946
312803
  } else {
311947
312804
  buildContext = join92(homedir29(), ".oa", "docker-build");
311948
- mkdirSync44(buildContext, { recursive: true });
312805
+ mkdirSync45(buildContext, { recursive: true });
311949
312806
  writeDockerfiles(buildContext);
311950
312807
  }
311951
312808
  try {
@@ -312019,8 +312876,8 @@ chown -R node:node /workspace /home/node/.oa /home/node/.open-agents 2>/dev/null
312019
312876
  if [ "$1" = "oa" ]; then shift; exec su - node -c "cd /workspace && oa $*"; fi
312020
312877
  exec "$@"
312021
312878
  `;
312022
- writeFileSync38(join92(dir, "Dockerfile"), dockerfile);
312023
- writeFileSync38(join92(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
312879
+ writeFileSync39(join92(dir, "Dockerfile"), dockerfile);
312880
+ writeFileSync39(join92(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
312024
312881
  }
312025
312882
  function hasNvidiaGpu() {
312026
312883
  try {
@@ -312097,14 +312954,14 @@ import * as http5 from "node:http";
312097
312954
  import * as https3 from "node:https";
312098
312955
  import { createRequire as createRequire4 } from "node:module";
312099
312956
  import { fileURLToPath as fileURLToPath16 } from "node:url";
312100
- import { dirname as dirname25, join as join93, resolve as resolve34 } from "node:path";
312957
+ import { dirname as dirname26, join as join93, resolve as resolve34 } from "node:path";
312101
312958
  import { spawn as spawn25, execSync as execSync54 } from "node:child_process";
312102
- import { mkdirSync as mkdirSync45, writeFileSync as writeFileSync39, readFileSync as readFileSync59, readdirSync as readdirSync24, existsSync as existsSync76 } from "node:fs";
312959
+ import { mkdirSync as mkdirSync46, writeFileSync as writeFileSync40, readFileSync as readFileSync59, readdirSync as readdirSync24, existsSync as existsSync76 } from "node:fs";
312103
312960
  import { randomBytes as randomBytes19, randomUUID as randomUUID8 } from "node:crypto";
312104
312961
  function getVersion3() {
312105
312962
  try {
312106
312963
  const require3 = createRequire4(import.meta.url);
312107
- const thisDir = dirname25(fileURLToPath16(import.meta.url));
312964
+ const thisDir = dirname26(fileURLToPath16(import.meta.url));
312108
312965
  const candidates = [
312109
312966
  join93(thisDir, "..", "package.json"),
312110
312967
  join93(thisDir, "..", "..", "package.json"),
@@ -312402,7 +313259,7 @@ function ollamaStream(ollamaUrl, path5, method, body, onData, onEnd, onError) {
312402
313259
  function jobsDir() {
312403
313260
  const root = resolve34(process.cwd());
312404
313261
  const dir = join93(root, ".oa", "jobs");
312405
- mkdirSync45(dir, { recursive: true });
313262
+ mkdirSync46(dir, { recursive: true });
312406
313263
  return dir;
312407
313264
  }
312408
313265
  function loadJob(id) {
@@ -312896,7 +313753,7 @@ async function handleV1Run(req2, res) {
312896
313753
  cwd4 = resolve34(workingDir);
312897
313754
  } else if (isolate) {
312898
313755
  const wsDir = join93(dir, "..", "workspaces", id);
312899
- mkdirSync45(wsDir, { recursive: true });
313756
+ mkdirSync46(wsDir, { recursive: true });
312900
313757
  cwd4 = wsDir;
312901
313758
  } else {
312902
313759
  cwd4 = resolve34(process.cwd());
@@ -312980,7 +313837,7 @@ async function handleV1Run(req2, res) {
312980
313837
  job.sandbox = sandbox;
312981
313838
  }
312982
313839
  job.pid = child.pid ?? 0;
312983
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313840
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
312984
313841
  runningProcesses.set(id, child);
312985
313842
  if (streamMode) {
312986
313843
  res.writeHead(200, {
@@ -313007,7 +313864,7 @@ async function handleV1Run(req2, res) {
313007
313864
  job.status = code8 === 0 ? "completed" : "failed";
313008
313865
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
313009
313866
  try {
313010
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313867
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313011
313868
  } catch {
313012
313869
  }
313013
313870
  runningProcesses.delete(id);
@@ -313047,7 +313904,7 @@ async function handleV1Run(req2, res) {
313047
313904
  job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
313048
313905
  }
313049
313906
  try {
313050
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313907
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313051
313908
  } catch {
313052
313909
  }
313053
313910
  runningProcesses.delete(id);
@@ -313115,7 +313972,7 @@ function handleV1RunsDelete(res, id) {
313115
313972
  job.error = "Aborted via API";
313116
313973
  const dir = jobsDir();
313117
313974
  try {
313118
- writeFileSync39(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313975
+ writeFileSync40(join93(dir, `${id}.json`), JSON.stringify(job, null, 2));
313119
313976
  } catch {
313120
313977
  }
313121
313978
  runningProcesses.delete(id);
@@ -314011,10 +314868,10 @@ var init_serve = __esm({
314011
314868
 
314012
314869
  // packages/cli/src/tui/interactive.ts
314013
314870
  import { cwd } from "node:process";
314014
- import { resolve as resolve35, join as join94, dirname as dirname26, extname as extname11 } from "node:path";
314871
+ import { resolve as resolve35, join as join94, dirname as dirname27, extname as extname11 } from "node:path";
314015
314872
  import { createRequire as createRequire5 } from "node:module";
314016
314873
  import { fileURLToPath as fileURLToPath17 } from "node:url";
314017
- import { readFileSync as readFileSync60, writeFileSync as writeFileSync40, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync25, mkdirSync as mkdirSync46 } from "node:fs";
314874
+ import { readFileSync as readFileSync60, writeFileSync as writeFileSync41, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync25, mkdirSync as mkdirSync47 } from "node:fs";
314018
314875
  import { existsSync as existsSync77 } from "node:fs";
314019
314876
  import { execSync as execSync55 } from "node:child_process";
314020
314877
  import { homedir as homedir30 } from "node:os";
@@ -314031,7 +314888,7 @@ function formatTimeAgo(date) {
314031
314888
  function getVersion4() {
314032
314889
  try {
314033
314890
  const require3 = createRequire5(import.meta.url);
314034
- const thisDir = dirname26(fileURLToPath17(import.meta.url));
314891
+ const thisDir = dirname27(fileURLToPath17(import.meta.url));
314035
314892
  const candidates = [
314036
314893
  join94(thisDir, "..", "package.json"),
314037
314894
  join94(thisDir, "..", "..", "package.json"),
@@ -315612,7 +316469,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
315612
316469
  if (existsSync77(ikFile)) {
315613
316470
  ikState = JSON.parse(readFileSync60(ikFile, "utf8"));
315614
316471
  } else {
315615
- mkdirSync46(ikDir, { recursive: true });
316472
+ mkdirSync47(ikDir, { recursive: true });
315616
316473
  const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
315617
316474
  ikState = {
315618
316475
  self_id: `oa-${machineId}`,
@@ -315668,7 +316525,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
315668
316525
  }
315669
316526
  ikState.session_count = (ikState.session_count || 0) + 1;
315670
316527
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
315671
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
316528
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
315672
316529
  } catch (ikErr) {
315673
316530
  try {
315674
316531
  console.error("[IK-OBSERVE]", ikErr);
@@ -315700,7 +316557,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
315700
316557
  if (ikState.version_history.length > 200) ikState.version_history = ikState.version_history.slice(-200);
315701
316558
  ikState.session_count = (ikState.session_count || 0) + 1;
315702
316559
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
315703
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
316560
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
315704
316561
  }
315705
316562
  } catch {
315706
316563
  }
@@ -316713,12 +317570,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
316713
317570
  function persistHistoryLine(line) {
316714
317571
  if (!line.trim()) return;
316715
317572
  try {
316716
- mkdirSync46(HISTORY_DIR, { recursive: true });
317573
+ mkdirSync47(HISTORY_DIR, { recursive: true });
316717
317574
  appendFileSync6(HISTORY_FILE, line + "\n", "utf8");
316718
317575
  if (Math.random() < 0.02) {
316719
317576
  const all2 = readFileSync60(HISTORY_FILE, "utf8").trim().split("\n");
316720
317577
  if (all2.length > MAX_HISTORY_LINES) {
316721
- writeFileSync40(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
317578
+ writeFileSync41(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
316722
317579
  }
316723
317580
  }
316724
317581
  } catch {
@@ -317270,6 +318127,15 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
317270
318127
  repoRoot,
317271
318128
  costTracker,
317272
318129
  workEvaluator,
318130
+ getMcpManager: () => _mcpManager,
318131
+ refreshMcpTools: async () => {
318132
+ if (_mcpManager) {
318133
+ try {
318134
+ _mcpTools = await _mcpManager.buildTools();
318135
+ } catch {
318136
+ }
318137
+ }
318138
+ },
317273
318139
  get lastTask() {
317274
318140
  return lastSubmittedPrompt;
317275
318141
  },
@@ -318836,6 +319702,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
318836
319702
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
318837
319703
  const isImage = isImagePath(cleanPath) && existsSync77(resolve35(repoRoot, cleanPath));
318838
319704
  const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync77(resolve35(repoRoot, cleanPath));
319705
+ const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) && existsSync77(resolve35(repoRoot, cleanPath));
318839
319706
  if (activeTask) {
318840
319707
  if (activeTask.runner.isPaused) {
318841
319708
  activeTask.runner.resume();
@@ -319009,6 +319876,44 @@ ${result.text}`;
319009
319876
  return;
319010
319877
  }
319011
319878
  }
319879
+ if (isMarkdown && fullInput === input) {
319880
+ try {
319881
+ const mdPath = resolve35(repoRoot, cleanPath);
319882
+ const mdContent = readFileSync60(mdPath, "utf8");
319883
+ const { parseMcpMarkdown: parseMcpMarkdown2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
319884
+ const result = parseMcpMarkdown2(mdContent);
319885
+ if (result.servers.length > 0) {
319886
+ writeContent(() => renderInfo(`Detected ${result.servers.length} MCP server config(s) in ${cleanPath} \u2014 adding to .oa/mcp.json`));
319887
+ const added = [];
319888
+ for (const s2 of result.servers) {
319889
+ try {
319890
+ if (_mcpManager) {
319891
+ const conn = await _mcpManager.addServer(s2.name, s2.config, "project");
319892
+ 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"})`;
319893
+ writeContent(() => renderInfo(` ${tag}`));
319894
+ added.push(s2.name);
319895
+ }
319896
+ } catch (e2) {
319897
+ writeContent(() => renderError(` \u2718 ${s2.name}: ${e2 instanceof Error ? e2.message : String(e2)}`));
319898
+ }
319899
+ }
319900
+ if (_mcpManager && added.length > 0) {
319901
+ try {
319902
+ _mcpTools = await _mcpManager.buildTools();
319903
+ writeContent(() => renderInfo(`MCP tool list refreshed (${_mcpTools.length} total MCP tools available)`));
319904
+ } catch {
319905
+ }
319906
+ }
319907
+ showPrompt();
319908
+ return;
319909
+ } else if (result.isMcpDocument) {
319910
+ writeContent(() => renderWarning(`${cleanPath} mentions MCP but no valid server config could be extracted from code blocks.`));
319911
+ for (const note of result.notes) writeContent(() => renderInfo(` ${note}`));
319912
+ }
319913
+ } catch (e2) {
319914
+ writeContent(() => renderError(`Failed to parse ${cleanPath}: ${e2 instanceof Error ? e2.message : String(e2)}`));
319915
+ }
319916
+ }
319012
319917
  if (isMedia && fullInput === input) {
319013
319918
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
319014
319919
  const engine = getListenEngine();
@@ -319403,7 +320308,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319403
320308
  if (existsSync77(ikFile)) {
319404
320309
  ikState = JSON.parse(readFileSync60(ikFile, "utf8"));
319405
320310
  } else {
319406
- mkdirSync46(ikDir, { recursive: true });
320311
+ mkdirSync47(ikDir, { recursive: true });
319407
320312
  ikState = {
319408
320313
  self_id: `oa-${Date.now().toString(36)}`,
319409
320314
  version: 1,
@@ -319425,7 +320330,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319425
320330
  ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
319426
320331
  ikState.session_count = (ikState.session_count || 0) + 1;
319427
320332
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
319428
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
320333
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
319429
320334
  } catch (ikErr) {
319430
320335
  }
319431
320336
  try {
@@ -319456,8 +320361,8 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319456
320361
  tags: ["general"]
319457
320362
  });
319458
320363
  if (variants.length > 50) variants = variants.slice(-50);
319459
- mkdirSync46(archeDir, { recursive: true });
319460
- writeFileSync40(archeFile, JSON.stringify(variants, null, 2));
320364
+ mkdirSync47(archeDir, { recursive: true });
320365
+ writeFileSync41(archeFile, JSON.stringify(variants, null, 2));
319461
320366
  } catch {
319462
320367
  }
319463
320368
  }
@@ -319475,7 +320380,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
319475
320380
  updated = true;
319476
320381
  }
319477
320382
  if (updated) {
319478
- writeFileSync40(metaFile, JSON.stringify(store2, null, 2));
320383
+ writeFileSync41(metaFile, JSON.stringify(store2, null, 2));
319479
320384
  }
319480
320385
  }
319481
320386
  } catch {
@@ -319529,7 +320434,7 @@ Rules:
319529
320434
  const { initDb: initDb2 } = __require("@open-agents/memory");
319530
320435
  const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
319531
320436
  const dbDir = join94(repoRoot, ".oa", "memory");
319532
- mkdirSync46(dbDir, { recursive: true });
320437
+ mkdirSync47(dbDir, { recursive: true });
319533
320438
  const db = initDb2(join94(dbDir, "structured.db"));
319534
320439
  const memStore = new ProceduralMemoryStore2(db);
319535
320440
  memStore.createWithEmbedding({
@@ -319564,8 +320469,8 @@ Rules:
319564
320469
  accessCount: 0
319565
320470
  });
319566
320471
  if (store2.length > 100) store2 = store2.slice(-100);
319567
- mkdirSync46(metaDir, { recursive: true });
319568
- writeFileSync40(storeFile, JSON.stringify(store2, null, 2));
320472
+ mkdirSync47(metaDir, { recursive: true });
320473
+ writeFileSync41(storeFile, JSON.stringify(store2, null, 2));
319569
320474
  }
319570
320475
  }
319571
320476
  } catch {
@@ -319615,7 +320520,7 @@ Rules:
319615
320520
  ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
319616
320521
  ikState.session_count = (ikState.session_count || 0) + 1;
319617
320522
  ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
319618
- writeFileSync40(ikFile, JSON.stringify(ikState, null, 2));
320523
+ writeFileSync41(ikFile, JSON.stringify(ikState, null, 2));
319619
320524
  }
319620
320525
  const metaFile = join94(repoRoot, ".oa", "memory", "metabolism", "store.json");
319621
320526
  if (existsSync77(metaFile)) {
@@ -319627,7 +320532,7 @@ Rules:
319627
320532
  item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
319628
320533
  item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
319629
320534
  }
319630
- writeFileSync40(metaFile, JSON.stringify(store2, null, 2));
320535
+ writeFileSync41(metaFile, JSON.stringify(store2, null, 2));
319631
320536
  }
319632
320537
  try {
319633
320538
  const archeDir = join94(repoRoot, ".oa", "arche");
@@ -319648,8 +320553,8 @@ Rules:
319648
320553
  tags: ["general"]
319649
320554
  });
319650
320555
  if (variants.length > 50) variants = variants.slice(-50);
319651
- mkdirSync46(archeDir, { recursive: true });
319652
- writeFileSync40(archeFile, JSON.stringify(variants, null, 2));
320556
+ mkdirSync47(archeDir, { recursive: true });
320557
+ writeFileSync41(archeFile, JSON.stringify(variants, null, 2));
319653
320558
  } catch {
319654
320559
  }
319655
320560
  } catch {
@@ -319731,13 +320636,13 @@ __export(run_exports, {
319731
320636
  });
319732
320637
  import { resolve as resolve36 } from "node:path";
319733
320638
  import { spawn as spawn26 } from "node:child_process";
319734
- import { mkdirSync as mkdirSync47, writeFileSync as writeFileSync41, readFileSync as readFileSync61, readdirSync as readdirSync26, existsSync as existsSync78 } from "node:fs";
320639
+ import { mkdirSync as mkdirSync48, writeFileSync as writeFileSync42, readFileSync as readFileSync61, readdirSync as readdirSync26, existsSync as existsSync78 } from "node:fs";
319735
320640
  import { randomBytes as randomBytes20 } from "node:crypto";
319736
320641
  import { join as join95 } from "node:path";
319737
320642
  function jobsDir2(repoPath) {
319738
320643
  const root = resolve36(repoPath ?? process.cwd());
319739
320644
  const dir = join95(root, ".oa", "jobs");
319740
- mkdirSync47(dir, { recursive: true });
320645
+ mkdirSync48(dir, { recursive: true });
319741
320646
  return dir;
319742
320647
  }
319743
320648
  async function runCommand(opts, config) {
@@ -319852,7 +320757,7 @@ async function runBackground(task, config, opts) {
319852
320757
  }
319853
320758
  });
319854
320759
  job.pid = child.pid ?? 0;
319855
- writeFileSync41(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
320760
+ writeFileSync42(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
319856
320761
  let output = "";
319857
320762
  child.stdout?.on("data", (chunk) => {
319858
320763
  output += chunk.toString();
@@ -319868,7 +320773,7 @@ async function runBackground(task, config, opts) {
319868
320773
  job.summary = result.summary;
319869
320774
  job.durationMs = result.durationMs;
319870
320775
  job.error = result.error;
319871
- writeFileSync41(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
320776
+ writeFileSync42(join95(dir, `${id}.json`), JSON.stringify(job, null, 2));
319872
320777
  } catch {
319873
320778
  }
319874
320779
  });
@@ -320691,7 +321596,7 @@ __export(eval_exports, {
320691
321596
  evalCommand: () => evalCommand
320692
321597
  });
320693
321598
  import { tmpdir as tmpdir20 } from "node:os";
320694
- import { mkdirSync as mkdirSync48, writeFileSync as writeFileSync42 } from "node:fs";
321599
+ import { mkdirSync as mkdirSync49, writeFileSync as writeFileSync43 } from "node:fs";
320695
321600
  import { join as join98 } from "node:path";
320696
321601
  async function evalCommand(opts, config) {
320697
321602
  const suiteName = opts.suite ?? "basic";
@@ -320822,8 +321727,8 @@ async function evalCommand(opts, config) {
320822
321727
  }
320823
321728
  function createTempEvalRepo() {
320824
321729
  const dir = join98(tmpdir20(), `open-agents-eval-${Date.now()}`);
320825
- mkdirSync48(dir, { recursive: true });
320826
- writeFileSync42(
321730
+ mkdirSync49(dir, { recursive: true });
321731
+ writeFileSync43(
320827
321732
  join98(dir, "package.json"),
320828
321733
  JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n",
320829
321734
  "utf8"
@@ -320887,7 +321792,7 @@ init_updater();
320887
321792
  import { parseArgs as nodeParseArgs2 } from "node:util";
320888
321793
  import { createRequire as createRequire6 } from "node:module";
320889
321794
  import { fileURLToPath as fileURLToPath18 } from "node:url";
320890
- import { dirname as dirname27, join as join99 } from "node:path";
321795
+ import { dirname as dirname28, join as join99 } from "node:path";
320891
321796
 
320892
321797
  // packages/cli/src/cli.ts
320893
321798
  import { createInterface } from "node:readline";
@@ -320994,7 +321899,7 @@ init_output();
320994
321899
  function getVersion5() {
320995
321900
  try {
320996
321901
  const require3 = createRequire6(import.meta.url);
320997
- const pkgPath = join99(dirname27(fileURLToPath18(import.meta.url)), "..", "package.json");
321902
+ const pkgPath = join99(dirname28(fileURLToPath18(import.meta.url)), "..", "package.json");
320998
321903
  const pkg = require3(pkgPath);
320999
321904
  return pkg.version;
321000
321905
  } catch {
@@ -321286,11 +322191,11 @@ function crashLog(label, err) {
321286
322191
  const logLine = `[${timestamp}] ${label}: ${msg}
321287
322192
  `;
321288
322193
  try {
321289
- const { appendFileSync: appendFileSync7, mkdirSync: mkdirSync49 } = __require("node:fs");
322194
+ const { appendFileSync: appendFileSync7, mkdirSync: mkdirSync50 } = __require("node:fs");
321290
322195
  const { join: join100 } = __require("node:path");
321291
322196
  const { homedir: homedir32 } = __require("node:os");
321292
322197
  const logDir = join100(homedir32(), ".open-agents");
321293
- mkdirSync49(logDir, { recursive: true });
322198
+ mkdirSync50(logDir, { recursive: true });
321294
322199
  appendFileSync7(join100(logDir, "crash.log"), logLine);
321295
322200
  } catch {
321296
322201
  }