@happyvertical/smrt-prompts 0.51.21 → 0.51.29

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 (40) hide show
  1. package/AGENTS.md +34 -1
  2. package/README.md +148 -2
  3. package/dist/__smrt-register__.d.ts +2 -0
  4. package/dist/__smrt-register__.d.ts.map +1 -0
  5. package/dist/cache.d.ts +33 -0
  6. package/dist/cache.d.ts.map +1 -0
  7. package/dist/collections/PromptOverrideCollection.d.ts +45 -0
  8. package/dist/collections/PromptOverrideCollection.d.ts.map +1 -0
  9. package/dist/index.d.ts +12 -174
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +298 -30
  12. package/dist/index.js.map +1 -1
  13. package/dist/manifest.json +117 -28
  14. package/dist/models/PromptOverride.d.ts +32 -0
  15. package/dist/models/PromptOverride.d.ts.map +1 -0
  16. package/dist/prompt-override-service.d.ts +56 -0
  17. package/dist/prompt-override-service.d.ts.map +1 -0
  18. package/dist/prompt-registry.d.ts +13 -0
  19. package/dist/prompt-registry.d.ts.map +1 -0
  20. package/dist/prompt-resolver.d.ts +3 -0
  21. package/dist/prompt-resolver.d.ts.map +1 -0
  22. package/dist/prompt-settings.d.ts +188 -0
  23. package/dist/prompt-settings.d.ts.map +1 -0
  24. package/dist/smrt-knowledge.json +108 -248
  25. package/dist/svelte/components/PromptSettingsPanel.svelte +353 -0
  26. package/dist/svelte/components/PromptSettingsPanel.svelte.d.ts +52 -0
  27. package/dist/svelte/components/PromptSettingsPanel.svelte.d.ts.map +1 -0
  28. package/dist/svelte/index.d.ts +17 -0
  29. package/dist/svelte/index.d.ts.map +1 -0
  30. package/dist/svelte/index.js +14 -0
  31. package/dist/svelte/types.d.ts +75 -0
  32. package/dist/svelte/types.d.ts.map +1 -0
  33. package/dist/svelte/types.js +42 -0
  34. package/dist/types.d.ts +107 -110
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +6 -0
  37. package/dist/types.js.map +1 -0
  38. package/dist/utils.d.ts +29 -0
  39. package/dist/utils.d.ts.map +1 -0
  40. package/package.json +27 -8
