@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.
Files changed (169) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/bin/argv.d.ts +2 -2
  3. package/dist/bin/argv.js +17 -0
  4. package/dist/bin/argv.js.map +1 -1
  5. package/dist/bin/config.d.ts +69 -0
  6. package/dist/bin/config.js +315 -0
  7. package/dist/bin/config.js.map +1 -0
  8. package/dist/bin/doctor.d.ts +1 -0
  9. package/dist/bin/doctor.js +12 -0
  10. package/dist/bin/doctor.js.map +1 -1
  11. package/dist/bin/forge.js +7 -0
  12. package/dist/bin/forge.js.map +1 -1
  13. package/dist/extensions/forgecli/config-command.d.ts +8 -0
  14. package/dist/extensions/forgecli/config-command.js +66 -0
  15. package/dist/extensions/forgecli/config-command.js.map +1 -0
  16. package/dist/extensions/forgecli/config-layer.d.ts +38 -0
  17. package/dist/extensions/forgecli/config-layer.js +68 -0
  18. package/dist/extensions/forgecli/config-layer.js.map +1 -0
  19. package/dist/extensions/forgecli/config-tui/component.d.ts +35 -0
  20. package/dist/extensions/forgecli/config-tui/component.js +236 -0
  21. package/dist/extensions/forgecli/config-tui/component.js.map +1 -0
  22. package/dist/extensions/forgecli/config-tui/handler.d.ts +40 -0
  23. package/dist/extensions/forgecli/config-tui/handler.js +240 -0
  24. package/dist/extensions/forgecli/config-tui/handler.js.map +1 -0
  25. package/dist/extensions/forgecli/config-tui/index.d.ts +5 -0
  26. package/dist/extensions/forgecli/config-tui/index.js +5 -0
  27. package/dist/extensions/forgecli/config-tui/index.js.map +1 -0
  28. package/dist/extensions/forgecli/config-tui/keys.d.ts +26 -0
  29. package/dist/extensions/forgecli/config-tui/keys.js +33 -0
  30. package/dist/extensions/forgecli/config-tui/keys.js.map +1 -0
  31. package/dist/extensions/forgecli/config-tui/plugin-config-reader.d.ts +23 -0
  32. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js +58 -0
  33. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js.map +1 -0
  34. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.d.ts +7 -0
  35. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js +83 -0
  36. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js.map +1 -0
  37. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.d.ts +11 -0
  38. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js +54 -0
  39. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js.map +1 -0
  40. package/dist/extensions/forgecli/config-tui/screens/override-editor.d.ts +11 -0
  41. package/dist/extensions/forgecli/config-tui/screens/override-editor.js +233 -0
  42. package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -0
  43. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.d.ts +7 -0
  44. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +91 -0
  45. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -0
  46. package/dist/extensions/forgecli/config-tui/screens/overrides-list.d.ts +7 -0
  47. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js +71 -0
  48. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js.map +1 -0
  49. package/dist/extensions/forgecli/config-tui/screens/persona-editor.d.ts +10 -0
  50. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js +182 -0
  51. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js.map +1 -0
  52. package/dist/extensions/forgecli/config-tui/screens/persona-picker.d.ts +7 -0
  53. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js +76 -0
  54. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js.map +1 -0
  55. package/dist/extensions/forgecli/config-tui/screens/personas-list.d.ts +7 -0
  56. package/dist/extensions/forgecli/config-tui/screens/personas-list.js +98 -0
  57. package/dist/extensions/forgecli/config-tui/screens/personas-list.js.map +1 -0
  58. package/dist/extensions/forgecli/config-tui/screens/shared.d.ts +29 -0
  59. package/dist/extensions/forgecli/config-tui/screens/shared.js +100 -0
  60. package/dist/extensions/forgecli/config-tui/screens/shared.js.map +1 -0
  61. package/dist/extensions/forgecli/config-tui/screens/show-resolved.d.ts +23 -0
  62. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +128 -0
  63. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -0
  64. package/dist/extensions/forgecli/config-tui/screens/tier-menu.d.ts +7 -0
  65. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js +135 -0
  66. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js.map +1 -0
  67. package/dist/extensions/forgecli/config-tui/screens/tier-picker.d.ts +9 -0
  68. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js +122 -0
  69. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js.map +1 -0
  70. package/dist/extensions/forgecli/config-tui/screens/types.d.ts +24 -0
  71. package/dist/extensions/forgecli/config-tui/screens/types.js +5 -0
  72. package/dist/extensions/forgecli/config-tui/screens/types.js.map +1 -0
  73. package/dist/extensions/forgecli/config-tui/screens.d.ts +24 -0
  74. package/dist/extensions/forgecli/config-tui/screens.js +78 -0
  75. package/dist/extensions/forgecli/config-tui/screens.js.map +1 -0
  76. package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +11 -0
  77. package/dist/extensions/forgecli/config-tui/state/buffer.js +91 -0
  78. package/dist/extensions/forgecli/config-tui/state/buffer.js.map +1 -0
  79. package/dist/extensions/forgecli/config-tui/state/constants.d.ts +4 -0
  80. package/dist/extensions/forgecli/config-tui/state/constants.js +14 -0
  81. package/dist/extensions/forgecli/config-tui/state/constants.js.map +1 -0
  82. package/dist/extensions/forgecli/config-tui/state/index.d.ts +6 -0
  83. package/dist/extensions/forgecli/config-tui/state/index.js +9 -0
  84. package/dist/extensions/forgecli/config-tui/state/index.js.map +1 -0
  85. package/dist/extensions/forgecli/config-tui/state/init.d.ts +2 -0
  86. package/dist/extensions/forgecli/config-tui/state/init.js +30 -0
  87. package/dist/extensions/forgecli/config-tui/state/init.js.map +1 -0
  88. package/dist/extensions/forgecli/config-tui/state/model.d.ts +192 -0
  89. package/dist/extensions/forgecli/config-tui/state/model.js +4 -0
  90. package/dist/extensions/forgecli/config-tui/state/model.js.map +1 -0
  91. package/dist/extensions/forgecli/config-tui/state/reducer.d.ts +2 -0
  92. package/dist/extensions/forgecli/config-tui/state/reducer.js +212 -0
  93. package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -0
  94. package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +91 -0
  95. package/dist/extensions/forgecli/config-tui/state/selectors.js +231 -0
  96. package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -0
  97. package/dist/extensions/forgecli/config-tui/state.d.ts +6 -0
  98. package/dist/extensions/forgecli/config-tui/state.js +11 -0
  99. package/dist/extensions/forgecli/config-tui/state.js.map +1 -0
  100. package/dist/extensions/forgecli/config-tui/theme.d.ts +37 -0
  101. package/dist/extensions/forgecli/config-tui/theme.js +88 -0
  102. package/dist/extensions/forgecli/config-tui/theme.js.map +1 -0
  103. package/dist/extensions/forgecli/config-tui/tier-meta.d.ts +28 -0
  104. package/dist/extensions/forgecli/config-tui/tier-meta.js +69 -0
  105. package/dist/extensions/forgecli/config-tui/tier-meta.js.map +1 -0
  106. package/dist/extensions/forgecli/config-writer.d.ts +16 -0
  107. package/dist/extensions/forgecli/config-writer.js +63 -0
  108. package/dist/extensions/forgecli/config-writer.js.map +1 -0
  109. package/dist/extensions/forgecli/fix-bug.js +85 -1
  110. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  111. package/dist/extensions/forgecli/forge-cli-schema.json +54 -0
  112. package/dist/extensions/forgecli/forge-commands.js +3 -8
  113. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  114. package/dist/extensions/forgecli/forge-subagent.d.ts +13 -0
  115. package/dist/extensions/forgecli/forge-subagent.js +19 -0
  116. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  117. package/dist/extensions/forgecli/index.js +16 -0
  118. package/dist/extensions/forgecli/index.js.map +1 -1
  119. package/dist/extensions/forgecli/input-router.d.ts +33 -0
  120. package/dist/extensions/forgecli/input-router.js +133 -0
  121. package/dist/extensions/forgecli/input-router.js.map +1 -0
  122. package/dist/extensions/forgecli/model-resolver.d.ts +32 -0
  123. package/dist/extensions/forgecli/model-resolver.js +65 -0
  124. package/dist/extensions/forgecli/model-resolver.js.map +1 -0
  125. package/dist/extensions/forgecli/model-validator.d.ts +29 -0
  126. package/dist/extensions/forgecli/model-validator.js +107 -0
  127. package/dist/extensions/forgecli/model-validator.js.map +1 -0
  128. package/dist/extensions/forgecli/run-sprint.js +59 -0
  129. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  130. package/dist/extensions/forgecli/run-task.js +93 -1
  131. package/dist/extensions/forgecli/run-task.js.map +1 -1
  132. package/dist/extensions/forgecli/thread-switcher.js +5 -2
  133. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  134. package/dist/extensions/forgecli/whats-new-widget.js +5 -2
  135. package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
  136. package/package.json +11 -3
  137. package/dist/extensions/forgecli/review-command.d.ts +0 -2
  138. package/dist/extensions/forgecli/review-command.js +0 -184
  139. package/dist/extensions/forgecli/review-command.js.map +0 -1
  140. package/dist/forge-payload/.tools/banners.cjs +0 -435
  141. package/dist/forge-payload/.tools/build-context-pack.cjs +0 -290
  142. package/dist/forge-payload/.tools/build-init-context.cjs +0 -322
  143. package/dist/forge-payload/.tools/build-overlay.cjs +0 -326
  144. package/dist/forge-payload/.tools/build-persona-pack.cjs +0 -226
  145. package/dist/forge-payload/.tools/collate.cjs +0 -1041
  146. package/dist/forge-payload/.tools/generation-manifest.cjs +0 -311
  147. package/dist/forge-payload/.tools/lib/forge-root.cjs +0 -59
  148. package/dist/forge-payload/.tools/lib/paths.cjs +0 -29
  149. package/dist/forge-payload/.tools/lib/pricing.cjs +0 -165
  150. package/dist/forge-payload/.tools/lib/project-root.cjs +0 -32
  151. package/dist/forge-payload/.tools/lib/result.js +0 -40
  152. package/dist/forge-payload/.tools/lib/store-facade.cjs +0 -162
  153. package/dist/forge-payload/.tools/lib/store-nlp.cjs +0 -250
  154. package/dist/forge-payload/.tools/lib/store-query-exec.cjs +0 -272
  155. package/dist/forge-payload/.tools/lib/validate.js +0 -141
  156. package/dist/forge-payload/.tools/manage-config.cjs +0 -340
  157. package/dist/forge-payload/.tools/manage-versions.cjs +0 -365
  158. package/dist/forge-payload/.tools/package.json +0 -3
  159. package/dist/forge-payload/.tools/parse-gates.cjs +0 -151
  160. package/dist/forge-payload/.tools/parse-verdict.cjs +0 -67
  161. package/dist/forge-payload/.tools/preflight-gate.cjs +0 -350
  162. package/dist/forge-payload/.tools/prompts/sprint-plan-prompt.md +0 -70
  163. package/dist/forge-payload/.tools/schemas/task-list.schema.json +0 -53
  164. package/dist/forge-payload/.tools/seed-store.cjs +0 -237
  165. package/dist/forge-payload/.tools/store-cli.cjs +0 -1226
  166. package/dist/forge-payload/.tools/store-query.cjs +0 -319
  167. package/dist/forge-payload/.tools/store.cjs +0 -315
  168. package/dist/forge-payload/.tools/substitute-placeholders.cjs +0 -625
  169. package/dist/forge-payload/.tools/validate-store.cjs +0 -593
