@gmickel/gno 2.9.2 → 2.10.1
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 +2 -2
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v2.9.2.zip → gno-browser-clipper-v2.10.1.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.10.1.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/bunfig.toml +5 -1
- package/package.json +3 -2
- package/spec/cli.md +102 -12
- package/spec/mcp.md +1 -1
- package/spec/output-schemas/mcp-remove-result.schema.json +2 -2
- package/src/app/bun-runtime.ts +41 -0
- package/src/cli/commands/cleanup.ts +9 -1
- package/src/cli/commands/collection/remove.ts +50 -31
- package/src/cli/commands/collection/rename.ts +36 -8
- package/src/cli/commands/daemon.ts +3 -0
- package/src/cli/commands/doctor.ts +61 -0
- package/src/cli/commands/mcp/config-editors.ts +56 -8
- package/src/cli/commands/mcp/install.ts +159 -24
- package/src/cli/commands/mcp/launch-path.ts +87 -0
- package/src/cli/commands/mcp/paths.ts +30 -6
- package/src/cli/commands/mcp/repair-entry.ts +160 -0
- package/src/cli/commands/mcp/status.ts +55 -15
- package/src/cli/commands/mcp.ts +4 -0
- package/src/cli/commands/serve.ts +3 -0
- package/src/cli/commands/status.ts +24 -0
- package/src/cli/detach.ts +10 -0
- package/src/cli/program.ts +64 -19
- package/src/cli/runtime-health.ts +328 -0
- package/src/core/network-boundary-inventory.ts +16 -0
- package/src/ingestion/file-processor.ts +118 -17
- package/src/ingestion/prepare-worker.ts +20 -2
- package/src/mcp/tools/remove-collection.ts +2 -1
- package/src/serve/public/components/BootstrapStatus.tsx +3 -3
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/routes/api.ts +3 -4
- package/src/serve/status.ts +2 -1
- package/src/store/sqlite/adapter.ts +17 -4
- package/browser-extension/artifacts/gno-browser-clipper-v2.9.2.zip.sha256 +0 -1
package/README.md
CHANGED
|
@@ -139,7 +139,7 @@ See the [guide](docs/COMPILED-CONTEXT.md).
|
|
|
139
139
|
|
|
140
140
|
<!-- public-truth:current-version -->
|
|
141
141
|
|
|
142
|
-
> Current source version: **v2.
|
|
142
|
+
> Current source version: **v2.10.1**. See [CHANGELOG.md](./CHANGELOG.md).
|
|
143
143
|
|
|
144
144
|
<!-- /public-truth -->
|
|
145
145
|
|
|
@@ -332,7 +332,7 @@ Manage the detached process with `gno daemon --status` and `gno daemon --stop`.
|
|
|
332
332
|
|
|
333
333
|
<!-- public-truth:runtime -->
|
|
334
334
|
|
|
335
|
-
Requires [Bun](https://bun.sh/) >=1.
|
|
335
|
+
Requires [Bun](https://bun.sh/) >=1.4.1.
|
|
336
336
|
|
|
337
337
|
<!-- /public-truth -->
|
|
338
338
|
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
e42897b28d0fc0fca7d1d7aca6ab016255cc3b5bf20d38bcac51535499eb7f25 gno-browser-clipper-v2.10.1.zip
|
package/bunfig.toml
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
plugins = ["bun-plugin-tailwind"]
|
|
3
3
|
|
|
4
4
|
[test]
|
|
5
|
-
preload = [
|
|
5
|
+
preload = [
|
|
6
|
+
"./test/preload/temp-dir.ts",
|
|
7
|
+
"./test/preload/happy-dom.ts",
|
|
8
|
+
"./test/preload/env-guard.ts",
|
|
9
|
+
]
|
|
6
10
|
# Frozen evidence and local experiments are not the executable regression suite.
|
|
7
11
|
pathIgnorePatterns = [".flow/artifacts/**", "notes/**"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gmickel/gno",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.1",
|
|
4
4
|
"description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"embeddings",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"test:e2e:install": "bunx playwright install chromium",
|
|
73
73
|
"test:package": "bun scripts/package-smoke.ts",
|
|
74
74
|
"test:package:clipper": "bun scripts/package-smoke-clipper-cli.ts",
|
|
75
|
+
"test:tmp-check": "bun scripts/test-tmp-check.ts",
|
|
75
76
|
"test:watch": "bun test --watch",
|
|
76
77
|
"test:coverage": "bun test --coverage",
|
|
77
78
|
"test:coverage:html": "bun test --coverage --html",
|
|
@@ -268,7 +269,7 @@
|
|
|
268
269
|
"file-type": "22.0.2"
|
|
269
270
|
},
|
|
270
271
|
"engines": {
|
|
271
|
-
"bun": ">=1.
|
|
272
|
+
"bun": ">=1.4.1"
|
|
272
273
|
},
|
|
273
274
|
"trustedDependencies": [
|
|
274
275
|
"bun",
|
package/spec/cli.md
CHANGED
|
@@ -242,8 +242,10 @@ the model with `id`, `model`, `dimensions`, `state` (`active`|`shadow`),
|
|
|
242
242
|
Terminal output prints a `Vector partitions:` block
|
|
243
243
|
unless there is exactly one healthy partition. `collections`, `totalDocuments`
|
|
244
244
|
and `totalChunks` cover configured collections only: a collection removed from
|
|
245
|
-
config
|
|
246
|
-
|
|
245
|
+
config is not reported even while its rows remain in the index until the next
|
|
246
|
+
command that syncs collections (`gno update`, `gno index`, `gno cleanup`). The
|
|
247
|
+
embedding backlog likewise counts chunks of configured collections only.
|
|
248
|
+
`gno collection remove` syncs at once, so no rows remain. `totalChunks` counts the
|
|
247
249
|
distinct chunks of active documents; chunks left by deleted documents do not
|
|
248
250
|
count. Per-collection chunk totals remain deduplicated by canonical chunk;
|
|
249
251
|
embedded counts require matching current inputs for every active owner within
|
|
@@ -393,6 +395,13 @@ is alive but did not answer its status request within 500ms). Each resident is
|
|
|
393
395
|
asked once with that 500ms budget, so `gno status` never waits on a hung
|
|
394
396
|
resident. Terminal output lists the same issues under `Background issues:`.
|
|
395
397
|
|
|
398
|
+
When an MCP client registration or a running resident uses a missing, old or
|
|
399
|
+
other Bun, JSON output adds `runtimeIssues` (absent otherwise) and terminal
|
|
400
|
+
output lists them under `Bun runtime:`. Each item has `kind`
|
|
401
|
+
(`registration` or `resident`), `severity` (`error`, `warn` or `info`),
|
|
402
|
+
`subject`, `message` and `repair`, the same findings as the doctor checks
|
|
403
|
+
`mcp-runtime` and `resident-runtime` below.
|
|
404
|
+
|
|
396
405
|
Local activation fingerprints use active-document identifiers and source/mirror
|
|
397
406
|
hashes plus schema, tokenizer, and owned FTS synchronization metadata. Passive
|
|
398
407
|
status never selects or compares stored markdown or FTS bodies. On a receipt
|
|
@@ -1090,12 +1099,12 @@ for `updateCmd`; without it the command is stopped after 10 minutes.
|
|
|
1090
1099
|
|
|
1091
1100
|
### gno collection remove
|
|
1092
1101
|
|
|
1093
|
-
Remove a collection from the index.
|
|
1102
|
+
Remove a collection from the config and the index.
|
|
1094
1103
|
|
|
1095
1104
|
**Synopsis:**
|
|
1096
1105
|
|
|
1097
1106
|
```bash
|
|
1098
|
-
gno collection remove <name>
|
|
1107
|
+
gno collection remove <name> [--lock-wait <duration>] [--no-wait]
|
|
1099
1108
|
```
|
|
1100
1109
|
|
|
1101
1110
|
**Arguments:**
|
|
@@ -1106,12 +1115,19 @@ gno collection remove <name>
|
|
|
1106
1115
|
**Behavior:**
|
|
1107
1116
|
|
|
1108
1117
|
- Removes collection from config
|
|
1109
|
-
-
|
|
1118
|
+
- Syncs the index in the same config write: the collection row and its
|
|
1119
|
+
documents are deleted at once, so status, search and the embedding backlog
|
|
1120
|
+
stop counting them without another command
|
|
1121
|
+
- Content, chunks and vectors no longer referenced by any document stay until
|
|
1122
|
+
`gno cleanup`
|
|
1123
|
+
- Waits for the index write lease (`--lock-wait`, default 120s; `--no-wait`
|
|
1124
|
+
fails at once)
|
|
1110
1125
|
|
|
1111
1126
|
**Exit Codes:**
|
|
1112
1127
|
|
|
1113
1128
|
- 0: Success
|
|
1114
|
-
- 1: Collection not found
|
|
1129
|
+
- 1: Collection not found or referenced by contexts
|
|
1130
|
+
- 2: Config save or index sync failure, or write lease busy
|
|
1115
1131
|
|
|
1116
1132
|
---
|
|
1117
1133
|
|
|
@@ -1122,7 +1138,7 @@ Rename a collection.
|
|
|
1122
1138
|
**Synopsis:**
|
|
1123
1139
|
|
|
1124
1140
|
```bash
|
|
1125
|
-
gno collection rename <old> <new>
|
|
1141
|
+
gno collection rename <old> <new> [--lock-wait <duration>] [--no-wait]
|
|
1126
1142
|
```
|
|
1127
1143
|
|
|
1128
1144
|
**Arguments:**
|
|
@@ -1131,10 +1147,22 @@ gno collection rename <old> <new>
|
|
|
1131
1147
|
| `<old>` | string | Current collection name |
|
|
1132
1148
|
| `<new>` | string | New collection name |
|
|
1133
1149
|
|
|
1150
|
+
**Behavior:**
|
|
1151
|
+
|
|
1152
|
+
- Renames the collection in config and rewrites contexts scoped to it
|
|
1153
|
+
- Syncs the index in the same config write. Documents are keyed by collection
|
|
1154
|
+
name, so the old name's documents are deleted at once and the collection is
|
|
1155
|
+
empty until the next `gno update` (or `gno index`) indexes its files under
|
|
1156
|
+
the new name; content and vectors not yet removed by `gno cleanup` are reused
|
|
1157
|
+
- Prints `Run: gno update to index it under the new name`
|
|
1158
|
+
- Waits for the index write lease (`--lock-wait`, default 120s; `--no-wait`
|
|
1159
|
+
fails at once)
|
|
1160
|
+
|
|
1134
1161
|
**Exit Codes:**
|
|
1135
1162
|
|
|
1136
1163
|
- 0: Success
|
|
1137
|
-
- 1: Old name not found
|
|
1164
|
+
- 1: Old name not found, new name already exists, or new name invalid
|
|
1165
|
+
- 2: Config save or index sync failure, or write lease busy
|
|
1138
1166
|
|
|
1139
1167
|
---
|
|
1140
1168
|
|
|
@@ -1507,7 +1535,12 @@ executable, which cannot start the worker, runs the phases in a child process
|
|
|
1507
1535
|
of itself (internal environment flag) under the same limits; the child's
|
|
1508
1536
|
resident memory counts toward `conversion.maxMemoryMb` (Linux `/proc`, `ps`
|
|
1509
1537
|
elsewhere; time only on Windows). A processor that cannot start fails the file
|
|
1510
|
-
with `ISOLATION_UNAVAILABLE`; nothing is prepared without the budget.
|
|
1538
|
+
with `ISOLATION_UNAVAILABLE`; nothing is prepared without the budget. A
|
|
1539
|
+
message to or from the processor that cannot be deserialized fails the file
|
|
1540
|
+
with `PROCESSOR_MESSAGE_FAILED` (details: `direction` `job`, `result`, or
|
|
1541
|
+
`unknown` for the child backend, whose channel Bun closes on both ends;
|
|
1542
|
+
`backend`; `phase`), replaces the processor, and writes one stderr line naming
|
|
1543
|
+
the direction, backend, `<collection>/<relPath>` and phase. The
|
|
1511
1544
|
child is SIGKILLed on process exit, SIGTERM, SIGINT (via the CLI's exit
|
|
1512
1545
|
path) and resident shutdown; on Linux it also carries a parent-death signal,
|
|
1513
1546
|
so it dies with a SIGKILLed parent, and elsewhere it exits at its next step
|
|
@@ -2932,12 +2965,13 @@ included, is refused. JSON output is
|
|
|
2932
2965
|
|
|
2933
2966
|
### gno cleanup
|
|
2934
2967
|
|
|
2935
|
-
Remove
|
|
2968
|
+
Remove documents of collections no longer in the config, then orphaned
|
|
2969
|
+
content, chunks, and vectors not referenced by active documents.
|
|
2936
2970
|
|
|
2937
2971
|
**Synopsis:**
|
|
2938
2972
|
|
|
2939
2973
|
```bash
|
|
2940
|
-
gno cleanup
|
|
2974
|
+
gno cleanup [--lock-wait <duration>] [--no-wait]
|
|
2941
2975
|
```
|
|
2942
2976
|
|
|
2943
2977
|
**Exit Codes:**
|
|
@@ -3019,6 +3053,30 @@ gno doctor [--json|--md]
|
|
|
3019
3053
|
}
|
|
3020
3054
|
```
|
|
3021
3055
|
|
|
3056
|
+
The `mcp-runtime` check reads every MCP client registration GNO can install
|
|
3057
|
+
(all targets and scopes) and reports one `error` when a registration's Bun or
|
|
3058
|
+
GNO entrypoint no longer exists or its Bun is below the supported minimum
|
|
3059
|
+
(`engines.bun`), and `info` when it resolves to a different Bun than the one
|
|
3060
|
+
running doctor. A Bun version comes from a version manager's install path when
|
|
3061
|
+
the interpreter resolves into one, else from `<interpreter> --version` under a
|
|
3062
|
+
2-second limit; a probe that fails or times out reports the version as unknown.
|
|
3063
|
+
The registered MCP command itself is never started. A registration that runs
|
|
3064
|
+
the `gno` launcher finds Bun on `PATH` and is only checked for existence. Each
|
|
3065
|
+
detail names the client, scope and file, and the repair
|
|
3066
|
+
`gno mcp install --target <target> --scope <scope> --force`.
|
|
3067
|
+
|
|
3068
|
+
The `resident-runtime` check reads the `serve` and `daemon` pid-files. A live
|
|
3069
|
+
resident's Bun comes from the pid-file's `bun_version` (written since this
|
|
3070
|
+
release) or, when absent, from `bootstrap.runtime.currentVersion` of
|
|
3071
|
+
`GET /api/status` on its recorded port (2-second limit; trusted only when the
|
|
3072
|
+
response is a GNO status payload). It is an `error` below the supported
|
|
3073
|
+
minimum, a `warn` when older than the Bun running doctor, and `info` when a
|
|
3074
|
+
resident from another GNO version does not report its Bun. The check never
|
|
3075
|
+
signals a process. Its repair restarts the resident: `gno <kind> --stop` then
|
|
3076
|
+
start it again, or, for a resident started by another GNO version (which
|
|
3077
|
+
`--stop` refuses), `kill <pid>` (`taskkill /PID <pid>` on Windows) and start it
|
|
3078
|
+
again.
|
|
3079
|
+
|
|
3022
3080
|
The `findings-pass` check reports the daemon's scheduled findings pass from
|
|
3023
3081
|
its persisted run state: `ok` when disabled or the last run succeeded, `warn`
|
|
3024
3082
|
on `skipped_lease` / `overdue` / no recorded run, `error` on `failed` or a
|
|
@@ -3093,7 +3151,7 @@ gno mcp install [--target <target>] [--scope <scope>] [--force] [--dry-run] [--e
|
|
|
3093
3151
|
| ---------------- | ------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
3094
3152
|
| `--target` | string | claude-desktop | Target client (see table below) |
|
|
3095
3153
|
| `--scope` | string | target default | Scope: `user` or `project`; LibreChat defaults to project |
|
|
3096
|
-
| `--force` | boolean | false |
|
|
3154
|
+
| `--force` | boolean | false | Repair an existing gno entry: rewrite its Bun and GNO paths, keep its other arguments, environment and keys, and apply only the options passed explicitly |
|
|
3097
3155
|
| `--dry-run` | boolean | false | Show what would be done without changes |
|
|
3098
3156
|
| `--enable-write` | boolean | false | Start the registered server with write tools enabled |
|
|
3099
3157
|
| `--tool-profile` | string | full | Advertised tool set written into the registration: `core` (7 read tools, plus capture and remember with `--enable-write`) or `full`; omitted writes no flag |
|
|
@@ -3132,6 +3190,25 @@ gno mcp install [--target <target>] [--scope <scope>] [--force] [--dry-run] [--e
|
|
|
3132
3190
|
| lmstudio | user | `~/.lmstudio/mcp.json` | `~/.lmstudio/mcp.json` | `~/.lmstudio/mcp.json` |
|
|
3133
3191
|
| librechat | project | `./librechat.yaml` | `./librechat.yaml` | `./librechat.yaml` |
|
|
3134
3192
|
|
|
3193
|
+
**Launch paths and repair:** the command is the running Bun, the first
|
|
3194
|
+
argument after `run` the running package's `src/index.ts`. When either sits in
|
|
3195
|
+
a version manager's versioned install directory (mise, asdf or proto
|
|
3196
|
+
`installs/bun/<version>/` or `tools/bun/<version>/`, Homebrew
|
|
3197
|
+
`Cellar/bun/<version>/`), the manager's version-independent link
|
|
3198
|
+
(`installs/bun/latest/...`, `opt/bun/...`) is written instead, but only if it
|
|
3199
|
+
resolves to the same file; otherwise the versioned path is kept, the text
|
|
3200
|
+
output adds a note, and `--json` adds `installed.pinnedPaths`. Shims that pick
|
|
3201
|
+
a version from the shell environment are never written. A standalone compiled
|
|
3202
|
+
executable is written as is. With `--force` over an existing entry that
|
|
3203
|
+
launches GNO (`run <entrypoint> ... mcp ...`, or a `gno` executable), only the
|
|
3204
|
+
launch prefix is rewritten; `--index`, `--config`, `--tool-profile` and
|
|
3205
|
+
`--enable-write` change only when passed in this invocation, existing
|
|
3206
|
+
environment values win over the installer's data and cache directories, and
|
|
3207
|
+
keys GNO does not write are kept in every format, Codex TOML included;
|
|
3208
|
+
`installed.repaired` is `true`. A Codex key that the TOML writer cannot express
|
|
3209
|
+
stops the command before anything is written. An entry that does not launch GNO
|
|
3210
|
+
is replaced as before. Without `--force` an existing entry is refused.
|
|
3211
|
+
|
|
3135
3212
|
**Config Formats:**
|
|
3136
3213
|
|
|
3137
3214
|
- JSONC-compatible (`mcpServers` key): Claude Desktop, Claude Code, Cursor, Windsurf, LM Studio
|
|
@@ -3352,6 +3429,19 @@ MCP Server Status
|
|
|
3352
3429
|
}
|
|
3353
3430
|
```
|
|
3354
3431
|
|
|
3432
|
+
An entry is reported (and offered to the connector verifier) only when its
|
|
3433
|
+
keys are the launch keys (`command`, `args`, `env`; OpenCode `type: "local"`,
|
|
3434
|
+
`command`, `environment`) plus inert client settings: `type: "stdio"`, numeric
|
|
3435
|
+
`timeout` / `startup_timeout_sec` / `tool_timeout_sec`, a string
|
|
3436
|
+
`description`, string-array `autoApprove` / `alwaysAllow`, and boolean
|
|
3437
|
+
`enabled` / `disabled` (OpenCode: numeric `timeout` and `enabled`).
|
|
3438
|
+
`serverEntry` carries only the launch keys. An entry with `enabled: false` or
|
|
3439
|
+
`disabled: true` is `configured: false` without an error. Any other key or
|
|
3440
|
+
value, including `cwd`, another transport `type`, `url`, `headers`, and
|
|
3441
|
+
environment variables other than `GNO_DATA_DIR` / `GNO_CACHE_DIR`, makes the
|
|
3442
|
+
entry `configured: false` with `error: "Malformed MCP server entry"`, and the
|
|
3443
|
+
connector verifier reports it as `connector_unsupported_config`.
|
|
3444
|
+
|
|
3355
3445
|
**Exit Codes:**
|
|
3356
3446
|
|
|
3357
3447
|
- 0: Success
|
package/spec/mcp.md
CHANGED
|
@@ -2830,7 +2830,7 @@ Full index: sync files + generate embeddings (write-enabled). Runs as background
|
|
|
2830
2830
|
|
|
2831
2831
|
### gno_remove_collection
|
|
2832
2832
|
|
|
2833
|
-
Remove a collection from config (write-enabled).
|
|
2833
|
+
Remove a collection from config and delete its documents from the index (write-enabled). Content, chunks and vectors stay until `gno cleanup`; `indexedDataRetained` is always `true` for that reason.
|
|
2834
2834
|
|
|
2835
2835
|
**Input Schema:**
|
|
2836
2836
|
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
},
|
|
29
29
|
"indexedDataRetained": {
|
|
30
30
|
"type": "boolean",
|
|
31
|
-
"description": "
|
|
31
|
+
"description": "Always true: the collection's documents are deleted, but content, chunks and vectors stay in the index until gno cleanup",
|
|
32
32
|
"const": true
|
|
33
33
|
},
|
|
34
34
|
"note": {
|
|
35
35
|
"type": "string",
|
|
36
|
-
"description": "
|
|
36
|
+
"description": "What was deleted and what stays until gno cleanup"
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimum supported Bun (fn-213).
|
|
3
|
+
*
|
|
4
|
+
* `engines.bun` in package.json is the single source of truth. Bun 1.4.0
|
|
5
|
+
* and 1.4.1 fixed structured-clone bugs in the path worker messages take,
|
|
6
|
+
* which can crash a long-running process; older runtimes still start, but
|
|
7
|
+
* `serve`, `daemon` and `mcp` say so once on stderr.
|
|
8
|
+
*
|
|
9
|
+
* @module src/app/bun-runtime
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import pkg from "../../package.json";
|
|
13
|
+
|
|
14
|
+
/** Supported Bun range, e.g. `>=1.4.1`. */
|
|
15
|
+
export const BUN_ENGINE_RANGE: string = pkg.engines.bun;
|
|
16
|
+
|
|
17
|
+
/** The minimum version in that range, e.g. `1.4.1`. */
|
|
18
|
+
export const BUN_FLOOR: string = BUN_ENGINE_RANGE.replace(/^>=\s*/, "");
|
|
19
|
+
|
|
20
|
+
/** Whether a Bun version is within the supported range. */
|
|
21
|
+
export function bunMeetsFloor(version: string = Bun.version): boolean {
|
|
22
|
+
return Bun.semver.satisfies(version, BUN_ENGINE_RANGE);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** One-line warning for a command started on an unsupported Bun, else null. */
|
|
26
|
+
export function bunFloorWarning(
|
|
27
|
+
command: string,
|
|
28
|
+
version: string = Bun.version
|
|
29
|
+
): string | null {
|
|
30
|
+
if (bunMeetsFloor(version)) return null;
|
|
31
|
+
return `gno ${command}: running on Bun ${version}, older than the supported minimum ${BUN_FLOOR}; older runtimes can crash long-running processes. Upgrade Bun and restart.`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Print the warning for `command` when the running Bun is unsupported. */
|
|
35
|
+
export function warnIfBunBelowFloor(
|
|
36
|
+
command: string,
|
|
37
|
+
write: (line: string) => void = console.warn
|
|
38
|
+
): void {
|
|
39
|
+
const warning = bunFloorWarning(command);
|
|
40
|
+
if (warning) write(warning);
|
|
41
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gno cleanup command implementation.
|
|
3
|
-
* Remove
|
|
3
|
+
* Remove documents of collections no longer configured, then orphaned
|
|
4
|
+
* content, chunks and vectors not referenced by active documents.
|
|
4
5
|
*
|
|
5
6
|
* @module src/cli/commands/cleanup
|
|
6
7
|
*/
|
|
@@ -61,6 +62,13 @@ export async function cleanup(
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
try {
|
|
65
|
+
// Drop collections no longer in the config first (their documents follow
|
|
66
|
+
// by cascade), so their content, chunks and vectors count as orphans.
|
|
67
|
+
const syncResult = await store.syncCollections(config.collections);
|
|
68
|
+
if (!syncResult.ok) {
|
|
69
|
+
return { success: false, error: syncResult.error.message };
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
const cleanupResult = await store.cleanupOrphans();
|
|
65
73
|
if (!cleanupResult.ok) {
|
|
66
74
|
return { success: false, error: cleanupResult.error.message };
|
|
@@ -3,43 +3,62 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { removeCollection } from "../../../collection";
|
|
6
|
-
import {
|
|
6
|
+
import { applyConfigChange } from "../../../core/config-mutation";
|
|
7
7
|
import { CliError } from "../../errors";
|
|
8
|
+
import { initStore } from "../shared";
|
|
8
9
|
|
|
9
10
|
export async function collectionRemove(
|
|
10
11
|
name: string,
|
|
11
|
-
options: { configPath?: string } = {}
|
|
12
|
+
options: { configPath?: string; indexName?: string } = {}
|
|
12
13
|
): Promise<void> {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
// Open the index so the removal reaches the store in the same locked
|
|
15
|
+
// boundary: syncing collections deletes the collection row, and its
|
|
16
|
+
// documents follow by cascade. A config-only edit left them active (and
|
|
17
|
+
// counted in the embedding backlog) until some later command synced.
|
|
18
|
+
const initialized = await initStore({
|
|
19
|
+
configPath: options.configPath,
|
|
20
|
+
indexName: options.indexName,
|
|
21
|
+
syncConfig: false,
|
|
22
|
+
allowEmptyCollections: true,
|
|
23
|
+
});
|
|
24
|
+
if (!initialized.ok) {
|
|
25
|
+
throw new CliError("RUNTIME", initialized.error);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const mutation = await applyConfigChange(
|
|
30
|
+
{ store: initialized.store, configPath: initialized.actualConfigPath },
|
|
31
|
+
(config) => {
|
|
32
|
+
const result = removeCollection(config, { name });
|
|
33
|
+
return result.ok
|
|
34
|
+
? {
|
|
35
|
+
ok: true as const,
|
|
36
|
+
config: result.config,
|
|
37
|
+
value: result.collection,
|
|
38
|
+
}
|
|
39
|
+
: {
|
|
40
|
+
ok: false as const,
|
|
41
|
+
error: result.message,
|
|
42
|
+
code: result.code,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (!mutation.ok) {
|
|
48
|
+
// Map collection error codes to CLI error codes
|
|
49
|
+
const cliCode =
|
|
50
|
+
mutation.code === "VALIDATION" ||
|
|
51
|
+
mutation.code === "NOT_FOUND" ||
|
|
52
|
+
mutation.code === "HAS_REFERENCES"
|
|
53
|
+
? "VALIDATION"
|
|
54
|
+
: "RUNTIME";
|
|
55
|
+
throw new CliError(cliCode, mutation.error);
|
|
28
56
|
}
|
|
29
|
-
);
|
|
30
57
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
mutation.code === "HAS_REFERENCES"
|
|
37
|
-
? "VALIDATION"
|
|
38
|
-
: "RUNTIME";
|
|
39
|
-
throw new CliError(cliCode, mutation.error);
|
|
58
|
+
process.stdout.write(
|
|
59
|
+
`Collection "${mutation.value?.name}" removed successfully\n`
|
|
60
|
+
);
|
|
61
|
+
} finally {
|
|
62
|
+
await initialized.store.close();
|
|
40
63
|
}
|
|
41
|
-
|
|
42
|
-
process.stdout.write(
|
|
43
|
-
`Collection "${mutation.value?.name}" removed successfully\n`
|
|
44
|
-
);
|
|
45
64
|
}
|
|
@@ -3,19 +3,51 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { CollectionSchema, getCollectionFromScope } from "../../../config";
|
|
6
|
-
import {
|
|
6
|
+
import { applyConfigChange } from "../../../core/config-mutation";
|
|
7
7
|
import { CliError } from "../../errors";
|
|
8
|
+
import { initStore, type InitStoreResult } from "../shared";
|
|
8
9
|
|
|
9
10
|
export async function collectionRename(
|
|
10
11
|
oldName: string,
|
|
11
12
|
newName: string,
|
|
12
|
-
options: { configPath?: string } = {}
|
|
13
|
+
options: { configPath?: string; indexName?: string } = {}
|
|
13
14
|
): Promise<void> {
|
|
14
15
|
const oldCollectionName = oldName.toLowerCase();
|
|
15
16
|
const newCollectionName = newName.toLowerCase();
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
// Documents are keyed by collection name (URIs, FTS paths, links), so the
|
|
19
|
+
// index cannot rename them in place. Sync in the same locked boundary: the
|
|
20
|
+
// old name's documents go now instead of at some later sync, and the next
|
|
21
|
+
// update indexes the files under the new name.
|
|
22
|
+
const initialized = await initStore({
|
|
23
|
+
configPath: options.configPath,
|
|
24
|
+
indexName: options.indexName,
|
|
25
|
+
syncConfig: false,
|
|
26
|
+
allowEmptyCollections: true,
|
|
27
|
+
});
|
|
28
|
+
if (!initialized.ok) {
|
|
29
|
+
throw new CliError("RUNTIME", initialized.error);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
await renameAndSync(initialized, oldCollectionName, newCollectionName);
|
|
34
|
+
} finally {
|
|
35
|
+
await initialized.store.close();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
process.stdout.write(
|
|
39
|
+
`Collection "${oldCollectionName}" renamed to "${newCollectionName}"\n` +
|
|
40
|
+
"Run: gno update to index it under the new name\n"
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function renameAndSync(
|
|
45
|
+
initialized: Extract<InitStoreResult, { ok: true }>,
|
|
46
|
+
oldCollectionName: string,
|
|
47
|
+
newCollectionName: string
|
|
48
|
+
): Promise<void> {
|
|
49
|
+
const mutation = await applyConfigChange(
|
|
50
|
+
{ store: initialized.store, configPath: initialized.actualConfigPath },
|
|
19
51
|
(config) => {
|
|
20
52
|
const collection = config.collections.find(
|
|
21
53
|
(item) => item.name === oldCollectionName
|
|
@@ -70,8 +102,4 @@ export async function collectionRename(
|
|
|
70
102
|
mutation.error
|
|
71
103
|
);
|
|
72
104
|
}
|
|
73
|
-
|
|
74
|
-
process.stdout.write(
|
|
75
|
-
`Collection "${oldCollectionName}" renamed to "${newCollectionName}"\n`
|
|
76
|
-
);
|
|
77
105
|
}
|
|
@@ -5,6 +5,7 @@ import type { FindingsPassResult } from "../../serve/findings-pass";
|
|
|
5
5
|
import type { ResidentRuntime } from "../../serve/resident-runtime";
|
|
6
6
|
import type { SessionAutomationRunResult } from "../../sessions/types";
|
|
7
7
|
|
|
8
|
+
import { warnIfBunBelowFloor } from "../../app/bun-runtime";
|
|
8
9
|
import {
|
|
9
10
|
enforceCollectionEgress,
|
|
10
11
|
EGRESS_DENIED_MESSAGE,
|
|
@@ -203,6 +204,8 @@ export async function daemon(
|
|
|
203
204
|
},
|
|
204
205
|
};
|
|
205
206
|
|
|
207
|
+
warnIfBunBelowFloor("daemon", logger.error);
|
|
208
|
+
|
|
206
209
|
const runtimeResult: BackgroundRuntimeResult = await (
|
|
207
210
|
deps.startBackgroundRuntime ?? startBackgroundRuntime
|
|
208
211
|
)({
|
|
@@ -45,6 +45,12 @@ import {
|
|
|
45
45
|
import { getStoredEmbeddingFingerprint } from "../../store/vector/freshness";
|
|
46
46
|
import { currentOwnerCount } from "../../store/vector/runtime-compat";
|
|
47
47
|
import { storedVectorPartition } from "../../store/vector/status";
|
|
48
|
+
import {
|
|
49
|
+
checkRegistrationRuntimes,
|
|
50
|
+
checkResidentRuntimes,
|
|
51
|
+
formatRuntimeIssue,
|
|
52
|
+
type RuntimeIssue,
|
|
53
|
+
} from "../runtime-health";
|
|
48
54
|
import {
|
|
49
55
|
buildDoctorActivation,
|
|
50
56
|
checkConnectorActivation,
|
|
@@ -622,6 +628,58 @@ async function checkSqliteExtensions(): Promise<DoctorCheck[]> {
|
|
|
622
628
|
* Report the daemon's scheduled findings pass from its persisted state so a
|
|
623
629
|
* misconfigured, starved, or failing scheduler is visible without the daemon.
|
|
624
630
|
*/
|
|
631
|
+
const SEVERITY_RANK: Record<RuntimeIssue["severity"], number> = {
|
|
632
|
+
info: 0,
|
|
633
|
+
warn: 1,
|
|
634
|
+
error: 2,
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
function runtimeCheck(
|
|
638
|
+
name: string,
|
|
639
|
+
issues: RuntimeIssue[],
|
|
640
|
+
okMessage: string
|
|
641
|
+
): DoctorCheck {
|
|
642
|
+
if (issues.length === 0) {
|
|
643
|
+
return { name, status: "ok", message: okMessage };
|
|
644
|
+
}
|
|
645
|
+
const worst = issues.reduce((current, issue) =>
|
|
646
|
+
SEVERITY_RANK[issue.severity] > SEVERITY_RANK[current.severity]
|
|
647
|
+
? issue
|
|
648
|
+
: current
|
|
649
|
+
);
|
|
650
|
+
return {
|
|
651
|
+
name,
|
|
652
|
+
status: worst.severity,
|
|
653
|
+
message:
|
|
654
|
+
issues.length === 1
|
|
655
|
+
? `${worst.subject}: ${worst.message}`
|
|
656
|
+
: `${issues.length} need attention; first: ${worst.subject}: ${worst.message}`,
|
|
657
|
+
details: issues.map(formatRuntimeIssue),
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/** Bun used by MCP registrations and by running residents. */
|
|
662
|
+
export async function checkRuntimes(
|
|
663
|
+
overrides: { cwd?: string; homeDir?: string } = {}
|
|
664
|
+
): Promise<DoctorCheck[]> {
|
|
665
|
+
const [registrations, residents] = await Promise.all([
|
|
666
|
+
checkRegistrationRuntimes(overrides),
|
|
667
|
+
checkResidentRuntimes(),
|
|
668
|
+
]);
|
|
669
|
+
return [
|
|
670
|
+
runtimeCheck(
|
|
671
|
+
"mcp-runtime",
|
|
672
|
+
registrations,
|
|
673
|
+
"MCP registrations launch an existing, supported Bun"
|
|
674
|
+
),
|
|
675
|
+
runtimeCheck(
|
|
676
|
+
"resident-runtime",
|
|
677
|
+
residents,
|
|
678
|
+
"No running resident is on an older Bun"
|
|
679
|
+
),
|
|
680
|
+
];
|
|
681
|
+
}
|
|
682
|
+
|
|
625
683
|
export async function checkFindingsPass(
|
|
626
684
|
config: Config,
|
|
627
685
|
indexName?: string
|
|
@@ -727,6 +785,9 @@ export async function doctor(
|
|
|
727
785
|
// Scheduled findings pass (daemon-only, opt-in)
|
|
728
786
|
checks.push(await checkFindingsPass(config, options.indexName));
|
|
729
787
|
|
|
788
|
+
// Which Bun client registrations and running residents use (fn-213)
|
|
789
|
+
checks.push(...(await checkRuntimes()));
|
|
790
|
+
|
|
730
791
|
const activation = await buildDoctorActivation(config, options);
|
|
731
792
|
checks.push(checkRetrievalActivation(activation));
|
|
732
793
|
const connectorActivation = checkConnectorActivation(activation);
|