@adhdev/daemon-core 0.8.36 → 0.8.38

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.
@@ -107,9 +107,12 @@ export declare class DevServer implements DevServerContext {
107
107
  event: string;
108
108
  data: any;
109
109
  }): void;
110
- /** Get CDP manager — matching IDE when ideType specified, first connected one otherwise.
111
- * DevServer is a debugging tool so first-connected fallback is acceptable,
112
- * but callers should pass ideType when possible. */
110
+ /**
111
+ * Resolve a CDP manager for DevServer APIs.
112
+ * - Pass full **managerKey** from `GET /api/cdp/targets` when multiple Cursor/VS Code windows are open
113
+ * (e.g. `cursor_0006DE34…`); short `cursor` only works when it maps to exactly one connected manager.
114
+ * - With `ideType` omitted: only succeeds when exactly one connected manager exists.
115
+ */
113
116
  getCdp(ideType?: string): DaemonCdpManager | null;
114
117
  json(res: http.ServerResponse, status: number, data: any): void;
115
118
  readBody(req: http.IncomingMessage): Promise<any>;
package/dist/index.js CHANGED
@@ -7122,11 +7122,10 @@ function shouldIncludeRuntimeMetadata(profile) {
7122
7122
  }
7123
7123
  function findCdpManager(cdpManagers, key) {
7124
7124
  const exact = cdpManagers.get(key);
7125
- if (exact) return exact;
7125
+ if (exact) return exact.isConnected ? exact : null;
7126
7126
  const prefix = key + "_";
7127
- for (const [k, m] of cdpManagers.entries()) {
7128
- if (k.startsWith(prefix) && m.isConnected) return m;
7129
- }
7127
+ const matches = [...cdpManagers.entries()].filter(([k, m]) => m.isConnected && k.startsWith(prefix));
7128
+ if (matches.length === 1) return matches[0][1];
7130
7129
  return null;
7131
7130
  }
7132
7131
  function hasCdpManager(cdpManagers, key) {
@@ -7138,8 +7137,13 @@ function hasCdpManager(cdpManagers, key) {
7138
7137
  return false;
7139
7138
  }
7140
7139
  function isCdpConnected(cdpManagers, key) {
7141
- const m = findCdpManager(cdpManagers, key);
7142
- return m?.isConnected ?? false;
7140
+ const exact = cdpManagers.get(key);
7141
+ if (exact?.isConnected) return true;
7142
+ const prefix = key + "_";
7143
+ for (const [k, m] of cdpManagers.entries()) {
7144
+ if (m.isConnected && k.startsWith(prefix)) return true;
7145
+ }
7146
+ return false;
7143
7147
  }
7144
7148
  function buildFallbackControls(providerControls, serverModel, serverMode, acpConfigOptions, acpModes) {
7145
7149
  if (providerControls && providerControls.length > 0) return providerControls;
@@ -13856,6 +13860,56 @@ function parseMessageTime(value) {
13856
13860
  }
13857
13861
  return 0;
13858
13862
  }
13863
+ function stringifyPreviewContent(content) {
13864
+ if (typeof content === "string") return content;
13865
+ if (Array.isArray(content)) {
13866
+ return content.map((block) => {
13867
+ if (typeof block === "string") return block;
13868
+ if (block && typeof block === "object" && "text" in block) {
13869
+ return String(block.text || "");
13870
+ }
13871
+ return "";
13872
+ }).join(" ");
13873
+ }
13874
+ if (content && typeof content === "object" && "text" in content) {
13875
+ return String(content.text || "");
13876
+ }
13877
+ return String(content || "");
13878
+ }
13879
+ function normalizePreviewText(content) {
13880
+ return stringifyPreviewContent(content).replace(/\s+/g, " ").trim();
13881
+ }
13882
+ function clampPreviewText(value, maxChars = 120) {
13883
+ if (value.length <= maxChars) return value;
13884
+ if (maxChars <= 1) return value.slice(0, maxChars);
13885
+ return `${value.slice(0, maxChars - 1)}\u2026`;
13886
+ }
13887
+ function simplePreviewHash(value) {
13888
+ let h = 2166136261;
13889
+ for (let i = 0; i < value.length; i += 1) {
13890
+ h ^= value.charCodeAt(i);
13891
+ h = h * 16777619 >>> 0;
13892
+ }
13893
+ return h.toString(16);
13894
+ }
13895
+ function getLastDisplayMessage(session) {
13896
+ const messages = session.activeChat?.messages;
13897
+ if (!Array.isArray(messages) || messages.length === 0) return null;
13898
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
13899
+ const candidate = messages[i];
13900
+ const role = typeof candidate?.role === "string" ? candidate.role : "";
13901
+ if (role === "system") continue;
13902
+ const preview = clampPreviewText(normalizePreviewText(candidate?.content));
13903
+ if (!preview) continue;
13904
+ return {
13905
+ role,
13906
+ preview,
13907
+ receivedAt: parseMessageTime(candidate?.receivedAt),
13908
+ hash: simplePreviewHash(`${role}:${preview}`)
13909
+ };
13910
+ }
13911
+ return null;
13912
+ }
13859
13913
  function getSessionMessageUpdatedAt(session) {
13860
13914
  const lastMessage = session.activeChat?.messages?.at?.(-1);
13861
13915
  if (!lastMessage) return 0;
@@ -13876,8 +13930,7 @@ function getSessionLastUsedAt(session) {
13876
13930
  return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
13877
13931
  }
13878
13932
  function getLastMessageRole(session) {
13879
- const role = session.activeChat?.messages?.at?.(-1)?.role;
13880
- return typeof role === "string" ? role : "";
13933
+ return getLastDisplayMessage(session)?.role || "";
13881
13934
  }
13882
13935
  function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
13883
13936
  if (status === "waiting_approval") {
@@ -13944,6 +13997,13 @@ function buildStatusSnapshot(options) {
13944
13997
  `snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(sourceSession)} msgUpdatedAt=${getSessionMessageUpdatedAt(sourceSession)}`
13945
13998
  );
13946
13999
  }
14000
+ const lastDisplayMessage = getLastDisplayMessage(sourceSession);
14001
+ if (lastDisplayMessage) {
14002
+ session.lastMessagePreview = lastDisplayMessage.preview;
14003
+ session.lastMessageRole = lastDisplayMessage.role;
14004
+ if (lastDisplayMessage.receivedAt > 0) session.lastMessageAt = lastDisplayMessage.receivedAt;
14005
+ session.lastMessageHash = lastDisplayMessage.hash;
14006
+ }
13947
14007
  }
