@neta-art/cohub-cli 3.1.5 → 3.2.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
@@ -121,6 +121,25 @@ cohub -s <spaceId> spaces sessions rename <sessionId> "<new title>"
121
121
 
122
122
  Use `spaces prompt --session <sessionId>` to send to a Chat.
123
123
 
124
+ ## Space turns
125
+
126
+ List recent turns across all visible Sessions in a Space:
127
+
128
+ ```bash
129
+ cohub -s <spaceId> spaces turns ls
130
+ cohub -s <spaceId> spaces turns ls --author others --limit 50 --json
131
+ cohub -s <spaceId> spaces turns ls --session <sessionId>
132
+ ```
133
+
134
+ Use `pageInfo.nextCursor` with `--cursor` to load older pages. Use a previous
135
+ `snapshotCursor` with `--after` and an explicit `--before` boundary to query
136
+ newer turns:
137
+
138
+ ```bash
139
+ cohub -s <spaceId> spaces turns ls --cursor <nextCursor> --json
140
+ cohub -s <spaceId> spaces turns ls --after <snapshotCursor> --before <snapshotAt> --json
141
+ ```
142
+
124
143
  ## Boards
125
144
 
126
145
  Board commands use the selected Space and support `-h` at every level:
@@ -19,12 +19,11 @@ export function registerSkills(program) {
19
19
  return console.log(" (empty)");
20
20
  table(result.skills.map((skill) => ({
21
21
  command: `/skill:${skill.name}`,
22
- name: skill.name,
23
- scope: skill.scope,
22
+ source: skill.source?.type === "mod" ? `mod:${skill.source.mountSlug}` : skill.scope,
24
23
  description: skill.description,
25
24
  })), [
26
25
  { key: "command", label: "Command" },
27
- { key: "scope", label: "Scope" },
26
+ { key: "source", label: "Source" },
28
27
  { key: "description", label: "Description" },
29
28
  ]);
30
29
  }
