@mindstudio-ai/remy 0.1.151 → 0.1.152

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/headless.js CHANGED
@@ -790,11 +790,40 @@ function serializeForSummary(messages) {
790
790
  return `[${msg.role}]: ${parts.join("\n")}`;
791
791
  }).join("\n\n");
792
792
  }
793
+ var CHUNK_CHAR_LIMIT = 24e5;
793
794
  async function generateSummary(apiConfig, name, compactionPrompt, messagesToSummarize, mainSystem, mainTools) {
794
795
  const serialized = serializeForSummary(messagesToSummarize);
795
796
  if (!serialized.trim()) {
796
797
  return null;
797
798
  }
799
+ if (serialized.length > CHUNK_CHAR_LIMIT && messagesToSummarize.length > 1) {
800
+ const mid = Math.floor(messagesToSummarize.length / 2);
801
+ log3.info("Chunking summary", {
802
+ name,
803
+ messageCount: messagesToSummarize.length,
804
+ serializedLength: serialized.length
805
+ });
806
+ const [first, second] = await Promise.all([
807
+ generateSummary(
808
+ apiConfig,
809
+ `${name} [pt1]`,
810
+ compactionPrompt,
811
+ messagesToSummarize.slice(0, mid),
812
+ mainSystem,
813
+ mainTools
814
+ ),
815
+ generateSummary(
816
+ apiConfig,
817
+ `${name} [pt2]`,
818
+ compactionPrompt,
819
+ messagesToSummarize.slice(mid),
820
+ mainSystem,
821
+ mainTools
822
+ )
823
+ ]);
824
+ const parts = [first, second].filter((p) => !!p);
825
+ return parts.length > 0 ? parts.join("\n\n---\n\n") : null;
826
+ }
798
827
  log3.info("Generating summary", {
799
828
  name,
800
829
  messageCount: messagesToSummarize.length,
@@ -2680,28 +2709,6 @@ function acquireBrowserLock() {
2680
2709
  lockQueue = next;
2681
2710
  return wait.then(() => release);
2682
2711
  }
2683
- async function checkBrowserConnected() {
2684
- try {
2685
- const status = await sidecarRequest(
2686
- "/browser-status",
2687
- {},
2688
- { timeout: 5e3 }
2689
- );
2690
- if (!status.connected) {
2691
- return {
2692
- connected: false,
2693
- reason: BROWSER_UNAVAILABLE_MESSAGE
2694
- };
2695
- }
2696
- return { connected: true };
2697
- } catch {
2698
- return {
2699
- connected: false,
2700
- reason: BROWSER_UNAVAILABLE_MESSAGE
2701
- };
2702
- }
2703
- }
2704
- var BROWSER_UNAVAILABLE_MESSAGE = "Browser preview unavailable \u2014 the user has closed their browser and we are continuing to work in the background. This is not a code failure and not something to diagnose. Do not tell the user to click or open anything. Skip the visual check and verify your work through other means: runMethod for backend behavior, queryDatabase for data checks, .logs/devServer.ndjson for build errors, .logs/browser.ndjson for runtime errors, lspDiagnostics for type/syntax, or read the code directly.";
2705
2712
 
2706
2713
  // src/statusWatcher.ts
2707
2714
  function startStatusWatcher(config) {
@@ -3338,7 +3345,7 @@ var BROWSER_TOOLS = [
3338
3345
  {
3339
3346
  clearable: true,
3340
3347
  name: "browserCommand",
3341
- description: "Interact with the app's live preview by sending browser commands. Commands execute sequentially with an animated cursor. Always start with a snapshot to see the current state and get ref identifiers. The result includes a snapshot field with the final page state after all steps complete. On error, the failing step has an error field and execution stops. Timeout: 120s.",
3348
+ description: "Interact with the app's live preview by sending browser commands. Commands execute sequentially with an animated cursor. Always start with a snapshot to see the current state and get ref identifiers. The result includes a snapshot field with the final page state after all steps complete. On error, the failing step has an error field and execution stops. Batches that contain an interactive step (click, type, select) also return a `recordingUrl` \u2014 an rrweb session recording for visual replay. Timeout: 120s.",
3342
3349
  inputSchema: {
3343
3350
  type: "object",
3344
3351
  properties: {
@@ -3475,14 +3482,6 @@ var browserAutomationTool = {
3475
3482
  }
3476
3483
  const release = await acquireBrowserLock();
3477
3484
  try {
3478
- const browserStatus = await checkBrowserConnected();
3479
- if (!browserStatus.connected) {
3480
- return browserStatus.reason ?? "Browser preview unavailable.";
3481
- }
3482
- try {
3483
- await sidecarRequest("/reset-browser", {}, { timeout: 5e3 });
3484
- } catch {
3485
- }
3486
3485
  const result = await runSubAgent({
3487
3486
  system: getBrowserAutomationPrompt(),
3488
3487
  task: input.task,
@@ -3572,10 +3571,6 @@ var browserAutomationTool = {
3572
3571
  toolRegistry: context.toolRegistry,
3573
3572
  captureArtifacts: ["screenshotFullPage"]
3574
3573
  });
3575
- try {
3576
- await sidecarRequest("/reset-browser", {}, { timeout: 5e3 });
3577
- } catch {
3578
- }
3579
3574
  context.subAgentMessages?.set(context.toolCallId, result.messages);
3580
3575
  const ss = result.artifacts?.screenshotFullPage;
3581
3576
  if (ss?.url) {
@@ -3661,10 +3656,6 @@ var screenshotTool = {
3661
3656
  }
3662
3657
  const release = await acquireBrowserLock();
3663
3658
  try {
3664
- const browserStatus = await checkBrowserConnected();
3665
- if (!browserStatus.connected) {
3666
- return browserStatus.reason ?? "Browser preview unavailable.";
3667
- }
3668
3659
  return await captureAndAnalyzeScreenshot({
3669
3660
  prompt: input.prompt,
3670
3661
  path: input.path,
@@ -3999,10 +3990,6 @@ async function execute5(input, onLog, context) {
3999
3990
  }
4000
3991
  const release = await acquireBrowserLock();
4001
3992
  try {
4002
- const browserStatus = await checkBrowserConnected();
4003
- if (!browserStatus.connected) {
4004
- return browserStatus.reason ?? "Browser preview unavailable.";
4005
- }
4006
3993
  return await captureAndAnalyzeScreenshot({
4007
3994
  prompt: input.prompt,
4008
3995
  path: input.path,
package/dist/index.js CHANGED
@@ -1511,6 +1511,34 @@ async function generateSummary(apiConfig, name, compactionPrompt, messagesToSumm
1511
1511
  if (!serialized.trim()) {
1512
1512
  return null;
1513
1513
  }
1514
+ if (serialized.length > CHUNK_CHAR_LIMIT && messagesToSummarize.length > 1) {
1515
+ const mid = Math.floor(messagesToSummarize.length / 2);
1516
+ log2.info("Chunking summary", {
1517
+ name,
1518
+ messageCount: messagesToSummarize.length,
1519
+ serializedLength: serialized.length
1520
+ });
1521
+ const [first, second] = await Promise.all([
1522
+ generateSummary(
1523
+ apiConfig,
1524
+ `${name} [pt1]`,
1525
+ compactionPrompt,
1526
+ messagesToSummarize.slice(0, mid),
1527
+ mainSystem,
1528
+ mainTools
1529
+ ),
1530
+ generateSummary(
1531
+ apiConfig,
1532
+ `${name} [pt2]`,
1533
+ compactionPrompt,
1534
+ messagesToSummarize.slice(mid),
1535
+ mainSystem,
1536
+ mainTools
1537
+ )
1538
+ ]);
1539
+ const parts = [first, second].filter((p) => !!p);
1540
+ return parts.length > 0 ? parts.join("\n\n---\n\n") : null;
1541
+ }
1514
1542
  log2.info("Generating summary", {
1515
1543
  name,
1516
1544
  messageCount: messagesToSummarize.length,
@@ -1548,7 +1576,7 @@ ${serialized}` : serialized;
1548
1576
  log2.info("Summary generated", { name, summaryLength: summaryText.length });
1549
1577
  return summaryText.trim();
1550
1578
  }
1551
- var log2, CONVERSATION_SUMMARY_PROMPT, SUBAGENT_SUMMARY_PROMPT, SUMMARIZABLE_SUBAGENTS;
1579
+ var log2, CONVERSATION_SUMMARY_PROMPT, SUBAGENT_SUMMARY_PROMPT, SUMMARIZABLE_SUBAGENTS, CHUNK_CHAR_LIMIT;
1552
1580
  var init_compaction = __esm({
1553
1581
  "src/compaction/index.ts"() {
1554
1582
  "use strict";
@@ -1559,6 +1587,7 @@ var init_compaction = __esm({
1559
1587
  CONVERSATION_SUMMARY_PROMPT = readAsset("compaction", "conversation.md");
1560
1588
  SUBAGENT_SUMMARY_PROMPT = readAsset("compaction", "subagent.md");
1561
1589
  SUMMARIZABLE_SUBAGENTS = ["visualDesignExpert", "productVision"];
1590
+ CHUNK_CHAR_LIMIT = 24e5;
1562
1591
  }
1563
1592
  });
1564
1593
 
@@ -2958,34 +2987,11 @@ function acquireBrowserLock() {
2958
2987
  lockQueue = next;
2959
2988
  return wait.then(() => release);
2960
2989
  }
2961
- async function checkBrowserConnected() {
2962
- try {
2963
- const status = await sidecarRequest(
2964
- "/browser-status",
2965
- {},
2966
- { timeout: 5e3 }
2967
- );
2968
- if (!status.connected) {
2969
- return {
2970
- connected: false,
2971
- reason: BROWSER_UNAVAILABLE_MESSAGE
2972
- };
2973
- }
2974
- return { connected: true };
2975
- } catch {
2976
- return {
2977
- connected: false,
2978
- reason: BROWSER_UNAVAILABLE_MESSAGE
2979
- };
2980
- }
2981
- }
2982
- var lockQueue, BROWSER_UNAVAILABLE_MESSAGE;
2990
+ var lockQueue;
2983
2991
  var init_browserLock = __esm({
2984
2992
  "src/tools/_helpers/browserLock.ts"() {
2985
2993
  "use strict";
2986
- init_sidecar();
2987
2994
  lockQueue = Promise.resolve();
2988
- BROWSER_UNAVAILABLE_MESSAGE = "Browser preview unavailable \u2014 the user has closed their browser and we are continuing to work in the background. This is not a code failure and not something to diagnose. Do not tell the user to click or open anything. Skip the visual check and verify your work through other means: runMethod for backend behavior, queryDatabase for data checks, .logs/devServer.ndjson for build errors, .logs/browser.ndjson for runtime errors, lspDiagnostics for type/syntax, or read the code directly.";
2989
2995
  }
2990
2996
  });
2991
2997
 
@@ -3654,7 +3660,7 @@ var init_tools = __esm({
3654
3660
  {
3655
3661
  clearable: true,
3656
3662
  name: "browserCommand",
3657
- description: "Interact with the app's live preview by sending browser commands. Commands execute sequentially with an animated cursor. Always start with a snapshot to see the current state and get ref identifiers. The result includes a snapshot field with the final page state after all steps complete. On error, the failing step has an error field and execution stops. Timeout: 120s.",
3663
+ description: "Interact with the app's live preview by sending browser commands. Commands execute sequentially with an animated cursor. Always start with a snapshot to see the current state and get ref identifiers. The result includes a snapshot field with the final page state after all steps complete. On error, the failing step has an error field and execution stops. Batches that contain an interactive step (click, type, select) also return a `recordingUrl` \u2014 an rrweb session recording for visual replay. Timeout: 120s.",
3658
3664
  inputSchema: {
3659
3665
  type: "object",
3660
3666
  properties: {
@@ -3812,14 +3818,6 @@ var init_browserAutomation = __esm({
3812
3818
  }
3813
3819
  const release = await acquireBrowserLock();
3814
3820
  try {
3815
- const browserStatus = await checkBrowserConnected();
3816
- if (!browserStatus.connected) {
3817
- return browserStatus.reason ?? "Browser preview unavailable.";
3818
- }
3819
- try {
3820
- await sidecarRequest("/reset-browser", {}, { timeout: 5e3 });
3821
- } catch {
3822
- }
3823
3821
  const result = await runSubAgent({
3824
3822
  system: getBrowserAutomationPrompt(),
3825
3823
  task: input.task,
@@ -3909,10 +3907,6 @@ var init_browserAutomation = __esm({
3909
3907
  toolRegistry: context.toolRegistry,
3910
3908
  captureArtifacts: ["screenshotFullPage"]
3911
3909
  });
3912
- try {
3913
- await sidecarRequest("/reset-browser", {}, { timeout: 5e3 });
3914
- } catch {
3915
- }
3916
3910
  context.subAgentMessages?.set(context.toolCallId, result.messages);
3917
3911
  const ss = result.artifacts?.screenshotFullPage;
3918
3912
  if (ss?.url) {
@@ -4008,10 +4002,6 @@ var init_screenshot2 = __esm({
4008
4002
  }
4009
4003
  const release = await acquireBrowserLock();
4010
4004
  try {
4011
- const browserStatus = await checkBrowserConnected();
4012
- if (!browserStatus.connected) {
4013
- return browserStatus.reason ?? "Browser preview unavailable.";
4014
- }
4015
4005
  return await captureAndAnalyzeScreenshot({
4016
4006
  prompt: input.prompt,
4017
4007
  path: input.path,
@@ -4362,10 +4352,6 @@ async function execute5(input, onLog, context) {
4362
4352
  }
4363
4353
  const release = await acquireBrowserLock();
4364
4354
  try {
4365
- const browserStatus = await checkBrowserConnected();
4366
- if (!browserStatus.connected) {
4367
- return browserStatus.reason ?? "Browser preview unavailable.";
4368
- }
4369
4355
  return await captureAndAnalyzeScreenshot({
4370
4356
  prompt: input.prompt,
4371
4357
  path: input.path,
@@ -145,7 +145,7 @@ The intro framing ("you have a lot on your plate") gives the model permission to
145
145
  | `productVision` | Roadmap ownership & product strategy | writeRoadmapItem, updateRoadmapItem, deleteRoadmapItem | Spec files + current roadmap |
146
146
  | `sdkConsultant` | MindStudio SDK architecture | None (shells out to `mindstudio ask` CLI) | None (external agent) |
147
147
  | `codeSanityCheck` | Pre-build review | readFile, grep, glob, searchGoogle, fetchUrl, askMindStudioSdk, bash (readonly) | Spec files |
148
- | `browserAutomation` | Interactive UI testing | browserCommand, screenshot, resetBrowser | None (interacts with live preview) |
148
+ | `browserAutomation` | Interactive UI testing | browserCommand, screenshotFullPage, setupBrowser | None (interacts with live preview) |
149
149
 
150
150
  ### Shared infrastructure
151
151
 
@@ -177,8 +177,6 @@ New `type: roadmap` for MSFM files in `src/roadmap/`. Each item has frontmatter
177
177
  - **Automated message sentinel** — `@@automated::{tag}@@` prefix on user messages, stripped before sending to LLM. Frontend uses for custom rendering.
178
178
  - **Project naming** — `setProjectName` tool for setting display name after intake.
179
179
  - **Dynamic status labels** — `statusWatcher.ts` periodically calls a lightweight endpoint to generate descriptive labels during agent work.
180
- - **Browser status check** — agent checks `/browser-status` before starting browser automation to fail fast if preview isn't connected.
181
- - **Browser reset** — `resetBrowser` tool restores preview to clean state after testing.
182
180
  - **Asset bundling** — `tsup.config.ts` copies .md/.json/.sh files from src/ to dist/ on build.
183
181
 
184
182
  ## What's Not Done
@@ -12,7 +12,7 @@ Run `lspDiagnostics` after every turn where you have edited code in any meaningf
12
12
  - Spot-check methods with `runMethod`. The dev database is a disposable snapshot that will have been seeded with scenario data, so don't worry about being destructive.
13
13
  - For frontend work, take a single `screenshot` to confirm the main view renders correctly or look at the browser log for any console errors in the user's preview.
14
14
  - Use `runAutomatedBrowserTest` to verify an interactive flow that you can't confirm from a screenshot, or when the user reports something broken that you can't identify from code alone.
15
- - If the browser preview isn't connected, skip the visual check and verify through methods, logs, and code instead. Preview unavailability is an environmental state, not a code issuethe user might have closed their browser and we are continuing to work in the background.
15
+ - If the browser is unavailable, skip the visual check and verify through methods, logs, and code instead. Browser unavailability is an infrastructure issue, not a code problemdon't try to diagnose or fix it.
16
16
 
17
17
  Aim for confidence that the core happy paths work. If the 80% case is solid, the remaining edge cases are likely fine and the user can surface them in chat. Don't screenshot every page, test every permutation, or verify every secondary flow. One or two runtime checks that confirm the app loads and data flows through is enough.
18
18
 
@@ -39,4 +39,5 @@ You will occasionally receive automated messages prefixed with `@@automated_mess
39
39
  - Keep language accessible. Describe what the app *does*, not how it's implemented, unless the user demonstrates technical fluency.
40
40
  - Always use full paths relative to the project root when mentioning files (`dist/interfaces/web/src/App.tsx`, not `App.tsx`). Paths will be rendered as clickable links for the user.
41
41
  - Use inline `code` formatting only for things the user needs to type or search for.
42
- - When writing prose or communicating with the user, avoid em dashes (and especially when writing specs); use periods, commas, colons, or parentheses instead. Do not use emojis.
42
+ - When writing prose or communicating with the user, avoid em dashes (and especially when writing specs); use periods, commas, colons, or parentheses instead.
43
+ - Never use emojis when responding to the user.
@@ -44,7 +44,7 @@ The QA agent can see the screen. Describe what to test, not how — it will figu
44
44
 
45
45
  Never tell QA what names to use when testing or what values to input - it will use its own judgment.
46
46
 
47
- If the browser preview is unavailable, QA can't run. Treat that as an environmental limit, not a problem with the app — the user has closed their browser and we are continuing to work in the background. Do not guide the user to open or click anything. Verify through methods, logs, and code inspection instead, and just note that visual QA was skipped.
47
+ If the browser is unavailable, QA can't run. That's an infrastructure issue, not a problem with the app — don't try to diagnose or fix it. Verify through methods, logs, and code inspection instead, and note that visual QA was skipped.
48
48
 
49
49
  ### Background Execution
50
50
 
@@ -3,7 +3,7 @@ You are a browser smoke test agent. You verify that features work end to end by
3
3
  ## Rules to Remember
4
4
  - Don't overthink the tests - the goal is to generally make sure things work as expected, not to provide detailed QA. If something seems mostly okay, note it and move on. Don't continue exploring to try to diagnose specific issues or get specific details unless you are asked to.
5
5
  - Fail early: If you encounter a showstopper bug (something doesn't load, something is broken, etc.) do not attempt to diagnose it or work around it. We need core common user paths to work - if they don't the app is broken and testing should not continue until it is fixed. Return early with a report to let the developer fix it, they'll run another test when they're ready.
6
- - Browser disconnection is environmental, not a test failure. If `browserCommand` returns `BROWSER_DISCONNECTED` or the browser otherwise drops mid-test, the test is **inconclusive** — the user has closed their browser and we are continuing to work in the background. Do not retry, do not attribute it to app brokenness, do not tell the user to open or click anything. Report "test inconclusive: browser disconnected" and stop.
6
+ - Browser unavailability is an infrastructure issue, not a test failure. If `browserCommand` reports the browser is unavailable or drops mid-test, the test is **inconclusive** — do not retry, do not attribute it to app brokenness. Report "test inconclusive: browser unavailable" and stop.
7
7
 
8
8
  ## Tester Persona
9
9
  The user is watching the automation happen on their screen in real-time. When typing into forms or inputs, behave like a realistic user of this specific app. Use the app context (if provided) to understand the audience and tone. Type the way that audience would actually type — not formal, not robotic. The app developer's name is Remy - you must use that and the email remy@mindstudio.ai as the basis for any testing that requires a persona.
@@ -39,7 +39,6 @@ Each interactive element has a `[ref=eN]` you can use to target it.
39
39
  - `select`: Select a dropdown option by text. Target the `<select>` element, set `option` to the option text.
40
40
  - `wait`: Wait for an element to appear (polls every 100ms, default 5s timeout). Also waits for network to settle after the element is found.
41
41
  - `navigate`: Navigate to a new URL within the app. Waits for the new page to load before continuing with subsequent steps. Use this instead of evaluate with `window.location.href` when you need to navigate and then continue interacting with the new page. Steps after navigate execute on the new page automatically.
42
- - `reload`: Reload the current page. Useful if something has crashed, you can not exit some dynamic screen, or you need to clear stale data or some stale app state. Waits for the page to reload before continuting with subsequent steps. Use this instead of using evaluate to reload a page.
43
42
  - `evaluate`: Run arbitrary JavaScript in the page and return the result.
44
43
  - `styles`: Read computed CSS styles from page elements. Pass a `properties` array with camelCase CSS property names (e.g., `["backgroundColor", "borderRadius", "fontSize"]`). Omit `properties` for a default set covering colors, typography, spacing, borders, shadows, dimensions, and layout. Uses the same targeting as click/type (ref, text, role, label, selector). Omit the target to get styles for all elements from the last snapshot.
45
44
  - `screenshotViewport`: Take a screenshot of the current viewport. Returns CDN url with full text analysis and dimensions. Useful at the end of an action batch to visually see things like layout shift or overflow. Do not use if you can get what you need with other tools - only use when you need to visually see the viewport.
@@ -61,6 +60,7 @@ Each browserCommand returns:
61
60
  - `snapshot`: the final page state after all steps complete (always present, even without an explicit snapshot step)
62
61
  - `logs`: array of browser-side events that fired during the batch (console output, network failures, JS errors, user interactions). Check this for errors before reporting pass.
63
62
  - `duration`: total execution time in ms
63
+ - `recordingUrl` (optional): URL to an rrweb session recording of the tool call. Present whenever the batch contained an interactive step (click, type, select). Include it in your failure reports so the main agent can share it — it's the fastest way to reproduce a bug visually.
64
64
 
65
65
  On error, the failing step has an `error` field and execution stops. Remaining steps are skipped.
66
66
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.151",
3
+ "version": "0.1.152",
4
4
  "description": "MindStudio coding agent",
5
5
  "repository": {
6
6
  "type": "git",