@agimon-ai/po-git 0.0.0-alpha.45 → 0.0.0-alpha.46

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.
@@ -1,5 +1,5 @@
1
- import { C as READ_TIMEOUT_MS, E as runGit, S as NETWORK_TIMEOUT_MS, T as createWorktreeGit, a as GIT_WORKTREE_LIFECYCLE_EVENT, c as isWorktreeLifecycleEvent, d as registryFile, f as readJson, g as invalidRequest, h as PoGitExpectedError, i as GIT_SESSION_CHANGED_EVENT, l as credentialsFile, m as HubUnavailableError, n as createWorktreeRegistry, o as createWorktreeMessageInbox, p as writeJsonAtomic, r as validRefName, s as isSessionChangedEvent, t as createWorktreeOperations, u as poGitRoot, w as REBASE_TIMEOUT_MS } from "../worktreeOperations-BqLLypS5.mjs";
2
- import fs from "node:fs";
1
+ import { C as READ_TIMEOUT_MS, E as runGit, S as NETWORK_TIMEOUT_MS, T as createWorktreeGit, a as GIT_WORKTREE_LIFECYCLE_EVENT, c as isWorktreeLifecycleEvent, d as registryFile, f as readJson, g as invalidRequest, h as PoGitExpectedError, i as GIT_SESSION_CHANGED_EVENT, l as credentialsFile, m as HubUnavailableError, n as createWorktreeRegistry, o as createWorktreeMessageInbox, p as writeJsonAtomic, r as validRefName, s as isSessionChangedEvent, t as createWorktreeOperations, u as poGitRoot, w as REBASE_TIMEOUT_MS } from "../worktreeOperations-CP2lYxrI.mjs";
2
+ import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import os from "node:os";
5
5
  import { composeServerProviderOverrides, defineServerPlugin, packageResourcePath, readPackageResource } from "@agimon-ai/po-core/serverPlugin";
@@ -646,11 +646,11 @@ const NAME_STATUS = {
646
646
  T: "modified"
647
647
  };
648
648
  /** Line count of a small regular file, or undefined when it is binary, large, or not a regular file. */
