@open-mercato/ai-assistant 0.6.7-develop.6862.1.c11a64ce0a → 0.6.7

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 (114) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +29 -12
  3. package/dist/modules/ai_assistant/__integration__/helpers/aiAssistantFixtures.js +0 -30
  4. package/dist/modules/ai_assistant/__integration__/helpers/aiAssistantFixtures.js.map +2 -2
  5. package/dist/modules/ai_assistant/api/ai/chat/route.js +0 -7
  6. package/dist/modules/ai_assistant/api/ai/chat/route.js.map +2 -2
  7. package/dist/modules/ai_assistant/api/settings/allowlist/route.js +10 -10
  8. package/dist/modules/ai_assistant/api/settings/allowlist/route.js.map +2 -2
  9. package/dist/modules/ai_assistant/api/settings/route.js +13 -34
  10. package/dist/modules/ai_assistant/api/settings/route.js.map +2 -2
  11. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js +0 -106
  12. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js.map +2 -2
  13. package/dist/modules/ai_assistant/data/entities.js +0 -42
  14. package/dist/modules/ai_assistant/data/entities.js.map +2 -2
  15. package/dist/modules/ai_assistant/data/repositories/AiAgentRuntimeOverrideRepository.js +1 -3
  16. package/dist/modules/ai_assistant/data/repositories/AiAgentRuntimeOverrideRepository.js.map +2 -2
  17. package/dist/modules/ai_assistant/di.js +2 -6
  18. package/dist/modules/ai_assistant/di.js.map +2 -2
  19. package/dist/modules/ai_assistant/events.js +0 -6
  20. package/dist/modules/ai_assistant/events.js.map +2 -2
  21. package/dist/modules/ai_assistant/i18n/de.json +0 -42
  22. package/dist/modules/ai_assistant/i18n/en.json +0 -42
  23. package/dist/modules/ai_assistant/i18n/es.json +0 -42
  24. package/dist/modules/ai_assistant/i18n/pl.json +0 -42
  25. package/dist/modules/ai_assistant/lib/agent-runtime.js +5 -158
  26. package/dist/modules/ai_assistant/lib/agent-runtime.js.map +2 -2
  27. package/dist/modules/ai_assistant/lib/ai-agent-definition.js.map +2 -2
  28. package/dist/modules/ai_assistant/lib/auth.js +7 -6
  29. package/dist/modules/ai_assistant/lib/auth.js.map +2 -2
  30. package/dist/modules/ai_assistant/lib/entity-graph.js +3 -3
  31. package/dist/modules/ai_assistant/lib/entity-graph.js.map +2 -2
  32. package/dist/modules/ai_assistant/lib/llm-adapters/anthropic.js +0 -3
  33. package/dist/modules/ai_assistant/lib/llm-adapters/anthropic.js.map +2 -2
  34. package/dist/modules/ai_assistant/lib/llm-adapters/openai.js +1 -8
  35. package/dist/modules/ai_assistant/lib/llm-adapters/openai.js.map +2 -2
  36. package/dist/modules/ai_assistant/lib/model-factory.js +1 -6
  37. package/dist/modules/ai_assistant/lib/model-factory.js.map +2 -2
  38. package/dist/modules/ai_assistant/lib/openai-compatible-presets.js +0 -2
  39. package/dist/modules/ai_assistant/lib/openai-compatible-presets.js.map +2 -2
  40. package/dist/modules/ai_assistant/lib/tool-search.js +12 -4
  41. package/dist/modules/ai_assistant/lib/tool-search.js.map +2 -2
  42. package/generated/entities/ai_agent_runtime_override/index.ts +0 -1
  43. package/generated/entities.ids.generated.ts +1 -2
  44. package/generated/entity-fields-registry.ts +1 -13
  45. package/package.json +12 -13
  46. package/src/modules/ai_assistant/__integration__/helpers/aiAssistantFixtures.ts +0 -48
  47. package/src/modules/ai_assistant/api/ai/chat/route.ts +0 -10
  48. package/src/modules/ai_assistant/api/settings/__tests__/route.test.ts +8 -58
  49. package/src/modules/ai_assistant/api/settings/allowlist/route.ts +12 -10
  50. package/src/modules/ai_assistant/api/settings/route.ts +10 -33
  51. package/src/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.tsx +0 -146
  52. package/src/modules/ai_assistant/data/entities.ts +0 -56
  53. package/src/modules/ai_assistant/data/repositories/AiAgentRuntimeOverrideRepository.ts +0 -4
  54. package/src/modules/ai_assistant/di.ts +1 -5
  55. package/src/modules/ai_assistant/events.ts +0 -21
  56. package/src/modules/ai_assistant/i18n/de.json +0 -42
  57. package/src/modules/ai_assistant/i18n/en.json +0 -42
  58. package/src/modules/ai_assistant/i18n/es.json +0 -42
  59. package/src/modules/ai_assistant/i18n/pl.json +0 -42
  60. package/src/modules/ai_assistant/lib/__tests__/auth.test.ts +5 -2
  61. package/src/modules/ai_assistant/lib/__tests__/llm-adapters-anthropic.test.ts +0 -13
  62. package/src/modules/ai_assistant/lib/__tests__/llm-adapters-openai.test.ts +0 -41
  63. package/src/modules/ai_assistant/lib/__tests__/model-factory.test.ts +0 -60
  64. package/src/modules/ai_assistant/lib/agent-runtime.ts +0 -259
  65. package/src/modules/ai_assistant/lib/ai-agent-definition.ts +0 -10
  66. package/src/modules/ai_assistant/lib/auth.ts +15 -6
  67. package/src/modules/ai_assistant/lib/entity-graph.ts +3 -3
  68. package/src/modules/ai_assistant/lib/llm-adapters/anthropic.ts +0 -10
  69. package/src/modules/ai_assistant/lib/llm-adapters/openai.ts +1 -32
  70. package/src/modules/ai_assistant/lib/model-factory.ts +0 -33
  71. package/src/modules/ai_assistant/lib/openai-compatible-presets.ts +0 -2
  72. package/src/modules/ai_assistant/lib/tool-search.ts +17 -4
  73. package/src/modules/ai_assistant/migrations/.snapshot-open-mercato.json +16 -388
  74. package/dist/modules/ai_assistant/__integration__/TC-AI-MODERATION-008-settings-and-audit.spec.js +0 -80
  75. package/dist/modules/ai_assistant/__integration__/TC-AI-MODERATION-008-settings-and-audit.spec.js.map +0 -7
  76. package/dist/modules/ai_assistant/__integration__/TC-AI-MODERATION-009-ui.spec.js +0 -124
  77. package/dist/modules/ai_assistant/__integration__/TC-AI-MODERATION-009-ui.spec.js.map +0 -7
  78. package/dist/modules/ai_assistant/api/moderation-flags/route.js +0 -121
  79. package/dist/modules/ai_assistant/api/moderation-flags/route.js.map +0 -7
  80. package/dist/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/AiModerationFlagsPageClient.js +0 -139
  81. package/dist/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/AiModerationFlagsPageClient.js.map +0 -7
  82. package/dist/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/page.js +0 -10
  83. package/dist/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/page.js.map +0 -7
  84. package/dist/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/page.meta.js +0 -26
  85. package/dist/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/page.meta.js.map +0 -7
  86. package/dist/modules/ai_assistant/data/repositories/AiModerationFlagRepository.js +0 -44
  87. package/dist/modules/ai_assistant/data/repositories/AiModerationFlagRepository.js.map +0 -7
  88. package/dist/modules/ai_assistant/i18n/ko.json +0 -527
  89. package/dist/modules/ai_assistant/lib/moderation-flag-recorder.js +0 -43
  90. package/dist/modules/ai_assistant/lib/moderation-flag-recorder.js.map +0 -7
  91. package/dist/modules/ai_assistant/lib/moderation-policy.js +0 -24
  92. package/dist/modules/ai_assistant/lib/moderation-policy.js.map +0 -7
  93. package/dist/modules/ai_assistant/lib/moderation.js +0 -109
  94. package/dist/modules/ai_assistant/lib/moderation.js.map +0 -7
  95. package/dist/modules/ai_assistant/migrations/Migration20260610134045_ai_assistant.js +0 -19
  96. package/dist/modules/ai_assistant/migrations/Migration20260610134045_ai_assistant.js.map +0 -7
  97. package/generated/entities/ai_moderation_flag/index.ts +0 -9
  98. package/src/modules/ai_assistant/__integration__/TC-AI-MODERATION-008-settings-and-audit.spec.ts +0 -126
  99. package/src/modules/ai_assistant/__integration__/TC-AI-MODERATION-009-ui.spec.ts +0 -161
  100. package/src/modules/ai_assistant/api/moderation-flags/__tests__/route.test.ts +0 -122
  101. package/src/modules/ai_assistant/api/moderation-flags/route.ts +0 -137
  102. package/src/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/AiModerationFlagsPageClient.tsx +0 -186
  103. package/src/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/page.meta.ts +0 -24
  104. package/src/modules/ai_assistant/backend/config/ai-assistant/moderation-flags/page.tsx +0 -12
  105. package/src/modules/ai_assistant/data/repositories/AiModerationFlagRepository.ts +0 -79
  106. package/src/modules/ai_assistant/i18n/ko.json +0 -527
  107. package/src/modules/ai_assistant/lib/__tests__/input-moderation-gate.test.ts +0 -121
  108. package/src/modules/ai_assistant/lib/__tests__/moderation-flag-recorder.test.ts +0 -76
  109. package/src/modules/ai_assistant/lib/__tests__/moderation-policy.test.ts +0 -86
  110. package/src/modules/ai_assistant/lib/__tests__/moderation.test.ts +0 -114
  111. package/src/modules/ai_assistant/lib/moderation-flag-recorder.ts +0 -75
  112. package/src/modules/ai_assistant/lib/moderation-policy.ts +0 -77
  113. package/src/modules/ai_assistant/lib/moderation.ts +0 -179
  114. package/src/modules/ai_assistant/migrations/Migration20260610134045_ai_assistant.ts +0 -21
