@automagik/omni 2.260303.3 → 2.260309.1

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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Agents Commands
3
+ *
4
+ * omni agents list [--provider <p>] [--inactive-only] [--limit <n>]
5
+ * omni agents get <id>
6
+ * omni agents create --name <name> --provider <provider> [--agent-provider <id>] [--model <model>] [--type <type>]
7
+ * omni agents delete <id>
8
+ */
9
+ import { Command } from 'commander';
10
+ export declare function createAgentsCommand(): Command;
11
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,mBAAmB,IAAI,OAAO,CAkI7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmapC,wBAAgB,iBAAiB,IAAI,OAAO,CA0E3C"}
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuapC,wBAAgB,iBAAiB,IAAI,OAAO,CA2E3C"}
package/dist/index.js CHANGED
@@ -27469,6 +27469,42 @@ function createOmniClient(config) {
27469
27469
  throw OmniApiError.from(await resp.json(), resp.status);
27470
27470
  }
27471
27471
  },
27472
+ agents: {
27473
+ async list(params) {
27474
+ const { data, error, response } = await client.GET("/agents", {
27475
+ params: { query: params }
27476
+ });
27477
+ throwIfError(response, error);
27478
+ return {
27479
+ items: data?.items ?? [],
27480
+ meta: data?.meta ?? { hasMore: false, cursor: null }
27481
+ };
27482
+ },
27483
+ async get(id) {
27484
+ const { data, error, response } = await client.GET("/agents/{id}", {
27485
+ params: { path: { id } }
27486
+ });
27487
+ throwIfError(response, error);
27488
+ if (!data?.data)
27489
+ throw new OmniApiError("Agent not found", "NOT_FOUND", undefined, 404);
27490
+ return data.data;
27491
+ },
27492
+ async create(body) {
27493
+ const { data, error, response } = await client.POST("/agents", {
27494
+ body
27495
+ });
27496
+ throwIfError(response, error);
27497
+ if (!data?.data)
27498
+ throw new OmniApiError("Failed to create agent", "CREATE_FAILED", undefined, response.status);
27499
+ return data.data;
27500
+ },
27501
+ async delete(id) {
27502
+ const { error, response } = await client.DELETE("/agents/{id}", {
27503
+ params: { path: { id } }
27504
+ });
27505
+ throwIfError(response, error);
27506
+ }
27507
+ },
27472
27508
  system: {
27473
27509
  async health() {
27474
27510
  const healthClient = createClient({ baseUrl: `${baseUrl}/api/v2` });
@@ -27673,7 +27709,7 @@ import { fileURLToPath } from "url";
27673
27709
  // package.json
27674
27710
  var package_default = {
27675
27711
  name: "@automagik/omni",
27676
- version: "2.260303.3",
27712
+ version: "2.260309.1",
27677
27713
  description: "LLM-optimized CLI for Omni v2",
27678
27714
  type: "module",
27679
27715
  bin: {
@@ -28389,6 +28425,90 @@ function createRoutesCommand() {
28389
28425
  return routes;
28390
28426
  }
28391
28427
 
28428
+ // src/commands/agents.ts
28429
+ var VALID_PROVIDERS = ["claude", "agno", "openai", "gemini", "custom", "omni-internal"];
28430
+ var VALID_TYPES = ["assistant", "workflow", "team", "tool"];
28431
+ function createAgentsCommand() {
28432
+ const agents = new Command("agents").description("Manage AI agent entities");
28433
+ agents.command("list").description("List all agents").option("--provider <provider>", `Filter by provider (${VALID_PROVIDERS.join(", ")})`).option("--inactive-only", "Show only inactive agents").option("--limit <n>", "Max results", (v) => {
28434
+ const n = Number.parseInt(v, 10);
28435
+ if (!Number.isFinite(n) || n < 1)
28436
+ throw new Error(`Invalid limit: ${v}`);
28437
+ return n;
28438
+ }, 50).action(async (options) => {
28439
+ const client = getClient();
28440
+ if (options.provider && !VALID_PROVIDERS.includes(options.provider)) {
28441
+ error(`Invalid provider: ${options.provider}. Valid: ${VALID_PROVIDERS.join(", ")}`);
28442
+ }
28443
+ try {
28444
+ const { items } = await client.agents.list({
28445
+ provider: options.provider,
28446
+ isActive: options.inactiveOnly ? false : undefined,
28447
+ limit: options.limit
28448
+ });
28449
+ const rows = items.map((a) => ({
28450
+ id: a.id,
28451
+ name: a.name,
28452
+ provider: a.provider,
28453
+ type: a.agentType,
28454
+ model: a.model ?? "-",
28455
+ active: a.isActive ? "yes" : "no"
28456
+ }));
28457
+ list(rows, { emptyMessage: "No agents found." });
28458
+ } catch (err) {
28459
+ const message = err instanceof Error ? err.message : "Unknown error";
28460
+ error(`Failed to list agents: ${message}`);
28461
+ }
28462
+ });
28463
+ agents.command("get <id>").description("Get agent details").action(async (id) => {
28464
+ const client = getClient();
28465
+ try {
28466
+ const agent = await client.agents.get(id);
28467
+ data(agent);
28468
+ } catch (err) {
28469
+ const message = err instanceof Error ? err.message : "Unknown error";
28470
+ error(`Failed to get agent: ${message}`, undefined, 3);
28471
+ }
28472
+ });
28473
+ agents.command("create").description("Create a new agent").requiredOption("--name <name>", "Agent name").requiredOption("--provider <provider>", `AI provider (${VALID_PROVIDERS.join(", ")})`).option("--model <model>", "Model identifier (e.g. claude-sonnet-4-6)").option("--type <type>", `Agent type (${VALID_TYPES.join(", ")})`, "assistant").option("--agent-provider <agentProviderId>", "Link to an agent provider configuration").action(async (options) => {
28474
+ const client = getClient();
28475
+ if (!VALID_PROVIDERS.includes(options.provider)) {
28476
+ error(`Invalid provider: ${options.provider}. Valid: ${VALID_PROVIDERS.join(", ")}`);
28477
+ }
28478
+ if (options.type && !VALID_TYPES.includes(options.type)) {
28479
+ error(`Invalid type: ${options.type}. Valid: ${VALID_TYPES.join(", ")}`);
28480
+ }
28481
+ try {
28482
+ const agent = await client.agents.create({
28483
+ name: options.name,
28484
+ provider: options.provider,
28485
+ model: options.model,
28486
+ agentType: options.type ?? "assistant",
28487
+ agentProviderId: options.agentProvider,
28488
+ capabilities: [],
28489
+ isInternal: false,
28490
+ isActive: true
28491
+ });
28492
+ success(`Agent created: ${agent.id}`);
28493
+ data(agent);
28494
+ } catch (err) {
28495
+ const message = err instanceof Error ? err.message : "Unknown error";
28496
+ error(`Failed to create agent: ${message}`);
28497
+ }
28498
+ });
28499
+ agents.command("delete <id>").description("Delete an agent (soft-delete, sets inactive)").action(async (id) => {
28500
+ const client = getClient();
28501
+ try {
28502
+ await client.agents.delete(id);
28503
+ success(`Agent ${id} deleted.`);
28504
+ } catch (err) {
28505
+ const message = err instanceof Error ? err.message : "Unknown error";
28506
+ error(`Failed to delete agent: ${message}`, undefined, 3);
28507
+ }
28508
+ });
28509
+ return agents;
28510
+ }
28511
+
28392
28512
  // src/commands/auth.ts
28393
28513
  init_config();
28394
28514
 
@@ -41414,10 +41534,282 @@ class InMemorySessionActivityStore {
41414
41534
  this.activities.clear();
41415
41535
  }
41416
41536
  }
41537
+ // ../core/src/providers/types.ts
41538
+ class ProviderError extends Error {
41539
+ code;
41540
+ statusCode;
41541
+ details;
41542
+ constructor(message2, code, statusCode, details) {
41543
+ super(message2);
41544
+ this.code = code;
41545
+ this.statusCode = statusCode;
41546
+ this.details = details;
41547
+ this.name = "ProviderError";
41548
+ }
41549
+ }
41417
41550
  // ../core/src/providers/claude-code-client.ts
41418
41551
  var log6 = createLogger("provider:claude-code");
41419
41552
  // ../core/src/providers/genie-client.ts
41553
+ import { execFile } from "child_process";
41554
+ import { mkdir, open, readFile, rename, stat, unlink, writeFile } from "fs/promises";
41555
+ import { homedir as homedir3 } from "os";
41556
+ import { join as join5 } from "path";
41420
41557
  var log7 = createLogger("providers:genie-client");
41558
+ function sanitize(value) {
41559
+ return value.replace(/[^a-zA-Z0-9_-]/g, "");
41560
+ }
41561
+ function interpolateTemplate(template, vars) {
41562
+ return template.replace(/\{(\w+)\}/g, (_match, key) => {
41563
+ const value = vars[key];
41564
+ return value ?? "";
41565
+ });
41566
+ }
41567
+ function extractTemplateVars(request) {
41568
+ return {
41569
+ thread_id: request.chat?.threadId,
41570
+ chat_id: request.chat?.id,
41571
+ sender_id: request.userId,
41572
+ channel: request.platform?.channel,
41573
+ instance_id: request.platform?.instanceId
41574
+ };
41575
+ }
41576
+
41577
+ class GenieClient {
41578
+ teamNameTemplate;
41579
+ agentNameTemplate;
41580
+ targetAgentTemplate;
41581
+ hasTemplates;
41582
+ autoSpawn;
41583
+ autoSpawnDir;
41584
+ knownTeams = new Set;
41585
+ pendingTeams = new Set;
41586
+ constructor(config2) {
41587
+ this.teamNameTemplate = config2.teamName ?? "genie";
41588
+ this.agentNameTemplate = config2.agentName;
41589
+ this.targetAgentTemplate = config2.targetAgent;
41590
+ this.autoSpawn = config2.autoSpawn ?? true;
41591
+ this.autoSpawnDir = config2.autoSpawnDir ?? join5(homedir3(), "workspace");
41592
+ this.hasTemplates = /\{\w+\}/.test(this.teamNameTemplate) || /\{\w+\}/.test(this.agentNameTemplate) || /\{\w+\}/.test(this.targetAgentTemplate);
41593
+ }
41594
+ resolveConfig(request) {
41595
+ let teamName;
41596
+ let agentName;
41597
+ let targetAgent;
41598
+ if (this.hasTemplates) {
41599
+ const vars = extractTemplateVars(request);
41600
+ teamName = sanitize(interpolateTemplate(this.teamNameTemplate, vars));
41601
+ agentName = sanitize(interpolateTemplate(this.agentNameTemplate, vars));
41602
+ targetAgent = sanitize(interpolateTemplate(this.targetAgentTemplate, vars));
41603
+ } else {
41604
+ teamName = sanitize(this.teamNameTemplate);
41605
+ agentName = sanitize(this.agentNameTemplate);
41606
+ targetAgent = sanitize(this.targetAgentTemplate);
41607
+ }
41608
+ if (!teamName) {
41609
+ throw new ProviderError(`Team name resolved to empty string (template: "${this.teamNameTemplate}"). Ensure the template variable (e.g. {thread_id}) is populated in the request.`, "INVALID_RESPONSE");
41610
+ }
41611
+ if (!agentName) {
41612
+ throw new ProviderError(`Agent name resolved to empty string (template: "${this.agentNameTemplate}"). Ensure the template variable is populated in the request.`, "INVALID_RESPONSE");
41613
+ }
41614
+ if (!targetAgent) {
41615
+ throw new ProviderError(`Target agent resolved to empty string (template: "${this.targetAgentTemplate}"). Ensure the template variable is populated in the request.`, "INVALID_RESPONSE");
41616
+ }
41617
+ const inboxDir = join5(homedir3(), ".claude", "teams", teamName, "inboxes");
41618
+ const inboxPath = join5(inboxDir, `${targetAgent}.json`);
41619
+ return { teamName, agentName, targetAgent, inboxDir, inboxPath };
41620
+ }
41621
+ ensureTeamExists(teamName) {
41622
+ if (!this.autoSpawn)
41623
+ return;
41624
+ if (this.knownTeams.has(teamName))
41625
+ return;
41626
+ if (this.pendingTeams.has(teamName))
41627
+ return;
41628
+ this.pendingTeams.add(teamName);
41629
+ const configPath = join5(homedir3(), ".claude", "teams", teamName, "config.json");
41630
+ stat(configPath).then(() => {
41631
+ this.knownTeams.add(teamName);
41632
+ this.pendingTeams.delete(teamName);
41633
+ }).catch(() => {
41634
+ const args = ["team", "ensure", teamName, "--dir", this.autoSpawnDir];
41635
+ log7.info("Auto-spawning team-lead", { teamName, args });
41636
+ execFile("genie", args, (error2) => {
41637
+ this.pendingTeams.delete(teamName);
41638
+ if (error2) {
41639
+ log7.warn("Auto-spawn failed (genie CLI may not be installed)", {
41640
+ teamName,
41641
+ error: error2.message
41642
+ });
41643
+ } else {
41644
+ log7.info("Auto-spawn succeeded", { teamName });
41645
+ this.knownTeams.add(teamName);
41646
+ }
41647
+ });
41648
+ });
41649
+ }
41650
+ buildMetadataHeader(request) {
41651
+ const tags = [];
41652
+ if (request.platform) {
41653
+ tags.push(`channel:${request.platform.channel}`);
41654
+ tags.push(`instance:${request.platform.instanceId}`);
41655
+ }
41656
+ if (request.chat?.id)
41657
+ tags.push(`chat:${request.chat.id}`);
41658
+ if (request.chat?.threadId)
41659
+ tags.push(`thread:${request.chat.threadId}`);
41660
+ if (request.messageId)
41661
+ tags.push(`msg:${request.messageId}`);
41662
+ if (request.sender?.displayName)
41663
+ tags.push(`from:${request.sender.displayName}`);
41664
+ if (request.chat?.type)
41665
+ tags.push(`type:${request.chat.type}`);
41666
+ if (request.replyToMessageId)
41667
+ tags.push(`replyTo:${request.replyToMessageId}`);
41668
+ return tags.length > 0 ? `[${tags.join(" ")}]` : "";
41669
+ }
41670
+ async acquireLock(lockPath) {
41671
+ try {
41672
+ return await open(lockPath, "wx");
41673
+ } catch {
41674
+ await new Promise((r) => setTimeout(r, 100));
41675
+ }
41676
+ try {
41677
+ return await open(lockPath, "wx");
41678
+ } catch {}
41679
+ try {
41680
+ const lockStat = await stat(lockPath);
41681
+ const ageMs = Date.now() - lockStat.mtimeMs;
41682
+ if (ageMs > 30000) {
41683
+ log7.warn("Removing stale lock file", { lockPath, ageMs });
41684
+ await unlink(lockPath);
41685
+ return await open(lockPath, "wx");
41686
+ }
41687
+ log7.error("Lock file is fresh, another process is active", { lockPath, ageMs });
41688
+ } catch (error2) {
41689
+ if (error2 instanceof ProviderError)
41690
+ throw error2;
41691
+ log7.error("Could not recover from lock contention", { lockPath, error: error2 });
41692
+ }
41693
+ throw new ProviderError("Failed to acquire lock on team inbox, message not delivered", "SERVER_ERROR");
41694
+ }
41695
+ async run(request) {
41696
+ const startMs = Date.now();
41697
+ const { teamName, agentName, targetAgent, inboxDir, inboxPath } = this.resolveConfig(request);
41698
+ const header2 = this.buildMetadataHeader(request);
41699
+ const replyInstruction = `\u26A1 REPLY NOW via SendMessage to "${agentName}". Include the routing header from the first line of this message in your reply. Do not proceed with other tasks until you respond.`;
41700
+ const text = header2 ? `${header2}
41701
+ ${request.message}
41702
+ ${replyInstruction}` : `${request.message}
41703
+ ${replyInstruction}`;
41704
+ const summary = request.message.length > 50 ? `${request.message.substring(0, 50)}...` : request.message;
41705
+ const inboxMessage = {
41706
+ from: agentName,
41707
+ text,
41708
+ summary,
41709
+ timestamp: new Date().toISOString(),
41710
+ read: false
41711
+ };
41712
+ await mkdir(inboxDir, { recursive: true });
41713
+ const lockPath = `${inboxPath}.lock`;
41714
+ const lockFd = await this.acquireLock(lockPath);
41715
+ try {
41716
+ let inbox = [];
41717
+ try {
41718
+ const data2 = await readFile(inboxPath, "utf-8");
41719
+ inbox = JSON.parse(data2);
41720
+ if (!Array.isArray(inbox))
41721
+ inbox = [];
41722
+ } catch {
41723
+ inbox = [];
41724
+ }
41725
+ inbox.push(inboxMessage);
41726
+ const tmpPath = `${inboxPath}.tmp`;
41727
+ await writeFile(tmpPath, JSON.stringify(inbox, null, 2), "utf-8");
41728
+ await rename(tmpPath, inboxPath);
41729
+ } finally {
41730
+ await lockFd.close();
41731
+ try {
41732
+ await unlink(lockPath);
41733
+ } catch {}
41734
+ }
41735
+ this.ensureTeamExists(teamName);
41736
+ const durationMs = Date.now() - startMs;
41737
+ log7.info("Message delivered to team inbox", {
41738
+ agent: agentName,
41739
+ team: teamName,
41740
+ target: targetAgent,
41741
+ messageLength: text.length,
41742
+ durationMs,
41743
+ hasTemplates: this.hasTemplates
41744
+ });
41745
+ return {
41746
+ content: "",
41747
+ runId: `genie-${agentName}-${Date.now()}`,
41748
+ sessionId: request.sessionId ?? "",
41749
+ status: "completed",
41750
+ metrics: {
41751
+ inputTokens: 0,
41752
+ outputTokens: 0,
41753
+ durationMs
41754
+ }
41755
+ };
41756
+ }
41757
+ async* stream(_request) {
41758
+ throw new ProviderError("Genie client does not support streaming", "STREAM_ERROR");
41759
+ }
41760
+ async checkHealth() {
41761
+ const startMs = Date.now();
41762
+ try {
41763
+ if (this.hasTemplates) {
41764
+ const teamsRoot = join5(homedir3(), ".claude", "teams");
41765
+ try {
41766
+ await stat(teamsRoot);
41767
+ } catch {
41768
+ return {
41769
+ healthy: false,
41770
+ latencyMs: Date.now() - startMs,
41771
+ error: `Teams root directory does not exist: ${teamsRoot}`
41772
+ };
41773
+ }
41774
+ return {
41775
+ healthy: true,
41776
+ latencyMs: Date.now() - startMs
41777
+ };
41778
+ }
41779
+ const teamName = sanitize(this.teamNameTemplate);
41780
+ const teamDir = join5(homedir3(), ".claude", "teams", teamName);
41781
+ const inboxDir = join5(teamDir, "inboxes");
41782
+ try {
41783
+ await stat(teamDir);
41784
+ } catch {
41785
+ return {
41786
+ healthy: false,
41787
+ latencyMs: Date.now() - startMs,
41788
+ error: `Team directory does not exist: ${teamDir}`
41789
+ };
41790
+ }
41791
+ try {
41792
+ await stat(inboxDir);
41793
+ } catch {
41794
+ return {
41795
+ healthy: false,
41796
+ latencyMs: Date.now() - startMs,
41797
+ error: `Inbox directory does not exist: ${inboxDir}`
41798
+ };
41799
+ }
41800
+ return {
41801
+ healthy: true,
41802
+ latencyMs: Date.now() - startMs
41803
+ };
41804
+ } catch (error2) {
41805
+ return {
41806
+ healthy: false,
41807
+ latencyMs: Date.now() - startMs,
41808
+ error: error2 instanceof Error ? error2.message : String(error2)
41809
+ };
41810
+ }
41811
+ }
41812
+ }
41421
41813
  // ../core/src/providers/agno-provider.ts
41422
41814
  var log8 = createLogger("provider:agno");
41423
41815
  // ../core/src/providers/claude-code-provider.ts
@@ -42229,7 +42621,7 @@ var log18 = createLogger("hooks:executor");
42229
42621
  import { execFileSync, execSync } from "child_process";
42230
42622
  import * as nodeCrypto2 from "crypto";
42231
42623
  import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
42232
- import { homedir as homedir3 } from "os";
42624
+ import { homedir as homedir4 } from "os";
42233
42625
  import { dirname as dirname4, resolve as resolve2 } from "path";
42234
42626
  import { createInterface as createInterface2 } from "readline";
42235
42627
  init_config();
@@ -42455,7 +42847,7 @@ async function pairDevice(gatewayUrl, gatewayToken, keypair, spinner) {
42455
42847
  ws.close(1000, "pairing complete");
42456
42848
  }
42457
42849
  }
42458
- var OPENCLAW_CONFIG_PATH = resolve2(homedir3(), ".openclaw", "openclaw.json");
42850
+ var OPENCLAW_CONFIG_PATH = resolve2(homedir4(), ".openclaw", "openclaw.json");
42459
42851
  var PLUGIN_MARKER = "plugin-openclaw/omni.ts";
42460
42852
  function readOpenClawConfig(configPath) {
42461
42853
  if (!existsSync5(configPath))
@@ -43056,7 +43448,7 @@ ${formatExamples(examples)}`);
43056
43448
  }
43057
43449
 
43058
43450
  // src/commands/restart.ts
43059
- import { join as join5 } from "path";
43451
+ import { join as join6 } from "path";
43060
43452
  init_config();
43061
43453
  var RESTART_HEALTH_TIMEOUT_MS = 1e4;
43062
43454
  function buildApiRuntimeEnv2() {
@@ -43066,9 +43458,9 @@ function buildApiRuntimeEnv2() {
43066
43458
  API_PORT: String(serverConfig.port),
43067
43459
  DATABASE_URL: serverConfig.databaseUrl,
43068
43460
  OMNI_API_KEY: config2.apiKey ?? "",
43069
- MEDIA_STORAGE_PATH: join5(serverConfig.dataDir, "media"),
43461
+ MEDIA_STORAGE_PATH: join6(serverConfig.dataDir, "media"),
43070
43462
  PGSERVE_EMBEDDED: "true",
43071
- PGSERVE_DATA: join5(serverConfig.dataDir, "pgserve"),
43463
+ PGSERVE_DATA: join6(serverConfig.dataDir, "pgserve"),
43072
43464
  NATS_URL: "nats://localhost:4222",
43073
43465
  NODE_ENV: serverConfig.nodeEnv,
43074
43466
  LOG_LEVEL: serverConfig.logLevel
@@ -43238,7 +43630,8 @@ var messageSenders = {
43238
43630
  instanceId,
43239
43631
  to,
43240
43632
  text,
43241
- replyTo: options3.replyTo
43633
+ replyTo: options3.replyTo,
43634
+ threadId: options3.threadId
43242
43635
  });
43243
43636
  success("Message sent", result);
43244
43637
  },
@@ -43260,7 +43653,8 @@ var messageSenders = {
43260
43653
  base64,
43261
43654
  filename,
43262
43655
  caption: options3.caption,
43263
- voiceNote: options3.voice
43656
+ voiceNote: options3.voice,
43657
+ threadId: options3.threadId
43264
43658
  });
43265
43659
  success("Media sent", result);
43266
43660
  },
@@ -43478,7 +43872,8 @@ function buildGroupedSendHelp() {
43478
43872
  ];
43479
43873
  const textOptions = [
43480
43874
  { flags: "--text <text>", description: "Message content" },
43481
- { flags: "--reply-to <id>", description: "Reply to specific message" }
43875
+ { flags: "--reply-to <id>", description: "Reply to specific message" },
43876
+ { flags: "--thread-id <id>", description: "Thread/topic ID (e.g. Telegram forum topic)" }
43482
43877
  ];
43483
43878
  const mediaOptions = [
43484
43879
  { flags: "--media <path>", description: "Image, video, audio, or document" },
@@ -43569,7 +43964,7 @@ function createSendCommand() {
43569
43964
  send.configureHelp({
43570
43965
  formatHelp: () => buildGroupedSendHelp()
43571
43966
  });
43572
- send.description("Send a message to a recipient").option("--instance <id>", "Instance ID (uses default if not specified)").option("--to <recipient>", "Recipient: WA JID, phone number, or Omni chat/person UUID").option("--text <text>", "Send text message").option("--reply-to <id>", "Reply to a message ID").option("--media <path>", "Send media file (image, audio, video, document)").option("--caption <text>", "Caption for media").option("--voice", "Send audio as voice note").option("--reaction <emoji>", "Send reaction emoji").option("--message <id>", "Message ID to react to").option("--sticker <url>", "Send sticker (URL or base64)").option("--contact", "Send contact card").option("--name <name>", "Contact name").option("--phone <phone>", "Contact phone number").option("--email <email>", "Contact email").option("--location", "Send location").option("--lat <latitude>", "Latitude", Number.parseFloat).option("--lng <longitude>", "Longitude", Number.parseFloat).option("--address <address>", "Location address").option("--poll <question>", "Send poll with question").option("--options <answers>", "Poll options (comma-separated)").option("--multi-select", "Allow multiple selections").option("--duration <hours>", "Poll duration in hours", Number.parseInt).option("--embed", "Send embed message").option("--title <title>", "Embed title").option("--description <desc>", "Embed description").option("--color <color>", "Embed color (hex)", Number.parseInt).option("--url <url>", "Embed URL").option("--presence <type>", "Send presence indicator (typing, recording, paused)").option("--tts <text>", "Send TTS voice note (text-to-speech)").option("--voice-id <id>", "ElevenLabs voice ID for TTS").option("--presence-delay <ms>", "Recording presence duration in ms", Number.parseInt).option("--forward", "Forward a message to another chat").option("--from-chat <chatId>", "Source chat ID for forwarding").action(async (options3) => {
43967
+ send.description("Send a message to a recipient").option("--instance <id>", "Instance ID (uses default if not specified)").option("--to <recipient>", "Recipient: WA JID, phone number, or Omni chat/person UUID").option("--text <text>", "Send text message").option("--reply-to <id>", "Reply to a message ID").option("--thread-id <id>", "Thread/topic ID (Telegram forum topic, etc.)").option("--media <path>", "Send media file (image, audio, video, document)").option("--caption <text>", "Caption for media").option("--voice", "Send audio as voice note").option("--reaction <emoji>", "Send reaction emoji").option("--message <id>", "Message ID to react to").option("--sticker <url>", "Send sticker (URL or base64)").option("--contact", "Send contact card").option("--name <name>", "Contact name").option("--phone <phone>", "Contact phone number").option("--email <email>", "Contact email").option("--location", "Send location").option("--lat <latitude>", "Latitude", Number.parseFloat).option("--lng <longitude>", "Longitude", Number.parseFloat).option("--address <address>", "Location address").option("--poll <question>", "Send poll with question").option("--options <answers>", "Poll options (comma-separated)").option("--multi-select", "Allow multiple selections").option("--duration <hours>", "Poll duration in hours", Number.parseInt).option("--embed", "Send embed message").option("--title <title>", "Embed title").option("--description <desc>", "Embed description").option("--color <color>", "Embed color (hex)", Number.parseInt).option("--url <url>", "Embed URL").option("--presence <type>", "Send presence indicator (typing, recording, paused)").option("--tts <text>", "Send TTS voice note (text-to-speech)").option("--voice-id <id>", "ElevenLabs voice ID for TTS").option("--presence-delay <ms>", "Recording presence duration in ms", Number.parseInt).option("--forward", "Forward a message to another chat").option("--from-chat <chatId>", "Source chat ID for forwarding").action(async (options3) => {
43573
43968
  const messageType = getMessageType(options3);
43574
43969
  if (!messageType) {
43575
43970
  error("No message type specified. Use --text, --media, --reaction, --forward, etc.");
@@ -43646,8 +44041,8 @@ function createSettingsCommand() {
43646
44041
 
43647
44042
  // src/commands/start.ts
43648
44043
  import { existsSync as existsSync7, mkdirSync as mkdirSync5 } from "fs";
43649
- import { homedir as homedir4 } from "os";
43650
- import { join as join6 } from "path";
44044
+ import { homedir as homedir5 } from "os";
44045
+ import { join as join7 } from "path";
43651
44046
  init_config();
43652
44047
  var START_HEALTH_TIMEOUT_MS = 1e4;
43653
44048
  function buildApiRuntimeEnv3() {
@@ -43657,10 +44052,10 @@ function buildApiRuntimeEnv3() {
43657
44052
  API_PORT: String(serverConfig.port),
43658
44053
  DATABASE_URL: serverConfig.databaseUrl,
43659
44054
  OMNI_API_KEY: config2.apiKey ?? "",
43660
- MEDIA_STORAGE_PATH: join6(serverConfig.dataDir, "media"),
43661
- OMNI_PACKAGES_DIR: join6(serverConfig.dataDir, "packages"),
44055
+ MEDIA_STORAGE_PATH: join7(serverConfig.dataDir, "media"),
44056
+ OMNI_PACKAGES_DIR: join7(serverConfig.dataDir, "packages"),
43662
44057
  PGSERVE_EMBEDDED: "true",
43663
- PGSERVE_DATA: join6(serverConfig.dataDir, "pgserve"),
44058
+ PGSERVE_DATA: join7(serverConfig.dataDir, "pgserve"),
43664
44059
  NATS_URL: "nats://localhost:4222",
43665
44060
  NODE_ENV: serverConfig.nodeEnv,
43666
44061
  LOG_LEVEL: serverConfig.logLevel
@@ -43684,10 +44079,10 @@ async function runStart() {
43684
44079
  error(`Failed to start ${PM2_PROCESSES.api} (pm2 exit code ${apiCode})`, undefined, 1);
43685
44080
  return;
43686
44081
  }
43687
- const natsPath = join6(homedir4(), ".omni", "nats-server");
44082
+ const natsPath = join7(homedir5(), ".omni", "nats-server");
43688
44083
  if (existsSync7(natsPath)) {
43689
44084
  info(`Starting ${PM2_PROCESSES.nats}...`);
43690
- const natsDataDir = join6(serverConfig.dataDir, "nats");
44085
+ const natsDataDir = join7(serverConfig.dataDir, "nats");
43691
44086
  mkdirSync5(natsDataDir, { recursive: true });
43692
44087
  const natsCode = await runPm2(["start", natsPath, "--name", PM2_PROCESSES.nats, "--", "-js", "-sd", natsDataDir]);
43693
44088
  if (natsCode !== 0) {
@@ -44225,6 +44620,12 @@ var COMMANDS = [
44225
44620
  helpGroup: "Management",
44226
44621
  helpDescription: "Event-driven workflows"
44227
44622
  },
44623
+ {
44624
+ create: createAgentsCommand,
44625
+ category: "core",
44626
+ helpGroup: "Management",
44627
+ helpDescription: "AI agent entity management"
44628
+ },
44228
44629
  {
44229
44630
  create: createProvidersCommand,
44230
44631
  category: "core",