@staff0rd/assist 0.284.1 → 0.286.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.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.284.1",
9
+ version: "0.286.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -275,6 +275,14 @@ var assistConfigSchema = z2.strictObject({
275
275
  screenshot: z2.strictObject({
276
276
  outputDir: z2.string().default("./screenshots")
277
277
  }).default({ outputDir: "./screenshots" }),
278
+ sessions: z2.strictObject({
279
+ // why: Windows .claude/projects root as seen from WSL (e.g. /mnt/c/Users/<user>/.claude/projects); when set its transcripts are discovered and tagged windows-origin
280
+ windowsProjectsRoot: z2.string().optional(),
281
+ // why: host the WSL daemon dials to reach the native Windows daemon over TCP (WSL can't use the Windows named pipe); defaults to 127.0.0.1 (WSL2 mirrored networking). NAT-mode users set the Windows host IP.
282
+ windowsDaemonHost: z2.string().optional(),
283
+ // why: TCP port the native Windows daemon listens on for the WSL bridge; defaults to 51764
284
+ windowsDaemonPort: z2.number().optional()
285
+ }).optional(),
278
286
  backlog: z2.strictObject({
279
287
  databaseUrl: z2.string().optional()
280
288
  }).default({}),
@@ -12069,10 +12077,10 @@ async function getAccessToken(apiKey) {
12069
12077
  }
12070
12078
  });
