@dudousxd/nestjs-agent 1.34.0 → 1.35.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.
@@ -1,9 +1,9 @@
1
1
  export * from '@dudousxd/nestjs-agent-core/a2ui';
2
- export { b as A2uiAdapterOptions, c as A2uiRunHandler, i as a2uiAdapter } from '../index-DIFUEKPr.cjs';
2
+ export { b as A2uiAdapterOptions, c as A2uiRunHandler, i as a2uiAdapter } from '../index-NF93YDF4.cjs';
3
3
  import '@dudousxd/nestjs-agent-core';
4
4
  import 'express';
5
5
  import '@dudousxd/nestjs-agent-core/genui';
6
- import '../chat-queue.service-QIuTS-5c.cjs';
6
+ import '../chat-queue.service-CF2fcJDx.cjs';
7
7
  import '@standard-schema/spec';
8
8
  import '@nestjs/common';
9
9
  import '../genui/index.cjs';
@@ -1,9 +1,9 @@
1
1
  export * from '@dudousxd/nestjs-agent-core/a2ui';
2
- export { b as A2uiAdapterOptions, c as A2uiRunHandler, i as a2uiAdapter } from '../index-DFKUTFfZ.js';
2
+ export { b as A2uiAdapterOptions, c as A2uiRunHandler, i as a2uiAdapter } from '../index-DpS9P7so.js';
3
3
  import '@dudousxd/nestjs-agent-core';
4
4
  import 'express';
5
5
  import '@dudousxd/nestjs-agent-core/genui';
6
- import '../chat-queue.service-wNWaoUN8.js';
6
+ import '../chat-queue.service-CzXsKVb1.js';
7
7
  import '@standard-schema/spec';
8
8
  import '@nestjs/common';
9
9
  import '../genui/index.js';
