@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.
- package/LICENSE +21 -0
- package/README.md +51 -2
- package/dist/backend/entities/prompt-action-request.entity.d.ts +37 -0
- package/dist/backend/entities/prompt-action-request.entity.d.ts.map +1 -0
- package/dist/backend/entities/prompt-action-request.entity.js +130 -0
- package/dist/backend/entities/prompt-action-request.entity.js.map +1 -0
- package/dist/backend/index.d.ts +94 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +127 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +30 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +71 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/services/bulk-progress-registry.d.ts +82 -0
- package/dist/backend/services/bulk-progress-registry.d.ts.map +1 -0
- package/dist/backend/services/bulk-progress-registry.js +44 -0
- package/dist/backend/services/bulk-progress-registry.js.map +1 -0
- package/dist/backend/services/interpreter.service.d.ts +59 -0
- package/dist/backend/services/interpreter.service.d.ts.map +1 -0
- package/dist/backend/services/interpreter.service.js +270 -0
- package/dist/backend/services/interpreter.service.js.map +1 -0
- package/dist/backend/services/llm/anthropic-adapter.d.ts +9 -0
- package/dist/backend/services/llm/anthropic-adapter.d.ts.map +1 -0
- package/dist/backend/services/llm/anthropic-adapter.js +83 -0
- package/dist/backend/services/llm/anthropic-adapter.js.map +1 -0
- package/dist/backend/services/llm/google-adapter.d.ts +9 -0
- package/dist/backend/services/llm/google-adapter.d.ts.map +1 -0
- package/dist/backend/services/llm/google-adapter.js +125 -0
- package/dist/backend/services/llm/google-adapter.js.map +1 -0
- package/dist/backend/services/llm/openai-adapter.d.ts +9 -0
- package/dist/backend/services/llm/openai-adapter.d.ts.map +1 -0
- package/dist/backend/services/llm/openai-adapter.js +95 -0
- package/dist/backend/services/llm/openai-adapter.js.map +1 -0
- package/dist/backend/services/llm/provider-factory.d.ts +60 -0
- package/dist/backend/services/llm/provider-factory.d.ts.map +1 -0
- package/dist/backend/services/llm/provider-factory.js +111 -0
- package/dist/backend/services/llm/provider-factory.js.map +1 -0
- package/dist/backend/services/llm/provider.d.ts +63 -0
- package/dist/backend/services/llm/provider.d.ts.map +1 -0
- package/dist/backend/services/llm/provider.js +67 -0
- package/dist/backend/services/llm/provider.js.map +1 -0
- package/dist/backend/services/plan-executor.service.d.ts +49 -0
- package/dist/backend/services/plan-executor.service.d.ts.map +1 -0
- package/dist/backend/services/plan-executor.service.js +132 -0
- package/dist/backend/services/plan-executor.service.js.map +1 -0
- package/dist/backend/services/prompt-request.service.d.ts +84 -0
- package/dist/backend/services/prompt-request.service.d.ts.map +1 -0
- package/dist/backend/services/prompt-request.service.js +338 -0
- package/dist/backend/services/prompt-request.service.js.map +1 -0
- package/dist/backend/services/tool-registry.d.ts +17 -0
- package/dist/backend/services/tool-registry.d.ts.map +1 -0
- package/dist/backend/services/tool-registry.js +89 -0
- package/dist/backend/services/tool-registry.js.map +1 -0
- package/dist/manifest.d.ts +252 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +199 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260611T140410_prompt_actions_init.d.ts +17 -0
- package/dist/migrations/20260611T140410_prompt_actions_init.d.ts.map +1 -0
- package/dist/migrations/20260611T140410_prompt_actions_init.js +47 -0
- package/dist/migrations/20260611T140410_prompt_actions_init.js.map +1 -0
- package/dist/migrations/index.d.ts +27 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +29 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/prompt-actions.md +117 -0
- package/i18n/en.json +40 -0
- package/i18n/pl.json +40 -0
- package/package.json +67 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# @endora-commerce/mod-prompt-actions
|
|
4
|
+
|
|
5
|
+
Natural-language prompt mode for the admin command palette: interpret an operator instruction with an LLM, preview the plan, execute it through existing module services after explicit confirmation.
|
|
6
|
+
|
|
7
|
+
## What this is
|
|
8
|
+
|
|
9
|
+
An **Endora Commerce module package**. Its module id is `prompt_actions` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
|
|
10
|
+
|
|
11
|
+
A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
|
|
12
|
+
|
|
13
|
+
## Entry points
|
|
14
|
+
|
|
15
|
+
| Import | Contents |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `@endora-commerce/mod-prompt-actions` | the module manifest — its id, version, dependencies, settings and activation |
|
|
18
|
+
| `@endora-commerce/mod-prompt-actions/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
|
|
19
|
+
| `@endora-commerce/mod-prompt-actions/migrations` | the module’s own schema migrations, in the order the platform runs them |
|
|
20
|
+
|
|
21
|
+
## Depends on
|
|
22
|
+
|
|
23
|
+
Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
|
|
24
|
+
|
|
25
|
+
**Endora packages**
|
|
26
|
+
|
|
27
|
+
- `@endora-commerce/contracts`
|
|
28
|
+
- `@endora-commerce/platform`
|
|
29
|
+
|
|
30
|
+
**Third-party**
|
|
31
|
+
|
|
32
|
+
- `@mikro-orm/core` ^6
|
|
33
|
+
- `@mikro-orm/migrations` ^6
|
|
34
|
+
- `@mikro-orm/postgresql` ^6
|
|
35
|
+
- `fastify` ^5
|
|
36
|
+
- `zod` ^4
|
|
37
|
+
|
|
38
|
+
## What the tarball carries
|
|
39
|
+
|
|
40
|
+
- `dist/` — the compiled JavaScript and its type declarations
|
|
41
|
+
- `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
|
|
42
|
+
- `docs/` — the package’s own pages in the Endora Commerce documentation site
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm add @endora-commerce/mod-prompt-actions
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Licence
|
|
51
|
+
|
|
52
|
+
MIT — the text is in `LICENSE`, beside this file.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
import type { PromptActionClarification, PromptActionPlan, PromptActionResult, PromptActionStatus } from '@endora-commerce/contracts';
|
|
3
|
+
/**
|
|
4
|
+
* PromptActionRequest — feature 043 / data-model §1–§2.
|
|
5
|
+
*
|
|
6
|
+
* One operator-submitted natural-language instruction with its full
|
|
7
|
+
* lifecycle: interpretation output (plan or clarification), the minimal
|
|
8
|
+
* provider-neutral conversation retained for the single clarify round-trip,
|
|
9
|
+
* confirmation, execution result, and the seen-marker driving the
|
|
10
|
+
* "finished while you were away" notice (FR-018).
|
|
11
|
+
*
|
|
12
|
+
* No FK on `admin_user_id` (module_actions precedent — lifecycle owns
|
|
13
|
+
* cleanup, admin users are platform-owned).
|
|
14
|
+
*/
|
|
15
|
+
export declare class PromptActionRequest {
|
|
16
|
+
[OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'language' | 'provider' | 'model' | 'plan' | 'clarification' | 'conversation' | 'result' | 'error' | 'bulkOperationId' | 'seenAt' | 'confirmedAt' | 'finishedAt';
|
|
17
|
+
id: string;
|
|
18
|
+
adminUserId: string;
|
|
19
|
+
prompt: string;
|
|
20
|
+
language: string | null;
|
|
21
|
+
status: PromptActionStatus;
|
|
22
|
+
provider: string | null;
|
|
23
|
+
model: string | null;
|
|
24
|
+
plan: PromptActionPlan | null;
|
|
25
|
+
clarification: PromptActionClarification | null;
|
|
26
|
+
/** Provider-neutral transcript retained for the clarify round-trip + diagnostics. */
|
|
27
|
+
conversation: unknown | null;
|
|
28
|
+
result: PromptActionResult | null;
|
|
29
|
+
error: string | null;
|
|
30
|
+
bulkOperationId: string | null;
|
|
31
|
+
seenAt: Date | null;
|
|
32
|
+
confirmedAt: Date | null;
|
|
33
|
+
finishedAt: Date | null;
|
|
34
|
+
createdAt: Date;
|
|
35
|
+
updatedAt: Date;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=prompt-action-request.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-action-request.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/prompt-action-request.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAGrF,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;GAWG;AACH,qBAGa,mBAAmB;IAC9B,CAAC,aAAa,CAAC,CAAC,EACZ,IAAI,GACJ,WAAW,GACX,WAAW,GACX,UAAU,GACV,UAAU,GACV,OAAO,GACP,MAAM,GACN,eAAe,GACf,cAAc,GACd,QAAQ,GACR,OAAO,GACP,iBAAiB,GACjB,QAAQ,GACR,aAAa,GACb,YAAY,CAAC;IAGjB,EAAE,EAAE,MAAM,CAAgB;IAG1B,WAAW,EAAG,MAAM,CAAC;IAGrB,MAAM,EAAG,MAAM,CAAC;IAGhB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,MAAM,EAAG,kBAAkB,CAAC;IAG5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG5B,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAGrC,aAAa,EAAE,yBAAyB,GAAG,IAAI,CAAQ;IAEvD,qFAAqF;IAErF,YAAY,EAAE,OAAO,GAAG,IAAI,CAAQ;IAGpC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAQ;IAGzC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG5B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAGtC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAQ;IAG3B,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAGhC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAQ;IAG/B,SAAS,EAAE,IAAI,CAAc;IAQ7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
|
|
11
|
+
import { GlobalEntity } from '@endora-commerce/platform/tenancy';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
/**
|
|
14
|
+
* PromptActionRequest — feature 043 / data-model §1–§2.
|
|
15
|
+
*
|
|
16
|
+
* One operator-submitted natural-language instruction with its full
|
|
17
|
+
* lifecycle: interpretation output (plan or clarification), the minimal
|
|
18
|
+
* provider-neutral conversation retained for the single clarify round-trip,
|
|
19
|
+
* confirmation, execution result, and the seen-marker driving the
|
|
20
|
+
* "finished while you were away" notice (FR-018).
|
|
21
|
+
*
|
|
22
|
+
* No FK on `admin_user_id` (module_actions precedent — lifecycle owns
|
|
23
|
+
* cleanup, admin users are platform-owned).
|
|
24
|
+
*/
|
|
25
|
+
let PromptActionRequest = class PromptActionRequest {
|
|
26
|
+
[OptionalProps];
|
|
27
|
+
id = randomUUID();
|
|
28
|
+
adminUserId;
|
|
29
|
+
prompt;
|
|
30
|
+
language = null;
|
|
31
|
+
status;
|
|
32
|
+
provider = null;
|
|
33
|
+
model = null;
|
|
34
|
+
plan = null;
|
|
35
|
+
clarification = null;
|
|
36
|
+
/** Provider-neutral transcript retained for the clarify round-trip + diagnostics. */
|
|
37
|
+
conversation = null;
|
|
38
|
+
result = null;
|
|
39
|
+
error = null;
|
|
40
|
+
bulkOperationId = null;
|
|
41
|
+
seenAt = null;
|
|
42
|
+
confirmedAt = null;
|
|
43
|
+
finishedAt = null;
|
|
44
|
+
createdAt = new Date();
|
|
45
|
+
updatedAt = new Date();
|
|
46
|
+
};
|
|
47
|
+
__decorate([
|
|
48
|
+
PrimaryKey({ type: 'uuid' }),
|
|
49
|
+
__metadata("design:type", String)
|
|
50
|
+
], PromptActionRequest.prototype, "id", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
Property({ type: 'uuid', fieldName: 'admin_user_id' }),
|
|
53
|
+
__metadata("design:type", String)
|
|
54
|
+
], PromptActionRequest.prototype, "adminUserId", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
Property({ type: 'text' }),
|
|
57
|
+
__metadata("design:type", String)
|
|
58
|
+
], PromptActionRequest.prototype, "prompt", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
Property({ type: 'string', length: 12, nullable: true }),
|
|
61
|
+
__metadata("design:type", Object)
|
|
62
|
+
], PromptActionRequest.prototype, "language", void 0);
|
|
63
|
+
__decorate([
|
|
64
|
+
Property({ type: 'string', length: 32 }),
|
|
65
|
+
__metadata("design:type", String)
|
|
66
|
+
], PromptActionRequest.prototype, "status", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
Property({ type: 'string', length: 32, nullable: true }),
|
|
69
|
+
__metadata("design:type", Object)
|
|
70
|
+
], PromptActionRequest.prototype, "provider", void 0);
|
|
71
|
+
__decorate([
|
|
72
|
+
Property({ type: 'string', length: 120, nullable: true }),
|
|
73
|
+
__metadata("design:type", Object)
|
|
74
|
+
], PromptActionRequest.prototype, "model", void 0);
|
|
75
|
+
__decorate([
|
|
76
|
+
Property({ type: 'json', nullable: true }),
|
|
77
|
+
__metadata("design:type", Object)
|
|
78
|
+
], PromptActionRequest.prototype, "plan", void 0);
|
|
79
|
+
__decorate([
|
|
80
|
+
Property({ type: 'json', nullable: true }),
|
|
81
|
+
__metadata("design:type", Object)
|
|
82
|
+
], PromptActionRequest.prototype, "clarification", void 0);
|
|
83
|
+
__decorate([
|
|
84
|
+
Property({ type: 'json', nullable: true }),
|
|
85
|
+
__metadata("design:type", Object)
|
|
86
|
+
], PromptActionRequest.prototype, "conversation", void 0);
|
|
87
|
+
__decorate([
|
|
88
|
+
Property({ type: 'json', nullable: true }),
|
|
89
|
+
__metadata("design:type", Object)
|
|
90
|
+
], PromptActionRequest.prototype, "result", void 0);
|
|
91
|
+
__decorate([
|
|
92
|
+
Property({ type: 'text', nullable: true }),
|
|
93
|
+
__metadata("design:type", Object)
|
|
94
|
+
], PromptActionRequest.prototype, "error", void 0);
|
|
95
|
+
__decorate([
|
|
96
|
+
Property({ type: 'uuid', fieldName: 'bulk_operation_id', nullable: true }),
|
|
97
|
+
__metadata("design:type", Object)
|
|
98
|
+
], PromptActionRequest.prototype, "bulkOperationId", void 0);
|
|
99
|
+
__decorate([
|
|
100
|
+
Property({ type: 'datetime', fieldName: 'seen_at', nullable: true }),
|
|
101
|
+
__metadata("design:type", Object)
|
|
102
|
+
], PromptActionRequest.prototype, "seenAt", void 0);
|
|
103
|
+
__decorate([
|
|
104
|
+
Property({ type: 'datetime', fieldName: 'confirmed_at', nullable: true }),
|
|
105
|
+
__metadata("design:type", Object)
|
|
106
|
+
], PromptActionRequest.prototype, "confirmedAt", void 0);
|
|
107
|
+
__decorate([
|
|
108
|
+
Property({ type: 'datetime', fieldName: 'finished_at', nullable: true }),
|
|
109
|
+
__metadata("design:type", Object)
|
|
110
|
+
], PromptActionRequest.prototype, "finishedAt", void 0);
|
|
111
|
+
__decorate([
|
|
112
|
+
Property({ type: 'datetime', fieldName: 'created_at', onCreate: () => new Date() }),
|
|
113
|
+
__metadata("design:type", Date)
|
|
114
|
+
], PromptActionRequest.prototype, "createdAt", void 0);
|
|
115
|
+
__decorate([
|
|
116
|
+
Property({
|
|
117
|
+
type: 'datetime',
|
|
118
|
+
fieldName: 'updated_at',
|
|
119
|
+
onCreate: () => new Date(),
|
|
120
|
+
onUpdate: () => new Date(),
|
|
121
|
+
}),
|
|
122
|
+
__metadata("design:type", Date)
|
|
123
|
+
], PromptActionRequest.prototype, "updatedAt", void 0);
|
|
124
|
+
PromptActionRequest = __decorate([
|
|
125
|
+
GlobalEntity(),
|
|
126
|
+
Entity({ tableName: 'prompt_action_requests' }),
|
|
127
|
+
Index({ properties: ['adminUserId', 'createdAt'] })
|
|
128
|
+
], PromptActionRequest);
|
|
129
|
+
export { PromptActionRequest };
|
|
130
|
+
//# sourceMappingURL=prompt-action-request.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-action-request.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/prompt-action-request.entity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { FastifyRequest } from 'fastify';
|
|
2
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
3
|
+
import type { AuditPort } from '@endora-commerce/platform/kernel';
|
|
4
|
+
import type { ModuleContext } from '@endora-commerce/platform/kernel';
|
|
5
|
+
import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
|
|
6
|
+
import { PromptRequestService } from './services/prompt-request.service.js';
|
|
7
|
+
import { PromptActionToolRegistry } from './services/tool-registry.js';
|
|
8
|
+
import { PromptActionBulkProgressRegistry } from './services/bulk-progress-registry.js';
|
|
9
|
+
import { LlmProviderFactory, type CredentialResolvePort, type SettingsReadPort } from './services/llm/provider-factory.js';
|
|
10
|
+
import type { FetchLike } from './services/llm/provider.js';
|
|
11
|
+
import { PromptActionRequest } from './entities/prompt-action-request.entity.js';
|
|
12
|
+
/**
|
|
13
|
+
* `prompt_actions` — the module every other module contributes *into*
|
|
14
|
+
* (feature 072, wave 1).
|
|
15
|
+
*
|
|
16
|
+
* It owns no domain logic. Its whole job is to hold the tool catalogue that
|
|
17
|
+
* `catalog`, `inventory` and `orders` populate, hand a permission-filtered view
|
|
18
|
+
* of it to an LLM, and execute the confirmed plan through the contributors'
|
|
19
|
+
* own services. That inverts the usual direction — this module is nobody's
|
|
20
|
+
* dependency and everybody's dependant — so nothing here is a port. A port is
|
|
21
|
+
* for a name *other* modules resolve; the two names this module publishes are
|
|
22
|
+
* read by the composition root, which is not gated by anything.
|
|
23
|
+
*
|
|
24
|
+
* **`promptActionToolRegistry` is deliberately an ordinary registration.**
|
|
25
|
+
* Making it a port would mean the root gets a 503 while contributing tools if
|
|
26
|
+
* the operator switched the assistant off — at composition time, before the
|
|
27
|
+
* effective state is even loaded. Contribution has to be tolerant; it is the
|
|
28
|
+
* *routes* that gate, and they already do.
|
|
29
|
+
*
|
|
30
|
+
* **No `activation:` declaration, deliberately.** The module already ships
|
|
31
|
+
* `prompt_actions.enabled`, and it is *not* an activation control in the
|
|
32
|
+
* Constitution XVII sense: switching it off is supposed to leave the capability
|
|
33
|
+
* endpoint answering `200 {status: 'disabled'}` and submissions answering `409
|
|
34
|
+
* ASSISTANT_DISABLED`, which is what the admin palette reads to hide the prompt
|
|
35
|
+
* mode. Declaring it as the activation setting would make `ctx.routes` 503 the
|
|
36
|
+
* whole surface instead, including the probe the palette needs to *learn* the
|
|
37
|
+
* module is off. Reconciling a bespoke kill switch with the two-axis machinery
|
|
38
|
+
* is feature 073's problem, not this conversion's; until then the module is
|
|
39
|
+
* gated on the platform axis alone — which is one axis more than it had.
|
|
40
|
+
*
|
|
41
|
+
* The one behaviour change: tool visibility now resolves `effectiveState`
|
|
42
|
+
* rather than `registryCache.isEnabled`. See
|
|
43
|
+
* `test/integration/prompt_actions/deactivated-module-tools.test.ts` — the old
|
|
44
|
+
* seam advertised tools belonging to a module the operator had deactivated.
|
|
45
|
+
*/
|
|
46
|
+
export interface PromptActionsCradle {
|
|
47
|
+
readonly emFactory: () => EntityManager;
|
|
48
|
+
readonly auditLogService: AuditPort;
|
|
49
|
+
readonly settingsReadPort: SettingsReadPort;
|
|
50
|
+
readonly settingsChannelResolver: () => Promise<string>;
|
|
51
|
+
readonly requireAdmin: RequireAdminFactory;
|
|
52
|
+
readonly adminContextResolver: (req: FastifyRequest) => {
|
|
53
|
+
adminUserId: string;
|
|
54
|
+
};
|
|
55
|
+
readonly permissionService: {
|
|
56
|
+
hasPermission(adminUserId: string, permission: string): Promise<boolean>;
|
|
57
|
+
};
|
|
58
|
+
readonly credentialsService: CredentialResolvePort;
|
|
59
|
+
/**
|
|
60
|
+
* Pushed into by `catalog` when a deployment ships it, so a delegated bulk
|
|
61
|
+
* request can show live progress. Absent is a supported state — the request
|
|
62
|
+
* simply reports no progress — which is why this module does not declare
|
|
63
|
+
* `catalog` as a dependency for it.
|
|
64
|
+
*
|
|
65
|
+
* D-72 point 4 — a **registry keyed by contributing module**, where it used
|
|
66
|
+
* to be a single name this module defaulted to `undefined` and a composition
|
|
67
|
+
* root overwrote with `catalog`'s resolver. That shape was the last thing
|
|
68
|
+
* keeping `catalog/prompt-tools.js` named in both roots: a module may not
|
|
69
|
+
* write a name another module owns, so `catalog` could not push a resolver
|
|
70
|
+
* into a slot, only into a table.
|
|
71
|
+
*/
|
|
72
|
+
readonly promptActionBulkProgressRegistry: PromptActionBulkProgressRegistry;
|
|
73
|
+
/** Test seams; a root overrides them by re-registering the name. */
|
|
74
|
+
readonly promptActionsLlmFetch: FetchLike | undefined;
|
|
75
|
+
readonly promptActionsNow: (() => Date) | undefined;
|
|
76
|
+
readonly promptActionsTtlMinutes: number | undefined;
|
|
77
|
+
readonly promptActionToolRegistry: PromptActionToolRegistry;
|
|
78
|
+
readonly llmProviderFactory: LlmProviderFactory;
|
|
79
|
+
readonly promptRequestService: PromptRequestService;
|
|
80
|
+
}
|
|
81
|
+
export declare function registerModule(ctx: ModuleContext): void;
|
|
82
|
+
/**
|
|
83
|
+
* The module's persisted entity classes, on the `./backend` subpath, as one
|
|
84
|
+
* array and **no named class export** (D-168).
|
|
85
|
+
*
|
|
86
|
+
* This is the shape the platform reads when the package is *installed*: the
|
|
87
|
+
* boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
|
|
88
|
+
* and the static declaration reader (`scripts/lib/package-declarations.ts`),
|
|
89
|
+
* which is the third source of `check:module-boundary`'s `table→owner` map and
|
|
90
|
+
* the package pass of `check-entity-tenant-classification`. A missing array is
|
|
91
|
+
* answered with `[]` — zero entities registered, no error anywhere.
|
|
92
|
+
*/
|
|
93
|
+
export declare const entities: (typeof PromptActionRequest)[];
|
|
94
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAK5E,OAAO,EACL,oBAAoB,EAErB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,gCAAgC,EAAE,MAAM,sCAAsC,CAAC;AACxF,OAAO,EACL,kBAAkB,EAClB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACtB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,aAAa,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,oBAAoB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAChF,QAAQ,CAAC,iBAAiB,EAAE;QAC1B,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KAC1E,CAAC;IACF,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;IACnD;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,gCAAgC,EAAE,gCAAgC,CAAC;IAC5E,oEAAoE;IACpE,QAAQ,CAAC,qBAAqB,EAAE,SAAS,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,gBAAgB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAC;IAErD,QAAQ,CAAC,wBAAwB,EAAE,wBAAwB,CAAC;IAC5D,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAChD,QAAQ,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;CACrD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAqIvD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,gCAEpB,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { lazyPort } from '@endora-commerce/platform/kernel';
|
|
2
|
+
import { effectiveState } from '@endora-commerce/platform/kernel';
|
|
3
|
+
import { registerPromptActionsAdminRoutes } from './routes.admin.js';
|
|
4
|
+
import { InterpreterService } from './services/interpreter.service.js';
|
|
5
|
+
import { PlanExecutorService } from './services/plan-executor.service.js';
|
|
6
|
+
import { PromptRequestService, } from './services/prompt-request.service.js';
|
|
7
|
+
import { PromptActionToolRegistry } from './services/tool-registry.js';
|
|
8
|
+
import { PromptActionBulkProgressRegistry } from './services/bulk-progress-registry.js';
|
|
9
|
+
import { LlmProviderFactory, } from './services/llm/provider-factory.js';
|
|
10
|
+
import { PromptActionRequest } from './entities/prompt-action-request.entity.js';
|
|
11
|
+
export function registerModule(ctx) {
|
|
12
|
+
ctx.di.register({
|
|
13
|
+
// A **contribution registry**, and a plain `di.register` on purpose: it must
|
|
14
|
+
// stay one. `catalog`, `inventory` and `orders` push their tool descriptors
|
|
15
|
+
// in from `ctx.onBoot`, and boot hooks run whatever this module's effective
|
|
16
|
+
// state is, so a `providePort` gate here would throw `MODULE_DISABLED`
|
|
17
|
+
// during composition and stop the backend from starting. It would also move
|
|
18
|
+
// every edge into this name from `contributes` to `fails-closed` in the
|
|
19
|
+
// deactivation-consequence ledger, changing the sentence the operator's
|
|
20
|
+
// confirmation dialog renders (issue #192; port-publication.md §1.4).
|
|
21
|
+
promptActionToolRegistry: ctx.asFunction(() => new PromptActionToolRegistry()).singleton(),
|
|
22
|
+
// The second contribution registry, and an ordinary registration for the
|
|
23
|
+
// same reason as the first: a boot hook has to be able to push into it
|
|
24
|
+
// whatever the assistant's own effective state is. The presence question
|
|
25
|
+
// is answered at enumeration, keyed on the module recorded with each
|
|
26
|
+
// entry, and the probe is wired to the kernel here — the class defaults it
|
|
27
|
+
// to always-present so a unit test that builds its own registry keeps
|
|
28
|
+
// answering about the resolvers that test registered.
|
|
29
|
+
promptActionBulkProgressRegistry: ctx
|
|
30
|
+
.asFunction(() => new PromptActionBulkProgressRegistry((moduleId) => effectiveState.isPresent(moduleId)))
|
|
31
|
+
.singleton(),
|
|
32
|
+
promptActionsLlmFetch: ctx.asFunction(() => undefined).singleton(),
|
|
33
|
+
promptActionsNow: ctx.asFunction(() => undefined).singleton(),
|
|
34
|
+
promptActionsTtlMinutes: ctx.asFunction(() => undefined).singleton(),
|
|
35
|
+
llmProviderFactory: ctx
|
|
36
|
+
.asFunction(({ promptActionsLlmFetch }) => {
|
|
37
|
+
// `credentialsService` is a **port**, so it is resolved per call
|
|
38
|
+
// rather than captured. Awilix's strict mode refuses the capture
|
|
39
|
+
// outright — a singleton may not hold a transient — and it is right
|
|
40
|
+
// to: a captured port keeps answering after the operator switches
|
|
41
|
+
// `credentials` off, so the assistant would go on decrypting API
|
|
42
|
+
// keys through a module that is supposed to be absent. Resolving per
|
|
43
|
+
// call turns that into the 503 the port exists to produce, and only
|
|
44
|
+
// on the path that actually needs a secret.
|
|
45
|
+
const credentials = {
|
|
46
|
+
resolve: (configurationCode) => ctx.cradle().credentialsService.resolve(configurationCode),
|
|
47
|
+
};
|
|
48
|
+
return new LlmProviderFactory({
|
|
49
|
+
settings: lazyPort(ctx, 'settingsReadPort'),
|
|
50
|
+
// A function-valued name, so it cannot go through `lazyPort` —
|
|
51
|
+
// that forwards method calls on an object. The closure is the same
|
|
52
|
+
// deferral by hand.
|
|
53
|
+
resolveChannelId: () => ctx.cradle().settingsChannelResolver(),
|
|
54
|
+
credentials,
|
|
55
|
+
...(promptActionsLlmFetch === undefined
|
|
56
|
+
? {}
|
|
57
|
+
: { fetchImpl: promptActionsLlmFetch }),
|
|
58
|
+
});
|
|
59
|
+
})
|
|
60
|
+
.singleton(),
|
|
61
|
+
promptRequestService: ctx
|
|
62
|
+
.asFunction(({ emFactory, auditLogService, promptActionToolRegistry, llmProviderFactory, promptActionsNow, promptActionsTtlMinutes, }) => {
|
|
63
|
+
// `maxRounds` is not threaded through a container seam: the old
|
|
64
|
+
// options type carried one and nothing ever passed it. The property
|
|
65
|
+
// it guards is covered where it belongs, in the interpreter's own
|
|
66
|
+
// unit test, which constructs the service directly.
|
|
67
|
+
const interpreter = new InterpreterService({
|
|
68
|
+
registry: promptActionToolRegistry,
|
|
69
|
+
providerFactory: llmProviderFactory,
|
|
70
|
+
...(promptActionsNow === undefined
|
|
71
|
+
? {}
|
|
72
|
+
: { now: () => promptActionsNow().getTime() }),
|
|
73
|
+
});
|
|
74
|
+
const visibilityFor = (adminUserId) => ({
|
|
75
|
+
hasPermission: (permission) => ctx.cradle().permissionService.hasPermission(adminUserId, permission),
|
|
76
|
+
// Constitution XVII: presence is the conjunction of both axes. A
|
|
77
|
+
// module the operator deactivated must not appear in the
|
|
78
|
+
// catalogue, or the assistant plans work the platform refuses.
|
|
79
|
+
isModuleInstalled: async (moduleId) => effectiveState.isPresent(moduleId),
|
|
80
|
+
});
|
|
81
|
+
// Read through the registry per call rather than captured out of it:
|
|
82
|
+
// a contributor's boot hook runs after this factory may first be
|
|
83
|
+
// resolved, and — more to the point — an operator switching a
|
|
84
|
+
// contributor off has to change the answer without a restart.
|
|
85
|
+
const bulkProgressReader = (bulkOperationId) => ctx
|
|
86
|
+
.cradle()
|
|
87
|
+
.promptActionBulkProgressRegistry.apply(bulkOperationId);
|
|
88
|
+
return new PromptRequestService({
|
|
89
|
+
emFactory,
|
|
90
|
+
interpreter,
|
|
91
|
+
executor: new PlanExecutorService(promptActionToolRegistry),
|
|
92
|
+
visibilityFor,
|
|
93
|
+
auditLogService,
|
|
94
|
+
bulkProgressReader,
|
|
95
|
+
...(promptActionsNow === undefined ? {} : { now: promptActionsNow }),
|
|
96
|
+
...(promptActionsTtlMinutes === undefined
|
|
97
|
+
? {}
|
|
98
|
+
: { ttlMinutes: promptActionsTtlMinutes }),
|
|
99
|
+
});
|
|
100
|
+
})
|
|
101
|
+
.singleton(),
|
|
102
|
+
});
|
|
103
|
+
ctx.routes(async (app) => {
|
|
104
|
+
const { promptRequestService, llmProviderFactory, requireAdmin, adminContextResolver } = ctx.cradle();
|
|
105
|
+
await registerPromptActionsAdminRoutes(app, {
|
|
106
|
+
requestService: promptRequestService,
|
|
107
|
+
providerFactory: llmProviderFactory,
|
|
108
|
+
requireAdmin,
|
|
109
|
+
resolveAdminContext: adminContextResolver,
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The module's persisted entity classes, on the `./backend` subpath, as one
|
|
115
|
+
* array and **no named class export** (D-168).
|
|
116
|
+
*
|
|
117
|
+
* This is the shape the platform reads when the package is *installed*: the
|
|
118
|
+
* boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
|
|
119
|
+
* and the static declaration reader (`scripts/lib/package-declarations.ts`),
|
|
120
|
+
* which is the third source of `check:module-boundary`'s `table→owner` map and
|
|
121
|
+
* the package pass of `check-entity-tenant-classification`. A missing array is
|
|
122
|
+
* answered with `[]` — zero entities registered, no error anywhere.
|
|
123
|
+
*/
|
|
124
|
+
export const entities = [
|
|
125
|
+
PromptActionRequest,
|
|
126
|
+
];
|
|
127
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EACL,oBAAoB,GAErB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,gCAAgC,EAAE,MAAM,sCAAsC,CAAC;AACxF,OAAO,EACL,kBAAkB,GAGnB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AAwEjF,MAAM,UAAU,cAAc,CAAC,GAAkB;IAC/C,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC;QACd,6EAA6E;QAC7E,4EAA4E;QAC5E,4EAA4E;QAC5E,uEAAuE;QACvE,4EAA4E;QAC5E,wEAAwE;QACxE,wEAAwE;QACxE,sEAAsE;QACtE,wBAAwB,EAAE,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,wBAAwB,EAAE,CAAC,CAAC,SAAS,EAAE;QAE1F,yEAAyE;QACzE,uEAAuE;QACvE,yEAAyE;QACzE,qEAAqE;QACrE,2EAA2E;QAC3E,sEAAsE;QACtE,sDAAsD;QACtD,gCAAgC,EAAE,GAAG;aAClC,UAAU,CACT,GAAG,EAAE,CACH,IAAI,gCAAgC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CACzF;aACA,SAAS,EAAE;QAEd,qBAAqB,EAAE,GAAG,CAAC,UAAU,CAAC,GAA0B,EAAE,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE;QACzF,gBAAgB,EAAE,GAAG,CAAC,UAAU,CAAC,GAA6B,EAAE,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE;QACvF,uBAAuB,EAAE,GAAG,CAAC,UAAU,CAAC,GAAuB,EAAE,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE;QAExF,kBAAkB,EAAE,GAAG;aACpB,UAAU,CACT,CAAC,EAAE,qBAAqB,EAAuB,EAAE,EAAE;YACjD,iEAAiE;YACjE,iEAAiE;YACjE,oEAAoE;YACpE,kEAAkE;YAClE,iEAAiE;YACjE,qEAAqE;YACrE,oEAAoE;YACpE,4CAA4C;YAC5C,MAAM,WAAW,GAA0B;gBACzC,OAAO,EAAE,CAAC,iBAAiB,EAAE,EAAE,CAC7B,GAAG,CAAC,MAAM,EAAuB,CAAC,kBAAkB,CAAC,OAAO,CAAC,iBAAiB,CAAC;aAClF,CAAC;YACF,OAAO,IAAI,kBAAkB,CAAC;gBAC5B,QAAQ,EAAE,QAAQ,CAAmB,GAAG,EAAE,kBAAkB,CAAC;gBAC7D,+DAA+D;gBAC/D,mEAAmE;gBACnE,oBAAoB;gBACpB,gBAAgB,EAAE,GAAG,EAAE,CACrB,GAAG,CAAC,MAAM,EAAuB,CAAC,uBAAuB,EAAE;gBAC7D,WAAW;gBACX,GAAG,CAAC,qBAAqB,KAAK,SAAS;oBACrC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,SAAS,EAAE,qBAAqB,EAAE,CAAC;aAC1C,CAAC,CAAC;QACL,CAAC,CACF;aACA,SAAS,EAAE;QAEd,oBAAoB,EAAE,GAAG;aACtB,UAAU,CACT,CAAC,EACC,SAAS,EACT,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,GACH,EAAE,EAAE;YACxB,gEAAgE;YAChE,oEAAoE;YACpE,kEAAkE;YAClE,oDAAoD;YACpD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC;gBACzC,QAAQ,EAAE,wBAAwB;gBAClC,eAAe,EAAE,kBAAkB;gBACnC,GAAG,CAAC,gBAAgB,KAAK,SAAS;oBAChC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;aACjD,CAAC,CAAC;YAEH,MAAM,aAAa,GAA8B,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;gBACjE,aAAa,EAAE,CAAC,UAAU,EAAE,EAAE,CAC5B,GAAG,CAAC,MAAM,EAAuB,CAAC,iBAAiB,CAAC,aAAa,CAC/D,WAAW,EACX,UAAU,CACX;gBACH,iEAAiE;gBACjE,yDAAyD;gBACzD,+DAA+D;gBAC/D,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC;aAC1E,CAAC,CAAC;YAEH,qEAAqE;YACrE,iEAAiE;YACjE,8DAA8D;YAC9D,8DAA8D;YAC9D,MAAM,kBAAkB,GAEpB,CAAC,eAAe,EAAE,EAAE,CACtB,GAAG;iBACA,MAAM,EAAuB;iBAC7B,gCAAgC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YAE7D,OAAO,IAAI,oBAAoB,CAAC;gBAC9B,SAAS;gBACT,WAAW;gBACX,QAAQ,EAAE,IAAI,mBAAmB,CAAC,wBAAwB,CAAC;gBAC3D,aAAa;gBACb,eAAe;gBACf,kBAAkB;gBAClB,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC;gBACpE,GAAG,CAAC,uBAAuB,KAAK,SAAS;oBACvC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,UAAU,EAAE,uBAAuB,EAAE,CAAC;aAC7C,CAAC,CAAC;QACL,CAAC,CACF;aACA,SAAS,EAAE;KACf,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,YAAY,EAAE,oBAAoB,EAAE,GACpF,GAAG,CAAC,MAAM,EAAuB,CAAC;QACpC,MAAM,gCAAgC,CAAC,GAAG,EAAE;YAC1C,cAAc,EAAE,oBAAoB;YACpC,eAAe,EAAE,kBAAkB;YACnC,YAAY;YACZ,mBAAmB,EAAE,oBAAoB;SAC1C,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,mBAAmB;CACpB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { FastifyInstance, FastifyRequest } from 'fastify';
|
|
2
|
+
import type { PromptRequestService } from './services/prompt-request.service.js';
|
|
3
|
+
import type { LlmProviderFactory } from './services/llm/provider-factory.js';
|
|
4
|
+
import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
|
|
5
|
+
/**
|
|
6
|
+
* Admin HTTP surface — feature 043 (contracts/prompt-actions-api.md).
|
|
7
|
+
*
|
|
8
|
+
* GET /api/v1/admin/prompt-actions/capability
|
|
9
|
+
* POST /api/v1/admin/prompt-actions/requests
|
|
10
|
+
* GET /api/v1/admin/prompt-actions/requests (?unseen=true&limit=)
|
|
11
|
+
* GET /api/v1/admin/prompt-actions/requests/:id
|
|
12
|
+
* POST /api/v1/admin/prompt-actions/requests/:id/clarify
|
|
13
|
+
* POST /api/v1/admin/prompt-actions/requests/:id/confirm
|
|
14
|
+
* POST /api/v1/admin/prompt-actions/requests/:id/cancel
|
|
15
|
+
* POST /api/v1/admin/prompt-actions/requests/:id/seen
|
|
16
|
+
*
|
|
17
|
+
* All routes are gated by `requireAdmin('prompt_actions:use')`; each
|
|
18
|
+
* planned operation is additionally re-checked against its own permission
|
|
19
|
+
* inside the executor (FR-007).
|
|
20
|
+
*/
|
|
21
|
+
export interface PromptActionsRoutesDeps {
|
|
22
|
+
requestService: PromptRequestService;
|
|
23
|
+
providerFactory: LlmProviderFactory;
|
|
24
|
+
requireAdmin: RequireAdminFactory;
|
|
25
|
+
resolveAdminContext: (req: FastifyRequest) => {
|
|
26
|
+
adminUserId: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function registerPromptActionsAdminRoutes(app: FastifyInstance, deps: PromptActionsRoutesDeps): Promise<void>;
|
|
30
|
+
//# sourceMappingURL=routes.admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.admin.d.ts","sourceRoot":"","sources":["../../src/backend/routes.admin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAW/D,OAAO,KAAK,EAAE,oBAAoB,EAAmB,MAAM,sCAAsC,CAAC;AAClG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAE5E;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,oBAAoB,CAAC;IACrC,eAAe,EAAE,kBAAkB,CAAC;IACpC,YAAY,EAAE,mBAAmB,CAAC;IAClC,mBAAmB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CACvE;AAED,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAoHf"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ClarifyRequestSchema, ERROR_CODES, PromptActionListQuerySchema, SubmitPromptRequestSchema, } from '@endora-commerce/contracts';
|
|
2
|
+
import { HttpError } from '@endora-commerce/platform/http';
|
|
3
|
+
import { PROMPT_ACTIONS_USE_PERMISSION } from '../manifest.js';
|
|
4
|
+
export async function registerPromptActionsAdminRoutes(app, deps) {
|
|
5
|
+
const { requestService, providerFactory, requireAdmin, resolveAdminContext } = deps;
|
|
6
|
+
const guard = requireAdmin(PROMPT_ACTIONS_USE_PERMISSION);
|
|
7
|
+
const operator = (request) => {
|
|
8
|
+
const { adminUserId } = resolveAdminContext(request);
|
|
9
|
+
const rid = request.headers['x-request-id'];
|
|
10
|
+
const language = request.headers['x-admin-language'];
|
|
11
|
+
return {
|
|
12
|
+
adminUserId,
|
|
13
|
+
language: typeof language === 'string' ? language : null,
|
|
14
|
+
auditCtx: {
|
|
15
|
+
ipAddress: request.ip ?? null,
|
|
16
|
+
userAgent: request.headers['user-agent'] ?? null,
|
|
17
|
+
requestId: typeof rid === 'string' ? rid : null,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const dto = (row) => ({
|
|
22
|
+
data: {
|
|
23
|
+
id: row.id,
|
|
24
|
+
status: row.status,
|
|
25
|
+
prompt: row.prompt,
|
|
26
|
+
plan: row.plan ?? null,
|
|
27
|
+
clarification: row.clarification ?? null,
|
|
28
|
+
result: row.result ?? null,
|
|
29
|
+
error: row.error ?? null,
|
|
30
|
+
bulkOperationId: row.bulkOperationId ?? null,
|
|
31
|
+
expiresAt: requestService.expiresAt(row)?.toISOString() ?? null,
|
|
32
|
+
seenAt: row.seenAt?.toISOString() ?? null,
|
|
33
|
+
createdAt: row.createdAt.toISOString(),
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
app.get('/api/v1/admin/prompt-actions/capability', { preHandler: guard }, async () => ({ data: await providerFactory.capability() }));
|
|
37
|
+
app.post('/api/v1/admin/prompt-actions/requests', { preHandler: guard }, async (request, reply) => {
|
|
38
|
+
const body = SubmitPromptRequestSchema.parse(request.body);
|
|
39
|
+
// Disabled / unconfigured assistants reject before any row is created.
|
|
40
|
+
const capability = await providerFactory.capability();
|
|
41
|
+
if (capability.status === 'disabled') {
|
|
42
|
+
throw new HttpError(409, ERROR_CODES.ASSISTANT_DISABLED, 'The prompt assistant is disabled on this platform.');
|
|
43
|
+
}
|
|
44
|
+
if (capability.status === 'not_configured') {
|
|
45
|
+
throw new HttpError(409, ERROR_CODES.ASSISTANT_NOT_CONFIGURED, 'The prompt assistant is not configured — set the provider, model and API key in Settings.');
|
|
46
|
+
}
|
|
47
|
+
const row = await requestService.submit(operator(request), body.prompt);
|
|
48
|
+
reply.code(201);
|
|
49
|
+
return dto(row);
|
|
50
|
+
});
|
|
51
|
+
app.get('/api/v1/admin/prompt-actions/requests', { preHandler: guard }, async (request) => {
|
|
52
|
+
const q = PromptActionListQuerySchema.parse(request.query ?? {});
|
|
53
|
+
const rows = q.unseen
|
|
54
|
+
? await requestService.listUnseenFinished(operator(request), q.limit)
|
|
55
|
+
: [];
|
|
56
|
+
return { data: rows.map((r) => dto(r).data) };
|
|
57
|
+
});
|
|
58
|
+
app.get('/api/v1/admin/prompt-actions/requests/:id', { preHandler: guard }, async (request) => dto(await requestService.get(operator(request), request.params.id)));
|
|
59
|
+
app.post('/api/v1/admin/prompt-actions/requests/:id/clarify', { preHandler: guard }, async (request) => {
|
|
60
|
+
const body = ClarifyRequestSchema.parse(request.body);
|
|
61
|
+
const row = await requestService.clarify(operator(request), request.params.id, body);
|
|
62
|
+
return dto(row);
|
|
63
|
+
});
|
|
64
|
+
app.post('/api/v1/admin/prompt-actions/requests/:id/confirm', { preHandler: guard }, async (request) => dto(await requestService.confirm(operator(request), request.params.id)));
|
|
65
|
+
app.post('/api/v1/admin/prompt-actions/requests/:id/cancel', { preHandler: guard }, async (request) => dto(await requestService.cancel(operator(request), request.params.id)));
|
|
66
|
+
app.post('/api/v1/admin/prompt-actions/requests/:id/seen', { preHandler: guard }, async (request, reply) => {
|
|
67
|
+
await requestService.markSeen(operator(request), request.params.id);
|
|
68
|
+
reply.code(204);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=routes.admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.admin.js","sourceRoot":"","sources":["../../src/backend/routes.admin.ts"],"names":[],"mappings":"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"}
|