@neta-art/cohub-cli 1.18.0 → 1.20.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.
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerMe(program: Command): void;
@@ -0,0 +1,68 @@
1
+ import { createClient } from "../client.js";
2
+ import { handleHttp, json as outJson, jsonRequested, table } from "../output.js";
3
+ function parseInteger(value, name, min) {
4
+ const parsed = Number.parseInt(value, 10);
5
+ if (!Number.isSafeInteger(parsed) || parsed < min) {
6
+ process.stderr.write(`\n ✗ Invalid ${name}\n ${name} must be an integer ≥ ${min}\n\n`);
7
+ process.exit(1);
8
+ }
9
+ return parsed;
10
+ }
11
+ export function registerMe(program) {
12
+ const meCmd = program.command("me").description("Account-level data across your spaces");
13
+ meCmd
14
+ .command("sessions")
15
+ .alias("list-sessions")
16
+ .description("List sessions you created across all spaces")
17
+ .option("--limit <n>", "Maximum number of sessions (default 20)")
18
+ .option("--cursor <cursor>", "Pagination cursor from a previous result")
19
+ .option("--json", "Output as JSON")
20
+ .action(async (opts) => {
21
+ const client = createClient();
22
+ try {
23
+ const result = await client.user.listSessions({
24
+ limit: opts.limit ? parseInteger(opts.limit, "limit", 1) : undefined,
25
+ cursor: opts.cursor ?? null,
26
+ });
27
+ if (jsonRequested(opts))
28
+ return outJson(result);
29
+ if (result.sessions.length === 0) {
30
+ console.log(" (empty)");
31
+ return;
32
+ }
33
+ table(result.sessions, [
34
+ { key: "id", label: "ID" },
35
+ { key: "spaceId", label: "Space" },
36
+ { key: "title", label: "Title" },
37
+ { key: "totalMessages", label: "Messages" },
38
+ { key: "createdAt", label: "Created" },
39
+ ]);
40
+ }
41
+ catch (e) {
42
+ handleHttp(e);
43
+ }
44
+ });
45
+ meCmd
46
+ .command("usage [days]")
47
+ .description("Your aggregated usage across all spaces (default: 30 days)")
48
+ .option("--json", "Output as JSON")
49
+ .action(async (days, opts) => {
50
+ const client = createClient();
51
+ try {
52
+ const usage = await client.user.getUsage(days ? parseInteger(days, "days", 1) : 30);
53
+ if (jsonRequested(opts))
54
+ return outJson(usage);
55
+ console.log("\n Summary:");
56
+ table([usage.summary], [
57
+ { key: "totalTokens", label: "Tokens" },
58
+ { key: "costTotal", label: "Cost ($)" },
59
+ { key: "requestCount", label: "Requests" },
60
+ { key: "successCount", label: "Success" },
61
+ { key: "errorCount", label: "Errors" },
62
+ ]);
63
+ }
64
+ catch (e) {
65
+ handleHttp(e);
66
+ }
67
+ });
68
+ }
@@ -24,6 +24,23 @@ function parseJsonObject(value, name) {
24
24
  function compactObject(input) {
25
25
  return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));
26
26
  }
