@adhdev/daemon-standalone 0.8.46 → 0.8.48

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/README.md CHANGED
@@ -1,36 +1,61 @@
1
1
  # @adhdev/daemon-standalone
2
2
 
3
- ADHDev standalone daemon run a local AI agent dashboard without any cloud server.
3
+ ADHDev standalone packages the local dashboard, local HTTP/WebSocket API, and session-host-backed CLI runtime management into a single binary.
4
4
 
5
5
  ## Quick Start
6
6
 
7
7
  ```bash
8
8
  npx @adhdev/daemon-standalone
9
- # → http://localhost:3847
10
9
  ```
11
10
 
12
- ## Features
11
+ Or install it directly:
13
12
 
14
- - 🔍 **Auto-detects IDEs** — VS Code, Cursor, Windsurf, and more
15
- - 💬 **Live agent chat** — read & send messages to AI agents (Cline, Roo Code, etc.)
16
- - 🖥️ **Local dashboard** — bundled web UI, no internet required
17
- - 🔒 **Privacy-first** — everything runs on your machine
13
+ ```bash
14
+ npm install -g @adhdev/daemon-standalone
15
+ adhdev-standalone
16
+ ```
17
+
18
+ Open `http://localhost:3847`.
19
+
20
+ ## What It Exposes
21
+
22
+ - Bundled standalone dashboard
23
+ - Local API routes such as `GET /api/v1/status` and `POST /api/v1/command`
24
+ - Runtime snapshot and event streams for hosted CLI sessions
25
+ - Workspace mux routes for local terminal flows
26
+ - `ws://localhost:3847/ws` for real-time updates
27
+ - Local runtime commands: `list`, `attach`, and `open`
18
28
 
19
29
  ## Options
20
30
 
21
31
  | Flag | Description |
22
32
  |------|-------------|
23
33
  | `--port, -p <port>` | Port to listen on (default: `3847`) |
24
- | `--host, -H` | Listen on all interfaces enables LAN access (`0.0.0.0`) |
34
+ | `--host, -H` | Listen on all interfaces and bind to `0.0.0.0` |
25
35
  | `--no-open` | Don't open browser automatically on start |
26
36
  | `--token <secret>` | Enable token authentication for API and WebSocket |
27
- | `--dev` | Enable DevServer on port `19280` (provider debugging, CDP tools) |
37
+ | `--dev` | Enable DevConsole and provider debugging helpers |
38
+ | `--public <path>` | Serve the dashboard from a custom build directory |
39
+
40
+ ## Runtime Commands
41
+
42
+ ```bash
43
+ adhdev-standalone list
44
+ adhdev-standalone attach <sessionId>
45
+ adhdev-standalone open <sessionId>
46
+ ```
47
+
48
+ ## Notes
49
+
50
+ - The canonical runtime model is `GET /api/v1/status` and its `sessions[]` array.
51
+ - Treat built-in provider inventory as shipped inventory, not blanket verified support.
52
+ - On Windows, Node.js 24+ is currently blocked for the normal install/start path. Use Node.js 22.x instead.
28
53
 
29
54
  ## Links
30
55
 
