@runtypelabs/sdk 9.2.1 → 9.3.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.
- package/dist/index.cjs +205 -12
- package/dist/index.d.cts +336 -13
- package/dist/index.d.ts +336 -13
- package/dist/index.mjs +202 -12
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4757,7 +4757,8 @@ var AGENT_CONFIG_KEYS = [
|
|
|
4757
4757
|
"temporal",
|
|
4758
4758
|
"memory",
|
|
4759
4759
|
"sandbox",
|
|
4760
|
-
"tenancyStrategy"
|
|
4760
|
+
"tenancyStrategy",
|
|
4761
|
+
"durability"
|
|
4761
4762
|
];
|
|
4762
4763
|
var AGENT_CONFIG_KEY_LIST = [...AGENT_CONFIG_KEYS].sort();
|
|
4763
4764
|
function isPlainObject2(value) {
|
|
@@ -6327,10 +6328,151 @@ var Runtype = class {
|
|
|
6327
6328
|
|
|
6328
6329
|
// src/version.ts
|
|
6329
6330
|
var FALLBACK_VERSION = "0.0.0";
|
|
6330
|
-
var SDK_VERSION = "9.
|
|
6331
|
+
var SDK_VERSION = "9.3.0".length > 0 ? "9.3.0" : FALLBACK_VERSION;
|
|
6331
6332
|
var RUNTYPE_CLIENT_KIND = "sdk";
|
|
6332
6333
|
var SDK_USER_AGENT = `runtype-sdk/${SDK_VERSION} (typescript)`;
|
|
6333
6334
|
|
|
6335
|
+
// src/detached-reconnect.ts
|
|
6336
|
+
var TERMINAL_EVENTS = /* @__PURE__ */ new Set(["execution_complete", "execution_error"]);
|
|
6337
|
+
var DEFAULT_MAX_DETACHED_RECONNECTS = 12;
|
|
6338
|
+
function observeBlock(block, into) {
|
|
6339
|
+
let eventName = null;
|
|
6340
|
+
for (const line of block.split("\n")) {
|
|
6341
|
+
if (line.startsWith("id:")) {
|
|
6342
|
+
into.lastId = line.slice(3).trim();
|
|
6343
|
+
continue;
|
|
6344
|
+
}
|
|
6345
|
+
if (line.startsWith("event:")) {
|
|
6346
|
+
eventName = line.slice(6).trim();
|
|
6347
|
+
continue;
|
|
6348
|
+
}
|
|
6349
|
+
if (!line.startsWith("data:")) continue;
|
|
6350
|
+
const raw = line.slice(5).trim();
|
|
6351
|
+
if (!raw || raw === "[DONE]") continue;
|
|
6352
|
+
let payload;
|
|
6353
|
+
try {
|
|
6354
|
+
const parsed = JSON.parse(raw);
|
|
6355
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) continue;
|
|
6356
|
+
payload = parsed;
|
|
6357
|
+
} catch {
|
|
6358
|
+
continue;
|
|
6359
|
+
}
|
|
6360
|
+
if (typeof payload.executionId === "string") into.executionId = payload.executionId;
|
|
6361
|
+
const type = typeof payload.type === "string" ? payload.type : eventName;
|
|
6362
|
+
if (type && TERMINAL_EVENTS.has(type)) into.sawTerminal = true;
|
|
6363
|
+
if (type === "await" && payload.awaitReason === "detached") into.sawDetach = true;
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
function withDetachedReconnect(response, reattach, options = {}) {
|
|
6367
|
+
if (options.autoReconnect === false) return response;
|
|
6368
|
+
if (!response.ok || !response.body) return response;
|
|
6369
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
6370
|
+
if (!contentType.includes("text/event-stream")) return response;
|
|
6371
|
+
const maxReconnects = options.maxReconnects ?? DEFAULT_MAX_DETACHED_RECONNECTS;
|
|
6372
|
+
const reconnectDelayMs = options.reconnectDelayMs ?? 0;
|
|
6373
|
+
const encoder = new TextEncoder();
|
|
6374
|
+
const decoder = new TextDecoder();
|
|
6375
|
+
const abort = new AbortController();
|
|
6376
|
+
let cancelled = false;
|
|
6377
|
+
let activeReader = null;
|
|
6378
|
+
const stream = new ReadableStream({
|
|
6379
|
+
async start(controller) {
|
|
6380
|
+
const observed = {
|
|
6381
|
+
lastId: null,
|
|
6382
|
+
executionId: null,
|
|
6383
|
+
sawTerminal: false,
|
|
6384
|
+
sawDetach: false
|
|
6385
|
+
};
|
|
6386
|
+
let current = response;
|
|
6387
|
+
let legs = 0;
|
|
6388
|
+
const enqueue = (chunk) => {
|
|
6389
|
+
if (cancelled) return;
|
|
6390
|
+
controller.enqueue(chunk);
|
|
6391
|
+
};
|
|
6392
|
+
try {
|
|
6393
|
+
while (!cancelled && current?.body) {
|
|
6394
|
+
const reader = current.body.getReader();
|
|
6395
|
+
activeReader = reader;
|
|
6396
|
+
let buffer = "";
|
|
6397
|
+
observed.sawDetach = false;
|
|
6398
|
+
for (; ; ) {
|
|
6399
|
+
const { value, done } = await reader.read();
|
|
6400
|
+
if (cancelled) break;
|
|
6401
|
+
if (value) {
|
|
6402
|
+
enqueue(value);
|
|
6403
|
+
buffer += decoder.decode(value, { stream: !done });
|
|
6404
|
+
let boundary = buffer.indexOf("\n\n");
|
|
6405
|
+
while (boundary >= 0) {
|
|
6406
|
+
observeBlock(buffer.slice(0, boundary), observed);
|
|
6407
|
+
buffer = buffer.slice(boundary + 2);
|
|
6408
|
+
boundary = buffer.indexOf("\n\n");
|
|
6409
|
+
}
|
|
6410
|
+
}
|
|
6411
|
+
if (done) break;
|
|
6412
|
+
}
|
|
6413
|
+
activeReader = null;
|
|
6414
|
+
if (cancelled) break;
|
|
6415
|
+
if (buffer.trim()) observeBlock(buffer, observed);
|
|
6416
|
+
if (observed.sawTerminal || !observed.sawDetach) break;
|
|
6417
|
+
if (!observed.executionId || legs >= maxReconnects) break;
|
|
6418
|
+
legs += 1;
|
|
6419
|
+
if (reconnectDelayMs > 0) {
|
|
6420
|
+
await new Promise((resolve) => setTimeout(resolve, reconnectDelayMs));
|
|
6421
|
+
}
|
|
6422
|
+
if (cancelled) break;
|
|
6423
|
+
current = await reattach({
|
|
6424
|
+
executionId: observed.executionId,
|
|
6425
|
+
// `'0'` replays the whole turn — the fail-open answer for a leg
|
|
6426
|
+
// that produced no cursor at all.
|
|
6427
|
+
after: observed.lastId ?? "0",
|
|
6428
|
+
signal: abort.signal
|
|
6429
|
+
});
|
|
6430
|
+
if (cancelled) {
|
|
6431
|
+
await current?.body?.cancel().catch(() => {
|
|
6432
|
+
});
|
|
6433
|
+
break;
|
|
6434
|
+
}
|
|
6435
|
+
if (!current || !current.ok || !current.body) {
|
|
6436
|
+
enqueue(
|
|
6437
|
+
encoder.encode(
|
|
6438
|
+
`event: error
|
|
6439
|
+
data: ${JSON.stringify({
|
|
6440
|
+
type: "error",
|
|
6441
|
+
executionId: observed.executionId,
|
|
6442
|
+
error: {
|
|
6443
|
+
code: "detached_reconnect_failed",
|
|
6444
|
+
message: "The agent detached and this client could not rejoin its stream. The execution is still running; reattach with the events route."
|
|
6445
|
+
},
|
|
6446
|
+
recoverable: false
|
|
6447
|
+
})}
|
|
6448
|
+
|
|
6449
|
+
`
|
|
6450
|
+
)
|
|
6451
|
+
);
|
|
6452
|
+
break;
|
|
6453
|
+
}
|
|
6454
|
+
}
|
|
6455
|
+
} finally {
|
|
6456
|
+
activeReader = null;
|
|
6457
|
+
if (!cancelled) controller.close();
|
|
6458
|
+
}
|
|
6459
|
+
},
|
|
6460
|
+
async cancel(reason) {
|
|
6461
|
+
cancelled = true;
|
|
6462
|
+
abort.abort(reason);
|
|
6463
|
+
const reader = activeReader;
|
|
6464
|
+
activeReader = null;
|
|
6465
|
+
if (reader) await reader.cancel(reason).catch(() => {
|
|
6466
|
+
});
|
|
6467
|
+
}
|
|
6468
|
+
});
|
|
6469
|
+
return new Response(stream, {
|
|
6470
|
+
status: response.status,
|
|
6471
|
+
statusText: response.statusText,
|
|
6472
|
+
headers: response.headers
|
|
6473
|
+
});
|
|
6474
|
+
}
|
|
6475
|
+
|
|
6334
6476
|
// src/generated-tool-gate.ts
|
|
6335
6477
|
var TOOL_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_]{1,63}$/;
|
|
6336
6478
|
var DEFAULT_MAX_CODE_LENGTH = 12e3;
|
|
@@ -9711,6 +9853,14 @@ function appendRuntimeToolsToAgentRequest(request6, runtimeTools) {
|
|
|
9711
9853
|
}
|
|
9712
9854
|
};
|
|
9713
9855
|
}
|
|
9856
|
+
function buildAgentAdmissionHeaders(options) {
|
|
9857
|
+
if (!options) return {};
|
|
9858
|
+
const headers = {};
|
|
9859
|
+
if (options.concurrency) headers["x-runtype-concurrency"] = options.concurrency;
|
|
9860
|
+
if (options.coalesce) headers["x-runtype-coalesce"] = "true";
|
|
9861
|
+
if (options.idempotencyKey) headers["idempotency-key"] = options.idempotencyKey;
|
|
9862
|
+
return headers;
|
|
9863
|
+
}
|
|
9714
9864
|
var _AgentsEndpoint = class _AgentsEndpoint {
|
|
9715
9865
|
constructor(client) {
|
|
9716
9866
|
this.client = client;
|
|
@@ -9802,18 +9952,22 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
9802
9952
|
/**
|
|
9803
9953
|
* Execute an agent (non-streaming)
|
|
9804
9954
|
*/
|
|
9805
|
-
async execute(id, data) {
|
|
9806
|
-
return this.client.post(
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9955
|
+
async execute(id, data, options) {
|
|
9956
|
+
return this.client.post(
|
|
9957
|
+
`/agents/${id}/execute`,
|
|
9958
|
+
{
|
|
9959
|
+
...data,
|
|
9960
|
+
streamResponse: false
|
|
9961
|
+
},
|
|
9962
|
+
buildAgentAdmissionHeaders(options)
|
|
9963
|
+
);
|
|
9810
9964
|
}
|
|
9811
9965
|
/** Start an agent execution and return its durable handle immediately. */
|
|
9812
|
-
async executeAsync(id, data) {
|
|
9966
|
+
async executeAsync(id, data, options) {
|
|
9813
9967
|
return this.client.post(
|
|
9814
9968
|
`/agents/${id}/execute`,
|
|
9815
9969
|
{ ...data, streamResponse: false },
|
|
9816
|
-
{ Prefer: "respond-async" }
|
|
9970
|
+
{ Prefer: "respond-async", ...buildAgentAdmissionHeaders(options) }
|
|
9817
9971
|
);
|
|
9818
9972
|
}
|
|
9819
9973
|
/**
|
|
@@ -9835,14 +9989,42 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
9835
9989
|
* ```
|
|
9836
9990
|
*/
|
|
9837
9991
|
async executeStream(id, data, init) {
|
|
9838
|
-
|
|
9992
|
+
const admissionHeaders = buildAgentAdmissionHeaders(init);
|
|
9993
|
+
const response = await this.client.requestStream(`/agents/${id}/execute`, {
|
|
9839
9994
|
method: "POST",
|
|
9840
9995
|
body: JSON.stringify({
|
|
9841
9996
|
...data,
|
|
9842
9997
|
streamResponse: true
|
|
9843
9998
|
}),
|
|
9999
|
+
...Object.keys(admissionHeaders).length > 0 ? { headers: admissionHeaders } : {},
|
|
9844
10000
|
...init?.signal ? { signal: init.signal } : {}
|
|
9845
10001
|
});
|
|
10002
|
+
return withDetachedReconnect(
|
|
10003
|
+
response,
|
|
10004
|
+
this.buildDetachedReattach(id, data, init?.signal),
|
|
10005
|
+
init ?? {}
|
|
10006
|
+
);
|
|
10007
|
+
}
|
|
10008
|
+
/**
|
|
10009
|
+
* The `?after=` reattach leg every durable agent stream is followed with.
|
|
10010
|
+
*
|
|
10011
|
+
* Shared by `executeStream` and by the local-tool loop's RESUME leg: a
|
|
10012
|
+
* durable resume answers on the same watch-lease contract as the original
|
|
10013
|
+
* execute, so its socket can close on `awaitReason: 'detached'` too. Building
|
|
10014
|
+
* it once is what keeps the two from drifting into different cursor or
|
|
10015
|
+
* conversation-key behavior.
|
|
10016
|
+
*/
|
|
10017
|
+
buildDetachedReattach(id, data, signal) {
|
|
10018
|
+
return async ({ executionId, after }) => {
|
|
10019
|
+
const named = data?.conversationId;
|
|
10020
|
+
const conversationId = typeof named === "string" ? named : "";
|
|
10021
|
+
const query = new URLSearchParams({ after });
|
|
10022
|
+
if (conversationId) query.set("conversationId", conversationId);
|
|
10023
|
+
return this.client.requestStream(`/agents/${id}/executions/${executionId}/events?${query.toString()}`, {
|
|
10024
|
+
method: "GET",
|
|
10025
|
+
...signal ? { signal } : {}
|
|
10026
|
+
}).catch(() => null);
|
|
10027
|
+
};
|
|
9846
10028
|
}
|
|
9847
10029
|
/**
|
|
9848
10030
|
* Execute an agent with streaming and callbacks
|
|
@@ -10006,7 +10188,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
10006
10188
|
callbacks?.onTurnComplete?.(event);
|
|
10007
10189
|
},
|
|
10008
10190
|
onAgentPaused: (event) => {
|
|
10009
|
-
pausedEvent = event;
|
|
10191
|
+
if (event.awaitReason !== "detached") pausedEvent = event;
|
|
10010
10192
|
callbacks?.onAgentPaused?.(event);
|
|
10011
10193
|
},
|
|
10012
10194
|
onAgentComplete: (event) => {
|
|
@@ -10187,7 +10369,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
10187
10369
|
}
|
|
10188
10370
|
let resumeResponse;
|
|
10189
10371
|
try {
|
|
10190
|
-
|
|
10372
|
+
const rawResumeResponse = await this.client.requestStream(`/agents/${id}/resume`, {
|
|
10191
10373
|
method: "POST",
|
|
10192
10374
|
body: JSON.stringify({
|
|
10193
10375
|
executionId,
|
|
@@ -10197,6 +10379,11 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
10197
10379
|
}),
|
|
10198
10380
|
...abortSignal ? { signal: abortSignal } : {}
|
|
10199
10381
|
});
|
|
10382
|
+
resumeResponse = withDetachedReconnect(
|
|
10383
|
+
rawResumeResponse,
|
|
10384
|
+
this.buildDetachedReattach(id, data, abortSignal),
|
|
10385
|
+
{}
|
|
10386
|
+
);
|
|
10200
10387
|
} catch (error) {
|
|
10201
10388
|
if (abortSignal?.aborted) return finishAborted(executionId);
|
|
10202
10389
|
throw error;
|
|
@@ -14258,6 +14445,7 @@ export {
|
|
|
14258
14445
|
CollectionsEndpoint,
|
|
14259
14446
|
ContextTemplatesEndpoint,
|
|
14260
14447
|
ConversationsEndpoint,
|
|
14448
|
+
DEFAULT_MAX_DETACHED_RECONNECTS,
|
|
14261
14449
|
DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS,
|
|
14262
14450
|
DEFAULT_STALL_STOP_AFTER,
|
|
14263
14451
|
DispatchEndpoint,
|
|
@@ -14316,6 +14504,7 @@ export {
|
|
|
14316
14504
|
UsersEndpoint,
|
|
14317
14505
|
applyGeneratedRuntimeToolProposalToDispatchRequest,
|
|
14318
14506
|
attachRuntimeToolsToDispatchRequest,
|
|
14507
|
+
buildAgentAdmissionHeaders,
|
|
14319
14508
|
buildEmptySessionNudge,
|
|
14320
14509
|
buildGeneratedRuntimeToolGateOutput,
|
|
14321
14510
|
buildLedgerOffloadReference,
|
|
@@ -14405,5 +14594,6 @@ export {
|
|
|
14405
14594
|
unregisterWorkflowHook,
|
|
14406
14595
|
usedNoTools,
|
|
14407
14596
|
validJson,
|
|
14597
|
+
withDetachedReconnect,
|
|
14408
14598
|
withUnifiedEvents
|
|
14409
14599
|
};
|
package/package.json
CHANGED