@xynogen/pix-9router 0.2.3 → 0.2.5

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/README.md CHANGED
@@ -39,6 +39,8 @@ export ROUTER_API_KEY="your-key-here"
39
39
 
40
40
  ## Full distro
41
41
 
42
+ Source: [github.com/xynogen/pix-mono](https://github.com/xynogen/pix-mono)
43
+
42
44
  To install the complete pix suite (all packages + Pi itself):
43
45
 
44
46
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xynogen/pix-9router",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Pi extension — 9Router provider + fetch/search tools via router API",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/data.test.ts CHANGED
@@ -1,12 +1,24 @@
1
- import { afterEach, beforeEach, describe, expect, it } from "bun:test";
1
+ import { afterEach, describe, expect, it } from "bun:test";
2
2
  import {
3
3
  buildModelsDevIndex,
4
4
  lookupInIndex,
5
- type ModelsDevApi,
6
- type ModelsDevModel,
5
+ type ModelGrepModel,
7
6
  routerBaseUrl,
8
7
  } from "./data.ts";
9
8
 
9
+ // modelgrep-shaped fixture builder (buildModelsDevIndex now takes ModelGrepModel[]).
10
+ function mg(
11
+ id: string,
12
+ opts: { name?: string; reasoning?: boolean; input?: string[] } = {},
13
+ ): ModelGrepModel {
14
+ return {
15
+ id,
16
+ name: opts.name ?? id,
17
+ capabilities: { reasoning: opts.reasoning },
18
+ modality: { input: opts.input },
19
+ };
20
+ }
21
+
10
22
  // ── routerBaseUrl ────────────────────────────────────────────────────────────
11
23
 
12
24
  describe("routerBaseUrl", () => {
@@ -36,75 +48,35 @@ describe("routerBaseUrl", () => {
36
48
  // ── buildModelsDevIndex ──────────────────────────────────────────────────────
37
49
 
38
50
  describe("buildModelsDevIndex", () => {
39
- const api: ModelsDevApi = {
40
- anthropic: {
41
- models: {
42
- "claude-sonnet-4-5": {
43
- id: "claude-sonnet-4-5",
44
- name: "Claude Sonnet 4.5",
45
- reasoning: false,
46
- limit: { context: 200_000, output: 8_192 },
47
- cost: { input: 3, output: 15 },
48
- },
49
- "claude-opus-4": {
50
- id: "claude-opus-4",
51
- name: "Claude Opus 4",
52
- reasoning: true,
53
- limit: { context: 200_000, output: 32_000 },
54
- cost: { input: 15, output: 75 },
55
- },
56
- },
57
- },
58
- openai: {
59
- models: {
60
- "gpt-4o": {
61
- id: "gpt-4o",
62
- name: "GPT-4o",
63
- modalities: { input: ["text", "image"], output: ["text"] },
64
- },
65
- },
66
- },
67
- };
68
-
69
- it("indexes all models by exact id", () => {
70
- const idx = buildModelsDevIndex(api);
51
+ const catalog: ModelGrepModel[] = [
52
+ mg("anthropic/claude-sonnet-4-5", { name: "Claude Sonnet 4.5" }),
53
+ mg("anthropic/claude-opus-4", { name: "Claude Opus 4", reasoning: true }),
54
+ mg("openai/gpt-4o", { name: "GPT-4o", input: ["text", "image"] }),
55
+ ];
56
+
57
+ it("indexes all models by slug", () => {
58
+ const idx = buildModelsDevIndex(catalog);
71
59
  expect(idx.has("claude-sonnet-4-5")).toBe(true);
72
60
  expect(idx.has("claude-opus-4")).toBe(true);
73
61
  expect(idx.has("gpt-4o")).toBe(true);
74
62
  });
75
63
 
76
- it("indexes normalized ids (strip date suffix)", () => {
77
- const apiWithDate: ModelsDevApi = {
78
- anthropic: {
79
- models: {
80
- "claude-sonnet-4-5-20250514": {
81
- id: "claude-sonnet-4-5-20250514",
82
- name: "Claude Sonnet 4.5",
83
- },
84
- },
85
- },
86
- };
87
- const idx = buildModelsDevIndex(apiWithDate);
88
- // normalized: strip -20250514
64
+ it("indexes normalized slug (strip date suffix)", () => {
65
+ const idx = buildModelsDevIndex([
66
+ mg("anthropic/claude-sonnet-4-5-20250514", { name: "Claude Sonnet 4.5" }),
67
+ ]);
89
68
  expect(idx.has("claude-sonnet-4-5")).toBe(true);
90
69
  });
91
70
 
92
- it("handles empty api gracefully", () => {
93
- const idx = buildModelsDevIndex({});
94
- expect(idx.size).toBe(0);
71
+ it("handles empty catalog gracefully", () => {
72
+ expect(buildModelsDevIndex([]).size).toBe(0);
95
73
  });
96
74
 
97
- it("handles provider with no models key", () => {
98
- const idx = buildModelsDevIndex({ anthropic: {} });
99
- expect(idx.size).toBe(0);
100
- });
101
-
102
- it("preserves first-seen on id collision", () => {
103
- const collide: ModelsDevApi = {
104
- a: { models: { "gpt-4o": { id: "gpt-4o", name: "First" } } },
105
- b: { models: { "gpt-4o": { id: "gpt-4o", name: "Second" } } },
106
- };
107
- const idx = buildModelsDevIndex(collide);
75
+ it("preserves first-seen on slug collision", () => {
76
+ const idx = buildModelsDevIndex([
77
+ mg("a/gpt-4o", { name: "First" }),
78
+ mg("b/gpt-4o", { name: "Second" }),
79
+ ]);
108
80
  expect(idx.get("gpt-4o")?.name).toBe("First");
109
81
  });
110
82
  });
@@ -112,28 +84,12 @@ describe("buildModelsDevIndex", () => {
112
84
  // ── lookupInIndex ────────────────────────────────────────────────────────────
113
85
 
114
86
  describe("lookupInIndex", () => {
115
- let index: Map<string, ModelsDevModel>;
116
-
117
- beforeEach(() => {
118
- const api: ModelsDevApi = {
119
- anthropic: {
120
- models: {
121
- "claude-sonnet-4-5": {
122
- id: "claude-sonnet-4-5",
123
- name: "Claude Sonnet 4.5",
124
- },
125
- "claude-opus-4": { id: "claude-opus-4", name: "Claude Opus 4" },
126
- },
127
- },
128
- openai: {
129
- models: {
130
- "gpt-4o": { id: "gpt-4o", name: "GPT-4o" },
131
- "o3-mini": { id: "o3-mini", name: "o3 mini" },
132
- },
133
- },
134
- };
135
- index = buildModelsDevIndex(api);
136
- });
87
+ const index = buildModelsDevIndex([
88
+ mg("anthropic/claude-sonnet-4-5", { name: "Claude Sonnet 4.5" }),
89
+ mg("anthropic/claude-opus-4", { name: "Claude Opus 4" }),
90
+ mg("openai/gpt-4o", { name: "GPT-4o" }),
91
+ mg("openai/o3-mini", { name: "o3 mini" }),
92
+ ]);
137
93
 
138
94
  it("finds exact match", () => {
139
95
  expect(lookupInIndex("claude-sonnet-4-5", index)?.name).toBe(
package/src/data.ts CHANGED
@@ -18,7 +18,11 @@
18
18
  import { join } from "node:path";
19
19
  import { CACHE_DIR, DataSource } from "../../pix-data/src/index.ts";
20
20
 
21
- export type { ModelsDevApi, ModelsDevModel } from "../../pix-data/src/index.ts";
21
+ export type {
22
+ ModelGrepModel,
23
+ ModelsDevApi,
24
+ ModelsDevModel,
25
+ } from "../../pix-data/src/index.ts";
22
26
  // Re-export the shared models.dev API so existing consumers (provider.ts)
23
27
  // can keep importing these names from "./data".
24
28
  export {