@mindstudio-ai/remy 0.1.136 → 0.1.138

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.
@@ -29,4 +29,4 @@ The initial build prioritizes getting everything connected and functional, but t
29
29
 
30
30
  Then, ask the `visualDesignExpert` to take a screenshot and verity that the visual design looks correct. Fix any issues it flags - we want the user's first time seeing the finished product to truly wow them.
31
31
 
32
- When everything is working, use `productVision` to mark the MVP roadmap item as done, then call `setProjectOnboardingState({ state: "onboardingFinished" })`.
32
+ When everything is working, use `productVision` to mark the MVP roadmap item as done, then call `setProjectOnboardingState({ state: "onboardingFinished" })`. Finally, call `compactConversation` to summarize the build session and free up context for the next phase of work.
@@ -12,4 +12,4 @@ Then, put together a plan to build out the feature. Present the plan to the user
12
12
 
13
13
  When they've approved the plan, be sure to update the spec first - remember, the spec is the source of truth about the product. Then, build everything in one turn, using the spec as the master plan.
14
14
 
15
- When you're finished, verify your work, then tell`productVision` what was done so it can update the roadmap to reflect the progress. Give the user a summary of what was done.
15
+ When you're finished, verify your work, then tell `productVision` what was done so it can update the roadmap to reflect the progress. Give the user a summary of what was done, then call `compactConversation` to summarize the build session and free up context.
@@ -0,0 +1,9 @@
1
+ ---
2
+ trigger: debugRequest
3
+ ---
4
+
5
+ This is an automated message triggered by the user having clicked "Debug" in the "Request" log detail in MindStudio UI. Find the request in .logs/requests.ndjson by its ID. If there is an error, fix it immediately - otherwise, explain the request at a high-level in non-technical/natural language and see what the user wishes to do with it. Remember, the user can't see this message, so keep that in mind when responding.
6
+
7
+ <request_id>
8
+ {{requestId}}
9
+ </request_id>
package/dist/headless.js CHANGED
@@ -1739,6 +1739,29 @@ var setProjectMetadataTool = {
1739
1739
  }
1740
1740
  };
1741
1741
 
1742
+ // src/tools/common/compactConversation.ts
1743
+ var compactConversationTool = {
1744
+ clearable: false,
1745
+ definition: {
1746
+ name: "compactConversation",
1747
+ 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. Use this when you have just finished a large block of mechanical work (building, refactoring, debugging) and are about to shift back into conversational mode with the user. Runs in the background. Do not use after small changes like fixing a bug or editing copy.",
1748
+ inputSchema: {
1749
+ type: "object",
1750
+ properties: {}
1751
+ }
1752
+ },
1753
+ async execute(_input, context) {
1754
+ if (!context?.conversationMessages || !context.apiConfig) {
1755
+ return "Error: compaction requires execution context.";
1756
+ }
1757
+ triggerCompaction(
1758
+ { messages: context.conversationMessages },
1759
+ context.apiConfig
1760
+ );
1761
+ return "Compaction started in the background.";
1762
+ }
1763
+ };
1764
+
1742
1765
  // src/tools/code/readFile.ts
1743
1766
  import fs9 from "fs/promises";
1744
1767
  var DEFAULT_MAX_LINES2 = 500;
@@ -4997,6 +5020,7 @@ var ALL_TOOLS = [
4997
5020
  designExpertTool,
4998
5021
  productVisionTool,
4999
5022
  codeSanityCheckTool,
5023
+ compactConversationTool,
5000
5024
  // Post-onboarding
5001
5025
  clearSyncStatusTool,
5002
5026
  presentSyncPlanTool,
@@ -5115,6 +5139,24 @@ function clearSession(state) {
5115
5139
  }
5116
5140
  }
5117
5141
 
