@crouton-kit/crouter 0.3.17 → 0.3.19
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/dist/build-root.js +6 -0
- package/dist/builtin-memory/crouter-development/marketplaces.md +164 -0
- package/dist/builtin-memory/crouter-development/personas/base-prompt.md +58 -0
- package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +60 -0
- package/dist/builtin-memory/crouter-development/personas.md +117 -0
- package/dist/builtin-memory/crouter-development/plugins.md +163 -0
- package/dist/builtin-memory/design.md +60 -0
- package/dist/builtin-memory/development.md +116 -0
- package/dist/builtin-memory/planning.md +66 -0
- package/dist/builtin-memory/spec.md +99 -0
- package/dist/builtin-personas/design/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/design/orchestrator.md +1 -1
- package/dist/builtin-personas/developer/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/developer/orchestrator.md +1 -1
- package/dist/builtin-personas/explore/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/general/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/lifecycle/resident.md +1 -1
- package/dist/builtin-personas/lifecycle/terminal.md +5 -2
- package/dist/builtin-personas/orchestration-kernel.md +15 -24
- package/dist/builtin-personas/plan/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/plan/orchestrator.md +1 -1
- package/dist/builtin-personas/plan/reviewers/architecture-fit/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/code-smells/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/pattern-consistency/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/requirements-coverage/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/security/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/review/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/runtime-base.md +6 -3
- package/dist/builtin-personas/spec/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/spec/orchestrator.md +1 -1
- package/dist/builtin-personas/waiting.md +8 -0
- package/dist/builtin-skills/skills/crouter-development/personas/SKILL.md +24 -14
- package/dist/builtin-skills/skills/crouter-development/personas/base-prompt/SKILL.md +4 -4
- package/dist/builtin-skills/skills/crouter-development/personas/orchestrator-prompt/SKILL.md +1 -1
- package/dist/builtin-skills/skills/crouter-development/plugins/SKILL.md +2 -2
- package/dist/builtin-views/_lib/states.mjs +161 -0
- package/dist/builtin-views/canvas/client.mjs +303 -0
- package/dist/builtin-views/canvas/view.mjs +576 -0
- package/dist/builtin-views/git-pr/client.mjs +440 -0
- package/dist/builtin-views/git-pr/view.mjs +675 -0
- package/dist/builtin-views/inbox/_lib/render.mjs +177 -0
- package/dist/builtin-views/inbox/sources/gmail.mjs +965 -0
- package/dist/builtin-views/inbox/sources/linkedin.mjs +427 -0
- package/dist/builtin-views/inbox/view.mjs +889 -0
- package/dist/builtin-views/linkedin/client.mjs +610 -0
- package/dist/builtin-views/linkedin/view.mjs +1171 -0
- package/dist/clients/attach/attach-cmd.d.ts +2 -0
- package/dist/clients/attach/attach-cmd.js +354 -0
- package/dist/clients/attach/chat-view.d.ts +77 -0
- package/dist/clients/attach/chat-view.js +450 -0
- package/dist/clients/attach/clipboard-image.d.ts +16 -0
- package/dist/clients/attach/clipboard-image.js +113 -0
- package/dist/clients/attach/config-load.d.ts +31 -0
- package/dist/clients/attach/config-load.js +113 -0
- package/dist/clients/attach/extension-dialogs.d.ts +29 -0
- package/dist/clients/attach/extension-dialogs.js +101 -0
- package/dist/clients/attach/input-controller.d.ts +54 -0
- package/dist/clients/attach/input-controller.js +204 -0
- package/dist/clients/attach/slash-commands.d.ts +36 -0
- package/dist/clients/attach/slash-commands.js +200 -0
- package/dist/clients/attach/view-socket.d.ts +48 -0
- package/dist/clients/attach/view-socket.js +126 -0
- package/dist/commands/attention.js +3 -3
- package/dist/commands/canvas-prune.js +1 -1
- package/dist/commands/daemon.js +4 -3
- package/dist/commands/human/prompts.js +4 -10
- package/dist/commands/human/queue.js +43 -8
- package/dist/commands/human/shared.d.ts +28 -1
- package/dist/commands/human/shared.js +48 -10
- package/dist/commands/memory/find.d.ts +1 -0
- package/dist/commands/memory/find.js +180 -0
- package/dist/commands/memory/lint.d.ts +1 -0
- package/dist/commands/memory/lint.js +140 -0
- package/dist/commands/memory/list.d.ts +1 -0
- package/dist/commands/memory/list.js +79 -0
- package/dist/commands/memory/read.js +103 -0
- package/dist/commands/memory/shared.d.ts +30 -0
- package/dist/commands/memory/shared.js +122 -0
- package/dist/commands/memory/write.d.ts +1 -0
- package/dist/commands/memory/write.js +85 -0
- package/dist/commands/memory.d.ts +2 -0
- package/dist/commands/memory.js +27 -0
- package/dist/commands/node.d.ts +3 -2
- package/dist/commands/node.js +660 -65
- package/dist/commands/pkg/market-manage.js +1 -1
- package/dist/commands/push.js +6 -6
- package/dist/commands/revive.js +1 -1
- package/dist/commands/skill/author.js +1 -1
- package/dist/commands/skill/shared.d.ts +1 -8
- package/dist/commands/skill/shared.js +2 -55
- package/dist/commands/skill.js +9 -14
- package/dist/commands/sys/doctor.js +1 -1
- package/dist/commands/sys/update.js +1 -1
- package/dist/commands/view-cycle.d.ts +2 -0
- package/dist/commands/view-cycle.js +125 -0
- package/dist/commands/view-list.d.ts +2 -0
- package/dist/commands/view-list.js +66 -0
- package/dist/commands/view-new.d.ts +2 -0
- package/dist/commands/view-new.js +70 -0
- package/dist/commands/view-pick.d.ts +2 -0
- package/dist/commands/view-pick.js +119 -0
- package/dist/commands/view-run.d.ts +2 -0
- package/dist/commands/view-run.js +191 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +29 -0
- package/dist/core/__tests__/broker-lifecycle.test.d.ts +1 -0
- package/dist/core/__tests__/broker-lifecycle.test.js +677 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.d.ts +1 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.js +166 -0
- package/dist/core/__tests__/cascade-close.test.js +12 -2
- package/dist/core/__tests__/child-death-wake.test.d.ts +1 -0
- package/dist/core/__tests__/child-death-wake.test.js +245 -0
- package/dist/core/__tests__/context-intro.test.js +76 -62
- package/dist/core/__tests__/daemon-boot.test.js +14 -5
- package/dist/core/__tests__/daemon-liveness.test.js +34 -9
- package/dist/core/__tests__/detach-focus.test.d.ts +1 -0
- package/dist/core/__tests__/detach-focus.test.js +206 -0
- package/dist/core/__tests__/draw-style.test.d.ts +1 -0
- package/dist/core/__tests__/draw-style.test.js +258 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.d.ts +2 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.js +18 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +138 -0
- package/dist/core/__tests__/fixtures/fake-engine.js +614 -0
- package/dist/core/__tests__/fixtures/fake-pi-host.js +1 -0
- package/dist/core/__tests__/flagship-lifecycle.test.js +7 -1
- package/dist/core/__tests__/frame-decoder-perf.test.d.ts +1 -0
- package/dist/core/__tests__/frame-decoder-perf.test.js +198 -0
- package/dist/core/__tests__/helpers/harness.d.ts +9 -0
- package/dist/core/__tests__/helpers/harness.js +111 -1
- package/dist/core/__tests__/home-session.test.js +41 -8
- package/dist/core/__tests__/human-new-window-regression.test.d.ts +1 -0
- package/dist/core/__tests__/human-new-window-regression.test.js +101 -0
- package/dist/core/__tests__/human-surface-target.test.d.ts +1 -0
- package/dist/core/__tests__/human-surface-target.test.js +98 -0
- package/dist/core/__tests__/kickoff.test.js +37 -3
- package/dist/core/__tests__/live-mutation.test.js +50 -33
- package/dist/core/__tests__/memory.test.js +23 -115
- package/dist/core/__tests__/persona-subkind.test.js +18 -15
- package/dist/core/__tests__/placement-focus.test.js +5 -0
- package/dist/core/__tests__/placement-teardown.test.js +54 -11
- package/dist/core/__tests__/relaunch.test.js +4 -3
- package/dist/core/__tests__/review-render-pane-regression.test.d.ts +1 -0
- package/dist/core/__tests__/review-render-pane-regression.test.js +133 -0
- package/dist/core/__tests__/spawn-root.test.js +10 -0
- package/dist/core/__tests__/spike-harness.test.js +1 -0
- package/dist/core/__tests__/wake-bearings.test.d.ts +1 -0
- package/dist/core/__tests__/wake-bearings.test.js +156 -0
- package/dist/core/__tests__/wake-origin.test.d.ts +1 -0
- package/dist/core/__tests__/wake-origin.test.js +110 -0
- package/dist/core/bootstrap.js +1 -1
- package/dist/core/canvas/browse/__tests__/render.test.js +1 -0
- package/dist/core/canvas/browse/app.js +24 -2
- package/dist/core/canvas/browse/model.d.ts +38 -2
- package/dist/core/canvas/browse/model.js +134 -10
- package/dist/core/canvas/browse/render.d.ts +6 -12
- package/dist/core/canvas/browse/render.js +72 -104
- package/dist/core/canvas/canvas.js +15 -22
- package/dist/core/canvas/db.js +46 -0
- package/dist/core/canvas/index.d.ts +1 -0
- package/dist/core/canvas/index.js +1 -0
- package/dist/core/canvas/paths.d.ts +4 -1
- package/dist/core/canvas/paths.js +10 -4
- package/dist/core/canvas/pid.d.ts +4 -0
- package/dist/core/canvas/pid.js +23 -0
- package/dist/core/canvas/render.d.ts +11 -2
- package/dist/core/canvas/render.js +69 -0
- package/dist/core/canvas/types.d.ts +85 -3
- package/dist/core/canvas/types.js +2 -2
- package/dist/core/canvas/wakeups.d.ts +76 -0
- package/dist/core/canvas/wakeups.js +185 -0
- package/dist/core/config.js +4 -1
- package/dist/core/frontmatter.js +37 -124
- package/dist/core/help.d.ts +6 -0
- package/dist/core/help.js +7 -0
- package/dist/core/memory-resolver.d.ts +49 -0
- package/dist/core/memory-resolver.js +141 -0
- package/dist/core/personas/index.d.ts +4 -3
- package/dist/core/personas/index.js +3 -2
- package/dist/core/personas/loader.d.ts +41 -16
- package/dist/core/personas/loader.js +133 -29
- package/dist/core/personas/resolve.d.ts +4 -4
- package/dist/core/personas/resolve.js +28 -16
- package/dist/core/predicate.d.ts +63 -0
- package/dist/core/predicate.js +189 -0
- package/dist/core/resolver.js +26 -5
- package/dist/core/runtime/bearings.d.ts +53 -12
- package/dist/core/runtime/bearings.js +132 -59
- package/dist/core/runtime/broker-cli.d.ts +1 -0
- package/dist/core/runtime/broker-cli.js +46 -0
- package/dist/core/runtime/broker-protocol.d.ts +332 -0
- package/dist/core/runtime/broker-protocol.js +153 -0
- package/dist/core/runtime/broker-sdk.d.ts +48 -0
- package/dist/core/runtime/broker-sdk.js +72 -0
- package/dist/core/runtime/broker.d.ts +55 -0
- package/dist/core/runtime/broker.js +1128 -0
- package/dist/core/runtime/close.js +35 -6
- package/dist/core/runtime/host.d.ts +53 -0
- package/dist/core/runtime/host.js +186 -0
- package/dist/core/runtime/kickoff.d.ts +2 -1
- package/dist/core/runtime/kickoff.js +91 -5
- package/dist/core/runtime/launch.d.ts +45 -2
- package/dist/core/runtime/launch.js +65 -2
- package/dist/core/runtime/lifecycle.js +23 -6
- package/dist/core/runtime/memory.d.ts +2 -42
- package/dist/core/runtime/memory.js +11 -162
- package/dist/core/runtime/nodes.d.ts +33 -0
- package/dist/core/runtime/nodes.js +59 -1
- package/dist/core/runtime/persona.js +21 -11
- package/dist/core/runtime/pi-vendored.d.ts +18 -0
- package/dist/core/runtime/pi-vendored.js +49 -0
- package/dist/core/runtime/placement.d.ts +42 -14
- package/dist/core/runtime/placement.js +228 -38
- package/dist/core/runtime/promote.d.ts +0 -6
- package/dist/core/runtime/promote.js +1 -12
- package/dist/core/runtime/{demote.d.ts → recycle.d.ts} +5 -5
- package/dist/core/runtime/{demote.js → recycle.js} +27 -11
- package/dist/core/runtime/reset.js +8 -6
- package/dist/core/runtime/revive.d.ts +2 -0
- package/dist/core/runtime/revive.js +34 -34
- package/dist/core/runtime/spawn.d.ts +19 -0
- package/dist/core/runtime/spawn.js +75 -22
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +6 -1
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +28 -0
- package/dist/core/runtime/tmux.js +80 -6
- package/dist/core/scope.d.ts +11 -0
- package/dist/core/scope.js +39 -0
- package/dist/core/spawn.d.ts +25 -1
- package/dist/core/spawn.js +72 -7
- package/dist/core/substrate/gate.d.ts +13 -0
- package/dist/core/substrate/gate.js +21 -0
- package/dist/core/substrate/index.d.ts +7 -0
- package/dist/core/substrate/index.js +18 -0
- package/dist/core/substrate/on-read.d.ts +14 -0
- package/dist/core/substrate/on-read.js +292 -0
- package/dist/core/substrate/render.d.ts +25 -0
- package/dist/core/substrate/render.js +256 -0
- package/dist/core/substrate/schema.d.ts +76 -0
- package/dist/core/substrate/schema.js +124 -0
- package/dist/core/substrate/session-cache.d.ts +30 -0
- package/dist/core/substrate/session-cache.js +77 -0
- package/dist/core/substrate/subject.d.ts +41 -0
- package/dist/core/substrate/subject.js +54 -0
- package/dist/core/tui/contract.d.ts +83 -0
- package/dist/core/tui/contract.js +8 -0
- package/dist/core/tui/draw.d.ts +96 -0
- package/dist/core/tui/draw.js +339 -0
- package/dist/core/tui/host.d.ts +29 -0
- package/dist/core/tui/host.js +379 -0
- package/dist/core/tui/loader.d.ts +16 -0
- package/dist/core/tui/loader.js +94 -0
- package/dist/core/{canvas/browse → tui}/terminal.js +7 -6
- package/dist/core/wake.d.ts +86 -0
- package/dist/core/wake.js +308 -0
- package/dist/daemon/crtrd.d.ts +29 -4
- package/dist/daemon/crtrd.js +662 -46
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +171 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +19 -12
- package/dist/pi-extensions/canvas-commands.d.ts +3 -0
- package/dist/pi-extensions/canvas-commands.js +10 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +17 -0
- package/dist/pi-extensions/canvas-context-intro.js +55 -15
- package/dist/pi-extensions/canvas-doc-substrate.d.ts +44 -0
- package/dist/pi-extensions/canvas-doc-substrate.js +112 -0
- package/dist/pi-extensions/canvas-nav.d.ts +3 -0
- package/dist/pi-extensions/canvas-nav.js +145 -34
- package/dist/pi-extensions/canvas-stophook.js +17 -8
- package/dist/pi-extensions/canvas-view.d.ts +21 -0
- package/dist/pi-extensions/canvas-view.js +75 -0
- package/dist/prompts/skill.js +19 -26
- package/dist/prompts/view.d.ts +7 -0
- package/dist/prompts/view.js +101 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -0
- package/package.json +9 -4
- package/dist/commands/skill/find.d.ts +0 -4
- package/dist/commands/skill/find.js +0 -257
- package/dist/commands/skill/read.js +0 -91
- /package/dist/commands/{skill → memory}/read.d.ts +0 -0
- /package/dist/core/{canvas/browse → tui}/terminal.d.ts +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// `crtr view run <name>` — resolve, load, and host a view.
|
|
2
|
+
//
|
|
3
|
+
// Resolves the view across scopes (project→user→builtin), dynamically imports
|
|
4
|
+
// it, then hands it to the core/tui host. The host owns the screen and the
|
|
5
|
+
// non-TTY path: when stdin is NOT a TTY it prints view.dump(state) and exits 0,
|
|
6
|
+
// so `crtr view run <name> | cat` works anywhere. The interactive path is
|
|
7
|
+
// tmux-only (crtr is tmux-only) — outside tmux with a TTY we notify + no-op,
|
|
8
|
+
// never a non-tmux fallback. --port / --target forward verbatim onto
|
|
9
|
+
// host.options (camelCased, stringified); crtr does not interpret them.
|
|
10
|
+
//
|
|
11
|
+
// --window / --split open the view as a PERSISTENT MONITOR instead of taking
|
|
12
|
+
// over the current pane: --window in a new background (non-focus-stealing)
|
|
13
|
+
// tmux window, --split in a right-hand split of the current pane. Both shell a
|
|
14
|
+
// plain inner `crtr view run <name>` into the new pane, which hosts the view
|
|
15
|
+
// there and self-tags the pane with @crtr_view so the Alt+V then ]/[ view-cycle
|
|
16
|
+
// can flip it to the next/prev view in place. Both are tmux-only by nature; in
|
|
17
|
+
// a pipe (non-TTY) placement is meaningless, so they degrade to the static dump.
|
|
18
|
+
import { defineLeaf } from '../core/command.js';
|
|
19
|
+
import { InputError } from '../core/io.js';
|
|
20
|
+
import { runView } from '../core/tui/host.js';
|
|
21
|
+
import { resolveView, loadView, listViews } from '../core/tui/loader.js';
|
|
22
|
+
// Commands reach the tmux driver through placement.ts (the sanctioned
|
|
23
|
+
// model-over-driver seam, §5.1) — never `./tmux.js` directly.
|
|
24
|
+
import { inTmux, currentTmux, openNodeWindow, splitWindow, piCommand, setPaneOption, } from '../core/runtime/placement.js';
|
|
25
|
+
export const viewRunLeaf = defineLeaf({
|
|
26
|
+
name: 'run',
|
|
27
|
+
description: 'resolve, load, and host a view (in this pane, a new window, or a split)',
|
|
28
|
+
whenToUse: 'you want to OPEN a view by name — a full-screen raw-ANSI surface. By default it hosts in the current pane (tmux-only interactive; piped it prints a static snapshot). Pass --window to open it as a background monitor window, or --split to open it beside the current pane — both leave you where you are so a view becomes a live monitor you flip between with Alt+V then ]/[. Pass --port/--target to forward connection details. Use `crtr view list` first to see what is available, or `crtr view new` to scaffold one',
|
|
29
|
+
help: {
|
|
30
|
+
name: 'view run',
|
|
31
|
+
summary: 'host a view in the current pane, a new window (--window), or a split (--split); outside a TTY it prints the view\'s static dump and exits 0',
|
|
32
|
+
params: [
|
|
33
|
+
{ kind: 'positional', name: 'name', required: true, constraint: 'View id to run (its directory name). Resolves project→user→builtin.' },
|
|
34
|
+
{ kind: 'flag', name: 'window', type: 'bool', required: false, constraint: 'Open the view in a NEW background tmux window (non-focus-stealing) instead of the current pane — a persistent monitor. tmux-only; ignored (static dump) in a pipe. Mutually exclusive with --split.' },
|
|
35
|
+
{ kind: 'flag', name: 'split', type: 'bool', required: false, constraint: 'Open the view in a right-hand SPLIT of the current pane instead of taking it over — a side-by-side monitor. tmux-only; ignored (static dump) in a pipe. Mutually exclusive with --window.' },
|
|
36
|
+
{ kind: 'flag', name: 'port', type: 'int', required: false, constraint: 'Forwarded verbatim to the view as options.port (e.g. a CDP debugging port).' },
|
|
37
|
+
{ kind: 'flag', name: 'target', type: 'string', required: false, constraint: 'Forwarded verbatim to the view as options.target (e.g. a browser tab id).' },
|
|
38
|
+
],
|
|
39
|
+
output: [
|
|
40
|
+
{ name: 'hosted', type: 'string', required: false, constraint: 'For --window/--split: "window" or "split" — where the monitor opened. Absent for an in-pane host (which holds the terminal until you quit).' },
|
|
41
|
+
{ name: 'view', type: 'string', required: false, constraint: 'The view id opened (only on the --window/--split path).' },
|
|
42
|
+
{ name: 'window', type: 'string', required: false, constraint: 'The new tmux window id (--window only).' },
|
|
43
|
+
{ name: 'pane', type: 'string', required: false, constraint: 'The new tmux pane id (--window/--split).' },
|
|
44
|
+
],
|
|
45
|
+
outputKind: 'object',
|
|
46
|
+
effects: [
|
|
47
|
+
'Default (no flag) inside a TTY+tmux: takes over the current pane in raw mode (alt-screen) until you quit (q/Ctrl-C), and tags the pane @crtr_view=<name> so Alt+V then ]/[ can cycle it.',
|
|
48
|
+
'--window: opens a new background tmux window running the view (does not steal focus); returns immediately.',
|
|
49
|
+
'--split: opens a right-hand split of the current pane running the view; you stay in your pane.',
|
|
50
|
+
'Outside a TTY: writes the view\'s static dump to stdout and exits 0 (no raw mode); --window/--split degrade to this.',
|
|
51
|
+
'Forwards --port/--target onto host.options for the view; mutates nothing on the canvas.',
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
run: async (input) => {
|
|
55
|
+
const name = input['name'];
|
|
56
|
+
const port = input['port'];
|
|
57
|
+
const target = input['target'];
|
|
58
|
+
const asWindow = input['window'] === true;
|
|
59
|
+
const asSplit = input['split'] === true;
|
|
60
|
+
if (asWindow && asSplit) {
|
|
61
|
+
throw new InputError({
|
|
62
|
+
error: 'conflicting_flags',
|
|
63
|
+
message: '--window and --split are mutually exclusive',
|
|
64
|
+
next: 'Pass at most one: --window (new background window) or --split (split the current pane).',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
const r = resolveView(name);
|
|
68
|
+
if (r === null) {
|
|
69
|
+
const avail = listViews().map((v) => v.id);
|
|
70
|
+
throw new InputError({
|
|
71
|
+
error: 'view_not_found',
|
|
72
|
+
message: `no view: ${name}`,
|
|
73
|
+
received: name,
|
|
74
|
+
next: avail.length > 0
|
|
75
|
+
? `Available views: ${avail.join(', ')}. Or scaffold one with \`crtr view new ${name}\`.`
|
|
76
|
+
: `No views found. Scaffold one with \`crtr view new ${name}\`.`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const options = {};
|
|
80
|
+
if (port !== undefined)
|
|
81
|
+
options.port = String(port);
|
|
82
|
+
if (target !== undefined)
|
|
83
|
+
options.target = target;
|
|
84
|
+
// --window / --split: open the view as a persistent monitor in a new pane.
|
|
85
|
+
if (asWindow || asSplit) {
|
|
86
|
+
// Placement is tmux-only. In a pipe (non-TTY) it is meaningless — degrade
|
|
87
|
+
// to the static dump (runView handles the non-TTY path internally).
|
|
88
|
+
if (!process.stdin.isTTY) {
|
|
89
|
+
const v = await loadView(r);
|
|
90
|
+
await runView(v, { options });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!inTmux()) {
|
|
94
|
+
throw new InputError({
|
|
95
|
+
error: 'not_in_tmux',
|
|
96
|
+
message: '--window/--split are tmux-only — run crtr inside its tmux session',
|
|
97
|
+
next: `Open it from inside tmux, or drop the flag to host in the current pane (or pipe for a snapshot: \`crtr view run ${name} | cat\`).`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const here = currentTmux();
|
|
101
|
+
if (here === null) {
|
|
102
|
+
throw new InputError({
|
|
103
|
+
error: 'no_tmux_location',
|
|
104
|
+
message: 'could not resolve the current tmux pane',
|
|
105
|
+
next: 'Run this inside a tmux pane.',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// The inner command re-enters this leaf with NO placement flag, so it
|
|
109
|
+
// hosts the view in its own (new) pane and self-tags it via @crtr_view.
|
|
110
|
+
const argv = ['view', 'run', name];
|
|
111
|
+
if (port !== undefined)
|
|
112
|
+
argv.push('--port', String(port));
|
|
113
|
+
if (target !== undefined)
|
|
114
|
+
argv.push('--target', target);
|
|
115
|
+
const command = piCommand(argv, 'crtr');
|
|
116
|
+
const cwd = process.cwd();
|
|
117
|
+
if (asWindow) {
|
|
118
|
+
const win = openNodeWindow({ session: here.session, name: `view:${name}`, cwd, env: {}, command });
|
|
119
|
+
if (win === null) {
|
|
120
|
+
throw new InputError({
|
|
121
|
+
error: 'window_open_failed',
|
|
122
|
+
message: `tmux could not open a window for view ${name}`,
|
|
123
|
+
next: 'Check the tmux server is reachable, then retry.',
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return { hosted: 'window', view: name, window: win.window, pane: win.pane };
|
|
127
|
+
}
|
|
128
|
+
// --split: a right-hand split (-h, the splitWindow default); -d keeps you put.
|
|
129
|
+
const pane = splitWindow(here.pane, { cwd, env: {}, command });
|
|
130
|
+
if (pane === null) {
|
|
131
|
+
throw new InputError({
|
|
132
|
+
error: 'split_failed',
|
|
133
|
+
message: `tmux could not split the pane for view ${name}`,
|
|
134
|
+
next: 'Check the tmux server is reachable, then retry.',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return { hosted: 'split', view: name, pane };
|
|
138
|
+
}
|
|
139
|
+
const v = await loadView(r);
|
|
140
|
+
// The interactive path is tmux-only; the piped/non-TTY dump path works
|
|
141
|
+
// anywhere (runView handles it internally), so only guard when stdin is a
|
|
142
|
+
// TTY. Outside tmux with a TTY: notify + no-op — never a non-tmux fallback.
|
|
143
|
+
if (process.stdin.isTTY && !inTmux()) {
|
|
144
|
+
throw new InputError({
|
|
145
|
+
error: 'not_in_tmux',
|
|
146
|
+
message: 'crtr view is tmux-only — run it inside the crtr tmux session',
|
|
147
|
+
next: `Open it from inside tmux (e.g. the /view popup), or pipe for a static snapshot: \`crtr view run ${name} | cat\`.`,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// Self-tag this pane with the view id (+ any forwarded --port/--target) so
|
|
151
|
+
// the Alt+V then ]/[ view-cycle can switch it to the next/prev view in place
|
|
152
|
+
// AND replay the connection params it was opened with. Best-effort; tmux-only.
|
|
153
|
+
const tagPane = (process.stdin.isTTY && inTmux())
|
|
154
|
+
? (process.env['TMUX_PANE'] ?? currentTmux()?.pane)
|
|
155
|
+
: undefined;
|
|
156
|
+
if (tagPane !== undefined && tagPane !== '') {
|
|
157
|
+
try {
|
|
158
|
+
setPaneOption(tagPane, '@crtr_view', name);
|
|
159
|
+
setPaneOption(tagPane, '@crtr_view_port', port !== undefined ? String(port) : '');
|
|
160
|
+
setPaneOption(tagPane, '@crtr_view_target', target ?? '');
|
|
161
|
+
}
|
|
162
|
+
catch { /* best-effort */ }
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
await runView(v, { options });
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
// On a clean quit (q) runView returns to the shell/pi that launched this
|
|
169
|
+
// pane — clear the monitor tag so a stray Alt+V ]/[ can't respawn-pane -k
|
|
170
|
+
// (and kill) whatever now owns the pane. When the cycle itself replaces
|
|
171
|
+
// this view it SIGKILLs us mid-await (this finally never runs); cycle + the
|
|
172
|
+
// new view-run re-tag, so that path stays correct.
|
|
173
|
+
if (tagPane !== undefined && tagPane !== '') {
|
|
174
|
+
try {
|
|
175
|
+
setPaneOption(tagPane, '@crtr_view', '');
|
|
176
|
+
}
|
|
177
|
+
catch { /* best-effort */ }
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
render: (result) => {
|
|
182
|
+
const hosted = result['hosted'];
|
|
183
|
+
if (hosted === 'window') {
|
|
184
|
+
return `<view-opened mode="window" view="${result['view']}" window="${result['window']}" pane="${result['pane']}"/>`;
|
|
185
|
+
}
|
|
186
|
+
if (hosted === 'split') {
|
|
187
|
+
return `<view-opened mode="split" view="${result['view']}" pane="${result['pane']}"/>`;
|
|
188
|
+
}
|
|
189
|
+
return '';
|
|
190
|
+
},
|
|
191
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// `crtr view` — the TUI view library.
|
|
2
|
+
//
|
|
3
|
+
// Views are switchable raw-ANSI terminal surfaces, each a self-contained .mjs
|
|
4
|
+
// the host loads and runs. This branch assembles the leaves: `list` enumerates
|
|
5
|
+
// what's available, `run` hosts one (interactive in tmux, static dump when
|
|
6
|
+
// piped), `new` scaffolds a fresh view.mjs, and the hidden `pick` backs the
|
|
7
|
+
// /view popup. Each leaf owns its own help one level down.
|
|
8
|
+
import { defineBranch } from '../core/command.js';
|
|
9
|
+
import { viewListLeaf } from './view-list.js';
|
|
10
|
+
import { viewRunLeaf } from './view-run.js';
|
|
11
|
+
import { viewCycleLeaf } from './view-cycle.js';
|
|
12
|
+
import { viewNewLeaf } from './view-new.js';
|
|
13
|
+
import { viewPickLeaf } from './view-pick.js';
|
|
14
|
+
export function registerView() {
|
|
15
|
+
return defineBranch({
|
|
16
|
+
name: 'view',
|
|
17
|
+
rootEntry: {
|
|
18
|
+
concept: 'switchable raw-ANSI terminal views — full-screen surfaces hosted in a pane, each a self-contained module',
|
|
19
|
+
desc: 'list, run, and author TUI views',
|
|
20
|
+
useWhen: 'you want a live full-screen surface (a monitor, an inbox, a dashboard) rather than one-shot command output — run a view by name, list what exists, or scaffold a new one. Views have no pi session; they render + take keystrokes until you quit.',
|
|
21
|
+
},
|
|
22
|
+
help: {
|
|
23
|
+
name: 'view',
|
|
24
|
+
summary: 'host and author switchable raw-ANSI terminal views',
|
|
25
|
+
model: '`list` when you do not know which views exist — a flat roster (id/title/description/scope) across project→user→builtin. `run <name>` opens one full-screen in the current pane (tmux-only interactive; piped it prints the view\'s static dump and exits 0), forwarding --port/--target onto the view; pass --window/--split to open it as a persistent monitor (new window / split) you flip between with Alt+V then ]/[. `cycle` switches a monitor pane to the next/prev view in place (what those keys drive). `new <name>` scaffolds a runnable view.mjs stub you edit. `pick` is a hidden raw-ANSI picker the /view popup shells. Append `-h` at any leaf for its schema.',
|
|
26
|
+
},
|
|
27
|
+
children: [viewListLeaf, viewRunLeaf, viewCycleLeaf, viewNewLeaf, viewPickLeaf],
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|