@tangle-network/agent-profile-materialize 0.10.3 → 0.12.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/dist/index.d.ts +195 -3
- package/dist/index.js +807 -43
- package/dist/model-id.d.ts +42 -0
- package/dist/model-id.js +59 -0
- package/package.json +3 -3
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one canonicalization of a model id, shared by everything that writes a
|
|
3
|
+
* model id into an {@link AgentProfile} and everything that later compares one
|
|
4
|
+
* against it.
|
|
5
|
+
*
|
|
6
|
+
* A model id is qualified by prepending provider segments, and the same model
|
|
7
|
+
* is legitimately spelled at more than one qualification level as it travels:
|
|
8
|
+
* the caller sends `{ provider: "openai-compat", model: "deepseek/deepseek-v4-flash" }`,
|
|
9
|
+
* the profile records the qualified `openai-compat/deepseek/deepseek-v4-flash`,
|
|
10
|
+
* and the CLI is spawned with that qualified form. Two spellings, one model.
|
|
11
|
+
*
|
|
12
|
+
* Every writer and every reader must run both sides through here, so a
|
|
13
|
+
* comparison cannot mistake two spellings of one model for a conflict. Two
|
|
14
|
+
* independent copies of this rule are exactly how that bug arises.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Qualify `modelId` with `provider` — the canonical form of a model id.
|
|
18
|
+
*
|
|
19
|
+
* The already-qualified check is prefix-SPECIFIC rather than "already contains
|
|
20
|
+
* a slash": a router slug legitimately carries an upstream segment of its own
|
|
21
|
+
* (`deepseek/deepseek-v4-flash`, `zai/glm-4.7`), so a generic slash test would
|
|
22
|
+
* leave those unqualified, while an unconditional prefix would double-qualify
|
|
23
|
+
* an id that has already been through here.
|
|
24
|
+
*
|
|
25
|
+
* Idempotent by construction:
|
|
26
|
+
* `qualifyModelId(p, qualifyModelId(p, m)) === qualifyModelId(p, m)`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function qualifyModelId<T extends string | undefined>(provider: string | undefined, modelId: T): T;
|
|
29
|
+
/**
|
|
30
|
+
* Do two model ids name the same model?
|
|
31
|
+
*
|
|
32
|
+
* Both operands are qualified by `provider` before comparison, so the
|
|
33
|
+
* qualification level a caller happened to use is not a difference. Two
|
|
34
|
+
* different model names are still different — this narrows a comparison to the
|
|
35
|
+
* model's identity, it does not make the comparison permissive.
|
|
36
|
+
*
|
|
37
|
+
* `provider` is optional because a profile may carry a `model.default` that was
|
|
38
|
+
* qualified by a writer which did not also record `model.provider`. With no
|
|
39
|
+
* provider to qualify by, a bare id and its single-segment-qualified spelling
|
|
40
|
+
* are still the same model, which is the only tolerance the undeclared case gets.
|
|
41
|
+
*/
|
|
42
|
+
export declare function modelIdsMatch(a: string | undefined, b: string | undefined, provider?: string): boolean;
|
package/dist/model-id.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one canonicalization of a model id, shared by everything that writes a
|
|
3
|
+
* model id into an {@link AgentProfile} and everything that later compares one
|
|
4
|
+
* against it.
|
|
5
|
+
*
|
|
6
|
+
* A model id is qualified by prepending provider segments, and the same model
|
|
7
|
+
* is legitimately spelled at more than one qualification level as it travels:
|
|
8
|
+
* the caller sends `{ provider: "openai-compat", model: "deepseek/deepseek-v4-flash" }`,
|
|
9
|
+
* the profile records the qualified `openai-compat/deepseek/deepseek-v4-flash`,
|
|
10
|
+
* and the CLI is spawned with that qualified form. Two spellings, one model.
|
|
11
|
+
*
|
|
12
|
+
* Every writer and every reader must run both sides through here, so a
|
|
13
|
+
* comparison cannot mistake two spellings of one model for a conflict. Two
|
|
14
|
+
* independent copies of this rule are exactly how that bug arises.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Qualify `modelId` with `provider` — the canonical form of a model id.
|
|
18
|
+
*
|
|
19
|
+
* The already-qualified check is prefix-SPECIFIC rather than "already contains
|
|
20
|
+
* a slash": a router slug legitimately carries an upstream segment of its own
|
|
21
|
+
* (`deepseek/deepseek-v4-flash`, `zai/glm-4.7`), so a generic slash test would
|
|
22
|
+
* leave those unqualified, while an unconditional prefix would double-qualify
|
|
23
|
+
* an id that has already been through here.
|
|
24
|
+
*
|
|
25
|
+
* Idempotent by construction:
|
|
26
|
+
* `qualifyModelId(p, qualifyModelId(p, m)) === qualifyModelId(p, m)`.
|
|
27
|
+
*/
|
|
28
|
+
export function qualifyModelId(provider, modelId) {
|
|
29
|
+
if (!provider || !modelId)
|
|
30
|
+
return modelId;
|
|
31
|
+
if (modelId === provider || modelId.startsWith(`${provider}/`))
|
|
32
|
+
return modelId;
|
|
33
|
+
return `${provider}/${modelId}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Do two model ids name the same model?
|
|
37
|
+
*
|
|
38
|
+
* Both operands are qualified by `provider` before comparison, so the
|
|
39
|
+
* qualification level a caller happened to use is not a difference. Two
|
|
40
|
+
* different model names are still different — this narrows a comparison to the
|
|
41
|
+
* model's identity, it does not make the comparison permissive.
|
|
42
|
+
*
|
|
43
|
+
* `provider` is optional because a profile may carry a `model.default` that was
|
|
44
|
+
* qualified by a writer which did not also record `model.provider`. With no
|
|
45
|
+
* provider to qualify by, a bare id and its single-segment-qualified spelling
|
|
46
|
+
* are still the same model, which is the only tolerance the undeclared case gets.
|
|
47
|
+
*/
|
|
48
|
+
export function modelIdsMatch(a, b, provider) {
|
|
49
|
+
if (a === b)
|
|
50
|
+
return true;
|
|
51
|
+
if (a === undefined || b === undefined)
|
|
52
|
+
return false;
|
|
53
|
+
if (qualifyModelId(provider, a) === qualifyModelId(provider, b))
|
|
54
|
+
return true;
|
|
55
|
+
if (provider)
|
|
56
|
+
return false;
|
|
57
|
+
return ((!a.includes("/") && b.endsWith(`/${a}`)) ||
|
|
58
|
+
(!b.includes("/") && a.endsWith(`/${b}`)));
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-profile-materialize",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Materialize an AgentProfile into the native per-harness workspace files (the one shared materializer for cli-bridge, agent-dev-container, and VB).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"dist"
|
|
21
21
|
],
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@tangle-network/agent-interface": "0.
|
|
23
|
+
"@tangle-network/agent-interface": "0.45.0",
|
|
24
24
|
"@types/node": "25.6.0",
|
|
25
25
|
"typescript": "^6.0.3",
|
|
26
26
|
"vitest": "^4.1.10"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@tangle-network/agent-interface": ">=0.
|
|
29
|
+
"@tangle-network/agent-interface": ">=0.45.0 <0.46.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsc -p tsconfig.json",
|