open-agents-ai 0.187.8 → 0.187.10

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 +694 -225
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12980,14 +12980,23 @@ var init_skill_tools = __esm({
12980
12980
  name: {
12981
12981
  type: "string",
12982
12982
  description: "Skill name (e.g. 'artifact-lookup', 'test-coverage', 'security-assessment')"
12983
+ },
12984
+ fork: {
12985
+ type: "boolean",
12986
+ description: "Run skill in a sub-agent instead of expanding inline (saves parent context for large skills)"
12983
12987
  }
12984
12988
  },
12985
12989
  required: ["name"]
12986
12990
  };
12987
12991
  repoRoot;
12992
+ _forkCallback;
12988
12993
  constructor(repoRoot) {
12989
12994
  this.repoRoot = repoRoot;
12990
12995
  }
12996
+ /** Set callback to handle forked skill execution via sub-agent (WO-FORK-01) */
12997
+ setForkCallback(cb) {
12998
+ this._forkCallback = cb;
12999
+ }
12991
13000
  async execute(args) {
12992
13001
  const start2 = performance.now();
12993
13002
  const name10 = String(args["name"] ?? args["skill_name"] ?? args["skillName"] ?? args["skill"] ?? "").trim();
@@ -13021,6 +13030,15 @@ Did you mean: ${fuzzy.map((s2) => s2.name).join(", ")}?` : "\nUse skill_list to
13021
13030
  durationMs: performance.now() - start2
13022
13031
  };
13023
13032
  }
13033
+ const fork = Boolean(args["fork"]);
13034
+ if (fork && this._forkCallback) {
13035
+ try {
13036
+ const result = await this._forkCallback(skill.name, content);
13037
+ return { success: true, output: result, durationMs: performance.now() - start2 };
13038
+ } catch (err) {
13039
+ return { success: false, output: "", error: `Skill fork failed: ${err instanceof Error ? err.message : String(err)}`, durationMs: performance.now() - start2 };
13040
+ }
13041
+ }
13024
13042
  const compactionHint = skill.compactionStrategy ? `
13025
13043
  Compaction strategy: ${skill.compactionStrategy}` : "";
13026
13044
  return {
@@ -247600,9 +247618,9 @@ var init_vision = __esm({
247600
247618
  if (ollamaResult)
247601
247619
  return ollamaResult;
247602
247620
  try {
247603
- const { execSync: execSync39 } = await import("node:child_process");
247621
+ const { execSync: execSync40 } = await import("node:child_process");
247604
247622
  try {
247605
- execSync39("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
247623
+ execSync40("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
247606
247624
  timeout: 12e4,
247607
247625
  stdio: "pipe"
247608
247626
  });
@@ -247615,7 +247633,7 @@ var init_vision = __esm({
247615
247633
  } catch {
247616
247634
  }
247617
247635
  try {
247618
- execSync39("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247636
+ execSync40("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247619
247637
  const retryOllama = await this.tryOllamaVision(buffer2, filename, action, prompt, length4, start2);
247620
247638
  if (retryOllama)
247621
247639
  return retryOllama;
@@ -247723,8 +247741,8 @@ Coordinates are normalized (0-1). Multiply by image width/height for pixel value
247723
247741
  const errText = await res.text().catch(() => "");
247724
247742
  if (res.status === 404 || /not found|does not exist/i.test(errText)) {
247725
247743
  try {
247726
- const { execSync: execSync39 } = await import("node:child_process");
247727
- execSync39("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247744
+ const { execSync: execSync40 } = await import("node:child_process");
247745
+ execSync40("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247728
247746
  res = await fetch(`${ollamaHost}/api/generate`, {
247729
247747
  method: "POST",
247730
247748
  headers: { "Content-Type": "application/json" },
@@ -259377,6 +259395,400 @@ var init_pressure_gate = __esm({
259377
259395
  }
259378
259396
  });
259379
259397
 
259398
+ // packages/orchestrator/dist/tool-batching.js
259399
+ function isConcurrencySafe(toolName, readOnlyHints) {
259400
+ if (CONCURRENT_SAFE_TOOLS.has(toolName))
259401
+ return true;
259402
+ if (SERIAL_ONLY_TOOLS.has(toolName))
259403
+ return false;
259404
+ if (toolName.startsWith("mcp__") && readOnlyHints?.get(toolName))
259405
+ return true;
259406
+ return false;
259407
+ }
259408
+ function partitionToolCalls(calls, readOnlyHints) {
259409
+ if (calls.length === 0)
259410
+ return [];
259411
+ if (calls.length === 1) {
259412
+ return [{ concurrent: false, calls }];
259413
+ }
259414
+ const batches = [];
259415
+ let currentConcurrent = [];
259416
+ for (const call of calls) {
259417
+ if (isConcurrencySafe(call.name, readOnlyHints)) {
259418
+ currentConcurrent.push(call);
259419
+ } else {
259420
+ if (currentConcurrent.length > 0) {
259421
+ batches.push({ concurrent: true, calls: currentConcurrent });
259422
+ currentConcurrent = [];
259423
+ }
259424
+ batches.push({ concurrent: false, calls: [call] });
259425
+ }
259426
+ }
259427
+ if (currentConcurrent.length > 0) {
259428
+ batches.push({ concurrent: true, calls: currentConcurrent });
259429
+ }
259430
+ return batches;
259431
+ }
259432
+ async function withConcurrencyLimit(fns, limit = 5) {
259433
+ const results = new Array(fns.length);
259434
+ let nextIdx = 0;
259435
+ async function runNext() {
259436
+ while (nextIdx < fns.length) {
259437
+ const idx = nextIdx++;
259438
+ results[idx] = await fns[idx]();
259439
+ }
259440
+ }
259441
+ const workers = Array.from({ length: Math.min(limit, fns.length) }, () => runNext());
259442
+ await Promise.all(workers);
259443
+ return results;
259444
+ }
259445
+ async function executeBatch(batch2, executeFn, concurrencyLimit = 5) {
259446
+ if (!batch2.concurrent || batch2.calls.length === 1) {
259447
+ const results = [];
259448
+ for (const call of batch2.calls) {
259449
+ results.push(await executeFn(call));
259450
+ }
259451
+ return results;
259452
+ }
259453
+ return withConcurrencyLimit(batch2.calls.map((call) => () => executeFn(call)), concurrencyLimit);
259454
+ }
259455
+ var CONCURRENT_SAFE_TOOLS, SERIAL_ONLY_TOOLS;
259456
+ var init_tool_batching = __esm({
259457
+ "packages/orchestrator/dist/tool-batching.js"() {
259458
+ "use strict";
259459
+ CONCURRENT_SAFE_TOOLS = /* @__PURE__ */ new Set([
259460
+ // Read-only file operations
259461
+ "file_read",
259462
+ "grep_search",
259463
+ // actual tool name (grep-search.ts)
259464
+ "grep",
259465
+ // alias (used in tests/documentation)
259466
+ "find_files",
259467
+ // actual tool name (glob-find.ts)
259468
+ "glob",
259469
+ // alias (used in tests/documentation)
259470
+ "list_directory",
259471
+ "file_explore",
259472
+ "read_structured_file",
259473
+ "git_info",
259474
+ "codebase_map",
259475
+ "repo_map",
259476
+ "semantic_map",
259477
+ // Read-only web operations
259478
+ "web_fetch",
259479
+ "web_search",
259480
+ // Read-only memory operations
259481
+ "memory_read",
259482
+ "memory_search",
259483
+ // Read-only MCP operations (all MCP reads are safe)
259484
+ "mcp_status",
259485
+ "mcp_read_resource",
259486
+ // Informational tools
259487
+ "explore_tools",
259488
+ "task_status",
259489
+ "task_output",
259490
+ "diagnostic",
259491
+ "process_health",
259492
+ "skill_list",
259493
+ "agenda",
259494
+ "working_notes",
259495
+ // Agent spawning (each gets own context)
259496
+ "agent",
259497
+ "sub_agent",
259498
+ "full_sub_agent",
259499
+ // Vision/image (read-only analysis)
259500
+ "vision",
259501
+ "image_read",
259502
+ "screenshot",
259503
+ // actual tool name (image.ts)
259504
+ "ocr",
259505
+ // actual tool name (image.ts)
259506
+ "ocr_image_advanced",
259507
+ "ocr_pdf",
259508
+ "pdf_to_text",
259509
+ "desktop_describe",
259510
+ // Completion signal
259511
+ "task_complete"
259512
+ ]);
259513
+ SERIAL_ONLY_TOOLS = /* @__PURE__ */ new Set([
259514
+ "file_write",
259515
+ "file_edit",
259516
+ "batch_edit",
259517
+ "file_patch",
259518
+ "shell",
259519
+ "code_sandbox",
259520
+ "notebook_edit",
259521
+ "memory_write",
259522
+ "enter_worktree",
259523
+ "exit_worktree",
259524
+ "create_tool",
259525
+ "desktop_click",
259526
+ "browser_action",
259527
+ "web_crawl",
259528
+ // Spawns browser session — can conflict
259529
+ "image_generate",
259530
+ // GPU resource contention
259531
+ "task_stop"
259532
+ ]);
259533
+ }
259534
+ });
259535
+
259536
+ // packages/orchestrator/dist/hooks.js
259537
+ import { execSync as execSync27 } from "node:child_process";
259538
+ function executeHook(hook, env2 = {}) {
259539
+ const start2 = performance.now();
259540
+ const timeout2 = hook.timeoutMs ?? DEFAULT_HOOK_TIMEOUT;
259541
+ try {
259542
+ const output = execSync27(hook.command, {
259543
+ timeout: timeout2,
259544
+ env: { ...process.env, ...env2 },
259545
+ encoding: "utf8",
259546
+ stdio: ["pipe", "pipe", "pipe"],
259547
+ maxBuffer: 1024 * 1024
259548
+ // 1MB
259549
+ });
259550
+ const directive = parseDirective(output);
259551
+ return {
259552
+ success: true,
259553
+ output: output.trim(),
259554
+ directive,
259555
+ durationMs: performance.now() - start2
259556
+ };
259557
+ } catch (err) {
259558
+ const error = err instanceof Error ? err.message : String(err);
259559
+ const stderr = err?.stderr?.toString?.() ?? "";
259560
+ return {
259561
+ success: false,
259562
+ output: "",
259563
+ error: stderr || error,
259564
+ durationMs: performance.now() - start2
259565
+ };
259566
+ }
259567
+ }
259568
+ function parseDirective(output) {
259569
+ const lines = output.split("\n");
259570
+ for (const line of lines) {
259571
+ const trimmed = line.trim();
259572
+ if (trimmed === "HOOK:ALLOW") {
259573
+ return { action: "allow" };
259574
+ }
259575
+ if (trimmed.startsWith("HOOK:DENY")) {
259576
+ const reason = trimmed.slice("HOOK:DENY".length).trim() || "Denied by hook";
259577
+ return { action: "deny", reason };
259578
+ }
259579
+ if (trimmed.startsWith("HOOK:MODIFY")) {
259580
+ try {
259581
+ const json = trimmed.slice("HOOK:MODIFY".length).trim();
259582
+ const args = JSON.parse(json);
259583
+ return { action: "modify", args };
259584
+ } catch {
259585
+ }
259586
+ }
259587
+ }
259588
+ return void 0;
259589
+ }
259590
+ function matchesToolFilter(hook, toolName) {
259591
+ if (!hook.toolFilter || hook.toolFilter === "*")
259592
+ return true;
259593
+ if (hook.toolFilter === toolName)
259594
+ return true;
259595
+ if (hook.toolFilter.includes("*")) {
259596
+ const regex = new RegExp("^" + hook.toolFilter.replace(/\*/g, ".*") + "$");
259597
+ return regex.test(toolName);
259598
+ }
259599
+ return false;
259600
+ }
259601
+ var DEFAULT_HOOK_TIMEOUT, HookManager;
259602
+ var init_hooks = __esm({
259603
+ "packages/orchestrator/dist/hooks.js"() {
259604
+ "use strict";
259605
+ DEFAULT_HOOK_TIMEOUT = 1e4;
259606
+ HookManager = class {
259607
+ config;
259608
+ constructor(config = {}) {
259609
+ this.config = config;
259610
+ }
259611
+ /** Update hook configuration */
259612
+ setConfig(config) {
259613
+ this.config = config;
259614
+ }
259615
+ /** Get current hook configuration */
259616
+ getConfig() {
259617
+ return this.config;
259618
+ }
259619
+ /** Check if any hooks are configured */
259620
+ hasHooks() {
259621
+ return Object.values(this.config).some((hooks) => hooks && hooks.length > 0);
259622
+ }
259623
+ /**
259624
+ * Run pre_tool_use hooks.
259625
+ * Returns: { allowed: true } or { allowed: false, reason } or { allowed: true, modifiedArgs }
259626
+ */
259627
+ runPreToolUse(toolName, args, sessionId) {
259628
+ const hooks = this.config.pre_tool_use ?? [];
259629
+ const matching = hooks.filter((h) => matchesToolFilter(h, toolName));
259630
+ let currentArgs = args;
259631
+ for (const hook of matching) {
259632
+ const result = executeHook(hook, {
259633
+ OA_HOOK_TYPE: "pre_tool_use",
259634
+ OA_TOOL_NAME: toolName,
259635
+ OA_TOOL_ARGS: JSON.stringify(currentArgs),
259636
+ OA_SESSION_ID: sessionId ?? ""
259637
+ });
259638
+ if (!result.success) {
259639
+ continue;
259640
+ }
259641
+ if (result.directive?.action === "deny") {
259642
+ return { allowed: false, reason: result.directive.reason };
259643
+ }
259644
+ if (result.directive?.action === "modify") {
259645
+ currentArgs = { ...currentArgs, ...result.directive.args };
259646
+ }
259647
+ }
259648
+ const modified = currentArgs !== args;
259649
+ return { allowed: true, modifiedArgs: modified ? currentArgs : void 0 };
259650
+ }
259651
+ /**
259652
+ * Run post_tool_use hooks (after successful execution).
259653
+ */
259654
+ runPostToolUse(toolName, args, result, sessionId) {
259655
+ const hooks = this.config.post_tool_use ?? [];
259656
+ const matching = hooks.filter((h) => matchesToolFilter(h, toolName));
259657
+ for (const hook of matching) {
259658
+ executeHook(hook, {
259659
+ OA_HOOK_TYPE: "post_tool_use",
259660
+ OA_TOOL_NAME: toolName,
259661
+ OA_TOOL_ARGS: JSON.stringify(args),
259662
+ OA_TOOL_RESULT: result.slice(0, 1e4),
259663
+ // Cap at 10KB
259664
+ OA_SESSION_ID: sessionId ?? ""
259665
+ });
259666
+ }
259667
+ }
259668
+ /**
259669
+ * Run post_tool_use_failure hooks (after failed execution).
259670
+ */
259671
+ runPostToolUseFailure(toolName, args, error, sessionId) {
259672
+ const hooks = this.config.post_tool_use_failure ?? [];
259673
+ const matching = hooks.filter((h) => matchesToolFilter(h, toolName));
259674
+ for (const hook of matching) {
259675
+ executeHook(hook, {
259676
+ OA_HOOK_TYPE: "post_tool_use_failure",
259677
+ OA_TOOL_NAME: toolName,
259678
+ OA_TOOL_ARGS: JSON.stringify(args),
259679
+ OA_TOOL_ERROR: error.slice(0, 5e3),
259680
+ OA_SESSION_ID: sessionId ?? ""
259681
+ });
259682
+ }
259683
+ }
259684
+ /**
259685
+ * Run session lifecycle hooks.
259686
+ */
259687
+ runSessionHook(type, sessionId) {
259688
+ const hooks = this.config[type] ?? [];
259689
+ for (const hook of hooks) {
259690
+ executeHook(hook, {
259691
+ OA_HOOK_TYPE: type,
259692
+ OA_SESSION_ID: sessionId ?? ""
259693
+ });
259694
+ }
259695
+ }
259696
+ };
259697
+ }
259698
+ });
259699
+
259700
+ // packages/orchestrator/dist/app-state.js
259701
+ function createAppState(opts) {
259702
+ return {
259703
+ // Session identity
259704
+ sessionId: opts?.sessionId ?? `session-${Date.now()}`,
259705
+ sessionStartTime: Date.now(),
259706
+ totalTurns: 0,
259707
+ // Model & context
259708
+ model: opts?.model ?? "",
259709
+ modelTier: opts?.modelTier ?? "medium",
259710
+ contextWindowSize: opts?.contextWindowSize ?? 0,
259711
+ maxOutputTokens: 16384,
259712
+ historyLength: 0,
259713
+ // Tool execution
259714
+ toolUseCountByName: /* @__PURE__ */ new Map(),
259715
+ lastToolDurationMs: 0,
259716
+ lastError: null,
259717
+ fileChangesSinceLastTurn: /* @__PURE__ */ new Set(),
259718
+ modifiedFilesSinceStart: /* @__PURE__ */ new Set(),
259719
+ // Tool decisions
259720
+ toolDecisions: [],
259721
+ toolDecisionMaxHistory: 500,
259722
+ // Cost tracking
259723
+ costState: {
259724
+ totalInputTokens: 0,
259725
+ totalOutputTokens: 0,
259726
+ totalCostUsd: 0,
259727
+ cacheHits: 0,
259728
+ cacheMisses: 0,
259729
+ taskCount: 0
259730
+ },
259731
+ // MCP
259732
+ mcpConnections: [],
259733
+ // Plugins
259734
+ loadedPlugins: [],
259735
+ // Skills
259736
+ discoveredSkillNames: /* @__PURE__ */ new Set(),
259737
+ // Nexus
259738
+ nexusConnectionStatus: "disconnected",
259739
+ // Agent tasks
259740
+ agentTasks: /* @__PURE__ */ new Map(),
259741
+ // Hooks
259742
+ hookExecutionHistory: [],
259743
+ // Speculative execution
259744
+ speculativeExecution: {
259745
+ enabled: false,
259746
+ lastHit: false,
259747
+ attempts: 0,
259748
+ hits: 0
259749
+ },
259750
+ // UI
259751
+ verbose: opts?.verbose ?? false,
259752
+ spinnerTip: "",
259753
+ expandedView: false
259754
+ };
259755
+ }
259756
+ function recordToolDecision(state, decision) {
259757
+ state.toolDecisions.push({ ...decision, timestamp: Date.now() });
259758
+ if (state.toolDecisions.length > state.toolDecisionMaxHistory) {
259759
+ state.toolDecisions.splice(0, state.toolDecisions.length - state.toolDecisionMaxHistory);
259760
+ }
259761
+ }
259762
+ function recordToolExecution(state, toolName, durationMs, success, filePath) {
259763
+ state.toolUseCountByName.set(toolName, (state.toolUseCountByName.get(toolName) ?? 0) + 1);
259764
+ state.lastToolDurationMs = durationMs;
259765
+ if (!success) {
259766
+ state.lastError = `${toolName} failed`;
259767
+ }
259768
+ if (filePath && ["file_write", "file_edit", "batch_edit", "file_patch", "notebook_edit"].includes(toolName)) {
259769
+ state.fileChangesSinceLastTurn.add(filePath);
259770
+ state.modifiedFilesSinceStart.add(filePath);
259771
+ }
259772
+ }
259773
+ function clearTurnState(state) {
259774
+ state.fileChangesSinceLastTurn.clear();
259775
+ state.totalTurns++;
259776
+ }
259777
+ function recordTokenUsage(state, inputTokens, outputTokens, costUsd, cacheHit) {
259778
+ state.costState.totalInputTokens += inputTokens;
259779
+ state.costState.totalOutputTokens += outputTokens;
259780
+ state.costState.totalCostUsd += costUsd;
259781
+ if (cacheHit)
259782
+ state.costState.cacheHits++;
259783
+ else
259784
+ state.costState.cacheMisses++;
259785
+ }
259786
+ var init_app_state = __esm({
259787
+ "packages/orchestrator/dist/app-state.js"() {
259788
+ "use strict";
259789
+ }
259790
+ });
259791
+
259380
259792
  // packages/orchestrator/dist/agenticRunner.js
259381
259793
  function repairJson(raw) {
259382
259794
  if (!raw || typeof raw !== "string")
@@ -259450,6 +259862,9 @@ var init_agenticRunner = __esm({
259450
259862
  init_promptLoader();
259451
259863
  init_pressure_gate();
259452
259864
  init_dist4();
259865
+ init_tool_batching();
259866
+ init_hooks();
259867
+ init_app_state();
259453
259868
  SYSTEM_PROMPT = loadPrompt("agentic/system-large.md");
259454
259869
  SYSTEM_PROMPT_MEDIUM = loadPrompt("agentic/system-medium.md");
259455
259870
  SYSTEM_PROMPT_SMALL = loadPrompt("agentic/system-small.md");
@@ -259467,6 +259882,8 @@ var init_agenticRunner = __esm({
259467
259882
  _sudoResolve = null;
259468
259883
  _pendingCompaction = null;
259469
259884
  _skillCompactionStrategy = null;
259885
+ _hookManager = new HookManager();
259886
+ _appState = createAppState();
259470
259887
  // -- Task State Tracking (Priority 3) --
259471
259888
  _taskState = {
259472
259889
  goal: "",
@@ -259741,6 +260158,14 @@ ${this.options.dynamicContext}`,
259741
260158
  get isPaused() {
259742
260159
  return this._paused;
259743
260160
  }
260161
+ /** Configure hook chains for tool execution (WO-HOOK-01) */
260162
+ setHooks(config) {
260163
+ this._hookManager.setConfig(config);
260164
+ }
260165
+ /** Get the current application state snapshot (WO-STATE-01) */
260166
+ get appState() {
260167
+ return this._appState;
260168
+ }
259744
260169
  /**
259745
260170
  * Request manual context compaction at the next turn boundary.
259746
260171
  * The strategy controls how aggressively context is compressed:
@@ -259851,6 +260276,14 @@ Respond with your assessment, then take action.`;
259851
260276
  this._fileRegistry.clear();
259852
260277
  this._memexArchive.clear();
259853
260278
  this._sessionId = `session-${Date.now()}`;
260279
+ this._appState = createAppState({
260280
+ sessionId: this._sessionId,
260281
+ model: this.backend.model ?? "",
260282
+ modelTier: this.options.modelTier ?? "medium",
260283
+ contextWindowSize: this.options.contextWindowSize ?? 0,
260284
+ verbose: false
260285
+ });
260286
+ this._hookManager.runSessionHook("session_start", this._sessionId);
259854
260287
  const contextComposition = this.assembleContext(task, context);
259855
260288
  const systemPrompt = contextComposition.assembled;
259856
260289
  this.emit({
@@ -259918,6 +260351,7 @@ TASK: ${task}` : task;
259918
260351
  toolCallBudget.set(tool, budget);
259919
260352
  }
259920
260353
  for (let turn = 0; turn < this.options.maxTurns; turn++) {
260354
+ clearTurnState(this._appState);
259921
260355
  if (this._paused) {
259922
260356
  const shouldContinue = await this.waitIfPaused();
259923
260357
  if (!shouldContinue) {
@@ -260244,6 +260678,12 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
260244
260678
  totalTokens += response.usage?.totalTokens ?? 0;
260245
260679
  promptTokens += response.usage?.promptTokens ?? 0;
260246
260680
  completionTokens += response.usage?.completionTokens ?? 0;
260681
+ const turnPromptTokens = response.usage?.promptTokens ?? 0;
260682
+ const turnCompletionTokens = response.usage?.completionTokens ?? 0;
260683
+ if (turnPromptTokens || turnCompletionTokens) {
260684
+ recordTokenUsage(this._appState, turnPromptTokens, turnCompletionTokens, 0, false);
260685
+ }
260686
+ this._appState.historyLength = messages2.length;
260247
260687
  const choiceContent = response.choices[0]?.message?.content ?? "";
260248
260688
  const choiceArgs = response.choices[0]?.message?.toolCalls?.map((tc) => JSON.stringify(tc.arguments)).join("") ?? "";
260249
260689
  estimatedTokens += Math.ceil((choiceContent.length + choiceArgs.length) / 4);
@@ -260300,25 +260740,10 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
260300
260740
  function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
260301
260741
  }))
260302
260742
  });
260303
- const PARALLEL_SAFE = /* @__PURE__ */ new Set([
260304
- "file_read",
260305
- "grep_search",
260306
- "find_files",
260307
- "list_directory",
260308
- "web_fetch",
260309
- "web_search",
260310
- "web_crawl",
260311
- "memory_read",
260312
- "task_status",
260313
- "task_output",
260314
- "image_read",
260315
- "screenshot",
260316
- "ocr",
260317
- "browser_action"
260318
- ]);
260319
260743
  const executeSingle = async (tc) => {
260320
260744
  if (this.aborted)
260321
260745
  return null;
260746
+ const toolStart = performance.now();
260322
260747
  toolCallCount++;
260323
260748
  const argsKey = Object.entries(tc.arguments ?? {}).sort(([a2], [b]) => a2.localeCompare(b)).map(([k, v]) => `${k}=${typeof v === "string" ? v.slice(0, 80) : JSON.stringify(v)}`).join(",");
260324
260749
  toolCallLog.push({ name: tc.name, argsKey });
@@ -260419,10 +260844,24 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
260419
260844
  this.emit({ type: "status", content: `\u26A0\uFE0F ${warning}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
260420
260845
  pendingConstraintWarnings.push(warning);
260421
260846
  }
260422
- try {
260423
- result = await tool.execute(tc.arguments);
260424
- } catch (err) {
260425
- result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
260847
+ const hookCheck = this._hookManager.runPreToolUse(tc.name, tc.arguments, this._sessionId);
260848
+ if (!hookCheck.allowed) {
260849
+ result = { success: false, output: "", error: `Blocked by hook: ${hookCheck.reason}` };
260850
+ recordToolDecision(this._appState, {
260851
+ toolName: tc.name,
260852
+ decision: "deny",
260853
+ reason: hookCheck.reason ?? "hook",
260854
+ source: "hook"
260855
+ });
260856
+ } else {
260857
+ const finalArgs = hookCheck.modifiedArgs ?? tc.arguments;
260858
+ try {
260859
+ result = await tool.execute(finalArgs);
260860
+ this._hookManager.runPostToolUse(tc.name, finalArgs, (result.output ?? "").slice(0, 2e3), this._sessionId);
260861
+ } catch (err) {
260862
+ result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
260863
+ this._hookManager.runPostToolUseFailure(tc.name, finalArgs, result.error ?? "", this._sessionId);
260864
+ }
260426
260865
  }
260427
260866
  }
260428
260867
  }
@@ -260492,6 +260931,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
260492
260931
  });
260493
260932
  this._taskState.toolCallCount++;
260494
260933
  const filePath = typeof tc.arguments?.path === "string" ? tc.arguments.path : "";
260934
+ recordToolExecution(this._appState, tc.name, performance.now() - toolStart, result.success, filePath || void 0);
260495
260935
  if (tc.name === "file_read" || tc.name === "list_directory" || tc.name === "find_files" || tc.name === "grep_search") {
260496
260936
  this._taskState.currentStep = `exploring: ${filePath || String(tc.arguments?.pattern ?? tc.arguments?.path ?? "").slice(0, 60)}`;
260497
260937
  } else if (tc.name === "file_write" || tc.name === "file_edit" || tc.name === "batch_edit") {
@@ -260575,46 +261015,36 @@ Then use file_read on individual FILES inside it.`);
260575
261015
  }
260576
261016
  return { tc, output };
260577
261017
  };
260578
- const parallelBatch2 = [];
260579
- const sequentialBatch = [];
260580
- for (const tc of msg.toolCalls) {
260581
- const isBackgroundSubAgent = tc.name === "sub_agent" && Boolean(tc.arguments?.["background"]);
260582
- if (PARALLEL_SAFE.has(tc.name) || isBackgroundSubAgent) {
260583
- parallelBatch2.push(tc);
260584
- } else {
260585
- sequentialBatch.push(tc);
260586
- }
260587
- }
260588
- if (parallelBatch2.length > 1) {
260589
- const results = await Promise.allSettled(parallelBatch2.map((tc) => executeSingle(tc)));
260590
- for (const settled of results) {
260591
- if (settled.status === "fulfilled" && settled.value) {
260592
- const toolMsg = this.buildToolMessage(settled.value.output, settled.value.tc.id);
260593
- messages2.push(toolMsg);
260594
- }
260595
- }
260596
- } else if (parallelBatch2.length === 1) {
260597
- const r2 = await executeSingle(parallelBatch2[0]);
260598
- if (r2) {
260599
- messages2.push(this.buildToolMessage(r2.output, r2.tc.id));
260600
- }
260601
- }
260602
- for (const tc of sequentialBatch) {
261018
+ const rawToolCalls = msg.toolCalls;
261019
+ const batchToolCalls = rawToolCalls.map((tc) => ({
261020
+ name: tc.name,
261021
+ args: tc.arguments,
261022
+ id: tc.id
261023
+ }));
261024
+ const batches = partitionToolCalls(batchToolCalls);
261025
+ for (const batch2 of batches) {
260603
261026
  if (this.aborted)
260604
261027
  break;
260605
- const r2 = await executeSingle(tc);
260606
- if (r2) {
260607
- messages2.push(this.buildToolMessage(r2.output, r2.tc.id));
260608
- }
260609
- if (tc.name === "task_complete") {
260610
- completed = true;
260611
- summary = tc.arguments.summary || "";
260612
- if (summary && !this._assistantTextEmitted) {
260613
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
260614
- this._assistantTextEmitted = true;
261028
+ const results = await executeBatch(batch2, async (call) => {
261029
+ const originalTc = rawToolCalls.find((tc) => tc.id === call.id);
261030
+ return executeSingle(originalTc);
261031
+ }, 5);
261032
+ for (const r2 of results) {
261033
+ if (r2) {
261034
+ messages2.push(this.buildToolMessage(r2.output, r2.tc.id));
261035
+ if (r2.tc.name === "task_complete") {
261036
+ completed = true;
261037
+ summary = r2.tc.arguments.summary || "";
261038
+ if (summary && !this._assistantTextEmitted) {
261039
+ this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
261040
+ this._assistantTextEmitted = true;
261041
+ }
261042
+ break;
261043
+ }
260615
261044
  }
260616
- break;
260617
261045
  }
261046
+ if (completed)
261047
+ break;
260618
261048
  }
260619
261049
  if (completed)
260620
261050
  break;
@@ -260887,6 +261317,12 @@ Integrate this guidance into your current approach. Continue working on the task
260887
261317
  totalTokens += response.usage?.totalTokens ?? 0;
260888
261318
  promptTokens += response.usage?.promptTokens ?? 0;
260889
261319
  completionTokens += response.usage?.completionTokens ?? 0;
261320
+ const bfTurnPrompt = response.usage?.promptTokens ?? 0;
261321
+ const bfTurnCompletion = response.usage?.completionTokens ?? 0;
261322
+ if (bfTurnPrompt || bfTurnCompletion) {
261323
+ recordTokenUsage(this._appState, bfTurnPrompt, bfTurnCompletion, 0, false);
261324
+ }
261325
+ this._appState.historyLength = messages2.length;
260890
261326
  const choiceContent2 = response.choices[0]?.message?.content ?? "";
260891
261327
  const choiceArgs2 = response.choices[0]?.message?.toolCalls?.map((tc) => JSON.stringify(tc.arguments)).join("") ?? "";
260892
261328
  estimatedTokens += Math.ceil((choiceContent2.length + choiceArgs2.length) / 4);
@@ -261031,6 +261467,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
261031
261467
  success: completed,
261032
261468
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
261033
261469
  });
261470
+ this._hookManager.runSessionHook("session_end", this._sessionId);
261034
261471
  return { completed, turns: messages2.filter((m2) => m2.role === "assistant").length, toolCalls: toolCallCount, totalTokens, promptTokens, completionTokens, estimatedTokens, summary, durationMs };
261035
261472
  }
261036
261473
  // -------------------------------------------------------------------------
@@ -262345,7 +262782,7 @@ ${transcript}`
262345
262782
  const buffer2 = Buffer.from(rawBase64, "base64");
262346
262783
  let resizedBase64 = null;
262347
262784
  try {
262348
- const { execSync: execSync39 } = await import("node:child_process");
262785
+ const { execSync: execSync40 } = await import("node:child_process");
262349
262786
  const { writeFileSync: writeFileSync34, readFileSync: readFileSync52, unlinkSync: unlinkSync13 } = await import("node:fs");
262350
262787
  const { join: join86 } = await import("node:path");
262351
262788
  const { tmpdir: tmpdir11 } = await import("node:os");
@@ -262355,7 +262792,7 @@ ${transcript}`
262355
262792
  const pyBin = process.platform === "win32" ? "python" : "python3";
262356
262793
  const escapedIn = tmpIn.replace(/\\/g, "\\\\");
262357
262794
  const escapedOut = tmpOut.replace(/\\/g, "\\\\");
262358
- execSync39(`${pyBin} -c "from PIL import Image; img = Image.open('${escapedIn}'); img.thumbnail((512, 512), Image.LANCZOS); img = img.convert('RGB'); img.save('${escapedOut}', 'JPEG', quality=75)"`, { timeout: 1e4, stdio: "pipe" });
262795
+ execSync40(`${pyBin} -c "from PIL import Image; img = Image.open('${escapedIn}'); img.thumbnail((512, 512), Image.LANCZOS); img = img.convert('RGB'); img.save('${escapedOut}', 'JPEG', quality=75)"`, { timeout: 1e4, stdio: "pipe" });
262359
262796
  const resizedBuf = readFileSync52(tmpOut);
262360
262797
  resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
262361
262798
  try {
@@ -262409,8 +262846,8 @@ ${transcript}`
262409
262846
  if (!res.ok && model === "moondream" && res.status === 404) {
262410
262847
  this.emit({ type: "status", content: `Pulling moondream vision model...`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
262411
262848
  try {
262412
- const { execSync: execSync39 } = await import("node:child_process");
262413
- execSync39("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
262849
+ const { execSync: execSync40 } = await import("node:child_process");
262850
+ execSync40("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
262414
262851
  res = await fetch(`${ollamaHost}/api/generate`, {
262415
262852
  method: "POST",
262416
262853
  headers: { "Content-Type": "application/json" },
@@ -264502,20 +264939,6 @@ var init_self_critique = __esm({
264502
264939
  }
264503
264940
  });
264504
264941
 
264505
- // packages/orchestrator/dist/tool-batching.js
264506
- var init_tool_batching = __esm({
264507
- "packages/orchestrator/dist/tool-batching.js"() {
264508
- "use strict";
264509
- }
264510
- });
264511
-
264512
- // packages/orchestrator/dist/hooks.js
264513
- var init_hooks = __esm({
264514
- "packages/orchestrator/dist/hooks.js"() {
264515
- "use strict";
264516
- }
264517
- });
264518
-
264519
264942
  // packages/orchestrator/dist/skill-fork.js
264520
264943
  var init_skill_fork = __esm({
264521
264944
  "packages/orchestrator/dist/skill-fork.js"() {
@@ -264563,6 +264986,7 @@ var init_dist7 = __esm({
264563
264986
  init_hooks();
264564
264987
  init_skill_fork();
264565
264988
  init_streaming_executor();
264989
+ init_app_state();
264566
264990
  }
264567
264991
  });
264568
264992
 
@@ -264577,7 +265001,7 @@ __export(listen_exports, {
264577
265001
  isVideoPath: () => isVideoPath,
264578
265002
  waitForTranscribeCli: () => waitForTranscribeCli
264579
265003
  });
264580
- import { spawn as spawn17, execSync as execSync27 } from "node:child_process";
265004
+ import { spawn as spawn17, execSync as execSync28 } from "node:child_process";
264581
265005
  import { existsSync as existsSync37, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readdirSync as readdirSync9 } from "node:fs";
264582
265006
  import { join as join53, dirname as dirname15 } from "node:path";
264583
265007
  import { homedir as homedir14 } from "node:os";
@@ -264599,7 +265023,7 @@ function findMicCaptureCommand() {
264599
265023
  const platform6 = process.platform;
264600
265024
  if (platform6 === "linux") {
264601
265025
  try {
264602
- execSync27("which arecord", { stdio: "pipe" });
265026
+ execSync28("which arecord", { stdio: "pipe" });
264603
265027
  return {
264604
265028
  cmd: "arecord",
264605
265029
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -264609,7 +265033,7 @@ function findMicCaptureCommand() {
264609
265033
  }
264610
265034
  if (platform6 === "darwin") {
264611
265035
  try {
264612
- execSync27("which sox", { stdio: "pipe" });
265036
+ execSync28("which sox", { stdio: "pipe" });
264613
265037
  return {
264614
265038
  cmd: "sox",
264615
265039
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -264618,7 +265042,7 @@ function findMicCaptureCommand() {
264618
265042
  }
264619
265043
  }
264620
265044
  try {
264621
- execSync27("which ffmpeg", { stdio: "pipe" });
265045
+ execSync28("which ffmpeg", { stdio: "pipe" });
264622
265046
  if (platform6 === "linux") {
264623
265047
  return {
264624
265048
  cmd: "ffmpeg",
@@ -264677,7 +265101,7 @@ function findLiveWhisperScript() {
264677
265101
  return p2;
264678
265102
  }
264679
265103
  try {
264680
- const globalRoot = execSync27("npm root -g", {
265104
+ const globalRoot = execSync28("npm root -g", {
264681
265105
  encoding: "utf-8",
264682
265106
  timeout: 5e3,
264683
265107
  stdio: ["pipe", "pipe", "pipe"]
@@ -264710,7 +265134,7 @@ function ensureTranscribeCliBackground() {
264710
265134
  return;
264711
265135
  _bgInstallPromise = (async () => {
264712
265136
  try {
264713
- const globalRoot = execSync27("npm root -g", {
265137
+ const globalRoot = execSync28("npm root -g", {
264714
265138
  encoding: "utf-8",
264715
265139
  timeout: 5e3,
264716
265140
  stdio: ["pipe", "pipe", "pipe"]
@@ -264916,7 +265340,7 @@ var init_listen = __esm({
264916
265340
  }
264917
265341
  if (!this.transcribeCliAvailable) {
264918
265342
  try {
264919
- execSync27("which transcribe-cli", { stdio: "pipe" });
265343
+ execSync28("which transcribe-cli", { stdio: "pipe" });
264920
265344
  this.transcribeCliAvailable = true;
264921
265345
  } catch {
264922
265346
  this.transcribeCliAvailable = false;
@@ -264933,7 +265357,7 @@ var init_listen = __esm({
264933
265357
  } catch {
264934
265358
  }
264935
265359
  try {
264936
- const globalRoot = execSync27("npm root -g", {
265360
+ const globalRoot = execSync28("npm root -g", {
264937
265361
  encoding: "utf-8",
264938
265362
  timeout: 5e3,
264939
265363
  stdio: ["pipe", "pipe", "pipe"]
@@ -264983,7 +265407,7 @@ var init_listen = __esm({
264983
265407
  }
264984
265408
  if (!tc) {
264985
265409
  try {
264986
- execSync27("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
265410
+ execSync28("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
264987
265411
  this.transcribeCliAvailable = null;
264988
265412
  tc = await this.loadTranscribeCli();
264989
265413
  } catch {
@@ -265166,7 +265590,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
265166
265590
  }
265167
265591
  if (!tc) {
265168
265592
  try {
265169
- execSync27("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
265593
+ execSync28("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
265170
265594
  this.transcribeCliAvailable = null;
265171
265595
  tc = await this.loadTranscribeCli();
265172
265596
  } catch {
@@ -265220,7 +265644,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
265220
265644
  }
265221
265645
  if (!tc) {
265222
265646
  try {
265223
- execSync27("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
265647
+ execSync28("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
265224
265648
  this.transcribeCliAvailable = null;
265225
265649
  tc = await this.loadTranscribeCli();
265226
265650
  } catch {
@@ -269734,7 +270158,7 @@ var init_render = __esm({
269734
270158
 
269735
270159
  // packages/cli/dist/tui/voice-session.js
269736
270160
  import { createServer as createServer3 } from "node:http";
269737
- import { spawn as spawn18, execSync as execSync28 } from "node:child_process";
270161
+ import { spawn as spawn18, execSync as execSync29 } from "node:child_process";
269738
270162
  import { EventEmitter as EventEmitter4 } from "node:events";
269739
270163
  function generateFrontendHTML() {
269740
270164
  return `<!DOCTYPE html>
@@ -275759,7 +276183,7 @@ __export(personaplex_exports, {
275759
276183
  import { existsSync as existsSync42, writeFileSync as writeFileSync18, readFileSync as readFileSync32, mkdirSync as mkdirSync17, copyFileSync as copyFileSync2, readdirSync as readdirSync12, statSync as statSync13 } from "node:fs";
275760
276184
  import { join as join59, dirname as dirname19 } from "node:path";
275761
276185
  import { homedir as homedir16 } from "node:os";
275762
- import { execSync as execSync29, spawn as spawn20, execFile as execFile7 } from "node:child_process";
276186
+ import { execSync as execSync30, spawn as spawn20, execFile as execFile7 } from "node:child_process";
275763
276187
  import { fileURLToPath as fileURLToPath12 } from "node:url";
275764
276188
  function execAsync(cmd, opts = {}) {
275765
276189
  return new Promise((resolve39, reject) => {
@@ -275796,7 +276220,7 @@ function detectJetson() {
275796
276220
  try {
275797
276221
  const model = readFileSync32("/proc/device-tree/model", "utf8").replace(/\0/g, "").trim();
275798
276222
  if (/jetson|orin|tegra/i.test(model)) {
275799
- const memInfo = execSync29("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
276223
+ const memInfo = execSync30("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
275800
276224
  const memKB = parseInt(memInfo.match(/(\d+)/)?.[1] ?? "0", 10);
275801
276225
  return { isJetson: true, model, totalMemGB: memKB / 1024 / 1024 };
275802
276226
  }
@@ -275831,7 +276255,7 @@ function detectPersonaPlexCapability() {
275831
276255
  };
275832
276256
  }
275833
276257
  try {
275834
- const nvsmi = execSync29("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
276258
+ const nvsmi = execSync30("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
275835
276259
  encoding: "utf8",
275836
276260
  timeout: 5e3,
275837
276261
  stdio: "pipe"
@@ -275844,7 +276268,7 @@ function detectPersonaPlexCapability() {
275844
276268
  return { ...fail(`GPU has ${vramGB.toFixed(1)}GB VRAM (need \u22658GB)`), gpuName: gpuName ?? "", vramGB };
275845
276269
  }
275846
276270
  try {
275847
- execSync29('python3 -c "import torch; assert torch.cuda.is_available()"', {
276271
+ execSync30('python3 -c "import torch; assert torch.cuda.is_available()"', {
275848
276272
  timeout: 1e4,
275849
276273
  stdio: "pipe"
275850
276274
  });
@@ -275921,7 +276345,7 @@ async function installPersonaPlex(onInfo, weightTier) {
275921
276345
  mkdirSync17(PERSONAPLEX_DIR, { recursive: true });
275922
276346
  let arch2 = "";
275923
276347
  try {
275924
- arch2 = execSync29("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
276348
+ arch2 = execSync30("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
275925
276349
  } catch {
275926
276350
  }
275927
276351
  const isAarch64 = arch2 === "aarch64" || arch2 === "arm64";
@@ -275943,16 +276367,16 @@ async function installPersonaPlex(onInfo, weightTier) {
275943
276367
  log22("Checking system dependencies (libopus)...");
275944
276368
  try {
275945
276369
  if (process.platform === "linux") {
275946
- execSync29("dpkg -l libopus-dev 2>/dev/null || sudo apt-get install -y libopus-dev", { timeout: 3e4, stdio: "pipe" });
276370
+ execSync30("dpkg -l libopus-dev 2>/dev/null || sudo apt-get install -y libopus-dev", { timeout: 3e4, stdio: "pipe" });
275947
276371
  } else if (process.platform === "darwin") {
275948
- execSync29("brew list opus 2>/dev/null || brew install opus", { timeout: 6e4, stdio: "pipe" });
276372
+ execSync30("brew list opus 2>/dev/null || brew install opus", { timeout: 6e4, stdio: "pipe" });
275949
276373
  }
275950
276374
  } catch {
275951
276375
  }
275952
276376
  if (isAarch64) {
275953
276377
  log22("ARM64: Checking Rust toolchain for sphn build...");
275954
276378
  try {
275955
- execSync29("rustc --version", { timeout: 5e3, stdio: "pipe" });
276379
+ execSync30("rustc --version", { timeout: 5e3, stdio: "pipe" });
275956
276380
  } catch {
275957
276381
  log22("ARM64: Installing Rust toolchain (needed for sphn audio codec)...");
275958
276382
  try {
@@ -276009,7 +276433,7 @@ async function installPersonaPlex(onInfo, weightTier) {
276009
276433
  }
276010
276434
  const serverPy = join59(venvDir, "lib", `python3.${process.versions.node ? "12" : "10"}`, "site-packages", "moshi", "server.py");
276011
276435
  try {
276012
- const sitePackages = execSync29(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
276436
+ const sitePackages = execSync30(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
276013
276437
  encoding: "utf8",
276014
276438
  timeout: 5e3,
276015
276439
  stdio: "pipe"
@@ -276026,7 +276450,7 @@ async function installPersonaPlex(onInfo, weightTier) {
276026
276450
  } catch {
276027
276451
  }
276028
276452
  try {
276029
- const sitePackages = execSync29(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
276453
+ const sitePackages = execSync30(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
276030
276454
  encoding: "utf8",
276031
276455
  timeout: 5e3,
276032
276456
  stdio: "pipe"
@@ -276124,7 +276548,7 @@ $2if filename.endswith(".safetensors"):`);
276124
276548
  } catch {
276125
276549
  }
276126
276550
  try {
276127
- const sitePackages2 = execSync29(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
276551
+ const sitePackages2 = execSync30(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
276128
276552
  encoding: "utf8",
276129
276553
  timeout: 5e3,
276130
276554
  stdio: "pipe"
@@ -276253,11 +276677,11 @@ async function startPersonaPlexDaemon(onInfo) {
276253
276677
  if (tier === "nf4-distilled") {
276254
276678
  log22(`Weight tier: ${tier} \u2014 distilled NF4 (90% token match, ${repoInfo.sizeGB}GB)...`);
276255
276679
  try {
276256
- const weightPath = execSync29(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}', token=False))"`, { encoding: "utf8", timeout: 6e4, stdio: "pipe" }).trim();
276680
+ const weightPath = execSync30(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}', token=False))"`, { encoding: "utf8", timeout: 6e4, stdio: "pipe" }).trim();
276257
276681
  if (existsSync42(weightPath)) {
276258
276682
  if (!existsSync42(cachedBf16)) {
276259
276683
  log22("Converting .pt checkpoint to safetensors (one-time)...");
276260
- execSync29(`"${venvPython2}" -c "
276684
+ execSync30(`"${venvPython2}" -c "
276261
276685
  import torch; from safetensors.torch import save_file
276262
276686
  state = torch.load('${weightPath}', map_location='cpu', weights_only=True)
276263
276687
  state = {k: v.to(torch.bfloat16) if v.is_floating_point() else v for k, v in state.items()}
@@ -276287,10 +276711,10 @@ print('Converted')
276287
276711
  }
276288
276712
  }
276289
276713
  try {
276290
- const weightPath = execSync29(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
276714
+ const weightPath = execSync30(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
276291
276715
  if (existsSync42(dequantScript) && existsSync42(weightPath)) {
276292
276716
  try {
276293
- execSync29(`"${venvPython2}" "${dequantScript}" --input "${weightPath}" --output "${cachedBf16}"`, { timeout: 3e5, stdio: "pipe" });
276717
+ execSync30(`"${venvPython2}" "${dequantScript}" --input "${weightPath}" --output "${cachedBf16}"`, { timeout: 3e5, stdio: "pipe" });
276294
276718
  if (existsSync42(cachedBf16)) {
276295
276719
  extraArgs.push("--moshi-weight", cachedBf16);
276296
276720
  log22(`Using dequantized cache: ${(statSync13(cachedBf16).size / 1024 ** 3).toFixed(1)}GB`);
@@ -276300,13 +276724,13 @@ print('Converted')
276300
276724
  }
276301
276725
  }
276302
276726
  try {
276303
- const mimiPath = execSync29(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer-e351c8d8-checkpoint125.safetensors', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
276727
+ const mimiPath = execSync30(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer-e351c8d8-checkpoint125.safetensors', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
276304
276728
  if (existsSync42(mimiPath))
276305
276729
  extraArgs.push("--mimi-weight", mimiPath);
276306
276730
  } catch {
276307
276731
  }
276308
276732
  try {
276309
- const tokPath = execSync29(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer_spm_32k_3.model', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
276733
+ const tokPath = execSync30(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer_spm_32k_3.model', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
276310
276734
  if (existsSync42(tokPath))
276311
276735
  extraArgs.push("--tokenizer", tokPath);
276312
276736
  } catch {
@@ -276330,7 +276754,7 @@ print('Converted')
276330
276754
  if (!ollamaModel)
276331
276755
  ollamaModel = "qwen3.5:4b";
276332
276756
  try {
276333
- const ollamaCheck = execSync29("curl -s http://localhost:11434/api/tags", {
276757
+ const ollamaCheck = execSync30("curl -s http://localhost:11434/api/tags", {
276334
276758
  timeout: 3e3,
276335
276759
  stdio: "pipe",
276336
276760
  encoding: "utf8"
@@ -276407,7 +276831,7 @@ print('Converted')
276407
276831
  return null;
276408
276832
  }
276409
276833
  try {
276410
- execSync29(`curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1:${PORT}/`, {
276834
+ execSync30(`curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1:${PORT}/`, {
276411
276835
  timeout: 3e3,
276412
276836
  stdio: "pipe",
276413
276837
  encoding: "utf8"
@@ -276433,7 +276857,7 @@ function stopPersonaPlex() {
276433
276857
  return;
276434
276858
  try {
276435
276859
  if (process.platform === "win32") {
276436
- execSync29(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
276860
+ execSync30(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
276437
276861
  } else {
276438
276862
  process.kill(pid, "SIGTERM");
276439
276863
  }
@@ -276747,7 +277171,7 @@ __export(setup_exports, {
276747
277171
  updateOllama: () => updateOllama
276748
277172
  });
276749
277173
  import * as readline from "node:readline";
276750
- import { execSync as execSync30, spawn as spawn21, exec as exec2 } from "node:child_process";
277174
+ import { execSync as execSync31, spawn as spawn21, exec as exec2 } from "node:child_process";
276751
277175
  import { promisify as promisify7 } from "node:util";
276752
277176
  import { existsSync as existsSync43, writeFileSync as writeFileSync19, readFileSync as readFileSync33, appendFileSync as appendFileSync2, mkdirSync as mkdirSync18 } from "node:fs";
276753
277177
  import { join as join60 } from "node:path";
@@ -276786,7 +277210,7 @@ function detectSystemSpecs() {
276786
277210
  let gpuVramGB = 0;
276787
277211
  let gpuName = "";
276788
277212
  try {
276789
- const memInfo = execSync30("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
277213
+ const memInfo = execSync31("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
276790
277214
  encoding: "utf8",
276791
277215
  timeout: 5e3
276792
277216
  });
@@ -276806,7 +277230,7 @@ function detectSystemSpecs() {
276806
277230
  } catch {
276807
277231
  }
276808
277232
  try {
276809
- const nvidiaSmi = execSync30("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
277233
+ const nvidiaSmi = execSync31("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
276810
277234
  const lines = nvidiaSmi.trim().split("\n");
276811
277235
  if (lines.length > 0) {
276812
277236
  for (const line of lines) {
@@ -276977,7 +277401,7 @@ function ensureCurl() {
276977
277401
  for (const s2 of strategies) {
276978
277402
  if (hasCmd(s2.check)) {
276979
277403
  try {
276980
- execSync30(s2.install, { stdio: "inherit", timeout: 12e4 });
277404
+ execSync31(s2.install, { stdio: "inherit", timeout: 12e4 });
276981
277405
  if (hasCmd("curl")) {
276982
277406
  process.stdout.write(` ${c3.green("\u2714")} curl installed via ${s2.label}.
276983
277407
  `);
@@ -276991,7 +277415,7 @@ function ensureCurl() {
276991
277415
  }
276992
277416
  if (plat === "darwin") {
276993
277417
  try {
276994
- execSync30("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
277418
+ execSync31("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
276995
277419
  if (hasCmd("curl"))
276996
277420
  return true;
276997
277421
  } catch {
@@ -277026,7 +277450,7 @@ function installOllamaLinux() {
277026
277450
 
277027
277451
  `);
277028
277452
  try {
277029
- execSync30("curl -fsSL https://ollama.com/install.sh | sh", {
277453
+ execSync31("curl -fsSL https://ollama.com/install.sh | sh", {
277030
277454
  stdio: "inherit",
277031
277455
  timeout: 3e5
277032
277456
  });
@@ -277054,7 +277478,7 @@ async function installOllamaMac(_rl) {
277054
277478
 
277055
277479
  `);
277056
277480
  try {
277057
- execSync30('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
277481
+ execSync31('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
277058
277482
  if (!hasCmd("brew")) {
277059
277483
  try {
277060
277484
  const brewPrefix = existsSync43("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
@@ -277087,7 +277511,7 @@ async function installOllamaMac(_rl) {
277087
277511
 
277088
277512
  `);
277089
277513
  try {
277090
- execSync30("brew install ollama", {
277514
+ execSync31("brew install ollama", {
277091
277515
  stdio: "inherit",
277092
277516
  timeout: 3e5
277093
277517
  });
@@ -277114,7 +277538,7 @@ function installOllamaWindows() {
277114
277538
 
277115
277539
  `);
277116
277540
  try {
277117
- execSync30('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
277541
+ execSync31('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
277118
277542
  stdio: "inherit",
277119
277543
  timeout: 3e5
277120
277544
  });
@@ -277195,7 +277619,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
277195
277619
  }
277196
277620
  function getOllamaVersion() {
277197
277621
  try {
277198
- const out = execSync30("ollama --version", { encoding: "utf8", timeout: 5e3 });
277622
+ const out = execSync31("ollama --version", { encoding: "utf8", timeout: 5e3 });
277199
277623
  const match = out.match(/(\d+\.\d+\.\d+)/);
277200
277624
  return match ? match[1] : null;
277201
277625
  } catch {
@@ -277246,7 +277670,7 @@ function updateOllama() {
277246
277670
  return false;
277247
277671
  }
277248
277672
  try {
277249
- execSync30("curl -fsSL https://ollama.com/install.sh | sh", {
277673
+ execSync31("curl -fsSL https://ollama.com/install.sh | sh", {
277250
277674
  stdio: "inherit",
277251
277675
  timeout: 3e5
277252
277676
  });
@@ -277257,7 +277681,7 @@ function updateOllama() {
277257
277681
  }
277258
277682
  function pullModelWithAutoUpdate(tag) {
277259
277683
  try {
277260
- execSync30(`ollama pull ${tag}`, {
277684
+ execSync31(`ollama pull ${tag}`, {
277261
277685
  stdio: "inherit",
277262
277686
  timeout: 36e5
277263
277687
  // 1 hour max
@@ -277277,7 +277701,7 @@ function pullModelWithAutoUpdate(tag) {
277277
277701
 
277278
277702
  `);
277279
277703
  try {
277280
- execSync30("curl -fsSL https://ollama.com/install.sh | sh", {
277704
+ execSync31("curl -fsSL https://ollama.com/install.sh | sh", {
277281
277705
  stdio: "inherit",
277282
277706
  timeout: 3e5
277283
277707
  // 5 min max for install
@@ -277288,7 +277712,7 @@ function pullModelWithAutoUpdate(tag) {
277288
277712
  process.stdout.write(` ${c3.cyan("\u25CF")} Retrying pull of ${c3.bold(tag)}...
277289
277713
 
277290
277714
  `);
277291
- execSync30(`ollama pull ${tag}`, {
277715
+ execSync31(`ollama pull ${tag}`, {
277292
277716
  stdio: "inherit",
277293
277717
  timeout: 36e5
277294
277718
  });
@@ -277390,7 +277814,7 @@ function ensurePython3() {
277390
277814
  if (plat === "darwin") {
277391
277815
  if (hasCmd("brew")) {
277392
277816
  try {
277393
- execSync30("brew install python3", { stdio: "inherit", timeout: 3e5 });
277817
+ execSync31("brew install python3", { stdio: "inherit", timeout: 3e5 });
277394
277818
  if (hasCmd("python3")) {
277395
277819
  process.stdout.write(` ${c3.green("\u2714")} Python3 installed via Homebrew.
277396
277820
  `);
@@ -277403,7 +277827,7 @@ function ensurePython3() {
277403
277827
  for (const s2 of strategies) {
277404
277828
  if (hasCmd(s2.check)) {
277405
277829
  try {
277406
- execSync30(s2.install, { stdio: "inherit", timeout: 12e4 });
277830
+ execSync31(s2.install, { stdio: "inherit", timeout: 12e4 });
277407
277831
  if (hasCmd("python3") || hasCmd("python")) {
277408
277832
  process.stdout.write(` ${c3.green("\u2714")} Python3 installed via ${s2.label}.
277409
277833
  `);
@@ -277419,11 +277843,11 @@ function ensurePython3() {
277419
277843
  }
277420
277844
  function checkPythonVenv() {
277421
277845
  try {
277422
- execSync30("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
277846
+ execSync31("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
277423
277847
  return true;
277424
277848
  } catch {
277425
277849
  try {
277426
- execSync30("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
277850
+ execSync31("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
277427
277851
  return true;
277428
277852
  } catch {
277429
277853
  return false;
@@ -277442,7 +277866,7 @@ function ensurePythonVenv() {
277442
277866
  for (const s2 of strategies) {
277443
277867
  if (hasCmd(s2.check)) {
277444
277868
  try {
277445
- execSync30(s2.install, { stdio: "inherit", timeout: 12e4 });
277869
+ execSync31(s2.install, { stdio: "inherit", timeout: 12e4 });
277446
277870
  if (checkPythonVenv()) {
277447
277871
  process.stdout.write(` ${c3.green("\u2714")} python3-venv installed via ${s2.label}.
277448
277872
  `);
@@ -277869,7 +278293,7 @@ async function doSetup(config, rl) {
277869
278293
  const modelfilePath = join60(modelDir2, `Modelfile.${customName}`);
277870
278294
  writeFileSync19(modelfilePath, modelfileContent + "\n", "utf8");
277871
278295
  process.stdout.write(` ${c3.dim("Creating model...")} `);
277872
- execSync30(`ollama create ${customName} -f ${modelfilePath}`, {
278296
+ execSync31(`ollama create ${customName} -f ${modelfilePath}`, {
277873
278297
  stdio: "pipe",
277874
278298
  timeout: 12e4
277875
278299
  });
@@ -277920,7 +278344,7 @@ function isFirstRun() {
277920
278344
  function hasCmd(cmd) {
277921
278345
  try {
277922
278346
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
277923
- execSync30(whichCmd, { stdio: "pipe", timeout: 3e3 });
278347
+ execSync31(whichCmd, { stdio: "pipe", timeout: 3e3 });
277924
278348
  return true;
277925
278349
  } catch {
277926
278350
  return false;
@@ -277934,7 +278358,7 @@ function detectPkgManager() {
277934
278358
  if (hasCmd("winget"))
277935
278359
  return "winget";
277936
278360
  try {
277937
- execSync30(`powershell -NoProfile -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"`, { stdio: "pipe", timeout: 12e4 });
278361
+ execSync31(`powershell -NoProfile -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"`, { stdio: "pipe", timeout: 12e4 });
277938
278362
  if (hasCmd("choco"))
277939
278363
  return "choco";
277940
278364
  } catch {
@@ -277945,7 +278369,7 @@ function detectPkgManager() {
277945
278369
  if (hasCmd("brew"))
277946
278370
  return "brew";
277947
278371
  try {
277948
- execSync30('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "pipe", timeout: 3e5, env: { ...process.env, NONINTERACTIVE: "1" } });
278372
+ execSync31('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "pipe", timeout: 3e5, env: { ...process.env, NONINTERACTIVE: "1" } });
277949
278373
  if (hasCmd("brew"))
277950
278374
  return "brew";
277951
278375
  } catch {
@@ -277967,7 +278391,7 @@ function getVenvDir() {
277967
278391
  }
277968
278392
  function hasVenvModule() {
277969
278393
  try {
277970
- execSync30("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
278394
+ execSync31("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
277971
278395
  return true;
277972
278396
  } catch {
277973
278397
  return false;
@@ -277992,8 +278416,8 @@ function ensureVenv(log22) {
277992
278416
  try {
277993
278417
  mkdirSync18(join60(homedir17(), ".open-agents"), { recursive: true });
277994
278418
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
277995
- execSync30(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
277996
- execSync30(`"${pipPath}" install --upgrade pip`, {
278419
+ execSync31(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
278420
+ execSync31(`"${pipPath}" install --upgrade pip`, {
277997
278421
  stdio: "pipe",
277998
278422
  timeout: 6e4
277999
278423
  });
@@ -278006,7 +278430,7 @@ function ensureVenv(log22) {
278006
278430
  }
278007
278431
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
278008
278432
  try {
278009
- execSync30(`sudo -n ${cmd}`, {
278433
+ execSync31(`sudo -n ${cmd}`, {
278010
278434
  stdio: "pipe",
278011
278435
  timeout: timeoutMs,
278012
278436
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -278019,7 +278443,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
278019
278443
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
278020
278444
  try {
278021
278445
  const escaped = cmd.replace(/'/g, "'\\''");
278022
- execSync30(`sudo -S bash -c '${escaped}'`, {
278446
+ execSync31(`sudo -S bash -c '${escaped}'`, {
278023
278447
  input: password + "\n",
278024
278448
  stdio: ["pipe", "pipe", "pipe"],
278025
278449
  timeout: timeoutMs,
@@ -278122,7 +278546,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278122
278546
  let winNeedsElevation = false;
278123
278547
  if (process.platform === "win32") {
278124
278548
  try {
278125
- execSync30("net session", { stdio: "pipe", timeout: 3e3 });
278549
+ execSync31("net session", { stdio: "pipe", timeout: 3e3 });
278126
278550
  } catch {
278127
278551
  winNeedsElevation = true;
278128
278552
  log22(`Installing ${labels} via ${pm2} (requires admin \u2014 UAC prompt will appear)...`);
@@ -278170,9 +278594,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278170
278594
  if (needsSudo) {
278171
278595
  await sudoInstall(installCmd, getPassword, log22, cachedPasswordRef, 18e4);
278172
278596
  } else if (winNeedsElevation) {
278173
- execSync30(`powershell -NoProfile -Command "Start-Process -FilePath 'cmd.exe' -ArgumentList '/c ${installCmd.replace(/'/g, "''")}' -Verb RunAs -Wait"`, { stdio: "pipe", timeout: 18e4 });
278597
+ execSync31(`powershell -NoProfile -Command "Start-Process -FilePath 'cmd.exe' -ArgumentList '/c ${installCmd.replace(/'/g, "''")}' -Verb RunAs -Wait"`, { stdio: "pipe", timeout: 18e4 });
278174
278598
  } else {
278175
- execSync30(installCmd, { stdio: "pipe", timeout: 18e4 });
278599
+ execSync31(installCmd, { stdio: "pipe", timeout: 18e4 });
278176
278600
  }
278177
278601
  } catch (e2) {
278178
278602
  const stderr = e2.stderr?.toString?.()?.trim?.() ?? "";
@@ -278186,7 +278610,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278186
278610
  if (!hasCmd(d2.binary) && pipPkg) {
278187
278611
  try {
278188
278612
  const pipCmd = process.platform === "win32" ? `pip install ${pipPkg}` : `pip3 install ${pipPkg}`;
278189
- execSync30(pipCmd, { stdio: "pipe", timeout: 12e4 });
278613
+ execSync31(pipCmd, { stdio: "pipe", timeout: 12e4 });
278190
278614
  lastError = "";
278191
278615
  } catch (e2) {
278192
278616
  const stderr = e2.stderr?.toString?.()?.trim?.() ?? "";
@@ -278198,7 +278622,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278198
278622
  }
278199
278623
  if (process.platform === "win32" && !hasCmd(d2.binary)) {
278200
278624
  try {
278201
- const freshPath = execSync30(`powershell -NoProfile -Command "[System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path','User')"`, { encoding: "utf8", timeout: 5e3, stdio: "pipe" }).trim();
278625
+ const freshPath = execSync31(`powershell -NoProfile -Command "[System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path','User')"`, { encoding: "utf8", timeout: 5e3, stdio: "pipe" }).trim();
278202
278626
  if (freshPath)
278203
278627
  process.env.PATH = freshPath;
278204
278628
  } catch {
@@ -278242,7 +278666,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278242
278666
  const venvCmds = {
278243
278667
  apt: () => {
278244
278668
  try {
278245
- const pyVer = execSync30(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
278669
+ const pyVer = execSync31(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
278246
278670
  return `apt-get install -y python3-venv python${pyVer}-venv`;
278247
278671
  } catch {
278248
278672
  return "apt-get install -y python3-venv";
@@ -278271,12 +278695,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278271
278695
  const venvPip2 = join60(venvBin, "pip");
278272
278696
  log22("Installing moondream-station in ~/.open-agents/venv...");
278273
278697
  try {
278274
- execSync30(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
278698
+ execSync31(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
278275
278699
  if (existsSync43(venvMoondream)) {
278276
278700
  log22("moondream-station installed successfully.");
278277
278701
  } else {
278278
278702
  try {
278279
- const check = execSync30(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
278703
+ const check = execSync31(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
278280
278704
  if (check.includes("moondream")) {
278281
278705
  log22("moondream-station package installed.");
278282
278706
  }
@@ -278293,7 +278717,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278293
278717
  const venvPip2 = join60(venvBin, isWin2 ? "pip.exe" : "pip");
278294
278718
  let ocrStackInstalled = false;
278295
278719
  try {
278296
- execSync30(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
278720
+ execSync31(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
278297
278721
  ocrStackInstalled = true;
278298
278722
  } catch {
278299
278723
  }
@@ -278301,9 +278725,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
278301
278725
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
278302
278726
  log22("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
278303
278727
  try {
278304
- execSync30(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
278728
+ execSync31(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
278305
278729
  try {
278306
- execSync30(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
278730
+ execSync31(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
278307
278731
  log22("OCR Python stack installed successfully.");
278308
278732
  } catch {
278309
278733
  log22("OCR Python stack install completed but import verification failed.");
@@ -278337,7 +278761,7 @@ function ensureCloudflaredBackground(onInfo) {
278337
278761
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
278338
278762
  const cfArch = archMap[arch2] ?? "amd64";
278339
278763
  try {
278340
- execSync30(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir17()}/.local/bin" && mv /tmp/cloudflared "${homedir17()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
278764
+ execSync31(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir17()}/.local/bin" && mv /tmp/cloudflared "${homedir17()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
278341
278765
  if (!process.env.PATH?.includes(`${homedir17()}/.local/bin`)) {
278342
278766
  process.env.PATH = `${homedir17()}/.local/bin:${process.env.PATH}`;
278343
278767
  }
@@ -278348,7 +278772,7 @@ function ensureCloudflaredBackground(onInfo) {
278348
278772
  } catch {
278349
278773
  }
278350
278774
  try {
278351
- execSync30(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
278775
+ execSync31(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
278352
278776
  if (hasCmd("cloudflared")) {
278353
278777
  log22("cloudflared installed.");
278354
278778
  return true;
@@ -278357,7 +278781,7 @@ function ensureCloudflaredBackground(onInfo) {
278357
278781
  }
278358
278782
  } else if (os8 === "darwin") {
278359
278783
  try {
278360
- execSync30("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
278784
+ execSync31("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
278361
278785
  if (hasCmd("cloudflared")) {
278362
278786
  log22("cloudflared installed via Homebrew.");
278363
278787
  return true;
@@ -278445,7 +278869,7 @@ function createExpandedVariant(baseModel, specs, sizeGB, kvBytesPerToken, archMa
278445
278869
  mkdirSync18(modelDir2, { recursive: true });
278446
278870
  const modelfilePath = join60(modelDir2, `Modelfile.${customName}`);
278447
278871
  writeFileSync19(modelfilePath, modelfileContent + "\n", "utf8");
278448
- execSync30(`ollama create ${customName} -f ${modelfilePath}`, {
278872
+ execSync31(`ollama create ${customName} -f ${modelfilePath}`, {
278449
278873
  stdio: "pipe",
278450
278874
  timeout: 12e4
278451
278875
  });
@@ -278531,7 +278955,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
278531
278955
  }
278532
278956
  async function ensureNeovim() {
278533
278957
  try {
278534
- const nvimPath = execSync30("which nvim 2>/dev/null || where nvim 2>nul", {
278958
+ const nvimPath = execSync31("which nvim 2>/dev/null || where nvim 2>nul", {
278535
278959
  encoding: "utf8",
278536
278960
  stdio: "pipe",
278537
278961
  timeout: 5e3
@@ -278553,14 +278977,14 @@ async function ensureNeovim() {
278553
278977
  const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
278554
278978
  console.log(` Downloading Neovim (${appImageName})...`);
278555
278979
  try {
278556
- execSync30(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
278557
- execSync30(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
278980
+ execSync31(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
278981
+ execSync31(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
278558
278982
  } catch (err) {
278559
278983
  console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
278560
278984
  return null;
278561
278985
  }
278562
278986
  try {
278563
- const ver = execSync30(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
278987
+ const ver = execSync31(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
278564
278988
  console.log(` Installed: ${ver}`);
278565
278989
  } catch {
278566
278990
  console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
@@ -278575,8 +278999,8 @@ async function ensureNeovim() {
278575
278999
  if (hasCmd("brew")) {
278576
279000
  console.log(" Installing Neovim via Homebrew...");
278577
279001
  try {
278578
- execSync30("brew install neovim", { stdio: "inherit", timeout: 12e4 });
278579
- const nvimPath = execSync30("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
279002
+ execSync31("brew install neovim", { stdio: "inherit", timeout: 12e4 });
279003
+ const nvimPath = execSync31("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
278580
279004
  return nvimPath || null;
278581
279005
  } catch {
278582
279006
  console.log(" brew install neovim failed.");
@@ -278590,7 +279014,7 @@ async function ensureNeovim() {
278590
279014
  if (hasCmd("choco")) {
278591
279015
  console.log(" Installing Neovim via Chocolatey...");
278592
279016
  try {
278593
- execSync30("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
279017
+ execSync31("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
278594
279018
  return "nvim";
278595
279019
  } catch {
278596
279020
  console.log(" choco install neovim failed.");
@@ -278599,7 +279023,7 @@ async function ensureNeovim() {
278599
279023
  if (hasCmd("winget")) {
278600
279024
  console.log(" Installing Neovim via winget...");
278601
279025
  try {
278602
- execSync30("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
279026
+ execSync31("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
278603
279027
  stdio: "inherit",
278604
279028
  timeout: 12e4
278605
279029
  });
@@ -278845,7 +279269,7 @@ var init_drop_panel = __esm({
278845
279269
  import { existsSync as existsSync45, unlinkSync as unlinkSync8 } from "node:fs";
278846
279270
  import { tmpdir as tmpdir8 } from "node:os";
278847
279271
  import { join as join61 } from "node:path";
278848
- import { execSync as execSync31 } from "node:child_process";
279272
+ import { execSync as execSync32 } from "node:child_process";
278849
279273
  function isNeovimActive() {
278850
279274
  return _state !== null && !_state.cleanedUp;
278851
279275
  }
@@ -278863,7 +279287,7 @@ async function startNeovimMode(opts) {
278863
279287
  }
278864
279288
  let nvimPath;
278865
279289
  try {
278866
- nvimPath = execSync31("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
279290
+ nvimPath = execSync32("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
278867
279291
  if (!nvimPath)
278868
279292
  throw new Error();
278869
279293
  } catch {
@@ -280626,7 +281050,7 @@ __export(voice_exports, {
280626
281050
  import { existsSync as existsSync47, mkdirSync as mkdirSync20, writeFileSync as writeFileSync21, readFileSync as readFileSync35, unlinkSync as unlinkSync9, readdirSync as readdirSync13, renameSync, statSync as statSync14 } from "node:fs";
280627
281051
  import { join as join63, dirname as dirname20 } from "node:path";
280628
281052
  import { homedir as homedir18, tmpdir as tmpdir9, platform as platform3 } from "node:os";
280629
- import { execSync as execSync32, spawn as nodeSpawn } from "node:child_process";
281053
+ import { execSync as execSync33, spawn as nodeSpawn } from "node:child_process";
280630
281054
  import { createRequire as createRequire2 } from "node:module";
280631
281055
  function sanitizeForTTS(text) {
280632
281056
  return text.replace(/^#{1,6}\s+/gm, "").replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1").replace(/_{1,3}([^_]+)_{1,3}/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^[\s]*[-*+]\s+/gm, "").replace(/^[\s]*\d+\.\s+/gm, "").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}$/gm, "").replace(/\[[ xX]\]\s*/g, "").replace(/[\u{1F600}-\u{1F64F}]/gu, "").replace(/[\u{1F300}-\u{1F5FF}]/gu, "").replace(/[\u{1F680}-\u{1F6FF}]/gu, "").replace(/[\u{1F1E0}-\u{1F1FF}]/gu, "").replace(/[\u{2600}-\u{26FF}]/gu, "").replace(/[\u{2700}-\u{27BF}]/gu, "").replace(/[\u{FE00}-\u{FE0F}]/gu, "").replace(/[\u{1F900}-\u{1F9FF}]/gu, "").replace(/[\u{1FA00}-\u{1FA6F}]/gu, "").replace(/[\u{1FA70}-\u{1FAFF}]/gu, "").replace(/[\u{200D}]/gu, "").replace(/[\u{20E3}]/gu, "").replace(/[✓✔✗✘✕✖⚠️⏸⏹⏵●○◆◇■□▪▫►▼▲◀⬆⬇⬅➡↑↓←→⇐⇒⇑⇓]/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐░▒▓█⠀-⣿]/g, "").replace(/\s{2,}/g, " ").trim();
@@ -282368,7 +282792,7 @@ var init_voice = __esm({
282368
282792
  }
282369
282793
  for (const player of ["paplay", "pw-play", "aplay"]) {
282370
282794
  try {
282371
- execSync32(`which ${player}`, { stdio: "pipe" });
282795
+ execSync33(`which ${player}`, { stdio: "pipe" });
282372
282796
  return [player, path5];
282373
282797
  } catch {
282374
282798
  }
@@ -282397,7 +282821,7 @@ var init_voice = __esm({
282397
282821
  return this.python3Path;
282398
282822
  for (const bin of ["python3", "python"]) {
282399
282823
  try {
282400
- const path5 = execSync32(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
282824
+ const path5 = execSync33(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
282401
282825
  if (path5) {
282402
282826
  this.python3Path = path5;
282403
282827
  return path5;
@@ -282463,7 +282887,7 @@ var init_voice = __esm({
282463
282887
  return false;
282464
282888
  }
282465
282889
  try {
282466
- execSync32(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
282890
+ execSync33(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
282467
282891
  this.mlxInstalled = true;
282468
282892
  return true;
282469
282893
  } catch {
@@ -282524,11 +282948,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
282524
282948
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
282525
282949
  ].join("; ");
282526
282950
  try {
282527
- execSync32(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
282951
+ execSync33(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
282528
282952
  } catch (err) {
282529
282953
  try {
282530
282954
  const safeText = cleaned.replace(/'/g, "'\\''");
282531
- execSync32(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
282955
+ execSync33(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
282532
282956
  } catch (err2) {
282533
282957
  return;
282534
282958
  }
@@ -282592,11 +283016,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
282592
283016
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
282593
283017
  ].join("; ");
282594
283018
  try {
282595
- execSync32(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
283019
+ execSync33(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
282596
283020
  } catch {
282597
283021
  try {
282598
283022
  const safeText = cleaned.replace(/'/g, "'\\''");
282599
- execSync32(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
283023
+ execSync33(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
282600
283024
  } catch {
282601
283025
  return null;
282602
283026
  }
@@ -287907,7 +288331,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
287907
288331
  }
287908
288332
  }
287909
288333
  async function handleParallel(arg, ctx3) {
287910
- const { execSync: execSync39 } = await import("node:child_process");
288334
+ const { execSync: execSync40 } = await import("node:child_process");
287911
288335
  const baseUrl = ctx3.config.backendUrl || "http://localhost:11434";
287912
288336
  const isRemote = ctx3.config.backendType === "nexus";
287913
288337
  if (isRemote) {
@@ -287931,7 +288355,7 @@ async function handleParallel(arg, ctx3) {
287931
288355
  }
287932
288356
  let systemdVal = "";
287933
288357
  try {
287934
- const out = execSync39("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
288358
+ const out = execSync40("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
287935
288359
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
287936
288360
  if (match)
287937
288361
  systemdVal = match[1];
@@ -287960,7 +288384,7 @@ async function handleParallel(arg, ctx3) {
287960
288384
  }
287961
288385
  const isSystemd = (() => {
287962
288386
  try {
287963
- const out = execSync39("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
288387
+ const out = execSync40("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
287964
288388
  return out === "active" || out === "inactive";
287965
288389
  } catch {
287966
288390
  return false;
@@ -287974,10 +288398,10 @@ async function handleParallel(arg, ctx3) {
287974
288398
  const overrideContent = `[Service]
287975
288399
  Environment="OLLAMA_NUM_PARALLEL=${n2}"
287976
288400
  `;
287977
- execSync39(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
287978
- execSync39(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
287979
- execSync39("sudo systemctl daemon-reload", { stdio: "pipe" });
287980
- execSync39("sudo systemctl restart ollama.service", { stdio: "pipe" });
288401
+ execSync40(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
288402
+ execSync40(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
288403
+ execSync40("sudo systemctl daemon-reload", { stdio: "pipe" });
288404
+ execSync40("sudo systemctl restart ollama.service", { stdio: "pipe" });
287981
288405
  let ready = false;
287982
288406
  for (let i2 = 0; i2 < 30 && !ready; i2++) {
287983
288407
  await new Promise((r2) => setTimeout(r2, 500));
@@ -288004,7 +288428,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n2}"
288004
288428
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n2}...`);
288005
288429
  try {
288006
288430
  try {
288007
- execSync39("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
288431
+ execSync40("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
288008
288432
  } catch {
288009
288433
  }
288010
288434
  await new Promise((r2) => setTimeout(r2, 1e3));
@@ -289021,18 +289445,18 @@ async function showExposeDashboard(gateway, rl, ctx3) {
289021
289445
  const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
289022
289446
  let copied = false;
289023
289447
  try {
289024
- const { execSync: execSync39 } = __require("node:child_process");
289448
+ const { execSync: execSync40 } = __require("node:child_process");
289025
289449
  const platform6 = process.platform;
289026
289450
  if (platform6 === "darwin") {
289027
- execSync39("pbcopy", { input: cmd, timeout: 3e3 });
289451
+ execSync40("pbcopy", { input: cmd, timeout: 3e3 });
289028
289452
  copied = true;
289029
289453
  } else if (platform6 === "win32") {
289030
- execSync39("clip", { input: cmd, timeout: 3e3 });
289454
+ execSync40("clip", { input: cmd, timeout: 3e3 });
289031
289455
  copied = true;
289032
289456
  } else {
289033
289457
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
289034
289458
  try {
289035
- execSync39(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
289459
+ execSync40(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
289036
289460
  copied = true;
289037
289461
  break;
289038
289462
  } catch {
@@ -289124,7 +289548,7 @@ var init_commands = __esm({
289124
289548
  // packages/cli/dist/tui/project-context.js
289125
289549
  import { existsSync as existsSync49, readFileSync as readFileSync37, readdirSync as readdirSync15 } from "node:fs";
289126
289550
  import { join as join65, basename as basename13 } from "node:path";
289127
- import { execSync as execSync33 } from "node:child_process";
289551
+ import { execSync as execSync34 } from "node:child_process";
289128
289552
  import { homedir as homedir20, platform as platform4, release } from "node:os";
289129
289553
  function getModelTier(modelName) {
289130
289554
  const m2 = modelName.toLowerCase();
@@ -289170,19 +289594,19 @@ function loadProjectMap(repoRoot) {
289170
289594
  }
289171
289595
  function getGitInfo(repoRoot) {
289172
289596
  try {
289173
- execSync33("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
289597
+ execSync34("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
289174
289598
  } catch {
289175
289599
  return "";
289176
289600
  }
289177
289601
  const lines = [];
289178
289602
  try {
289179
- const branch = execSync33("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
289603
+ const branch = execSync34("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
289180
289604
  if (branch)
289181
289605
  lines.push(`Branch: ${branch}`);
289182
289606
  } catch {
289183
289607
  }
289184
289608
  try {
289185
- const status = execSync33("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
289609
+ const status = execSync34("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
289186
289610
  if (status) {
289187
289611
  const changed = status.split("\n").length;
289188
289612
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -289192,7 +289616,7 @@ function getGitInfo(repoRoot) {
289192
289616
  } catch {
289193
289617
  }
289194
289618
  try {
289195
- const log22 = execSync33("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
289619
+ const log22 = execSync34("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
289196
289620
  if (log22)
289197
289621
  lines.push(`Recent commits:
289198
289622
  ${log22}`);
@@ -291988,7 +292412,7 @@ var init_promptLoader3 = __esm({
291988
292412
  // packages/cli/dist/tui/dream-engine.js
291989
292413
  import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync25, readFileSync as readFileSync41, existsSync as existsSync53, cpSync, rmSync as rmSync3, readdirSync as readdirSync17 } from "node:fs";
291990
292414
  import { join as join70, basename as basename15 } from "node:path";
291991
- import { execSync as execSync34 } from "node:child_process";
292415
+ import { execSync as execSync35 } from "node:child_process";
291992
292416
  function loadAutoresearchMemory(repoRoot) {
291993
292417
  const memoryPath = join70(repoRoot, ".oa", "memory", "autoresearch.json");
291994
292418
  if (!existsSync53(memoryPath))
@@ -292352,7 +292776,7 @@ var init_dream_engine = __esm({
292352
292776
  }
292353
292777
  }
292354
292778
  try {
292355
- const output = execSync34(cmd, {
292779
+ const output = execSync35(cmd, {
292356
292780
  cwd: this.repoRoot,
292357
292781
  timeout: 3e4,
292358
292782
  encoding: "utf-8",
@@ -293129,17 +293553,17 @@ ${summaryResult}
293129
293553
  try {
293130
293554
  mkdirSync25(checkpointDir, { recursive: true });
293131
293555
  try {
293132
- const gitStatus = execSync34("git status --porcelain", {
293556
+ const gitStatus = execSync35("git status --porcelain", {
293133
293557
  cwd: this.repoRoot,
293134
293558
  encoding: "utf-8",
293135
293559
  timeout: 1e4
293136
293560
  });
293137
- const gitDiff = execSync34("git diff", {
293561
+ const gitDiff = execSync35("git diff", {
293138
293562
  cwd: this.repoRoot,
293139
293563
  encoding: "utf-8",
293140
293564
  timeout: 1e4
293141
293565
  });
293142
- const gitHash = execSync34("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
293566
+ const gitHash = execSync35("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
293143
293567
  cwd: this.repoRoot,
293144
293568
  encoding: "utf-8",
293145
293569
  timeout: 5e3
@@ -296964,7 +297388,7 @@ __export(text_selection_exports, {
296964
297388
  stripAnsi: () => stripAnsi3,
296965
297389
  visibleLength: () => visibleLength
296966
297390
  });
296967
- import { execSync as execSync35 } from "node:child_process";
297391
+ import { execSync as execSync36 } from "node:child_process";
296968
297392
  function stripAnsi3(s2) {
296969
297393
  return s2.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
296970
297394
  }
@@ -296975,16 +297399,16 @@ function copyText(text) {
296975
297399
  try {
296976
297400
  const platform6 = process.platform;
296977
297401
  if (platform6 === "darwin") {
296978
- execSync35("pbcopy", { input: text, timeout: 3e3 });
297402
+ execSync36("pbcopy", { input: text, timeout: 3e3 });
296979
297403
  return true;
296980
297404
  }
296981
297405
  if (platform6 === "win32") {
296982
- execSync35("clip", { input: text, timeout: 3e3 });
297406
+ execSync36("clip", { input: text, timeout: 3e3 });
296983
297407
  return true;
296984
297408
  }
296985
297409
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
296986
297410
  try {
296987
- execSync35(tool, { input: text, timeout: 3e3 });
297411
+ execSync36(tool, { input: text, timeout: 3e3 });
296988
297412
  return true;
296989
297413
  } catch {
296990
297414
  continue;
@@ -296993,10 +297417,10 @@ function copyText(text) {
296993
297417
  if (!_clipboardAutoInstallAttempted) {
296994
297418
  _clipboardAutoInstallAttempted = true;
296995
297419
  try {
296996
- execSync35("which apt-get", { timeout: 2e3, stdio: "pipe" });
297420
+ execSync36("which apt-get", { timeout: 2e3, stdio: "pipe" });
296997
297421
  try {
296998
- execSync35("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
296999
- execSync35("xclip -selection clipboard", { input: text, timeout: 3e3 });
297422
+ execSync36("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
297423
+ execSync36("xclip -selection clipboard", { input: text, timeout: 3e3 });
297000
297424
  return true;
297001
297425
  } catch {
297002
297426
  }
@@ -302088,7 +302512,7 @@ var init_profiles = __esm({
302088
302512
  });
302089
302513
 
302090
302514
  // packages/cli/dist/docker.js
302091
- import { execSync as execSync36, spawn as spawn22 } from "node:child_process";
302515
+ import { execSync as execSync37, spawn as spawn22 } from "node:child_process";
302092
302516
  import { existsSync as existsSync61, mkdirSync as mkdirSync31, writeFileSync as writeFileSync29 } from "node:fs";
302093
302517
  import { join as join78, resolve as resolve33, dirname as dirname22 } from "node:path";
302094
302518
  import { homedir as homedir22 } from "node:os";
@@ -302109,7 +302533,7 @@ function getDockerDir() {
302109
302533
  }
302110
302534
  function isDockerAvailable() {
302111
302535
  try {
302112
- execSync36("docker info", { stdio: "pipe", timeout: 1e4 });
302536
+ execSync37("docker info", { stdio: "pipe", timeout: 1e4 });
302113
302537
  return true;
302114
302538
  } catch {
302115
302539
  return false;
@@ -302117,7 +302541,7 @@ function isDockerAvailable() {
302117
302541
  }
302118
302542
  function isDockerInstalled() {
302119
302543
  try {
302120
- execSync36("docker --version", { stdio: "pipe", timeout: 5e3 });
302544
+ execSync37("docker --version", { stdio: "pipe", timeout: 5e3 });
302121
302545
  return true;
302122
302546
  } catch {
302123
302547
  return false;
@@ -302142,31 +302566,31 @@ async function ensureDocker() {
302142
302566
  }
302143
302567
  try {
302144
302568
  console.log("[oa-docker] Docker not found. Installing via get.docker.com...");
302145
- execSync36("curl -fsSL https://get.docker.com | sh", {
302569
+ execSync37("curl -fsSL https://get.docker.com | sh", {
302146
302570
  stdio: "inherit",
302147
302571
  timeout: 3e5
302148
302572
  });
302149
302573
  const user = process.env["USER"] || process.env["LOGNAME"];
302150
302574
  if (user) {
302151
302575
  try {
302152
- execSync36(`sudo usermod -aG docker ${user}`, { stdio: "pipe" });
302576
+ execSync37(`sudo usermod -aG docker ${user}`, { stdio: "pipe" });
302153
302577
  } catch {
302154
302578
  }
302155
302579
  }
302156
302580
  try {
302157
- execSync36("sudo systemctl start docker", { stdio: "pipe", timeout: 15e3 });
302581
+ execSync37("sudo systemctl start docker", { stdio: "pipe", timeout: 15e3 });
302158
302582
  } catch {
302159
302583
  }
302160
302584
  try {
302161
- execSync36("nvidia-smi", { stdio: "pipe", timeout: 5e3 });
302162
- const runtimes = execSync36("docker info --format '{{json .Runtimes}}'", {
302585
+ execSync37("nvidia-smi", { stdio: "pipe", timeout: 5e3 });
302586
+ const runtimes = execSync37("docker info --format '{{json .Runtimes}}'", {
302163
302587
  stdio: "pipe",
302164
302588
  timeout: 5e3
302165
302589
  }).toString();
302166
302590
  if (!runtimes.includes("nvidia")) {
302167
302591
  console.log("[oa-docker] NVIDIA GPU detected. Installing nvidia-container-toolkit...");
302168
302592
  try {
302169
- execSync36(`
302593
+ execSync37(`
302170
302594
  curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg 2>/dev/null
302171
302595
  curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null 2>&1
302172
302596
  sudo apt-get update -qq 2>/dev/null && sudo apt-get install -y -qq nvidia-container-toolkit 2>/dev/null || ( sudo dnf install -y nvidia-container-toolkit 2>/dev/null || sudo yum install -y nvidia-container-toolkit 2>/dev/null || true )
@@ -302196,7 +302620,7 @@ async function ensureDocker() {
302196
302620
  }
302197
302621
  async function ensureNvidiaToolkit() {
302198
302622
  try {
302199
- execSync36("nvidia-smi --query-gpu=name --format=csv,noheader", { stdio: "pipe", timeout: 5e3 });
302623
+ execSync37("nvidia-smi --query-gpu=name --format=csv,noheader", { stdio: "pipe", timeout: 5e3 });
302200
302624
  } catch {
302201
302625
  return { ok: false, message: "No NVIDIA GPU detected (nvidia-smi not found)" };
302202
302626
  }
@@ -302207,7 +302631,7 @@ async function ensureNvidiaToolkit() {
302207
302631
  return { ok: false, message: "Auto-install only supported on Linux. Install manually: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html" };
302208
302632
  }
302209
302633
  try {
302210
- execSync36(`
302634
+ execSync37(`
302211
302635
  curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg 2>/dev/null
302212
302636
  curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null 2>&1
302213
302637
  sudo apt-get update -qq 2>/dev/null && sudo apt-get install -y -qq nvidia-container-toolkit 2>/dev/null || ( sudo dnf install -y nvidia-container-toolkit 2>/dev/null || sudo yum install -y nvidia-container-toolkit 2>/dev/null || true )
@@ -302221,7 +302645,7 @@ async function ensureNvidiaToolkit() {
302221
302645
  }
302222
302646
  function isOaImageBuilt() {
302223
302647
  try {
302224
- const out = execSync36(`docker images -q ${OA_IMAGE}:${OA_IMAGE_TAG}`, {
302648
+ const out = execSync37(`docker images -q ${OA_IMAGE}:${OA_IMAGE_TAG}`, {
302225
302649
  stdio: "pipe",
302226
302650
  timeout: 5e3
302227
302651
  }).toString().trim();
@@ -302245,7 +302669,7 @@ async function ensureOaImage(force = false) {
302245
302669
  }
302246
302670
  try {
302247
302671
  console.log(`[oa-docker] Building image ${OA_IMAGE}:${OA_IMAGE_TAG}...`);
302248
- execSync36(`docker build -t ${OA_IMAGE}:${OA_IMAGE_TAG} ${buildContext}`, {
302672
+ execSync37(`docker build -t ${OA_IMAGE}:${OA_IMAGE_TAG} ${buildContext}`, {
302249
302673
  stdio: "inherit",
302250
302674
  timeout: 6e5
302251
302675
  // 10 min
@@ -302319,11 +302743,11 @@ exec "$@"
302319
302743
  }
302320
302744
  function hasNvidiaGpu() {
302321
302745
  try {
302322
- execSync36("nvidia-smi --query-gpu=name --format=csv,noheader", {
302746
+ execSync37("nvidia-smi --query-gpu=name --format=csv,noheader", {
302323
302747
  stdio: "pipe",
302324
302748
  timeout: 5e3
302325
302749
  });
302326
- const runtimes = execSync36("docker info --format '{{json .Runtimes}}'", {
302750
+ const runtimes = execSync37("docker info --format '{{json .Runtimes}}'", {
302327
302751
  stdio: "pipe",
302328
302752
  timeout: 5e3
302329
302753
  }).toString();
@@ -302396,7 +302820,7 @@ import * as https3 from "node:https";
302396
302820
  import { createRequire as createRequire4 } from "node:module";
302397
302821
  import { fileURLToPath as fileURLToPath15 } from "node:url";
302398
302822
  import { dirname as dirname23, join as join79, resolve as resolve34 } from "node:path";
302399
- import { spawn as spawn23, execSync as execSync37 } from "node:child_process";
302823
+ import { spawn as spawn23, execSync as execSync38 } from "node:child_process";
302400
302824
  import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30, readFileSync as readFileSync49, readdirSync as readdirSync23, existsSync as existsSync62 } from "node:fs";
302401
302825
  import { randomBytes as randomBytes19, randomUUID as randomUUID5 } from "node:crypto";
302402
302826
  function getVersion3() {
@@ -303424,7 +303848,7 @@ function handleV1RunsDelete(res, id) {
303424
303848
  const containerName = `oa-${id}`;
303425
303849
  if (job.sandbox === "container") {
303426
303850
  try {
303427
- execSync37(`docker stop ${containerName}`, { timeout: 5e3, stdio: "ignore" });
303851
+ execSync38(`docker stop ${containerName}`, { timeout: 5e3, stdio: "ignore" });
303428
303852
  } catch {
303429
303853
  }
303430
303854
  }
@@ -304364,7 +304788,7 @@ import { createRequire as createRequire5 } from "node:module";
304364
304788
  import { fileURLToPath as fileURLToPath16 } from "node:url";
304365
304789
  import { readFileSync as readFileSync50, writeFileSync as writeFileSync31, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync24, mkdirSync as mkdirSync33 } from "node:fs";
304366
304790
  import { existsSync as existsSync63 } from "node:fs";
304367
- import { execSync as execSync38 } from "node:child_process";
304791
+ import { execSync as execSync39 } from "node:child_process";
304368
304792
  import { homedir as homedir23 } from "node:os";
304369
304793
  function formatTimeAgo(date) {
304370
304794
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -304559,6 +304983,8 @@ function buildTools(repoRoot, config, contextWindowSize, modelTier) {
304559
304983
  ];
304560
304984
  return [
304561
304985
  ...executionTools.map(adaptTool6),
304986
+ // MCP tools (dynamic — from connected MCP servers, WO-MCP-01)
304987
+ ..._mcpTools.map(adaptTool6),
304562
304988
  createSubAgentTool(config, repoRoot, contextWindowSize),
304563
304989
  createTaskCompleteTool(modelTier)
304564
304990
  ];
@@ -305113,6 +305539,21 @@ Content: ${content.slice(0, 500)}` }
305113
305539
  return { status, findings };
305114
305540
  });
305115
305541
  }
305542
+ const skillExecTool = tools.find((t2) => t2.name === "skill_execute");
305543
+ if (skillExecTool && "setForkCallback" in skillExecTool) {
305544
+ skillExecTool.setForkCallback(async (skillName, content) => {
305545
+ if (!_agentToolRef)
305546
+ return "Skill fork unavailable \u2014 agent tool not ready";
305547
+ const agentResult = await _agentToolRef.execute({
305548
+ prompt: `Execute this skill:
305549
+
305550
+ ${content}`,
305551
+ subagent_type: "general",
305552
+ description: `skill: ${skillName}`
305553
+ });
305554
+ return agentResult?.output ?? "Skill fork failed";
305555
+ });
305556
+ }
305116
305557
  const replToolForFinalVar = tools.find((t2) => t2.name === "repl_exec");
305117
305558
  if (replToolForFinalVar && "readVariable" in replToolForFinalVar) {
305118
305559
  runner.options.finalVarResolver = async (varName) => {
@@ -305853,6 +306294,29 @@ async function startInteractive(config, repoPath) {
305853
306294
  }
305854
306295
  initOaDirectory(repoRoot);
305855
306296
  const savedSettings = resolveSettings(repoRoot);
306297
+ _mcpManager = new McpManager(repoRoot);
306298
+ try {
306299
+ const mcpConnections = await _mcpManager.connectAll();
306300
+ const connected = mcpConnections.filter((c4) => c4.status === "connected");
306301
+ if (connected.length > 0) {
306302
+ _mcpTools = await _mcpManager.buildTools();
306303
+ }
306304
+ } catch {
306305
+ }
306306
+ _pluginManager = new PluginManager(repoRoot);
306307
+ try {
306308
+ const plugins = _pluginManager.discover();
306309
+ const loaded = plugins.filter((p2) => p2.loaded);
306310
+ if (loaded.length > 0 && _mcpManager) {
306311
+ const pluginServers = _pluginManager.getMcpServers();
306312
+ for (const [name10, serverConfig] of Object.entries(pluginServers)) {
306313
+ await _mcpManager.connectOne(name10, serverConfig).catch(() => {
306314
+ });
306315
+ }
306316
+ _mcpTools = await _mcpManager.buildTools().catch(() => []);
306317
+ }
306318
+ } catch {
306319
+ }
305856
306320
  let restoredSessionContext = null;
305857
306321
  if (process.stdout.isTTY) {
305858
306322
  process.stdout.write("\x1B[2J\x1B[3J\x1B]50;ClearScrollback\x07\x1B[H");
@@ -307283,6 +307747,8 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
307283
307747
  } catch {
307284
307748
  }
307285
307749
  }
307750
+ _mcpManager?.disconnectAll().catch(() => {
307751
+ });
307286
307752
  },
307287
307753
  async voiceToggle() {
307288
307754
  const msg = await voiceEngine.toggle();
@@ -308289,7 +308755,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
308289
308755
  try {
308290
308756
  if (process.platform === "win32") {
308291
308757
  try {
308292
- execSync38(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
308758
+ execSync39(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
308293
308759
  } catch {
308294
308760
  }
308295
308761
  } else {
@@ -308316,7 +308782,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
308316
308782
  if (pid > 0) {
308317
308783
  if (process.platform === "win32") {
308318
308784
  try {
308319
- execSync38(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
308785
+ execSync39(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
308320
308786
  } catch {
308321
308787
  }
308322
308788
  } else {
@@ -308333,7 +308799,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
308333
308799
  } catch {
308334
308800
  }
308335
308801
  try {
308336
- execSync38(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
308802
+ execSync39(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
308337
308803
  } catch {
308338
308804
  }
308339
308805
  const oaPath = join80(repoRoot, OA_DIR);
@@ -308347,14 +308813,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
308347
308813
  } catch (err) {
308348
308814
  if (attempt < 2) {
308349
308815
  try {
308350
- execSync38(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
308816
+ execSync39(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
308351
308817
  } catch {
308352
308818
  }
308353
308819
  } else {
308354
308820
  writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
308355
308821
  if (process.platform === "win32") {
308356
308822
  try {
308357
- execSync38(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
308823
+ execSync39(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
308358
308824
  deleted = true;
308359
308825
  } catch {
308360
308826
  }
@@ -309580,7 +310046,7 @@ Rules:
309580
310046
  process.exit(1);
309581
310047
  }
309582
310048
  }
309583
- var taskManager, _apiCallbacks, _shellToolRef, _replToolRef, _fullSubAgentToolRef, _agentToolRef, _sendMessageToolRef, _agentLifecycleMgr, _activeRunnerRef, _wireSubAgentCallbacks, _wireAgentToolCallbacks, _autoUpdatedThisSession, SELF_IMPROVE_INTERVAL, _tasksSinceImprove;
310049
+ var taskManager, _apiCallbacks, _shellToolRef, _replToolRef, _fullSubAgentToolRef, _agentToolRef, _sendMessageToolRef, _agentLifecycleMgr, _activeRunnerRef, _wireSubAgentCallbacks, _wireAgentToolCallbacks, _autoUpdatedThisSession, _mcpManager, _pluginManager, _mcpTools, SELF_IMPROVE_INTERVAL, _tasksSinceImprove;
309584
310050
  var init_interactive = __esm({
309585
310051
  "packages/cli/dist/tui/interactive.js"() {
309586
310052
  "use strict";
@@ -309632,6 +310098,9 @@ var init_interactive = __esm({
309632
310098
  _wireSubAgentCallbacks = null;
309633
310099
  _wireAgentToolCallbacks = null;
309634
310100
  _autoUpdatedThisSession = false;
310101
+ _mcpManager = null;
310102
+ _pluginManager = null;
310103
+ _mcpTools = [];
309635
310104
  SELF_IMPROVE_INTERVAL = 5;
309636
310105
  _tasksSinceImprove = 0;
309637
310106
  }