649
- function untrackedLines(root, relPath) {
649
+ async function untrackedLines(root, relPath) {
650
650
  const absolute = path.join(root, relPath);
651
651
  let stat;
652
652
  try {
653
- stat = fs.lstatSync(absolute);
653
+ stat = await fs.lstat(absolute);
654
654
  } catch {
655
655
  return;
656
656
  }
@@ -659,7 +659,7 @@ function untrackedLines(root, relPath) {
659
659
  binary: false
660
660
  };
661
661
  if (!stat.isFile() || stat.size > MAX_FILE_BYTES) return void 0;
662
- const content = fs.readFileSync(absolute);
662
+ const content = await fs.readFile(absolute);
663
663
  if (content.subarray(0, BINARY_PROBE_BYTES).includes(0)) return {
664
664
  lines: 0,
665
665
  binary: true
@@ -782,8 +782,8 @@ function createBranchDiff() {
782
782
  "--exclude-standard",
783
783
  "-z"
784
784
  ]));
785
- untracked.forEach((relPath, index) => {
786
- const counted = index < MAX_UNTRACKED_COUNTED ? untrackedLines(root, relPath) : void 0;
785
+ for (const [index, relPath] of untracked.entries()) {
786
+ const counted = index < MAX_UNTRACKED_COUNTED ? await untrackedLines(root, relPath) : void 0;
787
787
  entries.push({
788
788
  path: relPath,
789
789
  status: "untracked",
@@ -791,18 +791,20 @@ function createBranchDiff() {
791
791
  removed: 0,
792
792
  ...counted?.binary ? { binary: true } : {}
793
793
  });
794
- });
794
+ }
795
795
  entries.sort((left, right) => left.path.localeCompare(right.path));
796
796
  const conflicts = [...unmerged];
797
- const rebasing = [await readLine$1(root, [
797
+ const rebaseMerge = await readLine$1(root, [
798
798
  "rev-parse",
799
799
  "--git-path",
800
800
  "rebase-merge"
801
- ]), await readLine$1(root, [
801
+ ]);
802
+ const rebaseApply = await readLine$1(root, [
802
803
  "rev-parse",
803
804
  "--git-path",
804
805
  "rebase-apply"
805
- ])].some((gitPath) => gitPath !== void 0 && fs.existsSync(path.resolve(root, gitPath)));
806
+ ]);
807
+ const rebasing = (await Promise.all([rebaseMerge, rebaseApply].map(async (gitPath) => gitPath === void 0 ? false : fs.access(path.resolve(root, gitPath)).then(() => true, () => false)))).some(Boolean);
806
808
  const upstreamRef = branch === void 0 ? void 0 : await upstreamOf(root, branch);
807
809
  let upstream;
808
810
  if (upstreamRef !== void 0) {
@@ -847,7 +849,7 @@ function createBranchDiff() {
847
849
  if (entry === void 0) throw new Error("That path is not in this review.");
848
850
  if (entry.status === "untracked") {
849
851
  const absolute = path.join(review.root, entry.path);
850
- const stat = fs.lstatSync(absolute);
852
+ const stat = await fs.lstat(absolute);
851
853
  if (stat.isSymbolicLink()) return {
852
854
  path: entry.path,
853
855
  hunks: [{
@@ -855,7 +857,7 @@ function createBranchDiff() {
855
857
  rows: [{
856
858
  marker: "+",
857
859
  line: 1,
858
- content: fs.readlinkSync(absolute)
860
+ content: await fs.readlink(absolute)
859
861
  }]
860
862
  }]
861
863
  };
@@ -864,7 +866,7 @@ function createBranchDiff() {
864
866
  hunks: [],
865
867
  tooLarge: true
866
868
  };
867
- const content = fs.readFileSync(absolute);
869
+ const content = await fs.readFile(absolute);
868
870
  if (content.subarray(0, BINARY_PROBE_BYTES).includes(0)) return {
869
871
  path: entry.path,
870
872
  hunks: [],
@@ -981,9 +983,9 @@ function isRecord(value) {
981
983
  return typeof value === "object" && value !== null && !Array.isArray(value);
982
984
  }
983
985
  /** The workspace key: the canonical root, so a symlinked path and its target share one entry. */
984
- function workspaceKey(workspaceRoot) {
986
+ async function workspaceKey(workspaceRoot) {
985
987
  try {
986
- return fs.realpathSync(workspaceRoot);
988
+ return await fs.realpath(workspaceRoot);
987
989
  } catch {
988
990
  return path.resolve(workspaceRoot);
989
991
  }
@@ -1032,7 +1034,7 @@ function publicView(config) {
1032
1034
  * the saved one, and only for the same host: a token never follows a host it
1033
1035
  * was not entered for.
1034
1036
  */
1035
- function parseGitAuthSave(request, current, homeDir) {
1037
+ async function parseGitAuthSave(request, current, homeDir) {
1036
1038
  if (!isRecord(request)) throw invalidRequest("The git auth request is not an object.", "Send method none, ssh or https.");
1037
1039
  if (request.method === "none") return { method: "none" };
1038
1040
  if (request.method === "ssh") {
@@ -1042,7 +1044,7 @@ function parseGitAuthSave(request, current, homeDir) {
1042
1044
  if (!keyPath.startsWith("/") && !keyPath.startsWith("~/")) throw invalidRequest("The key path is not absolute.", "Give the key as an absolute path or one under ~/.");
1043
1045
  let isFile = false;
1044
1046
  try {
1045
- isFile = fs.statSync(expandHome(keyPath, homeDir)).isFile();
1047
+ isFile = (await fs.stat(expandHome(keyPath, homeDir))).isFile();
1046
1048
  } catch {
1047
1049
  isFile = false;
1048
1050
  }
@@ -1077,16 +1079,16 @@ function parseGitAuthSave(request, current, homeDir) {
1077
1079
  throw invalidRequest("The git auth method is unknown.", "Send method none, ssh or https.");
1078
1080
  }
1079
1081
  /** Tightens a file or folder something left readable by group or others. */
1080
- function tighten(target, mode) {
1082
+ async function tighten(target, mode) {
1081
1083
  try {
1082
- if ((fs.statSync(target).mode & LOOSE_BITS) !== 0) fs.chmodSync(target, mode);
1084
+ if (((await fs.stat(target)).mode & LOOSE_BITS) !== 0) await fs.chmod(target, mode);
1083
1085
  } catch {}
1084
1086
  }
1085
1087
  function createGitAuthStore(homeDir = os.homedir()) {
1086
1088
  const file = credentialsFile(homeDir);
1087
- const readFile = () => {
1088
- tighten(file, OWNER_ONLY_FILE);
1089
- const raw = readJson(file);
1089
+ const readFile = async () => {
1090
+ await tighten(file, OWNER_ONLY_FILE);
1091
+ const raw = await readJson(file);
1090
1092
  const workspaces = {};
1091
1093
  if (isRecord(raw) && raw.version === 1 && isRecord(raw.workspaces)) for (const [key, value] of Object.entries(raw.workspaces)) {
1092
1094
  const config = parseConfig(value);
@@ -1097,28 +1099,28 @@ function createGitAuthStore(homeDir = os.homedir()) {
1097
1099
  workspaces
1098
1100
  };
1099
1101
  };
1100
- const read = (workspaceRoot) => readFile().workspaces[workspaceKey(workspaceRoot)] ?? { method: "none" };
1102
+ const read = async (workspaceRoot) => (await readFile()).workspaces[await workspaceKey(workspaceRoot)] ?? { method: "none" };
1101
1103
  return {
1102
1104
  read,
1103
- view: (workspaceRoot) => publicView(read(workspaceRoot)),
1104
- save(workspaceRoot, request) {
1105
- const key = workspaceKey(workspaceRoot);
1106
- const current = readFile();
1107
- const next = parseGitAuthSave(request, current.workspaces[key] ?? { method: "none" }, homeDir);
1105
+ view: async (workspaceRoot) => publicView(await read(workspaceRoot)),
1106
+ async save(workspaceRoot, request) {
1107
+ const key = await workspaceKey(workspaceRoot);
1108
+ const current = await readFile();
1109
+ const next = await parseGitAuthSave(request, current.workspaces[key] ?? { method: "none" }, homeDir);
1108
1110
  const root = poGitRoot(homeDir);
1109
- fs.mkdirSync(root, {
1111
+ await fs.mkdir(root, {
1110
1112
  recursive: true,
1111
1113
  mode: OWNER_ONLY_DIRECTORY
1112
1114
  });
1113
- fs.chmodSync(root, OWNER_ONLY_DIRECTORY);
1115
+ await fs.chmod(root, OWNER_ONLY_DIRECTORY);
1114
1116
  const workspaces = { ...current.workspaces };
1115
1117
  if (next.method === "none") delete workspaces[key];
1116
1118
  else workspaces[key] = next;
1117
- writeJsonAtomic(file, {
1119
+ await writeJsonAtomic(file, {
1118
1120
  version: 1,
1119
1121
  workspaces
1120
1122
  });
1121
- fs.chmodSync(file, OWNER_ONLY_FILE);
1123
+ await fs.chmod(file, OWNER_ONLY_FILE);
1122
1124
  return publicView(next);
1123
1125
  }
1124
1126
  };
@@ -1364,9 +1366,9 @@ var route_server_default = defineRoute({
1364
1366
  if (request.method !== "GET" && request.method !== "PUT") return Response.json({ error: "Use GET or PUT." }, { status: 405 });
1365
1367
  const root = rootOf(url);
1366
1368
  if (root instanceof Response) return root;
1367
- if (request.method === "GET") return Response.json(gitAuth.view(root));
1369
+ if (request.method === "GET") return Response.json(await gitAuth.view(root));
1368
1370
  try {
1369
- return Response.json(gitAuth.save(root, await request.json().catch(() => void 0)));
1371
+ return Response.json(await gitAuth.save(root, await request.json().catch(() => void 0)));
1370
1372
  } catch (error) {
1371
1373
  if (error instanceof PoGitExpectedError && error.code === "invalid_request") {
1372
1374
  const text = error.message.replace(/^\[[a-z_]+\] /u, "").replace("\nRecovery: ", " ");
@@ -1390,7 +1392,7 @@ var route_server_default = defineRoute({
1390
1392
  if (request.method !== "GET") return Response.json({ error: "Use GET." }, { status: 405 });
1391
1393
  let recordedBaseRef;
1392
1394
  try {
1393
- recordedBaseRef = createWorktreeRegistry(registryFile(cwd, homeDir)).list().find((record) => record.sessionId === context.sessionId)?.baseRef;
1395
+ recordedBaseRef = (await createWorktreeRegistry(await registryFile(cwd, homeDir)).list()).find((record) => record.sessionId === context.sessionId)?.baseRef;
1394
1396
  } catch {
1395
1397
  recordedBaseRef = void 0;
1396
1398
  }
@@ -1590,7 +1592,7 @@ async function rebasing(root) {
1590
1592
  "--git-path",
1591
1593
  name
1592
1594
  ]);
1593
- if (gitPath !== void 0 && fs.existsSync(path.resolve(root, gitPath))) return true;
1595
+ if (gitPath !== void 0 && await fs.access(path.resolve(root, gitPath)).then(() => true, () => false)) return true;
1594
1596
  }
1595
1597
  return false;
1596
1598
  }
@@ -1823,9 +1825,9 @@ function createGitChangesChannel(options = {}) {
1823
1825
  const rerun = /* @__PURE__ */ new Set();
1824
1826
  const busy = /* @__PURE__ */ new Set();
1825
1827
  /** The base the session's own worktree was created from, when it has one. */
1826
- const recordedBaseRef = (scope) => {
1828
+ const recordedBaseRef = async (scope) => {
1827
1829
  try {
1828
- return createWorktreeRegistry(registryFile(scope.cwd, homeDir)).list().find((record) => record.sessionId === scope.sessionId)?.baseRef;
1830
+ return (await createWorktreeRegistry(await registryFile(scope.cwd, homeDir)).list()).find((record) => record.sessionId === scope.sessionId)?.baseRef;
1829
1831
  } catch {
1830
1832
  return;
1831
1833
  }
@@ -1858,8 +1860,7 @@ function createGitChangesChannel(options = {}) {
1858
1860
  return;
1859
1861
  }
1860
1862
  inFlight.add(sessionId);
1861
- const base = recordedBaseRef(scope);
1862
- diff.review(scope.cwd, base === void 0 ? {} : { recordedBaseRef: base }).then((review) => {
1863
+ recordedBaseRef(scope).then((base) => diff.review(scope.cwd, base === void 0 ? {} : { recordedBaseRef: base })).then((review) => {
1863
1864
  if (scopes.has(sessionId)) update(sessionId, { changes: review?.changes });
1864
1865
  }).catch((error) => {
1865
1866
  host.onNotice(`git diff refresh failed for ${sessionId} (${error instanceof Error ? error.name : "unknown"})`);
@@ -1868,12 +1869,12 @@ function createGitChangesChannel(options = {}) {
1868
1869
  if (rerun.delete(sessionId)) refresh(sessionId);
1869
1870
  });
1870
1871
  };
1871
- const run = (scope, command) => {
1872
+ const run = async (scope, command) => {
1872
1873
  const workspaceRoot = scope.sessionContext?.workspaceRoot ?? scope.cwd;
1873
- const base = recordedBaseRef(scope);
1874
+ const base = await recordedBaseRef(scope);
1874
1875
  const context = {
1875
1876
  cwd: scope.cwd,
1876
- auth: auth.read(workspaceRoot),
1877
+ auth: await auth.read(workspaceRoot),
1877
1878
  ...base === void 0 ? {} : { recordedBaseRef: base }
1878
1879
  };
1879
1880
  if (command.action === "pull") return sync.pull(context);
@@ -1971,9 +1972,9 @@ function payloadOf(state) {
1971
1972
  };
1972
1973
  }
1973
1974
  /** Worktrees visible to this session, using the hub's live session table for ownership. */
1974
- function viewsFor(scope, deps) {
1975
+ async function viewsFor(scope, deps) {
1975
1976
  try {
1976
- return createWorktreeRegistry(registryFile(scope.cwd, deps.homeDir)).list().flatMap((record) => {
1977
+ return (await createWorktreeRegistry(await registryFile(scope.cwd, deps.homeDir)).list()).flatMap((record) => {
1977
1978
  if (record.parentSessionId === void 0 && record.sessionId !== scope.sessionId) return [];
1978
1979
  const owned = record.parentSessionId === void 0 || record.parentSessionId === scope.sessionId;
1979
1980
  const unowned = !owned && !deps.sessionService.isLive(record.parentSessionId);
@@ -2091,10 +2092,13 @@ function createWorktreesChannel(options = {}) {
2091
2092
  return generation;
2092
2093
  };
2093
2094
  /** Republishes a session, skipping a frame that would say nothing new. */
2094
- const publish = (scope, force) => {
2095
+ const publish = async (scope, force) => {
2096
+ const generation = generations.get(scope.sessionId);
2097
+ const worktreeViews = await viewsFor(scope, views);
2098
+ if (generation === void 0 || generations.get(scope.sessionId) !== generation) return;
2095
2099
  const previous = latest.get(scope.sessionId);
2096
2100
  const next = {
2097
- worktrees: viewsFor(scope, views),
2101
+ worktrees: worktreeViews,
2098
2102
  pending: previous?.pending,
2099
2103
  error: previous?.error,
2100
2104
  errorTarget: previous?.errorTarget
@@ -2106,7 +2110,7 @@ function createWorktreesChannel(options = {}) {
2106
2110
  const mark = (scope, pending, error, errorTarget) => {
2107
2111
  const previous = latest.get(scope.sessionId);
2108
2112
  latest.set(scope.sessionId, {
2109
- worktrees: previous?.worktrees ?? viewsFor(scope, views),
2113
+ worktrees: previous?.worktrees ?? [],
2110
2114
  pending,
2111
2115
  error,
2112
2116
  errorTarget
@@ -2146,15 +2150,15 @@ function createWorktreesChannel(options = {}) {
2146
2150
  sessionAdded(scope) {
2147
2151
  newGeneration(scope.sessionId);
2148
2152
  publish(scope, false);
2149
- const unsubscribe = host.directEvents.subscribe(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, (payload) => {
2153
+ const unsubscribe = host.directEvents.subscribe(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, async (payload) => {
2150
2154
  if (!isWorktreeLifecycleEvent(payload)) return;
2151
2155
  let sameRepository = false;
2152
2156
  try {
2153
- sameRepository = registryFile(scope.cwd, options.homeDir) === registryFile(payload.repositoryRoot, options.homeDir);
2157
+ sameRepository = await registryFile(scope.cwd, options.homeDir) === await registryFile(payload.repositoryRoot, options.homeDir);
2154
2158
  } catch {
2155
2159
  sameRepository = false;
2156
2160
  }
2157
- if (sameRepository) publish(scope, false);
2161
+ if (sameRepository) await publish(scope, false);
2158
2162
  });
2159
2163
  subscriptions.set(scope.sessionId, unsubscribe);
2160
2164
  },