@creativeintelligence/abbie 0.1.6 → 0.1.7
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/bin/dev.js +1 -49
- package/bin/run.js +42 -49
- package/dist/cli/commands/project/add.d.ts +0 -1
- package/dist/cli/commands/project/add.js +16 -52
- package/dist/cli/commands/project/list.js +13 -93
- package/dist/cli/commands/project/remove.d.ts +0 -2
- package/dist/cli/commands/project/remove.js +11 -28
- package/dist/cli/commands/session/list.js +3 -12
- package/dist/cli/commands/session/mark-done.js +1 -7
- package/dist/cli/commands/session/start.d.ts +0 -1
- package/dist/cli/commands/session/start.js +5 -7
- package/dist/lib/active-sessions.d.ts +0 -12
- package/dist/lib/active-sessions.js +6 -175
- package/dist/lib/project-path.d.ts +6 -0
- package/dist/lib/project-path.js +21 -0
- package/dist/lib.d.ts +1 -2
- package/dist/lib.js +2 -4
- package/oclif.manifest.json +2569 -6368
- package/package.json +1 -1
- package/dist/cli/commands/backlog/add.d.ts +0 -22
- package/dist/cli/commands/backlog/add.js +0 -65
- package/dist/cli/commands/backlog/claim.d.ts +0 -19
- package/dist/cli/commands/backlog/claim.js +0 -45
- package/dist/cli/commands/backlog/complete.d.ts +0 -18
- package/dist/cli/commands/backlog/complete.js +0 -42
- package/dist/cli/commands/backlog/list.d.ts +0 -20
- package/dist/cli/commands/backlog/list.js +0 -91
- package/dist/cli/commands/backlog/pick.d.ts +0 -18
- package/dist/cli/commands/backlog/pick.js +0 -42
- package/dist/cli/commands/backlog/sync.d.ts +0 -24
- package/dist/cli/commands/backlog/sync.js +0 -109
- package/dist/cli/commands/daemon.d.ts +0 -56
- package/dist/cli/commands/daemon.js +0 -1465
- package/dist/cli/commands/docs/lint.d.ts +0 -18
- package/dist/cli/commands/docs/lint.js +0 -82
- package/dist/cli/commands/docs/sync.d.ts +0 -19
- package/dist/cli/commands/docs/sync.js +0 -76
- package/dist/cli/commands/gc.d.ts +0 -29
- package/dist/cli/commands/gc.js +0 -211
- package/dist/cli/commands/index.d.ts +0 -36
- package/dist/cli/commands/index.js +0 -228
- package/dist/cli/commands/panes/broker.d.ts +0 -17
- package/dist/cli/commands/panes/broker.js +0 -57
- package/dist/cli/commands/panes/pipe-sink.d.ts +0 -17
- package/dist/cli/commands/panes/pipe-sink.js +0 -90
- package/dist/cli/commands/panes/snapshot.d.ts +0 -20
- package/dist/cli/commands/panes/snapshot.js +0 -125
- package/dist/cli/commands/preview/init.d.ts +0 -25
- package/dist/cli/commands/preview/init.js +0 -159
- package/dist/cli/commands/preview/sync.d.ts +0 -23
- package/dist/cli/commands/preview/sync.js +0 -144
- package/dist/cli/commands/preview/watch.d.ts +0 -24
- package/dist/cli/commands/preview/watch.js +0 -153
- package/dist/cli/commands/resource/acquire.d.ts +0 -21
- package/dist/cli/commands/resource/acquire.js +0 -90
- package/dist/cli/commands/resource/list.d.ts +0 -15
- package/dist/cli/commands/resource/list.js +0 -61
- package/dist/cli/commands/resource/release.d.ts +0 -18
- package/dist/cli/commands/resource/release.js +0 -50
- package/dist/cli/commands/resource/wait.d.ts +0 -21
- package/dist/cli/commands/resource/wait.js +0 -73
- package/dist/cli/commands/session/view.d.ts +0 -24
- package/dist/cli/commands/session/view.js +0 -145
- package/dist/cli/commands/start.d.ts +0 -37
- package/dist/cli/commands/start.js +0 -234
- package/dist/cli/commands/triage/claim.d.ts +0 -23
- package/dist/cli/commands/triage/claim.js +0 -186
- package/dist/cli/commands/triage/list.d.ts +0 -22
- package/dist/cli/commands/triage/list.js +0 -112
- package/dist/cli/commands/triage/next.d.ts +0 -18
- package/dist/cli/commands/triage/next.js +0 -63
- package/dist/cli/commands/triage/pull.d.ts +0 -19
- package/dist/cli/commands/triage/pull.js +0 -82
- package/dist/cli/commands/triage/stats.d.ts +0 -16
- package/dist/cli/commands/triage/stats.js +0 -69
- package/dist/cli/commands/tunnel/list.d.ts +0 -16
- package/dist/cli/commands/tunnel/list.js +0 -98
- package/dist/cli/commands/tunnel/start.d.ts +0 -24
- package/dist/cli/commands/tunnel/start.js +0 -107
- package/dist/cli/commands/tunnel/stop.d.ts +0 -20
- package/dist/cli/commands/tunnel/stop.js +0 -90
- package/dist/cli/commands/tunnel/url.d.ts +0 -21
- package/dist/cli/commands/tunnel/url.js +0 -70
- package/dist/cli/commands/windows/context.d.ts +0 -18
- package/dist/cli/commands/windows/context.js +0 -326
- package/dist/cli/commands/windows/focus.d.ts +0 -17
- package/dist/cli/commands/windows/focus.js +0 -103
- package/dist/cli/commands/windows/list.d.ts +0 -21
- package/dist/cli/commands/windows/list.js +0 -172
- package/dist/cli/commands/windows/map.d.ts +0 -17
- package/dist/cli/commands/windows/map.js +0 -168
- package/dist/cli/commands/windows/read.d.ts +0 -21
- package/dist/cli/commands/windows/read.js +0 -241
- package/dist/cli/commands/windows/search.d.ts +0 -24
- package/dist/cli/commands/windows/search.js +0 -171
- package/dist/cli/commands/windows/show.d.ts +0 -19
- package/dist/cli/commands/windows/show.js +0 -165
- package/dist/cli/commands/windows/watch.d.ts +0 -19
- package/dist/cli/commands/windows/watch.js +0 -241
- package/dist/lib/managed-session.d.ts +0 -27
- package/dist/lib/managed-session.js +0 -105
- package/dist/lib/panes/broker.d.ts +0 -130
- package/dist/lib/panes/broker.js +0 -97
- package/dist/lib/panes/index.d.ts +0 -2
- package/dist/lib/panes/index.js +0 -1
- package/dist/lib/panes/server.d.ts +0 -17
- package/dist/lib/panes/server.js +0 -308
- package/dist/lib/preview/manager.d.ts +0 -77
- package/dist/lib/preview/manager.js +0 -369
- package/dist/lib/preview/schema.d.ts +0 -2
- package/dist/lib/preview/schema.js +0 -32
- package/dist/lib/preview/sprite.d.ts +0 -85
- package/dist/lib/preview/sprite.js +0 -321
- package/dist/lib/preview/watcher.d.ts +0 -63
- package/dist/lib/preview/watcher.js +0 -185
- package/dist/lib/project-identity.d.ts +0 -16
- package/dist/lib/project-identity.js +0 -75
- package/dist/lib/tmux/bridge.d.ts +0 -133
- package/dist/lib/tmux/bridge.js +0 -315
- package/dist/lib/tmux/context.d.ts +0 -82
- package/dist/lib/tmux/context.js +0 -239
- package/dist/lib/tmux/index.d.ts +0 -8
- package/dist/lib/tmux/index.js +0 -11
- package/dist/lib/tmux/map.d.ts +0 -57
- package/dist/lib/tmux/map.js +0 -198
- package/dist/lib/tmux/panes.d.ts +0 -27
- package/dist/lib/tmux/panes.js +0 -151
- package/dist/lib/tmux/redaction.d.ts +0 -57
- package/dist/lib/tmux/redaction.js +0 -152
- package/dist/lib/web/analytics.d.ts +0 -63
- package/dist/lib/web/analytics.js +0 -168
- package/dist/lib/web/server.d.ts +0 -26
- package/dist/lib/web/server.js +0 -697
- package/dist/lib/web/tmux-bridge.d.ts +0 -7
- package/dist/lib/web/tmux-bridge.js +0 -7
- package/dist/lib/windows/index.d.ts +0 -3
- package/dist/lib/windows/index.js +0 -2
- package/dist/lib/windows/inventory.d.ts +0 -21
- package/dist/lib/windows/inventory.js +0 -263
- package/dist/lib/windows/types.d.ts +0 -46
- package/dist/lib/windows/types.js +0 -1
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { Flags } from "@oclif/core";
|
|
2
|
-
import { getActiveSessionManager } from "../../../lib/active-sessions.js";
|
|
3
|
-
import { isRunning } from "../../../lib/tmux/index.js";
|
|
4
|
-
import * as windows from "../../../lib/windows/index.js";
|
|
5
|
-
import { BaseCommand } from "../../base-command.js";
|
|
6
|
-
function abbreviateHome(path) {
|
|
7
|
-
const home = process.env.HOME;
|
|
8
|
-
if (!home)
|
|
9
|
-
return path;
|
|
10
|
-
if (path === home)
|
|
11
|
-
return "~";
|
|
12
|
-
if (path.startsWith(`${home}/`))
|
|
13
|
-
return `~/${path.slice(home.length + 1)}`;
|
|
14
|
-
return path;
|
|
15
|
-
}
|
|
16
|
-
function paneRef(window) {
|
|
17
|
-
return `${window.session}:${window.window}.${window.pane}`;
|
|
18
|
-
}
|
|
19
|
-
function pad(value, width) {
|
|
20
|
-
if (value.length >= width)
|
|
21
|
-
return value;
|
|
22
|
-
return value + " ".repeat(width - value.length);
|
|
23
|
-
}
|
|
24
|
-
export default class WindowsMapCommand extends BaseCommand {
|
|
25
|
-
static summary = "Map agent sessions to windows";
|
|
26
|
-
static hidden = false;
|
|
27
|
-
static examples = [
|
|
28
|
-
"$ abbie windows map",
|
|
29
|
-
"$ abbie windows map --orphans",
|
|
30
|
-
"$ abbie windows map --unmapped",
|
|
31
|
-
"$ abbie windows map --json",
|
|
32
|
-
];
|
|
33
|
-
static flags = {
|
|
34
|
-
...BaseCommand.baseFlags,
|
|
35
|
-
orphans: Flags.boolean({
|
|
36
|
-
description: "Show orphan agents (no associated window)",
|
|
37
|
-
default: false,
|
|
38
|
-
}),
|
|
39
|
-
unmapped: Flags.boolean({
|
|
40
|
-
description: "Show windows without agents",
|
|
41
|
-
default: false,
|
|
42
|
-
}),
|
|
43
|
-
};
|
|
44
|
-
async execute() {
|
|
45
|
-
const { flags } = await this.parse(WindowsMapCommand);
|
|
46
|
-
this.parsedFlags = flags;
|
|
47
|
-
const tmuxRunning = await isRunning();
|
|
48
|
-
if (!tmuxRunning) {
|
|
49
|
-
const result = {
|
|
50
|
-
tmuxRunning: false,
|
|
51
|
-
mappings: [],
|
|
52
|
-
unmappedWindows: [],
|
|
53
|
-
orphanAgents: [],
|
|
54
|
-
};
|
|
55
|
-
if (!this.jsonEnabled?.()) {
|
|
56
|
-
this.log("tmux is not running");
|
|
57
|
-
}
|
|
58
|
-
return result;
|
|
59
|
-
}
|
|
60
|
-
const manager = getActiveSessionManager();
|
|
61
|
-
const activeSessions = await manager.listAsync({ status: "running" });
|
|
62
|
-
const states = await windows.inventory({
|
|
63
|
-
includeNvim: false,
|
|
64
|
-
includeAgent: true,
|
|
65
|
-
includeBuffers: false,
|
|
66
|
-
});
|
|
67
|
-
const bySessionId = new Map();
|
|
68
|
-
const byPid = new Map();
|
|
69
|
-
for (const state of states) {
|
|
70
|
-
if (state.agent?.sessionId) {
|
|
71
|
-
bySessionId.set(state.agent.sessionId, state);
|
|
72
|
-
}
|
|
73
|
-
if (state.agent?.pid) {
|
|
74
|
-
byPid.set(state.agent.pid, state);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const mappings = [];
|
|
78
|
-
for (const session of activeSessions) {
|
|
79
|
-
let matched;
|
|
80
|
-
let match = "none";
|
|
81
|
-
if (bySessionId.has(session.session_id)) {
|
|
82
|
-
matched = bySessionId.get(session.session_id);
|
|
83
|
-
match = "session-id";
|
|
84
|
-
}
|
|
85
|
-
else if (typeof session.agent_pid === "number" && byPid.has(session.agent_pid)) {
|
|
86
|
-
matched = byPid.get(session.agent_pid);
|
|
87
|
-
match = "pid";
|
|
88
|
-
}
|
|
89
|
-
mappings.push({
|
|
90
|
-
session: session.session_id,
|
|
91
|
-
agent: session.agent,
|
|
92
|
-
status: session.status,
|
|
93
|
-
window: matched ? paneRef(matched.window) : null,
|
|
94
|
-
paneId: matched?.window.paneId || null,
|
|
95
|
-
cmd: matched?.window.title || null,
|
|
96
|
-
cwd: matched ? abbreviateHome(matched.window.cwd) : session.cwd,
|
|
97
|
-
match,
|
|
98
|
-
pid: session.agent_pid ?? null,
|
|
99
|
-
issue: session.issue,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
const unmappedWindows = states
|
|
103
|
-
.filter((s) => !s.agent)
|
|
104
|
-
.map((s) => ({
|
|
105
|
-
paneId: s.window.paneId || paneRef(s.window),
|
|
106
|
-
ref: paneRef(s.window),
|
|
107
|
-
cmd: s.window.title,
|
|
108
|
-
cwd: abbreviateHome(s.window.cwd),
|
|
109
|
-
active: s.window.active,
|
|
110
|
-
}))
|
|
111
|
-
.sort((a, b) => a.ref.localeCompare(b.ref));
|
|
112
|
-
const orphanAgents = mappings
|
|
113
|
-
.filter((m) => m.window === null)
|
|
114
|
-
.map((m) => ({
|
|
115
|
-
session: m.session,
|
|
116
|
-
agent: m.agent,
|
|
117
|
-
status: m.status,
|
|
118
|
-
pid: m.pid,
|
|
119
|
-
cwd: m.cwd ?? "",
|
|
120
|
-
}));
|
|
121
|
-
const result = { tmuxRunning: true, mappings, unmappedWindows, orphanAgents };
|
|
122
|
-
if (!this.jsonEnabled?.()) {
|
|
123
|
-
this.printText(result, flags);
|
|
124
|
-
}
|
|
125
|
-
return result;
|
|
126
|
-
}
|
|
127
|
-
printText(result, flags) {
|
|
128
|
-
const mapped = result.mappings.filter((m) => m.window !== null);
|
|
129
|
-
if (mapped.length === 0) {
|
|
130
|
-
this.log("No agent mappings found");
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
const sessionWidth = Math.max("SESSION".length, ...mapped.map((m) => m.session.length));
|
|
134
|
-
const agentWidth = Math.max("AGENT".length, ...mapped.map((m) => m.agent.length));
|
|
135
|
-
const windowWidth = Math.max("WINDOW".length, ...mapped.map((m) => (m.window ?? "").length));
|
|
136
|
-
this.log("AGENT MAPPINGS");
|
|
137
|
-
this.log(`${pad("SESSION", sessionWidth)} ${pad("AGENT", agentWidth)} ${pad("WINDOW", windowWidth)} STATUS`);
|
|
138
|
-
for (const m of mapped) {
|
|
139
|
-
this.log(`${pad(m.session, sessionWidth)} ${pad(m.agent, agentWidth)} ${pad(m.window ?? "-", windowWidth)} ${m.status}`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (flags.unmapped) {
|
|
143
|
-
this.log("");
|
|
144
|
-
this.log("UNMAPPED WINDOWS (--unmapped)");
|
|
145
|
-
if (result.unmappedWindows.length === 0) {
|
|
146
|
-
this.log("None");
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
for (const w of result.unmappedWindows) {
|
|
150
|
-
this.log(`${w.paneId} ${w.ref} ${w.cmd} ${w.cwd}${w.active ? " [active]" : ""}`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (flags.orphans) {
|
|
155
|
-
this.log("");
|
|
156
|
-
this.log("ORPHAN AGENTS (--orphans)");
|
|
157
|
-
if (result.orphanAgents.length === 0) {
|
|
158
|
-
this.log("None");
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
for (const a of result.orphanAgents) {
|
|
162
|
-
const pidStr = a.pid ? `PID ${a.pid}` : "PID -";
|
|
163
|
-
this.log(`${pidStr} (${a.agent}) - no associated window (${a.session})`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class WindowsReadCommand extends BaseCommand {
|
|
3
|
-
static summary: string;
|
|
4
|
-
static hidden: boolean;
|
|
5
|
-
static examples: string[];
|
|
6
|
-
static args: {
|
|
7
|
-
ref: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
-
};
|
|
9
|
-
static flags: {
|
|
10
|
-
scope: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
lines: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
redact: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
-
"json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
-
ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
-
};
|
|
18
|
-
execute(): Promise<unknown>;
|
|
19
|
-
private printText;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=read.d.ts.map
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import { Args, Flags } from "@oclif/core";
|
|
2
|
-
import { getBufferLines, getCurrentBufferInfo, getVisibleRange } from "../../../lib/nvim/remote.js";
|
|
3
|
-
import { isRunning } from "../../../lib/tmux/index.js";
|
|
4
|
-
import { redactLine } from "../../../lib/tmux/redaction.js";
|
|
5
|
-
import * as windows from "../../../lib/windows/index.js";
|
|
6
|
-
import { BaseCommand } from "../../base-command.js";
|
|
7
|
-
function abbreviateHome(path) {
|
|
8
|
-
const home = process.env.HOME;
|
|
9
|
-
if (!home)
|
|
10
|
-
return path;
|
|
11
|
-
if (path === home)
|
|
12
|
-
return "~";
|
|
13
|
-
if (path.startsWith(`${home}/`))
|
|
14
|
-
return `~/${path.slice(home.length + 1)}`;
|
|
15
|
-
return path;
|
|
16
|
-
}
|
|
17
|
-
function paneRef(window) {
|
|
18
|
-
return `${window.session}:${window.window}.${window.pane}`;
|
|
19
|
-
}
|
|
20
|
-
function formatPathForDisplay(path, cwd) {
|
|
21
|
-
if (!path)
|
|
22
|
-
return path;
|
|
23
|
-
const normalizedCwd = cwd.endsWith("/") ? cwd : `${cwd}/`;
|
|
24
|
-
if (path.startsWith(normalizedCwd)) {
|
|
25
|
-
return path.slice(normalizedCwd.length);
|
|
26
|
-
}
|
|
27
|
-
return abbreviateHome(path);
|
|
28
|
-
}
|
|
29
|
-
export default class WindowsReadCommand extends BaseCommand {
|
|
30
|
-
static summary = "Read nvim buffer content for a window";
|
|
31
|
-
static hidden = false;
|
|
32
|
-
static examples = [
|
|
33
|
-
"$ abbie windows read",
|
|
34
|
-
"$ abbie windows read %3",
|
|
35
|
-
"$ abbie windows read --scope visible",
|
|
36
|
-
"$ abbie windows read --scope cursor",
|
|
37
|
-
"$ abbie windows read --scope all",
|
|
38
|
-
"$ abbie windows read --lines 50",
|
|
39
|
-
"$ abbie windows read --no-redact",
|
|
40
|
-
"$ abbie windows read --json",
|
|
41
|
-
];
|
|
42
|
-
static args = {
|
|
43
|
-
ref: Args.string({
|
|
44
|
-
description: "Pane ID (e.g. %3) or session:window.pane (e.g. work:0.0)",
|
|
45
|
-
required: false,
|
|
46
|
-
}),
|
|
47
|
-
};
|
|
48
|
-
static flags = {
|
|
49
|
-
...BaseCommand.baseFlags,
|
|
50
|
-
scope: Flags.string({
|
|
51
|
-
description: "Read scope",
|
|
52
|
-
options: ["visible", "cursor", "all"],
|
|
53
|
-
default: "visible",
|
|
54
|
-
}),
|
|
55
|
-
lines: Flags.integer({
|
|
56
|
-
description: "Maximum lines to read",
|
|
57
|
-
default: 50,
|
|
58
|
-
}),
|
|
59
|
-
redact: Flags.boolean({
|
|
60
|
-
description: "Enable redaction",
|
|
61
|
-
default: true,
|
|
62
|
-
allowNo: true,
|
|
63
|
-
}),
|
|
64
|
-
};
|
|
65
|
-
async execute() {
|
|
66
|
-
const { args, flags } = await this.parse(WindowsReadCommand);
|
|
67
|
-
this.parsedFlags = flags;
|
|
68
|
-
const scope = flags.scope;
|
|
69
|
-
const maxLines = Math.max(1, flags.lines);
|
|
70
|
-
const tmuxRunning = await isRunning();
|
|
71
|
-
if (!tmuxRunning) {
|
|
72
|
-
const result = {
|
|
73
|
-
tmuxRunning: false,
|
|
74
|
-
window: null,
|
|
75
|
-
ref: null,
|
|
76
|
-
scope,
|
|
77
|
-
startLine: null,
|
|
78
|
-
endLine: null,
|
|
79
|
-
buffer: null,
|
|
80
|
-
lines: [],
|
|
81
|
-
redacted: flags.redact,
|
|
82
|
-
wasRedacted: false,
|
|
83
|
-
};
|
|
84
|
-
if (!this.jsonEnabled?.()) {
|
|
85
|
-
this.log("tmux is not running");
|
|
86
|
-
}
|
|
87
|
-
return result;
|
|
88
|
-
}
|
|
89
|
-
const state = args.ref
|
|
90
|
-
? await windows.getWindowState(args.ref, {
|
|
91
|
-
includeNvim: true,
|
|
92
|
-
includeAgent: false,
|
|
93
|
-
includeBuffers: false,
|
|
94
|
-
})
|
|
95
|
-
: await windows.getFocusedWindow({
|
|
96
|
-
includeNvim: true,
|
|
97
|
-
includeAgent: false,
|
|
98
|
-
includeBuffers: false,
|
|
99
|
-
});
|
|
100
|
-
if (!state) {
|
|
101
|
-
const result = {
|
|
102
|
-
tmuxRunning: true,
|
|
103
|
-
window: null,
|
|
104
|
-
ref: null,
|
|
105
|
-
scope,
|
|
106
|
-
startLine: null,
|
|
107
|
-
endLine: null,
|
|
108
|
-
buffer: null,
|
|
109
|
-
lines: [],
|
|
110
|
-
redacted: flags.redact,
|
|
111
|
-
wasRedacted: false,
|
|
112
|
-
};
|
|
113
|
-
if (!this.jsonEnabled?.()) {
|
|
114
|
-
this.log("Window not found");
|
|
115
|
-
}
|
|
116
|
-
return result;
|
|
117
|
-
}
|
|
118
|
-
const nvimState = state.nvim;
|
|
119
|
-
if (!nvimState?.available || !nvimState.serverAddr) {
|
|
120
|
-
const result = {
|
|
121
|
-
tmuxRunning: true,
|
|
122
|
-
window: state.window,
|
|
123
|
-
ref: paneRef(state.window),
|
|
124
|
-
scope,
|
|
125
|
-
startLine: null,
|
|
126
|
-
endLine: null,
|
|
127
|
-
buffer: null,
|
|
128
|
-
lines: [],
|
|
129
|
-
redacted: flags.redact,
|
|
130
|
-
wasRedacted: false,
|
|
131
|
-
};
|
|
132
|
-
if (!this.jsonEnabled?.()) {
|
|
133
|
-
this.log("nvim is not available for this window");
|
|
134
|
-
}
|
|
135
|
-
return result;
|
|
136
|
-
}
|
|
137
|
-
const serverAddr = nvimState.serverAddr;
|
|
138
|
-
const bufferInfo = await getCurrentBufferInfo(serverAddr);
|
|
139
|
-
if (!bufferInfo) {
|
|
140
|
-
const result = {
|
|
141
|
-
tmuxRunning: true,
|
|
142
|
-
window: state.window,
|
|
143
|
-
ref: paneRef(state.window),
|
|
144
|
-
scope,
|
|
145
|
-
startLine: null,
|
|
146
|
-
endLine: null,
|
|
147
|
-
buffer: null,
|
|
148
|
-
lines: [],
|
|
149
|
-
redacted: flags.redact,
|
|
150
|
-
wasRedacted: false,
|
|
151
|
-
};
|
|
152
|
-
if (!this.jsonEnabled?.()) {
|
|
153
|
-
this.log("Unable to query nvim current buffer");
|
|
154
|
-
}
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
let startLine = 1;
|
|
158
|
-
let endLine = 1;
|
|
159
|
-
let cursor = bufferInfo.cursor ?? { line: 1, col: 1 };
|
|
160
|
-
if (scope === "visible") {
|
|
161
|
-
const range = await getVisibleRange(serverAddr, bufferInfo.bufnr);
|
|
162
|
-
if (range) {
|
|
163
|
-
startLine = range.topLine;
|
|
164
|
-
endLine = Math.min(range.bottomLine, range.topLine + maxLines - 1);
|
|
165
|
-
cursor = range.cursor;
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
endLine = startLine + maxLines - 1;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
else if (scope === "cursor") {
|
|
172
|
-
const desiredHalf = Math.min(20, Math.floor((maxLines - 1) / 2));
|
|
173
|
-
startLine = Math.max(1, cursor.line - desiredHalf);
|
|
174
|
-
endLine = startLine + Math.min(maxLines, desiredHalf * 2 + 1) - 1;
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
startLine = 1;
|
|
178
|
-
endLine = startLine + maxLines - 1;
|
|
179
|
-
}
|
|
180
|
-
const rawLines = await getBufferLines(serverAddr, bufferInfo.bufnr, startLine, endLine);
|
|
181
|
-
if (!rawLines) {
|
|
182
|
-
const result = {
|
|
183
|
-
tmuxRunning: true,
|
|
184
|
-
window: state.window,
|
|
185
|
-
ref: paneRef(state.window),
|
|
186
|
-
scope,
|
|
187
|
-
startLine,
|
|
188
|
-
endLine,
|
|
189
|
-
buffer: bufferInfo,
|
|
190
|
-
lines: [],
|
|
191
|
-
redacted: flags.redact,
|
|
192
|
-
wasRedacted: false,
|
|
193
|
-
};
|
|
194
|
-
if (!this.jsonEnabled?.()) {
|
|
195
|
-
this.log("Unable to read buffer content");
|
|
196
|
-
}
|
|
197
|
-
return result;
|
|
198
|
-
}
|
|
199
|
-
let wasRedacted = false;
|
|
200
|
-
const renderedLines = rawLines.map((line) => {
|
|
201
|
-
if (!flags.redact)
|
|
202
|
-
return line;
|
|
203
|
-
const redacted = redactLine(line);
|
|
204
|
-
if (redacted !== line)
|
|
205
|
-
wasRedacted = true;
|
|
206
|
-
return redacted;
|
|
207
|
-
});
|
|
208
|
-
const result = {
|
|
209
|
-
tmuxRunning: true,
|
|
210
|
-
window: state.window,
|
|
211
|
-
ref: paneRef(state.window),
|
|
212
|
-
scope,
|
|
213
|
-
startLine,
|
|
214
|
-
endLine,
|
|
215
|
-
buffer: { ...bufferInfo, cursor },
|
|
216
|
-
lines: renderedLines,
|
|
217
|
-
redacted: flags.redact,
|
|
218
|
-
wasRedacted,
|
|
219
|
-
};
|
|
220
|
-
if (!this.jsonEnabled?.()) {
|
|
221
|
-
this.printText(result);
|
|
222
|
-
}
|
|
223
|
-
return result;
|
|
224
|
-
}
|
|
225
|
-
printText(result) {
|
|
226
|
-
if (!result.window || !result.buffer || result.startLine === null || result.endLine === null) {
|
|
227
|
-
this.log("No buffer content available");
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
const displayPath = formatPathForDisplay(result.buffer.name, result.window.cwd);
|
|
231
|
-
this.log(`BUFFER ${displayPath} (${result.buffer.filetype || "unknown"})`);
|
|
232
|
-
this.log(`Window: ${result.window.paneId || "-"} (${result.ref})`);
|
|
233
|
-
this.log(`Scope: ${result.scope} (lines ${result.startLine}-${result.endLine})`);
|
|
234
|
-
this.log("");
|
|
235
|
-
const width = String(result.endLine).length;
|
|
236
|
-
for (let i = 0; i < result.lines.length; i++) {
|
|
237
|
-
const lineNo = result.startLine + i;
|
|
238
|
-
this.log(` ${String(lineNo).padStart(width)} │ ${result.lines[i]}`);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class WindowsSearchCommand extends BaseCommand {
|
|
3
|
-
static summary: string;
|
|
4
|
-
static hidden: boolean;
|
|
5
|
-
static description: string;
|
|
6
|
-
static examples: string[];
|
|
7
|
-
static args: {
|
|
8
|
-
query: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
9
|
-
};
|
|
10
|
-
static flags: {
|
|
11
|
-
session: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
context: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
lines: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
redact: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
-
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
-
format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
-
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
-
"json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
-
ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
|
-
};
|
|
21
|
-
execute(): Promise<unknown>;
|
|
22
|
-
private printText;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=search.d.ts.map
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { Args, Flags } from "@oclif/core";
|
|
2
|
-
import { capturePane } from "../../../lib/tmux/bridge.js";
|
|
3
|
-
import { isRunning } from "../../../lib/tmux/index.js";
|
|
4
|
-
import { redactLine } from "../../../lib/tmux/redaction.js";
|
|
5
|
-
import * as windows from "../../../lib/windows/index.js";
|
|
6
|
-
import { BaseCommand } from "../../base-command.js";
|
|
7
|
-
function abbreviateHome(path) {
|
|
8
|
-
const home = process.env.HOME;
|
|
9
|
-
if (!home)
|
|
10
|
-
return path;
|
|
11
|
-
if (path === home)
|
|
12
|
-
return "~";
|
|
13
|
-
if (path.startsWith(`${home}/`))
|
|
14
|
-
return `~/${path.slice(home.length + 1)}`;
|
|
15
|
-
return path;
|
|
16
|
-
}
|
|
17
|
-
function paneRef(window) {
|
|
18
|
-
return `${window.session}:${window.window}.${window.pane}`;
|
|
19
|
-
}
|
|
20
|
-
export default class WindowsSearchCommand extends BaseCommand {
|
|
21
|
-
static summary = "Search scrollback content across all tmux panes";
|
|
22
|
-
static hidden = false;
|
|
23
|
-
static description = "Searches terminal scrollback across all tmux panes for a pattern. " +
|
|
24
|
-
"Uses tmux capture-pane to read scrollback history (up to 10,000 lines per pane).";
|
|
25
|
-
static examples = [
|
|
26
|
-
'$ abbie windows search "spatial"',
|
|
27
|
-
'$ abbie windows search "TODO" --context 3',
|
|
28
|
-
'$ abbie windows search "error" --session 2 --lines 5000',
|
|
29
|
-
'$ abbie windows search "ARBOR-123" --json',
|
|
30
|
-
];
|
|
31
|
-
static args = {
|
|
32
|
-
query: Args.string({
|
|
33
|
-
description: "Search pattern (case-insensitive regex)",
|
|
34
|
-
required: true,
|
|
35
|
-
}),
|
|
36
|
-
};
|
|
37
|
-
static flags = {
|
|
38
|
-
...BaseCommand.baseFlags,
|
|
39
|
-
session: Flags.string({
|
|
40
|
-
char: "s",
|
|
41
|
-
description: "Filter to specific tmux session",
|
|
42
|
-
}),
|
|
43
|
-
context: Flags.integer({
|
|
44
|
-
char: "C",
|
|
45
|
-
description: "Lines of context around each match",
|
|
46
|
-
default: 1,
|
|
47
|
-
}),
|
|
48
|
-
lines: Flags.integer({
|
|
49
|
-
char: "n",
|
|
50
|
-
description: "Maximum scrollback lines to search per pane",
|
|
51
|
-
default: 10000,
|
|
52
|
-
}),
|
|
53
|
-
redact: Flags.boolean({
|
|
54
|
-
description: "Enable redaction of sensitive content",
|
|
55
|
-
default: true,
|
|
56
|
-
allowNo: true,
|
|
57
|
-
}),
|
|
58
|
-
limit: Flags.integer({
|
|
59
|
-
char: "l",
|
|
60
|
-
description: "Maximum matches per pane",
|
|
61
|
-
default: 20,
|
|
62
|
-
}),
|
|
63
|
-
};
|
|
64
|
-
async execute() {
|
|
65
|
-
const { args, flags } = await this.parse(WindowsSearchCommand);
|
|
66
|
-
this.parsedFlags = flags;
|
|
67
|
-
const query = args.query;
|
|
68
|
-
const contextLines = Math.max(0, flags.context);
|
|
69
|
-
const maxLines = Math.max(100, flags.lines);
|
|
70
|
-
const maxMatchesPerPane = Math.max(1, flags.limit);
|
|
71
|
-
const tmuxRunning = await isRunning();
|
|
72
|
-
if (!tmuxRunning) {
|
|
73
|
-
const result = { tmuxRunning: false, query, totalMatches: 0, windows: [] };
|
|
74
|
-
if (!this.jsonEnabled?.()) {
|
|
75
|
-
this.log("tmux is not running");
|
|
76
|
-
}
|
|
77
|
-
return result;
|
|
78
|
-
}
|
|
79
|
-
// Get all panes
|
|
80
|
-
const states = await windows.inventory({
|
|
81
|
-
session: flags.session,
|
|
82
|
-
includeNvim: false,
|
|
83
|
-
includeAgent: false,
|
|
84
|
-
includeBuffers: false,
|
|
85
|
-
});
|
|
86
|
-
let pattern;
|
|
87
|
-
try {
|
|
88
|
-
pattern = new RegExp(query, "i");
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
this.error(`Invalid regex pattern: ${query}`);
|
|
92
|
-
}
|
|
93
|
-
const windowMatches = [];
|
|
94
|
-
let totalMatches = 0;
|
|
95
|
-
// Search each pane's scrollback
|
|
96
|
-
for (const state of states) {
|
|
97
|
-
const w = state.window;
|
|
98
|
-
const ref = paneRef(w);
|
|
99
|
-
// Capture scrollback via tmux (works for all panes, nvim or not)
|
|
100
|
-
const content = await capturePane(w.window, w.pane, {
|
|
101
|
-
lines: maxLines,
|
|
102
|
-
session: w.session,
|
|
103
|
-
});
|
|
104
|
-
if (!content)
|
|
105
|
-
continue;
|
|
106
|
-
const lines = content.split("\n");
|
|
107
|
-
const matches = [];
|
|
108
|
-
for (let i = 0; i < lines.length; i++) {
|
|
109
|
-
if (matches.length >= maxMatchesPerPane)
|
|
110
|
-
break;
|
|
111
|
-
const line = lines[i];
|
|
112
|
-
if (!pattern.test(line))
|
|
113
|
-
continue;
|
|
114
|
-
const displayLine = flags.redact ? redactLine(line) : line;
|
|
115
|
-
// Gather context lines
|
|
116
|
-
const ctx = [];
|
|
117
|
-
if (contextLines > 0) {
|
|
118
|
-
const start = Math.max(0, i - contextLines);
|
|
119
|
-
const end = Math.min(lines.length - 1, i + contextLines);
|
|
120
|
-
for (let j = start; j <= end; j++) {
|
|
121
|
-
if (j === i)
|
|
122
|
-
continue;
|
|
123
|
-
const ctxLine = flags.redact ? redactLine(lines[j]) : lines[j];
|
|
124
|
-
ctx.push(ctxLine);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
matches.push({
|
|
128
|
-
lineNo: i + 1,
|
|
129
|
-
line: displayLine,
|
|
130
|
-
context: ctx.length > 0 ? ctx : undefined,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
if (matches.length > 0) {
|
|
134
|
-
totalMatches += matches.length;
|
|
135
|
-
windowMatches.push({
|
|
136
|
-
paneId: w.paneId || ref,
|
|
137
|
-
ref,
|
|
138
|
-
session: w.session,
|
|
139
|
-
windowName: w.windowName,
|
|
140
|
-
cwd: abbreviateHome(w.cwd),
|
|
141
|
-
matches,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
const result = {
|
|
146
|
-
tmuxRunning: true,
|
|
147
|
-
query,
|
|
148
|
-
totalMatches,
|
|
149
|
-
windows: windowMatches,
|
|
150
|
-
};
|
|
151
|
-
if (!this.jsonEnabled?.()) {
|
|
152
|
-
this.printText(result);
|
|
153
|
-
}
|
|
154
|
-
return result;
|
|
155
|
-
}
|
|
156
|
-
printText(result) {
|
|
157
|
-
if (result.totalMatches === 0) {
|
|
158
|
-
this.log(`No matches for "${result.query}"`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
this.log(`${result.totalMatches} match${result.totalMatches === 1 ? "" : "es"} across ${result.windows.length} window${result.windows.length === 1 ? "" : "s"}`);
|
|
162
|
-
this.log("");
|
|
163
|
-
for (const w of result.windows) {
|
|
164
|
-
this.log(`── ${w.paneId} (${w.windowName}) ${w.cwd} ──`);
|
|
165
|
-
for (const m of w.matches) {
|
|
166
|
-
this.log(` ${String(m.lineNo).padStart(6)} │ ${m.line}`);
|
|
167
|
-
}
|
|
168
|
-
this.log("");
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class WindowsShowCommand extends BaseCommand {
|
|
3
|
-
static summary: string;
|
|
4
|
-
static hidden: boolean;
|
|
5
|
-
static examples: string[];
|
|
6
|
-
static args: {
|
|
7
|
-
ref: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
-
};
|
|
9
|
-
static flags: {
|
|
10
|
-
"with-buffers": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
"json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
-
ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
-
};
|
|
16
|
-
execute(): Promise<unknown>;
|
|
17
|
-
private printText;
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=show.d.ts.map
|