gitxelectron 1.3.8 → 1.3.9

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.
@@ -26703,6 +26703,55 @@ Are you SURE you want to link "${repoName}" to this folder?`
26703
26703
  setIsPulling(false);
26704
26704
  }
26705
26705
  };
26706
+ const formatErrorMessage = (msg) => {
26707
+ if (!msg) return "";
26708
+ return msg.replace(/^Error invoking remote method '[^']+':\s*/i, "").replace(/^Error:\s*/i, "").replace(/^error:\s*/i, "").trim();
26709
+ };
26710
+ const handleResolveConflictOurs = async () => {
26711
+ try {
26712
+ showToast("Resolving conflicts: keeping local changes...", "info");
26713
+ await window.api.executeRawGit(["checkout", "--ours", "."]);
26714
+ await window.api.executeRawGit(["add", "."]);
26715
+ await window.api.executeRawGit(["commit", "-m", "Resolved conflicts (kept local changes)"]);
26716
+ setPushFailureData(null);
26717
+ await refreshRepoState();
26718
+ showToast("✅ Conflicts resolved (kept local changes)", "success");
26719
+ } catch (err) {
26720
+ showToast(`Failed to resolve conflicts: ${err.message}`, "error");
26721
+ }
26722
+ };
26723
+ const handleResolveConflictTheirs = async () => {
26724
+ try {
26725
+ showToast("Resolving conflicts: accepting remote changes...", "info");
26726
+ await window.api.executeRawGit(["checkout", "--theirs", "."]);
26727
+ await window.api.executeRawGit(["add", "."]);
26728
+ await window.api.executeRawGit(["commit", "-m", "Resolved conflicts (accepted remote changes)"]);
26729
+ setPushFailureData(null);
26730
+ await refreshRepoState();
26731
+ showToast("✅ Conflicts resolved (accepted remote changes)", "success");
26732
+ } catch (err) {
26733
+ showToast(`Failed to resolve conflicts: ${err.message}`, "error");
26734
+ }
26735
+ };
26736
+ const handleAbortMerge = async () => {
26737
+ try {
26738
+ showToast("Aborting merge...", "info");
26739
+ try {
26740
+ await window.api.executeRawGit(["merge", "--abort"]);
26741
+ } catch {
26742
+ try {
26743
+ await window.api.executeRawGit(["rebase", "--abort"]);
26744
+ } catch {
26745
+ await window.api.executeRawGit(["reset", "--merge"]);
26746
+ }
26747
+ }
26748
+ setPushFailureData(null);
26749
+ await refreshRepoState();
26750
+ showToast("✅ Merge aborted. Repository restored to clean state.", "success");
26751
+ } catch (err) {
26752
+ showToast(`Failed to abort merge: ${err.message}`, "error");
26753
+ }
26754
+ };
26706
26755
  const handleSyncCollabRepo = async (repo, savedPath) => {
26707
26756
  try {
26708
26757
  showToast(`Syncing ${repo.name} with GitHub...`, "info");
@@ -26768,6 +26817,29 @@ Are you SURE you want to link "${repoName}" to this folder?`
26768
26817
  }, 1500);
26769
26818
  break;
26770
26819
  }
26820
+ const isConflictErr = currentError.includes("unmerged files") || currentError.includes("unresolved conflict") || currentError.includes("automatic merge failed") || currentError.includes("you have unmerged paths");
26821
+ if (isConflictErr) {
26822
+ setHealerMessage("Unmerged conflict detected. Automatically resolving conflicted files...");
26823
+ try {
26824
+ await window.api.executeRawGit(["checkout", "--ours", "."]);
26825
+ await window.api.executeRawGit(["add", "."]);
26826
+ await window.api.executeRawGit(["commit", "-m", "Auto-resolved conflicts: kept local changes"]);
26827
+ } catch {
26828
+ try {
26829
+ await window.api.executeRawGit(["merge", "--abort"]);
26830
+ } catch {
26831
+ }
26832
+ }
26833
+ await refreshRepoState();
26834
+ showToast("Merge conflicts resolved successfully!", "success");
26835
+ setTimeout(() => {
26836
+ setShowHealerOverlay(false);
26837
+ if (overrideRepoPath && repoPath) {
26838
+ window.api.setRepoPath(repoPath);
26839
+ }
26840
+ }, 1500);
26841
+ return true;
26842
+ }
26771
26843
  const currentStatus = await window.api.getStatus();
