@dudousxd/nestjs-agent 1.10.0 → 1.11.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.cjs CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  AgentService: () => AgentService,
35
35
  AiTool: () => AiTool,
36
36
  AiToolDiscoveryService: () => AiToolDiscoveryService,
37
+ AnonymousActorResolver: () => AnonymousActorResolver,
37
38
  AttachmentsController: () => AttachmentsController,
38
39
  DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES: () => DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,
39
40
  DEFAULT_MAX_ATTACHMENT_BYTES: () => DEFAULT_MAX_ATTACHMENT_BYTES,
@@ -55,14 +56,17 @@ __export(index_exports, {
55
56
  SystemPromptContributor: () => SystemPromptContributor,
56
57
  ToolsController: () => ToolsController,
57
58
  declaredSkillProvider: () => declaredSkillProvider,
59
+ defaultRequestUserMapper: () => defaultRequestUserMapper,
58
60
  delegateToolName: () => delegateToolName,
59
61
  provideAgentTool: () => provideAgentTool,
60
62
  provideAgentTools: () => provideAgentTools,
61
63
  readAgentMetadata: () => readAgentMetadata,
62
64
  readAiToolMetadata: () => readAiToolMetadata,
63
65
  readSkillMetadata: () => readSkillMetadata,
66
+ requestUserActorResolver: () => requestUserActorResolver,
64
67
  resolveSkillsConfig: () => resolveSkillsConfig,
65
68
  skillScope: () => skillScope,
69
+ toolNameFromClass: () => toolNameFromClass,
66
70
  utcDay: () => utcDay
67
71
  });
68
72
  module.exports = __toCommonJS(index_exports);
@@ -193,7 +197,7 @@ var AgentDepsFactory2 = class {
193
197
  } : {},
194
198
  registry: this.registry,
195
199
  promptContributors: this.promptContributors,
196
- systemPrompt: definition?.systemPrompt ?? "You are a helpful assistant.",
200
+ systemPrompt: definition?.systemPrompt ?? this.options.systemPrompt ?? "You are a helpful assistant.",
197
201
  maxSteps: definition?.maxSteps ?? 8,
198
202
  ...definition?.maxDelegationDepth !== void 0 ? {
199
203
  maxDelegationDepth: definition.maxDelegationDepth
@@ -2718,9 +2722,23 @@ var import_zod = require("zod");
2718
2722
  // src/decorator/ai-tool.decorator.ts
2719
2723
  var import_reflect_metadata3 = require("reflect-metadata");
2720
2724
  var AI_TOOL_METADATA = /* @__PURE__ */ Symbol("nestjs-agent:ai-tool");
2725
+ function toolNameFromClass(className) {
2726
+ const base = className.replace(/Tool$/, "") || className;
2727
+ const leadingCaps = /^[A-Z]+(?=[A-Z][a-z]|$)/.exec(base)?.[0];
2728
+ if (leadingCaps !== void 0 && leadingCaps.length > 1) {
2729
+ return leadingCaps.toLowerCase() + base.slice(leadingCaps.length);
2730
+ }
2731
+ return base.charAt(0).toLowerCase() + base.slice(1);
2732
+ }
2733
+ __name(toolNameFromClass, "toolNameFromClass");
2721
2734
  function AiTool(options) {
2722
2735
  return (target) => {
2723
- Reflect.defineMetadata(AI_TOOL_METADATA, options, target);
2736
+ const resolved = {
2737
+ ...options,
2738
+ name: options.name ?? toolNameFromClass(target.name),
2739
+ kind: options.kind ?? "read"
2740
+ };
2741
+ Reflect.defineMetadata(AI_TOOL_METADATA, resolved, target);
2724
2742
  };
2725
2743
  }
2726
2744
  __name(AiTool, "AiTool");
@@ -3209,6 +3227,93 @@ var LedgerQuotaStore = class {
3209
3227
  }
3210
3228
  };
3211
3229
 
