@floomhq/floom 1.0.35 → 1.0.37
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/cli.js +71 -4
- package/dist/errors.js +4 -1
- package/dist/lib/api.js +24 -1
- package/dist/push-watch.js +24 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -126,6 +126,75 @@ function commandUsage() {
|
|
|
126
126
|
`;
|
|
127
127
|
process.stdout.write(out);
|
|
128
128
|
}
|
|
129
|
+
function shareUsage() {
|
|
130
|
+
process.stdout.write(`
|
|
131
|
+
${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} share`)} ${c.dim("<slug> [flags]")}
|
|
132
|
+
|
|
133
|
+
${c.bold("Manage email access for one of your skills.")}
|
|
134
|
+
${c.cyan(`${CLI_COMMAND} share support-tone --add person@example.com`)}
|
|
135
|
+
${c.cyan(`${CLI_COMMAND} share support-tone --remove person@example.com`)}
|
|
136
|
+
${c.cyan(`${CLI_COMMAND} share support-tone --list`)}
|
|
137
|
+
|
|
138
|
+
${c.bold("Flags")}
|
|
139
|
+
${c.cyan("--add <email>")} Grant access
|
|
140
|
+
${c.cyan("--remove <email>")} Revoke access
|
|
141
|
+
${c.cyan("--list")} Show who can access the skill
|
|
142
|
+
`);
|
|
143
|
+
}
|
|
144
|
+
function libraryUsage() {
|
|
145
|
+
process.stdout.write(`
|
|
146
|
+
${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} library`)} ${c.dim("<command> [args] [flags]")}
|
|
147
|
+
|
|
148
|
+
${c.bold("Commands")}
|
|
149
|
+
${c.cyan("list")} Browse public libraries
|
|
150
|
+
${c.cyan("create <slug> --name <name>")} Create a library
|
|
151
|
+
${c.cyan("add <library> <skill>")} Add a skill to a library
|
|
152
|
+
${c.cyan("remove <library> <skill>")} Remove a skill from a library
|
|
153
|
+
${c.cyan("subscribe <library>")} Follow a library
|
|
154
|
+
${c.cyan("unsubscribe <library>")} Stop following a library
|
|
155
|
+
|
|
156
|
+
${c.bold("Examples")}
|
|
157
|
+
${c.cyan(`${CLI_COMMAND} library list --json`)}
|
|
158
|
+
${c.cyan(`${CLI_COMMAND} library create team-onboarding --name "Team onboarding" --public`)}
|
|
159
|
+
${c.cyan(`${CLI_COMMAND} library add team-onboarding support-tone --folder support --tags support,tone`)}
|
|
160
|
+
`);
|
|
161
|
+
}
|
|
162
|
+
function moveUsage() {
|
|
163
|
+
process.stdout.write(`
|
|
164
|
+
${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} move`)} ${c.dim("<slug> --folder <path> [--tag <tag>]")}
|
|
165
|
+
|
|
166
|
+
${c.bold("Place a saved or subscribed skill in a local folder.")}
|
|
167
|
+
${c.cyan(`${CLI_COMMAND} move support-tone --folder support/tone`)}
|
|
168
|
+
${c.cyan(`${CLI_COMMAND} move support-tone --root`)}
|
|
169
|
+
${c.cyan(`${CLI_COMMAND} move support-tone --folder support --tags support,tone`)}
|
|
170
|
+
|
|
171
|
+
${c.bold("Flags")}
|
|
172
|
+
${c.cyan("--folder <path>")} Folder path for synced installs
|
|
173
|
+
${c.cyan("--root")} Put the skill at the root
|
|
174
|
+
${c.cyan("--tag <tag>")} Add one tag, repeatable
|
|
175
|
+
${c.cyan("--tags a,b")} Add comma-separated tags
|
|
176
|
+
`);
|
|
177
|
+
}
|
|
178
|
+
function isHelpArg(value) {
|
|
179
|
+
return value === "--help" || value === "-h" || value === "help";
|
|
180
|
+
}
|
|
181
|
+
function subcommandUsage(cmd) {
|
|
182
|
+
switch (cmd) {
|
|
183
|
+
case "share":
|
|
184
|
+
shareUsage();
|
|
185
|
+
return true;
|
|
186
|
+
case "library":
|
|
187
|
+
case "lib":
|
|
188
|
+
libraryUsage();
|
|
189
|
+
return true;
|
|
190
|
+
case "move":
|
|
191
|
+
moveUsage();
|
|
192
|
+
return true;
|
|
193
|
+
default:
|
|
194
|
+
commandUsage();
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
129
198
|
const ASSET_TYPES = new Set(["knowledge", "instruction", "workflow", "skill"]);
|
|
130
199
|
const INSTALL_TARGETS = new Set([
|
|
131
200
|
"claude_skill",
|
|
@@ -695,10 +764,8 @@ async function main() {
|
|
|
695
764
|
// never block on update-notifier
|
|
696
765
|
}
|
|
697
766
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
if (rest.includes("--help") || rest.includes("-h") || rest.includes("help")) {
|
|
701
|
-
usage();
|
|
767
|
+
if (rest.some(isHelpArg)) {
|
|
768
|
+
subcommandUsage(cmd);
|
|
702
769
|
return;
|
|
703
770
|
}
|
|
704
771
|
try {
|
package/dist/errors.js
CHANGED
|
@@ -12,7 +12,7 @@ export class FloomError extends Error {
|
|
|
12
12
|
this.hint = hint;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
export function friendlyHttp(status, action) {
|
|
15
|
+
export function friendlyHttp(status, action, detail) {
|
|
16
16
|
if (status === 401) {
|
|
17
17
|
return new FloomError("Your token expired.", "Run `npx -y @floomhq/floom login` to refresh.");
|
|
18
18
|
}
|
|
@@ -34,6 +34,9 @@ export function friendlyHttp(status, action) {
|
|
|
34
34
|
if (status >= 500) {
|
|
35
35
|
return new FloomError("Floom is having trouble right now.", "Try again in a moment.");
|
|
36
36
|
}
|
|
37
|
+
if (detail) {
|
|
38
|
+
return new FloomError(detail);
|
|
39
|
+
}
|
|
37
40
|
return new FloomError(`Request failed (HTTP ${status}) while trying to ${action}.`);
|
|
38
41
|
}
|
|
39
42
|
export function friendlyNetwork(err) {
|
package/dist/lib/api.js
CHANGED
|
@@ -39,7 +39,7 @@ export async function floomFetch(url, action, opts = {}) {
|
|
|
39
39
|
continue;
|
|
40
40
|
}
|
|
41
41
|
if (opts.checkOk !== false && !res.ok) {
|
|
42
|
-
throw friendlyHttp(res.status, action);
|
|
42
|
+
throw friendlyHttp(res.status, action, await responseErrorDetail(res));
|
|
43
43
|
}
|
|
44
44
|
return res;
|
|
45
45
|
}
|
|
@@ -94,6 +94,29 @@ async function drainResponse(res) {
|
|
|
94
94
|
// Ignore bodies from rate-limit responses; the retry decision is header-based.
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
+
async function responseErrorDetail(res) {
|
|
98
|
+
try {
|
|
99
|
+
const text = await res.text();
|
|
100
|
+
if (!text.trim())
|
|
101
|
+
return null;
|
|
102
|
+
try {
|
|
103
|
+
const json = JSON.parse(text);
|
|
104
|
+
const detail = typeof json.error === "string"
|
|
105
|
+
? json.error
|
|
106
|
+
: typeof json.message === "string"
|
|
107
|
+
? json.message
|
|
108
|
+
: null;
|
|
109
|
+
const hint = typeof json.hint === "string" ? json.hint : null;
|
|
110
|
+
return [detail, hint].filter(Boolean).join("\n") || null;
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return text.trim().slice(0, 400);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
97
120
|
function sleep(ms) {
|
|
98
121
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
99
122
|
}
|
package/dist/push-watch.js
CHANGED
|
@@ -156,9 +156,32 @@ export async function pushWatchOnce(opts) {
|
|
|
156
156
|
const pushed = pushManifest.files[pushKey];
|
|
157
157
|
if (pushed?.hash === hash) {
|
|
158
158
|
if (!isUnchangedSyncedPackage(root, skillPackage, syncManifest)) {
|
|
159
|
+
if (opts.yolo) {
|
|
160
|
+
try {
|
|
161
|
+
await publishSkillPath({ file: packagePath, update: true, updateSlug: pushed.slug, quiet: true });
|
|
162
|
+
updated += 1;
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
if (err instanceof Error && /Skill not found/i.test(err.message)) {
|
|
166
|
+
const result = await publishSkillPath({ file: packagePath, visibility: "unlisted", quiet: true });
|
|
167
|
+
published += 1;
|
|
168
|
+
pushManifest.files[pushKey] = { hash, slug: result.data.slug, path: key, pushedAt: new Date().toISOString() };
|
|
169
|
+
markPackageSynced(root, skillPackage, syncManifest, result.data.slug);
|
|
170
|
+
await writeSyncManifest(syncManifest);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
skipped += 1;
|
|
174
|
+
if (!opts.quiet) {
|
|
175
|
+
process.stderr.write(`[floom] skipped ${packagePath}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
176
|
+
}
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
adopted += 1;
|
|
182
|
+
}
|
|
159
183
|
markPackageSynced(root, skillPackage, syncManifest, pushed.slug);
|
|
160
184
|
await writeSyncManifest(syncManifest);
|
|
161
|
-
adopted += 1;
|
|
162
185
|
}
|
|
163
186
|
else {
|
|
164
187
|
skipped += 1;
|