open-agents-ai 0.187.234 → 0.187.236

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 +268 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -270510,8 +270510,10 @@ TASK: ${task}` : task;
270510
270510
  this._lastTodoReminderTurn = -1;
270511
270511
  let pendingConstraintWarnings = [];
270512
270512
  let consecutiveTextOnly = 0;
270513
+ let consecutiveThinkOnly = 0;
270513
270514
  let loopInterventionCount = 0;
270514
270515
  const MAX_CONSECUTIVE_TEXT_ONLY = 3;
270516
+ const MAX_CONSECUTIVE_THINK_ONLY = 6;
270515
270517
  let narratedToolCallCount = 0;
270516
270518
  let consecutiveEmptyResponses = 0;
270517
270519
  let sameToolFailStreak = 0;
@@ -271006,6 +271008,7 @@ ${memoryLines.join("\n")}`
271006
271008
  consecutiveEmptyResponses = 0;
271007
271009
  if (msg.toolCalls && msg.toolCalls.length > 0) {
271008
271010
  consecutiveTextOnly = 0;
271011
+ consecutiveThinkOnly = 0;
271009
271012
  messages2.push({
271010
271013
  role: "assistant",
271011
271014
  content: msg.content || null,
@@ -271639,7 +271642,13 @@ Call task_complete(summary="...") NOW with whatever you have.`
271639
271642
  } else {
271640
271643
  const content = msg.content || "";
271641
271644
  messages2.push({ role: "assistant", content });
271642
- consecutiveTextOnly++;
271645
+ if (isThinkOnly) {
271646
+ consecutiveThinkOnly++;
271647
+ consecutiveTextOnly = 0;
271648
+ } else {
271649
+ consecutiveTextOnly++;
271650
+ consecutiveThinkOnly = 0;
271651
+ }
271643
271652
  this.emit({
271644
271653
  type: "model_response",
271645
271654
  content: content.slice(0, 200),
@@ -271655,6 +271664,20 @@ Call task_complete(summary="...") NOW with whatever you have.`
271655
271664
  summary = content;
271656
271665
  break;
271657
271666
  }
271667
+ if (isThinkOnly) {
271668
+ if (consecutiveThinkOnly >= MAX_CONSECUTIVE_THINK_ONLY) {
271669
+ this.emit({
271670
+ type: "status",
271671
+ content: `Model produced ${consecutiveThinkOnly} consecutive think-only responses — nudging toward visible output`,
271672
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
271673
+ });
271674
+ messages2.push({
271675
+ role: "user",
271676
+ content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response."
271677
+ });
271678
+ }
271679
+ continue;
271680
+ }
271658
271681
  if (consecutiveTextOnly >= MAX_CONSECUTIVE_TEXT_ONLY) {
271659
271682
  this.emit({
271660
271683
  type: "status",
@@ -271739,6 +271762,7 @@ Call task_complete(summary="...") NOW with whatever you have.`
271739
271762
  }
271740
271763
  prevCycleToolCalls = toolCallCount;
271741
271764
  consecutiveTextOnly = 0;
271765
+ consecutiveThinkOnly = 0;
271742
271766
  this.emit({
271743
271767
  type: "status",
271744
271768
  content: `Re-engaging — cycle ${bruteForceCycle} (${totalTurns} turns, ${toolCallCount} tool calls so far)`,
@@ -271883,8 +271907,10 @@ Integrate this guidance into your current approach. Continue working on the task
271883
271907
  if (!choice)
271884
271908
  break;
271885
271909
  const msg = choice.message;
271910
+ const isThinkOnlyBF = response._thinkOnly === true;
271886
271911
  if (msg.toolCalls && msg.toolCalls.length > 0) {
271887
271912
  consecutiveTextOnly = 0;
271913
+ consecutiveThinkOnly = 0;
271888
271914
  messages2.push({ role: "assistant", content: msg.content || null, tool_calls: msg.toolCalls.map((tc) => ({ id: tc.id, type: "function", function: { name: tc.name, arguments: JSON.stringify(tc.arguments) } })) });
271889
271915
  for (const tc of msg.toolCalls) {
271890
271916
  if (this.aborted)
@@ -271970,7 +271996,13 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
271970
271996
  } else {
271971
271997
  const content = msg.content || "";
271972
271998
  messages2.push({ role: "assistant", content });
271973
- consecutiveTextOnly++;
271999
+ if (isThinkOnlyBF) {
272000
+ consecutiveThinkOnly++;
272001
+ consecutiveTextOnly = 0;
272002
+ } else {
272003
+ consecutiveTextOnly++;
272004
+ consecutiveThinkOnly = 0;
272005
+ }
271974
272006
  this.emit({ type: "model_response", content: content.slice(0, 200), turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
271975
272007
  if (/task.?complete|all tests pass/i.test(content)) {
271976
272008
  completed = true;
@@ -271988,6 +272020,15 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
271988
272020
  break;
271989
272021
  }
271990
272022
  }
272023
+ if (isThinkOnlyBF) {
272024
+ if (consecutiveThinkOnly >= MAX_CONSECUTIVE_THINK_ONLY) {
272025
+ messages2.push({
272026
+ role: "user",
272027
+ content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response."
272028
+ });
272029
+ }
272030
+ continue;
272031
+ }
271991
272032
  if (consecutiveTextOnly >= MAX_CONSECUTIVE_TEXT_ONLY) {
271992
272033
  this.emit({
271993
272034
  type: "status",
@@ -292314,11 +292355,11 @@ ${CONTENT_BG_SEQ}`);
292314
292355
  self2.cycleFocus();
292315
292356
  return;
292316
292357
  }
292317
- if (key?.ctrl && key?.shift && key?.name === "b") {
292318
- self2.armBlockSelection();
292358
+ if (key?.ctrl && key?.shift && key?.name === "c") {
292359
+ self2.copySelection();
292319
292360
  return;
292320
292361
  }
292321
- if (s2 === "\x1B[66;6u") {
292362
+ if (key?.ctrl && key?.shift && key?.name === "b") {
292322
292363
  self2.armBlockSelection();
292323
292364
  return;
292324
292365
  }
@@ -292434,6 +292475,8 @@ ${CONTENT_BG_SEQ}`);
292434
292475
  di.on("shiftdown", () => self2.scrollContentDown(3));
292435
292476
  di.on("tab-empty", () => self2.cycleFocus());
292436
292477
  di.on("ctrl-backslash", () => self2.cycleFocus());
292478
+ di.on("ctrl-shift-c", () => self2.copySelection());
292479
+ di.on("ctrl-shift-b", () => self2.armBlockSelection());
292437
292480
  di.on("up", () => {
292438
292481
  if (self2._suggestions.length > 0) {
292439
292482
  self2.suggestUp();
@@ -315012,8 +315055,28 @@ var init_direct_input = __esm({
315012
315055
  return;
315013
315056
  }
315014
315057
  return;
315015
- case "u":
315058
+ case "u": {
315059
+ const parts = params.split(";");
315060
+ const codepoint = parseInt(parts[0] ?? "0");
315061
+ const modifiers = parseInt(parts[1] ?? "1");
315062
+ const hasCtrl = modifiers - 1 & 4;
315063
+ const hasShift = modifiers - 1 & 1;
315064
+ if (hasCtrl && hasShift) {
315065
+ if (codepoint === 67) {
315066
+ this.emit("ctrl-shift-c");
315067
+ return;
315068
+ }
315069
+ if (codepoint === 66) {
315070
+ this.emit("ctrl-shift-b");
315071
+ return;
315072
+ }
315073
+ if (codepoint === 86) {
315074
+ this.emit("ctrl-shift-v");
315075
+ return;
315076
+ }
315077
+ }
315016
315078
  return;
315079
+ }
315017
315080
  }
315018
315081
  }
315019
315082
  /** Handle SS3 sequence: \x1BO {final} (some terminals use this for arrows/Home/End) */
@@ -323512,6 +323575,201 @@ function handleVersion(res) {
323512
323575
  function handleMetrics(res) {
323513
323576
  textResponse(res, 200, formatMetrics(), "text/plain; version=0.0.4; charset=utf-8");
323514
323577
  }
323578
+ function handleHelp(req2, res) {
323579
+ const version4 = getVersion3();
323580
+ const host = req2.headers.host ?? "localhost:11435";
323581
+ const base3 = `http://${host}`;
323582
+ const help = {
323583
+ name: "Open Agents",
323584
+ version: version4,
323585
+ description: "AI coding agent powered entirely by open-weight models. OpenAI-compatible API with full agentic tool-calling, text selection, MCP integration, and multi-model orchestration. No API keys required for local use.",
323586
+ quickstart: {
323587
+ chat: `curl ${base3}/v1/chat/completions -d '{"model":"auto","messages":[{"role":"user","content":"Hello"}]}'`,
323588
+ models: `curl ${base3}/v1/models`,
323589
+ stream: `curl ${base3}/v1/chat/completions -d '{"model":"auto","stream":true,"messages":[{"role":"user","content":"List files in the project"}]}'`,
323590
+ run_task: `curl -X POST ${base3}/v1/run -d '{"task":"Fix the failing tests","model":"auto"}'`
323591
+ },
323592
+ endpoints: {
323593
+ discovery: {
323594
+ "GET /help": "This guide — human and agent-friendly API reference",
323595
+ "GET /docs": "Interactive Swagger UI (browser)",
323596
+ "GET /openapi.json": "Full OpenAPI 3.0 specification (machine-readable)",
323597
+ "GET /health": "Liveness probe",
323598
+ "GET /health/ready": "Readiness probe (checks backend reachability)",
323599
+ "GET /version": "Package version, Node.js version, platform",
323600
+ "GET /metrics": "Prometheus-format metrics"
323601
+ },
323602
+ inference: {
323603
+ "GET /v1/models": "List all available models (local + sponsored, with prefixes)",
323604
+ "POST /v1/chat/completions": "OpenAI-compatible chat completion (supports streaming via stream:true)",
323605
+ "POST /v1/embeddings": "Generate embeddings",
323606
+ "POST /v1/generate": "Ollama-compatible text generation",
323607
+ "GET /api/tags": "Ollama-compatible model listing",
323608
+ "POST /api/chat": "Ollama-compatible chat",
323609
+ "POST /api/embed": "Ollama-compatible embeddings"
323610
+ },
323611
+ agentic: {
323612
+ "POST /v1/chat": "Stateful agentic chat — full tool access (file_read, shell, grep, etc.), SSE streaming",
323613
+ "GET /v1/chat/sessions": "List active chat sessions",
323614
+ "POST /v1/run": "Spawn autonomous task execution",
323615
+ "GET /v1/runs": "List all runs",
323616
+ "GET /v1/runs/:id": "Get run status and details",
323617
+ "GET /v1/runs/:id/output": "Get run output/logs",
323618
+ "DELETE /v1/runs/:id": "Cancel a running task"
323619
+ },
323620
+ tools_and_skills: {
323621
+ "GET /v1/tools": "List available agentic tools",
323622
+ "GET /v1/skills": "List available skills (slash commands)",
323623
+ "GET /v1/skills/:name": "Get skill details and content",
323624
+ "GET /v1/commands": "List slash commands",
323625
+ "POST /v1/commands/:cmd": "Execute a slash command",
323626
+ "GET /v1/agents": "List available agent types"
323627
+ },
323628
+ mcp: {
323629
+ "GET /v1/mcps": "List connected MCP (Model Context Protocol) servers",
323630
+ "GET /v1/mcps/:name": "Get MCP server details and available tools",
323631
+ "POST /v1/mcps/:name/call": "Call a tool on an MCP server — body: {tool, args}"
323632
+ },
323633
+ memory: {
323634
+ "GET /v1/memory": "Memory system summary",
323635
+ "POST /v1/memory/search": "Search episodic memory",
323636
+ "POST /v1/memory/write": "Write to memory store",
323637
+ "GET /v1/memory/episodes": "List stored episodes",
323638
+ "GET /v1/memory/failures": "List failure patterns"
323639
+ },
323640
+ workspace: {
323641
+ "GET /v1/files": "List directory contents (query: ?path=src/)",
323642
+ "POST /v1/files/read": "Read file content — body: {path}",
323643
+ "GET /v1/system": "OS info, GPU detection, installed tools",
323644
+ "GET /v1/context": "Current conversation context",
323645
+ "POST /v1/context/compact": "Compact session history"
323646
+ },
323647
+ config: {
323648
+ "GET /v1/config": "Current daemon configuration",
323649
+ "PATCH /v1/config": "Update configuration (admin scope required)",
323650
+ "GET /v1/config/model": "Current model",
323651
+ "PUT /v1/config/model": "Set model — body: {model}",
323652
+ "GET /v1/config/endpoint": "Current backend endpoint",
323653
+ "PUT /v1/config/endpoint": "Set backend endpoint — body: {endpoint}"
323654
+ },
323655
+ monitoring: {
323656
+ "GET /v1/events": "Server-Sent Events stream (task lifecycle, todo changes)",
323657
+ "GET /v1/usage": "Token usage summary",
323658
+ "GET /v1/audit": "Query audit log (query: ?since=, ?action=, ?limit=)",
323659
+ "GET /v1/cost": "Cost tracking per endpoint"
323660
+ },
323661
+ voice_and_vision: {
323662
+ "POST /v1/voice/tts": "Text-to-speech synthesis",
323663
+ "POST /v1/voice/asr": "Automatic speech recognition",
323664
+ "POST /v1/vision/describe": "Describe an image (vision pipeline)"
323665
+ }
323666
+ },
323667
+ mcp_integration: {
323668
+ description: "Open Agents can act as an MCP client — connect to external MCP servers and expose their tools through the /v1/mcps/* endpoints. Any AI agent or IDE that speaks the Model Context Protocol can discover and invoke these tools remotely.",
323669
+ discovery: `curl ${base3}/v1/mcps`,
323670
+ call_tool: `curl -X POST ${base3}/v1/mcps/YOUR_SERVER/call -d '{"tool":"tool_name","args":{"key":"value"}}'`
323671
+ },
323672
+ for_ai_agents: {
323673
+ description: "If you are an AI agent or coding assistant consuming this API, here is how to get started:",
323674
+ steps: [
323675
+ `1. GET ${base3}/v1/models — discover available models`,
323676
+ `2. POST ${base3}/v1/chat/completions — send messages (OpenAI-compatible format)`,
323677
+ `3. GET ${base3}/v1/tools — see what agentic tools are available`,
323678
+ `4. POST ${base3}/v1/chat — use the agentic chat endpoint for tool-calling tasks`,
323679
+ `5. GET ${base3}/v1/mcps — discover connected MCP servers and their tools`,
323680
+ `6. GET ${base3}/v1/skills — browse available skills for specialized tasks`
323681
+ ],
323682
+ tips: [
323683
+ "Set stream:true in chat requests for real-time token streaming via SSE",
323684
+ "Use model:'auto' to let the server pick the best available model",
323685
+ "The /v1/chat endpoint supports full agentic tool-calling (file I/O, shell, grep, etc.)",
323686
+ "Use /v1/events for real-time notifications of task progress and system events",
323687
+ "Bearer tokens are optional for localhost access; required for remote/LAN access"
323688
+ ]
323689
+ },
323690
+ authentication: {
323691
+ local: "No authentication required for loopback (127.0.0.1) access",
323692
+ remote: "Set OA_API_KEY or OA_API_KEYS env var; pass as Authorization: Bearer <key>",
323693
+ scopes: {
323694
+ read: "GET endpoints — model listing, file browsing, status queries",
323695
+ run: "POST endpoints — task execution, chat, tool invocation",
323696
+ admin: "Config writes, profile management, audit access"
323697
+ }
323698
+ },
323699
+ links: {
323700
+ docs: `${base3}/docs`,
323701
+ openapi: `${base3}/openapi.json`,
323702
+ health: `${base3}/health`,
323703
+ web_ui: base3
323704
+ }
323705
+ };
323706
+ const accept = req2.headers.accept ?? "";
323707
+ if (accept.includes("text/plain") || accept.includes("text/markdown")) {
323708
+ const md = renderHelpMarkdown(help);
323709
+ textResponse(res, 200, md, "text/plain; charset=utf-8");
323710
+ } else {
323711
+ jsonResponse(res, 200, help);
323712
+ }
323713
+ }
323714
+ function renderHelpMarkdown(help) {
323715
+ const h = help;
323716
+ const version4 = h.version;
323717
+ const base3 = h.links?.web_ui ?? "http://localhost:11435";
323718
+ const qs = h.quickstart;
323719
+ const agents = h.for_ai_agents;
323720
+ let out = `# Open Agents v${version4}
323721
+
323722
+ `;
323723
+ out += `${h.description}
323724
+
323725
+ `;
323726
+ out += `## Quick Start
323727
+
323728
+ `;
323729
+ for (const [label, cmd] of Object.entries(qs)) {
323730
+ out += ` ${label}:
323731
+ ${cmd}
323732
+
323733
+ `;
323734
+ }
323735
+ out += `## Endpoints
323736
+
323737
+ `;
323738
+ const endpoints = h.endpoints;
323739
+ for (const [category, routes] of Object.entries(endpoints)) {
323740
+ out += `### ${category}
323741
+ `;
323742
+ for (const [route, desc] of Object.entries(routes)) {
323743
+ out += ` ${route.padEnd(36)} ${desc}
323744
+ `;
323745
+ }
323746
+ out += `
323747
+ `;
323748
+ }
323749
+ out += `## For AI Agents
323750
+
323751
+ `;
323752
+ for (const step of agents.steps) out += ` ${step}
323753
+ `;
323754
+ out += `
323755
+ `;
323756
+ for (const tip of agents.tips) out += ` - ${tip}
323757
+ `;
323758
+ out += `
323759
+ `;
323760
+ out += `## Links
323761
+
323762
+ `;
323763
+ out += ` Interactive docs: ${base3}/docs
323764
+ `;
323765
+ out += ` OpenAPI spec: ${base3}/openapi.json
323766
+ `;
323767
+ out += ` Web UI: ${base3}
323768
+ `;
323769
+ out += ` Health check: ${base3}/health
323770
+ `;
323771
+ return out;
323772
+ }
323515
323773
  async function handleV1Models(res, ollamaUrl) {
323516
323774
  try {
323517
323775
  const models = await fetchAggregatedModels();
@@ -325128,6 +325386,10 @@ async function handleRequest(req2, res, ollamaUrl, verbose) {
325128
325386
  handleMetrics(res);
325129
325387
  return;
325130
325388
  }
325389
+ if (pathname === "/help" && method === "GET") {
325390
+ handleHelp(req2, res);
325391
+ return;
325392
+ }
325131
325393
  if (pathname === "/openapi.json" && method === "GET") {
325132
325394
  jsonResponse(res, 200, getOpenApiSpec());
325133
325395
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.234",
3
+ "version": "0.187.236",
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",