stashes 0.1.29 → 0.1.30
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/dist/cli.js +27 -22
- package/dist/mcp.js +27 -22
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -247,6 +247,10 @@ class WorktreeManager {
|
|
|
247
247
|
const { readdirSync } = await import("fs");
|
|
248
248
|
const entries = readdirSync(worktreesDir);
|
|
249
249
|
for (const entry of entries) {
|
|
250
|
+
if (entry.startsWith("screenshot-")) {
|
|
251
|
+
logger.info("worktree", `skipping active screenshot worktree: ${entry}`);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
250
254
|
const worktreePath = join3(worktreesDir, entry);
|
|
251
255
|
logger.info("worktree", `cleaning up stale worktree: ${entry}`);
|
|
252
256
|
try {
|
|
@@ -896,6 +900,20 @@ function parseAiResult(text) {
|
|
|
896
900
|
return null;
|
|
897
901
|
}
|
|
898
902
|
}
|
|
903
|
+
async function fallbackScreenshot(port, projectPath, stashId) {
|
|
904
|
+
try {
|
|
905
|
+
const url = await captureScreenshot(port, projectPath, stashId);
|
|
906
|
+
return {
|
|
907
|
+
primary: url,
|
|
908
|
+
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
909
|
+
};
|
|
910
|
+
} catch (err) {
|
|
911
|
+
logger.error("smart-screenshot", `Fallback screenshot also failed for ${stashId}`, {
|
|
912
|
+
error: err instanceof Error ? err.message : String(err)
|
|
913
|
+
});
|
|
914
|
+
return { primary: "", screenshots: [] };
|
|
915
|
+
}
|
|
916
|
+
}
|
|
899
917
|
async function captureSmartScreenshots(opts) {
|
|
900
918
|
const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "haiku", timeout = DEFAULT_TIMEOUT } = opts;
|
|
901
919
|
const screenshotDir = join6(projectPath, SCREENSHOTS_DIR2);
|
|
@@ -905,11 +923,7 @@ async function captureSmartScreenshots(opts) {
|
|
|
905
923
|
const diff = await getStashDiff(worktreePath, parentBranch);
|
|
906
924
|
if (!diff) {
|
|
907
925
|
logger.info("smart-screenshot", `No diff found for ${stashId}, using simple screenshot`);
|
|
908
|
-
|
|
909
|
-
return {
|
|
910
|
-
primary: url,
|
|
911
|
-
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
912
|
-
};
|
|
926
|
+
return fallbackScreenshot(port, projectPath, stashId);
|
|
913
927
|
}
|
|
914
928
|
const processId = `screenshot-ai-${stashId}`;
|
|
915
929
|
const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId);
|
|
@@ -939,12 +953,8 @@ async function captureSmartScreenshots(opts) {
|
|
|
939
953
|
}
|
|
940
954
|
const result = parseAiResult(textOutput);
|
|
941
955
|
if (!result || !result.screenshots || result.screenshots.length === 0) {
|
|
942
|
-
logger.info("smart-screenshot", `AI returned no screenshots for ${stashId}, falling back`);
|
|
943
|
-
|
|
944
|
-
return {
|
|
945
|
-
primary: url,
|
|
946
|
-
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
947
|
-
};
|
|
956
|
+
logger.info("smart-screenshot", `AI returned no screenshots for ${stashId} (timedOut=${timedOut}), falling back`);
|
|
957
|
+
return fallbackScreenshot(port, projectPath, stashId);
|
|
948
958
|
}
|
|
949
959
|
const screenshots = [];
|
|
950
960
|
let primaryUrl = "";
|
|
@@ -967,11 +977,7 @@ async function captureSmartScreenshots(opts) {
|
|
|
967
977
|
}
|
|
968
978
|
if (screenshots.length === 0) {
|
|
969
979
|
logger.info("smart-screenshot", `No valid screenshots for ${stashId}, falling back`);
|
|
970
|
-
|
|
971
|
-
return {
|
|
972
|
-
primary: url,
|
|
973
|
-
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
974
|
-
};
|
|
980
|
+
return fallbackScreenshot(port, projectPath, stashId);
|
|
975
981
|
}
|
|
976
982
|
if (!primaryUrl) {
|
|
977
983
|
primaryUrl = screenshots[0].url;
|
|
@@ -1120,7 +1126,7 @@ async function generate(opts) {
|
|
|
1120
1126
|
const port = await allocatePort();
|
|
1121
1127
|
const worktree = await worktreeManager.createForGeneration(`screenshot-${stash.id}`);
|
|
1122
1128
|
const screenshotGit = simpleGit3(worktree.path);
|
|
1123
|
-
await screenshotGit.checkout(["
|
|
1129
|
+
await screenshotGit.checkout(["--detach", stash.branch]);
|
|
1124
1130
|
const devServer = spawn3({
|
|
1125
1131
|
cmd: ["npm", "run", "dev"],
|
|
1126
1132
|
cwd: worktree.path,
|
|
@@ -1255,7 +1261,7 @@ async function vary(opts) {
|
|
|
1255
1261
|
const port = await allocatePort2();
|
|
1256
1262
|
const screenshotWorktree = await worktreeManager.createForGeneration(`screenshot-${stashId}`);
|
|
1257
1263
|
const screenshotGit = simpleGit4(screenshotWorktree.path);
|
|
1258
|
-
await screenshotGit.checkout(["
|
|
1264
|
+
await screenshotGit.checkout(["--detach", stash.branch]);
|
|
1259
1265
|
const devServer = spawn4({
|
|
1260
1266
|
cmd: ["npm", "run", "dev"],
|
|
1261
1267
|
cwd: screenshotWorktree.path,
|
|
@@ -1786,9 +1792,8 @@ ${sourceCode.substring(0, 3000)}
|
|
|
1786
1792
|
syncStashesFromDisk(projectId, chatId) {
|
|
1787
1793
|
const diskStashes = this.persistence.listStashes(projectId);
|
|
1788
1794
|
for (const stash of diskStashes) {
|
|
1789
|
-
if (chatId && !stash.originChatId
|
|
1790
|
-
|
|
1791
|
-
this.persistence.saveStash(updated);
|
|
1795
|
+
if (chatId && !stash.originChatId) {
|
|
1796
|
+
this.persistence.saveStash({ ...stash, originChatId: chatId });
|
|
1792
1797
|
}
|
|
1793
1798
|
this.broadcast({
|
|
1794
1799
|
type: "stash:status",
|
|
@@ -1819,7 +1824,7 @@ ${sourceCode.substring(0, 3000)}
|
|
|
1819
1824
|
for (const stash of stashes) {
|
|
1820
1825
|
const prev = lastStatus.get(stash.id);
|
|
1821
1826
|
if (!prev || prev !== stash.status) {
|
|
1822
|
-
if (chatId && !stash.originChatId
|
|
1827
|
+
if (chatId && !stash.originChatId) {
|
|
1823
1828
|
this.persistence.saveStash({ ...stash, originChatId: chatId });
|
|
1824
1829
|
}
|
|
1825
1830
|
this.broadcast({
|
package/dist/mcp.js
CHANGED
|
@@ -129,6 +129,10 @@ class WorktreeManager {
|
|
|
129
129
|
const { readdirSync } = await import("fs");
|
|
130
130
|
const entries = readdirSync(worktreesDir);
|
|
131
131
|
for (const entry of entries) {
|
|
132
|
+
if (entry.startsWith("screenshot-")) {
|
|
133
|
+
logger.info("worktree", `skipping active screenshot worktree: ${entry}`);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
132
136
|
const worktreePath = join2(worktreesDir, entry);
|
|
133
137
|
logger.info("worktree", `cleaning up stale worktree: ${entry}`);
|
|
134
138
|
try {
|
|
@@ -778,6 +782,20 @@ function parseAiResult(text) {
|
|
|
778
782
|
return null;
|
|
779
783
|
}
|
|
780
784
|
}
|
|
785
|
+
async function fallbackScreenshot(port, projectPath, stashId) {
|
|
786
|
+
try {
|
|
787
|
+
const url = await captureScreenshot(port, projectPath, stashId);
|
|
788
|
+
return {
|
|
789
|
+
primary: url,
|
|
790
|
+
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
791
|
+
};
|
|
792
|
+
} catch (err) {
|
|
793
|
+
logger.error("smart-screenshot", `Fallback screenshot also failed for ${stashId}`, {
|
|
794
|
+
error: err instanceof Error ? err.message : String(err)
|
|
795
|
+
});
|
|
796
|
+
return { primary: "", screenshots: [] };
|
|
797
|
+
}
|
|
798
|
+
}
|
|
781
799
|
async function captureSmartScreenshots(opts) {
|
|
782
800
|
const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "haiku", timeout = DEFAULT_TIMEOUT } = opts;
|
|
783
801
|
const screenshotDir = join5(projectPath, SCREENSHOTS_DIR2);
|
|
@@ -787,11 +805,7 @@ async function captureSmartScreenshots(opts) {
|
|
|
787
805
|
const diff = await getStashDiff(worktreePath, parentBranch);
|
|
788
806
|
if (!diff) {
|
|
789
807
|
logger.info("smart-screenshot", `No diff found for ${stashId}, using simple screenshot`);
|
|
790
|
-
|
|
791
|
-
return {
|
|
792
|
-
primary: url,
|
|
793
|
-
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
794
|
-
};
|
|
808
|
+
return fallbackScreenshot(port, projectPath, stashId);
|
|
795
809
|
}
|
|
796
810
|
const processId = `screenshot-ai-${stashId}`;
|
|
797
811
|
const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId);
|
|
@@ -821,12 +835,8 @@ async function captureSmartScreenshots(opts) {
|
|
|
821
835
|
}
|
|
822
836
|
const result = parseAiResult(textOutput);
|
|
823
837
|
if (!result || !result.screenshots || result.screenshots.length === 0) {
|
|
824
|
-
logger.info("smart-screenshot", `AI returned no screenshots for ${stashId}, falling back`);
|
|
825
|
-
|
|
826
|
-
return {
|
|
827
|
-
primary: url,
|
|
828
|
-
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
829
|
-
};
|
|
838
|
+
logger.info("smart-screenshot", `AI returned no screenshots for ${stashId} (timedOut=${timedOut}), falling back`);
|
|
839
|
+
return fallbackScreenshot(port, projectPath, stashId);
|
|
830
840
|
}
|
|
831
841
|
const screenshots = [];
|
|
832
842
|
let primaryUrl = "";
|
|
@@ -849,11 +859,7 @@ async function captureSmartScreenshots(opts) {
|
|
|
849
859
|
}
|
|
850
860
|
if (screenshots.length === 0) {
|
|
851
861
|
logger.info("smart-screenshot", `No valid screenshots for ${stashId}, falling back`);
|
|
852
|
-
|
|
853
|
-
return {
|
|
854
|
-
primary: url,
|
|
855
|
-
screenshots: [{ url, label: "Homepage", route: "/", isPrimary: true }]
|
|
856
|
-
};
|
|
862
|
+
return fallbackScreenshot(port, projectPath, stashId);
|
|
857
863
|
}
|
|
858
864
|
if (!primaryUrl) {
|
|
859
865
|
primaryUrl = screenshots[0].url;
|
|
@@ -1002,7 +1008,7 @@ async function generate(opts) {
|
|
|
1002
1008
|
const port = await allocatePort();
|
|
1003
1009
|
const worktree = await worktreeManager.createForGeneration(`screenshot-${stash.id}`);
|
|
1004
1010
|
const screenshotGit = simpleGit3(worktree.path);
|
|
1005
|
-
await screenshotGit.checkout(["
|
|
1011
|
+
await screenshotGit.checkout(["--detach", stash.branch]);
|
|
1006
1012
|
const devServer = spawn3({
|
|
1007
1013
|
cmd: ["npm", "run", "dev"],
|
|
1008
1014
|
cwd: worktree.path,
|
|
@@ -1137,7 +1143,7 @@ async function vary(opts) {
|
|
|
1137
1143
|
const port = await allocatePort2();
|
|
1138
1144
|
const screenshotWorktree = await worktreeManager.createForGeneration(`screenshot-${stashId}`);
|
|
1139
1145
|
const screenshotGit = simpleGit4(screenshotWorktree.path);
|
|
1140
|
-
await screenshotGit.checkout(["
|
|
1146
|
+
await screenshotGit.checkout(["--detach", stash.branch]);
|
|
1141
1147
|
const devServer = spawn4({
|
|
1142
1148
|
cmd: ["npm", "run", "dev"],
|
|
1143
1149
|
cwd: screenshotWorktree.path,
|
|
@@ -1982,9 +1988,8 @@ ${sourceCode.substring(0, 3000)}
|
|
|
1982
1988
|
syncStashesFromDisk(projectId, chatId) {
|
|
1983
1989
|
const diskStashes = this.persistence.listStashes(projectId);
|
|
1984
1990
|
for (const stash of diskStashes) {
|
|
1985
|
-
if (chatId && !stash.originChatId
|
|
1986
|
-
|
|
1987
|
-
this.persistence.saveStash(updated);
|
|
1991
|
+
if (chatId && !stash.originChatId) {
|
|
1992
|
+
this.persistence.saveStash({ ...stash, originChatId: chatId });
|
|
1988
1993
|
}
|
|
1989
1994
|
this.broadcast({
|
|
1990
1995
|
type: "stash:status",
|
|
@@ -2015,7 +2020,7 @@ ${sourceCode.substring(0, 3000)}
|
|
|
2015
2020
|
for (const stash of stashes) {
|
|
2016
2021
|
const prev = lastStatus.get(stash.id);
|
|
2017
2022
|
if (!prev || prev !== stash.status) {
|
|
2018
|
-
if (chatId && !stash.originChatId
|
|
2023
|
+
if (chatId && !stash.originChatId) {
|
|
2019
2024
|
this.persistence.saveStash({ ...stash, originChatId: chatId });
|
|
2020
2025
|
}
|
|
2021
2026
|
this.broadcast({
|