promptpilot 0.1.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/LICENSE +21 -0
- package/README.md +283 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.js +1543 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +287 -0
- package/dist/index.js +1270 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# promptpilot
|
|
2
|
+
|
|
3
|
+
`promptpilot` is a lightweight TypeScript npm package that sits between your app or CLI workflow and a target LLM. It rewrites prompts locally through Ollama when available, stores reusable session context, compresses older turns, and emits a Claude-friendly final prompt for shell pipelines or application code.
|
|
4
|
+
|
|
5
|
+
It is designed for local-first workflows on machines like an 18 GB MacBook. By default, `promptpilot` inspects your local Ollama installation and auto-selects a small optimization model, preferring `qwen2.5:3b`, `phi3:mini`, and `llama3.2:3b` in that order. The package still lets you override the model manually when needed.
|
|
6
|
+
|
|
7
|
+
## Why local Ollama
|
|
8
|
+
|
|
9
|
+
- It keeps prompt optimization close to your workflow.
|
|
10
|
+
- It reduces external API calls for prompt rewriting.
|
|
11
|
+
- It lets you use a small, fast model for compression before sending the final prompt to a stronger remote model like Claude.
|
|
12
|
+
- It automatically picks an installed local model that fits a low-memory workflow.
|
|
13
|
+
|
|
14
|
+
## What it does
|
|
15
|
+
|
|
16
|
+
- Accepts a raw prompt plus optional metadata.
|
|
17
|
+
- Persists session context across turns.
|
|
18
|
+
- Retrieves relevant prior context for the next prompt.
|
|
19
|
+
- Summarizes older context when budgets get tight.
|
|
20
|
+
- Preserves critical instructions and constraints.
|
|
21
|
+
- Estimates token usage before and after optimization.
|
|
22
|
+
- Outputs plain prompt text or structured JSON.
|
|
23
|
+
- Works cleanly with Claude CLI shell pipelines.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install
|
|
29
|
+
npm run build
|
|
30
|
+
npm test
|
|
31
|
+
ollama pull qwen2.5:3b
|
|
32
|
+
promptpilot optimize "explain binary search simply" --plain
|
|
33
|
+
promptpilot optimize "continue my study guide" --session dsa --save-context --plain | claude
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
After publishing, install from npm with:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g promptpilot
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Install and build
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install
|
|
46
|
+
npm run build
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Install directly from a local tarball:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm pack
|
|
53
|
+
npm install -g ./promptpilot-0.1.0.tgz
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Library usage
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { createOptimizer, optimizePrompt } from "promptpilot";
|
|
60
|
+
|
|
61
|
+
const optimizer = createOptimizer({
|
|
62
|
+
provider: "ollama",
|
|
63
|
+
host: "http://localhost:11434",
|
|
64
|
+
contextStore: "local"
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const result = await optimizer.optimize({
|
|
68
|
+
prompt: "help me write a better follow up email for a startup internship",
|
|
69
|
+
task: "email",
|
|
70
|
+
tone: "professional but human",
|
|
71
|
+
targetModel: "claude",
|
|
72
|
+
sessionId: "internship-search"
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log(result.optimizedPrompt);
|
|
76
|
+
|
|
77
|
+
const oneOff = await optimizePrompt({
|
|
78
|
+
prompt: "continue working on my essay intro",
|
|
79
|
+
task: "essay",
|
|
80
|
+
sessionId: "essay1"
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
console.log(oneOff.finalPrompt);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Claude CLI usage
|
|
87
|
+
|
|
88
|
+
Plain shell output:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
promptpilot optimize "help me explain binary search simply" --session study --plain
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Piping into Claude CLI:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
promptpilot optimize "help me explain binary search simply" --session study --plain | claude
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Using stdin in a shell pipeline:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
cat notes.txt | promptpilot optimize --task summarization --plain | claude
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Saving context between calls:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
promptpilot optimize "continue working on my essay intro" --session essay1 --task essay --save-context --plain
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Debugging token usage:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
promptpilot optimize "summarize these lecture notes" --session notes1 --json --debug
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Clearing a session:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
promptpilot optimize --session essay1 --clear-session
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Node `child_process` example:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { spawn } from "node:child_process";
|
|
128
|
+
|
|
129
|
+
const prompt = spawn("promptpilot", [
|
|
130
|
+
"optimize",
|
|
131
|
+
"continue my study guide",
|
|
132
|
+
"--session",
|
|
133
|
+
"dsa",
|
|
134
|
+
"--plain"
|
|
135
|
+
]);
|
|
136
|
+
|
|
137
|
+
const claude = spawn("claude", [], { stdio: ["pipe", "inherit", "inherit"] });
|
|
138
|
+
prompt.stdout.pipe(claude.stdin);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Session context
|
|
142
|
+
|
|
143
|
+
By default, if you pass a `sessionId`, `promptpilot` stores optimized turns in a local session store. The default store is JSON files under `~/.promptpilot/sessions`. A SQLite store is also available when `node:sqlite` or `better-sqlite3` is present.
|
|
144
|
+
|
|
145
|
+
If you do not pass `ollamaModel` or `--model`, `promptpilot` asks Ollama which models are installed and picks the best small model for the job. For most workflows it prefers `qwen2.5:3b`, then `phi3:mini`, then `llama3.2:3b`. For code-heavy prompts it will prefer `qwen2.5-coder:3b` when that model is installed. If only oversized local models are available, it warns and falls back to deterministic heuristic optimization instead of silently using a heavy model.
|
|
146
|
+
|
|
147
|
+
Each session stores:
|
|
148
|
+
|
|
149
|
+
- User prompts
|
|
150
|
+
- Optimized prompts
|
|
151
|
+
- Final prompts
|
|
152
|
+
- Extracted constraints
|
|
153
|
+
- Context summaries
|
|
154
|
+
- Timestamps
|
|
155
|
+
- Optional tags
|
|
156
|
+
|
|
157
|
+
Context retrieval prefers:
|
|
158
|
+
|
|
159
|
+
- Pinned constraints
|
|
160
|
+
- Task-aligned prior turns
|
|
161
|
+
- Recent prompts
|
|
162
|
+
- Named entities and recurring references
|
|
163
|
+
- Stored summaries when budgets are tight
|
|
164
|
+
|
|
165
|
+
## Token reduction
|
|
166
|
+
|
|
167
|
+
`promptpilot` estimates token usage heuristically for:
|
|
168
|
+
|
|
169
|
+
- The new prompt
|
|
170
|
+
- Retrieved session context
|
|
171
|
+
- The final composed prompt
|
|
172
|
+
|
|
173
|
+
You can control the budgets with:
|
|
174
|
+
|
|
175
|
+
- `maxInputTokens`
|
|
176
|
+
- `maxContextTokens`
|
|
177
|
+
- `maxTotalTokens`
|
|
178
|
+
|
|
179
|
+
When context is too large, it ranks prior turns, preserves high-value constraints, summarizes older context, and drops lower-signal items.
|
|
180
|
+
|
|
181
|
+
## CLI
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
promptpilot optimize "write me a better prompt for asking claude to summarize lecture notes"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Supported flags:
|
|
188
|
+
|
|
189
|
+
- `--session <id>`
|
|
190
|
+
- `--model <name>` to override auto-selection
|
|
191
|
+
- `--mode <mode>`
|
|
192
|
+
- `--task <task>`
|
|
193
|
+
- `--tone <tone>`
|
|
194
|
+
- `--preset <preset>`
|
|
195
|
+
- `--target-model <name>`
|
|
196
|
+
- `--output-format <text>`
|
|
197
|
+
- `--max-length <n>`
|
|
198
|
+
- `--tag <value>` repeatable
|
|
199
|
+
- `--pin-constraint <text>` repeatable
|
|
200
|
+
- `--store <local|sqlite>`
|
|
201
|
+
- `--storage-dir <path>`
|
|
202
|
+
- `--sqlite-path <path>`
|
|
203
|
+
- `--plain`
|
|
204
|
+
- `--json`
|
|
205
|
+
- `--debug`
|
|
206
|
+
- `--save-context`
|
|
207
|
+
- `--no-context`
|
|
208
|
+
- `--max-total-tokens <n>`
|
|
209
|
+
- `--max-context-tokens <n>`
|
|
210
|
+
- `--max-input-tokens <n>`
|
|
211
|
+
- `--clear-session`
|
|
212
|
+
- `--bypass-optimization`
|
|
213
|
+
|
|
214
|
+
If no prompt argument is provided, `promptpilot optimize` will read the raw prompt from stdin.
|
|
215
|
+
|
|
216
|
+
## Public API
|
|
217
|
+
|
|
218
|
+
Main exports:
|
|
219
|
+
|
|
220
|
+
- `createOptimizer`
|
|
221
|
+
- `optimizePrompt`
|
|
222
|
+
- `PromptOptimizer`
|
|
223
|
+
- `OllamaClient`
|
|
224
|
+
- `FileSessionStore`
|
|
225
|
+
- `SQLiteSessionStore`
|
|
226
|
+
|
|
227
|
+
Supported modes:
|
|
228
|
+
|
|
229
|
+
- `clarity`
|
|
230
|
+
- `concise`
|
|
231
|
+
- `detailed`
|
|
232
|
+
- `structured`
|
|
233
|
+
- `persuasive`
|
|
234
|
+
- `compress`
|
|
235
|
+
- `claude_cli`
|
|
236
|
+
|
|
237
|
+
Supported presets:
|
|
238
|
+
|
|
239
|
+
- `code`
|
|
240
|
+
- `email`
|
|
241
|
+
- `essay`
|
|
242
|
+
- `support`
|
|
243
|
+
- `summarization`
|
|
244
|
+
- `chat`
|
|
245
|
+
|
|
246
|
+
## File structure
|
|
247
|
+
|
|
248
|
+
```text
|
|
249
|
+
src/
|
|
250
|
+
index.ts
|
|
251
|
+
types.ts
|
|
252
|
+
errors.ts
|
|
253
|
+
cli.ts
|
|
254
|
+
core/
|
|
255
|
+
optimizer.ts
|
|
256
|
+
ollamaClient.ts
|
|
257
|
+
systemPrompt.ts
|
|
258
|
+
contextManager.ts
|
|
259
|
+
tokenEstimator.ts
|
|
260
|
+
contextCompressor.ts
|
|
261
|
+
storage/
|
|
262
|
+
fileSessionStore.ts
|
|
263
|
+
sqliteSessionStore.ts
|
|
264
|
+
utils/
|
|
265
|
+
validation.ts
|
|
266
|
+
logger.ts
|
|
267
|
+
json.ts
|
|
268
|
+
test/
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Safety and fallback behavior
|
|
272
|
+
|
|
273
|
+
If Ollama is unavailable, `promptpilot` falls back to a deterministic local formatter that still preserves constraints and emits a Claude-compatible final prompt. Empty prompts are rejected, timeouts are supported, and hard token budget failures throw explicit errors.
|
|
274
|
+
|
|
275
|
+
## Future improvements
|
|
276
|
+
|
|
277
|
+
- Semantic retrieval for context
|
|
278
|
+
- Better token counting by model
|
|
279
|
+
- Prompt scoring
|
|
280
|
+
- Local embeddings for relevance search
|
|
281
|
+
- Response-aware context updates
|
|
282
|
+
- Cache layer
|
|
283
|
+
- Benchmark suite
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createOptimizer } from './index.js';
|
|
3
|
+
|
|
4
|
+
type CliWriter = {
|
|
5
|
+
write(message: string): void;
|
|
6
|
+
};
|
|
7
|
+
interface CliIO {
|
|
8
|
+
stdout: CliWriter;
|
|
9
|
+
stderr: CliWriter;
|
|
10
|
+
stdin?: NodeJS.ReadStream;
|
|
11
|
+
}
|
|
12
|
+
interface CliDependencies {
|
|
13
|
+
createOptimizer: typeof createOptimizer;
|
|
14
|
+
readStdin: (stdin?: NodeJS.ReadStream) => Promise<string>;
|
|
15
|
+
}
|
|
16
|
+
declare function runCli(argv: string[], io?: CliIO, dependencies?: CliDependencies): Promise<number>;
|
|
17
|
+
|
|
18
|
+
export { runCli };
|