@floomhq/floom 1.0.55 → 1.0.56
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/audit.js +27 -2
- package/dist/push-watch.js +25 -1
- package/dist/sync.js +1 -1
- package/package.json +1 -1
package/dist/audit.js
CHANGED
|
@@ -5,6 +5,7 @@ import { getJson, postJson } from "./lib/api.js";
|
|
|
5
5
|
import { FloomError } from "./errors.js";
|
|
6
6
|
import { c, symbols } from "./ui.js";
|
|
7
7
|
const FIXTURE_RE = /\b(?:cli lifecycle audit fixture|launch gate|temp skill|test fixture|audit fixture)\b/i;
|
|
8
|
+
const ARCHIVE_CHUNK_SIZE = 1000;
|
|
8
9
|
function contentHash(skill) {
|
|
9
10
|
return skill.content_sha256 ?? skill.content_hash ?? undefined;
|
|
10
11
|
}
|
|
@@ -71,10 +72,21 @@ function scoreSkill(skill, duplicateGroup) {
|
|
|
71
72
|
reasons,
|
|
72
73
|
...(hash ? { content_hash: hash } : {}),
|
|
73
74
|
...(duplicateGroup ? { duplicate_group: duplicateGroup } : {}),
|
|
74
|
-
recommended_action:
|
|
75
|
+
recommended_action: archiveRecommended(reasons) ? "archive" : "review",
|
|
75
76
|
safe: !reasons.includes("possible_secret"),
|
|
76
77
|
};
|
|
77
78
|
}
|
|
79
|
+
function archiveRecommended(reasons) {
|
|
80
|
+
if (reasons.includes("possible_secret"))
|
|
81
|
+
return true;
|
|
82
|
+
if (reasons.includes("launch_or_test_fixture"))
|
|
83
|
+
return true;
|
|
84
|
+
if (reasons.includes("blank_title") && reasons.includes("duplicate_content_hash"))
|
|
85
|
+
return true;
|
|
86
|
+
if (reasons.includes("near_empty_body") && reasons.includes("duplicate_content_hash"))
|
|
87
|
+
return true;
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
78
90
|
async function loadOwnedSkills() {
|
|
79
91
|
const cfg = await readConfig();
|
|
80
92
|
if (!cfg)
|
|
@@ -123,7 +135,20 @@ async function applyArchivePlan(planPath, yes, json) {
|
|
|
123
135
|
throw new FloomError("Not signed in.", "Run `npx -y @floomhq/floom login` first.");
|
|
124
136
|
const raw = JSON.parse(await readFile(planPath, "utf8"));
|
|
125
137
|
const slugs = archiveSlugsFromPlan(raw);
|
|
126
|
-
const
|
|
138
|
+
const chunks = [];
|
|
139
|
+
for (let i = 0; i < slugs.length; i += ARCHIVE_CHUNK_SIZE)
|
|
140
|
+
chunks.push(slugs.slice(i, i + ARCHIVE_CHUNK_SIZE));
|
|
141
|
+
const responses = [];
|
|
142
|
+
for (const chunk of chunks) {
|
|
143
|
+
responses.push(await postJson(`${resolveApiUrl(cfg)}/api/v1/me/skills/archive`, yes ? "archive skills" : "preview skill archive", cfg.accessToken, { slugs: chunk, dry_run: !yes }));
|
|
144
|
+
}
|
|
145
|
+
const payload = {
|
|
146
|
+
dry_run: responses.every((response) => response.dry_run),
|
|
147
|
+
requested: responses.reduce((sum, response) => sum + response.requested, 0),
|
|
148
|
+
matched: responses.flatMap((response) => response.matched),
|
|
149
|
+
missing: responses.flatMap((response) => response.missing),
|
|
150
|
+
...(yes ? { archived: responses.flatMap((response) => response.archived ?? []) } : {}),
|
|
151
|
+
};
|
|
127
152
|
if (json) {
|
|
128
153
|
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
129
154
|
return;
|
package/dist/push-watch.js
CHANGED
|
@@ -6,7 +6,7 @@ import { CONFIG_DIR } from "./config.js";
|
|
|
6
6
|
import { FloomError } from "./errors.js";
|
|
7
7
|
import { publishSkillPath } from "./publish.js";
|
|
8
8
|
import { readSkillPackage } from "./package.js";
|
|
9
|
-
import { manifestKey, markSynced, readSyncManifest, writeSyncManifest } from "./sync-manifest.js";
|
|
9
|
+
import { manifestKey, markSynced, readSyncManifest, unmarkSynced, writeSyncManifest } from "./sync-manifest.js";
|
|
10
10
|
import { c, symbols } from "./ui.js";
|
|
11
11
|
import { targetSkillsDir } from "./targets.js";
|
|
12
12
|
const MANIFEST_VERSION = 1;
|
|
@@ -134,10 +134,13 @@ export async function pushWatchOnce(opts) {
|
|
|
134
134
|
const pushManifest = await readPushManifest();
|
|
135
135
|
const syncManifest = await readSyncManifest();
|
|
136
136
|
const packages = await findSkillPackages(root);
|
|
137
|
+
const activePushKeys = new Set();
|
|
138
|
+
const activeSyncKeys = new Set();
|
|
137
139
|
let published = 0;
|
|
138
140
|
let updated = 0;
|
|
139
141
|
let adopted = 0;
|
|
140
142
|
let skipped = 0;
|
|
143
|
+
let syncManifestChanged = false;
|
|
141
144
|
for (const packagePath of packages) {
|
|
142
145
|
let skillPackage;
|
|
143
146
|
try {
|
|
@@ -152,12 +155,18 @@ export async function pushWatchOnce(opts) {
|
|
|
152
155
|
}
|
|
153
156
|
const key = safeRootRelative(root, skillPackage.skillPath);
|
|
154
157
|
const pushKey = pushManifestKey(opts.target, key);
|
|
158
|
+
activePushKeys.add(pushKey);
|
|
159
|
+
activeSyncKeys.add(manifestKey(root, skillPackage.skillPath));
|
|
160
|
+
for (const file of skillPackage.packageFiles) {
|
|
161
|
+
activeSyncKeys.add(manifestKey(root, join(dirname(skillPackage.skillPath), ...file.path.split("/"))));
|
|
162
|
+
}
|
|
155
163
|
const hash = hashPackage(key, skillPackage.skillBody, skillPackage.packageFiles);
|
|
156
164
|
const pushed = pushManifest.files[pushKey];
|
|
157
165
|
if (pushed?.hash === hash) {
|
|
158
166
|
if (!isUnchangedSyncedPackage(root, skillPackage, syncManifest)) {
|
|
159
167
|
adopted += 1;
|
|
160
168
|
markPackageSynced(root, skillPackage, syncManifest, pushed.slug);
|
|
169
|
+
syncManifestChanged = true;
|
|
161
170
|
await writeSyncManifest(syncManifest);
|
|
162
171
|
}
|
|
163
172
|
else {
|
|
@@ -202,6 +211,7 @@ export async function pushWatchOnce(opts) {
|
|
|
202
211
|
updated += 1;
|
|
203
212
|
pushManifest.files[pushKey] = { hash, slug, path: key, pushedAt: new Date().toISOString() };
|
|
204
213
|
markPackageSynced(root, skillPackage, syncManifest, slug);
|
|
214
|
+
syncManifestChanged = true;
|
|
205
215
|
await writeSyncManifest(syncManifest);
|
|
206
216
|
}
|
|
207
217
|
catch (err) {
|
|
@@ -210,6 +220,7 @@ export async function pushWatchOnce(opts) {
|
|
|
210
220
|
published += 1;
|
|
211
221
|
pushManifest.files[pushKey] = { hash, slug: result.data.slug, path: key, pushedAt: new Date().toISOString() };
|
|
212
222
|
markPackageSynced(root, skillPackage, syncManifest, result.data.slug);
|
|
223
|
+
syncManifestChanged = true;
|
|
213
224
|
await writeSyncManifest(syncManifest);
|
|
214
225
|
continue;
|
|
215
226
|
}
|
|
@@ -225,6 +236,7 @@ export async function pushWatchOnce(opts) {
|
|
|
225
236
|
published += 1;
|
|
226
237
|
pushManifest.files[pushKey] = { hash, slug: result.data.slug, path: key, pushedAt: new Date().toISOString() };
|
|
227
238
|
markPackageSynced(root, skillPackage, syncManifest, result.data.slug);
|
|
239
|
+
syncManifestChanged = true;
|
|
228
240
|
await writeSyncManifest(syncManifest);
|
|
229
241
|
}
|
|
230
242
|
catch (err) {
|
|
@@ -234,7 +246,19 @@ export async function pushWatchOnce(opts) {
|
|
|
234
246
|
}
|
|
235
247
|
}
|
|
236
248
|
}
|
|
249
|
+
for (const key of Object.keys(pushManifest.files)) {
|
|
250
|
+
if (key.startsWith(`${opts.target}:`) && !activePushKeys.has(key))
|
|
251
|
+
delete pushManifest.files[key];
|
|
252
|
+
}
|
|
253
|
+
for (const key of Object.keys(syncManifest.files)) {
|
|
254
|
+
if (!activeSyncKeys.has(key)) {
|
|
255
|
+
unmarkSynced(syncManifest, key);
|
|
256
|
+
syncManifestChanged = true;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
237
259
|
await writePushManifest(pushManifest);
|
|
260
|
+
if (syncManifestChanged)
|
|
261
|
+
await writeSyncManifest(syncManifest);
|
|
238
262
|
if (!opts.quiet && (published > 0 || updated > 0 || adopted > 0)) {
|
|
239
263
|
process.stdout.write(`${symbols.ok} Floom push watch: ${packages.length} scanned, ${published} published, ${updated} updated, ${adopted} adopted\n`);
|
|
240
264
|
}
|
package/dist/sync.js
CHANGED
|
@@ -547,7 +547,7 @@ async function loadSyncPayload(apiUrl, token) {
|
|
|
547
547
|
if (!Array.isArray(payload.skills))
|
|
548
548
|
throw new FloomError("Invalid sync response.");
|
|
549
549
|
all.push(...payload.skills);
|
|
550
|
-
fullSync = payload.full_sync === true;
|
|
550
|
+
fullSync = fullSync || payload.full_sync === true;
|
|
551
551
|
if (!payload.next_cursor) {
|
|
552
552
|
return { skills: all, full_sync: fullSync };
|
|
553
553
|
}
|