@floomhq/floom-mcp-sync 1.0.25 → 1.0.26
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/auto-sync.js +38 -1
- package/dist/lib/manifest.js +39 -1
- package/dist/server.js +1 -1
- package/dist/tools/get.js +39 -2
- package/package.json +1 -1
package/dist/auto-sync.js
CHANGED
|
@@ -17,7 +17,37 @@ const HEARTBEAT_MS = 10 * 60 * 1000; // 10 minutes
|
|
|
17
17
|
const AUTH_WARNING_MS = 10 * 60 * 1000;
|
|
18
18
|
const MANIFEST_SEGMENT_RE = /^[A-Za-z0-9._-]{1,128}$/;
|
|
19
19
|
const PACKAGE_FILE_SEGMENT_RE = /^[A-Za-z0-9._-]{1,128}$/;
|
|
20
|
-
const SUPPORT_DIRS = new Set([
|
|
20
|
+
const SUPPORT_DIRS = new Set([
|
|
21
|
+
"agents",
|
|
22
|
+
"assets",
|
|
23
|
+
"canvas-fonts",
|
|
24
|
+
"checks",
|
|
25
|
+
"core",
|
|
26
|
+
"evidence",
|
|
27
|
+
"examples",
|
|
28
|
+
"helpers",
|
|
29
|
+
"reference",
|
|
30
|
+
"references",
|
|
31
|
+
"schemas",
|
|
32
|
+
"scripts",
|
|
33
|
+
"spreadsheets",
|
|
34
|
+
"templates",
|
|
35
|
+
"tests",
|
|
36
|
+
"themes",
|
|
37
|
+
]);
|
|
38
|
+
const ROOT_FILE_EXTENSIONS = [
|
|
39
|
+
".env.example",
|
|
40
|
+
".js",
|
|
41
|
+
".json",
|
|
42
|
+
".md",
|
|
43
|
+
".py",
|
|
44
|
+
".sh",
|
|
45
|
+
".toml",
|
|
46
|
+
".ts",
|
|
47
|
+
".txt",
|
|
48
|
+
".yaml",
|
|
49
|
+
".yml",
|
|
50
|
+
];
|
|
21
51
|
const FD_PATH_ROOT = "/proc/self/fd";
|
|
22
52
|
const PACKAGE_FILE_LIMIT = 100;
|
|
23
53
|
const PACKAGE_TOTAL_BYTES_LIMIT = 1_000_000;
|
|
@@ -173,6 +203,8 @@ function normalizePackageFilePath(path) {
|
|
|
173
203
|
const segments = path.split("/").filter(Boolean);
|
|
174
204
|
if (segments.length === 1 && segments[0] === "SKILL.md")
|
|
175
205
|
return "SKILL.md";
|
|
206
|
+
if (segments.length === 1 && isAllowedRootPackageFile(segments[0] ?? ""))
|
|
207
|
+
return segments[0] ?? "";
|
|
176
208
|
const first = segments[0];
|
|
177
209
|
if (segments.length < 2 || first === undefined || !SUPPORT_DIRS.has(first)) {
|
|
178
210
|
throw new Error("Invalid package file path");
|
|
@@ -182,6 +214,11 @@ function normalizePackageFilePath(path) {
|
|
|
182
214
|
}
|
|
183
215
|
return segments.join("/");
|
|
184
216
|
}
|
|
217
|
+
function isAllowedRootPackageFile(name) {
|
|
218
|
+
if (!name || (name.startsWith(".") && name !== ".env.example"))
|
|
219
|
+
return false;
|
|
220
|
+
return ROOT_FILE_EXTENSIONS.some((ext) => name.toLowerCase().endsWith(ext));
|
|
221
|
+
}
|
|
185
222
|
async function planPackageSync(root, files, manifest) {
|
|
186
223
|
let missing = 0;
|
|
187
224
|
let unchanged = 0;
|
package/dist/lib/manifest.js
CHANGED
|
@@ -33,13 +33,51 @@ function isEntryForKey(key, value) {
|
|
|
33
33
|
function isPackageFilePath(packagePath) {
|
|
34
34
|
if (packagePath.length === 1 && packagePath[0] === "SKILL.md")
|
|
35
35
|
return true;
|
|
36
|
+
if (packagePath.length === 1 && isAllowedRootPackageFile(packagePath[0] ?? ""))
|
|
37
|
+
return true;
|
|
36
38
|
if (packagePath.length < 2)
|
|
37
39
|
return false;
|
|
38
40
|
const first = packagePath[0];
|
|
39
|
-
if (first === undefined || !
|
|
41
|
+
if (first === undefined || !SUPPORT_DIRS.has(first))
|
|
40
42
|
return false;
|
|
41
43
|
return packagePath.every((segment) => segment !== "." && segment !== ".." && segment.length > 0);
|
|
42
44
|
}
|
|
45
|
+
const SUPPORT_DIRS = new Set([
|
|
46
|
+
"agents",
|
|
47
|
+
"assets",
|
|
48
|
+
"canvas-fonts",
|
|
49
|
+
"checks",
|
|
50
|
+
"core",
|
|
51
|
+
"evidence",
|
|
52
|
+
"examples",
|
|
53
|
+
"helpers",
|
|
54
|
+
"reference",
|
|
55
|
+
"references",
|
|
56
|
+
"schemas",
|
|
57
|
+
"scripts",
|
|
58
|
+
"spreadsheets",
|
|
59
|
+
"templates",
|
|
60
|
+
"tests",
|
|
61
|
+
"themes",
|
|
62
|
+
]);
|
|
63
|
+
const ROOT_FILE_EXTENSIONS = [
|
|
64
|
+
".env.example",
|
|
65
|
+
".js",
|
|
66
|
+
".json",
|
|
67
|
+
".md",
|
|
68
|
+
".py",
|
|
69
|
+
".sh",
|
|
70
|
+
".toml",
|
|
71
|
+
".ts",
|
|
72
|
+
".txt",
|
|
73
|
+
".yaml",
|
|
74
|
+
".yml",
|
|
75
|
+
];
|
|
76
|
+
function isAllowedRootPackageFile(name) {
|
|
77
|
+
if (!name || (name.startsWith(".") && name !== ".env.example"))
|
|
78
|
+
return false;
|
|
79
|
+
return ROOT_FILE_EXTENSIONS.some((ext) => name.toLowerCase().endsWith(ext));
|
|
80
|
+
}
|
|
43
81
|
export async function readSyncManifest() {
|
|
44
82
|
try {
|
|
45
83
|
await ensureSyncManifestDir();
|
package/dist/server.js
CHANGED
|
@@ -5,7 +5,7 @@ import { autoSync } from "./auto-sync.js";
|
|
|
5
5
|
import { getSkill } from "./tools/get.js";
|
|
6
6
|
import { searchSkills } from "./tools/search.js";
|
|
7
7
|
import { syncStatus } from "./tools/status.js";
|
|
8
|
-
const SERVER_VERSION = "1.0.
|
|
8
|
+
const SERVER_VERSION = "1.0.26";
|
|
9
9
|
const DEFAULT_INTERVAL_MS = 60_000;
|
|
10
10
|
const MIN_INTERVAL_MS = 10_000;
|
|
11
11
|
const SEARCH_TYPES = new Set(["knowledge", "instruction", "workflow", "skill"]);
|
package/dist/tools/get.js
CHANGED
|
@@ -6,7 +6,37 @@ const PACKAGE_FILE_LIMIT = 100;
|
|
|
6
6
|
const PACKAGE_FILE_BYTES_LIMIT = 500_000;
|
|
7
7
|
const PACKAGE_TOTAL_BYTES_LIMIT = 1_000_000;
|
|
8
8
|
const PATH_SEGMENT_RE = /^[A-Za-z0-9._-]{1,128}$/;
|
|
9
|
-
const SUPPORT_DIRS = new Set([
|
|
9
|
+
const SUPPORT_DIRS = new Set([
|
|
10
|
+
"agents",
|
|
11
|
+
"assets",
|
|
12
|
+
"canvas-fonts",
|
|
13
|
+
"checks",
|
|
14
|
+
"core",
|
|
15
|
+
"evidence",
|
|
16
|
+
"examples",
|
|
17
|
+
"helpers",
|
|
18
|
+
"reference",
|
|
19
|
+
"references",
|
|
20
|
+
"schemas",
|
|
21
|
+
"scripts",
|
|
22
|
+
"spreadsheets",
|
|
23
|
+
"templates",
|
|
24
|
+
"tests",
|
|
25
|
+
"themes",
|
|
26
|
+
]);
|
|
27
|
+
const ROOT_FILE_EXTENSIONS = [
|
|
28
|
+
".env.example",
|
|
29
|
+
".js",
|
|
30
|
+
".json",
|
|
31
|
+
".md",
|
|
32
|
+
".py",
|
|
33
|
+
".sh",
|
|
34
|
+
".toml",
|
|
35
|
+
".ts",
|
|
36
|
+
".txt",
|
|
37
|
+
".yaml",
|
|
38
|
+
".yml",
|
|
39
|
+
];
|
|
10
40
|
const SHA256_RE = /^[a-f0-9]{64}$/i;
|
|
11
41
|
const BASE64_RE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
12
42
|
export async function getSkill(slug) {
|
|
@@ -30,7 +60,7 @@ export async function getSkill(slug) {
|
|
|
30
60
|
content: detail.body_md,
|
|
31
61
|
package: {
|
|
32
62
|
main: "SKILL.md",
|
|
33
|
-
supporting_dirs:
|
|
63
|
+
supporting_dirs: Array.from(SUPPORT_DIRS),
|
|
34
64
|
},
|
|
35
65
|
package_files: normalizePackageFiles(detail.package_files ?? detail.files),
|
|
36
66
|
};
|
|
@@ -103,9 +133,16 @@ function isSafePackagePath(path) {
|
|
|
103
133
|
if (!path || path.length > 512 || path.startsWith("/") || path.includes("\\") || path.includes("//"))
|
|
104
134
|
return false;
|
|
105
135
|
const segments = path.split("/");
|
|
136
|
+
if (segments.length === 1)
|
|
137
|
+
return isAllowedRootPackageFile(segments[0] ?? "") && PATH_SEGMENT_RE.test(segments[0] ?? "");
|
|
106
138
|
if (segments.length < 2)
|
|
107
139
|
return false;
|
|
108
140
|
if (!SUPPORT_DIRS.has(segments[0] ?? ""))
|
|
109
141
|
return false;
|
|
110
142
|
return segments.every((segment) => PATH_SEGMENT_RE.test(segment) && segment !== "." && segment !== "..");
|
|
111
143
|
}
|
|
144
|
+
function isAllowedRootPackageFile(name) {
|
|
145
|
+
if (!name || (name.startsWith(".") && name !== ".env.example"))
|
|
146
|
+
return false;
|
|
147
|
+
return ROOT_FILE_EXTENSIONS.some((ext) => name.toLowerCase().endsWith(ext));
|
|
148
|
+
}
|