@rely-ai/caliber 1.22.0-dev.1773745340 → 1.22.0-dev.1773752996

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.
Files changed (2) hide show
  1. package/dist/bin.js +121 -89
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -1210,13 +1210,21 @@ var IS_WINDOWS = process.platform === "win32";
1210
1210
  var CursorAcpProvider = class {
1211
1211
  defaultModel;
1212
1212
  cursorApiKey;
1213
+ child = null;
1214
+ rl = null;
1215
+ pending = /* @__PURE__ */ new Map();
1216
+ nextId = 1;
1217
+ connectPromise = null;
1218
+ activeCallbacks = null;
1219
+ shutdownRequested = false;
1213
1220
  constructor(config) {
1214
- this.defaultModel = config.model || "default";
1221
+ this.defaultModel = config.model || "auto";
1215
1222
  this.cursorApiKey = process.env.CURSOR_API_KEY ?? process.env.CURSOR_AUTH_TOKEN;
1223
+ process.once("exit", () => this.shutdown());
1216
1224
  }
1217
1225
  async call(options) {
1218
1226
  const chunks = [];
1219
- await this.runAcpPrompt(options, {
1227
+ await this.runPrompt(options, {
1220
1228
  onText: (text) => chunks.push(text),
1221
1229
  onEnd: () => {
1222
1230
  },
@@ -1226,118 +1234,142 @@ var CursorAcpProvider = class {
1226
1234
  return chunks.join("");
1227
1235
  }
1228
1236
  async stream(options, callbacks) {
1229
- await this.runAcpPrompt(options, callbacks);
1237
+ await this.runPrompt(options, callbacks);
1238
+ }
1239
+ shutdown() {
1240
+ this.shutdownRequested = true;
1241
+ if (this.child) {
1242
+ this.child.stdin?.end();
1243
+ this.child.kill("SIGTERM");
1244
+ this.child = null;
1245
+ }
1246
+ this.rl = null;
1247
+ this.connectPromise = null;
1248
+ }
1249
+ // -- Connection management --------------------------------------------------
1250
+ async ensureConnection() {
1251
+ if (this.child && !this.child.killed) return;
1252
+ if (this.connectPromise) return this.connectPromise;
1253
+ this.connectPromise = this.connect();
1254
+ try {
1255
+ await this.connectPromise;
1256
+ } catch (err) {
1257
+ this.connectPromise = null;
1258
+ throw err;
1259
+ }
1230
1260
  }
1231
- async runAcpPrompt(options, callbacks) {
1232
- const combinedPrompt = this.buildCombinedPrompt(options);
1233
- const model = options.model || this.defaultModel;
1261
+ async connect() {
1234
1262
  const args = ["acp"];
1235
- if (model && model !== "auto" && model !== "default") {
1236
- args.unshift("--model", model);
1237
- }
1238
1263
  if (this.cursorApiKey) {
1239
1264
  args.unshift("--api-key", this.cursorApiKey);
1240
1265
  }
1241
- const agent = spawn(ACP_AGENT_BIN, args, {
1242
- stdio: ["pipe", "pipe", "inherit"],
1266
+ this.child = spawn(ACP_AGENT_BIN, args, {
1267
+ stdio: ["pipe", "pipe", "ignore"],
1243
1268
  cwd: process.cwd(),
1244
1269
  env: { ...process.env, ...this.cursorApiKey && { CURSOR_API_KEY: this.cursorApiKey } },
1245
1270
  ...IS_WINDOWS && { shell: true }
1246
1271
  });
1247
- const pending = /* @__PURE__ */ new Map();
1248
- let nextId = 1;
1249
- let sessionId = null;
1250
- const send = (method, params) => {
1251
- return new Promise((resolve2, reject) => {
1252
- const id = nextId++;
1253
- pending.set(id, { resolve: resolve2, reject });
1254
- const msg = { jsonrpc: "2.0", id, method, params };
1255
- agent.stdin.write(JSON.stringify(msg) + "\n", (err) => {
1256
- if (err) {
1257
- pending.delete(id);
1258
- reject(err);
1259
- }
1260
- });
1261
- });
1262
- };
1263
- const rl = readline.createInterface({ input: agent.stdout, crlfDelay: Infinity });
1264
- rl.on("line", (line) => {
1265
- let msg;
1266
- try {
1267
- msg = JSON.parse(line);
1268
- } catch {
1269
- return;
1272
+ this.rl = readline.createInterface({ input: this.child.stdout, crlfDelay: Infinity });
1273
+ this.rl.on("line", (line) => this.handleLine(line));
1274
+ this.child.on("error", (err) => {
1275
+ for (const w of this.pending.values()) w.reject(err);
1276
+ this.pending.clear();
1277
+ this.activeCallbacks?.onError(err);
1278
+ });
1279
+ this.child.on("close", () => {
1280
+ if (!this.shutdownRequested) {
1281
+ const err = new Error("Cursor agent process exited unexpectedly");
1282
+ for (const w of this.pending.values()) w.reject(err);
1283
+ this.pending.clear();
1284
+ this.activeCallbacks?.onError(err);
1270
1285
  }
1271
- if (msg.id != null && (msg.result !== void 0 || msg.error !== void 0)) {
1272
- const waiter = pending.get(msg.id);
1273
- if (waiter) {
1274
- pending.delete(msg.id);
1275
- if (msg.error) {
1276
- waiter.reject(new Error(msg.error.message || "ACP error"));
1277
- } else {
1278
- waiter.resolve(msg.result);
1279
- }
1280
- }
1281
- if (msg.result && typeof msg.result === "object" && "sessionId" in msg.result) {
1282
- sessionId = msg.result.sessionId;
1283
- }
1284
- if (msg.result && typeof msg.result === "object" && "stopReason" in msg.result) {
1285
- callbacks.onEnd({
1286
- stopReason: msg.result.stopReason
1287
- });
1286
+ this.child = null;
1287
+ this.rl = null;
1288
+ this.connectPromise = null;
1289
+ });
1290
+ await this.send("initialize", {
1291
+ protocolVersion: 1,
1292
+ clientCapabilities: { fs: { readTextFile: false, writeTextFile: false }, terminal: false },
1293
+ clientInfo: { name: "caliber", version: "1.0.0" }
1294
+ });
1295
+ await this.send("authenticate", { methodId: "cursor_login" });
1296
+ }
1297
+ // -- JSON-RPC ---------------------------------------------------------------
1298
+ send(method, params) {
1299
+ if (!this.child?.stdin) {
1300
+ return Promise.reject(new Error("Cursor agent not connected"));
1301
+ }
1302
+ return new Promise((resolve2, reject) => {
1303
+ const id = this.nextId++;
1304
+ this.pending.set(id, { resolve: resolve2, reject });
1305
+ const msg = { jsonrpc: "2.0", id, method, params };
1306
+ this.child.stdin.write(JSON.stringify(msg) + "\n", (err) => {
1307
+ if (err) {
1308
+ this.pending.delete(id);
1309
+ reject(err);
1288
1310
  }
1289
- return;
1290
- }
1291
- if (msg.method === "session/update" && msg.params?.update) {
1292
- const update = msg.params.update;
1293
- if (update.sessionUpdate === "agent_message_chunk" && update.content?.text) {
1294
- callbacks.onText(update.content.text);
1311
+ });
1312
+ });
1313
+ }
1314
+ handleLine(line) {
1315
+ let msg;
1316
+ try {
1317
+ msg = JSON.parse(line);
1318
+ } catch {
1319
+ return;
1320
+ }
1321
+ if (msg.id != null && (msg.result !== void 0 || msg.error !== void 0)) {
1322
+ const waiter = this.pending.get(msg.id);
1323
+ if (waiter) {
1324
+ this.pending.delete(msg.id);
1325
+ if (msg.error) {
1326
+ waiter.reject(new Error(msg.error.message || "ACP error"));
1327
+ } else {
1328
+ waiter.resolve(msg.result);
1295
1329
  }
1296
- return;
1297
1330
  }
1298
- if (msg.method === "session/request_permission" && msg.id != null) {
1299
- const response = JSON.stringify({
1300
- jsonrpc: "2.0",
1301
- id: msg.id,
1302
- result: { outcome: { outcome: "selected", optionId: "allow-once" } }
1303
- }) + "\n";
1304
- agent.stdin.write(response);
1331
+ if (msg.result && typeof msg.result === "object" && "stopReason" in msg.result) {
1332
+ this.activeCallbacks?.onEnd({
1333
+ stopReason: msg.result.stopReason
1334
+ });
1305
1335
  }
1306
- });
1307
- agent.on("error", (err) => {
1308
- for (const w of pending.values()) w.reject(err);
1309
- callbacks.onError(err);
1310
- });
1311
- agent.on("close", (code) => {
1312
- if (code !== 0 && code !== null) {
1313
- const err = new Error(`Cursor agent exited with code ${code}`);
1314
- for (const w of pending.values()) w.reject(err);
1315
- callbacks.onError(err);
1336
+ return;
1337
+ }
1338
+ if (msg.method === "session/update" && msg.params?.update) {
1339
+ const update = msg.params.update;
1340
+ if (update.sessionUpdate === "agent_message_chunk" && update.content?.text) {
1341
+ this.activeCallbacks?.onText(update.content.text);
1316
1342
  }
1317
- });
1343
+ return;
1344
+ }
1345
+ if (msg.method === "session/request_permission" && msg.id != null) {
1346
+ const response = JSON.stringify({
1347
+ jsonrpc: "2.0",
1348
+ id: msg.id,
1349
+ result: { outcome: { outcome: "selected", optionId: "allow-once" } }
1350
+ }) + "\n";
1351
+ this.child?.stdin?.write(response);
1352
+ }
1353
+ }
1354
+ // -- Prompt execution -------------------------------------------------------
1355
+ async runPrompt(options, callbacks) {
1356
+ await this.ensureConnection();
1357
+ this.activeCallbacks = callbacks;
1318
1358
  try {
1319
- await send("initialize", {
1320
- protocolVersion: 1,
1321
- clientCapabilities: { fs: { readTextFile: false, writeTextFile: false }, terminal: false },
1322
- clientInfo: { name: "caliber", version: "1.0.0" }
1323
- });
1324
- await send("authenticate", { methodId: "cursor_login" });
1325
- const sessionResult = await send("session/new", {
1359
+ const sessionResult = await this.send("session/new", {
1326
1360
  cwd: process.cwd(),
1327
1361
  mcpServers: []
1328
1362
  });
1329
- sessionId = sessionResult.sessionId;
1330
- await send("session/prompt", {
1331
- sessionId,
1332
- prompt: [{ type: "text", text: combinedPrompt }]
1363
+ await this.send("session/prompt", {
1364
+ sessionId: sessionResult.sessionId,
1365
+ prompt: [{ type: "text", text: this.buildCombinedPrompt(options) }]
1333
1366
  });
1334
1367
  } catch (err) {
1335
1368
  const error = err instanceof Error ? err : new Error(String(err));
1336
1369
  callbacks.onError(error);
1337
1370
  throw error;
1338
1371
  } finally {
1339
- agent.stdin?.end();
1340
- agent.kill("SIGTERM");
1372
+ this.activeCallbacks = null;
1341
1373
  }
1342
1374
  }
1343
1375
  buildCombinedPrompt(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rely-ai/caliber",
3
- "version": "1.22.0-dev.1773745340",
3
+ "version": "1.22.0-dev.1773752996",
4
4
  "description": "Analyze your codebase and generate optimized AI agent configs (CLAUDE.md, .cursorrules, skills) — no API key needed",
5
5
  "type": "module",
6
6
  "bin": {