tokenfactory-pi 0.2.4 → 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/dist/index.d.ts +2 -2
- package/dist/index.js +58 -15
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Nebius Token Factory
|
|
2
|
+
* Nebius Token Factory - pi extension
|
|
3
3
|
*
|
|
4
4
|
* Fetches the current model catalog from the Token Factory API on startup
|
|
5
5
|
* and registers all tool-capable text-generation models as a "nebius" provider.
|
|
6
6
|
*
|
|
7
7
|
* Environment:
|
|
8
|
-
* NEBIUS_API_KEY
|
|
8
|
+
* NEBIUS_API_KEY - required, Token Factory API key
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* pi -e /path/to/tokenfactory-pi
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Nebius Token Factory
|
|
2
|
+
* Nebius Token Factory - pi extension
|
|
3
3
|
*
|
|
4
4
|
* Fetches the current model catalog from the Token Factory API on startup
|
|
5
5
|
* and registers all tool-capable text-generation models as a "nebius" provider.
|
|
6
6
|
*
|
|
7
7
|
* Environment:
|
|
8
|
-
* NEBIUS_API_KEY
|
|
8
|
+
* NEBIUS_API_KEY - required, Token Factory API key
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* pi -e /path/to/tokenfactory-pi
|
|
@@ -18,10 +18,9 @@ const ENV_VAR = "NEBIUS_API_KEY";
|
|
|
18
18
|
// ============================================================================
|
|
19
19
|
// Helpers
|
|
20
20
|
// ============================================================================
|
|
21
|
-
function
|
|
22
|
-
const features = m.supported_features || [];
|
|
21
|
+
function isTextModel(m) {
|
|
23
22
|
const modality = m.architecture?.modality || "";
|
|
24
|
-
return
|
|
23
|
+
return modality.includes("->text");
|
|
25
24
|
}
|
|
26
25
|
function parseInputModalities(modality) {
|
|
27
26
|
const input = ["text"];
|
|
@@ -30,7 +29,8 @@ function parseInputModalities(modality) {
|
|
|
30
29
|
return input;
|
|
31
30
|
}
|
|
32
31
|
function parseCostPerMillion(raw) {
|
|
33
|
-
|
|
32
|
+
const parsed = parseFloat(raw || "0");
|
|
33
|
+
return isNaN(parsed) ? 0 : parsed * 1_000_000;
|
|
34
34
|
}
|
|
35
35
|
function isReasoningModel(id) {
|
|
36
36
|
return /(-R1|-Thinking|QwQ)/.test(id);
|
|
@@ -50,6 +50,7 @@ export default async function (pi) {
|
|
|
50
50
|
});
|
|
51
51
|
if (!res.ok) {
|
|
52
52
|
console.warn(`[${PROVIDER_NAME}] API returned ${res.status}: ${res.statusText}`);
|
|
53
|
+
console.warn(`[${PROVIDER_NAME}] Response headers:`, [...res.headers.entries()]);
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
55
56
|
response = (await res.json());
|
|
@@ -59,18 +60,34 @@ export default async function (pi) {
|
|
|
59
60
|
return;
|
|
60
61
|
}
|
|
61
62
|
if (!Array.isArray(response.data)) {
|
|
62
|
-
console.warn(`[${PROVIDER_NAME}] Unexpected API response shape
|
|
63
|
+
console.warn(`[${PROVIDER_NAME}] Unexpected API response shape. Expected array, got:`, typeof response.data);
|
|
64
|
+
console.warn(`[${PROVIDER_NAME}] Response data:`, response);
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
65
67
|
const models = [];
|
|
66
68
|
for (const m of response.data) {
|
|
67
|
-
|
|
69
|
+
// Skip models without valid IDs
|
|
70
|
+
if (!m.id || m.id.trim() === "") {
|
|
71
|
+
console.log(`[${PROVIDER_NAME}] Skipping model with empty ID:`, m);
|
|
68
72
|
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!isTextModel(m)) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
69
77
|
const modality = m.architecture?.modality || "";
|
|
78
|
+
// Validate and set defaults for critical fields
|
|
79
|
+
const contextLength = m.context_length && m.context_length > 0 ? m.context_length : 131072;
|
|
80
|
+
const modelName = m.name || m.id || "unknown-model";
|
|
81
|
+
const modelId = m.id || modelName;
|
|
82
|
+
// Skip models with zero context length even after defaults
|
|
83
|
+
if (contextLength <= 0) {
|
|
84
|
+
console.log(`[${PROVIDER_NAME}] Skipping model with invalid context length:`, m.id, m.context_length);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
70
87
|
models.push({
|
|
71
|
-
id:
|
|
72
|
-
name:
|
|
73
|
-
reasoning: isReasoningModel(
|
|
88
|
+
id: modelId,
|
|
89
|
+
name: modelName,
|
|
90
|
+
reasoning: isReasoningModel(modelId),
|
|
74
91
|
input: parseInputModalities(modality),
|
|
75
92
|
cost: {
|
|
76
93
|
input: parseCostPerMillion(m.pricing?.prompt),
|
|
@@ -78,8 +95,8 @@ export default async function (pi) {
|
|
|
78
95
|
cacheRead: 0,
|
|
79
96
|
cacheWrite: 0,
|
|
80
97
|
},
|
|
81
|
-
contextWindow:
|
|
82
|
-
maxTokens: Math.min(
|
|
98
|
+
contextWindow: contextLength,
|
|
99
|
+
maxTokens: Math.min(contextLength, 32768),
|
|
83
100
|
compat: {
|
|
84
101
|
supportsDeveloperRole: false,
|
|
85
102
|
maxTokensField: "max_tokens",
|
|
@@ -101,7 +118,7 @@ export default async function (pi) {
|
|
|
101
118
|
return;
|
|
102
119
|
}
|
|
103
120
|
const items = models
|
|
104
|
-
.sort((a, b) => a.
|
|
121
|
+
.sort((a, b) => b.cost.output - a.cost.output)
|
|
105
122
|
.map((m) => {
|
|
106
123
|
const tags = [];
|
|
107
124
|
if (m.reasoning)
|
|
@@ -111,7 +128,33 @@ export default async function (pi) {
|
|
|
111
128
|
const suffix = tags.length > 0 ? ` (${tags.join(", ")})` : "";
|
|
112
129
|
return `${m.id}${suffix}`;
|
|
113
130
|
});
|
|
114
|
-
|
|
131
|
+
// Show the selection dialog and capture the result
|
|
132
|
+
const selectedItem = await ctx.ui.select(`Nebius Token Factory - ${models.length} models`, items);
|
|
133
|
+
// If user cancelled (selectedItem is undefined), do nothing
|
|
134
|
+
if (!selectedItem) {
|
|
135
|
+
ctx.ui.notify("Model selection cancelled", "warning");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// Extract the model ID from the selection (remove the suffix)
|
|
139
|
+
const selectedId = selectedItem.split(" (")[0];
|
|
140
|
+
const selectedModel = models.find(m => m.id === selectedId);
|
|
141
|
+
if (!selectedModel) {
|
|
142
|
+
ctx.ui.notify(`Model not found: ${selectedId}`, "error");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
// Find the model in the registry and switch to it
|
|
146
|
+
const model = ctx.modelRegistry.find(PROVIDER_NAME, selectedModel.id);
|
|
147
|
+
if (!model) {
|
|
148
|
+
ctx.ui.notify(`Model not found in registry: ${PROVIDER_NAME}/${selectedModel.id}`, "error");
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const success = await pi.setModel(model);
|
|
152
|
+
if (success) {
|
|
153
|
+
ctx.ui.notify(`Switched to model: ${model.provider}/${model.id}`, "info");
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
ctx.ui.notify(`Failed to switch to model: ${model.provider}/${model.id}. Check API key?`, "error");
|
|
157
|
+
}
|
|
115
158
|
},
|
|
116
159
|
});
|
|
117
160
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokenfactory-pi",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Nebius Token Factory provider extension for pi coding agent. Requires `npm install -g @mariozechner/pi-coding-agent`. Install with `pi install npm:tokenfactory-pi`",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|