adhdev 0.8.37 → 0.8.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4615,11 +4615,10 @@ function shouldIncludeRuntimeMetadata(profile) {
4615
4615
  }
4616
4616
  function findCdpManager(cdpManagers, key) {
4617
4617
  const exact = cdpManagers.get(key);
4618
- if (exact) return exact;
4618
+ if (exact) return exact.isConnected ? exact : null;
4619
4619
  const prefix = key + "_";
4620
- for (const [k, m] of cdpManagers.entries()) {
4621
- if (k.startsWith(prefix) && m.isConnected) return m;
4622
- }
4620
+ const matches = [...cdpManagers.entries()].filter(([k, m]) => m.isConnected && k.startsWith(prefix));
4621
+ if (matches.length === 1) return matches[0][1];
4623
4622
  return null;
4624
4623
  }
4625
4624
  function hasCdpManager(cdpManagers, key) {
@@ -4631,8 +4630,13 @@ function hasCdpManager(cdpManagers, key) {
4631
4630
  return false;
4632
4631
  }
4633
4632
  function isCdpConnected(cdpManagers, key) {
4634
- const m = findCdpManager(cdpManagers, key);
4635
- return m?.isConnected ?? false;
4633
+ const exact = cdpManagers.get(key);
4634
+ if (exact?.isConnected) return true;
4635
+ const prefix = key + "_";
4636
+ for (const [k, m] of cdpManagers.entries()) {
4637
+ if (m.isConnected && k.startsWith(prefix)) return true;
4638
+ }
4639
+ return false;
4636
4640
  }
4637
4641
  function buildFallbackControls(providerControls, serverModel, serverMode, acpConfigOptions, acpModes) {
4638
4642
  if (providerControls && providerControls.length > 0) return providerControls;
@@ -32239,6 +32243,56 @@ function parseMessageTime(value) {
32239
32243
  }
32240
32244
  return 0;
32241
32245
  }
32246
+ function stringifyPreviewContent(content) {
32247
+ if (typeof content === "string") return content;
32248
+ if (Array.isArray(content)) {
32249
+ return content.map((block) => {
32250
+ if (typeof block === "string") return block;
32251
+ if (block && typeof block === "object" && "text" in block) {
32252
+ return String(block.text || "");
32253
+ }
32254
+ return "";
32255
+ }).join(" ");
32256
+ }
32257
+ if (content && typeof content === "object" && "text" in content) {
32258
+ return String(content.text || "");
32259
+ }
32260
+ return String(content || "");
32261
+ }
32262
+ function normalizePreviewText(content) {
32263
+ return stringifyPreviewContent(content).replace(/\s+/g, " ").trim();
32264
+ }
32265
+ function clampPreviewText(value, maxChars = 120) {
32266
+ if (value.length <= maxChars) return value;
32267
+ if (maxChars <= 1) return value.slice(0, maxChars);
32268
+ return `${value.slice(0, maxChars - 1)}\u2026`;
32269
+ }
32270
+ function simplePreviewHash(value) {
32271
+ let h = 2166136261;
32272
+ for (let i = 0; i < value.length; i += 1) {
32273
+ h ^= value.charCodeAt(i);
32274
+ h = h * 16777619 >>> 0;
32275
+ }
32276
+ return h.toString(16);
32277
+ }
32278
+ function getLastDisplayMessage(session) {
32279
+ const messages = session.activeChat?.messages;
32280
+ if (!Array.isArray(messages) || messages.length === 0) return null;
32281
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
32282
+ const candidate = messages[i];
32283
+ const role = typeof candidate?.role === "string" ? candidate.role : "";
32284
+ if (role === "system") continue;
32285
+ const preview = clampPreviewText(normalizePreviewText(candidate?.content));
32286
+ if (!preview) continue;
32287
+ return {
32288
+ role,
32289
+ preview,
32290
+ receivedAt: parseMessageTime(candidate?.receivedAt),
32291
+ hash: simplePreviewHash(`${role}:${preview}`)
32292
+ };
32293
+ }
32294
+ return null;
32295
+ }
32242
32296
  function getSessionMessageUpdatedAt(session) {
32243
32297
  const lastMessage = session.activeChat?.messages?.at?.(-1);
32244
32298
  if (!lastMessage) return 0;
@@ -32259,8 +32313,7 @@ function getSessionLastUsedAt(session) {
32259
32313
  return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
32260
32314
  }
32261
32315
  function getLastMessageRole(session) {
32262
- const role = session.activeChat?.messages?.at?.(-1)?.role;
32263
- return typeof role === "string" ? role : "";
32316
+ return getLastDisplayMessage(session)?.role || "";
32264
32317
  }
32265
32318
  function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
32266
32319
  if (status === "waiting_approval") {
@@ -32327,6 +32380,13 @@ function buildStatusSnapshot(options) {
32327
32380
  `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)}`
32328
32381
  );
32329
32382
  }
32383
+ const lastDisplayMessage = getLastDisplayMessage(sourceSession);
32384
+ if (lastDisplayMessage) {
32385
+ session.lastMessagePreview = lastDisplayMessage.preview;
32386
+ session.lastMessageRole = lastDisplayMessage.role;
32387
+ if (lastDisplayMessage.receivedAt > 0) session.lastMessageAt = lastDisplayMessage.receivedAt;
32388
+ session.lastMessageHash = lastDisplayMessage.hash;
32389
+ }
32330
32390
  }