13948
14008
  const includeMachineMetadata = profile !== "live";
13949
14009
  const terminalBackend = includeMachineMetadata ? getTerminalBackendRuntimeStatus() : void 0;
@@ -16702,8 +16762,18 @@ async function handleScriptHints(ctx, type, _req, res) {
16702
16762
  }
16703
16763
  async function handleCdpTargets(ctx, _req, res) {
16704
16764
  const targets = [];
16705
- for (const [ide, cdp] of ctx.cdpManagers.entries()) {
16706
- targets.push({ ide, connected: cdp.isConnected, port: cdp.getPort() });
16765
+ for (const [managerKey, cdp] of ctx.cdpManagers.entries()) {
16766
+ const underscore = managerKey.indexOf("_");
16767
+ const ideBase = underscore === -1 ? managerKey : managerKey.slice(0, underscore);
16768
+ targets.push({
16769
+ managerKey,
16770
+ ide: managerKey,
16771
+ ideBase,
16772
+ pageTitle: cdp.pageTitle,
16773
+ targetId: cdp.targetId,
16774
+ connected: cdp.isConnected,
16775
+ port: cdp.getPort()
16776
+ });
16707
16777
  }
16708
16778
  ctx.json(res, 200, { targets });
16709
16779
  }
@@ -18422,6 +18492,16 @@ function getDefaultAutoImplReference(ctx, category, type) {
18422
18492
  if (category === "cli") {
18423
18493
  return type === "codex-cli" ? "claude-cli" : "codex-cli";
18424
18494
  }
18495
+ if (category === "extension") {
18496
+ const preferred = ["claude-code-vscode", "codex", "cline", "roo-code"];
18497
+ for (const ref of preferred) {
18498
+ if (ref === type) continue;
18499
+ if (ctx.providerLoader.resolve(ref) || ctx.providerLoader.getMeta(ref)) return ref;
18500
+ }
18501
+ const all = ctx.providerLoader.getAll();
18502
+ const fb = all.find((p) => p.category === "extension" && p.type !== type);
18503
+ if (fb?.type) return fb.type;
18504
+ }
18425
18505
  return "antigravity";
18426
18506
  }
18427
18507
  function resolveAutoImplReference(ctx, category, requestedReference, targetType) {
@@ -19003,12 +19083,26 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19003
19083
  return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification);
19004
19084
  }
19005
19085
  const lines = [];
19086
+ const cdpIdeType = provider.category === "extension" ? "cursor" : type;
19006
19087
  lines.push("You are implementing browser automation scripts for an IDE provider.");
19007
19088
  lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
19008
19089
  lines.push("");
19009
19090
  lines.push(`# Target: ${provider.name || type} (${type})`);
19010
19091
  lines.push(`Provider directory: \`${providerDir}\``);
19011
19092
  lines.push("");