3230
+ // src/resolver/anonymous-actor-resolver.ts
3231
+ var import_node_crypto = require("crypto");
3232
+ var TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/;
3233
+ var MINTED = /* @__PURE__ */ Symbol("nestjs-agent:anonymous-token");
3234
+ function readCookie(req, name) {
3235
+ const header = req.headers?.cookie;
3236
+ const raw = Array.isArray(header) ? header.join("; ") : header;
3237
+ if (raw === void 0) return void 0;
3238
+ for (const pair of raw.split(";")) {
3239
+ const index = pair.indexOf("=");
3240
+ if (index === -1) continue;
3241
+ if (pair.slice(0, index).trim() === name) {
3242
+ try {
3243
+ return decodeURIComponent(pair.slice(index + 1).trim());
3244
+ } catch {
3245
+ return void 0;
3246
+ }
3247
+ }
3248
+ }
3249
+ return void 0;
3250
+ }
3251
+ __name(readCookie, "readCookie");
3252
+ function isHttps(req) {
3253
+ if (req.secure === true) return true;
3254
+ const forwarded = req.headers?.["x-forwarded-proto"];
3255
+ const proto = Array.isArray(forwarded) ? forwarded[0] : forwarded;
3256
+ return proto?.split(",")[0]?.trim() === "https";
3257
+ }
3258
+ __name(isHttps, "isHttps");
3259
+ var AnonymousActorResolver = class {
3260
+ static {
3261
+ __name(this, "AnonymousActorResolver");
3262
+ }
3263
+ options;
3264
+ cookieName;
3265
+ roles;
3266
+ constructor(options = {}) {
3267
+ this.options = options;
3268
+ this.cookieName = options.cookieName ?? "agent_anon";
3269
+ this.roles = options.roles ?? [
3270
+ "anonymous"
3271
+ ];
3272
+ }
3273
+ resolve(request) {
3274
+ const req = typeof request === "object" && request !== null ? request : {};
3275
+ let token = req[MINTED] ?? readCookie(req, this.cookieName);
3276
+ if (token === void 0 || !TOKEN_PATTERN.test(token)) {
3277
+ token = (0, import_node_crypto.randomBytes)(32).toString("base64url");
3278
+ req[MINTED] = token;
3279
+ this.setCookie(req, token);
3280
+ }
3281
+ const digest = (0, import_node_crypto.createHash)("sha256").update(token).digest("base64url").slice(0, 32);
3282
+ return {
3283
+ id: `anon:${digest}`,
3284
+ roles: [
3285
+ ...this.roles
3286
+ ]
3287
+ };
3288
+ }
3289
+ setCookie(req, token) {
3290
+ const res = req.res;
3291
+ if (res?.setHeader === void 0 || res.headersSent === true) return;
3292
+ const sameSite = this.options.sameSite ?? "lax";
3293
+ const secureOption = this.options.secure ?? "auto";
3294
+ const secure = sameSite === "none" || (secureOption === "auto" ? isHttps(req) : secureOption);
3295
+ const maxAge = Math.round((this.options.maxAgeDays ?? 365) * 24 * 60 * 60);
3296
+ const cookie = [
3297
+ `${this.cookieName}=${token}`,
3298
+ `Path=${this.options.path ?? "/"}`,
3299
+ `Max-Age=${maxAge}`,
3300
+ "HttpOnly",
3301
+ `SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`,
3302
+ ...secure ? [
3303
+ "Secure"
3304
+ ] : []
3305
+ ].join("; ");
3306
+ const existing = res.getHeader?.("Set-Cookie");
3307
+ const list = Array.isArray(existing) ? existing.map(String) : existing !== void 0 ? [
3308
+ String(existing)
3309
+ ] : [];
3310
+ res.setHeader("Set-Cookie", [
3311
+ ...list,
3312
+ cookie
3313
+ ]);
3314
+ }
3315
+ };
3316
+
3212
3317
  // src/runner/inline-agent-runner.ts
3213
3318
  var import_nestjs_agent_core21 = require("@dudousxd/nestjs-agent-core");
3214
3319
  var import_common18 = require("@nestjs/common");
@@ -3683,7 +3788,51 @@ function _ts_decorate19(decorators, target, key, desc) {
3683
3788
  }
