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/cli/index.js CHANGED
@@ -3051,7 +3051,6 @@ async function setupIdeInstance(ctx, opts) {
3051
3051
  sessionId: ideInstance.getInstanceId(),
3052
3052
  parentSessionId: null,
3053
3053
  providerType: ideType,
3054
- providerCategory: "ide",
3055
3054
  transport: "cdp-page",
3056
3055
  cdpManagerKey: managerKey,
3057
3056
  instanceKey: `ide:${managerKey}`
@@ -3066,7 +3065,6 @@ async function setupIdeInstance(ctx, opts) {
3066
3065
  sessionId: ext.getInstanceId(),
3067
3066
  parentSessionId: ideInstance.getInstanceId(),
3068
3067
  providerType: ext.type,
3069
- providerCategory: "extension",
3070
3068
  transport: "cdp-webview",
3071
3069
  cdpManagerKey: managerKey,
3072
3070
  instanceKey: `ide:${managerKey}`
@@ -3672,9 +3670,31 @@ function getCurrentManagerKey(h) {
3672
3670
  function getTargetedCliAdapter(h, args, providerType) {
3673
3671
  return h.getCliAdapter(args?.targetSessionId || providerType || h.currentSession?.providerType || h.currentManagerKey);
3674
3672
  }
3673
+ function getTargetTransport(h, provider) {
3674
+ if (h.currentSession?.transport) return h.currentSession.transport;
3675
+ switch (provider?.category) {
3676
+ case "cli":
3677
+ return "pty";
3678
+ case "acp":
3679
+ return "acp";
3680
+ case "extension":
3681
+ return "cdp-webview";
3682
+ case "ide":
3683
+ return "cdp-page";
3684
+ default:
3685
+ return null;
3686
+ }
3687
+ }
3688
+ function isCliLikeTransport(transport) {
3689
+ return transport === "pty" || transport === "acp";
3690
+ }
3691
+ function isExtensionTransport(transport) {
3692
+ return transport === "cdp-webview";
3693
+ }
3675
3694
  function buildRecentSendKey(h, args, provider, text) {
3695
+ const transport = getTargetTransport(h, provider) || "unknown";
3676
3696
  const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
3677
- return `${provider?.category || "unknown"}:${target}:${text.trim()}`;
3697
+ return `${transport}:${target}:${text.trim()}`;
3678
3698
  }
3679
3699
  function isRecentDuplicateSend(key) {
3680
3700
  const now = Date.now();
@@ -3700,25 +3720,25 @@ async function handleChatHistory(h, args) {
3700
3720
  }
3701
3721
  async function handleReadChat(h, args) {
3702
3722
  const provider = h.getProvider(args?.agentType);
3723
+ const transport = getTargetTransport(h, provider);
3703
3724
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
3704
- if (provider?.category === "cli" || provider?.category === "acp") {
3705
- const adapter = getTargetedCliAdapter(h, args, provider.type);
3725
+ if (isCliLikeTransport(transport)) {
3726
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
3706
3727
  if (adapter) {
3707
- _log(`${provider.category} adapter: ${adapter.cliType}`);
3728
+ _log(`${transport} adapter: ${adapter.cliType}`);
3708
3729
  const status = adapter.getStatus?.();
3709
3730
  if (status) {
3710
3731
  return {
3711
3732
  success: true,
3712
3733
  messages: status.messages || [],
3713
3734
  status: status.status,
3714
- activeModal: status.activeModal,
3715
- terminalHistory: status.terminalHistory || ""
3735
+ activeModal: status.activeModal
3716
3736
  };
3717
3737
  }
3718
3738
  }
3719
- return { success: false, error: `${provider.category} adapter not found` };
3739
+ return { success: false, error: `${transport} adapter not found` };
3720
3740
  }
3721
- if (provider?.category === "extension") {
3741
+ if (isExtensionTransport(transport)) {
3722
3742
  try {
3723
3743
  const evalResult = await h.evaluateProviderScript("readChat", void 0, 5e4);
3724
3744
  if (evalResult?.result) {
@@ -3732,7 +3752,7 @@ async function handleReadChat(h, args) {
3732
3752
  if (parsed && typeof parsed === "object") {
3733
3753
  _log(`Extension OK: ${parsed.messages?.length || 0} msgs`);
3734
3754
  h.historyWriter.appendNewMessages(
3735
- provider.type || "unknown_extension",
3755
+ provider?.type || "unknown_extension",
3736
3756
  parsed.messages || [],
3737
3757
  parsed.title,
3738
3758
  args?.targetSessionId
@@ -3748,7 +3768,7 @@ async function handleReadChat(h, args) {
3748
3768
  const parentSessionId = h.currentSession?.parentSessionId;
3749
3769
  if (cdp2 && parentSessionId) {
3750
3770
  const stream = await h.agentStream.collectActiveSession(cdp2, parentSessionId);
3751
- if (stream?.agentType !== provider.type) {
3771
+ if (stream?.agentType !== provider?.type) {
3752
3772
  return { success: true, messages: [], status: "idle" };
3753
3773
  }
3754
3774
  if (stream) {
@@ -3828,6 +3848,7 @@ async function handleSendChat(h, args) {
3828
3848
  if (!text) return { success: false, error: "text required" };
3829
3849
  const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
3830
3850
  const provider = h.getProvider(args?.agentType);
3851
+ const transport = getTargetTransport(h, provider);
3831
3852
  const dedupeKey = buildRecentSendKey(h, args, provider, text);
3832
3853
  const _logSendSuccess = (method, targetAgent) => {
3833
3854
  h.historyWriter.appendNewMessages(
@@ -3843,20 +3864,20 @@ async function handleSendChat(h, args) {
3843
3864
  _log(`Suppressed duplicate send for ${dedupeKey}`);
3844
3865
  return { success: true, sent: false, deduplicated: true };
3845
3866
  }
3846
- if (provider?.category === "cli" || provider?.category === "acp") {
3847
- const adapter = getTargetedCliAdapter(h, args, provider.type);
3867
+ if (isCliLikeTransport(transport)) {
3868
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
3848
3869
  if (adapter) {
3849
- _log(`${provider.category} adapter: ${adapter.cliType}`);
3870
+ _log(`${transport} adapter: ${adapter.cliType}`);
3850
3871
  try {
3851
3872
  await adapter.sendMessage(text);
3852
- return _logSendSuccess(`${provider.category}-adapter`, adapter.cliType);
3873
+ return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
3853
3874
  } catch (e) {
3854
- return { success: false, error: `${provider.category} send failed: ${e.message}` };
3875
+ return { success: false, error: `${transport} send failed: ${e.message}` };
3855
3876
  }
3856
3877
  }
3857
3878
  }
3858
- if (provider?.category === "extension") {
3859
- _log(`Extension: ${provider.type}`);
3879
+ if (isExtensionTransport(transport)) {
3880
+ _log(`Extension: ${provider?.type || "unknown_extension"}`);
3860
3881
  try {
3861
3882
  const evalResult = await h.evaluateProviderScript("sendMessage", { MESSAGE: text }, 3e4);
3862
3883
  if (evalResult?.result) {
@@ -3886,7 +3907,7 @@ async function handleSendChat(h, args) {
3886
3907
  return _logSendSuccess("agent-stream");
3887
3908
  }
3888
3909
  }
3889
- return { success: false, error: `Extension '${provider.type}' send failed` };
3910
+ return { success: false, error: `Extension '${provider?.type || "unknown_extension"}' send failed` };
3890
3911
  }
3891
3912
  const targetCdp = h.getCdp();
3892
3913
  if (!targetCdp?.isConnected) {
@@ -4012,7 +4033,8 @@ async function handleSendChat(h, args) {
4012
4033
  }
4013
4034
  async function handleListChats(h, args) {
4014
4035
  const provider = h.getProvider(args?.agentType);
4015
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4036
+ const transport = getTargetTransport(h, provider);
4037
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4016
4038
  try {
4017
4039
  const chats = await h.agentStream.listSessionChats(h.getCdp(), h.currentSession.sessionId);
4018
4040
  LOG.info("Command", `[list_chats] Extension: ${chats.length} chats`);
@@ -4064,8 +4086,9 @@ async function handleListChats(h, args) {
4064
4086
  }
4065
4087
  async function handleNewChat(h, args) {
4066
4088
  const provider = h.getProvider(args?.agentType);
4067
- if (provider?.category === "cli") {
4068
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4089
+ const transport = getTargetTransport(h, provider);
4090
+ if (transport === "pty") {
4091
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4069
4092
  if (!adapter) return { success: false, error: "CLI adapter not running" };
4070
4093
  if (typeof adapter.clearHistory === "function") {
4071
4094
  adapter.clearHistory();
@@ -4073,7 +4096,7 @@ async function handleNewChat(h, args) {
4073
4096
  }
4074
4097
  return { success: false, error: "new_chat not supported by this CLI provider" };
4075
4098
  }
4076
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4099
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4077
4100
  const ok = await h.agentStream.newSession(h.getCdp(), h.currentSession.sessionId);
4078
4101
  return { success: ok };
4079
4102
  }
@@ -4098,11 +4121,12 @@ async function handleNewChat(h, args) {
4098
4121
  }
4099
4122
  async function handleSwitchChat(h, args) {
4100
4123
  const provider = h.getProvider(args?.agentType);
4124
+ const transport = getTargetTransport(h, provider);
4101
4125
  const managerKey = getCurrentManagerKey(h);
4102
4126
  const sessionId = args?.sessionId || args?.id || args?.chatId;
4103
4127
  if (!sessionId) return { success: false, error: "sessionId required" };
4104
4128
  LOG.info("Command", `[switch_chat] sessionId=${sessionId}, manager=${managerKey}`);
4105
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4129
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4106
4130
  const ok = await h.agentStream.switchConversation(h.getCdp(), h.currentSession.sessionId, sessionId);
4107
4131
  return { success: ok, result: ok ? "switched" : "failed" };
4108
4132
  }
@@ -4192,9 +4216,10 @@ async function handleSwitchChat(h, args) {
4192
4216
  }
4193
4217
  async function handleSetMode(h, args) {
4194
4218
  const provider = h.getProvider(args?.agentType);
4219
+ const transport = getTargetTransport(h, provider);
4195
4220
  const mode = args?.mode || "agent";
4196
- if (provider?.category === "acp") {
4197
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4221
+ if (transport === "acp") {
4222
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4198
4223
  if (adapter) {
4199
4224
  const acpInstance = adapter._acpInstance;
4200
4225
  if (acpInstance && typeof acpInstance.onEvent === "function") {
@@ -4247,10 +4272,11 @@ async function handleSetMode(h, args) {
4247
4272
  }
4248
4273
  async function handleChangeModel(h, args) {
4249
4274
  const provider = h.getProvider(args?.agentType);
4275
+ const transport = getTargetTransport(h, provider);
4250
4276
  const model = args?.model;
4251
- LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} manager=${getCurrentManagerKey(h)} providerType=${getCurrentProviderType(h)}`);
4252
- if (provider?.category === "acp") {
4253
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4277
+ LOG.info("Command", `[change_model] model=${model} provider=${provider?.type} transport=${transport} manager=${getCurrentManagerKey(h)} providerType=${getCurrentProviderType(h)}`);
4278
+ if (transport === "acp") {
4279
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4254
4280
  LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
4255
4281
  if (adapter) {
4256
4282
  const acpInstance = adapter._acpInstance;
@@ -4308,15 +4334,16 @@ async function handleSetThoughtLevel(h, args) {
4308
4334
  const value = args?.value;
4309
4335
  if (!configId || !value) return { success: false, error: "configId and value required" };
4310
4336
  const provider = h.getProvider(args?.agentType);
4311
- if (!provider || provider.category !== "acp") {
4337
+ const transport = getTargetTransport(h, provider);
4338
+ if (transport !== "acp") {
4312
4339
  return { success: false, error: "set_thought_level only for ACP providers" };
4313
4340
  }
4314
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4341
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4315
4342
  const acpInstance = adapter?._acpInstance;
4316
4343
  if (!acpInstance) return { success: false, error: "ACP instance not found" };
4317
4344
  try {
4318
4345
  await acpInstance.setConfigOption(configId, value);
4319
- LOG.info("Command", `[set_thought_level] ${configId}=${value} for ${provider.type}`);
4346
+ LOG.info("Command", `[set_thought_level] ${configId}=${value} for ${provider?.type || "unknown_acp"}`);
4320
4347
  return { success: true, configId, value };
4321
4348
  } catch (e) {
4322
4349
  return { success: false, error: e?.message };
@@ -4324,11 +4351,12 @@ async function handleSetThoughtLevel(h, args) {
4324
4351
  }
4325
4352
  async function handleResolveAction(h, args) {
4326
4353
  const provider = h.getProvider(args?.agentType);
4354
+ const transport = getTargetTransport(h, provider);
4327
4355
  const action = args?.action || "approve";
4328
4356
  const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
4329
4357
  LOG.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
4330
- if (provider?.category === "cli") {
4331
- const adapter = getTargetedCliAdapter(h, args, provider.type);
4358
+ if (transport === "pty") {
4359
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
4332
4360
  if (!adapter) return { success: false, error: "CLI adapter not running" };
4333
4361
  if (args?.data && typeof adapter.resolveAction === "function") {
4334
4362
  try {
@@ -4369,7 +4397,7 @@ async function handleResolveAction(h, args) {
4369
4397
  LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
4370
4398
  return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
4371
4399
  }
4372
- if (provider?.category === "extension" && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4400
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
4373
4401
  const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
4374
4402
  return { success: ok };
4375
4403
  }
@@ -18630,21 +18658,39 @@ var init_xterm_backend = __esm({
18630
18658
 
18631
18659
  // ../../oss/packages/daemon-core/src/cli-adapters/terminal-screen.ts
18632
18660
  function createTerminalBackend(options, preference) {
18661
+ const ghosttyAvailable = isGhosttyVtBackendAvailable();
18633
18662
  if (preference === "ghostty-vt") {
18634
- return new GhosttyVtTerminalBackend(options);
18635
- }
18636
- if (preference === "auto" && isGhosttyVtBackendAvailable()) {
18637
- return new GhosttyVtTerminalBackend(options);
18638
- }
18639
- return new XtermTerminalBackend(options);
18663
+ const backend2 = new GhosttyVtTerminalBackend(options);
18664
+ logTerminalBackendSelection(preference, ghosttyAvailable, backend2.kind);
18665
+ return backend2;
18666
+ }
18667
+ if (preference === "auto" && ghosttyAvailable) {
18668
+ const backend2 = new GhosttyVtTerminalBackend(options);
18669
+ logTerminalBackendSelection(preference, ghosttyAvailable, backend2.kind);
18670
+ return backend2;
18671
+ }
18672
+ const backend = new XtermTerminalBackend(options);
18673
+ logTerminalBackendSelection(preference, ghosttyAvailable, backend.kind);
18674
+ return backend;
18675
+ }
18676
+ function logTerminalBackendSelection(preference, ghosttyAvailable, backendKind) {
18677
+ const key = `${preference}:${ghosttyAvailable}:${backendKind}`;
18678
+ if (loggedTerminalBackends.has(key)) return;
18679
+ loggedTerminalBackends.add(key);
18680
+ LOG.info(
18681
+ "Terminal",
18682
+ `[terminal-screen] backend=${backendKind} preference=${preference} ghosttyAvailable=${ghosttyAvailable}`
18683
+ );
18640
18684
  }
18641
- var DEFAULT_SCROLLBACK, TerminalScreen;
18685
+ var DEFAULT_SCROLLBACK, loggedTerminalBackends, TerminalScreen;
18642
18686
  var init_terminal_screen = __esm({
18643
18687
  "../../oss/packages/daemon-core/src/cli-adapters/terminal-screen.ts"() {
18644
18688
  "use strict";
18689
+ init_logger();
18645
18690
  init_ghostty_vt_backend();
18646
18691
  init_xterm_backend();
18647
18692
  DEFAULT_SCROLLBACK = 2e3;
18693
+ loggedTerminalBackends = /* @__PURE__ */ new Set();
18648
18694
  TerminalScreen = class {
18649
18695
  backendKind;
18650
18696
  rows;
@@ -37459,7 +37505,6 @@ var init_cli_manager = __esm({
37459
37505
  sessionId: cliInstance.instanceId,
37460
37506
  parentSessionId: null,
37461
37507
  providerType: normalizedType,
37462
- providerCategory: "cli",
37463
37508
  transport: "pty",
37464
37509
  adapterKey: key,
37465
37510
  instanceKey: key
@@ -37509,7 +37554,6 @@ ${installInfo}`
37509
37554
  sessionId,
37510
37555
  parentSessionId: null,
37511
37556
  providerType: normalizedType,
37512
- providerCategory: "acp",
37513
37557
  transport: "acp",
37514
37558
  adapterKey: key,
37515
37559
  instanceKey: key
@@ -38040,12 +38084,12 @@ var init_manager2 = __esm({
38040
38084
  this.logFn(`[AgentStream] Active session (${parentSessionId}): ${sessionId || "none"}`);
38041
38085
  }
38042
38086
  resolveSessionIdForTarget(parentSessionId, agentType) {
38043
- const child = (this.sessionRegistry?.listChildren(parentSessionId) || []).find((entry) => entry.providerCategory === "extension" && entry.providerType === agentType);
38087
+ const child = (this.sessionRegistry?.listChildren(parentSessionId) || []).find((entry) => entry.transport === "cdp-webview" && entry.providerType === agentType);
38044
38088
  return child?.sessionId || null;
38045
38089
  }
38046
38090
  async connectManagedSession(cdp, parentSessionId, runtimeSessionId) {
38047
38091
  const target = this.getSessionTarget(runtimeSessionId);
38048
- if (!target || target.providerCategory !== "extension") return null;
38092
+ if (!target || target.transport !== "cdp-webview") return null;
38049
38093
  const adapter = this.adaptersByType.get(target.providerType);
38050
38094
  if (!adapter) return null;
38051
38095
  const targets = await cdp.discoverAgentWebviews();
@@ -38344,7 +38388,6 @@ var init_poller = __esm({
38344
38388
  sessionId: extInstance.getInstanceId(),
38345
38389
  parentSessionId,
38346
38390
  providerType: extType,
38347
- providerCategory: "extension",
38348
38391
  transport: "cdp-webview",
38349
38392
  cdpManagerKey: ideType,
38350
38393
  instanceKey: `ide:${ideType}`
@@ -38582,7 +38625,6 @@ var init_provider_instance_manager = __esm({
38582
38625
  providerType,
38583
38626
  instanceId: state.instanceId,
38584
38627
  targetSessionId: state.instanceId,
38585
- providerCategory: state.category,
38586
38628
  workspaceName: state.workspace || void 0,
38587
38629
  ...extra
38588
38630
  });
@@ -44300,10 +44342,6 @@ var init_daemon_p2p = __esm({
44300
44342
  ptyResizeHandler = null;
44301
44343
  screenshotStartHandler = null;
44302
44344
  _ssDebugDone = false;
44303
- // PTY scrollback buffer per cliType (send recent output on reconnect)
44304
- ptyScrollback = /* @__PURE__ */ new Map();
44305
- PTY_SCROLLBACK_MAX = 64 * 1024;
44306
- // 64KB per CLI
44307
44345
  get screenshotActive() {
44308
44346
  for (const peer of this.peers.values()) {
44309
44347
  if (peer.screenshotActive && peer.state === "connected") return true;
@@ -44650,7 +44688,6 @@ ${e?.stack || ""}`);
44650
44688
  log(`Screenshots auto-starting for peer ${pid} (was waiting for channel open)`);
44651
44689
  }
44652
44690
  }
44653
- setTimeout(() => this.sendPtyScrollback(pid), 100);
44654
44691
  });
44655
44692
  dataCh.onClosed(() => {
44656
44693
  log(`Data channel CLOSED for peer ${pid}`);
@@ -44781,12 +44818,6 @@ ${e?.stack || ""}`);
44781
44818
  }
44782
44819
  /** Broadcast PTY output to all connected peers */
44783
44820
  broadcastPtyOutput(cliType, data) {
44784
- const prev = this.ptyScrollback.get(cliType) || "";
44785
- const updated = prev + data;
44786
- this.ptyScrollback.set(
44787
- cliType,
44788
- updated.length > this.PTY_SCROLLBACK_MAX ? updated.slice(-this.PTY_SCROLLBACK_MAX) : updated
44789
- );
44790
44821
  const msg = JSON.stringify({ type: "pty_output", cliType, data });
44791
44822
  let sentAny = false;
44792
44823
  for (const peer of this.peers.values()) {
@@ -44799,24 +44830,6 @@ ${e?.stack || ""}`);
44799
44830
  }
44800
44831
  return sentAny;
44801
44832
  }
44802
- /** Send scrollback on peer connect */
44803
- sendPtyScrollback(peerId) {
44804
- const peer = this.peers.get(peerId);
44805
- if (!peer?.dataChannel) return;
44806
- for (const [cliType, buffer] of this.ptyScrollback) {
44807
- if (!buffer) continue;
44808
- try {
44809
- peer.dataChannel.sendMessage(JSON.stringify({
44810
- type: "pty_output",
44811
- cliType,
44812
- data: buffer,
44813
- scrollback: true
44814
- }));
44815
- logDebug(`Sent PTY scrollback to peer ${peerId}: ${cliType} (${buffer.length} bytes)`);
44816
- } catch {
44817
- }
44818
- }
44819
- }
44820
44833
  sendScreenshot(base64Data) {
44821
44834
  const buffer = Buffer.from(base64Data, "base64");
44822
44835
  return this.sendScreenshotBuffer(buffer);
@@ -45381,11 +45394,12 @@ var init_adhdev_daemon = __esm({
45381
45394
  init_daemon_p2p();
45382
45395
  init_screenshot_controller();
45383
45396
  init_session_host();
45397
+ init_dist();
45384
45398
  os19 = __toESM(require("os"));
45385
45399
  fs14 = __toESM(require("fs"));
45386
45400
  path17 = __toESM(require("path"));
45387
45401
  import_chalk2 = __toESM(require("chalk"));
45388
- pkgVersion = "0.7.29";
45402
+ pkgVersion = "0.7.31";
45389
45403
  if (pkgVersion === "unknown") {
45390
45404
  try {
45391
45405
  const possiblePaths = [
@@ -45423,6 +45437,7 @@ var init_adhdev_daemon = __esm({
45423
45437
  screenshotController = null;
45424
45438
  statusReporter = null;
45425
45439
  components = null;
45440
+ sessionHostEndpoint = null;
45426
45441
  running = false;
45427
45442
  localPort;
45428
45443
  ideType = "unknown";
@@ -45444,200 +45459,210 @@ ${err?.stack || ""}`);
45444
45459
  });
45445
45460
  this.localPort = options.localPort || DEFAULT_DAEMON_PORT;
45446
45461
  const workingDir = options.workingDir || process.cwd();
45447
- if (isDaemonRunning()) {
45448
- console.log(import_chalk2.default.yellow("\n\u26A0 ADHDev Daemon is already running."));
45449
- console.log(import_chalk2.default.gray(` Stop with: adhdev daemon:stop
45462
+ let pidWritten = false;
45463
+ try {
45464
+ if (isDaemonRunning()) {
45465
+ console.log(import_chalk2.default.yellow("\n\u26A0 ADHDev Daemon is already running."));
45466
+ console.log(import_chalk2.default.gray(` Stop with: adhdev daemon:stop
45450
45467
  `));
45451
- return;
45452
- }
45453
- writeDaemonPid(process.pid);
45454
- const config2 = loadConfig();
45455
- const authToken = config2.machineSecret;
45456
- if (!authToken) {
45457
- console.log(import_chalk2.default.red("\n\u2717 No machine secret found."));
45458
- if (config2.connectionToken) {
45459
- console.log(import_chalk2.default.yellow(" Legacy connectionToken detected \u2014 please re-run setup."));
45460
- }
45461
- console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
45462
- process.exit(1);
45463
- }
45464
- const sessionHostEndpoint = await ensureSessionHostReady2();
45465
- this.components = await initDaemonComponents({
45466
- providerLogFn: LOG.forComponent("Provider").asLogFn(),
45467
- cliManagerDeps: {
45468
- getServerConn: () => this.serverConn,
45469
- getP2p: () => this.p2p,
45470
- onStatusChange: () => this.statusReporter?.onStatusChange(),
45471
- removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
45472
- createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => new SessionHostPtyTransportFactory({
45473
- endpoint: sessionHostEndpoint,
45474
- clientId: `daemon_${config2.machineId}`,
45475
- runtimeId,
45476
- providerType,
45477
- workspace,
45478
- appName: process.env.ADHDEV_SESSION_HOST_NAME || "adhdev",
45479
- meta: {
45480
- cliArgs
45481
- },
45482
- attachExisting
45483
- }),
45484
- listHostedCliRuntimes: async () => listHostedCliRuntimes2(sessionHostEndpoint)
45485
- },
45486
- enabledIdes: config2.enabledIdes,
45487
- onStatusChange: () => this.statusReporter?.onStatusChange(),
45488
- onPostChatCommand: () => {
45489
- setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
45490
- setTimeout(() => this.statusReporter?.throttledReport(), 3e3);
45491
- },
45492
- getCdpLogFn: (ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn(),
45493
- onCdpManagerSetup: (ideType) => {
45494
- if (this.ideType === "unknown") this.ideType = ideType;
45495
- },
45496
- onStreamsUpdated: (ideType, streams) => {
45497
- if (!this.components) return;
45498
- forwardAgentStreamsToIdeInstance(this.components.instanceManager, ideType, streams);
45468
+ return;
45499
45469
  }
45500
- });
45501
- await this.components.cliManager.restoreHostedSessions();
45502
- this.components.providerLoader.fetchLatest().then(({ updated }) => {
45503
- if (updated) {
45504
- this.components.providerLoader.reload();
45505
- this.components.providerLoader.registerToDetector();
45506
- LOG.info("Provider", "Providers auto-updated from upstream");
45507
- }
45508
- }).catch(() => {
45509
- });
45510
- const instanceId = `daemon_${config2.machineId}`;
45511
- this.serverConn = new ServerConnection({
45512
- serverUrl: options.serverUrl || config2.serverUrl,
45513
- token: authToken,
45514
- daemonVersion: pkgVersion,
45515
- cliInfo: {
45516
- type: "adhdev-daemon",
45517
- version: pkgVersion,
45518
- platform: os19.platform(),
45519
- hostname: os19.hostname(),
45520
- machineId: config2.machineId,
45521
- instanceId
45470
+ writeDaemonPid(process.pid);
45471
+ pidWritten = true;
45472
+ const config2 = loadConfig();
45473
+ const authToken = config2.machineSecret;
45474
+ if (!authToken) {
45475
+ console.log(import_chalk2.default.red("\n\u2717 No machine secret found."));
45476
+ if (config2.connectionToken) {
45477
+ console.log(import_chalk2.default.yellow(" Legacy connectionToken detected \u2014 please re-run setup."));
45478
+ }
45479
+ console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
45480
+ process.exit(1);
45522
45481
  }
45523
- });
45524
- this.p2p = new DaemonP2PSender(this.serverConn);
45525
- if (this.p2p.isAvailable) {
45526
- console.log(import_chalk2.default.green(" \u{1F517} P2P available (node-datachannel)"));
45527
- this.p2p.onInput(async (event) => {
45528
- return this.components.commandHandler.handle("cdp_remote_action", event);
45529
- });
45530
- this.p2p.onCommand(async (cmdType, data, id) => {
45531
- return this.handleP2PCommand(cmdType, data);
45532
- });
45533
- this.p2p.onFileRequest(async (req) => {
45534
- const handler = this.components.commandHandler;
45535
- if (req.type === "read") {
45536
- const result = await handler.handle("file_read", { path: req.path });
45537
- return { id: req.id, success: result.success, content: result.content, error: result.error };
45538
- } else if (req.type === "write") {
45539
- const result = await handler.handle("file_write", { path: req.path, content: req.content });
45540
- return { id: req.id, success: result.success, error: result.error };
45541
- } else {
45542
- const result = await handler.handle("file_list", { path: req.path });
45543
- return { id: req.id, success: result.success, entries: result.files, error: result.error };
45482
+ const sessionHostEndpoint = await ensureSessionHostReady2();
45483
+ this.sessionHostEndpoint = sessionHostEndpoint;
45484
+ this.components = await initDaemonComponents({
45485
+ providerLogFn: LOG.forComponent("Provider").asLogFn(),
45486
+ cliManagerDeps: {
45487
+ getServerConn: () => this.serverConn,
45488
+ getP2p: () => this.p2p,
45489
+ onStatusChange: () => this.statusReporter?.onStatusChange(),
45490
+ removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
45491
+ createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => new SessionHostPtyTransportFactory({
45492
+ endpoint: sessionHostEndpoint,
45493
+ clientId: `daemon_${config2.machineId}`,
45494
+ runtimeId,
45495
+ providerType,
45496
+ workspace,
45497
+ appName: process.env.ADHDEV_SESSION_HOST_NAME || "adhdev",
45498
+ meta: {
45499
+ cliArgs
45500
+ },
45501
+ attachExisting
45502
+ }),
45503
+ listHostedCliRuntimes: async () => listHostedCliRuntimes2(sessionHostEndpoint)
45504
+ },
45505
+ enabledIdes: config2.enabledIdes,
45506
+ onStatusChange: () => this.statusReporter?.onStatusChange(),
45507
+ onPostChatCommand: () => {
45508
+ setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
45509
+ setTimeout(() => this.statusReporter?.throttledReport(), 3e3);
45510
+ },
45511
+ getCdpLogFn: (ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn(),
45512
+ onCdpManagerSetup: (ideType) => {
45513
+ if (this.ideType === "unknown") this.ideType = ideType;
45514
+ },
45515
+ onStreamsUpdated: (ideType, streams) => {
45516
+ if (!this.components) return;
45517
+ forwardAgentStreamsToIdeInstance(this.components.instanceManager, ideType, streams);
45544
45518
  }
45545
45519
  });
45546
- this.p2p.onPtyInput((cliId, data) => {
45547
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45548
- if (found && typeof found.adapter.writeRaw === "function") {
45549
- found.adapter.writeRaw(data);
45550
- }
45520
+ await this.components.cliManager.restoreHostedSessions();
45521
+ this.components.providerLoader.fetchLatest().then(({ updated }) => {
45522
+ if (updated) {
45523
+ this.components.providerLoader.reload();
45524
+ this.components.providerLoader.registerToDetector();
45525
+ LOG.info("Provider", "Providers auto-updated from upstream");
45526
+ }
45527
+ }).catch(() => {
45551
45528
  });
45552
- this.p2p.onPtyResize((cliId, cols, rows) => {
45553
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45554
- if (found && typeof found.adapter.resize === "function") {
45555
- found.adapter.resize(cols, rows);
45529
+ const instanceId = `daemon_${config2.machineId}`;
45530
+ this.serverConn = new ServerConnection({
45531
+ serverUrl: options.serverUrl || config2.serverUrl,
45532
+ token: authToken,
45533
+ daemonVersion: pkgVersion,
45534
+ cliInfo: {
45535
+ type: "adhdev-daemon",
45536
+ version: pkgVersion,
45537
+ platform: os19.platform(),
45538
+ hostname: os19.hostname(),
45539
+ machineId: config2.machineId,
45540
+ instanceId
45556
45541
  }
45557
45542
  });
45558
- this.p2p.onStateChange((state) => {
45559
- if (state === "connected") {
45560
- LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
45561
- this.statusReporter?.resetP2PHash();
45562
- this.statusReporter?.sendUnifiedStatusReport().catch((e) => LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
45563
- setTimeout(() => {
45543
+ this.p2p = new DaemonP2PSender(this.serverConn);
45544
+ if (this.p2p.isAvailable) {
45545
+ console.log(import_chalk2.default.green(" \u{1F517} P2P available (node-datachannel)"));
45546
+ this.p2p.onInput(async (event) => {
45547
+ return this.components.commandHandler.handle("cdp_remote_action", event);
45548
+ });
45549
+ this.p2p.onCommand(async (cmdType, data, id) => {
45550
+ return this.handleP2PCommand(cmdType, data);
45551
+ });
45552
+ this.p2p.onFileRequest(async (req) => {
45553
+ const handler = this.components.commandHandler;
45554
+ if (req.type === "read") {
45555
+ const result = await handler.handle("file_read", { path: req.path });
45556
+ return { id: req.id, success: result.success, content: result.content, error: result.error };
45557
+ } else if (req.type === "write") {
45558
+ const result = await handler.handle("file_write", { path: req.path, content: req.content });
45559
+ return { id: req.id, success: result.success, error: result.error };
45560
+ } else {
45561
+ const result = await handler.handle("file_list", { path: req.path });
45562
+ return { id: req.id, success: result.success, entries: result.files, error: result.error };
45563
+ }
45564
+ });
45565
+ this.p2p.onPtyInput((cliId, data) => {
45566
+ const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45567
+ if (found && typeof found.adapter.writeRaw === "function") {
45568
+ found.adapter.writeRaw(data);
45569
+ }
45570
+ });
45571
+ this.p2p.onPtyResize((cliId, cols, rows) => {
45572
+ const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45573
+ if (found && typeof found.adapter.resize === "function") {
45574
+ found.adapter.resize(cols, rows);
45575
+ }
45576
+ });
45577
+ this.p2p.onStateChange((state) => {
45578
+ if (state === "connected") {
45579
+ LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
45564
45580
  this.statusReporter?.resetP2PHash();
45565
- this.statusReporter?.sendUnifiedStatusReport().catch(() => {
45566
- });
45567
- }, 2e3);
45581
+ this.statusReporter?.sendUnifiedStatusReport().catch((e) => LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
45582
+ setTimeout(() => {
45583
+ this.statusReporter?.resetP2PHash();
45584
+ this.statusReporter?.sendUnifiedStatusReport().catch(() => {
45585
+ });
45586
+ }, 2e3);
45587
+ }
45588
+ });
45589
+ const planLimits = this.serverConn.getPlanLimits();
45590
+ this.screenshotController = new ScreenshotController({
45591
+ isRunning: () => this.running,
45592
+ isScreenshotActive: () => this.p2p?.screenshotActive ?? false,
45593
+ getScreenshotIdeType: () => this.p2p?.screenshotIdeType,
45594
+ isUsingRelay: () => this.p2p?.isUsingRelay ?? false,
45595
+ hasAnyNeedingFirstFrame: () => this.p2p?.hasAnyNeedingFirstFrame() ?? false,
45596
+ getCdp: (ideType) => {
45597
+ if (ideType) return this.getCdpFor(ideType);
45598
+ LOG.warn("P2P", "Screenshot requested without ideType \u2014 cannot determine target IDE. Skipping frame.");
45599
+ return null;
45600
+ },
45601
+ sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf)
45602
+ }, planLimits ?? void 0);
45603
+ this.screenshotController.start();
45604
+ this.p2p.onScreenshotStart(() => this.screenshotController?.triggerImmediate());
45605
+ } else {
45606
+ console.log(import_chalk2.default.gray(" \u26A0 P2P unavailable \u2014 using server relay"));
45607
+ }
45608
+ this.registerServerHandlers();
45609
+ this.serverConn.on("auth_ok", (msg) => {
45610
+ const serverNickname = msg.payload?.machineNickname;
45611
+ if (serverNickname === void 0) return;
45612
+ const nextNickname = typeof serverNickname === "string" && serverNickname.trim() ? serverNickname.trim() : null;
45613
+ const latestConfig = loadConfig();
45614
+ if ((latestConfig.machineNickname || null) === nextNickname) return;
45615
+ latestConfig.machineNickname = nextNickname;
45616
+ saveConfig(latestConfig);
45617
+ LOG.info("Server", `[ServerConn] Synced machine nickname from server: ${nextNickname || "(cleared)"}`);
45618
+ this.statusReporter?.throttledReport();
45619
+ });
45620
+ this.serverConn.onStateChange((state) => {
45621
+ if (state === "connected") {
45622
+ console.log(import_chalk2.default.green(" \u{1F4E1} Connected to ADHDev server"));
45623
+ this.statusReporter?.sendUnifiedStatusReport();
45624
+ } else if (state === "disconnected") {
45625
+ console.log(import_chalk2.default.yellow(" \u26A0 Server disconnected, will reconnect..."));
45568
45626
  }
45569
45627
  });
45570
- const planLimits = this.serverConn.getPlanLimits();
45571
- this.screenshotController = new ScreenshotController({
45572
- isRunning: () => this.running,
45573
- isScreenshotActive: () => this.p2p?.screenshotActive ?? false,
45574
- getScreenshotIdeType: () => this.p2p?.screenshotIdeType,
45575
- isUsingRelay: () => this.p2p?.isUsingRelay ?? false,
45576
- hasAnyNeedingFirstFrame: () => this.p2p?.hasAnyNeedingFirstFrame() ?? false,
45577
- getCdp: (ideType) => {
45578
- if (ideType) return this.getCdpFor(ideType);
45579
- LOG.warn("P2P", "Screenshot requested without ideType \u2014 cannot determine target IDE. Skipping frame.");
45580
- return null;
45581
- },
45582
- sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf)
45583
- }, planLimits ?? void 0);
45584
- this.screenshotController.start();
45585
- this.p2p.onScreenshotStart(() => this.screenshotController?.triggerImmediate());
45586
- } else {
45587
- console.log(import_chalk2.default.gray(" \u26A0 P2P unavailable \u2014 using server relay"));
45588
- }
45589
- this.registerServerHandlers();
45590
- this.serverConn.on("auth_ok", (msg) => {
45591
- const serverNickname = msg.payload?.machineNickname;
45592
- if (serverNickname === void 0) return;
45593
- const nextNickname = typeof serverNickname === "string" && serverNickname.trim() ? serverNickname.trim() : null;
45594
- const latestConfig = loadConfig();
45595
- if ((latestConfig.machineNickname || null) === nextNickname) return;
45596
- latestConfig.machineNickname = nextNickname;
45597
- saveConfig(latestConfig);
45598
- LOG.info("Server", `[ServerConn] Synced machine nickname from server: ${nextNickname || "(cleared)"}`);
45599
- this.statusReporter?.throttledReport();
45600
- });
45601
- this.serverConn.onStateChange((state) => {
45602
- if (state === "connected") {
45603
- console.log(import_chalk2.default.green(" \u{1F4E1} Connected to ADHDev server"));
45604
- this.statusReporter?.sendUnifiedStatusReport();
45605
- } else if (state === "disconnected") {
45606
- console.log(import_chalk2.default.yellow(" \u26A0 Server disconnected, will reconnect..."));
45607
- }
45608
- });
45609
- await this.serverConn.connect();
45610
- this.statusReporter = new DaemonStatusReporter({
45611
- serverConn: this.serverConn,
45612
- cdpManagers: this.components.cdpManagers,
45613
- p2p: this.p2p,
45614
- providerLoader: this.components.providerLoader,
45615
- detectedIdes: this.components.detectedIdes.value,
45616
- instanceId,
45617
- daemonVersion: pkgVersion,
45618
- instanceManager: this.components.instanceManager,
45619
- getScreenshotUsage: () => this.screenshotController?.getUsageStats() || null
45620
- });
45621
- this.statusReporter.startReporting();
45622
- this.components.instanceManager.onEvent((event) => {
45623
- this.statusReporter?.emitStatusEvent(event);
45624
- });
45625
- this.running = true;
45626
- process.on("SIGINT", () => this.stop());
45627
- process.on("SIGTERM", () => this.stop());
45628
- if (options.dev && this.components) {
45629
- const devServer = new DevServer({
45630
- providerLoader: this.components.providerLoader,
45628
+ await this.serverConn.connect();
45629
+ this.statusReporter = new DaemonStatusReporter({
45630
+ serverConn: this.serverConn,
45631
45631
  cdpManagers: this.components.cdpManagers,
45632
+ p2p: this.p2p,
45633
+ providerLoader: this.components.providerLoader,
45634
+ detectedIdes: this.components.detectedIdes.value,
45635
+ instanceId,
45636
+ daemonVersion: pkgVersion,
45632
45637
  instanceManager: this.components.instanceManager,
45633
- cliManager: this.components.cliManager
45638
+ getScreenshotUsage: () => this.screenshotController?.getUsageStats() || null
45634
45639
  });
45635
- await devServer.start();
45636
- }
45637
- this.printBanner(options, config2.serverUrl);
45638
- if (options.foreground) {
45639
- await new Promise(() => {
45640
+ this.statusReporter.startReporting();
45641
+ this.components.instanceManager.onEvent((event) => {
45642
+ this.statusReporter?.emitStatusEvent(event);
45640
45643
  });
45644
+ this.running = true;
45645
+ process.on("SIGINT", () => this.stop());
45646
+ process.on("SIGTERM", () => this.stop());
45647
+ if (options.dev && this.components) {
45648
+ const devServer = new DevServer({
45649
+ providerLoader: this.components.providerLoader,
45650
+ cdpManagers: this.components.cdpManagers,
45651
+ instanceManager: this.components.instanceManager,
45652
+ cliManager: this.components.cliManager
45653
+ });
45654
+ await devServer.start();
45655
+ }
45656
+ this.printBanner(options, config2.serverUrl);
45657
+ if (options.foreground) {
45658
+ await new Promise(() => {
45659
+ });
45660
+ }
45661
+ } catch (error48) {
45662
+ if (!this.running && pidWritten) {
45663
+ removeDaemonPid();
45664
+ }
45665
+ throw error48;
45641
45666
  }
45642
45667
  }
45643
45668
  printBanner(options, serverUrl) {
@@ -45717,6 +45742,26 @@ ${err?.stack || ""}`);
45717
45742
  const cmdStart = Date.now();
45718
45743
  try {
45719
45744
  switch (cmdType) {
45745
+ case "get_runtime_snapshot": {
45746
+ const sessionId = typeof data.sessionId === "string" ? data.sessionId : "";
45747
+ if (!sessionId) return { success: false, error: "sessionId is required" };
45748
+ if (!this.sessionHostEndpoint) return { success: false, error: "Session host unavailable" };
45749
+ const client = new SessionHostClient({ endpoint: this.sessionHostEndpoint });
45750
+ try {
45751
+ await client.connect();
45752
+ const snapshot = await client.request({
45753
+ type: "get_snapshot",
45754
+ payload: { sessionId }
45755
+ });
45756
+ if (!snapshot.success || !snapshot.result) {
45757
+ return { success: false, error: snapshot.error || "Runtime snapshot unavailable" };
45758
+ }
45759
+ return { success: true, result: snapshot.result };
45760
+ } finally {
45761
+ await client.close().catch(() => {
45762
+ });
45763
+ }
45764
+ }
45720
45765
  case "get_cli_history": {
45721
45766
  const config2 = loadConfig();
45722
45767
  logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", success: true, durationMs: Date.now() - cmdStart });