codedeck 0.1.9 → 0.3.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 +97 -1
- package/dist/cli/cli-name.js +20 -0
- package/dist/cli/cli-name.js.map +1 -0
- package/dist/cli/commands/claims.js +170 -0
- package/dist/cli/commands/claims.js.map +1 -0
- package/dist/cli/commands/doctor.js +22 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/models.js +3 -3
- package/dist/cli/commands/models.js.map +1 -1
- package/dist/cli/commands/open.js +331 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/ps.js +260 -23
- package/dist/cli/commands/ps.js.map +1 -1
- package/dist/cli/commands/rename.js +29 -0
- package/dist/cli/commands/rename.js.map +1 -0
- package/dist/cli/commands/run.js +68 -30
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/setup.js +508 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/usage.js +37 -0
- package/dist/cli/commands/usage.js.map +1 -0
- package/dist/cli/commands/wait.js +3 -2
- package/dist/cli/commands/wait.js.map +1 -1
- package/dist/cli/index.js +37 -21
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/picker-state.js +168 -0
- package/dist/cli/picker-state.js.map +1 -0
- package/dist/cli/picker.js +157 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/ui.js +233 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/config.js +47 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/orchestrator-mode.js +72 -0
- package/dist/config/orchestrator-mode.js.map +1 -0
- package/dist/config/paths.js +8 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/core/models.js +23 -4
- package/dist/core/models.js.map +1 -1
- package/dist/core/pricing.js +65 -0
- package/dist/core/pricing.js.map +1 -0
- package/dist/core/roles.js +83 -0
- package/dist/core/roles.js.map +1 -0
- package/dist/core/run-usage.js +46 -0
- package/dist/core/run-usage.js.map +1 -0
- package/dist/core/session.js +5 -0
- package/dist/core/session.js.map +1 -1
- package/dist/daemon/daemon.js +90 -3
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/ipc.js +10 -3
- package/dist/daemon/ipc.js.map +1 -1
- package/dist/drivers/opencode/driver.js +1 -114
- package/dist/drivers/opencode/driver.js.map +1 -1
- package/dist/drivers/opencode/parser.js +86 -0
- package/dist/drivers/opencode/parser.js.map +1 -0
- package/dist/drivers/session-runtime.js +1 -0
- package/dist/drivers/session-runtime.js.map +1 -1
- package/dist/git/worktree.js +1 -1
- package/dist/git/worktree.js.map +1 -1
- package/dist/open/contract.js +104 -0
- package/dist/open/contract.js.map +1 -0
- package/dist/open/injection.js +59 -0
- package/dist/open/injection.js.map +1 -0
- package/dist/open/launchers/claude.js +212 -0
- package/dist/open/launchers/claude.js.map +1 -0
- package/dist/open/launchers/opencode.js +178 -0
- package/dist/open/launchers/opencode.js.map +1 -0
- package/dist/open/orchestrator-prose.js +12 -0
- package/dist/open/orchestrator-prose.js.map +1 -0
- package/dist/open/pty.js +281 -0
- package/dist/open/pty.js.map +1 -0
- package/dist/open/runtime.js +597 -0
- package/dist/open/runtime.js.map +1 -0
- package/dist/plugin/.claude-plugin/plugin.json +11 -0
- package/dist/plugin/agents/auditor.md +36 -0
- package/dist/plugin/agents/general.md +35 -0
- package/dist/plugin/agents/orchestrator-edit.md +69 -0
- package/dist/plugin/agents/orchestrator-read.md +69 -0
- package/dist/plugin/agents/orchestrator.md +91 -0
- package/dist/plugin/agents/reviewer.md +36 -0
- package/dist/plugin/commands/autonomous.md +58 -0
- package/dist/plugin/hooks/hooks.json +24 -0
- package/dist/plugin/hooks/session-id.sh +23 -0
- package/dist/plugin/hooks/session-name-lib.mjs +40 -0
- package/dist/plugin/hooks/session-name-worker.mjs +124 -0
- package/dist/plugin/hooks/session-name.mjs +66 -0
- package/dist/plugin/hooks/session-name.sh +7 -0
- package/dist/plugin/pty-shim.mjs +114 -0
- package/dist/plugin/statusline.sh +260 -0
- package/dist/plugin/themes/codedeck-rage.json +74 -0
- package/dist/plugin/themes/codedeck-ultra.json +76 -0
- package/dist/plugin/ultra.md +9 -0
- package/dist/store/claims.js +152 -0
- package/dist/store/claims.js.map +1 -0
- package/dist/store/database.js +14 -0
- package/dist/store/database.js.map +1 -1
- package/dist/store/sessions.js +17 -3
- package/dist/store/sessions.js.map +1 -1
- package/package.json +6 -4
package/dist/cli/index.js
CHANGED
|
@@ -5,7 +5,9 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { registerRunCommand } from "./commands/run.js";
|
|
7
7
|
import { registerPsCommand } from "./commands/ps.js";
|
|
8
|
+
import { registerClaimsCommand } from "./commands/claims.js";
|
|
8
9
|
import { registerShowCommand } from "./commands/show.js";
|
|
10
|
+
import { registerRenameCommand } from "./commands/rename.js";
|
|
9
11
|
import { registerLogsCommand } from "./commands/logs.js";
|
|
10
12
|
import { registerWaitCommand } from "./commands/wait.js";
|
|
11
13
|
import { registerSendCommand } from "./commands/send.js";
|
|
@@ -13,6 +15,10 @@ import { registerStopCommand } from "./commands/stop.js";
|
|
|
13
15
|
import { registerDiffCommand } from "./commands/diff.js";
|
|
14
16
|
import { registerDoctorCommand } from "./commands/doctor.js";
|
|
15
17
|
import { registerModelsCommand } from "./commands/models.js";
|
|
18
|
+
import { registerOpenCommand } from "./commands/open.js";
|
|
19
|
+
import { registerSetupCommand } from "./commands/setup.js";
|
|
20
|
+
import { registerUsageCommand } from "./commands/usage.js";
|
|
21
|
+
import { getCliInvocation, getCliName } from "./cli-name.js";
|
|
16
22
|
function getVersion() {
|
|
17
23
|
try {
|
|
18
24
|
const pkgPath = path.join(path.dirname(fileURLToPath(import.meta.url)), "../../package.json");
|
|
@@ -24,8 +30,12 @@ function getVersion() {
|
|
|
24
30
|
}
|
|
25
31
|
}
|
|
26
32
|
const program = new Command();
|
|
33
|
+
// CODEDECK_CLI_NAME renames the tool (for example a `codedeck-dev`
|
|
34
|
+
// alias), so the help below shows that name instead of `npx codedeck`.
|
|
35
|
+
const cliName = getCliName();
|
|
36
|
+
const cli = getCliInvocation();
|
|
27
37
|
program
|
|
28
|
-
.name(
|
|
38
|
+
.name(cliName)
|
|
29
39
|
.description("CodeDeck — local runtime for coding agents\nManage Claude, Codex, OpenCode and OMP through a single session interface")
|
|
30
40
|
.version(getVersion())
|
|
31
41
|
.helpOption("-h, --help", "display help for command")
|
|
@@ -33,34 +43,37 @@ program
|
|
|
33
43
|
.showSuggestionAfterError(true)
|
|
34
44
|
.addHelpText("after", `
|
|
35
45
|
Examples:
|
|
36
|
-
$
|
|
37
|
-
$
|
|
38
|
-
$
|
|
39
|
-
$
|
|
40
|
-
$
|
|
41
|
-
$
|
|
42
|
-
$
|
|
43
|
-
$
|
|
44
|
-
$
|
|
45
|
-
$
|
|
46
|
-
$
|
|
47
|
-
$
|
|
48
|
-
$
|
|
49
|
-
$
|
|
50
|
-
$
|
|
46
|
+
$ ${cli} run "implement authentication" --agent claude --worktree
|
|
47
|
+
$ ${cli} run "fix the tests" --agent codex --bg
|
|
48
|
+
$ ${cli} wait a83f
|
|
49
|
+
$ ${cli} ps
|
|
50
|
+
$ ${cli} ps --json
|
|
51
|
+
$ ${cli} show a83f
|
|
52
|
+
$ ${cli} rename a83f "fix auth tests"
|
|
53
|
+
$ ${cli} logs a83f --follow
|
|
54
|
+
$ ${cli} logs a83f --json
|
|
55
|
+
$ ${cli} send a83f "add tests"
|
|
56
|
+
$ ${cli} stop a83f
|
|
57
|
+
$ ${cli} diff a83f --stat
|
|
58
|
+
$ ${cli} doctor
|
|
59
|
+
$ ${cli} models
|
|
60
|
+
$ ${cli} models codex
|
|
61
|
+
$ ${cli} models --search sonnet
|
|
51
62
|
|
|
52
63
|
Recommended flow:
|
|
53
|
-
$
|
|
54
|
-
$
|
|
55
|
-
$
|
|
56
|
-
$
|
|
64
|
+
$ ${cli} run "task" # blocks and follows logs
|
|
65
|
+
$ ${cli} run "task" --bg --json # starts in background
|
|
66
|
+
$ ${cli} wait <id> # waits without ps/show loop
|
|
67
|
+
$ ${cli} logs <id> --follow # inspect progress
|
|
57
68
|
|
|
58
|
-
Run '
|
|
69
|
+
Run '${cli} <command> --help' for command-specific options.
|
|
59
70
|
Docs: https://github.com/4ndreello/run-agent
|
|
60
71
|
`);
|
|
61
72
|
registerRunCommand(program);
|
|
62
73
|
registerPsCommand(program);
|
|
74
|
+
registerClaimsCommand(program);
|
|
63
75
|
registerShowCommand(program);
|
|
76
|
+
registerRenameCommand(program);
|
|
64
77
|
registerLogsCommand(program);
|
|
65
78
|
registerWaitCommand(program);
|
|
66
79
|
registerSendCommand(program);
|
|
@@ -68,6 +81,9 @@ registerStopCommand(program);
|
|
|
68
81
|
registerDiffCommand(program);
|
|
69
82
|
registerDoctorCommand(program);
|
|
70
83
|
registerModelsCommand(program);
|
|
84
|
+
registerOpenCommand(program);
|
|
85
|
+
registerSetupCommand(program);
|
|
86
|
+
registerUsageCommand(program);
|
|
71
87
|
// Make `codedeck help` behave like `codedeck --help`
|
|
72
88
|
program.command("help", { hidden: true }).action(() => program.outputHelp());
|
|
73
89
|
program.parseAsync(process.argv).catch((err) => {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAC9F,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The catalog is keyed by both halves because a model id alone is ambiguous:
|
|
3
|
+
* two harnesses can list the same one, and `run --agent` needs to know which
|
|
4
|
+
* of them was picked.
|
|
5
|
+
*
|
|
6
|
+
* The separator is ":", the same one free text types and the summary line
|
|
7
|
+
* prints, so the key stays readable wherever it surfaces (the confirm footer
|
|
8
|
+
* shows it verbatim). Splitting it the other way would need a harness name
|
|
9
|
+
* containing ":", and the four there are cannot, so a model id carrying one
|
|
10
|
+
* is still unambiguous.
|
|
11
|
+
*/
|
|
12
|
+
export function itemKey(harness, id) {
|
|
13
|
+
return `${harness ?? ""}:${id}`;
|
|
14
|
+
}
|
|
15
|
+
export function initialState(screen) {
|
|
16
|
+
return { screen, filter: "", cursor: 0, offset: 0, pasting: false };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Searches everything the catalog knows about a model, not just what fits on
|
|
20
|
+
* the row. The provider is on screen as a group header, so typing it and
|
|
21
|
+
* getting nothing read as a broken filter, and the readable name is the only
|
|
22
|
+
* place a version like "Opus 5" is spelled the way people say it.
|
|
23
|
+
*/
|
|
24
|
+
function matches(item, filter) {
|
|
25
|
+
return [item.label, item.id, item.group, item.name].some((field) => field !== undefined && field.toLowerCase().includes(filter));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Real catalog matches, which is not `visibleItems().length`: that one never
|
|
29
|
+
* returns empty, so counting it reported one hit for a filter that matched
|
|
30
|
+
* nothing.
|
|
31
|
+
*/
|
|
32
|
+
export function hitCount(state) {
|
|
33
|
+
const filter = state.filter.trim().toLowerCase();
|
|
34
|
+
if (!filter)
|
|
35
|
+
return state.screen.items.length;
|
|
36
|
+
return state.screen.items.filter((item) => matches(item, filter)).length;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A model typed by hand has to name its harness, because the screen answers a
|
|
40
|
+
* role and a bare id says nothing about who runs it. The separator is ":" and
|
|
41
|
+
* not "/": opencode spells its own ids with a slash ("opencode/gpt-5.6-luna"),
|
|
42
|
+
* so splitting on that would cut a real id in half.
|
|
43
|
+
*
|
|
44
|
+
* Only the first ":" separates. Everything after it is the model, verbatim.
|
|
45
|
+
*/
|
|
46
|
+
export function parseFreeText(raw, harnesses) {
|
|
47
|
+
const cut = raw.indexOf(":");
|
|
48
|
+
if (cut <= 0)
|
|
49
|
+
return undefined;
|
|
50
|
+
const harness = raw.slice(0, cut).trim().toLowerCase();
|
|
51
|
+
const id = raw.slice(cut + 1).trim();
|
|
52
|
+
if (!id || !harnesses.has(harness))
|
|
53
|
+
return undefined;
|
|
54
|
+
return { harness, id };
|
|
55
|
+
}
|
|
56
|
+
export function visibleItems(state) {
|
|
57
|
+
const filter = state.filter.trim().toLowerCase();
|
|
58
|
+
const hits = filter ? state.screen.items.filter((item) => matches(item, filter)) : state.screen.items;
|
|
59
|
+
if (hits.length > 0)
|
|
60
|
+
return hits;
|
|
61
|
+
// Nothing to list, so the only way forward is writing the raw text. This is
|
|
62
|
+
// also the whole screen when no installed harness reported a catalog, which
|
|
63
|
+
// would never have a list to filter.
|
|
64
|
+
const raw = state.filter.trim();
|
|
65
|
+
const typed = parseFreeText(raw, state.screen.harnesses);
|
|
66
|
+
if (typed) {
|
|
67
|
+
return [{
|
|
68
|
+
id: typed.id,
|
|
69
|
+
label: `usar "${typed.id}" em ${typed.harness}`,
|
|
70
|
+
harness: typed.harness,
|
|
71
|
+
synthetic: true,
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
// An id with no harness in front of it is not a choice this screen can save,
|
|
75
|
+
// so the row says what is missing rather than offering an Enter that would
|
|
76
|
+
// have to guess. The empty id is what blocks that Enter.
|
|
77
|
+
const example = [...state.screen.harnesses][0] ?? "codex";
|
|
78
|
+
return [{
|
|
79
|
+
id: "",
|
|
80
|
+
label: raw ? `escreva ${example}:${raw}` : `digite harness:modelo, por exemplo ${example}:gpt-5.7`,
|
|
81
|
+
synthetic: true,
|
|
82
|
+
}];
|
|
83
|
+
}
|
|
84
|
+
function scrolled(state, cursor, viewport) {
|
|
85
|
+
const offset = Math.min(state.offset, cursor);
|
|
86
|
+
return { ...state, cursor, offset: Math.max(offset, cursor - viewport + 1) };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Pulls the cursor back into view without moving it. A resize can shrink the
|
|
90
|
+
* viewport under a cursor that was scrolled into the old one, and the frame
|
|
91
|
+
* then rendered a window the cursor was not in.
|
|
92
|
+
*/
|
|
93
|
+
export function reanchor(state, viewport) {
|
|
94
|
+
return scrolled(state, state.cursor, viewport);
|
|
95
|
+
}
|
|
96
|
+
const none = (state) => ({
|
|
97
|
+
state,
|
|
98
|
+
action: { kind: "none" },
|
|
99
|
+
});
|
|
100
|
+
export function applyKey(state, key, viewport) {
|
|
101
|
+
if (key.name === "paste-start")
|
|
102
|
+
return none({ ...state, pasting: true });
|
|
103
|
+
if (key.name === "paste-end")
|
|
104
|
+
return none({ ...state, pasting: false });
|
|
105
|
+
// Inside a paste only text gets through. A `\n` in the middle of pasted text
|
|
106
|
+
// must not choose a model, and a pasted `\x1b[A` must not move the cursor.
|
|
107
|
+
if (state.pasting) {
|
|
108
|
+
if (key.ctrl || key.meta || key.sequence.length !== 1)
|
|
109
|
+
return none(state);
|
|
110
|
+
if (key.sequence < " ")
|
|
111
|
+
return none(state);
|
|
112
|
+
// Pasted text edits the filter like typed text does, so it has to drop a
|
|
113
|
+
// pending confirmation the same way. Keeping it meant the footer asked
|
|
114
|
+
// about one id while the row on screen was already another.
|
|
115
|
+
return none({
|
|
116
|
+
...state,
|
|
117
|
+
confirming: undefined,
|
|
118
|
+
filter: state.filter + key.sequence,
|
|
119
|
+
cursor: 0,
|
|
120
|
+
offset: 0,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (key.ctrl && key.name === "c")
|
|
124
|
+
return { state, action: { kind: "aborted" } };
|
|
125
|
+
if (key.ctrl && key.name === "g")
|
|
126
|
+
return { state, action: { kind: "skipped" } };
|
|
127
|
+
const items = visibleItems(state);
|
|
128
|
+
const pending = state.confirming;
|
|
129
|
+
const cleared = pending === undefined ? state : { ...state, confirming: undefined };
|
|
130
|
+
if (key.name === "return") {
|
|
131
|
+
const item = items[cleared.cursor];
|
|
132
|
+
if (!item)
|
|
133
|
+
return none(cleared);
|
|
134
|
+
if (item.synthetic && item.id === "")
|
|
135
|
+
return none(cleared);
|
|
136
|
+
// Both halves or nothing. A row with no harness cannot be saved, and the
|
|
137
|
+
// rows that reach here without one are exactly the ones already refused
|
|
138
|
+
// above, so this only guards the type.
|
|
139
|
+
if (!item.harness)
|
|
140
|
+
return none(cleared);
|
|
141
|
+
const entry = itemKey(item.harness, item.id);
|
|
142
|
+
const picked = { kind: "picked", id: item.id, harness: item.harness };
|
|
143
|
+
if (!item.synthetic || cleared.screen.known.has(entry)) {
|
|
144
|
+
return { state: cleared, action: picked };
|
|
145
|
+
}
|
|
146
|
+
// The pending confirmation is keyed by both halves, so answering it for one
|
|
147
|
+
// harness cannot accept the same id under another.
|
|
148
|
+
if (pending === entry)
|
|
149
|
+
return { state: cleared, action: picked };
|
|
150
|
+
return none({ ...cleared, confirming: entry });
|
|
151
|
+
}
|
|
152
|
+
if (key.name === "up")
|
|
153
|
+
return none(scrolled(cleared, Math.max(0, cleared.cursor - 1), viewport));
|
|
154
|
+
if (key.name === "down") {
|
|
155
|
+
return none(scrolled(cleared, Math.min(items.length - 1, cleared.cursor + 1), viewport));
|
|
156
|
+
}
|
|
157
|
+
if (key.name === "backspace") {
|
|
158
|
+
return none({ ...cleared, filter: cleared.filter.slice(0, -1), cursor: 0, offset: 0 });
|
|
159
|
+
}
|
|
160
|
+
// Esc never skips: an arrow sequence that arrives fragmented shows up as a
|
|
161
|
+
// lone escape, and skipping on that would throw away the user's answer.
|
|
162
|
+
if (key.ctrl || key.meta || key.sequence.length !== 1)
|
|
163
|
+
return none(cleared);
|
|
164
|
+
if (key.sequence < " ")
|
|
165
|
+
return none(cleared);
|
|
166
|
+
return none({ ...cleared, filter: cleared.filter + key.sequence, cursor: 0, offset: 0 });
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=picker-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker-state.js","sourceRoot":"","sources":["../../src/cli/picker-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { emitKeypressEvents } from "node:readline";
|
|
2
|
+
import { applyKey, initialState, reanchor, } from "./picker-state.js";
|
|
3
|
+
import { readDimensions, renderFrame, viewportHeight } from "./ui.js";
|
|
4
|
+
const PASTE_ON = "\x1b[?2004h";
|
|
5
|
+
const PASTE_OFF = "\x1b[?2004l";
|
|
6
|
+
/**
|
|
7
|
+
* `emitKeypressEvents` attaches a parser to the stream and offers no way to
|
|
8
|
+
* take it back: it adds a `newListener` hook that swaps itself for a `data`
|
|
9
|
+
* handler once something listens for keypresses. Removing our own `keypress`
|
|
10
|
+
* handler leaves that parser turning every later byte into keypress events for
|
|
11
|
+
* a picker that is gone. Both names are watched because which one is left
|
|
12
|
+
* behind depends on whether a screen ever started.
|
|
13
|
+
*/
|
|
14
|
+
function detachKeypressParser(input, before) {
|
|
15
|
+
const stream = input;
|
|
16
|
+
for (const event of ["data", "newListener"]) {
|
|
17
|
+
for (const listener of stream.listeners(event)) {
|
|
18
|
+
if (!before[event].includes(listener))
|
|
19
|
+
stream.removeListener(event, listener);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Sole owner of raw mode, the listeners and the cleanup. Acquiring per screen
|
|
25
|
+
* would let one screen's type-ahead leak into the next.
|
|
26
|
+
*/
|
|
27
|
+
export async function runScreens(screens, io, c) {
|
|
28
|
+
const { input, output } = io;
|
|
29
|
+
const results = [];
|
|
30
|
+
let restored = false;
|
|
31
|
+
const restore = () => {
|
|
32
|
+
if (restored)
|
|
33
|
+
return;
|
|
34
|
+
restored = true;
|
|
35
|
+
try {
|
|
36
|
+
output.write(`${PASTE_OFF}\n`);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// A dead stdout (EPIPE under `| head`) must not cost the terminal its
|
|
40
|
+
// cooked mode: the write is the disposable half of restoring.
|
|
41
|
+
}
|
|
42
|
+
input.setRawMode?.(false);
|
|
43
|
+
input.pause();
|
|
44
|
+
};
|
|
45
|
+
// SIGTERM does not run the `exit` handler, and counting on Node to restore
|
|
46
|
+
// the TTY by itself is counting on luck.
|
|
47
|
+
const onExit = () => restore();
|
|
48
|
+
const onSigterm = () => {
|
|
49
|
+
restore();
|
|
50
|
+
process.exit(143);
|
|
51
|
+
};
|
|
52
|
+
process.on("exit", onExit);
|
|
53
|
+
process.on("SIGTERM", onSigterm);
|
|
54
|
+
// One frame and one resize listener for the whole run: a listener per screen
|
|
55
|
+
// piled up four of them on a four agent run.
|
|
56
|
+
const frame = { height: 0, repaint: () => { } };
|
|
57
|
+
let stopResize;
|
|
58
|
+
const listeners = input;
|
|
59
|
+
const before = {
|
|
60
|
+
data: [...listeners.listeners("data")],
|
|
61
|
+
newListener: [...listeners.listeners("newListener")],
|
|
62
|
+
};
|
|
63
|
+
// Setup lives inside the try because raw mode is on from its second line: a
|
|
64
|
+
// throw between there and the loop used to skip the finally entirely.
|
|
65
|
+
try {
|
|
66
|
+
emitKeypressEvents(input);
|
|
67
|
+
input.setRawMode?.(true);
|
|
68
|
+
input.resume();
|
|
69
|
+
output.write(PASTE_ON);
|
|
70
|
+
stopResize = io.onResize?.(() => frame.repaint());
|
|
71
|
+
const pending = [...screens];
|
|
72
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
73
|
+
const screen = pending[index];
|
|
74
|
+
const result = await runScreen(screen, io, c, frame);
|
|
75
|
+
results.push(result);
|
|
76
|
+
if (result.kind === "aborted")
|
|
77
|
+
break;
|
|
78
|
+
const followups = screen.next?.(result) ?? [];
|
|
79
|
+
if (followups.length > 0)
|
|
80
|
+
pending.splice(index + 1, 0, ...followups);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
frame.repaint = () => { };
|
|
85
|
+
stopResize?.();
|
|
86
|
+
detachKeypressParser(input, before);
|
|
87
|
+
process.off("exit", onExit);
|
|
88
|
+
process.off("SIGTERM", onSigterm);
|
|
89
|
+
restore();
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
}
|
|
93
|
+
function runScreen(screen, io, c, frame) {
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
const { input, output } = io;
|
|
96
|
+
let state = initialState(screen);
|
|
97
|
+
const paint = () => {
|
|
98
|
+
const dim = readDimensions(output);
|
|
99
|
+
// A resize can shrink the viewport under a cursor that was scrolled into
|
|
100
|
+
// the old one. Reanchoring here covers the repaint the resize triggers,
|
|
101
|
+
// where no key ran to fix the offset.
|
|
102
|
+
state = reanchor(state, viewportHeight(state, dim));
|
|
103
|
+
const lines = renderFrame(state, dim, c);
|
|
104
|
+
// Go up by the previous frame's height and clear from there down, or a
|
|
105
|
+
// smaller frame leaves the bigger one's leftovers on screen.
|
|
106
|
+
const prefix = frame.height > 0 ? `\x1b[${frame.height}A\x1b[0J` : "";
|
|
107
|
+
output.write(`${prefix}${lines.join("\n")}\n`);
|
|
108
|
+
frame.height = lines.length;
|
|
109
|
+
};
|
|
110
|
+
const detach = () => {
|
|
111
|
+
input.off("keypress", onKey);
|
|
112
|
+
frame.repaint = () => { };
|
|
113
|
+
};
|
|
114
|
+
const onKey = (sequence, key) => {
|
|
115
|
+
const pressed = key
|
|
116
|
+
? { ...key, sequence: key.sequence ?? sequence ?? "" }
|
|
117
|
+
: { sequence: sequence ?? "", ctrl: false, meta: false };
|
|
118
|
+
try {
|
|
119
|
+
const outcome = applyKey(state, pressed, viewportHeight(state, readDimensions(output)));
|
|
120
|
+
state = outcome.state;
|
|
121
|
+
if (outcome.action.kind === "none") {
|
|
122
|
+
paint();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
detach();
|
|
126
|
+
if (outcome.action.kind === "picked") {
|
|
127
|
+
resolve({
|
|
128
|
+
kind: "picked",
|
|
129
|
+
role: screen.role,
|
|
130
|
+
harness: outcome.action.harness,
|
|
131
|
+
id: outcome.action.id,
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (outcome.action.kind === "skipped") {
|
|
136
|
+
resolve({ kind: "skipped", role: screen.role });
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
resolve({ kind: "aborted" });
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
detach();
|
|
143
|
+
reject(error);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
input.on("keypress", onKey);
|
|
147
|
+
frame.repaint = paint;
|
|
148
|
+
try {
|
|
149
|
+
paint();
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
detach();
|
|
153
|
+
reject(error);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker.js","sourceRoot":"","sources":["../../src/cli/picker.ts"],"names":[],"mappings":"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"}
|