@kud/ai-conventional-commit-cli 3.2.3 → 3.2.6

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 (51) hide show
  1. package/dist/{chunk-IWJLYYKM.js → chunk-EHJXGWTJ.js} +3 -19
  2. package/dist/{chunk-OLEHSPCO.js → chunk-GZ5XLAI5.js} +85 -17
  3. package/dist/index.cjs +1200 -0
  4. package/dist/index.d.cts +1 -0
  5. package/dist/index.js +60 -44
  6. package/dist/{reword-3MH2DYFS.js → reword-BKQ7K33J.js} +1 -1
  7. package/dist/{reword-6EWRZ6WZ.js → reword-PNW5XREC.js} +3 -1
  8. package/dist/{reword-3JBE7MPQ.js → reword-QQO7UBGM.js} +2 -0
  9. package/package.json +1 -1
  10. package/dist/chunk-2WRUFO3O.js +0 -689
  11. package/dist/chunk-2X3JJVRR.js +0 -639
  12. package/dist/chunk-7FBRAH4R.js +0 -643
  13. package/dist/chunk-7U4J2ORD.js +0 -614
  14. package/dist/chunk-CC3NIT53.js +0 -650
  15. package/dist/chunk-CLQ6OPLU.js +0 -668
  16. package/dist/chunk-F3BOAVBY.js +0 -122
  17. package/dist/chunk-FYJNHXAR.js +0 -700
  18. package/dist/chunk-H4W6AMGZ.js +0 -549
  19. package/dist/chunk-HJR5M6U7.js +0 -120
  20. package/dist/chunk-HOUMTU6H.js +0 -699
  21. package/dist/chunk-KEEMHNNS.js +0 -628
  22. package/dist/chunk-RHXNXVGI.js +0 -621
  23. package/dist/chunk-SNV4RWS4.js +0 -696
  24. package/dist/chunk-W7OC77AV.js +0 -649
  25. package/dist/chunk-WFXVVHL2.js +0 -645
  26. package/dist/chunk-YIXP5EWA.js +0 -545
  27. package/dist/chunk-YRVQGOVW.js +0 -649
  28. package/dist/chunk-ZLYMV2NJ.js +0 -644
  29. package/dist/config-C3S4LWLD.js +0 -12
  30. package/dist/config-RHGCFLHQ.js +0 -12
  31. package/dist/reword-2ASH5EH5.js +0 -212
  32. package/dist/reword-CZDYMQEV.js +0 -150
  33. package/dist/reword-D5YVSCPO.js +0 -212
  34. package/dist/reword-ESY2TLBT.js +0 -212
  35. package/dist/reword-FE5N4MGV.js +0 -150
  36. package/dist/reword-IN2D2J4H.js +0 -212
  37. package/dist/reword-JRE6KAF7.js +0 -212
  38. package/dist/reword-KIR2DMTO.js +0 -212
  39. package/dist/reword-KUE3IVBE.js +0 -212
  40. package/dist/reword-LIVSGNUN.js +0 -212
  41. package/dist/reword-MCQOCOZ2.js +0 -212
  42. package/dist/reword-NGEKVTD6.js +0 -212
  43. package/dist/reword-PEOUOAT7.js +0 -212
  44. package/dist/reword-Q7MES34W.js +0 -212
  45. package/dist/reword-T44WTP5I.js +0 -212
  46. package/dist/reword-UA3EG7DK.js +0 -212
  47. package/dist/reword-UE5IP5V3.js +0 -212
  48. package/dist/reword-VKG5G6CB.js +0 -212
  49. package/dist/reword-VRH7B6BE.js +0 -205
  50. package/dist/reword-WFCNTOEU.js +0 -203
  51. package/dist/reword-XWYWVQRZ.js +0 -212
@@ -171,18 +171,7 @@ Refine now.`
171
171
 
172
172
  // src/model/provider.ts
173
173
  import { z } from "zod";
174
- import { createServer } from "net";
175
174
  import { createOpencode } from "@opencode-ai/sdk";
176
- function findFreePort() {
177
- return new Promise((resolve, reject) => {
178
- const server = createServer();
179
- server.on("error", reject);
180
- server.listen(0, "127.0.0.1", () => {
181
- const port = server.address().port;
182
- server.close(() => resolve(port));
183
- });
184
- });
185
- }
186
175
  var OpenCodeProvider = class {
187
176
  constructor(model = "github-copilot/gpt-4.1") {
188
177
  this.model = model;
@@ -221,16 +210,11 @@ ${userAggregate}`;
221
210
  const start = Date.now();