26772
26844
  const result = await window.api.askAi(
26773
26845
  "gemini",
@@ -26801,14 +26873,18 @@ Are you SURE you want to link "${repoName}" to this folder?`
26801
26873
  setShowHealerOverlay(false);
26802
26874
  await refreshRepoState();
26803
26875
  } else {
26804
- await window.api.pullFromRemote(remotes[0].name, overrideBranch || branches.current);
26876
+ const wasConflict = currentError.includes("unmerged files") || currentError.includes("unresolved conflict") || currentError.includes("automatic merge failed") || currentError.includes("you have unmerged paths");
26877
+ if (!wasConflict) {
26878
+ await window.api.pullFromRemote(remotes[0].name, overrideBranch || branches.current);
26879
+ }
26805
26880
  }
26806
- setHealerMessage(`Successfully auto-healed and ${operation}ed!`);
26881
+ setHealerMessage(`Successfully auto-healed and reconciled!`);
26807
26882
  setTimeout(() => {
26808
26883
  setShowHealerOverlay(false);
26809
26884
  if (overrideRepoPath && repoPath) {
26810
26885
  window.api.setRepoPath(repoPath);
26811
26886
  }
26887
+ refreshRepoState();
26812
26888
  }, 2e3);
26813
26889
  return;
26814
26890
  } else {
@@ -28176,60 +28252,199 @@ Are you SURE you want to link "${repoName}" to this folder?`
28176
28252
  }
28177
28253
  )
28178
28254
  ] }) }),
