fss-link 1.4.0 โ†’ 1.4.2

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/README.md CHANGED
@@ -12,17 +12,17 @@
12
12
 
13
13
  </div>
14
14
 
15
- **FSS Link** is a portable, scriptable agent that links tools, models, and knowledge into multi-instance workflows. Install anywhere with Node.js, launch 1-8 agents at once, feed them templated tasks, and watch them go.
15
+ **FSS Link** is a portable, scriptable agent that links tools, models, and knowledge into single-instance workflows. Install anywhere with Node.js, launch one agent at a time, feed it tasks, and watch it go.
16
16
 
17
17
  - **Lightweight distribution** (~15 MB bundle, requires Node.js 20+)
18
- - **Spawn many agents** with structured prompts
19
- - **Portable Mini-RAG** indices that travel with your projects
18
+ - **Single-agent workflows** with structured prompts
19
+ - **Portable Mini-RAG** indices that travel with your projects (planned feature)
20
20
  - **Local-first** with LM Studio/Ollama priority
21
21
  - **Professional tools** built in TypeScript for seamless integration
22
22
 
23
23
  ## ๐ŸŽฏ Why "Link"?
24
24
 
25
- Link connects thingsโ€”tools, models, tasks, and knowledge. **FSS Link** is a lightweight distribution that runs wherever Node.js is installed. Start an agent, or spawn eight in parallel with templated prompts. Each project carries its own Mini-RAG index, so knowledge travels with the work.
25
+ Link connects thingsโ€”tools, models, tasks, and knowledge. **FSS Link** is a lightweight distribution that runs wherever Node.js is installed. Start an agent, or spawn multiple agents with templated prompts (planned feature). Each project carries its own Mini-RAG index, so knowledge travels with the work.
26
26
 
27
27
  ## ๐Ÿš€ Quick Start
28
28
 
@@ -33,10 +33,7 @@ fss-link
33
33
  # Single-shot task
34
34
  fss-link run "Audit the repo for security keys and open PR fixes."
35
35
 
36
- # Launch 6 parallel agents with templated plan
37
- fss-link spawn --count 6 --template ./templates/regression.yml
38
-
39
- # Portable RAG - indexes travel with projects
36
+ # Portable RAG - indexes travel with projects (planned feature)
40
37
  cd project && fss-link rag index . && fss-link rag query "error handling"
41
38
  ```
42
39
 
@@ -98,10 +95,17 @@ FSS Link now features an intelligent **Welcome Back dialog** that appears when y
98
95
 
99
96
  - **๐Ÿ” Project Status Dashboard** - Git status, session history, momentum analysis
100
97
  - **๐Ÿ“Š Smart Context Generation** - Priority-based information filtering (7 levels)
101
- - **โšก Multi-Agent Awareness** - Universal session tracking across all agents
98
+ - **โšก Multi-Agent Awareness** - Universal session tracking across all agents (planned feature)
102
99
  - **๐ŸŽฏ Seamless Resumption** - Intelligent context population for continuing work
103
100
  - **๐Ÿš€ Production Quality** - Comprehensive error handling, performance optimization
104
101
 
102
+ ## ๐Ÿ“ External Directory Access
103
+
104
+ For accessing external directories like `/tmp`, user directories, or custom paths, see:
105
+ [External Directory Access Guide](./fss-docs/EXTERNAL-DIRECTORY-ACCESS.md)
106
+
107
+ This documentation explains how to configure FSS Link to securely access external directories through its folder trust system.
108
+
105
109
  ### ๐Ÿ”„ **Node.js Version Requirements**
106
110
 
107
111
  FSS Link requires **Node.js 20+**. If you have an older version, upgrade first:
@@ -153,7 +157,7 @@ Built-in semantic search that travels with your projects. No Python dependencies
153
157
  - **Deep Semantic Search**: Find code by describing what it does, not just what it's called
154
158
  - **Cross-Reference Analysis**: Discover how different parts of the system interact
155
159
  - **Context-Aware Suggestions**: Get recommendations based on the entire project context
156
- - **Portable Indices**: Knowledge travels with your projects
160
+ - **Portable Indices**: Knowledge travels with your projects (planned feature)
157
161
 
158
162
  ### ๐Ÿ“‹ **Enhanced Task Management**
159
163
  Built on FSS Link's native TodoWrite tool with professional enhancements for complex development workflows.
@@ -161,7 +165,7 @@ Built on FSS Link's native TodoWrite tool with professional enhancements for com
161
165
  - **Persistent Task Lists**: Never lose track of what needs to be done
162
166
  - **Visual Progress Indicators**: Instantly see what's complete, in-progress, or pending
163
167
  - **Intelligent Task Breakdown**: Automatically decompose complex features into actionable steps
164
- - **Multi-Agent Coordination**: Tasks shared across multiple agent instances
168
+ - **Multi-Agent Coordination**: Tasks shared across multiple agent instances (planned feature)
165
169
 
166
170
  ### ๐Ÿ” **Professional Web Research**
167
171
  TypeScript-native web research tools eliminate context switching between development and external resources.
@@ -210,7 +214,7 @@ fss-link
210
214
  # Launch with specific model
211
215
  fss-link --model qwen/qwen3-4b-2507
212
216
 
213
- # Launch with RAG index
217
+ # Launch with RAG index (planned feature)
214
218
  fss-link --rag ./project-index
215
219
  ```
216
220
 
@@ -222,34 +226,34 @@ fss-link run "Analyse this codebase structure"
222
226
  # With specific model
223
227
  fss-link run "Review security patterns" --model qwen/qwen3-30b-a3b-2507
224
228
 
225
- # With RAG context
229
+ # With RAG context (planned feature)
226
230
  fss-link run "Find authentication bugs" --rag .
227
231
  ```
228
232
 
229
- ### **Multi-Agent Workflows**
233
+ ### **Multi-Agent Workflows** (Planned Feature)
230
234
  ```bash
231
- # Launch multiple agents with template
235
+ # Launch multiple agents with template (planned feature)
232
236
  fss-link spawn --count 8 --template ./templates/build-test.yml
