@mcpmake/core 0.2.5 → 0.3.1
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/analyzer/dom-parser.d.ts +28 -0
- package/dist/analyzer/dom-parser.d.ts.map +1 -1
- package/dist/analyzer/dom-parser.js +77 -2
- package/dist/analyzer/dom-parser.js.map +1 -1
- package/dist/analyzer/goal-crawler.d.ts +3 -2
- package/dist/analyzer/goal-crawler.d.ts.map +1 -1
- package/dist/analyzer/goal-crawler.js +67 -18
- package/dist/analyzer/goal-crawler.js.map +1 -1
- package/dist/analyzer/semantic-analyzer.d.ts +2 -2
- package/dist/analyzer/semantic-analyzer.d.ts.map +1 -1
- package/dist/analyzer/semantic-analyzer.js +16 -17
- package/dist/analyzer/semantic-analyzer.js.map +1 -1
- package/dist/analyzer/site-crawler.d.ts.map +1 -1
- package/dist/analyzer/site-crawler.js +86 -12
- package/dist/analyzer/site-crawler.js.map +1 -1
- package/dist/config/mcpmake-config.d.ts.map +1 -1
- package/dist/config/mcpmake-config.js +5 -0
- package/dist/config/mcpmake-config.js.map +1 -1
- package/dist/emitter/code-writer.d.ts +1 -0
- package/dist/emitter/code-writer.d.ts.map +1 -1
- package/dist/emitter/code-writer.js +79 -12
- package/dist/emitter/code-writer.js.map +1 -1
- package/dist/emitter/index.d.ts +8 -0
- package/dist/emitter/index.d.ts.map +1 -1
- package/dist/emitter/index.js.map +1 -1
- package/dist/emitter/python-templates/dockerfile.hbs +4 -1
- package/dist/emitter/python-templates/server.py.hbs +4 -0
- package/dist/emitter/site-scaffolder.d.ts.map +1 -1
- package/dist/emitter/site-scaffolder.js +28 -1
- package/dist/emitter/site-scaffolder.js.map +1 -1
- package/dist/emitter/site-templates/browser-manager.ts.hbs +24 -3
- package/dist/emitter/site-templates/dockerfile.hbs +13 -4
- package/dist/emitter/site-templates/env.example.hbs +8 -0
- package/dist/emitter/site-templates/server-main-http.ts.hbs +53 -0
- package/dist/emitter/site-templates/telemetry.ts.hbs +117 -0
- package/dist/emitter/templates/auth-provider.ts.hbs +9 -5
- package/dist/emitter/templates/config.ts.hbs +22 -0
- package/dist/emitter/templates/dockerfile.hbs +12 -4
- package/dist/emitter/templates/oauth.ts.hbs +19 -65
- package/dist/emitter/templates/server-main-http.ts.hbs +33 -8
- package/dist/emitter/templates/task-handlers.ts.hbs +40 -1
- package/dist/emitter/worker-templates/worker.ts.hbs +88 -25
- package/dist/generator/spec-generator.d.ts.map +1 -1
- package/dist/generator/spec-generator.js +11 -56
- package/dist/generator/spec-generator.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/anthropic-provider.d.ts +14 -0
- package/dist/llm/anthropic-provider.d.ts.map +1 -0
- package/dist/llm/anthropic-provider.js +50 -0
- package/dist/llm/anthropic-provider.js.map +1 -0
- package/dist/llm/index.d.ts +19 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +116 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/openai-provider.d.ts +46 -0
- package/dist/llm/openai-provider.d.ts.map +1 -0
- package/dist/llm/openai-provider.js +245 -0
- package/dist/llm/openai-provider.js.map +1 -0
- package/dist/llm/types.d.ts +61 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/llm/types.js +16 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/parser/har-filter.d.ts +7 -0
- package/dist/parser/har-filter.d.ts.map +1 -1
- package/dist/parser/har-filter.js +107 -1
- package/dist/parser/har-filter.js.map +1 -1
- package/dist/parser/index.d.ts +1 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +1 -1
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/openapi-loader.d.ts.map +1 -1
- package/dist/parser/openapi-loader.js +36 -2
- package/dist/parser/openapi-loader.js.map +1 -1
- package/dist/parser/postman-loader.d.ts.map +1 -1
- package/dist/parser/postman-loader.js +6 -1
- package/dist/parser/postman-loader.js.map +1 -1
- package/dist/parser/schema-converter.d.ts.map +1 -1
- package/dist/parser/schema-converter.js +34 -23
- package/dist/parser/schema-converter.js.map +1 -1
- package/dist/plugins/loader.d.ts +5 -1
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +39 -10
- package/dist/plugins/loader.js.map +1 -1
- package/dist/pricing.d.ts +2 -1
- package/dist/pricing.d.ts.map +1 -1
- package/dist/pricing.js +11 -5
- package/dist/pricing.js.map +1 -1
- package/dist/recorder/browser-recorder.d.ts.map +1 -1
- package/dist/recorder/browser-recorder.js +50 -5
- package/dist/recorder/browser-recorder.js.map +1 -1
- package/dist/rescan/rescan-scheduler.d.ts.map +1 -1
- package/dist/rescan/rescan-scheduler.js +22 -7
- package/dist/rescan/rescan-scheduler.js.map +1 -1
- package/dist/site-transformer/selector-healer.d.ts +1 -1
- package/dist/site-transformer/selector-healer.d.ts.map +1 -1
- package/dist/site-transformer/selector-healer.js +17 -18
- package/dist/site-transformer/selector-healer.js.map +1 -1
- package/dist/transformer/auth-detector.d.ts.map +1 -1
- package/dist/transformer/auth-detector.js +13 -1
- package/dist/transformer/auth-detector.js.map +1 -1
- package/dist/transformer/har-schema-inferrer.d.ts.map +1 -1
- package/dist/transformer/har-schema-inferrer.js +2 -0
- package/dist/transformer/har-schema-inferrer.js.map +1 -1
- package/dist/transformer/har-to-operations.d.ts +1 -0
- package/dist/transformer/har-to-operations.d.ts.map +1 -1
- package/dist/transformer/har-to-operations.js +42 -10
- package/dist/transformer/har-to-operations.js.map +1 -1
- package/dist/transformer/llm-namer.d.ts +1 -1
- package/dist/transformer/llm-namer.d.ts.map +1 -1
- package/dist/transformer/llm-namer.js +12 -15
- package/dist/transformer/llm-namer.js.map +1 -1
- package/dist/transformer/tool-builder.d.ts.map +1 -1
- package/dist/transformer/tool-builder.js +30 -1
- package/dist/transformer/tool-builder.js.map +1 -1
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/fail.d.ts.map +1 -1
- package/dist/utils/fail.js +22 -4
- package/dist/utils/fail.js.map +1 -1
- package/dist/utils/json-extract.d.ts +21 -0
- package/dist/utils/json-extract.d.ts.map +1 -0
- package/dist/utils/json-extract.js +67 -0
- package/dist/utils/json-extract.js.map +1 -0
- package/dist/utils/model-resolver.d.ts.map +1 -1
- package/dist/utils/model-resolver.js +19 -4
- package/dist/utils/model-resolver.js.map +1 -1
- package/dist/utils/sanitize.d.ts +1 -1
- package/dist/utils/sanitize.d.ts.map +1 -1
- package/dist/utils/sanitize.js +6 -2
- package/dist/utils/sanitize.js.map +1 -1
- package/dist/utils/ssrf-guard.d.ts +10 -0
- package/dist/utils/ssrf-guard.d.ts.map +1 -0
- package/dist/utils/ssrf-guard.js +130 -0
- package/dist/utils/ssrf-guard.js.map +1 -0
- package/dist/utils/watcher.d.ts +17 -1
- package/dist/utils/watcher.d.ts.map +1 -1
- package/dist/utils/watcher.js +53 -21
- package/dist/utils/watcher.js.map +1 -1
- package/package.json +2 -1
package/dist/utils/fail.js
CHANGED
|
@@ -62,9 +62,27 @@ function redactHomePaths(input) {
|
|
|
62
62
|
out = out.replace(/\/(?:Users|home)\/[^/\s]+/g, '~');
|
|
63
63
|
return out;
|
|
64
64
|
}
|
|
65
|
-
/**
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Strip common credential formats from a header/URL-bearing string, replacing
|
|
67
|
+
* each secret value with `[redacted]` while keeping the surrounding structure
|
|
68
|
+
* (scheme, header name, param name) so the report stays useful for debugging.
|
|
69
|
+
*
|
|
70
|
+
* Covers, case-insensitively: `Authorization` bearer/basic schemes, `Cookie` /
|
|
71
|
+
* `Set-Cookie` header values, `x-api-key` / `api-key` / `apikey` header values,
|
|
72
|
+
* and `token` / `api_key` / `access_token` / `key` / `sig` query-string params.
|
|
73
|
+
* Every value pattern is `\S+` / `[^\s...]+` (no nested quantifiers), so there is
|
|
74
|
+
* no catastrophic-backtracking risk.
|
|
75
|
+
*/
|
|
76
|
+
function redactSecrets(input) {
|
|
77
|
+
return (input
|
|
78
|
+
// `Bearer <token>` / `Basic <base64>` (bare or after `Authorization:`).
|
|
79
|
+
.replace(/\b(Bearer|Basic)\s+\S+/gi, '$1 [redacted]')
|
|
80
|
+
// `Cookie:` / `Set-Cookie:` — drop the whole value up to end of line.
|
|
81
|
+
.replace(/\b(Set-Cookie|Cookie)\s*:\s*[^\r\n]*/gi, '$1: [redacted]')
|
|
82
|
+
// `x-api-key` / `api-key` / `apikey` header values (`:`-delimited).
|
|
83
|
+
.replace(/\b((?:x-)?api[-_]?key)\s*:\s*[^\s,;'"]+/gi, '$1: [redacted]')
|
|
84
|
+
// Query-string secrets: `token=`, `api_key=`, `access_token=`, `key=`, `sig=`.
|
|
85
|
+
.replace(/\b(access_token|api_key|apikey|token|sig|key)=[^\s&'"]+/gi, '$1=[redacted]'));
|
|
68
86
|
}
|
|
69
87
|
/** Strip mcpmake-style tokens (`mf_<hex>`). */
|
|
70
88
|
function redactMfTokens(input) {
|
|
@@ -81,7 +99,7 @@ function redactQueryStrings(input) {
|
|
|
81
99
|
* directly without invoking `fail()` (which calls `process.exit`).
|
|
82
100
|
*/
|
|
83
101
|
export function redactText(input) {
|
|
84
|
-
return redactQueryStrings(redactMfTokens(
|
|
102
|
+
return redactQueryStrings(redactMfTokens(redactSecrets(redactHomePaths(input))));
|
|
85
103
|
}
|
|
86
104
|
/** @deprecated internal alias — prefer the exported `redactText`. */
|
|
87
105
|
const redact = redactText;
|
package/dist/utils/fail.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fail.js","sourceRoot":"","sources":["../../src/utils/fail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEvD;;;;;;GAMG;AACH,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAA0B,CAAC;QAC/E,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;AAErC,mFAAmF;AACnF,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAIhC,+EAA+E;AAC/E,MAAM,IAAI,GAAG;IACX,OAAO,EAAE,GAAG;IACZ,YAAY,EAAE,IAAI;IAClB,KAAK,EAAE,MAAM;IACb,UAAU,EAAE,EAAE;IACd,QAAQ,EAAE,EAAE;IACZ,WAAW,EAAE,EAAE;CACP,CAAC;AAWX,8EAA8E;AAE9E,oFAAoF;AACpF,SAAS,eAAe,CAAC,KAAa;IACpC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,IAAI,IAAI,EAAE,CAAC;QACT,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IACD,2EAA2E;IAC3E,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"fail.js","sourceRoot":"","sources":["../../src/utils/fail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Robust extraction of JSON from raw LLM output.
|
|
3
|
+
*
|
|
4
|
+
* Models frequently wrap JSON in ```json fences or surround it with prose
|
|
5
|
+
* ("Here is the spec:" / "Hope this helps!"). These helpers locate the first
|
|
6
|
+
* balanced JSON value and return its exact substring, ignoring delimiters that
|
|
7
|
+
* appear inside quoted strings. The scan is single-pass and linear-time — no
|
|
8
|
+
* regex over the body, so there is no catastrophic-backtracking risk.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Return the substring spanning the first balanced top-level `{...}` object in
|
|
12
|
+
* `text`, or null if none. Robust to markdown fences and leading/trailing prose.
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractJsonObject(text: string): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Return the substring spanning the first balanced top-level JSON value in
|
|
17
|
+
* `text` — an object (`{...}`) or an array (`[...]`), whichever opens first —
|
|
18
|
+
* or null if none. Robust to markdown fences and leading/trailing prose.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractJsonValue(text: string): string | null;
|
|
21
|
+
//# sourceMappingURL=json-extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-extract.d.ts","sourceRoot":"","sources":["../../src/utils/json-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkCH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS5D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Robust extraction of JSON from raw LLM output.
|
|
3
|
+
*
|
|
4
|
+
* Models frequently wrap JSON in ```json fences or surround it with prose
|
|
5
|
+
* ("Here is the spec:" / "Hope this helps!"). These helpers locate the first
|
|
6
|
+
* balanced JSON value and return its exact substring, ignoring delimiters that
|
|
7
|
+
* appear inside quoted strings. The scan is single-pass and linear-time — no
|
|
8
|
+
* regex over the body, so there is no catastrophic-backtracking risk.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Return the substring spanning the first balanced top-level value opened by
|
|
12
|
+
* `open` (and closed by the matching `close`) in `text`, or null if none.
|
|
13
|
+
* String-aware: braces/brackets inside quoted strings are ignored.
|
|
14
|
+
*/
|
|
15
|
+
function extractBalanced(text, open, close) {
|
|
16
|
+
const start = text.indexOf(open);
|
|
17
|
+
if (start === -1)
|
|
18
|
+
return null;
|
|
19
|
+
let depth = 0;
|
|
20
|
+
let inString = false;
|
|
21
|
+
let escaped = false;
|
|
22
|
+
for (let i = start; i < text.length; i++) {
|
|
23
|
+
const ch = text[i];
|
|
24
|
+
if (inString) {
|
|
25
|
+
if (escaped)
|
|
26
|
+
escaped = false;
|
|
27
|
+
else if (ch === '\\')
|
|
28
|
+
escaped = true;
|
|
29
|
+
else if (ch === '"')
|
|
30
|
+
inString = false;
|
|
31
|
+
}
|
|
32
|
+
else if (ch === '"') {
|
|
33
|
+
inString = true;
|
|
34
|
+
}
|
|
35
|
+
else if (ch === open) {
|
|
36
|
+
depth++;
|
|
37
|
+
}
|
|
38
|
+
else if (ch === close) {
|
|
39
|
+
depth--;
|
|
40
|
+
if (depth === 0)
|
|
41
|
+
return text.slice(start, i + 1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Return the substring spanning the first balanced top-level `{...}` object in
|
|
48
|
+
* `text`, or null if none. Robust to markdown fences and leading/trailing prose.
|
|
49
|
+
*/
|
|
50
|
+
export function extractJsonObject(text) {
|
|
51
|
+
return extractBalanced(text, '{', '}');
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Return the substring spanning the first balanced top-level JSON value in
|
|
55
|
+
* `text` — an object (`{...}`) or an array (`[...]`), whichever opens first —
|
|
56
|
+
* or null if none. Robust to markdown fences and leading/trailing prose.
|
|
57
|
+
*/
|
|
58
|
+
export function extractJsonValue(text) {
|
|
59
|
+
const objStart = text.indexOf('{');
|
|
60
|
+
const arrStart = text.indexOf('[');
|
|
61
|
+
if (objStart === -1 && arrStart === -1)
|
|
62
|
+
return null;
|
|
63
|
+
// Whichever delimiter appears first wins; -1 means "not present".
|
|
64
|
+
const objFirst = arrStart === -1 || (objStart !== -1 && objStart < arrStart);
|
|
65
|
+
return objFirst ? extractBalanced(text, '{', '}') : extractBalanced(text, '[', ']');
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=json-extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-extract.js","sourceRoot":"","sources":["../../src/utils/json-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;GAIG;AACH,SAAS,eAAe,CAAC,IAAY,EAAE,IAAY,EAAE,KAAa;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,OAAO;gBAAE,OAAO,GAAG,KAAK,CAAC;iBACxB,IAAI,EAAE,KAAK,IAAI;gBAAE,OAAO,GAAG,IAAI,CAAC;iBAChC,IAAI,EAAE,KAAK,GAAG;gBAAE,QAAQ,GAAG,KAAK,CAAC;QACxC,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACvB,KAAK,EAAE,CAAC;QACV,CAAC;aAAM,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;YACxB,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEnC,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,kEAAkE;IAClE,MAAM,QAAQ,GAAG,QAAQ,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,GAAG,QAAQ,CAAC,CAAC;IAE7E,OAAO,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACtF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/model-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAG/C;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/model-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAG/C;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AA8B5C;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,SAAS,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CA6CjB"}
|
|
@@ -12,9 +12,17 @@ const TIER_PATTERN = {
|
|
|
12
12
|
balanced: /sonnet/i,
|
|
13
13
|
fast: /haiku/i,
|
|
14
14
|
};
|
|
15
|
-
// Resolved once per tier per process: the served-model list rarely
|
|
16
|
-
// mid-run, and we don't want a Models API round-trip before every call.
|
|
15
|
+
// Resolved once per (tier, baseURL) per process: the served-model list rarely
|
|
16
|
+
// changes mid-run, and we don't want a Models API round-trip before every call.
|
|
17
|
+
// The base URL is part of the key because two clients pointed at different
|
|
18
|
+
// endpoints (e.g. distinct Anthropic-compatible gateways) serve different model
|
|
19
|
+
// lists — keying on tier alone would leak the first endpoint's resolution to
|
|
20
|
+
// the second.
|
|
17
21
|
const cache = new Map();
|
|
22
|
+
/** Composite cache key so resolutions never cross endpoints. */
|
|
23
|
+
function cacheKey(tier, baseURL) {
|
|
24
|
+
return `${tier}::${baseURL}`;
|
|
25
|
+
}
|
|
18
26
|
/**
|
|
19
27
|
* Resolve a usable model id for a tier against the live Models API, so a retired
|
|
20
28
|
* model id can never silently 404 the way a hardcoded snapshot does.
|
|
@@ -30,7 +38,8 @@ const cache = new Map();
|
|
|
30
38
|
export async function resolveModel(client, tier, override) {
|
|
31
39
|
if (override)
|
|
32
40
|
return override;
|
|
33
|
-
const
|
|
41
|
+
const key = cacheKey(tier, client.baseURL ?? '');
|
|
42
|
+
const cached = cache.get(key);
|
|
34
43
|
if (cached)
|
|
35
44
|
return cached;
|
|
36
45
|
const preferred = PREFERRED[tier];
|
|
@@ -56,9 +65,15 @@ export async function resolveModel(client, tier, override) {
|
|
|
56
65
|
}
|
|
57
66
|
}
|
|
58
67
|
catch (err) {
|
|
68
|
+
// Transient Models API failure: return the fallback for this call WITHOUT
|
|
69
|
+
// caching it, so a later call retries once the API recovers (a poisoned
|
|
70
|
+
// cache would pin the whole process to the fallback alias).
|
|
59
71
|
logger.warn(`Could not list models (${err instanceof Error ? err.message : err}); using "${preferred}"`);
|
|
72
|
+
return preferred;
|
|
60
73
|
}
|
|
61
|
-
|
|
74
|
+
// Only successful resolutions are cached — the served-model list rarely
|
|
75
|
+
// changes mid-run, so one API round-trip per (tier, baseURL) is enough.
|
|
76
|
+
cache.set(key, choice);
|
|
62
77
|
return choice;
|
|
63
78
|
}
|
|
64
79
|
//# sourceMappingURL=model-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../src/utils/model-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AASrC;;;;GAIG;AACH,MAAM,SAAS,GAA8B;IAC3C,QAAQ,EAAE,mBAAmB;IAC7B,IAAI,EAAE,kBAAkB;CACzB,CAAC;AAEF,MAAM,YAAY,GAA8B;IAC9C,QAAQ,EAAE,SAAS;IACnB,IAAI,EAAE,QAAQ;CACf,CAAC;AAEF,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../src/utils/model-resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/sanitize.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sanitize a string for safe embedding in a JavaScript/TypeScript single-quoted string literal.
|
|
3
|
-
* Escapes backslashes, single quotes, and
|
|
3
|
+
* Escapes backslashes, single quotes, and CR/LF.
|
|
4
4
|
*/
|
|
5
5
|
export declare function escapeStringLiteral(str: string): string;
|
|
6
6
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,GAC3D,MAAM,CAUR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAStD;AAMD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMlD;AA0CD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpD;AAID;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD"}
|
package/dist/utils/sanitize.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sanitize a string for safe embedding in a JavaScript/TypeScript single-quoted string literal.
|
|
3
|
-
* Escapes backslashes, single quotes, and
|
|
3
|
+
* Escapes backslashes, single quotes, and CR/LF.
|
|
4
4
|
*/
|
|
5
5
|
export function escapeStringLiteral(str) {
|
|
6
|
-
return str
|
|
6
|
+
return str
|
|
7
|
+
.replace(/\\/g, '\\\\')
|
|
8
|
+
.replace(/'/g, "\\'")
|
|
9
|
+
.replace(/\n/g, '\\n')
|
|
10
|
+
.replace(/\r/g, '\\r');
|
|
7
11
|
}
|
|
8
12
|
/**
|
|
9
13
|
* Sanitize a string for safe embedding in a JavaScript/TypeScript template literal.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function privateHostsAllowed(): boolean;
|
|
2
|
+
/** Whether `ip` (a literal IPv4 or IPv6 address) is private, loopback, or reserved. */
|
|
3
|
+
export declare function isPrivateOrReservedIp(ip: string): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Throw if `urlString` is not a public http(s) URL. Resolves the host via DNS and
|
|
6
|
+
* rejects when any resolved address is private/loopback/link-local/reserved.
|
|
7
|
+
* Honors the `MCPMAKE_ALLOW_PRIVATE_HOSTS` escape hatch.
|
|
8
|
+
*/
|
|
9
|
+
export declare function assertPublicUrl(urlString: string): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=ssrf-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssrf-guard.d.ts","sourceRoot":"","sources":["../../src/utils/ssrf-guard.ts"],"names":[],"mappings":"AAyBA,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AA0CD,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKzD;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CtE"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { isIP } from 'node:net';
|
|
2
|
+
import { lookup } from 'node:dns/promises';
|
|
3
|
+
/**
|
|
4
|
+
* SSRF guard for outbound requests driven by untrusted input — crawled links,
|
|
5
|
+
* recorded navigations, and remote OpenAPI spec/`$ref` URLs.
|
|
6
|
+
*
|
|
7
|
+
* The browser crawler/recorder and the spec loader all fetch URLs that originate
|
|
8
|
+
* from user input or from an LLM/page following links. Without a host check they
|
|
9
|
+
* can be steered at `localhost`, RFC1918 intranets, or the cloud metadata
|
|
10
|
+
* endpoint (`169.254.169.254`). This module resolves a URL's host and rejects
|
|
11
|
+
* any that points at a private, loopback, link-local, or otherwise reserved
|
|
12
|
+
* address.
|
|
13
|
+
*
|
|
14
|
+
* Residual limitation (documented, not closed here): this checks at request time
|
|
15
|
+
* but does not pin DNS at the socket, so a TOCTOU/DNS-rebinding attacker who
|
|
16
|
+
* flips a record between this lookup and the browser's own connect can still slip
|
|
17
|
+
* through. Full DNS-pinning would require intercepting at the socket layer.
|
|
18
|
+
*
|
|
19
|
+
* Escape hatch: set `MCPMAKE_ALLOW_PRIVATE_HOSTS=1` to allow private/loopback
|
|
20
|
+
* targets (local development against `localhost` test servers).
|
|
21
|
+
*/
|
|
22
|
+
const ALLOW_ENV = 'MCPMAKE_ALLOW_PRIVATE_HOSTS';
|
|
23
|
+
export function privateHostsAllowed() {
|
|
24
|
+
return process.env[ALLOW_ENV] === '1' || process.env[ALLOW_ENV] === 'true';
|
|
25
|
+
}
|
|
26
|
+
/** Parse a dotted-quad IPv4 string into its four octets, or null if malformed. */
|
|
27
|
+
function ipv4Octets(ip) {
|
|
28
|
+
const parts = ip.split('.');
|
|
29
|
+
if (parts.length !== 4)
|
|
30
|
+
return null;
|
|
31
|
+
const nums = parts.map((p) => Number(p));
|
|
32
|
+
if (nums.some((n) => !Number.isInteger(n) || n < 0 || n > 255))
|
|
33
|
+
return null;
|
|
34
|
+
return nums;
|
|
35
|
+
}
|
|
36
|
+
function isPrivateIpv4(ip) {
|
|
37
|
+
const o = ipv4Octets(ip);
|
|
38
|
+
if (!o)
|
|
39
|
+
return false;
|
|
40
|
+
const [a, b] = o;
|
|
41
|
+
if (a === 0)
|
|
42
|
+
return true; // 0.0.0.0/8 "this network"
|
|
43
|
+
if (a === 10)
|
|
44
|
+
return true; // 10.0.0.0/8 private
|
|
45
|
+
if (a === 127)
|
|
46
|
+
return true; // 127.0.0.0/8 loopback
|
|
47
|
+
if (a === 169 && b === 254)
|
|
48
|
+
return true; // 169.254.0.0/16 link-local (cloud metadata)
|
|
49
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
50
|
+
return true; // 172.16.0.0/12 private
|
|
51
|
+
if (a === 192 && b === 168)
|
|
52
|
+
return true; // 192.168.0.0/16 private
|
|
53
|
+
if (a === 100 && b >= 64 && b <= 127)
|
|
54
|
+
return true; // 100.64.0.0/10 CGNAT
|
|
55
|
+
if (a === 192 && b === 0 && o[2] === 0)
|
|
56
|
+
return true; // 192.0.0.0/24 IETF protocol
|
|
57
|
+
if (a >= 224)
|
|
58
|
+
return true; // 224.0.0.0/4 multicast + 240.0.0.0/4 reserved + 255.* broadcast
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
function isPrivateIpv6(raw) {
|
|
62
|
+
const ip = raw.toLowerCase();
|
|
63
|
+
if (ip === '::1' || ip === '::')
|
|
64
|
+
return true; // loopback / unspecified
|
|
65
|
+
// IPv4-mapped (::ffff:a.b.c.d) and IPv4-compatible / NAT64 — re-check embedded v4.
|
|
66
|
+
const mapped = ip.match(/(?:::ffff:|::ffff:0:|64:ff9b::)(\d+\.\d+\.\d+\.\d+)$/);
|
|
67
|
+
if (mapped)
|
|
68
|
+
return isPrivateIpv4(mapped[1]);
|
|
69
|
+
if (ip.startsWith('fe8') || ip.startsWith('fe9') || ip.startsWith('fea') || ip.startsWith('feb'))
|
|
70
|
+
return true; // fe80::/10 link-local
|
|
71
|
+
if (ip.startsWith('fc') || ip.startsWith('fd'))
|
|
72
|
+
return true; // fc00::/7 unique-local
|
|
73
|
+
if (ip.startsWith('fec') || ip.startsWith('fed') || ip.startsWith('fee') || ip.startsWith('fef'))
|
|
74
|
+
return true; // fec0::/10 deprecated site-local
|
|
75
|
+
if (ip.startsWith('ff'))
|
|
76
|
+
return true; // ff00::/8 multicast
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
/** Whether `ip` (a literal IPv4 or IPv6 address) is private, loopback, or reserved. */
|
|
80
|
+
export function isPrivateOrReservedIp(ip) {
|
|
81
|
+
const kind = isIP(ip);
|
|
82
|
+
if (kind === 4)
|
|
83
|
+
return isPrivateIpv4(ip);
|
|
84
|
+
if (kind === 6)
|
|
85
|
+
return isPrivateIpv6(ip);
|
|
86
|
+
return false; // not an IP literal
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Throw if `urlString` is not a public http(s) URL. Resolves the host via DNS and
|
|
90
|
+
* rejects when any resolved address is private/loopback/link-local/reserved.
|
|
91
|
+
* Honors the `MCPMAKE_ALLOW_PRIVATE_HOSTS` escape hatch.
|
|
92
|
+
*/
|
|
93
|
+
export async function assertPublicUrl(urlString) {
|
|
94
|
+
let url;
|
|
95
|
+
try {
|
|
96
|
+
url = new URL(urlString);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
throw new Error(`Invalid URL: ${urlString}`);
|
|
100
|
+
}
|
|
101
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
102
|
+
throw new Error(`Refusing non-http(s) URL: ${urlString}`);
|
|
103
|
+
}
|
|
104
|
+
if (privateHostsAllowed())
|
|
105
|
+
return;
|
|
106
|
+
// Strip IPv6 brackets from the hostname for literal checks.
|
|
107
|
+
const host = url.hostname.replace(/^\[/, '').replace(/\]$/, '');
|
|
108
|
+
// Literal IP host — check directly, no DNS needed.
|
|
109
|
+
if (isIP(host)) {
|
|
110
|
+
if (isPrivateOrReservedIp(host)) {
|
|
111
|
+
throw new Error(`Refusing to access private/reserved address ${host} (set ${ALLOW_ENV}=1 to allow).`);
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Hostname — resolve every address it maps to and reject if ANY is private.
|
|
116
|
+
let addresses;
|
|
117
|
+
try {
|
|
118
|
+
addresses = await lookup(host, { all: true });
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
throw new Error(`Cannot resolve host "${host}" to verify it is public; refusing request.`);
|
|
122
|
+
}
|
|
123
|
+
for (const { address } of addresses) {
|
|
124
|
+
if (isPrivateOrReservedIp(address)) {
|
|
125
|
+
throw new Error(`Refusing request: host "${host}" resolves to private/reserved address ${address} ` +
|
|
126
|
+
`(set ${ALLOW_ENV}=1 to allow).`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=ssrf-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../../src/utils/ssrf-guard.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/watcher.d.ts
CHANGED
|
@@ -4,9 +4,25 @@ export interface WatchOptions {
|
|
|
4
4
|
onChange: () => Promise<void>;
|
|
5
5
|
debounceMs?: number;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Debounce + coalesce change notifications into regeneration runs.
|
|
9
|
+
*
|
|
10
|
+
* - Rapid bursts before a run are debounced into one run.
|
|
11
|
+
* - A change that arrives *while* a run is in flight sets a single `pending`
|
|
12
|
+
* flag, so exactly one trailing run fires afterwards. The flag (not a queue)
|
|
13
|
+
* caps the backlog at one regardless of how many events land mid-run, which
|
|
14
|
+
* avoids an unbounded backlog / memory growth.
|
|
15
|
+
*
|
|
16
|
+
* Exposed (and exported) separately from the fs binding so the coalescing logic
|
|
17
|
+
* is testable without relying on platform fs.watch event timing.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createChangeHandler(onChange: () => Promise<void>, debounceMs: number): {
|
|
20
|
+
notify: () => void;
|
|
21
|
+
};
|
|
7
22
|
/**
|
|
8
23
|
* Watch a file for changes and invoke a callback.
|
|
9
|
-
* Debounces rapid successive changes (e.g., editor save + format)
|
|
24
|
+
* Debounces rapid successive changes (e.g., editor save + format) and coalesces
|
|
25
|
+
* changes that arrive during a regeneration into a single trailing run.
|
|
10
26
|
*/
|
|
11
27
|
export declare function watchFile(options: WatchOptions): FSWatcher;
|
|
12
28
|
//# sourceMappingURL=watcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/utils/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAGhD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/utils/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAGhD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB;IAAE,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,CAmCxB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,CAa1D"}
|
package/dist/utils/watcher.js
CHANGED
|
@@ -1,34 +1,66 @@
|
|
|
1
1
|
import { watch } from 'node:fs';
|
|
2
2
|
import { logger } from './logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Debounce + coalesce change notifications into regeneration runs.
|
|
5
|
+
*
|
|
6
|
+
* - Rapid bursts before a run are debounced into one run.
|
|
7
|
+
* - A change that arrives *while* a run is in flight sets a single `pending`
|
|
8
|
+
* flag, so exactly one trailing run fires afterwards. The flag (not a queue)
|
|
9
|
+
* caps the backlog at one regardless of how many events land mid-run, which
|
|
10
|
+
* avoids an unbounded backlog / memory growth.
|
|
11
|
+
*
|
|
12
|
+
* Exposed (and exported) separately from the fs binding so the coalescing logic
|
|
13
|
+
* is testable without relying on platform fs.watch event timing.
|
|
14
|
+
*/
|
|
15
|
+
export function createChangeHandler(onChange, debounceMs) {
|
|
16
|
+
let timer;
|
|
17
|
+
let running = false;
|
|
18
|
+
let pending = false;
|
|
19
|
+
async function regenerate() {
|
|
20
|
+
running = true;
|
|
21
|
+
try {
|
|
22
|
+
do {
|
|
23
|
+
pending = false;
|
|
24
|
+
logger.info('Spec file changed, regenerating...');
|
|
25
|
+
try {
|
|
26
|
+
await onChange();
|
|
27
|
+
logger.success('Regeneration complete');
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
logger.error(`Regeneration failed: ${err instanceof Error ? err.message : err}`);
|
|
31
|
+
}
|
|
32
|
+
} while (pending);
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
running = false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
notify() {
|
|
40
|
+
if (running) {
|
|
41
|
+
pending = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (timer)
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
timer = setTimeout(() => {
|
|
47
|
+
void regenerate();
|
|
48
|
+
}, debounceMs);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
3
52
|
/**
|
|
4
53
|
* Watch a file for changes and invoke a callback.
|
|
5
|
-
* Debounces rapid successive changes (e.g., editor save + format)
|
|
54
|
+
* Debounces rapid successive changes (e.g., editor save + format) and coalesces
|
|
55
|
+
* changes that arrive during a regeneration into a single trailing run.
|
|
6
56
|
*/
|
|
7
57
|
export function watchFile(options) {
|
|
8
58
|
const debounceMs = options.debounceMs ?? 500;
|
|
9
|
-
|
|
10
|
-
let running = false;
|
|
59
|
+
const handler = createChangeHandler(options.onChange, debounceMs);
|
|
11
60
|
const watcher = watch(options.filePath, (eventType) => {
|
|
12
61
|
if (eventType !== 'change')
|
|
13
62
|
return;
|
|
14
|
-
|
|
15
|
-
return;
|
|
16
|
-
if (timer)
|
|
17
|
-
clearTimeout(timer);
|
|
18
|
-
timer = setTimeout(async () => {
|
|
19
|
-
running = true;
|
|
20
|
-
logger.info('Spec file changed, regenerating...');
|
|
21
|
-
try {
|
|
22
|
-
await options.onChange();
|
|
23
|
-
logger.success('Regeneration complete');
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
logger.error(`Regeneration failed: ${err instanceof Error ? err.message : err}`);
|
|
27
|
-
}
|
|
28
|
-
finally {
|
|
29
|
-
running = false;
|
|
30
|
-
}
|
|
31
|
-
}, debounceMs);
|
|
63
|
+
handler.notify();
|
|
32
64
|
});
|
|
33
65
|
logger.info(`Watching for changes: ${options.filePath}`);
|
|
34
66
|
logger.info('Press Ctrl+C to stop');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/utils/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAkB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/utils/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAkB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAA6B,EAC7B,UAAkB;IAElB,IAAI,KAAgD,CAAC;IACrD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,UAAU,UAAU;QACvB,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,CAAC;YACH,GAAG,CAAC;gBACF,OAAO,GAAG,KAAK,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;gBAClD,IAAI,CAAC;oBACH,MAAM,QAAQ,EAAE,CAAC;oBACjB,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;gBAC1C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,KAAK,CAAC,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;gBACnF,CAAC;YACH,CAAC,QAAQ,OAAO,EAAE;QACpB,CAAC;gBAAS,CAAC;YACT,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM;YACJ,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO;YACT,CAAC;YACD,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBACtB,KAAK,UAAU,EAAE,CAAC;YACpB,CAAC,EAAE,UAAU,CAAC,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,OAAqB;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC;IAC7C,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAElE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE;QACpD,IAAI,SAAS,KAAK,QAAQ;YAAE,OAAO;QACnC,OAAO,CAAC,MAAM,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,yBAAyB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAEpC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcpmake/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Shared generation library for mcpmake — parse APIs (OpenAPI/HAR/Postman/websites) and emit MCP servers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"handlebars": "^4.7.8",
|
|
36
36
|
"json-schema-to-zod": "^2.4.1",
|
|
37
37
|
"marked": "^12.0.2",
|
|
38
|
+
"openai": "^6.44.0",
|
|
38
39
|
"openapi-types": "^12.1.3",
|
|
39
40
|
"playwright": "^1.59.1",
|
|
40
41
|
"yaml": "^2.7.0"
|