@entelligentsia/forgecli 0.8.4 → 0.9.1
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 +61 -0
- package/README.md +165 -2
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"config-layer.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/config-layer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Component, Focusable } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { type InitOptions } from "./state.js";
|
|
4
|
+
export interface ConfigTuiComponentOptions extends InitOptions {
|
|
5
|
+
/** Called by the component when the user has quit (with discard or via clean exit). */
|
|
6
|
+
onExit: (exitCode: number) => void;
|
|
7
|
+
/** Called when a write to disk completes successfully — surfaces "saved to X". */
|
|
8
|
+
onSaved?: (target: string) => void;
|
|
9
|
+
/** Called on write failure — surfaces the error to the parent ctx. */
|
|
10
|
+
onError?: (message: string) => void;
|
|
11
|
+
/** Optional invalidate hook supplied by the TUI driver (forces re-render). */
|
|
12
|
+
requestRender?: () => void;
|
|
13
|
+
/** pi TUI theme — drives all colour choices inside the overlay. */
|
|
14
|
+
theme: Theme;
|
|
15
|
+
}
|
|
16
|
+
export declare class ConfigTuiComponent implements Component, Focusable {
|
|
17
|
+
private state;
|
|
18
|
+
private readonly opts;
|
|
19
|
+
/** Focusable — pi sets this to true when the overlay has keyboard focus.
|
|
20
|
+
* Without this, arrow keys don't route to handleInput (see commit 07e886f). */
|
|
21
|
+
focused: boolean;
|
|
22
|
+
/** Timer handle for the auto-clearing save banner (guards against unmount). */
|
|
23
|
+
private clearStatusTimer?;
|
|
24
|
+
constructor(opts: ConfigTuiComponentOptions);
|
|
25
|
+
invalidate(): void;
|
|
26
|
+
render(width: number): string[];
|
|
27
|
+
handleInput(data: string): void;
|
|
28
|
+
private handleResult;
|
|
29
|
+
private dispatch;
|
|
30
|
+
private maybeExit;
|
|
31
|
+
private maybePersist;
|
|
32
|
+
/** Schedule save-banner auto-clear. Guards against unmount (Hard Rule 5). */
|
|
33
|
+
private scheduleClearStatus;
|
|
34
|
+
}
|
|
35
|
+
export declare function createConfigTuiComponent(opts: ConfigTuiComponentOptions): ConfigTuiComponent;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// Composite Component that drives the config TUI.
|
|
2
|
+
//
|
|
3
|
+
// Phase 2: thin orchestrator that delegates render and handleInput to the
|
|
4
|
+
// active Screen implementation. The Component & Focusable impl stays here;
|
|
5
|
+
// per-view logic moved into screens/*.ts modules.
|
|
6
|
+
//
|
|
7
|
+
// The component composes:
|
|
8
|
+
// - state/ reducer (single source of truth)
|
|
9
|
+
// - screens/* renderers + input handlers (delegated via Screen interface)
|
|
10
|
+
// - config-writer.ts for atomic persistence on commit-persona-edit
|
|
11
|
+
import * as fs from "node:fs";
|
|
12
|
+
import { Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
13
|
+
import { DynamicBorder } from "@earendil-works/pi-coding-agent";
|
|
14
|
+
import { writeRoutingConfig } from "../config-writer.js";
|
|
15
|
+
import { getActiveView, initialState, reducer, } from "./state.js";
|
|
16
|
+
import { AdvancedMenuScreen } from "./screens/advanced-menu.js";
|
|
17
|
+
import { TierMenuScreen } from "./screens/tier-menu.js";
|
|
18
|
+
import { TierPickerScreen } from "./screens/tier-picker.js";
|
|
19
|
+
import { ConfirmQuitScreen, renderSaveBanner } from "./screens/confirm-quit.js";
|
|
20
|
+
import { PersonasListScreen } from "./screens/personas-list.js";
|
|
21
|
+
import { PersonaPickerScreen } from "./screens/persona-picker.js";
|
|
22
|
+
import { PersonaEditorScreen } from "./screens/persona-editor.js";
|
|
23
|
+
import { ShowResolvedScreen } from "./screens/show-resolved.js";
|
|
24
|
+
import { OverridesListPipelinesScreen } from "./screens/overrides-list.js";
|
|
25
|
+
import { OverridesListPhasesScreen } from "./screens/overrides-list-phases.js";
|
|
26
|
+
import { OverrideEditorScreen } from "./screens/override-editor.js";
|
|
27
|
+
function debugLog(line) {
|
|
28
|
+
if (process.env.FORGE_DEBUG_INPUT !== "1")
|
|
29
|
+
return;
|
|
30
|
+
try {
|
|
31
|
+
const ts = new Date().toISOString();
|
|
32
|
+
const path = process.env.FORGE_DEBUG_INPUT_LOG ?? "/tmp/forge-input-router.log";
|
|
33
|
+
fs.appendFileSync(path, `${ts} [config-tui] ${line}\n`);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
/* swallow */
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function hexEscape(s) {
|
|
40
|
+
return [...s]
|
|
41
|
+
.map((c) => {
|
|
42
|
+
const cp = c.codePointAt(0);
|
|
43
|
+
if (cp >= 0x20 && cp <= 0x7e)
|
|
44
|
+
return c;
|
|
45
|
+
return `\\x${cp.toString(16).padStart(2, "0")}`;
|
|
46
|
+
})
|
|
47
|
+
.join("");
|
|
48
|
+
}
|
|
49
|
+
// ── Screen factory ──────────────────────────────────────────────────────────
|
|
50
|
+
const SCREEN_INSTANCES = {
|
|
51
|
+
"confirm-quit": new ConfirmQuitScreen(),
|
|
52
|
+
"tier-menu": new TierMenuScreen(),
|
|
53
|
+
"tier-picker": new TierPickerScreen(),
|
|
54
|
+
"advanced-menu": new AdvancedMenuScreen(),
|
|
55
|
+
"personas-list": new PersonasListScreen(),
|
|
56
|
+
"persona-picker": new PersonaPickerScreen(),
|
|
57
|
+
"persona-editor": new PersonaEditorScreen(),
|
|
58
|
+
"show-resolved": new ShowResolvedScreen(),
|
|
59
|
+
"overrides-list-pipelines": new OverridesListPipelinesScreen(),
|
|
60
|
+
"overrides-list-phases": new OverridesListPhasesScreen(),
|
|
61
|
+
"override-editor": new OverrideEditorScreen(),
|
|
62
|
+
};
|
|
63
|
+
function createScreen(view) {
|
|
64
|
+
return SCREEN_INSTANCES[view.kind] ?? SCREEN_INSTANCES["tier-menu"];
|
|
65
|
+
}
|
|
66
|
+
// ── Hard Rule 4: Explicit layer-to-action mapping ──────────────────────────
|
|
67
|
+
function persistLayerForAction(action) {
|
|
68
|
+
switch (action.kind) {
|
|
69
|
+
case "commit-tier-model": return action.layer;
|
|
70
|
+
case "commit-persona-edit": return action.layer;
|
|
71
|
+
case "delete-persona-entry": return action.layer;
|
|
72
|
+
case "commit-override-name": return "project"; // L4 lives on project only
|
|
73
|
+
case "commit-override-inline": return "project"; // L4 lives on project only
|
|
74
|
+
case "clear-phase-override": return "project"; // L4 lives on project only
|
|
75
|
+
default: return undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export class ConfigTuiComponent {
|
|
79
|
+
state;
|
|
80
|
+
opts;
|
|
81
|
+
/** Focusable — pi sets this to true when the overlay has keyboard focus.
|
|
82
|
+
* Without this, arrow keys don't route to handleInput (see commit 07e886f). */
|
|
83
|
+
focused = false;
|
|
84
|
+
/** Timer handle for the auto-clearing save banner (guards against unmount). */
|
|
85
|
+
clearStatusTimer;
|
|
86
|
+
constructor(opts) {
|
|
87
|
+
this.opts = opts;
|
|
88
|
+
this.state = initialState(opts);
|
|
89
|
+
}
|
|
90
|
+
invalidate() {
|
|
91
|
+
// Stateless renderer; no cache to drop. (Hard Rule 3: no render caching.)
|
|
92
|
+
}
|
|
93
|
+
render(width) {
|
|
94
|
+
const theme = this.opts.theme;
|
|
95
|
+
const view = getActiveView(this.state);
|
|
96
|
+
// Delegate rendering to the active screen (or confirm-quit overlay).
|
|
97
|
+
let contentLines;
|
|
98
|
+
if (this.state.confirmQuit) {
|
|
99
|
+
// show the underlying screen plus the confirm-quit overlay
|
|
100
|
+
const screen = createScreen(view);
|
|
101
|
+
const baseLines = screen.render(this.state, width, theme);
|
|
102
|
+
const quitLines = SCREEN_INSTANCES["confirm-quit"].render(this.state, width, theme);
|
|
103
|
+
contentLines = [...baseLines, ...renderSaveBanner(this.state, width, theme), ...quitLines];
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const screen = createScreen(view);
|
|
107
|
+
contentLines = [
|
|
108
|
+
...screen.render(this.state, width, theme),
|
|
109
|
+
...renderSaveBanner(this.state, width, theme),
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
// ── Modal frame ────────────────────────────────────────────────────
|
|
113
|
+
const bgFn = (s) => theme.bg("selectedBg", s);
|
|
114
|
+
const lines = [];
|
|
115
|
+
// Top border
|
|
116
|
+
lines.push(...new DynamicBorder((s) => theme.fg("borderAccent", s)).render(width));
|
|
117
|
+
// Content: each line padded to full width so the background colour fills
|
|
118
|
+
// the entire row. visibleWidth correctly ignores ANSI codes added by theme.
|
|
119
|
+
// truncateToWidth ensures no line exceeds the terminal width.
|
|
120
|
+
for (const line of contentLines) {
|
|
121
|
+
const truncated = truncateToWidth(line, width, "");
|
|
122
|
+
const vis = visibleWidth(truncated);
|
|
123
|
+
const padded = vis < width ? truncated + " ".repeat(width - vis) : truncated;
|
|
124
|
+
lines.push(bgFn(padded));
|
|
125
|
+
}
|
|
126
|
+
// Bottom border
|
|
127
|
+
lines.push(...new DynamicBorder((s) => theme.fg("borderAccent", s)).render(width));
|
|
128
|
+
return lines;
|
|
129
|
+
}
|
|
130
|
+
handleInput(data) {
|
|
131
|
+
debugLog(`handleInput IN data="${hexEscape(data)}" focused=${this.focused} view=${getActiveView(this.state).kind}`);
|
|
132
|
+
if (this.state.shouldExit) {
|
|
133
|
+
debugLog(`handleInput RETURN (shouldExit)`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Universal: q always requests quit
|
|
137
|
+
if (matchesKey(data, "q")) {
|
|
138
|
+
this.dispatch({ kind: "request-quit" });
|
|
139
|
+
this.maybeExit();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// confirmQuit modal hijacks subsequent input
|
|
143
|
+
if (this.state.confirmQuit) {
|
|
144
|
+
const result = SCREEN_INSTANCES["confirm-quit"].handleInput(data, this.state);
|
|
145
|
+
this.handleResult(result);
|
|
146
|
+
// After confirm-quit, check if we should exit
|
|
147
|
+
this.maybeExit();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (matchesKey(data, Key.escape)) {
|
|
151
|
+
this.dispatch({ kind: "pop-view" });
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Delegate to the active screen's handleInput
|
|
155
|
+
const view = getActiveView(this.state);
|
|
156
|
+
const screen = createScreen(view);
|
|
157
|
+
const result = screen.handleInput(data, this.state);
|
|
158
|
+
this.handleResult(result);
|
|
159
|
+
}
|
|
160
|
+
// ── Result dispatcher ─────────────────────────────────────────────────────
|
|
161
|
+
handleResult(result) {
|
|
162
|
+
switch (result.kind) {
|
|
163
|
+
case "dispatch":
|
|
164
|
+
this.dispatch(result.action);
|
|
165
|
+
this.maybePersist(result.action);
|
|
166
|
+
break;
|
|
167
|
+
case "dispatch-seq":
|
|
168
|
+
for (const action of result.actions) {
|
|
169
|
+
this.dispatch(action);
|
|
170
|
+
}
|
|
171
|
+
// Persist the last action (the one that triggers the write)
|
|
172
|
+
if (result.actions.length > 0) {
|
|
173
|
+
this.maybePersist(result.actions[result.actions.length - 1]);
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
case "pop":
|
|
177
|
+
this.dispatch({ kind: "pop-view" });
|
|
178
|
+
break;
|
|
179
|
+
case "quit":
|
|
180
|
+
this.dispatch({ kind: "request-quit" });
|
|
181
|
+
this.maybeExit();
|
|
182
|
+
break;
|
|
183
|
+
case "error":
|
|
184
|
+
this.opts.onError?.(result.message);
|
|
185
|
+
this.opts.requestRender?.();
|
|
186
|
+
break;
|
|
187
|
+
case "consumed":
|
|
188
|
+
this.opts.requestRender?.();
|
|
189
|
+
break;
|
|
190
|
+
case "no-op":
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// ── Dispatcher helpers ────────────────────────────────────────────────────
|
|
195
|
+
dispatch(action) {
|
|
196
|
+
this.state = reducer(this.state, action);
|
|
197
|
+
this.opts.requestRender?.();
|
|
198
|
+
}
|
|
199
|
+
maybeExit() {
|
|
200
|
+
if (this.state.shouldExit) {
|
|
201
|
+
if (this.clearStatusTimer)
|
|
202
|
+
clearTimeout(this.clearStatusTimer); // Hard Rule 5
|
|
203
|
+
this.opts.onExit(0);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
maybePersist(action) {
|
|
207
|
+
const layer = persistLayerForAction(action);
|
|
208
|
+
if (!layer)
|
|
209
|
+
return;
|
|
210
|
+
try {
|
|
211
|
+
const buffer = layer === "global" ? this.state.buffer.global : this.state.buffer.project;
|
|
212
|
+
const target = writeRoutingConfig({ layer, cwd: this.state.cwd, buffer });
|
|
213
|
+
this.dispatch({ kind: "mark-clean", lastSaved: { target, layer } });
|
|
214
|
+
this.scheduleClearStatus(); // Hard Rule 5
|
|
215
|
+
this.opts.onSaved?.(target);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
219
|
+
this.opts.onError?.(msg);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/** Schedule save-banner auto-clear. Guards against unmount (Hard Rule 5). */
|
|
223
|
+
scheduleClearStatus() {
|
|
224
|
+
if (this.clearStatusTimer)
|
|
225
|
+
clearTimeout(this.clearStatusTimer);
|
|
226
|
+
this.clearStatusTimer = setTimeout(() => {
|
|
227
|
+
if (!this.state.shouldExit) {
|
|
228
|
+
this.dispatch({ kind: "clear-status" });
|
|
229
|
+
}
|
|
230
|
+
}, 3000);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
export function createConfigTuiComponent(opts) {
|
|
234
|
+
return new ConfigTuiComponent(opts);
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/component.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { InitOptions } from "./state.js";
|
|
2
|
+
export type ConfigTuiRoute = {
|
|
3
|
+
kind: "tier-menu";
|
|
4
|
+
} | {
|
|
5
|
+
kind: "show";
|
|
6
|
+
resolved: boolean;
|
|
7
|
+
json: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "dispatch";
|
|
10
|
+
pipeline: string | undefined;
|
|
11
|
+
json: boolean;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "edit-persona";
|
|
14
|
+
persona: string;
|
|
15
|
+
} | {
|
|
16
|
+
kind: "edit-override";
|
|
17
|
+
pipeline: string;
|
|
18
|
+
phaseRole: string;
|
|
19
|
+
};
|
|
20
|
+
export interface ConfigTuiArgsError {
|
|
21
|
+
error: string;
|
|
22
|
+
}
|
|
23
|
+
export type ParseConfigTuiResult = ConfigTuiRoute | ConfigTuiArgsError;
|
|
24
|
+
export declare function parseConfigTuiArgs(args: string[]): ParseConfigTuiResult;
|
|
25
|
+
/**
|
|
26
|
+
* Caller-provided interaction surface. The pi-extension wrapper supplies
|
|
27
|
+
* `ctx.mountConfigTui` to give us TUI access; the bin surface omits it (and
|
|
28
|
+
* gets a non-interactive fallback message).
|
|
29
|
+
*/
|
|
30
|
+
export interface ConfigTuiCallbacks {
|
|
31
|
+
write: (line: string) => void;
|
|
32
|
+
writeErr?: (line: string) => void;
|
|
33
|
+
/** Present only when invoked inside a pi session (TUI mount available). */
|
|
34
|
+
ctx?: {
|
|
35
|
+
notify: (msg: string, level?: string) => void;
|
|
36
|
+
mountConfigTui?: (init: InitOptions) => Promise<number>;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export declare function readPipelineCatalogue(cwd: string): string[] | null;
|
|
40
|
+
export declare function runConfigTui(args: string[], cwd: string, cb: ConfigTuiCallbacks): Promise<number>;
|
|
@@ -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
|
+
};
|