open-agents-ai 0.185.81 → 0.185.82

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 +105 -91
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -66411,10 +66411,6 @@ function addAssistantMessage(session, content) {
66411
66411
  session.messages.push({ role: "assistant", content });
66412
66412
  session.lastActivity = Date.now();
66413
66413
  }
66414
- function trackSessionTokens(session, tokensIn, tokensOut) {
66415
- session.tokensIn += tokensIn;
66416
- session.tokensOut += tokensOut;
66417
- }
66418
66414
  function listSessions() {
66419
66415
  return Array.from(sessions.values()).map((s) => ({
66420
66416
  id: s.id,
@@ -67933,18 +67929,43 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67933
67929
  }
67934
67930
  const sessionId = chatBody.session_id;
67935
67931
  const model = chatBody.model || loadConfig().model;
67936
- const session = getSession(sessionId, model, resolve31(process.cwd()));
67937
- const messages = addUserMessage(session, chatBody.message);
67932
+ const cwdPath = resolve31(process.cwd());
67933
+ const session = getSession(sessionId, model, cwdPath);
67934
+ addUserMessage(session, chatBody.message);
67938
67935
  compactSession(session);
67936
+ 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:
67946
+ ${historyLines}
67947
+
67948
+ ` : "") + `User's latest message: ${chatBody.message}
67949
+
67950
+ Respond conversationally. Call task_complete with your response when done.`;
67951
+ const oaBin = process.argv[1] || "oa";
67952
+ const args = [taskPrompt, "--json", "--non-interactive"];
67953
+ if (model)
67954
+ args.push("--model", model.replace(/^local\//, ""));
67939
67955
  const streamMode = chatBody.stream !== false;
67940
- const chatRequest = {
67941
- model: session.model,
67942
- messages,
67943
- stream: streamMode,
67944
- max_tokens: chatBody.max_tokens || 4096
67956
+ const runEnv = {
67957
+ ...process.env,
67958
+ __OPEN_AGENTS_NO_AUTO_RUN: "",
67959
+ OA_RUN_USER: req._authUser || "anonymous",
67960
+ OA_RUN_SCOPE: req._authScope || "admin"
67945
67961
  };
67946
- const route = resolveModelEndpoint(session.model);
67947
- const targetUrl = route?.endpoint?.url || loadConfig().backendUrl;
67962
+ const child = spawn21("oa", args, {
67963
+ cwd: cwdPath,
67964
+ env: runEnv,
67965
+ stdio: ["ignore", "pipe", "pipe"],
67966
+ detached: true
67967
+ });
67968
+ child.unref();
67948
67969
  if (streamMode) {
67949
67970
  res.writeHead(200, {
67950
67971
  "Content-Type": "text/event-stream",
@@ -67953,86 +67974,79 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67953
67974
  "X-Session-ID": session.id
67954
67975
  });
67955
67976
  let fullContent = "";
67956
- try {
67957
- const url = new URL("/api/chat", targetUrl);
67958
- const isHttps = url.protocol === "https:";
67959
- const transport = isHttps ? https : http;
67960
- const reqBody = JSON.stringify({
67961
- model: session.model.replace(/^local\//, ""),
67962
- messages: messages.map((m) => ({ role: m.role, content: m.content })),
67963
- stream: true
67964
- });
67965
- await new Promise((resolve36, reject) => {
67966
- const proxyReq = transport.request({
67967
- hostname: url.hostname,
67968
- port: url.port || (isHttps ? 443 : 80),
67969
- path: url.pathname,
67970
- method: "POST",
67971
- headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(reqBody) }
67972
- }, (proxyRes) => {
67973
- let buffer = "";
67974
- proxyRes.on("data", (chunk) => {
67975
- buffer += chunk.toString();
67976
- const lines = buffer.split("\n");
67977
- buffer = lines.pop() || "";
67978
- for (const line of lines) {
67979
- if (!line.trim())
67980
- continue;
67981
- try {
67982
- const parsed = JSON.parse(line);
67983
- if (parsed.message?.content) {
67984
- fullContent += parsed.message.content;
67985
- const sseChunk = {
67986
- id: `chatcmpl-${session.id.slice(0, 8)}`,
67987
- object: "chat.completion.chunk",
67988
- choices: [{ index: 0, delta: { content: parsed.message.content }, finish_reason: null }]
67989
- };
67990
- res.write("data: " + JSON.stringify(sseChunk) + "\n\n");
67991
- }
67992
- if (parsed.done) {
67993
- trackSessionTokens(session, parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
67994
- trackTokens("local", parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
67995
- metrics.totalTokensIn += parsed.prompt_eval_count ?? 0;
67996
- metrics.totalTokensOut += parsed.eval_count ?? 0;
67997
- res.write("data: [DONE]\n\n");
67998
- }
67999
- } catch {
68000
- }
68001
- }
68002
- });
68003
- proxyRes.on("end", resolve36);
68004
- proxyRes.on("error", reject);
68005
- });
68006
- proxyReq.setTimeout(12e4, () => proxyReq.destroy(new Error("Chat stream timeout")));
68007
- proxyReq.on("error", reject);
68008
- proxyReq.write(reqBody);
68009
- proxyReq.end();
68010
- });
68011
- } catch (e) {
68012
- res.write("data: " + JSON.stringify({ error: e.message }) + "\n\n");
68013
- }
68014
- addAssistantMessage(session, fullContent);
68015
- res.end();
67977
+ let lastOutput = "";
67978
+ child.stdout?.on("data", (chunk) => {
67979
+ const text = chunk.toString();
67980
+ for (const line of text.split("\n")) {
67981
+ if (!line.trim())
67982
+ continue;
67983
+ try {
67984
+ const evt = JSON.parse(line);
67985
+ if (evt.type === "assistant_text" || evt.type === "text") {
67986
+ const delta = evt.content || evt.text || "";
67987
+ fullContent += delta;
67988
+ res.write("data: " + JSON.stringify({
67989
+ id: `chatcmpl-${session.id.slice(0, 8)}`,
67990
+ object: "chat.completion.chunk",
67991
+ choices: [{ index: 0, delta: { content: delta }, finish_reason: null }]
67992
+ }) + "\n\n");
67993
+ } else if (evt.type === "tool_call") {
67994
+ res.write("data: " + JSON.stringify({
67995
+ type: "tool_call",
67996
+ tool: evt.tool || evt.name,
67997
+ args: evt.args
67998
+ }) + "\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
+ }
68004
+ lastOutput = line;
68005
+ } catch {
68006
+ if (line.trim() && !line.startsWith("{")) {
68007
+ fullContent += line;
68008
+ res.write("data: " + JSON.stringify({
68009
+ id: `chatcmpl-${session.id.slice(0, 8)}`,
68010
+ object: "chat.completion.chunk",
68011
+ choices: [{ index: 0, delta: { content: line }, finish_reason: null }]
68012
+ }) + "\n\n");
68013
+ }
68014
+ }
68015
+ }
68016
+ });
68017
+ child.stderr?.on("data", () => {
68018
+ });
68019
+ child.on("close", () => {
68020
+ addAssistantMessage(session, fullContent);
68021
+ res.write("data: [DONE]\n\n");
68022
+ res.end();
68023
+ });
68016
68024
  } else {
68017
- try {
68018
- const result = await ollamaRequest(targetUrl, "/api/chat", "POST", JSON.stringify({
68019
- model: session.model.replace(/^local\//, ""),
68020
- messages: messages.map((m) => ({ role: m.role, content: m.content })),
68021
- stream: false
68022
- }));
68023
- const parsed = JSON.parse(result.body);
68024
- const content = parsed.message?.content ?? "";
68025
- addAssistantMessage(session, content);
68026
- trackSessionTokens(session, parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
68027
- trackTokens("local", parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
68028
- jsonResponse(res, 200, {
68029
- session_id: session.id,
68030
- message: { role: "assistant", content },
68031
- usage: { prompt_tokens: parsed.prompt_eval_count ?? 0, completion_tokens: parsed.eval_count ?? 0 }
68032
- });
68033
- } catch (e) {
68034
- jsonResponse(res, 500, { error: "Chat failed", message: e.message });
68025
+ let output = "";
68026
+ child.stdout?.on("data", (chunk) => {
68027
+ output += chunk.toString();
68028
+ });
68029
+ child.stderr?.on("data", () => {
68030
+ });
68031
+ await new Promise((resolve36) => child.on("close", resolve36));
68032
+ 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";
68043
+ }
68035
68044
  }
68045
+ addAssistantMessage(session, content.trim());
68046
+ jsonResponse(res, 200, {
68047
+ session_id: session.id,
68048
+ message: { role: "assistant", content: content.trim() }
68049
+ });
68036
68050
  }
68037
68051
  return;
68038
68052
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.185.81",
3
+ "version": "0.185.82",
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",