@endora-commerce/mod-prompt-actions 0.0.0-stage → 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -2
  3. package/dist/backend/entities/prompt-action-request.entity.d.ts +37 -0
  4. package/dist/backend/entities/prompt-action-request.entity.d.ts.map +1 -0
  5. package/dist/backend/entities/prompt-action-request.entity.js +130 -0
  6. package/dist/backend/entities/prompt-action-request.entity.js.map +1 -0
  7. package/dist/backend/index.d.ts +94 -0
  8. package/dist/backend/index.d.ts.map +1 -0
  9. package/dist/backend/index.js +127 -0
  10. package/dist/backend/index.js.map +1 -0
  11. package/dist/backend/routes.admin.d.ts +30 -0
  12. package/dist/backend/routes.admin.d.ts.map +1 -0
  13. package/dist/backend/routes.admin.js +71 -0
  14. package/dist/backend/routes.admin.js.map +1 -0
  15. package/dist/backend/services/bulk-progress-registry.d.ts +82 -0
  16. package/dist/backend/services/bulk-progress-registry.d.ts.map +1 -0
  17. package/dist/backend/services/bulk-progress-registry.js +44 -0
  18. package/dist/backend/services/bulk-progress-registry.js.map +1 -0
  19. package/dist/backend/services/interpreter.service.d.ts +59 -0
  20. package/dist/backend/services/interpreter.service.d.ts.map +1 -0
  21. package/dist/backend/services/interpreter.service.js +270 -0
  22. package/dist/backend/services/interpreter.service.js.map +1 -0
  23. package/dist/backend/services/llm/anthropic-adapter.d.ts +9 -0
  24. package/dist/backend/services/llm/anthropic-adapter.d.ts.map +1 -0
  25. package/dist/backend/services/llm/anthropic-adapter.js +83 -0
  26. package/dist/backend/services/llm/anthropic-adapter.js.map +1 -0
  27. package/dist/backend/services/llm/google-adapter.d.ts +9 -0
  28. package/dist/backend/services/llm/google-adapter.d.ts.map +1 -0
  29. package/dist/backend/services/llm/google-adapter.js +125 -0
  30. package/dist/backend/services/llm/google-adapter.js.map +1 -0
  31. package/dist/backend/services/llm/openai-adapter.d.ts +9 -0
  32. package/dist/backend/services/llm/openai-adapter.d.ts.map +1 -0
  33. package/dist/backend/services/llm/openai-adapter.js +95 -0
  34. package/dist/backend/services/llm/openai-adapter.js.map +1 -0
  35. package/dist/backend/services/llm/provider-factory.d.ts +60 -0
  36. package/dist/backend/services/llm/provider-factory.d.ts.map +1 -0
  37. package/dist/backend/services/llm/provider-factory.js +111 -0
  38. package/dist/backend/services/llm/provider-factory.js.map +1 -0
  39. package/dist/backend/services/llm/provider.d.ts +63 -0
  40. package/dist/backend/services/llm/provider.d.ts.map +1 -0
  41. package/dist/backend/services/llm/provider.js +67 -0
  42. package/dist/backend/services/llm/provider.js.map +1 -0
  43. package/dist/backend/services/plan-executor.service.d.ts +49 -0
  44. package/dist/backend/services/plan-executor.service.d.ts.map +1 -0
  45. package/dist/backend/services/plan-executor.service.js +132 -0
  46. package/dist/backend/services/plan-executor.service.js.map +1 -0
  47. package/dist/backend/services/prompt-request.service.d.ts +84 -0
  48. package/dist/backend/services/prompt-request.service.d.ts.map +1 -0
  49. package/dist/backend/services/prompt-request.service.js +338 -0
  50. package/dist/backend/services/prompt-request.service.js.map +1 -0
  51. package/dist/backend/services/tool-registry.d.ts +17 -0
  52. package/dist/backend/services/tool-registry.d.ts.map +1 -0
  53. package/dist/backend/services/tool-registry.js +89 -0
  54. package/dist/backend/services/tool-registry.js.map +1 -0
  55. package/dist/manifest.d.ts +252 -0
  56. package/dist/manifest.d.ts.map +1 -0
  57. package/dist/manifest.js +199 -0
  58. package/dist/manifest.js.map +1 -0
  59. package/dist/migrations/20260611T140410_prompt_actions_init.d.ts +17 -0
  60. package/dist/migrations/20260611T140410_prompt_actions_init.d.ts.map +1 -0
  61. package/dist/migrations/20260611T140410_prompt_actions_init.js +47 -0
  62. package/dist/migrations/20260611T140410_prompt_actions_init.js.map +1 -0
  63. package/dist/migrations/index.d.ts +27 -0
  64. package/dist/migrations/index.d.ts.map +1 -0
  65. package/dist/migrations/index.js +29 -0
  66. package/dist/migrations/index.js.map +1 -0
  67. package/docs/prompt-actions.md +117 -0
  68. package/i18n/en.json +40 -0
  69. package/i18n/pl.json +40 -0
  70. package/package.json +67 -3