@@ -239,9 +239,6 @@ __decorateClass([
239
239
  __decorateClass([
240
240
  Property({ name: "loop_active_tools_json", type: "jsonb", nullable: true })
241
241
  ], AiAgentRuntimeOverride.prototype, "loopActiveToolsJson", 2);
242
- __decorateClass([
243
- Property({ name: "input_moderation", type: "boolean", nullable: true })
244
- ], AiAgentRuntimeOverride.prototype, "inputModeration", 2);
245
242
  AiAgentRuntimeOverride = __decorateClass([
246
243
  Entity({ tableName: "ai_agent_runtime_overrides" }),
247
244
  Index({
@@ -721,44 +718,6 @@ AiChatMessage = __decorateClass([
721
718
  properties: ["tenantId", "organizationId", "deletedAt"]
722
719
  })
723
720
  ], AiChatMessage);
724
- OptionalProps;
725
- let AiModerationFlag = class {
726
- constructor() {
727
- this.createdAt = /* @__PURE__ */ new Date();
728
- }
729
- };
730
- __decorateClass([
731
- PrimaryKey({ type: "uuid", defaultRaw: "gen_random_uuid()" })
732
- ], AiModerationFlag.prototype, "id", 2);
733
- __decorateClass([
734
- Property({ name: "tenant_id", type: "uuid" })
735
- ], AiModerationFlag.prototype, "tenantId", 2);
736
- __decorateClass([
737
- Property({ name: "organization_id", type: "uuid", nullable: true })
738
- ], AiModerationFlag.prototype, "organizationId", 2);
739
- __decorateClass([
740
- Property({ name: "agent_id", type: "text" })
741
- ], AiModerationFlag.prototype, "agentId", 2);
742
- __decorateClass([
743
- Property({ name: "user_id", type: "text" })
744
- ], AiModerationFlag.prototype, "userId", 2);
745
- __decorateClass([
746
- Property({ name: "provider_id", type: "text" })
747
- ], AiModerationFlag.prototype, "providerId", 2);
748
- __decorateClass([
749
- Property({ name: "model_id", type: "text" })
750
- ], AiModerationFlag.prototype, "modelId", 2);
751
- __decorateClass([
752
- Property({ name: "categories", type: "jsonb" })
753
- ], AiModerationFlag.prototype, "categories", 2);
754
- __decorateClass([
755
- Property({ name: "created_at", type: Date, onCreate: () => /* @__PURE__ */ new Date() })
756
- ], AiModerationFlag.prototype, "createdAt", 2);
757
- AiModerationFlag = __decorateClass([
758
- Entity({ tableName: "ai_moderation_flags" }),
759
- Index({ name: "ai_moderation_flags_tenant_created_idx", properties: ["tenantId", "createdAt"] }),
760
- Index({ name: "ai_moderation_flags_tenant_user_idx", properties: ["tenantId", "userId"] })
761
- ], AiModerationFlag);
762
721
  export {
763
722
  AiAgentMutationPolicyOverride,
764
723
  AiAgentPromptOverride,
@@ -766,7 +725,6 @@ export {
766
725
  AiChatConversation,
767
726
  AiChatConversationParticipant,
768
727
  AiChatMessage,
769
- AiModerationFlag,
770
728
  AiPendingAction,
771
729
  AiTenantModelAllowlist,
772
730
  AiTokenUsageDaily,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/ai_assistant/data/entities.ts"],
4
- "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport {\n Entity,\n Index,\n PrimaryKey,\n Property,\n} from '@mikro-orm/decorators/legacy'\nimport type {\n AiPendingActionExecutionResult,\n AiPendingActionFailedRecord,\n AiPendingActionFieldDiff,\n AiPendingActionQueueMode,\n AiPendingActionRecordDiff,\n AiPendingActionStatus,\n} from '../lib/pending-action-types'\n\n/**\n * Versioned additive prompt-override for a registered AI agent (Step 5.3).\n *\n * Each write creates a new row with `version = latest + 1`. Rows are never\n * updated in place \u2014 history is preserved so operators can roll back by\n * reading an earlier `version`. Column set is tenant/org-scoped per the\n * standard Open Mercato RBAC contract.\n *\n * `sections` holds additive text keyed by prompt section id. The runtime\n * composes the final `systemPrompt` via `composeSystemPromptWithOverride`\n * (see `lib/prompt-override-merge.ts`), which NEVER replaces a built-in\n * section \u2014 overrides are append-only by contract.\n */\n@Entity({ tableName: 'ai_agent_prompt_overrides' })\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_org_agent_version_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_version_null_org_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_agent_version_null_org_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"agent_id\", \"version\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_idx',\n expression:\n 'create index \"ai_agent_prompt_overrides_tenant_org_agent_version_idx\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\" desc)',\n})\nexport class AiAgentPromptOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'version', type: 'int' })\n version!: number\n\n @Property({ name: 'sections', type: 'jsonb' })\n sections!: Record<string, string>\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Persistent mutation-approval gate row backing the Phase 3 WS-C contract\n * (spec \u00A78 `AiPendingAction` + \u00A79 confirm/cancel flow, Step 5.5).\n *\n * One row is created by `prepareMutation` (Step 5.6) whenever the runtime\n * intercepts an `isMutation: true` tool call from a non-read-only agent.\n * The row stores the normalized tool input, a precomputed `fieldDiff` (or\n * per-record batch diff in `records[]`), the target record version, an\n * `idempotencyKey` that dedupes double-submits within the TTL, and a\n * `status` that walks the state machine defined in\n * {@link AI_PENDING_ACTION_ALLOWED_TRANSITIONS}.\n *\n * The cleanup worker (Step 5.12) sweeps `status='pending' AND expiresAt < now`\n * rows and transitions them to `expired`. The confirm route (Step 5.8)\n * walks `pending \u2192 confirmed \u2192 executing \u2192 (failed | terminal success)`.\n * Reads always flow through `findOneWithDecryption` /\n * `findWithDecryption`, even though no column is GDPR-flagged today, so\n * future encrypted columns (e.g. `normalizedInput`) are handled.\n */\n@Entity({ tableName: 'ai_pending_actions' })\n@Index({\n name: 'ai_pending_actions_tenant_org_idempotency_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_org_idempotency_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"organization_id\", \"idempotency_key\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_idem_null_org_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_idem_null_org_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"idempotency_key\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_status_expires_idx',\n properties: ['tenantId', 'organizationId', 'status', 'expiresAt'],\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_agent_status_idx',\n properties: ['tenantId', 'organizationId', 'agentId', 'status'],\n})\nexport class AiPendingAction {\n [OptionalProps]?:\n | 'createdAt'\n | 'organizationId'\n | 'conversationId'\n | 'targetEntityType'\n | 'targetRecordId'\n | 'fieldDiff'\n | 'records'\n | 'failedRecords'\n | 'sideEffectsSummary'\n | 'recordVersion'\n | 'attachmentIds'\n | 'executionResult'\n | 'resolvedAt'\n | 'resolvedByUserId'\n | 'queueMode'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'tool_name', type: 'text' })\n toolName!: string\n\n @Property({ name: 'conversation_id', type: 'text', nullable: true })\n conversationId?: string | null\n\n @Property({ name: 'target_entity_type', type: 'text', nullable: true })\n targetEntityType?: string | null\n\n @Property({ name: 'target_record_id', type: 'text', nullable: true })\n targetRecordId?: string | null\n\n @Property({ name: 'normalized_input', type: 'jsonb' })\n normalizedInput!: Record<string, unknown>\n\n @Property({ name: 'field_diff', type: 'jsonb', default: [] })\n fieldDiff: AiPendingActionFieldDiff[] = []\n\n @Property({ name: 'records', type: 'jsonb', nullable: true })\n records?: AiPendingActionRecordDiff[] | null\n\n @Property({ name: 'failed_records', type: 'jsonb', nullable: true })\n failedRecords?: AiPendingActionFailedRecord[] | null\n\n @Property({ name: 'side_effects_summary', type: 'text', nullable: true })\n sideEffectsSummary?: string | null\n\n @Property({ name: 'record_version', type: 'text', nullable: true })\n recordVersion?: string | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', default: [] })\n attachmentIds: string[] = []\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'created_by_user_id', type: 'uuid' })\n createdByUserId!: string\n\n @Property({ name: 'status', type: 'text' })\n status!: AiPendingActionStatus\n\n @Property({ name: 'queue_mode', type: 'text', default: 'inline' })\n queueMode: AiPendingActionQueueMode = 'inline'\n\n @Property({ name: 'execution_result', type: 'jsonb', nullable: true })\n executionResult?: AiPendingActionExecutionResult | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'resolved_at', type: Date, nullable: true })\n resolvedAt?: Date | null\n\n @Property({ name: 'resolved_by_user_id', type: 'uuid', nullable: true })\n resolvedByUserId?: string | null\n}\n\n/**\n * Per-tenant runtime override row that controls which provider, model, and\n * base URL the AI runtime uses for a given agent (or all agents when\n * `agent_id` is null).\n *\n * Resolution at query time: a non-null `agent_id` row takes precedence over\n * a null `agent_id` (tenant-wide) row for the same `(tenant_id,\n * organization_id)` scope. All value columns are nullable \u2014 an admin can\n * override just the provider, just the model, or any subset. A null value\n * means \"inherit from the next source in the factory resolution chain.\"\n *\n * Soft-delete via `deleted_at` so the unique partial index and audit trail\n * remain intact across upsert operations.\n *\n * Phase 4a of spec `2026-04-27-ai-agents-provider-model-baseurl-overrides`.\n */\n@Entity({ tableName: 'ai_agent_runtime_overrides' })\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_null_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_null_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_null_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_null_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiAgentRuntimeOverride {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'agentId'\n | 'providerId'\n | 'modelId'\n | 'baseUrl'\n | 'allowedOverrideProviders'\n | 'allowedOverrideModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n | 'loopDisabled'\n | 'loopMaxSteps'\n | 'loopMaxToolCalls'\n | 'loopMaxWallClockMs'\n | 'loopMaxTokens'\n | 'loopStopWhenJson'\n | 'loopActiveToolsJson'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'string', columnType: 'varchar(128)', nullable: true })\n agentId?: string | null\n\n @Property({ name: 'provider_id', type: 'string', columnType: 'varchar(64)', nullable: true })\n providerId?: string | null\n\n @Property({ name: 'model_id', type: 'string', columnType: 'varchar(256)', nullable: true })\n modelId?: string | null\n\n @Property({ name: 'base_url', type: 'string', columnType: 'varchar(2048)', nullable: true })\n baseUrl?: string | null\n\n @Property({ name: 'allowed_override_providers', type: 'jsonb', nullable: true })\n allowedOverrideProviders?: string[] | null\n\n @Property({ name: 'allowed_override_models_by_provider', type: 'jsonb', default: '{}' })\n allowedOverrideModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n\n /**\n * Kill switch \u2014 when `true`, runtime forces `stopWhen: stepCountIs(1)` and\n * ignores all other loop config. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_disabled', type: 'boolean', nullable: true })\n loopDisabled?: boolean | null\n\n /**\n * Override `loop.maxSteps`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_steps', type: 'int', nullable: true })\n loopMaxSteps?: number | null\n\n /**\n * Override `loop.budget.maxToolCalls`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tool_calls', type: 'int', nullable: true })\n loopMaxToolCalls?: number | null\n\n /**\n * Override `loop.budget.maxWallClockMs`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_wall_clock_ms', type: 'int', nullable: true })\n loopMaxWallClockMs?: number | null\n\n /**\n * Override `loop.budget.maxTokens`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tokens', type: 'int', nullable: true })\n loopMaxTokens?: number | null\n\n /**\n * Override `loop.stopWhen`. JSON-safe variants only (`stepCount`,\n * `hasToolCall`); validator rejects `kind: 'custom'`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_stop_when_json', type: 'jsonb', nullable: true })\n loopStopWhenJson?: unknown | null\n\n /**\n * Override `loop.activeTools` (must be subset of `agent.allowedTools`).\n * Phase 3 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_active_tools_json', type: 'jsonb', nullable: true })\n loopActiveToolsJson?: unknown | null\n\n /**\n * Per-agent (or tenant-wide when `agent_id` is null) input-moderation\n * override. `true` = on, `false` = off, `null` = inherit (env default \u2192\n * off). Additive nullable column; existing rows inherit. The `untrustedInput`\n * agent flag still forces moderation regardless of this value.\n *\n * Spec `2026-06-04-ai-input-moderation-and-safety-identifiers`.\n */\n @Property({ name: 'input_moderation', type: 'boolean', nullable: true })\n inputModeration?: boolean | null\n}\n\n/**\n * Append-only event log for token usage per step (chat) or per turn (object).\n *\n * One row is created by `recordTokenUsage` (Phase 6.3) for every completed\n * AI SDK step. Indexed for the three read patterns: daily rollup, per-agent\n * report, and session drill-down.\n *\n * Retention: rows older than `AI_TOKEN_USAGE_EVENTS_RETENTION_DAYS` (default\n * 90) are swept by the `ai-token-usage-prune` worker (Phase 6.4).\n *\n * Phase 6.0 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_events' })\n@Index({\n name: 'ai_token_usage_events_tenant_created_idx',\n properties: ['tenantId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_agent_created_idx',\n properties: ['tenantId', 'agentId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_model_created_idx',\n properties: ['tenantId', 'modelId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_session_turn_step_idx',\n properties: ['tenantId', 'sessionId', 'turnId', 'stepIndex'],\n})\nexport class AiTokenUsageEvent {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'cachedInputTokens'\n | 'reasoningTokens'\n | 'finishReason'\n | 'loopAbortReason'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'module_id', type: 'text' })\n moduleId!: string\n\n @Property({ name: 'session_id', type: 'uuid' })\n sessionId!: string\n\n @Property({ name: 'turn_id', type: 'uuid' })\n turnId!: string\n\n @Property({ name: 'step_index', type: 'int' })\n stepIndex!: number\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'input_tokens', type: 'int' })\n inputTokens!: number\n\n @Property({ name: 'output_tokens', type: 'int' })\n outputTokens!: number\n\n @Property({ name: 'cached_input_tokens', type: 'int', nullable: true })\n cachedInputTokens?: number | null\n\n @Property({ name: 'reasoning_tokens', type: 'int', nullable: true })\n reasoningTokens?: number | null\n\n @Property({ name: 'finish_reason', type: 'text', nullable: true })\n finishReason?: string | null\n\n @Property({ name: 'loop_abort_reason', type: 'text', nullable: true })\n loopAbortReason?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Materialized daily rollup of token usage per `(tenant, day, agent, model)`.\n *\n * Updated incrementally by UPSERT on every `recordTokenUsage` call so the\n * rollup is always current even when the prune worker is behind. A daily\n * reconciliation worker (Phase 6.4) recomputes `session_count` from the events\n * table to correct any drift caused by event delivery delays or outages.\n *\n * `session_count` is maintained via a per-row LATERAL exists check at write\n * time (first event in a `(tenant, day, agent, model, session)` window\n * increments the counter). This counter may drift if events arrive out of\n * order; the daily worker corrects it.\n *\n * Phase 6.1 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_daily' })\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\", \"organization_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_null_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_null_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_idx',\n properties: ['tenantId', 'day'],\n})\nexport class AiTokenUsageDaily {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'day', type: 'string', columnType: 'date' })\n day!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'input_tokens', type: 'string', columnType: 'bigint' })\n inputTokens!: string\n\n @Property({ name: 'output_tokens', type: 'string', columnType: 'bigint' })\n outputTokens!: string\n\n @Property({ name: 'cached_input_tokens', type: 'string', columnType: 'bigint' })\n cachedInputTokens!: string\n\n @Property({ name: 'reasoning_tokens', type: 'string', columnType: 'bigint' })\n reasoningTokens!: string\n\n @Property({ name: 'step_count', type: 'string', columnType: 'bigint' })\n stepCount!: string\n\n @Property({ name: 'turn_count', type: 'string', columnType: 'bigint' })\n turnCount!: string\n\n @Property({ name: 'session_count', type: 'string', columnType: 'bigint' })\n sessionCount!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped override of an agent's declared `mutationPolicy` (Step 5.4).\n *\n * Unlike {@link AiAgentPromptOverride}, this surface is NOT versioned \u2014 it is\n * a single-value policy switch per `(tenantId, organizationId, agentId)`. The\n * runtime enforces the override as a DOWNGRADE only: the effective policy\n * equals the MOST RESTRICTIVE of `{ code-declared, override }`. Escalation is\n * a code-level change and is rejected at the route layer.\n *\n * Hierarchy (most restrictive \u2192 least): `read-only` < `destructive-confirm-required`\n * < `confirm-required`. The route never allows an override to widen the\n * code-declared policy.\n */\n/**\n * Tenant-scoped allowlist clipping which providers and models the runtime is\n * permitted to use within the env-driven allowlist (Phase 1780-6 of spec\n * `2026-04-27-ai-agents-provider-model-baseurl-overrides`).\n *\n * Effective constraint chain (outer \u2192 inner): `OM_AI_AVAILABLE_*` env vars \u2192\n * this tenant allowlist \u2192 per-tenant runtime overrides \u2192 per-request overrides.\n * The tenant allowlist may NEVER widen the env allowlist; the runtime\n * intersects the two and surfaces the intersection through the settings GET\n * response so the UI never offers a value the runtime would refuse.\n *\n * `allowedProviders === null` means \"inherit env\" (no tenant-level restriction\n * beyond what the env imposes). `allowedModelsByProvider` keys are provider\n * ids; a missing key means \"inherit env\" for that provider; an empty array\n * means \"no models permitted for this provider\" (effectively disabling it).\n */\n@Entity({ tableName: 'ai_tenant_model_allowlists' })\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_null_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_null_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiTenantModelAllowlist {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'allowedProviders'\n | 'allowedModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'allowed_providers', type: 'jsonb', nullable: true })\n allowedProviders?: string[] | null\n\n @Property({ name: 'allowed_models_by_provider', type: 'jsonb', default: '{}' })\n allowedModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'ai_agent_mutation_policy_overrides' })\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_org_agent_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"agent_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\nexport class AiAgentMutationPolicyOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'mutation_policy', type: 'text' })\n mutationPolicy!: string\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped durable record of a typed AI chat session.\n *\n * Owner-only MVP per spec `2026-05-05-ai-chat-server-side-conversation-storage`.\n * The `participants` table prepares for future sharing without a schema\n * rewrite \u2014 the owner row is always written in the same transaction as the\n * conversation row (see `AiChatConversationRepository.createOrGet`).\n *\n * `conversationId` is the stable, client-visible identifier. It is unique\n * within `(tenant_id, organization_id)` so an idempotent `createOrGet` can\n * accept a client-generated UUID. Pending mutation approvals already store\n * the same id in `AiPendingAction.conversationId` \u2014 the chat-history schema\n * deliberately matches that contract so a future foreign key can be added\n * without churn.\n *\n * `imported_from_local_at` flags conversations that the UI lazily migrated\n * from `localStorage`. The flag is informational only; once a row exists it\n * is always the source of truth for that conversation.\n */\n@Entity({ tableName: 'ai_chat_conversations' })\n@Index({\n name: 'ai_chat_conversations_tenant_org_conv_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_org_conv_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"organization_id\", \"conversation_id\") where \"organization_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_conv_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_conv_null_org_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"conversation_id\") where \"organization_id\" is null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_owner_agent_idx',\n properties: ['tenantId', 'organizationId', 'ownerUserId', 'agentId', 'status', 'lastMessageAt'],\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatConversation {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'title'\n | 'status'\n | 'visibility'\n | 'pageContext'\n | 'lastMessageAt'\n | 'importedFromLocalAt'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'owner_user_id', type: 'uuid' })\n ownerUserId!: string\n\n @Property({ name: 'title', type: 'text', nullable: true })\n title?: string | null\n\n @Property({ name: 'status', type: 'text', default: 'open' })\n status: 'open' | 'closed' = 'open'\n\n @Property({ name: 'visibility', type: 'text', default: 'private' })\n visibility: 'private' | 'shared' | 'organization' = 'private'\n\n @Property({ name: 'page_context', type: 'jsonb', nullable: true })\n pageContext?: Record<string, unknown> | null\n\n @Property({ name: 'last_message_at', type: Date, nullable: true })\n lastMessageAt?: Date | null\n\n @Property({ name: 'imported_from_local_at', type: Date, nullable: true })\n importedFromLocalAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n/**\n * Membership row for an `AiChatConversation`.\n *\n * MVP always writes exactly one row per conversation with `role = 'owner'`,\n * written transactionally alongside the conversation. Sharing extensions\n * append additional rows with `role IN ('viewer', 'commenter', ...)`. The\n * access predicate is \"is the caller an undeleted participant\" \u2014 see\n * `AiChatConversationRepository.assertAccessible`.\n *\n * `last_read_at` is reserved for future unread/share UX and is unused in MVP.\n */\n@Entity({ tableName: 'ai_chat_conversation_participants' })\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_conv_user_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_org_conv_user_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_conv_user_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_conv_user_null_org_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_chat_conv_participants_active_conv_user_idx',\n expression:\n 'create index \"ai_chat_conv_participants_active_conv_user_idx\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"user_id\") where \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_user_conv_idx',\n properties: ['tenantId', 'organizationId', 'userId', 'conversationId'],\n})\nexport class AiChatConversationParticipant {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'role'\n | 'lastReadAt'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'role', type: 'text', default: 'owner' })\n role: 'owner' | 'viewer' | 'commenter' = 'owner'\n\n @Property({ name: 'last_read_at', type: Date, nullable: true })\n lastReadAt?: Date | null\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Append-only message row for an `AiChatConversation`.\n *\n * `client_message_id` is the idempotency key for retries and lazy imports\n * from `localStorage`. The partial unique index allows a non-null\n * `clientMessageId` to dedupe within the conversation while leaving\n * server-only rows (assistant turns persisted from the streaming dispatcher)\n * free of the constraint.\n *\n * `ui_parts` stores the serializable subset of `AiChatMessageUiPart[]` so the\n * chat surface can re-render record cards, mutation-preview cards, etc.\n * across reloads. Attachment previews (`data:` URLs and transient blob\n * URLs) MUST NOT be persisted here \u2014 the UI strips them before upload.\n */\n@Entity({ tableName: 'ai_chat_messages' })\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_client_id_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_org_conv_client_id_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is not null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_conv_client_id_null_org_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_conv_client_id_null_org_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_created_idx',\n properties: ['tenantId', 'organizationId', 'conversationId', 'createdAt'],\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatMessage {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'clientMessageId'\n | 'uiParts'\n | 'attachmentIds'\n | 'filesMetadata'\n | 'model'\n | 'metadata'\n | 'createdByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'client_message_id', type: 'text', nullable: true })\n clientMessageId?: string | null\n\n @Property({ name: 'role', type: 'text' })\n role!: 'user' | 'assistant' | 'system'\n\n @Property({ name: 'content', type: 'text' })\n content!: string\n\n @Property({ name: 'ui_parts', type: 'jsonb', nullable: true })\n uiParts?: unknown[] | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', nullable: true })\n attachmentIds?: string[] | null\n\n @Property({ name: 'files_metadata', type: 'jsonb', nullable: true })\n filesMetadata?: Array<Record<string, unknown>> | null\n\n @Property({ name: 'model', type: 'text', nullable: true })\n model?: string | null\n\n @Property({ name: 'metadata', type: 'jsonb', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n/**\n * Append-only audit record of an input that the moderation gate blocked.\n *\n * Stores ONLY category flags + numeric scores \u2014 never the prompt content or\n * any PII (Q4 data-minimization decision). Enough to identify repeat abusers\n * and tune policy. No `updated_at` / `deleted_at`: rows are immutable. Two\n * indexes back the audit listing (`tenant_id, created_at`) and the per-user\n * abuse review (`tenant_id, user_id`); every read filters `tenant_id`.\n *\n * Spec `2026-06-04-ai-input-moderation-and-safety-identifiers`.\n */\n@Entity({ tableName: 'ai_moderation_flags' })\n@Index({ name: 'ai_moderation_flags_tenant_created_idx', properties: ['tenantId', 'createdAt'] })\n@Index({ name: 'ai_moderation_flags_tenant_user_idx', properties: ['tenantId', 'userId'] })\nexport class AiModerationFlag {\n [OptionalProps]?: 'id' | 'createdAt' | 'organizationId'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'user_id', type: 'text' })\n userId!: string\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'categories', type: 'jsonb' })\n categories!: Record<string, { flagged: boolean; score: number }>\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport {\n Entity,\n Index,\n PrimaryKey,\n Property,\n} from '@mikro-orm/decorators/legacy'\nimport type {\n AiPendingActionExecutionResult,\n AiPendingActionFailedRecord,\n AiPendingActionFieldDiff,\n AiPendingActionQueueMode,\n AiPendingActionRecordDiff,\n AiPendingActionStatus,\n} from '../lib/pending-action-types'\n\n/**\n * Versioned additive prompt-override for a registered AI agent (Step 5.3).\n *\n * Each write creates a new row with `version = latest + 1`. Rows are never\n * updated in place \u2014 history is preserved so operators can roll back by\n * reading an earlier `version`. Column set is tenant/org-scoped per the\n * standard Open Mercato RBAC contract.\n *\n * `sections` holds additive text keyed by prompt section id. The runtime\n * composes the final `systemPrompt` via `composeSystemPromptWithOverride`\n * (see `lib/prompt-override-merge.ts`), which NEVER replaces a built-in\n * section \u2014 overrides are append-only by contract.\n */\n@Entity({ tableName: 'ai_agent_prompt_overrides' })\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_org_agent_version_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_version_null_org_uq',\n expression:\n 'create unique index \"ai_agent_prompt_overrides_tenant_agent_version_null_org_uq\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"agent_id\", \"version\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\n@Index({\n name: 'ai_agent_prompt_overrides_tenant_org_agent_version_idx',\n expression:\n 'create index \"ai_agent_prompt_overrides_tenant_org_agent_version_idx\" on \"ai_agent_prompt_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\", \"version\" desc)',\n})\nexport class AiAgentPromptOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'version', type: 'int' })\n version!: number\n\n @Property({ name: 'sections', type: 'jsonb' })\n sections!: Record<string, string>\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Persistent mutation-approval gate row backing the Phase 3 WS-C contract\n * (spec \u00A78 `AiPendingAction` + \u00A79 confirm/cancel flow, Step 5.5).\n *\n * One row is created by `prepareMutation` (Step 5.6) whenever the runtime\n * intercepts an `isMutation: true` tool call from a non-read-only agent.\n * The row stores the normalized tool input, a precomputed `fieldDiff` (or\n * per-record batch diff in `records[]`), the target record version, an\n * `idempotencyKey` that dedupes double-submits within the TTL, and a\n * `status` that walks the state machine defined in\n * {@link AI_PENDING_ACTION_ALLOWED_TRANSITIONS}.\n *\n * The cleanup worker (Step 5.12) sweeps `status='pending' AND expiresAt < now`\n * rows and transitions them to `expired`. The confirm route (Step 5.8)\n * walks `pending \u2192 confirmed \u2192 executing \u2192 (failed | terminal success)`.\n * Reads always flow through `findOneWithDecryption` /\n * `findWithDecryption`, even though no column is GDPR-flagged today, so\n * future encrypted columns (e.g. `normalizedInput`) are handled.\n */\n@Entity({ tableName: 'ai_pending_actions' })\n@Index({\n name: 'ai_pending_actions_tenant_org_idempotency_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_org_idempotency_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"organization_id\", \"idempotency_key\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_idem_null_org_uq',\n expression:\n 'create unique index \"ai_pending_actions_tenant_idem_null_org_uq\" on \"ai_pending_actions\" (\"tenant_id\", \"idempotency_key\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_status_expires_idx',\n properties: ['tenantId', 'organizationId', 'status', 'expiresAt'],\n})\n@Index({\n name: 'ai_pending_actions_tenant_org_agent_status_idx',\n properties: ['tenantId', 'organizationId', 'agentId', 'status'],\n})\nexport class AiPendingAction {\n [OptionalProps]?:\n | 'createdAt'\n | 'organizationId'\n | 'conversationId'\n | 'targetEntityType'\n | 'targetRecordId'\n | 'fieldDiff'\n | 'records'\n | 'failedRecords'\n | 'sideEffectsSummary'\n | 'recordVersion'\n | 'attachmentIds'\n | 'executionResult'\n | 'resolvedAt'\n | 'resolvedByUserId'\n | 'queueMode'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'tool_name', type: 'text' })\n toolName!: string\n\n @Property({ name: 'conversation_id', type: 'text', nullable: true })\n conversationId?: string | null\n\n @Property({ name: 'target_entity_type', type: 'text', nullable: true })\n targetEntityType?: string | null\n\n @Property({ name: 'target_record_id', type: 'text', nullable: true })\n targetRecordId?: string | null\n\n @Property({ name: 'normalized_input', type: 'jsonb' })\n normalizedInput!: Record<string, unknown>\n\n @Property({ name: 'field_diff', type: 'jsonb', default: [] })\n fieldDiff: AiPendingActionFieldDiff[] = []\n\n @Property({ name: 'records', type: 'jsonb', nullable: true })\n records?: AiPendingActionRecordDiff[] | null\n\n @Property({ name: 'failed_records', type: 'jsonb', nullable: true })\n failedRecords?: AiPendingActionFailedRecord[] | null\n\n @Property({ name: 'side_effects_summary', type: 'text', nullable: true })\n sideEffectsSummary?: string | null\n\n @Property({ name: 'record_version', type: 'text', nullable: true })\n recordVersion?: string | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', default: [] })\n attachmentIds: string[] = []\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'created_by_user_id', type: 'uuid' })\n createdByUserId!: string\n\n @Property({ name: 'status', type: 'text' })\n status!: AiPendingActionStatus\n\n @Property({ name: 'queue_mode', type: 'text', default: 'inline' })\n queueMode: AiPendingActionQueueMode = 'inline'\n\n @Property({ name: 'execution_result', type: 'jsonb', nullable: true })\n executionResult?: AiPendingActionExecutionResult | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'resolved_at', type: Date, nullable: true })\n resolvedAt?: Date | null\n\n @Property({ name: 'resolved_by_user_id', type: 'uuid', nullable: true })\n resolvedByUserId?: string | null\n}\n\n/**\n * Per-tenant runtime override row that controls which provider, model, and\n * base URL the AI runtime uses for a given agent (or all agents when\n * `agent_id` is null).\n *\n * Resolution at query time: a non-null `agent_id` row takes precedence over\n * a null `agent_id` (tenant-wide) row for the same `(tenant_id,\n * organization_id)` scope. All value columns are nullable \u2014 an admin can\n * override just the provider, just the model, or any subset. A null value\n * means \"inherit from the next source in the factory resolution chain.\"\n *\n * Soft-delete via `deleted_at` so the unique partial index and audit trail\n * remain intact across upsert operations.\n *\n * Phase 4a of spec `2026-04-27-ai-agents-provider-model-baseurl-overrides`.\n */\n@Entity({ tableName: 'ai_agent_runtime_overrides' })\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"agent_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is not null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_null_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_null_agent_null_org_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_org_null_agent_uq',\n expression:\n 'create unique index \"ai_agent_runtime_overrides_tenant_org_null_agent_uq\" on \"ai_agent_runtime_overrides\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null and \"agent_id\" is null',\n})\n@Index({\n name: 'ai_agent_runtime_overrides_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiAgentRuntimeOverride {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'agentId'\n | 'providerId'\n | 'modelId'\n | 'baseUrl'\n | 'allowedOverrideProviders'\n | 'allowedOverrideModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n | 'loopDisabled'\n | 'loopMaxSteps'\n | 'loopMaxToolCalls'\n | 'loopMaxWallClockMs'\n | 'loopMaxTokens'\n | 'loopStopWhenJson'\n | 'loopActiveToolsJson'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'string', columnType: 'varchar(128)', nullable: true })\n agentId?: string | null\n\n @Property({ name: 'provider_id', type: 'string', columnType: 'varchar(64)', nullable: true })\n providerId?: string | null\n\n @Property({ name: 'model_id', type: 'string', columnType: 'varchar(256)', nullable: true })\n modelId?: string | null\n\n @Property({ name: 'base_url', type: 'string', columnType: 'varchar(2048)', nullable: true })\n baseUrl?: string | null\n\n @Property({ name: 'allowed_override_providers', type: 'jsonb', nullable: true })\n allowedOverrideProviders?: string[] | null\n\n @Property({ name: 'allowed_override_models_by_provider', type: 'jsonb', default: '{}' })\n allowedOverrideModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n\n /**\n * Kill switch \u2014 when `true`, runtime forces `stopWhen: stepCountIs(1)` and\n * ignores all other loop config. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_disabled', type: 'boolean', nullable: true })\n loopDisabled?: boolean | null\n\n /**\n * Override `loop.maxSteps`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_steps', type: 'int', nullable: true })\n loopMaxSteps?: number | null\n\n /**\n * Override `loop.budget.maxToolCalls`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tool_calls', type: 'int', nullable: true })\n loopMaxToolCalls?: number | null\n\n /**\n * Override `loop.budget.maxWallClockMs`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_wall_clock_ms', type: 'int', nullable: true })\n loopMaxWallClockMs?: number | null\n\n /**\n * Override `loop.budget.maxTokens`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_max_tokens', type: 'int', nullable: true })\n loopMaxTokens?: number | null\n\n /**\n * Override `loop.stopWhen`. JSON-safe variants only (`stepCount`,\n * `hasToolCall`); validator rejects `kind: 'custom'`. Phase 3 of spec\n * `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_stop_when_json', type: 'jsonb', nullable: true })\n loopStopWhenJson?: unknown | null\n\n /**\n * Override `loop.activeTools` (must be subset of `agent.allowedTools`).\n * Phase 3 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n @Property({ name: 'loop_active_tools_json', type: 'jsonb', nullable: true })\n loopActiveToolsJson?: unknown | null\n}\n\n/**\n * Append-only event log for token usage per step (chat) or per turn (object).\n *\n * One row is created by `recordTokenUsage` (Phase 6.3) for every completed\n * AI SDK step. Indexed for the three read patterns: daily rollup, per-agent\n * report, and session drill-down.\n *\n * Retention: rows older than `AI_TOKEN_USAGE_EVENTS_RETENTION_DAYS` (default\n * 90) are swept by the `ai-token-usage-prune` worker (Phase 6.4).\n *\n * Phase 6.0 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_events' })\n@Index({\n name: 'ai_token_usage_events_tenant_created_idx',\n properties: ['tenantId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_agent_created_idx',\n properties: ['tenantId', 'agentId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_model_created_idx',\n properties: ['tenantId', 'modelId', 'createdAt'],\n})\n@Index({\n name: 'ai_token_usage_events_tenant_session_turn_step_idx',\n properties: ['tenantId', 'sessionId', 'turnId', 'stepIndex'],\n})\nexport class AiTokenUsageEvent {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'cachedInputTokens'\n | 'reasoningTokens'\n | 'finishReason'\n | 'loopAbortReason'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'module_id', type: 'text' })\n moduleId!: string\n\n @Property({ name: 'session_id', type: 'uuid' })\n sessionId!: string\n\n @Property({ name: 'turn_id', type: 'uuid' })\n turnId!: string\n\n @Property({ name: 'step_index', type: 'int' })\n stepIndex!: number\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'input_tokens', type: 'int' })\n inputTokens!: number\n\n @Property({ name: 'output_tokens', type: 'int' })\n outputTokens!: number\n\n @Property({ name: 'cached_input_tokens', type: 'int', nullable: true })\n cachedInputTokens?: number | null\n\n @Property({ name: 'reasoning_tokens', type: 'int', nullable: true })\n reasoningTokens?: number | null\n\n @Property({ name: 'finish_reason', type: 'text', nullable: true })\n finishReason?: string | null\n\n @Property({ name: 'loop_abort_reason', type: 'text', nullable: true })\n loopAbortReason?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Materialized daily rollup of token usage per `(tenant, day, agent, model)`.\n *\n * Updated incrementally by UPSERT on every `recordTokenUsage` call so the\n * rollup is always current even when the prune worker is behind. A daily\n * reconciliation worker (Phase 6.4) recomputes `session_count` from the events\n * table to correct any drift caused by event delivery delays or outages.\n *\n * `session_count` is maintained via a per-row LATERAL exists check at write\n * time (first event in a `(tenant, day, agent, model, session)` window\n * increments the counter). This counter may drift if events arrive out of\n * order; the daily worker corrects it.\n *\n * Phase 6.1 of spec `2026-04-28-ai-agents-agentic-loop-controls`.\n */\n@Entity({ tableName: 'ai_token_usage_daily' })\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\", \"organization_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_agent_model_null_org_uq',\n expression:\n 'create unique index \"ai_token_usage_daily_tenant_day_agent_model_null_org_uq\" on \"ai_token_usage_daily\" (\"tenant_id\", \"day\", \"agent_id\", \"model_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_token_usage_daily_tenant_day_idx',\n properties: ['tenantId', 'day'],\n})\nexport class AiTokenUsageDaily {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'day', type: 'string', columnType: 'date' })\n day!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'model_id', type: 'text' })\n modelId!: string\n\n @Property({ name: 'provider_id', type: 'text' })\n providerId!: string\n\n @Property({ name: 'input_tokens', type: 'string', columnType: 'bigint' })\n inputTokens!: string\n\n @Property({ name: 'output_tokens', type: 'string', columnType: 'bigint' })\n outputTokens!: string\n\n @Property({ name: 'cached_input_tokens', type: 'string', columnType: 'bigint' })\n cachedInputTokens!: string\n\n @Property({ name: 'reasoning_tokens', type: 'string', columnType: 'bigint' })\n reasoningTokens!: string\n\n @Property({ name: 'step_count', type: 'string', columnType: 'bigint' })\n stepCount!: string\n\n @Property({ name: 'turn_count', type: 'string', columnType: 'bigint' })\n turnCount!: string\n\n @Property({ name: 'session_count', type: 'string', columnType: 'bigint' })\n sessionCount!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped override of an agent's declared `mutationPolicy` (Step 5.4).\n *\n * Unlike {@link AiAgentPromptOverride}, this surface is NOT versioned \u2014 it is\n * a single-value policy switch per `(tenantId, organizationId, agentId)`. The\n * runtime enforces the override as a DOWNGRADE only: the effective policy\n * equals the MOST RESTRICTIVE of `{ code-declared, override }`. Escalation is\n * a code-level change and is rejected at the route layer.\n *\n * Hierarchy (most restrictive \u2192 least): `read-only` < `destructive-confirm-required`\n * < `confirm-required`. The route never allows an override to widen the\n * code-declared policy.\n */\n/**\n * Tenant-scoped allowlist clipping which providers and models the runtime is\n * permitted to use within the env-driven allowlist (Phase 1780-6 of spec\n * `2026-04-27-ai-agents-provider-model-baseurl-overrides`).\n *\n * Effective constraint chain (outer \u2192 inner): `OM_AI_AVAILABLE_*` env vars \u2192\n * this tenant allowlist \u2192 per-tenant runtime overrides \u2192 per-request overrides.\n * The tenant allowlist may NEVER widen the env allowlist; the runtime\n * intersects the two and surfaces the intersection through the settings GET\n * response so the UI never offers a value the runtime would refuse.\n *\n * `allowedProviders === null` means \"inherit env\" (no tenant-level restriction\n * beyond what the env imposes). `allowedModelsByProvider` keys are provider\n * ids; a missing key means \"inherit env\" for that provider; an empty array\n * means \"no models permitted for this provider\" (effectively disabling it).\n */\n@Entity({ tableName: 'ai_tenant_model_allowlists' })\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\", \"organization_id\") where \"deleted_at\" is null and \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_null_org_uq',\n expression:\n 'create unique index \"ai_tenant_model_allowlists_tenant_null_org_uq\" on \"ai_tenant_model_allowlists\" (\"tenant_id\") where \"deleted_at\" is null and \"organization_id\" is null',\n})\n@Index({\n name: 'ai_tenant_model_allowlists_tenant_idx',\n properties: ['tenantId'],\n})\nexport class AiTenantModelAllowlist {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'allowedProviders'\n | 'allowedModelsByProvider'\n | 'updatedByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'allowed_providers', type: 'jsonb', nullable: true })\n allowedProviders?: string[] | null\n\n @Property({ name: 'allowed_models_by_provider', type: 'jsonb', default: '{}' })\n allowedModelsByProvider: Record<string, string[]> = {}\n\n @Property({ name: 'updated_by_user_id', type: 'uuid', nullable: true })\n updatedByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'ai_agent_mutation_policy_overrides' })\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_org_agent_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_org_agent_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"organization_id\", \"agent_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq',\n expression:\n 'create unique index \"ai_agent_mutation_policy_overrides_tenant_agent_null_org_uq\" on \"ai_agent_mutation_policy_overrides\" (\"tenant_id\", \"agent_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_agent_mutation_policy_overrides_tenant_agent_idx',\n properties: ['tenantId', 'agentId'],\n})\nexport class AiAgentMutationPolicyOverride {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'organizationId' | 'createdByUserId' | 'notes'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'mutation_policy', type: 'text' })\n mutationPolicy!: string\n\n @Property({ name: 'notes', type: 'text', nullable: true })\n notes?: string | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Tenant-scoped durable record of a typed AI chat session.\n *\n * Owner-only MVP per spec `2026-05-05-ai-chat-server-side-conversation-storage`.\n * The `participants` table prepares for future sharing without a schema\n * rewrite \u2014 the owner row is always written in the same transaction as the\n * conversation row (see `AiChatConversationRepository.createOrGet`).\n *\n * `conversationId` is the stable, client-visible identifier. It is unique\n * within `(tenant_id, organization_id)` so an idempotent `createOrGet` can\n * accept a client-generated UUID. Pending mutation approvals already store\n * the same id in `AiPendingAction.conversationId` \u2014 the chat-history schema\n * deliberately matches that contract so a future foreign key can be added\n * without churn.\n *\n * `imported_from_local_at` flags conversations that the UI lazily migrated\n * from `localStorage`. The flag is informational only; once a row exists it\n * is always the source of truth for that conversation.\n */\n@Entity({ tableName: 'ai_chat_conversations' })\n@Index({\n name: 'ai_chat_conversations_tenant_org_conv_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_org_conv_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"organization_id\", \"conversation_id\") where \"organization_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_conv_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conversations_tenant_conv_null_org_uq\" on \"ai_chat_conversations\" (\"tenant_id\", \"conversation_id\") where \"organization_id\" is null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_owner_agent_idx',\n properties: ['tenantId', 'organizationId', 'ownerUserId', 'agentId', 'status', 'lastMessageAt'],\n})\n@Index({\n name: 'ai_chat_conversations_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatConversation {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'title'\n | 'status'\n | 'visibility'\n | 'pageContext'\n | 'lastMessageAt'\n | 'importedFromLocalAt'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'agent_id', type: 'text' })\n agentId!: string\n\n @Property({ name: 'owner_user_id', type: 'uuid' })\n ownerUserId!: string\n\n @Property({ name: 'title', type: 'text', nullable: true })\n title?: string | null\n\n @Property({ name: 'status', type: 'text', default: 'open' })\n status: 'open' | 'closed' = 'open'\n\n @Property({ name: 'visibility', type: 'text', default: 'private' })\n visibility: 'private' | 'shared' | 'organization' = 'private'\n\n @Property({ name: 'page_context', type: 'jsonb', nullable: true })\n pageContext?: Record<string, unknown> | null\n\n @Property({ name: 'last_message_at', type: Date, nullable: true })\n lastMessageAt?: Date | null\n\n @Property({ name: 'imported_from_local_at', type: Date, nullable: true })\n importedFromLocalAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n/**\n * Membership row for an `AiChatConversation`.\n *\n * MVP always writes exactly one row per conversation with `role = 'owner'`,\n * written transactionally alongside the conversation. Sharing extensions\n * append additional rows with `role IN ('viewer', 'commenter', ...)`. The\n * access predicate is \"is the caller an undeleted participant\" \u2014 see\n * `AiChatConversationRepository.assertAccessible`.\n *\n * `last_read_at` is reserved for future unread/share UX and is unused in MVP.\n */\n@Entity({ tableName: 'ai_chat_conversation_participants' })\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_conv_user_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_org_conv_user_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is not null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_conv_user_null_org_uq',\n expression:\n 'create unique index \"ai_chat_conv_participants_tenant_conv_user_null_org_uq\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"conversation_id\", \"user_id\") where \"organization_id\" is null',\n})\n@Index({\n name: 'ai_chat_conv_participants_active_conv_user_idx',\n expression:\n 'create index \"ai_chat_conv_participants_active_conv_user_idx\" on \"ai_chat_conversation_participants\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"user_id\") where \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_conv_participants_tenant_org_user_conv_idx',\n properties: ['tenantId', 'organizationId', 'userId', 'conversationId'],\n})\nexport class AiChatConversationParticipant {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'role'\n | 'lastReadAt'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'role', type: 'text', default: 'owner' })\n role: 'owner' | 'viewer' | 'commenter' = 'owner'\n\n @Property({ name: 'last_read_at', type: Date, nullable: true })\n lastReadAt?: Date | null\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n/**\n * Append-only message row for an `AiChatConversation`.\n *\n * `client_message_id` is the idempotency key for retries and lazy imports\n * from `localStorage`. The partial unique index allows a non-null\n * `clientMessageId` to dedupe within the conversation while leaving\n * server-only rows (assistant turns persisted from the streaming dispatcher)\n * free of the constraint.\n *\n * `ui_parts` stores the serializable subset of `AiChatMessageUiPart[]` so the\n * chat surface can re-render record cards, mutation-preview cards, etc.\n * across reloads. Attachment previews (`data:` URLs and transient blob\n * URLs) MUST NOT be persisted here \u2014 the UI strips them before upload.\n */\n@Entity({ tableName: 'ai_chat_messages' })\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_client_id_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_org_conv_client_id_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"organization_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is not null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_conv_client_id_null_org_uq',\n expression:\n 'create unique index \"ai_chat_messages_tenant_conv_client_id_null_org_uq\" on \"ai_chat_messages\" (\"tenant_id\", \"conversation_id\", \"client_message_id\") where \"organization_id\" is null and \"client_message_id\" is not null and \"deleted_at\" is null',\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_conv_created_idx',\n properties: ['tenantId', 'organizationId', 'conversationId', 'createdAt'],\n})\n@Index({\n name: 'ai_chat_messages_tenant_org_deleted_idx',\n properties: ['tenantId', 'organizationId', 'deletedAt'],\n})\nexport class AiChatMessage {\n [OptionalProps]?:\n | 'createdAt'\n | 'updatedAt'\n | 'organizationId'\n | 'clientMessageId'\n | 'uiParts'\n | 'attachmentIds'\n | 'filesMetadata'\n | 'model'\n | 'metadata'\n | 'createdByUserId'\n | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'conversation_id', type: 'text' })\n conversationId!: string\n\n @Property({ name: 'client_message_id', type: 'text', nullable: true })\n clientMessageId?: string | null\n\n @Property({ name: 'role', type: 'text' })\n role!: 'user' | 'assistant' | 'system'\n\n @Property({ name: 'content', type: 'text' })\n content!: string\n\n @Property({ name: 'ui_parts', type: 'jsonb', nullable: true })\n uiParts?: unknown[] | null\n\n @Property({ name: 'attachment_ids', type: 'jsonb', nullable: true })\n attachmentIds?: string[] | null\n\n @Property({ name: 'files_metadata', type: 'jsonb', nullable: true })\n filesMetadata?: Array<Record<string, unknown>> | null\n\n @Property({ name: 'model', type: 'text', nullable: true })\n model?: string | null\n\n @Property({ name: 'metadata', type: 'jsonb', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'created_by_user_id', type: 'uuid', nullable: true })\n createdByUserId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -187,7 +187,6 @@ class AiAgentRuntimeOverrideRepository {
187
187
  if ("loopMaxTokens" in input) existing.loopMaxTokens = input.loopMaxTokens ?? null;
188
188
  if ("loopStopWhenJson" in input) existing.loopStopWhenJson = input.loopStopWhenJson ?? null;
189
189
  if ("loopActiveToolsJson" in input) existing.loopActiveToolsJson = input.loopActiveToolsJson ?? null;
190
- if ("inputModeration" in input) existing.inputModeration = input.inputModeration ?? null;
191
190
  await tx.persist(existing).flush();
192
191
  return existing;
193
192
  }
