@creativeintelligence/abbie 0.1.5 → 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/login.js +26 -0
- 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,326 +0,0 @@
|
|
|
1
|
-
import { Flags } from "@oclif/core";
|
|
2
|
-
import { getBufferLines, getCurrentBufferInfo, getVisibleRange } from "../../../lib/nvim/remote.js";
|
|
3
|
-
import { isRunning } from "../../../lib/tmux/index.js";
|
|
4
|
-
import { redactContent } 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
|
-
function escapeXml(str) {
|
|
30
|
-
return str
|
|
31
|
-
.replace(/&/g, "&")
|
|
32
|
-
.replace(/</g, "<")
|
|
33
|
-
.replace(/>/g, ">")
|
|
34
|
-
.replace(/"/g, """)
|
|
35
|
-
.replace(/'/g, "'");
|
|
36
|
-
}
|
|
37
|
-
function truncateToBytes(str, maxBytes) {
|
|
38
|
-
const buf = Buffer.from(str, "utf-8");
|
|
39
|
-
if (buf.length <= maxBytes) {
|
|
40
|
-
return str;
|
|
41
|
-
}
|
|
42
|
-
let low = 0;
|
|
43
|
-
let high = str.length;
|
|
44
|
-
while (low < high) {
|
|
45
|
-
const mid = Math.ceil((low + high) / 2);
|
|
46
|
-
const slice = str.slice(0, mid);
|
|
47
|
-
if (Buffer.byteLength(slice, "utf-8") <= maxBytes) {
|
|
48
|
-
low = mid;
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
high = mid - 1;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return str.slice(0, low);
|
|
55
|
-
}
|
|
56
|
-
function bytesForLine(line) {
|
|
57
|
-
return Buffer.byteLength(`${line}\n`, "utf-8");
|
|
58
|
-
}
|
|
59
|
-
function buildWindowXmlLines(w, maxBytes) {
|
|
60
|
-
const baseLines = [];
|
|
61
|
-
baseLines.push(` <window id="${escapeXml(w.id)}" session="${escapeXml(w.session)}" window="${w.window}" pane="${w.pane}" active="${w.active}">`);
|
|
62
|
-
baseLines.push(` <cwd>${escapeXml(w.cwd)}</cwd>`);
|
|
63
|
-
baseLines.push(` <cmd>${escapeXml(w.cmd)}</cmd>`);
|
|
64
|
-
if (w.nvim) {
|
|
65
|
-
const attrs = [
|
|
66
|
-
`available="${w.nvim.available}"`,
|
|
67
|
-
w.nvim.pid !== null ? `pid="${w.nvim.pid}"` : null,
|
|
68
|
-
w.nvim.server ? `server="${escapeXml(w.nvim.server)}"` : null,
|
|
69
|
-
w.nvim.discoveryMethod ? `discovery="${w.nvim.discoveryMethod}"` : null,
|
|
70
|
-
].filter(Boolean);
|
|
71
|
-
baseLines.push(` <nvim ${attrs.join(" ")}>`);
|
|
72
|
-
if (w.nvim.buffer) {
|
|
73
|
-
const bufAttrs = [
|
|
74
|
-
`path="${escapeXml(w.nvim.buffer.path)}"`,
|
|
75
|
-
`filetype="${escapeXml(w.nvim.buffer.filetype)}"`,
|
|
76
|
-
`modified="${w.nvim.buffer.modified}"`,
|
|
77
|
-
w.nvim.buffer.cursor ? `cursor="${escapeXml(w.nvim.buffer.cursor)}"` : null,
|
|
78
|
-
].filter(Boolean);
|
|
79
|
-
baseLines.push(` <buffer ${bufAttrs.join(" ")} />`);
|
|
80
|
-
}
|
|
81
|
-
baseLines.push(" </nvim>");
|
|
82
|
-
}
|
|
83
|
-
if (w.agent) {
|
|
84
|
-
const attrs = [
|
|
85
|
-
`type="${w.agent.type}"`,
|
|
86
|
-
`pid="${w.agent.pid}"`,
|
|
87
|
-
w.agent.sessionId ? `session="${escapeXml(w.agent.sessionId)}"` : null,
|
|
88
|
-
w.agent.issue ? `issue="${escapeXml(w.agent.issue)}"` : null,
|
|
89
|
-
].filter(Boolean);
|
|
90
|
-
baseLines.push(` <agent ${attrs.join(" ")} />`);
|
|
91
|
-
}
|
|
92
|
-
baseLines.push(" </window>");
|
|
93
|
-
const baseBytes = baseLines.reduce((sum, line) => sum + bytesForLine(line), 0);
|
|
94
|
-
if (baseBytes > maxBytes)
|
|
95
|
-
return null;
|
|
96
|
-
const excerpt = w.nvim?.excerpt;
|
|
97
|
-
if (!excerpt || excerpt.lines.length === 0) {
|
|
98
|
-
return { lines: baseLines, truncated: false };
|
|
99
|
-
}
|
|
100
|
-
const insertAt = baseLines.indexOf(" </nvim>");
|
|
101
|
-
if (insertAt === -1) {
|
|
102
|
-
return { lines: baseLines, truncated: false };
|
|
103
|
-
}
|
|
104
|
-
const excerptOpen = ` <excerpt scope="${excerpt.scope}" start_line="${excerpt.startLine}" end_line="${excerpt.endLine}" redacted="${excerpt.redacted}">`;
|
|
105
|
-
const excerptClose = " </excerpt>";
|
|
106
|
-
const skeleton = [...baseLines];
|
|
107
|
-
skeleton.splice(insertAt, 0, excerptOpen, excerptClose);
|
|
108
|
-
const skeletonBytes = skeleton.reduce((sum, line) => sum + bytesForLine(line), 0);
|
|
109
|
-
if (skeletonBytes > maxBytes) {
|
|
110
|
-
return { lines: baseLines, truncated: true };
|
|
111
|
-
}
|
|
112
|
-
const remainingForContent = maxBytes - skeletonBytes;
|
|
113
|
-
const contentLines = [];
|
|
114
|
-
let used = 0;
|
|
115
|
-
let truncated = false;
|
|
116
|
-
for (const rawLine of excerpt.lines) {
|
|
117
|
-
const escaped = escapeXml(rawLine);
|
|
118
|
-
const line = ` ${escaped}`;
|
|
119
|
-
const lineBytes = bytesForLine(line);
|
|
120
|
-
if (used + lineBytes <= remainingForContent) {
|
|
121
|
-
contentLines.push(line);
|
|
122
|
-
used += lineBytes;
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
const remaining = remainingForContent - used;
|
|
126
|
-
const indentBytes = bytesForLine(" ");
|
|
127
|
-
if (remaining > indentBytes + 8) {
|
|
128
|
-
const availableForContent = remaining - indentBytes;
|
|
129
|
-
const clipped = truncateToBytes(escaped, Math.max(0, availableForContent));
|
|
130
|
-
contentLines.push(` ${clipped}`);
|
|
131
|
-
}
|
|
132
|
-
truncated = true;
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
const finalLines = [...baseLines];
|
|
136
|
-
finalLines.splice(insertAt, 0, excerptOpen, ...contentLines, excerptClose);
|
|
137
|
-
return { lines: finalLines, truncated };
|
|
138
|
-
}
|
|
139
|
-
function toXml(context, maxBytes) {
|
|
140
|
-
const lines = [];
|
|
141
|
-
let bytes = 0;
|
|
142
|
-
let truncated = false;
|
|
143
|
-
const closeRoot = "</workspace_context>";
|
|
144
|
-
const closeRootBytes = bytesForLine(closeRoot);
|
|
145
|
-
const root = `<workspace_context generated_at="${escapeXml(context.generatedAt)}" tmux_running="${context.tmuxRunning}">`;
|
|
146
|
-
lines.push(root);
|
|
147
|
-
bytes += bytesForLine(root);
|
|
148
|
-
for (const w of context.windows) {
|
|
149
|
-
const remaining = maxBytes - bytes - closeRootBytes;
|
|
150
|
-
if (remaining <= 0) {
|
|
151
|
-
truncated = true;
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
const built = buildWindowXmlLines(w, remaining);
|
|
155
|
-
if (!built) {
|
|
156
|
-
truncated = true;
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
const windowBytes = built.lines.reduce((sum, line) => sum + bytesForLine(line), 0);
|
|
160
|
-
if (bytes + windowBytes + closeRootBytes > maxBytes) {
|
|
161
|
-
truncated = true;
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
lines.push(...built.lines);
|
|
165
|
-
bytes += windowBytes;
|
|
166
|
-
if (built.truncated) {
|
|
167
|
-
truncated = true;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
lines.push(closeRoot);
|
|
171
|
-
return { xml: lines.join("\n"), truncated };
|
|
172
|
-
}
|
|
173
|
-
export default class WindowsContextCommand extends BaseCommand {
|
|
174
|
-
static summary = "Generate workspace context from windows inventory";
|
|
175
|
-
static hidden = false;
|
|
176
|
-
static examples = [
|
|
177
|
-
"$ abbie windows context",
|
|
178
|
-
"$ abbie windows context --focus",
|
|
179
|
-
"$ abbie windows context --json",
|
|
180
|
-
"$ abbie windows context --no-with-buffers",
|
|
181
|
-
"$ abbie windows context --max-bytes 100000",
|
|
182
|
-
"$ abbie windows context --no-redact",
|
|
183
|
-
];
|
|
184
|
-
static flags = {
|
|
185
|
-
...BaseCommand.baseFlags,
|
|
186
|
-
focus: Flags.boolean({
|
|
187
|
-
description: "Only include the focused window",
|
|
188
|
-
default: false,
|
|
189
|
-
}),
|
|
190
|
-
"with-buffers": Flags.boolean({
|
|
191
|
-
description: "Include buffer excerpts (visible range)",
|
|
192
|
-
default: true,
|
|
193
|
-
allowNo: true,
|
|
194
|
-
}),
|
|
195
|
-
"max-bytes": Flags.integer({
|
|
196
|
-
description: "Maximum output size in bytes",
|
|
197
|
-
default: 200000,
|
|
198
|
-
}),
|
|
199
|
-
redact: Flags.boolean({
|
|
200
|
-
description: "Enable redaction",
|
|
201
|
-
default: true,
|
|
202
|
-
allowNo: true,
|
|
203
|
-
}),
|
|
204
|
-
};
|
|
205
|
-
async execute() {
|
|
206
|
-
const { flags } = await this.parse(WindowsContextCommand);
|
|
207
|
-
this.parsedFlags = flags;
|
|
208
|
-
const generatedAt = new Date().toISOString();
|
|
209
|
-
const tmuxRunning = await isRunning();
|
|
210
|
-
if (!tmuxRunning) {
|
|
211
|
-
const context = {
|
|
212
|
-
generatedAt,
|
|
213
|
-
tmuxRunning: false,
|
|
214
|
-
truncated: false,
|
|
215
|
-
windows: [],
|
|
216
|
-
};
|
|
217
|
-
if (this.jsonEnabled?.()) {
|
|
218
|
-
return context;
|
|
219
|
-
}
|
|
220
|
-
const xml = toXml(context, flags["max-bytes"]);
|
|
221
|
-
context.truncated = xml.truncated;
|
|
222
|
-
const output = flags.format === "json" ? JSON.stringify(context, null, 2) : xml.xml;
|
|
223
|
-
this.log(output);
|
|
224
|
-
return context;
|
|
225
|
-
}
|
|
226
|
-
let states = await windows.inventory({
|
|
227
|
-
includeNvim: true,
|
|
228
|
-
includeAgent: true,
|
|
229
|
-
includeBuffers: false,
|
|
230
|
-
});
|
|
231
|
-
// Filter to focused window if requested
|
|
232
|
-
if (flags.focus) {
|
|
233
|
-
const focused = await windows.getFocusedWindow({ includeNvim: true, includeAgent: true });
|
|
234
|
-
states = focused ? [focused] : [];
|
|
235
|
-
}
|
|
236
|
-
const sorted = states.sort((a, b) => {
|
|
237
|
-
if (a.window.session !== b.window.session)
|
|
238
|
-
return a.window.session.localeCompare(b.window.session);
|
|
239
|
-
if (a.window.window !== b.window.window)
|
|
240
|
-
return a.window.window - b.window.window;
|
|
241
|
-
return a.window.pane - b.window.pane;
|
|
242
|
-
});
|
|
243
|
-
const ctxWindows = [];
|
|
244
|
-
for (const state of sorted) {
|
|
245
|
-
const id = state.window.paneId || paneRef(state.window);
|
|
246
|
-
const ref = paneRef(state.window);
|
|
247
|
-
let buffer = null;
|
|
248
|
-
let excerpt = null;
|
|
249
|
-
if (state.nvim?.available && state.nvim.serverAddr) {
|
|
250
|
-
const info = await getCurrentBufferInfo(state.nvim.serverAddr);
|
|
251
|
-
if (info) {
|
|
252
|
-
const cursor = info.cursor ? `${info.cursor.line}:${info.cursor.col}` : null;
|
|
253
|
-
buffer = {
|
|
254
|
-
path: formatPathForDisplay(info.name, state.window.cwd),
|
|
255
|
-
filetype: info.filetype,
|
|
256
|
-
modified: info.modified,
|
|
257
|
-
cursor,
|
|
258
|
-
};
|
|
259
|
-
if (flags["with-buffers"]) {
|
|
260
|
-
const visible = await getVisibleRange(state.nvim.serverAddr, info.bufnr);
|
|
261
|
-
if (visible) {
|
|
262
|
-
const raw = await getBufferLines(state.nvim.serverAddr, info.bufnr, visible.topLine, visible.bottomLine);
|
|
263
|
-
if (raw) {
|
|
264
|
-
const joined = raw.join("\n");
|
|
265
|
-
const redaction = flags.redact
|
|
266
|
-
? redactContent(joined, "balanced")
|
|
267
|
-
: { content: joined, wasRedacted: false };
|
|
268
|
-
const lines = redaction.content.split("\n");
|
|
269
|
-
excerpt = {
|
|
270
|
-
scope: "visible",
|
|
271
|
-
startLine: visible.topLine,
|
|
272
|
-
endLine: visible.bottomLine,
|
|
273
|
-
redacted: flags.redact && redaction.wasRedacted,
|
|
274
|
-
lines,
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
ctxWindows.push({
|
|
282
|
-
id,
|
|
283
|
-
ref,
|
|
284
|
-
session: state.window.session,
|
|
285
|
-
window: state.window.window,
|
|
286
|
-
windowName: state.window.windowName,
|
|
287
|
-
pane: state.window.pane,
|
|
288
|
-
active: state.window.active,
|
|
289
|
-
cwd: abbreviateHome(state.window.cwd),
|
|
290
|
-
cmd: state.window.title,
|
|
291
|
-
nvim: state.nvim
|
|
292
|
-
? {
|
|
293
|
-
available: state.nvim.available,
|
|
294
|
-
pid: state.nvim.pid,
|
|
295
|
-
server: state.nvim.serverAddr,
|
|
296
|
-
discoveryMethod: state.nvim.discoveryMethod,
|
|
297
|
-
buffer,
|
|
298
|
-
excerpt,
|
|
299
|
-
}
|
|
300
|
-
: null,
|
|
301
|
-
agent: state.agent
|
|
302
|
-
? {
|
|
303
|
-
type: state.agent.type,
|
|
304
|
-
pid: state.agent.pid,
|
|
305
|
-
sessionId: state.agent.sessionId,
|
|
306
|
-
issue: state.agent.issue,
|
|
307
|
-
}
|
|
308
|
-
: null,
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
const context = {
|
|
312
|
-
generatedAt,
|
|
313
|
-
tmuxRunning: true,
|
|
314
|
-
truncated: false,
|
|
315
|
-
windows: ctxWindows,
|
|
316
|
-
};
|
|
317
|
-
if (this.jsonEnabled?.()) {
|
|
318
|
-
return context;
|
|
319
|
-
}
|
|
320
|
-
const xml = toXml(context, flags["max-bytes"]);
|
|
321
|
-
context.truncated = xml.truncated;
|
|
322
|
-
const output = flags.format === "json" ? JSON.stringify(context, null, 2) : xml.xml;
|
|
323
|
-
this.log(output);
|
|
324
|
-
return context;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class WindowsFocusCommand extends BaseCommand {
|
|
3
|
-
static summary: string;
|
|
4
|
-
static hidden: boolean;
|
|
5
|
-
static examples: string[];
|
|
6
|
-
static flags: {
|
|
7
|
-
"with-nvim": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
"with-buffers": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
-
format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
"json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
-
ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
};
|
|
14
|
-
execute(): Promise<unknown>;
|
|
15
|
-
private printText;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=focus.d.ts.map
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { Flags } from "@oclif/core";
|
|
2
|
-
import { isRunning } from "../../../lib/tmux/index.js";
|
|
3
|
-
import * as windows from "../../../lib/windows/index.js";
|
|
4
|
-
import { BaseCommand } from "../../base-command.js";
|
|
5
|
-
function abbreviateHome(path) {
|
|
6
|
-
const home = process.env.HOME;
|
|
7
|
-
if (!home)
|
|
8
|
-
return path;
|
|
9
|
-
if (path === home)
|
|
10
|
-
return "~";
|
|
11
|
-
if (path.startsWith(`${home}/`))
|
|
12
|
-
return `~/${path.slice(home.length + 1)}`;
|
|
13
|
-
return path;
|
|
14
|
-
}
|
|
15
|
-
function windowLabel(window) {
|
|
16
|
-
return `${window.window}:${window.windowName}`;
|
|
17
|
-
}
|
|
18
|
-
export default class WindowsFocusCommand extends BaseCommand {
|
|
19
|
-
static summary = "Show focused window";
|
|
20
|
-
static hidden = false;
|
|
21
|
-
static examples = [
|
|
22
|
-
"$ abbie windows focus",
|
|
23
|
-
"$ abbie windows focus --no-with-nvim",
|
|
24
|
-
"$ abbie windows focus --with-buffers",
|
|
25
|
-
"$ abbie windows focus --json",
|
|
26
|
-
];
|
|
27
|
-
static flags = {
|
|
28
|
-
...BaseCommand.baseFlags,
|
|
29
|
-
"with-nvim": Flags.boolean({
|
|
30
|
-
description: "Include nvim details",
|
|
31
|
-
default: true,
|
|
32
|
-
allowNo: true,
|
|
33
|
-
}),
|
|
34
|
-
"with-buffers": Flags.boolean({
|
|
35
|
-
description: "Include buffer list",
|
|
36
|
-
default: false,
|
|
37
|
-
}),
|
|
38
|
-
};
|
|
39
|
-
async execute() {
|
|
40
|
-
const { flags } = await this.parse(WindowsFocusCommand);
|
|
41
|
-
this.parsedFlags = flags;
|
|
42
|
-
const tmuxRunning = await isRunning();
|
|
43
|
-
if (!tmuxRunning) {
|
|
44
|
-
const result = { tmuxRunning: false, window: null };
|
|
45
|
-
if (!this.jsonEnabled?.()) {
|
|
46
|
-
this.log("tmux is not running");
|
|
47
|
-
}
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
50
|
-
const includeNvim = flags["with-nvim"] || flags["with-buffers"];
|
|
51
|
-
const includeBuffers = flags["with-buffers"];
|
|
52
|
-
const state = await windows.getFocusedWindow({
|
|
53
|
-
includeNvim,
|
|
54
|
-
includeAgent: true,
|
|
55
|
-
includeBuffers,
|
|
56
|
-
});
|
|
57
|
-
const result = { tmuxRunning: true, window: state };
|
|
58
|
-
if (!this.jsonEnabled?.()) {
|
|
59
|
-
this.printText(result, flags);
|
|
60
|
-
}
|
|
61
|
-
return result;
|
|
62
|
-
}
|
|
63
|
-
printText(result, flags) {
|
|
64
|
-
if (!result.window) {
|
|
65
|
-
this.log("No focused window");
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const { window, nvim, agent, buffers } = result.window;
|
|
69
|
-
this.log("FOCUSED WINDOW");
|
|
70
|
-
this.log(`Session: ${window.session}`);
|
|
71
|
-
this.log(`Window: ${windowLabel(window)}`);
|
|
72
|
-
this.log(`Pane: ${window.paneId || `${window.pane}`} (${window.active ? "active" : "inactive"})`);
|
|
73
|
-
this.log(`CWD: ${abbreviateHome(window.cwd)}`);
|
|
74
|
-
this.log(`CMD: ${window.title}`);
|
|
75
|
-
if (agent) {
|
|
76
|
-
this.log(`Agent: ${agent.type} (pid: ${agent.pid}${agent.sessionId ? `, session: ${agent.sessionId}` : ""})`);
|
|
77
|
-
}
|
|
78
|
-
if (flags["with-nvim"]) {
|
|
79
|
-
this.log("");
|
|
80
|
-
this.log("NVIM");
|
|
81
|
-
if (nvim?.available) {
|
|
82
|
-
this.log(`PID: ${nvim.pid ?? "-"}`);
|
|
83
|
-
this.log(`Server: ${nvim.serverAddr ?? "-"}${nvim.discoveryMethod ? ` (${nvim.discoveryMethod})` : ""}`);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
this.log("Not available");
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (flags["with-buffers"]) {
|
|
90
|
-
this.log("");
|
|
91
|
-
this.log("BUFFERS");
|
|
92
|
-
if (buffers.length === 0) {
|
|
93
|
-
this.log("No buffers");
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
for (const buf of buffers) {
|
|
97
|
-
const mod = buf.modified ? " [modified]" : "";
|
|
98
|
-
this.log(`- ${buf.name || buf.path} (${buf.filetype || "unknown"})${mod}`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class WindowsListCommand extends BaseCommand {
|
|
3
|
-
static summary: string;
|
|
4
|
-
static hidden: boolean;
|
|
5
|
-
static examples: string[];
|
|
6
|
-
static flags: {
|
|
7
|
-
session: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
active: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
-
"with-nvim": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
-
"with-agent": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
sync: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
-
format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
-
"json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
-
ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
-
};
|
|
17
|
-
execute(): Promise<unknown>;
|
|
18
|
-
private syncToConvex;
|
|
19
|
-
private printText;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=list.d.ts.map
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { api, getHttpClient, isConvexConfigured } from "@creativeintelligence/sdk/convex";
|
|
2
|
-
import { Flags } from "@oclif/core";
|
|
3
|
-
import { getDeviceId } from "../../../lib/device.js";
|
|
4
|
-
import { isRunning } from "../../../lib/tmux/index.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 windowLabel(window) {
|
|
21
|
-
return `${window.window}:${window.windowName}`;
|
|
22
|
-
}
|
|
23
|
-
function pad(value, width) {
|
|
24
|
-
if (value.length >= width)
|
|
25
|
-
return value;
|
|
26
|
-
return value + " ".repeat(width - value.length);
|
|
27
|
-
}
|
|
28
|
-
function formatRow(state) {
|
|
29
|
-
const id = state.window.paneId || paneRef(state.window);
|
|
30
|
-
return {
|
|
31
|
-
id,
|
|
32
|
-
session: state.window.session,
|
|
33
|
-
window: windowLabel(state.window),
|
|
34
|
-
cmd: state.window.title,
|
|
35
|
-
cwd: abbreviateHome(state.window.cwd),
|
|
36
|
-
nvim: state.nvim?.available ? "✓" : "-",
|
|
37
|
-
agent: state.agent?.type ?? "-",
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
export default class WindowsListCommand extends BaseCommand {
|
|
41
|
-
static summary = "List workspace windows (tmux panes)";
|
|
42
|
-
static hidden = false;
|
|
43
|
-
static examples = [
|
|
44
|
-
"$ abbie windows list",
|
|
45
|
-
"$ abbie windows list --session work",
|
|
46
|
-
"$ abbie windows list --active",
|
|
47
|
-
"$ abbie windows list --no-with-nvim",
|
|
48
|
-
"$ abbie windows list --no-with-agent",
|
|
49
|
-
"$ abbie windows list --sync",
|
|
50
|
-
"$ abbie windows list --json",
|
|
51
|
-
];
|
|
52
|
-
static flags = {
|
|
53
|
-
...BaseCommand.baseFlags,
|
|
54
|
-
session: Flags.string({
|
|
55
|
-
char: "s",
|
|
56
|
-
description: "Filter to specific tmux session",
|
|
57
|
-
}),
|
|
58
|
-
active: Flags.boolean({
|
|
59
|
-
description: "Only show active panes",
|
|
60
|
-
default: false,
|
|
61
|
-
}),
|
|
62
|
-
"with-nvim": Flags.boolean({
|
|
63
|
-
description: "Include nvim state",
|
|
64
|
-
default: true,
|
|
65
|
-
allowNo: true,
|
|
66
|
-
}),
|
|
67
|
-
"with-agent": Flags.boolean({
|
|
68
|
-
description: "Include agent detection",
|
|
69
|
-
default: true,
|
|
70
|
-
allowNo: true,
|
|
71
|
-
}),
|
|
72
|
-
sync: Flags.boolean({
|
|
73
|
-
description: "Sync windows to Convex for cross-device visibility",
|
|
74
|
-
default: false,
|
|
75
|
-
}),
|
|
76
|
-
};
|
|
77
|
-
async execute() {
|
|
78
|
-
const { flags } = await this.parse(WindowsListCommand);
|
|
79
|
-
this.parsedFlags = flags;
|
|
80
|
-
const tmuxRunning = await isRunning();
|
|
81
|
-
if (!tmuxRunning) {
|
|
82
|
-
const result = { tmuxRunning: false, windows: [] };
|
|
83
|
-
if (!this.jsonEnabled?.()) {
|
|
84
|
-
this.log("tmux is not running");
|
|
85
|
-
}
|
|
86
|
-
return result;
|
|
87
|
-
}
|
|
88
|
-
const states = await windows.inventory({
|
|
89
|
-
session: flags.session,
|
|
90
|
-
includeNvim: flags["with-nvim"],
|
|
91
|
-
includeAgent: flags["with-agent"],
|
|
92
|
-
includeBuffers: false,
|
|
93
|
-
});
|
|
94
|
-
const filtered = (flags.active ? states.filter((s) => s.window.active) : states).sort((a, b) => {
|
|
95
|
-
if (a.window.session !== b.window.session)
|
|
96
|
-
return a.window.session.localeCompare(b.window.session);
|
|
97
|
-
if (a.window.window !== b.window.window)
|
|
98
|
-
return a.window.window - b.window.window;
|
|
99
|
-
return a.window.pane - b.window.pane;
|
|
100
|
-
});
|
|
101
|
-
const result = { tmuxRunning: true, windows: filtered };
|
|
102
|
-
// Sync to Convex if requested
|
|
103
|
-
if (flags.sync) {
|
|
104
|
-
await this.syncToConvex(filtered);
|
|
105
|
-
}
|
|
106
|
-
if (!this.jsonEnabled?.()) {
|
|
107
|
-
this.printText(result);
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
async syncToConvex(states) {
|
|
112
|
-
if (!isConvexConfigured()) {
|
|
113
|
-
if (!this.jsonEnabled?.()) {
|
|
114
|
-
this.warn("Convex not configured, skipping sync");
|
|
115
|
-
}
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const deviceId = getDeviceId();
|
|
119
|
-
const windowData = states.map((state) => ({
|
|
120
|
-
paneId: state.window.paneId ||
|
|
121
|
-
`${state.window.session}:${state.window.window}.${state.window.pane}`,
|
|
122
|
-
tmuxSession: state.window.session,
|
|
123
|
-
windowIndex: state.window.window,
|
|
124
|
-
windowName: state.window.windowName,
|
|
125
|
-
paneIndex: state.window.pane,
|
|
126
|
-
cwd: state.window.cwd || "",
|
|
127
|
-
title: state.window.title || undefined,
|
|
128
|
-
isActive: state.window.active,
|
|
129
|
-
cols: state.window.size.cols,
|
|
130
|
-
rows: state.window.size.rows,
|
|
131
|
-
hasNvim: state.nvim?.available ?? false,
|
|
132
|
-
nvimPid: state.nvim?.pid ?? undefined,
|
|
133
|
-
nvimServerAddr: state.nvim?.serverAddr ?? undefined,
|
|
134
|
-
agentType: state.agent?.type ?? undefined,
|
|
135
|
-
agentPid: state.agent?.pid ?? undefined,
|
|
136
|
-
}));
|
|
137
|
-
try {
|
|
138
|
-
const client = getHttpClient();
|
|
139
|
-
const syncResult = await client.mutation(api.windows.sync, {
|
|
140
|
-
deviceId,
|
|
141
|
-
windows: windowData,
|
|
142
|
-
});
|
|
143
|
-
if (!this.jsonEnabled?.()) {
|
|
144
|
-
this.log(`Synced ${syncResult.synced} windows to Convex`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
catch (error) {
|
|
148
|
-
if (!this.jsonEnabled?.()) {
|
|
149
|
-
this.warn(`Failed to sync to Convex: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
printText(result) {
|
|
154
|
-
if (result.windows.length === 0) {
|
|
155
|
-
this.log("No windows found");
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const rows = result.windows.map(formatRow);
|
|
159
|
-
const widths = {
|
|
160
|
-
id: Math.max(2, ...rows.map((r) => r.id.length), "ID".length),
|
|
161
|
-
session: Math.max(2, ...rows.map((r) => r.session.length), "SESSION".length),
|
|
162
|
-
window: Math.max(2, ...rows.map((r) => r.window.length), "WINDOW".length),
|
|
163
|
-
cmd: Math.max(2, ...rows.map((r) => r.cmd.length), "CMD".length),
|
|
164
|
-
cwd: Math.max(2, ...rows.map((r) => r.cwd.length), "CWD".length),
|
|
165
|
-
};
|
|
166
|
-
this.log("WINDOWS");
|
|
167
|
-
this.log(`${pad("ID", widths.id)} ${pad("SESSION", widths.session)} ${pad("WINDOW", widths.window)} ${pad("CMD", widths.cmd)} ${pad("CWD", widths.cwd)} NVIM AGENT`);
|
|
168
|
-
for (const row of rows) {
|
|
169
|
-
this.log(`${pad(row.id, widths.id)} ${pad(row.session, widths.session)} ${pad(row.window, widths.window)} ${pad(row.cmd, widths.cmd)} ${pad(row.cwd, widths.cwd)} ${pad(row.nvim, 4)} ${row.agent}`);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class WindowsMapCommand extends BaseCommand {
|
|
3
|
-
static summary: string;
|
|
4
|
-
static hidden: boolean;
|
|
5
|
-
static examples: string[];
|
|
6
|
-
static flags: {
|
|
7
|
-
orphans: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
unmapped: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
-
format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
"json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
-
ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
};
|
|
14
|
-
execute(): Promise<unknown>;
|
|
15
|
-
private printText;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=map.d.ts.map
|