@open-mercato/ai-assistant 0.5.1-develop.3036.f02c281f23 → 0.5.1-develop.3045.b4b3320cc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +361 -0
- package/README.md +5 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +2 -2
- package/dist/modules/ai_assistant/__integration__/TC-AI-002-agent-policy.spec.js +73 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-002-agent-policy.spec.js.map +7 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-AGENT-SETTINGS-005-settings-page.spec.js +484 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-AGENT-SETTINGS-005-settings-page.spec.js.map +7 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-PLAYGROUND-004-playground.spec.js +251 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-PLAYGROUND-004-playground.spec.js.map +7 -0
- package/dist/modules/ai_assistant/__integration__/TC-INT-AI-TOOLS.spec.js +91 -0
- package/dist/modules/ai_assistant/__integration__/TC-INT-AI-TOOLS.spec.js.map +7 -0
- package/dist/modules/ai_assistant/ai-tools/attachments-pack.js +202 -0
- package/dist/modules/ai_assistant/ai-tools/attachments-pack.js.map +7 -0
- package/dist/modules/ai_assistant/ai-tools/meta-pack.js +121 -0
- package/dist/modules/ai_assistant/ai-tools/meta-pack.js.map +7 -0
- package/dist/modules/ai_assistant/ai-tools/search-pack.js +94 -0
- package/dist/modules/ai_assistant/ai-tools/search-pack.js.map +7 -0
- package/dist/modules/ai_assistant/ai-tools.js +14 -0
- package/dist/modules/ai_assistant/ai-tools.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/actions/[id]/cancel/route.js +175 -0
- package/dist/modules/ai_assistant/api/ai/actions/[id]/cancel/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/actions/[id]/confirm/route.js +174 -0
- package/dist/modules/ai_assistant/api/ai/actions/[id]/confirm/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/actions/[id]/route.js +101 -0
- package/dist/modules/ai_assistant/api/ai/actions/[id]/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/route.js +311 -0
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/route.js +246 -0
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/agents/route.js +94 -0
- package/dist/modules/ai_assistant/api/ai/agents/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/chat/route.js +173 -0
- package/dist/modules/ai_assistant/api/ai/chat/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/run-object/route.js +167 -0
- package/dist/modules/ai_assistant/api/ai/run-object/route.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js +1111 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.js +10 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.meta.js +28 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.meta.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.js +10 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.meta.js +30 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.meta.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js +4 -6
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js.map +2 -2
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js +1 -21
- package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js.map +2 -2
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js +462 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.js +10 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.meta.js +28 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.meta.js.map +7 -0
- package/dist/modules/ai_assistant/cli.js +78 -12
- package/dist/modules/ai_assistant/cli.js.map +2 -2
- package/dist/modules/ai_assistant/data/entities/AiAgentMutationPolicyOverride.js +5 -0
- package/dist/modules/ai_assistant/data/entities/AiAgentMutationPolicyOverride.js.map +7 -0
- package/dist/modules/ai_assistant/data/entities/AiAgentPromptOverride.js +5 -0
- package/dist/modules/ai_assistant/data/entities/AiAgentPromptOverride.js.map +7 -0
- package/dist/modules/ai_assistant/data/entities/AiPendingAction.js +5 -0
- package/dist/modules/ai_assistant/data/entities/AiPendingAction.js.map +7 -0
- package/dist/modules/ai_assistant/data/entities.js +228 -0
- package/dist/modules/ai_assistant/data/entities.js.map +7 -0
- package/dist/modules/ai_assistant/data/repositories/AiAgentMutationPolicyOverrideRepository.js +95 -0
- package/dist/modules/ai_assistant/data/repositories/AiAgentMutationPolicyOverrideRepository.js.map +7 -0
- package/dist/modules/ai_assistant/data/repositories/AiAgentPromptOverrideRepository.js +95 -0
- package/dist/modules/ai_assistant/data/repositories/AiAgentPromptOverrideRepository.js.map +7 -0
- package/dist/modules/ai_assistant/data/repositories/AiPendingActionRepository.js +223 -0
- package/dist/modules/ai_assistant/data/repositories/AiPendingActionRepository.js.map +7 -0
- package/dist/modules/ai_assistant/events.js +33 -0
- package/dist/modules/ai_assistant/events.js.map +7 -0
- package/dist/modules/ai_assistant/i18n/de.json +252 -0
- package/dist/modules/ai_assistant/i18n/en.json +252 -0
- package/dist/modules/ai_assistant/i18n/es.json +252 -0
- package/dist/modules/ai_assistant/i18n/pl.json +252 -0
- package/dist/modules/ai_assistant/lib/agent-policy.js +168 -0
- package/dist/modules/ai_assistant/lib/agent-policy.js.map +7 -0
- package/dist/modules/ai_assistant/lib/agent-registry.js +195 -0
- package/dist/modules/ai_assistant/lib/agent-registry.js.map +7 -0
- package/dist/modules/ai_assistant/lib/agent-runtime.js +451 -0
- package/dist/modules/ai_assistant/lib/agent-runtime.js.map +7 -0
- package/dist/modules/ai_assistant/lib/agent-tools.js +223 -0
- package/dist/modules/ai_assistant/lib/agent-tools.js.map +7 -0
- package/dist/modules/ai_assistant/lib/agent-transport.js +25 -0
- package/dist/modules/ai_assistant/lib/agent-transport.js.map +7 -0
- package/dist/modules/ai_assistant/lib/ai-agent-definition.js +11 -0
- package/dist/modules/ai_assistant/lib/ai-agent-definition.js.map +7 -0
- package/dist/modules/ai_assistant/lib/ai-agents-generated.d.js +1 -0
- package/dist/modules/ai_assistant/lib/ai-agents-generated.d.js.map +7 -0
- package/dist/modules/ai_assistant/lib/ai-api-operation-runner.js +239 -0
- package/dist/modules/ai_assistant/lib/ai-api-operation-runner.js.map +7 -0
- package/dist/modules/ai_assistant/lib/ai-overrides.js +189 -0
- package/dist/modules/ai_assistant/lib/ai-overrides.js.map +7 -0
- package/dist/modules/ai_assistant/lib/ai-tool-definition.js +7 -0
- package/dist/modules/ai_assistant/lib/ai-tool-definition.js.map +7 -0
- package/dist/modules/ai_assistant/lib/ai-tools-generated.d.js +1 -0
- package/dist/modules/ai_assistant/lib/ai-tools-generated.d.js.map +7 -0
- package/dist/modules/ai_assistant/lib/api-backed-tool.js +48 -0
- package/dist/modules/ai_assistant/lib/api-backed-tool.js.map +7 -0
- package/dist/modules/ai_assistant/lib/attachment-bridge-types.js +1 -0
- package/dist/modules/ai_assistant/lib/attachment-bridge-types.js.map +7 -0
- package/dist/modules/ai_assistant/lib/attachment-parts.js +276 -0
- package/dist/modules/ai_assistant/lib/attachment-parts.js.map +7 -0
- package/dist/modules/ai_assistant/lib/model-factory.js +68 -0
- package/dist/modules/ai_assistant/lib/model-factory.js.map +7 -0
- package/dist/modules/ai_assistant/lib/pending-action-cancel.js +86 -0
- package/dist/modules/ai_assistant/lib/pending-action-cancel.js.map +7 -0
- package/dist/modules/ai_assistant/lib/pending-action-client.js +35 -0
- package/dist/modules/ai_assistant/lib/pending-action-client.js.map +7 -0
- package/dist/modules/ai_assistant/lib/pending-action-executor.js +243 -0
- package/dist/modules/ai_assistant/lib/pending-action-executor.js.map +7 -0
- package/dist/modules/ai_assistant/lib/pending-action-recheck.js +246 -0
- package/dist/modules/ai_assistant/lib/pending-action-recheck.js.map +7 -0
- package/dist/modules/ai_assistant/lib/pending-action-types.js +70 -0
- package/dist/modules/ai_assistant/lib/pending-action-types.js.map +7 -0
- package/dist/modules/ai_assistant/lib/prepare-mutation.js +315 -0
- package/dist/modules/ai_assistant/lib/prepare-mutation.js.map +7 -0
- package/dist/modules/ai_assistant/lib/prompt-composition-types.js +7 -0
- package/dist/modules/ai_assistant/lib/prompt-composition-types.js.map +7 -0
- package/dist/modules/ai_assistant/lib/prompt-override-merge.js +175 -0
- package/dist/modules/ai_assistant/lib/prompt-override-merge.js.map +7 -0
- package/dist/modules/ai_assistant/lib/schema-utils.js +5 -1
- package/dist/modules/ai_assistant/lib/schema-utils.js.map +2 -2
- package/dist/modules/ai_assistant/lib/tool-executor.js +13 -2
- package/dist/modules/ai_assistant/lib/tool-executor.js.map +2 -2
- package/dist/modules/ai_assistant/lib/tool-loader.js +86 -11
- package/dist/modules/ai_assistant/lib/tool-loader.js.map +2 -2
- package/dist/modules/ai_assistant/lib/tool-test-fixtures.js +120 -0
- package/dist/modules/ai_assistant/lib/tool-test-fixtures.js.map +7 -0
- package/dist/modules/ai_assistant/lib/tool-test-runner.js +418 -0
- package/dist/modules/ai_assistant/lib/tool-test-runner.js.map +7 -0
- package/dist/modules/ai_assistant/migrations/Migration20260419100521.js +17 -0
- package/dist/modules/ai_assistant/migrations/Migration20260419100521.js.map +7 -0
- package/dist/modules/ai_assistant/migrations/Migration20260419132948.js +16 -0
- package/dist/modules/ai_assistant/migrations/Migration20260419132948.js.map +7 -0
- package/dist/modules/ai_assistant/migrations/Migration20260419134235.js +17 -0
- package/dist/modules/ai_assistant/migrations/Migration20260419134235.js.map +7 -0
- package/dist/modules/ai_assistant/setup.js +36 -0
- package/dist/modules/ai_assistant/setup.js.map +2 -2
- package/dist/modules/ai_assistant/workers/ai-pending-action-cleanup.js +161 -0
- package/dist/modules/ai_assistant/workers/ai-pending-action-cleanup.js.map +7 -0
- package/generated/entities/ai_agent_mutation_policy_override/index.ts +9 -0
- package/generated/entities/ai_agent_prompt_override/index.ts +10 -0
- package/generated/entities/ai_pending_action/index.ts +24 -0
- package/generated/entities.ids.generated.ts +13 -0
- package/generated/entity-fields-registry.ts +57 -0
- package/jest.config.cjs +7 -0
- package/package.json +4 -4
- package/src/index.ts +215 -0
- package/src/modules/ai_assistant/__integration__/README.md +5 -0
- package/src/modules/ai_assistant/__integration__/TC-AI-002-agent-policy.spec.ts +115 -0
- package/src/modules/ai_assistant/__integration__/TC-AI-AGENT-SETTINGS-005-settings-page.spec.ts +574 -0
- package/src/modules/ai_assistant/__integration__/TC-AI-PLAYGROUND-004-playground.spec.ts +333 -0
- package/src/modules/ai_assistant/__integration__/TC-INT-AI-TOOLS.spec.ts +135 -0
- package/src/modules/ai_assistant/__tests__/events.test.ts +145 -0
- package/src/modules/ai_assistant/__tests__/integration/pending-action-contract.test.ts +1015 -0
- package/src/modules/ai_assistant/__tests__/integration/ws-c-attachment-bridge.test.ts +235 -0
- package/src/modules/ai_assistant/__tests__/integration/ws-c-policy-and-tools.test.ts +330 -0
- package/src/modules/ai_assistant/__tests__/integration/ws-c-tool-pack-coverage.test.ts +285 -0
- package/src/modules/ai_assistant/ai-tools/__tests__/attachments-pack.test.ts +322 -0
- package/src/modules/ai_assistant/ai-tools/__tests__/meta-pack.test.ts +218 -0
- package/src/modules/ai_assistant/ai-tools/__tests__/search-pack.test.ts +192 -0
- package/src/modules/ai_assistant/ai-tools/attachments-pack.ts +269 -0
- package/src/modules/ai_assistant/ai-tools/meta-pack.ts +140 -0
- package/src/modules/ai_assistant/ai-tools/search-pack.ts +122 -0
- package/src/modules/ai_assistant/ai-tools.ts +21 -0
- package/src/modules/ai_assistant/api/ai/actions/[id]/__tests__/route.test.ts +222 -0
- package/src/modules/ai_assistant/api/ai/actions/[id]/cancel/__tests__/route.test.ts +286 -0
- package/src/modules/ai_assistant/api/ai/actions/[id]/cancel/route.ts +237 -0
- package/src/modules/ai_assistant/api/ai/actions/[id]/confirm/__tests__/route.test.ts +339 -0
- package/src/modules/ai_assistant/api/ai/actions/[id]/confirm/route.ts +229 -0
- package/src/modules/ai_assistant/api/ai/actions/[id]/route.ts +142 -0
- package/src/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/__tests__/route.test.ts +367 -0
- package/src/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/route.ts +380 -0
- package/src/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/__tests__/route.test.ts +333 -0
- package/src/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/route.ts +307 -0
- package/src/modules/ai_assistant/api/ai/agents/route.ts +107 -0
- package/src/modules/ai_assistant/api/ai/chat/__tests__/route.test.ts +282 -0
- package/src/modules/ai_assistant/api/ai/chat/route.ts +207 -0
- package/src/modules/ai_assistant/api/ai/run-object/__tests__/route.test.ts +282 -0
- package/src/modules/ai_assistant/api/ai/run-object/route.ts +204 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.tsx +1419 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/agents/page.meta.ts +26 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/agents/page.tsx +12 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/legacy/page.meta.ts +28 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/legacy/page.tsx +12 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/page.meta.ts +8 -23
- package/src/modules/ai_assistant/backend/config/ai-assistant/page.tsx +15 -10
- package/src/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.tsx +604 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/playground/page.meta.ts +26 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/playground/page.tsx +12 -0
- package/src/modules/ai_assistant/cli.ts +99 -24
- package/src/modules/ai_assistant/data/__tests__/schema-unique-indexes.test.ts +69 -0
- package/src/modules/ai_assistant/data/entities/AiAgentMutationPolicyOverride.ts +7 -0
- package/src/modules/ai_assistant/data/entities/AiAgentPromptOverride.ts +7 -0
- package/src/modules/ai_assistant/data/entities/AiPendingAction.ts +7 -0
- package/src/modules/ai_assistant/data/entities.ts +270 -0
- package/src/modules/ai_assistant/data/repositories/AiAgentMutationPolicyOverrideRepository.ts +129 -0
- package/src/modules/ai_assistant/data/repositories/AiAgentPromptOverrideRepository.ts +132 -0
- package/src/modules/ai_assistant/data/repositories/AiPendingActionRepository.ts +334 -0
- package/src/modules/ai_assistant/data/repositories/__tests__/AiAgentMutationPolicyOverrideRepository.test.ts +195 -0
- package/src/modules/ai_assistant/data/repositories/__tests__/AiAgentPromptOverrideRepository.test.ts +197 -0
- package/src/modules/ai_assistant/data/repositories/__tests__/AiPendingActionRepository.test.ts +357 -0
- package/src/modules/ai_assistant/events.ts +112 -0
- package/src/modules/ai_assistant/i18n/de.json +252 -0
- package/src/modules/ai_assistant/i18n/en.json +252 -0
- package/src/modules/ai_assistant/i18n/es.json +252 -0
- package/src/modules/ai_assistant/i18n/pl.json +252 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-policy.mutation-override.test.ts +203 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-policy.test.ts +385 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-registry.test.ts +217 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime-object.test.ts +329 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime-parity.test.ts +573 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime.test.ts +291 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-tools.test.ts +172 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-transport.test.ts +41 -0
- package/src/modules/ai_assistant/lib/__tests__/ai-agent-definition.test.ts +183 -0
- package/src/modules/ai_assistant/lib/__tests__/ai-api-operation-runner.test.ts +432 -0
- package/src/modules/ai_assistant/lib/__tests__/ai-overrides.test.ts +308 -0
- package/src/modules/ai_assistant/lib/__tests__/api-backed-tool.test.ts +302 -0
- package/src/modules/ai_assistant/lib/__tests__/attachment-bridge-and-prompt-types.test.ts +188 -0
- package/src/modules/ai_assistant/lib/__tests__/attachment-parts.test.ts +531 -0
- package/src/modules/ai_assistant/lib/__tests__/max-steps-budget.integration.test.ts +263 -0
- package/src/modules/ai_assistant/lib/__tests__/model-factory.integration.test.ts +183 -0
- package/src/modules/ai_assistant/lib/__tests__/model-factory.test.ts +168 -0
- package/src/modules/ai_assistant/lib/__tests__/pending-action-cancel.test.ts +235 -0
- package/src/modules/ai_assistant/lib/__tests__/pending-action-client.test.ts +148 -0
- package/src/modules/ai_assistant/lib/__tests__/pending-action-executor.test.ts +348 -0
- package/src/modules/ai_assistant/lib/__tests__/pending-action-recheck.test.ts +378 -0
- package/src/modules/ai_assistant/lib/__tests__/phase-0-additive-contract.test.ts +299 -0
- package/src/modules/ai_assistant/lib/__tests__/prepare-mutation.test.ts +610 -0
- package/src/modules/ai_assistant/lib/__tests__/prompt-override-merge.test.ts +136 -0
- package/src/modules/ai_assistant/lib/__tests__/tool-loader.test.ts +125 -0
- package/src/modules/ai_assistant/lib/agent-policy.ts +270 -0
- package/src/modules/ai_assistant/lib/agent-registry.ts +277 -0
- package/src/modules/ai_assistant/lib/agent-runtime.ts +751 -0
- package/src/modules/ai_assistant/lib/agent-tools.ts +396 -0
- package/src/modules/ai_assistant/lib/agent-transport.ts +51 -0
- package/src/modules/ai_assistant/lib/ai-agent-definition.ts +86 -0
- package/src/modules/ai_assistant/lib/ai-agents-generated.d.ts +18 -0
- package/src/modules/ai_assistant/lib/ai-api-operation-runner.ts +333 -0
- package/src/modules/ai_assistant/lib/ai-overrides.ts +389 -0
- package/src/modules/ai_assistant/lib/ai-tool-definition.ts +7 -0
- package/src/modules/ai_assistant/lib/ai-tools-generated.d.ts +7 -0
- package/src/modules/ai_assistant/lib/api-backed-tool.ts +85 -0
- package/src/modules/ai_assistant/lib/attachment-bridge-types.ts +24 -0
- package/src/modules/ai_assistant/lib/attachment-parts.ts +433 -0
- package/src/modules/ai_assistant/lib/model-factory.ts +212 -0
- package/src/modules/ai_assistant/lib/pending-action-cancel.ts +179 -0
- package/src/modules/ai_assistant/lib/pending-action-client.ts +126 -0
- package/src/modules/ai_assistant/lib/pending-action-executor.ts +424 -0
- package/src/modules/ai_assistant/lib/pending-action-recheck.ts +410 -0
- package/src/modules/ai_assistant/lib/pending-action-types.ts +194 -0
- package/src/modules/ai_assistant/lib/prepare-mutation.ts +448 -0
- package/src/modules/ai_assistant/lib/prompt-composition-types.ts +24 -0
- package/src/modules/ai_assistant/lib/prompt-override-merge.ts +253 -0
- package/src/modules/ai_assistant/lib/schema-utils.ts +14 -2
- package/src/modules/ai_assistant/lib/tool-executor.ts +25 -3
- package/src/modules/ai_assistant/lib/tool-loader.ts +159 -13
- package/src/modules/ai_assistant/lib/tool-test-fixtures.ts +160 -0
- package/src/modules/ai_assistant/lib/tool-test-runner.ts +596 -0
- package/src/modules/ai_assistant/lib/types.ts +105 -2
- package/src/modules/ai_assistant/migrations/.snapshot-open-mercato.json +871 -0
- package/src/modules/ai_assistant/migrations/Migration20260419100521.ts +17 -0
- package/src/modules/ai_assistant/migrations/Migration20260419132948.ts +16 -0
- package/src/modules/ai_assistant/migrations/Migration20260419134235.ts +17 -0
- package/src/modules/ai_assistant/setup.ts +53 -0
- package/src/modules/ai_assistant/workers/__tests__/ai-pending-action-cleanup.test.ts +333 -0
- package/src/modules/ai_assistant/workers/ai-pending-action-cleanup.ts +269 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { AiPendingActionRepository } from "../data/repositories/AiPendingActionRepository.js";
|
|
2
|
+
import {
|
|
3
|
+
emitAiAssistantEvent
|
|
4
|
+
} from "../events.js";
|
|
5
|
+
import { AiPendingActionStateError } from "../lib/pending-action-types.js";
|
|
6
|
+
const metadata = {
|
|
7
|
+
queue: "ai-pending-action-cleanup",
|
|
8
|
+
id: "ai_assistant:cleanup-expired-pending-actions",
|
|
9
|
+
concurrency: 1
|
|
10
|
+
};
|
|
11
|
+
const DEFAULT_PAGE_SIZE = 100;
|
|
12
|
+
const MAX_PAGES_PER_TENANT = 50;
|
|
13
|
+
const defaultEmitter = async (eventId, payload) => {
|
|
14
|
+
await emitAiAssistantEvent(eventId, payload, {
|
|
15
|
+
persistent: true
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
async function discoverTenantsDefault(em, now) {
|
|
19
|
+
const connection = em.getConnection();
|
|
20
|
+
const rows = await connection.execute(
|
|
21
|
+
`select distinct "tenant_id", "organization_id"
|
|
22
|
+
from "ai_pending_actions"
|
|
23
|
+
where "status" = 'pending'
|
|
24
|
+
and "expires_at" < ?`,
|
|
25
|
+
[now],
|
|
26
|
+
"all"
|
|
27
|
+
);
|
|
28
|
+
if (!Array.isArray(rows)) return [];
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const row of rows) {
|
|
31
|
+
const tenantId = typeof row.tenant_id === "string" ? row.tenant_id : null;
|
|
32
|
+
if (!tenantId) continue;
|
|
33
|
+
const organizationId = typeof row.organization_id === "string" ? row.organization_id : null;
|
|
34
|
+
out.push({ tenantId, organizationId });
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
function toIso(value, fallback) {
|
|
39
|
+
if (value instanceof Date) return value.toISOString();
|
|
40
|
+
if (typeof value === "string") {
|
|
41
|
+
const parsed = new Date(value);
|
|
42
|
+
if (!Number.isNaN(parsed.getTime())) return parsed.toISOString();
|
|
43
|
+
}
|
|
44
|
+
return fallback.toISOString();
|
|
45
|
+
}
|
|
46
|
+
function buildExpiredPayload(row, scope, clock) {
|
|
47
|
+
const resolvedAtIso = toIso(row.resolvedAt ?? clock, clock);
|
|
48
|
+
const expiresAtIso = toIso(row.expiresAt ?? clock, clock);
|
|
49
|
+
return {
|
|
50
|
+
pendingActionId: row.id,
|
|
51
|
+
agentId: row.agentId,
|
|
52
|
+
toolName: row.toolName,
|
|
53
|
+
status: row.status,
|
|
54
|
+
tenantId: scope.tenantId,
|
|
55
|
+
organizationId: scope.organizationId ?? null,
|
|
56
|
+
userId: row.createdByUserId ?? null,
|
|
57
|
+
resolvedByUserId: null,
|
|
58
|
+
resolvedAt: resolvedAtIso,
|
|
59
|
+
expiresAt: expiresAtIso,
|
|
60
|
+
expiredAt: resolvedAtIso
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async function runPendingActionCleanup(options) {
|
|
64
|
+
const clock = options.now ?? /* @__PURE__ */ new Date();
|
|
65
|
+
const repo = options.repo ?? new AiPendingActionRepository(options.em);
|
|
66
|
+
const emitter = options.emitEvent ?? defaultEmitter;
|
|
67
|
+
const pageSize = Math.max(1, Math.min(500, options.pageSize ?? DEFAULT_PAGE_SIZE));
|
|
68
|
+
const discoverTenants = options.discoverTenants ?? discoverTenantsDefault;
|
|
69
|
+
const summary = {
|
|
70
|
+
tenantsScanned: 0,
|
|
71
|
+
rowsProcessed: 0,
|
|
72
|
+
rowsExpired: 0,
|
|
73
|
+
rowsSkipped: 0,
|
|
74
|
+
rowsErrored: 0
|
|
75
|
+
};
|
|
76
|
+
let tenants = [];
|
|
77
|
+
try {
|
|
78
|
+
tenants = await discoverTenants(options.em, clock);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error(
|
|
81
|
+
"[ai-pending-action-cleanup] Failed to discover tenants:",
|
|
82
|
+
error
|
|
83
|
+
);
|
|
84
|
+
return summary;
|
|
85
|
+
}
|
|
86
|
+
if (!tenants.length) return summary;
|
|
87
|
+
for (const scope of tenants) {
|
|
88
|
+
summary.tenantsScanned += 1;
|
|
89
|
+
for (let page = 0; page < MAX_PAGES_PER_TENANT; page += 1) {
|
|
90
|
+
let expiredRows;
|
|
91
|
+
try {
|
|
92
|
+
expiredRows = await repo.listExpired(
|
|
93
|
+
{
|
|
94
|
+
tenantId: scope.tenantId,
|
|
95
|
+
organizationId: scope.organizationId,
|
|
96
|
+
userId: null
|
|
97
|
+
},
|
|
98
|
+
clock,
|
|
99
|
+
pageSize
|
|
100
|
+
);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error(
|
|
103
|
+
`[ai-pending-action-cleanup] listExpired failed for tenant ${scope.tenantId}:`,
|
|
104
|
+
error
|
|
105
|
+
);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
if (!expiredRows.length) break;
|
|
109
|
+
for (const row of expiredRows) {
|
|
110
|
+
summary.rowsProcessed += 1;
|
|
111
|
+
try {
|
|
112
|
+
const updated = await repo.setStatus(
|
|
113
|
+
row.id,
|
|
114
|
+
"expired",
|
|
115
|
+
{
|
|
116
|
+
tenantId: scope.tenantId,
|
|
117
|
+
organizationId: scope.organizationId,
|
|
118
|
+
userId: null
|
|
119
|
+
},
|
|
120
|
+
{ resolvedByUserId: null, now: clock }
|
|
121
|
+
);
|
|
122
|
+
summary.rowsExpired += 1;
|
|
123
|
+
const payload = buildExpiredPayload(updated, scope, clock);
|
|
124
|
+
try {
|
|
125
|
+
await emitter("ai.action.expired", payload);
|
|
126
|
+
} catch (emitError) {
|
|
127
|
+
console.warn(
|
|
128
|
+
`[ai-pending-action-cleanup] Failed to emit ai.action.expired for ${row.id}:`,
|
|
129
|
+
emitError
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (error instanceof AiPendingActionStateError) {
|
|
134
|
+
summary.rowsSkipped += 1;
|
|
135
|
+
console.info(
|
|
136
|
+
`[ai-pending-action-cleanup] Skipping ${row.id}: concurrent transition ${error.from} \u2192 ${error.to} already occurred`
|
|
137
|
+
);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
summary.rowsErrored += 1;
|
|
141
|
+
console.error(
|
|
142
|
+
`[ai-pending-action-cleanup] Failed to expire ${row.id}:`,
|
|
143
|
+
error
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (expiredRows.length < pageSize) break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return summary;
|
|
151
|
+
}
|
|
152
|
+
async function handle(_job, ctx) {
|
|
153
|
+
const em = ctx.resolve("em");
|
|
154
|
+
await runPendingActionCleanup({ em });
|
|
155
|
+
}
|
|
156
|
+
export {
|
|
157
|
+
handle as default,
|
|
158
|
+
metadata,
|
|
159
|
+
runPendingActionCleanup
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=ai-pending-action-cleanup.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/ai_assistant/workers/ai-pending-action-cleanup.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport { AiPendingActionRepository } from '../data/repositories/AiPendingActionRepository'\nimport type { AiPendingAction } from '../data/entities'\nimport {\n emitAiAssistantEvent,\n type AiActionExpiredPayload,\n type AiAssistantEventId,\n} from '../events'\nimport { AiPendingActionStateError } from '../lib/pending-action-types'\n\n/**\n * Periodic cleanup worker for the Phase 3 WS-C mutation approval gate\n * (Step 5.12).\n *\n * Responsibilities:\n * - Sweep every tenant for rows where `status = 'pending'` AND\n * `expires_at < now`. Pending actions expire after\n * `AI_PENDING_ACTION_TTL_SECONDS` (default 15 minutes) \u2014 confirm/cancel\n * routes flip them opportunistically, but rows nobody touches again\n * would otherwise sit in `pending` forever.\n * - Atomically transition each expired row `pending \u2192 expired` via the\n * repository's state-machine guard. `resolvedByUserId` is `null`\n * because the worker (not a user) is the actor; `resolvedAt` is `now`.\n * - Emit the typed `ai.action.expired` event via\n * {@link emitAiAssistantEvent} for each successful transition so\n * downstream subscribers (UI, audit, metrics) see a single canonical\n * terminal signal.\n *\n * Race safety:\n * - `AiPendingActionRepository.setStatus` enforces the state machine\n * from `pending-action-types.ts`; the legal exits for `pending` are\n * `confirmed`, `cancelled`, `expired`. If a concurrent confirm raced\n * us and flipped the row to `confirmed` (or `executing`), the repo\n * throws {@link AiPendingActionStateError} \u2014 we catch, log, and skip,\n * WITHOUT emitting an event for that row (the confirm path already\n * emitted the canonical signal). Same behaviour if the cancel helper\n * beat us via its TTL short-circuit.\n * - Single-row failures NEVER abort the batch \u2014 the worker logs and\n * continues to the next row.\n * - Running the worker twice on an already-`expired` row is a no-op:\n * `setStatus(expired)` short-circuits on `existing.status === nextStatus`\n * (see repo), so no second emit.\n *\n * Tenant scoping:\n * - `listExpired` is tenant-scoped, so the worker first discovers the\n * distinct set of `tenant_id` values that have expired pending rows\n * via a narrow native SELECT (no row contents read). It then iterates\n * per tenant, reusing the repo and therefore the encrypted-read\n * contract. Each `setStatus` write carries the row's own tenant\n * scope \u2014 there is no cross-tenant write.\n *\n * Pagination:\n * - `listExpired` is called with a bounded page size and looped until\n * the tenant's expired queue drains. A per-tenant loop cap prevents\n * runaway behaviour if new rows keep expiring during the sweep (the\n * next scheduled tick picks up any leftovers).\n */\n\nexport const metadata: WorkerMeta = {\n queue: 'ai-pending-action-cleanup',\n id: 'ai_assistant:cleanup-expired-pending-actions',\n concurrency: 1,\n}\n\nconst DEFAULT_PAGE_SIZE = 100\nconst MAX_PAGES_PER_TENANT = 50\n\nexport type PendingActionCleanupEmitter = (\n eventId: Extract<AiAssistantEventId, 'ai.action.expired'>,\n payload: AiActionExpiredPayload,\n) => Promise<void>\n\nconst defaultEmitter: PendingActionCleanupEmitter = async (eventId, payload) => {\n await emitAiAssistantEvent(eventId, payload as unknown as Record<string, unknown>, {\n persistent: true,\n })\n}\n\nexport interface PendingActionCleanupRunOptions {\n em: EntityManager\n repo?: AiPendingActionRepository\n emitEvent?: PendingActionCleanupEmitter\n now?: Date\n pageSize?: number\n /** Injectable tenant-discovery seam for unit tests. */\n discoverTenants?: (em: EntityManager, now: Date) => Promise<TenantScope[]>\n}\n\nexport interface PendingActionCleanupSummary {\n tenantsScanned: number\n rowsProcessed: number\n rowsExpired: number\n rowsSkipped: number\n rowsErrored: number\n}\n\nexport interface TenantScope {\n tenantId: string\n organizationId: string | null\n}\n\nasync function discoverTenantsDefault(\n em: EntityManager,\n now: Date,\n): Promise<TenantScope[]> {\n const connection = em.getConnection()\n const rows = await connection.execute(\n `select distinct \"tenant_id\", \"organization_id\"\n from \"ai_pending_actions\"\n where \"status\" = 'pending'\n and \"expires_at\" < ?`,\n [now],\n 'all',\n )\n if (!Array.isArray(rows)) return []\n const out: TenantScope[] = []\n for (const row of rows as Array<Record<string, unknown>>) {\n const tenantId = typeof row.tenant_id === 'string' ? row.tenant_id : null\n if (!tenantId) continue\n const organizationId =\n typeof row.organization_id === 'string' ? row.organization_id : null\n out.push({ tenantId, organizationId })\n }\n return out\n}\n\nfunction toIso(value: Date | string | null | undefined, fallback: Date): string {\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'string') {\n const parsed = new Date(value)\n if (!Number.isNaN(parsed.getTime())) return parsed.toISOString()\n }\n return fallback.toISOString()\n}\n\nfunction buildExpiredPayload(\n row: AiPendingAction,\n scope: TenantScope,\n clock: Date,\n): AiActionExpiredPayload {\n const resolvedAtIso = toIso(row.resolvedAt ?? clock, clock)\n const expiresAtIso = toIso(row.expiresAt ?? clock, clock)\n return {\n pendingActionId: row.id,\n agentId: row.agentId,\n toolName: row.toolName,\n status: row.status,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId ?? null,\n userId: row.createdByUserId ?? null,\n resolvedByUserId: null,\n resolvedAt: resolvedAtIso,\n expiresAt: expiresAtIso,\n expiredAt: resolvedAtIso,\n }\n}\n\nexport async function runPendingActionCleanup(\n options: PendingActionCleanupRunOptions,\n): Promise<PendingActionCleanupSummary> {\n const clock = options.now ?? new Date()\n const repo = options.repo ?? new AiPendingActionRepository(options.em)\n const emitter = options.emitEvent ?? defaultEmitter\n const pageSize = Math.max(1, Math.min(500, options.pageSize ?? DEFAULT_PAGE_SIZE))\n const discoverTenants = options.discoverTenants ?? discoverTenantsDefault\n\n const summary: PendingActionCleanupSummary = {\n tenantsScanned: 0,\n rowsProcessed: 0,\n rowsExpired: 0,\n rowsSkipped: 0,\n rowsErrored: 0,\n }\n\n let tenants: TenantScope[] = []\n try {\n tenants = await discoverTenants(options.em, clock)\n } catch (error) {\n console.error(\n '[ai-pending-action-cleanup] Failed to discover tenants:',\n error,\n )\n return summary\n }\n\n if (!tenants.length) return summary\n\n for (const scope of tenants) {\n summary.tenantsScanned += 1\n for (let page = 0; page < MAX_PAGES_PER_TENANT; page += 1) {\n let expiredRows: AiPendingAction[]\n try {\n expiredRows = await repo.listExpired(\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: null,\n },\n clock,\n pageSize,\n )\n } catch (error) {\n console.error(\n `[ai-pending-action-cleanup] listExpired failed for tenant ${scope.tenantId}:`,\n error,\n )\n break\n }\n\n if (!expiredRows.length) break\n\n for (const row of expiredRows) {\n summary.rowsProcessed += 1\n try {\n const updated = await repo.setStatus(\n row.id,\n 'expired',\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: null,\n },\n { resolvedByUserId: null, now: clock },\n )\n summary.rowsExpired += 1\n const payload = buildExpiredPayload(updated, scope, clock)\n try {\n await emitter('ai.action.expired', payload)\n } catch (emitError) {\n console.warn(\n `[ai-pending-action-cleanup] Failed to emit ai.action.expired for ${row.id}:`,\n emitError,\n )\n }\n } catch (error) {\n if (error instanceof AiPendingActionStateError) {\n summary.rowsSkipped += 1\n console.info(\n `[ai-pending-action-cleanup] Skipping ${row.id}: concurrent transition ${error.from} \u2192 ${error.to} already occurred`,\n )\n continue\n }\n summary.rowsErrored += 1\n console.error(\n `[ai-pending-action-cleanup] Failed to expire ${row.id}:`,\n error,\n )\n }\n }\n\n if (expiredRows.length < pageSize) break\n }\n }\n\n return summary\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport default async function handle(\n _job: QueuedJob,\n ctx: HandlerContext,\n): Promise<void> {\n const em = ctx.resolve<EntityManager>('em')\n await runPendingActionCleanup({ em })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const id = "id";
|
|
2
|
+
export const tenant_id = "tenant_id";
|
|
3
|
+
export const organization_id = "organization_id";
|
|
4
|
+
export const agent_id = "agent_id";
|
|
5
|
+
export const mutation_policy = "mutation_policy";
|
|
6
|
+
export const notes = "notes";
|
|
7
|
+
export const created_by_user_id = "created_by_user_id";
|
|
8
|
+
export const created_at = "created_at";
|
|
9
|
+
export const updated_at = "updated_at";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const id = "id";
|
|
2
|
+
export const tenant_id = "tenant_id";
|
|
3
|
+
export const organization_id = "organization_id";
|
|
4
|
+
export const agent_id = "agent_id";
|
|
5
|
+
export const version = "version";
|
|
6
|
+
export const sections = "sections";
|
|
7
|
+
export const notes = "notes";
|
|
8
|
+
export const created_by_user_id = "created_by_user_id";
|
|
9
|
+
export const created_at = "created_at";
|
|
10
|
+
export const updated_at = "updated_at";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const id = "id";
|
|
2
|
+
export const tenant_id = "tenant_id";
|
|
3
|
+
export const organization_id = "organization_id";
|
|
4
|
+
export const agent_id = "agent_id";
|
|
5
|
+
export const tool_name = "tool_name";
|
|
6
|
+
export const conversation_id = "conversation_id";
|
|
7
|
+
export const target_entity_type = "target_entity_type";
|
|
8
|
+
export const target_record_id = "target_record_id";
|
|
9
|
+
export const normalized_input = "normalized_input";
|
|
10
|
+
export const field_diff = "field_diff";
|
|
11
|
+
export const records = "records";
|
|
12
|
+
export const failed_records = "failed_records";
|
|
13
|
+
export const side_effects_summary = "side_effects_summary";
|
|
14
|
+
export const record_version = "record_version";
|
|
15
|
+
export const attachment_ids = "attachment_ids";
|
|
16
|
+
export const idempotency_key = "idempotency_key";
|
|
17
|
+
export const created_by_user_id = "created_by_user_id";
|
|
18
|
+
export const status = "status";
|
|
19
|
+
export const queue_mode = "queue_mode";
|
|
20
|
+
export const execution_result = "execution_result";
|
|
21
|
+
export const created_at = "created_at";
|
|
22
|
+
export const expires_at = "expires_at";
|
|
23
|
+
export const resolved_at = "resolved_at";
|
|
24
|
+
export const resolved_by_user_id = "resolved_by_user_id";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// AUTO-GENERATED by mercato generate entity-ids
|
|
2
|
+
export const M = {
|
|
3
|
+
"ai_assistant": "ai_assistant"
|
|
4
|
+
} as const, E = {
|
|
5
|
+
"ai_assistant": {
|
|
6
|
+
"ai_agent_prompt_override": "ai_assistant:ai_agent_prompt_override",
|
|
7
|
+
"ai_pending_action": "ai_assistant:ai_pending_action",
|
|
8
|
+
"ai_agent_mutation_policy_override": "ai_assistant:ai_agent_mutation_policy_override"
|
|
9
|
+
}
|
|
10
|
+
} as const;
|
|
11
|
+
|
|
12
|
+
export type KnownModuleId = keyof typeof M;
|
|
13
|
+
export type KnownEntities = typeof E;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// AUTO-GENERATED by mercato generate entity-ids
|
|
2
|
+
// Static registry for entity fields - eliminates dynamic imports for Turbopack compatibility
|
|
3
|
+
export const entityFieldsRegistry: Record<string, Record<string, string>> = {
|
|
4
|
+
"ai_agent_mutation_policy_override": {
|
|
5
|
+
"id": "id",
|
|
6
|
+
"tenant_id": "tenant_id",
|
|
7
|
+
"organization_id": "organization_id",
|
|
8
|
+
"agent_id": "agent_id",
|
|
9
|
+
"mutation_policy": "mutation_policy",
|
|
10
|
+
"notes": "notes",
|
|
11
|
+
"created_by_user_id": "created_by_user_id",
|
|
12
|
+
"created_at": "created_at",
|
|
13
|
+
"updated_at": "updated_at"
|
|
14
|
+
},
|
|
15
|
+
"ai_agent_prompt_override": {
|
|
16
|
+
"id": "id",
|
|
17
|
+
"tenant_id": "tenant_id",
|
|
18
|
+
"organization_id": "organization_id",
|
|
19
|
+
"agent_id": "agent_id",
|
|
20
|
+
"version": "version",
|
|
21
|
+
"sections": "sections",
|
|
22
|
+
"notes": "notes",
|
|
23
|
+
"created_by_user_id": "created_by_user_id",
|
|
24
|
+
"created_at": "created_at",
|
|
25
|
+
"updated_at": "updated_at"
|
|
26
|
+
},
|
|
27
|
+
"ai_pending_action": {
|
|
28
|
+
"id": "id",
|
|
29
|
+
"tenant_id": "tenant_id",
|
|
30
|
+
"organization_id": "organization_id",
|
|
31
|
+
"agent_id": "agent_id",
|
|
32
|
+
"tool_name": "tool_name",
|
|
33
|
+
"conversation_id": "conversation_id",
|
|
34
|
+
"target_entity_type": "target_entity_type",
|
|
35
|
+
"target_record_id": "target_record_id",
|
|
36
|
+
"normalized_input": "normalized_input",
|
|
37
|
+
"field_diff": "field_diff",
|
|
38
|
+
"records": "records",
|
|
39
|
+
"failed_records": "failed_records",
|
|
40
|
+
"side_effects_summary": "side_effects_summary",
|
|
41
|
+
"record_version": "record_version",
|
|
42
|
+
"attachment_ids": "attachment_ids",
|
|
43
|
+
"idempotency_key": "idempotency_key",
|
|
44
|
+
"created_by_user_id": "created_by_user_id",
|
|
45
|
+
"status": "status",
|
|
46
|
+
"queue_mode": "queue_mode",
|
|
47
|
+
"execution_result": "execution_result",
|
|
48
|
+
"created_at": "created_at",
|
|
49
|
+
"expires_at": "expires_at",
|
|
50
|
+
"resolved_at": "resolved_at",
|
|
51
|
+
"resolved_by_user_id": "resolved_by_user_id"
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function getEntityFields(slug: string): Record<string, string> | undefined {
|
|
56
|
+
return entityFieldsRegistry[slug];
|
|
57
|
+
}
|
package/jest.config.cjs
CHANGED
|
@@ -3,10 +3,17 @@ module.exports = {
|
|
|
3
3
|
testEnvironment: 'node',
|
|
4
4
|
watchman: false,
|
|
5
5
|
rootDir: '.',
|
|
6
|
+
maxWorkers: 4,
|
|
6
7
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
|
7
8
|
moduleNameMapper: {
|
|
8
9
|
'^@open-mercato/ai-assistant/(.*)$': '<rootDir>/src/$1',
|
|
9
10
|
'^@open-mercato/shared/(.*)$': '<rootDir>/../shared/src/$1',
|
|
11
|
+
// Redirect core module imports to the TS source so Jest's ts-jest
|
|
12
|
+
// transformer handles them cleanly. Without this, the built dist/
|
|
13
|
+
// ESM output trips Jest's CJS-only parser (see
|
|
14
|
+
// pending-action-recheck.ts importing `@open-mercato/core/modules/
|
|
15
|
+
// attachments/data/entities` after Step 5.8).
|
|
16
|
+
'^@open-mercato/core/(.*)$': '<rootDir>/../core/src/$1',
|
|
10
17
|
},
|
|
11
18
|
transform: {
|
|
12
19
|
'^.+\\.(t|j)sx?$': [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/ai-assistant",
|
|
3
|
-
"version": "0.5.1-develop.
|
|
3
|
+
"version": "0.5.1-develop.3045.b4b3320cc2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -98,12 +98,12 @@
|
|
|
98
98
|
"zod-to-json-schema": "^3.25.2"
|
|
99
99
|
},
|
|
100
100
|
"peerDependencies": {
|
|
101
|
-
"@open-mercato/shared": "0.5.1-develop.
|
|
102
|
-
"@open-mercato/ui": "0.5.1-develop.
|
|
101
|
+
"@open-mercato/shared": "0.5.1-develop.3045.b4b3320cc2",
|
|
102
|
+
"@open-mercato/ui": "0.5.1-develop.3045.b4b3320cc2",
|
|
103
103
|
"zod": ">=3.23.0"
|
|
104
104
|
},
|
|
105
105
|
"devDependencies": {
|
|
106
|
-
"@open-mercato/cli": "0.5.1-develop.
|
|
106
|
+
"@open-mercato/cli": "0.5.1-develop.3045.b4b3320cc2",
|
|
107
107
|
"tsx": "^4.21.0"
|
|
108
108
|
},
|
|
109
109
|
"publishConfig": {
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,41 @@
|
|
|
29
29
|
// Re-export types
|
|
30
30
|
export * from './modules/ai_assistant/lib/types'
|
|
31
31
|
|
|
32
|
+
// Focused-agent definition types + helper
|
|
33
|
+
export {
|
|
34
|
+
defineAiAgent,
|
|
35
|
+
defineAiAgentExtension,
|
|
36
|
+
type AiAgentDefinition,
|
|
37
|
+
type AiAgentExtension,
|
|
38
|
+
type AiAgentSuggestion,
|
|
39
|
+
type AiAgentExecutionMode,
|
|
40
|
+
type AiAgentMutationPolicy,
|
|
41
|
+
type AiAgentAcceptedMediaType,
|
|
42
|
+
type AiAgentDataOperation,
|
|
43
|
+
type AiAgentPageContextInput,
|
|
44
|
+
type AiAgentStructuredOutput,
|
|
45
|
+
type AiAgentDataCapabilities,
|
|
46
|
+
} from './modules/ai_assistant/lib/ai-agent-definition'
|
|
47
|
+
|
|
48
|
+
// Additive AI tool builder
|
|
49
|
+
export { defineAiTool } from './modules/ai_assistant/lib/ai-tool-definition'
|
|
50
|
+
|
|
51
|
+
// Attachment-bridge contract types (spec Phase 0 §8/§10, implementation-ready for Phase 3 runtime)
|
|
52
|
+
export {
|
|
53
|
+
type AttachmentSource,
|
|
54
|
+
type AiResolvedAttachmentPart,
|
|
55
|
+
type AiUiPart,
|
|
56
|
+
type AiChatRequestContext,
|
|
57
|
+
} from './modules/ai_assistant/lib/attachment-bridge-types'
|
|
58
|
+
|
|
59
|
+
// Prompt-composition primitives (spec Phase 0 §8, implementation-ready for Phase 3 prompt composer)
|
|
60
|
+
export {
|
|
61
|
+
definePromptTemplate,
|
|
62
|
+
type PromptSectionName,
|
|
63
|
+
type PromptSection,
|
|
64
|
+
type PromptTemplate,
|
|
65
|
+
} from './modules/ai_assistant/lib/prompt-composition-types'
|
|
66
|
+
|
|
32
67
|
// Tool registry
|
|
33
68
|
export {
|
|
34
69
|
registerMcpTool,
|
|
@@ -58,6 +93,186 @@ export {
|
|
|
58
93
|
// Tool loader
|
|
59
94
|
export { loadAllModuleTools, indexToolsForSearch } from './modules/ai_assistant/lib/tool-loader'
|
|
60
95
|
|
|
96
|
+
// AI Overrides — module-to-module + modules.ts + programmatic agent/tool replacement.
|
|
97
|
+
// See `apps/docs/docs/framework/ai-assistant/overrides.mdx`.
|
|
98
|
+
export {
|
|
99
|
+
applyAiAgentOverrides,
|
|
100
|
+
applyAiAgentExtensions,
|
|
101
|
+
applyAiToolOverrides,
|
|
102
|
+
applyAiOverridesFromEnabledModules,
|
|
103
|
+
resetProgrammaticOverridesForTests,
|
|
104
|
+
type AiAgentOverride,
|
|
105
|
+
type AiToolOverride,
|
|
106
|
+
type AiAgentOverridesMap,
|
|
107
|
+
type AiToolOverridesMap,
|
|
108
|
+
type AiAgentOverrideConfigEntry,
|
|
109
|
+
type AiAgentExtensionConfigEntry,
|
|
110
|
+
type AiToolOverrideConfigEntry,
|
|
111
|
+
type EnabledModuleAiOverrides,
|
|
112
|
+
} from './modules/ai_assistant/lib/ai-overrides'
|
|
113
|
+
|
|
114
|
+
// Agent registry (Phase 1 WS-A — read-side lookup API, no policy / dispatch)
|
|
115
|
+
export {
|
|
116
|
+
loadAgentRegistry,
|
|
117
|
+
getAgent,
|
|
118
|
+
listAgents,
|
|
119
|
+
listAgentsByModule,
|
|
120
|
+
resetAgentRegistryForTests,
|
|
121
|
+
} from './modules/ai_assistant/lib/agent-registry'
|
|
122
|
+
|
|
123
|
+
// Agent runtime policy gate (Phase 1 WS-A — pure policy decisions, no HTTP or AI SDK wiring)
|
|
124
|
+
export {
|
|
125
|
+
checkAgentPolicy,
|
|
126
|
+
type AgentPolicyDenyCode,
|
|
127
|
+
type AgentPolicyDecision,
|
|
128
|
+
type AgentPolicyAuthContext,
|
|
129
|
+
type AgentPolicyCheckInput,
|
|
130
|
+
} from './modules/ai_assistant/lib/agent-policy'
|
|
131
|
+
|
|
132
|
+
// AI SDK helpers (Phase 1 WS-B — chat-mode runtime + transport glue)
|
|
133
|
+
export {
|
|
134
|
+
resolveAiAgentTools,
|
|
135
|
+
AgentPolicyError,
|
|
136
|
+
type ResolveAiAgentToolsInput,
|
|
137
|
+
type ResolvedAgentTools,
|
|
138
|
+
type AiUiPartQueue,
|
|
139
|
+
} from './modules/ai_assistant/lib/agent-tools'
|
|
140
|
+
|
|
141
|
+
// In-process API operation runner (Phase 1 of API-backed AI tool DRY refactor)
|
|
142
|
+
export {
|
|
143
|
+
createAiApiOperationRunner,
|
|
144
|
+
type AiApiOperationRequest,
|
|
145
|
+
type AiApiOperationResponse,
|
|
146
|
+
type AiApiOperationRunner,
|
|
147
|
+
type AiApiOperationRunnerOptions,
|
|
148
|
+
type AiApiHttpMethod,
|
|
149
|
+
type AiToolExecutionContext,
|
|
150
|
+
} from './modules/ai_assistant/lib/ai-api-operation-runner'
|
|
151
|
+
|
|
152
|
+
// API-backed AI tool helper (Phase 2 of API-backed AI tool DRY refactor)
|
|
153
|
+
export {
|
|
154
|
+
defineApiBackedAiTool,
|
|
155
|
+
type ApiBackedAiToolConfig,
|
|
156
|
+
} from './modules/ai_assistant/lib/api-backed-tool'
|
|
157
|
+
|
|
158
|
+
// Mutation-preparation helper (Phase 3 WS-C — Step 5.6)
|
|
159
|
+
export {
|
|
160
|
+
prepareMutation,
|
|
161
|
+
computeMutationIdempotencyKey,
|
|
162
|
+
AiMutationPreparationError,
|
|
163
|
+
MUTATION_PREVIEW_CARD_COMPONENT,
|
|
164
|
+
type PrepareMutationInput,
|
|
165
|
+
type PrepareMutationContext,
|
|
166
|
+
type PrepareMutationResult,
|
|
167
|
+
} from './modules/ai_assistant/lib/prepare-mutation'
|
|
168
|
+
|
|
169
|
+
export {
|
|
170
|
+
runAiAgentText,
|
|
171
|
+
runAiAgentObject,
|
|
172
|
+
composeSystemPrompt,
|
|
173
|
+
type RunAiAgentTextInput,
|
|
174
|
+
type RunAiAgentObjectInput,
|
|
175
|
+
type RunAiAgentObjectOutputOverride,
|
|
176
|
+
type RunAiAgentObjectResult,
|
|
177
|
+
type RunAiAgentObjectGenerateResult,
|
|
178
|
+
type RunAiAgentObjectStreamResult,
|
|
179
|
+
type AgentRequestPageContext,
|
|
180
|
+
} from './modules/ai_assistant/lib/agent-runtime'
|
|
181
|
+
|
|
182
|
+
export {
|
|
183
|
+
createAiAgentTransport,
|
|
184
|
+
type CreateAiAgentTransportInput,
|
|
185
|
+
} from './modules/ai_assistant/lib/agent-transport'
|
|
186
|
+
|
|
187
|
+
// Pending-action types / enums / state-machine guard (Phase 3 WS-C — Step 5.5)
|
|
188
|
+
export {
|
|
189
|
+
AI_PENDING_ACTION_STATUSES,
|
|
190
|
+
AI_PENDING_ACTION_QUEUE_MODES,
|
|
191
|
+
AI_PENDING_ACTION_ALLOWED_TRANSITIONS,
|
|
192
|
+
AI_PENDING_ACTION_TERMINAL_STATUSES,
|
|
193
|
+
AI_PENDING_ACTION_DEFAULT_TTL_SECONDS,
|
|
194
|
+
AI_PENDING_ACTION_TTL_ENV_VAR,
|
|
195
|
+
AiPendingActionStateError,
|
|
196
|
+
isAiPendingActionStatus,
|
|
197
|
+
isAiPendingActionQueueMode,
|
|
198
|
+
isTerminalAiPendingActionStatus,
|
|
199
|
+
isAllowedAiPendingActionTransition,
|
|
200
|
+
resolveAiPendingActionTtlSeconds,
|
|
201
|
+
type AiPendingActionStatus,
|
|
202
|
+
type AiPendingActionQueueMode,
|
|
203
|
+
type AiPendingActionRecordDiff,
|
|
204
|
+
type AiPendingActionFailedRecord,
|
|
205
|
+
type AiPendingActionFieldDiff,
|
|
206
|
+
type AiPendingActionExecutionResult,
|
|
207
|
+
} from './modules/ai_assistant/lib/pending-action-types'
|
|
208
|
+
|
|
209
|
+
// Client-facing pending-action serializer (Phase 3 WS-C — Step 5.7, reused by 5.8 / 5.9 / 5.10)
|
|
210
|
+
export {
|
|
211
|
+
serializePendingActionForClient,
|
|
212
|
+
type SerializedPendingAction,
|
|
213
|
+
type SerializablePendingActionRow,
|
|
214
|
+
} from './modules/ai_assistant/lib/pending-action-client'
|
|
215
|
+
|
|
216
|
+
// Pending-action confirm re-check contract (Phase 3 WS-C — Step 5.8, reused by 5.9)
|
|
217
|
+
export {
|
|
218
|
+
runPendingActionRechecks,
|
|
219
|
+
checkStatusAndExpiry,
|
|
220
|
+
checkAgentAndFeatures,
|
|
221
|
+
checkToolWhitelist,
|
|
222
|
+
checkAttachmentScope,
|
|
223
|
+
checkRecordVersion,
|
|
224
|
+
PENDING_ACTION_RECHECK_CODES,
|
|
225
|
+
isPendingActionRecheckCode,
|
|
226
|
+
type PendingActionRecheckCode,
|
|
227
|
+
type PendingActionRecheckResult,
|
|
228
|
+
type PendingActionRecheckInput,
|
|
229
|
+
type PendingActionAuthContext,
|
|
230
|
+
} from './modules/ai_assistant/lib/pending-action-recheck'
|
|
231
|
+
|
|
232
|
+
// Pending-action confirm executor (Phase 3 WS-C — Step 5.8)
|
|
233
|
+
export {
|
|
234
|
+
executePendingActionConfirm,
|
|
235
|
+
PENDING_ACTION_CONFIRMED_EVENT_ID,
|
|
236
|
+
type PendingActionExecuteInput,
|
|
237
|
+
type PendingActionExecuteContext,
|
|
238
|
+
type PendingActionExecuteResult,
|
|
239
|
+
type PendingActionExecuteOk,
|
|
240
|
+
type PendingActionExecuteFail,
|
|
241
|
+
} from './modules/ai_assistant/lib/pending-action-executor'
|
|
242
|
+
|
|
243
|
+
// Pending-action cancel executor (Phase 3 WS-C — Step 5.9)
|
|
244
|
+
export {
|
|
245
|
+
executePendingActionCancel,
|
|
246
|
+
PENDING_ACTION_CANCELLED_EVENT_ID,
|
|
247
|
+
PENDING_ACTION_EXPIRED_EVENT_ID,
|
|
248
|
+
type PendingActionCancelInput,
|
|
249
|
+
type PendingActionCancelContext,
|
|
250
|
+
type PendingActionCancelResult,
|
|
251
|
+
type PendingActionCancelStatus,
|
|
252
|
+
} from './modules/ai_assistant/lib/pending-action-cancel'
|
|
253
|
+
|
|
254
|
+
// Shared AI model factory (Phase 3 WS-A — Step 5.1)
|
|
255
|
+
export {
|
|
256
|
+
createModelFactory,
|
|
257
|
+
AiModelFactoryError,
|
|
258
|
+
type AiModelFactory,
|
|
259
|
+
type AiModelFactoryInput,
|
|
260
|
+
type AiModelResolution,
|
|
261
|
+
type AiModelFactoryErrorCode,
|
|
262
|
+
type AiModelInstance,
|
|
263
|
+
type CreateModelFactoryDependencies,
|
|
264
|
+
} from './modules/ai_assistant/lib/model-factory'
|
|
265
|
+
|
|
266
|
+
// Attachment-to-model bridge (Phase 1 WS-C — Step 3.7)
|
|
267
|
+
export {
|
|
268
|
+
resolveAttachmentParts,
|
|
269
|
+
resolveAttachmentPartsForAgent,
|
|
270
|
+
attachmentPartsToUiFileParts,
|
|
271
|
+
summarizeAttachmentPartsForPrompt,
|
|
272
|
+
type ResolveAttachmentPartsInput,
|
|
273
|
+
type AttachmentSigner,
|
|
274
|
+
} from './modules/ai_assistant/lib/attachment-parts'
|
|
275
|
+
|
|
61
276
|
// OpenCode client
|
|
62
277
|
export {
|
|
63
278
|
OpenCodeClient,
|