@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.
@@ -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;
@@ -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.10.3",
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.43.1",
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.38.0 <0.44.0"
29
+ "@tangle-network/agent-interface": ">=0.45.0 <0.46.0"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsc -p tsconfig.json",