@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.
@@ -2,7 +2,7 @@ import { A2uiStreamOptions, a2uiThreadReplay } from '@dudousxd/nestjs-agent-core
2
2
  import { AgentAttachmentConfig, AttachmentStagingStore, AgentStore, Actor, ListActionProposals, ActionProposalView, ActionProposalMutationView, TextActionProposalVocabulary, AgentRunner, ModelCatalog, QuotaProvider, ActionApprovalMode, MessageAttachment, QuotaReport, ModelCatalogView, AgentHostContext, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver } from '@dudousxd/nestjs-agent-core';
3
3
  import { Request, Response } from 'express';
4
4
  import { UiCapabilities } from '@dudousxd/nestjs-agent-core/genui';
5
- import { b as AgentModuleOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter } from './chat-queue.service-wNWaoUN8.js';
5
+ import { b as AgentModuleOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter } from './chat-queue.service-CzXsKVb1.js';
6
6
 
7
7
  /** Default per-file size cap (20 MiB). */
8
8
  declare const DEFAULT_MAX_ATTACHMENT_BYTES: number;
@@ -2,7 +2,7 @@ import { A2uiStreamOptions, a2uiThreadReplay } from '@dudousxd/nestjs-agent-core
2
2
  import { AgentAttachmentConfig, AttachmentStagingStore, AgentStore, Actor, ListActionProposals, ActionProposalView, ActionProposalMutationView, TextActionProposalVocabulary, AgentRunner, ModelCatalog, QuotaProvider, ActionApprovalMode, MessageAttachment, QuotaReport, ModelCatalogView, AgentHostContext, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver } from '@dudousxd/nestjs-agent-core';
3
3
  import { Request, Response } from 'express';
4
4
  import { UiCapabilities } from '@dudousxd/nestjs-agent-core/genui';
5
- import { b as AgentModuleOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter } from './chat-queue.service-QIuTS-5c.cjs';
5
+ import { b as AgentModuleOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter } from './chat-queue.service-CF2fcJDx.cjs';
6
6
 
7
7
  /** Default per-file size cap (20 MiB). */
8
8
  declare const DEFAULT_MAX_ATTACHMENT_BYTES: number;
package/dist/index.cjs CHANGED
@@ -4985,9 +4985,19 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
4985
4985
  this.logger.warn(`Agent "${meta.name}" hands off to ${target.name}, which is not an @Agent \u2014 skipped.`);
4986
4986
  continue;
4987
4987
  }
