@paradow/ledge 0.9.1 → 0.11.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.
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  attachEnv
3
- } from "./chunk-65XGYBHL.js";
4
- import "./chunk-LYTRXJAQ.js";
3
+ } from "./chunk-47G477C7.js";
4
+ import "./chunk-TSA5LD4D.js";
5
5
  import {
6
6
  realTmux
7
- } from "./chunk-TO4XO2ML.js";
7
+ } from "./chunk-YV7BMEEB.js";
8
8
  import "./chunk-YUSY3E47.js";
9
9
  import {
10
10
  connect
11
- } from "./chunk-IWJAJAPK.js";
11
+ } from "./chunk-TC3XJUJA.js";
12
12
  import {
13
13
  PROTOCOL_PORT
14
- } from "./chunk-KDYAHPYN.js";
14
+ } from "./chunk-JOCNCNRP.js";
15
15
  import "./chunk-FGOFRWIB.js";
16
16
 
17
17
  // src/cli/attach.ts
@@ -7,7 +7,7 @@ import {
7
7
  parseClientMessage,
8
8
  parseServerMessage,
9
9
  readDaemonToken
10
- } from "./chunk-KDYAHPYN.js";
10
+ } from "./chunk-JOCNCNRP.js";
11
11
  import "./chunk-FGOFRWIB.js";
12
12
 
13
13
  // src/cli/bridge.ts
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  exitFile,
3
3
  spawnSession
4
- } from "./chunk-LYTRXJAQ.js";
4
+ } from "./chunk-TSA5LD4D.js";
5
5
  import {
6
6
  realTmux
7
- } from "./chunk-TO4XO2ML.js";
7
+ } from "./chunk-YV7BMEEB.js";
8
8
  import {
9
9
  log
10
10
  } from "./chunk-YUSY3E47.js";
11
11
  import {
12
12
  DaemonRefusedError,
13
13
  connect
14
- } from "./chunk-IWJAJAPK.js";
14
+ } from "./chunk-TC3XJUJA.js";
15
15
  import {
16
16
  PROTOCOL_PORT
17
- } from "./chunk-KDYAHPYN.js";
17
+ } from "./chunk-JOCNCNRP.js";
18
18
  import {
19
19
  ensureLedgeDir
20
20
  } from "./chunk-FGOFRWIB.js";
@@ -176,6 +176,8 @@ var SessionSchema = z.object({
176
176
  repoPath: z.string().optional(),
177
177
  branch: z.string().optional(),
178
178
  worktree: z.boolean().optional(),
179
+ /** The folder the agent works in now, as its last hook reported it: `cwd` stays where it started, this follows a worktree it entered. */
180
+ workdir: z.string().optional(),
179
181
  tmuxSession: z.string().nullable(),
180
182
  state: SessionStateSchema,
181
183
  pending: PendingSchema.optional(),
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cleanTopic,
3
3
  sessionTitle
4
- } from "./chunk-KDYAHPYN.js";
4
+ } from "./chunk-JOCNCNRP.js";
5
5
 
6
6
  // src/daemon/crossSession.ts
7
7
  var FIRST_LINE = /^Another Claude session sent a message:\s*\n/;
@@ -0,0 +1,6 @@
1
+ // src/version.ts
2
+ var LEDGE_VERSION = true ? "0.11.0" : "0.0.0-dev";
3
+
4
+ export {
5
+ LEDGE_VERSION
6
+ };
@@ -2,7 +2,7 @@ import {
2
2
  PROTOCOL_PORT,
3
3
  parseServerMessage,
4
4
  readDaemonToken
5
- } from "./chunk-KDYAHPYN.js";
5
+ } from "./chunk-JOCNCNRP.js";
6
6
 
7
7
  // src/client.ts
8
8
  import WebSocket from "ws";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pickName
3
- } from "./chunk-KDYAHPYN.js";
3
+ } from "./chunk-JOCNCNRP.js";
4
4
  import {
5
5
  paths
6
6
  } from "./chunk-FGOFRWIB.js";