32331
32391
  const includeMachineMetadata = profile !== "live";
32332
32392
  const terminalBackend = includeMachineMetadata ? getTerminalBackendRuntimeStatus() : void 0;
@@ -35194,8 +35254,18 @@ async function handleScriptHints(ctx, type, _req, res) {
35194
35254
  }
35195
35255
  async function handleCdpTargets(ctx, _req, res) {
35196
35256
  const targets = [];
35197
- for (const [ide, cdp] of ctx.cdpManagers.entries()) {
35198
- targets.push({ ide, connected: cdp.isConnected, port: cdp.getPort() });
35257
+ for (const [managerKey, cdp] of ctx.cdpManagers.entries()) {
35258
+ const underscore = managerKey.indexOf("_");
35259
+ const ideBase = underscore === -1 ? managerKey : managerKey.slice(0, underscore);
35260
+ targets.push({
35261
+ managerKey,
35262
+ ide: managerKey,
35263
+ ideBase,
35264
+ pageTitle: cdp.pageTitle,
35265
+ targetId: cdp.targetId,
35266
+ connected: cdp.isConnected,
35267
+ port: cdp.getPort()
35268
+ });
35199
35269
  }
35200
35270
  ctx.json(res, 200, { targets });
35201
35271
  }
@@ -36926,6 +36996,16 @@ function getDefaultAutoImplReference(ctx, category, type) {
36926
36996
  if (category === "cli") {
36927
36997
  return type === "codex-cli" ? "claude-cli" : "codex-cli";
36928
36998
  }
36999
+ if (category === "extension") {
37000
+ const preferred = ["claude-code-vscode", "codex", "cline", "roo-code"];
37001
+ for (const ref of preferred) {
37002
+ if (ref === type) continue;
37003
+ if (ctx.providerLoader.resolve(ref) || ctx.providerLoader.getMeta(ref)) return ref;
37004
+ }
37005
+ const all = ctx.providerLoader.getAll();
37006
+ const fb = all.find((p) => p.category === "extension" && p.type !== type);
37007
+ if (fb?.type) return fb.type;
37008
+ }
36929
37009
  return "antigravity";
36930
37010
  }
36931
37011
  function resolveAutoImplReference(ctx, category, requestedReference, targetType) {
@@ -37507,12 +37587,26 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
37507
37587
  return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification);
37508
37588
  }
37509
37589
  const lines = [];
37590
+ const cdpIdeType = provider.category === "extension" ? "cursor" : type;
37510
37591
  lines.push("You are implementing browser automation scripts for an IDE provider.");