@@ -207,8 +206,7 @@ class AiAgentRuntimeOverrideRepository {
207
206
  loopMaxWallClockMs: input.loopMaxWallClockMs ?? null,
208
207
  loopMaxTokens: input.loopMaxTokens ?? null,
209
208
  loopStopWhenJson: input.loopStopWhenJson ?? null,
210
- loopActiveToolsJson: input.loopActiveToolsJson ?? null,
211
- inputModeration: input.inputModeration ?? null
209
+ loopActiveToolsJson: input.loopActiveToolsJson ?? null
212
210
  });
213
211
  await tx.persist(row).flush();
214
212
  return row;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/ai_assistant/data/repositories/AiAgentRuntimeOverrideRepository.ts"],
4
- "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { llmProviderRegistry } from '@open-mercato/shared/lib/ai/llm-provider-registry'\nimport { canonicalProviderId } from '../../lib/model-allowlist'\nimport { AiAgentRuntimeOverride } from '../entities'\nimport type { AiAgentLoopStopCondition } from '../../lib/ai-agent-definition'\n\nexport interface AiAgentRuntimeOverrideContext {\n tenantId: string\n organizationId?: string | null\n userId?: string | null\n}\n\nexport interface AiAgentRuntimeOverrideLoopInput {\n /** Kill switch \u2014 when true, runtime forces stepCountIs(1). */\n loopDisabled?: boolean | null\n /** Override loop.maxSteps. */\n loopMaxSteps?: number | null\n /** Override loop.budget.maxToolCalls. */\n loopMaxToolCalls?: number | null\n /** Override loop.budget.maxWallClockMs. */\n loopMaxWallClockMs?: number | null\n /** Override loop.budget.maxTokens. */\n loopMaxTokens?: number | null\n /** Override loop.stopWhen \u2014 JSON-safe variants only (stepCount, hasToolCall). */\n loopStopWhenJson?: AiAgentLoopStopCondition[] | null\n /** Override loop.activeTools \u2014 must be a subset of agent.allowedTools. */\n loopActiveToolsJson?: string[] | null\n}\n\nexport interface AiAgentRuntimeOverrideInput extends AiAgentRuntimeOverrideLoopInput {\n /** null means tenant-wide default (no agent pinning). */\n agentId?: string | null\n providerId?: string | null\n modelId?: string | null\n baseURL?: string | null\n allowedOverrideProviders?: string[] | null\n allowedOverrideModelsByProvider?: Record<string, string[]>\n /** Input-moderation override: true = on, false = off, null = inherit. */\n inputModeration?: boolean | null\n /**\n * Optional: the agent's declared allowedTools. When provided, loopActiveToolsJson\n * is validated to be a subset. When omitted, allowlist validation is skipped\n * (write-time defense only; the runtime re-validates at read time).\n */\n agentAllowedTools?: string[]\n}\n\n/**\n * Repository for per-tenant AI runtime overrides (Phase 4a of spec\n * `2026-04-27-ai-agents-provider-model-baseurl-overrides`).\n *\n * All reads MUST filter by `tenant_id` first. The three public methods follow\n * the same fail-safe pattern as sibling repositories: `getDefault` returns\n * null on missing tenant context; `upsertDefault` validates provider id at\n * write time; `clearDefault` soft-deletes via `deleted_at`.\n *\n * Resolution precedence returned by `getDefault`:\n * 1. Agent-specific row (non-null `agent_id`) when `agentId` is provided.\n * 2. Tenant-wide row (`agent_id IS NULL`) for the same `(tenant_id, org_id)`.\n * Both rows are always scoped to the caller's `tenant_id` \u2014 cross-tenant\n * reads are impossible because every query filters `WHERE tenant_id = ?`.\n */\nexport class AiAgentRuntimeOverrideRepository {\n constructor(private readonly em: EntityManager) {}\n\n /**\n * Returns the most-specific active runtime override for the given context.\n *\n * When `agentId` is provided, an agent-specific row takes precedence over a\n * tenant-wide null-agent row. Returns null when neither exists.\n *\n * Never returns a row with `deleted_at IS NOT NULL`.\n */\n async getDefault(ctx: {\n tenantId: string\n organizationId?: string | null\n agentId?: string | null\n }): Promise<AiAgentRuntimeOverride | null> {\n if (!ctx?.tenantId) return null\n\n const orgFilter = ctx.organizationId ?? null\n\n // Try agent-specific first when caller provided an agentId.\n if (ctx.agentId) {\n const agentRow = await this.em.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: ctx.agentId,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n if (agentRow) return agentRow\n }\n\n // Fall back to tenant-wide row (agentId = null).\n const tenantRow = await this.em.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: null,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n return tenantRow ?? null\n }\n\n async getExact(ctx: {\n tenantId: string\n organizationId?: string | null\n agentId?: string | null\n }): Promise<AiAgentRuntimeOverride | null> {\n if (!ctx?.tenantId) return null\n const row = await this.em.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId ?? null,\n agentId: ctx.agentId ?? null,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n return row ?? null\n }\n\n /**\n * Validates and normalizes the loop override fields from an input object.\n * Throws `AiAgentRuntimeOverrideValidationError` with code\n * `invalid_loop_override` for any validation failure.\n *\n * Validation rules (Phase 3 \u2014 R5 mitigation):\n * - `loopStopWhenJson`: all items must have kind `stepCount` or `hasToolCall`.\n * Items with kind `custom` are rejected \u2014 they cannot be stored as JSON.\n * - `loopActiveToolsJson`: when `agentAllowedTools` is provided, every entry\n * must be in that allowlist.\n */\n private validateLoopInput(input: AiAgentRuntimeOverrideInput): void {\n if (input.loopStopWhenJson != null) {\n if (!Array.isArray(input.loopStopWhenJson)) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson must be an array of stop condition objects.',\n 'invalid_loop_override',\n )\n }\n for (const item of input.loopStopWhenJson) {\n if (!item || typeof item !== 'object' || !('kind' in item)) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson items must have a \"kind\" field.',\n 'invalid_loop_override',\n )\n }\n const kind = (item as AiAgentLoopStopCondition).kind\n if (kind === 'custom') {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson does not support kind \"custom\" \u2014 only \"stepCount\" and \"hasToolCall\" are JSON-safe and storable.',\n 'invalid_loop_override',\n )\n }\n if (kind !== 'stepCount' && kind !== 'hasToolCall') {\n throw new AiAgentRuntimeOverrideValidationError(\n `loopStopWhenJson contains unknown kind \"${String(kind)}\". Allowed: \"stepCount\", \"hasToolCall\".`,\n 'invalid_loop_override',\n )\n }\n if (kind === 'stepCount' && typeof (item as { count?: unknown }).count !== 'number') {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson stepCount item must have a numeric \"count\" field.',\n 'invalid_loop_override',\n )\n }\n if (kind === 'hasToolCall' && typeof (item as { toolName?: unknown }).toolName !== 'string') {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson hasToolCall item must have a string \"toolName\" field.',\n 'invalid_loop_override',\n )\n }\n }\n }\n\n if (input.loopActiveToolsJson != null) {\n if (!Array.isArray(input.loopActiveToolsJson)) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopActiveToolsJson must be an array of tool name strings.',\n 'invalid_loop_override',\n )\n }\n for (const name of input.loopActiveToolsJson) {\n if (typeof name !== 'string' || name.length === 0) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopActiveToolsJson entries must be non-empty strings.',\n 'invalid_loop_override',\n )\n }\n }\n if (input.agentAllowedTools && input.agentAllowedTools.length > 0) {\n const outsideAllowlist = input.loopActiveToolsJson.filter(\n (name) => !input.agentAllowedTools!.includes(name),\n )\n if (outsideAllowlist.length > 0) {\n throw new AiAgentRuntimeOverrideValidationError(\n `loopActiveToolsJson contains tools outside the agent's allowedTools: ${outsideAllowlist.join(', ')}.`,\n 'invalid_loop_override',\n )\n }\n }\n }\n }\n\n /**\n * Inserts or updates the runtime override for the given context.\n *\n * Validates `providerId` against the registry at write time so an admin\n * cannot save a typo (Phase 1.4 contract re-applied per spec \u00A7Data Models).\n * An unknown provider id throws a typed error.\n *\n * Also validates loop override fields (R5 mitigation \u2014 Phase 3):\n * - `loopStopWhenJson` items must use only JSON-safe kinds.\n * - `loopActiveToolsJson` items must be a subset of `agentAllowedTools`\n * when that is provided.\n *\n * The R6 base-URL allowlist check is intentionally NOT performed here \u2014\n * that enforcement lives at the HTTP layer (PUT settings route). The\n * repository trusts that callers have already validated the value.\n */\n async upsertDefault(\n input: AiAgentRuntimeOverrideInput,\n ctx: AiAgentRuntimeOverrideContext,\n ): Promise<AiAgentRuntimeOverride> {\n if (!ctx?.tenantId) {\n throw new Error('AiAgentRuntimeOverrideRepository.upsertDefault requires tenantId')\n }\n\n const normalizedProviderId = input.providerId\n ? canonicalProviderId(input.providerId, llmProviderRegistry.list().map((p) => p.id))\n : null\n if (input.providerId) {\n const knownProvider = normalizedProviderId ? llmProviderRegistry.get(normalizedProviderId) : null\n if (!knownProvider) {\n throw new AiAgentRuntimeOverrideValidationError(\n `Unknown provider id \"${input.providerId}\". Registered provider ids: ${llmProviderRegistry.list().map((p) => p.id).join(', ')}.`,\n )\n }\n }\n\n this.validateLoopInput(input)\n\n const orgFilter = ctx.organizationId ?? null\n const agentIdFilter = input.agentId ?? null\n const hasProviderId = Object.prototype.hasOwnProperty.call(input, 'providerId')\n const hasModelId = Object.prototype.hasOwnProperty.call(input, 'modelId')\n const hasBaseURL = Object.prototype.hasOwnProperty.call(input, 'baseURL')\n const hasAllowedOverrideProviders = Object.prototype.hasOwnProperty.call(input, 'allowedOverrideProviders')\n const hasAllowedOverrideModels = Object.prototype.hasOwnProperty.call(input, 'allowedOverrideModelsByProvider')\n\n return this.em.transactional(async (tx) => {\n const existing = await tx.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: agentIdFilter,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n\n if (existing) {\n if (hasProviderId) existing.providerId = normalizedProviderId\n if (hasModelId) existing.modelId = input.modelId ?? null\n if (hasBaseURL) existing.baseUrl = input.baseURL ?? null\n if (hasAllowedOverrideProviders) {\n existing.allowedOverrideProviders = input.allowedOverrideProviders ?? null\n }\n if (hasAllowedOverrideModels) {\n existing.allowedOverrideModelsByProvider = input.allowedOverrideModelsByProvider ?? {}\n }\n existing.updatedByUserId = ctx.userId ?? null\n existing.updatedAt = new Date()\n if ('loopDisabled' in input) existing.loopDisabled = input.loopDisabled ?? null\n if ('loopMaxSteps' in input) existing.loopMaxSteps = input.loopMaxSteps ?? null\n if ('loopMaxToolCalls' in input) existing.loopMaxToolCalls = input.loopMaxToolCalls ?? null\n if ('loopMaxWallClockMs' in input) existing.loopMaxWallClockMs = input.loopMaxWallClockMs ?? null\n if ('loopMaxTokens' in input) existing.loopMaxTokens = input.loopMaxTokens ?? null\n if ('loopStopWhenJson' in input) existing.loopStopWhenJson = input.loopStopWhenJson ?? null\n if ('loopActiveToolsJson' in input) existing.loopActiveToolsJson = input.loopActiveToolsJson ?? null\n if ('inputModeration' in input) existing.inputModeration = input.inputModeration ?? null\n await tx.persist(existing).flush()\n return existing\n }\n\n const row = tx.create(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: agentIdFilter,\n providerId: hasProviderId ? normalizedProviderId : null,\n modelId: hasModelId ? (input.modelId ?? null) : null,\n baseUrl: hasBaseURL ? (input.baseURL ?? null) : null,\n allowedOverrideProviders: hasAllowedOverrideProviders\n ? (input.allowedOverrideProviders ?? null)\n : null,\n allowedOverrideModelsByProvider: hasAllowedOverrideModels\n ? (input.allowedOverrideModelsByProvider ?? {})\n : {},\n updatedByUserId: ctx.userId ?? null,\n loopDisabled: input.loopDisabled ?? null,\n loopMaxSteps: input.loopMaxSteps ?? null,\n loopMaxToolCalls: input.loopMaxToolCalls ?? null,\n loopMaxWallClockMs: input.loopMaxWallClockMs ?? null,\n loopMaxTokens: input.loopMaxTokens ?? null,\n loopStopWhenJson: input.loopStopWhenJson ?? null,\n loopActiveToolsJson: input.loopActiveToolsJson ?? null,\n inputModeration: input.inputModeration ?? null,\n } as unknown as AiAgentRuntimeOverride)\n await tx.persist(row).flush()\n return row\n })\n }\n\n /**\n * Soft-deletes the active override matching the given context by setting\n * `deleted_at = now()`. Returns true when a row was found and cleared,\n * false when no active row existed.\n */\n async clearDefault(ctx: {\n tenantId: string\n organizationId?: string | null\n agentId?: string | null\n }): Promise<boolean> {\n if (!ctx?.tenantId) return false\n\n const orgFilter = ctx.organizationId ?? null\n const agentIdFilter = ctx.agentId ?? null\n\n return this.em.transactional(async (tx) => {\n const existing = await tx.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: agentIdFilter,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n if (!existing) return false\n if (\n existing.allowedOverrideProviders != null ||\n Object.keys(existing.allowedOverrideModelsByProvider ?? {}).length > 0\n ) {\n existing.providerId = null\n existing.modelId = null\n existing.baseUrl = null\n existing.updatedAt = new Date()\n await tx.persist(existing).flush()\n return true\n }\n existing.deletedAt = new Date()\n await tx.persist(existing).flush()\n return true\n })\n }\n}\n\n/**\n * Thrown by `upsertDefault` when validation fails (unknown provider id,\n * invalid loop override JSON).\n */\nexport class AiAgentRuntimeOverrideValidationError extends Error {\n readonly code: string\n\n constructor(message: string, code = 'invalid_override') {\n super(message)\n this.name = 'AiAgentRuntimeOverrideValidationError'\n this.code = code\n }\n}\n\nexport default AiAgentRuntimeOverrideRepository\n"],
5
- "mappings": "AACA,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AA2DhC,MAAM,iCAAiC;AAAA,EAC5C,YAA6B,IAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUjD,MAAM,WAAW,KAI0B;AACzC,QAAI,CAAC,KAAK,SAAU,QAAO;AAE3B,UAAM,YAAY,IAAI,kBAAkB;AAGxC,QAAI,IAAI,SAAS;AACf,YAAM,WAAW,MAAM,KAAK,GAAG,QAAQ,wBAAwB;AAAA,QAC7D,UAAU,IAAI;AAAA,QACd,gBAAgB;AAAA,QAChB,SAAS,IAAI;AAAA,QACb,WAAW;AAAA,MACb,CAA+C;AAC/C,UAAI,SAAU,QAAO;AAAA,IACvB;AAGA,UAAM,YAAY,MAAM,KAAK,GAAG,QAAQ,wBAAwB;AAAA,MAC9D,UAAU,IAAI;AAAA,MACd,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,WAAW;AAAA,IACb,CAA+C;AAC/C,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,SAAS,KAI4B;AACzC,QAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,UAAM,MAAM,MAAM,KAAK,GAAG,QAAQ,wBAAwB;AAAA,MACxD,UAAU,IAAI;AAAA,MACd,gBAAgB,IAAI,kBAAkB;AAAA,MACtC,SAAS,IAAI,WAAW;AAAA,MACxB,WAAW;AAAA,IACb,CAA+C;AAC/C,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,kBAAkB,OAA0C;AAClE,QAAI,MAAM,oBAAoB,MAAM;AAClC,UAAI,CAAC,MAAM,QAAQ,MAAM,gBAAgB,GAAG;AAC1C,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,iBAAW,QAAQ,MAAM,kBAAkB;AACzC,YAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,EAAE,UAAU,OAAO;AAC1D,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,cAAM,OAAQ,KAAkC;AAChD,YAAI,SAAS,UAAU;AACrB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAI,SAAS,eAAe,SAAS,eAAe;AAClD,gBAAM,IAAI;AAAA,YACR,2CAA2C,OAAO,IAAI,CAAC;AAAA,YACvD;AAAA,UACF;AAAA,QACF;AACA,YAAI,SAAS,eAAe,OAAQ,KAA6B,UAAU,UAAU;AACnF,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAI,SAAS,iBAAiB,OAAQ,KAAgC,aAAa,UAAU;AAC3F,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,uBAAuB,MAAM;AACrC,UAAI,CAAC,MAAM,QAAQ,MAAM,mBAAmB,GAAG;AAC7C,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,iBAAW,QAAQ,MAAM,qBAAqB;AAC5C,YAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG;AACjD,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,qBAAqB,MAAM,kBAAkB,SAAS,GAAG;AACjE,cAAM,mBAAmB,MAAM,oBAAoB;AAAA,UACjD,CAAC,SAAS,CAAC,MAAM,kBAAmB,SAAS,IAAI;AAAA,QACnD;AACA,YAAI,iBAAiB,SAAS,GAAG;AAC/B,gBAAM,IAAI;AAAA,YACR,wEAAwE,iBAAiB,KAAK,IAAI,CAAC;AAAA,YACnG;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,cACJ,OACA,KACiC;AACjC,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AAEA,UAAM,uBAAuB,MAAM,aAC/B,oBAAoB,MAAM,YAAY,oBAAoB,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,IACjF;AACJ,QAAI,MAAM,YAAY;AACpB,YAAM,gBAAgB,uBAAuB,oBAAoB,IAAI,oBAAoB,IAAI;AAC7F,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI;AAAA,UACR,wBAAwB,MAAM,UAAU,+BAA+B,oBAAoB,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,QAC/H;AAAA,MACF;AAAA,IACF;AAEA,SAAK,kBAAkB,KAAK;AAE5B,UAAM,YAAY,IAAI,kBAAkB;AACxC,UAAM,gBAAgB,MAAM,WAAW;AACvC,UAAM,gBAAgB,OAAO,UAAU,eAAe,KAAK,OAAO,YAAY;AAC9E,UAAM,aAAa,OAAO,UAAU,eAAe,KAAK,OAAO,SAAS;AACxE,UAAM,aAAa,OAAO,UAAU,eAAe,KAAK,OAAO,SAAS;AACxE,UAAM,8BAA8B,OAAO,UAAU,eAAe,KAAK,OAAO,0BAA0B;AAC1G,UAAM,2BAA2B,OAAO,UAAU,eAAe,KAAK,OAAO,iCAAiC;AAE9G,WAAO,KAAK,GAAG,cAAc,OAAO,OAAO;AACzC,YAAM,WAAW,MAAM,GAAG,QAAQ,wBAAwB;AAAA,QACxD,UAAU,IAAI;AAAA,QACd,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,WAAW;AAAA,MACb,CAA+C;AAE/C,UAAI,UAAU;AACZ,YAAI,cAAe,UAAS,aAAa;AACzC,YAAI,WAAY,UAAS,UAAU,MAAM,WAAW;AACpD,YAAI,WAAY,UAAS,UAAU,MAAM,WAAW;AACpD,YAAI,6BAA6B;AAC/B,mBAAS,2BAA2B,MAAM,4BAA4B;AAAA,QACxE;AACA,YAAI,0BAA0B;AAC5B,mBAAS,kCAAkC,MAAM,mCAAmC,CAAC;AAAA,QACvF;AACA,iBAAS,kBAAkB,IAAI,UAAU;AACzC,iBAAS,YAAY,oBAAI,KAAK;AAC9B,YAAI,kBAAkB,MAAO,UAAS,eAAe,MAAM,gBAAgB;AAC3E,YAAI,kBAAkB,MAAO,UAAS,eAAe,MAAM,gBAAgB;AAC3E,YAAI,sBAAsB,MAAO,UAAS,mBAAmB,MAAM,oBAAoB;AACvF,YAAI,wBAAwB,MAAO,UAAS,qBAAqB,MAAM,sBAAsB;AAC7F,YAAI,mBAAmB,MAAO,UAAS,gBAAgB,MAAM,iBAAiB;AAC9E,YAAI,sBAAsB,MAAO,UAAS,mBAAmB,MAAM,oBAAoB;AACvF,YAAI,yBAAyB,MAAO,UAAS,sBAAsB,MAAM,uBAAuB;AAChG,YAAI,qBAAqB,MAAO,UAAS,kBAAkB,MAAM,mBAAmB;AACpF,cAAM,GAAG,QAAQ,QAAQ,EAAE,MAAM;AACjC,eAAO;AAAA,MACT;AAEA,YAAM,MAAM,GAAG,OAAO,wBAAwB;AAAA,QAC5C,UAAU,IAAI;AAAA,QACd,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,YAAY,gBAAgB,uBAAuB;AAAA,QACnD,SAAS,aAAc,MAAM,WAAW,OAAQ;AAAA,QAChD,SAAS,aAAc,MAAM,WAAW,OAAQ;AAAA,QAChD,0BAA0B,8BACrB,MAAM,4BAA4B,OACnC;AAAA,QACJ,iCAAiC,2BAC5B,MAAM,mCAAmC,CAAC,IAC3C,CAAC;AAAA,QACL,iBAAiB,IAAI,UAAU;AAAA,QAC/B,cAAc,MAAM,gBAAgB;AAAA,QACpC,cAAc,MAAM,gBAAgB;AAAA,QACpC,kBAAkB,MAAM,oBAAoB;AAAA,QAC5C,oBAAoB,MAAM,sBAAsB;AAAA,QAChD,eAAe,MAAM,iBAAiB;AAAA,QACtC,kBAAkB,MAAM,oBAAoB;AAAA,QAC5C,qBAAqB,MAAM,uBAAuB;AAAA,QAClD,iBAAiB,MAAM,mBAAmB;AAAA,MAC5C,CAAsC;AACtC,YAAM,GAAG,QAAQ,GAAG,EAAE,MAAM;AAC5B,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,KAIE;AACnB,QAAI,CAAC,KAAK,SAAU,QAAO;AAE3B,UAAM,YAAY,IAAI,kBAAkB;AACxC,UAAM,gBAAgB,IAAI,WAAW;AAErC,WAAO,KAAK,GAAG,cAAc,OAAO,OAAO;AACzC,YAAM,WAAW,MAAM,GAAG,QAAQ,wBAAwB;AAAA,QACxD,UAAU,IAAI;AAAA,QACd,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,WAAW;AAAA,MACb,CAA+C;AAC/C,UAAI,CAAC,SAAU,QAAO;AACtB,UACE,SAAS,4BAA4B,QACrC,OAAO,KAAK,SAAS,mCAAmC,CAAC,CAAC,EAAE,SAAS,GACrE;AACA,iBAAS,aAAa;AACtB,iBAAS,UAAU;AACnB,iBAAS,UAAU;AACnB,iBAAS,YAAY,oBAAI,KAAK;AAC9B,cAAM,GAAG,QAAQ,QAAQ,EAAE,MAAM;AACjC,eAAO;AAAA,MACT;AACA,eAAS,YAAY,oBAAI,KAAK;AAC9B,YAAM,GAAG,QAAQ,QAAQ,EAAE,MAAM;AACjC,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAMO,MAAM,8CAA8C,MAAM;AAAA,EAG/D,YAAY,SAAiB,OAAO,oBAAoB;AACtD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAO,2CAAQ;",
4
+ "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { llmProviderRegistry } from '@open-mercato/shared/lib/ai/llm-provider-registry'\nimport { canonicalProviderId } from '../../lib/model-allowlist'\nimport { AiAgentRuntimeOverride } from '../entities'\nimport type { AiAgentLoopStopCondition } from '../../lib/ai-agent-definition'\n\nexport interface AiAgentRuntimeOverrideContext {\n tenantId: string\n organizationId?: string | null\n userId?: string | null\n}\n\nexport interface AiAgentRuntimeOverrideLoopInput {\n /** Kill switch \u2014 when true, runtime forces stepCountIs(1). */\n loopDisabled?: boolean | null\n /** Override loop.maxSteps. */\n loopMaxSteps?: number | null\n /** Override loop.budget.maxToolCalls. */\n loopMaxToolCalls?: number | null\n /** Override loop.budget.maxWallClockMs. */\n loopMaxWallClockMs?: number | null\n /** Override loop.budget.maxTokens. */\n loopMaxTokens?: number | null\n /** Override loop.stopWhen \u2014 JSON-safe variants only (stepCount, hasToolCall). */\n loopStopWhenJson?: AiAgentLoopStopCondition[] | null\n /** Override loop.activeTools \u2014 must be a subset of agent.allowedTools. */\n loopActiveToolsJson?: string[] | null\n}\n\nexport interface AiAgentRuntimeOverrideInput extends AiAgentRuntimeOverrideLoopInput {\n /** null means tenant-wide default (no agent pinning). */\n agentId?: string | null\n providerId?: string | null\n modelId?: string | null\n baseURL?: string | null\n allowedOverrideProviders?: string[] | null\n allowedOverrideModelsByProvider?: Record<string, string[]>\n /**\n * Optional: the agent's declared allowedTools. When provided, loopActiveToolsJson\n * is validated to be a subset. When omitted, allowlist validation is skipped\n * (write-time defense only; the runtime re-validates at read time).\n */\n agentAllowedTools?: string[]\n}\n\n/**\n * Repository for per-tenant AI runtime overrides (Phase 4a of spec\n * `2026-04-27-ai-agents-provider-model-baseurl-overrides`).\n *\n * All reads MUST filter by `tenant_id` first. The three public methods follow\n * the same fail-safe pattern as sibling repositories: `getDefault` returns\n * null on missing tenant context; `upsertDefault` validates provider id at\n * write time; `clearDefault` soft-deletes via `deleted_at`.\n *\n * Resolution precedence returned by `getDefault`:\n * 1. Agent-specific row (non-null `agent_id`) when `agentId` is provided.\n * 2. Tenant-wide row (`agent_id IS NULL`) for the same `(tenant_id, org_id)`.\n * Both rows are always scoped to the caller's `tenant_id` \u2014 cross-tenant\n * reads are impossible because every query filters `WHERE tenant_id = ?`.\n */\nexport class AiAgentRuntimeOverrideRepository {\n constructor(private readonly em: EntityManager) {}\n\n /**\n * Returns the most-specific active runtime override for the given context.\n *\n * When `agentId` is provided, an agent-specific row takes precedence over a\n * tenant-wide null-agent row. Returns null when neither exists.\n *\n * Never returns a row with `deleted_at IS NOT NULL`.\n */\n async getDefault(ctx: {\n tenantId: string\n organizationId?: string | null\n agentId?: string | null\n }): Promise<AiAgentRuntimeOverride | null> {\n if (!ctx?.tenantId) return null\n\n const orgFilter = ctx.organizationId ?? null\n\n // Try agent-specific first when caller provided an agentId.\n if (ctx.agentId) {\n const agentRow = await this.em.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: ctx.agentId,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n if (agentRow) return agentRow\n }\n\n // Fall back to tenant-wide row (agentId = null).\n const tenantRow = await this.em.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: null,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n return tenantRow ?? null\n }\n\n async getExact(ctx: {\n tenantId: string\n organizationId?: string | null\n agentId?: string | null\n }): Promise<AiAgentRuntimeOverride | null> {\n if (!ctx?.tenantId) return null\n const row = await this.em.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId ?? null,\n agentId: ctx.agentId ?? null,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n return row ?? null\n }\n\n /**\n * Validates and normalizes the loop override fields from an input object.\n * Throws `AiAgentRuntimeOverrideValidationError` with code\n * `invalid_loop_override` for any validation failure.\n *\n * Validation rules (Phase 3 \u2014 R5 mitigation):\n * - `loopStopWhenJson`: all items must have kind `stepCount` or `hasToolCall`.\n * Items with kind `custom` are rejected \u2014 they cannot be stored as JSON.\n * - `loopActiveToolsJson`: when `agentAllowedTools` is provided, every entry\n * must be in that allowlist.\n */\n private validateLoopInput(input: AiAgentRuntimeOverrideInput): void {\n if (input.loopStopWhenJson != null) {\n if (!Array.isArray(input.loopStopWhenJson)) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson must be an array of stop condition objects.',\n 'invalid_loop_override',\n )\n }\n for (const item of input.loopStopWhenJson) {\n if (!item || typeof item !== 'object' || !('kind' in item)) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson items must have a \"kind\" field.',\n 'invalid_loop_override',\n )\n }\n const kind = (item as AiAgentLoopStopCondition).kind\n if (kind === 'custom') {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson does not support kind \"custom\" \u2014 only \"stepCount\" and \"hasToolCall\" are JSON-safe and storable.',\n 'invalid_loop_override',\n )\n }\n if (kind !== 'stepCount' && kind !== 'hasToolCall') {\n throw new AiAgentRuntimeOverrideValidationError(\n `loopStopWhenJson contains unknown kind \"${String(kind)}\". Allowed: \"stepCount\", \"hasToolCall\".`,\n 'invalid_loop_override',\n )\n }\n if (kind === 'stepCount' && typeof (item as { count?: unknown }).count !== 'number') {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson stepCount item must have a numeric \"count\" field.',\n 'invalid_loop_override',\n )\n }\n if (kind === 'hasToolCall' && typeof (item as { toolName?: unknown }).toolName !== 'string') {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopStopWhenJson hasToolCall item must have a string \"toolName\" field.',\n 'invalid_loop_override',\n )\n }\n }\n }\n\n if (input.loopActiveToolsJson != null) {\n if (!Array.isArray(input.loopActiveToolsJson)) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopActiveToolsJson must be an array of tool name strings.',\n 'invalid_loop_override',\n )\n }\n for (const name of input.loopActiveToolsJson) {\n if (typeof name !== 'string' || name.length === 0) {\n throw new AiAgentRuntimeOverrideValidationError(\n 'loopActiveToolsJson entries must be non-empty strings.',\n 'invalid_loop_override',\n )\n }\n }\n if (input.agentAllowedTools && input.agentAllowedTools.length > 0) {\n const outsideAllowlist = input.loopActiveToolsJson.filter(\n (name) => !input.agentAllowedTools!.includes(name),\n )\n if (outsideAllowlist.length > 0) {\n throw new AiAgentRuntimeOverrideValidationError(\n `loopActiveToolsJson contains tools outside the agent's allowedTools: ${outsideAllowlist.join(', ')}.`,\n 'invalid_loop_override',\n )\n }\n }\n }\n }\n\n /**\n * Inserts or updates the runtime override for the given context.\n *\n * Validates `providerId` against the registry at write time so an admin\n * cannot save a typo (Phase 1.4 contract re-applied per spec \u00A7Data Models).\n * An unknown provider id throws a typed error.\n *\n * Also validates loop override fields (R5 mitigation \u2014 Phase 3):\n * - `loopStopWhenJson` items must use only JSON-safe kinds.\n * - `loopActiveToolsJson` items must be a subset of `agentAllowedTools`\n * when that is provided.\n *\n * The R6 base-URL allowlist check is intentionally NOT performed here \u2014\n * that enforcement lives at the HTTP layer (PUT settings route). The\n * repository trusts that callers have already validated the value.\n */\n async upsertDefault(\n input: AiAgentRuntimeOverrideInput,\n ctx: AiAgentRuntimeOverrideContext,\n ): Promise<AiAgentRuntimeOverride> {\n if (!ctx?.tenantId) {\n throw new Error('AiAgentRuntimeOverrideRepository.upsertDefault requires tenantId')\n }\n\n const normalizedProviderId = input.providerId\n ? canonicalProviderId(input.providerId, llmProviderRegistry.list().map((p) => p.id))\n : null\n if (input.providerId) {\n const knownProvider = normalizedProviderId ? llmProviderRegistry.get(normalizedProviderId) : null\n if (!knownProvider) {\n throw new AiAgentRuntimeOverrideValidationError(\n `Unknown provider id \"${input.providerId}\". Registered provider ids: ${llmProviderRegistry.list().map((p) => p.id).join(', ')}.`,\n )\n }\n }\n\n this.validateLoopInput(input)\n\n const orgFilter = ctx.organizationId ?? null\n const agentIdFilter = input.agentId ?? null\n const hasProviderId = Object.prototype.hasOwnProperty.call(input, 'providerId')\n const hasModelId = Object.prototype.hasOwnProperty.call(input, 'modelId')\n const hasBaseURL = Object.prototype.hasOwnProperty.call(input, 'baseURL')\n const hasAllowedOverrideProviders = Object.prototype.hasOwnProperty.call(input, 'allowedOverrideProviders')\n const hasAllowedOverrideModels = Object.prototype.hasOwnProperty.call(input, 'allowedOverrideModelsByProvider')\n\n return this.em.transactional(async (tx) => {\n const existing = await tx.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: agentIdFilter,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n\n if (existing) {\n if (hasProviderId) existing.providerId = normalizedProviderId\n if (hasModelId) existing.modelId = input.modelId ?? null\n if (hasBaseURL) existing.baseUrl = input.baseURL ?? null\n if (hasAllowedOverrideProviders) {\n existing.allowedOverrideProviders = input.allowedOverrideProviders ?? null\n }\n if (hasAllowedOverrideModels) {\n existing.allowedOverrideModelsByProvider = input.allowedOverrideModelsByProvider ?? {}\n }\n existing.updatedByUserId = ctx.userId ?? null\n existing.updatedAt = new Date()\n if ('loopDisabled' in input) existing.loopDisabled = input.loopDisabled ?? null\n if ('loopMaxSteps' in input) existing.loopMaxSteps = input.loopMaxSteps ?? null\n if ('loopMaxToolCalls' in input) existing.loopMaxToolCalls = input.loopMaxToolCalls ?? null\n if ('loopMaxWallClockMs' in input) existing.loopMaxWallClockMs = input.loopMaxWallClockMs ?? null\n if ('loopMaxTokens' in input) existing.loopMaxTokens = input.loopMaxTokens ?? null\n if ('loopStopWhenJson' in input) existing.loopStopWhenJson = input.loopStopWhenJson ?? null\n if ('loopActiveToolsJson' in input) existing.loopActiveToolsJson = input.loopActiveToolsJson ?? null\n await tx.persist(existing).flush()\n return existing\n }\n\n const row = tx.create(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: agentIdFilter,\n providerId: hasProviderId ? normalizedProviderId : null,\n modelId: hasModelId ? (input.modelId ?? null) : null,\n baseUrl: hasBaseURL ? (input.baseURL ?? null) : null,\n allowedOverrideProviders: hasAllowedOverrideProviders\n ? (input.allowedOverrideProviders ?? null)\n : null,\n allowedOverrideModelsByProvider: hasAllowedOverrideModels\n ? (input.allowedOverrideModelsByProvider ?? {})\n : {},\n updatedByUserId: ctx.userId ?? null,\n loopDisabled: input.loopDisabled ?? null,\n loopMaxSteps: input.loopMaxSteps ?? null,\n loopMaxToolCalls: input.loopMaxToolCalls ?? null,\n loopMaxWallClockMs: input.loopMaxWallClockMs ?? null,\n loopMaxTokens: input.loopMaxTokens ?? null,\n loopStopWhenJson: input.loopStopWhenJson ?? null,\n loopActiveToolsJson: input.loopActiveToolsJson ?? null,\n } as unknown as AiAgentRuntimeOverride)\n await tx.persist(row).flush()\n return row\n })\n }\n\n /**\n * Soft-deletes the active override matching the given context by setting\n * `deleted_at = now()`. Returns true when a row was found and cleared,\n * false when no active row existed.\n */\n async clearDefault(ctx: {\n tenantId: string\n organizationId?: string | null\n agentId?: string | null\n }): Promise<boolean> {\n if (!ctx?.tenantId) return false\n\n const orgFilter = ctx.organizationId ?? null\n const agentIdFilter = ctx.agentId ?? null\n\n return this.em.transactional(async (tx) => {\n const existing = await tx.findOne(AiAgentRuntimeOverride, {\n tenantId: ctx.tenantId,\n organizationId: orgFilter,\n agentId: agentIdFilter,\n deletedAt: null,\n } satisfies FilterQuery<AiAgentRuntimeOverride>)\n if (!existing) return false\n if (\n existing.allowedOverrideProviders != null ||\n Object.keys(existing.allowedOverrideModelsByProvider ?? {}).length > 0\n ) {\n existing.providerId = null\n existing.modelId = null\n existing.baseUrl = null\n existing.updatedAt = new Date()\n await tx.persist(existing).flush()\n return true\n }\n existing.deletedAt = new Date()\n await tx.persist(existing).flush()\n return true\n })\n }\n}\n\n/**\n * Thrown by `upsertDefault` when validation fails (unknown provider id,\n * invalid loop override JSON).\n */\nexport class AiAgentRuntimeOverrideValidationError extends Error {\n readonly code: string\n\n constructor(message: string, code = 'invalid_override') {\n super(message)\n this.name = 'AiAgentRuntimeOverrideValidationError'\n this.code = code\n }\n}\n\nexport default AiAgentRuntimeOverrideRepository\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,8 @@
1
- import { asFunction, asValue } from "awilix";
1
+ import { asValue } from "awilix";
2
2
  import { toolRegistry } from "./lib/tool-registry.js";
