@letta-ai/letta-code 0.34.15 → 0.34.16
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/app-server-client.cjs +22 -2
- package/dist/app-server-client.cjs.map +4 -4
- package/dist/app-server-client.js +22 -2
- package/dist/app-server-client.js.map +4 -4
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp-oauth.js +2 -2
- package/dist/mcp-oauth.js.map +1 -1
- package/dist/types/agent/turn-recovery-policy.d.ts +1 -0
- package/dist/types/agent/turn-recovery-policy.d.ts.map +1 -1
- package/dist/types/app-server-client.d.ts +14 -8
- package/dist/types/app-server-client.d.ts.map +1 -1
- package/dist/types/backend/api/environments.d.ts +2 -0
- package/dist/types/backend/api/environments.d.ts.map +1 -1
- package/dist/types/backend/dev/local-provider-errors.d.ts.map +1 -1
- package/dist/types/reminders/engine.d.ts +7 -0
- package/dist/types/reminders/engine.d.ts.map +1 -1
- package/dist/types/tools/impl/external-coding-agent-task.d.ts +2 -0
- package/dist/types/tools/impl/external-coding-agent-task.d.ts.map +1 -1
- package/dist/types/tools/impl/external-coding-agent.d.ts +13 -1
- package/dist/types/tools/impl/external-coding-agent.d.ts.map +1 -1
- package/dist/types/tools/impl/remote-external-coding-agent.d.ts +37 -1
- package/dist/types/tools/impl/remote-external-coding-agent.d.ts.map +1 -1
- package/dist/types/tools/impl/send-agent-message.d.ts +2 -0
- package/dist/types/tools/impl/send-agent-message.d.ts.map +1 -1
- package/dist/types/tools/impl/task-stop.d.ts +4 -1
- package/dist/types/tools/impl/task-stop.d.ts.map +1 -1
- package/dist/types/types/app-server-info.d.ts +2 -0
- package/dist/types/types/app-server-info.d.ts.map +1 -1
- package/dist/types/types/app-server-protocol.d.ts +4 -0
- package/dist/types/types/app-server-protocol.d.ts.map +1 -1
- package/dist/types/types/protocol_v2.d.ts +1 -0
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/dist/types/types/subagent-protocol.d.ts +34 -0
- package/dist/types/types/subagent-protocol.d.ts.map +1 -1
- package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
- package/dist/types/websocket/listener/queue.d.ts.map +1 -1
- package/dist/types/websocket/listener/types.d.ts +4 -3
- package/dist/types/websocket/listener/types.d.ts.map +1 -1
- package/letta.js +530 -47
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/scripts/source-file-size-baseline.json +5 -3
- package/skills/working-across-computers/SKILL.md +4 -0
package/letta.js
CHANGED
|
@@ -5913,7 +5913,7 @@ var package_default;
|
|
|
5913
5913
|
var init_package = __esm(() => {
|
|
5914
5914
|
package_default = {
|
|
5915
5915
|
name: "@letta-ai/letta-code",
|
|
5916
|
-
version: "0.34.
|
|
5916
|
+
version: "0.34.16",
|
|
5917
5917
|
lettaStartupLogProtocol: 1,
|
|
5918
5918
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5919
5919
|
type: "module",
|
|
@@ -113780,7 +113780,7 @@ function selectChatGPTQuotaFailoverHandle(params) {
|
|
|
113780
113780
|
const index = Math.min(Math.floor(random() * candidates2.length), candidates2.length - 1);
|
|
113781
113781
|
return candidates2[index]?.handle ?? null;
|
|
113782
113782
|
}
|
|
113783
|
-
var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENTS, CONVERSATION_BUSY_RUN_ID_PATTERN, EMPTY_RESPONSE_DETAIL_FRAGMENT = "empty content in", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_RUN_ERROR_TYPES, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN, DEFAULT_TRANSIENT_RETRY_BASE_DELAY_MS = 1000, CLOUDFLARE_EDGE_52X_RETRY_BASE_DELAY_MS = 5000, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 1e4, EMPTY_RESPONSE_RETRY_BASE_DELAY_MS = 500, STALE_APPROVAL_RECOVERY_DENIAL_REASON = "The agent harness automatically closed this stale pending tool call to recover from a client/server state desync: the server was still waiting on a result for it, but the harness had no matching tool execution in flight and no result was ever recorded. It was not denied by the user or a permissions policy. Re-issue the tool call if you still need it.", CHATGPT_USAGE_LIMIT_FRAGMENT = "usage_limit_reached", CHATGPT_OAUTH_PROVIDER_TYPE2 = "chatgpt_oauth", BYOK_PROVIDER_CATEGORY = "byok";
|
|
113783
|
+
var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENTS, CONVERSATION_BUSY_RUN_ID_PATTERN, EMPTY_RESPONSE_DETAIL_FRAGMENT = "empty content in", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_RUN_ERROR_TYPES, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN, DEFAULT_TRANSIENT_RETRY_BASE_DELAY_MS = 1000, CLOUDFLARE_EDGE_52X_RETRY_BASE_DELAY_MS = 5000, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 1e4, EMPTY_RESPONSE_RETRY_BASE_DELAY_MS = 500, STALE_APPROVAL_RECOVERY_DENIAL_REASON = "The agent harness automatically closed this stale pending tool call to recover from a client/server state desync: the server was still waiting on a result for it, but the harness had no matching tool execution in flight and no result was ever recorded. It was not denied by the user or a permissions policy. Re-issue the tool call if you still need it.", STARTED_TOOL_CALL_RECOVERY_DENIAL_REASON = "The agent harness closed this pending tool call while recovering from an interrupted turn. The call had started, but its result was not recorded, so it may or may not have run. Check whether its effect already happened before running it again.", CHATGPT_USAGE_LIMIT_FRAGMENT = "usage_limit_reached", CHATGPT_OAUTH_PROVIDER_TYPE2 = "chatgpt_oauth", BYOK_PROVIDER_CATEGORY = "byok";
|
|
113784
113784
|
var init_turn_recovery_policy = __esm(() => {
|
|
113785
113785
|
init_error_formatter();
|
|
113786
113786
|
init_zai_errors();
|
|
@@ -114121,7 +114121,9 @@ var init_local_provider_errors = __esm(() => {
|
|
|
114121
114121
|
"timed out",
|
|
114122
114122
|
"terminated",
|
|
114123
114123
|
"retry delay",
|
|
114124
|
-
"unable to verify"
|
|
114124
|
+
"unable to verify",
|
|
114125
|
+
"websocket connection limit reached",
|
|
114126
|
+
"exceeded request buffer limit"
|
|
114125
114127
|
];
|
|
114126
114128
|
});
|
|
114127
114129
|
|
|
@@ -210859,7 +210861,7 @@ var init_mcp_client = __esm(() => {
|
|
|
210859
210861
|
init_streamableHttp();
|
|
210860
210862
|
DEFAULT_CLIENT_INFO = {
|
|
210861
210863
|
name: "letta-code",
|
|
210862
|
-
version: "0.34.
|
|
210864
|
+
version: "0.34.16"
|
|
210863
210865
|
};
|
|
210864
210866
|
});
|
|
210865
210867
|
|
|
@@ -215074,6 +215076,7 @@ agent IDs backed by their native sessions. A message to active work steers its
|
|
|
215074
215076
|
in-flight turn (Claude interrupts through stream-json and sends the replacement
|
|
215075
215077
|
instruction; Codex uses app-server turn/steer). An idle follow-up starts one tracked local background
|
|
215076
215078
|
turn. Neither path uses the Cloud messaging backend.
|
|
215079
|
+
Computer-qualified IDs returned by remote launches can be steered too.
|
|
215077
215080
|
|
|
215078
215081
|
An agent has a persistent identity and shared memory. It can have multiple
|
|
215079
215082
|
conversations, each with its own message history.
|
|
@@ -223299,6 +223302,7 @@ function buildSubagentSnapshot(runtime, scope) {
|
|
|
223299
223302
|
prompt: a2.prompt,
|
|
223300
223303
|
status: a2.status,
|
|
223301
223304
|
agent_url: a2.agentURL,
|
|
223305
|
+
agent_id: a2.agentId ?? null,
|
|
223302
223306
|
conversation_id: a2.conversationId ?? null,
|
|
223303
223307
|
super_run_id: a2.superRunId,
|
|
223304
223308
|
model: a2.model,
|
|
@@ -240089,7 +240093,7 @@ class CodexAppServerClient {
|
|
|
240089
240093
|
await this.request("initialize", {
|
|
240090
240094
|
clientInfo: {
|
|
240091
240095
|
name: "letta-code",
|
|
240092
|
-
version: "0.34.
|
|
240096
|
+
version: "0.34.16"
|
|
240093
240097
|
},
|
|
240094
240098
|
capabilities: null
|
|
240095
240099
|
});
|
|
@@ -241207,10 +241211,22 @@ async function buildAgentInfoReminder(context3) {
|
|
|
241207
241211
|
context3.state.hasSentAgentInfo = true;
|
|
241208
241212
|
return reminder || null;
|
|
241209
241213
|
}
|
|
241214
|
+
async function listAvailableSecretNames(agentId, lookupParent) {
|
|
241215
|
+
const { ensureSecretsLoaded: ensureSecretsLoaded2, listSecretNames: listSecretNames2 } = await Promise.resolve().then(() => (init_secrets_store(), exports_secrets_store));
|
|
241216
|
+
const names2 = new Set(listSecretNames2(agentId));
|
|
241217
|
+
try {
|
|
241218
|
+
const scopeAgentId = await getMcpScopeAgentId(agentId, undefined, lookupParent);
|
|
241219
|
+
if (scopeAgentId !== agentId) {
|
|
241220
|
+
await ensureSecretsLoaded2(scopeAgentId);
|
|
241221
|
+
for (const name of listSecretNames2(scopeAgentId))
|
|
241222
|
+
names2.add(name);
|
|
241223
|
+
}
|
|
241224
|
+
} catch {}
|
|
241225
|
+
return [...names2].sort();
|
|
241226
|
+
}
|
|
241210
241227
|
async function buildSecretsInfoReminder(context3) {
|
|
241211
241228
|
try {
|
|
241212
|
-
const
|
|
241213
|
-
const names2 = listSecretNames2(context3.agent.id);
|
|
241229
|
+
const names2 = await listAvailableSecretNames(context3.agent.id);
|
|
241214
241230
|
const namesKey = names2.join("\x00");
|
|
241215
241231
|
const isRefresh = context3.state.pendingSecretsInfoRefresh;
|
|
241216
241232
|
const namesChanged = context3.state.lastSentSecretNamesKey !== null && context3.state.lastSentSecretNamesKey !== namesKey;
|
|
@@ -242574,18 +242590,24 @@ function createExternalCodingAgentConfig(type3) {
|
|
|
242574
242590
|
function isExternalCodingAgentType(value) {
|
|
242575
242591
|
return EXTERNAL_CODING_AGENT_TYPES.includes(value);
|
|
242576
242592
|
}
|
|
242577
|
-
function formatExternalCodingAgentId(type3, sessionId) {
|
|
242578
|
-
|
|
242593
|
+
function formatExternalCodingAgentId(type3, sessionId, computer) {
|
|
242594
|
+
const id2 = `${EXTERNAL_AGENT_ID_PREFIXES[type3]}${sessionId}`;
|
|
242595
|
+
return computer ? `${id2}@${computer}` : id2;
|
|
242579
242596
|
}
|
|
242580
242597
|
function parseExternalCodingAgentId(agentId) {
|
|
242581
242598
|
if (!agentId)
|
|
242582
242599
|
return null;
|
|
242600
|
+
const separator = agentId.lastIndexOf("@");
|
|
242601
|
+
const nativeId = separator === -1 ? agentId : agentId.slice(0, separator);
|
|
242602
|
+
const computer = separator === -1 ? undefined : agentId.slice(separator + 1);
|
|
242603
|
+
if (computer !== undefined && !computer.trim())
|
|
242604
|
+
return null;
|
|
242583
242605
|
for (const type3 of EXTERNAL_CODING_AGENT_TYPES) {
|
|
242584
242606
|
const prefix = EXTERNAL_AGENT_ID_PREFIXES[type3];
|
|
242585
|
-
if (
|
|
242586
|
-
const sessionId =
|
|
242607
|
+
if (nativeId.startsWith(prefix)) {
|
|
242608
|
+
const sessionId = nativeId.slice(prefix.length);
|
|
242587
242609
|
if ((type3 === "opencode" ? /^ses_[a-zA-Z0-9]+$/ : NATIVE_SESSION_ID_PATTERN).test(sessionId)) {
|
|
242588
|
-
return { type: type3, sessionId };
|
|
242610
|
+
return { type: type3, sessionId, ...computer ? { computer } : {} };
|
|
242589
242611
|
}
|
|
242590
242612
|
}
|
|
242591
242613
|
}
|
|
@@ -242768,10 +242790,27 @@ function parseExternalCodingAgentOutput(type3, stdout) {
|
|
|
242768
242790
|
...sessionId ? { sessionId } : {}
|
|
242769
242791
|
};
|
|
242770
242792
|
}
|
|
242793
|
+
async function resolveExternalCodingAgentSecretEnv(parentAgentId, lookupParent) {
|
|
242794
|
+
const { ensureSecretsLoaded: ensureSecretsLoaded2, loadSecrets: loadSecrets2 } = await Promise.resolve().then(() => (init_secrets_store(), exports_secrets_store));
|
|
242795
|
+
let inherited = {};
|
|
242796
|
+
try {
|
|
242797
|
+
const scopeAgentId = await getMcpScopeAgentId(parentAgentId, undefined, lookupParent);
|
|
242798
|
+
if (scopeAgentId !== parentAgentId) {
|
|
242799
|
+
await ensureSecretsLoaded2(scopeAgentId);
|
|
242800
|
+
inherited = loadSecrets2(scopeAgentId);
|
|
242801
|
+
}
|
|
242802
|
+
} catch {}
|
|
242803
|
+
try {
|
|
242804
|
+
await ensureSecretsLoaded2(parentAgentId);
|
|
242805
|
+
} catch {}
|
|
242806
|
+
return { ...inherited, ...loadSecrets2(parentAgentId) };
|
|
242807
|
+
}
|
|
242771
242808
|
async function runExternalCodingAgent(options, deps = {}) {
|
|
242772
242809
|
const startedAt = Date.now();
|
|
242810
|
+
const secretEnv = await (deps.resolveSecretEnv ?? resolveExternalCodingAgentSecretEnv)(options.parentAgentId);
|
|
242773
242811
|
const env6 = {
|
|
242774
242812
|
...deps.env ?? process.env,
|
|
242813
|
+
...secretEnv,
|
|
242775
242814
|
AGENT_ID: options.parentAgentId,
|
|
242776
242815
|
LETTA_AGENT_ID: options.parentAgentId,
|
|
242777
242816
|
LETTA_PARENT_AGENT_ID: options.parentAgentId,
|
|
@@ -242798,7 +242837,14 @@ async function runExternalCodingAgent(options, deps = {}) {
|
|
|
242798
242837
|
captureReservation ??= reserveNativeSessionCapture(source, sessionId, scope, env6);
|
|
242799
242838
|
return captureReservation;
|
|
242800
242839
|
};
|
|
242801
|
-
const capture = async (
|
|
242840
|
+
const capture = async (rawResult) => {
|
|
242841
|
+
const result3 = {
|
|
242842
|
+
...rawResult,
|
|
242843
|
+
report: scrubSecretsFromString(rawResult.report, secretEnv),
|
|
242844
|
+
...rawResult.error !== undefined && {
|
|
242845
|
+
error: scrubSecretsFromString(rawResult.error, secretEnv)
|
|
242846
|
+
}
|
|
242847
|
+
};
|
|
242802
242848
|
const sessionId = result3.runtimeSessionId ?? captureSessionId;
|
|
242803
242849
|
if (scope && sessionId) {
|
|
242804
242850
|
try {
|
|
@@ -242931,6 +242977,7 @@ var init_external_coding_agent = __esm(() => {
|
|
|
242931
242977
|
init_mcp_scope();
|
|
242932
242978
|
init_engine3();
|
|
242933
242979
|
init_runtime_context();
|
|
242980
|
+
init_secret_substitution();
|
|
242934
242981
|
init_claude_stream_session();
|
|
242935
242982
|
init_codex_app_server();
|
|
242936
242983
|
init_native_session_capture();
|
|
@@ -243628,7 +243675,7 @@ function isAppServerInfoResponseMessage(message2) {
|
|
|
243628
243675
|
return false;
|
|
243629
243676
|
}
|
|
243630
243677
|
const capabilityRecord = capabilities;
|
|
243631
|
-
return candidate.type === "app_server_info_response" && typeof candidate.request_id === "string" && candidate.request_id.length > 0 && candidate.success === true && (candidate.backend === "local" || candidate.backend === "api") && typeof candidate.letta_code_version === "string" && typeof candidate.protocol_version === "number" && Number.isInteger(candidate.protocol_version) && typeof capabilityRecord.agent_management === "boolean" && typeof capabilityRecord.conversation_management === "boolean" && typeof capabilityRecord.memory_management === "boolean" && typeof capabilityRecord.runtime_start === "boolean" && (capabilityRecord.agent_free_conversations === undefined || typeof capabilityRecord.agent_free_conversations === "boolean") && (capabilityRecord.launch_subagent === undefined || typeof capabilityRecord.launch_subagent === "boolean") && (capabilityRecord.launch_subagent_notify_caller === undefined || typeof capabilityRecord.launch_subagent_notify_caller === "boolean") && (capabilityRecord.runtime_workspace_sandbox === undefined || typeof capabilityRecord.runtime_workspace_sandbox === "boolean") && (capabilityRecord.runtime_external_tools_update === undefined || typeof capabilityRecord.runtime_external_tools_update === "boolean") && (capabilityRecord.structured_outputs === undefined || typeof capabilityRecord.structured_outputs === "boolean") && (capabilityRecord.write_file_base64 === undefined || typeof capabilityRecord.write_file_base64 === "boolean") && typeof capabilityRecord.split_channels === "boolean";
|
|
243678
|
+
return candidate.type === "app_server_info_response" && typeof candidate.request_id === "string" && candidate.request_id.length > 0 && candidate.success === true && (candidate.backend === "local" || candidate.backend === "api") && typeof candidate.letta_code_version === "string" && typeof candidate.protocol_version === "number" && Number.isInteger(candidate.protocol_version) && typeof capabilityRecord.agent_management === "boolean" && typeof capabilityRecord.conversation_management === "boolean" && typeof capabilityRecord.memory_management === "boolean" && typeof capabilityRecord.runtime_start === "boolean" && (capabilityRecord.agent_free_conversations === undefined || typeof capabilityRecord.agent_free_conversations === "boolean") && (capabilityRecord.launch_subagent === undefined || typeof capabilityRecord.launch_subagent === "boolean") && (capabilityRecord.launch_subagent_notify_caller === undefined || typeof capabilityRecord.launch_subagent_notify_caller === "boolean") && (capabilityRecord.subagent_message === undefined || typeof capabilityRecord.subagent_message === "boolean") && (capabilityRecord.runtime_workspace_sandbox === undefined || typeof capabilityRecord.runtime_workspace_sandbox === "boolean") && (capabilityRecord.runtime_external_tools_update === undefined || typeof capabilityRecord.runtime_external_tools_update === "boolean") && (capabilityRecord.structured_outputs === undefined || typeof capabilityRecord.structured_outputs === "boolean") && (capabilityRecord.write_file_base64 === undefined || typeof capabilityRecord.write_file_base64 === "boolean") && typeof capabilityRecord.split_channels === "boolean";
|
|
243632
243679
|
}
|
|
243633
243680
|
var APP_SERVER_PROTOCOL_VERSION = 1;
|
|
243634
243681
|
|
|
@@ -243882,6 +243929,26 @@ class AppServerClient {
|
|
|
243882
243929
|
predicate: (message2) => message2.type === "launch_subagent_response"
|
|
243883
243930
|
});
|
|
243884
243931
|
}
|
|
243932
|
+
sendSubagentMessage(command, options = {}) {
|
|
243933
|
+
return this.request({
|
|
243934
|
+
...command,
|
|
243935
|
+
type: "subagent_message",
|
|
243936
|
+
request_id: command.request_id ?? this.nextRequestId("subagent-message")
|
|
243937
|
+
}, {
|
|
243938
|
+
...options,
|
|
243939
|
+
predicate: (message2) => message2.type === "subagent_message_response"
|
|
243940
|
+
});
|
|
243941
|
+
}
|
|
243942
|
+
stopSubagent(command, options = {}) {
|
|
243943
|
+
return this.request({
|
|
243944
|
+
...command,
|
|
243945
|
+
type: "subagent_stop",
|
|
243946
|
+
request_id: command.request_id ?? this.nextRequestId("subagent-stop")
|
|
243947
|
+
}, {
|
|
243948
|
+
...options,
|
|
243949
|
+
predicate: (message2) => message2.type === "subagent_stop_response" && message2.agent_id === command.agent_id
|
|
243950
|
+
});
|
|
243951
|
+
}
|
|
243885
243952
|
runtimeStart(command, options = {}) {
|
|
243886
243953
|
return this.request({
|
|
243887
243954
|
type: "runtime_start",
|
|
@@ -246262,6 +246329,9 @@ function formatRemoteStartupError(type3, computer, code2) {
|
|
|
246262
246329
|
function formatOutdatedComputerError(type3, computer) {
|
|
246263
246330
|
return `${computer} is running an older Letta Code that can't run ${DISPLAY_NAMES[type3]} subagents remotely. Update Letta Code on ${computer}.`;
|
|
246264
246331
|
}
|
|
246332
|
+
function formatOutdatedSteeringError(computer) {
|
|
246333
|
+
return `${computer} is running an older Letta Code that can't steer Claude Code subagents remotely. Update Letta Code on ${computer}.`;
|
|
246334
|
+
}
|
|
246265
246335
|
async function defaultResolveComputer(computer, scope) {
|
|
246266
246336
|
if (!isCloudEnvironmentSelector(computer))
|
|
246267
246337
|
return resolveEnvironmentConnectionId(computer);
|
|
@@ -246290,6 +246360,18 @@ async function defaultConnect(connectionId, scope) {
|
|
|
246290
246360
|
throw error5;
|
|
246291
246361
|
}
|
|
246292
246362
|
}
|
|
246363
|
+
async function resolveQualifiedComputer(deviceId) {
|
|
246364
|
+
try {
|
|
246365
|
+
const environment2 = await getEnvironmentConnection(deviceId);
|
|
246366
|
+
if (!isEnvironmentOnline(environment2) || !environment2.connectionId)
|
|
246367
|
+
throw new Error(`Computer "${deviceId}" is offline`);
|
|
246368
|
+
return { connectionId: environment2.connectionId, environment: environment2 };
|
|
246369
|
+
} catch (error5) {
|
|
246370
|
+
if (errorMessage3(error5).includes("offline"))
|
|
246371
|
+
throw error5;
|
|
246372
|
+
return resolveEnvironmentConnectionId(deviceId);
|
|
246373
|
+
}
|
|
246374
|
+
}
|
|
246293
246375
|
function errorMessage3(error5) {
|
|
246294
246376
|
return error5 instanceof Error ? error5.message : String(error5);
|
|
246295
246377
|
}
|
|
@@ -246342,6 +246424,22 @@ class RemoteSubagentFollower {
|
|
|
246342
246424
|
markLaunched() {
|
|
246343
246425
|
this.launched = true;
|
|
246344
246426
|
}
|
|
246427
|
+
async waitForAgentId(timeoutMs) {
|
|
246428
|
+
const deadline = Date.now() + timeoutMs;
|
|
246429
|
+
while (Date.now() < deadline) {
|
|
246430
|
+
if (this.latest?.agent_id)
|
|
246431
|
+
return this.latest.agent_id;
|
|
246432
|
+
const remaining = deadline - Date.now();
|
|
246433
|
+
if (remaining <= 0 || this.closed || this.lost)
|
|
246434
|
+
break;
|
|
246435
|
+
await Promise.race([
|
|
246436
|
+
this.wake.promise,
|
|
246437
|
+
new Promise((resolve37) => setTimeout(resolve37, remaining))
|
|
246438
|
+
]);
|
|
246439
|
+
this.wake = Promise.withResolvers();
|
|
246440
|
+
}
|
|
246441
|
+
return this.latest?.agent_id ?? null;
|
|
246442
|
+
}
|
|
246345
246443
|
close() {
|
|
246346
246444
|
this.closed = true;
|
|
246347
246445
|
this.detach?.();
|
|
@@ -246395,6 +246493,8 @@ class RemoteSubagentFollower {
|
|
|
246395
246493
|
async function launchRemoteExternalCodingAgent(params, deps) {
|
|
246396
246494
|
const { type: type3, computer, parentScope } = params;
|
|
246397
246495
|
let connectionId;
|
|
246496
|
+
let deviceId;
|
|
246497
|
+
let supportsSteering;
|
|
246398
246498
|
try {
|
|
246399
246499
|
const resolved2 = await (deps.resolveComputer ?? defaultResolveComputer)(computer, parentScope);
|
|
246400
246500
|
if (resolved2.environment.metadata?.launch_subagent_notify_caller !== true)
|
|
@@ -246403,6 +246503,8 @@ async function launchRemoteExternalCodingAgent(params, deps) {
|
|
|
246403
246503
|
error: formatOutdatedComputerError(type3, computer)
|
|
246404
246504
|
};
|
|
246405
246505
|
connectionId = resolved2.connectionId;
|
|
246506
|
+
deviceId = resolved2.environment.deviceId;
|
|
246507
|
+
supportsSteering = resolved2.environment.metadata?.subagent_message === true;
|
|
246406
246508
|
} catch (error5) {
|
|
246407
246509
|
return { success: false, error: errorMessage3(error5) };
|
|
246408
246510
|
}
|
|
@@ -246454,7 +246556,10 @@ async function launchRemoteExternalCodingAgent(params, deps) {
|
|
|
246454
246556
|
};
|
|
246455
246557
|
}
|
|
246456
246558
|
follower.markLaunched();
|
|
246457
|
-
const
|
|
246559
|
+
const nativeAgentId = supportsSteering ? await follower.waitForAgentId(deps.agentIdWaitMs ?? 2000) : null;
|
|
246560
|
+
const parsedNativeAgentId = nativeAgentId ? parseExternalCodingAgentId(nativeAgentId) : null;
|
|
246561
|
+
const qualifiedAgentId = parsedNativeAgentId && !parsedNativeAgentId.computer ? formatExternalCodingAgentId(parsedNativeAgentId.type, parsedNativeAgentId.sessionId, deviceId) : null;
|
|
246562
|
+
const { taskId, outputFile, subagentId } = deps.spawn({
|
|
246458
246563
|
subagentType: type3,
|
|
246459
246564
|
config: createExternalCodingAgentConfig(type3),
|
|
246460
246565
|
prompt: params.prompt,
|
|
@@ -246463,16 +246568,16 @@ async function launchRemoteExternalCodingAgent(params, deps) {
|
|
|
246463
246568
|
toolCallId: params.toolCallId,
|
|
246464
246569
|
parentScope,
|
|
246465
246570
|
deps: {
|
|
246466
|
-
spawnSubagentImpl: async (_type, _prompt, model,
|
|
246571
|
+
spawnSubagentImpl: async (_type, _prompt, model, subagentId2, signal) => {
|
|
246467
246572
|
const startedAt = Date.now();
|
|
246468
|
-
updateSubagent(
|
|
246573
|
+
updateSubagent(subagentId2, { status: "running" });
|
|
246469
246574
|
try {
|
|
246470
|
-
const final = await follower.waitForTerminal(signal, (snapshot2) => updateSubagent(
|
|
246575
|
+
const final = await follower.waitForTerminal(signal, (snapshot2) => updateSubagent(subagentId2, {
|
|
246471
246576
|
toolCalls: snapshot2.tool_calls,
|
|
246472
246577
|
totalTokens: snapshot2.total_tokens
|
|
246473
246578
|
}));
|
|
246474
246579
|
return {
|
|
246475
|
-
agentId: parentScope.agentId,
|
|
246580
|
+
agentId: qualifiedAgentId ?? parentScope.agentId,
|
|
246476
246581
|
model: final.model ?? model,
|
|
246477
246582
|
report: final.result ?? "",
|
|
246478
246583
|
success: final.status === "completed",
|
|
@@ -246495,14 +246600,142 @@ async function launchRemoteExternalCodingAgent(params, deps) {
|
|
|
246495
246600
|
}
|
|
246496
246601
|
}
|
|
246497
246602
|
});
|
|
246603
|
+
if (qualifiedAgentId)
|
|
246604
|
+
updateSubagent(subagentId, { agentId: qualifiedAgentId });
|
|
246498
246605
|
return {
|
|
246499
246606
|
success: true,
|
|
246500
246607
|
task_id: taskId,
|
|
246501
246608
|
output_file: outputFile,
|
|
246502
|
-
agent_id:
|
|
246609
|
+
agent_id: qualifiedAgentId,
|
|
246503
246610
|
conversation_id: null
|
|
246504
246611
|
};
|
|
246505
246612
|
}
|
|
246613
|
+
async function connectQualifiedTarget(agentId, parentScope, deps) {
|
|
246614
|
+
const target2 = parseExternalCodingAgentId(agentId);
|
|
246615
|
+
if (!target2?.computer || target2.type === "opencode")
|
|
246616
|
+
throw new Error(`Invalid remote external coding agent ID: ${agentId}`);
|
|
246617
|
+
const resolved2 = await (deps.resolveComputer ?? resolveQualifiedComputer)(target2.computer);
|
|
246618
|
+
if (resolved2.environment.metadata?.subagent_message !== true)
|
|
246619
|
+
throw new Error(formatOutdatedSteeringError(target2.computer));
|
|
246620
|
+
return {
|
|
246621
|
+
target: target2,
|
|
246622
|
+
client: await (deps.connect ?? defaultConnect)(resolved2.connectionId, parentScope)
|
|
246623
|
+
};
|
|
246624
|
+
}
|
|
246625
|
+
async function stopRemoteExternalCodingAgent(params, deps = {}) {
|
|
246626
|
+
const requestId = `subagent-stop-${randomUUID41()}`;
|
|
246627
|
+
const { target: target2, client } = await connectQualifiedTarget(params.agentId, params.parentScope, deps);
|
|
246628
|
+
try {
|
|
246629
|
+
const response = await client.stopSubagent({
|
|
246630
|
+
request_id: requestId,
|
|
246631
|
+
runtime: {
|
|
246632
|
+
agent_id: params.parentScope.agentId,
|
|
246633
|
+
conversation_id: params.parentScope.conversationId,
|
|
246634
|
+
...params.parentScope.actingUserId ? { acting_user_id: params.parentScope.actingUserId } : {}
|
|
246635
|
+
},
|
|
246636
|
+
agent_id: formatExternalCodingAgentId(target2.type, target2.sessionId)
|
|
246637
|
+
});
|
|
246638
|
+
if (!response.success)
|
|
246639
|
+
throw new Error(response.error ?? "Stop failed");
|
|
246640
|
+
return { stopped: response.stopped };
|
|
246641
|
+
} finally {
|
|
246642
|
+
client.close();
|
|
246643
|
+
}
|
|
246644
|
+
}
|
|
246645
|
+
async function sendRemoteExternalCodingAgentMessage(params, deps = {}) {
|
|
246646
|
+
const requestId = `subagent-message-${randomUUID41()}`;
|
|
246647
|
+
const { target: target2, client } = await connectQualifiedTarget(params.agentId, params.parentScope, deps);
|
|
246648
|
+
const toolCallId = params.toolCallId ?? `remote-followup-${randomUUID41()}`;
|
|
246649
|
+
const connect = async () => {
|
|
246650
|
+
const resolved2 = await (deps.resolveComputer ?? resolveQualifiedComputer)(target2.computer);
|
|
246651
|
+
return (deps.connect ?? defaultConnect)(resolved2.connectionId, params.parentScope);
|
|
246652
|
+
};
|
|
246653
|
+
const follower = new RemoteSubagentFollower(params.parentScope, toolCallId, connect, 2000);
|
|
246654
|
+
follower.attach(client);
|
|
246655
|
+
const bareAgentId = formatExternalCodingAgentId(target2.type, target2.sessionId);
|
|
246656
|
+
let response;
|
|
246657
|
+
try {
|
|
246658
|
+
response = await client.sendSubagentMessage({
|
|
246659
|
+
request_id: requestId,
|
|
246660
|
+
runtime: {
|
|
246661
|
+
agent_id: params.parentScope.agentId,
|
|
246662
|
+
conversation_id: params.parentScope.conversationId,
|
|
246663
|
+
...params.parentScope.actingUserId ? { acting_user_id: params.parentScope.actingUserId } : {}
|
|
246664
|
+
},
|
|
246665
|
+
agent_id: bareAgentId,
|
|
246666
|
+
message: params.message,
|
|
246667
|
+
tool_call_id: toolCallId
|
|
246668
|
+
});
|
|
246669
|
+
} catch (error5) {
|
|
246670
|
+
follower.close();
|
|
246671
|
+
throw error5;
|
|
246672
|
+
}
|
|
246673
|
+
if (!response.success) {
|
|
246674
|
+
follower.close();
|
|
246675
|
+
throw new Error(response.error);
|
|
246676
|
+
}
|
|
246677
|
+
if (response.delivery === "steered") {
|
|
246678
|
+
follower.close();
|
|
246679
|
+
return { delivery: "steered" };
|
|
246680
|
+
}
|
|
246681
|
+
follower.markLaunched();
|
|
246682
|
+
const completion = follower.waitForTerminal(undefined, () => {
|
|
246683
|
+
return;
|
|
246684
|
+
}).then((final) => ({
|
|
246685
|
+
agentId: bareAgentId,
|
|
246686
|
+
model: final.model,
|
|
246687
|
+
report: final.result ?? "",
|
|
246688
|
+
success: final.status === "completed",
|
|
246689
|
+
...final.status === "error" ? { error: final.error ?? "Remote follow-up failed" } : {},
|
|
246690
|
+
totalTokens: final.total_tokens,
|
|
246691
|
+
durationMs: final.duration_ms
|
|
246692
|
+
})).finally(() => follower.close());
|
|
246693
|
+
const interrupt = async () => {
|
|
246694
|
+
const resolved2 = await (deps.resolveComputer ?? resolveQualifiedComputer)(target2.computer);
|
|
246695
|
+
const stopClient = await (deps.connect ?? defaultConnect)(resolved2.connectionId, params.parentScope);
|
|
246696
|
+
try {
|
|
246697
|
+
await stopClient.stopSubagent({
|
|
246698
|
+
runtime: {
|
|
246699
|
+
agent_id: params.parentScope.agentId,
|
|
246700
|
+
conversation_id: params.parentScope.conversationId
|
|
246701
|
+
},
|
|
246702
|
+
agent_id: bareAgentId
|
|
246703
|
+
});
|
|
246704
|
+
} finally {
|
|
246705
|
+
stopClient.close();
|
|
246706
|
+
}
|
|
246707
|
+
};
|
|
246708
|
+
const track = deps.track;
|
|
246709
|
+
if (!track) {
|
|
246710
|
+
follower.close();
|
|
246711
|
+
throw new Error("Remote follow-up tracking is unavailable");
|
|
246712
|
+
}
|
|
246713
|
+
let tracked;
|
|
246714
|
+
try {
|
|
246715
|
+
tracked = track({
|
|
246716
|
+
type: target2.type,
|
|
246717
|
+
agentId: params.agentId,
|
|
246718
|
+
message: params.message,
|
|
246719
|
+
parentScope: params.parentScope,
|
|
246720
|
+
completion,
|
|
246721
|
+
interrupt
|
|
246722
|
+
});
|
|
246723
|
+
} catch (error5) {
|
|
246724
|
+
try {
|
|
246725
|
+
await interrupt();
|
|
246726
|
+
} catch {}
|
|
246727
|
+
follower.close();
|
|
246728
|
+
completion.catch(() => {
|
|
246729
|
+
return;
|
|
246730
|
+
});
|
|
246731
|
+
throw error5;
|
|
246732
|
+
}
|
|
246733
|
+
return {
|
|
246734
|
+
delivery: "resumed",
|
|
246735
|
+
taskId: tracked.taskId,
|
|
246736
|
+
outputFile: tracked.outputFile
|
|
246737
|
+
};
|
|
246738
|
+
}
|
|
246506
246739
|
var DISPLAY_NAMES, RemoteWorkerLostError;
|
|
246507
246740
|
var init_remote_external_coding_agent = __esm(() => {
|
|
246508
246741
|
init_subagent_state();
|
|
@@ -247160,6 +247393,8 @@ function trackExternalFollowupCompletion(args) {
|
|
|
247160
247393
|
prompt: args.message,
|
|
247161
247394
|
description: `Continue ${args.type} session`,
|
|
247162
247395
|
existingAgentId: args.agentId,
|
|
247396
|
+
toolCallId: args.toolCallId,
|
|
247397
|
+
publishResult: args.publishResult,
|
|
247163
247398
|
parentScope: args.parentScope,
|
|
247164
247399
|
actingUserId: args.parentScope.actingUserId,
|
|
247165
247400
|
deps: {
|
|
@@ -247273,6 +247508,28 @@ async function send_agent_message(args, deps = {}) {
|
|
|
247273
247508
|
}
|
|
247274
247509
|
args.signal?.throwIfAborted();
|
|
247275
247510
|
const parentScope = sender;
|
|
247511
|
+
if (externalTarget.computer) {
|
|
247512
|
+
const receipt3 = await (deps.sendRemoteExternalMessage ?? sendRemoteExternalCodingAgentMessage)({
|
|
247513
|
+
agentId: args.agent_id,
|
|
247514
|
+
message: args.message,
|
|
247515
|
+
parentScope: {
|
|
247516
|
+
...parentScope,
|
|
247517
|
+
actingUserId: getRuntimeActingUserAttribution()
|
|
247518
|
+
}
|
|
247519
|
+
}, {
|
|
247520
|
+
track: deps.trackExternalFollowup ?? trackExternalFollowupCompletion
|
|
247521
|
+
});
|
|
247522
|
+
return {
|
|
247523
|
+
content: JSON.stringify({
|
|
247524
|
+
status: "accepted",
|
|
247525
|
+
agent_id: args.agent_id,
|
|
247526
|
+
delivery: receipt3.delivery === "steered" ? "remote/steer" : "remote/resume",
|
|
247527
|
+
...receipt3.taskId ? { task_id: receipt3.taskId } : {},
|
|
247528
|
+
...receipt3.outputFile ? { output_file: receipt3.outputFile } : {}
|
|
247529
|
+
}),
|
|
247530
|
+
status: "success"
|
|
247531
|
+
};
|
|
247532
|
+
}
|
|
247276
247533
|
if (externalTarget.type === "opencode") {
|
|
247277
247534
|
const receipt3 = await sendOpenCodeMessage({
|
|
247278
247535
|
sessionId: externalTarget.sessionId,
|
|
@@ -247546,6 +247803,7 @@ var init_send_agent_message = __esm(async () => {
|
|
|
247546
247803
|
init_external_coding_agent();
|
|
247547
247804
|
init_native_session_capture();
|
|
247548
247805
|
init_opencode_session();
|
|
247806
|
+
init_remote_external_coding_agent();
|
|
247549
247807
|
await init_external_coding_agent_task();
|
|
247550
247808
|
FULL_CONVERSATION_ID = /^conv-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
247551
247809
|
});
|
|
@@ -248068,13 +248326,40 @@ async function cancelRemoteRun(subagentId) {
|
|
|
248068
248326
|
};
|
|
248069
248327
|
}
|
|
248070
248328
|
}
|
|
248071
|
-
async function task_stop(args) {
|
|
248329
|
+
async function task_stop(args, deps = {}) {
|
|
248072
248330
|
validateRequiredParams(args, ["task_id"], "TaskStop");
|
|
248073
248331
|
const { task_id } = args;
|
|
248074
248332
|
const task2 = backgroundTasks.get(task_id);
|
|
248075
248333
|
if (task2) {
|
|
248076
248334
|
if (task2.status === "running" && task2.abortController) {
|
|
248077
|
-
const
|
|
248335
|
+
const child = getSubagents().find((agent) => agent.id === task2.subagentId);
|
|
248336
|
+
const external3 = parseExternalCodingAgentId(child?.agentId ?? undefined);
|
|
248337
|
+
let remote;
|
|
248338
|
+
if (external3?.computer) {
|
|
248339
|
+
try {
|
|
248340
|
+
if (!task2.runtimeScope)
|
|
248341
|
+
throw new Error("its parent conversation is not known");
|
|
248342
|
+
const result3 = await (deps.stopRemoteExternal ?? stopRemoteExternalCodingAgent)({
|
|
248343
|
+
agentId: child?.agentId,
|
|
248344
|
+
parentScope: {
|
|
248345
|
+
agentId: task2.runtimeScope.agentId,
|
|
248346
|
+
conversationId: task2.runtimeScope.conversationId,
|
|
248347
|
+
actingUserId: task2.actingUserId
|
|
248348
|
+
}
|
|
248349
|
+
});
|
|
248350
|
+
remote = {
|
|
248351
|
+
killed: result3.stopped,
|
|
248352
|
+
output: result3.stopped ? "Stopped the remote external subagent" : "The remote external subagent was not running"
|
|
248353
|
+
};
|
|
248354
|
+
} catch (error5) {
|
|
248355
|
+
remote = {
|
|
248356
|
+
killed: false,
|
|
248357
|
+
output: `Couldn't stop the remote external subagent: ${getErrorMessage2(error5)}`
|
|
248358
|
+
};
|
|
248359
|
+
}
|
|
248360
|
+
} else if (task2.remote) {
|
|
248361
|
+
remote = await cancelRemoteRun(task2.subagentId);
|
|
248362
|
+
}
|
|
248078
248363
|
if (remote && !remote.killed)
|
|
248079
248364
|
return remote;
|
|
248080
248365
|
task2.abortController.abort();
|
|
@@ -248091,7 +248376,9 @@ async function task_stop(args) {
|
|
|
248091
248376
|
var init_task_stop = __esm(async () => {
|
|
248092
248377
|
init_subagent_state();
|
|
248093
248378
|
init_backend2();
|
|
248379
|
+
init_external_coding_agent();
|
|
248094
248380
|
init_process_manager();
|
|
248381
|
+
init_remote_external_coding_agent();
|
|
248095
248382
|
await init_kill_bash();
|
|
248096
248383
|
});
|
|
248097
248384
|
|
|
@@ -258274,11 +258561,13 @@ function buildQueuedTurnMessage(runtime, batch) {
|
|
|
258274
258561
|
return null;
|
|
258275
258562
|
const scopeItem = batch.items[0];
|
|
258276
258563
|
const batchActingUserId = batch.items.some((item) => item.kind === "message") ? getBatchActingUserId(batch.items) : template3?.actingUserId ?? getBatchActingUserId(batch.items);
|
|
258564
|
+
const processOwnedTurn = !batch.items.some((item) => item.kind === "message");
|
|
258277
258565
|
return {
|
|
258278
258566
|
type: "message",
|
|
258279
258567
|
agentId: scopeItem?.agentId ?? runtime.agentId ?? undefined,
|
|
258280
258568
|
conversationId: scopeItem?.conversationId ?? runtime.conversationId,
|
|
258281
258569
|
...template3,
|
|
258570
|
+
...processOwnedTurn ? { processOwnedTurn: true } : {},
|
|
258282
258571
|
actingUserId: batchActingUserId ?? undefined,
|
|
258283
258572
|
suppressActingUserFallback: batchActingUserId === null || batchActingUserId === undefined && template3?.suppressActingUserFallback === true,
|
|
258284
258573
|
...durableInputIdentities.length > 0 ? { durableInputIdentities: [...new Set(durableInputIdentities)] } : {},
|
|
@@ -262377,17 +262666,11 @@ function ListenerStatusUI(props) {
|
|
|
262377
262666
|
}, undefined, false, undefined, this)
|
|
262378
262667
|
]
|
|
262379
262668
|
}, undefined, true, undefined, this),
|
|
262380
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
262381
|
-
children:
|
|
262669
|
+
isFirstRun && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
262670
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
262382
262671
|
dimColor: true,
|
|
262383
262672
|
children: "Connected. Head back to Letta in your browser — it will detect this computer automatically. Keep this window open."
|
|
262384
|
-
}, undefined, false, undefined, this)
|
|
262385
|
-
dimColor: true,
|
|
262386
|
-
children: [
|
|
262387
|
-
'Connect to this computer by visiting any agent and clicking the "cloud" button at the bottom left of the messenger input and swapping your computer to ',
|
|
262388
|
-
envName
|
|
262389
|
-
]
|
|
262390
|
-
}, undefined, true, undefined, this)
|
|
262673
|
+
}, undefined, false, undefined, this)
|
|
262391
262674
|
}, undefined, false, undefined, this)
|
|
262392
262675
|
]
|
|
262393
262676
|
}, undefined, true, undefined, this);
|
|
@@ -263018,6 +263301,7 @@ async function registerWithCloud(opts, fetchImpl = fetch) {
|
|
|
263018
263301
|
supportsPairedListenerGenerations: true,
|
|
263019
263302
|
supported_commands: SUPPORTED_REMOTE_COMMANDS,
|
|
263020
263303
|
launch_subagent_notify_caller: true,
|
|
263304
|
+
subagent_message: true,
|
|
263021
263305
|
self_update: getSelfUpdateStatus()
|
|
263022
263306
|
}
|
|
263023
263307
|
})
|
|
@@ -264207,6 +264491,20 @@ function isLaunchSubagentCommand(value) {
|
|
|
264207
264491
|
return false;
|
|
264208
264492
|
return args.max_turns === undefined || typeof args.max_turns === "number" && Number.isSafeInteger(args.max_turns) && args.max_turns > 0;
|
|
264209
264493
|
}
|
|
264494
|
+
function hasValidControlBase(value) {
|
|
264495
|
+
if (!value || typeof value !== "object")
|
|
264496
|
+
return false;
|
|
264497
|
+
const c = value;
|
|
264498
|
+
return typeof c.request_id === "string" && c.request_id.trim().length > 0 && isAgentRuntimeScope(c.runtime) && c.runtime.agent_id.trim().length > 0 && c.runtime.conversation_id.trim().length > 0 && typeof c.agent_id === "string" && c.agent_id.trim().length > 0;
|
|
264499
|
+
}
|
|
264500
|
+
function isSubagentMessageCommand(value) {
|
|
264501
|
+
if (!hasValidControlBase(value) || value.type !== "subagent_message")
|
|
264502
|
+
return false;
|
|
264503
|
+
return typeof value.message === "string" && value.message.trim().length > 0 && (value.tool_call_id === undefined || typeof value.tool_call_id === "string" && value.tool_call_id.trim().length > 0);
|
|
264504
|
+
}
|
|
264505
|
+
function isSubagentStopCommand(value) {
|
|
264506
|
+
return hasValidControlBase(value) && value.type === "subagent_stop";
|
|
264507
|
+
}
|
|
264210
264508
|
var ARGUMENTS;
|
|
264211
264509
|
var init_subagent_protocol_inbound = __esm(() => {
|
|
264212
264510
|
ARGUMENTS = new Set([
|
|
@@ -264250,7 +264548,7 @@ var init_browser_device_mcp_oauth_protocol_inbound = __esm(() => {
|
|
|
264250
264548
|
|
|
264251
264549
|
// src/websocket/listener/task-control-protocol-inbound.ts
|
|
264252
264550
|
function isTaskControlProtocolCommand(value) {
|
|
264253
|
-
return isBrowserDeviceMcpOAuthProtocolCommand(value) || isExecuteCommandCommand(value) || isRemoveQueueItemCommand(value) || isMonitorStopCommand(value);
|
|
264551
|
+
return isBrowserDeviceMcpOAuthProtocolCommand(value) || isExecuteCommandCommand(value) || isRemoveQueueItemCommand(value) || isMonitorStopCommand(value) || isSubagentMessageCommand(value) || isSubagentStopCommand(value);
|
|
264254
264552
|
}
|
|
264255
264553
|
function isExecuteCommandCommand(value) {
|
|
264256
264554
|
if (!value || typeof value !== "object")
|
|
@@ -264272,6 +264570,7 @@ function isMonitorStopCommand(value) {
|
|
|
264272
264570
|
}
|
|
264273
264571
|
var init_task_control_protocol_inbound = __esm(() => {
|
|
264274
264572
|
init_browser_device_mcp_oauth_protocol_inbound();
|
|
264573
|
+
init_subagent_protocol_inbound();
|
|
264275
264574
|
});
|
|
264276
264575
|
|
|
264277
264576
|
// src/websocket/listener/protocol-inbound.ts
|
|
@@ -459752,6 +460051,7 @@ function buildAppServerInfoResponse(command, options) {
|
|
|
459752
460051
|
agent_free_conversations: true,
|
|
459753
460052
|
launch_subagent: true,
|
|
459754
460053
|
launch_subagent_notify_caller: true,
|
|
460054
|
+
subagent_message: true,
|
|
459755
460055
|
runtime_workspace_sandbox: true,
|
|
459756
460056
|
runtime_external_tools_update: true,
|
|
459757
460057
|
structured_outputs: options.backend === "api",
|
|
@@ -461248,6 +461548,174 @@ var init_monitors = __esm(async () => {
|
|
|
461248
461548
|
]);
|
|
461249
461549
|
});
|
|
461250
461550
|
|
|
461551
|
+
// src/websocket/listener/commands/subagent-control.ts
|
|
461552
|
+
function dedupeKey(command) {
|
|
461553
|
+
return JSON.stringify([
|
|
461554
|
+
command.runtime.agent_id,
|
|
461555
|
+
command.runtime.conversation_id,
|
|
461556
|
+
command.agent_id,
|
|
461557
|
+
command.request_id
|
|
461558
|
+
]);
|
|
461559
|
+
}
|
|
461560
|
+
function finishUntrackedNativeCapture2(completion, reservation, source, sessionId) {
|
|
461561
|
+
if (!reservation)
|
|
461562
|
+
return;
|
|
461563
|
+
completion.then(() => reservation.capture(), () => reservation.capture()).catch((error5) => reportNativeSessionCaptureFailure(source, sessionId, error5));
|
|
461564
|
+
}
|
|
461565
|
+
function findOwnedTask(runtime, agentId) {
|
|
461566
|
+
const subagent = getSubagents().find((entry) => entry.agentId === agentId && entry.parentAgentId === runtime.agentId && entry.parentConversationId === runtime.conversationId);
|
|
461567
|
+
if (!subagent)
|
|
461568
|
+
return;
|
|
461569
|
+
return [...backgroundTasks.entries()].find(([, task2]) => task2.subagentId === subagent.id);
|
|
461570
|
+
}
|
|
461571
|
+
function runtimeContext(parent, command) {
|
|
461572
|
+
return {
|
|
461573
|
+
agentId: parent.agentId,
|
|
461574
|
+
conversationId: parent.conversationId,
|
|
461575
|
+
actingUserId: command.runtime.acting_user_id,
|
|
461576
|
+
workingDirectory: getConversationWorkingDirectory(parent.listener, parent.agentId, parent.conversationId),
|
|
461577
|
+
skillSources: parent.skillSources,
|
|
461578
|
+
workspaceSandbox: parent.workspaceSandbox,
|
|
461579
|
+
executionSettings: parent.executionSettings
|
|
461580
|
+
};
|
|
461581
|
+
}
|
|
461582
|
+
async function handleSubagentMessageCommand(command, parent, deps = {}) {
|
|
461583
|
+
const now2 = (deps.now ?? Date.now)();
|
|
461584
|
+
const key3 = dedupeKey(command);
|
|
461585
|
+
for (const [id2, cached4] of responses) {
|
|
461586
|
+
if (cached4.expiresAt <= now2)
|
|
461587
|
+
responses.delete(id2);
|
|
461588
|
+
}
|
|
461589
|
+
const cached3 = responses.get(key3);
|
|
461590
|
+
if (cached3)
|
|
461591
|
+
return cached3.response;
|
|
461592
|
+
const response = (async () => {
|
|
461593
|
+
const base2 = {
|
|
461594
|
+
type: "subagent_message_response",
|
|
461595
|
+
request_id: command.request_id,
|
|
461596
|
+
runtime: command.runtime
|
|
461597
|
+
};
|
|
461598
|
+
try {
|
|
461599
|
+
if (parent.agentId !== command.runtime.agent_id || parent.conversationId !== command.runtime.conversation_id)
|
|
461600
|
+
throw new Error("Parent runtime does not match the message request");
|
|
461601
|
+
if (!findOwnedTask(parent, command.agent_id))
|
|
461602
|
+
throw new Error("Subagent does not belong to this conversation");
|
|
461603
|
+
const target2 = parseExternalCodingAgentId(command.agent_id);
|
|
461604
|
+
if (!target2 || target2.computer || !isExternalCodingAgentType(target2.type))
|
|
461605
|
+
throw new Error("Invalid external coding agent ID");
|
|
461606
|
+
if (!target2.sessionId)
|
|
461607
|
+
throw new Error("External coding agent ID has no session ID");
|
|
461608
|
+
const sessionId = target2.sessionId;
|
|
461609
|
+
if (target2.type === "opencode")
|
|
461610
|
+
throw new Error("Remote OpenCode steering is not supported");
|
|
461611
|
+
let captureReservation;
|
|
461612
|
+
const source = target2.type === "claude-code" ? "claude_code" : "codex";
|
|
461613
|
+
const receipt = await runOutsideRuntimeContext(() => runWithRuntimeContext(runtimeContext(parent, command), () => target2.type === "claude-code" ? (deps.sendClaude ?? sendClaudeMessage)({
|
|
461614
|
+
sessionId: target2.sessionId,
|
|
461615
|
+
prompt: command.message,
|
|
461616
|
+
parentAgentId: command.runtime.agent_id,
|
|
461617
|
+
cwd: getCurrentWorkingDirectory(),
|
|
461618
|
+
beforeStart: async () => {
|
|
461619
|
+
captureReservation = await (deps.reserveCapture ?? reserveNativeSessionCapture)(source, sessionId, {
|
|
461620
|
+
agentId: command.runtime.agent_id,
|
|
461621
|
+
conversationId: command.runtime.conversation_id,
|
|
461622
|
+
actingUserId: command.runtime.acting_user_id
|
|
461623
|
+
});
|
|
461624
|
+
}
|
|
461625
|
+
}) : (deps.sendCodex ?? sendCodexMessage)({
|
|
461626
|
+
threadId: target2.sessionId,
|
|
461627
|
+
prompt: command.message,
|
|
461628
|
+
parentAgentId: command.runtime.agent_id,
|
|
461629
|
+
cwd: getCurrentWorkingDirectory(),
|
|
461630
|
+
beforeStart: async () => {
|
|
461631
|
+
captureReservation = await (deps.reserveCapture ?? reserveNativeSessionCapture)(source, sessionId, {
|
|
461632
|
+
agentId: command.runtime.agent_id,
|
|
461633
|
+
conversationId: command.runtime.conversation_id,
|
|
461634
|
+
actingUserId: command.runtime.acting_user_id
|
|
461635
|
+
});
|
|
461636
|
+
}
|
|
461637
|
+
})));
|
|
461638
|
+
if (receipt.mode === "steered")
|
|
461639
|
+
return { ...base2, success: true, delivery: "steered" };
|
|
461640
|
+
if (!receipt.completion || !receipt.interrupt)
|
|
461641
|
+
throw new Error("External coding agent returned an incomplete receipt");
|
|
461642
|
+
try {
|
|
461643
|
+
(deps.track ?? trackExternalFollowupCompletion)({
|
|
461644
|
+
type: target2.type,
|
|
461645
|
+
agentId: command.agent_id,
|
|
461646
|
+
message: command.message,
|
|
461647
|
+
parentScope: {
|
|
461648
|
+
agentId: parent.agentId,
|
|
461649
|
+
conversationId: parent.conversationId,
|
|
461650
|
+
actingUserId: command.runtime.acting_user_id
|
|
461651
|
+
},
|
|
461652
|
+
completion: receipt.completion,
|
|
461653
|
+
interrupt: receipt.interrupt,
|
|
461654
|
+
captureReservation,
|
|
461655
|
+
toolCallId: command.tool_call_id,
|
|
461656
|
+
publishResult: true
|
|
461657
|
+
});
|
|
461658
|
+
} catch (error5) {
|
|
461659
|
+
await receipt.interrupt().catch(() => {
|
|
461660
|
+
return;
|
|
461661
|
+
});
|
|
461662
|
+
finishUntrackedNativeCapture2(receipt.completion, captureReservation, source, sessionId);
|
|
461663
|
+
throw error5;
|
|
461664
|
+
}
|
|
461665
|
+
return { ...base2, success: true, delivery: "resumed" };
|
|
461666
|
+
} catch (error5) {
|
|
461667
|
+
return {
|
|
461668
|
+
...base2,
|
|
461669
|
+
success: false,
|
|
461670
|
+
error: error5 instanceof Error ? error5.message : String(error5)
|
|
461671
|
+
};
|
|
461672
|
+
}
|
|
461673
|
+
})();
|
|
461674
|
+
responses.set(key3, {
|
|
461675
|
+
expiresAt: now2 + DEDUPE_TTL_MS,
|
|
461676
|
+
response
|
|
461677
|
+
});
|
|
461678
|
+
const result3 = await response;
|
|
461679
|
+
if (!result3.success && responses.get(key3)?.response === response)
|
|
461680
|
+
responses.delete(key3);
|
|
461681
|
+
return result3;
|
|
461682
|
+
}
|
|
461683
|
+
async function handleSubagentStopCommand(command, parent) {
|
|
461684
|
+
const base2 = {
|
|
461685
|
+
type: "subagent_stop_response",
|
|
461686
|
+
request_id: command.request_id,
|
|
461687
|
+
runtime: command.runtime,
|
|
461688
|
+
agent_id: command.agent_id,
|
|
461689
|
+
success: false,
|
|
461690
|
+
stopped: false
|
|
461691
|
+
};
|
|
461692
|
+
if (parent.agentId !== command.runtime.agent_id || parent.conversationId !== command.runtime.conversation_id)
|
|
461693
|
+
return { ...base2, error: "Parent runtime does not match the stop request" };
|
|
461694
|
+
const owned = findOwnedTask(parent, command.agent_id);
|
|
461695
|
+
if (!owned)
|
|
461696
|
+
return { ...base2, error: "Subagent does not belong to this conversation" };
|
|
461697
|
+
const [, task2] = owned;
|
|
461698
|
+
if (task2.status !== "running")
|
|
461699
|
+
return { ...base2, success: true };
|
|
461700
|
+
if (!task2.abortController)
|
|
461701
|
+
return { ...base2, error: "Subagent could not be stopped" };
|
|
461702
|
+
task2.abortController.abort(new Error("Stopped by remote parent"));
|
|
461703
|
+
return { ...base2, success: true, stopped: true };
|
|
461704
|
+
}
|
|
461705
|
+
var DEDUPE_TTL_MS = 30000, responses;
|
|
461706
|
+
var init_subagent_control = __esm(async () => {
|
|
461707
|
+
init_subagent_state();
|
|
461708
|
+
init_runtime_context();
|
|
461709
|
+
init_claude_stream_session();
|
|
461710
|
+
init_codex_app_server();
|
|
461711
|
+
init_external_coding_agent();
|
|
461712
|
+
init_native_session_capture();
|
|
461713
|
+
init_process_manager();
|
|
461714
|
+
init_cwd();
|
|
461715
|
+
await init_external_coding_agent_task();
|
|
461716
|
+
responses = new Map;
|
|
461717
|
+
});
|
|
461718
|
+
|
|
461251
461719
|
// src/websocket/listener/commands/subagents.ts
|
|
461252
461720
|
async function handleLaunchSubagentCommand(command, parent, connectionId, launch = launchSubagent, startupTimeoutMs2 = 25000) {
|
|
461253
461721
|
const response = {
|
|
@@ -461330,10 +461798,16 @@ async function handleTaskControlCommand(command, context3) {
|
|
|
461330
461798
|
safeSocketSend
|
|
461331
461799
|
} = context3;
|
|
461332
461800
|
const execute = async () => {
|
|
461333
|
-
|
|
461801
|
+
if (command.type === "monitor_stop") {
|
|
461802
|
+
const response2 = await handleMonitorStopCommand(command, runtime);
|
|
461803
|
+
safeSocketSend(socket, response2, response2.type, command.type);
|
|
461804
|
+
return;
|
|
461805
|
+
}
|
|
461806
|
+
const parent = getOrCreateScopedRuntime2(runtime, command.runtime.agent_id, command.runtime.conversation_id);
|
|
461807
|
+
const response = command.type === "launch_subagent" ? await handleLaunchSubagentCommand(command, parent, connectionId) : command.type === "subagent_message" ? await handleSubagentMessageCommand(command, parent) : await handleSubagentStopCommand(command, parent);
|
|
461334
461808
|
safeSocketSend(socket, response, response.type, command.type);
|
|
461335
461809
|
};
|
|
461336
|
-
if (command.type === "launch_subagent") {
|
|
461810
|
+
if (command.type === "launch_subagent" || command.type === "subagent_message") {
|
|
461337
461811
|
runDetachedListenerTask2(command.type, execute);
|
|
461338
461812
|
} else {
|
|
461339
461813
|
await execute();
|
|
@@ -461342,6 +461816,7 @@ async function handleTaskControlCommand(command, context3) {
|
|
|
461342
461816
|
var init_task_control = __esm(async () => {
|
|
461343
461817
|
await __promiseAll([
|
|
461344
461818
|
init_monitors(),
|
|
461819
|
+
init_subagent_control(),
|
|
461345
461820
|
init_subagents3()
|
|
461346
461821
|
]);
|
|
461347
461822
|
});
|
|
@@ -461415,7 +461890,7 @@ function createListenerMessageHandler(params) {
|
|
|
461415
461890
|
handleTurnFinishedAck(runtime, socket, connectionId, parsed);
|
|
461416
461891
|
return;
|
|
461417
461892
|
}
|
|
461418
|
-
if (parsed.type === "launch_subagent" || parsed.type === "monitor_stop") {
|
|
461893
|
+
if (parsed.type === "launch_subagent" || parsed.type === "monitor_stop" || parsed.type === "subagent_message" || parsed.type === "subagent_stop") {
|
|
461419
461894
|
const { handleTaskControlCommand: handleTaskControlCommand2 } = await init_task_control().then(() => exports_task_control);
|
|
461420
461895
|
await handleTaskControlCommand2(parsed, {
|
|
461421
461896
|
runtime,
|
|
@@ -462959,7 +463434,7 @@ async function recoverApprovalStateForSync(runtime, scope, deps = {}, opts = {})
|
|
|
462959
463434
|
return {
|
|
462960
463435
|
type: "deny",
|
|
462961
463436
|
approval,
|
|
462962
|
-
reason:
|
|
463437
|
+
reason: STARTED_TOOL_CALL_RECOVERY_DENIAL_REASON
|
|
462963
463438
|
};
|
|
462964
463439
|
}
|
|
462965
463440
|
if (!("tool_return" in saved)) {
|
|
@@ -479495,14 +479970,14 @@ async function executeChannelServiceCommand(command) {
|
|
|
479495
479970
|
if (!isDetachedChannelsCommand(command)) {
|
|
479496
479971
|
throw new Error(`Unsupported ChannelGateway command: ${command.type}`);
|
|
479497
479972
|
}
|
|
479498
|
-
const
|
|
479973
|
+
const responses2 = [];
|
|
479499
479974
|
const detachedTasks = [];
|
|
479500
479975
|
const socket = {};
|
|
479501
479976
|
const safeSocketSend2 = (_socket, payload) => {
|
|
479502
479977
|
if (!payload || typeof payload !== "object" || !("type" in payload)) {
|
|
479503
479978
|
throw new Error("ChannelGateway service emitted an invalid response");
|
|
479504
479979
|
}
|
|
479505
|
-
|
|
479980
|
+
responses2.push(payload);
|
|
479506
479981
|
return true;
|
|
479507
479982
|
};
|
|
479508
479983
|
const runDetachedListenerTask2 = (_commandName, task2) => {
|
|
@@ -479510,7 +479985,7 @@ async function executeChannelServiceCommand(command) {
|
|
|
479510
479985
|
};
|
|
479511
479986
|
await handleChannelsProtocolCommand(command, socket, runDetachedListenerTask2, safeSocketSend2);
|
|
479512
479987
|
await Promise.all(detachedTasks);
|
|
479513
|
-
return
|
|
479988
|
+
return responses2;
|
|
479514
479989
|
}
|
|
479515
479990
|
async function executeGatewayServiceCommand(request3) {
|
|
479516
479991
|
if (request3.kind === "protocol") {
|
|
@@ -522281,6 +522756,18 @@ var init_reasoning_tab_toggle = __esm(() => {
|
|
|
522281
522756
|
DISABLE_ARGS = new Set(["off", "disable", "disabled", "false", "0"]);
|
|
522282
522757
|
});
|
|
522283
522758
|
|
|
522759
|
+
// src/cli/helpers/rename-conversation-target.ts
|
|
522760
|
+
async function renameConvo(conversationId, summary) {
|
|
522761
|
+
if (conversationId === "default") {
|
|
522762
|
+
throw new Error(DEFAULT_CONVERSATION_RENAME_ERROR);
|
|
522763
|
+
}
|
|
522764
|
+
await getBackend().updateConversation(conversationId, { summary });
|
|
522765
|
+
}
|
|
522766
|
+
var DEFAULT_CONVERSATION_RENAME_ERROR = "The default conversation can't be renamed. Start a named one with /new <name>, or switch to another conversation first.";
|
|
522767
|
+
var init_rename_conversation_target = __esm(() => {
|
|
522768
|
+
init_backend2();
|
|
522769
|
+
});
|
|
522770
|
+
|
|
522284
522771
|
// src/cli/app/command-routing.ts
|
|
522285
522772
|
function aliasBareExitCommand(input) {
|
|
522286
522773
|
if (input === "exit" || input === "quit")
|
|
@@ -525328,23 +525815,18 @@ Tip: Use /clear instead to clear the current message buffer.`;
|
|
|
525328
525815
|
});
|
|
525329
525816
|
setCommandRunning(true);
|
|
525330
525817
|
try {
|
|
525331
|
-
const backend3 = getBackend();
|
|
525332
525818
|
if (shouldAutoGenerate) {
|
|
525333
525819
|
const conversationTitle = await generateConversationTitle();
|
|
525334
525820
|
if (!conversationTitle) {
|
|
525335
525821
|
cmd.fail("No conversation content available to generate a title");
|
|
525336
525822
|
return { submitted: true };
|
|
525337
525823
|
}
|
|
525338
|
-
await
|
|
525339
|
-
summary: conversationTitle
|
|
525340
|
-
});
|
|
525824
|
+
await renameConvo(conversationIdRef.current, conversationTitle);
|
|
525341
525825
|
setConversationSummary(conversationTitle);
|
|
525342
525826
|
setConversationAutoTitleEligibility(false);
|
|
525343
525827
|
cmd.finish(`Conversation title set to "${conversationTitle}"`, true);
|
|
525344
525828
|
} else {
|
|
525345
|
-
await
|
|
525346
|
-
summary: newValue
|
|
525347
|
-
});
|
|
525829
|
+
await renameConvo(conversationIdRef.current, newValue);
|
|
525348
525830
|
setConversationSummary(newValue);
|
|
525349
525831
|
setConversationAutoTitleEligibility(false);
|
|
525350
525832
|
cmd.finish(`Conversation renamed to "${newValue}"`, true);
|
|
@@ -526458,6 +526940,7 @@ var init_use_submit_handler = __esm(async () => {
|
|
|
526458
526940
|
init_reflection_completion();
|
|
526459
526941
|
init_reflection_launcher();
|
|
526460
526942
|
init_reflection_transcript();
|
|
526943
|
+
init_rename_conversation_target();
|
|
526461
526944
|
init_system_prompt_warning();
|
|
526462
526945
|
init_thinking_messages();
|
|
526463
526946
|
init_command_runtime();
|
|
@@ -533937,4 +534420,4 @@ function registerBunOAuthFlows() {
|
|
|
533937
534420
|
registerBunOAuthFlows();
|
|
533938
534421
|
await init_src5().then(() => exports_src2);
|
|
533939
534422
|
|
|
533940
|
-
//# debugId=
|
|
534423
|
+
//# debugId=B487A0F42461099B64756E2164756E21
|