@entelligentsia/forgecli 0.8.4 → 0.9.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/CHANGELOG.md +53 -0
- package/dist/bin/argv.d.ts +2 -2
- package/dist/bin/argv.js +17 -0
- package/dist/bin/argv.js.map +1 -1
- package/dist/bin/config.d.ts +69 -0
- package/dist/bin/config.js +315 -0
- package/dist/bin/config.js.map +1 -0
- package/dist/bin/doctor.d.ts +1 -0
- package/dist/bin/doctor.js +12 -0
- package/dist/bin/doctor.js.map +1 -1
- package/dist/bin/forge.js +7 -0
- package/dist/bin/forge.js.map +1 -1
- package/dist/extensions/forgecli/config-command.d.ts +8 -0
- package/dist/extensions/forgecli/config-command.js +66 -0
- package/dist/extensions/forgecli/config-command.js.map +1 -0
- package/dist/extensions/forgecli/config-layer.d.ts +38 -0
- package/dist/extensions/forgecli/config-layer.js +68 -0
- package/dist/extensions/forgecli/config-layer.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/component.d.ts +35 -0
- package/dist/extensions/forgecli/config-tui/component.js +236 -0
- package/dist/extensions/forgecli/config-tui/component.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/handler.d.ts +40 -0
- package/dist/extensions/forgecli/config-tui/handler.js +240 -0
- package/dist/extensions/forgecli/config-tui/handler.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/index.d.ts +5 -0
- package/dist/extensions/forgecli/config-tui/index.js +5 -0
- package/dist/extensions/forgecli/config-tui/index.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/keys.d.ts +26 -0
- package/dist/extensions/forgecli/config-tui/keys.js +33 -0
- package/dist/extensions/forgecli/config-tui/keys.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/plugin-config-reader.d.ts +23 -0
- package/dist/extensions/forgecli/config-tui/plugin-config-reader.js +58 -0
- package/dist/extensions/forgecli/config-tui/plugin-config-reader.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/advanced-menu.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js +83 -0
- package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/confirm-quit.d.ts +11 -0
- package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js +54 -0
- package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/override-editor.d.ts +11 -0
- package/dist/extensions/forgecli/config-tui/screens/override-editor.js +233 -0
- package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +91 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list.js +71 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-editor.d.ts +10 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-editor.js +182 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-editor.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-picker.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-picker.js +76 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-picker.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/personas-list.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/personas-list.js +98 -0
- package/dist/extensions/forgecli/config-tui/screens/personas-list.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/shared.d.ts +29 -0
- package/dist/extensions/forgecli/config-tui/screens/shared.js +100 -0
- package/dist/extensions/forgecli/config-tui/screens/shared.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/show-resolved.d.ts +23 -0
- package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +128 -0
- package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-menu.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-menu.js +135 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-menu.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-picker.d.ts +9 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-picker.js +122 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-picker.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/types.d.ts +24 -0
- package/dist/extensions/forgecli/config-tui/screens/types.js +5 -0
- package/dist/extensions/forgecli/config-tui/screens/types.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens.d.ts +24 -0
- package/dist/extensions/forgecli/config-tui/screens.js +78 -0
- package/dist/extensions/forgecli/config-tui/screens.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +11 -0
- package/dist/extensions/forgecli/config-tui/state/buffer.js +91 -0
- package/dist/extensions/forgecli/config-tui/state/buffer.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/constants.d.ts +4 -0
- package/dist/extensions/forgecli/config-tui/state/constants.js +14 -0
- package/dist/extensions/forgecli/config-tui/state/constants.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/index.d.ts +6 -0
- package/dist/extensions/forgecli/config-tui/state/index.js +9 -0
- package/dist/extensions/forgecli/config-tui/state/index.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/init.d.ts +2 -0
- package/dist/extensions/forgecli/config-tui/state/init.js +30 -0
- package/dist/extensions/forgecli/config-tui/state/init.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/model.d.ts +192 -0
- package/dist/extensions/forgecli/config-tui/state/model.js +4 -0
- package/dist/extensions/forgecli/config-tui/state/model.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/reducer.d.ts +2 -0
- package/dist/extensions/forgecli/config-tui/state/reducer.js +212 -0
- package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +91 -0
- package/dist/extensions/forgecli/config-tui/state/selectors.js +231 -0
- package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state.d.ts +6 -0
- package/dist/extensions/forgecli/config-tui/state.js +11 -0
- package/dist/extensions/forgecli/config-tui/state.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/theme.d.ts +37 -0
- package/dist/extensions/forgecli/config-tui/theme.js +88 -0
- package/dist/extensions/forgecli/config-tui/theme.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/tier-meta.d.ts +28 -0
- package/dist/extensions/forgecli/config-tui/tier-meta.js +69 -0
- package/dist/extensions/forgecli/config-tui/tier-meta.js.map +1 -0
- package/dist/extensions/forgecli/config-writer.d.ts +16 -0
- package/dist/extensions/forgecli/config-writer.js +63 -0
- package/dist/extensions/forgecli/config-writer.js.map +1 -0
- package/dist/extensions/forgecli/fix-bug.js +85 -1
- package/dist/extensions/forgecli/fix-bug.js.map +1 -1
- package/dist/extensions/forgecli/forge-cli-schema.json +54 -0
- package/dist/extensions/forgecli/forge-commands.js +3 -8
- package/dist/extensions/forgecli/forge-commands.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.d.ts +13 -0
- package/dist/extensions/forgecli/forge-subagent.js +19 -0
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/index.js +16 -0
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/input-router.d.ts +33 -0
- package/dist/extensions/forgecli/input-router.js +133 -0
- package/dist/extensions/forgecli/input-router.js.map +1 -0
- package/dist/extensions/forgecli/model-resolver.d.ts +32 -0
- package/dist/extensions/forgecli/model-resolver.js +65 -0
- package/dist/extensions/forgecli/model-resolver.js.map +1 -0
- package/dist/extensions/forgecli/model-validator.d.ts +29 -0
- package/dist/extensions/forgecli/model-validator.js +107 -0
- package/dist/extensions/forgecli/model-validator.js.map +1 -0
- package/dist/extensions/forgecli/run-sprint.js +59 -0
- package/dist/extensions/forgecli/run-sprint.js.map +1 -1
- package/dist/extensions/forgecli/run-task.js +93 -1
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/thread-switcher.js +5 -2
- package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
- package/dist/extensions/forgecli/whats-new-widget.js +5 -2
- package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
- package/package.json +11 -3
- package/dist/extensions/forgecli/review-command.d.ts +0 -2
- package/dist/extensions/forgecli/review-command.js +0 -184
- package/dist/extensions/forgecli/review-command.js.map +0 -1
- package/dist/forge-payload/.tools/banners.cjs +0 -435
- package/dist/forge-payload/.tools/build-context-pack.cjs +0 -290
- package/dist/forge-payload/.tools/build-init-context.cjs +0 -322
- package/dist/forge-payload/.tools/build-overlay.cjs +0 -326
- package/dist/forge-payload/.tools/build-persona-pack.cjs +0 -226
- package/dist/forge-payload/.tools/collate.cjs +0 -1041
- package/dist/forge-payload/.tools/generation-manifest.cjs +0 -311
- package/dist/forge-payload/.tools/lib/forge-root.cjs +0 -59
- package/dist/forge-payload/.tools/lib/paths.cjs +0 -29
- package/dist/forge-payload/.tools/lib/pricing.cjs +0 -165
- package/dist/forge-payload/.tools/lib/project-root.cjs +0 -32
- package/dist/forge-payload/.tools/lib/result.js +0 -40
- package/dist/forge-payload/.tools/lib/store-facade.cjs +0 -162
- package/dist/forge-payload/.tools/lib/store-nlp.cjs +0 -250
- package/dist/forge-payload/.tools/lib/store-query-exec.cjs +0 -272
- package/dist/forge-payload/.tools/lib/validate.js +0 -141
- package/dist/forge-payload/.tools/manage-config.cjs +0 -340
- package/dist/forge-payload/.tools/manage-versions.cjs +0 -365
- package/dist/forge-payload/.tools/package.json +0 -3
- package/dist/forge-payload/.tools/parse-gates.cjs +0 -151
- package/dist/forge-payload/.tools/parse-verdict.cjs +0 -67
- package/dist/forge-payload/.tools/preflight-gate.cjs +0 -350
- package/dist/forge-payload/.tools/prompts/sprint-plan-prompt.md +0 -70
- package/dist/forge-payload/.tools/schemas/task-list.schema.json +0 -53
- package/dist/forge-payload/.tools/seed-store.cjs +0 -237
- package/dist/forge-payload/.tools/store-cli.cjs +0 -1226
- package/dist/forge-payload/.tools/store-query.cjs +0 -319
- package/dist/forge-payload/.tools/store.cjs +0 -315
- package/dist/forge-payload/.tools/substitute-placeholders.cjs +0 -625
- package/dist/forge-payload/.tools/validate-store.cjs +0 -593
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// Shared entrypoint for the forge config TUI / show routes.
|
|
2
|
+
//
|
|
3
|
+
// Plan 16 Slice 4a+4b. Both surfaces — `forge config` (bin) and `/forge:config`
|
|
4
|
+
// (in-session pi command) — call into this module.
|
|
5
|
+
//
|
|
6
|
+
// Slice 4a wired: arg parsing, show-route delegation, stub responses for
|
|
7
|
+
// interactive routes.
|
|
8
|
+
// Slice 4b wires: tier-menu and edit-persona routes mount the TUI via
|
|
9
|
+
// cb.ctx.mountConfigTui (supplied by the pi-extension wrapper). The bin path
|
|
10
|
+
// stays non-interactive (no ctx) and prints a friendly fallback.
|
|
11
|
+
import * as fs from "node:fs";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
import { parseConfigArgs, runConfigDispatch, runConfigShow } from "../../../bin/config.js";
|
|
15
|
+
import { loadLayeredConfig } from "../config-layer.js";
|
|
16
|
+
export function parseConfigTuiArgs(args) {
|
|
17
|
+
if (args.length === 0) {
|
|
18
|
+
return { kind: "tier-menu" };
|
|
19
|
+
}
|
|
20
|
+
const [head, ...rest] = args;
|
|
21
|
+
if (head === "show") {
|
|
22
|
+
let resolved = false;
|
|
23
|
+
let json = false;
|
|
24
|
+
for (const flag of rest) {
|
|
25
|
+
if (flag === "--resolved") {
|
|
26
|
+
resolved = true;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (flag === "--json") {
|
|
30
|
+
json = true;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
return { error: `forge config show: unknown flag "${flag}"` };
|
|
34
|
+
}
|
|
35
|
+
return { kind: "show", resolved, json };
|
|
36
|
+
}
|
|
37
|
+
if (head === "dispatch") {
|
|
38
|
+
let json = false;
|
|
39
|
+
let pipeline;
|
|
40
|
+
for (const flag of rest) {
|
|
41
|
+
if (flag === "--json") {
|
|
42
|
+
json = true;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (flag.startsWith("--pipeline=")) {
|
|
46
|
+
pipeline = flag.slice("--pipeline=".length);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
return { error: `forge config dispatch: unknown flag "${flag}"` };
|
|
50
|
+
}
|
|
51
|
+
return { kind: "dispatch", pipeline, json };
|
|
52
|
+
}
|
|
53
|
+
if (head === "edit") {
|
|
54
|
+
const [target, ...editRest] = rest;
|
|
55
|
+
if (target === "persona") {
|
|
56
|
+
const persona = editRest[0];
|
|
57
|
+
if (!persona) {
|
|
58
|
+
return { error: `forge config edit persona: missing persona name` };
|
|
59
|
+
}
|
|
60
|
+
return { kind: "edit-persona", persona };
|
|
61
|
+
}
|
|
62
|
+
if (target === "override") {
|
|
63
|
+
const pipeline = editRest[0];
|
|
64
|
+
const phaseRole = editRest[1];
|
|
65
|
+
if (!pipeline || !phaseRole) {
|
|
66
|
+
return {
|
|
67
|
+
error: `forge config edit override: usage "edit override <pipeline> <phaseRole>"`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return { kind: "edit-override", pipeline, phaseRole };
|
|
71
|
+
}
|
|
72
|
+
return { error: `forge config edit: unknown target "${target ?? ""}" (try "persona" or "override")` };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
error: `forge config: unknown subcommand "${head}". Try: forge config [show [--resolved] [--json] | dispatch [--pipeline=<name>] [--json] | edit persona <name> | edit override <pipeline> <phaseRole>]`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const USAGE_LINES = [
|
|
79
|
+
"Usage:",
|
|
80
|
+
" forge config Open interactive config TUI",
|
|
81
|
+
" forge config show [--resolved] [--json] Print routing config",
|
|
82
|
+
" forge config dispatch [--pipeline=<name>] [--json]",
|
|
83
|
+
" Per-phase dispatch trace (no LLM call)",
|
|
84
|
+
" forge config edit persona <name> Edit a persona-model assignment",
|
|
85
|
+
" forge config edit override <pipeline> <phaseRole>",
|
|
86
|
+
" Edit a per-phase model override",
|
|
87
|
+
];
|
|
88
|
+
// ── Helpers: read catalogues + available models ─────────────────────────────
|
|
89
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
90
|
+
const __dirname = path.dirname(__filename);
|
|
91
|
+
function readPersonaCatalogue() {
|
|
92
|
+
// The compiled handler lives at dist/extensions/forgecli/config-tui/handler.js;
|
|
93
|
+
// the bundled personas dir is at dist/forge-payload/.base-pack/personas/. In
|
|
94
|
+
// source mode (vitest), the source tree's payload may be absent — return [].
|
|
95
|
+
const candidates = [
|
|
96
|
+
path.resolve(__dirname, "..", "..", "..", "forge-payload", ".base-pack", "personas"),
|
|
97
|
+
path.resolve(__dirname, "..", "..", "forge-payload", ".base-pack", "personas"),
|
|
98
|
+
];
|
|
99
|
+
for (const dir of candidates) {
|
|
100
|
+
try {
|
|
101
|
+
return fs
|
|
102
|
+
.readdirSync(dir)
|
|
103
|
+
.filter((f) => f.endsWith(".md") && !f.endsWith("-skills.md"))
|
|
104
|
+
.map((f) => f.replace(/\.md$/, ""));
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
export function readPipelineCatalogue(cwd) {
|
|
113
|
+
// Forge plugin's .forge/config.json doesn't carry `pipelines` in user
|
|
114
|
+
// projects — pipeline definitions live in the plugin install (forgeRoot).
|
|
115
|
+
// So presence of .forge/config.json alone is the "is this a Forge project?"
|
|
116
|
+
// signal. When the file exists but no pipelines key is present, fall back
|
|
117
|
+
// to ["default"] (the canonical 8-phase chain consumed by run-task).
|
|
118
|
+
const forgeCfgPath = path.join(cwd, ".forge", "config.json");
|
|
119
|
+
if (!fs.existsSync(forgeCfgPath))
|
|
120
|
+
return null;
|
|
121
|
+
try {
|
|
122
|
+
const raw = fs.readFileSync(forgeCfgPath, "utf-8");
|
|
123
|
+
const cfg = JSON.parse(raw);
|
|
124
|
+
if (cfg && typeof cfg === "object" && "pipelines" in cfg) {
|
|
125
|
+
const pipelines = cfg.pipelines;
|
|
126
|
+
if (pipelines && typeof pipelines === "object") {
|
|
127
|
+
const keys = Object.keys(pipelines);
|
|
128
|
+
return keys.length > 0 ? keys : ["default"];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return ["default"];
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// File exists but unreadable — still a Forge project; default pipeline applies.
|
|
135
|
+
return ["default"];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function readAvailableModels() {
|
|
139
|
+
// Defer the heavy imports to call-time so vitest specs that never hit this
|
|
140
|
+
// path don't pay the cost (or fail when auth.json is absent).
|
|
141
|
+
const { AuthStorage, ModelRegistry } = await import("@earendil-works/pi-coding-agent");
|
|
142
|
+
try {
|
|
143
|
+
const auth = AuthStorage.create();
|
|
144
|
+
const registry = ModelRegistry.create(auth);
|
|
145
|
+
const available = registry
|
|
146
|
+
.getAvailable()
|
|
147
|
+
.map((m) => ({ provider: m.provider, id: m.id }));
|
|
148
|
+
const authenticated = Array.from(new Set(available.map((m) => m.provider)));
|
|
149
|
+
return { available, authenticated, authError: null };
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
153
|
+
return { available: [], authenticated: [], authError: `Auth discovery failed: ${msg}` };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function buildInitOptions(cwd) {
|
|
157
|
+
const layered = loadLayeredConfig(cwd);
|
|
158
|
+
const personaCatalogue = readPersonaCatalogue();
|
|
159
|
+
const pipelineCatalogue = readPipelineCatalogue(cwd);
|
|
160
|
+
const { available, authenticated, authError } = await readAvailableModels();
|
|
161
|
+
return {
|
|
162
|
+
global: layered.global,
|
|
163
|
+
project: layered.project,
|
|
164
|
+
cwd,
|
|
165
|
+
personaCatalogue,
|
|
166
|
+
pipelineCatalogue,
|
|
167
|
+
availableModels: available,
|
|
168
|
+
authenticatedProviders: authenticated,
|
|
169
|
+
authError: authError ?? undefined,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
// ── Main entry ───────────────────────────────────────────────────────────────
|
|
173
|
+
export async function runConfigTui(args, cwd, cb) {
|
|
174
|
+
const parsed = parseConfigTuiArgs(args);
|
|
175
|
+
const writeErr = cb.writeErr ?? cb.write;
|
|
176
|
+
if ("error" in parsed) {
|
|
177
|
+
writeErr(`${parsed.error}\n`);
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
if (parsed.kind === "show") {
|
|
181
|
+
const showArgs = ["show"];
|
|
182
|
+
if (parsed.resolved)
|
|
183
|
+
showArgs.push("--resolved");
|
|
184
|
+
if (parsed.json)
|
|
185
|
+
showArgs.push("--json");
|
|
186
|
+
const showParsed = parseConfigArgs(showArgs);
|
|
187
|
+
if ("error" in showParsed) {
|
|
188
|
+
writeErr(`${showParsed.error}\n`);
|
|
189
|
+
return 1;
|
|
190
|
+
}
|
|
191
|
+
if (showParsed.subcommand === "usage") {
|
|
192
|
+
for (const line of USAGE_LINES)
|
|
193
|
+
cb.write(`${line}\n`);
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
return runConfigShow(showParsed, cwd, (line) => cb.write(`${line}\n`));
|
|
197
|
+
}
|
|
198
|
+
if (parsed.kind === "dispatch") {
|
|
199
|
+
const dispatchArgs = ["dispatch"];
|
|
200
|
+
if (parsed.json)
|
|
201
|
+
dispatchArgs.push("--json");
|
|
202
|
+
if (parsed.pipeline)
|
|
203
|
+
dispatchArgs.push(`--pipeline=${parsed.pipeline}`);
|
|
204
|
+
const dispatchParsed = parseConfigArgs(dispatchArgs);
|
|
205
|
+
if ("error" in dispatchParsed) {
|
|
206
|
+
writeErr(`${dispatchParsed.error}\n`);
|
|
207
|
+
return 1;
|
|
208
|
+
}
|
|
209
|
+
if (dispatchParsed.subcommand !== "dispatch") {
|
|
210
|
+
writeErr(`forge config dispatch: internal arg-parsing error\n`);
|
|
211
|
+
return 1;
|
|
212
|
+
}
|
|
213
|
+
return runConfigDispatch(dispatchParsed, cwd, (line) => cb.write(`${line}\n`));
|
|
214
|
+
}
|
|
215
|
+
// Interactive routes (tier-menu, edit-persona). edit-override stays a stub
|
|
216
|
+
// until Slice 4c.
|
|
217
|
+
if (parsed.kind === "edit-override") {
|
|
218
|
+
if (cb.ctx) {
|
|
219
|
+
cb.ctx.notify(`forge config: per-phase override editor lands in slice 4c.`, "info");
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
writeErr(`forge config: per-phase override editor lands in slice 4c.\n`);
|
|
223
|
+
return 1;
|
|
224
|
+
}
|
|
225
|
+
if (parsed.kind === "tier-menu" || parsed.kind === "edit-persona") {
|
|
226
|
+
if (!cb.ctx?.mountConfigTui) {
|
|
227
|
+
// Non-interactive surface (bin without a pi session).
|
|
228
|
+
for (const line of USAGE_LINES)
|
|
229
|
+
cb.write(`${line}\n`);
|
|
230
|
+
cb.write(`\n`);
|
|
231
|
+
cb.write(`Interactive TUI requires a pi session. Use \`/forge:config\` from inside pi.\n`);
|
|
232
|
+
return 0;
|
|
233
|
+
}
|
|
234
|
+
const init = await buildInitOptions(cwd);
|
|
235
|
+
return cb.ctx.mountConfigTui(init);
|
|
236
|
+
}
|
|
237
|
+
// Exhaustiveness — TS treats parsed as `never` here
|
|
238
|
+
return 1;
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createConfigTuiComponent, type ConfigTuiComponentOptions } from "./component.js";
|
|
2
|
+
export type { ConfigLayer } from "../config-writer.js";
|
|
3
|
+
export type { View, ConfigBuffer, AvailableModel, InitOptions, ConfigTuiState, ConfigTuiAction, PhaseOverride, ResolvedPersonaEntry, PersonaPickerEntry, PipelineOverrideSummary, TierAssignment, } from "./state/model.js";
|
|
4
|
+
export { CANONICAL_PHASES, initialState, reducer, getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, isConfigEmpty, personaSourceLabel, } from "./state.js";
|
|
5
|
+
export type { InputResult, Screen } from "./screens/types.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Config-TUI public re-exports.
|
|
2
|
+
// Phase 3: theming + width safety + data-driven menus + auth error surfacing.
|
|
3
|
+
export { createConfigTuiComponent } from "./component.js";
|
|
4
|
+
export { CANONICAL_PHASES, initialState, reducer, getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, isConfigEmpty, personaSourceLabel, } from "./state.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,8EAA8E;AAE9E,OAAO,EAAE,wBAAwB,EAAkC,MAAM,gBAAgB,CAAC;AAkB1F,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,aAAa,EACb,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EACf,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const KEY_BINDINGS: {
|
|
2
|
+
/** Navigate up / previous item */
|
|
3
|
+
readonly NAV_UP: "k";
|
|
4
|
+
/** Navigate down / next item */
|
|
5
|
+
readonly NAV_DOWN: "j";
|
|
6
|
+
/** Confirm / open */
|
|
7
|
+
readonly CONFIRM: "1";
|
|
8
|
+
/** Quit the TUI */
|
|
9
|
+
readonly QUIT: "q";
|
|
10
|
+
/** Confirm quit (y) */
|
|
11
|
+
readonly QUIT_CONFIRM: "y";
|
|
12
|
+
/** Cancel quit / go back (n) */
|
|
13
|
+
readonly QUIT_CANCEL: "n";
|
|
14
|
+
/** New persona */
|
|
15
|
+
readonly NEW: "n";
|
|
16
|
+
/** Delete */
|
|
17
|
+
readonly DELETE: "d";
|
|
18
|
+
/** Select project layer */
|
|
19
|
+
readonly LAYER_PROJECT: "p";
|
|
20
|
+
/** Select global layer */
|
|
21
|
+
readonly LAYER_GLOBAL: "g";
|
|
22
|
+
/** Show resolved */
|
|
23
|
+
readonly RESOLVED: "r";
|
|
24
|
+
/** Space key (for clearing overrides) */
|
|
25
|
+
readonly SPACE: " ";
|
|
26
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Shared key-binding constants for config-TUI screens.
|
|
2
|
+
// Phase 2: centralises key names used across screen modules.
|
|
3
|
+
//
|
|
4
|
+
// All key-matching goes through pi-tui's `matchesKey` for terminal
|
|
5
|
+
// escape-sequence compatibility; this file provides the semantic aliases
|
|
6
|
+
// that screens use to avoid scattering raw string literals.
|
|
7
|
+
export const KEY_BINDINGS = {
|
|
8
|
+
/** Navigate up / previous item */
|
|
9
|
+
NAV_UP: "k",
|
|
10
|
+
/** Navigate down / next item */
|
|
11
|
+
NAV_DOWN: "j",
|
|
12
|
+
/** Confirm / open */
|
|
13
|
+
CONFIRM: "1",
|
|
14
|
+
/** Quit the TUI */
|
|
15
|
+
QUIT: "q",
|
|
16
|
+
/** Confirm quit (y) */
|
|
17
|
+
QUIT_CONFIRM: "y",
|
|
18
|
+
/** Cancel quit / go back (n) */
|
|
19
|
+
QUIT_CANCEL: "n",
|
|
20
|
+
/** New persona */
|
|
21
|
+
NEW: "n",
|
|
22
|
+
/** Delete */
|
|
23
|
+
DELETE: "d",
|
|
24
|
+
/** Select project layer */
|
|
25
|
+
LAYER_PROJECT: "p",
|
|
26
|
+
/** Select global layer */
|
|
27
|
+
LAYER_GLOBAL: "g",
|
|
28
|
+
/** Show resolved */
|
|
29
|
+
RESOLVED: "r",
|
|
30
|
+
/** Space key (for clearing overrides) */
|
|
31
|
+
SPACE: " ",
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/keys.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,6DAA6D;AAC7D,EAAE;AACF,mEAAmE;AACnE,yEAAyE;AACzE,4DAA4D;AAE5D,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,kCAAkC;IAClC,MAAM,EAAE,GAAY;IACpB,gCAAgC;IAChC,QAAQ,EAAE,GAAY;IACtB,qBAAqB;IACrB,OAAO,EAAE,GAAY;IACrB,mBAAmB;IACnB,IAAI,EAAE,GAAY;IAClB,uBAAuB;IACvB,YAAY,EAAE,GAAY;IAC1B,gCAAgC;IAChC,WAAW,EAAE,GAAY;IACzB,kBAAkB;IAClB,GAAG,EAAE,GAAY;IACjB,aAAa;IACb,MAAM,EAAE,GAAY;IACpB,2BAA2B;IAC3B,aAAa,EAAE,GAAY;IAC3B,0BAA0B;IAC1B,YAAY,EAAE,GAAY;IAC1B,oBAAoB;IACpB,QAAQ,EAAE,GAAY;IACtB,yCAAyC;IACzC,KAAK,EAAE,GAAY;CACX,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PluginConfigPaths {
|
|
2
|
+
engineering?: string;
|
|
3
|
+
store?: string;
|
|
4
|
+
workflows?: string;
|
|
5
|
+
commands?: string;
|
|
6
|
+
templates?: string;
|
|
7
|
+
customCommands?: string;
|
|
8
|
+
forgeRoot?: string;
|
|
9
|
+
forgeRef?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PluginConfigSummary {
|
|
12
|
+
version: string | null;
|
|
13
|
+
projectName: string | null;
|
|
14
|
+
projectPrefix: string | null;
|
|
15
|
+
paths: PluginConfigPaths;
|
|
16
|
+
installedSkills: string[];
|
|
17
|
+
forgeRef: string | null;
|
|
18
|
+
/** Legacy 'mode' field if present in config.json; otherwise null. */
|
|
19
|
+
mode: string | null;
|
|
20
|
+
/** True iff `mode` is present (retired field; rendered as "(legacy)"). */
|
|
21
|
+
modeLegacy: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function readPluginConfig(cwd: string): PluginConfigSummary | null;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Read-only loader for the Forge plugin's `.forge/config.json`.
|
|
2
|
+
//
|
|
3
|
+
// Plan 16 Slice 4a: the config TUI needs to render a read-only summary of the
|
|
4
|
+
// installed Forge plugin (version, paths, installed skills) alongside the
|
|
5
|
+
// forge-cli routing config it edits. This module never mutates `.forge/`.
|
|
6
|
+
//
|
|
7
|
+
// The legacy `mode` field (fast/full) is retired (see memory
|
|
8
|
+
// project_fast_full_mode_retired). When present, we surface it as
|
|
9
|
+
// modeLegacy=true so the TUI can render it as "(legacy)" without offering to
|
|
10
|
+
// change it.
|
|
11
|
+
import * as fs from "node:fs";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
export function readPluginConfig(cwd) {
|
|
14
|
+
const configPath = path.join(cwd, ".forge", "config.json");
|
|
15
|
+
let raw;
|
|
16
|
+
try {
|
|
17
|
+
raw = fs.readFileSync(configPath, "utf-8");
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = JSON.parse(raw);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
30
|
+
return null;
|
|
31
|
+
const obj = parsed;
|
|
32
|
+
const project = (obj.project ?? null);
|
|
33
|
+
const paths = (obj.paths ?? {});
|
|
34
|
+
const installedSkills = Array.isArray(obj.installedSkills)
|
|
35
|
+
? obj.installedSkills.filter((s) => typeof s === "string")
|
|
36
|
+
: [];
|
|
37
|
+
const mode = typeof obj.mode === "string" ? obj.mode : null;
|
|
38
|
+
return {
|
|
39
|
+
version: typeof obj.version === "string" ? obj.version : null,
|
|
40
|
+
projectName: typeof project?.name === "string" ? project.name : null,
|
|
41
|
+
projectPrefix: typeof project?.prefix === "string" ? project.prefix : null,
|
|
42
|
+
paths: {
|
|
43
|
+
engineering: typeof paths.engineering === "string" ? paths.engineering : undefined,
|
|
44
|
+
store: typeof paths.store === "string" ? paths.store : undefined,
|
|
45
|
+
workflows: typeof paths.workflows === "string" ? paths.workflows : undefined,
|
|
46
|
+
commands: typeof paths.commands === "string" ? paths.commands : undefined,
|
|
47
|
+
templates: typeof paths.templates === "string" ? paths.templates : undefined,
|
|
48
|
+
customCommands: typeof paths.customCommands === "string" ? paths.customCommands : undefined,
|
|
49
|
+
forgeRoot: typeof paths.forgeRoot === "string" ? paths.forgeRoot : undefined,
|
|
50
|
+
forgeRef: typeof paths.forgeRef === "string" ? paths.forgeRef : undefined,
|
|
51
|
+
},
|
|
52
|
+
installedSkills,
|
|
53
|
+
forgeRef: typeof paths.forgeRef === "string" ? paths.forgeRef : null,
|
|
54
|
+
mode,
|
|
55
|
+
modeLegacy: mode !== null,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=plugin-config-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-config-reader.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/plugin-config-reader.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAC1E,0EAA0E;AAC1E,EAAE;AACF,6DAA6D;AAC7D,kEAAkE;AAClE,6EAA6E;AAC7E,aAAa;AAEb,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AA0BlC,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAE3D,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/D,MAAM,GAAG,GAAG,MAAiC,CAAC;IAE9C,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAmC,CAAC;IACxE,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;IAC3D,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QACxD,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QACvE,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAE5D,OAAO;QACL,OAAO,EAAE,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QAC7D,WAAW,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,OAAO,CAAC,IAAe,CAAC,CAAC,CAAC,IAAI;QAChF,aAAa,EAAE,OAAO,OAAO,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAE,OAAO,CAAC,MAAiB,CAAC,CAAC,CAAC,IAAI;QACtF,KAAK,EAAE;YACL,WAAW,EAAE,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,WAAsB,CAAC,CAAC,CAAC,SAAS;YAC9F,KAAK,EAAE,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,KAAgB,CAAC,CAAC,CAAC,SAAS;YAC5E,SAAS,EAAE,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,SAAoB,CAAC,CAAC,CAAC,SAAS;YACxF,QAAQ,EAAE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,QAAmB,CAAC,CAAC,CAAC,SAAS;YACrF,SAAS,EAAE,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,SAAoB,CAAC,CAAC,CAAC,SAAS;YACxF,cAAc,EACZ,OAAO,KAAK,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,cAAyB,CAAC,CAAC,CAAC,SAAS;YACzF,SAAS,EAAE,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,SAAoB,CAAC,CAAC,CAAC,SAAS;YACxF,QAAQ,EAAE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,QAAmB,CAAC,CAAC,CAAC,SAAS;SACtF;QACD,eAAe;QACf,QAAQ,EAAE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,QAAmB,CAAC,CAAC,CAAC,IAAI;QAChF,IAAI;QACJ,UAAU,EAAE,IAAI,KAAK,IAAI;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConfigTuiState } from "../state/model.js";
|
|
2
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { InputResult, Screen } from "./types.js";
|
|
4
|
+
export declare class AdvancedMenuScreen implements Screen {
|
|
5
|
+
render(state: ConfigTuiState, width: number, theme: Theme): string[];
|
|
6
|
+
handleInput(data: string, state: ConfigTuiState): InputResult;
|
|
7
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Advanced-menu screen — hub for per-persona / per-step overrides.
|
|
2
|
+
// Phase D: routes to existing personas-list and overrides-list-pipelines
|
|
3
|
+
// with explanation banners and plain-English headings.
|
|
4
|
+
// Reached only from the tier-menu's "Advanced" row — the user has to
|
|
5
|
+
// actively opt in to see these.
|
|
6
|
+
import { Key, matchesKey } from "@earendil-works/pi-tui";
|
|
7
|
+
import { getActiveView } from "../state/selectors.js";
|
|
8
|
+
import { rule, safeLines } from "./shared.js";
|
|
9
|
+
import { cursor, accentBold, muted, dirtyMarker } from "../theme.js";
|
|
10
|
+
/** Interactive row count: 3 items. */
|
|
11
|
+
const ITEM_COUNT = 3;
|
|
12
|
+
export class AdvancedMenuScreen {
|
|
13
|
+
render(state, width, theme) {
|
|
14
|
+
const view = getActiveView(state);
|
|
15
|
+
if (view.kind !== "advanced-menu") {
|
|
16
|
+
return ["(advanced-menu called with wrong active view)"];
|
|
17
|
+
}
|
|
18
|
+
const cursorIdx = view.cursor;
|
|
19
|
+
const lines = [];
|
|
20
|
+
// ── Header ─────────────────────────────────────────────────────────
|
|
21
|
+
lines.push(accentBold("forge config › advanced", theme));
|
|
22
|
+
lines.push(rule(width, theme));
|
|
23
|
+
// ── Explanation banner ─────────────────────────────────────────────
|
|
24
|
+
lines.push(muted("Most users don't need these. The three tier knobs above", theme));
|
|
25
|
+
lines.push(muted("cover the 80% path. Use these if you need fine-grained", theme));
|
|
26
|
+
lines.push(muted("control over a specific persona or step.", theme));
|
|
27
|
+
lines.push("");
|
|
28
|
+
// ── Menu items ─────────────────────────────────────────────────────
|
|
29
|
+
const items = [
|
|
30
|
+
"Override one persona's model",
|
|
31
|
+
"Override one step's model",
|
|
32
|
+
"Edit raw persona-models entries",
|
|
33
|
+
];
|
|
34
|
+
for (let i = 0; i < items.length; i++) {
|
|
35
|
+
const cur = cursor(i === cursorIdx, theme);
|
|
36
|
+
lines.push(` ${cur} ${items[i]}`);
|
|
37
|
+
}
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push(muted(" esc back q quit", theme));
|
|
40
|
+
if (state.dirty)
|
|
41
|
+
lines.push(` ${dirtyMarker(theme)}`);
|
|
42
|
+
return safeLines(lines, width);
|
|
43
|
+
}
|
|
44
|
+
handleInput(data, state) {
|
|
45
|
+
const view = getActiveView(state);
|
|
46
|
+
if (view.kind !== "advanced-menu")
|
|
47
|
+
return { kind: "no-op" };
|
|
48
|
+
// ── Navigation ──────────────────────────────────────────────────────
|
|
49
|
+
if (matchesKey(data, Key.up) || matchesKey(data, "k")) {
|
|
50
|
+
return { kind: "dispatch", action: { kind: "cursor-move", delta: -1 } };
|
|
51
|
+
}
|
|
52
|
+
if (matchesKey(data, Key.down) || matchesKey(data, "j")) {
|
|
53
|
+
if (view.cursor < ITEM_COUNT - 1) {
|
|
54
|
+
return { kind: "dispatch", action: { kind: "cursor-move", delta: 1 } };
|
|
55
|
+
}
|
|
56
|
+
return { kind: "consumed" };
|
|
57
|
+
}
|
|
58
|
+
// ── Enter: act on current cursor position ─────────────────────────
|
|
59
|
+
if (matchesKey(data, Key.enter)) {
|
|
60
|
+
if (view.cursor === 0) {
|
|
61
|
+
// "Override one persona's model" → personas-list
|
|
62
|
+
return { kind: "dispatch", action: { kind: "push-view", view: { kind: "personas-list", cursor: 0 } } };
|
|
63
|
+
}
|
|
64
|
+
if (view.cursor === 1) {
|
|
65
|
+
// "Override one step's model" → overrides-list-pipelines
|
|
66
|
+
return { kind: "dispatch", action: { kind: "push-view", view: { kind: "overrides-list-pipelines", cursor: 0 } } };
|
|
67
|
+
}
|
|
68
|
+
if (view.cursor === 2) {
|
|
69
|
+
// "Edit raw persona-models entries" → persona-picker
|
|
70
|
+
return { kind: "dispatch", action: { kind: "push-view", view: { kind: "persona-picker", cursor: 0 } } };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// ── Shortcuts ──────────────────────────────────────────────────────
|
|
74
|
+
if (matchesKey(data, "1"))
|
|
75
|
+
return { kind: "dispatch", action: { kind: "push-view", view: { kind: "personas-list", cursor: 0 } } };
|
|
76
|
+
if (matchesKey(data, "2"))
|
|
77
|
+
return { kind: "dispatch", action: { kind: "push-view", view: { kind: "overrides-list-pipelines", cursor: 0 } } };
|
|
78
|
+
if (matchesKey(data, "3"))
|
|
79
|
+
return { kind: "dispatch", action: { kind: "push-view", view: { kind: "persona-picker", cursor: 0 } } };
|
|
80
|
+
return { kind: "no-op" };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=advanced-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advanced-menu.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/screens/advanced-menu.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConfigTuiState } from "../state/model.js";
|
|
2
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { InputResult, Screen } from "./types.js";
|
|
4
|
+
export declare class ConfirmQuitScreen implements Screen {
|
|
5
|
+
render(state: ConfigTuiState, width: number, theme: Theme): string[];
|
|
6
|
+
handleInput(data: string, _state: ConfigTuiState): InputResult;
|
|
7
|
+
}
|
|
8
|
+
/** Render the save banner (non-interactive decoration). Kept as a plain function
|
|
9
|
+
* since it has no input handling — the orchestrator appends it after the active
|
|
10
|
+
* screen's render output. */
|
|
11
|
+
export declare function renderSaveBanner(state: ConfigTuiState, _width: number, theme: Theme): string[];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Confirm-quit overlay — renders and handles input for the quit-confirmation dialog.
|
|
2
|
+
// Phase 3: themed adaptive-width dialog using DynamicBorder, width safety.
|
|
3
|
+
import { DynamicBorder } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { Key, matchesKey } from "@earendil-works/pi-tui";
|
|
5
|
+
import { success, muted, error as themedError } from "../theme.js";
|
|
6
|
+
export class ConfirmQuitScreen {
|
|
7
|
+
render(state, width, theme) {
|
|
8
|
+
if (!state.confirmQuit)
|
|
9
|
+
return [];
|
|
10
|
+
// Adaptive-width confirm dialog, min 50, max terminal width - 4.
|
|
11
|
+
const dialogWidth = Math.max(50, Math.min(width - 4, 70));
|
|
12
|
+
const lines = [];
|
|
13
|
+
lines.push("");
|
|
14
|
+
// Themed border top
|
|
15
|
+
lines.push(...new DynamicBorder((s) => theme.fg("borderAccent", s)).render(dialogWidth));
|
|
16
|
+
// Dialog content
|
|
17
|
+
const bgFn = (s) => theme.bg("selectedBg", s);
|
|
18
|
+
const contentLines = [
|
|
19
|
+
themedError(" Unsaved changes — discard and quit?", theme),
|
|
20
|
+
"",
|
|
21
|
+
` ${muted("y / enter", theme)} — ${muted("discard and quit", theme)}`,
|
|
22
|
+
` ${muted("n / esc", theme)} — ${muted("cancel (stay in TUI)", theme)}`,
|
|
23
|
+
];
|
|
24
|
+
// Pad content lines to fill dialog width with themed background
|
|
25
|
+
for (const line of contentLines) {
|
|
26
|
+
const padLen = Math.max(0, dialogWidth - line.length);
|
|
27
|
+
lines.push(bgFn(line + " ".repeat(padLen)));
|
|
28
|
+
}
|
|
29
|
+
// Themed border bottom
|
|
30
|
+
lines.push(...new DynamicBorder((s) => theme.fg("borderAccent", s)).render(dialogWidth));
|
|
31
|
+
return lines;
|
|
32
|
+
}
|
|
33
|
+
handleInput(data, _state) {
|
|
34
|
+
if (matchesKey(data, "y") || matchesKey(data, Key.enter)) {
|
|
35
|
+
return { kind: "dispatch", action: { kind: "confirm-quit", discard: true } };
|
|
36
|
+
}
|
|
37
|
+
if (matchesKey(data, "n") || matchesKey(data, Key.escape)) {
|
|
38
|
+
return { kind: "dispatch", action: { kind: "confirm-quit", discard: false } };
|
|
39
|
+
}
|
|
40
|
+
return { kind: "no-op" };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Render the save banner (non-interactive decoration). Kept as a plain function
|
|
44
|
+
* since it has no input handling — the orchestrator appends it after the active
|
|
45
|
+
* screen's render output. */
|
|
46
|
+
export function renderSaveBanner(state, _width, theme) {
|
|
47
|
+
if (!state.lastSaved)
|
|
48
|
+
return [];
|
|
49
|
+
return [
|
|
50
|
+
"",
|
|
51
|
+
success(` ✓ Saved → ${state.lastSaved.target} (${state.lastSaved.layer})`, theme),
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=confirm-quit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm-quit.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/screens/confirm-quit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConfigTuiState } from "../state/model.js";
|
|
2
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { InputResult, Screen } from "./types.js";
|
|
4
|
+
export declare class OverrideEditorScreen implements Screen {
|
|
5
|
+
render(state: ConfigTuiState, width: number, theme: Theme): string[];
|
|
6
|
+
handleInput(data: string, state: ConfigTuiState): InputResult;
|
|
7
|
+
private handlePickTypeInput;
|
|
8
|
+
private handlePickNameInput;
|
|
9
|
+
private handlePickProviderInput;
|
|
10
|
+
private handlePickModelInput;
|
|
11
|
+
}
|