localpi 0.2.0 → 0.3.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.
@@ -0,0 +1,192 @@
1
+ ---
2
+ title: Endless Demo Mode Plan
3
+ author: Bob <dutifulbob@gmail.com>
4
+ date: 2026-06-18
5
+ ---
6
+
7
+ # Endless Demo Mode Plan
8
+
9
+ This plan covers an endless localpi demo mode that runs inside Pi's normal TUI and repeatedly prompts Pi until the user exits the TUI or interrupts it.
10
+
11
+ ## Goal
12
+
13
+ `localpi --demo` should run a hands-free local model demo without turning localpi into an interactive chat client and without subverting Pi's native TUI.
14
+
15
+ The demo orchestration is owned by a localpi-generated Pi extension. Rendering, streaming, tok/s display, input handling, slash commands, session state, and lifecycle remain owned by Pi.
16
+
17
+ ## Target Behavior
18
+
19
+ - `localpi --demo --model <alias|id|path>` starts Pi once with a built-in initial prompt.
20
+ - Pi opens in normal TUI mode.
21
+ - The demo extension sends the initial prompt after TUI `session_start`.
22
+ - After each completed generation, the demo extension sends the followup prompt after `turn_end`.
23
+ - The followup prompt defaults to `Continue. Try to write as long as possible.`
24
+ - The loop continues until the user exits Pi, `Ctrl-C` is pressed, or Pi stops the session normally.
25
+ - Runtime discovery, Pi config generation, extensions, thinking, tools, and approval behavior match normal localpi launches.
26
+ - Demo mode requires an explicit non-`auto` model through `--model` or `LOCALPI_MODEL`; it must not auto-select a model.
27
+ - Demo mode requires interactive TTY stdin and stdout so Pi opens its normal TUI.
28
+ - Demo mode uses one live Pi session so followup prompts keep the first prompt's context.
29
+ - Demo mode works with any provider localpi already supports: LM Studio, vLLM, generic OpenAI-compatible providers, and managed `llama-server`.
30
+ - Demo mode does not parse terminal output to detect when generation stops; it relies on Pi extension events.
31
+
32
+ ## Default Prompts
33
+
34
+ Initial prompt:
35
+
36
+ ```text
37
+ You are narrating a never-ending sci-fi adventure. Continue in short paragraphs. Whenever the user sends a message, treat it as a live director note and incorporate it immediately. Never end the story.
38
+ ```
39
+
40
+ Followup prompt:
41
+
42
+ ```text
43
+ Continue. Try to write as long as possible.
44
+ ```
45
+
46
+ ## CLI Contract
47
+
48
+ Add these flags:
49
+
50
+ - `--demo`: enable endless demo mode.
51
+ - `--demo-initial-prompt <text>`: override the first prompt.
52
+ - `--demo-followup-prompt <text>`: override every prompt after the first.
53
+ - `--demo-initial-prompt-file <path>`: read the first prompt from a UTF-8 file.
54
+ - `--demo-followup-prompt-file <path>`: read the followup prompt from a UTF-8 file.
55
+
56
+ Add matching environment variables:
57
+
58
+ - `LOCALPI_DEMO`
59
+ - `LOCALPI_DEMO_INITIAL_PROMPT`
60
+ - `LOCALPI_DEMO_FOLLOWUP_PROMPT`
61
+ - `LOCALPI_DEMO_INITIAL_PROMPT_FILE`
62
+ - `LOCALPI_DEMO_FOLLOWUP_PROMPT_FILE`
63
+
64
+ File flags should win over text flags for the same prompt because they are the better interface for long prompts.
65
+
66
+ Explicit CLI flags should win over environment variables.
67
+
68
+ ## Incompatible Modes
69
+
70
+ Reject these combinations with clear errors:
71
+
72
+ - `--demo --status`
73
+ - `--demo --stop`
74
+ - `--demo --list`
75
+ - `--demo` without an explicit non-`auto` model
76
+ - `--demo` without interactive TTY stdin and stdout
77
+ - `--demo` with user-supplied forwarded Pi prompt flags such as `-p` or `--prompt`
78
+
79
+ Forwarded non-prompt Pi options should remain allowed.
80
+
81
+ ## Launch Design
82
+
83
+ Keep `src/pi/launch.ts` as the single-launch layer. Demo mode should use the same launch path as a normal interactive localpi session.
84
+
85
+ Demo mode should not:
86
+
87
+ - pass prompts through stdin
88
+ - pass prompts with `-p` or `--prompt`
89
+ - force print, JSON, or RPC mode
90
+ - launch repeated one-shot Pi child processes
91
+ - create or manage a parallel localpi TUI
92
+
93
+ Normal localpi launch planning should write an additional generated extension when `--demo` is enabled, then launch Pi normally.
94
+
95
+ ## Demo Extension
96
+
97
+ Add a generated Pi extension, likely `demo-mode.ts`, alongside the existing localpi extensions.
98
+
99
+ The extension owns:
100
+
101
+ - resolving already-materialized prompt text provided by localpi
102
+ - sending the initial prompt once on `session_start` when `ctx.mode === "tui"`
103
+ - sending the followup prompt after each final assistant `turn_end` when demo mode is still active
104
+ - relying on Pi's own queueing via `pi.sendUserMessage`
105
+ - optional later controls such as `/demo stop`
106
+
107
+ Example shape:
108
+
109
+ ```ts
110
+ pi.on("session_start", (event, ctx) => {
111
+ if (started || event.reason !== "startup" || ctx.mode !== "tui") {
112
+ return;
113
+ }
114
+ started = true;
115
+ pi.sendUserMessage(initialPrompt);
116
+ });
117
+
118
+ pi.on("turn_end", (event, ctx) => {
119
+ if (!started || stopped || ctx.mode !== "tui") {
120
+ return;
121
+ }
122
+ if (event.message.role !== "assistant") {
123
+ return;
124
+ }
125
+ if (event.message.stopReason === "aborted" || event.message.stopReason === "error") {
126
+ stopped = true;
127
+ return;
128
+ }
129
+ if (event.message.stopReason === "toolUse") {
130
+ return;
131
+ }
132
+ pi.sendUserMessage(followupPrompt, { deliverAs: "followUp" });
133
+ });
134
+ ```
135
+
136
+ Prompt file loading should stay in localpi before extension generation. The generated extension should contain concrete prompt strings so Pi does not need to read localpi-specific files at runtime.
137
+
138
+ ## Signal And Exit Behavior
139
+
140
+ - Pi owns `Ctrl-C`, exit, and interactive lifecycle behavior.
141
+ - If a turn ends with an aborted or error assistant message, the demo extension should stop queueing followup prompts.
142
+ - If a turn ends with tool use, the demo extension should wait for the final assistant turn before queueing a followup.
143
+ - localpi should not restart Pi after exit.
144
+ - If Pi exits non-zero, localpi should return the same exit code as a normal launch.
145
+ - No special signal-forwarding loop should be needed beyond normal `execLaunchPlan` behavior.
146
+
147
+ ## Non-Goals
148
+
149
+ - Do not scrape stdout or terminal output to infer completion.
150
+ - Do not run demo mode as a hidden headless print-mode loop.
151
+ - Do not repeatedly spawn one-shot Pi processes.
152
+ - Do not create a second localpi-owned TUI or prompt loop.
153
+ - Do not make provider-specific demo behavior.
154
+ - Do not add classifier, benchmark, dataset, or schema workflow concepts.
155
+ - Do not keep a hidden background service running after localpi exits.
156
+
157
+ ## Testing Checklist
158
+
159
+ - [x] Parse `--demo` and all demo prompt flags.
160
+ - [x] Parse matching `LOCALPI_DEMO*` environment variables.
161
+ - [x] Verify CLI prompt values override environment values.
162
+ - [x] Verify prompt files override text prompt values.
163
+ - [x] Verify `--demo --status`, `--demo --stop`, and `--demo --list` fail clearly.
164
+ - [x] Verify demo mode rejects missing or `auto` model selection.
165
+ - [x] Verify demo mode rejects non-TTY stdin/stdout.
166
+ - [x] Verify demo mode rejects forwarded Pi prompt flags.
167
+ - [x] Unit-test that demo mode writes a generated Pi extension.
168
+ - [x] Unit-test that the generated extension sends the initial prompt on TUI `session_start`.
169
+ - [x] Unit-test that the generated extension sends followup prompts after `turn_end`.
170
+ - [x] Unit-test that the generated extension does not queue followups after tool-use continuation turns.
171
+ - [x] Unit-test that demo mode uses the normal Pi launch path and does not pipe prompts over stdin.
172
+ - [x] Unit-test that normal launches are unchanged.
173
+ - [x] Use a fake `LOCALPI_PI_CMD` to prove demo launches Pi once with the demo extension path.
174
+ - [x] Verify demo mode does not pass `-p`, `--prompt`, `--mode print`, `--mode json`, or `--mode rpc`.
175
+ - [x] Run `npm run check`.
176
+
177
+ ## Documentation Checklist
178
+
179
+ - [x] Document `--demo` in README options.
180
+ - [x] Document prompt override flags.
181
+ - [x] Document `LOCALPI_DEMO*` environment variables.
182
+ - [x] Include one simple example:
183
+
184
+ ```bash
185
+ localpi --demo --model gemma-e4b
186
+ ```
187
+
188
+ - [x] Include one override example:
189
+
190
+ ```bash
191
+ localpi --demo --model gemma-e4b --demo-initial-prompt-file ./prompts/story.txt --demo-followup-prompt "Continue. Try to write as long as possible."
192
+ ```
@@ -98,6 +98,32 @@ Provider registry JSON can define additional OpenAI-compatible providers:
98
98
 