3
- import { createModerationService } from "./lib/moderation.js";
4
3
  function register(container) {
5
4
  container.register({
6
- mcpToolRegistry: asValue(toolRegistry),
7
- // Input pre-moderation service (OpenAI /v1/moderations). Singleton +
8
- // overridable by downstream apps via the module overrides DI seam.
9
- moderationService: asFunction(() => createModerationService()).singleton()
5
+ mcpToolRegistry: asValue(toolRegistry)
10
6
  });
11
7
  }
12
8
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/ai_assistant/di.ts"],
4
- "sourcesContent": ["import { asFunction, asValue } from 'awilix'\nimport type { AwilixContainer } from 'awilix'\nimport { toolRegistry } from './lib/tool-registry'\nimport { createModerationService } from './lib/moderation'\n\nexport function register(container: AwilixContainer): void {\n container.register({\n mcpToolRegistry: asValue(toolRegistry),\n // Input pre-moderation service (OpenAI /v1/moderations). Singleton +\n // overridable by downstream apps via the module overrides DI seam.\n moderationService: asFunction(() => createModerationService()).singleton(),\n })\n}\n"],
5
- "mappings": "AAAA,SAAS,YAAY,eAAe;AAEpC,SAAS,oBAAoB;AAC7B,SAAS,+BAA+B;AAEjC,SAAS,SAAS,WAAkC;AACzD,YAAU,SAAS;AAAA,IACjB,iBAAiB,QAAQ,YAAY;AAAA;AAAA;AAAA,IAGrC,mBAAmB,WAAW,MAAM,wBAAwB,CAAC,EAAE,UAAU;AAAA,EAC3E,CAAC;AACH;",
4
+ "sourcesContent": ["import { asValue } from 'awilix'\nimport type { AwilixContainer } from 'awilix'\nimport { toolRegistry } from './lib/tool-registry'\n\nexport function register(container: AwilixContainer): void {\n container.register({\n mcpToolRegistry: asValue(toolRegistry),\n })\n}\n"],
5
+ "mappings": "AAAA,SAAS,eAAe;AAExB,SAAS,oBAAoB;AAEtB,SAAS,SAAS,WAAkC;AACzD,YAAU,SAAS;AAAA,IACjB,iBAAiB,QAAQ,YAAY;AAAA,EACvC,CAAC;AACH;",
6
6
  "names": []
