claude-threads 1.39.3 → 1.39.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.39.4] - 2026-10-30
9
+
10
+ ### Security
11
+ - `proxy-addr` 2.0.7 → 2.0.8 (critical, IP spoofing), `@modelcontextprotocol/sdk` 1.30.1 → 1.32.2 (three high advisories), `body-parser` 2.3.0 → 2.4.0, `fast-uri` 4.2.1 → 4.2.3, `shell-quote` 1.10.0 → 1.12.0 and `hono` 4.13.9 → 4.13.13, all bundled into what users run (#650). Supersedes the separate Dependabot PRs, none of which could go green on its own.
12
+
13
+ ### Changed
14
+ - `@hono/node-server` 2.1.5, `express-rate-limit` 8.7.1, `@redactpii/node` 1.0.19, `react` 19.3.1, `zod` 4.6.7, plus dev tooling (`eslint`, `knip`, `prettier`, `typescript-eslint`, `@types/*`). `ink` stays on 6.x; the 8.0 major is left for a separate change.
15
+
8
16
  ## [1.39.3] - 2026-10-01
9
17
 
10
18
  ### Fixed
package/dist/index.js CHANGED
@@ -19189,7 +19189,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
19189
19189
  exports.useTransition = function() {
19190
19190
  return resolveDispatcher().useTransition();
19191
19191
  };
19192
- exports.version = "19.3.0";
19192
+ exports.version = "19.3.1";
19193
19193
  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
19194
19194
  })();
19195
19195
  });
@@ -57094,15 +57094,15 @@ class Redactor {
57094
57094
  name: "CREDIT_CARD"
57095
57095
  },
57096
57096
  EMAIL: {
57097
- pattern: /\b[a-z0-9][a-z0-9._-]*@[a-z0-9][\w.-]*\.[a-z]{2,}/gi,
57097
+ pattern: /(?<![\p{L}\p{N}._%+-]|[\p{L}\p{N}]')[\p{L}\p{N}][\p{L}\p{N}._%+'-]*@[\p{L}\p{N}][\p{L}\p{N}_.-]*\.\p{L}{2,}/giu,
57098
57098
  name: "EMAIL"
57099
57099
  },
57100
57100
  NAME: {
57101
- pattern: /(?:^|\.\s+)(?:dear|hi|hello|greetings|hey|hey there)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)+)/gi,
57101
+ pattern: /(?=[DdHhGg])(?<=(?:^|[.!?\n])\s*)(?:[Dd]ear|[Hh]i|[Hh]ello|[Gg]reetings|[Hh]ey(?:\s+[Tt]here)?)\s+\p{Lu}[\p{L}'’-]*\p{Ll}(?:[ \t]+\p{Lu}[\p{L}'’-]*\p{Ll})+/gu,
57102
57102
  name: "PERSON_NAME"
57103
57103
  },
