open-agents-ai 0.187.584 → 0.187.586

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 CHANGED
@@ -528118,6 +528118,7 @@ var init_agenticRunner = __esm({
528118
528118
  compactionThreshold: options2?.compactionThreshold ?? 4e4,
528119
528119
  deepContext: options2?.deepContext ?? false,
528120
528120
  dynamicContext: options2?.dynamicContext ?? "",
528121
+ sessionId: options2?.sessionId ?? "",
528121
528122
  streamEnabled: options2?.streamEnabled ?? false,
528122
528123
  thinking: options2?.thinking ?? true,
528123
528124
  bruteForce: options2?.bruteForce ?? true,
@@ -528792,7 +528793,7 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
528792
528793
  }
528793
528794
  readSessionTodos() {
528794
528795
  try {
528795
- const sid = process.env["OA_SESSION_ID"] || this._sessionId || "default";
528796
+ const sid = this._sessionId || process.env["OA_SESSION_ID"] || "default";
528796
528797
  const safe = sid.replace(/[^a-zA-Z0-9_.-]/g, "_");
528797
528798
  const fp = _pathJoin(_osHomedir(), ".open-agents", "todos", `${safe}.json`);
528798
528799
  if (!_fsExistsSync(fp))
@@ -530787,7 +530788,7 @@ Respond with your assessment, then take action.`;
530787
530788
  }
530788
530789
  this._fileRegistry.clear();
530789
530790
  this._memexArchive.clear();
530790
- this._sessionId = process.env["OA_SESSION_ID"] && String(process.env["OA_SESSION_ID"]) || `session-${Date.now()}`;
530791
+ this._sessionId = this.options.sessionId && String(this.options.sessionId) || process.env["OA_SESSION_ID"] && String(process.env["OA_SESSION_ID"]) || `session-${Date.now()}`;
530791
530792
  this._appState = createAppState({
530792
530793
  sessionId: this._sessionId,
530793
530794
  model: this.backend.model ?? "",
@@ -530935,7 +530936,7 @@ TASK: ${task}` : task;
530935
530936
  messages2.push({ role: "system", content: _directive });
530936
530937
  const _todos = buildDecompositionTodos(_decomp.modules);
530937
530938
  try {
530938
- const sid = process.env["OA_SESSION_ID"] || this._sessionId || "default";
530939
+ const sid = this._sessionId || process.env["OA_SESSION_ID"] || "default";
530939
530940
  const safe = sid.replace(/[^a-zA-Z0-9_.-]/g, "_");
530940
530941
  const fp = _pathJoin(_osHomedir(), ".open-agents", "todos", `${safe}.json`);
530941
530942
  const dir = _pathJoin(_osHomedir(), ".open-agents", "todos");
@@ -536441,7 +536442,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
536441
536442
  */
536442
536443
  formatCompletedTodoAnchors() {
536443
536444
  try {
536444
- const sessionId = process.env["OA_SESSION_ID"] || this._sessionId;
536445
+ const sessionId = this._sessionId || process.env["OA_SESSION_ID"] || "default";
536445
536446
  const todos = readTodos(sessionId);
536446
536447
  if (todos.length === 0)
536447
536448
  return "";
@@ -590819,7 +590820,7 @@ function getDefaultPolicy(context2) {
590819
590820
  case "terminal":
590820
590821
  return { blocked: /* @__PURE__ */ new Set(), allowed: /* @__PURE__ */ new Set() };
590821
590822
  case "telegram-admin-dm":
590822
- return { blocked: /* @__PURE__ */ new Set(["shell"]), allowed: /* @__PURE__ */ new Set() };
590823
+ return { blocked: /* @__PURE__ */ new Set(), allowed: /* @__PURE__ */ new Set() };
590823
590824
  case "telegram-admin-group":
590824
590825
  return { blocked: /* @__PURE__ */ new Set(), allowed: SAFE_GROUP_ADMIN_TOOLS };
590825
590826
  case "telegram-public":
@@ -590866,6 +590867,8 @@ var init_tool_policy = __esm({
590866
590867
  "memory_read",
590867
590868
  "memory_write",
590868
590869
  "memory_search",
590870
+ "todo_read",
590871
+ "todo_write",
590869
590872
  "web_search",
590870
590873
  "web_fetch",
590871
590874
  "task_complete"
@@ -590874,6 +590877,8 @@ var init_tool_policy = __esm({
590874
590877
  "memory_read",
590875
590878
  "memory_write",
590876
590879
  "memory_search",
590880
+ "todo_read",
590881
+ "todo_write",
590877
590882
  "web_search",
590878
590883
  "web_fetch",
590879
590884
  "web_crawl",
@@ -590945,35 +590950,85 @@ function sanitizeTelegramProgressText(text, maxLength) {
590945
590950
  const compact = stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
590946
590951
  return compact.length > maxLength ? compact.slice(0, Math.max(0, maxLength - 3)) + "..." : compact;
590947
590952
  }
590953
+ function truncateTelegramContext(text, maxLength) {
590954
+ const trimmed = text.trim();
590955
+ if (trimmed.length <= maxLength) return trimmed;
590956
+ return `${trimmed.slice(0, Math.max(0, maxLength - 80)).trimEnd()}
590957
+
590958
+ [Telegram context truncated; use tools for full detail.]`;
590959
+ }
590960
+ function buildTelegramRuntimeContext(now = /* @__PURE__ */ new Date(), repoRoot) {
590961
+ const date = new Intl.DateTimeFormat("en-US", {
590962
+ weekday: "long",
590963
+ year: "numeric",
590964
+ month: "long",
590965
+ day: "numeric"
590966
+ }).format(now);
590967
+ const time = new Intl.DateTimeFormat("en-US", {
590968
+ hour: "numeric",
590969
+ minute: "2-digit",
590970
+ second: "2-digit",
590971
+ timeZoneName: "short"
590972
+ }).format(now);
590973
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || process.env["TZ"] || "system";
590974
+ return [
590975
+ `Current date: ${date}`,
590976
+ `Current time: ${time}`,
590977
+ `Current ISO timestamp: ${now.toISOString()}`,
590978
+ `Timezone: ${timezone}`,
590979
+ repoRoot ? `Working directory: ${repoRoot}` : ""
590980
+ ].filter(Boolean).join("\n");
590981
+ }
590982
+ function telegramSessionIdFromKey(sessionKey) {
590983
+ return `telegram-${createHash18("sha1").update(sessionKey).digest("hex").slice(0, 16)}`;
590984
+ }
590985
+ function formatTelegramConversationHistory(history, maxEntries = 12) {
590986
+ const recent = history.filter((entry) => entry.text.trim()).slice(-maxEntries);
590987
+ if (recent.length === 0) return "";
590988
+ return recent.map((entry) => {
590989
+ const who = entry.role === "assistant" ? "Assistant" : "Telegram user";
590990
+ const mode = entry.mode ? `/${entry.mode}` : "";
590991
+ return `${who}${mode}: ${entry.text.trim()}`;
590992
+ }).join("\n");
590993
+ }
590994
+ function selectTelegramFinalResponse(args) {
590995
+ const candidates = [
590996
+ args.assistantText,
590997
+ args.streamText,
590998
+ args.accumulated,
590999
+ args.summary
591000
+ ];
591001
+ for (const candidate of candidates) {
591002
+ const cleaned = stripTelegramHiddenThinking(candidate || "").trim();
591003
+ if (cleaned) return cleaned;
591004
+ }
591005
+ return "";
591006
+ }
590948
591007
  function formatTelegramProgressEvent(event) {
590949
591008
  if (event.type === "tool_call" && event.toolName === "task_complete") return null;
590950
591009
  if (event.type === "tool_result" && event.toolName === "task_complete") return null;
590951
591010
  if (event.type === "tool_call") {
590952
- return `🔧 Using <code>${escapeTelegramHTML(event.toolName || "tool")}</code>`;
591011
+ return `Using ${escapeTelegramHTML(event.toolName || "tool")}`;
590953
591012
  }
590954
591013
  if (event.type === "tool_result") {
590955
- const icon = event.success ? "✔" : "✘";
590956
591014
  const preview = sanitizeTelegramProgressText(event.content || "", 80);
590957
- const suffix = preview ? `: ${escapeTelegramHTML(preview)}` : "";
590958
- return `${icon} <code>${escapeTelegramHTML(event.toolName || "tool")}</code>${suffix}`;
591015
+ const toolName = escapeTelegramHTML(event.toolName || "tool");
591016
+ if (preview) return `${toolName}: ${escapeTelegramHTML(preview)}`;
591017
+ return event.success ? `${toolName} completed` : `${toolName} failed`;
590959
591018
  }
590960
591019
  if (event.type === "status") {
590961
591020
  const content = sanitizeTelegramProgressText(event.content || "", 120);
590962
- return content ? `⏳ ${escapeTelegramHTML(content)}` : null;
591021
+ return content ? escapeTelegramHTML(content) : null;
590963
591022
  }
590964
591023
  return null;
590965
591024
  }
590966
591025
  function renderTelegramLiveProgressHTML(progressLines, accumulated) {
590967
- const recentProgress = progressLines.slice(-6);
590968
- const progressBlock = recentProgress.length > 0 ? recentProgress.join("\n") : "⏳ Starting...";
590969
- const draft = sanitizeTelegramProgressText(accumulated, 700);
590970
- const draftBlock = draft ? `
590971
-
590972
- <i>Drafting answer...</i>
590973
- ${convertMarkdownToTelegramHTML(draft)}
590974
- <i>▌</i>` : "\n\n<i>Working...</i>";
590975
- return `<b>✈ Working on this...</b>
590976
- ${progressBlock}${draftBlock}`;
591026
+ const draft = stripTelegramHiddenThinking(accumulated).trim();
591027
+ if (draft) {
591028
+ const clipped = draft.length > 2e3 ? `${draft.slice(0, 1997).trimEnd()}...` : draft;
591029
+ return convertMarkdownToTelegramHTML(clipped);
591030
+ }
591031
+ return progressLines.slice(-6).map((line) => line.trim()).filter(Boolean).join("\n");
590977
591032
  }
590978
591033
  function normalizeTelegramChatId(value2) {
590979
591034
  if (typeof value2 === "number" || typeof value2 === "string") return value2;
@@ -591185,14 +591240,24 @@ function normalizeTelegramUpdate(update2) {
591185
591240
  sourceUpdateType
591186
591241
  };
591187
591242
  }
591188
- function adaptTool5(tool) {
591243
+ function adaptTool5(tool, todoSessionId) {
591189
591244
  return {
591190
591245
  name: tool.name,
591191
591246
  description: tool.description,
591192
591247
  parameters: tool.parameters,
591193
591248
  async execute(args) {
591194
- const result = await tool.execute(args);
591195
- return { success: result.success, output: result.output, error: result.error };
591249
+ const previousTodoSession = todoSessionId ? getTodoSessionId() : "";
591250
+ if (todoSessionId && (tool.name === "todo_write" || tool.name === "todo_read")) {
591251
+ setTodoSessionId(todoSessionId);
591252
+ }
591253
+ try {
591254
+ const result = await tool.execute(args);
591255
+ return { success: result.success, output: result.output, error: result.error };
591256
+ } finally {
591257
+ if (todoSessionId && (tool.name === "todo_write" || tool.name === "todo_read")) {
591258
+ setTodoSessionId(previousTodoSession);
591259
+ }
591260
+ }
591196
591261
  }
591197
591262
  };
591198
591263
  }
@@ -591309,7 +591374,7 @@ function renderTelegramSubAgentError(username, error) {
591309
591374
  process.stdout.write(` ${c3.dim("⎿")} ${c3.red("✘")} @${username}: ${c3.dim(preview)}
591310
591375
  `);
591311
591376
  }
591312
- var TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, TELEGRAM_ACTION_INTENT_RE, TELEGRAM_CODEBASE_CONTEXT_RE, TELEGRAM_COMMANDISH_RE, TELEGRAM_CHAT_INTENT_RE, MEDIA_CACHE_TTL_MS, TelegramBridge;
591377
+ var TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_ACTION_INTENT_RE, TELEGRAM_CODEBASE_CONTEXT_RE, TELEGRAM_COMMANDISH_RE, TELEGRAM_CHAT_INTENT_RE, MEDIA_CACHE_TTL_MS, TelegramBridge;
591313
591378
  var init_telegram_bridge = __esm({
591314
591379
  "packages/cli/src/tui/telegram-bridge.ts"() {
591315
591380
  "use strict";
@@ -591374,10 +591439,27 @@ You are Open Agents replying in Telegram quick-chat mode.
591374
591439
 
591375
591440
  Rules:
591376
591441
  1. Reply directly to the Telegram user, conversationally and concisely.
591377
- 2. Do not inspect, summarize, or expose local files, paths, secrets, tool output, or runtime internals.
591378
- 3. Do not claim that you changed code, ran commands, or checked the workspace in quick-chat mode.
591379
- 4. If the user asks for codebase action while quick-chat mode is forced, tell them to switch Telegram to action mode or send a concrete action request in auto mode.
591380
- 5. For ordinary chat, status questions, greetings, quick explanations, and playful messages, answer immediately without tool-use narration.
591442
+ 2. For public/group users, do not inspect, summarize, or expose local files, paths, secrets, tool output, or runtime internals.
591443
+ 3. For admin private DMs, quick-chat is a response style, not a capability downgrade: use the provided context and tools when needed.
591444
+ 4. For ordinary chat, status questions, greetings, quick explanations, and playful messages, answer immediately without tool-use narration.
591445
+ 5. For date/time questions, use the authoritative runtime context in this request. Do not infer dates from prior messages.
591446
+ `.trim();
591447
+ ADMIN_CHAT_PROFILE_PROMPT = `
591448
+ You are replying to the authenticated Telegram admin in a private DM.
591449
+ Quick-chat is a conversational response profile, not a restricted mode.
591450
+
591451
+ Capabilities:
591452
+ 1. You have the same admin-grade context and tools as an action run.
591453
+ 2. Use tools when they are required to answer accurately. Do not claim you lack logs, history, workspace access, or tooling if the context/tools provide a way to inspect them.
591454
+ 3. If the message is a substantial codebase task, delegate focused work with full_sub_agent or another available agent tool, then report the spawned agent/status or result.
591455
+ 4. If the message is a simple conversational question, answer directly from context without unnecessary tool use.
591456
+ 5. The final Telegram message must be the answer to send to the admin, not a meta-summary such as "answered the question".
591457
+ `.trim();
591458
+ TELEGRAM_ACTION_RESPONSE_CONTRACT = `
591459
+ Telegram response contract:
591460
+ - The final task_complete summary is the exact message that will be sent to Telegram.
591461
+ - Do not summarize the fact that you answered; send the answer itself.
591462
+ - If you delegated long-running work, include the sub-agent id/status and what the admin should expect next.
591381
591463
  `.trim();
591382
591464
  TELEGRAM_ACTION_INTENT_RE = /\b(implement|fix|patch|edit|write|create|delete|remove|refactor|run|execute|test|build|install|debug|investigate|diagnose|validate|commit|push|pull|merge|rebase|deploy|publish|read|open|inspect|grep|search|find|list|apply|change|update)\b/i;
591383
591465
  TELEGRAM_CODEBASE_CONTEXT_RE = /\b(repo|repository|codebase|workspace|working directory|file|files|folder|directory|src|source|test|tests|package|pnpm|npm|node|git|branch|commit|pr|pull request|issue|shell|terminal|cli|command|function|class|component|endpoint|api)\b/i;
@@ -591578,10 +591660,92 @@ Rules:
591578
591660
  }
591579
591661
  recordChatHistory(sessionKey, entry) {
591580
591662
  const existing = this.chatHistory.get(sessionKey) ?? [];
591581
- existing.push(entry);
591663
+ existing.push({ ...entry, ts: entry.ts ?? Date.now() });
591582
591664
  if (existing.length > 16) existing.splice(0, existing.length - 16);
591583
591665
  this.chatHistory.set(sessionKey, existing);
591584
591666
  }
591667
+ buildTelegramWorkspaceContext(modelTier, budget = 14e3) {
591668
+ if (!this.repoRoot) return "";
591669
+ try {
591670
+ const ctx3 = buildProjectContext(this.repoRoot);
591671
+ return truncateTelegramContext(formatContextForPrompt(ctx3, modelTier), budget);
591672
+ } catch (err) {
591673
+ const reason = err instanceof Error ? err.message : String(err);
591674
+ return `Workspace context unavailable: ${reason}`;
591675
+ }
591676
+ }
591677
+ buildPrimaryTuiSessionContext(telegramSessionId) {
591678
+ const primarySessionId = process.env["OA_SESSION_ID"] || process.env["OA_TUI_SESSION_ID"] || "";
591679
+ if (!primarySessionId || primarySessionId === telegramSessionId) return "";
591680
+ try {
591681
+ const todos = readTodos(primarySessionId);
591682
+ if (todos.length === 0) {
591683
+ return `Primary TUI session id: ${primarySessionId}
591684
+ No active checklist items are recorded for that session.`;
591685
+ }
591686
+ const lines = todos.slice(0, 18).map((todo) => {
591687
+ const blocker = todo.blocker ? ` - blocked: ${todo.blocker}` : "";
591688
+ return `- [${todo.status}] ${todo.content}${blocker}`;
591689
+ });
591690
+ const suffix = todos.length > lines.length ? `
591691
+ ... ${todos.length - lines.length} more item(s)` : "";
591692
+ return `Primary TUI session id: ${primarySessionId}
591693
+ Current checklist:
591694
+ ${lines.join("\n")}${suffix}`;
591695
+ } catch (err) {
591696
+ const reason = err instanceof Error ? err.message : String(err);
591697
+ return `Primary TUI session id: ${primarySessionId}
591698
+ Checklist unavailable: ${reason}`;
591699
+ }
591700
+ }
591701
+ buildTelegramSessionContext(msg, toolContext, profile, modelTier) {
591702
+ const sessionKey = this.sessionKeyForMessage(msg);
591703
+ const sessionId = telegramSessionIdFromKey(sessionKey);
591704
+ const isAdminDM = toolContext === "telegram-admin-dm";
591705
+ const isAdminGroup = toolContext === "telegram-admin-group";
591706
+ const history = formatTelegramConversationHistory(this.chatHistory.get(sessionKey) ?? [], isAdminDM ? 14 : 8);
591707
+ const chatLabel = msg.chatType !== "private" ? `Telegram group: ${msg.chatTitle || "unknown"}` : "Telegram private chat";
591708
+ const sections = [
591709
+ `## Telegram Runtime Context
591710
+
591711
+ ${buildTelegramRuntimeContext(/* @__PURE__ */ new Date(), isAdminDM ? this.repoRoot : void 0)}`,
591712
+ `## Telegram Session
591713
+
591714
+ Session key: ${sessionKey}
591715
+ Todo/session id: ${sessionId}
591716
+ Profile: ${profile}
591717
+ Tool context: ${toolContext}
591718
+ ${chatLabel}`,
591719
+ TELEGRAM_ACTION_RESPONSE_CONTRACT
591720
+ ];
591721
+ if (history) {
591722
+ sections.push(`## Recent Telegram Conversation
591723
+
591724
+ ${history}`);
591725
+ }
591726
+ if (isAdminDM) {
591727
+ sections.push(`## Admin Capability Contract
591728
+
591729
+ ${ADMIN_CHAT_PROFILE_PROMPT}`);
591730
+ const primarySessionContext = this.buildPrimaryTuiSessionContext(sessionId);
591731
+ if (primarySessionContext) sections.push(`## Primary TUI Session State
591732
+
591733
+ ${primarySessionContext}`);
591734
+ const workspaceContext = this.buildTelegramWorkspaceContext(modelTier, profile === "chat" ? 16e3 : 24e3);
591735
+ if (workspaceContext) sections.push(`## Workspace Context
591736
+
591737
+ ${workspaceContext}`);
591738
+ } else if (isAdminGroup) {
591739
+ sections.push(`## Telegram Safety Contract
591740
+
591741
+ ${ADMIN_GROUP_PROMPT}`);
591742
+ } else {
591743
+ sections.push(`## Telegram Safety Contract
591744
+
591745
+ ${TELEGRAM_SAFETY_PROMPT}`);
591746
+ }
591747
+ return { sessionKey, sessionId, context: sections.join("\n\n") };
591748
+ }
591585
591749
  shouldFastChatReplyInGroup(msg) {
591586
591750
  if (msg.chatType === "private" || msg.guestQueryId) return true;
591587
591751
  const lower = msg.text.toLowerCase();
@@ -591865,6 +592029,7 @@ Join: ${newUrl}`);
591865
592029
  }
591866
592030
  const existing = this.subAgents.get(sessionKey);
591867
592031
  if (existing && !existing.aborted) {
592032
+ this.recordChatHistory(sessionKey, { role: "user", text: msg.text, mode: "steering" });
591868
592033
  if (existing.runner) {
591869
592034
  existing.runner.injectUserMessage(msg.text);
591870
592035
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "mid-conversation steering injected"));
@@ -591889,7 +592054,10 @@ Join: ${newUrl}`);
591889
592054
  runner: null,
591890
592055
  typingInterval: null,
591891
592056
  liveMessageId: null,
592057
+ liveMessagePromise: null,
591892
592058
  accumulated: "",
592059
+ assistantText: "",
592060
+ streamText: "",
591893
592061
  intermediateLines: [],
591894
592062
  lastEditMs: 0,
591895
592063
  aborted: false,
@@ -591909,14 +592077,6 @@ Join: ${newUrl}`);
591909
592077
  }
591910
592078
  this.tuiWrite(() => renderTelegramSubAgentStart(msg.username, msg.text, isAdminDM));
591911
592079
  try {
591912
- if (!msg.guestQueryId) {
591913
- const msgId = await this.sendLiveMessage(
591914
- msg.chatId,
591915
- renderTelegramLiveProgressHTML([], ""),
591916
- msg.chatType !== "private" ? msg.messageId : void 0
591917
- );
591918
- subAgent.liveMessageId = msgId;
591919
- }
591920
592080
  let mediaContext = "";
591921
592081
  if (msg.media) {
591922
592082
  mediaContext = await this.processMedia(msg);
@@ -591937,6 +592097,12 @@ Join: ${newUrl}`);
591937
592097
  return;
591938
592098
  }
591939
592099
  const finalText = stripTelegramHiddenThinking(result || "").trim() || "I couldn't generate a response. Please try again.";
592100
+ if (subAgent.liveMessagePromise) {
592101
+ await subAgent.liveMessagePromise.catch(() => {
592102
+ });
592103
+ }
592104
+ this.recordChatHistory(sessionKey, { role: "user", text: msg.text, mode: "action" });
592105
+ this.recordChatHistory(sessionKey, { role: "assistant", text: finalText, mode: "action" });
591940
592106
  const finalHtml = convertMarkdownToTelegramHTML(finalText);
591941
592107
  if (subAgent.liveMessageId && !msg.guestQueryId) {
591942
592108
  await this.editLiveMessage(msg.chatId, subAgent.liveMessageId, finalHtml);
@@ -591959,7 +592125,7 @@ Join: ${newUrl}`);
591959
592125
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `error: ${errMsg}`);
591960
592126
  this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "failed");
591961
592127
  if (subAgent.liveMessageId && !msg.guestQueryId) {
591962
- await this.editLiveMessage(msg.chatId, subAgent.liveMessageId, `❌ Error: ${errMsg}`).catch(() => {
592128
+ await this.editLiveMessage(msg.chatId, subAgent.liveMessageId, `Error: ${errMsg}`).catch(() => {
591963
592129
  });
591964
592130
  } else {
591965
592131
  await this.replyToTelegramMessage(msg, "Sorry, I encountered an error processing your message. Please try again.").catch(() => {
@@ -591971,8 +592137,96 @@ Join: ${newUrl}`);
591971
592137
  this.subAgentViewCallbacks?.onComplete(subAgent.viewId);
591972
592138
  }
591973
592139
  }
592140
+ /** Admin quick-chat: conversational profile with full admin context/tools. */
592141
+ async handleTelegramAdminChatAgent(msg, toolContext) {
592142
+ const sessionKey = this.sessionKeyForMessage(msg);
592143
+ const subAgent = {
592144
+ chatId: msg.chatId,
592145
+ username: msg.username,
592146
+ viewId: `${this.viewIdForMessage(msg)}-chat`,
592147
+ runner: null,
592148
+ typingInterval: null,
592149
+ liveMessageId: null,
592150
+ liveMessagePromise: null,
592151
+ accumulated: "",
592152
+ assistantText: "",
592153
+ streamText: "",
592154
+ intermediateLines: [],
592155
+ lastEditMs: 0,
592156
+ aborted: false,
592157
+ toolContext,
592158
+ pendingMessages: []
592159
+ };
592160
+ this.subAgents.set(sessionKey, subAgent);
592161
+ this.refreshActiveTelegramInteractionCount();
592162
+ this.subAgentViewCallbacks?.onRegister(
592163
+ subAgent.viewId,
592164
+ `✈ @${msg.username || "telegram"}`,
592165
+ `Telegram admin chat: ${msg.text.slice(0, 160)}`
592166
+ );
592167
+ this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `✈ Telegram admin chat from @${msg.username}: ${msg.text}`);
592168
+ this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `route: chat (${this.interactionMode}) with admin tools`);
592169
+ this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "running");
592170
+ if (this.canUseChatActions(msg)) {
592171
+ subAgent.typingInterval = this.startTypingIndicator(msg.chatId);
592172
+ }
592173
+ this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `admin chat with full context/tools (${this.interactionMode})`));
592174
+ try {
592175
+ let mediaContext = "";
592176
+ if (msg.media) {
592177
+ mediaContext = await this.processMedia(msg);
592178
+ }
592179
+ const result = await this.runSubAgent(msg, subAgent, mediaContext, "chat");
592180
+ if (subAgent.typingInterval) {
592181
+ clearInterval(subAgent.typingInterval);
592182
+ subAgent.typingInterval = null;
592183
+ }
592184
+ const finalText = stripTelegramHiddenThinking(result || "").trim() || "I heard you.";
592185
+ if (subAgent.liveMessagePromise) {
592186
+ await subAgent.liveMessagePromise.catch(() => {
592187
+ });
592188
+ }
592189
+ this.recordChatHistory(sessionKey, { role: "user", text: msg.text, mode: "chat" });
592190
+ this.recordChatHistory(sessionKey, { role: "assistant", text: finalText, mode: "chat" });
592191
+ const finalHtml = convertMarkdownToTelegramHTML(finalText);
592192
+ if (subAgent.liveMessageId && !msg.guestQueryId) {
592193
+ await this.editLiveMessage(msg.chatId, subAgent.liveMessageId, finalHtml);
592194
+ } else {
592195
+ await this.replyToTelegramMessage(msg, finalHtml, {
592196
+ html: true,
592197
+ replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
592198
+ });
592199
+ }
592200
+ this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `completed: ${finalText}`);
592201
+ this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "completed");
592202
+ } catch (err) {
592203
+ if (subAgent.typingInterval) {
592204
+ clearInterval(subAgent.typingInterval);
592205
+ subAgent.typingInterval = null;
592206
+ }
592207
+ const errMsg = err instanceof Error ? err.message : String(err);
592208
+ this.tuiWrite(() => renderTelegramSubAgentError(msg.username, errMsg));
592209
+ this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `error: ${errMsg}`);
592210
+ this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "failed");
592211
+ if (subAgent.liveMessageId && !msg.guestQueryId) {
592212
+ await this.editLiveMessage(msg.chatId, subAgent.liveMessageId, `Error: ${escapeTelegramHTML(errMsg)}`).catch(() => {
592213
+ });
592214
+ } else {
592215
+ await this.replyToTelegramMessage(msg, "Sorry, I couldn't process that Telegram chat message.").catch(() => {
592216
+ });
592217
+ }
592218
+ } finally {
592219
+ this.subAgents.delete(sessionKey);
592220
+ this.refreshActiveTelegramInteractionCount();
592221
+ this.subAgentViewCallbacks?.onComplete(subAgent.viewId);
592222
+ }
592223
+ }
591974
592224
  /** Fast Telegram chat path: direct streamed completion, no tool loop. */
591975
592225
  async handleTelegramChatCompletion(msg, toolContext) {
592226
+ if (toolContext === "telegram-admin-dm") {
592227
+ await this.handleTelegramAdminChatAgent(msg, toolContext);
592228
+ return;
592229
+ }
591976
592230
  if (!this.shouldFastChatReplyInGroup(msg)) {
591977
592231
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "chat-mode discretion: skipped group chatter"));
591978
592232
  return;
@@ -591984,7 +592238,8 @@ Join: ${newUrl}`);
591984
592238
  let accumulated = "";
591985
592239
  let lastEditMs = 0;
591986
592240
  let lastViewWriteMs = 0;
591987
- const progressLines = [`💬 Quick chat mode (${this.interactionMode})`];
592241
+ let liveMessagePromise = null;
592242
+ const progressLines = [];
591988
592243
  this.activeChatViews.add(viewId);
591989
592244
  this.refreshActiveTelegramInteractionCount();
591990
592245
  this.subAgentViewCallbacks?.onRegister(
@@ -592000,19 +592255,12 @@ Join: ${newUrl}`);
592000
592255
  }
592001
592256
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `chat-mode fast reply (${this.interactionMode})`));
592002
592257
  try {
592003
- if (!msg.guestQueryId) {
592004
- liveMessageId = await this.sendLiveMessage(
592005
- msg.chatId,
592006
- renderTelegramLiveProgressHTML(progressLines, ""),
592007
- msg.chatType !== "private" ? msg.messageId : void 0
592008
- );
592009
- }
592010
592258
  const mediaContext = msg.media || msg.livePhoto ? "Attachment received. Quick-chat mode does not inspect media; use action mode for media analysis." : "";
592011
592259
  const finalText = await this.runTelegramChatCompletion(
592012
592260
  msg,
592013
592261
  toolContext,
592014
592262
  mediaContext,
592015
- (nextText) => {
592263
+ async (nextText) => {
592016
592264
  accumulated = nextText;
592017
592265
  const now = Date.now();
592018
592266
  if (now - lastViewWriteMs > 900) {
@@ -592021,12 +592269,28 @@ Join: ${newUrl}`);
592021
592269
  }
592022
592270
  if (liveMessageId && !msg.guestQueryId && now - lastEditMs > 900) {
592023
592271
  lastEditMs = now;
592024
- this.editLiveMessage(
592272
+ await this.editLiveMessage(
592025
592273
  msg.chatId,
592026
592274
  liveMessageId,
592027
592275
  renderTelegramLiveProgressHTML(progressLines, accumulated)
592028
592276
  ).catch(() => {
592029
592277
  });
592278
+ } else if (!liveMessageId && !liveMessagePromise && !msg.guestQueryId) {
592279
+ const html = renderTelegramLiveProgressHTML(progressLines, accumulated);
592280
+ if (html.trim()) {
592281
+ liveMessagePromise = this.sendLiveMessage(
592282
+ msg.chatId,
592283
+ html,
592284
+ msg.chatType !== "private" ? msg.messageId : void 0
592285
+ ).then((id) => {
592286
+ liveMessageId = id;
592287
+ lastEditMs = Date.now();
592288
+ }).catch(() => {
592289
+ }).finally(() => {
592290
+ liveMessagePromise = null;
592291
+ });
592292
+ await liveMessagePromise;
592293
+ }
592030
592294
  }
592031
592295
  }
592032
592296
  );
@@ -592035,8 +592299,13 @@ Join: ${newUrl}`);
592035
592299
  typingInterval = null;
592036
592300
  }
592037
592301
  const cleaned = stripTelegramHiddenThinking(finalText || accumulated).trim() || "I heard you.";
592038
- this.recordChatHistory(sessionKey, { role: "user", text: msg.text });
592039
- this.recordChatHistory(sessionKey, { role: "assistant", text: cleaned });
592302
+ const pendingLiveMessage = liveMessagePromise;
592303
+ if (pendingLiveMessage) {
592304
+ await pendingLiveMessage.catch(() => {
592305
+ });
592306
+ }
592307
+ this.recordChatHistory(sessionKey, { role: "user", text: msg.text, mode: "chat" });
592308
+ this.recordChatHistory(sessionKey, { role: "assistant", text: cleaned, mode: "chat" });
592040
592309
  const finalHtml = convertMarkdownToTelegramHTML(cleaned);
592041
592310
  if (liveMessageId && !msg.guestQueryId) {
592042
592311
  await this.editLiveMessage(msg.chatId, liveMessageId, finalHtml);
@@ -592058,7 +592327,7 @@ Join: ${newUrl}`);
592058
592327
  this.subAgentViewCallbacks?.onWrite(viewId, `error: ${errMsg}`);
592059
592328
  this.subAgentViewCallbacks?.onStatus(viewId, "failed");
592060
592329
  if (liveMessageId && !msg.guestQueryId) {
592061
- await this.editLiveMessage(msg.chatId, liveMessageId, `❌ Error: ${escapeTelegramHTML(errMsg)}`).catch(() => {
592330
+ await this.editLiveMessage(msg.chatId, liveMessageId, `Error: ${escapeTelegramHTML(errMsg)}`).catch(() => {
592062
592331
  });
592063
592332
  } else {
592064
592333
  await this.replyToTelegramMessage(msg, "Sorry, I couldn't process that quick chat message.").catch(() => {
@@ -592078,11 +592347,16 @@ Join: ${newUrl}`);
592078
592347
  const history = this.chatHistory.get(sessionKey) ?? [];
592079
592348
  const safety = isAdminDM ? "Admin private DM. The user is trusted, but quick-chat mode still has no tool access." : isAdminGroup ? ADMIN_GROUP_PROMPT : TELEGRAM_SAFETY_PROMPT;
592080
592349
  const groupHint = isGroup ? `Telegram group: ${msg.chatTitle || "unknown"}. Keep the reply short and relevant.` : "Telegram private chat.";
592350
+ const runtime = buildTelegramRuntimeContext(/* @__PURE__ */ new Date());
592081
592351
  const messages2 = [
592082
592352
  {
592083
592353
  role: "system",
592084
592354
  content: `${TELEGRAM_CHAT_MODE_PROMPT}
592085
592355
 
592356
+ ## Runtime Context
592357
+
592358
+ ${runtime}
592359
+
592086
592360
  ${safety}
592087
592361
 
592088
592362
  ${groupHint}`
@@ -592123,19 +592397,19 @@ ${mediaContext}` : ""}`
592123
592397
  for await (const chunk of streamable.chatCompletionStream(request)) {
592124
592398
  if (chunk.type === "content" && !chunk.thinking && chunk.content) {
592125
592399
  accumulated += chunk.content;
592126
- onToken(accumulated);
592400
+ await onToken(accumulated);
592127
592401
  }
592128
592402
  }
592129
592403
  }
592130
592404
  if (!accumulated.trim()) {
592131
592405
  const result = await backend.chatCompletion(request);
592132
592406
  accumulated = result.choices[0]?.message?.content ?? "";
592133
- if (accumulated) onToken(accumulated);
592407
+ if (accumulated) await onToken(accumulated);
592134
592408
  }
592135
592409
  return stripTelegramHiddenThinking(accumulated).trim();
592136
592410
  }
592137
592411
  /** Run a sub-agent for a Telegram message */
592138
- async runSubAgent(msg, subAgent, mediaContext = "") {
592412
+ async runSubAgent(msg, subAgent, mediaContext = "", profile = "action") {
592139
592413
  const config = this.agentConfig;
592140
592414
  const repoRoot = this.repoRoot;
592141
592415
  const modelTier = getModelTier(config.model);
@@ -592143,21 +592417,25 @@ ${mediaContext}` : ""}`
592143
592417
  const isAdminDM = ctx3 === "telegram-admin-dm";
592144
592418
  const isAdminGroup = ctx3 === "telegram-admin-group";
592145
592419
  const isGroup = msg.chatType !== "private";
592420
+ const sessionContext = this.buildTelegramSessionContext(msg, ctx3, profile, modelTier);
592146
592421
  const backend = new OllamaAgenticBackend(
592147
592422
  config.backendUrl,
592148
592423
  config.model,
592149
592424
  config.apiKey
592150
592425
  );
592151
592426
  const runner = new AgenticRunner(backend, {
592152
- maxTurns: isAdminDM ? 30 : isAdminGroup ? 12 : 8,
592153
- maxTokens: isAdminDM ? 8192 : 2048,
592427
+ maxTurns: isAdminDM ? profile === "chat" ? 16 : 30 : isAdminGroup ? 12 : 8,
592428
+ maxTokens: isAdminDM ? profile === "chat" ? 6144 : 8192 : 2048,
592154
592429
  temperature: 0.3,
592155
592430
  requestTimeoutMs: config.timeoutMs,
592156
592431
  taskTimeoutMs: isAdminDM ? config.timeoutMs * 3 : config.timeoutMs,
592157
592432
  compactionThreshold: modelTier === "small" ? 8e3 : 16e3,
592158
592433
  modelTier,
592159
- streamEnabled: true
592434
+ streamEnabled: true,
592435
+ dynamicContext: sessionContext.context,
592436
+ sessionId: sessionContext.sessionId
592160
592437
  });
592438
+ runner.setWorkingDirectory(repoRoot);
592161
592439
  subAgent.runner = runner;
592162
592440
  if (subAgent.pendingMessages.length > 0) {
592163
592441
  for (const queued of subAgent.pendingMessages) {
@@ -592166,7 +592444,7 @@ ${mediaContext}` : ""}`
592166
592444
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `replayed ${subAgent.pendingMessages.length} queued message(s)`));
592167
592445
  subAgent.pendingMessages.length = 0;
592168
592446
  }
592169
- const tools = this.buildSubAgentTools(ctx3, repoRoot, msg.chatId);
592447
+ const tools = this.buildSubAgentTools(ctx3, repoRoot, msg.chatId, sessionContext.sessionId);
592170
592448
  runner.registerTools(tools);
592171
592449
  runner.onEvent((event) => {
592172
592450
  if (subAgent.aborted) return;
@@ -592179,33 +592457,46 @@ ${mediaContext}` : ""}`
592179
592457
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `${event.success ? "ok" : "fail"}: ${event.toolName}: ${preview}`);
592180
592458
  } else if (event.type === "status" && event.content) {
592181
592459
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `status: ${event.content}`);
592460
+ } else if (event.type === "assistant_text" && event.content) {
592461
+ subAgent.assistantText = event.content;
592462
+ } else if (event.type === "stream_end" && event.content) {
592463
+ subAgent.streamText = event.content;
592182
592464
  }
592183
- if (subAgent.liveMessageId && !msg.guestQueryId) {
592184
- if (event.type === "stream_token" && event.streamKind === "content" && event.content) {
592185
- subAgent.accumulated += event.content;
592186
- }
592187
- const intermediateLine = formatTelegramProgressEvent(event);
592188
- if (intermediateLine) {
592189
- subAgent.intermediateLines.push(intermediateLine);
592190
- }
592465
+ if (event.type === "stream_token" && event.streamKind === "content" && event.content) {
592466
+ subAgent.accumulated += event.content;
592467
+ }
592468
+ const intermediateLine = formatTelegramProgressEvent(event);
592469
+ if (intermediateLine) {
592470
+ subAgent.intermediateLines.push(intermediateLine);
592471
+ }
592472
+ if (!msg.guestQueryId) {
592473
+ const html = renderTelegramLiveProgressHTML(subAgent.intermediateLines, subAgent.accumulated);
592474
+ if (!html.trim()) return;
592191
592475
  const now = Date.now();
592192
- if (now - subAgent.lastEditMs > 1e3) {
592193
- const hasContent = subAgent.accumulated.length > 10 || subAgent.intermediateLines.length > 0;
592194
- if (hasContent) {
592476
+ if (subAgent.liveMessageId) {
592477
+ if (now - subAgent.lastEditMs > 1e3) {
592195
592478
  subAgent.lastEditMs = now;
592196
- this.editLiveMessage(
592197
- msg.chatId,
592198
- subAgent.liveMessageId,
592199
- renderTelegramLiveProgressHTML(subAgent.intermediateLines, subAgent.accumulated)
592200
- ).catch(() => {
592479
+ this.editLiveMessage(msg.chatId, subAgent.liveMessageId, html).catch(() => {
592201
592480
  });
592202
592481
  }
592482
+ } else if (!subAgent.liveMessagePromise) {
592483
+ subAgent.liveMessagePromise = this.sendLiveMessage(
592484
+ msg.chatId,
592485
+ html,
592486
+ msg.chatType !== "private" ? msg.messageId : void 0
592487
+ ).then((id) => {
592488
+ subAgent.liveMessageId = id;
592489
+ subAgent.lastEditMs = Date.now();
592490
+ }).catch(() => {
592491
+ }).finally(() => {
592492
+ subAgent.liveMessagePromise = null;
592493
+ });
592203
592494
  }
592204
592495
  }
592205
592496
  });
592206
592497
  let systemPrompt;
592207
592498
  if (isAdminDM) {
592208
- systemPrompt = ADMIN_DM_PROMPT;
592499
+ systemPrompt = profile === "chat" ? ADMIN_CHAT_PROFILE_PROMPT : ADMIN_DM_PROMPT;
592209
592500
  } else if (isAdminGroup) {
592210
592501
  systemPrompt = ADMIN_GROUP_PROMPT;
592211
592502
  } else {
@@ -592217,7 +592508,14 @@ ${GROUP_REPLY_DISCRETION_PROMPT}` : "";
592217
592508
  const chatLabel = isGroup ? ` in group "${msg.chatTitle || "unknown"}"` : "";
592218
592509
  let userPrompt;
592219
592510
  if (isAdminDM) {
592220
- userPrompt = `Telegram message from admin @${msg.username}:
592511
+ const profileLine = profile === "chat" ? "Handle this as contextual Telegram chat: answer directly if simple, use tools/delegation if needed." : "Handle this as Telegram action work: complete the requested task or clearly report the blocker.";
592512
+ userPrompt = `${systemPrompt}
592513
+
592514
+ ${TELEGRAM_ACTION_RESPONSE_CONTRACT}
592515
+
592516
+ ${profileLine}
592517
+
592518
+ Telegram message from admin @${msg.username}:
592221
592519
  ${msg.text}`;
592222
592520
  } else {
592223
592521
  const toolHint = "You have access to isolated per-chat memory (memory_write, memory_read, memory_search) scoped to this conversation. You can remember facts about this user and retrieve them later. You also have web_search and web_fetch to look up information.";
@@ -592239,22 +592537,29 @@ Respond concisely and safely.`;
592239
592537
  ${mediaContext}`;
592240
592538
  }
592241
592539
  const systemCtx = isAdminDM ? `Working directory: ${repoRoot}
592242
- Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} chat. Respond concisely. Safety filter: ACTIVE.`;
592540
+ Telegram admin: @${msg.username}
592541
+ Telegram profile: ${profile}
592542
+ Todo/session id: ${sessionContext.sessionId}` : `Telegram ${isGroup ? "group" : "public"} chat. Respond concisely. Safety filter: ACTIVE.`;
592243
592543
  const result = await runner.run(userPrompt, systemCtx);
592244
- return result.summary || subAgent.accumulated || "";
592544
+ return selectTelegramFinalResponse({
592545
+ assistantText: subAgent.assistantText,
592546
+ streamText: subAgent.streamText,
592547
+ accumulated: subAgent.accumulated,
592548
+ summary: result.summary
592549
+ });
592245
592550
  }
592246
592551
  /**
592247
592552
  * Build tool set based on tool context, filtered through the policy system.
592248
592553
  * All possible tools are instantiated, then applyToolPolicy filters them.
592249
592554
  */
592250
- buildSubAgentTools(context2, repoRoot, chatId) {
592555
+ buildSubAgentTools(context2, repoRoot, chatId, todoSessionId) {
592251
592556
  const taskComplete = {
592252
592557
  name: "task_complete",
592253
- description: "Signal that your response is ready to send to the Telegram user. Use summary 'no_reply' to silently skip responding.",
592558
+ description: "Signal that your response is ready to send to the Telegram user. The summary must be the exact final Telegram message, not a meta-summary. Use summary 'no_reply' to silently skip responding.",
592254
592559
  parameters: {
592255
592560
  type: "object",
592256
592561
  properties: {
592257
- summary: { type: "string", description: "The response to send to the Telegram user, or 'no_reply' to skip" }
592562
+ summary: { type: "string", description: "Exact response to send to the Telegram user, or 'no_reply' to skip" }
592258
592563
  },
592259
592564
  required: ["summary"]
592260
592565
  },
@@ -592262,7 +592567,21 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
592262
592567
  return { success: true, output: args["summary"] || "Done." };
592263
592568
  }
592264
592569
  };
592265
- const allTools = [
592570
+ const fullSubAgentTool = new FullSubAgentTool(
592571
+ repoRoot,
592572
+ this.agentConfig?.model,
592573
+ this.agentConfig?.backendUrl,
592574
+ {
592575
+ onViewRegister: (id, label) => this.subAgentViewCallbacks?.onRegister(id, `✈ ${label}`, "Telegram delegated full sub-agent"),
592576
+ onViewWrite: (id, text) => this.subAgentViewCallbacks?.onWrite(id, text),
592577
+ onViewStatus: (id, status) => {
592578
+ if (status === "completed" || status === "failed" || status === "running") {
592579
+ this.subAgentViewCallbacks?.onStatus(id, status);
592580
+ }
592581
+ }
592582
+ }
592583
+ );
592584
+ const sharedReadMemoryWebTools = [
592266
592585
  // File tools
592267
592586
  new FileReadTool(repoRoot),
592268
592587
  new GrepSearchTool(repoRoot),
@@ -592272,6 +592591,8 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
592272
592591
  new MemoryReadTool(repoRoot),
592273
592592
  new MemoryWriteTool(repoRoot),
592274
592593
  new MemorySearchTool(repoRoot),
592594
+ new TodoReadTool(),
592595
+ new TodoWriteTool(),
592275
592596
  // Web tools
592276
592597
  new WebFetchTool(),
592277
592598
  new WebSearchTool(),
@@ -592286,7 +592607,62 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
592286
592607
  new TranscribeFileTool(repoRoot),
592287
592608
  new TranscribeUrlTool(repoRoot)
592288
592609
  ];
592289
- let adaptedTools = allTools.map(adaptTool5);
592610
+ const adminTools = [
592611
+ new ShellTool(repoRoot),
592612
+ new FileReadTool(repoRoot),
592613
+ new FileWriteTool(repoRoot),
592614
+ new FileEditTool(repoRoot),
592615
+ new FilePatchTool(repoRoot),
592616
+ new BatchEditTool(repoRoot),
592617
+ new GrepSearchTool(repoRoot),
592618
+ new GlobFindTool(repoRoot),
592619
+ new ListDirectoryTool(repoRoot),
592620
+ new SessionSearchTool(repoRoot),
592621
+ new ExploreToolsTool(),
592622
+ new CodebaseMapTool(repoRoot),
592623
+ new DiagnosticTool(repoRoot),
592624
+ new GitInfoTool(repoRoot),
592625
+ new PhaseRecallTool(repoRoot),
592626
+ new LogExploreTool(repoRoot),
592627
+ new FileExploreTool(repoRoot),
592628
+ new WorkingNotesTool(),
592629
+ new ProjectScaffoldingTool(),
592630
+ new TodoReadTool(),
592631
+ new TodoWriteTool(),
592632
+ new MemoryReadTool(repoRoot),
592633
+ new MemoryWriteTool(repoRoot),
592634
+ new MemorySearchTool(repoRoot),
592635
+ new WebFetchTool(),
592636
+ new WebSearchTool(),
592637
+ new WebCrawlTool(repoRoot),
592638
+ new StructuredReadTool(repoRoot),
592639
+ new StructuredFileTool(repoRoot),
592640
+ new CodeSandboxTool(repoRoot),
592641
+ new ImageReadTool(repoRoot),
592642
+ new ScreenshotTool(repoRoot),
592643
+ new OCRTool(repoRoot),
592644
+ new OcrImageAdvancedTool(repoRoot),
592645
+ new VisionTool(repoRoot),
592646
+ new OcrPdfTool(repoRoot),
592647
+ new PdfToTextTool(repoRoot),
592648
+ new TranscribeFileTool(repoRoot),
592649
+ new TranscribeUrlTool(repoRoot),
592650
+ new YouTubeDownloadTool(repoRoot),
592651
+ new BrowserActionTool(),
592652
+ new CarbonylBrowserTool(),
592653
+ new PlaywrightBrowserTool(),
592654
+ new ImageGenerateTool(repoRoot, this.agentConfig?.backendUrl),
592655
+ new NotebookEditTool(),
592656
+ new RepoMapTool(repoRoot),
592657
+ new ImportGraphTool(repoRoot),
592658
+ new SymbolSearchTool(repoRoot),
592659
+ new ImpactAnalysisTool(repoRoot),
592660
+ new CodeNeighborsTool(repoRoot),
592661
+ new ProcessHealthTool(),
592662
+ fullSubAgentTool
592663
+ ];
592664
+ const allTools = context2 === "telegram-admin-dm" ? adminTools : sharedReadMemoryWebTools;
592665
+ let adaptedTools = allTools.map((tool) => adaptTool5(tool, todoSessionId));
592290
592666
  adaptedTools = applyToolPolicy(adaptedTools, context2, this.toolPolicyConfig);
592291
592667
  if (context2 !== "telegram-admin-dm") {
592292
592668
  const memWriteIdx = adaptedTools.findIndex((t2) => t2.name === "memory_write");
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.584",
3
+ "version": "0.187.586",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "open-agents-ai",
9
- "version": "0.187.584",
9
+ "version": "0.187.586",
10
10
  "hasInstallScript": true,
11
11
  "license": "CC-BY-NC-4.0",
12
12
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.584",
3
+ "version": "0.187.586",
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",