tmux-ide 1.3.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/bin/cli.js +4 -216
  2. package/bin/cli.ts +536 -0
  3. package/package.json +27 -14
  4. package/src/__tests__/support.ts +186 -0
  5. package/src/attach.ts +20 -0
  6. package/src/cli.test.ts +314 -0
  7. package/src/command-center/discovery.test.ts +265 -0
  8. package/src/command-center/discovery.ts +296 -0
  9. package/src/command-center/index.ts +31 -0
  10. package/src/command-center/schemas.ts +57 -0
  11. package/src/command-center/server.test.ts +818 -0
  12. package/src/command-center/server.ts +1426 -0
  13. package/src/config-cli.test.ts +86 -0
  14. package/src/config.test.ts +205 -0
  15. package/src/config.ts +313 -0
  16. package/src/detect.test.ts +142 -0
  17. package/src/detect.ts +248 -0
  18. package/src/dispatch.ts +102 -0
  19. package/src/doctor.test.ts +119 -0
  20. package/src/doctor.ts +167 -0
  21. package/src/init.test.ts +101 -0
  22. package/src/init.ts +144 -0
  23. package/src/inspect.test.ts +67 -0
  24. package/src/inspect.ts +212 -0
  25. package/src/integration.test.ts.skip +276 -0
  26. package/src/js-yaml.d.ts +10 -0
  27. package/src/launch.test.ts +222 -0
  28. package/src/launch.ts +494 -0
  29. package/src/lib/auth/auth-service.test.ts +178 -0
  30. package/src/lib/auth/auth-service.ts +227 -0
  31. package/src/lib/auth/middleware.test.ts +119 -0
  32. package/src/lib/auth/middleware.ts +56 -0
  33. package/src/lib/auth/types.ts +13 -0
  34. package/src/lib/authorship.test.ts +242 -0
  35. package/src/lib/authorship.ts +280 -0
  36. package/src/lib/cast/recorder.test.ts +127 -0
  37. package/src/lib/cast/recorder.ts +148 -0
  38. package/src/lib/daemon-watchdog.ts +102 -0
  39. package/src/lib/daemon.ts +417 -0
  40. package/src/lib/dot-path.test.ts +66 -0
  41. package/src/lib/dot-path.ts +17 -0
  42. package/src/lib/errors.ts +44 -0
  43. package/src/lib/event-log.test.ts +189 -0
  44. package/src/lib/event-log.ts +237 -0
  45. package/src/lib/github-pr.ts +182 -0
  46. package/src/lib/hq/client.test.ts +154 -0
  47. package/src/lib/hq/client.ts +142 -0
  48. package/src/lib/hq/mdns.test.ts +54 -0
  49. package/src/lib/hq/mdns.ts +88 -0
  50. package/src/lib/hq/registry.test.ts +237 -0
  51. package/src/lib/hq/registry.ts +145 -0
  52. package/src/lib/hq/types.ts +44 -0
  53. package/src/lib/ipc/socket-protocol.test.ts +126 -0
  54. package/src/lib/ipc/socket-protocol.ts +324 -0
  55. package/src/lib/launch-plan.test.ts +119 -0
  56. package/src/lib/launch-plan.ts +90 -0
  57. package/src/lib/log.test.ts +39 -0
  58. package/src/lib/log.ts +71 -0
  59. package/src/lib/metrics.test.ts +213 -0
  60. package/src/lib/metrics.ts +345 -0
  61. package/src/lib/orchestrator.test.ts +2358 -0
  62. package/src/lib/orchestrator.ts +1792 -0
  63. package/src/lib/output.ts +76 -0
  64. package/src/lib/plan-store.test.ts +148 -0
  65. package/src/lib/plan-store.ts +131 -0
  66. package/src/lib/research.test.ts +208 -0
  67. package/src/lib/research.ts +475 -0
  68. package/src/lib/round-trip.test.ts +341 -0
  69. package/src/lib/session-monitor.test.ts +152 -0
  70. package/src/lib/session-monitor.ts +282 -0
  71. package/src/lib/session-options.test.ts +146 -0
  72. package/src/lib/session-options.ts +100 -0
  73. package/src/lib/shell.test.ts +20 -0
  74. package/src/lib/shell.ts +8 -0
  75. package/src/lib/sizes.test.ts +73 -0
  76. package/src/lib/sizes.ts +36 -0
  77. package/src/lib/skill-registry.test.ts +134 -0
  78. package/src/lib/skill-registry.ts +86 -0
  79. package/src/lib/slugify.test.ts +35 -0
  80. package/src/lib/slugify.ts +10 -0
  81. package/src/lib/task-store.ts +352 -0
  82. package/src/lib/tmux.test.ts +500 -0
  83. package/src/lib/tmux.ts +372 -0
  84. package/src/lib/token-tracker.test.ts +102 -0
  85. package/src/lib/token-tracker.ts +70 -0
  86. package/src/lib/tunnels/cloudflare.test.ts +73 -0
  87. package/src/lib/tunnels/cloudflare.ts +254 -0
  88. package/src/lib/tunnels/manager.test.ts +63 -0
  89. package/src/lib/tunnels/manager.ts +132 -0
  90. package/src/lib/tunnels/ngrok.test.ts +94 -0
  91. package/src/lib/tunnels/ngrok.ts +261 -0
  92. package/src/lib/tunnels/tailscale.test.ts +103 -0
  93. package/src/lib/tunnels/tailscale.ts +1048 -0
  94. package/src/lib/tunnels/types.ts +44 -0
  95. package/src/lib/validation.test.ts +289 -0
  96. package/src/lib/validation.ts +123 -0
  97. package/src/lib/webhook.ts +51 -0
  98. package/src/lib/workflow-store.ts +209 -0
  99. package/src/lib/ws-v3/protocol.test.ts +127 -0
  100. package/src/lib/ws-v3/protocol.ts +160 -0
  101. package/src/lib/yaml-io.test.ts +125 -0
  102. package/src/lib/yaml-io.ts +27 -0
  103. package/src/ls.test.ts +76 -0
  104. package/src/ls.ts +40 -0
  105. package/src/metrics-cli.ts +177 -0
  106. package/src/notify.ts +85 -0
  107. package/src/orchestrator-status.ts +228 -0
  108. package/src/plan.ts +117 -0
  109. package/src/postinstall.test.ts +79 -0
  110. package/src/remote.test.ts +115 -0
  111. package/src/remote.ts +148 -0
  112. package/src/restart.ts +24 -0
  113. package/src/schemas/domain.ts +422 -0
  114. package/src/schemas/ide-config.ts +148 -0
  115. package/src/schemas/index.ts +53 -0
  116. package/src/send.test.ts +70 -0
  117. package/src/send.ts +181 -0
  118. package/src/skill.test.ts +114 -0
  119. package/src/skill.ts +138 -0
  120. package/src/status.ts +66 -0
  121. package/src/stop.test.ts +176 -0
  122. package/src/stop.ts +47 -0
  123. package/src/task.test.ts +1466 -0
  124. package/src/task.ts +1143 -0
  125. package/src/tunnel.test.ts +80 -0
  126. package/src/tunnel.ts +133 -0
  127. package/src/types.ts +15 -0
  128. package/src/ui/index.ts +32 -0
  129. package/src/ui/terminal/index.ts +9 -0
  130. package/src/ui/types.ts +91 -0
  131. package/src/ui/web/base.css +80 -0
  132. package/src/ui/web/components/Box.tsx +59 -0
  133. package/src/ui/web/components/Input.tsx +32 -0
  134. package/src/ui/web/components/ScrollBox.tsx +60 -0
  135. package/src/ui/web/components/Text.tsx +28 -0
  136. package/src/ui/web/hooks.ts +106 -0
  137. package/src/ui/web/index.ts +27 -0
  138. package/src/ui/web/render.ts +77 -0
  139. package/src/ui/web/utils/color.test.ts +93 -0
  140. package/src/ui/web/utils/color.ts +27 -0
  141. package/src/validate.test.ts +385 -0
  142. package/src/validate.ts +217 -0
  143. package/src/widgets/changes/index.tsx +576 -0
  144. package/src/widgets/config/index.tsx +440 -0
  145. package/src/widgets/costs/index.tsx +216 -0
  146. package/src/widgets/explorer/breadcrumbs.tsx +77 -0
  147. package/src/widgets/explorer/footer.tsx +20 -0
  148. package/src/widgets/explorer/header.tsx +23 -0
  149. package/src/widgets/explorer/index.tsx +408 -0
  150. package/src/widgets/explorer/tree-model.test.ts +214 -0
  151. package/src/widgets/explorer/tree-model.ts +103 -0
  152. package/src/widgets/explorer/tree.tsx +156 -0
  153. package/src/widgets/lib/config-model.ts +116 -0
  154. package/src/widgets/lib/files.test.ts +103 -0
  155. package/src/widgets/lib/files.ts +88 -0
  156. package/src/widgets/lib/git.test.ts +151 -0
  157. package/src/widgets/lib/git.ts +88 -0
  158. package/src/widgets/lib/pane-comms.test.ts +178 -0
  159. package/src/widgets/lib/pane-comms.ts +192 -0
  160. package/src/widgets/lib/theme.ts +151 -0
  161. package/src/widgets/lib/watcher.ts +50 -0
  162. package/src/widgets/mission-control/activity-feed.tsx +59 -0
  163. package/src/widgets/mission-control/agent-panel.tsx +132 -0
  164. package/src/widgets/mission-control/command-bar.tsx +63 -0
  165. package/src/widgets/mission-control/index.tsx +751 -0
  166. package/src/widgets/mission-control/task-panel.tsx +238 -0
  167. package/src/widgets/preview/index.tsx +415 -0
  168. package/src/widgets/resolve.ts +40 -0
  169. package/src/widgets/setup/agent-naming.tsx +112 -0
  170. package/src/widgets/setup/config-tree.tsx +238 -0
  171. package/src/widgets/setup/detect-panel.tsx +72 -0
  172. package/src/widgets/setup/field-editor.tsx +265 -0
  173. package/src/widgets/setup/footer.tsx +107 -0
  174. package/src/widgets/setup/index.tsx +340 -0
  175. package/src/widgets/setup/layout-picker.tsx +96 -0
  176. package/src/widgets/setup/orchestrator-panel.tsx +200 -0
  177. package/src/widgets/setup/review-panel.tsx +140 -0
  178. package/src/widgets/setup/setup-model.test.ts +303 -0
  179. package/src/widgets/setup/setup-model.ts +188 -0
  180. package/src/widgets/tasks/index.tsx +129 -0
  181. package/src/widgets/tasks/task-detail.tsx +309 -0
  182. package/src/widgets/tasks/task-form.tsx +193 -0
  183. package/src/widgets/tasks/task-list.tsx +205 -0
  184. package/src/widgets/tasks/task-model.test.ts +473 -0
  185. package/src/widgets/tasks/task-model.ts +157 -0
  186. package/templates/AGENTS.md +20 -0
  187. package/templates/missions.yml +41 -0
  188. package/templates/skills/backend.md +30 -0
  189. package/templates/skills/frontend.md +30 -0
  190. package/templates/skills/general-worker.md +30 -0
  191. package/templates/skills/researcher.md +69 -0
  192. package/templates/skills/reviewer.md +30 -0
  193. package/dist/attach.d.ts +0 -3
  194. package/dist/attach.js +0 -14
  195. package/dist/config.d.ts +0 -5
  196. package/dist/config.js +0 -269
  197. package/dist/detect.d.ts +0 -15
  198. package/dist/detect.js +0 -228
  199. package/dist/doctor.d.ts +0 -3
  200. package/dist/doctor.js +0 -66
  201. package/dist/init.d.ts +0 -4
  202. package/dist/init.js +0 -67
  203. package/dist/inspect.d.ts +0 -54
  204. package/dist/inspect.js +0 -118
  205. package/dist/launch.d.ts +0 -22
  206. package/dist/launch.js +0 -174
  207. package/dist/lib/dot-path.d.ts +0 -2
  208. package/dist/lib/dot-path.js +0 -17
  209. package/dist/lib/errors.d.ts +0 -29
  210. package/dist/lib/errors.js +0 -37
  211. package/dist/lib/launch-plan.d.ts +0 -6
  212. package/dist/lib/launch-plan.js +0 -40
  213. package/dist/lib/output.d.ts +0 -9
  214. package/dist/lib/output.js +0 -65
  215. package/dist/lib/session-monitor.d.ts +0 -12
  216. package/dist/lib/session-monitor.js +0 -160
  217. package/dist/lib/session-options.d.ts +0 -13
  218. package/dist/lib/session-options.js +0 -85
  219. package/dist/lib/sizes.d.ts +0 -16
  220. package/dist/lib/sizes.js +0 -36
  221. package/dist/lib/tmux.d.ts +0 -42
  222. package/dist/lib/tmux.js +0 -225
  223. package/dist/lib/yaml-io.d.ts +0 -10
  224. package/dist/lib/yaml-io.js +0 -24
  225. package/dist/ls.d.ts +0 -3
  226. package/dist/ls.js +0 -35
  227. package/dist/restart.d.ts +0 -4
  228. package/dist/restart.js +0 -13
  229. package/dist/status.d.ts +0 -3
  230. package/dist/status.js +0 -29
  231. package/dist/stop.d.ts +0 -3
  232. package/dist/stop.js +0 -21
  233. package/dist/types.d.ts +0 -41
  234. package/dist/types.js +0 -1
  235. package/dist/validate.d.ts +0 -4
  236. package/dist/validate.js +0 -172
