@happyvertical/smrt-agents 0.33.1 → 0.34.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.
Files changed (33) hide show
  1. package/README.md +2 -1
  2. package/dist/chunks/{config-BYbOxt24.js → config-JYiYqNE-.js} +18 -8
  3. package/dist/chunks/config-JYiYqNE-.js.map +1 -0
  4. package/dist/config.d.ts +11 -2
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/index.js +19 -9
  7. package/dist/index.js.map +1 -1
  8. package/dist/manifest.json +2 -2
  9. package/dist/schedule.d.ts +11 -2
  10. package/dist/schedule.d.ts.map +1 -1
  11. package/dist/server.js +1 -1
  12. package/dist/smrt-knowledge.json +8 -4
  13. package/dist/svelte/admin.d.ts +20 -0
  14. package/dist/svelte/admin.d.ts.map +1 -0
  15. package/dist/svelte/admin.js +4 -0
  16. package/dist/svelte/components/AgentAdminPanel.svelte +111 -0
  17. package/dist/svelte/components/AgentAdminPanel.svelte.d.ts +25 -0
  18. package/dist/svelte/components/AgentAdminPanel.svelte.d.ts.map +1 -0
  19. package/dist/svelte/components/AgentAdminTabs.svelte +277 -0
  20. package/dist/svelte/components/AgentAdminTabs.svelte.d.ts +23 -0
  21. package/dist/svelte/components/AgentAdminTabs.svelte.d.ts.map +1 -0
  22. package/dist/svelte/components/AgentSettingsShell.svelte +322 -0
  23. package/dist/svelte/components/AgentSettingsShell.svelte.d.ts +33 -0
  24. package/dist/svelte/components/AgentSettingsShell.svelte.d.ts.map +1 -0
  25. package/dist/svelte/components/__tests__/AgentSettingsShell.tablist.test.js +94 -0
  26. package/dist/svelte/i18n.d.ts +6 -0
  27. package/dist/svelte/i18n.d.ts.map +1 -1
  28. package/dist/svelte/i18n.js +9 -0
  29. package/dist/svelte/index.d.ts +13 -3
  30. package/dist/svelte/index.d.ts.map +1 -1
  31. package/dist/svelte/index.js +9 -3
  32. package/package.json +17 -9
  33. package/dist/chunks/config-BYbOxt24.js.map +0 -1
package/README.md CHANGED
@@ -136,4 +136,5 @@ which work is an intentional intervention.
136
136
  - `@happyvertical/ai` -- AI client (SDK)
137
137
  - `@happyvertical/files` -- Filesystem utilities (SDK)
138
138
  - `@happyvertical/utils` -- Shared utilities (SDK)
139
- - Peer (optional): `@happyvertical/smrt-svelte`, `svelte`
139
+ - `@happyvertical/smrt-ui` -- UI runtime (i18n client, primitives, module registry) for the optional `./svelte` components, including the agent-admin shells (`AgentAdminPanel`, `AgentAdminTabs`, `AgentSettingsShell`) that moved here from smrt-svelte in #1589
140
+ - Peer (optional): `svelte`
@@ -1,5 +1,5 @@
1
1
  import { ObjectRegistry, getClassName, field, smrt, SmrtObject, SmrtCollection } from "@happyvertical/smrt-core";