@@ -0,0 +1,135 @@
1
+ // Tier-menu screen — the new landing view for forge:config.
2
+ // Phase A: replaces top-menu as the default entry point.
3
+ // Shows three workload tiers (Heavy / Standard / Light) as primary CTAs,
4
+ // a scope toggle, and secondary navigation to show-resolved / advanced.
5
+ import { Key, matchesKey } from "@earendil-works/pi-tui";
6
+ import { getActiveView, getAllScopedTierAssignments } from "../state/selectors.js";
7
+ import { TIERS, TIER_LABELS, TIER_SUB_LABELS } from "../tier-meta.js";
8
+ import { rule, safeLines } from "./shared.js";
9
+ import { padRight, cursor, accentBold, accent, muted, warning, dirtyMarker } from "../theme.js";
10
+ /** Interactive row count: 3 tiers + show-resolved + advanced = 5. */
11
+ const ITEM_COUNT = 5;
12
+ export class TierMenuScreen {
13
+ render(state, width, theme) {
14
+ const view = getActiveView(state);
15
+ if (view.kind !== "tier-menu") {
16
+ return ["(tier-menu called with wrong active view)"];
17
+ }
18
+ const cursorIdx = view.cursor;
19
+ const lines = [];
20
+ // ── Header ─────────────────────────────────────────────────────────
21
+ lines.push(accentBold("forge config", theme));
22
+ lines.push(rule(width, theme));
23
+ // ── "Active right now" summary ─────────────────────────────────────
24
+ lines.push(muted("Active right now", theme));
25
+ const scopedAssignments = getAllScopedTierAssignments(state, state.scope);
26
+ for (const { tier, assignment } of scopedAssignments) {
27
+ const label = padRight(TIER_LABELS[tier], 10);
28
+ if (assignment.status === "set") {
29
+ const modelStr = `${assignment.provider}:${assignment.model}`;
30
+ const layerLabel = `(${assignment.layer})`;
31
+ lines.push(` ${label} ${modelStr} ${muted(layerLabel, theme)}`);
32
+ }
33
+ else if (assignment.status === "set-in-other-layer") {
34
+ const otherLabel = assignment.otherLayer === "global" ? "global" : "project";
35
+ const modelStr = `${assignment.provider}:${assignment.model}`;
36
+ lines.push(` ${label} ${muted(modelStr + " (" + otherLabel + ")", theme)}`);
37
+ }
38
+ else if (assignment.status === "mixed") {
39
+ lines.push(` ${label} ${warning("mixed — personas differ", theme)}`);
40
+ }
41
+ else {
42
+ lines.push(` ${label} ${muted("not set — falls back to pi current", theme)}`);
43
+ }
44
+ }
45
+ // Scope row
46
+ const scopeLabel = state.scope === "global" ? "global" : `project ( ${state.cwd} )`;
47
+ const altLabel = state.scope === "global" ? "project" : "global";
48
+ lines.push(` ${padRight("Scope", 10)} ${accent(scopeLabel, theme)} ${muted(altLabel, theme)}`);
49
+ lines.push("");
50
+ // ── "Choose models for your AI workflow" ────────────────────────────
51
+ lines.push(muted("Choose models for your AI workflow", theme));
52
+ lines.push(rule(width, theme));
53
+ // Tier rows (items 0–2)
54
+ for (let i = 0; i < TIERS.length; i++) {
55
+ const tier = TIERS[i];
56
+ const cur = cursor(i === cursorIdx, theme);
57
+ const label = padRight(TIER_LABELS[tier], 10);
58
+ const subLabel = muted(`(${TIER_SUB_LABELS[tier]})`, theme);
59
+ const tierScoped = scopedAssignments.find((a) => a.tier === tier).assignment;
60
+ const valueStr = tierScoped.status === "set"
61
+ ? `${tierScoped.provider}:${tierScoped.model}`
62
+ : tierScoped.status === "set-in-other-layer"
63
+ ? muted(`(${tierScoped.otherLayer})`, theme)
64
+ : tierScoped.status === "mixed"
65
+ ? warning("mixed", theme)
66
+ : muted("not set", theme);
67
+ lines.push(` ${cur} ${label} ${subLabel} ${valueStr}`);
68
+ }
69
+ // "Show what runs at each step" (item 3)
70
+ {
71
+ const cur = cursor(3 === cursorIdx, theme);
72
+ lines.push(` ${cur} ${muted("Show what runs at each step", theme)}`);
73
+ }
74
+ // "Advanced — per-persona / per-step overrides" (item 4)
75
+ {
76
+ const cur = cursor(4 === cursorIdx, theme);
77
+ lines.push(` ${cur} ${muted("Advanced — per-persona / per-step overrides", theme)}`);
78
+ }
79
+ lines.push("");
80
+ // ── Footer ──────────────────────────────────────────────────────────
81
+ const tierWord = cursorIdx < 3 ? "enter pick model" : "enter open";
82
+ lines.push(muted(` ${tierWord} tab toggle scope q quit`, theme));
83
+ if (state.dirty)
84
+ lines.push(` ${dirtyMarker(theme)}`);
85
+ return safeLines(lines, width);
86
+ }
87
+ handleInput(data, state) {
88
+ const view = getActiveView(state);
89
+ if (view.kind !== "tier-menu")
90
+ return { kind: "no-op" };
91
+ // ── Navigation ──────────────────────────────────────────────────────
92
+ if (matchesKey(data, Key.up) || matchesKey(data, "k")) {
93
+ return { kind: "dispatch", action: { kind: "cursor-move", delta: -1 } };
94
+ }
95
+ if (matchesKey(data, Key.down) || matchesKey(data, "j")) {
96
+ if (view.cursor < ITEM_COUNT - 1) {
97
+ return { kind: "dispatch", action: { kind: "cursor-move", delta: 1 } };
98
+ }
99
+ return { kind: "consumed" };
100
+ }
101
+ // ── Tab: toggle scope ───────────────────────────────────────────────
102
+ if (matchesKey(data, Key.tab)) {
103
+ return { kind: "dispatch", action: { kind: "toggle-scope" } };
104
+ }
105
+ // ── Enter: act on current cursor position ───────────────────────────
106
+ if (matchesKey(data, Key.enter)) {
107
+ if (view.cursor < 3) {
108
+ // Tier row → open tier picker
109
+ const tier = TIERS[view.cursor];
110
+ return { kind: "dispatch", action: { kind: "select-tier", tier } };
111
+ }
112
+ if (view.cursor === 3) {
113
+ // "Show what runs at each step"
114
+ return { kind: "dispatch", action: { kind: "push-view", view: { kind: "show-resolved", cursor: 0 } } };
115
+ }
116
+ if (view.cursor === 4) {
117
+ // "Advanced" → advanced-menu (Phase D)
118
+ return { kind: "dispatch", action: { kind: "push-view", view: { kind: "advanced-menu", cursor: 0 } } };
119
+ }
120
+ }
121
+ // ── Shortcuts: 1/2/3 for tiers, s for show, a for advanced ──────────
122
+ if (matchesKey(data, "1"))
123
+ return { kind: "dispatch", action: { kind: "select-tier", tier: "heavy" } };
124
+ if (matchesKey(data, "2"))
125
+ return { kind: "dispatch", action: { kind: "select-tier", tier: "standard" } };
126
+ if (matchesKey(data, "3"))
127
+ return { kind: "dispatch", action: { kind: "select-tier", tier: "light" } };
128
+ if (matchesKey(data, "s"))
129
+ return { kind: "dispatch", action: { kind: "push-view", view: { kind: "show-resolved", cursor: 0 } } };
130
+ if (matchesKey(data, "a"))
131
+ return { kind: "dispatch", action: { kind: "push-view", view: { kind: "advanced-menu", cursor: 0 } } };
132
+ return { kind: "no-op" };
133
+ }
134
+ }
135
+ //# sourceMappingURL=tier-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier-menu.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/screens/tier-menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
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 TierPickerScreen implements Screen {
5
+ render(state: ConfigTuiState, width: number, theme: Theme): string[];
6
+ handleInput(data: string, state: ConfigTuiState): InputResult;
7
+ private handlePickProviderInput;
8
+ private handlePickModelInput;
9
+ }
@@ -0,0 +1,122 @@
1
+ // Tier-picker screen — provider + model picker for a workload tier.
2
+ // Phase A: minimal placeholder. Phase B adds full provider/model picking flow.
3
+ // Reuses the same UX patterns as persona-editor but scoped to a tier.
4
+ import { Key, matchesKey } from "@earendil-works/pi-tui";
5
+ import { getActiveView, uniqueProviders } from "../state/selectors.js";
6
+ import { TIER_LABELS, tierPersonaLine } from "../tier-meta.js";
7
+ import { rule, authBadgeFor, windowList, safeLines } from "./shared.js";
8
+ import { padRight, cursor, accentBold, muted, dirtyMarker } from "../theme.js";
9
+ export class TierPickerScreen {
10
+ render(state, width, theme) {
11
+ const view = getActiveView(state);
12
+ if (view.kind !== "tier-picker") {
13
+ return ["(tier-picker called with wrong active view)"];
14
+ }
15
+ const tierLabel = TIER_LABELS[view.tier];
16
+ const lines = [];
17
+ if (view.step === "pick-provider") {
18
+ lines.push(accentBold(`forge config › ${tierLabel} › pick provider`, theme));
19
+ lines.push(rule(width, theme));
20
+ lines.push(muted(` This will run for: ${tierPersonaLine(view.tier)}`, theme));
21
+ lines.push("");
22
+ const providers = uniqueProviders(state);
23
+ const win = windowList(providers, view.cursor);
24
+ if (win.aboveCount > 0)
25
+ lines.push(muted(` ↑ ${win.aboveCount} more above`, theme));
26
+ win.visible.forEach((p, i) => {
27
+ const absoluteIdx = win.start + i;
28
+ const cur = cursor(absoluteIdx === view.cursor, theme);
29
+ const auth = authBadgeFor(state, p, theme);
30
+ const modelCount = state.availableModels.filter((m) => m.provider === p).length;
31
+ const countLabel = `${modelCount} model${modelCount === 1 ? "" : "s"}`;
32
+ lines.push(` ${cur} ${padRight(p, 18)} ${auth} ${muted(countLabel, theme)}`);
33
+ });
34
+ if (win.belowCount > 0)
35
+ lines.push(muted(` ↓ ${win.belowCount} more below`, theme));
36
+ lines.push("");
37
+ lines.push(muted(" ↑↓ select enter advance esc back", theme));
38
+ }
39
+ else if (view.step === "pick-model") {
40
+ lines.push(accentBold(`forge config › ${tierLabel} › pick model`, theme));
41
+ lines.push(rule(width, theme));
42
+ lines.push(muted(` provider: ${view.provider ?? "(unknown)"}`, theme));
43
+ lines.push(muted(` This will run for: ${tierPersonaLine(view.tier)}`, theme));
44
+ lines.push("");
45
+ const models = state.availableModels.filter((m) => m.provider === view.provider);
46
+ if (models.length === 0) {
47
+ lines.push(muted(" No models available for this provider.", theme));
48
+ lines.push(muted(` (Run \`pi /login ${view.provider}\` then return.)`, theme));
49
+ }
50
+ else {
51
+ const win = windowList(models, view.cursor);
52
+ if (win.aboveCount > 0)
53
+ lines.push(muted(` ↑ ${win.aboveCount} more above`, theme));
54
+ win.visible.forEach((m, i) => {
55
+ const absoluteIdx = win.start + i;
56
+ const cur = cursor(absoluteIdx === view.cursor, theme);
57
+ lines.push(` ${cur} ${m.id}`);
58
+ });
59
+ if (win.belowCount > 0)
60
+ lines.push(muted(` ↓ ${win.belowCount} more below`, theme));
61
+ }
62
+ lines.push("");
63
+ lines.push(muted(" ↑↓ select enter save esc back", theme));
64
+ }
65
+ if (state.dirty)
66
+ lines.push(` ${dirtyMarker(theme)}`);
67
+ return safeLines(lines, width);
68
+ }
69
+ handleInput(data, state) {
70
+ const view = getActiveView(state);
71
+ if (view.kind !== "tier-picker")
72
+ return { kind: "no-op" };
73
+ if (view.step === "pick-provider") {
74
+ return this.handlePickProviderInput(data, state, view);
75
+ }
76
+ if (view.step === "pick-model") {
77
+ return this.handlePickModelInput(data, state, view);
78
+ }
79
+ return { kind: "no-op" };
80
+ }
81
+ handlePickProviderInput(data, state, view) {
82
+ const providers = uniqueProviders(state);
83
+ if (matchesKey(data, Key.up) || matchesKey(data, "k")) {
84
+ return { kind: "dispatch", action: { kind: "cursor-move", delta: -1 } };
85
+ }
86
+ if (matchesKey(data, Key.down) || matchesKey(data, "j")) {
87
+ if (view.cursor < providers.length - 1) {
88
+ return { kind: "dispatch", action: { kind: "cursor-move", delta: 1 } };
89
+ }
90
+ return { kind: "consumed" };
91
+ }
92
+ if (matchesKey(data, Key.enter)) {
93
+ const provider = providers[view.cursor];
94
+ if (provider) {
95
+ return { kind: "dispatch", action: { kind: "set-tier-provider", tier: view.tier, provider } };
96
+ }
97
+ return { kind: "consumed" };
98
+ }
99
+ return { kind: "no-op" };
100
+ }
101
+ handlePickModelInput(data, state, view) {
102
+ const models = state.availableModels.filter((m) => m.provider === view.provider);
103
+ if (matchesKey(data, Key.up) || matchesKey(data, "k")) {
104
+ return { kind: "dispatch", action: { kind: "cursor-move", delta: -1 } };
105
+ }
106
+ if (matchesKey(data, Key.down) || matchesKey(data, "j")) {
107
+ if (view.cursor < models.length - 1) {
108
+ return { kind: "dispatch", action: { kind: "cursor-move", delta: 1 } };
109
+ }
110
+ return { kind: "consumed" };
111
+ }
112
+ if (matchesKey(data, Key.enter)) {
113
+ const target = models[view.cursor];
114
+ if (target && view.provider) {
115
+ return { kind: "dispatch", action: { kind: "commit-tier-model", tier: view.tier, provider: view.provider, model: target.id, layer: state.scope } };
116
+ }
117
+ return { kind: "consumed" };
118
+ }
119
+ return { kind: "no-op" };
120
+ }
121
+ }
122
+ //# sourceMappingURL=tier-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier-picker.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/screens/tier-picker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { ConfigTuiState, ConfigTuiAction } from "../state/model.js";
2
+ import type { Theme } from "@earendil-works/pi-coding-agent";
3
+ export type InputResult = {
4
+ kind: "consumed";
5
+ } | {
6
+ kind: "no-op";
7
+ } | {
8
+ kind: "dispatch";
9
+ action: ConfigTuiAction;
10
+ } | {
11
+ kind: "dispatch-seq";
12
+ actions: ConfigTuiAction[];
13
+ } | {
14
+ kind: "pop";
15
+ } | {
16
+ kind: "quit";
17
+ } | {
18
+ kind: "error";
19
+ message: string;
20
+ };
21
+ export interface Screen {
22
+ render(state: ConfigTuiState, width: number, theme: Theme): string[];
23
+ handleInput(data: string, state: ConfigTuiState): InputResult;
24
+ }
@@ -0,0 +1,5 @@
1
+ // Screen interface + InputResult discriminated union.
2
+ // Phase 2: each screen module implements Screen; the orchestrator delegates
3
+ // render and handleInput to the active screen.
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/screens/types.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,4EAA4E;AAC5E,+CAA+C"}
@@ -0,0 +1,24 @@
1
+ import type { ConfigTuiState } from "./state.js";
2
+ import type { Theme } from "@earendil-works/pi-coding-agent";
3
+ export { TierMenuScreen } from "./screens/tier-menu.js";
4
+ export { TierPickerScreen } from "./screens/tier-picker.js";
5
+ export { AdvancedMenuScreen } from "./screens/advanced-menu.js";
6
+ export { PersonasListScreen } from "./screens/personas-list.js";
7
+ export { PersonaPickerScreen } from "./screens/persona-picker.js";
8
+ export { PersonaEditorScreen } from "./screens/persona-editor.js";
9
+ export { ShowResolvedScreen, computeResolvedRows, type ResolvedRow } from "./screens/show-resolved.js";
10
+ export { OverridesListPipelinesScreen } from "./screens/overrides-list.js";
11
+ export { OverridesListPhasesScreen } from "./screens/overrides-list-phases.js";
12
+ export { OverrideEditorScreen } from "./screens/override-editor.js";
13
+ export { ConfirmQuitScreen, renderSaveBanner } from "./screens/confirm-quit.js";
14
+ export { type InputResult, type Screen } from "./screens/types.js";
15
+ export declare function renderTierMenu(state: ConfigTuiState, width: number, theme: Theme): string[];
16
+ export declare function renderAdvancedMenu(state: ConfigTuiState, width: number, theme: Theme): string[];
17
+ export declare function renderPersonasList(state: ConfigTuiState, width: number, theme: Theme): string[];
18
+ export declare function renderPersonaPicker(state: ConfigTuiState, width: number, theme: Theme): string[];
19
+ export declare function renderPersonaEditor(state: ConfigTuiState, width: number, theme: Theme): string[];
20
+ export declare function renderShowResolved(state: ConfigTuiState, width: number, theme: Theme): string[];
21
+ export declare function renderOverridesListPipelines(state: ConfigTuiState, width: number, theme: Theme): string[];
22
+ export declare function renderOverridesListPhases(state: ConfigTuiState, width: number, theme: Theme): string[];
23
+ export declare function renderOverrideEditor(state: ConfigTuiState, width: number, theme: Theme): string[];
24
+ export declare function renderActive(state: ConfigTuiState, width: number, theme: Theme): string[];
@@ -0,0 +1,78 @@
1
+ // Screen renderers and routing — barrel re-export for backward compatibility.
2
+ //
3
+ // Phase 3: theming + width safety. All screen classes now use theme helpers
4
+ // for visible strings and truncate their output to terminal width.
5
+ import { getActiveView, } from "./state/selectors.js";
6
+ import { TierMenuScreen } from "./screens/tier-menu.js";
7
+ import { TierPickerScreen } from "./screens/tier-picker.js";
8
+ import { AdvancedMenuScreen } from "./screens/advanced-menu.js";
9
+ import { ConfirmQuitScreen, renderSaveBanner } from "./screens/confirm-quit.js";
10
+ import { PersonasListScreen } from "./screens/personas-list.js";
11
+ import { PersonaPickerScreen } from "./screens/persona-picker.js";
12
+ import { PersonaEditorScreen } from "./screens/persona-editor.js";
13
+ import { ShowResolvedScreen } from "./screens/show-resolved.js";
14
+ import { OverridesListPipelinesScreen } from "./screens/overrides-list.js";
15
+ import { OverridesListPhasesScreen } from "./screens/overrides-list-phases.js";
16
+ import { OverrideEditorScreen } from "./screens/override-editor.js";
17
+ // ── Screen instances for renderActive ───────────────────────────────────────
18
+ const SCREEN_INSTANCES = {
19
+ "tier-menu": new TierMenuScreen(),
20
+ "tier-picker": new TierPickerScreen(),
21
+ "advanced-menu": new AdvancedMenuScreen(),
22
+ "personas-list": new PersonasListScreen(),
23
+ "persona-picker": new PersonaPickerScreen(),
24
+ "persona-editor": new PersonaEditorScreen(),
25
+ "show-resolved": new ShowResolvedScreen(),
26
+ "overrides-list-pipelines": new OverridesListPipelinesScreen(),
27
+ "overrides-list-phases": new OverridesListPhasesScreen(),
28
+ "override-editor": new OverrideEditorScreen(),
29
+ };
30
+ // ── Re-exports for backward compatibility ───────────────────────────────────
31
+ export { TierMenuScreen } from "./screens/tier-menu.js";
32
+ export { TierPickerScreen } from "./screens/tier-picker.js";
33
+ export { AdvancedMenuScreen } from "./screens/advanced-menu.js";
34
+ export { PersonasListScreen } from "./screens/personas-list.js";
35
+ export { PersonaPickerScreen } from "./screens/persona-picker.js";
36
+ export { PersonaEditorScreen } from "./screens/persona-editor.js";
37
+ export { ShowResolvedScreen, computeResolvedRows } from "./screens/show-resolved.js";
38
+ export { OverridesListPipelinesScreen } from "./screens/overrides-list.js";
39
+ export { OverridesListPhasesScreen } from "./screens/overrides-list-phases.js";
40
+ export { OverrideEditorScreen } from "./screens/override-editor.js";
41
+ export { ConfirmQuitScreen, renderSaveBanner } from "./screens/confirm-quit.js";
42
+ // ── Render functions (backward-compatible wrappers) ──────────────────────
43
+ export function renderTierMenu(state, width, theme) {
44
+ return SCREEN_INSTANCES["tier-menu"].render(state, width, theme);
45
+ }
46
+ export function renderAdvancedMenu(state, width, theme) {
47
+ return SCREEN_INSTANCES["advanced-menu"].render(state, width, theme);
48
+ }
49
+ export function renderPersonasList(state, width, theme) {
50
+ return SCREEN_INSTANCES["personas-list"].render(state, width, theme);
51
+ }
52
+ export function renderPersonaPicker(state, width, theme) {
53
+ return SCREEN_INSTANCES["persona-picker"].render(state, width, theme);
54
+ }
55
+ export function renderPersonaEditor(state, width, theme) {
56
+ return SCREEN_INSTANCES["persona-editor"].render(state, width, theme);
57
+ }
58
+ export function renderShowResolved(state, width, theme) {
59
+ return SCREEN_INSTANCES["show-resolved"].render(state, width, theme);
60
+ }
61
+ export function renderOverridesListPipelines(state, width, theme) {
62
+ return SCREEN_INSTANCES["overrides-list-pipelines"].render(state, width, theme);
63
+ }
64
+ export function renderOverridesListPhases(state, width, theme) {
65
+ return SCREEN_INSTANCES["overrides-list-phases"].render(state, width, theme);
66
+ }
67
+ export function renderOverrideEditor(state, width, theme) {
68
+ return SCREEN_INSTANCES["override-editor"].render(state, width, theme);
69
+ }
70
+ // ── Top-level router ─────────────────────────────────────────────────────────
71
+ export function renderActive(state, width, theme) {
72
+ const view = getActiveView(state);
73
+ const screen = SCREEN_INSTANCES[view.kind];
74
+ const lines = screen ? screen.render(state, width, theme) : [];
75
+ // Decorations: save banner stacks at the bottom, confirm-quit modal on top.
76
+ return [...lines, ...renderSaveBanner(state, width, theme), ...new ConfirmQuitScreen().render(state, width, theme)];
77
+ }
78
+ //# sourceMappingURL=screens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screens.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/screens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { ConfigBuffer, PhaseOverride } from "./model.js";
2
+ import type { ConfigLayer } from "../../config-writer.js";
3
+ import type { PersonaModel } from "../../config-layer.js";
4
+ import type { Tier } from "../tier-meta.js";
5
+ export declare function writePersonaEntry(buffer: ConfigBuffer, layer: ConfigLayer, persona: string, entry: PersonaModel): ConfigBuffer;
6
+ export declare function deletePersonaEntry(buffer: ConfigBuffer, layer: ConfigLayer, persona: string): ConfigBuffer;
7
+ /** Fan out a single model into all persona entries for a tier.
8
+ * E.g. setting Heavy → anthropic:claude-opus writes architect and supervisor. */
9
+ export declare function writeTierAssignment(buffer: ConfigBuffer, layer: ConfigLayer, tier: Tier, entry: PersonaModel): ConfigBuffer;
10
+ export declare function writePhaseOverride(buffer: ConfigBuffer, pipelineName: string, phaseRole: string, override: PhaseOverride): ConfigBuffer;
11
+ export declare function clearPhaseOverride(buffer: ConfigBuffer, pipelineName: string, phaseRole: string): ConfigBuffer;
@@ -0,0 +1,91 @@
1
+ // Config TUI buffer mutation helpers — pure functions, no I/O.
2
+ // Split from state.ts (Phase 1).
3
+ import { TIER_PERSONAS } from "../tier-meta.js";
4
+ export function writePersonaEntry(buffer, layer, persona, entry) {
5
+ const targetLayer = buffer[layer];
6
+ const personaModels = { ...(targetLayer["persona-models"] ?? {}) };
7
+ personaModels[persona] = entry;
8
+ const updatedLayer = { ...targetLayer, "persona-models": personaModels };
9
+ return { ...buffer, [layer]: updatedLayer };
10
+ }
11
+ export function deletePersonaEntry(buffer, layer, persona) {
12
+ const targetLayer = buffer[layer];
13
+ const personaModels = { ...(targetLayer["persona-models"] ?? {}) };
14
+ if (!(persona in personaModels))
15
+ return buffer;
16
+ delete personaModels[persona];
17
+ const updatedLayer = { ...targetLayer };
18
+ if (Object.keys(personaModels).length === 0) {
19
+ delete updatedLayer["persona-models"];
20
+ }
21
+ else {
22
+ updatedLayer["persona-models"] = personaModels;
23
+ }
24
+ return { ...buffer, [layer]: updatedLayer };
25
+ }
26
+ /** Fan out a single model into all persona entries for a tier.
27
+ * E.g. setting Heavy → anthropic:claude-opus writes architect and supervisor. */
28
+ export function writeTierAssignment(buffer, layer, tier, entry) {
29
+ const personas = TIER_PERSONAS[tier];
30
+ let next = buffer;
31
+ for (const persona of personas) {
32
+ next = writePersonaEntry(next, layer, persona, entry);
33
+ }
34
+ return next;
35
+ }
36
+ export function writePhaseOverride(buffer, pipelineName, phaseRole, override) {
37
+ const project = { ...buffer.project };
38
+ const pipelines = { ...(project.pipelines ?? {}) };
39
+ const pipeline = { ...(pipelines[pipelineName] ?? {}) };
40
+ const phases = { ...(pipeline.phases ?? {}) };
41
+ phases[phaseRole] = { ...phases[phaseRole], "model-override": override };
42
+ pipeline.phases = phases;
43
+ pipelines[pipelineName] = pipeline;
44
+ project.pipelines = pipelines;
45
+ return { ...buffer, project };
46
+ }
47
+ export function clearPhaseOverride(buffer, pipelineName, phaseRole) {
48
+ const existingPipeline = buffer.project.pipelines?.[pipelineName];
49
+ const existingPhases = existingPipeline?.phases;
50
+ if (!existingPhases)
51
+ return buffer;
52
+ const existingPhase = existingPhases[phaseRole];
53
+ if (!existingPhase || existingPhase["model-override"] === undefined)
54
+ return buffer;
55
+ const project = { ...buffer.project };
56
+ const pipelines = { ...(project.pipelines ?? {}) };
57
+ const pipeline = { ...pipelines[pipelineName] };
58
+ const phases = { ...existingPhases };
59
+ const nextPhase = { ...phases[phaseRole] };
60
+ delete nextPhase["model-override"];
61
+ if (Object.keys(nextPhase).length === 0) {
62
+ delete phases[phaseRole];
63
+ }
64
+ else {
65
+ phases[phaseRole] = nextPhase;
66
+ }
67
+ if (Object.keys(phases).length === 0) {
68
+ delete pipeline.phases;
69
+ }
70
+ else {
71
+ pipeline.phases = phases;
72
+ }
73
+ // If the pipeline has no persona-models and no remaining phase overrides, drop it.
74
+ const hasPipelinePersonaModels = pipeline["persona-models"] !== undefined &&
75
+ Object.keys(pipeline["persona-models"]).length > 0;
76
+ const hasPhases = Object.keys(pipeline.phases ?? {}).length > 0;
77
+ if (!hasPipelinePersonaModels && !hasPhases) {
78
+ delete pipelines[pipelineName];
79
+ }
80
+ else {
81
+ pipelines[pipelineName] = pipeline;
82
+ }
83
+ if (Object.keys(pipelines).length === 0) {
84
+ delete project.pipelines;
85
+ }
86
+ else {
87
+ project.pipelines = pipelines;
88
+ }
89
+ return { ...buffer, project };
90
+ }
91
+ //# sourceMappingURL=buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/state/buffer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const CANONICAL_PHASES: ReadonlyArray<{
2
+ role: string;
3
+ personaNoun: string;
4
+ }>;
@@ -0,0 +1,14 @@
1
+ // Canonical phase definitions for the "default" pipeline.
2
+ // Inlined here so the config-tui module doesn't import the orchestrator
3
+ // (which would pull in pi-coding-agent runtime). Stays in sync via tests.
4
+ export const CANONICAL_PHASES = [
5
+ { role: "plan", personaNoun: "engineer" },
6
+ { role: "review-plan", personaNoun: "supervisor" },
7
+ { role: "implement", personaNoun: "engineer" },
8
+ { role: "review-code", personaNoun: "supervisor" },
9
+ { role: "validate", personaNoun: "qa-engineer" },
10
+ { role: "approve", personaNoun: "architect" },
11
+ { role: "writeback", personaNoun: "collator" },
12
+ { role: "commit", personaNoun: "engineer" },
13
+ ];
14
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/state/constants.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,wEAAwE;AACxE,0EAA0E;AAE1E,MAAM,CAAC,MAAM,gBAAgB,GAAyD;IACpF,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE;IACzC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE;IAClD,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE;IAC9C,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE;IAClD,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE;IAChD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE;IAC7C,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE;IAC9C,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE;CAC5C,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type { View, ConfigBuffer, AvailableModel, InitOptions, ConfigTuiState, ConfigTuiAction, PhaseOverride, ResolvedPersonaEntry, PersonaPickerEntry, PipelineOverrideSummary, TierAssignment, } from "./model.js";
2
+ export { CANONICAL_PHASES } from "./constants.js";
3
+ export { initialState } from "./init.js";
4
+ export { reducer } from "./reducer.js";
5
+ export { getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, getPhaseTable, sourceToLabel, type PhaseTableRow, type ScopedTierAssignment, getScopedTierAssignment, getAllScopedTierAssignments, isConfigEmpty, personaSourceLabel, } from "./selectors.js";
6
+ export { writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, } from "./buffer.js";
@@ -0,0 +1,9 @@
1
+ // Barrel re-export for config-tui state modules.
2
+ // Split from state.ts (Phase 1). All public symbols remain accessible from
3
+ // the same import path: `./state.js` → re-exports from split modules.
4
+ export { CANONICAL_PHASES } from "./constants.js";
5
+ export { initialState } from "./init.js";
6
+ export { reducer } from "./reducer.js";
7
+ export { getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, getPhaseTable, sourceToLabel, getScopedTierAssignment, getAllScopedTierAssignments, isConfigEmpty, personaSourceLabel, } from "./selectors.js";
8
+ export { writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, } from "./buffer.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/state/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,2EAA2E;AAC3E,sEAAsE;AAgBtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EACf,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,aAAa,EAGb,uBAAuB,EACvB,2BAA2B,EAC3B,aAAa,EACb,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ConfigTuiState, InitOptions } from "./model.js";
2
+ export declare function initialState(opts: InitOptions): ConfigTuiState;