@vexdo/cli 0.1.2 → 0.1.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.
Files changed (2) hide show
  1. package/dist/index.js +89 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -700,6 +700,29 @@ function formatElapsed(startedAt) {
700
700
  const seconds = Math.max(0, Math.round((Date.now() - startedAt) / 1e3));
701
701
  return `${String(seconds)}s`;
702
702
  }
703
+ function buildVerboseStreamHandler(label) {
704
+ let partialLine = "";
705
+ return {
706
+ onData(chunk) {
707
+ partialLine += chunk.toString();
708
+ const lines = partialLine.split(/\r?\n/);
709
+ partialLine = lines.pop() ?? "";
710
+ for (const line of lines) {
711
+ if (!line) {
712
+ continue;
713
+ }
714
+ debug(`[codex:${label}] ${line}`);
715
+ }
716
+ },
717
+ flush() {
718
+ if (!partialLine) {
719
+ return;
720
+ }
721
+ debug(`[codex:${label}] ${partialLine}`);
722
+ partialLine = "";
723
+ }
724
+ };
725
+ }
703
726
  async function checkCodexAvailable() {
704
727
  await new Promise((resolve, reject) => {
705
728
  execFileCb("codex", ["--version"], { timeout: CODEX_TIMEOUT_MS, encoding: "utf8" }, (error) => {
@@ -718,10 +741,13 @@ async function exec(opts) {
718
741
  debug(`[codex] starting (model=${opts.model}, cwd=${opts.cwd})`);
719
742
  }
720
743
  return await new Promise((resolve, reject) => {
744
+ let liveLogsAttached = false;
745
+ const stdoutHandler = buildVerboseStreamHandler("stdout");
746
+ const stderrHandler = buildVerboseStreamHandler("stderr");
721
747
  const heartbeat = opts.verbose ? setInterval(() => {
722
748
  debug(`[codex] still running (${formatElapsed(startedAt)})`);
723
749
  }, VERBOSE_HEARTBEAT_MS) : null;
724
- execFileCb(
750
+ const child = execFileCb(
725
751
  "codex",
726
752
  args,
727
753
  { cwd: opts.cwd, timeout: CODEX_TIMEOUT_MS, encoding: "utf8", maxBuffer: 10 * 1024 * 1024 },
@@ -729,14 +755,16 @@ async function exec(opts) {
729
755
  if (heartbeat) {
730
756
  clearInterval(heartbeat);
731
757
  }
758
+ stdoutHandler.flush();
759
+ stderrHandler.flush();
732
760
  const normalizedStdout = stdout.trimEnd();
733
761
  const normalizedStderr = stderr.trimEnd();
734
762
  if (opts.verbose) {
735
763
  debug(`[codex] finished in ${formatElapsed(startedAt)}`);
736
- if (normalizedStdout) {
764
+ if (!liveLogsAttached && normalizedStdout) {
737
765
  debug(normalizedStdout);
738
766
  }
739
- if (normalizedStderr) {
767
+ if (!liveLogsAttached && normalizedStderr) {
740
768
  debug(normalizedStderr);
741
769
  }
742
770
  }
@@ -755,18 +783,69 @@ async function exec(opts) {
755
783
  });
756
784
  }
757
785
  );
786
+ if (opts.verbose) {
787
+ const stdout = child.stdout;
788
+ const stderr = child.stderr;
789
+ if (stdout) {
790
+ liveLogsAttached = true;
791
+ stdout.on("data", stdoutHandler.onData);
792
+ }
793
+ if (stderr) {
794
+ liveLogsAttached = true;
795
+ stderr.on("data", stderrHandler.onData);
796
+ }
797
+ }
758
798
  });
759
799
  }
760
800
 
761
801
  // src/lib/gh.ts
762
802
  import { execFile as execFileCb2 } from "child_process";
763
803
  var GH_TIMEOUT_MS = 3e4;
804
+ var GIT_TIMEOUT_MS = 3e4;
764
805
  var GhNotFoundError = class extends Error {
765
806
  constructor() {
766
807
  super("gh CLI not found. Install it: https://cli.github.com");
767
808
  this.name = "GhNotFoundError";
768
809
  }
769
810
  };
811
+ var GitCommandError = class extends Error {
812
+ exitCode;
813
+ stderr;
814
+ constructor(args, exitCode, stderr) {
815
+ super(`git ${args.join(" ")} failed (exit ${String(exitCode)}): ${stderr}`);
816
+ this.name = "GitCommandError";
817
+ this.exitCode = exitCode;
818
+ this.stderr = stderr;
819
+ }
820
+ };
821
+ async function execGit(args, cwd) {
822
+ await new Promise((resolve, reject) => {
823
+ execFileCb2("git", args, { cwd, timeout: GIT_TIMEOUT_MS, encoding: "utf8" }, (error, _stdout, stderr) => {
824
+ if (error) {
825
+ const exitCode = typeof error.code === "number" ? error.code : -1;
826
+ reject(new GitCommandError(args, exitCode, (stderr || error.message).trim()));
827
+ return;
828
+ }
829
+ resolve();
830
+ });
831
+ });
832
+ }
833
+ function isNoUpstreamError(error) {
834
+ const text = error.stderr.toLowerCase();
835
+ return text.includes("no upstream configured for branch") || text.includes("has no upstream branch");
836
+ }
837
+ async function pushCurrentBranch(cwd) {
838
+ try {
839
+ await execGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd);
840
+ await execGit(["push"], cwd);
841
+ } catch (error) {
842
+ if (error instanceof GitCommandError && isNoUpstreamError(error)) {
843
+ await execGit(["push", "--set-upstream", "origin", "HEAD"], cwd);
844
+ return;
845
+ }
846
+ throw error;
847
+ }
848
+ }
770
849
  async function checkGhAvailable() {
771
850
  await new Promise((resolve, reject) => {
772
851
  execFileCb2("gh", ["--version"], { timeout: GH_TIMEOUT_MS, encoding: "utf8" }, (error) => {
@@ -780,6 +859,11 @@ async function checkGhAvailable() {
780
859
  }
781
860
  async function createPr(opts) {
782
861
  const base = opts.base ?? "main";
862
+ try {
863
+ await pushCurrentBranch(opts.cwd);
864
+ } catch (error) {
865
+ throw new Error(`Failed to push current branch before creating PR: ${error instanceof Error ? error.message : String(error)}`);
866
+ }
783
867
  return await new Promise((resolve, reject) => {
784
868
  execFileCb2(
785
869
  "gh",
@@ -813,7 +897,7 @@ import path5 from "path";
813
897
 
814
898
  // src/lib/git.ts
815
899
  import { execFile as execFileCb3 } from "child_process";
816
- var GIT_TIMEOUT_MS = 3e4;
900
+ var GIT_TIMEOUT_MS2 = 3e4;
817
901
  var GitError = class extends Error {
818
902
  command;
819
903
  exitCode;
@@ -828,7 +912,7 @@ var GitError = class extends Error {
828
912
  };
829
913
  async function exec2(args, cwd) {
830
914
  return new Promise((resolve, reject) => {
831
- execFileCb3("git", args, { cwd, timeout: GIT_TIMEOUT_MS, encoding: "utf8" }, (error, stdout, stderr) => {
915
+ execFileCb3("git", args, { cwd, timeout: GIT_TIMEOUT_MS2, encoding: "utf8" }, (error, stdout, stderr) => {
832
916
  if (error) {
833
917
  const exitCode = typeof error.code === "number" ? error.code : -1;
834
918
  reject(new GitError(args, exitCode, (stderr || error.message).trim()));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vexdo/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {