@gr8ful/spf 0.9.1 → 0.9.2
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/dist/cli/interview.js +40 -16
- package/package.json +1 -1
package/dist/cli/interview.js
CHANGED
|
@@ -95,25 +95,49 @@ export async function runInterview(asker, ctx) {
|
|
|
95
95
|
defaults.coding_agent = codingAgent;
|
|
96
96
|
if (codingAgent === "claude_code") {
|
|
97
97
|
if (!ctx.claudeOnPath) {
|
|
98
|
-
asker.note("warning: `claude` was not found on PATH — install it (or
|
|
98
|
+
asker.note("warning: `claude` was not found on PATH — install it (or pick a launch command below) before running spf.");
|
|
99
|
+
}
|
|
100
|
+
// A select, not free text: the three shapes below are the only ones
|
|
101
|
+
// agent_cc.ts actually supports (see its module doc comment), and
|
|
102
|
+
// getting one wrong by hand-typing is exactly how the two doctor.ts
|
|
103
|
+
// hard-fails here (a missing "--" separator, a missing "--model" before
|
|
104
|
+
// it) get triggered in practice. "ollama" is fully determined by
|
|
105
|
+
// picking it — no further typing, and no way to omit the `--model`
|
|
106
|
+
// flag or the `{model}` token by mistake. "custom" is the escape hatch
|
|
107
|
+
// for anything else (a proxy, a bespoke wrapper script).
|
|
108
|
+
const launchMode = await asker.select("Launch command for the `claude` CLI", [
|
|
109
|
+
{ value: "claude", label: "claude — resolved from PATH" },
|
|
110
|
+
{ value: "ollama", label: "ollama launch claude --model {model} — routes through Ollama, per-agent model" },
|
|
111
|
+
{ value: "custom", label: "custom — type your own launch command" },
|
|
112
|
+
], "claude");
|
|
113
|
+
let launchCommand = "claude";
|
|
114
|
+
if (launchMode === "ollama") {
|
|
115
|
+
launchCommand = "ollama launch claude --model {model}";
|
|
116
|
+
asker.note("{model} substitutes with each agent's own model: field before spawning — the model asked for next, or per-agent later via \"Customize models per agent?\".");
|
|
117
|
+
}
|
|
118
|
+
else if (launchMode === "custom") {
|
|
119
|
+
launchCommand = await asker.text("Custom launch command", { default: "claude" });
|
|
99
120
|
}
|
|
100
|
-
// Kept short on purpose: TextPromptView renders the label and the
|
|
101
|
-
// live-growing input on one unwrapped terminal row, so a long label
|
|
102
|
-
// desyncs Ink's redraw math the moment label+input exceeds the terminal
|
|
103
|
-
// width (reproduced live: a ~195-char label here produced garbled,
|
|
104
|
-
// overlapping keystrokes). Put anything beyond a one-line question in a
|
|
105
|
-
// note() instead — printed once, never re-rendered.
|
|
106
|
-
asker.note('e.g. "ollama launch claude --model {model}" to route through a wrapper — {model} substitutes per-agent, written to spf.config.yaml\'s env.SPF_CLAUDE_CMD');
|
|
107
|
-
const launchCommand = await asker.text("Launch command for the `claude` CLI", { default: "claude" });
|
|
108
121
|
if (launchCommand !== "claude")
|
|
109
122
|
configEnv["SPF_CLAUDE_CMD"] = launchCommand;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
123
|
+
let defaultModel;
|
|
124
|
+
if (launchMode === "ollama") {
|
|
125
|
+
// Not Claude Code's own alias vocabulary (sonnet/opus/haiku) — under
|
|
126
|
+
// this launcher, `ollama launch`'s OWN --model is what actually picks
|
|
127
|
+
// the served model (see agent_cc.ts's module doc comment), so this
|
|
128
|
+
// has to be a real Ollama tag from `ollama list`.
|
|
129
|
+
defaultModel = await asker.text("Ollama model tag (from `ollama list`)");
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const model = await asker.select("Model (Claude Code's own vocabulary — not provider/model-id)", [
|
|
133
|
+
{ value: "sonnet", label: "sonnet" },
|
|
134
|
+
{ value: "opus", label: "opus" },
|
|
135
|
+
{ value: "haiku", label: "haiku" },
|
|
136
|
+
{ value: "custom", label: "custom — type an exact model name" },
|
|
137
|
+
], "sonnet");
|
|
138
|
+
defaultModel = model === "custom" ? await asker.text("Exact model name") : model;
|
|
139
|
+
}
|
|
140
|
+
defaults.model = defaultModel;
|
|
117
141
|
const auth = await asker.select("Authentication", [
|
|
118
142
|
{ value: "login", label: "already logged in via `claude login`", hint: "writes nothing" },
|
|
119
143
|
{ value: "key", label: "ANTHROPIC_API_KEY" },
|