222
211
  let server;
223
212
  try {
224
- if (debug) console.error("[ai-cc][provider] starting opencode server");
225
- const port = await findFreePort();
226
- const opencode = await createOpencode({ signal: ac.signal, port });
213
+ const opencode = await createOpencode({ signal: ac.signal });
227
214
  server = opencode.server;
228
- const client = opencode.client;
215
+ const { client } = opencode;
229
216
  const session = await client.session.create({ body: { title: "aicc" } });
230
- if (!session.data) {
231
- const errMsg = session.error?.message ?? JSON.stringify(session.error) ?? "unknown";
232
- throw new Error(`Failed to create opencode session: ${errMsg}`);
233
- }
217
+ if (!session.data) throw new Error("Failed to create opencode session");
234
218
  const result = await client.session.prompt({
235
219
  path: { id: session.data.id },
236
220
  body: {
@@ -201,13 +201,39 @@ import { createServer } from "net";
201
201
  import { mkdirSync, writeFileSync } from "fs";
202
202
  import { join } from "path";
203
203
  import { tmpdir } from "os";
204
- import { createOpencode } from "@opencode-ai/sdk/v2";
204
+ import { spawn } from "child_process";
205
+ import { createOpencodeClient } from "@opencode-ai/sdk/v2";
205
206
  import chalk2 from "chalk";
206
207
  var pTag = chalk2.dim("[ai-cc]") + chalk2.cyan("[provider]");
207
208
  var pdbg = (msg, pairs = {}) => {
208
209
  const kvStr = Object.entries(pairs).map(([k, v]) => chalk2.dim(k + "=") + chalk2.yellow(String(v))).join(" ");
209
210
  console.error(pTag, chalk2.white(msg), kvStr || "");
210
211
  };
212
+ var killWithFallback = async (pid) => {
213
+ try {
214
+ process.kill(pid, "SIGTERM");
215
+ } catch {
216
+ return;
217
+ }
218
+ const deadline = Date.now() + 1e3;
219
+ while (Date.now() < deadline) {
220
+ await new Promise((r) => setTimeout(r, 100));
221
+ try {
222
+ process.kill(pid, 0);
223
+ } catch {
224
+ return;
225
+ }
226
+ }
227
+ try {
228
+ process.kill(pid, "SIGKILL");
229
+ console.warn(
230
+ chalk2.yellow("\n\u26A0 [ai-cc]") + " opencode server did not shut down cleanly and had to be force-killed." + chalk2.dim(
231
+ " Please report this at https://github.com/kud/ai-conventional-commit-cli/issues/new"
232
+ )
233
+ );
234
+ } catch {
235
+ }
236
+ };
211
237
  function findFreePort() {
212
238
  return new Promise((resolve, reject) => {
213
239
  const server = createServer();
@@ -243,7 +269,7 @@ var OpenCodeProvider = class {
243
269
  if (!this.warmPromise) return;
244
270
  try {
245
271
  const ctx = await this.warmPromise;
246
- ctx.server?.close();
272
+ await ctx.server?.closeAsync();
247
273
  } catch {
248
274
  } finally {
249
275
  process.off("exit", this.exitHandler);
@@ -267,18 +293,60 @@ var OpenCodeProvider = class {
267
293
  const isolatedDir = join(tmpdir(), `aicc-${process.pid}`, "opencode");
268
294
  mkdirSync(isolatedDir, { recursive: true });
269
295
  writeFileSync(join(isolatedDir, "config.json"), '{"mcp":{}}');
296
+ const port = await findFreePort();
270
297
  const originalXDG = process.env.XDG_CONFIG_HOME;
271
298
  process.env.XDG_CONFIG_HOME = join(tmpdir(), `aicc-${process.pid}`);
272
- let opencode;
273
- try {
274
- const port = await findFreePort();
275
- opencode = await createOpencode({ signal: this.ac.signal, port });
276
- } finally {
277
- if (originalXDG === void 0) delete process.env.XDG_CONFIG_HOME;
278
- else process.env.XDG_CONFIG_HOME = originalXDG;
279
- }
280
- const { server, client } = opencode;
281
- this.syncClose = () => server?.close();
299
+ const proc = spawn("opencode", ["serve", `--hostname=127.0.0.1`, `--port=${port}`], {
300
+ env: { ...process.env, OPENCODE_CONFIG_CONTENT: JSON.stringify({ mcp: {} }) }
301
+ });
302
+ const killProc = () => {
303
+ try {
304
+ process.kill(proc.pid, "SIGTERM");
305
+ } catch {
306
+ }
307
+ };
308
+ this.syncClose = killProc;
309
+ if (originalXDG === void 0) delete process.env.XDG_CONFIG_HOME;
310
+ else process.env.XDG_CONFIG_HOME = originalXDG;
311
+ const url = await new Promise((resolve, reject) => {
312
+ const id = setTimeout(
313
+ () => reject(new Error(`Timeout waiting for opencode server after 10s`)),
314
+ 1e4
315
+ );
316
+ let output = "";
317
+ proc.stdout?.on("data", (chunk) => {
318
+ output += chunk.toString();
319
+ for (const line of output.split("\n")) {
320
+ if (!line.startsWith("opencode server listening")) continue;
321
+ const match = line.match(/on\s+(https?:\/\/[^\s]+)/);
322
+ if (!match) {
323
+ reject(new Error(`Failed to parse server url: ${line}`));
324
+ return;
325
+ }
326
+ clearTimeout(id);
327
+ resolve(match[1]);
328
+ return;
329
+ }
330
+ });
331
+ proc.stderr?.on("data", (chunk) => {
332
+ output += chunk.toString();
333
+ });
334
+ proc.on("exit", (code) => {
335
+ clearTimeout(id);
336
+ reject(new Error(`Server exited with code ${code}
337
+ ${output}`));
338
+ });
339
+ proc.on("error", (err) => {
340
+ clearTimeout(id);
341
+ reject(err);
342
+ });
343
+ this.ac.signal.addEventListener("abort", () => {
344
+ clearTimeout(id);
345
+ killProc();
346
+ reject(new Error("Aborted"));
347
+ });
348
+ });
349
+ const client = createOpencodeClient({ baseUrl: url });
282
350
  if (this.debug) {
283
351
  const mcpStatusResult = await client.mcp.status();
284
352
  pdbg("mcp status", { status: JSON.stringify(mcpStatusResult.data) });
@@ -289,7 +357,11 @@ var OpenCodeProvider = class {
289
357
  throw new Error(`Failed to create opencode session: ${errMsg}`);
290
358
  }
291
359
  if (this.debug) pdbg("session created", { id: sessionResult.data.id });
292
- return { client, server, sessionID: sessionResult.data.id };
360
+ return {
361
+ client,
362
+ server: { url, close: killProc, closeAsync: () => killWithFallback(proc.pid) },
363
+ sessionID: sessionResult.data.id
364
+ };
293
365
  }
294
366
  async chat(messages, _opts) {
295
367
  const mockMode = process.env.AICC_DEBUG_PROVIDER === "mock";
@@ -316,10 +388,8 @@ ${userAggregate}`;
316
388
  const providerID = slashIdx !== -1 ? this.model.slice(0, slashIdx) : this.model;
317
389
  const modelID = slashIdx !== -1 ? this.model.slice(slashIdx + 1) : this.model;
318
390
  const start = Date.now();
319
- let server;
320
391
  try {
321
392
  const ctx = await (this.warmPromise ?? this._startServer());
322
- server = ctx.server;
323
393
  if (this.debug) {
324
394
  pdbg("sending prompt", { model: this.model, promptChars: fullPrompt.length });
325
395
  }
@@ -355,8 +425,6 @@ ${userAggregate}`;
355
425
  }
356
426
  if (this.debug) pdbg(chalk2.red("call failed"), { error: e.message });
357
427
  throw new Error(e.message || "opencode SDK call failed");
358
- } finally {
359
- server?.close();
360
428
  }
361
429
  }
362
430
  };