@@ -0,0 +1,353 @@
1
+ <script lang="ts">
2
+ /**
3
+ * PromptSettingsPanel — the shared prompt-management surface.
4
+ *
5
+ * Purely presentational: it takes rows and callbacks. It does no fetching, and
6
+ * it makes no authorization decision — the host decides who may see the panel
7
+ * and who may write, and enforces that on the server (see
8
+ * `PromptSettingsService` and `PromptOverrideService`). Rendering the app
9
+ * column is a host decision too: apps with no platform-admin tier omit it.
10
+ *
11
+ * Each row renders as its own `<form>`, so a SvelteKit host can point
12
+ * `formAction` at a form action and get a working screen with no client JS:
13
+ * the "override" checkbox and the textarea are independent fields, and
14
+ * whether a scope is overridden is decided by whether its checkbox's name is
15
+ * present in the submitted `FormData` — never by disabling the textarea,
16
+ * which a plain HTML submit could not re-enable. Supplying `onSave` instead
17
+ * intercepts the submit and hands the host the same decision.
18
+ */
19
+ import { Badge, Button, Card } from '@happyvertical/smrt-ui/ui';
20
+ import type { PromptSettingsChange, PromptSettingsView } from '../types.js';
21
+ import {
22
+ appRevertPreview,
23
+ isTemplateEditable,
24
+ supplyingLevelLabel,
25
+ tenantRevertPreview,
26
+ } from '../types.js';
27
+
28
+ export interface Props {
29
+ /** The prompts to manage, in the order they should be rendered. */
30
+ prompts?: PromptSettingsView[];
31
+ /** Column heading for the tenant-scope editor. */
32
+ tenantLabel?: string;
33
+ /**
34
+ * Render the app-scope column. Off by default: an app with no
35
+ * platform-admin tier has nothing to put there.
36
+ */
37
+ showApp?: boolean;
38
+ /**
39
+ * Let the operator change the app column. Ignored unless `showApp`. When
40
+ * false the column is rendered read-only, which is how a tenant admin sees
41
+ * the app-wide default their own override is layered on.
42
+ */
43
+ appEditable?: boolean;
44
+ /** Column heading for the app-scope editor. */
45
+ appLabel?: string;
46
+ /** Disable every control while a save is in flight. */
47
+ busy?: boolean;
48
+ /** Success text to show above the list. */
49
+ message?: string | null;
50
+ /** Error text to show above the list. */
51
+ error?: string | null;
52
+ /** Text for the empty state. */
53
+ emptyMessage?: string;
54
+ /**
55
+ * Identity of what is being edited (typically the tenant id). Unsaved edits
56
+ * are discarded whenever this changes — or, when it is omitted, whenever
57
+ * `prompts` is replaced with a new array, which is what a reloaded server
58
+ * load produces. Without that, a row edited for one tenant would carry its
59
+ * unsaved text into the next tenant's rows under the same key.
60
+ */
61
+ contextKey?: unknown;
62
+ /** Label for each row's submit control. */
63
+ saveLabel?: string;
64
+ /**
65
+ * SvelteKit form action for each row's `<form>` (e.g. `?/savePrompt`). Omit
66
+ * when driving the panel entirely through {@link Props.onSave}.
67
+ */
68
+ formAction?: string;
69
+ /**
70
+ * Called with the requested change instead of submitting the form. The host
71
+ * performs its own permission check and the write.
72
+ */
73
+ onSave?: (change: PromptSettingsChange) => void;
74
+ }
75
+
76
+ const {
77
+ prompts = [],
78
+ tenantLabel = 'Tenant override',
79
+ showApp = false,
80
+ appEditable = false,
81
+ appLabel = 'App override',
82
+ busy = false,
83
+ contextKey,
84
+ message = null,
85
+ error = null,
86
+ emptyMessage = 'No prompts are registered yet. Definitions appear here once they are registered from code.',
87
+ saveLabel = 'Save',
88
+ formAction,
89
+ onSave,
90
+ }: Props = $props();
91
+
92
+ const appIsEditable = $derived(showApp && appEditable);
93
+ const canSubmit = $derived(!busy && (onSave != null || formAction != null));
94
+
95
+ /**
96
+ * Remount the rows when the editing context changes, discarding unsaved
97
+ * edits. Without this an operator's unsaved text would survive a reload or a
98
+ * tenant switch and then be submitted against the new rows.
99
+ */
100
+ const resetKey = $derived(contextKey ?? prompts);
101
+
102
+ function submit(event: SubmitEvent, prompt: PromptSettingsView): void {
103
+ // A non-editable row's controls are disabled, and disabled controls are
104
+ // absent from FormData — a submit would read as "unchecked" and revert an
105
+ // existing override. Such a row is read-only: it never submits.
106
+ if (!isTemplateEditable(prompt)) {
107
+ event.preventDefault();
108
+ return;
109
+ }
110
+ if (!onSave) return;
111
+ event.preventDefault();
112
+ const fields = new FormData(event.currentTarget as HTMLFormElement);
113
+ const change: PromptSettingsChange = {
114
+ key: prompt.key,
115
+ tenantTemplate: fields.has('tenantOverride')
116
+ ? String(fields.get('tenantTemplate') ?? '')
117
+ : null,
118
+ };
119
+ if (appIsEditable) {
120
+ change.appTemplate = fields.has('appOverride')
121
+ ? String(fields.get('appTemplate') ?? '')
122
+ : null;
123
+ }
124
+ onSave(change);
125
+ }
126
+ </script>
127
+
128
+ <section class="prompt-settings" data-testid="prompt-settings-panel">
129
+ {#if message}
130
+ <p class="ps-flash" role="status">{message}</p>
131
+ {/if}
132
+ {#if error}
133
+ <p class="ps-flash ps-flash-error" role="alert">{error}</p>
134
+ {/if}
135
+
136
+ {#key resetKey}
137
+ {#each prompts as prompt (prompt.key)}
138
+ <Card variant="outlined">
139
+ <div class="ps-row">
140
+ <div class="ps-copy">
141
+ <div class="ps-title-row">
142
+ <h3 class="ps-title">{prompt.description || prompt.key}</h3>
143
+ <Badge variant="default" size="sm">
144
+ {supplyingLevelLabel(prompt.supplyingLevel)}
145
+ </Badge>
146
+ </div>
147
+ <code class="ps-key">{prompt.key}</code>
148
+ <pre class="ps-effective">{prompt.effectiveTemplate}</pre>
149
+ </div>
150
+
151
+ <form
152
+ class="ps-controls"
153
+ method="POST"
154
+ action={formAction}
155
+ onsubmit={(event) => submit(event, prompt)}
156
+ >
157
+ <input type="hidden" name="key" value={prompt.key} />
158
+
159
+ {#if showApp}
160
+ {#if appIsEditable}
161
+ <div class="ps-field">
162
+ <label class="ps-toggle">
163
+ <input
164
+ type="checkbox"
165
+ name="appOverride"
166
+ checked={prompt.appTemplate != null}
167
+ disabled={busy || !isTemplateEditable(prompt)}
168
+ />
169
+ {appLabel}
170
+ </label>
171
+ <textarea
172
+ class="ps-textarea"
173
+ name="appTemplate"
174
+ aria-label={appLabel}
175
+ rows="3"
176
+ disabled={busy || !isTemplateEditable(prompt)}
177
+ value={prompt.appTemplate ?? appRevertPreview(prompt)}
178
+ ></textarea>
179
+ <p class="ps-hint">
180
+ Unchecked reverts to: {appRevertPreview(prompt)}
181
+ </p>
182
+ </div>
183
+ {:else}
184
+ <div class="ps-field">
185
+ <span class="ps-field-label">{appLabel}</span>
186
+ <p class="ps-readonly">
187
+ {prompt.appTemplate ?? appRevertPreview(prompt)}
188
+ </p>
189
+ </div>
190
+ {/if}
191
+ {/if}
192
+
193
+ <div class="ps-field">
194
+ <label class="ps-toggle">
195
+ <input
196
+ type="checkbox"
197
+ name="tenantOverride"
198
+ checked={prompt.tenantTemplate != null}
199
+ disabled={busy || !isTemplateEditable(prompt)}
200
+ />
201
+ {tenantLabel}
202
+ </label>
203
+ <textarea
204
+ class="ps-textarea"
205
+ name="tenantTemplate"
206
+ aria-label={tenantLabel}
207
+ rows="4"
208
+ disabled={busy || !isTemplateEditable(prompt)}
209
+ value={prompt.tenantTemplate ?? tenantRevertPreview(prompt)}
210
+ ></textarea>
211
+ <p class="ps-hint">
212
+ Unchecked reverts to: {tenantRevertPreview(prompt)}
213
+ </p>
214
+ </div>
215
+
216
+ <Button
217
+ type="submit"
218
+ variant="primary"
219
+ size="sm"
220
+ disabled={!canSubmit || !isTemplateEditable(prompt)}
221
+ >
222
+ {saveLabel}
223
+ </Button>
224
+ </form>
225
+ </div>
226
+ </Card>
227
+ {:else}
228
+ <p class="ps-empty">{emptyMessage}</p>
229
+ {/each}
230
+ {/key}
231
+ </section>
232
+
233
+ <style>
234
+ .prompt-settings {
235
+ display: flex;
236
+ flex-direction: column;
237
+ gap: 1rem;
238
+ }
239
+
240
+ .ps-flash {
241
+ margin: 0;
242
+ padding: 0.625rem 0.75rem;
243
+ border-radius: 0.375rem;
244
+ background: var(--color-surface-muted, #f3f4f6);
245
+ }
246
+
247
+ .ps-flash-error {
248
+ color: var(--color-error-text, #991b1b);
249
+ background: var(--color-error-surface, #fef2f2);
250
+ }
251
+
252
+ .ps-empty {
253
+ margin: 0;
254
+ color: var(--color-text-muted, #6b7280);
255
+ font-style: italic;
256
+ }
257
+
258
+ .ps-row {
259
+ display: grid;
260
+ grid-template-columns: minmax(0, 1fr) minmax(18rem, 26rem);
261
+ gap: 1rem;
262
+ align-items: start;
263
+ }
264
+
265
+ .ps-copy {
266
+ min-width: 0;
267
+ display: flex;
268
+ flex-direction: column;
269
+ gap: 0.25rem;
270
+ }
271
+
272
+ .ps-title-row {
273
+ display: flex;
274
+ align-items: center;
275
+ justify-content: space-between;
276
+ gap: 0.5rem;
277
+ }
278
+
279
+ .ps-title {
280
+ margin: 0;
281
+ font-size: 1rem;
282
+ line-height: 1.25;
283
+ }
284
+
285
+ .ps-key {
286
+ font-size: 0.8125rem;
287
+ color: var(--color-text-muted, #6b7280);
288
+ overflow-wrap: anywhere;
289
+ }
290
+
291
+ .ps-effective {
292
+ margin: 0;
293
+ padding: 0.5rem;
294
+ border-radius: 0.375rem;
295
+ background: var(--color-surface-muted, #f3f4f6);
296
+ white-space: pre-wrap;
297
+ overflow-wrap: anywhere;
298
+ font-family: inherit;
299
+ font-size: 0.875rem;
300
+ }
301
+
302
+ .ps-controls {
303
+ display: flex;
304
+ flex-direction: column;
305
+ gap: 0.75rem;
306
+ }
307
+
308
+ .ps-field {
309
+ min-width: 0;
310
+ display: flex;
311
+ flex-direction: column;
312
+ gap: 0.25rem;
313
+ }
314
+
315
+ .ps-field-label {
316
+ font-size: 0.8125rem;
317
+ color: var(--color-text-muted, #6b7280);
318
+ }
319
+
320
+ .ps-toggle {
321
+ display: flex;
322
+ align-items: center;
323
+ gap: 0.375rem;
324
+ font-size: 0.8125rem;
325
+ color: var(--color-text-muted, #6b7280);
326
+ }
327
+
328
+ .ps-textarea {
329
+ width: 100%;
330
+ padding: 0.5rem;
331
+ border: 1px solid var(--color-border, #d1d5db);
332
+ border-radius: 0.375rem;
333
+ background: var(--color-surface, #fff);
334
+ color: inherit;
335
+ font: inherit;
336
+ resize: vertical;
337
+ }
338
+
339
+ .ps-hint,
340
+ .ps-readonly {
341
+ margin: 0;
342
+ font-size: 0.8125rem;
343
+ color: var(--color-text-muted, #6b7280);
344
+ line-height: 1.45;
345
+ overflow-wrap: anywhere;
346
+ }
347
+
348
+ @media (max-width: 860px) {
349
+ .ps-row {
350
+ grid-template-columns: 1fr;
351
+ }
352
+ }
353
+ </style>
@@ -0,0 +1,52 @@
1
+ import type { PromptSettingsChange, PromptSettingsView } from '../types.js';
2
+ export interface Props {
3
+ /** The prompts to manage, in the order they should be rendered. */
4
+ prompts?: PromptSettingsView[];
5
+ /** Column heading for the tenant-scope editor. */
6
+ tenantLabel?: string;
7
+ /**
8
+ * Render the app-scope column. Off by default: an app with no
9
+ * platform-admin tier has nothing to put there.
10
+ */
11
+ showApp?: boolean;
12
+ /**
13
+ * Let the operator change the app column. Ignored unless `showApp`. When
14
+ * false the column is rendered read-only, which is how a tenant admin sees
15
+ * the app-wide default their own override is layered on.
16
+ */
17
+ appEditable?: boolean;
18
+ /** Column heading for the app-scope editor. */
19
+ appLabel?: string;
20
+ /** Disable every control while a save is in flight. */
21
+ busy?: boolean;
22
+ /** Success text to show above the list. */
23
+ message?: string | null;
24
+ /** Error text to show above the list. */
25
+ error?: string | null;
26
+ /** Text for the empty state. */
27
+ emptyMessage?: string;
28
+ /**
29
+ * Identity of what is being edited (typically the tenant id). Unsaved edits
30
+ * are discarded whenever this changes — or, when it is omitted, whenever
31
+ * `prompts` is replaced with a new array, which is what a reloaded server
32
+ * load produces. Without that, a row edited for one tenant would carry its
33
+ * unsaved text into the next tenant's rows under the same key.
34
+ */
35
+ contextKey?: unknown;
36
+ /** Label for each row's submit control. */
37
+ saveLabel?: string;
38
+ /**
39
+ * SvelteKit form action for each row's `<form>` (e.g. `?/savePrompt`). Omit
40
+ * when driving the panel entirely through {@link Props.onSave}.
41
+ */
42
+ formAction?: string;
43
+ /**
44
+ * Called with the requested change instead of submitting the form. The host
45
+ * performs its own permission check and the write.
46
+ */
47
+ onSave?: (change: PromptSettingsChange) => void;
48
+ }
49
+ declare const PromptSettingsPanel: import("svelte").Component<Props, {}, "">;
50
+ type PromptSettingsPanel = ReturnType<typeof PromptSettingsPanel>;
51
+ export default PromptSettingsPanel;
52
+ //# sourceMappingURL=PromptSettingsPanel.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptSettingsPanel.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/PromptSettingsPanel.svelte.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAS5E,MAAM,WAAW,KAAK;IACpB,mEAAmE;IACnE,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC/B,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gCAAgC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACjD;AAuID,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @happyvertical/smrt-prompts/svelte
3
+ *
4
+ * Optional Svelte 5 UI for prompt management. Presentational only: the panel
5
+ * takes rows and callbacks, does no fetching, and makes no authorization
6
+ * decision. Hosts render it from a server load that used
7
+ * `PromptSettingsService` and wire saves to their own permission-checked
8
+ * route. The root `@happyvertical/smrt-prompts` export stays Svelte-free.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import type { ComponentProps } from 'svelte';
13
+ import PromptSettingsPanel from './components/PromptSettingsPanel.svelte';
14
+ export { PromptSettingsPanel };
15
+ export type PromptSettingsPanelProps = ComponentProps<typeof PromptSettingsPanel>;
16
+ export { appRevertPreview, isTemplateEditable, type PromptSettingsChange, type PromptSettingsSupplyingLevel, type PromptSettingsView, supplyingLevelLabel, tenantRevertPreview, } from './types.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,mBAAmB,MAAM,yCAAyC,CAAC;AAE1E,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAC/B,MAAM,MAAM,wBAAwB,GAAG,cAAc,CACnD,OAAO,mBAAmB,CAC3B,CAAC;AAEF,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,kBAAkB,EACvB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @happyvertical/smrt-prompts/svelte
3
+ *
4
+ * Optional Svelte 5 UI for prompt management. Presentational only: the panel
5
+ * takes rows and callbacks, does no fetching, and makes no authorization
6
+ * decision. Hosts render it from a server load that used
7
+ * `PromptSettingsService` and wire saves to their own permission-checked
8
+ * route. The root `@happyvertical/smrt-prompts` export stays Svelte-free.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import PromptSettingsPanel from './components/PromptSettingsPanel.svelte';
13
+ export { PromptSettingsPanel };
14
+ export { appRevertPreview, isTemplateEditable, supplyingLevelLabel, tenantRevertPreview, } from './types.js';
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Presentational types for the prompt management UI.
3
+ *
4
+ * Deliberately free of the `@smrt()` model classes and of `@happyvertical/smrt-core`
5
+ * so the Svelte bundle stays a thin presentation layer. Field names match
6
+ * `PromptSettingsRow` produced by `PromptSettingsService.listPromptSettings()`,
7
+ * so a row is structurally assignable to {@link PromptSettingsView} with no
8
+ * mapping step.
9
+ *
10
+ * @module
11
+ */
12
+ /** Which level supplied a prompt's effective template. */
13
+ export type PromptSettingsSupplyingLevel = 'default' | 'config' | 'app' | 'tenant';
14
+ /** A render-ready view of one prompt's settings. */
15
+ export interface PromptSettingsView {
16
+ /**
17
+ * The persisted identifier. Shown verbatim so an operator can correlate the
18
+ * row with code — renaming a key orphans its overrides, so it is stable
19
+ * enough to quote.
20
+ */
21
+ key: string;
22
+ /** Human description; falls back to the key when empty. */
23
+ description?: string;
24
+ /** The text actually in effect for the requested tenant (unrendered). */
25
+ effectiveTemplate: string;
26
+ /** Which level supplied {@link effectiveTemplate}. */
27
+ supplyingLevel?: PromptSettingsSupplyingLevel;
28
+ /** Whether a stored override may change the template; hides the editor when `false`. */
29
+ editable?: {
30
+ template?: boolean;
31
+ };
32
+ /** The app-level override's text, or `null`/absent when there is none. */
33
+ appTemplate?: string | null;
34
+ /** The tenant-level override's text, or `null`/absent when there is none. */
35
+ tenantTemplate?: string | null;
36
+ /** What the **app** scope's "revert to default" produces. */
37
+ appDefaultTemplate?: string;
38
+ /**
39
+ * What the **tenant** scope's "revert to default" produces. `null`/absent
40
+ * when not known (e.g. no tenant was requested) — the panel then falls back
41
+ * to {@link appDefaultTemplate} or {@link effectiveTemplate} rather than
42
+ * claiming a value nothing computed.
43
+ */
44
+ inheritedTemplate?: string | null;
45
+ }
46
+ /** One override change requested from the panel. */
47
+ export interface PromptSettingsChange {
48
+ /** The prompt the operator was editing. */
49
+ key: string;
50
+ /**
51
+ * Requested tenant-scope text, or `null` to revert (return the tenant scope
52
+ * to whatever it inherits).
53
+ */
54
+ tenantTemplate: string | null;
55
+ /**
56
+ * Requested app-scope text, or `null` to revert — present only when the
57
+ * panel rendered an editable app column.
58
+ */
59
+ appTemplate?: string | null;
60
+ }
61
+ /** Human label for {@link PromptSettingsView.supplyingLevel}. */
62
+ export declare function supplyingLevelLabel(level: PromptSettingsSupplyingLevel | undefined): string;
63
+ /**
64
+ * What the tenant scope's "revert to default" control returns to: the app
65
+ * override if there is one, otherwise the config/registry value. Falls back to
66
+ * {@link PromptSettingsView.effectiveTemplate} only when the row supplies
67
+ * neither computed fallback (e.g. a minimal test fixture), rather than
68
+ * rendering nothing.
69
+ */
70
+ export declare function tenantRevertPreview(view: PromptSettingsView): string;
71
+ /** What the app scope's "revert to default" control returns to. */
72
+ export declare function appRevertPreview(view: PromptSettingsView): string;
73
+ /** Whether the panel may offer an editor for this prompt's template at all. */
74
+ export declare function isTemplateEditable(view: PromptSettingsView): boolean;
75
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/svelte/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,0DAA0D;AAC1D,MAAM,MAAM,4BAA4B,GACpC,SAAS,GACT,QAAQ,GACR,KAAK,GACL,QAAQ,CAAC;AAEb,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,cAAc,CAAC,EAAE,4BAA4B,CAAC;IAC9C,wFAAwF;IACxF,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAClC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,oDAAoD;AACpD,MAAM,WAAW,oBAAoB;IACnC,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,iEAAiE;AACjE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,4BAA4B,GAAG,SAAS,GAC9C,MAAM,CAWR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAIpE;AAED,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAEjE;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAEpE"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Presentational types for the prompt management UI.
3
+ *
4
+ * Deliberately free of the `@smrt()` model classes and of `@happyvertical/smrt-core`
5
+ * so the Svelte bundle stays a thin presentation layer. Field names match
6
+ * `PromptSettingsRow` produced by `PromptSettingsService.listPromptSettings()`,
7
+ * so a row is structurally assignable to {@link PromptSettingsView} with no
8
+ * mapping step.
9
+ *
10
+ * @module
11
+ */
12
+ /** Human label for {@link PromptSettingsView.supplyingLevel}. */
13
+ export function supplyingLevelLabel(level) {
14
+ switch (level) {
15
+ case 'tenant':
16
+ return 'Tenant override';
17
+ case 'app':
18
+ return 'App override';
19
+ case 'config':
20
+ return 'Config override';
21
+ default:
22
+ return 'Registry default';
23
+ }
24
+ }
25
+ /**
26
+ * What the tenant scope's "revert to default" control returns to: the app
27
+ * override if there is one, otherwise the config/registry value. Falls back to
28
+ * {@link PromptSettingsView.effectiveTemplate} only when the row supplies
29
+ * neither computed fallback (e.g. a minimal test fixture), rather than
30
+ * rendering nothing.
31
+ */
32
+ export function tenantRevertPreview(view) {
33
+ return (view.inheritedTemplate ?? view.appDefaultTemplate ?? view.effectiveTemplate);
34
+ }
35
+ /** What the app scope's "revert to default" control returns to. */
36
+ export function appRevertPreview(view) {
37
+ return view.appDefaultTemplate ?? view.effectiveTemplate;
38
+ }
39
+ /** Whether the panel may offer an editor for this prompt's template at all. */
40
+ export function isTemplateEditable(view) {
41
+ return view.editable?.template !== false;
42
+ }