5142
+ // src/compaction/trigger.ts
5143
+ var log8 = createLogger("compaction:trigger");
5144
+ function triggerCompaction(state, apiConfig, callbacks) {
5145
+ callbacks?.onStart?.();
5146
+ const system = buildSystemPrompt("onboardingFinished");
5147
+ const tools2 = getToolDefinitions("onboardingFinished");
5148
+ compactConversation(state, apiConfig, system, tools2).then(() => {
5149
+ saveSession(state);
5150
+ callbacks?.onComplete?.();
5151
+ log8.info("Compaction complete");
5152
+ }).catch((err) => {
5153
+ callbacks?.onError?.(err.message || "Compaction failed");
5154
+ log8.error("Compaction failed", { error: err.message });
5155
+ }).finally(() => {
5156
+ callbacks?.onFinally?.();
5157
+ });
5158
+ }
5159
+
5118
5160
  // src/parsePartialJson.ts
5119
5161
  var PartialJSON = class extends Error {
5120
5162
  };
@@ -5305,7 +5347,7 @@ function friendlyError(raw) {
5305
5347
  }
5306
5348
 
5307
5349
  // src/agent.ts
5308
- var log8 = createLogger("agent");
5350
+ var log9 = createLogger("agent");
5309
5351
  function getTextContent(blocks) {
5310
5352
  return blocks.filter((b) => b.type === "text").map((b) => b.text).join("");
5311
5353
  }
@@ -5350,7 +5392,7 @@ async function runTurn(params) {
5350
5392
  } = params;
5351
5393
  const tools2 = getToolDefinitions(onboardingState);
5352
5394
  const excludeToolsFromClearing = tools2.filter((t) => !CLEARABLE_TOOLS.has(t.name)).map((t) => t.name);
