@floomhq/skills 0.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.
Files changed (82) hide show
  1. package/dist/api-client.d.ts +9 -0
  2. package/dist/api-client.js +61 -0
  3. package/dist/api-client.js.map +1 -0
  4. package/dist/commands/info.d.ts +1 -0
  5. package/dist/commands/info.js +24 -0
  6. package/dist/commands/info.js.map +1 -0
  7. package/dist/commands/init.d.ts +1 -0
  8. package/dist/commands/init.js +108 -0
  9. package/dist/commands/init.js.map +1 -0
  10. package/dist/commands/install.d.ts +8 -0
  11. package/dist/commands/install.js +136 -0
  12. package/dist/commands/install.js.map +1 -0
  13. package/dist/commands/installed.d.ts +4 -0
  14. package/dist/commands/installed.js +22 -0
  15. package/dist/commands/installed.js.map +1 -0
  16. package/dist/commands/library.d.ts +4 -0
  17. package/dist/commands/library.js +29 -0
  18. package/dist/commands/library.js.map +1 -0
  19. package/dist/commands/list.d.ts +7 -0
  20. package/dist/commands/list.js +32 -0
  21. package/dist/commands/list.js.map +1 -0
  22. package/dist/commands/login.d.ts +1 -0
  23. package/dist/commands/login.js +57 -0
  24. package/dist/commands/login.js.map +1 -0
  25. package/dist/commands/logout.d.ts +1 -0
  26. package/dist/commands/logout.js +19 -0
  27. package/dist/commands/logout.js.map +1 -0
  28. package/dist/commands/outdated.d.ts +1 -0
  29. package/dist/commands/outdated.js +50 -0
  30. package/dist/commands/outdated.js.map +1 -0
  31. package/dist/commands/publish.d.ts +4 -0
  32. package/dist/commands/publish.js +84 -0
  33. package/dist/commands/publish.js.map +1 -0
  34. package/dist/commands/share.d.ts +5 -0
  35. package/dist/commands/share.js +34 -0
  36. package/dist/commands/share.js.map +1 -0
  37. package/dist/commands/update.d.ts +4 -0
  38. package/dist/commands/update.js +92 -0
  39. package/dist/commands/update.js.map +1 -0
  40. package/dist/commands/validate.d.ts +32 -0
  41. package/dist/commands/validate.js +108 -0
  42. package/dist/commands/validate.js.map +1 -0
  43. package/dist/commands/whoami.d.ts +1 -0
  44. package/dist/commands/whoami.js +14 -0
  45. package/dist/commands/whoami.js.map +1 -0
  46. package/dist/config.d.ts +11 -0
  47. package/dist/config.js +39 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/index.d.ts +2 -0
  50. package/dist/index.js +99 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/lib/floom-lock.d.ts +22 -0
  53. package/dist/lib/floom-lock.js +66 -0
  54. package/dist/lib/floom-lock.js.map +1 -0
  55. package/dist/lib/output.d.ts +11 -0
  56. package/dist/lib/output.js +17 -0
  57. package/dist/lib/output.js.map +1 -0
  58. package/dist/version.d.ts +1 -0
  59. package/dist/version.js +2 -0
  60. package/dist/version.js.map +1 -0
  61. package/package.json +39 -0
  62. package/src/api-client.ts +80 -0
  63. package/src/commands/info.ts +36 -0
  64. package/src/commands/init.ts +109 -0
  65. package/src/commands/install.ts +176 -0
  66. package/src/commands/installed.ts +29 -0
  67. package/src/commands/library.ts +41 -0
  68. package/src/commands/list.ts +59 -0
  69. package/src/commands/login.ts +77 -0
  70. package/src/commands/logout.ts +18 -0
  71. package/src/commands/outdated.ts +57 -0
  72. package/src/commands/publish.ts +111 -0
  73. package/src/commands/share.ts +41 -0
  74. package/src/commands/update.ts +116 -0
  75. package/src/commands/validate.ts +132 -0
  76. package/src/commands/whoami.ts +14 -0
  77. package/src/config.ts +44 -0
  78. package/src/index.ts +109 -0
  79. package/src/lib/floom-lock.ts +81 -0
  80. package/src/lib/output.ts +17 -0
  81. package/src/version.ts +1 -0
  82. package/tsconfig.json +9 -0
