@cestoliv/wt 0.1.0-pr5.g3ca944a → 0.1.0-pr5.gd63269d
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.
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
openConfiguredIde,
|
|
4
3
|
prepareWorktree
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import
|
|
4
|
+
} from "./chunk-D4BVSTNE.js";
|
|
5
|
+
import {
|
|
6
|
+
openIde
|
|
7
|
+
} from "./chunk-FSARWOCW.js";
|
|
7
8
|
import "./chunk-IQWENLPW.js";
|
|
8
9
|
|
|
9
10
|
// src/commands/agent.ts
|
|
@@ -13,6 +14,7 @@ import pc from "picocolors";
|
|
|
13
14
|
// src/lib/zed.ts
|
|
14
15
|
import { spawn } from "child_process";
|
|
15
16
|
import {
|
|
17
|
+
copyFileSync,
|
|
16
18
|
existsSync,
|
|
17
19
|
mkdirSync,
|
|
18
20
|
readdirSync,
|
|
@@ -37,6 +39,13 @@ function buildAgentTask(agentCommand, prompt, label) {
|
|
|
37
39
|
shell: "system"
|
|
38
40
|
};
|
|
39
41
|
}
|
|
42
|
+
function upsertTask(tasks, task) {
|
|
43
|
+
const idx = tasks.findIndex((t) => t.label === task.label);
|
|
44
|
+
if (idx === -1) return [...tasks, task];
|
|
45
|
+
const next = [...tasks];
|
|
46
|
+
next[idx] = task;
|
|
47
|
+
return next;
|
|
48
|
+
}
|
|
40
49
|
function removeTask(tasks, label) {
|
|
41
50
|
return tasks.filter((t) => t.label !== label);
|
|
42
51
|
}
|
|
@@ -55,12 +64,6 @@ function upsertKeymapBinding(keymap, chord, label) {
|
|
|
55
64
|
if (already) return keymap;
|
|
56
65
|
return [...keymap, target];
|
|
57
66
|
}
|
|
58
|
-
function hasConflictingChord(keymap, chord, label) {
|
|
59
|
-
const ours = JSON.stringify(buildKeymapBinding(chord, label).bindings[chord]);
|
|
60
|
-
return keymap.some(
|
|
61
|
-
(e) => e.bindings != null && e.bindings[chord] !== void 0 && JSON.stringify(e.bindings[chord]) !== ours
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
67
|
var MODIFIER_MAP = {
|
|
65
68
|
ctrl: "control down",
|
|
66
69
|
control: "control down",
|
|
@@ -72,37 +75,6 @@ var MODIFIER_MAP = {
|
|
|
72
75
|
opt: "option down",
|
|
73
76
|
option: "option down"
|
|
74
77
|
};
|
|
75
|
-
var KEY_CODE_MAP = {
|
|
76
|
-
space: 49,
|
|
77
|
-
tab: 48,
|
|
78
|
-
return: 36,
|
|
79
|
-
enter: 36,
|
|
80
|
-
escape: 53,
|
|
81
|
-
esc: 53,
|
|
82
|
-
delete: 51,
|
|
83
|
-
backspace: 51,
|
|
84
|
-
forwarddelete: 117,
|
|
85
|
-
up: 126,
|
|
86
|
-
down: 125,
|
|
87
|
-
left: 123,
|
|
88
|
-
right: 124,
|
|
89
|
-
home: 115,
|
|
90
|
-
end: 119,
|
|
91
|
-
pageup: 116,
|
|
92
|
-
pagedown: 121,
|
|
93
|
-
f1: 122,
|
|
94
|
-
f2: 120,
|
|
95
|
-
f3: 99,
|
|
96
|
-
f4: 118,
|
|
97
|
-
f5: 96,
|
|
98
|
-
f6: 97,
|
|
99
|
-
f7: 98,
|
|
100
|
-
f8: 100,
|
|
101
|
-
f9: 101,
|
|
102
|
-
f10: 109,
|
|
103
|
-
f11: 103,
|
|
104
|
-
f12: 111
|
|
105
|
-
};
|
|
106
78
|
function parseChord(chord) {
|
|
107
79
|
const parts = chord.split("-").map((p) => p.trim().toLowerCase()).filter(Boolean);
|
|
108
80
|
if (parts.length === 0) {
|
|
@@ -122,35 +94,17 @@ function buildOsascript(chord, opts = {}) {
|
|
|
122
94
|
const { loadDelay = 3, activateDelay = 0.8 } = opts;
|
|
123
95
|
const { key, modifiers } = parseChord(chord);
|
|
124
96
|
const using = modifiers.length > 0 ? ` using {${modifiers.join(", ")}}` : "";
|
|
125
|
-
let press;
|
|
126
|
-
if (key.length === 1) {
|
|
127
|
-
const escaped = key.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
128
|
-
press = `keystroke "${escaped}"`;
|
|
129
|
-
} else {
|
|
130
|
-
const code = KEY_CODE_MAP[key];
|
|
131
|
-
if (code === void 0) {
|
|
132
|
-
throw new Error(
|
|
133
|
-
`Unsupported key "${key}" in chord "${chord}". Use a single character or one of: ${Object.keys(KEY_CODE_MAP).join(", ")}.`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
press = `key code ${code}`;
|
|
137
|
-
}
|
|
138
97
|
return [
|
|
139
98
|
`delay ${loadDelay}`,
|
|
140
99
|
'tell application "Zed" to activate',
|
|
141
100
|
`delay ${activateDelay}`,
|
|
142
|
-
`tell application "System Events" to ${
|
|
101
|
+
`tell application "System Events" to keystroke "${key}"${using}`
|
|
143
102
|
].join("\n");
|
|
144
103
|
}
|
|
145
|
-
function parseTasks(raw) {
|
|
146
|
-
const errors = [];
|
|
147
|
-
const parsed = parse(raw, errors, { allowTrailingComma: true });
|
|
148
|
-
if (errors.length > 0 || !Array.isArray(parsed)) return null;
|
|
149
|
-
return parsed;
|
|
150
|
-
}
|
|
151
104
|
function readTasks(tasksPath) {
|
|
152
105
|
try {
|
|
153
|
-
|
|
106
|
+
const parsed = JSON.parse(readFileSync(tasksPath, "utf8"));
|
|
107
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
154
108
|
} catch {
|
|
155
109
|
return [];
|
|
156
110
|
}
|
|
@@ -161,28 +115,9 @@ function writeAgentTask(worktreePath, task) {
|
|
|
161
115
|
const createdDir = !existsSync(zedDir);
|
|
162
116
|
if (createdDir) mkdirSync(zedDir, { recursive: true });
|
|
163
117
|
const createdFile = !existsSync(tasksPath);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return { createdDir, createdFile };
|
|
168
|
-
}
|
|
169
|
-
const raw = readFileSync(tasksPath, "utf8");
|
|
170
|
-
const tasks = parseTasks(raw);
|
|
171
|
-
if (tasks === null) {
|
|
172
|
-
process.stderr.write(
|
|
173
|
-
`
|
|
174
|
-
Warning: could not parse ${tasksPath}; not modifying it. The agent task was not added.
|
|
175
|
-
`
|
|
176
|
-
);
|
|
177
|
-
return { createdDir, createdFile };
|
|
178
|
-
}
|
|
179
|
-
const idx = tasks.findIndex((t) => t.label === task.label);
|
|
180
|
-
const edits = modify(raw, idx === -1 ? [tasks.length] : [idx], task, {
|
|
181
|
-
isArrayInsertion: idx === -1,
|
|
182
|
-
formattingOptions: { insertSpaces: true, tabSize: 2 }
|
|
183
|
-
});
|
|
184
|
-
const updated = applyEdits(raw, edits);
|
|
185
|
-
writeFileSync(tasksPath, updated.endsWith("\n") ? updated : `${updated}
|
|
118
|
+
const existing = createdFile ? [] : readTasks(tasksPath);
|
|
119
|
+
const next = upsertTask(existing, task);
|
|
120
|
+
writeFileSync(tasksPath, `${JSON.stringify(next, null, 2)}
|
|
186
121
|
`);
|
|
187
122
|
return { createdDir, createdFile };
|
|
188
123
|
}
|
|
@@ -190,30 +125,12 @@ function cleanupAgentTask(worktreePath, label, created) {
|
|
|
190
125
|
const zedDir = join(worktreePath, ".zed");
|
|
191
126
|
const tasksPath = join(zedDir, "tasks.json");
|
|
192
127
|
if (existsSync(tasksPath)) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
} else {
|
|
199
|
-
writeFileSync(tasksPath, `${JSON.stringify(next, null, 2)}
|
|
128
|
+
const next = removeTask(readTasks(tasksPath), label);
|
|
129
|
+
if (next.length === 0 && created.createdFile) {
|
|
130
|
+
rmSync(tasksPath, { force: true });
|
|
131
|
+
} else {
|
|
132
|
+
writeFileSync(tasksPath, `${JSON.stringify(next, null, 2)}
|
|
200
133
|
`);
|
|
201
|
-
}
|
|
202
|
-
} else {
|
|
203
|
-
const raw = readFileSync(tasksPath, "utf8");
|
|
204
|
-
const tasks = parseTasks(raw);
|
|
205
|
-
const idx = tasks?.findIndex((t) => t.label === label) ?? -1;
|
|
206
|
-
if (idx !== -1) {
|
|
207
|
-
const edits = modify(raw, [idx], void 0, {});
|
|
208
|
-
const updated = applyEdits(raw, edits);
|
|
209
|
-
writeFileSync(
|
|
210
|
-
tasksPath,
|
|
211
|
-
updated.endsWith("\n") ? updated : `${updated}
|
|
212
|
-
`
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
} catch {
|
|
217
134
|
}
|
|
218
135
|
}
|
|
219
136
|
if (created.createdDir && existsSync(zedDir)) {
|
|
@@ -255,18 +172,12 @@ ${JSON.stringify(binding, null, 2)}
|
|
|
255
172
|
if (upsertKeymapBinding(keymap, chord, label) === keymap) {
|
|
256
173
|
return true;
|
|
257
174
|
}
|
|
258
|
-
if (hasConflictingChord(keymap, chord, label)) {
|
|
259
|
-
process.stderr.write(
|
|
260
|
-
`
|
|
261
|
-
Note: "${chord}" is already bound in ${keymapPath}; wt's agent binding will take precedence.
|
|
262
|
-
`
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
175
|
const edits = modify(raw, [keymap.length], binding, {
|
|
266
176
|
isArrayInsertion: true,
|
|
267
177
|
formattingOptions: { insertSpaces: true, tabSize: 2 }
|
|
268
178
|
});
|
|
269
179
|
const updated = applyEdits(raw, edits);
|
|
180
|
+
copyFileSync(keymapPath, `${keymapPath}.bak`);
|
|
270
181
|
writeFileSync(keymapPath, updated.endsWith("\n") ? updated : `${updated}
|
|
271
182
|
`);
|
|
272
183
|
return true;
|
|
@@ -318,7 +229,7 @@ function openAccessibilitySettings(open = defaultOpen) {
|
|
|
318
229
|
}
|
|
319
230
|
|
|
320
231
|
// src/commands/agent.ts
|
|
321
|
-
var CLEANUP_DELAY_MS =
|
|
232
|
+
var CLEANUP_DELAY_MS = 2e3;
|
|
322
233
|
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
323
234
|
async function createAgentWorktree(branch, planPrompt, options = {}) {
|
|
324
235
|
const prepared = await prepareWorktree(branch, options);
|
|
@@ -330,14 +241,15 @@ async function createAgentWorktree(branch, planPrompt, options = {}) {
|
|
|
330
241
|
`\u26A0 Agent auto-start requires Zed (ide is "${config.ide}"). Opening without starting the agent.`
|
|
331
242
|
)
|
|
332
243
|
);
|
|
333
|
-
|
|
244
|
+
if (config.ide) {
|
|
245
|
+
await openIde(config.ide, config.ide_open_args, worktreePath);
|
|
246
|
+
}
|
|
334
247
|
return;
|
|
335
248
|
}
|
|
336
249
|
if (!config.agent_command) {
|
|
337
250
|
console.error(
|
|
338
251
|
pc.red("No agent_command configured. Set it with `wt config`.")
|
|
339
252
|
);
|
|
340
|
-
await openConfiguredIde(config, worktreePath);
|
|
341
253
|
return;
|
|
342
254
|
}
|
|
343
255
|
const task = buildAgentTask(
|
|
@@ -346,21 +258,14 @@ async function createAgentWorktree(branch, planPrompt, options = {}) {
|
|
|
346
258
|
AGENT_TASK_LABEL
|
|
347
259
|
);
|
|
348
260
|
const created = writeAgentTask(worktreePath, task);
|
|
349
|
-
|
|
350
|
-
const opened = await
|
|
261
|
+
ensureKeymap(config.agent_trigger_chord, AGENT_TASK_LABEL);
|
|
262
|
+
const opened = await openIde("zed", config.ide_open_args, worktreePath);
|
|
351
263
|
if (!opened) {
|
|
352
264
|
console.error(pc.red("\u2717 Could not open Zed."));
|
|
353
265
|
cleanupAgentTask(worktreePath, AGENT_TASK_LABEL, created);
|
|
354
266
|
return;
|
|
355
267
|
}
|
|
356
|
-
|
|
357
|
-
console.warn(
|
|
358
|
-
pc.yellow(
|
|
359
|
-
`\u26A0 Could not install the Zed keybinding (see above). In Zed, press ${config.agent_trigger_chord} to start the agent manually.`
|
|
360
|
-
)
|
|
361
|
-
);
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
268
|
+
console.log(pc.green("\u2713 Opened Zed"));
|
|
364
269
|
console.log(pc.dim("Starting agent in Zed\u2026"));
|
|
365
270
|
let result = await triggerChord(config.agent_trigger_chord);
|
|
366
271
|
while (!result.ok && result.reason === "accessibility" && process.stdin.isTTY) {
|
|
@@ -140,22 +140,23 @@ async function prepareWorktree(branch, options = {}) {
|
|
|
140
140
|
}
|
|
141
141
|
return { repoRoot, worktreePath, config };
|
|
142
142
|
}
|
|
143
|
-
async function openConfiguredIde(config, worktreePath) {
|
|
144
|
-
if (!config.ide) return false;
|
|
145
|
-
const opened = await openIde(config.ide, config.ide_open_args, worktreePath);
|
|
146
|
-
if (opened) {
|
|
147
|
-
console.log(pc.green(`\u2713 Opened ${config.ide}`));
|
|
148
|
-
}
|
|
149
|
-
return opened;
|
|
150
|
-
}
|
|
151
143
|
async function createWorktree(branch, options = {}) {
|
|
152
144
|
const prepared = await prepareWorktree(branch, options);
|
|
153
145
|
if (!prepared) return;
|
|
154
|
-
|
|
146
|
+
const { config, worktreePath } = prepared;
|
|
147
|
+
if (config.ide) {
|
|
148
|
+
const opened = await openIde(
|
|
149
|
+
config.ide,
|
|
150
|
+
config.ide_open_args,
|
|
151
|
+
worktreePath
|
|
152
|
+
);
|
|
153
|
+
if (opened) {
|
|
154
|
+
console.log(pc.green(`\u2713 Opened ${config.ide}`));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
export {
|
|
158
160
|
prepareWorktree,
|
|
159
|
-
openConfiguredIde,
|
|
160
161
|
createWorktree
|
|
161
162
|
};
|
package/dist/cli.js
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
var program = new Command();
|
|
6
|
-
program.name("wt").description("Git worktree manager").version("0.1.0-pr5.
|
|
7
|
-
const { runList } = await import("./list-
|
|
6
|
+
program.name("wt").description("Git worktree manager").version("0.1.0-pr5.gd63269d").action(async () => {
|
|
7
|
+
const { runList } = await import("./list-HO42YAEG.js");
|
|
8
8
|
await runList();
|
|
9
9
|
});
|
|
10
10
|
program.command("create [branch]").description("Create a new worktree").action(async (branch) => {
|
|
11
|
-
const { createWorktree } = await import("./create-
|
|
11
|
+
const { createWorktree } = await import("./create-55SXEUZV.js");
|
|
12
12
|
await createWorktree(branch);
|
|
13
13
|
});
|
|
14
14
|
program.command("agent <branch> <plan_prompt>").description("Create a worktree and auto-start an AI agent in Zed (macOS)").action(async (branch, planPrompt) => {
|
|
15
|
-
const { createAgentWorktree } = await import("./agent-
|
|
15
|
+
const { createAgentWorktree } = await import("./agent-PR7PGIE5.js");
|
|
16
16
|
await createAgentWorktree(branch, planPrompt);
|
|
17
17
|
});
|
|
18
18
|
program.command("config").description("Open the config file in $EDITOR").option("--path", "Print the config file path and exit").action(async (options) => {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createWorktree,
|
|
4
|
-
openConfiguredIde,
|
|
5
4
|
prepareWorktree
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-D4BVSTNE.js";
|
|
7
6
|
import "./chunk-FSARWOCW.js";
|
|
8
7
|
import "./chunk-IQWENLPW.js";
|
|
9
8
|
export {
|
|
10
9
|
createWorktree,
|
|
11
|
-
openConfiguredIde,
|
|
12
10
|
prepareWorktree
|
|
13
11
|
};
|
|
@@ -93,7 +93,7 @@ ${dirty.map((f) => ` ${f}`).join("\n")}`
|
|
|
93
93
|
},
|
|
94
94
|
onCreate: async () => {
|
|
95
95
|
if (repoRoot) {
|
|
96
|
-
const { createWorktree } = await import("./create-
|
|
96
|
+
const { createWorktree } = await import("./create-55SXEUZV.js");
|
|
97
97
|
await createWorktree(void 0, { cwd: repoRoot, store });
|
|
98
98
|
}
|
|
99
99
|
}
|