@m8tes/sdk 0.1.0-alpha.1
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 +100 -0
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/dist/chunk-UFQQNUFE.js +1083 -0
- package/dist/chunk-UFQQNUFE.js.map +1 -0
- package/dist/fixtures.cjs +297 -0
- package/dist/fixtures.cjs.map +1 -0
- package/dist/fixtures.d.cts +81 -0
- package/dist/fixtures.d.ts +81 -0
- package/dist/fixtures.js +295 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/index.cjs +1783 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +937 -0
- package/dist/index.d.ts +937 -0
- package/dist/index.js +672 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/index.cjs +1109 -0
- package/dist/protocol/index.cjs.map +1 -0
- package/dist/protocol/index.d.cts +576 -0
- package/dist/protocol/index.d.ts +576 -0
- package/dist/protocol/index.js +3 -0
- package/dist/protocol/index.js.map +1 -0
- package/package.json +64 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1783 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
|
|
5
|
+
// src/protocol/events.ts
|
|
6
|
+
var PROTOCOL_VERSION = "m8tes.stream.v2";
|
|
7
|
+
var TERMINAL_EVENT_TYPES = [
|
|
8
|
+
"run-finish",
|
|
9
|
+
"run-error",
|
|
10
|
+
"run-cancelled"
|
|
11
|
+
];
|
|
12
|
+
function isTerminalEvent(event) {
|
|
13
|
+
return TERMINAL_EVENT_TYPES.includes(event.type);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/protocol/sse-parser.ts
|
|
17
|
+
function splitConcatenatedJson(payload) {
|
|
18
|
+
const out = [];
|
|
19
|
+
let depth = 0;
|
|
20
|
+
let inString = false;
|
|
21
|
+
let escaped = false;
|
|
22
|
+
let start = -1;
|
|
23
|
+
let lastEnd = 0;
|
|
24
|
+
for (let i = 0; i < payload.length; i++) {
|
|
25
|
+
const ch = payload.charAt(i);
|
|
26
|
+
if (start === -1) {
|
|
27
|
+
if (ch === "{" || ch === "[") {
|
|
28
|
+
start = i;
|
|
29
|
+
depth = 1;
|
|
30
|
+
inString = false;
|
|
31
|
+
escaped = false;
|
|
32
|
+
}
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (inString) {
|
|
36
|
+
if (escaped) escaped = false;
|
|
37
|
+
else if (ch === "\\") escaped = true;
|
|
38
|
+
else if (ch === '"') inString = false;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (ch === '"') {
|
|
42
|
+
inString = true;
|
|
43
|
+
} else if (ch === "{" || ch === "[") {
|
|
44
|
+
depth++;
|
|
45
|
+
} else if (ch === "}" || ch === "]") {
|
|
46
|
+
depth--;
|
|
47
|
+
if (depth === 0) {
|
|
48
|
+
out.push(payload.slice(start, i + 1));
|
|
49
|
+
start = -1;
|
|
50
|
+
lastEnd = i + 1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (start !== -1) {
|
|
55
|
+
out.push(payload.slice(start));
|
|
56
|
+
} else {
|
|
57
|
+
const tail = payload.slice(lastEnd).trim();
|
|
58
|
+
if (tail !== "") out.push(tail);
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
function frameDataPayload(frameText) {
|
|
63
|
+
const dataLines = [];
|
|
64
|
+
for (const rawLine of frameText.split("\n")) {
|
|
65
|
+
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
|
|
66
|
+
if (line === "" || line.charAt(0) === ":") continue;
|
|
67
|
+
if (line.startsWith("data:")) {
|
|
68
|
+
let value = line.slice(5);
|
|
69
|
+
if (value.charAt(0) === " ") value = value.slice(1);
|
|
70
|
+
dataLines.push(value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (dataLines.length === 0) return null;
|
|
74
|
+
return dataLines.join("\n");
|
|
75
|
+
}
|
|
76
|
+
function parsePayload(payload, onMalformed) {
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const candidate of splitConcatenatedJson(payload)) {
|
|
79
|
+
try {
|
|
80
|
+
const parsed = JSON.parse(candidate);
|
|
81
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
82
|
+
out.push(parsed);
|
|
83
|
+
} else {
|
|
84
|
+
onMalformed?.(candidate, new Error("frame is not a JSON object"));
|
|
85
|
+
}
|
|
86
|
+
} catch (err) {
|
|
87
|
+
onMalformed?.(candidate, err);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
function createSseDecoder(opts = {}) {
|
|
93
|
+
let buf = "";
|
|
94
|
+
function ingest(chunk) {
|
|
95
|
+
buf += chunk;
|
|
96
|
+
let tail = "";
|
|
97
|
+
if (buf.endsWith("\r")) {
|
|
98
|
+
tail = "\r";
|
|
99
|
+
buf = buf.slice(0, -1);
|
|
100
|
+
}
|
|
101
|
+
buf = buf.replace(/\r\n?/g, "\n") + tail;
|
|
102
|
+
}
|
|
103
|
+
function drain(final) {
|
|
104
|
+
const frames = [];
|
|
105
|
+
let sep = buf.indexOf("\n\n");
|
|
106
|
+
while (sep !== -1) {
|
|
107
|
+
const frameText = buf.slice(0, sep);
|
|
108
|
+
buf = buf.slice(sep + 2);
|
|
109
|
+
const payload = frameDataPayload(frameText);
|
|
110
|
+
if (payload !== null) frames.push(...parsePayload(payload, opts.onMalformed));
|
|
111
|
+
sep = buf.indexOf("\n\n");
|
|
112
|
+
}
|
|
113
|
+
if (final && buf.trim() !== "") {
|
|
114
|
+
const payload = frameDataPayload(buf);
|
|
115
|
+
if (payload !== null) frames.push(...parsePayload(payload, opts.onMalformed));
|
|
116
|
+
buf = "";
|
|
117
|
+
}
|
|
118
|
+
return frames;
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
/** Feed a chunk; returns the wire frames it completed. */
|
|
122
|
+
push(chunk) {
|
|
123
|
+
ingest(chunk);
|
|
124
|
+
return drain(false);
|
|
125
|
+
},
|
|
126
|
+
/** Flush a trailing unterminated frame at end-of-stream. */
|
|
127
|
+
flush() {
|
|
128
|
+
if (buf.endsWith("\r")) buf = `${buf.slice(0, -1)}
|
|
129
|
+
`;
|
|
130
|
+
return drain(true);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function parseSse(text, opts = {}) {
|
|
135
|
+
const dec = createSseDecoder(opts);
|
|
136
|
+
return [...dec.push(text), ...dec.flush()];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/protocol/normalizer.ts
|
|
140
|
+
var ASK_USER_QUESTION = "AskUserQuestion";
|
|
141
|
+
var SANDBOX_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
142
|
+
"SANDBOX_BOOT_TIMEOUT",
|
|
143
|
+
"SANDBOX_QUOTA_EXHAUSTED",
|
|
144
|
+
"SANDBOX_UNAVAILABLE",
|
|
145
|
+
"SNAPSHOT_VERSION_MISMATCH",
|
|
146
|
+
"AGENT_RUNNER_DIED",
|
|
147
|
+
"RUNNER_LIFECYCLE_ERROR"
|
|
148
|
+
]);
|
|
149
|
+
var str = (o, k) => typeof o[k] === "string" ? o[k] : void 0;
|
|
150
|
+
var num = (o, k) => typeof o[k] === "number" ? o[k] : void 0;
|
|
151
|
+
var bool = (o, k) => typeof o[k] === "boolean" ? o[k] : void 0;
|
|
152
|
+
var obj = (o, k) => {
|
|
153
|
+
const v = o[k];
|
|
154
|
+
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
155
|
+
};
|
|
156
|
+
var arr = (o, k) => Array.isArray(o[k]) ? o[k] : void 0;
|
|
157
|
+
function blockKindFromType(t) {
|
|
158
|
+
switch (t) {
|
|
159
|
+
case "text":
|
|
160
|
+
return "text";
|
|
161
|
+
case "thinking":
|
|
162
|
+
case "reasoning":
|
|
163
|
+
return "reasoning";
|
|
164
|
+
case "plan":
|
|
165
|
+
return "plan";
|
|
166
|
+
case "tool_use":
|
|
167
|
+
case "server_tool_use":
|
|
168
|
+
return "tool_use";
|
|
169
|
+
default:
|
|
170
|
+
return "other";
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
var blockEndType = {
|
|
174
|
+
text: "text-end",
|
|
175
|
+
reasoning: "reasoning-end",
|
|
176
|
+
plan: "plan-end"
|
|
177
|
+
};
|
|
178
|
+
var blockStartType = {
|
|
179
|
+
text: "text-start",
|
|
180
|
+
reasoning: "reasoning-start",
|
|
181
|
+
plan: "plan-start"
|
|
182
|
+
};
|
|
183
|
+
var blockDeltaType = {
|
|
184
|
+
text: "text-delta",
|
|
185
|
+
reasoning: "reasoning-delta",
|
|
186
|
+
plan: "plan-delta"
|
|
187
|
+
};
|
|
188
|
+
function createNormalizer() {
|
|
189
|
+
let seq = 0;
|
|
190
|
+
let open = /* @__PURE__ */ new Set();
|
|
191
|
+
let seen = /* @__PURE__ */ new Set();
|
|
192
|
+
let blockKind = /* @__PURE__ */ new Map();
|
|
193
|
+
let currentMessageId = null;
|
|
194
|
+
let activeTextBlockId = null;
|
|
195
|
+
let lastToolId = null;
|
|
196
|
+
let lastQuestionToolId = null;
|
|
197
|
+
let anyContentStreamed = false;
|
|
198
|
+
let runStartEmitted = false;
|
|
199
|
+
let terminalEmitted = false;
|
|
200
|
+
function reset() {
|
|
201
|
+
seq = 0;
|
|
202
|
+
open = /* @__PURE__ */ new Set();
|
|
203
|
+
seen = /* @__PURE__ */ new Set();
|
|
204
|
+
blockKind = /* @__PURE__ */ new Map();
|
|
205
|
+
currentMessageId = null;
|
|
206
|
+
activeTextBlockId = null;
|
|
207
|
+
lastToolId = null;
|
|
208
|
+
lastQuestionToolId = null;
|
|
209
|
+
anyContentStreamed = false;
|
|
210
|
+
runStartEmitted = false;
|
|
211
|
+
terminalEmitted = false;
|
|
212
|
+
}
|
|
213
|
+
function emitContentBlockStart(f, out) {
|
|
214
|
+
const id = str(f, "id");
|
|
215
|
+
if (!id) return;
|
|
216
|
+
const kind = blockKindFromType(str(f, "block_type") ?? str(f, "type"));
|
|
217
|
+
const key = kind === "tool_use" ? `tool:${id}` : `block:${id}`;
|
|
218
|
+
if (open.has(key) || seen.has(key)) return;
|
|
219
|
+
blockKind.set(id, kind);
|
|
220
|
+
if (kind === "tool_use") {
|
|
221
|
+
const name = str(f, "name") ?? "";
|
|
222
|
+
if (name === ASK_USER_QUESTION) lastQuestionToolId = id;
|
|
223
|
+
else lastToolId = id;
|
|
224
|
+
open.add(key);
|
|
225
|
+
out.push({
|
|
226
|
+
type: "tool-input-start",
|
|
227
|
+
toolCallId: id,
|
|
228
|
+
toolName: name,
|
|
229
|
+
messageId: currentMessageId ?? "",
|
|
230
|
+
state: "input-streaming"
|
|
231
|
+
});
|
|
232
|
+
} else if (kind === "text" || kind === "reasoning" || kind === "plan") {
|
|
233
|
+
open.add(key);
|
|
234
|
+
if (kind === "text") activeTextBlockId = id;
|
|
235
|
+
anyContentStreamed = true;
|
|
236
|
+
out.push({
|
|
237
|
+
type: blockStartType[kind],
|
|
238
|
+
id,
|
|
239
|
+
messageId: currentMessageId ?? ""
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function emitContentBlockDelta(f, out) {
|
|
244
|
+
const id = str(f, "id");
|
|
245
|
+
if (!id) return;
|
|
246
|
+
const delta = obj(f, "delta");
|
|
247
|
+
if (!delta) return;
|
|
248
|
+
const dType = str(delta, "type");
|
|
249
|
+
if (dType === "input_json_delta") {
|
|
250
|
+
const key2 = `tool:${id}`;
|
|
251
|
+
if (seen.has(key2)) return;
|
|
252
|
+
const partial = str(delta, "partial_json") ?? "";
|
|
253
|
+
if (partial === "") return;
|
|
254
|
+
if (!open.has(key2)) {
|
|
255
|
+
open.add(key2);
|
|
256
|
+
blockKind.set(id, "tool_use");
|
|
257
|
+
}
|
|
258
|
+
out.push({
|
|
259
|
+
type: "tool-input-delta",
|
|
260
|
+
toolCallId: id,
|
|
261
|
+
inputTextDelta: partial,
|
|
262
|
+
state: "input-streaming"
|
|
263
|
+
});
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
let kind = null;
|
|
267
|
+
if (dType === "text_delta") kind = "text";
|
|
268
|
+
else if (dType === "thinking_delta" || dType === "reasoning_delta")
|
|
269
|
+
kind = "reasoning";
|
|
270
|
+
else if (dType === "plan_delta") kind = "plan";
|
|
271
|
+
if (!kind) return;
|
|
272
|
+
const key = `block:${id}`;
|
|
273
|
+
if (seen.has(key)) return;
|
|
274
|
+
const text = kind === "reasoning" ? str(delta, "thinking") ?? str(delta, "text") ?? "" : kind === "plan" ? str(delta, "text") ?? str(delta, "plan") ?? "" : str(delta, "text") ?? "";
|
|
275
|
+
if (text === "") return;
|
|
276
|
+
if (!open.has(key)) {
|
|
277
|
+
open.add(key);
|
|
278
|
+
blockKind.set(id, kind);
|
|
279
|
+
if (kind === "text") activeTextBlockId = id;
|
|
280
|
+
anyContentStreamed = true;
|
|
281
|
+
}
|
|
282
|
+
out.push({ type: blockDeltaType[kind], id, delta: text, messageId: currentMessageId ?? "" });
|
|
283
|
+
}
|
|
284
|
+
function emitContentBlockStop(f, out) {
|
|
285
|
+
const id = str(f, "id");
|
|
286
|
+
if (!id) return;
|
|
287
|
+
const kind = blockKind.get(id) ?? "other";
|
|
288
|
+
if (kind === "tool_use") {
|
|
289
|
+
seen.add(`tool:${id}`);
|
|
290
|
+
open.delete(`tool:${id}`);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (kind === "text" || kind === "reasoning" || kind === "plan") {
|
|
294
|
+
const key = `block:${id}`;
|
|
295
|
+
open.delete(key);
|
|
296
|
+
if (seen.has(key)) return;
|
|
297
|
+
seen.add(key);
|
|
298
|
+
if (activeTextBlockId === id) activeTextBlockId = null;
|
|
299
|
+
out.push({ type: blockEndType[kind], id, messageId: currentMessageId ?? "" });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function emitMessageDelta(f, out) {
|
|
303
|
+
const delta = obj(f, "delta");
|
|
304
|
+
if (!delta) return;
|
|
305
|
+
const text = str(delta, "text") ?? "";
|
|
306
|
+
if (text === "" || !activeTextBlockId) return;
|
|
307
|
+
const key = `block:${activeTextBlockId}`;
|
|
308
|
+
if (seen.has(key)) return;
|
|
309
|
+
out.push({
|
|
310
|
+
type: "text-delta",
|
|
311
|
+
id: activeTextBlockId,
|
|
312
|
+
delta: text,
|
|
313
|
+
messageId: currentMessageId ?? ""
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function emitStandaloneToolUse(f, out) {
|
|
317
|
+
const id = str(f, "id");
|
|
318
|
+
if (!id) return;
|
|
319
|
+
const name = str(f, "name") ?? "";
|
|
320
|
+
if (name === ASK_USER_QUESTION) lastQuestionToolId = id;
|
|
321
|
+
else if (name) lastToolId = id;
|
|
322
|
+
if ("input" in f) {
|
|
323
|
+
const key = `toolinput:${id}`;
|
|
324
|
+
if (seen.has(key)) return;
|
|
325
|
+
seen.add(key);
|
|
326
|
+
out.push({
|
|
327
|
+
type: "tool-input-available",
|
|
328
|
+
toolCallId: id,
|
|
329
|
+
toolName: name,
|
|
330
|
+
input: f["input"],
|
|
331
|
+
state: "input-available"
|
|
332
|
+
});
|
|
333
|
+
} else {
|
|
334
|
+
const partial = str(f, "input_text");
|
|
335
|
+
if (partial && !seen.has(`tool:${id}`)) {
|
|
336
|
+
out.push({
|
|
337
|
+
type: "tool-input-delta",
|
|
338
|
+
toolCallId: id,
|
|
339
|
+
inputTextDelta: partial,
|
|
340
|
+
state: "input-streaming"
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function emitToolResult(f, out) {
|
|
346
|
+
const id = str(f, "tool_use_id");
|
|
347
|
+
if (!id) return;
|
|
348
|
+
const key = `tool_result:${id}`;
|
|
349
|
+
if (seen.has(key)) return;
|
|
350
|
+
seen.add(key);
|
|
351
|
+
const isError = bool(f, "is_error") ?? false;
|
|
352
|
+
const output = "content" in f ? f["content"] : f["result"];
|
|
353
|
+
out.push({
|
|
354
|
+
type: "tool-output-available",
|
|
355
|
+
toolCallId: id,
|
|
356
|
+
output,
|
|
357
|
+
isError,
|
|
358
|
+
state: isError ? "output-error" : "output-available"
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function emitApprovalGate(f, out) {
|
|
362
|
+
const requestId = str(f, "request_id");
|
|
363
|
+
if (!requestId) return;
|
|
364
|
+
const toolName = str(f, "tool_name") ?? "";
|
|
365
|
+
const timeoutSeconds = num(f, "timeout_seconds") ?? 0;
|
|
366
|
+
const toolInput = f["tool_input"];
|
|
367
|
+
if (toolName === ASK_USER_QUESTION) {
|
|
368
|
+
const key = `question:${requestId}`;
|
|
369
|
+
if (seen.has(key)) return;
|
|
370
|
+
seen.add(key);
|
|
371
|
+
const ti = obj(f, "tool_input");
|
|
372
|
+
const questions = ((ti && arr(ti, "questions")) ?? []).flatMap((q) => {
|
|
373
|
+
if (q === null || typeof q !== "object") return [];
|
|
374
|
+
const qq = q;
|
|
375
|
+
const options = (arr(qq, "options") ?? []).flatMap((o) => {
|
|
376
|
+
if (typeof o === "string") return [{ label: o }];
|
|
377
|
+
if (o === null || typeof o !== "object") return [];
|
|
378
|
+
const label = str(o, "label");
|
|
379
|
+
if (!label) return [];
|
|
380
|
+
const description = str(o, "description");
|
|
381
|
+
return [description === void 0 ? { label } : { label, description }];
|
|
382
|
+
});
|
|
383
|
+
return [{ ...qq, question: str(qq, "question") ?? "", options }];
|
|
384
|
+
});
|
|
385
|
+
out.push({
|
|
386
|
+
type: "question",
|
|
387
|
+
requestId,
|
|
388
|
+
toolCallId: str(f, "tool_use_id") ?? lastQuestionToolId ?? "",
|
|
389
|
+
questions,
|
|
390
|
+
timeoutSeconds
|
|
391
|
+
});
|
|
392
|
+
} else {
|
|
393
|
+
const key = `approval:${requestId}`;
|
|
394
|
+
if (seen.has(key)) return;
|
|
395
|
+
seen.add(key);
|
|
396
|
+
out.push({
|
|
397
|
+
type: "approval-request",
|
|
398
|
+
requestId,
|
|
399
|
+
// The frame's own tool_use_id is authoritative (live awaiting_approval
|
|
400
|
+
// carries it; rejoin permission_request does too as of the run_join
|
|
401
|
+
// fix). The last-tool inference is only a fallback — with PARALLEL tool
|
|
402
|
+
// calls it can name the wrong tool.
|
|
403
|
+
toolCallId: str(f, "tool_use_id") ?? lastToolId ?? void 0,
|
|
404
|
+
toolName,
|
|
405
|
+
toolInput,
|
|
406
|
+
timeoutSeconds
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function emitSnapshot(f, out) {
|
|
411
|
+
const messageId = str(f, "message_id") ?? currentMessageId ?? "";
|
|
412
|
+
const blocks = arr(f, "content_blocks") ?? [];
|
|
413
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
414
|
+
const raw = blocks[i];
|
|
415
|
+
if (raw === null || typeof raw !== "object") continue;
|
|
416
|
+
const b = raw;
|
|
417
|
+
const bType = str(b, "type");
|
|
418
|
+
const kind = blockKindFromType(bType);
|
|
419
|
+
if (kind === "text" || kind === "reasoning" || kind === "plan") {
|
|
420
|
+
let id = str(b, "id");
|
|
421
|
+
if (!id) {
|
|
422
|
+
if (anyContentStreamed) continue;
|
|
423
|
+
id = `${messageId}:snap:${i}`;
|
|
424
|
+
}
|
|
425
|
+
const key = `block:${id}`;
|
|
426
|
+
if (seen.has(key)) continue;
|
|
427
|
+
if (open.has(key)) {
|
|
428
|
+
open.delete(key);
|
|
429
|
+
seen.add(key);
|
|
430
|
+
if (activeTextBlockId === id) activeTextBlockId = null;
|
|
431
|
+
out.push({ type: blockEndType[kind], id, messageId });
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
seen.add(key);
|
|
435
|
+
out.push({ type: blockStartType[kind], id, messageId });
|
|
436
|
+
const text = kind === "reasoning" ? str(b, "thinking") ?? str(b, "text") ?? "" : kind === "plan" ? str(b, "plan") ?? str(b, "text") ?? "" : str(b, "text") ?? "";
|
|
437
|
+
if (text !== "") out.push({ type: blockDeltaType[kind], id, delta: text, messageId });
|
|
438
|
+
out.push({ type: blockEndType[kind], id, messageId });
|
|
439
|
+
} else if (bType === "tool_use") {
|
|
440
|
+
const id = str(b, "id");
|
|
441
|
+
if (!id || seen.has(`toolinput:${id}`)) continue;
|
|
442
|
+
seen.add(`toolinput:${id}`);
|
|
443
|
+
out.push({
|
|
444
|
+
type: "tool-input-available",
|
|
445
|
+
toolCallId: id,
|
|
446
|
+
toolName: str(b, "name") ?? "",
|
|
447
|
+
input: b["input"],
|
|
448
|
+
state: "input-available"
|
|
449
|
+
});
|
|
450
|
+
} else if (bType === "tool_result") {
|
|
451
|
+
const id = str(b, "tool_use_id");
|
|
452
|
+
if (!id || seen.has(`tool_result:${id}`)) continue;
|
|
453
|
+
seen.add(`tool_result:${id}`);
|
|
454
|
+
const isError = bool(b, "is_error") ?? false;
|
|
455
|
+
out.push({
|
|
456
|
+
type: "tool-output-available",
|
|
457
|
+
toolCallId: id,
|
|
458
|
+
output: "content" in b ? b["content"] : b["result"],
|
|
459
|
+
isError,
|
|
460
|
+
state: isError ? "output-error" : "output-available"
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function emitNotice(out, level, source, message, detail) {
|
|
466
|
+
out.push(detail === void 0 ? { type: "notice", level, source, message } : { type: "notice", level, source, message, detail });
|
|
467
|
+
}
|
|
468
|
+
function handle(frame, out) {
|
|
469
|
+
const type = str(frame, "type") ?? "";
|
|
470
|
+
switch (type) {
|
|
471
|
+
/* ---- dropped no-ops ---- */
|
|
472
|
+
case "keep-alive":
|
|
473
|
+
case "ping":
|
|
474
|
+
case "RUNNER_DIAG":
|
|
475
|
+
case "sdk_init":
|
|
476
|
+
case "sandbox_metrics":
|
|
477
|
+
return;
|
|
478
|
+
/* ---- run lifecycle ---- */
|
|
479
|
+
case "metadata": {
|
|
480
|
+
if (runStartEmitted) return;
|
|
481
|
+
runStartEmitted = true;
|
|
482
|
+
const sandboxId = str(frame, "sandbox_id") ?? null;
|
|
483
|
+
const sandboxEnabled = bool(frame, "sandbox_enabled") ?? false;
|
|
484
|
+
out.push({
|
|
485
|
+
type: "run-start",
|
|
486
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
487
|
+
runId: num(frame, "run_id") ?? null,
|
|
488
|
+
runUuid: str(frame, "run_uuid") ?? null,
|
|
489
|
+
mode: str(frame, "mode") === "task" ? "task" : "chat",
|
|
490
|
+
...str(frame, "agent_name") ? { agentName: str(frame, "agent_name") } : {},
|
|
491
|
+
...num(frame, "instance_id") !== void 0 ? { instanceId: num(frame, "instance_id") } : {},
|
|
492
|
+
...num(frame, "task_id") !== void 0 ? { taskId: num(frame, "task_id") } : {},
|
|
493
|
+
...str(frame, "status") ? { status: str(frame, "status") } : {},
|
|
494
|
+
sandbox: { id: sandboxId, enabled: sandboxEnabled }
|
|
495
|
+
});
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
case "run_metrics": {
|
|
499
|
+
out.push({
|
|
500
|
+
type: "run-metrics",
|
|
501
|
+
model: str(frame, "model") ?? "",
|
|
502
|
+
executionTimeMs: num(frame, "execution_time_ms") ?? 0,
|
|
503
|
+
inputTokens: num(frame, "input_tokens_used") ?? 0,
|
|
504
|
+
outputTokens: num(frame, "output_tokens_used") ?? 0,
|
|
505
|
+
costUsd: num(frame, "claude_token_cost_usd") ?? null,
|
|
506
|
+
sdkCostUsd: num(frame, "sdk_total_cost_usd") ?? null,
|
|
507
|
+
stopReason: str(frame, "stop_reason") ?? null,
|
|
508
|
+
completionState: str(frame, "completion_state") ?? "",
|
|
509
|
+
unresolvedToolUseIds: (arr(frame, "unresolved_tool_use_ids") ?? []).filter(
|
|
510
|
+
(x) => typeof x === "string"
|
|
511
|
+
),
|
|
512
|
+
messageCount: num(frame, "message_count") ?? 0,
|
|
513
|
+
...obj(frame, "diagnostics") ? { diagnostics: obj(frame, "diagnostics") } : {}
|
|
514
|
+
});
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
case "done": {
|
|
518
|
+
if (terminalEmitted) return;
|
|
519
|
+
terminalEmitted = true;
|
|
520
|
+
const completionState = str(frame, "completion_state") ?? "complete";
|
|
521
|
+
out.push({
|
|
522
|
+
type: "run-finish",
|
|
523
|
+
status: completionState === "complete" ? "complete" : "incomplete",
|
|
524
|
+
completionState,
|
|
525
|
+
unresolvedToolUseIds: (arr(frame, "unresolved_tool_use_ids") ?? []).filter(
|
|
526
|
+
(x) => typeof x === "string"
|
|
527
|
+
),
|
|
528
|
+
stopReason: str(frame, "stop_reason") ?? null,
|
|
529
|
+
terminalCompletionSeen: bool(frame, "terminal_completion_seen") ?? false,
|
|
530
|
+
messageCount: num(frame, "message_count") ?? 0
|
|
531
|
+
});
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
case "cancelled": {
|
|
535
|
+
if (terminalEmitted) return;
|
|
536
|
+
terminalEmitted = true;
|
|
537
|
+
out.push({ type: "run-cancelled", runId: num(frame, "run_id") ?? null });
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
case "error":
|
|
541
|
+
case "AGENT_RUNNER_DIED":
|
|
542
|
+
case "RUNNER_LIFECYCLE_ERROR":
|
|
543
|
+
case "SANDBOX_BOOT_TIMEOUT":
|
|
544
|
+
case "SANDBOX_QUOTA_EXHAUSTED":
|
|
545
|
+
case "SANDBOX_UNAVAILABLE":
|
|
546
|
+
case "SNAPSHOT_VERSION_MISMATCH": {
|
|
547
|
+
if (terminalEmitted) return;
|
|
548
|
+
terminalEmitted = true;
|
|
549
|
+
const code = SANDBOX_ERROR_CODES.has(type) ? type : null;
|
|
550
|
+
out.push({
|
|
551
|
+
type: "run-error",
|
|
552
|
+
error: str(frame, "error") ?? str(frame, "message") ?? type,
|
|
553
|
+
message: str(frame, "message") ?? "Agent execution failed",
|
|
554
|
+
code,
|
|
555
|
+
fatal: true
|
|
556
|
+
});
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
case "sdk_error": {
|
|
560
|
+
emitNotice(out, "warning", "system", str(frame, "error") ?? "SDK error");
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
case "sdk_success": {
|
|
564
|
+
if (bool(frame, "is_error") !== true) {
|
|
565
|
+
out.push({ type: "unknown", wireType: type });
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
if (terminalEmitted) return;
|
|
569
|
+
terminalEmitted = true;
|
|
570
|
+
out.push({
|
|
571
|
+
type: "run-error",
|
|
572
|
+
error: str(frame, "subtype") ?? "sdk_error",
|
|
573
|
+
message: str(frame, "result") ?? "The model provider returned an error.",
|
|
574
|
+
code: null,
|
|
575
|
+
fatal: true
|
|
576
|
+
});
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
/* ---- message lifecycle ---- */
|
|
580
|
+
case "message_start": {
|
|
581
|
+
const msg = obj(frame, "message");
|
|
582
|
+
const id = (msg && str(msg, "id")) ?? str(frame, "message_id");
|
|
583
|
+
if (!id) return;
|
|
584
|
+
currentMessageId = id;
|
|
585
|
+
const key = `message:${id}`;
|
|
586
|
+
if (seen.has(key)) return;
|
|
587
|
+
seen.add(key);
|
|
588
|
+
const usage = msg && obj(msg, "usage");
|
|
589
|
+
out.push({
|
|
590
|
+
type: "message-start",
|
|
591
|
+
messageId: id,
|
|
592
|
+
role: "assistant",
|
|
593
|
+
...usage ? { usage: { inputTokens: num(usage, "input_tokens") ?? 0, outputTokens: num(usage, "output_tokens") ?? 0 } } : {}
|
|
594
|
+
});
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
case "message_stop":
|
|
598
|
+
case "message_complete": {
|
|
599
|
+
const id = str(frame, "message_id") ?? currentMessageId;
|
|
600
|
+
if (!id) return;
|
|
601
|
+
const key = `message:${id}:end`;
|
|
602
|
+
if (seen.has(key)) return;
|
|
603
|
+
seen.add(key);
|
|
604
|
+
const usage = obj(frame, "usage");
|
|
605
|
+
out.push({
|
|
606
|
+
type: "message-end",
|
|
607
|
+
messageId: id,
|
|
608
|
+
...usage ? { usage: { inputTokens: num(usage, "input_tokens") ?? 0, outputTokens: num(usage, "output_tokens") ?? 0 } } : {}
|
|
609
|
+
});
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
case "message_snapshot":
|
|
613
|
+
emitSnapshot(frame, out);
|
|
614
|
+
return;
|
|
615
|
+
/* ---- content blocks ---- */
|
|
616
|
+
case "content_block_start":
|
|
617
|
+
emitContentBlockStart(frame, out);
|
|
618
|
+
return;
|
|
619
|
+
case "content_block_delta":
|
|
620
|
+
emitContentBlockDelta(frame, out);
|
|
621
|
+
return;
|
|
622
|
+
case "content_block_stop":
|
|
623
|
+
emitContentBlockStop(frame, out);
|
|
624
|
+
return;
|
|
625
|
+
case "message_delta":
|
|
626
|
+
emitMessageDelta(frame, out);
|
|
627
|
+
return;
|
|
628
|
+
/* ---- tools ---- */
|
|
629
|
+
case "tool_use":
|
|
630
|
+
emitStandaloneToolUse(frame, out);
|
|
631
|
+
return;
|
|
632
|
+
case "tool_result":
|
|
633
|
+
emitToolResult(frame, out);
|
|
634
|
+
return;
|
|
635
|
+
/* ---- standalone reasoning / plan: passthrough as `unknown` for v1 ----
|
|
636
|
+
* These top-level (non-content_block) frames carry full content with no
|
|
637
|
+
* wire id, so they cannot be deduped across a rejoin and two bursts would
|
|
638
|
+
* collide on a synthetic id. Block-based reasoning (content_block
|
|
639
|
+
* reasoning_delta) is the dedupe-safe path and IS handled. Surface these
|
|
640
|
+
* raw until their real wire behavior is confirmed (CONTRACT.md open Q). */
|
|
641
|
+
/* ---- HITL ---- */
|
|
642
|
+
case "awaiting_approval":
|
|
643
|
+
case "permission_request":
|
|
644
|
+
emitApprovalGate(frame, out);
|
|
645
|
+
return;
|
|
646
|
+
/* ---- sandbox + notices ---- */
|
|
647
|
+
case "sandbox-connecting":
|
|
648
|
+
out.push({
|
|
649
|
+
type: "sandbox-status",
|
|
650
|
+
phase: "connecting",
|
|
651
|
+
message: str(frame, "message") ?? "Connecting to sandbox",
|
|
652
|
+
runId: num(frame, "run_id") ?? null
|
|
653
|
+
});
|
|
654
|
+
return;
|
|
655
|
+
case "sandbox-connected":
|
|
656
|
+
out.push({
|
|
657
|
+
type: "sandbox-status",
|
|
658
|
+
phase: "connected",
|
|
659
|
+
message: str(frame, "message") ?? "Connected to sandbox",
|
|
660
|
+
runId: num(frame, "run_id") ?? null,
|
|
661
|
+
...str(frame, "sandbox_id") !== void 0 ? { sandboxId: str(frame, "sandbox_id") } : {},
|
|
662
|
+
...num(frame, "duration_ms") !== void 0 ? { durationMs: num(frame, "duration_ms") } : {}
|
|
663
|
+
});
|
|
664
|
+
return;
|
|
665
|
+
case "stderr":
|
|
666
|
+
emitNotice(out, "info", "stderr", str(frame, "message") ?? "");
|
|
667
|
+
return;
|
|
668
|
+
case "mcp_error":
|
|
669
|
+
case "mcp_auth_failed":
|
|
670
|
+
emitNotice(out, "warning", "mcp", str(frame, "message") ?? str(frame, "error") ?? "MCP error", str(frame, "detail"));
|
|
671
|
+
return;
|
|
672
|
+
case "rate_limit": {
|
|
673
|
+
const info = obj(frame, "rate_limit_info");
|
|
674
|
+
const status = (info && str(info, "status")) ?? "allowed";
|
|
675
|
+
emitNotice(out, status === "rejected" ? "warning" : "info", "rate_limit", `Rate limit: ${status}`);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
case "compact_boundary":
|
|
679
|
+
out.push({
|
|
680
|
+
type: "compact-boundary",
|
|
681
|
+
trigger: str(frame, "trigger") === "manual" ? "manual" : "auto",
|
|
682
|
+
preTokens: num(frame, "pre_tokens") ?? 0
|
|
683
|
+
});
|
|
684
|
+
return;
|
|
685
|
+
/* ---- passthrough ---- */
|
|
686
|
+
default:
|
|
687
|
+
out.push({ type: "unknown", wireType: type });
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return {
|
|
692
|
+
push(frame) {
|
|
693
|
+
const partials = [];
|
|
694
|
+
handle(frame, partials);
|
|
695
|
+
return partials.map(
|
|
696
|
+
(e) => ({ ...e, seq: seq++, raw: frame })
|
|
697
|
+
);
|
|
698
|
+
},
|
|
699
|
+
reset
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// src/protocol/accumulator.ts
|
|
704
|
+
var initialConversationState = {
|
|
705
|
+
runId: null,
|
|
706
|
+
runUuid: null,
|
|
707
|
+
agentName: null,
|
|
708
|
+
status: "idle",
|
|
709
|
+
messages: [],
|
|
710
|
+
pendingApproval: null,
|
|
711
|
+
pendingQuestion: null,
|
|
712
|
+
finishStopReason: null,
|
|
713
|
+
error: null
|
|
714
|
+
};
|
|
715
|
+
function lastAssistantIndex(messages) {
|
|
716
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
717
|
+
if (messages[i].role === "assistant") return i;
|
|
718
|
+
}
|
|
719
|
+
return -1;
|
|
720
|
+
}
|
|
721
|
+
function withMessageParts(state, messageId, role, fn) {
|
|
722
|
+
const messages = state.messages.slice();
|
|
723
|
+
let idx = messageId ? messages.findIndex((m) => m.id === messageId) : lastAssistantIndex(messages);
|
|
724
|
+
if (idx === -1) {
|
|
725
|
+
messages.push({ id: messageId || `m:${messages.length}`, role, parts: [] });
|
|
726
|
+
idx = messages.length - 1;
|
|
727
|
+
}
|
|
728
|
+
const msg = messages[idx];
|
|
729
|
+
messages[idx] = { ...msg, parts: fn(msg.parts) };
|
|
730
|
+
return { ...state, messages };
|
|
731
|
+
}
|
|
732
|
+
var isTextLike = (p) => p.kind === "text" || p.kind === "reasoning" || p.kind === "plan";
|
|
733
|
+
function ensureTextPart(parts, kind, id) {
|
|
734
|
+
if (parts.some((p) => isTextLike(p) && p.id === id)) return parts;
|
|
735
|
+
return [...parts, { kind, id, text: "" }];
|
|
736
|
+
}
|
|
737
|
+
function applyTextDelta(parts, kind, id, delta) {
|
|
738
|
+
const i = parts.findIndex((p2) => isTextLike(p2) && p2.id === id);
|
|
739
|
+
if (i === -1) return [...parts, { kind, id, text: delta }];
|
|
740
|
+
const p = parts[i];
|
|
741
|
+
const next = parts.slice();
|
|
742
|
+
next[i] = { ...p, text: p.text + delta };
|
|
743
|
+
return next;
|
|
744
|
+
}
|
|
745
|
+
function updateToolPart(state, toolCallId, toolName, patch) {
|
|
746
|
+
const messages = state.messages.slice();
|
|
747
|
+
for (let mi = 0; mi < messages.length; mi++) {
|
|
748
|
+
const parts = messages[mi].parts;
|
|
749
|
+
const pi = parts.findIndex((p) => p.kind === "tool" && p.toolCallId === toolCallId);
|
|
750
|
+
if (pi !== -1) {
|
|
751
|
+
const np = parts.slice();
|
|
752
|
+
np[pi] = patch(parts[pi]);
|
|
753
|
+
messages[mi] = { ...messages[mi], parts: np };
|
|
754
|
+
return { ...state, messages };
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
let idx = lastAssistantIndex(messages);
|
|
758
|
+
if (idx === -1) {
|
|
759
|
+
messages.push({ id: `m:${messages.length}`, role: "assistant", parts: [] });
|
|
760
|
+
idx = messages.length - 1;
|
|
761
|
+
}
|
|
762
|
+
const base = {
|
|
763
|
+
kind: "tool",
|
|
764
|
+
toolCallId,
|
|
765
|
+
toolName: toolName ?? "",
|
|
766
|
+
state: "input-streaming",
|
|
767
|
+
inputText: ""
|
|
768
|
+
};
|
|
769
|
+
messages[idx] = { ...messages[idx], parts: [...messages[idx].parts, patch(base)] };
|
|
770
|
+
return { ...state, messages };
|
|
771
|
+
}
|
|
772
|
+
function resume(status) {
|
|
773
|
+
return status === "awaiting_approval" || status === "awaiting_input" ? "running" : status;
|
|
774
|
+
}
|
|
775
|
+
function accumulate(state, e) {
|
|
776
|
+
switch (e.type) {
|
|
777
|
+
case "run-start":
|
|
778
|
+
return {
|
|
779
|
+
...state,
|
|
780
|
+
runId: e.runId,
|
|
781
|
+
runUuid: e.runUuid,
|
|
782
|
+
agentName: e.agentName ?? state.agentName ?? null,
|
|
783
|
+
status: "running",
|
|
784
|
+
error: null,
|
|
785
|
+
// A retry re-drives the turn: the previous attempt's outcome row
|
|
786
|
+
// ("Response truncated", "Request declined") must not survive it.
|
|
787
|
+
finishStopReason: null
|
|
788
|
+
};
|
|
789
|
+
case "run-status":
|
|
790
|
+
return { ...state, status: e.status };
|
|
791
|
+
case "message-start":
|
|
792
|
+
return withMessageParts(state, e.messageId, e.role, (p) => p);
|
|
793
|
+
case "text-start":
|
|
794
|
+
return {
|
|
795
|
+
...withMessageParts(state, e.messageId, "assistant", (p) => ensureTextPart(p, "text", e.id)),
|
|
796
|
+
status: resume(state.status)
|
|
797
|
+
};
|
|
798
|
+
case "text-delta":
|
|
799
|
+
return {
|
|
800
|
+
...withMessageParts(state, e.messageId, "assistant", (p) => applyTextDelta(p, "text", e.id, e.delta)),
|
|
801
|
+
status: resume(state.status)
|
|
802
|
+
};
|
|
803
|
+
case "reasoning-start":
|
|
804
|
+
return withMessageParts(state, e.messageId, "assistant", (p) => ensureTextPart(p, "reasoning", e.id));
|
|
805
|
+
case "reasoning-delta":
|
|
806
|
+
return withMessageParts(state, e.messageId, "assistant", (p) => applyTextDelta(p, "reasoning", e.id, e.delta));
|
|
807
|
+
case "plan-start":
|
|
808
|
+
return withMessageParts(state, e.messageId, "assistant", (p) => ensureTextPart(p, "plan", e.id));
|
|
809
|
+
case "plan-delta":
|
|
810
|
+
return withMessageParts(state, e.messageId, "assistant", (p) => applyTextDelta(p, "plan", e.id, e.delta));
|
|
811
|
+
case "text-end":
|
|
812
|
+
case "reasoning-end":
|
|
813
|
+
case "plan-end":
|
|
814
|
+
case "message-end":
|
|
815
|
+
return state;
|
|
816
|
+
case "tool-input-start":
|
|
817
|
+
return {
|
|
818
|
+
...withMessageParts(
|
|
819
|
+
state,
|
|
820
|
+
e.messageId,
|
|
821
|
+
"assistant",
|
|
822
|
+
(p) => p.some((x) => x.kind === "tool" && x.toolCallId === e.toolCallId) ? p : [
|
|
823
|
+
...p,
|
|
824
|
+
{
|
|
825
|
+
kind: "tool",
|
|
826
|
+
toolCallId: e.toolCallId,
|
|
827
|
+
toolName: e.toolName,
|
|
828
|
+
state: "input-streaming",
|
|
829
|
+
inputText: ""
|
|
830
|
+
}
|
|
831
|
+
]
|
|
832
|
+
),
|
|
833
|
+
status: resume(state.status)
|
|
834
|
+
};
|
|
835
|
+
case "tool-input-delta":
|
|
836
|
+
return updateToolPart(state, e.toolCallId, void 0, (t) => ({
|
|
837
|
+
...t,
|
|
838
|
+
inputText: t.inputText + e.inputTextDelta,
|
|
839
|
+
state: "input-streaming"
|
|
840
|
+
}));
|
|
841
|
+
case "tool-input-available":
|
|
842
|
+
return updateToolPart(state, e.toolCallId, e.toolName, (t) => ({
|
|
843
|
+
...t,
|
|
844
|
+
input: e.input,
|
|
845
|
+
state: "input-available"
|
|
846
|
+
}));
|
|
847
|
+
case "tool-output-available": {
|
|
848
|
+
const s = updateToolPart(state, e.toolCallId, void 0, (t) => ({
|
|
849
|
+
...t,
|
|
850
|
+
output: e.output,
|
|
851
|
+
isError: e.isError,
|
|
852
|
+
state: e.state
|
|
853
|
+
}));
|
|
854
|
+
const pendingApproval = s.pendingApproval && s.pendingApproval.toolCallId === e.toolCallId ? null : s.pendingApproval;
|
|
855
|
+
const pendingQuestion = s.pendingQuestion && s.pendingQuestion.toolCallId === e.toolCallId ? null : s.pendingQuestion;
|
|
856
|
+
return { ...s, pendingApproval, pendingQuestion, status: resume(s.status) };
|
|
857
|
+
}
|
|
858
|
+
case "approval-request":
|
|
859
|
+
return { ...state, pendingApproval: e, status: "awaiting_approval" };
|
|
860
|
+
case "approval-resolved":
|
|
861
|
+
return state.pendingApproval && state.pendingApproval.requestId === e.requestId ? { ...state, pendingApproval: null } : state;
|
|
862
|
+
case "question":
|
|
863
|
+
return { ...state, pendingQuestion: e, status: "awaiting_input" };
|
|
864
|
+
case "run-finish":
|
|
865
|
+
return { ...state, status: e.status, pendingApproval: null, pendingQuestion: null };
|
|
866
|
+
case "run-error":
|
|
867
|
+
return {
|
|
868
|
+
...state,
|
|
869
|
+
status: "error",
|
|
870
|
+
error: {
|
|
871
|
+
message: e.message,
|
|
872
|
+
code: e.code,
|
|
873
|
+
...e.apiStatus !== void 0 ? { apiStatus: e.apiStatus } : {},
|
|
874
|
+
...e.apiDetails !== void 0 ? { apiDetails: e.apiDetails } : {}
|
|
875
|
+
},
|
|
876
|
+
pendingApproval: null,
|
|
877
|
+
pendingQuestion: null
|
|
878
|
+
};
|
|
879
|
+
case "run-cancelled":
|
|
880
|
+
return { ...state, status: "cancelled", pendingApproval: null, pendingQuestion: null };
|
|
881
|
+
case "sandbox-status": {
|
|
882
|
+
const withStatus = e.phase === "connecting" && state.status === "idle" ? { ...state, status: "connecting" } : state;
|
|
883
|
+
if (e.phase === "connecting") {
|
|
884
|
+
return withMessageParts(withStatus, "", "assistant", (p) => [
|
|
885
|
+
...p,
|
|
886
|
+
{ kind: "sandbox", id: `sb:${p.length}`, phase: "connecting" }
|
|
887
|
+
]);
|
|
888
|
+
}
|
|
889
|
+
const messages = withStatus.messages.slice();
|
|
890
|
+
for (let mi = messages.length - 1; mi >= 0; mi--) {
|
|
891
|
+
const parts = messages[mi].parts;
|
|
892
|
+
for (let pi = parts.length - 1; pi >= 0; pi--) {
|
|
893
|
+
const part = parts[pi];
|
|
894
|
+
if (part.kind === "sandbox" && part.phase === "connecting") {
|
|
895
|
+
const np = parts.slice();
|
|
896
|
+
np[pi] = { ...part, phase: "connected", ...e.durationMs !== void 0 ? { durationMs: e.durationMs } : {} };
|
|
897
|
+
messages[mi] = { ...messages[mi], parts: np };
|
|
898
|
+
return { ...withStatus, messages };
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return withMessageParts(withStatus, "", "assistant", (p) => [
|
|
903
|
+
...p,
|
|
904
|
+
{ kind: "sandbox", id: `sb:${p.length}`, phase: "connected", ...e.durationMs !== void 0 ? { durationMs: e.durationMs } : {} }
|
|
905
|
+
]);
|
|
906
|
+
}
|
|
907
|
+
case "notice":
|
|
908
|
+
if (e.level !== "warning") return state;
|
|
909
|
+
return withMessageParts(state, "", "assistant", (p) => [
|
|
910
|
+
...p,
|
|
911
|
+
{ kind: "notice", id: `n:${p.length}`, level: e.level, source: e.source, message: e.message }
|
|
912
|
+
]);
|
|
913
|
+
case "compact-boundary":
|
|
914
|
+
return withMessageParts(state, "", "assistant", (p) => [
|
|
915
|
+
...p,
|
|
916
|
+
{ kind: "compact", id: `c:${p.length}`, trigger: e.trigger, preTokens: e.preTokens }
|
|
917
|
+
]);
|
|
918
|
+
case "run-metrics":
|
|
919
|
+
return e.stopReason === "refusal" || e.stopReason === "max_tokens" ? { ...state, finishStopReason: e.stopReason } : state;
|
|
920
|
+
case "unknown":
|
|
921
|
+
return state;
|
|
922
|
+
default:
|
|
923
|
+
return state;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
function createAccumulator() {
|
|
927
|
+
let state = initialConversationState;
|
|
928
|
+
return {
|
|
929
|
+
get state() {
|
|
930
|
+
return state;
|
|
931
|
+
},
|
|
932
|
+
apply(event) {
|
|
933
|
+
state = accumulate(state, event);
|
|
934
|
+
return state;
|
|
935
|
+
},
|
|
936
|
+
addUserMessage(text) {
|
|
937
|
+
const id = `u:${state.messages.length}`;
|
|
938
|
+
state = {
|
|
939
|
+
...state,
|
|
940
|
+
messages: [...state.messages, { id, role: "user", parts: [{ kind: "text", id, text }] }]
|
|
941
|
+
};
|
|
942
|
+
return state;
|
|
943
|
+
},
|
|
944
|
+
reset() {
|
|
945
|
+
state = initialConversationState;
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// src/protocol/errors.ts
|
|
951
|
+
var M8tesApiError = class extends Error {
|
|
952
|
+
type;
|
|
953
|
+
code;
|
|
954
|
+
status;
|
|
955
|
+
requestId;
|
|
956
|
+
details;
|
|
957
|
+
docUrl;
|
|
958
|
+
errorCode;
|
|
959
|
+
retryAfter;
|
|
960
|
+
constructor(message, f) {
|
|
961
|
+
super(message);
|
|
962
|
+
this.name = "M8tesApiError";
|
|
963
|
+
this.type = f.type;
|
|
964
|
+
this.code = f.code;
|
|
965
|
+
this.status = f.status;
|
|
966
|
+
this.requestId = f.requestId;
|
|
967
|
+
this.details = f.details;
|
|
968
|
+
this.docUrl = f.docUrl;
|
|
969
|
+
this.errorCode = f.errorCode;
|
|
970
|
+
this.retryAfter = f.retryAfter;
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
var ValidationError = class extends M8tesApiError {
|
|
974
|
+
constructor(message, f) {
|
|
975
|
+
super(message, f);
|
|
976
|
+
this.name = "ValidationError";
|
|
977
|
+
}
|
|
978
|
+
};
|
|
979
|
+
var AuthenticationError = class extends M8tesApiError {
|
|
980
|
+
constructor(message, f) {
|
|
981
|
+
super(message, f);
|
|
982
|
+
this.name = "AuthenticationError";
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
var BillingError = class extends M8tesApiError {
|
|
986
|
+
constructor(message, f) {
|
|
987
|
+
super(message, f);
|
|
988
|
+
this.name = "BillingError";
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
var PermissionDeniedError = class extends M8tesApiError {
|
|
992
|
+
constructor(message, f) {
|
|
993
|
+
super(message, f);
|
|
994
|
+
this.name = "PermissionDeniedError";
|
|
995
|
+
}
|
|
996
|
+
};
|
|
997
|
+
var NotFoundError = class extends M8tesApiError {
|
|
998
|
+
constructor(message, f) {
|
|
999
|
+
super(message, f);
|
|
1000
|
+
this.name = "NotFoundError";
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
var ConflictError = class extends M8tesApiError {
|
|
1004
|
+
constructor(message, f) {
|
|
1005
|
+
super(message, f);
|
|
1006
|
+
this.name = "ConflictError";
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
var RunNotStreamingError = class extends ConflictError {
|
|
1010
|
+
constructor(message, f) {
|
|
1011
|
+
super(message, f);
|
|
1012
|
+
this.name = "RunNotStreamingError";
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
var RateLimitError = class extends M8tesApiError {
|
|
1016
|
+
constructor(message, f) {
|
|
1017
|
+
super(message, f);
|
|
1018
|
+
this.name = "RateLimitError";
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
var APIError = class extends M8tesApiError {
|
|
1022
|
+
constructor(message, f) {
|
|
1023
|
+
super(message, f);
|
|
1024
|
+
this.name = "APIError";
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
var RunFailedError = class extends M8tesApiError {
|
|
1028
|
+
constructor(message, f) {
|
|
1029
|
+
super(message, f);
|
|
1030
|
+
this.name = "RunFailedError";
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
var STATUS_MAP = {
|
|
1034
|
+
400: ValidationError,
|
|
1035
|
+
401: AuthenticationError,
|
|
1036
|
+
402: BillingError,
|
|
1037
|
+
403: PermissionDeniedError,
|
|
1038
|
+
404: NotFoundError,
|
|
1039
|
+
409: ConflictError,
|
|
1040
|
+
422: ValidationError,
|
|
1041
|
+
429: RateLimitError
|
|
1042
|
+
};
|
|
1043
|
+
function parseRetryAfter(raw) {
|
|
1044
|
+
if (!raw) return void 0;
|
|
1045
|
+
const seconds = Number(raw);
|
|
1046
|
+
return Number.isFinite(seconds) ? seconds : void 0;
|
|
1047
|
+
}
|
|
1048
|
+
function str2(o, key) {
|
|
1049
|
+
return typeof o[key] === "string" ? o[key] : void 0;
|
|
1050
|
+
}
|
|
1051
|
+
function parseErrorEnvelope(status, body, headers) {
|
|
1052
|
+
const e = body !== null && typeof body === "object" && "error" in body && typeof body.error === "object" ? body.error ?? {} : {};
|
|
1053
|
+
const details = e["details"];
|
|
1054
|
+
const errorCode = details !== null && typeof details === "object" ? str2(details, "error_code") : void 0;
|
|
1055
|
+
return {
|
|
1056
|
+
message: str2(e, "message") ?? `Request failed (${status})`,
|
|
1057
|
+
fields: {
|
|
1058
|
+
type: str2(e, "type") ?? "api_error",
|
|
1059
|
+
code: typeof e["code"] === "number" ? e["code"] : status,
|
|
1060
|
+
status,
|
|
1061
|
+
requestId: str2(e, "request_id") ?? headers?.get("x-request-id") ?? void 0,
|
|
1062
|
+
details,
|
|
1063
|
+
docUrl: str2(e, "doc_url"),
|
|
1064
|
+
errorCode,
|
|
1065
|
+
retryAfter: parseRetryAfter(headers?.get("retry-after"))
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
function errorClassForStatus(status, opts = {}) {
|
|
1070
|
+
if (status === 409 && opts.conflictIsNotStreaming) return RunNotStreamingError;
|
|
1071
|
+
return STATUS_MAP[status] ?? APIError;
|
|
1072
|
+
}
|
|
1073
|
+
async function errorFromResponse(res, opts = {}) {
|
|
1074
|
+
let body;
|
|
1075
|
+
try {
|
|
1076
|
+
body = await res.json();
|
|
1077
|
+
} catch {
|
|
1078
|
+
body = void 0;
|
|
1079
|
+
}
|
|
1080
|
+
const { message, fields } = parseErrorEnvelope(res.status, body, res.headers);
|
|
1081
|
+
const Cls = errorClassForStatus(res.status, opts);
|
|
1082
|
+
return new Cls(message, fields);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
// src/http.ts
|
|
1086
|
+
var DEFAULT_BASE_URL = "https://api.m8tes.ai/api/v2";
|
|
1087
|
+
var MAX_ATTEMPTS = 3;
|
|
1088
|
+
var INITIAL_BACKOFF_MS = 500;
|
|
1089
|
+
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
1090
|
+
var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
1091
|
+
function backoff(ms, signal) {
|
|
1092
|
+
if (signal?.aborted) return Promise.resolve();
|
|
1093
|
+
return new Promise((resolve) => {
|
|
1094
|
+
const timer = setTimeout(done, ms);
|
|
1095
|
+
function done() {
|
|
1096
|
+
clearTimeout(timer);
|
|
1097
|
+
signal?.removeEventListener("abort", done);
|
|
1098
|
+
resolve();
|
|
1099
|
+
}
|
|
1100
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
function looksLikeHtml(res, text) {
|
|
1104
|
+
if ((res.headers.get("content-type") ?? "").includes("text/html")) return true;
|
|
1105
|
+
const head = text.trimStart().slice(0, 9).toLowerCase();
|
|
1106
|
+
return head.startsWith("<!doctype") || head.startsWith("<html");
|
|
1107
|
+
}
|
|
1108
|
+
function diagnose(res, text, body, url) {
|
|
1109
|
+
if (looksLikeHtml(res, text)) {
|
|
1110
|
+
return `Received an HTML page instead of an API response (HTTP ${res.status}) from ${url}. This usually means the host does not serve the m8tes API; check your baseUrl (the hosted API is ${DEFAULT_BASE_URL}).`;
|
|
1111
|
+
}
|
|
1112
|
+
const isBareNotFound = res.status === 404 && body !== null && typeof body === "object" && !("error" in body) && body.detail === "Not Found";
|
|
1113
|
+
if (isBareNotFound) {
|
|
1114
|
+
return `HTTP 404 from ${url} with no API error envelope \u2014 the path matched no route. Check your baseUrl includes the /api/v2 prefix (the hosted API is ${DEFAULT_BASE_URL}).`;
|
|
1115
|
+
}
|
|
1116
|
+
return void 0;
|
|
1117
|
+
}
|
|
1118
|
+
function createHttp(options = {}) {
|
|
1119
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
1120
|
+
throw new Error(
|
|
1121
|
+
"@m8tes/sdk is server-only: it holds your secret m8_ API key, which anyone could read out of a browser bundle. To render an agent in the browser use @m8tes/react, which talks to a server proxy that keeps the key on your server. See https://www.m8tes.ai/docs/embed-a-ui"
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
const apiKey = options.apiKey ?? globalThis.process?.env?.["M8TES_API_KEY"];
|
|
1125
|
+
if (!apiKey) {
|
|
1126
|
+
throw new Error(
|
|
1127
|
+
"@m8tes/sdk: no API key. Pass `new M8tes({ apiKey })` or set M8TES_API_KEY. Create a key at https://m8tes.ai/developer."
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
1131
|
+
const timeout = options.timeout ?? 3e5;
|
|
1132
|
+
const maybeFetch = options.fetch ?? globalThis.fetch;
|
|
1133
|
+
if (!maybeFetch) {
|
|
1134
|
+
throw new Error(
|
|
1135
|
+
"@m8tes/sdk: no global fetch. Use Node 18+ or pass `fetch` in the client options."
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1138
|
+
const fetchImpl = maybeFetch;
|
|
1139
|
+
async function toError(res, url, errOpts) {
|
|
1140
|
+
const text = await res.text().catch(() => "");
|
|
1141
|
+
let body;
|
|
1142
|
+
try {
|
|
1143
|
+
body = JSON.parse(text);
|
|
1144
|
+
} catch {
|
|
1145
|
+
body = void 0;
|
|
1146
|
+
}
|
|
1147
|
+
const parsed = parseErrorEnvelope(res.status, body, res.headers);
|
|
1148
|
+
const message = diagnose(res, text, body, url) ?? (body ? parsed.message : text || parsed.message);
|
|
1149
|
+
return new (errorClassForStatus(res.status, errOpts))(message, parsed.fields);
|
|
1150
|
+
}
|
|
1151
|
+
async function attempt(method, url, opts) {
|
|
1152
|
+
const headers = {
|
|
1153
|
+
authorization: `Bearer ${apiKey}`,
|
|
1154
|
+
...options.headers,
|
|
1155
|
+
...opts.headers
|
|
1156
|
+
};
|
|
1157
|
+
const init = { method, headers };
|
|
1158
|
+
if (opts.body !== void 0) {
|
|
1159
|
+
headers["content-type"] = "application/json";
|
|
1160
|
+
init.body = JSON.stringify(opts.body);
|
|
1161
|
+
}
|
|
1162
|
+
const timer = AbortSignal.timeout(timeout);
|
|
1163
|
+
init.signal = opts.signal ? AbortSignal.any([opts.signal, timer]) : timer;
|
|
1164
|
+
return fetchImpl(url, init);
|
|
1165
|
+
}
|
|
1166
|
+
async function send(method, path, opts, errOpts = {}) {
|
|
1167
|
+
const url = `${baseUrl}${path}${opts.query ?? ""}`;
|
|
1168
|
+
const idempotent = IDEMPOTENT_METHODS.has(method.toUpperCase());
|
|
1169
|
+
let lastNetworkError;
|
|
1170
|
+
for (let i = 0; i < MAX_ATTEMPTS; i++) {
|
|
1171
|
+
const isLast = i === MAX_ATTEMPTS - 1;
|
|
1172
|
+
let res;
|
|
1173
|
+
try {
|
|
1174
|
+
res = await attempt(method, url, opts);
|
|
1175
|
+
} catch (e) {
|
|
1176
|
+
if (opts.signal?.aborted) throw e;
|
|
1177
|
+
lastNetworkError = e;
|
|
1178
|
+
if (!idempotent || isLast) {
|
|
1179
|
+
throw new APIError(e instanceof Error ? e.message : String(e), {
|
|
1180
|
+
type: "api_error",
|
|
1181
|
+
code: 0,
|
|
1182
|
+
status: 0
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
await backoff(INITIAL_BACKOFF_MS * 2 ** i, opts.signal);
|
|
1186
|
+
if (opts.signal?.aborted) throw e;
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
if (res.ok) return res;
|
|
1190
|
+
if (!RETRYABLE_STATUS.has(res.status) || !idempotent || isLast) {
|
|
1191
|
+
throw await toError(res, url, errOpts);
|
|
1192
|
+
}
|
|
1193
|
+
const retryAfter = res.status === 429 ? parseRetryAfter(res.headers.get("retry-after")) : void 0;
|
|
1194
|
+
await res.text().catch(() => "");
|
|
1195
|
+
await backoff(retryAfter !== void 0 ? retryAfter * 1e3 : INITIAL_BACKOFF_MS * 2 ** i, opts.signal);
|
|
1196
|
+
if (opts.signal?.aborted) throw await toError(res, url, errOpts);
|
|
1197
|
+
}
|
|
1198
|
+
throw new APIError(
|
|
1199
|
+
lastNetworkError instanceof Error ? lastNetworkError.message : "Max retries exceeded",
|
|
1200
|
+
{ type: "api_error", code: 0, status: 0 }
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
return {
|
|
1204
|
+
baseUrl,
|
|
1205
|
+
async request(method, path, opts = {}) {
|
|
1206
|
+
const res = await send(method, path, opts);
|
|
1207
|
+
if (res.status === 204) return void 0;
|
|
1208
|
+
const text = await res.text();
|
|
1209
|
+
return text ? JSON.parse(text) : void 0;
|
|
1210
|
+
},
|
|
1211
|
+
raw(method, path, opts = {}) {
|
|
1212
|
+
return send(method, path, opts);
|
|
1213
|
+
},
|
|
1214
|
+
async *stream(method, path, opts = {}) {
|
|
1215
|
+
const res = await send(method, path, opts, { conflictIsNotStreaming: true });
|
|
1216
|
+
if (!res.body) return;
|
|
1217
|
+
const normalizer = opts.normalizer ?? createNormalizer();
|
|
1218
|
+
const decoder = createSseDecoder({ onMalformed: options.onMalformed });
|
|
1219
|
+
const reader = res.body.getReader();
|
|
1220
|
+
const td = new TextDecoder();
|
|
1221
|
+
try {
|
|
1222
|
+
for (; ; ) {
|
|
1223
|
+
const { done, value } = await reader.read();
|
|
1224
|
+
if (done) break;
|
|
1225
|
+
for (const frame of decoder.push(td.decode(value, { stream: true }))) {
|
|
1226
|
+
yield* normalizer.push(frame);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
for (const frame of decoder.flush()) yield* normalizer.push(frame);
|
|
1230
|
+
} finally {
|
|
1231
|
+
try {
|
|
1232
|
+
await reader.cancel();
|
|
1233
|
+
} catch {
|
|
1234
|
+
try {
|
|
1235
|
+
reader.releaseLock();
|
|
1236
|
+
} catch {
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// src/pagination.ts
|
|
1245
|
+
var Page = class {
|
|
1246
|
+
data;
|
|
1247
|
+
hasMore;
|
|
1248
|
+
/** Fetches the next page given a cursor. Absent on a terminal page. */
|
|
1249
|
+
fetchNext;
|
|
1250
|
+
constructor(data, hasMore, fetchNext) {
|
|
1251
|
+
this.data = data;
|
|
1252
|
+
this.hasMore = hasMore;
|
|
1253
|
+
this.fetchNext = fetchNext;
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Auto-paging: yields every item across every page.
|
|
1257
|
+
*
|
|
1258
|
+
* Stops if the cursor ever fails to advance. A server that returns the same
|
|
1259
|
+
* page again with `has_more: true` — a caching layer, a replica lagging, a bug
|
|
1260
|
+
* — would otherwise spin forever, re-yielding the same rows and never
|
|
1261
|
+
* returning. Terminating is the only safe response: the caller gets the items
|
|
1262
|
+
* it did see rather than a hung process.
|
|
1263
|
+
*/
|
|
1264
|
+
async *[Symbol.asyncIterator]() {
|
|
1265
|
+
let page = this;
|
|
1266
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1267
|
+
for (; ; ) {
|
|
1268
|
+
yield* page.data;
|
|
1269
|
+
const last = page.data.at(-1);
|
|
1270
|
+
if (!page.hasMore || !last || !page.fetchNext) return;
|
|
1271
|
+
const cursor = typeof last.id === "number" || typeof last.id === "string" ? last.id : typeof last.name === "string" ? last.name : void 0;
|
|
1272
|
+
if (cursor === void 0 || seen.has(cursor)) return;
|
|
1273
|
+
seen.add(cursor);
|
|
1274
|
+
page = await page.fetchNext(cursor);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
/** Every item across every page, collected. Prefer iteration for large sets. */
|
|
1278
|
+
async all() {
|
|
1279
|
+
const out = [];
|
|
1280
|
+
for await (const item of this) out.push(item);
|
|
1281
|
+
return out;
|
|
1282
|
+
}
|
|
1283
|
+
};
|
|
1284
|
+
|
|
1285
|
+
// src/params.ts
|
|
1286
|
+
function toBody(params) {
|
|
1287
|
+
const out = {};
|
|
1288
|
+
for (const [k, v] of Object.entries(params)) {
|
|
1289
|
+
if (v !== void 0) out[k] = v;
|
|
1290
|
+
}
|
|
1291
|
+
return out;
|
|
1292
|
+
}
|
|
1293
|
+
function toQuery(params) {
|
|
1294
|
+
const q = new URLSearchParams();
|
|
1295
|
+
for (const [k, v] of Object.entries(params)) {
|
|
1296
|
+
if (v === void 0 || v === null) continue;
|
|
1297
|
+
q.set(k, String(v));
|
|
1298
|
+
}
|
|
1299
|
+
const s = q.toString();
|
|
1300
|
+
return s ? `?${s}` : "";
|
|
1301
|
+
}
|
|
1302
|
+
function resolveAgentId(teammateId, agentId) {
|
|
1303
|
+
if (agentId !== void 0 && teammateId !== void 0 && agentId !== teammateId) {
|
|
1304
|
+
throw new Error("Pass agent_id or teammate_id, not both");
|
|
1305
|
+
}
|
|
1306
|
+
return teammateId ?? agentId;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// src/resources/agents.ts
|
|
1310
|
+
function createAgentsResource(http) {
|
|
1311
|
+
return {
|
|
1312
|
+
create(params = {}) {
|
|
1313
|
+
return http.request("POST", "/agents/", { body: toBody({ ...params }) });
|
|
1314
|
+
},
|
|
1315
|
+
async list(params = {}) {
|
|
1316
|
+
const fetchPage = async (p) => {
|
|
1317
|
+
const res = await http.request("GET", "/agents/", {
|
|
1318
|
+
query: toQuery(p)
|
|
1319
|
+
});
|
|
1320
|
+
return new Page(
|
|
1321
|
+
res?.data ?? [],
|
|
1322
|
+
res?.has_more ?? false,
|
|
1323
|
+
(starting_after) => fetchPage({ ...p, starting_after })
|
|
1324
|
+
);
|
|
1325
|
+
};
|
|
1326
|
+
return fetchPage({ ...params });
|
|
1327
|
+
},
|
|
1328
|
+
get(agentId, params = {}) {
|
|
1329
|
+
return http.request("GET", `/agents/${agentId}`, { query: toQuery(params) });
|
|
1330
|
+
},
|
|
1331
|
+
update(agentId, params) {
|
|
1332
|
+
const { user_id, ...patch } = params;
|
|
1333
|
+
return http.request("PATCH", `/agents/${agentId}`, {
|
|
1334
|
+
body: toBody(patch),
|
|
1335
|
+
query: toQuery({ user_id })
|
|
1336
|
+
});
|
|
1337
|
+
},
|
|
1338
|
+
async delete(agentId, params = {}) {
|
|
1339
|
+
await http.request("DELETE", `/agents/${agentId}`, { query: toQuery(params) });
|
|
1340
|
+
},
|
|
1341
|
+
enableWebhook(agentId) {
|
|
1342
|
+
return http.request("POST", `/agents/${agentId}/webhook`, { body: {} });
|
|
1343
|
+
},
|
|
1344
|
+
async disableWebhook(agentId) {
|
|
1345
|
+
await http.request("DELETE", `/agents/${agentId}/webhook`);
|
|
1346
|
+
},
|
|
1347
|
+
enableEmailInbox(agentId) {
|
|
1348
|
+
return http.request("POST", `/agents/${agentId}/email-inbox`, { body: {} });
|
|
1349
|
+
},
|
|
1350
|
+
async disableEmailInbox(agentId) {
|
|
1351
|
+
await http.request("DELETE", `/agents/${agentId}/email-inbox`);
|
|
1352
|
+
}
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// src/resources/apps.ts
|
|
1357
|
+
function createAppsResource(http) {
|
|
1358
|
+
const slug = (name) => encodeURIComponent(name);
|
|
1359
|
+
return {
|
|
1360
|
+
async list(params = {}) {
|
|
1361
|
+
const res = await http.request("GET", "/apps/", {
|
|
1362
|
+
query: toQuery({ user_id: params.user_id })
|
|
1363
|
+
});
|
|
1364
|
+
return new Page(res?.data ?? [], res?.has_more ?? false);
|
|
1365
|
+
},
|
|
1366
|
+
async isConnected(appName, params = {}) {
|
|
1367
|
+
const { data } = await this.list(params);
|
|
1368
|
+
return data.find((a) => a.name === appName)?.connected ?? false;
|
|
1369
|
+
},
|
|
1370
|
+
connectOauth(appName, params) {
|
|
1371
|
+
return http.request("POST", `/apps/${slug(appName)}/connect`, {
|
|
1372
|
+
body: toBody({ ...params })
|
|
1373
|
+
});
|
|
1374
|
+
},
|
|
1375
|
+
connectApiKey(appName, params) {
|
|
1376
|
+
return http.request("POST", `/apps/${slug(appName)}/connect/api-key`, {
|
|
1377
|
+
body: toBody({ ...params })
|
|
1378
|
+
});
|
|
1379
|
+
},
|
|
1380
|
+
connectComplete(appName, params) {
|
|
1381
|
+
return http.request("POST", `/apps/${slug(appName)}/connect/complete`, {
|
|
1382
|
+
body: toBody({ ...params })
|
|
1383
|
+
});
|
|
1384
|
+
},
|
|
1385
|
+
async disconnect(appName, params = {}) {
|
|
1386
|
+
await http.request("DELETE", `/apps/${slug(appName)}/connections`, { query: toQuery(params) });
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
// src/streaming.ts
|
|
1392
|
+
var RunStream = class {
|
|
1393
|
+
source;
|
|
1394
|
+
raiseOnError;
|
|
1395
|
+
state = initialConversationState;
|
|
1396
|
+
textChunks = [];
|
|
1397
|
+
errorMessages = [];
|
|
1398
|
+
runIdValue = null;
|
|
1399
|
+
consumed = false;
|
|
1400
|
+
constructor(source, options = {}) {
|
|
1401
|
+
this.source = source;
|
|
1402
|
+
this.raiseOnError = options.raiseOnError ?? false;
|
|
1403
|
+
}
|
|
1404
|
+
async *[Symbol.asyncIterator]() {
|
|
1405
|
+
if (this.consumed) {
|
|
1406
|
+
throw new Error(
|
|
1407
|
+
"RunStream has already been consumed. A stream is single-pass \u2014 iterate once, then read .text / .state / .errors, or call runs.get(runId) to re-read the result."
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1410
|
+
this.consumed = true;
|
|
1411
|
+
try {
|
|
1412
|
+
for await (const event of this.source) {
|
|
1413
|
+
this.state = accumulate(this.state, event);
|
|
1414
|
+
if (event.type === "text-delta") this.textChunks.push(event.delta);
|
|
1415
|
+
if (event.type === "run-start" && event.runId !== null) this.runIdValue = event.runId;
|
|
1416
|
+
if (event.type === "run-error") this.errorMessages.push(event.message || event.error);
|
|
1417
|
+
yield event;
|
|
1418
|
+
}
|
|
1419
|
+
} finally {
|
|
1420
|
+
await this.source.return(void 0).catch(() => void 0);
|
|
1421
|
+
}
|
|
1422
|
+
if (this.raiseOnError && this.errorMessages.length > 0) {
|
|
1423
|
+
throw new RunFailedError(`Run failed: ${this.errorMessages.join("; ")}`, {
|
|
1424
|
+
type: "run_failed",
|
|
1425
|
+
code: 0,
|
|
1426
|
+
status: 0,
|
|
1427
|
+
details: { errors: this.errorMessages }
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
/** Yield only the assistant's text, in order. The 90% case for a server. */
|
|
1432
|
+
async *iterText() {
|
|
1433
|
+
for await (const event of this) {
|
|
1434
|
+
if (event.type === "text-delta") yield event.delta;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
/** Drain the stream and return the full assistant text. */
|
|
1438
|
+
async text() {
|
|
1439
|
+
for await (const _ of this) {
|
|
1440
|
+
}
|
|
1441
|
+
return this.textChunks.join("");
|
|
1442
|
+
}
|
|
1443
|
+
/** Accumulated text so far (complete once iteration finishes). */
|
|
1444
|
+
get output() {
|
|
1445
|
+
return this.textChunks.join("");
|
|
1446
|
+
}
|
|
1447
|
+
/** Run id, available as soon as the first `run-start` event arrives. */
|
|
1448
|
+
get runId() {
|
|
1449
|
+
return this.runIdValue;
|
|
1450
|
+
}
|
|
1451
|
+
/** Error messages the run emitted. Check this, or pass `raiseOnError`. */
|
|
1452
|
+
get errors() {
|
|
1453
|
+
return [...this.errorMessages];
|
|
1454
|
+
}
|
|
1455
|
+
get hasErrors() {
|
|
1456
|
+
return this.errorMessages.length > 0;
|
|
1457
|
+
}
|
|
1458
|
+
/** Full normalized conversation: messages, tool calls, notices, status. */
|
|
1459
|
+
get conversation() {
|
|
1460
|
+
return this.state;
|
|
1461
|
+
}
|
|
1462
|
+
/** Close the underlying response without draining it. */
|
|
1463
|
+
async close() {
|
|
1464
|
+
await this.source.return(void 0).catch(() => void 0);
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
|
|
1468
|
+
// src/resources/runs.ts
|
|
1469
|
+
function items(payload) {
|
|
1470
|
+
return Array.isArray(payload) ? payload : payload?.data ?? [];
|
|
1471
|
+
}
|
|
1472
|
+
function createRunsResource(http) {
|
|
1473
|
+
const createBody = (p, stream) => {
|
|
1474
|
+
const { agent_id, teammate_id, ...rest } = p;
|
|
1475
|
+
return toBody({ ...rest, teammate_id: resolveAgentId(teammate_id, agent_id), stream });
|
|
1476
|
+
};
|
|
1477
|
+
return {
|
|
1478
|
+
create(params, options) {
|
|
1479
|
+
return new RunStream(http.stream("POST", "/runs", { body: createBody(params, true) }), options);
|
|
1480
|
+
},
|
|
1481
|
+
createAsync(params) {
|
|
1482
|
+
return http.request("POST", "/runs", { body: createBody(params, false) });
|
|
1483
|
+
},
|
|
1484
|
+
stream(runId, options) {
|
|
1485
|
+
return new RunStream(http.stream("GET", `/runs/${runId}/stream`), options);
|
|
1486
|
+
},
|
|
1487
|
+
reply(runId, message, options) {
|
|
1488
|
+
return new RunStream(http.stream("POST", `/runs/${runId}/reply`, { body: { message } }), options);
|
|
1489
|
+
},
|
|
1490
|
+
get(runId) {
|
|
1491
|
+
return http.request("GET", `/runs/${runId}`);
|
|
1492
|
+
},
|
|
1493
|
+
async list(params = {}) {
|
|
1494
|
+
const { agent_id, teammate_id, ...rest } = params;
|
|
1495
|
+
const q = toBody({ ...rest, teammate_id: resolveAgentId(teammate_id, agent_id) });
|
|
1496
|
+
const fetchPage = async (p) => {
|
|
1497
|
+
const res = await http.request("GET", "/runs", {
|
|
1498
|
+
query: toQuery(p)
|
|
1499
|
+
});
|
|
1500
|
+
return new Page(
|
|
1501
|
+
res?.data ?? [],
|
|
1502
|
+
res?.has_more ?? false,
|
|
1503
|
+
(starting_after) => fetchPage({ ...p, starting_after })
|
|
1504
|
+
);
|
|
1505
|
+
};
|
|
1506
|
+
return fetchPage(q);
|
|
1507
|
+
},
|
|
1508
|
+
cancel(runId) {
|
|
1509
|
+
return http.request("POST", `/runs/${runId}/cancel`, { body: {} });
|
|
1510
|
+
},
|
|
1511
|
+
approve(runId, params) {
|
|
1512
|
+
return http.request("POST", `/runs/${runId}/approve`, {
|
|
1513
|
+
body: { remember: false, ...params }
|
|
1514
|
+
});
|
|
1515
|
+
},
|
|
1516
|
+
answer(runId, params) {
|
|
1517
|
+
return http.request("POST", `/runs/${runId}/answer`, {
|
|
1518
|
+
body: { answers: params.answers }
|
|
1519
|
+
});
|
|
1520
|
+
},
|
|
1521
|
+
async permissions(runId) {
|
|
1522
|
+
return items(await http.request("GET", `/runs/${runId}/permissions`));
|
|
1523
|
+
},
|
|
1524
|
+
outcome(runId) {
|
|
1525
|
+
return http.request("GET", `/runs/${runId}/outcome`);
|
|
1526
|
+
},
|
|
1527
|
+
async files(runId) {
|
|
1528
|
+
return items(await http.request("GET", `/runs/${runId}/files`));
|
|
1529
|
+
},
|
|
1530
|
+
async downloadFile(runId, filename) {
|
|
1531
|
+
const res = await http.raw("GET", `/runs/${runId}/files/${encodeURIComponent(filename)}/download`, {
|
|
1532
|
+
headers: { accept: "application/octet-stream" }
|
|
1533
|
+
});
|
|
1534
|
+
return res.arrayBuffer();
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
// src/resources/settings.ts
|
|
1540
|
+
function createSettingsResource(http) {
|
|
1541
|
+
return {
|
|
1542
|
+
get() {
|
|
1543
|
+
return http.request("GET", "/settings/");
|
|
1544
|
+
},
|
|
1545
|
+
// `null` must survive (it CLEARS a cap); only `undefined` is dropped.
|
|
1546
|
+
update(params) {
|
|
1547
|
+
return http.request("PATCH", "/settings/", { body: toBody({ ...params }) });
|
|
1548
|
+
}
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
// src/resources/tasks.ts
|
|
1553
|
+
function createTasksResource(http) {
|
|
1554
|
+
const triggers = {
|
|
1555
|
+
create(taskId, params) {
|
|
1556
|
+
return http.request("POST", `/tasks/${taskId}/triggers/`, {
|
|
1557
|
+
body: toBody({ timezone: "UTC", ...params })
|
|
1558
|
+
});
|
|
1559
|
+
},
|
|
1560
|
+
async list(taskId) {
|
|
1561
|
+
const res = await http.request(
|
|
1562
|
+
"GET",
|
|
1563
|
+
`/tasks/${taskId}/triggers/`
|
|
1564
|
+
);
|
|
1565
|
+
return Array.isArray(res) ? res : res?.data ?? [];
|
|
1566
|
+
},
|
|
1567
|
+
update(taskId, triggerId, params) {
|
|
1568
|
+
return http.request("PATCH", `/tasks/${taskId}/triggers/${triggerId}`, {
|
|
1569
|
+
body: toBody({ ...params })
|
|
1570
|
+
});
|
|
1571
|
+
},
|
|
1572
|
+
async delete(taskId, triggerId) {
|
|
1573
|
+
await http.request("DELETE", `/tasks/${taskId}/triggers/${triggerId}`);
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
return {
|
|
1577
|
+
triggers,
|
|
1578
|
+
create(params) {
|
|
1579
|
+
const { agent_id, teammate_id, ...rest } = params;
|
|
1580
|
+
return http.request("POST", "/tasks/", {
|
|
1581
|
+
body: toBody({ ...rest, teammate_id: resolveAgentId(teammate_id, agent_id) })
|
|
1582
|
+
});
|
|
1583
|
+
},
|
|
1584
|
+
async list(params = {}) {
|
|
1585
|
+
const { agent_id, teammate_id, ...rest } = params;
|
|
1586
|
+
const q = toBody({ ...rest, teammate_id: resolveAgentId(teammate_id, agent_id) });
|
|
1587
|
+
const fetchPage = async (p) => {
|
|
1588
|
+
const res = await http.request("GET", "/tasks/", {
|
|
1589
|
+
query: toQuery(p)
|
|
1590
|
+
});
|
|
1591
|
+
return new Page(
|
|
1592
|
+
res?.data ?? [],
|
|
1593
|
+
res?.has_more ?? false,
|
|
1594
|
+
(starting_after) => fetchPage({ ...p, starting_after })
|
|
1595
|
+
);
|
|
1596
|
+
};
|
|
1597
|
+
return fetchPage(q);
|
|
1598
|
+
},
|
|
1599
|
+
get(taskId, params = {}) {
|
|
1600
|
+
return http.request("GET", `/tasks/${taskId}`, { query: toQuery(params) });
|
|
1601
|
+
},
|
|
1602
|
+
update(taskId, params) {
|
|
1603
|
+
const { user_id, ...patch } = params;
|
|
1604
|
+
return http.request("PATCH", `/tasks/${taskId}`, {
|
|
1605
|
+
body: toBody(patch),
|
|
1606
|
+
query: toQuery({ user_id })
|
|
1607
|
+
});
|
|
1608
|
+
},
|
|
1609
|
+
async delete(taskId, params = {}) {
|
|
1610
|
+
await http.request("DELETE", `/tasks/${taskId}`, { query: toQuery(params) });
|
|
1611
|
+
},
|
|
1612
|
+
run(taskId, params = {}, options) {
|
|
1613
|
+
return new RunStream(
|
|
1614
|
+
http.stream("POST", `/tasks/${taskId}/runs`, { body: toBody({ ...params, stream: true }) }),
|
|
1615
|
+
options
|
|
1616
|
+
);
|
|
1617
|
+
},
|
|
1618
|
+
runAsync(taskId, params = {}) {
|
|
1619
|
+
return http.request("POST", `/tasks/${taskId}/runs`, {
|
|
1620
|
+
body: toBody({ ...params, stream: false })
|
|
1621
|
+
});
|
|
1622
|
+
},
|
|
1623
|
+
enableWebhook(taskId) {
|
|
1624
|
+
return http.request("POST", `/tasks/${taskId}/webhook`, { body: {} });
|
|
1625
|
+
},
|
|
1626
|
+
async disableWebhook(taskId) {
|
|
1627
|
+
await http.request("DELETE", `/tasks/${taskId}/webhook`);
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
// src/resources/users.ts
|
|
1633
|
+
function pager(http, path) {
|
|
1634
|
+
const fetchPage = async (p) => {
|
|
1635
|
+
const res = await http.request("GET", path, {
|
|
1636
|
+
query: toQuery(p)
|
|
1637
|
+
});
|
|
1638
|
+
return new Page(
|
|
1639
|
+
res?.data ?? [],
|
|
1640
|
+
res?.has_more ?? false,
|
|
1641
|
+
(starting_after) => fetchPage({ ...p, starting_after })
|
|
1642
|
+
);
|
|
1643
|
+
};
|
|
1644
|
+
return fetchPage;
|
|
1645
|
+
}
|
|
1646
|
+
function createUsersResource(http) {
|
|
1647
|
+
return {
|
|
1648
|
+
create(params) {
|
|
1649
|
+
return http.request("POST", "/users/", { body: toBody({ ...params }) });
|
|
1650
|
+
},
|
|
1651
|
+
list(params = {}) {
|
|
1652
|
+
return pager(http, "/users/")({ ...params });
|
|
1653
|
+
},
|
|
1654
|
+
get(userId) {
|
|
1655
|
+
return http.request("GET", `/users/${encodeURIComponent(userId)}`);
|
|
1656
|
+
},
|
|
1657
|
+
update(userId, params) {
|
|
1658
|
+
return http.request("PATCH", `/users/${encodeURIComponent(userId)}`, {
|
|
1659
|
+
body: toBody({ ...params })
|
|
1660
|
+
});
|
|
1661
|
+
},
|
|
1662
|
+
async delete(userId) {
|
|
1663
|
+
await http.request("DELETE", `/users/${encodeURIComponent(userId)}`);
|
|
1664
|
+
},
|
|
1665
|
+
usage(params = {}) {
|
|
1666
|
+
return pager(http, "/usage/end-users")({ ...params });
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
function verifySignature(body, headers, secret, options = {}) {
|
|
1671
|
+
const get = (name) => {
|
|
1672
|
+
if (typeof headers.get === "function") {
|
|
1673
|
+
return headers.get(name) ?? void 0;
|
|
1674
|
+
}
|
|
1675
|
+
const lower = Object.fromEntries(
|
|
1676
|
+
Object.entries(headers).map(([k, v]) => [
|
|
1677
|
+
k.toLowerCase(),
|
|
1678
|
+
Array.isArray(v) ? v[0] : v
|
|
1679
|
+
])
|
|
1680
|
+
);
|
|
1681
|
+
return lower[name];
|
|
1682
|
+
};
|
|
1683
|
+
const webhookId = get("webhook-id");
|
|
1684
|
+
const timestamp = get("webhook-timestamp");
|
|
1685
|
+
const signature = get("webhook-signature");
|
|
1686
|
+
if (!webhookId || !timestamp || !signature) return false;
|
|
1687
|
+
if (options.toleranceSeconds !== void 0) {
|
|
1688
|
+
const ts = Number.parseInt(timestamp, 10);
|
|
1689
|
+
if (!Number.isFinite(ts)) return false;
|
|
1690
|
+
const now = options.now ? options.now() : Math.floor(Date.now() / 1e3);
|
|
1691
|
+
if (Math.abs(now - ts) > options.toleranceSeconds) return false;
|
|
1692
|
+
}
|
|
1693
|
+
const raw = typeof body === "string" ? body : new TextDecoder().decode(body);
|
|
1694
|
+
const expected = `v1=${crypto.createHmac("sha256", secret).update(`${webhookId}.${timestamp}.${raw}`).digest("hex")}`;
|
|
1695
|
+
const a = Buffer.from(expected);
|
|
1696
|
+
const b = Buffer.from(signature);
|
|
1697
|
+
return a.length === b.length && crypto.timingSafeEqual(a, b);
|
|
1698
|
+
}
|
|
1699
|
+
function createWebhooksResource(http) {
|
|
1700
|
+
return {
|
|
1701
|
+
verifySignature,
|
|
1702
|
+
create(params) {
|
|
1703
|
+
return http.request("POST", "/webhooks/", { body: toBody({ ...params }) });
|
|
1704
|
+
},
|
|
1705
|
+
list(params = {}) {
|
|
1706
|
+
return pager(http, "/webhooks/")({ ...params });
|
|
1707
|
+
},
|
|
1708
|
+
get(webhookId) {
|
|
1709
|
+
return http.request("GET", `/webhooks/${webhookId}`);
|
|
1710
|
+
},
|
|
1711
|
+
update(webhookId, params) {
|
|
1712
|
+
return http.request("PATCH", `/webhooks/${webhookId}`, { body: toBody({ ...params }) });
|
|
1713
|
+
},
|
|
1714
|
+
async delete(webhookId) {
|
|
1715
|
+
await http.request("DELETE", `/webhooks/${webhookId}`);
|
|
1716
|
+
},
|
|
1717
|
+
listDeliveries(webhookId, params = {}) {
|
|
1718
|
+
return pager(http, `/webhooks/${webhookId}/deliveries`)({ ...params });
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
// src/index.ts
|
|
1724
|
+
var M8TES_SDK_VERSION = "0.1.0-alpha.1";
|
|
1725
|
+
var M8tes = class {
|
|
1726
|
+
runs;
|
|
1727
|
+
agents;
|
|
1728
|
+
/** Permanent alias for `agents` — the DB model and older docs say "teammate". */
|
|
1729
|
+
teammates;
|
|
1730
|
+
tasks;
|
|
1731
|
+
users;
|
|
1732
|
+
apps;
|
|
1733
|
+
webhooks;
|
|
1734
|
+
settings;
|
|
1735
|
+
/** The underlying transport. Use it to call an endpoint this version does not wrap yet. */
|
|
1736
|
+
http;
|
|
1737
|
+
constructor(options = {}) {
|
|
1738
|
+
this.http = createHttp(options);
|
|
1739
|
+
this.runs = createRunsResource(this.http);
|
|
1740
|
+
this.agents = createAgentsResource(this.http);
|
|
1741
|
+
this.teammates = this.agents;
|
|
1742
|
+
this.tasks = createTasksResource(this.http);
|
|
1743
|
+
this.users = createUsersResource(this.http);
|
|
1744
|
+
this.apps = createAppsResource(this.http);
|
|
1745
|
+
this.webhooks = createWebhooksResource(this.http);
|
|
1746
|
+
this.settings = createSettingsResource(this.http);
|
|
1747
|
+
}
|
|
1748
|
+
};
|
|
1749
|
+
|
|
1750
|
+
exports.APIError = APIError;
|
|
1751
|
+
exports.AuthenticationError = AuthenticationError;
|
|
1752
|
+
exports.BillingError = BillingError;
|
|
1753
|
+
exports.ConflictError = ConflictError;
|
|
1754
|
+
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
1755
|
+
exports.M8TES_SDK_VERSION = M8TES_SDK_VERSION;
|
|
1756
|
+
exports.M8tes = M8tes;
|
|
1757
|
+
exports.M8tesApiError = M8tesApiError;
|
|
1758
|
+
exports.NotFoundError = NotFoundError;
|
|
1759
|
+
exports.PROTOCOL_VERSION = PROTOCOL_VERSION;
|
|
1760
|
+
exports.Page = Page;
|
|
1761
|
+
exports.PermissionDeniedError = PermissionDeniedError;
|
|
1762
|
+
exports.RateLimitError = RateLimitError;
|
|
1763
|
+
exports.RunFailedError = RunFailedError;
|
|
1764
|
+
exports.RunNotStreamingError = RunNotStreamingError;
|
|
1765
|
+
exports.RunStream = RunStream;
|
|
1766
|
+
exports.TERMINAL_EVENT_TYPES = TERMINAL_EVENT_TYPES;
|
|
1767
|
+
exports.ValidationError = ValidationError;
|
|
1768
|
+
exports.accumulate = accumulate;
|
|
1769
|
+
exports.createAccumulator = createAccumulator;
|
|
1770
|
+
exports.createHttp = createHttp;
|
|
1771
|
+
exports.createNormalizer = createNormalizer;
|
|
1772
|
+
exports.createSseDecoder = createSseDecoder;
|
|
1773
|
+
exports.errorClassForStatus = errorClassForStatus;
|
|
1774
|
+
exports.errorFromResponse = errorFromResponse;
|
|
1775
|
+
exports.initialConversationState = initialConversationState;
|
|
1776
|
+
exports.isTerminalEvent = isTerminalEvent;
|
|
1777
|
+
exports.parseErrorEnvelope = parseErrorEnvelope;
|
|
1778
|
+
exports.parseRetryAfter = parseRetryAfter;
|
|
1779
|
+
exports.parseSse = parseSse;
|
|
1780
|
+
exports.splitConcatenatedJson = splitConcatenatedJson;
|
|
1781
|
+
exports.verifySignature = verifySignature;
|
|
1782
|
+
//# sourceMappingURL=index.cjs.map
|
|
1783
|
+
//# sourceMappingURL=index.cjs.map
|