`[[page|Label]]` is Obsidian syntax, not OKF. `kb-lint` resolves it Obsidian-style — by filename, anywhere in the bundle — so it has never tripped the link gate, while every other consumer of the bundle (an OKF renderer, a Gitea wiki export, `grep` for reachability) sees bracketed text where a link should be. That is how two generated pages ended up with no inbound link at all and nobody noticed: the my-first link census of the bundle reported them as orphans because their only inbound edges were wikilinks. Mechanical conversion, 52 links across 17 pages, each resolved against the same page set `kb-lint` uses: an explicit `|Label` is kept verbatim, an unlabelled link takes the target's frontmatter `title`. Targets are emitted bundle-absolute (`/tools/niri/tips.md`), the form the spec recommends and the form 99 existing links in this bundle already use. Two links were `[[index]]`, which resolves by filename to 21 pages — the ambiguity that filename-resolution invites. Both meant their own directory's index, so both are now written out in full: `/tools/gitea/index.md`, `/tools/niri/index.md`. The linter still tolerates wikilinks; whether it should reject them outright is an open question on #64, because that would replace the two tests pinning today's tolerance. Refs #64
6.3 KiB
type, title, description, tags, timestamp
| type | title | description | tags | timestamp | |||||
|---|---|---|---|---|---|---|---|---|---|
| reference | Pi Models Configuration | Complete reference for models.json — provider definitions, model specs, and API endpoints for the Frank Program. |
|
2026-08-28 |
Pi Models Configuration (models.json)
models.json defines the LLM providers pi connects to. Each provider specifies a base URL, API type, authentication, and available models.
Location: /home/dank/.pi/agent/models.json
Providers
Current providers in models.json (verified 2026-08-27, after the
2026-08-18 service swap):
llamacpp (dankserver)
| Property | Value |
|---|---|
| Base URL | http://192.168.0.235:7770/v1 |
| API | openai-completions |
| Auth | None (EMPTY) |
| Host | dankserver |
Models
| Model ID | Context Window | maxTokens | Reasoning | Input Types |
|---|---|---|---|---|
frank-default-small |
262,144 | 262,144 | Yes | Text, image |
The server is upstream llama.cpp (b10121) serving HauhauCS
Qwen3.6-35B-A3B-Uncensored-Aggressive Q6_K_P with 36 MoE experts on CPU,
ngram-mod spec, 4 slots of ~175K context. The server serves the loaded
model regardless of the requested model ID. Requests with any model
value succeed.
llamacpp (dankclaw)
| Property | Value |
|---|---|
| Base URL | http://192.168.0.143:7770/v1 |
| API | openai-completions |
| Auth | None (EMPTY) |
| Host | dankclaw |
2026-08-22:
frank-default-largemoved from:52625to:7770on Dankclaw (operator request: the primary inference server sits on the standard llama.cpp port). The OpenWebUI quadlet (OPENAI_API_BASE_URL) was re-pointed to:7770in the same change.
Models
| Model ID | Context Window | maxTokens | Reasoning | Input Types |
|---|---|---|---|---|
frank-default-large |
262,144 | 262,144 | Yes | Text, image |
The server is the ROCmFPX llama.cpp runtime serving
kingjones777's Qwen3.8-Flash-Next Uncensored ROCmFP4 STRIX_LEAN GGUF
— a 177B-parameter, 56B-MoE model sharded into 3 Q4_0-ROCmFP4 GGUF files
(98.3 GB total) with a standalone BF16 vision embedding project (0.85 GB).
Speculative decoding uses --spec-type ngram-mod because the ROCmFPX quantization
drops the 4B MTP head. The model is loaded from
/home/dank/models/kingjones-Qwen3.8-Flash-Next-Uncensored-ROCmFP4-STRIX_LEAN/;
the original Q4_0-ROCmFP4-STRIX variant remains as a .backup directory.
Context is 262144 (native max), 1 slot. Concurrent requests queue on the
single slot; the server never preempts a running generation. It exposes
reasoning_content in deepseek reasoning format and supports
multimodal (vision) inference via the embedded mmproj.
2026-08-27: Upgraded from the original Qwen3.8-Flash-Next Q4_0-ROCmFP4-STRIX GGUF to the Uncensored STRIX_LEAN variant with vision support and ngram-mod speculative decoding.
Thinking Levels
Pi's default thinking level is configured globally in settings.json as
"defaultThinkingLevel": "medium". The model entries map Pi's max level to the llama.cpp-supported xhigh
wire value. Pi shows max in the thinking selector from the global settings,
but sends reasoning_effort: "xhigh" to both local llama.cpp endpoints.
thinkingLevelMap can translate a UI level without changing the global default.
Verified 2026-07-22:
getSupportedThinkingLevels returns off,minimal,low,medium,high,xhigh
and the live server accepts reasoning_effort: "xhigh" and returns
reasoning_content (verified 2026-08-21).
Mechanism (pi-ai models.js + openai-completions.js):
getSupportedThinkingLevels: extended levelsxhigh/maxappear only whenthinkingLevelMapdefines them (string = supported,null= hidden, omitted = not supported).- Default request path (no
compat.thinkingFormat): sendsreasoning_effort = thinkingLevelMap[level] ?? levelwhensupportsReasoningEffortis true (default for this provider).
Token Budgets (maxTokens)
Verified in the pi source, 2026-08-16 (@earendil-works/pi-coding-agent 0.84.1 + pi-ai):
maxTokensis an optional model field inmodels.json. When omitted, pi defaults the model object to 16,384 (provider-composer.js).- The value is metadata. It drives the model-picker "max out" display and length-error recovery (
isRecoverableLength). - Normal chat turns do not send
max_tokens. The request builder sends the field only when a per-request option is set (openai-completions.js buildParams:if (options?.maxTokens)). The agent loop passes no such option. - The only pi calls that send
max_tokensare context compaction and branch summarization. They are deliberately budgeted.
Model Selection Strategy
graph LR
A[User Request] --> B{Complexity?}
B -->|Large context / long docs| C[frank-default-large<br/>CIRU llama.cpp dankclaw :7770, 262K ctx]
B -->|Fast / interactive| D[frank-default-small<br/>llama.cpp dankserver :7770, 262K ctx]
The CIRU endpoint (dankclaw) serves the 177B 56B-MoE model with
262144 context, ngram-mod speculative decoding, 1 slot. Concurrent
requests queue on the single slot. The upstream
llama.cpp endpoint (dankserver) serves the 35B A3B MoE model with 36
experts on CPU and 262K context per slot.
## Live Defaults
`settings.json` picks the main session provider and model (verified 2026-08-19):
| Scope | Provider | Model |
|-------|----------|-------|
| Main session | `llamacpp (dankclaw)` | `frank-default-large` |
| Subagent default | `frank-default-small` (llamacpp dankserver) | ~262K ctx per slot, ngram-mod spec |
| Subagent overrides | scout, researcher | `frank-default-small` |
| Subagent overrides | planner, worker, reviewer, oracle, context-builder | `frank-default-large` (llamacpp dankclaw) |
The subagent model IDs (`frank-default-small`, `frank-default-large`) resolve against the new provider set in `models.json`. The current mappings are `max -> xhigh` for both local models; the global and subagent defaults remain `max`.
---
## See Also
- [settings](/core/settings.md) — Main configuration file
- [dankserver](/system/dankserver.md) — Primary llama.cpp server
- [dankclaw](/system/dankclaw.md) — Secondary llama.cpp server