omnius 1.0.16 → 1.0.18

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
@@ -512308,7 +512308,7 @@ var init_agent_tool = __esm({
512308
512308
  })();
512309
512309
  if (isolation === "worktree") {
512310
512310
  this.callbacks.onViewRegister?.(agentId, label);
512311
- const spawn32 = this.callbacks.spawnSubprocess({
512311
+ const spawn31 = this.callbacks.spawnSubprocess({
512312
512312
  id: agentId,
512313
512313
  task: composedPrompt,
512314
512314
  model,
@@ -512318,7 +512318,7 @@ var init_agent_tool = __esm({
512318
512318
  success: true,
512319
512319
  output: `Agent spawned (subprocess, worktree): ${agentId}
512320
512320
  Type: ${subagentType}
512321
- PID: ${spawn32.pid}
512321
+ PID: ${spawn31.pid}
512322
512322
  Task: ${prompt.slice(0, 100)}
512323
512323
  Use task_status("${agentId}") to check progress.`,
512324
512324
  durationMs: performance.now() - start2
@@ -530830,7 +530830,7 @@ RECOVERY: cd to the directory containing '${file}', run a plain install with no
530830
530830
  import { existsSync as _fsExistsSync, readFileSync as _fsReadFileSync, writeFileSync as _fsWriteFileSync, unlinkSync as _fsUnlinkSync, mkdirSync as _fsMkdirSync } from "node:fs";
530831
530831
  import { execFile as _execFile } from "node:child_process";
530832
530832
  import { createHash as _createHash } from "node:crypto";
530833
- import { join as _pathJoin } from "node:path";
530833
+ import { join as _pathJoin, resolve as _pathResolve } from "node:path";
530834
530834
  import { tmpdir as _osTmpdir } from "node:os";
530835
530835
  import { homedir as _osHomedir } from "node:os";
530836
530836
  import { z as z15 } from "zod";
@@ -531578,6 +531578,9 @@ var init_agenticRunner = __esm({
531578
531578
  compactionThreshold: options2?.compactionThreshold ?? 4e4,
531579
531579
  deepContext: options2?.deepContext ?? false,
531580
531580
  dynamicContext: options2?.dynamicContext ?? "",
531581
+ stateDir: options2?.stateDir ?? "",
531582
+ disablePersistentMemory: options2?.disablePersistentMemory ?? false,
531583
+ disableCodebaseMap: options2?.disableCodebaseMap ?? false,
531581
531584
  sessionId: options2?.sessionId ?? "",
531582
531585
  streamEnabled: options2?.streamEnabled ?? false,
531583
531586
  thinking: options2?.thinking ?? true,
@@ -531604,6 +531607,11 @@ var init_agenticRunner = __esm({
531604
531607
  setWorkingDirectory(dir) {
531605
531608
  this._workingDirectory = dir;
531606
531609
  }
531610
+ /** State root for runner-owned memory/artifacts. Defaults to cwd/.omnius. */
531611
+ omniusStateDir() {
531612
+ const configured = (this.options.stateDir || "").trim();
531613
+ return configured ? _pathResolve(configured) : _pathJoin(process.cwd(), ".omnius");
531614
+ }
531607
531615
  /** Get current task state (for external inspection) */
531608
531616
  get taskState() {
531609
531617
  return this._taskState;
@@ -534298,10 +534306,10 @@ Respond with your assessment, then take action.`;
534298
534306
  this._toolLastUsedTurn.clear();
534299
534307
  this._contextTree = null;
534300
534308
  this._lastSurfacedAnchorIds.clear();
534301
- if (!this._memoryInitialized) {
534309
+ if (!this.options.disablePersistentMemory && !this._memoryInitialized) {
534302
534310
  try {
534303
534311
  const path11 = await import("node:path");
534304
- const omniusDir = path11.join(process.cwd(), ".omnius");
534312
+ const omniusDir = this.omniusStateDir();
534305
534313
  const rawEpisodeStore = new EpisodeStore(path11.join(omniusDir, "episodes.db"));
534306
534314
  const crlConfig = getCRLConfigStore(process.cwd());
534307
534315
  if (crlConfig.get().mode !== "json") {
@@ -534334,8 +534342,9 @@ Respond with your assessment, then take action.`;
534334
534342
  const path11 = await import("node:path");
534335
534343
  const os8 = await import("node:os");
534336
534344
  const globalFile = path11.join(os8.homedir(), ".omnius", "error-patterns.json");
534337
- const localFile = path11.join(process.cwd(), ".omnius", "error-patterns.json");
534338
- for (const patternsFile of [globalFile, localFile]) {
534345
+ const localFile = this.options.stateDir ? path11.join(this.omniusStateDir(), "error-patterns.json") : path11.join(process.cwd(), ".omnius", "error-patterns.json");
534346
+ const patternFiles = this.options.stateDir ? [localFile] : [globalFile, localFile];
534347
+ for (const patternsFile of patternFiles) {
534339
534348
  try {
534340
534349
  if (fs10.existsSync(patternsFile)) {
534341
534350
  const saved = JSON.parse(fs10.readFileSync(patternsFile, "utf8"));
@@ -534426,7 +534435,7 @@ Respond with your assessment, then take action.`;
534426
534435
  } catch {
534427
534436
  }
534428
534437
  }
534429
- if (process.env["OMNIUS_DISABLE_STAGE_CONTEXT"] !== "1") {
534438
+ if (!this.options.disablePersistentMemory && process.env["OMNIUS_DISABLE_STAGE_CONTEXT"] !== "1") {
534430
534439
  try {
534431
534440
  const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
534432
534441
  if (!this._stageContext) {
@@ -534459,7 +534468,7 @@ Respond with your assessment, then take action.`;
534459
534468
  } catch {
534460
534469
  }
534461
534470
  }
534462
- if (process.env["OMNIUS_DISABLE_EMBEDDING_DRIFT_CHECK"] !== "1" && this._episodeStore) {
534471
+ if (!this.options.disablePersistentMemory && process.env["OMNIUS_DISABLE_EMBEDDING_DRIFT_CHECK"] !== "1" && this._episodeStore) {
534463
534472
  try {
534464
534473
  const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
534465
534474
  const currentModel = process.env["OMNIUS_EMBEDDING_MODEL"] || "default";
@@ -534483,7 +534492,7 @@ Respond with your assessment, then take action.`;
534483
534492
  } catch {
534484
534493
  }
534485
534494
  }
534486
- if (process.env["OMNIUS_DISABLE_CODEBASE_MAP"] !== "1" && this._episodeStore && this._workingDirectory) {
534495
+ if (!this.options.disablePersistentMemory && !this.options.disableCodebaseMap && process.env["OMNIUS_DISABLE_CODEBASE_MAP"] !== "1" && this._episodeStore && this._workingDirectory) {
534487
534496
  try {
534488
534497
  const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
534489
534498
  let commitSha = "no-commit";
@@ -534604,7 +534613,7 @@ TASK: ${task}` : task;
534604
534613
  }
534605
534614
  try {
534606
534615
  if (!this._reflectionBuffer) {
534607
- const omniusDir = this._workingDirectory ? _pathJoin(this._workingDirectory, ".omnius", "memory") : null;
534616
+ const omniusDir = this.options.stateDir ? _pathJoin(this.omniusStateDir(), "memory") : this._workingDirectory ? _pathJoin(this._workingDirectory, ".omnius", "memory") : null;
534608
534617
  if (omniusDir) {
534609
534618
  this._reflectionBuffer = new TaskReflectionBuffer(_pathJoin(omniusDir, "reflections.json"));
534610
534619
  }
@@ -536572,7 +536581,7 @@ ${memoryLines.join("\n")}`
536572
536581
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
536573
536582
  });
536574
536583
  try {
536575
- const archDir = __require("node:path").join(process.cwd(), ".omnius", "phases");
536584
+ const archDir = __require("node:path").join(this.omniusStateDir(), "phases");
536576
536585
  __require("node:fs").mkdirSync(archDir, { recursive: true });
536577
536586
  for (const phaseName of contracted) {
536578
536587
  const node = this._contextTree.getSnapshot().phases[phaseName];
@@ -539190,8 +539199,9 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
539190
539199
  const path11 = await import("node:path");
539191
539200
  const os8 = await import("node:os");
539192
539201
  const globalFile = path11.join(os8.homedir(), ".omnius", "error-patterns.json");
539193
- const localFile = path11.join(process.cwd(), ".omnius", "error-patterns.json");
539194
- for (const targetFile of [globalFile, localFile]) {
539202
+ const localFile = path11.join(this.options.stateDir ? this.omniusStateDir() : path11.join(process.cwd(), ".omnius"), "error-patterns.json");
539203
+ const targetFiles = this.options.stateDir ? [localFile] : [globalFile, localFile];
539204
+ for (const targetFile of targetFiles) {
539195
539205
  try {
539196
539206
  const dir = path11.dirname(targetFile);
539197
539207
  fs10.mkdirSync(dir, { recursive: true });
@@ -539243,10 +539253,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
539243
539253
  };
539244
539254
  const fs10 = await import("node:fs");
539245
539255
  const path11 = await import("node:path");
539246
- const consolidDir = path11.join(process.cwd(), ".omnius", "consolidations");
539256
+ const stateDir = this.omniusStateDir();
539257
+ const consolidDir = path11.join(stateDir, "consolidations");
539247
539258
  fs10.mkdirSync(consolidDir, { recursive: true });
539248
539259
  fs10.writeFileSync(path11.join(consolidDir, `${this._sessionId}.json`), JSON.stringify(consolidation, null, 2));
539249
- const provenanceDir = path11.join(process.cwd(), ".omnius", "provenance");
539260
+ const provenanceDir = path11.join(stateDir, "provenance");
539250
539261
  fs10.mkdirSync(provenanceDir, { recursive: true });
539251
539262
  const provenanceGraph = {
539252
539263
  sessionId: this._sessionId,
@@ -539746,7 +539757,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
539746
539757
  try {
539747
539758
  const fs10 = await import("node:fs");
539748
539759
  const path11 = await import("node:path");
539749
- const trajDir = path11.join(process.cwd(), ".omnius", "trajectories");
539760
+ const trajDir = path11.join(this.omniusStateDir(), "trajectories");
539750
539761
  fs10.mkdirSync(trajDir, { recursive: true });
539751
539762
  const trajectory = {
539752
539763
  id: this._sessionId,
@@ -539918,7 +539929,7 @@ ${errOutput}`;
539918
539929
  try {
539919
539930
  const { mkdirSync: mkdirSync76, writeFileSync: writeFileSync71 } = __require("node:fs");
539920
539931
  const { join: join142 } = __require("node:path");
539921
- const resultsDir = join142(process.cwd(), ".omnius", "tool-results");
539932
+ const resultsDir = join142(this.omniusStateDir(), "tool-results");
539922
539933
  mkdirSync76(resultsDir, { recursive: true });
539923
539934
  writeFileSync71(join142(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
539924
539935
  # Turn: ${turn}
@@ -539929,7 +539940,7 @@ ${result.output}`, "utf-8");
539929
539940
  } catch {
539930
539941
  }
539931
539942
  const { join: _pj } = __require("node:path");
539932
- const savedPath = _pj(process.cwd(), ".omnius", "tool-results", `${handleId}.txt`);
539943
+ const savedPath = _pj(this.omniusStateDir(), "tool-results", `${handleId}.txt`);
539933
539944
  const folded = this.foldOutput(modelContent, maxLen);
539934
539945
  return `[Tool output truncated — ${result.output.length} chars, ${lineCount} lines]
539935
539946
  Full output saved to: ${savedPath}
@@ -540283,7 +540294,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
540283
540294
  try {
540284
540295
  const { mkdirSync: mkdirSync76, writeFileSync: writeFileSync71 } = __require("node:fs");
540285
540296
  const { join: join142 } = __require("node:path");
540286
- const sessionDir = join142(this._workingDirectory, ".omnius", "session", this._sessionId);
540297
+ const sessionDir = this.options.stateDir ? join142(this.omniusStateDir(), "session", this._sessionId) : join142(this._workingDirectory, ".omnius", "session", this._sessionId);
540287
540298
  mkdirSync76(sessionDir, { recursive: true });
540288
540299
  const checkpoint = {
540289
540300
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -579164,13 +579175,13 @@ async function runSudoScript(ctx3, script) {
579164
579175
  } catch {
579165
579176
  }
579166
579177
  try {
579167
- const { spawn: spawn32 } = await import("node:child_process");
579178
+ const { spawn: spawn31 } = await import("node:child_process");
579168
579179
  const full = `set -e; ${script}`;
579169
579180
  await new Promise((resolve48) => {
579170
579181
  const usePkexec = process.platform === "linux";
579171
579182
  const cmd = usePkexec ? "pkexec" : "sudo";
579172
579183
  const args = usePkexec ? ["bash", "-lc", full] : ["-n", "bash", "-lc", full];
579173
- const child = spawn32(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
579184
+ const child = spawn31(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
579174
579185
  let stdout = "";
579175
579186
  let stderr = "";
579176
579187
  child.stdout?.on("data", (data) => {
@@ -581357,8 +581368,8 @@ async function handleSlashCommand(input, ctx3) {
581357
581368
  writeFileSync50(jwtFile, JSON.stringify(jwtPayload, null, 2));
581358
581369
  renderInfo(`Launching fortemi-react from ${fDir}...`);
581359
581370
  try {
581360
- const { spawn: spawn32 } = __require("node:child_process");
581361
- const child = spawn32(
581371
+ const { spawn: spawn31 } = __require("node:child_process");
581372
+ const child = spawn31(
581362
581373
  "npx",
581363
581374
  ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"],
581364
581375
  {
@@ -582293,9 +582304,9 @@ systemctl --user daemon-reload || true
582293
582304
  systemctl --user enable --now omnius-daemon.service || true
582294
582305
  sleep 1
582295
582306
  `;
582296
- const { spawn: spawn32 } = await import("node:child_process");
582307
+ const { spawn: spawn31 } = await import("node:child_process");
582297
582308
  await new Promise((resolve48) => {
582298
- const child = spawn32("bash", ["-lc", takeover], {
582309
+ const child = spawn31("bash", ["-lc", takeover], {
582299
582310
  stdio: "inherit"
582300
582311
  });
582301
582312
  onChildExit(child, () => resolve48());
@@ -588307,8 +588318,8 @@ ${escapedContent}EOF'`, {
588307
588318
  }
588308
588319
  await new Promise((r2) => setTimeout(r2, 1e3));
588309
588320
  process.env.OLLAMA_NUM_PARALLEL = String(n2);
588310
- const { spawn: spawn32 } = await import("node:child_process");
588311
- const child = spawn32("ollama", ["serve"], {
588321
+ const { spawn: spawn31 } = await import("node:child_process");
588322
+ const child = spawn31("ollama", ["serve"], {
588312
588323
  stdio: "ignore",
588313
588324
  detached: true,
588314
588325
  env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n2) }
@@ -596226,9 +596237,9 @@ function getDefaultPolicy(context2) {
596226
596237
  case "telegram-admin-dm":
596227
596238
  return { blocked: /* @__PURE__ */ new Set(), allowed: /* @__PURE__ */ new Set() };
596228
596239
  case "telegram-admin-group":
596229
- return { blocked: /* @__PURE__ */ new Set(), allowed: SAFE_GROUP_ADMIN_TOOLS };
596240
+ return { blocked: new Set(SYSTEM_TOOLS), allowed: SAFE_GROUP_ADMIN_TOOLS };
596230
596241
  case "telegram-public":
596231
- return { blocked: /* @__PURE__ */ new Set(), allowed: SAFE_PUBLIC_TOOLS };
596242
+ return { blocked: new Set(SYSTEM_TOOLS), allowed: SAFE_PUBLIC_TOOLS };
596232
596243
  case "api":
596233
596244
  return { blocked: /* @__PURE__ */ new Set(), allowed: /* @__PURE__ */ new Set() };
596234
596245
  default:
@@ -596263,10 +596274,43 @@ function applyToolPolicy(tools, context2, userConfig) {
596263
596274
  return policy.allowed.has(tool.name);
596264
596275
  });
596265
596276
  }
596266
- var SAFE_PUBLIC_TOOLS, SAFE_GROUP_ADMIN_TOOLS;
596277
+ var SYSTEM_TOOLS, SAFE_PUBLIC_TOOLS, SAFE_GROUP_ADMIN_TOOLS;
596267
596278
  var init_tool_policy = __esm({
596268
596279
  "packages/cli/src/tui/tool-policy.ts"() {
596269
596280
  "use strict";
596281
+ SYSTEM_TOOLS = /* @__PURE__ */ new Set([
596282
+ "shell",
596283
+ "file_write",
596284
+ "file_edit",
596285
+ "file_read",
596286
+ "file_patch",
596287
+ "batch_edit",
596288
+ "structured_file",
596289
+ "grep_search",
596290
+ "glob_find",
596291
+ "list_directory",
596292
+ "code_sandbox",
596293
+ "codebase_map",
596294
+ "diagnostic",
596295
+ "git_info",
596296
+ "structured_read",
596297
+ "screenshot",
596298
+ "desktop_click",
596299
+ "desktop_describe",
596300
+ "background_run",
596301
+ "task_status",
596302
+ "task_output",
596303
+ "task_stop",
596304
+ "create_tool",
596305
+ "manage_tools",
596306
+ "aiwg_setup",
596307
+ "aiwg_health",
596308
+ "aiwg_workflow",
596309
+ "autoresearch",
596310
+ "scheduler",
596311
+ "reminder",
596312
+ "agenda"
596313
+ ]);
596270
596314
  SAFE_PUBLIC_TOOLS = /* @__PURE__ */ new Set([
596271
596315
  "memory_read",
596272
596316
  "memory_write",
@@ -596304,7 +596348,6 @@ var init_tool_policy = __esm({
596304
596348
  });
596305
596349
 
596306
596350
  // packages/cli/src/tui/telegram-creative-tools.ts
596307
- import { spawn as spawn27 } from "node:child_process";
596308
596351
  import {
596309
596352
  existsSync as existsSync104,
596310
596353
  mkdirSync as mkdirSync59,
@@ -596530,32 +596573,6 @@ function denied(error) {
596530
596573
  mutatedFiles: []
596531
596574
  };
596532
596575
  }
596533
- function runProcess4(command, args, cwd4, timeoutMs) {
596534
- return new Promise((resolveProcess) => {
596535
- const child = spawn27(command, args, {
596536
- cwd: cwd4,
596537
- stdio: ["ignore", "pipe", "pipe"]
596538
- });
596539
- let stdout = "";
596540
- let stderr = "";
596541
- const timer = setTimeout(() => child.kill("SIGTERM"), timeoutMs);
596542
- timer.unref();
596543
- child.stdout?.on("data", (chunk) => {
596544
- stdout += chunk.toString();
596545
- });
596546
- child.stderr?.on("data", (chunk) => {
596547
- stderr += chunk.toString();
596548
- });
596549
- onChildError(child, (err) => {
596550
- clearTimeout(timer);
596551
- resolveProcess({ code: 127, stdout, stderr: stderr + String(err.message || err) });
596552
- });
596553
- onChildClose(child, (code8) => {
596554
- clearTimeout(timer);
596555
- resolveProcess({ code: code8, stdout, stderr });
596556
- });
596557
- });
596558
- }
596559
596576
  var MANIFEST_FILE, PATH_KEYS, MEDIA_PATH_RE, CreativeAudioFileTool;
596560
596577
  var init_telegram_creative_tools = __esm({
596561
596578
  "packages/cli/src/tui/telegram-creative-tools.ts"() {
@@ -596577,8 +596594,11 @@ var init_telegram_creative_tools = __esm({
596577
596594
  properties: {
596578
596595
  text: { type: "string", description: "Text to synthesize into speech" },
596579
596596
  path: { type: "string", description: "Output .wav path inside the creative workspace" },
596580
- voice: { type: "string", description: "espeak-ng voice/language, default en" },
596581
- speed: { type: "number", description: "Speech speed, default 160" }
596597
+ backend: { type: "string", enum: ["auto", "luxtts", "supertonic", "mlx", "onnx", "piper", "espeak"], description: "TTS backend. Defaults to auto." },
596598
+ voice: { type: "string", description: "Voice id/name for the selected TTS backend" },
596599
+ clone_ref: { type: "string", description: "Optional LuxTTS clone reference" },
596600
+ model: { type: "string", description: "Optional backend model id or raw Piper/ONNX path" },
596601
+ speed: { type: "number", description: "Speech speed multiplier or backend-specific rate" }
596582
596602
  },
596583
596603
  required: ["text", "path"]
596584
596604
  };
@@ -596596,15 +596616,23 @@ var init_telegram_creative_tools = __esm({
596596
596616
  return denied("create_audio_file currently writes WAV files; use a .wav output path.");
596597
596617
  }
596598
596618
  await mkdir17(dirname33(guarded.path.abs), { recursive: true });
596599
- const voice = typeof args["voice"] === "string" && args["voice"].trim() ? String(args["voice"]) : "en";
596600
- const speed = Number.isFinite(Number(args["speed"])) ? String(Math.round(Number(args["speed"]))) : "160";
596601
- const result = await runProcess4("espeak-ng", ["-w", guarded.path.abs, "-v", voice, "-s", speed, text], this.root, 12e4);
596602
- if (result.code !== 0 || !existsSync104(guarded.path.abs)) {
596619
+ const tts = new TtsGenerateTool();
596620
+ const result = await tts.execute({
596621
+ text,
596622
+ output: guarded.path.abs,
596623
+ playback: false,
596624
+ backend: args["backend"],
596625
+ voice: args["voice"],
596626
+ clone_ref: args["clone_ref"],
596627
+ model: args["model"],
596628
+ speed: args["speed"]
596629
+ });
596630
+ if (!result.success || !existsSync104(guarded.path.abs)) {
596603
596631
  return {
596604
596632
  success: false,
596605
596633
  output: "",
596606
- error: `Audio synthesis failed. Install espeak-ng or check voice settings.
596607
- ${(result.stderr || result.stdout).slice(0, 800)}`,
596634
+ error: `Audio synthesis failed through generate_tts.
596635
+ ${(result.error || result.output || "").slice(0, 1200)}`,
596608
596636
  durationMs: performance.now() - start2
596609
596637
  };
596610
596638
  }
@@ -596612,7 +596640,8 @@ ${(result.stderr || result.stdout).slice(0, 800)}`,
596612
596640
  const sizeKB = Math.round(statSync35(guarded.path.abs).size / 1024);
596613
596641
  return {
596614
596642
  success: true,
596615
- output: `Created audio file: ${guarded.path.abs} (${sizeKB}KB WAV)`,
596643
+ output: `Created audio file: ${guarded.path.abs} (${sizeKB}KB WAV)
596644
+ ${result.output}`,
596616
596645
  llmContent: `Created audio file at ${guarded.path.abs}.`,
596617
596646
  durationMs: performance.now() - start2,
596618
596647
  mutated: true,
@@ -596777,7 +596806,7 @@ var init_vision_ingress = __esm({
596777
596806
  });
596778
596807
 
596779
596808
  // packages/cli/src/tui/telegram-bridge.ts
596780
- import { mkdirSync as mkdirSync60, existsSync as existsSync106, unlinkSync as unlinkSync20, statSync as statSync36, readFileSync as readFileSync87, writeFileSync as writeFileSync57 } from "node:fs";
596809
+ import { mkdirSync as mkdirSync60, existsSync as existsSync106, unlinkSync as unlinkSync20, readdirSync as readdirSync36, statSync as statSync36, readFileSync as readFileSync87, writeFileSync as writeFileSync57 } from "node:fs";
596781
596810
  import { join as join121, resolve as resolve39, basename as basename23, relative as relative13, isAbsolute as isAbsolute7 } from "node:path";
596782
596811
  import { writeFile as writeFileAsync } from "node:fs/promises";
596783
596812
  import { createHash as createHash19, randomInt } from "node:crypto";
@@ -597044,6 +597073,12 @@ function telegramSessionIdFromKey(sessionKey) {
597044
597073
  return `telegram-${createHash19("sha1").update(sessionKey).digest("hex").slice(0, 16)}`;
597045
597074
  }
597046
597075
  function selectTelegramFinalResponse(args) {
597076
+ const committedVisibleReply = cleanTelegramVisibleReply(args.visibleReplyText || "");
597077
+ if (committedVisibleReply) return committedVisibleReply;
597078
+ if (args.completionBoundarySeen) {
597079
+ void args.summary;
597080
+ return "";
597081
+ }
597047
597082
  const visibleCandidates = [
597048
597083
  args.streamText,
597049
597084
  args.accumulated,
@@ -597586,6 +597621,13 @@ You are responding to an ADMIN user in a private Telegram DM. This user has full
597586
597621
  and is the operator of this agent. You may use all available tools including memory read/write,
597587
597622
  file access, and code analysis. Respond thoroughly and helpfully.
597588
597623
 
597624
+ When asked to send a generated or existing file to Telegram, call telegram_send_file with
597625
+ path and target. Do not search for Telegram bot tokens, environment secrets, or Bot API
597626
+ credentials; upload authorization is encapsulated by telegram_send_file.
597627
+
597628
+ When asked to generate speech, narration, or TTS, use generate_tts or audio_playback.
597629
+ Do not fall back to shell commands for speech synthesis while those tools are available.
597630
+
597589
597631
  Keep responses concise for Telegram but don't withhold information from the admin.
597590
597632
  `.trim();
597591
597633
  ADMIN_GROUP_PROMPT = `
@@ -597815,6 +597857,8 @@ Telegram response contract:
597815
597857
  telegramConversationDir;
597816
597858
  /** Session keys loaded from persistent conversation memory */
597817
597859
  loadedConversationState = /* @__PURE__ */ new Set();
597860
+ /** True once persisted Telegram conversation scopes have been bulk-loaded. */
597861
+ loadedAllConversationState = false;
597818
597862
  /** Media metadata store per chat — chatId → metadata entries */
597819
597863
  mediaMetadata = /* @__PURE__ */ new Map();
597820
597864
  /** Cleanup timer for expired media cache entries */
@@ -598021,6 +598065,22 @@ Telegram response contract:
598021
598065
  } catch {
598022
598066
  }
598023
598067
  }
598068
+ ensureAllTelegramConversationsLoaded() {
598069
+ if (this.loadedAllConversationState) return;
598070
+ this.loadedAllConversationState = true;
598071
+ if (!existsSync106(this.telegramConversationDir)) return;
598072
+ try {
598073
+ for (const file of readdirSync36(this.telegramConversationDir)) {
598074
+ if (!file.endsWith(".json")) continue;
598075
+ try {
598076
+ const parsed = JSON.parse(readFileSync87(join121(this.telegramConversationDir, file), "utf8"));
598077
+ if (parsed.sessionKey) this.ensureTelegramConversationLoaded(parsed.sessionKey);
598078
+ } catch {
598079
+ }
598080
+ }
598081
+ } catch {
598082
+ }
598083
+ }
598024
598084
  saveTelegramConversationState(sessionKey) {
598025
598085
  if (!this.repoRoot) return;
598026
598086
  try {
@@ -598499,8 +598559,91 @@ ${lines.join("\n")}${suffix}`;
598499
598559
  Checklist unavailable: ${reason}`;
598500
598560
  }
598501
598561
  }
598562
+ knownTelegramChatTargets() {
598563
+ this.ensureAllTelegramConversationsLoaded();
598564
+ const targets = /* @__PURE__ */ new Map();
598565
+ for (const [sessionKey, history] of this.chatHistory.entries()) {
598566
+ if (history.length === 0) continue;
598567
+ const latest = [...history].reverse().find((entry) => entry.chatId !== void 0);
598568
+ if (!latest || latest.chatId === void 0) continue;
598569
+ const key = String(latest.chatId);
598570
+ const participants = [...this.chatParticipants.get(sessionKey)?.values() ?? []];
598571
+ const existing = targets.get(key);
598572
+ const target = existing ?? {
598573
+ chatId: latest.chatId,
598574
+ chatType: latest.chatType ?? "private",
598575
+ title: latest.chatTitle,
598576
+ sessionKey,
598577
+ lastSeenTs: latest.ts ?? 0,
598578
+ participantUserIds: [],
598579
+ participantUsernames: []
598580
+ };
598581
+ target.chatType = latest.chatType ?? target.chatType;
598582
+ target.title = latest.chatTitle || target.title;
598583
+ target.lastSeenTs = Math.max(target.lastSeenTs, latest.ts ?? 0);
598584
+ for (const participant of participants) {
598585
+ if (participant.fromUserId && !target.participantUserIds.includes(participant.fromUserId)) {
598586
+ target.participantUserIds.push(participant.fromUserId);
598587
+ }
598588
+ const username = (participant.username || "").replace(/^@/, "").trim().toLowerCase();
598589
+ if (username && username !== "unknown" && !target.participantUsernames.includes(username)) {
598590
+ target.participantUsernames.push(username);
598591
+ }
598592
+ }
598593
+ targets.set(key, target);
598594
+ }
598595
+ return [...targets.values()].sort((a2, b) => b.lastSeenTs - a2.lastSeenTs);
598596
+ }
598597
+ telegramGroupTargetsForSender(msg) {
598598
+ const username = (msg.username || "").replace(/^@/, "").trim().toLowerCase();
598599
+ return this.knownTelegramChatTargets().filter((target) => {
598600
+ if (target.chatType !== "group" && target.chatType !== "supergroup") return false;
598601
+ if (msg.fromUserId && target.participantUserIds.includes(msg.fromUserId)) return true;
598602
+ return !!username && target.participantUsernames.includes(username);
598603
+ });
598604
+ }
598605
+ formatTelegramSendTargetList(targets, max = 14) {
598606
+ if (targets.length === 0) return "";
598607
+ const lines = targets.slice(0, max).map((target) => {
598608
+ const label = target.title ? ` "${target.title}"` : "";
598609
+ const participants = target.participantUsernames.length ? ` participants:@${target.participantUsernames.slice(0, 8).join(", @")}` : "";
598610
+ return `- chat_id ${String(target.chatId)} (${target.chatType}${label}; session ${target.sessionKey})${participants}`;
598611
+ });
598612
+ const suffix = targets.length > lines.length ? `
598613
+ - ... ${targets.length - lines.length} more known chat(s)` : "";
598614
+ return `${lines.join("\n")}${suffix}`;
598615
+ }
598616
+ buildTelegramSendTargetContext(msg, isAdminDM) {
598617
+ if (isAdminDM) {
598618
+ const targets = this.knownTelegramChatTargets();
598619
+ const list = this.formatTelegramSendTargetList(targets, 18);
598620
+ return [
598621
+ "## Telegram Send Targets",
598622
+ "telegram_send_file is the only supported way to send generated/existing files to Telegram. Never look for or reveal the bot token; the bridge already owns upload auth.",
598623
+ "Use target with one of these known chat ids when the admin asks to send a file to a group/private chat:",
598624
+ list || "- No known prior Telegram chats are loaded yet. Numeric chat_id or @username can still be used if the admin provides one."
598625
+ ].join("\n");
598626
+ }
598627
+ if (msg.chatType === "private") {
598628
+ const targets = this.telegramGroupTargetsForSender(msg);
598629
+ const list = this.formatTelegramSendTargetList(targets, 10);
598630
+ return [
598631
+ "## Telegram Send Targets",
598632
+ "This private user may send generated files to this DM or to shared public groups where this sender has been observed by the bot. Public groups can never target private DMs.",
598633
+ list ? `Allowed shared group targets:
598634
+ ${list}` : "No shared group target is currently known for this sender. Ask in the group once or provide a numeric group chat_id the bot already participates in."
598635
+ ].join("\n");
598636
+ }
598637
+ return "";
598638
+ }
598639
+ telegramRunnerStateDir(sessionKey) {
598640
+ if (!this.repoRoot) return void 0;
598641
+ const safe = createHash19("sha1").update(sessionKey).digest("hex").slice(0, 20);
598642
+ return join121(this.repoRoot, ".omnius", "telegram-runner-state", safe);
598643
+ }
598502
598644
  buildTelegramAdminOverviewContext(currentSessionKey) {
598503
598645
  const sections = [];
598646
+ this.ensureAllTelegramConversationsLoaded();
598504
598647
  const chatEntries = [...this.chatHistory.entries()].filter(([sessionKey, history]) => sessionKey !== currentSessionKey && history.length > 0).sort(([, a2], [, b]) => (b[b.length - 1]?.ts ?? 0) - (a2[a2.length - 1]?.ts ?? 0)).slice(0, 18);
598505
598648
  for (const [sessionKey, history] of chatEntries) {
598506
598649
  const latest = history[history.length - 1];
@@ -598513,7 +598656,7 @@ Checklist unavailable: ${reason}`;
598513
598656
  ).join("\n");
598514
598657
  const cards = (this.chatMemoryCards.get(sessionKey) ?? []).slice(0, 4).map((card) => ` - ${card.title}: ${card.notes.slice(-1)[0] ?? ""}`).join("\n");
598515
598658
  sections.push([
598516
- `- ${sessionKey} (${latest.chatType || "chat"}${latest.chatTitle ? `: ${latest.chatTitle}` : ""})`,
598659
+ `- ${sessionKey} (chat_id ${String(latest.chatId ?? "unknown")}; ${latest.chatType || "chat"}${latest.chatTitle ? `: ${latest.chatTitle}` : ""})`,
598517
598660
  participants ? ` Participants: ${participants}` : "",
598518
598661
  ` Latest: ${telegramHistorySpeaker(latest)}: ${truncateTelegramContextLine(latest.text, 180)}`,
598519
598662
  recent ? ` Recent:
@@ -598554,6 +598697,8 @@ ${chatLabel}`,
598554
598697
  TELEGRAM_ACTION_RESPONSE_CONTRACT
598555
598698
  ];
598556
598699
  sections.push(conversationStream);
598700
+ const sendTargetContext = this.buildTelegramSendTargetContext(msg, isAdminDM);
598701
+ if (sendTargetContext) sections.push(sendTargetContext);
598557
598702
  if (isAdminDM) {
598558
598703
  sections.push(`## Admin Capability Contract
598559
598704
 
@@ -598961,6 +599106,9 @@ ${mediaContext}`;
598961
599106
  accumulated: "",
598962
599107
  assistantText: "",
598963
599108
  streamText: "",
599109
+ visibleReplyText: "",
599110
+ currentStreamToolNames: /* @__PURE__ */ new Set(),
599111
+ completionBoundarySeen: false,
598964
599112
  intermediateLines: [],
598965
599113
  lastEditMs: 0,
598966
599114
  aborted: false,
@@ -599059,6 +599207,9 @@ ${mediaContext}`;
599059
599207
  accumulated: "",
599060
599208
  assistantText: "",
599061
599209
  streamText: "",
599210
+ visibleReplyText: "",
599211
+ currentStreamToolNames: /* @__PURE__ */ new Set(),
599212
+ completionBoundarySeen: false,
599062
599213
  intermediateLines: [],
599063
599214
  lastEditMs: 0,
599064
599215
  aborted: false,
@@ -599334,6 +599485,22 @@ ${mediaContext}` : ""}`
599334
599485
  }
599335
599486
  return stripTelegramHiddenThinking(accumulated).trim();
599336
599487
  }
599488
+ retainTelegramVisibleReplyDraft(subAgent, draft, streamToolNames = subAgent.currentStreamToolNames) {
599489
+ if (subAgent.visibleReplyText) return;
599490
+ const clean3 = cleanTelegramVisibleReply(draft);
599491
+ if (!clean3) return;
599492
+ const toolNames = [...streamToolNames];
599493
+ const hasNonCompletionTool = toolNames.some((name10) => name10 !== "task_complete");
599494
+ if (hasNonCompletionTool) return;
599495
+ subAgent.visibleReplyText = clean3;
599496
+ }
599497
+ retainTelegramVisibleReplyFromCompletedStream(subAgent) {
599498
+ this.retainTelegramVisibleReplyDraft(
599499
+ subAgent,
599500
+ subAgent.streamText || subAgent.accumulated,
599501
+ subAgent.currentStreamToolNames
599502
+ );
599503
+ }
599337
599504
  /** Run a sub-agent for a Telegram message */
599338
599505
  async runSubAgent(msg, subAgent, mediaContext = "", profile = "action") {
599339
599506
  const config = this.agentConfig;
@@ -599346,6 +599513,7 @@ ${mediaContext}` : ""}`
599346
599513
  const creativeWorkspace = subAgent.creativeWorkspaceRoot ? formatTelegramCreativeWorkspacePrompt(subAgent.creativeWorkspaceRoot) : "";
599347
599514
  const sessionContext = this.buildTelegramSessionContext(msg, ctx3, profile, modelTier);
599348
599515
  const contextWindowSize = this.contextWindowSize;
599516
+ const runnerStateDir = isAdminDM ? void 0 : this.telegramRunnerStateDir(sessionContext.sessionKey);
599349
599517
  const backend = new OllamaAgenticBackend(
599350
599518
  config.backendUrl,
599351
599519
  config.model,
@@ -599362,7 +599530,11 @@ ${mediaContext}` : ""}`
599362
599530
  modelTier,
599363
599531
  streamEnabled: true,
599364
599532
  dynamicContext: sessionContext.context,
599365
- sessionId: sessionContext.sessionId
599533
+ stateDir: runnerStateDir,
599534
+ sessionId: sessionContext.sessionId,
599535
+ disablePersistentMemory: false,
599536
+ disableCodebaseMap: !isAdminDM,
599537
+ subAgent: !isAdminDM
599366
599538
  });
599367
599539
  runner.setWorkingDirectory(repoRoot);
599368
599540
  subAgent.runner = runner;
@@ -599379,6 +599551,16 @@ ${mediaContext}` : ""}`
599379
599551
  if (subAgent.aborted) return;
599380
599552
  let suppressExternalEvent = false;
599381
599553
  if (event.type === "tool_call" && event.toolName) {
599554
+ if (event.toolName === "task_complete") {
599555
+ subAgent.completionBoundarySeen = true;
599556
+ const toolNamesAtCompletion = new Set(subAgent.currentStreamToolNames);
599557
+ toolNamesAtCompletion.add("task_complete");
599558
+ this.retainTelegramVisibleReplyDraft(
599559
+ subAgent,
599560
+ subAgent.accumulated || subAgent.streamText,
599561
+ toolNamesAtCompletion
599562
+ );
599563
+ }
599382
599564
  const fp = `${event.toolName}:${stableTelegramValueKey(event.toolArgs ?? {})}`;
599383
599565
  if (subAgent.surfacedToolCallFingerprints.has(fp)) {
599384
599566
  suppressExternalEvent = true;
@@ -599390,6 +599572,7 @@ ${mediaContext}` : ""}`
599390
599572
  this.onSubAgentEvent?.(msg.chatId, msg.username, event);
599391
599573
  }
599392
599574
  if (event.type === "tool_call" && event.toolName) {
599575
+ subAgent.currentStreamToolNames.add(event.toolName);
599393
599576
  if (suppressExternalEvent) return;
599394
599577
  const argsPreview = event.toolArgs ? JSON.stringify(event.toolArgs).slice(0, 100) : "";
599395
599578
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `tool: ${event.toolName}(${argsPreview})`);
@@ -599406,8 +599589,10 @@ ${mediaContext}` : ""}`
599406
599589
  } else if (event.type === "assistant_text" && event.content && event.source !== "task_complete_summary") {
599407
599590
  subAgent.assistantText = event.content;
599408
599591
  } else if (event.type === "stream_start") {
599592
+ this.retainTelegramVisibleReplyFromCompletedStream(subAgent);
599409
599593
  subAgent.accumulated = "";
599410
599594
  subAgent.streamText = "";
599595
+ subAgent.currentStreamToolNames.clear();
599411
599596
  } else if (event.type === "stream_end" && event.content) {
599412
599597
  subAgent.streamText = event.content;
599413
599598
  }
@@ -599415,11 +599600,14 @@ ${mediaContext}` : ""}`
599415
599600
  subAgent.accumulated += event.content;
599416
599601
  }
599417
599602
  const intermediateLine = formatTelegramProgressEvent(event);
599418
- if (intermediateLine) {
599603
+ if (intermediateLine && (isAdminDM || event.type !== "status")) {
599419
599604
  subAgent.intermediateLines.push(intermediateLine);
599420
599605
  }
599421
599606
  if (!msg.guestQueryId) {
599422
- const html = renderTelegramLiveProgressHTML(subAgent.intermediateLines, subAgent.accumulated);
599607
+ const html = renderTelegramLiveProgressHTML(
599608
+ subAgent.intermediateLines,
599609
+ subAgent.visibleReplyText || subAgent.accumulated
599610
+ );
599423
599611
  if (!html.trim()) return;
599424
599612
  const now = Date.now();
599425
599613
  if (subAgent.liveMessageId) {
@@ -599500,10 +599688,12 @@ Todo/session id: ${sessionContext.sessionId}` : `Telegram ${isGroup ? "group" :
599500
599688
  ${creativeWorkspace}` : ""}`;
599501
599689
  const result = await runner.run(userPrompt, systemCtx);
599502
599690
  return selectTelegramFinalResponse({
599691
+ visibleReplyText: subAgent.visibleReplyText,
599503
599692
  assistantText: subAgent.assistantText,
599504
599693
  streamText: subAgent.streamText,
599505
599694
  accumulated: subAgent.accumulated,
599506
- summary: result.summary
599695
+ summary: result.summary,
599696
+ completionBoundarySeen: subAgent.completionBoundarySeen
599507
599697
  });
599508
599698
  }
599509
599699
  telegramScopedMemoryPrefix(chatId) {
@@ -599832,6 +600022,9 @@ Scoped workspace: ${scopedRoot}`,
599832
600022
  new PlaywrightBrowserTool(),
599833
600023
  new ImageGenerateTool(repoRoot, this.agentConfig?.backendUrl, imageDefaults),
599834
600024
  new AudioGenerateTool(repoRoot, audioDefaults),
600025
+ new TtsGenerateTool(),
600026
+ new AudioPlaybackTool(),
600027
+ new SoundPlaybackTool(),
599835
600028
  new NotebookEditTool(),
599836
600029
  new RepoMapTool(repoRoot),
599837
600030
  new ImportGraphTool(repoRoot),
@@ -599840,7 +600033,7 @@ Scoped workspace: ${scopedRoot}`,
599840
600033
  new CodeNeighborsTool(repoRoot),
599841
600034
  new ProcessHealthTool(),
599842
600035
  fullSubAgentTool,
599843
- this.buildTelegramSendFileTool(context2, repoRoot, chatId)
600036
+ this.buildTelegramSendFileTool(context2, repoRoot, chatId, msg)
599844
600037
  ];
599845
600038
  const allTools = context2 === "telegram-admin-dm" ? adminTools : sharedReadMemoryWebTools;
599846
600039
  if (this.contextWindowSize > 0) {
@@ -599862,7 +600055,7 @@ Scoped workspace: ${scopedRoot}`,
599862
600055
  audioDefaults
599863
600056
  ).map((tool) => adaptTool5(tool, todoSessionId));
599864
600057
  adaptedTools.push(...creativeTools);
599865
- adaptedTools.push(adaptTool5(this.buildTelegramSendFileTool(context2, repoRoot, chatId), todoSessionId));
600058
+ adaptedTools.push(adaptTool5(this.buildTelegramSendFileTool(context2, repoRoot, chatId, msg), todoSessionId));
599866
600059
  adaptedTools.push(adaptTool5(this.buildTelegramSandboxHandoffTool(context2, repoRoot, `chat:${String(chatId ?? "unknown")}`, chatId), todoSessionId));
599867
600060
  }
599868
600061
  return [...adaptedTools, taskComplete];
@@ -599883,13 +600076,13 @@ Scoped workspace: ${scopedRoot}`,
599883
600076
  musicBackend: settings.musicBackend
599884
600077
  };
599885
600078
  }
599886
- buildTelegramSendFileTool(context2, repoRoot, currentChatId) {
600079
+ buildTelegramSendFileTool(context2, repoRoot, currentChatId, currentMsg) {
599887
600080
  const bridge = this;
599888
600081
  const adminDm = context2 === "telegram-admin-dm";
599889
600082
  const scopedRoot = adminDm ? void 0 : telegramCreativeWorkspaceRoot(repoRoot, currentChatId);
599890
600083
  return {
599891
600084
  name: "telegram_send_file",
599892
- description: adminDm ? "Upload an existing local file to a Telegram chat. Admin DM scope may target the current chat, a numeric chat/user id, or a @username if the bot is allowed to message it. This only sends the file; it does not create, edit, or delete files." : `Upload an existing file from this chat's scoped creative workspace to the current Telegram chat. Public/group scope cannot target other chats and cannot send files outside ${scopedRoot}.`,
600085
+ description: adminDm ? "Upload an existing local file to a Telegram target. Use target=<chat_id|user_id|@username> to send to a specific group/user the bot can message. This only sends the file; it does not create, edit, delete, or inspect bot tokens." : currentMsg?.chatType === "private" ? `Upload an existing file from this private chat's scoped creative workspace. target may be omitted for this DM or set to a known shared group chat_id for this sender. It cannot target other private users and cannot send files outside ${scopedRoot}.` : `Upload an existing file from this chat's scoped creative workspace to the current Telegram chat. Public/group scope cannot target private DMs or other chats and cannot send files outside ${scopedRoot}.`,
599893
600086
  parameters: {
599894
600087
  type: "object",
599895
600088
  properties: {
@@ -599897,13 +600090,25 @@ Scoped workspace: ${scopedRoot}`,
599897
600090
  type: "string",
599898
600091
  description: adminDm ? "Local file path to send. Relative paths resolve from the repo root; absolute paths are allowed for admin DM." : "File path inside the scoped creative workspace."
599899
600092
  },
600093
+ target: {
600094
+ type: "string",
600095
+ description: adminDm ? "Optional target chat/user. Use a known numeric group chat_id (for example -100...), a numeric user id, or @username. Defaults to the current private chat." : currentMsg?.chatType === "private" ? "Optional target. Omit for this DM, or use a known shared group chat_id/title/session key for this sender." : "Public/group scope ignores external targets and may only send to the current chat."
600096
+ },
599900
600097
  chat_id: {
599901
600098
  type: "string",
599902
- description: "Admin DM only. Optional target chat/user id or @username. Defaults to the current Telegram chat."
600099
+ description: "Alias for target. Admin/private DM only."
600100
+ },
600101
+ target_chat_id: {
600102
+ type: "string",
600103
+ description: "Alias for target/chat_id. Admin/private DM only."
599903
600104
  },
599904
600105
  user_id: {
599905
600106
  type: "string",
599906
- description: "Admin DM only. Optional numeric Telegram user id to send to, if the bot can message that user."
600107
+ description: "Alias for target when sending to a numeric Telegram user id from admin/private DM."
600108
+ },
600109
+ username: {
600110
+ type: "string",
600111
+ description: "Alias for target when sending to @username from admin/private DM."
599907
600112
  },
599908
600113
  kind: {
599909
600114
  type: "string",
@@ -599927,7 +600132,7 @@ Scoped workspace: ${scopedRoot}`,
599927
600132
  if (!rawPath) {
599928
600133
  return { success: false, output: "", error: "path is required", durationMs: performance.now() - start2 };
599929
600134
  }
599930
- const target = bridge.resolveTelegramFileTarget(args, currentChatId, adminDm);
600135
+ const target = bridge.resolveTelegramFileTarget(args, currentChatId, adminDm, currentMsg);
599931
600136
  if (!target.ok) {
599932
600137
  return { success: false, output: "", error: target.error, durationMs: performance.now() - start2 };
599933
600138
  }
@@ -599963,9 +600168,34 @@ Scoped workspace: ${scopedRoot}`,
599963
600168
  }
599964
600169
  };
599965
600170
  }
599966
- resolveTelegramFileTarget(args, currentChatId, adminDm) {
599967
- const rawTarget = args["chat_id"] ?? args["target_chat_id"] ?? args["user_id"] ?? args["username"];
600171
+ resolveTelegramFileTarget(args, currentChatId, adminDm, currentMsg) {
600172
+ const rawTarget = args["target"] ?? args["chat_id"] ?? args["target_chat_id"] ?? args["user_id"] ?? args["username"];
599968
600173
  if (!adminDm) {
600174
+ if (currentMsg?.chatType === "private") {
600175
+ if (rawTarget === void 0 || !String(rawTarget).trim()) {
600176
+ if (currentChatId === void 0) return { ok: false, error: "Current Telegram chat id is unavailable." };
600177
+ return { ok: true, chatId: currentChatId };
600178
+ }
600179
+ const target2 = String(rawTarget).trim();
600180
+ if (currentChatId !== void 0 && target2 === String(currentChatId)) {
600181
+ return { ok: true, chatId: currentChatId };
600182
+ }
600183
+ const knownGroups = this.telegramGroupTargetsForSender(currentMsg);
600184
+ const normalized = target2.replace(/^@/, "").trim().toLowerCase();
600185
+ const match = knownGroups.find((candidate) => {
600186
+ if (String(candidate.chatId) === target2) return true;
600187
+ if (candidate.sessionKey === target2) return true;
600188
+ if (candidate.title && candidate.title.trim().toLowerCase() === normalized) return true;
600189
+ return false;
600190
+ });
600191
+ if (match) return { ok: true, chatId: match.chatId };
600192
+ const knownList = this.formatTelegramSendTargetList(knownGroups, 8);
600193
+ return {
600194
+ ok: false,
600195
+ error: knownList ? `Private-user telegram_send_file target must be this DM or a known shared group for this sender. Known shared groups:
600196
+ ${knownList}` : "Private-user telegram_send_file target must be this DM or a known shared group for this sender. No shared group is currently known."
600197
+ };
600198
+ }
599969
600199
  if (rawTarget !== void 0 && String(rawTarget).trim() && String(rawTarget).trim() !== String(currentChatId)) {
599970
600200
  return { ok: false, error: "Public/group telegram_send_file cannot target another chat. It may only send to the current chat." };
599971
600201
  }
@@ -604371,7 +604601,7 @@ __export(graphical_sudo_exports, {
604371
604601
  detectSudoHelper: () => detectSudoHelper,
604372
604602
  runGraphicalSudo: () => runGraphicalSudo
604373
604603
  });
604374
- import { spawn as spawn28 } from "node:child_process";
604604
+ import { spawn as spawn27 } from "node:child_process";
604375
604605
  import { existsSync as existsSync115, mkdirSync as mkdirSync67, writeFileSync as writeFileSync62, chmodSync as chmodSync2 } from "node:fs";
604376
604606
  import { join as join129 } from "node:path";
604377
604607
  import { tmpdir as tmpdir21 } from "node:os";
@@ -604441,7 +604671,7 @@ async function runGraphicalSudo(opts) {
604441
604671
  args = ["/bin/bash", opts.scriptPath, ...opts.args ?? []];
604442
604672
  }
604443
604673
  return new Promise((resolve48, reject) => {
604444
- const child = spawn28(cmd, args, {
604674
+ const child = spawn27(cmd, args, {
604445
604675
  env: { ...process.env, ...opts.env || {}, ...extraEnv },
604446
604676
  stdio: ["ignore", "pipe", "pipe"]
604447
604677
  });
@@ -616875,7 +617105,7 @@ var init_profiles = __esm({
616875
617105
  });
616876
617106
 
616877
617107
  // packages/cli/src/docker.ts
616878
- import { execSync as execSync56, spawn as spawn29 } from "node:child_process";
617108
+ import { execSync as execSync56, spawn as spawn28 } from "node:child_process";
616879
617109
  import { existsSync as existsSync119, mkdirSync as mkdirSync70, writeFileSync as writeFileSync65 } from "node:fs";
616880
617110
  import { join as join133, resolve as resolve42, dirname as dirname36 } from "node:path";
616881
617111
  import { homedir as homedir44 } from "node:os";
@@ -617156,7 +617386,7 @@ function runInContainer(opts) {
617156
617386
  if (opts.maxTurns) omniusArgs.push("--max-turns", String(opts.maxTurns));
617157
617387
  if (opts.timeoutS) omniusArgs.push("--timeout", String(opts.timeoutS));
617158
617388
  args.push(...omniusArgs);
617159
- return spawn29("docker", args, {
617389
+ return spawn28("docker", args, {
617160
617390
  stdio: ["ignore", "pipe", "pipe"]
617161
617391
  });
617162
617392
  }
@@ -617359,7 +617589,7 @@ import { createRequire as createRequire7 } from "node:module";
617359
617589
  import { fileURLToPath as fileURLToPath17 } from "node:url";
617360
617590
  import { dirname as dirname37, join as join135, resolve as resolve43 } from "node:path";
617361
617591
  import { homedir as homedir45 } from "node:os";
617362
- import { spawn as spawn30, execSync as execSync57 } from "node:child_process";
617592
+ import { spawn as spawn29, execSync as execSync57 } from "node:child_process";
617363
617593
  import { mkdirSync as mkdirSync71, writeFileSync as writeFileSync66, readFileSync as readFileSync98, readdirSync as readdirSync41, existsSync as existsSync120, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync24 } from "node:fs";
617364
617594
  import { randomBytes as randomBytes23, randomUUID as randomUUID16 } from "node:crypto";
617365
617595
  import { createHash as createHash23 } from "node:crypto";
@@ -619632,7 +619862,7 @@ ${task}` : task;
619632
619862
  runEnv["OMNIUS_RUN_SCOPE"] = req2._authScope || "admin";
619633
619863
  runEnv["OLLAMA_HOST"] = currentCfg.backendUrl || process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
619634
619864
  if (currentCfg.apiKey) runEnv["OMNIUS_API_KEY_INHERIT"] = currentCfg.apiKey;
619635
- const child = spawn30(process.execPath, [omniusBin, ...args], {
619865
+ const child = spawn29(process.execPath, [omniusBin, ...args], {
619636
619866
  cwd: resolve43(process.cwd()),
619637
619867
  env: runEnv,
619638
619868
  stdio: ["ignore", "pipe", "pipe"]
@@ -619961,7 +620191,7 @@ async function handleV1Update(req2, res, requestId) {
619961
620191
  cleanEnv.PATH = pathParts.join(":");
619962
620192
  let child;
619963
620193
  if (isWin2) {
619964
- child = spawn30(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
620194
+ child = spawn29(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
619965
620195
  detached: true,
619966
620196
  stdio: ["ignore", logFd, logFd],
619967
620197
  windowsHide: true,
@@ -619983,13 +620213,13 @@ async function handleV1Update(req2, res, requestId) {
619983
620213
  }
619984
620214
  }
619985
620215
  if (npmCli) {
619986
- child = spawn30(nodeBin, [npmCli, "install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
620216
+ child = spawn29(nodeBin, [npmCli, "install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
619987
620217
  detached: true,
619988
620218
  stdio: ["ignore", logFd, logFd],
619989
620219
  env: cleanEnv
619990
620220
  });
619991
620221
  } else {
619992
- child = spawn30(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
620222
+ child = spawn29(npmBin, ["install", "-g", pkgSpec, "--no-audit", "--no-fund", "--no-progress"], {
619993
620223
  detached: true,
619994
620224
  stdio: ["ignore", logFd, logFd],
619995
620225
  env: cleanEnv
@@ -620000,7 +620230,7 @@ async function handleV1Update(req2, res, requestId) {
620000
620230
  const installPid = child.pid ?? 0;
620001
620231
  if (installPid > 0 && !isWin2) {
620002
620232
  try {
620003
- const follower = spawn30("bash", ["-c", `while kill -0 ${installPid} 2>/dev/null; do sleep 1; done; echo "__EXIT_CODE=0" >> "${logPath3}"`], {
620233
+ const follower = spawn29("bash", ["-c", `while kill -0 ${installPid} 2>/dev/null; do sleep 1; done; echo "__EXIT_CODE=0" >> "${logPath3}"`], {
620004
620234
  detached: true,
620005
620235
  stdio: "ignore"
620006
620236
  });
@@ -620023,7 +620253,7 @@ async function handleV1Update(req2, res, requestId) {
620023
620253
  hasSystemdUnit ? `systemctl --user restart omnius-daemon.service >/dev/null 2>&1 || true` : `${JSON.stringify(omniusAbs)} serve --quiet --daemon >/dev/null 2>&1 & disown`,
620024
620254
  `kill -TERM ${process.pid} >/dev/null 2>&1 || true`
620025
620255
  ].join("; ");
620026
- const relauncher = spawn30("bash", ["-c", relaunchScript], {
620256
+ const relauncher = spawn29("bash", ["-c", relaunchScript], {
620027
620257
  detached: true,
620028
620258
  stdio: "ignore",
620029
620259
  env: cleanEnv
@@ -620245,7 +620475,7 @@ async function handleV1Run(req2, res) {
620245
620475
  });
620246
620476
  job.sandbox = "container";
620247
620477
  } else {
620248
- child = spawn30(process.execPath, [omniusBin, ...args], {
620478
+ child = spawn29(process.execPath, [omniusBin, ...args], {
620249
620479
  cwd: cwd4,
620250
620480
  env: runEnv,
620251
620481
  stdio: ["ignore", "pipe", "pipe"],
@@ -622224,7 +622454,7 @@ ${historyLines}
622224
622454
  }
622225
622455
  runEnv["OLLAMA_HOST"] = currentCfg.backendUrl || process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
622226
622456
  if (currentCfg.apiKey) runEnv["OMNIUS_API_KEY_INHERIT"] = currentCfg.apiKey;
622227
- const child = spawn30(process.execPath, [omniusBin, ...args], {
622457
+ const child = spawn29(process.execPath, [omniusBin, ...args], {
622228
622458
  cwd: cwdPath,
622229
622459
  env: runEnv,
622230
622460
  stdio: ["ignore", "pipe", "pipe"],
@@ -633279,7 +633509,7 @@ __export(run_exports, {
633279
633509
  statusCommand: () => statusCommand
633280
633510
  });
633281
633511
  import { resolve as resolve45 } from "node:path";
633282
- import { spawn as spawn31 } from "node:child_process";
633512
+ import { spawn as spawn30 } from "node:child_process";
633283
633513
  import { mkdirSync as mkdirSync74, writeFileSync as writeFileSync69, readFileSync as readFileSync101, readdirSync as readdirSync43, existsSync as existsSync122 } from "node:fs";
633284
633514
  import { randomBytes as randomBytes24 } from "node:crypto";
633285
633515
  import { join as join138 } from "node:path";
@@ -633392,7 +633622,7 @@ async function runBackground(task, config, opts) {
633392
633622
  const omniusBin = process.argv[1] || "omnius";
633393
633623
  const args = [task, "--json"];
633394
633624
  if (config.model) args.push("--model", config.model);
633395
- const child = spawn31(process.execPath, [omniusBin, ...args], {
633625
+ const child = spawn30(process.execPath, [omniusBin, ...args], {
633396
633626
  cwd: repoRoot,
633397
633627
  env: { ...process.env, OMNIUS_JOB_ID: id },
633398
633628
  stdio: ["ignore", "pipe", "pipe"],
@@ -634580,9 +634810,9 @@ async function main() {
634580
634810
  const mode = process.argv[process.argv.indexOf("--self-test") + 1] || "crossmodal";
634581
634811
  if (mode === "crossmodal") {
634582
634812
  process.stdout.write("Running crossmodal smoke tests...\n");
634583
- const { spawn: spawn32 } = await import("node:child_process");
634813
+ const { spawn: spawn31 } = await import("node:child_process");
634584
634814
  const run = (file) => new Promise((resolve48, reject) => {
634585
- const p2 = spawn32(process.execPath, [file], { stdio: ["ignore", "pipe", "pipe"] });
634815
+ const p2 = spawn31(process.execPath, [file], { stdio: ["ignore", "pipe", "pipe"] });
634586
634816
  p2.stdout.on("data", (d2) => process.stdout.write(d2));
634587
634817
  p2.stderr.on("data", (d2) => process.stdout.write(d2));
634588
634818
  onChildExit(p2, (code8) => code8 === 0 ? resolve48() : reject(new Error(`${file} exited ${code8}`)));
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.16",
9
+ "version": "1.0.18",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
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",