@floomhq/floom 1.0.16 → 1.0.18
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/package.js +5 -0
- package/dist/secrets.js +1 -1
- package/dist/sync.js +5 -5
- package/package.json +1 -1
package/dist/package.js
CHANGED
|
@@ -253,6 +253,7 @@ export function normalizeRemotePackageFiles(input) {
|
|
|
253
253
|
throw new FloomError("Skill package response has too many files.");
|
|
254
254
|
}
|
|
255
255
|
let totalBytes = 0;
|
|
256
|
+
const seenPaths = new Set();
|
|
256
257
|
return input.map((raw) => {
|
|
257
258
|
if (!raw || typeof raw !== "object")
|
|
258
259
|
throw new FloomError("Invalid skill package response.");
|
|
@@ -260,6 +261,10 @@ export function normalizeRemotePackageFiles(input) {
|
|
|
260
261
|
if (typeof file.path !== "string")
|
|
261
262
|
throw new FloomError("Invalid skill package response.");
|
|
262
263
|
validatePackageRelativePath(file.path);
|
|
264
|
+
const pathKey = file.path.toLowerCase();
|
|
265
|
+
if (seenPaths.has(pathKey))
|
|
266
|
+
throw new FloomError(`Duplicate package file: ${file.path}`);
|
|
267
|
+
seenPaths.add(pathKey);
|
|
263
268
|
let bytes;
|
|
264
269
|
if (typeof file.content_base64 === "string") {
|
|
265
270
|
if (file.encoding !== undefined && file.encoding !== "base64") {
|
package/dist/secrets.js
CHANGED
|
@@ -13,7 +13,7 @@ const SECRET_PATTERNS = [
|
|
|
13
13
|
];
|
|
14
14
|
const GENERIC_ASSIGNMENT_RE = /\b(?:api[_-]?key|secret|access[_-]?token|auth[_-]?token|bearer[_-]?token)\b\s*[:=]\s*["']?([A-Za-z0-9_./+=-]{24,})["']?/gi;
|
|
15
15
|
const PROVIDER_LIKE_ASSIGNMENT_RE = /\b(?:api[_-]?key|secret|access[_-]?token|auth[_-]?token|bearer[_-]?token)\b\s*[:=]\s*["']?((?:sk|pk|rk)-[A-Za-z0-9_-]{8,}|sbp_[A-Za-z0-9]{12,}|xox[baprs]-[A-Za-z0-9-]{12,})["']?/gi;
|
|
16
|
-
const PLACEHOLDER_RE = /(?:^|[_./+=-])(?:your|example|placeholder|replace|changeme|todo|xxx|demo|dummy|fake|redacted)(?:$|[_./+=-])/i;
|
|
16
|
+
const PLACEHOLDER_RE = /(?:^|[_./+=-])(?:your|example|sample|placeholder|replace|changeme|todo|xxx|test|demo|dummy|fake|mock|staging|dev|local|redacted)(?:$|[_./+=-])/i;
|
|
17
17
|
const PROMPT_INJECTION_PATTERNS = [
|
|
18
18
|
{ label: "Prompt injection instruction", regex: /\bignore (?:all )?(?:previous|prior|above|earlier) instructions\b/gi },
|
|
19
19
|
{ label: "Prompt injection instruction", regex: /\bdisregard (?:all )?(?:previous|prior|above|earlier) instructions\b/gi },
|
package/dist/sync.js
CHANGED
|
@@ -159,6 +159,7 @@ function syncPackageFiles(target, body, files) {
|
|
|
159
159
|
async function planPackageSync(root, files, manifest) {
|
|
160
160
|
let missing = 0;
|
|
161
161
|
let unchanged = 0;
|
|
162
|
+
let firstMissingTarget = null;
|
|
162
163
|
for (const file of files) {
|
|
163
164
|
const targetKey = manifestKey(root, file.target);
|
|
164
165
|
const tracked = manifest.files[targetKey];
|
|
@@ -179,8 +180,7 @@ async function planPackageSync(root, files, manifest) {
|
|
|
179
180
|
if (state.kind === "conflict")
|
|
180
181
|
return { kind: "conflict", target: state.conflictTarget ?? file.target, reason: state.reason };
|
|
181
182
|
if (state.kind === "missing") {
|
|
182
|
-
|
|
183
|
-
return { kind: "conflict", target: file.target, reason: "local package file missing since the last Floom sync" };
|
|
183
|
+
firstMissingTarget ??= file.target;
|
|
184
184
|
missing += 1;
|
|
185
185
|
continue;
|
|
186
186
|
}
|
|
@@ -196,10 +196,9 @@ async function planPackageSync(root, files, manifest) {
|
|
|
196
196
|
return { kind: "unchanged" };
|
|
197
197
|
if (missing === files.length)
|
|
198
198
|
return { kind: "write" };
|
|
199
|
-
const missingFile = files.find((file) => !manifest.files[manifestKey(root, file.target)]);
|
|
200
199
|
return {
|
|
201
200
|
kind: "conflict",
|
|
202
|
-
target:
|
|
201
|
+
target: firstMissingTarget ?? files[0]?.target ?? root,
|
|
203
202
|
reason: "local package is only partially installed",
|
|
204
203
|
};
|
|
205
204
|
}
|
|
@@ -301,6 +300,7 @@ export async function sync(opts = {}) {
|
|
|
301
300
|
const activeTargetKeys = new Set();
|
|
302
301
|
const pruneBlockedSlugs = new Set();
|
|
303
302
|
let manifestChanged = false;
|
|
303
|
+
let synced = 0;
|
|
304
304
|
const noteConflict = (target, reason) => {
|
|
305
305
|
conflicts += 1;
|
|
306
306
|
const rel = manifestKey(root, target);
|
|
@@ -334,6 +334,7 @@ export async function sync(opts = {}) {
|
|
|
334
334
|
}
|
|
335
335
|
const remotePackageFiles = normalizeRemotePackageFiles(skill.package_files ?? skill.files);
|
|
336
336
|
const packageFiles = syncPackageFiles(target, skill.body_md, remotePackageFiles);
|
|
337
|
+
synced += 1;
|
|
337
338
|
for (const file of packageFiles)
|
|
338
339
|
activeTargetKeys.add(manifestKey(root, file.target));
|
|
339
340
|
const plan = await planPackageSync(root, packageFiles, manifest);
|
|
@@ -421,7 +422,6 @@ export async function sync(opts = {}) {
|
|
|
421
422
|
throw err;
|
|
422
423
|
}
|
|
423
424
|
spinner?.stop();
|
|
424
|
-
const synced = activeTargetKeys.size;
|
|
425
425
|
const skippedNote = skipped > 0 ? c.dim(` (${skipped} skipped — invalid path)`) : "";
|
|
426
426
|
const conflictNote = conflicts > 0 ? c.dim(`, ${conflicts} conflict${conflicts === 1 ? "" : "s"} skipped`) : "";
|
|
427
427
|
const result = { synced, unchanged, updated, skipped, conflicts };
|