@aliwey/bmo 2.0.7 → 2.0.9
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/cli.py
CHANGED
|
@@ -1120,6 +1120,20 @@ def main_run():
|
|
|
1120
1120
|
warnings.filterwarnings("ignore", category=ResourceWarning)
|
|
1121
1121
|
# Suppress Windows asyncio pipe ValueError on exit (closed pipe repr noise)
|
|
1122
1122
|
warnings.filterwarnings("ignore", message=".*I/O operation on closed pipe.*")
|
|
1123
|
+
|
|
1124
|
+
# Set up basic logging for the CLI TUI to write to ~/.bmo/logs/cli.log
|
|
1125
|
+
try:
|
|
1126
|
+
from config.settings import LOGS_DIR
|
|
1127
|
+
LOGS_DIR.mkdir(parents=True, exist_ok=True)
|
|
1128
|
+
logging.basicConfig(
|
|
1129
|
+
filename=LOGS_DIR / "cli.log",
|
|
1130
|
+
filemode="a",
|
|
1131
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
1132
|
+
level=logging.INFO
|
|
1133
|
+
)
|
|
1134
|
+
except Exception:
|
|
1135
|
+
pass
|
|
1136
|
+
|
|
1123
1137
|
try:
|
|
1124
1138
|
asyncio.run(main())
|
|
1125
1139
|
except KeyboardInterrupt:
|
|
Binary file
|
|
Binary file
|
package/core/bot_client.py
CHANGED
|
@@ -57,7 +57,8 @@ class OpenCodeBotClient:
|
|
|
57
57
|
try:
|
|
58
58
|
r = await self._http.get("/session", timeout=5.0)
|
|
59
59
|
return r.status_code < 500
|
|
60
|
-
except Exception:
|
|
60
|
+
except Exception as e:
|
|
61
|
+
logger.error("is_alive check failed for %s: %s", OPENCODE_BASE_URL, e)
|
|
61
62
|
return False
|
|
62
63
|
|
|
63
64
|
async def connect(self) -> bool:
|
|
@@ -75,19 +76,23 @@ class OpenCodeBotClient:
|
|
|
75
76
|
self.is_connected = False
|
|
76
77
|
return self.is_connected
|
|
77
78
|
|
|
78
|
-
async def create_session(self, provider_id: Optional[str] = None, model_id: Optional[str] = None, env: Optional[dict] = None) -> Optional[str]:
|
|
79
|
+
async def create_session(self, provider_id: Optional[str] = None, model_id: Optional[str] = None, env: Optional[dict] = None, agent: str = "build") -> Optional[str]:
|
|
79
80
|
"""Create a new opencode session and return its ID."""
|
|
80
81
|
try:
|
|
81
82
|
# Force defaults if None/Empty
|
|
82
83
|
p_id = provider_id if (provider_id and str(provider_id) != "None") else "opencode"
|
|
83
84
|
m_id = model_id if (model_id and str(model_id) != "None") else "big-pickle"
|
|
84
85
|
|
|
85
|
-
#
|
|
86
|
+
# Map 'default' to 'build' to prevent server-side agent switching errors
|
|
87
|
+
agent_to_use = "build" if (not agent or agent == "default") else agent
|
|
88
|
+
|
|
89
|
+
# The server expects a nested 'model' object and optional 'agent'
|
|
86
90
|
payload = {
|
|
87
91
|
"model": {
|
|
88
92
|
"id": m_id,
|
|
89
93
|
"providerID": p_id
|
|
90
|
-
}
|
|
94
|
+
},
|
|
95
|
+
"agent": agent_to_use
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
if env:
|
|
@@ -103,7 +108,7 @@ class OpenCodeBotClient:
|
|
|
103
108
|
session_id = data.get("id")
|
|
104
109
|
|
|
105
110
|
actual_model = data.get("model", {}).get("id", "Unknown")
|
|
106
|
-
logger.info("--- OPENCODE SESSION CREATED: %s (Model: %s) ---", session_id, actual_model)
|
|
111
|
+
logger.info("--- OPENCODE SESSION CREATED: %s (Model: %s, Agent: %s) ---", session_id, actual_model, agent_to_use)
|
|
107
112
|
return session_id
|
|
108
113
|
except Exception as e:
|
|
109
114
|
logger.error("Failed to create session: %s", e)
|
|
@@ -281,7 +286,7 @@ class OpenCodeBotClient:
|
|
|
281
286
|
|
|
282
287
|
if not session_id:
|
|
283
288
|
# Inject keys if provided
|
|
284
|
-
session_id = await self.create_session(provider_id, model_id, env=provider_env)
|
|
289
|
+
session_id = await self.create_session(provider_id, model_id, env=provider_env, agent=active_agent)
|
|
285
290
|
if not session_id:
|
|
286
291
|
return "Error: Could not create OpenCode session."
|
|
287
292
|
|
|
@@ -410,7 +415,7 @@ class OpenCodeBotClient:
|
|
|
410
415
|
# Automatic recovery: if session not found, clear it and try once more
|
|
411
416
|
if r is not None and r.status_code == 404:
|
|
412
417
|
logger.warning("Session %s not found on server. Creating new session...", session_id)
|
|
413
|
-
session_id = await self.create_session(provider_id, model_id, env=provider_env)
|
|
418
|
+
session_id = await self.create_session(provider_id, model_id, env=provider_env, agent=active_agent)
|
|
414
419
|
if not session_id:
|
|
415
420
|
return "Error: Session lost and could not create a new one."
|
|
416
421
|
self.last_session_id = session_id
|
|
@@ -575,7 +580,7 @@ class OpenCodeBotClient:
|
|
|
575
580
|
return "❌ Error: Could not connect to OpenCode backend. Is the server running?"
|
|
576
581
|
|
|
577
582
|
if not session_id:
|
|
578
|
-
session_id = await self.create_session(provider_id, model_id, env=provider_env)
|
|
583
|
+
session_id = await self.create_session(provider_id, model_id, env=provider_env, agent=active_agent)
|
|
579
584
|
if not session_id:
|
|
580
585
|
return "Error: Could not create OpenCode session."
|
|
581
586
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliwey/bmo",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
4
|
"description": "BMO — AI coding assistant with Telegram, CLI & Web sync. One command, all frontends.",
|
|
5
5
|
"keywords": ["ai", "coding-assistant", "telegram-bot", "cli", "opencode", "bfp"],
|
|
6
6
|
"homepage": "https://github.com/aliwey/bmo",
|
package/webchat/server.js
CHANGED
|
@@ -327,7 +327,10 @@ app.post('/api/switch-model', express.json(), async (req, res) => {
|
|
|
327
327
|
const parts = (model || 'big-pickle').split('/');
|
|
328
328
|
const bareModelId = parts.pop();
|
|
329
329
|
const providerId = provider || parts.pop() || 'opencode';
|
|
330
|
-
const payload = {
|
|
330
|
+
const payload = {
|
|
331
|
+
model: { id: bareModelId, providerID: providerId },
|
|
332
|
+
agent: 'build'
|
|
333
|
+
};
|
|
331
334
|
const r = await fetch(`${OPENCODE_URL}/session`, {
|
|
332
335
|
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload)
|
|
333
336
|
});
|
|
@@ -353,9 +356,10 @@ function generateTitle(firstMessage) {
|
|
|
353
356
|
return words.slice(0, 6).join(' ') + '…';
|
|
354
357
|
}
|
|
355
358
|
|
|
356
|
-
async function createOpenCodeSession(modelId = 'qwen3.6-plus-free', providerId = 'opencode') {
|
|
359
|
+
async function createOpenCodeSession(modelId = 'qwen3.6-plus-free', providerId = 'opencode', agent = 'build') {
|
|
357
360
|
const payload = {
|
|
358
|
-
model: { id: modelId, providerID: providerId }
|
|
361
|
+
model: { id: modelId, providerID: providerId },
|
|
362
|
+
agent: agent === 'default' ? 'build' : agent
|
|
359
363
|
};
|
|
360
364
|
const controller = new AbortController();
|
|
361
365
|
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
@@ -371,7 +375,7 @@ async function createOpenCodeSession(modelId = 'qwen3.6-plus-free', providerId =
|
|
|
371
375
|
}
|
|
372
376
|
const data = await r.json();
|
|
373
377
|
const sessionId = data.id;
|
|
374
|
-
console.log('[OpenCode] Created session:', sessionId, 'model:', modelId);
|
|
378
|
+
console.log('[OpenCode] Created session:', sessionId, 'model:', modelId, 'agent:', payload.agent);
|
|
375
379
|
return sessionId;
|
|
376
380
|
} catch (e) {
|
|
377
381
|
clearTimeout(timeout);
|
|
@@ -412,14 +416,14 @@ async function callOpenCode(text, sessionId, mode = 'execute', agent = 'default'
|
|
|
412
416
|
|
|
413
417
|
if (r && r.status === 404) {
|
|
414
418
|
console.log('[OpenCode] Session not found, creating new one...');
|
|
415
|
-
sessionId = await createOpenCodeSession(modelId || 'qwen3.6-plus-free', providerId || 'opencode');
|
|
419
|
+
sessionId = await createOpenCodeSession(modelId || 'qwen3.6-plus-free', providerId || 'opencode', agent);
|
|
416
420
|
r = await doSend(sessionId);
|
|
417
421
|
}
|
|
418
422
|
|
|
419
423
|
// 500 with a recoverable model → create new session and retry
|
|
420
424
|
if (r && r.status === 500 && modelId) {
|
|
421
425
|
console.log('[OpenCode] Session 500, creating new session with model:', modelId);
|
|
422
|
-
sessionId = await createOpenCodeSession(modelId, providerId);
|
|
426
|
+
sessionId = await createOpenCodeSession(modelId, providerId, agent);
|
|
423
427
|
r = await doSend(sessionId, 30000);
|
|
424
428
|
}
|
|
425
429
|
|