@stablekernel/opencode-cursor 0.6.2-next.0 → 0.7.0-next.0

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.
@@ -6,13 +6,15 @@ import {
6
6
  extractSystemText,
7
7
  getSessionRecord,
8
8
  linkSubagentSession,
9
+ pluginLog,
9
10
  resolveControls,
10
11
  resolveCursorApiKey,
11
12
  resolveSystemDelivery,
12
13
  sendAgentTurnSilently,
13
14
  setPreferredTransport,
14
- streamAgentTurn
15
- } from "../chunk-52IYLL6B.js";
15
+ streamAgentTurn,
16
+ withSessionLock
17
+ } from "../chunk-COE6ZXMP.js";
16
18
 
17
19
  // src/provider/index.ts
18
20
  import { NoSuchModelError } from "@ai-sdk/provider";
@@ -1166,7 +1168,7 @@ var CursorLanguageModel = class {
1166
1168
  warnOnce(message) {
1167
1169
  if (this.warned.has(message)) return;
1168
1170
  this.warned.add(message);
1169
- console.warn(`[${this.provider}] ${message}`);
1171
+ pluginLog("warn", message, { provider: this.provider });
1170
1172
  }
1171
1173
  requireApiKey() {
1172
1174
  const apiKey = resolveCursorApiKey(this.config.apiKey);
@@ -1189,9 +1191,10 @@ var CursorLanguageModel = class {
1189
1191
  providerOptions
1190
1192
  );
1191
1193
  if (process.env["OPENCODE_CURSOR_DEBUG"] === "1") {
1192
- console.error(
1193
- `[cursor:debug] model=${this.modelId} selection=${JSON.stringify(modelSelection)}`
1194
- );
1194
+ pluginLog("debug", "model call", {
1195
+ model: this.modelId,
1196
+ selection: modelSelection
1197
+ });
1195
1198
  }
1196
1199
  const sessionID = typeof providerOptions?.["sessionID"] === "string" ? providerOptions["sessionID"] : void 0;
1197
1200
  const dynamicMcp = providerOptions?.["mcpServers"];
@@ -1201,85 +1204,93 @@ var CursorLanguageModel = class {
1201
1204
  const explicitAgentId = typeof providerOptions?.["agentId"] === "string" ? providerOptions["agentId"] : void 0;
1202
1205
  const ephemeral = providerOptions?.["ephemeral"] === true;
1203
1206
  const usePool = sessionEnabled && Boolean(sessionID) && !explicitAgentId;
1204
- let resumeAgentId = explicitAgentId;
1205
- let poolKey;
1206
- let record;
1207
- let multiNewUserCount = 0;
1208
- if (usePool) {
1209
- const classification = ephemeral ? {
1210
- kind: "side-call",
1211
- fingerprint: fingerprint(options.prompt)
1212
- } : classifyTurn(getSessionRecord(sessionID), options.prompt);
1213
- switch (classification.kind) {
1214
- case "continuation":
1215
- case "continuation-multi": {
1216
- const prev = getSessionRecord(sessionID);
1217
- if (prev?.mcpHash === mcpHash) {
1218
- resumeAgentId = prev?.agentId;
1219
- }
1220
- poolKey = sessionID;
1221
- record = { ...classification.fingerprint, mcpHash };
1222
- if (classification.kind === "continuation-multi") {
1223
- multiNewUserCount = classification.newUserCount ?? 0;
1207
+ const {
1208
+ acquired,
1209
+ multiTurns,
1210
+ idempotencyKey,
1211
+ systemMode,
1212
+ baseAcquire,
1213
+ record
1214
+ } = await withSessionLock(usePool ? sessionID : void 0, async () => {
1215
+ let resumeAgentId = explicitAgentId;
1216
+ let poolKey;
1217
+ let record2;
1218
+ let multiNewUserCount = 0;
1219
+ if (usePool) {
1220
+ const classification = ephemeral ? {
1221
+ kind: "side-call",
1222
+ fingerprint: fingerprint(options.prompt)
1223
+ } : classifyTurn(getSessionRecord(sessionID), options.prompt);
1224
+ switch (classification.kind) {
1225
+ case "continuation":
1226
+ case "continuation-multi": {
1227
+ const prev = getSessionRecord(sessionID);
1228
+ if (prev?.mcpHash === mcpHash) {
1229
+ resumeAgentId = prev?.agentId;
1230
+ }
1231
+ poolKey = sessionID;
1232
+ record2 = { ...classification.fingerprint, mcpHash };
1233
+ if (classification.kind === "continuation-multi") {
1234
+ multiNewUserCount = classification.newUserCount ?? 0;
1235
+ }
1236
+ break;
1224
1237
  }
1225
- break;
1238
+ case "new":
1239
+ case "divergence":
1240
+ poolKey = sessionID;
1241
+ record2 = { ...classification.fingerprint, mcpHash };
1242
+ break;
1243
+ case "side-call":
1244
+ break;
1245
+ }
1246
+ if (process.env["OPENCODE_CURSOR_DEBUG"] === "1") {
1247
+ const label = classification.kind === "continuation" ? "resume" : classification.kind === "continuation-multi" ? `resume-multi:${multiNewUserCount}` : `fresh:${classification.kind}`;
1248
+ pluginLog("debug", "turn classification", { label, session: sessionID });
1226
1249
  }
1227
- case "new":
1228
- case "divergence":
1229
- poolKey = sessionID;
1230
- record = { ...classification.fingerprint, mcpHash };
1231
- break;
1232
- case "side-call":
1233
- break;
1234
- }
1235
- if (process.env["OPENCODE_CURSOR_DEBUG"] === "1") {
1236
- const label = classification.kind === "continuation" ? "resume" : classification.kind === "continuation-multi" ? `resume-multi:${multiNewUserCount}` : `fresh:${classification.kind}`;
1237
- console.error(
1238
- `[cursor:debug] turn classification=${label} session=${sessionID}`
1239
- );
1240
1250
  }
1241
- }
1242
- let multiTurns;
1243
- if (multiNewUserCount >= 2) {
1244
- const turns = trailingUserMessages(options.prompt, multiNewUserCount);
1245
- if (turns.length === multiNewUserCount) {
1246
- multiTurns = turns;
1247
- } else {
1248
- resumeAgentId = void 0;
1251
+ let multiTurns2;
1252
+ if (multiNewUserCount >= 2) {
1253
+ const turns = trailingUserMessages(options.prompt, multiNewUserCount);
1254
+ if (turns.length === multiNewUserCount) {
1255
+ multiTurns2 = turns;
1256
+ } else {
1257
+ resumeAgentId = void 0;
1258
+ }
1249
1259
  }
1250
- }
1251
- const latestUser = latestUserMessage(options.prompt);
1252
- const idempotencyKey = sendIdempotencyKey(
1253
- sessionID,
1254
- record,
1255
- latestUser?.text ?? JSON.stringify(options.prompt)
1256
- );
1257
- const delivery = resolveSystemDelivery({
1258
- mode: this.config.systemPrompt ?? "rules",
1259
- settingSources: this.config.settingSources,
1260
- cwd: this.config.cwd,
1261
- systemText: extractSystemText(options.prompt),
1262
- warn: (message) => this.warnOnce(message)
1263
- });
1264
- const systemMode = delivery.mode;
1265
- const settingSources = delivery.settingSources;
1266
- const baseAcquire = {
1267
- apiKey: this.requireApiKey(),
1268
- modelSelection,
1269
- mode,
1270
- cwd: this.config.cwd,
1271
- ...settingSources ? { settingSources } : {},
1272
- ...this.config.sandbox !== void 0 ? { sandbox: this.config.sandbox } : {},
1273
- ...this.config.autoReview !== void 0 ? { autoReview: this.config.autoReview } : {},
1274
- ...mcpServers ? { mcpServers } : {},
1275
- ...this.config.agents ? { agents: this.config.agents } : {},
1276
- ...poolKey ? { name: `opencode/${sessionID.slice(-8)}` } : {},
1277
- ...poolKey ? { poolKey } : {},
1278
- ...record ? { record } : {}
1279
- };
1280
- const acquired = await acquireAgent({
1281
- ...baseAcquire,
1282
- ...resumeAgentId ? { resumeAgentId } : {}
1260
+ const latestUser = latestUserMessage(options.prompt);
1261
+ const idempotencyKey2 = sendIdempotencyKey(
1262
+ sessionID,
1263
+ record2,
1264
+ latestUser?.text ?? JSON.stringify(options.prompt)
1265
+ );
1266
+ const delivery = resolveSystemDelivery({
1267
+ mode: this.config.systemPrompt ?? "rules",
1268
+ settingSources: this.config.settingSources,
1269
+ cwd: this.config.cwd,
1270
+ systemText: extractSystemText(options.prompt),
1271
+ warn: (message) => this.warnOnce(message)
1272
+ });
1273
+ const systemMode2 = delivery.mode;
1274
+ const settingSources = delivery.settingSources;
1275
+ const baseAcquire2 = {
1276
+ apiKey: this.requireApiKey(),
1277
+ modelSelection,
1278
+ mode,
1279
+ cwd: this.config.cwd,
1280
+ ...settingSources ? { settingSources } : {},
1281
+ ...this.config.sandbox !== void 0 ? { sandbox: this.config.sandbox } : {},
1282
+ ...this.config.autoReview !== void 0 ? { autoReview: this.config.autoReview } : {},
1283
+ ...mcpServers ? { mcpServers } : {},
1284
+ ...this.config.agents ? { agents: this.config.agents } : {},
1285
+ ...poolKey ? { name: `opencode/${sessionID.slice(-8)}` } : {},
1286
+ ...poolKey ? { poolKey } : {},
1287
+ ...record2 ? { record: record2 } : {}
1288
+ };
1289
+ const acquired2 = await acquireAgent({
1290
+ ...baseAcquire2,
1291
+ ...resumeAgentId ? { resumeAgentId } : {}
1292
+ });
1293
+ return { acquired: acquired2, multiTurns: multiTurns2, idempotencyKey: idempotencyKey2, systemMode: systemMode2, baseAcquire: baseAcquire2, record: record2 };
1283
1294
  });
1284
1295
  let yielded = false;
1285
1296
  let releasedOriginal = false;
@@ -1358,23 +1369,26 @@ var CursorLanguageModel = class {
1358
1369
  const replayable = classified.kind === "agent-not-found" || classified.kind === "rate-limit" || classified.kind === "network" || classified.kind === "unknown";
1359
1370
  if (replayable && acquired.resumed && !yielded && !options.abortSignal?.aborted) {
1360
1371
  if (process.env["OPENCODE_CURSOR_DEBUG"] === "1") {
1361
- console.error(
1362
- "[cursor:debug] resumed turn failed before emitting; retrying with a fresh agent"
1372
+ pluginLog(
1373
+ "debug",
1374
+ "resumed turn failed before emitting; retrying with a fresh agent"
1363
1375
  );
1364
1376
  }
1365
1377
  acquired.release();
1366
1378
  releasedOriginal = true;
1367
1379
  let retry;
1368
1380
  try {
1369
- retry = await acquireAgent({ ...baseAcquire });
1381
+ retry = await withSessionLock(
1382
+ usePool ? sessionID : void 0,
1383
+ () => acquireAgent({ ...baseAcquire })
1384
+ );
1370
1385
  } catch (retryErr) {
1371
1386
  if (retryErr instanceof Error && retryErr.cause === void 0) {
1372
1387
  retryErr.cause = err;
1373
1388
  } else if (process.env["OPENCODE_CURSOR_DEBUG"] === "1") {
1374
- console.error(
1375
- "[cursor:debug] original resume failure (not attachable as cause):",
1376
- err
1377
- );
1389
+ pluginLog("debug", "original resume failure (not attachable as cause)", {
1390
+ error: err instanceof Error ? err.message : String(err)
1391
+ });
1378
1392
  }
1379
1393
  throw retryErr;
1380
1394
  }