@jasonews/agent-squad-gateway 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +200 -0
  3. package/SECURITY.md +44 -0
  4. package/dist/bin/agent-squad-gateway.js +55 -0
  5. package/dist/bin/agent-squad-gateway.js.map +1 -0
  6. package/dist/config/config.js +124 -0
  7. package/dist/config/config.js.map +1 -0
  8. package/dist/config/paths.js +16 -0
  9. package/dist/config/paths.js.map +1 -0
  10. package/dist/control-plane/clients.js +77 -0
  11. package/dist/control-plane/clients.js.map +1 -0
  12. package/dist/control-plane/core-connection.js +54 -0
  13. package/dist/control-plane/core-connection.js.map +1 -0
  14. package/dist/control-plane/credentials.js +134 -0
  15. package/dist/control-plane/credentials.js.map +1 -0
  16. package/dist/control-plane/db.js +33 -0
  17. package/dist/control-plane/db.js.map +1 -0
  18. package/dist/control-plane/extensions.js +59 -0
  19. package/dist/control-plane/extensions.js.map +1 -0
  20. package/dist/control-plane/grants.js +107 -0
  21. package/dist/control-plane/grants.js.map +1 -0
  22. package/dist/control-plane/idempotency.js +132 -0
  23. package/dist/control-plane/idempotency.js.map +1 -0
  24. package/dist/control-plane/migrations.js +133 -0
  25. package/dist/control-plane/migrations.js.map +1 -0
  26. package/dist/control-plane/response-sessions.js +359 -0
  27. package/dist/control-plane/response-sessions.js.map +1 -0
  28. package/dist/control-plane/retention.js +138 -0
  29. package/dist/control-plane/retention.js.map +1 -0
  30. package/dist/control-plane/runs.js +156 -0
  31. package/dist/control-plane/runs.js.map +1 -0
  32. package/dist/control-plane/targets.js +449 -0
  33. package/dist/control-plane/targets.js.map +1 -0
  34. package/dist/control-plane/types.js +2 -0
  35. package/dist/control-plane/types.js.map +1 -0
  36. package/dist/core-client/client.js +275 -0
  37. package/dist/core-client/client.js.map +1 -0
  38. package/dist/core-client/event-proxy.js +105 -0
  39. package/dist/core-client/event-proxy.js.map +1 -0
  40. package/dist/core-client/types.js +2 -0
  41. package/dist/core-client/types.js.map +1 -0
  42. package/dist/extensions/contract.js +2 -0
  43. package/dist/extensions/contract.js.map +1 -0
  44. package/dist/extensions/openai/auth.js +16 -0
  45. package/dist/extensions/openai/auth.js.map +1 -0
  46. package/dist/extensions/openai/chat.js +403 -0
  47. package/dist/extensions/openai/chat.js.map +1 -0
  48. package/dist/extensions/openai/errors.js +79 -0
  49. package/dist/extensions/openai/errors.js.map +1 -0
  50. package/dist/extensions/openai/image-input.js +79 -0
  51. package/dist/extensions/openai/image-input.js.map +1 -0
  52. package/dist/extensions/openai/models.js +40 -0
  53. package/dist/extensions/openai/models.js.map +1 -0
  54. package/dist/extensions/openai/responses.js +731 -0
  55. package/dist/extensions/openai/responses.js.map +1 -0
  56. package/dist/extensions/openai/routes.js +81 -0
  57. package/dist/extensions/openai/routes.js.map +1 -0
  58. package/dist/extensions/openai/run-attempt.js +96 -0
  59. package/dist/extensions/openai/run-attempt.js.map +1 -0
  60. package/dist/extensions/openai/schemas.js +176 -0
  61. package/dist/extensions/openai/schemas.js.map +1 -0
  62. package/dist/extensions/openai/sse.js +421 -0
  63. package/dist/extensions/openai/sse.js.map +1 -0
  64. package/dist/extensions/openai/tools.js +727 -0
  65. package/dist/extensions/openai/tools.js.map +1 -0
  66. package/dist/extensions/registry.js +30 -0
  67. package/dist/extensions/registry.js.map +1 -0
  68. package/dist/lifecycle/daemon.js +437 -0
  69. package/dist/lifecycle/daemon.js.map +1 -0
  70. package/dist/lifecycle/pidfile.js +34 -0
  71. package/dist/lifecycle/pidfile.js.map +1 -0
  72. package/dist/provider-runtime/antigravity/adapter.js +398 -0
  73. package/dist/provider-runtime/antigravity/adapter.js.map +1 -0
  74. package/dist/provider-runtime/antigravity/conversation.js +31 -0
  75. package/dist/provider-runtime/antigravity/conversation.js.map +1 -0
  76. package/dist/provider-runtime/capability-service.js +191 -0
  77. package/dist/provider-runtime/capability-service.js.map +1 -0
  78. package/dist/provider-runtime/claude/adapter.js +397 -0
  79. package/dist/provider-runtime/claude/adapter.js.map +1 -0
  80. package/dist/provider-runtime/claude/protocol.js +143 -0
  81. package/dist/provider-runtime/claude/protocol.js.map +1 -0
  82. package/dist/provider-runtime/codex/adapter.js +440 -0
  83. package/dist/provider-runtime/codex/adapter.js.map +1 -0
  84. package/dist/provider-runtime/codex/json-rpc-client.js +182 -0
  85. package/dist/provider-runtime/codex/json-rpc-client.js.map +1 -0
  86. package/dist/provider-runtime/codex/protocol.js +128 -0
  87. package/dist/provider-runtime/codex/protocol.js.map +1 -0
  88. package/dist/provider-runtime/command-discovery.js +106 -0
  89. package/dist/provider-runtime/command-discovery.js.map +1 -0
  90. package/dist/provider-runtime/cursor/adapter.js +427 -0
  91. package/dist/provider-runtime/cursor/adapter.js.map +1 -0
  92. package/dist/provider-runtime/cursor/protocol.js +81 -0
  93. package/dist/provider-runtime/cursor/protocol.js.map +1 -0
  94. package/dist/provider-runtime/fake/adapter.js +138 -0
  95. package/dist/provider-runtime/fake/adapter.js.map +1 -0
  96. package/dist/provider-runtime/image-assets.js +409 -0
  97. package/dist/provider-runtime/image-assets.js.map +1 -0
  98. package/dist/provider-runtime/image-support.js +5 -0
  99. package/dist/provider-runtime/image-support.js.map +1 -0
  100. package/dist/provider-runtime/invocation-service.js +503 -0
  101. package/dist/provider-runtime/invocation-service.js.map +1 -0
  102. package/dist/provider-runtime/kimi/adapter.js +657 -0
  103. package/dist/provider-runtime/kimi/adapter.js.map +1 -0
  104. package/dist/provider-runtime/opencode/adapter.js +610 -0
  105. package/dist/provider-runtime/opencode/adapter.js.map +1 -0
  106. package/dist/provider-runtime/opencode/server.js +46 -0
  107. package/dist/provider-runtime/opencode/server.js.map +1 -0
  108. package/dist/provider-runtime/process/line-reader.js +49 -0
  109. package/dist/provider-runtime/process/line-reader.js.map +1 -0
  110. package/dist/provider-runtime/process/managed-process.js +151 -0
  111. package/dist/provider-runtime/process/managed-process.js.map +1 -0
  112. package/dist/provider-runtime/provider-input.js +77 -0
  113. package/dist/provider-runtime/provider-input.js.map +1 -0
  114. package/dist/provider-runtime/register-providers.js +26 -0
  115. package/dist/provider-runtime/register-providers.js.map +1 -0
  116. package/dist/provider-runtime/registry.js +35 -0
  117. package/dist/provider-runtime/registry.js.map +1 -0
  118. package/dist/provider-runtime/replay-buffer.js +168 -0
  119. package/dist/provider-runtime/replay-buffer.js.map +1 -0
  120. package/dist/provider-runtime/scheduler.js +155 -0
  121. package/dist/provider-runtime/scheduler.js.map +1 -0
  122. package/dist/provider-runtime/types.js +2 -0
  123. package/dist/provider-runtime/types.js.map +1 -0
  124. package/dist/provider-runtime/workspaces.js +814 -0
  125. package/dist/provider-runtime/workspaces.js.map +1 -0
  126. package/dist/security/admin-auth.js +109 -0
  127. package/dist/security/admin-auth.js.map +1 -0
  128. package/dist/security/crypto.js +52 -0
  129. package/dist/security/crypto.js.map +1 -0
  130. package/dist/security/secret-files.js +33 -0
  131. package/dist/security/secret-files.js.map +1 -0
  132. package/dist/server/admin-routes.js +610 -0
  133. package/dist/server/admin-routes.js.map +1 -0
  134. package/dist/server/app.js +178 -0
  135. package/dist/server/app.js.map +1 -0
  136. package/dist/server/auth-hooks.js +43 -0
  137. package/dist/server/auth-hooks.js.map +1 -0
  138. package/dist/server/core-routes.js +127 -0
  139. package/dist/server/core-routes.js.map +1 -0
  140. package/dist/server/errors.js +19 -0
  141. package/dist/server/errors.js.map +1 -0
  142. package/dist/server/ui-routes.js +77 -0
  143. package/dist/server/ui-routes.js.map +1 -0
  144. package/dist/web/assets/index-BhqNoPpE.js +206 -0
  145. package/dist/web/assets/index-BhqNoPpE.js.map +1 -0
  146. package/dist/web/assets/index-C5nnaBfZ.css +1 -0
  147. package/dist/web/index.html +14 -0
  148. package/package.json +74 -0
  149. package/translations/README.zh-CN.md +175 -0
