@skaile/forge-settings 1.1.0 → 1.2.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 +9 -0
- package/README.md +2 -0
- package/dist/module.json +1 -1
- package/dist/runtime/ai-sdk/index.d.ts +13 -4
- package/dist/runtime/ai-sdk/index.js +11 -6
- package/package.json +2 -2
- package/src/runtime/ai-sdk/index.ts +27 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
- `@skaile/forge-settings/ai-sdk`: `resolveRegistryLanguageModel(selector, { …, registry? })` takes an already merged registry (e.g. one routed through the Workspaces transform proxy). When set, `projectDir` is not read for providers (so no `registry_invalid` from disk), the selector and the credential policy are checked against that registry, and it is forwarded to Workspaces' `resolveLanguageModel({ registry })`.
|
|
6
|
+
- Needs `@skaile/workspaces` ^7.8.0 (the `registry` option of `resolveLanguageModel`); the 6.x range is dropped.
|
|
7
|
+
|
|
8
|
+
## 1.1.1
|
|
9
|
+
|
|
10
|
+
- Accepts `@skaile/workspaces` 7: dependency range `^6.14.0 || ^7.0.0` (checked against 7.1.0; nothing this package imports changed). No code change.
|
|
11
|
+
|
|
3
12
|
## 1.1.0
|
|
4
13
|
|
|
5
14
|
- `@skaile/forge-settings/server`: `HarnessRow` carries `detection: HarnessDetection` (installed / version / login, from `@skaile/workspaces` `detectHarnesses()`). `buildHarnessRows(harnesses, settings, detections?)` takes the host's detections as an optional third argument; a harness it does not mention, or every harness when it is omitted, reports `{ id, status: "unknown" }`.
|
package/README.md
CHANGED
|
@@ -66,6 +66,8 @@ const { model } = await resolveRegistryLanguageModel('assistant-default/some-mod
|
|
|
66
66
|
|
|
67
67
|
Role-to-selector mapping belongs to the host's settings document; there is no global model locator. Failures are `ModelResolutionError` with a `code`; messages never carry a secret.
|
|
68
68
|
|
|
69
|
+
Pass `registry` (an already merged registry, e.g. one routed through the Workspaces transform proxy) to resolve against it instead of the providers on disk; the policy check runs on it and Workspaces receives it unchanged.
|
|
70
|
+
|
|
69
71
|
## Providers panel
|
|
70
72
|
|
|
71
73
|
```ts
|
package/dist/module.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* `@ai-sdk/openai-compatible`) are optional peers of Workspaces: install the
|
|
14
14
|
* one the selected surface needs.
|
|
15
15
|
*/
|
|
16
|
+
import { type MergedAIProviderRegistry } from "@skaile/workspaces/core";
|
|
16
17
|
import { type ResolvedLanguageModel } from "@skaile/workspaces/ai-sdk";
|
|
17
18
|
import type { CredentialPolicy } from "../server/credential-policy.js";
|
|
18
19
|
export { ModelResolutionError } from "../model/errors.js";
|
|
@@ -34,13 +35,21 @@ export interface ResolveRegistryLanguageModelOptions {
|
|
|
34
35
|
* before anything is read; a refused one is a `policy_refused` failure.
|
|
35
36
|
*/
|
|
36
37
|
policy?: CredentialPolicy;
|
|
38
|
+
/**
|
|
39
|
+
* An already merged (e.g. transform-proxy-routed) registry. When set,
|
|
40
|
+
* `projectDir` is not read for providers, the policy check runs on this
|
|
41
|
+
* registry, and it is handed to Workspaces as the registry to resolve against.
|
|
42
|
+
*/
|
|
43
|
+
registry?: MergedAIProviderRegistry;
|
|
37
44
|
}
|
|
38
45
|
/**
|
|
39
46
|
* The AI SDK model for `selector` (`<providerId>/<modelId>`, a bare model id or
|
|
40
|
-
* `@role`), resolved by Workspaces against the registry on disk
|
|
47
|
+
* `@role`), resolved by Workspaces against the registry on disk, or the given
|
|
48
|
+
* `registry`.
|
|
41
49
|
*
|
|
42
|
-
* @throws {ModelResolutionError} `registry_invalid`
|
|
43
|
-
* `policy_refused` · `unresolved` (credential, endpoint or
|
|
44
|
-
* message is fixed and never carries Workspaces' text, which
|
|
50
|
+
* @throws {ModelResolutionError} `registry_invalid` (only when read from disk) ·
|
|
51
|
+
* `unknown_selector` · `policy_refused` · `unresolved` (credential, endpoint or
|
|
52
|
+
* provider SDK; the message is fixed and never carries Workspaces' text, which
|
|
53
|
+
* stays on `cause`).
|
|
45
54
|
*/
|
|
46
55
|
export declare function resolveRegistryLanguageModel(selector: string, options: ResolveRegistryLanguageModelOptions): Promise<ResolvedLanguageModel>;
|
|
@@ -4,11 +4,7 @@ import { loadMergedProviderRegistry } from "@skaile/workspaces/sdk/bridge";
|
|
|
4
4
|
import { ModelResolutionError, assertEntryAllowed } from "../model/errors.js";
|
|
5
5
|
export { ModelResolutionError } from "../model/errors.js";
|
|
6
6
|
export async function resolveRegistryLanguageModel(selector, options) {
|
|
7
|
-
const
|
|
8
|
-
const errors = diagnostics.filter((d) => d.severity === "error").map((d) => d.path ? `${d.path}: ${d.message}` : d.message);
|
|
9
|
-
if (errors.length > 0) {
|
|
10
|
-
throw new ModelResolutionError("registry_invalid", `providers registry: ${errors.join("; ")}`);
|
|
11
|
-
}
|
|
7
|
+
const merged = options.registry ?? loadRegistry(options.projectDir);
|
|
12
8
|
const ref = parseModelRef(selector, merged, options.roles);
|
|
13
9
|
if (!ref) {
|
|
14
10
|
throw new ModelResolutionError("unknown_selector", `no provider serves '${selector}'`);
|
|
@@ -19,7 +15,8 @@ export async function resolveRegistryLanguageModel(selector, options) {
|
|
|
19
15
|
return await resolveLanguageModel(selector, {
|
|
20
16
|
projectDir: options.projectDir,
|
|
21
17
|
env: options.env,
|
|
22
|
-
...options.roles ? { roles: options.roles } : {}
|
|
18
|
+
...options.roles ? { roles: options.roles } : {},
|
|
19
|
+
...options.registry ? { registry: options.registry } : {}
|
|
23
20
|
});
|
|
24
21
|
} catch (cause) {
|
|
25
22
|
throw new ModelResolutionError(
|
|
@@ -29,3 +26,11 @@ export async function resolveRegistryLanguageModel(selector, options) {
|
|
|
29
26
|
);
|
|
30
27
|
}
|
|
31
28
|
}
|
|
29
|
+
function loadRegistry(projectDir) {
|
|
30
|
+
const { merged, diagnostics } = loadMergedProviderRegistry({ projectDir });
|
|
31
|
+
const errors = diagnostics.filter((d) => d.severity === "error").map((d) => d.path ? `${d.path}: ${d.message}` : d.message);
|
|
32
|
+
if (errors.length > 0) {
|
|
33
|
+
throw new ModelResolutionError("registry_invalid", `providers registry: ${errors.join("; ")}`);
|
|
34
|
+
}
|
|
35
|
+
return merged;
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skaile/forge-settings",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Provider and settings operations for Skaile forge apps: provider registry layers, credential store, env layers, model discovery, the providers panel, and editor / AI SDK model adapters.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "bun@1.3.9",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@nuxt/kit": "^4.0.0",
|
|
58
|
-
"@skaile/workspaces": "^
|
|
58
|
+
"@skaile/workspaces": "^7.8.0",
|
|
59
59
|
"ofetch": "^1.4.0",
|
|
60
60
|
"yaml": "^2.9.0"
|
|
61
61
|
},
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* one the selected surface needs.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { parseModelRef } from "@skaile/workspaces/core";
|
|
17
|
+
import { type MergedAIProviderRegistry, parseModelRef } from "@skaile/workspaces/core";
|
|
18
18
|
import { type ResolvedLanguageModel, resolveLanguageModel } from "@skaile/workspaces/ai-sdk";
|
|
19
19
|
import { loadMergedProviderRegistry } from "@skaile/workspaces/sdk/bridge";
|
|
20
20
|
import type { CredentialPolicy } from "../server/credential-policy";
|
|
@@ -40,27 +40,29 @@ export interface ResolveRegistryLanguageModelOptions {
|
|
|
40
40
|
* before anything is read; a refused one is a `policy_refused` failure.
|
|
41
41
|
*/
|
|
42
42
|
policy?: CredentialPolicy;
|
|
43
|
+
/**
|
|
44
|
+
* An already merged (e.g. transform-proxy-routed) registry. When set,
|
|
45
|
+
* `projectDir` is not read for providers, the policy check runs on this
|
|
46
|
+
* registry, and it is handed to Workspaces as the registry to resolve against.
|
|
47
|
+
*/
|
|
48
|
+
registry?: MergedAIProviderRegistry;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
/**
|
|
46
52
|
* The AI SDK model for `selector` (`<providerId>/<modelId>`, a bare model id or
|
|
47
|
-
* `@role`), resolved by Workspaces against the registry on disk
|
|
53
|
+
* `@role`), resolved by Workspaces against the registry on disk, or the given
|
|
54
|
+
* `registry`.
|
|
48
55
|
*
|
|
49
|
-
* @throws {ModelResolutionError} `registry_invalid`
|
|
50
|
-
* `policy_refused` · `unresolved` (credential, endpoint or
|
|
51
|
-
* message is fixed and never carries Workspaces' text, which
|
|
56
|
+
* @throws {ModelResolutionError} `registry_invalid` (only when read from disk) ·
|
|
57
|
+
* `unknown_selector` · `policy_refused` · `unresolved` (credential, endpoint or
|
|
58
|
+
* provider SDK; the message is fixed and never carries Workspaces' text, which
|
|
59
|
+
* stays on `cause`).
|
|
52
60
|
*/
|
|
53
61
|
export async function resolveRegistryLanguageModel(
|
|
54
62
|
selector: string,
|
|
55
63
|
options: ResolveRegistryLanguageModelOptions,
|
|
56
64
|
): Promise<ResolvedLanguageModel> {
|
|
57
|
-
const
|
|
58
|
-
const errors = diagnostics
|
|
59
|
-
.filter((d) => d.severity === "error")
|
|
60
|
-
.map((d) => (d.path ? `${d.path}: ${d.message}` : d.message));
|
|
61
|
-
if (errors.length > 0) {
|
|
62
|
-
throw new ModelResolutionError("registry_invalid", `providers registry: ${errors.join("; ")}`);
|
|
63
|
-
}
|
|
65
|
+
const merged = options.registry ?? loadRegistry(options.projectDir);
|
|
64
66
|
|
|
65
67
|
const ref = parseModelRef(selector, merged, options.roles);
|
|
66
68
|
if (!ref) {
|
|
@@ -74,6 +76,7 @@ export async function resolveRegistryLanguageModel(
|
|
|
74
76
|
projectDir: options.projectDir,
|
|
75
77
|
env: options.env,
|
|
76
78
|
...(options.roles ? { roles: options.roles } : {}),
|
|
79
|
+
...(options.registry ? { registry: options.registry } : {}),
|
|
77
80
|
});
|
|
78
81
|
} catch (cause) {
|
|
79
82
|
// Workspaces' message is not ours to vouch for: it can echo a resolved
|
|
@@ -86,3 +89,15 @@ export async function resolveRegistryLanguageModel(
|
|
|
86
89
|
);
|
|
87
90
|
}
|
|
88
91
|
}
|
|
92
|
+
|
|
93
|
+
/** The merged registry of `projectDir`; `registry_invalid` on any error diagnostic. */
|
|
94
|
+
function loadRegistry(projectDir: string): MergedAIProviderRegistry {
|
|
95
|
+
const { merged, diagnostics } = loadMergedProviderRegistry({ projectDir });
|
|
96
|
+
const errors = diagnostics
|
|
97
|
+
.filter((d) => d.severity === "error")
|
|
98
|
+
.map((d) => (d.path ? `${d.path}: ${d.message}` : d.message));
|
|
99
|
+
if (errors.length > 0) {
|
|
100
|
+
throw new ModelResolutionError("registry_invalid", `providers registry: ${errors.join("; ")}`);
|
|
101
|
+
}
|
|
102
|
+
return merged;
|
|
103
|
+
}
|