2
- import { tenantId, TenantScoped } from "@happyvertical/smrt-tenancy";
2
+ import { tenantId, TenantScoped, queryGlobal, queryWithGlobals } from "@happyvertical/smrt-tenancy";
3
3
  function getAgentTypeName(name) {
4
4
  const registered = ObjectRegistry.getClass(name);
5
5
  return registered?.qualifiedName || registered?.name || name;
@@ -151,21 +151,31 @@ class AgentConfigCollection extends SmrtCollection {
151
151
  return this.list({ where: { tenantId: tenantId2 } });
152
152
  }
153
153
  /**
154
- * Find all global configs (not associated with any tenant)
154
+ * Find all global configs (not associated with any tenant).
155
+ *
156
+ * Routes through the shared tenant-global helper so it does not throw under
157
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
158
+ * flagged as an isolation violation). (#1600)
159
+ *
155
160
  * @returns Array of global AgentConfig objects
156
161
  */
157
162
  async findGlobal() {
158
- return this.list({ where: { tenantId: null } });
163
+ return queryGlobal(this);
159
164
  }
160
165
  /**
161
- * Find configs for a tenant including global configs
166
+ * Find configs for a tenant including global configs.
167
+ *
168
+ * Fails closed if an active tenant context requests a different tenant's
169
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
170
+ *
162
171
  * @param tenantId - Tenant ID to include
163
172
  * @returns Array of AgentConfig objects for the tenant and global configs
164
173
  */
165
174
  async findWithGlobals(tenantId2) {
166
- return this.query(
167
- `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,
168
- [tenantId2]
175
+ return queryWithGlobals(
176
+ this,
177
+ tenantId2,
178
+ "AgentConfig.findWithGlobals"
169
179
  );
170
180
  }
171
181
  }
@@ -176,4 +186,4 @@ export {
176
186
  AgentConfigCollection as c,
177
187
  getAgentTypeName as g
178
188
  };
179
- //# sourceMappingURL=config-BYbOxt24.js.map
189
+ //# sourceMappingURL=config-JYiYqNE-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-JYiYqNE-.js","sources":["../../src/identity.ts","../../src/config.ts"],"sourcesContent":["import { getClassName, ObjectRegistry } from '@happyvertical/smrt-core';\n\n/**\n * Return the canonical agent type identifier for storage and dispatch routing.\n *\n * Uses the registry's qualified name when available and falls back to the input\n * name for dynamically defined or unregistered classes.\n */\nexport function getAgentTypeName(name: string): string {\n const registered = ObjectRegistry.getClass(name);\n return registered?.qualifiedName || registered?.name || name;\n}\n\n/**\n * Return the human-readable class name for UI and logs.\n */\nexport function getAgentClassName(name: string): string {\n const registered = ObjectRegistry.getClass(name);\n return registered?.name || getClassName(name);\n}\n\n/**\n * Return all meaningful aliases for an agent type.\n *\n * The qualified name is first so persistence lookups prefer canonical rows,\n * while the simple class name keeps legacy rows discoverable during migration.\n */\nexport function getAgentTypeAliases(name: string): string[] {\n return Array.from(\n new Set([getAgentTypeName(name), getAgentClassName(name)].filter(Boolean)),\n );\n}\n","/**\n * AgentConfig - Persistent configuration storage for agents\n *\n * This module provides database-backed configuration for agents,\n * enabling consuming apps to persist agent settings.\n *\n * @module\n */\n\nimport {\n field,\n type SmrtClassOptions,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n queryGlobal,\n queryWithGlobals,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport { getAgentTypeName } from './identity.js';\n\n/**\n * AgentConfig stores agent configuration in the database\n *\n * Each config record maps to a UI slot for an agent instance:\n * - agentId: The agent instance's ID\n * - agentClass: The canonical agent type (qualified name when available)\n * - slotId: The configuration slot (e.g., 'sources', 'settings')\n * - configData: JSON object containing the configuration\n *\n * @example\n * ```typescript\n * // Save config for an agent slot\n * const config = new AgentConfig({\n * agentId: agent.id,\n * agentClass: 'Praeco',\n * slotId: 'sources',\n * configData: { scrapers: ['civicweb', 'govstack'] },\n * db: options.db\n * });\n * await config.initialize();\n * await config.save();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'agent_configs',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class AgentConfig extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global agent configs\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * ID of the agent instance this config belongs to\n */\n @field({ type: 'text' })\n agentId: string = '';\n\n /**\n * Canonical agent type for this config (qualified name when available)\n */\n @field({ type: 'text' })\n agentClass: string = '';\n\n /**\n * UI slot ID (e.g., 'sources', 'settings', 'reports')\n */\n @field({ type: 'text' })\n slotId: string = '';\n\n /**\n * Configuration data stored as JSON\n *\n * Sensitive (#1540): agent config blobs routinely carry API keys/credentials,\n * so this is excluded from generated API/MCP responses and rejected as a\n * `where` filter key.\n */\n @field({ type: 'json', sensitive: true })\n configData: Record<string, any> = {};\n\n /**\n * Schema version for future migrations\n */\n @field({ type: 'integer' })\n schemaVersion: number = 1;\n\n /**\n * Load all configs for a specific agent\n *\n * @param agentId - Agent instance ID\n * @param options - Database options\n * @returns Map of slotId → configData\n */\n static async forAgent(\n agentId: string,\n options: SmrtClassOptions,\n ): Promise<Map<string, any>> {\n const configsByAgent = await AgentConfig.forAgents([agentId], options);\n return configsByAgent.get(agentId) ?? new Map();\n }\n\n /**\n * Load configs for multiple agents in a single query.\n *\n * @param agentIds - Agent instance IDs\n * @param options - Database options\n * @returns Map of agentId -> (slotId -> configData)\n */\n static async forAgents(\n agentIds: string[],\n options: SmrtClassOptions,\n ): Promise<Map<string, Map<string, any>>> {\n const configsByAgent = new Map<string, Map<string, any>>();\n if (agentIds.length === 0) {\n return configsByAgent;\n }\n\n const collection = await AgentConfigCollection.create(options);\n const configs = await collection.list({\n where: { 'agentId in': agentIds },\n });\n\n for (const config of configs) {\n if (!configsByAgent.has(config.agentId)) {\n configsByAgent.set(config.agentId, new Map());\n }\n configsByAgent.get(config.agentId)?.set(config.slotId, config.configData);\n }\n\n return configsByAgent;\n }\n\n /**\n * Load config for a specific agent and slot\n *\n * @param agentId - Agent instance ID\n * @param slotId - UI slot ID\n * @param options - Database options\n * @returns Config data or undefined if not found\n */\n static async forSlot(\n agentId: string,\n slotId: string,\n options: SmrtClassOptions,\n ): Promise<any | undefined> {\n const collection = await AgentConfigCollection.create(options);\n const configs = await collection.list({\n where: { agentId, slotId },\n limit: 1,\n });\n return configs[0]?.configData;\n }\n\n /**\n * Save or update config for an agent slot\n *\n * @param data - Config data including agentId, agentClass, slotId, configData\n * @param options - Database options\n * @returns Saved AgentConfig instance\n */\n static async saveSlot(\n data: {\n agentId: string;\n agentClass: string;\n slotId: string;\n configData: Record<string, any>;\n },\n options: SmrtClassOptions,\n ): Promise<AgentConfig> {\n const normalizedAgentClass = getAgentTypeName(data.agentClass);\n const collection = await AgentConfigCollection.create(options);\n\n // Check for existing config using list with where clause\n const existingConfigs = await collection.list({\n where: { agentId: data.agentId, slotId: data.slotId },\n limit: 1,\n });\n\n if (existingConfigs.length > 0) {\n // Update existing\n const existing = existingConfigs[0];\n existing.configData = data.configData;\n existing.agentClass = normalizedAgentClass;\n await existing.save();\n return existing;\n }\n\n // Create new\n const config = await collection.create({\n agentId: data.agentId,\n agentClass: normalizedAgentClass,\n slotId: data.slotId,\n configData: data.configData,\n slug: `${data.agentId}-${data.slotId}`,\n });\n await config.save();\n return config;\n }\n}\n\n/**\n * Collection for AgentConfig objects\n */\nexport class AgentConfigCollection extends SmrtCollection<AgentConfig> {\n static readonly _itemClass = AgentConfig;\n\n /**\n * Find all configs for a specific tenant\n * @param tenantId - Tenant ID to filter by\n * @returns Array of AgentConfig objects for the tenant\n */\n async findByTenant(tenantId: string): Promise<AgentConfig[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global configs (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global AgentConfig objects\n */\n async findGlobal(): Promise<AgentConfig[]> {\n return queryGlobal<AgentConfig>(this);\n }\n\n /**\n * Find configs for a tenant including global configs.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to include\n * @returns Array of AgentConfig objects for the tenant and global configs\n */\n async findWithGlobals(tenantId: string): Promise<AgentConfig[]> {\n return queryWithGlobals<AgentConfig>(\n this,\n tenantId,\n 'AgentConfig.findWithGlobals',\n );\n }\n}\n"],"names":["tenantId"],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -103,12 +103,21 @@ export declare class AgentConfigCollection extends SmrtCollection<AgentConfig> {
103
103
  */
104
104
  findByTenant(tenantId: string): Promise<AgentConfig[]>;
105
105
  /**
106
- * Find all global configs (not associated with any tenant)
106
+ * Find all global configs (not associated with any tenant).
107
+ *
108
+ * Routes through the shared tenant-global helper so it does not throw under
109
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
110
+ * flagged as an isolation violation). (#1600)
111
+ *
107
112
  * @returns Array of global AgentConfig objects
108
113
  */
109
114
  findGlobal(): Promise<AgentConfig[]>;
110
115
  /**
111
- * Find configs for a tenant including global configs
116
+ * Find configs for a tenant including global configs.
117
+ *
118
+ * Fails closed if an active tenant context requests a different tenant's
119
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
120
+ *
112
121
  * @param tenantId - Tenant ID to include
113
122
  * @returns Array of AgentConfig objects for the tenant and global configs
114
123
  */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,KAAK,gBAAgB,EACrB,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAIlC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAOa,WAAY,SAAQ,UAAU;IACzC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,OAAO,EAAE,MAAM,CAAM;IAErB;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IAEH,MAAM,EAAE,MAAM,CAAM;IAEpB;;;;;;OAMG;IAEH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAM;IAErC;;OAEG;IAEH,aAAa,EAAE,MAAM,CAAK;IAE1B;;;;;;OAMG;WACU,QAAQ,CACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAK5B;;;;;;OAMG;WACU,SAAS,CACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAqBzC;;;;;;;OAOG;WACU,OAAO,CAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC;IAS3B;;;;;;OAMG;WACU,QAAQ,CACnB,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACjC,EACD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,WAAW,CAAC;CA8BxB;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,cAAc,CAAC,WAAW,CAAC;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,qBAAe;IAEzC;;;;OAIG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI1C;;;;OAIG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAMhE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,KAAK,gBAAgB,EACrB,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AASlC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAOa,WAAY,SAAQ,UAAU;IACzC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,OAAO,EAAE,MAAM,CAAM;IAErB;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IAEH,MAAM,EAAE,MAAM,CAAM;IAEpB;;;;;;OAMG;IAEH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAM;IAErC;;OAEG;IAEH,aAAa,EAAE,MAAM,CAAK;IAE1B;;;;;;OAMG;WACU,QAAQ,CACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAK5B;;;;;;OAMG;WACU,SAAS,CACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAqBzC;;;;;;;OAOG;WACU,OAAO,CAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC;IAS3B;;;;;;OAMG;WACU,QAAQ,CACnB,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACjC,EACD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,WAAW,CAAC;CA8BxB;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,cAAc,CAAC,WAAW,CAAC;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,qBAAe;IAEzC;;;;OAIG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D;;;;;;;;OAQG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI1C;;;;;;;;OAQG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAOhE"}
package/dist/index.js CHANGED
@@ -2,11 +2,11 @@ import { ObjectRegistry, smrt, SmrtObject, createDispatchBus, resolveDispatchTen
2
2
  import { getClassConfigResolvers, getConfigResolver, isLazyConfigSentinel, listConfigResolvers, registerConfigResolver, resetConfigResolvers, resolveLazyConfig, unregisterConfigResolver } from "@happyvertical/smrt-core";
3
3
  import { createLogger } from "@happyvertical/logger";
4
4
  import { sanitizeConfig } from "@happyvertical/smrt-config";
5
- import { getCurrentTenant, withTenant, tenantId, TenantScoped } from "@happyvertical/smrt-tenancy";
5
+ import { getCurrentTenant, withTenant, tenantId, TenantScoped, queryGlobal, queryWithGlobals } from "@happyvertical/smrt-tenancy";
6
6
  import { SecretService } from "@happyvertical/smrt-secrets";
7
7
  import { TenantCollection } from "@happyvertical/smrt-users";
8
- import { g as getAgentTypeName, a as getAgentClassName, A as AgentConfig, b as getAgentTypeAliases } from "./chunks/config-BYbOxt24.js";
9
- import { c } from "./chunks/config-BYbOxt24.js";
8
+ import { g as getAgentTypeName, a as getAgentClassName, A as AgentConfig, b as getAgentTypeAliases } from "./chunks/config-JYiYqNE-.js";
9
+ import { c } from "./chunks/config-JYiYqNE-.js";
10
10
  import { AgentUIRegistry, createUIRegistry } from "./ui.js";
11
11
  ObjectRegistry.registerPackageManifest(
12
12
  new URL("./manifest.json", import.meta.url)
@@ -1050,21 +1050,31 @@ class AgentScheduleCollection extends SmrtCollection {
1050
1050
  return this.list({ where: { tenantId: tenantId2 } });
1051
1051
  }
1052
1052
  /**
1053
- * Find all global schedules (not associated with any tenant)
1053
+ * Find all global schedules (not associated with any tenant).
1054
+ *
1055
+ * Routes through the shared tenant-global helper so it does not throw under
1056
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
1057
+ * flagged as an isolation violation). (#1600)
1058
+ *
1054
1059
  * @returns Array of global AgentSchedule objects
1055
1060
  */
1056
1061
  async findGlobal() {
1057
- return this.list({ where: { tenantId: null } });
1062
+ return queryGlobal(this);
1058
1063
  }
1059
1064
  /**
1060
- * Find schedules for a tenant including global schedules
1065
+ * Find schedules for a tenant including global schedules.
1066
+ *
1067
+ * Fails closed if an active tenant context requests a different tenant's
1068
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
1069
+ *
1061
1070
  * @param tenantId - Tenant ID to include
1062
1071
  * @returns Array of AgentSchedule objects for the tenant and global schedules
1063
1072
  */
1064
1073
  async findWithGlobals(tenantId2) {
1065
- return this.query(
1066
- `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,
1067
- [tenantId2]
1074
+ return queryWithGlobals(
1075
+ this,
1076
+ tenantId2,
1077
+ "AgentSchedule.findWithGlobals"
1068
1078
  );
1069
1079
  }
1070
1080
  /**