233
237
 
234
- # Parallel code review
238
+ # Parallel code review (planned feature)
235
239
  fss-link spawn --count 4 --template ./templates/code-review.yml --files src/
236
240
 
237
- # Load-balanced task processing
241
+ # Load-balanced task processing (planned feature)
238
242
  fss-link spawn --count 6 --template ./templates/regression-test.yml
239
243
  ```
240
244
 
241
- ### **RAG Operations**
245
+ ### **RAG Operations** (Planned Feature)
242
246
  ```bash
243
- # Index current directory
247
+ # Index current directory (planned feature)
244
248
  fss-link rag index .
245
249
 
246
- # Index with specific extensions
250
+ # Index with specific extensions (planned feature)
247
251
  fss-link rag index . --extensions py,js,md
248
252
 
249
- # Query with filters
253
+ # Query with filters (planned feature)
250
254
  fss-link rag query "authentication logic" --topk 5
251
255
 
252
- # Cross-reference search
256
+ # Cross-reference search (planned feature)
253
257
  fss-link rag query "error handling patterns" --files py,js --recent
254
258
  ```
255
259
 
@@ -338,8 +342,8 @@ FSS Link builds on [QwenLM/fss-link](https://github.com/QwenLM/fss-link), which
338
342
 
339
343
  <div align="center">
340
344
 
341
- **FSS Link** - *Portable, scriptable, multi-instance AI agent*
345
+ **FSS Link** - *Portable, scriptable, single-instance AI agent*
342
346
 
343
347
  [Documentation](./FSS-LINK-IMPLEMENTATION-GUIDE.md) โ€ข [Installation Guide](./INSTALL.md) โ€ข [Examples](./examples/)
344
348
 
345
- </div>
349
+ </div>
@@ -22379,7 +22379,7 @@ async function createContentGeneratorConfig(config, authType) {
22379
22379
  async function createContentGenerator(config, gcConfig, sessionId2) {
22380
22380
  if (DEBUG_CONTENT)
22381
22381
  console.log(`\u{1F41B} DEBUG createContentGenerator: authType=${config.authType}, apiKey=${config.apiKey}, baseUrl=${config.baseUrl}`);
22382
- const version = "1.4.0";
22382
+ const version = "1.4.2";
22383
22383
  const userAgent = `FSS-Link/${version} (${process.platform}; ${process.arch})`;
22384
22384
  const baseHeaders = {
22385
22385
  "User-Agent": userAgent
@@ -90220,7 +90220,7 @@ import React31 from "react";
90220
90220
  import { render as render2 } from "ink";
90221
90221
 
90222
90222
  // packages/cli/src/ui/App.tsx
90223
- import { useCallback as useCallback29, useEffect as useEffect43, useMemo as useMemo9, useState as useState48, useRef as useRef12 } from "react";
90223
+ import { useCallback as useCallback29, useEffect as useEffect44, useMemo as useMemo9, useState as useState48, useRef as useRef12 } from "react";
90224
90224
  import {
90225
90225
  Box as Box59,
90226
90226
  measureElement,
@@ -96074,7 +96074,7 @@ async function getPackageJson() {
96074
96074
  // packages/cli/src/utils/version.ts
96075
96075
  async function getCliVersion() {
96076
96076
  const pkgJson = await getPackageJson();
96077
- return "1.4.0";
96077
+ return "1.4.2";
96078
96078
  }
96079
96079
 
96080
96080
  // packages/cli/src/ui/commands/aboutCommand.ts
@@ -96126,7 +96126,7 @@ import open4 from "open";
96126
96126
  import process11 from "node:process";
96127
96127
 
96128
96128
  // packages/cli/src/generated/git-commit.ts
96129
- var GIT_COMMIT_INFO = "92ea8a8d";
96129
+ var GIT_COMMIT_INFO = "607be21d";
96130
96130
 
96131
96131
  // packages/cli/src/ui/commands/bugCommand.ts
96132
96132
  init_dist2();
@@ -120419,8 +120419,61 @@ function LMStudioModelPrompt({
120419
120419
 
120420
120420
  // packages/cli/src/ui/components/AddCustomEndpointDialog.tsx
120421
120421
  init_dist2();
120422
- import { useState as useState33 } from "react";
120422
+ import { useState as useState33, useEffect as useEffect32 } from "react";
120423
120423
  import { Box as Box19, Text as Text26, useInput as useInput4 } from "ink";
120424
+ import TextInput from "ink-text-input";
120425
+
120426
+ // packages/cli/src/utils/modelFetcher.ts
120427
+ async function fetchModelsFromCustomEndpoint(baseUrl, providerType, apiKey) {
120428
+ const normalizedBase = baseUrl.replace(/\/+$/, "");
120429
+ const url2 = `${normalizedBase}/models`;
120430
+ const headers = {
120431
+ "Accept": "application/json"
120432
+ };
120433
+ if (apiKey && apiKey.trim() !== "") {
120434
+ headers["Authorization"] = `Bearer ${apiKey}`;
120435
+ }
120436
+ try {
120437
+ const controller = new AbortController();
120438
+ const timeoutId = setTimeout(() => controller.abort(), 1e4);
120439
+ const response = await fetch(url2, {
120440
+ headers,
120441
+ signal: controller.signal
120442
+ });
120443
+ clearTimeout(timeoutId);
120444
+ if (!response.ok) {
120445
+ if (response.status === 401 || response.status === 403) {
120446
+ throw new Error("Authentication failed - check API key");
120447
+ }
120448
+ if (response.status === 404) {
120449
+ throw new Error("Endpoint not found - verify URL includes /v1 suffix");
120450
+ }
120451
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
120452
+ }
120453
+ const json3 = await response.json();
120454
+ if (!json3.data || !Array.isArray(json3.data)) {
120455
+ throw new Error("Invalid response format - expected OpenAI-compatible /models endpoint");
120456
+ }
120457
+ if (json3.data.length === 0) {
120458
+ throw new Error("No models available on this endpoint");
120459
+ }
120460
+ return json3.data.map((m) => ({
120461
+ id: m.id,
120462
+ ownedBy: m.owned_by || "unknown",
120463
+ object: m.object
120464
+ }));
120465
+ } catch (error) {
120466
+ if (error instanceof Error) {
120467
+ if (error.name === "AbortError") {
120468
+ throw new Error("Connection timeout - endpoint took too long to respond");
120469
+ }
120470
+ throw error;
120471
+ }
120472
+ throw new Error(`Connection failed: ${String(error)}`);
120473
+ }
120474
+ }
120475
+
120476
+ // packages/cli/src/ui/components/AddCustomEndpointDialog.tsx
120424
120477
  import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
120425
120478
  function AddCustomEndpointDialog({
120426
120479
  onSubmit,
@@ -120432,12 +120485,25 @@ function AddCustomEndpointDialog({
120432
120485
  const [apiKey, setApiKey] = useState33("");
120433
120486
  const [providerType, setProviderType] = useState33(null);
120434
120487
  const [selectedProviderIndex, setSelectedProviderIndex] = useState33(0);
120435
- const [inputBuffer, setInputBuffer] = useState33("");
120488
+ const [availableModels, setAvailableModels] = useState33([]);
120489
+ const [selectedModelIndex, setSelectedModelIndex] = useState33(0);
120490
+ const [fetchError, setFetchError] = useState33(null);
120436
120491
  const providerOptions = [
120437
120492
  { label: "OpenAI-compatible API", value: AuthType.USE_OPENAI },
120438
120493
  { label: "Ollama", value: AuthType.OLLAMA },
120439
120494
  { label: "LM Studio", value: AuthType.LM_STUDIO }
120440
120495
  ];
120496
+ useEffect32(() => {
120497
+ if (step === "model-fetch" && url2 && providerType) {
120498
+ fetchModelsFromCustomEndpoint(url2, providerType, apiKey || void 0).then((models) => {
120499
+ setAvailableModels(models);
120500
+ setFetchError(null);
120501
+ setStep("model-select");
120502
+ }).catch((err) => {
120503
+ setFetchError(err instanceof Error ? err.message : String(err));
120504
+ });
120505
+ }
120506
+ }, [step, url2, providerType, apiKey]);
120441
120507
  useInput4((input, key) => {
120442
120508
  if (key.escape) {
120443
120509
  onCancel();
@@ -120459,47 +120525,67 @@ function AddCustomEndpointDialog({
120459
120525
  }
120460
120526
  return;
120461
120527
  }
120462
- if (key.return) {
120463
- if (step === "name") {
120464
- if (inputBuffer.trim()) {
120465
- setName(inputBuffer.trim());
120466
- setInputBuffer("");
120467
- setStep("url");
120468
- }
120469
- } else if (step === "url") {
120470
- if (inputBuffer.trim()) {
120471
- setUrl(inputBuffer.trim());
120472
- setInputBuffer("");
120473
- setStep("provider");
120474
- }
120475
- } else if (step === "apikey") {
120476
- setApiKey(inputBuffer.trim());
120477
- if (providerType) {
120478
- onSubmit(name2, url2, inputBuffer.trim(), providerType);
120528
+ if (step === "model-select") {
120529
+ if (key.upArrow && selectedModelIndex > 0) {
120530
+ setSelectedModelIndex(selectedModelIndex - 1);
120531
+ return;
120532
+ }
120533
+ if (key.downArrow && selectedModelIndex < availableModels.length - 1) {
120534
+ setSelectedModelIndex(selectedModelIndex + 1);
120535
+ return;
120536
+ }
120537
+ if (key.return) {
120538
+ if (availableModels.length > 0 && providerType) {
120539
+ const selectedModel = availableModels[selectedModelIndex];
120540
+ onSubmit(name2, url2, selectedModel.id, apiKey, providerType);
120479
120541
  }
120542
+ return;
120480
120543
  }
120481
120544
  return;
120482
120545
  }
120483
- if (key.backspace || key.delete) {
120484
- setInputBuffer(inputBuffer.slice(0, -1));
120546
+ if (step === "model-fetch" && fetchError) {
120547
+ if (input === "r" || input === "R") {
120548
+ setFetchError(null);
120549
+ setStep("model-fetch");
120550
+ return;
120551
+ }
120485
120552
  return;
120486
120553
  }
120487
- if (input && !key.ctrl && !key.meta) {
120488
- setInputBuffer(inputBuffer + input);
120489
- }
120490
120554
  });
120555
+ const handleNameSubmit = (value) => {
120556
+ if (value.trim()) {
120557
+ setName(value.trim());
120558
+ setStep("url");
120559
+ }
120560
+ };
120561
+ const handleUrlSubmit = (value) => {
120562
+ if (value.trim()) {
120563
+ setUrl(value.trim());
120564
+ setStep("provider");
120565
+ }
120566
+ };
120567
+ const handleApiKeySubmit = (value) => {
120568
+ setApiKey(value.trim());
120569
+ setStep("model-fetch");
120570
+ };
120491
120571
  const renderStep = () => {
120492
120572
  switch (step) {
120493
120573
  case "name":
120494
120574
  return /* @__PURE__ */ jsxs22(Fragment4, { children: [
120495
120575
  /* @__PURE__ */ jsx24(Text26, { bold: true, color: Colors.AccentBlue, children: "Step 1: Endpoint Name" }),
120496
120576
  /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { children: "Enter a friendly name for this endpoint:" }) }),
120497
- /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: 'Example: "vLLM Production" or "Internal API"' }) }),
120498
- /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { children: [
120577
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: 'Example: "RTX3090 Proxy" or "Inference Server"' }) }),
120578
+ /* @__PURE__ */ jsxs22(Box19, { marginTop: 1, children: [
120499
120579
  /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentPurple, children: "> " }),
120500
- inputBuffer,
120501
- /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentCyan, children: "\u258B" })
120502
- ] }) }),
120580
+ /* @__PURE__ */ jsx24(
120581
+ TextInput,
120582
+ {
120583
+ value: name2,
120584
+ onChange: setName,
120585
+ onSubmit: handleNameSubmit
120586
+ }
120587
+ )
120588
+ ] }),
120503
120589
  /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.Gray, children: "Press Enter to continue, Esc to cancel" }) })
120504
120590
  ] });
120505
120591
  case "url":
@@ -120510,12 +120596,18 @@ function AddCustomEndpointDialog({
120510
120596
  /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: name2 })
120511
120597
  ] }) }),
120512
120598
  /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { children: "Enter the base URL for this endpoint:" }) }),
120513
- /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: 'Example: "http://localhost:11433" or "https://api.company.com"' }) }),
120514
- /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { children: [
120599
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: 'Example: "https://rtx3090.bobai.com.au/v1"' }) }),
120600
+ /* @__PURE__ */ jsxs22(Box19, { marginTop: 1, children: [
120515
120601
  /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentPurple, children: "> " }),
120516
- inputBuffer,
120517
- /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentCyan, children: "\u258B" })
120518
- ] }) }),
120602
+ /* @__PURE__ */ jsx24(
120603
+ TextInput,
120604
+ {
120605
+ value: url2,
120606
+ onChange: setUrl,
120607
+ onSubmit: handleUrlSubmit
120608
+ }
120609
+ )
120610
+ ] }),
120519
120611
  /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.Gray, children: "Press Enter to continue, Esc to cancel" }) })
120520
120612
  ] });
120521
120613
  case "provider":
@@ -120559,12 +120651,101 @@ function AddCustomEndpointDialog({
120559
120651
  ")"
120560
120652
  ] }) }),
120561
120653
  /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { children: "Enter API key if required (leave empty if none):" }) }),
120562
- /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { children: [
120654
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentYellow, children: "\u2139 External endpoints usually require authentication" }) }),
120655
+ /* @__PURE__ */ jsxs22(Box19, { marginTop: 1, children: [
120563
120656
  /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentPurple, children: "> " }),
120564
- "*".repeat(inputBuffer.length),
120565
- /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentCyan, children: "\u258B" })
120657
+ /* @__PURE__ */ jsx24(
120658
+ TextInput,
120659
+ {
120660
+ value: apiKey,
120661
+ onChange: setApiKey,
120662
+ onSubmit: handleApiKeySubmit,
120663
+ mask: "*"
120664
+ }
120665
+ )
120666
+ ] }),
120667
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.Gray, children: "Press Enter to fetch models, Esc to cancel" }) })
120668
+ ] });
120669
+ case "model-fetch":
120670
+ if (fetchError) {
120671
+ return /* @__PURE__ */ jsxs22(Fragment4, { children: [
120672
+ /* @__PURE__ */ jsx24(Text26, { bold: true, color: Colors.AccentRed, children: "Connection Failed" }),
120673
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { children: [
120674
+ "Endpoint: ",
120675
+ /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: name2 }),
120676
+ " (",
120677
+ url2,
120678
+ ")"
120679
+ ] }) }),
120680
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { color: Colors.AccentRed, children: [
120681
+ "Error: ",
120682
+ fetchError
120683
+ ] }) }),
120684
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentYellow, children: "Common issues:" }) }),
120685
+ /* @__PURE__ */ jsxs22(Box19, { marginLeft: 2, flexDirection: "column", children: [
120686
+ /* @__PURE__ */ jsx24(Text26, { children: "\u2022 Incorrect URL (verify /v1 suffix)" }),
120687
+ /* @__PURE__ */ jsx24(Text26, { children: "\u2022 API key required but not provided" }),
120688
+ /* @__PURE__ */ jsx24(Text26, { children: "\u2022 Endpoint not accessible from this machine" }),
120689
+ /* @__PURE__ */ jsx24(Text26, { children: "\u2022 Firewall blocking connection" })
120690
+ ] }),
120691
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.Gray, children: "Press R to retry, Esc to cancel" }) })
120692
+ ] });
120693
+ }
120694
+ return /* @__PURE__ */ jsxs22(Fragment4, { children: [
120695
+ /* @__PURE__ */ jsx24(Text26, { bold: true, color: Colors.AccentBlue, children: "Fetching Models..." }),
120696
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { children: [
120697
+ "Connecting to ",
120698
+ /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: url2 })
120566
120699
  ] }) }),
120567
- /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.Gray, children: "Press Enter to save endpoint, Esc to cancel" }) })
120700
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.Gray, children: "Please wait..." }) })
120701
+ ] });
120702
+ case "model-select":
120703
+ return /* @__PURE__ */ jsxs22(Fragment4, { children: [
120704
+ /* @__PURE__ */ jsx24(Text26, { bold: true, color: Colors.AccentBlue, children: "Step 5: Select Model" }),
120705
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { children: [
120706
+ "Endpoint: ",
120707
+ /* @__PURE__ */ jsx24(Text26, { color: Colors.AccentGreen, children: name2 }),
120708
+ " (",
120709
+ url2,
120710
+ ")"
120711
+ ] }) }),
120712
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text26, { color: Colors.AccentGreen, children: [
120713
+ "\u2713 Found ",
120714
+ availableModels.length,
120715
+ " available models"
120716
+ ] }) }),
120717
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { children: "Choose a model to use:" }) }),
120718
+ /* @__PURE__ */ jsxs22(Box19, { marginTop: 1, flexDirection: "column", children: [
120719
+ availableModels.slice(0, 15).map((model, index) => {
120720
+ const isSelected = index === selectedModelIndex;
120721
+ const prefix = isSelected ? ">" : " ";
120722
+ return /* @__PURE__ */ jsxs22(
120723
+ Text26,
120724
+ {
120725
+ color: isSelected ? Colors.AccentBlue : Colors.Gray,
120726
+ bold: isSelected,
120727
+ children: [
120728
+ prefix,
120729
+ " ",
120730
+ model.id,
120731
+ " ",
120732
+ /* @__PURE__ */ jsxs22(Text26, { color: Colors.Gray, children: [
120733
+ "(",
120734
+ model.ownedBy,
120735
+ ")"
120736
+ ] })
120737
+ ]
120738
+ },
120739
+ model.id
120740
+ );
120741
+ }),
120742
+ availableModels.length > 15 && /* @__PURE__ */ jsxs22(Text26, { color: Colors.Gray, children: [
120743
+ "... and ",
120744
+ availableModels.length - 15,
120745
+ " more models"
120746
+ ] })
120747
+ ] }),
120748
+ /* @__PURE__ */ jsx24(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text26, { color: Colors.Gray, children: "\u2191/\u2193 to navigate, Enter to confirm, Esc to cancel" }) })
120568
120749
  ] });
120569
120750
  }
120570
120751
  };
@@ -120588,7 +120769,7 @@ function AddCustomEndpointDialog({
120588
120769
  init_modelManager();
120589
120770
 
120590
120771
  // packages/cli/src/ui/components/OpenAIEndpointDialog.tsx
120591
- import { useState as useState34, useEffect as useEffect32 } from "react";
120772
+ import { useState as useState34, useEffect as useEffect33 } from "react";
120592
120773
  import { Box as Box20, Text as Text27 } from "ink";
120593
120774
  init_database();
120594
120775
  import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
@@ -120618,7 +120799,7 @@ function OpenAIEndpointDialog({
120618
120799
  }) {
120619
120800
  const [savedEndpoints, setSavedEndpoints] = useState34([]);
120620
120801
  const [isLoading, setIsLoading] = useState34(true);
120621
- useEffect32(() => {
120802
+ useEffect33(() => {
120622
120803
  const loadEndpoints = async () => {
120623
120804
  try {
120624
120805
  const db = await getFSSLinkDatabase();
@@ -120827,7 +121008,7 @@ function AuthDialog({
120827
121008
  setSelectedEndpoint(null);
120828
121009
  setErrorMessage("OpenAI endpoint selection is required.");
120829
121010
  };
120830
- const handleCustomEndpointSubmit = async (name2, url2, apiKey, providerType) => {
121011
+ const handleCustomEndpointSubmit = async (name2, url2, model, apiKey, providerType) => {
120831
121012
  const db = await getFSSLinkDatabase();
120832
121013
  const endpointId = await db.saveCustomEndpoint(
120833
121014
  null,
@@ -120839,14 +121020,31 @@ function AuthDialog({
120839
121020
  await db.forceSave();
120840
121021
  console.log(`\u{1F4BE} [AUTH-DIALOG] Custom endpoint saved: ${name2} (${url2})`);
120841
121022
  setShowAddCustomEndpointDialog(false);
120842
- setSelectedEndpoint({ id: endpointId, name: name2, url: url2, isDefault: false });
120843
- if (providerType === AuthType.USE_OPENAI) {
120844
- setShowOpenAIKeyPrompt(true);
120845
- } else if (providerType === AuthType.OLLAMA) {
120846
- setShowOllamaModelPrompt(true);
120847
- } else if (providerType === AuthType.LM_STUDIO) {
120848
- setShowLMStudioModelPrompt(true);
121023
+ const modelManager = getModelManager();
121024
+ const modelId = await modelManager.configureModel(
121025
+ providerType,
121026
+ model,
121027
+ // โœจ Use selected model from dialog
121028
+ url2,
121029
+ // โœจ Use custom endpoint URL
121030
+ apiKey,
121031
+ `${name2}: ${model}`
121032
+ );
121033
+ if (endpointId && modelId) {
121034
+ await db.linkModelToEndpoint(modelId, endpointId);
121035
+ await db.saveCustomEndpoint(
121036
+ modelId,
121037
+ // Set provider_id to the model ID
121038
+ name2,
121039
+ url2,
121040
+ `Custom ${providerType} endpoint`,
121041
+ false
121042
+ );
121043
+ console.log(`\u{1F4BE} [AUTH-DIALOG] Linked custom_endpoints.provider_id=${modelId} for endpoint ${endpointId}`);
121044
+ await db.forceSave();
121045
+ console.log(`\u{1F4BE} [AUTH-DIALOG] Model ${modelId} linked to endpoint ${endpointId}`);
120849
121046
  }
121047
+ onSelect(providerType, "User" /* User */);
120850
121048
  };
120851
121049
  const handleCustomEndpointCancel = () => {
120852
121050
  setShowAddCustomEndpointDialog(false);
@@ -120947,7 +121145,7 @@ function AuthDialog({
120947
121145
  }
120948
121146
 
120949
121147
  // packages/cli/src/ui/components/ProviderEndpointSelectionDialog.tsx
120950
- import { useState as useState36, useEffect as useEffect33 } from "react";
121148
+ import { useState as useState36, useEffect as useEffect34 } from "react";
120951
121149
  import { Box as Box22, Text as Text29, useInput as useInput5 } from "ink";
120952
121150
  init_modelManager();
120953
121151
  import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
@@ -120961,7 +121159,7 @@ function ProviderEndpointSelectionDialog({
120961
121159
  const [loading, setLoading] = useState36(true);
120962
121160
  const [switching, setSwitching] = useState36(false);
120963
121161
  const [error, setError] = useState36(null);
120964
- useEffect33(() => {
121162
+ useEffect34(() => {
120965
121163
  const loadEndpoints = async () => {
120966
121164
  try {
120967
121165
  const modelManager = getModelManager();
@@ -121205,7 +121403,7 @@ function ProviderEndpointSelectionDialog({
121205
121403
  }
121206
121404
 
121207
121405
  // packages/cli/src/ui/components/EnhancedModelSelectionDialog.tsx
121208
- import { useState as useState37, useEffect as useEffect34 } from "react";
121406
+ import { useState as useState37, useEffect as useEffect35 } from "react";
121209
121407
  import { Box as Box23, Text as Text30, useInput as useInput6 } from "ink";
121210
121408
  init_modelManager();
121211
121409
  import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
@@ -121256,7 +121454,7 @@ function EnhancedModelSelectionDialog({
121256
121454
  setLoading(false);
121257
121455
  }
121258
121456
  };
121259
- useEffect34(() => {
121457
+ useEffect35(() => {
121260
121458
  loadModels();
121261
121459
  }, [providerType, endpointUrl]);
121262
121460
  useInput6((input, key) => {
@@ -121596,7 +121794,7 @@ var WelcomeBackDialog = ({
121596
121794
  };
121597
121795
 
121598
121796
  // packages/cli/src/ui/components/SearchEngineConfigDialog.tsx
121599
- import { useState as useState38, useEffect as useEffect35 } from "react";
121797
+ import { useState as useState38, useEffect as useEffect36 } from "react";
121600
121798
  import { Box as Box25, Text as Text32, useInput as useInput7 } from "ink";
121601
121799
  init_database();
121602
121800
  import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
@@ -121609,7 +121807,7 @@ function SearchEngineConfigDialog({
121609
121807
  const [currentField, setCurrentField] = useState38("braveApiKey");
121610
121808
  const [isLoading, setIsLoading] = useState38(true);
121611
121809
  const [isSaving, setIsSaving] = useState38(false);
121612
- useEffect35(() => {
121810
+ useEffect36(() => {
121613
121811
  const loadConfig = async () => {
121614
121812
  console.log("[WEBSCRAPER-DEBUG] Loading existing API keys from database...");
121615
121813
  const db = await getFSSLinkDatabase();
@@ -121629,7 +121827,7 @@ function SearchEngineConfigDialog({
121629
121827
  };
121630
121828
  loadConfig().catch(console.error);
121631
121829
  }, []);
121632
- useEffect35(() => {
121830
+ useEffect36(() => {
121633
121831
  if (!isSaving) return;
121634
121832
  const saveConfig = async () => {
121635
121833
  try {
@@ -121853,7 +122051,7 @@ function SearchEngineConfigDialog({
121853
122051
  }
121854
122052
 
121855
122053
  // packages/cli/src/ui/components/AuthInProgress.tsx
121856
- import { useState as useState39, useEffect as useEffect36 } from "react";
122054
+ import { useState as useState39, useEffect as useEffect37 } from "react";
121857
122055
  import { Box as Box26, Text as Text33 } from "ink";
121858
122056
  import Spinner2 from "ink-spinner";
121859
122057
  import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
@@ -121869,7 +122067,7 @@ function AuthInProgress({
121869
122067
  },
121870
122068
  { isActive: true }
121871
122069
  );
121872
- useEffect36(() => {
122070
+ useEffect37(() => {
121873
122071
  const timer = setTimeout(() => {
121874
122072
  setTimedOut(true);
121875
122073
  onTimeout();
@@ -125480,7 +125678,7 @@ function IdeIntegrationNudge({
125480
125678
  }
125481
125679
 
125482
125680
  // packages/cli/src/ui/hooks/useGitBranchName.ts
125483
- import { useState as useState42, useEffect as useEffect37, useCallback as useCallback24 } from "react";
125681
+ import { useState as useState42, useEffect as useEffect38, useCallback as useCallback24 } from "react";
125484
125682
  import { exec as exec6 } from "node:child_process";
125485
125683
  import fs65 from "node:fs";
125486
125684
  import fsPromises3 from "node:fs/promises";
@@ -125516,7 +125714,7 @@ function useGitBranchName(cwd3) {
125516
125714
  ),
125517
125715
  [cwd3, setBranchName]
125518
125716
  );
125519
- useEffect37(() => {
125717
+ useEffect38(() => {
125520
125718
  fetchBranchName();
125521
125719
  const gitLogsHeadPath = path77.join(cwd3, ".git", "logs", "HEAD");
125522
125720
  let watcher;
@@ -125540,14 +125738,14 @@ function useGitBranchName(cwd3) {
125540
125738
  }
125541
125739
 
125542
125740
  // packages/cli/src/ui/hooks/useBracketedPaste.ts
125543
- import { useEffect as useEffect38 } from "react";
125741
+ import { useEffect as useEffect39 } from "react";
125544
125742
  var ENABLE_BRACKETED_PASTE = "\x1B[?2004h";
125545
125743
  var DISABLE_BRACKETED_PASTE = "\x1B[?2004l";
125546
125744
  var useBracketedPaste = () => {
125547
125745
  const cleanup = () => {
125548
125746
  process.stdout.write(DISABLE_BRACKETED_PASTE);
125549
125747
  };
125550
- useEffect38(() => {
125748
+ useEffect39(() => {
125551
125749
  process.stdout.write(ENABLE_BRACKETED_PASTE);
125552
125750
  process.on("exit", cleanup);
125553
125751
  process.on("SIGINT", cleanup);
@@ -125567,7 +125765,7 @@ import {
125567
125765
  createContext as createContext5,
125568
125766
  useCallback as useCallback25,
125569
125767
  useContext as useContext5,
125570
- useEffect as useEffect39,
125768
+ useEffect as useEffect40,
125571
125769
  useState as useState43
125572
125770
  } from "react";
125573
125771
  import { jsx as jsx59 } from "react/jsx-runtime";
@@ -125581,7 +125779,7 @@ var VimModeProvider = ({
125581
125779
  const [vimMode, setVimMode] = useState43(
125582
125780
  initialVimEnabled ? "NORMAL" : "INSERT"
125583
125781
  );
125584
- useEffect39(() => {
125782
+ useEffect40(() => {
125585
125783
  const enabled = settings.merged.vimMode ?? false;
125586
125784
  setVimEnabled(enabled);
125587
125785
  if (enabled) {
@@ -125614,7 +125812,7 @@ var useVimMode = () => {
125614
125812
  };
125615
125813
 
125616
125814
  // packages/cli/src/ui/hooks/vim.ts
125617
- import { useCallback as useCallback26, useReducer as useReducer4, useEffect as useEffect40 } from "react";
125815
+ import { useCallback as useCallback26, useReducer as useReducer4, useEffect as useEffect41 } from "react";
125618
125816
  var DIGIT_MULTIPLIER = 10;
125619
125817
  var DEFAULT_COUNT = 1;
125620
125818
  var DIGIT_1_TO_9 = /^[1-9]$/;
@@ -125678,7 +125876,7 @@ var vimReducer = (state, action) => {
125678
125876
  function useVim(buffer, onSubmit) {
125679
125877
  const { vimEnabled, vimMode, setVimMode } = useVimMode();
125680
125878
  const [state, dispatch] = useReducer4(vimReducer, initialVimState);
125681
- useEffect40(() => {
125879
+ useEffect41(() => {
125682
125880
  dispatch({ type: "SET_MODE", mode: vimMode });
125683
125881
  }, [vimMode]);
125684
125882
  const updateMode = useCallback26(
@@ -126474,12 +126672,12 @@ import { Box as Box56, Newline as Newline3, Text as Text61 } from "ink";
126474
126672
 
126475
126673
  // packages/cli/src/ui/hooks/usePrivacySettings.ts
126476
126674
  init_dist2();
126477
- import { useState as useState45, useEffect as useEffect41, useCallback as useCallback27 } from "react";
126675
+ import { useState as useState45, useEffect as useEffect42, useCallback as useCallback27 } from "react";
126478
126676
  var usePrivacySettings = (config) => {
126479
126677
  const [privacyState, setPrivacyState] = useState45({
126480
126678
  isLoading: true
126481
126679
  });
126482
- useEffect41(() => {
126680
+ useEffect42(() => {
126483
126681
  const fetchInitialState = async () => {
126484
126682
  setPrivacyState({
126485
126683
  isLoading: true
@@ -126693,7 +126891,7 @@ function useSettingsCommand() {
126693
126891
  }
126694
126892
 
126695
126893
  // packages/cli/src/ui/components/SettingsDialog.tsx
126696
- import React30, { useState as useState47, useEffect as useEffect42 } from "react";
126894
+ import React30, { useState as useState47, useEffect as useEffect43 } from "react";
126697
126895
  import { Box as Box58, Text as Text62 } from "ink";
126698
126896
  init_settings();
126699
126897
  import chalk2 from "chalk";
@@ -126725,7 +126923,7 @@ function SettingsDialog({
126725
126923
  );
126726
126924
  const [globalPendingChanges, setGlobalPendingChanges] = useState47(/* @__PURE__ */ new Map());
126727
126925
  const [_restartRequiredSettings, setRestartRequiredSettings] = useState47(/* @__PURE__ */ new Set());
126728
- useEffect42(() => {
126926
+ useEffect43(() => {
126729
126927
  let updated = structuredClone(settings.forScope(selectedScope).settings);
126730
126928
  const newModified = /* @__PURE__ */ new Set();
126731
126929
  const newRestartRequired = /* @__PURE__ */ new Set();
@@ -126835,7 +127033,7 @@ function SettingsDialog({
126835
127033
  const [editBuffer, setEditBuffer] = useState47("");
126836
127034
  const [editCursorPos, setEditCursorPos] = useState47(0);
126837
127035
  const [cursorVisible, setCursorVisible] = useState47(true);
126838
- useEffect42(() => {
127036
+ useEffect43(() => {
126839
127037
  if (!editingKey) {
126840
127038
  setCursorVisible(true);
126841
127039
  return;
@@ -127539,11 +127737,11 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127539
127737
  const { history, addItem, clearItems, loadHistory } = useHistory();
127540
127738
  const [idePromptAnswered, setIdePromptAnswered] = useState48(false);
127541
127739
  const currentIDE = config.getIdeClient().getCurrentIde();
127542
- useEffect43(() => {
127740
+ useEffect44(() => {
127543
127741
  registerCleanup(() => config.getIdeClient().disconnect());
127544
127742
  }, [config]);
127545
127743
  const shouldShowIdePrompt = currentIDE && !config.getIdeMode() && !settings.merged.hasSeenIdeIntegrationNudge && !idePromptAnswered;
127546
- useEffect43(() => {
127744
+ useEffect44(() => {
127547
127745
  const cleanup = setUpdateHandler(addItem, setUpdateInfo);
127548
127746
  return cleanup;
127549
127747
  }, [addItem]);
@@ -127552,7 +127750,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127552
127750
  handleNewMessage,
127553
127751
  clearConsoleMessages: clearConsoleMessagesState
127554
127752
  } = useConsoleMessages();
127555
- useEffect43(() => {
127753
+ useEffect44(() => {
127556
127754
  const consolePatcher = new ConsolePatcher({
127557
127755
  onNewMessage: handleNewMessage,
127558
127756
  debugMode: config.getDebugMode()
@@ -127575,7 +127773,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127575
127773
  const [isSearchDialogOpen, setIsSearchDialogOpen] = useState48(false);
127576
127774
  const [isAddCustomEndpointDialogOpen, setIsAddCustomEndpointDialogOpen] = useState48(false);
127577
127775
  const [footerHeight, setFooterHeight] = useState48(0);
127578
- useEffect43(() => {
127776
+ useEffect44(() => {
127579
127777
  const initializeSearchEngineConfig = async () => {
127580
127778
  const configProvider = SearchEngineConfigProvider.getInstance();
127581
127779
  await configProvider.loadConfiguration();
@@ -127602,12 +127800,12 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127602
127800
  const [ideContextState, setIdeContextState] = useState48();
127603
127801
  const [showEscapePrompt, setShowEscapePrompt] = useState48(false);
127604
127802
  const [isProcessing, setIsProcessing] = useState48(false);
127605
- useEffect43(() => {
127803
+ useEffect44(() => {
127606
127804
  const unsubscribe = ideContext.subscribeToIdeContext(setIdeContextState);
127607
127805
  setIdeContextState(ideContext.getIdeContext());
127608
127806
  return unsubscribe;
127609
127807
  }, []);
127610
- useEffect43(() => {
127808
+ useEffect44(() => {
127611
127809
  const openDebugConsole = () => {
127612
127810
  setShowErrorDetails(true);
127613
127811
  setConstrainHeight(false);
@@ -127674,7 +127872,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127674
127872
  handleRestart: handleWelcomeBackRestart,
127675
127873
  handleCancel: handleWelcomeBackCancel
127676
127874
  } = useWelcomeBack(settings);
127677
- useEffect43(() => {
127875
+ useEffect44(() => {
127678
127876
  if (settings.merged.selectedAuthType && !settings.merged.useExternalAuth) {
127679
127877
  const error = validateAuthMethod(settings.merged.selectedAuthType);
127680
127878
  if (error) {
@@ -127688,7 +127886,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127688
127886
  openAuthDialog,
127689
127887
  setAuthError
127690
127888
  ]);
127691
- useEffect43(() => {
127889
+ useEffect44(() => {
127692
127890
  if (!isAuthenticating) {
127693
127891
  setUserTier(config.getGeminiClient()?.getUserTier());
127694
127892
  }
@@ -127752,7 +127950,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127752
127950
  console.error("Error refreshing memory:", error);
127753
127951
  }
127754
127952
  }, [config, addItem, settings.merged]);
127755
- useEffect43(() => {
127953
+ useEffect44(() => {
127756
127954
  const checkModelChange = () => {
127757
127955
  const configModel = config.getModel();
127758
127956
  if (configModel !== currentModel) {
@@ -127763,7 +127961,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127763
127961
  const interval = setInterval(checkModelChange, 1e3);
127764
127962
  return () => clearInterval(interval);
127765
127963
  }, [config, currentModel]);
127766
- useEffect43(() => {
127964
+ useEffect44(() => {
127767
127965
  const flashFallbackHandler = async (currentModel2, fallbackModel, error) => {
127768
127966
  let message;
127769
127967
  if (config.getContentGeneratorConfig().authType === AuthType.LOGIN_WITH_GOOGLE) {
@@ -127922,7 +128120,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
127922
128120
  refreshStatic,
127923
128121
  () => cancelHandlerRef.current()
127924
128122
  );
127925
- useEffect43(() => {
128123
+ useEffect44(() => {
127926
128124
  if (contextToPopulate && !initialPromptSubmitted.current) {
127927
128125
  submitQuery(contextToPopulate);
127928
128126
  initialPromptSubmitted.current = true;
@@ -128057,13 +128255,13 @@ ${queuedText}` : queuedText;
128057
128255
  useKeypress(handleGlobalKeypress, {
128058
128256
  isActive: true
128059
128257
  });
