@vtstech/pi-openrouter-sync 1.2.1 → 1.2.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/openrouter-sync.js +107 -13
- package/package.json +10 -6
package/openrouter-sync.js
CHANGED
|
@@ -1,12 +1,106 @@
|
|
|
1
|
-
//
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// shared/ollama.ts
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
|
|
6
|
+
// shared/debug.ts
|
|
7
|
+
var DEBUG_ENABLED = process?.env?.PI_EXTENSIONS_DEBUG === "1";
|
|
8
|
+
function debugLog(module, message, ...args) {
|
|
9
|
+
if (!DEBUG_ENABLED) return;
|
|
10
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
11
|
+
console.debug(`[pi-ext:${module}] ${timestamp} ${message}`, ...args);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// shared/ollama.ts
|
|
15
|
+
var EXTENSION_VERSION = "1.2.3";
|
|
16
|
+
var MODELS_JSON_PATH = path.join(os.homedir(), ".pi", "agent", "models.json");
|
|
17
|
+
var _modelsJsonCache = null;
|
|
18
|
+
var _ollamaBaseUrlCache = null;
|
|
19
|
+
var CACHE_TTL_MS = 2e3;
|
|
20
|
+
function readModelsJson() {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
if (_modelsJsonCache && now - _modelsJsonCache.ts < CACHE_TTL_MS) return _modelsJsonCache.data;
|
|
23
|
+
try {
|
|
24
|
+
if (fs.existsSync(MODELS_JSON_PATH)) {
|
|
25
|
+
const raw = fs.readFileSync(MODELS_JSON_PATH, "utf-8");
|
|
26
|
+
const data = JSON.parse(raw);
|
|
27
|
+
_modelsJsonCache = { data, ts: now };
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
} catch (err) {
|
|
31
|
+
debugLog("ollama", "failed to read/parse models.json", err);
|
|
32
|
+
}
|
|
33
|
+
const empty = { providers: {} };
|
|
34
|
+
_modelsJsonCache = { data: empty, ts: now };
|
|
35
|
+
return empty;
|
|
36
|
+
}
|
|
37
|
+
function writeModelsJson(data) {
|
|
38
|
+
const dir = path.dirname(MODELS_JSON_PATH);
|
|
39
|
+
if (!fs.existsSync(dir)) {
|
|
40
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
const tmpPath = MODELS_JSON_PATH + ".tmp";
|
|
43
|
+
fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
44
|
+
fs.renameSync(tmpPath, MODELS_JSON_PATH);
|
|
45
|
+
_modelsJsonCache = null;
|
|
46
|
+
_ollamaBaseUrlCache = null;
|
|
47
|
+
}
|
|
48
|
+
var _modelsJsonLock = null;
|
|
49
|
+
async function acquireModelsJsonLock() {
|
|
50
|
+
while (_modelsJsonLock) {
|
|
51
|
+
await _modelsJsonLock;
|
|
52
|
+
}
|
|
53
|
+
let releaseLock;
|
|
54
|
+
_modelsJsonLock = new Promise((resolve) => {
|
|
55
|
+
releaseLock = resolve;
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
release: () => {
|
|
59
|
+
releaseLock();
|
|
60
|
+
_modelsJsonLock = null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function readModifyWriteModelsJson(modifier) {
|
|
65
|
+
const { release } = await acquireModelsJsonLock();
|
|
66
|
+
try {
|
|
67
|
+
const data = readModelsJson();
|
|
68
|
+
const modified = modifier(data);
|
|
69
|
+
if (modified === null) return false;
|
|
70
|
+
writeModelsJson(modified);
|
|
71
|
+
return true;
|
|
72
|
+
} finally {
|
|
73
|
+
release();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
var BUILTIN_PROVIDERS = {
|
|
77
|
+
openrouter: { api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", envKey: "OPENROUTER_API_KEY" },
|
|
78
|
+
anthropic: { api: "anthropic-messages", baseUrl: "https://api.anthropic.com/v1", envKey: "ANTHROPIC_API_KEY" },
|
|
79
|
+
google: { api: "gemini", baseUrl: "https://generativelanguage.googleapis.com", envKey: "GOOGLE_API_KEY" },
|
|
80
|
+
openai: { api: "openai-completions", baseUrl: "https://api.openai.com/v1", envKey: "OPENAI_API_KEY" },
|
|
81
|
+
groq: { api: "openai-completions", baseUrl: "https://api.groq.com/v1", envKey: "GROQ_API_KEY" },
|
|
82
|
+
deepseek: { api: "openai-completions", baseUrl: "https://api.deepseek.com/v1", envKey: "DEEPSEEK_API_KEY" },
|
|
83
|
+
mistral: { api: "openai-completions", baseUrl: "https://api.mistral.ai/v1", envKey: "MISTRAL_API_KEY" },
|
|
84
|
+
xai: { api: "openai-completions", baseUrl: "https://api.x.ai/v1", envKey: "XAI_API_KEY" },
|
|
85
|
+
together: { api: "openai-completions", baseUrl: "https://api.together.xyz/v1", envKey: "TOGETHER_API_KEY" },
|
|
86
|
+
fireworks: { api: "openai-completions", baseUrl: "https://api.fireworks.ai/inference/v1", envKey: "FIREWORKS_API_KEY" },
|
|
87
|
+
cohere: { api: "cohere-chat", baseUrl: "https://api.cohere.com/v1", envKey: "COHERE_API_KEY" },
|
|
88
|
+
zai: { api: "openai-completions", baseUrl: "https://open.bigmodel.cn/api/paas/v4", envKey: "ZAI_API_KEY" }
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// shared/format.ts
|
|
92
|
+
function section(title) {
|
|
93
|
+
return `
|
|
94
|
+
\u2500\u2500 ${title} ${"\u2500".repeat(Math.max(1, 60 - title.length - 4))}`;
|
|
95
|
+
}
|
|
96
|
+
function ok(msg) {
|
|
97
|
+
return ` \u2705 ${msg}`;
|
|
98
|
+
}
|
|
99
|
+
function warn(msg) {
|
|
100
|
+
return ` \u26A0\uFE0F ${msg}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// extensions/openrouter-sync.ts
|
|
10
104
|
var BRANDING = [
|
|
11
105
|
` \u26A1 Pi OpenRouter Sync v${EXTENSION_VERSION}`,
|
|
12
106
|
` Written by VTSTech`,
|
|
@@ -66,7 +160,7 @@ async function performSync(modelIds) {
|
|
|
66
160
|
});
|
|
67
161
|
return result;
|
|
68
162
|
}
|
|
69
|
-
function
|
|
163
|
+
function openrouter_sync_default(pi) {
|
|
70
164
|
pi.registerCommand("openrouter-sync", {
|
|
71
165
|
description: "Add OpenRouter model(s) to models.json. Use: /or-sync <url-or-id> [url-or-id ...]",
|
|
72
166
|
async handler(args, ctx) {
|
|
@@ -94,7 +188,7 @@ function openrouter_sync_temp_default(pi) {
|
|
|
94
188
|
for (const id of skipped) lines.push(warn(id));
|
|
95
189
|
}
|
|
96
190
|
lines.push("");
|
|
97
|
-
lines.push(` Written to ${
|
|
191
|
+
lines.push(` Written to ${MODELS_JSON_PATH}`);
|
|
98
192
|
lines.push(` Run /reload to pick up changes`);
|
|
99
193
|
lines.push(BRANDING);
|
|
100
194
|
const report = lines.join("\n");
|
|
@@ -152,7 +246,7 @@ function openrouter_sync_temp_default(pi) {
|
|
|
152
246
|
...skipped.length > 0 ? ["\nSkipped (already present):"] : [],
|
|
153
247
|
...skipped.map((id) => ` = ${id}`),
|
|
154
248
|
"",
|
|
155
|
-
`Written to ${
|
|
249
|
+
`Written to ${MODELS_JSON_PATH}. Run /reload to pick up changes.`,
|
|
156
250
|
"",
|
|
157
251
|
"Current openrouter models:",
|
|
158
252
|
modelList
|
|
@@ -171,5 +265,5 @@ function openrouter_sync_temp_default(pi) {
|
|
|
171
265
|
});
|
|
172
266
|
}
|
|
173
267
|
export {
|
|
174
|
-
|
|
268
|
+
openrouter_sync_default as default
|
|
175
269
|
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vtstech/pi-openrouter-sync",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "OpenRouter model sync extension for Pi Coding Agent — add models from OpenRouter URLs or IDs",
|
|
5
5
|
"main": "openrouter-sync.js",
|
|
6
|
-
"keywords": [
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi",
|
|
9
|
+
"pi-coding-agent",
|
|
10
|
+
"pi-extensions"
|
|
11
|
+
],
|
|
7
12
|
"license": "MIT",
|
|
8
13
|
"access": "public",
|
|
9
14
|
"type": "module",
|
|
@@ -13,13 +18,12 @@
|
|
|
13
18
|
"type": "git",
|
|
14
19
|
"url": "https://github.com/VTSTech/pi-coding-agent"
|
|
15
20
|
},
|
|
16
|
-
"dependencies": {
|
|
17
|
-
"@vtstech/pi-shared": "1.2.1"
|
|
18
|
-
},
|
|
19
21
|
"peerDependencies": {
|
|
20
22
|
"@mariozechner/pi-coding-agent": ">=0.66"
|
|
21
23
|
},
|
|
22
24
|
"pi": {
|
|
23
|
-
"extensions": [
|
|
25
|
+
"extensions": [
|
|
26
|
+
"./openrouter-sync.js"
|
|
27
|
+
]
|
|
24
28
|
}
|
|
25
29
|
}
|