@@ -0,0 +1,9 @@
1
+ export interface ApiOptions {
2
+ method?: "GET" | "POST" | "PATCH" | "DELETE" | "PUT";
3
+ body?: unknown;
4
+ authRequired?: boolean;
5
+ query?: Record<string, string | number | boolean | undefined>;
6
+ }
7
+ export declare function api<T = unknown>(path: string, opts?: ApiOptions): Promise<T>;
8
+ export declare function rawPut(url: string, body: Buffer | Uint8Array, contentType?: string): Promise<void>;
9
+ export declare function rawGet(url: string): Promise<Buffer>;
@@ -0,0 +1,61 @@
1
+ import { FloomError } from "@floom/shared";
2
+ import { getApiUrl, readAuth } from "./config.js";
3
+ import { VERSION } from "./version.js";
4
+ export async function api(path, opts = {}) {
5
+ const auth = await readAuth();
6
+ if (opts.authRequired && !auth) {
7
+ throw new FloomError("AUTH_REQUIRED", "Not logged in. Run: floom login");
8
+ }
9
+ const url = new URL((auth?.apiUrl ?? getApiUrl()) + path);
10
+ if (opts.query) {
11
+ for (const [k, v] of Object.entries(opts.query)) {
12
+ if (v !== undefined)
13
+ url.searchParams.set(k, String(v));
14
+ }
15
+ }
16
+ const headers = {
17
+ "Content-Type": "application/json",
18
+ "User-Agent": `floom-cli/${VERSION}`,
19
+ "x-floom-cli-version": VERSION,
20
+ };
21
+ if (auth)
22
+ headers.Authorization = `Bearer ${auth.token}`;
23
+ const res = await fetch(url.toString(), {
24
+ method: opts.method ?? "GET",
25
+ headers,
26
+ body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
27
+ });
28
+ const text = await res.text();
29
+ let json = null;
30
+ try {
31
+ json = text ? JSON.parse(text) : null;
32
+ }
33
+ catch { /* not JSON */ }
34
+ if (!res.ok) {
35
+ const err = json?.error ?? {};
36
+ throw new FloomError((err.code ?? "INTERNAL_ERROR"), err.message ?? `HTTP ${res.status} ${res.statusText}`, { status: res.status, requestId: err.request_id });
37
+ }
38
+ return json;
39
+ }
40
+ // Variants for binary upload/download to Supabase Storage signed URLs (no auth header)
41
+ export async function rawPut(url, body, contentType = "application/octet-stream") {
42
+ // Convert to BufferSource that fetch accepts
43
+ const u8 = body instanceof Buffer ? new Uint8Array(body) : body;
44
+ const res = await fetch(url, {
45
+ method: "PUT",
46
+ headers: { "Content-Type": contentType },
47
+ body: u8,
48
+ });
49
+ if (!res.ok) {
50
+ throw new FloomError("UPLOAD_FAILED", `Upload failed: HTTP ${res.status} ${res.statusText}`);
51
+ }
52
+ }
53
+ export async function rawGet(url) {
54
+ const res = await fetch(url);
55
+ if (!res.ok) {
56
+ throw new FloomError("DOWNLOAD_FAILED", `Download failed: HTTP ${res.status} ${res.statusText}`);
57
+ }
58
+ const ab = await res.arrayBuffer();
59
+ return Buffer.from(ab);
60
+ }
61
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function infoCommand(refStr: string): Promise<void>;
@@ -0,0 +1,24 @@
1
+ import { parseSkillRef } from "@floom/shared";
2
+ import { api } from "../api-client.js";
3
+ import { log } from "../lib/output.js";
4
+ export async function infoCommand(refStr) {
5
+ const ref = parseSkillRef(refStr);
6
+ if (!ref) {
7
+ log.err(`Invalid skill ref: ${refStr}`);
8
+ process.exit(1);
9
+ }
10
+ const r = await api(`/skills/${ref.owner}/${ref.slug}`);
11
+ log.heading(r.ref);
12
+ log.kv("Title", r.title);
13
+ log.kv("Description", r.description);
14
+ log.kv("Latest", r.latest_version);
15
+ log.kv("Visibility", r.visibility);
16
+ log.kv("Owner", `@${r.owner.handle}${r.owner.display_name ? ` (${r.owner.display_name})` : ""}`);
17
+ if (r.has_scripts) {
18
+ log.kv("Scripts", "yes (review before activating)");
19
+ }
20
+ log.blank();
21
+ log.info("Install:");
22
+ log.info(` floom install ${r.ref}`);
23
+ }
24
+ //# sourceMappingURL=info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAavC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc;IAC9C,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,CAAC,GAAG,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,GAAG,CAAe,WAAW,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAEtE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;IACrC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC;IACnC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAClB,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;IACtD,CAAC;IACD,GAAG,CAAC,KAAK,EAAE,CAAC;IACZ,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrB,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function initCommand(): Promise<void>;
@@ -0,0 +1,108 @@
1
+ import { writeFile, stat } from "node:fs/promises";
2
+ import { join, basename } from "node:path";
3
+ import prompts from "prompts";
4
+ import { isValidSlug, slugErrorMessage } from "@floom/shared";
5
+ import { log } from "../lib/output.js";
6
+ async function pathExists(p) {
7
+ try {
8
+ await stat(p);
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ export async function initCommand() {
16
+ const cwd = process.cwd();
17
+ const folderName = basename(cwd);
18
+ if (await pathExists(join(cwd, "skill.json"))) {
19
+ log.err("skill.json already exists in this folder. Edit it directly or run from a fresh directory.");
20
+ process.exit(1);
21
+ }
22
+ const defaultName = folderName.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
23
+ const answers = await prompts([
24
+ {
25
+ type: "text",
26
+ name: "name",
27
+ message: "Skill name (lowercase, hyphens):",
28
+ initial: isValidSlug(defaultName) ? defaultName : "",
29
+ validate: (v) => slugErrorMessage(v) ?? true,
30
+ },
31
+ {
32
+ type: "text",
33
+ name: "title",
34
+ message: "Title (human-readable):",
35
+ initial: (prev) => prev.split("-").map((w) => w[0]?.toUpperCase() + w.slice(1)).join(" "),
36
+ validate: (v) => v.trim().length > 0 ? true : "title required",
37
+ },
38
+ {
39
+ type: "text",
40
+ name: "description",
41
+ message: "One-line description:",
42
+ validate: (v) => v.trim().length > 0 ? true : "description required",
43
+ },
44
+ {
45
+ type: "text",
46
+ name: "version",
47
+ message: "Version:",
48
+ initial: "0.1.0",
49
+ },
50
+ ]);
51
+ if (!answers.name) {
52
+ log.err("Init cancelled.");
53
+ process.exit(1);
54
+ }
55
+ const manifest = {
56
+ schema_version: "0.1",
57
+ name: answers.name,
58
+ title: answers.title,
59
+ description: answers.description,
60
+ version: answers.version,
61
+ entrypoint: "SKILL.md",
62
+ targets: ["generic"],
63
+ };
64
+ const skillMd = `---
65
+ name: ${answers.name}
66
+ description: ${answers.description}
67
+ ---
68
+
69
+ # ${answers.title}
70
+
71
+ ## Purpose
72
+
73
+ ${answers.description}
74
+
75
+ ## When to use
76
+
77
+ (Describe when this skill should be activated.)
78
+
79
+ ## Process
80
+
81
+ 1. (Step one)
82
+ 2. (Step two)
83
+
84
+ ## Output
85
+
86
+ (Describe what the skill produces.)
87
+ `;
88
+ const floomIgnore = `# Floom CLI ignore patterns
89
+ # One pattern per line, glob-style
90
+ tmp/
91
+ drafts/
92
+ *.log
93
+ `;
94
+ await writeFile(join(cwd, "skill.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
95
+ await writeFile(join(cwd, "SKILL.md"), skillMd, "utf8");
96
+ await writeFile(join(cwd, ".floomignore"), floomIgnore, "utf8");
97
+ log.blank();
98
+ log.ok("Skill scaffolded.");
99
+ log.kv("skill.json", "manifest (edit metadata)");
100
+ log.kv("SKILL.md", "instructions for the agent");
101
+ log.kv(".floomignore", "patterns to exclude from publish");
102
+ log.blank();
103
+ log.info("Next:");
104
+ log.info(" 1. Edit SKILL.md");
105
+ log.info(" 2. floom validate");
106
+ log.info(" 3. floom publish");
107
+ }
108
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type InstallTarget } from "@floom/shared";
2
+ export interface InstallOptions {
3
+ for?: InstallTarget;
4
+ to?: string;
5
+ global?: boolean;
6
+ force?: boolean;
7
+ }
8
+ export declare function installCommand(refStr: string, opts?: InstallOptions): Promise<void>;
@@ -0,0 +1,136 @@
1
+ import { mkdir, readdir, rm, rename } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { tmpdir } from "node:os";
4
+ import { parseSkillRef, formatSkillRef, resolveInstallDir, extractBundle, verifyBundleHash, FloomError, } from "@floom/shared";
5
+ import { api, rawGet } from "../api-client.js";
6
+ import { readAuth } from "../config.js";
7
+ import { log } from "../lib/output.js";
8
+ import { readLock, writeLock, setLockEntry, hashInstalledFolder } from "../lib/floom-lock.js";
9
+ import { VERSION } from "../version.js";
10
+ const CLI_VERSION = VERSION;
11
+ function semverGte(a, b) {
12
+ const pa = a.split(".").map(Number);
13
+ const pb = b.split(".").map(Number);
14
+ for (let i = 0; i < 3; i++) {
15
+ if ((pa[i] ?? 0) > (pb[i] ?? 0))
16
+ return true;
17
+ if ((pa[i] ?? 0) < (pb[i] ?? 0))
18
+ return false;
19
+ }
20
+ return true;
21
+ }
22
+ export async function installCommand(refStr, opts = {}) {
23
+ const ref = parseSkillRef(refStr);
24
+ if (!ref) {
25
+ log.err(`Invalid skill ref: ${refStr}`);
26
+ log.info("Expected: @owner/slug, library-slug/slug, or with @version suffix");
27
+ process.exit(1);
28
+ }
29
+ // Get metadata (works anonymously for public skills)
30
+ let info;
31
+ try {
32
+ info = await api(`/skills/${ref.owner}/${ref.slug}`);
33
+ }
34
+ catch (e) {
35
+ if (e instanceof FloomError && e.code === "SKILL_ACCESS_DENIED") {
36
+ const auth = await readAuth();
37
+ if (!auth) {
38
+ log.err(`Cannot access ${formatSkillRef(ref)}.`);
39
+ log.info("Run `floom login` to install private or unlisted skills.");
40
+ process.exit(1);
41
+ }
42
+ log.err(`You do not have access to ${formatSkillRef(ref)}.`);
43
+ log.info(`Ask the owner to share it with: ${auth.email}`);
44
+ process.exit(1);
45
+ }
46
+ throw e;
47
+ }
48
+ if (info.min_floom_version && !semverGte(CLI_VERSION, info.min_floom_version)) {
49
+ log.err(`This skill requires Floom CLI >= ${info.min_floom_version} (you have ${CLI_VERSION}).`);
50
+ log.info("Upgrade:");
51
+ log.info(" npm install -g @floomhq/skills@latest");
52
+ process.exit(1);
53
+ }
54
+ // Resolve install destination
55
+ const target = resolveInstallDir({
56
+ target: opts.for ?? "generic",
57
+ to: opts.to,
58
+ global: opts.global,
59
+ });
60
+ const projectDir = opts.global ? process.cwd() : process.cwd();
61
+ const destFolder = join(target.dir, ref.slug);
62
+ // Conflict check
63
+ const lock = await readLock(projectDir);
64
+ const refKey = formatSkillRef({ owner: ref.owner, slug: ref.slug });
65
+ const existing = lock.skills[refKey];
66
+ let folderExists = false;
67
+ try {
68
+ const entries = await readdir(destFolder);
69
+ folderExists = entries.length > 0;
70
+ }
71
+ catch { /* not exists */ }
72
+ if (folderExists) {
73
+ if (existing && existing.path === destFolder.replace(projectDir + "/", "")) {
74
+ // Tracked. Check local edits.
75
+ const current = await hashInstalledFolder(destFolder);
76
+ // For V0 we don't have file-level hashes in lock; we conservatively warn unless --force.
77
+ if (!opts.force) {
78
+ log.warn(`Folder already exists at ${destFolder} and may contain local edits.`);
79
+ log.info(`Re-run with --force to overwrite, or remove the folder manually.`);
80
+ process.exit(1);
81
+ }
82
+ }
83
+ else if (!opts.force) {
84
+ log.err(`Folder already exists at ${destFolder} (not tracked by floom.lock).`);
85
+ log.info("Re-run with --force to overwrite, or remove the folder manually.");
86
+ process.exit(1);
87
+ }
88
+ }
89
+ // Download
90
+ log.step("Fetching skill metadata...");
91
+ const dl = await api(`/skills/${ref.owner}/${ref.slug}/download`, {
92
+ query: { version: ref.version },
93
+ });
94
+ log.step("Downloading bundle...");
95
+ const buf = await rawGet(dl.download.url);
96
+ if (!verifyBundleHash(buf, dl.bundle_sha256)) {
97
+ log.err("Bundle hash mismatch — refusing to extract.");
98
+ process.exit(1);
99
+ }
100
+ log.ok(`Bundle verified (${(buf.length / 1024).toFixed(1)} KB).`);
101
+ // Extract to temp, then swap
102
+ const tmp = await import("node:fs/promises").then((m) => m.mkdtemp(join(tmpdir(), `floom-install-${ref.slug}-`)));
103
+ try {
104
+ await extractBundle(buf, tmp);
105
+ await mkdir(target.dir, { recursive: true });
106
+ if (folderExists) {
107
+ await rm(destFolder, { recursive: true, force: true });
108
+ }
109
+ await rename(tmp, destFolder);
110
+ }
111
+ catch (e) {
112
+ await rm(tmp, { recursive: true, force: true }).catch(() => { });
113
+ throw e;
114
+ }
115
+ // Update floom.lock
116
+ const next = setLockEntry(lock, refKey, {
117
+ version: dl.version,
118
+ resolved: `${process.env.FLOOM_APP_URL ?? "https://floom-v0.vercel.app"}/${refKey}`,
119
+ bundle_sha256: dl.bundle_sha256,
120
+ installed_at: new Date().toISOString(),
121
+ path: destFolder.replace(projectDir + "/", ""),
122
+ preset: opts.for,
123
+ });
124
+ await writeLock(projectDir, next);
125
+ log.blank();
126
+ log.ok(`Installed ${refKey}@${dl.version}`);
127
+ log.kv("Path", destFolder);
128
+ log.kv("Target", target.target);
129
+ log.kv("Compatible with", target.compatibleAgents.join(", "));
130
+ if (dl.has_scripts) {
131
+ log.blank();
132
+ log.warn("This skill contains executable scripts. Floom does not run them; your agent may.");
133
+ log.warn("Review the scripts/ folder before activating.");
134
+ }
135
+ }
136
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export interface InstalledOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function installedCommand(opts?: InstalledOptions): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { readLock } from "../lib/floom-lock.js";
2
+ import { log } from "../lib/output.js";
3
+ export async function installedCommand(opts = {}) {
4
+ const lock = await readLock(process.cwd());
5
+ const entries = Object.entries(lock.skills);
6
+ if (opts.json) {
7
+ console.log(JSON.stringify(lock, null, 2));
8
+ return;
9
+ }
10
+ if (entries.length === 0) {
11
+ log.info("No skills installed in this project.");
12
+ log.info("Get one: floom install @owner/slug");
13
+ return;
14
+ }
15
+ log.heading("Installed skills in this project");
16
+ for (const [ref, e] of entries) {
17
+ console.log(` ${ref.padEnd(40)} ${e.version.padEnd(8)} ${(e.preset ?? "-").padEnd(8)} ${e.path}`);
18
+ }
19
+ log.blank();
20
+ log.info(`${entries.length} skill${entries.length === 1 ? "" : "s"} installed.`);
21
+ }
22
+ //# sourceMappingURL=installed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installed.js","sourceRoot":"","sources":["../../src/commands/installed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAMvC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAyB,EAAE;IAChE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE5C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC;IAChD,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACrG,CAAC;IACD,GAAG,CAAC,KAAK,EAAE,CAAC;IACZ,GAAG,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,SAAS,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function libraryListCommand(): Promise<void>;
2
+ export declare function libraryCreateCommand(slug: string, name: string): Promise<void>;
3
+ export declare function libraryInviteCommand(librarySlug: string, email: string, role?: string): Promise<void>;
4
+ export declare function libraryLeaveCommand(librarySlug: string): Promise<void>;
@@ -0,0 +1,29 @@
1
+ import { api } from "../api-client.js";
2
+ import { log } from "../lib/output.js";
3
+ export async function libraryListCommand() {
4
+ const resp = await api("/libraries", { authRequired: true });
5
+ if (!resp.libraries.length) {
6
+ log.info("No libraries.");
7
+ return;
8
+ }
9
+ for (const l of resp.libraries) {
10
+ console.log(`${l.slug.padEnd(24)} ${l.type.padEnd(8)} ${l.role.padEnd(6)} ${l.name}`);
11
+ }
12
+ }
13
+ export async function libraryCreateCommand(slug, name) {
14
+ const resp = await api("/libraries", { method: "POST", authRequired: true, body: { slug, name } });
15
+ log.ok(`Created library ${resp.slug}`);
16
+ }
17
+ export async function libraryInviteCommand(librarySlug, email, role = "viewer") {
18
+ await api(`/libraries/${librarySlug}/pending-invites`, {
19
+ method: "POST",
20
+ authRequired: true,
21
+ body: { email, role },
22
+ });
23
+ log.ok(`Invited ${email} to ${librarySlug} as ${role}`);
24
+ }
25
+ export async function libraryLeaveCommand(librarySlug) {
26
+ await api(`/libraries/${librarySlug}/members/me`, { method: "DELETE", authRequired: true });
27
+ log.ok(`Left library ${librarySlug}`);
28
+ }
29
+ //# sourceMappingURL=library.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library.js","sourceRoot":"","sources":["../../src/commands/library.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAWvC,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,IAAI,GAAG,MAAM,GAAG,CAA8B,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1F,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY,EAAE,IAAY;IACnE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAa,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/G,GAAG,CAAC,EAAE,CAAC,mBAAmB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,WAAmB,EAAE,KAAa,EAAE,IAAI,GAAG,QAAQ;IAC5F,MAAM,GAAG,CAAC,cAAc,WAAW,kBAAkB,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,YAAY,EAAE,IAAI;QAClB,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;KACtB,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,CAAC,WAAW,KAAK,OAAO,WAAW,OAAO,IAAI,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,WAAmB;IAC3D,MAAM,GAAG,CAAC,cAAc,WAAW,aAAa,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5F,GAAG,CAAC,EAAE,CAAC,gBAAgB,WAAW,EAAE,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface ListOptions {
2
+ query?: string;
3
+ library?: string;
4
+ folder?: string;
5
+ flat?: boolean;
6
+ }
7
+ export declare function listCommand(opts?: ListOptions): Promise<void>;
@@ -0,0 +1,32 @@
1
+ import { api } from "../api-client.js";
2
+ import { log } from "../lib/output.js";
3
+ export async function listCommand(opts = {}) {
4
+ const resp = await api("/skills", {
5
+ authRequired: true,
6
+ query: { q: opts.query, library: opts.library, folder: opts.folder },
7
+ });
8
+ if (resp.skills.length === 0) {
9
+ log.info("No skills.");
10
+ return;
11
+ }
12
+ if (opts.flat) {
13
+ for (const s of resp.skills) {
14
+ console.log(`${s.library.slug}/${s.slug}`);
15
+ }
16
+ return;
17
+ }
18
+ const groups = new Map();
19
+ for (const skill of resp.skills) {
20
+ const k = `${skill.library.slug} (${skill.library.name})`;
21
+ const arr = groups.get(k) ?? [];
22
+ arr.push(skill);
23
+ groups.set(k, arr);
24
+ }
25
+ for (const [library, rows] of groups.entries()) {
26
+ log.heading(library);
27
+ for (const s of rows) {
28
+ console.log(` ${`${s.library.slug}/${s.slug}`.padEnd(40)} ${s.visibility.padEnd(10)} ${s.title}`);
29
+ }
30
+ }
31
+ }
32
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAyBvC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB,EAAE;IACtD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAe,SAAS,EAAE;QAC9C,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;KACrE,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACvB,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function loginCommand(): Promise<void>;
@@ -0,0 +1,57 @@
1
+ import { exec } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { api } from "../api-client.js";
4
+ import { getApiUrl, writeAuth } from "../config.js";
5
+ import { log } from "../lib/output.js";
6
+ const sh = promisify(exec);
7
+ async function openInBrowser(url) {
8
+ const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
9
+ try {
10
+ await sh(`${opener} ${JSON.stringify(url)}`);
11
+ }
12
+ catch { /* user can copy-paste */ }
13
+ }
14
+ export async function loginCommand() {
15
+ log.heading("Starting CLI login...");
16
+ const session = await api("/cli/sessions", {
17
+ method: "POST",
18
+ body: { client: "floom-cli", version: "0.0.1" },
19
+ });
20
+ log.info("");
21
+ log.info(`Open this URL in your browser:`);
22
+ log.info(` ${session.verification_uri}`);
23
+ log.info("");
24
+ log.info(`Your code: ${session.user_code}`);
25
+ log.info("");
26
+ openInBrowser(session.verification_uri).catch(() => { });
27
+ const start = Date.now();
28
+ const deadline = new Date(session.expires_at).getTime();
29
+ const interval = Math.max(2, session.poll_interval_seconds) * 1000;
30
+ while (Date.now() < deadline) {
31
+ await new Promise((r) => setTimeout(r, interval));
32
+ const pollPath = `/cli/sessions/${session.session_id}?device_code=${encodeURIComponent(session.device_code)}`;
33
+ const poll = await api(pollPath);
34
+ if (poll.status === "approved" && poll.token && poll.handle && poll.email) {
35
+ await writeAuth({
36
+ token: poll.token,
37
+ handle: poll.handle,
38
+ email: poll.email,
39
+ apiUrl: getApiUrl(),
40
+ });
41
+ log.ok(`Logged in as @${poll.handle} (${poll.email})`);
42
+ return;
43
+ }
44
+ if (poll.status === "denied") {
45
+ log.err("Login denied.");
46
+ process.exit(1);
47
+ }
48
+ if (poll.status === "expired") {
49
+ log.err("Login session expired. Run `floom login` again.");
50
+ process.exit(1);
51
+ }
52
+ process.stdout.write(".");
53
+ }
54
+ log.err("Login timed out.");
55
+ process.exit(1);
56
+ }
57
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function logoutCommand(): Promise<void>;
@@ -0,0 +1,19 @@
1
+ import { clearAuth, readAuth } from "../config.js";
2
+ import { api } from "../api-client.js";
3
+ import { log } from "../lib/output.js";
4
+ export async function logoutCommand() {
5
+ const auth = await readAuth();
6
+ if (!auth) {
7
+ log.info("Not logged in.");
8
+ return;
9
+ }
10
+ try {
11
+ await api("/cli/sessions/revoke", { method: "POST", authRequired: true });
12
+ }
13
+ catch {
14
+ // best effort; we still clear local token
15
+ }
16
+ await clearAuth();
17
+ log.ok("Logged out.");
18
+ }
19
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC3B,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,0CAA0C;IAC5C,CAAC;IACD,MAAM,SAAS,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function outdatedCommand(): Promise<void>;