@substrat-run/model-providers 0.4.12 → 0.5.1

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.
@@ -29,29 +29,66 @@ export async function listModels(provider, env) {
29
29
  .filter((id) => id !== null)
30
30
  .sort();
31
31
  }
32
+ /**
33
+ * Can this model run a tool call?
34
+ *
35
+ * A build turn is a tool loop from end to end, so a model that cannot call a
36
+ * function cannot run one — it can only be picked and then fail. The catalog
37
+ * answers per row: `function_calling: "true"` inside `properties`, present on the
38
+ * models that support it and absent on the ones that do not.
39
+ *
40
+ * Fails SOFT, and the asymmetry is deliberate. A row carrying NO `properties`
41
+ * array is kept, because that is the response shape moving rather than the model
42
+ * saying no; a row that HAS the array and no flag is dropped, because that is the
43
+ * catalog answering. Offering too much is a picker a builder can work around;
44
+ * offering nothing is not.
45
+ */
46
+ function runsToolCalls(row) {
47
+ if (!Array.isArray(row.properties))
48
+ return true;
49
+ const props = row.properties;
50
+ const flag = props.find((p) => p !== null && typeof p === 'object' && p.property_id === 'function_calling');
51
+ return flag?.value === 'true';
52
+ }
32
53
  /**
33
54
  * Workers AI's OpenAI-compatible surface serves chat/completions and embeddings
34
55
  * but NOT `GET /models` (405) — the catalog lives one level up, on the account
35
- * API (`…/ai/v1` → `…/ai/models/search`), task-filtered server-side so the
36
- * picker offers models that can run a text turn, not embeddings or speech. It
37
- * lists Cloudflare's own `@cf/…` models only; partner-served `vendor/model` ids
38
- * stay free-text. Paged defensively; the filtered catalog fits one page today.
56
+ * API (`…/ai/v1` → `…/ai/models/search`). Three of the four filters are the
57
+ * endpoint's own documented query parameters, so they cost nothing to apply:
58
+ * `task` (a text turn, not embeddings or speech), `hide_experimental` and
59
+ * `include_deprecated`. The fourth — can it run a tool call — is per row and
60
+ * applied here (`runsToolCalls`). It lists Cloudflare's own `@cf/…` models only;
61
+ * partner-served `vendor/model` ids stay free-text. Paged defensively; the
62
+ * filtered catalog fits one page today.
39
63
  */
40
64
  async function listCloudflareCatalog(baseUrl, headers) {
41
65
  const root = baseUrl.replace(/\/$/, '').replace(/\/v1$/, '');
42
66
  const names = [];
67
+ const seen = [];
43
68
  for (let page = 1; page <= 5; page++) {
44
- const url = `${root}/models/search?task=${encodeURIComponent('Text Generation')}&per_page=100&page=${page}`;
69
+ const url = `${root}/models/search?task=${encodeURIComponent('Text Generation')}` +
70
+ `&hide_experimental=true&include_deprecated=false&per_page=100&page=${page}`;
45
71
  const res = await fetch(url, { headers });
46
72
  if (!res.ok)
47
73
  throw new ProviderError(`${root}/models/search returned HTTP ${res.status}`);
48
74
  const body = (await res.json());
49
75
  const rows = body.result ?? [];
50
- names.push(...rows.map((m) => (typeof m.name === 'string' ? m.name : null)).filter((n) => n !== null));
76
+ for (const row of rows) {
77
+ if (typeof row.name !== 'string')
78
+ continue;
79
+ seen.push(row.name);
80
+ if (runsToolCalls(row))
81
+ names.push(row.name);
82
+ }
51
83
  // The page boundary is the RAW page length: a filtered-out entry must not end the walk early.
52
84
  if (rows.length < 100)
53
85
  break;
54
86
  }
87
+ // The last fail-soft: if the catalog answered and the tool-call filter took ALL of
88
+ // it, the flag has moved rather than every model having lost the capability. An
89
+ // over-wide picker beats an empty one, which reads as "Cloudflare is down".
90
+ if (names.length === 0 && seen.length > 0)
91
+ return seen.sort();
55
92
  return names.sort();
56
93
  }
57
94
  //# sourceMappingURL=list-models.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../src/list-models.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../src/list-models.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/model-providers",
3
- "version": "0.4.12",
3
+ "version": "0.5.1",
4
4
  "description": "The model-provider seam: one `provider:model` grammar, a table of providers (Anthropic, OpenAI, Google, Mistral, Qwen, Cloudflare, Scaleway, Ollama, any OpenAI-compatible endpoint), the hosting disclosure per provider, the generated rate card and the list-price math over it. Cloudflare is one row, not the design (#1054).",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "@ai-sdk/openai-compatible": "3.0.30",
26
26
  "ai": "7.0.62",
27
- "@substrat-run/contracts": "^0.109.0"
27
+ "@substrat-run/contracts": "^0.111.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "typescript": "^7.0.0",