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.
- package/dist/index.js +268 -6
- 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
|
-
|
|
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
|
-
|
|
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 === "
|
|
292318
|
-
self2.
|
|
292358
|
+
if (key?.ctrl && key?.shift && key?.name === "c") {
|
|
292359
|
+
self2.copySelection();
|
|
292319
292360
|
return;
|
|
292320
292361
|
}
|
|
292321
|
-
if (
|
|
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