4988
- edges.push(detached ? {
4988
+ const roles = typeof entry === "function" ? void 0 : entry.roles;
4989
+ const ability = typeof entry === "function" ? void 0 : entry.ability;
4990
+ edges.push(detached || roles !== void 0 || ability !== void 0 ? {
4989
4991
  agent: targetMeta.name,
4990
- detached: true
4992
+ ...detached ? {
4993
+ detached: true
4994
+ } : {},
4995
+ ...roles !== void 0 ? {
4996
+ roles
4997
+ } : {},
4998
+ ...ability !== void 0 ? {
4999
+ ability
5000
+ } : {}
4991
5001
  } : targetMeta.name);
4992
5002
  }
4993
5003
  return edges;
@@ -5199,7 +5209,7 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
5199
5209
  let delegates = 0;
5200
5210
  for (const definition of this.agents.list()) {
5201
5211
  for (const edge of definition.delegatesTo ?? []) {
5202
- const { agent: target, detached } = (0, import_nestjs_agent_core24.normalizeDelegation)(edge);
5212
+ const { agent: target, detached, roles, ability } = (0, import_nestjs_agent_core24.normalizeDelegation)(edge);
5203
5213
  const targetDefinition = this.agents.get(target);
5204
5214
  if (targetDefinition === void 0) {
5205
5215
  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.`);
@@ -5221,6 +5231,12 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
5221
5231
  ...detached ? {
5222
5232
  detached: true
5223
5233
  } : {},
5234
+ ...roles !== void 0 ? {
5235
+ roles
5236
+ } : {},
5237
+ ...ability !== void 0 ? {
5238
+ ability
5239
+ } : {},
5224
5240
  description,
5225
5241
  inputSchema: import_zod.z.object({
5226
5242
  task: import_zod.z.string()
@@ -5633,6 +5649,35 @@ var ActionProposalWorkerService = class _ActionProposalWorkerService {
5633
5649
  worker;
5634
5650
  logger = new import_common25.Logger(_ActionProposalWorkerService.name);
5635
5651
  settledListeners = /* @__PURE__ */ new Set();
5652
+ admittedListeners = /* @__PURE__ */ new Set();
5653
+ /**
5654
+ * Run `listener` once a settled proposal's outcome is written to its thread by this process's
5655
+ * worker (the thread was free) — what a module uses to CONTINUE a conversation once an action it
5656
+ * proposed ran (a Poppy connect: the next turn goes on with what was asked). Next to
5657
+ * `actionProposalWorker.onAdmitted`; a listener that throws is logged and does not stop the
5658
+ * others. Returns the unsubscribe.
5659
+ */
5660
+ onAdmitted(listener) {
5661
+ this.admittedListeners.add(listener);
5662
+ return () => {
5663
+ this.admittedListeners.delete(listener);
5664
+ };
5665
+ }
5666
+ async admitted(outcome) {
5667
+ const configured = this.options.actionProposalWorker?.onAdmitted;
5668
+ for (const listener of [
5669
+ ...configured ? [
5670
+ configured
5671
+ ] : [],
5672
+ ...this.admittedListeners
5673
+ ]) {
5674
+ try {
5675
+ await listener(outcome);
5676
+ } catch (error) {
5677
+ this.logger.error(error);
5678
+ }
5679
+ }
5680
+ }
5636
5681
  /**
5637
5682
  * Run `listener` after every proposal this process's worker settles — how a module relays an
5638
5683
  * outcome somewhere the turn's stream no longer reaches (a text channel's conversation). Next to
@@ -5676,6 +5721,7 @@ var ActionProposalWorkerService = class _ActionProposalWorkerService {
5676
5721
  workerId: (0, import_node_crypto2.randomUUID)(),
5677
5722
  ...this.options.actionProposalWorker,
5678
5723
  onSettled: /* @__PURE__ */ __name((proposal) => this.settled(proposal), "onSettled"),
5724
+ onAdmitted: /* @__PURE__ */ __name((outcome) => this.admitted(outcome), "onAdmitted"),
5679
5725
  executor: new import_nestjs_agent_core30.ActionProposalExecutor({
5680
5726
  resolver,
5681
5727
  resolveExecution: /* @__PURE__ */ __name(async (proposal, actor) => {
@@ -6494,6 +6540,13 @@ function forwardingPolicy(wrapper) {
6494
6540
  throw new Error("AgentModule: the AGENT_ROLES_POLICY bound by another module is not ready yet");
6495
6541
  }
6496
6542
  return policy.can(actor, tool);
6543
+ },
6544
+ canOffer(actor, tool) {
6545
+ const policy = wrapper.instance;
6546
+ if (policy === void 0 || policy === null) {
6547
+ throw new Error("AgentModule: the AGENT_ROLES_POLICY bound by another module is not ready yet");
6548
+ }
6549
+ return policy.canOffer ? policy.canOffer(actor, tool) : policy.can(actor, tool);
6497
6550
  }
6498
6551
  };
6499
6552
  }
@@ -6535,7 +6588,14 @@ function sharedProviders(durable, engine) {
6535
6588
  // drift, and a user would be offered a skill the agent cannot reach. `undefined` when the
6536
6589
  // host configured none — which is what keeps the turn's checkpoint sequence unchanged.
6537
6590
  provide: import_nestjs_agent_core34.AGENT_SKILLS,
6538
- useFactory: /* @__PURE__ */ __name((options, declared) => resolveSkillsConfig(options.skills, declared), "useFactory"),
6591
+ // Personal agents resolve no skill scope (`personalAgentScopes`): nothing of the app's to load.
6592
+ useFactory: /* @__PURE__ */ __name((options, declared) => {
6593
+ const skills = resolveSkillsConfig(options.skills, declared);
6594
+ return skills === void 0 ? void 0 : {
6595
+ ...skills,
6596
+ scopes: (0, import_nestjs_agent_core34.personalAgentScopes)(skills.scopes)
6597
+ };
6598
+ }, "useFactory"),
6539
6599
  inject: [
6540
6600
  import_nestjs_agent_core34.AGENT_OPTIONS,
6541
6601
  import_nestjs_agent_core34.AGENT_SKILL_SOURCES
@@ -6545,7 +6605,12 @@ function sharedProviders(durable, engine) {
6545
6605
  // One resolution, shared by the loop's deps and the read-back endpoint: a person has to be
6546
6606
  // shown what the model was shown, and two resolutions would eventually disagree about that.
6547
6607
  provide: import_nestjs_agent_core34.AGENT_MEMORY,
6548
- useFactory: /* @__PURE__ */ __name((options) => options.memory, "useFactory"),
6608
+ // Personal agents resolve no memory scope (`personalAgentScopes`): under a signed-in Poppy
6609
+ // conversation the actor is the account, and it must neither read nor write its memories.
6610
+ useFactory: /* @__PURE__ */ __name((options) => options.memory === void 0 ? void 0 : {
6611
+ ...options.memory,
6612
+ scopes: (0, import_nestjs_agent_core34.personalAgentScopes)(options.memory.scopes)
6613
+ }, "useFactory"),
6549
6614
  inject: [
6550
6615
  import_nestjs_agent_core34.AGENT_OPTIONS
6551
6616
  ]
@@ -6559,7 +6624,10 @@ function sharedProviders(durable, engine) {
6559
6624
  },
6560
6625
  {
6561
6626
  provide: import_nestjs_agent_core34.AGENT_ROLES_POLICY,
6562
- useFactory: /* @__PURE__ */ __name((options, modules) => resolveRolesPolicy(options, modules), "useFactory"),
6627
+ // Personal agents (a Poppy conversation, a Poppy session's MCP token) reach only the tools
6628
+ // written for them, and run only those of the scopes their user granted. A no-op for every
6629
+ // other actor.
6630
+ useFactory: /* @__PURE__ */ __name((options, modules) => (0, import_nestjs_agent_core34.personalAgentGate)(resolveRolesPolicy(options, modules)), "useFactory"),
6563
6631
  inject: [
6564
6632
  import_nestjs_agent_core34.AGENT_OPTIONS,
6565
6633
  import_core4.ModulesContainer