@letta-ai/letta-code 0.29.6 → 0.29.7
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 +16 -20
- package/dist/app-server-client.cjs.map +3 -3
- package/dist/app-server-client.js +16 -20
- package/dist/app-server-client.js.map +3 -3
- package/dist/types/app-server-client.d.ts +12 -9
- package/dist/types/app-server-client.d.ts.map +1 -1
- package/letta.js +1370 -694
- package/package.json +1 -1
- package/scripts/source-file-size-baseline.json +4 -4
package/letta.js
CHANGED
|
@@ -5462,7 +5462,7 @@ var package_default;
|
|
|
5462
5462
|
var init_package = __esm(() => {
|
|
5463
5463
|
package_default = {
|
|
5464
5464
|
name: "@letta-ai/letta-code",
|
|
5465
|
-
version: "0.29.
|
|
5465
|
+
version: "0.29.7",
|
|
5466
5466
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5467
5467
|
type: "module",
|
|
5468
5468
|
packageManager: "bun@1.3.0",
|
|
@@ -155347,7 +155347,8 @@ async function runSlackAttachmentDownloadTask(params) {
|
|
|
155347
155347
|
startTime: new Date,
|
|
155348
155348
|
outputFile,
|
|
155349
155349
|
totalStdoutLines: 0,
|
|
155350
|
-
totalStderrLines: 0
|
|
155350
|
+
totalStderrLines: 0,
|
|
155351
|
+
runtimeScope: params.runtimeScope
|
|
155351
155352
|
};
|
|
155352
155353
|
backgroundProcesses.set(taskId, processState);
|
|
155353
155354
|
appendToOutputFile(outputFile, `${params.description}
|
|
@@ -155781,6 +155782,10 @@ async function downloadSlackFile(ctx) {
|
|
|
155781
155782
|
}
|
|
155782
155783
|
const result = await runSlackAttachmentDownloadTask({
|
|
155783
155784
|
description: `Slack attachment download ${attachmentId} from message ${messageId} in ${request.chatId}`,
|
|
155785
|
+
runtimeScope: {
|
|
155786
|
+
agentId: ctx.route.agentId,
|
|
155787
|
+
conversationId: ctx.route.conversationId
|
|
155788
|
+
},
|
|
155784
155789
|
download: (signal) => downloadAttachment.call(ctx.adapter, {
|
|
155785
155790
|
attachmentId,
|
|
155786
155791
|
chatId: request.chatId,
|
|
@@ -170597,11 +170602,6 @@ function evictConversationRuntimeIfIdle(runtime) {
|
|
|
170597
170602
|
}
|
|
170598
170603
|
runtime.listener.conversationRuntimes.delete(runtime.key);
|
|
170599
170604
|
scheduleWorktreeWatcherIdleStop(runtime.listener, runtime);
|
|
170600
|
-
for (const [requestId, runtimeKey] of runtime.listener.approvalRuntimeKeyByRequestId) {
|
|
170601
|
-
if (runtimeKey === runtime.key) {
|
|
170602
|
-
runtime.listener.approvalRuntimeKeyByRequestId.delete(requestId);
|
|
170603
|
-
}
|
|
170604
|
-
}
|
|
170605
170605
|
if (runtime.listener.pendingQueueEmitScope?.agent_id === runtime.agentId && normalizeConversationId(runtime.listener.pendingQueueEmitScope?.conversation_id) === runtime.conversationId) {
|
|
170606
170606
|
runtime.listener.pendingQueueEmitScope = undefined;
|
|
170607
170607
|
}
|
|
@@ -170648,6 +170648,7 @@ function createConversationRuntime(listener, agentId, conversationId) {
|
|
|
170648
170648
|
conversationId: normalizedConversationId,
|
|
170649
170649
|
skillSources: listener.skillSourcesByConversation.get(runtimeKey)?.slice(),
|
|
170650
170650
|
activeChannelTurn: null,
|
|
170651
|
+
activeConnectionId: null,
|
|
170651
170652
|
turnLifecycle,
|
|
170652
170653
|
messageQueue: Promise.resolve(),
|
|
170653
170654
|
pendingApprovalResolvers: new Map,
|
|
@@ -170759,7 +170760,7 @@ function getPendingControlRequests(runtime, params) {
|
|
|
170759
170760
|
if (!conversationRuntime) {
|
|
170760
170761
|
return requests;
|
|
170761
170762
|
}
|
|
170762
|
-
for (const pending of conversationRuntime.pendingApprovalResolvers.values()) {
|
|
170763
|
+
for (const pending of new Set(conversationRuntime.pendingApprovalResolvers.values())) {
|
|
170763
170764
|
const request = pending.controlRequest;
|
|
170764
170765
|
if (!request)
|
|
170765
170766
|
continue;
|
|
@@ -172463,7 +172464,8 @@ async function bash(args) {
|
|
|
172463
172464
|
run_in_background = false,
|
|
172464
172465
|
signal,
|
|
172465
172466
|
onOutput,
|
|
172466
|
-
secretEnv
|
|
172467
|
+
secretEnv,
|
|
172468
|
+
parentScope
|
|
172467
172469
|
} = args;
|
|
172468
172470
|
const userCwd = getCurrentWorkingDirectory();
|
|
172469
172471
|
if (command === "/bg") {
|
|
@@ -172533,7 +172535,8 @@ async function bash(args) {
|
|
|
172533
172535
|
startTime: new Date,
|
|
172534
172536
|
outputFile,
|
|
172535
172537
|
totalStdoutLines: 0,
|
|
172536
|
-
totalStderrLines: 0
|
|
172538
|
+
totalStderrLines: 0,
|
|
172539
|
+
runtimeScope: parentScope
|
|
172537
172540
|
});
|
|
172538
172541
|
const bgProcess = backgroundProcesses.get(bashId);
|
|
172539
172542
|
if (!bgProcess) {
|
|
@@ -173164,6 +173167,268 @@ var init_worktree_lock = __esm(() => {
|
|
|
173164
173167
|
HOSTNAME = os3.hostname();
|
|
173165
173168
|
});
|
|
173166
173169
|
|
|
173170
|
+
// src/websocket/listener/transport.ts
|
|
173171
|
+
import WebSocket3 from "ws";
|
|
173172
|
+
|
|
173173
|
+
class LocalListenerTransport {
|
|
173174
|
+
kind = "local";
|
|
173175
|
+
bufferedAmount = 0;
|
|
173176
|
+
isOpen() {
|
|
173177
|
+
return true;
|
|
173178
|
+
}
|
|
173179
|
+
send(_data) {}
|
|
173180
|
+
}
|
|
173181
|
+
function isListenerTransportOpen(transport) {
|
|
173182
|
+
if ("isOpen" in transport && typeof transport.isOpen === "function") {
|
|
173183
|
+
return transport.isOpen();
|
|
173184
|
+
}
|
|
173185
|
+
return transport.readyState === WebSocket3.OPEN;
|
|
173186
|
+
}
|
|
173187
|
+
function getListenerTransportKind(transport) {
|
|
173188
|
+
return "kind" in transport ? transport.kind : "websocket";
|
|
173189
|
+
}
|
|
173190
|
+
var init_transport = () => {};
|
|
173191
|
+
|
|
173192
|
+
// src/websocket/listener/connection.ts
|
|
173193
|
+
function toListenerConnection(connectionId) {
|
|
173194
|
+
return { type: "ToConnection", connectionId };
|
|
173195
|
+
}
|
|
173196
|
+
function getResumeStates(runtime) {
|
|
173197
|
+
let states2 = resumeStateByRuntime.get(runtime);
|
|
173198
|
+
if (!states2) {
|
|
173199
|
+
states2 = new Map;
|
|
173200
|
+
resumeStateByRuntime.set(runtime, states2);
|
|
173201
|
+
}
|
|
173202
|
+
return states2;
|
|
173203
|
+
}
|
|
173204
|
+
function socketForTransport(transport) {
|
|
173205
|
+
return "kind" in transport ? null : transport;
|
|
173206
|
+
}
|
|
173207
|
+
function refreshLegacySingleConnection(runtime) {
|
|
173208
|
+
const live = [...runtime.connections.values()].filter((connection) => isListenerTransportOpen(connection.writer));
|
|
173209
|
+
const only = live.length === 1 ? live[0] : null;
|
|
173210
|
+
runtime.transport = only?.writer ?? runtime.processTransport;
|
|
173211
|
+
runtime.streamTransport = only?.streamWriter ?? null;
|
|
173212
|
+
runtime.socket = only ? socketForTransport(only.writer) : null;
|
|
173213
|
+
runtime.streamSocket = only?.streamWriter ? socketForTransport(only.streamWriter) : null;
|
|
173214
|
+
}
|
|
173215
|
+
function createConnectionRequestKey(connectionId, requestId) {
|
|
173216
|
+
return JSON.stringify([connectionId, requestId]);
|
|
173217
|
+
}
|
|
173218
|
+
function openListenerConnection(params) {
|
|
173219
|
+
const existing = params.runtime.connections.get(params.connectionId);
|
|
173220
|
+
if (existing) {
|
|
173221
|
+
throw new Error(`Listener connection already open: ${params.connectionId}`);
|
|
173222
|
+
}
|
|
173223
|
+
const resumeStates = getResumeStates(params.runtime);
|
|
173224
|
+
const resumed = resumeStates.get(params.connectionId);
|
|
173225
|
+
resumeStates.delete(params.connectionId);
|
|
173226
|
+
const connection = {
|
|
173227
|
+
id: params.connectionId,
|
|
173228
|
+
ordinal: resumed?.ordinal ?? params.runtime.nextConnectionOrdinal,
|
|
173229
|
+
writer: params.writer,
|
|
173230
|
+
streamWriter: params.streamWriter ?? null,
|
|
173231
|
+
cancellation: params.cancellation ?? new AbortController,
|
|
173232
|
+
initialized: false,
|
|
173233
|
+
subscriptions: resumed?.subscriptions ?? new Set,
|
|
173234
|
+
eventSeqCounter: resumed?.eventSeqCounter ?? 0,
|
|
173235
|
+
options: params.options
|
|
173236
|
+
};
|
|
173237
|
+
if (!resumed) {
|
|
173238
|
+
params.runtime.nextConnectionOrdinal += 1;
|
|
173239
|
+
}
|
|
173240
|
+
params.runtime.connections.set(connection.id, connection);
|
|
173241
|
+
for (const runtimeKey of connection.subscriptions) {
|
|
173242
|
+
let connectionIds = params.runtime.connectionIdsByRuntimeKey.get(runtimeKey);
|
|
173243
|
+
if (!connectionIds) {
|
|
173244
|
+
connectionIds = new Set;
|
|
173245
|
+
params.runtime.connectionIdsByRuntimeKey.set(runtimeKey, connectionIds);
|
|
173246
|
+
}
|
|
173247
|
+
connectionIds.add(connection.id);
|
|
173248
|
+
}
|
|
173249
|
+
refreshLegacySingleConnection(params.runtime);
|
|
173250
|
+
return connection;
|
|
173251
|
+
}
|
|
173252
|
+
function markListenerConnectionInitialized(runtime, connectionId) {
|
|
173253
|
+
const connection = runtime.connections.get(connectionId);
|
|
173254
|
+
if (connection) {
|
|
173255
|
+
connection.initialized = true;
|
|
173256
|
+
}
|
|
173257
|
+
}
|
|
173258
|
+
function subscribeListenerConnection(runtime, connectionId, scope) {
|
|
173259
|
+
const connection = runtime.connections.get(connectionId);
|
|
173260
|
+
if (!connection || typeof scope.agent_id !== "string") {
|
|
173261
|
+
return false;
|
|
173262
|
+
}
|
|
173263
|
+
const runtimeKey = getConversationRuntimeKey(scope.agent_id, scope.conversation_id);
|
|
173264
|
+
connection.subscriptions.add(runtimeKey);
|
|
173265
|
+
let connectionIds = runtime.connectionIdsByRuntimeKey.get(runtimeKey);
|
|
173266
|
+
if (!connectionIds) {
|
|
173267
|
+
connectionIds = new Set;
|
|
173268
|
+
runtime.connectionIdsByRuntimeKey.set(runtimeKey, connectionIds);
|
|
173269
|
+
}
|
|
173270
|
+
connectionIds.add(connectionId);
|
|
173271
|
+
return true;
|
|
173272
|
+
}
|
|
173273
|
+
function unsubscribeListenerConnection(runtime, connectionId, runtimeKey) {
|
|
173274
|
+
const connection = runtime.connections.get(connectionId);
|
|
173275
|
+
if (!connection?.subscriptions.delete(runtimeKey)) {
|
|
173276
|
+
return false;
|
|
173277
|
+
}
|
|
173278
|
+
const connectionIds = runtime.connectionIdsByRuntimeKey.get(runtimeKey);
|
|
173279
|
+
connectionIds?.delete(connectionId);
|
|
173280
|
+
if (connectionIds?.size === 0) {
|
|
173281
|
+
runtime.connectionIdsByRuntimeKey.delete(runtimeKey);
|
|
173282
|
+
}
|
|
173283
|
+
return true;
|
|
173284
|
+
}
|
|
173285
|
+
function getSubscribedListenerConnections(runtime, scope) {
|
|
173286
|
+
if (typeof scope.agent_id !== "string") {
|
|
173287
|
+
return [];
|
|
173288
|
+
}
|
|
173289
|
+
const runtimeKey = getConversationRuntimeKey(scope.agent_id, scope.conversation_id);
|
|
173290
|
+
const connectionIds = runtime.connectionIdsByRuntimeKey.get(runtimeKey);
|
|
173291
|
+
if (!connectionIds) {
|
|
173292
|
+
return [];
|
|
173293
|
+
}
|
|
173294
|
+
return [...connectionIds].map((connectionId) => runtime.connections.get(connectionId)).filter((connection) => connection?.initialized === true && isListenerTransportOpen(connection.writer)).sort((a, b) => a.ordinal - b.ordinal);
|
|
173295
|
+
}
|
|
173296
|
+
function findListenerConnectionByTransport(runtime, transport) {
|
|
173297
|
+
for (const connection of runtime.connections.values()) {
|
|
173298
|
+
if (connection.writer === transport || connection.streamWriter === transport) {
|
|
173299
|
+
return connection;
|
|
173300
|
+
}
|
|
173301
|
+
}
|
|
173302
|
+
return null;
|
|
173303
|
+
}
|
|
173304
|
+
function nextListenerConnectionEventSeq(connection, runtime) {
|
|
173305
|
+
if (!connection) {
|
|
173306
|
+
return nextEventSeq(runtime);
|
|
173307
|
+
}
|
|
173308
|
+
connection.eventSeqCounter += 1;
|
|
173309
|
+
return connection.eventSeqCounter;
|
|
173310
|
+
}
|
|
173311
|
+
function resolveListenerConnectionTargets(params) {
|
|
173312
|
+
const runtime = params.runtime;
|
|
173313
|
+
let connections;
|
|
173314
|
+
switch (params.routing.type) {
|
|
173315
|
+
case "ToConnection": {
|
|
173316
|
+
const explicitConnection = runtime?.connections.get(params.routing.connectionId);
|
|
173317
|
+
if (explicitConnection) {
|
|
173318
|
+
connections = [explicitConnection];
|
|
173319
|
+
break;
|
|
173320
|
+
}
|
|
173321
|
+
if ((runtime?.connections.size ?? 0) === 0 && params.routing.connectionId === (runtime?.connectionId ?? "legacy")) {
|
|
173322
|
+
connections = [null];
|
|
173323
|
+
break;
|
|
173324
|
+
}
|
|
173325
|
+
return [];
|
|
173326
|
+
}
|
|
173327
|
+
case "ToSubscribers": {
|
|
173328
|
+
connections = runtime ? getSubscribedListenerConnections(runtime, params.scope) : [];
|
|
173329
|
+
if (connections.length > 0) {
|
|
173330
|
+
break;
|
|
173331
|
+
}
|
|
173332
|
+
if ((runtime?.connections.size ?? 0) === 0) {
|
|
173333
|
+
connections = [null];
|
|
173334
|
+
break;
|
|
173335
|
+
}
|
|
173336
|
+
return [];
|
|
173337
|
+
}
|
|
173338
|
+
case "Broadcast": {
|
|
173339
|
+
connections = runtime ? [...runtime.connections.values()].filter((connection) => connection.initialized && isListenerTransportOpen(connection.writer)) : [];
|
|
173340
|
+
if (connections.length === 0 && (runtime?.connections.size ?? 0) === 0) {
|
|
173341
|
+
connections = [null];
|
|
173342
|
+
}
|
|
173343
|
+
break;
|
|
173344
|
+
}
|
|
173345
|
+
}
|
|
173346
|
+
return connections.map((connection) => {
|
|
173347
|
+
const streamTransport = connection?.streamWriter;
|
|
173348
|
+
if (params.streamMessage && streamTransport && isListenerTransportOpen(streamTransport)) {
|
|
173349
|
+
return { connection, transport: streamTransport };
|
|
173350
|
+
}
|
|
173351
|
+
const legacyStreamTransport = params.runtime?.streamTransport;
|
|
173352
|
+
if (!connection && params.streamMessage && legacyStreamTransport && isListenerTransportOpen(legacyStreamTransport)) {
|
|
173353
|
+
return { connection, transport: legacyStreamTransport };
|
|
173354
|
+
}
|
|
173355
|
+
return { connection, transport: connection?.writer ?? params.origin };
|
|
173356
|
+
});
|
|
173357
|
+
}
|
|
173358
|
+
function closeListenerConnection(runtime, connectionId) {
|
|
173359
|
+
getResumeStates(runtime).delete(connectionId);
|
|
173360
|
+
const connection = runtime.connections.get(connectionId);
|
|
173361
|
+
if (!connection) {
|
|
173362
|
+
return null;
|
|
173363
|
+
}
|
|
173364
|
+
for (const runtimeKey of [...connection.subscriptions]) {
|
|
173365
|
+
unsubscribeListenerConnection(runtime, connectionId, runtimeKey);
|
|
173366
|
+
}
|
|
173367
|
+
runtime.connections.delete(connectionId);
|
|
173368
|
+
connection.cancellation.abort();
|
|
173369
|
+
refreshLegacySingleConnection(runtime);
|
|
173370
|
+
return connection;
|
|
173371
|
+
}
|
|
173372
|
+
function suspendListenerConnection(runtime, connectionId) {
|
|
173373
|
+
const connection = runtime.connections.get(connectionId);
|
|
173374
|
+
if (!connection) {
|
|
173375
|
+
return null;
|
|
173376
|
+
}
|
|
173377
|
+
const resumeState = {
|
|
173378
|
+
ordinal: connection.ordinal,
|
|
173379
|
+
subscriptions: new Set(connection.subscriptions),
|
|
173380
|
+
eventSeqCounter: connection.eventSeqCounter
|
|
173381
|
+
};
|
|
173382
|
+
const closed = closeListenerConnection(runtime, connectionId);
|
|
173383
|
+
getResumeStates(runtime).set(connectionId, resumeState);
|
|
173384
|
+
return closed;
|
|
173385
|
+
}
|
|
173386
|
+
|
|
173387
|
+
class ProcessRuntimeTransport {
|
|
173388
|
+
runtime;
|
|
173389
|
+
kind = "runtime";
|
|
173390
|
+
constructor(runtime) {
|
|
173391
|
+
this.runtime = runtime;
|
|
173392
|
+
}
|
|
173393
|
+
get bufferedAmount() {
|
|
173394
|
+
let total = 0;
|
|
173395
|
+
for (const connection of this.runtime.connections.values()) {
|
|
173396
|
+
total += connection.writer.bufferedAmount;
|
|
173397
|
+
}
|
|
173398
|
+
return total;
|
|
173399
|
+
}
|
|
173400
|
+
isOpen() {
|
|
173401
|
+
for (const connection of this.runtime.connections.values()) {
|
|
173402
|
+
if (connection.initialized && isListenerTransportOpen(connection.writer)) {
|
|
173403
|
+
return true;
|
|
173404
|
+
}
|
|
173405
|
+
}
|
|
173406
|
+
return false;
|
|
173407
|
+
}
|
|
173408
|
+
send(data) {
|
|
173409
|
+
throw new Error(`Process runtime transport cannot send an implicit message (${data.length} bytes); resolve ToConnection, ToSubscribers, or Broadcast first`);
|
|
173410
|
+
}
|
|
173411
|
+
}
|
|
173412
|
+
function getOrCreateProcessTransport(runtime) {
|
|
173413
|
+
runtime.processTransport ??= new ProcessRuntimeTransport(runtime);
|
|
173414
|
+
if (runtime.connections.size !== 1) {
|
|
173415
|
+
refreshLegacySingleConnection(runtime);
|
|
173416
|
+
}
|
|
173417
|
+
return runtime.processTransport;
|
|
173418
|
+
}
|
|
173419
|
+
var TO_SUBSCRIBERS, BROADCAST, resumeStateByRuntime;
|
|
173420
|
+
var init_connection = __esm(() => {
|
|
173421
|
+
init_runtime6();
|
|
173422
|
+
init_transport();
|
|
173423
|
+
TO_SUBSCRIBERS = {
|
|
173424
|
+
type: "ToSubscribers"
|
|
173425
|
+
};
|
|
173426
|
+
BROADCAST = {
|
|
173427
|
+
type: "Broadcast"
|
|
173428
|
+
};
|
|
173429
|
+
resumeStateByRuntime = new WeakMap;
|
|
173430
|
+
});
|
|
173431
|
+
|
|
173167
173432
|
// src/cli/helpers/memory-reminder.ts
|
|
173168
173433
|
function isValidStepCount(value) {
|
|
173169
173434
|
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value > 0;
|
|
@@ -173434,6 +173699,43 @@ var init_system_prompt_warning = __esm(() => {
|
|
|
173434
173699
|
systemPromptDoctorStateByAgent = new Map;
|
|
173435
173700
|
});
|
|
173436
173701
|
|
|
173702
|
+
// src/websocket/listener/background-process-snapshot.ts
|
|
173703
|
+
function belongsToRuntime(entry, runtimeScope) {
|
|
173704
|
+
return entry.runtimeScope?.agentId === runtimeScope.agentId && entry.runtimeScope.conversationId === runtimeScope.conversationId;
|
|
173705
|
+
}
|
|
173706
|
+
function buildBackgroundProcessSnapshot(agentId, conversationId = "default") {
|
|
173707
|
+
if (agentId === null) {
|
|
173708
|
+
return [];
|
|
173709
|
+
}
|
|
173710
|
+
const runtimeScope = agentId === undefined ? undefined : { agentId, conversationId };
|
|
173711
|
+
const bashProcesses = Array.from(backgroundProcesses.entries()).filter(([, proc]) => proc.status === "running" && (!runtimeScope || belongsToRuntime(proc, runtimeScope))).map(([processId, proc]) => ({
|
|
173712
|
+
process_id: processId,
|
|
173713
|
+
kind: "bash",
|
|
173714
|
+
command: proc.command,
|
|
173715
|
+
started_at_ms: proc.startTime?.getTime() ?? null,
|
|
173716
|
+
status: proc.status,
|
|
173717
|
+
exit_code: proc.exitCode
|
|
173718
|
+
}));
|
|
173719
|
+
const taskProcesses = Array.from(backgroundTasks.entries()).filter(([, task]) => task.status === "running" && (!runtimeScope || belongsToRuntime(task, runtimeScope))).map(([processId, task]) => ({
|
|
173720
|
+
process_id: processId,
|
|
173721
|
+
kind: "agent_task",
|
|
173722
|
+
task_type: task.subagentType,
|
|
173723
|
+
description: task.description,
|
|
173724
|
+
started_at_ms: task.startTime.getTime(),
|
|
173725
|
+
status: task.status,
|
|
173726
|
+
subagent_id: task.subagentId,
|
|
173727
|
+
...task.error ? { error: task.error } : {}
|
|
173728
|
+
}));
|
|
173729
|
+
return [...bashProcesses, ...taskProcesses].sort((a, b) => {
|
|
173730
|
+
const aStart = a.started_at_ms ?? 0;
|
|
173731
|
+
const bStart = b.started_at_ms ?? 0;
|
|
173732
|
+
return bStart - aStart;
|
|
173733
|
+
});
|
|
173734
|
+
}
|
|
173735
|
+
var init_background_process_snapshot = __esm(() => {
|
|
173736
|
+
init_process_manager();
|
|
173737
|
+
});
|
|
173738
|
+
|
|
173437
173739
|
// src/websocket/listener/channel-turn-session.ts
|
|
173438
173740
|
function getChannelTurnSourceKey(source2) {
|
|
173439
173741
|
return [
|
|
@@ -346947,28 +347249,6 @@ var init_mod_commands = __esm(async () => {
|
|
|
346947
347249
|
]);
|
|
346948
347250
|
});
|
|
346949
347251
|
|
|
346950
|
-
// src/websocket/listener/transport.ts
|
|
346951
|
-
import WebSocket3 from "ws";
|
|
346952
|
-
|
|
346953
|
-
class LocalListenerTransport {
|
|
346954
|
-
kind = "local";
|
|
346955
|
-
bufferedAmount = 0;
|
|
346956
|
-
isOpen() {
|
|
346957
|
-
return true;
|
|
346958
|
-
}
|
|
346959
|
-
send(_data) {}
|
|
346960
|
-
}
|
|
346961
|
-
function isListenerTransportOpen(transport) {
|
|
346962
|
-
if ("isOpen" in transport && typeof transport.isOpen === "function") {
|
|
346963
|
-
return transport.isOpen();
|
|
346964
|
-
}
|
|
346965
|
-
return transport.readyState === WebSocket3.OPEN;
|
|
346966
|
-
}
|
|
346967
|
-
function getListenerTransportKind(transport) {
|
|
346968
|
-
return "kind" in transport ? transport.kind : "websocket";
|
|
346969
|
-
}
|
|
346970
|
-
var init_transport = () => {};
|
|
346971
|
-
|
|
346972
347252
|
// src/websocket/listener/outbound-wire.ts
|
|
346973
347253
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync24 } from "node:fs";
|
|
346974
347254
|
import { dirname as dirname14 } from "node:path";
|
|
@@ -347302,31 +347582,6 @@ function getScopeForRuntime(runtime, scope) {
|
|
|
347302
347582
|
}
|
|
347303
347583
|
return scope ?? {};
|
|
347304
347584
|
}
|
|
347305
|
-
function buildBackgroundProcessSnapshot() {
|
|
347306
|
-
const bashProcesses = Array.from(backgroundProcesses.entries()).filter(([, proc]) => proc.status === "running").map(([processId, proc]) => ({
|
|
347307
|
-
process_id: processId,
|
|
347308
|
-
kind: "bash",
|
|
347309
|
-
command: proc.command,
|
|
347310
|
-
started_at_ms: proc.startTime?.getTime() ?? null,
|
|
347311
|
-
status: proc.status,
|
|
347312
|
-
exit_code: proc.exitCode
|
|
347313
|
-
}));
|
|
347314
|
-
const taskProcesses = Array.from(backgroundTasks.entries()).filter(([, task]) => task.status === "running").map(([processId, task]) => ({
|
|
347315
|
-
process_id: processId,
|
|
347316
|
-
kind: "agent_task",
|
|
347317
|
-
task_type: task.subagentType,
|
|
347318
|
-
description: task.description,
|
|
347319
|
-
started_at_ms: task.startTime.getTime(),
|
|
347320
|
-
status: task.status,
|
|
347321
|
-
subagent_id: task.subagentId,
|
|
347322
|
-
...task.error ? { error: task.error } : {}
|
|
347323
|
-
}));
|
|
347324
|
-
return [...bashProcesses, ...taskProcesses].sort((a, b) => {
|
|
347325
|
-
const aStart = a.started_at_ms ?? 0;
|
|
347326
|
-
const bStart = b.started_at_ms ?? 0;
|
|
347327
|
-
return bStart - aStart;
|
|
347328
|
-
});
|
|
347329
|
-
}
|
|
347330
347585
|
function emitRuntimeStateUpdates(runtime, scope) {
|
|
347331
347586
|
emitLoopStatusIfOpen(runtime, scope);
|
|
347332
347587
|
emitDeviceStatusIfOpen(runtime, scope);
|
|
@@ -347401,7 +347656,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
347401
347656
|
current_toolset_preference: conversationRuntime?.currentToolsetPreference ?? toolsetPreference,
|
|
347402
347657
|
current_loaded_tools: conversationRuntime?.currentLoadedTools ?? [],
|
|
347403
347658
|
current_available_skills: [],
|
|
347404
|
-
background_processes: buildBackgroundProcessSnapshot(),
|
|
347659
|
+
background_processes: buildBackgroundProcessSnapshot(scopedAgentId, scopedConversationId),
|
|
347405
347660
|
pending_control_requests: interruptedCacheActive ? [] : getPendingControlRequests(listener, scope),
|
|
347406
347661
|
experiments: experimentManager.list(),
|
|
347407
347662
|
memory_directory: scopedAgentId ? getScopedMemoryFilesystemRoot(scopedAgentId) : null,
|
|
@@ -347464,87 +347719,90 @@ function isStreamChannelMessage(type3) {
|
|
|
347464
347719
|
function classifyOutboundFrame(message) {
|
|
347465
347720
|
return COALESCABLE_STATUS_MESSAGE_TYPES.has(message.type) ? "status" : "critical";
|
|
347466
347721
|
}
|
|
347467
|
-
function emitProtocolV2Message(socket, runtime, message, scope) {
|
|
347722
|
+
function emitProtocolV2Message(socket, runtime, message, scope, routing) {
|
|
347468
347723
|
const listener = getListenerRuntime(runtime);
|
|
347469
|
-
let targetSocket = socket;
|
|
347470
|
-
if (listener?.streamTransport && isStreamChannelMessage(message.type)) {
|
|
347471
|
-
if (isListenerTransportOpen(listener.streamTransport)) {
|
|
347472
|
-
targetSocket = listener.streamTransport;
|
|
347473
|
-
}
|
|
347474
|
-
}
|
|
347475
347724
|
const runtimeScope = resolveRuntimeScope(listener, getScopeForRuntime(runtime, scope));
|
|
347476
347725
|
if (!runtimeScope)
|
|
347477
347726
|
return;
|
|
347478
347727
|
notifyStreamObservers(listener, message, runtimeScope);
|
|
347479
|
-
if (!isListenerTransportOpen(targetSocket))
|
|
347480
|
-
return;
|
|
347481
347728
|
const frameClass = classifyOutboundFrame(message);
|
|
347482
|
-
|
|
347483
|
-
|
|
347484
|
-
|
|
347485
|
-
|
|
347486
|
-
|
|
347487
|
-
|
|
347488
|
-
|
|
347489
|
-
|
|
347490
|
-
|
|
347491
|
-
|
|
347492
|
-
|
|
347493
|
-
|
|
347494
|
-
|
|
347495
|
-
|
|
347496
|
-
|
|
347497
|
-
|
|
347498
|
-
|
|
347499
|
-
|
|
347500
|
-
|
|
347501
|
-
|
|
347502
|
-
|
|
347503
|
-
|
|
347729
|
+
const targets = resolveListenerConnectionTargets({
|
|
347730
|
+
runtime: listener,
|
|
347731
|
+
origin: socket,
|
|
347732
|
+
scope: runtimeScope,
|
|
347733
|
+
routing,
|
|
347734
|
+
streamMessage: isStreamChannelMessage(message.type)
|
|
347735
|
+
});
|
|
347736
|
+
for (const { connection, transport: targetSocket } of targets) {
|
|
347737
|
+
if (!isListenerTransportOpen(targetSocket))
|
|
347738
|
+
continue;
|
|
347739
|
+
enqueueOutboundFrame(targetSocket, {
|
|
347740
|
+
typeLabel: message.type,
|
|
347741
|
+
frameClass,
|
|
347742
|
+
...frameClass === "status" ? {
|
|
347743
|
+
coalesceKey: `${message.type}:${runtimeScope.agent_id ?? ""}:${runtimeScope.conversation_id ?? ""}`
|
|
347744
|
+
} : {},
|
|
347745
|
+
build: () => {
|
|
347746
|
+
const eventSeq = nextListenerConnectionEventSeq(connection, listener);
|
|
347747
|
+
if (eventSeq === null)
|
|
347748
|
+
return null;
|
|
347749
|
+
const outbound = {
|
|
347750
|
+
...message,
|
|
347751
|
+
runtime: runtimeScope,
|
|
347752
|
+
event_seq: eventSeq,
|
|
347753
|
+
emitted_at: new Date().toISOString(),
|
|
347754
|
+
idempotency_key: `${message.type}:${eventSeq}:${crypto.randomUUID()}`
|
|
347755
|
+
};
|
|
347756
|
+
let payload;
|
|
347757
|
+
try {
|
|
347758
|
+
payload = JSON.stringify(outbound);
|
|
347759
|
+
} catch (error54) {
|
|
347760
|
+
console.error(`[Listen V2] Failed to emit ${message.type} (seq=${eventSeq})`, error54);
|
|
347761
|
+
safeEmitWsEvent("send", "lifecycle", {
|
|
347762
|
+
type: "_ws_send_error",
|
|
347763
|
+
message_type: message.type,
|
|
347764
|
+
event_seq: eventSeq,
|
|
347765
|
+
error: error54 instanceof Error ? error54.message : String(error54)
|
|
347766
|
+
});
|
|
347767
|
+
return null;
|
|
347768
|
+
}
|
|
347769
|
+
return {
|
|
347770
|
+
payload,
|
|
347771
|
+
perfKey: getProtocolPerfKey(message),
|
|
347772
|
+
onSent: () => {
|
|
347773
|
+
if (isDebugEnabled()) {
|
|
347774
|
+
console.log(`[Listen V2] Emitting ${message.type} (seq=${eventSeq})`);
|
|
347775
|
+
}
|
|
347776
|
+
safeEmitWsEvent("send", "protocol", outbound);
|
|
347777
|
+
}
|
|
347778
|
+
};
|
|
347779
|
+
},
|
|
347780
|
+
onSendError: (error54) => {
|
|
347781
|
+
console.error(`[Listen V2] Failed to emit ${message.type}`, error54);
|
|
347504
347782
|
safeEmitWsEvent("send", "lifecycle", {
|
|
347505
347783
|
type: "_ws_send_error",
|
|
347506
347784
|
message_type: message.type,
|
|
347507
|
-
event_seq: eventSeq,
|
|
347508
347785
|
error: error54 instanceof Error ? error54.message : String(error54)
|
|
347509
347786
|
});
|
|
347510
|
-
return null;
|
|
347511
347787
|
}
|
|
347512
|
-
|
|
347513
|
-
|
|
347514
|
-
perfKey: getProtocolPerfKey(message),
|
|
347515
|
-
onSent: () => {
|
|
347516
|
-
if (isDebugEnabled()) {
|
|
347517
|
-
console.log(`[Listen V2] Emitting ${message.type} (seq=${eventSeq})`);
|
|
347518
|
-
}
|
|
347519
|
-
safeEmitWsEvent("send", "protocol", outbound);
|
|
347520
|
-
}
|
|
347521
|
-
};
|
|
347522
|
-
},
|
|
347523
|
-
onSendError: (error54) => {
|
|
347524
|
-
console.error(`[Listen V2] Failed to emit ${message.type}`, error54);
|
|
347525
|
-
safeEmitWsEvent("send", "lifecycle", {
|
|
347526
|
-
type: "_ws_send_error",
|
|
347527
|
-
message_type: message.type,
|
|
347528
|
-
error: error54 instanceof Error ? error54.message : String(error54)
|
|
347529
|
-
});
|
|
347530
|
-
}
|
|
347531
|
-
});
|
|
347788
|
+
});
|
|
347789
|
+
}
|
|
347532
347790
|
}
|
|
347533
|
-
function emitDeviceStatusUpdate(socket, runtime, scope) {
|
|
347791
|
+
function emitDeviceStatusUpdate(socket, runtime, scope, routing = TO_SUBSCRIBERS) {
|
|
347534
347792
|
const deviceStatus = buildDeviceStatus(runtime, scope);
|
|
347535
347793
|
recordDeviceStatus(socket, getScopeForRuntime(runtime, scope), deviceStatus);
|
|
347536
347794
|
const message = {
|
|
347537
347795
|
type: "update_device_status",
|
|
347538
347796
|
device_status: deviceStatus
|
|
347539
347797
|
};
|
|
347540
|
-
emitProtocolV2Message(socket, runtime, message, scope);
|
|
347798
|
+
emitProtocolV2Message(socket, runtime, message, scope, routing);
|
|
347541
347799
|
}
|
|
347542
|
-
function emitLoopStatusUpdate(socket, runtime, scope) {
|
|
347800
|
+
function emitLoopStatusUpdate(socket, runtime, scope, routing = TO_SUBSCRIBERS) {
|
|
347543
347801
|
const message = {
|
|
347544
347802
|
type: "update_loop_status",
|
|
347545
347803
|
loop_status: buildLoopStatus(runtime, scope)
|
|
347546
347804
|
};
|
|
347547
|
-
emitProtocolV2Message(socket, runtime, message, scope);
|
|
347805
|
+
emitProtocolV2Message(socket, runtime, message, scope, routing);
|
|
347548
347806
|
}
|
|
347549
347807
|
function emitLoopStatusIfOpen(runtime, scope) {
|
|
347550
347808
|
const listener = getListenerRuntime(runtime);
|
|
@@ -347560,7 +347818,7 @@ function emitDeviceStatusIfOpen(runtime, scope) {
|
|
|
347560
347818
|
emitDeviceStatusUpdate(transport, runtime, scope);
|
|
347561
347819
|
}
|
|
347562
347820
|
}
|
|
347563
|
-
function emitQueueUpdate(socket, runtime, scope) {
|
|
347821
|
+
function emitQueueUpdate(socket, runtime, scope, routing = TO_SUBSCRIBERS) {
|
|
347564
347822
|
const listener = getListenerRuntime(runtime);
|
|
347565
347823
|
if (!listener) {
|
|
347566
347824
|
return;
|
|
@@ -347570,7 +347828,7 @@ function emitQueueUpdate(socket, runtime, scope) {
|
|
|
347570
347828
|
type: "update_queue",
|
|
347571
347829
|
queue: buildQueueSnapshot(runtime, resolvedScope)
|
|
347572
347830
|
};
|
|
347573
|
-
emitProtocolV2Message(socket, runtime, message, resolvedScope);
|
|
347831
|
+
emitProtocolV2Message(socket, runtime, message, resolvedScope, routing);
|
|
347574
347832
|
}
|
|
347575
347833
|
function isTextContentPart(part) {
|
|
347576
347834
|
return !!part && typeof part === "object" && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string";
|
|
@@ -347670,7 +347928,7 @@ function emitQueueUpdateIfOpen(runtime, scope) {
|
|
|
347670
347928
|
emitQueueUpdate(transport, runtime, scope);
|
|
347671
347929
|
}
|
|
347672
347930
|
}
|
|
347673
|
-
function emitDeviceStatusUpdateIfChanged(socket, runtime, scope, options3) {
|
|
347931
|
+
function emitDeviceStatusUpdateIfChanged(socket, runtime, scope, options3, routing = TO_SUBSCRIBERS) {
|
|
347674
347932
|
const resolvedScope = getScopeForRuntime(runtime, scope);
|
|
347675
347933
|
const deviceStatus = buildDeviceStatus(runtime, resolvedScope);
|
|
347676
347934
|
if (!shouldEmitDeviceStatus(socket, resolvedScope, deviceStatus, options3?.force)) {
|
|
@@ -347680,14 +347938,15 @@ function emitDeviceStatusUpdateIfChanged(socket, runtime, scope, options3) {
|
|
|
347680
347938
|
type: "update_device_status",
|
|
347681
347939
|
device_status: deviceStatus
|
|
347682
347940
|
};
|
|
347683
|
-
emitProtocolV2Message(socket, runtime, message, resolvedScope);
|
|
347941
|
+
emitProtocolV2Message(socket, runtime, message, resolvedScope, routing);
|
|
347684
347942
|
return true;
|
|
347685
347943
|
}
|
|
347686
347944
|
function emitStateSync(socket, runtime, scope, options3) {
|
|
347687
|
-
|
|
347688
|
-
|
|
347689
|
-
|
|
347690
|
-
|
|
347945
|
+
const routing = options3?.routing ?? TO_SUBSCRIBERS;
|
|
347946
|
+
emitDeviceStatusUpdateIfChanged(socket, runtime, scope, options3?.forceDeviceStatus ? { force: true } : undefined, routing);
|
|
347947
|
+
emitLoopStatusUpdate(socket, runtime, scope, routing);
|
|
347948
|
+
emitQueueUpdate(socket, runtime, scope, routing);
|
|
347949
|
+
emitSubagentStateUpdate(socket, runtime, scope, routing);
|
|
347691
347950
|
}
|
|
347692
347951
|
function resolveSubagentScopeForSnapshot(runtime, scope) {
|
|
347693
347952
|
const listener = getListenerRuntime(runtime);
|
|
@@ -347728,12 +347987,12 @@ function buildSubagentSnapshot(runtime, scope) {
|
|
|
347728
347987
|
error: a.error
|
|
347729
347988
|
}));
|
|
347730
347989
|
}
|
|
347731
|
-
function emitSubagentStateUpdate(socket, runtime, scope) {
|
|
347990
|
+
function emitSubagentStateUpdate(socket, runtime, scope, routing = TO_SUBSCRIBERS) {
|
|
347732
347991
|
const message = {
|
|
347733
347992
|
type: "update_subagent_state",
|
|
347734
347993
|
subagents: buildSubagentSnapshot(runtime, scope)
|
|
347735
347994
|
};
|
|
347736
|
-
emitProtocolV2Message(socket, runtime, message, scope);
|
|
347995
|
+
emitProtocolV2Message(socket, runtime, message, scope, routing);
|
|
347737
347996
|
}
|
|
347738
347997
|
function emitSubagentStateIfOpen(runtime, scope) {
|
|
347739
347998
|
const listener = getListenerRuntime(runtime);
|
|
@@ -347842,7 +348101,7 @@ function emitStreamDelta(socket, runtime, delta2, scope, subagentId) {
|
|
|
347842
348101
|
delta: delta2,
|
|
347843
348102
|
...subagentId ? { subagent_id: subagentId } : {}
|
|
347844
348103
|
};
|
|
347845
|
-
emitProtocolV2Message(socket, runtime, message, scope);
|
|
348104
|
+
emitProtocolV2Message(socket, runtime, message, scope, TO_SUBSCRIBERS);
|
|
347846
348105
|
}
|
|
347847
348106
|
var GIT_CONTEXT_CACHE_TTL_MS = 15000, MAX_GIT_CONTEXT_CACHE_ENTRIES = 64, FROZEN_SUPPORTED_COMMANDS, gitContextCache, STREAM_CHANNEL_MESSAGE_TYPES, COALESCABLE_STATUS_MESSAGE_TYPES;
|
|
347848
348107
|
var init_protocol_outbound = __esm(async () => {
|
|
@@ -347856,9 +348115,10 @@ var init_protocol_outbound = __esm(async () => {
|
|
|
347856
348115
|
init_manager();
|
|
347857
348116
|
init_mode();
|
|
347858
348117
|
init_settings_manager();
|
|
347859
|
-
init_process_manager();
|
|
347860
348118
|
init_debug();
|
|
348119
|
+
init_background_process_snapshot();
|
|
347861
348120
|
init_channel_turn_session();
|
|
348121
|
+
init_connection();
|
|
347862
348122
|
init_constants3();
|
|
347863
348123
|
init_cwd();
|
|
347864
348124
|
init_device_status_cache();
|
|
@@ -347921,9 +348181,9 @@ async function switchConversationWorkingDirectory(params) {
|
|
|
347921
348181
|
reminderState.hasSentSessionContext = false;
|
|
347922
348182
|
reminderState.pendingSessionContextReason = "cwd_changed";
|
|
347923
348183
|
}
|
|
347924
|
-
|
|
347925
|
-
|
|
347926
|
-
emitDeviceStatusUpdate(
|
|
348184
|
+
if (params.emitStatus !== false) {
|
|
348185
|
+
const statusTransport = params.statusSocket ?? getOrCreateProcessTransport(runtime);
|
|
348186
|
+
emitDeviceStatusUpdate(statusTransport, params.statusRuntime ?? conversationRuntime ?? runtime, {
|
|
347927
348187
|
agent_id: agentId,
|
|
347928
348188
|
conversation_id: conversationId
|
|
347929
348189
|
});
|
|
@@ -347932,6 +348192,7 @@ async function switchConversationWorkingDirectory(params) {
|
|
|
347932
348192
|
var init_cwd_change = __esm(async () => {
|
|
347933
348193
|
init_runtime_context();
|
|
347934
348194
|
init_settings_manager();
|
|
348195
|
+
init_connection();
|
|
347935
348196
|
init_cwd();
|
|
347936
348197
|
init_runtime6();
|
|
347937
348198
|
await init_protocol_outbound();
|
|
@@ -349415,7 +349676,8 @@ async function startExecSession(args) {
|
|
|
349415
349676
|
startTime: new Date,
|
|
349416
349677
|
outputFile,
|
|
349417
349678
|
totalStdoutLines: 0,
|
|
349418
|
-
totalStderrLines: 0
|
|
349679
|
+
totalStderrLines: 0,
|
|
349680
|
+
runtimeScope: args.parentScope
|
|
349419
349681
|
});
|
|
349420
349682
|
if (session.status !== "running") {
|
|
349421
349683
|
scheduleBackgroundProcessCleanup(id2);
|
|
@@ -363635,7 +363897,8 @@ function spawnBackgroundSubagentTask(args) {
|
|
|
363635
363897
|
output: [],
|
|
363636
363898
|
startTime: new Date,
|
|
363637
363899
|
outputFile,
|
|
363638
|
-
abortController
|
|
363900
|
+
abortController,
|
|
363901
|
+
runtimeScope: resolvedParentScope
|
|
363639
363902
|
};
|
|
363640
363903
|
backgroundTasks.set(taskId, bgTask);
|
|
363641
363904
|
writeTaskTranscriptStart(outputFile, description, subagentType);
|
|
@@ -369549,10 +369812,8 @@ function filterToolRegistryByClientAllowlist(registry2, clientToolAllowlist) {
|
|
|
369549
369812
|
}
|
|
369550
369813
|
function filterExternalToolsByRuntimeContext(externalTools, runtimeContext) {
|
|
369551
369814
|
return new Map(Array.from(externalTools.entries()).filter(([, tool2]) => {
|
|
369552
|
-
|
|
369553
|
-
|
|
369554
|
-
}
|
|
369555
|
-
return tool2.runtime.agentId === runtimeContext.agentId && tool2.runtime.conversationId === runtimeContext.conversationId;
|
|
369815
|
+
const matchesConnection = tool2.connectionId === undefined || tool2.connectionId === runtimeContext.connectionId;
|
|
369816
|
+
return matchesConnection && (!tool2.runtime || tool2.runtime.agentId === runtimeContext.agentId && tool2.runtime.conversationId === runtimeContext.conversationId);
|
|
369556
369817
|
}));
|
|
369557
369818
|
}
|
|
369558
369819
|
function filterExternalToolsByScopeIds(externalTools, externalToolScopeIds) {
|
|
@@ -370747,6 +371008,9 @@ async function executeToolInner(name, args, options3) {
|
|
|
370747
371008
|
if (Object.keys(secretEnv).length > 0) {
|
|
370748
371009
|
enhancedArgs = { ...enhancedArgs, secretEnv };
|
|
370749
371010
|
}
|
|
371011
|
+
if (options3?.parentScope) {
|
|
371012
|
+
enhancedArgs = { ...enhancedArgs, parentScope: options3.parentScope };
|
|
371013
|
+
}
|
|
370750
371014
|
}
|
|
370751
371015
|
if (internalName === "Task") {
|
|
370752
371016
|
if (options3?.toolCallId) {
|
|
@@ -371460,6 +371724,7 @@ function parseInheritedChannelContextEnv() {
|
|
|
371460
371724
|
}
|
|
371461
371725
|
async function prepareToolExecutionContextForScope(params) {
|
|
371462
371726
|
const {
|
|
371727
|
+
connectionId,
|
|
371463
371728
|
agentId,
|
|
371464
371729
|
conversationId,
|
|
371465
371730
|
overrideModel,
|
|
@@ -371522,6 +371787,7 @@ async function prepareToolExecutionContextForScope(params) {
|
|
|
371522
371787
|
modAdapters,
|
|
371523
371788
|
agent: agent2,
|
|
371524
371789
|
runtimeContext: {
|
|
371790
|
+
connectionId,
|
|
371525
371791
|
agentId,
|
|
371526
371792
|
agentName: agent2.name ?? null,
|
|
371527
371793
|
conversationId: scopedConversationId,
|
|
@@ -435895,6 +436161,7 @@ function consumeQueuedTurn(runtime) {
|
|
|
435895
436161
|
let hasTaskNotification = false;
|
|
435896
436162
|
let hasCronPrompt = false;
|
|
435897
436163
|
let hasModContinue = false;
|
|
436164
|
+
let batchConnectionId;
|
|
435898
436165
|
let batchImageFailureMode = null;
|
|
435899
436166
|
const isNoCoalesce = (candidate) => candidate.kind === "message" && candidate.noCoalesce === true;
|
|
435900
436167
|
for (const item of queuedItems) {
|
|
@@ -435905,6 +436172,11 @@ function consumeQueuedTurn(runtime) {
|
|
|
435905
436172
|
break;
|
|
435906
436173
|
}
|
|
435907
436174
|
if (item.kind === "message") {
|
|
436175
|
+
const itemConnectionId = runtime.queuedMessagesByItemId.get(item.id)?.connectionId;
|
|
436176
|
+
if (batchConnectionId !== undefined && itemConnectionId !== undefined && itemConnectionId !== batchConnectionId) {
|
|
436177
|
+
break;
|
|
436178
|
+
}
|
|
436179
|
+
batchConnectionId ??= itemConnectionId;
|
|
435908
436180
|
const itemImageFailureMode = getInboundImageFailureMode(runtime.queuedMessagesByItemId.get(item.id));
|
|
435909
436181
|
if (batchImageFailureMode !== null && itemImageFailureMode !== batchImageFailureMode) {
|
|
435910
436182
|
break;
|
|
@@ -436087,14 +436359,6 @@ function ensureConversationQueueRuntime(listener, runtime) {
|
|
|
436087
436359
|
function getOrCreateScopedRuntime(listener, agentId, conversationId) {
|
|
436088
436360
|
return ensureConversationQueueRuntime(listener, getOrCreateConversationRuntime(listener, agentId, conversationId));
|
|
436089
436361
|
}
|
|
436090
|
-
function findFallbackRuntime(listener) {
|
|
436091
|
-
for (const cr of listener.conversationRuntimes.values()) {
|
|
436092
|
-
if (cr.queueRuntime) {
|
|
436093
|
-
return cr;
|
|
436094
|
-
}
|
|
436095
|
-
}
|
|
436096
|
-
return null;
|
|
436097
|
-
}
|
|
436098
436362
|
var init_conversation_runtime = __esm(async () => {
|
|
436099
436363
|
init_queue_runtime();
|
|
436100
436364
|
init_runtime6();
|
|
@@ -436236,21 +436500,20 @@ async function resolveCronFireConversationId(task2) {
|
|
|
436236
436500
|
return task2.conversation_id === "default" ? undefined : task2.conversation_id;
|
|
436237
436501
|
}
|
|
436238
436502
|
function emitCronsUpdated(socket, task2, conversationId) {
|
|
436239
|
-
|
|
436503
|
+
const listener = getActiveRuntime();
|
|
436504
|
+
if (!listener)
|
|
436240
436505
|
return;
|
|
436241
|
-
|
|
436506
|
+
const runtimeScope = {
|
|
436507
|
+
agent_id: task2.agent_id,
|
|
436508
|
+
conversation_id: conversationId ?? task2.conversation_id ?? "default"
|
|
436509
|
+
};
|
|
436242
436510
|
const payload = {
|
|
436243
436511
|
type: "crons_updated",
|
|
436244
436512
|
timestamp: Date.now(),
|
|
436245
436513
|
agent_id: task2.agent_id,
|
|
436246
|
-
conversation_id:
|
|
436514
|
+
conversation_id: runtimeScope.conversation_id
|
|
436247
436515
|
};
|
|
436248
|
-
|
|
436249
|
-
socket.send(JSON.stringify(payload));
|
|
436250
|
-
safeEmitWsEvent("send", "protocol", payload);
|
|
436251
|
-
} catch (err) {
|
|
436252
|
-
console.error(`[Cron] Error sending crons_updated for task ${task2.id}:`, err instanceof Error ? err.message : err);
|
|
436253
|
-
}
|
|
436516
|
+
emitProtocolV2Message(socket, listener, payload, runtimeScope, TO_SUBSCRIBERS);
|
|
436254
436517
|
}
|
|
436255
436518
|
function refreshTaskCache(state) {
|
|
436256
436519
|
const mtime = getCronFileMtime();
|
|
@@ -436631,13 +436894,14 @@ function stopScheduler() {
|
|
|
436631
436894
|
var schedulerState = null, listenerFireContext = null, TICK_INTERVAL_MS = 60000, GC_INTERVAL_MS, LEASE_RETRY_MS = 30000, MAX_LEASE_RETRIES = 3, NEW_CONVERSATION_TARGET = "new";
|
|
436632
436895
|
var init_scheduler = __esm(async () => {
|
|
436633
436896
|
init_backend2();
|
|
436897
|
+
init_connection();
|
|
436634
436898
|
init_runtime6();
|
|
436635
|
-
init_transport();
|
|
436636
436899
|
init_cron_file();
|
|
436637
436900
|
init_parse_interval();
|
|
436638
436901
|
init_run_log();
|
|
436639
436902
|
await __promiseAll([
|
|
436640
436903
|
init_conversation_runtime(),
|
|
436904
|
+
init_protocol_outbound(),
|
|
436641
436905
|
init_queue()
|
|
436642
436906
|
]);
|
|
436643
436907
|
GC_INTERVAL_MS = 60 * 60000;
|
|
@@ -445600,6 +445864,34 @@ var init_turn_status = __esm(async () => {
|
|
|
445600
445864
|
});
|
|
445601
445865
|
|
|
445602
445866
|
// src/websocket/listener/approval.ts
|
|
445867
|
+
function pendingApprovalEntries(runtime) {
|
|
445868
|
+
return [...new Set(runtime.pendingApprovalResolvers.values())];
|
|
445869
|
+
}
|
|
445870
|
+
function removePendingApproval(runtime, pending) {
|
|
445871
|
+
for (const [requestKey, candidate] of runtime.pendingApprovalResolvers) {
|
|
445872
|
+
if (candidate !== pending)
|
|
445873
|
+
continue;
|
|
445874
|
+
runtime.pendingApprovalResolvers.delete(requestKey);
|
|
445875
|
+
}
|
|
445876
|
+
pending.connectionIds.clear();
|
|
445877
|
+
}
|
|
445878
|
+
function addPendingApprovalConnection(runtime, pending, connectionId) {
|
|
445879
|
+
const unownedKey = createConnectionRequestKey(UNOWNED_APPROVAL_CONNECTION_ID, pending.requestId);
|
|
445880
|
+
runtime.pendingApprovalResolvers.delete(unownedKey);
|
|
445881
|
+
const requestKey = createConnectionRequestKey(connectionId, pending.requestId);
|
|
445882
|
+
pending.connectionIds.add(connectionId);
|
|
445883
|
+
runtime.pendingApprovalResolvers.set(requestKey, pending);
|
|
445884
|
+
}
|
|
445885
|
+
function keepPendingApprovalUnowned(runtime, pending) {
|
|
445886
|
+
const requestKey = createConnectionRequestKey(UNOWNED_APPROVAL_CONNECTION_ID, pending.requestId);
|
|
445887
|
+
runtime.pendingApprovalResolvers.set(requestKey, pending);
|
|
445888
|
+
}
|
|
445889
|
+
function hasPendingApprovalRequestId(runtime, requestId) {
|
|
445890
|
+
return pendingApprovalEntries(runtime).some((pending) => pending.requestId === requestId);
|
|
445891
|
+
}
|
|
445892
|
+
function getPendingApprovalRequestIds(runtime) {
|
|
445893
|
+
return new Set(pendingApprovalEntries(runtime).map((pending) => pending.requestId));
|
|
445894
|
+
}
|
|
445603
445895
|
function rememberPendingApprovalBatchIds(runtime, pendingApprovals, batchId) {
|
|
445604
445896
|
for (const approval of pendingApprovals) {
|
|
445605
445897
|
if (approval.toolCallId) {
|
|
@@ -445685,17 +445977,20 @@ function validateApprovalResultIds(decisions, approvals) {
|
|
|
445685
445977
|
}, null, 2));
|
|
445686
445978
|
throw new Error("Approval ID mismatch - refusing to send mismatched IDs");
|
|
445687
445979
|
}
|
|
445688
|
-
function resolvePendingApprovalResolver(runtime, response) {
|
|
445980
|
+
function resolvePendingApprovalResolver(runtime, response, connectionId) {
|
|
445689
445981
|
const requestId = response.request_id;
|
|
445690
445982
|
if (typeof requestId !== "string" || requestId.length === 0) {
|
|
445691
445983
|
return false;
|
|
445692
445984
|
}
|
|
445693
|
-
const
|
|
445985
|
+
const requestKey = connectionId ? createConnectionRequestKey(connectionId, requestId) : [...runtime.pendingApprovalResolvers.entries()].find(([, candidate]) => candidate.requestId === requestId)?.[0];
|
|
445986
|
+
if (!requestKey) {
|
|
445987
|
+
return false;
|
|
445988
|
+
}
|
|
445989
|
+
const pending = runtime.pendingApprovalResolvers.get(requestKey);
|
|
445694
445990
|
if (!pending) {
|
|
445695
445991
|
return false;
|
|
445696
445992
|
}
|
|
445697
|
-
runtime
|
|
445698
|
-
runtime.listener.approvalRuntimeKeyByRequestId.delete(requestId);
|
|
445993
|
+
removePendingApproval(runtime, pending);
|
|
445699
445994
|
if (runtime.pendingApprovalResolvers.size === 0 && !runtime.isProcessing) {
|
|
445700
445995
|
setCommandLoopStatus(runtime, "WAITING_ON_INPUT");
|
|
445701
445996
|
}
|
|
@@ -445712,15 +446007,10 @@ function resolvePendingApprovalResolver(runtime, response) {
|
|
|
445712
446007
|
return true;
|
|
445713
446008
|
}
|
|
445714
446009
|
function rejectPendingApprovalResolvers(runtime, reason) {
|
|
445715
|
-
for (const
|
|
446010
|
+
for (const pending of pendingApprovalEntries(runtime)) {
|
|
445716
446011
|
pending.reject(new Error(reason));
|
|
445717
446012
|
}
|
|
445718
446013
|
runtime.pendingApprovalResolvers.clear();
|
|
445719
|
-
for (const [requestId, runtimeKey] of runtime.listener.approvalRuntimeKeyByRequestId) {
|
|
445720
|
-
if (runtimeKey === runtime.key) {
|
|
445721
|
-
runtime.listener.approvalRuntimeKeyByRequestId.delete(requestId);
|
|
445722
|
-
}
|
|
445723
|
-
}
|
|
445724
446014
|
if (!runtime.isProcessing && !runtime.cancelRequested) {
|
|
445725
446015
|
setCommandLoopStatus(runtime, "WAITING_ON_INPUT");
|
|
445726
446016
|
}
|
|
@@ -445734,8 +446024,49 @@ function rejectPendingApprovalResolvers(runtime, reason) {
|
|
|
445734
446024
|
});
|
|
445735
446025
|
evictConversationRuntimeIfIdle(runtime);
|
|
445736
446026
|
}
|
|
446027
|
+
function rejectPendingApprovalResolversForConnection(runtime, connectionId, _reason) {
|
|
446028
|
+
for (const pending of pendingApprovalEntries(runtime)) {
|
|
446029
|
+
if (!pending.connectionIds.delete(connectionId)) {
|
|
446030
|
+
continue;
|
|
446031
|
+
}
|
|
446032
|
+
const requestKey = createConnectionRequestKey(connectionId, pending.requestId);
|
|
446033
|
+
runtime.pendingApprovalResolvers.delete(requestKey);
|
|
446034
|
+
if (pending.connectionIds.size === 0) {
|
|
446035
|
+
keepPendingApprovalUnowned(runtime, pending);
|
|
446036
|
+
}
|
|
446037
|
+
}
|
|
446038
|
+
evictConversationRuntimeIfIdle(runtime);
|
|
446039
|
+
}
|
|
446040
|
+
function replayPendingApprovalRequestsToConnection(runtime, connectionId) {
|
|
446041
|
+
const connection = runtime.listener.connections.get(connectionId);
|
|
446042
|
+
if (!connection?.initialized || !isListenerTransportOpen(connection.writer)) {
|
|
446043
|
+
return;
|
|
446044
|
+
}
|
|
446045
|
+
for (const pending of pendingApprovalEntries(runtime)) {
|
|
446046
|
+
addPendingApprovalConnection(runtime, pending, connectionId);
|
|
446047
|
+
if (!pending.controlRequest)
|
|
446048
|
+
continue;
|
|
446049
|
+
emitProtocolV2Message(connection.writer, runtime, pending.controlRequest, {
|
|
446050
|
+
agent_id: runtime.agentId,
|
|
446051
|
+
conversation_id: runtime.conversationId
|
|
446052
|
+
}, toListenerConnection(connectionId));
|
|
446053
|
+
}
|
|
446054
|
+
}
|
|
445737
446055
|
function requestApprovalOverWS(runtime, socket, turnLease, requestId, controlRequest) {
|
|
445738
|
-
|
|
446056
|
+
const scope = {
|
|
446057
|
+
agent_id: runtime.agentId,
|
|
446058
|
+
conversation_id: runtime.conversationId
|
|
446059
|
+
};
|
|
446060
|
+
const subscribers = getSubscribedListenerConnections(runtime.listener, scope);
|
|
446061
|
+
const originConnection = findListenerConnectionByTransport(runtime.listener, socket);
|
|
446062
|
+
const connectionIds = new Set(subscribers.map((subscriber) => subscriber.id));
|
|
446063
|
+
if (connectionIds.size === 0 && originConnection?.initialized && isListenerTransportOpen(originConnection.writer)) {
|
|
446064
|
+
connectionIds.add(originConnection.id);
|
|
446065
|
+
}
|
|
446066
|
+
if (connectionIds.size === 0 && runtime.listener.connections.size === 0 && isListenerTransportOpen(socket)) {
|
|
446067
|
+
connectionIds.add(runtime.listener.connectionId ?? "legacy");
|
|
446068
|
+
}
|
|
446069
|
+
if (connectionIds.size === 0 && !isListenerTransportOpen(socket) && runtime.listener.connections.size === 0) {
|
|
445739
446070
|
return Promise.reject(new Error("WebSocket not open"));
|
|
445740
446071
|
}
|
|
445741
446072
|
const abortSignal = turnLease.signal;
|
|
@@ -445745,51 +446076,53 @@ function requestApprovalOverWS(runtime, socket, turnLease, requestId, controlReq
|
|
|
445745
446076
|
}
|
|
445746
446077
|
return new Promise((resolve31, reject) => {
|
|
445747
446078
|
let settled = false;
|
|
446079
|
+
const pending = {
|
|
446080
|
+
requestId,
|
|
446081
|
+
connectionIds,
|
|
446082
|
+
resolve: (response) => {
|
|
446083
|
+
if (settled) {
|
|
446084
|
+
return;
|
|
446085
|
+
}
|
|
446086
|
+
settled = true;
|
|
446087
|
+
cleanupAbortListener();
|
|
446088
|
+
resolve31(response);
|
|
446089
|
+
},
|
|
446090
|
+
reject: (error54) => {
|
|
446091
|
+
if (settled) {
|
|
446092
|
+
return;
|
|
446093
|
+
}
|
|
446094
|
+
settled = true;
|
|
446095
|
+
cleanupAbortListener();
|
|
446096
|
+
reject(error54);
|
|
446097
|
+
},
|
|
446098
|
+
controlRequest
|
|
446099
|
+
};
|
|
445748
446100
|
const cleanupAbortListener = () => {
|
|
445749
446101
|
abortSignal.removeEventListener("abort", handleAbort);
|
|
445750
446102
|
};
|
|
445751
|
-
const wrappedResolve = (response) => {
|
|
445752
|
-
if (settled) {
|
|
445753
|
-
return;
|
|
445754
|
-
}
|
|
445755
|
-
settled = true;
|
|
445756
|
-
cleanupAbortListener();
|
|
445757
|
-
resolve31(response);
|
|
445758
|
-
};
|
|
445759
|
-
const wrappedReject = (error54) => {
|
|
445760
|
-
if (settled) {
|
|
445761
|
-
return;
|
|
445762
|
-
}
|
|
445763
|
-
settled = true;
|
|
445764
|
-
cleanupAbortListener();
|
|
445765
|
-
reject(error54);
|
|
445766
|
-
};
|
|
445767
446103
|
const handleAbort = () => {
|
|
445768
|
-
runtime
|
|
445769
|
-
|
|
445770
|
-
wrappedReject(new Error("Cancelled by user"));
|
|
446104
|
+
removePendingApproval(runtime, pending);
|
|
446105
|
+
pending.reject(new Error("Cancelled by user"));
|
|
445771
446106
|
};
|
|
445772
446107
|
abortSignal.addEventListener("abort", handleAbort, { once: true });
|
|
445773
446108
|
if (isInterrupted()) {
|
|
445774
446109
|
handleAbort();
|
|
445775
446110
|
return;
|
|
445776
446111
|
}
|
|
445777
|
-
|
|
445778
|
-
|
|
445779
|
-
|
|
445780
|
-
|
|
445781
|
-
|
|
445782
|
-
|
|
446112
|
+
if (connectionIds.size === 0) {
|
|
446113
|
+
keepPendingApprovalUnowned(runtime, pending);
|
|
446114
|
+
} else {
|
|
446115
|
+
for (const connectionId of connectionIds) {
|
|
446116
|
+
addPendingApprovalConnection(runtime, pending, connectionId);
|
|
446117
|
+
}
|
|
446118
|
+
}
|
|
445783
446119
|
if (isInterrupted()) {
|
|
445784
446120
|
handleAbort();
|
|
445785
446121
|
return;
|
|
445786
446122
|
}
|
|
445787
446123
|
runtime.turnLifecycle.recordStopReason(turnLease, "requires_approval");
|
|
445788
446124
|
setTurnLoopStatus(runtime, turnLease, "WAITING_ON_APPROVAL");
|
|
445789
|
-
emitProtocolV2Message(socket, runtime, controlRequest,
|
|
445790
|
-
agent_id: runtime.agentId,
|
|
445791
|
-
conversation_id: runtime.conversationId
|
|
445792
|
-
});
|
|
446125
|
+
emitProtocolV2Message(socket, runtime, controlRequest, scope, TO_SUBSCRIBERS);
|
|
445793
446126
|
emitLoopStatusIfOpen(runtime.listener, {
|
|
445794
446127
|
agent_id: runtime.agentId,
|
|
445795
446128
|
conversation_id: runtime.conversationId
|
|
@@ -445800,7 +446133,9 @@ function requestApprovalOverWS(runtime, socket, turnLease, requestId, controlReq
|
|
|
445800
446133
|
});
|
|
445801
446134
|
});
|
|
445802
446135
|
}
|
|
446136
|
+
var UNOWNED_APPROVAL_CONNECTION_ID = "__unowned_approval__";
|
|
445803
446137
|
var init_approval = __esm(async () => {
|
|
446138
|
+
init_connection();
|
|
445804
446139
|
init_runtime6();
|
|
445805
446140
|
init_transport();
|
|
445806
446141
|
await __promiseAll([
|
|
@@ -447017,6 +447352,93 @@ var init_agents_conversations = __esm(async () => {
|
|
|
447017
447352
|
await init_protocol_inbound();
|
|
447018
447353
|
});
|
|
447019
447354
|
|
|
447355
|
+
// src/websocket/listener/commands/channel-registry-events.ts
|
|
447356
|
+
function broadcastChannelRegistryUpdate(runtime, origin, message) {
|
|
447357
|
+
const payload = JSON.stringify(message);
|
|
447358
|
+
const targets = resolveListenerConnectionTargets({
|
|
447359
|
+
runtime,
|
|
447360
|
+
origin,
|
|
447361
|
+
scope: {},
|
|
447362
|
+
routing: BROADCAST,
|
|
447363
|
+
streamMessage: false
|
|
447364
|
+
});
|
|
447365
|
+
for (const target2 of targets) {
|
|
447366
|
+
if (isListenerTransportOpen(target2.transport)) {
|
|
447367
|
+
try {
|
|
447368
|
+
target2.transport.send(payload);
|
|
447369
|
+
} catch (error54) {
|
|
447370
|
+
trackBoundaryError({
|
|
447371
|
+
context: "listener_channel_registry_broadcast",
|
|
447372
|
+
errorType: "listener_channel_registry_send_failed",
|
|
447373
|
+
error: error54
|
|
447374
|
+
});
|
|
447375
|
+
}
|
|
447376
|
+
}
|
|
447377
|
+
}
|
|
447378
|
+
}
|
|
447379
|
+
function handleChannelRegistryEvent(event2, transport, runtime) {
|
|
447380
|
+
const broadcast = (message) => broadcastChannelRegistryUpdate(runtime, transport, message);
|
|
447381
|
+
if (event2.type === "pairings_updated") {
|
|
447382
|
+
const channelId = event2.channelId;
|
|
447383
|
+
broadcast({
|
|
447384
|
+
type: "channel_pairings_updated",
|
|
447385
|
+
timestamp: Date.now(),
|
|
447386
|
+
channel_id: channelId
|
|
447387
|
+
});
|
|
447388
|
+
broadcast({
|
|
447389
|
+
type: "channels_updated",
|
|
447390
|
+
timestamp: Date.now(),
|
|
447391
|
+
channel_id: channelId
|
|
447392
|
+
});
|
|
447393
|
+
return;
|
|
447394
|
+
}
|
|
447395
|
+
if (event2.type === "targets_updated") {
|
|
447396
|
+
const channelId = event2.channelId;
|
|
447397
|
+
broadcast({
|
|
447398
|
+
type: "channel_targets_updated",
|
|
447399
|
+
timestamp: Date.now(),
|
|
447400
|
+
channel_id: channelId
|
|
447401
|
+
});
|
|
447402
|
+
broadcast({
|
|
447403
|
+
type: "channels_updated",
|
|
447404
|
+
timestamp: Date.now(),
|
|
447405
|
+
channel_id: channelId
|
|
447406
|
+
});
|
|
447407
|
+
return;
|
|
447408
|
+
}
|
|
447409
|
+
if (event2.type === "channel_account_state_updated") {
|
|
447410
|
+
const channelId = event2.channelId;
|
|
447411
|
+
broadcast({
|
|
447412
|
+
type: "channel_accounts_updated",
|
|
447413
|
+
timestamp: Date.now(),
|
|
447414
|
+
channel_id: channelId,
|
|
447415
|
+
account_id: event2.accountId
|
|
447416
|
+
});
|
|
447417
|
+
broadcast({
|
|
447418
|
+
type: "channels_updated",
|
|
447419
|
+
timestamp: Date.now(),
|
|
447420
|
+
channel_id: channelId
|
|
447421
|
+
});
|
|
447422
|
+
return;
|
|
447423
|
+
}
|
|
447424
|
+
const permissionModeState = getOrCreateConversationPermissionModeStateRef(runtime, event2.agentId, event2.conversationId);
|
|
447425
|
+
permissionModeState.mode = event2.defaultPermissionMode;
|
|
447426
|
+
persistPermissionModeMapForRuntime(runtime);
|
|
447427
|
+
const seededWorkingDirectory = seedConversationWorkingDirectory(runtime, event2.agentId, event2.conversationId, runtime.bootWorkingDirectory);
|
|
447428
|
+
if (seededWorkingDirectory) {
|
|
447429
|
+
emitDeviceStatusUpdate(transport, getOrCreateConversationRuntime(runtime, event2.agentId, event2.conversationId));
|
|
447430
|
+
}
|
|
447431
|
+
}
|
|
447432
|
+
var init_channel_registry_events = __esm(async () => {
|
|
447433
|
+
init_error_reporting();
|
|
447434
|
+
init_connection();
|
|
447435
|
+
init_cwd();
|
|
447436
|
+
init_permission_mode();
|
|
447437
|
+
init_runtime6();
|
|
447438
|
+
init_transport();
|
|
447439
|
+
await init_protocol_outbound();
|
|
447440
|
+
});
|
|
447441
|
+
|
|
447020
447442
|
// src/channels/custom/scaffolding.ts
|
|
447021
447443
|
import { existsSync as existsSync48, mkdirSync as mkdirSync34, rmSync as rmSync11, writeFileSync as writeFileSync24 } from "node:fs";
|
|
447022
447444
|
function removeUserPlugin(channelId) {
|
|
@@ -447044,7 +447466,6 @@ var init_scaffolding = __esm(() => {
|
|
|
447044
447466
|
});
|
|
447045
447467
|
|
|
447046
447468
|
// src/websocket/listener/commands/channels.ts
|
|
447047
|
-
import WebSocket4 from "ws";
|
|
447048
447469
|
function setChannelsServiceLoaderOverride(loader) {
|
|
447049
447470
|
channelsServiceLoaderOverride = loader;
|
|
447050
447471
|
}
|
|
@@ -447762,52 +448183,13 @@ async function handleChannelsProtocolCommand(parsed, socket, runtime, opts, proc
|
|
|
447762
448183
|
}
|
|
447763
448184
|
return true;
|
|
447764
448185
|
}
|
|
447765
|
-
function handleChannelRegistryEvent(event2, socket, runtime, safeSocketSend) {
|
|
447766
|
-
if (event2.type === "pairings_updated") {
|
|
447767
|
-
if (socket instanceof WebSocket4) {
|
|
447768
|
-
emitChannelPairingsUpdated(socket, safeSocketSend, event2.channelId);
|
|
447769
|
-
emitChannelsUpdated(socket, safeSocketSend, event2.channelId);
|
|
447770
|
-
}
|
|
447771
|
-
return;
|
|
447772
|
-
}
|
|
447773
|
-
if (event2.type === "targets_updated") {
|
|
447774
|
-
if (socket instanceof WebSocket4) {
|
|
447775
|
-
emitChannelTargetsUpdated(socket, safeSocketSend, event2.channelId);
|
|
447776
|
-
emitChannelsUpdated(socket, safeSocketSend, event2.channelId);
|
|
447777
|
-
}
|
|
447778
|
-
return;
|
|
447779
|
-
}
|
|
447780
|
-
if (event2.type === "channel_account_state_updated") {
|
|
447781
|
-
if (socket instanceof WebSocket4) {
|
|
447782
|
-
emitChannelAccountsUpdated(socket, safeSocketSend, {
|
|
447783
|
-
channelId: event2.channelId,
|
|
447784
|
-
accountId: event2.accountId
|
|
447785
|
-
});
|
|
447786
|
-
emitChannelsUpdated(socket, safeSocketSend, event2.channelId);
|
|
447787
|
-
}
|
|
447788
|
-
return;
|
|
447789
|
-
}
|
|
447790
|
-
const permissionModeState = getOrCreateConversationPermissionModeStateRef(runtime, event2.agentId, event2.conversationId);
|
|
447791
|
-
permissionModeState.mode = event2.defaultPermissionMode;
|
|
447792
|
-
persistPermissionModeMapForRuntime(runtime);
|
|
447793
|
-
const seededWorkingDirectory = seedConversationWorkingDirectory(runtime, event2.agentId, event2.conversationId, runtime.bootWorkingDirectory);
|
|
447794
|
-
if (seededWorkingDirectory) {
|
|
447795
|
-
emitDeviceStatusUpdate(socket, getOrCreateConversationRuntime(runtime, event2.agentId, event2.conversationId));
|
|
447796
|
-
}
|
|
447797
|
-
}
|
|
447798
448186
|
var channelsServiceLoaderOverride = null;
|
|
447799
448187
|
var init_channels2 = __esm(async () => {
|
|
447800
448188
|
init_account_config7();
|
|
447801
448189
|
init_scaffolding();
|
|
447802
448190
|
init_plugin_registry();
|
|
447803
448191
|
init_types6();
|
|
447804
|
-
|
|
447805
|
-
init_permission_mode();
|
|
447806
|
-
init_runtime6();
|
|
447807
|
-
await __promiseAll([
|
|
447808
|
-
init_protocol_inbound(),
|
|
447809
|
-
init_protocol_outbound()
|
|
447810
|
-
]);
|
|
448192
|
+
await init_protocol_inbound();
|
|
447811
448193
|
});
|
|
447812
448194
|
|
|
447813
448195
|
// src/websocket/listener/commands/cron.ts
|
|
@@ -449626,11 +450008,7 @@ var init_model_toolset = __esm(async () => {
|
|
|
449626
450008
|
});
|
|
449627
450009
|
|
|
449628
450010
|
// src/websocket/listener/external-tools.ts
|
|
449629
|
-
function isSocketOpen(socket) {
|
|
449630
|
-
return socket?.readyState === WEBSOCKET_OPEN;
|
|
449631
|
-
}
|
|
449632
450011
|
function getPendingExternalToolCalls(runtime) {
|
|
449633
|
-
runtime.pendingExternalToolCalls ??= new Map;
|
|
449634
450012
|
return runtime.pendingExternalToolCalls;
|
|
449635
450013
|
}
|
|
449636
450014
|
function getRegisteredTools(runtime) {
|
|
@@ -449641,25 +450019,35 @@ function getRegisteredTools(runtime) {
|
|
|
449641
450019
|
}
|
|
449642
450020
|
return registeredTools;
|
|
449643
450021
|
}
|
|
450022
|
+
function getConnectionIdsByRegistrationKey(runtime) {
|
|
450023
|
+
let controllers = connectionIdByRegistrationKey.get(runtime);
|
|
450024
|
+
if (!controllers) {
|
|
450025
|
+
controllers = new Map;
|
|
450026
|
+
connectionIdByRegistrationKey.set(runtime, controllers);
|
|
450027
|
+
}
|
|
450028
|
+
return controllers;
|
|
450029
|
+
}
|
|
449644
450030
|
function getRuntimeKey(runtime) {
|
|
449645
450031
|
return `${runtime.agent_id}:${runtime.conversation_id}`;
|
|
449646
450032
|
}
|
|
449647
|
-
function getToolRegistrationKey(runtime, scopeId, toolName) {
|
|
450033
|
+
function getToolRegistrationKey(connectionId, runtime, scopeId, toolName) {
|
|
449648
450034
|
return JSON.stringify([
|
|
449649
450035
|
"runtime",
|
|
450036
|
+
connectionId,
|
|
449650
450037
|
runtime.agent_id,
|
|
449651
450038
|
runtime.conversation_id,
|
|
449652
450039
|
scopeId ?? null,
|
|
449653
450040
|
toolName
|
|
449654
450041
|
]);
|
|
449655
450042
|
}
|
|
449656
|
-
function toExternalToolDefinition(tool2, runtime, scopeId) {
|
|
450043
|
+
function toExternalToolDefinition(tool2, connectionId, runtime, scopeId) {
|
|
449657
450044
|
return {
|
|
449658
450045
|
name: tool2.name,
|
|
450046
|
+
connectionId,
|
|
449659
450047
|
...tool2.label !== undefined ? { label: tool2.label } : {},
|
|
449660
450048
|
description: tool2.description,
|
|
449661
450049
|
parameters: tool2.parameters,
|
|
449662
|
-
registrationKey: getToolRegistrationKey(runtime, scopeId, tool2.name),
|
|
450050
|
+
registrationKey: getToolRegistrationKey(connectionId, runtime, scopeId, tool2.name),
|
|
449663
450051
|
...scopeId !== undefined ? { scopeId } : {},
|
|
449664
450052
|
runtime: {
|
|
449665
450053
|
agentId: runtime.agent_id,
|
|
@@ -449667,16 +450055,17 @@ function toExternalToolDefinition(tool2, runtime, scopeId) {
|
|
|
449667
450055
|
}
|
|
449668
450056
|
};
|
|
449669
450057
|
}
|
|
449670
|
-
function sendJson(socket, payload) {
|
|
449671
|
-
socket.send(JSON.stringify(payload));
|
|
449672
|
-
}
|
|
449673
450058
|
function installExternalToolBridge(runtime) {
|
|
449674
450059
|
setExternalToolExecutor(async (toolCallId, toolName, input, context3) => {
|
|
449675
|
-
const
|
|
449676
|
-
|
|
450060
|
+
const registrationKey = context3?.tool.registrationKey;
|
|
450061
|
+
const connectionId = registrationKey ? getConnectionIdsByRegistrationKey(runtime).get(registrationKey) : undefined;
|
|
450062
|
+
const connection = connectionId ? runtime.connections.get(connectionId) : undefined;
|
|
450063
|
+
if (!connection || !isListenerTransportOpen(connection.writer) || runtime.intentionallyClosed) {
|
|
449677
450064
|
throw new Error("External tool controller is not connected");
|
|
449678
450065
|
}
|
|
450066
|
+
const writer = connection.writer;
|
|
449679
450067
|
const requestId = `external-tool-${crypto.randomUUID()}`;
|
|
450068
|
+
const requestKey = createConnectionRequestKey(connection.id, requestId);
|
|
449680
450069
|
const toolRuntime = context3?.tool.runtime;
|
|
449681
450070
|
const requestRuntime = toolRuntime?.agentId && toolRuntime.conversationId ? {
|
|
449682
450071
|
agent_id: toolRuntime.agentId,
|
|
@@ -449693,10 +450082,11 @@ function installExternalToolBridge(runtime) {
|
|
|
449693
450082
|
};
|
|
449694
450083
|
const result = await new Promise((resolve31, reject) => {
|
|
449695
450084
|
const timeout = setTimeout(() => {
|
|
449696
|
-
getPendingExternalToolCalls(runtime).delete(
|
|
450085
|
+
getPendingExternalToolCalls(runtime).delete(requestKey);
|
|
449697
450086
|
reject(new Error(`External tool call timed out: ${toolName}`));
|
|
449698
450087
|
}, EXTERNAL_TOOL_CALL_TIMEOUT_MS);
|
|
449699
|
-
getPendingExternalToolCalls(runtime).set(
|
|
450088
|
+
getPendingExternalToolCalls(runtime).set(requestKey, {
|
|
450089
|
+
connectionId: connection.id,
|
|
449700
450090
|
resolve: (response) => {
|
|
449701
450091
|
resolve31({
|
|
449702
450092
|
content: [...response.content],
|
|
@@ -449707,36 +450097,49 @@ function installExternalToolBridge(runtime) {
|
|
|
449707
450097
|
timeout
|
|
449708
450098
|
});
|
|
449709
450099
|
try {
|
|
449710
|
-
|
|
450100
|
+
writer.send(JSON.stringify(request));
|
|
449711
450101
|
} catch (error54) {
|
|
449712
450102
|
clearTimeout(timeout);
|
|
449713
|
-
getPendingExternalToolCalls(runtime).delete(
|
|
450103
|
+
getPendingExternalToolCalls(runtime).delete(requestKey);
|
|
449714
450104
|
reject(error54 instanceof Error ? error54 : new Error(String(error54)));
|
|
449715
450105
|
}
|
|
449716
450106
|
});
|
|
449717
450107
|
return result;
|
|
449718
450108
|
});
|
|
449719
450109
|
}
|
|
449720
|
-
function registerRuntimeExternalTools(runtime, runtimeScope, groups
|
|
450110
|
+
function registerRuntimeExternalTools(runtime, connectionId, runtimeScope, groups) {
|
|
450111
|
+
const resolvedGroups = groups ?? [];
|
|
449721
450112
|
const registeredTools = getRegisteredTools(runtime);
|
|
449722
|
-
const runtimeKey = getRuntimeKey(runtimeScope);
|
|
450113
|
+
const runtimeKey = createConnectionRequestKey(connectionId, getRuntimeKey(runtimeScope));
|
|
449723
450114
|
const previousTools = registeredTools.get(runtimeKey) ?? [];
|
|
449724
450115
|
unregisterExternalTools(previousTools);
|
|
449725
|
-
const tools =
|
|
450116
|
+
const tools = resolvedGroups.flatMap((group) => group.tools.map((tool2) => toExternalToolDefinition(tool2, connectionId, runtimeScope, group.scope_id)));
|
|
450117
|
+
const controllers = getConnectionIdsByRegistrationKey(runtime);
|
|
450118
|
+
for (const tool2 of previousTools) {
|
|
450119
|
+
if (tool2.registrationKey) {
|
|
450120
|
+
controllers.delete(tool2.registrationKey);
|
|
450121
|
+
}
|
|
450122
|
+
}
|
|
449726
450123
|
if (tools.length > 0) {
|
|
449727
450124
|
registerExternalTools(tools);
|
|
450125
|
+
for (const tool2 of tools) {
|
|
450126
|
+
if (tool2.registrationKey) {
|
|
450127
|
+
controllers.set(tool2.registrationKey, connectionId);
|
|
450128
|
+
}
|
|
450129
|
+
}
|
|
449728
450130
|
registeredTools.set(runtimeKey, tools);
|
|
449729
450131
|
} else {
|
|
449730
450132
|
registeredTools.delete(runtimeKey);
|
|
449731
450133
|
}
|
|
449732
450134
|
}
|
|
449733
|
-
function handleExternalToolCallResponseCommand(runtime, command) {
|
|
449734
|
-
const
|
|
450135
|
+
function handleExternalToolCallResponseCommand(runtime, connectionId, command) {
|
|
450136
|
+
const requestKey = createConnectionRequestKey(connectionId, command.request_id);
|
|
450137
|
+
const pending = getPendingExternalToolCalls(runtime).get(requestKey);
|
|
449735
450138
|
if (!pending) {
|
|
449736
450139
|
return false;
|
|
449737
450140
|
}
|
|
449738
450141
|
clearTimeout(pending.timeout);
|
|
449739
|
-
getPendingExternalToolCalls(runtime).delete(
|
|
450142
|
+
getPendingExternalToolCalls(runtime).delete(requestKey);
|
|
449740
450143
|
if (command.error !== undefined) {
|
|
449741
450144
|
pending.reject(new Error(command.error));
|
|
449742
450145
|
return true;
|
|
@@ -449748,6 +450151,35 @@ function handleExternalToolCallResponseCommand(runtime, command) {
|
|
|
449748
450151
|
pending.resolve(command.result);
|
|
449749
450152
|
return true;
|
|
449750
450153
|
}
|
|
450154
|
+
function rejectPendingExternalToolCallsForConnection(runtime, connectionId, reason) {
|
|
450155
|
+
const pendingExternalToolCalls = getPendingExternalToolCalls(runtime);
|
|
450156
|
+
for (const [requestKey, pending] of pendingExternalToolCalls) {
|
|
450157
|
+
if (pending.connectionId !== connectionId) {
|
|
450158
|
+
continue;
|
|
450159
|
+
}
|
|
450160
|
+
clearTimeout(pending.timeout);
|
|
450161
|
+
pendingExternalToolCalls.delete(requestKey);
|
|
450162
|
+
pending.reject(new Error(reason));
|
|
450163
|
+
}
|
|
450164
|
+
const registeredTools = registeredToolsByRuntime.get(runtime);
|
|
450165
|
+
if (!registeredTools) {
|
|
450166
|
+
return;
|
|
450167
|
+
}
|
|
450168
|
+
const controllers = getConnectionIdsByRegistrationKey(runtime);
|
|
450169
|
+
for (const [registrationScope, tools] of registeredTools) {
|
|
450170
|
+
const ownedByConnection = tools.some((tool2) => tool2.registrationKey !== undefined && controllers.get(tool2.registrationKey) === connectionId);
|
|
450171
|
+
if (!ownedByConnection) {
|
|
450172
|
+
continue;
|
|
450173
|
+
}
|
|
450174
|
+
unregisterExternalTools(tools);
|
|
450175
|
+
registeredTools.delete(registrationScope);
|
|
450176
|
+
for (const tool2 of tools) {
|
|
450177
|
+
if (tool2.registrationKey) {
|
|
450178
|
+
controllers.delete(tool2.registrationKey);
|
|
450179
|
+
}
|
|
450180
|
+
}
|
|
450181
|
+
}
|
|
450182
|
+
}
|
|
449751
450183
|
function rejectPendingExternalToolCalls(runtime, reason) {
|
|
449752
450184
|
const pendingExternalToolCalls = getPendingExternalToolCalls(runtime);
|
|
449753
450185
|
for (const [requestId, pending] of pendingExternalToolCalls) {
|
|
@@ -449762,12 +450194,16 @@ function rejectPendingExternalToolCalls(runtime, reason) {
|
|
|
449762
450194
|
}
|
|
449763
450195
|
registeredToolsByRuntime.delete(runtime);
|
|
449764
450196
|
}
|
|
450197
|
+
connectionIdByRegistrationKey.delete(runtime);
|
|
449765
450198
|
}
|
|
449766
|
-
var EXTERNAL_TOOL_CALL_TIMEOUT_MS,
|
|
450199
|
+
var EXTERNAL_TOOL_CALL_TIMEOUT_MS, registeredToolsByRuntime, connectionIdByRegistrationKey;
|
|
449767
450200
|
var init_external_tools = __esm(async () => {
|
|
450201
|
+
init_connection();
|
|
450202
|
+
init_transport();
|
|
449768
450203
|
await init_manager4();
|
|
449769
450204
|
EXTERNAL_TOOL_CALL_TIMEOUT_MS = 5 * 60 * 1000;
|
|
449770
450205
|
registeredToolsByRuntime = new WeakMap;
|
|
450206
|
+
connectionIdByRegistrationKey = new WeakMap;
|
|
449771
450207
|
});
|
|
449772
450208
|
|
|
449773
450209
|
// src/websocket/listener/commands/runtime-start.ts
|
|
@@ -449915,9 +450351,18 @@ async function handleRuntimeStartCommand(parsed, context3) {
|
|
|
449915
450351
|
agent2 = await resolveRuntimeStartAgent(parsed, created);
|
|
449916
450352
|
conversation = await resolveRuntimeStartConversation(parsed, agent2, created);
|
|
449917
450353
|
runtimeScope = buildRuntimeScope(agent2, conversation);
|
|
450354
|
+
const { connectionId } = context3;
|
|
450355
|
+
const assertConnectionOpen = () => {
|
|
450356
|
+
if (context3.runtime.connections.size > 0 && (!context3.runtime.connections.has(connectionId) || context3.runtime.connections.get(connectionId)?.cancellation.signal.aborted)) {
|
|
450357
|
+
throw new Error("App-server connection closed during runtime start");
|
|
450358
|
+
}
|
|
450359
|
+
};
|
|
450360
|
+
assertConnectionOpen();
|
|
449918
450361
|
const scopedRuntime = context3.getOrCreateScopedRuntime(context3.runtime, runtimeScope.agent_id, runtimeScope.conversation_id);
|
|
449919
450362
|
await applyRuntimeStartState(parsed, context3, runtimeScope, scopedRuntime);
|
|
449920
|
-
|
|
450363
|
+
assertConnectionOpen();
|
|
450364
|
+
subscribeListenerConnection(context3.runtime, connectionId, runtimeScope);
|
|
450365
|
+
registerRuntimeExternalTools(context3.runtime, connectionId, runtimeScope, parsed.external_tools ?? []);
|
|
449921
450366
|
const sent = sendRuntimeStartResponse(context3, parsed, {
|
|
449922
450367
|
success: true,
|
|
449923
450368
|
runtime: runtimeScope,
|
|
@@ -449959,6 +450404,7 @@ var init_runtime_start = __esm(async () => {
|
|
|
449959
450404
|
init_backend2();
|
|
449960
450405
|
init_mode();
|
|
449961
450406
|
init_settings_manager();
|
|
450407
|
+
init_connection();
|
|
449962
450408
|
init_cwd();
|
|
449963
450409
|
init_permission_mode();
|
|
449964
450410
|
await __promiseAll([
|
|
@@ -457404,16 +457850,19 @@ async function handleApprovalStop(params) {
|
|
|
457404
457850
|
return interruptTermination();
|
|
457405
457851
|
}
|
|
457406
457852
|
const onFileWrite = (filePath, content) => {
|
|
457407
|
-
if (runtime.turnLifecycle.isCurrent(turnLease)
|
|
457408
|
-
|
|
457409
|
-
|
|
457410
|
-
|
|
457411
|
-
|
|
457412
|
-
|
|
457413
|
-
|
|
457414
|
-
|
|
457415
|
-
|
|
457416
|
-
}
|
|
457853
|
+
if (!runtime.turnLifecycle.isCurrent(turnLease))
|
|
457854
|
+
return;
|
|
457855
|
+
emitProtocolV2Message(socket, runtime, {
|
|
457856
|
+
type: "file_ops",
|
|
457857
|
+
path: filePath,
|
|
457858
|
+
cg_entries: [],
|
|
457859
|
+
ops: [],
|
|
457860
|
+
source: "agent",
|
|
457861
|
+
document_content: content
|
|
457862
|
+
}, {
|
|
457863
|
+
agent_id: agentId,
|
|
457864
|
+
conversation_id: conversationId
|
|
457865
|
+
}, TO_SUBSCRIBERS);
|
|
457417
457866
|
};
|
|
457418
457867
|
let executionResults;
|
|
457419
457868
|
try {
|
|
@@ -457559,9 +458008,9 @@ var init_turn_approval = __esm(async () => {
|
|
|
457559
458008
|
init_diff_preview();
|
|
457560
458009
|
init_format_denial();
|
|
457561
458010
|
init_interactive_policy();
|
|
458011
|
+
init_connection();
|
|
457562
458012
|
init_secrets_sync();
|
|
457563
458013
|
init_skill_injection();
|
|
457564
|
-
init_transport();
|
|
457565
458014
|
init_turn_input_state();
|
|
457566
458015
|
await __promiseAll([
|
|
457567
458016
|
init_approval_execution(),
|
|
@@ -458995,6 +459444,7 @@ async function prepareListenerTurn(params) {
|
|
|
458995
459444
|
}
|
|
458996
459445
|
const modAdapters = await ensureListenerModAdaptersForAgent(runtime.listener, agentId);
|
|
458997
459446
|
const preparedToolContext = await prepareToolExecutionContextForScope({
|
|
459447
|
+
connectionId,
|
|
458998
459448
|
agentId,
|
|
458999
459449
|
conversationId,
|
|
459000
459450
|
clientToolAllowlist: msg.clientToolAllowlist,
|
|
@@ -459078,6 +459528,9 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
459078
459528
|
origin: "message",
|
|
459079
459529
|
workingDirectory: turnWorkingDirectory
|
|
459080
459530
|
});
|
|
459531
|
+
if (connectionId) {
|
|
459532
|
+
runtime.activeConnectionId = connectionId;
|
|
459533
|
+
}
|
|
459081
459534
|
if (!runtime.turnLifecycle.isCurrent(turnLease)) {
|
|
459082
459535
|
throw new Error("Cannot continue a turn with a stale lifecycle lease");
|
|
459083
459536
|
}
|
|
@@ -459682,6 +460135,9 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
459682
460135
|
});
|
|
459683
460136
|
}
|
|
459684
460137
|
richDraftStreamer?.dispose();
|
|
460138
|
+
if (runtime.activeConnectionId === connectionId) {
|
|
460139
|
+
runtime.activeConnectionId = null;
|
|
460140
|
+
}
|
|
459685
460141
|
try {
|
|
459686
460142
|
if (finalizedByThisInvocation) {
|
|
459687
460143
|
await runListenerTurnCleanup({
|
|
@@ -459787,15 +460243,19 @@ function handleModeChange(msg, socket, runtime, scope) {
|
|
|
459787
460243
|
}
|
|
459788
460244
|
}
|
|
459789
460245
|
}
|
|
459790
|
-
function resolveRuntimeForApprovalRequest(listener, requestId) {
|
|
460246
|
+
function resolveRuntimeForApprovalRequest(listener, scope, requestId, connectionId) {
|
|
459791
460247
|
if (!requestId) {
|
|
459792
460248
|
return null;
|
|
459793
460249
|
}
|
|
459794
|
-
const
|
|
459795
|
-
if (!
|
|
460250
|
+
const runtime = getConversationRuntime(listener, scope.agent_id, scope.conversation_id);
|
|
460251
|
+
if (!runtime) {
|
|
459796
460252
|
return null;
|
|
459797
460253
|
}
|
|
459798
|
-
|
|
460254
|
+
if (connectionId) {
|
|
460255
|
+
const requestKey = createConnectionRequestKey(connectionId, requestId);
|
|
460256
|
+
return runtime.pendingApprovalResolvers.has(requestKey) ? runtime : null;
|
|
460257
|
+
}
|
|
460258
|
+
return hasPendingApprovalRequestId(runtime, requestId) ? runtime : null;
|
|
459799
460259
|
}
|
|
459800
460260
|
async function handleApprovalResponseInput(listener, params, deps = {
|
|
459801
460261
|
resolveRuntimeForApprovalRequest,
|
|
@@ -459804,8 +460264,8 @@ async function handleApprovalResponseInput(listener, params, deps = {
|
|
|
459804
460264
|
resolveRecoveredApprovalResponse,
|
|
459805
460265
|
scheduleQueuePump
|
|
459806
460266
|
}) {
|
|
459807
|
-
const approvalRuntime = deps.resolveRuntimeForApprovalRequest(listener, params.response.request_id);
|
|
459808
|
-
if (approvalRuntime && deps.resolvePendingApprovalResolver(approvalRuntime, params.response)) {
|
|
460267
|
+
const approvalRuntime = deps.resolveRuntimeForApprovalRequest(listener, params.runtime, params.response.request_id, params.connectionId);
|
|
460268
|
+
if (approvalRuntime && deps.resolvePendingApprovalResolver(approvalRuntime, params.response, params.connectionId)) {
|
|
459809
460269
|
deps.scheduleQueuePump(approvalRuntime, params.socket, params.opts, params.processQueuedTurn);
|
|
459810
460270
|
return true;
|
|
459811
460271
|
}
|
|
@@ -460044,6 +460504,7 @@ var init_control_inputs = __esm(async () => {
|
|
|
460044
460504
|
init_mode();
|
|
460045
460505
|
init_error_reporting();
|
|
460046
460506
|
init_debug();
|
|
460507
|
+
init_connection();
|
|
460047
460508
|
init_cwd();
|
|
460048
460509
|
init_permission_mode();
|
|
460049
460510
|
init_runtime6();
|
|
@@ -460062,16 +460523,30 @@ var init_control_inputs = __esm(async () => {
|
|
|
460062
460523
|
});
|
|
460063
460524
|
|
|
460064
460525
|
// src/websocket/terminal-handler.ts
|
|
460526
|
+
import { existsSync as existsSync51 } from "node:fs";
|
|
460065
460527
|
import * as os6 from "node:os";
|
|
460066
|
-
import
|
|
460528
|
+
import WebSocket4 from "ws";
|
|
460529
|
+
function getTerminalKey(connectionId, terminalId) {
|
|
460530
|
+
return JSON.stringify([connectionId, terminalId]);
|
|
460531
|
+
}
|
|
460067
460532
|
function getDefaultShell() {
|
|
460068
460533
|
if (os6.platform() === "win32") {
|
|
460069
460534
|
return process.env.COMSPEC || "cmd.exe";
|
|
460070
460535
|
}
|
|
460071
|
-
|
|
460536
|
+
const candidates2 = [
|
|
460537
|
+
process.env.SHELL,
|
|
460538
|
+
os6.platform() === "darwin" ? "/bin/zsh" : "/bin/bash",
|
|
460539
|
+
"/bin/bash"
|
|
460540
|
+
];
|
|
460541
|
+
for (const candidate of candidates2) {
|
|
460542
|
+
if (candidate && existsSync51(candidate)) {
|
|
460543
|
+
return candidate;
|
|
460544
|
+
}
|
|
460545
|
+
}
|
|
460546
|
+
return "/bin/sh";
|
|
460072
460547
|
}
|
|
460073
460548
|
function sendTerminalMessage(socket, message) {
|
|
460074
|
-
if (socket.readyState ===
|
|
460549
|
+
if (socket.readyState === WebSocket4.OPEN) {
|
|
460075
460550
|
socket.send(JSON.stringify(message));
|
|
460076
460551
|
}
|
|
460077
460552
|
}
|
|
@@ -460097,7 +460572,8 @@ function makeOutputBatcher(onFlush) {
|
|
|
460097
460572
|
}
|
|
460098
460573
|
};
|
|
460099
460574
|
}
|
|
460100
|
-
function spawnBun(shell2, cwd2, cols, rows, terminal_id, socket) {
|
|
460575
|
+
function spawnBun(shell2, cwd2, cols, rows, terminal_id, connectionId, socket) {
|
|
460576
|
+
const terminalKey = getTerminalKey(connectionId, terminal_id);
|
|
460101
460577
|
const handleData = makeOutputBatcher((data) => sendTerminalMessage(socket, { type: "terminal_output", terminal_id, data }));
|
|
460102
460578
|
const proc2 = Bun.spawn([shell2], {
|
|
460103
460579
|
cwd: cwd2,
|
|
@@ -460113,9 +460589,9 @@ function spawnBun(shell2, cwd2, cols, rows, terminal_id, socket) {
|
|
|
460113
460589
|
throw new Error("Bun.spawn terminal object missing — API unavailable");
|
|
460114
460590
|
}
|
|
460115
460591
|
proc2.exited.then((exitCode) => {
|
|
460116
|
-
const current = terminals.get(
|
|
460592
|
+
const current = terminals.get(terminalKey);
|
|
460117
460593
|
if (current && current.pid === proc2.pid) {
|
|
460118
|
-
terminals.delete(
|
|
460594
|
+
terminals.delete(terminalKey);
|
|
460119
460595
|
sendTerminalMessage(socket, {
|
|
460120
460596
|
type: "terminal_exited",
|
|
460121
460597
|
terminal_id,
|
|
@@ -460144,10 +460620,12 @@ function spawnBun(shell2, cwd2, cols, rows, terminal_id, socket) {
|
|
|
460144
460620
|
},
|
|
460145
460621
|
pid: proc2.pid,
|
|
460146
460622
|
terminalId: terminal_id,
|
|
460623
|
+
connectionId,
|
|
460147
460624
|
spawnedAt: Date.now()
|
|
460148
460625
|
};
|
|
460149
460626
|
}
|
|
460150
|
-
function spawnNodePty(shell2, cwd2, cols, rows, terminal_id, socket) {
|
|
460627
|
+
function spawnNodePty(shell2, cwd2, cols, rows, terminal_id, connectionId, socket) {
|
|
460628
|
+
const terminalKey = getTerminalKey(connectionId, terminal_id);
|
|
460151
460629
|
const pty = __require("node-pty");
|
|
460152
460630
|
const handleData = makeOutputBatcher((data) => sendTerminalMessage(socket, { type: "terminal_output", terminal_id, data }));
|
|
460153
460631
|
const ptyProcess = pty.spawn(shell2, [], {
|
|
@@ -460163,9 +460641,9 @@ function spawnNodePty(shell2, cwd2, cols, rows, terminal_id, socket) {
|
|
|
460163
460641
|
});
|
|
460164
460642
|
ptyProcess.onData(handleData);
|
|
460165
460643
|
ptyProcess.onExit(({ exitCode }) => {
|
|
460166
|
-
const current = terminals.get(
|
|
460644
|
+
const current = terminals.get(terminalKey);
|
|
460167
460645
|
if (current && current.pid === ptyProcess.pid) {
|
|
460168
|
-
terminals.delete(
|
|
460646
|
+
terminals.delete(terminalKey);
|
|
460169
460647
|
sendTerminalMessage(socket, {
|
|
460170
460648
|
type: "terminal_exited",
|
|
460171
460649
|
terminal_id,
|
|
@@ -460191,12 +460669,14 @@ function spawnNodePty(shell2, cwd2, cols, rows, terminal_id, socket) {
|
|
|
460191
460669
|
},
|
|
460192
460670
|
pid: ptyProcess.pid,
|
|
460193
460671
|
terminalId: terminal_id,
|
|
460672
|
+
connectionId,
|
|
460194
460673
|
spawnedAt: Date.now()
|
|
460195
460674
|
};
|
|
460196
460675
|
}
|
|
460197
|
-
function handleTerminalSpawn(msg, socket, cwd2) {
|
|
460676
|
+
function handleTerminalSpawn(msg, socket, cwd2, connectionId = "legacy") {
|
|
460198
460677
|
const { terminal_id, cols, rows } = msg;
|
|
460199
|
-
const
|
|
460678
|
+
const terminalKey = getTerminalKey(connectionId, terminal_id);
|
|
460679
|
+
const existing = terminals.get(terminalKey);
|
|
460200
460680
|
if (existing && Date.now() - existing.spawnedAt < 2000) {
|
|
460201
460681
|
let alive = true;
|
|
460202
460682
|
try {
|
|
@@ -460213,14 +460693,14 @@ function handleTerminalSpawn(msg, socket, cwd2) {
|
|
|
460213
460693
|
});
|
|
460214
460694
|
return;
|
|
460215
460695
|
}
|
|
460216
|
-
terminals.delete(
|
|
460696
|
+
terminals.delete(terminalKey);
|
|
460217
460697
|
}
|
|
460218
|
-
killTerminal(terminal_id);
|
|
460698
|
+
killTerminal(terminal_id, connectionId);
|
|
460219
460699
|
const shell2 = getDefaultShell();
|
|
460220
460700
|
console.log(`[Terminal] Spawning PTY (${IS_BUN ? "bun" : "node-pty"}): shell=${shell2}, cwd=${cwd2}, cols=${cols}, rows=${rows}`);
|
|
460221
460701
|
try {
|
|
460222
|
-
const session = IS_BUN ? spawnBun(shell2, cwd2, cols, rows, terminal_id, socket) : spawnNodePty(shell2, cwd2, cols, rows, terminal_id, socket);
|
|
460223
|
-
terminals.set(
|
|
460702
|
+
const session = IS_BUN ? spawnBun(shell2, cwd2, cols, rows, terminal_id, connectionId, socket) : spawnNodePty(shell2, cwd2, cols, rows, terminal_id, connectionId, socket);
|
|
460703
|
+
terminals.set(terminalKey, session);
|
|
460224
460704
|
console.log(`[Terminal] Session stored for terminal_id=${terminal_id}, pid=${session.pid}`);
|
|
460225
460705
|
sendTerminalMessage(socket, {
|
|
460226
460706
|
type: "terminal_spawned",
|
|
@@ -460237,31 +460717,39 @@ function handleTerminalSpawn(msg, socket, cwd2) {
|
|
|
460237
460717
|
});
|
|
460238
460718
|
}
|
|
460239
460719
|
}
|
|
460240
|
-
function handleTerminalInput(msg) {
|
|
460241
|
-
terminals.get(msg.terminal_id)?.write(msg.data);
|
|
460720
|
+
function handleTerminalInput(msg, connectionId = "legacy") {
|
|
460721
|
+
terminals.get(getTerminalKey(connectionId, msg.terminal_id))?.write(msg.data);
|
|
460242
460722
|
}
|
|
460243
|
-
function handleTerminalResize(msg) {
|
|
460244
|
-
terminals.get(msg.terminal_id)?.resize(msg.cols, msg.rows);
|
|
460723
|
+
function handleTerminalResize(msg, connectionId = "legacy") {
|
|
460724
|
+
terminals.get(getTerminalKey(connectionId, msg.terminal_id))?.resize(msg.cols, msg.rows);
|
|
460245
460725
|
}
|
|
460246
|
-
function handleTerminalKill(msg) {
|
|
460247
|
-
const session = terminals.get(msg.terminal_id);
|
|
460726
|
+
function handleTerminalKill(msg, connectionId = "legacy") {
|
|
460727
|
+
const session = terminals.get(getTerminalKey(connectionId, msg.terminal_id));
|
|
460248
460728
|
if (session && Date.now() - session.spawnedAt < 2000) {
|
|
460249
460729
|
console.log(`[Terminal] Ignoring kill for recently spawned session (age=${Date.now() - session.spawnedAt}ms)`);
|
|
460250
460730
|
return;
|
|
460251
460731
|
}
|
|
460252
|
-
killTerminal(msg.terminal_id);
|
|
460732
|
+
killTerminal(msg.terminal_id, connectionId);
|
|
460253
460733
|
}
|
|
460254
|
-
function killTerminal(terminalId) {
|
|
460255
|
-
const
|
|
460734
|
+
function killTerminal(terminalId, connectionId) {
|
|
460735
|
+
const terminalKey = getTerminalKey(connectionId, terminalId);
|
|
460736
|
+
const session = terminals.get(terminalKey);
|
|
460256
460737
|
if (session) {
|
|
460257
460738
|
console.log(`[Terminal] killTerminal: terminalId=${terminalId}, pid=${session.pid}`);
|
|
460258
460739
|
session.kill();
|
|
460259
|
-
terminals.delete(
|
|
460740
|
+
terminals.delete(terminalKey);
|
|
460741
|
+
}
|
|
460742
|
+
}
|
|
460743
|
+
function killListenerConnectionTerminals(connectionId) {
|
|
460744
|
+
for (const session of [...terminals.values()]) {
|
|
460745
|
+
if (session.connectionId === connectionId) {
|
|
460746
|
+
killTerminal(session.terminalId, connectionId);
|
|
460747
|
+
}
|
|
460260
460748
|
}
|
|
460261
460749
|
}
|
|
460262
460750
|
function killAllTerminals() {
|
|
460263
|
-
for (const
|
|
460264
|
-
killTerminal(
|
|
460751
|
+
for (const session of [...terminals.values()]) {
|
|
460752
|
+
killTerminal(session.terminalId, session.connectionId);
|
|
460265
460753
|
}
|
|
460266
460754
|
}
|
|
460267
460755
|
var IS_BUN, FLUSH_INTERVAL_MS = 16, MAX_BUFFER_BYTES, terminals;
|
|
@@ -460489,7 +460977,7 @@ __export(exports_custom, {
|
|
|
460489
460977
|
GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
|
|
460490
460978
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
460491
460979
|
});
|
|
460492
|
-
import { existsSync as
|
|
460980
|
+
import { existsSync as existsSync52 } from "node:fs";
|
|
460493
460981
|
import { readdir as readdir10, readFile as readFile20 } from "node:fs/promises";
|
|
460494
460982
|
import { basename as basename25, dirname as dirname28, join as join65 } from "node:path";
|
|
460495
460983
|
async function getCustomCommands() {
|
|
@@ -460523,7 +461011,7 @@ async function discoverCustomCommands(projectPath = join65(process.cwd(), COMMAN
|
|
|
460523
461011
|
return result;
|
|
460524
461012
|
}
|
|
460525
461013
|
async function discoverFromDirectory(dirPath, source2) {
|
|
460526
|
-
if (!
|
|
461014
|
+
if (!existsSync52(dirPath)) {
|
|
460527
461015
|
return [];
|
|
460528
461016
|
}
|
|
460529
461017
|
const commands = [];
|
|
@@ -461488,6 +461976,144 @@ var init_commands2 = __esm(async () => {
|
|
|
461488
461976
|
]);
|
|
461489
461977
|
});
|
|
461490
461978
|
|
|
461979
|
+
// src/websocket/listener/connection-lifecycle.ts
|
|
461980
|
+
import WebSocket5 from "ws";
|
|
461981
|
+
function createConnectionTurnProcessor(runtime) {
|
|
461982
|
+
return async (queuedTurn, dequeuedBatch) => {
|
|
461983
|
+
const scopedRuntime = getOrCreateScopedRuntime(runtime, queuedTurn.agentId, queuedTurn.conversationId);
|
|
461984
|
+
if (!queuedTurn.connectionId) {
|
|
461985
|
+
await handleIncomingMessage(queuedTurn, getOrCreateProcessTransport(runtime), scopedRuntime, undefined, undefined, dequeuedBatch.batchId);
|
|
461986
|
+
return;
|
|
461987
|
+
}
|
|
461988
|
+
const connection = runtime.connections.get(queuedTurn.connectionId);
|
|
461989
|
+
if (!connection || connection.cancellation.signal.aborted) {
|
|
461990
|
+
return;
|
|
461991
|
+
}
|
|
461992
|
+
await handleIncomingMessage(queuedTurn, connection.writer, scopedRuntime, connection.options.onStatusChange, connection.id, dequeuedBatch.batchId);
|
|
461993
|
+
};
|
|
461994
|
+
}
|
|
461995
|
+
function cleanupListenerConnection(runtime, connectionId) {
|
|
461996
|
+
for (const conversationRuntime of runtime.conversationRuntimes.values()) {
|
|
461997
|
+
if (conversationRuntime.activeConnectionId === connectionId) {
|
|
461998
|
+
const hasEligibleFailover = getSubscribedListenerConnections(runtime, {
|
|
461999
|
+
agent_id: conversationRuntime.agentId,
|
|
462000
|
+
conversation_id: conversationRuntime.conversationId
|
|
462001
|
+
}).some((connection) => connection.id !== connectionId);
|
|
462002
|
+
if (hasEligibleFailover) {
|
|
462003
|
+
conversationRuntime.activeConnectionId = null;
|
|
462004
|
+
} else {
|
|
462005
|
+
conversationRuntime.turnLifecycle.requestCancellation();
|
|
462006
|
+
}
|
|
462007
|
+
}
|
|
462008
|
+
for (const [
|
|
462009
|
+
itemId,
|
|
462010
|
+
queuedMessage
|
|
462011
|
+
] of conversationRuntime.queuedMessagesByItemId) {
|
|
462012
|
+
if (queuedMessage.connectionId === connectionId) {
|
|
462013
|
+
conversationRuntime.queueRuntime.removeItem(itemId);
|
|
462014
|
+
conversationRuntime.queuedMessagesByItemId.delete(itemId);
|
|
462015
|
+
}
|
|
462016
|
+
}
|
|
462017
|
+
rejectPendingApprovalResolversForConnection(conversationRuntime, connectionId, "Listener connection closed");
|
|
462018
|
+
}
|
|
462019
|
+
rejectPendingExternalToolCallsForConnection(runtime, connectionId, "Listener connection closed");
|
|
462020
|
+
killListenerConnectionTerminals(connectionId);
|
|
462021
|
+
const closedSubscriptionKeys = [
|
|
462022
|
+
...runtime.connections.get(connectionId)?.subscriptions ?? []
|
|
462023
|
+
];
|
|
462024
|
+
closeListenerConnection(runtime, connectionId);
|
|
462025
|
+
for (const runtimeKey of closedSubscriptionKeys) {
|
|
462026
|
+
if (!runtime.connectionIdsByRuntimeKey.has(runtimeKey)) {
|
|
462027
|
+
const scopedRuntime = runtime.conversationRuntimes.get(runtimeKey);
|
|
462028
|
+
if (scopedRuntime) {
|
|
462029
|
+
evictConversationRuntimeIfIdle(scopedRuntime);
|
|
462030
|
+
}
|
|
462031
|
+
}
|
|
462032
|
+
}
|
|
462033
|
+
}
|
|
462034
|
+
function closeListenerRuntimeConnections(runtime, suppressCallbacks) {
|
|
462035
|
+
const socketsToClose = new Set;
|
|
462036
|
+
const collectSocket = (transport) => {
|
|
462037
|
+
if (transport && getListenerTransportKind(transport) === "websocket") {
|
|
462038
|
+
socketsToClose.add(transport);
|
|
462039
|
+
}
|
|
462040
|
+
};
|
|
462041
|
+
if (runtime.socket) {
|
|
462042
|
+
socketsToClose.add(runtime.socket);
|
|
462043
|
+
}
|
|
462044
|
+
if (runtime.streamSocket) {
|
|
462045
|
+
socketsToClose.add(runtime.streamSocket);
|
|
462046
|
+
}
|
|
462047
|
+
for (const connection of runtime.connections.values()) {
|
|
462048
|
+
collectSocket(connection.writer);
|
|
462049
|
+
collectSocket(connection.streamWriter);
|
|
462050
|
+
}
|
|
462051
|
+
for (const connectionId of [...runtime.connections.keys()]) {
|
|
462052
|
+
closeListenerConnection(runtime, connectionId);
|
|
462053
|
+
}
|
|
462054
|
+
runtime.connectionIdsByRuntimeKey.clear();
|
|
462055
|
+
runtime.socket = null;
|
|
462056
|
+
runtime.transport = null;
|
|
462057
|
+
runtime.streamSocket = null;
|
|
462058
|
+
runtime.streamTransport = null;
|
|
462059
|
+
for (const socket of socketsToClose) {
|
|
462060
|
+
if (suppressCallbacks) {
|
|
462061
|
+
socket.removeAllListeners();
|
|
462062
|
+
}
|
|
462063
|
+
if (socket.readyState === WebSocket5.OPEN || socket.readyState === WebSocket5.CONNECTING) {
|
|
462064
|
+
socket.close();
|
|
462065
|
+
}
|
|
462066
|
+
}
|
|
462067
|
+
}
|
|
462068
|
+
var init_connection_lifecycle = __esm(async () => {
|
|
462069
|
+
init_terminal_handler();
|
|
462070
|
+
init_connection();
|
|
462071
|
+
init_runtime6();
|
|
462072
|
+
init_transport();
|
|
462073
|
+
await __promiseAll([
|
|
462074
|
+
init_approval(),
|
|
462075
|
+
init_conversation_runtime(),
|
|
462076
|
+
init_external_tools(),
|
|
462077
|
+
init_turn()
|
|
462078
|
+
]);
|
|
462079
|
+
});
|
|
462080
|
+
|
|
462081
|
+
// src/websocket/listener/connection-state-sync.ts
|
|
462082
|
+
function emitInitialConnectionState(runtime, transport, connectionId, options3 = {}) {
|
|
462083
|
+
if (options3.emitInitialState === false)
|
|
462084
|
+
return;
|
|
462085
|
+
const routing = toListenerConnection(connectionId);
|
|
462086
|
+
if (runtime.conversationRuntimes.size === 0) {
|
|
462087
|
+
emitLoopStatusUpdate(transport, runtime, undefined, routing);
|
|
462088
|
+
return;
|
|
462089
|
+
}
|
|
462090
|
+
for (const conversationRuntime of runtime.conversationRuntimes.values()) {
|
|
462091
|
+
const scope = {
|
|
462092
|
+
agent_id: conversationRuntime.agentId,
|
|
462093
|
+
conversation_id: conversationRuntime.conversationId
|
|
462094
|
+
};
|
|
462095
|
+
emitDeviceStatusUpdate(transport, conversationRuntime, scope, routing);
|
|
462096
|
+
emitLoopStatusUpdate(transport, conversationRuntime, scope, routing);
|
|
462097
|
+
}
|
|
462098
|
+
}
|
|
462099
|
+
function replaySubscribedConnectionState(listener, transport, runtime, scope, forceDeviceStatus) {
|
|
462100
|
+
const connection = findListenerConnectionByTransport(listener, transport);
|
|
462101
|
+
if (connection) {
|
|
462102
|
+
replayPendingApprovalRequestsToConnection(runtime, connection.id);
|
|
462103
|
+
}
|
|
462104
|
+
emitStateSync(transport, listener, scope, {
|
|
462105
|
+
forceDeviceStatus,
|
|
462106
|
+
...connection ? { routing: toListenerConnection(connection.id) } : {}
|
|
462107
|
+
});
|
|
462108
|
+
}
|
|
462109
|
+
var init_connection_state_sync = __esm(async () => {
|
|
462110
|
+
init_connection();
|
|
462111
|
+
await __promiseAll([
|
|
462112
|
+
init_approval(),
|
|
462113
|
+
init_protocol_outbound()
|
|
462114
|
+
]);
|
|
462115
|
+
});
|
|
462116
|
+
|
|
461491
462117
|
// src/websocket/listener/grep-in-files.ts
|
|
461492
462118
|
import { execFile as execFile14 } from "node:child_process";
|
|
461493
462119
|
import { createRequire as createRequire6 } from "node:module";
|
|
@@ -462356,7 +462982,7 @@ function buildAppServerInfoResponse(command, options3) {
|
|
|
462356
462982
|
conversation_management: true,
|
|
462357
462983
|
memory_management: true,
|
|
462358
462984
|
runtime_start: true,
|
|
462359
|
-
split_channels:
|
|
462985
|
+
split_channels: false
|
|
462360
462986
|
}
|
|
462361
462987
|
};
|
|
462362
462988
|
}
|
|
@@ -463701,6 +464327,7 @@ function createListenerMessageHandler(params) {
|
|
|
463701
464327
|
const {
|
|
463702
464328
|
runtime,
|
|
463703
464329
|
socket,
|
|
464330
|
+
connectionId: explicitConnectionId,
|
|
463704
464331
|
opts,
|
|
463705
464332
|
processQueuedTurn,
|
|
463706
464333
|
fileCommandSession,
|
|
@@ -463717,6 +464344,7 @@ function createListenerMessageHandler(params) {
|
|
|
463717
464344
|
wireChannelIngress,
|
|
463718
464345
|
processIncomingMessage = handleIncomingMessage
|
|
463719
464346
|
} = params;
|
|
464347
|
+
const connectionId = explicitConnectionId ?? opts.connectionId;
|
|
463720
464348
|
return async (data) => {
|
|
463721
464349
|
const raw2 = data.toString();
|
|
463722
464350
|
let parsedScope = null;
|
|
@@ -463746,6 +464374,9 @@ function createListenerMessageHandler(params) {
|
|
|
463746
464374
|
return;
|
|
463747
464375
|
}
|
|
463748
464376
|
console.log(`[Listen V2] Received ${summarizeV2Command(parsed)}`);
|
|
464377
|
+
if (parsedScope) {
|
|
464378
|
+
subscribeListenerConnection(runtime, connectionId, parsedScope);
|
|
464379
|
+
}
|
|
463749
464380
|
if (parsed.type === "__invalid_input") {
|
|
463750
464381
|
emitLoopErrorNotice(socket, runtime, {
|
|
463751
464382
|
message: parsed.reason,
|
|
@@ -463762,6 +464393,7 @@ function createListenerMessageHandler(params) {
|
|
|
463762
464393
|
}
|
|
463763
464394
|
if (handleRuntimeStartProtocolCommand(parsed, {
|
|
463764
464395
|
socket,
|
|
464396
|
+
connectionId,
|
|
463765
464397
|
runtime,
|
|
463766
464398
|
safeSocketSend,
|
|
463767
464399
|
runDetachedListenerTask,
|
|
@@ -463771,7 +464403,7 @@ function createListenerMessageHandler(params) {
|
|
|
463771
464403
|
return;
|
|
463772
464404
|
}
|
|
463773
464405
|
if (parsed.type === "external_tool_call_response") {
|
|
463774
|
-
handleExternalToolCallResponseCommand(runtime, parsed);
|
|
464406
|
+
handleExternalToolCallResponseCommand(runtime, connectionId, parsed);
|
|
463775
464407
|
return;
|
|
463776
464408
|
}
|
|
463777
464409
|
if (parsed.type === "sync") {
|
|
@@ -463825,6 +464457,7 @@ function createListenerMessageHandler(params) {
|
|
|
463825
464457
|
if (await handleApprovalResponseInput2(runtime, {
|
|
463826
464458
|
runtime: parsed.runtime,
|
|
463827
464459
|
response: parsed.payload,
|
|
464460
|
+
connectionId,
|
|
463828
464461
|
socket,
|
|
463829
464462
|
opts: {
|
|
463830
464463
|
onStatusChange: opts.onStatusChange,
|
|
@@ -463849,6 +464482,7 @@ function createListenerMessageHandler(params) {
|
|
|
463849
464482
|
}
|
|
463850
464483
|
const incoming = {
|
|
463851
464484
|
type: "message",
|
|
464485
|
+
connectionId,
|
|
463852
464486
|
agentId: parsed.runtime.agent_id,
|
|
463853
464487
|
conversationId: parsed.runtime.conversation_id,
|
|
463854
464488
|
clientToolAllowlist: inputPayload.client_tool_allowlist,
|
|
@@ -463897,6 +464531,7 @@ function createListenerMessageHandler(params) {
|
|
|
463897
464531
|
if (parsed.type === "change_device_state") {
|
|
463898
464532
|
await handleChangeDeviceStateInput2(runtime, {
|
|
463899
464533
|
command: parsed,
|
|
464534
|
+
connectionId,
|
|
463900
464535
|
socket,
|
|
463901
464536
|
opts: {
|
|
463902
464537
|
onStatusChange: opts.onStatusChange,
|
|
@@ -463923,6 +464558,7 @@ function createListenerMessageHandler(params) {
|
|
|
463923
464558
|
try {
|
|
463924
464559
|
const aborted2 = await handleAbortMessageInput2(runtime, {
|
|
463925
464560
|
command: parsed,
|
|
464561
|
+
connectionId,
|
|
463926
464562
|
socket,
|
|
463927
464563
|
opts: {
|
|
463928
464564
|
onStatusChange: opts.onStatusChange,
|
|
@@ -464092,19 +464728,19 @@ function createListenerMessageHandler(params) {
|
|
|
464092
464728
|
return;
|
|
464093
464729
|
}
|
|
464094
464730
|
if (parsed.type === "terminal_spawn") {
|
|
464095
|
-
handleTerminalSpawn(parsed, socket, parsed.cwd ?? getBootWorkingDirectory(runtime));
|
|
464731
|
+
handleTerminalSpawn(parsed, socket, parsed.cwd ?? getBootWorkingDirectory(runtime), connectionId);
|
|
464096
464732
|
return;
|
|
464097
464733
|
}
|
|
464098
464734
|
if (parsed.type === "terminal_input") {
|
|
464099
|
-
handleTerminalInput(parsed);
|
|
464735
|
+
handleTerminalInput(parsed, connectionId);
|
|
464100
464736
|
return;
|
|
464101
464737
|
}
|
|
464102
464738
|
if (parsed.type === "terminal_resize") {
|
|
464103
|
-
handleTerminalResize(parsed);
|
|
464739
|
+
handleTerminalResize(parsed, connectionId);
|
|
464104
464740
|
return;
|
|
464105
464741
|
}
|
|
464106
464742
|
if (parsed.type === "terminal_kill") {
|
|
464107
|
-
handleTerminalKill(parsed);
|
|
464743
|
+
handleTerminalKill(parsed, connectionId);
|
|
464108
464744
|
}
|
|
464109
464745
|
} catch (error54) {
|
|
464110
464746
|
trackListenerError4("listener_message_handler_failed", error54, "listener_message_handler");
|
|
@@ -464131,6 +464767,7 @@ var init_message_router = __esm(async () => {
|
|
|
464131
464767
|
init_debug();
|
|
464132
464768
|
init_terminal_handler();
|
|
464133
464769
|
init_app_server_info();
|
|
464770
|
+
init_connection();
|
|
464134
464771
|
init_cwd();
|
|
464135
464772
|
init_runtime6();
|
|
464136
464773
|
await __promiseAll([
|
|
@@ -464157,6 +464794,97 @@ var init_message_router = __esm(async () => {
|
|
|
464157
464794
|
]);
|
|
464158
464795
|
});
|
|
464159
464796
|
|
|
464797
|
+
// src/websocket/listener/process-services.ts
|
|
464798
|
+
function installProcessEventRouting(params) {
|
|
464799
|
+
const { runtime, processTransport, opts, processQueuedTurn } = params;
|
|
464800
|
+
runtime._unsubscribeSubagentState?.();
|
|
464801
|
+
runtime._unsubscribeSubagentState = subscribe(() => {
|
|
464802
|
+
if (runtime.conversationRuntimes.size === 0) {
|
|
464803
|
+
emitSubagentStateIfOpen(runtime);
|
|
464804
|
+
return;
|
|
464805
|
+
}
|
|
464806
|
+
for (const conversationRuntime of runtime.conversationRuntimes.values()) {
|
|
464807
|
+
emitSubagentStateIfOpen(runtime, {
|
|
464808
|
+
agent_id: conversationRuntime.agentId,
|
|
464809
|
+
conversation_id: conversationRuntime.conversationId
|
|
464810
|
+
});
|
|
464811
|
+
}
|
|
464812
|
+
});
|
|
464813
|
+
runtime._unsubscribeSubagentStreamEvents?.();
|
|
464814
|
+
runtime._unsubscribeSubagentStreamEvents = subscribeToStreamEvents((subagentId, event2) => {
|
|
464815
|
+
if (!isListenerTransportOpen(processTransport))
|
|
464816
|
+
return;
|
|
464817
|
+
const subagent = getSubagents().find((entry) => entry.id === subagentId);
|
|
464818
|
+
if (subagent?.silent === true)
|
|
464819
|
+
return;
|
|
464820
|
+
emitStreamDelta(processTransport, runtime, event2, subagent?.parentAgentId ? {
|
|
464821
|
+
agent_id: subagent.parentAgentId,
|
|
464822
|
+
conversation_id: subagent.parentConversationId ?? "default"
|
|
464823
|
+
} : undefined, subagentId);
|
|
464824
|
+
});
|
|
464825
|
+
setMessageQueueAdder((queuedMessage) => {
|
|
464826
|
+
if (!queuedMessage.agentId || !queuedMessage.conversationId)
|
|
464827
|
+
return;
|
|
464828
|
+
const targetRuntime = getOrCreateScopedRuntime(runtime, queuedMessage.agentId, queuedMessage.conversationId);
|
|
464829
|
+
if (!targetRuntime?.queueRuntime)
|
|
464830
|
+
return;
|
|
464831
|
+
targetRuntime.queueRuntime.enqueue({
|
|
464832
|
+
kind: "task_notification",
|
|
464833
|
+
source: "task_notification",
|
|
464834
|
+
text: queuedMessage.text,
|
|
464835
|
+
agentId: queuedMessage.agentId ?? targetRuntime.agentId ?? undefined,
|
|
464836
|
+
conversationId: queuedMessage.conversationId ?? targetRuntime.conversationId
|
|
464837
|
+
});
|
|
464838
|
+
scheduleQueuePump(targetRuntime, processTransport, opts, processQueuedTurn);
|
|
464839
|
+
});
|
|
464840
|
+
}
|
|
464841
|
+
function clearProcessServices(runtime) {
|
|
464842
|
+
runtime._unsubscribeSubagentState?.();
|
|
464843
|
+
runtime._unsubscribeSubagentState = undefined;
|
|
464844
|
+
runtime._unsubscribeSubagentStreamEvents?.();
|
|
464845
|
+
runtime._unsubscribeSubagentStreamEvents = undefined;
|
|
464846
|
+
setMessageQueueAdder(null);
|
|
464847
|
+
stopScheduler();
|
|
464848
|
+
clearRuntimeTimers(runtime);
|
|
464849
|
+
runtime.processServicesStarted = false;
|
|
464850
|
+
}
|
|
464851
|
+
function invalidateProcessServices(runtime) {
|
|
464852
|
+
runtime.processServicesGeneration += 1;
|
|
464853
|
+
clearProcessServices(runtime);
|
|
464854
|
+
}
|
|
464855
|
+
async function waitForProcessServicesSlot(runtime, connectionId) {
|
|
464856
|
+
const initiatingConnection = runtime.connections.get(connectionId);
|
|
464857
|
+
const canInitiate = () => !initiatingConnection || runtime.connections.get(connectionId) === initiatingConnection && !initiatingConnection.cancellation.signal.aborted;
|
|
464858
|
+
while (runtime.processServicesReady) {
|
|
464859
|
+
const pending = runtime.processServicesReady;
|
|
464860
|
+
const pendingGeneration = runtime.processServicesReadyGeneration;
|
|
464861
|
+
try {
|
|
464862
|
+
await pending;
|
|
464863
|
+
} catch (error54) {
|
|
464864
|
+
if (pendingGeneration === runtime.processServicesGeneration)
|
|
464865
|
+
throw error54;
|
|
464866
|
+
}
|
|
464867
|
+
if (runtime.processServicesStarted)
|
|
464868
|
+
return false;
|
|
464869
|
+
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed || !canInitiate()) {
|
|
464870
|
+
return false;
|
|
464871
|
+
}
|
|
464872
|
+
}
|
|
464873
|
+
return canInitiate();
|
|
464874
|
+
}
|
|
464875
|
+
var init_process_services = __esm(async () => {
|
|
464876
|
+
init_subagent_state();
|
|
464877
|
+
init_message_queue_bridge();
|
|
464878
|
+
init_runtime6();
|
|
464879
|
+
init_transport();
|
|
464880
|
+
await __promiseAll([
|
|
464881
|
+
init_scheduler(),
|
|
464882
|
+
init_conversation_runtime(),
|
|
464883
|
+
init_protocol_outbound(),
|
|
464884
|
+
init_queue()
|
|
464885
|
+
]);
|
|
464886
|
+
});
|
|
464887
|
+
|
|
464160
464888
|
// src/websocket/listener/lifecycle.ts
|
|
464161
464889
|
import WebSocket6 from "ws";
|
|
464162
464890
|
function trackListenerError4(errorType, error54, context3) {
|
|
@@ -464219,9 +464947,7 @@ async function replaySyncStateForRuntime(listenerRuntime, socket, scope, opts) {
|
|
|
464219
464947
|
}
|
|
464220
464948
|
}
|
|
464221
464949
|
}
|
|
464222
|
-
|
|
464223
|
-
forceDeviceStatus: opts?.forceDeviceStatus
|
|
464224
|
-
});
|
|
464950
|
+
replaySubscribedConnectionState(listenerRuntime, socket, syncScopedRuntime, scope, opts?.forceDeviceStatus);
|
|
464225
464951
|
(opts?.scheduleWarmupsAfterSync ?? scheduleListenerWarmupsAfterSync)(listenerRuntime, scope);
|
|
464226
464952
|
}
|
|
464227
464953
|
async function recoverPendingChannelControlRequests(listener, opts) {
|
|
@@ -464253,7 +464979,7 @@ async function recoverPendingChannelControlRequests(listener, opts) {
|
|
|
464253
464979
|
}
|
|
464254
464980
|
for (const { scope, entries } of entriesByScope.values()) {
|
|
464255
464981
|
const runtime = getOrCreateScopedRuntime(listener, scope.agent_id, scope.conversation_id);
|
|
464256
|
-
const livePendingRequestIds =
|
|
464982
|
+
const livePendingRequestIds = getPendingApprovalRequestIds(runtime);
|
|
464257
464983
|
const shouldRecoverFromBackend = entries.some((entry) => !livePendingRequestIds.has(entry.event.requestId));
|
|
464258
464984
|
if (shouldRecoverFromBackend) {
|
|
464259
464985
|
try {
|
|
@@ -464378,7 +465104,7 @@ async function wireChannelIngress(listener, socket, opts, processQueuedTurn) {
|
|
|
464378
465104
|
scheduleQueuePump(conversationRuntime, socket, opts, processQueuedTurn);
|
|
464379
465105
|
});
|
|
464380
465106
|
registry2.setEventHandler((event2) => {
|
|
464381
|
-
handleChannelRegistryEvent(event2, socket, listener
|
|
465107
|
+
handleChannelRegistryEvent(event2, socket, listener);
|
|
464382
465108
|
});
|
|
464383
465109
|
await recoverPendingChannelControlRequests(listener);
|
|
464384
465110
|
registry2.setApprovalResponseHandler(async ({ runtime, response }) => handleApprovalResponseInput(listener, {
|
|
@@ -464643,6 +465369,14 @@ function createRuntime() {
|
|
|
464643
465369
|
hasSuccessfulConnection: false,
|
|
464644
465370
|
everConnected: false,
|
|
464645
465371
|
sessionId: `listen-${crypto.randomUUID()}`,
|
|
465372
|
+
nextConnectionOrdinal: 0,
|
|
465373
|
+
connections: new Map,
|
|
465374
|
+
connectionIdsByRuntimeKey: new Map,
|
|
465375
|
+
processTransport: null,
|
|
465376
|
+
processServicesStarted: false,
|
|
465377
|
+
processServicesGeneration: 0,
|
|
465378
|
+
processServicesReady: null,
|
|
465379
|
+
processServicesReadyGeneration: null,
|
|
464646
465380
|
eventSeqCounter: 0,
|
|
464647
465381
|
queueEmitScheduled: false,
|
|
464648
465382
|
pendingQueueEmitScope: undefined,
|
|
@@ -464660,7 +465394,6 @@ function createRuntime() {
|
|
|
464660
465394
|
connectionId: null,
|
|
464661
465395
|
connectionName: null,
|
|
464662
465396
|
conversationRuntimes: new Map,
|
|
464663
|
-
approvalRuntimeKeyByRequestId: new Map,
|
|
464664
465397
|
memfsSyncedAgents: new Map,
|
|
464665
465398
|
secretsHydrationByAgent: new Map,
|
|
464666
465399
|
secretsHydrationFreshnessByAgent: new Map,
|
|
@@ -464674,9 +465407,8 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
464674
465407
|
notifyStreamObserversRuntimeStopped(runtime);
|
|
464675
465408
|
disposeListenerModAdapter(runtime);
|
|
464676
465409
|
rejectPendingExternalToolCalls(runtime, "Listener runtime stopped");
|
|
464677
|
-
setMessageQueueAdder(null);
|
|
464678
465410
|
runtime.intentionallyClosed = true;
|
|
464679
|
-
|
|
465411
|
+
invalidateProcessServices(runtime);
|
|
464680
465412
|
for (const conversationRuntime of runtime.conversationRuntimes.values()) {
|
|
464681
465413
|
rejectPendingApprovalResolvers(conversationRuntime, "Listener runtime stopped");
|
|
464682
465414
|
clearConversationRuntimeState(conversationRuntime);
|
|
@@ -464686,7 +465418,9 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
464686
465418
|
}
|
|
464687
465419
|
}
|
|
464688
465420
|
runtime.conversationRuntimes.clear();
|
|
464689
|
-
runtime
|
|
465421
|
+
closeListenerRuntimeConnections(runtime, suppressCallbacks);
|
|
465422
|
+
runtime.processServicesReady = null;
|
|
465423
|
+
runtime.processServicesReadyGeneration = null;
|
|
464690
465424
|
clearListenerWarmState(runtime);
|
|
464691
465425
|
runtime.reminderStateByConversation.clear();
|
|
464692
465426
|
runtime.skillSourcesByConversation.clear();
|
|
@@ -464694,30 +465428,6 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
464694
465428
|
runtime.systemPromptRecompileByConversation.clear();
|
|
464695
465429
|
runtime.queuedSystemPromptRecompileByConversation.clear();
|
|
464696
465430
|
stopAllWorktreeWatchers(runtime);
|
|
464697
|
-
if (!runtime.socket) {
|
|
464698
|
-
if (runtime.streamSocket && (runtime.streamSocket.readyState === WebSocket6.OPEN || runtime.streamSocket.readyState === WebSocket6.CONNECTING)) {
|
|
464699
|
-
runtime.streamSocket.close();
|
|
464700
|
-
}
|
|
464701
|
-
runtime.streamSocket = null;
|
|
464702
|
-
runtime.streamTransport = null;
|
|
464703
|
-
runtime.transport = null;
|
|
464704
|
-
return;
|
|
464705
|
-
}
|
|
464706
|
-
const socket = runtime.socket;
|
|
464707
|
-
runtime.socket = null;
|
|
464708
|
-
runtime.transport = null;
|
|
464709
|
-
const streamSocket = runtime.streamSocket;
|
|
464710
|
-
runtime.streamSocket = null;
|
|
464711
|
-
runtime.streamTransport = null;
|
|
464712
|
-
if (suppressCallbacks) {
|
|
464713
|
-
socket.removeAllListeners();
|
|
464714
|
-
}
|
|
464715
|
-
if (socket.readyState === WebSocket6.OPEN || socket.readyState === WebSocket6.CONNECTING) {
|
|
464716
|
-
socket.close();
|
|
464717
|
-
}
|
|
464718
|
-
if (streamSocket && (streamSocket.readyState === WebSocket6.OPEN || streamSocket.readyState === WebSocket6.CONNECTING)) {
|
|
464719
|
-
streamSocket.close();
|
|
464720
|
-
}
|
|
464721
465431
|
}
|
|
464722
465432
|
async function startConnectedListenerRuntime(runtime, transport, opts, processQueuedTurn, options3 = {}) {
|
|
464723
465433
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
@@ -464726,103 +465436,88 @@ async function startConnectedListenerRuntime(runtime, transport, opts, processQu
|
|
|
464726
465436
|
const shouldStartHeartbeat = options3.startHeartbeat !== false;
|
|
464727
465437
|
const cronSchedulerDisabledByEnv = process.env.LETTA_DISABLE_CRON_SCHEDULER === "1";
|
|
464728
465438
|
const shouldStartCronScheduler = options3.startCronScheduler !== false && !cronSchedulerDisabledByEnv;
|
|
464729
|
-
runtime.
|
|
464730
|
-
runtime.streamTransport = options3.streamTransport ?? null;
|
|
465439
|
+
markListenerConnectionInitialized(runtime, opts.connectionId);
|
|
464731
465440
|
safeEmitWsEvent("recv", "lifecycle", {
|
|
464732
465441
|
type: getListenerTransportKind(transport) === "websocket" ? "_ws_open" : "_local_open"
|
|
464733
465442
|
});
|
|
464734
465443
|
runtime.hasSuccessfulConnection = true;
|
|
464735
465444
|
runtime.everConnected = true;
|
|
464736
465445
|
opts.onConnected(opts.connectionId);
|
|
464737
|
-
|
|
464738
|
-
|
|
464739
|
-
|
|
464740
|
-
for (const conversationRuntime of runtime.conversationRuntimes.values()) {
|
|
464741
|
-
const scope = {
|
|
464742
|
-
agent_id: conversationRuntime.agentId,
|
|
464743
|
-
conversation_id: conversationRuntime.conversationId
|
|
464744
|
-
};
|
|
464745
|
-
emitDeviceStatusUpdate(transport, conversationRuntime, scope);
|
|
464746
|
-
emitLoopStatusUpdate(transport, conversationRuntime, scope);
|
|
464747
|
-
}
|
|
465446
|
+
emitInitialConnectionState(runtime, transport, opts.connectionId, options3);
|
|
465447
|
+
if (runtime.processServicesStarted) {
|
|
465448
|
+
return;
|
|
464748
465449
|
}
|
|
464749
|
-
runtime.
|
|
464750
|
-
|
|
464751
|
-
|
|
464752
|
-
|
|
464753
|
-
|
|
465450
|
+
if (!await waitForProcessServicesSlot(runtime, opts.connectionId))
|
|
465451
|
+
return;
|
|
465452
|
+
const processServicesGeneration = runtime.processServicesGeneration + 1;
|
|
465453
|
+
runtime.processServicesGeneration = processServicesGeneration;
|
|
465454
|
+
const processServicesReady = (async () => {
|
|
465455
|
+
const processTransport = getOrCreateProcessTransport(runtime);
|
|
465456
|
+
installProcessEventRouting({
|
|
465457
|
+
runtime,
|
|
465458
|
+
processTransport,
|
|
465459
|
+
opts,
|
|
465460
|
+
processQueuedTurn
|
|
465461
|
+
});
|
|
465462
|
+
if (shouldStartHeartbeat) {
|
|
465463
|
+
runtime.lastPongAt = Date.now();
|
|
465464
|
+
runtime.heartbeatInterval = setInterval(() => {
|
|
465465
|
+
if (getListenerTransportKind(transport) === "websocket" && isListenerPongStale(runtime.lastPongAt, Date.now(), LISTENER_PONG_TIMEOUT_MS)) {
|
|
465466
|
+
trackListenerError4("listener_pong_timeout", new Error(`No relay pong within ${LISTENER_PONG_TIMEOUT_MS}ms; terminating half-open socket to force reconnect`), "listener_heartbeat");
|
|
465467
|
+
runtime.socket?.terminate();
|
|
465468
|
+
return;
|
|
465469
|
+
}
|
|
465470
|
+
safeTransportSend(transport, { type: "ping" }, "listener_ping_send_failed", "listener_heartbeat");
|
|
465471
|
+
}, LISTENER_HEARTBEAT_INTERVAL_MS);
|
|
464754
465472
|
}
|
|
464755
|
-
|
|
464756
|
-
|
|
464757
|
-
agent_id: conversationRuntime.agentId,
|
|
464758
|
-
conversation_id: conversationRuntime.conversationId
|
|
464759
|
-
});
|
|
465473
|
+
if (shouldStartCronScheduler) {
|
|
465474
|
+
startScheduler(processTransport, opts, processQueuedTurn);
|
|
464760
465475
|
}
|
|
464761
|
-
|
|
464762
|
-
|
|
464763
|
-
|
|
464764
|
-
if (!isListenerTransportOpen(transport))
|
|
464765
|
-
return;
|
|
464766
|
-
const subagent = getSubagents().find((entry) => entry.id === subagentId);
|
|
464767
|
-
if (subagent?.silent === true) {
|
|
464768
|
-
return;
|
|
465476
|
+
await (options3.wireChannelIngress ?? wireChannelIngress)(runtime, processTransport, opts, processQueuedTurn);
|
|
465477
|
+
if (runtime.processServicesGeneration === processServicesGeneration) {
|
|
465478
|
+
runtime.processServicesStarted = true;
|
|
464769
465479
|
}
|
|
464770
|
-
|
|
464771
|
-
|
|
464772
|
-
|
|
464773
|
-
|
|
464774
|
-
|
|
464775
|
-
|
|
464776
|
-
|
|
464777
|
-
if (!targetRuntime?.queueRuntime) {
|
|
465480
|
+
})();
|
|
465481
|
+
runtime.processServicesReady = processServicesReady;
|
|
465482
|
+
runtime.processServicesReadyGeneration = processServicesGeneration;
|
|
465483
|
+
try {
|
|
465484
|
+
await processServicesReady;
|
|
465485
|
+
} catch (error54) {
|
|
465486
|
+
if (runtime.processServicesGeneration !== processServicesGeneration)
|
|
464778
465487
|
return;
|
|
465488
|
+
clearProcessServices(runtime);
|
|
465489
|
+
throw error54;
|
|
465490
|
+
} finally {
|
|
465491
|
+
if (runtime.processServicesReady === processServicesReady) {
|
|
465492
|
+
runtime.processServicesReady = null;
|
|
465493
|
+
runtime.processServicesReadyGeneration = null;
|
|
464779
465494
|
}
|
|
464780
|
-
targetRuntime.queueRuntime.enqueue({
|
|
464781
|
-
kind: "task_notification",
|
|
464782
|
-
source: "task_notification",
|
|
464783
|
-
text: queuedMessage.text,
|
|
464784
|
-
agentId: queuedMessage.agentId ?? targetRuntime.agentId ?? undefined,
|
|
464785
|
-
conversationId: queuedMessage.conversationId ?? targetRuntime.conversationId
|
|
464786
|
-
});
|
|
464787
|
-
scheduleQueuePump(targetRuntime, transport, opts, processQueuedTurn);
|
|
464788
|
-
});
|
|
464789
|
-
if (shouldStartHeartbeat) {
|
|
464790
|
-
runtime.lastPongAt = Date.now();
|
|
464791
|
-
runtime.heartbeatInterval = setInterval(() => {
|
|
464792
|
-
if (getListenerTransportKind(transport) === "websocket" && isListenerPongStale(runtime.lastPongAt, Date.now(), LISTENER_PONG_TIMEOUT_MS)) {
|
|
464793
|
-
trackListenerError4("listener_pong_timeout", new Error(`No relay pong within ${LISTENER_PONG_TIMEOUT_MS}ms; terminating half-open socket to force reconnect`), "listener_heartbeat");
|
|
464794
|
-
runtime.socket?.terminate();
|
|
464795
|
-
return;
|
|
464796
|
-
}
|
|
464797
|
-
safeTransportSend(transport, { type: "ping" }, "listener_ping_send_failed", "listener_heartbeat");
|
|
464798
|
-
}, LISTENER_HEARTBEAT_INTERVAL_MS);
|
|
464799
465495
|
}
|
|
464800
|
-
if (shouldStartCronScheduler) {
|
|
464801
|
-
startScheduler(transport, opts, processQueuedTurn);
|
|
464802
|
-
}
|
|
464803
|
-
await wireChannelIngress(runtime, transport, opts, processQueuedTurn);
|
|
464804
465496
|
}
|
|
464805
465497
|
async function attachOpenListenerSocket(runtime, socket, opts, options3 = {}) {
|
|
464806
465498
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
464807
465499
|
return;
|
|
464808
465500
|
}
|
|
464809
465501
|
const streamSocket = options3.streamSocket ?? null;
|
|
465502
|
+
const connection = openListenerConnection({
|
|
465503
|
+
runtime,
|
|
465504
|
+
connectionId: opts.connectionId,
|
|
465505
|
+
writer: socket,
|
|
465506
|
+
streamWriter: streamSocket,
|
|
465507
|
+
options: opts
|
|
465508
|
+
});
|
|
464810
465509
|
const fileCommandSession = createFileCommandSession({
|
|
464811
465510
|
socket,
|
|
464812
465511
|
safeSocketSend,
|
|
464813
465512
|
runDetachedListenerTask
|
|
464814
465513
|
});
|
|
464815
|
-
runtime.socket = socket;
|
|
464816
|
-
runtime.streamSocket = streamSocket;
|
|
464817
465514
|
installExternalToolBridge(runtime);
|
|
464818
465515
|
const transport = socket;
|
|
464819
|
-
const processQueuedTurn =
|
|
464820
|
-
const scopedRuntime = getOrCreateScopedRuntime(runtime, queuedTurn.agentId, queuedTurn.conversationId);
|
|
464821
|
-
await handleIncomingMessage(queuedTurn, transport, scopedRuntime, opts.onStatusChange, opts.connectionId, dequeuedBatch.batchId);
|
|
464822
|
-
};
|
|
465516
|
+
const processQueuedTurn = createConnectionTurnProcessor(runtime);
|
|
464823
465517
|
const handleMessage = createListenerMessageHandler({
|
|
464824
465518
|
runtime,
|
|
464825
465519
|
socket,
|
|
465520
|
+
connectionId: opts.connectionId,
|
|
464826
465521
|
opts,
|
|
464827
465522
|
processQueuedTurn,
|
|
464828
465523
|
fileCommandSession,
|
|
@@ -464841,6 +465536,9 @@ async function attachOpenListenerSocket(runtime, socket, opts, options3 = {}) {
|
|
|
464841
465536
|
socket.on("message", (data) => {
|
|
464842
465537
|
(async () => {
|
|
464843
465538
|
await options3.startupReady;
|
|
465539
|
+
if (connection.cancellation.signal.aborted || runtime.connections.get(opts.connectionId) !== connection) {
|
|
465540
|
+
return;
|
|
465541
|
+
}
|
|
464844
465542
|
await handleMessage(data);
|
|
464845
465543
|
})().catch((error54) => {
|
|
464846
465544
|
trackListenerError4("listener_message_handler_failed", error54, "listener_message_handler");
|
|
@@ -464858,12 +465556,7 @@ async function attachOpenListenerSocket(runtime, socket, opts, options3 = {}) {
|
|
|
464858
465556
|
reason: reasonText
|
|
464859
465557
|
});
|
|
464860
465558
|
fileCommandSession.dispose();
|
|
464861
|
-
|
|
464862
|
-
getChannelRegistry()?.pause();
|
|
464863
|
-
stopRuntime(runtime, true);
|
|
464864
|
-
if (getActiveRuntime() === runtime) {
|
|
464865
|
-
setActiveRuntime(null);
|
|
464866
|
-
}
|
|
465559
|
+
cleanupListenerConnection(runtime, opts.connectionId);
|
|
464867
465560
|
opts.onDisconnected();
|
|
464868
465561
|
});
|
|
464869
465562
|
socket.on("error", (error54) => {
|
|
@@ -464891,11 +465584,15 @@ async function attachOpenListenerSocket(runtime, socket, opts, options3 = {}) {
|
|
|
464891
465584
|
});
|
|
464892
465585
|
}
|
|
464893
465586
|
await options3.startupReady;
|
|
465587
|
+
if (connection.cancellation.signal.aborted || runtime.connections.get(opts.connectionId) !== connection) {
|
|
465588
|
+
return;
|
|
465589
|
+
}
|
|
464894
465590
|
const streamTransport = streamSocket?.readyState === WebSocket6.OPEN ? streamSocket : null;
|
|
464895
465591
|
await startConnectedListenerRuntime(runtime, transport, opts, processQueuedTurn, {
|
|
464896
465592
|
startHeartbeat: options3.startHeartbeat ?? false,
|
|
464897
465593
|
startCronScheduler: options3.startCronScheduler ?? true,
|
|
464898
|
-
streamTransport
|
|
465594
|
+
streamTransport,
|
|
465595
|
+
emitInitialState: false
|
|
464899
465596
|
});
|
|
464900
465597
|
}
|
|
464901
465598
|
async function startListenerClient(opts) {
|
|
@@ -464929,10 +465626,18 @@ async function startLocalChannelListener(opts) {
|
|
|
464929
465626
|
await reloadListenerModAdapter(runtime);
|
|
464930
465627
|
await loadTools();
|
|
464931
465628
|
const transport = new LocalListenerTransport;
|
|
464932
|
-
const
|
|
464933
|
-
|
|
464934
|
-
|
|
465629
|
+
const connectionOptions = {
|
|
465630
|
+
...opts,
|
|
465631
|
+
wsUrl: "local://listener",
|
|
465632
|
+
onDisconnected: () => {}
|
|
464935
465633
|
};
|
|
465634
|
+
openListenerConnection({
|
|
465635
|
+
runtime,
|
|
465636
|
+
connectionId: opts.connectionId,
|
|
465637
|
+
writer: transport,
|
|
465638
|
+
options: connectionOptions
|
|
465639
|
+
});
|
|
465640
|
+
const processQueuedTurn = createConnectionTurnProcessor(runtime);
|
|
464936
465641
|
await startConnectedListenerRuntime(runtime, transport, opts, processQueuedTurn, { startHeartbeat: false, startCronScheduler: true });
|
|
464937
465642
|
} catch (error54) {
|
|
464938
465643
|
stopRuntime(runtime, true);
|
|
@@ -465010,15 +465715,19 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
465010
465715
|
runtime.socket = socket;
|
|
465011
465716
|
runtime.streamSocket = streamSocket;
|
|
465012
465717
|
const transport = socket;
|
|
465013
|
-
const processQueuedTurn =
|
|
465014
|
-
const scopedRuntime = getOrCreateScopedRuntime(runtime, queuedTurn.agentId, queuedTurn.conversationId);
|
|
465015
|
-
await handleIncomingMessage(queuedTurn, transport, scopedRuntime, opts.onStatusChange, opts.connectionId, dequeuedBatch.batchId);
|
|
465016
|
-
};
|
|
465718
|
+
const processQueuedTurn = createConnectionTurnProcessor(runtime);
|
|
465017
465719
|
socket.on("open", async () => {
|
|
465018
465720
|
let streamTransport = null;
|
|
465019
465721
|
if (streamSocket) {
|
|
465020
465722
|
streamTransport = await waitForStreamSocketOpen(streamSocket, runtime);
|
|
465021
465723
|
}
|
|
465724
|
+
openListenerConnection({
|
|
465725
|
+
runtime,
|
|
465726
|
+
connectionId: opts.connectionId,
|
|
465727
|
+
writer: socket,
|
|
465728
|
+
streamWriter: streamTransport,
|
|
465729
|
+
options: opts
|
|
465730
|
+
});
|
|
465022
465731
|
await startConnectedListenerRuntime(runtime, transport, opts, processQueuedTurn, {
|
|
465023
465732
|
startHeartbeat: true,
|
|
465024
465733
|
startCronScheduler: true,
|
|
@@ -465028,6 +465737,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
465028
465737
|
socket.on("message", createListenerMessageHandler({
|
|
465029
465738
|
runtime,
|
|
465030
465739
|
socket,
|
|
465740
|
+
connectionId: opts.connectionId,
|
|
465031
465741
|
opts,
|
|
465032
465742
|
processQueuedTurn,
|
|
465033
465743
|
fileCommandSession,
|
|
@@ -465053,12 +465763,11 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
465053
465763
|
reason: reason.toString()
|
|
465054
465764
|
});
|
|
465055
465765
|
fileCommandSession.dispose();
|
|
465056
|
-
|
|
465766
|
+
invalidateProcessServices(runtime);
|
|
465057
465767
|
const channelRegistry = getChannelRegistry();
|
|
465058
465768
|
if (channelRegistry) {
|
|
465059
465769
|
channelRegistry.pause();
|
|
465060
465770
|
}
|
|
465061
|
-
setMessageQueueAdder(null);
|
|
465062
465771
|
for (const conversationRuntime of runtime.conversationRuntimes.values()) {
|
|
465063
465772
|
conversationRuntime.queuedMessagesByItemId.clear();
|
|
465064
465773
|
if (conversationRuntime.queueRuntime) {
|
|
@@ -465068,12 +465777,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
465068
465777
|
if (isDebugEnabled()) {
|
|
465069
465778
|
console.log(`[Listen] WebSocket disconnected (code: ${code2}, reason: ${reason.toString()})`);
|
|
465070
465779
|
}
|
|
465071
|
-
|
|
465780
|
+
suspendListenerConnection(runtime, opts.connectionId);
|
|
465072
465781
|
killAllTerminals();
|
|
465073
|
-
runtime._unsubscribeSubagentState?.();
|
|
465074
|
-
runtime._unsubscribeSubagentState = undefined;
|
|
465075
|
-
runtime._unsubscribeSubagentStreamEvents?.();
|
|
465076
|
-
runtime._unsubscribeSubagentStreamEvents = undefined;
|
|
465077
465782
|
clearListenerWarmState(runtime);
|
|
465078
465783
|
if (streamSocket) {
|
|
465079
465784
|
streamSocket.removeAllListeners();
|
|
@@ -465150,7 +465855,6 @@ function stopListenerClient() {
|
|
|
465150
465855
|
stopRuntime(runtime, true);
|
|
465151
465856
|
}
|
|
465152
465857
|
var init_lifecycle = __esm(async () => {
|
|
465153
|
-
init_subagent_state();
|
|
465154
465858
|
init_commands();
|
|
465155
465859
|
init_progress_builder();
|
|
465156
465860
|
init_registry();
|
|
@@ -465160,10 +465864,10 @@ var init_lifecycle = __esm(async () => {
|
|
|
465160
465864
|
init_telemetry();
|
|
465161
465865
|
init_error_reporting();
|
|
465162
465866
|
init_debug();
|
|
465163
|
-
init_message_queue_bridge();
|
|
465164
465867
|
init_terminal_handler();
|
|
465165
465868
|
init_auth();
|
|
465166
465869
|
init_channel_turn_session();
|
|
465870
|
+
init_connection();
|
|
465167
465871
|
init_constants3();
|
|
465168
465872
|
init_cwd();
|
|
465169
465873
|
init_permission_mode();
|
|
@@ -465174,18 +465878,20 @@ var init_lifecycle = __esm(async () => {
|
|
|
465174
465878
|
init_manager4(),
|
|
465175
465879
|
init_approval(),
|
|
465176
465880
|
init_commands2(),
|
|
465177
|
-
|
|
465881
|
+
init_channel_registry_events(),
|
|
465178
465882
|
init_model_toolset(),
|
|
465883
|
+
init_connection_lifecycle(),
|
|
465884
|
+
init_connection_state_sync(),
|
|
465179
465885
|
init_control_inputs(),
|
|
465180
465886
|
init_conversation_runtime(),
|
|
465181
465887
|
init_external_tools(),
|
|
465182
465888
|
init_file_commands(),
|
|
465183
465889
|
init_message_router(),
|
|
465184
465890
|
init_mod_adapter2(),
|
|
465891
|
+
init_process_services(),
|
|
465185
465892
|
init_protocol_outbound(),
|
|
465186
465893
|
init_queue(),
|
|
465187
465894
|
init_recovery(),
|
|
465188
|
-
init_turn(),
|
|
465189
465895
|
init_turn_events(),
|
|
465190
465896
|
init_warmup(),
|
|
465191
465897
|
init_worktree_watcher()
|
|
@@ -465273,6 +465979,60 @@ function createLegacyTestRuntime() {
|
|
|
465273
465979
|
listener.sessionId = value;
|
|
465274
465980
|
}
|
|
465275
465981
|
},
|
|
465982
|
+
nextConnectionOrdinal: {
|
|
465983
|
+
get: () => listener.nextConnectionOrdinal,
|
|
465984
|
+
set: (value) => {
|
|
465985
|
+
listener.nextConnectionOrdinal = value;
|
|
465986
|
+
}
|
|
465987
|
+
},
|
|
465988
|
+
connections: {
|
|
465989
|
+
get: () => listener.connections,
|
|
465990
|
+
set: (value) => {
|
|
465991
|
+
listener.connections = value;
|
|
465992
|
+
}
|
|
465993
|
+
},
|
|
465994
|
+
connectionIdsByRuntimeKey: {
|
|
465995
|
+
get: () => listener.connectionIdsByRuntimeKey,
|
|
465996
|
+
set: (value) => {
|
|
465997
|
+
listener.connectionIdsByRuntimeKey = value;
|
|
465998
|
+
}
|
|
465999
|
+
},
|
|
466000
|
+
processTransport: {
|
|
466001
|
+
get: () => listener.processTransport,
|
|
466002
|
+
set: (value) => {
|
|
466003
|
+
listener.processTransport = value;
|
|
466004
|
+
}
|
|
466005
|
+
},
|
|
466006
|
+
processServicesStarted: {
|
|
466007
|
+
get: () => listener.processServicesStarted,
|
|
466008
|
+
set: (value) => {
|
|
466009
|
+
listener.processServicesStarted = value;
|
|
466010
|
+
}
|
|
466011
|
+
},
|
|
466012
|
+
processServicesGeneration: {
|
|
466013
|
+
get: () => listener.processServicesGeneration,
|
|
466014
|
+
set: (value) => {
|
|
466015
|
+
listener.processServicesGeneration = value;
|
|
466016
|
+
}
|
|
466017
|
+
},
|
|
466018
|
+
processServicesReady: {
|
|
466019
|
+
get: () => listener.processServicesReady,
|
|
466020
|
+
set: (value) => {
|
|
466021
|
+
listener.processServicesReady = value;
|
|
466022
|
+
}
|
|
466023
|
+
},
|
|
466024
|
+
processServicesReadyGeneration: {
|
|
466025
|
+
get: () => listener.processServicesReadyGeneration,
|
|
466026
|
+
set: (value) => {
|
|
466027
|
+
listener.processServicesReadyGeneration = value;
|
|
466028
|
+
}
|
|
466029
|
+
},
|
|
466030
|
+
pendingExternalToolCalls: {
|
|
466031
|
+
get: () => listener.pendingExternalToolCalls,
|
|
466032
|
+
set: (value) => {
|
|
466033
|
+
listener.pendingExternalToolCalls = value;
|
|
466034
|
+
}
|
|
466035
|
+
},
|
|
465276
466036
|
eventSeqCounter: {
|
|
465277
466037
|
get: () => listener.eventSeqCounter,
|
|
465278
466038
|
set: (value) => {
|
|
@@ -465345,12 +466105,6 @@ function createLegacyTestRuntime() {
|
|
|
465345
466105
|
listener.conversationRuntimes = value;
|
|
465346
466106
|
}
|
|
465347
466107
|
},
|
|
465348
|
-
approvalRuntimeKeyByRequestId: {
|
|
465349
|
-
get: () => listener.approvalRuntimeKeyByRequestId,
|
|
465350
|
-
set: (value) => {
|
|
465351
|
-
listener.approvalRuntimeKeyByRequestId = value;
|
|
465352
|
-
}
|
|
465353
|
-
},
|
|
465354
466108
|
memfsSyncedAgents: {
|
|
465355
466109
|
get: () => listener.memfsSyncedAgents,
|
|
465356
466110
|
set: (value) => {
|
|
@@ -465423,6 +466177,7 @@ var init_client7 = __esm(async () => {
|
|
|
465423
466177
|
await __promiseAll([
|
|
465424
466178
|
init_approval(),
|
|
465425
466179
|
init_agents_conversations(),
|
|
466180
|
+
init_channel_registry_events(),
|
|
465426
466181
|
init_channels2(),
|
|
465427
466182
|
init_cron3(),
|
|
465428
466183
|
init_memory6(),
|
|
@@ -465499,7 +466254,7 @@ var init_client7 = __esm(async () => {
|
|
|
465499
466254
|
handleListMemoryCommand: (parsed, socket, overrides) => handleListMemoryCommand(parsed, socket, safeSocketSend, overrides),
|
|
465500
466255
|
isDetachedChannelsCommand,
|
|
465501
466256
|
handleChannelsProtocolCommand: (parsed, socket, runtime, opts, processQueuedTurn) => handleChannelsProtocolCommand(parsed, socket, runtime, opts, processQueuedTurn, runDetachedListenerTask, wireChannelIngress, safeSocketSend),
|
|
465502
|
-
handleChannelRegistryEvent: (event2, socket, runtime) => handleChannelRegistryEvent(event2, socket, runtime
|
|
466257
|
+
handleChannelRegistryEvent: (event2, socket, runtime) => handleChannelRegistryEvent(event2, socket, runtime),
|
|
465503
466258
|
handleAgentConversationManagementCommand: (parsed, socket) => handleAgentConversationManagementCommand(parsed, socket, safeSocketSend),
|
|
465504
466259
|
handleAgentConversationManagementProtocolCommand: (parsed, socket) => handleAgentConversationManagementProtocolCommand(parsed, {
|
|
465505
466260
|
socket,
|
|
@@ -465508,6 +466263,7 @@ var init_client7 = __esm(async () => {
|
|
|
465508
466263
|
}),
|
|
465509
466264
|
handleRuntimeStartCommand: (parsed, socket, runtime) => handleRuntimeStartCommand(parsed, {
|
|
465510
466265
|
socket,
|
|
466266
|
+
connectionId: runtime.connectionId ?? "test-connection",
|
|
465511
466267
|
runtime,
|
|
465512
466268
|
safeSocketSend,
|
|
465513
466269
|
runDetachedListenerTask,
|
|
@@ -465519,6 +466275,7 @@ var init_client7 = __esm(async () => {
|
|
|
465519
466275
|
}),
|
|
465520
466276
|
handleRuntimeStartProtocolCommand: (parsed, socket, runtime) => handleRuntimeStartProtocolCommand(parsed, {
|
|
465521
466277
|
socket,
|
|
466278
|
+
connectionId: runtime.connectionId ?? "test-connection",
|
|
465522
466279
|
runtime,
|
|
465523
466280
|
safeSocketSend,
|
|
465524
466281
|
runDetachedListenerTask,
|
|
@@ -466121,7 +466878,7 @@ var init_listen = __esm(async () => {
|
|
|
466121
466878
|
import { randomUUID as randomUUID26 } from "node:crypto";
|
|
466122
466879
|
import {
|
|
466123
466880
|
copyFileSync as copyFileSync3,
|
|
466124
|
-
existsSync as
|
|
466881
|
+
existsSync as existsSync53,
|
|
466125
466882
|
mkdirSync as mkdirSync38,
|
|
466126
466883
|
readdirSync as readdirSync20,
|
|
466127
466884
|
readFileSync as readFileSync34,
|
|
@@ -466129,7 +466886,7 @@ import {
|
|
|
466129
466886
|
} from "node:fs";
|
|
466130
466887
|
import { join as join67 } from "node:path";
|
|
466131
466888
|
function readJsonl(path41) {
|
|
466132
|
-
if (!
|
|
466889
|
+
if (!existsSync53(path41))
|
|
466133
466890
|
return [];
|
|
466134
466891
|
return readFileSync34(path41, "utf8").split(`
|
|
466135
466892
|
`).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
@@ -466417,13 +467174,13 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
466417
467174
|
skipped: [],
|
|
466418
467175
|
dryRun: input.dryRun === true
|
|
466419
467176
|
};
|
|
466420
|
-
if (!
|
|
467177
|
+
if (!existsSync53(conversationsDir))
|
|
466421
467178
|
return result;
|
|
466422
467179
|
for (const name of readdirSync20(conversationsDir)) {
|
|
466423
467180
|
const conversationDir = join67(conversationsDir, name);
|
|
466424
467181
|
const messagesPath = join67(conversationDir, "messages.jsonl");
|
|
466425
467182
|
const manifestPath = join67(conversationDir, "manifest.json");
|
|
466426
|
-
const hasManifest =
|
|
467183
|
+
const hasManifest = existsSync53(manifestPath);
|
|
466427
467184
|
const existingManifest = hasManifest ? (() => {
|
|
466428
467185
|
try {
|
|
466429
467186
|
return JSON.parse(readFileSync34(manifestPath, "utf8"));
|
|
@@ -466467,7 +467224,7 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
466467
467224
|
copyFileSync3(messagesPath, backupPath);
|
|
466468
467225
|
const conversationPath = join67(conversationDir, "conversation.json");
|
|
466469
467226
|
let conversation;
|
|
466470
|
-
if (
|
|
467227
|
+
if (existsSync53(conversationPath)) {
|
|
466471
467228
|
try {
|
|
466472
467229
|
conversation = JSON.parse(readFileSync34(conversationPath, "utf8"));
|
|
466473
467230
|
} catch {
|
|
@@ -466661,7 +467418,7 @@ var init_memory_tokens = __esm(() => {
|
|
|
466661
467418
|
});
|
|
466662
467419
|
|
|
466663
467420
|
// src/cli/subcommands/memory.ts
|
|
466664
|
-
import { cpSync, existsSync as
|
|
467421
|
+
import { cpSync, existsSync as existsSync54, mkdirSync as mkdirSync39, rmSync as rmSync12, statSync as statSync17 } from "node:fs";
|
|
466665
467422
|
import { readdir as readdir13 } from "node:fs/promises";
|
|
466666
467423
|
import { dirname as dirname30, join as join68 } from "node:path";
|
|
466667
467424
|
import { parseArgs as parseArgs10 } from "node:util";
|
|
@@ -466723,7 +467480,7 @@ function formatBackupTimestamp(date6 = new Date) {
|
|
|
466723
467480
|
}
|
|
466724
467481
|
async function listBackups(agentId) {
|
|
466725
467482
|
const agentRoot = getAgentRoot(agentId);
|
|
466726
|
-
if (!
|
|
467483
|
+
if (!existsSync54(agentRoot)) {
|
|
466727
467484
|
return [];
|
|
466728
467485
|
}
|
|
466729
467486
|
const entries = await readdir13(agentRoot, { withFileTypes: true });
|
|
@@ -466826,14 +467583,14 @@ async function runMemorySubcommand(argv) {
|
|
|
466826
467583
|
}
|
|
466827
467584
|
if (action3 === "backup") {
|
|
466828
467585
|
const root2 = getMemoryRoot(agentId);
|
|
466829
|
-
if (!
|
|
467586
|
+
if (!existsSync54(root2)) {
|
|
466830
467587
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
466831
467588
|
return 1;
|
|
466832
467589
|
}
|
|
466833
467590
|
const agentRoot = getAgentRoot(agentId);
|
|
466834
467591
|
const backupName = `memory-backup-${formatBackupTimestamp()}`;
|
|
466835
467592
|
const backupPath = join68(agentRoot, backupName);
|
|
466836
|
-
if (
|
|
467593
|
+
if (existsSync54(backupPath)) {
|
|
466837
467594
|
console.error(`Backup already exists at ${backupPath}`);
|
|
466838
467595
|
return 1;
|
|
466839
467596
|
}
|
|
@@ -466857,7 +467614,7 @@ async function runMemorySubcommand(argv) {
|
|
|
466857
467614
|
return 1;
|
|
466858
467615
|
}
|
|
466859
467616
|
const backupPath = resolveBackupPath(agentId, from);
|
|
466860
|
-
if (!
|
|
467617
|
+
if (!existsSync54(backupPath)) {
|
|
466861
467618
|
console.error(`Backup not found: ${backupPath}`);
|
|
466862
467619
|
return 1;
|
|
466863
467620
|
}
|
|
@@ -466879,11 +467636,11 @@ async function runMemorySubcommand(argv) {
|
|
|
466879
467636
|
return 1;
|
|
466880
467637
|
}
|
|
466881
467638
|
const root2 = getMemoryRoot(agentId);
|
|
466882
|
-
if (!
|
|
467639
|
+
if (!existsSync54(root2)) {
|
|
466883
467640
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
466884
467641
|
return 1;
|
|
466885
467642
|
}
|
|
466886
|
-
if (
|
|
467643
|
+
if (existsSync54(out)) {
|
|
466887
467644
|
const stat15 = statSync17(out);
|
|
466888
467645
|
if (stat15.isDirectory()) {
|
|
466889
467646
|
const contents = await readdir13(out);
|
|
@@ -466931,10 +467688,10 @@ var init_memory7 = __esm(() => {
|
|
|
466931
467688
|
});
|
|
466932
467689
|
|
|
466933
467690
|
// src/backend/local/transcript-search.ts
|
|
466934
|
-
import { existsSync as
|
|
467691
|
+
import { existsSync as existsSync55, readdirSync as readdirSync21, readFileSync as readFileSync35, statSync as statSync18 } from "node:fs";
|
|
466935
467692
|
import { join as join69 } from "node:path";
|
|
466936
467693
|
function readJsonFile3(path41) {
|
|
466937
|
-
if (!
|
|
467694
|
+
if (!existsSync55(path41))
|
|
466938
467695
|
return;
|
|
466939
467696
|
try {
|
|
466940
467697
|
return JSON.parse(readFileSync35(path41, "utf8"));
|
|
@@ -466943,7 +467700,7 @@ function readJsonFile3(path41) {
|
|
|
466943
467700
|
}
|
|
466944
467701
|
}
|
|
466945
467702
|
function readJsonlFile2(path41) {
|
|
466946
|
-
if (!
|
|
467703
|
+
if (!existsSync55(path41))
|
|
466947
467704
|
return [];
|
|
466948
467705
|
try {
|
|
466949
467706
|
return readFileSync35(path41, "utf8").split(`
|
|
@@ -467179,7 +467936,7 @@ function collectConversationMessages(input) {
|
|
|
467179
467936
|
}
|
|
467180
467937
|
function conversationDirectories(storageDir) {
|
|
467181
467938
|
const conversationsDir = join69(storageDir, "conversations");
|
|
467182
|
-
if (!
|
|
467939
|
+
if (!existsSync55(conversationsDir))
|
|
467183
467940
|
return [];
|
|
467184
467941
|
try {
|
|
467185
467942
|
return readdirSync21(conversationsDir).map((entry) => join69(conversationsDir, entry)).filter((entryPath) => statSync18(entryPath).isDirectory());
|
|
@@ -467648,7 +468405,7 @@ import {
|
|
|
467648
468405
|
} from "node:child_process";
|
|
467649
468406
|
import {
|
|
467650
468407
|
copyFileSync as copyFileSync4,
|
|
467651
|
-
existsSync as
|
|
468408
|
+
existsSync as existsSync56,
|
|
467652
468409
|
lstatSync as lstatSync3,
|
|
467653
468410
|
mkdirSync as mkdirSync40,
|
|
467654
468411
|
mkdtempSync as mkdtempSync3,
|
|
@@ -467857,7 +468614,7 @@ function copyDependencyDirectoryFiltered(params) {
|
|
|
467857
468614
|
return copied;
|
|
467858
468615
|
}
|
|
467859
468616
|
function copyDependencyNodeModules(params) {
|
|
467860
|
-
if (!
|
|
468617
|
+
if (!existsSync56(params.sourceNodeModulesDirectory))
|
|
467861
468618
|
return;
|
|
467862
468619
|
copyDependencyDirectoryFiltered({
|
|
467863
468620
|
installedPackageName: params.installedPackageName,
|
|
@@ -467867,7 +468624,7 @@ function copyDependencyNodeModules(params) {
|
|
|
467867
468624
|
}
|
|
467868
468625
|
function copyPackageInternalNodeModules(params) {
|
|
467869
468626
|
const sourceNodeModulesDirectory = path41.join(params.packageDirectory, "node_modules");
|
|
467870
|
-
if (!
|
|
468627
|
+
if (!existsSync56(sourceNodeModulesDirectory))
|
|
467871
468628
|
return;
|
|
467872
468629
|
copyDependencyDirectoryFiltered({
|
|
467873
468630
|
sourceRoot: sourceNodeModulesDirectory,
|
|
@@ -467889,12 +468646,12 @@ function removeIfExists(targetPath) {
|
|
|
467889
468646
|
}
|
|
467890
468647
|
function restoreDestination(params) {
|
|
467891
468648
|
rmSync13(params.destinationRoot, { force: true, recursive: true });
|
|
467892
|
-
if (params.backupRoot &&
|
|
468649
|
+
if (params.backupRoot && existsSync56(params.backupRoot)) {
|
|
467893
468650
|
renameSync6(params.backupRoot, params.destinationRoot);
|
|
467894
468651
|
}
|
|
467895
468652
|
}
|
|
467896
468653
|
function restoreDestinationIfNeeded(params) {
|
|
467897
|
-
if (!params.backupRoot || !
|
|
468654
|
+
if (!params.backupRoot || !existsSync56(params.backupRoot)) {
|
|
467898
468655
|
rmSync13(params.destinationRoot, { force: true, recursive: true });
|
|
467899
468656
|
return;
|
|
467900
468657
|
}
|
|
@@ -467935,7 +468692,7 @@ function installPreparedManagedModPackage(params) {
|
|
|
467935
468692
|
targetPackageRoot: stagingRoot
|
|
467936
468693
|
});
|
|
467937
468694
|
}
|
|
467938
|
-
if (
|
|
468695
|
+
if (existsSync56(destinationRoot)) {
|
|
467939
468696
|
backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
|
|
467940
468697
|
rmSync13(backupRoot, { force: true, recursive: true });
|
|
467941
468698
|
renameSync6(destinationRoot, backupRoot);
|
|
@@ -468218,7 +468975,7 @@ function hasRuntimeDependencies(packageJson) {
|
|
|
468218
468975
|
}
|
|
468219
468976
|
function readPackageJsonIfExists(packageDirectory) {
|
|
468220
468977
|
const packageJsonPath = path41.join(packageDirectory, "package.json");
|
|
468221
|
-
if (!
|
|
468978
|
+
if (!existsSync56(packageJsonPath))
|
|
468222
468979
|
return null;
|
|
468223
468980
|
return readPackageJson(packageJsonPath);
|
|
468224
468981
|
}
|
|
@@ -468232,7 +468989,7 @@ function isRegularModFile(filePath) {
|
|
|
468232
468989
|
}
|
|
468233
468990
|
function inferCompatibilityModEntries(packageDirectory) {
|
|
468234
468991
|
const modsDirectory = path41.join(packageDirectory, "mods");
|
|
468235
|
-
if (
|
|
468992
|
+
if (existsSync56(modsDirectory)) {
|
|
468236
468993
|
const stats = lstatSync3(modsDirectory);
|
|
468237
468994
|
if (stats.isSymbolicLink()) {
|
|
468238
468995
|
throw new Error(`Package mods directory must not be a symlink: mods`);
|
|
@@ -468507,7 +469264,7 @@ var init_package_installer = __esm(() => {
|
|
|
468507
469264
|
// src/mods/package-scaffolder.ts
|
|
468508
469265
|
import {
|
|
468509
469266
|
copyFileSync as copyFileSync5,
|
|
468510
|
-
existsSync as
|
|
469267
|
+
existsSync as existsSync57,
|
|
468511
469268
|
lstatSync as lstatSync4,
|
|
468512
469269
|
mkdirSync as mkdirSync41,
|
|
468513
469270
|
rmSync as rmSync14,
|
|
@@ -468600,7 +469357,7 @@ function scaffoldLocalModPackage(options3) {
|
|
|
468600
469357
|
const sourceFile = readSourceFile(options3.sourceFile);
|
|
468601
469358
|
const packageName = assertValidPackageName(options3.packageName);
|
|
468602
469359
|
const outputDirectory = path42.resolve(options3.outputDirectory ?? defaultOutputDirectory(sourceFile, packageName));
|
|
468603
|
-
if (
|
|
469360
|
+
if (existsSync57(outputDirectory)) {
|
|
468604
469361
|
throw new Error(`Output directory already exists: ${outputDirectory}`);
|
|
468605
469362
|
}
|
|
468606
469363
|
const modFileName = path42.basename(sourceFile);
|
|
@@ -469311,7 +470068,7 @@ async function runTurnViaListenerRuntime(params) {
|
|
|
469311
470068
|
const listener = await ensureListenerRuntime(params.onLog);
|
|
469312
470069
|
const scopedRuntime = getOrCreateScopedRuntime(listener, params.agentId, params.conversationId);
|
|
469313
470070
|
getOrCreateConversationPermissionModeStateRef(listener, params.agentId, params.conversationId).mode = "unrestricted";
|
|
469314
|
-
const socket = listener
|
|
470071
|
+
const socket = getOrCreateProcessTransport(listener);
|
|
469315
470072
|
const dispatchOptions = {
|
|
469316
470073
|
connectionId: listener.connectionId ?? "openai-api",
|
|
469317
470074
|
wsUrl: "",
|
|
@@ -469323,10 +470080,7 @@ async function runTurnViaListenerRuntime(params) {
|
|
|
469323
470080
|
params.onLog?.(`OpenAI-compat turn error: ${error54.message}`);
|
|
469324
470081
|
}
|
|
469325
470082
|
};
|
|
469326
|
-
const processQueuedTurn =
|
|
469327
|
-
const queuedScope = getOrCreateScopedRuntime(listener, queuedTurn.agentId, queuedTurn.conversationId);
|
|
469328
|
-
await handleIncomingMessage(queuedTurn, socket, queuedScope, undefined, dispatchOptions.connectionId, dequeuedBatch.batchId);
|
|
469329
|
-
};
|
|
470083
|
+
const processQueuedTurn = createConnectionTurnProcessor(listener);
|
|
469330
470084
|
return await new Promise((resolve32) => {
|
|
469331
470085
|
let text2 = "";
|
|
469332
470086
|
let usage = {
|
|
@@ -469437,7 +470191,7 @@ async function runTurnViaListenerRuntime(params) {
|
|
|
469437
470191
|
socket,
|
|
469438
470192
|
options: dispatchOptions,
|
|
469439
470193
|
processQueuedTurn,
|
|
469440
|
-
processIncomingMessage: handleIncomingMessage,
|
|
470194
|
+
processIncomingMessage: (incoming2, incomingSocket, incomingRuntime, onStatusChange, _connectionId, batchId) => handleIncomingMessage(incoming2, incomingSocket, incomingRuntime, onStatusChange, undefined, batchId),
|
|
469441
470195
|
trackListenerError: (errorType, error54) => {
|
|
469442
470196
|
params.onLog?.(`OpenAI-compat listener error (${errorType}): ${error54 instanceof Error ? error54.message : String(error54)}`);
|
|
469443
470197
|
}
|
|
@@ -469447,14 +470201,15 @@ async function runTurnViaListenerRuntime(params) {
|
|
|
469447
470201
|
}
|
|
469448
470202
|
});
|
|
469449
470203
|
}
|
|
469450
|
-
var runTurnImpl, OPENAI_TURN_TIMEOUT_MS,
|
|
470204
|
+
var runTurnImpl, OPENAI_TURN_TIMEOUT_MS, bridgeRuntimeStart = null, bridgeOwnedRuntime = null;
|
|
469451
470205
|
var init_app_server_openai_turn = __esm(async () => {
|
|
469452
470206
|
init_settings_manager();
|
|
470207
|
+
init_connection();
|
|
469453
470208
|
init_permission_mode();
|
|
469454
470209
|
init_runtime6();
|
|
469455
|
-
init_transport();
|
|
469456
470210
|
init_turn_observers();
|
|
469457
470211
|
await __promiseAll([
|
|
470212
|
+
init_connection_lifecycle(),
|
|
469458
470213
|
init_conversation_runtime(),
|
|
469459
470214
|
init_inbound_dispatch(),
|
|
469460
470215
|
init_lifecycle(),
|
|
@@ -469462,7 +470217,6 @@ var init_app_server_openai_turn = __esm(async () => {
|
|
|
469462
470217
|
]);
|
|
469463
470218
|
runTurnImpl = runTurnViaListenerRuntime;
|
|
469464
470219
|
OPENAI_TURN_TIMEOUT_MS = 15 * 60 * 1000;
|
|
469465
|
-
bridgeTransport = new LocalListenerTransport;
|
|
469466
470220
|
});
|
|
469467
470221
|
|
|
469468
470222
|
// src/websocket/app-server-openai.ts
|
|
@@ -469470,7 +470224,7 @@ import { randomUUID as randomUUID28 } from "node:crypto";
|
|
|
469470
470224
|
function isOpenAiCompatPath(pathname) {
|
|
469471
470225
|
return pathname === MODELS_PATH || pathname === CHAT_COMPLETIONS_PATH;
|
|
469472
470226
|
}
|
|
469473
|
-
function
|
|
470227
|
+
function sendJson(response, statusCode2, body3) {
|
|
469474
470228
|
const payload = JSON.stringify(body3);
|
|
469475
470229
|
response.writeHead(statusCode2, {
|
|
469476
470230
|
"content-type": "application/json",
|
|
@@ -469479,7 +470233,7 @@ function sendJson2(response, statusCode2, body3) {
|
|
|
469479
470233
|
response.end(payload);
|
|
469480
470234
|
}
|
|
469481
470235
|
function sendOpenAiError(response, statusCode2, message, type3, code2 = null) {
|
|
469482
|
-
|
|
470236
|
+
sendJson(response, statusCode2, {
|
|
469483
470237
|
error: { message, type: type3, param: null, code: code2 }
|
|
469484
470238
|
});
|
|
469485
470239
|
}
|
|
@@ -469608,7 +470362,7 @@ async function handleListModels(response) {
|
|
|
469608
470362
|
created: toModelCreatedTimestamp(agent2.created_at),
|
|
469609
470363
|
owned_by: "letta"
|
|
469610
470364
|
}));
|
|
469611
|
-
|
|
470365
|
+
sendJson(response, 200, { object: "list", data });
|
|
469612
470366
|
}
|
|
469613
470367
|
async function resolveAgentForModel(model) {
|
|
469614
470368
|
const agents = await listAgentEntries();
|
|
@@ -469886,7 +470640,7 @@ async function handleChatCompletions(request, response, options3) {
|
|
|
469886
470640
|
sendOpenAiError(response, 500, streamError, "server_error");
|
|
469887
470641
|
return;
|
|
469888
470642
|
}
|
|
469889
|
-
|
|
470643
|
+
sendJson(response, 200, {
|
|
469890
470644
|
id: completionId,
|
|
469891
470645
|
object: "chat.completion",
|
|
469892
470646
|
created,
|
|
@@ -469956,10 +470710,9 @@ function getRequiredAddressInfo(server2) {
|
|
|
469956
470710
|
}
|
|
469957
470711
|
return address;
|
|
469958
470712
|
}
|
|
469959
|
-
function
|
|
470713
|
+
function getWebSocketUrl(baseUrl, path43) {
|
|
469960
470714
|
const url2 = new URL(baseUrl);
|
|
469961
470715
|
url2.pathname = path43;
|
|
469962
|
-
url2.searchParams.set("channel", channel);
|
|
469963
470716
|
return url2.toString();
|
|
469964
470717
|
}
|
|
469965
470718
|
function closeSocket(socket, code2 = 1001, reason = "closing") {
|
|
@@ -469984,35 +470737,6 @@ Content-Length: 0\r
|
|
|
469984
470737
|
function getRequestUrl(request, host) {
|
|
469985
470738
|
return new URL(request.url ?? "/", `http://${request.headers.host ?? host}`);
|
|
469986
470739
|
}
|
|
469987
|
-
function getRequestChannel(url2) {
|
|
469988
|
-
const channel = url2.searchParams.get("channel");
|
|
469989
|
-
if (channel === null || channel === "" || channel === "control") {
|
|
469990
|
-
return "control";
|
|
469991
|
-
}
|
|
469992
|
-
if (channel === "stream") {
|
|
469993
|
-
return "stream";
|
|
469994
|
-
}
|
|
469995
|
-
return null;
|
|
469996
|
-
}
|
|
469997
|
-
function attachStreamSocket(activeSession, socket) {
|
|
469998
|
-
if (activeSession.streamSocket) {
|
|
469999
|
-
closeSocket(socket, 1008, "stream channel already connected");
|
|
470000
|
-
return;
|
|
470001
|
-
}
|
|
470002
|
-
activeSession.streamSocket = socket;
|
|
470003
|
-
activeSession.runtime.streamSocket = socket;
|
|
470004
|
-
activeSession.runtime.streamTransport = socket;
|
|
470005
|
-
socket.on("close", () => {
|
|
470006
|
-
if (activeSession.streamSocket === socket) {
|
|
470007
|
-
activeSession.streamSocket = null;
|
|
470008
|
-
}
|
|
470009
|
-
if (activeSession.runtime.streamSocket === socket) {
|
|
470010
|
-
activeSession.runtime.streamSocket = null;
|
|
470011
|
-
activeSession.runtime.streamTransport = null;
|
|
470012
|
-
terminateSocket(activeSession.controlSocket);
|
|
470013
|
-
}
|
|
470014
|
-
});
|
|
470015
|
-
}
|
|
470016
470740
|
function parseAppServerListenUrl(listen = DEFAULT_LISTEN_URL) {
|
|
470017
470741
|
let url2;
|
|
470018
470742
|
try {
|
|
@@ -470033,46 +470757,6 @@ function parseAppServerListenUrl(listen = DEFAULT_LISTEN_URL) {
|
|
|
470033
470757
|
const path43 = url2.pathname === "/" ? DEFAULT_WS_PATH : url2.pathname;
|
|
470034
470758
|
return { host: normalizeListenHost(url2.hostname), port, path: path43 };
|
|
470035
470759
|
}
|
|
470036
|
-
async function startControlSession(params) {
|
|
470037
|
-
const existingRuntime = getActiveRuntime();
|
|
470038
|
-
if (existingRuntime) {
|
|
470039
|
-
stopRuntime(existingRuntime, true);
|
|
470040
|
-
setActiveRuntime(null);
|
|
470041
|
-
}
|
|
470042
|
-
const runtime = createRuntime();
|
|
470043
|
-
runtime.onWsEvent = undefined;
|
|
470044
|
-
runtime.connectionId = `app-server-${crypto.randomUUID()}`;
|
|
470045
|
-
runtime.connectionName = params.connectionName;
|
|
470046
|
-
setActiveRuntime(runtime);
|
|
470047
|
-
telemetry.setSurface(getListenerTelemetrySurface());
|
|
470048
|
-
telemetry.init();
|
|
470049
|
-
const startupReady = (async () => {
|
|
470050
|
-
await reloadListenerModAdapter(runtime);
|
|
470051
|
-
await loadTools();
|
|
470052
|
-
})();
|
|
470053
|
-
const activeSession = {
|
|
470054
|
-
runtime,
|
|
470055
|
-
controlSocket: params.socket,
|
|
470056
|
-
streamSocket: params.streamSocket
|
|
470057
|
-
};
|
|
470058
|
-
params.onSessionCreated(activeSession);
|
|
470059
|
-
await attachOpenListenerSocket(runtime, params.socket, {
|
|
470060
|
-
connectionId: runtime.connectionId ?? "app-server",
|
|
470061
|
-
wsUrl: params.serverUrl,
|
|
470062
|
-
supportsSplitStatusChannels: true,
|
|
470063
|
-
deviceId: settingsManager.getOrCreateDeviceId(),
|
|
470064
|
-
connectionName: params.connectionName,
|
|
470065
|
-
onConnected: () => {},
|
|
470066
|
-
onDisconnected: params.onSessionClosed,
|
|
470067
|
-
onError: () => {}
|
|
470068
|
-
}, {
|
|
470069
|
-
streamSocket: params.streamSocket,
|
|
470070
|
-
startHeartbeat: false,
|
|
470071
|
-
startCronScheduler: true,
|
|
470072
|
-
startupReady
|
|
470073
|
-
});
|
|
470074
|
-
return activeSession;
|
|
470075
|
-
}
|
|
470076
470760
|
async function startAppServer(options3 = {}) {
|
|
470077
470761
|
await settingsManager.initialize();
|
|
470078
470762
|
const listen = parseAppServerListenUrl(options3.listen);
|
|
@@ -470081,72 +470765,60 @@ async function startAppServer(options3 = {}) {
|
|
|
470081
470765
|
throw new Error(`refusing to start non-loopback websocket listener ${listen.host}:${listen.port} without auth; configure \`--ws-auth capability-token\` or \`--ws-auth signed-bearer-token\``);
|
|
470082
470766
|
}
|
|
470083
470767
|
const wss = new WebSocketServer({ noServer: true });
|
|
470084
|
-
let activeSession = null;
|
|
470085
|
-
let pendingStreamSocket = null;
|
|
470086
|
-
let pendingStreamTimeout = null;
|
|
470087
470768
|
let resolvedInfo = null;
|
|
470088
|
-
|
|
470089
|
-
const
|
|
470090
|
-
|
|
470091
|
-
|
|
470092
|
-
|
|
470769
|
+
let nextConnectionOrdinal = 0;
|
|
470770
|
+
const runtime = createRuntime();
|
|
470771
|
+
runtime.onWsEvent = undefined;
|
|
470772
|
+
runtime.connectionId = "app-server";
|
|
470773
|
+
runtime.connectionName = options3.connectionName ?? hostname6();
|
|
470774
|
+
let startupReady = null;
|
|
470775
|
+
const getStartupReady = () => {
|
|
470776
|
+
if (startupReady) {
|
|
470777
|
+
return startupReady;
|
|
470093
470778
|
}
|
|
470094
|
-
const
|
|
470095
|
-
|
|
470096
|
-
|
|
470779
|
+
const attempt = (async () => {
|
|
470780
|
+
if (options3.initializeRuntime) {
|
|
470781
|
+
await options3.initializeRuntime(runtime);
|
|
470782
|
+
return;
|
|
470783
|
+
}
|
|
470784
|
+
await reloadListenerModAdapter(runtime);
|
|
470785
|
+
await loadTools();
|
|
470786
|
+
})();
|
|
470787
|
+
startupReady = attempt;
|
|
470788
|
+
attempt.catch(() => {
|
|
470789
|
+
if (startupReady === attempt) {
|
|
470790
|
+
startupReady = null;
|
|
470791
|
+
}
|
|
470792
|
+
});
|
|
470793
|
+
return startupReady;
|
|
470097
470794
|
};
|
|
470098
|
-
const
|
|
470795
|
+
const lastPongAtBySocket = new WeakMap;
|
|
470796
|
+
const handleWebSocketConnection = (socket) => {
|
|
470797
|
+
const connectionId = `app-server-${nextConnectionOrdinal}`;
|
|
470798
|
+
nextConnectionOrdinal += 1;
|
|
470099
470799
|
lastPongAtBySocket.set(socket, Date.now());
|
|
470100
470800
|
socket.on("pong", () => {
|
|
470101
|
-
|
|
470102
|
-
|
|
470103
|
-
if (channel === "stream") {
|
|
470104
|
-
if (activeSession) {
|
|
470105
|
-
attachStreamSocket(activeSession, socket);
|
|
470106
|
-
return;
|
|
470107
|
-
}
|
|
470108
|
-
if (pendingStreamSocket) {
|
|
470109
|
-
closeSocket(socket, 1008, "stream channel already pending");
|
|
470110
|
-
return;
|
|
470801
|
+
if (options3.shouldRecordPong?.(connectionId) !== false) {
|
|
470802
|
+
lastPongAtBySocket.set(socket, Date.now());
|
|
470111
470803
|
}
|
|
470112
|
-
|
|
470113
|
-
|
|
470114
|
-
|
|
470115
|
-
|
|
470116
|
-
|
|
470117
|
-
socket.on("close", () => {
|
|
470118
|
-
if (pendingStreamSocket === socket) {
|
|
470119
|
-
clearPendingStream();
|
|
470120
|
-
}
|
|
470121
|
-
});
|
|
470122
|
-
socket.on("error", (error54) => {
|
|
470123
|
-
options3.onLog?.(`App-server stream socket error: ${error54.message}`);
|
|
470124
|
-
});
|
|
470125
|
-
return;
|
|
470126
|
-
}
|
|
470127
|
-
if (activeSession) {
|
|
470128
|
-
closeSocket(socket, 1008, "control channel already connected");
|
|
470129
|
-
return;
|
|
470130
|
-
}
|
|
470131
|
-
const streamSocket = clearPendingStream();
|
|
470132
|
-
startControlSession({
|
|
470133
|
-
socket,
|
|
470134
|
-
streamSocket,
|
|
470804
|
+
});
|
|
470805
|
+
attachOpenListenerSocket(runtime, socket, {
|
|
470806
|
+
connectionId,
|
|
470807
|
+
wsUrl: resolvedInfo?.url ?? options3.listen ?? DEFAULT_LISTEN_URL,
|
|
470808
|
+
deviceId: settingsManager.getOrCreateDeviceId(),
|
|
470135
470809
|
connectionName: options3.connectionName ?? hostname6(),
|
|
470136
|
-
|
|
470137
|
-
|
|
470138
|
-
|
|
470139
|
-
|
|
470140
|
-
onSessionClosed: () => {
|
|
470141
|
-
activeSession = null;
|
|
470810
|
+
onConnected: () => {},
|
|
470811
|
+
onDisconnected: () => {},
|
|
470812
|
+
onError: (error54) => {
|
|
470813
|
+
options3.onLog?.(`App-server connection ${connectionId} failed: ${error54.message}`);
|
|
470142
470814
|
}
|
|
470815
|
+
}, {
|
|
470816
|
+
startHeartbeat: false,
|
|
470817
|
+
startCronScheduler: true,
|
|
470818
|
+
startupReady: getStartupReady()
|
|
470143
470819
|
}).catch((error54) => {
|
|
470144
|
-
|
|
470145
|
-
|
|
470146
|
-
}
|
|
470147
|
-
options3.onLog?.(`Failed to start app-server session: ${error54 instanceof Error ? error54.message : String(error54)}`);
|
|
470148
|
-
closeSocket(socket, 1011, "failed to start session");
|
|
470149
|
-
closeSocket(streamSocket, 1011, "failed to start session");
|
|
470820
|
+
options3.onLog?.(`Failed to start app-server connection: ${error54 instanceof Error ? error54.message : String(error54)}`);
|
|
470821
|
+
closeSocket(socket, 1011, "failed to start connection");
|
|
470150
470822
|
});
|
|
470151
470823
|
};
|
|
470152
470824
|
const server2 = createServer((request, response) => {
|
|
@@ -470198,9 +470870,9 @@ async function startAppServer(options3 = {}) {
|
|
|
470198
470870
|
rejectUpgrade(socket, 404, "Not Found");
|
|
470199
470871
|
return;
|
|
470200
470872
|
}
|
|
470201
|
-
|
|
470202
|
-
|
|
470203
|
-
rejectUpgrade(socket,
|
|
470873
|
+
if (requestUrl.searchParams.has("channel")) {
|
|
470874
|
+
options3.onLog?.("Rejecting legacy split-channel app-server client; upgrade to a one-socket client");
|
|
470875
|
+
rejectUpgrade(socket, 426, "Upgrade Required");
|
|
470204
470876
|
return;
|
|
470205
470877
|
}
|
|
470206
470878
|
const authError = authorizeUpgrade(request.headers, authPolicy);
|
|
@@ -470215,7 +470887,7 @@ async function startAppServer(options3 = {}) {
|
|
|
470215
470887
|
return;
|
|
470216
470888
|
}
|
|
470217
470889
|
wss.handleUpgrade(request, socket, head2, (websocket) => {
|
|
470218
|
-
handleWebSocketConnection(websocket
|
|
470890
|
+
handleWebSocketConnection(websocket);
|
|
470219
470891
|
});
|
|
470220
470892
|
});
|
|
470221
470893
|
const heartbeatIntervalMs = options3.heartbeatIntervalMs ?? APP_SERVER_HEARTBEAT_INTERVAL_MS;
|
|
@@ -470238,25 +470910,38 @@ async function startAppServer(options3 = {}) {
|
|
|
470238
470910
|
wss.on("close", () => {
|
|
470239
470911
|
clearInterval(heartbeatInterval);
|
|
470240
470912
|
});
|
|
470241
|
-
|
|
470242
|
-
|
|
470243
|
-
|
|
470244
|
-
|
|
470245
|
-
|
|
470246
|
-
|
|
470247
|
-
|
|
470248
|
-
|
|
470249
|
-
|
|
470250
|
-
|
|
470251
|
-
|
|
470252
|
-
|
|
470253
|
-
|
|
470913
|
+
try {
|
|
470914
|
+
await new Promise((resolve32, reject) => {
|
|
470915
|
+
const onError = (error54) => {
|
|
470916
|
+
server2.off("listening", onListening);
|
|
470917
|
+
reject(error54);
|
|
470918
|
+
};
|
|
470919
|
+
const onListening = () => {
|
|
470920
|
+
server2.off("error", onError);
|
|
470921
|
+
resolve32();
|
|
470922
|
+
};
|
|
470923
|
+
server2.once("error", onError);
|
|
470924
|
+
server2.once("listening", onListening);
|
|
470925
|
+
server2.listen(listen.port, listen.host);
|
|
470926
|
+
});
|
|
470927
|
+
} catch (error54) {
|
|
470928
|
+
clearInterval(heartbeatInterval);
|
|
470929
|
+
runtime.intentionallyClosed = true;
|
|
470930
|
+
throw error54;
|
|
470931
|
+
}
|
|
470932
|
+
const existingRuntime = getActiveRuntime();
|
|
470933
|
+
if (existingRuntime) {
|
|
470934
|
+
stopRuntime(existingRuntime, true);
|
|
470935
|
+
setActiveRuntime(null);
|
|
470936
|
+
}
|
|
470937
|
+
setActiveRuntime(runtime);
|
|
470938
|
+
telemetry.setSurface(getListenerTelemetrySurface());
|
|
470939
|
+
telemetry.init();
|
|
470254
470940
|
const address = getRequiredAddressInfo(server2);
|
|
470255
470941
|
const baseUrl = `ws://${listen.host}:${address.port}`;
|
|
470256
470942
|
resolvedInfo = {
|
|
470257
470943
|
url: baseUrl,
|
|
470258
|
-
controlUrl:
|
|
470259
|
-
streamUrl: getChannelUrl(baseUrl, listen.path, "stream")
|
|
470944
|
+
controlUrl: getWebSocketUrl(baseUrl, listen.path)
|
|
470260
470945
|
};
|
|
470261
470946
|
options3.onListening?.(resolvedInfo);
|
|
470262
470947
|
return {
|
|
@@ -470266,21 +470951,13 @@ async function startAppServer(options3 = {}) {
|
|
|
470266
470951
|
if (options3.openaiApi) {
|
|
470267
470952
|
closeOpenAiBridgeRuntime();
|
|
470268
470953
|
}
|
|
470269
|
-
const streamSocket = clearPendingStream();
|
|
470270
|
-
terminateSocket(streamSocket);
|
|
470271
|
-
if (activeSession) {
|
|
470272
|
-
const session = activeSession;
|
|
470273
|
-
activeSession = null;
|
|
470274
|
-
terminateSocket(session.streamSocket);
|
|
470275
|
-
terminateSocket(session.controlSocket);
|
|
470276
|
-
stopRuntime(session.runtime, true);
|
|
470277
|
-
if (getActiveRuntime() === session.runtime) {
|
|
470278
|
-
setActiveRuntime(null);
|
|
470279
|
-
}
|
|
470280
|
-
}
|
|
470281
470954
|
for (const client of wss.clients) {
|
|
470282
470955
|
terminateSocket(client);
|
|
470283
470956
|
}
|
|
470957
|
+
if (getActiveRuntime() === runtime) {
|
|
470958
|
+
stopRuntime(runtime, true);
|
|
470959
|
+
setActiveRuntime(null);
|
|
470960
|
+
}
|
|
470284
470961
|
await new Promise((resolve32, reject) => {
|
|
470285
470962
|
wss.close();
|
|
470286
470963
|
const timeout = setTimeout(resolve32, 1000);
|
|
@@ -470296,7 +470973,7 @@ async function startAppServer(options3 = {}) {
|
|
|
470296
470973
|
}
|
|
470297
470974
|
};
|
|
470298
470975
|
}
|
|
470299
|
-
var DEFAULT_LISTEN_URL = "ws://127.0.0.1:0", DEFAULT_WS_PATH = "/ws",
|
|
470976
|
+
var DEFAULT_LISTEN_URL = "ws://127.0.0.1:0", DEFAULT_WS_PATH = "/ws", APP_SERVER_HEARTBEAT_INTERVAL_MS = 30000, APP_SERVER_PONG_TIMEOUT_MS = 90000;
|
|
470300
470977
|
var init_app_server = __esm(async () => {
|
|
470301
470978
|
init_settings_manager();
|
|
470302
470979
|
init_telemetry();
|
|
@@ -470402,8 +471079,7 @@ async function runAppServerSubcommand(argv) {
|
|
|
470402
471079
|
openaiApi,
|
|
470403
471080
|
onListening: (info) => {
|
|
470404
471081
|
console.log(`Listening on ${info.url}`);
|
|
470405
|
-
console.log(`
|
|
470406
|
-
console.log(`Stream: ${info.streamUrl}`);
|
|
471082
|
+
console.log(`WebSocket: ${info.controlUrl}`);
|
|
470407
471083
|
if (openaiApi) {
|
|
470408
471084
|
const openaiBase = new URL(info.url);
|
|
470409
471085
|
openaiBase.protocol = "http:";
|
|
@@ -472207,7 +472883,7 @@ var init_AgentSelector = __esm(async () => {
|
|
|
472207
472883
|
// src/cli/subcommands/skills.ts
|
|
472208
472884
|
import {
|
|
472209
472885
|
cpSync as cpSync2,
|
|
472210
|
-
existsSync as
|
|
472886
|
+
existsSync as existsSync58,
|
|
472211
472887
|
mkdtempSync as mkdtempSync4,
|
|
472212
472888
|
readFileSync as readFileSync37,
|
|
472213
472889
|
rmSync as rmSync15,
|
|
@@ -472666,7 +473342,7 @@ async function installSkillDirectory(params) {
|
|
|
472666
473342
|
const sourceDir = resolve32(params.sourceDir);
|
|
472667
473343
|
const memoryDir = resolve32(params.memoryDir);
|
|
472668
473344
|
const skillMdPath = join71(sourceDir, "SKILL.md");
|
|
472669
|
-
if (!
|
|
473345
|
+
if (!existsSync58(skillMdPath)) {
|
|
472670
473346
|
throw new Error("No SKILL.md found in the skill directory.");
|
|
472671
473347
|
}
|
|
472672
473348
|
if (!statSync19(sourceDir).isDirectory()) {
|
|
@@ -472676,7 +473352,7 @@ async function installSkillDirectory(params) {
|
|
|
472676
473352
|
const skillsDir = join71(memoryDir, "skills");
|
|
472677
473353
|
const targetPath = join71(skillsDir, name);
|
|
472678
473354
|
assertInside(skillsDir, targetPath);
|
|
472679
|
-
if (
|
|
473355
|
+
if (existsSync58(targetPath)) {
|
|
472680
473356
|
if (!params.force) {
|
|
472681
473357
|
throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
|
|
472682
473358
|
}
|
|
@@ -472692,7 +473368,7 @@ async function installSkillDirectory(params) {
|
|
|
472692
473368
|
async function listSkillDirectories(params) {
|
|
472693
473369
|
const memoryDir = resolve32(params.memoryDir);
|
|
472694
473370
|
const skillsDir = join71(memoryDir, "skills");
|
|
472695
|
-
if (!
|
|
473371
|
+
if (!existsSync58(skillsDir))
|
|
472696
473372
|
return [];
|
|
472697
473373
|
const entries = await readdir14(skillsDir, { withFileTypes: true });
|
|
472698
473374
|
const skills = [];
|
|
@@ -472701,7 +473377,7 @@ async function listSkillDirectories(params) {
|
|
|
472701
473377
|
continue;
|
|
472702
473378
|
const skillDir = join71(skillsDir, entry.name);
|
|
472703
473379
|
const skillMdPath = join71(skillDir, "SKILL.md");
|
|
472704
|
-
if (!
|
|
473380
|
+
if (!existsSync58(skillMdPath))
|
|
472705
473381
|
continue;
|
|
472706
473382
|
let name = entry.name;
|
|
472707
473383
|
let description;
|
|
@@ -472725,7 +473401,7 @@ async function deleteSkillDirectory(params) {
|
|
|
472725
473401
|
const name = sanitizeSkillName(params.name);
|
|
472726
473402
|
const targetPath = join71(skillsDir, name);
|
|
472727
473403
|
assertInside(skillsDir, targetPath);
|
|
472728
|
-
if (!
|
|
473404
|
+
if (!existsSync58(targetPath)) {
|
|
472729
473405
|
throw new Error(`Skill "${name}" is not installed at ${targetPath}.`);
|
|
472730
473406
|
}
|
|
472731
473407
|
if (!statSync19(targetPath).isDirectory()) {
|
|
@@ -472774,7 +473450,7 @@ async function installSkill(specifier, agentId, force) {
|
|
|
472774
473450
|
tmpDir = downloaded.tmpDir;
|
|
472775
473451
|
const sourceDir = resolve32(downloaded.sourceDir);
|
|
472776
473452
|
assertInside(tmpDir, sourceDir);
|
|
472777
|
-
if (!
|
|
473453
|
+
if (!existsSync58(sourceDir)) {
|
|
472778
473454
|
const missingPath = source2.type === "git" ? source2.location.subdir ?? "." : source2.type === "direct-file" ? source2.location.url : source2.location.slug;
|
|
472779
473455
|
throw new Error(`Skill path not found: ${missingPath}`);
|
|
472780
473456
|
}
|
|
@@ -474073,11 +474749,11 @@ var exports_bootstrap_tools = {};
|
|
|
474073
474749
|
__export(exports_bootstrap_tools, {
|
|
474074
474750
|
bootstrapBaseToolsIfNeeded: () => bootstrapBaseToolsIfNeeded
|
|
474075
474751
|
});
|
|
474076
|
-
import { existsSync as
|
|
474752
|
+
import { existsSync as existsSync59, mkdirSync as mkdirSync42, writeFileSync as writeFileSync31 } from "node:fs";
|
|
474077
474753
|
import { homedir as homedir42 } from "node:os";
|
|
474078
474754
|
import { join as join75 } from "node:path";
|
|
474079
474755
|
async function bootstrapBaseToolsIfNeeded() {
|
|
474080
|
-
if (
|
|
474756
|
+
if (existsSync59(MARKER_PATH))
|
|
474081
474757
|
return;
|
|
474082
474758
|
debugLog("bootstrap", "No marker found, bootstrapping base tools...");
|
|
474083
474759
|
try {
|
|
@@ -474643,7 +475319,7 @@ var init_headless_tool_events = __esm(async () => {
|
|
|
474643
475319
|
});
|
|
474644
475320
|
|
|
474645
475321
|
// src/skills/builtin/creating-skills/scripts/validate-skill.ts
|
|
474646
|
-
import { existsSync as
|
|
475322
|
+
import { existsSync as existsSync60, readFileSync as readFileSync38 } from "node:fs";
|
|
474647
475323
|
import { basename as basename30, join as join77, resolve as resolve33 } from "node:path";
|
|
474648
475324
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
474649
475325
|
function parseQuotedScalar(value) {
|
|
@@ -474742,7 +475418,7 @@ function parseFrontmatter2(source2) {
|
|
|
474742
475418
|
}
|
|
474743
475419
|
function validateSkill(skillPath) {
|
|
474744
475420
|
const skillMdPath = join77(skillPath, "SKILL.md");
|
|
474745
|
-
if (!
|
|
475421
|
+
if (!existsSync60(skillMdPath)) {
|
|
474746
475422
|
return { valid: false, message: "SKILL.md not found" };
|
|
474747
475423
|
}
|
|
474748
475424
|
const content = readFileSync38(skillMdPath, "utf-8");
|
|
@@ -479871,7 +480547,7 @@ var init_queued_message_parts = __esm(() => {
|
|
|
479871
480547
|
|
|
479872
480548
|
// src/cli/helpers/reflection-arena-hf-upload.ts
|
|
479873
480549
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
479874
|
-
import { existsSync as
|
|
480550
|
+
import { existsSync as existsSync62 } from "node:fs";
|
|
479875
480551
|
import { appendFile as appendFile2, chmod as chmod2, mkdir as mkdir18, writeFile as writeFile20 } from "node:fs/promises";
|
|
479876
480552
|
import { homedir as homedir45 } from "node:os";
|
|
479877
480553
|
import { join as join79 } from "node:path";
|
|
@@ -479925,7 +480601,7 @@ async function writeGitAskpass(repoRoot) {
|
|
|
479925
480601
|
}
|
|
479926
480602
|
async function prepareHfRepo(env5) {
|
|
479927
480603
|
await mkdir18(HF_CACHE_ROOT, { recursive: true });
|
|
479928
|
-
if (!
|
|
480604
|
+
if (!existsSync62(join79(HF_REPO_DIR, ".git"))) {
|
|
479929
480605
|
await runGit6(HF_CACHE_ROOT, ["clone", "--depth", "1", HF_REPO_URL, HF_REPO_DIR], env5);
|
|
479930
480606
|
return HF_REPO_DIR;
|
|
479931
480607
|
}
|
|
@@ -481128,7 +481804,7 @@ __export(exports_terminal_keybinding_installer, {
|
|
|
481128
481804
|
});
|
|
481129
481805
|
import {
|
|
481130
481806
|
copyFileSync as copyFileSync6,
|
|
481131
|
-
existsSync as
|
|
481807
|
+
existsSync as existsSync63,
|
|
481132
481808
|
mkdirSync as mkdirSync44,
|
|
481133
481809
|
readFileSync as readFileSync40,
|
|
481134
481810
|
writeFileSync as writeFileSync33
|
|
@@ -481197,7 +481873,7 @@ function parseKeybindings(content) {
|
|
|
481197
481873
|
}
|
|
481198
481874
|
}
|
|
481199
481875
|
function keybindingExists(keybindingsPath) {
|
|
481200
|
-
if (!
|
|
481876
|
+
if (!existsSync63(keybindingsPath))
|
|
481201
481877
|
return false;
|
|
481202
481878
|
try {
|
|
481203
481879
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -481210,7 +481886,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
481210
481886
|
}
|
|
481211
481887
|
}
|
|
481212
481888
|
function createBackup(keybindingsPath) {
|
|
481213
|
-
if (!
|
|
481889
|
+
if (!existsSync63(keybindingsPath))
|
|
481214
481890
|
return null;
|
|
481215
481891
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
481216
481892
|
try {
|
|
@@ -481226,12 +481902,12 @@ function installKeybinding(keybindingsPath) {
|
|
|
481226
481902
|
return { success: true, alreadyExists: true };
|
|
481227
481903
|
}
|
|
481228
481904
|
const parentDir = dirname34(keybindingsPath);
|
|
481229
|
-
if (!
|
|
481905
|
+
if (!existsSync63(parentDir)) {
|
|
481230
481906
|
mkdirSync44(parentDir, { recursive: true });
|
|
481231
481907
|
}
|
|
481232
481908
|
let keybindings = [];
|
|
481233
481909
|
let backupPath = null;
|
|
481234
|
-
if (
|
|
481910
|
+
if (existsSync63(keybindingsPath)) {
|
|
481235
481911
|
backupPath = createBackup(keybindingsPath);
|
|
481236
481912
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
481237
481913
|
const parsed = parseKeybindings(content);
|
|
@@ -481261,7 +481937,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
481261
481937
|
}
|
|
481262
481938
|
function removeKeybinding(keybindingsPath) {
|
|
481263
481939
|
try {
|
|
481264
|
-
if (!
|
|
481940
|
+
if (!existsSync63(keybindingsPath)) {
|
|
481265
481941
|
return { success: true };
|
|
481266
481942
|
}
|
|
481267
481943
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -481329,11 +482005,11 @@ function getWezTermConfigPath() {
|
|
|
481329
482005
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
481330
482006
|
if (xdgConfig) {
|
|
481331
482007
|
const xdgPath = join81(xdgConfig, "wezterm", "wezterm.lua");
|
|
481332
|
-
if (
|
|
482008
|
+
if (existsSync63(xdgPath))
|
|
481333
482009
|
return xdgPath;
|
|
481334
482010
|
}
|
|
481335
482011
|
const configPath = join81(homedir47(), ".config", "wezterm", "wezterm.lua");
|
|
481336
|
-
if (
|
|
482012
|
+
if (existsSync63(configPath))
|
|
481337
482013
|
return configPath;
|
|
481338
482014
|
return join81(homedir47(), ".wezterm.lua");
|
|
481339
482015
|
}
|
|
@@ -481438,7 +482114,7 @@ ${WEZTERM_DELETE_FIX}
|
|
|
481438
482114
|
`;
|
|
481439
482115
|
}
|
|
481440
482116
|
function wezTermDeleteFixExists(configPath) {
|
|
481441
|
-
if (!
|
|
482117
|
+
if (!existsSync63(configPath))
|
|
481442
482118
|
return false;
|
|
481443
482119
|
try {
|
|
481444
482120
|
const content = readFileSync40(configPath, { encoding: "utf-8" });
|
|
@@ -481455,14 +482131,14 @@ function installWezTermDeleteFix() {
|
|
|
481455
482131
|
}
|
|
481456
482132
|
let content = "";
|
|
481457
482133
|
let backupPath = null;
|
|
481458
|
-
if (
|
|
482134
|
+
if (existsSync63(configPath)) {
|
|
481459
482135
|
backupPath = `${configPath}.letta-backup`;
|
|
481460
482136
|
copyFileSync6(configPath, backupPath);
|
|
481461
482137
|
content = readFileSync40(configPath, { encoding: "utf-8" });
|
|
481462
482138
|
}
|
|
481463
482139
|
content = injectWezTermDeleteFix(content);
|
|
481464
482140
|
const parentDir = dirname34(configPath);
|
|
481465
|
-
if (!
|
|
482141
|
+
if (!existsSync63(parentDir)) {
|
|
481466
482142
|
mkdirSync44(parentDir, { recursive: true });
|
|
481467
482143
|
}
|
|
481468
482144
|
writeFileSync33(configPath, content, { encoding: "utf-8" });
|
|
@@ -483458,9 +484134,9 @@ function getHeaderText(fileEdit) {
|
|
|
483458
484134
|
const relPath = relative17(cwd2, fileEdit.filePath);
|
|
483459
484135
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
483460
484136
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
483461
|
-
const { existsSync:
|
|
484137
|
+
const { existsSync: existsSync64 } = __require("node:fs");
|
|
483462
484138
|
try {
|
|
483463
|
-
if (
|
|
484139
|
+
if (existsSync64(fileEdit.filePath)) {
|
|
483464
484140
|
return `Overwrite ${displayPath}?`;
|
|
483465
484141
|
}
|
|
483466
484142
|
} catch {}
|
|
@@ -492949,7 +493625,7 @@ var init_agents8 = __esm(() => {
|
|
|
492949
493625
|
// src/cli/commands/install-github-app.ts
|
|
492950
493626
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
492951
493627
|
import {
|
|
492952
|
-
existsSync as
|
|
493628
|
+
existsSync as existsSync64,
|
|
492953
493629
|
mkdirSync as mkdirSync45,
|
|
492954
493630
|
mkdtempSync as mkdtempSync5,
|
|
492955
493631
|
readFileSync as readFileSync41,
|
|
@@ -493191,12 +493867,12 @@ function runGit7(args, cwd2) {
|
|
|
493191
493867
|
}
|
|
493192
493868
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
493193
493869
|
const absolutePath = join83(repoDir, workflowPath);
|
|
493194
|
-
if (!
|
|
493870
|
+
if (!existsSync64(dirname35(absolutePath))) {
|
|
493195
493871
|
mkdirSync45(dirname35(absolutePath), { recursive: true });
|
|
493196
493872
|
}
|
|
493197
493873
|
const next = `${content.trimEnd()}
|
|
493198
493874
|
`;
|
|
493199
|
-
if (
|
|
493875
|
+
if (existsSync64(absolutePath)) {
|
|
493200
493876
|
const previous = readFileSync41(absolutePath, "utf8");
|
|
493201
493877
|
if (previous === next) {
|
|
493202
493878
|
return false;
|
|
@@ -497742,7 +498418,7 @@ __export(exports_generate_memory_viewer, {
|
|
|
497742
498418
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
497743
498419
|
});
|
|
497744
498420
|
import { execFile as execFileCb7 } from "node:child_process";
|
|
497745
|
-
import { chmodSync as chmodSync7, existsSync as
|
|
498421
|
+
import { chmodSync as chmodSync7, existsSync as existsSync65, mkdirSync as mkdirSync46, writeFileSync as writeFileSync35 } from "node:fs";
|
|
497746
498422
|
import { homedir as homedir50 } from "node:os";
|
|
497747
498423
|
import { join as join84 } from "node:path";
|
|
497748
498424
|
import { promisify as promisify17 } from "node:util";
|
|
@@ -498053,7 +498729,7 @@ ${m4.body}` : m4.subject;
|
|
|
498053
498729
|
async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
498054
498730
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
498055
498731
|
const repoDir = memoryRoot;
|
|
498056
|
-
if (!
|
|
498732
|
+
if (!existsSync65(join84(repoDir, ".git"))) {
|
|
498057
498733
|
throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
|
|
498058
498734
|
}
|
|
498059
498735
|
const data = await collectMemoryData(agentId, repoDir, memoryRoot, options3?.conversationId);
|
|
@@ -498063,7 +498739,7 @@ async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
|
498063
498739
|
data.context = applyContextUsageSnapshot(data.context, options3?.contextUsage);
|
|
498064
498740
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
498065
498741
|
const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
498066
|
-
if (!
|
|
498742
|
+
if (!existsSync65(VIEWERS_DIR)) {
|
|
498067
498743
|
mkdirSync46(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
498068
498744
|
}
|
|
498069
498745
|
try {
|
|
@@ -498099,7 +498775,7 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
498099
498775
|
});
|
|
498100
498776
|
|
|
498101
498777
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
498102
|
-
import { existsSync as
|
|
498778
|
+
import { existsSync as existsSync66 } from "node:fs";
|
|
498103
498779
|
import { join as join85 } from "node:path";
|
|
498104
498780
|
function renderTreePrefix(node) {
|
|
498105
498781
|
let prefix = "";
|
|
@@ -498128,8 +498804,8 @@ function MemfsTreeViewer({
|
|
|
498128
498804
|
const [status, setStatus] = import_react88.useState(null);
|
|
498129
498805
|
const statusTimerRef = import_react88.useRef(null);
|
|
498130
498806
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
498131
|
-
const memoryExists =
|
|
498132
|
-
const hasGitRepo = import_react88.useMemo(() =>
|
|
498807
|
+
const memoryExists = existsSync66(memoryRoot);
|
|
498808
|
+
const hasGitRepo = import_react88.useMemo(() => existsSync66(join85(memoryRoot, ".git")), [memoryRoot]);
|
|
498133
498809
|
function showStatus(msg, durationMs) {
|
|
498134
498810
|
if (statusTimerRef.current)
|
|
498135
498811
|
clearTimeout(statusTimerRef.current);
|
|
@@ -506021,9 +506697,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
506021
506697
|
const relPath = relative17(cwd2, filePath);
|
|
506022
506698
|
const displayPath2 = relPath.startsWith("..") ? filePath : relPath;
|
|
506023
506699
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
506024
|
-
const { existsSync:
|
|
506700
|
+
const { existsSync: existsSync67 } = __require("node:fs");
|
|
506025
506701
|
try {
|
|
506026
|
-
if (
|
|
506702
|
+
if (existsSync67(filePath)) {
|
|
506027
506703
|
return `Overwrite ${displayPath2}?`;
|
|
506028
506704
|
}
|
|
506029
506705
|
} catch {}
|
|
@@ -521363,7 +522039,7 @@ __export(exports_generate_diff_viewer, {
|
|
|
521363
522039
|
generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
|
|
521364
522040
|
});
|
|
521365
522041
|
import { execFile as execFileCb8 } from "node:child_process";
|
|
521366
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
522042
|
+
import { chmodSync as chmodSync8, existsSync as existsSync67, mkdirSync as mkdirSync47, writeFileSync as writeFileSync36 } from "node:fs";
|
|
521367
522043
|
import { homedir as homedir52 } from "node:os";
|
|
521368
522044
|
import { isAbsolute as isAbsolute27, join as join87, resolve as resolve37 } from "node:path";
|
|
521369
522045
|
import { promisify as promisify18 } from "node:util";
|
|
@@ -521584,7 +522260,7 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
521584
522260
|
};
|
|
521585
522261
|
const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
|
|
521586
522262
|
const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
521587
|
-
if (!
|
|
522263
|
+
if (!existsSync67(VIEWERS_DIR2)) {
|
|
521588
522264
|
mkdirSync47(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
521589
522265
|
}
|
|
521590
522266
|
try {
|
|
@@ -523643,12 +524319,12 @@ __export(exports_shell_aliases, {
|
|
|
523643
524319
|
expandAliases: () => expandAliases,
|
|
523644
524320
|
clearAliasCache: () => clearAliasCache
|
|
523645
524321
|
});
|
|
523646
|
-
import { existsSync as
|
|
524322
|
+
import { existsSync as existsSync68, readFileSync as readFileSync42 } from "node:fs";
|
|
523647
524323
|
import { homedir as homedir53 } from "node:os";
|
|
523648
524324
|
import { join as join88 } from "node:path";
|
|
523649
524325
|
function parseAliasesFromFile(filePath) {
|
|
523650
524326
|
const aliases = new Map;
|
|
523651
|
-
if (!
|
|
524327
|
+
if (!existsSync68(filePath)) {
|
|
523652
524328
|
return aliases;
|
|
523653
524329
|
}
|
|
523654
524330
|
try {
|
|
@@ -532012,7 +532688,7 @@ var init_conversation_switch_alert = __esm(() => {
|
|
|
532012
532688
|
|
|
532013
532689
|
// src/cli/app/use-submit-handler.ts
|
|
532014
532690
|
import { randomUUID as randomUUID37 } from "node:crypto";
|
|
532015
|
-
import { existsSync as
|
|
532691
|
+
import { existsSync as existsSync69, readFileSync as readFileSync43, renameSync as renameSync7, writeFileSync as writeFileSync37 } from "node:fs";
|
|
532016
532692
|
import { tmpdir as tmpdir12 } from "node:os";
|
|
532017
532693
|
import { join as join89 } from "node:path";
|
|
532018
532694
|
async function findCustomCommandByName(commandName) {
|
|
@@ -532712,7 +533388,7 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
532712
533388
|
join89(memoryRoot, "system", "persona.md"),
|
|
532713
533389
|
join89(memoryRoot, "memory", "system", "persona.md")
|
|
532714
533390
|
];
|
|
532715
|
-
const personaPath = personaCandidates.find((candidate) =>
|
|
533391
|
+
const personaPath = personaCandidates.find((candidate) => existsSync69(candidate));
|
|
532716
533392
|
if (personaPath) {
|
|
532717
533393
|
const personaContent = readFileSync43(personaPath, "utf-8");
|
|
532718
533394
|
setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
|
|
@@ -533592,7 +534268,7 @@ Path: ${memoryDir}`, true);
|
|
|
533592
534268
|
setCommandRunning(true);
|
|
533593
534269
|
try {
|
|
533594
534270
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
533595
|
-
if (!
|
|
534271
|
+
if (!existsSync69(memoryDir)) {
|
|
533596
534272
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
533597
534273
|
return { submitted: true };
|
|
533598
534274
|
}
|
|
@@ -536626,9 +537302,9 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
536626
537302
|
(async () => {
|
|
536627
537303
|
try {
|
|
536628
537304
|
const { watch: watch3 } = await import("node:fs");
|
|
536629
|
-
const { existsSync:
|
|
537305
|
+
const { existsSync: existsSync70 } = await import("node:fs");
|
|
536630
537306
|
const memRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
536631
|
-
if (!
|
|
537307
|
+
if (!existsSync70(memRoot))
|
|
536632
537308
|
return;
|
|
536633
537309
|
watcher2 = watch3(memRoot, { recursive: true }, () => {});
|
|
536634
537310
|
memfsWatcherRef.current = watcher2;
|
|
@@ -538740,9 +539416,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
538740
539416
|
}
|
|
538741
539417
|
} else {
|
|
538742
539418
|
const { resolve: resolve39 } = await import("node:path");
|
|
538743
|
-
const { existsSync:
|
|
539419
|
+
const { existsSync: existsSync70 } = await import("node:fs");
|
|
538744
539420
|
const resolvedPath = resolve39(fromAfFile);
|
|
538745
|
-
if (!
|
|
539421
|
+
if (!existsSync70(resolvedPath)) {
|
|
538746
539422
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
538747
539423
|
process.exit(1);
|
|
538748
539424
|
}
|
|
@@ -541433,4 +542109,4 @@ function registerBunOAuthFlows() {
|
|
|
541433
542109
|
registerBunOAuthFlows();
|
|
541434
542110
|
await init_src5().then(() => exports_src2);
|
|
541435
542111
|
|
|
541436
|
-
//# debugId=
|
|
542112
|
+
//# debugId=DC9DDCD2BDAB4F1564756E2164756E21
|