replicas-mcp 0.2.20 → 0.2.21
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/index.js +359 -320
- package/package.json +1 -1
- package/src/index.ts +1 -8
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
-
import { z as
|
|
6
|
+
import { z as z9 } from "zod";
|
|
7
7
|
|
|
8
8
|
// ../shared/src/agent.ts
|
|
9
9
|
var AGENT = {
|
|
@@ -19,7 +19,6 @@ var SUBAGENT_MCP_HARNESSES = [AGENT.CLAUDE, AGENT.CODEX];
|
|
|
19
19
|
function isValidAgentProvider(value) {
|
|
20
20
|
return VALID_AGENT_PROVIDERS.some((p) => p === value);
|
|
21
21
|
}
|
|
22
|
-
var LEGACY_RELAY_BASE_PROVIDERS = [AGENT.CLAUDE, AGENT.CODEX, AGENT.OPENCODE, AGENT.PI];
|
|
23
22
|
var VALID_THINKING_LEVELS = ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode"];
|
|
24
23
|
var STANDARD_THINKING_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
25
24
|
var THINKING_LEVELS_BY_AGENT = {
|
|
@@ -30,9 +29,6 @@ var THINKING_LEVELS_BY_AGENT = {
|
|
|
30
29
|
opencode: STANDARD_THINKING_LEVELS,
|
|
31
30
|
pi: STANDARD_THINKING_LEVELS
|
|
32
31
|
};
|
|
33
|
-
function isValidThinkingLevel(value) {
|
|
34
|
-
return VALID_THINKING_LEVELS.some((l) => l === value);
|
|
35
|
-
}
|
|
36
32
|
function getProviderDisplayName(provider, variant = "short") {
|
|
37
33
|
switch (provider) {
|
|
38
34
|
case "codex":
|
|
@@ -99,6 +95,13 @@ var CREDENTIAL_TYPE = {
|
|
|
99
95
|
MUSE_OAUTH: "muse_oauth",
|
|
100
96
|
MUSE_API_KEY: "muse_api_key"
|
|
101
97
|
};
|
|
98
|
+
var ENVIRONMENT_AUTH_REQUIRED_KEYS = {
|
|
99
|
+
[AGENT.CLAUDE]: [
|
|
100
|
+
[CREDENTIAL_METHOD.BEDROCK, ["CLAUDE_CODE_USE_BEDROCK", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]],
|
|
101
|
+
[CREDENTIAL_METHOD.API_KEY, ["ANTHROPIC_API_KEY"]]
|
|
102
|
+
],
|
|
103
|
+
[AGENT.CODEX]: [[CREDENTIAL_METHOD.API_KEY, ["OPENAI_API_KEY"]]]
|
|
104
|
+
};
|
|
102
105
|
var INFERENCE_PROVIDER_LABELS = {
|
|
103
106
|
[CREDENTIAL_METHOD.OLLAMA]: "Ollama",
|
|
104
107
|
[CREDENTIAL_METHOD.OPENCODE_GO]: "OpenCode Go",
|
|
@@ -230,13 +233,17 @@ var ENTERPRISE_PLAN = PLANS.enterprise;
|
|
|
230
233
|
// ../shared/src/analytics/types.ts
|
|
231
234
|
var credentialAccountSchema = z.object({
|
|
232
235
|
ownerName: z.string().optional(),
|
|
233
|
-
email: z.string().optional()
|
|
236
|
+
email: z.string().optional(),
|
|
237
|
+
/** 1-based place in the owner's account pool, set only when the pool holds several accounts. */
|
|
238
|
+
ordinal: z.number().int().positive().optional()
|
|
234
239
|
});
|
|
235
240
|
var agentCredentialSnapshotSchema = z.object({
|
|
236
241
|
method: z.enum(CREDENTIAL_METHOD),
|
|
237
242
|
scope: z.enum(CREDENTIAL_SCOPE),
|
|
238
243
|
revision: z.string().optional(),
|
|
239
|
-
account: credentialAccountSchema.optional()
|
|
244
|
+
account: credentialAccountSchema.optional(),
|
|
245
|
+
/** The `credentials` row, which tells apart accounts pooled under one method and scope. */
|
|
246
|
+
credentialId: z.string().optional()
|
|
240
247
|
});
|
|
241
248
|
|
|
242
249
|
// ../shared/src/event.ts
|
|
@@ -267,6 +274,7 @@ var CODEX_ITEM_EVENT_TYPE = "codex-item";
|
|
|
267
274
|
var CODEX_ITEM_PARTIAL_EVENT_TYPE = "codex-item-partial";
|
|
268
275
|
var CODEX_TURN_EVENT_TYPE = "codex-turn";
|
|
269
276
|
var CODEX_QUOTA_STATUS_EVENT_TYPE = "codex-quota-status";
|
|
277
|
+
var CHAT_INTERRUPTED_EVENT_TYPE = "replicas-interrupted";
|
|
270
278
|
|
|
271
279
|
// ../shared/src/urls.ts
|
|
272
280
|
var DASHBOARD_PATH = "/dashboard";
|
|
@@ -286,6 +294,7 @@ var WEB_APP_PATHS = {
|
|
|
286
294
|
settings: `${DASHBOARD_PATH}/settings`,
|
|
287
295
|
billing: `${DASHBOARD_PATH}/billing`,
|
|
288
296
|
members: `${DASHBOARD_PATH}/members`,
|
|
297
|
+
learnings: `${DASHBOARD_PATH}/learnings`,
|
|
289
298
|
"audit-logs": `${DASHBOARD_PATH}/audit-logs`,
|
|
290
299
|
accountAgents: `${DASHBOARD_PATH}/account/agents`,
|
|
291
300
|
accountProfile: `${DASHBOARD_PATH}/account/profile`,
|
|
@@ -330,14 +339,21 @@ var automationTriggerSchema = z2.discriminatedUnion("type", [
|
|
|
330
339
|
]);
|
|
331
340
|
|
|
332
341
|
// ../shared/src/replicas-mcp.ts
|
|
333
|
-
var REPLICAS_MCP_SERVER_NAME = "replicas-mcp";
|
|
334
342
|
var REPLICAS_MCP_TOOLS = {
|
|
335
343
|
listEnvironments: "list_environments",
|
|
336
344
|
createAutomation: "create_automation",
|
|
337
345
|
spawn: "spawn_workspace",
|
|
338
346
|
relay: "relay_to_workspace",
|
|
339
347
|
linearStart: "start_linear_session",
|
|
340
|
-
linearSessionIntent: "register_linear_session_intent"
|
|
348
|
+
linearSessionIntent: "register_linear_session_intent",
|
|
349
|
+
listChannelSettings: "list_channel_settings",
|
|
350
|
+
saveChannelPreset: "save_channel_preset",
|
|
351
|
+
updateChannelSettings: "update_channel_settings",
|
|
352
|
+
spawnSubagent: "spawn_subagent",
|
|
353
|
+
messageSubagent: "message_subagent",
|
|
354
|
+
listSubagents: "list_subagents",
|
|
355
|
+
readSubagent: "read_subagent",
|
|
356
|
+
archiveSubagent: "archive_subagent"
|
|
341
357
|
};
|
|
342
358
|
function environmentToolSummary({ id, name, description, is_global, repository_id, repository_set_id }) {
|
|
343
359
|
return { id, name, description, is_global, repository_id, repository_set_id };
|
|
@@ -804,10 +820,11 @@ Explore a codebase, get it running in this workspace, verify it end to end, and
|
|
|
804
820
|
Use this when:
|
|
805
821
|
- This workspace was started as an environment setup run (\`replicas environment-setup status\` succeeds)
|
|
806
822
|
- The user asks you to set up, configure, audit, or improve a Replicas environment for a repository
|
|
807
|
-
- The user asks what should go in a start hook, warm hook, or environment system prompt
|
|
823
|
+
- The user asks what should go in a start hook, warm hook, or environment system prompt
|
|
824
|
+
- A warm pool, warm hook, or start hook is failing, or the fix you found belongs in the environment rather than the repository`;
|
|
808
825
|
var REFERENCE3 = `# Environment setup (agent-led)
|
|
809
826
|
|
|
810
|
-
Use this workflow to make a repository fully usable by Replicas background agents: agents booted from the environment should be able to install, run, test, verify, and demo changes without a human babysitting them.
|
|
827
|
+
Use this workflow to make a repository fully usable by Replicas background agents: agents booted from the environment should be able to install, run, test, verify, and demo changes without a human babysitting them. In a setup run, the result is a **proposal**, never a direct change: the user reviews, edits, and saves it in the Environment panel next to the chat. Outside a setup run, see below.
|
|
811
828
|
|
|
812
829
|
## Mental model
|
|
813
830
|
|
|
@@ -839,7 +856,14 @@ replicas environment-setup wait-variables [-t 5m]
|
|
|
839
856
|
|
|
840
857
|
\`status\` prints the environment, repositories, current steps, and variable requests. \`request-variables\` returns immediately; \`wait-variables\` blocks until the required values arrive, are skipped, or the time runs out. Step statuses are \`pending\`, \`in_progress\`, \`completed\`, and \`skipped\`. Step keys, in order: \`understand\`, \`install\`, \`verify\`, \`configure\`, \`propose\`. Mark the first step \`in_progress\` before your first tool call, keep exactly one step \`in_progress\`, and mark a step \`completed\` only after its work actually succeeded. Use \`skipped\` when something genuinely cannot run (for example no browser UI to record) and say so in the proposal.
|
|
841
858
|
|
|
842
|
-
If \`replicas environment-setup status\` reports that there is no active setup run, the user asked for this in
|
|
859
|
+
If \`replicas environment-setup status\` reports that there is no active setup run, you are in an ordinary workspace, either because the user asked for this or because the fix you found while debugging belongs in the environment. Follow the same discovery and verification steps, show the exact change in chat, and offer to apply and test it yourself. Ask the user before changing the environment, since it affects every workspace built from it. Once they approve:
|
|
860
|
+
|
|
861
|
+
- Warm hook: \`replicas environment warm-hooks save-test <env> -f <file>\` runs it in an isolated sandbox and saves it only if it passes.
|
|
862
|
+
- Start hook: \`replicas environment start-hooks test <env> -f <file>\`, then \`replicas environment start-hooks save <env> -f <file>\` with the same file once it passes.
|
|
863
|
+
- Variables and files: apply with \`replicas environment vars set\` or \`files set\`, then confirm with \`vars list\` or \`files list\`.
|
|
864
|
+
- Automations: apply with \`replicas automation ...\`, then read back with \`replicas automation get <id>\`.
|
|
865
|
+
|
|
866
|
+
When a test fails, fix the earliest failure and test again instead of saving. If the fix materially changes what the user approved, show the revised change and ask again before saving. Report what you changed and the test result.
|
|
843
867
|
|
|
844
868
|
## 1. Understand the codebase
|
|
845
869
|
|
|
@@ -913,7 +937,7 @@ replicas computer record stop
|
|
|
913
937
|
replicas media upload /tmp/walkthrough.mp4 --name "<Project> walkthrough"
|
|
914
938
|
\`\`\`
|
|
915
939
|
|
|
916
|
-
Keep the recording short (one to three minutes) and focused on the flow that proves the environment works. \`replicas media upload\` prints a chat embed line and a \`View in Replicas\` link ending in \`?media=<media-id>\`; keep both. The media id goes into the proposal, and the embed line goes into your final message. Follow \`MEDIA.md\` for anything shared outside the dashboard.
|
|
940
|
+
Keep the recording short (one to three minutes) and focused on the flow that proves the environment works. \`replicas media upload\` prints a chat embed line and a \`View in Replicas\` link ending in \`?mode=media&media=<media-id>\`; keep both. The media id goes into the proposal, and the embed line goes into your final message. Follow \`MEDIA.md\` for anything shared outside the dashboard.
|
|
917
941
|
|
|
918
942
|
Add screenshots of important states (a passing test run, the running app) with \`replicas computer screenshot\` and upload them the same way when they help the user trust the result.
|
|
919
943
|
|
|
@@ -1031,7 +1055,7 @@ After \`propose\` succeeds, mark the \`propose\` step completed and send one mes
|
|
|
1031
1055
|
Review the start hook, warm hook, system prompt, variables, and automations in the Environment panel on the right. Edit anything inline, then select **Save configuration**. Ask me here if you want changes and I will revise the proposal.
|
|
1032
1056
|
\`\`\`
|
|
1033
1057
|
|
|
1034
|
-
Keep it under 250 words plus the lists. Do not paste the hooks or system prompt into chat; the panel shows them. Never imply the configuration was saved: saving is the user's action.
|
|
1058
|
+
Keep it under 250 words plus the lists. Do not paste the hooks or system prompt into chat; the panel shows them. Never imply the configuration was saved: in a setup run, saving is the user's action.
|
|
1035
1059
|
|
|
1036
1060
|
## Safety
|
|
1037
1061
|
|
|
@@ -1043,7 +1067,7 @@ Keep it under 250 words plus the lists. Do not paste the hooks or system prompt
|
|
|
1043
1067
|
var ENVIRONMENT_SETUP_ABILITY = {
|
|
1044
1068
|
label: "Environment setup",
|
|
1045
1069
|
description: "Explore a codebase, verify it runs, and propose environment hooks, a system prompt, variables, and automations for review.",
|
|
1046
|
-
bullet: "- Setting up, auditing, or improving a Replicas environment for a repository (hooks, system prompt, variables, automations)",
|
|
1070
|
+
bullet: "- Setting up, auditing, fixing, or improving a Replicas environment for a repository (hooks, system prompt, variables, automations), including a failing warm pool or hook",
|
|
1047
1071
|
section: SECTION3,
|
|
1048
1072
|
referenceFile: { name: "ENVIRONMENT-SETUP.md", content: REFERENCE3 }
|
|
1049
1073
|
};
|
|
@@ -1287,7 +1311,9 @@ if (result.errors?.length) throw new Error(JSON.stringify(result.errors));
|
|
|
1287
1311
|
|
|
1288
1312
|
The gateway refreshes expired credentials and retries authentication failures once. Check the response's \`errors\` field before using \`data\`.
|
|
1289
1313
|
|
|
1290
|
-
|
|
1314
|
+
Initiatives need the \`initiative:read\` scope, which organizations connected before it was requested do not have. If Linear answers \`Invalid scope\`, ask an admin to reconnect Linear under Organization \u2192 Integrations; retrying will not help.
|
|
1315
|
+
|
|
1316
|
+
Personal \u2192 Connections links a person's Linear identity for agent defaults and attribution. Its disconnected state does not mean the organization's Linear integration is disconnected, and connecting it does not refresh the organization's token. Only recommend reconnecting under Organization \u2192 Integrations when the gateway reports missing credentials or an unrecoverable OAuth failure, or when Linear answers \`Invalid scope\`. Report transient failures without asking the user to disconnect.
|
|
1291
1317
|
|
|
1292
1318
|
## Create a ticket
|
|
1293
1319
|
|
|
@@ -1437,7 +1463,7 @@ For each media file, the CLI prints an embed line and a dashboard link:
|
|
|
1437
1463
|
|
|
1438
1464
|
1. Images always print \`\`. This public, stable link works in Replicas chat, GitHub, and anywhere else Markdown images render. No flag is needed.
|
|
1439
1465
|
2. Video and audio print \`Replicas chat embed: \` by default; this authenticated URL renders inline in Replicas chat **only** \u2014 see below. \`--access public\` prints a public embed instead.
|
|
1440
|
-
3. \`View in Replicas: <deep-link>\` is a per-file dashboard URL of the form \`https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>\` that opens directly to that specific file.
|
|
1466
|
+
3. \`View in Replicas: <deep-link>\` is a per-file dashboard URL of the form \`https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>\` that opens directly to that specific file.
|
|
1441
1467
|
|
|
1442
1468
|
Match each "View in Replicas" line to the embed line directly above it \u2014 that's the deep link for that file.
|
|
1443
1469
|
|
|
@@ -1468,7 +1494,7 @@ Permanently delete an upload with \`replicas media delete <media-id>\`. The back
|
|
|
1468
1494
|
| \`https://api.replicas.dev/v1/media/<id>\` (inside \`\`) | Authenticated API redirect printed for private video, audio, and HTML \u2014 requires the Replicas chat session | **Only** in the Replicas chat reply. Nowhere else. |
|
|
1469
1495
|
| \`https://replicas.dev/organizations/<organization-id>/media/<media-id>\` | Organization-only page printed by \`--access organization\` | Pull requests and other places where every viewer belongs to the Replicas organization. |
|
|
1470
1496
|
| \`https://api.replicas.dev/v1/media/public/<id>/<token>\` | Public bearer URL printed for every image, and for video or audio with \`--access public\` | The Replicas chat reply and GitHub embeds. |
|
|
1471
|
-
| \`https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>\` | Authenticated dashboard deep link that opens the media file in the workspace | Everywhere external: Slack, GitHub, GitLab, Linear, PR bodies, comments, emails. |
|
|
1497
|
+
| \`https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>\` | Authenticated dashboard deep link that opens the media file in the workspace | Everywhere external: Slack, GitHub, GitLab, Linear, PR bodies, comments, emails. |
|
|
1472
1498
|
|
|
1473
1499
|
### NEVER link the API redirect URL outside the Replicas chat reply
|
|
1474
1500
|
|
|
@@ -1487,10 +1513,10 @@ This rule has no exceptions:
|
|
|
1487
1513
|
For an organization-only HTML page, use the \`Forge link\` printed by \`--access organization\`. For other authenticated media references, use the dashboard form:
|
|
1488
1514
|
|
|
1489
1515
|
\`\`\`
|
|
1490
|
-
https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>
|
|
1516
|
+
https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>
|
|
1491
1517
|
\`\`\`
|
|
1492
1518
|
|
|
1493
|
-
The \`media=<media-id>\` query
|
|
1519
|
+
The \`mode=media&media=<media-id>\` query params open that specific file in the workspace.
|
|
1494
1520
|
|
|
1495
1521
|
When you have a specific file in mind, never link the bare workspace URL without the \`media=<id>\` param.
|
|
1496
1522
|
|
|
@@ -1500,6 +1526,8 @@ Always render as a markdown / mrkdwn hyperlink labeled **View in Replicas** \u20
|
|
|
1500
1526
|
|
|
1501
1527
|
Include each markdown embed line **verbatim** where you want that file to render inline. The chat substitutes each one with an embedded image, video, or audio player. For HTML, use the printed \`HTML page\` link. Multiple embeds can appear in a single reply.
|
|
1502
1528
|
|
|
1529
|
+
Never reply with only dashboard links (for example a "Links:" list of \`?mode=media&media=\` URLs) in place of the embeds: a dashboard link renders as plain text, so the user sees nothing inline. This applies even when the task came from Slack, Linear, GitHub, or GitLab; the chat reply still gets the embeds.
|
|
1530
|
+
|
|
1503
1531
|
After (or alongside) the embeds, include a \`[View in Canvas](<deep-link>)\` hyperlink for each file using the per-file dashboard URL printed by the CLI as **View in Replicas**. Keep that URL unchanged so it opens the specific media item in the workspace's Canvas. External messages still label this dashboard link **View in Replicas**.
|
|
1504
1532
|
|
|
1505
1533
|
## On external platforms: embed the file AND link the dashboard
|
|
@@ -1507,7 +1535,7 @@ After (or alongside) the embeds, include a \`[View in Canvas](<deep-link>)\` hyp
|
|
|
1507
1535
|
After \`replicas media upload\` succeeds, external delivery has two required follow-up steps for every file:
|
|
1508
1536
|
|
|
1509
1537
|
1. **Use the destination's inline representation:** upload the raw bytes to Slack, Linear, or GitLab; embed the image's printed public link on GitHub.
|
|
1510
|
-
2. **Link the Replicas dashboard deep link** (\`?media=<id>\` form) so the user can jump straight to the file in the workspace.
|
|
1538
|
+
2. **Link the Replicas dashboard deep link** (\`?mode=media&media=<id>\` form) so the user can jump straight to the file in the workspace.
|
|
1511
1539
|
|
|
1512
1540
|
A dashboard link alone is not enough. An embed without the dashboard link is not enough. Do both.
|
|
1513
1541
|
|
|
@@ -1536,7 +1564,7 @@ await replicas.slack.call('files.completeUploadExternal', {
|
|
|
1536
1564
|
files: [{ id: reservation.file_id, title: 'Screenshot' }],
|
|
1537
1565
|
channel_id: 'CHANNEL_ID',
|
|
1538
1566
|
thread_ts: 'THREAD_TS',
|
|
1539
|
-
initial_comment: '<https://app.replicas.dev/workspaces/<workspace-id>?media=<media-id>|View in Replicas>',
|
|
1567
|
+
initial_comment: '<https://app.replicas.dev/workspaces/<workspace-id>?mode=media&media=<media-id>|View in Replicas>',
|
|
1540
1568
|
});
|
|
1541
1569
|
\`\`\`
|
|
1542
1570
|
|
|
@@ -1559,7 +1587,7 @@ Use \`jq\` to build the JSON bodies \u2014 the GraphQL variables (\`size\`, \`fi
|
|
|
1559
1587
|
FILE=/abs/path/to/screenshot.png
|
|
1560
1588
|
FILENAME=$(basename "$FILE")
|
|
1561
1589
|
SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
|
|
1562
|
-
CONTENT_TYPE=image/png
|
|
1590
|
+
CONTENT_TYPE=image/png # the file's real MIME type, e.g. video/mp4 for a recording
|
|
1563
1591
|
ISSUE_UUID=... # the Linear issue's UUID
|
|
1564
1592
|
MEDIA_ID=... # the media ID printed by \`replicas media upload\`
|
|
1565
1593
|
|
|
@@ -1596,7 +1624,7 @@ curl -s -X PUT "$UPLOAD_URL" \\
|
|
|
1596
1624
|
--data-binary @"$FILE"
|
|
1597
1625
|
|
|
1598
1626
|
# 3. Reference assetUrl inline in the comment body, alongside the dashboard link.
|
|
1599
|
-
BODY=$(printf '\\n\\n[View in Replicas](https://app.replicas.dev/workspaces/%s?media=%s)' \\
|
|
1627
|
+
BODY=$(printf '\\n\\n[View in Replicas](https://app.replicas.dev/workspaces/%s?mode=media&media=%s)' \\
|
|
1600
1628
|
"$ASSET_URL" "$REPLICAS_WORKSPACE_ID" "$MEDIA_ID")
|
|
1601
1629
|
|
|
1602
1630
|
jq -n \\
|
|
@@ -1608,6 +1636,8 @@ jq -n \\
|
|
|
1608
1636
|
}' | linear_graphql
|
|
1609
1637
|
\`\`\`
|
|
1610
1638
|
|
|
1639
|
+
For a recording, upload the MP4 with its own MIME type, then upload a poster frame (\`ffmpeg -i /tmp/demo.mp4 -frames:v 1 /tmp/demo-poster.png\`) the same way as \`image/png\` and link it: \`[](<recording-asset-url>)\`.
|
|
1640
|
+
|
|
1611
1641
|
The same flow works for issue bodies (use \`issueCreate\` / \`issueUpdate\` with the same markdown body).
|
|
1612
1642
|
|
|
1613
1643
|
Never paste the \`api.replicas.dev/v1/media/<id>\` URL into a Linear body or comment \u2014 it will render as a broken image to anyone outside your Replicas chat.
|
|
@@ -1647,7 +1677,7 @@ Do **not** commit screenshots to the repo, use placeholder URLs, expose the auth
|
|
|
1647
1677
|
|
|
1648
1678
|
GitLab supports native project Markdown uploads. For a GitLab destination, always upload the media to Replicas first, then POST the same original file to the repository's \`/projects/:id/uploads\` API using the workspace GitLab credential. Insert the returned \`markdown\` value into the merge request body or comment and include the Replicas dashboard link. Image uploads render inline; MP4, MOV, and WebM uploads render as inline video players.
|
|
1649
1679
|
|
|
1650
|
-
Do not use a Replicas public link for GitLab when the native project upload succeeds; native uploads preserve project access controls.
|
|
1680
|
+
Do not use a Replicas public link for GitLab when the native project upload succeeds; native uploads preserve project access controls. \`replicas.gitlab.request\` only sends JSON and cannot POST multipart file bytes, so without another supported upload path use the GitHub flow above instead: the image's printed public embed, and a poster linked to the recording's **View in Replicas** URL.
|
|
1651
1681
|
|
|
1652
1682
|
## Recording defaults
|
|
1653
1683
|
|
|
@@ -1695,7 +1725,7 @@ replicas media upload chart-a.svg chart-b.svg --name "Latency chart" --name "Err
|
|
|
1695
1725
|
var MEDIA_ABILITY = {
|
|
1696
1726
|
label: "Media",
|
|
1697
1727
|
description: "Deliver media to Replicas and destination workflows with inline uploads.",
|
|
1698
|
-
bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips, or HTML recap pages \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms",
|
|
1728
|
+
bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips, or HTML recap pages \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms. Paste the printed `` embeds in your chat reply, never only dashboard links, and upload the file itself to Slack, Linear, or GitLab",
|
|
1699
1729
|
section: SECTION7,
|
|
1700
1730
|
referenceFile: { name: "MEDIA.md", content: REFERENCE7 }
|
|
1701
1731
|
};
|
|
@@ -1802,6 +1832,7 @@ Use this when:
|
|
|
1802
1832
|
- The user asks to create or control an E2B sandbox
|
|
1803
1833
|
- The user asks to invoke a connected Modal function
|
|
1804
1834
|
- The user asks to access Vercel projects, deployments, domains, logs, or infrastructure
|
|
1835
|
+
- The user asks to read or update Lightfield CRM accounts, contacts, opportunities, meetings, notes, or tasks
|
|
1805
1836
|
- The user asks to search or read Greptile's codebase knowledge bases
|
|
1806
1837
|
- The user asks to inspect Vanta controls, tests, evidence, vendors, risks, or compliance data
|
|
1807
1838
|
- The user asks to query or update a connected turbopuffer namespace
|
|
@@ -1913,6 +1944,18 @@ const deployments = await replicas.vercel.request('/v6/deployments?teamId=team_1
|
|
|
1913
1944
|
|
|
1914
1945
|
Confirm mutations before using POST, PUT, PATCH, or DELETE.
|
|
1915
1946
|
|
|
1947
|
+
## Lightfield
|
|
1948
|
+
|
|
1949
|
+
Lightfield is a native API-key integration. Pass a path relative to the Lightfield \`/v1\` API; Replicas sends the key and \`Lightfield-Version\` header server-side:
|
|
1950
|
+
|
|
1951
|
+
\`\`\`ts
|
|
1952
|
+
const accounts = await replicas.lightfield.request('/accounts?limit=25');
|
|
1953
|
+
const fields = await replicas.lightfield.request('/accounts/definitions');
|
|
1954
|
+
const note = await replicas.lightfield.request('/notes', { method: 'POST', body: { fields: { $title: 'Call recap' } } });
|
|
1955
|
+
\`\`\`
|
|
1956
|
+
|
|
1957
|
+
See https://docs.lightfield.app/llms.txt for endpoints. Paginate with \`limit\` and \`offset\`. The key's scopes control permitted operations. Confirm mutations before using POST, PUT, PATCH, or DELETE.
|
|
1958
|
+
|
|
1916
1959
|
## Vanta
|
|
1917
1960
|
|
|
1918
1961
|
Vanta is a native Manage API integration. Pass a relative path beginning with /v1/; Replicas exchanges the stored client credentials and caches the short-lived token server-side:
|
|
@@ -1990,6 +2033,7 @@ Take action *with* Replicas itself \u2014 manage automations, environments (vari
|
|
|
1990
2033
|
|
|
1991
2034
|
Use this when:
|
|
1992
2035
|
- The user asks you to create, edit, run, or delete an automation
|
|
2036
|
+
- The user asks you to come back to something later ("check back on this in a week", "remind me tomorrow", "tell me when CI is green") \u2014 schedule a follow-up (see *Follow-ups and reminders*)
|
|
1993
2037
|
- The user asks you to manage environments, environment variables, or environment files
|
|
1994
2038
|
- The user asks "what envs / repos / automations do I have?"
|
|
1995
2039
|
- The user asks you to scaffold a \`replicas.json\` / \`replicas.yaml\` in a repo
|
|
@@ -2036,6 +2080,7 @@ In agent mode the CLI hides commands that don't make sense for in-workspace agen
|
|
|
2036
2080
|
| \`replicas preview ...\` | Register / list preview URLs (covered in \`PREVIEWS.md\`) |
|
|
2037
2081
|
| \`replicas service ...\` | Run long-lived services detached so they survive workspace sleep/wake (see below) |
|
|
2038
2082
|
| \`replicas media ...\` | Upload, list, share, revoke, or delete workspace media; follow \`MEDIA.md\` for destination embedding |
|
|
2083
|
+
| \`replicas skills suggest <SKILL.md> --title <text>\` | Suggest saving a lasting user instruction as a learning (an organization skill); the user accepts or dismisses it |
|
|
2039
2084
|
| \`replicas slack thread ...\` | Attach or switch Slack thread routing (covered in \`SLACK.md\`) |
|
|
2040
2085
|
|
|
2041
2086
|
\`replicas <command> --help\` is always the source of truth for flags.
|
|
@@ -2050,6 +2095,7 @@ In agent mode the CLI hides commands that don't make sense for in-workspace agen
|
|
|
2050
2095
|
| "Create a new env for my \`acme/web\` repo" | \`replicas environment create <name> -r acme/web\` |
|
|
2051
2096
|
| "What automations do I have?" | \`replicas automation list\` |
|
|
2052
2097
|
| "Run my nightly automation now" | \`replicas automation run <id>\` |
|
|
2098
|
+
| "Check back on this in a week" | \`replicas automation create ... --in 1w --background --personal\` |
|
|
2053
2099
|
| "Make an automation that runs every weekday at 9am" | \`replicas automation create\` (interactive) or \`--trigger-cron "0 9 * * 1-5"\` |
|
|
2054
2100
|
| "Make an automation that runs when a PR opens on \`acme/web\`" | \`replicas automation create ... --trigger-github pull_request.opened --trigger-github-repos acme/web\` |
|
|
2055
2101
|
| "Make an automation that runs when an MR opens on \`acme/web\`" | \`replicas automation create ... --trigger-gitlab merge_request.opened --trigger-gitlab-repos acme/web\` |
|
|
@@ -2161,6 +2207,26 @@ replicas automation create ... --lifecycle default --auto-stop-minutes 30
|
|
|
2161
2207
|
|
|
2162
2208
|
When the user says "make me an automation that...", default to **picking the environment for them by listing the available envs** and asking only when the user hasn't already pinned one. Same for repos in GitHub triggers. Don't pepper the user with questions you can answer by reading the existing config.
|
|
2163
2209
|
|
|
2210
|
+
### Follow-ups and reminders
|
|
2211
|
+
|
|
2212
|
+
You cannot wait days yourself. When the user asks you to come back to something later, schedule a one-time automation that delivers a prompt back into **this workspace's conversation** at that time, then deletes itself:
|
|
2213
|
+
|
|
2214
|
+
\`\`\`bash
|
|
2215
|
+
replicas automation create "Re-check PR #142 CI" \\
|
|
2216
|
+
--in 1w \\
|
|
2217
|
+
--background --personal \\
|
|
2218
|
+
--prompt "A week ago the user asked me to re-check CI on https://github.com/acme/web/pull/142 (flaky e2e job 'checkout'). Check the latest run, fix it if it is still failing, and summarize the result for the user."
|
|
2219
|
+
\`\`\`
|
|
2220
|
+
|
|
2221
|
+
- \`--in <duration>\` (\`30m\`, \`2h\`, \`3d\`, \`1w\`, \`1d12h\`) or \`--at <ISO-8601 with offset>\` (e.g. "tomorrow at 9am" \u2192 \`--at 2026-10-08T09:00:00-07:00\`, using the user's timezone if you know it; otherwise say which timezone you assumed).
|
|
2222
|
+
- Inside a workspace, one-time follow-ups default to \`--workspace current\`, so you resume with this conversation's context. Inside a workspace, \`--environment\` defaults to this workspace's environment (same repositories), including for \`--workspace new\` and \`reuse\`.
|
|
2223
|
+
- Write \`--prompt\` as instructions to your future self: the links, what to check, what "done" looks like, and how to report back (e.g. reply in the original Slack thread). It runs with no memory of why it was scheduled beyond what you write.
|
|
2224
|
+
- \`--background\` keeps follow-ups out of the user's main automations list (they are still visible under **Background**). Use it for every one-time follow-up that reports back into this conversation, even one that leads to a big decision. Omit it only for recurring automations the user wants to see and manage, such as ongoing monitoring.
|
|
2225
|
+
- \`--personal\` makes the automation the user's own. Omit it only when the follow-up belongs to the organization.
|
|
2226
|
+
- Recurring with an end: \`--trigger-cron "0 9 * * *" --max-runs 5 --workspace current\` runs daily five times, then deletes itself. \`--workspace reuse\` creates one new workspace on the first run and sends every later run to it; \`--workspace new\` (the default for non-one-time automations) creates a fresh workspace per run.
|
|
2227
|
+
- Only schedule when the user asked for a follow-up or clearly agreed to one; not for "maybe I'll look at this later".
|
|
2228
|
+
- Confirm using the **Next Run** time the CLI prints, not your own arithmetic. Cancel with \`replicas automation delete <id> --force\`; find them with \`replicas automation list --background true\`.
|
|
2229
|
+
|
|
2164
2230
|
### Edit
|
|
2165
2231
|
|
|
2166
2232
|
\`\`\`bash
|
|
@@ -2262,9 +2328,6 @@ var SENTRY_ABILITY = {
|
|
|
2262
2328
|
referenceFile: { name: "SENTRY.md", content: REFERENCE11 }
|
|
2263
2329
|
};
|
|
2264
2330
|
|
|
2265
|
-
// ../shared/src/memory.ts
|
|
2266
|
-
import { z as z5 } from "zod";
|
|
2267
|
-
|
|
2268
2331
|
// ../shared/src/sandbox.ts
|
|
2269
2332
|
var SANDBOX_LIFECYCLE = {
|
|
2270
2333
|
AUTO_STOP_MINUTES: 60,
|
|
@@ -2285,11 +2348,6 @@ var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZ
|
|
|
2285
2348
|
// ../shared/src/memory.ts
|
|
2286
2349
|
var HISTORY_ROOT = `${SANDBOX_PATHS.REPLICAS_DIR}/history`;
|
|
2287
2350
|
var HISTORY_INDEX_FILENAME = "INDEX.md";
|
|
2288
|
-
var memoryExtractionResultSchema = z5.object({
|
|
2289
|
-
summary: z5.string().nullable(),
|
|
2290
|
-
indexEntry: z5.string().nullable()
|
|
2291
|
-
});
|
|
2292
|
-
var { $schema: _, ...MEMORY_EXTRACTION_SCHEMA } = z5.toJSONSchema(memoryExtractionResultSchema);
|
|
2293
2351
|
|
|
2294
2352
|
// ../shared/src/default-skills/replicas-agent/abilities/session-history.ts
|
|
2295
2353
|
var SECTION12 = `### Session history
|
|
@@ -2300,20 +2358,20 @@ var REFERENCE12 = `# Session history
|
|
|
2300
2358
|
|
|
2301
2359
|
Past sessions are installed under \`${HISTORY_ROOT}\`:
|
|
2302
2360
|
|
|
2303
|
-
- \`${HISTORY_INDEX_FILENAME}\` lists every session, grouped under \`## YYYY-MM-DD\` headings by start day (UTC). Each line is \`- <date> <time> | <who> | <workspace> | <description> | active: <days> | <
|
|
2304
|
-
- \`
|
|
2361
|
+
- \`${HISTORY_INDEX_FILENAME}\` lists every session, grouped under \`## YYYY-MM-DD\` headings by start day (UTC). Each line is \`- <date> <time> | <who> | <workspace> | <description>; <PRs with current state> | active: <days> | <condensed file>\`; \`active:\` appears only for sessions spanning several days.
|
|
2362
|
+
- \`condensed/<YYYY-MM-DD>-<id>.md\` holds the condensed transcript of a session you can read: the user's messages, the agent's replies (the final one in full), commands with their last output lines, errors, links, small diffs, and the files touched. Teammates' private sessions show "Private session" and \`\u2014\` instead of a file.
|
|
2305
2363
|
|
|
2306
|
-
Search the index, then open the
|
|
2364
|
+
Search the index, then open or search the condensed transcripts:
|
|
2307
2365
|
|
|
2308
2366
|
\`\`\`bash
|
|
2309
2367
|
cd ${HISTORY_ROOT}
|
|
2310
2368
|
rg '^- 2026-09-30' ${HISTORY_INDEX_FILENAME} # sessions that started that day
|
|
2311
2369
|
rg 2026-09-30 ${HISTORY_INDEX_FILENAME} # also sessions active that day
|
|
2312
2370
|
rg -i 'launch|video' ${HISTORY_INDEX_FILENAME} # by topic, person, or workspace
|
|
2313
|
-
rg -il 'launch|video'
|
|
2371
|
+
rg -il 'launch|video' condensed/ # full-text search of condensed transcripts
|
|
2314
2372
|
\`\`\`
|
|
2315
2373
|
|
|
2316
|
-
When a
|
|
2374
|
+
Condensed transcripts drop most tool output. When you need an exact value, id, number, error, or a command's full output, fetch the full transcript of any session you can read. It is saved as JSONL, one JSON string per message or tool call:
|
|
2317
2375
|
|
|
2318
2376
|
\`\`\`bash
|
|
2319
2377
|
replicas history transcript 2026-09-30-<id>
|
|
@@ -2479,7 +2537,6 @@ var DEFAULT_USER_PREFERENCES = {
|
|
|
2479
2537
|
auto_draft_prs: false,
|
|
2480
2538
|
open_prs_in_graphite: false,
|
|
2481
2539
|
open_links_in_desktop_app: false,
|
|
2482
|
-
mothership_in_dms: false,
|
|
2483
2540
|
memory_enabled: null,
|
|
2484
2541
|
subagent_mcp_enabled: null,
|
|
2485
2542
|
default_fast_mode: false,
|
|
@@ -2504,15 +2561,6 @@ var DEFAULT_DEFAULT_SKILLS = {
|
|
|
2504
2561
|
}
|
|
2505
2562
|
};
|
|
2506
2563
|
|
|
2507
|
-
// ../shared/src/prompts.ts
|
|
2508
|
-
var mothershipMcpActions = `These are tools of the \`${REPLICAS_MCP_SERVER_NAME}\` MCP server; their argument names match the envelope fields. Call them directly as tools, never through a shell or the Replicas CLI.
|
|
2509
|
-
- **Spawn** a dedicated workspace for the thread and hand off: \`${REPLICAS_MCP_TOOLS.spawn}\`, with \`environment_id\` when you chose one.
|
|
2510
|
-
- **Relay** a follow-up that is clearly meant for you into the workspace already bound to the thread (pass the envelope's \`user_id\` so it's attributed to its author): \`${REPLICAS_MCP_TOOLS.relay}\`, with \`queue: true\` to queue it.
|
|
2511
|
-
- **List environments**: \`${REPLICAS_MCP_TOOLS.listEnvironments}\`.
|
|
2512
|
-
- **Create an automation**: \`${REPLICAS_MCP_TOOLS.createAutomation}\`, filling its \`confirmation_*\` arguments from the accepting message's envelope.
|
|
2513
|
-
- **Register a Linear session intent**: \`${REPLICAS_MCP_TOOLS.linearSessionIntent}\` with \`comment_id\` and \`action\`.
|
|
2514
|
-
- **Start a Linear session**: \`${REPLICAS_MCP_TOOLS.linearStart}\` with \`issue_id\`, \`agent_session_id\`, and \`prompt\`.`;
|
|
2515
|
-
|
|
2516
2564
|
// ../shared/src/display-message/types.ts
|
|
2517
2565
|
var BACKGROUND_TASK_SUBTYPES = /* @__PURE__ */ new Set([
|
|
2518
2566
|
"task_started",
|
|
@@ -2596,6 +2644,8 @@ function normalizeBackgroundTaskStatus(status) {
|
|
|
2596
2644
|
|
|
2597
2645
|
// ../shared/src/display-message/constants.ts
|
|
2598
2646
|
var USER_MESSAGE_MATCH_GRACE_PERIOD_MS = 3e4;
|
|
2647
|
+
var COMPACTION_CONTENT = "Context compacted";
|
|
2648
|
+
var GOAL_TOOL_NAME = "goal";
|
|
2599
2649
|
|
|
2600
2650
|
// ../shared/src/shell-commands.ts
|
|
2601
2651
|
var SHELL_OPAQUE = "\0";
|
|
@@ -3057,6 +3107,15 @@ function skillNamesFromCommand(command) {
|
|
|
3057
3107
|
})));
|
|
3058
3108
|
}
|
|
3059
3109
|
|
|
3110
|
+
// ../shared/src/user-message-matching.ts
|
|
3111
|
+
function parseTimestampMs(timestamp) {
|
|
3112
|
+
const value = typeof timestamp === "number" ? timestamp : Date.parse(timestamp);
|
|
3113
|
+
return Number.isFinite(value) ? value : 0;
|
|
3114
|
+
}
|
|
3115
|
+
function areUserMessagesWithinMatchWindow(a, b) {
|
|
3116
|
+
return a.content === b.content && Math.abs(parseTimestampMs(a.timestamp) - parseTimestampMs(b.timestamp)) <= USER_MESSAGE_MATCH_GRACE_PERIOD_MS;
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3060
3119
|
// ../shared/src/display-message/task-accumulator.ts
|
|
3061
3120
|
function mapTaskStatus(status) {
|
|
3062
3121
|
if (status === "in_progress" || status === "completed") return status;
|
|
@@ -3184,15 +3243,6 @@ var TaskAccumulator = class {
|
|
|
3184
3243
|
}
|
|
3185
3244
|
};
|
|
3186
3245
|
|
|
3187
|
-
// ../shared/src/user-message-matching.ts
|
|
3188
|
-
function parseTimestampMs(timestamp) {
|
|
3189
|
-
const value = typeof timestamp === "number" ? timestamp : Date.parse(timestamp);
|
|
3190
|
-
return Number.isFinite(value) ? value : 0;
|
|
3191
|
-
}
|
|
3192
|
-
function areUserMessagesWithinMatchWindow(a, b) {
|
|
3193
|
-
return a.content === b.content && Math.abs(parseTimestampMs(a.timestamp) - parseTimestampMs(b.timestamp)) <= USER_MESSAGE_MATCH_GRACE_PERIOD_MS;
|
|
3194
|
-
}
|
|
3195
|
-
|
|
3196
3246
|
// ../shared/src/agent-event-utils.ts
|
|
3197
3247
|
function getUserMessage(event) {
|
|
3198
3248
|
return event.type === "event_msg" && event.payload.type === "user_message" && typeof event.payload.message === "string" ? event.payload.message : null;
|
|
@@ -3232,20 +3282,20 @@ var ASTER_MODEL_LABELS = {
|
|
|
3232
3282
|
};
|
|
3233
3283
|
|
|
3234
3284
|
// ../shared/src/models-dev.ts
|
|
3235
|
-
import { z as
|
|
3285
|
+
import { z as z5 } from "zod";
|
|
3236
3286
|
var MODELS_DEV_CACHE_MS = 5 * 6e4;
|
|
3237
|
-
var modelsDevCatalogSchema =
|
|
3238
|
-
models:
|
|
3239
|
-
id:
|
|
3240
|
-
name:
|
|
3241
|
-
description:
|
|
3242
|
-
status:
|
|
3243
|
-
provider:
|
|
3244
|
-
cost:
|
|
3245
|
-
input:
|
|
3246
|
-
output:
|
|
3247
|
-
cache_read:
|
|
3248
|
-
cache_write:
|
|
3287
|
+
var modelsDevCatalogSchema = z5.record(z5.string(), z5.object({
|
|
3288
|
+
models: z5.record(z5.string(), z5.object({
|
|
3289
|
+
id: z5.string().optional(),
|
|
3290
|
+
name: z5.string(),
|
|
3291
|
+
description: z5.string().optional(),
|
|
3292
|
+
status: z5.enum(["alpha", "beta", "deprecated"]).optional(),
|
|
3293
|
+
provider: z5.object({ npm: z5.string().optional() }).optional(),
|
|
3294
|
+
cost: z5.object({
|
|
3295
|
+
input: z5.number().finite().nonnegative().optional(),
|
|
3296
|
+
output: z5.number().finite().nonnegative().optional(),
|
|
3297
|
+
cache_read: z5.number().finite().nonnegative().optional(),
|
|
3298
|
+
cache_write: z5.number().finite().nonnegative().optional()
|
|
3249
3299
|
}).optional()
|
|
3250
3300
|
}))
|
|
3251
3301
|
}));
|
|
@@ -3260,6 +3310,7 @@ var CLAUDE_OPUS_5_MODEL = "claude-opus-5";
|
|
|
3260
3310
|
var CLAUDE_OPUS_4_8_MODEL = "claude-opus-4-8";
|
|
3261
3311
|
var CLAUDE_SONNET_5_5_MODEL = "claude-sonnet-5-5";
|
|
3262
3312
|
var CLAUDE_SONNET_5_MODEL = "claude-sonnet-5";
|
|
3313
|
+
var CLAUDE_HAIKU_5_5_MODEL = "claude-haiku-5-5";
|
|
3263
3314
|
var CLAUDE_HAIKU_4_5_MODEL = "claude-haiku-4-5";
|
|
3264
3315
|
var CLAUDE_FABLE_5_1_BEDROCK_MODEL = "anthropic.claude-fable-5-1";
|
|
3265
3316
|
var CLAUDE_FABLE_5_BEDROCK_MODEL = "anthropic.claude-fable-5";
|
|
@@ -3268,6 +3319,7 @@ var CLAUDE_OPUS_5_BEDROCK_MODEL = "anthropic.claude-opus-5";
|
|
|
3268
3319
|
var CLAUDE_OPUS_4_8_BEDROCK_MODEL = "us.anthropic.claude-opus-4-8";
|
|
3269
3320
|
var CLAUDE_SONNET_5_5_BEDROCK_MODEL = "anthropic.claude-sonnet-5-5";
|
|
3270
3321
|
var CLAUDE_SONNET_5_BEDROCK_MODEL = "anthropic.claude-sonnet-5";
|
|
3322
|
+
var CLAUDE_HAIKU_5_5_BEDROCK_MODEL = "anthropic.claude-haiku-5-5";
|
|
3271
3323
|
var CLAUDE_HAIKU_4_5_BEDROCK_MODEL = "us.anthropic.claude-haiku-4-5-20251001-v1:0";
|
|
3272
3324
|
var GPT_6_ASTRA_MODEL = "gpt-6-astra";
|
|
3273
3325
|
var GPT_6_1_SOL_MODEL = "gpt-6.1-sol";
|
|
@@ -3303,6 +3355,7 @@ var CLAUDE_MODEL_CONTEXT_WINDOWS = {
|
|
|
3303
3355
|
[CLAUDE_OPUS_4_8_MODEL]: 1e6,
|
|
3304
3356
|
[CLAUDE_SONNET_5_5_MODEL]: 1e6,
|
|
3305
3357
|
[CLAUDE_SONNET_5_MODEL]: 1e6,
|
|
3358
|
+
[CLAUDE_HAIKU_5_5_MODEL]: 1e6,
|
|
3306
3359
|
[CLAUDE_HAIKU_4_5_MODEL]: 2e5,
|
|
3307
3360
|
[CLAUDE_FABLE_5_1_BEDROCK_MODEL]: 1e6,
|
|
3308
3361
|
[CLAUDE_FABLE_5_BEDROCK_MODEL]: 1e6,
|
|
@@ -3311,6 +3364,7 @@ var CLAUDE_MODEL_CONTEXT_WINDOWS = {
|
|
|
3311
3364
|
[CLAUDE_OPUS_4_8_BEDROCK_MODEL]: 1e6,
|
|
3312
3365
|
[CLAUDE_SONNET_5_5_BEDROCK_MODEL]: 1e6,
|
|
3313
3366
|
[CLAUDE_SONNET_5_BEDROCK_MODEL]: 1e6,
|
|
3367
|
+
[CLAUDE_HAIKU_5_5_BEDROCK_MODEL]: 1e6,
|
|
3314
3368
|
[CLAUDE_HAIKU_4_5_BEDROCK_MODEL]: 2e5,
|
|
3315
3369
|
"anthropic.claude-opus-4-8": 1e6,
|
|
3316
3370
|
"us.anthropic.claude-sonnet-5": 1e6,
|
|
@@ -3318,18 +3372,33 @@ var CLAUDE_MODEL_CONTEXT_WINDOWS = {
|
|
|
3318
3372
|
"claude-haiku-4-5-20251001": 2e5,
|
|
3319
3373
|
"claude-haiku-4-5@20251001": 2e5
|
|
3320
3374
|
};
|
|
3375
|
+
var CLAUDE_MODEL_MIN_SANDBOX_IMAGE = {
|
|
3376
|
+
[CLAUDE_FABLE_5_1_MODEL]: "replicas-sandbox-2026-09-01-v6",
|
|
3377
|
+
[CLAUDE_FABLE_5_MODEL]: null,
|
|
3378
|
+
[CLAUDE_OPUS_5_5_MODEL]: "replicas-sandbox-2026-09-22-v4",
|
|
3379
|
+
[CLAUDE_OPUS_5_MODEL]: null,
|
|
3380
|
+
[CLAUDE_OPUS_4_8_MODEL]: null,
|
|
3381
|
+
[CLAUDE_SONNET_5_5_MODEL]: "replicas-sandbox-2026-09-28-v7",
|
|
3382
|
+
[CLAUDE_SONNET_5_MODEL]: null,
|
|
3383
|
+
[CLAUDE_HAIKU_5_5_MODEL]: "replicas-sandbox-2026-10-08-v4",
|
|
3384
|
+
[CLAUDE_HAIKU_4_5_MODEL]: null
|
|
3385
|
+
};
|
|
3386
|
+
var CODEX_MODEL_MIN_SANDBOX_IMAGE = {
|
|
3387
|
+
[DEFAULT_CODEX_MODEL]: "replicas-sandbox-2026-09-30-v11",
|
|
3388
|
+
[GPT_6_SOL_MODEL]: "replicas-sandbox-2026-09-24-v1",
|
|
3389
|
+
[GPT_6_ASTRA_MODEL]: "replicas-sandbox-2026-09-04-v7",
|
|
3390
|
+
[GPT_6_LUNA_MODEL]: "replicas-sandbox-2026-09-24-v1",
|
|
3391
|
+
[GPT_5_6_SOL_MODEL]: null,
|
|
3392
|
+
[GPT_5_6_TERRA_MODEL]: null,
|
|
3393
|
+
[GPT_5_6_LUNA_MODEL]: null,
|
|
3394
|
+
"gpt-5.5": null,
|
|
3395
|
+
"gpt-5.4": null,
|
|
3396
|
+
"gpt-5.4-mini": null,
|
|
3397
|
+
"gpt-5.2": null
|
|
3398
|
+
};
|
|
3321
3399
|
var AGENT_MODELS = {
|
|
3322
|
-
claude:
|
|
3323
|
-
|
|
3324
|
-
CLAUDE_FABLE_5_MODEL,
|
|
3325
|
-
CLAUDE_OPUS_5_5_MODEL,
|
|
3326
|
-
CLAUDE_OPUS_5_MODEL,
|
|
3327
|
-
CLAUDE_OPUS_4_8_MODEL,
|
|
3328
|
-
CLAUDE_SONNET_5_5_MODEL,
|
|
3329
|
-
CLAUDE_SONNET_5_MODEL,
|
|
3330
|
-
CLAUDE_HAIKU_4_5_MODEL
|
|
3331
|
-
],
|
|
3332
|
-
codex: [DEFAULT_CODEX_MODEL, GPT_6_SOL_MODEL, GPT_6_ASTRA_MODEL, GPT_6_LUNA_MODEL, GPT_5_6_SOL_MODEL, GPT_5_6_TERRA_MODEL, GPT_5_6_LUNA_MODEL, "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.2"],
|
|
3400
|
+
claude: Object.keys(CLAUDE_MODEL_MIN_SANDBOX_IMAGE),
|
|
3401
|
+
codex: Object.keys(CODEX_MODEL_MIN_SANDBOX_IMAGE),
|
|
3333
3402
|
cursor: [
|
|
3334
3403
|
CLAUDE_FABLE_5_1_MODEL,
|
|
3335
3404
|
CLAUDE_FABLE_5_MODEL,
|
|
@@ -3401,20 +3470,10 @@ var DEFAULT_STATIC_AGENT_MODELS = {
|
|
|
3401
3470
|
codex: withoutHiddenByDefault(AGENT_MODELS.codex)
|
|
3402
3471
|
};
|
|
3403
3472
|
var DEFAULT_CURSOR_MODELS = withoutHiddenByDefault(AGENT_MODELS.cursor);
|
|
3404
|
-
var CLAUDE_MODEL_MIN_SANDBOX_IMAGE = {
|
|
3405
|
-
[CLAUDE_FABLE_5_1_MODEL]: "replicas-sandbox-2026-09-01-v6",
|
|
3406
|
-
[CLAUDE_OPUS_5_5_MODEL]: "replicas-sandbox-2026-09-22-v4",
|
|
3407
|
-
[CLAUDE_SONNET_5_5_MODEL]: "replicas-sandbox-2026-09-28-v7"
|
|
3408
|
-
};
|
|
3409
|
-
var CODEX_MODEL_MIN_SANDBOX_IMAGE = {
|
|
3410
|
-
[GPT_6_ASTRA_MODEL]: "replicas-sandbox-2026-09-04-v7",
|
|
3411
|
-
[GPT_6_1_SOL_MODEL]: "replicas-sandbox-2026-09-30-v11",
|
|
3412
|
-
[GPT_6_SOL_MODEL]: "replicas-sandbox-2026-09-24-v1",
|
|
3413
|
-
[GPT_6_LUNA_MODEL]: "replicas-sandbox-2026-09-24-v1"
|
|
3414
|
-
};
|
|
3415
3473
|
var SANDBOX_IMAGE_MODEL_FALLBACKS = {
|
|
3416
3474
|
[CLAUDE_OPUS_5_5_MODEL]: CLAUDE_OPUS_5_MODEL,
|
|
3417
3475
|
[CLAUDE_SONNET_5_5_MODEL]: CLAUDE_SONNET_5_MODEL,
|
|
3476
|
+
[CLAUDE_HAIKU_5_5_MODEL]: CLAUDE_HAIKU_4_5_MODEL,
|
|
3418
3477
|
[GPT_6_1_SOL_MODEL]: GPT_6_SOL_MODEL,
|
|
3419
3478
|
[GPT_6_SOL_MODEL]: GPT_5_6_SOL_MODEL,
|
|
3420
3479
|
[GPT_6_ASTRA_MODEL]: GPT_5_6_TERRA_MODEL,
|
|
@@ -3468,6 +3527,7 @@ var MODEL_LABELS = {
|
|
|
3468
3527
|
"composer-2.5": "Composer 2.5",
|
|
3469
3528
|
[CLAUDE_OPUS_4_8_MODEL]: "Opus 4.8",
|
|
3470
3529
|
"claude-opus-4-7": "Opus 4.7",
|
|
3530
|
+
[CLAUDE_HAIKU_5_5_MODEL]: "Haiku 5.5",
|
|
3471
3531
|
[CLAUDE_HAIKU_4_5_MODEL]: "Haiku 4.5",
|
|
3472
3532
|
"gemini-3.8-flash": "Gemini 3.8 Flash",
|
|
3473
3533
|
"gemini-3.1-pro": "Gemini 3.1 Pro",
|
|
@@ -3483,97 +3543,97 @@ var MAX_CANVAS_FILE_BYTES = 25 * 1024 * 1024;
|
|
|
3483
3543
|
var MAX_CANVAS_PREVIEW_BYTES = 5 * 1024 * 1024;
|
|
3484
3544
|
|
|
3485
3545
|
// ../shared/src/engine/v1.ts
|
|
3486
|
-
import { z as
|
|
3487
|
-
var updateChatDisplayNameRequestSchema =
|
|
3488
|
-
displayName:
|
|
3546
|
+
import { z as z6 } from "zod";
|
|
3547
|
+
var updateChatDisplayNameRequestSchema = z6.object({
|
|
3548
|
+
displayName: z6.string().trim().min(1).max(100)
|
|
3489
3549
|
});
|
|
3490
|
-
var createChatRequestSchema =
|
|
3491
|
-
id:
|
|
3492
|
-
createdAt:
|
|
3493
|
-
provider:
|
|
3494
|
-
title:
|
|
3495
|
-
parentChatId:
|
|
3496
|
-
forkSourceChatId:
|
|
3497
|
-
sideChat:
|
|
3498
|
-
clientRequestId:
|
|
3550
|
+
var createChatRequestSchema = z6.object({
|
|
3551
|
+
id: z6.string().uuid().optional(),
|
|
3552
|
+
createdAt: z6.string().datetime().optional(),
|
|
3553
|
+
provider: z6.enum(VALID_AGENT_PROVIDERS),
|
|
3554
|
+
title: z6.string().min(1).optional(),
|
|
3555
|
+
parentChatId: z6.string().uuid().optional(),
|
|
3556
|
+
forkSourceChatId: z6.string().uuid().optional(),
|
|
3557
|
+
sideChat: z6.boolean().optional(),
|
|
3558
|
+
clientRequestId: z6.string().min(1).max(128).optional()
|
|
3499
3559
|
}).refine((request) => !request.sideChat || request.forkSourceChatId !== void 0 && request.parentChatId === request.forkSourceChatId, {
|
|
3500
3560
|
message: "A side chat must fork its parent chat"
|
|
3501
3561
|
});
|
|
3502
|
-
var spawnSubagentRequestSchema =
|
|
3503
|
-
provider:
|
|
3504
|
-
prompt:
|
|
3505
|
-
forkTurns:
|
|
3562
|
+
var spawnSubagentRequestSchema = z6.object({
|
|
3563
|
+
provider: z6.enum(VALID_AGENT_PROVIDERS),
|
|
3564
|
+
prompt: z6.string().min(1),
|
|
3565
|
+
forkTurns: z6.string().regex(/^(all|none|[1-9]\d*)$/).refine(
|
|
3506
3566
|
(value) => value === "all" || value === "none" || Number.isSafeInteger(Number(value)),
|
|
3507
3567
|
"Expected all, none, or a positive safe integer string"
|
|
3508
3568
|
).default("all"),
|
|
3509
|
-
model:
|
|
3510
|
-
thinkingLevel:
|
|
3511
|
-
title:
|
|
3569
|
+
model: z6.string().min(1).optional(),
|
|
3570
|
+
thinkingLevel: z6.enum(VALID_THINKING_LEVELS).optional(),
|
|
3571
|
+
title: z6.string().min(1).optional()
|
|
3512
3572
|
});
|
|
3513
|
-
var messageSubagentRequestSchema =
|
|
3514
|
-
message:
|
|
3515
|
-
model:
|
|
3516
|
-
thinkingLevel:
|
|
3573
|
+
var messageSubagentRequestSchema = z6.object({
|
|
3574
|
+
message: z6.string().min(1),
|
|
3575
|
+
model: z6.string().min(1).optional(),
|
|
3576
|
+
thinkingLevel: z6.enum(VALID_THINKING_LEVELS).optional()
|
|
3517
3577
|
});
|
|
3518
|
-
var waitSubagentRequestSchema =
|
|
3519
|
-
timeoutMinutes:
|
|
3578
|
+
var waitSubagentRequestSchema = z6.object({
|
|
3579
|
+
timeoutMinutes: z6.coerce.number().positive().max(1440).optional()
|
|
3520
3580
|
});
|
|
3521
|
-
var subagentResponseSchema =
|
|
3522
|
-
chatId:
|
|
3523
|
-
status:
|
|
3524
|
-
response:
|
|
3525
|
-
timedOut:
|
|
3581
|
+
var subagentResponseSchema = z6.object({
|
|
3582
|
+
chatId: z6.string().uuid(),
|
|
3583
|
+
status: z6.enum(["working", "completed"]),
|
|
3584
|
+
response: z6.string().optional(),
|
|
3585
|
+
timedOut: z6.literal(true).optional(),
|
|
3586
|
+
interruptedByUserMessage: z6.literal(true).optional()
|
|
3526
3587
|
});
|
|
3527
|
-
var integrationErrorNotificationTargetSchema =
|
|
3528
|
-
|
|
3529
|
-
type:
|
|
3530
|
-
conversation:
|
|
3531
|
-
channelId:
|
|
3532
|
-
threadTs:
|
|
3588
|
+
var integrationErrorNotificationTargetSchema = z6.discriminatedUnion("type", [
|
|
3589
|
+
z6.object({
|
|
3590
|
+
type: z6.literal("slack"),
|
|
3591
|
+
conversation: z6.object({
|
|
3592
|
+
channelId: z6.string().min(1),
|
|
3593
|
+
threadTs: z6.string().min(1)
|
|
3533
3594
|
}).optional()
|
|
3534
3595
|
}),
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
type:
|
|
3538
|
-
provider:
|
|
3539
|
-
resource:
|
|
3540
|
-
repositoryId:
|
|
3541
|
-
resourceNumber:
|
|
3596
|
+
z6.object({ type: z6.literal("linear"), sessionId: z6.string().min(1) }),
|
|
3597
|
+
z6.object({
|
|
3598
|
+
type: z6.literal("code_host"),
|
|
3599
|
+
provider: z6.enum(["github", "gitlab"]),
|
|
3600
|
+
resource: z6.enum(["issue", "pull_request"]),
|
|
3601
|
+
repositoryId: z6.string().min(1),
|
|
3602
|
+
resourceNumber: z6.number().int().positive()
|
|
3542
3603
|
}),
|
|
3543
|
-
|
|
3604
|
+
z6.object({ type: z6.literal("automation"), executionId: z6.string().min(1) })
|
|
3544
3605
|
]);
|
|
3545
|
-
var sendChatMessageRequestSchema =
|
|
3546
|
-
messageId:
|
|
3547
|
-
submittedAt:
|
|
3548
|
-
message:
|
|
3549
|
-
model:
|
|
3550
|
-
customInstructions:
|
|
3551
|
-
planMode:
|
|
3552
|
-
images:
|
|
3553
|
-
type:
|
|
3554
|
-
source:
|
|
3555
|
-
|
|
3556
|
-
|
|
3606
|
+
var sendChatMessageRequestSchema = z6.object({
|
|
3607
|
+
messageId: z6.string().min(1).optional(),
|
|
3608
|
+
submittedAt: z6.string().datetime().optional(),
|
|
3609
|
+
message: z6.string().min(1),
|
|
3610
|
+
model: z6.string().optional(),
|
|
3611
|
+
customInstructions: z6.string().optional(),
|
|
3612
|
+
planMode: z6.boolean().optional(),
|
|
3613
|
+
images: z6.array(z6.object({
|
|
3614
|
+
type: z6.literal("image"),
|
|
3615
|
+
source: z6.discriminatedUnion("type", [
|
|
3616
|
+
z6.object({ type: z6.literal("base64"), media_type: z6.enum(IMAGE_MEDIA_TYPES), data: z6.string().min(1) }),
|
|
3617
|
+
z6.object({ type: z6.literal("url"), url: z6.string().url() })
|
|
3557
3618
|
])
|
|
3558
3619
|
})).optional(),
|
|
3559
|
-
canvasUploadIds:
|
|
3560
|
-
thinkingLevel:
|
|
3561
|
-
goalMode:
|
|
3562
|
-
fastMode:
|
|
3563
|
-
source:
|
|
3564
|
-
enableInteractiveTools:
|
|
3565
|
-
type:
|
|
3566
|
-
merge:
|
|
3567
|
-
idempotencyKey:
|
|
3568
|
-
automationId:
|
|
3569
|
-
environmentId:
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
senderAvatarUrl: z7.string().optional(),
|
|
3620
|
+
canvasUploadIds: z6.array(z6.string().min(1)).optional(),
|
|
3621
|
+
thinkingLevel: z6.enum(VALID_THINKING_LEVELS).optional(),
|
|
3622
|
+
goalMode: z6.boolean().optional(),
|
|
3623
|
+
fastMode: z6.boolean().optional(),
|
|
3624
|
+
source: z6.enum(MESSAGE_SOURCES).optional(),
|
|
3625
|
+
enableInteractiveTools: z6.boolean().optional(),
|
|
3626
|
+
type: z6.string().min(1).optional(),
|
|
3627
|
+
merge: z6.boolean().optional(),
|
|
3628
|
+
idempotencyKey: z6.string().min(1).max(128).optional(),
|
|
3629
|
+
automationId: z6.string().optional(),
|
|
3630
|
+
environmentId: z6.string().min(1).optional(),
|
|
3631
|
+
senderUserId: z6.string().optional(),
|
|
3632
|
+
senderEmail: z6.string().optional(),
|
|
3633
|
+
senderDisplayName: z6.string().optional(),
|
|
3634
|
+
senderAvatarUrl: z6.string().optional(),
|
|
3575
3635
|
errorNotificationTarget: integrationErrorNotificationTargetSchema.optional(),
|
|
3576
|
-
errorNotificationTargets:
|
|
3636
|
+
errorNotificationTargets: z6.array(integrationErrorNotificationTargetSchema).optional()
|
|
3577
3637
|
}).passthrough();
|
|
3578
3638
|
function normalizeCodexAspTranscriptStatus(status, failed = false) {
|
|
3579
3639
|
if (failed || status === "failed" || status === "declined") return "failed";
|
|
@@ -3605,6 +3665,7 @@ var CODEX_ITEM_FIELD_CHECKS = {
|
|
|
3605
3665
|
function isCodexAspTranscriptItem(value) {
|
|
3606
3666
|
if (!isRecord(value) || typeof value.id !== "string" || typeof value.timestamp !== "string") return false;
|
|
3607
3667
|
if (value.sequence !== void 0 && typeof value.sequence !== "number") return false;
|
|
3668
|
+
if (value.completedAt !== void 0 && typeof value.completedAt !== "string") return false;
|
|
3608
3669
|
if (typeof value.type !== "string" || !Object.hasOwn(CODEX_ITEM_FIELD_CHECKS, value.type)) return false;
|
|
3609
3670
|
return CODEX_ITEM_FIELD_CHECKS[value.type](value);
|
|
3610
3671
|
}
|
|
@@ -3791,9 +3852,10 @@ function messageForItem(item) {
|
|
|
3791
3852
|
return {
|
|
3792
3853
|
id: `reasoning-${item.id}`,
|
|
3793
3854
|
type: "reasoning",
|
|
3794
|
-
content:
|
|
3855
|
+
content: COMPACTION_CONTENT,
|
|
3795
3856
|
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
3796
|
-
timestamp: item.timestamp
|
|
3857
|
+
timestamp: item.timestamp,
|
|
3858
|
+
completedAt: item.completedAt
|
|
3797
3859
|
};
|
|
3798
3860
|
}
|
|
3799
3861
|
return {
|
|
@@ -4587,6 +4649,15 @@ function parseMuseEvents(events) {
|
|
|
4587
4649
|
status: terminal ? "completed" : "in_progress",
|
|
4588
4650
|
timestamp: typeof item.recordedAt === "string" ? item.recordedAt : event.timestamp
|
|
4589
4651
|
});
|
|
4652
|
+
} else if (item.kind === "compaction") {
|
|
4653
|
+
upsertDisplayMessage(messages, {
|
|
4654
|
+
id: `muse-compaction-${item.itemId}`,
|
|
4655
|
+
type: "reasoning",
|
|
4656
|
+
content: COMPACTION_CONTENT,
|
|
4657
|
+
status: item.status === "failed" ? "failed" : terminal ? "completed" : "in_progress",
|
|
4658
|
+
timestamp: typeof item.recordedAt === "string" ? item.recordedAt : event.timestamp,
|
|
4659
|
+
completedAt: terminal ? event.timestamp : void 0
|
|
4660
|
+
});
|
|
4590
4661
|
} else if (item.kind === "toolCall") {
|
|
4591
4662
|
let input = item.args;
|
|
4592
4663
|
if (typeof item.args === "string") {
|
|
@@ -4693,19 +4764,6 @@ function parsePiEvents(events) {
|
|
|
4693
4764
|
return messages;
|
|
4694
4765
|
}
|
|
4695
4766
|
|
|
4696
|
-
// ../shared/src/display-message/parsers/mcp.ts
|
|
4697
|
-
function parseMcpToolName(name) {
|
|
4698
|
-
const prefix = "mcp__";
|
|
4699
|
-
if (!name.startsWith(prefix)) return null;
|
|
4700
|
-
const rest = name.slice(prefix.length);
|
|
4701
|
-
const sep = rest.indexOf("__");
|
|
4702
|
-
if (sep <= 0) return null;
|
|
4703
|
-
const server2 = rest.slice(0, sep);
|
|
4704
|
-
const tool = rest.slice(sep + 2);
|
|
4705
|
-
if (!server2 || !tool) return null;
|
|
4706
|
-
return { server: server2, tool };
|
|
4707
|
-
}
|
|
4708
|
-
|
|
4709
4767
|
// ../shared/src/display-message/parsers/claude-parser.ts
|
|
4710
4768
|
var ABORTED_TERMINAL_REASONS = /* @__PURE__ */ new Set(["aborted_streaming", "aborted_tools"]);
|
|
4711
4769
|
var COMMAND_TOOL_NAMES = /* @__PURE__ */ new Set(["Bash", "bash", "shell"]);
|
|
@@ -4760,6 +4818,17 @@ function createSubagentMessage(messageIndex, timestamp, fields) {
|
|
|
4760
4818
|
function collectNestedEvents(events, toolUseId) {
|
|
4761
4819
|
return events.filter((e) => e.payload.parent_tool_use_id === toolUseId).map(({ timestamp, type, payload }) => ({ timestamp, type, payload }));
|
|
4762
4820
|
}
|
|
4821
|
+
function readToolResult(event) {
|
|
4822
|
+
if (event.type !== "claude-user") return void 0;
|
|
4823
|
+
const toolResult = normalizeContentBlocks(event.payload.message?.content).find((c) => c.type === "tool_result");
|
|
4824
|
+
if (!toolResult?.tool_use_id) return void 0;
|
|
4825
|
+
return {
|
|
4826
|
+
toolResult,
|
|
4827
|
+
toolUseId: toolResult.tool_use_id,
|
|
4828
|
+
output: extractToolResultText(toolResult.content),
|
|
4829
|
+
status: toolResult.is_error ? "failed" : "completed"
|
|
4830
|
+
};
|
|
4831
|
+
}
|
|
4763
4832
|
function coerceClaudeResultPayload(payload) {
|
|
4764
4833
|
return {
|
|
4765
4834
|
is_error: typeof payload.is_error === "boolean" ? payload.is_error : void 0,
|
|
@@ -4793,6 +4862,7 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
4793
4862
|
const completedStreamIds = /* @__PURE__ */ new Set();
|
|
4794
4863
|
const supersededStreamIds = /* @__PURE__ */ new Set();
|
|
4795
4864
|
let liveStreamId = null;
|
|
4865
|
+
let compaction;
|
|
4796
4866
|
const assistantThinking = /* @__PURE__ */ new Map();
|
|
4797
4867
|
const assistantTextCounts = /* @__PURE__ */ new Map();
|
|
4798
4868
|
const acceptedUserMessageIndexes = /* @__PURE__ */ new Set();
|
|
@@ -4926,6 +4996,20 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
4926
4996
|
const messageId = event.payload.message?.id;
|
|
4927
4997
|
const contentBlocks = normalizeContentBlocks(event.payload.message?.content);
|
|
4928
4998
|
const messageKey = messageId || event.timestamp;
|
|
4999
|
+
const localCommand = event.payload.local_command_run;
|
|
5000
|
+
const goalArgs = isRecord(localCommand) && localCommand.command === GOAL_TOOL_NAME && typeof localCommand.args === "string" ? localCommand.args.trim() : "";
|
|
5001
|
+
if (goalArgs) {
|
|
5002
|
+
upsertDisplayMessage(messages, {
|
|
5003
|
+
id: `goal-${messageKey}`,
|
|
5004
|
+
type: "tool_call",
|
|
5005
|
+
server: "claude",
|
|
5006
|
+
tool: GOAL_TOOL_NAME,
|
|
5007
|
+
input: goalArgs === "clear" ? void 0 : { objective: goalArgs },
|
|
5008
|
+
status: "completed",
|
|
5009
|
+
timestamp: event.timestamp
|
|
5010
|
+
});
|
|
5011
|
+
return;
|
|
5012
|
+
}
|
|
4929
5013
|
const streamRefs = messageId ? partialIndexes.get(messageId) : void 0;
|
|
4930
5014
|
if (messageId) {
|
|
4931
5015
|
if (liveStreamId !== null && liveStreamId !== messageId) {
|
|
@@ -5029,48 +5113,6 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
5029
5113
|
status: "in_progress",
|
|
5030
5114
|
timestamp: event.timestamp
|
|
5031
5115
|
});
|
|
5032
|
-
} else if (toolName === "mcp__relay-subagent-tools__spawn_agent") {
|
|
5033
|
-
const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
|
|
5034
|
-
const provider = typeof inputObj.provider === "string" ? inputObj.provider : "unknown";
|
|
5035
|
-
const prompt = typeof inputObj.prompt === "string" ? inputObj.prompt : "";
|
|
5036
|
-
const model = typeof inputObj.model === "string" ? inputObj.model : void 0;
|
|
5037
|
-
const title = typeof inputObj.title === "string" ? inputObj.title : void 0;
|
|
5038
|
-
messages.push(createSubagentMessage(messages.length, event.timestamp, {
|
|
5039
|
-
toolUseId,
|
|
5040
|
-
description: title || `Relay subagent (${provider})`,
|
|
5041
|
-
prompt,
|
|
5042
|
-
subagentType: provider,
|
|
5043
|
-
model,
|
|
5044
|
-
thinkingLevel: isValidThinkingLevel(inputObj.thinking_level) ? inputObj.thinking_level : void 0,
|
|
5045
|
-
status: "in_progress",
|
|
5046
|
-
nestedEvents: [],
|
|
5047
|
-
isChatBased: true
|
|
5048
|
-
}));
|
|
5049
|
-
} else if (toolName === "mcp__relay-subagent-tools__message_agent") {
|
|
5050
|
-
const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
|
|
5051
|
-
messages.push({
|
|
5052
|
-
id: `subagent-followup-${event.timestamp}-${messages.length}`,
|
|
5053
|
-
type: "subagent_followup",
|
|
5054
|
-
toolUseId,
|
|
5055
|
-
chatId: typeof inputObj.chatId === "string" ? inputObj.chatId : "",
|
|
5056
|
-
message: typeof inputObj.message === "string" ? inputObj.message : "",
|
|
5057
|
-
model: typeof inputObj.model === "string" ? inputObj.model : void 0,
|
|
5058
|
-
thinkingLevel: isValidThinkingLevel(inputObj.thinking_level) ? inputObj.thinking_level : void 0,
|
|
5059
|
-
status: "in_progress",
|
|
5060
|
-
timestamp: event.timestamp
|
|
5061
|
-
});
|
|
5062
|
-
} else if (toolName === "mcp__relay-subagent-tools__delete_agent") {
|
|
5063
|
-
const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
|
|
5064
|
-
const mcp = parseMcpToolName(toolName);
|
|
5065
|
-
messages.push({
|
|
5066
|
-
id: `toolcall-${event.timestamp}-${messages.length}`,
|
|
5067
|
-
type: "tool_call",
|
|
5068
|
-
server: mcp?.server ?? "relay-subagent-tools",
|
|
5069
|
-
tool: mcp?.tool ?? "delete_agent",
|
|
5070
|
-
input: inputObj,
|
|
5071
|
-
status: "in_progress",
|
|
5072
|
-
timestamp: event.timestamp
|
|
5073
|
-
});
|
|
5074
5116
|
} else {
|
|
5075
5117
|
messages.push({
|
|
5076
5118
|
id: `toolcall-${event.timestamp}-${messages.length}`,
|
|
@@ -5085,6 +5127,11 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
5085
5127
|
}
|
|
5086
5128
|
});
|
|
5087
5129
|
}
|
|
5130
|
+
if (compaction && (event.type === "claude-result" || event.type === CHAT_INTERRUPTED_EVENT_TYPE)) {
|
|
5131
|
+
compaction.status = "failed";
|
|
5132
|
+
compaction.completedAt = event.timestamp;
|
|
5133
|
+
compaction = void 0;
|
|
5134
|
+
}
|
|
5088
5135
|
if (event.type === "claude-result") {
|
|
5089
5136
|
const payload = coerceClaudeResultPayload(event.payload);
|
|
5090
5137
|
if (isClaudeResultError(payload)) {
|
|
@@ -5098,6 +5145,19 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
5098
5145
|
}
|
|
5099
5146
|
}
|
|
5100
5147
|
if (event.type === "claude-system") {
|
|
5148
|
+
const { subtype, status, compact_result: compactResult } = event.payload;
|
|
5149
|
+
const compactionEnded = subtype === "compact_boundary" || compactResult === "failed";
|
|
5150
|
+
if (compactionEnded || subtype === "status" && status === "compacting") {
|
|
5151
|
+
if (!compaction) {
|
|
5152
|
+
compaction = { id: `compaction-${event.timestamp}`, type: "reasoning", content: COMPACTION_CONTENT, timestamp: event.timestamp };
|
|
5153
|
+
messages.push(compaction);
|
|
5154
|
+
}
|
|
5155
|
+
compaction.status = !compactionEnded ? "in_progress" : compactResult === "failed" ? "failed" : "completed";
|
|
5156
|
+
if (compactionEnded) {
|
|
5157
|
+
compaction.completedAt = event.timestamp;
|
|
5158
|
+
compaction = void 0;
|
|
5159
|
+
}
|
|
5160
|
+
}
|
|
5101
5161
|
const payload = coerceBackgroundTaskPayload(event.payload);
|
|
5102
5162
|
if (payload?.ambient) ambientTaskIds.add(payload.taskId);
|
|
5103
5163
|
if (payload && !ambientTaskIds.has(payload.taskId)) {
|
|
@@ -5182,52 +5242,38 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
5182
5242
|
messages.push(fileOrCommandMessage(tool.name, tool.id, "filePath" in tool ? { file_path: tool.filePath } : { command: tool.command }, timestamp));
|
|
5183
5243
|
}
|
|
5184
5244
|
filteredEvents.forEach((event) => {
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
message.exitCode = parseInt(exitCodeMatch[1], 10);
|
|
5205
|
-
} else {
|
|
5206
|
-
message.exitCode = isError ? 1 : 0;
|
|
5207
|
-
}
|
|
5208
|
-
} else if (message.type === "patch") {
|
|
5209
|
-
message.status = status;
|
|
5210
|
-
} else if (message.type === "web_search") {
|
|
5211
|
-
message.status = status;
|
|
5212
|
-
} else if (message.type === "tool_call") {
|
|
5213
|
-
message.output = resultContent;
|
|
5214
|
-
message.status = status;
|
|
5215
|
-
} else if (message.type === "skill") {
|
|
5216
|
-
message.status = status;
|
|
5217
|
-
} else if (message.type === "subagent") {
|
|
5218
|
-
message.output = resultContent;
|
|
5219
|
-
message.status = status;
|
|
5220
|
-
if (!message.chatId && resultContent) {
|
|
5221
|
-
const parsed = safeJsonParse(resultContent, {});
|
|
5222
|
-
if (parsed.chatId) {
|
|
5223
|
-
message.chatId = parsed.chatId;
|
|
5224
|
-
}
|
|
5225
|
-
}
|
|
5226
|
-
} else if (message.type === "subagent_followup") {
|
|
5227
|
-
message.output = resultContent;
|
|
5228
|
-
message.status = status;
|
|
5229
|
-
}
|
|
5245
|
+
const result2 = readToolResult(event);
|
|
5246
|
+
if (!result2) return;
|
|
5247
|
+
const { toolResult, output: resultContent, status } = result2;
|
|
5248
|
+
const toolInfo = toolCallMap.get(result2.toolUseId);
|
|
5249
|
+
if (!toolInfo) return;
|
|
5250
|
+
const isError = status === "failed";
|
|
5251
|
+
if (toolInfo.toolName === "TaskCreate" && !isError) {
|
|
5252
|
+
taskAccumulator.processContentBlock(toolResult);
|
|
5253
|
+
}
|
|
5254
|
+
const message = messages[toolInfo.messageIndex];
|
|
5255
|
+
if (!message) return;
|
|
5256
|
+
if (message.type === "command") {
|
|
5257
|
+
message.output = resultContent;
|
|
5258
|
+
message.status = status;
|
|
5259
|
+
const exitCodeMatch = resultContent.match(/exit code:?\s*(\d+)/i);
|
|
5260
|
+
if (exitCodeMatch) {
|
|
5261
|
+
message.exitCode = parseInt(exitCodeMatch[1], 10);
|
|
5262
|
+
} else {
|
|
5263
|
+
message.exitCode = isError ? 1 : 0;
|
|
5230
5264
|
}
|
|
5265
|
+
} else if (message.type === "patch") {
|
|
5266
|
+
message.status = status;
|
|
5267
|
+
} else if (message.type === "web_search") {
|
|
5268
|
+
message.status = status;
|
|
5269
|
+
} else if (message.type === "tool_call") {
|
|
5270
|
+
message.output = resultContent;
|
|
5271
|
+
message.status = status;
|
|
5272
|
+
} else if (message.type === "skill") {
|
|
5273
|
+
message.status = status;
|
|
5274
|
+
} else if (message.type === "subagent") {
|
|
5275
|
+
message.output = resultContent;
|
|
5276
|
+
message.status = status;
|
|
5231
5277
|
}
|
|
5232
5278
|
});
|
|
5233
5279
|
for (const message of messages) {
|
|
@@ -5240,12 +5286,6 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
5240
5286
|
message.subagentType ??= toolMessage.subagentType;
|
|
5241
5287
|
}
|
|
5242
5288
|
}
|
|
5243
|
-
if (message.type !== "subagent_followup") continue;
|
|
5244
|
-
const target = messages.find((candidate) => candidate.type === "subagent" && candidate.chatId === message.chatId);
|
|
5245
|
-
if (target?.type === "subagent") {
|
|
5246
|
-
message.targetTitle = target.description;
|
|
5247
|
-
message.targetProvider = target.subagentType;
|
|
5248
|
-
}
|
|
5249
5289
|
}
|
|
5250
5290
|
const staleIndexes = new Set(supersededUserMessageIndexes);
|
|
5251
5291
|
for (const streamId of [...completedStreamIds, ...supersededStreamIds]) {
|
|
@@ -5254,7 +5294,7 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
5254
5294
|
if (refs?.agent !== void 0) staleIndexes.add(refs.agent);
|
|
5255
5295
|
}
|
|
5256
5296
|
if (staleIndexes.size === 0) return messages;
|
|
5257
|
-
return messages.filter((
|
|
5297
|
+
return messages.filter((_, index) => !staleIndexes.has(index));
|
|
5258
5298
|
}
|
|
5259
5299
|
|
|
5260
5300
|
// ../shared/src/display-message/parsers/index.ts
|
|
@@ -5279,15 +5319,15 @@ function parseAgentEvents(events, agentType) {
|
|
|
5279
5319
|
}
|
|
5280
5320
|
|
|
5281
5321
|
// ../shared/src/routes/workspaces.ts
|
|
5282
|
-
import { z as
|
|
5322
|
+
import { z as z8 } from "zod";
|
|
5283
5323
|
|
|
5284
5324
|
// ../shared/src/workspace-credentials.ts
|
|
5285
|
-
import { z as
|
|
5325
|
+
import { z as z7 } from "zod";
|
|
5286
5326
|
var WORKSPACE_CREDENTIAL_PROVIDERS = ["claude", "codex"];
|
|
5287
|
-
var workspaceCredentialProviderSchema =
|
|
5288
|
-
var workspaceCredentialSelectionSchema = agentCredentialSnapshotSchema.omit({ revision: true, account: true });
|
|
5327
|
+
var workspaceCredentialProviderSchema = z7.enum(WORKSPACE_CREDENTIAL_PROVIDERS);
|
|
5328
|
+
var workspaceCredentialSelectionSchema = agentCredentialSnapshotSchema.omit({ revision: true, account: true, credentialId: true });
|
|
5289
5329
|
var createWorkspaceCredentialSchema = workspaceCredentialSelectionSchema.extend({
|
|
5290
|
-
provider:
|
|
5330
|
+
provider: z7.enum(VALID_AGENT_PROVIDERS)
|
|
5291
5331
|
}).refine(({ provider, method }) => agentCredentialMethods(provider).includes(method), {
|
|
5292
5332
|
message: "This inference provider is not supported by this agent"
|
|
5293
5333
|
});
|
|
@@ -5299,6 +5339,7 @@ var switchWorkspaceCredentialSchema = workspaceCredentialSelectionSchema.extend(
|
|
|
5299
5339
|
|
|
5300
5340
|
// ../shared/src/routes/workspaces.ts
|
|
5301
5341
|
var WORKSPACE_STATUSES = ["active", "sleeping", "archived", "preparing", "error"];
|
|
5342
|
+
var STALE_PREPARING_MS = 10 * 6e4;
|
|
5302
5343
|
var VALID_LIFECYCLE_POLICIES = ["default", "archive_when_done", "sleep_when_done", "delete_after_inactivity"];
|
|
5303
5344
|
var WORKSPACE_STATUS_FILTERS = WORKSPACE_STATUSES.map((status) => status === "error" ? "failed" : status);
|
|
5304
5345
|
var WORKSPACE_SORT_CHOICES = [
|
|
@@ -5322,12 +5363,16 @@ var DEFAULT_WORKSPACE_FILTERS = {
|
|
|
5322
5363
|
activity: "any"
|
|
5323
5364
|
};
|
|
5324
5365
|
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
5325
|
-
var
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5366
|
+
var workspaceExecRequestSchema = z8.object({
|
|
5367
|
+
command: z8.string().regex(/\S/, "command is required"),
|
|
5368
|
+
timeout_seconds: z8.number().int().min(1).max(50).optional().describe("Default: 30")
|
|
5369
|
+
});
|
|
5370
|
+
var terminalRtcCandidateSchema = z8.object({ type: z8.literal("rtc-candidate"), candidate: z8.string(), mid: z8.string() });
|
|
5371
|
+
var terminalSocketServerMessageSchema = z8.discriminatedUnion("type", [
|
|
5372
|
+
z8.object({ type: z8.literal("output"), data: z8.string() }),
|
|
5373
|
+
z8.object({ type: z8.literal("rtc-answer"), sdp: z8.string() }),
|
|
5329
5374
|
terminalRtcCandidateSchema,
|
|
5330
|
-
|
|
5375
|
+
z8.object({ type: z8.literal("rtc-switch") })
|
|
5331
5376
|
]);
|
|
5332
5377
|
|
|
5333
5378
|
// src/index.ts
|
|
@@ -5363,7 +5408,7 @@ function result(data, isError = false) {
|
|
|
5363
5408
|
}
|
|
5364
5409
|
var server = new McpServer({
|
|
5365
5410
|
name: "replicas-mcp",
|
|
5366
|
-
version: "0.2.
|
|
5411
|
+
version: "0.2.21"
|
|
5367
5412
|
});
|
|
5368
5413
|
function registerTool(name, config, handler) {
|
|
5369
5414
|
server.registerTool.bind(server)(name, config, async (args) => {
|
|
@@ -5374,21 +5419,21 @@ function registerTool(name, config, handler) {
|
|
|
5374
5419
|
}
|
|
5375
5420
|
});
|
|
5376
5421
|
}
|
|
5377
|
-
var codingAgentSchema =
|
|
5422
|
+
var codingAgentSchema = z9.string().refine(isValidAgentProvider, {
|
|
5378
5423
|
message: `Coding agent must be ${getCodingAgentDisplayNames()}`
|
|
5379
5424
|
});
|
|
5380
|
-
var lifecyclePolicySchema =
|
|
5425
|
+
var lifecyclePolicySchema = z9.enum(VALID_LIFECYCLE_POLICIES);
|
|
5381
5426
|
registerTool(
|
|
5382
5427
|
"create_replica",
|
|
5383
5428
|
{
|
|
5384
5429
|
description: "Create a new replica workspace and send initial message",
|
|
5385
5430
|
inputSchema: {
|
|
5386
|
-
name:
|
|
5387
|
-
message:
|
|
5388
|
-
repository_ids:
|
|
5389
|
-
repository_set_id:
|
|
5431
|
+
name: z9.string().regex(/^\S+$/, "Name cannot contain spaces"),
|
|
5432
|
+
message: z9.string(),
|
|
5433
|
+
repository_ids: z9.array(z9.string()).min(1).optional().describe("Repository IDs to include. Mutually exclusive with repository_set_id."),
|
|
5434
|
+
repository_set_id: z9.string().optional().describe("Repository set ID to use. Mutually exclusive with repository_ids."),
|
|
5390
5435
|
coding_agent: codingAgentSchema.optional().describe("Coding agent to use (default: claude)"),
|
|
5391
|
-
model:
|
|
5436
|
+
model: z9.string().optional().describe("Model to use for the coding agent"),
|
|
5392
5437
|
lifecycle_policy: lifecyclePolicySchema.optional().describe("Lifecycle policy for the workspace")
|
|
5393
5438
|
}
|
|
5394
5439
|
},
|
|
@@ -5410,11 +5455,11 @@ registerTool(
|
|
|
5410
5455
|
{
|
|
5411
5456
|
description: "List all replicas with pagination and optional filters",
|
|
5412
5457
|
inputSchema: {
|
|
5413
|
-
page:
|
|
5414
|
-
limit:
|
|
5415
|
-
user_id:
|
|
5416
|
-
source:
|
|
5417
|
-
status:
|
|
5458
|
+
page: z9.number().optional(),
|
|
5459
|
+
limit: z9.number().optional(),
|
|
5460
|
+
user_id: z9.string().optional().describe("Filter by creator user ID"),
|
|
5461
|
+
source: z9.enum(["api", "dashboard", "slack", "linear", "github", "gitlab", "automation"]).optional().describe("Filter by creation source"),
|
|
5462
|
+
status: z9.enum(["active", "sleeping", "preparing"]).optional().describe("Filter by workspace status")
|
|
5418
5463
|
}
|
|
5419
5464
|
},
|
|
5420
5465
|
async (args) => {
|
|
@@ -5433,8 +5478,8 @@ registerTool(
|
|
|
5433
5478
|
{
|
|
5434
5479
|
description: "Get replica details by ID, including current status, chats, and repository statuses",
|
|
5435
5480
|
inputSchema: {
|
|
5436
|
-
id:
|
|
5437
|
-
include:
|
|
5481
|
+
id: z9.string(),
|
|
5482
|
+
include: z9.array(z9.enum(["environment", "diffs"])).optional().describe("Extra data to include in response")
|
|
5438
5483
|
}
|
|
5439
5484
|
},
|
|
5440
5485
|
async (args) => {
|
|
@@ -5449,12 +5494,12 @@ registerTool(
|
|
|
5449
5494
|
{
|
|
5450
5495
|
description: "Send a message to an existing replica. Automatically handles waking sleeping replicas.",
|
|
5451
5496
|
inputSchema: {
|
|
5452
|
-
id:
|
|
5453
|
-
message:
|
|
5497
|
+
id: z9.string(),
|
|
5498
|
+
message: z9.string(),
|
|
5454
5499
|
coding_agent: codingAgentSchema.optional().describe("Coding agent to use"),
|
|
5455
|
-
chat_id:
|
|
5456
|
-
model:
|
|
5457
|
-
plan_mode:
|
|
5500
|
+
chat_id: z9.string().optional().describe("Chat ID to send the message to (uses default chat if omitted)"),
|
|
5501
|
+
model: z9.string().optional().describe("Model to use"),
|
|
5502
|
+
plan_mode: z9.boolean().optional().describe("Whether to use plan mode")
|
|
5458
5503
|
}
|
|
5459
5504
|
},
|
|
5460
5505
|
async (args) => {
|
|
@@ -5471,7 +5516,7 @@ registerTool(
|
|
|
5471
5516
|
{
|
|
5472
5517
|
description: "Delete a replica. This terminates the workspace and cannot be undone.",
|
|
5473
5518
|
inputSchema: {
|
|
5474
|
-
id:
|
|
5519
|
+
id: z9.string()
|
|
5475
5520
|
}
|
|
5476
5521
|
},
|
|
5477
5522
|
(args) => api("DELETE", `/v1/replica/${args.id}`)
|
|
@@ -5495,7 +5540,7 @@ registerTool(
|
|
|
5495
5540
|
{
|
|
5496
5541
|
description: "List chats in a replica workspace",
|
|
5497
5542
|
inputSchema: {
|
|
5498
|
-
id:
|
|
5543
|
+
id: z9.string().describe("Replica ID")
|
|
5499
5544
|
}
|
|
5500
5545
|
},
|
|
5501
5546
|
(args) => api("GET", `/v1/replica/${args.id}/chats`)
|
|
@@ -5505,9 +5550,9 @@ registerTool(
|
|
|
5505
5550
|
{
|
|
5506
5551
|
description: "Create a new chat in a replica workspace",
|
|
5507
5552
|
inputSchema: {
|
|
5508
|
-
id:
|
|
5553
|
+
id: z9.string().describe("Replica ID"),
|
|
5509
5554
|
provider: codingAgentSchema.describe("Coding agent provider for the chat"),
|
|
5510
|
-
title:
|
|
5555
|
+
title: z9.string().optional().describe("Optional title for the chat")
|
|
5511
5556
|
}
|
|
5512
5557
|
},
|
|
5513
5558
|
async (args) => {
|
|
@@ -5521,8 +5566,8 @@ registerTool(
|
|
|
5521
5566
|
{
|
|
5522
5567
|
description: "Delete a chat from a replica workspace",
|
|
5523
5568
|
inputSchema: {
|
|
5524
|
-
id:
|
|
5525
|
-
chat_id:
|
|
5569
|
+
id: z9.string().describe("Replica ID"),
|
|
5570
|
+
chat_id: z9.string().describe("Chat ID to delete")
|
|
5526
5571
|
}
|
|
5527
5572
|
},
|
|
5528
5573
|
(args) => api("DELETE", `/v1/replica/${args.id}/chats/${args.chat_id}`)
|
|
@@ -5532,8 +5577,8 @@ registerTool(
|
|
|
5532
5577
|
{
|
|
5533
5578
|
description: "Read conversation history of a replica. Returns parsed DisplayMessage objects (user messages, agent responses, commands, file changes, tool calls, etc). If the workspace is sleeping, it will be woken and you should retry in 30-90 seconds.",
|
|
5534
5579
|
inputSchema: {
|
|
5535
|
-
id:
|
|
5536
|
-
chat_id:
|
|
5580
|
+
id: z9.string(),
|
|
5581
|
+
chat_id: z9.string().optional().describe("Read history for a specific chat (uses default chat if omitted)")
|
|
5537
5582
|
}
|
|
5538
5583
|
},
|
|
5539
5584
|
async (args) => {
|
|
@@ -5541,12 +5586,6 @@ registerTool(
|
|
|
5541
5586
|
if (args.chat_id) params.set("chat_id", args.chat_id);
|
|
5542
5587
|
const q = params.toString();
|
|
5543
5588
|
const response = await api("GET", `/v1/replica/${args.id}/history${q ? "?" + q : ""}`);
|
|
5544
|
-
if (response.waking) {
|
|
5545
|
-
return {
|
|
5546
|
-
status: "waking",
|
|
5547
|
-
message: "Workspace is waking from sleep. Retry in 30-90 seconds."
|
|
5548
|
-
};
|
|
5549
|
-
}
|
|
5550
5589
|
const agentType = response.coding_agent || "claude";
|
|
5551
5590
|
const messages = parseAgentEvents(response.events, agentType);
|
|
5552
5591
|
return {
|
|
@@ -5563,7 +5602,7 @@ registerTool(
|
|
|
5563
5602
|
{
|
|
5564
5603
|
description: "Get warm and start hook logs for a replica workspace",
|
|
5565
5604
|
inputSchema: {
|
|
5566
|
-
id:
|
|
5605
|
+
id: z9.string().describe("Replica ID")
|
|
5567
5606
|
}
|
|
5568
5607
|
},
|
|
5569
5608
|
(args) => api("GET", `/v1/replica/${args.id}/hooks`)
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -78,7 +78,7 @@ type RegisterToolFn = (
|
|
|
78
78
|
|
|
79
79
|
const server = new McpServer({
|
|
80
80
|
name: 'replicas-mcp',
|
|
81
|
-
version: '0.2.
|
|
81
|
+
version: '0.2.21',
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
function registerTool(
|
|
@@ -290,13 +290,6 @@ registerTool(
|
|
|
290
290
|
const q = params.toString();
|
|
291
291
|
const response = await api<ReadReplicaHistoryResponse>('GET', `/v1/replica/${args.id}/history${q ? '?' + q : ''}`);
|
|
292
292
|
|
|
293
|
-
if (response.waking) {
|
|
294
|
-
return {
|
|
295
|
-
status: 'waking',
|
|
296
|
-
message: 'Workspace is waking from sleep. Retry in 30-90 seconds.',
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
|
|
300
293
|
const agentType = (response.coding_agent || 'claude') as AgentProvider;
|
|
301
294
|
const messages = parseAgentEvents(response.events, agentType);
|
|
302
295
|
|