@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.
package/dist/index.mjs CHANGED
@@ -7035,11 +7035,10 @@ function shouldIncludeRuntimeMetadata(profile) {
7035
7035
  }
7036
7036
  function findCdpManager(cdpManagers, key) {
7037
7037
  const exact = cdpManagers.get(key);
7038
- if (exact) return exact;
7038
+ if (exact) return exact.isConnected ? exact : null;
7039
7039
  const prefix = key + "_";
7040
- for (const [k, m] of cdpManagers.entries()) {
7041
- if (k.startsWith(prefix) && m.isConnected) return m;
7042
- }
7040
+ const matches = [...cdpManagers.entries()].filter(([k, m]) => m.isConnected && k.startsWith(prefix));
7041
+ if (matches.length === 1) return matches[0][1];
7043
7042
  return null;
7044
7043
  }
7045
7044
  function hasCdpManager(cdpManagers, key) {
@@ -7051,8 +7050,13 @@ function hasCdpManager(cdpManagers, key) {
7051
7050
  return false;
7052
7051
  }
7053
7052
  function isCdpConnected(cdpManagers, key) {
7054
- const m = findCdpManager(cdpManagers, key);
7055
- return m?.isConnected ?? false;
7053
+ const exact = cdpManagers.get(key);
7054
+ if (exact?.isConnected) return true;
7055
+ const prefix = key + "_";
7056
+ for (const [k, m] of cdpManagers.entries()) {
7057
+ if (m.isConnected && k.startsWith(prefix)) return true;
7058
+ }
7059
+ return false;
7056
7060
  }
7057
7061
  function buildFallbackControls(providerControls, serverModel, serverMode, acpConfigOptions, acpModes) {
7058
7062
  if (providerControls && providerControls.length > 0) return providerControls;
@@ -13774,6 +13778,56 @@ function parseMessageTime(value) {
13774
13778
  }
13775
13779
  return 0;
13776
13780
  }
13781
+ function stringifyPreviewContent(content) {
13782
+ if (typeof content === "string") return content;
13783
+ if (Array.isArray(content)) {
13784
+ return content.map((block) => {
13785
+ if (typeof block === "string") return block;
13786
+ if (block && typeof block === "object" && "text" in block) {
13787
+ return String(block.text || "");
13788
+ }
13789
+ return "";
13790
+ }).join(" ");
13791
+ }
13792
+ if (content && typeof content === "object" && "text" in content) {
13793
+ return String(content.text || "");
13794
+ }
13795
+ return String(content || "");
13796
+ }
13797
+ function normalizePreviewText(content) {
13798
+ return stringifyPreviewContent(content).replace(/\s+/g, " ").trim();
13799
+ }
13800
+ function clampPreviewText(value, maxChars = 120) {
13801
+ if (value.length <= maxChars) return value;
13802
+ if (maxChars <= 1) return value.slice(0, maxChars);
13803
+ return `${value.slice(0, maxChars - 1)}\u2026`;
13804
+ }
13805
+ function simplePreviewHash(value) {
13806
+ let h = 2166136261;
13807
+ for (let i = 0; i < value.length; i += 1) {
13808
+ h ^= value.charCodeAt(i);
13809
+ h = h * 16777619 >>> 0;
13810
+ }
13811
+ return h.toString(16);
13812
+ }
13813
+ function getLastDisplayMessage(session) {
13814
+ const messages = session.activeChat?.messages;
13815
+ if (!Array.isArray(messages) || messages.length === 0) return null;
13816
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
13817
+ const candidate = messages[i];
13818
+ const role = typeof candidate?.role === "string" ? candidate.role : "";
13819
+ if (role === "system") continue;
13820
+ const preview = clampPreviewText(normalizePreviewText(candidate?.content));
13821
+ if (!preview) continue;
13822
+ return {
13823
+ role,
13824
+ preview,
13825
+ receivedAt: parseMessageTime(candidate?.receivedAt),
13826
+ hash: simplePreviewHash(`${role}:${preview}`)
13827
+ };
13828
+ }
13829
+ return null;
13830
+ }
13777
13831
  function getSessionMessageUpdatedAt(session) {
13778
13832
  const lastMessage = session.activeChat?.messages?.at?.(-1);
13779
13833
  if (!lastMessage) return 0;
@@ -13794,8 +13848,7 @@ function getSessionLastUsedAt(session) {
13794
13848
  return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
13795
13849
  }
13796
13850
  function getLastMessageRole(session) {
13797
- const role = session.activeChat?.messages?.at?.(-1)?.role;
13798
- return typeof role === "string" ? role : "";
13851
+ return getLastDisplayMessage(session)?.role || "";
13799
13852
  }
13800
13853
  function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
13801
13854
  if (status === "waiting_approval") {
@@ -13862,6 +13915,13 @@ function buildStatusSnapshot(options) {
13862
13915
  `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)}`
13863
13916
  );
13864
13917
  }
13918
+ const lastDisplayMessage = getLastDisplayMessage(sourceSession);
13919
+ if (lastDisplayMessage) {
13920
+ session.lastMessagePreview = lastDisplayMessage.preview;
13921
+ session.lastMessageRole = lastDisplayMessage.role;
13922
+ if (lastDisplayMessage.receivedAt > 0) session.lastMessageAt = lastDisplayMessage.receivedAt;
13923
+ session.lastMessageHash = lastDisplayMessage.hash;
13924
+ }
13865
13925
  }
