comfyui-mcp 0.7.0 → 0.8.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.
- package/CHANGELOG.md +52 -0
- package/README.md +12 -0
- package/ROADMAP.md +15 -0
- package/dist/services/download-auth.d.ts +7 -0
- package/dist/services/download-auth.d.ts.map +1 -1
- package/dist/services/download-auth.js +26 -1
- package/dist/services/download-auth.js.map +1 -1
- package/dist/services/download-cache.d.ts +3 -1
- package/dist/services/download-cache.d.ts.map +1 -1
- package/dist/services/download-cache.js +45 -9
- package/dist/services/download-cache.js.map +1 -1
- package/dist/services/image-convert.d.ts +29 -0
- package/dist/services/image-convert.d.ts.map +1 -0
- package/dist/services/image-convert.js +218 -0
- package/dist/services/image-convert.js.map +1 -0
- package/dist/services/manifest.d.ts +63 -0
- package/dist/services/manifest.d.ts.map +1 -0
- package/dist/services/manifest.js +333 -0
- package/dist/services/manifest.js.map +1 -0
- package/dist/services/model-resolver.d.ts.map +1 -1
- package/dist/services/model-resolver.js +7 -1
- package/dist/services/model-resolver.js.map +1 -1
- package/dist/services/node-authoring.d.ts +5 -0
- package/dist/services/node-authoring.d.ts.map +1 -1
- package/dist/services/node-authoring.js +56 -0
- package/dist/services/node-authoring.js.map +1 -1
- package/dist/services/node-verify.d.ts +35 -0
- package/dist/services/node-verify.d.ts.map +1 -0
- package/dist/services/node-verify.js +138 -0
- package/dist/services/node-verify.js.map +1 -0
- package/dist/services/skill-cache.d.ts +26 -0
- package/dist/services/skill-cache.d.ts.map +1 -0
- package/dist/services/skill-cache.js +172 -0
- package/dist/services/skill-cache.js.map +1 -0
- package/dist/services/storage/azure-blob.d.ts +8 -0
- package/dist/services/storage/azure-blob.d.ts.map +1 -0
- package/dist/services/storage/azure-blob.js +146 -0
- package/dist/services/storage/azure-blob.js.map +1 -0
- package/dist/services/storage/hf.d.ts +7 -0
- package/dist/services/storage/hf.d.ts.map +1 -0
- package/dist/services/storage/hf.js +80 -0
- package/dist/services/storage/hf.js.map +1 -0
- package/dist/services/storage/http.d.ts +6 -0
- package/dist/services/storage/http.d.ts.map +1 -0
- package/dist/services/storage/http.js +41 -0
- package/dist/services/storage/http.js.map +1 -0
- package/dist/services/storage/index.d.ts +28 -0
- package/dist/services/storage/index.d.ts.map +1 -0
- package/dist/services/storage/index.js +42 -0
- package/dist/services/storage/index.js.map +1 -0
- package/dist/services/storage/s3.d.ts +12 -0
- package/dist/services/storage/s3.d.ts.map +1 -0
- package/dist/services/storage/s3.js +84 -0
- package/dist/services/storage/s3.js.map +1 -0
- package/dist/services/storage/types.d.ts +22 -0
- package/dist/services/storage/types.d.ts.map +1 -0
- package/dist/services/storage/types.js +2 -0
- package/dist/services/storage/types.js.map +1 -0
- package/dist/services/storage/utils.d.ts +6 -0
- package/dist/services/storage/utils.d.ts.map +1 -0
- package/dist/services/storage/utils.js +39 -0
- package/dist/services/storage/utils.js.map +1 -0
- package/dist/services/storage-upload.d.ts +18 -0
- package/dist/services/storage-upload.d.ts.map +1 -0
- package/dist/services/storage-upload.js +121 -0
- package/dist/services/storage-upload.js.map +1 -0
- package/dist/tools/image-convert.d.ts +3 -0
- package/dist/tools/image-convert.d.ts.map +1 -0
- package/dist/tools/image-convert.js +58 -0
- package/dist/tools/image-convert.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/manifest.d.ts +3 -0
- package/dist/tools/manifest.d.ts.map +1 -0
- package/dist/tools/manifest.js +25 -0
- package/dist/tools/manifest.js.map +1 -0
- package/dist/tools/model-management.d.ts.map +1 -1
- package/dist/tools/model-management.js +9 -1
- package/dist/tools/model-management.js.map +1 -1
- package/dist/tools/node-authoring.d.ts.map +1 -1
- package/dist/tools/node-authoring.js +8 -2
- package/dist/tools/node-authoring.js.map +1 -1
- package/dist/tools/node-verify.d.ts +3 -0
- package/dist/tools/node-verify.d.ts.map +1 -0
- package/dist/tools/node-verify.js +42 -0
- package/dist/tools/node-verify.js.map +1 -0
- package/dist/tools/skill-generator.d.ts.map +1 -1
- package/dist/tools/skill-generator.js +16 -3
- package/dist/tools/skill-generator.js.map +1 -1
- package/dist/tools/storage-upload.d.ts +3 -0
- package/dist/tools/storage-upload.d.ts.map +1 -0
- package/dist/tools/storage-upload.js +57 -0
- package/dist/tools/storage-upload.js.map +1 -0
- package/package.json +5 -1
- package/scripts/gen-tool-docs.ts +6 -5
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface VerifyOptions {
|
|
2
|
+
/** Pack folder under custom_nodes/; used to infer class_types and for messaging. */
|
|
3
|
+
name?: string;
|
|
4
|
+
/** The NODE_CLASS_MAPPINGS keys expected to appear in /object_info. */
|
|
5
|
+
classTypes?: string[];
|
|
6
|
+
/** Restart ComfyUI before checking (default true). Set false to check the live server as-is. */
|
|
7
|
+
restart?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface VerifyResult {
|
|
10
|
+
ready: boolean;
|
|
11
|
+
restarted: boolean;
|
|
12
|
+
expected: string[];
|
|
13
|
+
loaded: string[];
|
|
14
|
+
missing: string[];
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
export interface VerifyDeps {
|
|
18
|
+
/** Restart ComfyUI; resolves once it is ready (or the readiness wait times out). */
|
|
19
|
+
restart: () => Promise<{
|
|
20
|
+
ready: boolean;
|
|
21
|
+
message: string;
|
|
22
|
+
}>;
|
|
23
|
+
/** Return the set of registered node class_types from /object_info. */
|
|
24
|
+
fetchObjectInfoKeys: () => Promise<string[]>;
|
|
25
|
+
/** Read a pack's __init__.py contents, or undefined if absent. */
|
|
26
|
+
readPackInit: (packName: string) => string | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse NODE_CLASS_MAPPINGS keys from an __init__.py. Best-effort regex (Python
|
|
30
|
+
* isn't parsed) — good enough for the common `{ "Key": Cls, ... }` literal the
|
|
31
|
+
* scaffold and most packs use. Returns [] when it can't find a literal.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseClassMappingKeys(initPy: string): string[];
|
|
34
|
+
export declare function verifyCustomNode(options: VerifyOptions, deps?: VerifyDeps): Promise<VerifyResult>;
|
|
35
|
+
//# sourceMappingURL=node-verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-verify.d.ts","sourceRoot":"","sources":["../../src/services/node-verify.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gGAAgG;IAChG,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,oFAAoF;IACpF,OAAO,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,uEAAuE;IACvE,mBAAmB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,kEAAkE;IAClE,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACxD;AAqCD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B9D;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,IAAI,GAAE,UAAwB,GAC7B,OAAO,CAAC,YAAY,CAAC,CA8EvB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { config, getComfyUIApiHost, getComfyUIProtocol } from "../config.js";
|
|
4
|
+
import { restartComfyUI } from "./process-control.js";
|
|
5
|
+
import { ComfyUIError, ProcessControlError, ValidationError } from "../utils/errors.js";
|
|
6
|
+
import { logger } from "../utils/logger.js";
|
|
7
|
+
const defaultDeps = {
|
|
8
|
+
restart: async () => {
|
|
9
|
+
const result = await restartComfyUI();
|
|
10
|
+
return { ready: result.readiness?.ready ?? false, message: result.message };
|
|
11
|
+
},
|
|
12
|
+
fetchObjectInfoKeys: async () => {
|
|
13
|
+
const url = `${getComfyUIProtocol()}://${getComfyUIApiHost()}/object_info`;
|
|
14
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(30_000) });
|
|
15
|
+
if (!res.ok) {
|
|
16
|
+
throw new ComfyUIError(`Failed to fetch /object_info: ${res.status} ${res.statusText}`, "OBJECT_INFO_FAILED");
|
|
17
|
+
}
|
|
18
|
+
const data = await res.json();
|
|
19
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
20
|
+
throw new ComfyUIError("Unexpected /object_info response (not a JSON object).", "OBJECT_INFO_FAILED");
|
|
21
|
+
}
|
|
22
|
+
return Object.keys(data);
|
|
23
|
+
},
|
|
24
|
+
readPackInit: (packName) => {
|
|
25
|
+
if (!config.comfyuiPath)
|
|
26
|
+
return undefined;
|
|
27
|
+
const initPath = join(config.comfyuiPath, "custom_nodes", packName, "__init__.py");
|
|
28
|
+
if (!existsSync(initPath))
|
|
29
|
+
return undefined;
|
|
30
|
+
try {
|
|
31
|
+
return readFileSync(initPath, "utf-8");
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Parse NODE_CLASS_MAPPINGS keys from an __init__.py. Best-effort regex (Python
|
|
40
|
+
* isn't parsed) — good enough for the common `{ "Key": Cls, ... }` literal the
|
|
41
|
+
* scaffold and most packs use. Returns [] when it can't find a literal.
|
|
42
|
+
*/
|
|
43
|
+
export function parseClassMappingKeys(initPy) {
|
|
44
|
+
const assign = initPy.search(/NODE_CLASS_MAPPINGS\s*=\s*\{/);
|
|
45
|
+
if (assign < 0)
|
|
46
|
+
return [];
|
|
47
|
+
const open = initPy.indexOf("{", assign);
|
|
48
|
+
// Find the brace that closes the literal by depth-counting, so a brace inside
|
|
49
|
+
// a value (e.g. `"Foo": make({"x": 1})`) doesn't truncate the block.
|
|
50
|
+
let depth = 0;
|
|
51
|
+
let end = -1;
|
|
52
|
+
for (let i = open; i < initPy.length; i += 1) {
|
|
53
|
+
if (initPy[i] === "{")
|
|
54
|
+
depth += 1;
|
|
55
|
+
else if (initPy[i] === "}") {
|
|
56
|
+
depth -= 1;
|
|
57
|
+
if (depth === 0) {
|
|
58
|
+
end = i;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const body = end > open ? initPy.slice(open + 1, end) : initPy.slice(open + 1);
|
|
64
|
+
// Match keys at the start of a line only, so keys of inline nested dicts in a
|
|
65
|
+
// value (mid-line) are not mistaken for top-level node class_types.
|
|
66
|
+
const keys = [];
|
|
67
|
+
const keyRe = /^[ \t]*["']([^"'\n]+)["']\s*:/gm;
|
|
68
|
+
let m;
|
|
69
|
+
while ((m = keyRe.exec(body)) !== null)
|
|
70
|
+
keys.push(m[1]);
|
|
71
|
+
return keys;
|
|
72
|
+
}
|
|
73
|
+
export async function verifyCustomNode(options, deps = defaultDeps) {
|
|
74
|
+
if (!config.comfyuiPath) {
|
|
75
|
+
throw new ProcessControlError("verify_custom_node is local-only: it restarts and inspects a local ComfyUI " +
|
|
76
|
+
"install and needs COMFYUI_PATH. It cannot verify a remote --comfyui-url target.");
|
|
77
|
+
}
|
|
78
|
+
// Resolve the expected class_types: explicit list wins, else infer from the pack.
|
|
79
|
+
let expected = (options.classTypes ?? []).map((s) => s.trim()).filter(Boolean);
|
|
80
|
+
if (expected.length === 0) {
|
|
81
|
+
if (!options.name) {
|
|
82
|
+
throw new ValidationError("Provide `class_types` (the NODE_CLASS_MAPPINGS keys to check) or a `name` " +
|
|
83
|
+
"whose __init__.py declares them.");
|
|
84
|
+
}
|
|
85
|
+
const initPy = deps.readPackInit(options.name);
|
|
86
|
+
if (!initPy) {
|
|
87
|
+
throw new ValidationError(`Could not read __init__.py for pack "${options.name}" to infer its node ` +
|
|
88
|
+
`class_types. Pass class_types explicitly.`);
|
|
89
|
+
}
|
|
90
|
+
expected = parseClassMappingKeys(initPy);
|
|
91
|
+
if (expected.length === 0) {
|
|
92
|
+
throw new ValidationError(`Could not find NODE_CLASS_MAPPINGS keys in "${options.name}"/__init__.py. ` +
|
|
93
|
+
`Pass class_types explicitly.`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Restart so newly-added packs are (re)loaded, unless the caller opted out.
|
|
97
|
+
const shouldRestart = options.restart !== false;
|
|
98
|
+
let ready = true;
|
|
99
|
+
let restartMessage = "Skipped restart; checked the running server as-is.";
|
|
100
|
+
if (shouldRestart) {
|
|
101
|
+
const r = await deps.restart();
|
|
102
|
+
ready = r.ready;
|
|
103
|
+
restartMessage = r.message;
|
|
104
|
+
if (!ready) {
|
|
105
|
+
return {
|
|
106
|
+
ready: false,
|
|
107
|
+
restarted: true,
|
|
108
|
+
expected,
|
|
109
|
+
loaded: [],
|
|
110
|
+
missing: expected,
|
|
111
|
+
message: `ComfyUI did not become ready after restart, so node loading could not be ` +
|
|
112
|
+
`verified. ${restartMessage}`,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const registered = new Set(await deps.fetchObjectInfoKeys());
|
|
117
|
+
const loaded = expected.filter((c) => registered.has(c));
|
|
118
|
+
const missing = expected.filter((c) => !registered.has(c));
|
|
119
|
+
const ok = missing.length === 0;
|
|
120
|
+
logger.info("Verified custom node", {
|
|
121
|
+
name: options.name,
|
|
122
|
+
loaded: loaded.length,
|
|
123
|
+
missing: missing.length,
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
ready,
|
|
127
|
+
restarted: shouldRestart,
|
|
128
|
+
expected,
|
|
129
|
+
loaded,
|
|
130
|
+
missing,
|
|
131
|
+
message: ok
|
|
132
|
+
? `All ${expected.length} node type(s) registered in ComfyUI. The pack loads correctly.`
|
|
133
|
+
: `${missing.length} of ${expected.length} node type(s) are NOT registered: ` +
|
|
134
|
+
`${missing.join(", ")}. The pack likely failed to import — check ComfyUI logs ` +
|
|
135
|
+
`(a missing dependency or a syntax error keeps a node out of /object_info).`,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=node-verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-verify.js","sourceRoot":"","sources":["../../src/services/node-verify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getNodePackDetails } from "./registry-client.js";
|
|
2
|
+
export interface SkillCacheMetadata {
|
|
3
|
+
source: string;
|
|
4
|
+
version: string;
|
|
5
|
+
cachedAt: string;
|
|
6
|
+
contentHash: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GenerateSkillCachedOptions {
|
|
9
|
+
refresh?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface GenerateSkillCachedResult {
|
|
12
|
+
markdown: string;
|
|
13
|
+
cacheHit: boolean;
|
|
14
|
+
cacheDir: string;
|
|
15
|
+
safeKey: string;
|
|
16
|
+
metadata: SkillCacheMetadata;
|
|
17
|
+
}
|
|
18
|
+
export interface SkillCacheDeps {
|
|
19
|
+
generate: (source: string) => Promise<string>;
|
|
20
|
+
getDetails: typeof getNodePackDetails;
|
|
21
|
+
now: () => Date;
|
|
22
|
+
}
|
|
23
|
+
export declare function normalizeSkillSource(source: string): string;
|
|
24
|
+
export declare function buildSkillCacheKey(source: string, version: string): string;
|
|
25
|
+
export declare function generateSkillCached(source: string, options?: GenerateSkillCachedOptions, deps?: SkillCacheDeps): Promise<GenerateSkillCachedResult>;
|
|
26
|
+
//# sourceMappingURL=skill-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-cache.d.ts","sourceRoot":"","sources":["../../src/services/skill-cache.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAM1D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,UAAU,EAAE,OAAO,kBAAkB,CAAC;IACtC,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAoBD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAY3D;AAWD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1E;AAgHD,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,0BAA+B,EACxC,IAAI,GAAE,cAA4B,GACjC,OAAO,CAAC,yBAAyB,CAAC,CAmCpC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { generateSkill } from "./skill-generator.js";
|
|
6
|
+
import { getNodePackDetails } from "./registry-client.js";
|
|
7
|
+
import { logger } from "../utils/logger.js";
|
|
8
|
+
const DEFAULT_CACHE_DIR = join(homedir(), ".comfyui-mcp", "skill-cache");
|
|
9
|
+
const HASH_CHARS = 12;
|
|
10
|
+
const defaultDeps = {
|
|
11
|
+
generate: generateSkill,
|
|
12
|
+
getDetails: getNodePackDetails,
|
|
13
|
+
now: () => new Date(),
|
|
14
|
+
};
|
|
15
|
+
function cacheDir() {
|
|
16
|
+
return resolve(process.env.COMFYUI_SKILL_CACHE_DIR || DEFAULT_CACHE_DIR);
|
|
17
|
+
}
|
|
18
|
+
function shortHash(value) {
|
|
19
|
+
return createHash("sha256").update(value).digest("hex").slice(0, HASH_CHARS);
|
|
20
|
+
}
|
|
21
|
+
function contentHash(value) {
|
|
22
|
+
return createHash("sha256").update(value).digest("hex");
|
|
23
|
+
}
|
|
24
|
+
export function normalizeSkillSource(source) {
|
|
25
|
+
const trimmed = source.trim();
|
|
26
|
+
try {
|
|
27
|
+
const url = new URL(trimmed);
|
|
28
|
+
url.hash = "";
|
|
29
|
+
url.search = "";
|
|
30
|
+
url.hostname = url.hostname.toLowerCase();
|
|
31
|
+
url.pathname = url.pathname.replace(/\/+$/, "").replace(/\.git$/, "");
|
|
32
|
+
return url.toString().replace(/\/$/, "");
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return trimmed.replace(/\/+$/, "");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function safeSegment(value) {
|
|
39
|
+
const segment = value
|
|
40
|
+
.toLowerCase()
|
|
41
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
42
|
+
.replace(/^-+|-+$/g, "")
|
|
43
|
+
.slice(0, 64);
|
|
44
|
+
return segment || "source";
|
|
45
|
+
}
|
|
46
|
+
export function buildSkillCacheKey(source, version) {
|
|
47
|
+
const normalized = normalizeSkillSource(source);
|
|
48
|
+
return `${safeSegment(normalized)}-${safeSegment(version)}-${shortHash(`${normalized}\0${version}`)}`;
|
|
49
|
+
}
|
|
50
|
+
async function resolveVersion(source, deps) {
|
|
51
|
+
const normalized = normalizeSkillSource(source);
|
|
52
|
+
if (!normalized.includes("github.com")) {
|
|
53
|
+
try {
|
|
54
|
+
const details = await deps.getDetails(normalized);
|
|
55
|
+
return details.latest_version || details.versions?.[0]?.version || `source-${shortHash(normalized)}`;
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
logger.warn("Could not resolve node pack version for skill cache; using source hash", {
|
|
59
|
+
source,
|
|
60
|
+
error: err instanceof Error ? err.message : String(err),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return `source-${shortHash(normalized)}`;
|
|
65
|
+
}
|
|
66
|
+
function parseMetadata(raw) {
|
|
67
|
+
try {
|
|
68
|
+
const data = JSON.parse(raw);
|
|
69
|
+
if (typeof data.source === "string" &&
|
|
70
|
+
typeof data.version === "string" &&
|
|
71
|
+
typeof data.cachedAt === "string" &&
|
|
72
|
+
typeof data.contentHash === "string") {
|
|
73
|
+
return {
|
|
74
|
+
source: data.source,
|
|
75
|
+
version: data.version,
|
|
76
|
+
cachedAt: data.cachedAt,
|
|
77
|
+
contentHash: data.contentHash,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Ignore corrupt cache entries.
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
function isNotFoundError(err) {
|
|
87
|
+
return (typeof err === "object" &&
|
|
88
|
+
err !== null &&
|
|
89
|
+
"code" in err &&
|
|
90
|
+
err.code === "ENOENT");
|
|
91
|
+
}
|
|
92
|
+
async function readCachedSkill(source, version, dir, safeKey) {
|
|
93
|
+
const normalized = normalizeSkillSource(source);
|
|
94
|
+
const entryDir = join(dir, safeKey);
|
|
95
|
+
let metadataRaw;
|
|
96
|
+
try {
|
|
97
|
+
metadataRaw = await readFile(join(entryDir, "metadata.json"), "utf-8");
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
if (isNotFoundError(err))
|
|
101
|
+
return undefined;
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
const metadata = parseMetadata(metadataRaw);
|
|
105
|
+
if (!metadata ||
|
|
106
|
+
normalizeSkillSource(metadata.source) !== normalized ||
|
|
107
|
+
metadata.version !== version) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
let markdown;
|
|
111
|
+
try {
|
|
112
|
+
markdown = await readFile(join(entryDir, "SKILL.md"), "utf-8");
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
if (isNotFoundError(err))
|
|
116
|
+
return undefined;
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
if (contentHash(markdown) !== metadata.contentHash) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return { markdown, cacheHit: true, cacheDir: dir, safeKey, metadata };
|
|
123
|
+
}
|
|
124
|
+
async function writeCachedSkill(dir, safeKey, markdown, metadata) {
|
|
125
|
+
const entryDir = join(dir, safeKey);
|
|
126
|
+
const suffix = `.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
127
|
+
const skillPath = join(entryDir, "SKILL.md");
|
|
128
|
+
const metadataPath = join(entryDir, "metadata.json");
|
|
129
|
+
const tempSkillPath = join(entryDir, `SKILL.md${suffix}`);
|
|
130
|
+
const tempMetadataPath = join(entryDir, `metadata.json${suffix}`);
|
|
131
|
+
await mkdir(entryDir, { recursive: true });
|
|
132
|
+
await writeFile(tempSkillPath, markdown, "utf-8");
|
|
133
|
+
await writeFile(tempMetadataPath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
134
|
+
await rename(tempSkillPath, skillPath);
|
|
135
|
+
await rename(tempMetadataPath, metadataPath);
|
|
136
|
+
}
|
|
137
|
+
export async function generateSkillCached(source, options = {}, deps = defaultDeps) {
|
|
138
|
+
const dir = cacheDir();
|
|
139
|
+
const version = await resolveVersion(source, deps);
|
|
140
|
+
const safeKey = buildSkillCacheKey(source, version);
|
|
141
|
+
if (!options.refresh) {
|
|
142
|
+
try {
|
|
143
|
+
const cached = await readCachedSkill(source, version, dir, safeKey);
|
|
144
|
+
if (cached)
|
|
145
|
+
return cached;
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
logger.warn("Skill cache read failed; generating without cache hit", {
|
|
149
|
+
source,
|
|
150
|
+
error: err instanceof Error ? err.message : String(err),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const markdown = await deps.generate(source);
|
|
155
|
+
const metadata = {
|
|
156
|
+
source,
|
|
157
|
+
version,
|
|
158
|
+
cachedAt: deps.now().toISOString(),
|
|
159
|
+
contentHash: contentHash(markdown),
|
|
160
|
+
};
|
|
161
|
+
try {
|
|
162
|
+
await writeCachedSkill(dir, safeKey, markdown, metadata);
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
logger.warn("Skill cache write failed; returning generated skill without caching", {
|
|
166
|
+
source,
|
|
167
|
+
error: err instanceof Error ? err.message : String(err),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return { markdown, cacheHit: false, cacheDir: dir, safeKey, metadata };
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=skill-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-cache.js","sourceRoot":"","sources":["../../src/services/skill-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StorageUploadResult, StorageUploadSource } from "./types.js";
|
|
2
|
+
export declare function isAzureBlobUrl(url: string): boolean;
|
|
3
|
+
export declare function downloadAzureBlobToFile(url: string, targetPath: string): Promise<void>;
|
|
4
|
+
export declare function uploadAzureBlobFile(source: StorageUploadSource, destination: {
|
|
5
|
+
container: string;
|
|
6
|
+
blob_prefix?: string;
|
|
7
|
+
}): Promise<StorageUploadResult>;
|
|
8
|
+
//# sourceMappingURL=azure-blob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-blob.d.ts","sourceRoot":"","sources":["../../../src/services/storage/azure-blob.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAM3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD;AAsGD,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5F;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,mBAAmB,CAAC,CAmB9B"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { createReadStream, createWriteStream } from "node:fs";
|
|
2
|
+
import { pipeline } from "node:stream/promises";
|
|
3
|
+
import { BlobClient, BlobServiceClient, StorageSharedKeyCredential, } from "@azure/storage-blob";
|
|
4
|
+
import { ModelError, ValidationError } from "../../utils/errors.js";
|
|
5
|
+
import { redactUrlForLogs } from "../download-auth.js";
|
|
6
|
+
import { safeErrorDetails, withPrefix } from "./utils.js";
|
|
7
|
+
const AZURE_BLOB_HOST_SUFFIX = ".blob.core.windows.net";
|
|
8
|
+
const AZURE_ACCOUNT_RE = /^[a-z0-9]{3,24}$/;
|
|
9
|
+
export function isAzureBlobUrl(url) {
|
|
10
|
+
try {
|
|
11
|
+
const parsed = new URL(url);
|
|
12
|
+
return parsed.protocol === "https:" && accountFromBlobHost(parsed.hostname) !== undefined;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function hasQuery(url) {
|
|
19
|
+
try {
|
|
20
|
+
return new URL(url).search.length > 1;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function accountFromBlobHost(hostname) {
|
|
27
|
+
if (!hostname.endsWith(AZURE_BLOB_HOST_SUFFIX))
|
|
28
|
+
return undefined;
|
|
29
|
+
const account = hostname.slice(0, -AZURE_BLOB_HOST_SUFFIX.length);
|
|
30
|
+
return AZURE_ACCOUNT_RE.test(account) ? account : undefined;
|
|
31
|
+
}
|
|
32
|
+
function accountFromConnectionString(connectionString) {
|
|
33
|
+
const account = /(?:^|;)AccountName=([^;]+)/i.exec(connectionString)?.[1];
|
|
34
|
+
if (account)
|
|
35
|
+
return account.toLowerCase();
|
|
36
|
+
const endpoint = /(?:^|;)BlobEndpoint=([^;]+)/i.exec(connectionString)?.[1];
|
|
37
|
+
if (!endpoint)
|
|
38
|
+
return undefined;
|
|
39
|
+
try {
|
|
40
|
+
return accountFromBlobHost(new URL(endpoint).hostname);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function blobServiceClientFromEnv() {
|
|
47
|
+
const connectionString = process.env.AZURE_STORAGE_CONNECTION_STRING;
|
|
48
|
+
if (connectionString) {
|
|
49
|
+
return {
|
|
50
|
+
account: accountFromConnectionString(connectionString),
|
|
51
|
+
client: BlobServiceClient.fromConnectionString(connectionString),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const account = process.env.AZURE_STORAGE_ACCOUNT;
|
|
55
|
+
const key = process.env.AZURE_STORAGE_KEY;
|
|
56
|
+
if (account && key) {
|
|
57
|
+
const normalizedAccount = account.toLowerCase();
|
|
58
|
+
return {
|
|
59
|
+
account: normalizedAccount,
|
|
60
|
+
client: new BlobServiceClient(`https://${normalizedAccount}.blob.core.windows.net`, new StorageSharedKeyCredential(normalizedAccount, key)),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
function parseAzureBlobUrl(url) {
|
|
66
|
+
let parsed;
|
|
67
|
+
try {
|
|
68
|
+
parsed = new URL(url);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
throw new ValidationError("Invalid Azure Blob URL.");
|
|
72
|
+
}
|
|
73
|
+
const account = accountFromBlobHost(parsed.hostname);
|
|
74
|
+
if (parsed.protocol !== "https:" || !account) {
|
|
75
|
+
throw new ValidationError("Invalid Azure Blob URL. Expected https://<account>.blob.core.windows.net/<container>/<blob>.");
|
|
76
|
+
}
|
|
77
|
+
const parts = parsed.pathname.split("/").filter(Boolean);
|
|
78
|
+
if (parts.length < 2) {
|
|
79
|
+
throw new ValidationError("Invalid Azure Blob URL. Expected https://<account>.blob.core.windows.net/<container>/<blob>.");
|
|
80
|
+
}
|
|
81
|
+
return { account, container: parts[0], blob: parts.slice(1).join("/") };
|
|
82
|
+
}
|
|
83
|
+
function blobClientForDownload(url) {
|
|
84
|
+
const parsed = parseAzureBlobUrl(url);
|
|
85
|
+
if (hasQuery(url)) {
|
|
86
|
+
return new BlobClient(url);
|
|
87
|
+
}
|
|
88
|
+
const envClient = blobServiceClientFromEnv();
|
|
89
|
+
if (envClient) {
|
|
90
|
+
if (!envClient.account || envClient.account !== parsed.account) {
|
|
91
|
+
throw new ValidationError("Azure Blob URL account must match configured Azure storage account.");
|
|
92
|
+
}
|
|
93
|
+
return envClient.client.getContainerClient(parsed.container).getBlobClient(parsed.blob);
|
|
94
|
+
}
|
|
95
|
+
return new BlobClient(url);
|
|
96
|
+
}
|
|
97
|
+
function blobServiceClientForUpload() {
|
|
98
|
+
const envClient = blobServiceClientFromEnv();
|
|
99
|
+
if (!envClient) {
|
|
100
|
+
throw new ValidationError("Azure upload requires AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT plus AZURE_STORAGE_KEY.");
|
|
101
|
+
}
|
|
102
|
+
return envClient.client;
|
|
103
|
+
}
|
|
104
|
+
export async function downloadAzureBlobToFile(url, targetPath) {
|
|
105
|
+
try {
|
|
106
|
+
const response = await blobClientForDownload(url).download();
|
|
107
|
+
if (!response.readableStreamBody) {
|
|
108
|
+
throw new ModelError("Azure Blob download response has no body", {
|
|
109
|
+
url: redactUrlForLogs(url),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
await pipeline(response.readableStreamBody, createWriteStream(targetPath));
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
if (err instanceof ModelError || err instanceof ValidationError)
|
|
116
|
+
throw err;
|
|
117
|
+
throw new ModelError("Azure Blob download failed", {
|
|
118
|
+
url: redactUrlForLogs(url),
|
|
119
|
+
...safeErrorDetails(err),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export async function uploadAzureBlobFile(source, destination) {
|
|
124
|
+
const blobName = withPrefix(destination.blob_prefix, source.filename);
|
|
125
|
+
try {
|
|
126
|
+
const blockBlobClient = blobServiceClientForUpload()
|
|
127
|
+
.getContainerClient(destination.container)
|
|
128
|
+
.getBlockBlobClient(blobName);
|
|
129
|
+
const options = source.contentType
|
|
130
|
+
? { blobHTTPHeaders: { blobContentType: source.contentType } }
|
|
131
|
+
: undefined;
|
|
132
|
+
if (source.path) {
|
|
133
|
+
await blockBlobClient.uploadStream(createReadStream(source.path), undefined, undefined, options);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
await blockBlobClient.uploadData(source.data ?? Buffer.alloc(0), options);
|
|
137
|
+
}
|
|
138
|
+
return { provider: "azure", url: redactUrlForLogs(blockBlobClient.url) };
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
if (err instanceof ValidationError)
|
|
142
|
+
throw err;
|
|
143
|
+
throw new ModelError("Azure Blob upload failed", safeErrorDetails(err));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=azure-blob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-blob.js","sourceRoot":"","sources":["../../../src/services/storage/azure-blob.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { StorageUploadResult, StorageUploadSource } from "./types.js";
|
|
2
|
+
export declare function uploadHfFile(source: StorageUploadSource, destination: {
|
|
3
|
+
repo: string;
|
|
4
|
+
repo_type?: "model" | "dataset" | "space";
|
|
5
|
+
path?: string;
|
|
6
|
+
}): Promise<StorageUploadResult>;
|
|
7
|
+
//# sourceMappingURL=hf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hf.d.ts","sourceRoot":"","sources":["../../../src/services/storage/hf.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAyC3E,wBAAsB,YAAY,CAChC,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACtF,OAAO,CAAC,mBAAmB,CAAC,CAoC9B"}
|