128060
- useEffect43(() => {
128258
+ useEffect44(() => {
128061
128259
  if (config) {
128062
128260
  setGeminiMdFileCount(config.getGeminiMdFileCount());
128063
128261
  }
128064
128262
  }, [config, config.getGeminiMdFileCount]);
128065
128263
  const logger6 = useLogger();
128066
- useEffect43(() => {
128264
+ useEffect44(() => {
128067
128265
  const fetchUserMessages = async () => {
128068
128266
  const pastMessagesRaw = await logger6?.getPreviousUserMessages() || [];
128069
128267
  const currentSessionUserMessages = history.filter(
@@ -128095,7 +128293,7 @@ ${queuedText}` : queuedText;
128095
128293
  }, [clearItems, clearConsoleMessagesState, refreshStatic]);
128096
128294
  const mainControlsRef = useRef12(null);
128097
128295
  const pendingHistoryItemRef = useRef12(null);
128098
- useEffect43(() => {
128296
+ useEffect44(() => {
128099
128297
  if (mainControlsRef.current) {
128100
128298
  const fullFooterMeasurement = measureElement(mainControlsRef.current);
128101
128299
  setFooterHeight(fullFooterMeasurement.height);
@@ -128109,7 +128307,7 @@ ${queuedText}` : queuedText;
128109
128307
  () => terminalHeight - footerHeight - staticExtraHeight,
128110
128308
  [terminalHeight, footerHeight]
128111
128309
  );
128112
- useEffect43(() => {
128310
+ useEffect44(() => {
128113
128311
  if (isInitialMount.current) {
128114
128312
  isInitialMount.current = false;
128115
128313
  return;
@@ -128122,7 +128320,7 @@ ${queuedText}` : queuedText;
128122
128320
  clearTimeout(handler);
128123
128321
  };
128124
128322
  }, [terminalWidth, terminalHeight, refreshStatic]);
128125
- useEffect43(() => {
128323
+ useEffect44(() => {
128126
128324
  if (streamingState === "idle" /* Idle */ && staticNeedsRefresh) {
128127
128325
  setStaticNeedsRefresh(false);
128128
128326
  refreshStatic();
@@ -128144,7 +128342,7 @@ ${queuedText}` : queuedText;
128144
128342
  }, [settings.merged.contextFileName]);
128145
128343
  const initialPrompt = useMemo9(() => config.getQuestion(), [config]);
128146
128344
  const geminiClient = config.getGeminiClient();
128147
- useEffect43(() => {
128345
+ useEffect44(() => {
128148
128346
  if (initialPrompt && !initialPromptSubmitted.current && !isAuthenticating && !isAuthDialogOpen && !shouldShowWelcomeBack && !isThemeDialogOpen && !isEditorDialogOpen && !isSearchDialogOpen && modelDialogState === "none" && !showPrivacyNotice && geminiClient?.isInitialized?.()) {
128149
128347
  submitQuery(initialPrompt);
128150
128348
  initialPromptSubmitted.current = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fss-link",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "engines": {
5
5
  "node": ">=20.0.0"
6
6
  },
@@ -133,6 +133,7 @@
133
133
  "ink-link": "^4.1.0",
134
134
  "ink-select-input": "^6.2.0",
135
135
  "ink-spinner": "^5.0.0",
136
+ "ink-text-input": "^6.0.0",
136
137
  "jsdom": "^27.0.0",
137
138
  "lowlight": "^3.3.0",
138
139
  "mime-types": "^3.0.1",