7
7
  }
@@ -39,12 +39,6 @@ const events = [
39
39
  entity: "ai_chat_conversation",
40
40
  category: "lifecycle",
41
41
  clientBroadcast: true
42
- },
43
- {
44
- id: "ai_assistant.moderation_flag.created",
45
- label: "AI Moderation Flag Created",
46
- entity: "ai_moderation_flag",
47
- category: "system"
48
42
  }
49
43
  ];
50
44
  const eventsConfig = createModuleEvents({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/ai_assistant/events.ts"],
4
- "sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\n/**\n * AI Assistant Module Events\n *\n * Typed declarations for the pending-action lifecycle events emitted by\n * the Phase 3 WS-C mutation approval flow. The event IDs are FROZEN per\n * `BACKWARD_COMPATIBILITY.md` \u00A75 (contract surface #5) and MUST NOT be\n * renamed; additive payload changes are allowed.\n *\n * - `ai.action.confirmed` \u2014 emitted by `executePendingActionConfirm`\n * (Step 5.8) after the `pending \u2192 confirmed \u2192 executing \u2192 {confirmed|\n * failed}` transition. The handler's outcome lives in\n * `executionResult`; partial-stale rows carry the surviving stale\n * records via `failedRecords`.\n * - `ai.action.cancelled` \u2014 emitted by `executePendingActionCancel`\n * (Step 5.9) after the atomic `pending \u2192 cancelled` transition.\n * - `ai.action.expired` \u2014 emitted by the Step 5.9 expired short-circuit\n * AND by the Step 5.12 cleanup worker when the TTL elapses. The\n * worker is the actor in that path, so `resolvedByUserId` is NOT part\n * of the payload.\n */\nconst events = [\n {\n id: 'ai.action.confirmed',\n label: 'AI Pending Action Confirmed',\n entity: 'ai_pending_action',\n category: 'system' as const,\n },\n {\n id: 'ai.action.cancelled',\n label: 'AI Pending Action Cancelled',\n entity: 'ai_pending_action',\n category: 'system' as const,\n },\n {\n id: 'ai.action.expired',\n label: 'AI Pending Action Expired',\n entity: 'ai_pending_action',\n category: 'system' as const,\n },\n {\n id: 'ai.token_usage.recorded',\n label: 'AI Token Usage Recorded',\n entity: 'token_usage',\n category: 'system' as const,\n clientBroadcast: false,\n portalBroadcast: false,\n },\n {\n id: 'ai_assistant.conversation.shared',\n label: 'AI Conversation Shared',\n entity: 'ai_chat_conversation',\n category: 'lifecycle' as const,\n clientBroadcast: true,\n },\n {\n id: 'ai_assistant.conversation.unshared',\n label: 'AI Conversation Unshared',\n entity: 'ai_chat_conversation',\n category: 'lifecycle' as const,\n clientBroadcast: true,\n },\n {\n id: 'ai_assistant.moderation_flag.created',\n label: 'AI Moderation Flag Created',\n entity: 'ai_moderation_flag',\n category: 'system' as const,\n },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'ai_assistant',\n events,\n})\n\n/** Type-safe event emitter for the ai_assistant module. */\nexport const emitAiAssistantEvent = eventsConfig.emit\n\n/** Event IDs declared by the ai_assistant module. */\nexport type AiAssistantEventId = (typeof events)[number]['id']\n\n/**\n * Typed payload contracts for each ai_assistant event. Payloads are\n * additive-only \u2014 extend existing fields rather than renaming/removing.\n */\nexport interface AiActionFailedRecordPayload {\n recordId: string\n error: { code: string; message: string }\n}\n\nexport interface AiActionExecutionResultPayload {\n recordId?: string\n commandName?: string\n error?: { code: string; message: string }\n}\n\nexport interface AiActionConfirmedPayload {\n pendingActionId: string\n agentId: string\n toolName: string\n status: string\n tenantId: string | null\n organizationId: string | null\n userId: string\n resolvedByUserId: string\n resolvedAt: string\n executionResult: AiActionExecutionResultPayload | null\n failedRecords?: AiActionFailedRecordPayload[] | null\n}\n\nexport interface AiActionCancelledPayload {\n pendingActionId: string\n agentId: string\n toolName: string\n status: string\n tenantId: string | null\n organizationId: string | null\n userId: string\n resolvedByUserId: string\n resolvedAt: string\n executionResult: AiActionExecutionResultPayload | null\n reason?: string\n}\n\nexport interface AiActionExpiredPayload {\n pendingActionId: string\n agentId: string\n toolName: string\n status: string\n tenantId: string | null\n organizationId: string | null\n userId: string | null\n resolvedByUserId: null\n resolvedAt: string\n expiresAt?: string\n expiredAt?: string\n}\n\nexport interface AiConversationSharedPayload {\n conversationId: string\n tenantId: string\n organizationId: string | null\n ownerUserId: string\n participantUserId: string\n role: string\n}\n\nexport interface AiConversationUnsharedPayload {\n conversationId: string\n tenantId: string\n organizationId: string | null\n ownerUserId: string\n participantUserId: string\n}\n\n/**\n * Emitted (best-effort) when the input moderation gate blocks a turn and the\n * audit row is persisted. Carries category flags only \u2014 never prompt content.\n *\n * Spec `2026-06-04-ai-input-moderation-and-safety-identifiers`.\n */\nexport interface AiModerationFlagCreatedPayload {\n id: string\n tenantId: string\n organizationId: string | null\n agentId: string\n userId: string\n categories: string[]\n}\n\nexport default eventsConfig\n"],
5
- "mappings": "AAAA,SAAS,0BAA0B;AAsBnC,MAAM,SAAS;AAAA,EACb;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;AAEO,MAAM,eAAe,mBAAmB;AAAA,EAC7C,UAAU;AAAA,EACV;AACF,CAAC;AAGM,MAAM,uBAAuB,aAAa;AA8FjD,IAAO,iBAAQ;",
4
+ "sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\n/**\n * AI Assistant Module Events\n *\n * Typed declarations for the pending-action lifecycle events emitted by\n * the Phase 3 WS-C mutation approval flow. The event IDs are FROZEN per\n * `BACKWARD_COMPATIBILITY.md` \u00A75 (contract surface #5) and MUST NOT be\n * renamed; additive payload changes are allowed.\n *\n * - `ai.action.confirmed` \u2014 emitted by `executePendingActionConfirm`\n * (Step 5.8) after the `pending \u2192 confirmed \u2192 executing \u2192 {confirmed|\n * failed}` transition. The handler's outcome lives in\n * `executionResult`; partial-stale rows carry the surviving stale\n * records via `failedRecords`.\n * - `ai.action.cancelled` \u2014 emitted by `executePendingActionCancel`\n * (Step 5.9) after the atomic `pending \u2192 cancelled` transition.\n * - `ai.action.expired` \u2014 emitted by the Step 5.9 expired short-circuit\n * AND by the Step 5.12 cleanup worker when the TTL elapses. The\n * worker is the actor in that path, so `resolvedByUserId` is NOT part\n * of the payload.\n */\nconst events = [\n {\n id: 'ai.action.confirmed',\n label: 'AI Pending Action Confirmed',\n entity: 'ai_pending_action',\n category: 'system' as const,\n },\n {\n id: 'ai.action.cancelled',\n label: 'AI Pending Action Cancelled',\n entity: 'ai_pending_action',\n category: 'system' as const,\n },\n {\n id: 'ai.action.expired',\n label: 'AI Pending Action Expired',\n entity: 'ai_pending_action',\n category: 'system' as const,\n },\n {\n id: 'ai.token_usage.recorded',\n label: 'AI Token Usage Recorded',\n entity: 'token_usage',\n category: 'system' as const,\n clientBroadcast: false,\n portalBroadcast: false,\n },\n {\n id: 'ai_assistant.conversation.shared',\n label: 'AI Conversation Shared',\n entity: 'ai_chat_conversation',\n category: 'lifecycle' as const,\n clientBroadcast: true,\n },\n {\n id: 'ai_assistant.conversation.unshared',\n label: 'AI Conversation Unshared',\n entity: 'ai_chat_conversation',\n category: 'lifecycle' as const,\n clientBroadcast: true,\n },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'ai_assistant',\n events,\n})\n\n/** Type-safe event emitter for the ai_assistant module. */\nexport const emitAiAssistantEvent = eventsConfig.emit\n\n/** Event IDs declared by the ai_assistant module. */\nexport type AiAssistantEventId = (typeof events)[number]['id']\n\n/**\n * Typed payload contracts for each ai_assistant event. Payloads are\n * additive-only \u2014 extend existing fields rather than renaming/removing.\n */\nexport interface AiActionFailedRecordPayload {\n recordId: string\n error: { code: string; message: string }\n}\n\nexport interface AiActionExecutionResultPayload {\n recordId?: string\n commandName?: string\n error?: { code: string; message: string }\n}\n\nexport interface AiActionConfirmedPayload {\n pendingActionId: string\n agentId: string\n toolName: string\n status: string\n tenantId: string | null\n organizationId: string | null\n userId: string\n resolvedByUserId: string\n resolvedAt: string\n executionResult: AiActionExecutionResultPayload | null\n failedRecords?: AiActionFailedRecordPayload[] | null\n}\n\nexport interface AiActionCancelledPayload {\n pendingActionId: string\n agentId: string\n toolName: string\n status: string\n tenantId: string | null\n organizationId: string | null\n userId: string\n resolvedByUserId: string\n resolvedAt: string\n executionResult: AiActionExecutionResultPayload | null\n reason?: string\n}\n\nexport interface AiActionExpiredPayload {\n pendingActionId: string\n agentId: string\n toolName: string\n status: string\n tenantId: string | null\n organizationId: string | null\n userId: string | null\n resolvedByUserId: null\n resolvedAt: string\n expiresAt?: string\n expiredAt?: string\n}\n\nexport interface AiConversationSharedPayload {\n conversationId: string\n tenantId: string\n organizationId: string | null\n ownerUserId: string\n participantUserId: string\n role: string\n}\n\nexport interface AiConversationUnsharedPayload {\n conversationId: string\n tenantId: string\n organizationId: string | null\n ownerUserId: string\n participantUserId: string\n}\n\nexport default eventsConfig\n"],
5
+ "mappings": "AAAA,SAAS,0BAA0B;AAsBnC,MAAM,SAAS;AAAA,EACb;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,EACnB;AACF;AAEO,MAAM,eAAe,mBAAmB;AAAA,EAC7C,UAAU;AAAA,EACV;AACF,CAAC;AAGM,MAAM,uBAAuB,aAAa;AA+EjD,IAAO,iBAAQ;",
6
6
  "names": []
7
7
  }