@skaile/forge-settings 1.3.3 → 2.0.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/CHANGELOG.md +40 -0
- package/README.md +52 -9
- package/dist/module.json +1 -1
- package/dist/runtime/ai-sdk/index.d.ts +33 -26
- package/dist/runtime/ai-sdk/index.js +34 -16
- package/dist/runtime/components/ForgeProvidersPanel.d.vue.ts +13 -0
- package/dist/runtime/components/ForgeProvidersPanel.vue +461 -78
- package/dist/runtime/components/ForgeProvidersPanel.vue.d.ts +13 -0
- package/dist/runtime/editor/index.d.ts +55 -16
- package/dist/runtime/editor/index.js +82 -40
- package/dist/runtime/model/selector.d.ts +16 -0
- package/dist/runtime/model/selector.js +12 -0
- package/dist/runtime/server/credential-store.d.ts +16 -4
- package/dist/runtime/server/credential-store.js +3 -4
- package/dist/runtime/server/env-layers.d.ts +1 -1
- package/dist/runtime/server/env-layers.js +3 -3
- package/dist/runtime/server/index.d.ts +9 -8
- package/dist/runtime/server/index.js +3 -3
- package/dist/runtime/server/provider-discovery.d.ts +28 -8
- package/dist/runtime/server/provider-discovery.js +57 -33
- package/dist/runtime/server/provider-layers.d.ts +1 -1
- package/dist/runtime/server/provider-layers.js +3 -5
- package/dist/runtime/server/provider-service.d.ts +26 -2
- package/dist/runtime/server/provider-service.js +16 -1
- package/dist/runtime/server/provider-write.d.ts +26 -10
- package/dist/runtime/server/provider-write.js +75 -7
- package/dist/runtime/server/voice-provider.d.ts +61 -0
- package/dist/runtime/server/voice-provider.js +31 -0
- package/dist/runtime/shared/data-zone.d.ts +68 -0
- package/dist/runtime/shared/data-zone.js +79 -0
- package/dist/runtime/shared/harness-providers.d.ts +42 -3
- package/dist/runtime/shared/harness-providers.js +31 -8
- package/dist/runtime/shared/harnesses.d.ts +7 -0
- package/dist/runtime/shared/harnesses.js +18 -0
- package/dist/runtime/shared/provider-accounts.d.ts +215 -0
- package/dist/runtime/shared/provider-accounts.js +255 -0
- package/dist/runtime/shared/provider-registry.d.ts +19 -182
- package/dist/runtime/shared/provider-registry.js +25 -65
- package/dist/runtime/vue/index.d.ts +2 -0
- package/dist/runtime/vue/index.js +2 -0
- package/dist/runtime/vue/providers-panel-model.d.ts +98 -5
- package/dist/runtime/vue/providers-panel-model.js +13 -1
- package/dist/runtime/vue/useProvidersPanel.d.ts +66 -5
- package/dist/runtime/vue/useProvidersPanel.js +417 -29
- package/dist/runtime/{server → workspaces}/harness-settings.d.ts +51 -13
- package/dist/runtime/{server → workspaces}/harness-settings.js +93 -9
- package/dist/runtime/workspaces/index.d.ts +16 -0
- package/dist/runtime/workspaces/index.js +5 -0
- package/dist/runtime/workspaces/language-model.d.ts +45 -0
- package/dist/runtime/workspaces/language-model.js +26 -0
- package/dist/runtime/workspaces/model-endpoint.d.ts +38 -0
- package/dist/runtime/workspaces/model-endpoint.js +54 -0
- package/dist/runtime/workspaces/provider-settings.d.ts +35 -0
- package/dist/runtime/{server → workspaces}/provider-settings.js +0 -31
- package/dist/runtime/{server → workspaces}/settings-defaults.d.ts +1 -1
- package/dist/runtime/{shared → workspaces}/settings-types.d.ts +11 -4
- package/package.json +11 -2
- package/src/runtime/ai-sdk/index.ts +88 -47
- package/src/runtime/components/ForgeProvidersPanel.vue +477 -78
- package/src/runtime/editor/index.ts +158 -63
- package/src/runtime/model/selector.ts +31 -0
- package/src/runtime/server/credential-store.ts +20 -10
- package/src/runtime/server/env-layers.ts +4 -4
- package/src/runtime/server/index.ts +9 -8
- package/src/runtime/server/provider-discovery.ts +114 -48
- package/src/runtime/server/provider-layers.ts +6 -6
- package/src/runtime/server/provider-service.ts +53 -1
- package/src/runtime/server/provider-write.ts +132 -18
- package/src/runtime/server/voice-provider.ts +110 -0
- package/src/runtime/shared/data-zone.ts +179 -0
- package/src/runtime/shared/harness-providers.ts +78 -7
- package/src/runtime/shared/harnesses.ts +25 -0
- package/src/runtime/shared/provider-accounts.ts +526 -0
- package/src/runtime/shared/provider-registry.ts +82 -256
- package/src/runtime/vue/index.ts +2 -0
- package/src/runtime/vue/providers-panel-model.ts +123 -5
- package/src/runtime/vue/useProvidersPanel.ts +589 -37
- package/src/runtime/{server → workspaces}/harness-settings.ts +166 -22
- package/src/runtime/workspaces/index.ts +17 -0
- package/src/runtime/workspaces/language-model.ts +82 -0
- package/src/runtime/workspaces/model-endpoint.ts +100 -0
- package/src/runtime/workspaces/provider-settings.ts +96 -0
- package/src/runtime/{server → workspaces}/settings-defaults.ts +1 -1
- package/src/runtime/{shared → workspaces}/settings-types.ts +11 -4
- package/dist/runtime/server/provider-settings.d.ts +0 -78
- package/src/runtime/server/provider-settings.ts +0 -192
- /package/dist/runtime/{server → workspaces}/settings-defaults.js +0 -0
- /package/dist/runtime/{shared → workspaces}/settings-types.js +0 -0
|
@@ -8,11 +8,16 @@
|
|
|
8
8
|
* Eligibility is by wire surface, never by vendor name: an entry is eligible
|
|
9
9
|
* for a harness when it is an enabled `llm` entry whose `surface` the harness
|
|
10
10
|
* declares. A harness that declares no surfaces accepts every `llm` entry.
|
|
11
|
+
* A host's data-zone rule then keeps out the entries outside it: such an
|
|
12
|
+
* entry is reported as `blocked-by-rule`, never eligible and never chosen.
|
|
11
13
|
*
|
|
12
14
|
* Browser-safe on purpose — no `node:` imports.
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
import { DATA_ZONE_RULE_LABELS, dataZoneRefusal, presetDataZone } from "./data-zone";
|
|
18
|
+
import type { AIProviderDataZone, AIProviderDataZoneRule } from "./provider-registry";
|
|
19
|
+
|
|
20
|
+
/** How many registry entries a harness can run at once (`HarnessInfo.providerPlurality` of a Workspaces harness). */
|
|
16
21
|
export type HarnessProviderPlurality = "registry" | "credentials-n" | "single";
|
|
17
22
|
|
|
18
23
|
/** The slice of a harness the rule reads. `GET /api/agents` rows satisfy it. */
|
|
@@ -33,6 +38,35 @@ export interface HarnessProviderCandidate {
|
|
|
33
38
|
surface?: string;
|
|
34
39
|
/** Absent means enabled. */
|
|
35
40
|
enabled?: boolean;
|
|
41
|
+
/** Catalog preset; gives the zone when {@link dataZone} is absent. */
|
|
42
|
+
preset?: string;
|
|
43
|
+
/** Effective data zone (`GET /api/providers` rows carry it). Absent: the preset's, else `transfer`. */
|
|
44
|
+
dataZone?: AIProviderDataZone;
|
|
45
|
+
/** The account's EU-processing setting is on. */
|
|
46
|
+
euProcessing?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Why an entry on a surface the harness speaks still cannot be used. */
|
|
50
|
+
export type HarnessProviderBlockReason = "blocked-by-rule";
|
|
51
|
+
|
|
52
|
+
/** One entry the harness could speak to that the host's rule keeps out. */
|
|
53
|
+
export interface HarnessProviderBlock {
|
|
54
|
+
id: string;
|
|
55
|
+
reason: HarnessProviderBlockReason;
|
|
56
|
+
/** The rule in force. */
|
|
57
|
+
rule: AIProviderDataZoneRule;
|
|
58
|
+
/** The rule's label ("EU only"). */
|
|
59
|
+
ruleLabel: string;
|
|
60
|
+
/** The entry's effective zone. */
|
|
61
|
+
zone: AIProviderDataZone;
|
|
62
|
+
/** What a settings table shows on the box it cannot tick. Secret-free. */
|
|
63
|
+
message: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** What {@link resolveHarnessProviders} applies beyond the surface rule. */
|
|
67
|
+
export interface HarnessProviderOptions {
|
|
68
|
+
/** The host's data-zone rule. Absent: `any`. */
|
|
69
|
+
dataZoneRule?: AIProviderDataZoneRule;
|
|
36
70
|
}
|
|
37
71
|
|
|
38
72
|
/**
|
|
@@ -55,8 +89,10 @@ export interface HarnessProviderResolution<
|
|
|
55
89
|
state: HarnessProviderState;
|
|
56
90
|
/** The harness can run several providers at once. */
|
|
57
91
|
multiple: boolean;
|
|
58
|
-
/** Stored pick ids that are no longer eligible, deduplicated, in stored order. */
|
|
92
|
+
/** Stored pick ids that are no longer eligible (blocked ones included), deduplicated, in stored order. */
|
|
59
93
|
stale: string[];
|
|
94
|
+
/** Candidates on a surface the harness speaks that the data-zone rule keeps out, in registry order. */
|
|
95
|
+
blocked: HarnessProviderBlock[];
|
|
60
96
|
}
|
|
61
97
|
|
|
62
98
|
/** Whether `candidate` is an enabled `llm` entry on a surface `harness` speaks. */
|
|
@@ -70,22 +106,55 @@ export function isProviderEligibleForHarness(
|
|
|
70
106
|
return candidate.surface !== undefined && harness.surfaces.includes(candidate.surface);
|
|
71
107
|
}
|
|
72
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Why the data-zone rule keeps `candidate` out of `harness`, or `undefined`
|
|
111
|
+
* when it does not: the candidate must be otherwise eligible
|
|
112
|
+
* ({@link isProviderEligibleForHarness}) and outside `rule`.
|
|
113
|
+
*/
|
|
114
|
+
export function harnessProviderBlock(
|
|
115
|
+
harness: HarnessProviderInfo,
|
|
116
|
+
candidate: HarnessProviderCandidate,
|
|
117
|
+
rule: AIProviderDataZoneRule | undefined,
|
|
118
|
+
): HarnessProviderBlock | undefined {
|
|
119
|
+
if (!rule || rule === "any" || !isProviderEligibleForHarness(harness, candidate)) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
const zone = candidate.dataZone ?? presetDataZone(candidate.preset) ?? "transfer";
|
|
123
|
+
const message = dataZoneRefusal(rule, zone, candidate.euProcessing);
|
|
124
|
+
if (!message) return undefined;
|
|
125
|
+
return {
|
|
126
|
+
id: candidate.id,
|
|
127
|
+
reason: "blocked-by-rule",
|
|
128
|
+
rule,
|
|
129
|
+
ruleLabel: DATA_ZONE_RULE_LABELS[rule],
|
|
130
|
+
zone,
|
|
131
|
+
message,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
73
135
|
/**
|
|
74
136
|
* Resolve the providers a harness runs against.
|
|
75
137
|
*
|
|
76
138
|
* @param candidates Registry entries in registry order.
|
|
77
139
|
* @param selection The stored per-harness pick (`SkaileSettings.harnessProviders[harness.id]`).
|
|
140
|
+
* @param options.dataZoneRule The host's data-zone rule: entries outside it are
|
|
141
|
+
* `blocked`, never eligible, never auto-chosen; a stored pick of one is `stale`.
|
|
78
142
|
*/
|
|
79
143
|
export function resolveHarnessProviders<C extends HarnessProviderCandidate>(
|
|
80
144
|
harness: HarnessProviderInfo,
|
|
81
145
|
candidates: readonly C[],
|
|
82
146
|
selection: readonly string[] | undefined,
|
|
147
|
+
options: HarnessProviderOptions = {},
|
|
83
148
|
): HarnessProviderResolution<C> {
|
|
84
149
|
const multiple =
|
|
85
150
|
harness.providerPlurality === "registry" || harness.providerPlurality === "credentials-n";
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
151
|
+
const blocked: HarnessProviderBlock[] = [];
|
|
152
|
+
const eligible = candidates.filter((candidate) => {
|
|
153
|
+
if (!isProviderEligibleForHarness(harness, candidate)) return false;
|
|
154
|
+
const block = harnessProviderBlock(harness, candidate, options.dataZoneRule);
|
|
155
|
+
if (block) blocked.push(block);
|
|
156
|
+
return !block;
|
|
157
|
+
});
|
|
89
158
|
const eligibleIds = new Set(eligible.map((candidate) => candidate.id));
|
|
90
159
|
const picked = new Set(selection ?? []);
|
|
91
160
|
const stale = [...picked].filter((id) => !eligibleIds.has(id));
|
|
@@ -100,10 +169,11 @@ export function resolveHarnessProviders<C extends HarnessProviderCandidate>(
|
|
|
100
169
|
state: "chosen",
|
|
101
170
|
multiple,
|
|
102
171
|
stale,
|
|
172
|
+
blocked,
|
|
103
173
|
};
|
|
104
174
|
}
|
|
105
175
|
if (eligible.length === 0) {
|
|
106
|
-
return { eligible, selected: [], state: "none-eligible", multiple, stale };
|
|
176
|
+
return { eligible, selected: [], state: "none-eligible", multiple, stale, blocked };
|
|
107
177
|
}
|
|
108
178
|
if (eligible.length === 1 || multiple) {
|
|
109
179
|
return {
|
|
@@ -112,7 +182,8 @@ export function resolveHarnessProviders<C extends HarnessProviderCandidate>(
|
|
|
112
182
|
state: "auto",
|
|
113
183
|
multiple,
|
|
114
184
|
stale,
|
|
185
|
+
blocked,
|
|
115
186
|
};
|
|
116
187
|
}
|
|
117
|
-
return { eligible, selected: [], state: "needs-choice", multiple, stale };
|
|
188
|
+
return { eligible, selected: [], state: "needs-choice", multiple, stale, blocked };
|
|
118
189
|
}
|
|
@@ -32,3 +32,28 @@ export const DEFAULT_ENABLED_HARNESSES = ["omp", "claude-sdk", "codex"] as const
|
|
|
32
32
|
export function isExperimentalHarness(id: string): boolean {
|
|
33
33
|
return !(DEFAULT_ENABLED_HARNESSES as readonly string[]).includes(id);
|
|
34
34
|
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The model roles ("models per task") each multi-model harness renders, keyed by
|
|
38
|
+
* harness id. A harness absent here runs one model and takes no roles.
|
|
39
|
+
*/
|
|
40
|
+
export const HARNESS_ROLES: Readonly<Record<string, readonly string[]>> = {
|
|
41
|
+
omp: [
|
|
42
|
+
"default",
|
|
43
|
+
"smol",
|
|
44
|
+
"slow",
|
|
45
|
+
"vision",
|
|
46
|
+
"plan",
|
|
47
|
+
"designer",
|
|
48
|
+
"commit",
|
|
49
|
+
"tiny",
|
|
50
|
+
"task",
|
|
51
|
+
"advisor",
|
|
52
|
+
],
|
|
53
|
+
continue: ["chat", "edit", "apply", "autocomplete", "embed", "rerank", "summarize"],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** The role ids `harnessId` supports ({@link HARNESS_ROLES}); empty for a one-model harness. */
|
|
57
|
+
export function harnessRoleIds(harnessId: string): string[] {
|
|
58
|
+
return [...(HARNESS_ROLES[harnessId] ?? [])];
|
|
59
|
+
}
|