@kopai/cli 0.8.1 → 0.9.0

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/README.md CHANGED
@@ -137,6 +137,9 @@ Search metrics by type.
137
137
  kopai metrics search --type Gauge --name cpu_usage
138
138
  kopai metrics search --type Histogram --service my-api
139
139
  kopai metrics search --type Sum --attr "host=server1"
140
+
141
+ # Aggregate: total bytes ingested grouped by signal
142
+ kopai metrics search --type Sum --name kopai.ingestion.bytes --aggregate sum --group-by signal
140
143
  ```
141
144
 
142
145
  **Types:** Gauge, Sum, Histogram, ExponentialHistogram, Summary
@@ -151,6 +154,8 @@ kopai metrics search --type Sum --attr "host=server1"
151
154
  - `--resource-attr <key=value>` - repeatable
152
155
  - `--scope-attr <key=value>` - repeatable
153
156
  - `--sort` - ASC or DESC
157
+ - `--aggregate <fn>` - aggregation function (sum, avg, min, max, count). Gauge/Sum only
158
+ - `--group-by <attr>` - group by attribute key (repeatable, requires --aggregate)
154
159
 
155
160
  **Fields:** TimeUnix, StartTimeUnix, MetricType, MetricName, MetricDescription, MetricUnit, ServiceName, Value, Count, Sum, Min, Max, Attributes, ResourceAttributes, ScopeName, ScopeAttributes, Exemplars, BucketCounts, ExplicitBounds
156
161
 
package/dist/index.mjs CHANGED
@@ -1,16 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { Command } from "commander";
2
+ import { Command, InvalidArgumentError } from "commander";
3
3
  import { KopaiClient } from "@kopai/sdk";
4
4
  import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
5
5
  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,12 +246,11 @@ 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() {
260
252
  const metrics = new Command("metrics").description("Query metrics");
261
- withConnectionOptions(metrics.command("search").description("Search metrics").requiredOption("--type <type>", "Metric type (Gauge|Sum|Histogram|ExponentialHistogram|Summary)").option("-j, --json", "JSON output").option("-t, --table", "Table output").option("-f, --fields <fields>", "Comma-separated fields to include").option("-l, --limit <n>", "Max results").option("-n, --name <name>", "Filter by metric name").option("-s, --service <name>", "Filter by service name").option("--scope <name>", "Filter by scope name").option("--time-min <ns>", "Min time (nanoseconds)").option("--time-max <ns>", "Max time (nanoseconds)").option("-a, --attr <key=value>", "Attribute filter (repeatable)", collect, []).option("--resource-attr <key=value>", "Resource attribute filter (repeatable)", collect, []).option("--scope-attr <key=value>", "Scope attribute filter (repeatable)", collect, []).option("--sort <order>", "Sort order (ASC|DESC)")).action(async (opts) => {
253
+ withConnectionOptions(metrics.command("search").description("Search metrics").requiredOption("--type <type>", "Metric type (Gauge|Sum|Histogram|ExponentialHistogram|Summary)").option("-j, --json", "JSON output").option("-t, --table", "Table output").option("-f, --fields <fields>", "Comma-separated fields to include").option("-l, --limit <n>", "Max results").option("-n, --name <name>", "Filter by metric name").option("-s, --service <name>", "Filter by service name").option("--scope <name>", "Filter by scope name").option("--time-min <ns>", "Min time (nanoseconds)").option("--time-max <ns>", "Max time (nanoseconds)").option("-a, --attr <key=value>", "Attribute filter (repeatable)", collect, []).option("--resource-attr <key=value>", "Resource attribute filter (repeatable)", collect, []).option("--scope-attr <key=value>", "Scope attribute filter (repeatable)", collect, []).option("--sort <order>", "Sort order (ASC|DESC)").option("--aggregate <fn>", "Aggregation function (sum|avg|min|max|count)").option("--group-by <attr>", "Group by attribute key (repeatable)", collect, [])).action(async (opts) => {
262
254
  const format = detectFormat(opts.json, opts.table);
263
255
  const fields = parseFields(opts.fields);
264
256
  try {
@@ -275,9 +267,14 @@ function createMetricsCommand() {
275
267
  resourceAttributes: parseAttributes(opts.resourceAttr),
276
268
  scopeAttributes: parseAttributes(opts.scopeAttr),
277
269
  limit,
278
- sortOrder: opts.sort
270
+ sortOrder: opts.sort,
271
+ aggregate: toAggregateFn(opts.aggregate),
272
+ groupBy: opts.groupBy && opts.groupBy.length > 0 ? opts.groupBy : void 0
279
273
  };
280
- output((await client.searchMetricsPage(filter)).data, {
274
+ output((filter.aggregate ? await client.searchAggregatedMetrics({
275
+ ...filter,
276
+ aggregate: filter.aggregate
277
+ }) : await client.searchMetricsPage(filter)).data, {
281
278
  format,
282
279
  fields
283
280
  });
@@ -304,7 +301,14 @@ function createMetricsCommand() {
304
301
  function collect(value, previous) {
305
302
  return previous.concat([value]);
306
303
  }
307
-
304
+ function isAggregateFn(value) {
305
+ return value === "sum" || value === "avg" || value === "min" || value === "max" || value === "count";
306
+ }
307
+ function toAggregateFn(value) {
308
+ if (value === void 0) return void 0;
309
+ if (isAggregateFn(value)) return value;
310
+ throw new InvalidArgumentError(`Invalid aggregate function: ${value}`);
311
+ }
308
312
  //#endregion
309
313
  //#region src/commands/dashboards.ts
310
314
  async function readStdin() {
@@ -358,7 +362,6 @@ Example:
358
362
  });
359
363
  return dashboards;
360
364
  }
361
-
362
365
  //#endregion
363
366
  //#region src/commands/login.ts
364
367
  function readTokenFromStdin() {
@@ -383,7 +386,7 @@ function createLoginCommand() {
383
386
  }
384
387
  saveConfig({
385
388
  token,
386
- url: opts.url ?? DEFAULT_URL$1
389
+ url: opts.url ?? "http://localhost:8000"
387
390
  }, resolveConfigPath(opts.global ?? false));
388
391
  if (!opts.global) {
389
392
  if (existsSync(join(process.cwd(), ".git"))) {
@@ -393,10 +396,9 @@ function createLoginCommand() {
393
396
  if (!isIgnored) console.error("Warning: .kopairc is not in .gitignore. Add it to avoid committing secrets.");
394
397
  }
395
398
  }
396
- console.log(`Logged in. Token: ${token.slice(0, TOKEN_PREFIX_LENGTH)}...`);
399
+ console.log(`Logged in. Token: ${token.slice(0, 10)}...`);
397
400
  });
398
401
  }
399
-
400
402
  //#endregion
401
403
  //#region src/commands/logout.ts
402
404
  function createLogoutCommand() {
@@ -405,7 +407,6 @@ function createLogoutCommand() {
405
407
  else console.log("Not logged in.");
406
408
  });
407
409
  }
408
-
409
410
  //#endregion
410
411
  //#region src/commands/whoami.ts
411
412
  function createWhoamiCommand() {
@@ -415,11 +416,11 @@ function createWhoamiCommand() {
415
416
  console.log("Not logged in.");
416
417
  return;
417
418
  }
418
- console.log(`Token: ${config.token.slice(0, TOKEN_PREFIX_LENGTH)}...`);
419
- console.log(`URL: ${config.url ?? `${DEFAULT_URL$1} (default)`}`);
419
+ console.log(`Token: ${config.token.slice(0, 10)}...`);
420
+ console.log(`URL: ${config.url ?? `http://localhost:8000 (default)`}`);
420
421
  try {
421
422
  await new KopaiClient({
422
- baseUrl: config.url ?? DEFAULT_URL$1,
423
+ baseUrl: config.url ?? "http://localhost:8000",
423
424
  token: config.token
424
425
  }).searchTracesPage({ limit: 1 });
425
426
  console.log("Token is valid.");
@@ -430,7 +431,6 @@ function createWhoamiCommand() {
430
431
  }
431
432
  });
432
433
  }
433
-
434
434
  //#endregion
435
435
  //#region src/update-check.ts
436
436
  const CACHE_FILENAME = "update-check.json";
@@ -526,11 +526,9 @@ async function checkForUpdates(currentVersion, opts) {
526
526
  });
527
527
  if (latest && compareVersions(currentVersion, latest)) printNotice(currentVersion, latest);
528
528
  }
529
-
530
529
  //#endregion
531
530
  //#region package.json
532
- var version = "0.8.1";
533
-
531
+ var version = "0.9.0";
534
532
  //#endregion
535
533
  //#region src/index.ts
536
534
  const program = new Command();
@@ -541,7 +539,7 @@ Examples:
541
539
  $ kopai logs search --url https://example.com --token kpi_… # with auth`);
