@happyvertical/smrt-inference 0.0.0-stage → 0.60.16
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/AGENTS.md +206 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +73 -2
- package/agents/fusions.md +105 -0
- package/agents/hosted.md +161 -0
- package/agents/resolver.md +65 -0
- package/agents/settings.md +107 -0
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/chunks/InferenceOverrideCollection-Dat4TrK5.js +423 -0
- package/dist/chunks/InferenceOverrideCollection-Dat4TrK5.js.map +1 -0
- package/dist/chunks/provider-config-BSpIQRVM.js +1873 -0
- package/dist/chunks/provider-config-BSpIQRVM.js.map +1 -0
- package/dist/classify.d.ts +32 -0
- package/dist/classify.d.ts.map +1 -0
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/errors.d.ts +51 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/executor.d.ts +45 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/fusion-store.d.ts +16 -0
- package/dist/fusion-store.d.ts.map +1 -0
- package/dist/fusion.d.ts +155 -0
- package/dist/fusion.d.ts.map +1 -0
- package/dist/gate.d.ts +143 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +94 -0
- package/dist/gate.js.map +1 -0
- package/dist/hosted.d.ts +461 -0
- package/dist/hosted.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +453 -0
- package/dist/models/InferenceOverride.d.ts +38 -0
- package/dist/models/InferenceOverride.d.ts.map +1 -0
- package/dist/models/InferenceOverrideCollection.d.ts +35 -0
- package/dist/models/InferenceOverrideCollection.d.ts.map +1 -0
- package/dist/models.d.ts +11 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +2 -0
- package/dist/node.d.ts +110 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +1414 -0
- package/dist/node.js.map +1 -0
- package/dist/provider-config.d.ts +113 -0
- package/dist/provider-config.d.ts.map +1 -0
- package/dist/register.d.ts +30 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/resolver.d.ts +166 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +291 -0
- package/dist/resolver.js.map +1 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1138 -0
- package/dist/server.js.map +1 -0
- package/dist/settings/cache.d.ts +5 -0
- package/dist/settings/cache.d.ts.map +1 -0
- package/dist/settings/keys.d.ts +70 -0
- package/dist/settings/keys.d.ts.map +1 -0
- package/dist/settings/layers.d.ts +68 -0
- package/dist/settings/layers.d.ts.map +1 -0
- package/dist/settings/override-service.d.ts +119 -0
- package/dist/settings/override-service.d.ts.map +1 -0
- package/dist/settings/preferences.d.ts +137 -0
- package/dist/settings/preferences.d.ts.map +1 -0
- package/dist/settings/resolver.d.ts +41 -0
- package/dist/settings/resolver.d.ts.map +1 -0
- package/dist/settings/settings-service.d.ts +355 -0
- package/dist/settings/settings-service.d.ts.map +1 -0
- package/dist/settings/targets.d.ts +112 -0
- package/dist/settings/targets.d.ts.map +1 -0
- package/dist/settings/transcripts.d.ts +33 -0
- package/dist/settings/transcripts.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +341 -0
- package/dist/smrt-knowledge.okf.md +80 -0
- package/dist/svelte/components/InferenceAliasEditor.svelte +210 -0
- package/dist/svelte/components/InferenceAliasEditor.svelte.d.ts +13 -0
- package/dist/svelte/components/InferenceAliasEditor.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InferenceDefaultView.svelte +330 -0
- package/dist/svelte/components/InferenceDefaultView.svelte.d.ts +15 -0
- package/dist/svelte/components/InferenceDefaultView.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InferenceFusionList.svelte +141 -0
- package/dist/svelte/components/InferenceFusionList.svelte.d.ts +16 -0
- package/dist/svelte/components/InferenceFusionList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InferenceSettingsPanel.svelte +392 -0
- package/dist/svelte/components/InferenceSettingsPanel.svelte.d.ts +84 -0
- package/dist/svelte/components/InferenceSettingsPanel.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InferenceTierRow.svelte +199 -0
- package/dist/svelte/components/InferenceTierRow.svelte.d.ts +14 -0
- package/dist/svelte/components/InferenceTierRow.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InferenceTranscriptSettings.svelte +165 -0
- package/dist/svelte/components/InferenceTranscriptSettings.svelte.d.ts +18 -0
- package/dist/svelte/components/InferenceTranscriptSettings.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InferenceUsageTable.svelte +177 -0
- package/dist/svelte/components/InferenceUsageTable.svelte.d.ts +21 -0
- package/dist/svelte/components/InferenceUsageTable.svelte.d.ts.map +1 -0
- package/dist/svelte/index.d.ts +17 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +14 -0
- package/dist/svelte/types.d.ts +262 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +124 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +105 -3
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* One rung of the tier ladder: "same as default", a model, an alias or a
|
|
4
|
+
* fusion. In the tenant scope, targets the allow-list does not open are
|
|
5
|
+
* disabled (display only; the server enforces the list on every write).
|
|
6
|
+
*/
|
|
7
|
+
import { untrack } from 'svelte';
|
|
8
|
+
import type {
|
|
9
|
+
InferenceAliasView,
|
|
10
|
+
InferenceFusionView,
|
|
11
|
+
InferenceProviderView,
|
|
12
|
+
InferenceSettingsScope,
|
|
13
|
+
InferenceTargetView,
|
|
14
|
+
InferenceTierChange,
|
|
15
|
+
InferenceTierView,
|
|
16
|
+
} from '../types.js';
|
|
17
|
+
import {
|
|
18
|
+
inferenceLevelLabel,
|
|
19
|
+
isRefAllowed,
|
|
20
|
+
targetViewRef,
|
|
21
|
+
tierRevertPreview,
|
|
22
|
+
} from '../types.js';
|
|
23
|
+
|
|
24
|
+
interface InferenceTierRowProps {
|
|
25
|
+
row: InferenceTierView;
|
|
26
|
+
scope: InferenceSettingsScope;
|
|
27
|
+
providers: InferenceProviderView[];
|
|
28
|
+
aliases: InferenceAliasView[];
|
|
29
|
+
fusions: InferenceFusionView[];
|
|
30
|
+
busy: boolean;
|
|
31
|
+
onSaveTier?: (change: InferenceTierChange) => void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const {
|
|
35
|
+
row,
|
|
36
|
+
scope,
|
|
37
|
+
providers,
|
|
38
|
+
aliases,
|
|
39
|
+
fusions,
|
|
40
|
+
busy,
|
|
41
|
+
onSaveTier,
|
|
42
|
+
}: InferenceTierRowProps = $props();
|
|
43
|
+
|
|
44
|
+
type Kind = 'default' | 'model' | 'alias' | 'fusion';
|
|
45
|
+
|
|
46
|
+
function kindOf(target: InferenceTargetView | null | undefined): Kind {
|
|
47
|
+
if (!target || Object.keys(target).length === 0) return 'default';
|
|
48
|
+
if (target.kind === 'fusion' || target.fusion) return 'fusion';
|
|
49
|
+
if (target.alias) return 'alias';
|
|
50
|
+
return 'model';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const own = untrack(
|
|
54
|
+
() => (scope === 'app' ? row.appTarget : row.tenantTarget) ?? null,
|
|
55
|
+
);
|
|
56
|
+
let kind = $state<Kind>(kindOf(own));
|
|
57
|
+
let provider = $state(own?.provider ?? '');
|
|
58
|
+
let model = $state(own?.model ?? '');
|
|
59
|
+
let alias = $state(own?.alias ?? '');
|
|
60
|
+
let fusion = $state(own?.fusion ?? '');
|
|
61
|
+
|
|
62
|
+
const restricted = $derived(scope === 'tenant');
|
|
63
|
+
const allowed = (target: InferenceTargetView) =>
|
|
64
|
+
!restricted || isRefAllowed(targetViewRef(target), row.tenantAllowList);
|
|
65
|
+
const modelAllowed = $derived(
|
|
66
|
+
!restricted ||
|
|
67
|
+
(row.tenantAllowList ?? []).some(
|
|
68
|
+
(pattern) => pattern === '*' || pattern.startsWith('model:'),
|
|
69
|
+
),
|
|
70
|
+
);
|
|
71
|
+
const aliasAllowed = $derived(
|
|
72
|
+
aliases.some((entry) => allowed({ alias: entry.name })),
|
|
73
|
+
);
|
|
74
|
+
const fusionAllowed = $derived(
|
|
75
|
+
fusions.some((entry) => allowed({ kind: 'fusion', fusion: entry.name })),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
function target(): InferenceTargetView | null {
|
|
79
|
+
if (kind === 'model') {
|
|
80
|
+
return provider
|
|
81
|
+
? { provider, model: model.trim() }
|
|
82
|
+
: { model: model.trim() };
|
|
83
|
+
}
|
|
84
|
+
if (kind === 'alias') return { alias };
|
|
85
|
+
if (kind === 'fusion') return { kind: 'fusion', fusion };
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function submit(event: SubmitEvent): void {
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
onSaveTier?.({ tier: row.tier, scope, target: target() });
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<form class="itr" onsubmit={submit} data-testid={`inference-tier-${row.tier}`}>
|
|
96
|
+
<div class="itr-head">
|
|
97
|
+
<strong class="itr-tier">{row.tier}</strong>
|
|
98
|
+
<span class="itr-effective">{row.effectiveLabel}</span>
|
|
99
|
+
<span class="itr-level">{inferenceLevelLabel(row.supplyingLevel)}</span>
|
|
100
|
+
</div>
|
|
101
|
+
{#if restricted && row.tenantBlocked}
|
|
102
|
+
<p class="itr-note" role="note">
|
|
103
|
+
This tenant binding is no longer on the allow-list and is not in effect.
|
|
104
|
+
</p>
|
|
105
|
+
{/if}
|
|
106
|
+
<div class="itr-controls">
|
|
107
|
+
<label>
|
|
108
|
+
<span class="itr-label">Target for {row.tier}</span>
|
|
109
|
+
<select name="kind" bind:value={kind} disabled={busy}>
|
|
110
|
+
<option value="default">Same as default</option>
|
|
111
|
+
<option value="model" disabled={!modelAllowed}>Model</option>
|
|
112
|
+
<option value="alias" disabled={!aliasAllowed}>Alias</option>
|
|
113
|
+
<option value="fusion" disabled={!fusionAllowed}>Fusion</option>
|
|
114
|
+
</select>
|
|
115
|
+
</label>
|
|
116
|
+
{#if kind === 'model'}
|
|
117
|
+
<label>
|
|
118
|
+
<span class="itr-label">Provider</span>
|
|
119
|
+
<select name="provider" bind:value={provider} disabled={busy}>
|
|
120
|
+
<option value="">Configured provider</option>
|
|
121
|
+
{#each providers.filter((option) => option.kind === 'provider') as option (option.id)}
|
|
122
|
+
<option value={option.id}>{option.label}</option>
|
|
123
|
+
{/each}
|
|
124
|
+
</select>
|
|
125
|
+
</label>
|
|
126
|
+
<label>
|
|
127
|
+
<span class="itr-label">Model</span>
|
|
128
|
+
<input name="model" bind:value={model} required disabled={busy} />
|
|
129
|
+
</label>
|
|
130
|
+
{:else if kind === 'alias'}
|
|
131
|
+
<label>
|
|
132
|
+
<span class="itr-label">Alias</span>
|
|
133
|
+
<select name="alias" bind:value={alias} required disabled={busy}>
|
|
134
|
+
<option value="" disabled>Choose an alias</option>
|
|
135
|
+
{#each aliases as entry (entry.name)}
|
|
136
|
+
<option value={entry.name} disabled={!allowed({ alias: entry.name })}>{entry.name}</option>
|
|
137
|
+
{/each}
|
|
138
|
+
</select>
|
|
139
|
+
</label>
|
|
140
|
+
{:else if kind === 'fusion'}
|
|
141
|
+
<label>
|
|
142
|
+
<span class="itr-label">Fusion</span>
|
|
143
|
+
<select name="fusion" bind:value={fusion} required disabled={busy}>
|
|
144
|
+
<option value="" disabled>Choose a fusion</option>
|
|
145
|
+
{#each fusions as entry (entry.name)}
|
|
146
|
+
<option value={entry.name} disabled={!allowed({ kind: 'fusion', fusion: entry.name })}>
|
|
147
|
+
{entry.name}
|
|
148
|
+
</option>
|
|
149
|
+
{/each}
|
|
150
|
+
</select>
|
|
151
|
+
</label>
|
|
152
|
+
{/if}
|
|
153
|
+
<button type="submit" disabled={busy || !onSaveTier}>Save</button>
|
|
154
|
+
</div>
|
|
155
|
+
<p class="itr-hint">"Same as default" reverts to: {tierRevertPreview(row, scope)}</p>
|
|
156
|
+
</form>
|
|
157
|
+
|
|
158
|
+
<style>
|
|
159
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
160
|
+
@layer smrt.theme {
|
|
161
|
+
.itr {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
gap: 0.375rem;
|
|
165
|
+
padding: 0.5rem 0;
|
|
166
|
+
border-bottom: var(--smrt-hairline);
|
|
167
|
+
}
|
|
168
|
+
.itr-head {
|
|
169
|
+
display: flex;
|
|
170
|
+
gap: 0.75rem;
|
|
171
|
+
align-items: baseline;
|
|
172
|
+
flex-wrap: wrap;
|
|
173
|
+
}
|
|
174
|
+
.itr-tier {
|
|
175
|
+
text-transform: capitalize;
|
|
176
|
+
min-width: 4rem;
|
|
177
|
+
}
|
|
178
|
+
.itr-level,
|
|
179
|
+
.itr-hint,
|
|
180
|
+
.itr-note,
|
|
181
|
+
.itr-label {
|
|
182
|
+
font-size: 0.8125rem;
|
|
183
|
+
color: var(--smrt-color-on-surface-variant);
|
|
184
|
+
}
|
|
185
|
+
.itr-hint,
|
|
186
|
+
.itr-note {
|
|
187
|
+
margin: 0;
|
|
188
|
+
}
|
|
189
|
+
.itr-label {
|
|
190
|
+
display: block;
|
|
191
|
+
}
|
|
192
|
+
.itr-controls {
|
|
193
|
+
display: flex;
|
|
194
|
+
gap: 0.5rem;
|
|
195
|
+
align-items: flex-end;
|
|
196
|
+
flex-wrap: wrap;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InferenceAliasView, InferenceFusionView, InferenceProviderView, InferenceSettingsScope, InferenceTierChange, InferenceTierView } from '../types.js';
|
|
2
|
+
interface InferenceTierRowProps {
|
|
3
|
+
row: InferenceTierView;
|
|
4
|
+
scope: InferenceSettingsScope;
|
|
5
|
+
providers: InferenceProviderView[];
|
|
6
|
+
aliases: InferenceAliasView[];
|
|
7
|
+
fusions: InferenceFusionView[];
|
|
8
|
+
busy: boolean;
|
|
9
|
+
onSaveTier?: (change: InferenceTierChange) => void;
|
|
10
|
+
}
|
|
11
|
+
declare const InferenceTierRow: import("svelte").Component<InferenceTierRowProps, {}, "">;
|
|
12
|
+
type InferenceTierRow = ReturnType<typeof InferenceTierRow>;
|
|
13
|
+
export default InferenceTierRow;
|
|
14
|
+
//# sourceMappingURL=InferenceTierRow.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InferenceTierRow.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/InferenceTierRow.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EAEtB,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AASrB,UAAU,qBAAqB;IAC7B,GAAG,EAAE,iBAAiB,CAAC;IACvB,KAAK,EAAE,sBAAsB,CAAC;IAC9B,SAAS,EAAE,qBAAqB,EAAE,CAAC;IACnC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACpD;AAyID,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* The app's transcript setting in Advanced (#4781). Read-only unless the
|
|
4
|
+
* host passes `editable` (platform admin, `appEditable` on the panel):
|
|
5
|
+
* tenants cannot override transcripts, and a save always writes the app
|
|
6
|
+
* row. Retention is the sweep's policy and stays read-only. Renders no
|
|
7
|
+
* transcript content.
|
|
8
|
+
*/
|
|
9
|
+
import type {
|
|
10
|
+
InferenceTranscriptSettingsChange,
|
|
11
|
+
InferenceTranscriptSettingsView,
|
|
12
|
+
} from '../types.js';
|
|
13
|
+
|
|
14
|
+
interface InferenceTranscriptSettingsProps {
|
|
15
|
+
settings: InferenceTranscriptSettingsView;
|
|
16
|
+
editable: boolean;
|
|
17
|
+
busy: boolean;
|
|
18
|
+
onSaveTranscripts?: (change: InferenceTranscriptSettingsChange) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
settings,
|
|
23
|
+
editable,
|
|
24
|
+
busy,
|
|
25
|
+
onSaveTranscripts,
|
|
26
|
+
}: InferenceTranscriptSettingsProps = $props();
|
|
27
|
+
|
|
28
|
+
const LEVELS: Record<string, string> = {
|
|
29
|
+
env: 'SMRT_INFERENCE_TRANSCRIPTS',
|
|
30
|
+
app: 'App setting',
|
|
31
|
+
config: 'Config',
|
|
32
|
+
default: 'Default',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const retention = $derived(
|
|
36
|
+
settings.retentionDays === null || settings.retentionDays === undefined
|
|
37
|
+
? 'not pruned'
|
|
38
|
+
: `${settings.retentionDays} days`,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
function percent(value: number): string {
|
|
42
|
+
return `${Math.round(value * 1000) / 10}%`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function save(event: SubmitEvent): void {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
if (!onSaveTranscripts) return;
|
|
48
|
+
const data = new FormData(event.currentTarget as HTMLFormElement);
|
|
49
|
+
onSaveTranscripts({
|
|
50
|
+
settings: {
|
|
51
|
+
enabled: data.get('enabled') === 'on',
|
|
52
|
+
sample: Number(data.get('sample')),
|
|
53
|
+
maxBytes: Number(data.get('maxBytes')),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function revert(): void {
|
|
59
|
+
onSaveTranscripts?.({ settings: null });
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<div class="its" data-testid="inference-transcripts">
|
|
64
|
+
{#if settings.envEnabled !== null && settings.envEnabled !== undefined}
|
|
65
|
+
<p class="its-hint" data-testid="inference-transcripts-env">
|
|
66
|
+
SMRT_INFERENCE_TRANSCRIPTS turns transcripts {settings.envEnabled ? 'on' : 'off'} over this setting.
|
|
67
|
+
</p>
|
|
68
|
+
{/if}
|
|
69
|
+
{#if editable}
|
|
70
|
+
<form class="its-form" onsubmit={save} data-testid="inference-transcripts-form">
|
|
71
|
+
<label>
|
|
72
|
+
<input type="checkbox" name="enabled" checked={settings.enabled} disabled={busy} />
|
|
73
|
+
Store transcripts
|
|
74
|
+
</label>
|
|
75
|
+
<label>
|
|
76
|
+
<span class="its-hint">Success sample rate (0–1)</span>
|
|
77
|
+
<input
|
|
78
|
+
type="number"
|
|
79
|
+
name="sample"
|
|
80
|
+
min="0"
|
|
81
|
+
max="1"
|
|
82
|
+
step="0.01"
|
|
83
|
+
value={settings.sample}
|
|
84
|
+
disabled={busy}
|
|
85
|
+
required
|
|
86
|
+
/>
|
|
87
|
+
</label>
|
|
88
|
+
<label>
|
|
89
|
+
<span class="its-hint">Max bytes per call</span>
|
|
90
|
+
<input
|
|
91
|
+
type="number"
|
|
92
|
+
name="maxBytes"
|
|
93
|
+
min="1024"
|
|
94
|
+
step="1"
|
|
95
|
+
value={settings.maxBytes}
|
|
96
|
+
disabled={busy}
|
|
97
|
+
required
|
|
98
|
+
/>
|
|
99
|
+
</label>
|
|
100
|
+
<button type="submit" disabled={busy}>Save</button>
|
|
101
|
+
{#if settings.appValue}
|
|
102
|
+
<button type="button" disabled={busy} onclick={revert}>
|
|
103
|
+
Revert to config{settings.appRevert
|
|
104
|
+
? ` (${settings.appRevert.enabled ? 'on' : 'off'})`
|
|
105
|
+
: ''}
|
|
106
|
+
</button>
|
|
107
|
+
{/if}
|
|
108
|
+
</form>
|
|
109
|
+
{/if}
|
|
110
|
+
<dl class="its-values">
|
|
111
|
+
{#if !editable}
|
|
112
|
+
<dt>Stored</dt>
|
|
113
|
+
<dd data-testid="inference-transcripts-enabled">{settings.enabled ? 'On' : 'Off'}</dd>
|
|
114
|
+
<dt>Success sample rate</dt>
|
|
115
|
+
<dd>{percent(settings.sample)}</dd>
|
|
116
|
+
<dt>Max bytes per call</dt>
|
|
117
|
+
<dd>{settings.maxBytes}</dd>
|
|
118
|
+
{/if}
|
|
119
|
+
<dt>Retention</dt>
|
|
120
|
+
<dd data-testid="inference-transcripts-retention">{retention}</dd>
|
|
121
|
+
{#if settings.supplyingLevel}
|
|
122
|
+
<dt>Set by</dt>
|
|
123
|
+
<dd>{LEVELS[settings.supplyingLevel] ?? settings.supplyingLevel}</dd>
|
|
124
|
+
{/if}
|
|
125
|
+
</dl>
|
|
126
|
+
{#if settings.promptOverrides && settings.promptOverrides.length > 0}
|
|
127
|
+
<p class="its-hint">
|
|
128
|
+
Config sets its own sample rate for {settings.promptOverrides.length} prompt key(s).
|
|
129
|
+
</p>
|
|
130
|
+
{/if}
|
|
131
|
+
{#if !editable}
|
|
132
|
+
<p class="its-hint">App-wide setting; tenants cannot change it.</p>
|
|
133
|
+
{/if}
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<style>
|
|
137
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
138
|
+
@layer smrt.theme {
|
|
139
|
+
.its {
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-direction: column;
|
|
142
|
+
gap: 0.5rem;
|
|
143
|
+
}
|
|
144
|
+
.its-form {
|
|
145
|
+
display: flex;
|
|
146
|
+
gap: 0.75rem;
|
|
147
|
+
align-items: flex-end;
|
|
148
|
+
flex-wrap: wrap;
|
|
149
|
+
}
|
|
150
|
+
.its-values {
|
|
151
|
+
display: grid;
|
|
152
|
+
grid-template-columns: max-content 1fr;
|
|
153
|
+
gap: 0.25rem 0.75rem;
|
|
154
|
+
margin: 0;
|
|
155
|
+
}
|
|
156
|
+
.its-values dd {
|
|
157
|
+
margin: 0;
|
|
158
|
+
}
|
|
159
|
+
.its-hint {
|
|
160
|
+
margin: 0;
|
|
161
|
+
font-size: 0.8125rem;
|
|
162
|
+
color: var(--smrt-color-on-surface-variant);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The app's transcript setting in Advanced (#4781). Read-only unless the
|
|
3
|
+
* host passes `editable` (platform admin, `appEditable` on the panel):
|
|
4
|
+
* tenants cannot override transcripts, and a save always writes the app
|
|
5
|
+
* row. Retention is the sweep's policy and stays read-only. Renders no
|
|
6
|
+
* transcript content.
|
|
7
|
+
*/
|
|
8
|
+
import type { InferenceTranscriptSettingsChange, InferenceTranscriptSettingsView } from '../types.js';
|
|
9
|
+
interface InferenceTranscriptSettingsProps {
|
|
10
|
+
settings: InferenceTranscriptSettingsView;
|
|
11
|
+
editable: boolean;
|
|
12
|
+
busy: boolean;
|
|
13
|
+
onSaveTranscripts?: (change: InferenceTranscriptSettingsChange) => void;
|
|
14
|
+
}
|
|
15
|
+
declare const InferenceTranscriptSettings: import("svelte").Component<InferenceTranscriptSettingsProps, {}, "">;
|
|
16
|
+
type InferenceTranscriptSettings = ReturnType<typeof InferenceTranscriptSettings>;
|
|
17
|
+
export default InferenceTranscriptSettings;
|
|
18
|
+
//# sourceMappingURL=InferenceTranscriptSettings.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InferenceTranscriptSettings.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/InferenceTranscriptSettings.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,iCAAiC,EACjC,+BAA+B,EAChC,MAAM,aAAa,CAAC;AAGrB,UAAU,gCAAgC;IACxC,QAAQ,EAAE,+BAA+B,CAAC;IAC1C,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,iCAAiC,KAAK,IAAI,CAAC;CACzE;AA4GD,QAAA,MAAM,2BAA2B,sEAAwC,CAAC;AAC1E,KAAK,2BAA2B,GAAG,UAAU,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAClF,eAAe,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* The Usage tab: `reportAiUsage()` buckets (#4751) by model, tier, prompt
|
|
4
|
+
* key, fusion and/or template hash. Renders only the dimensions the report
|
|
5
|
+
* was grouped by, so it works with the model dimension alone. With
|
|
6
|
+
* transcript counts (#4781) each row shows how many calls have a stored
|
|
7
|
+
* transcript and links them (and each outcome label) to the host's
|
|
8
|
+
* transcript route; transcript content is never rendered here.
|
|
9
|
+
*/
|
|
10
|
+
import type {
|
|
11
|
+
InferenceTranscriptLinkFilters,
|
|
12
|
+
InferenceUsageDimension,
|
|
13
|
+
InferenceUsageView,
|
|
14
|
+
} from '../types.js';
|
|
15
|
+
import { transcriptLinkFilters, usageColumns } from '../types.js';
|
|
16
|
+
|
|
17
|
+
interface InferenceUsageTableProps {
|
|
18
|
+
usage: InferenceUsageView | null;
|
|
19
|
+
busy: boolean;
|
|
20
|
+
/** Whether the app stores transcripts; `false` shows the status line. */
|
|
21
|
+
transcriptsEnabled?: boolean | null;
|
|
22
|
+
transcriptHref?: (
|
|
23
|
+
filters: InferenceTranscriptLinkFilters,
|
|
24
|
+
) => string | null | undefined;
|
|
25
|
+
onUsageGroupBy?: (by: InferenceUsageDimension[]) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
usage,
|
|
30
|
+
busy,
|
|
31
|
+
transcriptsEnabled = null,
|
|
32
|
+
transcriptHref,
|
|
33
|
+
onUsageGroupBy,
|
|
34
|
+
}: InferenceUsageTableProps = $props();
|
|
35
|
+
|
|
36
|
+
const DIMENSIONS: Array<{ id: InferenceUsageDimension; label: string }> = [
|
|
37
|
+
{ id: 'model', label: 'Model' },
|
|
38
|
+
{ id: 'tier', label: 'Tier' },
|
|
39
|
+
{ id: 'prompt', label: 'Prompt key' },
|
|
40
|
+
{ id: 'fusion', label: 'Fusion' },
|
|
41
|
+
{ id: 'template', label: 'Template' },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const columns = $derived(usage ? usageColumns(usage) : []);
|
|
45
|
+
const showTranscripts = $derived(
|
|
46
|
+
!!usage?.buckets.some((bucket) => typeof bucket.transcripts === 'number'),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
function href(
|
|
50
|
+
key: Record<string, string | null | undefined>,
|
|
51
|
+
outcome?: string,
|
|
52
|
+
): string | null {
|
|
53
|
+
if (!usage || !transcriptHref) return null;
|
|
54
|
+
return transcriptHref(transcriptLinkFilters(usage, key, outcome)) || null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function outcomeEntries(
|
|
58
|
+
value: Record<string, number> | undefined,
|
|
59
|
+
): Array<[string, number]> {
|
|
60
|
+
return Object.entries(value ?? {});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function regroup(event: Event): void {
|
|
64
|
+
const form = (event.currentTarget as HTMLInputElement).form;
|
|
65
|
+
if (!form || !onUsageGroupBy) return;
|
|
66
|
+
const by = new FormData(form)
|
|
67
|
+
.getAll('by')
|
|
68
|
+
.map(String) as InferenceUsageDimension[];
|
|
69
|
+
onUsageGroupBy(by.length > 0 ? by : ['model']);
|
|
70
|
+
}
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<div class="iut" data-testid="inference-usage">
|
|
74
|
+
{#if transcriptsEnabled === false}
|
|
75
|
+
<p class="iut-label" role="status" data-testid="inference-transcripts-off">
|
|
76
|
+
Transcripts are off; turn them on with <code>inference.transcripts.enabled</code> (Advanced, Transcripts) or <code>SMRT_INFERENCE_TRANSCRIPTS=1</code>.
|
|
77
|
+
</p>
|
|
78
|
+
{/if}
|
|
79
|
+
{#if onUsageGroupBy}
|
|
80
|
+
<form class="iut-group">
|
|
81
|
+
<span class="iut-label">Group by</span>
|
|
82
|
+
{#each DIMENSIONS as dimension (dimension.id)}
|
|
83
|
+
<label>
|
|
84
|
+
<input
|
|
85
|
+
type="checkbox"
|
|
86
|
+
name="by"
|
|
87
|
+
value={dimension.id}
|
|
88
|
+
checked={columns.includes(dimension.id)}
|
|
89
|
+
disabled={busy}
|
|
90
|
+
onchange={regroup}
|
|
91
|
+
/>
|
|
92
|
+
{dimension.label}
|
|
93
|
+
</label>
|
|
94
|
+
{/each}
|
|
95
|
+
</form>
|
|
96
|
+
{/if}
|
|
97
|
+
{#if !usage || usage.buckets.length === 0}
|
|
98
|
+
<p class="iut-label">No usage recorded yet.</p>
|
|
99
|
+
{:else}
|
|
100
|
+
<table class="iut-table">
|
|
101
|
+
<thead>
|
|
102
|
+
<tr>
|
|
103
|
+
{#each columns as column (column)}
|
|
104
|
+
<th scope="col">{DIMENSIONS.find((entry) => entry.id === column)?.label ?? column}</th>
|
|
105
|
+
{/each}
|
|
106
|
+
<th scope="col">Calls</th>
|
|
107
|
+
<th scope="col">Tokens</th>
|
|
108
|
+
<th scope="col">Est. cost</th>
|
|
109
|
+
<th scope="col">Outcomes</th>
|
|
110
|
+
{#if showTranscripts}<th scope="col">Transcripts</th>{/if}
|
|
111
|
+
</tr>
|
|
112
|
+
</thead>
|
|
113
|
+
<tbody>
|
|
114
|
+
{#each usage.buckets as bucket, index (index)}
|
|
115
|
+
<tr>
|
|
116
|
+
{#each columns as column (column)}
|
|
117
|
+
<td>{bucket.key[column] ?? '(unattributed)'}</td>
|
|
118
|
+
{/each}
|
|
119
|
+
<td>{bucket.calls}</td>
|
|
120
|
+
<td>{bucket.totalTokens}</td>
|
|
121
|
+
<td>
|
|
122
|
+
${bucket.estimatedCost.toFixed(4)}
|
|
123
|
+
{#if bucket.uncostedCalls}<span class="iut-label">({bucket.uncostedCalls} uncosted)</span>{/if}
|
|
124
|
+
</td>
|
|
125
|
+
<td>
|
|
126
|
+
{#each outcomeEntries(bucket.outcomes) as [label, count], position (label)}
|
|
127
|
+
{@const link = (bucket.transcripts ?? 0) > 0 ? href(bucket.key, label) : null}
|
|
128
|
+
{#if position > 0}, {/if}
|
|
129
|
+
{#if link}<a href={link} data-testid="inference-transcript-outcome-link">{label} {count}</a>{:else}{label} {count}{/if}
|
|
130
|
+
{:else}
|
|
131
|
+
–
|
|
132
|
+
{/each}
|
|
133
|
+
</td>
|
|
134
|
+
{#if showTranscripts}
|
|
135
|
+
{@const link = (bucket.transcripts ?? 0) > 0 ? href(bucket.key) : null}
|
|
136
|
+
<td data-testid="inference-transcript-count">
|
|
137
|
+
{#if link}<a href={link} data-testid="inference-transcript-link">{bucket.transcripts}</a>{:else}{bucket.transcripts ?? 0}{/if}
|
|
138
|
+
</td>
|
|
139
|
+
{/if}
|
|
140
|
+
</tr>
|
|
141
|
+
{/each}
|
|
142
|
+
</tbody>
|
|
143
|
+
</table>
|
|
144
|
+
{#if usage.costBasis}<p class="iut-label">{usage.costBasis}</p>{/if}
|
|
145
|
+
{/if}
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<style>
|
|
149
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
150
|
+
@layer smrt.theme {
|
|
151
|
+
.iut {
|
|
152
|
+
display: flex;
|
|
153
|
+
flex-direction: column;
|
|
154
|
+
gap: 0.75rem;
|
|
155
|
+
}
|
|
156
|
+
.iut-group {
|
|
157
|
+
display: flex;
|
|
158
|
+
gap: 0.75rem;
|
|
159
|
+
align-items: center;
|
|
160
|
+
}
|
|
161
|
+
.iut-table {
|
|
162
|
+
border-collapse: collapse;
|
|
163
|
+
font-size: 0.875rem;
|
|
164
|
+
}
|
|
165
|
+
.iut-table th,
|
|
166
|
+
.iut-table td {
|
|
167
|
+
text-align: left;
|
|
168
|
+
padding: 0.25rem 0.75rem 0.25rem 0;
|
|
169
|
+
border-bottom: var(--smrt-hairline);
|
|
170
|
+
}
|
|
171
|
+
.iut-label {
|
|
172
|
+
margin: 0;
|
|
173
|
+
font-size: 0.8125rem;
|
|
174
|
+
color: var(--smrt-color-on-surface-variant);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Usage tab: `reportAiUsage()` buckets (#4751) by model, tier, prompt
|
|
3
|
+
* key, fusion and/or template hash. Renders only the dimensions the report
|
|
4
|
+
* was grouped by, so it works with the model dimension alone. With
|
|
5
|
+
* transcript counts (#4781) each row shows how many calls have a stored
|
|
6
|
+
* transcript and links them (and each outcome label) to the host's
|
|
7
|
+
* transcript route; transcript content is never rendered here.
|
|
8
|
+
*/
|
|
9
|
+
import type { InferenceTranscriptLinkFilters, InferenceUsageDimension, InferenceUsageView } from '../types.js';
|
|
10
|
+
interface InferenceUsageTableProps {
|
|
11
|
+
usage: InferenceUsageView | null;
|
|
12
|
+
busy: boolean;
|
|
13
|
+
/** Whether the app stores transcripts; `false` shows the status line. */
|
|
14
|
+
transcriptsEnabled?: boolean | null;
|
|
15
|
+
transcriptHref?: (filters: InferenceTranscriptLinkFilters) => string | null | undefined;
|
|
16
|
+
onUsageGroupBy?: (by: InferenceUsageDimension[]) => void;
|
|
17
|
+
}
|
|
18
|
+
declare const InferenceUsageTable: import("svelte").Component<InferenceUsageTableProps, {}, "">;
|
|
19
|
+
type InferenceUsageTable = ReturnType<typeof InferenceUsageTable>;
|
|
20
|
+
export default InferenceUsageTable;
|
|
21
|
+
//# sourceMappingURL=InferenceUsageTable.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InferenceUsageTable.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/InferenceUsageTable.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,OAAO,KAAK,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAIrB,UAAU,wBAAwB;IAChC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,CACf,OAAO,EAAE,8BAA8B,KACpC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,uBAAuB,EAAE,KAAK,IAAI,CAAC;CAC1D;AA0HD,QAAA,MAAM,mBAAmB,8DAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-inference/svelte
|
|
3
|
+
*
|
|
4
|
+
* Optional Svelte 5 UI for inference settings (#4754). Presentational only:
|
|
5
|
+
* the panel takes rows and callbacks, does no fetching, and makes no
|
|
6
|
+
* authorization decision. Hosts render it from a server load that used
|
|
7
|
+
* `InferenceSettingsService` (`./server`) and wire saves to their own
|
|
8
|
+
* permission-checked actions. The root entry stays Svelte-free.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import type { ComponentProps } from 'svelte';
|
|
13
|
+
import InferenceSettingsPanel from './components/InferenceSettingsPanel.svelte';
|
|
14
|
+
export { InferenceSettingsPanel };
|
|
15
|
+
export type InferenceSettingsPanelProps = ComponentProps<typeof InferenceSettingsPanel>;
|
|
16
|
+
export { candidateViewLabel, defaultTierRevertPreview, describeTargetView, INFERENCE_SETTINGS_MODES, INFERENCE_SETTINGS_TIERS, type InferenceAliasChange, type InferenceAliasView, type InferenceCandidateView, type InferenceConnectionRequest, type InferenceDefaultsChange, type InferenceDefaultsView, type InferenceDefaultTierChange, type InferenceDefaultTierView, type InferenceDiscoveryView, type InferenceFusionChange, type InferenceFusionView, type InferenceKeyChange, type InferenceProviderView, type InferenceSettingsLevelView, type InferenceSettingsMode, type InferenceSettingsScope, type InferenceSettingsTier, type InferenceTargetView, type InferenceTestResultView, type InferenceTierChange, type InferenceTierView, type InferenceTranscriptLinkFilters, type InferenceTranscriptSettingsChange, type InferenceTranscriptSettingsView, type InferenceTranscriptValuesView, type InferenceUsageDimension, type InferenceUsageView, inferenceLevelLabel, isRefAllowed, targetViewRef, tierRevertPreview, transcriptLinkFilters, usageColumns, } 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,sBAAsB,MAAM,4CAA4C,CAAC;AAEhF,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAClC,MAAM,MAAM,2BAA2B,GAAG,cAAc,CACtD,OAAO,sBAAsB,CAC9B,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,8BAA8B,EACnC,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,EACpC,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,GACb,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-inference/svelte
|
|
3
|
+
*
|
|
4
|
+
* Optional Svelte 5 UI for inference settings (#4754). Presentational only:
|
|
5
|
+
* the panel takes rows and callbacks, does no fetching, and makes no
|
|
6
|
+
* authorization decision. Hosts render it from a server load that used
|
|
7
|
+
* `InferenceSettingsService` (`./server`) and wire saves to their own
|
|
8
|
+
* permission-checked actions. The root entry stays Svelte-free.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import InferenceSettingsPanel from './components/InferenceSettingsPanel.svelte';
|
|
13
|
+
export { InferenceSettingsPanel };
|
|
14
|
+
export { candidateViewLabel, defaultTierRevertPreview, describeTargetView, INFERENCE_SETTINGS_MODES, INFERENCE_SETTINGS_TIERS, inferenceLevelLabel, isRefAllowed, targetViewRef, tierRevertPreview, transcriptLinkFilters, usageColumns, } from './types.js';
|