@mindstudio-ai/remy 0.1.240 → 0.1.241

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,6 +618,18 @@ function readJsonAsset(fallback, ...segments) {
618
618
  // src/prompt/static/projectContext.ts
619
619
  import fs4 from "fs";
620
620
  import path3 from "path";
621
+
622
+ // src/projectRoot.ts
623
+ var PROJECT_ROOT = process.cwd();
624
+
625
+ // src/prompt/static/projectContext.ts
626
+ function loadProjectRoot() {
627
+ return `
628
+ ## Project Root
629
+ \`${PROJECT_ROOT}\`
630
+
631
+ File paths are relative to this directory. Every tool operates here and bash commands run it it.`;
632
+ }
621
633
  function loadProjectManifest() {
622
634
  try {
623
635
  const manifest = fs4.readFileSync("mindstudio.json", "utf-8");
@@ -750,6 +762,7 @@ function resolveIncludes(template) {
750
762
  }
751
763
  function buildSystemPrompt(onboardingState, viewContext) {
752
764
  const projectContext = [
765
+ loadProjectRoot(),
753
766
  loadProjectManifest(),
754
767
  loadSpecFileMetadata(),
755
768
  loadProjectFileListing()
@@ -2148,6 +2161,7 @@ ${unifiedDiff(input.path, content, updated)}`;
2148
2161
 
2149
2162
  // src/tools/code/bash.ts
2150
2163
  import { spawn as spawn2 } from "child_process";
2164
+ import path7 from "path";
2151
2165
  var DEFAULT_TIMEOUT_MS = 12e4;
2152
2166
  var DEFAULT_MAX_LINES2 = 500;
2153
2167
  var MAX_OUTPUT_BYTES = 3e4;
@@ -2165,7 +2179,7 @@ var bashTool = {
2165
2179
  },
2166
2180
  cwd: {
2167
2181
  type: "string",
2168
- description: "Working directory to run the command in. Defaults to the project root."
2182
+ description: "Working directory, relative to the project root. Defaults to the project root itself."
2169
2183
  },
2170
2184
  timeout: {
2171
2185
  type: "number",
@@ -2184,7 +2198,9 @@ var bashTool = {
2184
2198
  const timeoutMs = input.timeout ? input.timeout * 1e3 : DEFAULT_TIMEOUT_MS;
2185
2199
  return new Promise((resolve2) => {
2186
2200
  const child = spawn2("sh", ["-c", input.command], {
2187
- cwd: input.cwd || void 0,
2201
+ // Pinned rather than inherited. `undefined` here means "wherever the
2202
+ // process happens to be", which is the project root only by luck.
2203
+ cwd: input.cwd ? path7.resolve(PROJECT_ROOT, input.cwd) : PROJECT_ROOT,
2188
2204
  env: { ...process.env, FORCE_COLOR: "1" }
2189
2205
  });
2190
2206
  let output = "";
@@ -2430,7 +2446,7 @@ var globTool = {
2430
2446
 
2431
2447
  // src/tools/code/listDir.ts
2432
2448
  import fs15 from "fs/promises";
2433
- import path7 from "path";
2449
+ import path8 from "path";
2434
2450
  var EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
2435
2451
  var MAX_CHILDREN = 15;
2436
2452
  async function readAndSort(dirPath) {
@@ -2447,7 +2463,7 @@ async function readAndSort(dirPath) {
2447
2463
  }
2448
2464
  async function collapsePath(basePath, name) {
2449
2465
  let display = name;
2450
- let current = path7.join(basePath, name);
2466
+ let current = path8.join(basePath, name);
2451
2467
  for (; ; ) {
2452
2468
  let children;
2453
2469
  try {
@@ -2457,7 +2473,7 @@ async function collapsePath(basePath, name) {
2457
2473
  }
2458
2474
  if (children.length === 1 && children[0].isDirectory()) {
2459
2475
  display += "/" + children[0].name;
2460
- current = path7.join(current, children[0].name);
2476
+ current = path8.join(current, children[0].name);
2461
2477
  } else {
2462
2478
  break;
2463
2479
  }
@@ -2475,7 +2491,7 @@ function formatSize(bytes) {
2475
2491
  }
2476
2492
  async function formatFile(dirPath, name, indent) {
2477
2493
  try {
2478
- const stat = await fs15.stat(path7.join(dirPath, name));
2494
+ const stat = await fs15.stat(path8.join(dirPath, name));
2479
2495
  return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat.size)}`;
2480
2496
  } catch {
2481
2497
  return `${indent}${name}`;
@@ -2836,12 +2852,12 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2836
2852
  let existingUrl;
2837
2853
  let onLog;
2838
2854
  let model;
2839
- let path12;
2855
+ let path13;
2840
2856
  let fullPage = true;
2841
2857
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
2842
2858
  prompt = promptOrOptions.prompt;
2843
2859
  existingUrl = promptOrOptions.imageUrl;
2844
- path12 = promptOrOptions.path;
2860
+ path13 = promptOrOptions.path;
2845
2861
  if (promptOrOptions.fullPage !== void 0) {
2846
2862
  fullPage = promptOrOptions.fullPage;
2847
2863
  }
@@ -2857,7 +2873,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2857
2873
  } else {
2858
2874
  const ssResult = await sidecarRequest(
2859
2875
  fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
2860
- path12 ? { path: path12 } : void 0,
2876
+ path13 ? { path: path13 } : void 0,
2861
2877
  { timeout: fullPage ? 12e4 : 3e4 }
2862
2878
  );
2863
2879
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -4662,12 +4678,12 @@ __export(polishCopy_exports, {
4662
4678
 
4663
4679
  // src/subagents/common/context.ts
4664
4680
  import fs17 from "fs";
4665
- import path8 from "path";
4681
+ import path9 from "path";
4666
4682
  function walkMdFiles2(dir, skip) {
4667
4683
  const files = [];
4668
4684
  try {
4669
4685
  for (const entry of fs17.readdirSync(dir, { withFileTypes: true })) {
4670
- const full = path8.join(dir, entry.name);
4686
+ const full = path9.join(dir, entry.name);
4671
4687
  if (entry.isDirectory()) {
4672
4688
  if (!skip?.has(entry.name)) {
4673
4689
  files.push(...walkMdFiles2(full, skip));
@@ -5310,14 +5326,14 @@ var VISION_TOOLS = [
5310
5326
 
5311
5327
  // src/subagents/productVision/executor.ts
5312
5328
  import fs19 from "fs";
5313
- import path9 from "path";
5329
+ import path10 from "path";
5314
5330
  var ROADMAP_DIR = "src/roadmap";
5315
5331
  var PITCH_DECK_SHELL = readAsset(
5316
5332
  "subagents/productVision",
5317
5333
  "pitch-deck-shell.html"
5318
5334
  );
5319
5335
  function resolve(filePath) {
5320
- return path9.join(ROADMAP_DIR, filePath);
5336
+ return path10.join(ROADMAP_DIR, filePath);
5321
5337
  }
5322
5338
  async function executeVisionTool(name, input, context) {
5323
5339
  switch (name) {
@@ -6248,7 +6264,7 @@ Write the summary of the conversation above, following your instructions.`;
6248
6264
 
6249
6265
  // src/session.ts
6250
6266
  import fs21 from "fs";
6251
- import path10 from "path";
6267
+ import path11 from "path";
6252
6268
  var log9 = createLogger("session");
6253
6269
  var SESSION_FILE = ".remy-session.json";
6254
6270
  var ARCHIVE_DIR = ".logs/sessions";
@@ -6333,10 +6349,10 @@ function buildPayload(state) {
6333
6349
  function archiveMessages(messages, label, models) {
6334
6350
  fs21.mkdirSync(ARCHIVE_DIR, { recursive: true });
6335
6351
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
6336
- let dest = path10.join(ARCHIVE_DIR, `${label}-${ts}.json`);
6352
+ let dest = path11.join(ARCHIVE_DIR, `${label}-${ts}.json`);
6337
6353
  let n = 1;
6338
6354
  while (fs21.existsSync(dest)) {
6339
- dest = path10.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.json`);
6355
+ dest = path11.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.json`);
6340
6356
  }
6341
6357
  const payload = { messages };
6342
6358
  if (models && Object.keys(models).length > 0) {
@@ -6356,7 +6372,7 @@ function pruneArchives() {
6356
6372
  const sortKey = (name) => name.replace(/^(cleared|rotated)-/, "");
6357
6373
  const archives = entries.map((name) => ({
6358
6374
  name,
6359
- size: fs21.statSync(path10.join(ARCHIVE_DIR, name)).size
6375
+ size: fs21.statSync(path11.join(ARCHIVE_DIR, name)).size
6360
6376
  })).sort((a, b) => sortKey(b.name).localeCompare(sortKey(a.name)));
6361
6377
  let kept = 0;
6362
6378
  let cut = archives.length;
@@ -6372,7 +6388,7 @@ function pruneArchives() {
6372
6388
  let freed = 0;
6373
6389
  for (let i = cut; i < archives.length; i++) {
6374
6390
  try {
6375
- fs21.unlinkSync(path10.join(ARCHIVE_DIR, archives[i].name));
6391
+ fs21.unlinkSync(path11.join(ARCHIVE_DIR, archives[i].name));
6376
6392
  freed += archives[i].size;
6377
6393
  removed++;
6378
6394
  } catch {
@@ -6492,7 +6508,7 @@ function triggerCompaction(state, apiConfig, opts = {}) {
6492
6508
 
6493
6509
  // src/brandExtraction/index.ts
6494
6510
  import fs22 from "fs";
6495
- import path11 from "path";
6511
+ import path12 from "path";
6496
6512
  import { createHash } from "crypto";
6497
6513
  var log11 = createLogger("brandExtraction");
6498
6514
  var EXTRACT_PROMPT = readAsset("brandExtraction", "extract.md");
@@ -6516,7 +6532,7 @@ async function runExtraction(apiConfig, model) {
6516
6532
  return brand;
6517
6533
  }
6518
6534
  function isBrandRelevant(filePath) {
6519
- if (filePath === path11.join("src", "app.md")) {
6535
+ if (filePath === path12.join("src", "app.md")) {
6520
6536
  return true;
6521
6537
  }
6522
6538
  const { type } = parseFrontmatter3(filePath);
@@ -6552,7 +6568,7 @@ function walkMdFiles3(dir) {
6552
6568
  try {
6553
6569
  const entries = fs22.readdirSync(dir, { withFileTypes: true });
6554
6570
  for (const entry of entries) {
6555
- const full = path11.join(dir, entry.name);
6571
+ const full = path12.join(dir, entry.name);
6556
6572
  if (entry.isDirectory()) {
6557
6573
  results.push(...walkMdFiles3(full));
6558
6574
  } else if (entry.name.endsWith(".md")) {
package/dist/index.js CHANGED
@@ -2798,12 +2798,23 @@ ${unifiedDiff(input.path, content, updated)}`;
2798
2798
  }
2799
2799
  });
2800
2800
 
2801
+ // src/projectRoot.ts
2802
+ var PROJECT_ROOT;
2803
+ var init_projectRoot = __esm({
2804
+ "src/projectRoot.ts"() {
2805
+ "use strict";
2806
+ PROJECT_ROOT = process.cwd();
2807
+ }
2808
+ });
2809
+
2801
2810
  // src/tools/code/bash.ts
2802
2811
  import { spawn as spawn2 } from "child_process";
2812
+ import path6 from "path";
2803
2813
  var DEFAULT_TIMEOUT_MS, DEFAULT_MAX_LINES2, MAX_OUTPUT_BYTES, bashTool;
2804
2814
  var init_bash = __esm({
2805
2815
  "src/tools/code/bash.ts"() {
2806
2816
  "use strict";
2817
+ init_projectRoot();
2807
2818
  DEFAULT_TIMEOUT_MS = 12e4;
2808
2819
  DEFAULT_MAX_LINES2 = 500;
2809
2820
  MAX_OUTPUT_BYTES = 3e4;
@@ -2821,7 +2832,7 @@ var init_bash = __esm({
2821
2832
  },
2822
2833
  cwd: {
2823
2834
  type: "string",
2824
- description: "Working directory to run the command in. Defaults to the project root."
2835
+ description: "Working directory, relative to the project root. Defaults to the project root itself."
2825
2836
  },
2826
2837
  timeout: {
2827
2838
  type: "number",
@@ -2840,7 +2851,9 @@ var init_bash = __esm({
2840
2851
  const timeoutMs = input.timeout ? input.timeout * 1e3 : DEFAULT_TIMEOUT_MS;
2841
2852
  return new Promise((resolve2) => {
2842
2853
  const child = spawn2("sh", ["-c", input.command], {
2843
- cwd: input.cwd || void 0,
2854
+ // Pinned rather than inherited. `undefined` here means "wherever the
2855
+ // process happens to be", which is the project root only by luck.
2856
+ cwd: input.cwd ? path6.resolve(PROJECT_ROOT, input.cwd) : PROJECT_ROOT,
2844
2857
  env: { ...process.env, FORCE_COLOR: "1" }
2845
2858
  });
2846
2859
  let output = "";
@@ -3100,7 +3113,7 @@ var init_glob = __esm({
3100
3113
 
3101
3114
  // src/tools/code/listDir.ts
3102
3115
  import fs14 from "fs/promises";
3103
- import path6 from "path";
3116
+ import path7 from "path";
3104
3117
  async function readAndSort(dirPath) {
3105
3118
  const entries = await fs14.readdir(dirPath, { withFileTypes: true });
3106
3119
  return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
@@ -3115,7 +3128,7 @@ async function readAndSort(dirPath) {
3115
3128
  }
3116
3129
  async function collapsePath(basePath, name) {
3117
3130
  let display = name;
3118
- let current = path6.join(basePath, name);
3131
+ let current = path7.join(basePath, name);
3119
3132
  for (; ; ) {
3120
3133
  let children;
3121
3134
  try {
@@ -3125,7 +3138,7 @@ async function collapsePath(basePath, name) {
3125
3138
  }
3126
3139
  if (children.length === 1 && children[0].isDirectory()) {
3127
3140
  display += "/" + children[0].name;
3128
- current = path6.join(current, children[0].name);
3141
+ current = path7.join(current, children[0].name);
3129
3142
  } else {
3130
3143
  break;
3131
3144
  }
@@ -3143,7 +3156,7 @@ function formatSize(bytes) {
3143
3156
  }
3144
3157
  async function formatFile(dirPath, name, indent) {
3145
3158
  try {
3146
- const stat = await fs14.stat(path6.join(dirPath, name));
3159
+ const stat = await fs14.stat(path7.join(dirPath, name));
3147
3160
  return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat.size)}`;
3148
3161
  } catch {
3149
3162
  return `${indent}${name}`;
@@ -3566,12 +3579,12 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3566
3579
  let existingUrl;
3567
3580
  let onLog;
3568
3581
  let model;
3569
- let path13;
3582
+ let path14;
3570
3583
  let fullPage = true;
3571
3584
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
3572
3585
  prompt = promptOrOptions.prompt;
3573
3586
  existingUrl = promptOrOptions.imageUrl;
3574
- path13 = promptOrOptions.path;
3587
+ path14 = promptOrOptions.path;
3575
3588
  if (promptOrOptions.fullPage !== void 0) {
3576
3589
  fullPage = promptOrOptions.fullPage;
3577
3590
  }
@@ -3587,7 +3600,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3587
3600
  } else {
3588
3601
  const ssResult = await sidecarRequest(
3589
3602
  fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
3590
- path13 ? { path: path13 } : void 0,
3603
+ path14 ? { path: path14 } : void 0,
3591
3604
  { timeout: fullPage ? 12e4 : 3e4 }
3592
3605
  );
3593
3606
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -5363,12 +5376,12 @@ var init_editImages = __esm({
5363
5376
 
5364
5377
  // src/subagents/common/context.ts
5365
5378
  import fs16 from "fs";
5366
- import path7 from "path";
5379
+ import path8 from "path";
5367
5380
  function walkMdFiles(dir, skip) {
5368
5381
  const files = [];
5369
5382
  try {
5370
5383
  for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
5371
- const full = path7.join(dir, entry.name);
5384
+ const full = path8.join(dir, entry.name);
5372
5385
  if (entry.isDirectory()) {
5373
5386
  if (!skip?.has(entry.name)) {
5374
5387
  files.push(...walkMdFiles(full, skip));
@@ -6189,9 +6202,9 @@ var init_tools5 = __esm({
6189
6202
 
6190
6203
  // src/subagents/productVision/executor.ts
6191
6204
  import fs18 from "fs";
6192
- import path8 from "path";
6205
+ import path9 from "path";
6193
6206
  function resolve(filePath) {
6194
- return path8.join(ROADMAP_DIR, filePath);
6207
+ return path9.join(ROADMAP_DIR, filePath);
6195
6208
  }
6196
6209
  async function executeVisionTool(name, input, context) {
6197
6210
  switch (name) {
@@ -7135,7 +7148,7 @@ var init_errors = __esm({
7135
7148
 
7136
7149
  // src/brandExtraction/index.ts
7137
7150
  import fs20 from "fs";
7138
- import path9 from "path";
7151
+ import path10 from "path";
7139
7152
  import { createHash } from "crypto";
7140
7153
  async function runExtraction(apiConfig, model) {
7141
7154
  const inputHash = computeInputHash();
@@ -7155,7 +7168,7 @@ async function runExtraction(apiConfig, model) {
7155
7168
  return brand;
7156
7169
  }
7157
7170
  function isBrandRelevant(filePath) {
7158
- if (filePath === path9.join("src", "app.md")) {
7171
+ if (filePath === path10.join("src", "app.md")) {
7159
7172
  return true;
7160
7173
  }
7161
7174
  const { type } = parseFrontmatter2(filePath);
@@ -7191,7 +7204,7 @@ function walkMdFiles2(dir) {
7191
7204
  try {
7192
7205
  const entries = fs20.readdirSync(dir, { withFileTypes: true });
7193
7206
  for (const entry of entries) {
7194
- const full = path9.join(dir, entry.name);
7207
+ const full = path10.join(dir, entry.name);
7195
7208
  if (entry.isDirectory()) {
7196
7209
  results.push(...walkMdFiles2(full));
7197
7210
  } else if (entry.name.endsWith(".md")) {
@@ -8092,7 +8105,14 @@ var init_agent = __esm({
8092
8105
 
8093
8106
  // src/prompt/static/projectContext.ts
8094
8107
  import fs21 from "fs";
8095
- import path10 from "path";
8108
+ import path11 from "path";
8109
+ function loadProjectRoot() {
8110
+ return `
8111
+ ## Project Root
8112
+ \`${PROJECT_ROOT}\`
8113
+
8114
+ File paths are relative to this directory. Every tool operates here and bash commands run it it.`;
8115
+ }
8096
8116
  function loadProjectManifest() {
8097
8117
  try {
8098
8118
  const manifest = fs21.readFileSync("mindstudio.json", "utf-8");
@@ -8138,7 +8158,7 @@ function walkMdFiles3(dir) {
8138
8158
  try {
8139
8159
  const entries = fs21.readdirSync(dir, { withFileTypes: true });
8140
8160
  for (const entry of entries) {
8141
- const full = path10.join(dir, entry.name);
8161
+ const full = path11.join(dir, entry.name);
8142
8162
  if (entry.isDirectory()) {
8143
8163
  results.push(...walkMdFiles3(full));
8144
8164
  } else if (entry.name.endsWith(".md")) {
@@ -8217,6 +8237,7 @@ ${listing}
8217
8237
  var init_projectContext = __esm({
8218
8238
  "src/prompt/static/projectContext.ts"() {
8219
8239
  "use strict";
8240
+ init_projectRoot();
8220
8241
  }
8221
8242
  });
8222
8243
 
@@ -8230,6 +8251,7 @@ function resolveIncludes(template) {
8230
8251
  }
8231
8252
  function buildSystemPrompt(onboardingState, viewContext) {
8232
8253
  const projectContext = [
8254
+ loadProjectRoot(),
8233
8255
  loadProjectManifest(),
8234
8256
  loadSpecFileMetadata(),
8235
8257
  loadProjectFileListing()
@@ -8377,7 +8399,7 @@ var init_prompt4 = __esm({
8377
8399
 
8378
8400
  // src/config.ts
8379
8401
  import fs22 from "fs";
8380
- import path11 from "path";
8402
+ import path12 from "path";
8381
8403
  import os from "os";
8382
8404
  function loadConfigFile() {
8383
8405
  try {
@@ -8420,7 +8442,7 @@ var init_config = __esm({
8420
8442
  "use strict";
8421
8443
  init_logger();
8422
8444
  log13 = createLogger("config");
8423
- CONFIG_PATH = path11.join(
8445
+ CONFIG_PATH = path12.join(
8424
8446
  os.homedir(),
8425
8447
  ".mindstudio-local-tunnel",
8426
8448
  "config.json"
@@ -9701,7 +9723,7 @@ var init_headless = __esm({
9701
9723
  import { render } from "ink";
9702
9724
  import os2 from "os";
9703
9725
  import fs23 from "fs";
9704
- import path12 from "path";
9726
+ import path13 from "path";
9705
9727
 
9706
9728
  // src/tui/App.tsx
9707
9729
  import { useState as useState2, useCallback, useRef } from "react";
@@ -10023,7 +10045,7 @@ var startupLog = createLogger("startup");
10023
10045
  function printDebugInfo(config) {
10024
10046
  const pkg = JSON.parse(
10025
10047
  fs23.readFileSync(
10026
- path12.join(import.meta.dirname, "..", "package.json"),
10048
+ path13.join(import.meta.dirname, "..", "package.json"),
10027
10049
  "utf-8"
10028
10050
  )
10029
10051
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.240",
3
+ "version": "0.1.241",
4
4
  "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",