@band-ai/sdk 0.4.2 → 0.4.4
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/{CopilotACPAdapter-Bj6NRdqd.d.ts → CursorACPAdapter-7-Jtl1LV.d.ts} +90 -1
- package/dist/{CopilotACPAdapter-HRvat7CP.d.cts → CursorACPAdapter-_YhrXRWq.d.cts} +90 -1
- package/dist/adapters.cjs +476 -128
- package/dist/adapters.d.cts +1 -1
- package/dist/adapters.d.ts +1 -1
- package/dist/adapters.js +5 -1
- package/dist/{chunk-KXLV645N.js → chunk-STUSNTHF.js} +463 -117
- package/dist/index.cjs +413 -65
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/package.json +6 -6
package/dist/adapters.cjs
CHANGED
|
@@ -990,7 +990,9 @@ __export(adapters_exports, {
|
|
|
990
990
|
CodexAppServerStdioClient: () => CodexAppServerStdioClient,
|
|
991
991
|
CodexJsonRpcError: () => CodexJsonRpcError,
|
|
992
992
|
CopilotACPAdapter: () => CopilotACPAdapter,
|
|
993
|
+
CursorACPAdapter: () => CursorACPAdapter,
|
|
993
994
|
DEFAULT_COPILOT_ACP_COMMAND: () => DEFAULT_COPILOT_ACP_COMMAND,
|
|
995
|
+
DEFAULT_CURSOR_ACP_COMMAND: () => DEFAULT_CURSOR_ACP_COMMAND,
|
|
994
996
|
DEFAULT_OMP_ACP_COMMAND: () => DEFAULT_OMP_ACP_COMMAND,
|
|
995
997
|
FAILURE_CODE_SESSION_CONFIG: () => FAILURE_CODE_SESSION_CONFIG,
|
|
996
998
|
GatewayHistoryConverter: () => GatewayHistoryConverter,
|
|
@@ -1696,15 +1698,20 @@ function systemUpdateParts(participantsMessage, contactsMessage) {
|
|
|
1696
1698
|
}
|
|
1697
1699
|
function buildConversationPrompt(options) {
|
|
1698
1700
|
const parts = [];
|
|
1699
|
-
if (options.isSessionBootstrap
|
|
1700
|
-
const historyText = options.history.raw.slice(-(options.maxHistoryMessages ?? 50)).map(formatHistoryLine).join("\n");
|
|
1701
|
-
|
|
1701
|
+
if (options.isSessionBootstrap) {
|
|
1702
|
+
const historyText = options.history.raw.slice(-(options.maxHistoryMessages ?? 50)).filter(isTextHistoryEntry).map(formatHistoryLine).join("\n");
|
|
1703
|
+
if (historyText) {
|
|
1704
|
+
parts.push(`${options.historyHeader}
|
|
1702
1705
|
${historyText}`);
|
|
1706
|
+
}
|
|
1703
1707
|
}
|
|
1704
1708
|
parts.push(...systemUpdateParts(options.participantsMessage, options.contactsMessage));
|
|
1705
1709
|
parts.push(options.currentMessage);
|
|
1706
1710
|
return parts.join("\n\n");
|
|
1707
1711
|
}
|
|
1712
|
+
function isTextHistoryEntry(entry) {
|
|
1713
|
+
return entry.message_type === void 0 || entry.message_type === "text";
|
|
1714
|
+
}
|
|
1708
1715
|
function formatHistoryLine(entry) {
|
|
1709
1716
|
const sender = String(entry.sender_name ?? entry.sender_type ?? "Unknown");
|
|
1710
1717
|
const content = String(entry.content ?? "");
|
|
@@ -2338,74 +2345,17 @@ function checkPort2(http, port) {
|
|
|
2338
2345
|
});
|
|
2339
2346
|
}
|
|
2340
2347
|
|
|
2341
|
-
// src/adapters/acp/types.ts
|
|
2342
|
-
var DEFAULT_ACP_SERVER_MODES = [
|
|
2343
|
-
{
|
|
2344
|
-
id: "default",
|
|
2345
|
-
name: "Default",
|
|
2346
|
-
description: "General-purpose chat mode"
|
|
2347
|
-
},
|
|
2348
|
-
{
|
|
2349
|
-
id: "code",
|
|
2350
|
-
name: "Code",
|
|
2351
|
-
description: "Route prompts toward coding peers when available"
|
|
2352
|
-
}
|
|
2353
|
-
];
|
|
2354
|
-
function createPendingPrompt(sessionId) {
|
|
2355
|
-
let markDone = () => void 0;
|
|
2356
|
-
const done = new Promise((resolve) => {
|
|
2357
|
-
markDone = resolve;
|
|
2358
|
-
});
|
|
2359
|
-
return {
|
|
2360
|
-
sessionId,
|
|
2361
|
-
done,
|
|
2362
|
-
markDone,
|
|
2363
|
-
terminalMessageSeen: false,
|
|
2364
|
-
completionTimer: null
|
|
2365
|
-
};
|
|
2366
|
-
}
|
|
2367
|
-
function choosePermissionOption(options) {
|
|
2368
|
-
if (options.length === 0) {
|
|
2369
|
-
return null;
|
|
2370
|
-
}
|
|
2371
|
-
return options.find((option) => option.kind === "allow_once") ?? options.find((option) => option.kind === "allow_always") ?? options[0];
|
|
2372
|
-
}
|
|
2373
|
-
function asJsonSafe(value) {
|
|
2374
|
-
if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2375
|
-
return value;
|
|
2376
|
-
}
|
|
2377
|
-
if (Array.isArray(value)) {
|
|
2378
|
-
return value.map((item) => asJsonSafe(item));
|
|
2379
|
-
}
|
|
2380
|
-
if (typeof value === "object") {
|
|
2381
|
-
if ("model_dump" in value && typeof value.model_dump === "function") {
|
|
2382
|
-
return asJsonSafe(value.model_dump());
|
|
2383
|
-
}
|
|
2384
|
-
if ("toJSON" in value && typeof value.toJSON === "function") {
|
|
2385
|
-
return asJsonSafe(value.toJSON());
|
|
2386
|
-
}
|
|
2387
|
-
return Object.fromEntries(
|
|
2388
|
-
Object.entries(value).map(([key, item]) => [key, asJsonSafe(item)])
|
|
2389
|
-
);
|
|
2390
|
-
}
|
|
2391
|
-
return String(value);
|
|
2392
|
-
}
|
|
2393
|
-
function normalizeMcpServers(mcpServers) {
|
|
2394
|
-
if (!mcpServers) {
|
|
2395
|
-
return [];
|
|
2396
|
-
}
|
|
2397
|
-
return mcpServers.map((server) => asJsonSafe(server)).filter((server) => !!server && typeof server === "object" && !Array.isArray(server));
|
|
2398
|
-
}
|
|
2399
|
-
|
|
2400
2348
|
// src/adapters/acp/client.ts
|
|
2401
2349
|
var BandACPClient = class {
|
|
2402
2350
|
sessionChunks = /* @__PURE__ */ new Map();
|
|
2403
2351
|
permissionHandler;
|
|
2352
|
+
extensionHandler;
|
|
2404
2353
|
// The handler is connection-scoped and required at construction, so it is
|
|
2405
2354
|
// already in place before the agent process is spawned: there is no window
|
|
2406
2355
|
// in which a `session/request_permission` has nowhere to go.
|
|
2407
|
-
constructor(permissionHandler) {
|
|
2356
|
+
constructor(permissionHandler, extensionHandler) {
|
|
2408
2357
|
this.permissionHandler = permissionHandler;
|
|
2358
|
+
this.extensionHandler = extensionHandler;
|
|
2409
2359
|
}
|
|
2410
2360
|
beginSession(sessionId) {
|
|
2411
2361
|
this.sessionChunks.set(sessionId, []);
|
|
@@ -2450,62 +2400,26 @@ var BandACPClient = class {
|
|
|
2450
2400
|
return chunks;
|
|
2451
2401
|
}
|
|
2452
2402
|
async extMethod(method, params) {
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
return {
|
|
2460
|
-
outcome: {
|
|
2461
|
-
type: "cancelled"
|
|
2462
|
-
}
|
|
2463
|
-
};
|
|
2464
|
-
}
|
|
2465
|
-
return {
|
|
2466
|
-
outcome: {
|
|
2467
|
-
type: "selected",
|
|
2468
|
-
optionId: selected.optionId
|
|
2469
|
-
}
|
|
2470
|
-
};
|
|
2471
|
-
}
|
|
2472
|
-
if (method === "cursor/create_plan") {
|
|
2473
|
-
return {
|
|
2474
|
-
outcome: {
|
|
2475
|
-
type: "approved"
|
|
2476
|
-
}
|
|
2477
|
-
};
|
|
2478
|
-
}
|
|
2479
|
-
return {};
|
|
2403
|
+
const result = await this.extensionHandler?.extMethod?.(
|
|
2404
|
+
method,
|
|
2405
|
+
params,
|
|
2406
|
+
{ sessionId: sessionIdFrom(params) }
|
|
2407
|
+
);
|
|
2408
|
+
return result ?? {};
|
|
2480
2409
|
}
|
|
2481
2410
|
async extNotification(method, params) {
|
|
2482
|
-
const sessionId =
|
|
2483
|
-
|
|
2411
|
+
const sessionId = sessionIdFrom(params);
|
|
2412
|
+
const chunks = await this.extensionHandler?.extNotification?.(
|
|
2413
|
+
method,
|
|
2414
|
+
params,
|
|
2415
|
+
{ sessionId }
|
|
2416
|
+
);
|
|
2417
|
+
const targetSessionId = sessionId ?? this.extensionHandler?.extensionSessionId?.() ?? null;
|
|
2418
|
+
if (!targetSessionId || !chunks) {
|
|
2484
2419
|
return;
|
|
2485
2420
|
}
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
const lines = todos.filter((todo) => !!todo && typeof todo === "object").map((todo) => `- [${todo.completed === true ? "x" : " "}] ${String(todo.content ?? "")}`).filter((line) => line.trim().length > 0);
|
|
2489
|
-
if (lines.length > 0) {
|
|
2490
|
-
this.appendChunk(sessionId, {
|
|
2491
|
-
chunkType: "plan",
|
|
2492
|
-
content: lines.join("\n"),
|
|
2493
|
-
metadata: {},
|
|
2494
|
-
streamed: false
|
|
2495
|
-
});
|
|
2496
|
-
}
|
|
2497
|
-
return;
|
|
2498
|
-
}
|
|
2499
|
-
if (method === "cursor/task") {
|
|
2500
|
-
const result = toOptionalString(params.result);
|
|
2501
|
-
if (result) {
|
|
2502
|
-
this.appendChunk(sessionId, {
|
|
2503
|
-
chunkType: "text",
|
|
2504
|
-
content: `[Task completed] ${result}`,
|
|
2505
|
-
metadata: {},
|
|
2506
|
-
streamed: false
|
|
2507
|
-
});
|
|
2508
|
-
}
|
|
2421
|
+
for (const chunk of chunks) {
|
|
2422
|
+
this.appendChunk(targetSessionId, chunk);
|
|
2509
2423
|
}
|
|
2510
2424
|
}
|
|
2511
2425
|
appendChunk(sessionId, chunk) {
|
|
@@ -2630,6 +2544,68 @@ function extractTextFromContent(content) {
|
|
|
2630
2544
|
function toOptionalString(value) {
|
|
2631
2545
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
2632
2546
|
}
|
|
2547
|
+
function sessionIdFrom(params) {
|
|
2548
|
+
return toOptionalString(params.sessionId) ?? toOptionalString(params.session_id);
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
// src/adapters/acp/types.ts
|
|
2552
|
+
var DEFAULT_ACP_SERVER_MODES = [
|
|
2553
|
+
{
|
|
2554
|
+
id: "default",
|
|
2555
|
+
name: "Default",
|
|
2556
|
+
description: "General-purpose chat mode"
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
id: "code",
|
|
2560
|
+
name: "Code",
|
|
2561
|
+
description: "Route prompts toward coding peers when available"
|
|
2562
|
+
}
|
|
2563
|
+
];
|
|
2564
|
+
function createPendingPrompt(sessionId) {
|
|
2565
|
+
let markDone = () => void 0;
|
|
2566
|
+
const done = new Promise((resolve) => {
|
|
2567
|
+
markDone = resolve;
|
|
2568
|
+
});
|
|
2569
|
+
return {
|
|
2570
|
+
sessionId,
|
|
2571
|
+
done,
|
|
2572
|
+
markDone,
|
|
2573
|
+
terminalMessageSeen: false,
|
|
2574
|
+
completionTimer: null
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
function choosePermissionOption(options) {
|
|
2578
|
+
if (options.length === 0) {
|
|
2579
|
+
return null;
|
|
2580
|
+
}
|
|
2581
|
+
return options.find((option) => option.kind === "allow_once") ?? options.find((option) => option.kind === "allow_always") ?? options[0];
|
|
2582
|
+
}
|
|
2583
|
+
function asJsonSafe(value) {
|
|
2584
|
+
if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2585
|
+
return value;
|
|
2586
|
+
}
|
|
2587
|
+
if (Array.isArray(value)) {
|
|
2588
|
+
return value.map((item) => asJsonSafe(item));
|
|
2589
|
+
}
|
|
2590
|
+
if (typeof value === "object") {
|
|
2591
|
+
if ("model_dump" in value && typeof value.model_dump === "function") {
|
|
2592
|
+
return asJsonSafe(value.model_dump());
|
|
2593
|
+
}
|
|
2594
|
+
if ("toJSON" in value && typeof value.toJSON === "function") {
|
|
2595
|
+
return asJsonSafe(value.toJSON());
|
|
2596
|
+
}
|
|
2597
|
+
return Object.fromEntries(
|
|
2598
|
+
Object.entries(value).map(([key, item]) => [key, asJsonSafe(item)])
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
return String(value);
|
|
2602
|
+
}
|
|
2603
|
+
function normalizeMcpServers(mcpServers) {
|
|
2604
|
+
if (!mcpServers) {
|
|
2605
|
+
return [];
|
|
2606
|
+
}
|
|
2607
|
+
return mcpServers.map((server) => asJsonSafe(server)).filter((server) => !!server && typeof server === "object" && !Array.isArray(server));
|
|
2608
|
+
}
|
|
2633
2609
|
|
|
2634
2610
|
// src/adapters/acp/loader.ts
|
|
2635
2611
|
init_errors();
|
|
@@ -2725,6 +2701,7 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
2725
2701
|
additionalMcpTools;
|
|
2726
2702
|
clientCapabilities;
|
|
2727
2703
|
connectionFactory;
|
|
2704
|
+
extensionHandler;
|
|
2728
2705
|
tcpEndpoint;
|
|
2729
2706
|
// The value's `generation` is the connection generation the session was
|
|
2730
2707
|
// last established/restored against. `client` is the exact BandACPClient
|
|
@@ -2789,6 +2766,7 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
2789
2766
|
this.additionalMcpTools = [...options.additionalMcpTools ?? []];
|
|
2790
2767
|
this.clientCapabilities = options.clientCapabilities;
|
|
2791
2768
|
this.connectionFactory = options.connectionFactory;
|
|
2769
|
+
this.extensionHandler = options.extensionHandler;
|
|
2792
2770
|
this.tcpEndpoint = tcpEndpoint;
|
|
2793
2771
|
this.resolvePermission = options.resolvePermission;
|
|
2794
2772
|
this.resolveSessionMode = options.resolveSessionMode;
|
|
@@ -2844,6 +2822,7 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
2844
2822
|
let client = null;
|
|
2845
2823
|
let sessionId;
|
|
2846
2824
|
let generation = 0;
|
|
2825
|
+
await this.onAcpTurnStarted(message, tools, context);
|
|
2847
2826
|
try {
|
|
2848
2827
|
const ensured = await this.ensureConnection();
|
|
2849
2828
|
connection = ensured.connection;
|
|
@@ -2854,6 +2833,7 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
2854
2833
|
}
|
|
2855
2834
|
sessionId = await this.getOrCreateSession(context.roomId, connection, generation, client);
|
|
2856
2835
|
const sessionKey = this.sessionKey(generation, sessionId);
|
|
2836
|
+
await this.onAcpSessionReady(message, tools, context, sessionId);
|
|
2857
2837
|
client.beginSession(sessionId);
|
|
2858
2838
|
const content = replaceUuidMentions(message.content, mentionSubjectsFromMetadata(message.metadata));
|
|
2859
2839
|
const messageWithContext = [...systemUpdateParts(participantsMessage, contactsMessage), content].join("\n\n");
|
|
@@ -2924,8 +2904,16 @@ ${messageWithContext}`;
|
|
|
2924
2904
|
...configError ? { optionId: configError.optionId, selectedValue: configError.selectedValue } : {}
|
|
2925
2905
|
}
|
|
2926
2906
|
);
|
|
2907
|
+
} finally {
|
|
2908
|
+
await this.onAcpTurnFinished(message, tools, context);
|
|
2927
2909
|
}
|
|
2928
2910
|
}
|
|
2911
|
+
async onAcpTurnStarted(_message, _tools, _context) {
|
|
2912
|
+
}
|
|
2913
|
+
async onAcpTurnFinished(_message, _tools, _context) {
|
|
2914
|
+
}
|
|
2915
|
+
async onAcpSessionReady(_message, _tools, _context, _sessionId) {
|
|
2916
|
+
}
|
|
2929
2917
|
// Best-effort: tells the agent to stop working on a turn Band has already
|
|
2930
2918
|
// given up waiting for (the ACP client has no way to force it), evicts the
|
|
2931
2919
|
// session so the room's next turn re-establishes rather than reuses it
|
|
@@ -3095,6 +3083,9 @@ ${messageWithContext}`;
|
|
|
3095
3083
|
sessionKey(generation, sessionId) {
|
|
3096
3084
|
return `${generation}:${sessionId}`;
|
|
3097
3085
|
}
|
|
3086
|
+
roomIdForSession(sessionId) {
|
|
3087
|
+
return [...this.roomToSession.entries()].find(([, owner]) => owner.sessionId === sessionId)?.[0];
|
|
3088
|
+
}
|
|
3098
3089
|
async ensureConnection() {
|
|
3099
3090
|
if (this.connection && !this.connection.signal.aborted) {
|
|
3100
3091
|
return { connection: this.connection, generation: this.connectionGeneration };
|
|
@@ -3131,7 +3122,10 @@ ${messageWithContext}`;
|
|
|
3131
3122
|
throw new Error(CONNECTION_ATTEMPT_SUPERSEDED_ERROR);
|
|
3132
3123
|
}
|
|
3133
3124
|
const owner = { generation: -1 };
|
|
3134
|
-
const client = new BandACPClient(
|
|
3125
|
+
const client = new BandACPClient(
|
|
3126
|
+
(params) => this.routePermissionRequest(params, owner.generation),
|
|
3127
|
+
this.extensionHandler
|
|
3128
|
+
);
|
|
3135
3129
|
handle = await (this.connectionFactory ? this.connectionFactory(client, {
|
|
3136
3130
|
command: this.command,
|
|
3137
3131
|
cwd: this.cwd,
|
|
@@ -4856,6 +4850,358 @@ var CopilotACPAdapter = class extends ACPClientAdapter {
|
|
|
4856
4850
|
}
|
|
4857
4851
|
};
|
|
4858
4852
|
|
|
4853
|
+
// src/adapters/cursor-acp/CursorACPAdapter.ts
|
|
4854
|
+
var DEFAULT_CURSOR_ACP_COMMAND = ["agent", "acp"];
|
|
4855
|
+
var DEFAULT_CURSOR_DECISION_TIMEOUT_MS = 3e5;
|
|
4856
|
+
var DEFAULT_CURSOR_MAX_PENDING_DECISIONS = 10;
|
|
4857
|
+
var CursorExtensions = class {
|
|
4858
|
+
adapter = null;
|
|
4859
|
+
todosBySession = /* @__PURE__ */ new Map();
|
|
4860
|
+
bind(adapter) {
|
|
4861
|
+
this.adapter = adapter;
|
|
4862
|
+
}
|
|
4863
|
+
async resolvePermission(request, signal) {
|
|
4864
|
+
return this.adapter?.resolveCursorPermission(request, signal);
|
|
4865
|
+
}
|
|
4866
|
+
extensionSessionId() {
|
|
4867
|
+
return this.adapter?.extensionSessionId() ?? null;
|
|
4868
|
+
}
|
|
4869
|
+
async extMethod(method, params, context) {
|
|
4870
|
+
return this.adapter?.resolveExtension(method, params, context.sessionId) ?? null;
|
|
4871
|
+
}
|
|
4872
|
+
async extNotification(method, params, context) {
|
|
4873
|
+
const sessionId = context.sessionId ?? this.extensionSessionId();
|
|
4874
|
+
if (!sessionId) {
|
|
4875
|
+
return;
|
|
4876
|
+
}
|
|
4877
|
+
if (method === "cursor/update_todos") {
|
|
4878
|
+
const content = this.updateTodos(sessionId, params);
|
|
4879
|
+
if (!content) {
|
|
4880
|
+
return;
|
|
4881
|
+
}
|
|
4882
|
+
return [{ chunkType: "plan", content, metadata: { cursor_todos: true }, streamed: false }];
|
|
4883
|
+
}
|
|
4884
|
+
if (method === "cursor/task") {
|
|
4885
|
+
const description = stringValue(params.description);
|
|
4886
|
+
if (!description) {
|
|
4887
|
+
return [];
|
|
4888
|
+
}
|
|
4889
|
+
const subagentType = stringValue(params.subagentType) ?? "unspecified";
|
|
4890
|
+
const model = stringValue(params.model);
|
|
4891
|
+
const suffix = model ? ` (${model})` : "";
|
|
4892
|
+
return [{ chunkType: "plan", content: `[Cursor ${subagentType} task] ${description}${suffix}`, metadata: {}, streamed: false }];
|
|
4893
|
+
}
|
|
4894
|
+
if (method === "cursor/generate_image") {
|
|
4895
|
+
const description = stringValue(params.description);
|
|
4896
|
+
if (!description) {
|
|
4897
|
+
return [];
|
|
4898
|
+
}
|
|
4899
|
+
const filePath = stringValue(params.filePath);
|
|
4900
|
+
return [{ chunkType: "plan", content: `[Cursor generated image] ${description}${filePath ? ` \u2192 ${filePath}` : ""}`, metadata: {}, streamed: false }];
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
forgetSession(sessionId) {
|
|
4904
|
+
this.todosBySession.delete(sessionId);
|
|
4905
|
+
}
|
|
4906
|
+
clearSessions() {
|
|
4907
|
+
this.todosBySession.clear();
|
|
4908
|
+
}
|
|
4909
|
+
updateTodos(sessionId, params) {
|
|
4910
|
+
const todos = parseTodos(params.todos);
|
|
4911
|
+
if (params.merge === true) {
|
|
4912
|
+
const current2 = this.todosBySession.get(sessionId) ?? /* @__PURE__ */ new Map();
|
|
4913
|
+
for (const todo of todos) {
|
|
4914
|
+
current2.set(todo.id, todo);
|
|
4915
|
+
}
|
|
4916
|
+
this.todosBySession.set(sessionId, current2);
|
|
4917
|
+
} else {
|
|
4918
|
+
this.todosBySession.set(sessionId, new Map(todos.map((todo) => [todo.id, todo])));
|
|
4919
|
+
}
|
|
4920
|
+
const current = this.todosBySession.get(sessionId);
|
|
4921
|
+
return current && current.size > 0 ? [...current.values()].map((todo) => `- [${todoMark(todo.status)}] ${todo.content}`).join("\n") : void 0;
|
|
4922
|
+
}
|
|
4923
|
+
};
|
|
4924
|
+
var CursorACPAdapter = class extends ACPClientAdapter {
|
|
4925
|
+
provider = "cursor-acp";
|
|
4926
|
+
approvalMode;
|
|
4927
|
+
questionMode;
|
|
4928
|
+
planMode;
|
|
4929
|
+
decisionTimeoutMs;
|
|
4930
|
+
maxPendingDecisions;
|
|
4931
|
+
authorizedSenders;
|
|
4932
|
+
decisionLogger;
|
|
4933
|
+
extensions;
|
|
4934
|
+
turns = /* @__PURE__ */ new Map();
|
|
4935
|
+
pending = /* @__PURE__ */ new Map();
|
|
4936
|
+
activeTurn = null;
|
|
4937
|
+
turnTail = Promise.resolve();
|
|
4938
|
+
constructor(options = {}) {
|
|
4939
|
+
const extensions = new CursorExtensions();
|
|
4940
|
+
validateOptions(options);
|
|
4941
|
+
const env = cursorEnv(options);
|
|
4942
|
+
super({
|
|
4943
|
+
...options,
|
|
4944
|
+
env,
|
|
4945
|
+
command: options.command ?? [...DEFAULT_CURSOR_ACP_COMMAND],
|
|
4946
|
+
authMethod: "cursor_login",
|
|
4947
|
+
extensionHandler: extensions,
|
|
4948
|
+
resolvePermission: (request, signal) => extensions.resolvePermission(request, signal)
|
|
4949
|
+
});
|
|
4950
|
+
extensions.bind(this);
|
|
4951
|
+
this.extensions = extensions;
|
|
4952
|
+
this.approvalMode = options.approvalMode ?? "manual";
|
|
4953
|
+
this.questionMode = options.questionMode ?? "manual";
|
|
4954
|
+
this.planMode = options.planMode ?? "manual";
|
|
4955
|
+
this.decisionTimeoutMs = options.decisionTimeoutMs ?? DEFAULT_CURSOR_DECISION_TIMEOUT_MS;
|
|
4956
|
+
this.maxPendingDecisions = options.maxPendingDecisions ?? DEFAULT_CURSOR_MAX_PENDING_DECISIONS;
|
|
4957
|
+
this.authorizedSenders = options.decisionAuthorizedSenders ? new Set(options.decisionAuthorizedSenders) : null;
|
|
4958
|
+
this.decisionLogger = resolveLogger(options.logger);
|
|
4959
|
+
}
|
|
4960
|
+
async onMessage(message, tools, history, participantsMessage, contactsMessage, context) {
|
|
4961
|
+
if (await this.handleControl(message, tools, context.roomId)) {
|
|
4962
|
+
return;
|
|
4963
|
+
}
|
|
4964
|
+
await this.withCursorTurnLock(() => super.onMessage(message, tools, history, participantsMessage, contactsMessage, context));
|
|
4965
|
+
}
|
|
4966
|
+
async onAcpTurnStarted(message, tools, context) {
|
|
4967
|
+
const turn = { messageId: message.id, roomId: context.roomId, tools, requesterId: message.senderId };
|
|
4968
|
+
this.turns.set(context.roomId, turn);
|
|
4969
|
+
this.activeTurn = turn;
|
|
4970
|
+
}
|
|
4971
|
+
async onAcpSessionReady(message, _tools, context, sessionId) {
|
|
4972
|
+
const turn = this.turns.get(context.roomId);
|
|
4973
|
+
if (turn?.messageId === message.id) {
|
|
4974
|
+
turn.sessionId = sessionId;
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
async onAcpTurnFinished(message, _tools, context) {
|
|
4978
|
+
const turn = this.turns.get(context.roomId);
|
|
4979
|
+
if (turn?.messageId === message.id) {
|
|
4980
|
+
this.turns.delete(context.roomId);
|
|
4981
|
+
this.cancelRoom(context.roomId);
|
|
4982
|
+
}
|
|
4983
|
+
if (this.activeTurn?.messageId === message.id) {
|
|
4984
|
+
this.activeTurn = null;
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
async onCleanup(roomId) {
|
|
4988
|
+
const sessionId = this.turns.get(roomId)?.sessionId;
|
|
4989
|
+
this.cancelRoom(roomId);
|
|
4990
|
+
this.turns.delete(roomId);
|
|
4991
|
+
if (this.activeTurn?.roomId === roomId) {
|
|
4992
|
+
this.activeTurn = null;
|
|
4993
|
+
}
|
|
4994
|
+
await super.onCleanup(roomId);
|
|
4995
|
+
if (sessionId) {
|
|
4996
|
+
this.extensions.forgetSession(sessionId);
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4999
|
+
async stop() {
|
|
5000
|
+
for (const decision of this.pending.values()) {
|
|
5001
|
+
decision.resolve(void 0);
|
|
5002
|
+
}
|
|
5003
|
+
this.pending.clear();
|
|
5004
|
+
this.turns.clear();
|
|
5005
|
+
this.activeTurn = null;
|
|
5006
|
+
this.extensions.clearSessions();
|
|
5007
|
+
await super.stop();
|
|
5008
|
+
}
|
|
5009
|
+
async resolveExtension(method, params, sessionId) {
|
|
5010
|
+
const roomId = sessionId ? this.roomIdForSession(sessionId) : this.activeTurn?.roomId;
|
|
5011
|
+
const turn = roomId ? this.turns.get(roomId) : void 0;
|
|
5012
|
+
if (!turn || sessionId && turn.sessionId !== sessionId) {
|
|
5013
|
+
return { outcome: { outcome: "cancelled" } };
|
|
5014
|
+
}
|
|
5015
|
+
if (method === "cursor/ask_question") {
|
|
5016
|
+
return this.resolveQuestion(turn.roomId, turn, params);
|
|
5017
|
+
}
|
|
5018
|
+
if (method === "cursor/create_plan") {
|
|
5019
|
+
return this.resolvePlan(turn.roomId, turn, params);
|
|
5020
|
+
}
|
|
5021
|
+
return {};
|
|
5022
|
+
}
|
|
5023
|
+
async resolveCursorPermission(request, signal) {
|
|
5024
|
+
if (this.approvalMode === "autoAccept") {
|
|
5025
|
+
return allowOption(request.options)?.optionId;
|
|
5026
|
+
}
|
|
5027
|
+
if (this.approvalMode === "autoDecline") {
|
|
5028
|
+
return void 0;
|
|
5029
|
+
}
|
|
5030
|
+
const turn = this.turns.get(request.roomId);
|
|
5031
|
+
if (!turn) {
|
|
5032
|
+
return void 0;
|
|
5033
|
+
}
|
|
5034
|
+
const options = request.options.map((option) => option.optionId);
|
|
5035
|
+
const token = await this.waitForDecision("permission", request.roomId, turn, /* @__PURE__ */ new Map([["permission", options]]), /* @__PURE__ */ new Set(), `Cursor needs permission. Reply \`/cursor select {token} option-id\` or \`/cursor deny {token}\`.`, signal);
|
|
5036
|
+
return typeof token === "string" && options.includes(token) ? token : void 0;
|
|
5037
|
+
}
|
|
5038
|
+
extensionSessionId() {
|
|
5039
|
+
return this.activeTurn?.sessionId ?? null;
|
|
5040
|
+
}
|
|
5041
|
+
async resolveQuestion(roomId, turn, params) {
|
|
5042
|
+
const questions = questionChoices(params.questions);
|
|
5043
|
+
if (questions.choices.size === 0) {
|
|
5044
|
+
return { outcome: { outcome: "cancelled" } };
|
|
5045
|
+
}
|
|
5046
|
+
if (this.questionMode === "autoCancel") {
|
|
5047
|
+
return { outcome: { outcome: "cancelled" } };
|
|
5048
|
+
}
|
|
5049
|
+
if (this.questionMode === "autoFirst") {
|
|
5050
|
+
return answered(Object.fromEntries([...questions.choices].map(([id, options]) => [id, [options[0]]])));
|
|
5051
|
+
}
|
|
5052
|
+
const result = await this.waitForDecision("question", roomId, turn, questions.choices, questions.multiSelect, "Cursor needs input. Reply `/cursor answer {token} question-id=option-id[,option-id] ...`.");
|
|
5053
|
+
return isRecord(result) ? result : { outcome: { outcome: "cancelled" } };
|
|
5054
|
+
}
|
|
5055
|
+
async resolvePlan(roomId, turn, params) {
|
|
5056
|
+
if (this.planMode === "autoAccept") {
|
|
5057
|
+
return { outcome: { outcome: "accepted" } };
|
|
5058
|
+
}
|
|
5059
|
+
if (this.planMode === "autoDecline") {
|
|
5060
|
+
return { outcome: { outcome: "rejected" } };
|
|
5061
|
+
}
|
|
5062
|
+
const title = stringValue(params.title) ?? "Cursor plan";
|
|
5063
|
+
const result = await this.waitForDecision("plan", roomId, turn, /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set(), `${title} needs approval. Reply \`/cursor accept {token}\` or \`/cursor reject {token}\`.`);
|
|
5064
|
+
return isRecord(result) ? result : { outcome: { outcome: "cancelled" } };
|
|
5065
|
+
}
|
|
5066
|
+
async waitForDecision(kind, roomId, turn, choices, multiSelect, prompt, signal) {
|
|
5067
|
+
if (this.pending.size >= this.maxPendingDecisions) {
|
|
5068
|
+
this.pending.values().next().value?.resolve(void 0);
|
|
5069
|
+
}
|
|
5070
|
+
const token = crypto.randomUUID().slice(0, 8);
|
|
5071
|
+
return new Promise((resolve) => {
|
|
5072
|
+
const timer = setTimeout(() => settle(void 0), this.decisionTimeoutMs);
|
|
5073
|
+
const abort = () => settle(void 0);
|
|
5074
|
+
const settle = (value) => {
|
|
5075
|
+
clearTimeout(timer);
|
|
5076
|
+
signal?.removeEventListener("abort", abort);
|
|
5077
|
+
this.pending.delete(token);
|
|
5078
|
+
resolve(value);
|
|
5079
|
+
};
|
|
5080
|
+
this.pending.set(token, { kind, roomId, choices, multiSelect, resolve: settle });
|
|
5081
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
5082
|
+
void turn.tools.sendMessage(prompt.replaceAll("{token}", token), [turn.requesterId]).catch((error) => {
|
|
5083
|
+
this.decisionLogger.warn("cursor_acp.decision_prompt_delivery_failed", { roomId, kind, error: String(error) });
|
|
5084
|
+
settle(void 0);
|
|
5085
|
+
});
|
|
5086
|
+
});
|
|
5087
|
+
}
|
|
5088
|
+
async handleControl(message, tools, roomId) {
|
|
5089
|
+
const words = message.content.trim().split(/\s+/);
|
|
5090
|
+
if (words[0]?.toLowerCase() !== "/cursor") {
|
|
5091
|
+
return false;
|
|
5092
|
+
}
|
|
5093
|
+
if (words.length === 1 || words[1]?.toLowerCase() === "decisions") {
|
|
5094
|
+
const entries = [...this.pending.entries()].filter(([, decision2]) => decision2.roomId === roomId).map(([token2, decision2]) => `\`${token2}\` (${decision2.kind})`);
|
|
5095
|
+
await tools.sendMessage(`Pending Cursor decisions: ${entries.join(", ") || "none"}`);
|
|
5096
|
+
return true;
|
|
5097
|
+
}
|
|
5098
|
+
const [_, action, token, ...args] = words;
|
|
5099
|
+
const decision = token ? this.pending.get(token) : void 0;
|
|
5100
|
+
if (!decision || decision.roomId !== roomId) {
|
|
5101
|
+
await tools.sendMessage(`Cursor decision \`${token ?? ""}\` is not pending.`);
|
|
5102
|
+
return true;
|
|
5103
|
+
}
|
|
5104
|
+
if (this.authorizedSenders && !this.authorizedSenders.has(message.senderId)) {
|
|
5105
|
+
await tools.sendMessage("You are not authorized to resolve Cursor decisions.");
|
|
5106
|
+
return true;
|
|
5107
|
+
}
|
|
5108
|
+
const result = commandResult(action ?? "", args, decision);
|
|
5109
|
+
if (result === null) {
|
|
5110
|
+
await tools.sendMessage(`That command is not valid for Cursor ${decision.kind} decision \`${token}\`.`);
|
|
5111
|
+
return true;
|
|
5112
|
+
}
|
|
5113
|
+
decision.resolve(result);
|
|
5114
|
+
await tools.sendMessage(`Cursor ${decision.kind} decision \`${token}\` resolved.`);
|
|
5115
|
+
return true;
|
|
5116
|
+
}
|
|
5117
|
+
cancelRoom(roomId) {
|
|
5118
|
+
for (const [token, decision] of this.pending) {
|
|
5119
|
+
if (decision.roomId === roomId) {
|
|
5120
|
+
decision.resolve(void 0);
|
|
5121
|
+
this.pending.delete(token);
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
}
|
|
5125
|
+
async withCursorTurnLock(run) {
|
|
5126
|
+
const queued = this.turnTail.then(run, run);
|
|
5127
|
+
this.turnTail = queued.then(() => void 0, () => void 0);
|
|
5128
|
+
return queued;
|
|
5129
|
+
}
|
|
5130
|
+
};
|
|
5131
|
+
function cursorEnv(options) {
|
|
5132
|
+
const env = { ...options.env };
|
|
5133
|
+
if (options.apiKey) env.CURSOR_API_KEY ??= options.apiKey;
|
|
5134
|
+
if (options.authToken) env.CURSOR_AUTH_TOKEN ??= options.authToken;
|
|
5135
|
+
return Object.keys(env).length > 0 ? env : void 0;
|
|
5136
|
+
}
|
|
5137
|
+
function validateOptions(options) {
|
|
5138
|
+
if (options.apiKey && options.authToken) throw new Error("set either apiKey or authToken, not both");
|
|
5139
|
+
if (Array.isArray(options.command) && options.command.length === 0) throw new Error("Cursor ACP command must not be empty");
|
|
5140
|
+
if (options.decisionTimeoutMs !== void 0 && (!Number.isFinite(options.decisionTimeoutMs) || options.decisionTimeoutMs <= 0)) throw new Error("decisionTimeoutMs must be a positive finite number");
|
|
5141
|
+
if (options.maxPendingDecisions !== void 0 && (!Number.isInteger(options.maxPendingDecisions) || options.maxPendingDecisions <= 0)) throw new Error("maxPendingDecisions must be a positive integer");
|
|
5142
|
+
}
|
|
5143
|
+
function allowOption(options) {
|
|
5144
|
+
return options.find((option) => option.kind === "allow_once") ?? options.find((option) => option.kind === "allow_always");
|
|
5145
|
+
}
|
|
5146
|
+
function questionChoices(value) {
|
|
5147
|
+
const choices = /* @__PURE__ */ new Map();
|
|
5148
|
+
const multiSelect = /* @__PURE__ */ new Set();
|
|
5149
|
+
if (!Array.isArray(value)) return { choices, multiSelect };
|
|
5150
|
+
for (const question of value) {
|
|
5151
|
+
if (!isRecord(question) || typeof question.id !== "string" || !Array.isArray(question.options)) continue;
|
|
5152
|
+
const options = question.options.filter(isRecord).map((option) => stringValue(option.id)).filter((id) => !!id);
|
|
5153
|
+
if (options.length === 0) continue;
|
|
5154
|
+
choices.set(question.id, options);
|
|
5155
|
+
if (question.allowMultiple === true) multiSelect.add(question.id);
|
|
5156
|
+
}
|
|
5157
|
+
return { choices, multiSelect };
|
|
5158
|
+
}
|
|
5159
|
+
function commandResult(action, args, decision) {
|
|
5160
|
+
if (decision.kind === "permission") return action === "deny" ? void 0 : action === "select" && args.length === 1 && decision.choices.get("permission")?.includes(args[0] ?? "") ? args[0] : null;
|
|
5161
|
+
if (decision.kind === "plan") return action === "accept" ? { outcome: { outcome: "accepted" } } : action === "reject" ? { outcome: { outcome: "rejected" } } : null;
|
|
5162
|
+
if (action !== "answer") return null;
|
|
5163
|
+
const selected = {};
|
|
5164
|
+
for (const argument of args) {
|
|
5165
|
+
const [id, raw] = argument.split("=", 2);
|
|
5166
|
+
const values = raw?.split(",") ?? [];
|
|
5167
|
+
const offered = id ? decision.choices.get(id) : void 0;
|
|
5168
|
+
if (!id || !offered || selected[id] || values.length === 0 || values.length > 1 && !decision.multiSelect.has(id) || values.some((value) => !offered.includes(value))) return null;
|
|
5169
|
+
selected[id] = values;
|
|
5170
|
+
}
|
|
5171
|
+
return Object.keys(selected).length === decision.choices.size ? answered(selected) : null;
|
|
5172
|
+
}
|
|
5173
|
+
function answered(selected) {
|
|
5174
|
+
return { outcome: { outcome: "answered", answers: Object.entries(selected).map(([questionId, selectedOptionIds]) => ({ questionId, selectedOptionIds })) } };
|
|
5175
|
+
}
|
|
5176
|
+
function parseTodos(value) {
|
|
5177
|
+
if (!Array.isArray(value)) return [];
|
|
5178
|
+
return value.flatMap((todo) => {
|
|
5179
|
+
if (!isRecord(todo)) return [];
|
|
5180
|
+
const id = stringValue(todo.id);
|
|
5181
|
+
const content = stringValue(todo.content);
|
|
5182
|
+
const status = stringValue(todo.status);
|
|
5183
|
+
return id && content && status ? [{ id, content, status }] : [];
|
|
5184
|
+
});
|
|
5185
|
+
}
|
|
5186
|
+
function todoMark(status) {
|
|
5187
|
+
switch (status) {
|
|
5188
|
+
case "completed":
|
|
5189
|
+
return "x";
|
|
5190
|
+
case "in_progress":
|
|
5191
|
+
return "~";
|
|
5192
|
+
case "cancelled":
|
|
5193
|
+
return "-";
|
|
5194
|
+
default:
|
|
5195
|
+
return " ";
|
|
5196
|
+
}
|
|
5197
|
+
}
|
|
5198
|
+
function isRecord(value) {
|
|
5199
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5200
|
+
}
|
|
5201
|
+
function stringValue(value) {
|
|
5202
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
5203
|
+
}
|
|
5204
|
+
|
|
4859
5205
|
// src/adapters/tool-calling/ToolCallingAdapter.ts
|
|
4860
5206
|
init_protocols();
|
|
4861
5207
|
|
|
@@ -7283,20 +7629,20 @@ function unwrapResult(value, depth = 0) {
|
|
|
7283
7629
|
}
|
|
7284
7630
|
return event;
|
|
7285
7631
|
}
|
|
7286
|
-
function
|
|
7632
|
+
function isRecord2(value) {
|
|
7287
7633
|
return typeof value === "object" && value !== null;
|
|
7288
7634
|
}
|
|
7289
7635
|
function isOptionalString(value) {
|
|
7290
7636
|
return value === void 0 || typeof value === "string";
|
|
7291
7637
|
}
|
|
7292
7638
|
function isMessagePart(value) {
|
|
7293
|
-
if (!
|
|
7639
|
+
if (!isRecord2(value)) {
|
|
7294
7640
|
return false;
|
|
7295
7641
|
}
|
|
7296
7642
|
return isOptionalString(value.kind) && isOptionalString(value.type) && isOptionalString(value.text) && (value.root === void 0 || isMessagePart(value.root));
|
|
7297
7643
|
}
|
|
7298
7644
|
function isMessageLike(value) {
|
|
7299
|
-
if (!
|
|
7645
|
+
if (!isRecord2(value)) {
|
|
7300
7646
|
return false;
|
|
7301
7647
|
}
|
|
7302
7648
|
if (!isOptionalString(value.kind) || !isOptionalString(value.role)) {
|
|
@@ -7311,7 +7657,7 @@ function isMessageLike(value) {
|
|
|
7311
7657
|
return Array.isArray(value.parts) && value.parts.every((part) => isMessagePart(part));
|
|
7312
7658
|
}
|
|
7313
7659
|
function isStatusLike(value) {
|
|
7314
|
-
if (!
|
|
7660
|
+
if (!isRecord2(value)) {
|
|
7315
7661
|
return false;
|
|
7316
7662
|
}
|
|
7317
7663
|
if (!isOptionalString(value.state)) {
|
|
@@ -7320,7 +7666,7 @@ function isStatusLike(value) {
|
|
|
7320
7666
|
return value.message === void 0 || isMessageLike(value.message);
|
|
7321
7667
|
}
|
|
7322
7668
|
function isArtifactLike(value) {
|
|
7323
|
-
if (!
|
|
7669
|
+
if (!isRecord2(value)) {
|
|
7324
7670
|
return false;
|
|
7325
7671
|
}
|
|
7326
7672
|
if (value.parts === void 0) {
|
|
@@ -7329,19 +7675,19 @@ function isArtifactLike(value) {
|
|
|
7329
7675
|
return Array.isArray(value.parts) && value.parts.every((part) => isMessagePart(part));
|
|
7330
7676
|
}
|
|
7331
7677
|
function isMessageEvent(event) {
|
|
7332
|
-
return
|
|
7678
|
+
return isRecord2(event) && event.kind === "message" && isMessageLike(event) && Array.isArray(event.parts);
|
|
7333
7679
|
}
|
|
7334
7680
|
function isTaskEvent(event) {
|
|
7335
|
-
if (!
|
|
7681
|
+
if (!isRecord2(event) || event.kind !== "task") {
|
|
7336
7682
|
return false;
|
|
7337
7683
|
}
|
|
7338
7684
|
return typeof event.id === "string" && isOptionalString(event.contextId) && isStatusLike(event.status) && (event.artifacts === void 0 || Array.isArray(event.artifacts) && event.artifacts.every((item) => isArtifactLike(item))) && (event.history === void 0 || Array.isArray(event.history) && event.history.every((item) => isMessageLike(item)));
|
|
7339
7685
|
}
|
|
7340
7686
|
function isStatusUpdateEvent(event) {
|
|
7341
|
-
return
|
|
7687
|
+
return isRecord2(event) && event.kind === "status-update" && typeof event.taskId === "string" && typeof event.contextId === "string" && isStatusLike(event.status);
|
|
7342
7688
|
}
|
|
7343
7689
|
function isArtifactUpdateEvent(event) {
|
|
7344
|
-
return
|
|
7690
|
+
return isRecord2(event) && event.kind === "artifact-update" && typeof event.taskId === "string" && typeof event.contextId === "string" && isArtifactLike(event.artifact);
|
|
7345
7691
|
}
|
|
7346
7692
|
async function loadDefaultA2AClientFactory() {
|
|
7347
7693
|
let module2;
|
|
@@ -9981,7 +10327,7 @@ var SdkOpencodeClientBase = class {
|
|
|
9981
10327
|
{ signal: this.eventsAbortController.signal }
|
|
9982
10328
|
);
|
|
9983
10329
|
for await (const event of events.stream) {
|
|
9984
|
-
if (
|
|
10330
|
+
if (isRecord3(event)) {
|
|
9985
10331
|
yield event;
|
|
9986
10332
|
}
|
|
9987
10333
|
}
|
|
@@ -10099,7 +10445,7 @@ function optionalString(value) {
|
|
|
10099
10445
|
const trimmed = value.trim();
|
|
10100
10446
|
return trimmed.length > 0 ? trimmed : null;
|
|
10101
10447
|
}
|
|
10102
|
-
function
|
|
10448
|
+
function isRecord3(value) {
|
|
10103
10449
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
10104
10450
|
}
|
|
10105
10451
|
function getResultBody(result) {
|
|
@@ -10109,7 +10455,7 @@ function expectRecord(result) {
|
|
|
10109
10455
|
if (!result.response.ok) {
|
|
10110
10456
|
throw new HttpStatusError(result.response.status, getResultBody(result));
|
|
10111
10457
|
}
|
|
10112
|
-
return
|
|
10458
|
+
return isRecord3(result.data) ? result.data : {};
|
|
10113
10459
|
}
|
|
10114
10460
|
async function expectVoid(resultPromise) {
|
|
10115
10461
|
const result = await resultPromise;
|
|
@@ -13057,7 +13403,9 @@ function parseModelListResponse(value) {
|
|
|
13057
13403
|
CodexAppServerStdioClient,
|
|
13058
13404
|
CodexJsonRpcError,
|
|
13059
13405
|
CopilotACPAdapter,
|
|
13406
|
+
CursorACPAdapter,
|
|
13060
13407
|
DEFAULT_COPILOT_ACP_COMMAND,
|
|
13408
|
+
DEFAULT_CURSOR_ACP_COMMAND,
|
|
13061
13409
|
DEFAULT_OMP_ACP_COMMAND,
|
|
13062
13410
|
FAILURE_CODE_SESSION_CONFIG,
|
|
13063
13411
|
GatewayHistoryConverter,
|