package/dist/lib/sizes.js DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * Compute absolute sizes for items where some have explicit sizes and others don't.
3
- * Items with `size` (e.g. "70%") keep their value; remaining space is split equally
4
- * among items without a size.
5
- */
6
- export function computeSizes(items) {
7
- let claimed = 0;
8
- let unclaimed = 0;
9
- for (const item of items) {
10
- if (item.size) {
11
- claimed += parseFloat(item.size);
12
- }
13
- else {
14
- unclaimed++;
15
- }
16
- }
17
- const remaining = Math.max(0, 100 - claimed);
18
- const defaultSize = unclaimed > 0 ? remaining / unclaimed : 0;
19
- return items.map((item) => (item.size ? parseFloat(item.size) : defaultSize));
20
- }
21
- /**
22
- * Convert absolute sizes (e.g. [70, 30]) to tmux split percentages for sequential splits.
23
- * Returns array of -p values (one per split after the first item).
24
- *
25
- * Each tmux split divides the current pane. The percentage given to -p is
26
- * the portion allocated to the NEW (bottom/right) pane.
27
- */
28
- export function toSplitPercents(sizes) {
29
- const percents = [];
30
- for (let i = 1; i < sizes.length; i++) {
31
- const remaining = sizes.slice(i - 1).reduce((a, b) => a + b, 0);
32
- const topShare = sizes[i - 1];
33
- percents.push(Math.round(((remaining - topShare) / remaining) * 100));
34
- }
35
- return percents;
36
- }
@@ -1,42 +0,0 @@
1
- import { execFileSync, spawn } from "node:child_process";
2
- import { TmuxError } from "./errors.ts";
3
- import type { SessionState } from "../types.ts";
4
- export { TmuxError };
5
- export declare function getSessionState(session: string): SessionState;
6
- export declare function attachSession(session: string): void;
7
- export declare function hasSession(session: string): boolean;
8
- export declare function killSession(session: string): {
9
- stopped: boolean;
10
- reason: string | null;
11
- };
12
- export declare function listPanes(session: string): {
13
- index: number;
14
- title: string | undefined;
15
- width: number;
16
- height: number;
17
- active: boolean;
18
- }[];
19
- export declare function createDetachedSession(session: string, cwd: string, { cols, lines }?: {
20
- cols?: number;
21
- lines?: number;
22
- }): string;
23
- export declare function setSessionEnvironment(session: string, key: string, value: string | number): void;
24
- export declare function splitPane(targetPane: string, direction: string, cwd: string, percent: number): string;
25
- export declare function sendLiteral(targetPane: string, text: string): void;
26
- export declare function getPaneCurrentCommand(targetPane: string): string;
27
- export declare function selectPane(targetPane: string): void;
28
- export declare function setPaneTitle(targetPane: string, title: string): void;
29
- export declare function runSessionCommand(args: string[]): void;
30
- export declare function startSessionMonitor(session: string, monitorScript: string): void;
31
- export declare function stopSessionMonitor(session: string): void;
32
- export declare function getSessionVariable(session: string, name: string): string | null;
33
- export declare function setSessionVariable(session: string, name: string, value: string): void;
34
- type Executor = typeof execFileSync;
35
- type Spawner = typeof spawn;
36
- /** @internal Replace the executor for testing. Returns a restore function. */
37
- export declare function _setExecutor(fn: Executor): () => void;
38
- /** @internal Replace the spawner for testing. Returns a restore function. */
39
- export declare function _setSpawner(fn: Spawner): () => void;
40
- declare global {
41
- var __tmuxIdeVerbose: boolean | undefined;
42
- }
package/dist/lib/tmux.js DELETED
@@ -1,225 +0,0 @@
1
- import { execFileSync, spawn } from "node:child_process";
2
- import { TmuxError } from "./errors.js";
3
- const DEBUG = process.env.TMUX_IDE_DEBUG === "1";
4
- const SESSION_NOT_FOUND_PATTERNS = ["can't find session", "can't find window", "unknown target"];
5
- const TMUX_UNAVAILABLE_PATTERNS = [
6
- "failed to connect to server",
7
- "no server running",
8
- "error connecting to",
9
- "connection refused",
10
- ];
11
- export { TmuxError };
12
- export function getSessionState(session) {
13
- try {
14
- runTmux(["has-session", "-t", session]);
15
- return { running: true, reason: null };
16
- }
17
- catch (error) {
18
- if (error instanceof TmuxError) {
19
- if (error.code === "SESSION_NOT_FOUND") {
20
- return { running: false, reason: "SESSION_NOT_FOUND" };
21
- }
22
- if (error.code === "TMUX_UNAVAILABLE") {
23
- return { running: false, reason: "TMUX_UNAVAILABLE" };
24
- }
25
- }
26
- throw error;
27
- }
28
- }
29
- export function attachSession(session) {
30
- runTmux(["attach", "-t", session], { stdio: "inherit" });
31
- }
32
- export function hasSession(session) {
33
- try {
34
- runTmux(["has-session", "-t", session]);
35
- return true;
36
- }
37
- catch (error) {
38
- if (error instanceof TmuxError &&
39
- (error.code === "SESSION_NOT_FOUND" || error.code === "TMUX_UNAVAILABLE")) {
40
- return false;
41
- }
42
- throw error;
43
- }
44
- }
45
- export function killSession(session) {
46
- try {
47
- runTmux(["kill-session", "-t", session]);
48
- return { stopped: true, reason: null };
49
- }
50
- catch (error) {
51
- if (error instanceof TmuxError) {
52
- if (error.code === "SESSION_NOT_FOUND") {
53
- return { stopped: false, reason: "SESSION_NOT_FOUND" };
54
- }
55
- if (error.code === "TMUX_UNAVAILABLE") {
56
- return { stopped: false, reason: "TMUX_UNAVAILABLE" };
57
- }
58
- }
59
- throw error;
60
- }
61
- }
62
- export function listPanes(session) {
63
- const raw = runTmux([
64
- "list-panes",
65
- "-t",
66
- session,
67
- "-F",
68
- "#{pane_index}|#{pane_title}|#{pane_width}|#{pane_height}|#{pane_active}",
69
- ], { encoding: "utf-8" }).trim();
70
- if (!raw)
71
- return [];
72
- return raw.split("\n").map((line) => {
73
- const [index, title, width, height, active] = line.split("|");
74
- return {
75
- index: Number.parseInt(index, 10),
76
- title,
77
- width: Number.parseInt(width, 10),
78
- height: Number.parseInt(height, 10),
79
- active: active === "1",
80
- };
81
- });
82
- }
83
- export function createDetachedSession(session, cwd, { cols, lines } = {}) {
84
- return runTmux([
85
- "new-session",
86
- "-d",
87
- "-P",
88
- "-F",
89
- "#{pane_id}",
90
- "-s",
91
- session,
92
- "-c",
93
- cwd,
94
- "-x",
95
- String(cols ?? 200),
96
- "-y",
97
- String(lines ?? 50),
98
- ], { encoding: "utf-8" }).trim();
99
- }
100
- export function setSessionEnvironment(session, key, value) {
101
- runTmux(["set-environment", "-t", session, key, String(value)]);
102
- }
103
- export function splitPane(targetPane, direction, cwd, percent) {
104
- return runTmux([
105
- "split-window",
106
- "-P",
107
- "-F",
108
- "#{pane_id}",
109
- "-t",
110
- targetPane,
111
- direction === "vertical" ? "-v" : "-h",
112
- "-c",
113
- cwd,
114
- "-p",
115
- String(percent),
116
- ], { encoding: "utf-8" }).trim();
117
- }
118
- export function sendLiteral(targetPane, text) {
119
- runTmux(["send-keys", "-t", targetPane, "-l", "--", text], { stdio: "inherit" });
120
- runTmux(["send-keys", "-t", targetPane, "Enter"], { stdio: "inherit" });
121
- }
122
- export function getPaneCurrentCommand(targetPane) {
123
- return runTmux(["display-message", "-p", "-t", targetPane, "#{pane_current_command}"], {
124
- encoding: "utf-8",
125
- }).trim();
126
- }
127
- export function selectPane(targetPane) {
128
- runTmux(["select-pane", "-t", targetPane], { stdio: "inherit" });
129
- }
130
- export function setPaneTitle(targetPane, title) {
131
- runTmux(["select-pane", "-t", targetPane, "-T", title], { stdio: "inherit" });
132
- }
133
- export function runSessionCommand(args) {
134
- runTmux(args, { stdio: "inherit" });
135
- }
136
- export function startSessionMonitor(session, monitorScript) {
137
- const child = _spawner("node", [monitorScript, session], {
138
- detached: true,
139
- stdio: "ignore",
140
- });
141
- child.unref();
142
- // Store PID as tmux session variable for later cleanup
143
- runTmux(["set-option", "-t", session, "@monitor_pid", String(child.pid)]);
144
- }
145
- export function stopSessionMonitor(session) {
146
- try {
147
- const pid = runTmux(["show-option", "-gqvt", session, "@monitor_pid"], {
148
- encoding: "utf-8",
149
- }).trim();
150
- if (pid)
151
- process.kill(parseInt(pid, 10));
152
- }
153
- catch {
154
- /* session or process already gone */
155
- }
156
- }
157
- export function getSessionVariable(session, name) {
158
- try {
159
- const raw = runTmux(["show-option", "-gqvt", session, name], {
160
- encoding: "utf-8",
161
- });
162
- return raw.trim() || null;
163
- }
164
- catch {
165
- return null;
166
- }
167
- }
168
- export function setSessionVariable(session, name, value) {
169
- runTmux(["set-option", "-t", session, name, value]);
170
- }
171
- let _executor = execFileSync;
172
- let _spawner = spawn;
173
- /** @internal Replace the executor for testing. Returns a restore function. */
174
- export function _setExecutor(fn) {
175
- const prev = _executor;
176
- _executor = fn;
177
- return () => {
178
- _executor = prev;
179
- };
180
- }
181
- /** @internal Replace the spawner for testing. Returns a restore function. */
182
- export function _setSpawner(fn) {
183
- const prev = _spawner;
184
- _spawner = fn;
185
- return () => {
186
- _spawner = prev;
187
- };
188
- }
189
- function runTmux(args, options = {}) {
190
- if (DEBUG || globalThis.__tmuxIdeVerbose) {
191
- console.error(` [tmux] ${args.join(" ")}`);
192
- }
193
- const execOptions = {
194
- stdio: ["ignore", "pipe", "pipe"],
195
- ...options,
196
- };
197
- try {
198
- return _executor("tmux", args, execOptions);
199
- }
200
- catch (error) {
201
- throw classifyTmuxError(error);
202
- }
203
- }
204
- function classifyTmuxError(error) {
205
- const detail = getErrorDetail(error).toLowerCase();
206
- if (SESSION_NOT_FOUND_PATTERNS.some((pattern) => detail.includes(pattern))) {
207
- return new TmuxError("tmux session was not found", "SESSION_NOT_FOUND", {
208
- cause: error,
209
- });
210
- }
211
- if (TMUX_UNAVAILABLE_PATTERNS.some((pattern) => detail.includes(pattern))) {
212
- return new TmuxError("tmux is unavailable or its socket is inaccessible", "TMUX_UNAVAILABLE", {
213
- cause: error,
214
- });
215
- }
216
- return new TmuxError("tmux command failed", "TMUX_ERROR", { cause: error });
217
- }
218
- function getErrorDetail(error) {
219
- const stderr = error?.stderr;
220
- if (typeof stderr === "string" && stderr.length > 0)
221
- return stderr;
222
- if (Buffer.isBuffer(stderr) && stderr.length > 0)
223
- return stderr.toString("utf-8");
224
- return error?.message ?? "";
225
- }
@@ -1,10 +0,0 @@
1
- import type { IdeConfig } from "../types.ts";
2
- export declare function readConfig(dir: string): {
3
- config: IdeConfig;
4
- configPath: string;
5
- };
6
- export declare function writeConfig(dir: string, config: IdeConfig): string;
7
- export declare function getSessionName(dir: string): {
8
- name: string;
9
- source: "config" | "fallback";
10
- };
@@ -1,24 +0,0 @@
1
- import { readFileSync, writeFileSync } from "node:fs";
2
- import { resolve, basename } from "node:path";
3
- import yaml from "js-yaml";
4
- export function readConfig(dir) {
5
- const configPath = resolve(dir, "ide.yml");
6
- const raw = readFileSync(configPath, "utf-8");
7
- const config = yaml.load(raw);
8
- return { config, configPath };
9
- }
10
- export function writeConfig(dir, config) {
11
- const configPath = resolve(dir, "ide.yml");
12
- const out = yaml.dump(config, { lineWidth: -1, noRefs: true, quotingType: '"' });
13
- writeFileSync(configPath, out);
14
- return configPath;
15
- }
16
- export function getSessionName(dir) {
17
- try {
18
- const { config } = readConfig(dir);
19
- return { name: config.name ?? basename(dir), source: config.name ? "config" : "fallback" };
20
- }
21
- catch {
22
- return { name: basename(dir), source: "fallback" };
23
- }
24
- }
package/dist/ls.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export declare function ls({ json }?: {
2
- json?: boolean;
3
- }): Promise<void>;
package/dist/ls.js DELETED
@@ -1,35 +0,0 @@
1
- import { execSync } from "node:child_process";
2
- export async function ls({ json } = {}) {
3
- let raw;
4
- try {
5
- raw = execSync('tmux list-sessions -F "#{session_name}|#{session_created}|#{session_attached}"', { encoding: "utf-8" }).trim();
6
- }
7
- catch {
8
- if (json) {
9
- console.log(JSON.stringify({ sessions: [] }));
10
- }
11
- else {
12
- console.log("No tmux sessions running.");
13
- }
14
- return;
15
- }
16
- const sessions = raw.split("\n").map((line) => {
17
- const [name, created, attached] = line.split("|");
18
- return {
19
- name,
20
- created: new Date(parseInt(created) * 1000).toISOString(),
21
- attached: attached !== "0",
22
- };
23
- });
24
- if (json) {
25
- console.log(JSON.stringify({ sessions }, null, 2));
26
- return;
27
- }
28
- // Table output
29
- console.log("SESSION".padEnd(24) + "CREATED".padEnd(22) + "ATTACHED");
30
- console.log("─".repeat(54));
31
- for (const s of sessions) {
32
- const date = new Date(s.created).toLocaleString();
33
- console.log(s.name.padEnd(24) + date.padEnd(22) + (s.attached ? "yes" : "no"));
34
- }
35
- }
package/dist/restart.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare function restart(targetDir: string | undefined, { json, attach }?: {
2
- json?: boolean;
3
- attach?: boolean;
4
- }): Promise<void>;
package/dist/restart.js DELETED
@@ -1,13 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { getSessionName } from "./lib/yaml-io.js";
3
- import { launch } from "./launch.js";
4
- import { killSession } from "./lib/tmux.js";
5
- export async function restart(targetDir, { json, attach } = {}) {
6
- const dir = resolve(targetDir ?? ".");
7
- const { name: session } = getSessionName(dir);
8
- const result = killSession(session);
9
- if (result.stopped) {
10
- console.log(`Stopped session "${session}"`);
11
- }
12
- await launch(dir, { json, attach });
13
- }
package/dist/status.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export declare function status(targetDir: string | undefined, { json }?: {
2
- json?: boolean;
3
- }): Promise<void>;
package/dist/status.js DELETED
@@ -1,29 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { existsSync } from "node:fs";
3
- import { getSessionName } from "./lib/yaml-io.js";
4
- import { getSessionState, listPanes } from "./lib/tmux.js";
5
- export async function status(targetDir, { json } = {}) {
6
- const dir = resolve(targetDir ?? ".");
7
- const { name: session } = getSessionName(dir);
8
- const configExists = existsSync(resolve(dir, "ide.yml"));
9
- const state = getSessionState(session);
10
- const running = state.running;
11
- let panes = [];
12
- if (running)
13
- panes = listPanes(session);
14
- const data = { session, running, configExists, panes };
15
- if (json) {
16
- console.log(JSON.stringify(data, null, 2));
17
- return;
18
- }
19
- console.log(`Session: ${session}`);
20
- console.log(`Running: ${running ? "yes" : "no"}`);
21
- console.log(`Config: ${configExists ? "ide.yml found" : "no ide.yml"}`);
22
- if (panes.length > 0) {
23
- console.log(`\nPanes:`);
24
- for (const p of panes) {
25
- const active = p.active ? " (active)" : "";
26
- console.log(` ${p.index}: ${p.title} [${p.width}x${p.height}]${active}`);
27
- }
28
- }
29
- }
package/dist/stop.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export declare function stop(targetDir: string | undefined, { json }?: {
2
- json?: boolean;
3
- }): Promise<void>;
package/dist/stop.js DELETED
@@ -1,21 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { getSessionName } from "./lib/yaml-io.js";
3
- import { outputError } from "./lib/output.js";
4
- import { killSession, stopSessionMonitor } from "./lib/tmux.js";
5
- export async function stop(targetDir, { json } = {}) {
6
- const dir = resolve(targetDir ?? ".");
7
- const { name: session } = getSessionName(dir);
8
- // Stop the session monitor before killing the session
9
- stopSessionMonitor(session);
10
- const result = killSession(session);
11
- if (result.stopped) {
12
- if (json) {
13
- console.log(JSON.stringify({ stopped: session }));
14
- }
15
- else {
16
- console.log(`Stopped session "${session}"`);
17
- }
18
- return;
19
- }
20
- outputError(`No active session "${session}" found`, "NOT_RUNNING");
21
- }
package/dist/types.d.ts DELETED
@@ -1,41 +0,0 @@
1
- export interface IdeConfig {
2
- name?: string;
3
- before?: string;
4
- team?: {
5
- name: string;
6
- };
7
- rows: Row[];
8
- theme?: ThemeConfig;
9
- }
10
- export interface Row {
11
- size?: string;
12
- panes: Pane[];
13
- }
14
- export interface Pane {
15
- title?: string;
16
- command?: string;
17
- dir?: string;
18
- size?: string;
19
- focus?: boolean;
20
- env?: Record<string, string | number>;
21
- role?: "lead" | "teammate";
22
- task?: string;
23
- }
24
- export interface ThemeConfig {
25
- accent?: string;
26
- border?: string;
27
- bg?: string;
28
- fg?: string;
29
- }
30
- export type TmuxCommand = string[];
31
- export interface PaneAction {
32
- targetPane: string;
33
- title: string | null;
34
- chdir: string | null;
35
- exports: string[];
36
- command: string | null;
37
- }
38
- export interface SessionState {
39
- running: boolean;
40
- reason: string | null;
41
- }
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- export {};
@@ -1,4 +0,0 @@
1
- export declare function validateConfig(config: unknown): string[];
2
- export declare function validate(targetDir: string | undefined, { json }?: {
3
- json?: boolean;
4
- }): Promise<void>;