@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 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,yCAAyC,EAAE,MAAM,0CAA0C,CAAC;AAErG,eAAO,MAAM,UAAU,sDAEtB,CAAC;AAEF,OAAO,EACL,yCAAyC,GAC1C,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The `./migrations` subpath — every migration class this module owns, as one
3
+ * ordered `migrations` array.
4
+ *
5
+ * The array is what the platform reads when this module is **installed**:
6
+ * `src/packages/package-runtime.ts` takes `exported['migrations']` and refuses
7
+ * the package outright when it is absent (D-168).
8
+ *
9
+ * Listed in ascending timestamp, which is the order of this module's own
10
+ * migrations and of nothing else (feature 081): a manifest `dependencies` array
11
+ * is the only thing ordering this block against another module's.
12
+ *
13
+ * The **named** exports stay beside the array, and the asymmetry with
14
+ * `./backend` — which publishes an array and no named class (D-168) — is
15
+ * deliberate. `db/migrations-registry.generated.ts` imports each class by name
16
+ * from this specifier, and a migration class name is contract in a way an entity
17
+ * class name is not: `mikro_orm_migrations` persists it, so it is a string every
18
+ * already-migrated database holds.
19
+ *
20
+ * A class that is in neither the array nor the barrel is a migration that does
21
+ * not run: `migration:pending` reports nothing pending and the first symptom is
22
+ * a query against a table nobody created.
23
+ */
24
+ import { Migration20260611T140410PromptActionsInit } from './20260611T140410_prompt_actions_init.js';
25
+ export const migrations = [
26
+ Migration20260611T140410PromptActionsInit,
27
+ ];
28
+ export { Migration20260611T140410PromptActionsInit, };
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,yCAAyC,EAAE,MAAM,0CAA0C,CAAC;AAErG,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,yCAAyC;CAC1C,CAAC;AAEF,OAAO,EACL,yCAAyC,GAC1C,CAAC"}
@@ -0,0 +1,117 @@
1
+ ---
2
+ title: Prompt Actions (AI assistant)
3
+ description: Natural-language prompt mode for the admin command palette, with an explicit preview-and-confirm step before any change
4
+ ---
5
+
6
+ # Prompt Actions (AI assistant)
7
+
8
+ The `prompt_actions` module adds a natural-language prompt mode to the admin
9
+ command palette (`⌘K` / `Ctrl+K`). An operator describes what they want in
10
+ plain language — Polish or English — and the platform interprets the
11
+ instruction, shows exactly what it is about to change, and executes it only
12
+ after explicit confirmation.
13
+
14
+ Example prompts:
15
+
16
+ - *Dla produktu „Bolts 0193" zwiększ stan magazynowy w magazynie „Default" na 120 sztuk*
17
+ - *Assign every product with "Helmets" in its name to the "Helmets" category*
18
+
19
+ ## How it works (operator view)
20
+
21
+ 1. Open the palette and pick **Ask the assistant…** (visible only when the
22
+ feature is enabled, configured, and you hold the *Use the prompt
23
+ assistant* permission).
24
+ 2. Type the instruction and submit. The assistant resolves names ("Bolts
25
+ 0193", "Default") into concrete records using read-only searches.
26
+ 3. A **plan card** appears: the exact operation(s), the current value, the
27
+ number of affected records and a sample for bulk changes. Nothing has
28
+ been changed yet.
29
+ 4. **Confirm** to execute, or **Cancel** to keep everything untouched. Plans
30
+ expire after 10 minutes without confirmation.
31
+ 5. The result reports per-item outcomes. Bulk runs above 50 records continue
32
+ in the background; if you close the palette, a notice appears on the next
33
+ open until you view the result.
34
+
35
+ If the instruction is ambiguous the assistant asks one clarifying question
36
+ (with concrete candidates) instead of guessing. Unsupported requests and
37
+ missing permissions are reported plainly, and nothing changes.
38
+
39
+ ## Security model
40
+
41
+ - The model can only call a **curated tool catalogue** registered in code —
42
+ it cannot run SQL, call arbitrary endpoints, or invent operations. Tools
43
+ the operator has no permission for are not even shown to the model.
44
+ - Mutations are **never executed during interpretation**: they are captured
45
+ into a plan; each plan operation re-checks the operator's live permission
46
+ at execution time.
47
+ - Everything on the plan card is **server-computed** (names, counts, current
48
+ values). Model prose is never displayed, and tool results are treated
49
+ strictly as data — a product named like an instruction cannot change the
50
+ assistant's behavior.
51
+ - Every execution writes audit entries: a `prompt_action.execute` summary
52
+ (with the original prompt, provider and model) plus the underlying
53
+ modules' own audit rows (e.g. `stock_level.adjust`). Permission refusals
54
+ are audited as `prompt_action.refused`. Executions also appear on the
55
+ dashboard's Recent Activity card.
56
+
57
+ ## Configuration (platform administrator)
58
+
59
+ Settings → group **Prompt actions (AI assistant)**:
60
+
61
+ | Setting | Default | Meaning |
62
+ |---------|---------|---------|
63
+ | `prompt_actions.enabled` | `false` | Platform-wide kill switch. When off, the palette behaves exactly as without the module. |
64
+ | `prompt_actions.provider` | `anthropic` | LLM provider: `anthropic` (Claude), `google` (Gemini) or `openai` (GPT). |
65
+ | `prompt_actions.model` | `claude-sonnet-4-6` | Model ID for the chosen provider. |
66
+ | `prompt_actions.api_key` | *(unset)* | Provider credential. **Write-only secret**: encrypted at rest, never returned by the settings API after saving. |
67
+ | `prompt_actions.bulk_limit` | `500` | Maximum records one prompt may affect; larger plans are blocked at preview. |
68
+
69
+ Configuration changes apply on the next prompt — no restart. The backend
70
+ needs `SETTINGS_SECRET_ENCRYPTION_KEY` in its environment to store the API
71
+ key (see the root README, *Environment variables*).
72
+
73
+ Grant operators the **Use the prompt assistant** (`prompt_actions:use`)
74
+ permission on the Roles screen. Each planned operation additionally requires
75
+ the same permission as the equivalent manual action (e.g. `catalog:write`
76
+ for a stock change), so the assistant can never exceed what the operator
77
+ could do by hand.
78
+
79
+ ## Extending the catalogue (module authors)
80
+
81
+ Modules contribute tools at composition time through the
82
+ `PromptActionToolRegistry` port — the same adapter-registry pattern used by
83
+ payment and shipping providers. A tool declares:
84
+
85
+ ```ts
86
+ {
87
+ id: '<moduleId>.<snake_case_name>', // e.g. 'inventory.set_stock_level'
88
+ moduleId: 'inventory',
89
+ kind: 'resolver' | 'mutation',
90
+ description: '…', // English; the LLM's only documentation
91
+ requiredPermission: 'catalog:write', // MUST mirror the manual route's permission
92
+ paramsSchema: zodSchema, // validates LLM args + becomes the JSON Schema
93
+ execute(params, ctx) { … }, // resolvers run during interpretation;
94
+ // mutations only at confirm time
95
+ preview(params, ctx) { … }, // mutations only — server-computed facts
96
+ }
97
+ ```
98
+
99
+ Rules (enforced at registration where possible): dotted ids prefixed with
100
+ the owning module; resolvers are side-effect-free and cap results (≤ 20);
101
+ mutations must implement `preview()` returning honest, server-computed
102
+ counts and samples; tools of disabled modules disappear from the catalogue
103
+ automatically.
104
+
105
+ ## v1 tool catalogue
106
+
107
+ | Tool | Kind | Permission |
108
+ |------|------|------------|
109
+ | `catalog.search_products` | resolver | `catalog:read` |
110
+ | `catalog.search_categories` | resolver | `catalog:read` |
111
+ | `inventory.search_warehouses` | resolver | `catalog:read` |
112
+ | `inventory.set_stock_level` | mutation | `catalog:write` |
113
+ | `catalog.assign_products_to_category` | mutation | `catalog:write` |
114
+
115
+ Bulk category assignments above 50 products ride the existing durable
116
+ `catalog.bulk-operation` queue (the same worker that serves the bulk-edit
117
+ screen), so large prompts never block the API process.
package/i18n/en.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "adminRoles.permission.prompt_actions:use": "Use the prompt assistant",
3
+ "palette.entry.label": "Ask the assistant…",
4
+ "palette.entry.description": "Describe what you want to do in plain language",
5
+ "panel.inputPlaceholder": "e.g. Set the stock of \"Bolts 0193\" in warehouse \"Default\" to 120",
6
+ "panel.voiceInput": "Dictate (speech-to-text)",
7
+ "panel.voiceInputStop": "Stop dictation",
8
+ "panel.submit": "Interpret",
9
+ "panel.interpreting": "Interpreting your instruction…",
10
+ "panel.executing": "Executing…",
11
+ "panel.confirm": "Confirm and execute",
12
+ "panel.cancel": "Cancel",
13
+ "panel.back": "Back",
14
+ "panel.close": "Close",
15
+ "panel.planHeading": "The assistant proposes:",
16
+ "panel.affectedCount": "{count} record(s) will be affected",
17
+ "panel.sampleHeading": "Sample of matched records:",
18
+ "panel.currentValue": "Current value:",
19
+ "panel.expiresHint": "This plan must be confirmed within 10 minutes.",
20
+ "panel.success": "Done — the change has been applied.",
21
+ "panel.successWithErrors": "Finished with some failures — see the breakdown below.",
22
+ "panel.failed": "The assistant could not complete this request.",
23
+ "panel.unsupported": "This request is not supported by the assistant.",
24
+ "panel.refused": "You do not have the permission required for this action.",
25
+ "panel.providerError": "The assistant service is currently unavailable. Your data has not been changed — please try again or use the regular admin screens.",
26
+ "panel.clarificationHeading": "The assistant needs one detail:",
27
+ "panel.clarificationFreeTextPlaceholder": "Type your answer…",
28
+ "panel.clarificationSubmit": "Answer",
29
+ "panel.resultSucceeded": "{count} succeeded",
30
+ "panel.resultFailed": "{count} failed",
31
+ "panel.openTarget": "Open the affected record",
32
+ "panel.unseenNotice": "A prompt you confirmed earlier has finished — open the assistant to see the result.",
33
+ "panel.inFlight": "Another prompt is still being processed — wait for it to finish.",
34
+ "panel.bulkLimitExceeded": "This prompt would affect more records than the configured limit ({limit}). Narrow the instruction and try again.",
35
+ "panel.planExpired": "This plan has expired without confirmation. Submit the prompt again.",
36
+ "capability.disabled": "The prompt assistant is disabled on this platform.",
37
+ "capability.notConfigured": "The prompt assistant is not configured yet — set the provider and API key in Settings.",
38
+ "palette.group.label": "Assistant",
39
+ "activity.verb.prompt_action.execute": "ran a prompt action"
40
+ }
package/i18n/pl.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "adminRoles.permission.prompt_actions:use": "Korzystanie z asystenta promptów",
3
+ "palette.entry.label": "Zapytaj asystenta…",
4
+ "palette.entry.description": "Opisz, co chcesz zrobić, własnymi słowami",
5
+ "panel.inputPlaceholder": "np. Dla produktu \"Bolts 0193\" zwiększ stan magazynowy w magazynie \"Default\" na 120 sztuk",
6
+ "panel.voiceInput": "Dyktowanie (mowa na tekst)",
7
+ "panel.voiceInputStop": "Zatrzymaj dyktowanie",
8
+ "panel.submit": "Interpretuj",
9
+ "panel.interpreting": "Interpretuję polecenie…",
10
+ "panel.executing": "Wykonuję…",
11
+ "panel.confirm": "Potwierdź i wykonaj",
12
+ "panel.cancel": "Anuluj",
13
+ "panel.back": "Wróć",
14
+ "panel.close": "Zamknij",
15
+ "panel.planHeading": "Asystent proponuje:",
16
+ "panel.affectedCount": "Zmiana obejmie {count} rekord(ów)",
17
+ "panel.sampleHeading": "Przykładowe dopasowane rekordy:",
18
+ "panel.currentValue": "Obecna wartość:",
19
+ "panel.expiresHint": "Ten plan trzeba potwierdzić w ciągu 10 minut.",
20
+ "panel.success": "Gotowe — zmiana została zastosowana.",
21
+ "panel.successWithErrors": "Zakończono z błędami — szczegóły poniżej.",
22
+ "panel.failed": "Asystent nie mógł zrealizować tego polecenia.",
23
+ "panel.unsupported": "To polecenie nie jest obsługiwane przez asystenta.",
24
+ "panel.refused": "Nie masz uprawnienia wymaganego do tej operacji.",
25
+ "panel.providerError": "Usługa asystenta jest chwilowo niedostępna. Dane nie zostały zmienione — spróbuj ponownie lub użyj zwykłych ekranów panelu.",
26
+ "panel.clarificationHeading": "Asystent potrzebuje jednego doprecyzowania:",
27
+ "panel.clarificationFreeTextPlaceholder": "Wpisz odpowiedź…",
28
+ "panel.clarificationSubmit": "Odpowiedz",
29
+ "panel.resultSucceeded": "{count} powiodło się",
30
+ "panel.resultFailed": "{count} nie powiodło się",
31
+ "panel.openTarget": "Otwórz zmieniony rekord",
32
+ "panel.unseenNotice": "Wcześniej potwierdzony prompt został zakończony — otwórz asystenta, aby zobaczyć wynik.",
33
+ "panel.inFlight": "Poprzedni prompt jest wciąż przetwarzany — poczekaj na jego zakończenie.",
34
+ "panel.bulkLimitExceeded": "To polecenie objęłoby więcej rekordów niż ustawiony limit ({limit}). Zawęź polecenie i spróbuj ponownie.",
35
+ "panel.planExpired": "Ten plan wygasł bez potwierdzenia. Wyślij polecenie ponownie.",
36
+ "capability.disabled": "Asystent promptów jest wyłączony na tej platformie.",
37
+ "capability.notConfigured": "Asystent promptów nie jest jeszcze skonfigurowany — ustaw dostawcę i klucz API w Ustawieniach.",
38
+ "palette.group.label": "Asystent",
39
+ "activity.verb.prompt_action.execute": "wykonał akcję asystenta"
40
+ }
package/package.json CHANGED
@@ -1,6 +1,70 @@
1
1
  {
2
2
  "name": "@endora-commerce/mod-prompt-actions",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.100.0",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "description": "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.",
7
+ "license": "MIT",
8
+ "endora": {
9
+ "type": "module",
10
+ "id": "prompt_actions"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/endora-commerce/endora-commerce.git",
15
+ "directory": "packages/modules/prompt_actions"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/manifest.d.ts",
23
+ "default": "./dist/manifest.js"
24
+ },
25
+ "./backend": {
26
+ "types": "./dist/backend/index.d.ts",
27
+ "default": "./dist/backend/index.js"
28
+ },
29
+ "./migrations": {
30
+ "types": "./dist/migrations/index.d.ts",
31
+ "default": "./dist/migrations/index.js"
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "i18n",
38
+ "docs"
39
+ ],
40
+ "engines": {
41
+ "node": ">=22.18.0"
42
+ },
43
+ "peerDependencies": {
44
+ "@mikro-orm/core": "^6",
45
+ "@mikro-orm/migrations": "^6",
46
+ "@mikro-orm/postgresql": "^6",
47
+ "fastify": "^5",
48
+ "zod": "^4",
49
+ "@endora-commerce/contracts": "0.100.0",
50
+ "@endora-commerce/platform": "0.100.0"
51
+ },
52
+ "devDependencies": {
53
+ "@mikro-orm/core": "^6.6.13",
54
+ "@mikro-orm/migrations": "^6.6.13",
55
+ "@mikro-orm/postgresql": "^6.6.13",
56
+ "@types/node": "^22.9.0",
57
+ "fastify": "^5.12.5",
58
+ "typescript": "^5.9.3",
59
+ "vitest": "^4.1.11",
60
+ "zod": "^4.2.0",
61
+ "@endora-commerce/contracts": "0.100.0",
62
+ "@endora-commerce/platform": "0.100.0"
63
+ },
64
+ "scripts": {
65
+ "build": "tsc -p tsconfig.build.json",
66
+ "typecheck": "tsc -p tsconfig.json",
67
+ "lint": "eslint src",
68
+ "test": "vitest run"
69
+ }
6
70
  }