tinker-agent 1.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +173 -0
  2. package/package.json +78 -0
  3. package/patches/markdansi@0.3.2.patch +37 -0
  4. package/src/agent/context-builder.ts +43 -0
  5. package/src/agent/context-meter.ts +310 -0
  6. package/src/agent/loop.ts +525 -0
  7. package/src/agent/runtime-session.ts +1212 -0
  8. package/src/agent/session-ledger.ts +828 -0
  9. package/src/agent/turn-cancellation.ts +44 -0
  10. package/src/agent/types.ts +77 -0
  11. package/src/cli/config.ts +283 -0
  12. package/src/cli/index.ts +29 -0
  13. package/src/cli/model-profiles.ts +289 -0
  14. package/src/cli/run-runner.ts +107 -0
  15. package/src/cli/tui-runner.tsx +290 -0
  16. package/src/context/compiled-context-hash.ts +138 -0
  17. package/src/context/compiled-context-validator.ts +209 -0
  18. package/src/context/context-manager.ts +362 -0
  19. package/src/context/context-policy.ts +8 -0
  20. package/src/context/context-protocol-validator.ts +463 -0
  21. package/src/context/context-revision-compiler.ts +281 -0
  22. package/src/context/context-revision.ts +111 -0
  23. package/src/context/context-source.ts +30 -0
  24. package/src/context/context-swap-renderer.ts +272 -0
  25. package/src/context/protocol-frame.ts +240 -0
  26. package/src/context/swap-planner.ts +725 -0
  27. package/src/events/append-private-file.ts +16 -0
  28. package/src/events/bash-result-detail.ts +70 -0
  29. package/src/events/composite-event-sink.ts +82 -0
  30. package/src/events/event-sink.ts +16 -0
  31. package/src/events/jsonl-event-log.ts +13 -0
  32. package/src/events/observation-text-log.ts +195 -0
  33. package/src/events/stdout-event-printer.ts +396 -0
  34. package/src/events/types.ts +263 -0
  35. package/src/ids/runtime-id.ts +68 -0
  36. package/src/ids/uuid-v7.ts +5 -0
  37. package/src/instructions/project-instructions.ts +242 -0
  38. package/src/mcp/mcp-config.ts +144 -0
  39. package/src/mcp/mcp-manager.ts +216 -0
  40. package/src/mcp/mcp-tool-executor.ts +178 -0
  41. package/src/model/committed-prefix-auditor.ts +68 -0
  42. package/src/model/fake-model-client.ts +280 -0
  43. package/src/model/model-client.ts +64 -0
  44. package/src/model/model-context-profile.ts +134 -0
  45. package/src/model/model-request-preflight.ts +120 -0
  46. package/src/model/openai-chat-mapping.ts +444 -0
  47. package/src/model/openai-chat-model-client.ts +190 -0
  48. package/src/model/prompt-prefix-hash.ts +47 -0
  49. package/src/model/token-estimator.ts +148 -0
  50. package/src/observation/observation-builder.ts +481 -0
  51. package/src/session/resume-projection.ts +616 -0
  52. package/src/session/session-catalog.ts +270 -0
  53. package/src/session/session-errors.ts +121 -0
  54. package/src/session/session-history-reader.ts +535 -0
  55. package/src/session/session-lock.ts +291 -0
  56. package/src/session/session-schema.ts +741 -0
  57. package/src/session/session-store.ts +3067 -0
  58. package/src/session/sqlite-session-ledger.ts +153 -0
  59. package/src/tools/bash-task.ts +617 -0
  60. package/src/tools/bash.ts +450 -0
  61. package/src/tools/cwd-state.ts +22 -0
  62. package/src/tools/edit.ts +428 -0
  63. package/src/tools/file-diff.ts +116 -0
  64. package/src/tools/glob.ts +202 -0
  65. package/src/tools/grep.ts +550 -0
  66. package/src/tools/hash.ts +9 -0
  67. package/src/tools/path-safety.ts +33 -0
  68. package/src/tools/read.ts +319 -0
  69. package/src/tools/recall.ts +400 -0
  70. package/src/tools/registry.ts +213 -0
  71. package/src/tools/ripgrep.ts +220 -0
  72. package/src/tools/task-list.ts +59 -0
  73. package/src/tools/task-output-snapshot.ts +47 -0
  74. package/src/tools/task-output-tool.ts +62 -0
  75. package/src/tools/task-output.ts +159 -0
  76. package/src/tools/task-stop.ts +59 -0
  77. package/src/tools/task-tool-args.ts +29 -0
  78. package/src/tools/types.ts +330 -0
  79. package/src/tools/web-fetch/backend.ts +27 -0
  80. package/src/tools/web-fetch/browser-backend.ts +126 -0
  81. package/src/tools/web-fetch/exa-backend.ts +172 -0
  82. package/src/tools/web-fetch/index.ts +298 -0
  83. package/src/tools/web-fetch/local-backend.ts +267 -0
  84. package/src/tools/web-fetch/refiner.ts +78 -0
  85. package/src/tools/web-fetch/route.ts +95 -0
  86. package/src/tools/web-search.ts +300 -0
  87. package/src/tools/write.ts +244 -0
  88. package/src/tui/app.tsx +497 -0
  89. package/src/tui/components/assistant-markdown.tsx +47 -0
  90. package/src/tui/components/background-tasks.tsx +92 -0
  91. package/src/tui/components/bash-result-view.tsx +47 -0
  92. package/src/tui/components/context-status.tsx +127 -0
  93. package/src/tui/components/diff-view.tsx +151 -0
  94. package/src/tui/components/file-viewer.tsx +212 -0
  95. package/src/tui/components/footer.tsx +60 -0
  96. package/src/tui/components/header.tsx +21 -0
  97. package/src/tui/components/model-picker.tsx +142 -0
  98. package/src/tui/components/prompt-input.tsx +432 -0
  99. package/src/tui/components/resume-session-picker.tsx +273 -0
  100. package/src/tui/components/timeline.tsx +121 -0
  101. package/src/tui/context-format.ts +24 -0
  102. package/src/tui/event-store.ts +865 -0
  103. package/src/tui/git-branch.ts +23 -0
  104. package/src/tui/line-editor.ts +157 -0
  105. package/src/tui/prompt-history.ts +94 -0
  106. package/src/tui/slash-commands.ts +126 -0
  107. package/src/tui/tui-projection-policy.ts +35 -0
  108. package/src/tui/tui-projection-store.ts +123 -0
  109. package/src/tui/tui-session-controller.ts +170 -0
  110. package/src/tui/view-file.ts +122 -0