13866
13926
  const includeMachineMetadata = profile !== "live";
13867
13927
  const terminalBackend = includeMachineMetadata ? getTerminalBackendRuntimeStatus() : void 0;
@@ -16620,8 +16680,18 @@ async function handleScriptHints(ctx, type, _req, res) {
16620
16680
  }
16621
16681
  async function handleCdpTargets(ctx, _req, res) {
16622
16682
  const targets = [];
16623
- for (const [ide, cdp] of ctx.cdpManagers.entries()) {
16624
- targets.push({ ide, connected: cdp.isConnected, port: cdp.getPort() });
16683
+ for (const [managerKey, cdp] of ctx.cdpManagers.entries()) {
16684
+ const underscore = managerKey.indexOf("_");
16685
+ const ideBase = underscore === -1 ? managerKey : managerKey.slice(0, underscore);
16686
+ targets.push({
16687
+ managerKey,
16688
+ ide: managerKey,
16689
+ ideBase,
16690
+ pageTitle: cdp.pageTitle,
16691
+ targetId: cdp.targetId,
16692
+ connected: cdp.isConnected,
16693
+ port: cdp.getPort()
16694
+ });
16625
16695
  }
16626
16696
  ctx.json(res, 200, { targets });
16627
16697
  }
@@ -18340,6 +18410,16 @@ function getDefaultAutoImplReference(ctx, category, type) {
18340
18410
  if (category === "cli") {
18341
18411
  return type === "codex-cli" ? "claude-cli" : "codex-cli";
18342
18412
  }
18413
+ if (category === "extension") {
18414
+ const preferred = ["claude-code-vscode", "codex", "cline", "roo-code"];
18415
+ for (const ref of preferred) {
18416
+ if (ref === type) continue;
18417
+ if (ctx.providerLoader.resolve(ref) || ctx.providerLoader.getMeta(ref)) return ref;
18418
+ }
18419
+ const all = ctx.providerLoader.getAll();
18420
+ const fb = all.find((p) => p.category === "extension" && p.type !== type);
18421
+ if (fb?.type) return fb.type;
18422
+ }
18343
18423
  return "antigravity";
18344
18424
  }
18345
18425
  function resolveAutoImplReference(ctx, category, requestedReference, targetType) {
@@ -18921,12 +19001,26 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
18921
19001
  return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification);
18922
19002
  }
18923
19003
  const lines = [];
19004
+ const cdpIdeType = provider.category === "extension" ? "cursor" : type;
18924
19005
  lines.push("You are implementing browser automation scripts for an IDE provider.");
18925
19006
  lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
18926
19007
  lines.push("");
18927
19008
  lines.push(`# Target: ${provider.name || type} (${type})`);
18928
19009
  lines.push(`Provider directory: \`${providerDir}\``);
18929
19010
  lines.push("");
19011
+ if (provider.category === "extension") {
19012
+ lines.push("## CDP host (extension providers)");
19013
+ lines.push(
19014
+ `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.`
19015
+ );
19016
+ lines.push(
19017
+ `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.`
19018
+ );
19019
+ lines.push(
19020
+ "For VS Code hosts, use `vscode` or full `vscode_<targetId>` managerKey in every curl below."
19021
+ );
19022
+ lines.push("");
19023
+ }
18930
19024
  const funcToFile = {
18931
19025
  readChat: "read_chat.js",
18932
19026
  sendMessage: "send_message.js",
@@ -19107,14 +19201,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19107
19201
  lines.push("```bash");
19108
19202
  lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cdp/evaluate \\`);
19109
19203
  lines.push(` -H "Content-Type: application/json" \\`);
19110
- lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${type}"}'`);
19204
+ lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${cdpIdeType}"}'`);
19111
19205
  lines.push("```");
19112
19206
  lines.push("");
19113
19207
  lines.push("### 2. Test your generated function");
19114
19208
  lines.push("Once you save the file, test it by running:");
19115
19209
  lines.push("```bash");
19116
19210
  lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
19117
- 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}"}'`);
19211
+ 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}"}'`);
19118
19212
  lines.push("```");
19119
19213
  lines.push("");
19120
19214
  lines.push("### Task Workflow");
@@ -19124,10 +19218,12 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19124
19218
  lines.push("4. Reload providers and TEST your script via the API.");
19125
19219
  lines.push("");
19126
19220
  lines.push("### \u{1F525} Advanced UI Parsing (CRUCIAL for `readChat`)");
19127
- 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.");
19221
+ lines.push(
19222
+ `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).`
19223
+ );
19128
19224
  lines.push("To achieve this, you MUST generate a live test scenario:");
19129
19225
  lines.push(`1. Early in your process, send a rich prompt to the IDE using the API:`);
