@vtstech/pi-api 1.0.3
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/api.js +411 -0
- package/package.json +24 -0
package/api.js
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// .build-npm/api/api.temp.ts
|
|
20
|
+
var api_temp_exports = {};
|
|
21
|
+
__export(api_temp_exports, {
|
|
22
|
+
default: () => api_temp_default
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(api_temp_exports);
|
|
25
|
+
var import_format = require("@vtstech/pi-shared/format");
|
|
26
|
+
var import_ollama = require("@vtstech/pi-shared/ollama");
|
|
27
|
+
var API_MODES = {
|
|
28
|
+
"anthropic-messages": "Anthropic Claude API and compatibles",
|
|
29
|
+
"openai-completions": "OpenAI Chat Completions API and compatibles",
|
|
30
|
+
"openai-responses": "OpenAI Responses API",
|
|
31
|
+
"azure-openai-responses": "Azure OpenAI Responses API",
|
|
32
|
+
"openai-codex-responses": "OpenAI Codex Responses API",
|
|
33
|
+
"mistral-conversations": "Mistral SDK Conversations/Chat streaming",
|
|
34
|
+
"google-generative-ai": "Google Generative AI API",
|
|
35
|
+
"google-gemini-cli": "Google Cloud Code Assist API",
|
|
36
|
+
"google-vertex": "Google Vertex AI API",
|
|
37
|
+
"bedrock-converse-stream": "Amazon Bedrock Converse API"
|
|
38
|
+
};
|
|
39
|
+
var COMPAT_FLAGS = {
|
|
40
|
+
supportsDeveloperRole: {
|
|
41
|
+
description: 'Use "system" instead of "developer" role',
|
|
42
|
+
values: ["true", "false"]
|
|
43
|
+
},
|
|
44
|
+
supportsReasoningEffort: {
|
|
45
|
+
description: "Provider supports reasoning effort parameter",
|
|
46
|
+
values: ["true", "false"]
|
|
47
|
+
},
|
|
48
|
+
maxTokensField: {
|
|
49
|
+
description: 'Token field name ("max_tokens" or "max_completion_tokens")',
|
|
50
|
+
values: ["max_tokens", "max_completion_tokens"]
|
|
51
|
+
},
|
|
52
|
+
requiresToolResultName: {
|
|
53
|
+
description: "Tool results need name field",
|
|
54
|
+
values: ["true", "false"]
|
|
55
|
+
},
|
|
56
|
+
thinkingFormat: {
|
|
57
|
+
description: "Thinking token format (e.g., qwen, deepseek)",
|
|
58
|
+
values: ["qwen", "deepseek", "default"]
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function getLocalProvider(config) {
|
|
62
|
+
for (const [name, provider] of Object.entries(config.providers)) {
|
|
63
|
+
const url = provider.baseUrl || "";
|
|
64
|
+
if (url.includes("localhost") || url.includes("127.0.0.1") || url.includes("0.0.0.0") || name === "ollama") {
|
|
65
|
+
return { name, isLocal: true };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const first = Object.keys(config.providers)[0];
|
|
69
|
+
return { name: first || "ollama", isLocal: false };
|
|
70
|
+
}
|
|
71
|
+
function resolveProvider(config, explicit) {
|
|
72
|
+
const target = explicit || getLocalProvider(config).name;
|
|
73
|
+
const provider = config.providers[target];
|
|
74
|
+
if (!provider) return null;
|
|
75
|
+
return { name: target, config: provider };
|
|
76
|
+
}
|
|
77
|
+
function api_temp_default(pi) {
|
|
78
|
+
const branding = [
|
|
79
|
+
` \u26A1 Pi API Mode Switcher v1.0.3`,
|
|
80
|
+
` Written by VTSTech`,
|
|
81
|
+
` GitHub: https://github.com/VTSTech`,
|
|
82
|
+
` Website: www.vts-tech.org`
|
|
83
|
+
].join("\n");
|
|
84
|
+
pi.registerCommand("api", {
|
|
85
|
+
description: "View and switch API modes, base URLs, thinking, and compat flags",
|
|
86
|
+
handler: async (args, ctx) => {
|
|
87
|
+
const parts = args.trim().split(/\s+/);
|
|
88
|
+
const sub = parts[0]?.toLowerCase() || "";
|
|
89
|
+
const rest = parts.slice(1).join(" ");
|
|
90
|
+
const config = (0, import_ollama.readModelsJson)();
|
|
91
|
+
const provider = resolveProvider(config);
|
|
92
|
+
if (!provider) {
|
|
93
|
+
ctx.ui.notify("No providers found in models.json", "error");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
switch (sub) {
|
|
97
|
+
case "":
|
|
98
|
+
case "show":
|
|
99
|
+
return showConfig(provider);
|
|
100
|
+
case "mode":
|
|
101
|
+
return setMode(ctx, provider.name, rest);
|
|
102
|
+
case "url":
|
|
103
|
+
return setUrl(ctx, provider.name, rest);
|
|
104
|
+
case "think":
|
|
105
|
+
return setThink(ctx, provider.name, rest);
|
|
106
|
+
case "compat":
|
|
107
|
+
return handleCompat(ctx, provider.name, rest);
|
|
108
|
+
case "reload":
|
|
109
|
+
return reloadConfig(ctx);
|
|
110
|
+
case "modes":
|
|
111
|
+
return listModes();
|
|
112
|
+
case "providers":
|
|
113
|
+
return listProviders(config);
|
|
114
|
+
default:
|
|
115
|
+
ctx.ui.notify(`Unknown sub-command: "${sub}". Use: mode, url, think, compat, reload, modes, providers`, "error");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
function showConfig(provider) {
|
|
120
|
+
const p = provider.config;
|
|
121
|
+
const compat = p.compat || {};
|
|
122
|
+
const modelCount = p.models?.length || 0;
|
|
123
|
+
const firstModel = p.models?.[0]?.id || "none";
|
|
124
|
+
const lines = [branding];
|
|
125
|
+
lines.push((0, import_format.section)("CURRENT PROVIDER CONFIG"));
|
|
126
|
+
lines.push((0, import_format.info)(`Provider: ${provider.name}`));
|
|
127
|
+
lines.push((0, import_format.info)(`API mode: ${p.api || "(not set)"}`));
|
|
128
|
+
lines.push((0, import_format.info)(`Base URL: ${p.baseUrl || "(not set)"}`));
|
|
129
|
+
lines.push((0, import_format.info)(`API key: ${p.apiKey ? "\u2022\u2022\u2022\u2022" + String(p.apiKey).slice(-4) : "(not set)"}`));
|
|
130
|
+
lines.push((0, import_format.info)(`Models: ${modelCount} (first: ${firstModel})`));
|
|
131
|
+
if (Object.keys(compat).length > 0) {
|
|
132
|
+
lines.push((0, import_format.section)("COMPAT FLAGS"));
|
|
133
|
+
for (const [key, value] of Object.entries(compat)) {
|
|
134
|
+
lines.push((0, import_format.info)(` ${key}: ${JSON.stringify(value)}`));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const ollamaBase = (0, import_ollama.getOllamaBaseUrl)();
|
|
138
|
+
lines.push((0, import_format.section)("RESOLVED"));
|
|
139
|
+
lines.push((0, import_format.info)(`Ollama base: ${ollamaBase}`));
|
|
140
|
+
lines.push((0, import_format.info)(`(strip /v1 \u2192 ${ollamaBase})`));
|
|
141
|
+
pi.sendMessage({
|
|
142
|
+
customType: "api-config",
|
|
143
|
+
content: lines.join("\n"),
|
|
144
|
+
display: { type: "content", content: lines.join("\n") }
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function setMode(ctx, providerName, mode) {
|
|
148
|
+
if (!mode) {
|
|
149
|
+
ctx.ui.notify("Usage: /api mode <mode>. Use /api modes to list available modes.", "error");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const modeLower = mode.toLowerCase();
|
|
153
|
+
let matched = Object.keys(API_MODES).find((m) => m === modeLower);
|
|
154
|
+
if (!matched) {
|
|
155
|
+
matched = Object.keys(API_MODES).find((m) => m.includes(modeLower));
|
|
156
|
+
}
|
|
157
|
+
if (!matched) {
|
|
158
|
+
ctx.ui.notify(`Unknown API mode: "${mode}". Use /api modes to list available modes.`, "error");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const config = (0, import_ollama.readModelsJson)();
|
|
162
|
+
const provider = config.providers[providerName];
|
|
163
|
+
if (!provider) {
|
|
164
|
+
ctx.ui.notify(`Provider "${providerName}" not found in models.json`, "error");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const oldMode = provider.api || "(not set)";
|
|
168
|
+
provider.api = matched;
|
|
169
|
+
(0, import_ollama.writeModelsJson)(config);
|
|
170
|
+
const lines = [branding];
|
|
171
|
+
lines.push((0, import_format.section)("API MODE CHANGED"));
|
|
172
|
+
lines.push((0, import_format.ok)(`Provider: ${providerName}`));
|
|
173
|
+
lines.push((0, import_format.info)(`Old mode: ${oldMode}`));
|
|
174
|
+
lines.push((0, import_format.ok)(`New mode: ${matched}`));
|
|
175
|
+
lines.push((0, import_format.info)(`Description: ${API_MODES[matched]}`));
|
|
176
|
+
lines.push((0, import_format.warn)("Run /api reload or /reload to apply changes in Pi"));
|
|
177
|
+
pi.sendMessage({
|
|
178
|
+
customType: "api-mode-changed",
|
|
179
|
+
content: lines.join("\n"),
|
|
180
|
+
display: { type: "content", content: lines.join("\n") }
|
|
181
|
+
});
|
|
182
|
+
ctx.ui.notify(`API mode set to ${matched}`, "success");
|
|
183
|
+
}
|
|
184
|
+
function setUrl(ctx, providerName, url) {
|
|
185
|
+
if (!url) {
|
|
186
|
+
ctx.ui.notify("Usage: /api url <base-url>", "error");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
let normalizedUrl = url.trim();
|
|
190
|
+
if (!normalizedUrl.startsWith("http")) {
|
|
191
|
+
normalizedUrl = "http://" + normalizedUrl;
|
|
192
|
+
}
|
|
193
|
+
const config = (0, import_ollama.readModelsJson)();
|
|
194
|
+
const provider = config.providers[providerName];
|
|
195
|
+
if (!provider) {
|
|
196
|
+
ctx.ui.notify(`Provider "${providerName}" not found in models.json`, "error");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const oldUrl = provider.baseUrl || "(not set)";
|
|
200
|
+
provider.baseUrl = normalizedUrl;
|
|
201
|
+
(0, import_ollama.writeModelsJson)(config);
|
|
202
|
+
const lines = [branding];
|
|
203
|
+
lines.push((0, import_format.section)("BASE URL CHANGED"));
|
|
204
|
+
lines.push((0, import_format.ok)(`Provider: ${providerName}`));
|
|
205
|
+
lines.push((0, import_format.info)(`Old URL: ${oldUrl}`));
|
|
206
|
+
lines.push((0, import_format.ok)(`New URL: ${normalizedUrl}`));
|
|
207
|
+
lines.push((0, import_format.warn)("Run /api reload or /reload to apply changes in Pi"));
|
|
208
|
+
pi.sendMessage({
|
|
209
|
+
customType: "api-url-changed",
|
|
210
|
+
content: lines.join("\n"),
|
|
211
|
+
display: { type: "content", content: lines.join("\n") }
|
|
212
|
+
});
|
|
213
|
+
ctx.ui.notify(`Base URL set to ${normalizedUrl}`, "success");
|
|
214
|
+
}
|
|
215
|
+
function setThink(ctx, providerName, value) {
|
|
216
|
+
if (!value) {
|
|
217
|
+
ctx.ui.notify("Usage: /api think <on|off|auto>", "error");
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const config = (0, import_ollama.readModelsJson)();
|
|
221
|
+
const provider = config.providers[providerName];
|
|
222
|
+
if (!provider) {
|
|
223
|
+
ctx.ui.notify(`Provider "${providerName}" not found in models.json`, "error");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const models = provider.models || [];
|
|
227
|
+
if (models.length === 0) {
|
|
228
|
+
ctx.ui.notify(`No models found in provider "${providerName}"`, "error");
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const valLower = value.toLowerCase();
|
|
232
|
+
const setAll = (state) => {
|
|
233
|
+
for (const model of models) {
|
|
234
|
+
if (state === null) {
|
|
235
|
+
const name = (model.id || "").toLowerCase();
|
|
236
|
+
model.reasoning = name.includes("deepseek-r1") || name.includes("qwq") || name.includes("o1") || name.includes("o3") || name.includes("think") || name.includes("qwen3");
|
|
237
|
+
} else {
|
|
238
|
+
model.reasoning = state;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
if (valLower === "on" || valLower === "true" || valLower === "1") {
|
|
243
|
+
setAll(true);
|
|
244
|
+
} else if (valLower === "off" || valLower === "false" || valLower === "0") {
|
|
245
|
+
setAll(false);
|
|
246
|
+
} else if (valLower === "auto") {
|
|
247
|
+
setAll(null);
|
|
248
|
+
} else {
|
|
249
|
+
ctx.ui.notify("Invalid value. Use: on, off, or auto", "error");
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
(0, import_ollama.writeModelsJson)(config);
|
|
253
|
+
const lines = [branding];
|
|
254
|
+
lines.push((0, import_format.section)("THINKING MODE"));
|
|
255
|
+
lines.push((0, import_format.info)(`Provider: ${providerName}`));
|
|
256
|
+
lines.push((0, import_format.info)(`Mode: ${valLower}`));
|
|
257
|
+
lines.push((0, import_format.info)(`Affected ${models.length} model(s):`));
|
|
258
|
+
for (const model of models) {
|
|
259
|
+
lines.push((0, import_format.info)(` ${(model.id || "?").padEnd(40)} reasoning: ${model.reasoning ? "true" : "false"}`));
|
|
260
|
+
}
|
|
261
|
+
lines.push((0, import_format.warn)("Run /api reload or /reload to apply changes in Pi"));
|
|
262
|
+
pi.sendMessage({
|
|
263
|
+
customType: "api-think-changed",
|
|
264
|
+
content: lines.join("\n"),
|
|
265
|
+
display: { type: "content", content: lines.join("\n") }
|
|
266
|
+
});
|
|
267
|
+
ctx.ui.notify(`Thinking set to ${valLower} for ${models.length} model(s)`, "success");
|
|
268
|
+
}
|
|
269
|
+
function handleCompat(ctx, providerName, args) {
|
|
270
|
+
const parts = args.split(/\s+/);
|
|
271
|
+
const key = parts[0];
|
|
272
|
+
const value = parts.slice(1).join(" ");
|
|
273
|
+
if (!key) {
|
|
274
|
+
const config2 = (0, import_ollama.readModelsJson)();
|
|
275
|
+
const provider2 = config2.providers[providerName];
|
|
276
|
+
if (!provider2) {
|
|
277
|
+
ctx.ui.notify(`Provider "${providerName}" not found`, "error");
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const compat = provider2.compat || {};
|
|
281
|
+
const lines2 = [branding];
|
|
282
|
+
lines2.push((0, import_format.section)("COMPAT FLAGS"));
|
|
283
|
+
if (Object.keys(compat).length === 0) {
|
|
284
|
+
lines2.push((0, import_format.info)("No compat flags set"));
|
|
285
|
+
} else {
|
|
286
|
+
for (const [k, v] of Object.entries(compat)) {
|
|
287
|
+
const flag = COMPAT_FLAGS[k];
|
|
288
|
+
lines2.push((0, import_format.info)(` ${k}: ${JSON.stringify(v)}${flag ? ` \u2014 ${flag.description}` : ""}`));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
lines2.push((0, import_format.section)("AVAILABLE FLAGS"));
|
|
292
|
+
for (const [k, flag] of Object.entries(COMPAT_FLAGS)) {
|
|
293
|
+
lines2.push((0, import_format.info)(` ${k} = <${flag.values.join(" | ")}> \u2014 ${flag.description}`));
|
|
294
|
+
}
|
|
295
|
+
lines2.push((0, import_format.info)("Usage: /api compat <key> <value>"));
|
|
296
|
+
pi.sendMessage({
|
|
297
|
+
customType: "api-compat-flags",
|
|
298
|
+
content: lines2.join("\n"),
|
|
299
|
+
display: { type: "content", content: lines2.join("\n") }
|
|
300
|
+
});
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (!value) {
|
|
304
|
+
const config2 = (0, import_ollama.readModelsJson)();
|
|
305
|
+
const provider2 = config2.providers[providerName];
|
|
306
|
+
if (!provider2) {
|
|
307
|
+
ctx.ui.notify(`Provider "${providerName}" not found`, "error");
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const current = provider2.compat?.[key];
|
|
311
|
+
ctx.ui.notify(`${key} = ${current !== void 0 ? JSON.stringify(current) : "(not set)"}`, "info");
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const config = (0, import_ollama.readModelsJson)();
|
|
315
|
+
const provider = config.providers[providerName];
|
|
316
|
+
if (!provider) {
|
|
317
|
+
ctx.ui.notify(`Provider "${providerName}" not found`, "error");
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (!provider.compat) provider.compat = {};
|
|
321
|
+
let parsedValue = value;
|
|
322
|
+
if (value === "true") parsedValue = true;
|
|
323
|
+
else if (value === "false") parsedValue = false;
|
|
324
|
+
else if (value === "null") parsedValue = null;
|
|
325
|
+
else {
|
|
326
|
+
try {
|
|
327
|
+
parsedValue = JSON.parse(value);
|
|
328
|
+
} catch {
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const oldValue = provider.compat[key];
|
|
332
|
+
provider.compat[key] = parsedValue;
|
|
333
|
+
(0, import_ollama.writeModelsJson)(config);
|
|
334
|
+
const lines = [branding];
|
|
335
|
+
lines.push((0, import_format.section)("COMPAT FLAG SET"));
|
|
336
|
+
lines.push((0, import_format.ok)(`Provider: ${providerName}`));
|
|
337
|
+
lines.push((0, import_format.info)(`Key: ${key}`));
|
|
338
|
+
lines.push((0, import_format.info)(`Old value: ${oldValue !== void 0 ? JSON.stringify(oldValue) : "(not set)"}`));
|
|
339
|
+
lines.push((0, import_format.ok)(`New value: ${JSON.stringify(parsedValue)}`));
|
|
340
|
+
lines.push((0, import_format.warn)("Run /api reload or /reload to apply changes in Pi"));
|
|
341
|
+
pi.sendMessage({
|
|
342
|
+
customType: "api-compat-set",
|
|
343
|
+
content: lines.join("\n"),
|
|
344
|
+
display: { type: "content", content: lines.join("\n") }
|
|
345
|
+
});
|
|
346
|
+
ctx.ui.notify(`Compat flag ${key} set to ${JSON.stringify(parsedValue)}`, "success");
|
|
347
|
+
}
|
|
348
|
+
function reloadConfig(ctx) {
|
|
349
|
+
const lines = [branding];
|
|
350
|
+
lines.push((0, import_format.section)("RELOAD"));
|
|
351
|
+
lines.push((0, import_format.ok)("models.json has been modified"));
|
|
352
|
+
lines.push((0, import_format.info)("To apply changes, run Pi's built-in command:"));
|
|
353
|
+
lines.push((0, import_format.info)(" /reload"));
|
|
354
|
+
lines.push((0, import_format.warn)("This will reload all provider configurations from models.json"));
|
|
355
|
+
pi.sendMessage({
|
|
356
|
+
customType: "api-reload",
|
|
357
|
+
content: lines.join("\n"),
|
|
358
|
+
display: { type: "content", content: lines.join("\n") }
|
|
359
|
+
});
|
|
360
|
+
ctx.ui.notify("Run /reload to apply models.json changes", "info");
|
|
361
|
+
}
|
|
362
|
+
function listModes() {
|
|
363
|
+
const lines = [branding];
|
|
364
|
+
lines.push((0, import_format.section)("SUPPORTED API MODES"));
|
|
365
|
+
const config = (0, import_ollama.readModelsJson)();
|
|
366
|
+
const provider = resolveProvider(config);
|
|
367
|
+
const currentMode = provider?.config?.api || "(not set)";
|
|
368
|
+
for (const [mode, description] of Object.entries(API_MODES)) {
|
|
369
|
+
const isActive = mode === currentMode;
|
|
370
|
+
const marker = isActive ? (0, import_format.ok)(" \u25C0 current") : "";
|
|
371
|
+
lines.push((0, import_format.info)(` ${mode.padEnd(30)} ${description}${marker}`));
|
|
372
|
+
}
|
|
373
|
+
lines.push((0, import_format.info)(""));
|
|
374
|
+
lines.push((0, import_format.info)("Usage: /api mode <mode>"));
|
|
375
|
+
pi.sendMessage({
|
|
376
|
+
customType: "api-modes",
|
|
377
|
+
content: lines.join("\n"),
|
|
378
|
+
display: { type: "content", content: lines.join("\n") }
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
function listProviders(config) {
|
|
382
|
+
const lines = [branding];
|
|
383
|
+
lines.push((0, import_format.section)("PROVIDERS"));
|
|
384
|
+
for (const [name, provider] of Object.entries(config.providers)) {
|
|
385
|
+
const modelCount = provider.models?.length || 0;
|
|
386
|
+
const url = provider.baseUrl || "(no URL)";
|
|
387
|
+
const api = provider.api || "(no mode)";
|
|
388
|
+
const isLocal = url.includes("localhost") || url.includes("127.0.0.1") || name === "ollama";
|
|
389
|
+
lines.push((0, import_format.info)(` ${name}${isLocal ? " (local)" : ""}`));
|
|
390
|
+
lines.push((0, import_format.info)(` API: ${api} | URL: ${url} | Models: ${modelCount}`));
|
|
391
|
+
}
|
|
392
|
+
pi.sendMessage({
|
|
393
|
+
customType: "api-providers",
|
|
394
|
+
content: lines.join("\n"),
|
|
395
|
+
display: { type: "content", content: lines.join("\n") }
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
pi.registerCompletion?.("api", {
|
|
399
|
+
getCompletions: () => {
|
|
400
|
+
return [
|
|
401
|
+
{ value: "mode", label: "mode", description: "Switch API mode" },
|
|
402
|
+
{ value: "url", label: "url", description: "Switch base URL" },
|
|
403
|
+
{ value: "think", label: "think", description: "Toggle thinking mode (on/off/auto)" },
|
|
404
|
+
{ value: "compat", label: "compat", description: "View/set compat flags" },
|
|
405
|
+
{ value: "reload", label: "reload", description: "Reload models.json" },
|
|
406
|
+
{ value: "modes", label: "modes", description: "List all supported API modes" },
|
|
407
|
+
{ value: "providers", label: "providers", description: "List all configured providers" }
|
|
408
|
+
];
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vtstech/pi-api",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "API Mode Switcher extension for Pi Coding Agent",
|
|
5
|
+
"main": "api.js",
|
|
6
|
+
"keywords": ["pi-package", "pi-extensions"],
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"access": "public",
|
|
9
|
+
"author": "VTSTech",
|
|
10
|
+
"homepage": "https://www.vts-tech.org",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/VTSTech/pi-coding-agent"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@vtstech/pi-shared": "1.0.3"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@mariozechner/pi-coding-agent": ">=0.66"
|
|
20
|
+
},
|
|
21
|
+
"pi": {
|
|
22
|
+
"extensions": ["./api.js"]
|
|
23
|
+
}
|
|
24
|
+
}
|