@mindstudio-ai/remy 0.1.162 → 0.1.164

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.
@@ -55,7 +55,7 @@ declare class HeadlessSession {
55
55
  private earlyResults;
56
56
  private pendingBlockUpdates;
57
57
  private toolRegistry;
58
- private readline;
58
+ private stdinBuffer;
59
59
  constructor(opts?: HeadlessOptions);
60
60
  start(): Promise<void>;
61
61
  private shutdown;
package/dist/headless.js CHANGED
@@ -4,9 +4,6 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // src/headless/index.ts
8
- import { createInterface } from "readline";
9
-
10
7
  // src/logger.ts
11
8
  import fs from "fs";
12
9
  var LEVELS = {
@@ -1395,7 +1392,7 @@ var setProjectOnboardingStateTool = {
1395
1392
  clearable: false,
1396
1393
  definition: {
1397
1394
  name: "setProjectOnboardingState",
1398
- description: "Advance the project onboarding state. Only call this when an automated action explicitly instructs you to \u2014 calling it at the wrong time skips stages the user hasn't experienced. Forward-only: building \u2192 buildComplete \u2192 onboardingFinished. `onboardingFinished` is set by the frontend after the user dismisses the reveal; do not call it yourself.",
1395
+ 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.",
1399
1396
  inputSchema: {
1400
1397
  type: "object",
1401
1398
  properties: {
@@ -2943,8 +2940,15 @@ ${summaryBlock.text}
2943
2940
  }
2944
2941
  return true;
2945
2942
  }).map((msg) => {
2946
- if (msg.role === "user" && typeof msg.content === "string" && isAutomatedMessage(msg.content)) {
2947
- return { ...msg, content: stripSentinelLine(msg.content) };
2943
+ if (msg.role === "user" && typeof msg.content === "string") {
2944
+ const { attachmentHeader, ...rest } = msg;
2945
+ let content = isAutomatedMessage(msg.content) ? stripSentinelLine(msg.content) : msg.content;
2946
+ if (attachmentHeader) {
2947
+ content = content ? `${attachmentHeader}
2948
+
2949
+ ${content}` : attachmentHeader;
2950
+ }
2951
+ return { ...rest, content };
2948
2952
  }
2949
2953
  if (!Array.isArray(msg.content)) {
2950
2954
  return msg;
@@ -5775,6 +5779,7 @@ async function runTurn(params) {
5775
5779
  state,
5776
5780
  userMessage,
5777
5781
  attachments,
5782
+ attachmentHeader,
5778
5783
  apiConfig,
5779
5784
  system,
5780
5785
  model,
@@ -5811,6 +5816,9 @@ async function runTurn(params) {
5811
5816
  if (hasAttachments) {
5812
5817
  userMsg.attachments = attachments;
5813
5818
  }
5819
+ if (attachmentHeader) {
5820
+ userMsg.attachmentHeader = attachmentHeader;
5821
+ }
5814
5822
  state.messages.push(userMsg);
5815
5823
  onEvent({
5816
5824
  type: "user_message",
@@ -6655,8 +6663,8 @@ var HeadlessSession = class {
6655
6663
  pendingBlockUpdates = [];
6656
6664
  // Tool lifecycle management — shared across all nesting depths
6657
6665
  toolRegistry = new ToolRegistry();
6658
- // IO
6659
- readline = null;
6666
+ // IO — accumulates stdin bytes between newline boundaries
6667
+ stdinBuffer = "";
6660
6668
  constructor(opts = {}) {
6661
6669
  this.opts = opts;
6662
6670
  }
@@ -6687,9 +6695,24 @@ var HeadlessSession = class {
6687
6695
  }
6688
6696
  triggerBrandExtraction(this.config);
6689
6697
  this.toolRegistry.onEvent = this.onEvent;
6690
- this.readline = createInterface({ input: process.stdin });
6691
- this.readline.on("line", this.handleStdinLine);
6692
- this.readline.on("close", () => {
6698
+ process.stdin.setEncoding("utf-8");
6699
+ process.stdin.on("data", (chunk) => {
6700
+ this.stdinBuffer += chunk;
6701
+ let nlIdx;
6702
+ while ((nlIdx = this.stdinBuffer.indexOf("\n")) !== -1) {
6703
+ const endIdx = nlIdx > 0 && this.stdinBuffer[nlIdx - 1] === "\r" ? nlIdx - 1 : nlIdx;
6704
+ const line = this.stdinBuffer.slice(0, endIdx);
6705
+ this.stdinBuffer = this.stdinBuffer.slice(nlIdx + 1);
6706
+ if (line.length > 0) {
6707
+ void this.handleStdinLine(line);
6708
+ }
6709
+ }
6710
+ });
6711
+ process.stdin.on("end", () => {
6712
+ if (this.stdinBuffer.length > 0) {
6713
+ void this.handleStdinLine(this.stdinBuffer);
6714
+ this.stdinBuffer = "";
6715
+ }
6693
6716
  this.emit("stopping");
6694
6717
  this.emit("stopped");
6695
6718
  process.exit(0);
@@ -7012,15 +7035,14 @@ var HeadlessSession = class {
7012
7035
  });
7013
7036
  }
7014
7037
  let userMessage = parsed.text ?? "";
7038
+ let attachmentHeader;
7015
7039
  if (attachments?.some((a) => !a.isVoice)) {
7016
7040
  try {
7017
7041
  const { documents, images } = await persistAttachments(attachments);
7018
7042
  const all = [...documents, ...images];
7019
7043
  const header = buildUploadHeader(all);
7020
7044
  if (header) {
7021
- userMessage = userMessage ? `${header}
7022
-
7023
- ${userMessage}` : header;
7045
+ attachmentHeader = header;
7024
7046
  }
7025
7047
  } catch (err) {
7026
7048
  log14.warn("Attachment persistence failed", { error: err.message });
@@ -7063,6 +7085,7 @@ ${userMessage}` : header;
7063
7085
  state: this.state,
7064
7086
  userMessage,
7065
7087
  attachments,
7088
+ attachmentHeader,
7066
7089
  apiConfig: this.config,
7067
7090
  system,
7068
7091
  model: this.opts.model,
@@ -7223,7 +7246,12 @@ ${userMessage}` : header;
7223
7246
  let parsed;
7224
7247
  try {
7225
7248
  parsed = JSON.parse(line);
7226
- } catch {
7249
+ } catch (err) {
7250
+ log14.warn("Invalid JSON on stdin", {
7251
+ error: err.message,
7252
+ lineLength: line.length,
7253
+ preview: line.slice(0, 200)
7254
+ });
7227
7255
  this.emit("error", { error: "Invalid JSON on stdin" });
7228
7256
  return;
7229
7257
  }
package/dist/index.js CHANGED
@@ -919,7 +919,7 @@ var init_setProjectOnboardingState = __esm({
919
919
  clearable: false,
920
920
  definition: {
921
921
  name: "setProjectOnboardingState",
922
- description: "Advance the project onboarding state. Only call this when an automated action explicitly instructs you to \u2014 calling it at the wrong time skips stages the user hasn't experienced. Forward-only: building \u2192 buildComplete \u2192 onboardingFinished. `onboardingFinished` is set by the frontend after the user dismisses the reveal; do not call it yourself.",
922
+ 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.",
923
923
  inputSchema: {
924
924
  type: "object",
925
925
  properties: {
@@ -3238,8 +3238,15 @@ ${summaryBlock.text}
3238
3238
  }
3239
3239
  return true;
3240
3240
  }).map((msg) => {
3241
- if (msg.role === "user" && typeof msg.content === "string" && isAutomatedMessage(msg.content)) {
3242
- return { ...msg, content: stripSentinelLine(msg.content) };
3241
+ if (msg.role === "user" && typeof msg.content === "string") {
3242
+ const { attachmentHeader, ...rest } = msg;
3243
+ let content = isAutomatedMessage(msg.content) ? stripSentinelLine(msg.content) : msg.content;
3244
+ if (attachmentHeader) {
3245
+ content = content ? `${attachmentHeader}
3246
+
3247
+ ${content}` : attachmentHeader;
3248
+ }
3249
+ return { ...rest, content };
3243
3250
  }
3244
3251
  if (!Array.isArray(msg.content)) {
3245
3252
  return msg;
@@ -6374,6 +6381,7 @@ async function runTurn(params) {
6374
6381
  state,
6375
6382
  userMessage,
6376
6383
  attachments,
6384
+ attachmentHeader,
6377
6385
  apiConfig,
6378
6386
  system,
6379
6387
  model,
@@ -6410,6 +6418,9 @@ async function runTurn(params) {
6410
6418
  if (hasAttachments) {
6411
6419
  userMsg.attachments = attachments;
6412
6420
  }
6421
+ if (attachmentHeader) {
6422
+ userMsg.attachmentHeader = attachmentHeader;
6423
+ }
6413
6424
  state.messages.push(userMsg);
6414
6425
  onEvent({
6415
6426
  type: "user_message",
@@ -7344,7 +7355,6 @@ var headless_exports = {};
7344
7355
  __export(headless_exports, {
7345
7356
  HeadlessSession: () => HeadlessSession
7346
7357
  });
7347
- import { createInterface } from "readline";
7348
7358
  var log14, EXTERNAL_TOOL_TIMEOUT_MS, USER_FACING_TOOLS, HeadlessSession;
7349
7359
  var init_headless = __esm({
7350
7360
  "src/headless/index.ts"() {
@@ -7407,8 +7417,8 @@ var init_headless = __esm({
7407
7417
  pendingBlockUpdates = [];
7408
7418
  // Tool lifecycle management — shared across all nesting depths
7409
7419
  toolRegistry = new ToolRegistry();
7410
- // IO
7411
- readline = null;
7420
+ // IO — accumulates stdin bytes between newline boundaries
7421
+ stdinBuffer = "";
7412
7422
  constructor(opts = {}) {
7413
7423
  this.opts = opts;
7414
7424
  }
@@ -7439,9 +7449,24 @@ var init_headless = __esm({
7439
7449
  }
7440
7450
  triggerBrandExtraction(this.config);
7441
7451
  this.toolRegistry.onEvent = this.onEvent;
7442
- this.readline = createInterface({ input: process.stdin });
7443
- this.readline.on("line", this.handleStdinLine);
7444
- this.readline.on("close", () => {
7452
+ process.stdin.setEncoding("utf-8");
7453
+ process.stdin.on("data", (chunk) => {
7454
+ this.stdinBuffer += chunk;
7455
+ let nlIdx;
7456
+ while ((nlIdx = this.stdinBuffer.indexOf("\n")) !== -1) {
7457
+ const endIdx = nlIdx > 0 && this.stdinBuffer[nlIdx - 1] === "\r" ? nlIdx - 1 : nlIdx;
7458
+ const line = this.stdinBuffer.slice(0, endIdx);
7459
+ this.stdinBuffer = this.stdinBuffer.slice(nlIdx + 1);
7460
+ if (line.length > 0) {
7461
+ void this.handleStdinLine(line);
7462
+ }
7463
+ }
7464
+ });
7465
+ process.stdin.on("end", () => {
7466
+ if (this.stdinBuffer.length > 0) {
7467
+ void this.handleStdinLine(this.stdinBuffer);
7468
+ this.stdinBuffer = "";
7469
+ }
7445
7470
  this.emit("stopping");
7446
7471
  this.emit("stopped");
7447
7472
  process.exit(0);
@@ -7764,15 +7789,14 @@ var init_headless = __esm({
7764
7789
  });
7765
7790
  }
7766
7791
  let userMessage = parsed.text ?? "";
7792
+ let attachmentHeader;
7767
7793
  if (attachments?.some((a) => !a.isVoice)) {
7768
7794
  try {
7769
7795
  const { documents, images } = await persistAttachments(attachments);
7770
7796
  const all = [...documents, ...images];
7771
7797
  const header = buildUploadHeader(all);
7772
7798
  if (header) {
7773
- userMessage = userMessage ? `${header}
7774
-
7775
- ${userMessage}` : header;
7799
+ attachmentHeader = header;
7776
7800
  }
7777
7801
  } catch (err) {
7778
7802
  log14.warn("Attachment persistence failed", { error: err.message });
@@ -7815,6 +7839,7 @@ ${userMessage}` : header;
7815
7839
  state: this.state,
7816
7840
  userMessage,
7817
7841
  attachments,
7842
+ attachmentHeader,
7818
7843
  apiConfig: this.config,
7819
7844
  system,
7820
7845
  model: this.opts.model,
@@ -7975,7 +8000,12 @@ ${userMessage}` : header;
7975
8000
  let parsed;
7976
8001
  try {
7977
8002
  parsed = JSON.parse(line);
7978
- } catch {
8003
+ } catch (err) {
8004
+ log14.warn("Invalid JSON on stdin", {
8005
+ error: err.message,
8006
+ lineLength: line.length,
8007
+ preview: line.slice(0, 200)
8008
+ });
7979
8009
  this.emit("error", { error: "Invalid JSON on stdin" });
7980
8010
  return;
7981
8011
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.162",
3
+ "version": "0.1.164",
4
4
  "description": "MindStudio coding agent",
5
5
  "repository": {
6
6
  "type": "git",