@@ -143,9 +143,22 @@ function claudeSessionId(tool, args) {
143
143
  function exitFile(id) {
144
144
  return join2(paths().dir, `exit-${id}`);
145
145
  }
146
+ var PARENT_AGENT_VARS = [
147
+ "CLAUDECODE",
148
+ "CLAUDE_CODE_CHILD_SESSION",
149
+ "CLAUDE_CODE_SESSION_ID",
150
+ "CLAUDE_CODE_SESSION_ATTENDED",
151
+ "CLAUDE_CODE_ENTRYPOINT",
152
+ "CLAUDE_CODE_EXECPATH",
153
+ "CLAUDE_CODE_MESSAGING_SOCKET",
154
+ "CLAUDE_CODE_MESSAGING_TOKEN",
155
+ "CLAUDE_PID",
156
+ "CLAUDE_EFFORT"
157
+ ];
158
+ var PARENT_AGENT = new Set(PARENT_AGENT_VARS);
146
159
  function agentEnv(base, extra) {
147
160
  const env = {};
148
- for (const [k, v] of Object.entries(base)) if (v !== void 0 && k !== "TMUX" && !k.startsWith("TMUX_")) env[k] = v;
161
+ for (const [k, v] of Object.entries(base)) if (v !== void 0 && k !== "TMUX" && !k.startsWith("TMUX_") && !PARENT_AGENT.has(k)) env[k] = v;
149
162
  return { ...env, ...extra };
150
163
  }
151
164
  async function spawnSession(opts) {
@@ -163,7 +176,7 @@ async function spawnSession(opts) {
163
176
  const env = opts.env ?? process.env;
164
177
  const transcriptPath = agentSessionId ? claudeTranscriptPath(opts.cwd, agentSessionId, env) : void 0;
165
178
  const command = opts.recordExit ? ["sh", "-c", '"$@"; echo $? > "$0"', exitFile(id), ...agent] : agent;
166
- await opts.tmux.newSession({ name: tmuxSession, cwd: opts.cwd, env: agentEnv(env, { LEDGE_SESSION: id, LEDGE_NAME: name, ...opts.tool === "codex" ? { [CODEX_ENV_VAR]: id } : {} }), command });
179
+ await opts.tmux.newSession({ name: tmuxSession, cwd: opts.cwd, env: agentEnv(env, { LEDGE_SESSION: id, LEDGE_NAME: name, ...opts.tool === "codex" ? { [CODEX_ENV_VAR]: id } : {} }), unset: PARENT_AGENT_VARS, command });
167
180
  const at = now();
168
181
  return { id, name, tool: opts.tool, cwd: opts.cwd, project, title: `${name} \xB7 ${project}`, tmuxSession, state: "starting", helpers: [], startedAt: at, lastActivityAt: at, source: "launcher", ...agentSessionId ? { agentSessionId } : {}, ...transcriptPath ? { transcriptPath } : {} };
169
182
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-TO4XO2ML.js";
3
+ } from "./chunk-YV7BMEEB.js";
4
4
  import {
5
5
  ensureLedgeDir,
6
6
  paths
@@ -30,8 +30,9 @@ function realTmux(socket = "ledge", opts = {}) {
30
30
  const base = () => ["-L", socket, "-f", paths().tmuxConf];
31
31
  const t = (args, env) => run([...base(), ...args], env);
32
32
  return {
33
- async newSession({ name, cwd, env, command }) {
33
+ async newSession({ name, cwd, env, unset = [], command }) {
34
34
  const envArgs = Object.entries(env).flatMap(([k, v]) => ["-e", `${k}=${v}`]);
35
+ if (unset.length) command = ["env", ...unset.flatMap((v) => ["-u", v]), ...command];
35
36
  const clientEnv = env.PATH === void 0 ? void 0 : { ...process.env, PATH: env.PATH };
36
37
  const args = [...base(), "new-session", "-d", "-s", name, "-c", cwd, "-x", "200", "-y", "50", ...envArgs, "--", ...command];
37
38
  const serverUp = (await t(["list-sessions"])).code === 0;
@@ -12,26 +12,26 @@ import {
12
12
  pendingTool,
13
13
  reduce,
14
14
  repositoryId
15
- } from "./chunk-I4C5U6AI.js";
15
+ } from "./chunk-OHKQKXYM.js";
16
16
  import {
17
17
  agentMessages,
18
18
  claudeOpenCall,
19
19
  claudePlan,
20
20
  claudeToolAnswered,
21
21
  spawnSession
22
- } from "./chunk-LYTRXJAQ.js";
22
+ } from "./chunk-TSA5LD4D.js";
23
23
  import {
24
24
  LEDGE_VERSION
25
- } from "./chunk-YXXXSRQX.js";
25
+ } from "./chunk-RVEGELWF.js";
26
26
  import {
27
27
  SERVICE,
28
28
  inDaemonService,
29
29
  tmuxServerAtRisk
30
- } from "./chunk-Q7RCYJ4X.js";
30
+ } from "./chunk-USGAFLXF.js";
31
31
  import {
32
32
  realTmux,
33
33
  runFile
34
- } from "./chunk-TO4XO2ML.js";
34
+ } from "./chunk-YV7BMEEB.js";
35
35
  import {
36
36
  log
37
37
  } from "./chunk-YUSY3E47.js";
@@ -64,7 +64,7 @@ import {
64
64
  proposalRows,
65
65
  requestAuthorized,
66
66
  selectDaemonProtocol
67
- } from "./chunk-KDYAHPYN.js";
67
+ } from "./chunk-JOCNCNRP.js";
68
68
  import {
69
69
  ensureLedgeDir,
70
70
  paths
@@ -2583,10 +2583,18 @@ async function readDocument(request, context) {
2583
2583
  if (/^(?:file:|[a-zA-Z]:[\\/]|\\\\)/.test(source) || source.includes("\0")) return failure(request, "unsupported_path");
2584
2584
  if (request.basePath && (!isAbsolute3(request.basePath) || !markdown(request.basePath))) return failure(request, "unsupported_path");
2585
2585
  const expanded = source === "~" ? context.home : source.startsWith("~/") ? resolve6(context.home, source.slice(2)) : source;
2586
- const base = request.basePath ? dirname5(request.basePath) : context.cwd;
2587
- if (!isAbsolute3(expanded) && !base) return failure(request, "ambiguous_path");
2588
- const path = resolve6(base ?? context.home, expanded);
2589
- if (!markdown(path)) return failure(request, "unsupported_type");
2586
+ const bases = request.basePath ? [dirname5(request.basePath)] : [...new Set([context.workdir, context.cwd].filter((d) => !!d))];
2587
+ if (!isAbsolute3(expanded) && !bases.length) return failure(request, "ambiguous_path");
2588
+ const paths2 = isAbsolute3(expanded) ? [resolve6(expanded)] : bases.map((base) => resolve6(base, expanded));
2589
+ if (!markdown(paths2[0])) return failure(request, "unsupported_type");
2590
+ let read = failure(request, "not_found");
2591
+ for (const path of paths2) {
2592
+ read = await readAt(request, path);
2593
+ if (read.type === "document.content" || read.code !== "not_found") return read;
2594
+ }
2595
+ return read;
2596
+ }
2597
+ async function readAt(request, path) {
2590
2598
  let file;
2591
2599
  try {
2592
2600
  file = await open2(path, constants2.O_RDONLY | constants2.O_NONBLOCK);
@@ -3163,7 +3171,7 @@ async function startServer(opts) {
3163
3171
  case "document.read": {
3164
3172
  const session = msg.sessionId ? store.get(msg.sessionId) : void 0;
3165
3173
  if (msg.sessionId && !session) return send(ws, { type: "document.error", requestId: msg.requestId, path: msg.path, code: "session_missing" });
3166
- return send(ws, await readDocument(msg, { cwd: session?.cwd, home: opts.home ?? process.env.HOME ?? "" }));
3174
+ return send(ws, await readDocument(msg, { cwd: session?.cwd, workdir: session?.workdir, home: opts.home ?? process.env.HOME ?? "" }));
3167
3175
  }
3168
3176
  case "repos.inspect":
3169
3177
  return send(ws, { type: "repos.info", requestId: msg.requestId, repos: await inspectRepos(msg.paths, { home: opts.home }) });
@@ -3282,6 +3290,7 @@ async function startServer(opts) {
3282
3290
  store.upsert(base);
3283
3291
  store.apply(msg.id, msg.event);
3284
3292
  } else {
3293
+ if (msg.cwd) store.patch(msg.id, { workdir: msg.cwd });
3285
3294
  settleByHook(msg.id, ev);
3286
3295
  store.apply(msg.id, msg.event);
3287
3296
  }
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  QUESTION_TOOLS,
3
3
  gitInfo
4
- } from "./chunk-I4C5U6AI.js";
4
+ } from "./chunk-OHKQKXYM.js";
5
5
  import {
6
6
  CODEX_ENV_VAR,
7
7
  CODEX_HOOK_VAR,
8
8
  codexPlan
9
- } from "./chunk-LYTRXJAQ.js";
9
+ } from "./chunk-TSA5LD4D.js";
10
10
  import {
11
11
  log
12
12
  } from "./chunk-YUSY3E47.js";
13
13
  import {
14
14
  connect
15
- } from "./chunk-IWJAJAPK.js";
16
- import "./chunk-KDYAHPYN.js";
15
+ } from "./chunk-TC3XJUJA.js";
16
+ import "./chunk-JOCNCNRP.js";
17
17
  import "./chunk-FGOFRWIB.js";
18
18
 
19
19
  // src/cli/hook.ts
package/dist/cli/index.js CHANGED
@@ -17,7 +17,7 @@ async function hookMain(args) {
17
17
  try {
18
18
  const chunks = [];
19
19
  for await (const c of process.stdin) chunks.push(c);
20
- const { runHook } = await import("./hook-5HXY2UGM.js");
20
+ const { runHook } = await import("./hook-7V2GJUNO.js");
21
21
  const out = await runHook(event, Buffer.concat(chunks).toString("utf8"), { tool });
22
22
  if (out) process.stdout.write(`${out}
23
23
  `);
@@ -29,7 +29,7 @@ async function main(argv) {
29
29
  const [cmd, ...rest] = argv;
30
30
  switch (cmd) {
31
31
  case "daemon": {
32
- const { startDaemon } = await import("./daemon-NDXT3ZDF.js");
32
+ const { startDaemon } = await import("./daemon-YY66JWIB.js");
33
33
  await startDaemon();
34
34
  await new Promise(() => {
35
35
  });
@@ -37,44 +37,44 @@ async function main(argv) {
37
37
  }
38
38
  case "--version":
39
39
  case "version": {
40
- const { LEDGE_VERSION } = await import("./version-AQN6JNH7.js");
40
+ const { LEDGE_VERSION } = await import("./version-QSIZ47AV.js");
41
41
  console.log(LEDGE_VERSION);
42
42
  return 0;
43
43
  }
44
44
  case "setup": {
45
- const { runSetup } = await import("./setup-7AEH5DC3.js");
45
+ const { runSetup } = await import("./setup-SG43PPOZ.js");
46
46
  for (const l of await runSetup()) console.log(l);
47
47
  return 0;
48
48
  }
49
49
  case "uninstall": {
50
- const { runUninstall } = await import("./uninstall-7U7ENKOS.js");
50
+ const { runUninstall } = await import("./uninstall-SD736TBP.js");
51
51
  const r = await runUninstall({ purge: rest.includes("--purge") });
52
52
  for (const l of r.lines) console.log(l);
53
53
  return r.ok ? 0 : 1;
54
54
  }
55
55
  case "status": {
56
- const { printStatus } = await import("./status-PDNC6IC2.js");
56
+ const { printStatus } = await import("./status-QOXWNLLF.js");
57
57
  console.log(await printStatus());
58
58
  return 0;
59
59
  }
60
60
  case "who": {
61
- const { printWho } = await import("./who-LIMQJMNI.js");
61
+ const { printWho } = await import("./who-WVYFPCII.js");
62
62
  console.log(await printWho());
63
63
  return 0;
64
64
  }
65
65
  case "bridge": {
66
- const { bridge } = await import("./bridge-XHPCIYE4.js");
66
+ const { bridge } = await import("./bridge-ZOHP53DV.js");
67
67
  await bridge();
68
68
  return 0;
69
69
  }
70
70
  case "claude":
71
71
  case "codex":
72
72
  case "cursor": {
73
- const { launch } = await import("./launch-HEJKGMYS.js");
73
+ const { launch } = await import("./launch-2IQZPPTY.js");
74
74
  return launch(cmd, rest);
75
75
  }
76
76
  case "attach": {
77
- const { attach } = await import("./attach-AZFKVVKL.js");
77
+ const { attach } = await import("./attach-6JONTTMA.js");
78
78
  return attach(rest[0] ?? "");
79
79
  }
80
80
  default:
@@ -5,15 +5,15 @@ import {
5
5
  ensureDaemon,
6
6
  launch,
7
7
  parseLaunchArgs
8
- } from "./chunk-65XGYBHL.js";
8
+ } from "./chunk-47G477C7.js";
9
9
  import {
10
10
  agentEnv,
11
11
  exitFile
12
- } from "./chunk-LYTRXJAQ.js";
13
- import "./chunk-TO4XO2ML.js";
12
+ } from "./chunk-TSA5LD4D.js";
13
+ import "./chunk-YV7BMEEB.js";
14
14
  import "./chunk-YUSY3E47.js";
15
- import "./chunk-IWJAJAPK.js";
16
- import "./chunk-KDYAHPYN.js";
15
+ import "./chunk-TC3XJUJA.js";
16
+ import "./chunk-JOCNCNRP.js";
17
17
  import "./chunk-FGOFRWIB.js";
18
18
  export {
19
19
  DaemonError,
@@ -13,8 +13,8 @@ import {
13
13
  runSetup,
14
14
  stopDetachedDaemon,
15
15
  systemdUnit
16
- } from "./chunk-Q7RCYJ4X.js";
17
- import "./chunk-TO4XO2ML.js";
16
+ } from "./chunk-USGAFLXF.js";
17
+ import "./chunk-YV7BMEEB.js";
18
18
  import "./chunk-YUSY3E47.js";
19
19
  import "./chunk-FGOFRWIB.js";
20
20
  export {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  connect
3
- } from "./chunk-IWJAJAPK.js";
4
- import "./chunk-KDYAHPYN.js";
3
+ } from "./chunk-TC3XJUJA.js";
4
+ import "./chunk-JOCNCNRP.js";
5
5
  import "./chunk-FGOFRWIB.js";
6
6
 
7
7
  // src/cli/status.ts
@@ -2,8 +2,8 @@ import {
2
2
  SERVICE,
3
3
  execRunner,
4
4
  stopDetachedDaemon
5
- } from "./chunk-Q7RCYJ4X.js";
6
- import "./chunk-TO4XO2ML.js";
5
+ } from "./chunk-USGAFLXF.js";
6
+ import "./chunk-YV7BMEEB.js";
7
7
  import "./chunk-YUSY3E47.js";
8
8
  import {
9
9
  paths
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  LEDGE_VERSION
3
- } from "./chunk-YXXXSRQX.js";
3
+ } from "./chunk-RVEGELWF.js";
4
4
  export {
5
5
  LEDGE_VERSION
6
6
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  connect
3
- } from "./chunk-IWJAJAPK.js";
3
+ } from "./chunk-TC3XJUJA.js";
4
4
  import {
5
5
  isArchived
6
- } from "./chunk-KDYAHPYN.js";
6
+ } from "./chunk-JOCNCNRP.js";
7
7
  import "./chunk-FGOFRWIB.js";
8
8
 
9
9
  // src/cli/who.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paradow/ledge",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
4
4
  "description": "Follow and answer your WSL agent sessions (Claude Code, Codex, Cursor Agent) from the Ledge island on Windows.",
5
5
  "type": "module",
6
6
  "bin": { "ledge": "dist/cli/index.js" },
@@ -1,6 +0,0 @@
1
- // src/version.ts
2
- var LEDGE_VERSION = true ? "0.9.1" : "0.0.0-dev";
3
-
4
- export {
5
- LEDGE_VERSION
6
- };