open-agents-ai 0.185.83 → 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 +133 -35
  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');
@@ -67967,14 +68018,27 @@ Respond conversationally. Call task_complete with your final response.`;
67967
68018
  });
67968
68019
  let fullContent = "";
67969
68020
  let lastOutput = "";
68021
+ let toolCalls = [];
68022
+ let rawBuffer = "";
67970
68023
  child.stdout?.on("data", (chunk) => {
67971
- const text = chunk.toString();
67972
- 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) {
67973
68028
  if (!line.trim())
67974
68029
  continue;
67975
68030
  try {
67976
68031
  const evt = JSON.parse(line);
67977
- 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") {
67978
68042
  const delta = evt.content || evt.text || "";
67979
68043
  fullContent += delta;
67980
68044
  res.write("data: " + JSON.stringify({
@@ -67982,33 +68046,59 @@ Respond conversationally. Call task_complete with your final response.`;
67982
68046
  object: "chat.completion.chunk",
67983
68047
  choices: [{ index: 0, delta: { content: delta }, finish_reason: null }]
67984
68048
  }) + "\n\n");
67985
- } 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
+ }
67986
68061
  res.write("data: " + JSON.stringify({
67987
- type: "tool_call",
67988
- tool: evt.tool || evt.name,
67989
- 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
67990
68067
  }) + "\n\n");
67991
- } else if (evt.type === "task_complete") {
67992
- const summary = evt.summary || evt.content || "";
67993
- if (summary && !fullContent.includes(summary))
67994
- fullContent += summary;
67995
68068
  }
67996
- lastOutput = line;
67997
68069
  } catch {
67998
- if (line.trim() && !line.startsWith("{")) {
67999
- 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;
68000
68084
  res.write("data: " + JSON.stringify({
68001
68085
  id: `chatcmpl-${session.id.slice(0, 8)}`,
68002
68086
  object: "chat.completion.chunk",
68003
- 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)
68004
68097
  }) + "\n\n");
68005
68098
  }
68099
+ } catch {
68006
68100
  }
68007
68101
  }
68008
- });
68009
- child.stderr?.on("data", () => {
68010
- });
68011
- child.on("close", () => {
68012
68102
  addAssistantMessage(session, fullContent);
68013
68103
  res.write("data: [DONE]\n\n");
68014
68104
  res.end();
@@ -68022,16 +68112,24 @@ Respond conversationally. Call task_complete with your final response.`;
68022
68112
  });
68023
68113
  await new Promise((resolve36) => child.on("close", resolve36));
68024
68114
  let content = "";
68025
- for (const line of output.split("\n")) {
68026
- try {
68027
- const evt = JSON.parse(line);
68028
- if (evt.type === "assistant_text" || evt.type === "text")
68029
- content += evt.content || evt.text || "";
68030
- else if (evt.type === "task_complete")
68031
- content += evt.summary || evt.content || "";
68032
- } catch {
68033
- if (line.trim() && !line.startsWith("{"))
68034
- 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
+ }
68035
68133
  }
68036
68134
  }
68037
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.83",
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",