@mindstudio-ai/remy 0.1.267 → 0.1.269

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
@@ -618,7 +618,6 @@ function readJsonAsset(fallback, ...segments) {
618
618
 
619
619
  // src/prompt/static/projectContext.ts
620
620
  import fs4 from "fs";
621
- import path3 from "path";
622
621
 
623
622
  // src/projectRoot.ts
624
623
  var PROJECT_ROOT = process.cwd();
@@ -631,78 +630,23 @@ function loadProjectRoot() {
631
630
 
632
631
  File paths are relative to this directory. Every tool operates here and bash commands run it it.`;
633
632
  }
634
- function loadProjectManifest() {
635
- try {
636
- const manifest = fs4.readFileSync("mindstudio.json", "utf-8");
637
- return `
638
- ## Project Manifest (mindstudio.json)
639
- \`\`\`json
640
- ${manifest}
641
- \`\`\``;
642
- } catch {
643
- return "";
644
- }
645
- }
646
- function loadSpecFileMetadata() {
633
+ function loadAppIdentity() {
647
634
  try {
648
- const files = walkMdFiles("src");
649
- if (files.length === 0) {
635
+ const manifest = JSON.parse(fs4.readFileSync("mindstudio.json", "utf-8"));
636
+ const name = typeof manifest.name === "string" ? manifest.name.trim() : "";
637
+ if (!name) {
650
638
  return "";
651
639
  }
652
- const entries = [];
653
- for (const filePath of files) {
654
- const { name, description, type } = parseFrontmatter(filePath);
655
- let line = `- ${filePath}`;
656
- if (name) {
657
- line += ` \u2014 "${name}"`;
658
- }
659
- if (type) {
660
- line += ` (${type})`;
661
- }
662
- if (description) {
663
- line += ` \u2014 ${description}`;
664
- }
665
- entries.push(line);
666
- }
640
+ const description = typeof manifest.description === "string" ? manifest.description.trim() : "";
667
641
  return `
668
- ## Spec Files
669
- ${entries.join("\n")}`;
642
+ ## App
643
+ "${name}"${description ? ` \u2014 ${description}` : ""}
644
+
645
+ Full manifest: \`mindstudio.json\` (read it when you need the app's structure, tables, methods, roles, auth settings, interfaces, and everything else).`;
670
646
  } catch {
671
647
  return "";
672
648
  }
673
649
  }
674
- function walkMdFiles(dir) {
675
- const results = [];
676
- try {
677
- const entries = fs4.readdirSync(dir, { withFileTypes: true });
678
- for (const entry of entries) {
679
- const full = path3.join(dir, entry.name);
680
- if (entry.isDirectory()) {
681
- results.push(...walkMdFiles(full));
682
- } else if (entry.name.endsWith(".md")) {
683
- results.push(full);
684
- }
685
- }
686
- } catch {
687
- }
688
- return results.sort();
689
- }
690
- function parseFrontmatter(filePath) {
691
- try {
692
- const content = fs4.readFileSync(filePath, "utf-8");
693
- const match = content.match(/^---\n([\s\S]*?)\n---/);
694
- if (!match) {
695
- return { name: "", description: "", type: "" };
696
- }
697
- const fm = match[1];
698
- const name = fm.match(/^name:\s*(.+)$/m)?.[1]?.trim() ?? "";
699
- const description = fm.match(/^description:\s*(.+)$/m)?.[1]?.trim() ?? "";
700
- const type = fm.match(/^type:\s*(.+)$/m)?.[1]?.trim() ?? "";
701
- return { name, description, type };
702
- } catch {
703
- return { name: "", description: "", type: "" };
704
- }
705
- }
706
650
  function loadPlanStatus(onboardingState) {
707
651
  try {
708
652
  const content = fs4.readFileSync(".remy-plan.md", "utf-8");
@@ -731,33 +675,12 @@ The user has approved your implementation plan in .remy-plan.md. You may referen
731
675
  return "";
732
676
  }
733
677
  }
734
- function loadProjectFileListing() {
735
- try {
736
- const entries = fs4.readdirSync(".", { withFileTypes: true });
737
- const listing = entries.filter((e) => e.name !== ".git" && e.name !== "node_modules").sort((a, b) => {
738
- if (a.isDirectory() && !b.isDirectory()) {
739
- return -1;
740
- }
741
- if (!a.isDirectory() && b.isDirectory()) {
742
- return 1;
743
- }
744
- return a.name.localeCompare(b.name);
745
- }).map((e) => e.isDirectory() ? `${e.name}/` : e.name).join("\n");
746
- return `
747
- ## Project Files
748
- \`\`\`
749
- ${listing}
750
- \`\`\``;
751
- } catch {
752
- return "";
753
- }
754
- }
755
678
 
756
679
  // src/prompt/skills/catalog.ts
757
680
  import fs5 from "fs";
758
- import path4 from "path";
681
+ import path3 from "path";
759
682
  var SKILLS_DIR = assetPath("prompt", "skills");
760
- function parseFrontmatter2(content) {
683
+ function parseFrontmatter(content) {
761
684
  const match = content.match(/^---\n([\s\S]*?)\n---/);
762
685
  if (!match) {
763
686
  return {};
@@ -780,9 +703,9 @@ function loadCatalog() {
780
703
  }
781
704
  const skills = [];
782
705
  for (const file of files.sort()) {
783
- const full = path4.join(SKILLS_DIR, file);
706
+ const full = path3.join(SKILLS_DIR, file);
784
707
  const id = file.replace(/\.md$/, "");
785
- const fields = parseFrontmatter2(fs5.readFileSync(full, "utf-8"));
708
+ const fields = parseFrontmatter(fs5.readFileSync(full, "utf-8"));
786
709
  if (!fields.name || !fields.what || !fields.when) {
787
710
  continue;
788
711
  }
@@ -836,13 +759,7 @@ function resolveIncludes(template) {
836
759
  );
837
760
  return result.replace(/\n{3,}/g, "\n\n").trim();
838
761
  }
839
- function buildSystemPrompt(onboardingState, viewContext) {
840
- const projectContext = [
841
- loadProjectRoot(),
842
- loadProjectManifest(),
843
- loadSpecFileMetadata(),
844
- loadProjectFileListing()
845
- ].filter(Boolean).join("\n");
762
+ function buildSystemPrompt(onboardingState) {
846
763
  const now = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
847
764
  month: "long",
848
765
  day: "numeric",
@@ -851,8 +768,6 @@ function buildSystemPrompt(onboardingState, viewContext) {
851
768
  const template = `
852
769
  {{static/identity.md}}
853
770
 
854
- Current date: ${now}
855
-
856
771
  <platform_docs>
857
772
  <platform>
858
773
  {{compiled/platform.md}}
@@ -932,7 +847,7 @@ ${loadSkillsCatalog()}
932
847
  <conversation_summaries>
933
848
  Your conversation history may include <prior_conversation_summary> blocks in the user's messages. These are automated summaries of earlier messages that have been compacted to save context space. The user does not see this summary, they see the full conversation history in their UI. Treat the summary as ground truth for what happened before, but do not reference it directly to the user ("as mentioned in the summary..."). Just continue naturally as if you remember the prior work.
934
849
 
935
- Old tool results are periodically cleared from the conversation to save context space. This is automatic and expected \u2014 you don't need to note down or preserve information from tool results. If you need to reference something from an earlier tool call, just re-read the file or re-run the query.
850
+ Tool results generally persist in the conversation until a compaction summarizes them. In rare cases very old tool results may be trimmed when the conversation nears the context limit. Either way, if you need something from an earlier tool call and can't see it anymore, just re-read the file or re-run the query.
936
851
  </conversation_summaries>
937
852
 
938
853
  <project_onboarding>
@@ -944,24 +859,21 @@ New projects progress through three onboarding states. The user might skip this
944
859
  - **onboardingFinished**: The project is built and ready. Full development mode with all tools available. From here on, keep spec and code in sync as changes are made.
945
860
  </project_onboarding>
946
861
 
862
+ ${loadProjectRoot()}
863
+
864
+ ${renderOrgContextBlock()}
865
+
947
866
  {{static/instructions.md}}
948
867
 
949
868
  <!-- cache_breakpoint -->
950
869
 
870
+ Current date: ${now}
871
+
951
872
  <current_project_onboarding_state>
952
873
  ${onboardingState ?? "onboardingFinished"}
953
874
  </current_project_onboarding_state>
954
875
 
955
- <project_context>
956
- ${projectContext}
957
- </project_context>
958
-
959
- ${renderOrgContextBlock()}
960
-
961
- <view_context>
962
- The user is currently in ${viewContext?.mode ?? "code"} mode.
963
- ${viewContext?.activeFile ? `Active file: ${viewContext.activeFile}` : ""}
964
- </view_context>
876
+ ${loadAppIdentity()}
965
877
 
966
878
  ${loadPlanStatus(onboardingState)}
967
879
  `;
@@ -1043,7 +955,6 @@ function extractFrontmatter(content) {
1043
955
  var DEFAULT_MAX_LINES = 500;
1044
956
  var readSpecTool = {
1045
957
  definition: {
1046
- clearable: true,
1047
958
  name: "readSpec",
1048
959
  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).",
1049
960
  inputSchema: {
@@ -1101,7 +1012,7 @@ var readSpecTool = {
1101
1012
 
1102
1013
  // src/tools/spec/writeSpec.ts
1103
1014
  import fs7 from "fs/promises";
1104
- import path5 from "path";
1015
+ import path4 from "path";
1105
1016
 
1106
1017
  // src/tools/_helpers/diff.ts
1107
1018
  var CONTEXT_LINES = 3;
@@ -1157,7 +1068,6 @@ function acquireFileLock(filePath) {
1157
1068
  // src/tools/spec/writeSpec.ts
1158
1069
  var writeSpecTool = {
1159
1070
  definition: {
1160
- clearable: true,
1161
1071
  name: "writeSpec",
1162
1072
  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.",
1163
1073
  inputSchema: {
@@ -1191,7 +1101,7 @@ ${unifiedDiff(partial.path, oldContent, partial.content)}`;
1191
1101
  }
1192
1102
  const release = await acquireFileLock(input.path);
1193
1103
  try {
1194
- await fs7.mkdir(path5.dirname(input.path), { recursive: true });
1104
+ await fs7.mkdir(path4.dirname(input.path), { recursive: true });
1195
1105
  let oldContent = null;
1196
1106
  try {
1197
1107
  oldContent = await fs7.readFile(input.path, "utf-8");
@@ -1295,7 +1205,6 @@ function formatOccurrenceError(count, lines, filePath) {
1295
1205
  // src/tools/spec/editSpec.ts
1296
1206
  var editSpecTool = {
1297
1207
  definition: {
1298
- clearable: true,
1299
1208
  name: "editSpec",
1300
1209
  description: "Make a targeted find/replace edit to a spec file (src/*.md). old_string must appear exactly once (minor indentation differences are handled automatically); set replace_all to true to replace every occurrence. Read the file with readSpec first so you match the exact text, and include the full enclosing structure rather than an inner fragment. The file's YAML frontmatter (the leading --- \u2026 --- block, which holds required fields like name) is protected \u2014 an edit that would remove or malform it is refused. For a full rewrite, use writeSpec.",
1301
1210
  inputSchema: {
@@ -1397,10 +1306,9 @@ var editSpecTool = {
1397
1306
 
1398
1307
  // src/tools/spec/listSpecFiles.ts
1399
1308
  import fs9 from "fs/promises";
1400
- import path6 from "path";
1309
+ import path5 from "path";
1401
1310
  var listSpecFilesTool = {
1402
1311
  definition: {
1403
- clearable: false,
1404
1312
  name: "listSpecFiles",
1405
1313
  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.",
1406
1314
  inputSchema: {
@@ -1437,7 +1345,7 @@ async function listRecursive(dir) {
1437
1345
  return a.name.localeCompare(b.name);
1438
1346
  });
1439
1347
  for (const entry of entries) {
1440
- const fullPath = path6.join(dir, entry.name);
1348
+ const fullPath = path5.join(dir, entry.name);
1441
1349
  if (entry.isDirectory()) {
1442
1350
  results.push(`${fullPath}/`);
1443
1351
  results.push(...await listRecursive(fullPath));
@@ -1451,7 +1359,6 @@ async function listRecursive(dir) {
1451
1359
  // src/tools/spec/presentPublishPlan.ts
1452
1360
  var presentPublishPlanTool = {
1453
1361
  definition: {
1454
- clearable: false,
1455
1362
  name: "presentPublishPlan",
1456
1363
  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.",
1457
1364
  inputSchema: {
@@ -1476,7 +1383,6 @@ import fs10 from "fs/promises";
1476
1383
  var PLAN_FILE = ".remy-plan.md";
1477
1384
  var writePlanTool = {
1478
1385
  definition: {
1479
- clearable: false,
1480
1386
  name: "writePlan",
1481
1387
  description: "Write 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. The plan is displayed standalone in the UI with approve/reject buttons attached. The plan body ends with its last substantive section \u2014 do not write any closing line addressed to the reader. No 'If this lands, I'll start building,' no 'Let me know what to adjust,' no 'Approve when ready,' no trailing horizontal rule with a sign-off. Wrap-up text belongs in your chat message alongside the plan, not in the plan file. If the user asks for revisions, call this tool again with updated content to overwrite the plan.",
1482
1388
  inputSchema: {
@@ -1507,7 +1413,6 @@ import fs11 from "fs/promises";
1507
1413
  var PLAN_FILE2 = ".remy-plan.md";
1508
1414
  var updatePlanStatusTool = {
1509
1415
  definition: {
1510
- clearable: false,
1511
1416
  name: "updatePlanStatus",
1512
1417
  description: 'Update the status of the current implementation plan. Use when the user approves or rejects the plan via chat (e.g. "looks good, go ahead" or "scrap it"). Approving sets the plan to active so you can begin implementation. Rejecting deletes the plan.',
1513
1418
  inputSchema: {
@@ -1549,7 +1454,6 @@ var updatePlanStatusTool = {
1549
1454
  // src/tools/common/setProjectOnboardingState.ts
1550
1455
  var setProjectOnboardingStateTool = {
1551
1456
  definition: {
1552
- clearable: false,
1553
1457
  name: "setProjectOnboardingState",
1554
1458
  description: "Advance the project onboarding state. Forward-only: building \u2192 buildComplete \u2192 onboardingFinished. Normally driven by automated actions \u2014 don't call this out of order during a normal build, or you'll skip stages the user hasn't experienced. Exception: if the project has been in `building` for a while, the build is clearly done (the user is iterating on a working app, deploying, etc.), and the user reports the editor seems stuck \u2014 disabled Preview/Spec/Code tabs, no reveal, etc. \u2014 call `setProjectOnboardingState({ state: 'buildComplete' })` to unstick them. `onboardingFinished` is always set by the frontend after the user dismisses the reveal; never call it yourself.",
1555
1459
  inputSchema: {
@@ -1572,7 +1476,6 @@ var setProjectOnboardingStateTool = {
1572
1476
  // src/tools/common/promptUser.ts
1573
1477
  var promptUserTool = {
1574
1478
  definition: {
1575
- clearable: false,
1576
1479
  name: "promptUser",
1577
1480
  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.',
1578
1481
  inputSchema: {
@@ -1704,7 +1607,6 @@ ${lines.join("\n")}`;
1704
1607
  // src/tools/common/confirmDestructiveAction.ts
1705
1608
  var confirmDestructiveActionTool = {
1706
1609
  definition: {
1707
- clearable: false,
1708
1610
  name: "confirmDestructiveAction",
1709
1611
  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 presentPublishPlan or writePlan (those already include approval). Do not use before onboarding state transitions.",
1710
1612
  inputSchema: {
@@ -1878,7 +1780,6 @@ function runCli(command, args, options) {
1878
1780
  // src/subagents/sdkConsultant/index.ts
1879
1781
  var askMindStudioSdkTool = {
1880
1782
  definition: {
1881
- clearable: false,
1882
1783
  name: "askMindStudioSdk",
1883
1784
  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.",
1884
1785
  inputSchema: {
@@ -2019,7 +1920,6 @@ function stripDollarKeys(envelope) {
2019
1920
  // src/tools/common/searchGoogle.ts
2020
1921
  var searchGoogleTool = {
2021
1922
  definition: {
2022
- clearable: false,
2023
1923
  name: "searchGoogle",
2024
1924
  description: "Search Google and return results. Use for research, finding documentation, looking up APIs, or any task where web search would help.",
2025
1925
  inputSchema: {
@@ -2050,7 +1950,6 @@ var searchGoogleTool = {
2050
1950
  // src/tools/common/setProjectMetadata.ts
2051
1951
  var setProjectMetadataTool = {
2052
1952
  definition: {
2053
- clearable: false,
2054
1953
  name: "setProjectMetadata",
2055
1954
  description: "Set project metadata. Can update any combination of: display name, short description, app icon, and Open Graph share image. Provide only the fields you want to change.",
2056
1955
  inputSchema: {
@@ -2089,7 +1988,6 @@ var compactConversationTool = {
2089
1988
  // call (cleanMessagesForApi).
2090
1989
  backgroundNotify: "silent",
2091
1990
  definition: {
2092
- clearable: false,
2093
1991
  name: "compactConversation",
2094
1992
  description: "Compact the conversation history by summarizing older messages into a checkpoint. The summary preserves key decisions, what was built, and the current state of the project, but drops the verbose tool results, diffs, and intermediate steps that are no longer useful. Runs in the background.",
2095
1993
  inputSchema: {
@@ -2135,7 +2033,6 @@ var compactConversationTool = {
2135
2033
  // src/tools/common/loadSkill.ts
2136
2034
  var loadSkillTool = {
2137
2035
  definition: {
2138
- clearable: true,
2139
2036
  name: "loadSkill",
2140
2037
  description: "Load the full reference for a platform capability that isn't in your system prompt \u2014 task agents, agent interfaces, voice interfaces, MCP interfaces, data sources. The available skills and the trigger for each are listed in <available_skills>. Load one before writing code in its area, not after: these are APIs where a plausible-looking guess is usually wrong. Calling this is cheap and expected \u2014 if you're unsure whether you need it, load it. Only covers the capabilities listed in the catalog; for backend SDK actions and model IDs use askMindStudioSdk.",
2141
2038
  inputSchema: {
@@ -2186,7 +2083,6 @@ function isBinary(buffer) {
2186
2083
  }
2187
2084
  var readFileTool = {
2188
2085
  definition: {
2189
- clearable: true,
2190
2086
  name: "readFile",
2191
2087
  description: "Read a file's contents with line numbers. Always read a file before editing it \u2014 never guess at contents. By default returns the first 500 lines, and at most 64KB \u2014 a file with very wide lines (a CSV, a minified bundle) comes back short of 500 lines, so read a narrower range or grep rather than paging through it. To read a specific range, pass startLine and endLine (1-indexed, inclusive) \u2014 e.g. to read lines 253\u2013343, pass startLine: 253, endLine: 343. To read the end of a file or log, pass tail (the number of lines from the end). Line numbers in the output correspond to what editFile expects. For a large file, locate the relevant section first (symbols or grep), then read just that range.",
2192
2088
  inputSchema: {
@@ -2287,10 +2183,9 @@ var readFileTool = {
2287
2183
 
2288
2184
  // src/tools/code/writeFile.ts
2289
2185
  import fs14 from "fs/promises";
2290
- import path7 from "path";
2186
+ import path6 from "path";
2291
2187
  var writeFileTool = {
2292
2188
  definition: {
2293
- clearable: true,
2294
2189
  name: "writeFile",
2295
2190
  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.",
2296
2191
  inputSchema: {
@@ -2333,7 +2228,7 @@ ${unifiedDiff(partial.path, oldContent, completeContent)}`;
2333
2228
  async execute(input) {
2334
2229
  const release = await acquireFileLock(input.path);
2335
2230
  try {
2336
- await fs14.mkdir(path7.dirname(input.path), { recursive: true });
2231
+ await fs14.mkdir(path6.dirname(input.path), { recursive: true });
2337
2232
  let oldContent = null;
2338
2233
  try {
2339
2234
  oldContent = await fs14.readFile(input.path, "utf-8");
@@ -2356,7 +2251,6 @@ ${unifiedDiff(input.path, oldContent ?? "", input.content)}`;
2356
2251
  import fs15 from "fs/promises";
2357
2252
  var editFileTool = {
2358
2253
  definition: {
2359
- clearable: true,
2360
2254
  name: "editFile",
2361
2255
  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.",
2362
2256
  inputSchema: {
@@ -2443,13 +2337,12 @@ ${unifiedDiff(input.path, content, updated)}`;
2443
2337
 
2444
2338
  // src/tools/code/bash.ts
2445
2339
  import { spawn as spawn2 } from "child_process";
2446
- import path8 from "path";
2340
+ import path7 from "path";
2447
2341
  var DEFAULT_TIMEOUT_MS = 12e4;
2448
2342
  var DEFAULT_MAX_LINES2 = 500;
2449
2343
  var MAX_OUTPUT_BYTES = 3e4;
2450
2344
  var bashTool = {
2451
2345
  definition: {
2452
- clearable: true,
2453
2346
  name: "bash",
2454
2347
  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 or 30KB, whichever comes first. If a command would emit a lot of data, narrow it down (grep, head/tail, --short flags) rather than reading everything.",
2455
2348
  inputSchema: {
@@ -2482,7 +2375,7 @@ var bashTool = {
2482
2375
  const child = spawn2("sh", ["-c", input.command], {
2483
2376
  // Pinned rather than inherited. `undefined` here means "wherever the
2484
2377
  // process happens to be", which is the project root only by luck.
2485
- cwd: input.cwd ? path8.resolve(PROJECT_ROOT, input.cwd) : PROJECT_ROOT,
2378
+ cwd: input.cwd ? path7.resolve(PROJECT_ROOT, input.cwd) : PROJECT_ROOT,
2486
2379
  env: { ...process.env, FORCE_COLOR: "1" }
2487
2380
  });
2488
2381
  let output = "";
@@ -2571,7 +2464,6 @@ function formatResults(stdout, max, mode) {
2571
2464
  }
2572
2465
  var grepTool = {
2573
2466
  definition: {
2574
- clearable: true,
2575
2467
  name: "grep",
2576
2468
  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. Set outputMode to 'count' for per-file match counts (like grep -c) or 'filesWithMatches' for just the file paths (like grep -l). Add context (like grep -C), or contextBefore/contextAfter (like grep -B/-A), to include surrounding lines. Set caseInsensitive (like grep -i) for a case-insensitive search. For finding a symbol's definition precisely, prefer the definition tool if LSP is available. Automatically excludes node_modules and .git.",
2577
2469
  inputSchema: {
@@ -2683,7 +2575,6 @@ import fg from "fast-glob";
2683
2575
  var DEFAULT_MAX2 = 200;
2684
2576
  var globTool = {
2685
2577
  definition: {
2686
- clearable: true,
2687
2578
  name: "glob",
2688
2579
  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.',
2689
2580
  inputSchema: {
@@ -2728,7 +2619,7 @@ var globTool = {
2728
2619
 
2729
2620
  // src/tools/code/listDir.ts
2730
2621
  import fs16 from "fs/promises";
2731
- import path9 from "path";
2622
+ import path8 from "path";
2732
2623
  var EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
2733
2624
  var MAX_CHILDREN = 15;
2734
2625
  async function readAndSort(dirPath) {
@@ -2745,7 +2636,7 @@ async function readAndSort(dirPath) {
2745
2636
  }
2746
2637
  async function collapsePath(basePath, name) {
2747
2638
  let display = name;
2748
- let current = path9.join(basePath, name);
2639
+ let current = path8.join(basePath, name);
2749
2640
  for (; ; ) {
2750
2641
  let children;
2751
2642
  try {
@@ -2755,7 +2646,7 @@ async function collapsePath(basePath, name) {
2755
2646
  }
2756
2647
  if (children.length === 1 && children[0].isDirectory()) {
2757
2648
  display += "/" + children[0].name;
2758
- current = path9.join(current, children[0].name);
2649
+ current = path8.join(current, children[0].name);
2759
2650
  } else {
2760
2651
  break;
2761
2652
  }
@@ -2773,7 +2664,7 @@ function formatSize(bytes) {
2773
2664
  }
2774
2665
  async function formatFile(dirPath, name, indent) {
2775
2666
  try {
2776
- const stat2 = await fs16.stat(path9.join(dirPath, name));
2667
+ const stat2 = await fs16.stat(path8.join(dirPath, name));
2777
2668
  return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat2.size)}`;
2778
2669
  } catch {
2779
2670
  return `${indent}${name}`;
@@ -2781,7 +2672,6 @@ async function formatFile(dirPath, name, indent) {
2781
2672
  }
2782
2673
  var listDirTool = {
2783
2674
  definition: {
2784
- clearable: true,
2785
2675
  name: "listDir",
2786
2676
  description: "List the contents of a directory with one level of subdirectory expansion. Shows file sizes and collapses single-child directory chains (a/b/c/ shown as one entry). Use this for a quick overview of a directory's structure. For finding files across the whole project, use glob instead.",
2787
2677
  inputSchema: {
@@ -2858,7 +2748,6 @@ var listDirTool = {
2858
2748
  // src/tools/code/editsFinished.ts
2859
2749
  var editsFinishedTool = {
2860
2750
  definition: {
2861
- clearable: false,
2862
2751
  name: "editsFinished",
2863
2752
  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.",
2864
2753
  inputSchema: {
@@ -2925,7 +2814,6 @@ async function lspRequest(endpoint, body) {
2925
2814
  // src/tools/code/lspDiagnostics.ts
2926
2815
  var lspDiagnosticsTool = {
2927
2816
  definition: {
2928
- clearable: true,
2929
2817
  name: "lspDiagnostics",
2930
2818
  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.",
2931
2819
  inputSchema: {
@@ -2974,7 +2862,6 @@ var lspDiagnosticsTool = {
2974
2862
  // src/tools/code/restartProcess.ts
2975
2863
  var restartProcessTool = {
2976
2864
  definition: {
2977
- clearable: false,
2978
2865
  name: "restartProcess",
2979
2866
  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.",
2980
2867
  inputSchema: {
@@ -3001,7 +2888,6 @@ var restartProcessTool = {
3001
2888
  // src/tools/code/runScenario.ts
3002
2889
  var runScenarioTool = {
3003
2890
  definition: {
3004
- clearable: true,
3005
2891
  name: "runScenario",
3006
2892
  description: "Run a scenario to seed the dev database with test data. By default truncates all tables first, then executes the seed function and impersonates the scenario roles. Use skipTruncate to run the seed function against existing data without resetting. 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.",
3007
2893
  inputSchema: {
@@ -3027,7 +2913,6 @@ var runScenarioTool = {
3027
2913
  // src/tools/code/runMethod.ts
3028
2914
  var runMethodTool = {
3029
2915
  definition: {
3030
- clearable: true,
3031
2916
  name: "runMethod",
3032
2917
  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. Returns synchronously \u2014 no need to sleep before checking results.\n\nBy default methods run unauthenticated. If the method is auth-gated (calls `auth.requireRole()`, filters on `auth.userId`, etc.), pass `userId: "testUser"` to run as the default test user \u2014 no scenario setup required, no userId lookup.',
3033
2918
  inputSchema: {
@@ -3062,7 +2947,6 @@ var runMethodTool = {
3062
2947
  // src/tools/code/queryDatabase.ts
3063
2948
  var queryDatabaseTool = {
3064
2949
  definition: {
3065
- clearable: true,
3066
2950
  name: "queryDatabase",
3067
2951
  description: "Execute a raw SQL query against the dev database and return the results. Use for inspecting data and debugging issues.",
3068
2952
  inputSchema: {
@@ -3243,7 +3127,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3243
3127
  let onLog;
3244
3128
  let model;
3245
3129
  let apiConfig;
3246
- let path14;
3130
+ let path13;
3247
3131
  let fullPage = true;
3248
3132
  let width;
3249
3133
  let height;
@@ -3251,7 +3135,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3251
3135
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
3252
3136
  prompt = promptOrOptions.prompt;
3253
3137
  existingImage = promptOrOptions.image;
3254
- path14 = promptOrOptions.path;
3138
+ path13 = promptOrOptions.path;
3255
3139
  if (promptOrOptions.fullPage !== void 0) {
3256
3140
  fullPage = promptOrOptions.fullPage;
3257
3141
  }
@@ -3275,7 +3159,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3275
3159
  const ssResult = await sidecarRequest(
3276
3160
  fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
3277
3161
  {
3278
- ...path14 ? { path: path14 } : {},
3162
+ ...path13 ? { path: path13 } : {},
3279
3163
  ...width != null ? { width } : {},
3280
3164
  ...height != null ? { height } : {},
3281
3165
  ...format ? { format } : {}
@@ -4134,7 +4018,6 @@ var COMMON_READ_TOOL_NAMES = new Set(
4134
4018
  // src/subagents/browserAutomation/tools.ts
4135
4019
  var BROWSER_TOOLS = [
4136
4020
  {
4137
- clearable: false,
4138
4021
  name: "setupBrowser",
4139
4022
  description: "Pre-authenticate the browser and optionally navigate to a starting page. Call this before interacting with authenticated content instead of manually logging in. Auth is optional \u2014 omit to just navigate without authenticating.",
4140
4023
  inputSchema: {
@@ -4167,7 +4050,6 @@ var BROWSER_TOOLS = [
4167
4050
  }
4168
4051
  },
4169
4052
  {
4170
- clearable: true,
4171
4053
  name: "browserCommand",
4172
4054
  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 `recording` object \u2014 one chunk of a continuous per-session rrweb recording that the viewer stitches into a single replay (not a standalone per-call clip). Timeout: 120s.",
4173
4055
  inputSchema: {
@@ -4280,15 +4162,15 @@ var BROWSER_EXTERNAL_TOOLS = /* @__PURE__ */ new Set(["browserCommand"]);
4280
4162
 
4281
4163
  // src/subagents/common/context.ts
4282
4164
  import fs17 from "fs";
4283
- import path10 from "path";
4284
- function walkMdFiles2(dir, skip) {
4165
+ import path9 from "path";
4166
+ function walkMdFiles(dir, skip) {
4285
4167
  const files = [];
4286
4168
  try {
4287
4169
  for (const entry of fs17.readdirSync(dir, { withFileTypes: true })) {
4288
- const full = path10.join(dir, entry.name);
4170
+ const full = path9.join(dir, entry.name);
4289
4171
  if (entry.isDirectory()) {
4290
4172
  if (!skip?.has(entry.name)) {
4291
- files.push(...walkMdFiles2(full, skip));
4173
+ files.push(...walkMdFiles(full, skip));
4292
4174
  }
4293
4175
  } else if (entry.name.endsWith(".md")) {
4294
4176
  files.push(full);
@@ -4298,7 +4180,7 @@ function walkMdFiles2(dir, skip) {
4298
4180
  }
4299
4181
  return files.sort();
4300
4182
  }
4301
- function parseFrontmatter3(filePath) {
4183
+ function parseFrontmatter2(filePath) {
4302
4184
  try {
4303
4185
  const content = fs17.readFileSync(filePath, "utf-8");
4304
4186
  const match = content.match(/^---\n([\s\S]*?)\n---/);
@@ -4320,12 +4202,12 @@ function parseFrontmatter3(filePath) {
4320
4202
  }
4321
4203
  }
4322
4204
  function loadSpecIndex() {
4323
- const files = walkMdFiles2("src", /* @__PURE__ */ new Set(["roadmap"]));
4205
+ const files = walkMdFiles("src", /* @__PURE__ */ new Set(["roadmap"]));
4324
4206
  if (files.length === 0) {
4325
4207
  return "";
4326
4208
  }
4327
4209
  const lines = files.map((f) => {
4328
- const fm = parseFrontmatter3(f);
4210
+ const fm = parseFrontmatter2(f);
4329
4211
  let line = `- ${f}`;
4330
4212
  if (fm.name) {
4331
4213
  line += ` \u2014 "${fm.name}"`;
@@ -4363,10 +4245,10 @@ ${indexJson.standalone.map((s) => `- ${s}`).join("\n")}`
4363
4245
  }
4364
4246
  } catch {
4365
4247
  }
4366
- const files = walkMdFiles2("src/roadmap");
4248
+ const files = walkMdFiles("src/roadmap");
4367
4249
  if (files.length > 0) {
4368
4250
  const lines = files.map((f) => {
4369
- const fm = parseFrontmatter3(f);
4251
+ const fm = parseFrontmatter2(f);
4370
4252
  let line = `- ${f}`;
4371
4253
  if (fm.name) {
4372
4254
  line += ` \u2014 "${fm.name}"`;
@@ -4584,7 +4466,6 @@ async function runBrowserAutomation(task, context, opts) {
4584
4466
  }
4585
4467
  var browserAutomationTool = {
4586
4468
  definition: {
4587
- clearable: true,
4588
4469
  name: "runAutomatedBrowserTest",
4589
4470
  description: "Run an automated browser test against the live preview. Describe what to test \u2014 the agent figures out how. Use after meaningful changes to frontend code, to reproduce user-reported issues, or to test end-to-end flows. Never give it explicit values to use when filling out forms or creating accounts \u2014 it will use its own judgement (often it needs specific values to trigger dev-mode bypasses of things like login verification codes).",
4590
4471
  inputSchema: {
@@ -4614,7 +4495,6 @@ var browserAutomationTool = {
4614
4495
 
4615
4496
  // src/tools/code/screenshot.ts
4616
4497
  var screenshotDefinition = {
4617
- clearable: true,
4618
4498
  name: "screenshot",
4619
4499
  description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. The analysis is not precise about every detail \u2014 for example it cannot reliably identify specific fonts by name, only describe what the letterforms look like. 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; `imageUrl` also accepts the disk path of an image file (a user upload, a saved asset) to analyze that instead of the preview. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps. To render a fixed-size image such as an Open Graph share card, set `width` and `height` (e.g. 1200 \xD7 630) and `format: 'png'`: the tool navigates to `path`, clips to exactly those pixel dimensions, and returns the image URL.",
4620
4500
  inputSchema: {
@@ -4720,7 +4600,6 @@ __export(searchGoogle_exports, {
4720
4600
  execute: () => execute
4721
4601
  });
4722
4602
  var definition = {
4723
- clearable: false,
4724
4603
  name: "searchGoogle",
4725
4604
  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.',
4726
4605
  inputSchema: {
@@ -4753,7 +4632,6 @@ __export(scrapeWebUrl_exports, {
4753
4632
  execute: () => execute2
4754
4633
  });
4755
4634
  var definition2 = {
4756
- clearable: false,
4757
4635
  name: "scrapeWebUrl",
4758
4636
  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.",
4759
4637
  inputSchema: {
@@ -4811,7 +4689,6 @@ Identify the specific design moves that make this page interesting and unique, d
4811
4689
  Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.
4812
4690
  `;
4813
4691
  var definition3 = {
4814
- clearable: false,
4815
4692
  name: "analyzeDesign",
4816
4693
  description: "Analyze the visual design of a website, an image URL, or an image file on disk. 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.",
4817
4694
  inputSchema: {
@@ -4876,7 +4753,6 @@ __export(analyzeImage_exports, {
4876
4753
  execute: () => execute4
4877
4754
  });
4878
4755
  var definition4 = {
4879
- clearable: true,
4880
4756
  name: "analyzeImage",
4881
4757
  description: "Analyze an image 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.",
4882
4758
  inputSchema: {
@@ -5110,7 +4986,6 @@ async function generateImageAssets(opts) {
5110
4986
 
5111
4987
  // src/subagents/designExpert/tools/images/generateImages.ts
5112
4988
  var definition5 = {
5113
- clearable: false,
5114
4989
  name: "generateImages",
5115
4990
  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.",
5116
4991
  inputSchema: {
@@ -5178,7 +5053,6 @@ __export(editImages_exports, {
5178
5053
  execute: () => execute6
5179
5054
  });
5180
5055
  var definition6 = {
5181
- clearable: false,
5182
5056
  name: "editImages",
5183
5057
  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.",
5184
5058
  inputSchema: {
@@ -5256,7 +5130,6 @@ var COPY_EDITOR_TOOLS = [...COMMON_READ_TOOLS];
5256
5130
  var BASE_PROMPT2 = readAsset("subagents/copyEditor", "prompt.md");
5257
5131
  var copyEditorTool = {
5258
5132
  definition: {
5259
- clearable: false,
5260
5133
  name: "copyEditor",
5261
5134
  description: "Hand it user-facing copy and it hands back a sharper version \u2014 better structured for its audience and free of the overused words, telltale constructions, and rhythms that make text read as AI-generated. Think of it as a design expert for words: it elevates how the copy communicates and strips the AI fingerprints, but it never invents facts or claims you didn't give it. Use it on anything users will read: in-app strings, empty states, errors, the Build Overview, deck copy, launch posts, Slack announcements. Readonly.",
5262
5135
  inputSchema: {
@@ -5304,7 +5177,6 @@ var copyEditorTool = {
5304
5177
 
5305
5178
  // src/subagents/designExpert/tools/polishCopy.ts
5306
5179
  var definition7 = {
5307
- clearable: false,
5308
5180
  name: "polishCopy",
5309
5181
  description: "Hand off any user-facing copy you've written \u2014 headlines, captions, labels, body text \u2014 and get back a sharper version: better built for its audience and free of the fingerprints that make writing read as AI. It elevates how the copy communicates without inventing facts or claims you didn't give it. Give it the text plus what it's for (where it appears, the audience).",
5310
5182
  inputSchema: {
@@ -5656,7 +5528,6 @@ async function runDesignExpert(opts, context) {
5656
5528
  }
5657
5529
  var designExpertTool = {
5658
5530
  definition: {
5659
- clearable: false,
5660
5531
  name: "visualDesignExpert",
5661
5532
  description: DESCRIPTION,
5662
5533
  inputSchema: {
@@ -5746,14 +5617,14 @@ var VISION_TOOLS = [
5746
5617
 
5747
5618
  // src/subagents/productVision/executor.ts
5748
5619
  import fs19 from "fs";
5749
- import path11 from "path";
5620
+ import path10 from "path";
5750
5621
  var ROADMAP_DIR = "src/roadmap";
5751
5622
  var PITCH_DECK_SHELL = readAsset(
5752
5623
  "subagents/productVision",
5753
5624
  "pitch-deck-shell.html"
5754
5625
  );
5755
5626
  function resolve2(filePath) {
5756
- return path11.join(ROADMAP_DIR, filePath);
5627
+ return path10.join(ROADMAP_DIR, filePath);
5757
5628
  }
5758
5629
  async function executeVisionTool(name, input, context) {
5759
5630
  switch (name) {
@@ -5864,7 +5735,6 @@ function getProductVisionPrompt() {
5864
5735
  // src/subagents/productVision/index.ts
5865
5736
  var productVisionTool = {
5866
5737
  definition: {
5867
- clearable: false,
5868
5738
  name: "productVision",
5869
5739
  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.",
5870
5740
  inputSchema: {
@@ -5977,7 +5847,6 @@ var SANITY_CHECK_TOOLS = [
5977
5847
  var BASE_PROMPT4 = readAsset("subagents/codeSanityCheck", "prompt.md");
5978
5848
  var codeSanityCheckTool = {
5979
5849
  definition: {
5980
- clearable: false,
5981
5850
  name: "codeSanityCheck",
5982
5851
  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.',
5983
5852
  inputSchema: {
@@ -6112,7 +5981,6 @@ ${result.text}`;
6112
5981
  }
6113
5982
  var buildOverviewTool = {
6114
5983
  definition: {
6115
- clearable: false,
6116
5984
  name: "writeBuildOverview",
6117
5985
  description: "Generate or refresh the Build Overview \u2014 the project's home page in the Spec tab: a single-page, plain-language reference of everything the app actually contains, including the parts the user can't see (data stores, backend operations, access and roles, background jobs, seeded scenarios, the design system). You author the full copy: read the manifest and spec and state, plainly and exactly, what genuinely exists \u2014 real names and accurate counts \u2014 in calm, declarative, present-tense outcome language, with no persuasion or hype. Describe only what exists. Pass the complete copy as `content`; the design expert lays it out and skins it to the app's brand using your copy verbatim \u2014 it typesets your words, it does not rewrite them, so polish the copy before you pass it. Generate it at the end of a build; routine refreshes ride specSync's `refreshBuildOverview` flag instead, so call this directly only for the initial generation or when the user explicitly asks.",
6118
5986
  inputSchema: {
@@ -6173,7 +6041,6 @@ var specSyncTool = {
6173
6041
  // next real turn as a hidden background_results note instead.
6174
6042
  backgroundNotify: "passive",
6175
6043
  definition: {
6176
- clearable: false,
6177
6044
  name: "specSync",
6178
6045
  description: "Reconcile the spec to bring it in line with code changes you have made. Provide a brief, bulleted list of what changed and why; it finds the affected spec sections and updates them to match. Set `refreshBuildOverview` after a deploy or a large milestone to also re-author the Build Overview from the updated spec. Always runs in the background and completes silently \u2014 do not wait for it; its outcome appears as an automated note at the start of a later turn.",
6179
6046
  inputSchema: {
@@ -6260,7 +6127,6 @@ After reconciling the spec, refresh the Build Overview: author the complete upda
6260
6127
  // src/tools/common/scrapeWebUrl.ts
6261
6128
  var scrapeWebUrlTool = {
6262
6129
  definition: {
6263
- clearable: false,
6264
6130
  name: "scrapeWebUrl",
6265
6131
  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",
6266
6132
  inputSchema: {
@@ -6778,7 +6644,7 @@ Write the summary of the conversation above, following your instructions.`;
6778
6644
 
6779
6645
  // src/session.ts
6780
6646
  import fs21 from "fs";
6781
- import path12 from "path";
6647
+ import path11 from "path";
6782
6648
  var log10 = createLogger("session");
6783
6649
  var SESSION_FILE = ".remy-session.json";
6784
6650
  var ARCHIVE_DIR = ".logs/sessions";
@@ -6877,17 +6743,17 @@ function archiveMessages(messages, label, models) {
6877
6743
  fs21.mkdirSync(ARCHIVE_DIR, { recursive: true });
6878
6744
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
6879
6745
  const count = messages.length;
6880
- let dest = path12.join(ARCHIVE_DIR, `${label}-${ts}.c${count}.json`);
6746
+ let dest = path11.join(ARCHIVE_DIR, `${label}-${ts}.c${count}.json`);
6881
6747
  let n = 1;
6882
6748
  while (fs21.existsSync(dest)) {
6883
- dest = path12.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.c${count}.json`);
6749
+ dest = path11.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.c${count}.json`);
6884
6750
  }
6885
6751
  const payload = { messages };
6886
6752
  if (models && Object.keys(models).length > 0) {
6887
6753
  payload.models = models;
6888
6754
  }
6889
6755
  writeFileAtomicSync(dest, JSON.stringify(payload));
6890
- archiveCountCache.set(path12.basename(dest), count);
6756
+ archiveCountCache.set(path11.basename(dest), count);
6891
6757
  log10.info("Session archived", { label, dest, messageCount: count });
6892
6758
  pruneArchives();
6893
6759
  return dest;
@@ -6900,7 +6766,7 @@ function pruneArchives() {
6900
6766
  }
6901
6767
  const archives = entries.map((name) => ({
6902
6768
  name,
6903
- size: fs21.statSync(path12.join(ARCHIVE_DIR, name)).size
6769
+ size: fs21.statSync(path11.join(ARCHIVE_DIR, name)).size
6904
6770
  })).sort(
6905
6771
  (a, b) => archiveSortKey(b.name).localeCompare(archiveSortKey(a.name))
6906
6772
  );
@@ -6918,7 +6784,7 @@ function pruneArchives() {
6918
6784
  let freed = 0;
6919
6785
  for (let i = cut; i < archives.length; i++) {
6920
6786
  try {
6921
- fs21.unlinkSync(path12.join(ARCHIVE_DIR, archives[i].name));
6787
+ fs21.unlinkSync(path11.join(ARCHIVE_DIR, archives[i].name));
6922
6788
  freed += archives[i].size;
6923
6789
  removed++;
6924
6790
  } catch {
@@ -6942,7 +6808,7 @@ function parseArchive(name) {
6942
6808
  return cached3;
6943
6809
  }
6944
6810
  try {
6945
- const raw = fs21.readFileSync(path12.join(ARCHIVE_DIR, name), "utf-8");
6811
+ const raw = fs21.readFileSync(path11.join(ARCHIVE_DIR, name), "utf-8");
6946
6812
  const data = JSON.parse(raw);
6947
6813
  const messages = Array.isArray(data?.messages) ? data.messages : [];
6948
6814
  archiveCountCache.set(name, messages.length);
@@ -7223,7 +7089,7 @@ function triggerCompaction(state, apiConfig, opts = {}) {
7223
7089
 
7224
7090
  // src/brandExtraction/index.ts
7225
7091
  import fs22 from "fs";
7226
- import path13 from "path";
7092
+ import path12 from "path";
7227
7093
  import { createHash } from "crypto";
7228
7094
  var log12 = createLogger("brandExtraction");
7229
7095
  var EXTRACT_PROMPT = readAsset("brandExtraction", "extract.md");
@@ -7247,18 +7113,18 @@ async function runExtraction(apiConfig, model) {
7247
7113
  return brand;
7248
7114
  }
7249
7115
  function isDedicatedBrandFile(filePath) {
7250
- if (filePath.split(path13.sep).includes("@brand")) {
7116
+ if (filePath.split(path12.sep).includes("@brand")) {
7251
7117
  return true;
7252
7118
  }
7253
- const { type } = parseFrontmatter4(filePath);
7119
+ const { type } = parseFrontmatter3(filePath);
7254
7120
  return type.startsWith("design/color") || type.startsWith("design/typography");
7255
7121
  }
7256
7122
  function isBrandRelevant(filePath) {
7257
- return filePath === path13.join("src", "app.md") || isDedicatedBrandFile(filePath);
7123
+ return filePath === path12.join("src", "app.md") || isDedicatedBrandFile(filePath);
7258
7124
  }
7259
7125
  function computeInputHash() {
7260
7126
  const entries = [];
7261
- for (const filePath of walkMdFiles3("src")) {
7127
+ for (const filePath of walkMdFiles2("src")) {
7262
7128
  if (isBrandRelevant(filePath)) {
7263
7129
  entries.push({ path: filePath, content: readSafe(filePath) });
7264
7130
  }
@@ -7299,14 +7165,14 @@ function readBrandManifest() {
7299
7165
  return "";
7300
7166
  }
7301
7167
  }
7302
- function walkMdFiles3(dir) {
7168
+ function walkMdFiles2(dir) {
7303
7169
  const results = [];
7304
7170
  try {
7305
7171
  const entries = fs22.readdirSync(dir, { withFileTypes: true });
7306
7172
  for (const entry of entries) {
7307
- const full = path13.join(dir, entry.name);
7173
+ const full = path12.join(dir, entry.name);
7308
7174
  if (entry.isDirectory()) {
7309
- results.push(...walkMdFiles3(full));
7175
+ results.push(...walkMdFiles2(full));
7310
7176
  } else if (entry.name.endsWith(".md")) {
7311
7177
  results.push(full);
7312
7178
  }
@@ -7315,7 +7181,7 @@ function walkMdFiles3(dir) {
7315
7181
  }
7316
7182
  return results.sort();
7317
7183
  }
7318
- function parseFrontmatter4(filePath) {
7184
+ function parseFrontmatter3(filePath) {
7319
7185
  try {
7320
7186
  const content = fs22.readFileSync(filePath, "utf-8");
7321
7187
  const match = content.match(/^---\n([\s\S]*?)\n---/);
@@ -7383,7 +7249,7 @@ async function extractBrand(apiConfig, model) {
7383
7249
  var HEAD_SLICE_CHARS = 2e3;
7384
7250
  var BRAND_CORPUS_CHAR_LIMIT = 24e5;
7385
7251
  function buildCorpus() {
7386
- const all = walkMdFiles3("src");
7252
+ const all = walkMdFiles2("src");
7387
7253
  const ordered = [
7388
7254
  ...all.filter(isBrandRelevant),
7389
7255
  ...all.filter((f) => !isBrandRelevant(f))
@@ -9396,10 +9262,7 @@ var HeadlessSession = class {
9396
9262
  const buildModel = hasSentinel(rawText, "approvePlan") ? parsed.buildModel : void 0;
9397
9263
  const onboardingState = parsed.onboardingState ?? "onboardingFinished";
9398
9264
  this.currentOnboardingState = onboardingState;
9399
- const system = buildSystemPrompt(
9400
- onboardingState,
9401
- parsed.viewContext
9402
- );
9265
+ const system = buildSystemPrompt(onboardingState);
9403
9266
  if (resolved?.next && !fromChain) {
9404
9267
  for (const step of getActionChain(resolved.next)) {
9405
9268
  this.queue.push({
@@ -9476,13 +9339,12 @@ var HeadlessSession = class {
9476
9339
  }
9477
9340
  const onboardingState = batch.find((b) => b.command.onboardingState !== void 0)?.command.onboardingState ?? this.currentOnboardingState ?? "onboardingFinished";
9478
9341
  this.currentOnboardingState = onboardingState;
9479
- const viewContext = [...batch].reverse().find((b) => b.command.viewContext !== void 0)?.command.viewContext;
9480
9342
  await this.executeTurn({
9481
9343
  entries,
9482
9344
  requestId: primaryRid,
9483
9345
  absorbedRids,
9484
9346
  onboardingState,
9485
- system: buildSystemPrompt(onboardingState, viewContext)
9347
+ system: buildSystemPrompt(onboardingState)
9486
9348
  });
9487
9349
  }
9488
9350
  /**