@neta-art/cohub-cli 8.4.1 → 9.1.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.
Files changed (70) hide show
  1. package/README.md +66 -30
  2. package/dist/board-export.d.ts +21 -36
  3. package/dist/board-export.js +163 -88
  4. package/dist/board-kernel.d.ts +2 -3
  5. package/dist/board-kernel.js +3428 -3770
  6. package/dist/board-time.d.ts +3 -0
  7. package/dist/board-time.js +28 -0
  8. package/dist/commands/apps.js +2 -2
  9. package/dist/commands/auth.js +2 -2
  10. package/dist/commands/boards/examples.d.ts +8 -2
  11. package/dist/commands/boards/examples.js +79 -411
  12. package/dist/commands/boards.d.ts +4 -9
  13. package/dist/commands/boards.js +365 -286
  14. package/dist/commands/desktop.d.ts +1 -5
  15. package/dist/commands/desktop.js +5 -16
  16. package/dist/commands/generations.js +1 -1
  17. package/dist/commands/me.js +1 -1
  18. package/dist/commands/public.js +3 -3
  19. package/dist/commands/references.js +3 -0
  20. package/dist/commands/referrals.js +2 -2
  21. package/dist/commands/run.js +3 -3
  22. package/dist/commands/runtime.d.ts +1 -1
  23. package/dist/commands/runtime.js +14 -9
  24. package/dist/commands/sandboxd-binary.d.ts +1 -1
  25. package/dist/commands/sandboxd-binary.js +2 -23
  26. package/dist/commands/search.js +15 -7
  27. package/dist/commands/space-activity.js +3 -5
  28. package/dist/commands/space-displays.d.ts +2 -0
  29. package/dist/commands/space-displays.js +347 -0
  30. package/dist/commands/space-files.d.ts +5 -0
  31. package/dist/commands/space-files.js +215 -0
  32. package/dist/commands/space-invitations.js +3 -3
  33. package/dist/commands/spaces.d.ts +3 -11
  34. package/dist/commands/spaces.js +146 -75
  35. package/dist/index.js +8 -5
  36. package/dist/runtime/launch.d.ts +2 -0
  37. package/dist/runtime/launch.js +38 -8
  38. package/dist/runtime/presentation.d.ts +1 -0
  39. package/dist/runtime/presentation.js +3 -2
  40. package/dist/runtime/supervisor.d.ts +1 -0
  41. package/dist/runtime/supervisor.js +2 -1
  42. package/dist/space-files/limit.d.ts +2 -0
  43. package/dist/space-files/limit.js +16 -0
  44. package/dist/space-files/operands.d.ts +16 -0
  45. package/dist/space-files/operands.js +33 -0
  46. package/dist/space-files/transfer.d.ts +53 -0
  47. package/dist/space-files/transfer.js +296 -0
  48. package/dist/space-files/upload.d.ts +14 -0
  49. package/dist/space-files/upload.js +53 -0
  50. package/dist/space.d.ts +18 -16
  51. package/dist/space.js +86 -39
  52. package/dist/web.d.ts +1 -0
  53. package/dist/web.js +6 -0
  54. package/package.json +2 -2
  55. package/dist/commands/board-domain.d.ts +0 -2
  56. package/dist/commands/board-domain.js +0 -16
  57. package/dist/commands/boards/animation.d.ts +0 -2
  58. package/dist/commands/boards/animation.js +0 -171
  59. package/dist/commands/boards/appearance.d.ts +0 -2
  60. package/dist/commands/boards/appearance.js +0 -127
  61. package/dist/commands/boards/batch.d.ts +0 -4
  62. package/dist/commands/boards/batch.js +0 -62
  63. package/dist/commands/boards/connections.d.ts +0 -2
  64. package/dist/commands/boards/connections.js +0 -95
  65. package/dist/commands/boards/context.d.ts +0 -31
  66. package/dist/commands/boards/context.js +0 -71
  67. package/dist/commands/boards/items.d.ts +0 -2
  68. package/dist/commands/boards/items.js +0 -184
  69. package/dist/commands/boards/transactions.d.ts +0 -12
  70. package/dist/commands/boards/transactions.js +0 -69
@@ -1,11 +1,7 @@
1
1
  import { resolveOpenSurface } from "@neta-art/cohub";
2
2
  import type { Command } from "commander";