37511
37592
  lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
37512
37593
  lines.push("");
37513
37594
  lines.push(`# Target: ${provider.name || type} (${type})`);
37514
37595
  lines.push(`Provider directory: \`${providerDir}\``);
37515
37596
  lines.push("");
37597
+ if (provider.category === "extension") {
37598
+ lines.push("## CDP host (extension providers)");
37599
+ lines.push(
37600
+ `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.`
37601
+ );
37602
+ lines.push(
37603
+ `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.`
37604
+ );
37605
+ lines.push(
37606
+ "For VS Code hosts, use `vscode` or full `vscode_<targetId>` managerKey in every curl below."
37607
+ );
37608
+ lines.push("");
37609
+ }
37516
37610
  const funcToFile = {
37517
37611
  readChat: "read_chat.js",
37518
37612
  sendMessage: "send_message.js",
@@ -37693,14 +37787,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
37693
37787
  lines.push("```bash");
37694
37788
  lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cdp/evaluate \\`);
37695
37789
  lines.push(` -H "Content-Type: application/json" \\`);
37696
- lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${type}"}'`);
37790
+ lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${cdpIdeType}"}'`);
37697
37791
  lines.push("```");
37698
37792
  lines.push("");
37699
37793
  lines.push("### 2. Test your generated function");
37700
37794
  lines.push("Once you save the file, test it by running:");
37701
37795
  lines.push("```bash");
37702
37796
  lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
37703
- 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}"}'`);
37797
+ 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}"}'`);
37704
37798
  lines.push("```");
37705
37799
  lines.push("");
37706
37800
  lines.push("### Task Workflow");
@@ -37710,10 +37804,12 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
37710
37804
  lines.push("4. Reload providers and TEST your script via the API.");
37711
37805
  lines.push("");
37712
37806
  lines.push("### \u{1F525} Advanced UI Parsing (CRUCIAL for `readChat`)");
37713
- 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.");
37807
+ lines.push(
37808
+ `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).`
37809
+ );
37714
37810
  lines.push("To achieve this, you MUST generate a live test scenario:");
37715
37811
  lines.push(`1. Early in your process, send a rich prompt to the IDE using the API:`);
37716
- 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"}}'\``);
37812
+ 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"}}'\``);
37717
37813
  lines.push("2. Wait a few seconds for the IDE AI to generate these elements in the UI.");
37718
37814
  lines.push("3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.");
37719
37815
  lines.push("4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).");
@@ -37724,27 +37820,27 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
37724
37820
  lines.push("### Step 1: Baseline \u2014 confirm idle");
37725
37821
  lines.push("```bash");
37726
37822
  lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
37727
- 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}"}')`);
37823
+ 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}"}')`);
37728
37824
  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')"`);
37729
37825
  lines.push("```");
37730
37826
  lines.push("");
37731
37827
  lines.push("### Step 2: Send a LONG message that triggers extended generation (10+ seconds)");
37732
37828
  lines.push("```bash");
37733
- 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."}}'`);
37829
+ 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."}}'`);
37734
37830
  lines.push("sleep 3");
37735
37831
  lines.push("```");
37736
37832
  lines.push("");
37737
37833
  lines.push("### Step 3: Check generating OR completed");
37738
37834
  lines.push("The AI may still be generating OR may have finished already. Either generating or idle is acceptable:");
37739
37835
  lines.push("```bash");
37740
- 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}"}')`);
37836
+ 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}"}')`);
37741
37837
  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}')"`);
37742
37838
  lines.push("```");
37743
37839
  lines.push("");
37744
37840
  lines.push("### Step 4: Wait for completion and verify new message");
37745
37841
  lines.push("```bash");
37746
37842
  lines.push("sleep 10");
37747
- 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}"}')`);
37843
+ 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}"}')`);
37748
37844
  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)}')"`);
37749
37845
  lines.push("```");
37750
37846
  lines.push("");