@@ -0,0 +1,727 @@
1
+ import Ajv2020 from 'ajv/dist/2020.js';
2
+ import { randomUUID } from 'node:crypto';
3
+ const MAX_FUNCTIONS = 64;
4
+ const MAX_SCHEMA_BYTES = 64 * 1024;
5
+ const MAX_SCHEMA_DEPTH = 16;
6
+ const MAX_TOOL_ENVELOPE_BYTES = 1024 * 1024;
7
+ const TOOL_METADATA = Symbol('toolMetadata');
8
+ export class ToolInputError extends Error {
9
+ constructor(message = 'invalid_tools') {
10
+ super(message);
11
+ this.name = 'ToolInputError';
12
+ }
13
+ }
14
+ export class AdapterProtocolError extends Error {
15
+ code = 'adapter_protocol_error';
16
+ constructor() {
17
+ super('adapter_protocol_error');
18
+ this.name = 'AdapterProtocolError';
19
+ }
20
+ }
21
+ function failInput(message) {
22
+ throw new ToolInputError(message);
23
+ }
24
+ function isObject(value) {
25
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
26
+ }
27
+ function schemaObject() {
28
+ return Object.create(null);
29
+ }
30
+ function defineSchemaProperty(target, key, value) {
31
+ Object.defineProperty(target, key, {
32
+ value,
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ });
37
+ }
38
+ function sanitizeSchema(value, depth, ancestors) {
39
+ if (depth > MAX_SCHEMA_DEPTH)
40
+ failInput('tool_schema_too_deep');
41
+ if (value === null || typeof value === 'string' || typeof value === 'boolean')
42
+ return value;
43
+ if (typeof value === 'number') {
44
+ if (!Number.isFinite(value))
45
+ failInput('invalid_tool_schema');
46
+ return value;
47
+ }
48
+ if (typeof value !== 'object')
49
+ failInput('invalid_tool_schema');
50
+ if (!Array.isArray(value)) {
51
+ const prototype = Object.getPrototypeOf(value);
52
+ if (prototype !== Object.prototype && prototype !== null)
53
+ failInput('invalid_tool_schema');
54
+ }
55
+ if (ancestors.has(value))
56
+ failInput('tool_schema_cycle');
57
+ ancestors.add(value);
58
+ try {
59
+ if (Array.isArray(value)) {
60
+ return value.map((entry) => sanitizeSchema(entry, depth + 1, ancestors));
61
+ }
62
+ const result = schemaObject();
63
+ for (const [key, entry] of Object.entries(value)) {
64
+ if (key === '$schema')
65
+ continue;
66
+ if (key === '$ref' && (typeof entry !== 'string' || !entry.startsWith('#'))) {
67
+ failInput('external_tool_schema_ref');
68
+ }
69
+ defineSchemaProperty(result, key, sanitizeSchema(entry, depth + 1, ancestors));
70
+ }
71
+ return result;
72
+ }
73
+ finally {
74
+ ancestors.delete(value);
75
+ }
76
+ }
77
+ function canonicalJson(value) {
78
+ if (value === null || typeof value !== 'object')
79
+ return JSON.stringify(value);
80
+ if (Array.isArray(value))
81
+ return `[${value.map(canonicalJson).join(',')}]`;
82
+ return `{${Object.keys(value).sort().map((key) => (`${JSON.stringify(key)}:${canonicalJson(value[key])}`)).join(',')}}`;
83
+ }
84
+ function parseTools(tools) {
85
+ if (!Array.isArray(tools))
86
+ failInput();
87
+ if (tools.length > MAX_FUNCTIONS)
88
+ failInput('too_many_tools');
89
+ const names = new Set();
90
+ return tools.map((value) => {
91
+ if (!isObject(value) || value.type !== 'function' || !isObject(value.function))
92
+ failInput();
93
+ const definition = value.function;
94
+ if (typeof definition.name !== 'string' || definition.name.length === 0)
95
+ failInput();
96
+ if (names.has(definition.name))
97
+ failInput('duplicate_tool_name');
98
+ names.add(definition.name);
99
+ if (definition.description !== undefined && typeof definition.description !== 'string')
100
+ failInput();
101
+ if (definition.parameters !== undefined && !isObject(definition.parameters))
102
+ failInput();
103
+ const parameters = sanitizeSchema(definition.parameters ?? { type: 'object', properties: {} }, 1, new Set());
104
+ if (!isObject(parameters))
105
+ failInput();
106
+ return {
107
+ tool: {
108
+ type: 'function',
109
+ function: {
110
+ name: definition.name,
111
+ ...(definition.description === undefined ? {} : { description: definition.description }),
112
+ parameters,
113
+ },
114
+ },
115
+ parameters,
116
+ };
117
+ });
118
+ }
119
+ function parseChoice(choice) {
120
+ if (choice === undefined)
121
+ return 'auto';
122
+ if (choice === 'auto' || choice === 'none' || choice === 'required')
123
+ return choice;
124
+ if (isObject(choice)
125
+ && choice.type === 'function'
126
+ && isObject(choice.function)
127
+ && typeof choice.function.name === 'string'
128
+ && Object.keys(choice).length === 2
129
+ && Object.keys(choice.function).length === 1) {
130
+ return { type: 'function', function: { name: choice.function.name } };
131
+ }
132
+ return failInput('invalid_tool_choice');
133
+ }
134
+ function assistantBranch() {
135
+ return {
136
+ type: 'object',
137
+ additionalProperties: false,
138
+ properties: {
139
+ type: { const: 'assistant_text' },
140
+ content: { type: 'string' },
141
+ },
142
+ required: ['type', 'content'],
143
+ };
144
+ }
145
+ function functionBranch(tool, parameters) {
146
+ return {
147
+ type: 'object',
148
+ additionalProperties: false,
149
+ ...(tool.function.description === undefined
150
+ ? {}
151
+ : { description: tool.function.description }),
152
+ properties: {
153
+ name: { const: tool.function.name },
154
+ arguments: parameters,
155
+ },
156
+ required: ['name', 'arguments'],
157
+ };
158
+ }
159
+ function rebaseLocalRefs(value, base) {
160
+ if (Array.isArray(value))
161
+ return value.map((entry) => rebaseLocalRefs(entry, base));
162
+ if (!isObject(value))
163
+ return value;
164
+ const result = schemaObject();
165
+ for (const [key, entry] of Object.entries(value)) {
166
+ defineSchemaProperty(result, key, key === '$ref' && typeof entry === 'string'
167
+ ? `${base}${entry.slice(1)}`
168
+ : rebaseLocalRefs(entry, base));
169
+ }
170
+ return result;
171
+ }
172
+ function ajvRuntimeSchema(value) {
173
+ if (Array.isArray(value))
174
+ return value.map(ajvRuntimeSchema);
175
+ if (!isObject(value))
176
+ return value;
177
+ const result = schemaObject();
178
+ for (const [key, entry] of Object.entries(value)) {
179
+ defineSchemaProperty(result, key, ajvRuntimeSchema(entry));
180
+ }
181
+ const properties = result.properties;
182
+ if (isObject(properties) && Object.hasOwn(properties, '__proto__')) {
183
+ const patterns = schemaObject();
184
+ defineSchemaProperty(patterns, '^__proto__$', properties.__proto__);
185
+ const guard = schemaObject();
186
+ defineSchemaProperty(guard, 'patternProperties', patterns);
187
+ const allOf = result.allOf;
188
+ if (allOf === undefined)
189
+ defineSchemaProperty(result, 'allOf', [guard]);
190
+ else if (Array.isArray(allOf))
191
+ allOf.push(guard);
192
+ }
193
+ return result;
194
+ }
195
+ function toolCallsBranch(functions, rootBranchIndex) {
196
+ return {
197
+ type: 'object',
198
+ additionalProperties: false,
199
+ properties: {
200
+ type: { const: 'tool_calls' },
201
+ tool_calls: {
202
+ type: 'array',
203
+ minItems: 1,
204
+ items: {
205
+ oneOf: functions.map(({ tool, parameters }, functionIndex) => {
206
+ const base = `#/oneOf/${rootBranchIndex}/properties/tool_calls/items/oneOf/${functionIndex}/properties/arguments`;
207
+ return functionBranch(tool, rebaseLocalRefs(parameters, base));
208
+ }),
209
+ },
210
+ },
211
+ },
212
+ required: ['type', 'tool_calls'],
213
+ };
214
+ }
215
+ export function buildToolOutputSchema(tools, choice) {
216
+ const parsedChoice = parseChoice(choice);
217
+ const parsedTools = parseTools(tools);
218
+ if (parsedChoice === 'none')
219
+ return null;
220
+ if (parsedTools.length === 0) {
221
+ if (parsedChoice === 'auto')
222
+ return null;
223
+ failInput('tool_choice_requires_tools');
224
+ }
225
+ let allowed = parsedTools;
226
+ let mode = parsedChoice === 'auto' ? 'auto' : 'required';
227
+ if (typeof parsedChoice === 'object') {
228
+ allowed = parsedTools.filter(({ tool }) => tool.function.name === parsedChoice.function.name);
229
+ if (allowed.length === 0)
230
+ failInput('unknown_tool_choice');
231
+ mode = 'required';
232
+ }
233
+ const schema = {
234
+ oneOf: mode === 'auto'
235
+ ? [assistantBranch(), toolCallsBranch(allowed, 1)]
236
+ : [toolCallsBranch(allowed, 0)],
237
+ };
238
+ if (Buffer.byteLength(canonicalJson(schema), 'utf8') > MAX_SCHEMA_BYTES) {
239
+ failInput('tool_schema_too_large');
240
+ }
241
+ const ajv = new Ajv2020({
242
+ allErrors: false,
243
+ strict: false,
244
+ validateSchema: true,
245
+ ownProperties: true,
246
+ });
247
+ const functions = new Map();
248
+ try {
249
+ for (const { tool, parameters } of allowed) {
250
+ functions.set(tool.function.name, {
251
+ name: tool.function.name,
252
+ validate: ajv.compile(ajvRuntimeSchema(parameters)),
253
+ });
254
+ }
255
+ }
256
+ catch {
257
+ failInput('invalid_tool_schema');
258
+ }
259
+ Object.defineProperty(schema, TOOL_METADATA, {
260
+ value: { mode, functions },
261
+ enumerable: false,
262
+ configurable: false,
263
+ writable: false,
264
+ });
265
+ return schema;
266
+ }
267
+ function metadataFor(schema) {
268
+ const metadata = schema[TOOL_METADATA];
269
+ if (!metadata)
270
+ throw new ToolInputError('unprepared_tool_schema');
271
+ return metadata;
272
+ }
273
+ function whitespace(char) {
274
+ return char === ' ' || char === '\n' || char === '\r' || char === '\t';
275
+ }
276
+ export class StructuredEnvelopeDecoder {
277
+ metadata;
278
+ state = 'start';
279
+ token = '';
280
+ raw = '';
281
+ rawBytes = 0;
282
+ branch;
283
+ content = '';
284
+ escaped = false;
285
+ unicode;
286
+ pendingHighSurrogate;
287
+ finished = false;
288
+ constructor(schema) {
289
+ this.metadata = metadataFor(schema);
290
+ }
291
+ push(fragment) {
292
+ if (this.finished)
293
+ throw new AdapterProtocolError();
294
+ let emitted = '';
295
+ for (const char of fragment) {
296
+ if (this.branch === 'tool_calls')
297
+ this.appendRaw(char);
298
+ else if (this.branch === undefined)
299
+ this.appendRaw(char);
300
+ emitted += this.consume(char);
301
+ }
302
+ return emitted;
303
+ }
304
+ finish() {
305
+ if (this.finished)
306
+ throw new AdapterProtocolError();
307
+ this.finished = true;
308
+ if (this.branch === 'assistant_text') {
309
+ if (this.state !== 'after_object' || this.escaped || this.unicode !== undefined || this.pendingHighSurrogate !== undefined) {
310
+ throw new AdapterProtocolError();
311
+ }
312
+ return { type: 'assistant_text', content: this.content };
313
+ }
314
+ if (this.branch !== 'tool_calls')
315
+ throw new AdapterProtocolError();
316
+ let parsed;
317
+ try {
318
+ parsed = JSON.parse(this.raw);
319
+ }
320
+ catch {
321
+ throw new AdapterProtocolError();
322
+ }
323
+ if (!isObject(parsed) || Object.keys(parsed).length !== 2 || parsed.type !== 'tool_calls') {
324
+ throw new AdapterProtocolError();
325
+ }
326
+ if (!Array.isArray(parsed.tool_calls) || parsed.tool_calls.length === 0)
327
+ throw new AdapterProtocolError();
328
+ const toolCalls = parsed.tool_calls.map((call) => {
329
+ if (!isObject(call) || Object.keys(call).length !== 2)
330
+ throw new AdapterProtocolError();
331
+ if (typeof call.name !== 'string' || !isObject(call.arguments))
332
+ throw new AdapterProtocolError();
333
+ const runtime = this.metadata.functions.get(call.name);
334
+ if (!runtime || !runtime.validate(call.arguments))
335
+ throw new AdapterProtocolError();
336
+ return { name: call.name, arguments: call.arguments };
337
+ });
338
+ return { type: 'tool_calls', toolCalls };
339
+ }
340
+ appendRaw(char) {
341
+ this.raw += char;
342
+ this.rawBytes += Buffer.byteLength(char, 'utf8');
343
+ if (this.rawBytes > MAX_TOOL_ENVELOPE_BYTES)
344
+ throw new AdapterProtocolError();
345
+ }
346
+ consume(char) {
347
+ switch (this.state) {
348
+ case 'start':
349
+ if (whitespace(char))
350
+ return '';
351
+ if (char !== '{')
352
+ throw new AdapterProtocolError();
353
+ this.state = 'first_key_start';
354
+ return '';
355
+ case 'first_key_start':
356
+ if (whitespace(char))
357
+ return '';
358
+ if (char !== '"')
359
+ throw new AdapterProtocolError();
360
+ this.token = '';
361
+ this.state = 'first_key';
362
+ return '';
363
+ case 'first_key':
364
+ if (char === '"') {
365
+ if (this.token !== 'type')
366
+ throw new AdapterProtocolError();
367
+ this.state = 'after_first_key';
368
+ }
369
+ else {
370
+ if (char === '\\' || char.charCodeAt(0) < 0x20)
371
+ throw new AdapterProtocolError();
372
+ this.token += char;
373
+ }
374
+ return '';
375
+ case 'after_first_key':
376
+ if (whitespace(char))
377
+ return '';
378
+ if (char !== ':')
379
+ throw new AdapterProtocolError();
380
+ this.state = 'before_type_value';
381
+ return '';
382
+ case 'before_type_value':
383
+ if (whitespace(char))
384
+ return '';
385
+ if (char !== '"')
386
+ throw new AdapterProtocolError();
387
+ this.token = '';
388
+ this.state = 'type_value';
389
+ return '';
390
+ case 'type_value':
391
+ if (char === '"') {
392
+ if (this.token !== 'assistant_text' && this.token !== 'tool_calls')
393
+ throw new AdapterProtocolError();
394
+ if (this.token === 'assistant_text' && this.metadata.mode !== 'auto')
395
+ throw new AdapterProtocolError();
396
+ this.branch = this.token;
397
+ this.state = 'after_type_value';
398
+ }
399
+ else {
400
+ if (char === '\\' || char.charCodeAt(0) < 0x20)
401
+ throw new AdapterProtocolError();
402
+ this.token += char;
403
+ }
404
+ return '';
405
+ case 'after_type_value':
406
+ if (this.branch === 'tool_calls')
407
+ return '';
408
+ if (whitespace(char))
409
+ return '';
410
+ if (char !== ',')
411
+ throw new AdapterProtocolError();
412
+ this.state = 'content_key_start';
413
+ return '';
414
+ case 'content_key_start':
415
+ if (whitespace(char))
416
+ return '';
417
+ if (char !== '"')
418
+ throw new AdapterProtocolError();
419
+ this.token = '';
420
+ this.state = 'content_key';
421
+ return '';
422
+ case 'content_key':
423
+ if (char === '"') {
424
+ if (this.token !== 'content')
425
+ throw new AdapterProtocolError();
426
+ this.state = 'after_content_key';
427
+ }
428
+ else {
429
+ if (char === '\\' || char.charCodeAt(0) < 0x20)
430
+ throw new AdapterProtocolError();
431
+ this.token += char;
432
+ }
433
+ return '';
434
+ case 'after_content_key':
435
+ if (whitespace(char))
436
+ return '';
437
+ if (char !== ':')
438
+ throw new AdapterProtocolError();
439
+ this.state = 'before_content_value';
440
+ return '';
441
+ case 'before_content_value':
442
+ if (whitespace(char))
443
+ return '';
444
+ if (char !== '"')
445
+ throw new AdapterProtocolError();
446
+ this.state = 'content_value';
447
+ return '';
448
+ case 'content_value':
449
+ return this.consumeContent(char);
450
+ case 'after_content_value':
451
+ if (whitespace(char))
452
+ return '';
453
+ if (char !== '}')
454
+ throw new AdapterProtocolError();
455
+ this.state = 'after_object';
456
+ return '';
457
+ case 'after_object':
458
+ if (!whitespace(char))
459
+ throw new AdapterProtocolError();
460
+ return '';
461
+ }
462
+ }
463
+ consumeContent(char) {
464
+ if (this.unicode !== undefined) {
465
+ if (!this.isHex(char))
466
+ throw new AdapterProtocolError();
467
+ this.unicode += char;
468
+ if (this.unicode.length < 4)
469
+ return '';
470
+ const code = Number.parseInt(this.unicode, 16);
471
+ this.unicode = undefined;
472
+ this.escaped = false;
473
+ return this.emitCodeUnit(code);
474
+ }
475
+ if (this.escaped) {
476
+ if (char === 'u') {
477
+ this.unicode = '';
478
+ return '';
479
+ }
480
+ this.escaped = false;
481
+ const escaped = {
482
+ '"': '"', '\\': '\\', '/': '/', b: '\b', f: '\f', n: '\n', r: '\r', t: '\t',
483
+ };
484
+ const decoded = escaped[char];
485
+ if (decoded === undefined)
486
+ throw new AdapterProtocolError();
487
+ return this.emitText(decoded);
488
+ }
489
+ if (char === '\\') {
490
+ this.escaped = true;
491
+ return '';
492
+ }
493
+ if (char === '"') {
494
+ if (this.pendingHighSurrogate !== undefined)
495
+ throw new AdapterProtocolError();
496
+ this.state = 'after_content_value';
497
+ return '';
498
+ }
499
+ if (char.charCodeAt(0) < 0x20)
500
+ throw new AdapterProtocolError();
501
+ if (char.length === 1) {
502
+ const code = char.charCodeAt(0);
503
+ if (code >= 0xd800 && code <= 0xdfff)
504
+ return this.emitCodeUnit(code);
505
+ }
506
+ return this.emitText(char);
507
+ }
508
+ emitCodeUnit(code) {
509
+ if (code >= 0xd800 && code <= 0xdbff) {
510
+ if (this.pendingHighSurrogate !== undefined)
511
+ throw new AdapterProtocolError();
512
+ this.pendingHighSurrogate = code;
513
+ return '';
514
+ }
515
+ if (code >= 0xdc00 && code <= 0xdfff) {
516
+ if (this.pendingHighSurrogate === undefined)
517
+ throw new AdapterProtocolError();
518
+ const text = String.fromCharCode(this.pendingHighSurrogate, code);
519
+ this.pendingHighSurrogate = undefined;
520
+ return this.emitText(text);
521
+ }
522
+ if (this.pendingHighSurrogate !== undefined)
523
+ throw new AdapterProtocolError();
524
+ return this.emitText(String.fromCharCode(code));
525
+ }
526
+ isHex(char) {
527
+ const code = char.charCodeAt(0);
528
+ return (code >= 0x30 && code <= 0x39)
529
+ || (code >= 0x41 && code <= 0x46)
530
+ || (code >= 0x61 && code <= 0x66);
531
+ }
532
+ emitText(text) {
533
+ if (this.pendingHighSurrogate !== undefined)
534
+ throw new AdapterProtocolError();
535
+ this.content += text;
536
+ return text;
537
+ }
538
+ }
539
+ export function assignGatewayCallIds(calls) {
540
+ return calls.map((call) => ({ ...call, id: `call_${randomUUID()}` }));
541
+ }
542
+ export function normalizeChatToolRoundTrip(messages) {
543
+ if (!Array.isArray(messages))
544
+ failInput('invalid_messages');
545
+ const input = [];
546
+ const seenCallIds = new Set();
547
+ let pending = new Set();
548
+ let seenResults = new Set();
549
+ for (const message of messages) {
550
+ if (!isObject(message) || typeof message.role !== 'string')
551
+ failInput('invalid_message');
552
+ if (message.role === 'tool') {
553
+ if (typeof message.tool_call_id !== 'string'
554
+ || typeof message.content !== 'string'
555
+ || !pending.has(message.tool_call_id)
556
+ || seenResults.has(message.tool_call_id))
557
+ failInput('invalid_tool_result');
558
+ seenResults.add(message.tool_call_id);
559
+ input.push({ role: 'tool', toolCallId: message.tool_call_id, content: message.content });
560
+ continue;
561
+ }
562
+ if (pending.size !== seenResults.size)
563
+ failInput('incomplete_tool_results');
564
+ pending = new Set();
565
+ seenResults = new Set();
566
+ if (message.role === 'assistant' && Array.isArray(message.tool_calls)) {
567
+ if (message.tool_calls.length === 0 || (message.content !== undefined && message.content !== null && typeof message.content !== 'string')) {
568
+ failInput('invalid_tool_calls');
569
+ }
570
+ const toolCalls = message.tool_calls.map((call) => {
571
+ if (!isObject(call) || call.type !== 'function' || !isObject(call.function))
572
+ failInput('invalid_tool_call');
573
+ if (typeof call.id !== 'string' || seenCallIds.has(call.id))
574
+ failInput('duplicate_tool_call_id');
575
+ if (typeof call.function.name !== 'string' || typeof call.function.arguments !== 'string')
576
+ failInput('invalid_tool_call');
577
+ let args;
578
+ try {
579
+ args = JSON.parse(call.function.arguments);
580
+ }
581
+ catch {
582
+ failInput('invalid_tool_arguments');
583
+ }
584
+ if (!isObject(args))
585
+ failInput('invalid_tool_arguments');
586
+ seenCallIds.add(call.id);
587
+ pending.add(call.id);
588
+ return { id: call.id, name: call.function.name, arguments: args };
589
+ });
590
+ input.push({ role: 'assistant', content: message.content ?? null, toolCalls });
591
+ continue;
592
+ }
593
+ if ((message.role !== 'system' && message.role !== 'user' && message.role !== 'assistant')
594
+ || typeof message.content !== 'string')
595
+ failInput('invalid_message');
596
+ input.push({ role: message.role, content: message.content });
597
+ }
598
+ if (pending.size !== seenResults.size)
599
+ failInput('incomplete_tool_results');
600
+ return input;
601
+ }
602
+ export class FunctionCallMetadataStore {
603
+ capacity;
604
+ entries = new Map();
605
+ constructor(capacity = 10_000) {
606
+ this.capacity = capacity;
607
+ if (!Number.isInteger(capacity) || capacity < 1)
608
+ throw new Error('invalid_metadata_capacity');
609
+ }
610
+ remember(responseId, callIds) {
611
+ if (responseId.length === 0)
612
+ failInput('invalid_call_metadata');
613
+ const ids = new Set(callIds);
614
+ if (ids.size !== callIds.length || [...ids].some((id) => id.length === 0)) {
615
+ failInput('invalid_call_metadata');
616
+ }
617
+ this.entries.delete(responseId);
618
+ this.entries.set(responseId, ids);
619
+ while (this.entries.size > this.capacity) {
620
+ const oldest = this.entries.keys().next().value;
621
+ if (oldest === undefined)
622
+ break;
623
+ this.entries.delete(oldest);
624
+ }
625
+ }
626
+ expected(responseId) {
627
+ const ids = this.entries.get(responseId);
628
+ if (!ids)
629
+ failInput('tool_validation_state_unavailable');
630
+ return new Set(ids);
631
+ }
632
+ find(responseId) {
633
+ const ids = this.entries.get(responseId);
634
+ return ids === undefined ? undefined : new Set(ids);
635
+ }
636
+ }
637
+ function parseArgumentObject(value) {
638
+ let parsed;
639
+ try {
640
+ parsed = JSON.parse(value);
641
+ }
642
+ catch {
643
+ failInput('invalid_tool_arguments');
644
+ }
645
+ if (!isObject(parsed))
646
+ failInput('invalid_tool_arguments');
647
+ return parsed;
648
+ }
649
+ export function normalizeResponsesToolRoundTrip(items, expectedResults) {
650
+ if (!Array.isArray(items) || items.length === 0)
651
+ failInput('invalid_response_input');
652
+ const input = [];
653
+ if (expectedResults !== undefined) {
654
+ const received = new Set();
655
+ for (const item of items) {
656
+ if (!isObject(item)
657
+ || item.type !== 'function_call_output'
658
+ || typeof item.call_id !== 'string'
659
+ || typeof item.output !== 'string'
660
+ || !expectedResults.has(item.call_id)
661
+ || received.has(item.call_id))
662
+ failInput('invalid_function_call_output');
663
+ received.add(item.call_id);
664
+ input.push({ role: 'tool', toolCallId: item.call_id, content: item.output });
665
+ }
666
+ if (received.size !== expectedResults.size)
667
+ failInput('incomplete_tool_results');
668
+ return input;
669
+ }
670
+ const seenCallIds = new Set();
671
+ let pending = new Set();
672
+ let results = new Set();
673
+ let activeCalls;
674
+ for (const item of items) {
675
+ if (!isObject(item))
676
+ failInput('invalid_response_input');
677
+ if (item.type === 'function_call') {
678
+ if (!activeCalls) {
679
+ if (pending.size !== results.size)
680
+ failInput('incomplete_tool_results');
681
+ if (results.size > 0) {
682
+ pending = new Set();
683
+ results = new Set();
684
+ }
685
+ activeCalls = [];
686
+ input.push({ role: 'assistant', content: null, toolCalls: activeCalls });
687
+ }
688
+ if (typeof item.call_id !== 'string'
689
+ || typeof item.name !== 'string'
690
+ || typeof item.arguments !== 'string'
691
+ || seenCallIds.has(item.call_id))
692
+ failInput('invalid_function_call');
693
+ const call = {
694
+ id: item.call_id,
695
+ name: item.name,
696
+ arguments: parseArgumentObject(item.arguments),
697
+ };
698
+ seenCallIds.add(item.call_id);
699
+ pending.add(item.call_id);
700
+ activeCalls.push(call);
701
+ continue;
702
+ }
703
+ activeCalls = undefined;
704
+ if (item.type === 'function_call_output') {
705
+ if (typeof item.call_id !== 'string'
706
+ || typeof item.output !== 'string'
707
+ || !pending.has(item.call_id)
708
+ || results.has(item.call_id))
709
+ failInput('invalid_function_call_output');
710
+ results.add(item.call_id);
711
+ input.push({ role: 'tool', toolCallId: item.call_id, content: item.output });
712
+ continue;
713
+ }
714
+ if (pending.size !== results.size)
715
+ failInput('incomplete_tool_results');
716
+ pending = new Set();
717
+ results = new Set();
718
+ if ((item.role !== 'system' && item.role !== 'user' && item.role !== 'assistant')
719
+ || typeof item.content !== 'string')
720
+ failInput('invalid_response_input');
721
+ input.push({ role: item.role, content: item.content });
722
+ }
723
+ if (pending.size !== results.size)
724
+ failInput('incomplete_tool_results');
725
+ return input;
726
+ }
727
+ //# sourceMappingURL=tools.js.map