@@ -0,0 +1,29 @@
1
+ import type { SpaceTurnListItem, SpaceTurnListOptions, SpaceTurnsResponse } from "@neta-art/cohub";
2
+ import type { Command } from "commander";
3
+ import { type Row } from "../output.js";
4
+ export type SpaceTurnListCliOptions = {
5
+ author?: string;
6
+ after?: string;
7
+ before?: string;
8
+ cursor?: string;
9
+ limit?: string;
10
+ session?: string;
11
+ json?: boolean;
12
+ };
13
+ type SpaceTurnsCommandClient = {
14
+ space(spaceId: string): {
15
+ turns: {
16
+ list(options: SpaceTurnListOptions): Promise<SpaceTurnsResponse>;
17
+ };
18
+ };
19
+ };
20
+ export declare class InvalidSpaceTurnCliOptionsError extends Error {
21
+ readonly detail: string;
22
+ constructor(message: string, detail: string);
23
+ }
24
+ export declare function parseSpaceTurnListOptions(options: SpaceTurnListCliOptions): SpaceTurnListOptions;
25
+ export declare function toSpaceTurnRows(turns: SpaceTurnListItem[]): Row[];
26
+ export declare function registerSpaceTurns(spacesCmd: Command, dependencies?: {
27
+ createClient?: () => SpaceTurnsCommandClient;
28
+ }): Command;
29
+ export {};
@@ -0,0 +1,121 @@
1
+ import { createClient } from "../client.js";
2
+ import { error, handleHttp, json as outJson, jsonRequested, table, } from "../output.js";
3
+ import { resolveSpace } from "../space.js";
4
+ const SPACE_TURN_AUTHORS = ["any", "self", "others"];
5
+ export class InvalidSpaceTurnCliOptionsError extends Error {
6
+ detail;
7
+ constructor(message, detail) {
8
+ super(message);
9
+ this.detail = detail;
10
+ this.name = "InvalidSpaceTurnCliOptionsError";
11
+ }
12
+ }
13
+ function parseAuthor(value) {
14
+ if (value === undefined)
15
+ return undefined;
16
+ if (SPACE_TURN_AUTHORS.includes(value)) {
17
+ return value;
18
+ }
19
+ throw new InvalidSpaceTurnCliOptionsError("Invalid author", `Use one of: ${SPACE_TURN_AUTHORS.join(", ")}`);
20
+ }
21
+ function parseLimit(value) {
22
+ if (value === undefined)
23
+ return undefined;
24
+ if (!/^\d+$/.test(value.trim())) {
25
+ throw new InvalidSpaceTurnCliOptionsError("Invalid limit", "limit must be an integer from 1 to 100");
26
+ }
27
+ const limit = Number.parseInt(value, 10);
28
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100) {
29
+ throw new InvalidSpaceTurnCliOptionsError("Invalid limit", "limit must be an integer from 1 to 100");
30
+ }
31
+ return limit;
32
+ }
33
+ function parseBefore(value) {
34
+ if (value === undefined)
35
+ return undefined;
36
+ if (!value.trim() || Number.isNaN(new Date(value).getTime())) {
37
+ throw new InvalidSpaceTurnCliOptionsError("Invalid before", "before must be an ISO 8601 timestamp");
38
+ }
39
+ return value;
40
+ }
41
+ export function parseSpaceTurnListOptions(options) {
42
+ return {
43
+ author: parseAuthor(options.author),
44
+ after: options.after,
45
+ before: parseBefore(options.before),
46
+ cursor: options.cursor,
47
+ limit: parseLimit(options.limit),
48
+ sessionId: options.session,
49
+ };
50
+ }
51
+ export function toSpaceTurnRows(turns) {
52
+ return turns.map((turn) => ({
53
+ createdAt: turn.createdAt,
54
+ author: turn.authorProfile?.displayName ?? turn.userUuid ?? "system",
55
+ sessionTitle: turn.session.title ?? "",
56
+ sessionId: turn.session.id,
57
+ sequence: turn.sequence,
58
+ id: turn.id,
59
+ status: turn.status,
60
+ userPreview: turn.userPreview ?? "",
61
+ assistantPreview: turn.assistantPreview ?? "",
62
+ }));
63
+ }
64
+ export function registerSpaceTurns(spacesCmd, dependencies = {}) {
65
+ const turnsCmd = spacesCmd
66
+ .command("turns")
67
+ .description("Browse turns across the space")
68
+ .hook("preAction", () => {
69
+ resolveSpace(spacesCmd);
70
+ });
71
+ turnsCmd
72
+ .command("ls")
73
+ .alias("list")
74
+ .description("List recent turns across sessions")
75
+ .option("--author <any|self|others>", "Filter turns by author")
76
+ .option("--after <cursor>", "Only turns after a snapshot cursor")
77
+ .option("--before <timestamp>", "Only turns at or before an ISO 8601 timestamp")
78
+ .option("--cursor <cursor>", "Older-page cursor from a previous result")
79
+ .option("--limit <n>", "Page size, from 1 to 100")
80
+ .option("--session <id>", "Only turns from this session")
81
+ .option("--json", "Output as JSON")
82
+ .action(async (options) => {
83
+ let query;
84
+ try {
85
+ query = parseSpaceTurnListOptions(options);
86
+ }
87
+ catch (cause) {
88
+ if (cause instanceof InvalidSpaceTurnCliOptionsError) {
89
+ return error(cause.message, cause.detail);
90
+ }
91
+ throw cause;
92
+ }
93
+ const spaceId = resolveSpace(spacesCmd);
94
+ const client = dependencies.createClient?.() ?? createClient();
95
+ try {
96
+ const result = await client.space(spaceId).turns.list(query);
97
+ if (jsonRequested(options))
98
+ return outJson(result);
99
+ if (result.turns.length === 0)
100
+ return console.log(" No turns found");
101
+ table(toSpaceTurnRows(result.turns), [
102
+ { key: "createdAt", label: "Created" },
103
+ { key: "author", label: "Author" },
104
+ { key: "sessionTitle", label: "Session" },
105
+ { key: "sessionId", label: "Session ID" },
106
+ { key: "sequence", label: "Seq" },
107
+ { key: "id", label: "Turn ID" },
108
+ { key: "status", label: "Status" },
109
+ { key: "userPreview", label: "User" },
110
+ { key: "assistantPreview", label: "Assistant" },
111
+ ]);
112
+ if (result.pageInfo.hasMore && result.pageInfo.nextCursor) {
113
+ console.log(`\n More turns available - next cursor: ${result.pageInfo.nextCursor}`);
114
+ }
115
+ }
116
+ catch (cause) {
117
+ handleHttp(cause);
118
+ }
119
+ });
120
+ return turnsCmd;
121
+ }
@@ -8,6 +8,7 @@ import { createClient } from "../client.js";
8
8
  import { table, json as outJson, jsonRequested, ok, error, handleHttp } from "../output.js";
9
9
  import { resolveSpace } from "../space.js";
10
10
  import { registerSpaceCommerce } from "./space-commerce.js";
11
+ import { registerSpaceTurns } from "./space-turns.js";
11
12
  const cliEnv = resolveCohubEnvironment();
12
13
  const defaultIdleTtlSeconds = cliEnv === "prod" ? 12 * 60 * 60 : 10 * 60;
13
14
  const SPACE_ROLES = ["host", "builder", "guest"];
@@ -609,6 +610,8 @@ export function registerSpaces(program) {
609
610
  registerFiles(spacesCmd);
610
611
  // ── spaces sessions ──
611
612
  registerSessions(spacesCmd);
613
+ // ── spaces turns ──
614
+ registerSpaceTurns(spacesCmd);
612
615
  // ── spaces members ──
613
616
  registerMembers(spacesCmd);
614
617
  // ── spaces access ──
package/dist/index.js CHANGED
@@ -50,6 +50,7 @@ Common commands:
50
50
  cohub sandbox up ./my-project
51
51
  cohub search "release notes"
52
52
  cohub -s <space-id> boards inspect <board-id>
53
+ cohub -s <space-id> spaces turns ls --author others
53
54
  cohub -s <space-id> spaces sessions turns ls <session-id>
54
55
  cohub -s <space-id> spaces files ls
55
56
  cohub -s <space-id> works publish demo --file dist/index.html
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub-cli",
3
- "version": "3.1.5",
3
+ "version": "3.2.0",
4
4
  "description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -19,7 +19,7 @@
19
19
  "commander": "^15.0.0",
20
20
  "pixi.js": "^8.19.0",
21
21
  "sharp": "^0.35.3",
22
- "@neta-art/cohub": "4.2.0"
22
+ "@neta-art/cohub": "4.4.0"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"