@@ -1,4 +1,4 @@
1
- import { ResolveToolUiCatalog, ToolUiChannelGuide, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
1
+ import { ResolveToolUiCatalog, ToolUiChannelGuide, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, ActionProposalOutcome, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
2
2
  import { Catalog } from '@dudousxd/nestjs-agent-core/genui';
3
3
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
4
  import { Provider, InjectionToken, Type, FactoryProvider, CanActivate, ModuleMetadata, OptionalFactoryDependency } from '@nestjs/common';
@@ -311,13 +311,16 @@ interface AgentModuleOptions {
311
311
  * integers, and `pollIntervalMs` must stay below a third of `leaseMs`. `onSettled` runs after each
312
312
  * proposal the worker settles (executed or failed), with the stored proposal — its `outcome` and
313
313
  * `executionContext.pageContext` included; a module can subscribe the same way through
314
- * `ActionProposalWorkerService.onSettled`.
314
+ * `ActionProposalWorkerService.onSettled`. `onAdmitted` runs once a settled proposal's outcome
315
+ * was written to its thread — the moment to continue the conversation from it
316
+ * (`ActionProposalWorkerService.onAdmitted` for a module).
315
317
  */
316
318
  actionProposalWorker?: {
317
319
  pollIntervalMs?: number;
318
320
  leaseMs?: number;
319
321
  maxConcurrency?: number;
320
322
  onSettled?(proposal: ActionProposal): void | Promise<void>;
323
+ onAdmitted?(outcome: ActionProposalOutcome): void | Promise<void>;
321
324
  };
322
325
  /**
323
326
  * The words a chat message must consist of to approve or reject a proposal by text, and what the
@@ -1,4 +1,4 @@
1
- import { ResolveToolUiCatalog, ToolUiChannelGuide, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
1
+ import { ResolveToolUiCatalog, ToolUiChannelGuide, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, ActionProposalOutcome, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
2
2
  import { Catalog } from '@dudousxd/nestjs-agent-core/genui';
3
3
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
4
  import { Provider, InjectionToken, Type, FactoryProvider, CanActivate, ModuleMetadata, OptionalFactoryDependency } from '@nestjs/common';
@@ -311,13 +311,16 @@ interface AgentModuleOptions {
311
311
  * integers, and `pollIntervalMs` must stay below a third of `leaseMs`. `onSettled` runs after each
312
312
  * proposal the worker settles (executed or failed), with the stored proposal — its `outcome` and
313
313
  * `executionContext.pageContext` included; a module can subscribe the same way through
314
- * `ActionProposalWorkerService.onSettled`.
314
+ * `ActionProposalWorkerService.onSettled`. `onAdmitted` runs once a settled proposal's outcome
315
+ * was written to its thread — the moment to continue the conversation from it
316
+ * (`ActionProposalWorkerService.onAdmitted` for a module).
315
317
  */
316
318
  actionProposalWorker?: {
317
319
  pollIntervalMs?: number;
318
320
  leaseMs?: number;
319
321
  maxConcurrency?: number;
320
322
  onSettled?(proposal: ActionProposal): void | Promise<void>;
323
+ onAdmitted?(outcome: ActionProposalOutcome): void | Promise<void>;
321
324
  };
322
325
  /**
323
326
  * The words a chat message must consist of to approve or reject a proposal by text, and what the
@@ -221,9 +221,9 @@ var AgentRunSteps = class {
221
221
  ),
222
222
  ask: deps.ask
223
223
  }),
224
- enabled: deps.skills !== void 0
224
+ enabled: deps.skills !== void 0 && input.builtins?.skills !== false
225
225
  }),
226
- enabled: deps.memory?.provider.write !== void 0
226
+ enabled: deps.memory?.provider.write !== void 0 && input.builtins?.memory !== false
227
227
  });
228
228
  const buffer = input.bufferOutput === true ? (0, import_nestjs_agent_core3.createFrameBuffer)() : void 0;
229
229
  let writer;
@@ -233,7 +233,8 @@ var AgentRunSteps = class {
233
233
  const opened = await deps.sink.open(input.sinkRunId);
234
234
  writer = input.childSink ? childSinkWriter(opened) : opened;
235
235
  }
236
- const previews = (0, import_nestjs_agent_core3.previewToolInputs)(writer, (0, import_nestjs_agent_core3.registryInputPreviews)(deps.registry, tools, {
236
+ const announced = (0, import_nestjs_agent_core3.announcedToolCalls)(writer);
237
+ const previews = (0, import_nestjs_agent_core3.previewToolInputs)(announced.writer, (0, import_nestjs_agent_core3.registryInputPreviews)(deps.registry, tools, {
237
238
  actor: input.actor,
238
239
  ...input.threadId !== void 0 ? {
239
240
  threadId: input.threadId
@@ -257,6 +258,7 @@ var AgentRunSteps = class {
257
258
  } : {}
258
259
  })), frames.summary());
259
260
  const stamped = (0, import_nestjs_agent_core3.stampToolKinds)(turn, deps);
261
+ await announced.announceRest(stamped.toolCalls, tools);
260
262
  const allowedTools = (0, import_nestjs_agent_core3.intersectAllowLists)(deps.toolAllowList, input.personaAllowedTools);
261
263
  for (const call of stamped.toolCalls) {
262
264
  if (call.kind !== "action") continue;
@@ -6060,9 +6062,19 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
6060
6062
  this.logger.warn(`Agent "${meta.name}" hands off to ${target.name}, which is not an @Agent \u2014 skipped.`);
6061
6063
  continue;
6062
6064
  }
6063
- edges.push(detached ? {
6065
+ const roles = typeof entry === "function" ? void 0 : entry.roles;
6066
+ const ability = typeof entry === "function" ? void 0 : entry.ability;
6067
+ edges.push(detached || roles !== void 0 || ability !== void 0 ? {
6064
6068
  agent: targetMeta.name,
6065
- detached: true
6069
+ ...detached ? {
6070
+ detached: true
6071
+ } : {},
6072
+ ...roles !== void 0 ? {
6073
+ roles
6074
+ } : {},
6075
+ ...ability !== void 0 ? {
6076
+ ability
6077
+ } : {}
6066
6078
  } : targetMeta.name);
6067
6079
  }
6068
6080
  return edges;
@@ -6254,7 +6266,7 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
6254
6266
  let delegates = 0;
6255
6267
  for (const definition of this.agents.list()) {
6256
6268
  for (const edge of definition.delegatesTo ?? []) {
6257
- const { agent: target, detached } = (0, import_nestjs_agent_core31.normalizeDelegation)(edge);
6269
+ const { agent: target, detached, roles, ability } = (0, import_nestjs_agent_core31.normalizeDelegation)(edge);
6258
6270
  const targetDefinition = this.agents.get(target);
6259
6271
  if (targetDefinition === void 0) {
6260
6272
  throw new Error(`Agent "${definition.name}" hands off to "${target}", which is not a registered @Agent. Declare it as an @Agent provider or fix the reference.`);
@@ -6276,6 +6288,12 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
6276
6288
  ...detached ? {
6277
6289
  detached: true
6278
6290
  } : {},
6291
+ ...roles !== void 0 ? {
6292
+ roles
6293
+ } : {},
6294
+ ...ability !== void 0 ? {
6295
+ ability
6296
+ } : {},
6279
6297
  description,
6280
6298
  inputSchema: import_zod.z.object({
6281
6299
  task: import_zod.z.string()
@@ -6614,6 +6632,35 @@ var ActionProposalWorkerService = class _ActionProposalWorkerService {
6614
6632
  worker;
6615
6633
  logger = new import_common29.Logger(_ActionProposalWorkerService.name);
6616
6634
  settledListeners = /* @__PURE__ */ new Set();
6635
+ admittedListeners = /* @__PURE__ */ new Set();
6636
+ /**
6637
+ * Run `listener` once a settled proposal's outcome is written to its thread by this process's
6638
+ * worker (the thread was free) — what a module uses to CONTINUE a conversation once an action it
6639
+ * proposed ran (a Poppy connect: the next turn goes on with what was asked). Next to
6640
+ * `actionProposalWorker.onAdmitted`; a listener that throws is logged and does not stop the
6641
+ * others. Returns the unsubscribe.
6642
+ */
6643
+ onAdmitted(listener) {
6644
+ this.admittedListeners.add(listener);
6645
+ return () => {
6646
+ this.admittedListeners.delete(listener);
6647
+ };
6648
+ }
6649
+ async admitted(outcome) {
6650
+ const configured = this.options.actionProposalWorker?.onAdmitted;
6651
+ for (const listener of [
6652
+ ...configured ? [
6653
+ configured
6654
+ ] : [],
6655
+ ...this.admittedListeners
6656
+ ]) {
6657
+ try {
6658
+ await listener(outcome);
6659
+ } catch (error) {
6660
+ this.logger.error(error);
6661
+ }
6662
+ }
6663
+ }
6617
6664
  /**
6618
6665
  * Run `listener` after every proposal this process's worker settles — how a module relays an
6619
6666
  * outcome somewhere the turn's stream no longer reaches (a text channel's conversation). Next to
@@ -6657,6 +6704,7 @@ var ActionProposalWorkerService = class _ActionProposalWorkerService {
6657
6704
  workerId: (0, import_node_crypto3.randomUUID)(),
6658
6705
  ...this.options.actionProposalWorker,
6659
6706
  onSettled: /* @__PURE__ */ __name((proposal) => this.settled(proposal), "onSettled"),
6707
+ onAdmitted: /* @__PURE__ */ __name((outcome) => this.admitted(outcome), "onAdmitted"),
6660
6708
  executor: new import_nestjs_agent_core36.ActionProposalExecutor({
6661
6709
  resolver,
6662
6710
  resolveExecution: /* @__PURE__ */ __name(async (proposal, actor) => {
@@ -7472,6 +7520,13 @@ function forwardingPolicy(wrapper) {
7472
7520
  throw new Error("AgentModule: the AGENT_ROLES_POLICY bound by another module is not ready yet");
7473
7521
  }
7474
7522
  return policy.can(actor, tool);
7523
+ },
7524
+ canOffer(actor, tool) {
7525
+ const policy = wrapper.instance;
7526
+ if (policy === void 0 || policy === null) {
7527
+ throw new Error("AgentModule: the AGENT_ROLES_POLICY bound by another module is not ready yet");
7528
+ }
7529
+ return policy.canOffer ? policy.canOffer(actor, tool) : policy.can(actor, tool);
7475
7530
  }
7476
7531
  };
7477
7532
  }
@@ -7513,7 +7568,14 @@ function sharedProviders(durable, engine) {
7513
7568
  // drift, and a user would be offered a skill the agent cannot reach. `undefined` when the
7514
7569
  // host configured none — which is what keeps the turn's checkpoint sequence unchanged.
7515
7570
  provide: import_nestjs_agent_core40.AGENT_SKILLS,
7516
- useFactory: /* @__PURE__ */ __name((options, declared) => resolveSkillsConfig(options.skills, declared), "useFactory"),
7571
+ // Personal agents resolve no skill scope (`personalAgentScopes`): nothing of the app's to load.
7572
+ useFactory: /* @__PURE__ */ __name((options, declared) => {
7573
+ const skills = resolveSkillsConfig(options.skills, declared);
7574
+ return skills === void 0 ? void 0 : {
7575
+ ...skills,
7576
+ scopes: (0, import_nestjs_agent_core40.personalAgentScopes)(skills.scopes)
7577
+ };
7578
+ }, "useFactory"),
7517
7579
  inject: [
7518
7580
  import_nestjs_agent_core40.AGENT_OPTIONS,
7519
7581
  import_nestjs_agent_core40.AGENT_SKILL_SOURCES
@@ -7523,7 +7585,12 @@ function sharedProviders(durable, engine) {
7523
7585
  // One resolution, shared by the loop's deps and the read-back endpoint: a person has to be
7524
7586
  // shown what the model was shown, and two resolutions would eventually disagree about that.
7525
7587
  provide: import_nestjs_agent_core40.AGENT_MEMORY,
7526
- useFactory: /* @__PURE__ */ __name((options) => options.memory, "useFactory"),
7588
+ // Personal agents resolve no memory scope (`personalAgentScopes`): under a signed-in Poppy
7589
+ // conversation the actor is the account, and it must neither read nor write its memories.
7590
+ useFactory: /* @__PURE__ */ __name((options) => options.memory === void 0 ? void 0 : {
7591
+ ...options.memory,
7592
+ scopes: (0, import_nestjs_agent_core40.personalAgentScopes)(options.memory.scopes)
7593
+ }, "useFactory"),
7527
7594
  inject: [
7528
7595
  import_nestjs_agent_core40.AGENT_OPTIONS
7529
7596
  ]
@@ -7537,7 +7604,10 @@ function sharedProviders(durable, engine) {
7537
7604
  },
7538
7605
  {
7539
7606
  provide: import_nestjs_agent_core40.AGENT_ROLES_POLICY,
7540
- useFactory: /* @__PURE__ */ __name((options, modules) => resolveRolesPolicy(options, modules), "useFactory"),
7607
+ // Personal agents (a Poppy conversation, a Poppy session's MCP token) reach only the tools
7608
+ // written for them, and run only those of the scopes their user granted. A no-op for every
7609
+ // other actor.
7610
+ useFactory: /* @__PURE__ */ __name((options, modules) => (0, import_nestjs_agent_core40.personalAgentGate)(resolveRolesPolicy(options, modules)), "useFactory"),
7541
7611
  inject: [
7542
7612
  import_nestjs_agent_core40.AGENT_OPTIONS,
7543
7613
  import_core4.ModulesContainer