replicas-cli 0.2.603 → 0.2.604
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.cjs +1884 -1842
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -22358,58 +22358,6 @@ function date4(params) {
|
|
|
22358
22358
|
// ../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
22359
22359
|
config(en_default());
|
|
22360
22360
|
|
|
22361
|
-
// ../shared/src/analytics/types.ts
|
|
22362
|
-
var agentCredentialSnapshotSchema = external_exports.object({
|
|
22363
|
-
method: external_exports.enum(CREDENTIAL_METHOD),
|
|
22364
|
-
scope: external_exports.enum(CREDENTIAL_SCOPE),
|
|
22365
|
-
revision: external_exports.string().optional()
|
|
22366
|
-
});
|
|
22367
|
-
function isAuthMethod(value) {
|
|
22368
|
-
return typeof value === "string" && Object.values(CREDENTIAL_METHOD).some((method) => method === value);
|
|
22369
|
-
}
|
|
22370
|
-
function isCredentialScope(value) {
|
|
22371
|
-
return typeof value === "string" && CREDENTIAL_SCOPES.some((scope) => scope === value);
|
|
22372
|
-
}
|
|
22373
|
-
|
|
22374
|
-
// ../shared/src/event.ts
|
|
22375
|
-
var CLAUDE_PARTIAL_MESSAGE_EVENT_TYPE = "claude-partial-message";
|
|
22376
|
-
function coerceClaudePartialMessagePayload(payload) {
|
|
22377
|
-
const streamId = payload.streamId;
|
|
22378
|
-
if (typeof streamId !== "string" || !streamId) return null;
|
|
22379
|
-
const parentToolUseId = payload.parent_tool_use_id;
|
|
22380
|
-
const text = typeof payload.text === "string" && payload.text ? payload.text : void 0;
|
|
22381
|
-
const thinking = typeof payload.thinking === "string" && payload.thinking ? payload.thinking : void 0;
|
|
22382
|
-
if (!text && !thinking) return null;
|
|
22383
|
-
return {
|
|
22384
|
-
streamId,
|
|
22385
|
-
parent_tool_use_id: typeof parentToolUseId === "string" ? parentToolUseId : null,
|
|
22386
|
-
...text ? { text } : {},
|
|
22387
|
-
...thinking ? { thinking } : {},
|
|
22388
|
-
status: payload.status === "completed" ? "completed" : "in_progress"
|
|
22389
|
-
};
|
|
22390
|
-
}
|
|
22391
|
-
var USER_MESSAGE_ID_PAYLOAD_KEY = "replicasMessageId";
|
|
22392
|
-
var CODEX_ASP_ITEM_ID_PAYLOAD_KEY = "codexAspItemId";
|
|
22393
|
-
var CODEX_QUOTA_STATUS_EVENT_TYPE = "codex-quota-status";
|
|
22394
|
-
var CHAT_INTERRUPTED_EVENT_TYPE = "replicas-interrupted";
|
|
22395
|
-
var AUTH_FALLBACK_EVENT_TYPE = "auth-fallback";
|
|
22396
|
-
function coerceAuthFallbackPayload(payload) {
|
|
22397
|
-
const { provider, reason, exhaustedMethod, exhaustedScope, candidateMethod, candidateScope, status, detail } = payload;
|
|
22398
|
-
if (typeof provider !== "string" || !isValidCodingAgentProvider(provider) || reason !== "rate_limit" && reason !== "out_of_credits" || !isAuthMethod(exhaustedMethod) || !isAuthMethod(candidateMethod) || !isCredentialScope(candidateScope) || status !== "switched" && status !== "failed") {
|
|
22399
|
-
return null;
|
|
22400
|
-
}
|
|
22401
|
-
return {
|
|
22402
|
-
provider,
|
|
22403
|
-
reason,
|
|
22404
|
-
exhaustedMethod,
|
|
22405
|
-
...isCredentialScope(exhaustedScope) ? { exhaustedScope } : {},
|
|
22406
|
-
candidateMethod,
|
|
22407
|
-
candidateScope,
|
|
22408
|
-
status,
|
|
22409
|
-
...typeof detail === "string" && detail ? { detail } : {}
|
|
22410
|
-
};
|
|
22411
|
-
}
|
|
22412
|
-
|
|
22413
22361
|
// ../shared/src/aster.ts
|
|
22414
22362
|
var ASTER_MODELS = [
|
|
22415
22363
|
"kimi-k3",
|
|
@@ -22663,319 +22611,529 @@ function classifyCanvasFilename(filename) {
|
|
|
22663
22611
|
return CANVAS_KIND_BY_EXTENSION[ext] ?? { kind: "other", mimeType: "application/octet-stream" };
|
|
22664
22612
|
}
|
|
22665
22613
|
|
|
22666
|
-
// ../shared/src/
|
|
22667
|
-
var
|
|
22668
|
-
var
|
|
22669
|
-
|
|
22670
|
-
|
|
22671
|
-
|
|
22672
|
-
|
|
22673
|
-
|
|
22674
|
-
|
|
22675
|
-
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
|
|
22680
|
-
|
|
22681
|
-
|
|
22682
|
-
|
|
22683
|
-
|
|
22684
|
-
|
|
22685
|
-
|
|
22686
|
-
|
|
22687
|
-
|
|
22688
|
-
|
|
22689
|
-
|
|
22690
|
-
|
|
22691
|
-
|
|
22692
|
-
|
|
22693
|
-
|
|
22694
|
-
|
|
22695
|
-
|
|
22696
|
-
|
|
22697
|
-
|
|
22698
|
-
|
|
22699
|
-
|
|
22700
|
-
|
|
22701
|
-
|
|
22702
|
-
|
|
22703
|
-
|
|
22704
|
-
|
|
22705
|
-
seatPriceCents: 3e4,
|
|
22706
|
-
features: [
|
|
22707
|
-
"Unlimited manual workspace minutes",
|
|
22708
|
-
"15,000 automated workspace minutes per month",
|
|
22709
|
-
"Unlimited repositories",
|
|
22710
|
-
"Unlimited automations",
|
|
22711
|
-
"Warm pools and warm hooks",
|
|
22712
|
-
"Higher API rate limits",
|
|
22713
|
-
"Access to a static egress IP",
|
|
22714
|
-
"Auto-upgraded sandbox resources (4 vCPU, 32 GB disk, 16 GB memory)",
|
|
22715
|
-
"Shared Slack support channel"
|
|
22716
|
-
]
|
|
22717
|
-
},
|
|
22718
|
-
enterprise: {
|
|
22719
|
-
id: "enterprise",
|
|
22720
|
-
name: "Enterprise",
|
|
22721
|
-
monthlyPrice: 0,
|
|
22722
|
-
seatPriceCents: 0,
|
|
22723
|
-
features: [
|
|
22724
|
-
"Unlimited manual workspace minutes",
|
|
22725
|
-
"Unlimited automated workspace minutes",
|
|
22726
|
-
"Unlimited automations",
|
|
22727
|
-
"Custom warm hooks and pools",
|
|
22728
|
-
"Custom API rates",
|
|
22729
|
-
"Custom rate limits",
|
|
22730
|
-
"Shared Slack support channel",
|
|
22731
|
-
"SOC 2",
|
|
22732
|
-
"Data Processing Agreement (DPA)",
|
|
22733
|
-
"SCIM user provisioning",
|
|
22734
|
-
"Custom security and privacy settings"
|
|
22735
|
-
]
|
|
22736
|
-
}
|
|
22737
|
-
};
|
|
22738
|
-
var TEAM_PLAN = PLANS.team;
|
|
22739
|
-
var ENTERPRISE_PLAN = PLANS.enterprise;
|
|
22614
|
+
// ../shared/src/chat-fork.ts
|
|
22615
|
+
var quotaLimitKindSchema = external_exports.enum(["rate_limit", "out_of_credits"]);
|
|
22616
|
+
var chatForkInfoSchema = external_exports.object({
|
|
22617
|
+
source: external_exports.object({
|
|
22618
|
+
chatId: external_exports.string().min(1),
|
|
22619
|
+
provider: external_exports.enum(VALID_AGENT_PROVIDERS),
|
|
22620
|
+
title: external_exports.string()
|
|
22621
|
+
}),
|
|
22622
|
+
trigger: external_exports.enum(["manual", "auto"]),
|
|
22623
|
+
reason: quotaLimitKindSchema.optional(),
|
|
22624
|
+
state: external_exports.enum(["preparing", "ready", "failed"]),
|
|
22625
|
+
error: external_exports.string().optional(),
|
|
22626
|
+
startedAt: external_exports.string(),
|
|
22627
|
+
completedAt: external_exports.string().optional()
|
|
22628
|
+
});
|
|
22629
|
+
var forkChatRequestSchema = external_exports.object({
|
|
22630
|
+
provider: external_exports.enum(VALID_AGENT_PROVIDERS),
|
|
22631
|
+
model: external_exports.string().min(1).optional(),
|
|
22632
|
+
thinkingLevel: external_exports.enum(VALID_THINKING_LEVELS).optional(),
|
|
22633
|
+
title: external_exports.string().min(1).max(200).optional(),
|
|
22634
|
+
id: external_exports.string().uuid().optional(),
|
|
22635
|
+
clientRequestId: external_exports.string().min(1).max(128).optional(),
|
|
22636
|
+
enableInteractiveTools: external_exports.boolean().optional(),
|
|
22637
|
+
// Server-injected by the monolith from the authenticated request; never trusted from clients.
|
|
22638
|
+
senderUserId: external_exports.string().optional(),
|
|
22639
|
+
senderEmail: external_exports.string().optional(),
|
|
22640
|
+
senderDisplayName: external_exports.string().optional(),
|
|
22641
|
+
senderAvatarUrl: external_exports.string().optional()
|
|
22642
|
+
});
|
|
22643
|
+
var chatForkFallbackResponseSchema = external_exports.object({
|
|
22644
|
+
provider: external_exports.enum(VALID_AGENT_PROVIDERS).nullable(),
|
|
22645
|
+
model: external_exports.string().min(1).optional(),
|
|
22646
|
+
thinkingLevel: external_exports.enum(VALID_THINKING_LEVELS).optional()
|
|
22647
|
+
});
|
|
22648
|
+
var agentQuotaExhaustedPayloadSchema = external_exports.object({
|
|
22649
|
+
provider: external_exports.enum(VALID_CODING_AGENT_PROVIDERS),
|
|
22650
|
+
reason: quotaLimitKindSchema,
|
|
22651
|
+
detail: external_exports.string().optional()
|
|
22652
|
+
});
|
|
22740
22653
|
|
|
22741
|
-
// ../shared/src/
|
|
22742
|
-
|
|
22743
|
-
|
|
22654
|
+
// ../shared/src/analytics/types.ts
|
|
22655
|
+
var agentCredentialSnapshotSchema = external_exports.object({
|
|
22656
|
+
method: external_exports.enum(CREDENTIAL_METHOD),
|
|
22657
|
+
scope: external_exports.enum(CREDENTIAL_SCOPE),
|
|
22658
|
+
revision: external_exports.string().optional()
|
|
22659
|
+
});
|
|
22660
|
+
function isAuthMethod(value) {
|
|
22661
|
+
return typeof value === "string" && Object.values(CREDENTIAL_METHOD).some((method) => method === value);
|
|
22744
22662
|
}
|
|
22745
|
-
function
|
|
22746
|
-
|
|
22747
|
-
const portNumber = Number(port);
|
|
22748
|
-
if (!isValidPort(portNumber)) throw new Error("Port must be a number between 1 and 65535");
|
|
22749
|
-
return portNumber;
|
|
22663
|
+
function isCredentialScope(value) {
|
|
22664
|
+
return typeof value === "string" && CREDENTIAL_SCOPES.some((scope) => scope === value);
|
|
22750
22665
|
}
|
|
22751
22666
|
|
|
22752
|
-
// ../shared/src/
|
|
22753
|
-
var
|
|
22754
|
-
|
|
22755
|
-
|
|
22756
|
-
|
|
22757
|
-
|
|
22758
|
-
|
|
22759
|
-
|
|
22760
|
-
|
|
22761
|
-
|
|
22762
|
-
|
|
22763
|
-
|
|
22764
|
-
|
|
22765
|
-
}
|
|
22766
|
-
|
|
22767
|
-
}
|
|
22768
|
-
|
|
22769
|
-
|
|
22770
|
-
var
|
|
22771
|
-
|
|
22772
|
-
|
|
22773
|
-
|
|
22774
|
-
|
|
22775
|
-
};
|
|
22776
|
-
|
|
22777
|
-
|
|
22778
|
-
|
|
22779
|
-
|
|
22780
|
-
|
|
22781
|
-
|
|
22782
|
-
|
|
22783
|
-
}
|
|
22784
|
-
|
|
22785
|
-
|
|
22667
|
+
// ../shared/src/event.ts
|
|
22668
|
+
var CLAUDE_PARTIAL_MESSAGE_EVENT_TYPE = "claude-partial-message";
|
|
22669
|
+
function coerceClaudePartialMessagePayload(payload) {
|
|
22670
|
+
const streamId = payload.streamId;
|
|
22671
|
+
if (typeof streamId !== "string" || !streamId) return null;
|
|
22672
|
+
const parentToolUseId = payload.parent_tool_use_id;
|
|
22673
|
+
const text = typeof payload.text === "string" && payload.text ? payload.text : void 0;
|
|
22674
|
+
const thinking = typeof payload.thinking === "string" && payload.thinking ? payload.thinking : void 0;
|
|
22675
|
+
if (!text && !thinking) return null;
|
|
22676
|
+
return {
|
|
22677
|
+
streamId,
|
|
22678
|
+
parent_tool_use_id: typeof parentToolUseId === "string" ? parentToolUseId : null,
|
|
22679
|
+
...text ? { text } : {},
|
|
22680
|
+
...thinking ? { thinking } : {},
|
|
22681
|
+
status: payload.status === "completed" ? "completed" : "in_progress"
|
|
22682
|
+
};
|
|
22683
|
+
}
|
|
22684
|
+
var USER_MESSAGE_ID_PAYLOAD_KEY = "replicasMessageId";
|
|
22685
|
+
var CODEX_ASP_ITEM_ID_PAYLOAD_KEY = "codexAspItemId";
|
|
22686
|
+
var CODEX_QUOTA_STATUS_EVENT_TYPE = "codex-quota-status";
|
|
22687
|
+
var CHAT_INTERRUPTED_EVENT_TYPE = "replicas-interrupted";
|
|
22688
|
+
var AUTH_FALLBACK_EVENT_TYPE = "auth-fallback";
|
|
22689
|
+
function coerceAuthFallbackPayload(payload) {
|
|
22690
|
+
const { provider, reason, exhaustedMethod, exhaustedScope, candidateMethod, candidateScope, status, detail } = payload;
|
|
22691
|
+
if (typeof provider !== "string" || !isValidCodingAgentProvider(provider) || reason !== "rate_limit" && reason !== "out_of_credits" || !isAuthMethod(exhaustedMethod) || !isAuthMethod(candidateMethod) || !isCredentialScope(candidateScope) || status !== "switched" && status !== "failed") {
|
|
22692
|
+
return null;
|
|
22693
|
+
}
|
|
22694
|
+
return {
|
|
22695
|
+
provider,
|
|
22696
|
+
reason,
|
|
22697
|
+
exhaustedMethod,
|
|
22698
|
+
...isCredentialScope(exhaustedScope) ? { exhaustedScope } : {},
|
|
22699
|
+
candidateMethod,
|
|
22700
|
+
candidateScope,
|
|
22701
|
+
status,
|
|
22702
|
+
...typeof detail === "string" && detail ? { detail } : {}
|
|
22703
|
+
};
|
|
22704
|
+
}
|
|
22786
22705
|
|
|
22787
|
-
// ../shared/src/
|
|
22788
|
-
var
|
|
22789
|
-
|
|
22790
|
-
|
|
22791
|
-
|
|
22792
|
-
|
|
22793
|
-
|
|
22794
|
-
|
|
22795
|
-
|
|
22796
|
-
|
|
22797
|
-
|
|
22798
|
-
|
|
22799
|
-
|
|
22800
|
-
|
|
22801
|
-
|
|
22802
|
-
|
|
22803
|
-
|
|
22804
|
-
|
|
22805
|
-
|
|
22806
|
-
|
|
22807
|
-
|
|
22808
|
-
|
|
22809
|
-
|
|
22810
|
-
|
|
22811
|
-
|
|
22812
|
-
|
|
22813
|
-
|
|
22814
|
-
|
|
22815
|
-
|
|
22816
|
-
|
|
22817
|
-
|
|
22818
|
-
|
|
22819
|
-
|
|
22820
|
-
|
|
22821
|
-
|
|
22822
|
-
|
|
22823
|
-
|
|
22824
|
-
|
|
22825
|
-
|
|
22826
|
-
|
|
22827
|
-
|
|
22828
|
-
|
|
22829
|
-
|
|
22830
|
-
|
|
22831
|
-
|
|
22832
|
-
|
|
22833
|
-
|
|
22834
|
-
|
|
22835
|
-
|
|
22836
|
-
|
|
22837
|
-
|
|
22838
|
-
|
|
22839
|
-
|
|
22840
|
-
|
|
22841
|
-
|
|
22842
|
-
|
|
22843
|
-
|
|
22844
|
-
|
|
22845
|
-
|
|
22846
|
-
|
|
22847
|
-
|
|
22848
|
-
UP_SCRIPT: "/usr/local/lib/replicas-egress-up",
|
|
22849
|
-
DOWN_SCRIPT: "/usr/local/lib/replicas-egress-down"
|
|
22850
|
-
};
|
|
22851
|
-
var EGRESS_WORKSPACE_CONFIG_FILE = "/opt/replicas/egress-config.env";
|
|
22852
|
-
var EGRESS_WORKSPACE_SHELL_VARS = {
|
|
22853
|
-
EGRESS_WORKSPACE_CONFIG_FILE,
|
|
22854
|
-
EGRESS_TUNNEL_SERVICE,
|
|
22855
|
-
EGRESS_TUNNEL_INTERFACE,
|
|
22856
|
-
EGRESS_DNS_SERVERS: EGRESS_DNS_SERVERS.join(" "),
|
|
22857
|
-
EGRESS_EXIT_IP_ENDPOINTS: EGRESS_EXIT_IP_ENDPOINTS.join(" ")
|
|
22858
|
-
};
|
|
22706
|
+
// ../shared/src/engine/v1.ts
|
|
22707
|
+
var createChatRequestSchema = external_exports.object({
|
|
22708
|
+
id: external_exports.string().uuid().optional(),
|
|
22709
|
+
createdAt: external_exports.string().datetime().optional(),
|
|
22710
|
+
provider: external_exports.enum(VALID_AGENT_PROVIDERS),
|
|
22711
|
+
title: external_exports.string().min(1).optional(),
|
|
22712
|
+
parentChatId: external_exports.string().uuid().optional(),
|
|
22713
|
+
clientRequestId: external_exports.string().min(1).max(128).optional()
|
|
22714
|
+
});
|
|
22715
|
+
var sendChatMessageRequestSchema = external_exports.object({
|
|
22716
|
+
messageId: external_exports.string().min(1).optional(),
|
|
22717
|
+
submittedAt: external_exports.string().datetime().optional(),
|
|
22718
|
+
message: external_exports.string().min(1),
|
|
22719
|
+
model: external_exports.string().optional(),
|
|
22720
|
+
customInstructions: external_exports.string().optional(),
|
|
22721
|
+
planMode: external_exports.boolean().optional(),
|
|
22722
|
+
images: external_exports.array(external_exports.object({
|
|
22723
|
+
type: external_exports.literal("image"),
|
|
22724
|
+
source: external_exports.discriminatedUnion("type", [
|
|
22725
|
+
external_exports.object({ type: external_exports.literal("base64"), media_type: external_exports.enum(IMAGE_MEDIA_TYPES), data: external_exports.string().min(1) }),
|
|
22726
|
+
external_exports.object({ type: external_exports.literal("url"), url: external_exports.string().url() })
|
|
22727
|
+
])
|
|
22728
|
+
})).optional(),
|
|
22729
|
+
canvasUploadIds: external_exports.array(external_exports.string().min(1)).optional(),
|
|
22730
|
+
thinkingLevel: external_exports.enum(VALID_THINKING_LEVELS).optional(),
|
|
22731
|
+
goalMode: external_exports.boolean().optional(),
|
|
22732
|
+
fastMode: external_exports.boolean().optional(),
|
|
22733
|
+
enableInteractiveTools: external_exports.boolean().optional(),
|
|
22734
|
+
type: external_exports.string().min(1).optional(),
|
|
22735
|
+
merge: external_exports.boolean().optional(),
|
|
22736
|
+
idempotencyKey: external_exports.string().min(1).max(128).optional(),
|
|
22737
|
+
automationId: external_exports.string().optional(),
|
|
22738
|
+
environmentId: external_exports.string().min(1).optional(),
|
|
22739
|
+
senderUserId: external_exports.string().optional(),
|
|
22740
|
+
senderEmail: external_exports.string().optional(),
|
|
22741
|
+
senderDisplayName: external_exports.string().optional(),
|
|
22742
|
+
senderAvatarUrl: external_exports.string().optional(),
|
|
22743
|
+
errorNotificationTarget: external_exports.discriminatedUnion("type", [
|
|
22744
|
+
external_exports.object({ type: external_exports.literal("slack") }),
|
|
22745
|
+
external_exports.object({ type: external_exports.literal("linear"), sessionId: external_exports.string().min(1) }),
|
|
22746
|
+
external_exports.object({
|
|
22747
|
+
type: external_exports.literal("code_host"),
|
|
22748
|
+
provider: external_exports.enum(["github", "gitlab"]),
|
|
22749
|
+
resource: external_exports.enum(["issue", "pull_request"]),
|
|
22750
|
+
repositoryId: external_exports.string().min(1),
|
|
22751
|
+
resourceNumber: external_exports.number().int().positive()
|
|
22752
|
+
}),
|
|
22753
|
+
external_exports.object({ type: external_exports.literal("automation"), executionId: external_exports.string().min(1) })
|
|
22754
|
+
]).optional()
|
|
22755
|
+
}).passthrough();
|
|
22756
|
+
function normalizeCodexAspTranscriptStatus(status, failed = false) {
|
|
22757
|
+
if (failed || status === "failed" || status === "declined") return "failed";
|
|
22758
|
+
if (status === "completed") return "completed";
|
|
22759
|
+
return "in_progress";
|
|
22760
|
+
}
|
|
22761
|
+
function getCodexAspTurnResponse(turn) {
|
|
22762
|
+
const finalAnswer = turn.items.find((item) => item.type === "agentMessage" && item.phase === "final_answer");
|
|
22763
|
+
if (finalAnswer) return finalAnswer;
|
|
22764
|
+
if (normalizeCodexAspTranscriptStatus(turn.status) === "in_progress") return null;
|
|
22765
|
+
return turn.items.findLast((item) => item.type === "agentMessage") ?? null;
|
|
22766
|
+
}
|
|
22859
22767
|
|
|
22860
|
-
// ../shared/src/
|
|
22861
|
-
var
|
|
22862
|
-
|
|
22863
|
-
|
|
22864
|
-
|
|
22865
|
-
|
|
22866
|
-
|
|
22867
|
-
|
|
22868
|
-
|
|
22869
|
-
environment: `${HOME_PATH}/environment`,
|
|
22870
|
-
analytics: `${HOME_PATH}/analytics`,
|
|
22871
|
-
memory: `${HOME_PATH}/memory`,
|
|
22872
|
-
dashboard: DASHBOARD_PATH,
|
|
22873
|
-
agents: `${DASHBOARD_PATH}/agents`,
|
|
22874
|
-
integrations: `${DASHBOARD_PATH}/integrations`,
|
|
22875
|
-
integrationsGithub: `${DASHBOARD_PATH}/integrations/github`,
|
|
22876
|
-
integrationsGitlab: `${DASHBOARD_PATH}/integrations/gitlab`,
|
|
22877
|
-
settings: `${DASHBOARD_PATH}/settings`,
|
|
22878
|
-
billing: `${DASHBOARD_PATH}/billing`,
|
|
22879
|
-
members: `${DASHBOARD_PATH}/members`,
|
|
22880
|
-
"audit-logs": `${DASHBOARD_PATH}/audit-logs`,
|
|
22881
|
-
accountAgents: `${DASHBOARD_PATH}/account/agents`,
|
|
22882
|
-
accountProfile: `${DASHBOARD_PATH}/account/profile`,
|
|
22883
|
-
accountConnections: `${DASHBOARD_PATH}/account/connections`,
|
|
22884
|
-
accountIntegrations: `${DASHBOARD_PATH}/account/integrations`,
|
|
22885
|
-
accountApiKeys: `${DASHBOARD_PATH}/account/api-keys`,
|
|
22886
|
-
accountPreferences: `${DASHBOARD_PATH}/account/preferences`,
|
|
22887
|
-
fullscreenWorkspaces: "/workspaces"
|
|
22888
|
-
};
|
|
22889
|
-
var LEGACY_WEB_APP_PATHS = {
|
|
22890
|
-
app: "/app",
|
|
22891
|
-
dashboardWorkspaces: `${DASHBOARD_PATH}/workspaces`
|
|
22892
|
-
};
|
|
22893
|
-
function getWorkspaceDashboardUrl(workspaceId, options = {}) {
|
|
22894
|
-
const { encodeWorkspaceId = true, mode, mediaId } = options;
|
|
22895
|
-
const workspaceIdValue = encodeWorkspaceId ? encodeURIComponent(workspaceId) : workspaceId;
|
|
22896
|
-
const params = [];
|
|
22897
|
-
if (mode) params.push(`mode=${encodeURIComponent(mode)}`);
|
|
22898
|
-
if (mediaId) params.push(`media=${encodeURIComponent(mediaId)}`);
|
|
22899
|
-
const query = params.length > 0 ? `?${params.join("&")}` : "";
|
|
22900
|
-
return `${DEFAULT_WEB_APP_URL}${WEB_APP_PATHS.fullscreenWorkspaces}/${workspaceIdValue}${query}`;
|
|
22768
|
+
// ../shared/src/display-message/types.ts
|
|
22769
|
+
var BACKGROUND_TASK_SUBTYPES = /* @__PURE__ */ new Set([
|
|
22770
|
+
"task_started",
|
|
22771
|
+
"task_progress",
|
|
22772
|
+
"task_updated",
|
|
22773
|
+
"task_notification"
|
|
22774
|
+
]);
|
|
22775
|
+
function isBackgroundTaskSubtype(subtype) {
|
|
22776
|
+
return typeof subtype === "string" && BACKGROUND_TASK_SUBTYPES.has(subtype);
|
|
22901
22777
|
}
|
|
22902
|
-
function
|
|
22903
|
-
return
|
|
22778
|
+
function optionalString(value) {
|
|
22779
|
+
return typeof value === "string" ? value : void 0;
|
|
22904
22780
|
}
|
|
22905
|
-
function
|
|
22906
|
-
|
|
22781
|
+
function coerceBackgroundTaskPayload(payload) {
|
|
22782
|
+
if (!isRecord(payload)) return null;
|
|
22783
|
+
const subtype = payload.subtype;
|
|
22784
|
+
if (!isBackgroundTaskSubtype(subtype)) return null;
|
|
22785
|
+
const taskId = payload.task_id;
|
|
22786
|
+
if (typeof taskId !== "string" || !taskId) return null;
|
|
22787
|
+
const patch = isRecord(payload.patch) ? {
|
|
22788
|
+
status: optionalString(payload.patch.status),
|
|
22789
|
+
description: optionalString(payload.patch.description),
|
|
22790
|
+
error: optionalString(payload.patch.error),
|
|
22791
|
+
isBackgrounded: optionalBoolean(payload.patch.is_backgrounded)
|
|
22792
|
+
} : void 0;
|
|
22793
|
+
const usage = isRecord(payload.usage) ? {
|
|
22794
|
+
totalTokens: optionalNumber(payload.usage.total_tokens),
|
|
22795
|
+
toolUses: optionalNumber(payload.usage.tool_uses),
|
|
22796
|
+
durationMs: optionalNumber(payload.usage.duration_ms)
|
|
22797
|
+
} : void 0;
|
|
22798
|
+
return {
|
|
22799
|
+
subtype,
|
|
22800
|
+
taskId,
|
|
22801
|
+
description: optionalString(payload.description),
|
|
22802
|
+
summary: optionalString(payload.summary),
|
|
22803
|
+
outputFile: optionalString(payload.output_file),
|
|
22804
|
+
status: optionalString(payload.status),
|
|
22805
|
+
taskType: optionalString(payload.task_type),
|
|
22806
|
+
workflowName: optionalString(payload.workflow_name),
|
|
22807
|
+
prompt: optionalString(payload.prompt),
|
|
22808
|
+
lastToolName: optionalString(payload.last_tool_name),
|
|
22809
|
+
usage,
|
|
22810
|
+
ambient: optionalBoolean(payload.ambient),
|
|
22811
|
+
patch
|
|
22812
|
+
};
|
|
22813
|
+
}
|
|
22814
|
+
function optionalNumber(value) {
|
|
22815
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
22816
|
+
}
|
|
22817
|
+
function optionalBoolean(value) {
|
|
22818
|
+
return typeof value === "boolean" ? value : void 0;
|
|
22819
|
+
}
|
|
22820
|
+
function normalizeBackgroundTaskStatus(status) {
|
|
22821
|
+
if (status === "completed" || status === "failed" || status === "stopped") {
|
|
22822
|
+
return status;
|
|
22823
|
+
}
|
|
22824
|
+
if (status === "killed") {
|
|
22825
|
+
return "stopped";
|
|
22826
|
+
}
|
|
22827
|
+
return "in_progress";
|
|
22907
22828
|
}
|
|
22908
22829
|
|
|
22909
|
-
// ../shared/src/
|
|
22910
|
-
var
|
|
22911
|
-
Drive the workspace's Linux desktop - open a browser, click, type, scroll, screenshot, record - via the \`replicas computer\` CLI. Every Replicas workspace boots with a live H.264 and Opus stream published as an authenticated preview, so a \`Desktop\` tab is always available in the dashboard. Use \`replicas computer info\` to get the viewer URL when you want to share it (e.g. point a user on Slack at the live stream).
|
|
22912
|
-
|
|
22913
|
-
**Reference:** \`references/COMPUTER-USE.md\`
|
|
22914
|
-
|
|
22915
|
-
Use this when:
|
|
22916
|
-
- A task requires interacting with a website, web app, or desktop application that has no usable API
|
|
22917
|
-
- You want the user to watch the agent work - they can open the \`Desktop\` tab, or you can share the URL from \`replicas computer info\`
|
|
22918
|
-
- You're testing UI changes in a browser before reporting them as done
|
|
22919
|
-
- You want to record a screen capture of a task as proof to share back`;
|
|
22920
|
-
var REFERENCE = `# Computer use (Linux desktop control)
|
|
22921
|
-
|
|
22922
|
-
Every Replicas workspace boots with a full Linux desktop stack - Xvfb (1920\xD71080), openbox, tint2, PulseAudio, ffmpeg, and Google Chrome. The engine auto-registers the H.264 and Opus viewer (port 6080) as an authenticated preview at startup, so the dashboard \`Desktop\` tab is live the moment the workspace is up. You drive the desktop through the \`replicas computer\` CLI.
|
|
22923
|
-
|
|
22924
|
-
Use this for anything the user can't reasonably do via an API - clicking around web apps, filling forms, testing UI changes, dragging files between desktop apps, recording a walkthrough.
|
|
22925
|
-
|
|
22926
|
-
## When to use it
|
|
22927
|
-
|
|
22928
|
-
- **Prefer real APIs first.** If a task has a CLI or HTTP API (GitHub, Linear, Slack, Replicas itself), use that. Driving a UI is slower, flakier, and less auditable.
|
|
22929
|
-
- **Use it when there's no API**: testing a frontend you just changed, navigating a vendor portal, demonstrating a flow on video.
|
|
22930
|
-
- **Use it when the user wants to watch.** The dashboard already shows a \`Desktop\` tab. If you're talking to the user somewhere else (e.g. Slack), call \`replicas computer info\` to get the viewer URL and paste it in.
|
|
22931
|
-
|
|
22932
|
-
## Never use raw \`xdotool\` / \`scrot\` / \`ffmpeg\` directly
|
|
22933
|
-
|
|
22934
|
-
The CLI is the canonical surface. Chat transcripts that show \`DISPLAY=:99 xdotool key Return\` are noisy and break when the underlying stack changes. Always call the CLI:
|
|
22935
|
-
|
|
22936
|
-
\`\`\`bash
|
|
22937
|
-
# DO
|
|
22938
|
-
replicas computer key Return
|
|
22939
|
-
replicas computer observe /tmp/state.png
|
|
22940
|
-
|
|
22941
|
-
# DON'T
|
|
22942
|
-
DISPLAY=:99 xdotool key Return
|
|
22943
|
-
scrot /tmp/state.png
|
|
22944
|
-
\`\`\`
|
|
22830
|
+
// ../shared/src/display-message/constants.ts
|
|
22831
|
+
var USER_MESSAGE_MATCH_GRACE_PERIOD_MS = 3e4;
|
|
22945
22832
|
|
|
22946
|
-
|
|
22833
|
+
// ../shared/src/json.ts
|
|
22834
|
+
function safeJsonParse(str, fallback) {
|
|
22835
|
+
try {
|
|
22836
|
+
return JSON.parse(str);
|
|
22837
|
+
} catch {
|
|
22838
|
+
return fallback;
|
|
22839
|
+
}
|
|
22840
|
+
}
|
|
22947
22841
|
|
|
22948
|
-
|
|
22949
|
-
|
|
22950
|
-
|
|
22951
|
-
|
|
22952
|
-
|
|
22842
|
+
// ../shared/src/display-message/parsers/utils.ts
|
|
22843
|
+
var INTERRUPTED_MESSAGE_REGEX = /^\[Request interrupted by user.*\]$/;
|
|
22844
|
+
function userMessageImages(value) {
|
|
22845
|
+
if (!Array.isArray(value)) return void 0;
|
|
22846
|
+
const images = value.filter((item) => isRecord(item) && item.type === "image" && typeof item.mediaType === "string" && typeof item.data === "string");
|
|
22847
|
+
return images.length > 0 ? images : void 0;
|
|
22848
|
+
}
|
|
22849
|
+
function stringifyDisplayValue(value) {
|
|
22850
|
+
if (value === void 0 || value === null) return void 0;
|
|
22851
|
+
if (typeof value === "string") return value;
|
|
22852
|
+
try {
|
|
22853
|
+
return JSON.stringify(value, null, 2);
|
|
22854
|
+
} catch {
|
|
22855
|
+
return String(value);
|
|
22856
|
+
}
|
|
22857
|
+
}
|
|
22858
|
+
function upsertDisplayMessage(messages, message) {
|
|
22859
|
+
const index = messages.findIndex((candidate) => candidate.id === message.id);
|
|
22860
|
+
if (index === -1) messages.push(message);
|
|
22861
|
+
else messages[index] = message;
|
|
22862
|
+
}
|
|
22863
|
+
function applyToolInputEvent(event, messages, provider, state, questionFilter) {
|
|
22864
|
+
if (event.type === "replicas-tool-input-request" && typeof event.payload.toolUseId === "string" && typeof event.payload.requestId === "string" && (Array.isArray(event.payload.options) || Array.isArray(event.payload.questions))) {
|
|
22865
|
+
const resolved = state.resolutions.get(event.payload.toolUseId);
|
|
22866
|
+
const inputRequest = {
|
|
22867
|
+
requestId: event.payload.requestId,
|
|
22868
|
+
status: resolved?.selectionId === "aborted" || resolved?.selectionId === "declined" ? "aborted" : resolved ? "resolved" : "pending",
|
|
22869
|
+
...Array.isArray(event.payload.options) ? { options: event.payload.options } : {},
|
|
22870
|
+
...Array.isArray(event.payload.questions) ? { questions: questionFilter ? event.payload.questions.filter(questionFilter) : event.payload.questions } : {},
|
|
22871
|
+
...resolved ? { selectionId: resolved.selectionId } : {},
|
|
22872
|
+
...resolved?.selectionSummary ? { selectionSummary: resolved.selectionSummary } : {}
|
|
22873
|
+
};
|
|
22874
|
+
state.requests.set(event.payload.toolUseId, inputRequest);
|
|
22875
|
+
const message = messages.find((candidate) => candidate.type === "tool_call" && candidate.id === `${provider}-tool-${event.payload.toolUseId}`);
|
|
22876
|
+
if (message) message.inputRequest = inputRequest;
|
|
22877
|
+
return true;
|
|
22878
|
+
}
|
|
22879
|
+
if (event.type === "replicas-tool-input-resolved" && typeof event.payload.toolUseId === "string" && typeof event.payload.selectionId === "string") {
|
|
22880
|
+
const resolved = {
|
|
22881
|
+
selectionId: event.payload.selectionId,
|
|
22882
|
+
...typeof event.payload.selectionSummary === "string" ? { selectionSummary: event.payload.selectionSummary } : {}
|
|
22883
|
+
};
|
|
22884
|
+
state.resolutions.set(event.payload.toolUseId, resolved);
|
|
22885
|
+
const inputRequest = state.requests.get(event.payload.toolUseId);
|
|
22886
|
+
if (inputRequest) {
|
|
22887
|
+
inputRequest.status = resolved.selectionId === "aborted" || resolved.selectionId === "declined" ? "aborted" : "resolved";
|
|
22888
|
+
inputRequest.selectionId = resolved.selectionId;
|
|
22889
|
+
if (resolved.selectionSummary) inputRequest.selectionSummary = resolved.selectionSummary;
|
|
22890
|
+
}
|
|
22891
|
+
return true;
|
|
22892
|
+
}
|
|
22893
|
+
return false;
|
|
22894
|
+
}
|
|
22895
|
+
function parseSkillName(tool, input) {
|
|
22896
|
+
if (typeof tool !== "string") return null;
|
|
22897
|
+
const normalizedTool = tool.toLowerCase();
|
|
22898
|
+
if (normalizedTool.startsWith("skill.")) return tool.slice("skill.".length) || null;
|
|
22899
|
+
if (normalizedTool !== "skill") return null;
|
|
22900
|
+
const parsedInput = typeof input === "string" ? safeJsonParse(input, null) : input;
|
|
22901
|
+
if (!isRecord(parsedInput)) return null;
|
|
22902
|
+
const skillName = parsedInput.skill ?? parsedInput.name;
|
|
22903
|
+
return typeof skillName === "string" && skillName ? skillName : null;
|
|
22904
|
+
}
|
|
22905
|
+
function skillNameFromFilePath(path6) {
|
|
22906
|
+
const skillName = skillNameFromSkillRootPath(path6);
|
|
22907
|
+
if (skillName) return skillName;
|
|
22908
|
+
const parts = path6.split(/[\\/]+/).filter(Boolean);
|
|
22909
|
+
if (parts.length < 2 || parts[parts.length - 1].toLowerCase() !== "skill.md") return null;
|
|
22910
|
+
const fallbackSkillName = parts[parts.length - 2];
|
|
22911
|
+
return fallbackSkillName && fallbackSkillName.toLowerCase() !== "skills" ? fallbackSkillName : null;
|
|
22912
|
+
}
|
|
22913
|
+
function skillNameFromSkillRootPath(path6) {
|
|
22914
|
+
const parts = path6.split(/[\\/]+/).filter(Boolean);
|
|
22915
|
+
const skillsIndex = parts.findLastIndex((part) => part.toLowerCase() === "skills");
|
|
22916
|
+
if (skillsIndex === -1) return null;
|
|
22917
|
+
const firstSkillPart = parts[skillsIndex + 1];
|
|
22918
|
+
const skillName = firstSkillPart?.toLowerCase() === ".system" ? parts[skillsIndex + 2] : firstSkillPart;
|
|
22919
|
+
return skillName && skillName.toLowerCase() !== "skill.md" ? skillName : null;
|
|
22920
|
+
}
|
|
22921
|
+
function parseSkillFilePath(input) {
|
|
22922
|
+
const parsedInput = typeof input === "string" ? safeJsonParse(input, null) : input;
|
|
22923
|
+
if (!isRecord(parsedInput)) return null;
|
|
22924
|
+
const path6 = [parsedInput.path, parsedInput.filePath, parsedInput.file_path].find((value) => typeof value === "string" && value.length > 0);
|
|
22925
|
+
if (!path6) return null;
|
|
22926
|
+
return skillNameFromFilePath(path6);
|
|
22927
|
+
}
|
|
22928
|
+
function skillNameFromToolCall(tool, input) {
|
|
22929
|
+
const directSkillName = parseSkillName(tool, input);
|
|
22930
|
+
if (directSkillName) return directSkillName;
|
|
22931
|
+
if (typeof tool !== "string" || !["read", "read_file", "readfile"].includes(tool.toLowerCase())) return null;
|
|
22932
|
+
return parseSkillFilePath(input);
|
|
22933
|
+
}
|
|
22934
|
+
function createCallDisplayMessage(message) {
|
|
22935
|
+
const skillName = message.server.toLowerCase() === "skills" ? message.tool : skillNameFromToolCall(message.tool, message.input);
|
|
22936
|
+
if (skillName === null) return { ...message, type: "tool_call" };
|
|
22937
|
+
return {
|
|
22938
|
+
id: message.id,
|
|
22939
|
+
type: "skill",
|
|
22940
|
+
skillName,
|
|
22941
|
+
status: message.status,
|
|
22942
|
+
timestamp: message.timestamp
|
|
22943
|
+
};
|
|
22944
|
+
}
|
|
22945
|
+
function insertDisplayMessageByTimestamp(messages, message) {
|
|
22946
|
+
const messageMs = parseTimestampMs(message.timestamp);
|
|
22947
|
+
let index = messages.length;
|
|
22948
|
+
while (index > 0 && parseTimestampMs(messages[index - 1].timestamp) > messageMs) index--;
|
|
22949
|
+
messages.splice(index, 0, message);
|
|
22950
|
+
}
|
|
22953
22951
|
|
|
22954
|
-
|
|
22955
|
-
|
|
22952
|
+
// ../shared/src/display-message/format.ts
|
|
22953
|
+
function unquoteShellArg(value) {
|
|
22954
|
+
const trimmed = value.trim();
|
|
22955
|
+
if (trimmed.length < 2) return trimmed;
|
|
22956
|
+
if (trimmed[0] === "'" && trimmed[trimmed.length - 1] === "'") {
|
|
22957
|
+
return trimmed.slice(1, -1).replace(/'\\''/g, "'");
|
|
22958
|
+
}
|
|
22959
|
+
if (trimmed[0] === '"' && trimmed[trimmed.length - 1] === '"') {
|
|
22960
|
+
return trimmed.slice(1, -1).replace(/\\(["\\$`])/g, "$1");
|
|
22961
|
+
}
|
|
22962
|
+
return trimmed;
|
|
22963
|
+
}
|
|
22964
|
+
function shellPayload(command) {
|
|
22965
|
+
const match = command.trim().match(/^(?:\S*\/)?(?:ba|z|c|fi)?sh\s+-(?:[a-zA-Z]*c[a-zA-Z]*|c)\s+([\s\S]+)$/);
|
|
22966
|
+
return match ? unquoteShellArg(match[1]) : command.trim();
|
|
22967
|
+
}
|
|
22968
|
+
function splitShellWords(command) {
|
|
22969
|
+
const words = [];
|
|
22970
|
+
let word = "";
|
|
22971
|
+
let quote = null;
|
|
22972
|
+
let escaped = false;
|
|
22973
|
+
for (const char of command) {
|
|
22974
|
+
if (escaped) {
|
|
22975
|
+
word += char;
|
|
22976
|
+
escaped = false;
|
|
22977
|
+
continue;
|
|
22978
|
+
}
|
|
22979
|
+
if (char === "\\" && quote !== "'") {
|
|
22980
|
+
escaped = true;
|
|
22981
|
+
continue;
|
|
22982
|
+
}
|
|
22983
|
+
if (quote) {
|
|
22984
|
+
if (char === quote) quote = null;
|
|
22985
|
+
else word += char;
|
|
22986
|
+
continue;
|
|
22987
|
+
}
|
|
22988
|
+
if (char === '"' || char === "'") {
|
|
22989
|
+
quote = char;
|
|
22990
|
+
continue;
|
|
22991
|
+
}
|
|
22992
|
+
if (/\s/.test(char)) {
|
|
22993
|
+
if (word) {
|
|
22994
|
+
words.push(word);
|
|
22995
|
+
word = "";
|
|
22996
|
+
}
|
|
22997
|
+
continue;
|
|
22998
|
+
}
|
|
22999
|
+
word += char;
|
|
23000
|
+
}
|
|
23001
|
+
if (word) words.push(word);
|
|
23002
|
+
return words;
|
|
23003
|
+
}
|
|
23004
|
+
function commandWords(command) {
|
|
23005
|
+
const payload = shellPayload(command);
|
|
23006
|
+
if (!payload || /[;|<>]|&&/.test(payload)) return null;
|
|
23007
|
+
return splitShellWords(payload);
|
|
23008
|
+
}
|
|
23009
|
+
function skillNamesFromCommand(command) {
|
|
23010
|
+
const words = commandWords(command);
|
|
23011
|
+
if (!words) return [];
|
|
23012
|
+
return Array.from(new Set(words.flatMap((word) => {
|
|
23013
|
+
const skillName = skillNameFromSkillRootPath(word);
|
|
23014
|
+
return skillName ? [skillName] : [];
|
|
23015
|
+
})));
|
|
23016
|
+
}
|
|
22956
23017
|
|
|
22957
|
-
|
|
22958
|
-
|
|
23018
|
+
// ../shared/src/urls.ts
|
|
23019
|
+
var DEFAULT_WEB_APP_URL = "https://replicas.dev";
|
|
23020
|
+
var HOME_PATH = "/home";
|
|
23021
|
+
var DASHBOARD_PATH = "/dashboard";
|
|
23022
|
+
var WEB_APP_PATHS = {
|
|
23023
|
+
home: HOME_PATH,
|
|
23024
|
+
onboarding: `${HOME_PATH}/onboarding`,
|
|
23025
|
+
workspaces: `${HOME_PATH}/workspace`,
|
|
23026
|
+
automations: `${HOME_PATH}/automations`,
|
|
23027
|
+
environment: `${HOME_PATH}/environment`,
|
|
23028
|
+
analytics: `${HOME_PATH}/analytics`,
|
|
23029
|
+
memory: `${HOME_PATH}/memory`,
|
|
23030
|
+
dashboard: DASHBOARD_PATH,
|
|
23031
|
+
agents: `${DASHBOARD_PATH}/agents`,
|
|
23032
|
+
integrations: `${DASHBOARD_PATH}/integrations`,
|
|
23033
|
+
integrationsGithub: `${DASHBOARD_PATH}/integrations/github`,
|
|
23034
|
+
integrationsGitlab: `${DASHBOARD_PATH}/integrations/gitlab`,
|
|
23035
|
+
settings: `${DASHBOARD_PATH}/settings`,
|
|
23036
|
+
billing: `${DASHBOARD_PATH}/billing`,
|
|
23037
|
+
members: `${DASHBOARD_PATH}/members`,
|
|
23038
|
+
"audit-logs": `${DASHBOARD_PATH}/audit-logs`,
|
|
23039
|
+
accountAgents: `${DASHBOARD_PATH}/account/agents`,
|
|
23040
|
+
accountProfile: `${DASHBOARD_PATH}/account/profile`,
|
|
23041
|
+
accountConnections: `${DASHBOARD_PATH}/account/connections`,
|
|
23042
|
+
accountIntegrations: `${DASHBOARD_PATH}/account/integrations`,
|
|
23043
|
+
accountApiKeys: `${DASHBOARD_PATH}/account/api-keys`,
|
|
23044
|
+
accountPreferences: `${DASHBOARD_PATH}/account/preferences`,
|
|
23045
|
+
fullscreenWorkspaces: "/workspaces"
|
|
23046
|
+
};
|
|
23047
|
+
var LEGACY_WEB_APP_PATHS = {
|
|
23048
|
+
app: "/app",
|
|
23049
|
+
dashboardWorkspaces: `${DASHBOARD_PATH}/workspaces`
|
|
23050
|
+
};
|
|
23051
|
+
function getWorkspaceDashboardUrl(workspaceId, options = {}) {
|
|
23052
|
+
const { encodeWorkspaceId = true, mode, mediaId } = options;
|
|
23053
|
+
const workspaceIdValue = encodeWorkspaceId ? encodeURIComponent(workspaceId) : workspaceId;
|
|
23054
|
+
const params = [];
|
|
23055
|
+
if (mode) params.push(`mode=${encodeURIComponent(mode)}`);
|
|
23056
|
+
if (mediaId) params.push(`media=${encodeURIComponent(mediaId)}`);
|
|
23057
|
+
const query = params.length > 0 ? `?${params.join("&")}` : "";
|
|
23058
|
+
return `${DEFAULT_WEB_APP_URL}${WEB_APP_PATHS.fullscreenWorkspaces}/${workspaceIdValue}${query}`;
|
|
23059
|
+
}
|
|
23060
|
+
function getOrganizationMediaPath(organizationId, mediaId) {
|
|
23061
|
+
return `/organizations/${encodeURIComponent(organizationId)}/media/${encodeURIComponent(mediaId)}`;
|
|
23062
|
+
}
|
|
23063
|
+
function getOrganizationMediaUrl(organizationId, mediaId, webAppUrl = DEFAULT_WEB_APP_URL) {
|
|
23064
|
+
return `${webAppUrl}${getOrganizationMediaPath(organizationId, mediaId)}`;
|
|
23065
|
+
}
|
|
22959
23066
|
|
|
22960
|
-
|
|
22961
|
-
|
|
22962
|
-
|
|
23067
|
+
// ../shared/src/default-skills/replicas-agent/abilities/computer.ts
|
|
23068
|
+
var SECTION = `### Computer use (Linux desktop control)
|
|
23069
|
+
Drive the workspace's Linux desktop - open a browser, click, type, scroll, screenshot, record - via the \`replicas computer\` CLI. Every Replicas workspace boots with a live H.264 and Opus stream published as an authenticated preview, so a \`Desktop\` tab is always available in the dashboard. Use \`replicas computer info\` to get the viewer URL when you want to share it (e.g. point a user on Slack at the live stream).
|
|
22963
23070
|
|
|
22964
|
-
|
|
22965
|
-
replicas computer record start /tmp/demo.mp4 --fps 60
|
|
22966
|
-
# ... do stuff ...
|
|
22967
|
-
replicas computer record stop
|
|
22968
|
-
replicas media upload /tmp/demo.mp4 --name "Demo recording"
|
|
22969
|
-
\`\`\`
|
|
23071
|
+
**Reference:** \`references/COMPUTER-USE.md\`
|
|
22970
23072
|
|
|
22971
|
-
|
|
23073
|
+
Use this when:
|
|
23074
|
+
- A task requires interacting with a website, web app, or desktop application that has no usable API
|
|
23075
|
+
- You want the user to watch the agent work - they can open the \`Desktop\` tab, or you can share the URL from \`replicas computer info\`
|
|
23076
|
+
- You're testing UI changes in a browser before reporting them as done
|
|
23077
|
+
- You want to record a screen capture of a task as proof to share back`;
|
|
23078
|
+
var REFERENCE = `# Computer use (Linux desktop control)
|
|
22972
23079
|
|
|
22973
|
-
|
|
23080
|
+
Every Replicas workspace boots with a full Linux desktop stack - Xvfb (1920\xD71080), openbox, tint2, PulseAudio, ffmpeg, and Google Chrome. The engine auto-registers the H.264 and Opus viewer (port 6080) as an authenticated preview at startup, so the dashboard \`Desktop\` tab is live the moment the workspace is up. You drive the desktop through the \`replicas computer\` CLI.
|
|
22974
23081
|
|
|
22975
|
-
|
|
22976
|
-
Prints the live desktop viewer URL (\`https://6080-<hash>.replicas.dev/\`). The engine auto-registers this authenticated preview on startup; \`info\` just looks it up. Use it when you want to share the live stream URL with the user out-of-band (e.g. in a Slack reply) - the dashboard \`Desktop\` tab already points at the same URL automatically.
|
|
23082
|
+
Use this for anything the user can't reasonably do via an API - clicking around web apps, filling forms, testing UI changes, dragging files between desktop apps, recording a walkthrough.
|
|
22977
23083
|
|
|
22978
|
-
|
|
23084
|
+
## When to use it
|
|
23085
|
+
|
|
23086
|
+
- **Prefer real APIs first.** If a task has a CLI or HTTP API (GitHub, Linear, Slack, Replicas itself), use that. Driving a UI is slower, flakier, and less auditable.
|
|
23087
|
+
- **Use it when there's no API**: testing a frontend you just changed, navigating a vendor portal, demonstrating a flow on video.
|
|
23088
|
+
- **Use it when the user wants to watch.** The dashboard already shows a \`Desktop\` tab. If you're talking to the user somewhere else (e.g. Slack), call \`replicas computer info\` to get the viewer URL and paste it in.
|
|
23089
|
+
|
|
23090
|
+
## Never use raw \`xdotool\` / \`scrot\` / \`ffmpeg\` directly
|
|
23091
|
+
|
|
23092
|
+
The CLI is the canonical surface. Chat transcripts that show \`DISPLAY=:99 xdotool key Return\` are noisy and break when the underlying stack changes. Always call the CLI:
|
|
23093
|
+
|
|
23094
|
+
\`\`\`bash
|
|
23095
|
+
# DO
|
|
23096
|
+
replicas computer key Return
|
|
23097
|
+
replicas computer observe /tmp/state.png
|
|
23098
|
+
|
|
23099
|
+
# DON'T
|
|
23100
|
+
DISPLAY=:99 xdotool key Return
|
|
23101
|
+
scrot /tmp/state.png
|
|
23102
|
+
\`\`\`
|
|
23103
|
+
|
|
23104
|
+
## Quickstart
|
|
23105
|
+
|
|
23106
|
+
\`\`\`bash
|
|
23107
|
+
# 1) (Optional) Get the live viewer URL so you can share it with the user.
|
|
23108
|
+
# The desktop is already running and the preview is already registered -
|
|
23109
|
+
# this just looks up the URL.
|
|
23110
|
+
replicas computer info
|
|
23111
|
+
|
|
23112
|
+
# 2) Launch a browser on the workspace display.
|
|
23113
|
+
replicas computer launch chrome https://news.ycombinator.com
|
|
23114
|
+
|
|
23115
|
+
# 3) Capture the settled viewport and native accessibility tree together.
|
|
23116
|
+
replicas computer browser-state /tmp/state.png --full
|
|
23117
|
+
|
|
23118
|
+
# 4) Batch actions that use refs from the same state, then capture the semantic diff.
|
|
23119
|
+
replicas computer browser-batch '[{"action":"fill","ref":17,"value":"hello"},{"action":"click","ref":42}]'
|
|
23120
|
+
replicas computer browser-state /tmp/after-click.png
|
|
23121
|
+
|
|
23122
|
+
# 5) (Optional) Record a screencap to share back.
|
|
23123
|
+
replicas computer record start /tmp/demo.mp4 --fps 60
|
|
23124
|
+
# ... do stuff ...
|
|
23125
|
+
replicas computer record stop
|
|
23126
|
+
replicas media upload /tmp/demo.mp4 --name "Demo recording"
|
|
23127
|
+
\`\`\`
|
|
23128
|
+
|
|
23129
|
+
For any external destination, continue with the required delivery flow in \`MEDIA.md\`.
|
|
23130
|
+
|
|
23131
|
+
## Command reference
|
|
23132
|
+
|
|
23133
|
+
### \`replicas computer info\`
|
|
23134
|
+
Prints the live desktop viewer URL (\`https://6080-<hash>.replicas.dev/\`). The engine auto-registers this authenticated preview on startup; \`info\` just looks it up. Use it when you want to share the live stream URL with the user out-of-band (e.g. in a Slack reply) - the dashboard \`Desktop\` tab already points at the same URL automatically.
|
|
23135
|
+
|
|
23136
|
+
If invoked very early in the workspace lifecycle, \`info\` will poll briefly while the engine finishes registering the preview, then error if it's still not available.
|
|
22979
23137
|
|
|
22980
23138
|
### \`replicas computer status\`
|
|
22981
23139
|
Checks and repairs the desktop bridge, then prints which desktop services are running and the active preview URL (if any). Useful for debugging when a tool call seems to be doing nothing.
|
|
@@ -24524,7 +24682,9 @@ var DEFAULT_USER_PREFERENCES = {
|
|
|
24524
24682
|
open_links_in_desktop_app: false,
|
|
24525
24683
|
default_fast_mode: false,
|
|
24526
24684
|
agent_defaults: { ...EMPTY_AGENT_DEFAULT_SETTINGS },
|
|
24527
|
-
credential_priority: null
|
|
24685
|
+
credential_priority: null,
|
|
24686
|
+
chat_fork_fallbacks_enabled: false,
|
|
24687
|
+
chat_fork_fallback_providers: []
|
|
24528
24688
|
};
|
|
24529
24689
|
function defaultReplicasAgentAbilities() {
|
|
24530
24690
|
const abilities = {};
|
|
@@ -24554,980 +24714,24 @@ function removeReplicasInstructions(text) {
|
|
|
24554
24714
|
return removeTag(text, REPLICAS_INSTRUCTIONS_TAG);
|
|
24555
24715
|
}
|
|
24556
24716
|
|
|
24557
|
-
// ../shared/src/
|
|
24558
|
-
|
|
24559
|
-
|
|
24560
|
-
// ../shared/src/warm-hooks.ts
|
|
24561
|
-
var DEFAULT_WARM_HOOK_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
24562
|
-
var MAX_WARM_HOOK_TIMEOUT_MS = 120 * 60 * 1e3;
|
|
24563
|
-
var DEFAULT_START_HOOK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
24564
|
-
var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
24565
|
-
|
|
24566
|
-
// ../shared/src/replicas-config.ts
|
|
24567
|
-
var REPLICAS_CONFIG_FILENAMES = ["replicas.json", "replicas.yaml", "replicas.yml"];
|
|
24568
|
-
|
|
24569
|
-
// ../shared/src/headless-agent.ts
|
|
24570
|
-
var headlessAgentRequestBaseSchema = external_exports.object({
|
|
24571
|
-
agent: external_exports.custom(
|
|
24572
|
-
(value) => typeof value === "string" && isValidCodingAgentProvider(value)
|
|
24573
|
-
),
|
|
24574
|
-
model: external_exports.string().min(1),
|
|
24575
|
-
prompt: external_exports.string(),
|
|
24576
|
-
workingDirectory: external_exports.string().min(1),
|
|
24577
|
-
timeoutSeconds: external_exports.number().int().min(1).max(1800).default(300),
|
|
24578
|
-
codexOauthTokens: external_exports.object({ accessToken: external_exports.string(), accountId: external_exports.string() }).optional()
|
|
24579
|
-
});
|
|
24580
|
-
var headlessAgentInputFileSchema = external_exports.object({
|
|
24581
|
-
path: external_exports.string().min(1),
|
|
24582
|
-
downloadUrl: external_exports.url()
|
|
24583
|
-
});
|
|
24584
|
-
var headlessAgentOutputFileSchema = external_exports.object({
|
|
24585
|
-
path: external_exports.string().min(1),
|
|
24586
|
-
uploadUrl: external_exports.url(),
|
|
24587
|
-
contentType: external_exports.string().min(1),
|
|
24588
|
-
minChars: external_exports.number().int().positive().optional(),
|
|
24589
|
-
maxChars: external_exports.number().int().positive().optional()
|
|
24590
|
-
});
|
|
24591
|
-
var headlessAgentRequestSchema = external_exports.discriminatedUnion("mode", [
|
|
24592
|
-
headlessAgentRequestBaseSchema.extend({
|
|
24593
|
-
mode: external_exports.literal("structured"),
|
|
24594
|
-
outputSchema: external_exports.record(external_exports.string(), external_exports.json())
|
|
24595
|
-
}),
|
|
24596
|
-
headlessAgentRequestBaseSchema.extend({
|
|
24597
|
-
mode: external_exports.literal("filesystem"),
|
|
24598
|
-
inputFiles: external_exports.array(headlessAgentInputFileSchema),
|
|
24599
|
-
outputFiles: external_exports.array(headlessAgentOutputFileSchema),
|
|
24600
|
-
sensitiveValues: external_exports.array(external_exports.string())
|
|
24601
|
-
})
|
|
24602
|
-
]);
|
|
24603
|
-
var headlessFilesystemAgentResultSchema = external_exports.object({
|
|
24604
|
-
message: external_exports.string(),
|
|
24605
|
-
files: external_exports.record(external_exports.string(), external_exports.object({
|
|
24606
|
-
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
24607
|
-
sizeBytes: external_exports.number().int().nonnegative()
|
|
24608
|
-
}))
|
|
24609
|
-
});
|
|
24610
|
-
|
|
24611
|
-
// ../shared/src/errors.ts
|
|
24612
|
-
var TRANSIENT_NETWORK_ERROR_PATTERNS = [
|
|
24613
|
-
/socket connection was closed unexpectedly/,
|
|
24614
|
-
/fetch failed/,
|
|
24615
|
-
/network error/,
|
|
24616
|
-
/network request failed/,
|
|
24617
|
-
/econnreset/,
|
|
24618
|
-
/econnrefused/,
|
|
24619
|
-
/etimedout/,
|
|
24620
|
-
/enotfound/,
|
|
24621
|
-
/eai_again/,
|
|
24622
|
-
/und_err_socket/,
|
|
24623
|
-
/und_err_connect_timeout/,
|
|
24624
|
-
/headers timeout/,
|
|
24625
|
-
/body timeout/,
|
|
24626
|
-
/connection reset/,
|
|
24627
|
-
/connection closed/,
|
|
24628
|
-
/closed unexpectedly/
|
|
24629
|
-
];
|
|
24630
|
-
var HTTP_CONTEXT_PATTERN = /(api error|request|response|status|http)/;
|
|
24631
|
-
var HTTP_STATUS_PATTERN = /(^|[^0-9])([1-5][0-9]{2})(?=$|[^0-9])/g;
|
|
24632
|
-
function isTransientErrorText(text, options = {}) {
|
|
24633
|
-
const normalized = text.toLowerCase();
|
|
24634
|
-
if (!normalized) return false;
|
|
24635
|
-
if (TRANSIENT_NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(normalized))) return true;
|
|
24636
|
-
if (options.includeRateLimit && /rate limit/.test(normalized)) return true;
|
|
24637
|
-
if (options.extraPatterns?.some((pattern) => pattern.test(normalized))) return true;
|
|
24638
|
-
const httpStatuses = new Set(options.httpStatuses ?? []);
|
|
24639
|
-
const httpStatusClasses = new Set(options.httpStatusClasses ?? []);
|
|
24640
|
-
if (httpStatuses.size === 0 && httpStatusClasses.size === 0) return false;
|
|
24641
|
-
if (options.requireHttpContext !== false && !HTTP_CONTEXT_PATTERN.test(normalized)) return false;
|
|
24642
|
-
for (const match of normalized.matchAll(HTTP_STATUS_PATTERN)) {
|
|
24643
|
-
const status = Number(match[2]);
|
|
24644
|
-
if (httpStatuses.has(status) || httpStatusClasses.has(Math.floor(status / 100))) return true;
|
|
24645
|
-
}
|
|
24646
|
-
return false;
|
|
24717
|
+
// ../shared/src/display-message/parsers/codex-parser.ts
|
|
24718
|
+
function getStatusFromExitCode(exitCode) {
|
|
24719
|
+
return exitCode === 0 ? "completed" : "failed";
|
|
24647
24720
|
}
|
|
24648
|
-
|
|
24649
|
-
|
|
24650
|
-
|
|
24651
|
-
|
|
24652
|
-
// ../shared/src/version.ts
|
|
24653
|
-
function compareVersions(v1, v2) {
|
|
24654
|
-
const parts1 = v1.split(".").map(Number);
|
|
24655
|
-
const parts2 = v2.split(".").map(Number);
|
|
24656
|
-
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
24657
|
-
const num1 = parts1[i] || 0;
|
|
24658
|
-
const num2 = parts2[i] || 0;
|
|
24659
|
-
if (num1 > num2) return 1;
|
|
24660
|
-
if (num1 < num2) return -1;
|
|
24661
|
-
}
|
|
24662
|
-
return 0;
|
|
24721
|
+
function getPayloadString(event, key) {
|
|
24722
|
+
const value = event.payload?.[key];
|
|
24723
|
+
return typeof value === "string" ? value : null;
|
|
24663
24724
|
}
|
|
24664
|
-
|
|
24665
|
-
|
|
24666
|
-
|
|
24667
|
-
id: external_exports.string().uuid().optional(),
|
|
24668
|
-
createdAt: external_exports.string().datetime().optional(),
|
|
24669
|
-
provider: external_exports.enum(VALID_AGENT_PROVIDERS),
|
|
24670
|
-
title: external_exports.string().min(1).optional(),
|
|
24671
|
-
parentChatId: external_exports.string().uuid().optional(),
|
|
24672
|
-
clientRequestId: external_exports.string().min(1).max(128).optional()
|
|
24673
|
-
});
|
|
24674
|
-
var sendChatMessageRequestSchema = external_exports.object({
|
|
24675
|
-
messageId: external_exports.string().min(1).optional(),
|
|
24676
|
-
submittedAt: external_exports.string().datetime().optional(),
|
|
24677
|
-
message: external_exports.string().min(1),
|
|
24678
|
-
model: external_exports.string().optional(),
|
|
24679
|
-
customInstructions: external_exports.string().optional(),
|
|
24680
|
-
planMode: external_exports.boolean().optional(),
|
|
24681
|
-
images: external_exports.array(external_exports.object({
|
|
24682
|
-
type: external_exports.literal("image"),
|
|
24683
|
-
source: external_exports.discriminatedUnion("type", [
|
|
24684
|
-
external_exports.object({ type: external_exports.literal("base64"), media_type: external_exports.enum(IMAGE_MEDIA_TYPES), data: external_exports.string().min(1) }),
|
|
24685
|
-
external_exports.object({ type: external_exports.literal("url"), url: external_exports.string().url() })
|
|
24686
|
-
])
|
|
24687
|
-
})).optional(),
|
|
24688
|
-
canvasUploadIds: external_exports.array(external_exports.string().min(1)).optional(),
|
|
24689
|
-
thinkingLevel: external_exports.enum(VALID_THINKING_LEVELS).optional(),
|
|
24690
|
-
goalMode: external_exports.boolean().optional(),
|
|
24691
|
-
fastMode: external_exports.boolean().optional(),
|
|
24692
|
-
enableInteractiveTools: external_exports.boolean().optional(),
|
|
24693
|
-
type: external_exports.string().min(1).optional(),
|
|
24694
|
-
merge: external_exports.boolean().optional(),
|
|
24695
|
-
idempotencyKey: external_exports.string().min(1).max(128).optional(),
|
|
24696
|
-
automationId: external_exports.string().optional(),
|
|
24697
|
-
environmentId: external_exports.string().min(1).optional(),
|
|
24698
|
-
senderUserId: external_exports.string().optional(),
|
|
24699
|
-
senderEmail: external_exports.string().optional(),
|
|
24700
|
-
senderDisplayName: external_exports.string().optional(),
|
|
24701
|
-
senderAvatarUrl: external_exports.string().optional(),
|
|
24702
|
-
errorNotificationTarget: external_exports.discriminatedUnion("type", [
|
|
24703
|
-
external_exports.object({ type: external_exports.literal("slack") }),
|
|
24704
|
-
external_exports.object({ type: external_exports.literal("linear"), sessionId: external_exports.string().min(1) }),
|
|
24705
|
-
external_exports.object({
|
|
24706
|
-
type: external_exports.literal("code_host"),
|
|
24707
|
-
provider: external_exports.enum(["github", "gitlab"]),
|
|
24708
|
-
resource: external_exports.enum(["issue", "pull_request"]),
|
|
24709
|
-
repositoryId: external_exports.string().min(1),
|
|
24710
|
-
resourceNumber: external_exports.number().int().positive()
|
|
24711
|
-
}),
|
|
24712
|
-
external_exports.object({ type: external_exports.literal("automation"), executionId: external_exports.string().min(1) })
|
|
24713
|
-
]).optional()
|
|
24714
|
-
}).passthrough();
|
|
24715
|
-
function normalizeCodexAspTranscriptStatus(status, failed = false) {
|
|
24716
|
-
if (failed || status === "failed" || status === "declined") return "failed";
|
|
24717
|
-
if (status === "completed") return "completed";
|
|
24718
|
-
return "in_progress";
|
|
24725
|
+
function displayId(event, eventIndex, prefix) {
|
|
24726
|
+
const stableId = getPayloadString(event, USER_MESSAGE_ID_PAYLOAD_KEY) ?? getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY);
|
|
24727
|
+
return stableId ? `${prefix}-${stableId}` : `${prefix}-${event.timestamp}-${eventIndex}`;
|
|
24719
24728
|
}
|
|
24720
|
-
function
|
|
24721
|
-
const
|
|
24722
|
-
|
|
24723
|
-
|
|
24724
|
-
|
|
24725
|
-
}
|
|
24726
|
-
|
|
24727
|
-
// ../shared/src/routes/plugin-catalog.ts
|
|
24728
|
-
var EXPLICIT_PLUGIN_CATALOG = [
|
|
24729
|
-
{
|
|
24730
|
-
id: "attio",
|
|
24731
|
-
backend: "composio",
|
|
24732
|
-
toolkit: "attio",
|
|
24733
|
-
authType: "oauth",
|
|
24734
|
-
category: "business",
|
|
24735
|
-
name: "Attio",
|
|
24736
|
-
description: "Manage CRM records, people, companies, lists, and notes."
|
|
24737
|
-
},
|
|
24738
|
-
{
|
|
24739
|
-
id: "calendly",
|
|
24740
|
-
backend: "composio",
|
|
24741
|
-
toolkit: "calendly",
|
|
24742
|
-
authType: "oauth",
|
|
24743
|
-
category: "productivity",
|
|
24744
|
-
name: "Calendly",
|
|
24745
|
-
description: "Manage event types, scheduled events, invitees, and scheduling links."
|
|
24746
|
-
},
|
|
24747
|
-
{
|
|
24748
|
-
id: "clickhouse",
|
|
24749
|
-
backend: "composio",
|
|
24750
|
-
toolkit: "clickhouse",
|
|
24751
|
-
authType: "basic",
|
|
24752
|
-
category: "data",
|
|
24753
|
-
name: "ClickHouse",
|
|
24754
|
-
description: "Manage databases, tables, schemas, and queries."
|
|
24755
|
-
},
|
|
24756
|
-
{
|
|
24757
|
-
id: "cloudflare",
|
|
24758
|
-
backend: "composio",
|
|
24759
|
-
toolkit: "cloudflare_api_key",
|
|
24760
|
-
authType: "api_key",
|
|
24761
|
-
category: "data",
|
|
24762
|
-
name: "Cloudflare",
|
|
24763
|
-
description: "Manage zones, DNS records, analytics, and security settings."
|
|
24764
|
-
},
|
|
24765
|
-
{
|
|
24766
|
-
id: "e2b",
|
|
24767
|
-
toolkit: "e2b",
|
|
24768
|
-
backend: "native",
|
|
24769
|
-
authType: "api_key",
|
|
24770
|
-
category: "data",
|
|
24771
|
-
name: "E2B",
|
|
24772
|
-
description: "Create secure cloud sandboxes and run commands in them."
|
|
24773
|
-
},
|
|
24774
|
-
{
|
|
24775
|
-
id: "gmail",
|
|
24776
|
-
backend: "composio",
|
|
24777
|
-
toolkit: "gmail",
|
|
24778
|
-
authType: "oauth",
|
|
24779
|
-
category: "productivity",
|
|
24780
|
-
name: "Gmail",
|
|
24781
|
-
description: "Manage messages, threads, attachments, labels, and mailbox settings."
|
|
24782
|
-
},
|
|
24783
|
-
{
|
|
24784
|
-
id: "googleads",
|
|
24785
|
-
backend: "composio",
|
|
24786
|
-
toolkit: "googleads",
|
|
24787
|
-
authType: "oauth",
|
|
24788
|
-
category: "data",
|
|
24789
|
-
name: "Google Ads",
|
|
24790
|
-
description: "Manage campaigns, customers, accounts, and reporting data."
|
|
24791
|
-
},
|
|
24792
|
-
{
|
|
24793
|
-
id: "googledocs",
|
|
24794
|
-
backend: "composio",
|
|
24795
|
-
toolkit: "googledocs",
|
|
24796
|
-
authType: "oauth",
|
|
24797
|
-
category: "productivity",
|
|
24798
|
-
name: "Google Docs",
|
|
24799
|
-
description: "Manage documents, structure, comments, and exported content."
|
|
24800
|
-
},
|
|
24801
|
-
{
|
|
24802
|
-
id: "googledrive",
|
|
24803
|
-
backend: "composio",
|
|
24804
|
-
toolkit: "googledrive",
|
|
24805
|
-
authType: "oauth",
|
|
24806
|
-
category: "productivity",
|
|
24807
|
-
name: "Google Drive",
|
|
24808
|
-
description: "Manage files, folders, metadata, permissions, and shared drives."
|
|
24809
|
-
},
|
|
24810
|
-
{
|
|
24811
|
-
id: "googlesearch",
|
|
24812
|
-
backend: "composio",
|
|
24813
|
-
toolkit: "google_search_console",
|
|
24814
|
-
authType: "oauth",
|
|
24815
|
-
category: "data",
|
|
24816
|
-
name: "Google Search",
|
|
24817
|
-
description: "Manage Search Console performance, indexing, sites, and sitemaps."
|
|
24818
|
-
},
|
|
24819
|
-
{
|
|
24820
|
-
id: "googlesheets",
|
|
24821
|
-
backend: "composio",
|
|
24822
|
-
toolkit: "googlesheets",
|
|
24823
|
-
authType: "oauth",
|
|
24824
|
-
category: "productivity",
|
|
24825
|
-
name: "Google Sheets",
|
|
24826
|
-
description: "Manage spreadsheets, worksheets, ranges, tables, and charts."
|
|
24827
|
-
},
|
|
24828
|
-
{
|
|
24829
|
-
id: "linkedin",
|
|
24830
|
-
backend: "composio",
|
|
24831
|
-
toolkit: "linkedin",
|
|
24832
|
-
authType: "oauth",
|
|
24833
|
-
category: "business",
|
|
24834
|
-
name: "LinkedIn",
|
|
24835
|
-
description: "Manage profiles, organizations, posts, and professional activity."
|
|
24836
|
-
},
|
|
24837
|
-
{
|
|
24838
|
-
id: "modal",
|
|
24839
|
-
backend: "native",
|
|
24840
|
-
toolkit: "modal",
|
|
24841
|
-
authType: "basic",
|
|
24842
|
-
category: "data",
|
|
24843
|
-
name: "Modal",
|
|
24844
|
-
description: "Invoke deployed functions through Modal compute."
|
|
24845
|
-
},
|
|
24846
|
-
{
|
|
24847
|
-
id: "posthog",
|
|
24848
|
-
backend: "composio",
|
|
24849
|
-
toolkit: "posthog",
|
|
24850
|
-
authType: "api_key",
|
|
24851
|
-
category: "data",
|
|
24852
|
-
name: "PostHog",
|
|
24853
|
-
description: "Manage projects, events, insights, dashboards, flags, and recordings."
|
|
24854
|
-
},
|
|
24855
|
-
{
|
|
24856
|
-
id: "planetscale",
|
|
24857
|
-
toolkit: "planetscale",
|
|
24858
|
-
backend: "native",
|
|
24859
|
-
authType: "oauth",
|
|
24860
|
-
category: "data",
|
|
24861
|
-
name: "PlanetScale",
|
|
24862
|
-
description: "Manage organizations, databases, branches, deploy requests, and Insights."
|
|
24863
|
-
},
|
|
24864
|
-
{
|
|
24865
|
-
id: "stripe",
|
|
24866
|
-
backend: "composio",
|
|
24867
|
-
toolkit: "stripe",
|
|
24868
|
-
authType: "oauth",
|
|
24869
|
-
category: "business",
|
|
24870
|
-
name: "Stripe",
|
|
24871
|
-
description: "Manage customers, payments, invoices, subscriptions, and balances."
|
|
24872
|
-
},
|
|
24873
|
-
{
|
|
24874
|
-
id: "pangram",
|
|
24875
|
-
backend: "native",
|
|
24876
|
-
toolkit: "pangram",
|
|
24877
|
-
authType: "api_key",
|
|
24878
|
-
category: "data",
|
|
24879
|
-
name: "Pangram",
|
|
24880
|
-
description: "Analyze text for AI generation and plagiarism signals."
|
|
24881
|
-
},
|
|
24882
|
-
{
|
|
24883
|
-
id: "vercel",
|
|
24884
|
-
backend: "native",
|
|
24885
|
-
toolkit: "vercel",
|
|
24886
|
-
authType: "api_key",
|
|
24887
|
-
category: "data",
|
|
24888
|
-
name: "Vercel",
|
|
24889
|
-
description: "Manage projects, deployments, logs, domains, and infrastructure."
|
|
24890
|
-
},
|
|
24891
|
-
{
|
|
24892
|
-
id: "turbopuffer",
|
|
24893
|
-
backend: "native",
|
|
24894
|
-
toolkit: "turbopuffer",
|
|
24895
|
-
authType: "api_key",
|
|
24896
|
-
category: "data",
|
|
24897
|
-
name: "turbopuffer",
|
|
24898
|
-
description: "Query and manage turbopuffer namespaces."
|
|
24899
|
-
},
|
|
24900
|
-
{
|
|
24901
|
-
id: "vanta",
|
|
24902
|
-
backend: "native",
|
|
24903
|
-
toolkit: "vanta",
|
|
24904
|
-
authType: "credentials",
|
|
24905
|
-
category: "data",
|
|
24906
|
-
name: "Vanta",
|
|
24907
|
-
description: "Review and manage controls, tests, evidence, vendors, risks, and compliance data.",
|
|
24908
|
-
scopes: ["environment"]
|
|
24909
|
-
}
|
|
24910
|
-
];
|
|
24911
|
-
var HOSTED_COMPOSIO_PLUGIN_DEFINITIONS = [
|
|
24912
|
-
["notion", "notion", "OAUTH2", true, "productivity", "Notion"],
|
|
24913
|
-
["jira", "jira", "OAUTH2", true, "productivity", "Jira"],
|
|
24914
|
-
["confluence", "confluence", "OAUTH2", true, "productivity", "Confluence"],
|
|
24915
|
-
["googlecalendar", "googlecalendar", "OAUTH2", true, "productivity", "Google Calendar"],
|
|
24916
|
-
["microsoftteams", "microsoft_teams", "OAUTH2", true, "productivity", "Microsoft Teams"],
|
|
24917
|
-
["outlook", "outlook", "OAUTH2", true, "productivity", "Outlook"],
|
|
24918
|
-
["bitbucket", "bitbucket", "OAUTH2", true, "data", "Bitbucket"],
|
|
24919
|
-
["datadog", "datadog", "API_KEY", false, "data", "Datadog"],
|
|
24920
|
-
["pagerduty", "pagerduty", "OAUTH2", true, "data", "PagerDuty"],
|
|
24921
|
-
["intercom", "intercom", "OAUTH2", true, "business", "Intercom"],
|
|
24922
|
-
["zendesk", "zendesk", "OAUTH2", true, "business", "Zendesk"],
|
|
24923
|
-
["hubspot", "hubspot", "OAUTH2", true, "business", "HubSpot"],
|
|
24924
|
-
["supabase", "supabase", "OAUTH2", true, "data", "Supabase"],
|
|
24925
|
-
["figma", "figma", "OAUTH2", true, "productivity", "Figma"],
|
|
24926
|
-
["launchdarkly", "launch_darkly", "API_KEY", false, "data", "LaunchDarkly"],
|
|
24927
|
-
["asana", "asana", "OAUTH2", true, "productivity", "Asana"],
|
|
24928
|
-
["clickup", "clickup", "OAUTH2", true, "productivity", "ClickUp"],
|
|
24929
|
-
["trello", "trello", "OAUTH1", true, "productivity", "Trello"],
|
|
24930
|
-
["todoist", "todoist", "OAUTH2", true, "productivity", "Todoist"],
|
|
24931
|
-
["airtable", "airtable", "OAUTH2", true, "productivity", "Airtable"],
|
|
24932
|
-
["coda", "coda", "API_KEY", false, "productivity", "Coda"],
|
|
24933
|
-
["miro", "miro", "OAUTH2", true, "productivity", "Miro"],
|
|
24934
|
-
["sharepoint", "share_point", "OAUTH2", true, "productivity", "SharePoint"],
|
|
24935
|
-
["onedrive", "one_drive", "OAUTH2", true, "productivity", "OneDrive"],
|
|
24936
|
-
["googleslides", "googleslides", "OAUTH2", true, "productivity", "Google Slides"],
|
|
24937
|
-
["googlemeet", "googlemeet", "OAUTH2", true, "productivity", "Google Meet"],
|
|
24938
|
-
["googletasks", "googletasks", "OAUTH2", true, "productivity", "Google Tasks"],
|
|
24939
|
-
["dropbox", "dropbox", "OAUTH2", true, "productivity", "Dropbox"],
|
|
24940
|
-
["box", "box", "OAUTH2", true, "productivity", "Box"],
|
|
24941
|
-
["discord", "discord", "OAUTH2", true, "productivity", "Discord"],
|
|
24942
|
-
["discordbot", "discordbot", "OAUTH2", true, "productivity", "Discord Bot"],
|
|
24943
|
-
["zoom", "zoom", "OAUTH2", true, "productivity", "Zoom"],
|
|
24944
|
-
["googlechat", "google_chat", "OAUTH2", false, "productivity", "Google Chat"],
|
|
24945
|
-
["newrelic", "new_relic", "API_KEY", false, "data", "New Relic"],
|
|
24946
|
-
["betterstack", "better_stack", "API_KEY", false, "data", "Better Stack"],
|
|
24947
|
-
["incidentio", "incident_io", "API_KEY", false, "data", "incident.io"],
|
|
24948
|
-
["grafana", "grafana", "BEARER_TOKEN", false, "data", "Grafana"],
|
|
24949
|
-
["honeycomb", "honeycomb_mcp", "DCR_OAUTH", false, "data", "Honeycomb MCP"],
|
|
24950
|
-
["bugsnag", "bugsnag", "API_KEY", false, "data", "Bugsnag"],
|
|
24951
|
-
["circleci", "circleci", "API_KEY", false, "data", "CircleCI"],
|
|
24952
|
-
["buildkite", "buildkite", "API_KEY", false, "data", "Buildkite"],
|
|
24953
|
-
["dockerhub", "docker_hub", "API_KEY", false, "data", "Docker Hub"],
|
|
24954
|
-
["digitalocean", "digital_ocean", "OAUTH2", true, "data", "DigitalOcean"],
|
|
24955
|
-
["railway", "railway", "API_KEY", false, "data", "Railway"],
|
|
24956
|
-
["render", "render", "API_KEY", false, "data", "Render"],
|
|
24957
|
-
["firebase", "firebase", "API_KEY", false, "data", "Firebase"],
|
|
24958
|
-
["cloudinary", "cloudinary", "API_KEY", false, "data", "Cloudinary"],
|
|
24959
|
-
["configcat", "configcat", "API_KEY", false, "data", "ConfigCat"],
|
|
24960
|
-
["contextdev", "context_dev", "API_KEY", false, "data", "Context.dev"],
|
|
24961
|
-
["googleanalytics", "google_analytics", "OAUTH2", true, "data", "Google Analytics"],
|
|
24962
|
-
["googlebigquery", "googlebigquery", "OAUTH2", true, "data", "Google BigQuery"],
|
|
24963
|
-
["amplitude", "amplitude", "API_KEY", false, "data", "Amplitude"],
|
|
24964
|
-
["mixpanel", "mixpanel", "BASIC", false, "data", "Mixpanel"],
|
|
24965
|
-
["segment", "segment", "API_KEY", false, "data", "Segment"],
|
|
24966
|
-
["databricks", "databricks", "API_KEY", false, "data", "Databricks"],
|
|
24967
|
-
["snowflake", "snowflake", "OAUTH2", false, "data", "Snowflake"],
|
|
24968
|
-
["algolia", "algolia", "API_KEY", false, "data", "Algolia"],
|
|
24969
|
-
["elasticsearch", "elasticsearch", "API_KEY", false, "data", "Elasticsearch"],
|
|
24970
|
-
["salesforce", "salesforce", "OAUTH2", true, "business", "Salesforce"],
|
|
24971
|
-
["pipedrive", "pipedrive", "API_KEY", false, "business", "Pipedrive"],
|
|
24972
|
-
["close", "close", "API_KEY", false, "business", "Close"],
|
|
24973
|
-
["apollo", "apollo", "API_KEY", false, "business", "Apollo"],
|
|
24974
|
-
["gong", "gong", "OAUTH2", true, "business", "Gong"],
|
|
24975
|
-
["freshdesk", "freshdesk", "API_KEY", false, "business", "Freshdesk"],
|
|
24976
|
-
["helpscout", "help_scout", "OAUTH2", false, "business", "Help Scout"],
|
|
24977
|
-
["servicenow", "servicenow", "BASIC", false, "business", "ServiceNow"],
|
|
24978
|
-
["mailchimp", "mailchimp", "OAUTH2", true, "business", "Mailchimp"],
|
|
24979
|
-
["customerio", "customerio", "API_KEY", false, "business", "Customer.io"],
|
|
24980
|
-
["klaviyo", "klaviyo", "API_KEY", false, "business", "Klaviyo"],
|
|
24981
|
-
["shopify", "shopify", "API_KEY", false, "business", "Shopify"],
|
|
24982
|
-
["quickbooks", "quickbooks", "OAUTH2", true, "business", "QuickBooks"],
|
|
24983
|
-
["xero", "xero", "OAUTH2", false, "business", "Xero"],
|
|
24984
|
-
["brex", "brex", "API_KEY", false, "business", "Brex"],
|
|
24985
|
-
["buffer", "buffer", "OAUTH2", false, "business", "Buffer"],
|
|
24986
|
-
["canva", "canva", "OAUTH2", true, "productivity", "Canva"],
|
|
24987
|
-
["webflow", "webflow", "API_KEY", false, "business", "Webflow"],
|
|
24988
|
-
["firecrawl", "firecrawl", "API_KEY", false, "data", "Firecrawl"],
|
|
24989
|
-
["browserbase", "browserbase_tool", "API_KEY", false, "data", "Browserbase"],
|
|
24990
|
-
["exa", "exa", "API_KEY", false, "data", "Exa"],
|
|
24991
|
-
["youtube", "youtube", "OAUTH2", true, "business", "YouTube"],
|
|
24992
|
-
["twitter", "twitter", "OAUTH2", false, "business", "Twitter/X"],
|
|
24993
|
-
["instagram", "instagram", "OAUTH2", true, "business", "Instagram"],
|
|
24994
|
-
["facebook", "facebook", "OAUTH2", true, "business", "Facebook"]
|
|
24995
|
-
];
|
|
24996
|
-
var HOSTED_COMPOSIO_PLUGINS = HOSTED_COMPOSIO_PLUGIN_DEFINITIONS.map(
|
|
24997
|
-
([id, toolkit, authScheme, managedAuth, category, name]) => ({
|
|
24998
|
-
id,
|
|
24999
|
-
backend: "composio",
|
|
25000
|
-
toolkit,
|
|
25001
|
-
authType: "hosted",
|
|
25002
|
-
authScheme,
|
|
25003
|
-
managedAuth,
|
|
25004
|
-
category,
|
|
25005
|
-
name,
|
|
25006
|
-
description: `Use ${name} tools from workspace agents.`
|
|
25007
|
-
})
|
|
25008
|
-
);
|
|
25009
|
-
var PLUGIN_CATALOG = [
|
|
25010
|
-
...EXPLICIT_PLUGIN_CATALOG,
|
|
25011
|
-
...HOSTED_COMPOSIO_PLUGINS
|
|
25012
|
-
];
|
|
25013
|
-
|
|
25014
|
-
// ../shared/src/routes/user.ts
|
|
25015
|
-
var PROFILE_AVATAR_MAX_SIZE_BYTES = 5 * 1024 * 1024;
|
|
25016
|
-
|
|
25017
|
-
// ../shared/src/routes/client-state.ts
|
|
25018
|
-
var MAX_CLIENT_STATE_REQUEST_BYTES = 5 * 1024 * 1024;
|
|
25019
|
-
var MAX_CLIENT_STATE_BYTES_PER_USER = 10 * 1024 * 1024;
|
|
25020
|
-
|
|
25021
|
-
// ../shared/src/routes/workspaces.ts
|
|
25022
|
-
var WORKSPACE_STATUSES = ["active", "sleeping", "archived", "preparing", "error"];
|
|
25023
|
-
function isWorkspaceSuspendedStatus(status) {
|
|
25024
|
-
return status === "sleeping" || status === "archived";
|
|
25025
|
-
}
|
|
25026
|
-
function workspaceConfigWithCapabilities(config3, capabilities = {}) {
|
|
25027
|
-
const mergedCapabilities = {
|
|
25028
|
-
...config3?.capabilities,
|
|
25029
|
-
...capabilities
|
|
25030
|
-
};
|
|
25031
|
-
return {
|
|
25032
|
-
...config3,
|
|
25033
|
-
capabilities: {
|
|
25034
|
-
...mergedCapabilities,
|
|
25035
|
-
pr_followups: mergedCapabilities.pr_followups === true
|
|
25036
|
-
}
|
|
25037
|
-
};
|
|
25038
|
-
}
|
|
25039
|
-
function workspaceConfigWithPrFollowups(config3, prFollowups = config3?.capabilities?.pr_followups === true) {
|
|
25040
|
-
return workspaceConfigWithCapabilities(config3, { pr_followups: prFollowups });
|
|
25041
|
-
}
|
|
25042
|
-
var WORKSPACE_STATUS_FILTERS = WORKSPACE_STATUSES.map((status) => status === "error" ? "failed" : status);
|
|
25043
|
-
var WORKSPACE_SORT_CHOICES = [
|
|
25044
|
-
["manual", "Custom"],
|
|
25045
|
-
["activity", "Last activity"],
|
|
25046
|
-
["created", "Created date"]
|
|
25047
|
-
];
|
|
25048
|
-
var WORKSPACE_SORT_OPTIONS = WORKSPACE_SORT_CHOICES.map(([option]) => option);
|
|
25049
|
-
var WORKSPACE_SORT_LABELS = Object.fromEntries(WORKSPACE_SORT_CHOICES);
|
|
25050
|
-
var WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES = [
|
|
25051
|
-
["chronological", "Chronological"],
|
|
25052
|
-
["environments", "Environments"],
|
|
25053
|
-
["recent", "Recent environments"]
|
|
25054
|
-
];
|
|
25055
|
-
var WORKSPACE_SIDEBAR_ORGANIZATIONS = WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES.map(([organization]) => organization);
|
|
25056
|
-
var WORKSPACE_SIDEBAR_ORGANIZATION_LABELS = Object.fromEntries(WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES);
|
|
25057
|
-
var DEFAULT_STATUS_FILTERS = [...WORKSPACE_STATUS_FILTERS];
|
|
25058
|
-
var DEFAULT_WORKSPACE_FILTERS = {
|
|
25059
|
-
statuses: [...DEFAULT_STATUS_FILTERS],
|
|
25060
|
-
ownerIds: [],
|
|
25061
|
-
activity: "any"
|
|
25062
|
-
};
|
|
25063
|
-
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
25064
|
-
|
|
25065
|
-
// ../shared/src/routes/workspace-events.ts
|
|
25066
|
-
var workspaceChangedEventSchema = external_exports.discriminatedUnion("type", [
|
|
25067
|
-
external_exports.object({
|
|
25068
|
-
type: external_exports.literal("workspace.changed"),
|
|
25069
|
-
workspaceId: external_exports.string(),
|
|
25070
|
-
completion: external_exports.object({
|
|
25071
|
-
workspaceName: external_exports.string(),
|
|
25072
|
-
completedAt: external_exports.string(),
|
|
25073
|
-
processing: external_exports.boolean().optional()
|
|
25074
|
-
}).optional(),
|
|
25075
|
-
ts: external_exports.string()
|
|
25076
|
-
}),
|
|
25077
|
-
external_exports.object({
|
|
25078
|
-
type: external_exports.literal("workspace.chat.changed"),
|
|
25079
|
-
workspaceId: external_exports.string(),
|
|
25080
|
-
chatId: external_exports.string(),
|
|
25081
|
-
ts: external_exports.string()
|
|
25082
|
-
}),
|
|
25083
|
-
external_exports.object({ type: external_exports.literal("presence.changed"), ts: external_exports.string() }),
|
|
25084
|
-
external_exports.object({
|
|
25085
|
-
type: external_exports.literal("mobile-testing.changed"),
|
|
25086
|
-
workspaceId: external_exports.string(),
|
|
25087
|
-
ts: external_exports.string()
|
|
25088
|
-
})
|
|
25089
|
-
]);
|
|
25090
|
-
|
|
25091
|
-
// ../shared/src/routes/presence.ts
|
|
25092
|
-
var presenceStatusSchema = external_exports.enum(["online", "typing"]);
|
|
25093
|
-
var presenceLocationSchema = external_exports.object({
|
|
25094
|
-
environmentId: external_exports.string().optional(),
|
|
25095
|
-
workspaceId: external_exports.string().optional()
|
|
25096
|
-
});
|
|
25097
|
-
var presenceEntrySchema = external_exports.object({
|
|
25098
|
-
userId: external_exports.string(),
|
|
25099
|
-
status: presenceStatusSchema,
|
|
25100
|
-
location: presenceLocationSchema,
|
|
25101
|
-
ts: external_exports.string()
|
|
25102
|
-
});
|
|
25103
|
-
var updatePresenceRequestSchema = external_exports.object({
|
|
25104
|
-
status: presenceStatusSchema,
|
|
25105
|
-
location: presenceLocationSchema.optional()
|
|
25106
|
-
});
|
|
25107
|
-
|
|
25108
|
-
// ../shared/src/audit-log.ts
|
|
25109
|
-
var AUDIT_LOG_ACTION = {
|
|
25110
|
-
CREATE: "create",
|
|
25111
|
-
UPDATE: "update",
|
|
25112
|
-
DELETE: "delete",
|
|
25113
|
-
CONNECT: "connect",
|
|
25114
|
-
DISCONNECT: "disconnect"
|
|
25115
|
-
};
|
|
25116
|
-
var AUDIT_LOG_ACTIONS = Object.values(AUDIT_LOG_ACTION);
|
|
25117
|
-
|
|
25118
|
-
// ../shared/src/automations/types.ts
|
|
25119
|
-
var AUTOMATION_DEBOUNCE_MAX_SECONDS = 24 * 60 * 60;
|
|
25120
|
-
var AUTOMATION_LIFECYCLE_POLICIES = ["default", "archive_when_done", "sleep_when_done"];
|
|
25121
|
-
function toAutomationLifecyclePolicy(policy) {
|
|
25122
|
-
if (!policy) return "default";
|
|
25123
|
-
if (policy === "default" || policy === "archive_when_done" || policy === "sleep_when_done") return policy;
|
|
25124
|
-
return "archive_when_done";
|
|
25125
|
-
}
|
|
25126
|
-
function lifecyclePolicySupportsAutoStop(policy) {
|
|
25127
|
-
return policy === "default";
|
|
25128
|
-
}
|
|
25129
|
-
|
|
25130
|
-
// ../shared/src/automations/github-checks.ts
|
|
25131
|
-
var AUTOMATION_CHECK_CONCLUSIONS = ["success", "failure"];
|
|
25132
|
-
function isAutomationCheckConclusion(value) {
|
|
25133
|
-
return AUTOMATION_CHECK_CONCLUSIONS.some((conclusion) => conclusion === value);
|
|
25134
|
-
}
|
|
25135
|
-
function normalizeAutomationGithubCheckNames(names) {
|
|
25136
|
-
return names.map((name) => name.trim()).filter(Boolean);
|
|
25137
|
-
}
|
|
25138
|
-
|
|
25139
|
-
// ../shared/src/automations/agent-validation.ts
|
|
25140
|
-
function validateAgentSelection(body, existing, modelCatalogs = {}) {
|
|
25141
|
-
const agentProvider = body.agent_provider;
|
|
25142
|
-
if (agentProvider !== void 0 && agentProvider !== null) {
|
|
25143
|
-
if (!isValidAgentProvider(agentProvider)) {
|
|
25144
|
-
return createErrorResult({ message: `Invalid agent_provider: must be one of ${VALID_AGENT_PROVIDERS.join(", ")}` });
|
|
25145
|
-
}
|
|
25146
|
-
}
|
|
25147
|
-
const effectiveAgent = agentProvider !== void 0 ? agentProvider : existing.agentProvider;
|
|
25148
|
-
const agentChanged = agentProvider !== void 0 && agentProvider !== existing.agentProvider;
|
|
25149
|
-
let model = body.model;
|
|
25150
|
-
if (agentChanged && model === void 0 && existing.model) {
|
|
25151
|
-
model = null;
|
|
25152
|
-
}
|
|
25153
|
-
if (model !== void 0 && model !== null) {
|
|
25154
|
-
if (typeof model !== "string" || model.trim().length === 0) {
|
|
25155
|
-
return createErrorResult({ message: "model must be a non-empty string" });
|
|
25156
|
-
}
|
|
25157
|
-
model = normalizeClaudeModel(model) ?? model;
|
|
25158
|
-
if (!effectiveAgent) {
|
|
25159
|
-
return createErrorResult({ message: "Cannot set model without an agent_provider (the model would be applied against the org default agent and may not be valid for it)" });
|
|
25160
|
-
}
|
|
25161
|
-
const allowed = getAgentModelOptions(effectiveAgent, modelCatalogs);
|
|
25162
|
-
if (!isAgentModelAllowed(effectiveAgent, model, modelCatalogs)) {
|
|
25163
|
-
return createErrorResult({ message: `Invalid model "${model}" for agent ${effectiveAgent}. Valid models: ${allowed.join(", ")}` });
|
|
25164
|
-
}
|
|
25165
|
-
}
|
|
25166
|
-
const thinkingLevel = body.thinking_level;
|
|
25167
|
-
if (thinkingLevel !== void 0 && thinkingLevel !== null) {
|
|
25168
|
-
if (!effectiveAgent && isProviderSpecificThinkingLevel(thinkingLevel)) {
|
|
25169
|
-
return createErrorResult({ message: `Cannot set ${thinkingLevel} without an agent_provider` });
|
|
25170
|
-
}
|
|
25171
|
-
if (!isValidThinkingLevel(thinkingLevel) || effectiveAgent && !getThinkingLevelOptions(effectiveAgent).includes(thinkingLevel)) {
|
|
25172
|
-
const validLevels = effectiveAgent ? getThinkingLevelOptions(effectiveAgent) : VALID_THINKING_LEVELS;
|
|
25173
|
-
return createErrorResult({ message: `Invalid thinking_level: must be one of ${validLevels.join(", ")}` });
|
|
25174
|
-
}
|
|
25175
|
-
}
|
|
25176
|
-
return createSuccessResult({ agentProvider, model, thinkingLevel });
|
|
25177
|
-
}
|
|
25178
|
-
|
|
25179
|
-
// ../shared/src/automations/github/index.ts
|
|
25180
|
-
var REPO_FILTER_PARAM = {
|
|
25181
|
-
id: "repository_ids",
|
|
25182
|
-
label: "Filter by repository",
|
|
25183
|
-
type: "repository_ids"
|
|
25184
|
-
};
|
|
25185
|
-
var EXCLUDED_ACTORS_PARAM = {
|
|
25186
|
-
id: "excluded_actors",
|
|
25187
|
-
label: "Exclude users",
|
|
25188
|
-
type: "excluded_actors"
|
|
25189
|
-
};
|
|
25190
|
-
var GROUP_PR_EVENTS_PARAM = {
|
|
25191
|
-
id: "group_pr_events",
|
|
25192
|
-
label: "Group PR events to same workspace",
|
|
25193
|
-
type: "boolean"
|
|
25194
|
-
};
|
|
25195
|
-
var GITHUB_TRIGGER = {
|
|
25196
|
-
type: "github",
|
|
25197
|
-
label: "GitHub",
|
|
25198
|
-
description: "Trigger on repository events",
|
|
25199
|
-
icon: "github",
|
|
25200
|
-
events: [
|
|
25201
|
-
{ id: "pull_request.opened", label: "PR opened", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM, GROUP_PR_EVENTS_PARAM] },
|
|
25202
|
-
{ id: "pull_request.synchronize", label: "PR updated (new commits)", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM, GROUP_PR_EVENTS_PARAM] },
|
|
25203
|
-
{ id: "pull_request.merged", label: "PR merged", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM] },
|
|
25204
|
-
{ id: "pull_request.closed", label: "PR closed", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM] },
|
|
25205
|
-
{ id: "pull_request.command", label: "PR command (/replicas run)", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM, GROUP_PR_EVENTS_PARAM] }
|
|
25206
|
-
]
|
|
25207
|
-
};
|
|
25208
|
-
|
|
25209
|
-
// ../shared/src/automations/gitlab/index.ts
|
|
25210
|
-
var REPO_FILTER_PARAM2 = {
|
|
25211
|
-
id: "repository_ids",
|
|
25212
|
-
label: "Filter by project",
|
|
25213
|
-
type: "repository_ids"
|
|
25214
|
-
};
|
|
25215
|
-
var EXCLUDED_ACTORS_PARAM2 = {
|
|
25216
|
-
id: "excluded_actors",
|
|
25217
|
-
label: "Exclude users",
|
|
25218
|
-
type: "excluded_actors"
|
|
25219
|
-
};
|
|
25220
|
-
var GROUP_MR_EVENTS_PARAM = {
|
|
25221
|
-
id: "group_pr_events",
|
|
25222
|
-
label: "Group MR events to same workspace",
|
|
25223
|
-
type: "boolean"
|
|
25224
|
-
};
|
|
25225
|
-
var GITLAB_TRIGGER = {
|
|
25226
|
-
type: "gitlab",
|
|
25227
|
-
label: "GitLab",
|
|
25228
|
-
description: "Trigger on project events",
|
|
25229
|
-
icon: "gitlab",
|
|
25230
|
-
events: [
|
|
25231
|
-
{ id: "merge_request.opened", label: "MR opened", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2, GROUP_MR_EVENTS_PARAM] },
|
|
25232
|
-
{ id: "merge_request.updated", label: "MR updated (new commits)", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2, GROUP_MR_EVENTS_PARAM] },
|
|
25233
|
-
{ id: "merge_request.merged", label: "MR merged", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2] },
|
|
25234
|
-
{ id: "merge_request.closed", label: "MR closed", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2] }
|
|
25235
|
-
]
|
|
25236
|
-
};
|
|
25237
|
-
|
|
25238
|
-
// ../shared/src/routes/repo-files.ts
|
|
25239
|
-
var MAX_REPO_FILE_CONTENT_BYTES = 256 * 1024;
|
|
25240
|
-
|
|
25241
|
-
// ../shared/src/routes/admin.ts
|
|
25242
|
-
var WEBHOOK_PROVIDERS = ["linear", "github", "gitlab", "slack", "e2b", "stripe", "sentry"];
|
|
25243
|
-
var WEBHOOK_PROVIDER_SET = new Set(WEBHOOK_PROVIDERS);
|
|
25244
|
-
|
|
25245
|
-
// ../shared/src/display-message/types.ts
|
|
25246
|
-
var BACKGROUND_TASK_SUBTYPES = /* @__PURE__ */ new Set([
|
|
25247
|
-
"task_started",
|
|
25248
|
-
"task_progress",
|
|
25249
|
-
"task_updated",
|
|
25250
|
-
"task_notification"
|
|
25251
|
-
]);
|
|
25252
|
-
function isBackgroundTaskSubtype(subtype) {
|
|
25253
|
-
return typeof subtype === "string" && BACKGROUND_TASK_SUBTYPES.has(subtype);
|
|
25254
|
-
}
|
|
25255
|
-
function optionalString(value) {
|
|
25256
|
-
return typeof value === "string" ? value : void 0;
|
|
25257
|
-
}
|
|
25258
|
-
function coerceBackgroundTaskPayload(payload) {
|
|
25259
|
-
if (!isRecord(payload)) return null;
|
|
25260
|
-
const subtype = payload.subtype;
|
|
25261
|
-
if (!isBackgroundTaskSubtype(subtype)) return null;
|
|
25262
|
-
const taskId = payload.task_id;
|
|
25263
|
-
if (typeof taskId !== "string" || !taskId) return null;
|
|
25264
|
-
const patch = isRecord(payload.patch) ? {
|
|
25265
|
-
status: optionalString(payload.patch.status),
|
|
25266
|
-
description: optionalString(payload.patch.description),
|
|
25267
|
-
error: optionalString(payload.patch.error),
|
|
25268
|
-
isBackgrounded: optionalBoolean(payload.patch.is_backgrounded)
|
|
25269
|
-
} : void 0;
|
|
25270
|
-
const usage = isRecord(payload.usage) ? {
|
|
25271
|
-
totalTokens: optionalNumber(payload.usage.total_tokens),
|
|
25272
|
-
toolUses: optionalNumber(payload.usage.tool_uses),
|
|
25273
|
-
durationMs: optionalNumber(payload.usage.duration_ms)
|
|
25274
|
-
} : void 0;
|
|
25275
|
-
return {
|
|
25276
|
-
subtype,
|
|
25277
|
-
taskId,
|
|
25278
|
-
description: optionalString(payload.description),
|
|
25279
|
-
summary: optionalString(payload.summary),
|
|
25280
|
-
outputFile: optionalString(payload.output_file),
|
|
25281
|
-
status: optionalString(payload.status),
|
|
25282
|
-
taskType: optionalString(payload.task_type),
|
|
25283
|
-
workflowName: optionalString(payload.workflow_name),
|
|
25284
|
-
prompt: optionalString(payload.prompt),
|
|
25285
|
-
lastToolName: optionalString(payload.last_tool_name),
|
|
25286
|
-
usage,
|
|
25287
|
-
ambient: optionalBoolean(payload.ambient),
|
|
25288
|
-
patch
|
|
25289
|
-
};
|
|
25290
|
-
}
|
|
25291
|
-
function optionalNumber(value) {
|
|
25292
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
25293
|
-
}
|
|
25294
|
-
function optionalBoolean(value) {
|
|
25295
|
-
return typeof value === "boolean" ? value : void 0;
|
|
25296
|
-
}
|
|
25297
|
-
function normalizeBackgroundTaskStatus(status) {
|
|
25298
|
-
if (status === "completed" || status === "failed" || status === "stopped") {
|
|
25299
|
-
return status;
|
|
25300
|
-
}
|
|
25301
|
-
if (status === "killed") {
|
|
25302
|
-
return "stopped";
|
|
25303
|
-
}
|
|
25304
|
-
return "in_progress";
|
|
25305
|
-
}
|
|
25306
|
-
|
|
25307
|
-
// ../shared/src/display-message/constants.ts
|
|
25308
|
-
var USER_MESSAGE_MATCH_GRACE_PERIOD_MS = 3e4;
|
|
25309
|
-
|
|
25310
|
-
// ../shared/src/user-message-matching.ts
|
|
25311
|
-
function parseTimestampMs(timestamp) {
|
|
25312
|
-
const value = Date.parse(timestamp);
|
|
25313
|
-
return Number.isFinite(value) ? value : 0;
|
|
25314
|
-
}
|
|
25315
|
-
function areUserMessagesWithinMatchWindow(a, b) {
|
|
25316
|
-
return a.content === b.content && Math.abs(parseTimestampMs(a.timestamp) - parseTimestampMs(b.timestamp)) <= USER_MESSAGE_MATCH_GRACE_PERIOD_MS;
|
|
25317
|
-
}
|
|
25318
|
-
|
|
25319
|
-
// ../shared/src/agent-event-utils.ts
|
|
25320
|
-
function getUserMessage(event) {
|
|
25321
|
-
return event.type === "event_msg" && event.payload.type === "user_message" && typeof event.payload.message === "string" ? event.payload.message : null;
|
|
25322
|
-
}
|
|
25323
|
-
function getUserMessageId(event) {
|
|
25324
|
-
const messageId = event.payload[USER_MESSAGE_ID_PAYLOAD_KEY];
|
|
25325
|
-
return typeof messageId === "string" ? messageId : null;
|
|
25326
|
-
}
|
|
25327
|
-
|
|
25328
|
-
// ../shared/src/json.ts
|
|
25329
|
-
function safeJsonParse(str, fallback) {
|
|
25330
|
-
try {
|
|
25331
|
-
return JSON.parse(str);
|
|
25332
|
-
} catch {
|
|
25333
|
-
return fallback;
|
|
25334
|
-
}
|
|
25335
|
-
}
|
|
25336
|
-
|
|
25337
|
-
// ../shared/src/display-message/parsers/utils.ts
|
|
25338
|
-
var INTERRUPTED_MESSAGE_REGEX = /^\[Request interrupted by user.*\]$/;
|
|
25339
|
-
function userMessageImages(value) {
|
|
25340
|
-
if (!Array.isArray(value)) return void 0;
|
|
25341
|
-
const images = value.filter((item) => isRecord(item) && item.type === "image" && typeof item.mediaType === "string" && typeof item.data === "string");
|
|
25342
|
-
return images.length > 0 ? images : void 0;
|
|
25343
|
-
}
|
|
25344
|
-
function stringifyDisplayValue(value) {
|
|
25345
|
-
if (value === void 0 || value === null) return void 0;
|
|
25346
|
-
if (typeof value === "string") return value;
|
|
25347
|
-
try {
|
|
25348
|
-
return JSON.stringify(value, null, 2);
|
|
25349
|
-
} catch {
|
|
25350
|
-
return String(value);
|
|
25351
|
-
}
|
|
25352
|
-
}
|
|
25353
|
-
function upsertDisplayMessage(messages, message) {
|
|
25354
|
-
const index = messages.findIndex((candidate) => candidate.id === message.id);
|
|
25355
|
-
if (index === -1) messages.push(message);
|
|
25356
|
-
else messages[index] = message;
|
|
25357
|
-
}
|
|
25358
|
-
function applyToolInputEvent(event, messages, provider, state, questionFilter) {
|
|
25359
|
-
if (event.type === "replicas-tool-input-request" && typeof event.payload.toolUseId === "string" && typeof event.payload.requestId === "string" && (Array.isArray(event.payload.options) || Array.isArray(event.payload.questions))) {
|
|
25360
|
-
const resolved = state.resolutions.get(event.payload.toolUseId);
|
|
25361
|
-
const inputRequest = {
|
|
25362
|
-
requestId: event.payload.requestId,
|
|
25363
|
-
status: resolved?.selectionId === "aborted" || resolved?.selectionId === "declined" ? "aborted" : resolved ? "resolved" : "pending",
|
|
25364
|
-
...Array.isArray(event.payload.options) ? { options: event.payload.options } : {},
|
|
25365
|
-
...Array.isArray(event.payload.questions) ? { questions: questionFilter ? event.payload.questions.filter(questionFilter) : event.payload.questions } : {},
|
|
25366
|
-
...resolved ? { selectionId: resolved.selectionId } : {},
|
|
25367
|
-
...resolved?.selectionSummary ? { selectionSummary: resolved.selectionSummary } : {}
|
|
25368
|
-
};
|
|
25369
|
-
state.requests.set(event.payload.toolUseId, inputRequest);
|
|
25370
|
-
const message = messages.find((candidate) => candidate.type === "tool_call" && candidate.id === `${provider}-tool-${event.payload.toolUseId}`);
|
|
25371
|
-
if (message) message.inputRequest = inputRequest;
|
|
25372
|
-
return true;
|
|
25373
|
-
}
|
|
25374
|
-
if (event.type === "replicas-tool-input-resolved" && typeof event.payload.toolUseId === "string" && typeof event.payload.selectionId === "string") {
|
|
25375
|
-
const resolved = {
|
|
25376
|
-
selectionId: event.payload.selectionId,
|
|
25377
|
-
...typeof event.payload.selectionSummary === "string" ? { selectionSummary: event.payload.selectionSummary } : {}
|
|
25378
|
-
};
|
|
25379
|
-
state.resolutions.set(event.payload.toolUseId, resolved);
|
|
25380
|
-
const inputRequest = state.requests.get(event.payload.toolUseId);
|
|
25381
|
-
if (inputRequest) {
|
|
25382
|
-
inputRequest.status = resolved.selectionId === "aborted" || resolved.selectionId === "declined" ? "aborted" : "resolved";
|
|
25383
|
-
inputRequest.selectionId = resolved.selectionId;
|
|
25384
|
-
if (resolved.selectionSummary) inputRequest.selectionSummary = resolved.selectionSummary;
|
|
25385
|
-
}
|
|
25386
|
-
return true;
|
|
25387
|
-
}
|
|
25388
|
-
return false;
|
|
25389
|
-
}
|
|
25390
|
-
function parseSkillName(tool, input) {
|
|
25391
|
-
if (typeof tool !== "string") return null;
|
|
25392
|
-
const normalizedTool = tool.toLowerCase();
|
|
25393
|
-
if (normalizedTool.startsWith("skill.")) return tool.slice("skill.".length) || null;
|
|
25394
|
-
if (normalizedTool !== "skill") return null;
|
|
25395
|
-
const parsedInput = typeof input === "string" ? safeJsonParse(input, null) : input;
|
|
25396
|
-
if (!isRecord(parsedInput)) return null;
|
|
25397
|
-
const skillName = parsedInput.skill ?? parsedInput.name;
|
|
25398
|
-
return typeof skillName === "string" && skillName ? skillName : null;
|
|
25399
|
-
}
|
|
25400
|
-
function skillNameFromFilePath(path6) {
|
|
25401
|
-
const skillName = skillNameFromSkillRootPath(path6);
|
|
25402
|
-
if (skillName) return skillName;
|
|
25403
|
-
const parts = path6.split(/[\\/]+/).filter(Boolean);
|
|
25404
|
-
if (parts.length < 2 || parts[parts.length - 1].toLowerCase() !== "skill.md") return null;
|
|
25405
|
-
const fallbackSkillName = parts[parts.length - 2];
|
|
25406
|
-
return fallbackSkillName && fallbackSkillName.toLowerCase() !== "skills" ? fallbackSkillName : null;
|
|
25407
|
-
}
|
|
25408
|
-
function skillNameFromSkillRootPath(path6) {
|
|
25409
|
-
const parts = path6.split(/[\\/]+/).filter(Boolean);
|
|
25410
|
-
const skillsIndex = parts.findLastIndex((part) => part.toLowerCase() === "skills");
|
|
25411
|
-
if (skillsIndex === -1) return null;
|
|
25412
|
-
const firstSkillPart = parts[skillsIndex + 1];
|
|
25413
|
-
const skillName = firstSkillPart?.toLowerCase() === ".system" ? parts[skillsIndex + 2] : firstSkillPart;
|
|
25414
|
-
return skillName && skillName.toLowerCase() !== "skill.md" ? skillName : null;
|
|
25415
|
-
}
|
|
25416
|
-
function parseSkillFilePath(input) {
|
|
25417
|
-
const parsedInput = typeof input === "string" ? safeJsonParse(input, null) : input;
|
|
25418
|
-
if (!isRecord(parsedInput)) return null;
|
|
25419
|
-
const path6 = [parsedInput.path, parsedInput.filePath, parsedInput.file_path].find((value) => typeof value === "string" && value.length > 0);
|
|
25420
|
-
if (!path6) return null;
|
|
25421
|
-
return skillNameFromFilePath(path6);
|
|
25422
|
-
}
|
|
25423
|
-
function skillNameFromToolCall(tool, input) {
|
|
25424
|
-
const directSkillName = parseSkillName(tool, input);
|
|
25425
|
-
if (directSkillName) return directSkillName;
|
|
25426
|
-
if (typeof tool !== "string" || !["read", "read_file", "readfile"].includes(tool.toLowerCase())) return null;
|
|
25427
|
-
return parseSkillFilePath(input);
|
|
25428
|
-
}
|
|
25429
|
-
function createCallDisplayMessage(message) {
|
|
25430
|
-
const skillName = message.server.toLowerCase() === "skills" ? message.tool : skillNameFromToolCall(message.tool, message.input);
|
|
25431
|
-
if (skillName === null) return { ...message, type: "tool_call" };
|
|
25432
|
-
return {
|
|
25433
|
-
id: message.id,
|
|
25434
|
-
type: "skill",
|
|
25435
|
-
skillName,
|
|
25436
|
-
status: message.status,
|
|
25437
|
-
timestamp: message.timestamp
|
|
25438
|
-
};
|
|
25439
|
-
}
|
|
25440
|
-
function insertDisplayMessageByTimestamp(messages, message) {
|
|
25441
|
-
const messageMs = parseTimestampMs(message.timestamp);
|
|
25442
|
-
let index = messages.length;
|
|
25443
|
-
while (index > 0 && parseTimestampMs(messages[index - 1].timestamp) > messageMs) index--;
|
|
25444
|
-
messages.splice(index, 0, message);
|
|
25445
|
-
}
|
|
25446
|
-
|
|
25447
|
-
// ../shared/src/display-message/format.ts
|
|
25448
|
-
function unquoteShellArg(value) {
|
|
25449
|
-
const trimmed = value.trim();
|
|
25450
|
-
if (trimmed.length < 2) return trimmed;
|
|
25451
|
-
if (trimmed[0] === "'" && trimmed[trimmed.length - 1] === "'") {
|
|
25452
|
-
return trimmed.slice(1, -1).replace(/'\\''/g, "'");
|
|
25453
|
-
}
|
|
25454
|
-
if (trimmed[0] === '"' && trimmed[trimmed.length - 1] === '"') {
|
|
25455
|
-
return trimmed.slice(1, -1).replace(/\\(["\\$`])/g, "$1");
|
|
25456
|
-
}
|
|
25457
|
-
return trimmed;
|
|
25458
|
-
}
|
|
25459
|
-
function shellPayload(command) {
|
|
25460
|
-
const match = command.trim().match(/^(?:\S*\/)?(?:ba|z|c|fi)?sh\s+-(?:[a-zA-Z]*c[a-zA-Z]*|c)\s+([\s\S]+)$/);
|
|
25461
|
-
return match ? unquoteShellArg(match[1]) : command.trim();
|
|
25462
|
-
}
|
|
25463
|
-
function splitShellWords(command) {
|
|
25464
|
-
const words = [];
|
|
25465
|
-
let word = "";
|
|
25466
|
-
let quote = null;
|
|
25467
|
-
let escaped = false;
|
|
25468
|
-
for (const char of command) {
|
|
25469
|
-
if (escaped) {
|
|
25470
|
-
word += char;
|
|
25471
|
-
escaped = false;
|
|
25472
|
-
continue;
|
|
25473
|
-
}
|
|
25474
|
-
if (char === "\\" && quote !== "'") {
|
|
25475
|
-
escaped = true;
|
|
25476
|
-
continue;
|
|
25477
|
-
}
|
|
25478
|
-
if (quote) {
|
|
25479
|
-
if (char === quote) quote = null;
|
|
25480
|
-
else word += char;
|
|
25481
|
-
continue;
|
|
25482
|
-
}
|
|
25483
|
-
if (char === '"' || char === "'") {
|
|
25484
|
-
quote = char;
|
|
25485
|
-
continue;
|
|
25486
|
-
}
|
|
25487
|
-
if (/\s/.test(char)) {
|
|
25488
|
-
if (word) {
|
|
25489
|
-
words.push(word);
|
|
25490
|
-
word = "";
|
|
25491
|
-
}
|
|
25492
|
-
continue;
|
|
25493
|
-
}
|
|
25494
|
-
word += char;
|
|
25495
|
-
}
|
|
25496
|
-
if (word) words.push(word);
|
|
25497
|
-
return words;
|
|
25498
|
-
}
|
|
25499
|
-
function commandWords(command) {
|
|
25500
|
-
const payload = shellPayload(command);
|
|
25501
|
-
if (!payload || /[;|<>]|&&/.test(payload)) return null;
|
|
25502
|
-
return splitShellWords(payload);
|
|
25503
|
-
}
|
|
25504
|
-
function skillNamesFromCommand(command) {
|
|
25505
|
-
const words = commandWords(command);
|
|
25506
|
-
if (!words) return [];
|
|
25507
|
-
return Array.from(new Set(words.flatMap((word) => {
|
|
25508
|
-
const skillName = skillNameFromSkillRootPath(word);
|
|
25509
|
-
return skillName ? [skillName] : [];
|
|
25510
|
-
})));
|
|
25511
|
-
}
|
|
25512
|
-
|
|
25513
|
-
// ../shared/src/display-message/parsers/codex-parser.ts
|
|
25514
|
-
function getStatusFromExitCode(exitCode) {
|
|
25515
|
-
return exitCode === 0 ? "completed" : "failed";
|
|
25516
|
-
}
|
|
25517
|
-
function getPayloadString(event, key) {
|
|
25518
|
-
const value = event.payload?.[key];
|
|
25519
|
-
return typeof value === "string" ? value : null;
|
|
25520
|
-
}
|
|
25521
|
-
function displayId(event, eventIndex, prefix) {
|
|
25522
|
-
const stableId = getPayloadString(event, USER_MESSAGE_ID_PAYLOAD_KEY) ?? getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY);
|
|
25523
|
-
return stableId ? `${prefix}-${stableId}` : `${prefix}-${event.timestamp}-${eventIndex}`;
|
|
25524
|
-
}
|
|
25525
|
-
function parseShellOutput(raw) {
|
|
25526
|
-
const exitCodeMatch = raw.match(/^Exit code: (\d+)/m) || raw.match(/Process exited with code (\d+)/);
|
|
25527
|
-
const exitCode = exitCodeMatch ? parseInt(exitCodeMatch[1], 10) : 0;
|
|
25528
|
-
const outputIndex = raw.indexOf("Output:\n");
|
|
25529
|
-
const output = outputIndex >= 0 ? raw.slice(outputIndex + "Output:\n".length) : raw;
|
|
25530
|
-
return { exitCode, output };
|
|
24729
|
+
function parseShellOutput(raw) {
|
|
24730
|
+
const exitCodeMatch = raw.match(/^Exit code: (\d+)/m) || raw.match(/Process exited with code (\d+)/);
|
|
24731
|
+
const exitCode = exitCodeMatch ? parseInt(exitCodeMatch[1], 10) : 0;
|
|
24732
|
+
const outputIndex = raw.indexOf("Output:\n");
|
|
24733
|
+
const output = outputIndex >= 0 ? raw.slice(outputIndex + "Output:\n".length) : raw;
|
|
24734
|
+
return { exitCode, output };
|
|
25531
24735
|
}
|
|
25532
24736
|
function parsePatch(input) {
|
|
25533
24737
|
const operations = [];
|
|
@@ -26204,6 +25408,44 @@ function parseFxEvents(events) {
|
|
|
26204
25408
|
return parseAcpEvents(events, "fx");
|
|
26205
25409
|
}
|
|
26206
25410
|
|
|
25411
|
+
// ../shared/src/errors.ts
|
|
25412
|
+
var TRANSIENT_NETWORK_ERROR_PATTERNS = [
|
|
25413
|
+
/socket connection was closed unexpectedly/,
|
|
25414
|
+
/fetch failed/,
|
|
25415
|
+
/network error/,
|
|
25416
|
+
/network request failed/,
|
|
25417
|
+
/econnreset/,
|
|
25418
|
+
/econnrefused/,
|
|
25419
|
+
/etimedout/,
|
|
25420
|
+
/enotfound/,
|
|
25421
|
+
/eai_again/,
|
|
25422
|
+
/und_err_socket/,
|
|
25423
|
+
/und_err_connect_timeout/,
|
|
25424
|
+
/headers timeout/,
|
|
25425
|
+
/body timeout/,
|
|
25426
|
+
/connection reset/,
|
|
25427
|
+
/connection closed/,
|
|
25428
|
+
/closed unexpectedly/
|
|
25429
|
+
];
|
|
25430
|
+
var HTTP_CONTEXT_PATTERN = /(api error|request|response|status|http)/;
|
|
25431
|
+
var HTTP_STATUS_PATTERN = /(^|[^0-9])([1-5][0-9]{2})(?=$|[^0-9])/g;
|
|
25432
|
+
function isTransientErrorText(text, options = {}) {
|
|
25433
|
+
const normalized = text.toLowerCase();
|
|
25434
|
+
if (!normalized) return false;
|
|
25435
|
+
if (TRANSIENT_NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(normalized))) return true;
|
|
25436
|
+
if (options.includeRateLimit && /rate limit/.test(normalized)) return true;
|
|
25437
|
+
if (options.extraPatterns?.some((pattern) => pattern.test(normalized))) return true;
|
|
25438
|
+
const httpStatuses = new Set(options.httpStatuses ?? []);
|
|
25439
|
+
const httpStatusClasses = new Set(options.httpStatusClasses ?? []);
|
|
25440
|
+
if (httpStatuses.size === 0 && httpStatusClasses.size === 0) return false;
|
|
25441
|
+
if (options.requireHttpContext !== false && !HTTP_CONTEXT_PATTERN.test(normalized)) return false;
|
|
25442
|
+
for (const match of normalized.matchAll(HTTP_STATUS_PATTERN)) {
|
|
25443
|
+
const status = Number(match[2]);
|
|
25444
|
+
if (httpStatuses.has(status) || httpStatusClasses.has(Math.floor(status / 100))) return true;
|
|
25445
|
+
}
|
|
25446
|
+
return false;
|
|
25447
|
+
}
|
|
25448
|
+
|
|
26207
25449
|
// ../shared/src/display-message/parsers/inference-error.ts
|
|
26208
25450
|
var TRANSIENT_HTTP_STATUSES = [408, 429, 500, 502, 503, 504, 529];
|
|
26209
25451
|
var SERVER_ERROR_TEXT_PATTERN = /internal ?server ?error|server ?error|service unavailable|bad gateway|gateway timeout|overloaded|too many requests/i;
|
|
@@ -26694,6 +25936,15 @@ function parseMcpToolName(name) {
|
|
|
26694
25936
|
return { server, tool };
|
|
26695
25937
|
}
|
|
26696
25938
|
|
|
25939
|
+
// ../shared/src/user-message-matching.ts
|
|
25940
|
+
function parseTimestampMs(timestamp) {
|
|
25941
|
+
const value = Date.parse(timestamp);
|
|
25942
|
+
return Number.isFinite(value) ? value : 0;
|
|
25943
|
+
}
|
|
25944
|
+
function areUserMessagesWithinMatchWindow(a, b) {
|
|
25945
|
+
return a.content === b.content && Math.abs(parseTimestampMs(a.timestamp) - parseTimestampMs(b.timestamp)) <= USER_MESSAGE_MATCH_GRACE_PERIOD_MS;
|
|
25946
|
+
}
|
|
25947
|
+
|
|
26697
25948
|
// ../shared/src/display-message/parsers/claude-parser.ts
|
|
26698
25949
|
var ABORTED_TERMINAL_REASONS = /* @__PURE__ */ new Set(["aborted_streaming", "aborted_tools"]);
|
|
26699
25950
|
function coerceClaudeResultPayload(payload) {
|
|
@@ -27060,577 +26311,1368 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
27060
26311
|
timestamp: event.timestamp
|
|
27061
26312
|
});
|
|
27062
26313
|
} else {
|
|
27063
|
-
messages.push({
|
|
27064
|
-
id: `toolcall-${event.timestamp}-${messages.length}`,
|
|
27065
|
-
type: "tool_call",
|
|
27066
|
-
server: "claude",
|
|
27067
|
-
tool: toolName,
|
|
27068
|
-
input: toolInput,
|
|
27069
|
-
status: "in_progress",
|
|
27070
|
-
timestamp: event.timestamp
|
|
27071
|
-
});
|
|
26314
|
+
messages.push({
|
|
26315
|
+
id: `toolcall-${event.timestamp}-${messages.length}`,
|
|
26316
|
+
type: "tool_call",
|
|
26317
|
+
server: "claude",
|
|
26318
|
+
tool: toolName,
|
|
26319
|
+
input: toolInput,
|
|
26320
|
+
status: "in_progress",
|
|
26321
|
+
timestamp: event.timestamp
|
|
26322
|
+
});
|
|
26323
|
+
}
|
|
26324
|
+
}
|
|
26325
|
+
});
|
|
26326
|
+
}
|
|
26327
|
+
if (event.type === "claude-result") {
|
|
26328
|
+
const payload = coerceClaudeResultPayload(event.payload);
|
|
26329
|
+
if (isClaudeResultError(payload)) {
|
|
26330
|
+
const genuineErrors = stripAgentDiagnosticErrors(payload.errors ?? []);
|
|
26331
|
+
messages.push({
|
|
26332
|
+
id: `error-${event.timestamp}`,
|
|
26333
|
+
type: "error",
|
|
26334
|
+
message: genuineErrors.length > 0 ? genuineErrors.join("\n") : "Claude session encountered an unexpected error.",
|
|
26335
|
+
timestamp: event.timestamp
|
|
26336
|
+
});
|
|
26337
|
+
}
|
|
26338
|
+
}
|
|
26339
|
+
if (event.type === "claude-system") {
|
|
26340
|
+
const payload = coerceBackgroundTaskPayload(event.payload);
|
|
26341
|
+
if (payload?.ambient) ambientTaskIds.add(payload.taskId);
|
|
26342
|
+
if (payload && !ambientTaskIds.has(payload.taskId)) {
|
|
26343
|
+
const existing = taskMessageMap.get(payload.taskId);
|
|
26344
|
+
const nextStatus = payload.subtype === "task_notification" ? normalizeBackgroundTaskStatus(payload.status) : payload.subtype === "task_updated" ? normalizeBackgroundTaskStatus(payload.patch?.status) : existing?.status ?? "in_progress";
|
|
26345
|
+
const nextMessage = {
|
|
26346
|
+
id: existing?.id ?? `task-${event.timestamp}-${messages.length}`,
|
|
26347
|
+
type: "background_task",
|
|
26348
|
+
taskId: payload.taskId,
|
|
26349
|
+
status: nextStatus,
|
|
26350
|
+
description: payload.description ?? payload.patch?.description ?? existing?.description,
|
|
26351
|
+
summary: payload.summary ?? existing?.summary,
|
|
26352
|
+
outputFile: payload.outputFile ?? existing?.outputFile,
|
|
26353
|
+
taskType: payload.taskType ?? existing?.taskType,
|
|
26354
|
+
workflowName: payload.workflowName ?? existing?.workflowName,
|
|
26355
|
+
prompt: payload.prompt ?? existing?.prompt,
|
|
26356
|
+
lastToolName: payload.lastToolName ?? existing?.lastToolName,
|
|
26357
|
+
usage: payload.usage ?? existing?.usage,
|
|
26358
|
+
error: payload.patch?.error ?? existing?.error,
|
|
26359
|
+
isBackgrounded: payload.patch?.isBackgrounded ?? existing?.isBackgrounded,
|
|
26360
|
+
timestamp: existing?.timestamp ?? event.timestamp
|
|
26361
|
+
};
|
|
26362
|
+
if (existing) {
|
|
26363
|
+
Object.assign(existing, nextMessage);
|
|
26364
|
+
} else {
|
|
26365
|
+
taskMessageMap.set(payload.taskId, nextMessage);
|
|
26366
|
+
messages.push(nextMessage);
|
|
26367
|
+
}
|
|
26368
|
+
}
|
|
26369
|
+
}
|
|
26370
|
+
});
|
|
26371
|
+
filteredEvents.forEach((event) => {
|
|
26372
|
+
if (event.type === "replicas-tool-input-request") {
|
|
26373
|
+
const payload = event.payload;
|
|
26374
|
+
if (!payload.toolUseId || !payload.requestId) return;
|
|
26375
|
+
if (!Array.isArray(payload.options) && !Array.isArray(payload.questions)) return;
|
|
26376
|
+
const toolInfo = toolCallMap.get(payload.toolUseId);
|
|
26377
|
+
if (!toolInfo) return;
|
|
26378
|
+
const message = messages[toolInfo.messageIndex];
|
|
26379
|
+
if (!message || message.type !== "tool_call") return;
|
|
26380
|
+
message.inputRequest = {
|
|
26381
|
+
requestId: payload.requestId,
|
|
26382
|
+
status: "pending",
|
|
26383
|
+
options: payload.options,
|
|
26384
|
+
questions: payload.questions
|
|
26385
|
+
};
|
|
26386
|
+
}
|
|
26387
|
+
if (event.type === "replicas-tool-input-resolved") {
|
|
26388
|
+
const payload = event.payload;
|
|
26389
|
+
if (!payload.toolUseId || !payload.selectionId) return;
|
|
26390
|
+
const toolInfo = toolCallMap.get(payload.toolUseId);
|
|
26391
|
+
if (!toolInfo) return;
|
|
26392
|
+
const message = messages[toolInfo.messageIndex];
|
|
26393
|
+
if (!message || message.type !== "tool_call" || !message.inputRequest) return;
|
|
26394
|
+
message.inputRequest = {
|
|
26395
|
+
...message.inputRequest,
|
|
26396
|
+
status: payload.selectionId === "aborted" ? "aborted" : "resolved",
|
|
26397
|
+
selectionId: payload.selectionId,
|
|
26398
|
+
selectionSummary: payload.selectionSummary
|
|
26399
|
+
};
|
|
26400
|
+
}
|
|
26401
|
+
});
|
|
26402
|
+
filteredEvents.forEach((event) => {
|
|
26403
|
+
if (event.type === "claude-user") {
|
|
26404
|
+
const content = normalizeContentBlocks(event.payload.message?.content);
|
|
26405
|
+
const toolResult = content.find((c) => c.type === "tool_result");
|
|
26406
|
+
if (toolResult && toolResult.tool_use_id) {
|
|
26407
|
+
const toolInfo = toolCallMap.get(toolResult.tool_use_id);
|
|
26408
|
+
if (!toolInfo) return;
|
|
26409
|
+
const resultContent = extractToolResultText(toolResult.content);
|
|
26410
|
+
const isError = toolResult.is_error || false;
|
|
26411
|
+
const status = isError ? "failed" : "completed";
|
|
26412
|
+
if (toolInfo.toolName === "TaskCreate" && !isError) {
|
|
26413
|
+
taskAccumulator.processContentBlock(toolResult);
|
|
26414
|
+
}
|
|
26415
|
+
const message = messages[toolInfo.messageIndex];
|
|
26416
|
+
if (!message) return;
|
|
26417
|
+
if (message.type === "command") {
|
|
26418
|
+
message.output = resultContent;
|
|
26419
|
+
message.status = status;
|
|
26420
|
+
const exitCodeMatch = resultContent.match(/exit code:?\s*(\d+)/i);
|
|
26421
|
+
if (exitCodeMatch) {
|
|
26422
|
+
message.exitCode = parseInt(exitCodeMatch[1], 10);
|
|
26423
|
+
} else {
|
|
26424
|
+
message.exitCode = isError ? 1 : 0;
|
|
26425
|
+
}
|
|
26426
|
+
} else if (message.type === "patch") {
|
|
26427
|
+
message.status = status;
|
|
26428
|
+
} else if (message.type === "web_search") {
|
|
26429
|
+
message.status = status;
|
|
26430
|
+
} else if (message.type === "tool_call") {
|
|
26431
|
+
message.output = resultContent;
|
|
26432
|
+
message.status = status;
|
|
26433
|
+
} else if (message.type === "skill") {
|
|
26434
|
+
message.status = status;
|
|
26435
|
+
} else if (message.type === "subagent") {
|
|
26436
|
+
message.output = resultContent;
|
|
26437
|
+
message.status = status;
|
|
26438
|
+
if (!message.chatId && resultContent) {
|
|
26439
|
+
const parsed = safeJsonParse(resultContent, {});
|
|
26440
|
+
if (parsed.chatId) {
|
|
26441
|
+
message.chatId = parsed.chatId;
|
|
26442
|
+
}
|
|
26443
|
+
}
|
|
26444
|
+
} else if (message.type === "subagent_followup") {
|
|
26445
|
+
message.output = resultContent;
|
|
26446
|
+
message.status = status;
|
|
26447
|
+
}
|
|
26448
|
+
}
|
|
26449
|
+
}
|
|
26450
|
+
});
|
|
26451
|
+
for (const message of messages) {
|
|
26452
|
+
if (message.type !== "subagent_followup") continue;
|
|
26453
|
+
const target = messages.find((candidate) => candidate.type === "subagent" && candidate.chatId === message.chatId);
|
|
26454
|
+
if (target?.type === "subagent") {
|
|
26455
|
+
message.targetTitle = target.description;
|
|
26456
|
+
message.targetProvider = target.subagentType;
|
|
26457
|
+
}
|
|
26458
|
+
}
|
|
26459
|
+
const staleIndexes = new Set(supersededUserMessageIndexes);
|
|
26460
|
+
for (const streamId of [...completedStreamIds, ...supersededStreamIds]) {
|
|
26461
|
+
const refs = partialIndexes.get(streamId);
|
|
26462
|
+
if (refs?.reasoning !== void 0) staleIndexes.add(refs.reasoning);
|
|
26463
|
+
if (refs?.agent !== void 0) staleIndexes.add(refs.agent);
|
|
26464
|
+
}
|
|
26465
|
+
if (staleIndexes.size === 0) return messages;
|
|
26466
|
+
return messages.filter((_2, index) => !staleIndexes.has(index));
|
|
26467
|
+
}
|
|
26468
|
+
|
|
26469
|
+
// ../shared/src/display-message/parsers/codex-asp-parser.ts
|
|
26470
|
+
var DUPLICATE_WINDOW_MS = 5 * 60 * 1e3;
|
|
26471
|
+
function nearTimestamp(a, b) {
|
|
26472
|
+
return Math.abs(parseTimestampMs(a) - parseTimestampMs(b)) <= DUPLICATE_WINDOW_MS;
|
|
26473
|
+
}
|
|
26474
|
+
function inputForDisplay(input) {
|
|
26475
|
+
if (input === void 0 || input === null) return void 0;
|
|
26476
|
+
if (typeof input === "string") return input;
|
|
26477
|
+
if (isRecord(input)) return input;
|
|
26478
|
+
return String(input);
|
|
26479
|
+
}
|
|
26480
|
+
function isInternalUserMessage(content) {
|
|
26481
|
+
const trimmed = content.trim();
|
|
26482
|
+
return trimmed.startsWith("<environment_context>") || trimmed.startsWith("<goal_context>");
|
|
26483
|
+
}
|
|
26484
|
+
function messageForItem(item) {
|
|
26485
|
+
if (item.type === "userMessage") {
|
|
26486
|
+
if (isInternalUserMessage(item.content)) return null;
|
|
26487
|
+
return {
|
|
26488
|
+
id: `user-${item.id}`,
|
|
26489
|
+
type: "user",
|
|
26490
|
+
content: item.content,
|
|
26491
|
+
images: item.images,
|
|
26492
|
+
timestamp: item.timestamp
|
|
26493
|
+
};
|
|
26494
|
+
}
|
|
26495
|
+
if (item.type === "agentMessage") {
|
|
26496
|
+
if (!item.text) return null;
|
|
26497
|
+
return {
|
|
26498
|
+
id: `agent-${item.id}`,
|
|
26499
|
+
type: "agent",
|
|
26500
|
+
content: item.text,
|
|
26501
|
+
timestamp: item.timestamp
|
|
26502
|
+
};
|
|
26503
|
+
}
|
|
26504
|
+
if (item.type === "reasoning") {
|
|
26505
|
+
if (!item.text) return null;
|
|
26506
|
+
return {
|
|
26507
|
+
id: `reasoning-${item.id}`,
|
|
26508
|
+
type: "reasoning",
|
|
26509
|
+
content: item.text,
|
|
26510
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26511
|
+
timestamp: item.timestamp,
|
|
26512
|
+
...item.sourceTimestamp ? { sourceTimestamp: item.sourceTimestamp } : {}
|
|
26513
|
+
};
|
|
26514
|
+
}
|
|
26515
|
+
if (item.type === "commandExecution") {
|
|
26516
|
+
const skillNames = skillNamesFromCommand(item.command);
|
|
26517
|
+
return {
|
|
26518
|
+
id: `command-${item.id}`,
|
|
26519
|
+
type: "command",
|
|
26520
|
+
command: item.command,
|
|
26521
|
+
...skillNames.length > 0 ? { skillNames } : {},
|
|
26522
|
+
output: item.output,
|
|
26523
|
+
exitCode: item.exitCode ?? void 0,
|
|
26524
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26525
|
+
timestamp: item.timestamp
|
|
26526
|
+
};
|
|
26527
|
+
}
|
|
26528
|
+
if (item.type === "fileChange") {
|
|
26529
|
+
return {
|
|
26530
|
+
id: `patch-${item.id}`,
|
|
26531
|
+
type: "patch",
|
|
26532
|
+
operations: item.operations,
|
|
26533
|
+
output: item.output,
|
|
26534
|
+
exitCode: item.exitCode ?? void 0,
|
|
26535
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26536
|
+
timestamp: item.timestamp
|
|
26537
|
+
};
|
|
26538
|
+
}
|
|
26539
|
+
if (item.type === "toolCall") {
|
|
26540
|
+
return createCallDisplayMessage({
|
|
26541
|
+
id: `toolcall-${item.id}`,
|
|
26542
|
+
server: item.server,
|
|
26543
|
+
tool: item.tool,
|
|
26544
|
+
input: inputForDisplay(item.input),
|
|
26545
|
+
output: item.output,
|
|
26546
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26547
|
+
timestamp: item.timestamp
|
|
26548
|
+
});
|
|
26549
|
+
}
|
|
26550
|
+
if (item.type === "subagent") {
|
|
26551
|
+
return {
|
|
26552
|
+
id: `subagent-${item.id}`,
|
|
26553
|
+
type: "subagent",
|
|
26554
|
+
toolUseId: item.id,
|
|
26555
|
+
description: item.description,
|
|
26556
|
+
prompt: item.prompt,
|
|
26557
|
+
subagentType: item.subagentType,
|
|
26558
|
+
...item.receiverThreadIds ? { receiverThreadIds: item.receiverThreadIds } : {},
|
|
26559
|
+
...item.model ? { model: item.model } : {},
|
|
26560
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26561
|
+
...item.output ? { output: item.output } : {},
|
|
26562
|
+
nestedEvents: [],
|
|
26563
|
+
timestamp: item.timestamp
|
|
26564
|
+
};
|
|
26565
|
+
}
|
|
26566
|
+
if (item.type === "webSearch") {
|
|
26567
|
+
return {
|
|
26568
|
+
id: `web-search-${item.id}`,
|
|
26569
|
+
type: "web_search",
|
|
26570
|
+
query: item.query,
|
|
26571
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26572
|
+
timestamp: item.timestamp
|
|
26573
|
+
};
|
|
26574
|
+
}
|
|
26575
|
+
if (item.type === "plan") {
|
|
26576
|
+
if (!item.text) return null;
|
|
26577
|
+
return {
|
|
26578
|
+
id: `todo-${item.id}`,
|
|
26579
|
+
type: "todo_list",
|
|
26580
|
+
items: item.text.split("\n").map((line) => line.trim()).filter(Boolean).map((text) => ({ text, completed: item.status === "completed" })),
|
|
26581
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26582
|
+
timestamp: item.timestamp
|
|
26583
|
+
};
|
|
26584
|
+
}
|
|
26585
|
+
if (item.type === "contextCompaction") {
|
|
26586
|
+
return {
|
|
26587
|
+
id: `reasoning-${item.id}`,
|
|
26588
|
+
type: "reasoning",
|
|
26589
|
+
content: "Context compacted",
|
|
26590
|
+
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
26591
|
+
timestamp: item.timestamp
|
|
26592
|
+
};
|
|
26593
|
+
}
|
|
26594
|
+
return {
|
|
26595
|
+
id: `error-${item.id}`,
|
|
26596
|
+
type: "error",
|
|
26597
|
+
message: item.message,
|
|
26598
|
+
timestamp: item.timestamp
|
|
26599
|
+
};
|
|
26600
|
+
}
|
|
26601
|
+
function skillMessagesForItem(item) {
|
|
26602
|
+
if (item.type !== "userMessage" || !item.skillNames) return [];
|
|
26603
|
+
return item.skillNames.filter((skillName) => skillName.trim().length > 0).map((skillName, index) => ({
|
|
26604
|
+
id: `skill-${item.id}-${index}`,
|
|
26605
|
+
type: "skill",
|
|
26606
|
+
skillName,
|
|
26607
|
+
status: "completed",
|
|
26608
|
+
timestamp: item.timestamp
|
|
26609
|
+
}));
|
|
26610
|
+
}
|
|
26611
|
+
function stableString(value) {
|
|
26612
|
+
if (value === void 0) return "";
|
|
26613
|
+
if (typeof value !== "object" || value === null) return String(value);
|
|
26614
|
+
try {
|
|
26615
|
+
return JSON.stringify(value, Object.keys(value).sort());
|
|
26616
|
+
} catch {
|
|
26617
|
+
return String(value);
|
|
26618
|
+
}
|
|
26619
|
+
}
|
|
26620
|
+
function duplicateKey(message) {
|
|
26621
|
+
if (message.type === "user" || message.type === "agent" || message.type === "reasoning") {
|
|
26622
|
+
return JSON.stringify([message.type, message.content]);
|
|
26623
|
+
}
|
|
26624
|
+
if (message.type === "command") return JSON.stringify([message.type, message.command]);
|
|
26625
|
+
if (message.type === "web_search") return JSON.stringify([message.type, message.query]);
|
|
26626
|
+
if (message.type === "subagent") {
|
|
26627
|
+
return JSON.stringify([
|
|
26628
|
+
message.type,
|
|
26629
|
+
message.description,
|
|
26630
|
+
message.prompt,
|
|
26631
|
+
message.subagentType,
|
|
26632
|
+
message.model
|
|
26633
|
+
]);
|
|
26634
|
+
}
|
|
26635
|
+
if (message.type === "todo_list") {
|
|
26636
|
+
return JSON.stringify([message.type, stableString(message.items)]);
|
|
26637
|
+
}
|
|
26638
|
+
if (message.type === "patch") {
|
|
26639
|
+
return JSON.stringify([message.type, stableString(message.operations)]);
|
|
26640
|
+
}
|
|
26641
|
+
if (message.type === "tool_call") {
|
|
26642
|
+
return JSON.stringify([
|
|
26643
|
+
message.type,
|
|
26644
|
+
message.server,
|
|
26645
|
+
message.tool,
|
|
26646
|
+
stableString(message.input)
|
|
26647
|
+
]);
|
|
26648
|
+
}
|
|
26649
|
+
return null;
|
|
26650
|
+
}
|
|
26651
|
+
function duplicateBucketKey(message, bucketOffset = 0) {
|
|
26652
|
+
const key = duplicateKey(message);
|
|
26653
|
+
if (key === null) return null;
|
|
26654
|
+
const bucket = Math.floor(parseTimestampMs(message.timestamp) / DUPLICATE_WINDOW_MS) + bucketOffset;
|
|
26655
|
+
return JSON.stringify([bucket, key]);
|
|
26656
|
+
}
|
|
26657
|
+
function mergeCodexAspDisplayMessages(primary, supplemental) {
|
|
26658
|
+
const merged = [...primary];
|
|
26659
|
+
const primaryCount = primary.length;
|
|
26660
|
+
const firstIndexById = /* @__PURE__ */ new Map();
|
|
26661
|
+
const indexesByDuplicateBucket = /* @__PURE__ */ new Map();
|
|
26662
|
+
const indexMessage = (message, index) => {
|
|
26663
|
+
if (!firstIndexById.has(message.id)) firstIndexById.set(message.id, index);
|
|
26664
|
+
const key = duplicateBucketKey(message);
|
|
26665
|
+
if (key === null) return;
|
|
26666
|
+
const indexes = indexesByDuplicateBucket.get(key) ?? /* @__PURE__ */ new Set();
|
|
26667
|
+
indexes.add(index);
|
|
26668
|
+
indexesByDuplicateBucket.set(key, indexes);
|
|
26669
|
+
};
|
|
26670
|
+
const unindexMessage = (message, index) => {
|
|
26671
|
+
const key = duplicateBucketKey(message);
|
|
26672
|
+
if (key === null) return;
|
|
26673
|
+
const indexes = indexesByDuplicateBucket.get(key);
|
|
26674
|
+
indexes?.delete(index);
|
|
26675
|
+
if (indexes?.size === 0) indexesByDuplicateBucket.delete(key);
|
|
26676
|
+
};
|
|
26677
|
+
merged.forEach(indexMessage);
|
|
26678
|
+
for (const message of supplemental) {
|
|
26679
|
+
let duplicateIndex = firstIndexById.get(message.id);
|
|
26680
|
+
if (duplicateIndex === void 0) {
|
|
26681
|
+
for (let bucketOffset = -1; bucketOffset <= 1; bucketOffset += 1) {
|
|
26682
|
+
const key = duplicateBucketKey(message, bucketOffset);
|
|
26683
|
+
for (const index of (key === null ? void 0 : indexesByDuplicateBucket.get(key)) ?? []) {
|
|
26684
|
+
if (nearTimestamp(merged[index].timestamp, message.timestamp) && (duplicateIndex === void 0 || index < duplicateIndex)) {
|
|
26685
|
+
duplicateIndex = index;
|
|
27072
26686
|
}
|
|
27073
26687
|
}
|
|
27074
|
-
});
|
|
27075
|
-
}
|
|
27076
|
-
if (event.type === "claude-result") {
|
|
27077
|
-
const payload = coerceClaudeResultPayload(event.payload);
|
|
27078
|
-
if (isClaudeResultError(payload)) {
|
|
27079
|
-
const genuineErrors = stripAgentDiagnosticErrors(payload.errors ?? []);
|
|
27080
|
-
messages.push({
|
|
27081
|
-
id: `error-${event.timestamp}`,
|
|
27082
|
-
type: "error",
|
|
27083
|
-
message: genuineErrors.length > 0 ? genuineErrors.join("\n") : "Claude session encountered an unexpected error.",
|
|
27084
|
-
timestamp: event.timestamp
|
|
27085
|
-
});
|
|
27086
|
-
}
|
|
27087
|
-
}
|
|
27088
|
-
if (event.type === "claude-system") {
|
|
27089
|
-
const payload = coerceBackgroundTaskPayload(event.payload);
|
|
27090
|
-
if (payload?.ambient) ambientTaskIds.add(payload.taskId);
|
|
27091
|
-
if (payload && !ambientTaskIds.has(payload.taskId)) {
|
|
27092
|
-
const existing = taskMessageMap.get(payload.taskId);
|
|
27093
|
-
const nextStatus = payload.subtype === "task_notification" ? normalizeBackgroundTaskStatus(payload.status) : payload.subtype === "task_updated" ? normalizeBackgroundTaskStatus(payload.patch?.status) : existing?.status ?? "in_progress";
|
|
27094
|
-
const nextMessage = {
|
|
27095
|
-
id: existing?.id ?? `task-${event.timestamp}-${messages.length}`,
|
|
27096
|
-
type: "background_task",
|
|
27097
|
-
taskId: payload.taskId,
|
|
27098
|
-
status: nextStatus,
|
|
27099
|
-
description: payload.description ?? payload.patch?.description ?? existing?.description,
|
|
27100
|
-
summary: payload.summary ?? existing?.summary,
|
|
27101
|
-
outputFile: payload.outputFile ?? existing?.outputFile,
|
|
27102
|
-
taskType: payload.taskType ?? existing?.taskType,
|
|
27103
|
-
workflowName: payload.workflowName ?? existing?.workflowName,
|
|
27104
|
-
prompt: payload.prompt ?? existing?.prompt,
|
|
27105
|
-
lastToolName: payload.lastToolName ?? existing?.lastToolName,
|
|
27106
|
-
usage: payload.usage ?? existing?.usage,
|
|
27107
|
-
error: payload.patch?.error ?? existing?.error,
|
|
27108
|
-
isBackgrounded: payload.patch?.isBackgrounded ?? existing?.isBackgrounded,
|
|
27109
|
-
timestamp: existing?.timestamp ?? event.timestamp
|
|
27110
|
-
};
|
|
27111
|
-
if (existing) {
|
|
27112
|
-
Object.assign(existing, nextMessage);
|
|
27113
|
-
} else {
|
|
27114
|
-
taskMessageMap.set(payload.taskId, nextMessage);
|
|
27115
|
-
messages.push(nextMessage);
|
|
27116
|
-
}
|
|
27117
26688
|
}
|
|
27118
26689
|
}
|
|
27119
|
-
|
|
27120
|
-
|
|
27121
|
-
if (
|
|
27122
|
-
|
|
27123
|
-
|
|
27124
|
-
|
|
27125
|
-
|
|
27126
|
-
if (!toolInfo) return;
|
|
27127
|
-
const message = messages[toolInfo.messageIndex];
|
|
27128
|
-
if (!message || message.type !== "tool_call") return;
|
|
27129
|
-
message.inputRequest = {
|
|
27130
|
-
requestId: payload.requestId,
|
|
27131
|
-
status: "pending",
|
|
27132
|
-
options: payload.options,
|
|
27133
|
-
questions: payload.questions
|
|
27134
|
-
};
|
|
27135
|
-
}
|
|
27136
|
-
if (event.type === "replicas-tool-input-resolved") {
|
|
27137
|
-
const payload = event.payload;
|
|
27138
|
-
if (!payload.toolUseId || !payload.selectionId) return;
|
|
27139
|
-
const toolInfo = toolCallMap.get(payload.toolUseId);
|
|
27140
|
-
if (!toolInfo) return;
|
|
27141
|
-
const message = messages[toolInfo.messageIndex];
|
|
27142
|
-
if (!message || message.type !== "tool_call" || !message.inputRequest) return;
|
|
27143
|
-
message.inputRequest = {
|
|
27144
|
-
...message.inputRequest,
|
|
27145
|
-
status: payload.selectionId === "aborted" ? "aborted" : "resolved",
|
|
27146
|
-
selectionId: payload.selectionId,
|
|
27147
|
-
selectionSummary: payload.selectionSummary
|
|
26690
|
+
if (duplicateIndex === void 0) {
|
|
26691
|
+
indexMessage(message, merged.push(message) - 1);
|
|
26692
|
+
} else if (message.type === "user") {
|
|
26693
|
+
unindexMessage(merged[duplicateIndex], duplicateIndex);
|
|
26694
|
+
merged[duplicateIndex] = {
|
|
26695
|
+
...merged[duplicateIndex],
|
|
26696
|
+
id: message.id
|
|
27148
26697
|
};
|
|
26698
|
+
firstIndexById.set(message.id, duplicateIndex);
|
|
26699
|
+
indexMessage(merged[duplicateIndex], duplicateIndex);
|
|
27149
26700
|
}
|
|
26701
|
+
}
|
|
26702
|
+
const ordered = merged.slice(0, primaryCount);
|
|
26703
|
+
const supplementalOnly = merged.slice(primaryCount).map((message, index) => ({ message, index })).sort((a, b) => parseTimestampMs(a.message.timestamp) - parseTimestampMs(b.message.timestamp) || a.index - b.index);
|
|
26704
|
+
for (const { message } of supplementalOnly) {
|
|
26705
|
+
insertDisplayMessageByTimestamp(ordered, message);
|
|
26706
|
+
}
|
|
26707
|
+
return ordered;
|
|
26708
|
+
}
|
|
26709
|
+
function parseCodexAspTranscript(transcript) {
|
|
26710
|
+
const messages = [];
|
|
26711
|
+
const orderedItems = transcript.turns.map((turn, turnIndex) => ({ turn, turnIndex })).flatMap(({ turn, turnIndex }) => turn.items.map((item, itemIndex) => ({ item, turn, turnIndex, itemIndex }))).sort((a, b) => {
|
|
26712
|
+
const aSequence = a.item.sequence ?? Number.MAX_SAFE_INTEGER;
|
|
26713
|
+
const bSequence = b.item.sequence ?? Number.MAX_SAFE_INTEGER;
|
|
26714
|
+
return aSequence - bSequence || parseTimestampMs(a.item.timestamp) - parseTimestampMs(b.item.timestamp) || a.turnIndex - b.turnIndex || a.itemIndex - b.itemIndex;
|
|
27150
26715
|
});
|
|
27151
|
-
|
|
27152
|
-
|
|
27153
|
-
|
|
27154
|
-
|
|
27155
|
-
|
|
27156
|
-
|
|
27157
|
-
|
|
27158
|
-
|
|
27159
|
-
|
|
27160
|
-
|
|
27161
|
-
|
|
27162
|
-
|
|
27163
|
-
|
|
27164
|
-
|
|
27165
|
-
|
|
27166
|
-
|
|
27167
|
-
|
|
27168
|
-
|
|
27169
|
-
|
|
27170
|
-
|
|
27171
|
-
|
|
27172
|
-
|
|
27173
|
-
|
|
27174
|
-
}
|
|
27175
|
-
} else if (message.type === "patch") {
|
|
27176
|
-
message.status = status;
|
|
27177
|
-
} else if (message.type === "web_search") {
|
|
27178
|
-
message.status = status;
|
|
27179
|
-
} else if (message.type === "tool_call") {
|
|
27180
|
-
message.output = resultContent;
|
|
27181
|
-
message.status = status;
|
|
27182
|
-
} else if (message.type === "skill") {
|
|
27183
|
-
message.status = status;
|
|
27184
|
-
} else if (message.type === "subagent") {
|
|
27185
|
-
message.output = resultContent;
|
|
27186
|
-
message.status = status;
|
|
27187
|
-
if (!message.chatId && resultContent) {
|
|
27188
|
-
const parsed = safeJsonParse(resultContent, {});
|
|
27189
|
-
if (parsed.chatId) {
|
|
27190
|
-
message.chatId = parsed.chatId;
|
|
27191
|
-
}
|
|
27192
|
-
}
|
|
27193
|
-
} else if (message.type === "subagent_followup") {
|
|
27194
|
-
message.output = resultContent;
|
|
27195
|
-
message.status = status;
|
|
27196
|
-
}
|
|
26716
|
+
const reasoningByTurnId = /* @__PURE__ */ new Map();
|
|
26717
|
+
for (const { item, turn } of orderedItems) {
|
|
26718
|
+
if (item.type !== "reasoning" || !item.text.trim()) continue;
|
|
26719
|
+
const reasoning = reasoningByTurnId.get(turn.id) ?? [];
|
|
26720
|
+
reasoning.push(item);
|
|
26721
|
+
reasoningByTurnId.set(turn.id, reasoning);
|
|
26722
|
+
}
|
|
26723
|
+
const emittedReasoningTurnIds = /* @__PURE__ */ new Set();
|
|
26724
|
+
const coalescedItems = orderedItems.flatMap((entry) => {
|
|
26725
|
+
if (entry.item.type !== "reasoning") return [entry];
|
|
26726
|
+
const reasoning = reasoningByTurnId.get(entry.turn.id);
|
|
26727
|
+
if (!reasoning || emittedReasoningTurnIds.has(entry.turn.id)) return [];
|
|
26728
|
+
emittedReasoningTurnIds.add(entry.turn.id);
|
|
26729
|
+
return [{
|
|
26730
|
+
...entry,
|
|
26731
|
+
item: {
|
|
26732
|
+
type: "reasoning",
|
|
26733
|
+
id: entry.turn.id,
|
|
26734
|
+
text: reasoning.map(({ text }) => text.trim()).join("\n\n"),
|
|
26735
|
+
timestamp: entry.turn.startedAt,
|
|
26736
|
+
...reasoning[0] ? { sourceTimestamp: reasoning[0].timestamp } : {},
|
|
26737
|
+
status: reasoning.at(-1)?.status ?? "completed",
|
|
26738
|
+
sequence: entry.item.sequence
|
|
27197
26739
|
}
|
|
27198
|
-
}
|
|
26740
|
+
}];
|
|
27199
26741
|
});
|
|
27200
|
-
for (const
|
|
27201
|
-
|
|
27202
|
-
|
|
27203
|
-
|
|
27204
|
-
|
|
27205
|
-
|
|
27206
|
-
}
|
|
26742
|
+
for (const turn of transcript.turns) {
|
|
26743
|
+
const reasoningIndex = coalescedItems.findIndex(({ item, turn: itemTurn }) => itemTurn.id === turn.id && item.type === "reasoning");
|
|
26744
|
+
if (reasoningIndex === -1) continue;
|
|
26745
|
+
const responseItem = getCodexAspTurnResponse({
|
|
26746
|
+
status: turn.status,
|
|
26747
|
+
items: coalescedItems.filter(({ turn: itemTurn }) => itemTurn.id === turn.id).map(({ item }) => item)
|
|
26748
|
+
});
|
|
26749
|
+
const finalAnswerIndex = responseItem ? coalescedItems.findIndex(({ item }) => item === responseItem) : -1;
|
|
26750
|
+
if (finalAnswerIndex === -1 || reasoningIndex < finalAnswerIndex) continue;
|
|
26751
|
+
const [reasoning] = coalescedItems.splice(reasoningIndex, 1);
|
|
26752
|
+
coalescedItems.splice(finalAnswerIndex, 0, reasoning);
|
|
27207
26753
|
}
|
|
27208
|
-
const
|
|
27209
|
-
|
|
27210
|
-
|
|
27211
|
-
|
|
27212
|
-
|
|
26754
|
+
for (const { item } of coalescedItems) {
|
|
26755
|
+
const message = messageForItem(item);
|
|
26756
|
+
if (message) {
|
|
26757
|
+
messages.push(message);
|
|
26758
|
+
}
|
|
26759
|
+
messages.push(...skillMessagesForItem(item));
|
|
27213
26760
|
}
|
|
27214
|
-
|
|
27215
|
-
return messages.filter((_2, index) => !staleIndexes.has(index));
|
|
26761
|
+
return messages;
|
|
27216
26762
|
}
|
|
27217
26763
|
|
|
27218
|
-
// ../shared/src/display-message/parsers/
|
|
27219
|
-
var
|
|
27220
|
-
function
|
|
27221
|
-
|
|
27222
|
-
|
|
27223
|
-
function inputForDisplay(input) {
|
|
27224
|
-
if (input === void 0 || input === null) return void 0;
|
|
27225
|
-
if (typeof input === "string") return input;
|
|
27226
|
-
if (isRecord(input)) return input;
|
|
27227
|
-
return String(input);
|
|
27228
|
-
}
|
|
27229
|
-
function isInternalUserMessage(content) {
|
|
27230
|
-
const trimmed = content.trim();
|
|
27231
|
-
return trimmed.startsWith("<environment_context>") || trimmed.startsWith("<goal_context>");
|
|
27232
|
-
}
|
|
27233
|
-
function messageForItem(item) {
|
|
27234
|
-
if (item.type === "userMessage") {
|
|
27235
|
-
if (isInternalUserMessage(item.content)) return null;
|
|
27236
|
-
return {
|
|
27237
|
-
id: `user-${item.id}`,
|
|
27238
|
-
type: "user",
|
|
27239
|
-
content: item.content,
|
|
27240
|
-
images: item.images,
|
|
27241
|
-
timestamp: item.timestamp
|
|
27242
|
-
};
|
|
26764
|
+
// ../shared/src/display-message/parsers/index.ts
|
|
26765
|
+
var INTERRUPTION_DEDUP_WINDOW_MS = 15e3;
|
|
26766
|
+
function parseAgentEvents(events, agentType) {
|
|
26767
|
+
if (agentType === "codex") {
|
|
26768
|
+
return parseCodexEvents(events);
|
|
27243
26769
|
}
|
|
27244
|
-
if (
|
|
27245
|
-
|
|
27246
|
-
return {
|
|
27247
|
-
id: `agent-${item.id}`,
|
|
27248
|
-
type: "agent",
|
|
27249
|
-
content: item.text,
|
|
27250
|
-
timestamp: item.timestamp
|
|
27251
|
-
};
|
|
26770
|
+
if (agentType === "cursor") {
|
|
26771
|
+
return parseCursorEvents(events);
|
|
27252
26772
|
}
|
|
27253
|
-
if (
|
|
27254
|
-
|
|
27255
|
-
return {
|
|
27256
|
-
id: `reasoning-${item.id}`,
|
|
27257
|
-
type: "reasoning",
|
|
27258
|
-
content: item.text,
|
|
27259
|
-
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
27260
|
-
timestamp: item.timestamp,
|
|
27261
|
-
...item.sourceTimestamp ? { sourceTimestamp: item.sourceTimestamp } : {}
|
|
27262
|
-
};
|
|
26773
|
+
if (agentType === "deepseek") {
|
|
26774
|
+
return parseDeepseekEvents(events);
|
|
27263
26775
|
}
|
|
27264
|
-
if (
|
|
27265
|
-
|
|
27266
|
-
return {
|
|
27267
|
-
id: `command-${item.id}`,
|
|
27268
|
-
type: "command",
|
|
27269
|
-
command: item.command,
|
|
27270
|
-
...skillNames.length > 0 ? { skillNames } : {},
|
|
27271
|
-
output: item.output,
|
|
27272
|
-
exitCode: item.exitCode ?? void 0,
|
|
27273
|
-
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
27274
|
-
timestamp: item.timestamp
|
|
27275
|
-
};
|
|
26776
|
+
if (agentType === "fx") {
|
|
26777
|
+
return parseFxEvents(events);
|
|
27276
26778
|
}
|
|
27277
|
-
if (
|
|
27278
|
-
return
|
|
27279
|
-
id: `patch-${item.id}`,
|
|
27280
|
-
type: "patch",
|
|
27281
|
-
operations: item.operations,
|
|
27282
|
-
output: item.output,
|
|
27283
|
-
exitCode: item.exitCode ?? void 0,
|
|
27284
|
-
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
27285
|
-
timestamp: item.timestamp
|
|
27286
|
-
};
|
|
26779
|
+
if (agentType === "kimi") {
|
|
26780
|
+
return parseAcpEvents(events, "kimi");
|
|
27287
26781
|
}
|
|
27288
|
-
if (
|
|
27289
|
-
return
|
|
27290
|
-
id: `toolcall-${item.id}`,
|
|
27291
|
-
server: item.server,
|
|
27292
|
-
tool: item.tool,
|
|
27293
|
-
input: inputForDisplay(item.input),
|
|
27294
|
-
output: item.output,
|
|
27295
|
-
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
27296
|
-
timestamp: item.timestamp
|
|
27297
|
-
});
|
|
26782
|
+
if (agentType === "muse") {
|
|
26783
|
+
return parseMuseEvents(events);
|
|
27298
26784
|
}
|
|
27299
|
-
if (
|
|
27300
|
-
return
|
|
27301
|
-
id: `subagent-${item.id}`,
|
|
27302
|
-
type: "subagent",
|
|
27303
|
-
toolUseId: item.id,
|
|
27304
|
-
description: item.description,
|
|
27305
|
-
prompt: item.prompt,
|
|
27306
|
-
subagentType: item.subagentType,
|
|
27307
|
-
...item.receiverThreadIds ? { receiverThreadIds: item.receiverThreadIds } : {},
|
|
27308
|
-
...item.model ? { model: item.model } : {},
|
|
27309
|
-
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
27310
|
-
...item.output ? { output: item.output } : {},
|
|
27311
|
-
nestedEvents: [],
|
|
27312
|
-
timestamp: item.timestamp
|
|
27313
|
-
};
|
|
26785
|
+
if (agentType === "opencode") {
|
|
26786
|
+
return parseOpencodeEvents(events);
|
|
27314
26787
|
}
|
|
27315
|
-
if (
|
|
27316
|
-
return
|
|
27317
|
-
id: `web-search-${item.id}`,
|
|
27318
|
-
type: "web_search",
|
|
27319
|
-
query: item.query,
|
|
27320
|
-
status: normalizeCodexAspTranscriptStatus(item.status),
|
|
27321
|
-
timestamp: item.timestamp
|
|
27322
|
-
};
|
|
26788
|
+
if (agentType === "pi") {
|
|
26789
|
+
return parsePiEvents(events);
|
|
27323
26790
|
}
|
|
27324
|
-
|
|
27325
|
-
|
|
27326
|
-
|
|
27327
|
-
|
|
27328
|
-
|
|
27329
|
-
|
|
27330
|
-
|
|
27331
|
-
|
|
27332
|
-
|
|
26791
|
+
return parseClaudeEvents(events);
|
|
26792
|
+
}
|
|
26793
|
+
function parseDisplayMessages(events, agentType, codexAspTranscript, options = {}) {
|
|
26794
|
+
const shouldFilter = options.filter ?? true;
|
|
26795
|
+
const parsedEvents = agentType === "claude" || agentType === "relay" ? parseClaudeEvents(events, options.parentToolUseId) : parseAgentEvents(events, agentType);
|
|
26796
|
+
const reconciledEvents = [];
|
|
26797
|
+
for (const message of parsedEvents) {
|
|
26798
|
+
if (message.type === "user") upsertDisplayMessage(reconciledEvents, message);
|
|
26799
|
+
else reconciledEvents.push(message);
|
|
27333
26800
|
}
|
|
27334
|
-
|
|
27335
|
-
|
|
27336
|
-
|
|
27337
|
-
|
|
27338
|
-
|
|
27339
|
-
|
|
27340
|
-
|
|
26801
|
+
const legacyMessages = shouldFilter ? filterDisplayMessages(reconciledEvents, agentType) : reconciledEvents;
|
|
26802
|
+
const applySyntheticNotices = (messages) => shouldFilter ? applyAuthFallbackNotices(applyInterruptions(messages, events), events) : messages;
|
|
26803
|
+
if (agentType !== "codex" || !codexAspTranscript) {
|
|
26804
|
+
return applySyntheticNotices(legacyMessages);
|
|
26805
|
+
}
|
|
26806
|
+
const nativeCodexMessages = shouldFilter ? filterDisplayMessages(parseCodexAspTranscript(codexAspTranscript), agentType) : parseCodexAspTranscript(codexAspTranscript);
|
|
26807
|
+
return applySyntheticNotices(mergeCodexAspDisplayMessages(nativeCodexMessages, legacyMessages));
|
|
26808
|
+
}
|
|
26809
|
+
function applyInterruptions(messages, events) {
|
|
26810
|
+
const result = [...messages];
|
|
26811
|
+
for (const event of events) {
|
|
26812
|
+
if (event.type !== CHAT_INTERRUPTED_EVENT_TYPE) continue;
|
|
26813
|
+
insertDisplayMessageByTimestamp(result, {
|
|
26814
|
+
id: `interruption-${event.timestamp}`,
|
|
26815
|
+
type: "interruption",
|
|
26816
|
+
timestamp: event.timestamp
|
|
26817
|
+
});
|
|
26818
|
+
}
|
|
26819
|
+
let lastUserMs = null;
|
|
26820
|
+
let lastInterruption = null;
|
|
26821
|
+
const finalized = [];
|
|
26822
|
+
for (const msg of result) {
|
|
26823
|
+
if (msg.type === "user") {
|
|
26824
|
+
lastUserMs = parseTimestampMs(msg.timestamp);
|
|
26825
|
+
lastInterruption = null;
|
|
26826
|
+
finalized.push(msg);
|
|
26827
|
+
continue;
|
|
26828
|
+
}
|
|
26829
|
+
if (msg.type !== "interruption") {
|
|
26830
|
+
finalized.push(msg);
|
|
26831
|
+
continue;
|
|
26832
|
+
}
|
|
26833
|
+
const ms = parseTimestampMs(msg.timestamp);
|
|
26834
|
+
if (lastInterruption && ms - parseTimestampMs(lastInterruption.timestamp) <= INTERRUPTION_DEDUP_WINDOW_MS) {
|
|
26835
|
+
continue;
|
|
26836
|
+
}
|
|
26837
|
+
lastInterruption = {
|
|
26838
|
+
...msg,
|
|
26839
|
+
...lastUserMs !== null && ms >= lastUserMs ? { durationMs: ms - lastUserMs } : {}
|
|
27341
26840
|
};
|
|
26841
|
+
finalized.push(lastInterruption);
|
|
26842
|
+
}
|
|
26843
|
+
return finalized;
|
|
26844
|
+
}
|
|
26845
|
+
function applyAuthFallbackNotices(messages, events) {
|
|
26846
|
+
const notices = [];
|
|
26847
|
+
events.forEach((event, index) => {
|
|
26848
|
+
if (event.type !== AUTH_FALLBACK_EVENT_TYPE) return;
|
|
26849
|
+
const payload = coerceAuthFallbackPayload(event.payload);
|
|
26850
|
+
if (!payload) return;
|
|
26851
|
+
notices.push({
|
|
26852
|
+
...payload,
|
|
26853
|
+
id: `auth-fallback-${event.timestamp}-${index}`,
|
|
26854
|
+
type: "auth_fallback",
|
|
26855
|
+
timestamp: event.timestamp
|
|
26856
|
+
});
|
|
26857
|
+
});
|
|
26858
|
+
if (notices.length === 0) return messages;
|
|
26859
|
+
const result = [...messages];
|
|
26860
|
+
for (const notice of notices) insertDisplayMessageByTimestamp(result, notice);
|
|
26861
|
+
return result;
|
|
26862
|
+
}
|
|
26863
|
+
function isCodexInitializationPrompt(message) {
|
|
26864
|
+
return message.type === "user" && removeReplicasInstructions(message.content).trim() === "Hello";
|
|
26865
|
+
}
|
|
26866
|
+
function filterDisplayMessages(messages, provider) {
|
|
26867
|
+
let result = messages;
|
|
26868
|
+
if (provider === "codex") {
|
|
26869
|
+
const userMessages = result.map((msg, index) => ({ msg, index })).filter(({ msg }) => msg.type === "user");
|
|
26870
|
+
if (userMessages.length >= 2 && isCodexInitializationPrompt(userMessages[0].msg)) {
|
|
26871
|
+
result = result.slice(userMessages[1].index);
|
|
26872
|
+
}
|
|
26873
|
+
}
|
|
26874
|
+
result = result.map((msg) => {
|
|
26875
|
+
if (msg.type !== "user") return msg;
|
|
26876
|
+
const cleaned = removeReplicasInstructions(msg.content).trim();
|
|
26877
|
+
if (INTERRUPTED_MESSAGE_REGEX.test(cleaned)) {
|
|
26878
|
+
return { id: msg.id, type: "interruption", timestamp: msg.timestamp };
|
|
26879
|
+
}
|
|
26880
|
+
return cleaned !== msg.content ? { ...msg, content: cleaned } : msg;
|
|
26881
|
+
});
|
|
26882
|
+
return result;
|
|
26883
|
+
}
|
|
26884
|
+
|
|
26885
|
+
// ../shared/src/agent-event-utils.ts
|
|
26886
|
+
function getUserMessage(event) {
|
|
26887
|
+
return event.type === "event_msg" && event.payload.type === "user_message" && typeof event.payload.message === "string" ? event.payload.message : null;
|
|
26888
|
+
}
|
|
26889
|
+
function getUserMessageId(event) {
|
|
26890
|
+
const messageId = event.payload[USER_MESSAGE_ID_PAYLOAD_KEY];
|
|
26891
|
+
return typeof messageId === "string" ? messageId : null;
|
|
26892
|
+
}
|
|
26893
|
+
|
|
26894
|
+
// ../shared/src/pricing.ts
|
|
26895
|
+
var AUTOMATED_SOURCES = ["api", "automation"];
|
|
26896
|
+
var AUTOMATED_SOURCES_SQL = AUTOMATED_SOURCES.map((s) => `'${s}'`).join(", ");
|
|
26897
|
+
var PLANS = {
|
|
26898
|
+
trial: {
|
|
26899
|
+
id: "trial",
|
|
26900
|
+
name: "Free Trial",
|
|
26901
|
+
monthlyPrice: 0,
|
|
26902
|
+
seatPriceCents: 0,
|
|
26903
|
+
features: [
|
|
26904
|
+
"14 days free, no credit card required",
|
|
26905
|
+
"Unlimited manual workspace minutes",
|
|
26906
|
+
"15,000 automated workspace minutes",
|
|
26907
|
+
"Unlimited repositories and environments",
|
|
26908
|
+
"Unlimited automations",
|
|
26909
|
+
"Warm pools and warm hooks",
|
|
26910
|
+
"API access"
|
|
26911
|
+
]
|
|
26912
|
+
},
|
|
26913
|
+
developer: {
|
|
26914
|
+
id: "developer",
|
|
26915
|
+
name: "Developer",
|
|
26916
|
+
monthlyPrice: 120,
|
|
26917
|
+
seatPriceCents: 12e3,
|
|
26918
|
+
features: [
|
|
26919
|
+
"Unlimited manual workspace minutes",
|
|
26920
|
+
"5,000 automated workspace minutes per month",
|
|
26921
|
+
"Up to 10 repositories",
|
|
26922
|
+
"Up to 15 environments",
|
|
26923
|
+
"Up to 5 automations",
|
|
26924
|
+
"Warm pools and warm hooks",
|
|
26925
|
+
"API access",
|
|
26926
|
+
"Mobile app"
|
|
26927
|
+
]
|
|
26928
|
+
},
|
|
26929
|
+
team: {
|
|
26930
|
+
id: "team",
|
|
26931
|
+
name: "Team",
|
|
26932
|
+
monthlyPrice: 300,
|
|
26933
|
+
seatPriceCents: 3e4,
|
|
26934
|
+
features: [
|
|
26935
|
+
"Unlimited manual workspace minutes",
|
|
26936
|
+
"15,000 automated workspace minutes per month",
|
|
26937
|
+
"Unlimited repositories",
|
|
26938
|
+
"Unlimited automations",
|
|
26939
|
+
"Warm pools and warm hooks",
|
|
26940
|
+
"Higher API rate limits",
|
|
26941
|
+
"Access to a static egress IP",
|
|
26942
|
+
"Auto-upgraded sandbox resources (4 vCPU, 32 GB disk, 16 GB memory)",
|
|
26943
|
+
"Shared Slack support channel"
|
|
26944
|
+
]
|
|
26945
|
+
},
|
|
26946
|
+
enterprise: {
|
|
26947
|
+
id: "enterprise",
|
|
26948
|
+
name: "Enterprise",
|
|
26949
|
+
monthlyPrice: 0,
|
|
26950
|
+
seatPriceCents: 0,
|
|
26951
|
+
features: [
|
|
26952
|
+
"Unlimited manual workspace minutes",
|
|
26953
|
+
"Unlimited automated workspace minutes",
|
|
26954
|
+
"Unlimited automations",
|
|
26955
|
+
"Custom warm hooks and pools",
|
|
26956
|
+
"Custom API rates",
|
|
26957
|
+
"Custom rate limits",
|
|
26958
|
+
"Shared Slack support channel",
|
|
26959
|
+
"SOC 2",
|
|
26960
|
+
"Data Processing Agreement (DPA)",
|
|
26961
|
+
"SCIM user provisioning",
|
|
26962
|
+
"Custom security and privacy settings"
|
|
26963
|
+
]
|
|
27342
26964
|
}
|
|
27343
|
-
|
|
27344
|
-
|
|
27345
|
-
|
|
27346
|
-
|
|
27347
|
-
|
|
27348
|
-
|
|
26965
|
+
};
|
|
26966
|
+
var TEAM_PLAN = PLANS.team;
|
|
26967
|
+
var ENTERPRISE_PLAN = PLANS.enterprise;
|
|
26968
|
+
|
|
26969
|
+
// ../shared/src/port.ts
|
|
26970
|
+
function isValidPort(port) {
|
|
26971
|
+
return Number.isInteger(port) && Number(port) >= 1 && Number(port) <= 65535;
|
|
27349
26972
|
}
|
|
27350
|
-
function
|
|
27351
|
-
if (
|
|
27352
|
-
|
|
27353
|
-
|
|
27354
|
-
|
|
27355
|
-
skillName,
|
|
27356
|
-
status: "completed",
|
|
27357
|
-
timestamp: item.timestamp
|
|
27358
|
-
}));
|
|
26973
|
+
function parsePort(port) {
|
|
26974
|
+
if (!/^\d+$/.test(port)) throw new Error("Port must be a number between 1 and 65535");
|
|
26975
|
+
const portNumber = Number(port);
|
|
26976
|
+
if (!isValidPort(portNumber)) throw new Error("Port must be a number between 1 and 65535");
|
|
26977
|
+
return portNumber;
|
|
27359
26978
|
}
|
|
27360
|
-
|
|
27361
|
-
|
|
27362
|
-
|
|
27363
|
-
|
|
27364
|
-
|
|
27365
|
-
|
|
27366
|
-
|
|
26979
|
+
|
|
26980
|
+
// ../shared/src/models-dev.ts
|
|
26981
|
+
var MODELS_DEV_CACHE_MS = 5 * 6e4;
|
|
26982
|
+
var modelsDevCatalogSchema = external_exports.record(external_exports.string(), external_exports.object({
|
|
26983
|
+
models: external_exports.record(external_exports.string(), external_exports.object({
|
|
26984
|
+
id: external_exports.string().optional(),
|
|
26985
|
+
name: external_exports.string(),
|
|
26986
|
+
description: external_exports.string().optional(),
|
|
26987
|
+
status: external_exports.enum(["alpha", "beta", "deprecated"]).optional(),
|
|
26988
|
+
cost: external_exports.object({
|
|
26989
|
+
input: external_exports.number().finite().nonnegative().optional(),
|
|
26990
|
+
output: external_exports.number().finite().nonnegative().optional(),
|
|
26991
|
+
cache_read: external_exports.number().finite().nonnegative().optional(),
|
|
26992
|
+
cache_write: external_exports.number().finite().nonnegative().optional()
|
|
26993
|
+
}).optional()
|
|
26994
|
+
}))
|
|
26995
|
+
}));
|
|
26996
|
+
|
|
26997
|
+
// ../shared/src/sandbox.ts
|
|
26998
|
+
var SANDBOX_LIFECYCLE = {
|
|
26999
|
+
AUTO_STOP_MINUTES: 60,
|
|
27000
|
+
AUTO_ARCHIVE_MINUTES: 60 * 24 * 7,
|
|
27001
|
+
AUTO_DELETE_MINUTES: -1,
|
|
27002
|
+
SSH_TOKEN_EXPIRATION_MINUTES: 3 * 60
|
|
27003
|
+
};
|
|
27004
|
+
var SANDBOX_PATHS = {
|
|
27005
|
+
HOME_DIR: "/home/user",
|
|
27006
|
+
WORKSPACES_DIR: "/home/user/workspaces",
|
|
27007
|
+
REPLICAS_DIR: "/home/user/.replicas",
|
|
27008
|
+
ENGINE_INIT_GATE: "/home/user/.replicas/engine-init-gate",
|
|
27009
|
+
REPLICAS_CANVAS_DIR: "/home/user/.replicas/canvas",
|
|
27010
|
+
REPLICAS_RUNTIME_ENV_FILE: "/home/user/.replicas/runtime-env.sh"
|
|
27011
|
+
};
|
|
27012
|
+
var WORKSPACE_SIZES = ["small", "large"];
|
|
27013
|
+
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
27014
|
+
|
|
27015
|
+
// ../shared/src/egress.ts
|
|
27016
|
+
var EGRESS_CIPHER = "2022-blake3-aes-256-gcm";
|
|
27017
|
+
var EGRESS_KEY_BYTES = 32;
|
|
27018
|
+
var EGRESS_SHADOWSOCKS_MODE = "tcp_and_udp";
|
|
27019
|
+
var EGRESS_SHADOWSOCKS_VERSION = "1.24.0";
|
|
27020
|
+
var EGRESS_SHADOWSOCKS_SHA256 = "0d84f5f350ec99396867d718f146fc3810975b2a7cd06192f158d96bdef460e7";
|
|
27021
|
+
var EGRESS_PORT_RANGE_START = 8400;
|
|
27022
|
+
var EGRESS_PORT_RANGE_END = 8499;
|
|
27023
|
+
var EGRESS_EXIT_IP_ENDPOINTS = [
|
|
27024
|
+
"https://checkip.amazonaws.com",
|
|
27025
|
+
"https://api.ipify.org",
|
|
27026
|
+
"https://icanhazip.com"
|
|
27027
|
+
];
|
|
27028
|
+
var EGRESS_DIRECT_ROUTES = [
|
|
27029
|
+
"10.0.0.0/8",
|
|
27030
|
+
"172.16.0.0/12",
|
|
27031
|
+
"192.168.0.0/16",
|
|
27032
|
+
"169.254.0.0/16",
|
|
27033
|
+
"100.64.0.0/10"
|
|
27034
|
+
];
|
|
27035
|
+
var EGRESS_NEW_CONN_RATE = 100;
|
|
27036
|
+
var EGRESS_NEW_CONN_BURST = 200;
|
|
27037
|
+
var EGRESS_UDP_RATE = 500;
|
|
27038
|
+
var EGRESS_UDP_BURST = 1e3;
|
|
27039
|
+
var EGRESS_OUT_CONN_RATE = 1e3;
|
|
27040
|
+
var EGRESS_OUT_CONN_BURST = 2e3;
|
|
27041
|
+
var EGRESS_DNS_SERVERS = ["1.1.1.1", "8.8.8.8"];
|
|
27042
|
+
var EGRESS_SHELL_CONFIG = [
|
|
27043
|
+
`EGRESS_PORT_RANGE_START=${EGRESS_PORT_RANGE_START}`,
|
|
27044
|
+
`EGRESS_PORT_RANGE_END=${EGRESS_PORT_RANGE_END}`,
|
|
27045
|
+
`EGRESS_SHADOWSOCKS_VERSION=${EGRESS_SHADOWSOCKS_VERSION}`,
|
|
27046
|
+
`EGRESS_SHADOWSOCKS_SHA256=${EGRESS_SHADOWSOCKS_SHA256}`,
|
|
27047
|
+
`EGRESS_CIPHER=${EGRESS_CIPHER}`,
|
|
27048
|
+
`EGRESS_KEY_BYTES=${EGRESS_KEY_BYTES}`,
|
|
27049
|
+
`EGRESS_MODE=${EGRESS_SHADOWSOCKS_MODE}`,
|
|
27050
|
+
`EGRESS_DNS_SERVERS="${EGRESS_DNS_SERVERS.join(" ")}"`,
|
|
27051
|
+
`EGRESS_EXIT_IP_ENDPOINTS="${EGRESS_EXIT_IP_ENDPOINTS.join(" ")}"`,
|
|
27052
|
+
`EGRESS_DIRECT_ROUTES="${EGRESS_DIRECT_ROUTES.join(" ")}"`,
|
|
27053
|
+
`EGRESS_NEW_CONN_RATE=${EGRESS_NEW_CONN_RATE}`,
|
|
27054
|
+
`EGRESS_NEW_CONN_BURST=${EGRESS_NEW_CONN_BURST}`,
|
|
27055
|
+
`EGRESS_UDP_RATE=${EGRESS_UDP_RATE}`,
|
|
27056
|
+
`EGRESS_UDP_BURST=${EGRESS_UDP_BURST}`,
|
|
27057
|
+
`EGRESS_OUT_CONN_RATE=${EGRESS_OUT_CONN_RATE}`,
|
|
27058
|
+
`EGRESS_OUT_CONN_BURST=${EGRESS_OUT_CONN_BURST}`
|
|
27059
|
+
].join("\n");
|
|
27060
|
+
var EGRESS_TUNNEL_SERVICE = "replicas-egress.service";
|
|
27061
|
+
var EGRESS_TUNNEL_INTERFACE = "rpxtun0";
|
|
27062
|
+
var EGRESS_PATHS = {
|
|
27063
|
+
/**
|
|
27064
|
+
* Under /run, which is tmpfs. The key therefore never touches disk and cannot
|
|
27065
|
+
* be carried into a filesystem snapshot or a paused sandbox's disk image. It
|
|
27066
|
+
* does not survive a reboot either. A full-memory resume can reuse it only
|
|
27067
|
+
* while the root-owned revision still matches the current profile and the
|
|
27068
|
+
* running service and route are healthy.
|
|
27069
|
+
*/
|
|
27070
|
+
CONFIG_DIR: "/run/replicas-egress",
|
|
27071
|
+
CONFIG_FILE: "/run/replicas-egress/config.json",
|
|
27072
|
+
REVISION_FILE: "/run/replicas-egress/revision",
|
|
27073
|
+
/** Persistent: this records the workspace's original resolver so the tunnel can put it back, and must outlive a reboot. */
|
|
27074
|
+
RESOLV_BACKUP: "/var/lib/replicas-egress-resolv.conf.orig",
|
|
27075
|
+
UNIT_FILE: `/etc/systemd/system/${EGRESS_TUNNEL_SERVICE}`,
|
|
27076
|
+
UP_SCRIPT: "/usr/local/lib/replicas-egress-up",
|
|
27077
|
+
DOWN_SCRIPT: "/usr/local/lib/replicas-egress-down"
|
|
27078
|
+
};
|
|
27079
|
+
var EGRESS_WORKSPACE_CONFIG_FILE = "/opt/replicas/egress-config.env";
|
|
27080
|
+
var EGRESS_WORKSPACE_SHELL_VARS = {
|
|
27081
|
+
EGRESS_WORKSPACE_CONFIG_FILE,
|
|
27082
|
+
EGRESS_TUNNEL_SERVICE,
|
|
27083
|
+
EGRESS_TUNNEL_INTERFACE,
|
|
27084
|
+
EGRESS_DNS_SERVERS: EGRESS_DNS_SERVERS.join(" "),
|
|
27085
|
+
EGRESS_EXIT_IP_ENDPOINTS: EGRESS_EXIT_IP_ENDPOINTS.join(" ")
|
|
27086
|
+
};
|
|
27087
|
+
|
|
27088
|
+
// ../shared/src/replicas-config.ts
|
|
27089
|
+
var import_yaml = __toESM(require_dist());
|
|
27090
|
+
|
|
27091
|
+
// ../shared/src/warm-hooks.ts
|
|
27092
|
+
var DEFAULT_WARM_HOOK_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
27093
|
+
var MAX_WARM_HOOK_TIMEOUT_MS = 120 * 60 * 1e3;
|
|
27094
|
+
var DEFAULT_START_HOOK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
27095
|
+
var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
27096
|
+
|
|
27097
|
+
// ../shared/src/replicas-config.ts
|
|
27098
|
+
var REPLICAS_CONFIG_FILENAMES = ["replicas.json", "replicas.yaml", "replicas.yml"];
|
|
27099
|
+
|
|
27100
|
+
// ../shared/src/headless-agent.ts
|
|
27101
|
+
var headlessAgentRequestBaseSchema = external_exports.object({
|
|
27102
|
+
agent: external_exports.custom(
|
|
27103
|
+
(value) => typeof value === "string" && isValidCodingAgentProvider(value)
|
|
27104
|
+
),
|
|
27105
|
+
model: external_exports.string().min(1),
|
|
27106
|
+
prompt: external_exports.string(),
|
|
27107
|
+
workingDirectory: external_exports.string().min(1),
|
|
27108
|
+
timeoutSeconds: external_exports.number().int().min(1).max(1800).default(300),
|
|
27109
|
+
codexOauthTokens: external_exports.object({ accessToken: external_exports.string(), accountId: external_exports.string() }).optional()
|
|
27110
|
+
});
|
|
27111
|
+
var headlessAgentInputFileSchema = external_exports.object({
|
|
27112
|
+
path: external_exports.string().min(1),
|
|
27113
|
+
downloadUrl: external_exports.url()
|
|
27114
|
+
});
|
|
27115
|
+
var headlessAgentOutputFileSchema = external_exports.object({
|
|
27116
|
+
path: external_exports.string().min(1),
|
|
27117
|
+
uploadUrl: external_exports.url(),
|
|
27118
|
+
contentType: external_exports.string().min(1),
|
|
27119
|
+
minChars: external_exports.number().int().positive().optional(),
|
|
27120
|
+
maxChars: external_exports.number().int().positive().optional()
|
|
27121
|
+
});
|
|
27122
|
+
var headlessAgentRequestSchema = external_exports.discriminatedUnion("mode", [
|
|
27123
|
+
headlessAgentRequestBaseSchema.extend({
|
|
27124
|
+
mode: external_exports.literal("structured"),
|
|
27125
|
+
outputSchema: external_exports.record(external_exports.string(), external_exports.json())
|
|
27126
|
+
}),
|
|
27127
|
+
headlessAgentRequestBaseSchema.extend({
|
|
27128
|
+
mode: external_exports.literal("filesystem"),
|
|
27129
|
+
inputFiles: external_exports.array(headlessAgentInputFileSchema),
|
|
27130
|
+
outputFiles: external_exports.array(headlessAgentOutputFileSchema),
|
|
27131
|
+
sensitiveValues: external_exports.array(external_exports.string())
|
|
27132
|
+
})
|
|
27133
|
+
]);
|
|
27134
|
+
var headlessFilesystemAgentResultSchema = external_exports.object({
|
|
27135
|
+
message: external_exports.string(),
|
|
27136
|
+
files: external_exports.record(external_exports.string(), external_exports.object({
|
|
27137
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
27138
|
+
sizeBytes: external_exports.number().int().nonnegative()
|
|
27139
|
+
}))
|
|
27140
|
+
});
|
|
27141
|
+
|
|
27142
|
+
// ../shared/src/cli-version.ts
|
|
27143
|
+
var CLI_VERSION = "0.2.604";
|
|
27144
|
+
|
|
27145
|
+
// ../shared/src/version.ts
|
|
27146
|
+
function compareVersions(v1, v2) {
|
|
27147
|
+
const parts1 = v1.split(".").map(Number);
|
|
27148
|
+
const parts2 = v2.split(".").map(Number);
|
|
27149
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
27150
|
+
const num1 = parts1[i] || 0;
|
|
27151
|
+
const num2 = parts2[i] || 0;
|
|
27152
|
+
if (num1 > num2) return 1;
|
|
27153
|
+
if (num1 < num2) return -1;
|
|
27367
27154
|
}
|
|
27155
|
+
return 0;
|
|
27368
27156
|
}
|
|
27369
|
-
|
|
27370
|
-
|
|
27371
|
-
|
|
27372
|
-
|
|
27373
|
-
|
|
27374
|
-
|
|
27375
|
-
|
|
27376
|
-
|
|
27377
|
-
|
|
27378
|
-
|
|
27379
|
-
|
|
27380
|
-
|
|
27381
|
-
|
|
27382
|
-
|
|
27383
|
-
|
|
27384
|
-
|
|
27385
|
-
|
|
27386
|
-
|
|
27387
|
-
|
|
27388
|
-
|
|
27389
|
-
}
|
|
27390
|
-
|
|
27391
|
-
|
|
27392
|
-
|
|
27393
|
-
|
|
27394
|
-
|
|
27395
|
-
|
|
27396
|
-
|
|
27157
|
+
|
|
27158
|
+
// ../shared/src/routes/plugin-catalog.ts
|
|
27159
|
+
var EXPLICIT_PLUGIN_CATALOG = [
|
|
27160
|
+
{
|
|
27161
|
+
id: "attio",
|
|
27162
|
+
backend: "composio",
|
|
27163
|
+
toolkit: "attio",
|
|
27164
|
+
authType: "oauth",
|
|
27165
|
+
category: "business",
|
|
27166
|
+
name: "Attio",
|
|
27167
|
+
description: "Manage CRM records, people, companies, lists, and notes."
|
|
27168
|
+
},
|
|
27169
|
+
{
|
|
27170
|
+
id: "calendly",
|
|
27171
|
+
backend: "composio",
|
|
27172
|
+
toolkit: "calendly",
|
|
27173
|
+
authType: "oauth",
|
|
27174
|
+
category: "productivity",
|
|
27175
|
+
name: "Calendly",
|
|
27176
|
+
description: "Manage event types, scheduled events, invitees, and scheduling links."
|
|
27177
|
+
},
|
|
27178
|
+
{
|
|
27179
|
+
id: "clickhouse",
|
|
27180
|
+
backend: "composio",
|
|
27181
|
+
toolkit: "clickhouse",
|
|
27182
|
+
authType: "basic",
|
|
27183
|
+
category: "data",
|
|
27184
|
+
name: "ClickHouse",
|
|
27185
|
+
description: "Manage databases, tables, schemas, and queries."
|
|
27186
|
+
},
|
|
27187
|
+
{
|
|
27188
|
+
id: "cloudflare",
|
|
27189
|
+
backend: "composio",
|
|
27190
|
+
toolkit: "cloudflare_api_key",
|
|
27191
|
+
authType: "api_key",
|
|
27192
|
+
category: "data",
|
|
27193
|
+
name: "Cloudflare",
|
|
27194
|
+
description: "Manage zones, DNS records, analytics, and security settings."
|
|
27195
|
+
},
|
|
27196
|
+
{
|
|
27197
|
+
id: "e2b",
|
|
27198
|
+
toolkit: "e2b",
|
|
27199
|
+
backend: "native",
|
|
27200
|
+
authType: "api_key",
|
|
27201
|
+
category: "data",
|
|
27202
|
+
name: "E2B",
|
|
27203
|
+
description: "Create secure cloud sandboxes and run commands in them."
|
|
27204
|
+
},
|
|
27205
|
+
{
|
|
27206
|
+
id: "gmail",
|
|
27207
|
+
backend: "composio",
|
|
27208
|
+
toolkit: "gmail",
|
|
27209
|
+
authType: "oauth",
|
|
27210
|
+
category: "productivity",
|
|
27211
|
+
name: "Gmail",
|
|
27212
|
+
description: "Manage messages, threads, attachments, labels, and mailbox settings."
|
|
27213
|
+
},
|
|
27214
|
+
{
|
|
27215
|
+
id: "googleads",
|
|
27216
|
+
backend: "composio",
|
|
27217
|
+
toolkit: "googleads",
|
|
27218
|
+
authType: "oauth",
|
|
27219
|
+
category: "data",
|
|
27220
|
+
name: "Google Ads",
|
|
27221
|
+
description: "Manage campaigns, customers, accounts, and reporting data."
|
|
27222
|
+
},
|
|
27223
|
+
{
|
|
27224
|
+
id: "googledocs",
|
|
27225
|
+
backend: "composio",
|
|
27226
|
+
toolkit: "googledocs",
|
|
27227
|
+
authType: "oauth",
|
|
27228
|
+
category: "productivity",
|
|
27229
|
+
name: "Google Docs",
|
|
27230
|
+
description: "Manage documents, structure, comments, and exported content."
|
|
27231
|
+
},
|
|
27232
|
+
{
|
|
27233
|
+
id: "googledrive",
|
|
27234
|
+
backend: "composio",
|
|
27235
|
+
toolkit: "googledrive",
|
|
27236
|
+
authType: "oauth",
|
|
27237
|
+
category: "productivity",
|
|
27238
|
+
name: "Google Drive",
|
|
27239
|
+
description: "Manage files, folders, metadata, permissions, and shared drives."
|
|
27240
|
+
},
|
|
27241
|
+
{
|
|
27242
|
+
id: "googlesearch",
|
|
27243
|
+
backend: "composio",
|
|
27244
|
+
toolkit: "google_search_console",
|
|
27245
|
+
authType: "oauth",
|
|
27246
|
+
category: "data",
|
|
27247
|
+
name: "Google Search",
|
|
27248
|
+
description: "Manage Search Console performance, indexing, sites, and sitemaps."
|
|
27249
|
+
},
|
|
27250
|
+
{
|
|
27251
|
+
id: "googlesheets",
|
|
27252
|
+
backend: "composio",
|
|
27253
|
+
toolkit: "googlesheets",
|
|
27254
|
+
authType: "oauth",
|
|
27255
|
+
category: "productivity",
|
|
27256
|
+
name: "Google Sheets",
|
|
27257
|
+
description: "Manage spreadsheets, worksheets, ranges, tables, and charts."
|
|
27258
|
+
},
|
|
27259
|
+
{
|
|
27260
|
+
id: "linkedin",
|
|
27261
|
+
backend: "composio",
|
|
27262
|
+
toolkit: "linkedin",
|
|
27263
|
+
authType: "oauth",
|
|
27264
|
+
category: "business",
|
|
27265
|
+
name: "LinkedIn",
|
|
27266
|
+
description: "Manage profiles, organizations, posts, and professional activity."
|
|
27267
|
+
},
|
|
27268
|
+
{
|
|
27269
|
+
id: "modal",
|
|
27270
|
+
backend: "native",
|
|
27271
|
+
toolkit: "modal",
|
|
27272
|
+
authType: "basic",
|
|
27273
|
+
category: "data",
|
|
27274
|
+
name: "Modal",
|
|
27275
|
+
description: "Invoke deployed functions through Modal compute."
|
|
27276
|
+
},
|
|
27277
|
+
{
|
|
27278
|
+
id: "posthog",
|
|
27279
|
+
backend: "composio",
|
|
27280
|
+
toolkit: "posthog",
|
|
27281
|
+
authType: "api_key",
|
|
27282
|
+
category: "data",
|
|
27283
|
+
name: "PostHog",
|
|
27284
|
+
description: "Manage projects, events, insights, dashboards, flags, and recordings."
|
|
27285
|
+
},
|
|
27286
|
+
{
|
|
27287
|
+
id: "planetscale",
|
|
27288
|
+
toolkit: "planetscale",
|
|
27289
|
+
backend: "native",
|
|
27290
|
+
authType: "oauth",
|
|
27291
|
+
category: "data",
|
|
27292
|
+
name: "PlanetScale",
|
|
27293
|
+
description: "Manage organizations, databases, branches, deploy requests, and Insights."
|
|
27294
|
+
},
|
|
27295
|
+
{
|
|
27296
|
+
id: "stripe",
|
|
27297
|
+
backend: "composio",
|
|
27298
|
+
toolkit: "stripe",
|
|
27299
|
+
authType: "oauth",
|
|
27300
|
+
category: "business",
|
|
27301
|
+
name: "Stripe",
|
|
27302
|
+
description: "Manage customers, payments, invoices, subscriptions, and balances."
|
|
27303
|
+
},
|
|
27304
|
+
{
|
|
27305
|
+
id: "pangram",
|
|
27306
|
+
backend: "native",
|
|
27307
|
+
toolkit: "pangram",
|
|
27308
|
+
authType: "api_key",
|
|
27309
|
+
category: "data",
|
|
27310
|
+
name: "Pangram",
|
|
27311
|
+
description: "Analyze text for AI generation and plagiarism signals."
|
|
27312
|
+
},
|
|
27313
|
+
{
|
|
27314
|
+
id: "vercel",
|
|
27315
|
+
backend: "native",
|
|
27316
|
+
toolkit: "vercel",
|
|
27317
|
+
authType: "api_key",
|
|
27318
|
+
category: "data",
|
|
27319
|
+
name: "Vercel",
|
|
27320
|
+
description: "Manage projects, deployments, logs, domains, and infrastructure."
|
|
27321
|
+
},
|
|
27322
|
+
{
|
|
27323
|
+
id: "turbopuffer",
|
|
27324
|
+
backend: "native",
|
|
27325
|
+
toolkit: "turbopuffer",
|
|
27326
|
+
authType: "api_key",
|
|
27327
|
+
category: "data",
|
|
27328
|
+
name: "turbopuffer",
|
|
27329
|
+
description: "Query and manage turbopuffer namespaces."
|
|
27330
|
+
},
|
|
27331
|
+
{
|
|
27332
|
+
id: "vanta",
|
|
27333
|
+
backend: "native",
|
|
27334
|
+
toolkit: "vanta",
|
|
27335
|
+
authType: "credentials",
|
|
27336
|
+
category: "data",
|
|
27337
|
+
name: "Vanta",
|
|
27338
|
+
description: "Review and manage controls, tests, evidence, vendors, risks, and compliance data.",
|
|
27339
|
+
scopes: ["environment"]
|
|
27397
27340
|
}
|
|
27398
|
-
|
|
27399
|
-
|
|
27400
|
-
|
|
27401
|
-
|
|
27402
|
-
|
|
27403
|
-
|
|
27404
|
-
|
|
27341
|
+
];
|
|
27342
|
+
var HOSTED_COMPOSIO_PLUGIN_DEFINITIONS = [
|
|
27343
|
+
["notion", "notion", "OAUTH2", true, "productivity", "Notion"],
|
|
27344
|
+
["jira", "jira", "OAUTH2", true, "productivity", "Jira"],
|
|
27345
|
+
["confluence", "confluence", "OAUTH2", true, "productivity", "Confluence"],
|
|
27346
|
+
["googlecalendar", "googlecalendar", "OAUTH2", true, "productivity", "Google Calendar"],
|
|
27347
|
+
["microsoftteams", "microsoft_teams", "OAUTH2", true, "productivity", "Microsoft Teams"],
|
|
27348
|
+
["outlook", "outlook", "OAUTH2", true, "productivity", "Outlook"],
|
|
27349
|
+
["bitbucket", "bitbucket", "OAUTH2", true, "data", "Bitbucket"],
|
|
27350
|
+
["datadog", "datadog", "API_KEY", false, "data", "Datadog"],
|
|
27351
|
+
["pagerduty", "pagerduty", "OAUTH2", true, "data", "PagerDuty"],
|
|
27352
|
+
["intercom", "intercom", "OAUTH2", true, "business", "Intercom"],
|
|
27353
|
+
["zendesk", "zendesk", "OAUTH2", true, "business", "Zendesk"],
|
|
27354
|
+
["hubspot", "hubspot", "OAUTH2", true, "business", "HubSpot"],
|
|
27355
|
+
["supabase", "supabase", "OAUTH2", true, "data", "Supabase"],
|
|
27356
|
+
["figma", "figma", "OAUTH2", true, "productivity", "Figma"],
|
|
27357
|
+
["launchdarkly", "launch_darkly", "API_KEY", false, "data", "LaunchDarkly"],
|
|
27358
|
+
["asana", "asana", "OAUTH2", true, "productivity", "Asana"],
|
|
27359
|
+
["clickup", "clickup", "OAUTH2", true, "productivity", "ClickUp"],
|
|
27360
|
+
["trello", "trello", "OAUTH1", true, "productivity", "Trello"],
|
|
27361
|
+
["todoist", "todoist", "OAUTH2", true, "productivity", "Todoist"],
|
|
27362
|
+
["airtable", "airtable", "OAUTH2", true, "productivity", "Airtable"],
|
|
27363
|
+
["coda", "coda", "API_KEY", false, "productivity", "Coda"],
|
|
27364
|
+
["miro", "miro", "OAUTH2", true, "productivity", "Miro"],
|
|
27365
|
+
["sharepoint", "share_point", "OAUTH2", true, "productivity", "SharePoint"],
|
|
27366
|
+
["onedrive", "one_drive", "OAUTH2", true, "productivity", "OneDrive"],
|
|
27367
|
+
["googleslides", "googleslides", "OAUTH2", true, "productivity", "Google Slides"],
|
|
27368
|
+
["googlemeet", "googlemeet", "OAUTH2", true, "productivity", "Google Meet"],
|
|
27369
|
+
["googletasks", "googletasks", "OAUTH2", true, "productivity", "Google Tasks"],
|
|
27370
|
+
["dropbox", "dropbox", "OAUTH2", true, "productivity", "Dropbox"],
|
|
27371
|
+
["box", "box", "OAUTH2", true, "productivity", "Box"],
|
|
27372
|
+
["discord", "discord", "OAUTH2", true, "productivity", "Discord"],
|
|
27373
|
+
["discordbot", "discordbot", "OAUTH2", true, "productivity", "Discord Bot"],
|
|
27374
|
+
["zoom", "zoom", "OAUTH2", true, "productivity", "Zoom"],
|
|
27375
|
+
["googlechat", "google_chat", "OAUTH2", false, "productivity", "Google Chat"],
|
|
27376
|
+
["newrelic", "new_relic", "API_KEY", false, "data", "New Relic"],
|
|
27377
|
+
["betterstack", "better_stack", "API_KEY", false, "data", "Better Stack"],
|
|
27378
|
+
["incidentio", "incident_io", "API_KEY", false, "data", "incident.io"],
|
|
27379
|
+
["grafana", "grafana", "BEARER_TOKEN", false, "data", "Grafana"],
|
|
27380
|
+
["honeycomb", "honeycomb_mcp", "DCR_OAUTH", false, "data", "Honeycomb MCP"],
|
|
27381
|
+
["bugsnag", "bugsnag", "API_KEY", false, "data", "Bugsnag"],
|
|
27382
|
+
["circleci", "circleci", "API_KEY", false, "data", "CircleCI"],
|
|
27383
|
+
["buildkite", "buildkite", "API_KEY", false, "data", "Buildkite"],
|
|
27384
|
+
["dockerhub", "docker_hub", "API_KEY", false, "data", "Docker Hub"],
|
|
27385
|
+
["digitalocean", "digital_ocean", "OAUTH2", true, "data", "DigitalOcean"],
|
|
27386
|
+
["railway", "railway", "API_KEY", false, "data", "Railway"],
|
|
27387
|
+
["render", "render", "API_KEY", false, "data", "Render"],
|
|
27388
|
+
["firebase", "firebase", "API_KEY", false, "data", "Firebase"],
|
|
27389
|
+
["cloudinary", "cloudinary", "API_KEY", false, "data", "Cloudinary"],
|
|
27390
|
+
["configcat", "configcat", "API_KEY", false, "data", "ConfigCat"],
|
|
27391
|
+
["contextdev", "context_dev", "API_KEY", false, "data", "Context.dev"],
|
|
27392
|
+
["googleanalytics", "google_analytics", "OAUTH2", true, "data", "Google Analytics"],
|
|
27393
|
+
["googlebigquery", "googlebigquery", "OAUTH2", true, "data", "Google BigQuery"],
|
|
27394
|
+
["amplitude", "amplitude", "API_KEY", false, "data", "Amplitude"],
|
|
27395
|
+
["mixpanel", "mixpanel", "BASIC", false, "data", "Mixpanel"],
|
|
27396
|
+
["segment", "segment", "API_KEY", false, "data", "Segment"],
|
|
27397
|
+
["databricks", "databricks", "API_KEY", false, "data", "Databricks"],
|
|
27398
|
+
["snowflake", "snowflake", "OAUTH2", false, "data", "Snowflake"],
|
|
27399
|
+
["algolia", "algolia", "API_KEY", false, "data", "Algolia"],
|
|
27400
|
+
["elasticsearch", "elasticsearch", "API_KEY", false, "data", "Elasticsearch"],
|
|
27401
|
+
["salesforce", "salesforce", "OAUTH2", true, "business", "Salesforce"],
|
|
27402
|
+
["pipedrive", "pipedrive", "API_KEY", false, "business", "Pipedrive"],
|
|
27403
|
+
["close", "close", "API_KEY", false, "business", "Close"],
|
|
27404
|
+
["apollo", "apollo", "API_KEY", false, "business", "Apollo"],
|
|
27405
|
+
["gong", "gong", "OAUTH2", true, "business", "Gong"],
|
|
27406
|
+
["freshdesk", "freshdesk", "API_KEY", false, "business", "Freshdesk"],
|
|
27407
|
+
["helpscout", "help_scout", "OAUTH2", false, "business", "Help Scout"],
|
|
27408
|
+
["servicenow", "servicenow", "BASIC", false, "business", "ServiceNow"],
|
|
27409
|
+
["mailchimp", "mailchimp", "OAUTH2", true, "business", "Mailchimp"],
|
|
27410
|
+
["customerio", "customerio", "API_KEY", false, "business", "Customer.io"],
|
|
27411
|
+
["klaviyo", "klaviyo", "API_KEY", false, "business", "Klaviyo"],
|
|
27412
|
+
["shopify", "shopify", "API_KEY", false, "business", "Shopify"],
|
|
27413
|
+
["quickbooks", "quickbooks", "OAUTH2", true, "business", "QuickBooks"],
|
|
27414
|
+
["xero", "xero", "OAUTH2", false, "business", "Xero"],
|
|
27415
|
+
["brex", "brex", "API_KEY", false, "business", "Brex"],
|
|
27416
|
+
["buffer", "buffer", "OAUTH2", false, "business", "Buffer"],
|
|
27417
|
+
["canva", "canva", "OAUTH2", true, "productivity", "Canva"],
|
|
27418
|
+
["webflow", "webflow", "API_KEY", false, "business", "Webflow"],
|
|
27419
|
+
["firecrawl", "firecrawl", "API_KEY", false, "data", "Firecrawl"],
|
|
27420
|
+
["browserbase", "browserbase_tool", "API_KEY", false, "data", "Browserbase"],
|
|
27421
|
+
["exa", "exa", "API_KEY", false, "data", "Exa"],
|
|
27422
|
+
["youtube", "youtube", "OAUTH2", true, "business", "YouTube"],
|
|
27423
|
+
["twitter", "twitter", "OAUTH2", false, "business", "Twitter/X"],
|
|
27424
|
+
["instagram", "instagram", "OAUTH2", true, "business", "Instagram"],
|
|
27425
|
+
["facebook", "facebook", "OAUTH2", true, "business", "Facebook"]
|
|
27426
|
+
];
|
|
27427
|
+
var HOSTED_COMPOSIO_PLUGINS = HOSTED_COMPOSIO_PLUGIN_DEFINITIONS.map(
|
|
27428
|
+
([id, toolkit, authScheme, managedAuth, category, name]) => ({
|
|
27429
|
+
id,
|
|
27430
|
+
backend: "composio",
|
|
27431
|
+
toolkit,
|
|
27432
|
+
authType: "hosted",
|
|
27433
|
+
authScheme,
|
|
27434
|
+
managedAuth,
|
|
27435
|
+
category,
|
|
27436
|
+
name,
|
|
27437
|
+
description: `Use ${name} tools from workspace agents.`
|
|
27438
|
+
})
|
|
27439
|
+
);
|
|
27440
|
+
var PLUGIN_CATALOG = [
|
|
27441
|
+
...EXPLICIT_PLUGIN_CATALOG,
|
|
27442
|
+
...HOSTED_COMPOSIO_PLUGINS
|
|
27443
|
+
];
|
|
27444
|
+
|
|
27445
|
+
// ../shared/src/routes/user.ts
|
|
27446
|
+
var PROFILE_AVATAR_MAX_SIZE_BYTES = 5 * 1024 * 1024;
|
|
27447
|
+
|
|
27448
|
+
// ../shared/src/routes/client-state.ts
|
|
27449
|
+
var MAX_CLIENT_STATE_REQUEST_BYTES = 5 * 1024 * 1024;
|
|
27450
|
+
var MAX_CLIENT_STATE_BYTES_PER_USER = 10 * 1024 * 1024;
|
|
27451
|
+
|
|
27452
|
+
// ../shared/src/routes/workspaces.ts
|
|
27453
|
+
var WORKSPACE_STATUSES = ["active", "sleeping", "archived", "preparing", "error"];
|
|
27454
|
+
function isWorkspaceSuspendedStatus(status) {
|
|
27455
|
+
return status === "sleeping" || status === "archived";
|
|
27405
27456
|
}
|
|
27406
|
-
function
|
|
27407
|
-
const
|
|
27408
|
-
|
|
27409
|
-
|
|
27410
|
-
const indexesByDuplicateBucket = /* @__PURE__ */ new Map();
|
|
27411
|
-
const indexMessage = (message, index) => {
|
|
27412
|
-
if (!firstIndexById.has(message.id)) firstIndexById.set(message.id, index);
|
|
27413
|
-
const key = duplicateBucketKey(message);
|
|
27414
|
-
if (key === null) return;
|
|
27415
|
-
const indexes = indexesByDuplicateBucket.get(key) ?? /* @__PURE__ */ new Set();
|
|
27416
|
-
indexes.add(index);
|
|
27417
|
-
indexesByDuplicateBucket.set(key, indexes);
|
|
27418
|
-
};
|
|
27419
|
-
const unindexMessage = (message, index) => {
|
|
27420
|
-
const key = duplicateBucketKey(message);
|
|
27421
|
-
if (key === null) return;
|
|
27422
|
-
const indexes = indexesByDuplicateBucket.get(key);
|
|
27423
|
-
indexes?.delete(index);
|
|
27424
|
-
if (indexes?.size === 0) indexesByDuplicateBucket.delete(key);
|
|
27457
|
+
function workspaceConfigWithCapabilities(config3, capabilities = {}) {
|
|
27458
|
+
const mergedCapabilities = {
|
|
27459
|
+
...config3?.capabilities,
|
|
27460
|
+
...capabilities
|
|
27425
27461
|
};
|
|
27426
|
-
|
|
27427
|
-
|
|
27428
|
-
|
|
27429
|
-
|
|
27430
|
-
|
|
27431
|
-
const key = duplicateBucketKey(message, bucketOffset);
|
|
27432
|
-
for (const index of (key === null ? void 0 : indexesByDuplicateBucket.get(key)) ?? []) {
|
|
27433
|
-
if (nearTimestamp(merged[index].timestamp, message.timestamp) && (duplicateIndex === void 0 || index < duplicateIndex)) {
|
|
27434
|
-
duplicateIndex = index;
|
|
27435
|
-
}
|
|
27436
|
-
}
|
|
27437
|
-
}
|
|
27438
|
-
}
|
|
27439
|
-
if (duplicateIndex === void 0) {
|
|
27440
|
-
indexMessage(message, merged.push(message) - 1);
|
|
27441
|
-
} else if (message.type === "user") {
|
|
27442
|
-
unindexMessage(merged[duplicateIndex], duplicateIndex);
|
|
27443
|
-
merged[duplicateIndex] = {
|
|
27444
|
-
...merged[duplicateIndex],
|
|
27445
|
-
id: message.id
|
|
27446
|
-
};
|
|
27447
|
-
firstIndexById.set(message.id, duplicateIndex);
|
|
27448
|
-
indexMessage(merged[duplicateIndex], duplicateIndex);
|
|
27462
|
+
return {
|
|
27463
|
+
...config3,
|
|
27464
|
+
capabilities: {
|
|
27465
|
+
...mergedCapabilities,
|
|
27466
|
+
pr_followups: mergedCapabilities.pr_followups === true
|
|
27449
27467
|
}
|
|
27450
|
-
}
|
|
27451
|
-
const ordered = merged.slice(0, primaryCount);
|
|
27452
|
-
const supplementalOnly = merged.slice(primaryCount).map((message, index) => ({ message, index })).sort((a, b) => parseTimestampMs(a.message.timestamp) - parseTimestampMs(b.message.timestamp) || a.index - b.index);
|
|
27453
|
-
for (const { message } of supplementalOnly) {
|
|
27454
|
-
insertDisplayMessageByTimestamp(ordered, message);
|
|
27455
|
-
}
|
|
27456
|
-
return ordered;
|
|
27468
|
+
};
|
|
27457
27469
|
}
|
|
27458
|
-
function
|
|
27459
|
-
|
|
27460
|
-
|
|
27461
|
-
|
|
27462
|
-
|
|
27463
|
-
|
|
27464
|
-
|
|
27465
|
-
|
|
27466
|
-
|
|
27467
|
-
|
|
27468
|
-
|
|
27469
|
-
|
|
27470
|
-
|
|
27471
|
-
|
|
27472
|
-
|
|
27473
|
-
|
|
27474
|
-
|
|
27475
|
-
|
|
27476
|
-
|
|
27477
|
-
|
|
27478
|
-
|
|
27479
|
-
|
|
27480
|
-
|
|
27481
|
-
|
|
27482
|
-
|
|
27483
|
-
|
|
27484
|
-
|
|
27485
|
-
|
|
27486
|
-
|
|
27487
|
-
|
|
27488
|
-
|
|
27489
|
-
|
|
27490
|
-
|
|
27491
|
-
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
27497
|
-
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27501
|
-
|
|
27502
|
-
}
|
|
27503
|
-
|
|
27504
|
-
|
|
27505
|
-
|
|
27506
|
-
|
|
27507
|
-
|
|
27508
|
-
|
|
27509
|
-
|
|
27510
|
-
|
|
27470
|
+
function workspaceConfigWithPrFollowups(config3, prFollowups = config3?.capabilities?.pr_followups === true) {
|
|
27471
|
+
return workspaceConfigWithCapabilities(config3, { pr_followups: prFollowups });
|
|
27472
|
+
}
|
|
27473
|
+
var WORKSPACE_STATUS_FILTERS = WORKSPACE_STATUSES.map((status) => status === "error" ? "failed" : status);
|
|
27474
|
+
var WORKSPACE_SORT_CHOICES = [
|
|
27475
|
+
["manual", "Custom"],
|
|
27476
|
+
["activity", "Last activity"],
|
|
27477
|
+
["created", "Created date"]
|
|
27478
|
+
];
|
|
27479
|
+
var WORKSPACE_SORT_OPTIONS = WORKSPACE_SORT_CHOICES.map(([option]) => option);
|
|
27480
|
+
var WORKSPACE_SORT_LABELS = Object.fromEntries(WORKSPACE_SORT_CHOICES);
|
|
27481
|
+
var WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES = [
|
|
27482
|
+
["chronological", "Chronological"],
|
|
27483
|
+
["environments", "Environments"],
|
|
27484
|
+
["recent", "Recent environments"]
|
|
27485
|
+
];
|
|
27486
|
+
var WORKSPACE_SIDEBAR_ORGANIZATIONS = WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES.map(([organization]) => organization);
|
|
27487
|
+
var WORKSPACE_SIDEBAR_ORGANIZATION_LABELS = Object.fromEntries(WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES);
|
|
27488
|
+
var DEFAULT_STATUS_FILTERS = [...WORKSPACE_STATUS_FILTERS];
|
|
27489
|
+
var DEFAULT_WORKSPACE_FILTERS = {
|
|
27490
|
+
statuses: [...DEFAULT_STATUS_FILTERS],
|
|
27491
|
+
ownerIds: [],
|
|
27492
|
+
activity: "any"
|
|
27493
|
+
};
|
|
27494
|
+
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
27495
|
+
|
|
27496
|
+
// ../shared/src/routes/workspace-events.ts
|
|
27497
|
+
var workspaceChangedEventSchema = external_exports.discriminatedUnion("type", [
|
|
27498
|
+
external_exports.object({
|
|
27499
|
+
type: external_exports.literal("workspace.changed"),
|
|
27500
|
+
workspaceId: external_exports.string(),
|
|
27501
|
+
completion: external_exports.object({
|
|
27502
|
+
workspaceName: external_exports.string(),
|
|
27503
|
+
completedAt: external_exports.string(),
|
|
27504
|
+
processing: external_exports.boolean().optional()
|
|
27505
|
+
}).optional(),
|
|
27506
|
+
ts: external_exports.string()
|
|
27507
|
+
}),
|
|
27508
|
+
external_exports.object({
|
|
27509
|
+
type: external_exports.literal("workspace.chat.changed"),
|
|
27510
|
+
workspaceId: external_exports.string(),
|
|
27511
|
+
chatId: external_exports.string(),
|
|
27512
|
+
ts: external_exports.string()
|
|
27513
|
+
}),
|
|
27514
|
+
external_exports.object({ type: external_exports.literal("presence.changed"), ts: external_exports.string() }),
|
|
27515
|
+
external_exports.object({
|
|
27516
|
+
type: external_exports.literal("mobile-testing.changed"),
|
|
27517
|
+
workspaceId: external_exports.string(),
|
|
27518
|
+
ts: external_exports.string()
|
|
27519
|
+
})
|
|
27520
|
+
]);
|
|
27521
|
+
|
|
27522
|
+
// ../shared/src/routes/presence.ts
|
|
27523
|
+
var presenceStatusSchema = external_exports.enum(["online", "typing"]);
|
|
27524
|
+
var presenceLocationSchema = external_exports.object({
|
|
27525
|
+
environmentId: external_exports.string().optional(),
|
|
27526
|
+
workspaceId: external_exports.string().optional()
|
|
27527
|
+
});
|
|
27528
|
+
var presenceEntrySchema = external_exports.object({
|
|
27529
|
+
userId: external_exports.string(),
|
|
27530
|
+
status: presenceStatusSchema,
|
|
27531
|
+
location: presenceLocationSchema,
|
|
27532
|
+
ts: external_exports.string()
|
|
27533
|
+
});
|
|
27534
|
+
var updatePresenceRequestSchema = external_exports.object({
|
|
27535
|
+
status: presenceStatusSchema,
|
|
27536
|
+
location: presenceLocationSchema.optional()
|
|
27537
|
+
});
|
|
27538
|
+
|
|
27539
|
+
// ../shared/src/audit-log.ts
|
|
27540
|
+
var AUDIT_LOG_ACTION = {
|
|
27541
|
+
CREATE: "create",
|
|
27542
|
+
UPDATE: "update",
|
|
27543
|
+
DELETE: "delete",
|
|
27544
|
+
CONNECT: "connect",
|
|
27545
|
+
DISCONNECT: "disconnect"
|
|
27546
|
+
};
|
|
27547
|
+
var AUDIT_LOG_ACTIONS = Object.values(AUDIT_LOG_ACTION);
|
|
27548
|
+
|
|
27549
|
+
// ../shared/src/automations/types.ts
|
|
27550
|
+
var AUTOMATION_DEBOUNCE_MAX_SECONDS = 24 * 60 * 60;
|
|
27551
|
+
var AUTOMATION_LIFECYCLE_POLICIES = ["default", "archive_when_done", "sleep_when_done"];
|
|
27552
|
+
function toAutomationLifecyclePolicy(policy) {
|
|
27553
|
+
if (!policy) return "default";
|
|
27554
|
+
if (policy === "default" || policy === "archive_when_done" || policy === "sleep_when_done") return policy;
|
|
27555
|
+
return "archive_when_done";
|
|
27556
|
+
}
|
|
27557
|
+
function lifecyclePolicySupportsAutoStop(policy) {
|
|
27558
|
+
return policy === "default";
|
|
27511
27559
|
}
|
|
27512
27560
|
|
|
27513
|
-
// ../shared/src/
|
|
27514
|
-
var
|
|
27515
|
-
function
|
|
27516
|
-
|
|
27517
|
-
return parseCodexEvents(events);
|
|
27518
|
-
}
|
|
27519
|
-
if (agentType === "cursor") {
|
|
27520
|
-
return parseCursorEvents(events);
|
|
27521
|
-
}
|
|
27522
|
-
if (agentType === "deepseek") {
|
|
27523
|
-
return parseDeepseekEvents(events);
|
|
27524
|
-
}
|
|
27525
|
-
if (agentType === "fx") {
|
|
27526
|
-
return parseFxEvents(events);
|
|
27527
|
-
}
|
|
27528
|
-
if (agentType === "kimi") {
|
|
27529
|
-
return parseAcpEvents(events, "kimi");
|
|
27530
|
-
}
|
|
27531
|
-
if (agentType === "muse") {
|
|
27532
|
-
return parseMuseEvents(events);
|
|
27533
|
-
}
|
|
27534
|
-
if (agentType === "opencode") {
|
|
27535
|
-
return parseOpencodeEvents(events);
|
|
27536
|
-
}
|
|
27537
|
-
if (agentType === "pi") {
|
|
27538
|
-
return parsePiEvents(events);
|
|
27539
|
-
}
|
|
27540
|
-
return parseClaudeEvents(events);
|
|
27561
|
+
// ../shared/src/automations/github-checks.ts
|
|
27562
|
+
var AUTOMATION_CHECK_CONCLUSIONS = ["success", "failure"];
|
|
27563
|
+
function isAutomationCheckConclusion(value) {
|
|
27564
|
+
return AUTOMATION_CHECK_CONCLUSIONS.some((conclusion) => conclusion === value);
|
|
27541
27565
|
}
|
|
27542
|
-
function
|
|
27543
|
-
|
|
27544
|
-
const parsedEvents = agentType === "claude" || agentType === "relay" ? parseClaudeEvents(events, options.parentToolUseId) : parseAgentEvents(events, agentType);
|
|
27545
|
-
const reconciledEvents = [];
|
|
27546
|
-
for (const message of parsedEvents) {
|
|
27547
|
-
if (message.type === "user") upsertDisplayMessage(reconciledEvents, message);
|
|
27548
|
-
else reconciledEvents.push(message);
|
|
27549
|
-
}
|
|
27550
|
-
const legacyMessages = shouldFilter ? filterDisplayMessages(reconciledEvents, agentType) : reconciledEvents;
|
|
27551
|
-
const applySyntheticNotices = (messages) => shouldFilter ? applyAuthFallbackNotices(applyInterruptions(messages, events), events) : messages;
|
|
27552
|
-
if (agentType !== "codex" || !codexAspTranscript) {
|
|
27553
|
-
return applySyntheticNotices(legacyMessages);
|
|
27554
|
-
}
|
|
27555
|
-
const nativeCodexMessages = shouldFilter ? filterDisplayMessages(parseCodexAspTranscript(codexAspTranscript), agentType) : parseCodexAspTranscript(codexAspTranscript);
|
|
27556
|
-
return applySyntheticNotices(mergeCodexAspDisplayMessages(nativeCodexMessages, legacyMessages));
|
|
27566
|
+
function normalizeAutomationGithubCheckNames(names) {
|
|
27567
|
+
return names.map((name) => name.trim()).filter(Boolean);
|
|
27557
27568
|
}
|
|
27558
|
-
|
|
27559
|
-
|
|
27560
|
-
|
|
27561
|
-
|
|
27562
|
-
|
|
27563
|
-
|
|
27564
|
-
|
|
27565
|
-
|
|
27566
|
-
});
|
|
27569
|
+
|
|
27570
|
+
// ../shared/src/automations/agent-validation.ts
|
|
27571
|
+
function validateAgentSelection(body, existing, modelCatalogs = {}) {
|
|
27572
|
+
const agentProvider = body.agent_provider;
|
|
27573
|
+
if (agentProvider !== void 0 && agentProvider !== null) {
|
|
27574
|
+
if (!isValidAgentProvider(agentProvider)) {
|
|
27575
|
+
return createErrorResult({ message: `Invalid agent_provider: must be one of ${VALID_AGENT_PROVIDERS.join(", ")}` });
|
|
27576
|
+
}
|
|
27567
27577
|
}
|
|
27568
|
-
|
|
27569
|
-
|
|
27570
|
-
|
|
27571
|
-
|
|
27572
|
-
|
|
27573
|
-
|
|
27574
|
-
|
|
27575
|
-
|
|
27576
|
-
|
|
27578
|
+
const effectiveAgent = agentProvider !== void 0 ? agentProvider : existing.agentProvider;
|
|
27579
|
+
const agentChanged = agentProvider !== void 0 && agentProvider !== existing.agentProvider;
|
|
27580
|
+
let model = body.model;
|
|
27581
|
+
if (agentChanged && model === void 0 && existing.model) {
|
|
27582
|
+
model = null;
|
|
27583
|
+
}
|
|
27584
|
+
if (model !== void 0 && model !== null) {
|
|
27585
|
+
if (typeof model !== "string" || model.trim().length === 0) {
|
|
27586
|
+
return createErrorResult({ message: "model must be a non-empty string" });
|
|
27577
27587
|
}
|
|
27578
|
-
|
|
27579
|
-
|
|
27580
|
-
|
|
27588
|
+
model = normalizeClaudeModel(model) ?? model;
|
|
27589
|
+
if (!effectiveAgent) {
|
|
27590
|
+
return createErrorResult({ message: "Cannot set model without an agent_provider (the model would be applied against the org default agent and may not be valid for it)" });
|
|
27581
27591
|
}
|
|
27582
|
-
const
|
|
27583
|
-
if (
|
|
27584
|
-
|
|
27592
|
+
const allowed = getAgentModelOptions(effectiveAgent, modelCatalogs);
|
|
27593
|
+
if (!isAgentModelAllowed(effectiveAgent, model, modelCatalogs)) {
|
|
27594
|
+
return createErrorResult({ message: `Invalid model "${model}" for agent ${effectiveAgent}. Valid models: ${allowed.join(", ")}` });
|
|
27585
27595
|
}
|
|
27586
|
-
lastInterruption = {
|
|
27587
|
-
...msg,
|
|
27588
|
-
...lastUserMs !== null && ms >= lastUserMs ? { durationMs: ms - lastUserMs } : {}
|
|
27589
|
-
};
|
|
27590
|
-
finalized.push(lastInterruption);
|
|
27591
27596
|
}
|
|
27592
|
-
|
|
27593
|
-
|
|
27594
|
-
|
|
27595
|
-
|
|
27596
|
-
events.forEach((event, index) => {
|
|
27597
|
-
if (event.type !== AUTH_FALLBACK_EVENT_TYPE) return;
|
|
27598
|
-
const payload = coerceAuthFallbackPayload(event.payload);
|
|
27599
|
-
if (!payload) return;
|
|
27600
|
-
notices.push({
|
|
27601
|
-
...payload,
|
|
27602
|
-
id: `auth-fallback-${event.timestamp}-${index}`,
|
|
27603
|
-
type: "auth_fallback",
|
|
27604
|
-
timestamp: event.timestamp
|
|
27605
|
-
});
|
|
27606
|
-
});
|
|
27607
|
-
if (notices.length === 0) return messages;
|
|
27608
|
-
const result = [...messages];
|
|
27609
|
-
for (const notice of notices) insertDisplayMessageByTimestamp(result, notice);
|
|
27610
|
-
return result;
|
|
27611
|
-
}
|
|
27612
|
-
function isCodexInitializationPrompt(message) {
|
|
27613
|
-
return message.type === "user" && removeReplicasInstructions(message.content).trim() === "Hello";
|
|
27614
|
-
}
|
|
27615
|
-
function filterDisplayMessages(messages, provider) {
|
|
27616
|
-
let result = messages;
|
|
27617
|
-
if (provider === "codex") {
|
|
27618
|
-
const userMessages = result.map((msg, index) => ({ msg, index })).filter(({ msg }) => msg.type === "user");
|
|
27619
|
-
if (userMessages.length >= 2 && isCodexInitializationPrompt(userMessages[0].msg)) {
|
|
27620
|
-
result = result.slice(userMessages[1].index);
|
|
27597
|
+
const thinkingLevel = body.thinking_level;
|
|
27598
|
+
if (thinkingLevel !== void 0 && thinkingLevel !== null) {
|
|
27599
|
+
if (!effectiveAgent && isProviderSpecificThinkingLevel(thinkingLevel)) {
|
|
27600
|
+
return createErrorResult({ message: `Cannot set ${thinkingLevel} without an agent_provider` });
|
|
27621
27601
|
}
|
|
27622
|
-
|
|
27623
|
-
|
|
27624
|
-
|
|
27625
|
-
const cleaned = removeReplicasInstructions(msg.content).trim();
|
|
27626
|
-
if (INTERRUPTED_MESSAGE_REGEX.test(cleaned)) {
|
|
27627
|
-
return { id: msg.id, type: "interruption", timestamp: msg.timestamp };
|
|
27602
|
+
if (!isValidThinkingLevel(thinkingLevel) || effectiveAgent && !getThinkingLevelOptions(effectiveAgent).includes(thinkingLevel)) {
|
|
27603
|
+
const validLevels = effectiveAgent ? getThinkingLevelOptions(effectiveAgent) : VALID_THINKING_LEVELS;
|
|
27604
|
+
return createErrorResult({ message: `Invalid thinking_level: must be one of ${validLevels.join(", ")}` });
|
|
27628
27605
|
}
|
|
27629
|
-
|
|
27630
|
-
});
|
|
27631
|
-
return result;
|
|
27606
|
+
}
|
|
27607
|
+
return createSuccessResult({ agentProvider, model, thinkingLevel });
|
|
27632
27608
|
}
|
|
27633
27609
|
|
|
27610
|
+
// ../shared/src/automations/github/index.ts
|
|
27611
|
+
var REPO_FILTER_PARAM = {
|
|
27612
|
+
id: "repository_ids",
|
|
27613
|
+
label: "Filter by repository",
|
|
27614
|
+
type: "repository_ids"
|
|
27615
|
+
};
|
|
27616
|
+
var EXCLUDED_ACTORS_PARAM = {
|
|
27617
|
+
id: "excluded_actors",
|
|
27618
|
+
label: "Exclude users",
|
|
27619
|
+
type: "excluded_actors"
|
|
27620
|
+
};
|
|
27621
|
+
var GROUP_PR_EVENTS_PARAM = {
|
|
27622
|
+
id: "group_pr_events",
|
|
27623
|
+
label: "Group PR events to same workspace",
|
|
27624
|
+
type: "boolean"
|
|
27625
|
+
};
|
|
27626
|
+
var GITHUB_TRIGGER = {
|
|
27627
|
+
type: "github",
|
|
27628
|
+
label: "GitHub",
|
|
27629
|
+
description: "Trigger on repository events",
|
|
27630
|
+
icon: "github",
|
|
27631
|
+
events: [
|
|
27632
|
+
{ id: "pull_request.opened", label: "PR opened", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM, GROUP_PR_EVENTS_PARAM] },
|
|
27633
|
+
{ id: "pull_request.synchronize", label: "PR updated (new commits)", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM, GROUP_PR_EVENTS_PARAM] },
|
|
27634
|
+
{ id: "pull_request.merged", label: "PR merged", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM] },
|
|
27635
|
+
{ id: "pull_request.closed", label: "PR closed", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM] },
|
|
27636
|
+
{ id: "pull_request.command", label: "PR command (/replicas run)", parameters: [REPO_FILTER_PARAM, EXCLUDED_ACTORS_PARAM, GROUP_PR_EVENTS_PARAM] }
|
|
27637
|
+
]
|
|
27638
|
+
};
|
|
27639
|
+
|
|
27640
|
+
// ../shared/src/automations/gitlab/index.ts
|
|
27641
|
+
var REPO_FILTER_PARAM2 = {
|
|
27642
|
+
id: "repository_ids",
|
|
27643
|
+
label: "Filter by project",
|
|
27644
|
+
type: "repository_ids"
|
|
27645
|
+
};
|
|
27646
|
+
var EXCLUDED_ACTORS_PARAM2 = {
|
|
27647
|
+
id: "excluded_actors",
|
|
27648
|
+
label: "Exclude users",
|
|
27649
|
+
type: "excluded_actors"
|
|
27650
|
+
};
|
|
27651
|
+
var GROUP_MR_EVENTS_PARAM = {
|
|
27652
|
+
id: "group_pr_events",
|
|
27653
|
+
label: "Group MR events to same workspace",
|
|
27654
|
+
type: "boolean"
|
|
27655
|
+
};
|
|
27656
|
+
var GITLAB_TRIGGER = {
|
|
27657
|
+
type: "gitlab",
|
|
27658
|
+
label: "GitLab",
|
|
27659
|
+
description: "Trigger on project events",
|
|
27660
|
+
icon: "gitlab",
|
|
27661
|
+
events: [
|
|
27662
|
+
{ id: "merge_request.opened", label: "MR opened", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2, GROUP_MR_EVENTS_PARAM] },
|
|
27663
|
+
{ id: "merge_request.updated", label: "MR updated (new commits)", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2, GROUP_MR_EVENTS_PARAM] },
|
|
27664
|
+
{ id: "merge_request.merged", label: "MR merged", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2] },
|
|
27665
|
+
{ id: "merge_request.closed", label: "MR closed", parameters: [REPO_FILTER_PARAM2, EXCLUDED_ACTORS_PARAM2] }
|
|
27666
|
+
]
|
|
27667
|
+
};
|
|
27668
|
+
|
|
27669
|
+
// ../shared/src/routes/repo-files.ts
|
|
27670
|
+
var MAX_REPO_FILE_CONTENT_BYTES = 256 * 1024;
|
|
27671
|
+
|
|
27672
|
+
// ../shared/src/routes/admin.ts
|
|
27673
|
+
var WEBHOOK_PROVIDERS = ["linear", "github", "gitlab", "slack", "e2b", "stripe", "sentry"];
|
|
27674
|
+
var WEBHOOK_PROVIDER_SET = new Set(WEBHOOK_PROVIDERS);
|
|
27675
|
+
|
|
27634
27676
|
// ../shared/src/onboarding-emails.ts
|
|
27635
27677
|
var EMAIL_KEYS = [
|
|
27636
27678
|
"welcome",
|