@neta-art/cohub-cli 3.1.6 → 3.3.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 +22 -0
- package/dist/commands/space-invitations.d.ts +28 -0
- package/dist/commands/space-invitations.js +168 -0
- package/dist/commands/space-turns.d.ts +29 -0
- package/dist/commands/space-turns.js +121 -0
- package/dist/commands/spaces.js +5 -0
- package/dist/index.js +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -65,6 +65,9 @@ COHUB_SPACE_ID=<spaceId> cohub spaces get
|
|
|
65
65
|
cohub spaces create --name "<name>" --description "<description>" --json
|
|
66
66
|
cohub spaces update <spaceId> --slug <space-slug>
|
|
67
67
|
cohub spaces rename <spaceId> "<new name>"
|
|
68
|
+
cohub -s <spaceId> spaces invites create --role builder --days 7
|
|
69
|
+
cohub -s <spaceId> spaces invites ls
|
|
70
|
+
cohub -s <spaceId> spaces invites revoke <code> --yes
|
|
68
71
|
cohub -s <spaceId> run -- git status
|
|
69
72
|
```
|
|
70
73
|
|
|
@@ -121,6 +124,25 @@ cohub -s <spaceId> spaces sessions rename <sessionId> "<new title>"
|
|
|
121
124
|
|
|
122
125
|
Use `spaces prompt --session <sessionId>` to send to a Chat.
|
|
123
126
|
|
|
127
|
+
## Space turns
|
|
128
|
+
|
|
129
|
+
List recent turns across all visible Sessions in a Space:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
cohub -s <spaceId> spaces turns ls
|
|
133
|
+
cohub -s <spaceId> spaces turns ls --author others --limit 50 --json
|
|
134
|
+
cohub -s <spaceId> spaces turns ls --session <sessionId>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use `pageInfo.nextCursor` with `--cursor` to load older pages. Use a previous
|
|
138
|
+
`snapshotCursor` with `--after` and an explicit `--before` boundary to query
|
|
139
|
+
newer turns:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
cohub -s <spaceId> spaces turns ls --cursor <nextCursor> --json
|
|
143
|
+
cohub -s <spaceId> spaces turns ls --after <snapshotCursor> --before <snapshotAt> --json
|
|
144
|
+
```
|
|
145
|
+
|
|
124
146
|
## Boards
|
|
125
147
|
|
|
126
148
|
Board commands use the selected Space and support `-h` at every level:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type CreateInvitationInput, type CreateInvitationResponse, type SpaceInvitationListResponse } from "@neta-art/cohub";
|
|
2
|
+
import type { Command } from "commander";
|
|
3
|
+
export type SpaceInvitationCreateCliOptions = {
|
|
4
|
+
role?: string;
|
|
5
|
+
days?: string;
|
|
6
|
+
maxUses?: string;
|
|
7
|
+
json?: boolean;
|
|
8
|
+
};
|
|
9
|
+
type SpaceInvitationCommandClient = {
|
|
10
|
+
space(spaceId: string): {
|
|
11
|
+
invitations: {
|
|
12
|
+
list(): Promise<SpaceInvitationListResponse>;
|
|
13
|
+
create(input: CreateInvitationInput): Promise<CreateInvitationResponse>;
|
|
14
|
+
revoke(token: string): Promise<{
|
|
15
|
+
ok: true;
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare class InvalidSpaceInvitationCliOptionsError extends Error {
|
|
21
|
+
readonly detail: string;
|
|
22
|
+
constructor(message: string, detail: string);
|
|
23
|
+
}
|
|
24
|
+
export declare function parseSpaceInvitationCreateOptions(options: SpaceInvitationCreateCliOptions): Required<Pick<CreateInvitationInput, "role" | "ttlSeconds" | "maxUses">>;
|
|
25
|
+
export declare function registerSpaceInvitations(spacesCommand: Command, dependencies?: {
|
|
26
|
+
createClient: () => SpaceInvitationCommandClient;
|
|
27
|
+
}): Command;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { buildSpaceInvitePath, } from "@neta-art/cohub";
|
|
2
|
+
import { createClient } from "../client.js";
|
|
3
|
+
import { error, handleHttp, json as outJson, jsonRequested, ok, table, } from "../output.js";
|
|
4
|
+
import { resolveSpace } from "../space.js";
|
|
5
|
+
const SPACE_ROLES = ["host", "builder", "guest"];
|
|
6
|
+
const DEFAULT_DAYS = 7;
|
|
7
|
+
const MAX_DAYS = 30;
|
|
8
|
+
const MAX_USES = 10_000;
|
|
9
|
+
export class InvalidSpaceInvitationCliOptionsError extends Error {
|
|
10
|
+
detail;
|
|
11
|
+
constructor(message, detail) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.detail = detail;
|
|
14
|
+
this.name = "InvalidSpaceInvitationCliOptionsError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function parseInteger(value, label, min, max) {
|
|
18
|
+
if (!/^\d+$/.test(value.trim())) {
|
|
19
|
+
throw new InvalidSpaceInvitationCliOptionsError(`Invalid ${label}`, `${label} must be an integer from ${min} to ${max}`);
|
|
20
|
+
}
|
|
21
|
+
const parsed = Number.parseInt(value, 10);
|
|
22
|
+
if (!Number.isSafeInteger(parsed) || parsed < min || parsed > max) {
|
|
23
|
+
throw new InvalidSpaceInvitationCliOptionsError(`Invalid ${label}`, `${label} must be an integer from ${min} to ${max}`);
|
|
24
|
+
}
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
27
|
+
export function parseSpaceInvitationCreateOptions(options) {
|
|
28
|
+
const role = (options.role ?? "builder");
|
|
29
|
+
if (!SPACE_ROLES.includes(role)) {
|
|
30
|
+
throw new InvalidSpaceInvitationCliOptionsError("Invalid role", `Use one of: ${SPACE_ROLES.join(", ")}`);
|
|
31
|
+
}
|
|
32
|
+
const days = parseInteger(options.days ?? String(DEFAULT_DAYS), "days", 1, MAX_DAYS);
|
|
33
|
+
const maxUses = parseInteger(options.maxUses ?? "0", "max uses", 0, MAX_USES);
|
|
34
|
+
return { role, ttlSeconds: days * 24 * 60 * 60, maxUses };
|
|
35
|
+
}
|
|
36
|
+
function invitationUrl(invitation) {
|
|
37
|
+
const origin = process.env.COHUB_WEB_URL?.replace(/\/+$/, "") ?? "https://cohub.run";
|
|
38
|
+
return `${origin}${buildSpaceInvitePath({
|
|
39
|
+
spaceId: invitation.spaceId,
|
|
40
|
+
ownerUsername: invitation.ownerUsername,
|
|
41
|
+
spaceSlug: invitation.spaceSlug,
|
|
42
|
+
inviteCode: invitation.token,
|
|
43
|
+
})}`;
|
|
44
|
+
}
|
|
45
|
+
async function confirmRevoke(options) {
|
|
46
|
+
if (options.yes)
|
|
47
|
+
return;
|
|
48
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
49
|
+
return error("Confirmation required", "Pass --yes to revoke the invite link.");
|
|
50
|
+
}
|
|
51
|
+
process.stdout.write("This invite link will stop working. Continue? [y/N] ");
|
|
52
|
+
const chunks = [];
|
|
53
|
+
for await (const chunk of process.stdin) {
|
|
54
|
+
chunks.push(chunk);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
const answer = Buffer.concat(chunks).toString().trim().toLowerCase();
|
|
58
|
+
if (answer !== "y" && answer !== "yes")
|
|
59
|
+
return error("Cancelled");
|
|
60
|
+
}
|
|
61
|
+
export function registerSpaceInvitations(spacesCommand, dependencies = {
|
|
62
|
+
createClient,
|
|
63
|
+
}) {
|
|
64
|
+
const invitations = spacesCommand
|
|
65
|
+
.command("invites")
|
|
66
|
+
.description("Create and manage space invite links");
|
|
67
|
+
invitations
|
|
68
|
+
.command("create")
|
|
69
|
+
.description("Create an invite link")
|
|
70
|
+
.option("--role <role>", "Member role: host, builder, or guest", "builder")
|
|
71
|
+
.option("--days <days>", "Validity in days, from 1 to 30", String(DEFAULT_DAYS))
|
|
72
|
+
.option("--max-uses <count>", "Usage limit, or 0 for unlimited", "0")
|
|
73
|
+
.option("--json", "Output as JSON")
|
|
74
|
+
.action(async (options) => {
|
|
75
|
+
const spaceId = resolveSpace(spacesCommand);
|
|
76
|
+
let input;
|
|
77
|
+
try {
|
|
78
|
+
input = parseSpaceInvitationCreateOptions(options);
|
|
79
|
+
}
|
|
80
|
+
catch (cause) {
|
|
81
|
+
if (cause instanceof InvalidSpaceInvitationCliOptionsError) {
|
|
82
|
+
return error(cause.message, cause.detail);
|
|
83
|
+
}
|
|
84
|
+
throw cause;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const created = await dependencies
|
|
88
|
+
.createClient()
|
|
89
|
+
.space(spaceId)
|
|
90
|
+
.invitations.create(input);
|
|
91
|
+
const output = {
|
|
92
|
+
...created,
|
|
93
|
+
url: invitationUrl({
|
|
94
|
+
...created,
|
|
95
|
+
spaceId: created.spaceId || spaceId,
|
|
96
|
+
ownerUsername: created.ownerUsername ?? null,
|
|
97
|
+
spaceSlug: created.spaceSlug ?? null,
|
|
98
|
+
}),
|
|
99
|
+
};
|
|
100
|
+
if (jsonRequested(options))
|
|
101
|
+
return outJson(output);
|
|
102
|
+
ok(`Invite link created: ${output.url}`);
|
|
103
|
+
}
|
|
104
|
+
catch (cause) {
|
|
105
|
+
handleHttp(cause);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
invitations
|
|
109
|
+
.command("ls")
|
|
110
|
+
.alias("list")
|
|
111
|
+
.description("List invite links")
|
|
112
|
+
.option("--json", "Output as JSON")
|
|
113
|
+
.action(async (options) => {
|
|
114
|
+
const spaceId = resolveSpace(spacesCommand);
|
|
115
|
+
try {
|
|
116
|
+
const result = await dependencies
|
|
117
|
+
.createClient()
|
|
118
|
+
.space(spaceId)
|
|
119
|
+
.invitations.list();
|
|
120
|
+
const items = result.items.map((item) => ({
|
|
121
|
+
...item,
|
|
122
|
+
url: invitationUrl({
|
|
123
|
+
...result,
|
|
124
|
+
token: item.token,
|
|
125
|
+
spaceId: result.spaceId || spaceId,
|
|
126
|
+
ownerUsername: result.ownerUsername ?? null,
|
|
127
|
+
spaceSlug: result.spaceSlug ?? null,
|
|
128
|
+
}),
|
|
129
|
+
uses: item.maxUses ? `${item.useCount}/${item.maxUses}` : String(item.useCount),
|
|
130
|
+
}));
|
|
131
|
+
if (jsonRequested(options))
|
|
132
|
+
return outJson({ ...result, items });
|
|
133
|
+
table(items, [
|
|
134
|
+
{ key: "token", label: "Code" },
|
|
135
|
+
{ key: "role", label: "Role" },
|
|
136
|
+
{ key: "status", label: "Status" },
|
|
137
|
+
{ key: "uses", label: "Uses" },
|
|
138
|
+
{ key: "expiresInSeconds", label: "Expires in" },
|
|
139
|
+
{ key: "url", label: "URL" },
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
catch (cause) {
|
|
143
|
+
handleHttp(cause);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
invitations
|
|
147
|
+
.command("revoke <code>")
|
|
148
|
+
.description("Revoke an invite link")
|
|
149
|
+
.option("-y, --yes", "Confirm revocation")
|
|
150
|
+
.option("--json", "Output as JSON")
|
|
151
|
+
.action(async (code, options) => {
|
|
152
|
+
await confirmRevoke(options);
|
|
153
|
+
const spaceId = resolveSpace(spacesCommand);
|
|
154
|
+
try {
|
|
155
|
+
const result = await dependencies
|
|
156
|
+
.createClient()
|
|
157
|
+
.space(spaceId)
|
|
158
|
+
.invitations.revoke(code);
|
|
159
|
+
if (jsonRequested(options))
|
|
160
|
+
return outJson(result);
|
|
161
|
+
ok("Invite link revoked");
|
|
162
|
+
}
|
|
163
|
+
catch (cause) {
|
|
164
|
+
handleHttp(cause);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
return invitations;
|
|
168
|
+
}
|
|
@@ -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
|
+
}
|
package/dist/commands/spaces.js
CHANGED
|
@@ -8,6 +8,8 @@ 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 { registerSpaceInvitations } from "./space-invitations.js";
|
|
12
|
+
import { registerSpaceTurns } from "./space-turns.js";
|
|
11
13
|
const cliEnv = resolveCohubEnvironment();
|
|
12
14
|
const defaultIdleTtlSeconds = cliEnv === "prod" ? 12 * 60 * 60 : 10 * 60;
|
|
13
15
|
const SPACE_ROLES = ["host", "builder", "guest"];
|
|
@@ -376,6 +378,7 @@ export function registerPrompt(program) {
|
|
|
376
378
|
}
|
|
377
379
|
export function registerSpaces(program) {
|
|
378
380
|
const spacesCmd = program.command("spaces").description("Space management");
|
|
381
|
+
registerSpaceInvitations(spacesCmd);
|
|
379
382
|
// ── spaces ls ──
|
|
380
383
|
spacesCmd
|
|
381
384
|
.command("ls")
|
|
@@ -609,6 +612,8 @@ export function registerSpaces(program) {
|
|
|
609
612
|
registerFiles(spacesCmd);
|
|
610
613
|
// ── spaces sessions ──
|
|
611
614
|
registerSessions(spacesCmd);
|
|
615
|
+
// ── spaces turns ──
|
|
616
|
+
registerSpaceTurns(spacesCmd);
|
|
612
617
|
// ── spaces members ──
|
|
613
618
|
registerMembers(spacesCmd);
|
|
614
619
|
// ── 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.
|
|
3
|
+
"version": "3.3.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.
|
|
22
|
+
"@neta-art/cohub": "4.5.0"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|
|
25
25
|
"access": "public"
|