@frontmcp/utils 1.10.15 → 1.11.0-rc.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.
Files changed (137) hide show
  1. package/README.md +1 -0
  2. package/browser/async-context/browser-async-context.mjs +177 -0
  3. package/browser/async-context/index.mjs +15 -0
  4. package/browser/async-context/overlap-error.mjs +10 -0
  5. package/browser/class-brand/class-brand.mjs +27 -0
  6. package/browser/class-brand/index.mjs +6 -0
  7. package/browser/content/content.mjs +151 -0
  8. package/browser/content/index.mjs +8 -0
  9. package/browser/crypto/browser.mjs +103 -0
  10. package/browser/crypto/encrypted-blob.mjs +119 -0
  11. package/browser/crypto/hmac-signing.mjs +70 -0
  12. package/browser/crypto/index.mjs +281 -0
  13. package/browser/crypto/jwt-alg.mjs +40 -0
  14. package/browser/crypto/key-persistence/factory.mjs +134 -0
  15. package/browser/crypto/key-persistence/index.mjs +26 -0
  16. package/browser/crypto/key-persistence/key-persistence.mjs +185 -0
  17. package/browser/crypto/key-persistence/schemas.mjs +82 -0
  18. package/browser/crypto/pkce/index.mjs +25 -0
  19. package/browser/crypto/pkce/pkce.mjs +59 -0
  20. package/browser/crypto/runtime.mjs +17 -0
  21. package/browser/crypto/secret-persistence/index.mjs +29 -0
  22. package/browser/crypto/secret-persistence/persistence.mjs +181 -0
  23. package/browser/crypto/secret-persistence/schema.mjs +40 -0
  24. package/browser/crypto/web-rsa.mjs +36 -0
  25. package/browser/env/browser-env.mjs +56 -0
  26. package/browser/env/browser-runtime-context.mjs +85 -0
  27. package/browser/env/build-target.mjs +25 -0
  28. package/browser/env/edge-scope.mjs +17 -0
  29. package/browser/env/index.mjs +47 -0
  30. package/browser/env/provider.mjs +46 -0
  31. package/browser/escape/escape.mjs +43 -0
  32. package/browser/escape/index.mjs +9 -0
  33. package/browser/event-emitter/browser-event-emitter.mjs +49 -0
  34. package/browser/event-emitter/index.mjs +5 -0
  35. package/browser/fs/fs.mjs +227 -0
  36. package/browser/fs/index.mjs +65 -0
  37. package/browser/http/cookie.mjs +85 -0
  38. package/browser/http/http.mjs +18 -0
  39. package/browser/http/index.mjs +11 -0
  40. package/browser/index.mjs +526 -0
  41. package/browser/llm/index.mjs +5 -0
  42. package/browser/llm/llm-tool-handlers.mjs +55 -0
  43. package/browser/machine-id/index.mjs +7 -0
  44. package/browser/machine-id/machine-id.mjs +108 -0
  45. package/browser/naming/index.mjs +10 -0
  46. package/browser/naming/naming.mjs +68 -0
  47. package/browser/net/index.mjs +10 -0
  48. package/browser/net/ip-address.mjs +128 -0
  49. package/browser/net/redirect.mjs +7 -0
  50. package/browser/path/browser-path.mjs +47 -0
  51. package/browser/path/index.mjs +24 -0
  52. package/browser/path/path.mjs +13 -0
  53. package/browser/process/child-process.mjs +23 -0
  54. package/browser/process/index.mjs +15 -0
  55. package/browser/process/owned-process.mjs +175 -0
  56. package/browser/process/process-tree.mjs +149 -0
  57. package/browser/process/process-watch.mjs +48 -0
  58. package/browser/redaction/index.mjs +6 -0
  59. package/browser/redaction/redaction.mjs +74 -0
  60. package/browser/regex/index.mjs +3 -0
  61. package/browser/regex/patterns.mjs +167 -0
  62. package/browser/regex/safe-regex.mjs +93 -0
  63. package/browser/serialization/index.mjs +5 -0
  64. package/browser/serialization/serialization.mjs +22 -0
  65. package/browser/stdio-bridge/errors.mjs +27 -0
  66. package/browser/stdio-bridge/index.mjs +24 -0
  67. package/browser/stdio-bridge/list-changed.mjs +21 -0
  68. package/browser/stdio-bridge/state-machine.mjs +211 -0
  69. package/browser/stdio-bridge/stdio-framer.mjs +91 -0
  70. package/browser/stdio-bridge/upstream-client.mjs +189 -0
  71. package/browser/storage/adapters/base.mjs +139 -0
  72. package/browser/storage/adapters/cloudflare-kv.mjs +149 -0
  73. package/browser/storage/adapters/filesystem.mjs +279 -0
  74. package/browser/storage/adapters/index.mjs +23 -0
  75. package/browser/storage/adapters/indexeddb.mjs +198 -0
  76. package/browser/storage/adapters/localstorage.mjs +222 -0
  77. package/browser/storage/adapters/memory.mjs +350 -0
  78. package/browser/storage/adapters/redis.mjs +497 -0
  79. package/browser/storage/adapters/upstash.mjs +299 -0
  80. package/browser/storage/adapters/vercel-kv.mjs +226 -0
  81. package/browser/storage/change-feed.mjs +189 -0
  82. package/browser/storage/encrypted-typed-storage.mjs +329 -0
  83. package/browser/storage/errors.mjs +92 -0
  84. package/browser/storage/factory.mjs +155 -0
  85. package/browser/storage/index.mjs +96 -0
  86. package/browser/storage/namespace.mjs +186 -0
  87. package/browser/storage/redis-error-listener.mjs +32 -0
  88. package/browser/storage/redis-url.mjs +66 -0
  89. package/browser/storage/typed-storage.mjs +171 -0
  90. package/browser/storage/utils/compare-and-delete.mjs +9 -0
  91. package/browser/storage/utils/index.mjs +24 -0
  92. package/browser/storage/utils/pattern.mjs +68 -0
  93. package/browser/storage/utils/ttl.mjs +48 -0
  94. package/browser/uri/index.mjs +19 -0
  95. package/browser/uri/uri-template.mjs +86 -0
  96. package/browser/uri/uri-validation.mjs +18 -0
  97. package/content/content.d.ts +8 -0
  98. package/content/index.d.ts +1 -1
  99. package/crypto/browser.d.ts +1 -13
  100. package/crypto/browser.js +1 -1
  101. package/crypto/node.js +1 -1
  102. package/crypto/web-rsa.d.ts +13 -0
  103. package/env/browser-runtime-context.js +1 -1
  104. package/env/runtime-context.js +1 -1
  105. package/esm/crypto/browser.mjs +1 -1
  106. package/esm/crypto/node.mjs +1 -1
  107. package/esm/env/browser-runtime-context.mjs +1 -1
  108. package/esm/env/runtime-context.mjs +1 -1
  109. package/esm/index.mjs +1 -1
  110. package/fs/fs.d.ts +45 -4
  111. package/fs/index.d.ts +1 -1
  112. package/index.d.ts +10 -4
  113. package/index.js +1 -1
  114. package/package.json +24 -8
  115. package/process/child-process.d.ts +2 -0
  116. package/process/index.d.ts +6 -0
  117. package/process/owned-process.d.ts +59 -0
  118. package/process/process-tree.d.ts +78 -0
  119. package/process/process-watch.d.ts +41 -0
  120. package/redaction/index.d.ts +2 -0
  121. package/redaction/redaction.d.ts +24 -0
  122. package/stdio-bridge/errors.d.ts +23 -0
  123. package/stdio-bridge/index.d.ts +9 -0
  124. package/stdio-bridge/list-changed.d.ts +3 -0
  125. package/stdio-bridge/state-machine.d.ts +61 -0
  126. package/stdio-bridge/stdio-framer.d.ts +49 -0
  127. package/stdio-bridge/types.d.ts +10 -0
  128. package/stdio-bridge/upstream-client.d.ts +66 -0
  129. package/storage/adapters/base.d.ts +2 -0
  130. package/storage/adapters/memory.d.ts +1 -0
  131. package/storage/adapters/redis.d.ts +3 -0
  132. package/storage/change-feed.d.ts +47 -0
  133. package/storage/factory.d.ts +6 -0
  134. package/storage/index.d.ts +3 -1
  135. package/storage/namespace.d.ts +2 -0
  136. package/storage/types.d.ts +46 -1
  137. package/storage/utils/compare-and-delete.d.ts +2 -0