27
+ function withCohubBarMeta(input) {
28
+ if (!input.hideCohubBar && !input.showCohubBar)
29
+ return input.meta;
30
+ const meta = input.meta ? { ...input.meta } : {};
31
+ const presentation = meta.presentation && typeof meta.presentation === "object" && !Array.isArray(meta.presentation)
32
+ ? { ...meta.presentation }
33
+ : {};
34
+ if (input.hideCohubBar)
35
+ presentation.hideCohubBar = true;
36
+ if (input.showCohubBar)
37
+ delete presentation.hideCohubBar;
38
+ if (Object.keys(presentation).length > 0)
39
+ meta.presentation = presentation;
40
+ else
41
+ delete meta.presentation;
42
+ return Object.keys(meta).length > 0 ? meta : null;
43
+ }
27
44
  function resolveTarget(opts) {
28
45
  const targets = [
29
46
  opts.file ? { targetType: "file", targetRef: opts.file } : null,
@@ -145,17 +162,26 @@ export function registerWorks(program) {
145
162
  .option("--draft", "Create as draft")
146
163
  .option("--disabled", "Create as disabled")
147
164
  .option("--status <status>", "Work status: draft, published, disabled")
148
- .option("--work-scope <scope>", "Scope granted to the work runtime", collectOption, [])
149
- .option("--viewer-scope <scope>", "Scope viewers may request", collectOption, [])
165
+ .option("--work-scope <scope>", "Scope granted to the work runtime (space.view, session.view, file.view, taskrun.view)", collectOption, [])
166
+ .option("--viewer-scope <scope>", "Scope viewers may request (session.prompt.readonly, session.prompt.fullaccess, generation.create, user.space.list, user.session.list, user.usage.read)", collectOption, [])
150
167
  .option("--meta <json>", "Work metadata as a JSON object")
168
+ .option("--hide-cohub-bar", "Hide the Cohub footer bar on the public work page")
169
+ .option("--show-cohub-bar", "Show the Cohub footer bar on the public work page")
151
170
  .option("--json", "Output as JSON")
152
171
  .action(async (slug, opts) => {
172
+ if (opts.hideCohubBar && opts.showCohubBar)
173
+ return error("Conflicting Cohub bar options", "Use either --hide-cohub-bar or --show-cohub-bar.");
153
174
  const target = resolveTarget(opts);
154
175
  if (!target)
155
176
  return error("Missing target", "Use one of --file, --dir, or --port.");
156
177
  const spaceId = resolveSpace(worksCmd);
157
178
  const client = createClient();
158
179
  const status = resolveStatus(opts);
180
+ const meta = withCohubBarMeta({
181
+ meta: parseJsonObject(opts.meta, "meta"),
182
+ hideCohubBar: opts.hideCohubBar,
183
+ showCohubBar: opts.showCohubBar,
184
+ });
159
185
  const input = {
160
186
  spaceId,
161
187
  slug,
@@ -164,7 +190,7 @@ export function registerWorks(program) {
164
190
  targetRef: target.targetRef,
165
191
  workScopes: opts.workScope,
166
192
  allowedViewerScopes: opts.viewerScope,
167
- meta: parseJsonObject(opts.meta, "meta"),
193
+ meta,
168
194
  };
169
195
  try {
170
196
  const result = await client.works.create(input);
@@ -188,18 +214,41 @@ export function registerWorks(program) {
188
214
  .option("--disabled", "Set status to disabled")
189
215
  .option("--status <status>", "Work status: draft, published, disabled")
190
216
  .option("--publish-version", "Force publishing a new version")
191
- .option("--work-scope <scope>", "Scope granted to the work runtime", collectOption, [])
192
- .option("--viewer-scope <scope>", "Scope viewers may request", collectOption, [])
217
+ .option("--work-scope <scope>", "Scope granted to the work runtime (space.view, session.view, file.view, taskrun.view)", collectOption, [])
218
+ .option("--viewer-scope <scope>", "Scope viewers may request (session.prompt.readonly, session.prompt.fullaccess, generation.create, user.space.list, user.session.list, user.usage.read)", collectOption, [])
193
219
  .option("--clear-work-scopes", "Clear work runtime scopes")
194
220
  .option("--clear-viewer-scopes", "Clear viewer-requestable scopes")
195
221
  .option("--meta <json>", "Work metadata as a JSON object")
222
+ .option("--hide-cohub-bar", "Hide the Cohub footer bar on the public work page")
223
+ .option("--show-cohub-bar", "Show the Cohub footer bar on the public work page")
196
224
  .option("--json", "Output as JSON")
197
225
  .action(async (id, opts) => {
226
+ if (opts.hideCohubBar && opts.showCohubBar)
227
+ return error("Conflicting Cohub bar options", "Use either --hide-cohub-bar or --show-cohub-bar.");
198
228
  const target = resolveTarget(opts);
199
229
  if (opts.clearWorkScopes && opts.workScope?.length)
200
230
  return error("Conflicting work scopes", "Use either --work-scope or --clear-work-scopes.");
201
231
  if (opts.clearViewerScopes && opts.viewerScope?.length)
202
232
  return error("Conflicting viewer scopes", "Use either --viewer-scope or --clear-viewer-scopes.");
233
+ const hasMetaUpdate = opts.meta !== undefined || opts.hideCohubBar || opts.showCohubBar;
234
+ const client = createClient();
235
+ let meta;
236
+ if (hasMetaUpdate) {
237
+ let baseMeta = opts.meta !== undefined ? parseJsonObject(opts.meta, "meta") ?? null : undefined;
238
+ if (baseMeta === undefined && (opts.hideCohubBar || opts.showCohubBar)) {
239
+ try {
240
+ baseMeta = (await client.works.get(id)).work.meta;
241
+ }
242
+ catch (e) {
243
+ handleHttp(e);
244
+ }
245
+ }
246
+ meta = withCohubBarMeta({
247
+ meta: baseMeta,
248
+ hideCohubBar: opts.hideCohubBar,
249
+ showCohubBar: opts.showCohubBar,
250
+ });
251
+ }
203
252
  const input = compactObject({
204
253
  slug: opts.slug,
205
254
  status: opts.status || opts.draft || opts.disabled ? resolveStatus(opts) : undefined,
@@ -208,11 +257,10 @@ export function registerWorks(program) {
208
257
  publishVersion: opts.publishVersion || undefined,
209
258
  workScopes: opts.clearWorkScopes ? [] : opts.workScope?.length ? opts.workScope : undefined,
210
259
  allowedViewerScopes: opts.clearViewerScopes ? [] : opts.viewerScope?.length ? opts.viewerScope : undefined,
211
- meta: opts.meta !== undefined ? parseJsonObject(opts.meta, "meta") ?? null : undefined,
260
+ meta,
212
261
  });
213
262
  if (Object.keys(input).length === 0)
214
- return error("Nothing to update", "Pass --slug, --file, --dir, --port, --status, --publish-version, --work-scope, --viewer-scope, --clear-work-scopes, --clear-viewer-scopes, or --meta.");
215
- const client = createClient();
263
+ return error("Nothing to update", "Pass --slug, --file, --dir, --port, --status, --publish-version, --work-scope, --viewer-scope, --clear-work-scopes, --clear-viewer-scopes, --meta, --hide-cohub-bar, or --show-cohub-bar.");
216
264
  try {
217
265
  const result = await client.works.update(id, input);
218
266
  if (jsonRequested(opts))
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { registerAuth } from "./commands/auth.js";
5
5
  import { registerChannels } from "./commands/channels.js";
6
6
  import { registerCronJobs } from "./commands/cron-jobs.js";
7
7
  import { registerGenerations } from "./commands/generations.js";
8
+ import { registerMe } from "./commands/me.js";
8
9
  import { registerModels } from "./commands/models.js";
9
10
  import { registerProfile } from "./commands/profile.js";
10
11
  import { registerSearch } from "./commands/search.js";
@@ -51,6 +52,7 @@ Environment:
51
52
  `);
52
53
  registerAuth(program);
53
54
  registerProfile(program);
55
+ registerMe(program);
54
56
  registerPrompt(program);
55
57
  registerSpaces(program);
56
58
  registerChannels(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub-cli",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -13,10 +13,10 @@
13
13
  "README.md"
14
14
  ],
15
15
  "dependencies": {
16
- "@neta-art/generation": "^0.1.5",
16
+ "@neta-art/generation": "^0.1.7",
17
17
  "commander": "^14.0.3",
18
18
  "sharp": "^0.34.5",
19
- "@neta-art/cohub": "1.29.0"
19
+ "@neta-art/cohub": "1.31.0"
20
20
  },
21
21
  "publishConfig": {
22
22
  "access": "public"