replicas-engine 0.1.96 → 0.1.97
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/src/index.js +56 -16
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -1091,7 +1091,7 @@ function parseReplicasConfigString(content, filename) {
|
|
|
1091
1091
|
}
|
|
1092
1092
|
|
|
1093
1093
|
// ../shared/src/engine/environment.ts
|
|
1094
|
-
var DAYTONA_SNAPSHOT_ID = "
|
|
1094
|
+
var DAYTONA_SNAPSHOT_ID = "13-04-2026-relay-prompt";
|
|
1095
1095
|
|
|
1096
1096
|
// ../shared/src/engine/types.ts
|
|
1097
1097
|
var DEFAULT_CHAT_TITLES = {
|
|
@@ -2998,7 +2998,7 @@ var CodexManager = class extends CodingAgentManager {
|
|
|
2998
2998
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
2999
2999
|
import { z } from "zod";
|
|
3000
3000
|
var POLL_INTERVAL_MS = 2e3;
|
|
3001
|
-
var
|
|
3001
|
+
var DEFAULT_SUBAGENT_TIMEOUT_MS = 6e5;
|
|
3002
3002
|
async function engineFetch(path4, options) {
|
|
3003
3003
|
const baseUrl = `http://localhost:${ENGINE_ENV.REPLICAS_ENGINE_PORT}`;
|
|
3004
3004
|
return fetch(`${baseUrl}${path4}`, {
|
|
@@ -3010,28 +3010,38 @@ async function engineFetch(path4, options) {
|
|
|
3010
3010
|
}
|
|
3011
3011
|
});
|
|
3012
3012
|
}
|
|
3013
|
-
async function waitForChatCompletion(chatId) {
|
|
3013
|
+
async function waitForChatCompletion(chatId, timeoutMs = DEFAULT_SUBAGENT_TIMEOUT_MS) {
|
|
3014
3014
|
const start = Date.now();
|
|
3015
3015
|
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
3016
|
-
while (Date.now() - start <
|
|
3016
|
+
while (Date.now() - start < timeoutMs) {
|
|
3017
3017
|
const res = await engineFetch(`/chats/${chatId}`);
|
|
3018
3018
|
if (!res.ok) {
|
|
3019
3019
|
throw new Error(`Failed to poll chat ${chatId}: ${res.status}`);
|
|
3020
3020
|
}
|
|
3021
|
-
|
|
3021
|
+
let data;
|
|
3022
|
+
try {
|
|
3023
|
+
data = await res.json();
|
|
3024
|
+
} catch {
|
|
3025
|
+
throw new Error(`Failed to parse poll response for chat ${chatId} (chat may have been interrupted)`);
|
|
3026
|
+
}
|
|
3022
3027
|
if (!data.chat.processing) {
|
|
3023
3028
|
return;
|
|
3024
3029
|
}
|
|
3025
3030
|
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
3026
3031
|
}
|
|
3027
|
-
throw new Error(`Subagent chat ${chatId} timed out after ${
|
|
3032
|
+
throw new Error(`Subagent chat ${chatId} timed out after ${timeoutMs}ms`);
|
|
3028
3033
|
}
|
|
3029
3034
|
async function getChatFinalResponse(chatId) {
|
|
3030
3035
|
const res = await engineFetch(`/chats/${chatId}/history`);
|
|
3031
3036
|
if (!res.ok) {
|
|
3032
3037
|
return "[Failed to retrieve subagent history]";
|
|
3033
3038
|
}
|
|
3034
|
-
|
|
3039
|
+
let history;
|
|
3040
|
+
try {
|
|
3041
|
+
history = await res.json();
|
|
3042
|
+
} catch {
|
|
3043
|
+
return "[Failed to parse subagent history (response may have been interrupted)]";
|
|
3044
|
+
}
|
|
3035
3045
|
const events = history.events || [];
|
|
3036
3046
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
3037
3047
|
const event = events[i];
|
|
@@ -3083,7 +3093,8 @@ You will also receive the chatId so you can send follow-up messages or clean up
|
|
|
3083
3093
|
provider: z.enum(["claude", "codex", "relay"]).describe("Which agent to use. Prefer codex for code writing, claude for exploration/analysis, relay for complex multi-step orchestration."),
|
|
3084
3094
|
prompt: z.string().describe("The full prompt/instructions for the subagent. Be detailed - it has no context from your conversation."),
|
|
3085
3095
|
model: z.string().optional().describe("Model override. Claude: opus, sonnet, haiku. Codex: gpt-5.4, gpt-5.3-codex, etc."),
|
|
3086
|
-
title: z.string().optional().describe("Optional title for the subagent chat (for identification).")
|
|
3096
|
+
title: z.string().optional().describe("Optional title for the subagent chat (for identification)."),
|
|
3097
|
+
timeout_minutes: z.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
|
|
3087
3098
|
},
|
|
3088
3099
|
async (args) => {
|
|
3089
3100
|
try {
|
|
@@ -3116,7 +3127,8 @@ You will also receive the chatId so you can send follow-up messages or clean up
|
|
|
3116
3127
|
const err = await sendRes.text();
|
|
3117
3128
|
return { content: [{ type: "text", text: `Failed to send message to subagent: ${err}` }], isError: true };
|
|
3118
3129
|
}
|
|
3119
|
-
|
|
3130
|
+
const timeoutMs = args.timeout_minutes ? args.timeout_minutes * 6e4 : DEFAULT_SUBAGENT_TIMEOUT_MS;
|
|
3131
|
+
await waitForChatCompletion(chatId, timeoutMs);
|
|
3120
3132
|
const response = await getChatFinalResponse(chatId);
|
|
3121
3133
|
return {
|
|
3122
3134
|
content: [{
|
|
@@ -3142,7 +3154,8 @@ The tool blocks until the subagent completes and returns its response.`,
|
|
|
3142
3154
|
{
|
|
3143
3155
|
chatId: z.string().describe("The chat ID of the subagent (returned by spawn_agent)."),
|
|
3144
3156
|
message: z.string().describe("The follow-up message to send."),
|
|
3145
|
-
model: z.string().optional().describe("Optional model override for this message.")
|
|
3157
|
+
model: z.string().optional().describe("Optional model override for this message."),
|
|
3158
|
+
timeout_minutes: z.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
|
|
3146
3159
|
},
|
|
3147
3160
|
async (args) => {
|
|
3148
3161
|
try {
|
|
@@ -3158,7 +3171,8 @@ The tool blocks until the subagent completes and returns its response.`,
|
|
|
3158
3171
|
const err = await sendRes.text();
|
|
3159
3172
|
return { content: [{ type: "text", text: `Failed to send message: ${err}` }], isError: true };
|
|
3160
3173
|
}
|
|
3161
|
-
|
|
3174
|
+
const timeoutMs = args.timeout_minutes ? args.timeout_minutes * 6e4 : DEFAULT_SUBAGENT_TIMEOUT_MS;
|
|
3175
|
+
await waitForChatCompletion(args.chatId, timeoutMs);
|
|
3162
3176
|
const response = await getChatFinalResponse(args.chatId);
|
|
3163
3177
|
return {
|
|
3164
3178
|
content: [{
|
|
@@ -3305,15 +3319,41 @@ function getDelegationSection() {
|
|
|
3305
3319
|
|
|
3306
3320
|
You have three subagent tools for spawning and managing agents that run in separate context windows:
|
|
3307
3321
|
|
|
3308
|
-
- **spawn_agent**: Create a new subagent with a specific provider (claude or codex), send it a prompt, and wait for its response. Returns the chatId and the agent's final response.
|
|
3322
|
+
- **spawn_agent**: Create a new subagent with a specific provider (claude or codex), send it a prompt, and wait for its response. Returns the chatId and the agent's final response. You can set a custom timeout via the timeout_minutes parameter (default: 10 minutes).
|
|
3309
3323
|
- **message_agent**: Send a follow-up message to an existing subagent by chatId. Use for iteration, corrections, or additional requests in the same context.
|
|
3310
3324
|
- **delete_agent**: Delete a subagent chat when you no longer need it.
|
|
3311
3325
|
|
|
3312
|
-
## When to delegate vs work directly
|
|
3326
|
+
## When to delegate vs work directly \u2014 the context efficiency rule
|
|
3327
|
+
|
|
3328
|
+
Your primary resource is your context window. Every tool call result, every code snippet, every debug log you read consumes context that you cannot reclaim. The key question when deciding whether to delegate is: **will doing this work myself cost more context than delegating it?**
|
|
3329
|
+
|
|
3330
|
+
**Do it directly** when the task is simple and context-light: a small edit, a quick search, running a single command, reading one file, answering a question from brief investigation. These cost little context and the overhead of explaining the task to a subagent would be greater.
|
|
3331
|
+
|
|
3332
|
+
**Delegate to a subagent** when the work would pollute your context with large amounts of intermediate output. Examples:
|
|
3333
|
+
- Testing and debugging: Running a server, curling endpoints, reading error output, iterating on fixes \u2014 this cycle consumes enormous context. Delegate the entire test-and-fix loop to a subagent.
|
|
3334
|
+
- Large code writing across multiple files.
|
|
3335
|
+
- Exploring a large codebase where you'd need to read many files.
|
|
3336
|
+
- Any iterative work (trial-and-error debugging, running tests repeatedly, build-fix cycles).
|
|
3337
|
+
|
|
3338
|
+
**The tradeoff**: Subagents start with zero context, so they may produce lower quality work if the task requires deep understanding of the project. Weigh this: is it more context-efficient for you to do the work directly (because explaining the full context to a subagent would be lengthy and the task itself is small), or is it more efficient to spend tokens on a thorough subagent prompt and keep your own context clean? When in doubt, if the work involves more than a few tool calls of iterative output (e.g., running commands and reacting to results), delegate it.
|
|
3339
|
+
|
|
3340
|
+
## Parallel execution
|
|
3341
|
+
|
|
3342
|
+
You can spawn multiple subagents in parallel by making multiple spawn_agent tool calls in a single response. Do this whenever you have independent tasks \u2014 do NOT call them sequentially if they don't depend on each other. For example, if you need to test three endpoints, spawn three subagents in one response, not one after another.
|
|
3343
|
+
|
|
3344
|
+
## Testing your work
|
|
3345
|
+
|
|
3346
|
+
After implementing changes, verify they work. Scale testing to the complexity of the task:
|
|
3347
|
+
|
|
3348
|
+
- **Small changes** (updating one endpoint, fixing a bug): A quick direct verification is sufficient.
|
|
3349
|
+
- **Medium changes** (new feature, multiple files): Spawn a subagent to run tests or verify the feature works end-to-end.
|
|
3350
|
+
- **Large/complex changes** (new system, many features, full application): Spawn multiple parallel subagents to test different aspects thoroughly. For example, test each endpoint or feature independently via separate subagents. Do not skip testing on complex work \u2014 missing features and broken functionality are worse than the token cost of verification.
|
|
3351
|
+
|
|
3352
|
+
Do not burn tokens for the sake of it. Match testing depth to the risk and complexity of the change.
|
|
3313
3353
|
|
|
3314
|
-
|
|
3354
|
+
## Subagent timeouts
|
|
3315
3355
|
|
|
3316
|
-
|
|
3356
|
+
The default subagent timeout is 10 minutes. For tasks you expect to take longer (large implementations, extensive test suites, complex debugging), set a generous timeout using the timeout_minutes parameter on spawn_agent. For example, a subagent building a full feature might need 20-30 minutes. If a subagent times out, you lose all of its work, so err on the side of generous timeouts for substantial tasks.
|
|
3317
3357
|
|
|
3318
3358
|
## Agent selection
|
|
3319
3359
|
|
|
@@ -3326,7 +3366,7 @@ Use provider 'claude' for codebase exploration, code review, planning, complex d
|
|
|
3326
3366
|
- Subagents start with a blank context. Include all relevant file paths, code snippets, requirements, and constraints in the prompt.
|
|
3327
3367
|
- Give each subagent a focused, specific task. Don't ask one agent to do everything.
|
|
3328
3368
|
- After a subagent completes, review its output. Send follow-up messages for corrections, or verify changes with your direct tools.
|
|
3329
|
-
-
|
|
3369
|
+
- Do NOT proactively delete subagent chats. Only use delete_agent when the user explicitly asks you to clean up or delete agents. Keeping subagents around allows the user to inspect their work and allows you to send follow-up messages if needed.
|
|
3330
3370
|
- Use provider 'relay' for complex multi-step tasks that themselves benefit from orchestration and delegation.
|
|
3331
3371
|
- Do not over-delegate. Spawning an agent for a trivial edit wastes time.`;
|
|
3332
3372
|
}
|