@neta-art/cohub-cli 1.0.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,104 @@
1
+ import { resolveToken } from "../auth.js";
2
+ import { createClient } from "../client.js";
3
+ import { table, json as outJson, ok, error, handleHttp } from "../output.js";
4
+ export function registerTasks(program) {
5
+ const cmd = program.command("tasks").description("Task management");
6
+ cmd
7
+ .command("ls")
8
+ .alias("list")
9
+ .description("List task runs")
10
+ .option("--cron-job <id>", "Filter by cron job")
11
+ .option("--space <id>", "Filter by space")
12
+ .option("--json", "Output as JSON")
13
+ .action(async (opts) => {
14
+ const token = resolveToken();
15
+ if (!token)
16
+ return error("Not authenticated", "Run 'cohub auth login <token>'");
17
+ const client = createClient(token);
18
+ try {
19
+ const filters = {};
20
+ if (opts.cronJob)
21
+ filters.cronJobId = opts.cronJob;
22
+ if (opts.space)
23
+ filters.spaceId = opts.space;
24
+ const result = await client.tasks.list(filters);
25
+ if (opts.json)
26
+ return outJson(result);
27
+ if (result.runs.length === 0)
28
+ return console.log(" (empty)");
29
+ table(result.runs, [
30
+ { key: "id", label: "ID" },
31
+ { key: "taskType", label: "Type" },
32
+ { key: "status", label: "Status" },
33
+ { key: "createdAt", label: "Created" },
34
+ ]);
35
+ }
36
+ catch (e) {
37
+ handleHttp(e);
38
+ }
39
+ });
40
+ cmd
41
+ .command("get <id>")
42
+ .description("Task run details")
43
+ .option("--json", "Output as JSON")
44
+ .action(async (id, opts) => {
45
+ const token = resolveToken();
46
+ if (!token)
47
+ return error("Not authenticated");
48
+ const client = createClient(token);
49
+ try {
50
+ const result = await client.tasks.get(id);
51
+ if (opts.json)
52
+ return outJson(result);
53
+ table([result.run], [
54
+ { key: "id", label: "ID" },
55
+ { key: "taskType", label: "Type" },
56
+ { key: "status", label: "Status" },
57
+ { key: "attemptCount", label: "Attempts" },
58
+ { key: "createdAt", label: "Created" },
59
+ ]);
60
+ }
61
+ catch (e) {
62
+ handleHttp(e);
63
+ }
64
+ });
65
+ cmd
66
+ .command("create")
67
+ .description("Create a scheduled task")
68
+ .requiredOption("-t, --task-type <type>", "Task type")
69
+ .requiredOption("--schedule-at <time>", "ISO timestamp")
70
+ .option("--payload <json>", "Task payload as JSON")
71
+ .option("--space <id>", "Space ID")
72
+ .option("--session <id>", "Session ID")
73
+ .option("--json", "Output as JSON")
74
+ .action(async (opts) => {
75
+ const token = resolveToken();
76
+ if (!token)
77
+ return error("Not authenticated");
78
+ let payload = {};
79
+ if (opts.payload) {
80
+ try {
81
+ payload = JSON.parse(opts.payload);
82
+ }
83
+ catch {
84
+ return error("Invalid JSON", "--payload must be valid JSON");
85
+ }
86
+ }
87
+ const client = createClient(token);
88
+ try {
89
+ const result = await client.tasks.createScheduled({
90
+ taskType: opts.taskType,
91
+ payload,
92
+ scheduleAt: opts.scheduleAt,
93
+ spaceId: opts.space,
94
+ sessionId: opts.session,
95
+ });
96
+ if (opts.json)
97
+ return outJson(result);
98
+ ok(`Task scheduled — taskRunId: ${result.taskRunId}`);
99
+ }
100
+ catch (e) {
101
+ handleHttp(e);
102
+ }
103
+ });
104
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { readFileSync } from "node:fs";
4
+ import { registerAuth } from "./commands/auth.js";
5
+ import { registerChannels } from "./commands/channels.js";
6
+ import { registerCronJobs } from "./commands/cron-jobs.js";
7
+ import { registerModels } from "./commands/models.js";
8
+ import { registerPrompts } from "./commands/prompts.js";
9
+ import { registerSessionAccess } from "./commands/session-access.js";
10
+ import { registerSpaces } from "./commands/spaces.js";
11
+ import { registerTasks } from "./commands/tasks.js";
12
+ const VERSION = (() => {
13
+ try {
14
+ const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
15
+ return pkg.version;
16
+ }
17
+ catch {
18
+ return "1.0.0";
19
+ }
20
+ })();
21
+ const program = new Command("cohub");
22
+ program
23
+ .version(VERSION)
24
+ .description("CLI for Cohub — spaces, sessions, and agent collaboration.")
25
+ .option("-s, --space <id>", "Target space ID")
26
+ .option("--json", "Output as JSON")
27
+ .option("--env <name>", "Cohub environment (default: production)", "production")
28
+ .helpOption("-h, --help", "Show help");
29
+ registerAuth(program);
30
+ registerSpaces(program);
31
+ registerChannels(program);
32
+ registerModels(program);
33
+ registerPrompts(program);
34
+ registerTasks(program);
35
+ registerCronJobs(program);
36
+ registerSessionAccess(program);
37
+ program.parse();
@@ -0,0 +1,14 @@
1
+ type Row = Record<string, unknown>;
2
+ export declare function table(rows: Row[], columns: {
3
+ key: string;
4
+ label: string;
5
+ }[]): void;
6
+ export declare function json(data: unknown): void;
7
+ export declare function ok(msg: string): void;
8
+ export declare function error(msg: string, detail?: string): never;
9
+ export declare function handleHttp(e: unknown): never;
10
+ export declare function spinner(): {
11
+ start(msg: string): void;
12
+ stop(msg: string): void;
13
+ };
14
+ export {};
package/dist/output.js ADDED
@@ -0,0 +1,91 @@
1
+ import process from "node:process";
2
+ function colWidth(rows, key, label) {
3
+ const maxVal = rows.reduce((m, r) => {
4
+ const v = r[key] ?? "";
5
+ const s = typeof v === "object" ? JSON.stringify(v) : String(v);
6
+ return Math.max(m, s.length);
7
+ }, 0);
8
+ return Math.max(label.length, maxVal) + 2;
9
+ }
10
+ export function table(rows, columns) {
11
+ if (rows.length === 0) {
12
+ console.log(" (empty)");
13
+ return;
14
+ }
15
+ const widths = columns.map((c) => colWidth(rows, c.key, c.label));
16
+ const header = columns
17
+ .map((c, i) => c.label.padEnd(widths[i]))
18
+ .join(" │ ")
19
+ .trimEnd();
20
+ console.log(header);
21
+ console.log("─".repeat(header.length));
22
+ for (const row of rows) {
23
+ const line = columns
24
+ .map((c, i) => {
25
+ const v = row[c.key] ?? "";
26
+ const s = typeof v === "object" ? JSON.stringify(v) : String(v);
27
+ return s.padEnd(widths[i]);
28
+ })
29
+ .join(" │ ")
30
+ .trimEnd();
31
+ console.log(line);
32
+ }
33
+ }
34
+ // -- Output helpers ----------------------------------------------------------
35
+ export function json(data) {
36
+ console.log(JSON.stringify(data, null, 2));
37
+ }
38
+ export function ok(msg) {
39
+ console.log(`\n ✓ ${msg}\n`);
40
+ }
41
+ export function error(msg, detail) {
42
+ process.stderr.write(`\n ✗ ${msg}\n`);
43
+ if (detail)
44
+ process.stderr.write(` ${detail}\n`);
45
+ process.stderr.write("\n");
46
+ process.exit(1);
47
+ }
48
+ // -- HTTP error handler ------------------------------------------------------
49
+ export function handleHttp(e) {
50
+ const status = e.status;
51
+ const body = e.body;
52
+ const msg = e instanceof Error ? e.message : String(e);
53
+ let detail;
54
+ if (status)
55
+ detail = `HTTP ${status}`;
56
+ if (body && typeof body === "object" && "message" in body) {
57
+ detail = `${detail ? detail + " — " : ""}${body.message}`;
58
+ }
59
+ error(msg, detail);
60
+ }
61
+ // -- Spinner -----------------------------------------------------------------
62
+ export function spinner() {
63
+ let interval = null;
64
+ const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
65
+ let i = 0;
66
+ return {
67
+ start(msg) {
68
+ if (process.env.CI || !process.stderr.isTTY) {
69
+ process.stderr.write(` ${msg}...\n`);
70
+ return;
71
+ }
72
+ process.stderr.write(` ${msg} `);
73
+ interval = setInterval(() => {
74
+ process.stderr.clearLine?.(0);
75
+ process.stderr.cursorTo?.(0);
76
+ process.stderr.write(` ${frames[i++ % frames.length]} ${msg} `);
77
+ }, 80);
78
+ },
79
+ stop(msg) {
80
+ if (interval)
81
+ clearInterval(interval);
82
+ if (process.env.CI || !process.stderr.isTTY) {
83
+ process.stderr.write(` ${msg}\n`);
84
+ return;
85
+ }
86
+ process.stderr.clearLine?.(0);
87
+ process.stderr.cursorTo?.(0);
88
+ process.stderr.write(` ✓ ${msg}\n`);
89
+ },
90
+ };
91
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@neta-art/cohub-cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
5
+ "type": "module",
6
+ "bin": {
7
+ "cohub": "./bin/cohub.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "bin",
12
+ "README.md"
13
+ ],
14
+ "dependencies": {
15
+ "commander": "^13.1.0",
16
+ "@neta-art/cohub": "1.1.0"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^22.0.0",
23
+ "typescript": "^6.0.3"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc -p tsconfig.build.json",
27
+ "typecheck": "tsc -p tsconfig.json --noEmit"
28
+ }
29
+ }