open-agents-ai 0.185.82 → 0.185.84

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 +136 -46
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -65740,9 +65740,19 @@ async function sendMessage() {
65740
65740
 
65741
65741
  const msgDiv = addMessage('assistant', '');
65742
65742
  let fullContent = '';
65743
+ let chatTools = []; // tool calls collected during streaming
65744
+ let metaInfo = null; // completion metadata
65745
+
65746
+ // Tool calls container \u2014 shown live during streaming
65747
+ const toolsContainer = document.createElement('div');
65748
+ toolsContainer.style.cssText = 'margin:4px 0;font-size:0.7rem';
65749
+ msgDiv.appendChild(toolsContainer);
65750
+
65751
+ // Content container
65752
+ const contentDiv = document.createElement('div');
65753
+ msgDiv.appendChild(contentDiv);
65743
65754
 
65744
65755
  try {
65745
- // Use stateful /v1/chat endpoint (maintains OA identity + context)
65746
65756
  const body = {
65747
65757
  session_id: chatSessionId,
65748
65758
  model: modelSelect.value,
@@ -65757,7 +65767,6 @@ async function sendMessage() {
65757
65767
  body: JSON.stringify(body),
65758
65768
  });
65759
65769
 
65760
- // Capture session ID from response header
65761
65770
  const sid = response.headers.get('x-session-id');
65762
65771
  if (sid) chatSessionId = sid;
65763
65772
 
@@ -65779,10 +65788,38 @@ async function sendMessage() {
65779
65788
  if (data === '[DONE]') continue;
65780
65789
  try {
65781
65790
  const chunk = JSON.parse(data);
65791
+
65792
+ // Tool call event \u2014 show live
65793
+ if (chunk.type === 'tool_call') {
65794
+ chatTools.push(chunk);
65795
+ const toolEl = document.createElement('div');
65796
+ toolEl.style.cssText = 'background:#1e1e22;border-left:2px solid #b2920a;padding:4px 8px;margin:2px 0;color:#888';
65797
+ toolEl.textContent = '\\u25B8 ' + (chunk.tool || 'tool') + (chunk.args ? ': ' + JSON.stringify(chunk.args).slice(0,80) : '');
65798
+ toolsContainer.appendChild(toolEl);
65799
+ conv.scrollTop = conv.scrollHeight;
65800
+ continue;
65801
+ }
65802
+
65803
+ // Tool result
65804
+ if (chunk.type === 'tool_result') {
65805
+ const resultEl = document.createElement('div');
65806
+ resultEl.style.cssText = 'background:#1e1e22;padding:2px 8px 2px 18px;margin:0 0 2px 0;color:#555;font-size:0.65rem;max-height:60px;overflow:hidden';
65807
+ resultEl.textContent = (chunk.output || '').slice(0, 150);
65808
+ toolsContainer.appendChild(resultEl);
65809
+ continue;
65810
+ }
65811
+
65812
+ // Completion metadata
65813
+ if (chunk.type === 'complete') {
65814
+ metaInfo = chunk;
65815
+ continue;
65816
+ }
65817
+
65818
+ // Content delta
65782
65819
  const delta = chunk.choices?.[0]?.delta?.content || '';
65783
65820
  if (delta) {
65784
65821
  fullContent += delta;
65785
- msgDiv.innerHTML = renderMarkdown(fullContent);
65822
+ contentDiv.innerHTML = renderMarkdown(fullContent);
65786
65823
  conv.scrollTop = conv.scrollHeight;
65787
65824
  }
65788
65825
  } catch {}
@@ -65790,9 +65827,23 @@ async function sendMessage() {
65790
65827
  }
65791
65828
 
65792
65829
  messages.push({ role: 'assistant', content: fullContent });
65793
- updateTokenCounter(fullContent.split(/\\s+/).length * 1.3 | 0); // rough token estimate
65794
- // Re-render with copy button
65795
- msgDiv.innerHTML = renderMarkdown(fullContent);
65830
+ updateTokenCounter(fullContent.split(/\\s+/).length * 1.3 | 0);
65831
+
65832
+ // Final render: content + collapsible tools
65833
+ contentDiv.innerHTML = renderMarkdown(fullContent);
65834
+
65835
+ // Collapse tool calls into a dropdown after streaming completes
65836
+ if (chatTools.length > 0) {
65837
+ const details = document.createElement('details');
65838
+ details.style.cssText = 'margin:4px 0;font-size:0.65rem;color:#555';
65839
+ const summary = document.createElement('summary');
65840
+ summary.style.cssText = 'cursor:pointer;color:#b2920a;font-size:0.65rem';
65841
+ summary.textContent = chatTools.length + ' tool call' + (chatTools.length > 1 ? 's' : '') + (metaInfo?.tokens ? ' | ' + metaInfo.tokens + ' tokens' : '') + (metaInfo?.duration ? ' | ' + (metaInfo.duration/1000).toFixed(1) + 's' : '');
65842
+ details.appendChild(summary);
65843
+ // Move live tool elements into the details
65844
+ while (toolsContainer.firstChild) details.appendChild(toolsContainer.firstChild);
65845
+ toolsContainer.appendChild(details);
65846
+ }
65796
65847
  const actions = document.createElement('div');
65797
65848
  actions.className = 'msg-actions';
65798
65849
  const copyBtn = document.createElement('button');
@@ -67934,20 +67985,12 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67934
67985
  addUserMessage(session, chatBody.message);
67935
67986
  compactSession(session);
67936
67987
  const historyLines = session.messages.filter((m) => m.role !== "system").slice(-10).map((m) => m.role === "user" ? `User: ${m.content}` : `Assistant: ${m.content}`).join("\n");
67937
- const taskPrompt = `You are in a conversational chat session. Respond naturally and helpfully.
67938
- Use your tools (web_search, web_fetch, file_read, shell, memory_read, etc.) when the user's request requires real data.
67939
- If the user asks about current events, news, or real-time data \u2014 use web_search to find it.
67940
- If the user asks about files or code \u2014 use file_read.
67941
- If the user asks you to run something \u2014 use shell.
67942
- NEVER say "I don't have browsing capabilities" \u2014 you DO have web_search and web_fetch.
67943
- NEVER say "I'm just an AI" \u2014 you are Open Agent with full tool access.
67944
-
67945
- ` + (historyLines ? `Previous conversation:
67988
+ const taskPrompt = (historyLines ? `Previous conversation:
67946
67989
  ${historyLines}
67947
67990
 
67948
- ` : "") + `User's latest message: ${chatBody.message}
67991
+ ` : "") + `${chatBody.message}
67949
67992
 
67950
- Respond conversationally. Call task_complete with your response when done.`;
67993
+ Respond conversationally. Call task_complete with your final response.`;
67951
67994
  const oaBin = process.argv[1] || "oa";
67952
67995
  const args = [taskPrompt, "--json", "--non-interactive"];
67953
67996
  if (model)
@@ -67975,14 +68018,27 @@ Respond conversationally. Call task_complete with your response when done.`;
67975
68018
  });
67976
68019
  let fullContent = "";
67977
68020
  let lastOutput = "";
68021
+ let toolCalls = [];
68022
+ let rawBuffer = "";
67978
68023
  child.stdout?.on("data", (chunk) => {
67979
- const text = chunk.toString();
67980
- for (const line of text.split("\n")) {
68024
+ rawBuffer += chunk.toString();
68025
+ const lines = rawBuffer.split("\n");
68026
+ rawBuffer = lines.pop() || "";
68027
+ for (const line of lines) {
67981
68028
  if (!line.trim())
67982
68029
  continue;
67983
68030
  try {
67984
68031
  const evt = JSON.parse(line);
67985
- if (evt.type === "assistant_text" || evt.type === "text") {
68032
+ if (evt.type === "tool_call" || evt.tool) {
68033
+ const toolInfo = { tool: evt.tool || evt.name || "unknown", args: evt.args };
68034
+ toolCalls.push(toolInfo);
68035
+ res.write("data: " + JSON.stringify({ type: "tool_call", ...toolInfo }) + "\n\n");
68036
+ } else if (evt.type === "tool_result") {
68037
+ const lastTool = toolCalls[toolCalls.length - 1];
68038
+ if (lastTool)
68039
+ lastTool.result = (evt.output || evt.result || "").slice(0, 500);
68040
+ res.write("data: " + JSON.stringify({ type: "tool_result", output: (evt.output || evt.result || "").slice(0, 200) }) + "\n\n");
68041
+ } else if (evt.type === "assistant_text" || evt.type === "text") {
67986
68042
  const delta = evt.content || evt.text || "";
67987
68043
  fullContent += delta;
67988
68044
  res.write("data: " + JSON.stringify({
@@ -67990,33 +68046,59 @@ Respond conversationally. Call task_complete with your response when done.`;
67990
68046
  object: "chat.completion.chunk",
67991
68047
  choices: [{ index: 0, delta: { content: delta }, finish_reason: null }]
67992
68048
  }) + "\n\n");
67993
- } else if (evt.type === "tool_call") {
68049
+ } else if (evt.status === "completed" || evt.type === "task_complete") {
68050
+ const summary = evt.summary || evt.content || "";
68051
+ const contentMatch = summary.match(/Tokens:\s*[\d,]+\s+(.*)/s);
68052
+ const cleanContent = contentMatch ? contentMatch[1].trim() : summary;
68053
+ if (cleanContent && cleanContent.length > 5) {
68054
+ fullContent = cleanContent;
68055
+ res.write("data: " + JSON.stringify({
68056
+ id: `chatcmpl-${session.id.slice(0, 8)}`,
68057
+ object: "chat.completion.chunk",
68058
+ choices: [{ index: 0, delta: { content: cleanContent }, finish_reason: null }]
68059
+ }) + "\n\n");
68060
+ }
67994
68061
  res.write("data: " + JSON.stringify({
67995
- type: "tool_call",
67996
- tool: evt.tool || evt.name,
67997
- args: evt.args
68062
+ type: "complete",
68063
+ turns: evt.turns || summary.match(/(\d+) turns/)?.[1],
68064
+ toolCalls: toolCalls.length,
68065
+ tokens: evt.tokens || summary.match(/Tokens:\s*([\d,]+)/)?.[1],
68066
+ duration: evt.durationMs || evt.duration
67998
68067
  }) + "\n\n");
67999
- } else if (evt.type === "task_complete") {
68000
- const summary = evt.summary || evt.content || "";
68001
- if (summary && !fullContent.includes(summary))
68002
- fullContent += summary;
68003
68068
  }
