open-agents-ai 0.103.72 → 0.103.74

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 +170 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12394,6 +12394,7 @@ async function handleCmd(cmd) {
12394
12394
  }
12395
12395
  if (args.temperature !== undefined) riData.temperature = Number(args.temperature);
12396
12396
  if (args.max_tokens) riData.max_tokens = Number(args.max_tokens);
12397
+ if (args.think !== undefined) riData.think = args.think === 'true' || args.think === true;
12397
12398
  } else {
12398
12399
  riData = { prompt: riPrompt };
12399
12400
  }
@@ -12984,6 +12985,7 @@ async function handleCmd(cmd) {
12984
12985
  }
12985
12986
  if (parsedReq.temperature !== undefined) chatBody.temperature = parsedReq.temperature;
12986
12987
  if (parsedReq.max_tokens) chatBody.max_tokens = parsedReq.max_tokens;
12988
+ if (parsedReq.think !== undefined) chatBody.think = parsedReq.think;
12987
12989
 
12988
12990
  var chatHeaders = { 'Content-Type': 'application/json' };
12989
12991
  if (isPassthrough && endpointAuth) chatHeaders['Authorization'] = 'Bearer ' + endpointAuth;
@@ -18637,6 +18639,7 @@ var init_agenticRunner = __esm({
18637
18639
  deepContext: options?.deepContext ?? false,
18638
18640
  dynamicContext: options?.dynamicContext ?? "",
18639
18641
  streamEnabled: options?.streamEnabled ?? false,
18642
+ thinking: options?.thinking ?? true,
18640
18643
  bruteForce: options?.bruteForce ?? true,
18641
18644
  bruteForceMaxCycles: options?.bruteForceMaxCycles ?? 100,
18642
18645
  modelTier: options?.modelTier ?? "large",
@@ -20953,10 +20956,12 @@ ${transcript}`
20953
20956
  baseUrl;
20954
20957
  model;
20955
20958
  apiKey;
20956
- constructor(baseUrl, model, apiKey) {
20959
+ thinking;
20960
+ constructor(baseUrl, model, apiKey, thinking) {
20957
20961
  this.baseUrl = normalizeBaseUrl(baseUrl);
20958
20962
  this.model = model;
20959
20963
  this.apiKey = apiKey ?? "";
20964
+ this.thinking = thinking ?? true;
20960
20965
  }
20961
20966
  /** Build auth headers — all providers use standard Bearer token auth. */
20962
20967
  authHeaders() {
@@ -20973,7 +20978,7 @@ ${transcript}`
20973
20978
  tools: request.tools,
20974
20979
  temperature: request.temperature,
20975
20980
  max_tokens: request.maxTokens,
20976
- think: false
20981
+ think: this.thinking
20977
20982
  };
20978
20983
  const resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {
20979
20984
  method: "POST",
@@ -21023,7 +21028,7 @@ ${transcript}`
21023
21028
  }
21024
21029
  /**
21025
21030
  * SSE streaming variant — yields StreamChunks as tokens arrive.
21026
- * Uses `stream: true` and `think: true` so thinking tokens are visible.
21031
+ * Uses `stream: true` and the current thinking setting.
21027
21032
  * The existing chatCompletion() method is completely unmodified.
21028
21033
  */
21029
21034
  async *chatCompletionStream(request) {
@@ -21035,7 +21040,7 @@ ${transcript}`
21035
21040
  max_tokens: request.maxTokens,
21036
21041
  stream: true,
21037
21042
  stream_options: { include_usage: true },
21038
- think: true
21043
+ think: this.thinking
21039
21044
  };
21040
21045
  const resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {
21041
21046
  method: "POST",
@@ -21121,11 +21126,13 @@ var init_nexusBackend = __esm({
21121
21126
  authKey;
21122
21127
  consecutiveFailures = 0;
21123
21128
  static MAX_CONSECUTIVE_FAILURES = 3;
21124
- constructor(sendFn, model, targetPeer, authKey) {
21129
+ thinking;
21130
+ constructor(sendFn, model, targetPeer, authKey, thinking) {
21125
21131
  this.sendFn = sendFn;
21126
21132
  this.model = model;
21127
21133
  this.targetPeer = targetPeer || "";
21128
21134
  this.authKey = authKey || "";
21135
+ this.thinking = thinking ?? true;
21129
21136
  }
21130
21137
  async chatCompletion(request) {
21131
21138
  if (this.consecutiveFailures >= _NexusAgenticBackend.MAX_CONSECUTIVE_FAILURES) {
@@ -21146,6 +21153,7 @@ var init_nexusBackend = __esm({
21146
21153
  if (this.authKey) {
21147
21154
  daemonArgs.auth_key = this.authKey;
21148
21155
  }
21156
+ daemonArgs.think = String(this.thinking);
21149
21157
  let rawResult;
21150
21158
  try {
21151
21159
  rawResult = await this.sendFn("remote_infer", daemonArgs, request.timeoutMs || 12e4);
@@ -26934,6 +26942,8 @@ function renderSlashHelp() {
26934
26942
  ["/endpoint <url>", "Set backend URL (auto-detects type)"],
26935
26943
  ["/endpoint <url> --auth <t>", "Set endpoint with Bearer auth"],
26936
26944
  ["/config", "Show current configuration"],
26945
+ ["/parallel", "Show current Ollama parallel inference slots"],
26946
+ ["/parallel <1-15>", "Set parallel slots (restarts Ollama, max 15)"],
26937
26947
  ["/update", "Check for updates and auto-install"],
26938
26948
  ["/update auto", "Enable auto-update after task completion (default)"],
26939
26949
  ["/update manual", "Disable auto-update (only update on /update)"],
@@ -26942,6 +26952,7 @@ function renderSlashHelp() {
26942
26952
  ["/voice clone <file>", "Set voice clone reference audio (wav/mp3/ogg/flac)"],
26943
26953
  ["/voice clone glados", "Generate clone ref from GLaDOS for LuxTTS"],
26944
26954
  ["/voice clone overwatch", "Generate clone ref from Overwatch for LuxTTS"],
26955
+ ["/think", "Toggle thinking/reasoning mode (Qwen3, DeepSeek-R1, etc.)"],
26945
26956
  ["/stream", "Toggle real-time token streaming (pastel syntax highlighting)"],
26946
26957
  ["/dream", "Start dream mode \u2014 creative idle exploration (writes to .oa/dreams/)"],
26947
26958
  ["/dream deep", "Deep dream \u2014 multi-cycle exploration with sleep architecture"],
@@ -34092,6 +34103,9 @@ async function handleSlashCommand(input, ctx) {
34092
34103
  case "ep":
34093
34104
  await handleEndpoint(arg, ctx, hasLocal);
34094
34105
  return "handled";
34106
+ case "parallel":
34107
+ await handleParallel(arg, ctx);
34108
+ return "handled";
34095
34109
  case "update":
34096
34110
  case "upgrade":
34097
34111
  await handleUpdate(arg, ctx);
@@ -34143,6 +34157,13 @@ async function handleSlashCommand(input, ctx) {
34143
34157
  renderInfo(`Token streaming: ${isOn ? "on" : "off"}${hasLocal ? " (project-local)" : ""}` + (isOn ? " \u2014 thinking tokens in grey italics, responses with pastel syntax highlighting" : ""));
34144
34158
  return "handled";
34145
34159
  }
34160
+ case "think": {
34161
+ const isOn = ctx.thinkToggle();
34162
+ const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
34163
+ save({ thinking: isOn });
34164
+ renderInfo(`Thinking mode: ${isOn ? "on" : "off"}${hasLocal ? " (project-local)" : ""}` + (isOn ? " \u2014 models that support reasoning (Qwen3, DeepSeek-R1, etc.) will show their thinking chain" : " \u2014 reasoning chain suppressed, model responds directly"));
34165
+ return "handled";
34166
+ }
34146
34167
  case "tools": {
34147
34168
  const tools = listCustomToolFiles(ctx.repoRoot);
34148
34169
  if (tools.length === 0) {
@@ -35515,6 +35536,137 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
35515
35536
  renderWarning("Active task aborted \u2014 endpoint changed. Send a new prompt to continue.");
35516
35537
  }
35517
35538
  }
35539
+ async function handleParallel(arg, ctx) {
35540
+ const { execSync: execSync29 } = await import("node:child_process");
35541
+ const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
35542
+ const isRemote = ctx.config.backendType === "nexus";
35543
+ if (isRemote) {
35544
+ renderInfo("Parallel slots are configured on the remote provider's Ollama, not locally.");
35545
+ renderInfo("The remote provider controls OLLAMA_NUM_PARALLEL on their end.");
35546
+ return;
35547
+ }
35548
+ if (!arg) {
35549
+ const envVal = process.env.OLLAMA_NUM_PARALLEL;
35550
+ let runningInfo = "";
35551
+ try {
35552
+ const psResp = await fetch(baseUrl + "/api/ps", { signal: AbortSignal.timeout(3e3) });
35553
+ if (psResp.ok) {
35554
+ const ps = await psResp.json();
35555
+ const models = ps.models || [];
35556
+ if (models.length > 0) {
35557
+ runningInfo = models.map((m) => ` ${c2.cyan(m.name)} \u2014 ${m.size_vram ? (m.size_vram / 1e9).toFixed(1) + " GB VRAM" : "CPU"}`).join("\n");
35558
+ }
35559
+ }
35560
+ } catch {
35561
+ }
35562
+ let systemdVal = "";
35563
+ try {
35564
+ const out = execSync29("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
35565
+ const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
35566
+ if (match)
35567
+ systemdVal = match[1];
35568
+ } catch {
35569
+ }
35570
+ const effective = envVal || systemdVal || "1 (default)";
35571
+ console.log("");
35572
+ console.log(` ${c2.bold("Parallel Inference Slots")}`);
35573
+ console.log("");
35574
+ console.log(` ${c2.dim("OLLAMA_NUM_PARALLEL:")} ${c2.bold(c2.cyan(effective))}`);
35575
+ console.log(` ${c2.dim("Endpoint:")} ${baseUrl}`);
35576
+ if (runningInfo) {
35577
+ console.log(` ${c2.dim("Running models:")}`);
35578
+ console.log(runningInfo);
35579
+ }
35580
+ console.log("");
35581
+ console.log(` ${c2.dim("Set with:")} ${c2.cyan("/parallel <1-15>")}`);
35582
+ console.log(` ${c2.dim("Each slot multiplies context memory usage per model.")}`);
35583
+ console.log("");
35584
+ return;
35585
+ }
35586
+ const n = parseInt(arg, 10);
35587
+ if (isNaN(n) || n < 1 || n > 15) {
35588
+ renderError("Parallel slots must be between 1 and 15. Usage: /parallel <1-15>");
35589
+ return;
35590
+ }
35591
+ const isSystemd = (() => {
35592
+ try {
35593
+ const out = execSync29("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
35594
+ return out === "active" || out === "inactive";
35595
+ } catch {
35596
+ return false;
35597
+ }
35598
+ })();
35599
+ if (isSystemd) {
35600
+ renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n} via systemd override...`);
35601
+ try {
35602
+ const overrideDir = "/etc/systemd/system/ollama.service.d";
35603
+ const overrideFile = `${overrideDir}/parallel.conf`;
35604
+ const overrideContent = `[Service]
35605
+ Environment="OLLAMA_NUM_PARALLEL=${n}"
35606
+ `;
35607
+ execSync29(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
35608
+ execSync29(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
35609
+ execSync29("sudo systemctl daemon-reload", { stdio: "pipe" });
35610
+ execSync29("sudo systemctl restart ollama.service", { stdio: "pipe" });
35611
+ let ready = false;
35612
+ for (let i = 0; i < 30 && !ready; i++) {
35613
+ await new Promise((r) => setTimeout(r, 500));
35614
+ try {
35615
+ const resp = await fetch(baseUrl + "/api/tags", { signal: AbortSignal.timeout(2e3) });
35616
+ if (resp.ok)
35617
+ ready = true;
35618
+ } catch {
35619
+ }
35620
+ }
35621
+ if (ready) {
35622
+ renderInfo(`Ollama restarted with OLLAMA_NUM_PARALLEL=${n}. ${n > 4 ? "Note: memory usage scales with parallel slots." : ""}`);
35623
+ } else {
35624
+ renderWarning(`Ollama service restarted but not responding yet. Check: sudo systemctl status ollama`);
35625
+ }
35626
+ } catch (e) {
35627
+ renderError(`Failed to set systemd override: ${e.message || e}`);
35628
+ renderInfo(`Manual steps:
35629
+ sudo mkdir -p /etc/systemd/system/ollama.service.d
35630
+ echo '[Service]\\nEnvironment="OLLAMA_NUM_PARALLEL=${n}"' | sudo tee /etc/systemd/system/ollama.service.d/parallel.conf
35631
+ sudo systemctl daemon-reload && sudo systemctl restart ollama`);
35632
+ }
35633
+ } else {
35634
+ renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
35635
+ try {
35636
+ try {
35637
+ execSync29("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
35638
+ } catch {
35639
+ }
35640
+ await new Promise((r) => setTimeout(r, 1e3));
35641
+ process.env.OLLAMA_NUM_PARALLEL = String(n);
35642
+ const { spawn: spawn19 } = await import("node:child_process");
35643
+ const child = spawn19("ollama", ["serve"], {
35644
+ stdio: "ignore",
35645
+ detached: true,
35646
+ env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n) }
35647
+ });
35648
+ child.unref();
35649
+ let ready = false;
35650
+ for (let i = 0; i < 30 && !ready; i++) {
35651
+ await new Promise((r) => setTimeout(r, 500));
35652
+ try {
35653
+ const resp = await fetch(baseUrl + "/api/tags", { signal: AbortSignal.timeout(2e3) });
35654
+ if (resp.ok)
35655
+ ready = true;
35656
+ } catch {
35657
+ }
35658
+ }
35659
+ if (ready) {
35660
+ renderInfo(`Ollama restarted with OLLAMA_NUM_PARALLEL=${n}. ${n > 4 ? "Note: memory usage scales with parallel slots." : ""}`);
35661
+ } else {
35662
+ renderWarning(`Ollama restarted but not responding yet. Try: OLLAMA_NUM_PARALLEL=${n} ollama serve`);
35663
+ }
35664
+ } catch (e) {
35665
+ renderError(`Failed to restart Ollama: ${e.message || e}`);
35666
+ renderInfo(`Set manually: OLLAMA_NUM_PARALLEL=${n} ollama serve`);
35667
+ }
35668
+ }
35669
+ }
35518
35670
  async function handleUpdate(subcommand, ctx) {
35519
35671
  const repoRoot = ctx.repoRoot;
35520
35672
  if (subcommand === "auto") {
@@ -46501,7 +46653,7 @@ function formatDMNToolArgs(toolName, args) {
46501
46653
  return "";
46502
46654
  }
46503
46655
  }
46504
- function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler) {
46656
+ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler, thinkingEnabled) {
46505
46657
  const voiceStyleMap = {
46506
46658
  concise: 1,
46507
46659
  balanced: 3,
@@ -46549,9 +46701,9 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
46549
46701
  return baseSendFn(cmd, args, timeout);
46550
46702
  };
46551
46703
  const targetPeer = config.backendUrl.startsWith("peer://") ? config.backendUrl.slice(7) : void 0;
46552
- backend = new NexusAgenticBackend(sendFn, config.model, targetPeer, config.apiKey);
46704
+ backend = new NexusAgenticBackend(sendFn, config.model, targetPeer, config.apiKey, thinkingEnabled);
46553
46705
  } else {
46554
- backend = new OllamaAgenticBackend(config.backendUrl, config.model, config.apiKey);
46706
+ backend = new OllamaAgenticBackend(config.backendUrl, config.model, config.apiKey, thinkingEnabled);
46555
46707
  }
46556
46708
  try {
46557
46709
  const endpointHistory = loadUsageHistory("endpoint", repoRoot);
@@ -46617,6 +46769,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
46617
46769
  dynamicContext,
46618
46770
  modelTier,
46619
46771
  streamEnabled: stream?.enabled ?? false,
46772
+ thinking: thinkingEnabled,
46620
46773
  bruteForce: bruteForce ?? true,
46621
46774
  bruteForceMaxCycles: 100,
46622
46775
  // effectively unlimited — no hard timeout, agent runs until complete or aborted
@@ -46730,6 +46883,8 @@ ${entry.fullContent}`
46730
46883
  "ep",
46731
46884
  "update",
46732
46885
  "upgrade",
46886
+ "parallel",
46887
+ "think",
46733
46888
  "telegram",
46734
46889
  "tg",
46735
46890
  "call",
@@ -47078,6 +47233,7 @@ async function startInteractive(config, repoPath) {
47078
47233
  if (savedSettings.dbPath)
47079
47234
  config = { ...config, dbPath: savedSettings.dbPath };
47080
47235
  let streamEnabled = savedSettings.stream ?? false;
47236
+ let thinkingEnabled = savedSettings.thinking !== false;
47081
47237
  let bruteForceEnabled = savedSettings.bruteforce ?? true;
47082
47238
  let currentStyle = PRESET_NAMES.includes(savedSettings.style) ? savedSettings.style : "balanced";
47083
47239
  let deepContextEnabled = savedSettings.deepContext ?? false;
@@ -47759,6 +47915,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
47759
47915
  streamEnabled = !streamEnabled;
47760
47916
  return streamEnabled;
47761
47917
  },
47918
+ thinkToggle() {
47919
+ thinkingEnabled = !thinkingEnabled;
47920
+ return thinkingEnabled;
47921
+ },
47762
47922
  bruteForceToggle() {
47763
47923
  bruteForceEnabled = !bruteForceEnabled;
47764
47924
  return bruteForceEnabled;
@@ -48912,7 +49072,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
48912
49072
  }, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
48913
49073
  lastCompletedSummary = summary;
48914
49074
  lastTaskMeta = meta ?? null;
48915
- }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler());
49075
+ }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled);
48916
49076
  activeTask = task;
48917
49077
  showPrompt();
48918
49078
  await task.promise;
@@ -49144,7 +49304,7 @@ NEW TASK: ${fullInput}`;
49144
49304
  }, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
49145
49305
  lastCompletedSummary = summary;
49146
49306
  lastTaskMeta = meta ?? null;
49147
- }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler());
49307
+ }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled);
49148
49308
  activeTask = task;
49149
49309
  showPrompt();
49150
49310
  await task.promise;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.72",
3
+ "version": "0.103.74",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",