@dudousxd/nestjs-agent-core 0.37.0 → 0.38.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/README.md +2 -2
- package/dist/ag-ui/index.cjs.map +1 -1
- package/dist/ag-ui/index.d.cts +1 -1
- package/dist/ag-ui/index.d.ts +1 -1
- package/dist/ag-ui/index.js.map +1 -1
- package/dist/genui/index.d.cts +2 -2
- package/dist/genui/index.d.ts +2 -2
- package/dist/guardrails/index.d.cts +3 -3
- package/dist/guardrails/index.d.ts +3 -3
- package/dist/index.cjs +252 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +155 -8
- package/dist/index.d.ts +155 -8
- package/dist/index.js +251 -5
- package/dist/index.js.map +1 -1
- package/dist/{processors-D5110pit.d.ts → processors-C-FP4nDy.d.ts} +1 -1
- package/dist/{processors-C0snQzZJ.d.cts → processors-CAVevaYJ.d.cts} +1 -1
- package/dist/{stream-events-CgWqAI-1.d.cts → stream-events-rpd3d6gh.d.cts} +5 -0
- package/dist/{stream-events-CgWqAI-1.d.ts → stream-events-rpd3d6gh.d.ts} +5 -0
- package/dist/{tool-DuJ-_qXM.d.cts → tool-Dp8HA_f4.d.cts} +1 -1
- package/dist/{tool-DklsS3JX.d.ts → tool-hhssZ_HW.d.ts} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -88,7 +88,7 @@ __name(decodeStreamEvent, "decodeStreamEvent");
|
|
|
88
88
|
|
|
89
89
|
// src/turn-frames.ts
|
|
90
90
|
function observeTurnFrames(writer, now = Date.now) {
|
|
91
|
-
const
|
|
91
|
+
const decoder3 = new TextDecoder();
|
|
92
92
|
let pending = "";
|
|
93
93
|
let reasoning = "";
|
|
94
94
|
let reasoningMs = 0;
|
|
@@ -128,7 +128,7 @@ function observeTurnFrames(writer, now = Date.now) {
|
|
|
128
128
|
}
|
|
129
129
|
__name(observeLine, "observeLine");
|
|
130
130
|
function observe(chunk) {
|
|
131
|
-
pending +=
|
|
131
|
+
pending += decoder3.decode(chunk, {
|
|
132
132
|
stream: true
|
|
133
133
|
});
|
|
134
134
|
let newline = pending.indexOf("\n");
|
|
@@ -2511,7 +2511,8 @@ function detachedUnsettled(args) {
|
|
|
2511
2511
|
__name(detachedUnsettled, "detachedUnsettled");
|
|
2512
2512
|
async function settleUnsettledDelegation(args) {
|
|
2513
2513
|
const { store, delivery, agent, runId, status } = args;
|
|
2514
|
-
|
|
2514
|
+
const thread = await store.getThread(delivery.threadId);
|
|
2515
|
+
if (thread === null || thread.messages.some((message) => message.runId === runId)) {
|
|
2515
2516
|
return;
|
|
2516
2517
|
}
|
|
2517
2518
|
await store.appendMessage({
|
|
@@ -5441,7 +5442,8 @@ var InMemoryAgentStore = class {
|
|
|
5441
5442
|
}
|
|
5442
5443
|
}
|
|
5443
5444
|
/**
|
|
5444
|
-
* Of `mediaIds`, the ones a surviving message in
|
|
5445
|
+
* Of `mediaIds`, the ones a surviving message — or a message waiting in the queue — in one of
|
|
5446
|
+
* this actor's threads still carries.
|
|
5445
5447
|
* Re-derived from the messages each call, so a media whose message was truncated away reads as
|
|
5446
5448
|
* unreferenced again.
|
|
5447
5449
|
*/
|
|
@@ -5455,7 +5457,11 @@ var InMemoryAgentStore = class {
|
|
|
5455
5457
|
if (thread.actorRef !== actorRef) {
|
|
5456
5458
|
continue;
|
|
5457
5459
|
}
|
|
5458
|
-
|
|
5460
|
+
const queued = this.queues.get(thread.id) ?? [];
|
|
5461
|
+
for (const message of [
|
|
5462
|
+
...thread.messages,
|
|
5463
|
+
...queued
|
|
5464
|
+
]) {
|
|
5459
5465
|
for (const attachment of message.attachments ?? []) {
|
|
5460
5466
|
if (wanted.has(attachment.mediaId)) {
|
|
5461
5467
|
found.add(attachment.mediaId);
|
|
@@ -6097,6 +6103,245 @@ function defineConfirmedTool(options, steps) {
|
|
|
6097
6103
|
};
|
|
6098
6104
|
}
|
|
6099
6105
|
__name(defineConfirmedTool, "defineConfirmedTool");
|
|
6106
|
+
|
|
6107
|
+
// src/sql-token-stream-sink.ts
|
|
6108
|
+
var DEFAULT_TTL_SECONDS = 3600;
|
|
6109
|
+
var DEFAULT_POLL_INTERVAL_MS = 250;
|
|
6110
|
+
var DEFAULT_IDLE_POLL_INTERVAL_MS = 1e3;
|
|
6111
|
+
var IDLE_AFTER_MS = 5e3;
|
|
6112
|
+
var DEFAULT_FLUSH_MS = 50;
|
|
6113
|
+
var READ_PAGE = 500;
|
|
6114
|
+
var PURGE_CHUNK = 200;
|
|
6115
|
+
var AUTO_PURGE_EVERY_MS = 6e4;
|
|
6116
|
+
var APPEND_ATTEMPTS = 8;
|
|
6117
|
+
var decoder2 = new TextDecoder();
|
|
6118
|
+
var encoder2 = new TextEncoder();
|
|
6119
|
+
var sleep = /* @__PURE__ */ __name((ms) => new Promise((resolve) => setTimeout(resolve, ms)), "sleep");
|
|
6120
|
+
function textOf(line) {
|
|
6121
|
+
if (!line.startsWith('{"kind":"text"')) return null;
|
|
6122
|
+
try {
|
|
6123
|
+
const parsed = JSON.parse(line);
|
|
6124
|
+
if (typeof parsed === "object" && parsed !== null && Object.keys(parsed).length === 2 && parsed.kind === "text" && typeof parsed.text === "string") {
|
|
6125
|
+
return parsed.text;
|
|
6126
|
+
}
|
|
6127
|
+
} catch {
|
|
6128
|
+
}
|
|
6129
|
+
return null;
|
|
6130
|
+
}
|
|
6131
|
+
__name(textOf, "textOf");
|
|
6132
|
+
var SqlTokenStreamSink = class {
|
|
6133
|
+
static {
|
|
6134
|
+
__name(this, "SqlTokenStreamSink");
|
|
6135
|
+
}
|
|
6136
|
+
table;
|
|
6137
|
+
pollIntervalMs;
|
|
6138
|
+
idlePollIntervalMs;
|
|
6139
|
+
flushMs;
|
|
6140
|
+
ttlSeconds;
|
|
6141
|
+
autoPurge;
|
|
6142
|
+
writes = /* @__PURE__ */ new Map();
|
|
6143
|
+
lastAutoPurge = 0;
|
|
6144
|
+
constructor(table, options = {}) {
|
|
6145
|
+
this.table = table;
|
|
6146
|
+
this.pollIntervalMs = Math.max(1, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
6147
|
+
this.idlePollIntervalMs = Math.max(this.pollIntervalMs, options.idlePollIntervalMs ?? DEFAULT_IDLE_POLL_INTERVAL_MS);
|
|
6148
|
+
this.flushMs = Math.max(0, options.flushMs ?? DEFAULT_FLUSH_MS);
|
|
6149
|
+
this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
6150
|
+
this.autoPurge = options.autoPurge ?? true;
|
|
6151
|
+
}
|
|
6152
|
+
runWrites(runId) {
|
|
6153
|
+
let state = this.writes.get(runId);
|
|
6154
|
+
if (state === void 0) {
|
|
6155
|
+
state = {
|
|
6156
|
+
text: null,
|
|
6157
|
+
timer: void 0,
|
|
6158
|
+
tail: Promise.resolve(),
|
|
6159
|
+
pending: 0,
|
|
6160
|
+
failure: void 0
|
|
6161
|
+
};
|
|
6162
|
+
this.writes.set(runId, state);
|
|
6163
|
+
}
|
|
6164
|
+
return state;
|
|
6165
|
+
}
|
|
6166
|
+
/** Forget a run's write state once nothing is gathered, queued or left to report. */
|
|
6167
|
+
release(runId, state) {
|
|
6168
|
+
if (state.pending === 0 && state.text === null && state.failure === void 0 && this.writes.get(runId) === state) {
|
|
6169
|
+
this.writes.delete(runId);
|
|
6170
|
+
}
|
|
6171
|
+
}
|
|
6172
|
+
/** Queue `work` behind every write already queued for the run, so rows land in call order. */
|
|
6173
|
+
enqueue(runId, state, work) {
|
|
6174
|
+
state.pending += 1;
|
|
6175
|
+
const next = state.tail.then(work);
|
|
6176
|
+
state.tail = next.then(() => void 0, () => void 0).then(() => {
|
|
6177
|
+
state.pending -= 1;
|
|
6178
|
+
this.release(runId, state);
|
|
6179
|
+
});
|
|
6180
|
+
return next;
|
|
6181
|
+
}
|
|
6182
|
+
/** Queue the gathered text (if any) as one `text` row. */
|
|
6183
|
+
flushText(runId, state) {
|
|
6184
|
+
if (state.timer !== void 0) {
|
|
6185
|
+
clearTimeout(state.timer);
|
|
6186
|
+
state.timer = void 0;
|
|
6187
|
+
}
|
|
6188
|
+
if (state.text === null) return Promise.resolve();
|
|
6189
|
+
const line = decoder2.decode(encodeStreamEvent({
|
|
6190
|
+
kind: "text",
|
|
6191
|
+
text: state.text
|
|
6192
|
+
}));
|
|
6193
|
+
state.text = null;
|
|
6194
|
+
return this.enqueue(runId, state, () => this.append(runId, line, null));
|
|
6195
|
+
}
|
|
6196
|
+
/** Raise, once, a gathered write that failed with nobody awaiting it. */
|
|
6197
|
+
raiseFailure(state) {
|
|
6198
|
+
const failure = state.failure;
|
|
6199
|
+
if (failure !== void 0) {
|
|
6200
|
+
state.failure = void 0;
|
|
6201
|
+
throw failure.error;
|
|
6202
|
+
}
|
|
6203
|
+
}
|
|
6204
|
+
/** Append one row — a frame, or the terminal row (`frame: null`, with `error` on a failure). */
|
|
6205
|
+
async append(runId, frame, error) {
|
|
6206
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
6207
|
+
try {
|
|
6208
|
+
await this.table.append(runId, {
|
|
6209
|
+
frame,
|
|
6210
|
+
error,
|
|
6211
|
+
createdAt: Date.now()
|
|
6212
|
+
});
|
|
6213
|
+
return;
|
|
6214
|
+
} catch (caught) {
|
|
6215
|
+
if (attempt >= APPEND_ATTEMPTS || !this.table.isUniqueViolation(caught)) throw caught;
|
|
6216
|
+
}
|
|
6217
|
+
}
|
|
6218
|
+
}
|
|
6219
|
+
/** Write out what is gathered, then a terminal row; raise a failure nobody saw. */
|
|
6220
|
+
async terminate(runId, error) {
|
|
6221
|
+
const state = this.runWrites(runId);
|
|
6222
|
+
const flushed = this.flushText(runId, state);
|
|
6223
|
+
const ended = this.enqueue(runId, state, () => this.append(runId, null, error));
|
|
6224
|
+
await Promise.all([
|
|
6225
|
+
flushed,
|
|
6226
|
+
ended
|
|
6227
|
+
]);
|
|
6228
|
+
this.raiseFailure(state);
|
|
6229
|
+
this.release(runId, state);
|
|
6230
|
+
this.purgeInBackground();
|
|
6231
|
+
}
|
|
6232
|
+
/**
|
|
6233
|
+
* The run's writer. Writers opened for the same run in one process share what they are gathering,
|
|
6234
|
+
* so a delegated run's text (forwarded through a child writer) and its parent's next frame keep
|
|
6235
|
+
* the order they were written in.
|
|
6236
|
+
*/
|
|
6237
|
+
open(runId) {
|
|
6238
|
+
return {
|
|
6239
|
+
write: /* @__PURE__ */ __name(async (chunk) => {
|
|
6240
|
+
const state = this.runWrites(runId);
|
|
6241
|
+
this.raiseFailure(state);
|
|
6242
|
+
const line = decoder2.decode(chunk);
|
|
6243
|
+
const text = this.flushMs > 0 ? textOf(line.trimEnd()) : null;
|
|
6244
|
+
if (text !== null) {
|
|
6245
|
+
state.text = (state.text ?? "") + text;
|
|
6246
|
+
if (state.timer === void 0) {
|
|
6247
|
+
state.timer = setTimeout(() => {
|
|
6248
|
+
state.timer = void 0;
|
|
6249
|
+
this.flushText(runId, state).catch((error) => {
|
|
6250
|
+
state.failure = {
|
|
6251
|
+
error
|
|
6252
|
+
};
|
|
6253
|
+
});
|
|
6254
|
+
}, this.flushMs);
|
|
6255
|
+
}
|
|
6256
|
+
return;
|
|
6257
|
+
}
|
|
6258
|
+
const flushed = this.flushText(runId, state);
|
|
6259
|
+
const appended = this.enqueue(runId, state, () => this.append(runId, line, null));
|
|
6260
|
+
await Promise.all([
|
|
6261
|
+
flushed,
|
|
6262
|
+
appended
|
|
6263
|
+
]);
|
|
6264
|
+
}, "write"),
|
|
6265
|
+
flush: /* @__PURE__ */ __name(async () => {
|
|
6266
|
+
const state = this.runWrites(runId);
|
|
6267
|
+
const flushed = this.flushText(runId, state);
|
|
6268
|
+
await Promise.all([
|
|
6269
|
+
flushed,
|
|
6270
|
+
state.tail
|
|
6271
|
+
]);
|
|
6272
|
+
this.raiseFailure(state);
|
|
6273
|
+
this.release(runId, state);
|
|
6274
|
+
}, "flush"),
|
|
6275
|
+
end: /* @__PURE__ */ __name(() => this.terminate(runId, null), "end"),
|
|
6276
|
+
fail: /* @__PURE__ */ __name((error) => this.terminate(runId, JSON.stringify({
|
|
6277
|
+
code: error.code,
|
|
6278
|
+
message: error.message
|
|
6279
|
+
})), "fail")
|
|
6280
|
+
};
|
|
6281
|
+
}
|
|
6282
|
+
async *subscribe(runId) {
|
|
6283
|
+
let cursor = 0;
|
|
6284
|
+
let quietSince = Date.now();
|
|
6285
|
+
while (true) {
|
|
6286
|
+
const rows = await this.table.read(runId, cursor, READ_PAGE);
|
|
6287
|
+
for (const row of rows) {
|
|
6288
|
+
cursor = row.seq;
|
|
6289
|
+
if (row.frame === null) {
|
|
6290
|
+
if (row.error !== null) {
|
|
6291
|
+
throw new AgentStreamError(JSON.parse(row.error));
|
|
6292
|
+
}
|
|
6293
|
+
return;
|
|
6294
|
+
}
|
|
6295
|
+
yield encoder2.encode(row.frame);
|
|
6296
|
+
}
|
|
6297
|
+
if (rows.length > 0) {
|
|
6298
|
+
quietSince = Date.now();
|
|
6299
|
+
if (rows.length >= READ_PAGE) continue;
|
|
6300
|
+
}
|
|
6301
|
+
await sleep(Date.now() - quietSince >= IDLE_AFTER_MS ? this.idlePollIntervalMs : this.pollIntervalMs);
|
|
6302
|
+
}
|
|
6303
|
+
}
|
|
6304
|
+
/** Does the table hold anything for the run — a frame, or its end? */
|
|
6305
|
+
has(runId) {
|
|
6306
|
+
return this.table.has(runId);
|
|
6307
|
+
}
|
|
6308
|
+
async close(runId) {
|
|
6309
|
+
const state = this.writes.get(runId);
|
|
6310
|
+
if (state !== void 0) {
|
|
6311
|
+
if (state.timer !== void 0) clearTimeout(state.timer);
|
|
6312
|
+
state.timer = void 0;
|
|
6313
|
+
state.text = null;
|
|
6314
|
+
state.failure = void 0;
|
|
6315
|
+
await state.tail;
|
|
6316
|
+
this.writes.delete(runId);
|
|
6317
|
+
}
|
|
6318
|
+
await this.table.remove([
|
|
6319
|
+
runId
|
|
6320
|
+
]);
|
|
6321
|
+
}
|
|
6322
|
+
/**
|
|
6323
|
+
* Delete every run whose last write is older than `ttlSeconds` at `now` (epoch-ms) — ended runs
|
|
6324
|
+
* past their replay window and runs that crashed without ending alike. Returns how many runs went.
|
|
6325
|
+
* Safe from any replica, and from several at once. A no-op under `ttlSeconds: 0`.
|
|
6326
|
+
*/
|
|
6327
|
+
async purgeExpired(now = Date.now()) {
|
|
6328
|
+
if (this.ttlSeconds <= 0) return 0;
|
|
6329
|
+
const lapsed = await this.table.lapsedRuns(now - this.ttlSeconds * 1e3);
|
|
6330
|
+
for (let index = 0; index < lapsed.length; index += PURGE_CHUNK) {
|
|
6331
|
+
await this.table.remove(lapsed.slice(index, index + PURGE_CHUNK));
|
|
6332
|
+
}
|
|
6333
|
+
return lapsed.length;
|
|
6334
|
+
}
|
|
6335
|
+
/** {@link purgeExpired}, unawaited and at most once a minute. Its failure is not the run's. */
|
|
6336
|
+
purgeInBackground() {
|
|
6337
|
+
if (!this.autoPurge || this.ttlSeconds <= 0) return;
|
|
6338
|
+
const now = Date.now();
|
|
6339
|
+
if (now - this.lastAutoPurge < AUTO_PURGE_EVERY_MS) return;
|
|
6340
|
+
this.lastAutoPurge = now;
|
|
6341
|
+
this.purgeExpired(now).catch(() => {
|
|
6342
|
+
});
|
|
6343
|
+
}
|
|
6344
|
+
};
|
|
6100
6345
|
export {
|
|
6101
6346
|
AGENT_ACTOR_DIRECTORY,
|
|
6102
6347
|
AGENT_ACTOR_RESOLVER,
|
|
@@ -6168,6 +6413,7 @@ export {
|
|
|
6168
6413
|
SCHEMA_EXTENSION,
|
|
6169
6414
|
SKILL_TOOL_DESCRIPTION,
|
|
6170
6415
|
SKILL_TOOL_NAME,
|
|
6416
|
+
SqlTokenStreamSink,
|
|
6171
6417
|
StructuredOutputError,
|
|
6172
6418
|
THREAD_DETAIL_CONTENT_CHARS,
|
|
6173
6419
|
ToolDisabledError,
|