@automagik/omni 2.260407.1 → 2.260409.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"mock-api.d.ts","sourceRoot":"","sources":["../../src/__tests__/mock-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,YAAY,4BAA4B,CAAC;AAgStD,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAID;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC,CA2B3D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAIlC"}
1
+ {"version":3,"file":"mock-api.d.ts","sourceRoot":"","sources":["../../src/__tests__/mock-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,YAAY,4BAA4B,CAAC;AAmdtD,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAID;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC,CA6B3D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAIlC"}
@@ -4,6 +4,7 @@
4
4
  * omni agents list [--provider <p>] [--inactive-only] [--limit <n>]
5
5
  * omni agents get <id>
6
6
  * omni agents create --name <name> --provider <provider> [--agent-provider <id>] [--model <model>] [--type <type>]
7
+ * omni agents update <id> [--name <name>] [--model <model>] [--provider <provider>] [--agent-provider <id>] [--type <type>] [--active|--inactive]
7
8
  * omni agents delete <id>
8
9
  */
9
10
  import { Command } from 'commander';
@@ -1 +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
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0DpC,wBAAgB,mBAAmB,IAAI,OAAO,CA+J7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"done.d.ts","sourceRoot":"","sources":["../../src/commands/done.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2HpC,wBAAgB,iBAAiB,IAAI,OAAO,CA0C3C"}
1
+ {"version":3,"file":"done.d.ts","sourceRoot":"","sources":["../../src/commands/done.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmIpC,wBAAgB,iBAAiB,IAAI,OAAO,CA0C3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/commands/events.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkMpC,wBAAgB,mBAAmB,IAAI,OAAO,CA6L7C"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/commands/events.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkMpC,wBAAgB,mBAAmB,IAAI,OAAO,CA6M7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyCpC,wBAAgB,iBAAiB,IAAI,OAAO,CA4C3C"}
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgFpC,wBAAgB,iBAAiB,IAAI,OAAO,CAsE3C"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Turns Commands — Admin turn management
3
+ *
4
+ * omni turns list [--status open|done|timeout] [--instance <id>] [--chat <id>] [--agent <id>] [--limit N]
5
+ * omni turns get <id>
6
+ * omni turns close <id> [--reason <text>]
7
+ * omni turns close-all --confirm [--reason <text>]
8
+ * omni turns stats
9
+ */
10
+ import { Command } from 'commander';
11
+ export declare function createTurnsCommand(): Command;
12
+ //# sourceMappingURL=turns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turns.d.ts","sourceRoot":"","sources":["../../src/commands/turns.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,kBAAkB,IAAI,OAAO,CAiG5C"}
package/dist/index.js CHANGED
@@ -75939,6 +75939,15 @@ function createOmniClient(config) {
75939
75939
  meta: data?.meta ?? { hasMore: false }
75940
75940
  };
75941
75941
  },
75942
+ async get(id) {
75943
+ const { data, error, response } = await client.GET("/events/{id}", {
75944
+ params: { path: { id } }
75945
+ });
75946
+ throwIfError(response, error);
75947
+ if (!data?.data)
75948
+ throw new OmniApiError("Event not found", "NOT_FOUND", undefined, 404);
75949
+ return data.data;
75950
+ },
75942
75951
  async analytics(params) {
75943
75952
  const { data, error, response } = await client.GET("/events/analytics", {
75944
75953
  params: { query: params }
@@ -76806,16 +76815,82 @@ function createOmniClient(config) {
76806
76815
  }
76807
76816
  },
76808
76817
  turns: {
76809
- async close(body) {
76818
+ async close(body, extraHeaders) {
76810
76819
  const resp = await apiFetch(`${baseUrl}/api/v2/turns/close`, {
76811
76820
  method: "POST",
76812
- headers: { "Content-Type": "application/json" },
76821
+ headers: { "Content-Type": "application/json", ...extraHeaders },
76813
76822
  body: JSON.stringify(body)
76814
76823
  });
76815
76824
  const json = await resp.json();
76816
76825
  if (!resp.ok)
76817
76826
  throw OmniApiError.from(json, resp.status);
76818
76827
  return json?.data ?? {};
76828
+ },
76829
+ async list(params) {
76830
+ const qs = new URLSearchParams;
76831
+ if (params?.status)
76832
+ qs.set("status", params.status);
76833
+ if (params?.instanceId)
76834
+ qs.set("instanceId", params.instanceId);
76835
+ if (params?.chatId)
76836
+ qs.set("chatId", params.chatId);
76837
+ if (params?.agentId)
76838
+ qs.set("agentId", params.agentId);
76839
+ if (params?.limit !== undefined)
76840
+ qs.set("limit", String(params.limit));
76841
+ if (params?.offset !== undefined)
76842
+ qs.set("offset", String(params.offset));
76843
+ const query = qs.toString();
76844
+ const url = `${baseUrl}/api/v2/turns${query ? `?${query}` : ""}`;
76845
+ const resp = await apiFetch(url);
76846
+ const json = await resp.json();
76847
+ if (!resp.ok)
76848
+ throw OmniApiError.from(json, resp.status);
76849
+ return json?.data ?? { items: [], total: 0, limit: 50, offset: 0 };
76850
+ },
76851
+ async get(id) {
76852
+ const resp = await apiFetch(`${baseUrl}/api/v2/turns/${id}`);
76853
+ const json = await resp.json();
76854
+ if (!resp.ok)
76855
+ throw OmniApiError.from(json, resp.status);
76856
+ if (!json?.data)
76857
+ throw new OmniApiError("Turn not found", "NOT_FOUND", undefined, 404);
76858
+ return json.data;
76859
+ },
76860
+ async forceClose(id, reason) {
76861
+ const resp = await apiFetch(`${baseUrl}/api/v2/turns/${id}/close`, {
76862
+ method: "POST",
76863
+ headers: { "Content-Type": "application/json" },
76864
+ body: JSON.stringify({ reason })
76865
+ });
76866
+ const json = await resp.json();
76867
+ if (!resp.ok)
76868
+ throw OmniApiError.from(json, resp.status);
76869
+ if (!json?.data)
76870
+ throw new OmniApiError("Turn not found or already closed", "NOT_FOUND", undefined, 404);
76871
+ return json.data;
76872
+ },
76873
+ async bulkClose(reason) {
76874
+ const resp = await apiFetch(`${baseUrl}/api/v2/turns/close-all`, {
76875
+ method: "POST",
76876
+ headers: { "Content-Type": "application/json" },
76877
+ body: JSON.stringify({ confirm: true, reason })
76878
+ });
76879
+ const json = await resp.json();
76880
+ if (!resp.ok)
76881
+ throw OmniApiError.from(json, resp.status);
76882
+ if (!json?.data)
76883
+ throw new OmniApiError("Bulk close failed", "INTERNAL_ERROR", undefined, 500);
76884
+ return json.data;
76885
+ },
76886
+ async stats() {
76887
+ const resp = await apiFetch(`${baseUrl}/api/v2/turns/stats`);
76888
+ const json = await resp.json();
76889
+ if (!resp.ok)
76890
+ throw OmniApiError.from(json, resp.status);
76891
+ if (!json?.data)
76892
+ throw new OmniApiError("Stats unavailable", "INTERNAL_ERROR", undefined, 500);
76893
+ return json.data;
76819
76894
  }
76820
76895
  },
76821
76896
  agents: {
@@ -76847,6 +76922,16 @@ function createOmniClient(config) {
76847
76922
  throw new OmniApiError("Failed to create agent", "CREATE_FAILED", undefined, response.status);
76848
76923
  return data.data;
76849
76924
  },
76925
+ async update(id, body) {
76926
+ const { data, error, response } = await client.PATCH("/agents/{id}", {
76927
+ params: { path: { id } },
76928
+ body
76929
+ });
76930
+ throwIfError(response, error);
76931
+ if (!data?.data)
76932
+ throw new OmniApiError("Failed to update agent", "UPDATE_FAILED", undefined, response.status);
76933
+ return data.data;
76934
+ },
76850
76935
  async delete(id) {
76851
76936
  const { error, response } = await client.DELETE("/agents/{id}", {
76852
76937
  params: { path: { id } }
@@ -76887,7 +76972,7 @@ import { fileURLToPath } from "url";
76887
76972
  // package.json
76888
76973
  var package_default = {
76889
76974
  name: "@automagik/omni",
76890
- version: "2.260407.1",
76975
+ version: "2.260409.4",
76891
76976
  description: "LLM-optimized CLI for Omni",
76892
76977
  type: "module",
76893
76978
  bin: {
@@ -77656,6 +77741,33 @@ function createRoutesCommand() {
77656
77741
  init_output();
77657
77742
  var VALID_PROVIDERS = ["claude", "agno", "openai", "gemini", "custom", "omni-internal"];
77658
77743
  var VALID_TYPES = ["assistant", "workflow", "team", "tool"];
77744
+ function buildUpdateAgentBody(options) {
77745
+ if (options.active && options.inactive) {
77746
+ error("Cannot combine --active and --inactive.");
77747
+ }
77748
+ if (options.provider !== undefined && !VALID_PROVIDERS.includes(options.provider)) {
77749
+ error(`Invalid provider: ${options.provider}. Valid: ${VALID_PROVIDERS.join(", ")}`);
77750
+ }
77751
+ if (options.type !== undefined && !VALID_TYPES.includes(options.type)) {
77752
+ error(`Invalid type: ${options.type}. Valid: ${VALID_TYPES.join(", ")}`);
77753
+ }
77754
+ const body = {};
77755
+ if (options.name !== undefined)
77756
+ body.name = options.name;
77757
+ if (options.model !== undefined)
77758
+ body.model = options.model;
77759
+ if (options.provider !== undefined)
77760
+ body.provider = options.provider;
77761
+ if (options.agentProvider !== undefined)
77762
+ body.agentProviderId = options.agentProvider;
77763
+ if (options.type !== undefined)
77764
+ body.agentType = options.type;
77765
+ if (options.active)
77766
+ body.isActive = true;
77767
+ if (options.inactive)
77768
+ body.isActive = false;
77769
+ return body;
77770
+ }
77659
77771
  function createAgentsCommand() {
77660
77772
  const agents = new Command("agents").description("Manage AI agent entities");
77661
77773
  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) => {
@@ -77724,6 +77836,19 @@ function createAgentsCommand() {
77724
77836
  error(`Failed to create agent: ${message}`);
77725
77837
  }
77726
77838
  });
77839
+ agents.command("update <id>").description("Update an existing agent (partial patch; omitted fields are preserved)").option("--name <name>", "Agent name").option("--model <model>", "Model identifier (e.g. claude-sonnet-4-6)").option("--provider <provider>", `AI provider (${VALID_PROVIDERS.join(", ")})`).option("--agent-provider <agentProviderId>", "Link to an agent provider configuration").option("--type <type>", `Agent type (${VALID_TYPES.join(", ")})`).option("--active", "Mark agent as active").option("--inactive", "Mark agent as inactive").action(async (id, options) => {
77840
+ const body = buildUpdateAgentBody(options);
77841
+ if (Object.keys(body).length === 0) {
77842
+ error("No fields to update. Pass at least one of --name, --model, --provider, --agent-provider, --type, --active, --inactive.");
77843
+ }
77844
+ try {
77845
+ const agent = await getClient().agents.update(id, body);
77846
+ data(agent);
77847
+ } catch (err) {
77848
+ const message = err instanceof Error ? err.message : "Unknown error";
77849
+ error(`Failed to update agent: ${message}`, undefined, 3);
77850
+ }
77851
+ });
77727
77852
  agents.command("delete <id>").description("Delete an agent (soft-delete, sets inactive)").action(async (id) => {
77728
77853
  const client = getClient();
77729
77854
  try {
@@ -80641,7 +80766,13 @@ function getMediaType(path) {
80641
80766
  }
80642
80767
  async function closeTurn(client, action, successMsg, reason) {
80643
80768
  try {
80644
- const result = await client.turns.close({ action, reason });
80769
+ const turnId = process.env.OMNI_TURN_ID;
80770
+ const extraHeaders = {};
80771
+ if (process.env.OMNI_INSTANCE)
80772
+ extraHeaders["x-omni-instance"] = process.env.OMNI_INSTANCE;
80773
+ if (process.env.OMNI_CHAT)
80774
+ extraHeaders["x-omni-chat"] = process.env.OMNI_CHAT;
80775
+ const result = await client.turns.close({ action, reason, turnId }, extraHeaders);
80645
80776
  if (result.alreadyClosed) {
80646
80777
  success(`${successMsg} Turn already closed (idempotent).`);
80647
80778
  } else {
@@ -80731,7 +80862,7 @@ function createDoneCommand() {
80731
80862
  return handleMedia(client, ctxWithMessage, options.media, options.caption);
80732
80863
  if (text)
80733
80864
  return handleText(client, ctxWithMessage, text);
80734
- error('Specify what to do: omni done "text", omni done --media <file>, omni done --react <emoji>, or omni done --skip');
80865
+ return handleSkip(client, options.reason);
80735
80866
  });
80736
80867
  }
80737
80868
 
@@ -80893,6 +81024,16 @@ function createEventsCommand() {
80893
81024
  error(`Failed to list events: ${message}`);
80894
81025
  }
80895
81026
  });
81027
+ events.command("get <id>").description("Get full details for a single event by ID").action(async (id) => {
81028
+ const client = getClient();
81029
+ try {
81030
+ const event = await client.events.get(id);
81031
+ data(event);
81032
+ } catch (err) {
81033
+ const message = err instanceof Error ? err.message : "Unknown error";
81034
+ error(`Failed to get event: ${message}`);
81035
+ }
81036
+ });
80896
81037
  events.command("search <query>").description("Search events by content").option("--since <time>", "Events since (e.g., 24h, 7d)").option("--limit <n>", "Limit results", (v) => Number.parseInt(v, 10), 50).action(async (query, options) => {
80897
81038
  const client = getClient();
80898
81039
  try {
@@ -83904,9 +84045,27 @@ async function streamProcessLogs(service, lines, follow) {
83904
84045
  });
83905
84046
  await proc.exited;
83906
84047
  }
84048
+ function printVerboseEntry(entry) {
84049
+ const time = new Date(entry.time).toISOString();
84050
+ raw(`${time} [${entry.level.toUpperCase()}] ${entry.module}`);
84051
+ raw(` ${entry.msg}`);
84052
+ if (entry.data && Object.keys(entry.data).length > 0) {
84053
+ for (const [key, value] of Object.entries(entry.data)) {
84054
+ const formatted = typeof value === "string" && value.includes(`
84055
+ `) ? `
84056
+ ${value.split(`
84057
+ `).map((line) => ` ${line}`).join(`
84058
+ `)}` : typeof value === "object" ? JSON.stringify(value, null, 2).split(`
84059
+ `).map((line, idx) => idx === 0 ? line : ` ${line}`).join(`
84060
+ `) : String(value);
84061
+ raw(` ${key}: ${formatted}`);
84062
+ }
84063
+ }
84064
+ raw("");
84065
+ }
83907
84066
  function createLogsCommand() {
83908
84067
  const logs = new Command("logs").description("View system logs");
83909
- logs.argument("[level]", "Log level filter (debug, info, warn, error)").option("--modules <modules>", "Comma-separated module names to filter").option("--limit <n>", "Limit results", (v) => Number.parseInt(v, 10), 100).option("--process [service]", "Stream PM2 process logs (default: api)").option("--follow", "Stream live logs (only with --process)", false).action(async (level, options) => {
84068
+ logs.argument("[level]", "Log level filter (debug, info, warn, error)").option("--modules <modules>", "Comma-separated module names to filter").option("--limit <n>", "Limit results", (v) => Number.parseInt(v, 10), 100).option("--process [service]", "Stream PM2 process logs (default: api)").option("--follow", "Stream live logs (only with --process)", false).option("--json", "Emit raw LogEntry[] as JSON (no truncation, no summary line)", false).option("--verbose", "Multi-line pretty-print with stack traces and data fields", false).action(async (level, options) => {
83910
84069
  if (options?.process !== undefined) {
83911
84070
  const service = typeof options.process === "string" ? options.process : "api";
83912
84071
  await streamProcessLogs(service, options.limit, options.follow);
@@ -83919,6 +84078,22 @@ function createLogsCommand() {
83919
84078
  modules: options?.modules,
83920
84079
  limit: options?.limit
83921
84080
  });
84081
+ if (getCurrentFormat() === "json") {
84082
+ raw(JSON.stringify(result.items, null, 2));
84083
+ await flushStdout();
84084
+ return;
84085
+ }
84086
+ if (options?.verbose) {
84087
+ if (result.items.length === 0) {
84088
+ dim("No logs found.");
84089
+ return;
84090
+ }
84091
+ for (const entry of result.items) {
84092
+ printVerboseEntry(entry);
84093
+ }
84094
+ dim(`Showing ${result.items.length} of ${result.meta.total} logs (buffer: ${result.meta.bufferSize})`);
84095
+ return;
84096
+ }
83922
84097
  const items = result.items.map((l) => ({
83923
84098
  time: new Date(l.time).toISOString(),
83924
84099
  level: l.level,
@@ -95491,6 +95666,78 @@ function createTtsCommand() {
95491
95666
  return tts;
95492
95667
  }
95493
95668
 
95669
+ // src/commands/turns.ts
95670
+ init_output();
95671
+ function formatDuration2(startedAt, closedAt) {
95672
+ const start = new Date(startedAt).getTime();
95673
+ const end = closedAt ? new Date(closedAt).getTime() : Date.now();
95674
+ const ms = end - start;
95675
+ if (ms < 1000)
95676
+ return `${ms}ms`;
95677
+ if (ms < 60000)
95678
+ return `${Math.round(ms / 1000)}s`;
95679
+ return `${Math.round(ms / 60000)}m`;
95680
+ }
95681
+ function createTurnsCommand() {
95682
+ const cmd = new Command("turns").description("Admin turn management");
95683
+ cmd.command("list").description("List turns with optional filters").option("--status <status>", "Filter by status (open, done, timeout)").option("--instance <id>", "Filter by instance ID").option("--chat <id>", "Filter by chat ID").option("--agent <id>", "Filter by agent ID").option("--limit <n>", "Max results (default 50)", "50").option("--offset <n>", "Offset for pagination (default 0)", "0").action(async (opts) => {
95684
+ const client = getClient();
95685
+ const result = await client.turns.list({
95686
+ status: opts.status,
95687
+ instanceId: opts.instance,
95688
+ chatId: opts.chat,
95689
+ agentId: opts.agent,
95690
+ limit: Number(opts.limit),
95691
+ offset: Number(opts.offset)
95692
+ });
95693
+ const rows = result.items.map((t) => ({
95694
+ id: t.id.slice(0, 8),
95695
+ status: t.status,
95696
+ chat: t.chatId.length > 20 ? `${t.chatId.slice(0, 20)}\u2026` : t.chatId,
95697
+ agent: t.agentId.slice(0, 8),
95698
+ duration: formatDuration2(t.startedAt, t.closedAt),
95699
+ nudges: t.nudgeCount,
95700
+ msgs: t.messagesSent
95701
+ }));
95702
+ list(rows, {
95703
+ emptyMessage: "No turns found.",
95704
+ rawData: result.items
95705
+ });
95706
+ if (getCurrentFormat() !== "json") {
95707
+ dim(`Total: ${result.total} | Showing ${result.offset + 1}\u2013${result.offset + result.items.length}`);
95708
+ }
95709
+ });
95710
+ cmd.command("get").description("Get a single turn by ID").argument("<id>", "Turn ID").action(async (id) => {
95711
+ const client = getClient();
95712
+ const turn = await client.turns.get(id);
95713
+ data(turn);
95714
+ });
95715
+ cmd.command("close").description("Admin force-close a turn").argument("<id>", "Turn ID to close").option("--reason <text>", "Close reason").action(async (id, opts) => {
95716
+ const client = getClient();
95717
+ const result = await client.turns.forceClose(id, opts.reason);
95718
+ success(`Turn ${result.turnId} closed`, result);
95719
+ });
95720
+ cmd.command("close-all").description("Bulk close all open turns (requires --confirm)").option("--confirm", "Confirm bulk close").option("--reason <text>", "Close reason").action(async (opts) => {
95721
+ if (!opts.confirm) {
95722
+ error("Bulk close requires --confirm flag to proceed.");
95723
+ }
95724
+ const client = getClient();
95725
+ const result = await client.turns.bulkClose(opts.reason);
95726
+ success(result.message, result);
95727
+ });
95728
+ cmd.command("stats").description("Show aggregate turn metrics").action(async () => {
95729
+ const client = getClient();
95730
+ const stats = await client.turns.stats();
95731
+ data({
95732
+ openCount: stats.openCount,
95733
+ totalCount: stats.totalCount,
95734
+ avgDurationMs: stats.avgDurationMs,
95735
+ timeoutRate: `${(stats.timeoutRate * 100).toFixed(1)}%`
95736
+ });
95737
+ });
95738
+ return cmd;
95739
+ }
95740
+
95494
95741
  // src/commands/update.ts
95495
95742
  import { createInterface as createInterface4 } from "readline";
95496
95743
  init_source();
@@ -96435,6 +96682,12 @@ var COMMANDS = [
96435
96682
  helpGroup: "Management",
96436
96683
  helpDescription: "Webhook management"
96437
96684
  },
96685
+ {
96686
+ create: createTurnsCommand,
96687
+ category: "advanced",
96688
+ helpGroup: "Management",
96689
+ helpDescription: "Admin turn management (list, close, stats)"
96690
+ },
96438
96691
  {
96439
96692
  create: createStatusCommand,
96440
96693
  category: "core",