@gigaflow/gmux 0.15.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/CHANGELOG.md +654 -0
- package/LICENSE +21 -0
- package/README.md +351 -0
- package/dist/adapters/claude-code.d.ts +52 -0
- package/dist/adapters/claude-code.js +315 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +39 -0
- package/dist/adapters/codex.js +233 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/jsonl.d.ts +40 -0
- package/dist/adapters/jsonl.js +92 -0
- package/dist/adapters/jsonl.js.map +1 -0
- package/dist/adapters/registry.d.ts +11 -0
- package/dist/adapters/registry.js +21 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/types.d.ts +43 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli/border-client.d.ts +8 -0
- package/dist/cli/border-client.js +11 -0
- package/dist/cli/border-client.js.map +1 -0
- package/dist/cli/commands/__ask-cancel.d.ts +35 -0
- package/dist/cli/commands/__ask-cancel.js +91 -0
- package/dist/cli/commands/__ask-cancel.js.map +1 -0
- package/dist/cli/commands/__ask-refresh.d.ts +40 -0
- package/dist/cli/commands/__ask-refresh.js +54 -0
- package/dist/cli/commands/__ask-refresh.js.map +1 -0
- package/dist/cli/commands/__ask-run.d.ts +43 -0
- package/dist/cli/commands/__ask-run.js +126 -0
- package/dist/cli/commands/__ask-run.js.map +1 -0
- package/dist/cli/commands/__ask-send.d.ts +50 -0
- package/dist/cli/commands/__ask-send.js +138 -0
- package/dist/cli/commands/__ask-send.js.map +1 -0
- package/dist/cli/commands/__preview-card.d.ts +31 -0
- package/dist/cli/commands/__preview-card.js +72 -0
- package/dist/cli/commands/__preview-card.js.map +1 -0
- package/dist/cli/commands/ask.d.ts +50 -0
- package/dist/cli/commands/ask.js +240 -0
- package/dist/cli/commands/ask.js.map +1 -0
- package/dist/cli/commands/auto.d.ts +12 -0
- package/dist/cli/commands/auto.js +28 -0
- package/dist/cli/commands/auto.js.map +1 -0
- package/dist/cli/commands/cockpit.d.ts +14 -0
- package/dist/cli/commands/cockpit.js +52 -0
- package/dist/cli/commands/cockpit.js.map +1 -0
- package/dist/cli/commands/daemon.d.ts +75 -0
- package/dist/cli/commands/daemon.js +258 -0
- package/dist/cli/commands/daemon.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +6 -0
- package/dist/cli/commands/doctor.js +159 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/grep.d.ts +2 -0
- package/dist/cli/commands/grep.js +52 -0
- package/dist/cli/commands/grep.js.map +1 -0
- package/dist/cli/commands/index-cmd.d.ts +2 -0
- package/dist/cli/commands/index-cmd.js +29 -0
- package/dist/cli/commands/index-cmd.js.map +1 -0
- package/dist/cli/commands/ls.d.ts +30 -0
- package/dist/cli/commands/ls.js +95 -0
- package/dist/cli/commands/ls.js.map +1 -0
- package/dist/cli/commands/overlay.d.ts +26 -0
- package/dist/cli/commands/overlay.js +216 -0
- package/dist/cli/commands/overlay.js.map +1 -0
- package/dist/cli/commands/pick.d.ts +59 -0
- package/dist/cli/commands/pick.js +254 -0
- package/dist/cli/commands/pick.js.map +1 -0
- package/dist/cli/commands/picker-rows.d.ts +17 -0
- package/dist/cli/commands/picker-rows.js +47 -0
- package/dist/cli/commands/picker-rows.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +25 -0
- package/dist/cli/commands/resume.js +88 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/run.d.ts +13 -0
- package/dist/cli/commands/run.js +78 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +37 -0
- package/dist/cli/commands/setup.js +200 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/show.d.ts +2 -0
- package/dist/cli/commands/show.js +24 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/summarize.d.ts +2 -0
- package/dist/cli/commands/summarize.js +59 -0
- package/dist/cli/commands/summarize.js.map +1 -0
- package/dist/cli/commands/tmux.d.ts +11 -0
- package/dist/cli/commands/tmux.js +90 -0
- package/dist/cli/commands/tmux.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +2 -0
- package/dist/cli/commands/watch.js +76 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/format.d.ts +74 -0
- package/dist/cli/format.js +242 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/gmux-render.d.ts +11 -0
- package/dist/cli/gmux-render.js +60 -0
- package/dist/cli/gmux-render.js.map +1 -0
- package/dist/cli/main.d.ts +8 -0
- package/dist/cli/main.js +145 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/overlay-ask.d.ts +13 -0
- package/dist/cli/overlay-ask.js +32 -0
- package/dist/cli/overlay-ask.js.map +1 -0
- package/dist/cli/overlay.d.ts +26 -0
- package/dist/cli/overlay.js +149 -0
- package/dist/cli/overlay.js.map +1 -0
- package/dist/cli/picker.d.ts +308 -0
- package/dist/cli/picker.js +642 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/preview.d.ts +87 -0
- package/dist/cli/preview.js +292 -0
- package/dist/cli/preview.js.map +1 -0
- package/dist/cli/tmux-label.d.ts +50 -0
- package/dist/cli/tmux-label.js +146 -0
- package/dist/cli/tmux-label.js.map +1 -0
- package/dist/core/errors.d.ts +54 -0
- package/dist/core/errors.js +91 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/fingerprint.d.ts +21 -0
- package/dist/core/fingerprint.js +59 -0
- package/dist/core/fingerprint.js.map +1 -0
- package/dist/core/gmux-types.d.ts +102 -0
- package/dist/core/gmux-types.js +13 -0
- package/dist/core/gmux-types.js.map +1 -0
- package/dist/core/pane-state.d.ts +5 -0
- package/dist/core/pane-state.js +15 -0
- package/dist/core/pane-state.js.map +1 -0
- package/dist/core/paths.d.ts +68 -0
- package/dist/core/paths.js +106 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/proc-tree.d.ts +9 -0
- package/dist/core/proc-tree.js +33 -0
- package/dist/core/proc-tree.js.map +1 -0
- package/dist/core/text.d.ts +34 -0
- package/dist/core/text.js +126 -0
- package/dist/core/text.js.map +1 -0
- package/dist/core/types.d.ts +322 -0
- package/dist/core/types.js +10 -0
- package/dist/core/types.js.map +1 -0
- package/dist/services/ask-transcript.d.ts +256 -0
- package/dist/services/ask-transcript.js +544 -0
- package/dist/services/ask-transcript.js.map +1 -0
- package/dist/services/ask.d.ts +54 -0
- package/dist/services/ask.js +161 -0
- package/dist/services/ask.js.map +1 -0
- package/dist/services/auto-summarize.d.ts +188 -0
- package/dist/services/auto-summarize.js +415 -0
- package/dist/services/auto-summarize.js.map +1 -0
- package/dist/services/concurrency.d.ts +2 -0
- package/dist/services/concurrency.js +16 -0
- package/dist/services/concurrency.js.map +1 -0
- package/dist/services/config.d.ts +131 -0
- package/dist/services/config.js +325 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/daemon-client.d.ts +9 -0
- package/dist/services/daemon-client.js +34 -0
- package/dist/services/daemon-client.js.map +1 -0
- package/dist/services/daemon-socket.d.ts +30 -0
- package/dist/services/daemon-socket.js +76 -0
- package/dist/services/daemon-socket.js.map +1 -0
- package/dist/services/daemon.d.ts +43 -0
- package/dist/services/daemon.js +106 -0
- package/dist/services/daemon.js.map +1 -0
- package/dist/services/distill.d.ts +39 -0
- package/dist/services/distill.js +93 -0
- package/dist/services/distill.js.map +1 -0
- package/dist/services/guardian.d.ts +26 -0
- package/dist/services/guardian.js +71 -0
- package/dist/services/guardian.js.map +1 -0
- package/dist/services/index-store.d.ts +36 -0
- package/dist/services/index-store.js +125 -0
- package/dist/services/index-store.js.map +1 -0
- package/dist/services/log-rotation.d.ts +3 -0
- package/dist/services/log-rotation.js +28 -0
- package/dist/services/log-rotation.js.map +1 -0
- package/dist/services/pane-links.d.ts +10 -0
- package/dist/services/pane-links.js +47 -0
- package/dist/services/pane-links.js.map +1 -0
- package/dist/services/pane-process.d.ts +95 -0
- package/dist/services/pane-process.js +183 -0
- package/dist/services/pane-process.js.map +1 -0
- package/dist/services/pane-registry.d.ts +24 -0
- package/dist/services/pane-registry.js +40 -0
- package/dist/services/pane-registry.js.map +1 -0
- package/dist/services/provider-process.d.ts +37 -0
- package/dist/services/provider-process.js +105 -0
- package/dist/services/provider-process.js.map +1 -0
- package/dist/services/providers.d.ts +76 -0
- package/dist/services/providers.js +104 -0
- package/dist/services/providers.js.map +1 -0
- package/dist/services/resolve.d.ts +3 -0
- package/dist/services/resolve.js +18 -0
- package/dist/services/resolve.js.map +1 -0
- package/dist/services/resources.d.ts +17 -0
- package/dist/services/resources.js +113 -0
- package/dist/services/resources.js.map +1 -0
- package/dist/services/search.d.ts +29 -0
- package/dist/services/search.js +135 -0
- package/dist/services/search.js.map +1 -0
- package/dist/services/semantic-gate.d.ts +13 -0
- package/dist/services/semantic-gate.js +23 -0
- package/dist/services/semantic-gate.js.map +1 -0
- package/dist/services/semantic.d.ts +113 -0
- package/dist/services/semantic.js +216 -0
- package/dist/services/semantic.js.map +1 -0
- package/dist/services/sensors.d.ts +92 -0
- package/dist/services/sensors.js +246 -0
- package/dist/services/sensors.js.map +1 -0
- package/dist/services/summarize.d.ts +84 -0
- package/dist/services/summarize.js +230 -0
- package/dist/services/summarize.js.map +1 -0
- package/dist/services/tmux-gateway.d.ts +17 -0
- package/dist/services/tmux-gateway.js +10 -0
- package/dist/services/tmux-gateway.js.map +1 -0
- package/dist/services/tmux-resolve.d.ts +54 -0
- package/dist/services/tmux-resolve.js +0 -0
- package/dist/services/tmux-resolve.js.map +1 -0
- package/dist/services/tmux.d.ts +32 -0
- package/dist/services/tmux.js +107 -0
- package/dist/services/tmux.js.map +1 -0
- package/dist/services/views.d.ts +7 -0
- package/dist/services/views.js +18 -0
- package/dist/services/views.js.map +1 -0
- package/dist/services/watch.d.ts +36 -0
- package/dist/services/watch.js +98 -0
- package/dist/services/watch.js.map +1 -0
- package/dist/services/workspace.d.ts +19 -0
- package/dist/services/workspace.js +88 -0
- package/dist/services/workspace.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SCHEMA_VERSION } from "../../core/types.js";
|
|
2
|
+
import { relativeAge } from "../../core/text.js";
|
|
3
|
+
import { loadRecords } from "../../services/views.js";
|
|
4
|
+
import { searchSessions } from "../../services/search.js";
|
|
5
|
+
import { bold, cyan, dim, jsonEnvelope, sessionLabel } from "../format.js";
|
|
6
|
+
import { toFilters } from "./ls.js";
|
|
7
|
+
export function registerGrep(program) {
|
|
8
|
+
program
|
|
9
|
+
.command("grep <query>")
|
|
10
|
+
.description("search the full text of every transcript, grouped by session")
|
|
11
|
+
.option("--harness <id>", "only this harness")
|
|
12
|
+
.option("-p, --project <name>", "only sessions whose project matches")
|
|
13
|
+
.option("-s, --since <when>", "only sessions newer than this (3d, 12h, 2w)")
|
|
14
|
+
.option("-n, --limit <count>", "max sessions to report", "20")
|
|
15
|
+
.option("-e, --regex", "treat the query as a regular expression")
|
|
16
|
+
.option("-C, --case-sensitive", "match case")
|
|
17
|
+
.option("--include-sidechains", "include subagent transcripts")
|
|
18
|
+
.option("--include-automated", "include non-interactive runs (claude -p, codex exec)")
|
|
19
|
+
.option("--json", "emit JSON for scripts and agents")
|
|
20
|
+
.action(async (query, options) => {
|
|
21
|
+
// Search every session the filters allow, then cap the *results*, not the
|
|
22
|
+
// corpus — capping the corpus first would silently hide matches.
|
|
23
|
+
const filters = toFilters(options, 0);
|
|
24
|
+
delete filters.limit;
|
|
25
|
+
const records = await loadRecords(filters);
|
|
26
|
+
const limit = options.limit ? Number.parseInt(options.limit, 10) : 20;
|
|
27
|
+
const hits = await searchSessions({
|
|
28
|
+
records,
|
|
29
|
+
query,
|
|
30
|
+
regex: options.regex === true,
|
|
31
|
+
caseSensitive: options.caseSensitive === true,
|
|
32
|
+
maxSessions: limit,
|
|
33
|
+
});
|
|
34
|
+
if (options.json) {
|
|
35
|
+
process.stdout.write(`${jsonEnvelope(SCHEMA_VERSION, hits)}\n`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (hits.length === 0) {
|
|
39
|
+
process.stdout.write(`${dim(`No session mentions "${query}".`)}\n`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
for (const hit of hits) {
|
|
43
|
+
const { session } = hit;
|
|
44
|
+
process.stdout.write(`${bold(cyan(sessionLabel(session)))} ${dim(session.sessionId.slice(0, 8))} ${dim(`${relativeAge(session.updatedAt)} ago · ${hit.matchCount} match${hit.matchCount === 1 ? "" : "es"}`)}\n`);
|
|
45
|
+
for (const snippet of hit.snippets)
|
|
46
|
+
process.stdout.write(` ${dim("…")}${snippet}\n`);
|
|
47
|
+
process.stdout.write("\n");
|
|
48
|
+
}
|
|
49
|
+
process.stdout.write(`${dim(`${hits.length} session${hits.length === 1 ? "" : "s"}. Open one with: gmux show <id>`)}\n`);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=grep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/cli/commands/grep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SCHEMA_VERSION } from "../../core/types.js";
|
|
2
|
+
import { indexPath } from "../../core/paths.js";
|
|
3
|
+
import { refreshIndex } from "../../services/index-store.js";
|
|
4
|
+
import { dim, green, jsonEnvelope } from "../format.js";
|
|
5
|
+
export function registerIndex(program) {
|
|
6
|
+
program
|
|
7
|
+
.command("index")
|
|
8
|
+
.description("refresh the session index (normally automatic)")
|
|
9
|
+
.option("--rebuild", "re-parse every session, ignoring the cache")
|
|
10
|
+
.option("--json", "emit JSON for scripts and agents")
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
const started = Date.now();
|
|
13
|
+
const result = await refreshIndex({ force: options.rebuild === true });
|
|
14
|
+
const elapsedMs = Date.now() - started;
|
|
15
|
+
const stats = {
|
|
16
|
+
sessions: result.records.length,
|
|
17
|
+
parsed: result.parsed,
|
|
18
|
+
servedFromCache: result.cached,
|
|
19
|
+
elapsedMs,
|
|
20
|
+
indexPath: indexPath(),
|
|
21
|
+
};
|
|
22
|
+
if (options.json) {
|
|
23
|
+
process.stdout.write(`${jsonEnvelope(SCHEMA_VERSION, stats)}\n`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
process.stdout.write(`${green(`✓ ${stats.sessions} sessions indexed`)} ${dim(`(${stats.parsed} parsed, ${stats.servedFromCache} cached, ${elapsedMs}ms)`)}\n${dim(stats.indexPath)}\n`);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=index-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-cmd.js","sourceRoot":"","sources":["../../../src/cli/commands/index-cmd.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,WAAW,EAAE,4CAA4C,CAAC;SACjE,MAAM,CAAC,QAAQ,EAAE,kCAAkC,CAAC;SACpD,MAAM,CAAC,KAAK,EAAE,OAA8C,EAAE,EAAE;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC;QACvE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;QAEvC,MAAM,KAAK,GAAG;YACZ,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;YAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,eAAe,EAAE,MAAM,CAAC,MAAM;YAC9B,SAAS;YACT,SAAS,EAAE,SAAS,EAAE;SACvB,CAAC;QAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACjE,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,QAAQ,mBAAmB,CAAC,IAAI,GAAG,CACrD,IAAI,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,eAAe,YAAY,SAAS,KAAK,CAC5E,KAAK,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAC/B,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type ListFilters } from "../../core/types.js";
|
|
3
|
+
export interface LsOptions {
|
|
4
|
+
harness?: string;
|
|
5
|
+
project?: string;
|
|
6
|
+
branch?: string;
|
|
7
|
+
since?: string;
|
|
8
|
+
limit?: string;
|
|
9
|
+
includeSidechains?: boolean;
|
|
10
|
+
includeAutomated?: boolean;
|
|
11
|
+
json?: boolean;
|
|
12
|
+
autoSummarize?: boolean;
|
|
13
|
+
resumeInWindow?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Whether `--no-auto-summarize` was passed.
|
|
17
|
+
*
|
|
18
|
+
* MUST be read with `optsWithGlobals`. `--no-auto-summarize` is declared on the
|
|
19
|
+
* ROOT program, and commander does not copy root options into a subcommand's
|
|
20
|
+
* own `opts()` — reading `options.autoSummarize` there yields `undefined`
|
|
21
|
+
* forever, so `undefined !== false` is always true and the flag silently does
|
|
22
|
+
* nothing. That is exactly what `gmux --no-auto-summarize ls` did before this
|
|
23
|
+
* existed: it spent tokens the user had explicitly declined.
|
|
24
|
+
*
|
|
25
|
+
* Shared by `ls`, `pick` and `__picker-rows` so the three cannot drift apart.
|
|
26
|
+
*/
|
|
27
|
+
export declare function autoSummarizeRequested(command: Command): boolean;
|
|
28
|
+
/** Shared by `ls` and the picker so both filter identically. */
|
|
29
|
+
export declare function toFilters(options: LsOptions, fallbackLimit: number): ListFilters;
|
|
30
|
+
export declare function registerLs(program: Command): void;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { SCHEMA_VERSION } from "../../core/types.js";
|
|
2
|
+
import { parseSince } from "../../core/text.js";
|
|
3
|
+
import { GmuxError } from "../../core/errors.js";
|
|
4
|
+
import { loadViews } from "../../services/views.js";
|
|
5
|
+
import { inProgressIds, maybeAutoSummarize } from "../../services/auto-summarize.js";
|
|
6
|
+
import { dim, formatLegend, formatRowLines, jsonEnvelope, terminalWidth } from "../format.js";
|
|
7
|
+
/**
|
|
8
|
+
* Whether `--no-auto-summarize` was passed.
|
|
9
|
+
*
|
|
10
|
+
* MUST be read with `optsWithGlobals`. `--no-auto-summarize` is declared on the
|
|
11
|
+
* ROOT program, and commander does not copy root options into a subcommand's
|
|
12
|
+
* own `opts()` — reading `options.autoSummarize` there yields `undefined`
|
|
13
|
+
* forever, so `undefined !== false` is always true and the flag silently does
|
|
14
|
+
* nothing. That is exactly what `gmux --no-auto-summarize ls` did before this
|
|
15
|
+
* existed: it spent tokens the user had explicitly declined.
|
|
16
|
+
*
|
|
17
|
+
* Shared by `ls`, `pick` and `__picker-rows` so the three cannot drift apart.
|
|
18
|
+
*/
|
|
19
|
+
export function autoSummarizeRequested(command) {
|
|
20
|
+
return command.optsWithGlobals()["autoSummarize"] !== false;
|
|
21
|
+
}
|
|
22
|
+
/** Shared by `ls` and the picker so both filter identically. */
|
|
23
|
+
export function toFilters(options, fallbackLimit) {
|
|
24
|
+
const filters = {
|
|
25
|
+
includeSidechains: options.includeSidechains === true,
|
|
26
|
+
includeAutomated: options.includeAutomated === true,
|
|
27
|
+
limit: options.limit ? Number.parseInt(options.limit, 10) : fallbackLimit,
|
|
28
|
+
};
|
|
29
|
+
if (options.harness)
|
|
30
|
+
filters.harness = options.harness;
|
|
31
|
+
if (options.project)
|
|
32
|
+
filters.project = options.project;
|
|
33
|
+
if (options.branch)
|
|
34
|
+
filters.branch = options.branch;
|
|
35
|
+
if (options.since) {
|
|
36
|
+
const cutoff = parseSince(options.since);
|
|
37
|
+
if (!cutoff) {
|
|
38
|
+
throw new GmuxError(`Could not understand --since "${options.since}".`, {
|
|
39
|
+
fix: "Use a duration like `3d`, `12h`, `2w`, or an ISO date like `2026-07-01`.",
|
|
40
|
+
exitCode: 2,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
filters.since = cutoff;
|
|
44
|
+
}
|
|
45
|
+
return filters;
|
|
46
|
+
}
|
|
47
|
+
export function registerLs(program) {
|
|
48
|
+
program
|
|
49
|
+
.command("ls")
|
|
50
|
+
.description("list recent sessions, most recent first")
|
|
51
|
+
.option("--harness <id>", "only this harness (claude-code, codex)")
|
|
52
|
+
.option("-p, --project <name>", "only sessions whose project matches")
|
|
53
|
+
.option("-b, --branch <name>", "only sessions whose git branch matches")
|
|
54
|
+
.option("-s, --since <when>", "only sessions newer than this (3d, 12h, 2w, or a date)")
|
|
55
|
+
.option("-n, --limit <count>", "how many to show", "20")
|
|
56
|
+
.option("--include-sidechains", "include subagent transcripts")
|
|
57
|
+
.option("--include-automated", "include non-interactive runs (claude -p, codex exec)")
|
|
58
|
+
.option("--json", "emit JSON for scripts and agents")
|
|
59
|
+
.action(async (options, command) => {
|
|
60
|
+
const views = await loadViews(toFilters(options, 20));
|
|
61
|
+
if (options.json) {
|
|
62
|
+
process.stdout.write(`${jsonEnvelope(SCHEMA_VERSION, views)}\n`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (views.length === 0) {
|
|
66
|
+
process.stdout.write(`${dim("No sessions matched.")}\n`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Kick the background pass off BEFORE rendering, over exactly the sessions
|
|
70
|
+
// we are about to show — so `gmux ls -n 50` summarizes all fifty, and the
|
|
71
|
+
// rows it just picked up can be marked ◐ on this very run rather than the
|
|
72
|
+
// next one. Deciding costs a lock write and a spawn; the model calls all
|
|
73
|
+
// happen in the detached child.
|
|
74
|
+
const started = await maybeAutoSummarize({
|
|
75
|
+
records: views.map((v) => v.record),
|
|
76
|
+
enabled: autoSummarizeRequested(command),
|
|
77
|
+
notify: (message) => process.stderr.write(`${dim(message)}\n`),
|
|
78
|
+
});
|
|
79
|
+
// Rows already in flight from an earlier run count too.
|
|
80
|
+
const inProgress = new Set([...(await inProgressIds()), ...started.targetIds]);
|
|
81
|
+
// Wrap to the terminal so a long summary is readable in full. When piped,
|
|
82
|
+
// stay one line per session so `gmux ls | grep` still works.
|
|
83
|
+
const width = process.stdout.isTTY ? terminalWidth() : Number.POSITIVE_INFINITY;
|
|
84
|
+
const now = new Date();
|
|
85
|
+
for (const view of views) {
|
|
86
|
+
for (const line of formatRowLines(view, now, width, inProgress)) {
|
|
87
|
+
process.stdout.write(`${line}\n`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const legend = formatLegend(views, inProgress);
|
|
91
|
+
if (legend !== "")
|
|
92
|
+
process.stdout.write(`\n${legend}\n`);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=ls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/cli/commands/ls.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAe9F;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO,OAAO,CAAC,eAAe,EAAE,CAAC,eAAe,CAAC,KAAK,KAAK,CAAC;AAC9D,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,SAAS,CAAC,OAAkB,EAAE,aAAqB;IACjE,MAAM,OAAO,GAAgB;QAC3B,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,KAAK,IAAI;QACrD,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,KAAK,IAAI;QACnD,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa;KAC1E,CAAC;IACF,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACvD,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACvD,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEpD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,SAAS,CAAC,iCAAiC,OAAO,CAAC,KAAK,IAAI,EAAE;gBACtE,GAAG,EAAE,0EAA0E;gBAC/E,QAAQ,EAAE,CAAC;aACZ,CAAC,CAAC;QACL,CAAC;QACD,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO;SACJ,OAAO,CAAC,IAAI,CAAC;SACb,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,gBAAgB,EAAE,wCAAwC,CAAC;SAClE,MAAM,CAAC,sBAAsB,EAAE,qCAAqC,CAAC;SACrE,MAAM,CAAC,qBAAqB,EAAE,wCAAwC,CAAC;SACvE,MAAM,CAAC,oBAAoB,EAAE,wDAAwD,CAAC;SACtF,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,EAAE,IAAI,CAAC;SACvD,MAAM,CAAC,sBAAsB,EAAE,8BAA8B,CAAC;SAC9D,MAAM,CAAC,qBAAqB,EAAE,sDAAsD,CAAC;SACrF,MAAM,CAAC,QAAQ,EAAE,kCAAkC,CAAC;SACpD,MAAM,CAAC,KAAK,EAAE,OAAkB,EAAE,OAAgB,EAAE,EAAE;QACrD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QAEtD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACjE,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QAED,2EAA2E;QAC3E,0EAA0E;QAC1E,0EAA0E;QAC1E,yEAAyE;QACzE,gCAAgC;QAChC,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC;YACvC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YACnC,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC;YACxC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;SAC/D,CAAC,CAAC;QAEH,wDAAwD;QACxD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,aAAa,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAE/E,0EAA0E;QAC1E,6DAA6D;QAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAChF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC;gBAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC/C,IAAI,MAAM,KAAK,EAAE;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { SessionView } from "../../core/types.js";
|
|
3
|
+
import { type ResolvedPane } from "../../services/tmux-resolve.js";
|
|
4
|
+
import { type OverlayCell } from "../overlay.js";
|
|
5
|
+
/** A question broadcast to every pane, and the per-session answers as they land. */
|
|
6
|
+
export interface AskBroadcast {
|
|
7
|
+
question: string;
|
|
8
|
+
answers: Map<string, string>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Pair each resolved pane with its summary view and the in-flight refresh set —
|
|
12
|
+
* and, when a question has been broadcast, this pane's own answer (or the
|
|
13
|
+
* `asking…` state until it lands). Pure, so the pairing is tested without a terminal.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildCells(resolved: readonly ResolvedPane[], views: readonly SessionView[], refreshingIds: ReadonlySet<string>, ask?: AskBroadcast | null): OverlayCell[];
|
|
16
|
+
/**
|
|
17
|
+
* The keys that dismiss the overlay.
|
|
18
|
+
*
|
|
19
|
+
* ctrl-g (`\x07`) is here so the same key that opens the popup also closes it —
|
|
20
|
+
* a toggle, which is what a peek key should feel like. Since the ask box landed
|
|
21
|
+
* every other key types into it, so a close key has to be spelled out; without
|
|
22
|
+
* ctrl-g listed it would fall through and be swallowed as un-printable input.
|
|
23
|
+
* Esc, ctrl-c and ctrl-d are the long-standing exits, kept exactly.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isCloseKey(s: string): boolean;
|
|
26
|
+
export declare function registerOverlay(program: Command): void;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { buildAskContext, buildAskPrompt, defaultAskProvider } from "../../services/ask.js";
|
|
2
|
+
import { inProgressIds, maybeAutoSummarize } from "../../services/auto-summarize.js";
|
|
3
|
+
import { mapLimit } from "../../services/concurrency.js";
|
|
4
|
+
import { prunePaneLinks } from "../../services/pane-links.js";
|
|
5
|
+
import { defaultSummaryProvider, summarizeBatch } from "../../services/summarize.js";
|
|
6
|
+
import { listAllPanes, listPanes } from "../../services/tmux.js";
|
|
7
|
+
import { resolvePanesLive } from "../../services/tmux-resolve.js";
|
|
8
|
+
import { attachSummaries, loadCachedRecords, loadRecords } from "../../services/views.js";
|
|
9
|
+
import { renderOverlay } from "../overlay.js";
|
|
10
|
+
import { ASK_BOX_HEIGHT, askBoxLines, askCursorColumn } from "../overlay-ask.js";
|
|
11
|
+
/** How often the overlay repaints while it waits, to fold in landed refreshes. */
|
|
12
|
+
const REPAINT_MS = 1000;
|
|
13
|
+
const CLEAR = "\x1b[2J\x1b[H";
|
|
14
|
+
/**
|
|
15
|
+
* Pair each resolved pane with its summary view and the in-flight refresh set —
|
|
16
|
+
* and, when a question has been broadcast, this pane's own answer (or the
|
|
17
|
+
* `asking…` state until it lands). Pure, so the pairing is tested without a terminal.
|
|
18
|
+
*/
|
|
19
|
+
export function buildCells(resolved, views, refreshingIds, ask) {
|
|
20
|
+
const bySession = new Map(views.map((v) => [v.record.sessionId, v]));
|
|
21
|
+
return resolved.map(({ pane, record }) => {
|
|
22
|
+
const cell = {
|
|
23
|
+
pane,
|
|
24
|
+
view: record ? bySession.get(record.sessionId) ?? { record, summary: null } : null,
|
|
25
|
+
refreshing: record ? refreshingIds.has(record.sessionId) : false,
|
|
26
|
+
};
|
|
27
|
+
if (ask && record) {
|
|
28
|
+
cell.answer = ask.answers.get(record.sessionId) ?? null;
|
|
29
|
+
cell.asking = cell.answer == null;
|
|
30
|
+
}
|
|
31
|
+
return cell;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The keys that dismiss the overlay.
|
|
36
|
+
*
|
|
37
|
+
* ctrl-g (`\x07`) is here so the same key that opens the popup also closes it —
|
|
38
|
+
* a toggle, which is what a peek key should feel like. Since the ask box landed
|
|
39
|
+
* every other key types into it, so a close key has to be spelled out; without
|
|
40
|
+
* ctrl-g listed it would fall through and be swallowed as un-printable input.
|
|
41
|
+
* Esc, ctrl-c and ctrl-d are the long-standing exits, kept exactly.
|
|
42
|
+
*/
|
|
43
|
+
export function isCloseKey(s) {
|
|
44
|
+
return s === "\x1b" || s === "\x03" || s === "\x04" || s === "\x07";
|
|
45
|
+
}
|
|
46
|
+
const rows = () => process.stdout.rows || 24;
|
|
47
|
+
const cols = () => process.stdout.columns || 80;
|
|
48
|
+
/** The card frame for the resolved panes — re-reads only the (small) summaries. */
|
|
49
|
+
async function cardsFrame(resolved, ask, forcing) {
|
|
50
|
+
const present = resolved
|
|
51
|
+
.map((r) => r.record)
|
|
52
|
+
.filter((r) => r !== null);
|
|
53
|
+
const views = await attachSummaries(present);
|
|
54
|
+
const refreshing = new Set([...(await inProgressIds()), ...forcing]);
|
|
55
|
+
return renderOverlay(buildCells(resolved, views, refreshing, ask));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the window's panes with GLOBAL de-duplication, so a fresh pane can't
|
|
59
|
+
* claim a session another window's pane already owns. Resolves every pane in the
|
|
60
|
+
* server, then keeps just this window's.
|
|
61
|
+
*/
|
|
62
|
+
async function resolveWindow(windowId, records) {
|
|
63
|
+
const all = await listAllPanes();
|
|
64
|
+
const links = await prunePaneLinks(all.map((p) => p.paneId));
|
|
65
|
+
const windowPaneIds = new Set((await listPanes(windowId)).map((p) => p.paneId));
|
|
66
|
+
const resolvedAll = await resolvePanesLive(all, records, links);
|
|
67
|
+
return resolvedAll.filter((r) => windowPaneIds.has(r.pane.paneId));
|
|
68
|
+
}
|
|
69
|
+
/** The ask box drawn across the bottom rows, with the cursor left in the field. */
|
|
70
|
+
function boxFrame(input) {
|
|
71
|
+
const top = rows() - ASK_BOX_HEIGHT + 1; // 1-based first box row
|
|
72
|
+
let out = "";
|
|
73
|
+
askBoxLines(input, cols()).forEach((line, i) => {
|
|
74
|
+
out += `\x1b[${top + i};1H${line}`;
|
|
75
|
+
});
|
|
76
|
+
out += `\x1b[${top + 1};${askCursorColumn(input, cols())}H`; // cursor into the input line
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
/** One concise answer per session — asked in parallel, but bounded. */
|
|
80
|
+
const ASK_CONCURRENCY = 6;
|
|
81
|
+
async function runOverlay(windowId) {
|
|
82
|
+
// A peek must feel instant. We reach this command only because `display-popup`
|
|
83
|
+
// launched it, which already proves tmux >= 3.2. Resolve ONCE from the cache;
|
|
84
|
+
// repaints re-read only summaries, so an open overlay is not re-scanning
|
|
85
|
+
// thousands of files every second.
|
|
86
|
+
let resolved = await resolveWindow(windowId, await loadCachedRecords());
|
|
87
|
+
const state = { input: "", ask: null };
|
|
88
|
+
const forcing = new Set(); // sessions being force-regenerated right now (ctrl-r)
|
|
89
|
+
let busy = false; // a broadcast is in flight
|
|
90
|
+
let provider = null;
|
|
91
|
+
void defaultAskProvider()
|
|
92
|
+
.then((p) => (provider = p))
|
|
93
|
+
.catch(() => { });
|
|
94
|
+
// Always cards (with any per-pane answers) above, the ask box below.
|
|
95
|
+
const drawAll = async () => {
|
|
96
|
+
process.stdout.write(CLEAR + (await cardsFrame(resolved, state.ask, forcing)) + boxFrame(state.input));
|
|
97
|
+
};
|
|
98
|
+
await drawAll();
|
|
99
|
+
// Off the critical path: upgrade to the full index, re-resolve, and kick stale
|
|
100
|
+
// cards to refresh in the background — targeting exactly the panes on screen.
|
|
101
|
+
void (async () => {
|
|
102
|
+
resolved = await resolveWindow(windowId, await loadRecords());
|
|
103
|
+
if (!state.ask && !busy)
|
|
104
|
+
await drawAll();
|
|
105
|
+
const present = resolved.map((r) => r.record).filter((r) => r !== null);
|
|
106
|
+
await maybeAutoSummarize({ records: present, force: true });
|
|
107
|
+
})().catch(() => { });
|
|
108
|
+
// Repaint the cards while browsing (not while a broadcast owns the screen).
|
|
109
|
+
const timer = setInterval(() => {
|
|
110
|
+
if (!state.ask && !busy)
|
|
111
|
+
void drawAll().catch(() => { });
|
|
112
|
+
}, REPAINT_MS);
|
|
113
|
+
/** Broadcast the question to every pane's session, answering each on its card. */
|
|
114
|
+
const broadcast = async (question) => {
|
|
115
|
+
const present = resolved.map((r) => r.record).filter((r) => r !== null);
|
|
116
|
+
const views = await attachSummaries(present);
|
|
117
|
+
const byId = new Map(views.map((v) => [v.record.sessionId, v]));
|
|
118
|
+
const answers = new Map();
|
|
119
|
+
state.ask = { question, answers };
|
|
120
|
+
if (!provider) {
|
|
121
|
+
for (const r of present)
|
|
122
|
+
answers.set(r.sessionId, "No model configured — run `gmux setup`.");
|
|
123
|
+
await drawAll();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
busy = true;
|
|
127
|
+
await drawAll(); // every card shows "asking…"
|
|
128
|
+
await mapLimit(present, ASK_CONCURRENCY, async (record) => {
|
|
129
|
+
try {
|
|
130
|
+
const view = byId.get(record.sessionId);
|
|
131
|
+
const context = buildAskContext(view ? [view] : [], record.sessionId, 1);
|
|
132
|
+
const answer = await provider.ask(buildAskPrompt(context, [], question));
|
|
133
|
+
answers.set(record.sessionId, answer.trim());
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
answers.set(record.sessionId, `ask failed: ${error.message}`);
|
|
137
|
+
}
|
|
138
|
+
await drawAll(); // this card fills in as its answer lands
|
|
139
|
+
});
|
|
140
|
+
busy = false;
|
|
141
|
+
await drawAll();
|
|
142
|
+
};
|
|
143
|
+
/** ctrl-r: regenerate every visible pane's summary now, ignoring the divergence gate. */
|
|
144
|
+
const forceRefresh = async () => {
|
|
145
|
+
const present = resolved.map((r) => r.record).filter((r) => r !== null);
|
|
146
|
+
if (present.length === 0)
|
|
147
|
+
return;
|
|
148
|
+
present.forEach((r) => forcing.add(r.sessionId));
|
|
149
|
+
await drawAll(); // cards show refreshing…
|
|
150
|
+
try {
|
|
151
|
+
const summaryProvider = await defaultSummaryProvider();
|
|
152
|
+
if (summaryProvider && (await summaryProvider.isAvailable())) {
|
|
153
|
+
await summarizeBatch(present, summaryProvider, { force: true });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
present.forEach((r) => forcing.delete(r.sessionId));
|
|
158
|
+
await drawAll();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const stdin = process.stdin;
|
|
162
|
+
if (stdin.isTTY)
|
|
163
|
+
stdin.setRawMode(true);
|
|
164
|
+
stdin.resume();
|
|
165
|
+
await new Promise((done) => {
|
|
166
|
+
stdin.on("data", (buf) => {
|
|
167
|
+
void (async () => {
|
|
168
|
+
const s = buf.toString();
|
|
169
|
+
if (isCloseKey(s))
|
|
170
|
+
return done(); // Esc / ctrl-c / ctrl-d / ctrl-g
|
|
171
|
+
if (s.startsWith("\x1b"))
|
|
172
|
+
return; // an arrow or other escape sequence — ignore
|
|
173
|
+
if (s === "\x12")
|
|
174
|
+
return void forceRefresh(); // ctrl-r: force a summary refresh now
|
|
175
|
+
if (busy)
|
|
176
|
+
return; // a broadcast is landing; ignore keys (Esc handled above)
|
|
177
|
+
if (s === "\r" || s === "\n") {
|
|
178
|
+
const question = state.input.trim();
|
|
179
|
+
state.input = "";
|
|
180
|
+
if (!question) {
|
|
181
|
+
// Empty Enter clears the answers, returning the cards to their summaries.
|
|
182
|
+
if (state.ask) {
|
|
183
|
+
state.ask = null;
|
|
184
|
+
await drawAll();
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
await broadcast(question);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (s === "\x7f" || s === "\b") {
|
|
192
|
+
state.input = state.input.slice(0, -1);
|
|
193
|
+
process.stdout.write(boxFrame(state.input));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const printable = [...s].filter((c) => c >= " " && c <= "~").join("");
|
|
197
|
+
if (printable) {
|
|
198
|
+
state.input += printable;
|
|
199
|
+
process.stdout.write(boxFrame(state.input));
|
|
200
|
+
}
|
|
201
|
+
})().catch(() => { });
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
clearInterval(timer);
|
|
205
|
+
process.stdout.write("\x1b[2J\x1b[H");
|
|
206
|
+
process.exit(0);
|
|
207
|
+
}
|
|
208
|
+
export function registerOverlay(program) {
|
|
209
|
+
program
|
|
210
|
+
.command("overlay <window>")
|
|
211
|
+
.description("draw every pane's summary in place (used by the tmux ctrl-g binding)")
|
|
212
|
+
.action(async (windowId) => {
|
|
213
|
+
await runOverlay(windowId);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../src/cli/commands/overlay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type LsOptions } from "./ls.js";
|
|
3
|
+
/** The hidden command fzf's ctrl-r binding runs. Not a thing a person runs. */
|
|
4
|
+
export declare const PICKER_ROWS_COMMAND = "__picker-rows";
|
|
5
|
+
export interface PickerRowsOptions extends LsOptions {
|
|
6
|
+
/** The parent's measured list width. The reload child's own stdout is a pipe. */
|
|
7
|
+
width?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The filter flags this picker was opened with, as argv.
|
|
11
|
+
*
|
|
12
|
+
* One copy, because every command the picker spawns must describe the *same*
|
|
13
|
+
* window. A filter that drifts in one of several copies is the silent
|
|
14
|
+
* wrong-window bug the `pickerAskArgs` comment below exists to warn about —
|
|
15
|
+
* nothing errors, the answers are just about other sessions.
|
|
16
|
+
*
|
|
17
|
+
* Values are NOT quoted here — the caller joins and quotes, because argv and a
|
|
18
|
+
* shell command string want different escaping.
|
|
19
|
+
*/
|
|
20
|
+
export declare function filterArgs(options: LsOptions): string[];
|
|
21
|
+
/**
|
|
22
|
+
* The argv behind ctrl-o, reproducing this picker's filter set for `gmux ask`.
|
|
23
|
+
*
|
|
24
|
+
* Pure, and separate from `pickerReloadArgs` only because the two target
|
|
25
|
+
* different commands — they carry the same filters for the same reason.
|
|
26
|
+
*
|
|
27
|
+
* THE FILTERS ARE THE POINT. `gmux ask` builds its own window; left to its
|
|
28
|
+
* defaults it takes the 20 most recent sessions across every project, which for
|
|
29
|
+
* `gmux pick -p webshop` (or any pick past the 20th row) does not contain the
|
|
30
|
+
* session you are highlighting. `--focus` then finds nothing, resolves to null,
|
|
31
|
+
* and the chat answers about sessions you were not looking at — with no sign
|
|
32
|
+
* anything went wrong.
|
|
33
|
+
*
|
|
34
|
+
* `-n` is forwarded too: the window ask reasons over should be the list you are
|
|
35
|
+
* looking at, not a shorter one it chose for itself.
|
|
36
|
+
*
|
|
37
|
+
* `--focus {1}` is NOT added here. fzf substitutes that token, so it is appended
|
|
38
|
+
* unquoted by the picker; a shell-quoted `{1}` would arrive as a literal.
|
|
39
|
+
*/
|
|
40
|
+
export declare function pickerAskArgs(options: LsOptions): string[];
|
|
41
|
+
/**
|
|
42
|
+
* The argv that reproduces this picker's filter set, for fzf's reload binding.
|
|
43
|
+
*
|
|
44
|
+
* Pure, so the thing a refresh actually runs is testable without spawning fzf.
|
|
45
|
+
*
|
|
46
|
+
* `--width` is passed explicitly: the reload child's stdout is a pipe, so it
|
|
47
|
+
* cannot measure the terminal and would fall back to a default width, reflowing
|
|
48
|
+
* every row on refresh. Only the parent, inside fzf, knows the real width.
|
|
49
|
+
*/
|
|
50
|
+
export declare function pickerReloadArgs(options: LsOptions, width: number, autoSummarize?: boolean): string[];
|
|
51
|
+
/**
|
|
52
|
+
* The bare `gmux` command: pick a recent session, then resume it.
|
|
53
|
+
* This is the whole point of the tool — everything else is in service of it.
|
|
54
|
+
*
|
|
55
|
+
* Registered as commander's *default* command rather than as options on the root
|
|
56
|
+
* program. Hanging `-n`/`-p` off the root would shadow the identically-named
|
|
57
|
+
* flags on `gmux ls`, so `gmux ls -n 8` would silently ignore the 8.
|
|
58
|
+
*/
|
|
59
|
+
export declare function registerPick(program: Command): void;
|