19130
- 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"}}'\``);
19226
+ 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"}}'\``);
19131
19227
  lines.push("2. Wait a few seconds for the IDE AI to generate these elements in the UI.");
19132
19228
  lines.push("3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.");
19133
19229
  lines.push("4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).");
@@ -19138,27 +19234,27 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19138
19234
  lines.push("### Step 1: Baseline \u2014 confirm idle");
19139
19235
  lines.push("```bash");
19140
19236
  lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
19141
- 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}"}')`);
19237
+ 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}"}')`);
19142
19238
  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')"`);
19143
19239
  lines.push("```");
19144
19240
  lines.push("");
19145
19241
  lines.push("### Step 2: Send a LONG message that triggers extended generation (10+ seconds)");
19146
19242
  lines.push("```bash");
19147
- 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."}}'`);
19243
+ 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."}}'`);
19148
19244
  lines.push("sleep 3");
19149
19245
  lines.push("```");
19150
19246
  lines.push("");
19151
19247
  lines.push("### Step 3: Check generating OR completed");
19152
19248
  lines.push("The AI may still be generating OR may have finished already. Either generating or idle is acceptable:");
19153
19249
  lines.push("```bash");
19154
- 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}"}')`);
19250
+ 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}"}')`);
19155
19251
  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}')"`);
19156
19252
  lines.push("```");
19157
19253
  lines.push("");
19158
19254
  lines.push("### Step 4: Wait for completion and verify new message");
19159
19255
  lines.push("```bash");
19160
19256
  lines.push("sleep 10");
19161
- 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}"}')`);
19257
+ 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}"}')`);
19162
19258
  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)}')"`);
19163
19259
  lines.push("```");
19164
19260
  lines.push("");
@@ -21034,22 +21130,29 @@ data: ${JSON.stringify(msg.data)}
21034
21130
  }
21035
21131
  }
21036
21132
  }
21037
- /** Get CDP manager — matching IDE when ideType specified, first connected one otherwise.
21038
- * DevServer is a debugging tool so first-connected fallback is acceptable,
21039
- * but callers should pass ideType when possible. */
21133
+ /**
21134
+ * Resolve a CDP manager for DevServer APIs.
21135
+ * - Pass full **managerKey** from `GET /api/cdp/targets` when multiple Cursor/VS Code windows are open
21136
+ * (e.g. `cursor_0006DE34…`); short `cursor` only works when it maps to exactly one connected manager.
21137
+ * - With `ideType` omitted: only succeeds when exactly one connected manager exists.
21138
+ */
21040
21139
  getCdp(ideType) {
21041
21140
  if (ideType) {
21042
- const cdp = this.cdpManagers.get(ideType);
21043
- if (cdp?.isConnected) return cdp;
21044
- for (const [k, m] of this.cdpManagers.entries()) {
21045
- if (k.startsWith(ideType + "_") && m.isConnected) return m;
21046
- }
21047
- LOG.warn("DevServer", `getCdp: no manager found for ideType '${ideType}', available: [${[...this.cdpManagers.keys()].join(", ")}]`);
21141
+ const cdp = findCdpManager(this.cdpManagers, ideType);
21142
+ if (cdp) return cdp;
21143
+ LOG.warn(
21144
+ "DevServer",
21145
+ `getCdp: no unique match for '${ideType}', available: [${[...this.cdpManagers.keys()].join(", ")}] \u2014 use managerKey from GET /api/cdp/targets`
21146
+ );
21048
21147
  return null;
21049
21148
  }
21050
- for (const cdp of this.cdpManagers.values()) {
21051
- if (cdp.isConnected) return cdp;
21052
- }
21149
+ const connected = [...this.cdpManagers.entries()].filter(([, m]) => m.isConnected);
21150
+ if (connected.length === 1) return connected[0][1];
21151
+ if (connected.length === 0) return null;
21152
+ LOG.warn(
21153
+ "DevServer",
21154
+ `getCdp: ideType omitted but ${connected.length} CDP windows \u2014 pass managerKey from GET /api/cdp/targets`
21155
+ );
21053
21156
  return null;
21054
21157
  }
21055
21158
  json(res, status, data) {
@@ -21628,6 +21731,19 @@ var EXTENSION_CATALOG = [
21628
21731
  requiresApiKey: true,
21629
21732
  apiKeyName: "Anthropic/OpenAI API key"
21630
21733
  },
21734
+ {
21735
+ id: "claude-code-vscode",
21736
+ name: "Claude Code",
21737
+ displayName: "Claude Code (Anthropic)",
21738
+ marketplaceId: "anthropic.claude-code",
21739
+ description: "Anthropic Claude Code agent in VS Code\u2013compatible editors",
21740
+ category: "ai-agent",
21741
+ icon: "\u{1F7E0}",
21742
+ recommended: true,
21743
+ requiresApiKey: true,
21744
+ apiKeyName: "Anthropic account",
21745
+ website: "https://www.anthropic.com/claude-code"
21746
+ },
21631
21747
  {
21632
21748
  id: "continue",
21633
21749
  name: "Continue",