28179
- pushFailureData && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-surface/95 backdrop-blur-xl p-8 rounded-xl shadow-2xl border border-danger/50 w-full max-w-[500px] mx-4 animate-float", children: [
28180
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mb-4 text-danger", children: [
28181
- /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
28182
- "path",
28183
- {
28184
- strokeLinecap: "round",
28185
- strokeLinejoin: "round",
28186
- strokeWidth: 2,
28187
- d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
28188
- }
28189
- ) }),
28190
- /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold", children: "Push Rejected" })
28191
- ] }),
28192
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-5 bg-canvas border border-border p-4 rounded-md", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-primary text-sm", children: pushFailureData.reason }) }),
28193
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-secondary mb-6 text-sm", children: "Recommendation: You can pull the latest changes from the remote to reconcile your local branch, or you can use the AI Auto-Healer to analyze and fix the issue automatically." }),
28194
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-3", children: [
28195
- /* @__PURE__ */ jsxRuntimeExports.jsx(
28196
- "button",
28197
- {
28198
- onClick: () => {
28199
- const data = pushFailureData;
28200
- setPushFailureData(null);
28201
- autonomousHealAndPush(
28202
- data.reason,
28203
- data.operation || "push",
28204
- data.overrideRepoPath,
28205
- data.overrideBranch
28206
- );
28207
- },
28208
- className: "flex-1 py-2 bg-brand hover:bg-brand-hover border border-white/10 text-white rounded-md font-semibold transition-all text-sm flex items-center justify-center gap-2",
28209
- children: "✨ Fix with AI"
28210
- }
28211
- ),
28212
- /* @__PURE__ */ jsxRuntimeExports.jsx(
28213
- "button",
28214
- {
28215
- onClick: () => {
28216
- setPushFailureData(null);
28217
- handlePull();
28218
- },
28219
- className: "flex-1 py-2 bg-surface hover:bg-surface-hover border border-border text-primary rounded-md font-semibold transition-all text-sm",
28220
- children: "Pull Changes"
28221
- }
28222
- ),
28223
- /* @__PURE__ */ jsxRuntimeExports.jsx(
28224
- "button",
28225
- {
28226
- onClick: () => setPushFailureData(null),
28227
- className: "flex-1 py-2 bg-surface hover:bg-surface-hover border border-border text-primary rounded-md font-semibold transition-colors text-sm",
28228
- children: "Cancel"
28229
- }
28230
- )
28231
- ] })
28232
- ] }) }),
28255
+ pushFailureData && (() => {
28256
+ const isConflict = Boolean(
28257
+ pushFailureData.reason && (pushFailureData.reason.includes("unmerged files") || pushFailureData.reason.includes("unresolved conflict") || pushFailureData.reason.includes("merge conflict") || pushFailureData.reason.includes("Automatic merge failed") || pushFailureData.reason.includes("you have unmerged paths") || pushFailureData.reason.includes("CONFLICT ("))
28258
+ );
28259
+ const isPull = pushFailureData.operation === "pull" || pushFailureData.reason?.includes("pull-from-remote");
28260
+ const cleanedReason = formatErrorMessage(pushFailureData.reason);
28261
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `bg-surface/95 backdrop-blur-xl p-6 sm:p-8 rounded-xl shadow-2xl border ${isConflict ? "border-amber-500/50" : "border-danger/50"} w-full max-w-[520px] animate-float`, children: [
28262
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex items-center gap-3 mb-4 ${isConflict ? "text-amber-500" : "text-danger"}`, children: [
28263
+ isConflict ? /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className: "w-6 h-6 flex-shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
28264
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "18", cy: "18", r: "3" }),
28265
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "6", cy: "6", r: "3" }),
28266
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6 9v12" }),
28267
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M18 9a9 9 0 0 0-9 9" })
28268
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-6 h-6 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
28269
+ "path",
28270
+ {
28271
+ strokeLinecap: "round",
28272
+ strokeLinejoin: "round",
28273
+ strokeWidth: 2,
28274
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
28275
+ }
28276
+ ) }),
28277
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
28278
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold tracking-tight", children: isConflict ? "Merge Conflict Detected" : isPull ? "Pull Failed" : "Push Rejected" }),
28279
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-secondary mt-0.5", children: isConflict ? "Unmerged files prevent Git from syncing automatically." : isPull ? "Unable to pull incoming commits from the remote repository." : "Remote repository rejected your push request." })
28280
+ ] })
28281
+ ] }),
28282
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4 bg-canvas/80 border border-border p-3.5 rounded-lg max-h-36 overflow-y-auto custom-scrollbar", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-primary font-mono text-xs leading-relaxed whitespace-pre-wrap select-text", children: cleanedReason }) }),
28283
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-secondary mb-5 text-sm leading-relaxed", children: isConflict ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
28284
+ "Choose a resolution below: let ",
28285
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-primary font-semibold", children: "AI Auto-Healer" }),
28286
+ " intelligently reconcile conflicts, keep your local changes, accept remote incoming changes, or abort the merge to revert to the previous state."
28287
+ ] }) : isPull ? /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: "Failed to pull latest changes from the remote repository. Check your connection or use the AI Auto-Healer to analyze and fix the issue." }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: "Recommendation: You can pull the latest changes from the remote to reconcile your local branch, or you can use the AI Auto-Healer to analyze and fix the issue automatically." }) }),
28288
+ isConflict ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2.5", children: [
28289
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28290
+ "button",
28291
+ {
28292
+ onClick: () => {
28293
+ const data = pushFailureData;
28294
+ setPushFailureData(null);
28295
+ autonomousHealAndPush(
28296
+ data.reason,
28297
+ data.operation || "pull",
28298
+ data.overrideRepoPath,
28299
+ data.overrideBranch
28300
+ );
28301
+ },
28302
+ className: "w-full py-2.5 bg-brand hover:bg-brand-hover border border-white/10 text-white rounded-md font-semibold transition-all text-sm flex items-center justify-center gap-2 shadow-lg shadow-brand/20 active:scale-[0.99]",
28303
+ children: "✨ Auto-Resolve with AI"
28304
+ }
28305
+ ),
28306
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
28307
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28308
+ "button",
28309
+ {
28310
+ onClick: handleResolveConflictOurs,
28311
+ className: "py-2 px-2 bg-surface hover:bg-surface-hover border border-border text-primary rounded-md font-semibold transition-all text-xs text-center hover:border-brand/40",
28312
+ title: "Keep local changes and discard remote changes",
28313
+ children: "Keep Local (Ours)"
28314
+ }
28315
+ ),
28316
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28317
+ "button",
28318
+ {
28319
+ onClick: handleResolveConflictTheirs,
28320
+ className: "py-2 px-2 bg-surface hover:bg-surface-hover border border-border text-primary rounded-md font-semibold transition-all text-xs text-center hover:border-brand/40",
28321
+ title: "Accept remote incoming changes and discard local changes",
28322
+ children: "Accept Remote (Theirs)"
28323
+ }
28324
+ ),
28325
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28326
+ "button",
28327
+ {
28328
+ onClick: handleAbortMerge,
28329
+ className: "py-2 px-2 bg-danger/10 hover:bg-danger/20 border border-danger/30 text-danger rounded-md font-semibold transition-all text-xs text-center",
28330
+ title: "Abort the merge and revert repository to previous state",
28331
+ children: "Abort Merge"
28332
+ }
28333
+ )
28334
+ ] }),
28335
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28336
+ "button",
28337
+ {
28338
+ onClick: () => {
28339
+ setPushFailureData(null);
28340
+ setChangesTab("changes");
28341
+ },
28342
+ className: "w-full py-2 bg-surface hover:bg-surface-hover border border-border text-secondary hover:text-primary rounded-md font-medium transition-colors text-xs text-center",
28343
+ children: "Review Conflicted Files Manually in Changes Tab"
28344
+ }
28345
+ ),
28346
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28347
+ "button",
28348
+ {
28349
+ onClick: async () => {
28350
+ const data = pushFailureData;
28351
+ setPushFailureData(null);
28352
+ try {
28353
+ const remotes = await window.api.getRemotes();
28354
+ const targetRemote = data?.overrideRepoPath || remotes[0]?.name || "origin";
28355
+ const targetBranch = data?.overrideBranch || "main";
28356
+ await window.api.masterPush(targetRemote, targetBranch);
28357
+ setPushSuccessData({
28358
+ files: "All",
28359
+ branch: targetBranch,
28360
+ repository: targetRemote
28361
+ });
28362
+ } catch (err) {
28363
+ setPushFailureData({
28364
+ reason: err.message || "Master Force Push Failed",
28365
+ operation: "push",
28366
+ overrideRepoPath: data?.overrideRepoPath,
28367
+ overrideBranch: data?.overrideBranch
28368
+ });
28369
+ }
28370
+ },
28371
+ className: "w-full mt-2 py-2.5 bg-danger/20 hover:bg-danger/30 border border-danger/50 text-danger rounded-md font-bold transition-all text-sm flex items-center justify-center gap-2 shadow-lg shadow-danger/10 active:scale-[0.99]",
28372
+ title: "Force push everything (including ignored files) bypassing all rules",
28373
+ children: "⚡ Master Force Push (Override All)"
28374
+ }
28375
+ )
28376
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3", children: [
28377
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-3", children: [
28378
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28379
+ "button",
28380
+ {
28381
+ onClick: () => {
28382
+ const data = pushFailureData;
28383
+ setPushFailureData(null);
28384
+ autonomousHealAndPush(
28385
+ data.reason,
28386
+ data.operation || (isPull ? "pull" : "push"),
28387
+ data.overrideRepoPath,
28388
+ data.overrideBranch
28389
+ );
28390
+ },
28391
+ className: "flex-1 py-2 bg-brand hover:bg-brand-hover border border-white/10 text-white rounded-md font-semibold transition-all text-sm flex items-center justify-center gap-2 active:scale-[0.99]",
28392
+ children: "✨ Fix with AI"
28393
+ }
28394
+ ),
28395
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28396
+ "button",
28397
+ {
28398
+ onClick: () => {
28399
+ setPushFailureData(null);
28400
+ handlePull();
28401
+ },
28402
+ className: "flex-1 py-2 bg-surface hover:bg-surface-hover border border-border text-primary rounded-md font-semibold transition-all text-sm active:scale-[0.99]",
28403
+ children: isPull ? "Retry Pull" : "Pull Changes"
28404
+ }
28405
+ ),
28406
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28407
+ "button",
28408
+ {
28409
+ onClick: () => setPushFailureData(null),
28410
+ className: "flex-1 py-2 bg-surface hover:bg-surface-hover border border-border text-primary rounded-md font-semibold transition-colors text-sm active:scale-[0.99]",
28411
+ children: "Cancel"
28412
+ }
28413
+ )
28414
+ ] }),
28415
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
28416
+ "button",
28417
+ {
28418
+ onClick: async () => {
28419
+ const data = pushFailureData;
28420
+ setPushFailureData(null);
28421
+ try {
28422
+ const remotes = await window.api.getRemotes();
28423
+ const targetRemote = data?.overrideRepoPath || remotes[0]?.name || "origin";
28424
+ const targetBranch = data?.overrideBranch || "main";
28425
+ await window.api.masterPush(targetRemote, targetBranch);
28426
+ setPushSuccessData({
28427
+ files: "All",
28428
+ branch: targetBranch,
28429
+ repository: targetRemote
28430
+ });
28431
+ } catch (err) {
28432
+ setPushFailureData({
28433
+ reason: err.message || "Master Force Push Failed",
28434
+ operation: "push",
28435
+ overrideRepoPath: data?.overrideRepoPath,
28436
+ overrideBranch: data?.overrideBranch
28437
+ });
28438
+ }
28439
+ },
28440
+ className: "w-full py-2 bg-danger/20 hover:bg-danger/30 border border-danger/50 text-danger rounded-md font-bold transition-all text-sm flex items-center justify-center gap-2 active:scale-[0.99]",
28441
+ title: "Force push everything (including ignored files) bypassing all rules",
28442
+ children: "⚡ Master Force Push (Override All)"
28443
+ }
28444
+ )
28445
+ ] })
28446
+ ] }) });
28447
+ })(),
28233
28448
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-64 lg:w-72 flex-shrink-0 bg-surface/80 backdrop-blur-md p-5 border-r border-border flex flex-col relative z-10 shadow-lg transition-colors duration-300", children: [
28234
28449
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mb-6 p-1", children: [
28235
28450
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -21,8 +21,8 @@
21
21
  href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
22
22
  rel="stylesheet"
23
23
  />
24
- <script type="module" crossorigin src="./assets/index-FVTFdxtU.js"></script>
25
- <link rel="stylesheet" crossorigin href="./assets/index-D_wJ7hR7.css">
24
+ <script type="module" crossorigin src="./assets/index-Dtxyy2BB.js"></script>
25
+ <link rel="stylesheet" crossorigin href="./assets/index-Bhk4vMRr.css">
26
26
  </head>
27
27
 
28
28
  <body class="bg-gray-900 text-white font-sans antialiased overflow-hidden">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitxelectron",
3
- "version": "1.3.8",
3
+ "version": "1.3.9",
4
4
  "description": "An elegant, completely silent auto-syncing Git client. Works as a desktop app and npm CLI tool.",
5
5
  "main": "./out/main/index.js",
6
6
  "files": [