@cremini/skillpack 1.2.4 → 1.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/cli.js CHANGED
@@ -107,6 +107,12 @@ var init_config = __esm({
107
107
  if (updates.baseUrl !== void 0) {
108
108
  this.configData.baseUrl = updates.baseUrl?.trim() || void 0;
109
109
  }
110
+ if (updates.modelId !== void 0) {
111
+ this.configData.modelId = updates.modelId?.trim() || void 0;
112
+ }
113
+ if (updates.apiProtocol !== void 0) {
114
+ this.configData.apiProtocol = updates.apiProtocol || void 0;
115
+ }
110
116
  if (updates.adapters !== void 0) {
111
117
  const merged = { ...this.configData.adapters || {} };
112
118
  for (const [adapterKey, adapterVal] of Object.entries(updates.adapters)) {
@@ -5565,10 +5571,30 @@ var PackAgent = class {
5565
5571
  const { rootDir, provider, modelId, baseUrl } = this.options;
5566
5572
  const authStorage = this.authStorage;
5567
5573
  const modelRegistry = new ModelRegistry(authStorage);
5574
+ if (baseUrl && modelId) {
5575
+ const apiProtocol = this.options.apiProtocol ?? "openai-completions";
5576
+ log(`[PackAgent] Registering custom model ${provider}/${modelId} api=${apiProtocol} baseUrl=${baseUrl}`);
5577
+ modelRegistry.registerProvider(provider, {
5578
+ baseUrl,
5579
+ apiKey: this.options.apiKey,
5580
+ models: [
5581
+ {
5582
+ id: modelId,
5583
+ name: modelId,
5584
+ api: apiProtocol,
5585
+ reasoning: false,
5586
+ input: ["text"],
5587
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
5588
+ contextWindow: 128e3,
5589
+ maxTokens: 4096
5590
+ }
5591
+ ]
5592
+ });
5593
+ }
5568
5594
  const resolvedModel = modelRegistry.find(provider, modelId);
5569
- const model = resolvedModel && baseUrl ? { ...resolvedModel, baseUrl } : resolvedModel;
5595
+ const model = resolvedModel && baseUrl && !this.options.apiProtocol ? { ...resolvedModel, baseUrl } : resolvedModel;
5570
5596
  if (resolvedModel && baseUrl) {
5571
- log(`[PackAgent] Overriding ${provider}/${modelId} baseUrl -> ${baseUrl}`);
5597
+ log(`[PackAgent] Resolved ${provider}/${modelId} api=${resolvedModel.api} baseUrl=${baseUrl}`);
5572
5598
  }
5573
5599
  const sessionDir = path9.resolve(
5574
5600
  rootDir,
@@ -5859,6 +5885,8 @@ function getRuntimeConfigSignature(config) {
5859
5885
  apiKey: config.apiKey || "",
5860
5886
  provider: config.provider || "openai",
5861
5887
  baseUrl: config.baseUrl || "",
5888
+ modelId: config.modelId || "",
5889
+ apiProtocol: config.apiProtocol || "",
5862
5890
  telegramToken: config.adapters?.telegram?.token || "",
5863
5891
  slackBotToken: config.adapters?.slack?.botToken || "",
5864
5892
  slackAppToken: config.adapters?.slack?.appToken || ""
@@ -5889,6 +5917,8 @@ var WebAdapter = class {
5889
5917
  apiKey: conf.apiKey || "",
5890
5918
  provider: currentProvider2,
5891
5919
  baseUrl: conf.baseUrl || "",
5920
+ modelId: conf.modelId || "",
5921
+ apiProtocol: conf.apiProtocol || "",
5892
5922
  adapters: conf.adapters || {},
5893
5923
  supportedProviders: SUPPORTED_PROVIDERS,
5894
5924
  oauthConnected
@@ -5899,7 +5929,7 @@ var WebAdapter = class {
5899
5929
  res.json(config.skills || []);
5900
5930
  });
5901
5931
  app.post("/api/config/update", (req, res) => {
5902
- const { key, provider, baseUrl, adapters } = req.body;
5932
+ const { key, provider, baseUrl, modelId, apiProtocol, adapters } = req.body;
5903
5933
  const updates = {};
5904
5934
  const beforeConfig = JSON.parse(JSON.stringify(configManager.getConfig()));
5905
5935
  if (key !== void 0) {
@@ -5913,6 +5943,12 @@ var WebAdapter = class {
5913
5943
  if (baseUrl !== void 0) {
5914
5944
  updates.baseUrl = baseUrl;
5915
5945
  }
5946
+ if (modelId !== void 0) {
5947
+ updates.modelId = modelId;
5948
+ }
5949
+ if (apiProtocol !== void 0) {
5950
+ updates.apiProtocol = apiProtocol;
5951
+ }
5916
5952
  if (adapters !== void 0) {
5917
5953
  updates.adapters = adapters;
5918
5954
  }
@@ -6402,7 +6438,8 @@ async function startServer(options) {
6402
6438
  const canonicalRootDir = canonicalizeDir(rootDir);
6403
6439
  const packConfig = loadConfig(canonicalRootDir);
6404
6440
  const baseUrl = dataConfig.baseUrl?.trim() || void 0;
6405
- const modelId = SUPPORTED_PROVIDERS[provider]?.defaultModelId ?? SUPPORTED_PROVIDERS.openai.defaultModelId;
6441
+ const modelId = dataConfig.modelId?.trim() || (SUPPORTED_PROVIDERS[provider]?.defaultModelId ?? SUPPORTED_PROVIDERS.openai.defaultModelId);
6442
+ const apiProtocol = dataConfig.apiProtocol;
6406
6443
  const packageRoot = path13.resolve(__dirname, "..");
6407
6444
  const webDir = fs14.existsSync(path13.join(rootDir, "web")) ? path13.join(rootDir, "web") : path13.join(packageRoot, "web");
6408
6445
  const app = express();
@@ -6428,6 +6465,7 @@ async function startServer(options) {
6428
6465
  provider,
6429
6466
  modelId,
6430
6467
  baseUrl,
6468
+ apiProtocol,
6431
6469
  lifecycleHandler: lifecycle
6432
6470
  });
6433
6471
  const adapters = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cremini/skillpack",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "description": "Pack AI Skills into Local Agents",
5
5
  "type": "module",
6
6
  "repository": {
@@ -65,4 +65,4 @@
65
65
  "tsup": "^8.5.1",
66
66
  "typescript": "^5.9.3"
67
67
  }
68
- }
68
+ }
@@ -7,7 +7,7 @@ set "FIRST_RUN=1"
7
7
  :loop
8
8
  set "SKILLPACK_FIRST_RUN=%FIRST_RUN%"
9
9
  set "PACK_ROOT=%~dp0"
10
- npx -y @cremini/skillpack run .
10
+ npx -y @cremini/skillpack@latest run .
11
11
  set "EXIT_CODE=%errorlevel%"
12
12
 
13
13
  set "FIRST_RUN=0"
@@ -7,7 +7,7 @@ FIRST_RUN=1
7
7
  while true; do
8
8
  SKILLPACK_FIRST_RUN="$FIRST_RUN" \
9
9
  PACK_ROOT="$(pwd)" \
10
- npx -y @cremini/skillpack run .
10
+ npx -y @cremini/skillpack@latest run .
11
11
  EXIT_CODE=$?
12
12
 
13
13
  FIRST_RUN=0
package/web/index.html CHANGED
@@ -96,6 +96,19 @@
96
96
  <label>Custom Base URL <span class="label-hint">(optional)</span></label>
97
97
  <input type="text" id="apikey-baseurl-input" placeholder="https://api.openai.com/v1" class="form-input" />
98
98
  </div>
99
+ <div class="form-group" id="apikey-modelid-group" style="display: none;">
100
+ <label>Custom Model Name <span class="label-hint">(optional)</span></label>
101
+ <input type="text" id="apikey-modelid-input" placeholder="e.g. gpt-4o, llama-3-70b" class="form-input" />
102
+ </div>
103
+ <div class="form-group" id="apikey-protocol-group" style="display: none;">
104
+ <label>API Protocol</label>
105
+ <div class="provider-select-wrapper">
106
+ <select id="apikey-protocol-select" class="form-input">
107
+ <option value="openai-completions">Chat Completions API (most proxies)</option>
108
+ <option value="openai-responses">Responses API (native OpenAI)</option>
109
+ </select>
110
+ </div>
111
+ </div>
99
112
  </div>
100
113
 
101
114
  <!-- OAuth Section -->
@@ -16,6 +16,10 @@ let providerSelect;
16
16
  let apiKeyInput;
17
17
  let baseUrlInput;
18
18
  let baseUrlGroup;
19
+ let modelIdInput;
20
+ let modelIdGroup;
21
+ let protocolSelect;
22
+ let protocolGroup;
19
23
  let apikeySection;
20
24
  let oauthSection;
21
25
  let oauthLoginBtn;
@@ -36,6 +40,10 @@ export function initApiKeyDialog() {
36
40
  apiKeyInput = document.getElementById("apikey-input");
37
41
  baseUrlInput = document.getElementById("apikey-baseurl-input");
38
42
  baseUrlGroup = document.getElementById("apikey-baseurl-group");
43
+ modelIdInput = document.getElementById("apikey-modelid-input");
44
+ modelIdGroup = document.getElementById("apikey-modelid-group");
45
+ protocolSelect = document.getElementById("apikey-protocol-select");
46
+ protocolGroup = document.getElementById("apikey-protocol-group");
39
47
  apikeySection = document.getElementById("apikey-apikey-section");
40
48
  oauthSection = document.getElementById("apikey-oauth-section");
41
49
  oauthLoginBtn = document.getElementById("oauth-login-btn");
@@ -67,6 +75,9 @@ export function initApiKeyDialog() {
67
75
  if (oauthLogoutBtn) {
68
76
  oauthLogoutBtn.addEventListener("click", handleOAuthLogout);
69
77
  }
78
+ if (baseUrlInput) {
79
+ baseUrlInput.addEventListener("input", updateModelIdVisibility);
80
+ }
70
81
  }
71
82
 
72
83
  /**
@@ -126,6 +137,12 @@ function populateForm() {
126
137
  if (baseUrlInput) {
127
138
  baseUrlInput.value = config.baseUrl || "";
128
139
  }
140
+ if (modelIdInput) {
141
+ modelIdInput.value = config.modelId || "";
142
+ }
143
+ if (protocolSelect) {
144
+ protocolSelect.value = config.apiProtocol || "openai-completions";
145
+ }
129
146
 
130
147
  // OAuth Status
131
148
  if (config.oauthConnected) {
@@ -163,6 +180,9 @@ function updateProviderUI() {
163
180
  baseUrlInput.placeholder =
164
181
  meta.baseUrlPlaceholder || "https://api.openai.com/v1";
165
182
  }
183
+
184
+ // Show model name field only when a custom base URL is filled in
185
+ updateModelIdVisibility();
166
186
 
167
187
  // Update placeholder
168
188
  if (apiKeyInput) {
@@ -171,10 +191,21 @@ function updateProviderUI() {
171
191
  }
172
192
  }
173
193
 
194
+ function updateModelIdVisibility() {
195
+ if (!modelIdGroup) return;
196
+ const hasCustomUrl = baseUrlInput && baseUrlInput.value.trim().length > 0;
197
+ modelIdGroup.style.display = hasCustomUrl ? "" : "none";
198
+ if (protocolGroup) {
199
+ protocolGroup.style.display = hasCustomUrl ? "" : "none";
200
+ }
201
+ }
202
+
174
203
  async function handleSave() {
175
204
  const key = apiKeyInput.value.trim();
176
205
  const provider = providerSelect.value;
177
206
  const baseUrl = baseUrlInput.value.trim();
207
+ const modelId = modelIdInput ? modelIdInput.value.trim() : "";
208
+ const apiProtocol = protocolSelect ? protocolSelect.value : "";
178
209
 
179
210
  // If OAuth is selected, we don't handle it here but it shouldn't happen as save button is hidden
180
211
  const meta = state.config?.supportedProviders?.[provider];
@@ -184,6 +215,15 @@ async function handleSave() {
184
215
  if (baseUrl !== state.config.baseUrl) {
185
216
  updates.baseUrl = baseUrl;
186
217
  }
218
+ if (modelId !== (state.config.modelId || "")) {
219
+ updates.modelId = modelId;
220
+ }
221
+ const hasCustomUrl = baseUrl.length > 0;
222
+ if (hasCustomUrl && apiProtocol !== (state.config.apiProtocol || "openai-completions")) {
223
+ updates.apiProtocol = apiProtocol;
224
+ } else if (!hasCustomUrl && state.config.apiProtocol) {
225
+ updates.apiProtocol = "";
226
+ }
187
227
 
188
228
  if (key && key !== "***************************************************" && key !== state.config.apiKey) {
189
229
  updates.key = key;
@@ -195,6 +235,8 @@ async function handleSave() {
195
235
 
196
236
  state.config.provider = res.provider;
197
237
  state.config.baseUrl = res.baseUrl || "";
238
+ state.config.modelId = res.modelId || "";
239
+ state.config.apiProtocol = res.apiProtocol || "";
198
240
  if (updates.key) {
199
241
  state.config.hasApiKey = true;
200
242
  state.config.apiKey = updates.key;