poe-code 3.0.427 → 3.0.428

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.
@@ -68,6 +68,7 @@ export interface StreamableHttpTransportOptions {
68
68
  sessionTtlMs?: number;
69
69
  maxStreamsPerSession?: number;
70
70
  maxSseEventHistory?: number;
71
+ sseKeepAliveMs?: number;
71
72
  maxConcurrentToolCalls?: number;
72
73
  sessionStore?: SessionStore;
73
74
  requestIdGenerator?: () => string;
@@ -88,6 +89,7 @@ export declare class StreamableHttpTransport {
88
89
  private readonly sessionTtlMs;
89
90
  private readonly maxStreamsPerSession;
90
91
  private readonly maxSseEventHistory;
92
+ private readonly sseKeepAliveMs;
91
93
  private readonly maxConcurrentToolCalls;
92
94
  private readonly sessionStore;
93
95
  private readonly requestIdGenerator;
@@ -101,6 +103,7 @@ export declare class StreamableHttpTransport {
101
103
  private nextNotificationEventId;
102
104
  private nextRequestId;
103
105
  private activeToolCalls;
106
+ private sseKeepAliveInterval;
104
107
  constructor(server: Server, options?: StreamableHttpTransportOptions, runWithRequestContext?: RequestContextRunner);
105
108
  handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void>;
106
109
  close(): Promise<void>;
@@ -122,6 +125,9 @@ export declare class StreamableHttpTransport {
122
125
  private createLocalMessageSession;
123
126
  private ensureLocalMessageSession;
124
127
  private closeStreamsForSession;
128
+ private startSseKeepAlive;
129
+ private stopSseKeepAliveIfIdle;
130
+ private stopSseKeepAlive;
125
131
  private sendNotificationToSession;
126
132
  private recordSseEvent;
127
133
  private replaySseEvents;
@@ -1,8 +1,8 @@
1
1
  import { validateHeaderValue } from "node:http";
2
2
  import { JSON_RPC_ERROR_CODES } from "tiny-stdio-mcp-server";
3
- import { formatErrorResponse, formatSuccessResponse, } from "tiny-stdio-mcp-server/jsonrpc";
4
- import { JsonRpcMessageError, readAndClassifyBody, } from "./parse-body.js";
5
- import { createSessionStore, defaultSessionIdGenerator, } from "./session.js";
3
+ import { formatErrorResponse, formatSuccessResponse } from "tiny-stdio-mcp-server/jsonrpc";
4
+ import { JsonRpcMessageError, readAndClassifyBody } from "./parse-body.js";
5
+ import { createSessionStore, defaultSessionIdGenerator } from "./session.js";
6
6
  import { formatSseEvent, SSE_HEADERS } from "./sse.js";
7
7
  const ALLOWED_METHODS = "POST, GET, DELETE, OPTIONS";
8
8
  const MCP_SESSION_ID_HEADER = "Mcp-Session-Id";
@@ -30,6 +30,7 @@ export class StreamableHttpTransport {
30
30
  sessionTtlMs;
31
31
  maxStreamsPerSession;
32
32
  maxSseEventHistory;
33
+ sseKeepAliveMs;
33
34
  maxConcurrentToolCalls;
34
35
  sessionStore;
35
36
  requestIdGenerator;
@@ -43,13 +44,13 @@ export class StreamableHttpTransport {
43
44
  nextNotificationEventId = 1;
44
45
  nextRequestId = 1;
45
46
  activeToolCalls = 0;
47
+ sseKeepAliveInterval;
46
48
  constructor(server, options = {}, runWithRequestContext = async (_req, callback) => callback()) {
47
49
  this.server = server;
48
50
  this.runWithRequestContext = runWithRequestContext;
49
- this.sessionIdGenerator =
50
- hasOwnProperty(options, "sessionIdGenerator")
51
- ? options.sessionIdGenerator
52
- : defaultSessionIdGenerator;
51
+ this.sessionIdGenerator = hasOwnProperty(options, "sessionIdGenerator")
52
+ ? options.sessionIdGenerator
53
+ : defaultSessionIdGenerator;
53
54
  this.enableJsonResponse = options.enableJsonResponse ?? false;
54
55
  this.allowedOrigins = new Set(options.allowedOrigins ?? []);
55
56
  this.allowedHosts = new Set((options.allowedHosts ?? LOCAL_HOSTS).map((host) => this.normalizeHost(host)));
@@ -57,13 +58,15 @@ export class StreamableHttpTransport {
57
58
  this.maxBatchSize = validateOptionalIntegerOption("maxBatchSize", options.maxBatchSize, 1);
58
59
  this.maxSessions = validateOptionalIntegerOption("maxSessions", options.maxSessions, 1);
59
60
  this.sessionTtlMs = validateOptionalIntegerOption("sessionTtlMs", options.sessionTtlMs, 1);
60
- this.maxStreamsPerSession = validateOptionalIntegerOption("maxStreamsPerSession", options.maxStreamsPerSession, 1) ?? 1;
61
+ this.maxStreamsPerSession =
62
+ validateOptionalIntegerOption("maxStreamsPerSession", options.maxStreamsPerSession, 1) ?? 1;
61
63
  this.maxSseEventHistory =
62
64
  validateOptionalIntegerOption("maxSseEventHistory", options.maxSseEventHistory, 0) ?? 100;
65
+ this.sseKeepAliveMs =
66
+ validateOptionalIntegerOption("sseKeepAliveMs", options.sseKeepAliveMs, 0) ?? 30_000;
63
67
  this.maxConcurrentToolCalls = validateOptionalIntegerOption("maxConcurrentToolCalls", options.maxConcurrentToolCalls, 1);
64
68
  this.sessionStore = options.sessionStore ?? createSessionStore();
65
- this.requestIdGenerator =
66
- options.requestIdGenerator ?? (() => `req-${this.nextRequestId++}`);
69
+ this.requestIdGenerator = options.requestIdGenerator ?? (() => `req-${this.nextRequestId++}`);
67
70
  this.observability = options.observability ?? {};
68
71
  this.trustedProxy = options.trustedProxy ?? false;
69
72
  }
@@ -80,7 +83,7 @@ export class StreamableHttpTransport {
80
83
  requestId,
81
84
  method: req.method ?? "",
82
85
  path: req.url ?? "",
83
- sessionId: this.readSessionId(req),
86
+ sessionId: this.readSessionId(req)
84
87
  });
85
88
  try {
86
89
  this.purgeExpiredSessions();
@@ -108,7 +111,7 @@ export class StreamableHttpTransport {
108
111
  return;
109
112
  default:
110
113
  this.respondWithStatus(res, 405, undefined, {
111
- Allow: ALLOWED_METHODS,
114
+ Allow: ALLOWED_METHODS
112
115
  });
113
116
  }
114
117
  }
@@ -119,7 +122,7 @@ export class StreamableHttpTransport {
119
122
  method: req.method ?? "",
120
123
  durationMs: Date.now() - startedAt,
121
124
  error,
122
- sessionId: this.readSessionId(req),
125
+ sessionId: this.readSessionId(req)
123
126
  });
124
127
  if (!res.headersSent) {
125
128
  this.respondWithStatus(res, 500);
@@ -136,11 +139,12 @@ export class StreamableHttpTransport {
136
139
  method: req.method ?? "",
137
140
  statusCode: res.statusCode,
138
141
  durationMs: Date.now() - startedAt,
139
- sessionId: this.readSessionId(req),
142
+ sessionId: this.readSessionId(req)
140
143
  });
141
144
  }
142
145
  }
143
146
  async close() {
147
+ this.stopSseKeepAlive();
144
148
  for (const sessionId of [...this.sseStreams.keys()]) {
145
149
  this.closeStreamsForSession(sessionId);
146
150
  }
@@ -162,7 +166,7 @@ export class StreamableHttpTransport {
162
166
  try {
163
167
  classified = await readAndClassifyBody(req, undefined, {
164
168
  maxBytes: this.maxRequestBytes,
165
- maxBatchSize: this.maxBatchSize,
169
+ maxBatchSize: this.maxBatchSize
166
170
  });
167
171
  }
168
172
  catch (error) {
@@ -211,7 +215,8 @@ export class StreamableHttpTransport {
211
215
  }
212
216
  sessionId = headerSessionId;
213
217
  this.touchSession(sessionId);
214
- if (session?.protocolVersion !== undefined && !this.acceptsProtocolVersion(req, session.protocolVersion)) {
218
+ if (session?.protocolVersion !== undefined &&
219
+ !this.acceptsProtocolVersion(req, session.protocolVersion)) {
215
220
  this.respondWithStatus(res, 400);
216
221
  return;
217
222
  }
@@ -224,7 +229,7 @@ export class StreamableHttpTransport {
224
229
  if (message === null) {
225
230
  responses.push(formatErrorResponse(null, {
226
231
  code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
227
- message: "Invalid Request",
232
+ message: "Invalid Request"
228
233
  }));
229
234
  continue;
230
235
  }
@@ -232,35 +237,35 @@ export class StreamableHttpTransport {
232
237
  continue;
233
238
  }
234
239
  const session = sessionId === undefined ? undefined : this.sessionStore.get(sessionId);
235
- if (session !== undefined
236
- && message.method !== "initialize"
237
- && message.method !== "notifications/initialized"
238
- && message.method !== "ping"
239
- && !session.initialized) {
240
+ if (session !== undefined &&
241
+ message.method !== "initialize" &&
242
+ message.method !== "notifications/initialized" &&
243
+ message.method !== "ping" &&
244
+ !session.initialized) {
240
245
  if (this.isRequest(message)) {
241
246
  responses.push(formatErrorResponse(message.id, {
242
247
  code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
243
- message: "Session not initialized",
248
+ message: "Session not initialized"
244
249
  }));
245
250
  }
246
251
  continue;
247
252
  }
248
253
  const requestId = this.responseRequestIds.get(res) ?? "";
249
254
  const toolName = this.readToolName(message);
250
- if (message.method === "tools/call"
251
- && this.maxConcurrentToolCalls !== undefined
252
- && this.activeToolCalls >= this.maxConcurrentToolCalls) {
255
+ if (message.method === "tools/call" &&
256
+ this.maxConcurrentToolCalls !== undefined &&
257
+ this.activeToolCalls >= this.maxConcurrentToolCalls) {
253
258
  if (this.isRequest(message)) {
254
259
  responses.push(formatErrorResponse(message.id, {
255
260
  code: -32000,
256
- message: "Too many concurrent tool calls",
261
+ message: "Too many concurrent tool calls"
257
262
  }));
258
263
  }
259
264
  continue;
260
265
  }
261
266
  const messageHandler = sessionId === undefined
262
267
  ? this.server.handleMessage
263
- : this.sessionMessages.get(sessionId)?.handleMessage ?? this.server.handleMessage;
268
+ : (this.sessionMessages.get(sessionId)?.handleMessage ?? this.server.handleMessage);
264
269
  const isToolCall = message.method === "tools/call";
265
270
  const toolStartedAt = Date.now();
266
271
  if (isToolCall) {
@@ -269,7 +274,7 @@ export class StreamableHttpTransport {
269
274
  type: "tool.start",
270
275
  requestId,
271
276
  sessionId,
272
- toolName,
277
+ toolName
273
278
  });
274
279
  }
275
280
  let handled;
@@ -289,7 +294,7 @@ export class StreamableHttpTransport {
289
294
  sessionId,
290
295
  toolName,
291
296
  ok: this.isToolCallOk(error, result),
292
- durationMs: Date.now() - toolStartedAt,
297
+ durationMs: Date.now() - toolStartedAt
293
298
  });
294
299
  }
295
300
  if (session !== undefined && error === undefined) {
@@ -299,8 +304,8 @@ export class StreamableHttpTransport {
299
304
  session.protocolVersion = initializeResult.protocolVersion;
300
305
  }
301
306
  }
302
- else if (message.method === "notifications/initialized"
303
- && session.protocolVersion !== undefined) {
307
+ else if (message.method === "notifications/initialized" &&
308
+ session.protocolVersion !== undefined) {
304
309
  session.initialized = true;
305
310
  }
306
311
  }
@@ -337,7 +342,7 @@ export class StreamableHttpTransport {
337
342
  async handleGet(req, res) {
338
343
  if (this.sessionIdGenerator === undefined) {
339
344
  this.respondWithStatus(res, 405, undefined, {
340
- Allow: ALLOWED_METHODS,
345
+ Allow: ALLOWED_METHODS
341
346
  });
342
347
  return;
343
348
  }
@@ -356,9 +361,9 @@ export class StreamableHttpTransport {
356
361
  return;
357
362
  }
358
363
  this.touchSession(sessionId);
359
- if (session.initialized
360
- && session.protocolVersion !== undefined
361
- && !this.acceptsProtocolVersion(req, session.protocolVersion)) {
364
+ if (session.initialized &&
365
+ session.protocolVersion !== undefined &&
366
+ !this.acceptsProtocolVersion(req, session.protocolVersion)) {
362
367
  this.respondWithStatus(res, 400);
363
368
  return;
364
369
  }
@@ -374,10 +379,11 @@ export class StreamableHttpTransport {
374
379
  this.sseStreams.set(sessionId, streams);
375
380
  }
376
381
  streams.add(res);
382
+ this.startSseKeepAlive();
377
383
  this.emit({
378
384
  type: "stream.opened",
379
385
  sessionId,
380
- streamCount: streams.size,
386
+ streamCount: streams.size
381
387
  });
382
388
  const cleanup = () => {
383
389
  const activeStreams = this.sseStreams.get(sessionId);
@@ -389,12 +395,13 @@ export class StreamableHttpTransport {
389
395
  this.emit({
390
396
  type: "stream.closed",
391
397
  sessionId,
392
- streamCount: activeStreams.size,
398
+ streamCount: activeStreams.size
393
399
  });
394
400
  }
395
401
  if (activeStreams.size === 0) {
396
402
  this.sseStreams.delete(sessionId);
397
403
  }
404
+ this.stopSseKeepAliveIfIdle();
398
405
  };
399
406
  req.on("close", cleanup);
400
407
  res.on("close", cleanup);
@@ -406,7 +413,7 @@ export class StreamableHttpTransport {
406
413
  handleDelete(req, res) {
407
414
  if (this.sessionIdGenerator === undefined) {
408
415
  this.respondWithStatus(res, 405, undefined, {
409
- Allow: ALLOWED_METHODS,
416
+ Allow: ALLOWED_METHODS
410
417
  });
411
418
  return;
412
419
  }
@@ -416,7 +423,8 @@ export class StreamableHttpTransport {
416
423
  return;
417
424
  }
418
425
  const session = this.getActiveSession(sessionId);
419
- if (session?.protocolVersion !== undefined && !this.acceptsProtocolVersion(req, session.protocolVersion)) {
426
+ if (session?.protocolVersion !== undefined &&
427
+ !this.acceptsProtocolVersion(req, session.protocolVersion)) {
420
428
  this.respondWithStatus(res, 400);
421
429
  return;
422
430
  }
@@ -431,7 +439,7 @@ export class StreamableHttpTransport {
431
439
  const method = Array.isArray(requestedMethod) ? requestedMethod[0] : requestedMethod;
432
440
  if (method !== undefined && !ALLOWED_METHODS.split(", ").includes(method)) {
433
441
  this.respondWithStatus(res, 405, undefined, {
434
- Allow: ALLOWED_METHODS,
442
+ Allow: ALLOWED_METHODS
435
443
  });
436
444
  return;
437
445
  }
@@ -441,8 +449,8 @@ export class StreamableHttpTransport {
441
449
  "Access-Control-Allow-Methods": ALLOWED_METHODS,
442
450
  "Access-Control-Allow-Headers": Array.isArray(requestedHeaders)
443
451
  ? requestedHeaders.join(", ")
444
- : requestedHeaders ?? DEFAULT_ALLOWED_HEADERS,
445
- "Access-Control-Max-Age": "600",
452
+ : (requestedHeaders ?? DEFAULT_ALLOWED_HEADERS),
453
+ "Access-Control-Max-Age": "600"
446
454
  });
447
455
  }
448
456
  readSessionId(req) {
@@ -546,7 +554,7 @@ export class StreamableHttpTransport {
546
554
  const messageSession = this.createLocalMessageSession(sessionId);
547
555
  if (session.protocolVersion !== undefined) {
548
556
  await messageSession.handleMessage("initialize", {
549
- protocolVersion: session.protocolVersion,
557
+ protocolVersion: session.protocolVersion
550
558
  });
551
559
  if (session.initialized) {
552
560
  await messageSession.handleMessage("notifications/initialized");
@@ -565,6 +573,35 @@ export class StreamableHttpTransport {
565
573
  }
566
574
  }
567
575
  this.sseStreams.delete(sessionId);
576
+ this.stopSseKeepAliveIfIdle();
577
+ }
578
+ startSseKeepAlive() {
579
+ if (this.sseKeepAliveMs === 0 || this.sseKeepAliveInterval !== undefined) {
580
+ return;
581
+ }
582
+ this.sseKeepAliveInterval = setInterval(() => {
583
+ for (const streams of this.sseStreams.values()) {
584
+ for (const response of streams) {
585
+ if (!response.writableEnded) {
586
+ response.write(": keepalive\n\n");
587
+ }
588
+ }
589
+ }
590
+ }, this.sseKeepAliveMs);
591
+ this.sseKeepAliveInterval.unref();
592
+ }
593
+ stopSseKeepAliveIfIdle() {
594
+ if ([...this.sseStreams.values()].some((streams) => streams.size > 0)) {
595
+ return;
596
+ }
597
+ this.stopSseKeepAlive();
598
+ }
599
+ stopSseKeepAlive() {
600
+ if (this.sseKeepAliveInterval === undefined) {
601
+ return;
602
+ }
603
+ clearInterval(this.sseKeepAliveInterval);
604
+ this.sseKeepAliveInterval = undefined;
568
605
  }
569
606
  sendNotificationToSession(sessionId, notification) {
570
607
  if (!this.sessionStore.get(sessionId)?.initialized) {
@@ -579,7 +616,7 @@ export class StreamableHttpTransport {
579
616
  }
580
617
  const event = formatSseEvent({
581
618
  id: String(id),
582
- data,
619
+ data
583
620
  });
584
621
  let latestResponse;
585
622
  for (const response of streams) {
@@ -659,7 +696,7 @@ export class StreamableHttpTransport {
659
696
  }
660
697
  }
661
698
  const host = req.headers.host;
662
- return Array.isArray(host) ? host[0] ?? "127.0.0.1" : host ?? "127.0.0.1";
699
+ return Array.isArray(host) ? (host[0] ?? "127.0.0.1") : (host ?? "127.0.0.1");
663
700
  }
664
701
  readForwardedHeader(req, headerName) {
665
702
  const value = req.headers[headerName];
@@ -686,9 +723,7 @@ export class StreamableHttpTransport {
686
723
  if (colonCount > 1) {
687
724
  return normalized;
688
725
  }
689
- return normalized.includes(":")
690
- ? normalized.split(":")[0] ?? normalized
691
- : normalized;
726
+ return normalized.includes(":") ? (normalized.split(":")[0] ?? normalized) : normalized;
692
727
  }
693
728
  acceptsConfiguredResponse(req) {
694
729
  const expectedType = this.enableJsonResponse ? "application/json" : "text/event-stream";
@@ -727,8 +762,7 @@ export class StreamableHttpTransport {
727
762
  if (typeof result !== "object" || result === null || Array.isArray(result)) {
728
763
  return true;
729
764
  }
730
- return !(hasOwnProperty(result, "isError")
731
- && result.isError === true);
765
+ return !(hasOwnProperty(result, "isError") && result.isError === true);
732
766
  }
733
767
  respondWithJsonRpcError(res, statusCode, errorCode, message, id = null) {
734
768
  this.respondWithStatus(res, statusCode, undefined, { "Content-Type": "application/json" }, formatErrorResponse(id, { code: errorCode, message }));
@@ -749,19 +783,19 @@ export class StreamableHttpTransport {
749
783
  ? {}
750
784
  : {
751
785
  "Access-Control-Allow-Origin": origin,
752
- "Access-Control-Expose-Headers": "Mcp-Session-Id, X-Request-Id",
753
- }),
786
+ "Access-Control-Expose-Headers": "Mcp-Session-Id, X-Request-Id"
787
+ })
754
788
  };
755
789
  if (sessionId === undefined) {
756
790
  return {
757
791
  ...baseHeaders,
758
- ...(headers ?? {}),
792
+ ...(headers ?? {})
759
793
  };
760
794
  }
761
795
  return {
762
796
  ...baseHeaders,
763
797
  ...(headers ?? {}),
764
- [MCP_SESSION_ID_HEADER]: sessionId,
798
+ [MCP_SESSION_ID_HEADER]: sessionId
765
799
  };
766
800
  }
767
801
  emit(event) {
@@ -1,5 +1,4 @@
1
1
  export { countTokens, createTokenizer, DEFAULT_ENCODING } from "./tokenizer.js";
2
- export { estimateTokens } from "./estimate.js";
3
2
  export type { Tokenizer, TokenizerOptions } from "./tokenizer.js";
4
3
  export { tokenfill } from "./tokenfill.js";
5
4
  export type { TokenfillOptions, TokenfillResult } from "./tokenfill.js";
@@ -1,3 +1,2 @@
1
1
  export { countTokens, createTokenizer, DEFAULT_ENCODING } from "./tokenizer.js";
2
- export { estimateTokens } from "./estimate.js";
3
2
  export { tokenfill } from "./tokenfill.js";
@@ -77,9 +77,13 @@ function stepKey(state, key, runtimeHandles) {
77
77
  case "bottom":
78
78
  return setCursor(state, state.filtered.length - 1);
79
79
  case "pageUp":
80
- return moveCursor(state, -pageSize(state));
80
+ return isDetailBlobFocused(state)
81
+ ? detailScroll(state, -detailBodyHeight(state))
82
+ : moveCursor(state, -pageSize(state));
81
83
  case "pageDown":
82
- return moveCursor(state, pageSize(state));
84
+ return isDetailBlobFocused(state)
85
+ ? detailScroll(state, detailBodyHeight(state))
86
+ : moveCursor(state, pageSize(state));
83
87
  case "focusNext":
84
88
  return focusNext(state);
85
89
  case "escape":
@@ -328,8 +332,16 @@ function moveCursor(state, delta) {
328
332
  if (state.focused === "detail" && hasDetailCursor(state)) {
329
333
  return moveDetailCursor(state, delta);
330
334
  }
335
+ if (isDetailBlobFocused(state)) {
336
+ return detailScroll(state, delta);
337
+ }
331
338
  return setCursor(state, state.cursor + delta);
332
339
  }
340
+ function isDetailBlobFocused(state) {
341
+ return (state.focused === "detail" &&
342
+ !hasDetailCursor(state) &&
343
+ (state.detail.items?.length ?? 0) > 0);
344
+ }
333
345
  function moveDetailCursor(state, delta) {
334
346
  const max = Math.max(0, (state.detail.items?.length ?? 0) - 1);
335
347
  const cursor = clamp(state.detail.cursor + delta, 0, max);
@@ -1,2 +0,0 @@
1
- export declare const EXACT_COUNT_CHAR_LIMIT = 8192;
2
- export declare function estimateTokens(text: string): number;
@@ -1,38 +0,0 @@
1
- import { countTokens } from "./tokenizer.js";
2
- export const EXACT_COUNT_CHAR_LIMIT = 8192;
3
- const SAMPLE_CHUNK_LENGTH = 2048;
4
- export function estimateTokens(text) {
5
- if (text.length <= EXACT_COUNT_CHAR_LIMIT) {
6
- return countTokens(text);
7
- }
8
- const middleStart = Math.floor(text.length / 2 - SAMPLE_CHUNK_LENGTH / 2);
9
- const sample = [
10
- text.slice(0, SAMPLE_CHUNK_LENGTH),
11
- text.slice(middleStart, middleStart + SAMPLE_CHUNK_LENGTH),
12
- text.slice(text.length - SAMPLE_CHUNK_LENGTH)
13
- ]
14
- .map(trimBrokenSurrogates)
15
- .join("");
16
- const sampleTokens = countTokens(sample);
17
- if (sampleTokens === 0) {
18
- return 0;
19
- }
20
- return Math.round((text.length / sample.length) * sampleTokens);
21
- }
22
- function trimBrokenSurrogates(value) {
23
- let start = 0;
24
- let end = value.length;
25
- if (end > start && isLowSurrogate(value.charCodeAt(start))) {
26
- start += 1;
27
- }
28
- if (end > start && isHighSurrogate(value.charCodeAt(end - 1))) {
29
- end -= 1;
30
- }
31
- return value.slice(start, end);
32
- }
33
- function isHighSurrogate(code) {
34
- return code >= 0xd800 && code <= 0xdbff;
35
- }
36
- function isLowSurrogate(code) {
37
- return code >= 0xdc00 && code <= 0xdfff;
38
- }