adhdev 0.7.29 → 0.7.31

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
@@ -3044,7 +3044,6 @@ async function setupIdeInstance(ctx, opts) {
3044
3044
  sessionId: ideInstance.getInstanceId(),
3045
3045
  parentSessionId: null,
3046
3046
  providerType: ideType,
3047
- providerCategory: "ide",
3048
3047
  transport: "cdp-page",
3049
3048
  cdpManagerKey: managerKey,
3050
3049
  instanceKey: `ide:${managerKey}`
@@ -3059,7 +3058,6 @@ async function setupIdeInstance(ctx, opts) {
3059
3058
  sessionId: ext.getInstanceId(),
3060
3059
  parentSessionId: ideInstance.getInstanceId(),
3061
3060
  providerType: ext.type,
3062
- providerCategory: "extension",
3063
3061
  transport: "cdp-webview",
3064
3062
  cdpManagerKey: managerKey,
3065
3063
  instanceKey: `ide:${managerKey}`
@@ -3498,9 +3496,31 @@ function getCurrentManagerKey(h) {
3498
3496
  function getTargetedCliAdapter(h, args, providerType) {
3499
3497
  return h.getCliAdapter(args?.targetSessionId || providerType || h.currentSession?.providerType || h.currentManagerKey);
3500
3498
  }
3499
+ function getTargetTransport(h, provider) {
3500
+ if (h.currentSession?.transport) return h.currentSession.transport;
3501
+ switch (provider?.category) {
3502
+ case "cli":
3503
+ return "pty";
3504
+ case "acp":
3505
+ return "acp";
3506
+ case "extension":
3507
+ return "cdp-webview";
3508
+ case "ide":
3509
+ return "cdp-page";
3510
+ default:
3511
+ return null;
3512
+ }
3513
+ }
3514
+ function isCliLikeTransport(transport) {
3515
+ return transport === "pty" || transport === "acp";
3516
+ }
3517
+ function isExtensionTransport(transport) {
3518
+ return transport === "cdp-webview";
3519
+ }
3501
3520
  function buildRecentSendKey(h, args, provider, text) {
3521
+ const transport = getTargetTransport(h, provider) || "unknown";
3502
3522
  const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
3503
- return `${provider?.category || "unknown"}:${target}:${text.trim()}`;
3523
+ return `${transport}:${target}:${text.trim()}`;
3504
3524
  }
3505
3525
  function isRecentDuplicateSend(key) {
3506
3526
  const now = Date.now();
@@ -3526,25 +3546,25 @@ async function handleChatHistory(h, args) {
3526
3546
  }
3527
3547
  async function handleReadChat(h, args) {
3528
3548
  const provider = h.getProvider(args?.agentType);
3549
+ const transport = getTargetTransport(h, provider);
3529
3550
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
3530
- if (provider?.category === "cli" || provider?.category === "acp") {
3531
- const adapter = getTargetedCliAdapter(h, args, provider.type);
3551
+ if (isCliLikeTransport(transport)) {
3552
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
3532
3553
  if (adapter) {
3533
- _log(`${provider.category} adapter: ${adapter.cliType}`);
3554
+ _log(`${transport} adapter: ${adapter.cliType}`);
3534
3555
  const status = adapter.getStatus?.();
3535
3556
  if (status) {
3536
3557
  return {
3537
3558
  success: true,
3538
3559
  messages: status.messages || [],
3539
3560
  status: status.status,
3540
- activeModal: status.activeModal,
3541
- terminalHistory: status.terminalHistory || ""
3561
+ activeModal: status.activeModal
3542
3562
  };
3543
3563
  }
3544
3564
  }
3545
- return { success: false, error: `${provider.category} adapter not found` };
3565
+ return { success: false, error: `${transport} adapter not found` };
3546
3566
  }
3547
- if (provider?.category === "extension") {
3567
+ if (isExtensionTransport(transport)) {
3548
3568
  try {
3549
3569
  const evalResult = await h.evaluateProviderScript("readChat", void 0, 5e4);
3550
3570
  if (evalResult?.result) {
@@ -3558,7 +3578,7 @@ async function handleReadChat(h, args) {
3558
3578
  if (parsed && typeof parsed === "object") {
3559
3579
  _log(`Extension OK: ${parsed.messages?.length || 0} msgs`);
3560
3580
  h.historyWriter.appendNewMessages(
3561
- provider.type || "unknown_extension",
3581
+ provider?.type || "unknown_extension",
3562
3582
  parsed.messages || [],
3563
3583
  parsed.title,
3564
3584
  args?.targetSessionId
@@ -3574,7 +3594,7 @@ async function handleReadChat(h, args) {
3574
3594
  const parentSessionId = h.currentSession?.parentSessionId;
3575
3595
  if (cdp2 && parentSessionId) {
3576
3596
  const stream = await h.agentStream.collectActiveSession(cdp2, parentSessionId);
3577
- if (stream?.agentType !== provider.type) {
3597
+ if (stream?.agentType !== provider?.type) {
3578
3598
  return { success: true, messages: [], status: "idle" };
3579
3599
  }
3580
3600
  if (stream) {
@@ -3654,6 +3674,7 @@ async function handleSendChat(h, args) {
3654
3674
  if (!text) return { success: false, error: "text required" };
3655
3675
  const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
3656
3676
  const provider = h.getProvider(args?.agentType);
3677
+ const transport = getTargetTransport(h, provider);
3657
3678
  const dedupeKey = buildRecentSendKey(h, args, provider, text);
3658
3679
  const _logSendSuccess = (method, targetAgent) => {
3659
3680
  h.historyWriter.appendNewMessages(
@@ -3669,20 +3690,20 @@ async function handleSendChat(h, args) {
3669
3690
  _log(`Suppressed duplicate send for ${dedupeKey}`);
3670
3691
  return { success: true, sent: false, deduplicated: true };
3671
3692
  }
3672
- if (provider?.category === "cli" || provider?.category === "acp") {
3673
- const adapter = getTargetedCliAdapter(h, args, provider.type);
3693
+ if (isCliLikeTransport(transport)) {
3694
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
3674
3695
  if (adapter) {
3675
- _log(`${provider.category} adapter: ${adapter.cliType}`);
3696
+ _log(`${transport} adapter: ${adapter.cliType}`);
3676
3697
  try {
3677
3698
  await adapter.sendMessage(text);
3678
- return _logSendSuccess(`${provider.category}-adapter`, adapter.cliType);
3699
+ return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
3679
3700
  } catch (e) {
3680
- return { success: false, error: `${provider.category} send failed: ${e.message}` };
3701
+ return { success: false, error: `${transport} send failed: ${e.message}` };
3681
3702
  }
3682
3703
  }
3683
3704
  }
3684
- if (provider?.category === "extension") {
3685
- _log(`Extension: ${provider.type}`);
3705
+ if (isExtensionTransport(transport)) {
3706
+ _log(`Extension: ${provider?.type || "unknown_extension"}`);
3686
3707
  try {
3687
3708
  const evalResult = await h.evaluateProviderScript("sendMessage", { MESSAGE: text }, 3e4);
3688
3709
  if (evalResult?.result) {
@@ -3712,7 +3733,7 @@ async function handleSendChat(h, args) {
3712
3733
  return _logSendSuccess("agent-stream");
3713
3734
  }
3714
3735
  }
3715
- return { success: false, error: `Extension '${provider.type}' send failed` };
3736
+ return { success: false, error: `Extension '${provider?.type || "unknown_extension"}' send failed` };
3716
3737
  }
3717
3738
  const targetCdp = h.getCdp();
3718
3739
  if (!targetCdp?.isConnected) {
@@ -3838,7 +3859,8 @@ async function handleSendChat(h, args) {
3838
3859
  }
3839
3860
  async function handleListChats(h, args) {
3840
3861
  const provider = h.getProvider(args?.agentType);
3841
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
3862
+ const transport = getTargetTransport(h, provider);
3863
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
3842
3864
  try {
3843
3865
  const chats = await h.agentStream.listSessionChats(h.getCdp(), h.currentSession.sessionId);
3844
3866
  LOG.info("Command", `[list_chats] Extension: ${chats.length} chats`);
@@ -3890,8 +3912,9 @@ async function handleListChats(h, args) {
3890
3912
  }
3891
3913
  async function handleNewChat(h, args) {
3892
3914
  const provider = h.getProvider(args?.agentType);
3893
- if (provider?.category === "cli") {
3894
- const adapter = getTargetedCliAdapter(h, args, provider.type);
3915
+ const transport = getTargetTransport(h, provider);
3916
+ if (transport === "pty") {
3917
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
3895
3918
  if (!adapter) return { success: false, error: "CLI adapter not running" };
3896
3919
  if (typeof adapter.clearHistory === "function") {
3897
3920
  adapter.clearHistory();
@@ -3899,7 +3922,7 @@ async function handleNewChat(h, args) {
3899
3922
  }
3900
3923
  return { success: false, error: "new_chat not supported by this CLI provider" };
3901
3924
  }
3902
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
3925
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
3903
3926
  const ok = await h.agentStream.newSession(h.getCdp(), h.currentSession.sessionId);
3904
3927
  return { success: ok };
3905
3928
  }
@@ -3924,11 +3947,12 @@ async function handleNewChat(h, args) {
3924
3947
  }
3925
3948
  async function handleSwitchChat(h, args) {
3926
3949
  const provider = h.getProvider(args?.agentType);
3950
+ const transport = getTargetTransport(h, provider);
3927
3951
  const managerKey = getCurrentManagerKey(h);
3928
3952
  const sessionId = args?.sessionId || args?.id || args?.chatId;
3929
3953
  if (!sessionId) return { success: false, error: "sessionId required" };
3930
3954
  LOG.info("Command", `[switch_chat] sessionId=${sessionId}, manager=${managerKey}`);
3931
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
3955
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
3932
3956
  const ok = await h.agentStream.switchConversation(h.getCdp(), h.currentSession.sessionId, sessionId);
3933
3957
  return { success: ok, result: ok ? "switched" : "failed" };
3934
3958
  }
@@ -4018,9 +4042,10 @@ async function handleSwitchChat(h, args) {
4018
4042
  }
4019
4043
  async function handleSetMode(h, args) {
4020
4044
  const provider = h.getProvider(args?.agentType);
4045
+ const transport = getTargetTransport(h, provider);
4021
4046
  const mode = args?.mode || "agent";
4022
- if (provider?.category === "acp") {
4023
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4047
+ if (transport === "acp") {
4048
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4024
4049
  if (adapter) {
4025
4050
  const acpInstance = adapter._acpInstance;
4026
4051
  if (acpInstance && typeof acpInstance.onEvent === "function") {
@@ -4073,10 +4098,11 @@ async function handleSetMode(h, args) {
4073
4098
  }
4074
4099
  async function handleChangeModel(h, args) {
4075
4100
  const provider = h.getProvider(args?.agentType);
4101
+ const transport = getTargetTransport(h, provider);
4076
4102
  const model = args?.model;
4077
- LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} manager=${getCurrentManagerKey(h)} providerType=${getCurrentProviderType(h)}`);
4078
- if (provider?.category === "acp") {
4079
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4103
+ LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} transport=${transport} manager=${getCurrentManagerKey(h)} providerType=${getCurrentProviderType(h)}`);
4104
+ if (transport === "acp") {
4105
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4080
4106
  LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
4081
4107
  if (adapter) {
4082
4108
  const acpInstance = adapter._acpInstance;
@@ -4134,15 +4160,16 @@ async function handleSetThoughtLevel(h, args) {
4134
4160
  const value = args?.value;
4135
4161
  if (!configId || !value) return { success: false, error: "configId and value required" };
4136
4162
  const provider = h.getProvider(args?.agentType);
4137
- if (!provider || provider.category !== "acp") {
4163
+ const transport = getTargetTransport(h, provider);
4164
+ if (transport !== "acp") {
4138
4165
  return { success: false, error: "set_thought_level only for ACP providers" };
4139
4166
  }
4140
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4167
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4141
4168
  const acpInstance = adapter?._acpInstance;
4142
4169
  if (!acpInstance) return { success: false, error: "ACP instance not found" };
4143
4170
  try {
4144
4171
  await acpInstance.setConfigOption(configId, value);
4145
- LOG.info("Command", `[set_thought_level] ${configId}=${value} for ${provider.type}`);
4172
+ LOG.info("Command", `[set_thought_level] ${configId}=${value} for ${provider?.type || "unknown_acp"}`);
4146
4173
  return { success: true, configId, value };
4147
4174
  } catch (e) {
4148
4175
  return { success: false, error: e?.message };
@@ -4150,11 +4177,12 @@ async function handleSetThoughtLevel(h, args) {
4150
4177
  }
4151
4178
  async function handleResolveAction(h, args) {
4152
4179
  const provider = h.getProvider(args?.agentType);
4180
+ const transport = getTargetTransport(h, provider);
4153
4181
  const action = args?.action || "approve";
4154
4182
  const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
4155
4183
  LOG.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
4156
- if (provider?.category === "cli") {
4157
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4184
+ if (transport === "pty") {
4185
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4158
4186
  if (!adapter) return { success: false, error: "CLI adapter not running" };
4159
4187
  if (args?.data && typeof adapter.resolveAction === "function") {
4160
4188
  try {
@@ -4195,7 +4223,7 @@ async function handleResolveAction(h, args) {
4195
4223
  LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
4196
4224
  return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
4197
4225
  }
4198
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4226
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4199
4227
  const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
4200
4228
  return { success: ok };
4201
4229
  }
@@ -18428,21 +18456,39 @@ var init_xterm_backend = __esm({
18428
18456
 
18429
18457
  // ../../oss/packages/daemon-core/src/cli-adapters/terminal-screen.ts
18430
18458
  function createTerminalBackend(options, preference) {
18459
+ const ghosttyAvailable = isGhosttyVtBackendAvailable();
18431
18460
  if (preference === "ghostty-vt") {
18432
- return new GhosttyVtTerminalBackend(options);
18433
- }
18434
- if (preference === "auto" && isGhosttyVtBackendAvailable()) {
18435
- return new GhosttyVtTerminalBackend(options);
18436
- }
18437
- return new XtermTerminalBackend(options);
18461
+ const backend2 = new GhosttyVtTerminalBackend(options);
18462
+ logTerminalBackendSelection(preference, ghosttyAvailable, backend2.kind);
18463
+ return backend2;
18464
+ }
18465
+ if (preference === "auto" && ghosttyAvailable) {
18466
+ const backend2 = new GhosttyVtTerminalBackend(options);
18467
+ logTerminalBackendSelection(preference, ghosttyAvailable, backend2.kind);
18468
+ return backend2;
18469
+ }
18470
+ const backend = new XtermTerminalBackend(options);
18471
+ logTerminalBackendSelection(preference, ghosttyAvailable, backend.kind);
18472
+ return backend;
18473
+ }
18474
+ function logTerminalBackendSelection(preference, ghosttyAvailable, backendKind) {
18475
+ const key = `${preference}:${ghosttyAvailable}:${backendKind}`;
18476
+ if (loggedTerminalBackends.has(key)) return;
18477
+ loggedTerminalBackends.add(key);
18478
+ LOG.info(
18479
+ "Terminal",
18480
+ `[terminal-screen] backend=${backendKind} preference=${preference} ghosttyAvailable=${ghosttyAvailable}`
18481
+ );
18438
18482
  }
18439
- var DEFAULT_SCROLLBACK, TerminalScreen;
18483
+ var DEFAULT_SCROLLBACK, loggedTerminalBackends, TerminalScreen;
18440
18484
  var init_terminal_screen = __esm({
18441
18485
  "../../oss/packages/daemon-core/src/cli-adapters/terminal-screen.ts"() {
18442
18486
  "use strict";
18487
+ init_logger();
18443
18488
  init_ghostty_vt_backend();
18444
18489
  init_xterm_backend();
18445
18490
  DEFAULT_SCROLLBACK = 2e3;
18491
+ loggedTerminalBackends = /* @__PURE__ */ new Set();
18446
18492
  TerminalScreen = class {
18447
18493
  backendKind;
18448
18494
  rows;
@@ -37257,7 +37303,6 @@ var init_cli_manager = __esm({
37257
37303
  sessionId: cliInstance.instanceId,
37258
37304
  parentSessionId: null,
37259
37305
  providerType: normalizedType,
37260
- providerCategory: "cli",
37261
37306
  transport: "pty",
37262
37307
  adapterKey: key,
37263
37308
  instanceKey: key
@@ -37307,7 +37352,6 @@ ${installInfo}`
37307
37352
  sessionId,
37308
37353
  parentSessionId: null,
37309
37354
  providerType: normalizedType,
37310
- providerCategory: "acp",
37311
37355
  transport: "acp",
37312
37356
  adapterKey: key,
37313
37357
  instanceKey: key
@@ -37837,12 +37881,12 @@ var init_manager2 = __esm({
37837
37881
  this.logFn(`[AgentStream] Active session (${parentSessionId}): ${sessionId || "none"}`);
37838
37882
  }
37839
37883
  resolveSessionIdForTarget(parentSessionId, agentType) {
37840
- const child = (this.sessionRegistry?.listChildren(parentSessionId) || []).find((entry) => entry.providerCategory === "extension" && entry.providerType === agentType);
37884
+ const child = (this.sessionRegistry?.listChildren(parentSessionId) || []).find((entry) => entry.transport === "cdp-webview" && entry.providerType === agentType);
37841
37885
  return child?.sessionId || null;
37842
37886
  }
37843
37887
  async connectManagedSession(cdp, parentSessionId, runtimeSessionId) {
37844
37888
  const target = this.getSessionTarget(runtimeSessionId);
37845
- if (!target || target.providerCategory !== "extension") return null;
37889
+ if (!target || target.transport !== "cdp-webview") return null;
37846
37890
  const adapter = this.adaptersByType.get(target.providerType);
37847
37891
  if (!adapter) return null;
37848
37892
  const targets = await cdp.discoverAgentWebviews();
@@ -38141,7 +38185,6 @@ var init_poller = __esm({
38141
38185
  sessionId: extInstance.getInstanceId(),
38142
38186
  parentSessionId,
38143
38187
  providerType: extType,
38144
- providerCategory: "extension",
38145
38188
  transport: "cdp-webview",
38146
38189
  cdpManagerKey: ideType,
38147
38190
  instanceKey: `ide:${ideType}`
@@ -38379,7 +38422,6 @@ var init_provider_instance_manager = __esm({
38379
38422
  providerType,
38380
38423
  instanceId: state.instanceId,
38381
38424
  targetSessionId: state.instanceId,
38382
- providerCategory: state.category,
38383
38425
  workspaceName: state.workspace || void 0,
38384
38426
  ...extra
38385
38427
  });
@@ -43834,10 +43876,6 @@ var init_daemon_p2p = __esm({
43834
43876
  ptyResizeHandler = null;
43835
43877
  screenshotStartHandler = null;
43836
43878
  _ssDebugDone = false;
43837
- // PTY scrollback buffer per cliType (send recent output on reconnect)
43838
- ptyScrollback = /* @__PURE__ */ new Map();
43839
- PTY_SCROLLBACK_MAX = 64 * 1024;
43840
- // 64KB per CLI
43841
43879
  get screenshotActive() {
43842
43880
  for (const peer of this.peers.values()) {
43843
43881
  if (peer.screenshotActive && peer.state === "connected") return true;
@@ -44184,7 +44222,6 @@ ${e?.stack || ""}`);
44184
44222
  log(`Screenshots auto-starting for peer ${pid} (was waiting for channel open)`);
44185
44223
  }
44186
44224
  }
44187
- setTimeout(() => this.sendPtyScrollback(pid), 100);
44188
44225
  });
44189
44226
  dataCh.onClosed(() => {
44190
44227
  log(`Data channel CLOSED for peer ${pid}`);
@@ -44315,12 +44352,6 @@ ${e?.stack || ""}`);
44315
44352
  }
44316
44353
  /** Broadcast PTY output to all connected peers */
44317
44354
  broadcastPtyOutput(cliType, data) {
44318
- const prev = this.ptyScrollback.get(cliType) || "";
44319
- const updated = prev + data;
44320
- this.ptyScrollback.set(
44321
- cliType,
44322
- updated.length > this.PTY_SCROLLBACK_MAX ? updated.slice(-this.PTY_SCROLLBACK_MAX) : updated
44323
- );
44324
44355
  const msg = JSON.stringify({ type: "pty_output", cliType, data });
44325
44356
  let sentAny = false;
44326
44357
  for (const peer of this.peers.values()) {
@@ -44333,24 +44364,6 @@ ${e?.stack || ""}`);
44333
44364
  }
44334
44365
  return sentAny;
44335
44366
  }
44336
- /** Send scrollback on peer connect */
44337
- sendPtyScrollback(peerId) {
44338
- const peer = this.peers.get(peerId);
44339
- if (!peer?.dataChannel) return;
44340
- for (const [cliType, buffer] of this.ptyScrollback) {
44341
- if (!buffer) continue;
44342
- try {
44343
- peer.dataChannel.sendMessage(JSON.stringify({
44344
- type: "pty_output",
44345
- cliType,
44346
- data: buffer,
44347
- scrollback: true
44348
- }));
44349
- logDebug(`Sent PTY scrollback to peer ${peerId}: ${cliType} (${buffer.length} bytes)`);
44350
- } catch {
44351
- }
44352
- }
44353
- }
44354
44367
  sendScreenshot(base64Data) {
44355
44368
  const buffer = Buffer.from(base64Data, "base64");
44356
44369
  return this.sendScreenshotBuffer(buffer);
@@ -44915,11 +44928,12 @@ var init_adhdev_daemon = __esm({
44915
44928
  init_daemon_p2p();
44916
44929
  init_screenshot_controller();
44917
44930
  init_session_host();
44931
+ init_dist();
44918
44932
  os19 = __toESM(require("os"));
44919
44933
  fs14 = __toESM(require("fs"));
44920
44934
  path17 = __toESM(require("path"));
44921
44935
  import_chalk2 = __toESM(require("chalk"));
44922
- pkgVersion = "0.7.29";
44936
+ pkgVersion = "0.7.31";
44923
44937
  if (pkgVersion === "unknown") {
44924
44938
  try {
44925
44939
  const possiblePaths = [
@@ -44957,6 +44971,7 @@ var init_adhdev_daemon = __esm({
44957
44971
  screenshotController = null;
44958
44972
  statusReporter = null;
44959
44973
  components = null;
44974
+ sessionHostEndpoint = null;
44960
44975
  running = false;
44961
44976
  localPort;
44962
44977
  ideType = "unknown";
@@ -44978,200 +44993,210 @@ ${err?.stack || ""}`);
44978
44993
  });
44979
44994
  this.localPort = options.localPort || DEFAULT_DAEMON_PORT;
44980
44995
  const workingDir = options.workingDir || process.cwd();
44981
- if (isDaemonRunning()) {
44982
- console.log(import_chalk2.default.yellow("\n\u26A0 ADHDev Daemon is already running."));
44983
- console.log(import_chalk2.default.gray(` Stop with: adhdev daemon:stop
44996
+ let pidWritten = false;
44997
+ try {
44998
+ if (isDaemonRunning()) {
44999
+ console.log(import_chalk2.default.yellow("\n\u26A0 ADHDev Daemon is already running."));
45000
+ console.log(import_chalk2.default.gray(` Stop with: adhdev daemon:stop
44984
45001
  `));
44985
- return;
44986
- }
44987
- writeDaemonPid(process.pid);
44988
- const config2 = loadConfig();
44989
- const authToken = config2.machineSecret;
44990
- if (!authToken) {
44991
- console.log(import_chalk2.default.red("\n\u2717 No machine secret found."));
44992
- if (config2.connectionToken) {
44993
- console.log(import_chalk2.default.yellow(" Legacy connectionToken detected \u2014 please re-run setup."));
44994
- }
44995
- console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
44996
- process.exit(1);
44997
- }
44998
- const sessionHostEndpoint = await ensureSessionHostReady2();
44999
- this.components = await initDaemonComponents({
45000
- providerLogFn: LOG.forComponent("Provider").asLogFn(),
45001
- cliManagerDeps: {
45002
- getServerConn: () => this.serverConn,
45003
- getP2p: () => this.p2p,
45004
- onStatusChange: () => this.statusReporter?.onStatusChange(),
45005
- removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
45006
- createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => new SessionHostPtyTransportFactory({
45007
- endpoint: sessionHostEndpoint,
45008
- clientId: `daemon_${config2.machineId}`,
45009
- runtimeId,
45010
- providerType,
45011
- workspace,
45012
- appName: process.env.ADHDEV_SESSION_HOST_NAME || "adhdev",
45013
- meta: {
45014
- cliArgs
45015
- },
45016
- attachExisting
45017
- }),
45018
- listHostedCliRuntimes: async () => listHostedCliRuntimes2(sessionHostEndpoint)
45019
- },
45020
- enabledIdes: config2.enabledIdes,
45021
- onStatusChange: () => this.statusReporter?.onStatusChange(),
45022
- onPostChatCommand: () => {
45023
- setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
45024
- setTimeout(() => this.statusReporter?.throttledReport(), 3e3);
45025
- },
45026
- getCdpLogFn: (ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn(),
45027
- onCdpManagerSetup: (ideType) => {
45028
- if (this.ideType === "unknown") this.ideType = ideType;
45029
- },
45030
- onStreamsUpdated: (ideType, streams) => {
45031
- if (!this.components) return;
45032
- forwardAgentStreamsToIdeInstance(this.components.instanceManager, ideType, streams);
45033
- }
45034
- });
45035
- await this.components.cliManager.restoreHostedSessions();
45036
- this.components.providerLoader.fetchLatest().then(({ updated }) => {
45037
- if (updated) {
45038
- this.components.providerLoader.reload();
45039
- this.components.providerLoader.registerToDetector();
45040
- LOG.info("Provider", "Providers auto-updated from upstream");
45041
- }
45042
- }).catch(() => {
45043
- });
45044
- const instanceId = `daemon_${config2.machineId}`;
45045
- this.serverConn = new ServerConnection({
45046
- serverUrl: options.serverUrl || config2.serverUrl,
45047
- token: authToken,
45048
- daemonVersion: pkgVersion,
45049
- cliInfo: {
45050
- type: "adhdev-daemon",
45051
- version: pkgVersion,
45052
- platform: os19.platform(),
45053
- hostname: os19.hostname(),
45054
- machineId: config2.machineId,
45055
- instanceId
45002
+ return;
45056
45003
  }
45057
- });
45058
- this.p2p = new DaemonP2PSender(this.serverConn);
45059
- if (this.p2p.isAvailable) {
45060
- console.log(import_chalk2.default.green(" \u{1F517} P2P available (node-datachannel)"));
45061
- this.p2p.onInput(async (event) => {
45062
- return this.components.commandHandler.handle("cdp_remote_action", event);
45063
- });
45064
- this.p2p.onCommand(async (cmdType, data, id) => {
45065
- return this.handleP2PCommand(cmdType, data);
45066
- });
45067
- this.p2p.onFileRequest(async (req) => {
45068
- const handler = this.components.commandHandler;
45069
- if (req.type === "read") {
45070
- const result = await handler.handle("file_read", { path: req.path });
45071
- return { id: req.id, success: result.success, content: result.content, error: result.error };
45072
- } else if (req.type === "write") {
45073
- const result = await handler.handle("file_write", { path: req.path, content: req.content });
45074
- return { id: req.id, success: result.success, error: result.error };
45075
- } else {
45076
- const result = await handler.handle("file_list", { path: req.path });
45077
- return { id: req.id, success: result.success, entries: result.files, error: result.error };
45004
+ writeDaemonPid(process.pid);
45005
+ pidWritten = true;
45006
+ const config2 = loadConfig();
45007
+ const authToken = config2.machineSecret;
45008
+ if (!authToken) {
45009
+ console.log(import_chalk2.default.red("\n\u2717 No machine secret found."));
45010
+ if (config2.connectionToken) {
45011
+ console.log(import_chalk2.default.yellow(" Legacy connectionToken detected \u2014 please re-run setup."));
45012
+ }
45013
+ console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
45014
+ process.exit(1);
45015
+ }
45016
+ const sessionHostEndpoint = await ensureSessionHostReady2();
45017
+ this.sessionHostEndpoint = sessionHostEndpoint;
45018
+ this.components = await initDaemonComponents({
45019
+ providerLogFn: LOG.forComponent("Provider").asLogFn(),
45020
+ cliManagerDeps: {
45021
+ getServerConn: () => this.serverConn,
45022
+ getP2p: () => this.p2p,
45023
+ onStatusChange: () => this.statusReporter?.onStatusChange(),
45024
+ removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
45025
+ createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => new SessionHostPtyTransportFactory({
45026
+ endpoint: sessionHostEndpoint,
45027
+ clientId: `daemon_${config2.machineId}`,
45028
+ runtimeId,
45029
+ providerType,
45030
+ workspace,
45031
+ appName: process.env.ADHDEV_SESSION_HOST_NAME || "adhdev",
45032
+ meta: {
45033
+ cliArgs
45034
+ },
45035
+ attachExisting
45036
+ }),
45037
+ listHostedCliRuntimes: async () => listHostedCliRuntimes2(sessionHostEndpoint)
45038
+ },
45039
+ enabledIdes: config2.enabledIdes,
45040
+ onStatusChange: () => this.statusReporter?.onStatusChange(),
45041
+ onPostChatCommand: () => {
45042
+ setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
45043
+ setTimeout(() => this.statusReporter?.throttledReport(), 3e3);
45044
+ },
45045
+ getCdpLogFn: (ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn(),
45046
+ onCdpManagerSetup: (ideType) => {
45047
+ if (this.ideType === "unknown") this.ideType = ideType;
45048
+ },
45049
+ onStreamsUpdated: (ideType, streams) => {
45050
+ if (!this.components) return;
45051
+ forwardAgentStreamsToIdeInstance(this.components.instanceManager, ideType, streams);
45078
45052
  }
45079
45053
  });
45080
- this.p2p.onPtyInput((cliId, data) => {
45081
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45082
- if (found && typeof found.adapter.writeRaw === "function") {
45083
- found.adapter.writeRaw(data);
45084
- }
45054
+ await this.components.cliManager.restoreHostedSessions();
45055
+ this.components.providerLoader.fetchLatest().then(({ updated }) => {
45056
+ if (updated) {
45057
+ this.components.providerLoader.reload();
45058
+ this.components.providerLoader.registerToDetector();
45059
+ LOG.info("Provider", "Providers auto-updated from upstream");
45060
+ }
45061
+ }).catch(() => {
45085
45062
  });
45086
- this.p2p.onPtyResize((cliId, cols, rows) => {
45087
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45088
- if (found && typeof found.adapter.resize === "function") {
45089
- found.adapter.resize(cols, rows);
45063
+ const instanceId = `daemon_${config2.machineId}`;
45064
+ this.serverConn = new ServerConnection({
45065
+ serverUrl: options.serverUrl || config2.serverUrl,
45066
+ token: authToken,
45067
+ daemonVersion: pkgVersion,
45068
+ cliInfo: {
45069
+ type: "adhdev-daemon",
45070
+ version: pkgVersion,
45071
+ platform: os19.platform(),
45072
+ hostname: os19.hostname(),
45073
+ machineId: config2.machineId,
45074
+ instanceId
45090
45075
  }
45091
45076
  });
45092
- this.p2p.onStateChange((state) => {
45093
- if (state === "connected") {
45094
- LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
45095
- this.statusReporter?.resetP2PHash();
45096
- this.statusReporter?.sendUnifiedStatusReport().catch((e) => LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
45097
- setTimeout(() => {
45077
+ this.p2p = new DaemonP2PSender(this.serverConn);
45078
+ if (this.p2p.isAvailable) {
45079
+ console.log(import_chalk2.default.green(" \u{1F517} P2P available (node-datachannel)"));
45080
+ this.p2p.onInput(async (event) => {
45081
+ return this.components.commandHandler.handle("cdp_remote_action", event);
45082
+ });
45083
+ this.p2p.onCommand(async (cmdType, data, id) => {
45084
+ return this.handleP2PCommand(cmdType, data);
45085
+ });
45086
+ this.p2p.onFileRequest(async (req) => {
45087
+ const handler = this.components.commandHandler;
45088
+ if (req.type === "read") {
45089
+ const result = await handler.handle("file_read", { path: req.path });
45090
+ return { id: req.id, success: result.success, content: result.content, error: result.error };
45091
+ } else if (req.type === "write") {
45092
+ const result = await handler.handle("file_write", { path: req.path, content: req.content });
45093
+ return { id: req.id, success: result.success, error: result.error };
45094
+ } else {
45095
+ const result = await handler.handle("file_list", { path: req.path });
45096
+ return { id: req.id, success: result.success, entries: result.files, error: result.error };
45097
+ }
45098
+ });
45099
+ this.p2p.onPtyInput((cliId, data) => {
45100
+ const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45101
+ if (found && typeof found.adapter.writeRaw === "function") {
45102
+ found.adapter.writeRaw(data);
45103
+ }
45104
+ });
45105
+ this.p2p.onPtyResize((cliId, cols, rows) => {
45106
+ const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45107
+ if (found && typeof found.adapter.resize === "function") {
45108
+ found.adapter.resize(cols, rows);
45109
+ }
45110
+ });
45111
+ this.p2p.onStateChange((state) => {
45112
+ if (state === "connected") {
45113
+ LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
45098
45114
  this.statusReporter?.resetP2PHash();
45099
- this.statusReporter?.sendUnifiedStatusReport().catch(() => {
45100
- });
45101
- }, 2e3);
45115
+ this.statusReporter?.sendUnifiedStatusReport().catch((e) => LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
45116
+ setTimeout(() => {
45117
+ this.statusReporter?.resetP2PHash();
45118
+ this.statusReporter?.sendUnifiedStatusReport().catch(() => {
45119
+ });
45120
+ }, 2e3);
45121
+ }
45122
+ });
45123
+ const planLimits = this.serverConn.getPlanLimits();
45124
+ this.screenshotController = new ScreenshotController({
45125
+ isRunning: () => this.running,
45126
+ isScreenshotActive: () => this.p2p?.screenshotActive ?? false,
45127
+ getScreenshotIdeType: () => this.p2p?.screenshotIdeType,
45128
+ isUsingRelay: () => this.p2p?.isUsingRelay ?? false,
45129
+ hasAnyNeedingFirstFrame: () => this.p2p?.hasAnyNeedingFirstFrame() ?? false,
45130
+ getCdp: (ideType) => {
45131
+ if (ideType) return this.getCdpFor(ideType);
45132
+ LOG.warn("P2P", "Screenshot requested without ideType \u2014 cannot determine target IDE. Skipping frame.");
45133
+ return null;
45134
+ },
45135
+ sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf)
45136
+ }, planLimits ?? void 0);
45137
+ this.screenshotController.start();
45138
+ this.p2p.onScreenshotStart(() => this.screenshotController?.triggerImmediate());
45139
+ } else {
45140
+ console.log(import_chalk2.default.gray(" \u26A0 P2P unavailable \u2014 using server relay"));
45141
+ }
45142
+ this.registerServerHandlers();
45143
+ this.serverConn.on("auth_ok", (msg) => {
45144
+ const serverNickname = msg.payload?.machineNickname;
45145
+ if (serverNickname === void 0) return;
45146
+ const nextNickname = typeof serverNickname === "string" && serverNickname.trim() ? serverNickname.trim() : null;
45147
+ const latestConfig = loadConfig();
45148
+ if ((latestConfig.machineNickname || null) === nextNickname) return;
45149
+ latestConfig.machineNickname = nextNickname;
45150
+ saveConfig(latestConfig);
45151
+ LOG.info("Server", `[ServerConn] Synced machine nickname from server: ${nextNickname || "(cleared)"}`);
45152
+ this.statusReporter?.throttledReport();
45153
+ });
45154
+ this.serverConn.onStateChange((state) => {
45155
+ if (state === "connected") {
45156
+ console.log(import_chalk2.default.green(" \u{1F4E1} Connected to ADHDev server"));
45157
+ this.statusReporter?.sendUnifiedStatusReport();
45158
+ } else if (state === "disconnected") {
45159
+ console.log(import_chalk2.default.yellow(" \u26A0 Server disconnected, will reconnect..."));
45102
45160
  }
45103
45161
  });
45104
- const planLimits = this.serverConn.getPlanLimits();
45105
- this.screenshotController = new ScreenshotController({
45106
- isRunning: () => this.running,
45107
- isScreenshotActive: () => this.p2p?.screenshotActive ?? false,
45108
- getScreenshotIdeType: () => this.p2p?.screenshotIdeType,
45109
- isUsingRelay: () => this.p2p?.isUsingRelay ?? false,
45110
- hasAnyNeedingFirstFrame: () => this.p2p?.hasAnyNeedingFirstFrame() ?? false,
45111
- getCdp: (ideType) => {
45112
- if (ideType) return this.getCdpFor(ideType);
45113
- LOG.warn("P2P", "Screenshot requested without ideType \u2014 cannot determine target IDE. Skipping frame.");
45114
- return null;
45115
- },
45116
- sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf)
45117
- }, planLimits ?? void 0);
45118
- this.screenshotController.start();
45119
- this.p2p.onScreenshotStart(() => this.screenshotController?.triggerImmediate());
45120
- } else {
45121
- console.log(import_chalk2.default.gray(" \u26A0 P2P unavailable \u2014 using server relay"));
45122
- }
45123
- this.registerServerHandlers();
45124
- this.serverConn.on("auth_ok", (msg) => {
45125
- const serverNickname = msg.payload?.machineNickname;
45126
- if (serverNickname === void 0) return;
45127
- const nextNickname = typeof serverNickname === "string" && serverNickname.trim() ? serverNickname.trim() : null;
45128
- const latestConfig = loadConfig();
45129
- if ((latestConfig.machineNickname || null) === nextNickname) return;
45130
- latestConfig.machineNickname = nextNickname;
45131
- saveConfig(latestConfig);
45132
- LOG.info("Server", `[ServerConn] Synced machine nickname from server: ${nextNickname || "(cleared)"}`);
45133
- this.statusReporter?.throttledReport();
45134
- });
45135
- this.serverConn.onStateChange((state) => {
45136
- if (state === "connected") {
45137
- console.log(import_chalk2.default.green(" \u{1F4E1} Connected to ADHDev server"));
45138
- this.statusReporter?.sendUnifiedStatusReport();
45139
- } else if (state === "disconnected") {
45140
- console.log(import_chalk2.default.yellow(" \u26A0 Server disconnected, will reconnect..."));
45141
- }
45142
- });
45143
- await this.serverConn.connect();
45144
- this.statusReporter = new DaemonStatusReporter({
45145
- serverConn: this.serverConn,
45146
- cdpManagers: this.components.cdpManagers,
45147
- p2p: this.p2p,
45148
- providerLoader: this.components.providerLoader,
45149
- detectedIdes: this.components.detectedIdes.value,
45150
- instanceId,
45151
- daemonVersion: pkgVersion,
45152
- instanceManager: this.components.instanceManager,
45153
- getScreenshotUsage: () => this.screenshotController?.getUsageStats() || null
45154
- });
45155
- this.statusReporter.startReporting();
45156
- this.components.instanceManager.onEvent((event) => {
45157
- this.statusReporter?.emitStatusEvent(event);
45158
- });
45159
- this.running = true;
45160
- process.on("SIGINT", () => this.stop());
45161
- process.on("SIGTERM", () => this.stop());
45162
- if (options.dev && this.components) {
45163
- const devServer = new DevServer({
45164
- providerLoader: this.components.providerLoader,
45162
+ await this.serverConn.connect();
45163
+ this.statusReporter = new DaemonStatusReporter({
45164
+ serverConn: this.serverConn,
45165
45165
  cdpManagers: this.components.cdpManagers,
45166
+ p2p: this.p2p,
45167
+ providerLoader: this.components.providerLoader,
45168
+ detectedIdes: this.components.detectedIdes.value,
45169
+ instanceId,
45170
+ daemonVersion: pkgVersion,
45166
45171
  instanceManager: this.components.instanceManager,
45167
- cliManager: this.components.cliManager
45172
+ getScreenshotUsage: () => this.screenshotController?.getUsageStats() || null
45168
45173
  });
45169
- await devServer.start();
45170
- }
45171
- this.printBanner(options, config2.serverUrl);
45172
- if (options.foreground) {
45173
- await new Promise(() => {
45174
+ this.statusReporter.startReporting();
45175
+ this.components.instanceManager.onEvent((event) => {
45176
+ this.statusReporter?.emitStatusEvent(event);
45174
45177
  });
45178
+ this.running = true;
45179
+ process.on("SIGINT", () => this.stop());
45180
+ process.on("SIGTERM", () => this.stop());
45181
+ if (options.dev && this.components) {
45182
+ const devServer = new DevServer({
45183
+ providerLoader: this.components.providerLoader,
45184
+ cdpManagers: this.components.cdpManagers,
45185
+ instanceManager: this.components.instanceManager,
45186
+ cliManager: this.components.cliManager
45187
+ });
45188
+ await devServer.start();
45189
+ }
45190
+ this.printBanner(options, config2.serverUrl);
45191
+ if (options.foreground) {
45192
+ await new Promise(() => {
45193
+ });
45194
+ }
45195
+ } catch (error48) {
45196
+ if (!this.running && pidWritten) {
45197
+ removeDaemonPid();
45198
+ }
45199
+ throw error48;
45175
45200
  }
45176
45201
  }
45177
45202
  printBanner(options, serverUrl) {
@@ -45251,6 +45276,26 @@ ${err?.stack || ""}`);
45251
45276
  const cmdStart = Date.now();
45252
45277
  try {
45253
45278
  switch (cmdType) {
45279
+ case "get_runtime_snapshot": {
45280
+ const sessionId = typeof data.sessionId === "string" ? data.sessionId : "";
45281
+ if (!sessionId) return { success: false, error: "sessionId is required" };
45282
+ if (!this.sessionHostEndpoint) return { success: false, error: "Session host unavailable" };
45283
+ const client = new SessionHostClient({ endpoint: this.sessionHostEndpoint });
45284
+ try {
45285
+ await client.connect();
45286
+ const snapshot = await client.request({
45287
+ type: "get_snapshot",
45288
+ payload: { sessionId }
45289
+ });
45290
+ if (!snapshot.success || !snapshot.result) {
45291
+ return { success: false, error: snapshot.error || "Runtime snapshot unavailable" };
45292
+ }
45293
+ return { success: true, result: snapshot.result };
45294
+ } finally {
45295
+ await client.close().catch(() => {
45296
+ });
45297
+ }
45298
+ }
45254
45299
  case "get_cli_history": {
45255
45300
  const config2 = loadConfig();
45256
45301
  logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", success: true, durationMs: Date.now() - cmdStart });