@kopai/cli 0.8.1 → 0.8.2

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.mjs CHANGED
@@ -6,11 +6,8 @@ import { homedir } from "node:os";
6
6
  import { join } from "node:path";
7
7
  import { createInterface } from "node:readline";
8
8
  import { mkdir, readFile, writeFile } from "node:fs/promises";
9
-
10
9
  //#region src/config.ts
11
10
  const CONFIG_FILENAME = ".kopairc";
12
- const TOKEN_PREFIX_LENGTH = 10;
13
- const DEFAULT_URL$1 = "http://localhost:8000";
14
11
  /** Owner read+write only (rw-------). Used for files containing secrets. */
15
12
  const OWNER_READ_WRITE = 384;
16
13
  function loadConfigFile(path) {
@@ -68,7 +65,6 @@ function removeConfigToken(targetPath) {
68
65
  } catch {}
69
66
  return true;
70
67
  }
71
-
72
68
  //#endregion
73
69
  //#region src/client.ts
74
70
  function withConnectionOptions(cmd) {
@@ -104,7 +100,6 @@ function parseAttributes(attrs) {
104
100
  }
105
101
  return result;
106
102
  }
107
-
108
103
  //#endregion
109
104
  //#region src/output.ts
110
105
  function detectFormat(json, table) {
@@ -155,7 +150,6 @@ function outputError(error, json) {
155
150
  if (json) console.error(JSON.stringify({ error: err }));
156
151
  else console.error(`Error: ${err.message}`);
157
152
  }
158
-
159
153
  //#endregion
160
154
  //#region src/commands/traces.ts
161
155
  function createTracesCommand() {
@@ -211,7 +205,6 @@ function createTracesCommand() {
211
205
  function collect$2(value, previous) {
212
206
  return previous.concat([value]);
213
207
  }
214
-
215
208
  //#endregion
216
209
  //#region src/commands/logs.ts
217
210
  function createLogsCommand() {
@@ -253,7 +246,6 @@ function createLogsCommand() {
253
246
  function collect$1(value, previous) {
254
247
  return previous.concat([value]);
255
248
  }
256
-
257
249
  //#endregion
258
250
  //#region src/commands/metrics.ts
259
251
  function createMetricsCommand() {
@@ -304,7 +296,6 @@ function createMetricsCommand() {
304
296
  function collect(value, previous) {
305
297
  return previous.concat([value]);
306
298
  }
307
-
308
299
  //#endregion
309
300
  //#region src/commands/dashboards.ts
310
301
  async function readStdin() {
@@ -358,7 +349,6 @@ Example:
358
349
  });
359
350
  return dashboards;
360
351
  }
361
-
362
352
  //#endregion
363
353
  //#region src/commands/login.ts
364
354
  function readTokenFromStdin() {
@@ -383,7 +373,7 @@ function createLoginCommand() {
383
373
  }
384
374
  saveConfig({
385
375
  token,
386
- url: opts.url ?? DEFAULT_URL$1
376
+ url: opts.url ?? "http://localhost:8000"
387
377
  }, resolveConfigPath(opts.global ?? false));
388
378
  if (!opts.global) {
389
379
  if (existsSync(join(process.cwd(), ".git"))) {
@@ -393,10 +383,9 @@ function createLoginCommand() {
393
383
  if (!isIgnored) console.error("Warning: .kopairc is not in .gitignore. Add it to avoid committing secrets.");
394
384
  }
395
385
  }
396
- console.log(`Logged in. Token: ${token.slice(0, TOKEN_PREFIX_LENGTH)}...`);
386
+ console.log(`Logged in. Token: ${token.slice(0, 10)}...`);
397
387
  });
398
388
  }
399
-
400
389
  //#endregion
401
390
  //#region src/commands/logout.ts
402
391
  function createLogoutCommand() {
@@ -405,7 +394,6 @@ function createLogoutCommand() {
405
394
  else console.log("Not logged in.");
406
395
  });
407
396
  }
408
-
409
397
  //#endregion
410
398
  //#region src/commands/whoami.ts
411
399
  function createWhoamiCommand() {
@@ -415,11 +403,11 @@ function createWhoamiCommand() {
415
403
  console.log("Not logged in.");
416
404
  return;
417
405
  }
418
- console.log(`Token: ${config.token.slice(0, TOKEN_PREFIX_LENGTH)}...`);
419
- console.log(`URL: ${config.url ?? `${DEFAULT_URL$1} (default)`}`);
406
+ console.log(`Token: ${config.token.slice(0, 10)}...`);
407
+ console.log(`URL: ${config.url ?? `http://localhost:8000 (default)`}`);
420
408
  try {
421
409
  await new KopaiClient({
422
- baseUrl: config.url ?? DEFAULT_URL$1,
410
+ baseUrl: config.url ?? "http://localhost:8000",
423
411
  token: config.token
424
412
  }).searchTracesPage({ limit: 1 });
425
413
  console.log("Token is valid.");
@@ -430,7 +418,6 @@ function createWhoamiCommand() {
430
418
  }
431
419
  });
432
420
  }
433
-
434
421
  //#endregion
435
422
  //#region src/update-check.ts
436
423
  const CACHE_FILENAME = "update-check.json";
@@ -526,11 +513,9 @@ async function checkForUpdates(currentVersion, opts) {
526
513
  });
527
514
  if (latest && compareVersions(currentVersion, latest)) printNotice(currentVersion, latest);
528
515
  }
529
-
530
516
  //#endregion
531
517
  //#region package.json
532
- var version = "0.8.1";
533
-
518
+ var version = "0.8.2";
534
519
  //#endregion
535
520
  //#region src/index.ts
536
521
  const program = new Command();
@@ -541,7 +526,7 @@ Examples:
541
526
  $ kopai logs search --url https://example.com --token kpi_… # with auth`);
542
527
  program.parse();
543
528
  checkForUpdates(version);
544
-
545
529
  //#endregion
546
- export { };
530
+ export {};
531
+
547
532
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["DEFAULT_URL","collect","collect","DEFAULT_URL","DEFAULT_URL","pkg.version"],"sources":["../src/config.ts","../src/client.ts","../src/output.ts","../src/commands/traces.ts","../src/commands/logs.ts","../src/commands/metrics.ts","../src/commands/dashboards.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/update-check.ts","../package.json","../src/index.ts"],"sourcesContent":["import { readFileSync, existsSync, writeFileSync, chmodSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Config {\n url?: string;\n token?: string;\n}\n\nexport const CONFIG_FILENAME = \".kopairc\";\nexport const TOKEN_PREFIX_LENGTH = 10;\nexport const DEFAULT_URL = \"http://localhost:8000\";\n\n/** Owner read+write only (rw-------). Used for files containing secrets. */\nconst OWNER_READ_WRITE = 0o600;\n\nfunction loadConfigFile(path: string): Config | null {\n if (!existsSync(path)) return null;\n try {\n const content = readFileSync(path, \"utf-8\");\n return JSON.parse(content) as Config;\n } catch {\n return null;\n }\n}\n\nexport function loadConfig(configPath?: string): Config {\n // Priority: --config flag > ./.kopairc > ~/.kopairc\n const paths = configPath\n ? [configPath]\n : [join(process.cwd(), CONFIG_FILENAME), join(homedir(), CONFIG_FILENAME)];\n\n for (const path of paths) {\n const config = loadConfigFile(path);\n if (config) return config;\n }\n\n return {};\n}\n\nexport function resolveConfigPath(global: boolean): string {\n return global\n ? join(homedir(), CONFIG_FILENAME)\n : join(process.cwd(), CONFIG_FILENAME);\n}\n\nexport function saveConfig(updates: Partial<Config>, targetPath: string): void {\n let existing: Config = {};\n if (existsSync(targetPath)) {\n try {\n const content = readFileSync(targetPath, \"utf-8\");\n existing = JSON.parse(content) as Config;\n } catch {\n // ignore parse errors, overwrite\n }\n }\n const merged = { ...existing, ...updates };\n writeFileSync(targetPath, JSON.stringify(merged, null, 2) + \"\\n\", {\n encoding: \"utf-8\",\n mode: OWNER_READ_WRITE,\n });\n chmodSync(targetPath, OWNER_READ_WRITE);\n}\n\nexport function removeConfigToken(targetPath: string): boolean {\n if (!existsSync(targetPath)) return false;\n try {\n const content = readFileSync(targetPath, \"utf-8\");\n const config = JSON.parse(content) as Config;\n if (!config.token) return false;\n delete config.token;\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\", {\n encoding: \"utf-8\",\n mode: OWNER_READ_WRITE,\n });\n } catch {\n return false;\n }\n try {\n chmodSync(targetPath, OWNER_READ_WRITE);\n } catch {\n // chmod failure does not affect the successful token removal\n }\n return true;\n}\n","import type { Command } from \"commander\";\nimport { KopaiClient } from \"@kopai/sdk\";\nimport { loadConfig } from \"./config.js\";\n\nexport function withConnectionOptions<T extends Command>(cmd: T): T {\n return cmd\n .option(\"--url <url>\", \"API base URL\")\n .option(\"--token <token>\", \"Auth token\")\n .option(\"-c, --config <path>\", \"Config file path\")\n .option(\"--timeout <ms>\", \"Request timeout\") as T;\n}\n\nexport interface ClientOptions {\n config?: string;\n url?: string;\n token?: string;\n timeout?: number;\n}\n\nconst DEFAULT_URL = \"http://localhost:8000\";\n\nexport interface ConnectionOpts {\n url: string;\n token: string | undefined;\n}\n\nexport function resolveConnectionOpts(opts: ClientOptions): ConnectionOpts {\n const fileConfig = loadConfig(opts.config);\n const raw = opts.url ?? fileConfig.url ?? DEFAULT_URL;\n const url = raw.replace(/\\/signals\\/?$/, \"\").replace(/\\/$/, \"\");\n return {\n url,\n token: opts.token ?? fileConfig.token,\n };\n}\n\nexport function createClient(opts: ClientOptions): KopaiClient {\n const { url, token } = resolveConnectionOpts(opts);\n\n const timeout =\n opts.timeout != null ? parseInt(String(opts.timeout), 10) : undefined;\n\n return new KopaiClient({\n baseUrl: url,\n token,\n timeout: Number.isNaN(timeout) ? undefined : timeout,\n });\n}\n\nexport function parseAttributes(attrs?: string[]): Record<string, string> {\n if (!attrs || attrs.length === 0) return {};\n const result: Record<string, string> = {};\n for (const attr of attrs) {\n const idx = attr.indexOf(\"=\");\n if (idx === -1) {\n console.error(`Invalid attribute format: ${attr}. Use key=value`);\n process.exit(2);\n }\n result[attr.slice(0, idx)] = attr.slice(idx + 1);\n }\n return result;\n}\n","export type OutputFormat = \"json\" | \"table\";\n\nexport interface OutputOptions {\n format: OutputFormat;\n fields?: string[];\n}\n\nexport function detectFormat(json?: boolean, table?: boolean): OutputFormat {\n if (json) return \"json\";\n if (table) return \"table\";\n // Default: table for TTY, JSON for pipes\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nfunction countAttributes(attr: { values: Record<string, string[]> }): number {\n return Object.keys(attr.values).length;\n}\n\nfunction filterFields<T extends object>(data: T, fields: string[]): Partial<T> {\n return Object.fromEntries(\n Object.entries(data).filter(([key]) => fields.includes(key))\n ) as Partial<T>;\n}\n\nexport function parseFields(fieldsStr?: string): string[] | undefined {\n if (!fieldsStr) return undefined;\n return fieldsStr.split(\",\").map((f) => f.trim());\n}\n\nfunction isMetricsDiscoverData(data: unknown[]): data is Array<{\n attributes: { values: Record<string, string[]> };\n resourceAttributes: { values: Record<string, string[]> };\n}> {\n return (\n data.length > 0 &&\n typeof data[0] === \"object\" &&\n data[0] !== null &&\n \"attributes\" in data[0] &&\n \"resourceAttributes\" in data[0] &&\n typeof (data[0] as Record<string, unknown>).attributes === \"object\" &&\n (data[0] as Record<string, unknown>).attributes !== null &&\n \"values\" in ((data[0] as Record<string, unknown>).attributes as object)\n );\n}\n\nexport function output<T>(data: T, opts: OutputOptions): void {\n let outputData = data;\n\n // Apply field filtering\n if (opts.fields && opts.fields.length > 0) {\n if (Array.isArray(data)) {\n outputData = data.map((item) =>\n typeof item === \"object\" && item !== null\n ? filterFields(item as object, opts.fields!)\n : item\n ) as T;\n } else if (typeof data === \"object\" && data !== null) {\n outputData = filterFields(data as object, opts.fields) as T;\n }\n }\n\n if (opts.format === \"json\") {\n console.log(JSON.stringify(outputData, null, 2));\n } else {\n if (Array.isArray(outputData)) {\n if (outputData.length === 0) {\n console.log(\"No results found.\");\n } else if (!opts.fields && isMetricsDiscoverData(outputData)) {\n const transformed = outputData.map((m) => ({\n name: m.name,\n type: m.type,\n unit: m.unit,\n description: m.description,\n attrs: countAttributes(m.attributes),\n resourceAttrs: countAttributes(m.resourceAttributes),\n }));\n console.table(transformed);\n console.log(\"\\nUse --json for full attribute details.\");\n } else {\n console.table(outputData);\n }\n } else {\n console.log(outputData);\n }\n }\n}\n\nexport function outputError(error: unknown, json: boolean): void {\n const err =\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) };\n\n if (json) {\n console.error(JSON.stringify({ error: err }));\n } else {\n console.error(`Error: ${err.message}`);\n }\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface TracesGetOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\ninterface TracesSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n parentSpanId?: string;\n service?: string;\n spanName?: string;\n spanKind?: string;\n statusCode?: string;\n scope?: string;\n timestampMin?: string;\n timestampMax?: string;\n durationMin?: string;\n durationMax?: string;\n spanAttr?: string[];\n resourceAttr?: string[];\n sort?: string;\n}\n\nexport function createTracesCommand(): Command {\n const traces = new Command(\"traces\").description(\"Query traces\");\n\n withConnectionOptions(\n traces\n .command(\"get\")\n .description(\"Get all spans for a trace by ID\")\n .argument(\"<traceId>\", \"Trace ID\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (traceId: string, opts: TracesGetOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const spans = await client.getTrace(traceId);\n output(spans, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n traces\n .command(\"search\")\n .description(\"Search traces\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"--parent-span-id <id>\", \"Filter by parent span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--span-name <name>\", \"Filter by span name\")\n .option(\"--span-kind <kind>\", \"Filter by span kind\")\n .option(\"--status-code <code>\", \"Filter by status code\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\"--duration-min <ns>\", \"Min duration (nanoseconds)\")\n .option(\"--duration-max <ns>\", \"Max duration (nanoseconds)\")\n .option(\n \"--span-attr <key=value>\",\n \"Span attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: TracesSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n parentSpanId: opts.parentSpanId,\n serviceName: opts.service,\n spanName: opts.spanName,\n spanKind: opts.spanKind,\n statusCode: opts.statusCode,\n scopeName: opts.scope,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n durationMin: opts.durationMin,\n durationMax: opts.durationMax,\n spanAttributes: parseAttributes(opts.spanAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchTracesPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return traces;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface LogsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n service?: string;\n scope?: string;\n severityText?: string;\n severityMin?: string;\n severityMax?: string;\n body?: string;\n timestampMin?: string;\n timestampMax?: string;\n logAttr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\nexport function createLogsCommand(): Command {\n const logs = new Command(\"logs\").description(\"Query logs\");\n\n withConnectionOptions(\n logs\n .command(\"search\")\n .description(\"Search logs\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--severity-text <level>\", \"Filter by severity text\")\n .option(\"--severity-min <n>\", \"Min severity number\")\n .option(\"--severity-max <n>\", \"Max severity number\")\n .option(\"-b, --body <text>\", \"Filter by body contains\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\n \"--log-attr <key=value>\",\n \"Log attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: LogsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n serviceName: opts.service,\n scopeName: opts.scope,\n severityText: opts.severityText,\n severityNumberMin: opts.severityMin\n ? parseInt(opts.severityMin, 10)\n : undefined,\n severityNumberMax: opts.severityMax\n ? parseInt(opts.severityMax, 10)\n : undefined,\n bodyContains: opts.body,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n logAttributes: parseAttributes(opts.logAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchLogsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return logs;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface MetricsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n type: string;\n name?: string;\n service?: string;\n scope?: string;\n timeMin?: string;\n timeMax?: string;\n attr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\ninterface MetricsDiscoverOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\nexport function createMetricsCommand(): Command {\n const metrics = new Command(\"metrics\").description(\"Query metrics\");\n\n withConnectionOptions(\n metrics\n .command(\"search\")\n .description(\"Search metrics\")\n .requiredOption(\n \"--type <type>\",\n \"Metric type (Gauge|Sum|Histogram|ExponentialHistogram|Summary)\"\n )\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"-n, --name <name>\", \"Filter by metric name\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--time-min <ns>\", \"Min time (nanoseconds)\")\n .option(\"--time-max <ns>\", \"Max time (nanoseconds)\")\n .option(\n \"-a, --attr <key=value>\",\n \"Attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: MetricsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n metricType: opts.type as\n | \"Gauge\"\n | \"Sum\"\n | \"Histogram\"\n | \"ExponentialHistogram\"\n | \"Summary\",\n metricName: opts.name,\n serviceName: opts.service,\n scopeName: opts.scope,\n timeUnixMin: opts.timeMin,\n timeUnixMax: opts.timeMax,\n attributes: parseAttributes(opts.attr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchMetricsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n metrics\n .command(\"discover\")\n .description(\"List available metrics\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (opts: MetricsDiscoverOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const result = await client.discoverMetrics();\n output(result.metrics, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return metrics;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n resolveConnectionOpts,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError } from \"../output.js\";\n\ninterface DashboardCreateOptions extends ClientOptions {\n name: string;\n treeVersion: string;\n json?: boolean;\n table?: boolean;\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n\nexport function createDashboardsCommand(): Command {\n const dashboards = new Command(\"dashboards\").description(\"Manage dashboards\");\n\n withConnectionOptions(\n dashboards\n .command(\"schema\")\n .description(\"Print UI tree schema for AI agents\")\n ).action(async (opts: ClientOptions) => {\n try {\n const { url, token } = resolveConnectionOpts(opts);\n const headers: Record<string, string> = {};\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n const response = await fetch(`${url}/dashboards/schema`, { headers });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n const schema = await response.text();\n process.stdout.write(schema);\n } catch (err) {\n outputError(err, false);\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n dashboards\n .command(\"create\")\n .description(\"Create a dashboard (reads uiTree JSON from stdin)\")\n .requiredOption(\"--name <name>\", \"Dashboard name\")\n .requiredOption(\"--tree-version <semver>\", \"UI tree version (semver)\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .addHelpText(\n \"after\",\n `\nExample:\n $ echo '{\"uiTree\":{\"root\":\"s1\",\"elements\":{\"s1\":{\"key\":\"s1\",\"type\":\"Stack\",\"props\":{\"direction\":\"vertical\",\"gap\":\"md\",\"align\":null},\"children\":[],\"parentKey\":\"\"}}}}' | kopai dashboards create --name \"My Dashboard\" --tree-version \"0.5.0\" --json`\n )\n ).action(async (opts: DashboardCreateOptions) => {\n const isJson = opts.json ?? false;\n try {\n const client = createClient(opts);\n const raw = await readStdin();\n let body: Record<string, unknown>;\n try {\n body = JSON.parse(raw) as Record<string, unknown>;\n } catch (e) {\n if (e instanceof SyntaxError) {\n process.stderr.write(`Invalid JSON input: ${e.message}\\n`);\n process.exit(2);\n }\n throw e;\n }\n\n const result = await client.createDashboard({\n name: opts.name,\n uiTreeVersion: opts.treeVersion,\n uiTree: (body.uiTree ?? body) as Record<string, unknown>,\n metadata: body.metadata as Record<string, unknown> | undefined,\n });\n\n const format = detectFormat(opts.json, opts.table);\n output(result, { format });\n } catch (err) {\n outputError(err, isJson);\n process.exit(1);\n }\n });\n\n return dashboards;\n}\n","import { Command } from \"commander\";\nimport { createInterface } from \"node:readline\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n saveConfig,\n resolveConfigPath,\n TOKEN_PREFIX_LENGTH,\n DEFAULT_URL,\n type Config,\n} from \"../config.js\";\n\nfunction readTokenFromStdin(): Promise<string> {\n return new Promise((resolve) => {\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n rl.question(\"Token: \", (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport function createLoginCommand(): Command {\n return new Command(\"login\")\n .description(\"Save an API token to .kopairc\")\n .option(\"--url <url>\", \"API base URL to save alongside token\")\n .option(\"--global\", \"Write to ~/.kopairc instead of ./.kopairc\")\n .action(async (opts: { url?: string; global?: boolean }) => {\n const token = await readTokenFromStdin();\n if (!token) {\n console.error(\"Token cannot be empty.\");\n process.exitCode = 2;\n return;\n }\n\n const updates: Partial<Config> = {\n token,\n url: opts.url ?? DEFAULT_URL,\n };\n\n const targetPath = resolveConfigPath(opts.global ?? false);\n saveConfig(updates, targetPath);\n\n // Warn if in a git repo and .kopairc is not gitignored\n if (!opts.global) {\n const gitDir = join(process.cwd(), \".git\");\n if (existsSync(gitDir)) {\n const gitignorePath = join(process.cwd(), \".gitignore\");\n let isIgnored = false;\n if (existsSync(gitignorePath)) {\n const content = readFileSync(gitignorePath, \"utf-8\");\n isIgnored = content\n .split(\"\\n\")\n .some((line) => line.trim() === \".kopairc\");\n }\n if (!isIgnored) {\n console.error(\n \"Warning: .kopairc is not in .gitignore. Add it to avoid committing secrets.\"\n );\n }\n }\n }\n\n console.log(\n `Logged in. Token: ${token.slice(0, TOKEN_PREFIX_LENGTH)}...`\n );\n });\n}\n","import { Command } from \"commander\";\nimport { removeConfigToken, resolveConfigPath } from \"../config.js\";\n\nexport function createLogoutCommand(): Command {\n return new Command(\"logout\")\n .description(\"Remove saved API token from .kopairc\")\n .option(\"--global\", \"Remove from ~/.kopairc instead of ./.kopairc\")\n .action((opts: { global?: boolean }) => {\n const targetPath = resolveConfigPath(opts.global ?? false);\n const removed = removeConfigToken(targetPath);\n\n if (removed) {\n console.log(\"Logged out.\");\n } else {\n console.log(\"Not logged in.\");\n }\n });\n}\n","import { Command } from \"commander\";\nimport { KopaiClient } from \"@kopai/sdk\";\nimport { loadConfig, TOKEN_PREFIX_LENGTH, DEFAULT_URL } from \"../config.js\";\n\nexport function createWhoamiCommand(): Command {\n return new Command(\"whoami\")\n .description(\"Show current authentication status\")\n .option(\"-c, --config <path>\", \"Config file path\")\n .action(async (opts: { config?: string }) => {\n const config = loadConfig(opts.config);\n\n if (!config.token) {\n console.log(\"Not logged in.\");\n return;\n }\n\n console.log(`Token: ${config.token.slice(0, TOKEN_PREFIX_LENGTH)}...`);\n console.log(`URL: ${config.url ?? `${DEFAULT_URL} (default)`}`);\n\n // Try to validate token against server\n try {\n const client = new KopaiClient({\n baseUrl: config.url ?? DEFAULT_URL,\n token: config.token,\n });\n await client.searchTracesPage({ limit: 1 });\n console.log(\"Token is valid.\");\n } catch (err: unknown) {\n const status =\n err && typeof err === \"object\" && \"status\" in err\n ? (err as { status: number }).status\n : undefined;\n if (status === 401) {\n console.log(\"Token is invalid or expired.\");\n } else {\n console.log(\"Could not reach server to validate token.\");\n }\n process.exitCode = 1;\n }\n });\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst CACHE_FILENAME = \"update-check.json\";\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\ninterface CacheData {\n lastCheck: number;\n latestVersion: string | null;\n}\n\ninterface CheckOptions {\n fetchFn?: typeof fetch;\n}\n\nexport function getCacheDir(): string {\n switch (process.platform) {\n case \"darwin\":\n return join(homedir(), \"Library\", \"Caches\", \"kopai\");\n case \"win32\": {\n const localAppData = process.env.LOCALAPPDATA;\n if (localAppData) return join(localAppData, \"kopai\", \"cache\");\n return join(homedir(), \"AppData\", \"Local\", \"kopai\", \"cache\");\n }\n default: {\n const xdg = process.env.XDG_CACHE_HOME;\n if (xdg) return join(xdg, \"kopai\");\n return join(homedir(), \".cache\", \"kopai\");\n }\n }\n}\n\nexport function compareVersions(current: string, latest: string): boolean {\n const parse = (v: string): [number, number, number] | null => {\n const parts = v.split(\".\").map(Number);\n if (parts.length < 3 || parts.some(isNaN)) return null;\n return [parts[0]!, parts[1]!, parts[2]!];\n };\n const c = parse(current);\n const l = parse(latest);\n if (!c || !l) return false;\n if (l[0] !== c[0]) return l[0] > c[0];\n if (l[1] !== c[1]) return l[1] > c[1];\n return l[2] > c[2];\n}\n\nexport function shouldCheck(): boolean {\n if (process.env.KOPAI_NO_UPDATE_CHECK) return false;\n if (process.env.CI || process.env.BUILD_NUMBER || process.env.RUN_ID)\n return false;\n if (!process.stderr.isTTY) return false;\n return true;\n}\n\nasync function readCache(cacheDir: string): Promise<CacheData | null> {\n try {\n const raw = await readFile(join(cacheDir, CACHE_FILENAME), \"utf-8\");\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n if (typeof parsed.lastCheck !== \"number\") return null;\n const latestVersion =\n typeof parsed.latestVersion === \"string\" && parsed.latestVersion\n ? parsed.latestVersion\n : null;\n return { lastCheck: parsed.lastCheck, latestVersion };\n } catch {\n return null;\n }\n}\n\nasync function writeCache(cacheDir: string, data: CacheData): Promise<void> {\n try {\n await mkdir(cacheDir, { recursive: true });\n await writeFile(join(cacheDir, CACHE_FILENAME), JSON.stringify(data));\n } catch {\n // ignore cache write failures\n }\n}\n\nasync function fetchLatestVersion(\n fetchFn: typeof fetch\n): Promise<string | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 3000);\n try {\n const res = await fetchFn(\"https://registry.npmjs.org/@kopai/cli/latest\", {\n signal: controller.signal,\n });\n if (!res.ok) return null;\n const data = (await res.json()) as Record<string, unknown>;\n if (typeof data?.version !== \"string\" || !data.version.trim()) return null;\n return data.version;\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction printNotice(current: string, latest: string): void {\n process.stderr.write(\n `\\n Update available: ${current} → ${latest}\\n Run: npx @kopai/cli@latest\\n Set KOPAI_NO_UPDATE_CHECK=1 to disable.\\n\\n`\n );\n}\n\nexport async function checkForUpdates(\n currentVersion: string,\n opts?: CheckOptions\n): Promise<void> {\n if (!shouldCheck()) return;\n\n const cacheDir = getCacheDir();\n const cache = await readCache(cacheDir);\n\n if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {\n if (\n cache.latestVersion &&\n compareVersions(currentVersion, cache.latestVersion)\n ) {\n printNotice(currentVersion, cache.latestVersion);\n }\n return;\n }\n\n const fetchFn = opts?.fetchFn ?? fetch;\n const latest = await fetchLatestVersion(fetchFn);\n\n await writeCache(cacheDir, { lastCheck: Date.now(), latestVersion: latest });\n\n if (latest && compareVersions(currentVersion, latest)) {\n printNotice(currentVersion, latest);\n }\n}\n","","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { createTracesCommand } from \"./commands/traces.js\";\nimport { createLogsCommand } from \"./commands/logs.js\";\nimport { createMetricsCommand } from \"./commands/metrics.js\";\nimport { createDashboardsCommand } from \"./commands/dashboards.js\";\nimport { createLoginCommand } from \"./commands/login.js\";\nimport { createLogoutCommand } from \"./commands/logout.js\";\nimport { createWhoamiCommand } from \"./commands/whoami.js\";\nimport { checkForUpdates } from \"./update-check.js\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\nconst program = new Command();\n\nprogram\n .name(\"@kopai/cli\")\n .description(\"|--k> kopai - Query OpenTelemetry data\")\n .version(pkg.version)\n .addCommand(createTracesCommand())\n .addCommand(createLogsCommand())\n .addCommand(createMetricsCommand())\n .addCommand(createDashboardsCommand())\n .addCommand(createLoginCommand())\n .addCommand(createLogoutCommand())\n .addCommand(createWhoamiCommand())\n .addHelpText(\n \"after\",\n `\nExamples:\n $ kopai traces search # localhost:8000 (default, for @kopai/app running locally)\n $ kopai traces search --url https://example.com # remote instance\n $ kopai logs search --url https://example.com --token kpi_… # with auth`\n );\n\nprogram.parse();\nvoid checkForUpdates(pkg.version);\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["DEFAULT_URL","collect","collect","pkg.version"],"sources":["../src/config.ts","../src/client.ts","../src/output.ts","../src/commands/traces.ts","../src/commands/logs.ts","../src/commands/metrics.ts","../src/commands/dashboards.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/update-check.ts","../package.json","../src/index.ts"],"sourcesContent":["import { readFileSync, existsSync, writeFileSync, chmodSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Config {\n url?: string;\n token?: string;\n}\n\nexport const CONFIG_FILENAME = \".kopairc\";\nexport const TOKEN_PREFIX_LENGTH = 10;\nexport const DEFAULT_URL = \"http://localhost:8000\";\n\n/** Owner read+write only (rw-------). Used for files containing secrets. */\nconst OWNER_READ_WRITE = 0o600;\n\nfunction loadConfigFile(path: string): Config | null {\n if (!existsSync(path)) return null;\n try {\n const content = readFileSync(path, \"utf-8\");\n return JSON.parse(content) as Config;\n } catch {\n return null;\n }\n}\n\nexport function loadConfig(configPath?: string): Config {\n // Priority: --config flag > ./.kopairc > ~/.kopairc\n const paths = configPath\n ? [configPath]\n : [join(process.cwd(), CONFIG_FILENAME), join(homedir(), CONFIG_FILENAME)];\n\n for (const path of paths) {\n const config = loadConfigFile(path);\n if (config) return config;\n }\n\n return {};\n}\n\nexport function resolveConfigPath(global: boolean): string {\n return global\n ? join(homedir(), CONFIG_FILENAME)\n : join(process.cwd(), CONFIG_FILENAME);\n}\n\nexport function saveConfig(updates: Partial<Config>, targetPath: string): void {\n let existing: Config = {};\n if (existsSync(targetPath)) {\n try {\n const content = readFileSync(targetPath, \"utf-8\");\n existing = JSON.parse(content) as Config;\n } catch {\n // ignore parse errors, overwrite\n }\n }\n const merged = { ...existing, ...updates };\n writeFileSync(targetPath, JSON.stringify(merged, null, 2) + \"\\n\", {\n encoding: \"utf-8\",\n mode: OWNER_READ_WRITE,\n });\n chmodSync(targetPath, OWNER_READ_WRITE);\n}\n\nexport function removeConfigToken(targetPath: string): boolean {\n if (!existsSync(targetPath)) return false;\n try {\n const content = readFileSync(targetPath, \"utf-8\");\n const config = JSON.parse(content) as Config;\n if (!config.token) return false;\n delete config.token;\n writeFileSync(targetPath, JSON.stringify(config, null, 2) + \"\\n\", {\n encoding: \"utf-8\",\n mode: OWNER_READ_WRITE,\n });\n } catch {\n return false;\n }\n try {\n chmodSync(targetPath, OWNER_READ_WRITE);\n } catch {\n // chmod failure does not affect the successful token removal\n }\n return true;\n}\n","import type { Command } from \"commander\";\nimport { KopaiClient } from \"@kopai/sdk\";\nimport { loadConfig } from \"./config.js\";\n\nexport function withConnectionOptions<T extends Command>(cmd: T): T {\n return cmd\n .option(\"--url <url>\", \"API base URL\")\n .option(\"--token <token>\", \"Auth token\")\n .option(\"-c, --config <path>\", \"Config file path\")\n .option(\"--timeout <ms>\", \"Request timeout\") as T;\n}\n\nexport interface ClientOptions {\n config?: string;\n url?: string;\n token?: string;\n timeout?: number;\n}\n\nconst DEFAULT_URL = \"http://localhost:8000\";\n\nexport interface ConnectionOpts {\n url: string;\n token: string | undefined;\n}\n\nexport function resolveConnectionOpts(opts: ClientOptions): ConnectionOpts {\n const fileConfig = loadConfig(opts.config);\n const raw = opts.url ?? fileConfig.url ?? DEFAULT_URL;\n const url = raw.replace(/\\/signals\\/?$/, \"\").replace(/\\/$/, \"\");\n return {\n url,\n token: opts.token ?? fileConfig.token,\n };\n}\n\nexport function createClient(opts: ClientOptions): KopaiClient {\n const { url, token } = resolveConnectionOpts(opts);\n\n const timeout =\n opts.timeout != null ? parseInt(String(opts.timeout), 10) : undefined;\n\n return new KopaiClient({\n baseUrl: url,\n token,\n timeout: Number.isNaN(timeout) ? undefined : timeout,\n });\n}\n\nexport function parseAttributes(attrs?: string[]): Record<string, string> {\n if (!attrs || attrs.length === 0) return {};\n const result: Record<string, string> = {};\n for (const attr of attrs) {\n const idx = attr.indexOf(\"=\");\n if (idx === -1) {\n console.error(`Invalid attribute format: ${attr}. Use key=value`);\n process.exit(2);\n }\n result[attr.slice(0, idx)] = attr.slice(idx + 1);\n }\n return result;\n}\n","export type OutputFormat = \"json\" | \"table\";\n\nexport interface OutputOptions {\n format: OutputFormat;\n fields?: string[];\n}\n\nexport function detectFormat(json?: boolean, table?: boolean): OutputFormat {\n if (json) return \"json\";\n if (table) return \"table\";\n // Default: table for TTY, JSON for pipes\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nfunction countAttributes(attr: { values: Record<string, string[]> }): number {\n return Object.keys(attr.values).length;\n}\n\nfunction filterFields<T extends object>(data: T, fields: string[]): Partial<T> {\n return Object.fromEntries(\n Object.entries(data).filter(([key]) => fields.includes(key))\n ) as Partial<T>;\n}\n\nexport function parseFields(fieldsStr?: string): string[] | undefined {\n if (!fieldsStr) return undefined;\n return fieldsStr.split(\",\").map((f) => f.trim());\n}\n\nfunction isMetricsDiscoverData(data: unknown[]): data is Array<{\n attributes: { values: Record<string, string[]> };\n resourceAttributes: { values: Record<string, string[]> };\n}> {\n return (\n data.length > 0 &&\n typeof data[0] === \"object\" &&\n data[0] !== null &&\n \"attributes\" in data[0] &&\n \"resourceAttributes\" in data[0] &&\n typeof (data[0] as Record<string, unknown>).attributes === \"object\" &&\n (data[0] as Record<string, unknown>).attributes !== null &&\n \"values\" in ((data[0] as Record<string, unknown>).attributes as object)\n );\n}\n\nexport function output<T>(data: T, opts: OutputOptions): void {\n let outputData = data;\n\n // Apply field filtering\n if (opts.fields && opts.fields.length > 0) {\n if (Array.isArray(data)) {\n outputData = data.map((item) =>\n typeof item === \"object\" && item !== null\n ? filterFields(item as object, opts.fields!)\n : item\n ) as T;\n } else if (typeof data === \"object\" && data !== null) {\n outputData = filterFields(data as object, opts.fields) as T;\n }\n }\n\n if (opts.format === \"json\") {\n console.log(JSON.stringify(outputData, null, 2));\n } else {\n if (Array.isArray(outputData)) {\n if (outputData.length === 0) {\n console.log(\"No results found.\");\n } else if (!opts.fields && isMetricsDiscoverData(outputData)) {\n const transformed = outputData.map((m) => ({\n name: m.name,\n type: m.type,\n unit: m.unit,\n description: m.description,\n attrs: countAttributes(m.attributes),\n resourceAttrs: countAttributes(m.resourceAttributes),\n }));\n console.table(transformed);\n console.log(\"\\nUse --json for full attribute details.\");\n } else {\n console.table(outputData);\n }\n } else {\n console.log(outputData);\n }\n }\n}\n\nexport function outputError(error: unknown, json: boolean): void {\n const err =\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) };\n\n if (json) {\n console.error(JSON.stringify({ error: err }));\n } else {\n console.error(`Error: ${err.message}`);\n }\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface TracesGetOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\ninterface TracesSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n parentSpanId?: string;\n service?: string;\n spanName?: string;\n spanKind?: string;\n statusCode?: string;\n scope?: string;\n timestampMin?: string;\n timestampMax?: string;\n durationMin?: string;\n durationMax?: string;\n spanAttr?: string[];\n resourceAttr?: string[];\n sort?: string;\n}\n\nexport function createTracesCommand(): Command {\n const traces = new Command(\"traces\").description(\"Query traces\");\n\n withConnectionOptions(\n traces\n .command(\"get\")\n .description(\"Get all spans for a trace by ID\")\n .argument(\"<traceId>\", \"Trace ID\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (traceId: string, opts: TracesGetOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const spans = await client.getTrace(traceId);\n output(spans, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n traces\n .command(\"search\")\n .description(\"Search traces\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"--parent-span-id <id>\", \"Filter by parent span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--span-name <name>\", \"Filter by span name\")\n .option(\"--span-kind <kind>\", \"Filter by span kind\")\n .option(\"--status-code <code>\", \"Filter by status code\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\"--duration-min <ns>\", \"Min duration (nanoseconds)\")\n .option(\"--duration-max <ns>\", \"Max duration (nanoseconds)\")\n .option(\n \"--span-attr <key=value>\",\n \"Span attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: TracesSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n parentSpanId: opts.parentSpanId,\n serviceName: opts.service,\n spanName: opts.spanName,\n spanKind: opts.spanKind,\n statusCode: opts.statusCode,\n scopeName: opts.scope,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n durationMin: opts.durationMin,\n durationMax: opts.durationMax,\n spanAttributes: parseAttributes(opts.spanAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchTracesPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return traces;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface LogsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n traceId?: string;\n spanId?: string;\n service?: string;\n scope?: string;\n severityText?: string;\n severityMin?: string;\n severityMax?: string;\n body?: string;\n timestampMin?: string;\n timestampMax?: string;\n logAttr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\nexport function createLogsCommand(): Command {\n const logs = new Command(\"logs\").description(\"Query logs\");\n\n withConnectionOptions(\n logs\n .command(\"search\")\n .description(\"Search logs\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"--trace-id <id>\", \"Filter by trace ID\")\n .option(\"--span-id <id>\", \"Filter by span ID\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--severity-text <level>\", \"Filter by severity text\")\n .option(\"--severity-min <n>\", \"Min severity number\")\n .option(\"--severity-max <n>\", \"Max severity number\")\n .option(\"-b, --body <text>\", \"Filter by body contains\")\n .option(\"--timestamp-min <ns>\", \"Min timestamp (nanoseconds)\")\n .option(\"--timestamp-max <ns>\", \"Max timestamp (nanoseconds)\")\n .option(\n \"--log-attr <key=value>\",\n \"Log attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: LogsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n traceId: opts.traceId,\n spanId: opts.spanId,\n serviceName: opts.service,\n scopeName: opts.scope,\n severityText: opts.severityText,\n severityNumberMin: opts.severityMin\n ? parseInt(opts.severityMin, 10)\n : undefined,\n severityNumberMax: opts.severityMax\n ? parseInt(opts.severityMax, 10)\n : undefined,\n bodyContains: opts.body,\n timestampMin: opts.timestampMin,\n timestampMax: opts.timestampMax,\n logAttributes: parseAttributes(opts.logAttr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchLogsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return logs;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n parseAttributes,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError, parseFields } from \"../output.js\";\n\ninterface MetricsSearchOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n limit?: string;\n type: string;\n name?: string;\n service?: string;\n scope?: string;\n timeMin?: string;\n timeMax?: string;\n attr?: string[];\n resourceAttr?: string[];\n scopeAttr?: string[];\n sort?: string;\n}\n\ninterface MetricsDiscoverOptions extends ClientOptions {\n json?: boolean;\n table?: boolean;\n fields?: string;\n}\n\nexport function createMetricsCommand(): Command {\n const metrics = new Command(\"metrics\").description(\"Query metrics\");\n\n withConnectionOptions(\n metrics\n .command(\"search\")\n .description(\"Search metrics\")\n .requiredOption(\n \"--type <type>\",\n \"Metric type (Gauge|Sum|Histogram|ExponentialHistogram|Summary)\"\n )\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n .option(\"-l, --limit <n>\", \"Max results\")\n .option(\"-n, --name <name>\", \"Filter by metric name\")\n .option(\"-s, --service <name>\", \"Filter by service name\")\n .option(\"--scope <name>\", \"Filter by scope name\")\n .option(\"--time-min <ns>\", \"Min time (nanoseconds)\")\n .option(\"--time-max <ns>\", \"Max time (nanoseconds)\")\n .option(\n \"-a, --attr <key=value>\",\n \"Attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--resource-attr <key=value>\",\n \"Resource attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\n \"--scope-attr <key=value>\",\n \"Scope attribute filter (repeatable)\",\n collect,\n []\n )\n .option(\"--sort <order>\", \"Sort order (ASC|DESC)\")\n ).action(async (opts: MetricsSearchOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;\n\n const filter = {\n metricType: opts.type as\n | \"Gauge\"\n | \"Sum\"\n | \"Histogram\"\n | \"ExponentialHistogram\"\n | \"Summary\",\n metricName: opts.name,\n serviceName: opts.service,\n scopeName: opts.scope,\n timeUnixMin: opts.timeMin,\n timeUnixMax: opts.timeMax,\n attributes: parseAttributes(opts.attr),\n resourceAttributes: parseAttributes(opts.resourceAttr),\n scopeAttributes: parseAttributes(opts.scopeAttr),\n limit,\n sortOrder: opts.sort as \"ASC\" | \"DESC\" | undefined,\n };\n\n const result = await client.searchMetricsPage(filter);\n output(result.data, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n metrics\n .command(\"discover\")\n .description(\"List available metrics\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .option(\"-f, --fields <fields>\", \"Comma-separated fields to include\")\n ).action(async (opts: MetricsDiscoverOptions) => {\n const format = detectFormat(opts.json, opts.table);\n const fields = parseFields(opts.fields);\n try {\n const client = createClient(opts);\n const result = await client.discoverMetrics();\n output(result.metrics, { format, fields });\n } catch (err) {\n outputError(err, format === \"json\");\n process.exit(1);\n }\n });\n\n return metrics;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n","import { Command } from \"commander\";\nimport {\n createClient,\n resolveConnectionOpts,\n withConnectionOptions,\n type ClientOptions,\n} from \"../client.js\";\nimport { detectFormat, output, outputError } from \"../output.js\";\n\ninterface DashboardCreateOptions extends ClientOptions {\n name: string;\n treeVersion: string;\n json?: boolean;\n table?: boolean;\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n\nexport function createDashboardsCommand(): Command {\n const dashboards = new Command(\"dashboards\").description(\"Manage dashboards\");\n\n withConnectionOptions(\n dashboards\n .command(\"schema\")\n .description(\"Print UI tree schema for AI agents\")\n ).action(async (opts: ClientOptions) => {\n try {\n const { url, token } = resolveConnectionOpts(opts);\n const headers: Record<string, string> = {};\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n const response = await fetch(`${url}/dashboards/schema`, { headers });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n const schema = await response.text();\n process.stdout.write(schema);\n } catch (err) {\n outputError(err, false);\n process.exit(1);\n }\n });\n\n withConnectionOptions(\n dashboards\n .command(\"create\")\n .description(\"Create a dashboard (reads uiTree JSON from stdin)\")\n .requiredOption(\"--name <name>\", \"Dashboard name\")\n .requiredOption(\"--tree-version <semver>\", \"UI tree version (semver)\")\n .option(\"-j, --json\", \"JSON output\")\n .option(\"-t, --table\", \"Table output\")\n .addHelpText(\n \"after\",\n `\nExample:\n $ echo '{\"uiTree\":{\"root\":\"s1\",\"elements\":{\"s1\":{\"key\":\"s1\",\"type\":\"Stack\",\"props\":{\"direction\":\"vertical\",\"gap\":\"md\",\"align\":null},\"children\":[],\"parentKey\":\"\"}}}}' | kopai dashboards create --name \"My Dashboard\" --tree-version \"0.5.0\" --json`\n )\n ).action(async (opts: DashboardCreateOptions) => {\n const isJson = opts.json ?? false;\n try {\n const client = createClient(opts);\n const raw = await readStdin();\n let body: Record<string, unknown>;\n try {\n body = JSON.parse(raw) as Record<string, unknown>;\n } catch (e) {\n if (e instanceof SyntaxError) {\n process.stderr.write(`Invalid JSON input: ${e.message}\\n`);\n process.exit(2);\n }\n throw e;\n }\n\n const result = await client.createDashboard({\n name: opts.name,\n uiTreeVersion: opts.treeVersion,\n uiTree: (body.uiTree ?? body) as Record<string, unknown>,\n metadata: body.metadata as Record<string, unknown> | undefined,\n });\n\n const format = detectFormat(opts.json, opts.table);\n output(result, { format });\n } catch (err) {\n outputError(err, isJson);\n process.exit(1);\n }\n });\n\n return dashboards;\n}\n","import { Command } from \"commander\";\nimport { createInterface } from \"node:readline\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n saveConfig,\n resolveConfigPath,\n TOKEN_PREFIX_LENGTH,\n DEFAULT_URL,\n type Config,\n} from \"../config.js\";\n\nfunction readTokenFromStdin(): Promise<string> {\n return new Promise((resolve) => {\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n rl.question(\"Token: \", (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport function createLoginCommand(): Command {\n return new Command(\"login\")\n .description(\"Save an API token to .kopairc\")\n .option(\"--url <url>\", \"API base URL to save alongside token\")\n .option(\"--global\", \"Write to ~/.kopairc instead of ./.kopairc\")\n .action(async (opts: { url?: string; global?: boolean }) => {\n const token = await readTokenFromStdin();\n if (!token) {\n console.error(\"Token cannot be empty.\");\n process.exitCode = 2;\n return;\n }\n\n const updates: Partial<Config> = {\n token,\n url: opts.url ?? DEFAULT_URL,\n };\n\n const targetPath = resolveConfigPath(opts.global ?? false);\n saveConfig(updates, targetPath);\n\n // Warn if in a git repo and .kopairc is not gitignored\n if (!opts.global) {\n const gitDir = join(process.cwd(), \".git\");\n if (existsSync(gitDir)) {\n const gitignorePath = join(process.cwd(), \".gitignore\");\n let isIgnored = false;\n if (existsSync(gitignorePath)) {\n const content = readFileSync(gitignorePath, \"utf-8\");\n isIgnored = content\n .split(\"\\n\")\n .some((line) => line.trim() === \".kopairc\");\n }\n if (!isIgnored) {\n console.error(\n \"Warning: .kopairc is not in .gitignore. Add it to avoid committing secrets.\"\n );\n }\n }\n }\n\n console.log(\n `Logged in. Token: ${token.slice(0, TOKEN_PREFIX_LENGTH)}...`\n );\n });\n}\n","import { Command } from \"commander\";\nimport { removeConfigToken, resolveConfigPath } from \"../config.js\";\n\nexport function createLogoutCommand(): Command {\n return new Command(\"logout\")\n .description(\"Remove saved API token from .kopairc\")\n .option(\"--global\", \"Remove from ~/.kopairc instead of ./.kopairc\")\n .action((opts: { global?: boolean }) => {\n const targetPath = resolveConfigPath(opts.global ?? false);\n const removed = removeConfigToken(targetPath);\n\n if (removed) {\n console.log(\"Logged out.\");\n } else {\n console.log(\"Not logged in.\");\n }\n });\n}\n","import { Command } from \"commander\";\nimport { KopaiClient } from \"@kopai/sdk\";\nimport { loadConfig, TOKEN_PREFIX_LENGTH, DEFAULT_URL } from \"../config.js\";\n\nexport function createWhoamiCommand(): Command {\n return new Command(\"whoami\")\n .description(\"Show current authentication status\")\n .option(\"-c, --config <path>\", \"Config file path\")\n .action(async (opts: { config?: string }) => {\n const config = loadConfig(opts.config);\n\n if (!config.token) {\n console.log(\"Not logged in.\");\n return;\n }\n\n console.log(`Token: ${config.token.slice(0, TOKEN_PREFIX_LENGTH)}...`);\n console.log(`URL: ${config.url ?? `${DEFAULT_URL} (default)`}`);\n\n // Try to validate token against server\n try {\n const client = new KopaiClient({\n baseUrl: config.url ?? DEFAULT_URL,\n token: config.token,\n });\n await client.searchTracesPage({ limit: 1 });\n console.log(\"Token is valid.\");\n } catch (err: unknown) {\n const status =\n err && typeof err === \"object\" && \"status\" in err\n ? (err as { status: number }).status\n : undefined;\n if (status === 401) {\n console.log(\"Token is invalid or expired.\");\n } else {\n console.log(\"Could not reach server to validate token.\");\n }\n process.exitCode = 1;\n }\n });\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst CACHE_FILENAME = \"update-check.json\";\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\ninterface CacheData {\n lastCheck: number;\n latestVersion: string | null;\n}\n\ninterface CheckOptions {\n fetchFn?: typeof fetch;\n}\n\nexport function getCacheDir(): string {\n switch (process.platform) {\n case \"darwin\":\n return join(homedir(), \"Library\", \"Caches\", \"kopai\");\n case \"win32\": {\n const localAppData = process.env.LOCALAPPDATA;\n if (localAppData) return join(localAppData, \"kopai\", \"cache\");\n return join(homedir(), \"AppData\", \"Local\", \"kopai\", \"cache\");\n }\n default: {\n const xdg = process.env.XDG_CACHE_HOME;\n if (xdg) return join(xdg, \"kopai\");\n return join(homedir(), \".cache\", \"kopai\");\n }\n }\n}\n\nexport function compareVersions(current: string, latest: string): boolean {\n const parse = (v: string): [number, number, number] | null => {\n const parts = v.split(\".\").map(Number);\n if (parts.length < 3 || parts.some(isNaN)) return null;\n return [parts[0]!, parts[1]!, parts[2]!];\n };\n const c = parse(current);\n const l = parse(latest);\n if (!c || !l) return false;\n if (l[0] !== c[0]) return l[0] > c[0];\n if (l[1] !== c[1]) return l[1] > c[1];\n return l[2] > c[2];\n}\n\nexport function shouldCheck(): boolean {\n if (process.env.KOPAI_NO_UPDATE_CHECK) return false;\n if (process.env.CI || process.env.BUILD_NUMBER || process.env.RUN_ID)\n return false;\n if (!process.stderr.isTTY) return false;\n return true;\n}\n\nasync function readCache(cacheDir: string): Promise<CacheData | null> {\n try {\n const raw = await readFile(join(cacheDir, CACHE_FILENAME), \"utf-8\");\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n if (typeof parsed.lastCheck !== \"number\") return null;\n const latestVersion =\n typeof parsed.latestVersion === \"string\" && parsed.latestVersion\n ? parsed.latestVersion\n : null;\n return { lastCheck: parsed.lastCheck, latestVersion };\n } catch {\n return null;\n }\n}\n\nasync function writeCache(cacheDir: string, data: CacheData): Promise<void> {\n try {\n await mkdir(cacheDir, { recursive: true });\n await writeFile(join(cacheDir, CACHE_FILENAME), JSON.stringify(data));\n } catch {\n // ignore cache write failures\n }\n}\n\nasync function fetchLatestVersion(\n fetchFn: typeof fetch\n): Promise<string | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 3000);\n try {\n const res = await fetchFn(\"https://registry.npmjs.org/@kopai/cli/latest\", {\n signal: controller.signal,\n });\n if (!res.ok) return null;\n const data = (await res.json()) as Record<string, unknown>;\n if (typeof data?.version !== \"string\" || !data.version.trim()) return null;\n return data.version;\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction printNotice(current: string, latest: string): void {\n process.stderr.write(\n `\\n Update available: ${current} → ${latest}\\n Run: npx @kopai/cli@latest\\n Set KOPAI_NO_UPDATE_CHECK=1 to disable.\\n\\n`\n );\n}\n\nexport async function checkForUpdates(\n currentVersion: string,\n opts?: CheckOptions\n): Promise<void> {\n if (!shouldCheck()) return;\n\n const cacheDir = getCacheDir();\n const cache = await readCache(cacheDir);\n\n if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {\n if (\n cache.latestVersion &&\n compareVersions(currentVersion, cache.latestVersion)\n ) {\n printNotice(currentVersion, cache.latestVersion);\n }\n return;\n }\n\n const fetchFn = opts?.fetchFn ?? fetch;\n const latest = await fetchLatestVersion(fetchFn);\n\n await writeCache(cacheDir, { lastCheck: Date.now(), latestVersion: latest });\n\n if (latest && compareVersions(currentVersion, latest)) {\n printNotice(currentVersion, latest);\n }\n}\n","","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { createTracesCommand } from \"./commands/traces.js\";\nimport { createLogsCommand } from \"./commands/logs.js\";\nimport { createMetricsCommand } from \"./commands/metrics.js\";\nimport { createDashboardsCommand } from \"./commands/dashboards.js\";\nimport { createLoginCommand } from \"./commands/login.js\";\nimport { createLogoutCommand } from \"./commands/logout.js\";\nimport { createWhoamiCommand } from \"./commands/whoami.js\";\nimport { checkForUpdates } from \"./update-check.js\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\nconst program = new Command();\n\nprogram\n .name(\"@kopai/cli\")\n .description(\"|--k> kopai - Query OpenTelemetry data\")\n .version(pkg.version)\n .addCommand(createTracesCommand())\n .addCommand(createLogsCommand())\n .addCommand(createMetricsCommand())\n .addCommand(createDashboardsCommand())\n .addCommand(createLoginCommand())\n .addCommand(createLogoutCommand())\n .addCommand(createWhoamiCommand())\n .addHelpText(\n \"after\",\n `\nExamples:\n $ kopai traces search # localhost:8000 (default, for @kopai/app running locally)\n $ kopai traces search --url https://example.com # remote instance\n $ kopai logs search --url https://example.com --token kpi_… # with auth`\n );\n\nprogram.parse();\nvoid checkForUpdates(pkg.version);\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopai/cli",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "CLI for querying OpenTelemetry data from Kopai - traces, logs, and metrics",
5
5
  "keywords": [
6
6
  "opentelemetry",
@@ -36,11 +36,11 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "commander": "^14.0.3",
39
- "@kopai/sdk": "0.5.0",
40
- "@kopai/core": "0.7.0"
39
+ "@kopai/core": "0.8.0",
40
+ "@kopai/sdk": "0.6.0"
41
41
  },
42
42
  "devDependencies": {
43
- "tsdown": "^0.20.3",
43
+ "tsdown": "^0.21.2",
44
44
  "@kopai/tsconfig": "0.2.0"
45
45
  },
46
46
  "scripts": {