stashes 0.1.57 → 0.1.59
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 +72 -30
- package/dist/mcp.js +72 -30
- package/dist/web/assets/index-WpgHkzXv.js +97 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-DLRxgF4c.js +0 -97
package/dist/cli.js
CHANGED
|
@@ -545,6 +545,31 @@ class PersistenceService {
|
|
|
545
545
|
// ../core/dist/ai-process.js
|
|
546
546
|
var {spawn } = globalThis.Bun;
|
|
547
547
|
var CLAUDE_BIN = "/opt/homebrew/bin/claude";
|
|
548
|
+
var OVERHEAD_TOOLS = [
|
|
549
|
+
"Agent",
|
|
550
|
+
"TodoWrite",
|
|
551
|
+
"TaskCreate",
|
|
552
|
+
"TaskUpdate",
|
|
553
|
+
"TaskList",
|
|
554
|
+
"TaskGet",
|
|
555
|
+
"Skill",
|
|
556
|
+
"ToolSearch",
|
|
557
|
+
"EnterPlanMode",
|
|
558
|
+
"ExitPlanMode",
|
|
559
|
+
"WebSearch",
|
|
560
|
+
"WebFetch",
|
|
561
|
+
"NotebookEdit",
|
|
562
|
+
"LSP",
|
|
563
|
+
"Read",
|
|
564
|
+
"Write",
|
|
565
|
+
"Edit",
|
|
566
|
+
"Glob",
|
|
567
|
+
"Grep",
|
|
568
|
+
"mcp__UseAI__*",
|
|
569
|
+
"mcp__stashes__*",
|
|
570
|
+
"mcp__plugin_drills*",
|
|
571
|
+
"mcp__plugin_coverit*"
|
|
572
|
+
];
|
|
548
573
|
var processes = new Map;
|
|
549
574
|
function startAiProcess(idOrOpts, prompt, cwd, resumeSessionId, model) {
|
|
550
575
|
const opts = typeof idOrOpts === "string" ? { id: idOrOpts, prompt, cwd, resumeSessionId, model } : idOrOpts;
|
|
@@ -557,6 +582,9 @@ function startAiProcess(idOrOpts, prompt, cwd, resumeSessionId, model) {
|
|
|
557
582
|
model: opts.model
|
|
558
583
|
});
|
|
559
584
|
const cmd = [CLAUDE_BIN, "-p", opts.prompt, "--output-format=stream-json", "--verbose", "--dangerously-skip-permissions"];
|
|
585
|
+
if (opts.disableOverheadTools) {
|
|
586
|
+
cmd.push("--disallowedTools", OVERHEAD_TOOLS.join(","));
|
|
587
|
+
}
|
|
560
588
|
if (opts.resumeSessionId) {
|
|
561
589
|
cmd.push("--resume", opts.resumeSessionId);
|
|
562
590
|
}
|
|
@@ -769,50 +797,61 @@ ${truncatedDiff}`;
|
|
|
769
797
|
return "";
|
|
770
798
|
}
|
|
771
799
|
}
|
|
772
|
-
function buildScreenshotPrompt(port, diff, screenshotDir, stashId) {
|
|
800
|
+
function buildScreenshotPrompt(port, diff, screenshotDir, stashId, componentPath) {
|
|
773
801
|
const outputPath = join5(screenshotDir, `${stashId}.png`);
|
|
774
802
|
return [
|
|
775
|
-
"##
|
|
803
|
+
"## You are a screenshot agent. Your goal: capture a screenshot showing the UI changes described in the diff below.",
|
|
776
804
|
"",
|
|
777
|
-
"
|
|
778
|
-
"-
|
|
779
|
-
"-
|
|
780
|
-
"
|
|
781
|
-
"
|
|
782
|
-
"-
|
|
805
|
+
"## RULES",
|
|
806
|
+
"- ONLY use Playwright MCP tools (prefixed with mcp__plugin_playwright_playwright__)",
|
|
807
|
+
"- Do NOT call: ToolSearch, Skill, Agent, TodoWrite, TaskCreate, TaskUpdate,",
|
|
808
|
+
" mcp__UseAI__*, mcp__stashes__*, mcp__plugin_drills__*, mcp__plugin_coverit__*,",
|
|
809
|
+
" EnterPlanMode, ExitPlanMode, WebSearch, WebFetch, LSP, Read, Write, Edit, Glob, Grep",
|
|
810
|
+
"- You have a strict time budget. Be fast and decisive.",
|
|
783
811
|
"",
|
|
784
|
-
|
|
812
|
+
`## App: http://localhost:${port}`,
|
|
813
|
+
componentPath ? `## Target component file: ${componentPath}` : "",
|
|
785
814
|
"",
|
|
786
|
-
|
|
787
|
-
"",
|
|
788
|
-
"## Git diff (shows what changed \u2014 use this to decide where to navigate):",
|
|
815
|
+
"## Git diff of changes:",
|
|
789
816
|
"```",
|
|
790
817
|
diff,
|
|
791
818
|
"```",
|
|
792
819
|
"",
|
|
793
|
-
"##
|
|
794
|
-
|
|
795
|
-
"
|
|
796
|
-
"
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
"
|
|
820
|
+
"## Your task",
|
|
821
|
+
"Study the diff above to understand:",
|
|
822
|
+
"1. WHAT changed (component, styles, layout, content)",
|
|
823
|
+
"2. WHERE it lives in the app (which route? which section of the page? is it behind a tab/modal/click?)",
|
|
824
|
+
"3. WHAT STATE is needed to see it (does a button need to be clicked? a tab selected? a form filled?)",
|
|
825
|
+
"",
|
|
826
|
+
"Then use Playwright tools to navigate there and capture it:",
|
|
800
827
|
"",
|
|
828
|
+
"**Available Playwright tools:**",
|
|
829
|
+
"- `mcp__plugin_playwright_playwright__browser_navigate` \u2014 go to a URL",
|
|
830
|
+
"- `mcp__plugin_playwright_playwright__browser_snapshot` \u2014 get the page accessibility tree (use this to find elements)",
|
|
831
|
+
"- `mcp__plugin_playwright_playwright__browser_click` \u2014 click an element (use ref from snapshot)",
|
|
832
|
+
"- `mcp__plugin_playwright_playwright__browser_hover` \u2014 hover over an element",
|
|
833
|
+
"- `mcp__plugin_playwright_playwright__browser_evaluate` \u2014 run JS on the page (e.g. scroll, trigger state)",
|
|
834
|
+
"- `mcp__plugin_playwright_playwright__browser_take_screenshot` \u2014 capture the screenshot",
|
|
835
|
+
"",
|
|
836
|
+
"**Typical flow:**",
|
|
837
|
+
`1. Navigate to http://localhost:${port} (or a sub-route if the diff indicates one)`,
|
|
838
|
+
"2. Take a snapshot to understand the page layout",
|
|
839
|
+
"3. If the changed component is not visible: scroll to it, click a tab, open a modal \u2014 whatever is needed",
|
|
840
|
+
"4. Take the screenshot once the changed component is visible",
|
|
841
|
+
"",
|
|
842
|
+
`## Output \u2014 after taking the screenshot, respond with ONLY this JSON:`,
|
|
801
843
|
"```json",
|
|
802
844
|
"{",
|
|
803
845
|
' "screenshots": [',
|
|
804
846
|
" {",
|
|
805
847
|
` "path": "${outputPath}",`,
|
|
806
|
-
' "label": "
|
|
807
|
-
' "route": "/",',
|
|
848
|
+
' "label": "Brief description of what the screenshot shows",',
|
|
849
|
+
' "route": "/the-route-you-navigated-to",',
|
|
808
850
|
' "isPrimary": true',
|
|
809
851
|
" }",
|
|
810
852
|
" ]",
|
|
811
853
|
"}",
|
|
812
|
-
"```"
|
|
813
|
-
"",
|
|
814
|
-
"REMEMBER: Do NOT call ToolSearch, Skill, UseAI, Read, or any tool not listed above.",
|
|
815
|
-
"You have a strict time limit. Just navigate, screenshot, output JSON, done."
|
|
854
|
+
"```"
|
|
816
855
|
].join(`
|
|
817
856
|
`);
|
|
818
857
|
}
|
|
@@ -846,7 +885,7 @@ async function fallbackScreenshot(port, projectPath, stashId) {
|
|
|
846
885
|
}
|
|
847
886
|
}
|
|
848
887
|
async function captureSmartScreenshots(opts) {
|
|
849
|
-
const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "sonnet", timeout = DEFAULT_TIMEOUT } = opts;
|
|
888
|
+
const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "sonnet", timeout = DEFAULT_TIMEOUT, componentPath } = opts;
|
|
850
889
|
const screenshotDir = join5(projectPath, SCREENSHOTS_DIR2);
|
|
851
890
|
if (!existsSync5(screenshotDir)) {
|
|
852
891
|
mkdirSync4(screenshotDir, { recursive: true });
|
|
@@ -857,13 +896,14 @@ async function captureSmartScreenshots(opts) {
|
|
|
857
896
|
return fallbackScreenshot(port, projectPath, stashId);
|
|
858
897
|
}
|
|
859
898
|
const processId = `screenshot-ai-${stashId}`;
|
|
860
|
-
const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId);
|
|
899
|
+
const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId, componentPath);
|
|
861
900
|
const modelFlag = model === "sonnet" ? "sonnet" : "haiku";
|
|
862
901
|
const aiProcess = startAiProcess({
|
|
863
902
|
id: processId,
|
|
864
903
|
prompt,
|
|
865
904
|
cwd: worktreePath,
|
|
866
|
-
model: modelFlag
|
|
905
|
+
model: modelFlag,
|
|
906
|
+
disableOverheadTools: true
|
|
867
907
|
});
|
|
868
908
|
let textOutput = "";
|
|
869
909
|
let timedOut = false;
|
|
@@ -1129,7 +1169,8 @@ async function generate(opts) {
|
|
|
1129
1169
|
worktreePath: screenshotWorktree.path,
|
|
1130
1170
|
port,
|
|
1131
1171
|
model: opts.screenshotModel,
|
|
1132
|
-
timeout: opts.screenshotTimeout
|
|
1172
|
+
timeout: opts.screenshotTimeout,
|
|
1173
|
+
componentPath: stash.componentPath ?? undefined
|
|
1133
1174
|
});
|
|
1134
1175
|
const readyStash = { ...generatedStash, status: "ready", screenshotUrl: primary, screenshots };
|
|
1135
1176
|
completedStashes.push(readyStash);
|
|
@@ -1295,7 +1336,8 @@ async function vary(opts) {
|
|
|
1295
1336
|
worktreePath: screenshotWorktree.path,
|
|
1296
1337
|
port,
|
|
1297
1338
|
model: opts.screenshotModel,
|
|
1298
|
-
timeout: opts.screenshotTimeout
|
|
1339
|
+
timeout: opts.screenshotTimeout,
|
|
1340
|
+
componentPath: stash.componentPath ?? undefined
|
|
1299
1341
|
});
|
|
1300
1342
|
screenshotPath = result.primary;
|
|
1301
1343
|
screenshots = [...result.screenshots];
|
package/dist/mcp.js
CHANGED
|
@@ -530,6 +530,31 @@ class PersistenceService {
|
|
|
530
530
|
// ../core/dist/ai-process.js
|
|
531
531
|
var {spawn } = globalThis.Bun;
|
|
532
532
|
var CLAUDE_BIN = "/opt/homebrew/bin/claude";
|
|
533
|
+
var OVERHEAD_TOOLS = [
|
|
534
|
+
"Agent",
|
|
535
|
+
"TodoWrite",
|
|
536
|
+
"TaskCreate",
|
|
537
|
+
"TaskUpdate",
|
|
538
|
+
"TaskList",
|
|
539
|
+
"TaskGet",
|
|
540
|
+
"Skill",
|
|
541
|
+
"ToolSearch",
|
|
542
|
+
"EnterPlanMode",
|
|
543
|
+
"ExitPlanMode",
|
|
544
|
+
"WebSearch",
|
|
545
|
+
"WebFetch",
|
|
546
|
+
"NotebookEdit",
|
|
547
|
+
"LSP",
|
|
548
|
+
"Read",
|
|
549
|
+
"Write",
|
|
550
|
+
"Edit",
|
|
551
|
+
"Glob",
|
|
552
|
+
"Grep",
|
|
553
|
+
"mcp__UseAI__*",
|
|
554
|
+
"mcp__stashes__*",
|
|
555
|
+
"mcp__plugin_drills*",
|
|
556
|
+
"mcp__plugin_coverit*"
|
|
557
|
+
];
|
|
533
558
|
var processes = new Map;
|
|
534
559
|
function startAiProcess(idOrOpts, prompt, cwd, resumeSessionId, model) {
|
|
535
560
|
const opts = typeof idOrOpts === "string" ? { id: idOrOpts, prompt, cwd, resumeSessionId, model } : idOrOpts;
|
|
@@ -542,6 +567,9 @@ function startAiProcess(idOrOpts, prompt, cwd, resumeSessionId, model) {
|
|
|
542
567
|
model: opts.model
|
|
543
568
|
});
|
|
544
569
|
const cmd = [CLAUDE_BIN, "-p", opts.prompt, "--output-format=stream-json", "--verbose", "--dangerously-skip-permissions"];
|
|
570
|
+
if (opts.disableOverheadTools) {
|
|
571
|
+
cmd.push("--disallowedTools", OVERHEAD_TOOLS.join(","));
|
|
572
|
+
}
|
|
545
573
|
if (opts.resumeSessionId) {
|
|
546
574
|
cmd.push("--resume", opts.resumeSessionId);
|
|
547
575
|
}
|
|
@@ -754,50 +782,61 @@ ${truncatedDiff}`;
|
|
|
754
782
|
return "";
|
|
755
783
|
}
|
|
756
784
|
}
|
|
757
|
-
function buildScreenshotPrompt(port, diff, screenshotDir, stashId) {
|
|
785
|
+
function buildScreenshotPrompt(port, diff, screenshotDir, stashId, componentPath) {
|
|
758
786
|
const outputPath = join5(screenshotDir, `${stashId}.png`);
|
|
759
787
|
return [
|
|
760
|
-
"##
|
|
788
|
+
"## You are a screenshot agent. Your goal: capture a screenshot showing the UI changes described in the diff below.",
|
|
761
789
|
"",
|
|
762
|
-
"
|
|
763
|
-
"-
|
|
764
|
-
"-
|
|
765
|
-
"
|
|
766
|
-
"
|
|
767
|
-
"-
|
|
790
|
+
"## RULES",
|
|
791
|
+
"- ONLY use Playwright MCP tools (prefixed with mcp__plugin_playwright_playwright__)",
|
|
792
|
+
"- Do NOT call: ToolSearch, Skill, Agent, TodoWrite, TaskCreate, TaskUpdate,",
|
|
793
|
+
" mcp__UseAI__*, mcp__stashes__*, mcp__plugin_drills__*, mcp__plugin_coverit__*,",
|
|
794
|
+
" EnterPlanMode, ExitPlanMode, WebSearch, WebFetch, LSP, Read, Write, Edit, Glob, Grep",
|
|
795
|
+
"- You have a strict time budget. Be fast and decisive.",
|
|
768
796
|
"",
|
|
769
|
-
|
|
797
|
+
`## App: http://localhost:${port}`,
|
|
798
|
+
componentPath ? `## Target component file: ${componentPath}` : "",
|
|
770
799
|
"",
|
|
771
|
-
|
|
772
|
-
"",
|
|
773
|
-
"## Git diff (shows what changed \u2014 use this to decide where to navigate):",
|
|
800
|
+
"## Git diff of changes:",
|
|
774
801
|
"```",
|
|
775
802
|
diff,
|
|
776
803
|
"```",
|
|
777
804
|
"",
|
|
778
|
-
"##
|
|
779
|
-
|
|
780
|
-
"
|
|
781
|
-
"
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
"
|
|
805
|
+
"## Your task",
|
|
806
|
+
"Study the diff above to understand:",
|
|
807
|
+
"1. WHAT changed (component, styles, layout, content)",
|
|
808
|
+
"2. WHERE it lives in the app (which route? which section of the page? is it behind a tab/modal/click?)",
|
|
809
|
+
"3. WHAT STATE is needed to see it (does a button need to be clicked? a tab selected? a form filled?)",
|
|
810
|
+
"",
|
|
811
|
+
"Then use Playwright tools to navigate there and capture it:",
|
|
785
812
|
"",
|
|
813
|
+
"**Available Playwright tools:**",
|
|
814
|
+
"- `mcp__plugin_playwright_playwright__browser_navigate` \u2014 go to a URL",
|
|
815
|
+
"- `mcp__plugin_playwright_playwright__browser_snapshot` \u2014 get the page accessibility tree (use this to find elements)",
|
|
816
|
+
"- `mcp__plugin_playwright_playwright__browser_click` \u2014 click an element (use ref from snapshot)",
|
|
817
|
+
"- `mcp__plugin_playwright_playwright__browser_hover` \u2014 hover over an element",
|
|
818
|
+
"- `mcp__plugin_playwright_playwright__browser_evaluate` \u2014 run JS on the page (e.g. scroll, trigger state)",
|
|
819
|
+
"- `mcp__plugin_playwright_playwright__browser_take_screenshot` \u2014 capture the screenshot",
|
|
820
|
+
"",
|
|
821
|
+
"**Typical flow:**",
|
|
822
|
+
`1. Navigate to http://localhost:${port} (or a sub-route if the diff indicates one)`,
|
|
823
|
+
"2. Take a snapshot to understand the page layout",
|
|
824
|
+
"3. If the changed component is not visible: scroll to it, click a tab, open a modal \u2014 whatever is needed",
|
|
825
|
+
"4. Take the screenshot once the changed component is visible",
|
|
826
|
+
"",
|
|
827
|
+
`## Output \u2014 after taking the screenshot, respond with ONLY this JSON:`,
|
|
786
828
|
"```json",
|
|
787
829
|
"{",
|
|
788
830
|
' "screenshots": [',
|
|
789
831
|
" {",
|
|
790
832
|
` "path": "${outputPath}",`,
|
|
791
|
-
' "label": "
|
|
792
|
-
' "route": "/",',
|
|
833
|
+
' "label": "Brief description of what the screenshot shows",',
|
|
834
|
+
' "route": "/the-route-you-navigated-to",',
|
|
793
835
|
' "isPrimary": true',
|
|
794
836
|
" }",
|
|
795
837
|
" ]",
|
|
796
838
|
"}",
|
|
797
|
-
"```"
|
|
798
|
-
"",
|
|
799
|
-
"REMEMBER: Do NOT call ToolSearch, Skill, UseAI, Read, or any tool not listed above.",
|
|
800
|
-
"You have a strict time limit. Just navigate, screenshot, output JSON, done."
|
|
839
|
+
"```"
|
|
801
840
|
].join(`
|
|
802
841
|
`);
|
|
803
842
|
}
|
|
@@ -831,7 +870,7 @@ async function fallbackScreenshot(port, projectPath, stashId) {
|
|
|
831
870
|
}
|
|
832
871
|
}
|
|
833
872
|
async function captureSmartScreenshots(opts) {
|
|
834
|
-
const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "sonnet", timeout = DEFAULT_TIMEOUT } = opts;
|
|
873
|
+
const { projectPath, stashId, stashBranch, parentBranch, worktreePath, port, model = "sonnet", timeout = DEFAULT_TIMEOUT, componentPath } = opts;
|
|
835
874
|
const screenshotDir = join5(projectPath, SCREENSHOTS_DIR2);
|
|
836
875
|
if (!existsSync5(screenshotDir)) {
|
|
837
876
|
mkdirSync4(screenshotDir, { recursive: true });
|
|
@@ -842,13 +881,14 @@ async function captureSmartScreenshots(opts) {
|
|
|
842
881
|
return fallbackScreenshot(port, projectPath, stashId);
|
|
843
882
|
}
|
|
844
883
|
const processId = `screenshot-ai-${stashId}`;
|
|
845
|
-
const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId);
|
|
884
|
+
const prompt = buildScreenshotPrompt(port, diff, screenshotDir, stashId, componentPath);
|
|
846
885
|
const modelFlag = model === "sonnet" ? "sonnet" : "haiku";
|
|
847
886
|
const aiProcess = startAiProcess({
|
|
848
887
|
id: processId,
|
|
849
888
|
prompt,
|
|
850
889
|
cwd: worktreePath,
|
|
851
|
-
model: modelFlag
|
|
890
|
+
model: modelFlag,
|
|
891
|
+
disableOverheadTools: true
|
|
852
892
|
});
|
|
853
893
|
let textOutput = "";
|
|
854
894
|
let timedOut = false;
|
|
@@ -1114,7 +1154,8 @@ async function generate(opts) {
|
|
|
1114
1154
|
worktreePath: screenshotWorktree.path,
|
|
1115
1155
|
port,
|
|
1116
1156
|
model: opts.screenshotModel,
|
|
1117
|
-
timeout: opts.screenshotTimeout
|
|
1157
|
+
timeout: opts.screenshotTimeout,
|
|
1158
|
+
componentPath: stash.componentPath ?? undefined
|
|
1118
1159
|
});
|
|
1119
1160
|
const readyStash = { ...generatedStash, status: "ready", screenshotUrl: primary, screenshots };
|
|
1120
1161
|
completedStashes.push(readyStash);
|
|
@@ -1280,7 +1321,8 @@ async function vary(opts) {
|
|
|
1280
1321
|
worktreePath: screenshotWorktree.path,
|
|
1281
1322
|
port,
|
|
1282
1323
|
model: opts.screenshotModel,
|
|
1283
|
-
timeout: opts.screenshotTimeout
|
|
1324
|
+
timeout: opts.screenshotTimeout,
|
|
1325
|
+
componentPath: stash.componentPath ?? undefined
|
|
1284
1326
|
});
|
|
1285
1327
|
screenshotPath = result.primary;
|
|
1286
1328
|
screenshots = [...result.screenshots];
|