@posthog/mcp 0.14.1 → 0.16.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/LICENSE +64 -0
- package/README.md +64 -0
- package/dist/extensions/constants.d.ts +9 -0
- package/dist/extensions/constants.d.ts.map +1 -1
- package/dist/extensions/constants.js +9 -0
- package/dist/extensions/constants.mjs +9 -0
- package/dist/extensions/event-types.d.ts +1 -0
- package/dist/extensions/event-types.d.ts.map +1 -1
- package/dist/extensions/event-types.js +1 -0
- package/dist/extensions/event-types.mjs +1 -0
- package/dist/extensions/feedback.d.ts +41 -0
- package/dist/extensions/feedback.d.ts.map +1 -0
- package/dist/extensions/feedback.js +259 -0
- package/dist/extensions/feedback.mjs +200 -0
- package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-highlevel.js +23 -2
- package/dist/extensions/instrument-highlevel.mjs +25 -4
- package/dist/extensions/instrument-lowlevel.d.ts +4 -3
- package/dist/extensions/instrument-lowlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-lowlevel.js +23 -2
- package/dist/extensions/instrument-lowlevel.mjs +25 -4
- package/dist/extensions/instrumentation.d.ts +33 -13
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +103 -9
- package/dist/extensions/instrumentation.mjs +99 -8
- package/dist/extensions/internal.js +9 -2
- package/dist/extensions/internal.mjs +9 -2
- package/dist/extensions/mcp-payloads.d.ts +19 -0
- package/dist/extensions/mcp-payloads.d.ts.map +1 -1
- package/dist/extensions/mcp-payloads.js +217 -7
- package/dist/extensions/mcp-payloads.mjs +210 -6
- package/dist/extensions/posthog-events.d.ts.map +1 -1
- package/dist/extensions/posthog-events.js +1 -0
- package/dist/extensions/posthog-events.mjs +1 -0
- package/dist/extensions/posthog-mcp.d.ts +23 -3
- package/dist/extensions/posthog-mcp.d.ts.map +1 -1
- package/dist/extensions/posthog-mcp.js +27 -1
- package/dist/extensions/posthog-mcp.mjs +27 -1
- package/dist/extensions/sanitization.d.ts.map +1 -1
- package/dist/extensions/sanitization.js +2 -1
- package/dist/extensions/sanitization.mjs +3 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.mjs +5 -1
- package/dist/types.d.ts +114 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +4 -4
- package/src/extensions/constants.ts +9 -0
- package/src/extensions/event-types.ts +1 -0
- package/src/extensions/feedback.ts +349 -0
- package/src/extensions/instrument-highlevel.ts +45 -2
- package/src/extensions/instrument-lowlevel.ts +49 -5
- package/src/extensions/instrumentation.ts +170 -17
- package/src/extensions/internal.ts +13 -2
- package/src/extensions/mcp-payloads.ts +443 -7
- package/src/extensions/posthog-events.ts +1 -0
- package/src/extensions/posthog-mcp.ts +74 -3
- package/src/extensions/sanitization.ts +14 -6
- package/src/index.ts +24 -3
- package/src/types.ts +120 -0
- package/src/version.ts +1 -1
|
@@ -38,6 +38,18 @@ const BASE64_DATA_URL_PAYLOAD_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;
|
|
|
38
38
|
const SIZE_GATE = 10240;
|
|
39
39
|
const POSTHOG_TOKEN_PATTERN = /\bph[a-z]_[A-Za-z0-9_-]{20,}\b/g;
|
|
40
40
|
const SENSITIVE_KEY_PATTERN = /^(authorization|cookie|set-cookie|x-api-key|api[-_]?key|api[-_]?token|access[-_]?token|refresh[-_]?token|token|password|secret|client[-_]?secret|private[-_]?key)$/i;
|
|
41
|
+
const URL_PATTERN = /[a-z][a-z0-9+.-]{0,63}:[^\s<>"]+/gi;
|
|
42
|
+
const URL_PATTERN_ONCE = new RegExp(URL_PATTERN.source, 'i');
|
|
43
|
+
const URL_AUTHORITY_SEARCH = /[a-z][a-z0-9+.-]{0,63}:\/\//i;
|
|
44
|
+
const URL_AUTHORITY_PATTERN = new RegExp(`^${URL_AUTHORITY_SEARCH.source}`, 'i');
|
|
45
|
+
const URL_AUTHORITY_SEARCH_ALL = new RegExp(URL_AUTHORITY_SEARCH.source, 'gi');
|
|
46
|
+
const URL_FIELD_CHARACTERS = '=&';
|
|
47
|
+
const LEGACY_FIELD_SEPARATOR = ';';
|
|
48
|
+
const URL_TRAILING_PUNCTUATION = ".,;:!?)]}'";
|
|
49
|
+
const MAX_URL_LENGTH = 8192;
|
|
50
|
+
const MAX_URL_QUERY_FIELDS = 128;
|
|
51
|
+
const SENSITIVE_QUERY_KEY_SEGMENT_PATTERN = /(^|[-_./;])(auth|token|secret|password|passwd|pwd|credential|signature|sig|key|hmac|sas|bearer|jwt|session|sessionid)([-_./;]|$)/i;
|
|
52
|
+
const SENSITIVE_QUERY_KEY_EXACT_PATTERN = /^(code|AWSAccessKeyId|GoogleAccessId|Policy)$/i;
|
|
41
53
|
const UNICODE_SPACE_PATTERN = /[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
42
54
|
const EMAIL_PATTERN = /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,24}/g;
|
|
43
55
|
const IPV4_PATTERN = /\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/g;
|
|
@@ -53,6 +65,9 @@ function isRecord(value) {
|
|
|
53
65
|
function shouldRedactKey(key) {
|
|
54
66
|
return SENSITIVE_KEY_PATTERN.test(key);
|
|
55
67
|
}
|
|
68
|
+
function shouldRedactQueryKey(key) {
|
|
69
|
+
return shouldRedactKey(key) || SENSITIVE_QUERY_KEY_SEGMENT_PATTERN.test(key) || SENSITIVE_QUERY_KEY_EXACT_PATTERN.test(key);
|
|
70
|
+
}
|
|
56
71
|
function isBase64DataUrl(value) {
|
|
57
72
|
const prefix = BASE64_DATA_URL_PREFIX_PATTERN.exec(value);
|
|
58
73
|
if (!prefix) return false;
|
|
@@ -64,10 +79,193 @@ function isBase64DataUrl(value) {
|
|
|
64
79
|
}
|
|
65
80
|
return BASE64_DATA_URL_PAYLOAD_PATTERN.test(payload.replace(/[\r\n]/g, ''));
|
|
66
81
|
}
|
|
67
|
-
function
|
|
68
|
-
|
|
82
|
+
function exceedsUrlFieldLimit(fields) {
|
|
83
|
+
return fields.split('&', MAX_URL_QUERY_FIELDS + 1).length > MAX_URL_QUERY_FIELDS;
|
|
84
|
+
}
|
|
85
|
+
function hasLegacySensitiveField(value) {
|
|
86
|
+
return value.split(LEGACY_FIELD_SEPARATOR).some((piece)=>shouldRedactQueryKey(piece.split('=', 1)[0]));
|
|
87
|
+
}
|
|
88
|
+
function sanitizeUrlFieldValue(key, value, allowNestedUrls) {
|
|
89
|
+
if (shouldRedactQueryKey(key)) return REDACTED_VALUE;
|
|
90
|
+
if (value.includes(LEGACY_FIELD_SEPARATOR) && hasLegacySensitiveField(value)) return REDACTED_VALUE;
|
|
91
|
+
if (!URL_PATTERN_ONCE.test(value)) return value;
|
|
92
|
+
return allowNestedUrls ? sanitizeUrlsInString(value, {
|
|
93
|
+
allowNestedUrls: false,
|
|
94
|
+
stripPunctuation: true
|
|
95
|
+
}) : REDACTED_VALUE;
|
|
96
|
+
}
|
|
97
|
+
function sanitizeUrlFields(fields, allowNestedUrls) {
|
|
98
|
+
const sanitized = new URLSearchParams();
|
|
99
|
+
let changed = false;
|
|
100
|
+
let lastFieldSensitive = false;
|
|
101
|
+
for (const [key, value] of new URLSearchParams(fields)){
|
|
102
|
+
const sanitizedValue = sanitizeUrlFieldValue(key, value, allowNestedUrls);
|
|
103
|
+
changed ||= sanitizedValue !== value;
|
|
104
|
+
lastFieldSensitive = shouldRedactQueryKey(key) || sanitizedValue !== value;
|
|
105
|
+
sanitized.append(key, sanitizedValue);
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
changed,
|
|
109
|
+
lastFieldSensitive,
|
|
110
|
+
serialized: sanitized.toString()
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function splitTrailingPunctuation(value) {
|
|
114
|
+
let end = value.length;
|
|
115
|
+
while(end > 0 && URL_TRAILING_PUNCTUATION.includes(value[end - 1]))end--;
|
|
116
|
+
return {
|
|
117
|
+
address: value.slice(0, end),
|
|
118
|
+
suffix: value.slice(end)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function sanitizeFragmentTail(tail, headLastFieldSensitive, allowNestedUrls) {
|
|
122
|
+
if (!headLastFieldSensitive) return sanitizeFragmentPart(tail, allowNestedUrls);
|
|
123
|
+
return {
|
|
124
|
+
value: '' === tail ? '' : REDACTED_VALUE,
|
|
125
|
+
lastFieldSensitive: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function splitFragmentParts(hash) {
|
|
129
|
+
const fragment = hash.slice(1);
|
|
130
|
+
const separator = fragment.indexOf('?');
|
|
131
|
+
if (separator < 0) return {
|
|
132
|
+
head: fragment,
|
|
133
|
+
tail: null
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
head: fragment.slice(0, separator),
|
|
137
|
+
tail: fragment.slice(separator + 1)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function sanitizeFragmentPart(part, allowNestedUrls) {
|
|
141
|
+
if (!part.includes('=')) return {
|
|
142
|
+
value: sanitizeFragmentText(part, allowNestedUrls),
|
|
143
|
+
lastFieldSensitive: false
|
|
144
|
+
};
|
|
145
|
+
const fields = sanitizeUrlFields(part, allowNestedUrls);
|
|
146
|
+
return {
|
|
147
|
+
value: fields.changed ? fields.serialized : part,
|
|
148
|
+
lastFieldSensitive: fields.lastFieldSensitive
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function sanitizeFragmentText(text, allowNestedUrls) {
|
|
152
|
+
if (!allowNestedUrls) return URL_PATTERN_ONCE.test(text) ? REDACTED_VALUE : text;
|
|
153
|
+
return sanitizeUrlsInString(text, {
|
|
154
|
+
allowNestedUrls: false,
|
|
155
|
+
stripPunctuation: true
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function findEmbeddedAuthorityIndexes(value) {
|
|
159
|
+
const starts = [
|
|
160
|
+
...value.matchAll(URL_AUTHORITY_SEARCH_ALL)
|
|
161
|
+
].map((match)=>match.index);
|
|
162
|
+
const indexes = [];
|
|
163
|
+
const delimiters = {
|
|
164
|
+
query: false,
|
|
165
|
+
fragment: false,
|
|
166
|
+
fragmentQuery: false
|
|
167
|
+
};
|
|
168
|
+
let pending = 0;
|
|
169
|
+
let inFields = false;
|
|
170
|
+
let lastStructural = '';
|
|
171
|
+
for(let cursor = 0; cursor < value.length && pending < starts.length; cursor++){
|
|
172
|
+
if (starts[pending] === cursor) {
|
|
173
|
+
if (cursor > 0 && '=' !== lastStructural) indexes.push(cursor);
|
|
174
|
+
pending++;
|
|
175
|
+
}
|
|
176
|
+
const character = value[cursor];
|
|
177
|
+
if (isDelimiter(character, delimiters, lastStructural)) {
|
|
178
|
+
lastStructural = character;
|
|
179
|
+
inFields = true;
|
|
180
|
+
} else if (inFields && URL_FIELD_CHARACTERS.includes(character)) lastStructural = character;
|
|
181
|
+
}
|
|
182
|
+
return indexes;
|
|
183
|
+
}
|
|
184
|
+
function isDelimiter(character, seen, lastStructural) {
|
|
185
|
+
if ('#' === character) return seen.fragment ? false : seen.fragment = true;
|
|
186
|
+
if ('?' !== character) return false;
|
|
187
|
+
if (seen.fragment) {
|
|
188
|
+
if ('=' === lastStructural) return false;
|
|
189
|
+
return seen.fragmentQuery ? false : seen.fragmentQuery = true;
|
|
190
|
+
}
|
|
191
|
+
return seen.query ? false : seen.query = true;
|
|
192
|
+
}
|
|
193
|
+
function sanitizeUrl(value, mode) {
|
|
194
|
+
const embedded = findEmbeddedAuthorityIndexes(value);
|
|
195
|
+
if (0 === embedded.length) return sanitizeSingleUrl(value, mode);
|
|
196
|
+
let result = '';
|
|
197
|
+
let start = 0;
|
|
198
|
+
for (const index of embedded){
|
|
199
|
+
result += sanitizeSingleUrl(value.slice(start, index), {
|
|
200
|
+
...mode,
|
|
201
|
+
stripPunctuation: false
|
|
202
|
+
});
|
|
203
|
+
start = index;
|
|
204
|
+
}
|
|
205
|
+
return result + sanitizeSingleUrl(value.slice(start), mode);
|
|
206
|
+
}
|
|
207
|
+
function sanitizeSingleUrl(value, mode) {
|
|
208
|
+
if (value.length > MAX_URL_LENGTH && URL_AUTHORITY_PATTERN.test(value)) return REDACTED_VALUE;
|
|
209
|
+
const { address, suffix } = mode.stripPunctuation ? splitTrailingPunctuation(value) : {
|
|
210
|
+
address: value,
|
|
211
|
+
suffix: ''
|
|
212
|
+
};
|
|
213
|
+
let url;
|
|
214
|
+
try {
|
|
215
|
+
url = new URL(address);
|
|
216
|
+
} catch {
|
|
217
|
+
return REDACTED_VALUE + suffix;
|
|
218
|
+
}
|
|
219
|
+
const query = url.search.slice(1);
|
|
220
|
+
const hasFragment = '' !== url.hash;
|
|
221
|
+
const fragment = splitFragmentParts(url.hash);
|
|
222
|
+
if (exceedsUrlFieldLimit(query) || exceedsUrlFieldLimit(fragment.head) || exceedsUrlFieldLimit(fragment.tail ?? '')) return REDACTED_VALUE + suffix;
|
|
223
|
+
let changed = false;
|
|
224
|
+
if (url.username || url.password) {
|
|
225
|
+
url.username = REDACTED_VALUE;
|
|
226
|
+
url.password = '';
|
|
227
|
+
changed = true;
|
|
228
|
+
}
|
|
229
|
+
const sanitizedQuery = sanitizeUrlFields(query, mode.allowNestedUrls);
|
|
230
|
+
if (sanitizedQuery.changed) {
|
|
231
|
+
url.search = sanitizedQuery.serialized;
|
|
232
|
+
changed = true;
|
|
233
|
+
}
|
|
234
|
+
const sanitizedHead = sanitizeFragmentPart(fragment.head, mode.allowNestedUrls);
|
|
235
|
+
const sanitizedTail = null === fragment.tail ? null : sanitizeFragmentTail(fragment.tail, sanitizedHead.lastFieldSensitive, mode.allowNestedUrls);
|
|
236
|
+
const sanitizedHash = null === sanitizedTail ? sanitizedHead.value : `${sanitizedHead.value}?${sanitizedTail.value}`;
|
|
237
|
+
if (sanitizedHash !== url.hash.slice(1)) {
|
|
238
|
+
url.hash = sanitizedHash;
|
|
239
|
+
changed = true;
|
|
240
|
+
}
|
|
241
|
+
const trailingFields = hasFragment ? sanitizedTail ?? sanitizedHead : sanitizedQuery;
|
|
242
|
+
return (changed ? url.toString() : address) + (trailingFields.lastFieldSensitive ? '' : suffix);
|
|
243
|
+
}
|
|
244
|
+
function sanitizeUrlsInString(text, mode) {
|
|
245
|
+
return text.replace(URL_PATTERN, (match)=>sanitizeUrl(match, {
|
|
246
|
+
...mode,
|
|
247
|
+
stripPunctuation: mode.stripPunctuation && match.length !== text.length
|
|
248
|
+
}));
|
|
249
|
+
}
|
|
250
|
+
function isBinaryBlob(value) {
|
|
251
|
+
return value.length >= SIZE_GATE && (BASE64_PATTERN.test(value) || isBase64DataUrl(value) || BASE64URL_SPECIFIC_CHAR_PATTERN.test(value) && BASE64URL_PATTERN.test(value));
|
|
252
|
+
}
|
|
253
|
+
function redactCredentials(value) {
|
|
69
254
|
return value.replace(POSTHOG_TOKEN_PATTERN, REDACTED_VALUE);
|
|
70
255
|
}
|
|
256
|
+
function redactUrls(value) {
|
|
257
|
+
return sanitizeUrlsInString(value, {
|
|
258
|
+
allowNestedUrls: true,
|
|
259
|
+
stripPunctuation: true
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
function sanitizeString(value) {
|
|
263
|
+
return isBinaryBlob(value) ? BINARY_REDACTED_VALUE : redactUrls(redactCredentials(value));
|
|
264
|
+
}
|
|
265
|
+
function sanitizeFreeText(value) {
|
|
266
|
+
if (isBinaryBlob(value)) return BINARY_REDACTED_VALUE;
|
|
267
|
+
return redactUrls(redactPii(redactCredentials(value)));
|
|
268
|
+
}
|
|
71
269
|
function passesLuhn(digits) {
|
|
72
270
|
let sum = 0;
|
|
73
271
|
let double = false;
|
|
@@ -121,13 +319,19 @@ function redactPii(value) {
|
|
|
121
319
|
return result;
|
|
122
320
|
}
|
|
123
321
|
function sanitizeCapturedValue(value) {
|
|
322
|
+
return sanitizeValueWith(value, sanitizeString);
|
|
323
|
+
}
|
|
324
|
+
function sanitizeFreeTextValue(value) {
|
|
325
|
+
return sanitizeValueWith(value, sanitizeFreeText);
|
|
326
|
+
}
|
|
327
|
+
function sanitizeValueWith(value, sanitizeStringFn) {
|
|
124
328
|
if (null == value) return value;
|
|
125
|
-
if ('string' == typeof value) return
|
|
126
|
-
if (Array.isArray(value)) return value.map(
|
|
329
|
+
if ('string' == typeof value) return sanitizeStringFn(value);
|
|
330
|
+
if (Array.isArray(value)) return value.map((item)=>sanitizeValueWith(item, sanitizeStringFn));
|
|
127
331
|
if (value instanceof Date) return value;
|
|
128
332
|
if ('object' != typeof value) return value;
|
|
129
333
|
const result = {};
|
|
130
|
-
for (const [key, nestedValue] of Object.entries(value))result[key] = shouldRedactKey(key) ? REDACTED_VALUE :
|
|
334
|
+
for (const [key, nestedValue] of Object.entries(value))result[key] = shouldRedactKey(key) ? REDACTED_VALUE : sanitizeValueWith(nestedValue, sanitizeStringFn);
|
|
131
335
|
return result;
|
|
132
336
|
}
|
|
133
337
|
function buildCapturedMcpArguments(argumentsValue) {
|
|
@@ -160,15 +364,21 @@ function buildCapturedMcpParameters(request) {
|
|
|
160
364
|
__webpack_require__.d(__webpack_exports__, {
|
|
161
365
|
buildCapturedMcpParameters: ()=>buildCapturedMcpParameters,
|
|
162
366
|
redactPii: ()=>redactPii,
|
|
163
|
-
sanitizeCapturedValue: ()=>sanitizeCapturedValue
|
|
367
|
+
sanitizeCapturedValue: ()=>sanitizeCapturedValue,
|
|
368
|
+
sanitizeFreeText: ()=>sanitizeFreeText,
|
|
369
|
+
sanitizeFreeTextValue: ()=>sanitizeFreeTextValue
|
|
164
370
|
});
|
|
165
371
|
exports.buildCapturedMcpParameters = __webpack_exports__.buildCapturedMcpParameters;
|
|
166
372
|
exports.redactPii = __webpack_exports__.redactPii;
|
|
167
373
|
exports.sanitizeCapturedValue = __webpack_exports__.sanitizeCapturedValue;
|
|
374
|
+
exports.sanitizeFreeText = __webpack_exports__.sanitizeFreeText;
|
|
375
|
+
exports.sanitizeFreeTextValue = __webpack_exports__.sanitizeFreeTextValue;
|
|
168
376
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
169
377
|
"buildCapturedMcpParameters",
|
|
170
378
|
"redactPii",
|
|
171
|
-
"sanitizeCapturedValue"
|
|
379
|
+
"sanitizeCapturedValue",
|
|
380
|
+
"sanitizeFreeText",
|
|
381
|
+
"sanitizeFreeTextValue"
|
|
172
382
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
173
383
|
Object.defineProperty(exports, '__esModule', {
|
|
174
384
|
value: true
|
|
@@ -9,6 +9,18 @@ const BASE64_DATA_URL_PAYLOAD_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;
|
|
|
9
9
|
const SIZE_GATE = 10240;
|
|
10
10
|
const POSTHOG_TOKEN_PATTERN = /\bph[a-z]_[A-Za-z0-9_-]{20,}\b/g;
|
|
11
11
|
const SENSITIVE_KEY_PATTERN = /^(authorization|cookie|set-cookie|x-api-key|api[-_]?key|api[-_]?token|access[-_]?token|refresh[-_]?token|token|password|secret|client[-_]?secret|private[-_]?key)$/i;
|
|
12
|
+
const URL_PATTERN = /[a-z][a-z0-9+.-]{0,63}:[^\s<>"]+/gi;
|
|
13
|
+
const URL_PATTERN_ONCE = new RegExp(URL_PATTERN.source, 'i');
|
|
14
|
+
const URL_AUTHORITY_SEARCH = /[a-z][a-z0-9+.-]{0,63}:\/\//i;
|
|
15
|
+
const URL_AUTHORITY_PATTERN = new RegExp(`^${URL_AUTHORITY_SEARCH.source}`, 'i');
|
|
16
|
+
const URL_AUTHORITY_SEARCH_ALL = new RegExp(URL_AUTHORITY_SEARCH.source, 'gi');
|
|
17
|
+
const URL_FIELD_CHARACTERS = '=&';
|
|
18
|
+
const LEGACY_FIELD_SEPARATOR = ';';
|
|
19
|
+
const URL_TRAILING_PUNCTUATION = ".,;:!?)]}'";
|
|
20
|
+
const MAX_URL_LENGTH = 8192;
|
|
21
|
+
const MAX_URL_QUERY_FIELDS = 128;
|
|
22
|
+
const SENSITIVE_QUERY_KEY_SEGMENT_PATTERN = /(^|[-_./;])(auth|token|secret|password|passwd|pwd|credential|signature|sig|key|hmac|sas|bearer|jwt|session|sessionid)([-_./;]|$)/i;
|
|
23
|
+
const SENSITIVE_QUERY_KEY_EXACT_PATTERN = /^(code|AWSAccessKeyId|GoogleAccessId|Policy)$/i;
|
|
12
24
|
const UNICODE_SPACE_PATTERN = /[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
13
25
|
const EMAIL_PATTERN = /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,24}/g;
|
|
14
26
|
const IPV4_PATTERN = /\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/g;
|
|
@@ -24,6 +36,9 @@ function isRecord(value) {
|
|
|
24
36
|
function shouldRedactKey(key) {
|
|
25
37
|
return SENSITIVE_KEY_PATTERN.test(key);
|
|
26
38
|
}
|
|
39
|
+
function shouldRedactQueryKey(key) {
|
|
40
|
+
return shouldRedactKey(key) || SENSITIVE_QUERY_KEY_SEGMENT_PATTERN.test(key) || SENSITIVE_QUERY_KEY_EXACT_PATTERN.test(key);
|
|
41
|
+
}
|
|
27
42
|
function isBase64DataUrl(value) {
|
|
28
43
|
const prefix = BASE64_DATA_URL_PREFIX_PATTERN.exec(value);
|
|
29
44
|
if (!prefix) return false;
|
|
@@ -35,10 +50,193 @@ function isBase64DataUrl(value) {
|
|
|
35
50
|
}
|
|
36
51
|
return BASE64_DATA_URL_PAYLOAD_PATTERN.test(payload.replace(/[\r\n]/g, ''));
|
|
37
52
|
}
|
|
38
|
-
function
|
|
39
|
-
|
|
53
|
+
function exceedsUrlFieldLimit(fields) {
|
|
54
|
+
return fields.split('&', MAX_URL_QUERY_FIELDS + 1).length > MAX_URL_QUERY_FIELDS;
|
|
55
|
+
}
|
|
56
|
+
function hasLegacySensitiveField(value) {
|
|
57
|
+
return value.split(LEGACY_FIELD_SEPARATOR).some((piece)=>shouldRedactQueryKey(piece.split('=', 1)[0]));
|
|
58
|
+
}
|
|
59
|
+
function sanitizeUrlFieldValue(key, value, allowNestedUrls) {
|
|
60
|
+
if (shouldRedactQueryKey(key)) return REDACTED_VALUE;
|
|
61
|
+
if (value.includes(LEGACY_FIELD_SEPARATOR) && hasLegacySensitiveField(value)) return REDACTED_VALUE;
|
|
62
|
+
if (!URL_PATTERN_ONCE.test(value)) return value;
|
|
63
|
+
return allowNestedUrls ? sanitizeUrlsInString(value, {
|
|
64
|
+
allowNestedUrls: false,
|
|
65
|
+
stripPunctuation: true
|
|
66
|
+
}) : REDACTED_VALUE;
|
|
67
|
+
}
|
|
68
|
+
function sanitizeUrlFields(fields, allowNestedUrls) {
|
|
69
|
+
const sanitized = new URLSearchParams();
|
|
70
|
+
let changed = false;
|
|
71
|
+
let lastFieldSensitive = false;
|
|
72
|
+
for (const [key, value] of new URLSearchParams(fields)){
|
|
73
|
+
const sanitizedValue = sanitizeUrlFieldValue(key, value, allowNestedUrls);
|
|
74
|
+
changed ||= sanitizedValue !== value;
|
|
75
|
+
lastFieldSensitive = shouldRedactQueryKey(key) || sanitizedValue !== value;
|
|
76
|
+
sanitized.append(key, sanitizedValue);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
changed,
|
|
80
|
+
lastFieldSensitive,
|
|
81
|
+
serialized: sanitized.toString()
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function splitTrailingPunctuation(value) {
|
|
85
|
+
let end = value.length;
|
|
86
|
+
while(end > 0 && URL_TRAILING_PUNCTUATION.includes(value[end - 1]))end--;
|
|
87
|
+
return {
|
|
88
|
+
address: value.slice(0, end),
|
|
89
|
+
suffix: value.slice(end)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function sanitizeFragmentTail(tail, headLastFieldSensitive, allowNestedUrls) {
|
|
93
|
+
if (!headLastFieldSensitive) return sanitizeFragmentPart(tail, allowNestedUrls);
|
|
94
|
+
return {
|
|
95
|
+
value: '' === tail ? '' : REDACTED_VALUE,
|
|
96
|
+
lastFieldSensitive: true
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function splitFragmentParts(hash) {
|
|
100
|
+
const fragment = hash.slice(1);
|
|
101
|
+
const separator = fragment.indexOf('?');
|
|
102
|
+
if (separator < 0) return {
|
|
103
|
+
head: fragment,
|
|
104
|
+
tail: null
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
head: fragment.slice(0, separator),
|
|
108
|
+
tail: fragment.slice(separator + 1)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function sanitizeFragmentPart(part, allowNestedUrls) {
|
|
112
|
+
if (!part.includes('=')) return {
|
|
113
|
+
value: sanitizeFragmentText(part, allowNestedUrls),
|
|
114
|
+
lastFieldSensitive: false
|
|
115
|
+
};
|
|
116
|
+
const fields = sanitizeUrlFields(part, allowNestedUrls);
|
|
117
|
+
return {
|
|
118
|
+
value: fields.changed ? fields.serialized : part,
|
|
119
|
+
lastFieldSensitive: fields.lastFieldSensitive
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function sanitizeFragmentText(text, allowNestedUrls) {
|
|
123
|
+
if (!allowNestedUrls) return URL_PATTERN_ONCE.test(text) ? REDACTED_VALUE : text;
|
|
124
|
+
return sanitizeUrlsInString(text, {
|
|
125
|
+
allowNestedUrls: false,
|
|
126
|
+
stripPunctuation: true
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function findEmbeddedAuthorityIndexes(value) {
|
|
130
|
+
const starts = [
|
|
131
|
+
...value.matchAll(URL_AUTHORITY_SEARCH_ALL)
|
|
132
|
+
].map((match)=>match.index);
|
|
133
|
+
const indexes = [];
|
|
134
|
+
const delimiters = {
|
|
135
|
+
query: false,
|
|
136
|
+
fragment: false,
|
|
137
|
+
fragmentQuery: false
|
|
138
|
+
};
|
|
139
|
+
let pending = 0;
|
|
140
|
+
let inFields = false;
|
|
141
|
+
let lastStructural = '';
|
|
142
|
+
for(let cursor = 0; cursor < value.length && pending < starts.length; cursor++){
|
|
143
|
+
if (starts[pending] === cursor) {
|
|
144
|
+
if (cursor > 0 && '=' !== lastStructural) indexes.push(cursor);
|
|
145
|
+
pending++;
|
|
146
|
+
}
|
|
147
|
+
const character = value[cursor];
|
|
148
|
+
if (isDelimiter(character, delimiters, lastStructural)) {
|
|
149
|
+
lastStructural = character;
|
|
150
|
+
inFields = true;
|
|
151
|
+
} else if (inFields && URL_FIELD_CHARACTERS.includes(character)) lastStructural = character;
|
|
152
|
+
}
|
|
153
|
+
return indexes;
|
|
154
|
+
}
|
|
155
|
+
function isDelimiter(character, seen, lastStructural) {
|
|
156
|
+
if ('#' === character) return seen.fragment ? false : seen.fragment = true;
|
|
157
|
+
if ('?' !== character) return false;
|
|
158
|
+
if (seen.fragment) {
|
|
159
|
+
if ('=' === lastStructural) return false;
|
|
160
|
+
return seen.fragmentQuery ? false : seen.fragmentQuery = true;
|
|
161
|
+
}
|
|
162
|
+
return seen.query ? false : seen.query = true;
|
|
163
|
+
}
|
|
164
|
+
function sanitizeUrl(value, mode) {
|
|
165
|
+
const embedded = findEmbeddedAuthorityIndexes(value);
|
|
166
|
+
if (0 === embedded.length) return sanitizeSingleUrl(value, mode);
|
|
167
|
+
let result = '';
|
|
168
|
+
let start = 0;
|
|
169
|
+
for (const index of embedded){
|
|
170
|
+
result += sanitizeSingleUrl(value.slice(start, index), {
|
|
171
|
+
...mode,
|
|
172
|
+
stripPunctuation: false
|
|
173
|
+
});
|
|
174
|
+
start = index;
|
|
175
|
+
}
|
|
176
|
+
return result + sanitizeSingleUrl(value.slice(start), mode);
|
|
177
|
+
}
|
|
178
|
+
function sanitizeSingleUrl(value, mode) {
|
|
179
|
+
if (value.length > MAX_URL_LENGTH && URL_AUTHORITY_PATTERN.test(value)) return REDACTED_VALUE;
|
|
180
|
+
const { address, suffix } = mode.stripPunctuation ? splitTrailingPunctuation(value) : {
|
|
181
|
+
address: value,
|
|
182
|
+
suffix: ''
|
|
183
|
+
};
|
|
184
|
+
let url;
|
|
185
|
+
try {
|
|
186
|
+
url = new URL(address);
|
|
187
|
+
} catch {
|
|
188
|
+
return REDACTED_VALUE + suffix;
|
|
189
|
+
}
|
|
190
|
+
const query = url.search.slice(1);
|
|
191
|
+
const hasFragment = '' !== url.hash;
|
|
192
|
+
const fragment = splitFragmentParts(url.hash);
|
|
193
|
+
if (exceedsUrlFieldLimit(query) || exceedsUrlFieldLimit(fragment.head) || exceedsUrlFieldLimit(fragment.tail ?? '')) return REDACTED_VALUE + suffix;
|
|
194
|
+
let changed = false;
|
|
195
|
+
if (url.username || url.password) {
|
|
196
|
+
url.username = REDACTED_VALUE;
|
|
197
|
+
url.password = '';
|
|
198
|
+
changed = true;
|
|
199
|
+
}
|
|
200
|
+
const sanitizedQuery = sanitizeUrlFields(query, mode.allowNestedUrls);
|
|
201
|
+
if (sanitizedQuery.changed) {
|
|
202
|
+
url.search = sanitizedQuery.serialized;
|
|
203
|
+
changed = true;
|
|
204
|
+
}
|
|
205
|
+
const sanitizedHead = sanitizeFragmentPart(fragment.head, mode.allowNestedUrls);
|
|
206
|
+
const sanitizedTail = null === fragment.tail ? null : sanitizeFragmentTail(fragment.tail, sanitizedHead.lastFieldSensitive, mode.allowNestedUrls);
|
|
207
|
+
const sanitizedHash = null === sanitizedTail ? sanitizedHead.value : `${sanitizedHead.value}?${sanitizedTail.value}`;
|
|
208
|
+
if (sanitizedHash !== url.hash.slice(1)) {
|
|
209
|
+
url.hash = sanitizedHash;
|
|
210
|
+
changed = true;
|
|
211
|
+
}
|
|
212
|
+
const trailingFields = hasFragment ? sanitizedTail ?? sanitizedHead : sanitizedQuery;
|
|
213
|
+
return (changed ? url.toString() : address) + (trailingFields.lastFieldSensitive ? '' : suffix);
|
|
214
|
+
}
|
|
215
|
+
function sanitizeUrlsInString(text, mode) {
|
|
216
|
+
return text.replace(URL_PATTERN, (match)=>sanitizeUrl(match, {
|
|
217
|
+
...mode,
|
|
218
|
+
stripPunctuation: mode.stripPunctuation && match.length !== text.length
|
|
219
|
+
}));
|
|
220
|
+
}
|
|
221
|
+
function isBinaryBlob(value) {
|
|
222
|
+
return value.length >= SIZE_GATE && (BASE64_PATTERN.test(value) || isBase64DataUrl(value) || BASE64URL_SPECIFIC_CHAR_PATTERN.test(value) && BASE64URL_PATTERN.test(value));
|
|
223
|
+
}
|
|
224
|
+
function redactCredentials(value) {
|
|
40
225
|
return value.replace(POSTHOG_TOKEN_PATTERN, REDACTED_VALUE);
|
|
41
226
|
}
|
|
227
|
+
function redactUrls(value) {
|
|
228
|
+
return sanitizeUrlsInString(value, {
|
|
229
|
+
allowNestedUrls: true,
|
|
230
|
+
stripPunctuation: true
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
function sanitizeString(value) {
|
|
234
|
+
return isBinaryBlob(value) ? BINARY_REDACTED_VALUE : redactUrls(redactCredentials(value));
|
|
235
|
+
}
|
|
236
|
+
function sanitizeFreeText(value) {
|
|
237
|
+
if (isBinaryBlob(value)) return BINARY_REDACTED_VALUE;
|
|
238
|
+
return redactUrls(redactPii(redactCredentials(value)));
|
|
239
|
+
}
|
|
42
240
|
function passesLuhn(digits) {
|
|
43
241
|
let sum = 0;
|
|
44
242
|
let double = false;
|
|
@@ -92,13 +290,19 @@ function redactPii(value) {
|
|
|
92
290
|
return result;
|
|
93
291
|
}
|
|
94
292
|
function sanitizeCapturedValue(value) {
|
|
293
|
+
return sanitizeValueWith(value, sanitizeString);
|
|
294
|
+
}
|
|
295
|
+
function sanitizeFreeTextValue(value) {
|
|
296
|
+
return sanitizeValueWith(value, sanitizeFreeText);
|
|
297
|
+
}
|
|
298
|
+
function sanitizeValueWith(value, sanitizeStringFn) {
|
|
95
299
|
if (null == value) return value;
|
|
96
|
-
if ('string' == typeof value) return
|
|
97
|
-
if (Array.isArray(value)) return value.map(
|
|
300
|
+
if ('string' == typeof value) return sanitizeStringFn(value);
|
|
301
|
+
if (Array.isArray(value)) return value.map((item)=>sanitizeValueWith(item, sanitizeStringFn));
|
|
98
302
|
if (value instanceof Date) return value;
|
|
99
303
|
if ('object' != typeof value) return value;
|
|
100
304
|
const result = {};
|
|
101
|
-
for (const [key, nestedValue] of Object.entries(value))result[key] = shouldRedactKey(key) ? REDACTED_VALUE :
|
|
305
|
+
for (const [key, nestedValue] of Object.entries(value))result[key] = shouldRedactKey(key) ? REDACTED_VALUE : sanitizeValueWith(nestedValue, sanitizeStringFn);
|
|
102
306
|
return result;
|
|
103
307
|
}
|
|
104
308
|
function buildCapturedMcpArguments(argumentsValue) {
|
|
@@ -128,4 +332,4 @@ function buildCapturedMcpParameters(request) {
|
|
|
128
332
|
request: capturedRequest
|
|
129
333
|
};
|
|
130
334
|
}
|
|
131
|
-
export { buildCapturedMcpParameters, redactPii, sanitizeCapturedValue };
|
|
335
|
+
export { buildCapturedMcpParameters, redactPii, sanitizeCapturedValue, sanitizeFreeText, sanitizeFreeTextValue };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posthog-events.d.ts","sourceRoot":"","sources":["../../src/extensions/posthog-events.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"posthog-events.d.ts","sourceRoot":"","sources":["../../src/extensions/posthog-events.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AA0BrC,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,MAAM,WAAW,gCAAgC;IAC/C,2FAA2F;IAC3F,0BAA0B,CAAC,EAAE,OAAO,CAAA;CACrC;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE,gCAAqC,GAC7C,mBAAmB,EAAE,CAQvB"}
|
|
@@ -35,6 +35,7 @@ const external_event_types_js_namespaceObject = require("./event-types.js");
|
|
|
35
35
|
const BUILT_IN_EVENT_NAME_BY_TYPE = {
|
|
36
36
|
[external_event_types_js_namespaceObject.MCPAnalyticsEventType.custom]: external_constants_js_namespaceObject.PostHogMCPAnalyticsEvent.Custom,
|
|
37
37
|
[external_event_types_js_namespaceObject.MCPAnalyticsEventType.identify]: external_constants_js_namespaceObject.PostHogMCPAnalyticsEvent.Identify,
|
|
38
|
+
[external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpFeedback]: external_constants_js_namespaceObject.PostHogMCPAnalyticsEvent.Feedback,
|
|
38
39
|
[external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpMissingCapability]: external_constants_js_namespaceObject.PostHogMCPAnalyticsEvent.MissingCapability,
|
|
39
40
|
[external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpInitialize]: external_constants_js_namespaceObject.PostHogMCPAnalyticsEvent.Initialize,
|
|
40
41
|
[external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpPromptsGet]: external_constants_js_namespaceObject.PostHogMCPAnalyticsEvent.PromptGet,
|
|
@@ -3,6 +3,7 @@ import { MCPAnalyticsEventType } from "./event-types.mjs";
|
|
|
3
3
|
const BUILT_IN_EVENT_NAME_BY_TYPE = {
|
|
4
4
|
[MCPAnalyticsEventType.custom]: PostHogMCPAnalyticsEvent.Custom,
|
|
5
5
|
[MCPAnalyticsEventType.identify]: PostHogMCPAnalyticsEvent.Identify,
|
|
6
|
+
[MCPAnalyticsEventType.mcpFeedback]: PostHogMCPAnalyticsEvent.Feedback,
|
|
6
7
|
[MCPAnalyticsEventType.mcpMissingCapability]: PostHogMCPAnalyticsEvent.MissingCapability,
|
|
7
8
|
[MCPAnalyticsEventType.mcpInitialize]: PostHogMCPAnalyticsEvent.Initialize,
|
|
8
9
|
[MCPAnalyticsEventType.mcpPromptsGet]: PostHogMCPAnalyticsEvent.PromptGet,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PostHog, type PostHogOptions } from 'posthog-node';
|
|
2
|
-
import type { InitializeCaptureData, MCPAnalyticsOptions, MissingCapabilityCaptureData, PreparedToolCall, PrepareToolCallOptions, PrepareToolListOptions, ToolCallCaptureData, ToolsListCaptureData } from '../types';
|
|
2
|
+
import type { FeedbackCaptureData, CollectFeedbackConfig, InitializeCaptureData, MCPAnalyticsOptions, MissingCapabilityCaptureData, PreparedToolCall, PrepareToolCallOptions, PrepareToolListOptions, ToolCallCaptureData, ToolsListCaptureData } from '../types';
|
|
3
3
|
import { type ContextInjectableTool } from './context-parameters';
|
|
4
4
|
/**
|
|
5
5
|
* Options for {@link PostHogMCP}. A superset of `posthog-node`'s options, plus
|
|
@@ -13,6 +13,17 @@ export interface PostHogMCPOptions extends PostHogOptions {
|
|
|
13
13
|
* can't drift. Defaults to `get_more_tools`.
|
|
14
14
|
*/
|
|
15
15
|
missingCapabilityToolName?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Enable + configure the `send_feedback` virtual tool: injected by
|
|
18
|
+
* {@link PostHogMCP.prepareToolList} (when its `collectFeedback` toggle is on)
|
|
19
|
+
* and detected by {@link PostHogMCP.prepareToolCall}. Set once here so
|
|
20
|
+
* injection and detection can't drift — without this option, `prepareToolCall`
|
|
21
|
+
* never flags a call as feedback, so a real tool that uses the name is not
|
|
22
|
+
* shadowed. Pick a `toolName` no real tool uses. `onFeedback` is ignored on
|
|
23
|
+
* this path — the host dispatcher routes reports itself via
|
|
24
|
+
* {@link PreparedToolCall.feedbackReport}.
|
|
25
|
+
*/
|
|
26
|
+
collectFeedback?: CollectFeedbackConfig;
|
|
16
27
|
/**
|
|
17
28
|
* Capture the calling model from recognized client metadata, with an injected
|
|
18
29
|
* `llm_model` argument as fallback. Off by default.
|
|
@@ -73,8 +84,9 @@ export declare class PostHogMCP extends PostHog {
|
|
|
73
84
|
* Decorate your `tools/list` response with PostHog's analytics affordances:
|
|
74
85
|
* injects the `context` argument into every tool (so agents state their intent,
|
|
75
86
|
* captured as `$mcp_intent`), injects `llm_model` when the constructor's
|
|
76
|
-
* `captureModel` option is enabled,
|
|
77
|
-
* `reportMissing` is on
|
|
87
|
+
* `captureModel` option is enabled, appends `get_more_tools` when
|
|
88
|
+
* `reportMissing` is on, and appends `send_feedback` when `collectFeedback` is
|
|
89
|
+
* on. Returns a new array; your tools are untouched.
|
|
78
90
|
*
|
|
79
91
|
* The appended `get_more_tools` descriptor carries only the base MCP tool fields
|
|
80
92
|
* (name, description, input schema) — not any framework-specific fields your
|
|
@@ -128,5 +140,13 @@ export declare class PostHogMCP extends PostHog {
|
|
|
128
140
|
* to the agent with `getMoreToolsResult()`.
|
|
129
141
|
*/
|
|
130
142
|
captureMissingCapability(data: MissingCapabilityCaptureData): void;
|
|
143
|
+
/**
|
|
144
|
+
* Capture a `send_feedback` call as an agent-feedback report. Emits
|
|
145
|
+
* `$mcp_feedback` with the report's `$mcp_feedback_*` properties and its
|
|
146
|
+
* summary/details as `$mcp_intent`. Reply to the agent with
|
|
147
|
+
* `sendFeedbackResult()` (or a custom text) after routing the report to your
|
|
148
|
+
* own feedback backend.
|
|
149
|
+
*/
|
|
150
|
+
captureFeedback(data: FeedbackCaptureData): void;
|
|
131
151
|
}
|
|
132
152
|
//# sourceMappingURL=posthog-mcp.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posthog-mcp.d.ts","sourceRoot":"","sources":["../../src/extensions/posthog-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAE3D,OAAO,KAAK,EACV,qBAAqB,EAErB,mBAAmB,EAGnB,4BAA4B,EAC5B,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"posthog-mcp.d.ts","sourceRoot":"","sources":["../../src/extensions/posthog-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAE3D,OAAO,KAAK,EACV,mBAAmB,EAEnB,qBAAqB,EACrB,qBAAqB,EAErB,mBAAmB,EAGnB,4BAA4B,EAC5B,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,UAAU,CAAA;AAUjB,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAA;AAgB7B;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,cAAc;IACvD;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAA;IACvC;;;OAGG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC,cAAc,CAAC,CAAA;CACnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,UAAW,SAAQ,OAAO;;gBAazB,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;IAoB3D,8FAA8F;IAC9F,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI;IAkBhD,iEAAiE;IACjE,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI;IAUpD;;;;;OAKG;IACH,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI;IAclD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,eAAe,CAAC,KAAK,SAAS,qBAAqB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,GAAE,sBAA2B,GAAG,KAAK,EAAE;IAyCnH;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,eAAe,CACb,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,GAAE,sBAA2B,GACnC,gBAAgB;IA+BnB;;;;OAIG;IACH,wBAAwB,CAAC,IAAI,EAAE,4BAA4B,GAAG,IAAI;IASlE;;;;;;OAMG;IACH,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI;CAuBjD"}
|