@crouton-kit/crouter 0.3.70 → 0.3.79
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 +1 -1
- package/dist/build-root.d.ts +12 -4
- package/dist/build-root.js +25 -6
- package/dist/builtin-memory/00-runtime-base.md +3 -10
- package/dist/builtin-memory/04-base-worker.md +18 -0
- package/dist/builtin-memory/04-orchestration-kernel.md +1 -1
- package/dist/builtin-memory/crouter-development/plugins.md +82 -5
- package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +13 -34
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +1115 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +234 -71
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +2 -9
- package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +2 -516
- package/dist/builtin-pi-packages/pi-crtr-extensions/package-lock.json +2 -2
- package/dist/builtin-pi-packages/pi-mode-switch/README.md +11 -39
- package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +20 -15
- package/dist/builtin-pi-packages/pi-mode-switch/package.json +1 -1
- package/dist/builtin-views/canvas/tui.mjs +8 -9
- package/dist/builtin-views/chat/tui.mjs +12 -12
- package/dist/builtin-views/git-pr/tui.mjs +7 -8
- package/dist/builtin-views/inbox/tui.mjs +27 -41
- package/dist/builtin-views/linkedin/tui.mjs +23 -37
- package/dist/builtin-views/prompt-review/tui.mjs +11 -11
- package/dist/builtin-views/settings/tui.mjs +11 -11
- package/dist/builtin-views/workspace-sidebar/tui.mjs +8 -9
- package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +11 -6
- package/dist/clients/attach/__tests__/attach-keybindings.test.d.ts +1 -0
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +113 -0
- package/dist/clients/attach/__tests__/crtr-output-render.test.js +1 -1
- package/dist/clients/attach/__tests__/mermaid-render.test.d.ts +1 -0
- package/dist/clients/attach/__tests__/mermaid-render.test.js +28 -0
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.d.ts +1 -0
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +110 -0
- package/dist/clients/attach/attach-cmd.d.ts +9 -1
- package/dist/clients/attach/attach-cmd.js +841 -792
- package/dist/clients/attach/auth-pickers.d.ts +0 -12
- package/dist/clients/attach/auth-pickers.js +64 -15
- package/dist/clients/attach/canvas-panels.js +2 -3
- package/dist/clients/attach/chat-view.d.ts +7 -8
- package/dist/clients/attach/chat-view.js +119 -79
- package/dist/clients/attach/edit-diff-render.d.ts +6 -0
- package/dist/clients/attach/edit-diff-render.js +263 -0
- package/dist/clients/attach/graph-overlay.d.ts +12 -2
- package/dist/clients/attach/graph-overlay.js +83 -33
- package/dist/clients/attach/input-controller.d.ts +28 -2
- package/dist/clients/attach/input-controller.js +38 -5
- package/dist/clients/attach/mermaid-render.js +5 -2
- package/dist/clients/attach/pickers.d.ts +8 -7
- package/dist/clients/attach/pickers.js +11 -17
- package/dist/clients/attach/slash-commands.d.ts +9 -0
- package/dist/clients/attach/slash-commands.js +127 -7
- package/dist/clients/attach/titled-editor.d.ts +12 -1
- package/dist/clients/attach/titled-editor.js +103 -8
- package/dist/commands/canvas-browse.js +2 -2
- package/dist/commands/human/queue.js +3 -4
- package/dist/commands/memory/lint.js +39 -5
- package/dist/commands/memory/write.js +1 -0
- package/dist/commands/node.js +9 -2
- package/dist/commands/pkg/plugin-inspect.js +22 -1
- package/dist/commands/pkg/plugin-manage.js +31 -9
- package/dist/commands/surface-tmux-spread.js +1 -3
- package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +1 -0
- package/dist/commands/sys/__tests__/config-keybindings.test.js +55 -0
- package/dist/commands/sys/__tests__/config-model-ladders.test.d.ts +1 -0
- package/dist/commands/sys/__tests__/config-model-ladders.test.js +121 -0
- package/dist/commands/sys/__tests__/setup-core.test.js +158 -1
- package/dist/commands/sys/config.js +18 -21
- package/dist/commands/sys/doctor.js +42 -4
- package/dist/commands/sys/setup-core.d.ts +49 -1
- package/dist/commands/sys/setup-core.js +161 -4
- package/dist/commands/sys/setup.d.ts +88 -0
- package/dist/commands/sys/setup.js +943 -169
- package/dist/commands/view-pick.d.ts +4 -0
- package/dist/commands/view-pick.js +17 -7
- package/dist/core/__tests__/base-worker-prompt.test.d.ts +1 -0
- package/dist/core/__tests__/base-worker-prompt.test.js +24 -0
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +232 -1
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +34 -9
- package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +1 -0
- package/dist/core/__tests__/command-plugins-surfaces.test.js +298 -0
- package/dist/core/__tests__/command-plugins.test.d.ts +1 -0
- package/dist/core/__tests__/command-plugins.test.js +444 -0
- package/dist/core/__tests__/fault-classifier.test.js +15 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +6 -0
- package/dist/core/__tests__/fixtures/fake-engine.js +9 -1
- package/dist/core/__tests__/full/broker-dialogs.test.js +7 -2
- package/dist/core/__tests__/host-teardown-process-group.test.js +15 -4
- package/dist/core/__tests__/preview-registry-sync.test.js +30 -1
- package/dist/core/__tests__/scope-crouter-home-fence.test.d.ts +1 -0
- package/dist/core/__tests__/scope-crouter-home-fence.test.js +55 -0
- package/dist/core/__tests__/stream-watchdog.test.d.ts +1 -0
- package/dist/core/__tests__/stream-watchdog.test.js +70 -0
- package/dist/core/__tests__/tmux-surface.test.js +72 -0
- package/dist/core/canvas/browse/__tests__/model.test.js +23 -5
- package/dist/core/canvas/browse/__tests__/render.test.js +1 -0
- package/dist/core/canvas/browse/app.d.ts +6 -0
- package/dist/core/canvas/browse/app.js +230 -41
- package/dist/core/canvas/browse/model.d.ts +10 -6
- package/dist/core/canvas/browse/model.js +20 -12
- package/dist/core/canvas/browse/pins.d.ts +4 -0
- package/dist/core/canvas/browse/pins.js +29 -0
- package/dist/core/canvas/browse/render.d.ts +13 -1
- package/dist/core/canvas/browse/render.js +72 -15
- package/dist/core/canvas/nav-model.js +5 -11
- package/dist/core/canvas/paths.d.ts +5 -0
- package/dist/core/canvas/paths.js +7 -0
- package/dist/core/command-plugins/adapter.d.ts +15 -0
- package/dist/core/command-plugins/adapter.js +145 -0
- package/dist/core/command-plugins/compose.d.ts +5 -0
- package/dist/core/command-plugins/compose.js +56 -0
- package/dist/core/command-plugins/discovery.d.ts +104 -0
- package/dist/core/command-plugins/discovery.js +565 -0
- package/dist/core/config.d.ts +48 -0
- package/dist/core/config.js +228 -110
- package/dist/core/fault-classifier.js +1 -1
- package/dist/core/fs-utils.d.ts +1 -0
- package/dist/core/fs-utils.js +15 -1
- package/dist/core/keybindings/__tests__/bespoke-consumers.test.d.ts +1 -0
- package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +40 -0
- package/dist/core/keybindings/__tests__/resolve.test.d.ts +1 -0
- package/dist/core/keybindings/__tests__/resolve.test.js +224 -0
- package/dist/core/keybindings/catalog.d.ts +14 -0
- package/dist/core/keybindings/catalog.js +257 -0
- package/dist/core/keybindings/index.d.ts +5 -0
- package/dist/core/keybindings/index.js +4 -0
- package/dist/core/keybindings/match.d.ts +29 -0
- package/dist/core/keybindings/match.js +99 -0
- package/dist/core/keybindings/persistence.d.ts +14 -0
- package/dist/core/keybindings/persistence.js +31 -0
- package/dist/core/keybindings/resolve.d.ts +14 -0
- package/dist/core/keybindings/resolve.js +305 -0
- package/dist/core/keybindings/types.d.ts +37 -0
- package/dist/core/keybindings/types.js +1 -0
- package/dist/core/memory-resolver.d.ts +1 -1
- package/dist/core/memory-resolver.js +10 -3
- package/dist/core/predicate.d.ts +5 -3
- package/dist/core/predicate.js +5 -3
- package/dist/core/profiles/select.d.ts +6 -0
- package/dist/core/profiles/select.js +86 -52
- package/dist/core/provider-management.d.ts +12 -0
- package/dist/core/provider-management.js +24 -0
- package/dist/core/runtime/broker-protocol.d.ts +33 -5
- package/dist/core/runtime/broker.js +164 -14
- package/dist/core/runtime/launch.d.ts +39 -6
- package/dist/core/runtime/launch.js +78 -20
- package/dist/core/runtime/naming.js +3 -3
- package/dist/core/runtime/pi-cli.d.ts +6 -0
- package/dist/core/runtime/pi-cli.js +16 -2
- package/dist/core/runtime/pi-vendored.d.ts +8 -0
- package/dist/core/runtime/pi-vendored.js +14 -0
- package/dist/core/runtime/placement.d.ts +2 -2
- package/dist/core/runtime/placement.js +4 -1
- package/dist/core/runtime/promote.js +4 -0
- package/dist/core/runtime/recap.d.ts +3 -3
- package/dist/core/runtime/recap.js +75 -47
- package/dist/core/runtime/recycle.js +6 -1
- package/dist/core/runtime/reset.js +5 -0
- package/dist/core/runtime/session-list-cache.d.ts +33 -0
- package/dist/core/runtime/session-list-cache.js +338 -0
- package/dist/core/runtime/spawn.js +52 -45
- package/dist/core/runtime/stream-watchdog.d.ts +26 -0
- package/dist/core/runtime/stream-watchdog.js +75 -0
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +2 -2
- package/dist/core/runtime/tmux.d.ts +18 -15
- package/dist/core/runtime/tmux.js +217 -110
- package/dist/core/scope.js +27 -4
- package/dist/core/subscription-state.d.ts +90 -0
- package/dist/core/subscription-state.js +762 -0
- package/dist/core/tui/__tests__/host-keybindings.test.d.ts +1 -0
- package/dist/core/tui/__tests__/host-keybindings.test.js +112 -0
- package/dist/core/tui/host.d.ts +30 -1
- package/dist/core/tui/host.js +148 -34
- package/dist/core/view/contract.d.ts +17 -3
- package/dist/daemon/crtrd.js +253 -12
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +41 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +121 -0
- package/dist/pi-extensions/canvas-inbox-watcher.d.ts +1 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +203 -25
- package/dist/pi-extensions/canvas-recap.d.ts +4 -0
- package/dist/pi-extensions/canvas-recap.js +73 -46
- package/dist/pi-extensions/canvas-stophook.d.ts +11 -0
- package/dist/pi-extensions/canvas-stophook.js +33 -4
- package/dist/types.d.ts +9 -26
- package/dist/types.js +1 -28
- package/dist/web-client/assets/{index-DiFuLcp6.js → index--md2ylfi.js} +1 -1
- package/dist/web-client/index.html +1 -1
- package/dist/web-client/sw.js +1 -1
- package/package.json +8 -4
- package/dist/pi-extensions/canvas-nav.d.ts +0 -43
- package/dist/pi-extensions/canvas-nav.js +0 -640
- package/dist/pi-extensions/widget-order-bus.d.ts +0 -6
- package/dist/pi-extensions/widget-order-bus.js +0 -34
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Mode Switch Extension
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* cycles plan / accept-edits. Modes here:
|
|
4
|
+
* Use the configured crouter mode-cycle binding to cycle between operating
|
|
5
|
+
* modes, the way Claude's Shift+Tab cycles plan / accept-edits. Modes here:
|
|
6
6
|
*
|
|
7
7
|
* normal → full access (default)
|
|
8
8
|
* spec → write a specification before any code
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* instructions are prepended (invisibly) to the next agent turn. Stay in the
|
|
14
14
|
* same mode across turns and nothing extra is injected.
|
|
15
15
|
*
|
|
16
|
-
* -
|
|
16
|
+
* - The configured shortcut or /mode cycles; /mode <name> jumps to a mode
|
|
17
17
|
* - The agent can switch its own mode by running the bundled `bin/mode` CLI via
|
|
18
18
|
* its bash tool; the command prints the new mode's guidance to stdout, so that
|
|
19
19
|
* text only enters context at the moment of the switch (no always-on tool)
|
|
@@ -31,6 +31,7 @@ import { type FSWatcher, mkdirSync, readFileSync, rmSync, watch, writeFileSync }
|
|
|
31
31
|
import { dirname, join } from "node:path";
|
|
32
32
|
import { fileURLToPath } from "node:url";
|
|
33
33
|
import { workspaceRoot } from "../../../core/artifact.js";
|
|
34
|
+
import { resolveUserKeybindings } from "../../../core/keybindings/index.js";
|
|
34
35
|
|
|
35
36
|
type Mode = "normal" | "spec" | "plan";
|
|
36
37
|
|
|
@@ -62,7 +63,7 @@ function modeSwitchDir(cwd: string = process.cwd(), nodeId: string = process.env
|
|
|
62
63
|
return join(workspaceRoot(cwd), "mode-switch", nodeId);
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
// The
|
|
66
|
+
// The order used by the shortcut and /mode command.
|
|
66
67
|
const CYCLE: Mode[] = ["normal", "spec", "plan"];
|
|
67
68
|
|
|
68
69
|
interface ModeDef {
|
|
@@ -214,9 +215,8 @@ export default function modeSwitchExtension(pi: ExtensionAPI): void {
|
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
// Apply a mode change to state and persistence. Shared by every path: the
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
// stdout).
|
|
218
|
+
// Shortcut/command changes add a UI toast and inject guidance on the next
|
|
219
|
+
// turn; the CLI path has already handed the agent its guidance via stdout.
|
|
220
220
|
function applyMode(next: Mode): void {
|
|
221
221
|
currentMode = next;
|
|
222
222
|
repaint();
|
|
@@ -241,8 +241,8 @@ export default function modeSwitchExtension(pi: ExtensionAPI): void {
|
|
|
241
241
|
// requested mode to <root>/mode-switch/request.json. We pick that up live via
|
|
242
242
|
// fs.watch (with a before_agent_start reconcile as a backstop) only to sync the
|
|
243
243
|
// badge and persisted state — never to inject guidance, since the CLI already
|
|
244
|
-
// printed it to the agent's bash output.
|
|
245
|
-
//
|
|
244
|
+
// printed it to the agent's bash output. Token gating ensures a later
|
|
245
|
+
// shortcut-driven change can't be clobbered by a stale request.
|
|
246
246
|
function applyFromRequest(next: Mode, source: "cli" | "attach"): void {
|
|
247
247
|
if (next === currentMode) return;
|
|
248
248
|
applyMode(next);
|
|
@@ -266,7 +266,7 @@ export default function modeSwitchExtension(pi: ExtensionAPI): void {
|
|
|
266
266
|
// Apply each CLI request at most once (token-gated) and never delete it, so
|
|
267
267
|
// every live instance — including the one actually on screen — converges to the
|
|
268
268
|
// requested mode regardless of /reload leftovers. A lingering request whose
|
|
269
|
-
// token we already applied can't clobber a later
|
|
269
|
+
// token we already applied can't clobber a later shortcut-driven change.
|
|
270
270
|
if (parsed.token && parsed.token === lastAppliedToken) return;
|
|
271
271
|
lastAppliedToken = parsed.token;
|
|
272
272
|
if (parsed.mode && (CYCLE as string[]).includes(parsed.mode)) {
|
|
@@ -291,11 +291,16 @@ export default function modeSwitchExtension(pi: ExtensionAPI): void {
|
|
|
291
291
|
setMode(CYCLE[(idx + 1) % CYCLE.length], ctx);
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
//
|
|
295
|
-
pi
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
294
|
+
// Resolve once when the extension loads. Crouter's sparse user config owns
|
|
295
|
+
// this semantic action; pi's stock action bindings remain independently owned
|
|
296
|
+
// by pi and are neither read nor rewritten here.
|
|
297
|
+
const bindings = resolveUserKeybindings();
|
|
298
|
+
for (const gesture of bindings.gestures("crtr.mode.cycle")) {
|
|
299
|
+
pi.registerShortcut(gesture, {
|
|
300
|
+
description: "Cycle mode (normal → spec → plan)",
|
|
301
|
+
handler: async (ctx) => cycleMode(ctx),
|
|
302
|
+
});
|
|
303
|
+
}
|
|
299
304
|
|
|
300
305
|
// /mode cycles; /mode <name> jumps to a specific mode.
|
|
301
306
|
pi.registerCommand("mode", {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mode-switch",
|
|
3
3
|
"version": "0.1.0",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Cycle between spec, plan, and normal modes with crouter's configurable mode binding. Injects mode-specific guidance whenever the mode changes.",
|
|
5
5
|
"keywords": ["pi-package", "modes", "spec", "plan"],
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"peerDependencies": {
|
|
@@ -127,12 +127,12 @@ export function render(state, draw, content) {
|
|
|
127
127
|
if (state.totalNodes === 0) {
|
|
128
128
|
emptyState(draw, content, {
|
|
129
129
|
headline: 'No nodes on the canvas',
|
|
130
|
-
secondary: ['Spawn one with `crtr node new`.', '
|
|
130
|
+
secondary: ['Spawn one with `crtr node new`.', 'Use refresh to update.'],
|
|
131
131
|
});
|
|
132
132
|
} else {
|
|
133
133
|
emptyState(draw, content, {
|
|
134
134
|
headline: 'All caught up',
|
|
135
|
-
secondary: [`${state.totalNodes} node${state.totalNodes === 1 ? '' : 's'} finished — none active.`, '
|
|
135
|
+
secondary: [`${state.totalNodes} node${state.totalNodes === 1 ? '' : 's'} finished — none active.`, 'Use refresh to update.'],
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
138
|
return;
|
|
@@ -156,14 +156,13 @@ export function render(state, draw, content) {
|
|
|
156
156
|
// ── keymap ───────────────────────────────────────────────────────────────
|
|
157
157
|
|
|
158
158
|
/**
|
|
159
|
-
* Read-only navigation
|
|
160
|
-
*
|
|
161
|
-
* from these bindings' `hint` fields (the single source of truth).
|
|
159
|
+
* Read-only navigation. No async actions from input — this is a monitor, not a
|
|
160
|
+
* controller. Footer hints come from these bindings' `hint` fields.
|
|
162
161
|
* @type {import('../../core/view/contract.js').KeyBinding<CanvasState>[]}
|
|
163
162
|
*/
|
|
164
163
|
export const keymap = [
|
|
165
|
-
{
|
|
166
|
-
{
|
|
167
|
-
{
|
|
168
|
-
{
|
|
164
|
+
{ bindingId: 'crtr.view.canvas.down', intent: 'cursorDown', hint: { label: 'move' } },
|
|
165
|
+
{ bindingId: 'crtr.view.canvas.up', intent: 'cursorUp' },
|
|
166
|
+
{ bindingId: 'crtr.view.canvas.refresh', intent: 'refresh', hint: { label: 'refresh' } },
|
|
167
|
+
{ bindingId: 'crtr.view.canvas.quit', intent: 'quit', hint: { label: 'quit' } },
|
|
169
168
|
];
|
|
@@ -275,7 +275,7 @@ function renderTakeover(state, draw, content) {
|
|
|
275
275
|
errorState(draw, content, {
|
|
276
276
|
headline: 'Missing target',
|
|
277
277
|
cause: 'run crtr view run chat --target <node-id>',
|
|
278
|
-
hint: '
|
|
278
|
+
hint: 'Use the view quit control.',
|
|
279
279
|
});
|
|
280
280
|
return;
|
|
281
281
|
}
|
|
@@ -285,7 +285,7 @@ function renderTakeover(state, draw, content) {
|
|
|
285
285
|
glyphFg: '33',
|
|
286
286
|
headline: 'Node asleep',
|
|
287
287
|
explanation: 'node is asleep / focus or revive it first',
|
|
288
|
-
nextStep: '
|
|
288
|
+
nextStep: 'Reconnect after revive.',
|
|
289
289
|
});
|
|
290
290
|
return;
|
|
291
291
|
}
|
|
@@ -293,7 +293,7 @@ function renderTakeover(state, draw, content) {
|
|
|
293
293
|
errorState(draw, content, {
|
|
294
294
|
headline: 'Node not found',
|
|
295
295
|
cause: 'check the target',
|
|
296
|
-
hint: '
|
|
296
|
+
hint: 'Use the view quit control.',
|
|
297
297
|
});
|
|
298
298
|
return;
|
|
299
299
|
}
|
|
@@ -354,15 +354,15 @@ const canCompose = (state) => state.target != null && state.conn !== 'no-broker'
|
|
|
354
354
|
|
|
355
355
|
/** @type {import('../../core/view/contract.js').KeyBinding<ChatState>[]} */
|
|
356
356
|
export const keymap = [
|
|
357
|
-
{ capture: 'setDraft', when: canCompose, hint: {
|
|
358
|
-
{
|
|
359
|
-
{
|
|
360
|
-
{
|
|
361
|
-
{
|
|
362
|
-
{
|
|
363
|
-
{
|
|
364
|
-
{
|
|
365
|
-
{
|
|
357
|
+
{ capture: 'setDraft', when: canCompose, hint: { label: 'compose' } },
|
|
358
|
+
{ bindingId: 'crtr.view.chat.submit', intent: 'submitDraft', when: canCompose, hint: { label: 'send' } },
|
|
359
|
+
{ bindingId: 'crtr.view.chat.contextual-cancel', intent: 'abort', when: isControllerStreaming },
|
|
360
|
+
{ bindingId: 'crtr.view.chat.contextual-cancel', intent: 'clearNotice', when: hasNotice, payload: (state) => state.notices[state.notices.length - 1]?.id },
|
|
361
|
+
{ bindingId: 'crtr.view.chat.contextual-cancel', intent: 'setDraft', when: hasDraft, payload: () => '' },
|
|
362
|
+
{ bindingId: 'crtr.view.chat.reconnect', intent: 'reconnect', when: canCompose, hint: { label: 'reconnect' } },
|
|
363
|
+
{ bindingId: 'crtr.view.chat.request-control', intent: 'requestControl', when: isObserver, hint: { label: 'control' } },
|
|
364
|
+
{ bindingId: 'crtr.view.chat.release-control', intent: 'releaseControl', when: isController, hint: { label: 'yield' } },
|
|
365
|
+
{ bindingId: 'crtr.view.chat.quit', intent: 'quit', hint: { label: 'quit' } },
|
|
366
366
|
];
|
|
367
367
|
|
|
368
368
|
export default { render, keymap };
|
|
@@ -275,7 +275,7 @@ export function render(state, draw, content) {
|
|
|
275
275
|
if (g.files.length === 0 && state.prs.length === 0 && !state.prNote) {
|
|
276
276
|
emptyState(draw, bodyRect, {
|
|
277
277
|
headline: 'All clear',
|
|
278
|
-
secondary: [`${g.branch} — clean working tree, no open PRs.`, '
|
|
278
|
+
secondary: [`${g.branch} — clean working tree, no open PRs.`, 'Use refresh to update.'],
|
|
279
279
|
});
|
|
280
280
|
return;
|
|
281
281
|
}
|
|
@@ -289,14 +289,13 @@ export function render(state, draw, content) {
|
|
|
289
289
|
// ── keymap ───────────────────────────────────────────────────────────────
|
|
290
290
|
|
|
291
291
|
/**
|
|
292
|
-
* Read-only navigation
|
|
293
|
-
*
|
|
294
|
-
* from these bindings' `hint` fields (the single source of truth).
|
|
292
|
+
* Read-only navigation. No async actions from input — this is a monitor, not a
|
|
293
|
+
* controller. Footer hints come from these bindings' `hint` fields.
|
|
295
294
|
* @type {import('../../core/view/contract.js').KeyBinding<GitPrState>[]}
|
|
296
295
|
*/
|
|
297
296
|
export const keymap = [
|
|
298
|
-
{
|
|
299
|
-
{
|
|
300
|
-
{
|
|
301
|
-
{
|
|
297
|
+
{ bindingId: 'crtr.view.git-pr.down', intent: 'cursorDown', hint: { label: 'move' } },
|
|
298
|
+
{ bindingId: 'crtr.view.git-pr.up', intent: 'cursorUp' },
|
|
299
|
+
{ bindingId: 'crtr.view.git-pr.refresh', intent: 'refresh', hint: { label: 'refresh' } },
|
|
300
|
+
{ bindingId: 'crtr.view.git-pr.quit', intent: 'quit', hint: { label: 'quit' } },
|
|
302
301
|
];
|
|
@@ -33,7 +33,7 @@ function renderGuided(draw, content, guide) {
|
|
|
33
33
|
errorState(draw, content, {
|
|
34
34
|
headline,
|
|
35
35
|
cause: d.explanation,
|
|
36
|
-
hint: d.nextStep || '
|
|
36
|
+
hint: d.nextStep || 'Refresh to retry.',
|
|
37
37
|
});
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
@@ -149,11 +149,10 @@ function renderThreadBody(state, draw, rect, reactTarget) {
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
/** The compose bar (reply mode): hairline + label + draft + cursor
|
|
152
|
+
/** The compose bar (reply mode): hairline + label + draft + cursor. */
|
|
153
153
|
function renderComposer(state, draw, right) {
|
|
154
|
-
const hairRow = right.row + right.height -
|
|
155
|
-
const barRow = right.row + right.height -
|
|
156
|
-
const hintRow = right.row + right.height - 1;
|
|
154
|
+
const hairRow = right.row + right.height - 2;
|
|
155
|
+
const barRow = right.row + right.height - 1;
|
|
157
156
|
draw.hline(hairRow, right.col, right.col + right.width);
|
|
158
157
|
const label = '✎ Reply ';
|
|
159
158
|
const labelW = Array.from(label).length;
|
|
@@ -166,18 +165,12 @@ function renderComposer(state, draw, right) {
|
|
|
166
165
|
{ text: shown },
|
|
167
166
|
{ text: '█', style: { fg: '33' } },
|
|
168
167
|
], right.width);
|
|
169
|
-
draw.spans(hintRow, right.col, [
|
|
170
|
-
{ text: 'enter', style: { bold: true } }, { text: ' send', style: { dim: true } },
|
|
171
|
-
{ text: ' · ', style: { dim: true } },
|
|
172
|
-
{ text: 'esc', style: { bold: true } }, { text: ' cancel', style: { dim: true } },
|
|
173
|
-
], right.width);
|
|
174
168
|
}
|
|
175
169
|
|
|
176
|
-
/** The react picker bar (react mode): hairline + emoji chip row
|
|
170
|
+
/** The react picker bar (react mode): hairline + emoji chip row. */
|
|
177
171
|
function renderReactBar(state, draw, right) {
|
|
178
|
-
const hairRow = right.row + right.height -
|
|
179
|
-
const barRow = right.row + right.height -
|
|
180
|
-
const hintRow = right.row + right.height - 1;
|
|
172
|
+
const hairRow = right.row + right.height - 2;
|
|
173
|
+
const barRow = right.row + right.height - 1;
|
|
181
174
|
draw.hline(hairRow, right.col, right.col + right.width);
|
|
182
175
|
/** @type {object[]} */
|
|
183
176
|
const spans = [{ text: '☺ React ', style: { fg: '33', bold: true } }];
|
|
@@ -190,13 +183,6 @@ function renderReactBar(state, draw, right) {
|
|
|
190
183
|
}
|
|
191
184
|
});
|
|
192
185
|
draw.spans(barRow, right.col, spans, right.width);
|
|
193
|
-
draw.spans(hintRow, right.col, [
|
|
194
|
-
{ text: '←/→', style: { bold: true } }, { text: ' pick', style: { dim: true } },
|
|
195
|
-
{ text: ' · ', style: { dim: true } },
|
|
196
|
-
{ text: 'enter', style: { bold: true } }, { text: ' react', style: { dim: true } },
|
|
197
|
-
{ text: ' · ', style: { dim: true } },
|
|
198
|
-
{ text: 'esc', style: { bold: true } }, { text: ' cancel', style: { dim: true } },
|
|
199
|
-
], right.width);
|
|
200
186
|
}
|
|
201
187
|
|
|
202
188
|
/**
|
|
@@ -210,7 +196,7 @@ function renderDetail(state, draw, right) {
|
|
|
210
196
|
centeredStack(draw, right, [
|
|
211
197
|
[{ text: '✉ ', style: { dim: true } }, { text: 'No conversation open', style: { dim: true } }],
|
|
212
198
|
[{ text: '' }],
|
|
213
|
-
[{ text: '
|
|
199
|
+
[{ text: 'Open a conversation to view it.', style: { dim: true } }],
|
|
214
200
|
]);
|
|
215
201
|
return;
|
|
216
202
|
}
|
|
@@ -233,7 +219,7 @@ function renderDetail(state, draw, right) {
|
|
|
233
219
|
|
|
234
220
|
const composing = state.mode === 'reply';
|
|
235
221
|
const reacting = state.mode === 'react';
|
|
236
|
-
const composerRows = composing || reacting ?
|
|
222
|
+
const composerRows = composing || reacting ? 2 : 0;
|
|
237
223
|
const bodyTop = right.row + headerRows + 1;
|
|
238
224
|
const bodyBottom = right.row + right.height - 1 - composerRows;
|
|
239
225
|
const bodyRect = { row: bodyTop, col: right.col, width: right.width, height: Math.max(0, bodyBottom - bodyTop + 1) };
|
|
@@ -269,7 +255,7 @@ export function render(state, draw, content) {
|
|
|
269
255
|
}
|
|
270
256
|
emptyState(draw, content, {
|
|
271
257
|
headline: 'All caught up',
|
|
272
|
-
secondary: ['No messages in your inbox.', '
|
|
258
|
+
secondary: ['No messages in your inbox.', 'Refresh to check again.'],
|
|
273
259
|
});
|
|
274
260
|
return;
|
|
275
261
|
}
|
|
@@ -290,23 +276,23 @@ const reactMode = (s) => s.mode === 'react';
|
|
|
290
276
|
/** @type {import('../../core/view/contract.js').KeyBinding<InboxState>[]} */
|
|
291
277
|
export const keymap = [
|
|
292
278
|
// list
|
|
293
|
-
{
|
|
294
|
-
{
|
|
295
|
-
{
|
|
296
|
-
{
|
|
297
|
-
{
|
|
298
|
-
{
|
|
299
|
-
{
|
|
300
|
-
{
|
|
301
|
-
{
|
|
302
|
-
{
|
|
279
|
+
{ bindingId: 'crtr.view.inbox.down', intent: 'cursorDown', when: listMode, hint: { label: 'move' } },
|
|
280
|
+
{ bindingId: 'crtr.view.inbox.up', intent: 'cursorUp', when: listMode },
|
|
281
|
+
{ bindingId: 'crtr.view.inbox.open', intent: 'open', payload: (s) => s.cursor, when: listMode, hint: { label: 'open' } },
|
|
282
|
+
{ bindingId: 'crtr.view.inbox.reply', intent: 'startReply', when: listMode, hint: { label: 'reply' } },
|
|
283
|
+
{ bindingId: 'crtr.view.inbox.react', intent: 'startReact', when: listMode, hint: { label: 'react' } },
|
|
284
|
+
{ bindingId: 'crtr.view.inbox.filter', intent: 'cycleFilter', when: listMode, hint: { label: 'filter' } },
|
|
285
|
+
{ bindingId: 'crtr.view.inbox.refresh', intent: 'refresh', when: listMode, hint: { label: 'refresh' } },
|
|
286
|
+
{ bindingId: 'crtr.view.inbox.connect-linkedin', intent: 'connectLinkedin', when: listMode },
|
|
287
|
+
{ bindingId: 'crtr.view.inbox.connect-gmail', intent: 'connectGmail', when: listMode, hint: { label: 'connect' } },
|
|
288
|
+
{ bindingId: 'crtr.view.inbox.quit', intent: 'quit', when: listMode, hint: { label: 'quit' } },
|
|
303
289
|
// reply
|
|
304
|
-
{ capture: 'setDraft', when: replyMode, hint: {
|
|
305
|
-
{
|
|
306
|
-
{
|
|
290
|
+
{ capture: 'setDraft', when: replyMode, hint: { label: 'reply' } },
|
|
291
|
+
{ bindingId: 'crtr.view.inbox.submit-reply', intent: 'submitReply', when: replyMode, hint: { label: 'send' } },
|
|
292
|
+
{ bindingId: 'crtr.view.inbox.cancel', intent: 'cancelCompose', when: replyMode, hint: { label: 'cancel' } },
|
|
307
293
|
// react
|
|
308
|
-
{
|
|
309
|
-
{
|
|
310
|
-
{
|
|
311
|
-
{
|
|
294
|
+
{ bindingId: 'crtr.view.inbox.reaction-previous', intent: 'reactPrev', when: reactMode, hint: { label: 'pick' } },
|
|
295
|
+
{ bindingId: 'crtr.view.inbox.reaction-next', intent: 'reactNext', when: reactMode },
|
|
296
|
+
{ bindingId: 'crtr.view.inbox.submit-reaction', intent: 'submitReact', when: reactMode, hint: { label: 'react' } },
|
|
297
|
+
{ bindingId: 'crtr.view.inbox.cancel', intent: 'cancelCompose', when: reactMode, hint: { label: 'cancel' } },
|
|
312
298
|
];
|
|
@@ -274,9 +274,8 @@ function renderThreadBody(state, draw, rect, reactTarget) {
|
|
|
274
274
|
|
|
275
275
|
/** The compose bar (reply mode). @param {LiState} state @param {Draw} draw @param {Rect} right */
|
|
276
276
|
function renderComposer(state, draw, right) {
|
|
277
|
-
const hairRow = right.row + right.height -
|
|
278
|
-
const barRow = right.row + right.height -
|
|
279
|
-
const hintRow = right.row + right.height - 1;
|
|
277
|
+
const hairRow = right.row + right.height - 2;
|
|
278
|
+
const barRow = right.row + right.height - 1;
|
|
280
279
|
draw.hline(hairRow, right.col, right.col + right.width);
|
|
281
280
|
const label = '✎ Reply ';
|
|
282
281
|
const labelW = Array.from(label).length;
|
|
@@ -289,18 +288,12 @@ function renderComposer(state, draw, right) {
|
|
|
289
288
|
{ text: shown },
|
|
290
289
|
{ text: '█', style: { fg: '33' } },
|
|
291
290
|
], right.width);
|
|
292
|
-
draw.spans(hintRow, right.col, [
|
|
293
|
-
{ text: 'enter', style: { bold: true } }, { text: ' send', style: { dim: true } },
|
|
294
|
-
{ text: ' · ', style: { dim: true } },
|
|
295
|
-
{ text: 'esc', style: { bold: true } }, { text: ' cancel', style: { dim: true } },
|
|
296
|
-
], right.width);
|
|
297
291
|
}
|
|
298
292
|
|
|
299
293
|
/** The react picker bar (react mode). @param {LiState} state @param {Draw} draw @param {Rect} right */
|
|
300
294
|
function renderReactBar(state, draw, right) {
|
|
301
|
-
const hairRow = right.row + right.height -
|
|
302
|
-
const barRow = right.row + right.height -
|
|
303
|
-
const hintRow = right.row + right.height - 1;
|
|
295
|
+
const hairRow = right.row + right.height - 2;
|
|
296
|
+
const barRow = right.row + right.height - 1;
|
|
304
297
|
draw.hline(hairRow, right.col, right.col + right.width);
|
|
305
298
|
/** @type {Span[]} */
|
|
306
299
|
const spans = [{ text: '☺ React ', style: { fg: '33', bold: true } }];
|
|
@@ -313,13 +306,6 @@ function renderReactBar(state, draw, right) {
|
|
|
313
306
|
}
|
|
314
307
|
});
|
|
315
308
|
draw.spans(barRow, right.col, spans, right.width);
|
|
316
|
-
draw.spans(hintRow, right.col, [
|
|
317
|
-
{ text: '←/→', style: { bold: true } }, { text: ' pick', style: { dim: true } },
|
|
318
|
-
{ text: ' · ', style: { dim: true } },
|
|
319
|
-
{ text: 'enter', style: { bold: true } }, { text: ' react', style: { dim: true } },
|
|
320
|
-
{ text: ' · ', style: { dim: true } },
|
|
321
|
-
{ text: 'esc', style: { bold: true } }, { text: ' cancel', style: { dim: true } },
|
|
322
|
-
], right.width);
|
|
323
309
|
}
|
|
324
310
|
|
|
325
311
|
/** Right pane — the open thread + the compose/react bar when in a mode. @param {LiState} state @param {Draw} draw @param {Rect} right */
|
|
@@ -331,7 +317,7 @@ function renderThread(state, draw, right) {
|
|
|
331
317
|
centeredStack(draw, right, [
|
|
332
318
|
[{ text: '✉ ', style: { dim: true } }, { text: 'No conversation open', style: { dim: true } }],
|
|
333
319
|
[{ text: '' }],
|
|
334
|
-
[{ text: '
|
|
320
|
+
[{ text: 'Open a conversation to view it.', style: { dim: true } }],
|
|
335
321
|
]);
|
|
336
322
|
return;
|
|
337
323
|
}
|
|
@@ -345,7 +331,7 @@ function renderThread(state, draw, right) {
|
|
|
345
331
|
|
|
346
332
|
const composing = state.mode === 'reply';
|
|
347
333
|
const reacting = state.mode === 'react';
|
|
348
|
-
const composerRows = composing || reacting ?
|
|
334
|
+
const composerRows = composing || reacting ? 2 : 0;
|
|
349
335
|
const bodyTop = right.row + 2;
|
|
350
336
|
const bodyBottom = right.row + right.height - 1 - composerRows;
|
|
351
337
|
const bodyRect = { row: bodyTop, col: right.col, width: right.width, height: Math.max(0, bodyBottom - bodyTop + 1) };
|
|
@@ -380,7 +366,7 @@ export function render(state, draw, content) {
|
|
|
380
366
|
}
|
|
381
367
|
emptyState(draw, content, {
|
|
382
368
|
headline: 'All caught up',
|
|
383
|
-
secondary: ['No conversations in your inbox.', '
|
|
369
|
+
secondary: ['No conversations in your inbox.', 'Refresh to check again.'],
|
|
384
370
|
});
|
|
385
371
|
return;
|
|
386
372
|
}
|
|
@@ -403,25 +389,25 @@ const isComposeOrReact = (s) => s.mode === 'reply' || s.mode === 'react';
|
|
|
403
389
|
/**
|
|
404
390
|
* Input→intent map. List-mode navigation + entry into compose/react; the compose
|
|
405
391
|
* bar uses a `capture` binding (the host's line-editor dispatches setDraft with
|
|
406
|
-
* the next draft)
|
|
407
|
-
*
|
|
392
|
+
* the next draft). Footer hints come from these `hint` fields (single source of
|
|
393
|
+
* truth).
|
|
408
394
|
* @type {import('../../core/view/contract.js').KeyBinding<LiState>[]}
|
|
409
395
|
*/
|
|
410
396
|
export const keymap = [
|
|
411
397
|
// ── List mode ──
|
|
412
|
-
{
|
|
413
|
-
{
|
|
414
|
-
{
|
|
415
|
-
{
|
|
416
|
-
{
|
|
417
|
-
{
|
|
418
|
-
{
|
|
419
|
-
// ── Reply mode ──
|
|
420
|
-
{ capture: 'setDraft', when: isReply },
|
|
421
|
-
{
|
|
422
|
-
{
|
|
398
|
+
{ bindingId: 'crtr.view.linkedin.down', intent: 'cursorDown', when: isList, hint: { label: 'move' } },
|
|
399
|
+
{ bindingId: 'crtr.view.linkedin.up', intent: 'cursorUp', when: isList },
|
|
400
|
+
{ bindingId: 'crtr.view.linkedin.open', intent: 'openThread', payload: (s) => s.convCursor, when: isList, hint: { label: 'open' } },
|
|
401
|
+
{ bindingId: 'crtr.view.linkedin.reply', intent: 'startReply', when: isList, hint: { label: 'reply' } },
|
|
402
|
+
{ bindingId: 'crtr.view.linkedin.react', intent: 'startReact', when: isList, hint: { label: 'react' } },
|
|
403
|
+
{ bindingId: 'crtr.view.linkedin.refresh', intent: 'refresh', when: isList, hint: { label: 'refresh' } },
|
|
404
|
+
{ bindingId: 'crtr.view.linkedin.quit', intent: 'quit', when: isList, hint: { label: 'quit' } },
|
|
405
|
+
// ── Reply mode ──
|
|
406
|
+
{ capture: 'setDraft', when: isReply, hint: { label: 'reply' } },
|
|
407
|
+
{ bindingId: 'crtr.view.linkedin.submit-reply', intent: 'submitReply', when: isReply, hint: { label: 'send' } },
|
|
408
|
+
{ bindingId: 'crtr.view.linkedin.cancel', intent: 'cancelCompose', when: isComposeOrReact, hint: { label: 'cancel' } },
|
|
423
409
|
// ── React mode ──
|
|
424
|
-
{
|
|
425
|
-
{
|
|
426
|
-
{
|
|
410
|
+
{ bindingId: 'crtr.view.linkedin.reaction-previous', intent: 'reactPrev', when: isReact, hint: { label: 'pick' } },
|
|
411
|
+
{ bindingId: 'crtr.view.linkedin.reaction-next', intent: 'reactNext', when: isReact },
|
|
412
|
+
{ bindingId: 'crtr.view.linkedin.submit-reaction', intent: 'submitReact', when: isReact, hint: { label: 'react' } },
|
|
427
413
|
];
|
|
@@ -107,14 +107,14 @@ export function render(state, draw, content) {
|
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
if (state.review.length === 0) {
|
|
110
|
-
emptyState(draw, content, { headline: 'No prompt layers', secondary: ['
|
|
110
|
+
emptyState(draw, content, { headline: 'No prompt layers', secondary: ['Refresh to try again.'] });
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
const headerRows = 3;
|
|
115
115
|
draw.text(content.row, content.col, 'Prompt Studio', { bold: true });
|
|
116
116
|
draw.text(content.row + 1, content.col, configHeadline(state.config), { dim: true });
|
|
117
|
-
draw.text(content.row + 2, content.col, `
|
|
117
|
+
draw.text(content.row + 2, content.col, `Layer navigation · comparison · raw/layered · export · refresh${state.lastExportPath ? ` · ${state.lastExportPath}` : ''}`, { dim: true });
|
|
118
118
|
|
|
119
119
|
const body = { row: content.row + headerRows + 1, col: content.col, width: content.width, height: Math.max(0, content.height - headerRows - 1) };
|
|
120
120
|
const cols = draw.columns(body, [3, 5, 4]);
|
|
@@ -184,13 +184,13 @@ export function render(state, draw, content) {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
export const keymap = [
|
|
187
|
-
{
|
|
188
|
-
{
|
|
189
|
-
{
|
|
190
|
-
{
|
|
191
|
-
{
|
|
192
|
-
{
|
|
193
|
-
{
|
|
194
|
-
{
|
|
195
|
-
{
|
|
187
|
+
{ bindingId: 'crtr.view.prompt-review.down', intent: 'cursorDown', hint: { label: 'layer' } },
|
|
188
|
+
{ bindingId: 'crtr.view.prompt-review.up', intent: 'cursorUp' },
|
|
189
|
+
{ bindingId: 'crtr.view.prompt-review.compare-previous', intent: 'compareCursorUp', hint: { label: 'compare' } },
|
|
190
|
+
{ bindingId: 'crtr.view.prompt-review.compare-next', intent: 'compareCursorDown' },
|
|
191
|
+
{ bindingId: 'crtr.view.prompt-review.toggle-mode', intent: 'setViewMode', payload: (s) => (s.viewMode === 'raw' ? 'layered' : 'raw'), hint: { label: 'raw/layered' } },
|
|
192
|
+
{ bindingId: 'crtr.view.prompt-review.expand', intent: 'toggleLayerExpanded', payload: (s) => s.selectedLayerId || (s.review && s.review[s.cursor] && s.review[s.cursor].id) || '', hint: { label: 'expand' } },
|
|
193
|
+
{ bindingId: 'crtr.view.prompt-review.export', intent: 'exportComments', hint: { label: 'export' } },
|
|
194
|
+
{ bindingId: 'crtr.view.prompt-review.refresh', intent: 'refresh', hint: { label: 'refresh' } },
|
|
195
|
+
{ bindingId: 'crtr.view.prompt-review.quit', intent: 'quit', hint: { label: 'quit' } },
|
|
196
196
|
];
|
|
@@ -61,8 +61,8 @@ export function render(state, draw, content) {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const header = state.edit
|
|
64
|
-
? `Replacing ${state.edit.label} —
|
|
65
|
-
: '
|
|
64
|
+
? `Replacing ${state.edit.label} — submit saves, cancel discards`
|
|
65
|
+
: 'Move · switch matrix cell · edit · refresh';
|
|
66
66
|
draw.text(content.row, content.col, 'Model ladders', { bold: true });
|
|
67
67
|
draw.text(content.row + 1, content.col, header, { dim: true });
|
|
68
68
|
if (state.edit) {
|
|
@@ -76,14 +76,14 @@ export function render(state, draw, content) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export const keymap = [
|
|
79
|
-
{
|
|
80
|
-
{
|
|
81
|
-
{
|
|
82
|
-
{
|
|
83
|
-
{
|
|
84
|
-
{
|
|
79
|
+
{ bindingId: 'crtr.view.settings.down', intent: 'cursorDown', when: (s) => !s.edit, hint: { label: 'move' } },
|
|
80
|
+
{ bindingId: 'crtr.view.settings.up', intent: 'cursorUp', when: (s) => !s.edit },
|
|
81
|
+
{ bindingId: 'crtr.view.settings.cell-previous', intent: 'matrixLeft', when: (s) => !s.edit, hint: { label: 'switch cell' } },
|
|
82
|
+
{ bindingId: 'crtr.view.settings.cell-next', intent: 'matrixRight', when: (s) => !s.edit },
|
|
83
|
+
{ bindingId: 'crtr.view.settings.refresh', intent: 'refresh', when: (s) => !s.edit, hint: { label: 'refresh' } },
|
|
84
|
+
{ bindingId: 'crtr.view.settings.quit', intent: 'quit', hint: { label: 'quit' } },
|
|
85
85
|
{ capture: 'setDraft', when: (s) => !!s.edit },
|
|
86
|
-
{
|
|
87
|
-
{
|
|
88
|
-
{
|
|
86
|
+
{ bindingId: 'crtr.view.settings.edit-or-submit', intent: 'submitEdit', when: (s) => !!s.edit },
|
|
87
|
+
{ bindingId: 'crtr.view.settings.edit-or-submit', intent: 'beginEdit', when: (s) => !s.edit, hint: { label: 'edit' } },
|
|
88
|
+
{ bindingId: 'crtr.view.settings.cancel-edit', intent: 'cancelEdit', when: (s) => !!s.edit },
|
|
89
89
|
];
|
|
@@ -115,7 +115,7 @@ export function render(state, draw, content) {
|
|
|
115
115
|
}
|
|
116
116
|
emptyState(draw, content, {
|
|
117
117
|
headline: 'No agents here',
|
|
118
|
-
secondary: ['Nothing started in this cwd.', '
|
|
118
|
+
secondary: ['Nothing started in this cwd.', 'Refresh to try again.'],
|
|
119
119
|
});
|
|
120
120
|
return;
|
|
121
121
|
}
|
|
@@ -128,15 +128,14 @@ export function render(state, draw, content) {
|
|
|
128
128
|
// ── keymap ───────────────────────────────────────────────────────────────
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* these bindings' `hint` fields (the single source of truth).
|
|
131
|
+
* Move over node rows, open the selected node in the chat pane, refresh, or
|
|
132
|
+
* leave the view. Footer hints use the host-resolved binding gestures.
|
|
134
133
|
* @type {import('../../core/view/contract.js').KeyBinding<SidebarState>[]}
|
|
135
134
|
*/
|
|
136
135
|
export const keymap = [
|
|
137
|
-
{
|
|
138
|
-
{
|
|
139
|
-
{
|
|
140
|
-
{
|
|
141
|
-
{
|
|
136
|
+
{ bindingId: 'crtr.view.workspace-sidebar.down', intent: 'cursorDown', hint: { label: 'move' } },
|
|
137
|
+
{ bindingId: 'crtr.view.workspace-sidebar.up', intent: 'cursorUp' },
|
|
138
|
+
{ bindingId: 'crtr.view.workspace-sidebar.open', intent: 'open', hint: { label: 'open' } },
|
|
139
|
+
{ bindingId: 'crtr.view.workspace-sidebar.refresh', intent: 'refresh', hint: { label: 'refresh' } },
|
|
140
|
+
{ bindingId: 'crtr.view.workspace-sidebar.quit', intent: 'quit', hint: { label: 'quit' } },
|
|
142
141
|
];
|