@mindstudio-ai/remy 0.1.8 → 0.1.9

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.
Files changed (3) hide show
  1. package/dist/headless.js +201 -114
  2. package/dist/index.js +244 -143
  3. package/package.json +1 -1
package/dist/headless.js CHANGED
@@ -893,7 +893,88 @@ async function listRecursive(dir) {
893
893
  return results;
894
894
  }
895
895
 
896
- // src/tools/spec/setProjectOnboardingState.ts
896
+ // src/tools/spec/clearSyncStatus.ts
897
+ var clearSyncStatusTool = {
898
+ definition: {
899
+ name: "clearSyncStatus",
900
+ description: "Clear the sync status flags after syncing spec and code. Call this after finishing a sync operation.",
901
+ inputSchema: {
902
+ type: "object",
903
+ properties: {}
904
+ }
905
+ },
906
+ async execute() {
907
+ return "ok";
908
+ }
909
+ };
910
+
911
+ // src/tools/spec/presentSyncPlan.ts
912
+ var presentSyncPlanTool = {
913
+ definition: {
914
+ name: "presentSyncPlan",
915
+ 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.",
916
+ inputSchema: {
917
+ type: "object",
918
+ properties: {
919
+ content: {
920
+ type: "string",
921
+ description: "Markdown plan describing what changed and what will be updated."
922
+ }
923
+ },
924
+ required: ["content"]
925
+ }
926
+ },
927
+ streaming: {},
928
+ async execute() {
929
+ return "approved";
930
+ }
931
+ };
932
+
933
+ // src/tools/spec/presentPublishPlan.ts
934
+ var presentPublishPlanTool = {
935
+ definition: {
936
+ name: "presentPublishPlan",
937
+ 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.",
938
+ inputSchema: {
939
+ type: "object",
940
+ properties: {
941
+ content: {
942
+ type: "string",
943
+ description: "Markdown changelog describing what changed and what will be deployed."
944
+ }
945
+ },
946
+ required: ["content"]
947
+ }
948
+ },
949
+ streaming: {},
950
+ async execute() {
951
+ return "approved";
952
+ }
953
+ };
954
+
955
+ // src/tools/spec/presentPlan.ts
956
+ var presentPlanTool = {
957
+ definition: {
958
+ name: "presentPlan",
959
+ description: "Present an implementation plan for user approval before making changes. Use this only for large, multi-step changes 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.",
960
+ inputSchema: {
961
+ type: "object",
962
+ properties: {
963
+ content: {
964
+ type: "string",
965
+ description: "Markdown plan describing what you intend to do."
966
+ }
967
+ },
968
+ required: ["content"]
969
+ }
970
+ },
971
+ streaming: {},
972
+ async execute() {
973
+ return "approved";
974
+ }
975
+ };
976
+
977
+ // src/tools/common/setProjectOnboardingState.ts
897
978
  var setProjectOnboardingStateTool = {
898
979
  definition: {
899
980
  name: "setProjectOnboardingState",
@@ -919,7 +1000,7 @@ var setProjectOnboardingStateTool = {
919
1000
  }
920
1001
  };
921
1002
 
922
- // src/tools/spec/promptUser.ts
1003
+ // src/tools/common/promptUser.ts
923
1004
  var promptUserTool = {
924
1005
  definition: {
925
1006
  name: "promptUser",
@@ -948,7 +1029,7 @@ var promptUserTool = {
948
1029
  type: {
949
1030
  type: "string",
950
1031
  enum: ["select", "checklist", "text", "file", "color"],
951
- description: "select: pick one from a list. checklist: pick one or more from a list. text: free-form input. file: file/image upload, returns CDN URL(s) that can be referenced directly or curled onto disk. color: color picker (returns hex)."
1032
+ description: 'select: pick one from a list. checklist: pick one or more from a list. The user can always provide a custom "Other" answer for select and checklist questions, so there is no need to include an "Other" option. text: free-form input. file: file/image upload, returns CDN URL(s) that can be referenced directly or curled onto disk. color: color picker (returns hex).'
952
1033
  },
953
1034
  helpText: {
954
1035
  type: "string",
@@ -985,10 +1066,6 @@ var promptUserTool = {
985
1066
  type: "boolean",
986
1067
  description: "For file type: allow multiple uploads (returns array of URLs). Defaults to false."
987
1068
  },
988
- allowOther: {
989
- type: "boolean",
990
- description: 'For select and checklist types: adds an "Other" option that lets the user type a custom answer. Use this instead of adding a separate follow-up text field for custom input. Defaults to false.'
991
- },
992
1069
  format: {
993
1070
  type: "string",
994
1071
  enum: ["email", "url", "phone", "number"],
@@ -1056,113 +1133,160 @@ ${lines.join("\n")}`;
1056
1133
  }
1057
1134
  };
1058
1135
 
1059
- // src/tools/spec/clearSyncStatus.ts
1060
- var clearSyncStatusTool = {
1061
- definition: {
1062
- name: "clearSyncStatus",
1063
- description: "Clear the sync status flags after syncing spec and code. Call this after finishing a sync operation.",
1064
- inputSchema: {
1065
- type: "object",
1066
- properties: {}
1067
- }
1068
- },
1069
- async execute() {
1070
- return "ok";
1071
- }
1072
- };
1073
-
1074
- // src/tools/spec/presentSyncPlan.ts
1075
- var presentSyncPlanTool = {
1136
+ // src/tools/common/confirmDestructiveAction.ts
1137
+ var confirmDestructiveActionTool = {
1076
1138
  definition: {
1077
- name: "presentSyncPlan",
1078
- 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.",
1139
+ name: "confirmDestructiveAction",
1140
+ 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.",
1079
1141
  inputSchema: {
1080
1142
  type: "object",
1081
1143
  properties: {
1082
- content: {
1144
+ message: {
1083
1145
  type: "string",
1084
- description: "Markdown plan describing what changed and what will be updated."
1146
+ description: "Explanation of what is about to happen and why confirmation is needed."
1147
+ },
1148
+ confirmLabel: {
1149
+ type: "string",
1150
+ description: 'Custom label for the confirm button (e.g., "Delete", "Reset Database"). Defaults to "Confirm".'
1151
+ },
1152
+ dismissLabel: {
1153
+ type: "string",
1154
+ description: 'Custom label for the dismiss button (e.g., "Keep It", "Go Back"). Defaults to "Cancel".'
1085
1155
  }
1086
1156
  },
1087
- required: ["content"]
1157
+ required: ["message"]
1088
1158
  }
1089
1159
  },
1090
- streaming: {},
1091
1160
  async execute() {
1092
- return "approved";
1161
+ return "confirmed";
1093
1162
  }
1094
1163
  };
1095
1164
 
1096
- // src/tools/spec/presentPublishPlan.ts
1097
- var presentPublishPlanTool = {
1165
+ // src/tools/common/askMindStudioSdk.ts
1166
+ import { exec } from "child_process";
1167
+ var askMindStudioSdkTool = {
1098
1168
  definition: {
1099
- name: "presentPublishPlan",
1100
- 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.",
1169
+ name: "askMindStudioSdk",
1170
+ description: "Ask the MindStudio SDK assistant about available actions, AI models, connectors, and integrations using natural language. Returns code examples with correct method signatures, model IDs, and config options. Always use this to verify correct SDK usage, especially model IDs and configuration options. Describe what you need, not what API methods you need; the assistant will figure out the right approach. This runs its own LLM call so it has a few seconds of latency; batch multiple questions into a single query.",
1101
1171
  inputSchema: {
1102
1172
  type: "object",
1103
1173
  properties: {
1104
- content: {
1174
+ query: {
1105
1175
  type: "string",
1106
- description: "Markdown changelog describing what changed and what will be deployed."
1176
+ description: "Natural language question about the SDK."
1107
1177
  }
1108
1178
  },
1109
- required: ["content"]
1179
+ required: ["query"]
1110
1180
  }
1111
1181
  },
1112
- streaming: {},
1113
- async execute() {
1114
- return "approved";
1182
+ async execute(input) {
1183
+ const query = input.query;
1184
+ return new Promise((resolve) => {
1185
+ exec(
1186
+ `mindstudio ask ${JSON.stringify(query)}`,
1187
+ { timeout: 6e4, maxBuffer: 512 * 1024 },
1188
+ (err, stdout, stderr) => {
1189
+ if (stdout.trim()) {
1190
+ resolve(stdout.trim());
1191
+ return;
1192
+ }
1193
+ if (err) {
1194
+ resolve(`Error: ${stderr.trim() || err.message}`);
1195
+ return;
1196
+ }
1197
+ resolve("(no response)");
1198
+ }
1199
+ );
1200
+ });
1115
1201
  }
1116
1202
  };
1117
1203
 
1118
- // src/tools/spec/presentPlan.ts
1119
- var presentPlanTool = {
1204
+ // src/tools/common/fetchUrl.ts
1205
+ import { exec as exec2 } from "child_process";
1206
+ var fetchUrlTool = {
1120
1207
  definition: {
1121
- name: "presentPlan",
1122
- description: "Present an implementation plan for user approval before making changes. Use this only for large, multi-step changes 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.",
1208
+ name: "fetchUrl",
1209
+ description: "Fetch the content of a web page. Returns the page as markdown text. Optionally capture a screenshot if you need see the visual design.",
1123
1210
  inputSchema: {
1124
1211
  type: "object",
1125
1212
  properties: {
1126
- content: {
1213
+ url: {
1127
1214
  type: "string",
1128
- description: "Markdown plan describing what you intend to do."
1215
+ description: "The URL to fetch."
1216
+ },
1217
+ screenshot: {
1218
+ type: "boolean",
1219
+ description: "Capture a screenshot of the page in addition to the text content. Adds latency; only use when you need to see the visual design."
1129
1220
  }
1130
1221
  },
1131
- required: ["content"]
1222
+ required: ["url"]
1132
1223
  }
1133
1224
  },
1134
- streaming: {},
1135
- async execute() {
1136
- return "approved";
1225
+ async execute(input) {
1226
+ const url = input.url;
1227
+ const screenshot = input.screenshot;
1228
+ const pageOptions = { onlyMainContent: true };
1229
+ if (screenshot) {
1230
+ pageOptions.screenshot = true;
1231
+ }
1232
+ const cmd = `mindstudio scrape-url --url ${JSON.stringify(url)} --page-options ${JSON.stringify(JSON.stringify(pageOptions))} --no-meta`;
1233
+ return new Promise((resolve) => {
1234
+ exec2(
1235
+ cmd,
1236
+ { timeout: 6e4, maxBuffer: 1024 * 1024 },
1237
+ (err, stdout, stderr) => {
1238
+ if (stdout.trim()) {
1239
+ resolve(stdout.trim());
1240
+ return;
1241
+ }
1242
+ if (err) {
1243
+ resolve(`Error: ${stderr.trim() || err.message}`);
1244
+ return;
1245
+ }
1246
+ resolve("(no response)");
1247
+ }
1248
+ );
1249
+ });
1137
1250
  }
1138
1251
  };
1139
1252
 
1140
- // src/tools/spec/confirmDestructiveAction.ts
1141
- var confirmDestructiveActionTool = {
1253
+ // src/tools/common/searchGoogle.ts
1254
+ import { exec as exec3 } from "child_process";
1255
+ var searchGoogleTool = {
1142
1256
  definition: {
1143
- name: "confirmDestructiveAction",
1144
- 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.",
1257
+ name: "searchGoogle",
1258
+ description: "Search Google and return results. Use for research, finding documentation, looking up APIs, or any task where web search would help.",
1145
1259
  inputSchema: {
1146
1260
  type: "object",
1147
1261
  properties: {
1148
- message: {
1149
- type: "string",
1150
- description: "Explanation of what is about to happen and why confirmation is needed."
1151
- },
1152
- confirmLabel: {
1153
- type: "string",
1154
- description: 'Custom label for the confirm button (e.g., "Delete", "Reset Database"). Defaults to "Confirm".'
1155
- },
1156
- dismissLabel: {
1262
+ query: {
1157
1263
  type: "string",
1158
- description: 'Custom label for the dismiss button (e.g., "Keep It", "Go Back"). Defaults to "Cancel".'
1264
+ description: "The search query."
1159
1265
  }
1160
1266
  },
1161
- required: ["message"]
1267
+ required: ["query"]
1162
1268
  }
1163
1269
  },
1164
- async execute() {
1165
- return "confirmed";
1270
+ async execute(input) {
1271
+ const query = input.query;
1272
+ const cmd = `mindstudio search-google --query ${JSON.stringify(query)} --export-type json --output-key results --no-meta`;
1273
+ return new Promise((resolve) => {
1274
+ exec3(
1275
+ cmd,
1276
+ { timeout: 6e4, maxBuffer: 512 * 1024 },
1277
+ (err, stdout, stderr) => {
1278
+ if (stdout.trim()) {
1279
+ resolve(stdout.trim());
1280
+ return;
1281
+ }
1282
+ if (err) {
1283
+ resolve(`Error: ${stderr.trim() || err.message}`);
1284
+ return;
1285
+ }
1286
+ resolve("(no response)");
1287
+ }
1288
+ );
1289
+ });
1166
1290
  }
1167
1291
  };
1168
1292
 
@@ -1466,7 +1590,7 @@ ${unifiedDiff(input.path, content, updated)}`;
1466
1590
  };
1467
1591
 
1468
1592
  // src/tools/code/bash.ts
1469
- import { exec } from "child_process";
1593
+ import { exec as exec4 } from "child_process";
1470
1594
  var DEFAULT_TIMEOUT_MS = 12e4;
1471
1595
  var DEFAULT_MAX_LINES3 = 500;
1472
1596
  var bashTool = {
@@ -1500,7 +1624,7 @@ var bashTool = {
1500
1624
  const maxLines = input.maxLines === 0 ? Infinity : input.maxLines || DEFAULT_MAX_LINES3;
1501
1625
  const timeoutMs = input.timeout ? input.timeout * 1e3 : DEFAULT_TIMEOUT_MS;
1502
1626
  return new Promise((resolve) => {
1503
- exec(
1627
+ exec4(
1504
1628
  input.command,
1505
1629
  {
1506
1630
  timeout: timeoutMs,
@@ -1540,7 +1664,7 @@ var bashTool = {
1540
1664
  };
1541
1665
 
1542
1666
  // src/tools/code/grep.ts
1543
- import { exec as exec2 } from "child_process";
1667
+ import { exec as exec5 } from "child_process";
1544
1668
  var DEFAULT_MAX = 50;
1545
1669
  function formatResults(stdout, max) {
1546
1670
  const lines = stdout.trim().split("\n");
@@ -1587,12 +1711,12 @@ var grepTool = {
1587
1711
  const rgCmd = `rg -n --no-heading --max-count=${max}${globFlag} '${escaped}' ${searchPath}`;
1588
1712
  const grepCmd = `grep -rn --max-count=${max} '${escaped}' ${searchPath} --include='*.ts' --include='*.tsx' --include='*.js' --include='*.json' --include='*.md'`;
1589
1713
  return new Promise((resolve) => {
1590
- exec2(rgCmd, { maxBuffer: 512 * 1024 }, (err, stdout) => {
1714
+ exec5(rgCmd, { maxBuffer: 512 * 1024 }, (err, stdout) => {
1591
1715
  if (stdout?.trim()) {
1592
1716
  resolve(formatResults(stdout, max));
1593
1717
  return;
1594
1718
  }
1595
- exec2(grepCmd, { maxBuffer: 512 * 1024 }, (_err, grepStdout) => {
1719
+ exec5(grepCmd, { maxBuffer: 512 * 1024 }, (_err, grepStdout) => {
1596
1720
  if (grepStdout?.trim()) {
1597
1721
  resolve(formatResults(grepStdout, max));
1598
1722
  } else {
@@ -1776,45 +1900,6 @@ var restartProcessTool = {
1776
1900
  }
1777
1901
  };
1778
1902
 
1779
- // src/tools/code/askMindStudioSdk.ts
1780
- import { exec as exec3 } from "child_process";
1781
- var askMindStudioSdkTool = {
1782
- definition: {
1783
- name: "askMindStudioSdk",
1784
- description: "Ask the MindStudio SDK assistant about available actions, AI models, connectors, and integrations using natural language. Returns code examples with correct method signatures, model IDs, and config options. Always use this to verify correct SDK usage, especially model IDs and configuration options. Describe what you need, not what API methods you need; the assistant will figure out the right approach. This runs its own LLM call so it has a few seconds of latency; batch multiple questions into a single query.",
1785
- inputSchema: {
1786
- type: "object",
1787
- properties: {
1788
- query: {
1789
- type: "string",
1790
- description: "Natural language question about the SDK."
1791
- }
1792
- },
1793
- required: ["query"]
1794
- }
1795
- },
1796
- async execute(input) {
1797
- const query = input.query;
1798
- return new Promise((resolve) => {
1799
- exec3(
1800
- `mindstudio ask ${JSON.stringify(query)}`,
1801
- { timeout: 6e4, maxBuffer: 512 * 1024 },
1802
- (err, stdout, stderr) => {
1803
- if (stdout.trim()) {
1804
- resolve(stdout.trim());
1805
- return;
1806
- }
1807
- if (err) {
1808
- resolve(`Error: ${stderr.trim() || err.message}`);
1809
- return;
1810
- }
1811
- resolve("(no response)");
1812
- }
1813
- );
1814
- });
1815
- }
1816
- };
1817
-
1818
1903
  // src/tools/code/runScenario.ts
1819
1904
  var runScenarioTool = {
1820
1905
  definition: {
@@ -2135,7 +2220,6 @@ function getCodeTools() {
2135
2220
  globTool,
2136
2221
  listDirTool,
2137
2222
  editsFinishedTool,
2138
- askMindStudioSdkTool,
2139
2223
  runScenarioTool,
2140
2224
  runMethodTool,
2141
2225
  screenshotTool,
@@ -2150,7 +2234,10 @@ function getCommonTools() {
2150
2234
  return [
2151
2235
  setProjectOnboardingStateTool,
2152
2236
  promptUserTool,
2153
- confirmDestructiveActionTool
2237
+ confirmDestructiveActionTool,
2238
+ askMindStudioSdkTool,
2239
+ fetchUrlTool,
2240
+ searchGoogleTool
2154
2241
  ];
2155
2242
  }
2156
2243
  function getPostOnboardingTools() {
package/dist/index.js CHANGED
@@ -634,10 +634,115 @@ var init_listSpecFiles = __esm({
634
634
  }
635
635
  });
636
636
 
637
- // src/tools/spec/setProjectOnboardingState.ts
637
+ // src/tools/spec/clearSyncStatus.ts
638
+ var clearSyncStatusTool;
639
+ var init_clearSyncStatus = __esm({
640
+ "src/tools/spec/clearSyncStatus.ts"() {
641
+ "use strict";
642
+ clearSyncStatusTool = {
643
+ definition: {
644
+ name: "clearSyncStatus",
645
+ description: "Clear the sync status flags after syncing spec and code. Call this after finishing a sync operation.",
646
+ inputSchema: {
647
+ type: "object",
648
+ properties: {}
649
+ }
650
+ },
651
+ async execute() {
652
+ return "ok";
653
+ }
654
+ };
655
+ }
656
+ });
657
+
658
+ // src/tools/spec/presentSyncPlan.ts
659
+ var presentSyncPlanTool;
660
+ var init_presentSyncPlan = __esm({
661
+ "src/tools/spec/presentSyncPlan.ts"() {
662
+ "use strict";
663
+ presentSyncPlanTool = {
664
+ definition: {
665
+ name: "presentSyncPlan",
666
+ 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.",
667
+ inputSchema: {
668
+ type: "object",
669
+ properties: {
670
+ content: {
671
+ type: "string",
672
+ description: "Markdown plan describing what changed and what will be updated."
673
+ }
674
+ },
675
+ required: ["content"]
676
+ }
677
+ },
678
+ streaming: {},
679
+ async execute() {
680
+ return "approved";
681
+ }
682
+ };
683
+ }
684
+ });
685
+
686
+ // src/tools/spec/presentPublishPlan.ts
687
+ var presentPublishPlanTool;
688
+ var init_presentPublishPlan = __esm({
689
+ "src/tools/spec/presentPublishPlan.ts"() {
690
+ "use strict";
691
+ presentPublishPlanTool = {
692
+ definition: {
693
+ name: "presentPublishPlan",
694
+ 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.",
695
+ inputSchema: {
696
+ type: "object",
697
+ properties: {
698
+ content: {
699
+ type: "string",
700
+ description: "Markdown changelog describing what changed and what will be deployed."
701
+ }
702
+ },
703
+ required: ["content"]
704
+ }
705
+ },
706
+ streaming: {},
707
+ async execute() {
708
+ return "approved";
709
+ }
710
+ };
711
+ }
712
+ });
713
+
714
+ // src/tools/spec/presentPlan.ts
715
+ var presentPlanTool;
716
+ var init_presentPlan = __esm({
717
+ "src/tools/spec/presentPlan.ts"() {
718
+ "use strict";
719
+ presentPlanTool = {
720
+ definition: {
721
+ name: "presentPlan",
722
+ description: "Present an implementation plan for user approval before making changes. Use this only for large, multi-step changes 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.",
723
+ inputSchema: {
724
+ type: "object",
725
+ properties: {
726
+ content: {
727
+ type: "string",
728
+ description: "Markdown plan describing what you intend to do."
729
+ }
730
+ },
731
+ required: ["content"]
732
+ }
733
+ },
734
+ streaming: {},
735
+ async execute() {
736
+ return "approved";
737
+ }
738
+ };
739
+ }
740
+ });
741
+
742
+ // src/tools/common/setProjectOnboardingState.ts
638
743
  var setProjectOnboardingStateTool;
639
744
  var init_setProjectOnboardingState = __esm({
640
- "src/tools/spec/setProjectOnboardingState.ts"() {
745
+ "src/tools/common/setProjectOnboardingState.ts"() {
641
746
  "use strict";
642
747
  setProjectOnboardingStateTool = {
643
748
  definition: {
@@ -666,10 +771,10 @@ var init_setProjectOnboardingState = __esm({
666
771
  }
667
772
  });
668
773
 
669
- // src/tools/spec/promptUser.ts
774
+ // src/tools/common/promptUser.ts
670
775
  var promptUserTool;
671
776
  var init_promptUser = __esm({
672
- "src/tools/spec/promptUser.ts"() {
777
+ "src/tools/common/promptUser.ts"() {
673
778
  "use strict";
674
779
  promptUserTool = {
675
780
  definition: {
@@ -699,7 +804,7 @@ var init_promptUser = __esm({
699
804
  type: {
700
805
  type: "string",
701
806
  enum: ["select", "checklist", "text", "file", "color"],
702
- description: "select: pick one from a list. checklist: pick one or more from a list. text: free-form input. file: file/image upload, returns CDN URL(s) that can be referenced directly or curled onto disk. color: color picker (returns hex)."
807
+ description: 'select: pick one from a list. checklist: pick one or more from a list. The user can always provide a custom "Other" answer for select and checklist questions, so there is no need to include an "Other" option. text: free-form input. file: file/image upload, returns CDN URL(s) that can be referenced directly or curled onto disk. color: color picker (returns hex).'
703
808
  },
704
809
  helpText: {
705
810
  type: "string",
@@ -736,10 +841,6 @@ var init_promptUser = __esm({
736
841
  type: "boolean",
737
842
  description: "For file type: allow multiple uploads (returns array of URLs). Defaults to false."
738
843
  },
739
- allowOther: {
740
- type: "boolean",
741
- description: 'For select and checklist types: adds an "Other" option that lets the user type a custom answer. Use this instead of adding a separate follow-up text field for custom input. Defaults to false.'
742
- },
743
844
  format: {
744
845
  type: "string",
745
846
  enum: ["email", "url", "phone", "number"],
@@ -809,141 +910,182 @@ ${lines.join("\n")}`;
809
910
  }
810
911
  });
811
912
 
812
- // src/tools/spec/clearSyncStatus.ts
813
- var clearSyncStatusTool;
814
- var init_clearSyncStatus = __esm({
815
- "src/tools/spec/clearSyncStatus.ts"() {
816
- "use strict";
817
- clearSyncStatusTool = {
818
- definition: {
819
- name: "clearSyncStatus",
820
- description: "Clear the sync status flags after syncing spec and code. Call this after finishing a sync operation.",
821
- inputSchema: {
822
- type: "object",
823
- properties: {}
824
- }
825
- },
826
- async execute() {
827
- return "ok";
828
- }
829
- };
830
- }
831
- });
832
-
833
- // src/tools/spec/presentSyncPlan.ts
834
- var presentSyncPlanTool;
835
- var init_presentSyncPlan = __esm({
836
- "src/tools/spec/presentSyncPlan.ts"() {
913
+ // src/tools/common/confirmDestructiveAction.ts
914
+ var confirmDestructiveActionTool;
915
+ var init_confirmDestructiveAction = __esm({
916
+ "src/tools/common/confirmDestructiveAction.ts"() {
837
917
  "use strict";
838
- presentSyncPlanTool = {
918
+ confirmDestructiveActionTool = {
839
919
  definition: {
840
- name: "presentSyncPlan",
841
- 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.",
920
+ name: "confirmDestructiveAction",
921
+ 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.",
842
922
  inputSchema: {
843
923
  type: "object",
844
924
  properties: {
845
- content: {
925
+ message: {
846
926
  type: "string",
847
- description: "Markdown plan describing what changed and what will be updated."
927
+ description: "Explanation of what is about to happen and why confirmation is needed."
928
+ },
929
+ confirmLabel: {
930
+ type: "string",
931
+ description: 'Custom label for the confirm button (e.g., "Delete", "Reset Database"). Defaults to "Confirm".'
932
+ },
933
+ dismissLabel: {
934
+ type: "string",
935
+ description: 'Custom label for the dismiss button (e.g., "Keep It", "Go Back"). Defaults to "Cancel".'
848
936
  }
849
937
  },
850
- required: ["content"]
938
+ required: ["message"]
851
939
  }
852
940
  },
853
- streaming: {},
854
941
  async execute() {
855
- return "approved";
942
+ return "confirmed";
856
943
  }
857
944
  };
858
945
  }
859
946
  });
860
947
 
861
- // src/tools/spec/presentPublishPlan.ts
862
- var presentPublishPlanTool;
863
- var init_presentPublishPlan = __esm({
864
- "src/tools/spec/presentPublishPlan.ts"() {
948
+ // src/tools/common/askMindStudioSdk.ts
949
+ import { exec } from "child_process";
950
+ var askMindStudioSdkTool;
951
+ var init_askMindStudioSdk = __esm({
952
+ "src/tools/common/askMindStudioSdk.ts"() {
865
953
  "use strict";
866
- presentPublishPlanTool = {
954
+ askMindStudioSdkTool = {
867
955
  definition: {
868
- name: "presentPublishPlan",
869
- 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.",
956
+ name: "askMindStudioSdk",
957
+ description: "Ask the MindStudio SDK assistant about available actions, AI models, connectors, and integrations using natural language. Returns code examples with correct method signatures, model IDs, and config options. Always use this to verify correct SDK usage, especially model IDs and configuration options. Describe what you need, not what API methods you need; the assistant will figure out the right approach. This runs its own LLM call so it has a few seconds of latency; batch multiple questions into a single query.",
870
958
  inputSchema: {
871
959
  type: "object",
872
960
  properties: {
873
- content: {
961
+ query: {
874
962
  type: "string",
875
- description: "Markdown changelog describing what changed and what will be deployed."
963
+ description: "Natural language question about the SDK."
876
964
  }
877
965
  },
878
- required: ["content"]
966
+ required: ["query"]
879
967
  }
880
968
  },
881
- streaming: {},
882
- async execute() {
883
- return "approved";
969
+ async execute(input) {
970
+ const query = input.query;
971
+ return new Promise((resolve) => {
972
+ exec(
973
+ `mindstudio ask ${JSON.stringify(query)}`,
974
+ { timeout: 6e4, maxBuffer: 512 * 1024 },
975
+ (err, stdout, stderr) => {
976
+ if (stdout.trim()) {
977
+ resolve(stdout.trim());
978
+ return;
979
+ }
980
+ if (err) {
981
+ resolve(`Error: ${stderr.trim() || err.message}`);
982
+ return;
983
+ }
984
+ resolve("(no response)");
985
+ }
986
+ );
987
+ });
884
988
  }
885
989
  };
886
990
  }
887
991
  });
888
992
 
889
- // src/tools/spec/presentPlan.ts
890
- var presentPlanTool;
891
- var init_presentPlan = __esm({
892
- "src/tools/spec/presentPlan.ts"() {
993
+ // src/tools/common/fetchUrl.ts
994
+ import { exec as exec2 } from "child_process";
995
+ var fetchUrlTool;
996
+ var init_fetchUrl = __esm({
997
+ "src/tools/common/fetchUrl.ts"() {
893
998
  "use strict";
894
- presentPlanTool = {
999
+ fetchUrlTool = {
895
1000
  definition: {
896
- name: "presentPlan",
897
- description: "Present an implementation plan for user approval before making changes. Use this only for large, multi-step changes 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.",
1001
+ name: "fetchUrl",
1002
+ description: "Fetch the content of a web page. Returns the page as markdown text. Optionally capture a screenshot if you need see the visual design.",
898
1003
  inputSchema: {
899
1004
  type: "object",
900
1005
  properties: {
901
- content: {
1006
+ url: {
902
1007
  type: "string",
903
- description: "Markdown plan describing what you intend to do."
1008
+ description: "The URL to fetch."
1009
+ },
1010
+ screenshot: {
1011
+ type: "boolean",
1012
+ description: "Capture a screenshot of the page in addition to the text content. Adds latency; only use when you need to see the visual design."
904
1013
  }
905
1014
  },
906
- required: ["content"]
1015
+ required: ["url"]
907
1016
  }
908
1017
  },
909
- streaming: {},
910
- async execute() {
911
- return "approved";
1018
+ async execute(input) {
1019
+ const url = input.url;
1020
+ const screenshot = input.screenshot;
1021
+ const pageOptions = { onlyMainContent: true };
1022
+ if (screenshot) {
1023
+ pageOptions.screenshot = true;
1024
+ }
1025
+ const cmd = `mindstudio scrape-url --url ${JSON.stringify(url)} --page-options ${JSON.stringify(JSON.stringify(pageOptions))} --no-meta`;
1026
+ return new Promise((resolve) => {
1027
+ exec2(
1028
+ cmd,
1029
+ { timeout: 6e4, maxBuffer: 1024 * 1024 },
1030
+ (err, stdout, stderr) => {
1031
+ if (stdout.trim()) {
1032
+ resolve(stdout.trim());
1033
+ return;
1034
+ }
1035
+ if (err) {
1036
+ resolve(`Error: ${stderr.trim() || err.message}`);
1037
+ return;
1038
+ }
1039
+ resolve("(no response)");
1040
+ }
1041
+ );
1042
+ });
912
1043
  }
913
1044
  };
914
1045
  }
915
1046
  });
916
1047
 
917
- // src/tools/spec/confirmDestructiveAction.ts
918
- var confirmDestructiveActionTool;
919
- var init_confirmDestructiveAction = __esm({
920
- "src/tools/spec/confirmDestructiveAction.ts"() {
1048
+ // src/tools/common/searchGoogle.ts
1049
+ import { exec as exec3 } from "child_process";
1050
+ var searchGoogleTool;
1051
+ var init_searchGoogle = __esm({
1052
+ "src/tools/common/searchGoogle.ts"() {
921
1053
  "use strict";
922
- confirmDestructiveActionTool = {
1054
+ searchGoogleTool = {
923
1055
  definition: {
924
- name: "confirmDestructiveAction",
925
- 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.",
1056
+ name: "searchGoogle",
1057
+ description: "Search Google and return results. Use for research, finding documentation, looking up APIs, or any task where web search would help.",
926
1058
  inputSchema: {
927
1059
  type: "object",
928
1060
  properties: {
929
- message: {
930
- type: "string",
931
- description: "Explanation of what is about to happen and why confirmation is needed."
932
- },
933
- confirmLabel: {
934
- type: "string",
935
- description: 'Custom label for the confirm button (e.g., "Delete", "Reset Database"). Defaults to "Confirm".'
936
- },
937
- dismissLabel: {
1061
+ query: {
938
1062
  type: "string",
939
- description: 'Custom label for the dismiss button (e.g., "Keep It", "Go Back"). Defaults to "Cancel".'
1063
+ description: "The search query."
940
1064
  }
941
1065
  },
942
- required: ["message"]
1066
+ required: ["query"]
943
1067
  }
944
1068
  },
945
- async execute() {
946
- return "confirmed";
1069
+ async execute(input) {
1070
+ const query = input.query;
1071
+ const cmd = `mindstudio search-google --query ${JSON.stringify(query)} --export-type json --output-key results --no-meta`;
1072
+ return new Promise((resolve) => {
1073
+ exec3(
1074
+ cmd,
1075
+ { timeout: 6e4, maxBuffer: 512 * 1024 },
1076
+ (err, stdout, stderr) => {
1077
+ if (stdout.trim()) {
1078
+ resolve(stdout.trim());
1079
+ return;
1080
+ }
1081
+ if (err) {
1082
+ resolve(`Error: ${stderr.trim() || err.message}`);
1083
+ return;
1084
+ }
1085
+ resolve("(no response)");
1086
+ }
1087
+ );
1088
+ });
947
1089
  }
948
1090
  };
949
1091
  }
@@ -1273,7 +1415,7 @@ ${unifiedDiff(input.path, content, updated)}`;
1273
1415
  });
1274
1416
 
1275
1417
  // src/tools/code/bash.ts
1276
- import { exec } from "child_process";
1418
+ import { exec as exec4 } from "child_process";
1277
1419
  var DEFAULT_TIMEOUT_MS, DEFAULT_MAX_LINES3, bashTool;
1278
1420
  var init_bash = __esm({
1279
1421
  "src/tools/code/bash.ts"() {
@@ -1311,7 +1453,7 @@ var init_bash = __esm({
1311
1453
  const maxLines = input.maxLines === 0 ? Infinity : input.maxLines || DEFAULT_MAX_LINES3;
1312
1454
  const timeoutMs = input.timeout ? input.timeout * 1e3 : DEFAULT_TIMEOUT_MS;
1313
1455
  return new Promise((resolve) => {
1314
- exec(
1456
+ exec4(
1315
1457
  input.command,
1316
1458
  {
1317
1459
  timeout: timeoutMs,
@@ -1353,7 +1495,7 @@ var init_bash = __esm({
1353
1495
  });
1354
1496
 
1355
1497
  // src/tools/code/grep.ts
1356
- import { exec as exec2 } from "child_process";
1498
+ import { exec as exec5 } from "child_process";
1357
1499
  function formatResults(stdout, max) {
1358
1500
  const lines = stdout.trim().split("\n");
1359
1501
  let result = lines.join("\n");
@@ -1404,12 +1546,12 @@ var init_grep = __esm({
1404
1546
  const rgCmd = `rg -n --no-heading --max-count=${max}${globFlag} '${escaped}' ${searchPath}`;
1405
1547
  const grepCmd = `grep -rn --max-count=${max} '${escaped}' ${searchPath} --include='*.ts' --include='*.tsx' --include='*.js' --include='*.json' --include='*.md'`;
1406
1548
  return new Promise((resolve) => {
1407
- exec2(rgCmd, { maxBuffer: 512 * 1024 }, (err, stdout) => {
1549
+ exec5(rgCmd, { maxBuffer: 512 * 1024 }, (err, stdout) => {
1408
1550
  if (stdout?.trim()) {
1409
1551
  resolve(formatResults(stdout, max));
1410
1552
  return;
1411
1553
  }
1412
- exec2(grepCmd, { maxBuffer: 512 * 1024 }, (_err, grepStdout) => {
1554
+ exec5(grepCmd, { maxBuffer: 512 * 1024 }, (_err, grepStdout) => {
1413
1555
  if (grepStdout?.trim()) {
1414
1556
  resolve(formatResults(grepStdout, max));
1415
1557
  } else {
@@ -1669,51 +1811,6 @@ var init_restartProcess = __esm({
1669
1811
  }
1670
1812
  });
1671
1813
 
1672
- // src/tools/code/askMindStudioSdk.ts
1673
- import { exec as exec3 } from "child_process";
1674
- var askMindStudioSdkTool;
1675
- var init_askMindStudioSdk = __esm({
1676
- "src/tools/code/askMindStudioSdk.ts"() {
1677
- "use strict";
1678
- askMindStudioSdkTool = {
1679
- definition: {
1680
- name: "askMindStudioSdk",
1681
- description: "Ask the MindStudio SDK assistant about available actions, AI models, connectors, and integrations using natural language. Returns code examples with correct method signatures, model IDs, and config options. Always use this to verify correct SDK usage, especially model IDs and configuration options. Describe what you need, not what API methods you need; the assistant will figure out the right approach. This runs its own LLM call so it has a few seconds of latency; batch multiple questions into a single query.",
1682
- inputSchema: {
1683
- type: "object",
1684
- properties: {
1685
- query: {
1686
- type: "string",
1687
- description: "Natural language question about the SDK."
1688
- }
1689
- },
1690
- required: ["query"]
1691
- }
1692
- },
1693
- async execute(input) {
1694
- const query = input.query;
1695
- return new Promise((resolve) => {
1696
- exec3(
1697
- `mindstudio ask ${JSON.stringify(query)}`,
1698
- { timeout: 6e4, maxBuffer: 512 * 1024 },
1699
- (err, stdout, stderr) => {
1700
- if (stdout.trim()) {
1701
- resolve(stdout.trim());
1702
- return;
1703
- }
1704
- if (err) {
1705
- resolve(`Error: ${stderr.trim() || err.message}`);
1706
- return;
1707
- }
1708
- resolve("(no response)");
1709
- }
1710
- );
1711
- });
1712
- }
1713
- };
1714
- }
1715
- });
1716
-
1717
1814
  // src/tools/code/runScenario.ts
1718
1815
  var runScenarioTool;
1719
1816
  var init_runScenario = __esm({
@@ -2080,7 +2177,6 @@ function getCodeTools() {
2080
2177
  globTool,
2081
2178
  listDirTool,
2082
2179
  editsFinishedTool,
2083
- askMindStudioSdkTool,
2084
2180
  runScenarioTool,
2085
2181
  runMethodTool,
2086
2182
  screenshotTool,
@@ -2095,7 +2191,10 @@ function getCommonTools() {
2095
2191
  return [
2096
2192
  setProjectOnboardingStateTool,
2097
2193
  promptUserTool,
2098
- confirmDestructiveActionTool
2194
+ confirmDestructiveActionTool,
2195
+ askMindStudioSdkTool,
2196
+ fetchUrlTool,
2197
+ searchGoogleTool
2099
2198
  ];
2100
2199
  }
2101
2200
  function getPostOnboardingTools() {
@@ -2147,13 +2246,16 @@ var init_tools2 = __esm({
2147
2246
  init_writeSpec();
2148
2247
  init_editSpec();
2149
2248
  init_listSpecFiles();
2150
- init_setProjectOnboardingState();
2151
- init_promptUser();
2152
2249
  init_clearSyncStatus();
2153
2250
  init_presentSyncPlan();
2154
2251
  init_presentPublishPlan();
2155
2252
  init_presentPlan();
2253
+ init_setProjectOnboardingState();
2254
+ init_promptUser();
2156
2255
  init_confirmDestructiveAction();
2256
+ init_askMindStudioSdk();
2257
+ init_fetchUrl();
2258
+ init_searchGoogle();
2157
2259
  init_readFile();
2158
2260
  init_writeFile();
2159
2261
  init_editFile();
@@ -2165,7 +2267,6 @@ var init_tools2 = __esm({
2165
2267
  init_lsp();
2166
2268
  init_lspDiagnostics();
2167
2269
  init_restartProcess();
2168
- init_askMindStudioSdk();
2169
2270
  init_runScenario();
2170
2271
  init_runMethod();
2171
2272
  init_screenshot();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "MindStudio coding agent",
5
5
  "repository": {
6
6
  "type": "git",