@mindstudio-ai/remy 0.1.69 → 0.1.71

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/index.js CHANGED
@@ -398,6 +398,7 @@ var init_readSpec = __esm({
398
398
  init_helpers();
399
399
  DEFAULT_MAX_LINES = 500;
400
400
  readSpecTool = {
401
+ clearable: true,
401
402
  definition: {
402
403
  name: "readSpec",
403
404
  description: "Read a spec file from src/ with line numbers. Always read a spec file before editing it. Paths are relative to the project root and must start with src/ (e.g., src/app.md, src/interfaces/web.md).",
@@ -511,6 +512,7 @@ var init_writeSpec = __esm({
511
512
  init_helpers();
512
513
  init_diff();
513
514
  writeSpecTool = {
515
+ clearable: true,
514
516
  definition: {
515
517
  name: "writeSpec",
516
518
  description: "Create a new spec file or completely overwrite an existing one in src/. Parent directories are created automatically. Use this for new spec files or full rewrites. For targeted changes to existing specs, use editSpec instead.",
@@ -572,6 +574,7 @@ var init_editSpec = __esm({
572
574
  init_helpers();
573
575
  init_diff();
574
576
  editSpecTool = {
577
+ clearable: true,
575
578
  definition: {
576
579
  name: "editSpec",
577
580
  description: 'Make targeted edits to a spec file by heading path. This is the primary tool for modifying existing specs. Each edit targets a section by its heading hierarchy (e.g., "Vendors > Approval Flow") and applies an operation. Multiple edits are applied in order.',
@@ -714,6 +717,7 @@ var init_listSpecFiles = __esm({
714
717
  "src/tools/spec/listSpecFiles.ts"() {
715
718
  "use strict";
716
719
  listSpecFilesTool = {
720
+ clearable: false,
717
721
  definition: {
718
722
  name: "listSpecFiles",
719
723
  description: "List all files in the src/ directory (spec files, brand guidelines, interface specs, references). Use this to understand what spec files exist before reading or editing them.",
@@ -747,6 +751,7 @@ var init_clearSyncStatus = __esm({
747
751
  "src/tools/spec/clearSyncStatus.ts"() {
748
752
  "use strict";
749
753
  clearSyncStatusTool = {
754
+ clearable: false,
750
755
  definition: {
751
756
  name: "clearSyncStatus",
752
757
  description: "Clear the sync status flags after syncing spec and code. Call this after finishing a sync operation.",
@@ -768,6 +773,7 @@ var init_presentSyncPlan = __esm({
768
773
  "src/tools/spec/presentSyncPlan.ts"() {
769
774
  "use strict";
770
775
  presentSyncPlanTool = {
776
+ clearable: false,
771
777
  definition: {
772
778
  name: "presentSyncPlan",
773
779
  description: "Present a structured sync plan to the user for approval. Write a clear markdown summary of what changed and what you intend to update. The user will see this in a full-screen view and can approve or dismiss. Call this BEFORE making any sync edits.",
@@ -796,6 +802,7 @@ var init_presentPublishPlan = __esm({
796
802
  "src/tools/spec/presentPublishPlan.ts"() {
797
803
  "use strict";
798
804
  presentPublishPlanTool = {
805
+ clearable: false,
799
806
  definition: {
800
807
  name: "presentPublishPlan",
801
808
  description: "Present a publish changelog to the user for approval. Write a clear markdown summary of what changed since the last deploy. The user will see this in a full-screen view and can approve or dismiss. Call this BEFORE committing or pushing.",
@@ -824,6 +831,7 @@ var init_presentPlan = __esm({
824
831
  "src/tools/spec/presentPlan.ts"() {
825
832
  "use strict";
826
833
  presentPlanTool = {
834
+ clearable: false,
827
835
  definition: {
828
836
  name: "presentPlan",
829
837
  description: "Present an implementation plan for user approval before making changes. Use this only for large, multi-step changes like new features, new interface types, or when the user explicitly asks to see a plan. Most work should be done autonomously without a plan. Write a clear markdown summary of what you intend to do in plain language \u2014 describe the changes from the user's perspective, not as a list of files and code paths. If the user rejects with feedback, revise and present again.",
@@ -852,19 +860,16 @@ var init_setProjectOnboardingState = __esm({
852
860
  "src/tools/common/setProjectOnboardingState.ts"() {
853
861
  "use strict";
854
862
  setProjectOnboardingStateTool = {
863
+ clearable: false,
855
864
  definition: {
856
865
  name: "setProjectOnboardingState",
857
- description: "Advance the project onboarding state. Call at natural transition points: before writing the first spec (initialSpecAuthoring), before starting the first code generation (initialCodegen), after the first build succeeds (onboardingFinished). Forward-only progression.",
866
+ description: "Advance the project onboarding state. Call at natural transition points: after writing the first draft of the spec (initialSpecReview), before starting the first code generation (initialCodegen), after the first build succeeds (onboardingFinished). Forward-only progression.",
858
867
  inputSchema: {
859
868
  type: "object",
860
869
  properties: {
861
870
  state: {
862
871
  type: "string",
863
- enum: [
864
- "initialSpecAuthoring",
865
- "initialCodegen",
866
- "onboardingFinished"
867
- ],
872
+ enum: ["initialSpecReview", "initialCodegen", "onboardingFinished"],
868
873
  description: "The onboarding state to advance to."
869
874
  }
870
875
  },
@@ -884,6 +889,7 @@ var init_promptUser = __esm({
884
889
  "src/tools/common/promptUser.ts"() {
885
890
  "use strict";
886
891
  promptUserTool = {
892
+ clearable: false,
887
893
  definition: {
888
894
  name: "promptUser",
889
895
  description: 'Ask the user structured questions. Choose type first: "form" for structured intake (5+ questions, takes over screen), "inline" for quick clarifications or confirmations. Blocks until the user responds. Result contains `_dismissed: true` if the user dismisses without answering.',
@@ -1021,6 +1027,7 @@ var init_confirmDestructiveAction = __esm({
1021
1027
  "src/tools/common/confirmDestructiveAction.ts"() {
1022
1028
  "use strict";
1023
1029
  confirmDestructiveActionTool = {
1030
+ clearable: false,
1024
1031
  definition: {
1025
1032
  name: "confirmDestructiveAction",
1026
1033
  description: "Confirm a destructive or irreversible action with the user. Use for things like deleting data, resetting the database, or discarding draft work. Do not use after presentSyncPlan, presentPublishPlan, or presentPlan (those already include approval). Do not use before onboarding state transitions.",
@@ -1144,9 +1151,10 @@ var init_sdkConsultant = __esm({
1144
1151
  "use strict";
1145
1152
  init_runCli();
1146
1153
  askMindStudioSdkTool = {
1154
+ clearable: false,
1147
1155
  definition: {
1148
1156
  name: "askMindStudioSdk",
1149
- description: "@mindstudio-ai/agent SDK expert. Knows every action, model, connector, and configuration option. Returns architectural guidance and working code. Describe what you want to build, not just what API method you need. Batch related questions into a single query.",
1157
+ description: "@mindstudio-ai/agent backend SDK expert. Knows every backend action, AI model, connector, and configuration option. Returns architectural guidance and working code. Only covers the backend SDK (@mindstudio-ai/agent) \u2014 do NOT use for frontend/interface SDK questions (@mindstudio-ai/interface) like file uploads, auth, or client-side APIs. Describe what you want to build, not just what API method you need. Batch related questions into a single query.",
1150
1158
  inputSchema: {
1151
1159
  type: "object",
1152
1160
  properties: {
@@ -1177,6 +1185,7 @@ var init_searchGoogle = __esm({
1177
1185
  "use strict";
1178
1186
  init_runCli();
1179
1187
  searchGoogleTool = {
1188
+ clearable: false,
1180
1189
  definition: {
1181
1190
  name: "searchGoogle",
1182
1191
  description: "Search Google and return results. Use for research, finding documentation, looking up APIs, or any task where web search would help.",
@@ -1208,6 +1217,7 @@ var init_setProjectMetadata = __esm({
1208
1217
  "src/tools/common/setProjectMetadata.ts"() {
1209
1218
  "use strict";
1210
1219
  setProjectMetadataTool = {
1220
+ clearable: false,
1211
1221
  definition: {
1212
1222
  name: "setProjectMetadata",
1213
1223
  description: "Set project metadata. Can update any combination of: display name, app icon, and Open Graph share image. Provide only the fields you want to change.",
@@ -1253,6 +1263,7 @@ var init_readFile = __esm({
1253
1263
  "use strict";
1254
1264
  DEFAULT_MAX_LINES2 = 500;
1255
1265
  readFileTool = {
1266
+ clearable: true,
1256
1267
  definition: {
1257
1268
  name: "readFile",
1258
1269
  description: "Read a file's contents with line numbers. Always read a file before editing it \u2014 never guess at contents. For large files, consider using symbols first to identify the relevant section, then use offset and maxLines to read just that section. Line numbers in the output correspond to what editFile expects. Defaults to first 500 lines. Use a negative offset to read from the end of the file (e.g., offset: -50 reads the last 50 lines).",
@@ -1321,6 +1332,7 @@ var init_writeFile = __esm({
1321
1332
  "use strict";
1322
1333
  init_diff();
1323
1334
  writeFileTool = {
1335
+ clearable: true,
1324
1336
  definition: {
1325
1337
  name: "writeFile",
1326
1338
  description: "Create a new file or completely overwrite an existing one. Parent directories are created automatically. Use this for new files or full rewrites. For targeted changes to existing files, use editFile instead \u2014 it preserves the parts you don't want to change and avoids errors from forgetting to include unchanged code.",
@@ -1475,6 +1487,7 @@ var init_editFile = __esm({
1475
1487
  init_diff();
1476
1488
  init_helpers2();
1477
1489
  editFileTool = {
1490
+ clearable: true,
1478
1491
  definition: {
1479
1492
  name: "editFile",
1480
1493
  description: "Replace a string in a file. old_string must appear exactly once (minor indentation differences are handled automatically). Set replace_all to true to replace every occurrence at once. For bulk mechanical substitutions (renaming a variable, swapping colors), prefer replace_all. Always read the file first so you know the exact text to match. When editing nested structures (objects, function bodies, arrays, template literals), always include the full enclosing structure in old_string rather than just an inner fragment. Replacing a partial slice from the middle of nested code is the most common source of syntax errors.",
@@ -1568,6 +1581,7 @@ var init_bash = __esm({
1568
1581
  DEFAULT_TIMEOUT_MS = 12e4;
1569
1582
  DEFAULT_MAX_LINES3 = 500;
1570
1583
  bashTool = {
1584
+ clearable: true,
1571
1585
  definition: {
1572
1586
  name: "bash",
1573
1587
  description: "Run a shell command and return stdout + stderr. 120-second timeout by default (configurable). Use for: npm install/build/test, git operations, tsc --noEmit, or any CLI tool. Prefer dedicated tools over bash when available (use grep instead of bash + rg, readFile instead of bash + cat). Output is truncated to 500 lines by default.",
@@ -1657,6 +1671,7 @@ var init_grep = __esm({
1657
1671
  "use strict";
1658
1672
  DEFAULT_MAX = 50;
1659
1673
  grepTool = {
1674
+ clearable: true,
1660
1675
  definition: {
1661
1676
  name: "grep",
1662
1677
  description: "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers (default 50 results). Use this to find where something is used, locate function definitions, or search for patterns across the codebase. For finding a symbol's definition precisely, prefer the definition tool if LSP is available. Automatically excludes node_modules and .git.",
@@ -1718,6 +1733,7 @@ var init_glob = __esm({
1718
1733
  "use strict";
1719
1734
  DEFAULT_MAX2 = 200;
1720
1735
  globTool = {
1736
+ clearable: true,
1721
1737
  definition: {
1722
1738
  name: "glob",
1723
1739
  description: 'Find files matching a glob pattern. Returns matching file paths sorted alphabetically (default 200 results). Use this to discover project structure, find files by name or extension, or check if a file exists. Common patterns: "**/*.ts" (all TypeScript files), "src/**/*.tsx" (React components in src), "*.json" (root-level JSON files). Automatically excludes node_modules and .git.',
@@ -1770,6 +1786,7 @@ var init_listDir = __esm({
1770
1786
  "src/tools/code/listDir.ts"() {
1771
1787
  "use strict";
1772
1788
  listDirTool = {
1789
+ clearable: true,
1773
1790
  definition: {
1774
1791
  name: "listDir",
1775
1792
  description: "List the contents of a directory. Shows entries with / suffix for directories, sorted directories-first then alphabetically. Use this for a quick overview of a directory's contents. For finding files across the whole project, use glob instead.",
@@ -1811,6 +1828,7 @@ var init_editsFinished = __esm({
1811
1828
  "src/tools/code/editsFinished.ts"() {
1812
1829
  "use strict";
1813
1830
  editsFinishedTool = {
1831
+ clearable: false,
1814
1832
  definition: {
1815
1833
  name: "editsFinished",
1816
1834
  description: "Signal that file edits are complete. Call this after you finish writing/editing files so the live preview updates cleanly. The preview is paused while you edit to avoid showing broken intermediate states \u2014 this unpauses it. If you forget to call this, the preview updates when your turn ends.",
@@ -1891,6 +1909,7 @@ var init_lspDiagnostics = __esm({
1891
1909
  "use strict";
1892
1910
  init_lsp();
1893
1911
  lspDiagnosticsTool = {
1912
+ clearable: true,
1894
1913
  definition: {
1895
1914
  name: "lspDiagnostics",
1896
1915
  description: "Get TypeScript diagnostics (type errors, warnings) for a file, with suggested fixes when available. Use this after editing a file to check for errors.",
@@ -1946,6 +1965,7 @@ var init_restartProcess = __esm({
1946
1965
  "use strict";
1947
1966
  init_lsp();
1948
1967
  restartProcessTool = {
1968
+ clearable: false,
1949
1969
  definition: {
1950
1970
  name: "restartProcess",
1951
1971
  description: "Restart a managed sandbox process. Use this after running npm install or changing package.json to restart the dev server so it picks up new dependencies.",
@@ -1978,6 +1998,7 @@ var init_runScenario = __esm({
1978
1998
  "src/tools/code/runScenario.ts"() {
1979
1999
  "use strict";
1980
2000
  runScenarioTool = {
2001
+ clearable: true,
1981
2002
  definition: {
1982
2003
  name: "runScenario",
1983
2004
  description: "Run a scenario to seed the dev database with test data. Truncates all tables first, then executes the seed function and impersonates the scenario roles. Blocks until complete. Scenario IDs are defined in mindstudio.json. If it fails, check .logs/tunnel.log or .logs/requests.ndjson for details. Return synchronously - no need to sleep before checking results.",
@@ -2005,6 +2026,7 @@ var init_runMethod = __esm({
2005
2026
  "src/tools/code/runMethod.ts"() {
2006
2027
  "use strict";
2007
2028
  runMethodTool = {
2029
+ clearable: true,
2008
2030
  definition: {
2009
2031
  name: "runMethod",
2010
2032
  description: "Run a method in the dev environment and return the result. Use for testing methods after writing or modifying them. Returns output, captured console output, errors with stack traces, and duration. If it fails, check .logs/tunnel.log or .logs/requests.ndjson for more details. Return synchronously - no need to sleep before checking results.",
@@ -2109,6 +2131,7 @@ var init_screenshot2 = __esm({
2109
2131
  "use strict";
2110
2132
  init_screenshot();
2111
2133
  screenshotTool = {
2134
+ clearable: true,
2112
2135
  definition: {
2113
2136
  name: "screenshot",
2114
2137
  description: "Capture a full-height screenshot of the app preview and get a description of what's on screen. Provides static image analysis only, will not capture animations or video. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture.",
@@ -2378,6 +2401,7 @@ async function runSubAgent(config) {
2378
2401
  const fullSystem = `${system}
2379
2402
 
2380
2403
  Current date: ${dateStr}`;
2404
+ const excludeToolsFromClearing = tools2.filter((t) => t.clearable === false).map((t) => t.name);
2381
2405
  let turns = 0;
2382
2406
  const run = async () => {
2383
2407
  const messages = [
@@ -2441,6 +2465,7 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
2441
2465
  system: fullSystem,
2442
2466
  messages: cleanMessagesForApi(messages),
2443
2467
  tools: tools2,
2468
+ excludeToolsFromClearing,
2444
2469
  signal
2445
2470
  },
2446
2471
  {
@@ -2706,6 +2731,7 @@ var init_tools = __esm({
2706
2731
  "use strict";
2707
2732
  BROWSER_TOOLS = [
2708
2733
  {
2734
+ clearable: true,
2709
2735
  name: "browserCommand",
2710
2736
  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.",
2711
2737
  inputSchema: {
@@ -2786,6 +2812,7 @@ var init_tools = __esm({
2786
2812
  }
2787
2813
  },
2788
2814
  {
2815
+ clearable: true,
2789
2816
  name: "screenshotFullPage",
2790
2817
  description: "Capture a full-height screenshot of the current page. Returns a CDN URL with full text analysis and description.",
2791
2818
  inputSchema: {
@@ -2799,6 +2826,7 @@ var init_tools = __esm({
2799
2826
  }
2800
2827
  },
2801
2828
  {
2829
+ clearable: false,
2802
2830
  name: "resetBrowser",
2803
2831
  description: "Reset the browser to a clean state. Call this once after all tests are complete to restore the preview for the user. Fire and forget \u2014 does not wait for the reload to finish.",
2804
2832
  inputSchema: {
@@ -2893,6 +2921,7 @@ var init_browserAutomation = __esm({
2893
2921
  init_logger();
2894
2922
  log4 = createLogger("browser-automation");
2895
2923
  browserAutomationTool = {
2924
+ clearable: true,
2896
2925
  definition: {
2897
2926
  name: "runAutomatedBrowserTest",
2898
2927
  description: "Run an automated browser test against the live preview. Describe what to test \u2014 the agent figures out how. Use after meaningful changes frontend code, to reproduce user-reported issues, or to test end-to-end flows.",
@@ -3027,6 +3056,7 @@ var init_searchGoogle2 = __esm({
3027
3056
  "use strict";
3028
3057
  init_runCli();
3029
3058
  definition = {
3059
+ clearable: false,
3030
3060
  name: "searchGoogle",
3031
3061
  description: 'Search Google for web results. Reserch modern design trends in industries or verticals, "best [domain] apps 2026", ui patterns, or find something specific if the the user has an explicit reference. Searching for and reading case studies is a great way to get information and context about a project\'s domain. Prioritize authoritative sources like Figma and other design leaders, avoid random blog spam. Pick one or more URLs from the results and then use `scrapeWebUrl` to get their text content.',
3032
3062
  inputSchema: {
@@ -3065,6 +3095,7 @@ var init_scrapeWebUrl = __esm({
3065
3095
  "use strict";
3066
3096
  init_runCli();
3067
3097
  definition2 = {
3098
+ clearable: false,
3068
3099
  name: "scrapeWebUrl",
3069
3100
  description: "Fetch the content of a web page as markdown. Use when reading sites from search results or specific things the user wants to incorporate.",
3070
3101
  inputSchema: {
@@ -3139,6 +3170,7 @@ Identify the specific design moves that make this page interesting and unique, d
3139
3170
  Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.
3140
3171
  `;
3141
3172
  definition3 = {
3173
+ clearable: false,
3142
3174
  name: "analyzeDesign",
3143
3175
  description: "Analyze the visual design of a website or image URL. Websites are automatically screenshotted first. Provides static image analysis only, will not capture animations or video. If no prompt is provided, performs a full design reference analysis (mood, color, typography, layout, distinctiveness). Provide a custom prompt to ask a specific design question instead. Use a bulleted list to ask many questions at once.",
3144
3176
  inputSchema: {
@@ -3182,6 +3214,7 @@ var init_analyzeImage2 = __esm({
3182
3214
  init_analyzeImage();
3183
3215
  DEFAULT_PROMPT = "Describe everything visible in this image \u2014 every element, its position, its size relative to the frame, its colors, its content. Be comprehensive, thorough and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components). Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.";
3184
3216
  definition4 = {
3217
+ clearable: true,
3185
3218
  name: "analyzeImage",
3186
3219
  description: "Analyze an image by URL using a vision model. Provides static image analysis only, will not capture animations or video. Returns an objective description of what is visible \u2014 shapes, colors, layout, text, artifacts. Use for factual inventory of image contents, not for subjective design judgment - the vision model providing the analysis has no sense of design. You are the design expert - use the analysis tool for factual inventory, then apply your own expertise for quality and suitability assessments. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. If you are analyzing a screenshot of the app preview, you can reuse the same screenshot URL multiple times to ask multiple questions.",
3187
3220
  inputSchema: {
@@ -3249,6 +3282,7 @@ var init_screenshot3 = __esm({
3249
3282
  init_analyzeImage();
3250
3283
  init_browserAutomation();
3251
3284
  definition5 = {
3285
+ clearable: true,
3252
3286
  name: "screenshot",
3253
3287
  description: "Capture a full-height screenshot of the current app preview. Returns a CDN URL along with visual analysis. Use to review the current state of the UI being built. Remember, the screenshot analysis is not overly precise - for example, it cannot reliably identify specific fonts by name \u2014 it can only describe what letterforms look like.",
3254
3288
  inputSchema: {
@@ -3449,6 +3483,7 @@ var init_generateImages = __esm({
3449
3483
  "use strict";
3450
3484
  init_imageGenerator();
3451
3485
  definition6 = {
3486
+ clearable: false,
3452
3487
  name: "generateImages",
3453
3488
  description: "Generate images. Returns CDN URLs with a quality analysis for each image. Produces high-quality results for everything from photorealistic images and abstract/creative visuals. Pass multiple prompts to generate in parallel. No need to analyze images separately after generating \u2014 the analysis is included.",
3454
3489
  inputSchema: {
@@ -3502,6 +3537,7 @@ var init_editImages = __esm({
3502
3537
  "use strict";
3503
3538
  init_imageGenerator();
3504
3539
  definition7 = {
3540
+ clearable: false,
3505
3541
  name: "editImages",
3506
3542
  description: "Edit or transform existing images. Provide one or more source image URLs as reference and a prompt describing the desired edit. Use for compositing, style transfer, subject transformation, blending multiple references, or incorporating one or more references into something new. Returns CDN URLs with analysis.",
3507
3543
  inputSchema: {
@@ -3623,15 +3659,19 @@ function loadPlatformBrief() {
3623
3659
  return `<platform_brief>
3624
3660
  ## What is a MindStudio app?
3625
3661
 
3626
- A MindStudio app is a managed TypeScript project with three layers: a spec (natural language in src/), a backend contract (methods, tables, roles in dist/), and one or more interfaces (web, API, bots, cron, etc.). The spec is the source of truth; code is derived from it.
3662
+ A MindStudio app is a managed full-stack TypeScript project with three layers: a spec (natural language in src/), a backend contract (methods, tables, roles in dist/), and one or more interfaces (web, API, bots, cron, etc.). The spec is the source of truth; code is derived from it.
3663
+
3664
+ This is a capable, stable platform used in production by 100k+ users. Build with confidence \u2014 you're building production-grade apps, not fragile prototypes.
3627
3665
 
3628
3666
  ## What people build
3629
3667
 
3630
- - Business tools \u2014 dashboards, admin panels, approval workflows, data entry apps, internal tools with role-based access
3631
- - AI-powered apps \u2014 chatbots, content generators, document processors, image/video tools, AI agents that take actions
3668
+ - Business tools \u2014 client portals, approval workflows, admin panels with role-based access
3669
+ - AI-powered apps \u2014 document processors, image/video tools, content generators, conversational agents that take actions
3670
+ - Full-stack web apps \u2014 social platforms, membership sites, marketplaces, booking systems, community hubs \u2014 multi-user apps with auth, data, UI
3632
3671
  - Automations with no UI \u2014 cron jobs, webhook handlers, email processors, data sync pipelines
3672
+ - Marketing & launch pages \u2014 landing pages, waitlist pages with referral mechanics, product sites with scroll animations
3633
3673
  - Bots \u2014 Discord slash-command bots, Telegram bots, MCP tool servers for AI assistants
3634
- - Creative/interactive projects \u2014 games, interactive visualizations, generative art, portfolio sites
3674
+ - Creative/interactive projects \u2014 browser games with p5.js or Three.js, interactive visualizations, generative art, portfolio sites
3635
3675
  - API services \u2014 backend logic exposed as REST endpoints
3636
3676
  - Simple static sites \u2014 no backend needed, just a web interface with a build step
3637
3677
 
@@ -3656,13 +3696,12 @@ Each interface type invokes the same backend methods. Methods don't know which i
3656
3696
  TypeScript running in a sandboxed environment. Any npm package can be installed. Key capabilities:
3657
3697
 
3658
3698
  - Managed SQLite database with typed schemas and automatic migrations. Define a TypeScript interface, push, and the platform handles diffing and migrating.
3659
- - Built-in role-based auth. Define roles in the manifest, gate methods with auth.requireRole(). Platform handles sessions, tokens, user resolution.
3660
- - Sandboxed execution with npm packages pre-installed.
3699
+ - Built-in app-managed auth. Opt-in via manifest \u2014 developer builds login UI, platform handles verification codes (email/SMS), cookie sessions, and role enforcement. Backend methods use auth.requireRole() for access control.
3661
3700
  - Git-native deployment. Push to default branch to deploy.
3662
3701
 
3663
3702
  ## MindStudio SDK
3664
3703
 
3665
- The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (OpenAI, Anthropic, Google, Meta, Mistral, and more) and 1000+ integrations (email, SMS, Slack, HubSpot, Google Workspace, web scraping, image/video generation, media processing, and much more) with zero configuration \u2014 credentials are handled automatically in the execution environment. No API keys needed.
3704
+ The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (OpenAI, Anthropic, Google, Meta, Mistral, and more) and 1000+ integrations (email, SMS, Slack, HubSpot, Google Workspace, web scraping, image/video generation, media processing, and much more) with zero configuration \u2014 credentials are handled automatically in the execution environment. No API keys needed. This SDK is robust and battle-tested in production.
3666
3705
 
3667
3706
  ## What MindStudio apps are NOT good for
3668
3707
 
@@ -3910,6 +3949,7 @@ var init_designExpert = __esm({
3910
3949
  Visual design expert. Describe the situation and what you need \u2014 the agent decides what to deliver. It reads the spec files automatically. Include relevant user requirements and context it can't get from the spec, but do not list specific deliverables or tell it how to do its job. Do not suggest implementation details or ideas - only relay what is needed.
3911
3950
  `.trim();
3912
3951
  designExpertTool = {
3952
+ clearable: false,
3913
3953
  definition: {
3914
3954
  name: "visualDesignExpert",
3915
3955
  description: DESCRIPTION,
@@ -4244,6 +4284,7 @@ var init_productVision = __esm({
4244
4284
  init_prompt3();
4245
4285
  init_history();
4246
4286
  productVisionTool = {
4287
+ clearable: false,
4247
4288
  definition: {
4248
4289
  name: "productVision",
4249
4290
  description: "Owns the product roadmap. Reads spec and roadmap files automatically. Creates, updates, and deletes roadmap items in src/roadmap/. Describe the situation and what needs to happen.",
@@ -4409,6 +4450,7 @@ var init_codeSanityCheck = __esm({
4409
4450
  init_tools4();
4410
4451
  BASE_PROMPT3 = readAsset("subagents/codeSanityCheck", "prompt.md");
4411
4452
  codeSanityCheckTool = {
4453
+ clearable: false,
4412
4454
  definition: {
4413
4455
  name: "codeSanityCheck",
4414
4456
  description: 'Quick sanity check on an approach before building. Reviews architecture, package choices, and flags potential issues. Usually responds with "looks good." Occasionally catches something important. Readonly \u2014 can search the web and read code but cannot modify anything.',
@@ -4464,6 +4506,7 @@ var init_scrapeWebUrl2 = __esm({
4464
4506
  "use strict";
4465
4507
  init_runCli();
4466
4508
  scrapeWebUrlTool = {
4509
+ clearable: false,
4467
4510
  definition: {
4468
4511
  name: "scrapeWebUrl",
4469
4512
  description: "Scrape the content of a web page. Returns the HTML of the page as markdown text. Optionally capture a screenshot if you need see the visual design. Use this when you need to fetch or analyze content from a website",
@@ -4512,7 +4555,7 @@ function executeTool(name, input, context) {
4512
4555
  }
4513
4556
  return tool.execute(input, context);
4514
4557
  }
4515
- var ALL_TOOLS;
4558
+ var ALL_TOOLS, CLEARABLE_TOOLS;
4516
4559
  var init_tools5 = __esm({
4517
4560
  "src/tools/index.ts"() {
4518
4561
  "use strict";
@@ -4587,6 +4630,9 @@ var init_tools5 = __esm({
4587
4630
  lspDiagnosticsTool,
4588
4631
  restartProcessTool
4589
4632
  ];
4633
+ CLEARABLE_TOOLS = new Set(
4634
+ ALL_TOOLS.filter((t) => t.clearable).map((t) => t.definition.name)
4635
+ );
4590
4636
  }
4591
4637
  });
4592
4638
 
@@ -4901,6 +4947,7 @@ async function runTurn(params) {
4901
4947
  onBackgroundComplete
4902
4948
  } = params;
4903
4949
  const tools2 = getToolDefinitions(onboardingState);
4950
+ const excludeToolsFromClearing = tools2.filter((t) => !CLEARABLE_TOOLS.has(t.name)).map((t) => t.name);
4904
4951
  log6.info("Turn started", {
4905
4952
  requestId,
4906
4953
  model,
@@ -4910,11 +4957,17 @@ async function runTurn(params) {
4910
4957
  }
4911
4958
  });
4912
4959
  onEvent({ type: "turn_started" });
4960
+ const hasText = userMessage.trim().length > 0;
4961
+ const hasAttachments = attachments && attachments.length > 0;
4962
+ if (!hasText && !hasAttachments) {
4963
+ onEvent({ type: "error", error: "Empty message" });
4964
+ return;
4965
+ }
4913
4966
  const userMsg = { role: "user", content: userMessage };
4914
4967
  if (hidden) {
4915
4968
  userMsg.hidden = true;
4916
4969
  }
4917
- if (attachments && attachments.length > 0) {
4970
+ if (hasAttachments) {
4918
4971
  userMsg.attachments = attachments;
4919
4972
  }
4920
4973
  state.messages.push(userMsg);
@@ -5040,6 +5093,7 @@ async function runTurn(params) {
5040
5093
  system,
5041
5094
  messages: cleanMessagesForApi(state.messages),
5042
5095
  tools: tools2,
5096
+ excludeToolsFromClearing,
5043
5097
  signal
5044
5098
  },
5045
5099
  {
@@ -5358,6 +5412,7 @@ var init_agent = __esm({
5358
5412
  init_statusWatcher();
5359
5413
  init_errors();
5360
5414
  init_cleanMessages();
5415
+ init_tools5();
5361
5416
  log6 = createLogger("agent");
5362
5417
  EXTERNAL_TOOLS = /* @__PURE__ */ new Set([
5363
5418
  "promptUser",
@@ -5698,7 +5753,7 @@ var init_config = __esm({
5698
5753
  });
5699
5754
 
5700
5755
  // src/compaction/index.ts
5701
- async function compactConversation(state, apiConfig) {
5756
+ async function compactConversation(state, apiConfig, system, tools2) {
5702
5757
  const insertionIndex = findSafeInsertionPoint(state.messages);
5703
5758
  const summaries = [];
5704
5759
  const tasks = [];
@@ -5712,7 +5767,9 @@ async function compactConversation(state, apiConfig) {
5712
5767
  apiConfig,
5713
5768
  "conversation",
5714
5769
  CONVERSATION_SUMMARY_PROMPT,
5715
- conversationMessages
5770
+ conversationMessages,
5771
+ system,
5772
+ tools2
5716
5773
  ).then((text) => {
5717
5774
  if (text) {
5718
5775
  summaries.push({ name: "conversation", text });
@@ -5732,7 +5789,9 @@ async function compactConversation(state, apiConfig) {
5732
5789
  apiConfig,
5733
5790
  name,
5734
5791
  SUBAGENT_SUMMARY_PROMPT,
5735
- subagentMessages
5792
+ subagentMessages,
5793
+ system,
5794
+ tools2
5736
5795
  ).then((text) => {
5737
5796
  if (text) {
5738
5797
  summaries.push({ name, text });
@@ -5859,22 +5918,33 @@ function serializeForSummary(messages) {
5859
5918
  return `[${msg.role}]: ${parts.join("\n")}`;
5860
5919
  }).join("\n\n");
5861
5920
  }
5862
- async function generateSummary(apiConfig, name, systemPrompt, messagesToSummarize) {
5921
+ async function generateSummary(apiConfig, name, compactionPrompt, messagesToSummarize, mainSystem, mainTools) {
5863
5922
  const serialized = serializeForSummary(messagesToSummarize);
5864
5923
  if (!serialized.trim()) {
5865
5924
  return null;
5866
5925
  }
5867
5926
  log8.info("Generating summary", {
5868
5927
  name,
5869
- messageCount: messagesToSummarize.length
5928
+ messageCount: messagesToSummarize.length,
5929
+ cacheReuse: !!mainSystem
5870
5930
  });
5871
5931
  let summaryText = "";
5932
+ const useMainCache = !!mainSystem;
5933
+ const system = useMainCache ? mainSystem : compactionPrompt;
5934
+ const tools2 = useMainCache ? mainTools ?? [] : [];
5935
+ const userContent = useMainCache ? `${compactionPrompt}
5936
+
5937
+ ---
5938
+
5939
+ Conversation to summarize:
5940
+
5941
+ ${serialized}` : serialized;
5872
5942
  for await (const event of streamChat({
5873
5943
  ...apiConfig,
5874
5944
  subAgentId: "conversationSummarizer",
5875
- system: systemPrompt,
5876
- messages: [{ role: "user", content: serialized }],
5877
- tools: []
5945
+ system,
5946
+ messages: [{ role: "user", content: userContent }],
5947
+ tools: tools2
5878
5948
  })) {
5879
5949
  if (event.type === "text") {
5880
5950
  summaryText += event.text;
@@ -6088,6 +6158,7 @@ async function startHeadless(opts = {}) {
6088
6158
  let currentAbort = null;
6089
6159
  let currentRequestId;
6090
6160
  let completedEmitted = false;
6161
+ let turnStart = 0;
6091
6162
  const EXTERNAL_TOOL_TIMEOUT_MS = 3e5;
6092
6163
  const pendingTools = /* @__PURE__ */ new Map();
6093
6164
  const earlyResults = /* @__PURE__ */ new Map();
@@ -6200,8 +6271,8 @@ ${xmlParts}
6200
6271
  function onEvent(e) {
6201
6272
  const rid = currentRequestId;
6202
6273
  switch (e.type) {
6203
- // Suppressed — caller already knows the request started
6204
6274
  case "turn_started":
6275
+ emit("turn_started", {}, rid);
6205
6276
  return;
6206
6277
  // Terminal events — translate to `completed`
6207
6278
  case "turn_done":
@@ -6220,7 +6291,11 @@ ${xmlParts}
6220
6291
  writeFileSync(".remy-stats.json", JSON.stringify(sessionStats));
6221
6292
  } catch {
6222
6293
  }
6223
- emit("completed", { success: true }, rid);
6294
+ emit(
6295
+ "completed",
6296
+ { success: true, durationMs: Date.now() - turnStart },
6297
+ rid
6298
+ );
6224
6299
  setTimeout(() => {
6225
6300
  applyPendingBlockUpdates();
6226
6301
  flushBackgroundQueue();
@@ -6360,7 +6435,7 @@ ${xmlParts}
6360
6435
  currentRequestId = requestId;
6361
6436
  currentAbort = new AbortController();
6362
6437
  completedEmitted = false;
6363
- const turnStart = Date.now();
6438
+ turnStart = Date.now();
6364
6439
  const attachments = parsed.attachments;
6365
6440
  if (attachments?.length) {
6366
6441
  console.warn(
@@ -6505,7 +6580,9 @@ ${xmlParts}
6505
6580
  writeFileSync(".remy-stats.json", JSON.stringify(sessionStats));
6506
6581
  } catch {
6507
6582
  }
6508
- compactConversation(state, config).then(() => {
6583
+ const compactSystem = buildSystemPrompt("onboardingFinished");
6584
+ const compactTools = getToolDefinitions("onboardingFinished");
6585
+ compactConversation(state, config, compactSystem, compactTools).then(() => {
6509
6586
  saveSession(state);
6510
6587
  emit("compaction_complete", {}, requestId);
6511
6588
  emit("completed", { success: true }, requestId);
@@ -6564,6 +6641,7 @@ var init_headless = __esm({
6564
6641
  init_config();
6565
6642
  init_prompt4();
6566
6643
  init_compaction();
6644
+ init_tools5();
6567
6645
  init_lsp();
6568
6646
  init_agent();
6569
6647
  init_session();