3
3
  export { resolveOpenSurface };
4
- /**
5
- * Optional disambiguation for file:// vs app://. Unlike ordinary
6
- * Space-scoped commands, an unbound directory must not fall back to Home:
7
- * the plain target should remain eligible for App resolution.
8
- */
4
+ /** Never falls back to Home, so a plain target stays eligible for App resolution. */
9
5
  export declare function resolveOptionalSpaceId(command: Command, options?: {
10
6
  cwd?: string;
11
7
  bindingsPath?: string;
@@ -2,28 +2,17 @@ import { readFileSync } from "node:fs";
2
2
  import { HttpError, parseAppRef, resolveOpenSurface, DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, DESKTOP_COMMAND_MAX_TIMEOUT_MS, DESKTOP_COMMAND_OPEN_TIMEOUT_MS, } from "@neta-art/cohub";
3
3
  import { createClient } from "../client.js";
4
4
  import { error, handleHttp, json as outJson, jsonRequested, ok } from "../output.js";
5
- import { resolveBoundSpace } from "../space.js";
5
+ import { explicitSpace, failSpaceTarget, resolveBoundSpace, resolveSpaceRef } from "../space.js";
6
6
  import { getAppByRef } from "../app-ref.js";
7
7
  export { resolveOpenSurface };
8
8
  const FILE_SCHEME = "file://";
9
9
  const APP_SCHEME = "app://";
10
10
  const LEGACY_WORK_SCHEME = "work://";
11
- /**
12
- * Optional disambiguation for file:// vs app://. Unlike ordinary
13
- * Space-scoped commands, an unbound directory must not fall back to Home:
14
- * the plain target should remain eligible for App resolution.
15
- */
11
+ /** Never falls back to Home, so a plain target stays eligible for App resolution. */
16
12
  export async function resolveOptionalSpaceId(command, options = {}) {
17
- let current = command;
18
- while (current) {
19
- const opts = current.opts();
20
- if (typeof opts.space === "string" && opts.space.trim())
21
- return opts.space.trim();
22
- current = current.parent ?? null;
23
- }
24
- const fromEnvironment = process.env.COHUB_SPACE_ID?.trim();
25
- if (fromEnvironment)
26
- return fromEnvironment;
13
+ const explicit = explicitSpace(command);
14
+ if (explicit)
15
+ return resolveSpaceRef(explicit).catch(failSpaceTarget);
27
16
  return (await resolveBoundSpace(options)) ?? undefined;
28
17
  }
29
18
  function parseFilePath(value) {
@@ -300,7 +300,7 @@ Examples:
300
300
  `)
301
301
  .action(async (prompt, opts) => {
302
302
  try {
303
- const spaceId = await resolveSpace(program);
303
+ const spaceId = await resolveSpace(program, { home: true });
304
304
  const sessionId = envValue("COHUB_SESSION_ID");
305
305
  const inputs = await Promise.all([
306
306
  ...opts.image.map((value) => parseMediaInput("image", value)),
@@ -71,7 +71,7 @@ export function registerMe(program) {
71
71
  if (jsonRequested(opts))
72
72
  return outJson(activity);
73
73
  console.log(`\n ${formatLocalDateTime(activity.range.from)} → ${formatLocalDateTime(activity.range.to)}`);
74
- table([activity.summary], [
74
+ table([activity.totals], [
75
75
  { key: "totalTokens", label: "Tokens" },
76
76
  { key: "costTotal", label: "Cost ($)" },
77
77
  { key: "requestCount", label: "Requests" },
@@ -182,7 +182,7 @@ function publicUrlPrefix(destination, entry) {
182
182
  }
183
183
  async function uploadPublic(command, source, destination, opts, deps) {
184
184
  const client = deps.createClient?.() ?? createClient();
185
- const spaceId = await resolveSpace(command);
185
+ const spaceId = await resolveSpace(command, { home: true });
186
186
  try {
187
187
  const upload = await collectPublicUpload(source, destination);
188
188
  const plan = await client.space(spaceId).publicFiles.createUpload({
@@ -247,7 +247,7 @@ async function uploadPublic(command, source, destination, opts, deps) {
247
247
  async function listPublic(command, path, opts, deps) {
248
248
  const client = deps.createClient?.() ?? createClient();
249
249
  try {
250
- const publicFiles = client.space(await resolveSpace(command)).publicFiles;
250
+ const publicFiles = client.space(await resolveSpace(command, { home: true })).publicFiles;
251
251
  const entries = [];
252
252
  let cursor;
253
253
  do {
@@ -274,7 +274,7 @@ async function listPublic(command, path, opts, deps) {
274
274
  async function printPublicUrl(command, path, deps) {
275
275
  const client = deps.createClient?.() ?? createClient();
276
276
  try {
277
- const result = await client.space(await resolveSpace(command)).publicFiles.url(path);
277
+ const result = await client.space(await resolveSpace(command, { home: true })).publicFiles.url(path);
278
278
  console.log(result.url);
279
279
  }
280
280
  catch (exception) {
@@ -14,6 +14,7 @@ const REFERENCE_KINDS = new Set([
14
14
  "mod",
15
15
  "mention",
16
16
  "tool_call",
17
+ "turn_trigger",
17
18
  "agent_tool_file_read",
18
19
  "agent_tool_file_write",
19
20
  "agent_tool_file_edit",
@@ -53,6 +54,7 @@ function clampNumber(value, fallback, min, max) {
53
54
  const KINDS_HELP = `Kinds:
54
55
  structural: session_fork, space_fork, checkpoint_fork, mod
55
56
  content: mention, tool_call
57
+ causality: turn_trigger
56
58
  file access: agent_tool_file_read, agent_tool_file_write, agent_tool_file_edit,
57
59
  agent_tool_file_ls, agent_tool_file_find, agent_tool_file_grep`;
58
60
  export function registerReferences(program) {
@@ -75,6 +77,7 @@ ${KINDS_HELP}
75
77
 
76
78
  Examples:
77
79
  cohub references query turn:<uuid> --kinds agent_tool_file_read,agent_tool_file_write
80
+ cohub references query turn:<uuid> --direction out --kinds turn_trigger
78
81
  cohub references query session:<uuid> --json
79
82
  cohub references query checkpoint:<uuid> --direction out
80
83
  cohub references query space:<uuid> --direction in --kinds mention,tool_call
@@ -1,8 +1,8 @@
1
1
  import { createClient } from "../client.js";
2
2
  import { error, handleHttp, json as outJson, jsonRequested, ok, table } from "../output.js";
3
+ import { webUrl } from "../web.js";
3
4
  function referralUrl(code) {
4
- const origin = process.env.COHUB_WEB_URL?.replace(/\/+$/, "") ?? "https://cohub.live";
5
- return `${origin}/referrals/${code}`;
5
+ return webUrl(`/referrals/${code}`);
6
6
  }
7
7
  async function confirmRotate(opts) {
8
8
  if (opts.yes)
@@ -110,8 +110,8 @@ export async function parseRunCliOptions(argv, spaceOptions = {}) {
110
110
  export function printRunHelp() {
111
111
  process.stdout.write(`
112
112
  Usage:
113
- cohub [-s <spaceId>] run [options] -- <shell command>
114
- cohub [-s <spaceId>] run --command <shell command>
113
+ cohub [-s <space>] run [options] -- <shell command>
114
+ cohub [-s <space>] run --command <shell command>
115
115
 
116
116
  Options:
117
117
  -c, --command <command> Shell command to execute in the space workspace
@@ -125,7 +125,7 @@ Examples:
125
125
  cohub -s <spaceId> run -- git status -sb
126
126
 
127
127
  Notes:
128
- - Without -s or COHUB_SPACE_ID, the command uses the current directory Runtime binding, then Home.
128
+ - Without -s or COHUB_SPACE_ID, the command uses the current directory Runtime binding; it never falls back to Home.
129
129
  - Use --command for commands that contain leading flags, or use -- before the shell command.
130
130
  - The command runs in /workspace.
131
131
  `);
@@ -1,3 +1,3 @@
1
1
  import type { Command } from "commander";
2
- export { resolveLocalSpaceName, parseRuntimeHarnesses } from "../runtime/launch.js";
2
+ export { resolveLocalSpaceName, parseRuntimeDisplay, parseRuntimeHarnesses } from "../runtime/launch.js";
3
3
  export declare function registerRuntime(program: Command): void;
@@ -12,7 +12,7 @@ import { installPiExtension, piExtensionState } from "../runtime/native/install.
12
12
  import { controlRuntimeInstance, requestRuntimeInstance, runtimeInstanceDirectory } from "../runtime/instance.js";
13
13
  import { atLeastLevel, diagnosticLevels, formatDiagnostic, formatImportProgress, formatNativeSync, printRuntimeSummary } from "../runtime/presentation.js";
14
14
  import { readRuntimeDiagnosticEvents, RuntimeDiagnosticReader, runtimeDiagnosticsDirectory, serializeDiagnosticError } from "../runtime/diagnostics.js";
15
- export { resolveLocalSpaceName, parseRuntimeHarnesses } from "../runtime/launch.js";
15
+ export { resolveLocalSpaceName, parseRuntimeDisplay, parseRuntimeHarnesses } from "../runtime/launch.js";
16
16
  const reportFailure = (cause) => {
17
17
  process.stderr.write(`Runtime failed: ${serializeDiagnosticError(cause).message}\n`);
18
18
  process.exitCode = 1;
@@ -34,14 +34,16 @@ export function registerRuntime(program) {
34
34
  const runtime = program.command("runtime").description("Connect a local workspace");
35
35
  runtime.command("up [dir]")
36
36
  .description("Connect local Harnesses and files")
37
- .option("-s, --space <id>", "Target Space")
37
+ .option("-s, --space <space>", "Target Space: ID, slug, or username/slug")
38
38
  .option("-n, --new", "Create a new Space")
39
39
  .option("--name <name>", "New Space name")
40
40
  .option("-d, --detach", "Run in the background")
41
41
  .option("--harness <name>", "Pi or Codex; repeatable", (value, previous) => [...previous, value], [])
42
42
  .option("--pi <path>", "Pi executable")
43
43
  .option("--codex <path>", "Codex executable")
44
- .option("-y, --yes", "Accept defaults and authorize local execution and native sync")
44
+ .option("--display [screen]", "Share a screen (default: auto when available), or xvfb[:WIDTHxHEIGHT] for a virtual one")
45
+ .option("--no-display", "Disable screen sharing and skip its confirmation")
46
+ .option("-y, --yes", "Accept defaults and authorize local execution, native sync, and screen sharing")
45
47
  .option("--verbose", "Show diagnostic details")
46
48
  .option("--json", "JSON output")
47
49
  .action(async (dir, options) => {
@@ -54,7 +56,7 @@ export function registerRuntime(program) {
54
56
  });
55
57
  runtime.command("attach")
56
58
  .description("Connect native harnesses to Cohub: install the Pi extension")
57
- .option("-s, --space <id>", "Target Space")
59
+ .option("-s, --space <space>", "Target Space: ID, slug, or username/slug")
58
60
  .option("--harness <name>", "Pi; repeatable", (value, previous) => [...previous, value], [])
59
61
  .option("--json", "JSON output")
60
62
  .action(async (options) => {
@@ -81,7 +83,7 @@ export function registerRuntime(program) {
81
83
  });
82
84
  runtime.command("detach")
83
85
  .description("Pause native sync; keep all data")
84
- .option("-s, --space <id>", "Target Space")
86
+ .option("-s, --space <space>", "Target Space: ID, slug, or username/slug")
85
87
  .option("--harness <name>", "Pi or Codex; repeatable", (value, previous) => [...previous, value], [])
86
88
  .option("--json", "JSON output")
87
89
  .action(async (options) => {
@@ -110,7 +112,7 @@ export function registerRuntime(program) {
110
112
  });
111
113
  runtime.command("import [dir]")
112
114
  .description("Import earlier local conversations, newest first")
113
- .option("-s, --space <id>", "Target Space")
115
+ .option("-s, --space <space>", "Target Space: ID, slug, or username/slug")
114
116
  .option("--harness <name>", "Filter by harness; repeatable", (value, previous) => [...previous, value], [])
115
117
  .option("--session <id>", "Filter by native session ID")
116
118
  .option("--concurrency <count>", `Conversations read in parallel, 1 to ${MAX_IMPORT_CONCURRENCY}`, String(DEFAULT_IMPORT_CONCURRENCY))
@@ -207,7 +209,7 @@ export function registerRuntime(program) {
207
209
  }
208
210
  });
209
211
  runtime.command("status").description("Local and server status")
210
- .option("-s, --space <id>", "Target Space")
212
+ .option("-s, --space <space>", "Target Space: ID, slug, or username/slug")
211
213
  .option("--json", "JSON output")
212
214
  .action(async (options) => {
213
215
  try {
@@ -232,6 +234,9 @@ export function registerRuntime(program) {
232
234
  else
233
235
  process.stdout.write(`Local process Not running\nSpace ${spaceId}\nLogs ${result.diagnosticsPath}\n`);
234
236
  process.stdout.write(`Server ${remote.error ? `Unknown — ${remote.error}` : remote.value?.online ? "Harness connected" : "Offline"}\nArchives ${pendingLocalArchives} pending · ${failedLocalArchives} failed\n`);
237
+ const displays = remote.value?.displays ?? [];
238
+ if (displays.length)
239
+ process.stdout.write(`Displays ${displays.map((display) => `${display.name || display.id} ${display.width}x${display.height}${display.needs?.length ? ` (needs ${display.needs.join(", ")})` : display.input ? "" : " (view only)"}`).join(" · ")}\n`);
235
240
  process.stdout.write(formatNativeSync(nativeSync.config, local?.native, nativeSync.error));
236
241
  }
237
242
  }
@@ -240,7 +245,7 @@ export function registerRuntime(program) {
240
245
  }
241
246
  });
242
247
  runtime.command("down").description("Stop this local Runtime; retain all data")
243
- .option("-s, --space <id>", "Target Space")
248
+ .option("-s, --space <space>", "Target Space: ID, slug, or username/slug")
244
249
  .option("-y, --yes", "Stop even with unconfirmed executions")
245
250
  .option("--json", "JSON output")
246
251
  .action(async (options) => {
@@ -278,7 +283,7 @@ export function registerRuntime(program) {
278
283
  }
279
284
  });
280
285
  runtime.command("logs").description("Read local Runtime diagnostics")
281
- .option("-s, --space <id>", "Target Space")
286
+ .option("-s, --space <space>", "Target Space: ID, slug, or username/slug")
282
287
  .option("-l, --limit <count>", "Number of events", "100")
283
288
  .option("--level <level>", "Minimum level: debug, info, warn, error", "info")
284
289
  .option("-f, --follow", "Keep watching")
@@ -1,4 +1,4 @@
1
- export declare const SANDBOXD_VERSION = "v2.55.0";
1
+ export declare const SANDBOXD_VERSION = "v2.61.1";
2
2
  export declare class SandboxdDownloadError extends Error {
3
3
  name: string;
4
4
  }
@@ -6,29 +6,8 @@ import { homedir, tmpdir } from "node:os";
6
6
  import { dirname, join } from "node:path";
7
7
  import { pipeline } from "node:stream/promises";
8
8
  import { Readable } from "node:stream";
9
- // The sandboxd binary version is pinned independently of the CLI package: it
10
- // only needs to change when apps/sandbox changes, and the agent-sandbox wire
11
- // protocol ("1") guarantees backward compatibility.
12
- //
13
- // IMPORTANT: this must point at a tag whose CDN artifacts have already been
14
- // published by .github/workflows/sandbox-binaries-build.yml. Only bump it AFTER
15
- // that tag's publish-cdn job has succeeded, otherwise `runtime up` 404s on the
16
- // default download.
17
- //
18
- // v2.54.0 is the first published tag with the private managed Runtime control
19
- // pipe (`COHUB_RUNTIME_MANAGED` over fd 3), so `runtime up` reads connection
20
- // state from the daemon instead of polling the API every five seconds. It also
21
- // carries the optional workspace-search runner download. v2.53.1 already has
22
- // the native FSEvents backends and the `runtimeId` control frame, and older
23
- // releases stay usable through the compatibility readiness/restart path.
24
- //
25
- // v2.54.1 keeps the same wire protocol and adds relay diagnostics: data-channel
26
- // pairing outlives the runner's dial timeout, dial failures distinguish a
27
- // timeout from an explicit rejection, and teardown-time websocket write
28
- // failures log at debug instead of warn. v2.55.0 republishes that compatible
29
- // runner alongside the matching platform release; no new runner capability is
30
- // required.
31
- export const SANDBOXD_VERSION = "v2.55.0";
9
+ // Pin only after all platform artifacts are published to the public CDN.
10
+ export const SANDBOXD_VERSION = "v2.61.1";
32
11
  const BINARY_NAME = "cohub-sandboxd";
33
12
  // Public CDN prefix hosting the release archives (the repo is private, so the
34
13
  // GitHub Release assets are not publicly downloadable). Overridable for staging
@@ -4,7 +4,8 @@ import { formatLocalDateTime, table, json as outJson, jsonRequested, error, hand
4
4
  const DEFAULT_LIMIT = 20;
5
5
  const MAX_TITLE_LENGTH = 72;
6
6
  const MAX_CONTEXT_LENGTH = 42;
7
- const SEARCH_TYPES = new Set(["turn", "session", "space", "label"]);
7
+ const MAX_MATCH_LENGTH = 60;
8
+ const SEARCH_TYPES = new Set(["chat", "space", "label"]);
8
9
  function clampLimit(value) {
9
10
  const parsed = Number(value ?? DEFAULT_LIMIT);
10
11
  if (!Number.isFinite(parsed))
@@ -17,7 +18,14 @@ function contextFor(item) {
17
18
  return `@${owner.username}`;
18
19
  if (owner?.displayName)
19
20
  return owner.displayName;
20
- return item.href;
21
+ if (item.type === "label")
22
+ return item.labelRef ?? "";
23
+ return item.spaceName ?? "";
24
+ }
25
+ function matchFor(item) {
26
+ if (item.hit)
27
+ return item.hit.excerpt;
28
+ return item.matchedField;
21
29
  }
22
30
  function parseTypes(value) {
23
31
  const types = value
@@ -41,9 +49,9 @@ function parseSearchInput(opts) {
41
49
  function rowsFor(items) {
42
50
  return items.map((item) => ({
43
51
  type: item.type,
44
- title: truncateText(item.title, MAX_TITLE_LENGTH),
52
+ title: truncateText(item.title || "New chat", MAX_TITLE_LENGTH),
45
53
  context: truncateText(contextFor(item), MAX_CONTEXT_LENGTH),
46
- match: item.matchedField,
54
+ match: truncateText(matchFor(item), MAX_MATCH_LENGTH),
47
55
  updated: item.updatedAt ? formatLocalDateTime(item.updatedAt).slice(0, 10) : "",
48
56
  href: item.href,
49
57
  }));
@@ -51,10 +59,10 @@ function rowsFor(items) {
51
59
  export function registerSearch(program) {
52
60
  program
53
61
  .command("search")
54
- .description("Search spaces, chats, turns, and label items")
62
+ .description("Search spaces, chats, and label items")
55
63
  .argument("[query]", "Search query")
56
64
  .option("--limit <n>", "Maximum results, 1-50", String(DEFAULT_LIMIT))
57
- .option("--types <types>", "Comma-separated result types: turn,session,space,label")
65
+ .option("--types <types>", "Comma-separated result types: chat,space,label")
58
66
  .option("--space-id <id>", "Limit search to a space")
59
67
  .option("--label-ref <ref>", "Search items under an exact label ref")
60
68
  .option("--json", "Output as JSON")
@@ -63,7 +71,7 @@ export function registerSearch(program) {
63
71
  Examples:
64
72
  cohub search "release notes"
65
73
  cohub search "failing tests" --limit 10
66
- cohub search "bug" --types turn,session --space-id <spaceId>
74
+ cohub search "bug" --types chat --space-id <spaceId>
67
75
  cohub search --types label --label-ref bug
68
76
  cohub search "login" --types label --label-ref bug
69
77
  cohub search "design review" --json
@@ -63,13 +63,11 @@ export function toAppRankingRows(apps) {
63
63
  id: app.appId,
64
64
  }));
65
65
  }
66
- function hasCost(activity) {
67
- return activity.summary.costTotal !== 0;
68
- }
69
66
  export function printActivityReport(activity) {
70
- const showCost = hasCost(activity);
67
+ const { totals } = activity;
68
+ const showCost = totals.costTotal !== 0;
71
69
  console.log(`\n Summary (last ${activity.days} days):`);
72
- table([activity.summary], [
70
+ table([totals], [
73
71
  { key: "totalTokens", label: "Tokens", format: formatNumber },
74
72
  { key: "requestCount", label: "Requests", format: formatNumber },
75
73
  ...(showCost ? [{ key: "costTotal", label: "Cost", format: formatCost }] : []),
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerSpaceDisplays(spacesCmd: Command): void;