gitxelectron 1.2.1 → 1.2.3
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/out/main/index.js +100 -10
- package/out/preload/index.js +4 -0
- package/out/renderer/assets/{index-ChfAIvyi.js → index-C9VJOfEp.js} +113 -106
- package/out/renderer/assets/index-iCHfrYpB.css +193 -0
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/out/renderer/assets/index-BAXzLIAI.css +0 -193
package/out/main/index.js
CHANGED
|
@@ -576,7 +576,14 @@ function initGit(sessionId, baseDir) {
|
|
|
576
576
|
baseDir,
|
|
577
577
|
binary: "git",
|
|
578
578
|
maxConcurrentProcesses: 6,
|
|
579
|
-
unsafe: { allowUnsafeEditor: true, allowUnsafeAskPass: true, allowUnsafeCredentialHelper: true }
|
|
579
|
+
unsafe: { allowUnsafeEditor: true, allowUnsafeAskPass: true, allowUnsafeCredentialHelper: true },
|
|
580
|
+
progress: ({ method, stage, progress }) => {
|
|
581
|
+
try {
|
|
582
|
+
const wc = electron.webContents.fromId(sessionId);
|
|
583
|
+
if (wc) wc.send("git-progress", { method, stage, progress });
|
|
584
|
+
} catch (e) {
|
|
585
|
+
}
|
|
586
|
+
}
|
|
580
587
|
};
|
|
581
588
|
const git = simpleGit.simpleGit(options).env({
|
|
582
589
|
...process.env,
|
|
@@ -586,11 +593,19 @@ function initGit(sessionId, baseDir) {
|
|
|
586
593
|
});
|
|
587
594
|
gitSessions.set(sessionId, { git, repoPath: baseDir });
|
|
588
595
|
}
|
|
589
|
-
function createSafeGit(baseDir) {
|
|
596
|
+
function createSafeGit(baseDir, sessionId) {
|
|
590
597
|
const options = {
|
|
591
598
|
binary: "git",
|
|
592
599
|
maxConcurrentProcesses: 6,
|
|
593
|
-
unsafe: { allowUnsafeEditor: true, allowUnsafeAskPass: true, allowUnsafeCredentialHelper: true }
|
|
600
|
+
unsafe: { allowUnsafeEditor: true, allowUnsafeAskPass: true, allowUnsafeCredentialHelper: true },
|
|
601
|
+
progress: ({ method, stage, progress }) => {
|
|
602
|
+
if (!sessionId) return;
|
|
603
|
+
try {
|
|
604
|
+
const wc = electron.webContents.fromId(sessionId);
|
|
605
|
+
if (wc) wc.send("git-progress", { method, stage, progress });
|
|
606
|
+
} catch (e) {
|
|
607
|
+
}
|
|
608
|
+
}
|
|
594
609
|
};
|
|
595
610
|
if (baseDir) {
|
|
596
611
|
options.baseDir = baseDir;
|
|
@@ -728,6 +743,19 @@ async function unstageFiles(sessionId, files) {
|
|
|
728
743
|
}
|
|
729
744
|
async function commitChanges(sessionId, message) {
|
|
730
745
|
const { git } = getGitSession(sessionId);
|
|
746
|
+
try {
|
|
747
|
+
const nameConfig = await git.getConfig("user.name");
|
|
748
|
+
const emailConfig = await git.getConfig("user.email");
|
|
749
|
+
if (!nameConfig.value || !emailConfig.value) {
|
|
750
|
+
const account = getActiveAccount(sessionId);
|
|
751
|
+
const name = account?.username || "GitQuickPush User";
|
|
752
|
+
const email = account ? `${account.username}@users.noreply.github.com` : "noreply@gitquickpush.local";
|
|
753
|
+
if (!nameConfig.value) await git.addConfig("user.name", name);
|
|
754
|
+
if (!emailConfig.value) await git.addConfig("user.email", email);
|
|
755
|
+
}
|
|
756
|
+
} catch (e) {
|
|
757
|
+
console.warn("Failed to check or set git author identity", e);
|
|
758
|
+
}
|
|
731
759
|
return await git.commit(message);
|
|
732
760
|
}
|
|
733
761
|
function injectAuthToken(sessionId, remoteUrl) {
|
|
@@ -1156,7 +1184,7 @@ async function cloneRepository(sessionId, remoteUrl, destPath) {
|
|
|
1156
1184
|
}
|
|
1157
1185
|
try {
|
|
1158
1186
|
if (destExists && destHasGit) {
|
|
1159
|
-
const existingGit = createSafeGit(destPath);
|
|
1187
|
+
const existingGit = createSafeGit(destPath, sessionId);
|
|
1160
1188
|
try {
|
|
1161
1189
|
await existingGit.raw(["config", "--global", "--add", "safe.directory", destPath]);
|
|
1162
1190
|
const remotes = await existingGit.getRemotes();
|
|
@@ -1178,10 +1206,10 @@ async function cloneRepository(sessionId, remoteUrl, destPath) {
|
|
|
1178
1206
|
}
|
|
1179
1207
|
}
|
|
1180
1208
|
if (destExists && destIsEmpty) {
|
|
1181
|
-
const emptyDirGit = createSafeGit(destPath);
|
|
1209
|
+
const emptyDirGit = createSafeGit(destPath, sessionId);
|
|
1182
1210
|
await emptyDirGit.raw(["-c", "credential.helper=", "clone", authUrl, "."]);
|
|
1183
1211
|
try {
|
|
1184
|
-
await createSafeGit().raw(["config", "--global", "--add", "safe.directory", destPath]);
|
|
1212
|
+
await createSafeGit(void 0, sessionId).raw(["config", "--global", "--add", "safe.directory", destPath]);
|
|
1185
1213
|
} catch (e) {
|
|
1186
1214
|
}
|
|
1187
1215
|
return destPath;
|
|
@@ -1193,10 +1221,10 @@ async function cloneRepository(sessionId, remoteUrl, destPath) {
|
|
|
1193
1221
|
}
|
|
1194
1222
|
const baseDir = path__namespace.dirname(destPath);
|
|
1195
1223
|
const targetDirName = path__namespace.basename(destPath);
|
|
1196
|
-
const parentGit = createSafeGit(baseDir);
|
|
1224
|
+
const parentGit = createSafeGit(baseDir, sessionId);
|
|
1197
1225
|
await parentGit.raw(["-c", "credential.helper=", "clone", authUrl, targetDirName]);
|
|
1198
1226
|
try {
|
|
1199
|
-
await createSafeGit().raw(["config", "--global", "--add", "safe.directory", destPath]);
|
|
1227
|
+
await createSafeGit(void 0, sessionId).raw(["config", "--global", "--add", "safe.directory", destPath]);
|
|
1200
1228
|
} catch (e) {
|
|
1201
1229
|
}
|
|
1202
1230
|
return destPath;
|
|
@@ -1320,6 +1348,55 @@ ${errorMsg}
|
|
|
1320
1348
|
`AI Analysis failed after trying all provided keys. Last error: ${lastError?.message}`
|
|
1321
1349
|
);
|
|
1322
1350
|
}
|
|
1351
|
+
async function generateCommitMessage(provider, apiKeyInput, diffStr, githubToken) {
|
|
1352
|
+
const systemPrompt = `You are an expert developer. Generate a concise, clear Git commit message based on the provided git diff.
|
|
1353
|
+
Format your response exactly like a standard Git commit message:
|
|
1354
|
+
<type>: <short summary>
|
|
1355
|
+
|
|
1356
|
+
<detailed description>
|
|
1357
|
+
|
|
1358
|
+
Do not wrap it in JSON or code blocks. Return just the plain text of the commit message.
|
|
1359
|
+
If the diff is empty or invalid, return "Auto-sync: update files".`;
|
|
1360
|
+
const truncatedDiff = diffStr.length > 1e4 ? diffStr.substring(0, 1e4) + "\n...[diff truncated]" : diffStr;
|
|
1361
|
+
const prompt = `GIT DIFF:
|
|
1362
|
+
${truncatedDiff}`;
|
|
1363
|
+
let keys = "".split(",").map((k) => k.trim()).filter((k) => k);
|
|
1364
|
+
if (!keys.length && provider === "gemini") {
|
|
1365
|
+
keys = ["AQ.Ab8RN6LFu9vxQBWCSzE72V4CG2ILxnreqAP4AZQzSmXZ_1vphw"];
|
|
1366
|
+
}
|
|
1367
|
+
if (githubToken) {
|
|
1368
|
+
try {
|
|
1369
|
+
const openai = new OpenAI({
|
|
1370
|
+
apiKey: githubToken,
|
|
1371
|
+
baseURL: "https://models.inference.ai.azure.com"
|
|
1372
|
+
});
|
|
1373
|
+
const response = await openai.chat.completions.create({
|
|
1374
|
+
model: "gpt-4o-mini",
|
|
1375
|
+
messages: [
|
|
1376
|
+
{ role: "system", content: systemPrompt },
|
|
1377
|
+
{ role: "user", content: prompt }
|
|
1378
|
+
]
|
|
1379
|
+
});
|
|
1380
|
+
const content = response.choices[0].message.content?.trim();
|
|
1381
|
+
if (content) return content;
|
|
1382
|
+
} catch (e) {
|
|
1383
|
+
console.warn(`[AI Service] GitHub Copilot fallback for commit gen failed: ${e.message}`);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
for (const apiKey of keys) {
|
|
1387
|
+
try {
|
|
1388
|
+
if (provider === "gemini") {
|
|
1389
|
+
const genAI = new generativeAi.GoogleGenerativeAI(apiKey);
|
|
1390
|
+
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
|
|
1391
|
+
const result = await model.generateContent([{ text: systemPrompt }, { text: prompt }]);
|
|
1392
|
+
return result.response.text().trim();
|
|
1393
|
+
}
|
|
1394
|
+
} catch (e) {
|
|
1395
|
+
console.warn(`[AI Service] Provider ${provider} commit gen failed: ${e.message}`);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
return "Auto-sync: update files";
|
|
1399
|
+
}
|
|
1323
1400
|
const getConfigPath = () => path__namespace.join(electron.app.getPath("userData"), "gitx-config.json");
|
|
1324
1401
|
const saveLastWorkspace = async (workspacePath) => {
|
|
1325
1402
|
try {
|
|
@@ -1406,8 +1483,21 @@ async function triggerSyncSequence(sessionId, _repoPath, onLog) {
|
|
|
1406
1483
|
await stageFiles(sessionId, existingFiles);
|
|
1407
1484
|
const status = await getStatus(sessionId);
|
|
1408
1485
|
const branch = status.current || "main";
|
|
1409
|
-
|
|
1410
|
-
|
|
1486
|
+
onLog("Generating AI commit message...");
|
|
1487
|
+
let commitMsg = `Auto-sync: update ${filesToSync.length > 1 ? filesToSync.length + " files" : filesToSync[0]}`;
|
|
1488
|
+
try {
|
|
1489
|
+
const diffStr = await getFileDiff(sessionId, "", true);
|
|
1490
|
+
if (diffStr && diffStr.trim() !== "") {
|
|
1491
|
+
const githubToken = getToken(sessionId) || void 0;
|
|
1492
|
+
const aiMsg = await generateCommitMessage("gemini", "", diffStr, githubToken);
|
|
1493
|
+
if (aiMsg) {
|
|
1494
|
+
commitMsg = aiMsg;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
} catch (aiErr) {
|
|
1498
|
+
console.warn("AI commit generation failed, falling back to default", aiErr);
|
|
1499
|
+
}
|
|
1500
|
+
onLog(`Committing: "${commitMsg.split("\n")[0]}"...`);
|
|
1411
1501
|
await commitChanges(sessionId, commitMsg);
|
|
1412
1502
|
onLog(`Pushing to ${branch}...`);
|
|
1413
1503
|
await pushToRemote(sessionId, "origin", branch);
|
package/out/preload/index.js
CHANGED
|
@@ -6,6 +6,10 @@ const api = {
|
|
|
6
6
|
onSetCliRepo: (callback) => {
|
|
7
7
|
electron.ipcRenderer.on("set-cli-repo", (_event, repoPath) => callback(repoPath));
|
|
8
8
|
},
|
|
9
|
+
onGitProgress: (callback) => {
|
|
10
|
+
electron.ipcRenderer.removeAllListeners("git-progress");
|
|
11
|
+
electron.ipcRenderer.on("git-progress", (_event, data) => callback(data));
|
|
12
|
+
},
|
|
9
13
|
selectDirectory: () => electron.ipcRenderer.invoke("select-directory"),
|
|
10
14
|
setRepoPath: (path) => electron.ipcRenderer.invoke("set-repo-path", path),
|
|
11
15
|
initRepo: (path) => electron.ipcRenderer.invoke("init-repo", path),
|