fss-link 1.7.7 → 1.9.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 +17 -6
- package/bundle/fss-link-main.js +2025 -1709
- package/bundle/fss-link-main.js.bak-20260629 +4468 -0
- package/docs/CONFIGURATION.md +10 -26
- package/docs/README.md +6 -8
- package/docs/SLASH-COMMANDS.md +186 -0
- package/package.json +3 -2
- package/scripts/build_package.js +8 -1
- package/scripts/prebundle-sync-dist.js +8 -0
- package/scripts/version.js +29 -18
package/docs/CONFIGURATION.md
CHANGED
|
@@ -10,21 +10,6 @@ FSS Link supports multiple LLM providers. Configure via CLI flags, environment v
|
|
|
10
10
|
2. **Database config** — persistent, survives restarts
|
|
11
11
|
3. **Environment variables** — traditional fallback
|
|
12
12
|
|
|
13
|
-
### Ollama
|
|
14
|
-
|
|
15
|
-
Local models via Ollama. Default port 11434.
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
# CLI
|
|
19
|
-
fss-link --provider ollama --model qwen3:4b
|
|
20
|
-
|
|
21
|
-
# Or set the context window for large conversations
|
|
22
|
-
fss-link --provider ollama --model qwen3:4b
|
|
23
|
-
# Then use /context 32768 inside the session
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
**Context window**: Defaults to 32,768 tokens. Use the `/context` command to set a custom value that persists to the database.
|
|
27
|
-
|
|
28
13
|
### LM Studio
|
|
29
14
|
|
|
30
15
|
Local models via LM Studio. Default port 1234.
|
|
@@ -65,7 +50,7 @@ fss-link --provider gemini-api-key --model gemini-2.0-flash
|
|
|
65
50
|
|
|
66
51
|
## Database Configuration
|
|
67
52
|
|
|
68
|
-
FSS Link stores model configuration in a SQLite database at `~/.fss-link/
|
|
53
|
+
FSS Link stores model configuration in a SQLite database at `~/.fss-link/fss-link.db`. This is the persistent source of truth for model settings.
|
|
69
54
|
|
|
70
55
|
<!-- bobai:image-card width="6" -->
|
|
71
56
|

|
|
@@ -77,19 +62,19 @@ Your model choice survives restarts. CLI flags override, environment fallback.
|
|
|
77
62
|
|
|
78
63
|
```bash
|
|
79
64
|
# View current config
|
|
80
|
-
sqlite3 ~/.fss-link/
|
|
65
|
+
sqlite3 ~/.fss-link/fss-link.db "SELECT auth_type, model_name, endpoint_url, is_active FROM model_configs"
|
|
81
66
|
|
|
82
67
|
# Switch active model
|
|
83
|
-
sqlite3 ~/.fss-link/
|
|
84
|
-
sqlite3 ~/.fss-link/
|
|
68
|
+
sqlite3 ~/.fss-link/fss-link.db "UPDATE model_configs SET is_active = 0"
|
|
69
|
+
sqlite3 ~/.fss-link/fss-link.db "UPDATE model_configs SET is_active = 1 WHERE auth_type = 'bob-ai' AND model_name = 'qwen3.5-35b-a3b'"
|
|
85
70
|
|
|
86
71
|
# Change endpoint
|
|
87
|
-
sqlite3 ~/.fss-link/
|
|
72
|
+
sqlite3 ~/.fss-link/fss-link.db "UPDATE model_configs SET endpoint_url = 'http://your-server:1234/v1' WHERE auth_type = 'lm-studio'"
|
|
88
73
|
```
|
|
89
74
|
|
|
90
75
|
### Database Location
|
|
91
76
|
|
|
92
|
-
- Linux/macOS: `~/.fss-link/
|
|
77
|
+
- Linux/macOS: `~/.fss-link/fss-link.db`
|
|
93
78
|
- Data directory: `~/.fss-link/`
|
|
94
79
|
- Todos: `~/.fss-link/todos/`
|
|
95
80
|
|
|
@@ -103,10 +88,9 @@ The context window is the maximum number of tokens the model can process in a si
|
|
|
103
88
|
|
|
104
89
|
1. **Manual override** in `settings.json` (`chatCompression.contextWindow`)
|
|
105
90
|
2. **LM Studio API query** (auto-detected from server)
|
|
106
|
-
3. **
|
|
107
|
-
4. **
|
|
108
|
-
5. **
|
|
109
|
-
6. **Provider defaults**: Ollama 32k, LM Studio 32k, OpenAI-compat 128k
|
|
91
|
+
3. **OpenAI-compatible `/models` endpoint** (vLLM `max_model_len`)
|
|
92
|
+
4. **Static lookup** for known models (Gemini variants)
|
|
93
|
+
5. **Provider defaults**: LM Studio 32k, OpenAI-compat 128k
|
|
110
94
|
|
|
111
95
|
### Compression
|
|
112
96
|
|
|
@@ -128,7 +112,7 @@ Full detail on recent context, compressed summaries for older messages.
|
|
|
128
112
|
|
|
129
113
|
### The `/context` Command
|
|
130
114
|
|
|
131
|
-
Set the context window
|
|
115
|
+
Set the context window size:
|
|
132
116
|
|
|
133
117
|
```
|
|
134
118
|
/context 32768 # Set to 32k
|
package/docs/README.md
CHANGED
|
@@ -21,7 +21,7 @@ $ fss-link
|
|
|
21
21
|
## Key Features
|
|
22
22
|
|
|
23
23
|
<!-- bobai:badges -->
|
|
24
|
-
|
|
24
|
+
LM Studio, BobAI, OpenAI, Gemini, vLLM
|
|
25
25
|
<!-- /bobai:badges -->
|
|
26
26
|
|
|
27
27
|
- **Multi-provider support** — Connect to any LLM (local or cloud)
|
|
@@ -40,7 +40,7 @@ Ollama, LM Studio, OpenAI, Gemini, vLLM
|
|
|
40
40
|
<!-- bobai:image-card width="6" -->
|
|
41
41
|

|
|
42
42
|
### Connect Anywhere
|
|
43
|
-
Local models via
|
|
43
|
+
Local models via LM Studio and BobAI. Cloud providers (OpenAI, Gemini). Custom endpoints (vLLM).
|
|
44
44
|
<!-- /bobai:image-card -->
|
|
45
45
|
|
|
46
46
|
## Installation
|
|
@@ -65,14 +65,11 @@ npm install -g .
|
|
|
65
65
|
|
|
66
66
|
## Quick Start
|
|
67
67
|
|
|
68
|
-
### With
|
|
68
|
+
### With BobAI / vLLM (Local)
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# Launch FSS Link
|
|
75
|
-
fss-link --provider ollama --model qwen3:4b
|
|
71
|
+
export BOB_AI_BASE_URL="http://your-server:8000/v1"
|
|
72
|
+
fss-link --provider bob-ai --model qwen3.5-35b-a3b
|
|
76
73
|
```
|
|
77
74
|
|
|
78
75
|
### With LM Studio (Local)
|
|
@@ -186,6 +183,7 @@ npx vitest run packages/cli/src/config/database.test.ts
|
|
|
186
183
|
|
|
187
184
|
- [Configuration Guide](CONFIGURATION.md) — providers, models, database, context settings
|
|
188
185
|
- [Tools Reference](TOOLS.md) — all available tools and their parameters
|
|
186
|
+
- [Slash Commands](SLASH-COMMANDS.md) — `/resume`, `/rewind`, `/sessions`, and the Welcome Back dialog
|
|
189
187
|
- [Tool Flow Diagrams](../fss-docs/tool-flow-diagrams/) — visual documentation with Mermaid diagrams
|
|
190
188
|
|
|
191
189
|
## License
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Slash Commands — Session Management
|
|
2
|
+
|
|
3
|
+
## `/resume` — List and Resume Saved Sessions
|
|
4
|
+
|
|
5
|
+
Resume a previous conversation session by number, title, or session ID.
|
|
6
|
+
|
|
7
|
+
### Usage
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
/resume # List recent sessions
|
|
11
|
+
/resume <number> # Resume by list position
|
|
12
|
+
/resume <title substring> # Resume by title match
|
|
13
|
+
/resume <session-id> # Resume by exact session ID
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Alternatives
|
|
17
|
+
|
|
18
|
+
`/sessions`, `/continue` — all three names invoke the same command.
|
|
19
|
+
|
|
20
|
+
### Listing Sessions
|
|
21
|
+
|
|
22
|
+
Running `/resume` with no arguments displays a numbered list of up to 50 recent sessions for the current project, sorted by most recently updated:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Recent sessions:
|
|
26
|
+
|
|
27
|
+
1. Implement auth middleware for API endpoints 2 hours ago 14 turns
|
|
28
|
+
2. Fix login bug on password reset flow 1 day ago 8 turns
|
|
29
|
+
3. Set up CI pipeline with GitHub Actions 3 days ago 22 turns
|
|
30
|
+
|
|
31
|
+
Type a number to resume, or /resume <partial title> to match by name.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Titles are truncated at 55 characters. The list is scoped to the current project (identified by project hash).
|
|
35
|
+
|
|
36
|
+
### Selection Methods
|
|
37
|
+
|
|
38
|
+
| Method | Example | Behavior |
|
|
39
|
+
|--------|---------|----------|
|
|
40
|
+
| **Numeric index** | `/resume 2` | Selects the second item in the listed order (1-based) |
|
|
41
|
+
| **Title substring** | `/resume auth` | First session whose title contains "auth" (case-insensitive) |
|
|
42
|
+
| **Exact session ID** | `/resume abc123def` | Matches the session's unique ID exactly |
|
|
43
|
+
|
|
44
|
+
### Matching Rules
|
|
45
|
+
|
|
46
|
+
- **Numeric index** is checked first. If the number is out of range (fewer sessions than the number given), it falls through to title matching.
|
|
47
|
+
- **Title substring** uses `String.prototype.includes()` — any part of the title matching the input selects the first such session. There is no ranking or scoring; the first match wins.
|
|
48
|
+
- **Exact session ID** is the final fallback if neither numeric nor title matching succeeds.
|
|
49
|
+
- If no match is found at all, an error message is shown: `No session matched "foo". Use /resume to list sessions.`
|
|
50
|
+
|
|
51
|
+
### Tab Completion
|
|
52
|
+
|
|
53
|
+
Pressing Tab while typing `/resume <partial>` shows completions for session titles that **start with** the partial text (`startsWith`). This is intentionally stricter than the action's own matching (`includes`) — tab completion may show fewer options than what `/resume <text>` would actually match.
|
|
54
|
+
|
|
55
|
+
### What Happens When You Resume
|
|
56
|
+
|
|
57
|
+
The selected session's full conversation history is restored:
|
|
58
|
+
- The Gemini client's history is replaced with the saved history from the session
|
|
59
|
+
- The session ID is set so subsequent exchanges update the same session record
|
|
60
|
+
- Turn count is restored from the session record
|
|
61
|
+
- The UI displays the restored history as a scrollable message list
|
|
62
|
+
|
|
63
|
+
### Session Storage
|
|
64
|
+
|
|
65
|
+
Sessions are stored in `~/.fss-link/sessions.db` (a dedicated SQLite database). Each session record includes:
|
|
66
|
+
- `id` — unique session identifier
|
|
67
|
+
- `title` — auto-generated from the first user message (truncated to 80 chars)
|
|
68
|
+
- `project_path`, `project_hash` — project identification
|
|
69
|
+
- `provider`, `model_name` — which model was used
|
|
70
|
+
- `created_at`, `updated_at` — timestamps
|
|
71
|
+
- `turn_count`, `total_input_tokens`, `total_output_tokens` — usage metrics
|
|
72
|
+
- `history_json` — full conversation history as JSON
|
|
73
|
+
|
|
74
|
+
Sessions are created on the first exchange in a conversation and updated after each subsequent exchange. An auto-save timer flushes changes every 30 seconds.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## `/rewind` — Rewind to a Previous Turn
|
|
79
|
+
|
|
80
|
+
Rewind the conversation to a selected past turn, discarding everything after it.
|
|
81
|
+
|
|
82
|
+
### Usage
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
/rewind # Open rewind dialog
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
No arguments are accepted — `/rewind foo` behaves identically to `/rewind`.
|
|
89
|
+
|
|
90
|
+
### How It Works
|
|
91
|
+
|
|
92
|
+
Running `/rewind` opens an interactive dialog that shows all user-initiated turns in the current conversation. Selecting a turn discards everything after it, effectively rewinding the conversation to that point.
|
|
93
|
+
|
|
94
|
+
### Turn Extraction
|
|
95
|
+
|
|
96
|
+
The dialog filters the conversation history to show only meaningful user turns:
|
|
97
|
+
- **Included**: User messages with text content
|
|
98
|
+
- **Excluded**: Tool-response turns (all parts are `functionResponse`), system notes (`[System note:`), steering messages (`[Steering message`)
|
|
99
|
+
|
|
100
|
+
Turns are displayed in reverse-chronological order (most recent first), numbered T1, T2, T3… from oldest to newest.
|
|
101
|
+
|
|
102
|
+
### Navigation & Search
|
|
103
|
+
|
|
104
|
+
| Key | Action |
|
|
105
|
+
|-----|--------|
|
|
106
|
+
| `↑` / `↓` | Move selection up/down |
|
|
107
|
+
| `Enter` | Confirm selection and rewind |
|
|
108
|
+
| `Esc` (first press) | Clear the search filter |
|
|
109
|
+
| `Esc` (second press) | Close the dialog without rewinding |
|
|
110
|
+
| `Backspace` | Delete one character from the search filter |
|
|
111
|
+
| Any printable character | Type into the search filter box |
|
|
112
|
+
|
|
113
|
+
### Search
|
|
114
|
+
|
|
115
|
+
The dialog has a working text filter. Type any characters to narrow the visible turns:
|
|
116
|
+
|
|
117
|
+
- **Case-insensitive substring match** on turn text
|
|
118
|
+
- Selection resets to the top (index 0) when the filter changes
|
|
119
|
+
- Shows "No turns match" if the filter produces zero results
|
|
120
|
+
- First `Esc` clears the filter and restores the full list; second `Esc` closes the dialog
|
|
121
|
+
|
|
122
|
+
**Limitations:**
|
|
123
|
+
- Single-term only — multi-word queries like "auth middleware" won't work as two separate terms
|
|
124
|
+
- Searches only user message text, not tool calls, results, or delta events
|
|
125
|
+
- No ranking or scoring — just `includes` substring match
|
|
126
|
+
|
|
127
|
+
### What Happens When You Rewind
|
|
128
|
+
|
|
129
|
+
1. The conversation history is cleared
|
|
130
|
+
2. A preview message is built from the selected turn's content
|
|
131
|
+
3. All turns after the selected one are discarded
|
|
132
|
+
4. The model can then continue from the rewound point
|
|
133
|
+
|
|
134
|
+
### Known Behavior
|
|
135
|
+
|
|
136
|
+
The rewind point uses `fullHistory.slice(0, contentIndex)` — the selected turn is **included** in the rewound history. The dialog help text says "conversation after selected turn will be discarded," which is accurate: the selected turn itself is preserved, everything after it is removed.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## `/sessions` — Alias for `/resume`
|
|
141
|
+
|
|
142
|
+
`/sessions` and `/continue` are aliases for `/resume`. All three names invoke the same command with identical behavior. See `/resume` above for full details.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Welcome Back Dialog — Project-Level Resume
|
|
147
|
+
|
|
148
|
+
The **Welcome Back dialog** is a separate feature from `/resume`. It appears automatically when you launch FSS Link in a project that has prior session history, offering a high-level choice to continue from where you left off or start fresh.
|
|
149
|
+
|
|
150
|
+
### When It Appears
|
|
151
|
+
|
|
152
|
+
- On startup, when `enableWelcomeBack` is enabled in settings (default: on)
|
|
153
|
+
- Only when the project has existing conversation history
|
|
154
|
+
- Uses `ProjectSummaryParser` to analyze project state — not `sessions.db` directly
|
|
155
|
+
|
|
156
|
+
### Options
|
|
157
|
+
|
|
158
|
+
| Option | Keyboard Shortcut | Behavior |
|
|
159
|
+
|--------|-------------------|----------|
|
|
160
|
+
| **Continue Project** | `C` | Resumes from the most recent session with contextual summary |
|
|
161
|
+
| **Start Fresh Session** | `R` | Begins a new conversation with no history |
|
|
162
|
+
| **Cancel** | `Q` / `Escape` | Exits without starting a session |
|
|
163
|
+
|
|
164
|
+
### What It Shows
|
|
165
|
+
|
|
166
|
+
The dialog displays project-level information including:
|
|
167
|
+
- Project goal (if available)
|
|
168
|
+
- Time since last activity
|
|
169
|
+
- Session count and active sessions
|
|
170
|
+
- Momentum indicator (high / building / stale / none)
|
|
171
|
+
- Git status (branch, staged/unstaged changes, last commit)
|
|
172
|
+
- Efficiency metrics and recent activity summary
|
|
173
|
+
- Next suggestion (if available)
|
|
174
|
+
|
|
175
|
+
### Key Differences from `/resume`
|
|
176
|
+
|
|
177
|
+
| Aspect | Welcome Back Dialog | `/resume` |
|
|
178
|
+
|--------|---------------------|-----------|
|
|
179
|
+
| **Trigger** | Automatic on project launch | Manual slash command |
|
|
180
|
+
| **Scope** | Project-level (one choice) | Per-session picker (up to 50) |
|
|
181
|
+
| **Data source** | `ProjectSummaryParser` (analysis of project state) | `sessions.db` (direct session records) |
|
|
182
|
+
| **Selection** | Continue / Restart / Cancel | Number, title substring, or session ID |
|
|
183
|
+
| **Context** | Smart summary built from project analysis | Full conversation history restored verbatim |
|
|
184
|
+
| **Search** | None — single decision point | Substring search across session titles |
|
|
185
|
+
|
|
186
|
+
The Welcome Back dialog is best for quick decisions at project launch. `/resume` is for browsing and selecting from multiple saved sessions within an active conversation.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fss-link",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.2",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.0.0"
|
|
6
6
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "git+https://github.com/FSSCoding/fss-link.git"
|
|
14
14
|
},
|
|
15
15
|
"config": {
|
|
16
|
-
"sandboxImageUri": "ghcr.io/fsscoding/fss-link:1.
|
|
16
|
+
"sandboxImageUri": "ghcr.io/fsscoding/fss-link:1.9.2"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"start": "node scripts/start.js",
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
"LICENSE"
|
|
83
83
|
],
|
|
84
84
|
"devDependencies": {
|
|
85
|
+
"@testing-library/dom": "^10.4.1",
|
|
85
86
|
"@types/ink-testing-library": "^1.0.4",
|
|
86
87
|
"@vitest/coverage-v8": "^4.1.8",
|
|
87
88
|
"concurrently": "^9.2.0",
|
package/scripts/build_package.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// limitations under the License.
|
|
19
19
|
|
|
20
20
|
import { execSync } from 'child_process';
|
|
21
|
-
import { writeFileSync } from 'fs';
|
|
21
|
+
import { writeFileSync, rmSync } from 'fs';
|
|
22
22
|
import { join } from 'path';
|
|
23
23
|
|
|
24
24
|
if (!process.cwd().includes('packages')) {
|
|
@@ -26,6 +26,13 @@ if (!process.cwd().includes('packages')) {
|
|
|
26
26
|
process.exit(1);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
// Clean dist first — `tsc --build` is incremental and trusts its
|
|
30
|
+
// .tsbuildinfo cache. Any prior partial `rm -rf dist` or interrupted build
|
|
31
|
+
// leaves that cache out of sync with what's actually on disk, which surfaces
|
|
32
|
+
// as TS5055 "Cannot write file ... because it would overwrite input file".
|
|
33
|
+
// Same fix already applied in prebundle-sync-dist.js for the bundle path.
|
|
34
|
+
rmSync(join(process.cwd(), 'dist'), { recursive: true, force: true });
|
|
35
|
+
|
|
29
36
|
// build typescript files
|
|
30
37
|
execSync('tsc --build', { stdio: 'inherit' });
|
|
31
38
|
|
|
@@ -24,6 +24,14 @@ const root = resolve(__dirname, '..');
|
|
|
24
24
|
const packages = ['packages/core', 'packages/cli'];
|
|
25
25
|
|
|
26
26
|
for (const pkg of packages) {
|
|
27
|
+
// Clean dist first to avoid incremental build cache corruption that
|
|
28
|
+
// produces mangled output (e.g. #; private fields, broken syntax).
|
|
29
|
+
// See: incremental tsbuildinfo gets out of sync with source changes.
|
|
30
|
+
const { execSync } = await import('child_process');
|
|
31
|
+
const { rm } = await import('fs/promises');
|
|
32
|
+
const { resolve } = await import('path');
|
|
33
|
+
const distDir = resolve(root, pkg, 'dist');
|
|
34
|
+
try { await rm(distDir, { recursive: true, force: true }); } catch {}
|
|
27
35
|
const tsconfig = resolve(root, pkg, 'tsconfig.json');
|
|
28
36
|
try {
|
|
29
37
|
execSync(`npx tsc --noCheck -p ${tsconfig}`, {
|
package/scripts/version.js
CHANGED
|
@@ -36,33 +36,44 @@ if (!versionType) {
|
|
|
36
36
|
// 2. Bump the version in the root and all workspace package.json files.
|
|
37
37
|
run(`npm version ${versionType} --no-git-tag-version --allow-same-version`);
|
|
38
38
|
|
|
39
|
-
// 3.
|
|
40
|
-
const workspacesToExclude = [
|
|
39
|
+
// 3. Resolve workspace globs and collect all workspace names.
|
|
40
|
+
const workspacesToExclude = [
|
|
41
|
+
'fss-link-vscode-ide-companion',
|
|
42
|
+
'@fsscoding/fss-link-web-client',
|
|
43
|
+
];
|
|
41
44
|
const rootPkg = readJson(resolve(process.cwd(), 'package.json'));
|
|
42
45
|
const workspaceDirs = rootPkg.workspaces || [];
|
|
46
|
+
const { glob } = await import('glob');
|
|
43
47
|
const workspacesToVersion = [];
|
|
44
|
-
for (const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
for (const pattern of workspaceDirs) {
|
|
49
|
+
const matches = await glob(pattern, { cwd: process.cwd(), absolute: false });
|
|
50
|
+
for (const dir of matches) {
|
|
51
|
+
const pkgPath = resolve(process.cwd(), dir, 'package.json');
|
|
52
|
+
try {
|
|
53
|
+
const wsPkg = readJson(pkgPath);
|
|
54
|
+
if (!workspacesToExclude.includes(wsPkg.name)) {
|
|
55
|
+
workspacesToVersion.push({ name: wsPkg.name, dir });
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// Skip directories without package.json
|
|
50
59
|
}
|
|
51
|
-
} catch {
|
|
52
|
-
// Skip directories without package.json
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
|
|
57
|
-
run(
|
|
58
|
-
`npm version ${versionType} --workspace ${workspaceName} --no-git-tag-version --allow-same-version`,
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 4. Get the new version number from the root package.json
|
|
63
|
+
// 4. Get the new version number from the root package.json (AFTER npm version bump)
|
|
63
64
|
const rootPackageJsonPath = resolve(process.cwd(), 'package.json');
|
|
64
65
|
const newVersion = readJson(rootPackageJsonPath).version;
|
|
65
66
|
|
|
67
|
+
for (const { name, dir } of workspacesToVersion) {
|
|
68
|
+
// npm version doesn't support --legacy-peer-deps, so we update the file directly
|
|
69
|
+
// and let the final npm install reconcile everything
|
|
70
|
+
const pkgPath = resolve(process.cwd(), dir, 'package.json');
|
|
71
|
+
const wsPkg = readJson(pkgPath);
|
|
72
|
+
wsPkg.version = newVersion;
|
|
73
|
+
writeJson(pkgPath, wsPkg);
|
|
74
|
+
console.log(`Updated ${name} to v${newVersion}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
66
77
|
// 6. Update the sandboxImageUri in the root package.json
|
|
67
78
|
const rootPackageJson = readJson(rootPackageJsonPath);
|
|
68
79
|
if (rootPackageJson.config?.sandboxImageUri) {
|
|
@@ -86,6 +97,6 @@ if (cliPackageJson.config?.sandboxImageUri) {
|
|
|
86
97
|
|
|
87
98
|
// 8. Run `npm install` to update package-lock.json.
|
|
88
99
|
// --ignore-scripts prevents the prepare hook (bundle) from firing before deps exist.
|
|
89
|
-
run('npm install --ignore-scripts');
|
|
100
|
+
run('npm install --ignore-scripts --legacy-peer-deps');
|
|
90
101
|
|
|
91
102
|
console.log(`Successfully bumped versions to v${newVersion}.`);
|