fss-link 1.2.20 → 1.2.22

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.
Files changed (2) hide show
  1. package/bundle/fss-link.js +167 -13
  2. package/package.json +1 -1
@@ -19872,7 +19872,11 @@ var init_openaiContentGenerator = __esm({
19872
19872
  if (this.contentGeneratorConfig.authType === "ollama") {
19873
19873
  return true;
19874
19874
  }
19875
- return false;
19875
+ const baseUrl = this.contentGeneratorConfig.baseUrl;
19876
+ if (!baseUrl)
19877
+ return false;
19878
+ return baseUrl.includes("localhost:11434") || baseUrl.includes("127.0.0.1:11434") || baseUrl.includes(":11434/v1") || baseUrl.includes(":11435/v1") || // Support proxy port
19879
+ baseUrl.includes("/ollama");
19876
19880
  }
19877
19881
  /**
19878
19882
  * Determine if this is a custom OpenAI-compatible endpoint (proxy, local server, etc.)
@@ -22226,6 +22230,28 @@ var init_qwenContentGenerator = __esm({
22226
22230
 
22227
22231
  // packages/core/dist/src/core/contentGenerator.js
22228
22232
  import { GoogleGenAI } from "@google/genai";
22233
+ function normalizeOpenAICompatibleBaseUrl(url2, provider) {
22234
+ if (!url2) {
22235
+ throw new Error(`${provider} base URL is required`);
22236
+ }
22237
+ let normalized2 = url2.replace(/\/+$/, "");
22238
+ if (normalized2.endsWith("/v1/v1")) {
22239
+ normalized2 = normalized2.slice(0, -3);
22240
+ if (DEBUG_CONTENT)
22241
+ console.log(`\u26A0\uFE0F ${provider}: Removed duplicate /v1 from URL: ${url2} \u2192 ${normalized2}`);
22242
+ }
22243
+ if (!normalized2.endsWith("/v1")) {
22244
+ normalized2 = `${normalized2}/v1`;
22245
+ if (DEBUG_CONTENT)
22246
+ console.log(`\u2705 ${provider}: Added /v1 suffix to URL: ${url2} \u2192 ${normalized2}`);
22247
+ }
22248
+ try {
22249
+ new URL(normalized2);
22250
+ } catch (error) {
22251
+ throw new Error(`${provider}: Invalid base URL after normalization: ${normalized2}`);
22252
+ }
22253
+ return normalized2;
22254
+ }
22229
22255
  async function createContentGeneratorConfig(config, authType) {
22230
22256
  const geminiApiKey = process.env["GEMINI_API_KEY"] || void 0;
22231
22257
  const googleApiKey = process.env["GOOGLE_API_KEY"] || void 0;
@@ -22281,7 +22307,8 @@ async function createContentGeneratorConfig(config, authType) {
22281
22307
  if (authType === AuthType.OLLAMA) {
22282
22308
  if (ollamaApiKey) {
22283
22309
  contentGeneratorConfig.apiKey = ollamaApiKey;
22284
- contentGeneratorConfig.baseUrl = ollamaBaseUrl || "http://localhost:11434/v1";
22310
+ const rawBaseUrl = ollamaBaseUrl || "http://localhost:11434/v1";
22311
+ contentGeneratorConfig.baseUrl = normalizeOpenAICompatibleBaseUrl(rawBaseUrl, "Ollama");
22285
22312
  contentGeneratorConfig.model = ollamaModel || "qwen3-coder-4b";
22286
22313
  return contentGeneratorConfig;
22287
22314
  }
@@ -22300,7 +22327,7 @@ async function createContentGeneratorConfig(config, authType) {
22300
22327
  if (DEBUG_CONTENT)
22301
22328
  console.log("\u{1F527} Using Ollama defaults: http://localhost:11434/v1");
22302
22329
  contentGeneratorConfig.apiKey = "1";
22303
- contentGeneratorConfig.baseUrl = "http://localhost:11434/v1";
22330
+ contentGeneratorConfig.baseUrl = normalizeOpenAICompatibleBaseUrl("http://localhost:11434/v1", "Ollama");
22304
22331
  const configModel = config.getModel();
22305
22332
  const finalModel = ollamaModel || configModel || "qwen3-coder-4b";
22306
22333
  contentGeneratorConfig.model = finalModel;
@@ -22311,7 +22338,8 @@ async function createContentGeneratorConfig(config, authType) {
22311
22338
  if (authType === AuthType.LM_STUDIO) {
22312
22339
  if (lmStudioApiKey) {
22313
22340
  contentGeneratorConfig.apiKey = lmStudioApiKey;
22314
- contentGeneratorConfig.baseUrl = lmStudioBaseUrl || "http://localhost:1234/v1";
22341
+ const rawBaseUrl = lmStudioBaseUrl || "http://localhost:1234/v1";
22342
+ contentGeneratorConfig.baseUrl = normalizeOpenAICompatibleBaseUrl(rawBaseUrl, "LM Studio");
22315
22343
  contentGeneratorConfig.model = lmStudioModel || "qwen3-coder-4b";
22316
22344
  return contentGeneratorConfig;
22317
22345
  }
@@ -22330,7 +22358,7 @@ async function createContentGeneratorConfig(config, authType) {
22330
22358
  if (DEBUG_CONTENT)
22331
22359
  console.log("\u{1F527} Using LM Studio defaults: http://localhost:1234/v1");
22332
22360
  contentGeneratorConfig.apiKey = "1";
22333
- contentGeneratorConfig.baseUrl = "http://localhost:1234/v1";
22361
+ contentGeneratorConfig.baseUrl = normalizeOpenAICompatibleBaseUrl("http://localhost:1234/v1", "LM Studio");
22334
22362
  const configModel = config.getModel();
22335
22363
  const finalModel = lmStudioModel || configModel || "qwen3-coder-4b";
22336
22364
  contentGeneratorConfig.model = finalModel;
@@ -22343,7 +22371,7 @@ async function createContentGeneratorConfig(config, authType) {
22343
22371
  async function createContentGenerator(config, gcConfig, sessionId2) {
22344
22372
  if (DEBUG_CONTENT)
22345
22373
  console.log(`\u{1F41B} DEBUG createContentGenerator: authType=${config.authType}, apiKey=${config.apiKey}, baseUrl=${config.baseUrl}`);
22346
- const version = "1.2.20";
22374
+ const version = "1.2.22";
22347
22375
  const userAgent = `FSS-Link/${version} (${process.platform}; ${process.arch})`;
22348
22376
  const baseHeaders = {
22349
22377
  "User-Agent": userAgent
@@ -60795,7 +60823,59 @@ var init_project_structure = __esm({
60795
60823
  type: "array",
60796
60824
  description: 'Patterns to exclude (e.g., ["node_modules", "*.log"])',
60797
60825
  items: { type: "string" },
60798
- default: ["node_modules", ".git", "__pycache__", "dist", "build"]
60826
+ default: [
60827
+ // Version control
60828
+ ".git",
60829
+ ".svn",
60830
+ ".hg",
60831
+ // JavaScript/Node.js
60832
+ "node_modules",
60833
+ ".npm",
60834
+ ".yarn",
60835
+ "bower_components",
60836
+ // Python virtualenvs (directories only)
60837
+ "venv",
60838
+ ".venv",
60839
+ "virtualenv",
60840
+ // Python cache and artifacts
60841
+ "__pycache__",
60842
+ "*.pyc",
60843
+ ".pytest_cache",
60844
+ ".tox",
60845
+ ".mypy_cache",
60846
+ ".ruff_cache",
60847
+ "site-packages",
60848
+ "*.egg-info",
60849
+ ".eggs",
60850
+ // Build outputs
60851
+ "dist",
60852
+ "build",
60853
+ "out",
60854
+ // Coverage/Testing
60855
+ "coverage",
60856
+ ".nyc_output",
60857
+ ".coverage",
60858
+ "htmlcov",
60859
+ // Ruby
60860
+ ".bundle",
60861
+ "vendor",
60862
+ // Java/JVM
60863
+ ".gradle",
60864
+ ".m2",
60865
+ "target",
60866
+ // IDE/Editor
60867
+ ".idea",
60868
+ ".vscode",
60869
+ ".vs",
60870
+ "*.swp",
60871
+ "*.swo",
60872
+ // OS
60873
+ ".DS_Store",
60874
+ "Thumbs.db",
60875
+ // Temporary
60876
+ ".tmp",
60877
+ ".cache"
60878
+ ]
60799
60879
  },
60800
60880
  size_analysis: {
60801
60881
  type: "boolean",
@@ -60852,7 +60932,48 @@ Features:
60852
60932
  return `Analyze project structure (${analysis_type}) for ${target}`;
60853
60933
  }
60854
60934
  async execute(_signal) {
60855
- const { target = ".", analysis_type = "overview", max_depth = 5, show_hidden = false, file_types, exclude_patterns = ["node_modules", ".git", "__pycache__", "dist", "build"], size_analysis = true, git_awareness = true, query } = this.params;
60935
+ const { target = ".", analysis_type = "overview", max_depth = 5, show_hidden = false, file_types, exclude_patterns = [
60936
+ ".git",
60937
+ ".svn",
60938
+ ".hg",
60939
+ "node_modules",
60940
+ ".npm",
60941
+ ".yarn",
60942
+ "bower_components",
60943
+ "venv",
60944
+ ".venv",
60945
+ "virtualenv",
60946
+ "__pycache__",
60947
+ "*.pyc",
60948
+ ".pytest_cache",
60949
+ ".tox",
60950
+ ".mypy_cache",
60951
+ ".ruff_cache",
60952
+ "site-packages",
60953
+ "*.egg-info",
60954
+ ".eggs",
60955
+ "dist",
60956
+ "build",
60957
+ "out",
60958
+ "coverage",
60959
+ ".nyc_output",
60960
+ ".coverage",
60961
+ "htmlcov",
60962
+ ".bundle",
60963
+ "vendor",
60964
+ ".gradle",
60965
+ ".m2",
60966
+ "target",
60967
+ ".idea",
60968
+ ".vscode",
60969
+ ".vs",
60970
+ "*.swp",
60971
+ "*.swo",
60972
+ ".DS_Store",
60973
+ "Thumbs.db",
60974
+ ".tmp",
60975
+ ".cache"
60976
+ ], size_analysis = true, git_awareness = true, query } = this.params;
60856
60977
  try {
60857
60978
  const targetPath = path27.resolve(target);
60858
60979
  try {
@@ -61048,7 +61169,7 @@ Features:
61048
61169
  const fullFilePath = path27.join(fullPath, fileName);
61049
61170
  if (!showHidden && fileName.startsWith("."))
61050
61171
  continue;
61051
- if (excludePatterns.some((pattern) => fileName.includes(pattern) || filePath.includes(pattern)))
61172
+ if (excludePatterns.some((pattern) => this.matchesExcludePattern(fileName, filePath, entry.isDirectory(), pattern)))
61052
61173
  continue;
61053
61174
  try {
61054
61175
  const stats = await fs23.stat(fullFilePath);
@@ -61076,6 +61197,20 @@ Features:
61076
61197
  }
61077
61198
  return files;
61078
61199
  }
61200
+ /**
61201
+ * Check if a file/directory matches an exclude pattern
61202
+ * Supports glob patterns (*.ext) and exact directory/file name matching
61203
+ */
61204
+ matchesExcludePattern(fileName, filePath, isDirectory, pattern) {
61205
+ if (pattern.includes("*")) {
61206
+ const regex2 = new RegExp("^" + pattern.replace(/\./g, "\\.").replace(/\*/g, ".*") + "$");
61207
+ return regex2.test(fileName);
61208
+ }
61209
+ if (isDirectory) {
61210
+ return fileName === pattern || filePath.split("/").includes(pattern);
61211
+ }
61212
+ return fileName === pattern;
61213
+ }
61079
61214
  getFileIcon(fileName, isDirectory) {
61080
61215
  if (isDirectory) {
61081
61216
  const dirIcons = {
@@ -68981,7 +69116,7 @@ var init_turn = __esm({
68981
69116
  /*curated*/
68982
69117
  true
68983
69118
  ), req];
68984
- await reportError(error, "Error when talking to LLM API", contextForReport, "Turn.run-sendMessageStream");
69119
+ await reportError(error, "Error when talking to Gemini API", contextForReport, "Turn.run-sendMessageStream");
68985
69120
  const status = typeof error === "object" && error !== null && "status" in error && typeof error.status === "number" ? error.status : void 0;
68986
69121
  const structuredError = {
68987
69122
  message: getErrorMessage(error),
@@ -84383,6 +84518,25 @@ var init_model_database = __esm({
84383
84518
  encryptedApiKey
84384
84519
  );
84385
84520
  }
84521
+ if (normalizedModelName && normalizedModelName !== "") {
84522
+ existingRecord = await safeQueryFirstWithLocking(
84523
+ this.db,
84524
+ `SELECT id FROM model_configs
84525
+ WHERE auth_type = ?
84526
+ AND model_name = ?
84527
+ LIMIT 1`,
84528
+ [config.authType, normalizedModelName]
84529
+ );
84530
+ if (existingRecord) {
84531
+ return await this.updateModelRecord(
84532
+ existingRecord.id,
84533
+ config,
84534
+ normalizedModelName,
84535
+ normalizedEndpointUrl,
84536
+ encryptedApiKey
84537
+ );
84538
+ }
84539
+ }
84386
84540
  if (!normalizedModelName || normalizedModelName === "") {
84387
84541
  existingRecord = await safeQueryFirstWithLocking(
84388
84542
  this.db,
@@ -95429,7 +95583,7 @@ async function getPackageJson() {
95429
95583
  // packages/cli/src/utils/version.ts
95430
95584
  async function getCliVersion() {
95431
95585
  const pkgJson = await getPackageJson();
95432
- return "1.2.20";
95586
+ return "1.2.22";
95433
95587
  }
95434
95588
 
95435
95589
  // packages/cli/src/ui/commands/aboutCommand.ts
@@ -95481,7 +95635,7 @@ import open4 from "open";
95481
95635
  import process11 from "node:process";
95482
95636
 
95483
95637
  // packages/cli/src/generated/git-commit.ts
95484
- var GIT_COMMIT_INFO = "fccbeb7a";
95638
+ var GIT_COMMIT_INFO = "01c4caed";
95485
95639
 
95486
95640
  // packages/cli/src/ui/commands/bugCommand.ts
95487
95641
  init_dist2();
@@ -118338,7 +118492,7 @@ var SETTINGS_SCHEMA = {
118338
118492
  label: "Enable Checkpointing",
118339
118493
  category: "Checkpointing",
118340
118494
  requiresRestart: true,
118341
- default: false,
118495
+ default: true,
118342
118496
  description: "Enable session checkpointing for recovery",
118343
118497
  showInDialog: false
118344
118498
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fss-link",
3
- "version": "1.2.20",
3
+ "version": "1.2.22",
4
4
  "engines": {
5
5
  "node": ">=20.0.0"
6
6
  },