@skaile/forge-settings 1.4.0 → 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 +25 -0
- package/README.md +34 -11
- 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 +2 -2
- package/dist/runtime/components/ForgeProvidersPanel.vue.d.ts +2 -2
- 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 +7 -8
- package/dist/runtime/server/index.js +1 -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 +2 -2
- package/dist/runtime/server/provider-write.d.ts +1 -1
- package/dist/runtime/server/provider-write.js +3 -3
- 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 +28 -26
- package/dist/runtime/shared/data-zone.js +4 -4
- package/dist/runtime/shared/harness-providers.d.ts +7 -7
- package/dist/runtime/shared/provider-accounts.d.ts +1 -1
- package/dist/runtime/shared/provider-registry.d.ts +19 -220
- package/dist/runtime/shared/provider-registry.js +25 -81
- package/dist/runtime/vue/providers-panel-model.d.ts +4 -4
- package/dist/runtime/{server → workspaces}/harness-settings.d.ts +3 -3
- 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 +4 -4
- package/package.json +11 -2
- package/src/runtime/ai-sdk/index.ts +88 -47
- package/src/runtime/components/ForgeProvidersPanel.vue +2 -2
- 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 +7 -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 +2 -2
- package/src/runtime/server/provider-write.ts +3 -3
- package/src/runtime/server/voice-provider.ts +110 -0
- package/src/runtime/shared/data-zone.ts +40 -33
- package/src/runtime/shared/harness-providers.ts +7 -7
- package/src/runtime/shared/provider-accounts.ts +1 -1
- package/src/runtime/shared/provider-registry.ts +82 -314
- package/src/runtime/vue/providers-panel-model.ts +5 -5
- package/src/runtime/vue/useProvidersPanel.ts +5 -2
- package/src/runtime/{server → workspaces}/harness-settings.ts +3 -3
- 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 +4 -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}/harness-settings.js +0 -0
- /package/dist/runtime/{server → workspaces}/settings-defaults.js +0 -0
- /package/dist/runtime/{shared → workspaces}/settings-types.js +0 -0
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { existsSync, readFileSync } from "node:fs";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
saveProviderRegistryFile,
|
|
16
|
-
} from "@skaile/workspaces/core";
|
|
17
|
-
import { AI_PROVIDER_PRESETS, type AIProviderPreset } from "@skaile/workspaces/sdk/bridge";
|
|
12
|
+
import type { AIProviderRegistryPatch } from "@skaile/provider-registry";
|
|
13
|
+
import { AI_PROVIDER_PRESETS, type AIProviderPreset } from "@skaile/provider-registry/catalog";
|
|
14
|
+
import { saveProviderRegistryFile } from "@skaile/provider-registry/files";
|
|
18
15
|
import { parse as parseYaml } from "yaml";
|
|
19
16
|
import { isPlainObject } from "../shared/guards";
|
|
20
17
|
|
|
18
|
+
/** A layer document's file name, as every registry host spells it. */
|
|
19
|
+
const PROVIDERS_FILENAME = "providers.yml";
|
|
20
|
+
|
|
21
21
|
/** The `.yaml` spelling of {@link PROVIDERS_FILENAME}. */
|
|
22
22
|
const PROVIDERS_FILENAME_ALIAS = "providers.yaml";
|
|
23
23
|
|
|
@@ -23,12 +23,12 @@ import { entryDataZone } from "../shared/data-zone";
|
|
|
23
23
|
import type {
|
|
24
24
|
AIProviderCapabilities,
|
|
25
25
|
AIProviderCredentialKind,
|
|
26
|
+
AIProviderDataZone,
|
|
26
27
|
AIProviderKind,
|
|
27
28
|
AIProviderRegistryView,
|
|
28
29
|
AIProviderSurface,
|
|
29
30
|
AIProviderTransport,
|
|
30
31
|
AIProviderVoiceParams,
|
|
31
|
-
DataZone,
|
|
32
32
|
} from "../shared/provider-registry";
|
|
33
33
|
import {
|
|
34
34
|
entriesOfKind,
|
|
@@ -100,7 +100,7 @@ export interface ProviderInfo {
|
|
|
100
100
|
/** Frozen by the control plane: a lower layer cannot change or disable it. */
|
|
101
101
|
locked: boolean;
|
|
102
102
|
/** Where the entry processes data: its `data_zone`, else its preset's, else `transfer`. */
|
|
103
|
-
dataZone:
|
|
103
|
+
dataZone: AIProviderDataZone;
|
|
104
104
|
/** The entry's `eu_processing` switch (an `eu_option` entry counts as EU only with it on). */
|
|
105
105
|
euProcessing: boolean;
|
|
106
106
|
/**
|
|
@@ -28,17 +28,17 @@ import {
|
|
|
28
28
|
type AIProviderRegistryLayer,
|
|
29
29
|
type AIProviderRegistryPatch,
|
|
30
30
|
isSafeProviderId,
|
|
31
|
-
loadProviderRegistryFile,
|
|
32
31
|
mergeRegistries,
|
|
33
32
|
parseCredentialRef,
|
|
34
33
|
validateMergedRegistry,
|
|
35
34
|
validateRegistry,
|
|
36
|
-
} from "@skaile/
|
|
35
|
+
} from "@skaile/provider-registry";
|
|
37
36
|
import {
|
|
38
37
|
AI_PROVIDER_PRESETS,
|
|
39
38
|
type AIProviderPreset,
|
|
40
39
|
expandPreset,
|
|
41
|
-
} from "@skaile/
|
|
40
|
+
} from "@skaile/provider-registry/catalog";
|
|
41
|
+
import { loadProviderRegistryFile } from "@skaile/provider-registry/files";
|
|
42
42
|
import { isDataZone } from "../shared/data-zone";
|
|
43
43
|
import { isPlainObject } from "../shared/guards";
|
|
44
44
|
import { missingRequiredParams } from "../shared/provider-accounts";
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice selection: which `kind: stt|tts` registry entry serves a request and
|
|
3
|
+
* with which parameters.
|
|
4
|
+
*
|
|
5
|
+
* `sttProvider`/`ttsProvider` are registry ids of `kind: stt|tts` entries; the
|
|
6
|
+
* endpoint and the voice parameters live on the entry, and
|
|
7
|
+
* `sttLanguage`/`ttsVoice` are per-request overrides of two of those
|
|
8
|
+
* parameters. Resolving all of that used to be three apps' worth of hardcoded
|
|
9
|
+
* endpoints and voice ids.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
AIProviderRegistryView,
|
|
14
|
+
AIProviderVoiceEntry,
|
|
15
|
+
AIProviderVoiceKind,
|
|
16
|
+
AIProviderVoiceParams,
|
|
17
|
+
} from "../shared/provider-registry";
|
|
18
|
+
import {
|
|
19
|
+
entriesOfKind,
|
|
20
|
+
selectVoiceEntryId,
|
|
21
|
+
VOICE_OVERRIDE_PARAM,
|
|
22
|
+
} from "../shared/provider-registry";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Settings fields that name a voice entry and override its parameters — the
|
|
26
|
+
* same field names as the Workspaces `settings.json` document, so a
|
|
27
|
+
* `SkaileSettings` (`@skaile/forge-settings/workspaces`) can be passed as is.
|
|
28
|
+
*/
|
|
29
|
+
export interface VoiceSettings {
|
|
30
|
+
/** Registry id of the `kind: stt` entry. */
|
|
31
|
+
sttProvider?: string;
|
|
32
|
+
/** Registry id of the `kind: tts` entry. */
|
|
33
|
+
ttsProvider?: string;
|
|
34
|
+
/** Overrides the stt entry's `language` parameter. */
|
|
35
|
+
sttLanguage?: string;
|
|
36
|
+
/** Overrides the tts entry's `voice_id` parameter. */
|
|
37
|
+
ttsVoice?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The `kind: stt|tts` entry a request runs against, with its parameters resolved. */
|
|
41
|
+
export interface VoiceProviderSelection {
|
|
42
|
+
/** Registry id of the entry. */
|
|
43
|
+
providerId: string;
|
|
44
|
+
entry: AIProviderVoiceEntry;
|
|
45
|
+
/** Endpoint from the entry; absent when the entry inherits its preset's default. */
|
|
46
|
+
baseUrl?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The entry's `params` with overrides applied — Deepgram `{model, language}`,
|
|
49
|
+
* ElevenLabs `{voice_id, output_format}`. This is the only place a forge app
|
|
50
|
+
* should read voice defaults from.
|
|
51
|
+
*/
|
|
52
|
+
params: AIProviderVoiceParams;
|
|
53
|
+
/** True when settings named no usable entry and registry order decided. */
|
|
54
|
+
fallback: boolean;
|
|
55
|
+
/** Non-fatal notes, e.g. settings naming an entry the registry does not have. */
|
|
56
|
+
warnings: string[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Resolve which registry entry serves speech-to-text or text-to-speech.
|
|
61
|
+
*
|
|
62
|
+
* Selection is `settings.sttProvider`/`settings.ttsProvider`, falling back to
|
|
63
|
+
* the first enabled entry of that kind in registry order when the setting is
|
|
64
|
+
* absent or names an entry that is gone — a missing setting must not silence an
|
|
65
|
+
* app that has a perfectly good entry configured.
|
|
66
|
+
*
|
|
67
|
+
* Parameter precedence, lowest first: the entry's `params`, then the settings
|
|
68
|
+
* overrides (`sttLanguage` → `language`, `ttsVoice` → `voice_id`), then
|
|
69
|
+
* `overrides` from the request. The per-request override is the contract
|
|
70
|
+
* forge-concept already honoured and the other apps silently dropped.
|
|
71
|
+
*
|
|
72
|
+
* @returns The selection, or `undefined` when the registry has no enabled entry
|
|
73
|
+
* of that kind.
|
|
74
|
+
*/
|
|
75
|
+
export function resolveVoiceProvider(
|
|
76
|
+
registry: AIProviderRegistryView,
|
|
77
|
+
kind: AIProviderVoiceKind,
|
|
78
|
+
settings: VoiceSettings = {},
|
|
79
|
+
overrides: AIProviderVoiceParams = {},
|
|
80
|
+
): VoiceProviderSelection | undefined {
|
|
81
|
+
const candidates = entriesOfKind(registry, kind);
|
|
82
|
+
if (candidates.length === 0) return undefined;
|
|
83
|
+
|
|
84
|
+
const warnings: string[] = [];
|
|
85
|
+
const wanted = (kind === "stt" ? settings.sttProvider : settings.ttsProvider)?.trim();
|
|
86
|
+
const ids = candidates.map(([id]) => id);
|
|
87
|
+
// `candidates` is non-empty, so the shared rule always names one of these ids.
|
|
88
|
+
const providerId = selectVoiceEntryId(ids, wanted) as string;
|
|
89
|
+
const entry = candidates[ids.indexOf(providerId)][1];
|
|
90
|
+
if (wanted && wanted !== providerId) {
|
|
91
|
+
warnings.push(
|
|
92
|
+
`settings name '${wanted}' for ${kind}, which is not an enabled ${kind} entry — ` +
|
|
93
|
+
`using '${providerId}' instead`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const fallback = wanted !== providerId;
|
|
97
|
+
|
|
98
|
+
const settingsOverride: AIProviderVoiceParams = {};
|
|
99
|
+
const override = (kind === "stt" ? settings.sttLanguage : settings.ttsVoice)?.trim();
|
|
100
|
+
if (override) settingsOverride[VOICE_OVERRIDE_PARAM[kind]] = override;
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
providerId,
|
|
104
|
+
entry,
|
|
105
|
+
...(entry.base_url ? { baseUrl: entry.base_url } : {}),
|
|
106
|
+
params: { ...entry.params, ...settingsOverride, ...overrides },
|
|
107
|
+
fallback,
|
|
108
|
+
warnings,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -2,34 +2,36 @@
|
|
|
2
2
|
* Data zones: where a provider entry processes data, and which entries a
|
|
3
3
|
* host's data-zone rule ("Where may AI process data?") keeps.
|
|
4
4
|
*
|
|
5
|
-
* `@skaile/
|
|
6
|
-
* `
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* `@skaile/provider-registry` owns the vocabulary (`AI_PROVIDER_DATA_ZONES`,
|
|
6
|
+
* `AI_PROVIDER_DATA_ZONE_RULES`, re-exported by `./provider-registry`) and the
|
|
7
|
+
* catalog's `data_zone` column with `entryDataZone`, `entryAllowedByDataZone`
|
|
8
|
+
* and `filterRegistryByDataZone` in its `/catalog` entry. forge-settings keeps
|
|
9
|
+
* the browser-side view here so the settings panel does not ship the catalog
|
|
10
|
+
* (and its generated model table) to the browser: the same semantics, plus
|
|
11
|
+
* labels, refusal wording and a filter that keeps a merged registry merged.
|
|
12
|
+
* {@link PRESET_DATA_ZONES} is a copy of the catalog's column; a test holds it
|
|
13
|
+
* equal to `@skaile/provider-registry/catalog`.
|
|
12
14
|
*
|
|
13
15
|
* Browser-safe on purpose — no `node:` imports.
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
import {
|
|
19
|
+
AI_PROVIDER_DATA_ZONE_RULES,
|
|
20
|
+
AI_PROVIDER_DATA_ZONES,
|
|
21
|
+
type AIProviderDataZone,
|
|
22
|
+
type AIProviderDataZoneRule,
|
|
17
23
|
type AIProviderRegistry,
|
|
18
24
|
type AIProviderRegistryView,
|
|
19
|
-
DATA_ZONE_RULES,
|
|
20
|
-
DATA_ZONES,
|
|
21
|
-
type DataZone,
|
|
22
|
-
type DataZoneRule,
|
|
23
25
|
isMergedRegistry,
|
|
24
26
|
type MergedAIProviderRegistry,
|
|
25
27
|
} from "./provider-registry";
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* The `data_zone` of each catalog preset, by preset id. Copied from
|
|
29
|
-
* `@skaile/
|
|
31
|
+
* `@skaile/provider-registry/catalog`'s `AI_PROVIDER_PRESETS`; change it there
|
|
30
32
|
* first. A preset this table does not name is `transfer`.
|
|
31
33
|
*/
|
|
32
|
-
export const PRESET_DATA_ZONES: Readonly<Record<string,
|
|
34
|
+
export const PRESET_DATA_ZONES: Readonly<Record<string, AIProviderDataZone>> = {
|
|
33
35
|
anthropic: "transfer",
|
|
34
36
|
openai: "transfer",
|
|
35
37
|
google: "transfer",
|
|
@@ -53,7 +55,7 @@ export const PRESET_DATA_ZONES: Readonly<Record<string, DataZone>> = {
|
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
/** What a provider row's zone chip says. */
|
|
56
|
-
export const DATA_ZONE_LABELS: Readonly<Record<
|
|
58
|
+
export const DATA_ZONE_LABELS: Readonly<Record<AIProviderDataZone, string>> = {
|
|
57
59
|
eu: "EU",
|
|
58
60
|
eu_option: "EU option",
|
|
59
61
|
transfer: "Transfer",
|
|
@@ -61,24 +63,26 @@ export const DATA_ZONE_LABELS: Readonly<Record<DataZone, string>> = {
|
|
|
61
63
|
};
|
|
62
64
|
|
|
63
65
|
/** What a host calls each rule when it names the rule that keeps an entry out. */
|
|
64
|
-
export const DATA_ZONE_RULE_LABELS: Readonly<Record<
|
|
66
|
+
export const DATA_ZONE_RULE_LABELS: Readonly<Record<AIProviderDataZoneRule, string>> = {
|
|
65
67
|
any: "Anywhere",
|
|
66
68
|
eu_options: "EU, or EU option with EU processing on",
|
|
67
69
|
eu: "EU only",
|
|
68
70
|
};
|
|
69
71
|
|
|
70
|
-
/** Whether `value` is one of
|
|
71
|
-
export function isDataZone(value: unknown): value is
|
|
72
|
-
return typeof value === "string" && (
|
|
72
|
+
/** Whether `value` is one of `AI_PROVIDER_DATA_ZONES`. */
|
|
73
|
+
export function isDataZone(value: unknown): value is AIProviderDataZone {
|
|
74
|
+
return typeof value === "string" && (AI_PROVIDER_DATA_ZONES as readonly string[]).includes(value);
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
/** Whether `value` is one of
|
|
76
|
-
export function isDataZoneRule(value: unknown): value is
|
|
77
|
-
return
|
|
77
|
+
/** Whether `value` is one of `AI_PROVIDER_DATA_ZONE_RULES`. */
|
|
78
|
+
export function isDataZoneRule(value: unknown): value is AIProviderDataZoneRule {
|
|
79
|
+
return (
|
|
80
|
+
typeof value === "string" && (AI_PROVIDER_DATA_ZONE_RULES as readonly string[]).includes(value)
|
|
81
|
+
);
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
/** The zone of catalog preset `presetId`, or `undefined` for an id the catalog does not name. */
|
|
81
|
-
export function presetDataZone(presetId: string | undefined):
|
|
85
|
+
export function presetDataZone(presetId: string | undefined): AIProviderDataZone | undefined {
|
|
82
86
|
return presetId !== undefined && Object.hasOwn(PRESET_DATA_ZONES, presetId)
|
|
83
87
|
? PRESET_DATA_ZONES[presetId]
|
|
84
88
|
: undefined;
|
|
@@ -89,7 +93,10 @@ export function presetDataZone(presetId: string | undefined): DataZone | undefin
|
|
|
89
93
|
* catalog preset it names, else `transfer` (an unknown endpoint is assumed to
|
|
90
94
|
* leave the EU).
|
|
91
95
|
*/
|
|
92
|
-
export function entryDataZone(entry: {
|
|
96
|
+
export function entryDataZone(entry: {
|
|
97
|
+
data_zone?: AIProviderDataZone;
|
|
98
|
+
preset?: string;
|
|
99
|
+
}): AIProviderDataZone {
|
|
93
100
|
return entry.data_zone ?? presetDataZone(entry.preset) ?? "transfer";
|
|
94
101
|
}
|
|
95
102
|
|
|
@@ -99,8 +106,8 @@ export function entryDataZone(entry: { data_zone?: DataZone; preset?: string }):
|
|
|
99
106
|
* `euProcessing` is `true`.
|
|
100
107
|
*/
|
|
101
108
|
export function dataZoneAllows(
|
|
102
|
-
rule:
|
|
103
|
-
zone:
|
|
109
|
+
rule: AIProviderDataZoneRule,
|
|
110
|
+
zone: AIProviderDataZone,
|
|
104
111
|
euProcessing: boolean | undefined,
|
|
105
112
|
): boolean {
|
|
106
113
|
if (rule === "any") return true;
|
|
@@ -110,8 +117,8 @@ export function dataZoneAllows(
|
|
|
110
117
|
|
|
111
118
|
/** Whether `rule` allows `entry` ({@link dataZoneAllows} over {@link entryDataZone}). */
|
|
112
119
|
export function entryAllowedByDataZone(
|
|
113
|
-
entry: { data_zone?:
|
|
114
|
-
rule:
|
|
120
|
+
entry: { data_zone?: AIProviderDataZone; preset?: string; eu_processing?: boolean },
|
|
121
|
+
rule: AIProviderDataZoneRule,
|
|
115
122
|
): boolean {
|
|
116
123
|
return dataZoneAllows(rule, entryDataZone(entry), entry.eu_processing);
|
|
117
124
|
}
|
|
@@ -121,8 +128,8 @@ export function entryAllowedByDataZone(
|
|
|
121
128
|
* when the rule allows it. Secret-free, safe to render.
|
|
122
129
|
*/
|
|
123
130
|
export function dataZoneRefusal(
|
|
124
|
-
rule:
|
|
125
|
-
zone:
|
|
131
|
+
rule: AIProviderDataZoneRule,
|
|
132
|
+
zone: AIProviderDataZone,
|
|
126
133
|
euProcessing: boolean | undefined,
|
|
127
134
|
): string | undefined {
|
|
128
135
|
if (dataZoneAllows(rule, zone, euProcessing)) return undefined;
|
|
@@ -141,19 +148,19 @@ export function dataZoneRefusal(
|
|
|
141
148
|
*/
|
|
142
149
|
export function filterRegistryByDataZone(
|
|
143
150
|
registry: AIProviderRegistry,
|
|
144
|
-
rule:
|
|
151
|
+
rule: AIProviderDataZoneRule,
|
|
145
152
|
): AIProviderRegistry;
|
|
146
153
|
export function filterRegistryByDataZone(
|
|
147
154
|
registry: MergedAIProviderRegistry,
|
|
148
|
-
rule:
|
|
155
|
+
rule: AIProviderDataZoneRule,
|
|
149
156
|
): MergedAIProviderRegistry;
|
|
150
157
|
export function filterRegistryByDataZone(
|
|
151
158
|
registry: AIProviderRegistryView,
|
|
152
|
-
rule:
|
|
159
|
+
rule: AIProviderDataZoneRule,
|
|
153
160
|
): AIProviderRegistryView;
|
|
154
161
|
export function filterRegistryByDataZone(
|
|
155
162
|
registry: AIProviderRegistryView,
|
|
156
|
-
rule:
|
|
163
|
+
rule: AIProviderDataZoneRule,
|
|
157
164
|
): AIProviderRegistryView {
|
|
158
165
|
const entries = isMergedRegistry(registry) ? registry.providers : registry;
|
|
159
166
|
const providers: AIProviderRegistry = {};
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { DATA_ZONE_RULE_LABELS, dataZoneRefusal, presetDataZone } from "./data-zone";
|
|
18
|
-
import type {
|
|
18
|
+
import type { AIProviderDataZone, AIProviderDataZoneRule } from "./provider-registry";
|
|
19
19
|
|
|
20
|
-
/** How many registry entries a harness can run at once (
|
|
20
|
+
/** How many registry entries a harness can run at once (`HarnessInfo.providerPlurality` of a Workspaces harness). */
|
|
21
21
|
export type HarnessProviderPlurality = "registry" | "credentials-n" | "single";
|
|
22
22
|
|
|
23
23
|
/** The slice of a harness the rule reads. `GET /api/agents` rows satisfy it. */
|
|
@@ -41,7 +41,7 @@ export interface HarnessProviderCandidate {
|
|
|
41
41
|
/** Catalog preset; gives the zone when {@link dataZone} is absent. */
|
|
42
42
|
preset?: string;
|
|
43
43
|
/** Effective data zone (`GET /api/providers` rows carry it). Absent: the preset's, else `transfer`. */
|
|
44
|
-
dataZone?:
|
|
44
|
+
dataZone?: AIProviderDataZone;
|
|
45
45
|
/** The account's EU-processing setting is on. */
|
|
46
46
|
euProcessing?: boolean;
|
|
47
47
|
}
|
|
@@ -54,11 +54,11 @@ export interface HarnessProviderBlock {
|
|
|
54
54
|
id: string;
|
|
55
55
|
reason: HarnessProviderBlockReason;
|
|
56
56
|
/** The rule in force. */
|
|
57
|
-
rule:
|
|
57
|
+
rule: AIProviderDataZoneRule;
|
|
58
58
|
/** The rule's label ("EU only"). */
|
|
59
59
|
ruleLabel: string;
|
|
60
60
|
/** The entry's effective zone. */
|
|
61
|
-
zone:
|
|
61
|
+
zone: AIProviderDataZone;
|
|
62
62
|
/** What a settings table shows on the box it cannot tick. Secret-free. */
|
|
63
63
|
message: string;
|
|
64
64
|
}
|
|
@@ -66,7 +66,7 @@ export interface HarnessProviderBlock {
|
|
|
66
66
|
/** What {@link resolveHarnessProviders} applies beyond the surface rule. */
|
|
67
67
|
export interface HarnessProviderOptions {
|
|
68
68
|
/** The host's data-zone rule. Absent: `any`. */
|
|
69
|
-
dataZoneRule?:
|
|
69
|
+
dataZoneRule?: AIProviderDataZoneRule;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
@@ -114,7 +114,7 @@ export function isProviderEligibleForHarness(
|
|
|
114
114
|
export function harnessProviderBlock(
|
|
115
115
|
harness: HarnessProviderInfo,
|
|
116
116
|
candidate: HarnessProviderCandidate,
|
|
117
|
-
rule:
|
|
117
|
+
rule: AIProviderDataZoneRule | undefined,
|
|
118
118
|
): HarnessProviderBlock | undefined {
|
|
119
119
|
if (!rule || rule === "any" || !isProviderEligibleForHarness(harness, candidate)) {
|
|
120
120
|
return undefined;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Pure and browser-safe: the settings panel and the server's write gate read
|
|
8
8
|
* the same rules. The facts come from the catalog preset
|
|
9
|
-
* (`@skaile/
|
|
9
|
+
* (`@skaile/provider-registry/catalog`'s `AIProviderPreset`): its `credential.kind`, its
|
|
10
10
|
* `transport`, its default `params` and its `required_params`. The catalog
|
|
11
11
|
* names no list of accepted sign-in kinds, so they are derived here from those
|
|
12
12
|
* facts.
|