31
- - [ADHDev Cloud](https://adhf.dev) — Cloud version with remote access & P2P
32
- - [GitHub](https://github.com/vilmire/adhdev) — Open source core
33
- - [CONTRIBUTING.md](https://github.com/vilmire/adhdev/blob/main/CONTRIBUTING.md)
56
+ - [Self-hosted setup](https://docs.adhf.dev/self-hosted/setup)
57
+ - [Self-hosted local API](https://docs.adhf.dev/self-hosted/local-api)
58
+ - [GitHub](https://github.com/vilmire/adhdev)
34
59
 
35
60
  ## License
36
61
 
package/dist/index.js CHANGED
@@ -32195,6 +32195,8 @@ ${data.message || ""}`.trim();
32195
32195
  allTargets = result?.targetInfos || [];
32196
32196
  }
32197
32197
  const pageWebviewUrls = await this.getCurrentPageWebviewUrls();
32198
+ const pageWebviewOrder = /* @__PURE__ */ new Map();
32199
+ Array.from(pageWebviewUrls).forEach((url2, index) => pageWebviewOrder.set(url2, index));
32198
32200
  const iframes = allTargets.filter((t) => t.type === "iframe");
32199
32201
  const typeMap = /* @__PURE__ */ new Map();
32200
32202
  for (const t of allTargets) {
@@ -32236,6 +32238,14 @@ ${data.message || ""}`.trim();
32236
32238
  }
32237
32239
  }
32238
32240
  }
32241
+ agents.sort((lhs, rhs) => {
32242
+ const leftOrder = pageWebviewOrder.get(lhs.url);
32243
+ const rightOrder = pageWebviewOrder.get(rhs.url);
32244
+ if (leftOrder != null && rightOrder != null) return leftOrder - rightOrder;
32245
+ if (leftOrder != null) return -1;
32246
+ if (rightOrder != null) return 1;
32247
+ return lhs.url.localeCompare(rhs.url);
32248
+ });
32239
32249
  this._lastDiscoveredTargets = new Set(agents.map((a) => a.targetId));
32240
32250
  return agents;
32241
32251
  } catch (e) {
@@ -32374,6 +32384,26 @@ ${data.message || ""}`.trim();
32374
32384
  }
32375
32385
  async getCurrentPageWebviewUrls() {
32376
32386
  if (!this.isConnected) return /* @__PURE__ */ new Set();
32387
+ try {
32388
+ const raw = await this.evaluate(
32389
+ `JSON.stringify(Array.from(document.querySelectorAll('iframe,webview'))
32390
+ .filter((el) => {
32391
+ const rect = el.getBoundingClientRect();
32392
+ if (rect.width <= 8 || rect.height <= 8) return false;
32393
+ const style = window.getComputedStyle(el);
32394
+ return style.display !== 'none' && style.visibility !== 'hidden';
32395
+ })
32396
+ .map((el) => el.src || el.getAttribute('src') || '')
32397
+ .filter((src) => typeof src === 'string' && src.includes('vscode-webview')))`,
32398
+ 5e3
32399
+ );
32400
+ const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
32401
+ if (Array.isArray(parsed)) {
32402
+ const urls = parsed.filter((src) => typeof src === "string" && src.length > 0);
32403
+ if (urls.length > 0) return new Set(urls);
32404
+ }
32405
+ } catch {
32406
+ }
32377
32407
  try {
32378
32408
  const urls = /* @__PURE__ */ new Set();
32379
32409
  const { frameTree } = await this.sendInternal("Page.getFrameTree", {}, 5e3);
@@ -32385,19 +32415,7 @@ ${data.message || ""}`.trim();
32385
32415
  for (const child of node?.childFrames || []) visit(child);
32386
32416
  };
32387
32417
  if (frameTree) visit(frameTree);
32388
- if (urls.size > 0) return urls;
32389
- } catch {
32390
- }
32391
- try {
32392
- const raw = await this.evaluate(
32393
- `JSON.stringify(Array.from(document.querySelectorAll('iframe,webview'))
32394
- .map((el) => el.src || el.getAttribute('src') || '')
32395
- .filter((src) => typeof src === 'string' && src.includes('vscode-webview')))`,
32396
- 5e3
32397
- );
32398
- const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
32399
- if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
32400
- return new Set(parsed.filter((src) => typeof src === "string" && src.length > 0));
32418
+ return urls;
32401
32419
  } catch {
32402
32420
  return /* @__PURE__ */ new Set();
32403
32421
  }
@@ -36781,7 +36799,7 @@ ${effect.notification.body || ""}`.trim();
36781
36799
  }
36782
36800
  const managed = runtimeSessionId ? h.agentStream?.getManagedSession(runtimeSessionId) : null;
36783
36801
  const targetSessionId = managed?.cdpSessionId || null;
36784
- const IDE_LEVEL_SCRIPTS = ["listModes", "setMode", "listModels", "setModel"];
36802
+ const IDE_LEVEL_SCRIPTS = provider.type === "claude-code-vscode" ? ["listModes", "setMode"] : ["listModes", "setMode", "listModels", "setModel"];
36785
36803
  if (IDE_LEVEL_SCRIPTS.includes(scriptName)) {
36786
36804
  if (targetSessionId) {
36787
36805
  try {
@@ -37700,14 +37718,18 @@ ${effect.notification.body || ""}`.trim();
37700
37718
  }
37701
37719
  const runtime = this.adapter.getRuntimeMetadata();
37702
37720
  this.maybeAppendRuntimeRecoveryMessage(runtime);
37703
- const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
37721
+ let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
37722
+ const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
37723
+ if (historyMessageCount !== null) {
37724
+ parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
37725
+ }
37704
37726
  const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
37705
37727
  if (controlValues) {
37706
- this.controlValues = controlValues;
37707
- } else if (Object.keys(this.controlValues).length > 0) {
37708
- this.controlValues = {};
37728
+ this.controlValues = { ...this.controlValues, ...controlValues };
37709
37729
  }
37710
37730
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
37731
+ const currentModel = typeof parsedStatus?.model === "string" && parsedStatus.model.trim() ? parsedStatus.model.trim() : typeof this.controlValues.model === "string" && this.controlValues.model.trim() ? this.controlValues.model.trim() : void 0;
37732
+ const currentPlan = typeof parsedStatus?.mode === "string" && parsedStatus.mode.trim() ? parsedStatus.mode.trim() : typeof this.controlValues.mode === "string" && this.controlValues.mode.trim() ? this.controlValues.mode.trim() : void 0;
37711
37733
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
37712
37734
  if (parsedMessages.length > 0) {
37713
37735
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -37744,6 +37766,8 @@ ${effect.notification.body || ""}`.trim();
37744
37766
  inputContent: ""
37745
37767
  },
37746
37768
  workspace: this.workingDir,
37769
+ currentModel,
37770
+ currentPlan,
37747
37771
  instanceId: this.instanceId,
37748
37772
  providerSessionId: this.providerSessionId,
37749
37773
  lastUpdated: Date.now(),
@@ -37933,6 +37957,15 @@ ${effect.notification.body || ""}`.trim();
37933
37957
  }
37934
37958
  applyProviderResponse(data, options) {
37935
37959
  if (!data || typeof data !== "object") return;
37960
+ const patchedProviderSessionId = typeof data.providerSessionId === "string" ? data.providerSessionId.trim() : "";
37961
+ if (patchedProviderSessionId) {
37962
+ this.promoteProviderSessionId(patchedProviderSessionId);
37963
+ }
37964
+ if (data.sessionEvent === "new_session") {
37965
+ this.runtimeMessages = [];
37966
+ this.suppressIdleHistoryReplay = false;
37967
+ this.adapter.clearHistory();
37968
+ }
37936
37969
  const controlValues = extractProviderControlValues(this.provider.controls, data);
37937
37970
  if (controlValues) {
37938
37971
  this.controlValues = { ...this.controlValues, ...controlValues };