@@ -0,0 +1,48 @@
1
+ // libs/utils/src/process/process-watch.ts
2
+ import { isMissingSync } from "../fs/fs.mjs";
3
+ import { isPidRunning } from "./process-tree.mjs";
4
+ var DEFAULT_INTERVAL_MS = 1e3;
5
+ function watchParent(options, deps) {
6
+ const d = { ppid: () => process.ppid, kill: (pid, signal) => process.kill(pid, signal), ...deps };
7
+ const parentPid = d.ppid();
8
+ const stdin = options.stdin;
9
+ let timer;
10
+ let closed = false;
11
+ const close = () => {
12
+ closed = true;
13
+ clearInterval(timer);
14
+ stdin?.removeListener("end", onStdinEnded);
15
+ stdin?.removeListener("close", onStdinEnded);
16
+ };
17
+ const report = (reason) => {
18
+ if (closed) return;
19
+ close();
20
+ options.onGone(reason);
21
+ };
22
+ function onStdinEnded() {
23
+ report("stdin-ended");
24
+ }
25
+ if (stdin?.readableEnded || stdin?.destroyed) queueMicrotask(onStdinEnded);
26
+ stdin?.once("end", onStdinEnded);
27
+ stdin?.once("close", onStdinEnded);
28
+ if (parentPid > 1) {
29
+ timer = setInterval(() => {
30
+ if (d.ppid() !== parentPid || !isPidRunning(parentPid, d)) report("parent-exited");
31
+ }, options.intervalMs ?? DEFAULT_INTERVAL_MS);
32
+ timer.unref();
33
+ }
34
+ return { close };
35
+ }
36
+ function watchPath(path, options) {
37
+ const timer = setInterval(() => {
38
+ if (!isMissingSync(path)) return;
39
+ clearInterval(timer);
40
+ options.onGone();
41
+ }, options.intervalMs ?? DEFAULT_INTERVAL_MS);
42
+ timer.unref();
43
+ return { close: () => clearInterval(timer) };
44
+ }
45
+ export {
46
+ watchParent,
47
+ watchPath
48
+ };
@@ -0,0 +1,6 @@
1
+ // libs/utils/src/redaction/index.ts
2
+ import { redactFields, redactJson } from "./redaction.mjs";
3
+ export {
4
+ redactFields,
5
+ redactJson
6
+ };
@@ -0,0 +1,74 @@
1
+ // libs/utils/src/redaction/redaction.ts
2
+ var REDACTED = "[REDACTED]";
3
+ function redactFields(obj, fields, maxDepth = 5) {
4
+ if (typeof fields !== "function" && fields.length === 0) return obj;
5
+ return redactRecord(obj, 0, { isSensitive: sensitiveKeyTest(fields), maxDepth, jsonText: false });
6
+ }
7
+ function redactJson(value, fields) {
8
+ return redactValue(value, 0, { isSensitive: sensitiveKeyTest(fields), maxDepth: Infinity, jsonText: true });
9
+ }
10
+ function sensitiveKeyTest(fields) {
11
+ if (typeof fields === "function") return fields;
12
+ const names = new Set(fields.map((field) => field.toLowerCase()));
13
+ return (key) => names.has(key.toLowerCase());
14
+ }
15
+ function redactValue(value, depth, options) {
16
+ if (typeof value === "string") return options.jsonText ? redactJsonText(value, depth, options) : value;
17
+ if (Array.isArray(value)) return value.map((item) => redactValue(item, depth, options));
18
+ if (isPlainObject(value)) return redactRecord(value, depth, options);
19
+ return value;
20
+ }
21
+ function redactRecord(obj, depth, options) {
22
+ if (depth >= options.maxDepth) return obj;
23
+ const result = {};
24
+ for (const [key, value] of Object.entries(obj)) {
25
+ result[key] = options.isSensitive(key) ? REDACTED : redactValue(value, depth + 1, options);
26
+ }
27
+ return result;
28
+ }
29
+ var AUTH_SCHEME_CREDENTIAL = /\b(Bearer|Basic)([ \t]+)(?=[\w.~+/-]*[\d.~+/_-])[\w.~+/-]{8,}=*/gi;
30
+ var JWT = /(?<![\w-])eyJ[\w-]+(?:\.[\w-]*){2,4}/g;
31
+ var URL_CREDENTIALS = /(?<![a-z\d+.-])([a-z][a-z\d+.-]*:\/\/)[^\s/?#@]+@/gi;
32
+ var VALUE_NAME = /(?:^|[?&#;,{("'\s])(["']?)([A-Za-z_][\w.-]*)\1[ \t]*[:=][ \t]*/g;
33
+ var NAMED_VALUE = /"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|[^\s"'&#;?,)}]+/y;
34
+ function redactNamedValues(text, isSensitive) {
35
+ let redacted = "";
36
+ let copiedUpTo = 0;
37
+ VALUE_NAME.lastIndex = 0;
38
+ for (let name = VALUE_NAME.exec(text); name; name = VALUE_NAME.exec(text)) {
39
+ if (!isSensitive(name[2])) continue;
40
+ NAMED_VALUE.lastIndex = VALUE_NAME.lastIndex;
41
+ const value = NAMED_VALUE.exec(text)?.[0];
42
+ if (value === void 0) continue;
43
+ const quote = value[0] === '"' || value[0] === "'" ? value[0] : "";
44
+ redacted += `${text.slice(copiedUpTo, VALUE_NAME.lastIndex)}${quote}${REDACTED}${quote}`;
45
+ copiedUpTo = VALUE_NAME.lastIndex + value.length;
46
+ VALUE_NAME.lastIndex = copiedUpTo;
47
+ }
48
+ return copiedUpTo === 0 ? text : redacted + text.slice(copiedUpTo);
49
+ }
50
+ function redactCredentialText(text, isSensitive) {
51
+ const withoutCredentials = text.replace(AUTH_SCHEME_CREDENTIAL, `$1$2${REDACTED}`).replace(JWT, REDACTED).replace(URL_CREDENTIALS, `$1${REDACTED}@`);
52
+ return redactNamedValues(withoutCredentials, isSensitive);
53
+ }
54
+ function redactJsonText(text, depth, options) {
55
+ const start = text.trimStart()[0];
56
+ if (start !== "{" && start !== "[") return redactCredentialText(text, options.isSensitive);
57
+ let parsed;
58
+ try {
59
+ parsed = JSON.parse(text);
60
+ } catch {
61
+ return redactCredentialText(text, options.isSensitive);
62
+ }
63
+ const redacted = JSON.stringify(redactValue(parsed, depth, options));
64
+ return redacted === JSON.stringify(parsed) ? text : redacted;
65
+ }
66
+ function isPlainObject(value) {
67
+ if (typeof value !== "object" || value === null) return false;
68
+ const proto = Object.getPrototypeOf(value);
69
+ return proto === Object.prototype || proto === null;
70
+ }
71
+ export {
72
+ redactFields,
73
+ redactJson
74
+ };
@@ -0,0 +1,3 @@
1
+ // libs/utils/src/regex/index.ts
2
+ export { DEFAULT_MAX_INPUT_LENGTH, REDOS_THRESHOLDS, analyzePattern, createSafeRegExp, isInputLengthSafe, isPatternSafe, safeExec, safeMatch, safeReplace, safeTest } from "./safe-regex.mjs";
3
+ export { collapseChar, collapseWhitespace, expandTemplate, extractBracedParams, hasTemplatePlaceholders, trimBoth, trimChars, trimLeading, trimTrailing } from "./patterns.mjs";
@@ -0,0 +1,167 @@
1
+ // libs/utils/src/regex/patterns.ts
2
+ import { DEFAULT_MAX_INPUT_LENGTH } from "./safe-regex.mjs";
3
+ function trimLeading(input, char) {
4
+ if (!input || char.length !== 1) {
5
+ return input ?? "";
6
+ }
7
+ let start = 0;
8
+ while (start < input.length && input[start] === char) {
9
+ start++;
10
+ }
11
+ return start === 0 ? input : input.slice(start);
12
+ }
13
+ function trimTrailing(input, char) {
14
+ if (!input || char.length !== 1) {
15
+ return input ?? "";
16
+ }
17
+ let end = input.length;
18
+ while (end > 0 && input[end - 1] === char) {
19
+ end--;
20
+ }
21
+ return end === input.length ? input : input.slice(0, end);
22
+ }
23
+ function trimBoth(input, char) {
24
+ return trimTrailing(trimLeading(input, char), char);
25
+ }
26
+ function trimChars(input, chars) {
27
+ if (!input || chars.size === 0) {
28
+ return input ?? "";
29
+ }
30
+ let start = 0;
31
+ while (start < input.length && chars.has(input[start])) {
32
+ start++;
33
+ }
34
+ let end = input.length;
35
+ while (end > start && chars.has(input[end - 1])) {
36
+ end--;
37
+ }
38
+ return input.slice(start, end);
39
+ }
40
+ function extractBracedParams(template, maxLength = DEFAULT_MAX_INPUT_LENGTH) {
41
+ if (!template || template.length > maxLength) {
42
+ return [];
43
+ }
44
+ const params = [];
45
+ let i = 0;
46
+ while (i < template.length) {
47
+ const openBrace = template.indexOf("{", i);
48
+ if (openBrace === -1) {
49
+ break;
50
+ }
51
+ const closeBrace = template.indexOf("}", openBrace + 1);
52
+ if (closeBrace === -1) {
53
+ break;
54
+ }
55
+ const nestedOpen = template.indexOf("{", openBrace + 1);
56
+ if (nestedOpen !== -1 && nestedOpen < closeBrace) {
57
+ i = nestedOpen + 1;
58
+ continue;
59
+ }
60
+ const paramName = template.slice(openBrace + 1, closeBrace).trim();
61
+ if (paramName && !paramName.includes("{") && !paramName.includes("}")) {
62
+ params.push(paramName);
63
+ }
64
+ i = closeBrace + 1;
65
+ }
66
+ return params;
67
+ }
68
+ function expandTemplate(template, values, maxLength = DEFAULT_MAX_INPUT_LENGTH) {
69
+ if (!template || template.length > maxLength) {
70
+ return template ?? "";
71
+ }
72
+ let result = "";
73
+ let i = 0;
74
+ while (i < template.length) {
75
+ const openBrace = template.indexOf("{", i);
76
+ if (openBrace === -1) {
77
+ result += template.slice(i);
78
+ break;
79
+ }
80
+ result += template.slice(i, openBrace);
81
+ const closeBrace = template.indexOf("}", openBrace + 1);
82
+ if (closeBrace === -1) {
83
+ result += template.slice(openBrace);
84
+ break;
85
+ }
86
+ const nestedOpen = template.indexOf("{", openBrace + 1);
87
+ if (nestedOpen !== -1 && nestedOpen < closeBrace) {
88
+ result += "{";
89
+ i = openBrace + 1;
90
+ continue;
91
+ }
92
+ const paramName = template.slice(openBrace + 1, closeBrace).trim();
93
+ if (paramName in values) {
94
+ result += values[paramName];
95
+ } else {
96
+ result += template.slice(openBrace, closeBrace + 1);
97
+ }
98
+ i = closeBrace + 1;
99
+ }
100
+ return result;
101
+ }
102
+ function hasTemplatePlaceholders(str, maxLength = DEFAULT_MAX_INPUT_LENGTH) {
103
+ if (!str || str.length > maxLength) {
104
+ return false;
105
+ }
106
+ const openBrace = str.indexOf("{");
107
+ if (openBrace === -1) {
108
+ return false;
109
+ }
110
+ const closeBrace = str.indexOf("}", openBrace + 1);
111
+ return closeBrace > openBrace + 1;
112
+ }
113
+ function collapseChar(input, char) {
114
+ if (!input || char.length !== 1) {
115
+ return input ?? "";
116
+ }
117
+ let result = "";
118
+ let lastWasChar = false;
119
+ for (let i = 0; i < input.length; i++) {
120
+ const c = input[i];
121
+ if (c === char) {
122
+ if (!lastWasChar) {
123
+ result += c;
124
+ lastWasChar = true;
125
+ }
126
+ } else {
127
+ result += c;
128
+ lastWasChar = false;
129
+ }
130
+ }
131
+ return result;
132
+ }
133
+ function collapseWhitespace(input, maxLength = DEFAULT_MAX_INPUT_LENGTH) {
134
+ if (!input) {
135
+ return "";
136
+ }
137
+ if (input.length > maxLength) {
138
+ return input;
139
+ }
140
+ let result = "";
141
+ let lastWasWhitespace = false;
142
+ for (let i = 0; i < input.length; i++) {
143
+ const c = input[i];
144
+ const isWhitespace = c === " " || c === " " || c === "\n" || c === "\r" || c === "\f" || c === "\v";
145
+ if (isWhitespace) {
146
+ if (!lastWasWhitespace) {
147
+ result += " ";
148
+ lastWasWhitespace = true;
149
+ }
150
+ } else {
151
+ result += c;
152
+ lastWasWhitespace = false;
153
+ }
154
+ }
155
+ return result;
156
+ }
157
+ export {
158
+ collapseChar,
159
+ collapseWhitespace,
160
+ expandTemplate,
161
+ extractBracedParams,
162
+ hasTemplatePlaceholders,
163
+ trimBoth,
164
+ trimChars,
165
+ trimLeading,
166
+ trimTrailing
167
+ };
@@ -0,0 +1,93 @@
1
+ // libs/utils/src/regex/safe-regex.ts
2
+ import { analyzeForReDoS, REDOS_THRESHOLDS } from "@enclave-vm/ast/redos";
3
+ var DEFAULT_MAX_INPUT_LENGTH = 5e4;
4
+ function analyzePattern(pattern, level = "polynomial") {
5
+ const patternStr = typeof pattern === "string" ? pattern : pattern.source;
6
+ try {
7
+ new RegExp(patternStr);
8
+ } catch {
9
+ return {
10
+ safe: false,
11
+ score: 100,
12
+ vulnerabilityType: "invalid_syntax",
13
+ explanation: "Pattern has invalid regex syntax"
14
+ };
15
+ }
16
+ try {
17
+ const result = analyzeForReDoS(patternStr, level);
18
+ return {
19
+ safe: !result.vulnerable,
20
+ score: result.score,
21
+ vulnerabilityType: result.vulnerabilityType,
22
+ explanation: result.explanation
23
+ };
24
+ } catch {
25
+ return {
26
+ safe: false,
27
+ score: 100,
28
+ vulnerabilityType: "analysis_failed",
29
+ explanation: "Pattern analysis failed - treating as potentially unsafe"
30
+ };
31
+ }
32
+ }
33
+ function isPatternSafe(pattern, level = "polynomial") {
34
+ return analyzePattern(pattern, level).safe;
35
+ }
36
+ function createSafeRegExp(pattern, flags, options = {}) {
37
+ const { level = "polynomial", throwOnVulnerable = false } = options;
38
+ const analysis = analyzePattern(pattern, level);
39
+ if (!analysis.safe) {
40
+ if (throwOnVulnerable) {
41
+ throw new Error(`Vulnerable regex pattern detected: ${analysis.explanation || analysis.vulnerabilityType}`);
42
+ }
43
+ return null;
44
+ }
45
+ try {
46
+ return new RegExp(pattern, flags);
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+ function safeTest(pattern, input, options = {}) {
52
+ const { maxInputLength = DEFAULT_MAX_INPUT_LENGTH } = options;
53
+ if (input.length > maxInputLength) {
54
+ return null;
55
+ }
56
+ return pattern.test(input);
57
+ }
58
+ function safeMatch(pattern, input, options = {}) {
59
+ const { maxInputLength = DEFAULT_MAX_INPUT_LENGTH } = options;
60
+ if (input.length > maxInputLength) {
61
+ return null;
62
+ }
63
+ return input.match(pattern);
64
+ }
65
+ function safeReplace(input, pattern, replacement, options = {}) {
66
+ const { maxInputLength = DEFAULT_MAX_INPUT_LENGTH } = options;
67
+ if (input.length > maxInputLength) {
68
+ return input;
69
+ }
70
+ return input.replace(pattern, replacement);
71
+ }
72
+ function safeExec(pattern, input, options = {}) {
73
+ const { maxInputLength = DEFAULT_MAX_INPUT_LENGTH } = options;
74
+ if (input.length > maxInputLength) {
75
+ return null;
76
+ }
77
+ return pattern.exec(input);
78
+ }
79
+ function isInputLengthSafe(input, maxLength = DEFAULT_MAX_INPUT_LENGTH) {
80
+ return input.length <= maxLength;
81
+ }
82
+ export {
83
+ DEFAULT_MAX_INPUT_LENGTH,
84
+ REDOS_THRESHOLDS,
85
+ analyzePattern,
86
+ createSafeRegExp,
87
+ isInputLengthSafe,
88
+ isPatternSafe,
89
+ safeExec,
90
+ safeMatch,
91
+ safeReplace,
92
+ safeTest
93
+ };
@@ -0,0 +1,5 @@
1
+ // libs/utils/src/serialization/index.ts
2
+ import { safeStringify } from "./serialization.mjs";
3
+ export {
4
+ safeStringify
5
+ };
@@ -0,0 +1,22 @@
1
+ // libs/utils/src/serialization/serialization.ts
2
+ function safeStringify(value, space) {
3
+ const seen = /* @__PURE__ */ new WeakSet();
4
+ try {
5
+ return JSON.stringify(
6
+ value,
7
+ (_key, val) => {
8
+ if (typeof val === "object" && val !== null) {
9
+ if (seen.has(val)) return "[Circular]";
10
+ seen.add(val);
11
+ }
12
+ return val;
13
+ },
14
+ space
15
+ );
16
+ } catch {
17
+ return JSON.stringify({ error: "Output could not be serialized" });
18
+ }
19
+ }
20
+ export {
21
+ safeStringify
22
+ };
@@ -0,0 +1,27 @@
1
+ // libs/utils/src/stdio-bridge/errors.ts
2
+ var DEV_SERVER_UNREACHABLE = -32099;
3
+ var DEV_BUFFER_FULL = -32098;
4
+ var DEV_RELOAD_DEADLINE = -32097;
5
+ var DEV_ERROR_MESSAGE = {
6
+ [DEV_SERVER_UNREACHABLE]: "dev_server_unreachable",
7
+ [DEV_BUFFER_FULL]: "dev_buffer_full",
8
+ [DEV_RELOAD_DEADLINE]: "dev_reload_deadline"
9
+ };
10
+ function makeDevError(id, code, data) {
11
+ return {
12
+ jsonrpc: "2.0",
13
+ id,
14
+ error: {
15
+ code,
16
+ message: DEV_ERROR_MESSAGE[code] ?? "dev_error",
17
+ ...data ? { data } : {}
18
+ }
19
+ };
20
+ }
21
+ export {
22
+ DEV_BUFFER_FULL,
23
+ DEV_ERROR_MESSAGE,
24
+ DEV_RELOAD_DEADLINE,
25
+ DEV_SERVER_UNREACHABLE,
26
+ makeDevError
27
+ };
@@ -0,0 +1,24 @@
1
+ // libs/utils/src/stdio-bridge/index.ts
2
+ import {
3
+ DEV_BUFFER_FULL,
4
+ DEV_ERROR_MESSAGE,
5
+ DEV_RELOAD_DEADLINE,
6
+ DEV_SERVER_UNREACHABLE,
7
+ makeDevError
8
+ } from "./errors.mjs";
9
+ import { listChangedNotifications } from "./list-changed.mjs";
10
+ import { createBridgeStateMachine } from "./state-machine.mjs";
11
+ import { createStdioFramer } from "./stdio-framer.mjs";
12
+ import { createHttpUpstream, createPipeUpstream } from "./upstream-client.mjs";
13
+ export {
14
+ DEV_BUFFER_FULL,
15
+ DEV_ERROR_MESSAGE,
16
+ DEV_RELOAD_DEADLINE,
17
+ DEV_SERVER_UNREACHABLE,
18
+ createBridgeStateMachine,
19
+ createHttpUpstream,
20
+ createPipeUpstream,
21
+ createStdioFramer,
22
+ listChangedNotifications,
23
+ makeDevError
24
+ };
@@ -0,0 +1,21 @@
1
+ // libs/utils/src/stdio-bridge/list-changed.ts
2
+ var LIST_CHANGED = {
3
+ tools: "notifications/tools/list_changed",
4
+ resources: "notifications/resources/list_changed",
5
+ prompts: "notifications/prompts/list_changed"
6
+ };
7
+ function listChangedNotifications(initializeResult) {
8
+ const capabilities = initializeResult?.["capabilities"];
9
+ if (typeof capabilities !== "object" || capabilities === null) return [];
10
+ const frames = [];
11
+ for (const [capability, method] of Object.entries(LIST_CHANGED)) {
12
+ const entry = capabilities[capability];
13
+ if (typeof entry === "object" && entry !== null && entry.listChanged === true) {
14
+ frames.push({ jsonrpc: "2.0", method });
15
+ }
16
+ }
17
+ return frames;
18
+ }
19
+ export {
20
+ listChangedNotifications
21
+ };