@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.
Files changed (142) hide show
  1. package/bin/dev.js +1 -49
  2. package/bin/run.js +42 -49
  3. package/dist/cli/commands/login.js +26 -0
  4. package/dist/cli/commands/project/add.d.ts +0 -1
  5. package/dist/cli/commands/project/add.js +16 -52
  6. package/dist/cli/commands/project/list.js +13 -93
  7. package/dist/cli/commands/project/remove.d.ts +0 -2
  8. package/dist/cli/commands/project/remove.js +11 -28
  9. package/dist/cli/commands/session/list.js +3 -12
  10. package/dist/cli/commands/session/mark-done.js +1 -7
  11. package/dist/cli/commands/session/start.d.ts +0 -1
  12. package/dist/cli/commands/session/start.js +5 -7
  13. package/dist/lib/active-sessions.d.ts +0 -12
  14. package/dist/lib/active-sessions.js +6 -175
  15. package/dist/lib/project-path.d.ts +6 -0
  16. package/dist/lib/project-path.js +21 -0
  17. package/dist/lib.d.ts +1 -2
  18. package/dist/lib.js +2 -4
  19. package/oclif.manifest.json +2569 -6368
  20. package/package.json +1 -1
  21. package/dist/cli/commands/backlog/add.d.ts +0 -22
  22. package/dist/cli/commands/backlog/add.js +0 -65
  23. package/dist/cli/commands/backlog/claim.d.ts +0 -19
  24. package/dist/cli/commands/backlog/claim.js +0 -45
  25. package/dist/cli/commands/backlog/complete.d.ts +0 -18
  26. package/dist/cli/commands/backlog/complete.js +0 -42
  27. package/dist/cli/commands/backlog/list.d.ts +0 -20
  28. package/dist/cli/commands/backlog/list.js +0 -91
  29. package/dist/cli/commands/backlog/pick.d.ts +0 -18
  30. package/dist/cli/commands/backlog/pick.js +0 -42
  31. package/dist/cli/commands/backlog/sync.d.ts +0 -24
  32. package/dist/cli/commands/backlog/sync.js +0 -109
  33. package/dist/cli/commands/daemon.d.ts +0 -56
  34. package/dist/cli/commands/daemon.js +0 -1465
  35. package/dist/cli/commands/docs/lint.d.ts +0 -18
  36. package/dist/cli/commands/docs/lint.js +0 -82
  37. package/dist/cli/commands/docs/sync.d.ts +0 -19
  38. package/dist/cli/commands/docs/sync.js +0 -76
  39. package/dist/cli/commands/gc.d.ts +0 -29
  40. package/dist/cli/commands/gc.js +0 -211
  41. package/dist/cli/commands/index.d.ts +0 -36
  42. package/dist/cli/commands/index.js +0 -228
  43. package/dist/cli/commands/panes/broker.d.ts +0 -17
  44. package/dist/cli/commands/panes/broker.js +0 -57
  45. package/dist/cli/commands/panes/pipe-sink.d.ts +0 -17
  46. package/dist/cli/commands/panes/pipe-sink.js +0 -90
  47. package/dist/cli/commands/panes/snapshot.d.ts +0 -20
  48. package/dist/cli/commands/panes/snapshot.js +0 -125
  49. package/dist/cli/commands/preview/init.d.ts +0 -25
  50. package/dist/cli/commands/preview/init.js +0 -159
  51. package/dist/cli/commands/preview/sync.d.ts +0 -23
  52. package/dist/cli/commands/preview/sync.js +0 -144
  53. package/dist/cli/commands/preview/watch.d.ts +0 -24
  54. package/dist/cli/commands/preview/watch.js +0 -153
  55. package/dist/cli/commands/resource/acquire.d.ts +0 -21
  56. package/dist/cli/commands/resource/acquire.js +0 -90
  57. package/dist/cli/commands/resource/list.d.ts +0 -15
  58. package/dist/cli/commands/resource/list.js +0 -61
  59. package/dist/cli/commands/resource/release.d.ts +0 -18
  60. package/dist/cli/commands/resource/release.js +0 -50
  61. package/dist/cli/commands/resource/wait.d.ts +0 -21
  62. package/dist/cli/commands/resource/wait.js +0 -73
  63. package/dist/cli/commands/session/view.d.ts +0 -24
  64. package/dist/cli/commands/session/view.js +0 -145
  65. package/dist/cli/commands/start.d.ts +0 -37
  66. package/dist/cli/commands/start.js +0 -234
  67. package/dist/cli/commands/triage/claim.d.ts +0 -23
  68. package/dist/cli/commands/triage/claim.js +0 -186
  69. package/dist/cli/commands/triage/list.d.ts +0 -22
  70. package/dist/cli/commands/triage/list.js +0 -112
  71. package/dist/cli/commands/triage/next.d.ts +0 -18
  72. package/dist/cli/commands/triage/next.js +0 -63
  73. package/dist/cli/commands/triage/pull.d.ts +0 -19
  74. package/dist/cli/commands/triage/pull.js +0 -82
  75. package/dist/cli/commands/triage/stats.d.ts +0 -16
  76. package/dist/cli/commands/triage/stats.js +0 -69
  77. package/dist/cli/commands/tunnel/list.d.ts +0 -16
  78. package/dist/cli/commands/tunnel/list.js +0 -98
  79. package/dist/cli/commands/tunnel/start.d.ts +0 -24
  80. package/dist/cli/commands/tunnel/start.js +0 -107
  81. package/dist/cli/commands/tunnel/stop.d.ts +0 -20
  82. package/dist/cli/commands/tunnel/stop.js +0 -90
  83. package/dist/cli/commands/tunnel/url.d.ts +0 -21
  84. package/dist/cli/commands/tunnel/url.js +0 -70
  85. package/dist/cli/commands/windows/context.d.ts +0 -18
  86. package/dist/cli/commands/windows/context.js +0 -326
  87. package/dist/cli/commands/windows/focus.d.ts +0 -17
  88. package/dist/cli/commands/windows/focus.js +0 -103
  89. package/dist/cli/commands/windows/list.d.ts +0 -21
  90. package/dist/cli/commands/windows/list.js +0 -172
  91. package/dist/cli/commands/windows/map.d.ts +0 -17
  92. package/dist/cli/commands/windows/map.js +0 -168
  93. package/dist/cli/commands/windows/read.d.ts +0 -21
  94. package/dist/cli/commands/windows/read.js +0 -241
  95. package/dist/cli/commands/windows/search.d.ts +0 -24
  96. package/dist/cli/commands/windows/search.js +0 -171
  97. package/dist/cli/commands/windows/show.d.ts +0 -19
  98. package/dist/cli/commands/windows/show.js +0 -165
  99. package/dist/cli/commands/windows/watch.d.ts +0 -19
  100. package/dist/cli/commands/windows/watch.js +0 -241
  101. package/dist/lib/managed-session.d.ts +0 -27
  102. package/dist/lib/managed-session.js +0 -105
  103. package/dist/lib/panes/broker.d.ts +0 -130
  104. package/dist/lib/panes/broker.js +0 -97
  105. package/dist/lib/panes/index.d.ts +0 -2
  106. package/dist/lib/panes/index.js +0 -1
  107. package/dist/lib/panes/server.d.ts +0 -17
  108. package/dist/lib/panes/server.js +0 -308
  109. package/dist/lib/preview/manager.d.ts +0 -77
  110. package/dist/lib/preview/manager.js +0 -369
  111. package/dist/lib/preview/schema.d.ts +0 -2
  112. package/dist/lib/preview/schema.js +0 -32
  113. package/dist/lib/preview/sprite.d.ts +0 -85
  114. package/dist/lib/preview/sprite.js +0 -321
  115. package/dist/lib/preview/watcher.d.ts +0 -63
  116. package/dist/lib/preview/watcher.js +0 -185
  117. package/dist/lib/project-identity.d.ts +0 -16
  118. package/dist/lib/project-identity.js +0 -75
  119. package/dist/lib/tmux/bridge.d.ts +0 -133
  120. package/dist/lib/tmux/bridge.js +0 -315
  121. package/dist/lib/tmux/context.d.ts +0 -82
  122. package/dist/lib/tmux/context.js +0 -239
  123. package/dist/lib/tmux/index.d.ts +0 -8
  124. package/dist/lib/tmux/index.js +0 -11
  125. package/dist/lib/tmux/map.d.ts +0 -57
  126. package/dist/lib/tmux/map.js +0 -198
  127. package/dist/lib/tmux/panes.d.ts +0 -27
  128. package/dist/lib/tmux/panes.js +0 -151
  129. package/dist/lib/tmux/redaction.d.ts +0 -57
  130. package/dist/lib/tmux/redaction.js +0 -152
  131. package/dist/lib/web/analytics.d.ts +0 -63
  132. package/dist/lib/web/analytics.js +0 -168
  133. package/dist/lib/web/server.d.ts +0 -26
  134. package/dist/lib/web/server.js +0 -697
  135. package/dist/lib/web/tmux-bridge.d.ts +0 -7
  136. package/dist/lib/web/tmux-bridge.js +0 -7
  137. package/dist/lib/windows/index.d.ts +0 -3
  138. package/dist/lib/windows/index.js +0 -2
  139. package/dist/lib/windows/inventory.d.ts +0 -21
  140. package/dist/lib/windows/inventory.js +0 -263
  141. package/dist/lib/windows/types.d.ts +0 -46
  142. 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, "&lt;")
33
- .replace(/>/g, "&gt;")
34
- .replace(/"/g, "&quot;")
35
- .replace(/'/g, "&apos;");
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