@mindstudio-ai/remy 0.1.337 → 0.1.339
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 +449 -461
- package/dist/index.js +458 -470
- package/dist/prompt/compiled/interfaces.md +11 -0
- package/dist/prompt/static/coding.md +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4949,127 +4949,6 @@ ${partial}` : "[INTERRUPTED] Tool execution was stopped.";
|
|
|
4949
4949
|
}
|
|
4950
4950
|
});
|
|
4951
4951
|
|
|
4952
|
-
// src/statusWatcher.ts
|
|
4953
|
-
function sanitizeStatusText(text) {
|
|
4954
|
-
if (!text) {
|
|
4955
|
-
return "";
|
|
4956
|
-
}
|
|
4957
|
-
for (const marker of INTERNAL_PAYLOAD_MARKERS) {
|
|
4958
|
-
if (text.includes(marker)) {
|
|
4959
|
-
return "";
|
|
4960
|
-
}
|
|
4961
|
-
}
|
|
4962
|
-
const truncIdx = text.indexOf("(tool result truncated at");
|
|
4963
|
-
return truncIdx === -1 ? text : text.slice(0, truncIdx);
|
|
4964
|
-
}
|
|
4965
|
-
function startStatusWatcher(config) {
|
|
4966
|
-
const { apiConfig, getContext, onStatus, interval = 5e3, signal } = config;
|
|
4967
|
-
let inflight2 = false;
|
|
4968
|
-
let stopped = false;
|
|
4969
|
-
let pauseCount = 0;
|
|
4970
|
-
const url = `${apiConfig.baseUrl}/_internal/v2/agent/remy/generate-status`;
|
|
4971
|
-
let consecutiveFailures = 0;
|
|
4972
|
-
let backoffMs = 0;
|
|
4973
|
-
let nextAllowedAt = 0;
|
|
4974
|
-
const MAX_CONSECUTIVE_FAILURES = 10;
|
|
4975
|
-
const MAX_BACKOFF_MS = 6e4;
|
|
4976
|
-
function recordFailure() {
|
|
4977
|
-
consecutiveFailures++;
|
|
4978
|
-
backoffMs = Math.min(
|
|
4979
|
-
backoffMs === 0 ? interval : backoffMs * 2,
|
|
4980
|
-
MAX_BACKOFF_MS
|
|
4981
|
-
);
|
|
4982
|
-
nextAllowedAt = Date.now() + backoffMs;
|
|
4983
|
-
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES && !stopped) {
|
|
4984
|
-
stopped = true;
|
|
4985
|
-
clearInterval(timer);
|
|
4986
|
-
}
|
|
4987
|
-
}
|
|
4988
|
-
async function tick() {
|
|
4989
|
-
if (stopped || signal?.aborted || inflight2 || pauseCount > 0) {
|
|
4990
|
-
return;
|
|
4991
|
-
}
|
|
4992
|
-
if (Date.now() < nextAllowedAt) {
|
|
4993
|
-
return;
|
|
4994
|
-
}
|
|
4995
|
-
inflight2 = true;
|
|
4996
|
-
try {
|
|
4997
|
-
const context = getContext();
|
|
4998
|
-
if (!context) {
|
|
4999
|
-
return;
|
|
5000
|
-
}
|
|
5001
|
-
const res = await fetch(url, {
|
|
5002
|
-
method: "POST",
|
|
5003
|
-
headers: {
|
|
5004
|
-
"Content-Type": "application/json",
|
|
5005
|
-
Authorization: `Bearer ${apiConfig.apiKey}`,
|
|
5006
|
-
// Also a liveness signal for this box, and the most frequent one there is — this ticks
|
|
5007
|
-
// every few seconds for as long as the agent is working, which is exactly the window in
|
|
5008
|
-
// which the user may have backgrounded the tab and stopped its own keepalive.
|
|
5009
|
-
...sandboxSessionHeader()
|
|
5010
|
-
},
|
|
5011
|
-
body: JSON.stringify({ appId: apiConfig.appId, context }),
|
|
5012
|
-
signal
|
|
5013
|
-
});
|
|
5014
|
-
if (stopped) {
|
|
5015
|
-
return;
|
|
5016
|
-
}
|
|
5017
|
-
if (!res.ok) {
|
|
5018
|
-
recordFailure();
|
|
5019
|
-
return;
|
|
5020
|
-
}
|
|
5021
|
-
const data = await res.json();
|
|
5022
|
-
if (!data.label) {
|
|
5023
|
-
recordFailure();
|
|
5024
|
-
return;
|
|
5025
|
-
}
|
|
5026
|
-
consecutiveFailures = 0;
|
|
5027
|
-
backoffMs = 0;
|
|
5028
|
-
nextAllowedAt = 0;
|
|
5029
|
-
if (pauseCount > 0 || stopped || signal?.aborted) {
|
|
5030
|
-
return;
|
|
5031
|
-
}
|
|
5032
|
-
onStatus(data.label);
|
|
5033
|
-
} catch {
|
|
5034
|
-
if (!stopped && !signal?.aborted) {
|
|
5035
|
-
recordFailure();
|
|
5036
|
-
}
|
|
5037
|
-
} finally {
|
|
5038
|
-
inflight2 = false;
|
|
5039
|
-
}
|
|
5040
|
-
}
|
|
5041
|
-
const timer = setInterval(tick, interval);
|
|
5042
|
-
tick().catch(() => {
|
|
5043
|
-
});
|
|
5044
|
-
return {
|
|
5045
|
-
stop() {
|
|
5046
|
-
stopped = true;
|
|
5047
|
-
clearInterval(timer);
|
|
5048
|
-
},
|
|
5049
|
-
pause() {
|
|
5050
|
-
pauseCount++;
|
|
5051
|
-
},
|
|
5052
|
-
resume() {
|
|
5053
|
-
pauseCount = Math.max(0, pauseCount - 1);
|
|
5054
|
-
}
|
|
5055
|
-
};
|
|
5056
|
-
}
|
|
5057
|
-
var INTERNAL_PAYLOAD_MARKERS;
|
|
5058
|
-
var init_statusWatcher = __esm({
|
|
5059
|
-
"src/statusWatcher.ts"() {
|
|
5060
|
-
"use strict";
|
|
5061
|
-
init_api();
|
|
5062
|
-
INTERNAL_PAYLOAD_MARKERS = [
|
|
5063
|
-
"[USER CANCELLED]",
|
|
5064
|
-
"[INTERRUPTED]",
|
|
5065
|
-
"[INTERRUPTED - PARTIAL OUTPUT RETRIEVED]",
|
|
5066
|
-
"<background_results>",
|
|
5067
|
-
"<workspace_status>",
|
|
5068
|
-
"<tool_result"
|
|
5069
|
-
];
|
|
5070
|
-
}
|
|
5071
|
-
});
|
|
5072
|
-
|
|
5073
4952
|
// src/subagents/runner.ts
|
|
5074
4953
|
async function runSubAgent(config) {
|
|
5075
4954
|
const {
|
|
@@ -5137,376 +5016,339 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
|
|
|
5137
5016
|
}
|
|
5138
5017
|
return { text: cancelledToolResult(signal), messages: thisInvocation() };
|
|
5139
5018
|
}
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
try {
|
|
5183
|
-
for await (const event of streamChatWithRetry(
|
|
5184
|
-
{
|
|
5185
|
-
...apiConfig,
|
|
5186
|
-
model,
|
|
5187
|
-
requestId,
|
|
5188
|
-
subAgentId,
|
|
5189
|
-
system: fullSystem,
|
|
5190
|
-
messages: cleanMessagesForApi(messages),
|
|
5191
|
-
tools: tools2,
|
|
5192
|
-
cachePolicy,
|
|
5193
|
-
signal
|
|
5194
|
-
},
|
|
5195
|
-
{
|
|
5196
|
-
onRetry: (attempt) => emit({
|
|
5197
|
-
type: "status",
|
|
5198
|
-
message: `Lost connection, retrying (attempt ${attempt + 2} of 3)`
|
|
5199
|
-
})
|
|
5200
|
-
}
|
|
5201
|
-
)) {
|
|
5202
|
-
if (signal?.aborted) {
|
|
5203
|
-
break;
|
|
5204
|
-
}
|
|
5205
|
-
switch (event.type) {
|
|
5206
|
-
case "text": {
|
|
5207
|
-
const lastBlock = contentBlocks.at(-1);
|
|
5208
|
-
if (lastBlock?.type === "text") {
|
|
5209
|
-
lastBlock.text += event.text;
|
|
5210
|
-
} else {
|
|
5211
|
-
contentBlocks.push({
|
|
5212
|
-
type: "text",
|
|
5213
|
-
text: event.text,
|
|
5214
|
-
startedAt: event.ts
|
|
5215
|
-
});
|
|
5216
|
-
}
|
|
5217
|
-
emit({ type: "text", text: event.text });
|
|
5218
|
-
break;
|
|
5219
|
-
}
|
|
5220
|
-
case "thinking":
|
|
5221
|
-
if (!thinkingStartedAt) {
|
|
5222
|
-
thinkingStartedAt = event.ts;
|
|
5223
|
-
}
|
|
5224
|
-
emit({ type: "thinking", text: event.text });
|
|
5225
|
-
break;
|
|
5226
|
-
case "thinking_complete":
|
|
5227
|
-
contentBlocks.push({
|
|
5228
|
-
type: "thinking",
|
|
5229
|
-
thinking: event.thinking,
|
|
5230
|
-
signature: event.signature,
|
|
5231
|
-
startedAt: thinkingStartedAt,
|
|
5232
|
-
completedAt: event.ts
|
|
5233
|
-
});
|
|
5234
|
-
lastThinkingRelatedStartedAt = thinkingStartedAt;
|
|
5235
|
-
thinkingStartedAt = 0;
|
|
5236
|
-
break;
|
|
5237
|
-
case "redacted_thinking_complete": {
|
|
5238
|
-
const startedAt = lastThinkingRelatedStartedAt !== void 0 ? lastThinkingRelatedStartedAt + 1 : event.ts;
|
|
5019
|
+
while (true) {
|
|
5020
|
+
turns++;
|
|
5021
|
+
if (signal?.aborted) {
|
|
5022
|
+
return abortResult([]);
|
|
5023
|
+
}
|
|
5024
|
+
const iterStart = Date.now();
|
|
5025
|
+
const contentBlocks = [];
|
|
5026
|
+
let thinkingStartedAt = 0;
|
|
5027
|
+
let lastThinkingRelatedStartedAt;
|
|
5028
|
+
let stopReason = "end_turn";
|
|
5029
|
+
let lastUsage;
|
|
5030
|
+
let lastProviderMetadata;
|
|
5031
|
+
let lastModelId;
|
|
5032
|
+
try {
|
|
5033
|
+
for await (const event of streamChatWithRetry(
|
|
5034
|
+
{
|
|
5035
|
+
...apiConfig,
|
|
5036
|
+
model,
|
|
5037
|
+
requestId,
|
|
5038
|
+
subAgentId,
|
|
5039
|
+
system: fullSystem,
|
|
5040
|
+
messages: cleanMessagesForApi(messages),
|
|
5041
|
+
tools: tools2,
|
|
5042
|
+
cachePolicy,
|
|
5043
|
+
signal
|
|
5044
|
+
},
|
|
5045
|
+
{
|
|
5046
|
+
onRetry: (attempt) => emit({
|
|
5047
|
+
type: "status",
|
|
5048
|
+
message: `Lost connection, retrying (attempt ${attempt + 2} of 3)`
|
|
5049
|
+
})
|
|
5050
|
+
}
|
|
5051
|
+
)) {
|
|
5052
|
+
if (signal?.aborted) {
|
|
5053
|
+
break;
|
|
5054
|
+
}
|
|
5055
|
+
switch (event.type) {
|
|
5056
|
+
case "text": {
|
|
5057
|
+
const lastBlock = contentBlocks.at(-1);
|
|
5058
|
+
if (lastBlock?.type === "text") {
|
|
5059
|
+
lastBlock.text += event.text;
|
|
5060
|
+
} else {
|
|
5239
5061
|
contentBlocks.push({
|
|
5240
|
-
type: "
|
|
5241
|
-
|
|
5242
|
-
startedAt
|
|
5243
|
-
completedAt: event.ts
|
|
5062
|
+
type: "text",
|
|
5063
|
+
text: event.text,
|
|
5064
|
+
startedAt: event.ts
|
|
5244
5065
|
});
|
|
5245
|
-
lastThinkingRelatedStartedAt = startedAt;
|
|
5246
|
-
break;
|
|
5247
5066
|
}
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
type: "tool",
|
|
5251
|
-
id: event.id,
|
|
5252
|
-
name: event.name,
|
|
5253
|
-
input: event.input,
|
|
5254
|
-
startedAt: Date.now()
|
|
5255
|
-
});
|
|
5256
|
-
emit({
|
|
5257
|
-
type: "tool_start",
|
|
5258
|
-
id: event.id,
|
|
5259
|
-
name: event.name,
|
|
5260
|
-
input: event.input
|
|
5261
|
-
});
|
|
5262
|
-
break;
|
|
5263
|
-
case "done":
|
|
5264
|
-
stopReason = event.stopReason;
|
|
5265
|
-
lastUsage = {
|
|
5266
|
-
inputTokens: event.usage.inputTokens,
|
|
5267
|
-
outputTokens: event.usage.outputTokens,
|
|
5268
|
-
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
5269
|
-
cacheReadTokens: event.usage.cacheReadTokens,
|
|
5270
|
-
llmCalls: 1
|
|
5271
|
-
};
|
|
5272
|
-
lastProviderMetadata = event.providerMetadata;
|
|
5273
|
-
lastModelId = event.modelId;
|
|
5274
|
-
recordUsage({
|
|
5275
|
-
ts: Date.now(),
|
|
5276
|
-
requestId,
|
|
5277
|
-
agentName: subAgentId || "sub-agent",
|
|
5278
|
-
parentToolId,
|
|
5279
|
-
modelId: event.modelId,
|
|
5280
|
-
inputTokens: event.usage.inputTokens,
|
|
5281
|
-
outputTokens: event.usage.outputTokens,
|
|
5282
|
-
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
5283
|
-
cacheReadTokens: event.usage.cacheReadTokens,
|
|
5284
|
-
cost: nanoToDollars(event.cost),
|
|
5285
|
-
billingEvents: event.billingEvents,
|
|
5286
|
-
durationMs: Date.now() - iterStart,
|
|
5287
|
-
toolNames: contentBlocks.filter(
|
|
5288
|
-
(b) => b.type === "tool"
|
|
5289
|
-
).map((b) => b.name)
|
|
5290
|
-
});
|
|
5291
|
-
break;
|
|
5292
|
-
case "error":
|
|
5293
|
-
statusWatcher.stop();
|
|
5294
|
-
return {
|
|
5295
|
-
text: `Error: ${event.error}`,
|
|
5296
|
-
messages: thisInvocation()
|
|
5297
|
-
};
|
|
5067
|
+
emit({ type: "text", text: event.text });
|
|
5068
|
+
break;
|
|
5298
5069
|
}
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
...lastUsage ? { usage: lastUsage } : {},
|
|
5313
|
-
...lastProviderMetadata ? { providerMetadata: lastProviderMetadata } : {},
|
|
5314
|
-
model: lastModelId ?? model
|
|
5315
|
-
});
|
|
5316
|
-
const toolCalls = contentBlocks.filter(
|
|
5317
|
-
(b) => b.type === "tool"
|
|
5318
|
-
);
|
|
5319
|
-
if (stopReason !== "tool_use" || toolCalls.length === 0) {
|
|
5320
|
-
let text = getPartialText(contentBlocks);
|
|
5321
|
-
if (validateResult) {
|
|
5322
|
-
let objection = null;
|
|
5323
|
-
try {
|
|
5324
|
-
objection = await validateResult(text, thisInvocation());
|
|
5325
|
-
} catch (err) {
|
|
5326
|
-
log8.warn("Result validator failed, accepting response", {
|
|
5327
|
-
requestId,
|
|
5328
|
-
parentToolId,
|
|
5329
|
-
agentName,
|
|
5330
|
-
error: err.message
|
|
5070
|
+
case "thinking":
|
|
5071
|
+
if (!thinkingStartedAt) {
|
|
5072
|
+
thinkingStartedAt = event.ts;
|
|
5073
|
+
}
|
|
5074
|
+
emit({ type: "thinking", text: event.text });
|
|
5075
|
+
break;
|
|
5076
|
+
case "thinking_complete":
|
|
5077
|
+
contentBlocks.push({
|
|
5078
|
+
type: "thinking",
|
|
5079
|
+
thinking: event.thinking,
|
|
5080
|
+
signature: event.signature,
|
|
5081
|
+
startedAt: thinkingStartedAt,
|
|
5082
|
+
completedAt: event.ts
|
|
5331
5083
|
});
|
|
5084
|
+
lastThinkingRelatedStartedAt = thinkingStartedAt;
|
|
5085
|
+
thinkingStartedAt = 0;
|
|
5086
|
+
break;
|
|
5087
|
+
case "redacted_thinking_complete": {
|
|
5088
|
+
const startedAt = lastThinkingRelatedStartedAt !== void 0 ? lastThinkingRelatedStartedAt + 1 : event.ts;
|
|
5089
|
+
contentBlocks.push({
|
|
5090
|
+
type: "redacted_thinking",
|
|
5091
|
+
data: event.data,
|
|
5092
|
+
startedAt,
|
|
5093
|
+
completedAt: event.ts
|
|
5094
|
+
});
|
|
5095
|
+
lastThinkingRelatedStartedAt = startedAt;
|
|
5096
|
+
break;
|
|
5332
5097
|
}
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5098
|
+
case "tool_use":
|
|
5099
|
+
contentBlocks.push({
|
|
5100
|
+
type: "tool",
|
|
5101
|
+
id: event.id,
|
|
5102
|
+
name: event.name,
|
|
5103
|
+
input: event.input,
|
|
5104
|
+
startedAt: Date.now()
|
|
5340
5105
|
});
|
|
5341
5106
|
emit({
|
|
5342
|
-
type: "
|
|
5343
|
-
|
|
5107
|
+
type: "tool_start",
|
|
5108
|
+
id: event.id,
|
|
5109
|
+
name: event.name,
|
|
5110
|
+
input: event.input
|
|
5344
5111
|
});
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
statusWatcher.stop();
|
|
5355
|
-
const hasArtifacts = Object.keys(artifacts).length > 0;
|
|
5356
|
-
return {
|
|
5357
|
-
text,
|
|
5358
|
-
messages: thisInvocation(),
|
|
5359
|
-
...hasArtifacts ? { artifacts } : {}
|
|
5360
|
-
};
|
|
5361
|
-
}
|
|
5362
|
-
log8.info("Tools executing", {
|
|
5363
|
-
requestId,
|
|
5364
|
-
parentToolId,
|
|
5365
|
-
count: toolCalls.length,
|
|
5366
|
-
tools: toolCalls.map((tc) => tc.name)
|
|
5367
|
-
});
|
|
5368
|
-
watchedToolNames = toolCalls.map((tc) => tc.name).join(", ");
|
|
5369
|
-
const results = await Promise.all(
|
|
5370
|
-
toolCalls.map(async (tc) => {
|
|
5371
|
-
if (signal?.aborted) {
|
|
5372
|
-
return {
|
|
5373
|
-
id: tc.id,
|
|
5374
|
-
result: cancelledToolResult(signal),
|
|
5375
|
-
isError: true
|
|
5112
|
+
break;
|
|
5113
|
+
case "done":
|
|
5114
|
+
stopReason = event.stopReason;
|
|
5115
|
+
lastUsage = {
|
|
5116
|
+
inputTokens: event.usage.inputTokens,
|
|
5117
|
+
outputTokens: event.usage.outputTokens,
|
|
5118
|
+
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
5119
|
+
cacheReadTokens: event.usage.cacheReadTokens,
|
|
5120
|
+
llmCalls: 1
|
|
5376
5121
|
};
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5122
|
+
lastProviderMetadata = event.providerMetadata;
|
|
5123
|
+
lastModelId = event.modelId;
|
|
5124
|
+
recordUsage({
|
|
5125
|
+
ts: Date.now(),
|
|
5126
|
+
requestId,
|
|
5127
|
+
agentName: subAgentId || "sub-agent",
|
|
5128
|
+
parentToolId,
|
|
5129
|
+
modelId: event.modelId,
|
|
5130
|
+
inputTokens: event.usage.inputTokens,
|
|
5131
|
+
outputTokens: event.usage.outputTokens,
|
|
5132
|
+
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
5133
|
+
cacheReadTokens: event.usage.cacheReadTokens,
|
|
5134
|
+
cost: nanoToDollars(event.cost),
|
|
5135
|
+
billingEvents: event.billingEvents,
|
|
5136
|
+
durationMs: Date.now() - iterStart,
|
|
5137
|
+
toolNames: contentBlocks.filter(
|
|
5138
|
+
(b) => b.type === "tool"
|
|
5139
|
+
).map((b) => b.name)
|
|
5385
5140
|
});
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
onLog,
|
|
5422
|
-
subAgentMessages
|
|
5423
|
-
);
|
|
5424
|
-
}
|
|
5425
|
-
safeSettle(
|
|
5426
|
-
capToolResult(result),
|
|
5427
|
-
result.startsWith("Error"),
|
|
5428
|
-
recording
|
|
5429
|
-
);
|
|
5430
|
-
} catch (err) {
|
|
5431
|
-
safeSettle(`Error: ${err.message}`, true);
|
|
5432
|
-
}
|
|
5433
|
-
};
|
|
5434
|
-
const entry = {
|
|
5435
|
-
id: tc.id,
|
|
5436
|
-
name: tc.name,
|
|
5437
|
-
input: tc.input,
|
|
5141
|
+
break;
|
|
5142
|
+
case "error":
|
|
5143
|
+
return {
|
|
5144
|
+
text: `Error: ${event.error}`,
|
|
5145
|
+
messages: thisInvocation()
|
|
5146
|
+
};
|
|
5147
|
+
}
|
|
5148
|
+
}
|
|
5149
|
+
} catch (err) {
|
|
5150
|
+
if (!signal?.aborted) {
|
|
5151
|
+
throw err;
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
5154
|
+
if (signal?.aborted) {
|
|
5155
|
+
return abortResult(contentBlocks);
|
|
5156
|
+
}
|
|
5157
|
+
messages.push({
|
|
5158
|
+
role: "assistant",
|
|
5159
|
+
content: contentBlocks,
|
|
5160
|
+
...lastUsage ? { usage: lastUsage } : {},
|
|
5161
|
+
...lastProviderMetadata ? { providerMetadata: lastProviderMetadata } : {},
|
|
5162
|
+
model: lastModelId ?? model
|
|
5163
|
+
});
|
|
5164
|
+
const toolCalls = contentBlocks.filter(
|
|
5165
|
+
(b) => b.type === "tool"
|
|
5166
|
+
);
|
|
5167
|
+
if (stopReason !== "tool_use" || toolCalls.length === 0) {
|
|
5168
|
+
let text = getPartialText(contentBlocks);
|
|
5169
|
+
if (validateResult) {
|
|
5170
|
+
let objection = null;
|
|
5171
|
+
try {
|
|
5172
|
+
objection = await validateResult(text, thisInvocation());
|
|
5173
|
+
} catch (err) {
|
|
5174
|
+
log8.warn("Result validator failed, accepting response", {
|
|
5175
|
+
requestId,
|
|
5438
5176
|
parentToolId,
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
once: true
|
|
5447
|
-
});
|
|
5448
|
-
entry.abortController = toolAbort;
|
|
5449
|
-
entry.input = newInput;
|
|
5450
|
-
run2(newInput);
|
|
5451
|
-
}
|
|
5452
|
-
};
|
|
5453
|
-
toolRegistry?.register(entry);
|
|
5454
|
-
const toolStart = Date.now();
|
|
5455
|
-
run2(tc.input);
|
|
5456
|
-
const r = await resultPromise;
|
|
5457
|
-
toolRegistry?.unregister(tc.id);
|
|
5458
|
-
log8.info("Tool completed", {
|
|
5177
|
+
agentName,
|
|
5178
|
+
error: err.message
|
|
5179
|
+
});
|
|
5180
|
+
}
|
|
5181
|
+
if (objection && !validationRetried && !signal?.aborted) {
|
|
5182
|
+
validationRetried = true;
|
|
5183
|
+
log8.info("Result rejected by validator, retrying once", {
|
|
5459
5184
|
requestId,
|
|
5460
5185
|
parentToolId,
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
durationMs: Date.now() - toolStart,
|
|
5464
|
-
isError: r.isError
|
|
5186
|
+
agentName,
|
|
5187
|
+
objection: objection.slice(0, 200)
|
|
5465
5188
|
});
|
|
5466
5189
|
emit({
|
|
5467
|
-
type: "
|
|
5190
|
+
type: "status",
|
|
5191
|
+
message: "Response failed validation, revising"
|
|
5192
|
+
});
|
|
5193
|
+
messages.push({ role: "user", content: objection });
|
|
5194
|
+
continue;
|
|
5195
|
+
}
|
|
5196
|
+
if (objection) {
|
|
5197
|
+
text = `${text}
|
|
5198
|
+
|
|
5199
|
+
[Response validator: ${objection}]`;
|
|
5200
|
+
}
|
|
5201
|
+
}
|
|
5202
|
+
const hasArtifacts = Object.keys(artifacts).length > 0;
|
|
5203
|
+
return {
|
|
5204
|
+
text,
|
|
5205
|
+
messages: thisInvocation(),
|
|
5206
|
+
...hasArtifacts ? { artifacts } : {}
|
|
5207
|
+
};
|
|
5208
|
+
}
|
|
5209
|
+
log8.info("Tools executing", {
|
|
5210
|
+
requestId,
|
|
5211
|
+
parentToolId,
|
|
5212
|
+
count: toolCalls.length,
|
|
5213
|
+
tools: toolCalls.map((tc) => tc.name)
|
|
5214
|
+
});
|
|
5215
|
+
const results = await Promise.all(
|
|
5216
|
+
toolCalls.map(async (tc) => {
|
|
5217
|
+
if (signal?.aborted) {
|
|
5218
|
+
return {
|
|
5219
|
+
id: tc.id,
|
|
5220
|
+
result: cancelledToolResult(signal),
|
|
5221
|
+
isError: true
|
|
5222
|
+
};
|
|
5223
|
+
}
|
|
5224
|
+
let settle;
|
|
5225
|
+
const resultPromise = new Promise((res) => {
|
|
5226
|
+
settle = (result, isError, recording) => res({
|
|
5468
5227
|
id: tc.id,
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
...r.recording ? { recording: r.recording } : {}
|
|
5228
|
+
result,
|
|
5229
|
+
isError,
|
|
5230
|
+
...recording ? { recording } : {}
|
|
5473
5231
|
});
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
const
|
|
5480
|
-
(
|
|
5481
|
-
|
|
5482
|
-
if (block?.type === "tool") {
|
|
5483
|
-
block.result = r.result;
|
|
5484
|
-
block.isError = r.isError;
|
|
5485
|
-
block.completedAt = Date.now();
|
|
5486
|
-
if (r.recording) {
|
|
5487
|
-
block.recording = r.recording;
|
|
5488
|
-
}
|
|
5489
|
-
const innerMsgs = subAgentMessages.get(r.id);
|
|
5490
|
-
if (innerMsgs) {
|
|
5491
|
-
attachSubAgentTranscript(block, innerMsgs);
|
|
5232
|
+
});
|
|
5233
|
+
let toolAbort = new AbortController();
|
|
5234
|
+
const cascadeAbort = () => toolAbort.abort();
|
|
5235
|
+
signal?.addEventListener("abort", cascadeAbort, { once: true });
|
|
5236
|
+
let settled = false;
|
|
5237
|
+
const safeSettle = (result, isError, recording) => {
|
|
5238
|
+
if (settled) {
|
|
5239
|
+
return;
|
|
5492
5240
|
}
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5241
|
+
settled = true;
|
|
5242
|
+
signal?.removeEventListener("abort", cascadeAbort);
|
|
5243
|
+
settle(result, isError, recording);
|
|
5244
|
+
};
|
|
5245
|
+
const run2 = async (input) => {
|
|
5246
|
+
try {
|
|
5247
|
+
let result;
|
|
5248
|
+
let recording;
|
|
5249
|
+
if (externalTools.has(tc.name) && resolveExternalTool) {
|
|
5250
|
+
result = await resolveExternalTool(tc.id, tc.name, input);
|
|
5251
|
+
if (tc.name === "browserCommand") {
|
|
5252
|
+
const lifted = liftRecording(result);
|
|
5253
|
+
result = lifted.result;
|
|
5254
|
+
recording = lifted.recording;
|
|
5255
|
+
}
|
|
5256
|
+
} else {
|
|
5257
|
+
const onLog = (line) => emit({
|
|
5258
|
+
type: "tool_input_delta",
|
|
5259
|
+
id: tc.id,
|
|
5260
|
+
name: tc.name,
|
|
5261
|
+
result: line
|
|
5262
|
+
});
|
|
5263
|
+
result = await executeTool2(
|
|
5264
|
+
tc.name,
|
|
5265
|
+
input,
|
|
5266
|
+
tc.id,
|
|
5267
|
+
onLog,
|
|
5268
|
+
subAgentMessages
|
|
5269
|
+
);
|
|
5497
5270
|
}
|
|
5271
|
+
safeSettle(
|
|
5272
|
+
capToolResult(result),
|
|
5273
|
+
result.startsWith("Error"),
|
|
5274
|
+
recording
|
|
5275
|
+
);
|
|
5276
|
+
} catch (err) {
|
|
5277
|
+
safeSettle(`Error: ${err.message}`, true);
|
|
5498
5278
|
}
|
|
5499
|
-
}
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5279
|
+
};
|
|
5280
|
+
const entry = {
|
|
5281
|
+
id: tc.id,
|
|
5282
|
+
name: tc.name,
|
|
5283
|
+
input: tc.input,
|
|
5284
|
+
parentToolId,
|
|
5285
|
+
abortController: toolAbort,
|
|
5286
|
+
startedAt: Date.now(),
|
|
5287
|
+
settle: safeSettle,
|
|
5288
|
+
rerun: (newInput) => {
|
|
5289
|
+
settled = false;
|
|
5290
|
+
toolAbort = new AbortController();
|
|
5291
|
+
signal?.addEventListener("abort", () => toolAbort.abort(), {
|
|
5292
|
+
once: true
|
|
5293
|
+
});
|
|
5294
|
+
entry.abortController = toolAbort;
|
|
5295
|
+
entry.input = newInput;
|
|
5296
|
+
run2(newInput);
|
|
5297
|
+
}
|
|
5298
|
+
};
|
|
5299
|
+
toolRegistry?.register(entry);
|
|
5300
|
+
const toolStart = Date.now();
|
|
5301
|
+
run2(tc.input);
|
|
5302
|
+
const r = await resultPromise;
|
|
5303
|
+
toolRegistry?.unregister(tc.id);
|
|
5304
|
+
log8.info("Tool completed", {
|
|
5305
|
+
requestId,
|
|
5306
|
+
parentToolId,
|
|
5307
|
+
toolCallId: tc.id,
|
|
5308
|
+
name: tc.name,
|
|
5309
|
+
durationMs: Date.now() - toolStart,
|
|
5310
|
+
isError: r.isError
|
|
5311
|
+
});
|
|
5312
|
+
emit({
|
|
5313
|
+
type: "tool_done",
|
|
5314
|
+
id: tc.id,
|
|
5315
|
+
name: tc.name,
|
|
5316
|
+
result: r.result,
|
|
5317
|
+
isError: r.isError,
|
|
5318
|
+
...r.recording ? { recording: r.recording } : {}
|
|
5505
5319
|
});
|
|
5320
|
+
return r;
|
|
5321
|
+
})
|
|
5322
|
+
);
|
|
5323
|
+
for (const r of results) {
|
|
5324
|
+
const block = contentBlocks.find(
|
|
5325
|
+
(b) => b.type === "tool" && b.id === r.id
|
|
5326
|
+
);
|
|
5327
|
+
if (block?.type === "tool") {
|
|
5328
|
+
block.result = r.result;
|
|
5329
|
+
block.isError = r.isError;
|
|
5330
|
+
block.completedAt = Date.now();
|
|
5331
|
+
if (r.recording) {
|
|
5332
|
+
block.recording = r.recording;
|
|
5333
|
+
}
|
|
5334
|
+
const innerMsgs = subAgentMessages.get(r.id);
|
|
5335
|
+
if (innerMsgs) {
|
|
5336
|
+
attachSubAgentTranscript(block, innerMsgs);
|
|
5337
|
+
}
|
|
5338
|
+
if (captureArtifacts?.includes(block.name) && !r.isError) {
|
|
5339
|
+
try {
|
|
5340
|
+
artifacts[block.name] = JSON.parse(r.result);
|
|
5341
|
+
} catch {
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
5506
5344
|
}
|
|
5345
|
+
messages.push({
|
|
5346
|
+
role: "user",
|
|
5347
|
+
content: r.result,
|
|
5348
|
+
toolCallId: r.id,
|
|
5349
|
+
isToolError: r.isError
|
|
5350
|
+
});
|
|
5507
5351
|
}
|
|
5508
|
-
} finally {
|
|
5509
|
-
statusWatcher.stop();
|
|
5510
5352
|
}
|
|
5511
5353
|
};
|
|
5512
5354
|
const wrapRun = async () => {
|
|
@@ -5578,7 +5420,6 @@ var init_runner = __esm({
|
|
|
5578
5420
|
init_toolRegistry();
|
|
5579
5421
|
init_historyLimits();
|
|
5580
5422
|
init_recording();
|
|
5581
|
-
init_statusWatcher();
|
|
5582
5423
|
init_cleanMessages();
|
|
5583
5424
|
log8 = createLogger("sub-agent");
|
|
5584
5425
|
}
|
|
@@ -9393,6 +9234,153 @@ var init_parsePartialJson = __esm({
|
|
|
9393
9234
|
}
|
|
9394
9235
|
});
|
|
9395
9236
|
|
|
9237
|
+
// src/statusWatcher.ts
|
|
9238
|
+
import { createHash } from "crypto";
|
|
9239
|
+
function sanitizeStatusText(text) {
|
|
9240
|
+
if (!text) {
|
|
9241
|
+
return "";
|
|
9242
|
+
}
|
|
9243
|
+
for (const marker of INTERNAL_PAYLOAD_MARKERS) {
|
|
9244
|
+
if (text.includes(marker)) {
|
|
9245
|
+
return "";
|
|
9246
|
+
}
|
|
9247
|
+
}
|
|
9248
|
+
const truncIdx = text.indexOf("(tool result truncated at");
|
|
9249
|
+
return truncIdx === -1 ? text : text.slice(0, truncIdx);
|
|
9250
|
+
}
|
|
9251
|
+
function startStatusWatcher(config) {
|
|
9252
|
+
const { apiConfig, getContext, onStatus, interval = 5e3, signal } = config;
|
|
9253
|
+
let inflight2 = false;
|
|
9254
|
+
let stopped = false;
|
|
9255
|
+
let pauseCount = 0;
|
|
9256
|
+
let labeledContextHash = null;
|
|
9257
|
+
const url = `${apiConfig.baseUrl}/_internal/v2/agent/remy/generate-status`;
|
|
9258
|
+
let consecutiveFailures = 0;
|
|
9259
|
+
let backoffMs = 0;
|
|
9260
|
+
let nextAllowedAt = 0;
|
|
9261
|
+
const MAX_CONSECUTIVE_FAILURES = 10;
|
|
9262
|
+
const MAX_BACKOFF_MS = 6e4;
|
|
9263
|
+
function recordFailure() {
|
|
9264
|
+
consecutiveFailures++;
|
|
9265
|
+
backoffMs = Math.min(
|
|
9266
|
+
backoffMs === 0 ? interval : backoffMs * 2,
|
|
9267
|
+
MAX_BACKOFF_MS
|
|
9268
|
+
);
|
|
9269
|
+
nextAllowedAt = Date.now() + backoffMs;
|
|
9270
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES && !stopped) {
|
|
9271
|
+
stopped = true;
|
|
9272
|
+
clearInterval(timer);
|
|
9273
|
+
}
|
|
9274
|
+
}
|
|
9275
|
+
async function tick() {
|
|
9276
|
+
if (stopped || signal?.aborted || inflight2 || pauseCount > 0) {
|
|
9277
|
+
return;
|
|
9278
|
+
}
|
|
9279
|
+
if (Date.now() < nextAllowedAt) {
|
|
9280
|
+
return;
|
|
9281
|
+
}
|
|
9282
|
+
inflight2 = true;
|
|
9283
|
+
try {
|
|
9284
|
+
const context = getContext();
|
|
9285
|
+
if (!context) {
|
|
9286
|
+
return;
|
|
9287
|
+
}
|
|
9288
|
+
const contextHash = createHash("sha1").update(context).digest("hex");
|
|
9289
|
+
const unchanged = contextHash === labeledContextHash;
|
|
9290
|
+
const startedAt = Date.now();
|
|
9291
|
+
const res = await fetch(url, {
|
|
9292
|
+
method: "POST",
|
|
9293
|
+
headers: {
|
|
9294
|
+
"Content-Type": "application/json",
|
|
9295
|
+
Authorization: `Bearer ${apiConfig.apiKey}`,
|
|
9296
|
+
// Also a liveness signal for this box, and the most frequent one there is — this ticks
|
|
9297
|
+
// every few seconds for as long as the agent is working, which is exactly the window in
|
|
9298
|
+
// which the user may have backgrounded the tab and stopped its own keepalive.
|
|
9299
|
+
...sandboxSessionHeader()
|
|
9300
|
+
},
|
|
9301
|
+
body: JSON.stringify({
|
|
9302
|
+
appId: apiConfig.appId,
|
|
9303
|
+
...unchanged ? {} : { context }
|
|
9304
|
+
}),
|
|
9305
|
+
signal
|
|
9306
|
+
});
|
|
9307
|
+
if (stopped) {
|
|
9308
|
+
return;
|
|
9309
|
+
}
|
|
9310
|
+
if (unchanged) {
|
|
9311
|
+
await res.body?.cancel().catch(() => {
|
|
9312
|
+
});
|
|
9313
|
+
return;
|
|
9314
|
+
}
|
|
9315
|
+
if (!res.ok) {
|
|
9316
|
+
recordFailure();
|
|
9317
|
+
return;
|
|
9318
|
+
}
|
|
9319
|
+
const data = await res.json();
|
|
9320
|
+
if (!data.label) {
|
|
9321
|
+
recordFailure();
|
|
9322
|
+
return;
|
|
9323
|
+
}
|
|
9324
|
+
recordUsage({
|
|
9325
|
+
ts: Date.now(),
|
|
9326
|
+
agentName: "statusLabel",
|
|
9327
|
+
modelId: data.modelId,
|
|
9328
|
+
inputTokens: data.usage?.inputTokens ?? 0,
|
|
9329
|
+
outputTokens: data.usage?.outputTokens ?? 0,
|
|
9330
|
+
cost: nanoToDollars(data.cost),
|
|
9331
|
+
billingEvents: data.billingEvents,
|
|
9332
|
+
durationMs: Date.now() - startedAt,
|
|
9333
|
+
toolNames: []
|
|
9334
|
+
});
|
|
9335
|
+
consecutiveFailures = 0;
|
|
9336
|
+
backoffMs = 0;
|
|
9337
|
+
nextAllowedAt = 0;
|
|
9338
|
+
if (pauseCount > 0 || stopped || signal?.aborted) {
|
|
9339
|
+
return;
|
|
9340
|
+
}
|
|
9341
|
+
onStatus(data.label);
|
|
9342
|
+
labeledContextHash = contextHash;
|
|
9343
|
+
} catch {
|
|
9344
|
+
if (!stopped && !signal?.aborted) {
|
|
9345
|
+
recordFailure();
|
|
9346
|
+
}
|
|
9347
|
+
} finally {
|
|
9348
|
+
inflight2 = false;
|
|
9349
|
+
}
|
|
9350
|
+
}
|
|
9351
|
+
const timer = setInterval(tick, interval);
|
|
9352
|
+
tick().catch(() => {
|
|
9353
|
+
});
|
|
9354
|
+
return {
|
|
9355
|
+
stop() {
|
|
9356
|
+
stopped = true;
|
|
9357
|
+
clearInterval(timer);
|
|
9358
|
+
},
|
|
9359
|
+
pause() {
|
|
9360
|
+
pauseCount++;
|
|
9361
|
+
},
|
|
9362
|
+
resume() {
|
|
9363
|
+
pauseCount = Math.max(0, pauseCount - 1);
|
|
9364
|
+
}
|
|
9365
|
+
};
|
|
9366
|
+
}
|
|
9367
|
+
var INTERNAL_PAYLOAD_MARKERS;
|
|
9368
|
+
var init_statusWatcher = __esm({
|
|
9369
|
+
"src/statusWatcher.ts"() {
|
|
9370
|
+
"use strict";
|
|
9371
|
+
init_api();
|
|
9372
|
+
init_usageLedger();
|
|
9373
|
+
INTERNAL_PAYLOAD_MARKERS = [
|
|
9374
|
+
"[USER CANCELLED]",
|
|
9375
|
+
"[INTERRUPTED]",
|
|
9376
|
+
"[INTERRUPTED - PARTIAL OUTPUT RETRIEVED]",
|
|
9377
|
+
"<background_results>",
|
|
9378
|
+
"<workspace_status>",
|
|
9379
|
+
"<tool_result"
|
|
9380
|
+
];
|
|
9381
|
+
}
|
|
9382
|
+
});
|
|
9383
|
+
|
|
9396
9384
|
// src/automatedActions/resolve.ts
|
|
9397
9385
|
function resolveAction(text) {
|
|
9398
9386
|
const parsed = parseSentinel(text);
|
|
@@ -9681,7 +9669,7 @@ var init_suggestions = __esm({
|
|
|
9681
9669
|
// src/brandExtraction/index.ts
|
|
9682
9670
|
import fs20 from "fs";
|
|
9683
9671
|
import path11 from "path";
|
|
9684
|
-
import { createHash } from "crypto";
|
|
9672
|
+
import { createHash as createHash2 } from "crypto";
|
|
9685
9673
|
async function runExtraction(apiConfig, model) {
|
|
9686
9674
|
const inputHash = computeInputHash();
|
|
9687
9675
|
const cached3 = readCache();
|
|
@@ -9722,7 +9710,7 @@ function computeInputHash() {
|
|
|
9722
9710
|
return sha256(fingerprint);
|
|
9723
9711
|
}
|
|
9724
9712
|
function sha256(input) {
|
|
9725
|
-
return
|
|
9713
|
+
return createHash2("sha256").update(input).digest("hex");
|
|
9726
9714
|
}
|
|
9727
9715
|
function readSafe(filePath) {
|
|
9728
9716
|
try {
|