paseo-prompt-kit 0.5.3 → 0.5.5
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 +24 -20
- package/client/settings/api-endpoints.ts +10 -0
- package/client/sheet/rewrite-sheet.tsx +12 -10
- package/package.json +1 -1
- package/server/transports/cli/family.ts +28 -12
- package/server/transports/cli/runner.ts +32 -1
- package/shared/settings.ts +4 -5
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# PromptKit
|
|
2
2
|
|
|
3
|
-
PromptKit is a Paseo plugin
|
|
3
|
+
PromptKit is a Paseo plugin that rewrites the prompt in your Composer before you send it. It adds a `PromptKit` pill to the Composer and a `/rewrite <prompt>` slash command. The rewrite replaces the Composer text in your own voice — first person, speaking to the agent — and keeps your language and every protected literal (URLs, absolute paths, shell commands, code blocks, model and tool names).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The rewrite runs one of three ways, chosen in Settings: the agent's own provider CLI with the model the Composer shows (the default), a provider CLI with a model you pick, or a direct request to an API you configure (OpenAI, Anthropic, Google Gemini, Cloudflare Workers AI, or anything speaking one of those protocols). A CLI runs headlessly in a temporary directory — no Paseo agent, no tab, no archive — so your conversation never receives a rewrite turn.
|
|
6
6
|
|
|
7
7
|
See [CHANGELOG.md](CHANGELOG.md) for release notes.
|
|
8
8
|
|
|
@@ -10,15 +10,19 @@ See [CHANGELOG.md](CHANGELOG.md) for release notes.
|
|
|
10
10
|
|
|
11
11
|
- **The pill** — write your prompt, press `PromptKit`. The text is rewritten in place; a leading `/rewrite ` left in the text is ignored. Available once the agent exists, so on a new seat it appears after the first message.
|
|
12
12
|
- **`/rewrite <prompt>`** — type the command with the prompt after it and press Enter. Paseo empties the Composer and hands the text to PromptKit, which puts the `/rewrite …` line straight back, dims it with a light sweep while it works, and then replaces it with the rewrite. A failed rewrite leaves your line in place. Available immediately, including on a new seat before its first message. Because no agent exists yet on a draft, `/rewrite` cannot use `Current agent model`; choose `Dedicated model` or `Direct API` with a selected endpoint and model in Settings, or use the pill once the agent exists.
|
|
13
|
-
- **The PromptKit sheet** (mobile) — write in the Composer as usual and press the pill. A sheet slides up
|
|
13
|
+
- **The PromptKit sheet** (mobile) — write in the Composer as usual and press the pill. A sheet slides up holding your text. With one enabled action it rewrites at once and **Rewrite** runs it again; with several, each action has its own button and nothing runs until you press one. **Send** gives the message to the agent, clears the Composer and closes the sheet. **✕** closes the sheet and leaves the Composer untouched.
|
|
14
14
|
|
|
15
15
|
No path sends the message on its own. You review the result and send it yourself.
|
|
16
16
|
|
|
17
|
+
## The General action
|
|
18
|
+
|
|
19
|
+
`General` is the one action that ships. It turns the draft into a clear instruction the agent can act on: the concrete action, each constraint made checkable, the working steps for that kind of task (find the cause first, follow the codebase's existing way, keep the change scoped), and how the agent knows it is done. It never invents files, numbers, requirements or decisions the draft does not contain, and it never writes about you as "the user". Add your own actions under Settings → **Custom actions**.
|
|
20
|
+
|
|
17
21
|
## Requirements
|
|
18
22
|
|
|
19
|
-
- Paseo
|
|
20
|
-
- For
|
|
21
|
-
- For
|
|
23
|
+
- Paseo `>=0.9.0` (Desktop, Web or mobile). Built and tested against the 0.9.0 plugin SDK.
|
|
24
|
+
- For **Provider CLI**: that provider's CLI on the daemon's `PATH`, and a model it can reach.
|
|
25
|
+
- For **Direct API**: an endpoint URL, a model id, and a key — see [API keys](#api-keys).
|
|
22
26
|
|
|
23
27
|
## Install from npm (recommended)
|
|
24
28
|
|
|
@@ -29,7 +33,7 @@ paseo plugin add npm:paseo-prompt-kit
|
|
|
29
33
|
paseo plugin ls
|
|
30
34
|
```
|
|
31
35
|
|
|
32
|
-
Pin a release by adding its version, for example `npm:paseo-prompt-kit@0.5.
|
|
36
|
+
Pin a release by adding its version, for example `npm:paseo-prompt-kit@0.5.5`. The plugin id stays `prompt-kit`, so reload and logs use that id:
|
|
33
37
|
|
|
34
38
|
```bash
|
|
35
39
|
paseo plugin reload prompt-kit
|
|
@@ -55,7 +59,7 @@ paseo plugin logs prompt-kit
|
|
|
55
59
|
|
|
56
60
|
## Install from Git
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
Install a managed Git checkout:
|
|
59
63
|
|
|
60
64
|
```bash
|
|
61
65
|
paseo plugin install hungcuong9125/paseo-prompt-kit --ref main
|
|
@@ -65,24 +69,24 @@ paseo plugin ls
|
|
|
65
69
|
`--ref` chooses the initial branch, tag, or commit once; later `paseo plugin update prompt-kit` follows the remote's default HEAD. Pin a release instead of tracking `main` by giving `--ref` a tag:
|
|
66
70
|
|
|
67
71
|
```bash
|
|
68
|
-
paseo plugin install hungcuong9125/paseo-prompt-kit --ref v0.5.
|
|
72
|
+
paseo plugin install hungcuong9125/paseo-prompt-kit --ref v0.5.5
|
|
69
73
|
```
|
|
70
74
|
|
|
71
75
|
`paseo plugin ls` reports the installed commit.
|
|
72
76
|
|
|
73
77
|
## Settings
|
|
74
78
|
|
|
75
|
-
Open
|
|
79
|
+
Open PromptKit's settings from Paseo Settings → Plugins → the `…` menu on `prompt-kit` → **Settings**. The bar at the top says whether a rewrite would run and over which path, names the reason when it would not, and holds **Save** / **Discard** once something has changed. Nothing is written until Save.
|
|
76
80
|
|
|
77
81
|

|
|
78
82
|
|
|
79
83
|
The screen reads top to bottom in setup order:
|
|
80
84
|
|
|
81
|
-
1. **Actions** — one switch per action, bundled or custom; up to 6 can be on. One enabled action makes the pill rewrite at once; two or more make it a menu (on mobile, one button per action in the sheet); none hides the pill. A lone action shows no switch. Saving updates every pill at once.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
1. **Actions** — one switch per action, bundled or custom; up to 6 can be on. One enabled action makes the pill rewrite at once; two or more make it a menu (on mobile, one button per action in the sheet); none hides the pill. A lone action shows as **Always on**, with no switch. Saving updates every pill at once.
|
|
86
|
+
2. **Custom actions** — your own actions, written as action-pack JSON in a text box on the same screen. **Add** opens a sample (Blank template, Copy of General, Execution brief, Plan first, Review request, Make concise, or a copy of one of yours); change the id, title and instructions, press **Apply** to check the JSON, then **Save**. They run through the same rewrite as `General`.
|
|
87
|
+
3. **Rewrite engine** — Transport, Model source (Provider CLI only) and Output language. Every other section appears only when these need it.
|
|
88
|
+
4. **Dedicated model** (Provider CLI with Dedicated model) or **API endpoint** (Direct API).
|
|
89
|
+
5. **Advanced** (collapsed) — timeout and the two per-provider overrides.
|
|
86
90
|
|
|
87
91
|
### Transport
|
|
88
92
|
|
|
@@ -110,14 +114,14 @@ On `Direct API`, an agent whose provider is mapped under **Advanced → Endpoint
|
|
|
110
114
|
|
|
111
115
|
### API endpoint
|
|
112
116
|
|
|
113
|
-
Choose an endpoint — presets and your saved custom endpoints are listed A–Z (Anthropic, Cloudflare Workers AI, Google Gemini, Local server, OpenAI, OpenRouter), with **Custom endpoint…** last — fill in the base URL, pick a **Key source** (see [API keys](#api-keys)), and press **Test**. A successful test fills the **Model** list from the endpoint; the rewrite refuses a model outside that list. When a list has more than 8 models, a **Filter models** row above Model narrows the dropdown by name or id; the saved model always stays in it. Save is blocked while the endpoint cannot work (for example an empty base URL), with the reason in the status bar.
|
|
117
|
+
Choose an endpoint — presets and your saved custom endpoints are listed A–Z (Anthropic, Cloudflare Workers AI, Google Gemini, Groq, Local server, OpenAI, OpenRouter), with **Custom endpoint…** last — fill in the base URL, pick a **Key source** (see [API keys](#api-keys)), and press **Test**. A successful test fills the **Model** list from the endpoint; the rewrite refuses a model outside that list. When a list has more than 8 models, a **Filter models** row above Model narrows the dropdown by name or id; the saved model always stays in it. Save is blocked while the endpoint cannot work (for example an empty base URL), with the reason in the status bar.
|
|
114
118
|
|
|
115
119
|

|
|
116
120
|
|
|
117
121
|
### Advanced
|
|
118
122
|
|
|
119
123
|
- `Timeout (ms)`: how long a rewrite may run, default `90000`, allowed range `1000`–`600000`. The daemon caps one plugin call at 30 s, so the screen notes when a budget above that cannot be reached.
|
|
120
|
-
- `CLI per provider` (Provider CLI): lists only the providers you have overridden, plus an Add row. A
|
|
124
|
+
- `CLI per provider` (Provider CLI): lists only the providers you have overridden, plus an Add row. A provider named after its CLI (for example `pi` or `codex`) resolves on its own and needs no entry; an unresolved provider is refused, never guessed.
|
|
121
125
|
- `Endpoint per provider` (Direct API): lists only mapped providers, plus an Add row. Pressing the pill in an agent of a mapped provider sends that agent's own model to the endpoint over HTTP. A mapped provider ignores the Model chosen under API endpoint.
|
|
122
126
|
|
|
123
127
|
Settings are host-scoped and persist across plugin reload.
|
|
@@ -177,7 +181,7 @@ Prefer, in this order:
|
|
|
177
181
|
2. **Editing `secrets.json` yourself** on the daemon's machine, as above — the key never passes through the Paseo app.
|
|
178
182
|
3. **The API key field** — only when neither of the above is practical.
|
|
179
183
|
|
|
180
|
-
With Key source `secrets.json`, the API endpoint section shows an **API key** field (masked) and a **Store key** row. **Save** writes the value under the endpoint's Key variable in `secrets.json`: other entries and fields are kept, the directory is created `0700` and the file written `0600` through a temporary file and a rename, and a malformed file is refused rather than overwritten. The field is cleared after saving. The key is write-only: the screen only says whether a value is stored, and **Remove stored key** deletes that one entry. The value never enters the settings document, a log, or an RPC answer. Two clients saving at the same moment can overwrite each other's change.
|
|
184
|
+
With Key source `secrets.json`, the API endpoint section shows an **API key** field (masked) and a **Store API key** row. **Save** writes the value under the endpoint's Key variable in `secrets.json`: other entries and fields are kept, the directory is created `0700` and the file written `0600` through a temporary file and a rename, and a malformed file is refused rather than overwritten. The field is cleared after saving. The key is write-only: the screen only says whether a value is stored, and **Remove stored API key** deletes that one entry. The value never enters the settings document, a log, or an RPC answer. Two clients saving at the same moment can overwrite each other's change.
|
|
181
185
|
|
|
182
186
|
### What PromptKit guarantees about keys
|
|
183
187
|
|
|
@@ -239,6 +243,7 @@ An endpoint that lists `models` restricts the choice to that list, and a model o
|
|
|
239
243
|
|---|---|
|
|
240
244
|
| `missing_api_key` | The endpoint's Key source has no value for its key variable, `secrets.json` is missing or malformed, or the secrets directory is not absolute |
|
|
241
245
|
| `api_endpoint_unknown` | The selected or mapped endpoint id is not defined in `apiEndpoints` |
|
|
246
|
+
| `invalid_model` | The model is not in the endpoint's `models` list |
|
|
242
247
|
| `api_http_error` | The endpoint answered a non-2xx status, or was unreachable |
|
|
243
248
|
| `api_bad_response` | The answer was not JSON, or carried no text |
|
|
244
249
|
| `timeout` | The request exceeded `Timeout (ms)` |
|
|
@@ -249,9 +254,8 @@ Every one of these leaves the Composer text untouched.
|
|
|
249
254
|
|
|
250
255
|
- In-place rewriting works on Desktop and Web only: the mobile app renders the Composer as a native text input with no DOM, and Paseo 0.9.0 exposes no plugin API for Composer text. On mobile the `PromptKit` pill opens the **PromptKit sheet** instead (see above); it reads and clears the Composer through the app's React tree rather than the DOM, which a Paseo update can break in the same way. Nothing is copied or sent on its own. `/rewrite` is not available on mobile. On Web, a refusal names what was found (no Composer, none visible, or more than one visible).
|
|
251
256
|
- Requires Paseo `>=0.9.0`. Because text access depends on the Composer DOM (or, on mobile, the React tree), a Paseo UI change can break it even when the public plugin SDK is compatible.
|
|
252
|
-
- No auto-send. PromptKit only replaces the Composer text; you send the message.
|
|
253
257
|
- PromptKit refuses to replace text you edited while a rewrite was running, and refuses when more than one Composer (or none) is visible.
|
|
254
|
-
-
|
|
258
|
+
- Only `General` ships. Any other action is a custom action you write in Settings, or a pack you bundle as a JSON file — see `docs/EXTENDING.md`.
|
|
255
259
|
- The API transport does not stream: it makes one request and waits for the whole answer. A slow endpoint can exceed the daemon's 30-second plugin-call cap, in which case the host reports a timeout before PromptKit's own `Timeout (ms)` can fire.
|
|
256
260
|
- No OAuth or token refresh: an endpoint uses a static key. A provider that needs an interactive login is better served by the CLI transport.
|
|
257
261
|
|
|
@@ -52,6 +52,16 @@ export const ENDPOINT_PRESETS: readonly EndpointPreset[] = [
|
|
|
52
52
|
accountIdVar: "",
|
|
53
53
|
note: "AI Studio",
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
id: "groq",
|
|
57
|
+
label: "Groq",
|
|
58
|
+
protocol: "openai",
|
|
59
|
+
baseUrl: "https://api.groq.com/openai/v1",
|
|
60
|
+
keySource: "env",
|
|
61
|
+
apiKeyEnv: "GROQ_API_KEY",
|
|
62
|
+
accountIdVar: "",
|
|
63
|
+
note: "OpenAI-compatible, very fast",
|
|
64
|
+
},
|
|
55
65
|
{
|
|
56
66
|
id: "openrouter",
|
|
57
67
|
label: "OpenRouter",
|
|
@@ -32,6 +32,8 @@ const drafts = new Map<string, string>();
|
|
|
32
32
|
|
|
33
33
|
/** Action buttons per row when several actions are enabled. */
|
|
34
34
|
const ACTIONS_PER_ROW = 2;
|
|
35
|
+
/** One grid cell: every cell, filled or empty, takes an equal share of the row. */
|
|
36
|
+
const GRID_CELL = { flexGrow: 1, flexShrink: 1, flexBasis: 0 } as const;
|
|
35
37
|
|
|
36
38
|
function rows<T>(items: readonly T[]): T[][] {
|
|
37
39
|
const out: T[][] = [];
|
|
@@ -206,17 +208,17 @@ export function createRewriteSheet(locate: ComposerLocator): ComponentType<Plugi
|
|
|
206
208
|
? rows(choices).map((row) => (
|
|
207
209
|
<View key={row.map((action) => action.id).join(",")} style={{ flexDirection: "row", gap: SPACE.md }}>
|
|
208
210
|
{row.map((action) => (
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
211
|
+
<View key={action.id} style={GRID_CELL}>
|
|
212
|
+
<Button
|
|
213
|
+
theme={theme}
|
|
214
|
+
label={action.title}
|
|
215
|
+
onPress={() => void runRewrite(value, action.id)}
|
|
216
|
+
disabled={busy !== "idle" || value.trim() === ""}
|
|
217
|
+
testID={`prompt-kit-sheet-action-${action.id}`}
|
|
218
|
+
/>
|
|
219
|
+
</View>
|
|
218
220
|
))}
|
|
219
|
-
{row.length < ACTIONS_PER_ROW ? <View style={
|
|
221
|
+
{row.length < ACTIONS_PER_ROW ? <View style={GRID_CELL} /> : null}
|
|
220
222
|
</View>
|
|
221
223
|
))
|
|
222
224
|
: null}
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@ export interface CliInvocation {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface CliRequest {
|
|
18
|
-
/** The model id as the agent snapshot reports it, e.g. `
|
|
18
|
+
/** The model id as the agent snapshot reports it, e.g. `openai/gpt-4.1-mini`. */
|
|
19
19
|
readonly model: string;
|
|
20
20
|
readonly thinkingOptionId: string | null;
|
|
21
21
|
/** Instruction text. Replaces the CLI's own default system prompt where supported. */
|
|
@@ -34,6 +34,8 @@ export interface CliFamily {
|
|
|
34
34
|
buildInvocation(request: CliRequest): CliInvocation;
|
|
35
35
|
/** Extracts the final answer from captured stdout, or null when there is none. */
|
|
36
36
|
parseOutput(stdout: string): string | null;
|
|
37
|
+
/** The failure the CLI itself reports in stdout, or null when it reports none. */
|
|
38
|
+
parseError(stdout: string): string | null;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/** Collects the text parts of a pi/opencode-style JSONL event stream. */
|
|
@@ -104,8 +106,21 @@ export const piFamily: CliFamily = {
|
|
|
104
106
|
lastJsonlText(stdout, (event) =>
|
|
105
107
|
event.type === "turn_end" ? piMessageText(event.message) : null,
|
|
106
108
|
),
|
|
109
|
+
parseError: () => null,
|
|
107
110
|
};
|
|
108
111
|
|
|
112
|
+
/** The single JSON result object `claude -p --output-format json` prints, or null. */
|
|
113
|
+
function claudeResult(stdout: string): { result?: unknown; is_error?: unknown } | null {
|
|
114
|
+
const start = stdout.indexOf("{");
|
|
115
|
+
if (start === -1) return null;
|
|
116
|
+
try {
|
|
117
|
+
const parsed: unknown = JSON.parse(stdout.slice(start));
|
|
118
|
+
return parsed !== null && typeof parsed === "object" ? (parsed as { result?: unknown; is_error?: unknown }) : null;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
109
124
|
export const claudeFamily: CliFamily = {
|
|
110
125
|
id: "claude",
|
|
111
126
|
promptDelivery: "stdin",
|
|
@@ -128,17 +143,16 @@ export const claudeFamily: CliFamily = {
|
|
|
128
143
|
return { command: "claude", args };
|
|
129
144
|
},
|
|
130
145
|
parseOutput: (stdout) => {
|
|
131
|
-
const
|
|
132
|
-
if (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (parsed === null ||
|
|
140
|
-
|
|
141
|
-
return typeof result === "string" ? result : null;
|
|
146
|
+
const parsed = claudeResult(stdout);
|
|
147
|
+
if (parsed === null || parsed.is_error === true) return null;
|
|
148
|
+
return typeof parsed.result === "string" ? parsed.result : null;
|
|
149
|
+
},
|
|
150
|
+
// An auth or API failure still prints a result object, flagged `is_error`, whose
|
|
151
|
+
// `result` is the error text rather than an answer.
|
|
152
|
+
parseError: (stdout) => {
|
|
153
|
+
const parsed = claudeResult(stdout);
|
|
154
|
+
if (parsed === null || parsed.is_error !== true) return null;
|
|
155
|
+
return typeof parsed.result === "string" && parsed.result.trim() !== "" ? parsed.result : "Claude reported an error.";
|
|
142
156
|
},
|
|
143
157
|
};
|
|
144
158
|
|
|
@@ -171,6 +185,7 @@ export const codexFamily: CliFamily = {
|
|
|
171
185
|
const typed = item as { type?: unknown; text?: unknown };
|
|
172
186
|
return typed.type === "agent_message" && typeof typed.text === "string" ? typed.text : null;
|
|
173
187
|
}),
|
|
188
|
+
parseError: () => null,
|
|
174
189
|
};
|
|
175
190
|
|
|
176
191
|
export const opencodeFamily: CliFamily = {
|
|
@@ -190,6 +205,7 @@ export const opencodeFamily: CliFamily = {
|
|
|
190
205
|
const text = (part as { text?: unknown }).text;
|
|
191
206
|
return typeof text === "string" ? text : null;
|
|
192
207
|
}),
|
|
208
|
+
parseError: () => null,
|
|
193
209
|
};
|
|
194
210
|
|
|
195
211
|
const FAMILIES: readonly CliFamily[] = [piFamily, claudeFamily, codexFamily, opencodeFamily];
|
|
@@ -22,7 +22,17 @@ export interface CliRewriteDependencies {
|
|
|
22
22
|
|
|
23
23
|
export type CliRewriteResult =
|
|
24
24
|
| { readonly ok: true; readonly text: string }
|
|
25
|
-
| {
|
|
25
|
+
| {
|
|
26
|
+
readonly ok: false;
|
|
27
|
+
readonly code: "timeout" | "spawn_failed" | "empty_output" | "generation_failed";
|
|
28
|
+
readonly message: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** Enough of a CLI's own error text to recognise it, on one line. */
|
|
32
|
+
function firstLine(text: string, max = 200): string {
|
|
33
|
+
const line = text.split("\n").map((part) => part.trim()).find((part) => part !== "") ?? "";
|
|
34
|
+
return line.length <= max ? line : `${line.slice(0, max - 1)}…`;
|
|
35
|
+
}
|
|
26
36
|
|
|
27
37
|
/**
|
|
28
38
|
* Runs one rewrite through a CLI in a scratch directory.
|
|
@@ -74,6 +84,27 @@ export async function runCliRewrite(
|
|
|
74
84
|
return { ok: false, code: "timeout", message: "The rewrite timed out." };
|
|
75
85
|
}
|
|
76
86
|
|
|
87
|
+
// A failed run never becomes a rewrite: its stdout can hold an error text
|
|
88
|
+
// that would otherwise read like an answer.
|
|
89
|
+
const reported = input.family.parseError(result.stdout);
|
|
90
|
+
if (reported !== null) {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
code: "generation_failed",
|
|
94
|
+
message: `The rewrite CLI "${input.family.id}" reported an error: ${firstLine(reported)}`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (result.exitCode !== 0) {
|
|
98
|
+
const detail = firstLine(result.stderr);
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
code: "generation_failed",
|
|
102
|
+
message: `The rewrite CLI "${input.family.id}" exited with ${
|
|
103
|
+
result.exitCode === null ? "a signal" : `code ${result.exitCode}`
|
|
104
|
+
}${detail === "" ? "." : `: ${detail}`}`,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
77
108
|
const text = input.family.parseOutput(result.stdout);
|
|
78
109
|
if (text === null || text.trim() === "") {
|
|
79
110
|
return {
|
package/shared/settings.ts
CHANGED
|
@@ -38,11 +38,10 @@ export const promptKitSettingsSchema = z.object({
|
|
|
38
38
|
dedicatedModel: z.string().min(1).nullable().default(null),
|
|
39
39
|
dedicatedThinkingOptionId: z.string().min(1).nullable().default(null),
|
|
40
40
|
/**
|
|
41
|
-
* Maps a Paseo provider id to the CLI family that runs it.
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* id does not mention its CLI, and an unknown id fails closed either way.
|
|
41
|
+
* Maps a Paseo provider id to the CLI family that runs it. A provider named
|
|
42
|
+
* after its CLI (`pi`, `codex`), or whose id starts with that name, resolves
|
|
43
|
+
* without an entry here. An entry is needed only for a provider whose id does
|
|
44
|
+
* not mention its CLI, and an unknown id fails closed either way.
|
|
46
45
|
*/
|
|
47
46
|
providerCli: z.record(z.string(), z.enum(CLI_FAMILY_IDS)).default({}),
|
|
48
47
|
/** The API endpoints this host can reach. Key values are never stored here. */
|