542
540
  program.parse();
543
541
  checkForUpdates(version);
544
-
545
542
  //#endregion
546
- export { };
543
+ export {};
544
+
547
545
  //# 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, InvalidArgumentError } 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 aggregate?: string;\n groupBy?: 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 .option(\n \"--aggregate <fn>\",\n \"Aggregation function (sum|avg|min|max|count)\"\n )\n .option(\n \"--group-by <attr>\",\n \"Group by attribute key (repeatable)\",\n collect,\n []\n )\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 aggregate: toAggregateFn(opts.aggregate),\n groupBy:\n opts.groupBy && opts.groupBy.length > 0 ? opts.groupBy : undefined,\n };\n\n const result = filter.aggregate\n ? await client.searchAggregatedMetrics({\n ...filter,\n aggregate: filter.aggregate,\n })\n : 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\ntype AggregateFn = \"sum\" | \"avg\" | \"min\" | \"max\" | \"count\";\n\nfunction isAggregateFn(value: string): value is AggregateFn {\n return (\n value === \"sum\" ||\n value === \"avg\" ||\n value === \"min\" ||\n value === \"max\" ||\n value === \"count\"\n );\n}\n\nfunction toAggregateFn(value: string | undefined): AggregateFn | undefined {\n if (value === undefined) return undefined;\n if (isAggregateFn(value)) return value;\n throw new InvalidArgumentError(`Invalid aggregate function: ${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.9.0",
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.9.0",
40
+ "@kopai/sdk": "0.7.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": {