@@ -0,0 +1,8 @@
1
+ export const swapOnlyPolicyV1 = Object.freeze({
2
+ version: "swap-only-v1",
3
+ minimumObservationBytes: 8 * 1_024,
4
+ protectedRecentTurnCount: 8,
5
+ targetInputRatio: 0.6,
6
+ } as const);
7
+
8
+ export type SwapOnlyPolicyV1 = typeof swapOnlyPolicyV1;
@@ -0,0 +1,463 @@
1
+ import type { MessageId, ProtocolFrameId, ToolCallId } from "../ids/runtime-id";
2
+ import {
3
+ contentHash,
4
+ rawResultHash,
5
+ type CanonicalMessageRecord,
6
+ type ProtocolContextView,
7
+ type ProtocolFrame,
8
+ type ToolResultRecord,
9
+ } from "./protocol-frame";
10
+
11
+ export type ContextProtocolErrorCode =
12
+ | "ledger_faulted"
13
+ | "open_frame"
14
+ | "ordinal_gap"
15
+ | "frame_range_mismatch"
16
+ | "duplicate_frame_id"
17
+ | "duplicate_message_id"
18
+ | "duplicate_tool_call_id"
19
+ | "duplicate_provider_tool_call_id"
20
+ | "invalid_system_frame"
21
+ | "invalid_user_frame"
22
+ | "invalid_assistant_frame"
23
+ | "missing_tool_message"
24
+ | "unexpected_tool_message"
25
+ | "tool_message_order_mismatch"
26
+ | "tool_message_identity_mismatch"
27
+ | "missing_tool_result"
28
+ | "tool_result_mismatch"
29
+ | "content_hash_mismatch"
30
+ | "raw_hash_mismatch";
31
+
32
+ export class ContextProtocolError extends Error {
33
+ readonly code: ContextProtocolErrorCode;
34
+ readonly frameId?: ProtocolFrameId;
35
+ readonly messageId?: MessageId;
36
+ readonly ordinal?: number;
37
+ readonly toolCallId?: ToolCallId;
38
+
39
+ constructor(
40
+ code: ContextProtocolErrorCode,
41
+ message: string,
42
+ identity: {
43
+ frameId?: ProtocolFrameId;
44
+ messageId?: MessageId;
45
+ ordinal?: number;
46
+ toolCallId?: ToolCallId;
47
+ } = {},
48
+ ) {
49
+ super(message);
50
+ this.name = "ContextProtocolError";
51
+ this.code = code;
52
+ Object.assign(this, identity);
53
+ }
54
+ }
55
+
56
+ export type ContextProtocolValidationOptions = {
57
+ allowOpenTail?: boolean;
58
+ fullIntegrity?: boolean;
59
+ };
60
+
61
+ export class ContextProtocolValidator {
62
+ validate(
63
+ view: ProtocolContextView,
64
+ options: ContextProtocolValidationOptions = {},
65
+ ): void {
66
+ if (view.faulted) {
67
+ fail("ledger_faulted", "Cannot build context from a faulted ledger.");
68
+ }
69
+ if (view.frames.length === 0 || view.messages.length === 0) {
70
+ fail("invalid_system_frame", "Protocol context has no system frame.");
71
+ }
72
+
73
+ const messageIds = new Set<string>();
74
+ const messagesByFrame = new Map<string, CanonicalMessageRecord[]>();
75
+ for (let index = 0; index < view.messages.length; index += 1) {
76
+ const message = requireItem(view.messages, index, "message");
77
+ const expectedOrdinal = index + 1;
78
+ if (message.ordinal !== expectedOrdinal) {
79
+ fail(
80
+ "ordinal_gap",
81
+ `Message ordinal must be ${expectedOrdinal}; received ${message.ordinal}.`,
82
+ identityForMessage(message),
83
+ );
84
+ }
85
+ if (message.sessionId !== view.sessionId) {
86
+ fail(
87
+ "frame_range_mismatch",
88
+ `Message ${message.messageId} belongs to another session.`,
89
+ identityForMessage(message),
90
+ );
91
+ }
92
+ if (messageIds.has(message.messageId)) {
93
+ fail(
94
+ "duplicate_message_id",
95
+ `Duplicate message ID ${message.messageId}.`,
96
+ identityForMessage(message),
97
+ );
98
+ }
99
+ messageIds.add(message.messageId);
100
+ const frameMessages = messagesByFrame.get(message.frameId) ?? [];
101
+ frameMessages.push(message);
102
+ messagesByFrame.set(message.frameId, frameMessages);
103
+
104
+ if (
105
+ options.fullIntegrity === true &&
106
+ message.contentSha256 !== contentHash(message.content)
107
+ ) {
108
+ fail(
109
+ "content_hash_mismatch",
110
+ `Content hash does not match message ${message.messageId}.`,
111
+ identityForMessage(message),
112
+ );
113
+ }
114
+ }
115
+
116
+ const frameIds = new Set<string>();
117
+ let expectedFirstOrdinal = 1;
118
+ let openFrame: ProtocolFrame | undefined;
119
+ const seenToolCallIds = new Set<string>();
120
+ const usedResultCallIds = new Set<string>();
121
+ const resultsByCallId = groupResults(view.toolResults);
122
+
123
+ for (let index = 0; index < view.frames.length; index += 1) {
124
+ const frame = requireItem(view.frames, index, "frame");
125
+ if (frame.sessionId !== view.sessionId) {
126
+ fail(
127
+ "frame_range_mismatch",
128
+ `Frame ${frame.frameId} belongs to another session.`,
129
+ { frameId: frame.frameId },
130
+ );
131
+ }
132
+ if (frameIds.has(frame.frameId)) {
133
+ fail("duplicate_frame_id", `Duplicate frame ID ${frame.frameId}.`, {
134
+ frameId: frame.frameId,
135
+ });
136
+ }
137
+ frameIds.add(frame.frameId);
138
+ if (frame.firstOrdinal !== expectedFirstOrdinal) {
139
+ fail(
140
+ "frame_range_mismatch",
141
+ `Frame ${frame.frameId} must start at ordinal ${expectedFirstOrdinal}; received ${frame.firstOrdinal}.`,
142
+ { frameId: frame.frameId, ordinal: frame.firstOrdinal },
143
+ );
144
+ }
145
+
146
+ const frameMessages = messagesByFrame.get(frame.frameId) ?? [];
147
+ if (frameMessages.length === 0) {
148
+ fail("frame_range_mismatch", `Frame ${frame.frameId} is empty.`, {
149
+ frameId: frame.frameId,
150
+ });
151
+ }
152
+ const actualLast = requireItem(
153
+ frameMessages,
154
+ frameMessages.length - 1,
155
+ "frame message",
156
+ ).ordinal;
157
+ if (frame.state === "open") {
158
+ if (
159
+ options.allowOpenTail !== true ||
160
+ index !== view.frames.length - 1 ||
161
+ frame.lastOrdinal !== undefined ||
162
+ openFrame !== undefined
163
+ ) {
164
+ fail("open_frame", `Frame ${frame.frameId} is open.`, {
165
+ frameId: frame.frameId,
166
+ });
167
+ }
168
+ openFrame = frame;
169
+ } else if (frame.lastOrdinal !== actualLast) {
170
+ fail(
171
+ "frame_range_mismatch",
172
+ `Frame ${frame.frameId} ends at ${String(frame.lastOrdinal)}, but its messages end at ${actualLast}.`,
173
+ { frameId: frame.frameId, ordinal: actualLast },
174
+ );
175
+ }
176
+ if (frameMessages[0]?.ordinal !== frame.firstOrdinal) {
177
+ fail(
178
+ "frame_range_mismatch",
179
+ `Frame ${frame.frameId} does not own its declared first message.`,
180
+ { frameId: frame.frameId, ordinal: frame.firstOrdinal },
181
+ );
182
+ }
183
+
184
+ validateFrame({
185
+ frame,
186
+ frameMessages,
187
+ seenToolCallIds,
188
+ usedResultCallIds,
189
+ resultsByCallId,
190
+ fullIntegrity: options.fullIntegrity === true,
191
+ });
192
+ expectedFirstOrdinal = actualLast + 1;
193
+ }
194
+
195
+ if (expectedFirstOrdinal !== view.messages.length + 1) {
196
+ fail(
197
+ "frame_range_mismatch",
198
+ "Protocol frames do not cover every message ordinal.",
199
+ );
200
+ }
201
+ for (const frameId of messagesByFrame.keys()) {
202
+ if (!frameIds.has(frameId)) {
203
+ const message = messagesByFrame.get(frameId)?.[0];
204
+ fail(
205
+ "frame_range_mismatch",
206
+ `Message references unknown frame ${frameId}.`,
207
+ message === undefined ? {} : identityForMessage(message),
208
+ );
209
+ }
210
+ }
211
+ for (const result of view.toolResults) {
212
+ if (!usedResultCallIds.has(result.toolCallId)) {
213
+ fail(
214
+ "tool_result_mismatch",
215
+ `Tool result ${result.toolCallId} is not referenced by a tool message.`,
216
+ { frameId: result.frameId, toolCallId: result.toolCallId },
217
+ );
218
+ }
219
+ }
220
+ }
221
+ }
222
+
223
+ type ValidateFrameInput = {
224
+ frame: ProtocolFrame;
225
+ frameMessages: readonly CanonicalMessageRecord[];
226
+ seenToolCallIds: Set<string>;
227
+ usedResultCallIds: Set<string>;
228
+ resultsByCallId: Map<string, ToolResultRecord[]>;
229
+ fullIntegrity: boolean;
230
+ };
231
+
232
+ function validateFrame(input: ValidateFrameInput): void {
233
+ const { frame, frameMessages } = input;
234
+ const first = requireItem(frameMessages, 0, "frame message");
235
+ switch (frame.kind) {
236
+ case "system":
237
+ if (
238
+ frame.firstOrdinal !== 1 ||
239
+ frameMessages.length !== 1 ||
240
+ first.role !== "system"
241
+ ) {
242
+ fail("invalid_system_frame", `Invalid system frame ${frame.frameId}.`, {
243
+ ...identityForMessage(first),
244
+ });
245
+ }
246
+ return;
247
+ case "user":
248
+ if (
249
+ frameMessages.length !== 1 ||
250
+ first.role !== "user" ||
251
+ first.turnId !== frame.turnId
252
+ ) {
253
+ fail("invalid_user_frame", `Invalid user frame ${frame.frameId}.`, {
254
+ ...identityForMessage(first),
255
+ });
256
+ }
257
+ return;
258
+ case "assistant_text":
259
+ if (
260
+ frameMessages.length !== 1 ||
261
+ first.role !== "assistant" ||
262
+ first.turnId !== frame.turnId ||
263
+ first.iterationId !== frame.iterationId ||
264
+ (first.toolCalls?.length ?? 0) !== 0 ||
265
+ first.content === null ||
266
+ first.content.trim() === ""
267
+ ) {
268
+ fail(
269
+ "invalid_assistant_frame",
270
+ `Invalid assistant text frame ${frame.frameId}.`,
271
+ identityForMessage(first),
272
+ );
273
+ }
274
+ return;
275
+ case "tool_exchange":
276
+ validateToolExchange(input, first);
277
+ }
278
+ }
279
+
280
+ function validateToolExchange(
281
+ input: ValidateFrameInput,
282
+ assistant: CanonicalMessageRecord,
283
+ ): void {
284
+ const { frame, frameMessages } = input;
285
+ if (
286
+ assistant.role !== "assistant" ||
287
+ assistant.turnId !== frame.turnId ||
288
+ assistant.iterationId !== frame.iterationId ||
289
+ assistant.toolCalls === undefined ||
290
+ assistant.toolCalls.length === 0
291
+ ) {
292
+ fail(
293
+ "invalid_assistant_frame",
294
+ `Tool exchange ${frame.frameId} must begin with an assistant tool call message.`,
295
+ identityForMessage(assistant),
296
+ );
297
+ }
298
+
299
+ const providerIds = new Set<string>();
300
+ for (let index = 0; index < assistant.toolCalls.length; index += 1) {
301
+ const call = requireItem(assistant.toolCalls, index, "tool call");
302
+ if (
303
+ call.sessionId !== frame.sessionId ||
304
+ call.turnId !== frame.turnId ||
305
+ call.iterationId !== frame.iterationId ||
306
+ call.toolCallNumber !== index + 1
307
+ ) {
308
+ fail(
309
+ "tool_message_identity_mismatch",
310
+ `Tool call ${call.toolCallId} has invalid frame identity or number.`,
311
+ { frameId: frame.frameId, toolCallId: call.toolCallId },
312
+ );
313
+ }
314
+ if (input.seenToolCallIds.has(call.toolCallId)) {
315
+ fail("duplicate_tool_call_id", `Duplicate tool call ID ${call.toolCallId}.`, {
316
+ frameId: frame.frameId,
317
+ toolCallId: call.toolCallId,
318
+ });
319
+ }
320
+ input.seenToolCallIds.add(call.toolCallId);
321
+ if (
322
+ call.providerToolCallId.trim() === "" ||
323
+ providerIds.has(call.providerToolCallId)
324
+ ) {
325
+ fail(
326
+ "duplicate_provider_tool_call_id",
327
+ `Provider tool call ID must be non-empty and unique in frame ${frame.frameId}.`,
328
+ { frameId: frame.frameId, toolCallId: call.toolCallId },
329
+ );
330
+ }
331
+ providerIds.add(call.providerToolCallId);
332
+ }
333
+
334
+ const toolMessages = frameMessages.slice(1);
335
+ if (toolMessages.length > assistant.toolCalls.length) {
336
+ const extra = requireItem(toolMessages, assistant.toolCalls.length, "tool message");
337
+ fail(
338
+ "unexpected_tool_message",
339
+ `Tool exchange ${frame.frameId} contains an unexpected tool message.`,
340
+ identityForMessage(extra),
341
+ );
342
+ }
343
+ if (frame.state === "closed" && toolMessages.length !== assistant.toolCalls.length) {
344
+ const missing = assistant.toolCalls[toolMessages.length];
345
+ fail(
346
+ "missing_tool_message",
347
+ `Tool exchange ${frame.frameId} is missing a tool message.`,
348
+ { frameId: frame.frameId, toolCallId: missing?.toolCallId },
349
+ );
350
+ }
351
+
352
+ for (let index = 0; index < toolMessages.length; index += 1) {
353
+ const message = requireItem(toolMessages, index, "tool message");
354
+ const call = requireItem(assistant.toolCalls, index, "tool call");
355
+ if (message.role !== "tool") {
356
+ fail(
357
+ "unexpected_tool_message",
358
+ `Expected a tool message at ordinal ${message.ordinal}.`,
359
+ identityForMessage(message),
360
+ );
361
+ }
362
+ if (message.toolCallId !== call.toolCallId) {
363
+ fail(
364
+ "tool_message_order_mismatch",
365
+ `Tool message at ordinal ${message.ordinal} does not match call order.`,
366
+ { ...identityForMessage(message), toolCallId: call.toolCallId },
367
+ );
368
+ }
369
+ if (
370
+ message.providerToolCallId !== call.providerToolCallId ||
371
+ message.name !== call.name ||
372
+ message.turnId !== frame.turnId ||
373
+ message.iterationId !== frame.iterationId
374
+ ) {
375
+ fail(
376
+ "tool_message_identity_mismatch",
377
+ `Tool message ${message.messageId} does not match call ${call.toolCallId}.`,
378
+ { ...identityForMessage(message), toolCallId: call.toolCallId },
379
+ );
380
+ }
381
+
382
+ const results = input.resultsByCallId.get(call.toolCallId) ?? [];
383
+ if (results.length === 0) {
384
+ fail(
385
+ "missing_tool_result",
386
+ `Tool call ${call.toolCallId} has no result record.`,
387
+ { ...identityForMessage(message), toolCallId: call.toolCallId },
388
+ );
389
+ }
390
+ if (results.length !== 1) {
391
+ fail(
392
+ "tool_result_mismatch",
393
+ `Tool call ${call.toolCallId} has ${results.length} result records.`,
394
+ { ...identityForMessage(message), toolCallId: call.toolCallId },
395
+ );
396
+ }
397
+ const result = requireItem(results, 0, "tool result");
398
+ if (
399
+ result.sessionId !== frame.sessionId ||
400
+ result.frameId !== frame.frameId ||
401
+ result.toolMessageId !== message.messageId ||
402
+ result.observationSha256 !== contentHash(message.content)
403
+ ) {
404
+ fail(
405
+ "tool_result_mismatch",
406
+ `Tool result for ${call.toolCallId} does not match its message.`,
407
+ { ...identityForMessage(message), toolCallId: call.toolCallId },
408
+ );
409
+ }
410
+ if (
411
+ input.fullIntegrity &&
412
+ result.completion.kind === "returned" &&
413
+ result.completion.rawSha256 !== rawResultHash(result.completion.raw)
414
+ ) {
415
+ fail(
416
+ "raw_hash_mismatch",
417
+ `Raw result hash does not match tool call ${call.toolCallId}.`,
418
+ { ...identityForMessage(message), toolCallId: call.toolCallId },
419
+ );
420
+ }
421
+ input.usedResultCallIds.add(call.toolCallId);
422
+ }
423
+ }
424
+
425
+ function groupResults(
426
+ results: readonly ToolResultRecord[],
427
+ ): Map<string, ToolResultRecord[]> {
428
+ const grouped = new Map<string, ToolResultRecord[]>();
429
+ for (const result of results) {
430
+ const group = grouped.get(result.toolCallId) ?? [];
431
+ group.push(result);
432
+ grouped.set(result.toolCallId, group);
433
+ }
434
+ return grouped;
435
+ }
436
+
437
+ function identityForMessage(message: CanonicalMessageRecord): {
438
+ frameId: ProtocolFrameId;
439
+ messageId: MessageId;
440
+ ordinal: number;
441
+ } {
442
+ return {
443
+ frameId: message.frameId,
444
+ messageId: message.messageId,
445
+ ordinal: message.ordinal,
446
+ };
447
+ }
448
+
449
+ function requireItem<T>(items: readonly T[], index: number, name: string): T {
450
+ const item = items[index];
451
+ if (item === undefined) {
452
+ throw new Error(`Missing ${name} at index ${index}.`);
453
+ }
454
+ return item;
455
+ }
456
+
457
+ function fail(
458
+ code: ContextProtocolErrorCode,
459
+ message: string,
460
+ identity?: ConstructorParameters<typeof ContextProtocolError>[2],
461
+ ): never {
462
+ throw new ContextProtocolError(code, message, identity);
463
+ }