@dudousxd/nestjs-agent-core 0.38.0 → 0.39.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.js CHANGED
@@ -331,6 +331,9 @@ function queuedMessageView(message) {
331
331
  ...message.agentName !== void 0 ? {
332
332
  agentName: message.agentName
333
333
  } : {},
334
+ ...message.persona !== void 0 ? {
335
+ persona: message.persona
336
+ } : {},
334
337
  ...message.model !== void 0 ? {
335
338
  model: message.model
336
339
  } : {},
@@ -723,6 +726,54 @@ function filterToolsByAllowList(tools, allowedTools) {
723
726
  }
724
727
  __name(filterToolsByAllowList, "filterToolsByAllowList");
725
728
 
729
+ // src/personas.ts
730
+ function intersectAllowLists(first, second) {
731
+ if (first === void 0) {
732
+ return second === void 0 ? void 0 : [
733
+ ...second
734
+ ];
735
+ }
736
+ if (second === void 0) {
737
+ return [
738
+ ...first
739
+ ];
740
+ }
741
+ const allowed = new Set(second);
742
+ return first.filter((name) => allowed.has(name));
743
+ }
744
+ __name(intersectAllowLists, "intersectAllowLists");
745
+ function findPersona(definition, id) {
746
+ if (id === void 0) {
747
+ return void 0;
748
+ }
749
+ return definition?.personas?.find((persona) => persona.id === id);
750
+ }
751
+ __name(findPersona, "findPersona");
752
+ function personaCatalogEntry(persona) {
753
+ return {
754
+ id: persona.id,
755
+ label: persona.label,
756
+ ...persona.description !== void 0 ? {
757
+ description: persona.description
758
+ } : {}
759
+ };
760
+ }
761
+ __name(personaCatalogEntry, "personaCatalogEntry");
762
+ function resolvePersonaAlias(definitions, name) {
763
+ for (const definition of definitions) {
764
+ for (const persona of definition.personas ?? []) {
765
+ if (persona.aliases?.includes(name) === true) {
766
+ return {
767
+ agent: definition.name,
768
+ persona: persona.id
769
+ };
770
+ }
771
+ }
772
+ }
773
+ return void 0;
774
+ }
775
+ __name(resolvePersonaAlias, "resolvePersonaAlias");
776
+
726
777
  // src/history.ts
727
778
  function estimateMessageTokens(message) {
728
779
  const extras = (message.toolCalls !== void 0 ? JSON.stringify(message.toolCalls).length : 0) + (message.toolResults !== void 0 ? JSON.stringify(message.toolResults).length : 0);
@@ -2511,7 +2562,8 @@ function detachedUnsettled(args) {
2511
2562
  __name(detachedUnsettled, "detachedUnsettled");
2512
2563
  async function settleUnsettledDelegation(args) {
2513
2564
  const { store, delivery, agent, runId, status } = args;
2514
- if (await store.getThread(delivery.threadId) === null) {
2565
+ const thread = await store.getThread(delivery.threadId);
2566
+ if (thread === null || thread.messages.some((message) => message.runId === runId)) {
2515
2567
  return;
2516
2568
  }
2517
2569
  await store.appendMessage({
@@ -2661,7 +2713,7 @@ var ToolRegistry = class {
2661
2713
  * a call can reach here from a replayed durable step or an approval granted before the flag
2662
2714
  * moved, neither of which went through `definitionsFor` again) and re-parses the input via Zod.
2663
2715
  */
2664
- async invoke(name, input, ctx, policy) {
2716
+ async invoke(name, input, ctx, policy, options = {}) {
2665
2717
  const entry = this.entries.get(name);
2666
2718
  if (entry === void 0) {
2667
2719
  throw new ToolNotFoundError(name);
@@ -2675,6 +2727,9 @@ var ToolRegistry = class {
2675
2727
  if (!await canActorUseTool(ctx.actor, entry.handler)) {
2676
2728
  throw new ToolForbiddenError(name);
2677
2729
  }
2730
+ if (options.allowedTools !== void 0 && !options.allowedTools.includes(name)) {
2731
+ throw new ToolForbiddenError(name);
2732
+ }
2678
2733
  const validation = await entry.spec.inputSchema["~standard"].validate(input);
2679
2734
  if (validation.issues !== void 0) {
2680
2735
  throw new ToolInputInvalidError(name, validation.issues);
@@ -3026,16 +3081,10 @@ async function resolvePrompt(prompt, ctx) {
3026
3081
  return typeof prompt === "function" ? prompt(ctx) : prompt;
3027
3082
  }
3028
3083
  __name(resolvePrompt, "resolvePrompt");
3029
- async function resolveSystemPrompt(deps, input) {
3030
- const ctx = {
3031
- actor: input.actor,
3032
- agentName: input.agentName ?? "default",
3033
- ...input.pageContext !== void 0 ? {
3034
- pageContext: input.pageContext
3035
- } : {}
3036
- };
3084
+ async function resolveSystemPrompt(deps, input, persona) {
3085
+ const ctx = promptContext(input, persona);
3037
3086
  const sections = [
3038
- await resolvePrompt(deps.systemPrompt, ctx)
3087
+ persona?.prompt ?? await resolvePrompt(deps.systemPrompt, ctx)
3039
3088
  ];
3040
3089
  for (const contribute of deps.promptContributors ?? []) {
3041
3090
  const section = await contribute(ctx);
@@ -3046,6 +3095,67 @@ async function resolveSystemPrompt(deps, input) {
3046
3095
  return sections.join("\n\n");
3047
3096
  }
3048
3097
  __name(resolveSystemPrompt, "resolveSystemPrompt");
3098
+ function withoutPersona(input) {
3099
+ const { persona: _dropped, ...rest } = input;
3100
+ return rest;
3101
+ }
3102
+ __name(withoutPersona, "withoutPersona");
3103
+ function promptContext(input, persona) {
3104
+ return {
3105
+ actor: input.actor,
3106
+ agentName: input.agentName ?? "default",
3107
+ ...input.pageContext !== void 0 ? {
3108
+ pageContext: input.pageContext
3109
+ } : {},
3110
+ ...persona !== void 0 ? {
3111
+ persona: {
3112
+ id: persona.id,
3113
+ label: persona.label
3114
+ }
3115
+ } : {}
3116
+ };
3117
+ }
3118
+ __name(promptContext, "promptContext");
3119
+ async function resolveTurnPersona(deps, input) {
3120
+ const persona = findPersona(deps, input.persona);
3121
+ if (persona === void 0) {
3122
+ return null;
3123
+ }
3124
+ const ref = {
3125
+ id: persona.id,
3126
+ label: persona.label
3127
+ };
3128
+ let prompt;
3129
+ if (persona.systemPrompt !== void 0) {
3130
+ const ctx = promptContext(input, ref);
3131
+ const basePrompt = typeof persona.systemPrompt === "function" ? await resolvePrompt(deps.systemPrompt, ctx) : void 0;
3132
+ prompt = await resolvePrompt(persona.systemPrompt, {
3133
+ ...ctx,
3134
+ ...basePrompt !== void 0 ? {
3135
+ basePrompt
3136
+ } : {}
3137
+ });
3138
+ }
3139
+ return {
3140
+ ...ref,
3141
+ ...persona.allowedTools !== void 0 ? {
3142
+ allowedTools: [
3143
+ ...persona.allowedTools
3144
+ ]
3145
+ } : {},
3146
+ ...prompt !== void 0 ? {
3147
+ prompt
3148
+ } : {}
3149
+ };
3150
+ }
3151
+ __name(resolveTurnPersona, "resolveTurnPersona");
3152
+ function personaRefusal(persona, toolName) {
3153
+ if (persona?.allowedTools === void 0 || persona.allowedTools.includes(toolName)) {
3154
+ return null;
3155
+ }
3156
+ return `(tool "${toolName}" is not available to the "${persona.id}" persona)`;
3157
+ }
3158
+ __name(personaRefusal, "personaRefusal");
3049
3159
  function extractTask(input) {
3050
3160
  if (typeof input === "object" && input !== null && "task" in input) {
3051
3161
  const task = input.task;
@@ -3287,6 +3397,9 @@ function processorContext(input, step) {
3287
3397
  step,
3288
3398
  ...input.agentName !== void 0 ? {
3289
3399
  agentName: input.agentName
3400
+ } : {},
3401
+ ...input.persona !== void 0 ? {
3402
+ persona: input.persona
3290
3403
  } : {}
3291
3404
  };
3292
3405
  }
@@ -3450,6 +3563,9 @@ function toolContext(deps, input, hooks) {
3450
3563
  ...input.agentName !== void 0 ? {
3451
3564
  agentName: input.agentName
3452
3565
  } : {},
3566
+ ...input.persona !== void 0 ? {
3567
+ persona: input.persona
3568
+ } : {},
3453
3569
  ...input.pageContext !== void 0 ? {
3454
3570
  pageContext: input.pageContext
3455
3571
  } : {},
@@ -3497,6 +3613,9 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
3497
3613
  ],
3498
3614
  ...input.agentName !== void 0 ? {
3499
3615
  agentName: input.agentName
3616
+ } : {},
3617
+ ...input.persona !== void 0 ? {
3618
+ persona: input.persona
3500
3619
  } : {}
3501
3620
  });
3502
3621
  await deps.store.recordToolCall({
@@ -3842,6 +3961,7 @@ async function invokeClaimedTool(turn, claimed) {
3842
3961
  if (claimed.toolType === "memory") {
3843
3962
  return await rememberIntoTurn(turn, claimed, startedAt);
3844
3963
  }
3964
+ const invokeAllowList = turn.persona?.allowedTools === void 0 ? void 0 : intersectAllowLists(deps.toolAllowList, turn.persona.allowedTools);
3845
3965
  let raw;
3846
3966
  if (hooks.dispatchTool) {
3847
3967
  const stepCtx = {
@@ -3852,6 +3972,9 @@ async function invokeClaimedTool(turn, claimed) {
3852
3972
  ...input.agentName !== void 0 ? {
3853
3973
  agentName: input.agentName
3854
3974
  } : {},
3975
+ ...input.persona !== void 0 ? {
3976
+ persona: input.persona
3977
+ } : {},
3855
3978
  ...input.pageContext !== void 0 ? {
3856
3979
  pageContext: input.pageContext
3857
3980
  } : {}
@@ -3860,6 +3983,9 @@ async function invokeClaimedTool(turn, claimed) {
3860
3983
  toolName: call.name,
3861
3984
  input: call.input,
3862
3985
  ctx: stepCtx,
3986
+ ...invokeAllowList !== void 0 ? {
3987
+ allowedTools: invokeAllowList
3988
+ } : {},
3863
3989
  ...deps.toolTimeoutMs !== void 0 ? {
3864
3990
  timeoutMs: deps.toolTimeoutMs
3865
3991
  } : {},
@@ -3882,7 +4008,9 @@ async function invokeClaimedTool(turn, claimed) {
3882
4008
  return deps.registry.invoke(call.name, call.input, {
3883
4009
  ...toolCallContext(ctx, call.id),
3884
4010
  emitUi: ui2.emit
3885
- }, deps.rolesPolicy);
4011
+ }, deps.rolesPolicy, invokeAllowList !== void 0 ? {
4012
+ allowedTools: invokeAllowList
4013
+ } : {});
3886
4014
  }, deps.toolTransientRetry ?? {}, {
3887
4015
  ...hooks.isControlFlowError !== void 0 ? {
3888
4016
  isControlFlowError: hooks.isControlFlowError
@@ -4013,7 +4141,7 @@ async function delegateToolCall(turn, claimed) {
4013
4141
  const { deps, input, hooks } = turn;
4014
4142
  const { call, targetAgent = call.name } = claimed;
4015
4143
  const task = extractTask(call.input);
4016
- const refusal = delegationRefusal({
4144
+ const refusal = personaRefusal(turn.persona, call.name) ?? delegationRefusal({
4017
4145
  deps,
4018
4146
  input,
4019
4147
  targetAgent
@@ -4309,14 +4437,16 @@ async function invokeClaimedToolsTogether(turn, parallel, claimed) {
4309
4437
  return results;
4310
4438
  }
4311
4439
  __name(invokeClaimedToolsTogether, "invokeClaimedToolsTogether");
4312
- async function runAgentLoop(boundDeps, input, hooks) {
4440
+ async function runAgentLoop(boundDeps, requested, hooks) {
4441
+ const persona = requested.persona === void 0 ? void 0 : await hooks.step("persona:resolve", () => resolveTurnPersona(boundDeps, requested)) ?? void 0;
4442
+ const input = persona === void 0 || persona.id !== requested.persona ? withoutPersona(requested) : requested;
4313
4443
  const deps = input.model === void 0 ? boundDeps : {
4314
4444
  ...boundDeps,
4315
4445
  model: withSelectedModel(boundDeps.model, input.model),
4316
4446
  modelId: input.model
4317
4447
  };
4318
4448
  const maxSteps = deps.maxSteps ?? 8;
4319
- let system = await resolveSystemPrompt(deps, input);
4449
+ let system = await resolveSystemPrompt(deps, input, persona);
4320
4450
  const inputProcessors = deps.inputProcessors ?? [];
4321
4451
  const outputProcessors = deps.outputProcessors ?? [];
4322
4452
  const gateMode = resolveOutputGateMode(outputProcessors);
@@ -4357,6 +4487,9 @@ async function runAgentLoop(boundDeps, input, hooks) {
4357
4487
  role: "user",
4358
4488
  content: input.userText,
4359
4489
  runId: hooks.runId,
4490
+ ...input.persona !== void 0 ? {
4491
+ persona: input.persona
4492
+ } : {},
4360
4493
  ...input.attachments !== void 0 ? {
4361
4494
  attachments: input.attachments
4362
4495
  } : {}
@@ -4379,6 +4512,9 @@ async function runAgentLoop(boundDeps, input, hooks) {
4379
4512
  actorId: input.actor.id,
4380
4513
  ...input.agentName !== void 0 ? {
4381
4514
  agentName: input.agentName
4515
+ } : {},
4516
+ ...input.persona !== void 0 ? {
4517
+ persona: input.persona
4382
4518
  } : {}
4383
4519
  });
4384
4520
  const stages = await resolvePromptStages(deps, hooks);
@@ -4515,13 +4651,16 @@ ${block}`;
4515
4651
  } : {},
4516
4652
  ...input.model !== void 0 ? {
4517
4653
  model: input.model
4654
+ } : {},
4655
+ ...persona?.allowedTools !== void 0 ? {
4656
+ personaAllowedTools: persona.allowedTools
4518
4657
  } : {}
4519
4658
  });
4520
4659
  } else {
4521
4660
  const tools = withMemoryTool({
4522
4661
  tools: withSkillTool({
4523
4662
  tools: withAskTool({
4524
- tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList, {
4663
+ tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, intersectAllowLists(deps.toolAllowList, persona?.allowedTools), {
4525
4664
  threadId: input.threadId,
4526
4665
  ...input.agentName !== void 0 ? {
4527
4666
  agentName: input.agentName
@@ -4736,6 +4875,9 @@ ${block}`;
4736
4875
  ...input.agentName !== void 0 ? {
4737
4876
  agentName: input.agentName
4738
4877
  } : {},
4878
+ ...input.persona !== void 0 ? {
4879
+ persona: input.persona
4880
+ } : {},
4739
4881
  ...turn.reasoning !== void 0 ? {
4740
4882
  reasoning: turn.reasoning
4741
4883
  } : {},
@@ -4830,6 +4972,9 @@ ${block}`;
4830
4972
  } : {},
4831
4973
  ...memoryDigest !== void 0 ? {
4832
4974
  memory: memoryDigest
4975
+ } : {},
4976
+ ...persona !== void 0 ? {
4977
+ persona
4833
4978
  } : {}
4834
4979
  };
4835
4980
  const parallel = hooks.parallel;
@@ -4962,7 +5107,10 @@ var InMemoryAgentStore = class {
4962
5107
  transient: input.transient ?? false,
4963
5108
  createdAt: ts,
4964
5109
  updatedAt: ts,
4965
- messages: []
5110
+ messages: [],
5111
+ ...input.persona !== void 0 ? {
5112
+ persona: input.persona
5113
+ } : {}
4966
5114
  };
4967
5115
  this.threads.set(id, row);
4968
5116
  return this.toSummary(row);
@@ -5067,6 +5215,9 @@ var InMemoryAgentStore = class {
5067
5215
  } : {},
5068
5216
  ...source.model != null ? {
5069
5217
  model: source.model
5218
+ } : {},
5219
+ ...source.persona != null ? {
5220
+ persona: source.persona
5070
5221
  } : {}
5071
5222
  };
5072
5223
  this.threads.set(id, row);
@@ -5118,6 +5269,9 @@ var InMemoryAgentStore = class {
5118
5269
  if (patch.model !== void 0) {
5119
5270
  row.model = patch.model;
5120
5271
  }
5272
+ if (patch.persona !== void 0) {
5273
+ row.persona = patch.persona;
5274
+ }
5121
5275
  row.updatedAt = this.now();
5122
5276
  }
5123
5277
  async activeRunForThread(threadId) {
@@ -5131,6 +5285,10 @@ var InMemoryAgentStore = class {
5131
5285
  async defaultAgentForThread(threadId) {
5132
5286
  return this.threads.get(threadId)?.defaultAgent ?? null;
5133
5287
  }
5288
+ /** The thread's persona, projected like {@link defaultAgentForThread}. */
5289
+ async personaForThread(threadId) {
5290
+ return this.threads.get(threadId)?.persona ?? null;
5291
+ }
5134
5292
  /** The thread's pinned model, projected like {@link defaultAgentForThread}. */
5135
5293
  async modelForThread(threadId) {
5136
5294
  return this.threads.get(threadId)?.model ?? null;
@@ -5235,6 +5393,9 @@ var InMemoryAgentStore = class {
5235
5393
  ...input.agentName !== void 0 ? {
5236
5394
  agentName: input.agentName
5237
5395
  } : {},
5396
+ ...input.persona !== void 0 ? {
5397
+ persona: input.persona
5398
+ } : {},
5238
5399
  ...input.model !== void 0 ? {
5239
5400
  model: input.model
5240
5401
  } : {},
@@ -5373,6 +5534,9 @@ var InMemoryAgentStore = class {
5373
5534
  ...input.agentName !== void 0 ? {
5374
5535
  agentName: input.agentName
5375
5536
  } : {},
5537
+ ...input.persona !== void 0 ? {
5538
+ persona: input.persona
5539
+ } : {},
5376
5540
  ...input.runId !== void 0 ? {
5377
5541
  runId: input.runId
5378
5542
  } : {},
@@ -5441,7 +5605,8 @@ var InMemoryAgentStore = class {
5441
5605
  }
5442
5606
  }
5443
5607
  /**
5444
- * Of `mediaIds`, the ones a surviving message in one of this actor's threads still carries.
5608
+ * Of `mediaIds`, the ones a surviving message — or a message waiting in the queue — in one of
5609
+ * this actor's threads still carries.
5445
5610
  * Re-derived from the messages each call, so a media whose message was truncated away reads as
5446
5611
  * unreferenced again.
5447
5612
  */
@@ -5455,7 +5620,11 @@ var InMemoryAgentStore = class {
5455
5620
  if (thread.actorRef !== actorRef) {
5456
5621
  continue;
5457
5622
  }
5458
- for (const message of thread.messages) {
5623
+ const queued = this.queues.get(thread.id) ?? [];
5624
+ for (const message of [
5625
+ ...thread.messages,
5626
+ ...queued
5627
+ ]) {
5459
5628
  for (const attachment of message.attachments ?? []) {
5460
5629
  if (wanted.has(attachment.mediaId)) {
5461
5630
  found.add(attachment.mediaId);
@@ -5784,7 +5953,8 @@ var InMemoryAgentStore = class {
5784
5953
  defaultAgent: row.defaultAgent ?? null,
5785
5954
  ...row.model != null ? {
5786
5955
  model: row.model
5787
- } : {}
5956
+ } : {},
5957
+ persona: row.persona ?? null
5788
5958
  };
5789
5959
  }
5790
5960
  };
@@ -6456,9 +6626,11 @@ export {
6456
6626
  filterToolsByEnabled,
6457
6627
  filterToolsByRole,
6458
6628
  findCatalogModel,
6629
+ findPersona,
6459
6630
  gateFollowUps,
6460
6631
  gateTail,
6461
6632
  hashConfirmToken,
6633
+ intersectAllowLists,
6462
6634
  invokeWithTransientRetry,
6463
6635
  isChatQueueStore,
6464
6636
  isControlFlowSignal,
@@ -6476,6 +6648,7 @@ export {
6476
6648
  observeTurnFrames,
6477
6649
  offerMemories,
6478
6650
  offerSkills,
6651
+ personaCatalogEntry,
6479
6652
  publishAgentDelegated,
6480
6653
  publishAgentMemoryResolved,
6481
6654
  publishAgentMemoryWritten,
@@ -6505,6 +6678,7 @@ export {
6505
6678
  resolveGateLookback,
6506
6679
  resolveMemoryDigest,
6507
6680
  resolveOutputGateMode,
6681
+ resolvePersonaAlias,
6508
6682
  resolveSkillCatalog,
6509
6683
  resolveToolTransientRetryNumbers,
6510
6684
  rollupThreadUsage,