68004
- lastOutput = line;
68005
68069
  } catch {
68006
- if (line.trim() && !line.startsWith("{")) {
68007
- fullContent += line;
68070
+ }
68071
+ }
68072
+ });
68073
+ child.stderr?.on("data", () => {
68074
+ });
68075
+ child.on("close", () => {
68076
+ if (!fullContent && rawBuffer.trim()) {
68077
+ try {
68078
+ const result = JSON.parse(rawBuffer.trim());
68079
+ const summary = result.summary || "";
68080
+ const match = summary.match(/Tokens:\s*[\d,]+\s+([\s\S]*)/);
68081
+ const cleanContent = match ? match[1].trim() : summary;
68082
+ if (cleanContent) {
68083
+ fullContent = cleanContent;
68008
68084
  res.write("data: " + JSON.stringify({
68009
68085
  id: `chatcmpl-${session.id.slice(0, 8)}`,
68010
68086
  object: "chat.completion.chunk",
68011
- choices: [{ index: 0, delta: { content: line }, finish_reason: null }]
68087
+ choices: [{ index: 0, delta: { content: cleanContent }, finish_reason: null }]
68088
+ }) + "\n\n");
68089
+ const turns = summary.match(/(\d+) turns/)?.[1];
68090
+ const tokens = summary.match(/Tokens:\s*([\d,]+)/)?.[1];
68091
+ res.write("data: " + JSON.stringify({
68092
+ type: "complete",
68093
+ turns,
68094
+ tokens,
68095
+ duration: result.durationMs,
68096
+ toolCalls: parseInt(summary.match(/(\d+) tool calls/)?.[1] || "0", 10)
68012
68097
  }) + "\n\n");
68013
68098
  }
68099
+ } catch {
68014
68100
  }
68015
68101
  }
68016
- });
68017
- child.stderr?.on("data", () => {
68018
- });
68019
- child.on("close", () => {
68020
68102
  addAssistantMessage(session, fullContent);
68021
68103
  res.write("data: [DONE]\n\n");
68022
68104
  res.end();
@@ -68030,16 +68112,24 @@ Respond conversationally. Call task_complete with your response when done.`;
68030
68112
  });
68031
68113
  await new Promise((resolve36) => child.on("close", resolve36));
68032
68114
  let content = "";
68033
- for (const line of output.split("\n")) {
68034
- try {
68035
- const evt = JSON.parse(line);
68036
- if (evt.type === "assistant_text" || evt.type === "text")
68037
- content += evt.content || evt.text || "";
68038
- else if (evt.type === "task_complete")
68039
- content += evt.summary || evt.content || "";
68040
- } catch {
68041
- if (line.trim() && !line.startsWith("{"))
68042
- content += line + "\n";
68115
+ try {
68116
+ const result = JSON.parse(output.trim());
68117
+ const summary = result.summary || "";
68118
+ const match = summary.match(/Tokens:\s*[\d,]+\s+([\s\S]*)/);
68119
+ content = match ? match[1].trim() : summary;
68120
+ } catch {
68121
+ for (const line of output.split("\n")) {
68122
+ if (!line.trim())
68123
+ continue;
68124
+ try {
68125
+ const evt = JSON.parse(line);
68126
+ if (evt.status === "completed") {
68127
+ const summary = evt.summary || "";
68128
+ const match = summary.match(/Tokens:\s*[\d,]+\s+([\s\S]*)/);
68129
+ content = match ? match[1].trim() : summary;
68130
+ }
68131
+ } catch {
68132
+ }
68043
68133
  }
68044
68134
  }
68045
68135
  addAssistantMessage(session, content.trim());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.185.82",
3
+ "version": "0.185.84",
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",