@compilr-dev/cli 0.4.0 → 0.5.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/README.md +30 -12
- package/dist/agent.d.ts +74 -1
- package/dist/agent.js +259 -76
- package/dist/anchors/index.d.ts +9 -0
- package/dist/anchors/index.js +9 -0
- package/dist/anchors/project-anchors.d.ts +79 -0
- package/dist/anchors/project-anchors.js +202 -0
- package/dist/commands/handler-types.d.ts +68 -0
- package/dist/commands/handler-types.js +8 -0
- package/dist/commands/handlers/agent-commands.d.ts +13 -0
- package/dist/commands/handlers/agent-commands.js +305 -0
- package/dist/commands/handlers/design-commands.d.ts +15 -0
- package/dist/commands/handlers/design-commands.js +334 -0
- package/dist/commands/handlers/index.d.ts +20 -0
- package/dist/commands/handlers/index.js +43 -0
- package/dist/commands/handlers/overlay-commands.d.ts +21 -0
- package/dist/commands/handlers/overlay-commands.js +287 -0
- package/dist/commands/handlers/project-commands.d.ts +11 -0
- package/dist/commands/handlers/project-commands.js +167 -0
- package/dist/commands/handlers/simple-commands.d.ts +19 -0
- package/dist/commands/handlers/simple-commands.js +144 -0
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/registry.d.ts +50 -0
- package/dist/commands/registry.js +75 -0
- package/dist/commands-v2/handlers/context.d.ts +13 -0
- package/dist/commands-v2/handlers/context.js +348 -0
- package/dist/commands-v2/handlers/core.d.ts +13 -0
- package/dist/commands-v2/handlers/core.js +165 -0
- package/dist/commands-v2/handlers/debug.d.ts +11 -0
- package/dist/commands-v2/handlers/debug.js +159 -0
- package/dist/commands-v2/handlers/index.d.ts +12 -0
- package/dist/commands-v2/handlers/index.js +24 -0
- package/dist/commands-v2/handlers/project.d.ts +22 -0
- package/dist/commands-v2/handlers/project.js +814 -0
- package/dist/commands-v2/handlers/settings.d.ts +15 -0
- package/dist/commands-v2/handlers/settings.js +235 -0
- package/dist/commands-v2/index.d.ts +13 -0
- package/dist/commands-v2/index.js +15 -0
- package/dist/commands-v2/registry.d.ts +37 -0
- package/dist/commands-v2/registry.js +80 -0
- package/dist/commands-v2/types.d.ts +75 -0
- package/dist/commands-v2/types.js +7 -0
- package/dist/commands.js +110 -7
- package/dist/index.js +288 -29
- package/dist/input-handlers/index.d.ts +7 -0
- package/dist/input-handlers/index.js +7 -0
- package/dist/input-handlers/memory-handler.d.ts +26 -0
- package/dist/input-handlers/memory-handler.js +68 -0
- package/dist/repl-helpers.d.ts +63 -0
- package/dist/repl-helpers.js +318 -0
- package/dist/repl-v2.d.ts +155 -0
- package/dist/repl-v2.js +774 -0
- package/dist/repl.d.ts +32 -4
- package/dist/repl.js +250 -977
- package/dist/settings/index.d.ts +23 -0
- package/dist/settings/index.js +48 -0
- package/dist/settings/paths.d.ts +110 -0
- package/dist/settings/paths.js +264 -0
- package/dist/templates/compilr-md.js +7 -4
- package/dist/templates/index.js +3 -4
- package/dist/themes/colors.js +3 -1
- package/dist/themes/registry.d.ts +5 -36
- package/dist/themes/registry.js +11 -95
- package/dist/themes/types.d.ts +3 -38
- package/dist/themes/types.js +2 -2
- package/dist/tools/anchor-tools.d.ts +31 -0
- package/dist/tools/anchor-tools.js +255 -0
- package/dist/tools/backlog-wrappers.d.ts +54 -0
- package/dist/tools/backlog-wrappers.js +338 -0
- package/dist/tools/backlog.js +1 -1
- package/dist/tools/db-tools.d.ts +65 -0
- package/dist/tools/db-tools.js +19 -0
- package/dist/tools/document-db.d.ts +43 -0
- package/dist/tools/document-db.js +220 -0
- package/dist/tools/project-db.d.ts +102 -0
- package/dist/tools/project-db.js +370 -0
- package/dist/tools/workitem-db.d.ts +103 -0
- package/dist/tools/workitem-db.js +549 -0
- package/dist/tools.js +13 -3
- package/dist/ui/agents-overlay-v2.d.ts +43 -0
- package/dist/ui/agents-overlay-v2.js +809 -0
- package/dist/ui/agents-overlay.d.ts +5 -5
- package/dist/ui/agents-overlay.js +782 -420
- package/dist/ui/anchors-overlay.d.ts +12 -0
- package/dist/ui/anchors-overlay.js +775 -0
- package/dist/ui/arch-type-overlay.d.ts +1 -6
- package/dist/ui/arch-type-overlay.js +175 -203
- package/dist/ui/ask-user-overlay-v2.d.ts +26 -0
- package/dist/ui/ask-user-overlay-v2.js +555 -0
- package/dist/ui/ask-user-overlay.d.ts +2 -2
- package/dist/ui/ask-user-overlay.js +443 -535
- package/dist/ui/ask-user-simple-overlay-v2.d.ts +25 -0
- package/dist/ui/ask-user-simple-overlay-v2.js +215 -0
- package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
- package/dist/ui/ask-user-simple-overlay.js +182 -209
- package/dist/ui/backlog-overlay.d.ts +16 -1
- package/dist/ui/backlog-overlay.js +525 -659
- package/dist/ui/base/index.d.ts +26 -0
- package/dist/ui/base/index.js +33 -0
- package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
- package/dist/ui/base/inline-overlay-utils.js +320 -0
- package/dist/ui/base/inline-overlay.d.ts +159 -0
- package/dist/ui/base/inline-overlay.js +257 -0
- package/dist/ui/base/key-utils.d.ts +15 -0
- package/dist/ui/base/key-utils.js +30 -0
- package/dist/ui/base/overlay-base-v2.d.ts +193 -0
- package/dist/ui/base/overlay-base-v2.js +246 -0
- package/dist/ui/base/overlay-base.d.ts +156 -0
- package/dist/ui/base/overlay-base.js +238 -0
- package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
- package/dist/ui/base/overlay-lifecycle.js +159 -0
- package/dist/ui/base/overlay-types.d.ts +185 -0
- package/dist/ui/base/overlay-types.js +7 -0
- package/dist/ui/base/render-utils.d.ts +8 -0
- package/dist/ui/base/render-utils.js +11 -0
- package/dist/ui/base/screen-stack.d.ts +148 -0
- package/dist/ui/base/screen-stack.js +184 -0
- package/dist/ui/base/tabbed-list-overlay-v2.d.ts +103 -0
- package/dist/ui/base/tabbed-list-overlay-v2.js +317 -0
- package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
- package/dist/ui/base/tabbed-list-overlay.js +369 -0
- package/dist/ui/commands-overlay-v2.d.ts +33 -0
- package/dist/ui/commands-overlay-v2.js +441 -0
- package/dist/ui/commands-overlay.d.ts +7 -2
- package/dist/ui/commands-overlay.js +384 -355
- package/dist/ui/config-overlay.d.ts +5 -4
- package/dist/ui/config-overlay.js +243 -513
- package/dist/ui/conversation.d.ts +75 -4
- package/dist/ui/conversation.js +374 -161
- package/dist/ui/docs-overlay.d.ts +17 -0
- package/dist/ui/docs-overlay.js +303 -0
- package/dist/ui/ephemeral.d.ts +1 -1
- package/dist/ui/ephemeral.js +1 -1
- package/dist/ui/features/index.d.ts +34 -0
- package/dist/ui/features/index.js +34 -0
- package/dist/ui/features/input-feature.d.ts +85 -0
- package/dist/ui/features/input-feature.js +238 -0
- package/dist/ui/features/list-feature.d.ts +155 -0
- package/dist/ui/features/list-feature.js +244 -0
- package/dist/ui/features/pagination-feature.d.ts +154 -0
- package/dist/ui/features/pagination-feature.js +238 -0
- package/dist/ui/features/search-feature.d.ts +148 -0
- package/dist/ui/features/search-feature.js +185 -0
- package/dist/ui/features/tab-feature.d.ts +194 -0
- package/dist/ui/features/tab-feature.js +307 -0
- package/dist/ui/footer-v2.d.ts +222 -0
- package/dist/ui/footer-v2.js +1349 -0
- package/dist/ui/footer.d.ts +107 -0
- package/dist/ui/footer.js +359 -67
- package/dist/ui/guardrail-overlay.d.ts +29 -0
- package/dist/ui/guardrail-overlay.js +145 -0
- package/dist/ui/help-overlay-v2.d.ts +34 -0
- package/dist/ui/help-overlay-v2.js +309 -0
- package/dist/ui/help-overlay.d.ts +16 -0
- package/dist/ui/help-overlay.js +316 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -3
- package/dist/ui/init-overlay-v2.d.ts +34 -0
- package/dist/ui/init-overlay-v2.js +600 -0
- package/dist/ui/init-overlay.d.ts +12 -2
- package/dist/ui/init-overlay.js +349 -270
- package/dist/ui/input-prompt-v2.d.ts +1 -0
- package/dist/ui/input-prompt-v2.js +14 -6
- package/dist/ui/input-prompt.d.ts +116 -33
- package/dist/ui/input-prompt.js +536 -337
- package/dist/ui/iteration-limit-overlay-v2.d.ts +21 -0
- package/dist/ui/iteration-limit-overlay-v2.js +114 -0
- package/dist/ui/iteration-limit-overlay.d.ts +2 -2
- package/dist/ui/iteration-limit-overlay.js +92 -128
- package/dist/ui/keys-overlay-v2.d.ts +41 -0
- package/dist/ui/keys-overlay-v2.js +248 -0
- package/dist/ui/keys-overlay.d.ts +1 -0
- package/dist/ui/keys-overlay.js +203 -141
- package/dist/ui/line-utils.d.ts +88 -0
- package/dist/ui/line-utils.js +150 -0
- package/dist/ui/live-region.d.ts +161 -0
- package/dist/ui/live-region.js +387 -0
- package/dist/ui/mascot/expressions.d.ts +32 -0
- package/dist/ui/mascot/expressions.js +213 -0
- package/dist/ui/mascot/index.d.ts +8 -0
- package/dist/ui/mascot/index.js +8 -0
- package/dist/ui/mascot/renderer.d.ts +19 -0
- package/dist/ui/mascot/renderer.js +97 -0
- package/dist/ui/mascot-overlay-v2.d.ts +41 -0
- package/dist/ui/mascot-overlay-v2.js +138 -0
- package/dist/ui/mascot-overlay.d.ts +21 -0
- package/dist/ui/mascot-overlay.js +146 -0
- package/dist/ui/model-overlay-v2.d.ts +49 -0
- package/dist/ui/model-overlay-v2.js +118 -0
- package/dist/ui/model-overlay.d.ts +27 -0
- package/dist/ui/model-overlay.js +221 -0
- package/dist/ui/model-warning-overlay.js +3 -5
- package/dist/ui/new-overlay.d.ts +34 -0
- package/dist/ui/new-overlay.js +604 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.js +825 -0
- package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
- package/dist/ui/overlay/impl/anchors-overlay-v2.js +783 -0
- package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
- package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.js +584 -0
- package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
- package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.js +642 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.js +441 -0
- package/dist/ui/overlay/impl/config-overlay-v2.d.ts +100 -0
- package/dist/ui/overlay/impl/config-overlay-v2.js +654 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +55 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.js +359 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.js +114 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1071 -0
- package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
- package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
- package/dist/ui/overlay/impl/help-overlay-v2.d.ts +34 -0
- package/dist/ui/overlay/impl/help-overlay-v2.js +309 -0
- package/dist/ui/overlay/impl/init-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/init-overlay-v2.js +593 -0
- package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
- package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
- package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
- package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
- package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
- package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
- package/dist/ui/overlay/impl/model-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/model-overlay-v2.js +118 -0
- package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
- package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
- package/dist/ui/overlay/impl/new-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/new-overlay-v2.js +593 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.js +499 -0
- package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
- package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.js +218 -0
- package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +31 -0
- package/dist/ui/overlay/impl/tutorial-overlay-v2.js +1035 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.js +637 -0
- package/dist/ui/overlay/index.d.ts +33 -0
- package/dist/ui/overlay/index.js +35 -0
- package/dist/ui/overlay/key-utils.d.ts +6 -0
- package/dist/ui/overlay/key-utils.js +6 -0
- package/dist/ui/overlay/overlay-types.d.ts +128 -0
- package/dist/ui/overlay/overlay-types.js +22 -0
- package/dist/ui/overlay/types.d.ts +135 -0
- package/dist/ui/overlay/types.js +22 -0
- package/dist/ui/overlays/help-overlay-v2.d.ts +28 -0
- package/dist/ui/overlays/help-overlay-v2.js +198 -0
- package/dist/ui/overlays/index.d.ts +11 -0
- package/dist/ui/overlays/index.js +11 -0
- package/dist/ui/overlays.d.ts +0 -4
- package/dist/ui/overlays.js +0 -444
- package/dist/ui/permission-overlay-v2.d.ts +36 -0
- package/dist/ui/permission-overlay-v2.js +380 -0
- package/dist/ui/permission-overlay.d.ts +1 -1
- package/dist/ui/permission-overlay.js +186 -298
- package/dist/ui/projects-overlay.d.ts +19 -0
- package/dist/ui/projects-overlay.js +484 -0
- package/dist/ui/providers/types.d.ts +178 -0
- package/dist/ui/providers/types.js +9 -0
- package/dist/ui/render-modes.d.ts +36 -0
- package/dist/ui/render-modes.js +44 -0
- package/dist/ui/startup-menu.d.ts +36 -0
- package/dist/ui/startup-menu.js +236 -0
- package/dist/ui/subagent-renderer.d.ts +117 -0
- package/dist/ui/subagent-renderer.js +334 -0
- package/dist/ui/terminal-codes.d.ts +94 -0
- package/dist/ui/terminal-codes.js +124 -0
- package/dist/ui/terminal-renderer.d.ts +221 -0
- package/dist/ui/terminal-renderer.js +751 -0
- package/dist/ui/terminal-ui.d.ts +463 -0
- package/dist/ui/terminal-ui.js +2296 -0
- package/dist/ui/terminal.d.ts +20 -0
- package/dist/ui/terminal.js +72 -0
- package/dist/ui/theme-overlay-v2.d.ts +42 -0
- package/dist/ui/theme-overlay-v2.js +135 -0
- package/dist/ui/theme-overlay.d.ts +24 -0
- package/dist/ui/theme-overlay.js +127 -0
- package/dist/ui/todo-zone.js +53 -25
- package/dist/ui/tool-formatters.d.ts +16 -0
- package/dist/ui/tool-formatters.js +516 -0
- package/dist/ui/tools-overlay-v2.d.ts +47 -0
- package/dist/ui/tools-overlay-v2.js +218 -0
- package/dist/ui/tools-overlay.d.ts +10 -2
- package/dist/ui/tools-overlay.js +172 -220
- package/dist/ui/tutorial-overlay-v2.d.ts +31 -0
- package/dist/ui/tutorial-overlay-v2.js +1035 -0
- package/dist/ui/tutorial-overlay.d.ts +1 -0
- package/dist/ui/tutorial-overlay.js +400 -302
- package/dist/ui/workflow-overlay.d.ts +22 -0
- package/dist/ui/workflow-overlay.js +636 -0
- package/dist/utils/debug-log.d.ts +28 -0
- package/dist/utils/debug-log.js +57 -0
- package/dist/utils/model-tiers.js +1 -1
- package/dist/utils/path-safety.d.ts +56 -0
- package/dist/utils/path-safety.js +239 -0
- package/dist/workflow/guided-mode-injector.d.ts +42 -0
- package/dist/workflow/guided-mode-injector.js +191 -0
- package/dist/workflow/index.d.ts +8 -0
- package/dist/workflow/index.js +8 -0
- package/dist/workflow/step-criteria.d.ts +62 -0
- package/dist/workflow/step-criteria.js +150 -0
- package/dist/workflow/step-tracker.d.ts +92 -0
- package/dist/workflow/step-tracker.js +141 -0
- package/package.json +12 -5
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agents Overlay V2
|
|
3
|
+
*
|
|
4
|
+
* Modal overlay for viewing and managing agent configurations.
|
|
5
|
+
* Uses TabbedListOverlayV2 for consistent list/tab/search behavior.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Built-in tab: Lists predefined agent types with detail view
|
|
9
|
+
* - Custom tab: Lists user-defined agents with detail/edit + create new
|
|
10
|
+
* - Wizard mode: Step-by-step agent creation
|
|
11
|
+
*/
|
|
12
|
+
import * as terminal from '../../terminal.js';
|
|
13
|
+
import { TabbedListOverlayV2, BaseScreen, stay, popScreen, closeOverlay, isEscape, isCtrlC, isEnter, isNavigateUp, isNavigateDown, isBackspace, isClose, extractPrintable, renderBorder, wrapText, } from '../../base/index.js';
|
|
14
|
+
import { getAgentRegistry } from '../../../agents/registry.js';
|
|
15
|
+
const TABS = [
|
|
16
|
+
{ id: 'builtin', label: 'Built-in' },
|
|
17
|
+
{ id: 'custom', label: 'Custom' },
|
|
18
|
+
];
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Detail Screen (View Agent Info)
|
|
21
|
+
// =============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Screen for viewing agent details.
|
|
24
|
+
* Shows name, model, description, and for custom agents: system prompt.
|
|
25
|
+
* Press 'e' to edit custom agents.
|
|
26
|
+
*/
|
|
27
|
+
class DetailScreen extends BaseScreen {
|
|
28
|
+
item;
|
|
29
|
+
styles;
|
|
30
|
+
editState;
|
|
31
|
+
onEdit;
|
|
32
|
+
constructor(item, styles, editState, onEdit) {
|
|
33
|
+
super();
|
|
34
|
+
this.item = item;
|
|
35
|
+
this.styles = styles;
|
|
36
|
+
this.editState = editState;
|
|
37
|
+
this.onEdit = onEdit;
|
|
38
|
+
}
|
|
39
|
+
render() {
|
|
40
|
+
const s = this.styles;
|
|
41
|
+
const cols = terminal.getTerminalWidth();
|
|
42
|
+
const border = renderBorder(cols, s);
|
|
43
|
+
const lines = [];
|
|
44
|
+
// Header
|
|
45
|
+
lines.push(border);
|
|
46
|
+
lines.push(` ${s.primaryBold('Agent Details')}`);
|
|
47
|
+
lines.push('');
|
|
48
|
+
// Name and model
|
|
49
|
+
lines.push(` ${s.muted('Name:')} ${s.primary(this.item.name)}`);
|
|
50
|
+
lines.push(` ${s.muted('Model:')} ${s.secondary(this.item.model)}`);
|
|
51
|
+
lines.push(` ${s.muted('Type:')} ${this.item.isBuiltin ? s.muted('Built-in') : s.secondary('Custom')}`);
|
|
52
|
+
// Location for custom agents
|
|
53
|
+
if (!this.item.isBuiltin && this.item.location) {
|
|
54
|
+
const locationLabel = this.item.location === 'project' ? 'Project' : 'Personal';
|
|
55
|
+
lines.push(` ${s.muted('Location:')} ${s.secondary(locationLabel)}`);
|
|
56
|
+
}
|
|
57
|
+
lines.push('');
|
|
58
|
+
// Description
|
|
59
|
+
lines.push(` ${s.muted('Description:')}`);
|
|
60
|
+
const descLines = wrapText(this.item.description, cols - 6);
|
|
61
|
+
for (const line of descLines) {
|
|
62
|
+
lines.push(` ${s.secondary(line)}`);
|
|
63
|
+
}
|
|
64
|
+
// System prompt for custom agents
|
|
65
|
+
if (!this.item.isBuiltin && this.item.systemPrompt) {
|
|
66
|
+
lines.push('');
|
|
67
|
+
lines.push(` ${s.muted('System Prompt:')}`);
|
|
68
|
+
// Show first few lines of system prompt
|
|
69
|
+
const promptLines = this.item.systemPrompt.split('\n').slice(0, 5);
|
|
70
|
+
for (const line of promptLines) {
|
|
71
|
+
const truncated = line.length > cols - 6 ? line.slice(0, cols - 9) + '...' : line;
|
|
72
|
+
lines.push(` ${s.secondary(truncated)}`);
|
|
73
|
+
}
|
|
74
|
+
if (this.item.systemPrompt.split('\n').length > 5) {
|
|
75
|
+
lines.push(` ${s.muted('...')}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// File path for custom agents
|
|
79
|
+
if (!this.item.isBuiltin && this.item.filePath) {
|
|
80
|
+
lines.push('');
|
|
81
|
+
lines.push(` ${s.muted('File:')} ${s.secondary(this.item.filePath)}`);
|
|
82
|
+
}
|
|
83
|
+
// Usage hint for built-in agents
|
|
84
|
+
if (this.item.isBuiltin) {
|
|
85
|
+
lines.push('');
|
|
86
|
+
lines.push(` ${s.muted('Usage:')}`);
|
|
87
|
+
lines.push(` ${s.secondary('This agent is invoked via the Task tool.')}`);
|
|
88
|
+
lines.push(` ${s.secondary(`Example: Task(subagent_type="${this.item.name}", prompt="...")`)}`);
|
|
89
|
+
}
|
|
90
|
+
lines.push('');
|
|
91
|
+
lines.push(border);
|
|
92
|
+
// Show edit hint for custom agents
|
|
93
|
+
if (!this.item.isBuiltin) {
|
|
94
|
+
lines.push(` ${s.muted('e Edit · q/Esc Back')}`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
lines.push(` ${s.muted('q/Esc Back')}`);
|
|
98
|
+
}
|
|
99
|
+
lines.push(border);
|
|
100
|
+
return lines;
|
|
101
|
+
}
|
|
102
|
+
handleKey(data) {
|
|
103
|
+
// Ctrl+C closes everything
|
|
104
|
+
if (isCtrlC(data)) {
|
|
105
|
+
return closeOverlay(undefined);
|
|
106
|
+
}
|
|
107
|
+
// Escape or q - back to list
|
|
108
|
+
if (isEscape(data) || isClose(data)) {
|
|
109
|
+
return popScreen();
|
|
110
|
+
}
|
|
111
|
+
// 'e' opens edit screen for custom agents
|
|
112
|
+
const char = extractPrintable(data);
|
|
113
|
+
if (char === 'e' && !this.item.isBuiltin) {
|
|
114
|
+
const editScreen = new EditScreen(this.item, this.editState, this.styles);
|
|
115
|
+
this.onEdit(editScreen);
|
|
116
|
+
return stay();
|
|
117
|
+
}
|
|
118
|
+
return stay(false);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Minimum height for stable rendering.
|
|
122
|
+
*/
|
|
123
|
+
getMinHeight() {
|
|
124
|
+
return 25;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Screen for editing an existing custom agent.
|
|
129
|
+
* Allows editing: model, description, system prompt.
|
|
130
|
+
* Also allows deleting the agent.
|
|
131
|
+
*/
|
|
132
|
+
class EditScreen extends BaseScreen {
|
|
133
|
+
originalItem;
|
|
134
|
+
editState;
|
|
135
|
+
styles;
|
|
136
|
+
step = 'field-select';
|
|
137
|
+
selectedOption = 0;
|
|
138
|
+
inputBuffer = '';
|
|
139
|
+
error = null;
|
|
140
|
+
// Working copy of agent data (location is only 'project' | 'personal' since we don't edit built-in)
|
|
141
|
+
editedAgent;
|
|
142
|
+
constructor(originalItem, editState, styles) {
|
|
143
|
+
super();
|
|
144
|
+
this.originalItem = originalItem;
|
|
145
|
+
this.editState = editState;
|
|
146
|
+
this.styles = styles;
|
|
147
|
+
// Initialize with current values
|
|
148
|
+
// Custom agents can only be 'project' or 'personal', never 'builtin'
|
|
149
|
+
const loc = originalItem.location;
|
|
150
|
+
this.editedAgent = {
|
|
151
|
+
name: originalItem.name,
|
|
152
|
+
prompt: originalItem.systemPrompt ?? '',
|
|
153
|
+
description: originalItem.description,
|
|
154
|
+
model: originalItem.model,
|
|
155
|
+
location: (loc === 'project' || loc === 'personal') ? loc : 'project',
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
render() {
|
|
159
|
+
const s = this.styles;
|
|
160
|
+
const cols = terminal.getTerminalWidth();
|
|
161
|
+
const border = renderBorder(cols, s);
|
|
162
|
+
const lines = [];
|
|
163
|
+
lines.push(border);
|
|
164
|
+
lines.push(` ${s.primaryBold('Edit Agent:')} ${s.primary(this.originalItem.name)}`);
|
|
165
|
+
lines.push('');
|
|
166
|
+
switch (this.step) {
|
|
167
|
+
case 'field-select': {
|
|
168
|
+
lines.push(` ${s.secondary('Select field to edit:')}`);
|
|
169
|
+
lines.push('');
|
|
170
|
+
const fields = [
|
|
171
|
+
{ id: 'model', label: 'Model', value: this.editedAgent.model },
|
|
172
|
+
{ id: 'description', label: 'Description', value: this.truncate(this.editedAgent.description, 40) },
|
|
173
|
+
{ id: 'prompt', label: 'System Prompt', value: this.truncate(this.editedAgent.prompt, 40) },
|
|
174
|
+
{ id: 'save', label: 'Save Changes', value: '' },
|
|
175
|
+
{ id: 'delete', label: 'Delete Agent', value: '' },
|
|
176
|
+
{ id: 'cancel', label: 'Cancel', value: '' },
|
|
177
|
+
];
|
|
178
|
+
for (let i = 0; i < fields.length; i++) {
|
|
179
|
+
const f = fields[i];
|
|
180
|
+
const isSelected = this.selectedOption === i;
|
|
181
|
+
const prefix = isSelected ? s.primary('❯ ') : ' ';
|
|
182
|
+
if (f.id === 'save') {
|
|
183
|
+
const label = s.primary(f.label);
|
|
184
|
+
lines.push(` ${prefix}${isSelected ? label : s.muted(f.label)}`);
|
|
185
|
+
}
|
|
186
|
+
else if (f.id === 'delete') {
|
|
187
|
+
const label = s.error(f.label);
|
|
188
|
+
lines.push(` ${prefix}${isSelected ? label : s.muted(f.label)}`);
|
|
189
|
+
}
|
|
190
|
+
else if (f.id === 'cancel') {
|
|
191
|
+
lines.push(` ${prefix}${isSelected ? s.secondary(f.label) : s.muted(f.label)}`);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
const label = `${f.label.padEnd(16)}${f.value}`;
|
|
195
|
+
lines.push(` ${prefix}${isSelected ? s.primary(label) : s.muted(label)}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case 'edit-model': {
|
|
201
|
+
lines.push(` ${s.secondary('Select model')}`);
|
|
202
|
+
lines.push('');
|
|
203
|
+
const models = [
|
|
204
|
+
{ id: 'sonnet', label: 'Sonnet', desc: 'Balanced (recommended)' },
|
|
205
|
+
{ id: 'opus', label: 'Opus', desc: 'Most capable' },
|
|
206
|
+
{ id: 'haiku', label: 'Haiku', desc: 'Fast and efficient' },
|
|
207
|
+
{ id: 'inherit', label: 'Inherit', desc: "Use parent's model" },
|
|
208
|
+
];
|
|
209
|
+
for (let i = 0; i < models.length; i++) {
|
|
210
|
+
const m = models[i];
|
|
211
|
+
const isSelected = this.selectedOption === i;
|
|
212
|
+
const prefix = isSelected ? s.primary('❯ ') : ' ';
|
|
213
|
+
const current = this.editedAgent.model === m.id ? s.muted(' (current)') : '';
|
|
214
|
+
const label = `${String(i + 1)}. ${m.label.padEnd(10)} - ${m.desc}${current}`;
|
|
215
|
+
lines.push(` ${prefix}${isSelected ? s.primary(label) : s.muted(label)}`);
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case 'edit-description':
|
|
220
|
+
lines.push(` ${s.secondary('Edit description')}`);
|
|
221
|
+
lines.push('');
|
|
222
|
+
lines.push(` When should the LLM use this agent?`);
|
|
223
|
+
lines.push(` > ${this.inputBuffer}█`);
|
|
224
|
+
lines.push('');
|
|
225
|
+
if (this.error) {
|
|
226
|
+
lines.push(` ${s.error(this.error)}`);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
lines.push(` ${s.muted('Press Enter to save, Esc to cancel')}`);
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
case 'edit-prompt':
|
|
233
|
+
lines.push(` ${s.secondary('Edit system prompt')}`);
|
|
234
|
+
lines.push('');
|
|
235
|
+
lines.push(` Enter the agent's instructions:`);
|
|
236
|
+
lines.push(` > ${this.inputBuffer}█`);
|
|
237
|
+
lines.push('');
|
|
238
|
+
if (this.error) {
|
|
239
|
+
lines.push(` ${s.error(this.error)}`);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
lines.push(` ${s.muted('Press Enter to save, Esc to cancel')}`);
|
|
243
|
+
lines.push(` ${s.muted('(For multiline prompts, edit the .md file directly)')}`);
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
case 'confirm-delete':
|
|
247
|
+
lines.push(` ${s.error('Delete this agent?')}`);
|
|
248
|
+
lines.push('');
|
|
249
|
+
lines.push(` ${s.muted('Name:')} ${s.primary(this.originalItem.name)}`);
|
|
250
|
+
lines.push(` ${s.muted('File:')} ${s.secondary(this.originalItem.filePath ?? 'unknown')}`);
|
|
251
|
+
lines.push('');
|
|
252
|
+
lines.push(this.selectedOption === 0
|
|
253
|
+
? ` ${s.error('❯ Yes, delete')}`
|
|
254
|
+
: ` ${s.muted(' Yes, delete')}`);
|
|
255
|
+
lines.push(this.selectedOption === 1
|
|
256
|
+
? ` ${s.primary('❯ No, cancel')}`
|
|
257
|
+
: ` ${s.muted(' No, cancel')}`);
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
lines.push('');
|
|
261
|
+
lines.push(border);
|
|
262
|
+
lines.push(` ${s.muted('Esc Back')}`);
|
|
263
|
+
lines.push(border);
|
|
264
|
+
return lines;
|
|
265
|
+
}
|
|
266
|
+
handleKey(data) {
|
|
267
|
+
const char = extractPrintable(data);
|
|
268
|
+
// Ctrl+C closes everything
|
|
269
|
+
if (isCtrlC(data)) {
|
|
270
|
+
return closeOverlay(undefined);
|
|
271
|
+
}
|
|
272
|
+
// Escape goes back
|
|
273
|
+
if (isEscape(data)) {
|
|
274
|
+
return this.handleBack();
|
|
275
|
+
}
|
|
276
|
+
// Text input steps
|
|
277
|
+
if (this.step === 'edit-description' || this.step === 'edit-prompt') {
|
|
278
|
+
if (isEnter(data)) {
|
|
279
|
+
const text = this.inputBuffer.trim();
|
|
280
|
+
if (!text) {
|
|
281
|
+
this.error = 'Cannot be empty';
|
|
282
|
+
return stay();
|
|
283
|
+
}
|
|
284
|
+
if (this.step === 'edit-description') {
|
|
285
|
+
this.editedAgent.description = text;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
this.editedAgent.prompt = text;
|
|
289
|
+
}
|
|
290
|
+
this.step = 'field-select';
|
|
291
|
+
this.inputBuffer = '';
|
|
292
|
+
this.error = null;
|
|
293
|
+
return stay();
|
|
294
|
+
}
|
|
295
|
+
if (isBackspace(data)) {
|
|
296
|
+
this.inputBuffer = this.inputBuffer.slice(0, -1);
|
|
297
|
+
this.error = null;
|
|
298
|
+
return stay();
|
|
299
|
+
}
|
|
300
|
+
if (char) {
|
|
301
|
+
this.inputBuffer += char;
|
|
302
|
+
this.error = null;
|
|
303
|
+
return stay();
|
|
304
|
+
}
|
|
305
|
+
return stay(false);
|
|
306
|
+
}
|
|
307
|
+
// Selection steps
|
|
308
|
+
const maxOptions = this.step === 'field-select' ? 6 : this.step === 'edit-model' ? 4 : 2;
|
|
309
|
+
if (isNavigateUp(data) && this.selectedOption > 0) {
|
|
310
|
+
this.selectedOption--;
|
|
311
|
+
return stay();
|
|
312
|
+
}
|
|
313
|
+
if (isNavigateDown(data) && this.selectedOption < maxOptions - 1) {
|
|
314
|
+
this.selectedOption++;
|
|
315
|
+
return stay();
|
|
316
|
+
}
|
|
317
|
+
if (isEnter(data)) {
|
|
318
|
+
return this.handleSelect();
|
|
319
|
+
}
|
|
320
|
+
return stay(false);
|
|
321
|
+
}
|
|
322
|
+
handleBack() {
|
|
323
|
+
switch (this.step) {
|
|
324
|
+
case 'field-select':
|
|
325
|
+
return popScreen();
|
|
326
|
+
case 'edit-model':
|
|
327
|
+
case 'edit-description':
|
|
328
|
+
case 'edit-prompt':
|
|
329
|
+
case 'confirm-delete':
|
|
330
|
+
this.step = 'field-select';
|
|
331
|
+
this.selectedOption = 0;
|
|
332
|
+
this.inputBuffer = '';
|
|
333
|
+
this.error = null;
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
return stay();
|
|
337
|
+
}
|
|
338
|
+
handleSelect() {
|
|
339
|
+
switch (this.step) {
|
|
340
|
+
case 'field-select':
|
|
341
|
+
switch (this.selectedOption) {
|
|
342
|
+
case 0: { // Model
|
|
343
|
+
this.step = 'edit-model';
|
|
344
|
+
const models = ['sonnet', 'opus', 'haiku', 'inherit'];
|
|
345
|
+
this.selectedOption = models.indexOf(this.editedAgent.model);
|
|
346
|
+
if (this.selectedOption < 0)
|
|
347
|
+
this.selectedOption = 0;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case 1: // Description
|
|
351
|
+
this.step = 'edit-description';
|
|
352
|
+
this.inputBuffer = this.editedAgent.description;
|
|
353
|
+
break;
|
|
354
|
+
case 2: // System Prompt
|
|
355
|
+
this.step = 'edit-prompt';
|
|
356
|
+
this.inputBuffer = this.editedAgent.prompt;
|
|
357
|
+
break;
|
|
358
|
+
case 3: // Save
|
|
359
|
+
return this.saveAgent();
|
|
360
|
+
case 4: // Delete
|
|
361
|
+
this.step = 'confirm-delete';
|
|
362
|
+
this.selectedOption = 1; // Default to "No"
|
|
363
|
+
break;
|
|
364
|
+
case 5: // Cancel
|
|
365
|
+
return popScreen();
|
|
366
|
+
}
|
|
367
|
+
break;
|
|
368
|
+
case 'edit-model': {
|
|
369
|
+
const models = ['sonnet', 'opus', 'haiku', 'inherit'];
|
|
370
|
+
this.editedAgent.model = models[this.selectedOption];
|
|
371
|
+
this.step = 'field-select';
|
|
372
|
+
this.selectedOption = 0;
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
case 'confirm-delete':
|
|
376
|
+
if (this.selectedOption === 0) {
|
|
377
|
+
// Delete
|
|
378
|
+
return this.deleteAgent();
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
// Cancel
|
|
382
|
+
this.step = 'field-select';
|
|
383
|
+
this.selectedOption = 0;
|
|
384
|
+
}
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
return stay();
|
|
388
|
+
}
|
|
389
|
+
saveAgent() {
|
|
390
|
+
try {
|
|
391
|
+
this.editState.registry.saveAgent({
|
|
392
|
+
name: this.editedAgent.name,
|
|
393
|
+
description: this.editedAgent.description,
|
|
394
|
+
model: this.editedAgent.model,
|
|
395
|
+
systemPrompt: this.editedAgent.prompt,
|
|
396
|
+
}, this.editedAgent.location);
|
|
397
|
+
this.editState.registry.load();
|
|
398
|
+
// Pop back to list with result
|
|
399
|
+
return closeOverlay({ edited: this.editedAgent.name });
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
this.error = error.message;
|
|
403
|
+
return stay();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
deleteAgent() {
|
|
407
|
+
try {
|
|
408
|
+
this.editState.registry.deleteAgent(this.originalItem.name);
|
|
409
|
+
this.editState.registry.load();
|
|
410
|
+
// Close with result
|
|
411
|
+
return closeOverlay({ deleted: this.originalItem.name });
|
|
412
|
+
}
|
|
413
|
+
catch (error) {
|
|
414
|
+
this.error = error.message;
|
|
415
|
+
return stay();
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
truncate(text, max) {
|
|
419
|
+
if (!text)
|
|
420
|
+
return '';
|
|
421
|
+
if (text.length <= max)
|
|
422
|
+
return text;
|
|
423
|
+
return text.slice(0, max - 3) + '...';
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Minimum height for stable rendering.
|
|
427
|
+
*/
|
|
428
|
+
getMinHeight() {
|
|
429
|
+
return 20;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
// =============================================================================
|
|
433
|
+
// Wizard Screen (Multi-Step Agent Creation)
|
|
434
|
+
// =============================================================================
|
|
435
|
+
/**
|
|
436
|
+
* Screen for creating a new agent via multi-step wizard.
|
|
437
|
+
* Steps: location, name, prompt, description, model, confirm
|
|
438
|
+
*/
|
|
439
|
+
class WizardScreen extends BaseScreen {
|
|
440
|
+
editState;
|
|
441
|
+
styles;
|
|
442
|
+
step = 'location';
|
|
443
|
+
selectedOption = 0;
|
|
444
|
+
inputBuffer = '';
|
|
445
|
+
error = null;
|
|
446
|
+
newAgent = {
|
|
447
|
+
location: 'project',
|
|
448
|
+
name: '',
|
|
449
|
+
prompt: '',
|
|
450
|
+
description: '',
|
|
451
|
+
model: 'sonnet',
|
|
452
|
+
};
|
|
453
|
+
constructor(editState, styles) {
|
|
454
|
+
super();
|
|
455
|
+
this.editState = editState;
|
|
456
|
+
this.styles = styles;
|
|
457
|
+
}
|
|
458
|
+
render() {
|
|
459
|
+
const s = this.styles;
|
|
460
|
+
const cols = terminal.getTerminalWidth();
|
|
461
|
+
const border = renderBorder(cols, s);
|
|
462
|
+
const lines = [];
|
|
463
|
+
lines.push(border);
|
|
464
|
+
lines.push(` ${s.primaryBold('Create New Agent')}`);
|
|
465
|
+
lines.push('');
|
|
466
|
+
switch (this.step) {
|
|
467
|
+
case 'location':
|
|
468
|
+
lines.push(` ${s.secondary('Choose location')}`);
|
|
469
|
+
lines.push('');
|
|
470
|
+
lines.push(this.selectedOption === 0
|
|
471
|
+
? ` ${s.primary('❯ 1. Project (.compilr-dev/agents/)')}`
|
|
472
|
+
: ` ${s.muted(' 1. Project (.compilr-dev/agents/)')}`);
|
|
473
|
+
lines.push(this.selectedOption === 1
|
|
474
|
+
? ` ${s.primary('❯ 2. Personal (~/.compilr-dev/agents/)')}`
|
|
475
|
+
: ` ${s.muted(' 2. Personal (~/.compilr-dev/agents/)')}`);
|
|
476
|
+
lines.push('');
|
|
477
|
+
lines.push(` ${s.muted('Project agents are shared with your team.')}`);
|
|
478
|
+
lines.push(` ${s.muted('Personal agents apply to all your projects.')}`);
|
|
479
|
+
break;
|
|
480
|
+
case 'name':
|
|
481
|
+
lines.push(` ${s.secondary('Agent name (identifier)')}`);
|
|
482
|
+
lines.push('');
|
|
483
|
+
lines.push(` Enter a unique identifier:`);
|
|
484
|
+
lines.push(` > ${this.inputBuffer}█`);
|
|
485
|
+
lines.push('');
|
|
486
|
+
if (this.error) {
|
|
487
|
+
lines.push(` ${s.error(this.error)}`);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
lines.push(` ${s.muted('Use lowercase letters, numbers, hyphens (e.g., code-reviewer)')}`);
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
case 'prompt':
|
|
494
|
+
lines.push(` ${s.secondary('System prompt')}`);
|
|
495
|
+
lines.push('');
|
|
496
|
+
lines.push(` Enter the agent's instructions:`);
|
|
497
|
+
lines.push(` > ${this.inputBuffer}█`);
|
|
498
|
+
lines.push('');
|
|
499
|
+
lines.push(` ${s.muted('This defines how the agent behaves.')}`);
|
|
500
|
+
lines.push(` ${s.muted('Press Enter to continue.')}`);
|
|
501
|
+
break;
|
|
502
|
+
case 'description':
|
|
503
|
+
lines.push(` ${s.secondary('Description')}`);
|
|
504
|
+
lines.push('');
|
|
505
|
+
lines.push(` When should the LLM use this agent?`);
|
|
506
|
+
lines.push(` > ${this.inputBuffer}█`);
|
|
507
|
+
lines.push('');
|
|
508
|
+
lines.push(` ${s.muted('This helps the LLM know when to invoke this agent.')}`);
|
|
509
|
+
break;
|
|
510
|
+
case 'model': {
|
|
511
|
+
lines.push(` ${s.secondary('Select model')}`);
|
|
512
|
+
lines.push('');
|
|
513
|
+
const models = [
|
|
514
|
+
{ id: 'sonnet', label: 'Sonnet', desc: 'Balanced (recommended)' },
|
|
515
|
+
{ id: 'opus', label: 'Opus', desc: 'Most capable' },
|
|
516
|
+
{ id: 'haiku', label: 'Haiku', desc: 'Fast and efficient' },
|
|
517
|
+
{ id: 'inherit', label: 'Inherit', desc: "Use parent's model" },
|
|
518
|
+
];
|
|
519
|
+
for (let i = 0; i < models.length; i++) {
|
|
520
|
+
const m = models[i];
|
|
521
|
+
const isSelected = this.selectedOption === i;
|
|
522
|
+
const prefix = isSelected ? s.primary('❯ ') : ' ';
|
|
523
|
+
const label = `${String(i + 1)}. ${m.label.padEnd(10)} - ${m.desc}`;
|
|
524
|
+
lines.push(` ${prefix}${isSelected ? s.primary(label) : s.muted(label)}`);
|
|
525
|
+
}
|
|
526
|
+
break;
|
|
527
|
+
}
|
|
528
|
+
case 'confirm': {
|
|
529
|
+
lines.push(` ${s.secondary('Confirm')}`);
|
|
530
|
+
lines.push('');
|
|
531
|
+
lines.push(` Name: ${s.primary(this.newAgent.name)}`);
|
|
532
|
+
lines.push(` Location: ${s.primary(this.newAgent.location === 'project' ? '.compilr-dev/agents/' : '~/.compilr-dev/agents/')}${this.newAgent.name}.md`);
|
|
533
|
+
lines.push(` Model: ${s.primary(this.newAgent.model)}`);
|
|
534
|
+
lines.push('');
|
|
535
|
+
lines.push(` ${s.secondary('Description:')}`);
|
|
536
|
+
const descPreview = this.newAgent.description.length > 60
|
|
537
|
+
? this.newAgent.description.slice(0, 57) + '...'
|
|
538
|
+
: this.newAgent.description;
|
|
539
|
+
lines.push(` ${s.muted(descPreview)}`);
|
|
540
|
+
lines.push('');
|
|
541
|
+
lines.push(` ${s.secondary('System prompt:')}`);
|
|
542
|
+
const promptPreview = this.newAgent.prompt.length > 60
|
|
543
|
+
? this.newAgent.prompt.slice(0, 57) + '...'
|
|
544
|
+
: this.newAgent.prompt;
|
|
545
|
+
lines.push(` ${s.muted(promptPreview)}`);
|
|
546
|
+
lines.push('');
|
|
547
|
+
lines.push(this.selectedOption === 0
|
|
548
|
+
? ` ${s.primary('❯ Save')}`
|
|
549
|
+
: ` ${s.muted(' Save')}`);
|
|
550
|
+
lines.push(this.selectedOption === 1
|
|
551
|
+
? ` ${s.primary('❯ Cancel')}`
|
|
552
|
+
: ` ${s.muted(' Cancel')}`);
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
lines.push('');
|
|
557
|
+
lines.push(border);
|
|
558
|
+
lines.push(` ${s.muted('Esc Back')}`);
|
|
559
|
+
lines.push(border);
|
|
560
|
+
return lines;
|
|
561
|
+
}
|
|
562
|
+
handleKey(data) {
|
|
563
|
+
const char = extractPrintable(data);
|
|
564
|
+
// Ctrl+C closes everything
|
|
565
|
+
if (isCtrlC(data)) {
|
|
566
|
+
return closeOverlay(undefined);
|
|
567
|
+
}
|
|
568
|
+
// Escape goes back
|
|
569
|
+
if (isEscape(data)) {
|
|
570
|
+
return this.handleBack();
|
|
571
|
+
}
|
|
572
|
+
// Input steps: name, prompt, description
|
|
573
|
+
if (this.step === 'name' || this.step === 'prompt' || this.step === 'description') {
|
|
574
|
+
if (isEnter(data)) {
|
|
575
|
+
const text = this.inputBuffer.trim();
|
|
576
|
+
if (!text) {
|
|
577
|
+
return stay(false);
|
|
578
|
+
}
|
|
579
|
+
// Validate name
|
|
580
|
+
if (this.step === 'name') {
|
|
581
|
+
if (!/^[a-z][a-z0-9-]{1,49}$/.test(text)) {
|
|
582
|
+
this.error = 'Invalid name. Use lowercase letters, numbers, hyphens.';
|
|
583
|
+
return stay();
|
|
584
|
+
}
|
|
585
|
+
if (this.editState.registry.hasAgent(text)) {
|
|
586
|
+
this.error = `Agent "${text}" already exists.`;
|
|
587
|
+
return stay();
|
|
588
|
+
}
|
|
589
|
+
this.newAgent.name = text;
|
|
590
|
+
this.step = 'prompt';
|
|
591
|
+
this.inputBuffer = '';
|
|
592
|
+
this.error = null;
|
|
593
|
+
}
|
|
594
|
+
else if (this.step === 'prompt') {
|
|
595
|
+
this.newAgent.prompt = text;
|
|
596
|
+
this.step = 'description';
|
|
597
|
+
this.inputBuffer = '';
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
this.newAgent.description = text;
|
|
601
|
+
this.step = 'model';
|
|
602
|
+
this.selectedOption = 0;
|
|
603
|
+
}
|
|
604
|
+
return stay();
|
|
605
|
+
}
|
|
606
|
+
if (isBackspace(data)) {
|
|
607
|
+
this.inputBuffer = this.inputBuffer.slice(0, -1);
|
|
608
|
+
this.error = null;
|
|
609
|
+
return stay();
|
|
610
|
+
}
|
|
611
|
+
if (char) {
|
|
612
|
+
this.inputBuffer += char;
|
|
613
|
+
this.error = null;
|
|
614
|
+
return stay();
|
|
615
|
+
}
|
|
616
|
+
return stay(false);
|
|
617
|
+
}
|
|
618
|
+
// Selection steps: location, model, confirm
|
|
619
|
+
const maxOptions = this.step === 'model' ? 4 : 2;
|
|
620
|
+
if (isNavigateUp(data) && this.selectedOption > 0) {
|
|
621
|
+
this.selectedOption--;
|
|
622
|
+
return stay();
|
|
623
|
+
}
|
|
624
|
+
if (isNavigateDown(data) && this.selectedOption < maxOptions - 1) {
|
|
625
|
+
this.selectedOption++;
|
|
626
|
+
return stay();
|
|
627
|
+
}
|
|
628
|
+
if (isEnter(data)) {
|
|
629
|
+
return this.handleSelect();
|
|
630
|
+
}
|
|
631
|
+
return stay(false);
|
|
632
|
+
}
|
|
633
|
+
handleBack() {
|
|
634
|
+
switch (this.step) {
|
|
635
|
+
case 'location':
|
|
636
|
+
return popScreen();
|
|
637
|
+
case 'name':
|
|
638
|
+
this.step = 'location';
|
|
639
|
+
this.selectedOption = this.newAgent.location === 'project' ? 0 : 1;
|
|
640
|
+
break;
|
|
641
|
+
case 'prompt':
|
|
642
|
+
this.step = 'name';
|
|
643
|
+
this.inputBuffer = this.newAgent.name;
|
|
644
|
+
break;
|
|
645
|
+
case 'description':
|
|
646
|
+
this.step = 'prompt';
|
|
647
|
+
this.inputBuffer = this.newAgent.prompt;
|
|
648
|
+
break;
|
|
649
|
+
case 'model':
|
|
650
|
+
this.step = 'description';
|
|
651
|
+
this.inputBuffer = this.newAgent.description;
|
|
652
|
+
break;
|
|
653
|
+
case 'confirm': {
|
|
654
|
+
this.step = 'model';
|
|
655
|
+
const models = ['sonnet', 'opus', 'haiku', 'inherit'];
|
|
656
|
+
this.selectedOption = models.indexOf(this.newAgent.model);
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
this.error = null;
|
|
661
|
+
return stay();
|
|
662
|
+
}
|
|
663
|
+
handleSelect() {
|
|
664
|
+
switch (this.step) {
|
|
665
|
+
case 'location':
|
|
666
|
+
this.newAgent.location = this.selectedOption === 0 ? 'project' : 'personal';
|
|
667
|
+
this.step = 'name';
|
|
668
|
+
this.inputBuffer = '';
|
|
669
|
+
break;
|
|
670
|
+
case 'model': {
|
|
671
|
+
const models = ['sonnet', 'opus', 'haiku', 'inherit'];
|
|
672
|
+
this.newAgent.model = models[this.selectedOption];
|
|
673
|
+
this.step = 'confirm';
|
|
674
|
+
this.selectedOption = 0;
|
|
675
|
+
break;
|
|
676
|
+
}
|
|
677
|
+
case 'confirm':
|
|
678
|
+
if (this.selectedOption === 0) {
|
|
679
|
+
// Save
|
|
680
|
+
try {
|
|
681
|
+
this.editState.registry.saveAgent({
|
|
682
|
+
name: this.newAgent.name,
|
|
683
|
+
description: this.newAgent.description,
|
|
684
|
+
model: this.newAgent.model,
|
|
685
|
+
systemPrompt: this.newAgent.prompt,
|
|
686
|
+
}, this.newAgent.location);
|
|
687
|
+
this.editState.registry.load();
|
|
688
|
+
return closeOverlay({ created: this.newAgent.name });
|
|
689
|
+
}
|
|
690
|
+
catch (error) {
|
|
691
|
+
this.error = error.message;
|
|
692
|
+
return stay();
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
else {
|
|
696
|
+
// Cancel
|
|
697
|
+
return popScreen();
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
return stay();
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Minimum height for stable rendering.
|
|
704
|
+
*/
|
|
705
|
+
getMinHeight() {
|
|
706
|
+
return 22;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
// =============================================================================
|
|
710
|
+
// Agents Overlay V2 Class
|
|
711
|
+
// =============================================================================
|
|
712
|
+
export class AgentsOverlayV2 extends TabbedListOverlayV2 {
|
|
713
|
+
type = 'inline';
|
|
714
|
+
id = 'agents-overlay-v2';
|
|
715
|
+
editState;
|
|
716
|
+
constructor() {
|
|
717
|
+
const registry = getAgentRegistry();
|
|
718
|
+
registry.load();
|
|
719
|
+
// Build items from registry
|
|
720
|
+
const items = AgentsOverlayV2.buildItems(registry);
|
|
721
|
+
super({
|
|
722
|
+
title: 'Agents',
|
|
723
|
+
tabs: TABS,
|
|
724
|
+
items,
|
|
725
|
+
pageSize: 12,
|
|
726
|
+
filterByTab: (item, tabId) => {
|
|
727
|
+
if (tabId === 'builtin')
|
|
728
|
+
return item.isBuiltin;
|
|
729
|
+
return !item.isBuiltin;
|
|
730
|
+
},
|
|
731
|
+
getSearchText: (item) => `${item.name} ${item.description}`,
|
|
732
|
+
renderItem: (item, isSelected, styles) => {
|
|
733
|
+
const prefix = isSelected ? styles.primary('❯ ') : ' ';
|
|
734
|
+
// Special "Create new agent" option
|
|
735
|
+
if (item.isCreateNew) {
|
|
736
|
+
return isSelected
|
|
737
|
+
? `${prefix}${styles.primary('Create new agent')}`
|
|
738
|
+
: `${prefix}${styles.muted('Create new agent')}`;
|
|
739
|
+
}
|
|
740
|
+
const name = `${item.name} · ${item.model}`;
|
|
741
|
+
const nameStyled = isSelected
|
|
742
|
+
? styles.primary(name.padEnd(30))
|
|
743
|
+
: styles.secondary(name.padEnd(30));
|
|
744
|
+
if (item.isBuiltin) {
|
|
745
|
+
return `${prefix}${nameStyled}${styles.muted(item.description)}`;
|
|
746
|
+
}
|
|
747
|
+
else {
|
|
748
|
+
return `${prefix}${nameStyled}${styles.muted(`(${item.location ?? 'unknown'})`)}`;
|
|
749
|
+
}
|
|
750
|
+
},
|
|
751
|
+
showCount: true,
|
|
752
|
+
emptyMessage: 'No agents found.',
|
|
753
|
+
noResultsMessage: 'No agents match the search.',
|
|
754
|
+
footerHints: (searchMode) => {
|
|
755
|
+
if (searchMode) {
|
|
756
|
+
return 'Type to search · Enter/Esc Exit search · Backspace Delete';
|
|
757
|
+
}
|
|
758
|
+
return '/ Search · ↑↓/jk Navigate · Tab Switch tabs · Enter Details · q/Esc Close';
|
|
759
|
+
},
|
|
760
|
+
});
|
|
761
|
+
this.editState = { registry };
|
|
762
|
+
}
|
|
763
|
+
static buildItems(registry) {
|
|
764
|
+
const items = [];
|
|
765
|
+
// Add built-in agents
|
|
766
|
+
for (const agent of registry.getBuiltinAgents()) {
|
|
767
|
+
items.push(AgentsOverlayV2.agentToItem(agent, true));
|
|
768
|
+
}
|
|
769
|
+
// Add custom agents
|
|
770
|
+
for (const agent of registry.getCustomAgents()) {
|
|
771
|
+
items.push(AgentsOverlayV2.agentToItem(agent, false));
|
|
772
|
+
}
|
|
773
|
+
// Add "Create new agent" option for custom tab
|
|
774
|
+
items.push({
|
|
775
|
+
name: '',
|
|
776
|
+
model: '',
|
|
777
|
+
description: '',
|
|
778
|
+
isBuiltin: false,
|
|
779
|
+
isCreateNew: true,
|
|
780
|
+
});
|
|
781
|
+
return items;
|
|
782
|
+
}
|
|
783
|
+
static agentToItem(agent, isBuiltin) {
|
|
784
|
+
return {
|
|
785
|
+
name: agent.name,
|
|
786
|
+
model: agent.model,
|
|
787
|
+
description: agent.description,
|
|
788
|
+
location: agent.location,
|
|
789
|
+
systemPrompt: agent.systemPrompt,
|
|
790
|
+
filePath: agent.filePath,
|
|
791
|
+
isBuiltin,
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
createDetailScreen(item) {
|
|
795
|
+
// "Create new agent" opens the wizard
|
|
796
|
+
if (item.isCreateNew) {
|
|
797
|
+
return new WizardScreen(this.editState, this.getStyles());
|
|
798
|
+
}
|
|
799
|
+
// All other agents open the detail view
|
|
800
|
+
// The onEdit callback pushes the edit screen when user presses 'e'
|
|
801
|
+
return new DetailScreen(item, this.getStyles(), this.editState, (editScreen) => {
|
|
802
|
+
this.screenStack.push(editScreen);
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Refresh items after wizard/edit completes.
|
|
807
|
+
*/
|
|
808
|
+
refreshItems() {
|
|
809
|
+
this.editState.registry.load();
|
|
810
|
+
const items = AgentsOverlayV2.buildItems(this.editState.registry);
|
|
811
|
+
this.state.items = items;
|
|
812
|
+
// Re-apply filters
|
|
813
|
+
const currentTabId = this.listConfig.tabs[this.state.currentTab]?.id ?? 'builtin';
|
|
814
|
+
let filtered = items.filter((item) => this.listConfig.filterByTab(item, currentTabId));
|
|
815
|
+
if (this.state.searchQuery) {
|
|
816
|
+
const query = this.state.searchQuery.toLowerCase();
|
|
817
|
+
filtered = filtered.filter((item) => this.listConfig.getSearchText(item).toLowerCase().includes(query));
|
|
818
|
+
}
|
|
819
|
+
this.state.filteredItems = filtered;
|
|
820
|
+
// Clamp selected index
|
|
821
|
+
if (this.state.selectedIndex >= filtered.length) {
|
|
822
|
+
this.state.selectedIndex = Math.max(0, filtered.length - 1);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|