@adhdev/daemon-core 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/daemon/dev-server.d.ts +6 -3
- package/dist/index.js +146 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +146 -30
- package/dist/index.mjs.map +1 -1
- package/dist/shared-types.d.ts +4 -0
- package/dist/status/builders.d.ts +4 -7
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/daemon/dev-auto-implement.ts +36 -8
- package/src/daemon/dev-cdp-handlers.ts +22 -3
- package/src/daemon/dev-server.ts +20 -14
- package/src/installer.ts +13 -0
- package/src/shared-types.ts +4 -0
- package/src/status/builders.ts +17 -16
- package/src/status/snapshot.ts +73 -2
|
@@ -107,9 +107,12 @@ export declare class DevServer implements DevServerContext {
|
|
|
107
107
|
event: string;
|
|
108
108
|
data: any;
|
|
109
109
|
}): void;
|
|
110
|
-
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
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
|
-
|
|
7128
|
-
|
|
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
|
|
7142
|
-
|
|
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
|
-
|
|
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 [
|
|
16706
|
-
|
|
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": "${
|
|
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": "${
|
|
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(
|
|
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": "${
|
|
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": "${
|
|
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": "${
|
|
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": "${
|
|
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": "${
|
|
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
|
-
/**
|
|
21120
|
-
*
|
|
21121
|
-
*
|
|
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
|
|
21125
|
-
if (cdp
|
|
21126
|
-
|
|
21127
|
-
|
|
21128
|
-
|
|
21129
|
-
|
|
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
|
-
|
|
21133
|
-
|
|
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",
|