3684
3789
  __name(_ts_decorate19, "_ts_decorate");
3685
3790
  var DEFAULT_PATH = "agent";
3686
- function sharedProviders(durable, includeStore) {
3791
+ var logger = new import_common19.Logger("AgentModule");
3792
+ function externalStoreWrapper(modules) {
3793
+ for (const module2 of modules.values()) {
3794
+ if (module2.metatype === AgentModule) continue;
3795
+ const wrapper = module2.providers.get(import_nestjs_agent_core23.AGENT_STORE);
3796
+ if (wrapper !== void 0) return wrapper;
3797
+ }
3798
+ return void 0;
3799
+ }
3800
+ __name(externalStoreWrapper, "externalStoreWrapper");
3801
+ function forwardingStore(wrapper) {
3802
+ const target = /* @__PURE__ */ __name(() => {
3803
+ const instance = wrapper.instance;
3804
+ if (instance === void 0 || instance === null) {
3805
+ throw new Error("AgentModule: the AGENT_STORE bound by another module is not ready yet");
3806
+ }
3807
+ return instance;
3808
+ }, "target");
3809
+ return new Proxy({}, {
3810
+ get(_, property) {
3811
+ const store = target();
3812
+ const value = store[property];
3813
+ return typeof value === "function" ? value.bind(store) : value;
3814
+ },
3815
+ has(_, property) {
3816
+ return property in target();
3817
+ }
3818
+ });
3819
+ }
3820
+ __name(forwardingStore, "forwardingStore");
3821
+ function resolveStore(options, modules) {
3822
+ if (options.store !== void 0) return options.store;
3823
+ const external = externalStoreWrapper(modules);
3824
+ if (external !== void 0) return forwardingStore(external);
3825
+ logger.warn("No `store` configured and no store module imported \u2014 using the in-memory store. Threads are lost on restart and not shared between processes: not for production. Pass `store`, or import a store module (e.g. MikroOrmAgentStoreModule.forFeature()).");
3826
+ return new import_nestjs_agent_core23.InMemoryAgentStore();
3827
+ }
3828
+ __name(resolveStore, "resolveStore");
3829
+ function resolveCatalog(options) {
3830
+ if (options.models !== void 0) return options.models;
3831
+ const carried = options.model.catalog;
3832
+ return carried !== void 0 && typeof carried.list === "function" ? carried : void 0;
3833
+ }
3834
+ __name(resolveCatalog, "resolveCatalog");
3835
+ function sharedProviders(durable) {
3687
3836
  const providers = [
3688
3837
  {
3689
3838
  provide: import_nestjs_agent_core23.AGENT_TOOL_REGISTRY,
@@ -3741,7 +3890,11 @@ function sharedProviders(durable, includeStore) {
3741
3890
  },
3742
3891
  {
3743
3892
  provide: import_nestjs_agent_core23.AGENT_ACTOR_RESOLVER,
3744
- useFactory: /* @__PURE__ */ __name((options) => options.actorResolver, "useFactory"),
3893
+ useFactory: /* @__PURE__ */ __name((options) => {
3894
+ if (options.actorResolver !== void 0) return options.actorResolver;
3895
+ logger.warn("No `actorResolver` configured \u2014 the agent endpoints are PUBLIC: every browser gets its own anonymous identity (an HttpOnly cookie). Set `actorResolver: requestUserActorResolver()` (or your own) to require login.");
3896
+ return new AnonymousActorResolver();
3897
+ }, "useFactory"),
3745
3898
  inject: [
3746
3899
  import_nestjs_agent_core23.AGENT_OPTIONS
3747
3900
  ]
@@ -3775,7 +3928,7 @@ function sharedProviders(durable, includeStore) {
3775
3928
  },
3776
3929
  {
3777
3930
  provide: import_nestjs_agent_core23.AGENT_MODEL_CATALOG,
3778
- useFactory: /* @__PURE__ */ __name((o) => o.models, "useFactory"),
3931
+ useFactory: /* @__PURE__ */ __name((o) => resolveCatalog(o), "useFactory"),
3779
3932
  inject: [
3780
3933
  import_nestjs_agent_core23.AGENT_OPTIONS
3781
3934
  ]
@@ -3800,15 +3953,14 @@ function sharedProviders(durable, includeStore) {
3800
3953
  useExisting: AgentApprovalPortAdapter
3801
3954
  }
3802
3955
  ];
3803
- if (includeStore) {
3804
- providers.push({
3805
- provide: import_nestjs_agent_core23.AGENT_STORE,
3806
- useFactory: /* @__PURE__ */ __name((o) => o.store, "useFactory"),
3807
- inject: [
3808
- import_nestjs_agent_core23.AGENT_OPTIONS
3809
- ]
3810
- });
3811
- }
3956
+ providers.push({
3957
+ provide: import_nestjs_agent_core23.AGENT_STORE,
3958
+ useFactory: /* @__PURE__ */ __name((o, modules) => resolveStore(o, modules), "useFactory"),
3959
+ inject: [
3960
+ import_nestjs_agent_core23.AGENT_OPTIONS,
3961
+ import_core4.ModulesContainer
3962
+ ]
3963
+ });
3812
3964
  if (durable) {
3813
3965
  providers.push({
3814
3966
  provide: import_nestjs_agent_core23.AGENT_RUNNER,
@@ -3834,7 +3986,7 @@ function sharedProviders(durable, includeStore) {
3834
3986
  return providers;
3835
3987
  }
3836
3988
  __name(sharedProviders, "sharedProviders");
3837
- function exportsFor(includeStore) {
3989
+ function exportsFor() {
3838
3990
  return [
3839
3991
  import_nestjs_agent_core23.AGENT_OPTIONS,
3840
3992
  import_nestjs_agent_core23.AGENT_TOOL_REGISTRY,
@@ -3843,9 +3995,7 @@ function exportsFor(includeStore) {
3843
3995
  import_nestjs_agent_core23.AGENT_ROLES_POLICY,
3844
3996
  import_nestjs_agent_core23.AGENT_ACTOR_RESOLVER,
3845
3997
  import_nestjs_agent_core23.AGENT_MODEL,
3846
- ...includeStore ? [
3847
- import_nestjs_agent_core23.AGENT_STORE
3848
- ] : [],
3998
+ import_nestjs_agent_core23.AGENT_STORE,
3849
3999
  import_nestjs_agent_core23.AGENT_QUOTA_STORE,
3850
4000
  import_nestjs_agent_core23.AGENT_MODEL_CATALOG,
3851
4001
  import_nestjs_agent_core23.AGENT_QUOTA_PROVIDER,
@@ -3916,7 +4066,6 @@ var AgentModule = class _AgentModule {
3916
4066
  }
3917
4067
  static forRoot(options) {
3918
4068
  const path = options.path ?? DEFAULT_PATH;
3919
- const includeStore = options.store !== void 0;
3920
4069
  applyGuards(options.guards);
3921
4070
  return {
3922
4071
  module: _AgentModule,
@@ -3931,15 +4080,14 @@ var AgentModule = class _AgentModule {
3931
4080
  provide: import_nestjs_agent_core23.AGENT_OPTIONS,
3932
4081
  useValue: options
3933
4082
  },
3934
- ...sharedProviders(options.durable ?? false, includeStore),
4083
+ ...sharedProviders(options.durable ?? false),
3935
4084
  ...guardProviders(options.guards)
3936
4085
  ],
3937
- exports: exportsFor(includeStore)
4086
+ exports: exportsFor()
3938
4087
  };
3939
4088
  }
3940
4089
  static forRootAsync(options) {
3941
4090
  const path = options.path ?? DEFAULT_PATH;
3942
- const includeStore = options.externalStore !== true;
3943
4091
  applyGuards(options.guards);
3944
4092
  return {
3945
4093
  module: _AgentModule,
@@ -3966,10 +4114,10 @@ var AgentModule = class _AgentModule {
3966
4114
  }), "useFactory"),
3967
4115
  inject: options.inject ?? []
3968
4116
  },
3969
- ...sharedProviders(options.durable ?? false, includeStore),
4117
+ ...sharedProviders(options.durable ?? false),
3970
4118
  ...guardProviders(options.guards)
3971
4119
  ],
3972
- exports: exportsFor(includeStore)
4120
+ exports: exportsFor()
3973
4121
  };
3974
4122
  }
3975
4123
  };
@@ -4009,6 +4157,49 @@ var HeaderActorResolver = class {
4009
4157
  }
4010
4158
  };
4011
4159
 
4160
+ // src/resolver/request-user-actor-resolver.ts
4161
+ var import_common21 = require("@nestjs/common");
4162
+ function field(user, ...names) {
4163
+ for (const name of names) {
4164
+ const value = user[name];
4165
+ if (value !== void 0 && value !== null && value !== "") return value;
4166
+ }
4167
+ return void 0;
4168
+ }
4169
+ __name(field, "field");
4170
+ function defaultRequestUserMapper(user) {
4171
+ const id = field(user, "id", "sub", "_id", "userId");
4172
+ if (id === void 0) {
4173
+ throw new import_common21.UnauthorizedException("requestUserActorResolver: req.user has no id/sub/_id/userId \u2014 pass a mapper: requestUserActorResolver((user) => ({ id: \u2026, roles: \u2026 }))");
4174
+ }
4175
+ const rawRoles = field(user, "roles", "role");
4176
+ const roles = Array.isArray(rawRoles) ? rawRoles.map(String) : typeof rawRoles === "string" ? [
4177
+ rawRoles
4178
+ ] : [];
4179
+ const tenant = field(user, "tenantRef", "tenantId", "orgId");
4180
+ return {
4181
+ id: String(id),
4182
+ roles,
4183
+ ...tenant !== void 0 ? {
4184
+ tenantRef: String(tenant)
4185
+ } : {}
4186
+ };
4187
+ }
4188
+ __name(defaultRequestUserMapper, "defaultRequestUserMapper");
4189
+ function requestUserActorResolver(map) {
4190
+ return {
4191
+ async resolve(req) {
4192
+ const user = typeof req === "object" && req !== null ? req.user : void 0;
4193
+ if (user === void 0 || user === null || user === false) {
4194
+ throw new import_common21.UnauthorizedException("Sign in to use the agent.");
4195
+ }
4196
+ if (map !== void 0) return map(user, req);
4197
+ return defaultRequestUserMapper(user);
4198
+ }
4199
+ };
4200
+ }
4201
+ __name(requestUserActorResolver, "requestUserActorResolver");
4202
+
4012
4203
  // src/index.ts
4013
4204
  __reExport(index_exports, require("@dudousxd/nestjs-agent-core"), module.exports);
4014
4205
  // Annotate the CommonJS export names for ESM import in node:
@@ -4025,6 +4216,7 @@ __reExport(index_exports, require("@dudousxd/nestjs-agent-core"), module.exports
4025
4216
  AgentService,
4026
4217
  AiTool,
4027
4218
  AiToolDiscoveryService,
4219
+ AnonymousActorResolver,
4028
4220
  AttachmentsController,
4029
4221
  DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,
4030
4222
  DEFAULT_MAX_ATTACHMENT_BYTES,
@@ -4046,14 +4238,17 @@ __reExport(index_exports, require("@dudousxd/nestjs-agent-core"), module.exports
4046
4238
  SystemPromptContributor,
4047
4239
  ToolsController,
4048
4240
  declaredSkillProvider,
4241
+ defaultRequestUserMapper,
4049
4242
  delegateToolName,
4050
4243
  provideAgentTool,
4051
4244
  provideAgentTools,
4052
4245
  readAgentMetadata,
4053
4246
  readAiToolMetadata,
4054
4247
  readSkillMetadata,
4248
+ requestUserActorResolver,
4055
4249
  resolveSkillsConfig,
4056
4250
  skillScope,
4251
+ toolNameFromClass,
4057
4252
  utcDay,
4058
4253
  ...require("@dudousxd/nestjs-agent-core")
4059
4254
  });