@@ -38267,6 +38363,7 @@ var init_dev_server = __esm({
38267
38363
  init_scaffold_template();
38268
38364
  init_version_archive();
38269
38365
  init_logger();
38366
+ init_builders();
38270
38367
  init_dev_cdp_handlers();
38271
38368
  init_dev_cli_debug();
38272
38369
  init_dev_auto_implement();
@@ -39644,22 +39741,29 @@ data: ${JSON.stringify(msg.data)}
39644
39741
  }
39645
39742
  }
39646
39743
  }
39647
- /** Get CDP manager — matching IDE when ideType specified, first connected one otherwise.
39648
- * DevServer is a debugging tool so first-connected fallback is acceptable,
39649
- * but callers should pass ideType when possible. */
39744
+ /**
39745
+ * Resolve a CDP manager for DevServer APIs.
39746
+ * - Pass full **managerKey** from `GET /api/cdp/targets` when multiple Cursor/VS Code windows are open
39747
+ * (e.g. `cursor_0006DE34…`); short `cursor` only works when it maps to exactly one connected manager.
39748
+ * - With `ideType` omitted: only succeeds when exactly one connected manager exists.
39749
+ */
39650
39750
  getCdp(ideType) {
39651
39751
  if (ideType) {
39652
- const cdp = this.cdpManagers.get(ideType);
39653
- if (cdp?.isConnected) return cdp;
39654
- for (const [k, m] of this.cdpManagers.entries()) {
39655
- if (k.startsWith(ideType + "_") && m.isConnected) return m;
39656
- }
39657
- LOG.warn("DevServer", `getCdp: no manager found for ideType '${ideType}', available: [${[...this.cdpManagers.keys()].join(", ")}]`);
39752
+ const cdp = findCdpManager(this.cdpManagers, ideType);
39753
+ if (cdp) return cdp;
39754
+ LOG.warn(
39755
+ "DevServer",
39756
+ `getCdp: no unique match for '${ideType}', available: [${[...this.cdpManagers.keys()].join(", ")}] \u2014 use managerKey from GET /api/cdp/targets`
39757
+ );
39658
39758
  return null;
39659
39759
  }
39660
- for (const cdp of this.cdpManagers.values()) {
39661
- if (cdp.isConnected) return cdp;
39662
- }
39760
+ const connected = [...this.cdpManagers.entries()].filter(([, m]) => m.isConnected);
39761
+ if (connected.length === 1) return connected[0][1];
39762
+ if (connected.length === 0) return null;
39763
+ LOG.warn(
39764
+ "DevServer",
39765
+ `getCdp: ideType omitted but ${connected.length} CDP windows \u2014 pass managerKey from GET /api/cdp/targets`
39766
+ );
39663
39767
  return null;
39664
39768
  }
39665
39769
  json(res, status, data) {
@@ -40350,6 +40454,19 @@ var init_installer = __esm({
40350
40454
  requiresApiKey: true,
40351
40455
  apiKeyName: "Anthropic/OpenAI API key"
40352
40456
  },
40457
+ {
40458
+ id: "claude-code-vscode",
40459
+ name: "Claude Code",
40460
+ displayName: "Claude Code (Anthropic)",
40461
+ marketplaceId: "anthropic.claude-code",
40462
+ description: "Anthropic Claude Code agent in VS Code\u2013compatible editors",
40463
+ category: "ai-agent",
40464
+ icon: "\u{1F7E0}",
40465
+ recommended: true,
40466
+ requiresApiKey: true,
40467
+ apiKeyName: "Anthropic account",
40468
+ website: "https://www.anthropic.com/claude-code"
40469
+ },
40353
40470
  {
40354
40471
  id: "continue",
40355
40472
  name: "Continue",
@@ -49410,7 +49527,7 @@ var init_adhdev_daemon = __esm({
49410
49527
  import_ws3 = require("ws");
49411
49528
  import_chalk2 = __toESM(require("chalk"));
49412
49529
  init_version();
49413
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.37" });
49530
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.39" });
49414
49531
  ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
49415
49532
  "generating",
49416
49533
  "waiting_approval",