@mindstudio-ai/remy 0.1.149 → 0.1.151
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.d.ts +4 -0
- package/dist/headless.js +61 -20
- package/dist/index.js +61 -20
- package/package.json +1 -1
package/dist/headless.d.ts
CHANGED
|
@@ -90,6 +90,10 @@ declare class HeadlessSession {
|
|
|
90
90
|
/**
|
|
91
91
|
* Drain the queue in strict FIFO order. Caller must hold `running = true`.
|
|
92
92
|
* User messages arriving during the drain will be enqueued behind current items.
|
|
93
|
+
*
|
|
94
|
+
* Consecutive background-source items are coalesced into a single turn so
|
|
95
|
+
* the LLM sees all the background results together and produces one
|
|
96
|
+
* acknowledgment, not N separate ones.
|
|
93
97
|
*/
|
|
94
98
|
private drainQueueLoop;
|
|
95
99
|
/**
|
package/dist/headless.js
CHANGED
|
@@ -537,6 +537,12 @@ async function* streamChat(params) {
|
|
|
537
537
|
}
|
|
538
538
|
}
|
|
539
539
|
}
|
|
540
|
+
if (buffer.startsWith("data: ")) {
|
|
541
|
+
try {
|
|
542
|
+
yield JSON.parse(buffer.slice(6));
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
}
|
|
540
546
|
if (!receivedDone) {
|
|
541
547
|
log2.warn("Stream ended without done event", {
|
|
542
548
|
requestId,
|
|
@@ -544,12 +550,10 @@ async function* streamChat(params) {
|
|
|
544
550
|
durationMs: Date.now() - startTime,
|
|
545
551
|
remainingBuffer: buffer.slice(0, 200)
|
|
546
552
|
});
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
} catch {
|
|
552
|
-
}
|
|
553
|
+
yield {
|
|
554
|
+
type: "error",
|
|
555
|
+
error: "Network error: stream ended before completion"
|
|
556
|
+
};
|
|
553
557
|
}
|
|
554
558
|
}
|
|
555
559
|
var MAX_RETRIES = 5;
|
|
@@ -2778,12 +2782,23 @@ function buildBackgroundResultsMessage(results) {
|
|
|
2778
2782
|
${r.result}
|
|
2779
2783
|
</tool_result>`
|
|
2780
2784
|
).join("\n\n");
|
|
2781
|
-
const
|
|
2785
|
+
const plural = results.length > 1 ? "s" : "";
|
|
2786
|
+
const body = `This is an automated message containing the result${plural} of ${results.length > 1 ? "tool calls" : "a tool call"} that ${results.length > 1 ? "have" : "has"} been working in the background. This is not a direct message from the user.
|
|
2782
2787
|
<background_results>
|
|
2783
2788
|
${xml}
|
|
2784
2789
|
</background_results>`;
|
|
2785
2790
|
return automatedMessage("background_results", body);
|
|
2786
2791
|
}
|
|
2792
|
+
function mergeBackgroundResultsMessages(messages) {
|
|
2793
|
+
const results = [];
|
|
2794
|
+
const toolRe = /<tool_result id="([^"]+)" name="([^"]+)">\n([\s\S]*?)\n<\/tool_result>/g;
|
|
2795
|
+
for (const msg of messages) {
|
|
2796
|
+
for (const m of msg.matchAll(toolRe)) {
|
|
2797
|
+
results.push({ toolCallId: m[1], name: m[2], result: m[3] });
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
return buildBackgroundResultsMessage(results);
|
|
2801
|
+
}
|
|
2787
2802
|
|
|
2788
2803
|
// src/subagents/common/cleanMessages.ts
|
|
2789
2804
|
function findLastSummaryCheckpoint(messages, name) {
|
|
@@ -2807,9 +2822,9 @@ function fixOrphanedToolCalls(messages) {
|
|
|
2807
2822
|
toolResultIds.add(msg.toolCallId);
|
|
2808
2823
|
}
|
|
2809
2824
|
}
|
|
2810
|
-
const result = [
|
|
2811
|
-
for (
|
|
2812
|
-
|
|
2825
|
+
const result = [];
|
|
2826
|
+
for (const msg of messages) {
|
|
2827
|
+
result.push(msg);
|
|
2813
2828
|
if (msg.role !== "assistant" || !Array.isArray(msg.content)) {
|
|
2814
2829
|
continue;
|
|
2815
2830
|
}
|
|
@@ -2817,17 +2832,15 @@ function fixOrphanedToolCalls(messages) {
|
|
|
2817
2832
|
(b) => b.type === "tool"
|
|
2818
2833
|
);
|
|
2819
2834
|
const orphans = toolBlocks.filter((tc) => !toolResultIds.has(tc.id));
|
|
2820
|
-
|
|
2821
|
-
|
|
2835
|
+
for (const tc of orphans) {
|
|
2836
|
+
result.push({
|
|
2837
|
+
role: "user",
|
|
2838
|
+
content: "Error: tool result lost (session recovered)",
|
|
2839
|
+
toolCallId: tc.id,
|
|
2840
|
+
isToolError: true
|
|
2841
|
+
});
|
|
2842
|
+
toolResultIds.add(tc.id);
|
|
2822
2843
|
}
|
|
2823
|
-
const synthetics = orphans.map((tc) => ({
|
|
2824
|
-
role: "user",
|
|
2825
|
-
content: "Error: tool result lost (session recovered)",
|
|
2826
|
-
toolCallId: tc.id,
|
|
2827
|
-
isToolError: true
|
|
2828
|
-
}));
|
|
2829
|
-
result.splice(i + 1, 0, ...synthetics);
|
|
2830
|
-
break;
|
|
2831
2844
|
}
|
|
2832
2845
|
return result;
|
|
2833
2846
|
}
|
|
@@ -6246,6 +6259,10 @@ var MessageQueue = class {
|
|
|
6246
6259
|
snapshot() {
|
|
6247
6260
|
return [...this.items];
|
|
6248
6261
|
}
|
|
6262
|
+
/** Return the next item without removing it. */
|
|
6263
|
+
peek() {
|
|
6264
|
+
return this.items[0];
|
|
6265
|
+
}
|
|
6249
6266
|
get length() {
|
|
6250
6267
|
return this.items.length;
|
|
6251
6268
|
}
|
|
@@ -6810,6 +6827,10 @@ ${userMessage}` : header;
|
|
|
6810
6827
|
/**
|
|
6811
6828
|
* Drain the queue in strict FIFO order. Caller must hold `running = true`.
|
|
6812
6829
|
* User messages arriving during the drain will be enqueued behind current items.
|
|
6830
|
+
*
|
|
6831
|
+
* Consecutive background-source items are coalesced into a single turn so
|
|
6832
|
+
* the LLM sees all the background results together and produces one
|
|
6833
|
+
* acknowledgment, not N separate ones.
|
|
6813
6834
|
*/
|
|
6814
6835
|
async drainQueueLoop() {
|
|
6815
6836
|
while (true) {
|
|
@@ -6817,6 +6838,26 @@ ${userMessage}` : header;
|
|
|
6817
6838
|
if (!next) {
|
|
6818
6839
|
break;
|
|
6819
6840
|
}
|
|
6841
|
+
if (next.source === "background") {
|
|
6842
|
+
const batch = [next];
|
|
6843
|
+
while (this.queue.peek()?.source === "background") {
|
|
6844
|
+
const more = this.queue.shift();
|
|
6845
|
+
if (more) {
|
|
6846
|
+
batch.push(more);
|
|
6847
|
+
}
|
|
6848
|
+
}
|
|
6849
|
+
const combinedCommand = {
|
|
6850
|
+
action: "message",
|
|
6851
|
+
text: mergeBackgroundResultsMessages(
|
|
6852
|
+
batch.map((b) => b.command.text ?? "")
|
|
6853
|
+
),
|
|
6854
|
+
...this.currentOnboardingState && {
|
|
6855
|
+
onboardingState: this.currentOnboardingState
|
|
6856
|
+
}
|
|
6857
|
+
};
|
|
6858
|
+
await this.runSingleTurn(combinedCommand, `background-${Date.now()}`);
|
|
6859
|
+
continue;
|
|
6860
|
+
}
|
|
6820
6861
|
const nextRid = next.command.requestId ?? `${next.source}-${Date.now()}`;
|
|
6821
6862
|
await this.runSingleTurn(next.command, nextRid);
|
|
6822
6863
|
}
|
package/dist/index.js
CHANGED
|
@@ -222,6 +222,12 @@ async function* streamChat(params) {
|
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
|
+
if (buffer.startsWith("data: ")) {
|
|
226
|
+
try {
|
|
227
|
+
yield JSON.parse(buffer.slice(6));
|
|
228
|
+
} catch {
|
|
229
|
+
}
|
|
230
|
+
}
|
|
225
231
|
if (!receivedDone) {
|
|
226
232
|
log.warn("Stream ended without done event", {
|
|
227
233
|
requestId,
|
|
@@ -229,12 +235,10 @@ async function* streamChat(params) {
|
|
|
229
235
|
durationMs: Date.now() - startTime,
|
|
230
236
|
remainingBuffer: buffer.slice(0, 200)
|
|
231
237
|
});
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
} catch {
|
|
237
|
-
}
|
|
238
|
+
yield {
|
|
239
|
+
type: "error",
|
|
240
|
+
error: "Network error: stream ended before completion"
|
|
241
|
+
};
|
|
238
242
|
}
|
|
239
243
|
}
|
|
240
244
|
function isRetryableError(error) {
|
|
@@ -3069,12 +3073,23 @@ function buildBackgroundResultsMessage(results) {
|
|
|
3069
3073
|
${r.result}
|
|
3070
3074
|
</tool_result>`
|
|
3071
3075
|
).join("\n\n");
|
|
3072
|
-
const
|
|
3076
|
+
const plural = results.length > 1 ? "s" : "";
|
|
3077
|
+
const body = `This is an automated message containing the result${plural} of ${results.length > 1 ? "tool calls" : "a tool call"} that ${results.length > 1 ? "have" : "has"} been working in the background. This is not a direct message from the user.
|
|
3073
3078
|
<background_results>
|
|
3074
3079
|
${xml}
|
|
3075
3080
|
</background_results>`;
|
|
3076
3081
|
return automatedMessage("background_results", body);
|
|
3077
3082
|
}
|
|
3083
|
+
function mergeBackgroundResultsMessages(messages) {
|
|
3084
|
+
const results = [];
|
|
3085
|
+
const toolRe = /<tool_result id="([^"]+)" name="([^"]+)">\n([\s\S]*?)\n<\/tool_result>/g;
|
|
3086
|
+
for (const msg of messages) {
|
|
3087
|
+
for (const m of msg.matchAll(toolRe)) {
|
|
3088
|
+
results.push({ toolCallId: m[1], name: m[2], result: m[3] });
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
return buildBackgroundResultsMessage(results);
|
|
3092
|
+
}
|
|
3078
3093
|
var init_sentinel = __esm({
|
|
3079
3094
|
"src/automatedActions/sentinel.ts"() {
|
|
3080
3095
|
"use strict";
|
|
@@ -3103,9 +3118,9 @@ function fixOrphanedToolCalls(messages) {
|
|
|
3103
3118
|
toolResultIds.add(msg.toolCallId);
|
|
3104
3119
|
}
|
|
3105
3120
|
}
|
|
3106
|
-
const result = [
|
|
3107
|
-
for (
|
|
3108
|
-
|
|
3121
|
+
const result = [];
|
|
3122
|
+
for (const msg of messages) {
|
|
3123
|
+
result.push(msg);
|
|
3109
3124
|
if (msg.role !== "assistant" || !Array.isArray(msg.content)) {
|
|
3110
3125
|
continue;
|
|
3111
3126
|
}
|
|
@@ -3113,17 +3128,15 @@ function fixOrphanedToolCalls(messages) {
|
|
|
3113
3128
|
(b) => b.type === "tool"
|
|
3114
3129
|
);
|
|
3115
3130
|
const orphans = toolBlocks.filter((tc) => !toolResultIds.has(tc.id));
|
|
3116
|
-
|
|
3117
|
-
|
|
3131
|
+
for (const tc of orphans) {
|
|
3132
|
+
result.push({
|
|
3133
|
+
role: "user",
|
|
3134
|
+
content: "Error: tool result lost (session recovered)",
|
|
3135
|
+
toolCallId: tc.id,
|
|
3136
|
+
isToolError: true
|
|
3137
|
+
});
|
|
3138
|
+
toolResultIds.add(tc.id);
|
|
3118
3139
|
}
|
|
3119
|
-
const synthetics = orphans.map((tc) => ({
|
|
3120
|
-
role: "user",
|
|
3121
|
-
content: "Error: tool result lost (session recovered)",
|
|
3122
|
-
toolCallId: tc.id,
|
|
3123
|
-
isToolError: true
|
|
3124
|
-
}));
|
|
3125
|
-
result.splice(i + 1, 0, ...synthetics);
|
|
3126
|
-
break;
|
|
3127
3140
|
}
|
|
3128
3141
|
return result;
|
|
3129
3142
|
}
|
|
@@ -6948,6 +6961,10 @@ var init_messageQueue = __esm({
|
|
|
6948
6961
|
snapshot() {
|
|
6949
6962
|
return [...this.items];
|
|
6950
6963
|
}
|
|
6964
|
+
/** Return the next item without removing it. */
|
|
6965
|
+
peek() {
|
|
6966
|
+
return this.items[0];
|
|
6967
|
+
}
|
|
6951
6968
|
get length() {
|
|
6952
6969
|
return this.items.length;
|
|
6953
6970
|
}
|
|
@@ -7546,6 +7563,10 @@ ${userMessage}` : header;
|
|
|
7546
7563
|
/**
|
|
7547
7564
|
* Drain the queue in strict FIFO order. Caller must hold `running = true`.
|
|
7548
7565
|
* User messages arriving during the drain will be enqueued behind current items.
|
|
7566
|
+
*
|
|
7567
|
+
* Consecutive background-source items are coalesced into a single turn so
|
|
7568
|
+
* the LLM sees all the background results together and produces one
|
|
7569
|
+
* acknowledgment, not N separate ones.
|
|
7549
7570
|
*/
|
|
7550
7571
|
async drainQueueLoop() {
|
|
7551
7572
|
while (true) {
|
|
@@ -7553,6 +7574,26 @@ ${userMessage}` : header;
|
|
|
7553
7574
|
if (!next) {
|
|
7554
7575
|
break;
|
|
7555
7576
|
}
|
|
7577
|
+
if (next.source === "background") {
|
|
7578
|
+
const batch = [next];
|
|
7579
|
+
while (this.queue.peek()?.source === "background") {
|
|
7580
|
+
const more = this.queue.shift();
|
|
7581
|
+
if (more) {
|
|
7582
|
+
batch.push(more);
|
|
7583
|
+
}
|
|
7584
|
+
}
|
|
7585
|
+
const combinedCommand = {
|
|
7586
|
+
action: "message",
|
|
7587
|
+
text: mergeBackgroundResultsMessages(
|
|
7588
|
+
batch.map((b) => b.command.text ?? "")
|
|
7589
|
+
),
|
|
7590
|
+
...this.currentOnboardingState && {
|
|
7591
|
+
onboardingState: this.currentOnboardingState
|
|
7592
|
+
}
|
|
7593
|
+
};
|
|
7594
|
+
await this.runSingleTurn(combinedCommand, `background-${Date.now()}`);
|
|
7595
|
+
continue;
|
|
7596
|
+
}
|
|
7556
7597
|
const nextRid = next.command.requestId ?? `${next.source}-${Date.now()}`;
|
|
7557
7598
|
await this.runSingleTurn(next.command, nextRid);
|
|
7558
7599
|
}
|