19093
+ if (provider.category === "extension") {
19094
+ lines.push("## CDP host (extension providers)");
19095
+ lines.push(
19096
+ `Extension **${type}** runs inside a host IDE. For \`/api/scripts/run\` and \`/api/cdp/evaluate\`, keep \`"type": "${type}"\` (which provider scripts run) but set \`"ideType"\` to the DevServer CDP **managerKey** for that window.`
19097
+ );
19098
+ lines.push(
19099
+ `Examples use \`"ideType": "${cdpIdeType}"\` (Cursor). If **multiple** IDE windows are connected, run \`GET /api/cdp/targets\` and use the correct \`managerKey\` / \`pageTitle\` \u2014 short \`cursor\` or \`vscode\` only works when it uniquely identifies one window.`
19100
+ );
19101
+ lines.push(
19102
+ "For VS Code hosts, use `vscode` or full `vscode_<targetId>` managerKey in every curl below."
19103
+ );
19104
+ lines.push("");
19105
+ }
19012
19106
  const funcToFile = {
19013
19107
  readChat: "read_chat.js",
19014
19108
  sendMessage: "send_message.js",
@@ -19189,14 +19283,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19189
19283
  lines.push("```bash");
19190
19284
  lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cdp/evaluate \\`);
19191
19285
  lines.push(` -H "Content-Type: application/json" \\`);
19192
- lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${type}"}'`);
19286
+ lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${cdpIdeType}"}'`);
19193
19287
  lines.push("```");
19194
19288
  lines.push("");
19195
19289
  lines.push("### 2. Test your generated function");
19196
19290
  lines.push("Once you save the file, test it by running:");
19197
19291
  lines.push("```bash");
19198
19292
  lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
19199
- lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}'`);
19293
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${cdpIdeType}"}'`);
19200
19294
  lines.push("```");
19201
19295
  lines.push("");
19202
19296
  lines.push("### Task Workflow");
@@ -19206,10 +19300,12 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19206
19300
  lines.push("4. Reload providers and TEST your script via the API.");
19207
19301
  lines.push("");
19208
19302
  lines.push("### \u{1F525} Advanced UI Parsing (CRUCIAL for `readChat`)");
19209
- lines.push("Your `readChat` must flawlessly parse complex UI elements (tables, code blocks, tool calls, and AI thoughts). The quality must match the `antigravity` reference.");
19303
+ lines.push(
19304
+ `Your \`readChat\` must flawlessly parse complex UI elements (tables, code blocks, tool calls, and AI thoughts). Match the depth of the **${referenceType || "reference"}** scripts above (patterns and structure, not necessarily the same DOM).`
19305
+ );
19210
19306
  lines.push("To achieve this, you MUST generate a live test scenario:");
19211
19307
  lines.push(`1. Early in your process, send a rich prompt to the IDE using the API:`);
19212
- lines.push(` \`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "sendMessage", "type": "${type}", "ideType": "${type}", "args": {"message": "Write a python script, draw a markdown table, use a tool, and show your reasoning/thought process"}}'\``);
19308
+ lines.push(` \`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "sendMessage", "type": "${type}", "ideType": "${cdpIdeType}", "args": {"message": "Write a python script, draw a markdown table, use a tool, and show your reasoning/thought process"}}'\``);
19213
19309
  lines.push("2. Wait a few seconds for the IDE AI to generate these elements in the UI.");
19214
19310
  lines.push("3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.");
19215
19311
  lines.push("4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).");
@@ -19220,27 +19316,27 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19220
19316
  lines.push("### Step 1: Baseline \u2014 confirm idle");
19221
19317
  lines.push("```bash");
19222
19318
  lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
19223
- lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}')`);
19319
+ lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${cdpIdeType}"}')`);
19224
19320
  lines.push(`echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); r=d.get('result',d); r=json.loads(r) if isinstance(r,str) else r; assert r.get('status')=='idle', f'Expected idle, got {r.get(chr(34)+chr(115)+chr(116)+chr(97)+chr(116)+chr(117)+chr(115)+chr(34))}'; print('Step 1 PASS: status=idle')"`);
19225
19321
  lines.push("```");
19226
19322
  lines.push("");
19227
19323
  lines.push("### Step 2: Send a LONG message that triggers extended generation (10+ seconds)");
19228
19324
  lines.push("```bash");
19229
- lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "sendMessage", "type": "${type}", "ideType": "${type}", "args": {"message": "Write an extremely detailed 5000-word essay about the history of artificial intelligence from Alan Turing to 2025. Be very thorough and verbose."}}'`);
19325
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "sendMessage", "type": "${type}", "ideType": "${cdpIdeType}", "args": {"message": "Write an extremely detailed 5000-word essay about the history of artificial intelligence from Alan Turing to 2025. Be very thorough and verbose."}}'`);
19230
19326
  lines.push("sleep 3");
