mindsmith 0.1.0 → 0.2.0
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 +174 -107
- package/bin/mindsmith +71 -4
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -1,153 +1,220 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
# mindsmith
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/mindsmith)
|
|
4
|
+
[](https://www.npmjs.com/package/mindsmith)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
**Your small model fits your VRAM. Quantization stole its judgment on the way down.
|
|
9
|
+
mindsmith forges it back.** A certified method vocabulary steers it, an external critical
|
|
10
|
+
mind checks it, and covered questions are answered from *your* verified stock at **zero
|
|
11
|
+
frontier calls** — all on your box, nothing leaving by default. Point any OpenAI client at
|
|
12
|
+
it and go. The `-smith` is literal: you forge a mind for the model you can actually run.
|
|
13
|
+
|
|
14
|
+
> **Pre-launch. Nothing here is field-adopted yet — rung 6/6 is empty on every bar below.**
|
|
15
|
+
> We publish maturity per feature, and **a refuted claim comes off the page the day it falls**
|
|
16
|
+
> (several are still listed on purpose — knowing where the floor is *is* the product). The
|
|
17
|
+
> radical-honesty page: [honesty](https://9pings.github.io/mindsmith/honesty.html).
|
|
18
|
+
|
|
19
|
+
Built on the [skynet-graph](https://github.com/9pings/skynet-graph) reasoning engine — the
|
|
20
|
+
substrate + the combos this appliance puts to work.
|
|
21
|
+
|
|
22
|
+
## What it does
|
|
23
|
+
|
|
24
|
+
- **Forge — repair the low-quant.** A menu of *certified* method shapes steers the model's
|
|
25
|
+
output; a covered query is served from your verified local stock at **0 frontier calls**
|
|
26
|
+
and can't hallucinate by construction. Measured on the *same* model at two quant levels:
|
|
27
|
+
SQL covered queries **8→63 %** (N=201; high-quant reference 46→92 %) · finance-table
|
|
28
|
+
traffic **7→62 %** (N=120; 20→78 %).
|
|
29
|
+
- **Check — an external mind, not a self-pep-talk.** `critique` weighs a question over a
|
|
30
|
+
witness-gated pool and returns an honest, certification-aware verdict (or an honest
|
|
31
|
+
UNDECIDED). `propose` / `hint` are gated think-mode lanes that hand back a *tested* verdict
|
|
32
|
+
or a typed refusal — never a confident guess. All as MCP tools.
|
|
33
|
+
- **Own it — sealed by default.** OpenAI-compatible endpoint, no accounts, no catalog, no
|
|
34
|
+
phone-home, **no-egress by default (enforced fail-closed on real sockets, with a negative
|
|
35
|
+
control that proves the guard has teeth)**. Your stock lives in a local **room** you own:
|
|
36
|
+
freeze it, checksum it, hand it to a colleague, import theirs — a malformed bundle is
|
|
37
|
+
refused at the gate, never written.
|
|
27
38
|
|
|
28
39
|
## 60-second quickstart
|
|
29
40
|
|
|
30
41
|
```bash
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
#
|
|
42
|
+
# Install (on npm):
|
|
43
|
+
npm i -g mindsmith # per-project: npm i mindsmith · one-shot: npx mindsmith
|
|
44
|
+
# Running a local .gguf (embedded or single-model) needs the local runtime once — prebuilt, no compile:
|
|
45
|
+
npm install node-llama-cpp
|
|
46
|
+
# On WSL, export this or the gguf silently falls back to CPU:
|
|
47
|
+
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:/usr/lib/x86_64-linux-gnu
|
|
48
|
+
|
|
49
|
+
# 1 — serve. Escalation is ONE of: an embedded gguf, an OpenAI endpoint, or an N-tier routing config.
|
|
36
50
|
FRONTIER_MODEL=/path/model.gguf mindsmith serve --room ./sgc
|
|
37
|
-
# → mindsmith → http://127.0.0.1:4747/v1 (OpenAI-compatible)
|
|
51
|
+
# → mindsmith → http://127.0.0.1:4747/v1 (OpenAI-compatible, binds 127.0.0.1)
|
|
52
|
+
# (no local runtime? point at an endpoint instead: LLM_BASE=<url> mindsmith serve)
|
|
38
53
|
|
|
39
54
|
# 2 — point ANY OpenAI client at it (official SDKs, LangChain, Open WebUI, curl):
|
|
40
|
-
#
|
|
55
|
+
# baseURL = http://127.0.0.1:4747/v1 apiKey = anything
|
|
41
56
|
curl -si http://127.0.0.1:4747/v1/chat/completions \
|
|
42
57
|
-H 'content-type: application/json' \
|
|
43
58
|
-d '{"messages":[{"role":"user","content":"your question"}]}'
|
|
44
|
-
# every completion carries provenance headers:
|
|
59
|
+
# every completion carries provenance headers, so you always know what you got:
|
|
45
60
|
# x-sg-served-from: local|frontier · x-sg-arm · x-sg-cost · x-sg-coverage · x-sg-saved · x-sg-sgc-version
|
|
46
61
|
|
|
47
|
-
# 3 — your stock rooms (local .sgc mini-repos, gate-checked):
|
|
62
|
+
# 3 — your stock rooms (local .sgc mini-repos, gate-checked on every load):
|
|
48
63
|
mindsmith rooms list # inventory: name@version, classes, sha256, ❄ frozen
|
|
49
|
-
mindsmith rooms import ./fin-tables-stock.sgc #
|
|
64
|
+
mindsmith rooms import ./fin-tables-stock.sgc # a bad bundle never lands
|
|
50
65
|
mindsmith rooms freeze fin-tables-stock # writes the auditable sha256 dossier
|
|
51
66
|
mindsmith rooms export fin-tables-stock ./out # bundle + dossier, ready to share
|
|
52
67
|
|
|
53
|
-
# 4 — or
|
|
68
|
+
# 4 — or wire it into an agent host as MCP tools (Claude Code, any MCP client):
|
|
54
69
|
claude mcp add mindsmith -- mindsmith mcp --routing routing.json
|
|
55
|
-
# tools: ask · drift · metrics · lattice_load · hint · propose
|
|
70
|
+
# tools: ask · drift · metrics · lattice_load · critique (+ hint · propose once a methods stock is loaded)
|
|
56
71
|
```
|
|
57
72
|
|
|
58
|
-
|
|
59
|
-
|
|
73
|
+
The demo and the test suite live in the [repo](https://github.com/9pings/mindsmith), not the
|
|
74
|
+
npm tarball — `git clone` for those; npm is for *running* the appliance and *embedding* the
|
|
75
|
+
engine. `GET /healthz` is the ops readout (no key, no query content): policy, configured vs
|
|
76
|
+
reachable tiers, loaded `.sgc` versions, stock size.
|
|
60
77
|
|
|
61
|
-
##
|
|
78
|
+
## One model. One load. The whole appliance.
|
|
79
|
+
|
|
80
|
+
Most VRAM-constrained boxes have room for exactly **one** model. Fine — that's all mindsmith
|
|
81
|
+
needs:
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
83
|
+
```bash
|
|
84
|
+
mindsmith serve --model /path/model.gguf # ONE gguf, ONE VRAM load
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
That single load is doing **both** jobs at once. Your users get a full local LLM server whose
|
|
88
|
+
answers run **with** native reasoning (think). The graph's structured work — coverage,
|
|
89
|
+
`critique`, `propose` — runs on the **same** weights **without** think. How? The thinking
|
|
90
|
+
budget is **per-call, not per-load**: one set of weights in VRAM, two behaviours out of it. A
|
|
91
|
+
box that can hold a single model still gets the entire appliance — server *and* value-add — for
|
|
92
|
+
one model's worth of memory.
|
|
93
|
+
|
|
94
|
+
Tune the load: `--ctx <N>` · `--gpu auto|cuda|metal|vulkan|false` · `--gpu-layers <N>` ·
|
|
95
|
+
`--think <tokens>` (the answer-side reasoning budget, default 1024). Need a custom llama.cpp
|
|
96
|
+
build? `--no-prebuilt` builds from source, `--llama-build auto|forceRebuild|never` controls it,
|
|
97
|
+
and `LLAMA_CMAKE=<json>` passes cmake options through.
|
|
98
|
+
|
|
99
|
+
## Features × maturity
|
|
66
100
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
|
73
|
-
|
|
101
|
+
Maturity uses a fixed 6-rung scale: **1** coherent idea · **2** design with pre-registered
|
|
102
|
+
kill-gates · **3** mechanics proven · **4** measured at scale · **5** product-integrated ·
|
|
103
|
+
**6** field-adopted (external replications). **Nothing is at 6 — this is pre-launch.** Scale
|
|
104
|
+
detail: [honesty](https://9pings.github.io/mindsmith/honesty.html).
|
|
105
|
+
|
|
106
|
+
| Feature | Maturity | Measured |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| **F1 — Low-quant repair** — certified stock steers the model; covered → 0 frontier calls | `█████░` 5/6 product-integrated | SQL **8→63 %** (N=201) · finance tables **7→62 %** (N=120) · forge **0 false admissions** (3 datasets × 2 forge models) |
|
|
109
|
+
| **F4 — External think mode** — `propose` → gated verdict + blame + gate-tested options; `hint` menu | `█████░` 5/6 product-integrated | one dialogue round **17/24 → 24/24** at **zero false admissions**; a forced write lands UNTRUSTED, never admitted |
|
|
110
|
+
| **F5 — External critical mind** — `critique`: witness gate, anchored generation, honest verdict | `█████░` 5/6 surface (campaign numbers at 4/6) | coverage **77 % vs 58 %** (48 args) · certified perimeter **12/24 → 24/24** · **0 fabrication** in negative controls (8/8 injected theses retracted) |
|
|
111
|
+
| **F6 — Local `.sgc` rooms** — list/import/export/freeze, sha256 dossiers, engine-gated loads | `█████░` 5/6 product-integrated | gate-checked import; loads never bypass the engine gates |
|
|
112
|
+
| **F2 — Piece-by-piece zoom** — typed DAG on big tasks | `████░░` 4/6 measured — **library-only in the engine today; NOT surfaced here (the known gap)** | math word problems **×3.25** [2.4–4.8] · financial-table QA **×2.54** [1.96–3.5], 560 tasks |
|
|
113
|
+
|
|
114
|
+
## The illusion this kills
|
|
115
|
+
|
|
116
|
+
Ask a low-quant model to weigh two sides of a real question and it picks a winner with total
|
|
117
|
+
confidence — and is right about as often as a coin. In a head-to-head (24 composed perimeters,
|
|
118
|
+
gold hidden, every arm re-run bit-identical), the naive single call and the *same model with a
|
|
119
|
+
1024-token native think budget* both score **13/24 ≈ chance**, each throwing 11 confident wrong
|
|
120
|
+
verdicts and refusing zero times. And it doesn't know: measured self-believed coverage runs
|
|
121
|
+
**~106 %** against a real gold of **64–77 %** — it's sure it covered everything when it didn't.
|
|
122
|
+
|
|
123
|
+
The external critical mind renders **0 wrong verdicts across all 48 debates**. Two things buy
|
|
124
|
+
that. First, it decides mechanically **only at a measured margin** — and below it returns counts
|
|
125
|
+
+ coverage + an honest **UNDECIDED** instead of flipping a coin. Second, a **certified
|
|
126
|
+
perimeter closes the illusion**: declaring what you're judging against takes the decision from
|
|
127
|
+
**12/24 to 24/24**. mindsmith declines; it doesn't guess. That's the whole point.
|
|
74
128
|
|
|
75
129
|
## Why not just…?
|
|
76
130
|
|
|
77
|
-
- **…run a bigger model?** If it fits your VRAM, do.
|
|
78
|
-
certified-stock steering recovers most of what quantization broke (SQL 8→63 %, finance
|
|
79
|
-
at 0 frontier calls on the covered slice.
|
|
80
|
-
- **…use the model's think mode
|
|
81
|
-
3-form refutation
|
|
82
|
-
The `propose` gate and `critique` tool are that
|
|
83
|
-
un-arguable-with (a forced write lands
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
131
|
+
- **…run a bigger model?** If it fits your VRAM, do. mindsmith is for the model you *can*
|
|
132
|
+
run: certified-stock steering recovers most of what quantization broke (SQL 8→63 %, finance
|
|
133
|
+
7→62 %), at 0 frontier calls on the covered slice.
|
|
134
|
+
- **…use the model's think mode, or a self-critique prompt?** The 2024–25 literature and our
|
|
135
|
+
own 3-form refutation agree: self-critique underperforms *external* feedback with localized
|
|
136
|
+
blame. A low-quant can't audit itself. The `propose` gate and `critique` tool are that
|
|
137
|
+
external feedback — structural, auditable, and un-arguable-with (a forced write lands
|
|
138
|
+
UNTRUSTED, never admitted). A prompt can always be talked out of it; a gate can't.
|
|
139
|
+
- **…RAG or a prompt library?** Retrieval trusts whatever got indexed. A room only admits
|
|
140
|
+
what passes the gate (**0 false admissions** measured at the forge), and every completion
|
|
141
|
+
tells you which slice you can trust (`x-sg-served-from`, `x-sg-coverage`).
|
|
142
|
+
- **…an agent framework's memory?** None we checked reopens a task whose premise drifted. The
|
|
143
|
+
engine's typed task state retracts and reopens *with the reason*, at 0 model calls (surfaced
|
|
144
|
+
on the engine side via MCP `state_recall` / `plan_sync`).
|
|
90
145
|
|
|
91
146
|
## What actually runs
|
|
92
147
|
|
|
93
|
-
- **`serve`** — `POST /v1/chat/completions`, `GET /v1/models`, `GET /healthz`. Default port
|
|
94
|
-
binds 127.0.0.1 on purpose.
|
|
95
|
-
a miss escalates (you always get an answer); the local side never fabricates
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
any OpenAI-compatible endpoint)
|
|
99
|
-
tagged with an egress class (`none` / `mid` / `frontier`),
|
|
100
|
-
`no-egress` (default for routing configs) · `allow-mid` · `allow-all`. A query is **never**
|
|
101
|
-
sent to a forbidden tier: if the policy leaves nothing reachable
|
|
102
|
-
refusal. The no-egress guarantee is enforced fail-closed on real sockets
|
|
103
|
-
negative control proving the guard
|
|
148
|
+
- **`serve`** — `POST /v1/chat/completions`, `GET /v1/models`, `GET /healthz`. Default port
|
|
149
|
+
4747, binds 127.0.0.1 on purpose. Covered query → served from verified local stock at 0
|
|
150
|
+
frontier calls; a miss escalates (you always get an answer); the local side never fabricates.
|
|
151
|
+
- **Escalation — pick one.** A **single model** (`--model <path.gguf>`, the shared-load mode
|
|
152
|
+
above) · a **single frontier** (`FRONTIER_MODEL=<path.gguf>` embedded, or `LLM_BASE=<url>`
|
|
153
|
+
any OpenAI-compatible endpoint) · or **N-tier routing** (`--routing config.json`): ordered
|
|
154
|
+
tiers, each tagged with an egress class (`none` / `mid` / `frontier`), under a policy ceiling
|
|
155
|
+
— `no-egress` (default for routing configs) · `allow-mid` · `allow-all`. A query is **never**
|
|
156
|
+
silently sent to a forbidden tier: if the policy leaves nothing reachable you get a typed
|
|
157
|
+
`NO_REACHABLE_TIER` refusal. The no-egress guarantee is enforced fail-closed on real sockets
|
|
158
|
+
in the test suite, with a negative control proving the guard bites.
|
|
104
159
|
- **`mcp`** — the same verified stock + escalation over stdio (no HTTP socket). Tools:
|
|
105
160
|
`ask` (local-first, `{answer, source, cached, cost}`) · `drift` (invalidate a stale entry) ·
|
|
106
|
-
`metrics` (economy readout) · `lattice_load` (learn
|
|
107
|
-
`hint` (SOFT lane: advisory certified-shape menu, no guarantee attached) ·
|
|
108
|
-
gate never yields; `force=true` records untrusted provenance,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
bundle
|
|
161
|
+
`metrics` (economy readout) · `lattice_load` (learn *through* the gate — the only registry
|
|
162
|
+
write path) · `hint` (SOFT lane: advisory certified-shape menu, no guarantee attached) ·
|
|
163
|
+
`propose` (HARD lane: the gate never yields; `force=true` records untrusted provenance,
|
|
164
|
+
never admits) · `critique` (below).
|
|
165
|
+
- **`rooms`** — `list | import <file> | export <name> <dest> | freeze <name>`. Import
|
|
166
|
+
dry-loads the bundle through the same gates the appliance uses; freeze writes the sha256
|
|
167
|
+
dossier that makes the bundle a fixed, auditable reference.
|
|
112
168
|
|
|
113
169
|
## The `critique` iteration contract
|
|
114
170
|
|
|
115
|
-
`critique` runs the external critical mind on a question:
|
|
116
|
-
witness gate over a statement pool, anchored generation of missing theses
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
fake weighing.
|
|
171
|
+
`critique` runs the external critical mind on a question: viewpoints established through a
|
|
172
|
+
**witness gate** over a statement pool, anchored generation of missing theses (drafted **only**
|
|
173
|
+
from pool witnesses — 0 fabrication across negative controls), a typed ledger, and a
|
|
174
|
+
certification-aware verdict. The contract: **OPEN ledger points and an UNDECIDED verdict are a
|
|
175
|
+
typed data request, not a dead end.** The tool can't reach the web — the host (you, or your
|
|
176
|
+
agent) gathers real statements that bear on the OPEN points and calls `critique` again with
|
|
177
|
+
`statements: [...]` (`"PRO: …"` / `"CON: …"` lines). The frame upgrades to MATERIAL and the
|
|
178
|
+
margin can move honestly. Below the measured decidability bound the deliverable is counts +
|
|
179
|
+
coverage + an honest UNDECIDED — never a fake weighing.
|
|
124
180
|
|
|
125
181
|
## Honest limits (what is NOT claimed)
|
|
126
182
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- **The
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
183
|
+
This is the part every hype-y AI repo leaves out. We tested these, here's exactly what broke,
|
|
184
|
+
and it stays on the page.
|
|
185
|
+
|
|
186
|
+
- **The guarantee is at stock admission, not at execution.** Runtime steering *orients*; a
|
|
187
|
+
suggestion is not a correctness proof. A runtime "trusted answers" cross-agreement tier was
|
|
188
|
+
tested and **refuted** — removed, and still listed in
|
|
189
|
+
[honesty](https://9pings.github.io/mindsmith/honesty.html).
|
|
190
|
+
- **The win lives on the typed, recurrent slice of your traffic.** Coverage depends on your
|
|
191
|
+
stocks; forge yield is per-domain; amortization is a property of the domain's stereotypy.
|
|
192
|
+
Free prose and genuinely novel reasoning stay in the model, without guarantee — by design.
|
|
193
|
+
- **F2 zoom is not surfaced here.** The piece-by-piece decomposition is measured (rung 4/6)
|
|
194
|
+
but library-only in skynet-graph today; no MCP tool exposes it yet.
|
|
195
|
+
- **Verdicts are reliable only on certified perimeters or wide margins.** Below the measured
|
|
196
|
+
decidability bound, `critique` returns UNDECIDED by design. Its entry templates
|
|
197
|
+
(pool brainstorm, viewpoint naming) are not yet form-robustness-tested; on FREE frames
|
|
198
|
+
coverage is relative to the pool (the payload says so).
|
|
137
199
|
- Streaming is simulated; no per-tier timeout yet.
|
|
138
|
-
- **Nothing is field-adopted (rung 6/6)
|
|
200
|
+
- **Nothing is field-adopted (rung 6/6).** No external replications. This is pre-launch — and
|
|
201
|
+
that's exactly the rung you can help fill.
|
|
139
202
|
|
|
140
203
|
## Env / flags
|
|
141
204
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
(`
|
|
145
|
-
|
|
146
|
-
|
|
205
|
+
**Single-model:** `--model <path.gguf>` (or `MODEL`) · `--ctx` (`CONTEXT_SIZE`) ·
|
|
206
|
+
`--gpu auto|cuda|metal|vulkan|false` · `--gpu-layers` (`GPU_LAYERS`) · `--think <tokens>`
|
|
207
|
+
(`THINK_BUDGET`, default 1024) · custom build `--no-prebuilt` / `--llama-build` / `LLAMA_CMAKE`.
|
|
208
|
+
**Escalation (single frontier):** `FRONTIER_MODEL` (gguf, embedded) or `LLM_BASE` (any
|
|
209
|
+
OpenAI-compatible endpoint). **N-tier:** `--routing <config.json>` / `$SG_ROUTING` +
|
|
210
|
+
`--policy` / `$SG_POLICY` (`no-egress|allow-mid|allow-all`). **Coverage:** `LOCAL_MODEL`
|
|
211
|
+
(separate gguf — paraphrases hit the stock; opt-in). **Rooms/store:** `--room <dir>`
|
|
212
|
+
(default `sgc`) · `--store <f.json>` (durable cross-restart stock, default
|
|
213
|
+
`.skynet-stock.json`) · `--port` (default 4747, binds 127.0.0.1).
|
|
147
214
|
|
|
148
215
|
---
|
|
149
216
|
|
|
150
217
|
AGPL-3.0-or-later · © 2026 Nathanael Braun · solo-author project ·
|
|
151
218
|
engine: [github.com/9pings/skynet-graph](https://github.com/9pings/skynet-graph) ·
|
|
152
|
-
docs
|
|
219
|
+
docs: [9pings.github.io/mindsmith](https://9pings.github.io/mindsmith/) ·
|
|
153
220
|
**pre-launch — nothing is field-adopted yet (rung 6/6)**
|
package/bin/mindsmith
CHANGED
|
@@ -26,8 +26,72 @@ const cmd = argv[0];
|
|
|
26
26
|
const flag = ( n ) => { const i = argv.indexOf('--' + n); return i !== -1 ? argv[i + 1] : undefined; };
|
|
27
27
|
const roomDir = flag('room') || flag('sgc') || 'sgc';
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
if ( !cmd || cmd === '--help' || cmd === '-h' || cmd === 'help' ) {
|
|
30
|
+
console.log([
|
|
31
|
+
'mindsmith — an external reasoning layer for your local LLM: OpenAI-compatible proxy + MCP tools + local .sgc rooms.',
|
|
32
|
+
'',
|
|
33
|
+
'Usage:',
|
|
34
|
+
' mindsmith serve [--port N] [--room <dir>] [--store <f.json>] OpenAI endpoint over your verified stock',
|
|
35
|
+
' escalation (ONE required): --routing <config.json> [--policy no-egress|allow-mid|allow-all]',
|
|
36
|
+
' | env FRONTIER_MODEL=<path.gguf> (embedded gguf — needs `npm install node-llama-cpp`)',
|
|
37
|
+
' | env LLM_BASE=<url> (any OpenAI-compatible endpoint)',
|
|
38
|
+
' single model (ONE VRAM load = LLM server + the graph): --model <path.gguf>',
|
|
39
|
+
' — user answers run WITH think; the graph (coverage · critique · propose) runs no-think, same load.',
|
|
40
|
+
' model opts: --ctx <N> --gpu <auto|cuda|metal|vulkan|false> --gpu-layers <N> --think <tokens>',
|
|
41
|
+
' custom llama.cpp build: --no-prebuilt (build from source) · --llama-build <auto|forceRebuild|never> · env LLAMA_CMAKE=<json>',
|
|
42
|
+
' optional (separate coverage model): env LOCAL_MODEL=<path.gguf>. On WSL, export',
|
|
43
|
+
' LD_LIBRARY_PATH=/usr/lib/wsl/lib:/usr/lib/x86_64-linux-gnu or the gguf silently runs on CPU.',
|
|
44
|
+
' mindsmith mcp [same flags/env as serve] MCP tool surface over stdio (no http socket)',
|
|
45
|
+
' mindsmith rooms list | import <f.sgc> | export <name> <dir> | freeze <name> [--room <dir>]',
|
|
46
|
+
'',
|
|
47
|
+
'Docs: https://github.com/9pings/mindsmith · built on the skynet-graph engine.'
|
|
48
|
+
].join('\n'));
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const flagInt = ( n, d ) => { const v = flag(n); return v === undefined ? d : Number(v); };
|
|
53
|
+
const hasFlag = ( n ) => argv.indexOf('--' + n) !== -1;
|
|
54
|
+
|
|
55
|
+
// --model <gguf> (env MODEL) = the SINGLE-MODEL server mode. ONE gguf load answers BOTH the graph's structured
|
|
56
|
+
// work WITHOUT think (reasoningBudget 0 — coverage, critique, propose) AND the user-facing answers WITH think
|
|
57
|
+
// (the escalation), sharing one VRAM load (local-host keys the load by path+opts; the budget is per-call). So a
|
|
58
|
+
// box with room for a single model still gets a full LLM server + the graph value-add. Model/build options
|
|
59
|
+
// (context size, gpu, gpu-layers, a custom llama.cpp build) apply to that one load.
|
|
60
|
+
function modelConfig() {
|
|
61
|
+
const gpuRaw = flag('gpu'); // auto | cuda | metal | vulkan | false/cpu
|
|
62
|
+
const gpu = gpuRaw === undefined ? undefined : (/^(false|cpu|off|none)$/i.test(gpuRaw) ? false : gpuRaw);
|
|
63
|
+
const llama = {}; // getLlama opts = the custom-build surface
|
|
64
|
+
if ( flag('llama-build') ) llama.build = flag('llama-build'); // auto | forceRebuild | never
|
|
65
|
+
if ( hasFlag('no-prebuilt') || /^(1|true)$/i.test(process.env.LLAMA_FROM_SOURCE || '') ) llama.usePrebuiltBinaries = false; // build from source
|
|
66
|
+
if ( process.env.LLAMA_CMAKE ) { try { llama.cmakeOptions = JSON.parse(process.env.LLAMA_CMAKE); } catch ( _e ) {} }
|
|
67
|
+
const model = {}; // loadModel opts
|
|
68
|
+
const gl = flagInt('gpu-layers', process.env.GPU_LAYERS != null ? Number(process.env.GPU_LAYERS) : undefined);
|
|
69
|
+
if ( gl != null && !Number.isNaN(gl) ) model.gpuLayers = gl;
|
|
70
|
+
const cfg = {};
|
|
71
|
+
const ctx = flagInt('ctx', process.env.CONTEXT_SIZE != null ? Number(process.env.CONTEXT_SIZE) : undefined);
|
|
72
|
+
if ( ctx != null && !Number.isNaN(ctx) ) cfg.contextSize = ctx;
|
|
73
|
+
if ( gpu !== undefined ) cfg.gpu = gpu;
|
|
74
|
+
if ( Object.keys(llama).length ) cfg.llama = llama;
|
|
75
|
+
if ( Object.keys(model).length ) cfg.model = model;
|
|
76
|
+
return cfg;
|
|
77
|
+
}
|
|
78
|
+
let _sm;
|
|
79
|
+
function singleModel() {
|
|
80
|
+
if ( _sm !== undefined ) return _sm;
|
|
81
|
+
const path = flag('model') || process.env.MODEL;
|
|
82
|
+
if ( !path ) return (_sm = null);
|
|
83
|
+
const { makeLocalAsk } = require('skynet-graph/lib/providers/llm-local.js');
|
|
84
|
+
const base = modelConfig(); // IDENTICAL load opts for both handles → ONE shared load
|
|
85
|
+
const think = flagInt('think', process.env.THINK_BUDGET != null ? Number(process.env.THINK_BUDGET) : 1024);
|
|
86
|
+
const answerAsk = makeLocalAsk(Object.assign({ modelPath: path, reasoningBudget: think }, base)); // user answers — WITH think
|
|
87
|
+
const graphAsk = makeLocalAsk(Object.assign({ modelPath: path, reasoningBudget: 0 }, base)); // graph/critique/propose — no think, SAME load
|
|
88
|
+
return (_sm = { answerAsk, graphAsk, path, think, base });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// escalation resolution shared by serve + mcp: single-model, an N-tier routing config, or a single frontier backend.
|
|
30
92
|
function resolveEscalation( need ) {
|
|
93
|
+
const sm = singleModel();
|
|
94
|
+
if ( sm ) return { frontierChat: sm.answerAsk };
|
|
31
95
|
const routing = resolveRouting(argv, process.env);
|
|
32
96
|
if ( routing ) return { tiers: routing.tiers, policy: routing.policy };
|
|
33
97
|
let frontierChat;
|
|
@@ -37,7 +101,9 @@ function resolveEscalation( need ) {
|
|
|
37
101
|
return { frontierChat };
|
|
38
102
|
}
|
|
39
103
|
function buildApp( escalation, extra ) {
|
|
40
|
-
const
|
|
104
|
+
const sm = singleModel();
|
|
105
|
+
const localAsk = sm ? sm.graphAsk // single-model: the graph shares the one load (no think)
|
|
106
|
+
: (process.env.LOCAL_MODEL ? require('skynet-graph/lib/providers/llm-local.js').makeLocalAsk({ modelPath: process.env.LOCAL_MODEL, reasoningBudget: 0 }) : undefined);
|
|
41
107
|
return createApp(Object.assign({}, escalation, {
|
|
42
108
|
localAsk,
|
|
43
109
|
store: flag('store') || '.skynet-stock.json', sgcDir: roomDir,
|
|
@@ -65,7 +131,7 @@ if ( cmd === 'rooms' ) {
|
|
|
65
131
|
console.log('frozen: ' + r.dossier + ' sha256 ' + r.sha256.slice(0, 16) + '… (' + r.classes + ' classes)');
|
|
66
132
|
} else { console.error('usage: mindsmith rooms list|import <file>|export <name> <dest>|freeze <name> [--room <dir>]'); process.exit(1); }
|
|
67
133
|
} catch ( e ) { console.error(e.message); process.exit(1); }
|
|
68
|
-
} else if ( cmd === 'serve'
|
|
134
|
+
} else if ( cmd === 'serve' ) {
|
|
69
135
|
const app = buildApp(resolveEscalation('serve'), {
|
|
70
136
|
port: Number(flag('port')) || 4747,
|
|
71
137
|
onAnswer: ( row ) => console.error('[' + (row.source === 'local' ? 'cache' : 'frontier') + '] ' + row.query),
|
|
@@ -86,7 +152,8 @@ if ( cmd === 'rooms' ) {
|
|
|
86
152
|
// the FULL tool surface over the room: proxy (ask/drift/metrics/lattice_load) + the ASSISTANT
|
|
87
153
|
// lanes over the room's methods stock (hint = certified menu · propose = gated admission) +
|
|
88
154
|
// the C9 critical mind on the escalation backend (critique).
|
|
89
|
-
const
|
|
155
|
+
const sm = singleModel();
|
|
156
|
+
const wiring = { proxy: app.proxy, critiqueAsk: sm ? sm.graphAsk : app.escalationAsk }; // single-model: critique/lanes run no-think on the shared load
|
|
90
157
|
const mf = first.loaded.methods[0];
|
|
91
158
|
if ( mf ) { try { Object.assign(wiring, stockWiring(JSON.parse(require('fs').readFileSync(require('path').join(app.sgcDir, mf), 'utf8')))); } catch ( e ) { console.error('room stock lanes unavailable: ' + e.message); } }
|
|
92
159
|
const server = createMcpServer({
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mindsmith",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "AGPL-3.0-or-later",
|
|
5
5
|
"author": "Nathanael Braun <pp9ping@gmail.com>",
|
|
6
|
+
"repository": { "type": "git", "url": "git+https://github.com/9pings/mindsmith.git" },
|
|
7
|
+
"homepage": "https://github.com/9pings/mindsmith#readme",
|
|
8
|
+
"bugs": "https://github.com/9pings/mindsmith/issues",
|
|
6
9
|
"description": "An external reasoning layer for your local LLM — an OpenAI-compatible proxy + MCP tools (an auditable critical mind, gated think-mode lanes) backed by a mixture of certified graph-experts in your own verified .sgc rooms. Repairs low-quant judgment; nothing leaves the machine (no-egress proven on real sockets).",
|
|
7
10
|
"keywords": ["llm", "local-llm", "reasoning", "critical-thinking", "mixture-of-experts", "knowledge-graph", "openai-compatible", "proxy", "mcp", "agent", "offline", "gguf", "agpl", "skynet-graph"],
|
|
8
11
|
"main": "./lib/app.js",
|
|
@@ -18,6 +21,9 @@
|
|
|
18
21
|
"test": "node --test --test-force-exit test/*.test.js"
|
|
19
22
|
},
|
|
20
23
|
"dependencies": {
|
|
21
|
-
"skynet-graph": "^1.
|
|
24
|
+
"skynet-graph": "^1.3.0"
|
|
25
|
+
},
|
|
26
|
+
"optionalDependencies": {
|
|
27
|
+
"node-llama-cpp": "^3.0.0"
|
|
22
28
|
}
|
|
23
29
|
}
|