@@ -0,0 +1,132 @@
1
+ /**
2
+ * PlanExecutorService — feature 043 US1/US2 (research §R6).
3
+ *
4
+ * Walks a confirmed plan with defense-in-depth re-validation: catalogue
5
+ * membership, Zod params, and the operator's LIVE permission are all checked
6
+ * again at execution time (a plan may be minutes old — FR-007). Execution
7
+ * delegates to the owning module's service through the tool handler; this
8
+ * module owns zero domain logic.
9
+ *
10
+ * Partial-failure semantics (FR-011): independent operations keep their
11
+ * outcome; one failure never rolls back a previously succeeded operation.
12
+ */
13
+ export class PermissionRevoked extends Error {
14
+ toolId;
15
+ permission;
16
+ name = 'PermissionRevoked';
17
+ code = 'PROMPT_PERMISSION_REVOKED';
18
+ constructor(toolId, permission) {
19
+ super(`Permission "${permission}" required by "${toolId}" is no longer held by the operator.`);
20
+ this.toolId = toolId;
21
+ this.permission = permission;
22
+ }
23
+ }
24
+ export function isDelegatedExecution(value) {
25
+ return (typeof value === 'object' &&
26
+ value !== null &&
27
+ value.delegated === true &&
28
+ typeof value.bulkOperationId === 'string');
29
+ }
30
+ function extractSummary(value) {
31
+ if (typeof value !== 'object' || value === null)
32
+ return null;
33
+ const summary = value.summary;
34
+ if (typeof summary !== 'object' || summary === null)
35
+ return null;
36
+ const s = summary;
37
+ if (typeof s.total !== 'number' ||
38
+ typeof s.succeeded !== 'number' ||
39
+ typeof s.failed !== 'number') {
40
+ return null;
41
+ }
42
+ return summary;
43
+ }
44
+ export class PlanExecutorService {
45
+ registry;
46
+ constructor(registry) {
47
+ this.registry = registry;
48
+ }
49
+ /**
50
+ * Executes every operation in the plan. Throws {@link PermissionRevoked}
51
+ * (the whole request becomes `refused`) when a live permission check
52
+ * fails BEFORE any operation has run; revocation discovered mid-plan is
53
+ * reported as a per-operation failure instead (already-applied work must
54
+ * stay applied — FR-011).
55
+ */
56
+ async execute(plan, toolCtx, visibility) {
57
+ // Up-front live permission sweep: refuse before side effects.
58
+ for (const op of plan.operations) {
59
+ const tool = this.registry.get(op.toolId);
60
+ if (tool && !(await visibility.hasPermission(tool.requiredPermission))) {
61
+ throw new PermissionRevoked(op.toolId, tool.requiredPermission);
62
+ }
63
+ }
64
+ const operations = [];
65
+ let bulkOperationId = null;
66
+ for (const op of plan.operations) {
67
+ const tool = this.registry.get(op.toolId);
68
+ if (!tool || tool.kind !== 'mutation') {
69
+ operations.push({
70
+ toolId: op.toolId,
71
+ status: 'failed',
72
+ message: 'Operation is no longer available on this platform.',
73
+ });
74
+ continue;
75
+ }
76
+ if (!(await visibility.isModuleInstalled(tool.moduleId))) {
77
+ operations.push({
78
+ toolId: op.toolId,
79
+ status: 'failed',
80
+ message: 'The owning module is disabled.',
81
+ });
82
+ continue;
83
+ }
84
+ const params = tool.paramsSchema.safeParse(op.params);
85
+ if (!params.success) {
86
+ operations.push({
87
+ toolId: op.toolId,
88
+ status: 'failed',
89
+ message: 'Stored plan parameters failed re-validation.',
90
+ });
91
+ continue;
92
+ }
93
+ try {
94
+ const value = await tool.execute(params.data, toolCtx);
95
+ if (isDelegatedExecution(value)) {
96
+ bulkOperationId = value.bulkOperationId;
97
+ operations.push({
98
+ toolId: op.toolId,
99
+ status: 'delegated',
100
+ bulkOperationId: value.bulkOperationId,
101
+ });
102
+ }
103
+ else {
104
+ // Bulk handlers report per-item outcomes (FR-011) via a `summary`
105
+ // payload; single-record handlers return plain data.
106
+ const summary = extractSummary(value);
107
+ operations.push({
108
+ toolId: op.toolId,
109
+ status: 'succeeded',
110
+ ...(summary ? { summary } : {}),
111
+ });
112
+ }
113
+ }
114
+ catch (err) {
115
+ operations.push({
116
+ toolId: op.toolId,
117
+ status: 'failed',
118
+ message: err.message ?? 'Execution failed.',
119
+ });
120
+ }
121
+ }
122
+ const failedOps = operations.filter((o) => o.status === 'failed').length;
123
+ const partialFailures = operations.reduce((n, o) => n + (o.summary?.failed ?? 0), 0);
124
+ const outcome = failedOps === operations.length && operations.length > 0
125
+ ? 'failed'
126
+ : failedOps === 0 && partialFailures === 0
127
+ ? 'completed'
128
+ : 'completed_with_errors';
129
+ return { result: { outcome, operations }, bulkOperationId };
130
+ }
131
+ }
132
+ //# sourceMappingURL=plan-executor.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-executor.service.js","sourceRoot":"","sources":["../../../src/backend/services/plan-executor.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import { type BulkProgressSnapshot, type ToolAuditContext } from '@endora-commerce/contracts';
3
+ import type { AuditPort } from '@endora-commerce/platform/kernel';
4
+ import { PromptActionRequest } from '../entities/prompt-action-request.entity.js';
5
+ import type { InterpreterService } from './interpreter.service.js';
6
+ import { type PlanExecutorService } from './plan-executor.service.js';
7
+ /**
8
+ * PromptRequestService — feature 043 lifecycle (data-model §2).
9
+ *
10
+ * Owns the `prompt_action_requests` state machine: submit (interpretation in
11
+ * the request path), idempotent confirm with lazy 10-minute expiry, cancel,
12
+ * the single clarify round-trip, owner-scoped reads, and the seen-marker
13
+ * queries behind the FR-018 completion notice. All state-changing audit rows
14
+ * (`prompt_action.execute`, `prompt_action.refused`) are recorded here.
15
+ */
16
+ export interface OperatorVisibilityFactory {
17
+ (adminUserId: string): {
18
+ hasPermission(permission: string): Promise<boolean>;
19
+ isModuleInstalled(moduleId: string): Promise<boolean>;
20
+ };
21
+ }
22
+ export interface PromptRequestServiceDeps {
23
+ emFactory: () => EntityManager;
24
+ interpreter: InterpreterService;
25
+ executor: PlanExecutorService;
26
+ auditLogService?: AuditPort;
27
+ visibilityFor: OperatorVisibilityFactory;
28
+ /**
29
+ * US2: reads live progress for a delegated bulk operation from whichever
30
+ * module started it.
31
+ *
32
+ * Data in, data out (D-76). It used to be handed the request row and the
33
+ * `EntityManager` and left to mutate both, which put this module's state
34
+ * machine in a contributor's hands; the fold and the terminal-status decision
35
+ * live in {@link foldBulkProgress} now.
36
+ */
37
+ bulkProgressReader?: (bulkOperationId: string) => Promise<BulkProgressSnapshot | null>;
38
+ ttlMinutes?: number;
39
+ now?: () => Date;
40
+ }
41
+ export interface OperatorContext {
42
+ adminUserId: string;
43
+ language?: string | null;
44
+ auditCtx: ToolAuditContext;
45
+ }
46
+ export declare class PromptRequestService {
47
+ private readonly deps;
48
+ constructor(deps: PromptRequestServiceDeps);
49
+ private now;
50
+ private ttlMs;
51
+ expiresAt(row: PromptActionRequest): Date | null;
52
+ submit(op: OperatorContext, prompt: string): Promise<PromptActionRequest>;
53
+ clarify(op: OperatorContext, id: string, answer: {
54
+ selectedCandidateId?: string;
55
+ text?: string;
56
+ }): Promise<PromptActionRequest>;
57
+ private runInterpretation;
58
+ confirm(op: OperatorContext, id: string): Promise<PromptActionRequest>;
59
+ cancel(op: OperatorContext, id: string): Promise<PromptActionRequest>;
60
+ get(op: OperatorContext, id: string): Promise<PromptActionRequest>;
61
+ /**
62
+ * Fold one contributor's snapshot into the request, and rule on the request's
63
+ * own terminal status (D-76, FR-011/FR-018).
64
+ *
65
+ * Both halves used to live in `catalog/prompt-tools.ts`, which meant a
66
+ * contributing module decided whether *this* module's request was
67
+ * `completed`, `failed` or `completed_with_errors`. The mapping is unchanged
68
+ * — it is moved, not rewritten: a run that ended with no failures completed,
69
+ * one with no successes failed, and anything between is
70
+ * `completed_with_errors`.
71
+ *
72
+ * `snapshot.terminal` says only that the bulk run ended. What it ended *as*
73
+ * for the request is read from the counts, which is what the previous
74
+ * implementation did too — it tested `op.status` for "ended" and then ignored
75
+ * it.
76
+ */
77
+ private foldBulkProgress;
78
+ listUnseenFinished(op: OperatorContext, limit: number): Promise<PromptActionRequest[]>;
79
+ markSeen(op: OperatorContext, id: string): Promise<void>;
80
+ private loadOwned;
81
+ private auditExecution;
82
+ private auditRefusal;
83
+ }
84
+ //# sourceMappingURL=prompt-request.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-request.service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/prompt-request.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAEtB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEzF;;;;;;;;GAQG;AAEH,MAAM,WAAW,yBAAyB;IACxC,CAAC,WAAW,EAAE,MAAM,GAAG;QACrB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACpD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACvD,CAAC;CACH;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,aAAa,EAAE,yBAAyB,CAAC;IACzC;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAID,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,wBAAwB;IAE3D,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,KAAK;IAIb,SAAS,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG,IAAI;IAS1C,MAAM,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAiCzE,OAAO,CACX,EAAE,EAAE,eAAe,EACnB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE;QAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GACtD,OAAO,CAAC,mBAAmB,CAAC;YAmCjB,iBAAiB;IAwEzB,OAAO,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA0FtE,MAAM,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAkBrE,GAAG,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAexE;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,gBAAgB;IA2BlB,kBAAkB,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAatF,QAAQ,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAehD,SAAS;YAaT,cAAc;YAyBd,YAAY;CAe3B"}
@@ -0,0 +1,338 @@
1
+ import { ERROR_CODES, PROMPT_ACTION_PLAN_TTL_MINUTES, } from '@endora-commerce/contracts';
2
+ import { HttpError } from '@endora-commerce/platform/http';
3
+ import { PromptActionRequest } from '../entities/prompt-action-request.entity.js';
4
+ import { PermissionRevoked } from './plan-executor.service.js';
5
+ const IN_FLIGHT_STATUSES = ['interpreting', 'executing'];
6
+ export class PromptRequestService {
7
+ deps;
8
+ constructor(deps) {
9
+ this.deps = deps;
10
+ }
11
+ now() {
12
+ return this.deps.now ? this.deps.now() : new Date();
13
+ }
14
+ ttlMs() {
15
+ return (this.deps.ttlMinutes ?? PROMPT_ACTION_PLAN_TTL_MINUTES) * 60_000;
16
+ }
17
+ expiresAt(row) {
18
+ if (row.status !== 'awaiting_confirmation')
19
+ return null;
20
+ return new Date(row.updatedAt.getTime() + this.ttlMs());
21
+ }
22
+ // --------------------------------------------------------------------
23
+ // Submit (interpretation)
24
+ // --------------------------------------------------------------------
25
+ async submit(op, prompt) {
26
+ // command-coverage-ignore: prompt-action request-queue lifecycle — the executed
27
+ // admin action is audited by its target service; this is queue state.
28
+ const em = this.deps.emFactory();
29
+ const inFlight = await em.count(PromptActionRequest, {
30
+ adminUserId: op.adminUserId,
31
+ status: { $in: [...IN_FLIGHT_STATUSES] },
32
+ });
33
+ if (inFlight > 0) {
34
+ throw new HttpError(429, ERROR_CODES.PROMPT_REQUEST_IN_FLIGHT, 'Another prompt is still being processed for this operator.');
35
+ }
36
+ const row = em.create(PromptActionRequest, {
37
+ adminUserId: op.adminUserId,
38
+ prompt,
39
+ language: op.language ?? null,
40
+ status: 'interpreting',
41
+ });
42
+ await em.flush();
43
+ await this.runInterpretation(em, row, op, { resume: false });
44
+ return row;
45
+ }
46
+ // --------------------------------------------------------------------
47
+ // Clarify (single round-trip, US3)
48
+ // --------------------------------------------------------------------
49
+ async clarify(op, id, answer) {
50
+ // command-coverage-ignore: prompt-action request-queue lifecycle — the executed
51
+ // admin action is audited by its target service; this is queue state.
52
+ const em = this.deps.emFactory();
53
+ const row = await this.loadOwned(em, id, op.adminUserId);
54
+ if (row.status !== 'needs_clarification') {
55
+ throw new HttpError(409, ERROR_CODES.PROMPT_REQUEST_INVALID_STATE, `Request is "${row.status}", not awaiting clarification.`);
56
+ }
57
+ const candidate = answer.selectedCandidateId
58
+ ? row.clarification?.candidates?.find((c) => c.id === answer.selectedCandidateId)
59
+ : undefined;
60
+ if (answer.selectedCandidateId && !candidate) {
61
+ throw new HttpError(400, ERROR_CODES.VALIDATION_FAILED, 'selectedCandidateId does not match any offered candidate.');
62
+ }
63
+ const answerText = candidate
64
+ ? `The operator chose: ${candidate.label} (id: ${candidate.id}).`
65
+ : (answer.text ?? '');
66
+ row.status = 'interpreting';
67
+ row.clarification = null;
68
+ await em.flush();
69
+ await this.runInterpretation(em, row, op, { resume: true, answerText });
70
+ return row;
71
+ }
72
+ async runInterpretation(em, row, op, opts) {
73
+ const toolCtx = {
74
+ adminUserId: op.adminUserId,
75
+ requestId: row.id,
76
+ auditCtx: op.auditCtx,
77
+ };
78
+ const outcome = await this.deps.interpreter.interpret({
79
+ prompt: row.prompt,
80
+ toolCtx,
81
+ visibility: this.deps.visibilityFor(op.adminUserId),
82
+ resumeConversation: opts.resume ? row.conversation : null,
83
+ clarificationAnswer: opts.answerText ?? null,
84
+ });
85
+ switch (outcome.kind) {
86
+ case 'plan':
87
+ row.status = 'awaiting_confirmation';
88
+ row.plan = outcome.plan;
89
+ row.conversation = outcome.conversation;
90
+ row.provider = outcome.provider;
91
+ row.model = outcome.model;
92
+ break;
93
+ case 'clarification':
94
+ if (opts.resume) {
95
+ // Second clarification round → unsupported (data-model §2).
96
+ row.status = 'unsupported';
97
+ row.error =
98
+ 'The instruction stayed ambiguous after one clarification — please rephrase it.';
99
+ row.finishedAt = this.now();
100
+ break;
101
+ }
102
+ row.status = 'needs_clarification';
103
+ row.clarification = outcome.clarification;
104
+ row.conversation = outcome.conversation;
105
+ row.provider = outcome.provider;
106
+ row.model = outcome.model;
107
+ break;
108
+ case 'unsupported':
109
+ row.status = 'unsupported';
110
+ row.error = outcome.detail;
111
+ row.finishedAt = this.now();
112
+ break;
113
+ case 'refused':
114
+ row.status = 'refused';
115
+ row.error = outcome.detail;
116
+ row.finishedAt = this.now();
117
+ await this.auditRefusal(row, op, 'interpretation');
118
+ break;
119
+ case 'blocked_bulk_limit':
120
+ row.status = 'unsupported';
121
+ row.error = `The prompt would affect ${outcome.affectedCount} records — the configured limit is ${outcome.limit}. Narrow the instruction.`;
122
+ row.finishedAt = this.now();
123
+ break;
124
+ case 'failed':
125
+ row.status = 'failed';
126
+ row.error = outcome.detail;
127
+ row.finishedAt = this.now();
128
+ break;
129
+ }
130
+ await em.flush();
131
+ }
132
+ // --------------------------------------------------------------------
133
+ // Confirm → execute
134
+ // --------------------------------------------------------------------
135
+ async confirm(op, id) {
136
+ const em = this.deps.emFactory();
137
+ const row = await this.loadOwned(em, id, op.adminUserId);
138
+ // Idempotency (FR-006): a repeat confirm returns the current state.
139
+ if (row.status === 'executing' ||
140
+ row.status === 'completed' ||
141
+ row.status === 'completed_with_errors') {
142
+ return row;
143
+ }
144
+ if (row.status !== 'awaiting_confirmation') {
145
+ throw new HttpError(409, ERROR_CODES.PROMPT_REQUEST_INVALID_STATE, `Request is "${row.status}" and cannot be confirmed.`);
146
+ }
147
+ // Lazy expiry (research §R5): no sweeper — checked exactly here.
148
+ const expiresAt = this.expiresAt(row);
149
+ if (expiresAt && this.now().getTime() > expiresAt.getTime()) {
150
+ row.status = 'expired';
151
+ row.finishedAt = this.now();
152
+ await em.flush();
153
+ throw new HttpError(409, ERROR_CODES.PROMPT_PLAN_EXPIRED, 'The plan expired before confirmation — submit the prompt again.');
154
+ }
155
+ // Atomic claim: only one confirm transitions to `executing`.
156
+ const claimed = await em.nativeUpdate(PromptActionRequest, { id: row.id, status: 'awaiting_confirmation' }, { status: 'executing', confirmedAt: this.now(), updatedAt: this.now() });
157
+ if (claimed === 0) {
158
+ em.clear();
159
+ return this.loadOwned(this.deps.emFactory(), id, op.adminUserId);
160
+ }
161
+ row.status = 'executing';
162
+ row.confirmedAt = this.now();
163
+ const toolCtx = {
164
+ adminUserId: op.adminUserId,
165
+ requestId: row.id,
166
+ auditCtx: op.auditCtx,
167
+ };
168
+ try {
169
+ const { result, bulkOperationId } = await this.deps.executor.execute(row.plan, toolCtx, this.deps.visibilityFor(op.adminUserId));
170
+ row.result = result;
171
+ if (bulkOperationId) {
172
+ // Delegated bulk work: stays `executing`; GET folds live progress in.
173
+ row.bulkOperationId = bulkOperationId;
174
+ }
175
+ else {
176
+ row.status = result.outcome;
177
+ row.finishedAt = this.now();
178
+ }
179
+ await em.flush();
180
+ await this.auditExecution(row, op);
181
+ return row;
182
+ }
183
+ catch (err) {
184
+ if (err instanceof PermissionRevoked) {
185
+ row.status = 'refused';
186
+ row.error = err.message;
187
+ row.finishedAt = this.now();
188
+ await em.flush();
189
+ await this.auditRefusal(row, op, 'execution');
190
+ throw new HttpError(403, ERROR_CODES.PROMPT_PERMISSION_REVOKED, err.message);
191
+ }
192
+ row.status = 'failed';
193
+ row.error = err.message ?? 'Execution failed.';
194
+ row.finishedAt = this.now();
195
+ await em.flush();
196
+ throw err;
197
+ }
198
+ }
199
+ // --------------------------------------------------------------------
200
+ // Cancel / read / seen
201
+ // --------------------------------------------------------------------
202
+ async cancel(op, id) {
203
+ // command-coverage-ignore: prompt-action request-queue lifecycle — the executed
204
+ // admin action is audited by its target service; this is queue state.
205
+ const em = this.deps.emFactory();
206
+ const row = await this.loadOwned(em, id, op.adminUserId);
207
+ if (row.status !== 'awaiting_confirmation' && row.status !== 'needs_clarification') {
208
+ throw new HttpError(409, ERROR_CODES.PROMPT_REQUEST_INVALID_STATE, `Request is "${row.status}" and cannot be cancelled.`);
209
+ }
210
+ row.status = 'cancelled';
211
+ row.finishedAt = this.now();
212
+ await em.flush();
213
+ return row;
214
+ }
215
+ async get(op, id) {
216
+ const em = this.deps.emFactory();
217
+ const row = await this.loadOwned(em, id, op.adminUserId);
218
+ if (row.status === 'executing' && row.bulkOperationId && this.deps.bulkProgressReader) {
219
+ const snapshot = await this.deps.bulkProgressReader(row.bulkOperationId);
220
+ if (snapshot)
221
+ this.foldBulkProgress(row, snapshot);
222
+ if (row.status !== 'executing') {
223
+ row.finishedAt = row.finishedAt ?? this.now();
224
+ await em.flush();
225
+ await this.auditExecution(row, op);
226
+ }
227
+ }
228
+ return row;
229
+ }
230
+ /**
231
+ * Fold one contributor's snapshot into the request, and rule on the request's
232
+ * own terminal status (D-76, FR-011/FR-018).
233
+ *
234
+ * Both halves used to live in `catalog/prompt-tools.ts`, which meant a
235
+ * contributing module decided whether *this* module's request was
236
+ * `completed`, `failed` or `completed_with_errors`. The mapping is unchanged
237
+ * — it is moved, not rewritten: a run that ended with no failures completed,
238
+ * one with no successes failed, and anything between is
239
+ * `completed_with_errors`.
240
+ *
241
+ * `snapshot.terminal` says only that the bulk run ended. What it ended *as*
242
+ * for the request is read from the counts, which is what the previous
243
+ * implementation did too — it tested `op.status` for "ended" and then ignored
244
+ * it.
245
+ */
246
+ foldBulkProgress(row, snapshot) {
247
+ if (!row.result || !row.bulkOperationId)
248
+ return;
249
+ const summary = {
250
+ total: snapshot.total,
251
+ succeeded: snapshot.succeeded,
252
+ failed: snapshot.failed,
253
+ failures: snapshot.failures,
254
+ };
255
+ row.result = {
256
+ ...row.result,
257
+ operations: row.result.operations.map((operation) => operation.bulkOperationId === row.bulkOperationId ? { ...operation, summary } : operation),
258
+ };
259
+ if (snapshot.terminal === null)
260
+ return;
261
+ const outcome = snapshot.failed === 0
262
+ ? 'completed'
263
+ : snapshot.succeeded === 0
264
+ ? 'failed'
265
+ : 'completed_with_errors';
266
+ row.result = { ...row.result, outcome };
267
+ row.status = outcome;
268
+ if (snapshot.error)
269
+ row.error = snapshot.error;
270
+ }
271
+ async listUnseenFinished(op, limit) {
272
+ const em = this.deps.emFactory();
273
+ return em.find(PromptActionRequest, {
274
+ adminUserId: op.adminUserId,
275
+ status: { $in: ['completed', 'completed_with_errors', 'failed'] },
276
+ seenAt: null,
277
+ }, { orderBy: { createdAt: 'desc' }, limit });
278
+ }
279
+ async markSeen(op, id) {
280
+ // command-coverage-ignore: prompt-action request-queue lifecycle — the executed
281
+ // admin action is audited by its target service; this is queue state.
282
+ const em = this.deps.emFactory();
283
+ const row = await this.loadOwned(em, id, op.adminUserId);
284
+ if (!row.seenAt) {
285
+ row.seenAt = this.now();
286
+ await em.flush();
287
+ }
288
+ }
289
+ // --------------------------------------------------------------------
290
+ // Internals
291
+ // --------------------------------------------------------------------
292
+ async loadOwned(em, id, adminUserId) {
293
+ const row = await em.findOne(PromptActionRequest, { id });
294
+ // Foreign requests 404 (not 403) to avoid existence leaks (contract §1).
295
+ if (!row || row.adminUserId !== adminUserId) {
296
+ throw new HttpError(404, ERROR_CODES.NOT_FOUND, 'Prompt request not found.');
297
+ }
298
+ return row;
299
+ }
300
+ async auditExecution(row, op) {
301
+ if (!this.deps.auditLogService)
302
+ return;
303
+ await this.deps.auditLogService.record({
304
+ actorAdminUserId: op.adminUserId,
305
+ action: 'prompt_action.execute',
306
+ objectType: 'prompt_action_request',
307
+ objectId: row.id,
308
+ stateAfter: {
309
+ prompt: row.prompt,
310
+ provider: row.provider,
311
+ model: row.model,
312
+ operations: row.plan?.operations.map((o) => ({
313
+ toolId: o.toolId,
314
+ params: o.params,
315
+ headline: o.preview.headline,
316
+ })),
317
+ outcome: row.result?.outcome ?? row.status,
318
+ bulkOperationId: row.bulkOperationId,
319
+ },
320
+ ...(op.auditCtx.ipAddress !== undefined ? { ipAddress: op.auditCtx.ipAddress } : {}),
321
+ ...(op.auditCtx.userAgent !== undefined ? { userAgent: op.auditCtx.userAgent } : {}),
322
+ ...(op.auditCtx.requestId !== undefined ? { requestId: op.auditCtx.requestId } : {}),
323
+ });
324
+ }
325
+ async auditRefusal(row, op, phase) {
326
+ if (!this.deps.auditLogService)
327
+ return;
328
+ await this.deps.auditLogService.record({
329
+ actorAdminUserId: op.adminUserId,
330
+ action: 'prompt_action.refused',
331
+ objectType: 'prompt_action_request',
332
+ objectId: row.id,
333
+ stateAfter: { prompt: row.prompt, phase, detail: row.error },
334
+ ...(op.auditCtx.requestId !== undefined ? { requestId: op.auditCtx.requestId } : {}),
335
+ });
336
+ }
337
+ }
338
+ //# sourceMappingURL=prompt-request.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-request.service.js","sourceRoot":"","sources":["../../../src/backend/services/prompt-request.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { LlmToolDefinition, PromptActionTool, PromptActionToolRegistryPort, ToolVisibilityContext } from '@endora-commerce/contracts';
2
+ export declare class PromptActionToolRegistry implements PromptActionToolRegistryPort {
3
+ private readonly tools;
4
+ register<P>(tool: PromptActionTool<P>): void;
5
+ get(id: string): PromptActionTool | undefined;
6
+ list(): PromptActionTool[];
7
+ /**
8
+ * The catalogue sent to the LLM for one operator: tools whose owning
9
+ * module is installed AND whose permission the operator holds. Filtering
10
+ * happens here (before the model ever sees a tool) and again at execution
11
+ * time in the plan executor (defense in depth, FR-007).
12
+ */
13
+ visibleFor(ctx: ToolVisibilityContext): Promise<PromptActionTool[]>;
14
+ /** Provider-facing definition: same Zod schema, serialized as JSON Schema. */
15
+ toLlmToolDefinition(tool: PromptActionTool): LlmToolDefinition;
16
+ }
17
+ //# sourceMappingURL=tool-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../../src/backend/services/tool-registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,4BAA4B,EAC5B,qBAAqB,EACtB,MAAM,4BAA4B,CAAC;AAmCpC,qBAAa,wBAAyB,YAAW,4BAA4B;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAE7D,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI;IAuB5C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAI7C,IAAI,IAAI,gBAAgB,EAAE;IAI1B;;;;;OAKG;IACG,UAAU,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAgBzE,8EAA8E;IAC9E,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,iBAAiB;CAO/D"}