@captainsafia/stitch 1.0.0-preview.00492d9 → 1.0.0-preview.26f92f3

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 (3) hide show
  1. package/dist/cli.js +110 -36
  2. package/dist/mcp.js +1 -1
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1895,7 +1895,7 @@ var require_commander = __commonJS((exports) => {
1895
1895
  var require_package = __commonJS((exports, module) => {
1896
1896
  module.exports = {
1897
1897
  name: "@captainsafia/stitch",
1898
- version: "1.0.0-preview.00492d9",
1898
+ version: "1.0.0-preview.26f92f3",
1899
1899
  type: "module",
1900
1900
  description: "A local-first CLI for recording intent and binding it to git commits/diffs",
1901
1901
  main: "dist/api.js",
@@ -1966,7 +1966,7 @@ var require_package = __commonJS((exports, module) => {
1966
1966
  });
1967
1967
 
1968
1968
  // src/cli.ts
1969
- import { join as join4 } from "path";
1969
+ import { join as join5 } from "path";
1970
1970
 
1971
1971
  // node_modules/commander/esm.mjs
1972
1972
  var import__ = __toESM(require_commander(), 1);
@@ -4139,7 +4139,11 @@ function renderSuccess(message) {
4139
4139
  return `\u2713 ${message}`;
4140
4140
  }
4141
4141
  // src/platform/update/download.ts
4142
+ var {$: $2 } = globalThis.Bun;
4143
+ import { existsSync as existsSync3 } from "fs";
4144
+ import { join as join3 } from "path";
4142
4145
  var DOWNLOAD_BASE_URL = "https://github.com/captainsafia/stitch/releases/download";
4146
+ var REPO = "captainsafia/stitch";
4143
4147
  function detectPlatform() {
4144
4148
  const platform = process.platform;
4145
4149
  const arch = process.arch;
@@ -4218,48 +4222,98 @@ async function downloadBinary(url, destPath, onProgress) {
4218
4222
  }
4219
4223
  await Bun.write(destPath, binary);
4220
4224
  }
4225
+ async function downloadPRArtifact(prNumber, destPath, onProgress) {
4226
+ const ghCheck = await $2`which gh`.nothrow().quiet();
4227
+ if (ghCheck.exitCode !== 0) {
4228
+ throw new Error("GitHub CLI (gh) is required to download PR artifacts. Install it from https://cli.github.com/");
4229
+ }
4230
+ const platform = detectPlatform();
4231
+ const artifactName = `stitch-pr-${prNumber}-${platform}`;
4232
+ onProgress?.(`Downloading PR #${prNumber} artifact: ${artifactName}...`);
4233
+ const runsResult = await $2`gh run list --repo ${REPO} --workflow pr-publish.yml --json databaseId,status,conclusion,headBranch --limit 50`.nothrow().quiet();
4234
+ if (runsResult.exitCode !== 0) {
4235
+ throw new Error(`Failed to list workflow runs: ${runsResult.stderr.toString()}`);
4236
+ }
4237
+ const runs = JSON.parse(runsResult.stdout.toString());
4238
+ const { tmpdir } = await import("os");
4239
+ const { mkdtemp } = await import("fs/promises");
4240
+ const tmpDir = await mkdtemp(join3(tmpdir(), `stitch-pr-${prNumber}-`));
4241
+ try {
4242
+ let foundRun = null;
4243
+ for (const run of runs) {
4244
+ if (run.status === "completed" && run.conclusion === "success") {
4245
+ const downloadResult = await $2`gh run download ${run.databaseId} --repo ${REPO} --name ${artifactName} --dir ${tmpDir}`.nothrow().quiet();
4246
+ if (downloadResult.exitCode === 0) {
4247
+ foundRun = run;
4248
+ break;
4249
+ }
4250
+ }
4251
+ }
4252
+ if (!foundRun) {
4253
+ throw new Error(`Failed to find artifact for PR #${prNumber}. Make sure the PR exists and has completed successfully.`);
4254
+ }
4255
+ const binaryName = platform === "windows-x64" ? `stitch-${platform}.exe` : `stitch-${platform}`;
4256
+ const tmpBinaryPath = join3(tmpDir, binaryName);
4257
+ if (!existsSync3(tmpBinaryPath)) {
4258
+ throw new Error(`Downloaded artifact does not contain expected binary: ${binaryName}`);
4259
+ }
4260
+ const binaryData = await Bun.file(tmpBinaryPath).arrayBuffer();
4261
+ await Bun.write(destPath, binaryData);
4262
+ onProgress?.("Download complete");
4263
+ } finally {
4264
+ try {
4265
+ const { rm } = await import("fs/promises");
4266
+ await rm(tmpDir, { recursive: true, force: true });
4267
+ } catch {}
4268
+ }
4269
+ }
4221
4270
  // src/platform/update/install.ts
4222
4271
  import { rename, unlink, chmod } from "fs/promises";
4223
- import { existsSync as existsSync3 } from "fs";
4224
- import { dirname, join as join3 } from "path";
4225
- var {$: $2 } = globalThis.Bun;
4272
+ import { existsSync as existsSync4 } from "fs";
4273
+ import { dirname, join as join4 } from "path";
4274
+ var {$: $3 } = globalThis.Bun;
4226
4275
  function getCurrentExecutablePath() {
4227
4276
  return process.execPath;
4228
4277
  }
4229
4278
  async function cleanupOldBinaries(execPath) {
4230
4279
  const dir = dirname(execPath);
4231
4280
  const baseName = execPath.endsWith(".exe") ? "stitch" : "stitch";
4232
- const oldPath = join3(dir, `${baseName}.old`);
4233
- const oldPathExe = join3(dir, `${baseName}.old.exe`);
4281
+ const oldPath = join4(dir, `${baseName}.old`);
4282
+ const oldPathExe = join4(dir, `${baseName}.old.exe`);
4234
4283
  for (const path of [oldPath, oldPathExe]) {
4235
- if (existsSync3(path)) {
4284
+ if (existsSync4(path)) {
4236
4285
  try {
4237
4286
  await unlink(path);
4238
4287
  } catch {}
4239
4288
  }
4240
4289
  }
4241
4290
  }
4242
- async function installBinaryUpdate(targetVersion, currentVersion, onProgress) {
4291
+ async function installBinaryUpdate(targetVersion, currentVersion, onProgress, prNumber) {
4243
4292
  const platform = detectPlatform();
4244
4293
  const execPath = getCurrentExecutablePath();
4245
4294
  const dir = dirname(execPath);
4246
4295
  const isWindows = platform === "windows-x64";
4247
- const newBinaryPath = join3(dir, isWindows ? "stitch.new.exe" : "stitch.new");
4248
- const oldBinaryPath = join3(dir, isWindows ? "stitch.old.exe" : "stitch.old");
4249
- const downloadUrl = getDownloadUrl(targetVersion, platform);
4296
+ const newBinaryPath = join4(dir, isWindows ? "stitch.new.exe" : "stitch.new");
4297
+ const oldBinaryPath = join4(dir, isWindows ? "stitch.old.exe" : "stitch.old");
4250
4298
  try {
4251
4299
  await cleanupOldBinaries(execPath);
4252
- onProgress?.(`Downloading stitch v${targetVersion}...`);
4253
- let lastPercent = 0;
4254
- await downloadBinary(downloadUrl, newBinaryPath, (downloaded, total) => {
4255
- if (total) {
4256
- const percent = Math.round(downloaded / total * 100);
4257
- if (percent !== lastPercent && percent % 10 === 0) {
4258
- onProgress?.(`Downloading: ${percent}%`);
4259
- lastPercent = percent;
4300
+ if (prNumber) {
4301
+ onProgress?.(`Downloading from PR #${prNumber}...`);
4302
+ await downloadPRArtifact(prNumber, newBinaryPath, onProgress);
4303
+ } else {
4304
+ const downloadUrl = getDownloadUrl(targetVersion, platform);
4305
+ onProgress?.(`Downloading stitch v${targetVersion}...`);
4306
+ let lastPercent = 0;
4307
+ await downloadBinary(downloadUrl, newBinaryPath, (downloaded, total) => {
4308
+ if (total) {
4309
+ const percent = Math.round(downloaded / total * 100);
4310
+ if (percent !== lastPercent && percent % 10 === 0) {
4311
+ onProgress?.(`Downloading: ${percent}%`);
4312
+ lastPercent = percent;
4313
+ }
4260
4314
  }
4261
- }
4262
- });
4315
+ });
4316
+ }
4263
4317
  if (!isWindows) {
4264
4318
  await chmod(newBinaryPath, 493);
4265
4319
  }
@@ -4275,12 +4329,12 @@ async function installBinaryUpdate(targetVersion, currentVersion, onProgress) {
4275
4329
  newVersion: targetVersion
4276
4330
  };
4277
4331
  } catch (error) {
4278
- if (existsSync3(oldBinaryPath) && !existsSync3(execPath)) {
4332
+ if (existsSync4(oldBinaryPath) && !existsSync4(execPath)) {
4279
4333
  try {
4280
4334
  await rename(oldBinaryPath, execPath);
4281
4335
  } catch {}
4282
4336
  }
4283
- if (existsSync3(newBinaryPath)) {
4337
+ if (existsSync4(newBinaryPath)) {
4284
4338
  try {
4285
4339
  await unlink(newBinaryPath);
4286
4340
  } catch {}
@@ -4297,7 +4351,7 @@ async function installNpmUpdate(targetVersion, currentVersion, onProgress) {
4297
4351
  try {
4298
4352
  onProgress?.(`Updating via npm to v${targetVersion}...`);
4299
4353
  const versionSpec = targetVersion === "latest" ? "@captainsafia/stitch@latest" : `@captainsafia/stitch@${targetVersion}`;
4300
- const result = await $2`npm install -g ${versionSpec}`.quiet();
4354
+ const result = await $3`npm install -g ${versionSpec}`.quiet();
4301
4355
  if (result.exitCode !== 0) {
4302
4356
  return {
4303
4357
  success: false,
@@ -4324,7 +4378,7 @@ async function installBunUpdate(targetVersion, currentVersion, onProgress) {
4324
4378
  try {
4325
4379
  onProgress?.(`Updating via bun to v${targetVersion}...`);
4326
4380
  const versionSpec = targetVersion === "latest" ? "@captainsafia/stitch@latest" : `@captainsafia/stitch@${targetVersion}`;
4327
- const result = await $2`bun install -g ${versionSpec}`.quiet();
4381
+ const result = await $3`bun install -g ${versionSpec}`.quiet();
4328
4382
  if (result.exitCode !== 0) {
4329
4383
  return {
4330
4384
  success: false,
@@ -4347,14 +4401,30 @@ async function installBunUpdate(targetVersion, currentVersion, onProgress) {
4347
4401
  };
4348
4402
  }
4349
4403
  }
4350
- async function installUpdate(targetVersion, currentVersion, onProgress) {
4404
+ async function installUpdate(targetVersion, currentVersion, onProgress, prNumber) {
4351
4405
  const installMethod = detectInstallMethod();
4352
4406
  switch (installMethod) {
4353
4407
  case "binary":
4354
- return installBinaryUpdate(targetVersion, currentVersion, onProgress);
4408
+ return installBinaryUpdate(targetVersion, currentVersion, onProgress, prNumber);
4355
4409
  case "npm":
4410
+ if (prNumber) {
4411
+ return {
4412
+ success: false,
4413
+ previousVersion: currentVersion,
4414
+ newVersion: targetVersion,
4415
+ error: "PR updates are only available for standalone binary installations."
4416
+ };
4417
+ }
4356
4418
  return installNpmUpdate(targetVersion, currentVersion, onProgress);
4357
4419
  case "bun":
4420
+ if (prNumber) {
4421
+ return {
4422
+ success: false,
4423
+ previousVersion: currentVersion,
4424
+ newVersion: targetVersion,
4425
+ error: "PR updates are only available for standalone binary installations."
4426
+ };
4427
+ }
4358
4428
  return installBunUpdate(targetVersion, currentVersion, onProgress);
4359
4429
  case "dev":
4360
4430
  return {
@@ -4382,7 +4452,7 @@ var packageJson = await Promise.resolve().then(() => __toESM(require_package(),
4382
4452
  var program2 = new Command;
4383
4453
  program2.name("stitch").description(packageJson.description).version(packageJson.version);
4384
4454
  function createNotifier() {
4385
- const cacheFilePath = join4(getConfigDir(), "update-check.json");
4455
+ const cacheFilePath = join5(getConfigDir(), "update-check.json");
4386
4456
  return new ReleaseNotifier({
4387
4457
  repo: "captainsafia/stitch",
4388
4458
  checkInterval: 86400000,
@@ -4619,12 +4689,19 @@ program2.command("blame").description("Show stitch attribution for each line in
4619
4689
  __callDispose(__stack, _err, _hasErr);
4620
4690
  }
4621
4691
  });
4622
- program2.command("update").description("Update stitch to the latest version").option("-t, --target <version>", "Install a specific version").option("-p, --preview", "Install the latest preview version").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
4692
+ program2.command("update").description("Update stitch to the latest version").allowExcessArguments(false).option("-t, --target <version>", "Install a specific version").option("-p, --preview", "Install the latest preview version").option("--pr <number>", "Install from a PR artifact (requires gh CLI)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
4623
4693
  try {
4624
4694
  const current = packageJson.version;
4625
4695
  const installMethod = detectInstallMethod();
4626
4696
  let targetVersion;
4627
- if (options.target) {
4697
+ const optionCount = [options.target, options.preview, options.pr].filter(Boolean).length;
4698
+ if (optionCount > 1) {
4699
+ console.error("Error: Cannot specify more than one of --target, --preview, or --pr");
4700
+ process.exit(1);
4701
+ }
4702
+ if (options.pr) {
4703
+ targetVersion = `PR #${options.pr}`;
4704
+ } else if (options.target) {
4628
4705
  targetVersion = options.target;
4629
4706
  } else if (options.preview) {
4630
4707
  console.log("Checking for latest preview version...");
@@ -4647,7 +4724,7 @@ program2.command("update").description("Update stitch to the latest version").op
4647
4724
  }
4648
4725
  targetVersion = stableRelease.tagName.replace(/^v/, "");
4649
4726
  }
4650
- if (current === targetVersion) {
4727
+ if (!options.pr && current === targetVersion) {
4651
4728
  console.log(`Already running stitch v${current}`);
4652
4729
  return;
4653
4730
  }
@@ -4668,13 +4745,10 @@ program2.command("update").description("Update stitch to the latest version").op
4668
4745
  }
4669
4746
  const result = await installUpdate(targetVersion, current, (message) => {
4670
4747
  console.log(message);
4671
- });
4748
+ }, options.pr);
4672
4749
  if (result.success) {
4673
4750
  console.log("");
4674
4751
  console.log(renderSuccess(`Updated stitch from v${current} to v${targetVersion}`));
4675
- if (installMethod === "binary") {
4676
- console.log("Please restart your terminal for changes to take effect.");
4677
- }
4678
4752
  } else {
4679
4753
  console.error("");
4680
4754
  console.error(`Error: Update failed: ${result.error}`);
package/dist/mcp.js CHANGED
@@ -6494,7 +6494,7 @@ var require_dist = __commonJS((exports, module) => {
6494
6494
  var require_package = __commonJS((exports, module) => {
6495
6495
  module.exports = {
6496
6496
  name: "@captainsafia/stitch",
6497
- version: "1.0.0-preview.00492d9",
6497
+ version: "1.0.0-preview.26f92f3",
6498
6498
  type: "module",
6499
6499
  description: "A local-first CLI for recording intent and binding it to git commits/diffs",
6500
6500
  main: "dist/api.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@captainsafia/stitch",
3
- "version": "1.0.0-preview.00492d9",
3
+ "version": "1.0.0-preview.26f92f3",
4
4
  "type": "module",
5
5
  "description": "A local-first CLI for recording intent and binding it to git commits/diffs",
6
6
  "main": "dist/api.js",