12071
12079
  if (!response.ok) {
12072
- const errorText = await response.text();
12080
+ const errorText2 = await response.text();
12073
12081
  throw new Error(
12074
12082
  `Failed to get access token: ${response.status} ${response.statusText}
12075
- ${errorText}`
12083
+ ${errorText2}`
12076
12084
  );
12077
12085
  }
12078
12086
  const tokenData = await response.json();
@@ -18100,11 +18108,11 @@ function toSessionInfo({
18100
18108
  }
18101
18109
 
18102
18110
  // src/commands/sessions/daemon/broadcastSessions.ts
18103
- function broadcastSessions(sessions, clients) {
18111
+ function broadcastSessions(sessions, clients, windowsSessions = []) {
18104
18112
  persistLiveSessions(sessions);
18105
18113
  broadcast(clients, {
18106
18114
  type: "sessions",
18107
- sessions: [...sessions.values()].map(toSessionInfo)
18115
+ sessions: [...sessions.values()].map(toSessionInfo).concat(windowsSessions)
18108
18116
  });
18109
18117
  }
18110
18118
 
@@ -18228,9 +18236,10 @@ function replayScrollback(sessions, client) {
18228
18236
  }
18229
18237
 
18230
18238
  // src/commands/sessions/daemon/greetClient.ts
18231
- function greetClient(client, sessions, list4) {
18239
+ function greetClient(client, sessions, list4, windowsProxy) {
18232
18240
  sendTo(client, { type: "sessions", sessions: list4() });
18233
18241
  replayScrollback(sessions, client);
18242
+ windowsProxy.replayScrollback(client);
18234
18243
  }
18235
18244
 
18236
18245
  // src/commands/sessions/daemon/shouldAutoDismiss.ts
@@ -18470,6 +18479,308 @@ function shutdownSessions(sessions) {
18470
18479
  }
18471
18480
  }
18472
18481
 
18482
+ // src/commands/sessions/daemon/connectToWindowsDaemon.ts
18483
+ import * as net2 from "net";
18484
+
18485
+ // src/commands/sessions/daemon/windowsDaemonPort.ts
18486
+ var DEFAULT_PORT = 51764;
18487
+ var DEFAULT_HOST = "127.0.0.1";
18488
+ function windowsDaemonPort() {
18489
+ return loadConfig().sessions?.windowsDaemonPort ?? DEFAULT_PORT;
18490
+ }
18491
+ function windowsDaemonHost() {
18492
+ return loadConfig().sessions?.windowsDaemonHost ?? DEFAULT_HOST;
18493
+ }
18494
+
18495
+ // src/commands/sessions/daemon/connectToWindowsDaemon.ts
18496
+ function connectToWindowsDaemon() {
18497
+ return new Promise((resolve16, reject) => {
18498
+ const socket = net2.connect(windowsDaemonPort(), windowsDaemonHost());
18499
+ socket.once("connect", () => resolve16(socket));
18500
+ socket.once("error", reject);
18501
+ });
18502
+ }
18503
+ async function isWindowsDaemonRunning() {
18504
+ try {
18505
+ (await connectToWindowsDaemon()).destroy();
18506
+ return true;
18507
+ } catch {
18508
+ return false;
18509
+ }
18510
+ }
18511
+
18512
+ // src/commands/sessions/daemon/ensureWindowsDaemonRunning.ts
18513
+ import { spawn as spawn10 } from "child_process";
18514
+ var SPAWN_TIMEOUT_MS2 = 3e4;
18515
+ var RETRY_DELAY_MS2 = 300;
18516
+ async function ensureWindowsDaemonRunning() {
18517
+ if (await isWindowsDaemonRunning()) return;
18518
+ launchWindowsDaemon();
18519
+ await waitForWindowsDaemon();
18520
+ }
18521
+ function launchWindowsDaemon() {
18522
+ const child = spawn10(
18523
+ "cmd.exe",
18524
+ ["/c", "start", "", "assist", "daemon", "run"],
18525
+ { detached: true, stdio: "ignore" }
18526
+ );
18527
+ child.on(
18528
+ "error",
18529
+ (e) => daemonLog(`failed to launch windows daemon: ${e.message}`)
18530
+ );
18531
+ child.unref();
18532
+ }
18533
+ async function waitForWindowsDaemon() {
18534
+ const deadline = Date.now() + SPAWN_TIMEOUT_MS2;
18535
+ while (Date.now() < deadline) {
18536
+ await delay2(RETRY_DELAY_MS2);
18537
+ if (await isWindowsDaemonRunning()) return;
18538
+ }
18539
+ throw new Error(
18540
+ "Windows daemon did not start; is assist installed on the Windows host?"
18541
+ );
18542
+ }
18543
+ function delay2(ms) {
18544
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
18545
+ }
18546
+
18547
+ // src/commands/sessions/daemon/buildHello.ts
18548
+ var ASSIST_VERSION = package_default.version;
18549
+ function buildHello() {
18550
+ return { type: "hello", version: ASSIST_VERSION };
18551
+ }
18552
+ function isHello(msg) {
18553
+ return msg.type === "hello" && typeof msg.version === "string";
18554
+ }
18555
+ function versionsMatch(a, b) {
18556
+ return a === b;
18557
+ }
18558
+
18559
+ // src/commands/sessions/daemon/toWindowsSessionId.ts
18560
+ var PREFIX = "w-";
18561
+ function toWindowsSessionId(id) {
18562
+ return `${PREFIX}${id}`;
18563
+ }
18564
+ function isWindowsSessionId(id) {
18565
+ return id.startsWith(PREFIX);
18566
+ }
18567
+ function stripWindowsSessionId(id) {
18568
+ return id.startsWith(PREFIX) ? id.slice(PREFIX.length) : id;
18569
+ }
18570
+
18571
+ // src/commands/sessions/daemon/WindowsProxyState.ts
18572
+ var MAX_SCROLLBACK2 = 256 * 1024;
18573
+ function createState(broadcast2, onSessionsChanged) {
18574
+ return {
18575
+ windowsSessions: [],
18576
+ scrollback: /* @__PURE__ */ new Map(),
18577
+ pendingCreators: [],
18578
+ broadcast: broadcast2,
18579
+ onSessionsChanged
18580
+ };
18581
+ }
18582
+ function resetState(state) {
18583
+ state.windowsSessions = [];
18584
+ state.scrollback.clear();
18585
+ state.pendingCreators = [];
18586
+ }
18587
+ function replayScrollback2(state, client) {
18588
+ for (const [sessionId, data] of state.scrollback)
18589
+ if (data) sendTo(client, { type: "output", sessionId, data });
18590
+ }
18591
+ function appendScrollback2(state, sessionId, data) {
18592
+ const next3 = (state.scrollback.get(sessionId) ?? "") + data;
18593
+ state.scrollback.set(
18594
+ sessionId,
18595
+ next3.length > MAX_SCROLLBACK2 ? next3.slice(-MAX_SCROLLBACK2) : next3
18596
+ );
18597
+ }
18598
+
18599
+ // src/commands/sessions/daemon/handleInbound.ts
18600
+ function handleInbound(state, line) {
18601
+ let msg;
18602
+ try {
18603
+ msg = JSON.parse(line);
18604
+ } catch {
18605
+ return;
18606
+ }
18607
+ inbound[msg.type]?.(state, msg);
18608
+ }
18609
+ var inbound = {
18610
+ hello: (_state, msg) => handleHello(msg),
18611
+ created: handleCreated,
18612
+ sessions: handleSessions,
18613
+ output: handleOutput,
18614
+ clear: relayWithSessionId,
18615
+ error: (state, msg) => state.broadcast(msg)
18616
+ };
18617
+ function handleHello(msg) {
18618
+ if (isHello(msg) && !versionsMatch(msg.version, ASSIST_VERSION))
18619
+ daemonLog(
18620
+ `windows daemon version mismatch: ${msg.version} (wsl ${ASSIST_VERSION})`
18621
+ );
18622
+ }
18623
+ function handleCreated(state, msg) {
18624
+ const client = state.pendingCreators.shift();
18625
+ if (client) sendTo(client, { type: "created", sessionId: nsId(msg) });
18626
+ }
18627
+ function handleSessions(state, msg) {
18628
+ state.windowsSessions = msg.sessions.map((s) => ({
18629
+ ...s,
18630
+ id: toWindowsSessionId(s.id)
18631
+ }));
18632
+ const live = new Set(state.windowsSessions.map((s) => s.id));
18633
+ for (const id of state.scrollback.keys())
18634
+ if (!live.has(id)) state.scrollback.delete(id);
18635
+ state.onSessionsChanged();
18636
+ }
18637
+ function handleOutput(state, msg) {
18638
+ const sessionId = nsId(msg);
18639
+ const data = msg.data;
18640
+ appendScrollback2(state, sessionId, data);
18641
+ state.broadcast({ type: "output", sessionId, data });
18642
+ }
18643
+ function relayWithSessionId(state, msg) {
18644
+ state.broadcast({ ...msg, sessionId: nsId(msg) });
18645
+ }
18646
+ function nsId(msg) {
18647
+ return toWindowsSessionId(msg.sessionId);
18648
+ }
18649
+
18650
+ // src/commands/sessions/daemon/isWindowsCwd.ts
18651
+ function isWindowsCwd(cwd) {
18652
+ return /^[A-Za-z]:[\\/]/.test(cwd);
18653
+ }
18654
+ function shouldProxyToWindows(cwd) {
18655
+ return detectPlatform() === "wsl" && isWindowsCwd(cwd);
18656
+ }
18657
+
18658
+ // src/commands/sessions/daemon/WindowsConnection.ts
18659
+ import { createInterface as createInterface5 } from "readline";
18660
+ var WindowsConnection = class {
18661
+ constructor(deps2) {
18662
+ this.deps = deps2;
18663
+ }
18664
+ connection = null;
18665
+ socket = null;
18666
+ ensure() {
18667
+ if (this.connection) return this.connection;
18668
+ const connection = this.open();
18669
+ this.connection = connection;
18670
+ connection.catch(() => {
18671
+ if (this.connection === connection) this.connection = null;
18672
+ });
18673
+ return connection;
18674
+ }
18675
+ write(msg) {
18676
+ this.socket?.write(`${JSON.stringify(msg)}
18677
+ `);
18678
+ }
18679
+ trySend(msg) {
18680
+ if (!this.socket?.writable) return false;
18681
+ this.write(msg);
18682
+ return true;
18683
+ }
18684
+ dispose() {
18685
+ this.socket?.destroy();
18686
+ this.reset();
18687
+ }
18688
+ async open() {
18689
+ const socket = await this.deps.connect();
18690
+ this.socket = socket;
18691
+ const lines = createInterface5({ input: socket });
18692
+ lines.on("error", () => {
18693
+ });
18694
+ lines.on("line", (line) => this.deps.onLine(line));
18695
+ socket.on("error", () => {
18696
+ });
18697
+ socket.on("close", () => {
18698
+ this.reset();
18699
+ this.deps.onClose();
18700
+ });
18701
+ this.write(buildHello());
18702
+ return socket;
18703
+ }
18704
+ reset() {
18705
+ this.socket = null;
18706
+ this.connection = null;
18707
+ }
18708
+ };
18709
+
18710
+ // src/commands/sessions/daemon/WindowsProxy.ts
18711
+ var WindowsProxy = class {
18712
+ state;
18713
+ conn;
18714
+ constructor(clients, onSessionsChanged, connect3 = defaultConnect) {
18715
+ this.state = createState(
18716
+ (msg) => broadcast(clients, msg),
18717
+ onSessionsChanged
18718
+ );
18719
+ this.conn = new WindowsConnection({
18720
+ connect: connect3,
18721
+ onLine: (line) => handleInbound(this.state, line),
18722
+ onClose: () => this.handleClose()
18723
+ });
18724
+ }
18725
+ sessions() {
18726
+ return this.state.windowsSessions;
18727
+ }
18728
+ replayScrollback(client) {
18729
+ replayScrollback2(this.state, client);
18730
+ }
18731
+ // Returns true when the message targets Windows: a create/resume in a
18732
+ // windows-origin cwd is forwarded, as is I/O for a namespaced session id.
18733
+ route(client, data) {
18734
+ if (isWindowsCreate(data)) {
18735
+ void this.forwardCreate(client, data);
18736
+ return true;
18737
+ }
18738
+ if (isWindowsIo(data)) {
18739
+ const sessionId = stripWindowsSessionId(data.sessionId);
18740
+ this.conn.trySend({ ...data, sessionId });
18741
+ return true;
18742
+ }
18743
+ return false;
18744
+ }
18745
+ dispose() {
18746
+ this.conn.dispose();
18747
+ }
18748
+ async forwardCreate(client, data) {
18749
+ try {
18750
+ await this.conn.ensure();
18751
+ this.state.pendingCreators.push(client);
18752
+ this.conn.write(data);
18753
+ } catch (e) {
18754
+ sendTo(client, {
18755
+ type: "error",
18756
+ message: `Windows session unavailable: ${errorText(e)}`
18757
+ });
18758
+ }
18759
+ }
18760
+ handleClose() {
18761
+ for (const client of this.state.pendingCreators)
18762
+ sendTo(client, {
18763
+ type: "error",
18764
+ message: "Windows daemon connection closed"
18765
+ });
18766
+ resetState(this.state);
18767
+ this.state.onSessionsChanged();
18768
+ }
18769
+ };
18770
+ function isWindowsCreate(data) {
18771
+ return typeof data.cwd === "string" && shouldProxyToWindows(data.cwd);
18772
+ }
18773
+ function isWindowsIo(data) {
18774
+ return typeof data.sessionId === "string" && isWindowsSessionId(data.sessionId);
18775
+ }
18776
+ async function defaultConnect() {
18777
+ await ensureWindowsDaemonRunning();
18778
+ return connectToWindowsDaemon();
18779
+ }
18780
+ function errorText(e) {
18781
+ return e instanceof Error ? e.message : String(e);
18782
+ }
18783
+
18473
18784
  // src/commands/sessions/daemon/watchClaudeSessionId.ts
18474
18785
  import * as fs27 from "fs";
18475
18786
  import * as path48 from "path";
@@ -18567,23 +18878,20 @@ function matchMarker(text3, tag) {
18567
18878
  }
18568
18879
 
18569
18880
  // src/commands/sessions/shared/parseSessionFile.ts
18570
- async function parseSessionFile(filePath) {
18881
+ async function parseSessionFile(filePath, origin = "wsl") {
18571
18882
  let handle;
18572
18883
  try {
18573
18884
  handle = await fs25.promises.open(filePath, "r");
18574
- const buf = Buffer.alloc(16384);
18575
- const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
18576
- const lines = buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
18577
- const meta = extractSessionMeta(lines);
18885
+ const meta = extractSessionMeta(await readHeadLines(handle));
18578
18886
  if (!meta.sessionId) return null;
18579
18887
  const timestamp = meta.timestamp || (await fs25.promises.stat(filePath)).mtime.toISOString();
18580
- const project = meta.cwd ? path46.basename(meta.cwd) : dirNameToProject(filePath);
18581
18888
  return {
18582
18889
  sessionId: meta.sessionId,
18583
18890
  name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
18584
- project,
18891
+ project: deriveProject(meta.cwd, filePath, origin),
18585
18892
  cwd: meta.cwd,
18586
18893
  timestamp,
18894
+ origin,
18587
18895
  ...deriveHistoryFields(meta.commandName, meta.commandArgs, meta.name)
18588
18896
  };
18589
18897
  } catch {
@@ -18592,6 +18900,15 @@ async function parseSessionFile(filePath) {
18592
18900
  await handle?.close();
18593
18901
  }
18594
18902
  }
18903
+ async function readHeadLines(handle) {
18904
+ const buf = Buffer.alloc(16384);
18905
+ const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
18906
+ return buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
18907
+ }
18908
+ function deriveProject(cwd, filePath, origin) {
18909
+ if (!cwd) return dirNameToProject(filePath);
18910
+ return origin === "windows" ? path46.win32.basename(cwd) : path46.basename(cwd);
18911
+ }
18595
18912
  function dirNameToProject(filePath) {
18596
18913
  const dirName = path46.basename(path46.dirname(filePath));
18597
18914
  const parts = dirName.split("--");
@@ -18599,38 +18916,52 @@ function dirNameToProject(filePath) {
18599
18916
  }
18600
18917
 
18601
18918
  // src/commands/sessions/shared/discoverSessions.ts
18919
+ function sessionRoots() {
18920
+ const roots = [
18921
+ { dir: path47.join(os.homedir(), ".claude", "projects"), origin: "wsl" }
18922
+ ];
18923
+ const windowsRoot = loadConfig().sessions?.windowsProjectsRoot;
18924
+ if (windowsRoot) roots.push({ dir: windowsRoot, origin: "windows" });
18925
+ return roots;
18926
+ }
18602
18927
  async function discoverSessionJsonlPaths() {
18603
- const projectsDir = path47.join(os.homedir(), ".claude", "projects");
18604
- let projectDirs;
18605
- try {
18606
- projectDirs = await fs26.promises.readdir(projectsDir);
18607
- } catch {
18608
- return [];
18609
- }
18610
- const paths = [];
18928
+ const results = [];
18611
18929
  await Promise.all(
18612
- projectDirs.map(async (dirName) => {
18613
- const dirPath = path47.join(projectsDir, dirName);
18614
- let entries;
18930
+ sessionRoots().map(async ({ dir, origin }) => {
18931
+ let projectDirs;
18615
18932
  try {
18616
- entries = await fs26.promises.readdir(dirPath);
18933
+ projectDirs = await fs26.promises.readdir(dir);
18617
18934
  } catch {
18618
18935
  return;
18619
18936
  }
18620
- const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
18621
- for (const file of jsonlFiles) {
18622
- paths.push(path47.join(dirPath, file));
18623
- }
18937
+ await Promise.all(
18938
+ projectDirs.map(async (dirName) => {
18939
+ const dirPath = path47.join(dir, dirName);
18940
+ let entries;
18941
+ try {
18942
+ entries = await fs26.promises.readdir(dirPath);
18943
+ } catch {
18944
+ return;
18945
+ }
18946
+ for (const file of entries) {
18947
+ if (file.endsWith(".jsonl"))
18948
+ results.push({ path: path47.join(dirPath, file), origin });
18949
+ }
18950
+ })
18951
+ );
18624
18952
  })
18625
18953
  );
18626
- return paths;
18954
+ return results;
18955
+ }
18956
+ async function discoverSessionFiles() {
18957
+ return (await discoverSessionJsonlPaths()).map((p) => p.path);
18627
18958
  }
18628
18959
  async function discoverSessions() {
18629
18960
  const paths = await discoverSessionJsonlPaths();
18630
18961
  const sessions = [];
18631
18962
  await Promise.all(
18632
- paths.map(async (filePath) => {
18633
- const session = await parseSessionFile(filePath);
18963
+ paths.map(async ({ path: filePath, origin }) => {
18964
+ const session = await parseSessionFile(filePath, origin);
18634
18965
  if (session) sessions.push(session);
18635
18966
  })
18636
18967
  );
@@ -18656,10 +18987,10 @@ async function watchClaudeSessionId(options2) {
18656
18987
  async function findLatestSessionId(options2) {
18657
18988
  const paths = await discoverSessionJsonlPaths();
18658
18989
  let latest = null;
18659
- for (const filePath of paths) {
18990
+ for (const { path: filePath, origin } of paths) {
18660
18991
  const createdMs = await createdSince(filePath, options2.sinceMs);
18661
18992
  if (createdMs === null) continue;
18662
- const meta = await parseSessionFile(filePath);
18993
+ const meta = await parseSessionFile(filePath, origin);
18663
18994
  if (!meta?.cwd || options2.isClaimed(meta.sessionId)) continue;
18664
18995
  if (path48.resolve(meta.cwd) !== path48.resolve(options2.cwd)) continue;
18665
18996
  if (!latest || createdMs > latest.createdMs)
@@ -18753,10 +19084,12 @@ var SessionManager = class {
18753
19084
  clients = /* @__PURE__ */ new Set();
18754
19085
  nextId = 1;
18755
19086
  shuttingDown = false;
19087
+ // why: dispatch calls windowsProxy.route() to forward windows-origin sessions
19088
+ windowsProxy = new WindowsProxy(this.clients, () => this.notify());
18756
19089
  addClient(client) {
18757
19090
  this.clients.add(client);
18758
19091
  this.onIdleChange?.(this.isIdle());
18759
- greetClient(client, this.sessions, () => this.listSessions());
19092
+ greetClient(client, this.sessions, this.listSessions, this.windowsProxy);
18760
19093
  }
18761
19094
  removeClient(client) {
18762
19095
  this.clients.delete(client);
@@ -18825,22 +19158,24 @@ var SessionManager = class {
18825
19158
  setAutoAdvance(id, enabled) {
18826
19159
  if (setAutoAdvance(this.sessions, id, enabled)) this.notify();
18827
19160
  }
18828
- listSessions() {
18829
- return [...this.sessions.values()].map(toSessionInfo);
18830
- }
19161
+ listSessions = () => {
19162
+ const local = [...this.sessions.values()].map(toSessionInfo);
19163
+ return local.concat(this.windowsProxy.sessions());
19164
+ };
18831
19165
  notify = () => {
18832
19166
  if (this.shuttingDown) return;
18833
- broadcastSessions(this.sessions, this.clients);
19167
+ const windows = this.windowsProxy.sessions();
19168
+ broadcastSessions(this.sessions, this.clients, windows);
18834
19169
  this.onIdleChange?.(this.isIdle());
18835
19170
  };
18836
19171
  };
18837
19172
 
18838
19173
  // src/commands/sessions/daemon/startDaemonServer.ts
18839
19174
  import { unlinkSync as unlinkSync19 } from "fs";
18840
- import * as net2 from "net";
19175
+ import * as net3 from "net";
18841
19176
 
18842
19177
  // src/commands/sessions/daemon/handleConnection.ts
18843
- import { createInterface as createInterface5 } from "readline";
19178
+ import { createInterface as createInterface6 } from "readline";
18844
19179
 
18845
19180
  // src/commands/sessions/shared/parseTranscript.ts
18846
19181
  import * as fs28 from "fs";
@@ -18894,11 +19229,13 @@ function cleanUserText(value) {
18894
19229
  import * as path49 from "path";
18895
19230
  async function findSessionJsonlPath(sessionId) {
18896
19231
  const paths = await discoverSessionJsonlPaths();
18897
- const direct = paths.find((p) => path49.basename(p, ".jsonl") === sessionId);
18898
- if (direct) return direct;
19232
+ const direct = paths.find(
19233
+ (p) => path49.basename(p.path, ".jsonl") === sessionId
19234
+ );
19235
+ if (direct) return direct.path;
18899
19236
  for (const p of paths) {
18900
- const meta = await parseSessionFile(p);
18901
- if (meta?.sessionId === sessionId) return p;
19237
+ const meta = await parseSessionFile(p.path, p.origin);
19238
+ if (meta?.sessionId === sessionId) return p.path;
18902
19239
  }
18903
19240
  return null;
18904
19241
  }
@@ -18932,46 +19269,11 @@ function safeParse2(line) {
18932
19269
  }
18933
19270
 
18934
19271
  // src/commands/sessions/daemon/dispatchMessage.ts
18935
- function sendCreated(client, id) {
18936
- sendTo(client, { type: "created", sessionId: id });
18937
- }
18938
- function handleCreate(client, manager, data) {
18939
- sendCreated(
18940
- client,
18941
- manager.spawn(
18942
- data.prompt,
18943
- data.cwd
18944
- )
18945
- );
18946
- }
18947
- function handleCreateRun(client, manager, data) {
18948
- sendCreated(
18949
- client,
18950
- manager.spawnRun(
18951
- data.runName,
18952
- data.runArgs ?? [],
18953
- data.cwd
18954
- )
18955
- );
18956
- }
18957
- function handleCreateAssist(client, manager, data) {
18958
- sendCreated(
18959
- client,
18960
- manager.spawnAssist(
18961
- data.assistArgs ?? [],
18962
- data.cwd
18963
- )
18964
- );
18965
- }
18966
- function handleResume(client, manager, data) {
18967
- sendCreated(
18968
- client,
18969
- manager.resume(
18970
- data.sessionId,
18971
- data.cwd,
18972
- data.name
18973
- )
18974
- );
19272
+ function creator(spawn11) {
19273
+ return (client, m, d) => {
19274
+ if (m.windowsProxy.route(client, d)) return;
19275
+ sendTo(client, { type: "created", sessionId: spawn11(m, d) });
19276
+ };
18975
19277
  }
18976
19278
  function handleHistory(client) {
18977
19279
  discoverSessions().then(
@@ -18989,21 +19291,54 @@ function handleShutdown(client, manager) {
18989
19291
  sendTo(client, { type: "shutting-down" });
18990
19292
  setImmediate(() => process.exit(0));
18991
19293
  }
19294
+ function routed(local) {
19295
+ return (client, m, d) => {
19296
+ if (!m.windowsProxy.route(client, d)) local(client, m, d);
19297
+ };
19298
+ }
18992
19299
  var handlers = {
18993
19300
  ping: (client) => sendTo(client, { type: "pong", pid: process.pid }),
18994
- create: handleCreate,
18995
- "create-run": handleCreateRun,
18996
- "create-assist": handleCreateAssist,
18997
- resume: handleResume,
19301
+ hello: (client) => sendTo(client, buildHello()),
19302
+ create: creator(
19303
+ (m, d) => m.spawn(d.prompt, d.cwd)
19304
+ ),
19305
+ "create-run": creator(
19306
+ (m, d) => m.spawnRun(
19307
+ d.runName,
19308
+ d.runArgs ?? [],
19309
+ d.cwd
19310
+ )
19311
+ ),
19312
+ "create-assist": creator(
19313
+ (m, d) => m.spawnAssist(
19314
+ d.assistArgs ?? [],
19315
+ d.cwd
19316
+ )
19317
+ ),
19318
+ resume: creator(
19319
+ (m, d) => m.resume(
19320
+ d.sessionId,
19321
+ d.cwd,
19322
+ d.name
19323
+ )
19324
+ ),
18998
19325
  history: handleHistory,
18999
19326
  "fetch-transcript": handleFetchTranscript,
19000
19327
  shutdown: handleShutdown,
19001
- input: (_client, m, d) => m.writeToSession(d.sessionId, d.data),
19002
- resize: (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows),
19003
- retry: (_client, m, d) => m.retrySession(d.sessionId),
19004
- dismiss: (_client, m, d) => m.dismissSession(d.sessionId),
19005
- "set-autorun": (_client, m, d) => m.setAutoRun(d.sessionId, d.enabled),
19006
- "set-autoadvance": (_client, m, d) => m.setAutoAdvance(d.sessionId, d.enabled)
19328
+ input: routed(
19329
+ (_client, m, d) => m.writeToSession(d.sessionId, d.data)
19330
+ ),
19331
+ resize: routed(
19332
+ (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows)
19333
+ ),
19334
+ retry: routed((_client, m, d) => m.retrySession(d.sessionId)),
19335
+ dismiss: routed((_client, m, d) => m.dismissSession(d.sessionId)),
19336
+ "set-autorun": routed(
19337
+ (_client, m, d) => m.setAutoRun(d.sessionId, d.enabled)
19338
+ ),
19339
+ "set-autoadvance": routed(
19340
+ (_client, m, d) => m.setAutoAdvance(d.sessionId, d.enabled)
19341
+ )
19007
19342
  };
19008
19343
  function dispatchMessage(client, manager, data) {
19009
19344
  handlers[data.type]?.(client, manager, data);
@@ -19018,7 +19353,7 @@ function handleConnection(socket, manager) {
19018
19353
  }
19019
19354
  };
19020
19355
  manager.addClient(client);
19021
- const lines = createInterface5({ input: socket });
19356
+ const lines = createInterface6({ input: socket });
19022
19357
  lines.on("error", () => {
19023
19358
  });
19024
19359
  lines.on("line", (line) => {
@@ -19095,9 +19430,10 @@ function cleanupOwnedFiles() {
19095
19430
 
19096
19431
  // src/commands/sessions/daemon/startDaemonServer.ts
19097
19432
  function startDaemonServer(manager, checkAutoExit) {
19098
- const server = net2.createServer(
19433
+ const server = net3.createServer(
19099
19434
  (socket) => handleConnection(socket, manager)
19100
19435
  );
19436
+ if (process.platform === "win32") startWindowsBridge(manager);
19101
19437
  let retried = false;
19102
19438
  server.on("error", (e) => {
19103
19439
  if (e.code !== "EADDRINUSE" || retried) {
@@ -19109,6 +19445,17 @@ function startDaemonServer(manager, checkAutoExit) {
19109
19445
  });
19110
19446
  server.listen(daemonPaths.socket, () => onListening(manager, checkAutoExit));
19111
19447
  }
19448
+ function startWindowsBridge(manager) {
19449
+ const port = windowsDaemonPort();
19450
+ const bridge = net3.createServer(
19451
+ (socket) => handleConnection(socket, manager)
19452
+ );
19453
+ bridge.on(
19454
+ "error",
19455
+ (e) => daemonLog(`windows bridge error: ${e.message}`)
19456
+ );
19457
+ bridge.listen(port, () => daemonLog(`windows bridge listening on :${port}`));
19458
+ }
19112
19459
  async function recoverFromAddrInUse(server, manager, checkAutoExit) {
19113
19460
  if (await isDaemonRunning()) {
19114
19461
  daemonLog("another daemon owns the socket; exiting");
@@ -19286,7 +19633,7 @@ ${firstMessage}`);
19286
19633
 
19287
19634
  // src/commands/sessions/summarise/index.ts
19288
19635
  async function summarise4(options2) {
19289
- const files = await discoverSessionJsonlPaths();
19636
+ const files = await discoverSessionFiles();
19290
19637
  if (files.length === 0) {
19291
19638
  console.log(chalk161.yellow("No sessions found."));
19292
19639
  return;