@runeya/runeya 2.0.87 → 2.0.88

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.
package/agent/index.js CHANGED
@@ -4928,12 +4928,69 @@ var terminalRouter = router({
4928
4928
  // src/trpc/routers/git.ts
4929
4929
  import { z as z25 } from "zod";
4930
4930
  import { TRPCError as TRPCError4 } from "@trpc/server";
4931
- import { execFile as execFile4, spawn as spawn3 } from "child_process";
4932
- import { promisify as promisify2 } from "util";
4931
+ import { execFile as execFile5, spawn as spawn3 } from "child_process";
4932
+ import { promisify as promisify3 } from "util";
4933
4933
  import { existsSync, watch as fsWatch } from "fs";
4934
4934
  import { promises as fsPromises2 } from "fs";
4935
4935
  import { join as join4, resolve as resolvePath } from "path";
4936
+
4937
+ // src/utils/git-remote.ts
4938
+ import { execFile as execFile4 } from "child_process";
4939
+ import { promisify as promisify2 } from "util";
4936
4940
  var execFileAsync2 = promisify2(execFile4);
4941
+ function parseGitRemote(url) {
4942
+ const trimmed = url.trim();
4943
+ if (!trimmed) return null;
4944
+ let host;
4945
+ let path3;
4946
+ const scp = /^(?:[^/@]+@)?([^/:]+):(?!\/)(.+)$/.exec(trimmed);
4947
+ if (scp) {
4948
+ host = scp[1];
4949
+ path3 = scp[2];
4950
+ } else {
4951
+ let parsed;
4952
+ try {
4953
+ parsed = new URL(trimmed);
4954
+ } catch {
4955
+ return null;
4956
+ }
4957
+ if (parsed.protocol === "file:" || !parsed.hostname) return null;
4958
+ host = parsed.hostname;
4959
+ path3 = parsed.pathname;
4960
+ }
4961
+ path3 = path3.replace(/^\/+/, "").replace(/\/+$/, "").replace(/\.git$/i, "");
4962
+ if (!host || !path3) return null;
4963
+ return { host: host.toLowerCase(), path: path3.toLowerCase() };
4964
+ }
4965
+ async function resolveSshHost(host) {
4966
+ if (!/^[a-zA-Z0-9._-]+$/.test(host)) return host;
4967
+ try {
4968
+ const { stdout } = await execFileAsync2("ssh", ["-G", host], {
4969
+ timeout: 3e3,
4970
+ env: { PATH: process.env["PATH"] ?? "", HOME: process.env["HOME"] ?? "" }
4971
+ });
4972
+ const match = /^hostname (.+)$/m.exec(stdout);
4973
+ return match ? match[1].trim().toLowerCase() : host;
4974
+ } catch {
4975
+ return host;
4976
+ }
4977
+ }
4978
+ async function sameGitRemote(a, b, resolveHost = resolveSshHost) {
4979
+ if (a.trim() === b.trim()) return true;
4980
+ const left = parseGitRemote(a);
4981
+ const right = parseGitRemote(b);
4982
+ if (!left || !right) return false;
4983
+ if (left.path !== right.path) return false;
4984
+ if (left.host === right.host) return true;
4985
+ const [leftHost, rightHost] = await Promise.all([
4986
+ resolveHost(left.host),
4987
+ resolveHost(right.host)
4988
+ ]);
4989
+ return leftHost === rightHost;
4990
+ }
4991
+
4992
+ // src/trpc/routers/git.ts
4993
+ var execFileAsync3 = promisify3(execFile5);
4937
4994
  var GIT_TIMEOUT = 15e3;
4938
4995
  var DIFF_MAX_BYTES = 512 * 1024;
4939
4996
  var CWD_SCHEMA = z25.string().min(1).max(4096);
@@ -4975,7 +5032,7 @@ async function git(args, cwd, readOnly = false) {
4975
5032
  const env2 = gitSafeEnv();
4976
5033
  if (readOnly) env2["GIT_OPTIONAL_LOCKS"] = "0";
4977
5034
  try {
4978
- const result = execFileAsync2("git", args, { cwd, signal: ac.signal, env: env2 });
5035
+ const result = execFileAsync3("git", args, { cwd, signal: ac.signal, env: env2 });
4979
5036
  if (result.child) {
4980
5037
  activeGitProcesses.add(result.child);
4981
5038
  result.child.on("close", () => activeGitProcesses.delete(result.child));
@@ -5067,20 +5124,21 @@ var gitRouter = router({
5067
5124
  const resolvedCwd = expandEnvVar(input.cwd);
5068
5125
  const unresolvedVars = [...resolvedCwd.matchAll(/\$\{?(\w+)\}?/g)].map((m) => m[1]);
5069
5126
  if (unresolvedVars.length > 0) {
5070
- return { exists: false, actualRemote: null, unreachable: false, resolvedCwd, unresolvedVars };
5127
+ return { exists: false, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd, unresolvedVars };
5071
5128
  }
5072
5129
  const absoluteCwd = resolvePath(resolvedCwd);
5073
5130
  const exists = existsSync(absoluteCwd);
5074
5131
  if (!exists || !input.remote) {
5075
- return { exists, actualRemote: null, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5132
+ return { exists, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5076
5133
  }
5077
5134
  const { code: urlCode, out: actualRemote } = await runGitRaw(["-C", absoluteCwd, "remote", "get-url", "origin"], 5e3);
5078
- if (urlCode !== 0) return { exists, actualRemote: null, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5135
+ if (urlCode !== 0) return { exists, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5136
+ const remoteMatches = await sameGitRemote(actualRemote, input.remote);
5079
5137
  if (input.checkReachability) {
5080
5138
  const { code: showCode } = await runGitRaw(["-C", absoluteCwd, "remote", "show", "origin"], 1e4);
5081
- return { exists, actualRemote, unreachable: showCode !== 0, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5139
+ return { exists, actualRemote, remoteMatches, unreachable: showCode !== 0, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5082
5140
  }
5083
- return { exists, actualRemote, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5141
+ return { exists, actualRemote, remoteMatches, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };
5084
5142
  }),
5085
5143
  /** Clone a git repository into a target directory */
5086
5144
  clone: protectedProcedure.input(z25.object({
@@ -6625,12 +6683,12 @@ function appendToPath(dir, environment = process.env) {
6625
6683
  }
6626
6684
 
6627
6685
  // ../../packages/shared/src/node/user-path.ts
6628
- import { execFile as execFile5 } from "child_process";
6629
- import { promisify as promisify3 } from "util";
6686
+ import { execFile as execFile6 } from "child_process";
6687
+ import { promisify as promisify4 } from "util";
6630
6688
  import { homedir as homedir7 } from "os";
6631
6689
  import { existsSync as existsSync4, statSync } from "fs";
6632
6690
  import { join as join6, delimiter as delimiter2 } from "path";
6633
- var execFileAsync3 = promisify3(execFile5);
6691
+ var execFileAsync4 = promisify4(execFile6);
6634
6692
  var MARKER = "__RUNEYA_PATH__";
6635
6693
  var SHELL_TIMEOUT_MS = 3e3;
6636
6694
  function commonUserBins(home) {
@@ -6649,7 +6707,7 @@ async function readLoginShellPath() {
6649
6707
  const shell = process.env["SHELL"];
6650
6708
  if (!shell || !existsSync4(shell)) return null;
6651
6709
  try {
6652
- const { stdout } = await execFileAsync3(shell, ["-l", "-i", "-c", `echo "${MARKER}$PATH"`], {
6710
+ const { stdout } = await execFileAsync4(shell, ["-l", "-i", "-c", `echo "${MARKER}$PATH"`], {
6653
6711
  timeout: SHELL_TIMEOUT_MS,
6654
6712
  shell: false,
6655
6713
  encoding: "utf8",