@neta-art/cohub-cli 1.6.3 → 1.7.1
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/dist/avatar.d.ts +15 -0
- package/dist/avatar.js +35 -0
- package/dist/commands/generations.js +1 -1
- package/dist/commands/profile.d.ts +2 -0
- package/dist/commands/profile.js +23 -0
- package/dist/commands/session-access.js +3 -3
- package/dist/commands/spaces.js +20 -0
- package/dist/index.js +3 -0
- package/package.json +3 -2
package/dist/avatar.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CohubHttpClient, PublicAssetPurpose } from "@neta-art/cohub";
|
|
2
|
+
export declare function normalizeAvatarFile(path: string): Promise<Buffer>;
|
|
3
|
+
export declare function uploadAvatarAsset(input: {
|
|
4
|
+
client: CohubHttpClient;
|
|
5
|
+
purpose: PublicAssetPurpose;
|
|
6
|
+
path: string;
|
|
7
|
+
spaceId?: string;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
purpose: PublicAssetPurpose;
|
|
10
|
+
objectKey: string;
|
|
11
|
+
publicUrl: string;
|
|
12
|
+
uploadMethod: "POST";
|
|
13
|
+
uploadUrl: string;
|
|
14
|
+
uploadFields: Record<string, string>;
|
|
15
|
+
}>;
|
package/dist/avatar.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import sharp from "sharp";
|
|
2
|
+
const AVATAR_SIZE = 1024;
|
|
3
|
+
const AVATAR_QUALITY = 86;
|
|
4
|
+
export async function normalizeAvatarFile(path) {
|
|
5
|
+
return sharp(path)
|
|
6
|
+
.rotate()
|
|
7
|
+
.resize(AVATAR_SIZE, AVATAR_SIZE, { fit: "cover", position: "centre" })
|
|
8
|
+
.webp({ quality: AVATAR_QUALITY })
|
|
9
|
+
.toBuffer();
|
|
10
|
+
}
|
|
11
|
+
export async function uploadAvatarAsset(input) {
|
|
12
|
+
const body = await normalizeAvatarFile(input.path);
|
|
13
|
+
const plan = await input.client.publicAssets.createUpload({
|
|
14
|
+
purpose: input.purpose,
|
|
15
|
+
spaceId: input.spaceId,
|
|
16
|
+
file: {
|
|
17
|
+
size: body.byteLength,
|
|
18
|
+
mimeType: "image/webp",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
const formData = new FormData();
|
|
22
|
+
for (const [key, value] of Object.entries(plan.asset.uploadFields)) {
|
|
23
|
+
formData.append(key, value);
|
|
24
|
+
}
|
|
25
|
+
formData.append("file", new Blob([new Uint8Array(body)], { type: "image/webp" }), "avatar.webp");
|
|
26
|
+
const response = await fetch(plan.asset.uploadUrl, {
|
|
27
|
+
method: plan.asset.uploadMethod,
|
|
28
|
+
body: formData,
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
const detail = await response.text().catch(() => "");
|
|
32
|
+
throw new Error(`Avatar upload failed: HTTP ${response.status}${detail ? ` — ${detail}` : ""}`);
|
|
33
|
+
}
|
|
34
|
+
return plan.asset;
|
|
35
|
+
}
|
|
@@ -91,7 +91,7 @@ async function saveOutputs(output, outputPath) {
|
|
|
91
91
|
}
|
|
92
92
|
function outputName(type, url, index) {
|
|
93
93
|
const fromUrl = url ? basename(new URL(url).pathname) : "";
|
|
94
|
-
if (fromUrl
|
|
94
|
+
if (fromUrl?.includes("."))
|
|
95
95
|
return `generation-${index + 1}-${fromUrl}`;
|
|
96
96
|
const ext = type === "video" ? "mp4" : type === "audio" ? "bin" : "png";
|
|
97
97
|
return `generation-${index + 1}.${ext}`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { uploadAvatarAsset } from "../avatar.js";
|
|
2
|
+
import { createClient } from "../client.js";
|
|
3
|
+
import { json as outJson, ok, handleHttp } from "../output.js";
|
|
4
|
+
export function registerProfile(program) {
|
|
5
|
+
const profileCmd = program.command("profile").description("Manage your profile");
|
|
6
|
+
profileCmd
|
|
7
|
+
.command("avatar <path>")
|
|
8
|
+
.description("Upload your avatar")
|
|
9
|
+
.option("--json", "Output as JSON")
|
|
10
|
+
.action(async (path, opts) => {
|
|
11
|
+
const client = createClient();
|
|
12
|
+
try {
|
|
13
|
+
const asset = await uploadAvatarAsset({ client, purpose: "user_avatar", path });
|
|
14
|
+
const result = await client.user.updateProfile({ avatarUrl: asset.publicUrl });
|
|
15
|
+
if (opts.json)
|
|
16
|
+
return outJson({ ...result, asset });
|
|
17
|
+
ok("Avatar updated");
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
handleHttp(e);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createClient } from "../client.js";
|
|
2
|
-
import { table, json as outJson,
|
|
2
|
+
import { table, json as outJson, handleHttp } from "../output.js";
|
|
3
3
|
export function registerSessionAccess(program) {
|
|
4
4
|
const cmd = program
|
|
5
5
|
.command("session-access")
|
|
@@ -36,7 +36,7 @@ export function registerSessionAccess(program) {
|
|
|
36
36
|
});
|
|
37
37
|
if (opts.json)
|
|
38
38
|
return outJson(policy);
|
|
39
|
-
|
|
39
|
+
console.log("Session access updated");
|
|
40
40
|
table([policy], [
|
|
41
41
|
{ key: "signed_in_user", label: "Signed-in" },
|
|
42
42
|
{ key: "anonymous_user", label: "Anonymous" },
|
|
@@ -53,7 +53,7 @@ export function registerSessionAccess(program) {
|
|
|
53
53
|
const client = createClient();
|
|
54
54
|
try {
|
|
55
55
|
await client.sessionAccess.remove(id);
|
|
56
|
-
|
|
56
|
+
console.log(`Session access override removed: ${id}`);
|
|
57
57
|
}
|
|
58
58
|
catch (e) {
|
|
59
59
|
handleHttp(e);
|
package/dist/commands/spaces.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createReadStream } from "node:fs";
|
|
|
3
3
|
import { readdir, stat } from "node:fs/promises";
|
|
4
4
|
import { basename, dirname, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { createClient } from "../client.js";
|
|
6
|
+
import { uploadAvatarAsset } from "../avatar.js";
|
|
6
7
|
import { table, json as outJson, ok, error, handleHttp } from "../output.js";
|
|
7
8
|
function requireSpace(program) {
|
|
8
9
|
let current = program;
|
|
@@ -295,6 +296,25 @@ export function registerSpaces(program) {
|
|
|
295
296
|
handleHttp(e);
|
|
296
297
|
}
|
|
297
298
|
});
|
|
299
|
+
// ── spaces avatar ──
|
|
300
|
+
spacesCmd
|
|
301
|
+
.command("avatar <path>")
|
|
302
|
+
.description("Upload the space avatar")
|
|
303
|
+
.option("--json", "Output as JSON")
|
|
304
|
+
.action(async (path, opts) => {
|
|
305
|
+
const spaceId = requireSpace(spacesCmd);
|
|
306
|
+
const client = createClient();
|
|
307
|
+
try {
|
|
308
|
+
const asset = await uploadAvatarAsset({ client, purpose: "space_avatar", spaceId, path });
|
|
309
|
+
const result = await client.space(spaceId).profile({ avatarUrl: asset.publicUrl });
|
|
310
|
+
if (opts.json)
|
|
311
|
+
return outJson({ ...result, asset });
|
|
312
|
+
ok("Space avatar updated");
|
|
313
|
+
}
|
|
314
|
+
catch (e) {
|
|
315
|
+
handleHttp(e);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
298
318
|
// ── spaces config ──
|
|
299
319
|
spacesCmd
|
|
300
320
|
.command("config <id>")
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { registerChannels } from "./commands/channels.js";
|
|
|
6
6
|
import { registerCronJobs } from "./commands/cron-jobs.js";
|
|
7
7
|
import { registerGenerations } from "./commands/generations.js";
|
|
8
8
|
import { registerModels } from "./commands/models.js";
|
|
9
|
+
import { registerProfile } from "./commands/profile.js";
|
|
9
10
|
import { registerSearch } from "./commands/search.js";
|
|
10
11
|
import { registerPrompt, registerSpaces } from "./commands/spaces.js";
|
|
11
12
|
import { registerTasks } from "./commands/tasks.js";
|
|
@@ -32,6 +33,7 @@ program
|
|
|
32
33
|
|
|
33
34
|
Common commands:
|
|
34
35
|
cohub auth login
|
|
36
|
+
cohub profile avatar ./avatar.png
|
|
35
37
|
cohub spaces ls
|
|
36
38
|
cohub -s <space-id> prompt "Fix the failing tests"
|
|
37
39
|
cohub search "release notes"
|
|
@@ -46,6 +48,7 @@ Environment:
|
|
|
46
48
|
ENV=dev Use the development Cohub environment
|
|
47
49
|
`);
|
|
48
50
|
registerAuth(program);
|
|
51
|
+
registerProfile(program);
|
|
49
52
|
registerPrompt(program);
|
|
50
53
|
registerSpaces(program);
|
|
51
54
|
registerChannels(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neta-art/cohub-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"commander": "^13.1.0",
|
|
17
|
-
"
|
|
17
|
+
"sharp": "^0.34.5",
|
|
18
|
+
"@neta-art/cohub": "1.15.1"
|
|
18
19
|
},
|
|
19
20
|
"publishConfig": {
|
|
20
21
|
"access": "public"
|