fss-link 1.1.5 → 1.1.6
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/bundle/fss-link.js +176 -43
- package/package.json +1 -1
package/bundle/fss-link.js
CHANGED
|
@@ -22090,7 +22090,7 @@ async function createContentGeneratorConfig(config, authType) {
|
|
|
22090
22090
|
async function createContentGenerator(config, gcConfig, sessionId2) {
|
|
22091
22091
|
if (DEBUG_CONTENT)
|
|
22092
22092
|
console.log(`\u{1F41B} DEBUG createContentGenerator: authType=${config.authType}, apiKey=${config.apiKey}, baseUrl=${config.baseUrl}`);
|
|
22093
|
-
const version = "1.1.
|
|
22093
|
+
const version = "1.1.6";
|
|
22094
22094
|
const userAgent = `FSS-Link/${version} (${process.platform}; ${process.arch})`;
|
|
22095
22095
|
const baseHeaders = {
|
|
22096
22096
|
"User-Agent": userAgent
|
|
@@ -81787,6 +81787,29 @@ var init_databaseMigrations = __esm({
|
|
|
81787
81787
|
db.exec("DROP TABLE IF EXISTS model_configs");
|
|
81788
81788
|
}
|
|
81789
81789
|
});
|
|
81790
|
+
this.migrations.push({
|
|
81791
|
+
version: 2,
|
|
81792
|
+
name: "normalize_endpoint_urls",
|
|
81793
|
+
up: (db) => {
|
|
81794
|
+
db.exec(`
|
|
81795
|
+
UPDATE model_configs
|
|
81796
|
+
SET endpoint_url = NULL
|
|
81797
|
+
WHERE endpoint_url = '' OR TRIM(endpoint_url) = ''
|
|
81798
|
+
`);
|
|
81799
|
+
if (process.env["FSS_DEBUG"] === "true") {
|
|
81800
|
+
const result = db.exec(`
|
|
81801
|
+
SELECT COUNT(*) as count
|
|
81802
|
+
FROM model_configs
|
|
81803
|
+
WHERE endpoint_url IS NULL
|
|
81804
|
+
`);
|
|
81805
|
+
const count = result[0]?.values?.[0]?.[0] || 0;
|
|
81806
|
+
console.log(`Migration v2: Normalized endpoints (${count} records with NULL endpoint)`);
|
|
81807
|
+
}
|
|
81808
|
+
},
|
|
81809
|
+
down: (db) => {
|
|
81810
|
+
console.warn("Migration v2 rollback not implemented - endpoint normalization is one-way");
|
|
81811
|
+
}
|
|
81812
|
+
});
|
|
81790
81813
|
}
|
|
81791
81814
|
/**
|
|
81792
81815
|
* Get current schema version from database
|
|
@@ -83117,57 +83140,167 @@ var init_model_database = __esm({
|
|
|
83117
83140
|
[id]
|
|
83118
83141
|
);
|
|
83119
83142
|
}
|
|
83143
|
+
/**
|
|
83144
|
+
* Normalize endpoint URL to canonical form:
|
|
83145
|
+
* - undefined → NULL
|
|
83146
|
+
* - '' (empty string) → NULL
|
|
83147
|
+
* - whitespace-only → NULL
|
|
83148
|
+
* - Non-empty string → trimmed string
|
|
83149
|
+
*
|
|
83150
|
+
* This ensures UNIQUE(auth_type, model_name, endpoint_url) works correctly
|
|
83151
|
+
*/
|
|
83152
|
+
normalizeEndpointUrl(endpointUrl) {
|
|
83153
|
+
if (!endpointUrl || endpointUrl.trim() === "") {
|
|
83154
|
+
return null;
|
|
83155
|
+
}
|
|
83156
|
+
return endpointUrl.trim();
|
|
83157
|
+
}
|
|
83158
|
+
/**
|
|
83159
|
+
* Find model by UNIQUE constraint (auth_type, model_name, endpoint_url)
|
|
83160
|
+
* With canonical NULL normalization, we use simple exact match
|
|
83161
|
+
*/
|
|
83162
|
+
async findByUniqueKey(authType, modelName, endpointUrl) {
|
|
83163
|
+
if (endpointUrl === null) {
|
|
83164
|
+
return await safeQueryFirstWithLocking(
|
|
83165
|
+
this.db,
|
|
83166
|
+
`SELECT id FROM model_configs
|
|
83167
|
+
WHERE auth_type = ?
|
|
83168
|
+
AND model_name = ?
|
|
83169
|
+
AND endpoint_url IS NULL
|
|
83170
|
+
LIMIT 1`,
|
|
83171
|
+
[authType, modelName]
|
|
83172
|
+
);
|
|
83173
|
+
} else {
|
|
83174
|
+
return await safeQueryFirstWithLocking(
|
|
83175
|
+
this.db,
|
|
83176
|
+
`SELECT id FROM model_configs
|
|
83177
|
+
WHERE auth_type = ?
|
|
83178
|
+
AND model_name = ?
|
|
83179
|
+
AND endpoint_url = ?
|
|
83180
|
+
LIMIT 1`,
|
|
83181
|
+
[authType, modelName, endpointUrl]
|
|
83182
|
+
);
|
|
83183
|
+
}
|
|
83184
|
+
}
|
|
83185
|
+
/**
|
|
83186
|
+
* Update existing model record with canonical normalization
|
|
83187
|
+
*/
|
|
83188
|
+
async updateModelRecord(recordId, config, normalizedModelName, normalizedEndpointUrl, encryptedApiKey) {
|
|
83189
|
+
const updateParams = [
|
|
83190
|
+
config.authType || "",
|
|
83191
|
+
normalizedModelName,
|
|
83192
|
+
normalizedEndpointUrl,
|
|
83193
|
+
// NULL or actual URL (never '')
|
|
83194
|
+
encryptedApiKey,
|
|
83195
|
+
config.displayName || null,
|
|
83196
|
+
config.isFavorite === true ? 1 : 0,
|
|
83197
|
+
config.isActive === true ? 1 : 0,
|
|
83198
|
+
recordId
|
|
83199
|
+
];
|
|
83200
|
+
await safeExecWithLocking(this.db, `
|
|
83201
|
+
UPDATE model_configs SET
|
|
83202
|
+
auth_type = ?,
|
|
83203
|
+
model_name = ?,
|
|
83204
|
+
endpoint_url = ?, -- Can be NULL
|
|
83205
|
+
api_key = ?,
|
|
83206
|
+
display_name = ?,
|
|
83207
|
+
is_favorite = ?,
|
|
83208
|
+
is_active = ?,
|
|
83209
|
+
last_used = CURRENT_TIMESTAMP
|
|
83210
|
+
WHERE id = ?
|
|
83211
|
+
`, updateParams);
|
|
83212
|
+
return recordId;
|
|
83213
|
+
}
|
|
83214
|
+
/**
|
|
83215
|
+
* Insert new model record with canonical normalization
|
|
83216
|
+
*/
|
|
83217
|
+
async insertModelRecord(config, normalizedModelName, normalizedEndpointUrl, encryptedApiKey) {
|
|
83218
|
+
const insertParams = [
|
|
83219
|
+
config.authType || "",
|
|
83220
|
+
normalizedModelName,
|
|
83221
|
+
normalizedEndpointUrl,
|
|
83222
|
+
// NULL or actual URL (never '')
|
|
83223
|
+
encryptedApiKey,
|
|
83224
|
+
config.displayName || null,
|
|
83225
|
+
config.isFavorite === true ? 1 : 0,
|
|
83226
|
+
config.isActive === true ? 1 : 0,
|
|
83227
|
+
config.source || "db"
|
|
83228
|
+
];
|
|
83229
|
+
await safeExecWithLocking(this.db, `
|
|
83230
|
+
INSERT INTO model_configs
|
|
83231
|
+
(auth_type, model_name, endpoint_url, api_key, display_name, is_favorite, is_active, last_used, source)
|
|
83232
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)
|
|
83233
|
+
`, insertParams);
|
|
83234
|
+
return getLastInsertId(this.db);
|
|
83235
|
+
}
|
|
83120
83236
|
/**
|
|
83121
83237
|
* Upsert model configuration - UPDATE existing or INSERT new
|
|
83238
|
+
*
|
|
83239
|
+
* Uses cascading lookup strategy:
|
|
83240
|
+
* 1. Level 1: Lookup by ID (explicit update)
|
|
83241
|
+
* 2. Level 2: Lookup by UNIQUE key (auth_type, model_name, endpoint_url)
|
|
83242
|
+
* 3. Level 3: Fallback to auth_type only (backward compatibility)
|
|
83122
83243
|
*/
|
|
83123
83244
|
async upsertModelConfig(config) {
|
|
83124
83245
|
if (!this.db) {
|
|
83125
83246
|
throw new Error("Database not initialized");
|
|
83126
83247
|
}
|
|
83127
83248
|
const encryptedApiKey = config.apiKey ? FSSLinkDatabase.encryptApiKey(config.apiKey) : null;
|
|
83128
|
-
const normalizedEndpointUrl = config.endpointUrl
|
|
83129
|
-
const
|
|
83130
|
-
|
|
83131
|
-
|
|
83132
|
-
|
|
83249
|
+
const normalizedEndpointUrl = this.normalizeEndpointUrl(config.endpointUrl);
|
|
83250
|
+
const normalizedModelName = config.modelName?.trim() || "";
|
|
83251
|
+
let existingRecord = null;
|
|
83252
|
+
if (config.id) {
|
|
83253
|
+
existingRecord = await safeQueryFirstWithLocking(
|
|
83254
|
+
this.db,
|
|
83255
|
+
"SELECT id FROM model_configs WHERE id = ?",
|
|
83256
|
+
[config.id]
|
|
83257
|
+
);
|
|
83258
|
+
if (existingRecord) {
|
|
83259
|
+
return await this.updateModelRecord(
|
|
83260
|
+
existingRecord.id,
|
|
83261
|
+
config,
|
|
83262
|
+
normalizedModelName,
|
|
83263
|
+
normalizedEndpointUrl,
|
|
83264
|
+
encryptedApiKey
|
|
83265
|
+
);
|
|
83266
|
+
}
|
|
83267
|
+
}
|
|
83268
|
+
existingRecord = await this.findByUniqueKey(
|
|
83269
|
+
config.authType,
|
|
83270
|
+
normalizedModelName,
|
|
83271
|
+
normalizedEndpointUrl
|
|
83133
83272
|
);
|
|
83134
|
-
if (existingRecord
|
|
83135
|
-
|
|
83136
|
-
|
|
83137
|
-
config
|
|
83138
|
-
|
|
83139
|
-
normalizedEndpointUrl,
|
|
83140
|
-
encryptedApiKey || null,
|
|
83141
|
-
config.displayName || null,
|
|
83142
|
-
config.isFavorite === true ? 1 : 0,
|
|
83143
|
-
config.isActive === true ? 1 : 0,
|
|
83144
|
-
recordId
|
|
83145
|
-
];
|
|
83146
|
-
await safeExecWithLocking(this.db, `
|
|
83147
|
-
UPDATE model_configs SET
|
|
83148
|
-
auth_type = ?, model_name = ?, endpoint_url = ?, api_key = ?,
|
|
83149
|
-
display_name = ?, is_favorite = ?, is_active = ?, last_used = CURRENT_TIMESTAMP
|
|
83150
|
-
WHERE id = ?
|
|
83151
|
-
`, updateParams);
|
|
83152
|
-
return recordId || 0;
|
|
83153
|
-
} else {
|
|
83154
|
-
const insertParams = [
|
|
83155
|
-
config.authType || "",
|
|
83156
|
-
config.modelName || "",
|
|
83273
|
+
if (existingRecord) {
|
|
83274
|
+
return await this.updateModelRecord(
|
|
83275
|
+
existingRecord.id,
|
|
83276
|
+
config,
|
|
83277
|
+
normalizedModelName,
|
|
83157
83278
|
normalizedEndpointUrl,
|
|
83158
|
-
encryptedApiKey
|
|
83159
|
-
|
|
83160
|
-
config.isFavorite === true ? 1 : 0,
|
|
83161
|
-
config.isActive === true ? 1 : 0,
|
|
83162
|
-
config.source || "db"
|
|
83163
|
-
];
|
|
83164
|
-
await safeExecWithLocking(this.db, `
|
|
83165
|
-
INSERT INTO model_configs
|
|
83166
|
-
(auth_type, model_name, endpoint_url, api_key, display_name, is_favorite, is_active, last_used, source)
|
|
83167
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)
|
|
83168
|
-
`, insertParams);
|
|
83169
|
-
return getLastInsertId(this.db);
|
|
83279
|
+
encryptedApiKey
|
|
83280
|
+
);
|
|
83170
83281
|
}
|
|
83282
|
+
if (!normalizedModelName || normalizedModelName === "") {
|
|
83283
|
+
existingRecord = await safeQueryFirstWithLocking(
|
|
83284
|
+
this.db,
|
|
83285
|
+
"SELECT id FROM model_configs WHERE auth_type = ? LIMIT 1",
|
|
83286
|
+
[config.authType]
|
|
83287
|
+
);
|
|
83288
|
+
if (existingRecord) {
|
|
83289
|
+
return await this.updateModelRecord(
|
|
83290
|
+
existingRecord.id,
|
|
83291
|
+
config,
|
|
83292
|
+
normalizedModelName,
|
|
83293
|
+
normalizedEndpointUrl,
|
|
83294
|
+
encryptedApiKey
|
|
83295
|
+
);
|
|
83296
|
+
}
|
|
83297
|
+
}
|
|
83298
|
+
return await this.insertModelRecord(
|
|
83299
|
+
config,
|
|
83300
|
+
normalizedModelName,
|
|
83301
|
+
normalizedEndpointUrl,
|
|
83302
|
+
encryptedApiKey
|
|
83303
|
+
);
|
|
83171
83304
|
}
|
|
83172
83305
|
/**
|
|
83173
83306
|
* Get all model configurations
|
|
@@ -94147,7 +94280,7 @@ async function getPackageJson() {
|
|
|
94147
94280
|
// packages/cli/src/utils/version.ts
|
|
94148
94281
|
async function getCliVersion() {
|
|
94149
94282
|
const pkgJson = await getPackageJson();
|
|
94150
|
-
return "1.1.
|
|
94283
|
+
return "1.1.6";
|
|
94151
94284
|
}
|
|
94152
94285
|
|
|
94153
94286
|
// packages/cli/src/ui/commands/aboutCommand.ts
|
|
@@ -94199,7 +94332,7 @@ import open4 from "open";
|
|
|
94199
94332
|
import process11 from "node:process";
|
|
94200
94333
|
|
|
94201
94334
|
// packages/cli/src/generated/git-commit.ts
|
|
94202
|
-
var GIT_COMMIT_INFO = "
|
|
94335
|
+
var GIT_COMMIT_INFO = "2fbcfa4c";
|
|
94203
94336
|
|
|
94204
94337
|
// packages/cli/src/ui/commands/bugCommand.ts
|
|
94205
94338
|
init_dist2();
|