57104
57104
  PHONE: {
57105
- pattern: /\b(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b/g,
57105
+ pattern: /(?<!\w)(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b/g,
57106
57106
  name: "PHONE_NUMBER"
57107
57107
  },
57108
57108
  SSN: {
@@ -57116,15 +57116,15 @@ class Redactor {
57116
57116
  name: "CREDIT_CARD"
57117
57117
  },
57118
57118
  EMAIL: {
57119
- pattern: /\b[a-z0-9][a-z0-9._-]*\s*(?:@|\[at\]|\(at\))\s*[a-z0-9][\w.-]*\s*(?:\.|\[dot\]|\(dot\))\s*[a-z]{2,}\b/gi,
57119
+ pattern: /(?<![\p{L}\p{N}._%+-]|[\p{L}\p{N}]')[\p{L}\p{N}][\p{L}\p{N}._%+'-]*\s*(?:@|\[at\]|\(at\))\s*[\p{L}\p{N}][\p{L}\p{N}_.-]*\s*(?:\.|\[dot\]|\(dot\))\s*\p{L}{2,}(?![\p{L}\p{N}_])/giu,
57120
57120
  name: "EMAIL"
57121
57121
  },
57122
57122
  NAME: {
57123
- pattern: /(?:^|\.\s+|,\s*)(?:dear|hi|hello|greetings|hey|hey there|mr|mrs|ms|dr|prof)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)/gi,
57123
+ pattern: /(?=[DdHhGgMmPp])(?<=(?:^|[.!?\n,])\s*)(?:[Dd]ear|[Hh]i|[Hh]ello|[Gg]reetings|[Hh]ey(?:\s+[Tt]here)?|[Mm][Rr][Ss]?\.?|[Mm][Ss]\.?|[Dd][Rr]\.?|[Pp]rof\.?)\s+\p{Lu}[\p{L}'’-]*\p{Ll}(?:[ \t]+\p{Lu}[\p{L}'’-]*\p{Ll})*/gu,
57124
57124
  name: "PERSON_NAME"
57125
57125
  },
57126
57126
  PHONE: {
57127
- pattern: /\b(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b|\b\d{3}[-.\s]\d{4}\b/g,
57127
+ pattern: /(?<!\w)(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b|\b\d{3}[-.\s]\d{4}\b/g,
57128
57128
  name: "PHONE_NUMBER"
57129
57129
  },
57130
57130
  SSN: {
@@ -57145,7 +57145,8 @@ class Redactor {
57145
57145
  return activeRules;
57146
57146
  }
57147
57147
  _clonePattern(pattern) {
57148
- return new RegExp(pattern.source, pattern.flags);
57148
+ const flags = pattern.flags.replace("y", "");
57149
+ return new RegExp(pattern.source, flags.includes("g") ? flags : `${flags}g`);
57149
57150
  }
57150
57151
  hasPII(text) {
57151
57152
  for (const { pattern } of this.activeRules) {
@@ -57185,48 +57186,42 @@ class Redactor {
57185
57186
  }
57186
57187
  _redactString(text, resetState) {
57187
57188
  const events = [];
57188
- let redactedText = text;
57189
57189
  if (resetState && this.anonymize) {
57190
57190
  this.anonymizationMap.clear();
57191
57191
  this.anonymizationCounters.clear();
57192
57192
  }
57193
+ const spans = [];
57193
57194
  for (const { pattern, name } of this.activeRules) {
57194
- const clonedPattern = this._clonePattern(pattern);
57195
- redactedText = redactedText.replace(clonedPattern, (match) => {
57196
- const piiType = name;
57197
- events.push({ pii_type: piiType, action: "REDACTED" });
57198
- if (this.anonymize) {
57199
- const normalizedMatch = match.toLowerCase();
57200
- const key = `${piiType}:${normalizedMatch}`;
57201
- if (this.anonymizationMap.has(key)) {
57202
- return this.anonymizationMap.get(key) ?? match;
57203
- }
57204
- const counter = (this.anonymizationCounters.get(piiType) ?? 0) + 1;
57205
- this.anonymizationCounters.set(piiType, counter);
57206
- const tokenPrefix = this._getTokenPrefix(piiType);
57207
- const token = `${tokenPrefix}_${counter}`;
57208
- this.anonymizationMap.set(key, token);
57209
- return token;
57210
- }
57211
- if (this.globalReplaceWith !== undefined) {
57212
- return this.globalReplaceWith;
57213
- }
57214
- switch (piiType) {
57215
- case "CREDIT_CARD":
57216
- return "CREDIT_CARD_NUMBER";
57217
- case "EMAIL":
57218
- return "EMAIL_ADDRESS";
57219
- case "PERSON_NAME":
57220
- return "PERSON_NAME";
57221
- case "PHONE_NUMBER":
57222
- return "PHONE_NUMBER";
57223
- case "US_SOCIAL_SECURITY_NUMBER":
57224
- return "US_SOCIAL_SECURITY_NUMBER";
57225
- default:
57226
- return "DIGITS";
57195
+ for (const match of text.matchAll(this._clonePattern(pattern))) {
57196
+ if (match[0] === "") {
57197
+ continue;
57227
57198
  }
57228
- });
57199
+ const start = match.index;
57200
+ spans.push({ start, end: start + match[0].length, name, length: match[0].length });
57201
+ }
57202
+ }
57203
+ spans.sort((a, b) => a.start === b.start ? b.end - a.end : a.start - b.start);
57204
+ const merged = [];
57205
+ for (const span of spans) {
57206
+ const last = merged[merged.length - 1];
57207
+ if (last !== undefined && span.start < last.end) {
57208
+ last.end = Math.max(last.end, span.end);
57209
+ if (span.length > last.length) {
57210
+ last.name = span.name;
57211
+ last.length = span.length;
57212
+ }
57213
+ } else {
57214
+ merged.push({ ...span });
57215
+ }
57229
57216
  }
57217
+ let redactedText = "";
57218
+ let cursor = 0;
57219
+ for (const { start, end, name } of merged) {
57220
+ events.push({ pii_type: name, action: "REDACTED" });
57221
+ redactedText += text.slice(cursor, start) + this._replacementFor(name, text.slice(start, end));
57222
+ cursor = end;
57223
+ }
57224
+ redactedText += text.slice(cursor);
57230
57225
  if (resetState) {
57231
57226
  const hasValidApiKey = this.apiKey !== null && this.apiKey !== "";
57232
57227
  if (hasValidApiKey && events.length > 0) {
@@ -57239,6 +57234,38 @@ class Redactor {
57239
57234
  }
57240
57235
  return redactedText;
57241
57236
  }
57237
+ _replacementFor(piiType, match) {
57238
+ if (this.anonymize) {
57239
+ const normalizedMatch = match.toLowerCase();
57240
+ const key = `${piiType}:${normalizedMatch}`;
57241
+ if (this.anonymizationMap.has(key)) {
57242
+ return this.anonymizationMap.get(key) ?? match;
57243
+ }
57244
+ const counter = (this.anonymizationCounters.get(piiType) ?? 0) + 1;
57245
+ this.anonymizationCounters.set(piiType, counter);
57246
+ const tokenPrefix = this._getTokenPrefix(piiType);
57247
+ const token = `${tokenPrefix}_${counter}`;
57248
+ this.anonymizationMap.set(key, token);
57249
+ return token;
57250
+ }
57251
+ if (this.globalReplaceWith !== undefined) {
57252
+ return this.globalReplaceWith;
57253
+ }
57254
+ switch (piiType) {
57255
+ case "CREDIT_CARD":
57256
+ return "CREDIT_CARD_NUMBER";
57257
+ case "EMAIL":
57258
+ return "EMAIL_ADDRESS";
57259
+ case "PERSON_NAME":
57260
+ return "PERSON_NAME";
57261
+ case "PHONE_NUMBER":
57262
+ return "PHONE_NUMBER";
57263
+ case "US_SOCIAL_SECURITY_NUMBER":
57264
+ return "US_SOCIAL_SECURITY_NUMBER";
57265
+ default:
57266
+ return "DIGITS";
57267
+ }
57268
+ }
57242
57269
  redact(text) {
57243
57270
  return this._redactString(text, true);
57244
57271
  }
@@ -3071,6 +3071,8 @@ var require_utils = __commonJS(function(exports, module) {
3071
3071
  var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
3072
3072
  var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
3073
3073
  var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
3074
+ var isRegNameCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=]$/u);
3075
+ var isLiteralRegName = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=]*$/u);
3074
3076
  function stringArrayToHexStripped(input) {
3075
3077
  let acc = "";
3076
3078
  let code = 0;
@@ -3300,13 +3302,47 @@ var require_utils = __commonJS(function(exports, module) {
3300
3302
  }
3301
3303
  return output.join("");
3302
3304
  }
3303
- var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
3304
- var HOST_DELIM_RE = /[@/?#:]/g;
3305
- var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
3306
- function reescapeHostDelimiters(host, isIP) {
3307
- const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
3308
- re.lastIndex = 0;
3309
- return host.replace(re, (ch) => HOST_DELIMS[ch]);
3305
+ function removeDotSegmentsRelative(path) {
3306
+ if (path === "" || path[0] === "/") {
3307
+ return removeDotSegments(path);
3308
+ }
3309
+ const segments = path.split("/");
3310
+ const last = segments.length - 1;
3311
+ const output = [];
3312
+ let trailingDirectory = false;
3313
+ for (let i = 0;i <= last; i++) {
3314
+ const segment = segments[i];
3315
+ if (segment === "." || segment === "..") {
3316
+ if (segment === "..") {
3317
+ if (output.length !== 0 && output[output.length - 1] !== "..") {
3318
+ output.pop();
3319
+ } else {
3320
+ output.push("..");
3321
+ }
3322
+ }
3323
+ trailingDirectory = i === last;
3324
+ } else {
3325
+ output.push(segment);
3326
+ }
3327
+ }
3328
+ if (trailingDirectory && output[output.length - 1] !== "..") {
3329
+ output.push("");
3330
+ }
3331
+ if (output.length === 0 || output[0] === "" || output[0].includes(":")) {
3332
+ output.unshift(".");
3333
+ }
3334
+ return output.join("/");
3335
+ }
3336
+ var IP_HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23" };
3337
+ var IP_HOST_DELIM_RE = /[@/?#]/g;
3338
+ function encodeHost(host, isIP, allowNonAscii = false) {
3339
+ if (!isIP) {
3340
+ if (isLiteralRegName(host))
3341
+ return host;
3342
+ return encodeComponent(host, isRegNameCharacter, allowNonAscii);
3343
+ }
3344
+ IP_HOST_DELIM_RE.lastIndex = 0;
3345
+ return host.replace(IP_HOST_DELIM_RE, (ch) => IP_HOST_DELIMS[ch]);
3310
3346
  }
3311
3347
  function normalizePercentEncoding(input, decodeUnreserved = false) {
3312
3348
  if (input.indexOf("%") === -1) {
@@ -3472,7 +3508,7 @@ var require_utils = __commonJS(function(exports, module) {
3472
3508
  }
3473
3509
  return output;
3474
3510
  }
3475
- function encodeComponent(input, isAllowed) {
3511
+ function encodeComponent(input, isAllowed, allowNonAscii = false) {
3476
3512
  let output = "";
3477
3513
  for (let i = 0;i < input.length; i++) {
3478
3514
  const ch = input[i];
@@ -3491,17 +3527,17 @@ var require_utils = __commonJS(function(exports, module) {
3491
3527
  if (code < 128) {
3492
3528
  output += BYTE_HEX[code];
3493
3529
  } else if (code < 55296 || code > 57343) {
3494
- output += percentEncodeNonAscii(code);
3530
+ output += allowNonAscii ? ch : percentEncodeNonAscii(code);
3495
3531
  } else if (code <= 56319 && i + 1 < input.length) {
3496
3532
  const low = input.charCodeAt(i + 1);
3497
3533
  if (low >= 56320 && low <= 57343) {
3498
- output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
3534
+ output += allowNonAscii ? ch + input[i + 1] : percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
3499
3535
  i++;
3500
3536
  } else {
3501
- output += percentEncodeNonAscii(65533);
3537
+ output += allowNonAscii ? "�" : percentEncodeNonAscii(65533);
3502
3538
  }
3503
3539
  } else {
3504
- output += percentEncodeNonAscii(65533);
3540
+ output += allowNonAscii ? "�" : percentEncodeNonAscii(65533);
3505
3541
  }
3506
3542
  }
3507
3543
  }
@@ -3563,7 +3599,7 @@ var require_utils = __commonJS(function(exports, module) {
3563
3599
  }
3564
3600
  return;
3565
3601
  }
3566
- function recomposeAuthority(component) {
3602
+ function recomposeAuthority(component, allowNonAscii = false) {
3567
3603
  const uriTokens = [];
3568
3604
  if (component.userinfo !== undefined) {
3569
3605
  uriTokens.push(encodeUserinfo(component.userinfo));
@@ -3584,7 +3620,7 @@ var require_utils = __commonJS(function(exports, module) {
3584
3620
  if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
3585
3621
  host = `[${ipV6res.escapedHost}]`;
3586
3622
  } else {
3587
- host = reescapeHostDelimiters(host, false);
3623
+ host = encodeHost(host, false, allowNonAscii);
3588
3624
  }
3589
3625
  }
3590
3626
  }
@@ -3606,7 +3642,7 @@ var require_utils = __commonJS(function(exports, module) {
3606
3642
  nonSimpleDomain,
3607
3643
  nonSimpleMailtoDomain,
3608
3644
  recomposeAuthority,
3609
- reescapeHostDelimiters,
3645
+ encodeHost,
3610
3646
  normalizePercentEncoding,
3611
3647
  normalizePathEncoding,
3612
3648
  serializePathEncoding,
@@ -3616,6 +3652,7 @@ var require_utils = __commonJS(function(exports, module) {
3616
3652
  encodeFragment,
3617
3653
  escapePreservingEscapes,
3618
3654
  removeDotSegments,
3655
+ removeDotSegmentsRelative,
3619
3656
  isIPv4,
3620
3657
  isUUID,
3621
3658
  normalizeIPv6,
@@ -3771,7 +3808,8 @@ var require_schemes = __commonJS(function(exports, module) {
3771
3808
  scheme: "urn",
3772
3809
  parse: urnParse,
3773
3810
  serialize: urnSerialize,
3774
- skipNormalize: true
3811
+ skipNormalize: true,
3812
+ absolutePath: true
3775
3813
  };
3776
3814
  var urnuuid = {
3777
3815
  scheme: "urn:uuid",
@@ -4050,16 +4088,18 @@ var require_schemes = __commonJS(function(exports, module) {
4050
4088
 
4051
4089
  // node_modules/fast-uri/index.js
4052
4090
  var require_fast_uri = __commonJS(function(exports, module) {
4053
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
4091
+ var { normalizeIPv6, removeDotSegments, removeDotSegmentsRelative, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, encodeHost, isIPv4, nonSimpleDomain } = require_utils();
4054
4092
  var { SCHEMES, getSchemeHandler } = require_schemes();
4055
4093
  var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
4056
4094
  var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
4057
- function decodeValidScheme(scheme) {
4058
- const decodedScheme = unescape(String(scheme));
4059
- if (!VALID_SCHEME.test(decodedScheme)) {
4095
+ var MALFORMED_HOST_ERROR = "URI host is malformed.";
4096
+ var FORBIDDEN_DOMAIN_HOST_CHARACTER = /[\0-\x20"#/:<>?@[\\\]^`{|}\x7F]/u;
4097
+ function validateScheme(scheme) {
4098
+ const stringScheme = String(scheme);
4099
+ if (!VALID_SCHEME.test(stringScheme)) {
4060
4100
  throw new TypeError(MALFORMED_SCHEME_ERROR);
4061
4101
  }
4062
- return decodedScheme;
4102
+ return stringScheme;
4063
4103
  }
4064
4104
  function normalize(uri, options) {
4065
4105
  if (typeof uri === "string") {
@@ -4074,6 +4114,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
4074
4114
  const {
4075
4115
  parsed: baseParsed,
4076
4116
  malformedAuthorityOrPort: baseMalformed,
4117
+ malformedReferenceEdge: baseMalformedReferenceEdge,
4077
4118
  malformedPercentEncoding: baseMalformedPercentEncoding,
4078
4119
  malformedSchemeSpecific: baseMalformedSchemeSpecific,
4079
4120
  malformedHost: baseMalformedHost,
@@ -4082,24 +4123,34 @@ var require_fast_uri = __commonJS(function(exports, module) {
4082
4123
  const {
4083
4124
  parsed: relativeParsed,
4084
4125
  malformedAuthorityOrPort: relativeMalformed,
4126
+ malformedReferenceEdge: relativeMalformedReferenceEdge,
4085
4127
  malformedPercentEncoding: relativeMalformedPercentEncoding,
4086
4128
  malformedSchemeSpecific: relativeMalformedSchemeSpecific,
4087
4129
  malformedHost: relativeMalformedHost,
4088
4130
  malformedScheme: relativeMalformedScheme
4089
4131
  } = parseWithStatus(relativeURI, schemelessOptions);
4090
- if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
4132
+ if (baseMalformed || relativeMalformed || baseMalformedReferenceEdge || relativeMalformedReferenceEdge || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
4091
4133
  throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
4092
4134
  }
4093
4135
  const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
4094
4136
  const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
4095
4137
  const resolvedHost = resolved.host;
4138
+ if ((resolved.scheme === "http" || resolved.scheme === "https") && !resolvedHost) {
4139
+ throw new Error("HTTP URIs must have a host.");
4140
+ }
4096
4141
  const resolvedHostIsIP = resolvedHost !== undefined && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
4142
+ if (hasForbiddenDomainHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP)) {
4143
+ throw new Error(MALFORMED_HOST_ERROR);
4144
+ }
4097
4145
  canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
4098
4146
  const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
4099
4147
  if (resolved.error && !encodedASCIIHost) {
4100
4148
  throw new Error(resolved.error);
4101
4149
  }
4102
4150
  schemelessOptions.skipEscape = true;
4151
+ if (resolvedSchemeHandler && resolvedSchemeHandler.absolutePath) {
4152
+ schemelessOptions.absolutePath = true;
4153
+ }
4103
4154
  return serialize(resolved, schemelessOptions);
4104
4155
  }
4105
4156
  function copyHost(target, source) {
@@ -4120,7 +4171,8 @@ var require_fast_uri = __commonJS(function(exports, module) {
4120
4171
  target.userinfo = relative.userinfo;
4121
4172
  copyHost(target, relative);
4122
4173
  target.port = relative.port;
4123
- target.path = removeDotSegments(relative.path || "");
4174
+ const relativeSchemeHandler = getSchemeHandler(relative.scheme);
4175
+ target.path = relativeSchemeHandler && relativeSchemeHandler.absolutePath ? relative.path || "" : removeDotSegments(relative.path || "");
4124
4176
  target.query = relative.query;
4125
4177
  } else {
4126
4178
  if (relative.userinfo !== undefined || relative.host !== undefined || relative.port !== undefined) {
@@ -4141,14 +4193,15 @@ var require_fast_uri = __commonJS(function(exports, module) {
4141
4193
  if (relative.path[0] === "/") {
4142
4194
  target.path = removeDotSegments(relative.path);
4143
4195
  } else {
4144
- if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
4196
+ const baseHasAuthority = base.userinfo !== undefined || base.host !== undefined || base.port !== undefined;
4197
+ if (baseHasAuthority && !base.path) {
4145
4198
  target.path = "/" + relative.path;
4146
4199
  } else if (!base.path) {
4147
4200
  target.path = relative.path;
4148
4201
  } else {
4149
4202
  target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
4150
4203
  }
4151
- target.path = removeDotSegments(target.path);
4204
+ target.path = base.scheme === undefined && !baseHasAuthority && target.path[0] !== "/" ? removeDotSegmentsRelative(target.path) : removeDotSegments(target.path);
4152
4205
  }
4153
4206
  target.query = relative.query;
4154
4207
  }
@@ -4191,13 +4244,14 @@ var require_fast_uri = __commonJS(function(exports, module) {
4191
4244
  const options = Object.assign({}, opts);
4192
4245
  const uriTokens = [];
4193
4246
  if (component.scheme) {
4194
- component.scheme = decodeValidScheme(component.scheme);
4247
+ component.scheme = validateScheme(component.scheme);
4195
4248
  }
4196
4249
  const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
4197
4250
  if (schemeHandler && schemeHandler.serialize)
4198
4251
  schemeHandler.serialize(component, options);
4199
4252
  const hasAuthority = component.userinfo !== undefined || component.host !== undefined || component.port !== undefined;
4200
- const pathNoScheme = !options.skipEscape && component.scheme === undefined && !hasAuthority;
4253
+ const schemelessReference = (component.scheme === undefined || options.reference === "suffix") && !hasAuthority;
4254
+ const pathNoScheme = !options.skipEscape && schemelessReference;
4201
4255
  if (component.path !== undefined) {
4202
4256
  if (!options.skipEscape) {
4203
4257
  component.path = serializePathEncoding(component.path, pathNoScheme);
@@ -4206,10 +4260,11 @@ var require_fast_uri = __commonJS(function(exports, module) {
4206
4260
  }
4207
4261
  }
4208
4262
  if (options.reference !== "suffix" && component.scheme) {
4209
- component.scheme = decodeValidScheme(component.scheme);
4263
+ component.scheme = validateScheme(component.scheme);
4210
4264
  uriTokens.push(component.scheme, ":");
4211
4265
  }
4212
- const authority = recomposeAuthority(component);
4266
+ const allowNonAsciiHost = options.unicodeSupport === true || Boolean(schemeHandler && schemeHandler.unicodeSupport);
4267
+ const authority = recomposeAuthority(component, allowNonAsciiHost);
4213
4268
  if (authority !== undefined) {
4214
4269
  if (options.reference !== "suffix") {
4215
4270
  uriTokens.push("//");
@@ -4222,9 +4277,9 @@ var require_fast_uri = __commonJS(function(exports, module) {
4222
4277
  if (component.path !== undefined) {
4223
4278
  let s = component.path;
4224
4279
  if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
4225
- s = removeDotSegments(s);
4280
+ s = schemelessReference && s[0] !== "/" ? removeDotSegmentsRelative(s) : removeDotSegments(s);
4226
4281
  }
4227
- if (pathNoScheme) {
4282
+ if (schemelessReference) {
4228
4283
  s = serializePathEncoding(s, true);
4229
4284
  }
4230
4285
  if (authority === undefined && s[0] === "/" && s[1] === "/") {
@@ -4273,16 +4328,32 @@ var require_fast_uri = __commonJS(function(exports, module) {
4273
4328
  }
4274
4329
  function canonicalizeHost(parsed, options, schemeHandler, isIP) {
4275
4330
  const bracketedIPLiteral = parsed.host && parsed.host[0] === "[" && parsed.host[parsed.host.length - 1] === "]";
4331
+ if (hasForbiddenDomainHost(parsed, options, schemeHandler, isIP)) {
4332
+ parsed.error = parsed.error || MALFORMED_HOST_ERROR;
4333
+ return true;
4334
+ }
4276
4335
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && !bracketedIPLiteral && nonSimpleDomain(parsed.host)) {
4336
+ let url;
4277
4337
  try {
4278
- parsed.host = new URL("http://" + parsed.host).hostname;
4338
+ url = new URL("http://" + parsed.host);
4279
4339
  } catch (e) {
4280
4340
  parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
4281
4341
  return true;
4282
4342
  }
4343
+ if (!isHostOnlyURL(url)) {
4344
+ parsed.error = parsed.error || MALFORMED_HOST_ERROR;
4345
+ return true;
4346
+ }
4347
+ parsed.host = url.hostname;
4283
4348
  }
4284
4349
  return false;
4285
4350
  }
4351
+ function hasForbiddenDomainHost(parsed, options, schemeHandler, isIP) {
4352
+ return Boolean(parsed.host && isIP === false && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && FORBIDDEN_DOMAIN_HOST_CHARACTER.test(parsed.host));
4353
+ }
4354
+ function isHostOnlyURL(url) {
4355
+ return url.username === "" && url.password === "" && url.port === "" && url.pathname === "/" && url.search === "" && url.hash === "" && url.hostname !== "";
4356
+ }
4286
4357
  function parseWithStatus(uri, opts) {
4287
4358
  const options = Object.assign({}, opts);
4288
4359
  const parsed = {
@@ -4295,6 +4366,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
4295
4366
  fragment: undefined
4296
4367
  };
4297
4368
  let malformedAuthorityOrPort = false;
4369
+ const malformedReferenceEdge = uri.length !== 0 && (uri.charCodeAt(0) <= 32 || uri.charCodeAt(uri.length - 1) <= 32);
4298
4370
  let malformedPercentEncoding = false;
4299
4371
  let malformedSchemeSpecific = false;
4300
4372
  let malformedHost = false;
@@ -4327,6 +4399,9 @@ var require_fast_uri = __commonJS(function(exports, module) {
4327
4399
  }
4328
4400
  }
4329
4401
  }
4402
+ if (malformedReferenceEdge) {
4403
+ parsed.error = parsed.error || "URI must not contain leading or trailing C0 controls or spaces.";
4404
+ }
4330
4405
  const matches = uri.match(URI_PARSE);
4331
4406
  if (matches) {
4332
4407
  parsed.scheme = matches[1];
@@ -4337,9 +4412,8 @@ var require_fast_uri = __commonJS(function(exports, module) {
4337
4412
  parsed.query = matches[7];
4338
4413
  parsed.fragment = matches[8];
4339
4414
  if (parsed.scheme !== undefined) {
4340
- const decodedScheme = unescape(parsed.scheme);
4341
- if (VALID_SCHEME.test(decodedScheme)) {
4342
- parsed.scheme = decodedScheme.toLowerCase();
4415
+ if (VALID_SCHEME.test(parsed.scheme)) {
4416
+ parsed.scheme = parsed.scheme.toLowerCase();
4343
4417
  } else {
4344
4418
  parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
4345
4419
  malformedScheme = true;
@@ -4370,7 +4444,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
4370
4444
  parsed.ipv6Zone = parsed.host.slice(parsed.host.indexOf("%") + 1);
4371
4445
  }
4372
4446
  if (malformedIPLiteral) {
4373
- parsed.error = parsed.error || "URI host is malformed.";
4447
+ parsed.error = parsed.error || MALFORMED_HOST_ERROR;
4374
4448
  malformedAuthorityOrPort = true;
4375
4449
  }
4376
4450
  } else {
@@ -4393,12 +4467,18 @@ var require_fast_uri = __commonJS(function(exports, module) {
4393
4467
  if (!malformedIPLiteral) {
4394
4468
  malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4395
4469
  }
4396
- if (uri.indexOf("%") !== -1 && parsed.host !== undefined && !malformedIPLiteral) {
4397
- let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4398
- if (!isIP) {
4470
+ if (parsed.host !== undefined && !malformedIPLiteral) {
4471
+ let host = parsed.host;
4472
+ if (uri.indexOf("%") !== -1 && !isIP) {
4473
+ host = normalizePercentEncoding(host, true);
4399
4474
  host = normalizePercentEncoding(host.toLowerCase());
4400
4475
  }
4401
- parsed.host = reescapeHostDelimiters(host, isIP);
4476
+ if (options.scheme !== "null") {
4477
+ const allowNonAsciiHost = options.unicodeSupport === true || Boolean(schemeHandler && schemeHandler.unicodeSupport);
4478
+ parsed.host = encodeHost(host, isIP, allowNonAsciiHost);
4479
+ } else {
4480
+ parsed.host = host;
4481
+ }
4402
4482
  }
4403
4483
  if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4404
4484
  if (parsed.path) {
@@ -4420,7 +4500,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
4420
4500
  } else {
4421
4501
  parsed.error = parsed.error || "URI can not be parsed.";
4422
4502
  }
4423
- return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
4503
+ return { parsed, malformedAuthorityOrPort, malformedReferenceEdge, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
4424
4504
  }
4425
4505
  function parse(uri, opts) {
4426
4506
  return parseWithStatus(uri, opts).parsed;
@@ -4429,10 +4509,11 @@ var require_fast_uri = __commonJS(function(exports, module) {
4429
4509
  return normalizeStringWithStatus(uri, opts).normalized;
4430
4510
  }
4431
4511
  function normalizeStringWithStatus(uri, opts) {
4432
- const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
4512
+ const { parsed, malformedAuthorityOrPort, malformedReferenceEdge, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
4433
4513
  return {
4434
- normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
4514
+ normalized: malformedAuthorityOrPort || malformedReferenceEdge || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
4435
4515
  malformedAuthorityOrPort,
4516
+ malformedReferenceEdge,
4436
4517
  malformedPercentEncoding,
4437
4518
  malformedSchemeSpecific,
4438
4519
  malformedHost,
@@ -4449,8 +4530,8 @@ var require_fast_uri = __commonJS(function(exports, module) {
4449
4530
  } catch {
4450
4531
  return;
4451
4532
  }
4452
- const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
4453
- return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? undefined : normalized;
4533
+ const { normalized, malformedAuthorityOrPort, malformedReferenceEdge, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
4534
+ return malformedAuthorityOrPort || malformedReferenceEdge || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? undefined : normalized;
4454
4535
  }
4455
4536
  var fastUri = {
4456
4537
  SCHEMES,
@@ -22680,6 +22761,18 @@ function prefixIssues(path, issues) {
22680
22761
  function unwrapMessage(message) {
22681
22762
  return typeof message === "string" ? message : message?.message;
22682
22763
  }
22764
+ function sizeCaps(defChecks) {
22765
+ const caps = [];
22766
+ for (const ch of defChecks ?? []) {
22767
+ const d = ch._zod.def;
22768
+ if (!/_(length|size)$|_equals$/.test(d.check))
22769
+ break;
22770
+ const max = d.maximum ?? d.length ?? d.size;
22771
+ if (max >= 0)
22772
+ caps.push([max, ch]);
22773
+ }
22774
+ return caps;
22775
+ }
22683
22776
  function attachSchema(issues, start, inst) {
22684
22777
  var _a;
22685
22778
  for (let i = start;i < issues.length; i++) {
@@ -23683,7 +23776,7 @@ ${content.join(`
23683
23776
  var version = {
23684
23777
  major: 4,
23685
23778
  minor: 6,
23686
- patch: 5
23779
+ patch: 7
23687
23780
  };
23688
23781
 
23689
23782
  // node_modules/zod/v4/core/schemas.js
@@ -24294,6 +24387,29 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
24294
24387
  return payload;
24295
24388
  };
24296
24389
  });
24390
+ function capSize(inst, size) {
24391
+ const caps = sizeCaps(inst._zod.def.checks);
24392
+ if (!caps.length)
24393
+ return;
24394
+ const cap = Math.min(...caps.map((c) => c[0]));
24395
+ const parse = inst._zod.parse;
24396
+ inst._zod.parse = (payload, ctx) => {
24397
+ const n = size(payload.value);
24398
+ if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
24399
+ for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
24400
+ if (n > max && ch._zod.def.when(payload)) {
24401
+ const start = payload.issues.length;
24402
+ ch._zod.check(payload);
24403
+ payload.issues[start].continue = false;
24404
+ attachSchema(payload.issues, start, inst);
24405
+ return payload;
24406
+ }
24407
+ }
24408
+ }
24409
+ return parse(payload, ctx);
24410
+ };
24411
+ }
24412
+ var arraySize = (input) => Array.isArray(input) ? input.length : -1;
24297
24413
  function handleArrayResult(result, final, index) {
24298
24414
  if (result.issues.length) {
24299
24415
  final.issues.push(...prefixIssues(index, result.issues));
@@ -24337,6 +24453,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
24337
24453
  }
24338
24454
  return payload;
24339
24455
  };
24456
+ capSize(inst, arraySize);
24340
24457
  });
24341
24458
  function handlePropertyResult(result, final, key, input, optin, optout) {
24342
24459
  const isPresent = key in input;
@@ -31021,6 +31138,9 @@ class Protocol {
31021
31138
  this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
31022
31139
  const handleTaskResult = async () => {
31023
31140
  const taskId = request.params.taskId;
31141
+ if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
31142
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
31143
+ }
31024
31144
  if (this._taskMessageQueue) {
31025
31145
  let queuedMessage;
31026
31146
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -31051,12 +31171,12 @@ class Protocol {
31051
31171
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
31052
31172
  }
31053
31173
  if (!isTerminal(task.status)) {
31054
- await this._waitForTaskUpdate(taskId, extra.signal);
31174
+ await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
31055
31175
  return await handleTaskResult();
31056
31176
  }
31057
31177
  if (isTerminal(task.status)) {
31058
31178
  const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
31059
- this._clearTaskQueue(taskId);
31179
+ this._clearTaskQueue(taskId, extra.sessionId);
31060
31180
  return {
31061
31181
  ...result,
31062
31182
  _meta: {
@@ -31093,7 +31213,7 @@ class Protocol {
31093
31213
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
31094
31214
  }
31095
31215
  await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
31096
- this._clearTaskQueue(request.params.taskId);
31216
+ this._clearTaskQueue(request.params.taskId, extra.sessionId);
31097
31217
  const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
31098
31218
  if (!cancelledTask) {
31099
31219
  throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
@@ -31216,6 +31336,19 @@ class Protocol {
31216
31336
  const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
31217
31337
  const capturedTransport = this._transport;
31218
31338
  const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
31339
+ const sessionId = capturedTransport?.sessionId;
31340
+ const store = this._taskStore;
31341
+ let relatedTaskFound = true;
31342
+ let relatedTaskLookup;
31343
+ if (relatedTaskId && store && this._taskMessageQueue && sessionId !== undefined) {
31344
+ relatedTaskFound = false;
31345
+ relatedTaskLookup = (async () => {
31346
+ if (!await store.getTask(relatedTaskId, sessionId)) {
31347
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
31348
+ }
31349
+ relatedTaskFound = true;
31350
+ })();
31351
+ }
31219
31352
  if (handler === undefined) {
31220
31353
  const errorResponse = {
31221
31354
  jsonrpc: "2.0",
@@ -31225,7 +31358,10 @@ class Protocol {
31225
31358
  message: "Method not found"
31226
31359
  }
31227
31360
  };
31228
- if (relatedTaskId && this._taskMessageQueue) {
31361
+ if (relatedTaskId && relatedTaskLookup) {
31362
+ const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
31363
+ relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error) => this._onerror(new Error(`Failed to send an error response: ${error}`)));
31364
+ } else if (relatedTaskId && this._taskMessageQueue) {
31229
31365
  this._enqueueTaskMessage(relatedTaskId, {
31230
31366
  type: "error",
31231
31367
  message: errorResponse,
@@ -31276,7 +31412,10 @@ class Protocol {
31276
31412
  closeSSEStream: extra?.closeSSEStream,
31277
31413
  closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
31278
31414
  };
31279
- Promise.resolve().then(() => {
31415
+ (relatedTaskLookup ?? Promise.resolve()).then(() => {
31416
+ if (relatedTaskLookup && abortController.signal.aborted) {
31417
+ throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
31418
+ }
31280
31419
  if (taskCreationParams) {
31281
31420
  this.assertTaskHandlerCapability(request.method);
31282
31421
  }
@@ -31311,7 +31450,7 @@ class Protocol {
31311
31450
  ...error["data"] !== undefined && { data: error["data"] }
31312
31451
  }
31313
31452
  };
31314
- if (relatedTaskId && this._taskMessageQueue) {
31453
+ if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
31315
31454
  await this._enqueueTaskMessage(relatedTaskId, {
31316
31455
  type: "error",
31317
31456
  message: errorResponse,
@@ -31699,7 +31838,7 @@ class Protocol {
31699
31838
  throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
31700
31839
  }
31701
31840
  const maxQueueSize = this._options?.maxTaskQueueSize;
31702
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
31841
+ await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
31703
31842
  }
31704
31843
  async _clearTaskQueue(taskId, sessionId) {
31705
31844
  if (this._taskMessageQueue) {
@@ -31718,10 +31857,10 @@ class Protocol {
31718
31857
  }
31719
31858
  }
31720
31859
  }
31721
- async _waitForTaskUpdate(taskId, signal) {
31860
+ async _waitForTaskUpdate(taskId, signal, sessionId) {
31722
31861
  let interval = this._options?.defaultTaskPollInterval ?? 1000;
31723
31862
  try {
31724
- const task = await this._taskStore?.getTask(taskId);
31863
+ const task = await this._taskStore?.getTask(taskId, sessionId);
31725
31864
  if (task?.pollInterval) {
31726
31865
  interval = task.pollInterval;
31727
31866
  }
@@ -32388,6 +32527,43 @@ class ExperimentalMcpServerTasks {
32388
32527
  }
32389
32528
  }
32390
32529
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
32530
+ function toolInputElementCount(value, max) {
32531
+ let count = 0;
32532
+ const stack = [value];
32533
+ while (stack.length > 0) {
32534
+ const node = stack.pop();
32535
+ if (node === null || typeof node !== "object")
32536
+ continue;
32537
+ if (Array.isArray(node)) {
32538
+ for (const child of node) {
32539
+ if (++count > max)
32540
+ return count;
32541
+ if (child !== null && typeof child === "object")
32542
+ stack.push(child);
32543
+ }
32544
+ } else {
32545
+ for (const key in node) {
32546
+ if (!Object.prototype.hasOwnProperty.call(node, key))
32547
+ continue;
32548
+ if (++count > max)
32549
+ return count;
32550
+ const child = node[key];
32551
+ if (child !== null && typeof child === "object")
32552
+ stack.push(child);
32553
+ }
32554
+ }
32555
+ }
32556
+ return count;
32557
+ }
32558
+ function resolveMaxToolInputElements(value) {
32559
+ if (value === undefined || value === Infinity)
32560
+ return;
32561
+ if (typeof value !== "number" || Number.isNaN(value) || value < 1) {
32562
+ throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
32563
+ }
32564
+ return value;
32565
+ }
32566
+
32391
32567
  class McpServer {
32392
32568
  constructor(serverInfo, options) {
32393
32569
  this._registeredResources = {};
@@ -32399,6 +32575,16 @@ class McpServer {
32399
32575
  this._resourceHandlersInitialized = false;
32400
32576
  this._promptHandlersInitialized = false;
32401
32577
  this.server = new Server(serverInfo, options);
32578
+ this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
32579
+ if (options?.capabilities?.tools) {
32580
+ this.setToolRequestHandlers();
32581
+ }
32582
+ if (options?.capabilities?.resources) {
32583
+ this.setResourceRequestHandlers();
32584
+ }
32585
+ if (options?.capabilities?.prompts) {
32586
+ this.setPromptRequestHandlers();
32587
+ }
32402
32588
  }
32403
32589
  get experimental() {
32404
32590
  if (!this._experimental) {
@@ -32505,12 +32691,15 @@ class McpServer {
32505
32691
  };
32506
32692
  }
32507
32693
  async validateToolInput(tool, args, toolName) {
32694
+ if (this._maxToolInputElements !== undefined && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) {
32695
+ throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
32696
+ }
32508
32697
  if (!tool.inputSchema) {
32509
32698
  return;
32510
32699
  }
32511
32700
  const inputObj = normalizeObjectSchema(tool.inputSchema);
32512
32701
  const schemaToParse = inputObj ?? tool.inputSchema;
32513
- const parseResult = await safeParseAsync2(schemaToParse, args);
32702
+ const parseResult = await safeParseAsync2(schemaToParse, args ?? {});
32514
32703
  if (!parseResult.success) {
32515
32704
  const error = "error" in parseResult ? parseResult.error : "Unknown error";
32516
32705
  const errorMessage = getParseErrorMessage(error);
@@ -32735,7 +32924,7 @@ class McpServer {
32735
32924
  }
32736
32925
  if (prompt.argsSchema) {
32737
32926
  const argsObj = normalizeObjectSchema(prompt.argsSchema);
32738
- const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
32927
+ const parseResult = await safeParseAsync2(argsObj, request.params.arguments ?? {});
32739
32928
  if (!parseResult.success) {
32740
32929
  const error = "error" in parseResult ? parseResult.error : "Unknown error";
32741
32930
  const errorMessage = getParseErrorMessage(error);
@@ -38422,15 +38611,15 @@ class Redactor {
38422
38611
  name: "CREDIT_CARD"
38423
38612
  },
38424
38613
  EMAIL: {
38425
- pattern: /\b[a-z0-9][a-z0-9._-]*@[a-z0-9][\w.-]*\.[a-z]{2,}/gi,
38614
+ pattern: /(?<![\p{L}\p{N}._%+-]|[\p{L}\p{N}]')[\p{L}\p{N}][\p{L}\p{N}._%+'-]*@[\p{L}\p{N}][\p{L}\p{N}_.-]*\.\p{L}{2,}/giu,
38426
38615
  name: "EMAIL"
38427
38616
  },
38428
38617
  NAME: {
38429
- pattern: /(?:^|\.\s+)(?:dear|hi|hello|greetings|hey|hey there)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)+)/gi,
38618
+ pattern: /(?=[DdHhGg])(?<=(?:^|[.!?\n])\s*)(?:[Dd]ear|[Hh]i|[Hh]ello|[Gg]reetings|[Hh]ey(?:\s+[Tt]here)?)\s+\p{Lu}[\p{L}'’-]*\p{Ll}(?:[ \t]+\p{Lu}[\p{L}'’-]*\p{Ll})+/gu,
38430
38619
  name: "PERSON_NAME"
38431
38620
  },
38432
38621
  PHONE: {
38433
- pattern: /\b(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b/g,
38622
+ pattern: /(?<!\w)(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b/g,
38434
38623
  name: "PHONE_NUMBER"
38435
38624
  },
38436
38625
  SSN: {
@@ -38444,15 +38633,15 @@ class Redactor {
38444
38633
  name: "CREDIT_CARD"
38445
38634
  },
38446
38635
  EMAIL: {
38447
- pattern: /\b[a-z0-9][a-z0-9._-]*\s*(?:@|\[at\]|\(at\))\s*[a-z0-9][\w.-]*\s*(?:\.|\[dot\]|\(dot\))\s*[a-z]{2,}\b/gi,
38636
+ pattern: /(?<![\p{L}\p{N}._%+-]|[\p{L}\p{N}]')[\p{L}\p{N}][\p{L}\p{N}._%+'-]*\s*(?:@|\[at\]|\(at\))\s*[\p{L}\p{N}][\p{L}\p{N}_.-]*\s*(?:\.|\[dot\]|\(dot\))\s*\p{L}{2,}(?![\p{L}\p{N}_])/giu,
38448
38637
  name: "EMAIL"
38449
38638
  },
38450
38639
  NAME: {
38451
- pattern: /(?:^|\.\s+|,\s*)(?:dear|hi|hello|greetings|hey|hey there|mr|mrs|ms|dr|prof)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)/gi,
38640
+ pattern: /(?=[DdHhGgMmPp])(?<=(?:^|[.!?\n,])\s*)(?:[Dd]ear|[Hh]i|[Hh]ello|[Gg]reetings|[Hh]ey(?:\s+[Tt]here)?|[Mm][Rr][Ss]?\.?|[Mm][Ss]\.?|[Dd][Rr]\.?|[Pp]rof\.?)\s+\p{Lu}[\p{L}'’-]*\p{Ll}(?:[ \t]+\p{Lu}[\p{L}'’-]*\p{Ll})*/gu,
38452
38641
  name: "PERSON_NAME"
38453
38642
  },
38454
38643
  PHONE: {
38455
- pattern: /\b(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b|\b\d{3}[-.\s]\d{4}\b/g,
38644
+ pattern: /(?<!\w)(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b|\b\d{3}[-.\s]\d{4}\b/g,
38456
38645
  name: "PHONE_NUMBER"
38457
38646
  },
38458
38647
  SSN: {
@@ -38473,7 +38662,8 @@ class Redactor {
38473
38662
  return activeRules;
38474
38663
  }
38475
38664
  _clonePattern(pattern) {
38476
- return new RegExp(pattern.source, pattern.flags);
38665
+ const flags = pattern.flags.replace("y", "");
38666
+ return new RegExp(pattern.source, flags.includes("g") ? flags : `${flags}g`);
38477
38667
  }
38478
38668
  hasPII(text) {
38479
38669
  for (const { pattern } of this.activeRules) {
@@ -38513,48 +38703,42 @@ class Redactor {
38513
38703
  }
38514
38704
  _redactString(text, resetState) {
38515
38705
  const events = [];
38516
- let redactedText = text;
38517
38706
  if (resetState && this.anonymize) {
38518
38707
  this.anonymizationMap.clear();
38519
38708
  this.anonymizationCounters.clear();
38520
38709
  }
38710
+ const spans = [];
38521
38711
  for (const { pattern, name } of this.activeRules) {
38522
- const clonedPattern = this._clonePattern(pattern);
38523
- redactedText = redactedText.replace(clonedPattern, (match) => {
38524
- const piiType = name;
38525
- events.push({ pii_type: piiType, action: "REDACTED" });
38526
- if (this.anonymize) {
38527
- const normalizedMatch = match.toLowerCase();
38528
- const key = `${piiType}:${normalizedMatch}`;
38529
- if (this.anonymizationMap.has(key)) {
38530
- return this.anonymizationMap.get(key) ?? match;
38531
- }
38532
- const counter = (this.anonymizationCounters.get(piiType) ?? 0) + 1;
38533
- this.anonymizationCounters.set(piiType, counter);
38534
- const tokenPrefix = this._getTokenPrefix(piiType);
38535
- const token = `${tokenPrefix}_${counter}`;
38536
- this.anonymizationMap.set(key, token);
38537
- return token;
38538
- }
38539
- if (this.globalReplaceWith !== undefined) {
38540
- return this.globalReplaceWith;
38541
- }
38542
- switch (piiType) {
38543
- case "CREDIT_CARD":
38544
- return "CREDIT_CARD_NUMBER";
38545
- case "EMAIL":
38546
- return "EMAIL_ADDRESS";
38547
- case "PERSON_NAME":
38548
- return "PERSON_NAME";
38549
- case "PHONE_NUMBER":
38550
- return "PHONE_NUMBER";
38551
- case "US_SOCIAL_SECURITY_NUMBER":
38552
- return "US_SOCIAL_SECURITY_NUMBER";
38553
- default:
38554
- return "DIGITS";
38712
+ for (const match of text.matchAll(this._clonePattern(pattern))) {
38713
+ if (match[0] === "") {
38714
+ continue;
38555
38715
  }
38556
- });
38716
+ const start = match.index;
38717
+ spans.push({ start, end: start + match[0].length, name, length: match[0].length });
38718
+ }
38719
+ }
38720
+ spans.sort((a, b) => a.start === b.start ? b.end - a.end : a.start - b.start);
38721
+ const merged = [];
38722
+ for (const span of spans) {
38723
+ const last = merged[merged.length - 1];
38724
+ if (last !== undefined && span.start < last.end) {
38725
+ last.end = Math.max(last.end, span.end);
38726
+ if (span.length > last.length) {
38727
+ last.name = span.name;
38728
+ last.length = span.length;
38729
+ }
38730
+ } else {
38731
+ merged.push({ ...span });
38732
+ }
38557
38733
  }
38734
+ let redactedText = "";
38735
+ let cursor = 0;
38736
+ for (const { start, end, name } of merged) {
38737
+ events.push({ pii_type: name, action: "REDACTED" });
38738
+ redactedText += text.slice(cursor, start) + this._replacementFor(name, text.slice(start, end));
38739
+ cursor = end;
38740
+ }
38741
+ redactedText += text.slice(cursor);
38558
38742
  if (resetState) {
38559
38743
  const hasValidApiKey = this.apiKey !== null && this.apiKey !== "";
38560
38744
  if (hasValidApiKey && events.length > 0) {
@@ -38567,6 +38751,38 @@ class Redactor {
38567
38751
  }
38568
38752
  return redactedText;
38569
38753
  }
38754
+ _replacementFor(piiType, match) {
38755
+ if (this.anonymize) {
38756
+ const normalizedMatch = match.toLowerCase();
38757
+ const key = `${piiType}:${normalizedMatch}`;
38758
+ if (this.anonymizationMap.has(key)) {
38759
+ return this.anonymizationMap.get(key) ?? match;
38760
+ }
38761
+ const counter = (this.anonymizationCounters.get(piiType) ?? 0) + 1;
38762
+ this.anonymizationCounters.set(piiType, counter);
38763
+ const tokenPrefix = this._getTokenPrefix(piiType);
38764
+ const token = `${tokenPrefix}_${counter}`;
38765
+ this.anonymizationMap.set(key, token);
38766
+ return token;
38767
+ }
38768
+ if (this.globalReplaceWith !== undefined) {
38769
+ return this.globalReplaceWith;
38770
+ }
38771
+ switch (piiType) {
38772
+ case "CREDIT_CARD":
38773
+ return "CREDIT_CARD_NUMBER";
38774
+ case "EMAIL":
38775
+ return "EMAIL_ADDRESS";
38776
+ case "PERSON_NAME":
38777
+ return "PERSON_NAME";
38778
+ case "PHONE_NUMBER":
38779
+ return "PHONE_NUMBER";
38780
+ case "US_SOCIAL_SECURITY_NUMBER":
38781
+ return "US_SOCIAL_SECURITY_NUMBER";
38782
+ default:
38783
+ return "DIGITS";
38784
+ }
38785
+ }
38570
38786
  redact(text) {
38571
38787
  return this._redactString(text, true);
38572
38788
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.39.3",
3
+ "version": "1.39.4",
4
4
  "description": "Run Claude Code from Slack or Mattermost. Sessions stream live into threads where your whole team can watch and steer.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -69,45 +69,45 @@
69
69
  "package.json"
70
70
  ],
71
71
  "dependencies": {
72
- "@hono/node-server": "2.1.1",
72
+ "@hono/node-server": "2.1.5",
73
73
  "@inkjs/ui": "^2.0.0",
74
- "@modelcontextprotocol/sdk": "^1.26.0",
75
- "@redactpii/node": "^1.0.16",
74
+ "@modelcontextprotocol/sdk": "^1.32.1",
75
+ "@redactpii/node": "^1.0.19",
76
76
  "cli-spinners": "^3.3.0",
77
77
  "commander": "^14.0.2",
78
78
  "cross-spawn": "^7.0.6",
79
79
  "diff": "^8.0.3",
80
- "express-rate-limit": "^8.3.0",
81
- "hono": "4.13.9",
80
+ "express-rate-limit": "^8.7.1",
81
+ "hono": "4.13.13",
82
82
  "ink": "^6.6.0",
83
83
  "ink-scroll-view": "^0.3.5",
84
84
  "js-yaml": "^4.3.1",
85
85
  "prompts": "^2.4.2",
86
- "react": "^19.2.3",
86
+ "react": "^19.3.1",
87
87
  "semver": "7.8.5",
88
88
  "update-notifier": "^7.3.1",
89
89
  "ws": "8.22.0",
90
- "zod": "^4.3.6"
90
+ "zod": "^4.6.7"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@eslint/js": "^10.0.1",
94
94
  "@types/bun": "latest",
95
95
  "@types/cross-spawn": "^6.0.6",
96
96
  "@types/js-yaml": "^4.0.9",
97
- "@types/node": "^26.1.1",
97
+ "@types/node": "^26.6.5",
98
98
  "@types/prompts": "^2.4.9",
99
99
  "@types/react": "^19.2.7",
100
100
  "@types/semver": "^7.7.1",
101
101
  "@types/update-notifier": "^6.0.8",
102
- "@types/ws": "^8.18.0",
103
- "eslint": "^10.7.0",
102
+ "@types/ws": "^8.18.2",
103
+ "eslint": "^10.13.0",
104
104
  "husky": "^9.1.7",
105
- "knip": "6.38.0",
105
+ "knip": "6.41.0",
106
106
  "lint-staged": "^17.0.4",
107
- "prettier": "^3.9.5",
107
+ "prettier": "^3.9.10",
108
108
  "react-devtools-core": "^8.0.0",
109
109
  "typescript": "^6.0.2",
110
- "typescript-eslint": "^8.64.0"
110
+ "typescript-eslint": "^8.71.2"
111
111
  },
112
112
  "engines": {
113
113
  "node": ">=20.0.0",
@@ -126,11 +126,13 @@
126
126
  "flatted": ">=3.4.0",
127
127
  "picomatch": ">=2.3.2",
128
128
  "path-to-regexp": ">=8.4.0",
129
- "fast-uri": ">=4.2.1",
129
+ "fast-uri": ">=4.2.3",
130
130
  "brace-expansion": ">=5.0.9",
131
131
  "ip-address": ">=10.3.1",
132
132
  "ws": "$ws",
133
- "shell-quote": ">=1.10.0"
133
+ "shell-quote": ">=1.12.0",
134
+ "proxy-addr": ">=2.0.8",
135
+ "body-parser": ">=2.4.0"
134
136
  },
135
137
  "resolutions": {
136
138
  "hono": "$hono",
@@ -139,10 +141,12 @@
139
141
  "flatted": ">=3.4.0",
140
142
  "picomatch": ">=2.3.2",
141
143
  "path-to-regexp": ">=8.4.0",
142
- "fast-uri": ">=4.2.1",
144
+ "fast-uri": ">=4.2.3",
143
145
  "brace-expansion": ">=5.0.9",
144
146
  "ip-address": ">=10.3.1",
145
147
  "ws": "$ws",
146
- "shell-quote": ">=1.10.0"
148
+ "shell-quote": ">=1.12.0",
149
+ "proxy-addr": ">=2.0.8",
150
+ "body-parser": ">=2.4.0"
147
151
  }
148
152
  }