19231
19327
  lines.push("```");
19232
19328
  lines.push("");
19233
19329
  lines.push("### Step 3: Check generating OR completed");
19234
19330
  lines.push("The AI may still be generating OR may have finished already. Either generating or idle is acceptable:");
19235
19331
  lines.push("```bash");
19236
- lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}')`);
19332
+ lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${cdpIdeType}"}')`);
19237
19333
  lines.push(`echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); r=d.get('result',d); r=json.loads(r) if isinstance(r,str) else r; s=r.get('status'); assert s in ('generating','idle','waiting_approval'), f'Unexpected: {s}'; print(f'Step 3 PASS: status={s}')"`);
19238
19334
  lines.push("```");
19239
19335
  lines.push("");
19240
19336
  lines.push("### Step 4: Wait for completion and verify new message");
19241
19337
  lines.push("```bash");
19242
19338
  lines.push("sleep 10");
19243
- lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}')`);
19339
+ lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${cdpIdeType}"}')`);
19244
19340
  lines.push(`echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); r=d.get('result',d); r=json.loads(r) if isinstance(r,str) else r; s=r.get('status'); msgs=r.get('messages',[]); assert s=='idle', f'Expected idle, got {s}'; assert len(msgs)>0, 'No messages'; print(f'Step 4 PASS: status={s}, messages={len(msgs)}')"`);
19245
19341
  lines.push("```");
19246
19342
  lines.push("");
@@ -21116,22 +21212,29 @@ data: ${JSON.stringify(msg.data)}
21116
21212
  }
21117
21213
  }
21118
21214
  }
21119
- /** Get CDP manager — matching IDE when ideType specified, first connected one otherwise.
21120
- * DevServer is a debugging tool so first-connected fallback is acceptable,
21121
- * but callers should pass ideType when possible. */
21215
+ /**
21216
+ * Resolve a CDP manager for DevServer APIs.
21217
+ * - Pass full **managerKey** from `GET /api/cdp/targets` when multiple Cursor/VS Code windows are open
21218
+ * (e.g. `cursor_0006DE34…`); short `cursor` only works when it maps to exactly one connected manager.
21219
+ * - With `ideType` omitted: only succeeds when exactly one connected manager exists.
21220
+ */
21122
21221
  getCdp(ideType) {
21123
21222
  if (ideType) {
21124
- const cdp = this.cdpManagers.get(ideType);
21125
- if (cdp?.isConnected) return cdp;
21126
- for (const [k, m] of this.cdpManagers.entries()) {
21127
- if (k.startsWith(ideType + "_") && m.isConnected) return m;
21128
- }
21129
- LOG.warn("DevServer", `getCdp: no manager found for ideType '${ideType}', available: [${[...this.cdpManagers.keys()].join(", ")}]`);
21223
+ const cdp = findCdpManager(this.cdpManagers, ideType);
21224
+ if (cdp) return cdp;
21225
+ LOG.warn(
21226
+ "DevServer",
21227
+ `getCdp: no unique match for '${ideType}', available: [${[...this.cdpManagers.keys()].join(", ")}] \u2014 use managerKey from GET /api/cdp/targets`
21228
+ );
21130
21229
  return null;
21131
21230
  }
21132
- for (const cdp of this.cdpManagers.values()) {
21133
- if (cdp.isConnected) return cdp;
21134
- }
21231
+ const connected = [...this.cdpManagers.entries()].filter(([, m]) => m.isConnected);
21232
+ if (connected.length === 1) return connected[0][1];
21233
+ if (connected.length === 0) return null;
21234
+ LOG.warn(
21235
+ "DevServer",
21236
+ `getCdp: ideType omitted but ${connected.length} CDP windows \u2014 pass managerKey from GET /api/cdp/targets`
21237
+ );
21135
21238
  return null;
21136
21239
  }
21137
21240
  json(res, status, data) {
@@ -21705,6 +21808,19 @@ var EXTENSION_CATALOG = [
21705
21808
  requiresApiKey: true,
21706
21809
  apiKeyName: "Anthropic/OpenAI API key"
21707
21810
  },
21811
+ {
21812
+ id: "claude-code-vscode",
21813
+ name: "Claude Code",
21814
+ displayName: "Claude Code (Anthropic)",
21815
+ marketplaceId: "anthropic.claude-code",
21816
+ description: "Anthropic Claude Code agent in VS Code\u2013compatible editors",
21817
+ category: "ai-agent",
21818
+ icon: "\u{1F7E0}",
21819
+ recommended: true,
21820
+ requiresApiKey: true,
21821
+ apiKeyName: "Anthropic account",
21822
+ website: "https://www.anthropic.com/claude-code"
21823
+ },
21708
21824
  {
21709
21825
  id: "continue",
21710
21826
  name: "Continue",