5353
- log8.info("Turn started", {
5395
+ log9.info("Turn started", {
5354
5396
  requestId,
5355
5397
  model,
5356
5398
  toolCount: tools2.length,
@@ -5574,7 +5616,7 @@ async function runTurn(params) {
5574
5616
  const tool = getToolByName(event.name);
5575
5617
  const wasStreamed = acc?.started ?? false;
5576
5618
  const isInputStreaming = !!tool?.streaming?.partialInput;
5577
- log8.info("Tool received", {
5619
+ log9.info("Tool received", {
5578
5620
  requestId,
5579
5621
  toolCallId: event.id,
5580
5622
  name: event.name
@@ -5621,7 +5663,14 @@ async function runTurn(params) {
5621
5663
  });
5622
5664
  state.messages.push({
5623
5665
  role: "assistant",
5624
- content: [...contentBlocks].sort((a, b) => a.startedAt - b.startedAt)
5666
+ content: [...contentBlocks].sort((a, b) => a.startedAt - b.startedAt),
5667
+ usage: {
5668
+ inputTokens: turnInputTokens,
5669
+ outputTokens: turnOutputTokens,
5670
+ cacheCreationTokens: turnCacheCreation || void 0,
5671
+ cacheReadTokens: turnCacheRead || void 0,
5672
+ llmCalls: turnLlmCalls
5673
+ }
5625
5674
  });
5626
5675
  }
5627
5676
  onEvent({ type: "turn_cancelled" });
@@ -5631,7 +5680,14 @@ async function runTurn(params) {
5631
5680
  if (contentBlocks.length > 0) {
5632
5681
  state.messages.push({
5633
5682
  role: "assistant",
5634
- content: [...contentBlocks].sort((a, b) => a.startedAt - b.startedAt)
5683
+ content: [...contentBlocks].sort((a, b) => a.startedAt - b.startedAt),
5684
+ usage: {
5685
+ inputTokens: turnInputTokens,
5686
+ outputTokens: turnOutputTokens,
5687
+ cacheCreationTokens: turnCacheCreation || void 0,
5688
+ cacheReadTokens: turnCacheRead || void 0,
5689
+ llmCalls: turnLlmCalls
5690
+ }
5635
5691
  });
5636
5692
  }
5637
5693
  const toolCalls = getToolCalls(contentBlocks);
@@ -5653,7 +5709,7 @@ async function runTurn(params) {
5653
5709
  });
5654
5710
  return;
5655
5711
  }
5656
- log8.info("Tools executing", {
5712
+ log9.info("Tools executing", {
5657
5713
  requestId,
5658
5714
  count: toolCalls.length,
5659
5715
  tools: toolCalls.map((tc) => tc.name)
@@ -5700,7 +5756,7 @@ async function runTurn(params) {
5700
5756
  let result;
5701
5757
  if (EXTERNAL_TOOLS.has(tc.name) && resolveExternalTool) {
5702
5758
  saveSession(state);
5703
- log8.info("Waiting for external tool result", {
5759
+ log9.info("Waiting for external tool result", {
5704
5760
  requestId,
5705
5761
  toolCallId: tc.id,
5706
5762
  name: tc.name
@@ -5757,7 +5813,7 @@ async function runTurn(params) {
5757
5813
  if (!tc.input.background) {
5758
5814
  toolRegistry?.unregister(tc.id);
5759
5815
  }
5760
- log8.info("Tool completed", {
5816
+ log9.info("Tool completed", {
5761
5817
  requestId,
5762
5818
  toolCallId: tc.id,
5763
5819
  name: tc.name,
@@ -5812,7 +5868,7 @@ async function runTurn(params) {
5812
5868
  }
5813
5869
 
5814
5870
  // src/toolRegistry.ts
5815
- var log9 = createLogger("tool-registry");
5871
+ var log10 = createLogger("tool-registry");
5816
5872
  var ToolRegistry = class {
5817
5873
  entries = /* @__PURE__ */ new Map();
5818
5874
  onEvent;
@@ -5838,7 +5894,7 @@ var ToolRegistry = class {
5838
5894
  if (!entry) {
5839
5895
  return false;
5840
5896
  }
5841
- log9.info("Tool stopped", { toolCallId: id, name: entry.name, mode });
5897
+ log10.info("Tool stopped", { toolCallId: id, name: entry.name, mode });
5842
5898
  entry.abortController.abort(mode);
5843
5899
  if (mode === "graceful") {
5844
5900
  const partial = entry.getPartialResult?.() ?? "";
@@ -5871,7 +5927,7 @@ ${partial}` : "[INTERRUPTED] Tool execution was stopped.";
5871
5927
  if (!entry) {
5872
5928
  return false;
5873
5929
  }
5874
- log9.info("Tool restarted", { toolCallId: id, name: entry.name });
5930
+ log10.info("Tool restarted", { toolCallId: id, name: entry.name });
5875
5931
  entry.abortController.abort("restart");
5876
5932
  const newInput = patchedInput ? { ...entry.input, ...patchedInput } : entry.input;
5877
5933
  this.onEvent?.({
@@ -5916,7 +5972,7 @@ ${body}`;
5916
5972
  }
5917
5973
 
5918
5974
  // src/headless.ts
5919
- var log10 = createLogger("headless");
5975
+ var log11 = createLogger("headless");
5920
5976
  function emit(event, data, requestId) {
5921
5977
  const payload = { event, ...data };
5922
5978
  if (requestId) {
@@ -6032,7 +6088,7 @@ ${xmlParts}
6032
6088
  }
6033
6089
  function onBackgroundComplete(toolCallId, name, result, subAgentMessages) {
6034
6090
  pendingBlockUpdates.push({ toolCallId, result, subAgentMessages });
6035
- log10.info("Background complete", {
6091
+ log11.info("Background complete", {
6036
6092
  toolCallId,
6037
6093
  name,
6038
6094
  requestId: currentRequestId
@@ -6304,7 +6360,7 @@ ${xmlParts}
6304
6360
  requestId
6305
6361
  );
6306
6362
  }
6307
- log10.info("Turn complete", {
6363
+ log11.info("Turn complete", {
6308
6364
  requestId,
6309
6365
  durationMs: Date.now() - turnStart
6310
6366
  });
@@ -6313,7 +6369,7 @@ ${xmlParts}
6313
6369
  emit("error", { error: err.message }, requestId);
6314
6370
  emit("completed", { success: false, error: err.message }, requestId);
6315
6371
  }
6316
- log10.warn("Command failed", {
6372
+ log11.warn("Command failed", {
6317
6373
  action: "message",
6318
6374
  requestId,
6319
6375
  error: err.message
@@ -6333,7 +6389,7 @@ ${xmlParts}
6333
6389
  return;
6334
6390
  }
6335
6391
  const { action, requestId } = parsed;
6336
- log10.info("Command received", { action, requestId });
6392
+ log11.info("Command received", { action, requestId });
6337
6393
  if (action === "tool_result" && parsed.id) {
6338
6394
  const id = parsed.id;
6339
6395
  const result = parsed.result ?? "";
@@ -6342,7 +6398,7 @@ ${xmlParts}
6342
6398
  pendingTools.delete(id);
6343
6399
  pending.resolve(result);
6344
6400
  } else if (!running) {
6345
- log10.info("Late tool_result while idle, dismissing", { id });
6401
+ log11.info("Late tool_result while idle, dismissing", { id });
6346
6402
  emit("completed", { success: true }, requestId);
6347
6403
  } else {
6348
6404
  earlyResults.set(id, result);
@@ -6398,36 +6454,31 @@ ${xmlParts}
6398
6454
  return;
6399
6455
  }
6400
6456
  if (action === "compact") {
6401
- sessionStats.compactionInProgress = true;
6402
- sessionStats.updatedAt = Date.now();
6403
- try {
6404
- writeFileSync(".remy-stats.json", JSON.stringify(sessionStats));
6405
- } catch {
6406
- }
6407
- const compactSystem = buildSystemPrompt("onboardingFinished");
6408
- const compactTools = getToolDefinitions("onboardingFinished");
6409
- compactConversation(state, config, compactSystem, compactTools).then(() => {
6410
- saveSession(state);
6411
- emit("compaction_complete", {}, requestId);
6412
- emit("completed", { success: true }, requestId);
6413
- }).catch((err) => {
6414
- emit(
6415
- "compaction_complete",
6416
- { error: err.message || "Compaction failed" },
6417
- requestId
6418
- );
6419
- emit(
6420
- "completed",
6421
- { success: false, error: err.message || "Compaction failed" },
6422
- requestId
6423
- );
6424
- }).finally(() => {
6425
- sessionStats.compactionInProgress = false;
6426
- sessionStats.messageCount = state.messages.length;
6427
- sessionStats.updatedAt = Date.now();
6428
- try {
6429
- writeFileSync(".remy-stats.json", JSON.stringify(sessionStats));
6430
- } catch {
6457
+ triggerCompaction(state, config, {
6458
+ onStart: () => {
6459
+ sessionStats.compactionInProgress = true;
6460
+ sessionStats.updatedAt = Date.now();
6461
+ try {
6462
+ writeFileSync(".remy-stats.json", JSON.stringify(sessionStats));
6463
+ } catch {
6464
+ }
6465
+ },
6466
+ onComplete: () => {
6467
+ emit("compaction_complete", {}, requestId);
6468
+ emit("completed", { success: true }, requestId);
6469
+ },
6470
+ onError: (error) => {
6471
+ emit("compaction_complete", { error }, requestId);
6472
+ emit("completed", { success: false, error }, requestId);
6473
+ },
6474
+ onFinally: () => {
6475
+ sessionStats.compactionInProgress = false;
6476
+ sessionStats.messageCount = state.messages.length;
6477
+ sessionStats.updatedAt = Date.now();
6478
+ try {
6479
+ writeFileSync(".remy-stats.json", JSON.stringify(sessionStats));
6480
+ } catch {
6481
+ }
6431
6482
  }
6432
6483
  });
6433
6484
  return;