replicas-engine 0.1.469 → 0.1.471
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 +204 -138
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -582,7 +582,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
582
582
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
583
583
|
|
|
584
584
|
// ../shared/src/e2b.ts
|
|
585
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-
|
|
585
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-21-v1";
|
|
586
586
|
|
|
587
587
|
// ../shared/src/runtime-env.ts
|
|
588
588
|
function shellQuotePosix(value) {
|
|
@@ -1190,7 +1190,7 @@ GitHub does NOT have a public API for uploading images to PRs/issues. When you n
|
|
|
1190
1190
|
- Do NOT commit screenshots as files to the repository
|
|
1191
1191
|
- Run \`replicas media upload <image> --share\` and put the printed \`Forge embed\` Markdown in the PR body or comment
|
|
1192
1192
|
- For video, embed a shared poster image linked to the recording's **View in Replicas** URL; GitHub does not reliably render externally hosted video inline
|
|
1193
|
-
- Treat the public URL as an opt-in bearer capability
|
|
1193
|
+
- Treat the public URL as an opt-in bearer capability; revoke it with \`replicas media revoke <media-id>\` only when the user asks or the media should stop rendering \u2014 revoking breaks embeds already posted on the PR
|
|
1194
1194
|
- If you were triggered from Slack, also upload the image to the Slack thread so the user can see it directly
|
|
1195
1195
|
`;
|
|
1196
1196
|
var GITHUB_ABILITY = {
|
|
@@ -1969,7 +1969,7 @@ GitHub does not reliably render arbitrary external videos as inline players. For
|
|
|
1969
1969
|
[](<recording-dashboard-url>)
|
|
1970
1970
|
\`\`\`
|
|
1971
1971
|
|
|
1972
|
-
Public forge shares are bearer capabilities. For private repositories, create one only when the user asked for inline PR media
|
|
1972
|
+
Public forge shares are bearer capabilities. For private repositories, create one only when the user asked for inline PR media. Revoke with \`replicas media revoke <media-id>\` **only** when the user asks or the media should intentionally stop rendering \u2014 never as routine post-task cleanup, since revoking breaks every embed already posted on the PR.
|
|
1973
1973
|
|
|
1974
1974
|
Do **not** commit screenshots to the repo, use placeholder URLs, expose the authenticated \`/v1/media/<id>\` URL, or automate GitHub's undocumented browser upload flow.
|
|
1975
1975
|
|
|
@@ -2796,10 +2796,19 @@ function hasChatStarted(chat) {
|
|
|
2796
2796
|
var DESKTOP_NOVNC_PORT = 6080;
|
|
2797
2797
|
|
|
2798
2798
|
// ../shared/src/engine/v1.ts
|
|
2799
|
+
import { z as z2 } from "zod";
|
|
2799
2800
|
var MERGED_MESSAGE_SEPARATOR = "\n\n<!-- replicas:merged -->\n\n";
|
|
2800
2801
|
var ENGINE_HEALTH_WAIT_HEADER = "X-Replicas-Health-Wait";
|
|
2801
2802
|
var ENGINE_HEALTH_WAIT_QUERY_PARAM = "wait_ms";
|
|
2802
2803
|
var ENGINE_HEALTH_MAX_WAIT_MS = 2e3;
|
|
2804
|
+
var createChatRequestSchema = z2.object({
|
|
2805
|
+
id: z2.string().uuid().optional(),
|
|
2806
|
+
createdAt: z2.string().datetime().optional(),
|
|
2807
|
+
provider: z2.enum(VALID_AGENT_PROVIDERS),
|
|
2808
|
+
title: z2.string().min(1).optional(),
|
|
2809
|
+
parentChatId: z2.string().uuid().optional(),
|
|
2810
|
+
clientRequestId: z2.string().min(1).max(128).optional()
|
|
2811
|
+
});
|
|
2803
2812
|
function normalizeCodexAspTranscriptStatus(status, failed = false) {
|
|
2804
2813
|
if (failed || status === "failed" || status === "declined") return "failed";
|
|
2805
2814
|
if (status === "completed") return "completed";
|
|
@@ -2817,6 +2826,20 @@ function imageContentToUserMessageImages(images) {
|
|
|
2817
2826
|
}
|
|
2818
2827
|
return userImages.length > 0 ? userImages : void 0;
|
|
2819
2828
|
}
|
|
2829
|
+
function createAcceptedUserMessageEvent(message, messageId, timestamp, images) {
|
|
2830
|
+
const eventImages = imageContentToUserMessageImages(images);
|
|
2831
|
+
return {
|
|
2832
|
+
timestamp,
|
|
2833
|
+
type: "event_msg",
|
|
2834
|
+
payload: {
|
|
2835
|
+
type: "user_message",
|
|
2836
|
+
message,
|
|
2837
|
+
source: ACCEPTED_USER_MESSAGE_SOURCE,
|
|
2838
|
+
[USER_MESSAGE_ID_PAYLOAD_KEY]: messageId,
|
|
2839
|
+
...eventImages ? { images: eventImages } : {}
|
|
2840
|
+
}
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2820
2843
|
function isCodexAspTranscript(value) {
|
|
2821
2844
|
if (!isRecord(value)) return false;
|
|
2822
2845
|
return typeof value.threadId === "string" && typeof value.updatedAt === "string" && Array.isArray(value.turns);
|
|
@@ -3207,6 +3230,22 @@ function safeJsonParse(str, fallback) {
|
|
|
3207
3230
|
}
|
|
3208
3231
|
}
|
|
3209
3232
|
|
|
3233
|
+
// ../shared/src/display-message/parsers/utils.ts
|
|
3234
|
+
function userMessageImages(value) {
|
|
3235
|
+
if (!Array.isArray(value)) return void 0;
|
|
3236
|
+
const images = value.filter((item) => isRecord(item) && item.type === "image" && typeof item.mediaType === "string" && typeof item.data === "string");
|
|
3237
|
+
return images.length > 0 ? images : void 0;
|
|
3238
|
+
}
|
|
3239
|
+
function stringifyDisplayValue(value) {
|
|
3240
|
+
if (value === void 0 || value === null) return void 0;
|
|
3241
|
+
if (typeof value === "string") return value;
|
|
3242
|
+
try {
|
|
3243
|
+
return JSON.stringify(value, null, 2);
|
|
3244
|
+
} catch {
|
|
3245
|
+
return String(value);
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3210
3249
|
// ../shared/src/display-message/parsers/codex-parser.ts
|
|
3211
3250
|
function getStatusFromExitCode(exitCode) {
|
|
3212
3251
|
return exitCode === 0 ? "completed" : "failed";
|
|
@@ -3219,14 +3258,6 @@ function displayId(event, eventIndex, prefix) {
|
|
|
3219
3258
|
const stableId = getPayloadString(event, USER_MESSAGE_ID_PAYLOAD_KEY) ?? getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY);
|
|
3220
3259
|
return stableId ? `${prefix}-${stableId}` : `${prefix}-${event.timestamp}-${eventIndex}`;
|
|
3221
3260
|
}
|
|
3222
|
-
function userMessageImages(value) {
|
|
3223
|
-
if (!Array.isArray(value)) return void 0;
|
|
3224
|
-
const images = value.filter((item) => {
|
|
3225
|
-
if (!isRecord(item)) return false;
|
|
3226
|
-
return item.type === "image" && typeof item.mediaType === "string" && typeof item.data === "string";
|
|
3227
|
-
});
|
|
3228
|
-
return images.length > 0 ? images : void 0;
|
|
3229
|
-
}
|
|
3230
3261
|
function parseShellOutput(raw) {
|
|
3231
3262
|
const exitCodeMatch = raw.match(/^Exit code: (\d+)/m) || raw.match(/Process exited with code (\d+)/);
|
|
3232
3263
|
const exitCode = exitCodeMatch ? parseInt(exitCodeMatch[1], 10) : 0;
|
|
@@ -3450,17 +3481,6 @@ function parseCodexEvents(events) {
|
|
|
3450
3481
|
return messages;
|
|
3451
3482
|
}
|
|
3452
3483
|
|
|
3453
|
-
// ../shared/src/display-message/parsers/utils.ts
|
|
3454
|
-
function stringifyDisplayValue(value) {
|
|
3455
|
-
if (value === void 0 || value === null) return void 0;
|
|
3456
|
-
if (typeof value === "string") return value;
|
|
3457
|
-
try {
|
|
3458
|
-
return JSON.stringify(value, null, 2);
|
|
3459
|
-
} catch {
|
|
3460
|
-
return String(value);
|
|
3461
|
-
}
|
|
3462
|
-
}
|
|
3463
|
-
|
|
3464
3484
|
// ../shared/src/display-message/parsers/cursor-parser.ts
|
|
3465
3485
|
function getTextContent(value) {
|
|
3466
3486
|
if (!Array.isArray(value)) return "";
|
|
@@ -4021,6 +4041,7 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
4021
4041
|
let liveStreamId = null;
|
|
4022
4042
|
const assistantThinking = /* @__PURE__ */ new Map();
|
|
4023
4043
|
const assistantTextCounts = /* @__PURE__ */ new Map();
|
|
4044
|
+
const acceptedUserMessageIndexes = /* @__PURE__ */ new Set();
|
|
4024
4045
|
const taskAccumulator = new TaskAccumulator();
|
|
4025
4046
|
const taskSnapshot = () => taskAccumulator.getTasks().map((task) => ({
|
|
4026
4047
|
text: task.subject,
|
|
@@ -4028,6 +4049,21 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
4028
4049
|
itemStatus: task.status
|
|
4029
4050
|
}));
|
|
4030
4051
|
filteredEvents.forEach((event) => {
|
|
4052
|
+
if (event.type === "event_msg" && event.payload.type === "user_message") {
|
|
4053
|
+
const content = typeof event.payload.message === "string" ? event.payload.message : "";
|
|
4054
|
+
const images = userMessageImages(event.payload.images);
|
|
4055
|
+
if (content || images) {
|
|
4056
|
+
const messageId = event.payload[USER_MESSAGE_ID_PAYLOAD_KEY];
|
|
4057
|
+
acceptedUserMessageIndexes.add(messages.push({
|
|
4058
|
+
id: typeof messageId === "string" ? messageId : `user-${event.timestamp}`,
|
|
4059
|
+
type: "user",
|
|
4060
|
+
content,
|
|
4061
|
+
images,
|
|
4062
|
+
timestamp: event.timestamp
|
|
4063
|
+
}) - 1);
|
|
4064
|
+
}
|
|
4065
|
+
return;
|
|
4066
|
+
}
|
|
4031
4067
|
if (event.type === CLAUDE_PARTIAL_MESSAGE_EVENT_TYPE) {
|
|
4032
4068
|
const payload = coerceClaudePartialMessagePayload(event.payload);
|
|
4033
4069
|
if (!payload) return;
|
|
@@ -4085,13 +4121,24 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
4085
4121
|
};
|
|
4086
4122
|
}).filter((img) => img.data);
|
|
4087
4123
|
if (textContent || images.length > 0) {
|
|
4088
|
-
|
|
4089
|
-
|
|
4124
|
+
const acceptedIndex = [...acceptedUserMessageIndexes].find((index) => {
|
|
4125
|
+
const accepted2 = messages[index];
|
|
4126
|
+
return accepted2?.type === "user" && accepted2.content === textContent;
|
|
4127
|
+
});
|
|
4128
|
+
const accepted = acceptedIndex === void 0 ? void 0 : messages[acceptedIndex];
|
|
4129
|
+
const message = {
|
|
4130
|
+
id: accepted?.id ?? `user-${event.timestamp}`,
|
|
4090
4131
|
type: "user",
|
|
4091
4132
|
content: textContent || (images.length > 0 ? `[${images.length} image${images.length > 1 ? "s" : ""} attached]` : ""),
|
|
4092
|
-
images: images.length > 0 ? images : void 0,
|
|
4133
|
+
images: images.length > 0 ? images : accepted?.type === "user" ? accepted.images : void 0,
|
|
4093
4134
|
timestamp: event.timestamp
|
|
4094
|
-
}
|
|
4135
|
+
};
|
|
4136
|
+
if (acceptedIndex === void 0) {
|
|
4137
|
+
messages.push(message);
|
|
4138
|
+
} else {
|
|
4139
|
+
messages[acceptedIndex] = message;
|
|
4140
|
+
acceptedUserMessageIndexes.delete(acceptedIndex);
|
|
4141
|
+
}
|
|
4095
4142
|
}
|
|
4096
4143
|
}
|
|
4097
4144
|
if (event.type === "claude-assistant") {
|
|
@@ -7610,11 +7657,11 @@ var MessageQueueService = class {
|
|
|
7610
7657
|
position: this.queue.length
|
|
7611
7658
|
};
|
|
7612
7659
|
}
|
|
7613
|
-
const messageId = this.generateMessageId();
|
|
7660
|
+
const messageId = request.messageId ?? this.generateMessageId();
|
|
7614
7661
|
const queuedMessage = {
|
|
7615
7662
|
id: messageId,
|
|
7616
7663
|
...request,
|
|
7617
|
-
queuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7664
|
+
queuedAt: request.submittedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
7618
7665
|
};
|
|
7619
7666
|
if (this.processing) {
|
|
7620
7667
|
this.queue.push(queuedMessage);
|
|
@@ -9785,7 +9832,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
9785
9832
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
9786
9833
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
9787
9834
|
var codexCliVersionEnsured = null;
|
|
9788
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
9835
|
+
var ENGINE_PACKAGE_VERSION = "0.1.471";
|
|
9789
9836
|
var INITIALIZE_METHOD = "initialize";
|
|
9790
9837
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
9791
9838
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -12016,6 +12063,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12016
12063
|
abortActiveTurn = null;
|
|
12017
12064
|
blockedToolCallIds = /* @__PURE__ */ new Set();
|
|
12018
12065
|
pendingCursorBlockReason = null;
|
|
12066
|
+
instructionsDelivered = false;
|
|
12019
12067
|
historyFilePath;
|
|
12020
12068
|
historyFile;
|
|
12021
12069
|
slashCommandsCache = null;
|
|
@@ -12089,16 +12137,18 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12089
12137
|
throw new Error("Cursor API key is not configured for this workspace.");
|
|
12090
12138
|
}
|
|
12091
12139
|
const model = { id: request.model ?? DEFAULT_CURSOR_MODEL };
|
|
12140
|
+
const settingSources = ["project", "user"];
|
|
12141
|
+
const local = { cwd: this.workingDirectory, settingSources };
|
|
12092
12142
|
this.agent = this.initialSessionId ? await CursorAgent.resume(this.initialSessionId, {
|
|
12093
12143
|
apiKey,
|
|
12094
12144
|
model,
|
|
12095
|
-
local
|
|
12145
|
+
local
|
|
12096
12146
|
}) : await CursorAgent.create({
|
|
12097
12147
|
apiKey,
|
|
12098
12148
|
model,
|
|
12099
|
-
local
|
|
12149
|
+
local
|
|
12100
12150
|
});
|
|
12101
|
-
await this.onSaveSessionId(this.agent.agentId);
|
|
12151
|
+
if (this.initialSessionId) await this.onSaveSessionId(this.agent.agentId);
|
|
12102
12152
|
return this.agent;
|
|
12103
12153
|
}
|
|
12104
12154
|
async processMessageInternal(request) {
|
|
@@ -12109,8 +12159,9 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12109
12159
|
const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
|
|
12110
12160
|
const linearForwarder = new LinearEventForwarder(linearSessionId);
|
|
12111
12161
|
try {
|
|
12162
|
+
const includeInstructions = !this.initialSessionId && !this.instructionsDelivered;
|
|
12163
|
+
const message = await this.toCursorMessage(request, includeInstructions);
|
|
12112
12164
|
const agent = await this.ensureAgent(request);
|
|
12113
|
-
const message = await this.toCursorMessage(request);
|
|
12114
12165
|
const model = request.model ?? DEFAULT_CURSOR_MODEL;
|
|
12115
12166
|
this.recordHistoryEvent("event_msg", {
|
|
12116
12167
|
type: "user_message",
|
|
@@ -12164,6 +12215,10 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12164
12215
|
if (result === TIMEOUT) {
|
|
12165
12216
|
throw new Error("Cursor run did not report a result after its event stream ended");
|
|
12166
12217
|
}
|
|
12218
|
+
if (includeInstructions) {
|
|
12219
|
+
this.instructionsDelivered = true;
|
|
12220
|
+
await this.onSaveSessionId(agent.agentId);
|
|
12221
|
+
}
|
|
12167
12222
|
if (result.status === "error") {
|
|
12168
12223
|
this.recordHistoryEvent("cursor-error", {
|
|
12169
12224
|
type: "error",
|
|
@@ -12222,13 +12277,19 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12222
12277
|
}
|
|
12223
12278
|
this.pendingCursorBlockReason = message;
|
|
12224
12279
|
}
|
|
12225
|
-
async toCursorMessage(request) {
|
|
12280
|
+
async toCursorMessage(request, includeInstructions) {
|
|
12281
|
+
const instructions = includeInstructions ? this.buildCombinedInstructions(request.customInstructions) : void 0;
|
|
12282
|
+
const text = instructions ? `<workspace-instructions>
|
|
12283
|
+
${instructions}
|
|
12284
|
+
</workspace-instructions>
|
|
12285
|
+
|
|
12286
|
+
${request.message}` : request.message;
|
|
12226
12287
|
if (!request.images || request.images.length === 0) {
|
|
12227
|
-
return
|
|
12288
|
+
return text;
|
|
12228
12289
|
}
|
|
12229
12290
|
const images = await normalizeImages(request.images);
|
|
12230
12291
|
return {
|
|
12231
|
-
text
|
|
12292
|
+
text,
|
|
12232
12293
|
images: images.map((image) => ({
|
|
12233
12294
|
data: image.source.data,
|
|
12234
12295
|
mimeType: image.source.media_type
|
|
@@ -12310,7 +12371,7 @@ import { delimiter, dirname as dirname6, join as join18 } from "path";
|
|
|
12310
12371
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
12311
12372
|
import { fileURLToPath } from "url";
|
|
12312
12373
|
import { Agent } from "undici";
|
|
12313
|
-
import { z as
|
|
12374
|
+
import { z as z3 } from "zod";
|
|
12314
12375
|
import {
|
|
12315
12376
|
createOpencodeClient,
|
|
12316
12377
|
createOpencodeServer
|
|
@@ -12347,9 +12408,9 @@ var OPENCODE_VARIANT_CANDIDATES_BY_THINKING_LEVEL = {
|
|
|
12347
12408
|
ultra: ["max", "xhigh", "high"],
|
|
12348
12409
|
ultracode: ["max", "xhigh", "high"]
|
|
12349
12410
|
};
|
|
12350
|
-
var opencodeAuthSchema =
|
|
12351
|
-
type:
|
|
12352
|
-
key:
|
|
12411
|
+
var opencodeAuthSchema = z3.record(z3.string(), z3.object({
|
|
12412
|
+
type: z3.string().optional(),
|
|
12413
|
+
key: z3.string().optional()
|
|
12353
12414
|
}));
|
|
12354
12415
|
async function hasOpenCodeGoCredentials() {
|
|
12355
12416
|
if (!existsSync7(OPENCODE_AUTH_PATH2)) return false;
|
|
@@ -13194,7 +13255,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13194
13255
|
|
|
13195
13256
|
// src/managers/relay-tools.ts
|
|
13196
13257
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
13197
|
-
import { z as
|
|
13258
|
+
import { z as z4 } from "zod";
|
|
13198
13259
|
|
|
13199
13260
|
// src/managers/relay-providers.ts
|
|
13200
13261
|
function isRelaySubagentProviderAllowed(provider, allowedProviders) {
|
|
@@ -13309,7 +13370,7 @@ function buildSpawnAgentTool(parentChatId, availability = {}, getAllowedProvider
|
|
|
13309
13370
|
const cursorAvailable = availability.cursorAvailable ?? false;
|
|
13310
13371
|
const opencodeAvailable = availability.opencodeAvailable ?? false;
|
|
13311
13372
|
const availableProviders = getAvailableRelayProviders(availability);
|
|
13312
|
-
const providerEnum =
|
|
13373
|
+
const providerEnum = z4.enum(availableProviders);
|
|
13313
13374
|
const codeProviders = getAvailableCodeProviders(availability);
|
|
13314
13375
|
const providerDesc = codeProviders.length > 0 ? `Which agent to use. Prefer ${codeProviders.join(" or ")} for code writing, claude for exploration/analysis, relay for complex multi-step orchestration.` : "Which agent to use. Use claude for code writing, exploration, and analysis. Use relay for complex multi-step orchestration.";
|
|
13315
13376
|
const useCases = codeProviders.length > 0 ? `- Complex code writing tasks (use provider '${codeProviders.join("' or '")}' with a capable model)
|
|
@@ -13328,18 +13389,18 @@ The tool blocks until the subagent completes and returns its final response.
|
|
|
13328
13389
|
You will also receive the chatId so you can send follow-up messages or clean up the chat.`,
|
|
13329
13390
|
{
|
|
13330
13391
|
provider: providerEnum.describe(providerDesc),
|
|
13331
|
-
prompt:
|
|
13332
|
-
model:
|
|
13392
|
+
prompt: z4.string().describe("The full prompt/instructions for the subagent. Be detailed - it has no context from your conversation."),
|
|
13393
|
+
model: z4.string().optional().describe([
|
|
13333
13394
|
`Model override. Claude: ${AGENT_MODELS.claude.join(", ")} (opus is the default; sonnet is faster).`,
|
|
13334
13395
|
codexAvailable ? `Codex: ${AGENT_MODELS.codex.join(", ")}.` : null,
|
|
13335
13396
|
cursorAvailable ? `Cursor: ${AGENT_MODELS.cursor.join(", ")}.` : null,
|
|
13336
13397
|
opencodeAvailable ? `Opencode: ${AGENT_MODELS.opencode.join(", ")}.` : null
|
|
13337
13398
|
].filter(Boolean).join(" ")),
|
|
13338
|
-
thinking_level:
|
|
13399
|
+
thinking_level: z4.enum(VALID_THINKING_LEVELS).optional().describe(
|
|
13339
13400
|
"Controls how much thinking/reasoning the subagent applies. low = light thinking, medium = moderate, high = deep reasoning, xhigh = extended effort, max = maximum effort, ultra = Codex ultra, ultracode = Claude Code dynamic workflows. Defaults: Claude = high, Codex = medium, Cursor = medium, Opencode = medium."
|
|
13340
13401
|
),
|
|
13341
|
-
title:
|
|
13342
|
-
timeout_minutes:
|
|
13402
|
+
title: z4.string().optional().describe("Optional title for the subagent chat (for identification)."),
|
|
13403
|
+
timeout_minutes: z4.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
|
|
13343
13404
|
},
|
|
13344
13405
|
async (args) => {
|
|
13345
13406
|
try {
|
|
@@ -13414,13 +13475,13 @@ var messageAgentTool = tool(
|
|
|
13414
13475
|
|
|
13415
13476
|
The tool blocks until the subagent completes and returns its response.`,
|
|
13416
13477
|
{
|
|
13417
|
-
chatId:
|
|
13418
|
-
message:
|
|
13419
|
-
model:
|
|
13420
|
-
thinking_level:
|
|
13478
|
+
chatId: z4.string().describe("The chat ID of the subagent (returned by spawn_agent)."),
|
|
13479
|
+
message: z4.string().describe("The follow-up message to send."),
|
|
13480
|
+
model: z4.string().optional().describe("Optional model override for this message."),
|
|
13481
|
+
thinking_level: z4.enum(VALID_THINKING_LEVELS).optional().describe(
|
|
13421
13482
|
"Controls how much thinking/reasoning the subagent applies. low = light thinking, medium = moderate, high = deep reasoning, xhigh = extended effort, max = maximum effort, ultra = Codex ultra, ultracode = Claude Code dynamic workflows. Defaults: Claude = high, Codex = medium, Cursor = medium, Opencode = medium."
|
|
13422
13483
|
),
|
|
13423
|
-
timeout_minutes:
|
|
13484
|
+
timeout_minutes: z4.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
|
|
13424
13485
|
},
|
|
13425
13486
|
async (args) => {
|
|
13426
13487
|
try {
|
|
@@ -13458,7 +13519,7 @@ var deleteAgentTool = tool(
|
|
|
13458
13519
|
"delete_agent",
|
|
13459
13520
|
`Delete a subagent chat to free resources. Use this after a subagent has completed its work and you no longer need to send it follow-up messages.`,
|
|
13460
13521
|
{
|
|
13461
|
-
chatId:
|
|
13522
|
+
chatId: z4.string().describe("The chat ID of the subagent to delete.")
|
|
13462
13523
|
},
|
|
13463
13524
|
async (args) => {
|
|
13464
13525
|
try {
|
|
@@ -14234,7 +14295,11 @@ function normalizePersistedChat(chat) {
|
|
|
14234
14295
|
providerSessionId: isLegacyCodexSdkChat ? null : chat.providerSessionId,
|
|
14235
14296
|
parentChatId: chat.parentChatId ?? null,
|
|
14236
14297
|
lastMessageText: chat.lastMessageText ?? null,
|
|
14237
|
-
deletedAt: chat.deletedAt ?? null
|
|
14298
|
+
deletedAt: chat.deletedAt ?? null,
|
|
14299
|
+
acceptedSendResponses: isRecord4(chat.acceptedSendResponses) ? Object.fromEntries(Object.entries(chat.acceptedSendResponses).filter((entry) => {
|
|
14300
|
+
const response = entry[1];
|
|
14301
|
+
return isRecord4(response) && typeof response.messageId === "string" && typeof response.queued === "boolean" && typeof response.position === "number";
|
|
14302
|
+
})) : {}
|
|
14238
14303
|
};
|
|
14239
14304
|
}
|
|
14240
14305
|
function parsePersistedChatsContent(content) {
|
|
@@ -14247,20 +14312,6 @@ function parsePersistedChatsContent(content) {
|
|
|
14247
14312
|
function corruptChatsFilePath() {
|
|
14248
14313
|
return `${CHATS_FILE}.corrupt-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
14249
14314
|
}
|
|
14250
|
-
function createUserMessageEvent(message, messageId, images) {
|
|
14251
|
-
const eventImages = imageContentToUserMessageImages(images);
|
|
14252
|
-
return {
|
|
14253
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14254
|
-
type: "event_msg",
|
|
14255
|
-
payload: {
|
|
14256
|
-
type: "user_message",
|
|
14257
|
-
message,
|
|
14258
|
-
source: ACCEPTED_USER_MESSAGE_SOURCE,
|
|
14259
|
-
[USER_MESSAGE_ID_PAYLOAD_KEY]: messageId,
|
|
14260
|
-
...eventImages ? { images: eventImages } : {}
|
|
14261
|
-
}
|
|
14262
|
-
};
|
|
14263
|
-
}
|
|
14264
14315
|
var ChatService = class {
|
|
14265
14316
|
constructor(workingDirectory) {
|
|
14266
14317
|
this.workingDirectory = workingDirectory;
|
|
@@ -14323,17 +14374,30 @@ var ChatService = class {
|
|
|
14323
14374
|
};
|
|
14324
14375
|
}
|
|
14325
14376
|
async createChat(request) {
|
|
14326
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14377
|
+
const now = request.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
14327
14378
|
const title = request.title?.trim() || `${request.provider} chat`;
|
|
14328
|
-
if (
|
|
14329
|
-
|
|
14379
|
+
if (request.id) {
|
|
14380
|
+
const existing = this.chats.get(request.id);
|
|
14381
|
+
if (existing && !existing.persisted.deletedAt) {
|
|
14382
|
+
if (existing.persisted.provider !== request.provider) {
|
|
14383
|
+
throw new Error(`Chat ${request.id} already exists with a different provider`);
|
|
14384
|
+
}
|
|
14385
|
+
return this.toSummary(existing);
|
|
14386
|
+
}
|
|
14387
|
+
}
|
|
14388
|
+
const existingDefault = isDefaultChat({ provider: request.provider, title }) ? Array.from(this.chats.values()).find((chat) => !chat.persisted.deletedAt && chat.persisted.provider === request.provider && isDefaultChat(chat.persisted)) : void 0;
|
|
14389
|
+
if (existingDefault) {
|
|
14390
|
+
if (!request.id || hasChatStarted(this.toSummary(existingDefault))) {
|
|
14391
|
+
throw new DuplicateDefaultChatError(request.provider);
|
|
14392
|
+
}
|
|
14393
|
+
this.chats.delete(existingDefault.persisted.id);
|
|
14330
14394
|
}
|
|
14331
14395
|
const parentChatId = request.parentChatId ?? null;
|
|
14332
14396
|
if (parentChatId && !this.chats.has(parentChatId)) {
|
|
14333
14397
|
throw new ChatNotFoundError(parentChatId);
|
|
14334
14398
|
}
|
|
14335
14399
|
const persisted = {
|
|
14336
|
-
id: randomUUID5(),
|
|
14400
|
+
id: request.id ?? randomUUID5(),
|
|
14337
14401
|
provider: request.provider,
|
|
14338
14402
|
title,
|
|
14339
14403
|
createdAt: now,
|
|
@@ -14368,8 +14432,14 @@ var ChatService = class {
|
|
|
14368
14432
|
if (chat.acceptedSendResponses.size <= MAX_ACCEPTED_SEND_RESPONSES) break;
|
|
14369
14433
|
chat.acceptedSendResponses.delete(key);
|
|
14370
14434
|
}
|
|
14435
|
+
chat.persisted.acceptedSendResponses = Object.fromEntries(chat.acceptedSendResponses);
|
|
14371
14436
|
}
|
|
14372
|
-
const acceptedEvent =
|
|
14437
|
+
const acceptedEvent = createAcceptedUserMessageEvent(
|
|
14438
|
+
request.message,
|
|
14439
|
+
result.messageId,
|
|
14440
|
+
request.submittedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
14441
|
+
request.images
|
|
14442
|
+
);
|
|
14373
14443
|
chat.pendingMessageIds.push(result.messageId);
|
|
14374
14444
|
if (request.errorNotificationTarget) {
|
|
14375
14445
|
chat.errorNotificationTargets.set(result.messageId, request.errorNotificationTarget);
|
|
@@ -14384,7 +14454,7 @@ var ChatService = class {
|
|
|
14384
14454
|
senderEmail: request.senderEmail,
|
|
14385
14455
|
...request.senderDisplayName ? { senderDisplayName: request.senderDisplayName } : {},
|
|
14386
14456
|
...request.senderAvatarUrl ? { senderAvatarUrl: request.senderAvatarUrl } : {},
|
|
14387
|
-
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
14457
|
+
recordedAt: request.submittedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
14388
14458
|
};
|
|
14389
14459
|
await this.appendSender(chatId, recordedSender);
|
|
14390
14460
|
}
|
|
@@ -14736,7 +14806,7 @@ var ChatService = class {
|
|
|
14736
14806
|
provider,
|
|
14737
14807
|
pendingMessageIds: [],
|
|
14738
14808
|
acceptedUserEvents: /* @__PURE__ */ new Map(),
|
|
14739
|
-
acceptedSendResponses:
|
|
14809
|
+
acceptedSendResponses: new Map(Object.entries(persisted.acceptedSendResponses ?? {})),
|
|
14740
14810
|
activeMessageId: null,
|
|
14741
14811
|
hasActiveTurn: false,
|
|
14742
14812
|
observedBranchesByRepo: /* @__PURE__ */ new Map(),
|
|
@@ -15275,7 +15345,7 @@ var RepoFileService = class {
|
|
|
15275
15345
|
|
|
15276
15346
|
// src/v1-routes.ts
|
|
15277
15347
|
import { Hono } from "hono";
|
|
15278
|
-
import { z as
|
|
15348
|
+
import { z as z5 } from "zod";
|
|
15279
15349
|
import { readdir as readdir9, stat as stat5, readFile as readFile18 } from "fs/promises";
|
|
15280
15350
|
import { join as join26, resolve as resolve3 } from "path";
|
|
15281
15351
|
|
|
@@ -15783,79 +15853,75 @@ var TerminalService = class {
|
|
|
15783
15853
|
var terminalService = new TerminalService();
|
|
15784
15854
|
|
|
15785
15855
|
// src/v1-routes.ts
|
|
15786
|
-
var setWorkspaceNameSchema =
|
|
15787
|
-
name:
|
|
15788
|
-
});
|
|
15789
|
-
var createChatSchema = z4.object({
|
|
15790
|
-
provider: z4.enum(["claude", "codex", "cursor", "opencode", "pi", "relay"]),
|
|
15791
|
-
title: z4.string().min(1).optional(),
|
|
15792
|
-
parentChatId: z4.string().uuid().optional(),
|
|
15793
|
-
clientRequestId: z4.string().min(1).max(128).optional()
|
|
15856
|
+
var setWorkspaceNameSchema = z5.object({
|
|
15857
|
+
name: z5.string().min(1).max(48)
|
|
15794
15858
|
});
|
|
15795
|
-
var imageMediaTypeSchema =
|
|
15796
|
-
var createPreviewSchema =
|
|
15797
|
-
port:
|
|
15798
|
-
publicUrl:
|
|
15859
|
+
var imageMediaTypeSchema = z5.enum(IMAGE_MEDIA_TYPES);
|
|
15860
|
+
var createPreviewSchema = z5.object({
|
|
15861
|
+
port: z5.number().int().min(1).max(65535),
|
|
15862
|
+
publicUrl: z5.string().min(1)
|
|
15799
15863
|
});
|
|
15800
|
-
var terminalSizeSchema =
|
|
15801
|
-
cols:
|
|
15802
|
-
rows:
|
|
15864
|
+
var terminalSizeSchema = z5.object({
|
|
15865
|
+
cols: z5.number().int().min(2).max(500),
|
|
15866
|
+
rows: z5.number().int().min(1).max(200)
|
|
15803
15867
|
});
|
|
15804
|
-
var writeTerminalSessionSchema =
|
|
15805
|
-
data:
|
|
15806
|
-
generation:
|
|
15807
|
-
sequence:
|
|
15868
|
+
var writeTerminalSessionSchema = z5.object({
|
|
15869
|
+
data: z5.string().max(64 * 1024),
|
|
15870
|
+
generation: z5.number().int().nonnegative(),
|
|
15871
|
+
sequence: z5.number().int().nonnegative()
|
|
15808
15872
|
});
|
|
15809
|
-
var sendMessageSchema =
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15873
|
+
var sendMessageSchema = z5.object({
|
|
15874
|
+
messageId: z5.string().min(1).optional(),
|
|
15875
|
+
submittedAt: z5.string().datetime().optional(),
|
|
15876
|
+
message: z5.string().min(1),
|
|
15877
|
+
model: z5.string().optional(),
|
|
15878
|
+
customInstructions: z5.string().optional(),
|
|
15879
|
+
planMode: z5.boolean().optional(),
|
|
15880
|
+
images: z5.array(z5.object({
|
|
15881
|
+
type: z5.literal("image"),
|
|
15882
|
+
source: z5.union([
|
|
15883
|
+
z5.object({
|
|
15884
|
+
type: z5.literal("base64"),
|
|
15819
15885
|
media_type: imageMediaTypeSchema,
|
|
15820
|
-
data:
|
|
15886
|
+
data: z5.string().min(1)
|
|
15821
15887
|
}),
|
|
15822
|
-
|
|
15823
|
-
type:
|
|
15824
|
-
url:
|
|
15888
|
+
z5.object({
|
|
15889
|
+
type: z5.literal("url"),
|
|
15890
|
+
url: z5.string().url()
|
|
15825
15891
|
})
|
|
15826
15892
|
])
|
|
15827
15893
|
})).optional(),
|
|
15828
|
-
thinkingLevel:
|
|
15829
|
-
goalMode:
|
|
15830
|
-
fastMode:
|
|
15831
|
-
enableInteractiveTools:
|
|
15832
|
-
type:
|
|
15833
|
-
merge:
|
|
15834
|
-
idempotencyKey:
|
|
15835
|
-
senderUserId:
|
|
15836
|
-
senderEmail:
|
|
15837
|
-
senderDisplayName:
|
|
15838
|
-
senderAvatarUrl:
|
|
15839
|
-
errorNotificationTarget:
|
|
15840
|
-
|
|
15841
|
-
|
|
15842
|
-
|
|
15843
|
-
type:
|
|
15844
|
-
provider:
|
|
15845
|
-
resource:
|
|
15846
|
-
repositoryId:
|
|
15847
|
-
resourceNumber:
|
|
15894
|
+
thinkingLevel: z5.enum(VALID_THINKING_LEVELS).optional(),
|
|
15895
|
+
goalMode: z5.boolean().optional(),
|
|
15896
|
+
fastMode: z5.boolean().optional(),
|
|
15897
|
+
enableInteractiveTools: z5.boolean().optional(),
|
|
15898
|
+
type: z5.string().min(1).optional(),
|
|
15899
|
+
merge: z5.boolean().optional(),
|
|
15900
|
+
idempotencyKey: z5.string().min(1).max(128).optional(),
|
|
15901
|
+
senderUserId: z5.string().optional(),
|
|
15902
|
+
senderEmail: z5.string().optional(),
|
|
15903
|
+
senderDisplayName: z5.string().optional(),
|
|
15904
|
+
senderAvatarUrl: z5.string().optional(),
|
|
15905
|
+
errorNotificationTarget: z5.discriminatedUnion("type", [
|
|
15906
|
+
z5.object({ type: z5.literal("slack") }),
|
|
15907
|
+
z5.object({ type: z5.literal("linear"), sessionId: z5.string().min(1) }),
|
|
15908
|
+
z5.object({
|
|
15909
|
+
type: z5.literal("code_host"),
|
|
15910
|
+
provider: z5.enum(["github", "gitlab"]),
|
|
15911
|
+
resource: z5.enum(["issue", "pull_request"]),
|
|
15912
|
+
repositoryId: z5.string().min(1),
|
|
15913
|
+
resourceNumber: z5.number().int().positive()
|
|
15848
15914
|
}),
|
|
15849
|
-
|
|
15915
|
+
z5.object({ type: z5.literal("automation"), executionId: z5.string().min(1) })
|
|
15850
15916
|
]).optional()
|
|
15851
15917
|
});
|
|
15852
|
-
var respondToolInputSchema =
|
|
15853
|
-
requestId:
|
|
15854
|
-
selectionId:
|
|
15918
|
+
var respondToolInputSchema = z5.object({
|
|
15919
|
+
requestId: z5.string().min(1),
|
|
15920
|
+
selectionId: z5.string().min(1)
|
|
15855
15921
|
});
|
|
15856
|
-
var updateGoalSchema =
|
|
15857
|
-
objective:
|
|
15858
|
-
status:
|
|
15922
|
+
var updateGoalSchema = z5.object({
|
|
15923
|
+
objective: z5.string().trim().min(1).max(MAX_CODEX_GOAL_OBJECTIVE_CHARS).optional(),
|
|
15924
|
+
status: z5.enum(["active", "paused"]).optional()
|
|
15859
15925
|
}).refine((body) => body.objective !== void 0 || body.status !== void 0, {
|
|
15860
15926
|
message: "Goal objective or status required"
|
|
15861
15927
|
});
|
|
@@ -15937,7 +16003,7 @@ function createV1Routes(deps) {
|
|
|
15937
16003
|
});
|
|
15938
16004
|
app2.post("/chats", async (c) => {
|
|
15939
16005
|
try {
|
|
15940
|
-
const body =
|
|
16006
|
+
const body = createChatRequestSchema.parse(await c.req.json());
|
|
15941
16007
|
const chat = await deps.chatService.createChat(body);
|
|
15942
16008
|
const response = { chat };
|
|
15943
16009
|
return c.json(response, 201);
|
|
@@ -16046,7 +16112,7 @@ function createV1Routes(deps) {
|
|
|
16046
16112
|
const result = await deps.chatService.updateGoal(c.req.param("chatId"), body);
|
|
16047
16113
|
return c.json(result);
|
|
16048
16114
|
} catch (error) {
|
|
16049
|
-
if (error instanceof
|
|
16115
|
+
if (error instanceof z5.ZodError) {
|
|
16050
16116
|
return c.json(jsonError(error.issues[0]?.message || "Invalid goal update"), 400);
|
|
16051
16117
|
}
|
|
16052
16118
|
if (error instanceof ChatNotFoundError) {
|