@dudousxd/nestjs-agent-core 0.25.0 → 0.27.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/README.md +3 -1
- package/dist/catalog-CrzetM3_.d.cts +147 -0
- package/dist/catalog-CrzetM3_.d.ts +147 -0
- package/dist/genui/builtins.cjs +555 -0
- package/dist/genui/builtins.cjs.map +1 -0
- package/dist/genui/builtins.d.cts +47 -0
- package/dist/genui/builtins.d.ts +47 -0
- package/dist/genui/builtins.js +511 -0
- package/dist/genui/builtins.js.map +1 -0
- package/dist/genui/index.cjs +1225 -0
- package/dist/genui/index.cjs.map +1 -0
- package/dist/genui/index.d.cts +175 -0
- package/dist/genui/index.d.ts +175 -0
- package/dist/genui/index.js +1175 -0
- package/dist/genui/index.js.map +1 -0
- package/dist/guardrails/index.d.cts +2 -1
- package/dist/guardrails/index.d.ts +2 -1
- package/dist/index.cjs +730 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +221 -6
- package/dist/index.d.ts +221 -6
- package/dist/index.js +728 -14
- package/dist/index.js.map +1 -1
- package/dist/processors-Bf1fYLbY.d.cts +160 -0
- package/dist/processors-CK1RWv0D.d.ts +160 -0
- package/dist/{tool-fLRLs_f3.d.cts → tool-BXKG2xSm.d.cts} +36 -163
- package/dist/{tool-fLRLs_f3.d.ts → tool-BXKG2xSm.d.ts} +36 -163
- package/package.json +24 -2
package/dist/index.cjs
CHANGED
|
@@ -67,6 +67,7 @@ __export(src_exports, {
|
|
|
67
67
|
DefaultRolesPolicy: () => DefaultRolesPolicy,
|
|
68
68
|
ELICITATION_INPUT_TYPES: () => ELICITATION_INPUT_TYPES,
|
|
69
69
|
GLOBAL_SCOPE: () => GLOBAL_SCOPE,
|
|
70
|
+
InMemoryAgentStore: () => InMemoryAgentStore,
|
|
70
71
|
MAX_ASK_QUESTIONS: () => MAX_ASK_QUESTIONS,
|
|
71
72
|
OutputRejectedError: () => OutputRejectedError,
|
|
72
73
|
ProcessorFailedError: () => ProcessorFailedError,
|
|
@@ -99,6 +100,7 @@ __export(src_exports, {
|
|
|
99
100
|
compositeSkillProvider: () => compositeSkillProvider,
|
|
100
101
|
createFrameBuffer: () => createFrameBuffer,
|
|
101
102
|
createIncrementalGate: () => createIncrementalGate,
|
|
103
|
+
createNoopEmitUi: () => createNoopEmitUi,
|
|
102
104
|
createUiCollector: () => createUiCollector,
|
|
103
105
|
dayBoundsUtc: () => dayBoundsUtc,
|
|
104
106
|
decodeStreamEvent: () => decodeStreamEvent,
|
|
@@ -411,6 +413,22 @@ function unwrapToolStepOutput(raw) {
|
|
|
411
413
|
};
|
|
412
414
|
}
|
|
413
415
|
__name(unwrapToolStepOutput, "unwrapToolStepOutput");
|
|
416
|
+
function createNoopEmitUi(scope = "noop") {
|
|
417
|
+
let next = 0;
|
|
418
|
+
return async (_component, _props, options = {}) => {
|
|
419
|
+
if (options.id !== void 0) {
|
|
420
|
+
return {
|
|
421
|
+
id: options.id
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
const id = `${scope}:ui:${next}`;
|
|
425
|
+
next += 1;
|
|
426
|
+
return {
|
|
427
|
+
id
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
__name(createNoopEmitUi, "createNoopEmitUi");
|
|
414
432
|
function createUiCollector(toolCallId, write) {
|
|
415
433
|
const pushed = /* @__PURE__ */ new Map();
|
|
416
434
|
let next = 0;
|
|
@@ -2595,12 +2613,19 @@ var ToolRegistry = class {
|
|
|
2595
2613
|
* feature-flag store, an MCP server — and this runs once per model step. Asking those about a
|
|
2596
2614
|
* tool the allow-list has already excluded is a call whose answer nothing reads.
|
|
2597
2615
|
*/
|
|
2598
|
-
async definitionsFor(actor, policy, allowedTools) {
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2616
|
+
async definitionsFor(actor, policy, allowedTools, scope = {}) {
|
|
2617
|
+
const visible = await this.visibleEntries(actor, policy, allowedTools);
|
|
2618
|
+
return Promise.all(visible.map(async ({ spec, handler }) => {
|
|
2619
|
+
const override = handler.describe === void 0 ? void 0 : await handler.describe({
|
|
2620
|
+
actor,
|
|
2621
|
+
...scope
|
|
2622
|
+
});
|
|
2623
|
+
return {
|
|
2624
|
+
name: spec.name,
|
|
2625
|
+
kind: spec.kind,
|
|
2626
|
+
description: override?.description ?? spec.description,
|
|
2627
|
+
inputSchema: override?.inputSchema ?? spec.inputSchema
|
|
2628
|
+
};
|
|
2604
2629
|
}));
|
|
2605
2630
|
}
|
|
2606
2631
|
/**
|
|
@@ -2609,6 +2634,9 @@ var ToolRegistry = class {
|
|
|
2609
2634
|
* (`GET <base>/tools`), which must never disagree with what the model is actually shown.
|
|
2610
2635
|
*/
|
|
2611
2636
|
async visibleSpecs(actor, policy, allowedTools) {
|
|
2637
|
+
return (await this.visibleEntries(actor, policy, allowedTools)).map(({ spec }) => spec);
|
|
2638
|
+
}
|
|
2639
|
+
async visibleEntries(actor, policy, allowedTools) {
|
|
2612
2640
|
const pinnedNames = new Set(filterToolsByAllowList(this.allSpecs(), allowedTools).map((spec) => spec.name));
|
|
2613
2641
|
const pinned = [
|
|
2614
2642
|
...this.entries.values()
|
|
@@ -2616,8 +2644,7 @@ var ToolRegistry = class {
|
|
|
2616
2644
|
const live = await filterToolsByEnabled(pinned);
|
|
2617
2645
|
const allowedByRole = new Set((await filterToolsByRole(live.map((entry) => entry.spec), actor, policy)).map((spec) => spec.name));
|
|
2618
2646
|
const roleScoped = live.filter((entry) => allowedByRole.has(entry.spec.name));
|
|
2619
|
-
|
|
2620
|
-
return actorScoped.map(({ spec }) => spec);
|
|
2647
|
+
return filterToolsByCanUse(roleScoped, actor);
|
|
2621
2648
|
}
|
|
2622
2649
|
/**
|
|
2623
2650
|
* Run a tool. Re-checks that the tool is enabled and that the role allows it (defense-in-depth —
|
|
@@ -2642,7 +2669,11 @@ var ToolRegistry = class {
|
|
|
2642
2669
|
if (validation.issues !== void 0) {
|
|
2643
2670
|
throw new ToolInputInvalidError(name, validation.issues);
|
|
2644
2671
|
}
|
|
2645
|
-
|
|
2672
|
+
const withEmit = typeof ctx.emitUi === "function" ? ctx : {
|
|
2673
|
+
...ctx,
|
|
2674
|
+
emitUi: createNoopEmitUi(ctx.requestId)
|
|
2675
|
+
};
|
|
2676
|
+
return entry.handler.execute(validation.value, withEmit);
|
|
2646
2677
|
}
|
|
2647
2678
|
};
|
|
2648
2679
|
var DefaultRolesPolicy = class {
|
|
@@ -2650,13 +2681,12 @@ var DefaultRolesPolicy = class {
|
|
|
2650
2681
|
__name(this, "DefaultRolesPolicy");
|
|
2651
2682
|
}
|
|
2652
2683
|
defaultRoles;
|
|
2653
|
-
constructor(defaultRoles = [
|
|
2654
|
-
"ADMIN"
|
|
2655
|
-
]) {
|
|
2684
|
+
constructor(defaultRoles = []) {
|
|
2656
2685
|
this.defaultRoles = defaultRoles;
|
|
2657
2686
|
}
|
|
2658
2687
|
can(actor, tool) {
|
|
2659
2688
|
const allowed = tool.roles ?? this.defaultRoles;
|
|
2689
|
+
if (allowed.length === 0) return true;
|
|
2660
2690
|
return (actor.roles ?? []).some((role) => allowed.includes(role));
|
|
2661
2691
|
}
|
|
2662
2692
|
};
|
|
@@ -3332,7 +3362,10 @@ function toolContext(deps, input, hooks) {
|
|
|
3332
3362
|
} : {},
|
|
3333
3363
|
...deps.host !== void 0 ? {
|
|
3334
3364
|
host: deps.host
|
|
3335
|
-
} : {}
|
|
3365
|
+
} : {},
|
|
3366
|
+
// Replaced per tool call by the call's own collector (see the tool step); this one only serves
|
|
3367
|
+
// what runs outside a call — the elicitation wait.
|
|
3368
|
+
emitUi: createNoopEmitUi(hooks.runId)
|
|
3336
3369
|
};
|
|
3337
3370
|
}
|
|
3338
3371
|
__name(toolContext, "toolContext");
|
|
@@ -4383,6 +4416,7 @@ ${block}`;
|
|
|
4383
4416
|
system: prompt.system,
|
|
4384
4417
|
messages: prompt.messages,
|
|
4385
4418
|
actor: input.actor,
|
|
4419
|
+
threadId: input.threadId,
|
|
4386
4420
|
...gated ? {
|
|
4387
4421
|
bufferOutput: true
|
|
4388
4422
|
} : {},
|
|
@@ -4394,7 +4428,12 @@ ${block}`;
|
|
|
4394
4428
|
const tools = withMemoryTool({
|
|
4395
4429
|
tools: withSkillTool({
|
|
4396
4430
|
tools: withAskTool({
|
|
4397
|
-
tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList
|
|
4431
|
+
tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList, {
|
|
4432
|
+
threadId: input.threadId,
|
|
4433
|
+
...input.agentName !== void 0 ? {
|
|
4434
|
+
agentName: input.agentName
|
|
4435
|
+
} : {}
|
|
4436
|
+
}),
|
|
4398
4437
|
ask: deps.ask
|
|
4399
4438
|
}),
|
|
4400
4439
|
enabled: deps.skills !== void 0
|
|
@@ -4794,6 +4833,681 @@ ${block}`;
|
|
|
4794
4833
|
};
|
|
4795
4834
|
}
|
|
4796
4835
|
__name(runAgentLoop, "runAgentLoop");
|
|
4836
|
+
|
|
4837
|
+
// src/in-memory-store.ts
|
|
4838
|
+
var InMemoryAgentStore = class {
|
|
4839
|
+
static {
|
|
4840
|
+
__name(this, "InMemoryAgentStore");
|
|
4841
|
+
}
|
|
4842
|
+
threads = /* @__PURE__ */ new Map();
|
|
4843
|
+
toolCalls = /* @__PURE__ */ new Map();
|
|
4844
|
+
usage = [];
|
|
4845
|
+
runs = /* @__PURE__ */ new Map();
|
|
4846
|
+
now() {
|
|
4847
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4848
|
+
}
|
|
4849
|
+
async createThread(input) {
|
|
4850
|
+
const id = crypto.randomUUID();
|
|
4851
|
+
const ts = this.now();
|
|
4852
|
+
const row = {
|
|
4853
|
+
id,
|
|
4854
|
+
actorRef: input.actor.id,
|
|
4855
|
+
title: input.title ?? "New chat",
|
|
4856
|
+
transient: input.transient ?? false,
|
|
4857
|
+
createdAt: ts,
|
|
4858
|
+
updatedAt: ts,
|
|
4859
|
+
messages: []
|
|
4860
|
+
};
|
|
4861
|
+
this.threads.set(id, row);
|
|
4862
|
+
return this.toSummary(row);
|
|
4863
|
+
}
|
|
4864
|
+
async getThread(threadId) {
|
|
4865
|
+
const row = this.threads.get(threadId);
|
|
4866
|
+
if (row === void 0) {
|
|
4867
|
+
return null;
|
|
4868
|
+
}
|
|
4869
|
+
return {
|
|
4870
|
+
...this.toSummary(row),
|
|
4871
|
+
messages: row.messages.map((message) => this.withApprovals(message)),
|
|
4872
|
+
...row.activeStreamId !== void 0 ? {
|
|
4873
|
+
activeStreamId: row.activeStreamId
|
|
4874
|
+
} : {}
|
|
4875
|
+
};
|
|
4876
|
+
}
|
|
4877
|
+
/** A message with the approval record of every call on it that was put to a person. */
|
|
4878
|
+
withApprovals(message) {
|
|
4879
|
+
const approvals = [];
|
|
4880
|
+
for (const call of this.toolCalls.values()) {
|
|
4881
|
+
if (call.messageId !== message.id) {
|
|
4882
|
+
continue;
|
|
4883
|
+
}
|
|
4884
|
+
const approval = toolCallApprovalFromRow({
|
|
4885
|
+
toolCallId: call.toolCallId,
|
|
4886
|
+
status: call.status,
|
|
4887
|
+
approver: call.approver,
|
|
4888
|
+
expiresAt: call.expiresAt,
|
|
4889
|
+
remember: call.remember,
|
|
4890
|
+
executedByRef: call.executedByRef,
|
|
4891
|
+
decidedVia: call.decidedVia,
|
|
4892
|
+
error: call.error
|
|
4893
|
+
});
|
|
4894
|
+
if (approval !== null) {
|
|
4895
|
+
approvals.push(approval);
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4898
|
+
return approvals.length > 0 ? {
|
|
4899
|
+
...message,
|
|
4900
|
+
approvals
|
|
4901
|
+
} : message;
|
|
4902
|
+
}
|
|
4903
|
+
async rememberedApprovals(threadId) {
|
|
4904
|
+
const names = /* @__PURE__ */ new Set();
|
|
4905
|
+
for (const call of this.toolCalls.values()) {
|
|
4906
|
+
if (call.threadId === threadId && call.remember === true) {
|
|
4907
|
+
names.add(call.toolName);
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4910
|
+
return [
|
|
4911
|
+
...names
|
|
4912
|
+
];
|
|
4913
|
+
}
|
|
4914
|
+
async toolCallInput(toolCallId) {
|
|
4915
|
+
return this.toolCalls.get(toolCallId)?.input ?? null;
|
|
4916
|
+
}
|
|
4917
|
+
async toolCallApproval(toolCallId) {
|
|
4918
|
+
const call = this.toolCalls.get(toolCallId);
|
|
4919
|
+
if (call === void 0) {
|
|
4920
|
+
return null;
|
|
4921
|
+
}
|
|
4922
|
+
return {
|
|
4923
|
+
status: call.status,
|
|
4924
|
+
approver: call.approver ?? null,
|
|
4925
|
+
expiresAt: call.expiresAt ?? null
|
|
4926
|
+
};
|
|
4927
|
+
}
|
|
4928
|
+
async listThreads(actorRef, limit = 50) {
|
|
4929
|
+
return [
|
|
4930
|
+
...this.threads.values()
|
|
4931
|
+
].filter((row) => row.actorRef === actorRef && !row.transient).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, limit).map((row) => this.toSummary(row));
|
|
4932
|
+
}
|
|
4933
|
+
async softDeleteThread(threadId) {
|
|
4934
|
+
this.threads.delete(threadId);
|
|
4935
|
+
}
|
|
4936
|
+
async forkThread(threadId, fromMessageId) {
|
|
4937
|
+
const source = this.threads.get(threadId);
|
|
4938
|
+
if (source === void 0) {
|
|
4939
|
+
throw new Error(`thread ${threadId} not found`);
|
|
4940
|
+
}
|
|
4941
|
+
const cutoff = source.messages.findIndex((message) => message.id === fromMessageId);
|
|
4942
|
+
const kept = cutoff >= 0 ? source.messages.slice(0, cutoff + 1) : [
|
|
4943
|
+
...source.messages
|
|
4944
|
+
];
|
|
4945
|
+
const id = crypto.randomUUID();
|
|
4946
|
+
const ts = this.now();
|
|
4947
|
+
const row = {
|
|
4948
|
+
id,
|
|
4949
|
+
actorRef: source.actorRef,
|
|
4950
|
+
title: source.title,
|
|
4951
|
+
transient: false,
|
|
4952
|
+
createdAt: ts,
|
|
4953
|
+
updatedAt: ts,
|
|
4954
|
+
// Feedback rates a message in ITS thread; a fork starts unrated.
|
|
4955
|
+
messages: kept.map(({ feedback: _feedback, ...message }) => ({
|
|
4956
|
+
...message
|
|
4957
|
+
})),
|
|
4958
|
+
...source.defaultAgent != null ? {
|
|
4959
|
+
defaultAgent: source.defaultAgent
|
|
4960
|
+
} : {},
|
|
4961
|
+
...source.model != null ? {
|
|
4962
|
+
model: source.model
|
|
4963
|
+
} : {}
|
|
4964
|
+
};
|
|
4965
|
+
this.threads.set(id, row);
|
|
4966
|
+
return this.toSummary(row);
|
|
4967
|
+
}
|
|
4968
|
+
async ownerOfThread(threadId) {
|
|
4969
|
+
return this.threads.get(threadId)?.actorRef ?? null;
|
|
4970
|
+
}
|
|
4971
|
+
async ownerOfToolCall(toolCallId) {
|
|
4972
|
+
const call = this.toolCalls.get(toolCallId);
|
|
4973
|
+
if (call === void 0) {
|
|
4974
|
+
return null;
|
|
4975
|
+
}
|
|
4976
|
+
return this.threads.get(call.threadId)?.actorRef ?? null;
|
|
4977
|
+
}
|
|
4978
|
+
async runForToolCall(toolCallId) {
|
|
4979
|
+
const call = this.toolCalls.get(toolCallId);
|
|
4980
|
+
if (call === void 0) {
|
|
4981
|
+
return null;
|
|
4982
|
+
}
|
|
4983
|
+
return call.runId ?? this.threads.get(call.threadId)?.activeStreamId ?? null;
|
|
4984
|
+
}
|
|
4985
|
+
async ownerOfActiveStream(runId) {
|
|
4986
|
+
for (const row of this.threads.values()) {
|
|
4987
|
+
if (row.activeStreamId === runId) {
|
|
4988
|
+
return row.actorRef;
|
|
4989
|
+
}
|
|
4990
|
+
}
|
|
4991
|
+
return null;
|
|
4992
|
+
}
|
|
4993
|
+
async setTitle(threadId, title) {
|
|
4994
|
+
const row = this.threads.get(threadId);
|
|
4995
|
+
if (row !== void 0) {
|
|
4996
|
+
row.title = title;
|
|
4997
|
+
row.updatedAt = this.now();
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
async updateThread(threadId, patch) {
|
|
5001
|
+
const row = this.threads.get(threadId);
|
|
5002
|
+
if (row === void 0) {
|
|
5003
|
+
return;
|
|
5004
|
+
}
|
|
5005
|
+
if (patch.title !== void 0) {
|
|
5006
|
+
row.title = patch.title;
|
|
5007
|
+
}
|
|
5008
|
+
if (patch.defaultAgent !== void 0) {
|
|
5009
|
+
row.defaultAgent = patch.defaultAgent;
|
|
5010
|
+
}
|
|
5011
|
+
if (patch.model !== void 0) {
|
|
5012
|
+
row.model = patch.model;
|
|
5013
|
+
}
|
|
5014
|
+
row.updatedAt = this.now();
|
|
5015
|
+
}
|
|
5016
|
+
async activeRunForThread(threadId) {
|
|
5017
|
+
return this.threads.get(threadId)?.activeStreamId ?? null;
|
|
5018
|
+
}
|
|
5019
|
+
/**
|
|
5020
|
+
* The thread's default agent, projected. A map lookup here, but the SQL adapters answer this with
|
|
5021
|
+
* a one-column read instead of materializing the whole transcript — so the caller that only needs
|
|
5022
|
+
* this scalar has a method to ask for it.
|
|
5023
|
+
*/
|
|
5024
|
+
async defaultAgentForThread(threadId) {
|
|
5025
|
+
return this.threads.get(threadId)?.defaultAgent ?? null;
|
|
5026
|
+
}
|
|
5027
|
+
/** The thread's pinned model, projected like {@link defaultAgentForThread}. */
|
|
5028
|
+
async modelForThread(threadId) {
|
|
5029
|
+
return this.threads.get(threadId)?.model ?? null;
|
|
5030
|
+
}
|
|
5031
|
+
/**
|
|
5032
|
+
* Persist the start of a run (turn). Replay-safe: called under a durable localStep.
|
|
5033
|
+
*
|
|
5034
|
+
* Takes the SPI's own {@link RecordRunStartInput} rather than a hand-copied shape: a field added
|
|
5035
|
+
* to the input is otherwise accepted and dropped, silently, by every adapter that re-declares it.
|
|
5036
|
+
*/
|
|
5037
|
+
async recordRunStart(run) {
|
|
5038
|
+
this.runs.set(run.runId, {
|
|
5039
|
+
runId: run.runId,
|
|
5040
|
+
threadId: run.threadId,
|
|
5041
|
+
actorRef: run.actorRef,
|
|
5042
|
+
status: "running",
|
|
5043
|
+
retries: 0,
|
|
5044
|
+
startedAt: this.now(),
|
|
5045
|
+
...run.agentName !== void 0 ? {
|
|
5046
|
+
agentName: run.agentName
|
|
5047
|
+
} : {},
|
|
5048
|
+
...run.parentRunId !== void 0 ? {
|
|
5049
|
+
parentRunId: run.parentRunId
|
|
5050
|
+
} : {},
|
|
5051
|
+
...run.promptHash !== void 0 ? {
|
|
5052
|
+
promptHash: run.promptHash
|
|
5053
|
+
} : {}
|
|
5054
|
+
});
|
|
5055
|
+
}
|
|
5056
|
+
/** Settle a run's outcome. A no-op when the run is unknown (mirrors `setTitle`/`updateThread`). */
|
|
5057
|
+
async recordRunEnd(end) {
|
|
5058
|
+
const row = this.runs.get(end.runId);
|
|
5059
|
+
if (row === void 0) {
|
|
5060
|
+
return;
|
|
5061
|
+
}
|
|
5062
|
+
row.status = end.status;
|
|
5063
|
+
row.settledAt = this.now();
|
|
5064
|
+
if (end.durationMs !== void 0) {
|
|
5065
|
+
row.durationMs = end.durationMs;
|
|
5066
|
+
}
|
|
5067
|
+
if (end.errorCode !== void 0) {
|
|
5068
|
+
row.errorCode = end.errorCode;
|
|
5069
|
+
}
|
|
5070
|
+
if (end.errorMessage !== void 0) {
|
|
5071
|
+
row.errorMessage = end.errorMessage;
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
/** Bump the run's llm-step retry counter. */
|
|
5075
|
+
async bumpRunRetries(runId) {
|
|
5076
|
+
const row = this.runs.get(runId);
|
|
5077
|
+
if (row !== void 0) {
|
|
5078
|
+
row.retries += 1;
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
async promoteThread(threadId) {
|
|
5082
|
+
const row = this.threads.get(threadId);
|
|
5083
|
+
if (row?.transient) {
|
|
5084
|
+
row.transient = false;
|
|
5085
|
+
row.updatedAt = this.now();
|
|
5086
|
+
}
|
|
5087
|
+
}
|
|
5088
|
+
async setActiveStream(threadId, runId) {
|
|
5089
|
+
const row = this.threads.get(threadId);
|
|
5090
|
+
if (row !== void 0) {
|
|
5091
|
+
if (runId === null) {
|
|
5092
|
+
delete row.activeStreamId;
|
|
5093
|
+
} else {
|
|
5094
|
+
row.activeStreamId = runId;
|
|
5095
|
+
}
|
|
5096
|
+
}
|
|
5097
|
+
}
|
|
5098
|
+
async appendMessage(input) {
|
|
5099
|
+
const row = this.threads.get(input.threadId);
|
|
5100
|
+
if (row === void 0) {
|
|
5101
|
+
throw new Error(`thread ${input.threadId} not found`);
|
|
5102
|
+
}
|
|
5103
|
+
const message = {
|
|
5104
|
+
id: crypto.randomUUID(),
|
|
5105
|
+
role: input.role,
|
|
5106
|
+
content: input.content,
|
|
5107
|
+
createdAt: this.now(),
|
|
5108
|
+
...input.toolCalls !== void 0 ? {
|
|
5109
|
+
toolCalls: input.toolCalls
|
|
5110
|
+
} : {},
|
|
5111
|
+
...input.toolResults !== void 0 ? {
|
|
5112
|
+
toolResults: input.toolResults
|
|
5113
|
+
} : {},
|
|
5114
|
+
...input.attachments !== void 0 ? {
|
|
5115
|
+
attachments: input.attachments
|
|
5116
|
+
} : {},
|
|
5117
|
+
...input.followUps !== void 0 ? {
|
|
5118
|
+
followUps: input.followUps
|
|
5119
|
+
} : {},
|
|
5120
|
+
...input.usage !== void 0 ? {
|
|
5121
|
+
usage: input.usage
|
|
5122
|
+
} : {},
|
|
5123
|
+
...input.agentName !== void 0 ? {
|
|
5124
|
+
agentName: input.agentName
|
|
5125
|
+
} : {},
|
|
5126
|
+
...input.runId !== void 0 ? {
|
|
5127
|
+
runId: input.runId
|
|
5128
|
+
} : {},
|
|
5129
|
+
...input.reasoning !== void 0 ? {
|
|
5130
|
+
reasoning: input.reasoning
|
|
5131
|
+
} : {},
|
|
5132
|
+
...input.reasoningMs !== void 0 ? {
|
|
5133
|
+
reasoningMs: input.reasoningMs
|
|
5134
|
+
} : {},
|
|
5135
|
+
...input.ui !== void 0 ? {
|
|
5136
|
+
ui: input.ui
|
|
5137
|
+
} : {}
|
|
5138
|
+
};
|
|
5139
|
+
row.messages.push(message);
|
|
5140
|
+
row.updatedAt = message.createdAt;
|
|
5141
|
+
return message;
|
|
5142
|
+
}
|
|
5143
|
+
async setMessageToolResults(messageId, results) {
|
|
5144
|
+
for (const row of this.threads.values()) {
|
|
5145
|
+
const message = row.messages.find((candidate) => candidate.id === messageId);
|
|
5146
|
+
if (message !== void 0) {
|
|
5147
|
+
message.toolResults = results;
|
|
5148
|
+
return;
|
|
5149
|
+
}
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
async setMessageUi(messageId, ui) {
|
|
5153
|
+
for (const row of this.threads.values()) {
|
|
5154
|
+
const index = row.messages.findIndex((candidate) => candidate.id === messageId);
|
|
5155
|
+
const message = row.messages[index];
|
|
5156
|
+
if (message !== void 0) {
|
|
5157
|
+
const { ui: _previous, ...rest } = message;
|
|
5158
|
+
row.messages[index] = ui.length > 0 ? {
|
|
5159
|
+
...rest,
|
|
5160
|
+
ui
|
|
5161
|
+
} : rest;
|
|
5162
|
+
return;
|
|
5163
|
+
}
|
|
5164
|
+
}
|
|
5165
|
+
}
|
|
5166
|
+
async threadOfMessage(messageId) {
|
|
5167
|
+
return this.threadIdForMessage(messageId) ?? null;
|
|
5168
|
+
}
|
|
5169
|
+
async setMessageFeedback(messageId, feedback) {
|
|
5170
|
+
for (const row of this.threads.values()) {
|
|
5171
|
+
const index = row.messages.findIndex((candidate) => candidate.id === messageId);
|
|
5172
|
+
const message = row.messages[index];
|
|
5173
|
+
if (message !== void 0) {
|
|
5174
|
+
const { feedback: _previous, ...rest } = message;
|
|
5175
|
+
row.messages[index] = feedback !== null ? {
|
|
5176
|
+
...rest,
|
|
5177
|
+
feedback
|
|
5178
|
+
} : rest;
|
|
5179
|
+
return;
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
async truncateFrom(threadId, messageId) {
|
|
5184
|
+
const row = this.threads.get(threadId);
|
|
5185
|
+
if (row === void 0) {
|
|
5186
|
+
return;
|
|
5187
|
+
}
|
|
5188
|
+
const cutoff = row.messages.findIndex((message) => message.id === messageId);
|
|
5189
|
+
if (cutoff >= 0) {
|
|
5190
|
+
row.messages = row.messages.slice(0, cutoff);
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
5193
|
+
/**
|
|
5194
|
+
* Of `mediaIds`, the ones a surviving message in one of this actor's threads still carries.
|
|
5195
|
+
* Re-derived from the messages each call, so a media whose message was truncated away reads as
|
|
5196
|
+
* unreferenced again.
|
|
5197
|
+
*/
|
|
5198
|
+
async referencedMediaIds(actorRef, mediaIds) {
|
|
5199
|
+
if (mediaIds.length === 0) {
|
|
5200
|
+
return [];
|
|
5201
|
+
}
|
|
5202
|
+
const wanted = new Set(mediaIds);
|
|
5203
|
+
const found = /* @__PURE__ */ new Set();
|
|
5204
|
+
for (const thread of this.threads.values()) {
|
|
5205
|
+
if (thread.actorRef !== actorRef) {
|
|
5206
|
+
continue;
|
|
5207
|
+
}
|
|
5208
|
+
for (const message of thread.messages) {
|
|
5209
|
+
for (const attachment of message.attachments ?? []) {
|
|
5210
|
+
if (wanted.has(attachment.mediaId)) {
|
|
5211
|
+
found.add(attachment.mediaId);
|
|
5212
|
+
}
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
}
|
|
5216
|
+
return [
|
|
5217
|
+
...wanted
|
|
5218
|
+
].filter((mediaId) => found.has(mediaId));
|
|
5219
|
+
}
|
|
5220
|
+
async recordToolCall(input) {
|
|
5221
|
+
this.toolCalls.set(input.toolCallId, {
|
|
5222
|
+
toolCallId: input.toolCallId,
|
|
5223
|
+
messageId: input.messageId,
|
|
5224
|
+
threadId: this.threadIdForMessage(input.messageId) ?? "",
|
|
5225
|
+
toolName: input.toolName,
|
|
5226
|
+
toolType: input.toolType,
|
|
5227
|
+
input: input.input,
|
|
5228
|
+
status: input.status,
|
|
5229
|
+
createdAt: this.now(),
|
|
5230
|
+
...input.runId !== void 0 ? {
|
|
5231
|
+
runId: input.runId
|
|
5232
|
+
} : {},
|
|
5233
|
+
...input.approver !== void 0 ? {
|
|
5234
|
+
approver: input.approver
|
|
5235
|
+
} : {},
|
|
5236
|
+
...input.expiresAt !== void 0 ? {
|
|
5237
|
+
expiresAt: input.expiresAt
|
|
5238
|
+
} : {}
|
|
5239
|
+
});
|
|
5240
|
+
}
|
|
5241
|
+
async updateToolCall(input) {
|
|
5242
|
+
const row = this.toolCalls.get(input.toolCallId);
|
|
5243
|
+
if (row === void 0) {
|
|
5244
|
+
return;
|
|
5245
|
+
}
|
|
5246
|
+
row.status = input.status;
|
|
5247
|
+
if (input.output !== void 0) {
|
|
5248
|
+
row.output = input.output;
|
|
5249
|
+
}
|
|
5250
|
+
if (input.error !== void 0) {
|
|
5251
|
+
row.error = input.error;
|
|
5252
|
+
}
|
|
5253
|
+
if (input.executionMs !== void 0) {
|
|
5254
|
+
row.executionMs = input.executionMs;
|
|
5255
|
+
}
|
|
5256
|
+
if (input.executedByRef !== void 0) {
|
|
5257
|
+
row.executedByRef = input.executedByRef;
|
|
5258
|
+
}
|
|
5259
|
+
if (input.remember !== void 0) {
|
|
5260
|
+
row.remember = input.remember;
|
|
5261
|
+
}
|
|
5262
|
+
if (input.decidedVia !== void 0) {
|
|
5263
|
+
row.decidedVia = input.decidedVia;
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5266
|
+
async recordUsage(input) {
|
|
5267
|
+
const createdAt = this.now();
|
|
5268
|
+
this.usage.push({
|
|
5269
|
+
actorRef: input.actorRef,
|
|
5270
|
+
threadId: input.threadId,
|
|
5271
|
+
modelId: input.modelId,
|
|
5272
|
+
inputTokens: input.usage.inputTokens,
|
|
5273
|
+
outputTokens: input.usage.outputTokens,
|
|
5274
|
+
day: createdAt.slice(0, 10),
|
|
5275
|
+
createdAt,
|
|
5276
|
+
...input.usage.cacheWriteTokens !== void 0 ? {
|
|
5277
|
+
cacheWriteTokens: input.usage.cacheWriteTokens
|
|
5278
|
+
} : {},
|
|
5279
|
+
...input.usage.cacheReadTokens !== void 0 ? {
|
|
5280
|
+
cacheReadTokens: input.usage.cacheReadTokens
|
|
5281
|
+
} : {},
|
|
5282
|
+
...input.costUsd !== void 0 ? {
|
|
5283
|
+
costUsd: input.costUsd
|
|
5284
|
+
} : {}
|
|
5285
|
+
});
|
|
5286
|
+
}
|
|
5287
|
+
async quotaToday(actorRef, day) {
|
|
5288
|
+
return this.usageBetween(actorRef, day, day);
|
|
5289
|
+
}
|
|
5290
|
+
async usageBetween(actorRef, fromDay, toDay) {
|
|
5291
|
+
const rows = this.usage.filter((row) => row.actorRef === actorRef && row.day >= fromDay && row.day <= toDay);
|
|
5292
|
+
const usedTokens = rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);
|
|
5293
|
+
const costUsd = rows.reduce((sum, row) => sum + (row.costUsd ?? 0), 0);
|
|
5294
|
+
return {
|
|
5295
|
+
usedTokens,
|
|
5296
|
+
costUsd
|
|
5297
|
+
};
|
|
5298
|
+
}
|
|
5299
|
+
/** Test helper: read the recorded usage rows (modelId + token totals). */
|
|
5300
|
+
usageRows() {
|
|
5301
|
+
return this.usage.map((row) => ({
|
|
5302
|
+
actorRef: row.actorRef,
|
|
5303
|
+
tokens: row.inputTokens + row.outputTokens,
|
|
5304
|
+
modelId: row.modelId
|
|
5305
|
+
}));
|
|
5306
|
+
}
|
|
5307
|
+
/** Governance read-model feed: recorded usage rows with the input/output split + thread/day. */
|
|
5308
|
+
governanceUsage() {
|
|
5309
|
+
return this.usage.map((row) => ({
|
|
5310
|
+
actorRef: row.actorRef,
|
|
5311
|
+
threadId: row.threadId,
|
|
5312
|
+
modelId: row.modelId,
|
|
5313
|
+
inputTokens: row.inputTokens,
|
|
5314
|
+
outputTokens: row.outputTokens,
|
|
5315
|
+
day: row.day,
|
|
5316
|
+
createdAt: row.createdAt,
|
|
5317
|
+
...row.cacheWriteTokens !== void 0 ? {
|
|
5318
|
+
cacheWriteTokens: row.cacheWriteTokens
|
|
5319
|
+
} : {},
|
|
5320
|
+
...row.cacheReadTokens !== void 0 ? {
|
|
5321
|
+
cacheReadTokens: row.cacheReadTokens
|
|
5322
|
+
} : {},
|
|
5323
|
+
...row.costUsd !== void 0 ? {
|
|
5324
|
+
costUsd: row.costUsd
|
|
5325
|
+
} : {}
|
|
5326
|
+
}));
|
|
5327
|
+
}
|
|
5328
|
+
/** Governance read-model feed: recorded tool calls with the resolved thread + timestamp. */
|
|
5329
|
+
governanceToolCalls() {
|
|
5330
|
+
return [
|
|
5331
|
+
...this.toolCalls.values()
|
|
5332
|
+
].map((row) => ({
|
|
5333
|
+
toolCallId: row.toolCallId,
|
|
5334
|
+
toolName: row.toolName,
|
|
5335
|
+
toolType: row.toolType,
|
|
5336
|
+
status: row.status,
|
|
5337
|
+
threadId: row.threadId,
|
|
5338
|
+
messageId: row.messageId,
|
|
5339
|
+
createdAt: row.createdAt,
|
|
5340
|
+
...row.executionMs !== void 0 ? {
|
|
5341
|
+
executionMs: row.executionMs
|
|
5342
|
+
} : {},
|
|
5343
|
+
...row.error !== void 0 ? {
|
|
5344
|
+
error: row.error
|
|
5345
|
+
} : {},
|
|
5346
|
+
...row.runId !== void 0 ? {
|
|
5347
|
+
runId: row.runId
|
|
5348
|
+
} : {}
|
|
5349
|
+
}));
|
|
5350
|
+
}
|
|
5351
|
+
/** Governance read-model feed: every stored message, thread-resolved, for the thread drill-down. */
|
|
5352
|
+
governanceMessages() {
|
|
5353
|
+
const rows = [];
|
|
5354
|
+
for (const thread of this.threads.values()) {
|
|
5355
|
+
for (const message of thread.messages) {
|
|
5356
|
+
rows.push({
|
|
5357
|
+
messageId: message.id,
|
|
5358
|
+
threadId: thread.id,
|
|
5359
|
+
role: message.role,
|
|
5360
|
+
content: message.content,
|
|
5361
|
+
createdAt: message.createdAt,
|
|
5362
|
+
...message.agentName !== void 0 ? {
|
|
5363
|
+
agentName: message.agentName
|
|
5364
|
+
} : {}
|
|
5365
|
+
});
|
|
5366
|
+
}
|
|
5367
|
+
}
|
|
5368
|
+
return rows;
|
|
5369
|
+
}
|
|
5370
|
+
/**
|
|
5371
|
+
* Governance read-model feed: tool calls sitting `pending_approval`, joined to their thread
|
|
5372
|
+
* (title/actorRef) and the message that requested them (`agentName`, when the message has one).
|
|
5373
|
+
*/
|
|
5374
|
+
governancePendingApprovals() {
|
|
5375
|
+
const rows = [];
|
|
5376
|
+
for (const call of this.toolCalls.values()) {
|
|
5377
|
+
if (call.status !== "pending_approval") {
|
|
5378
|
+
continue;
|
|
5379
|
+
}
|
|
5380
|
+
const thread = this.threads.get(call.threadId);
|
|
5381
|
+
if (thread === void 0) {
|
|
5382
|
+
continue;
|
|
5383
|
+
}
|
|
5384
|
+
const message = thread.messages.find((candidate) => candidate.id === call.messageId);
|
|
5385
|
+
rows.push({
|
|
5386
|
+
toolCallId: call.toolCallId,
|
|
5387
|
+
toolName: call.toolName,
|
|
5388
|
+
input: call.input,
|
|
5389
|
+
threadId: call.threadId,
|
|
5390
|
+
threadTitle: thread.title,
|
|
5391
|
+
actorRef: thread.actorRef,
|
|
5392
|
+
requestedAt: call.createdAt,
|
|
5393
|
+
...message?.agentName !== void 0 ? {
|
|
5394
|
+
agentName: message.agentName
|
|
5395
|
+
} : {},
|
|
5396
|
+
...call.runId !== void 0 ? {
|
|
5397
|
+
runId: call.runId
|
|
5398
|
+
} : {}
|
|
5399
|
+
});
|
|
5400
|
+
}
|
|
5401
|
+
return rows;
|
|
5402
|
+
}
|
|
5403
|
+
/** Governance read-model feed: thread metadata (title/actor/message count/last activity). */
|
|
5404
|
+
governanceThreads() {
|
|
5405
|
+
return [
|
|
5406
|
+
...this.threads.values()
|
|
5407
|
+
].map((row) => ({
|
|
5408
|
+
threadId: row.id,
|
|
5409
|
+
title: row.title,
|
|
5410
|
+
actorRef: row.actorRef,
|
|
5411
|
+
messageCount: row.messages.length,
|
|
5412
|
+
updatedAt: row.updatedAt
|
|
5413
|
+
}));
|
|
5414
|
+
}
|
|
5415
|
+
/** Governance read-model feed: recorded run outcomes (the reliability surfaces). */
|
|
5416
|
+
governanceRuns() {
|
|
5417
|
+
return [
|
|
5418
|
+
...this.runs.values()
|
|
5419
|
+
].map((row) => ({
|
|
5420
|
+
runId: row.runId,
|
|
5421
|
+
threadId: row.threadId,
|
|
5422
|
+
actorRef: row.actorRef,
|
|
5423
|
+
status: row.status,
|
|
5424
|
+
retries: row.retries,
|
|
5425
|
+
startedAt: row.startedAt,
|
|
5426
|
+
...row.agentName !== void 0 ? {
|
|
5427
|
+
agentName: row.agentName
|
|
5428
|
+
} : {},
|
|
5429
|
+
...row.parentRunId !== void 0 ? {
|
|
5430
|
+
parentRunId: row.parentRunId
|
|
5431
|
+
} : {},
|
|
5432
|
+
...row.durationMs !== void 0 ? {
|
|
5433
|
+
durationMs: row.durationMs
|
|
5434
|
+
} : {},
|
|
5435
|
+
...row.errorCode !== void 0 ? {
|
|
5436
|
+
errorCode: row.errorCode
|
|
5437
|
+
} : {},
|
|
5438
|
+
...row.errorMessage !== void 0 ? {
|
|
5439
|
+
errorMessage: row.errorMessage
|
|
5440
|
+
} : {},
|
|
5441
|
+
...row.settledAt !== void 0 ? {
|
|
5442
|
+
settledAt: row.settledAt
|
|
5443
|
+
} : {},
|
|
5444
|
+
...row.promptHash !== void 0 ? {
|
|
5445
|
+
promptHash: row.promptHash
|
|
5446
|
+
} : {}
|
|
5447
|
+
}));
|
|
5448
|
+
}
|
|
5449
|
+
threadIdForMessage(messageId) {
|
|
5450
|
+
for (const [threadId, row] of this.threads) {
|
|
5451
|
+
if (row.messages.some((message) => message.id === messageId)) {
|
|
5452
|
+
return threadId;
|
|
5453
|
+
}
|
|
5454
|
+
}
|
|
5455
|
+
return void 0;
|
|
5456
|
+
}
|
|
5457
|
+
/** Test helper: read the recorded tool-call rows. */
|
|
5458
|
+
toolCallRows() {
|
|
5459
|
+
return [
|
|
5460
|
+
...this.toolCalls.values()
|
|
5461
|
+
].map((row) => ({
|
|
5462
|
+
toolCallId: row.toolCallId,
|
|
5463
|
+
toolName: row.toolName,
|
|
5464
|
+
toolType: row.toolType,
|
|
5465
|
+
status: row.status,
|
|
5466
|
+
input: row.input,
|
|
5467
|
+
...row.output !== void 0 ? {
|
|
5468
|
+
output: row.output
|
|
5469
|
+
} : {},
|
|
5470
|
+
...row.error !== void 0 ? {
|
|
5471
|
+
error: row.error
|
|
5472
|
+
} : {},
|
|
5473
|
+
...row.runId !== void 0 ? {
|
|
5474
|
+
runId: row.runId
|
|
5475
|
+
} : {},
|
|
5476
|
+
...row.executedByRef !== void 0 ? {
|
|
5477
|
+
executedByRef: row.executedByRef
|
|
5478
|
+
} : {},
|
|
5479
|
+
...row.approver !== void 0 ? {
|
|
5480
|
+
approver: row.approver
|
|
5481
|
+
} : {},
|
|
5482
|
+
...row.expiresAt !== void 0 ? {
|
|
5483
|
+
expiresAt: row.expiresAt
|
|
5484
|
+
} : {},
|
|
5485
|
+
...row.remember !== void 0 ? {
|
|
5486
|
+
remember: row.remember
|
|
5487
|
+
} : {},
|
|
5488
|
+
...row.decidedVia !== void 0 ? {
|
|
5489
|
+
decidedVia: row.decidedVia
|
|
5490
|
+
} : {}
|
|
5491
|
+
}));
|
|
5492
|
+
}
|
|
5493
|
+
toSummary(row) {
|
|
5494
|
+
const last = row.messages[row.messages.length - 1];
|
|
5495
|
+
return {
|
|
5496
|
+
id: row.id,
|
|
5497
|
+
title: row.title,
|
|
5498
|
+
transient: row.transient,
|
|
5499
|
+
createdAt: row.createdAt,
|
|
5500
|
+
updatedAt: row.updatedAt,
|
|
5501
|
+
...last !== void 0 ? {
|
|
5502
|
+
lastMessagePreview: last.content.slice(0, 120)
|
|
5503
|
+
} : {},
|
|
5504
|
+
defaultAgent: row.defaultAgent ?? null,
|
|
5505
|
+
...row.model != null ? {
|
|
5506
|
+
model: row.model
|
|
5507
|
+
} : {}
|
|
5508
|
+
};
|
|
5509
|
+
}
|
|
5510
|
+
};
|
|
4797
5511
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4798
5512
|
0 && (module.exports = {
|
|
4799
5513
|
AGENT_ACTOR_DIRECTORY,
|
|
@@ -4842,6 +5556,7 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
4842
5556
|
DefaultRolesPolicy,
|
|
4843
5557
|
ELICITATION_INPUT_TYPES,
|
|
4844
5558
|
GLOBAL_SCOPE,
|
|
5559
|
+
InMemoryAgentStore,
|
|
4845
5560
|
MAX_ASK_QUESTIONS,
|
|
4846
5561
|
OutputRejectedError,
|
|
4847
5562
|
ProcessorFailedError,
|
|
@@ -4874,6 +5589,7 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
4874
5589
|
compositeSkillProvider,
|
|
4875
5590
|
createFrameBuffer,
|
|
4876
5591
|
createIncrementalGate,
|
|
5592
|
+
createNoopEmitUi,
|
|
4877
5593
|
createUiCollector,
|
|
4878
5594
|
dayBoundsUtc,
|
|
4879
5595
|
decodeStreamEvent,
|