99
99
  Set `discover: false` when the endpoint should not be probed during startup. Explicit `--provider <id> --model <id>` can still select that provider and generate Pi config.
100
100
 
101
+ ## Capability Profiles
102
+
103
+ OpenAI-compatible `/v1/models` responses do not reliably report local serving capabilities such as reasoning support or Pi's required thinking request format. Localpi can read a local model capability profile with `--model-profile`, `LOCALPI_MODEL_PROFILE`, or `LOCALPAGER_AGENT_PROFILE`.
104
+
105
+ Example:
106
+
107
+ ```json
108
+ {
109
+ "id": "gemma4-26b-a4b-nvfp4",
110
+ "model": "nvidia/Gemma-4-26B-A4B-NVFP4",
111
+ "base_url": "http://127.0.0.1:8000/v1",
112
+ "client": {
113
+ "context_window": 32768,
114
+ "max_tokens": 4096
115
+ },
116
+ "capabilities": {
117
+ "reasoning": true,
118
+ "thinking_format": "qwen-chat-template"
119
+ }
120
+ }
121
+ ```
122
+
123
+ When the served model id matches `model` or `id`, localpi uses the profile to generate Pi model config. `LOCALPI_MODEL_REASONING` / `LOCALPAGER_AGENT_REASONING` and `LOCALPI_MODEL_THINKING_FORMAT` / `LOCALPAGER_AGENT_THINKING_FORMAT` are explicit overrides.
124
+
125
+ Name-based capability detection remains fallback behavior. Built-in vLLM Gemma 4 model ids are treated as reasoning-capable with `qwen-chat-template`, matching vLLM Gemma servers launched with `--reasoning-parser gemma4`.
126
+
101
127
  ## Model Selection
102
128
 
103
129
  `--model` should accept:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "localpi",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Pi-compatible local model launcher with managed llama-server support.",
5
5
  "type": "module",
6
6
  "license": "MIT",