open-agents-ai 0.185.81 → 0.185.83

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 +97 -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,35 @@ 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 = (historyLines ? `Previous conversation:
67938
+ ${historyLines}
67939
+
67940
+ ` : "") + `${chatBody.message}
67941
+
67942
+ Respond conversationally. Call task_complete with your final response.`;
67943
+ const oaBin = process.argv[1] || "oa";
67944
+ const args = [taskPrompt, "--json", "--non-interactive"];
67945
+ if (model)
67946
+ args.push("--model", model.replace(/^local\//, ""));
67939
67947
  const streamMode = chatBody.stream !== false;
67940
- const chatRequest = {
67941
- model: session.model,
67942
- messages,
67943
- stream: streamMode,
67944
- max_tokens: chatBody.max_tokens || 4096
67948
+ const runEnv = {
67949
+ ...process.env,
67950
+ __OPEN_AGENTS_NO_AUTO_RUN: "",
67951
+ OA_RUN_USER: req._authUser || "anonymous",
67952
+ OA_RUN_SCOPE: req._authScope || "admin"
67945
67953
  };
67946
- const route = resolveModelEndpoint(session.model);
67947
- const targetUrl = route?.endpoint?.url || loadConfig().backendUrl;
67954
+ const child = spawn21("oa", args, {
67955
+ cwd: cwdPath,
67956
+ env: runEnv,
67957
+ stdio: ["ignore", "pipe", "pipe"],
67958
+ detached: true
67959
+ });
67960
+ child.unref();
67948
67961
  if (streamMode) {
67949
67962
  res.writeHead(200, {
67950
67963
  "Content-Type": "text/event-stream",
@@ -67953,86 +67966,79 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67953
67966
  "X-Session-ID": session.id
67954
67967
  });
67955
67968
  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();
67969
+ let lastOutput = "";
67970
+ child.stdout?.on("data", (chunk) => {
67971
+ const text = chunk.toString();
67972
+ for (const line of text.split("\n")) {
67973
+ if (!line.trim())
67974
+ continue;
67975
+ try {
67976
+ const evt = JSON.parse(line);
67977
+ if (evt.type === "assistant_text" || evt.type === "text") {
67978
+ const delta = evt.content || evt.text || "";
67979
+ fullContent += delta;
67980
+ res.write("data: " + JSON.stringify({
67981
+ id: `chatcmpl-${session.id.slice(0, 8)}`,
67982
+ object: "chat.completion.chunk",
67983
+ choices: [{ index: 0, delta: { content: delta }, finish_reason: null }]
67984
+ }) + "\n\n");
67985
+ } else if (evt.type === "tool_call") {
67986
+ res.write("data: " + JSON.stringify({
67987
+ type: "tool_call",
67988
+ tool: evt.tool || evt.name,
67989
+ args: evt.args
67990
+ }) + "\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
+ }
67996
+ lastOutput = line;
67997
+ } catch {
67998
+ if (line.trim() && !line.startsWith("{")) {
67999
+ fullContent += line;
68000
+ res.write("data: " + JSON.stringify({
68001
+ id: `chatcmpl-${session.id.slice(0, 8)}`,
68002
+ object: "chat.completion.chunk",
68003
+ choices: [{ index: 0, delta: { content: line }, finish_reason: null }]
68004
+ }) + "\n\n");
68005
+ }
68006
+ }
68007
+ }
68008
+ });
68009
+ child.stderr?.on("data", () => {
68010
+ });
68011
+ child.on("close", () => {
68012
+ addAssistantMessage(session, fullContent);
68013
+ res.write("data: [DONE]\n\n");
68014
+ res.end();
68015
+ });
68016
68016
  } 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 });
68017
+ let output = "";
68018
+ child.stdout?.on("data", (chunk) => {
68019
+ output += chunk.toString();
68020
+ });
68021
+ child.stderr?.on("data", () => {
68022
+ });
68023
+ await new Promise((resolve36) => child.on("close", resolve36));
68024
+ 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";
68035
+ }
68035
68036
  }
68037
+ addAssistantMessage(session, content.trim());
68038
+ jsonResponse(res, 200, {
68039
+ session_id: session.id,
68040
+ message: { role: "assistant", content: content.trim() }
68041
+ });
68036
68042
  }
68037
68043
  return;
68038
68044
  }
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.83",
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",