@moxt-ai/mobius 0.0.17 → 0.0.19
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/acp/activity.d.ts.map +1 -1
- package/dist/acp/activity.js +4 -12
- package/dist/acp/activity.js.map +1 -1
- package/dist/acp/create-client.d.ts.map +1 -1
- package/dist/acp/create-client.js.map +1 -1
- package/dist/acp/native-session.d.ts.map +1 -1
- package/dist/acp/native-session.js +1 -3
- package/dist/acp/native-session.js.map +1 -1
- package/dist/acp/run-prompt.d.ts.map +1 -1
- package/dist/acp/run-prompt.js +1 -1
- package/dist/acp/run-prompt.js.map +1 -1
- package/dist/acp/session-capabilities.d.ts +5 -0
- package/dist/acp/session-capabilities.d.ts.map +1 -0
- package/dist/acp/session-capabilities.js +31 -0
- package/dist/acp/session-capabilities.js.map +1 -0
- package/dist/acp/session-config/grok-build-session-config.d.ts.map +1 -1
- package/dist/acp/session-config/grok-build-session-config.js +6 -11
- package/dist/acp/session-config/grok-build-session-config.js.map +1 -1
- package/dist/acp/session-config/session-config-protocol.d.ts.map +1 -1
- package/dist/acp/session-config/session-config-protocol.js +4 -12
- package/dist/acp/session-config/session-config-protocol.js.map +1 -1
- package/dist/acp/session-config/session-config-registry.d.ts.map +1 -1
- package/dist/acp/session-config/session-config-registry.js +2 -4
- package/dist/acp/session-config/session-config-registry.js.map +1 -1
- package/dist/acp/session-history.d.ts.map +1 -1
- package/dist/acp/session-history.js +7 -8
- package/dist/acp/session-history.js.map +1 -1
- package/dist/acp/session-manager.d.ts.map +1 -1
- package/dist/acp/session-manager.js +59 -96
- package/dist/acp/session-manager.js.map +1 -1
- package/dist/acp/session-store.d.ts.map +1 -1
- package/dist/acp/session-store.js +12 -24
- package/dist/acp/session-store.js.map +1 -1
- package/dist/agent-catalog/acp-readiness-probe.d.ts +7 -1
- package/dist/agent-catalog/acp-readiness-probe.d.ts.map +1 -1
- package/dist/agent-catalog/acp-readiness-probe.js +13 -3
- package/dist/agent-catalog/acp-readiness-probe.js.map +1 -1
- package/dist/agent-catalog/agent-diagnostics.d.ts.map +1 -1
- package/dist/agent-catalog/agent-diagnostics.js.map +1 -1
- package/dist/agent-catalog/agent-discovery-context.d.ts.map +1 -1
- package/dist/agent-catalog/agent-discovery.d.ts +19 -9
- package/dist/agent-catalog/agent-discovery.d.ts.map +1 -1
- package/dist/agent-catalog/agent-discovery.js +32 -16
- package/dist/agent-catalog/agent-discovery.js.map +1 -1
- package/dist/agent-catalog/agent-probe-error.d.ts.map +1 -1
- package/dist/agent-catalog/agent-probe-error.js.map +1 -1
- package/dist/agent-catalog/agent-specification.d.ts +0 -1
- package/dist/agent-catalog/agent-specification.d.ts.map +1 -1
- package/dist/agent-catalog/agent-specification.js +2 -6
- package/dist/agent-catalog/agent-specification.js.map +1 -1
- package/dist/agent-catalog/agents/claude-code-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/claude-code-agent.js +1 -8
- package/dist/agent-catalog/agents/claude-code-agent.js.map +1 -1
- package/dist/agent-catalog/agents/codex-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/codex-agent.js.map +1 -1
- package/dist/agent-catalog/agents/cursor-cli-agent.d.ts +0 -1
- package/dist/agent-catalog/agents/cursor-cli-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/cursor-cli-agent.js +0 -1
- package/dist/agent-catalog/agents/cursor-cli-agent.js.map +1 -1
- package/dist/agent-catalog/agents/deepseek-harness-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/deepseek-harness-agent.js +4 -4
- package/dist/agent-catalog/agents/deepseek-harness-agent.js.map +1 -1
- package/dist/agent-catalog/agents/grok-build-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/grok-build-agent.js +4 -14
- package/dist/agent-catalog/agents/grok-build-agent.js.map +1 -1
- package/dist/agent-catalog/agents/opencode-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/opencode-agent.js +1 -1
- package/dist/agent-catalog/agents/opencode-agent.js.map +1 -1
- package/dist/agent-catalog/agents/pi-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/pi-agent.js +1 -1
- package/dist/agent-catalog/agents/pi-agent.js.map +1 -1
- package/dist/agent-catalog/agents/supported-agent-specifications.js.map +1 -1
- package/dist/agent-catalog/agents/verify-session-creation.d.ts.map +1 -1
- package/dist/agent-catalog/agents/verify-session-creation.js +1 -1
- package/dist/agent-catalog/agents/verify-session-creation.js.map +1 -1
- package/dist/agent-catalog/agents/workbuddy-agent.d.ts.map +1 -1
- package/dist/agent-catalog/agents/workbuddy-agent.js +3 -6
- package/dist/agent-catalog/agents/workbuddy-agent.js.map +1 -1
- package/dist/agent-catalog/discover-agent.d.ts.map +1 -1
- package/dist/agent-catalog/discover-agent.js +33 -29
- package/dist/agent-catalog/discover-agent.js.map +1 -1
- package/dist/agent-catalog/discover-local-agents.d.ts +0 -1
- package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
- package/dist/agent-catalog/discover-local-agents.js +1 -1
- package/dist/agent-catalog/discover-local-agents.js.map +1 -1
- package/dist/agent-catalog/executable-discovery.d.ts.map +1 -1
- package/dist/agent-catalog/executable-discovery.js.map +1 -1
- package/dist/agent-catalog/local-agent.d.ts +15 -2
- package/dist/agent-catalog/local-agent.d.ts.map +1 -1
- package/dist/agent-catalog/local-agent.js +21 -3
- package/dist/agent-catalog/local-agent.js.map +1 -1
- package/dist/agent-catalog/publish-agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog/publish-agent-catalog.js +5 -7
- package/dist/agent-catalog/publish-agent-catalog.js.map +1 -1
- package/dist/agent-installation/agent-installation-manager.d.ts.map +1 -1
- package/dist/agent-installation/agent-installation-manager.js +8 -7
- package/dist/agent-installation/agent-installation-manager.js.map +1 -1
- package/dist/agent-installation/deepseek-managed-package.d.ts.map +1 -1
- package/dist/agent-installation/deepseek-managed-package.js +1 -3
- package/dist/agent-installation/deepseek-managed-package.js.map +1 -1
- package/dist/agent-installation/fixed-installation-executor.d.ts +2 -3
- package/dist/agent-installation/fixed-installation-executor.d.ts.map +1 -1
- package/dist/agent-installation/fixed-installation-executor.js +47 -70
- package/dist/agent-installation/fixed-installation-executor.js.map +1 -1
- package/dist/agent-installation/grok-managed-package.d.ts.map +1 -1
- package/dist/agent-installation/grok-managed-package.js +2 -4
- package/dist/agent-installation/grok-managed-package.js.map +1 -1
- package/dist/agent-installation/managed-adapter-installer.d.ts.map +1 -1
- package/dist/agent-installation/managed-adapter-installer.js +3 -1
- package/dist/agent-installation/managed-adapter-installer.js.map +1 -1
- package/dist/agent-installation/managed-agent-archive.d.ts +2 -5
- package/dist/agent-installation/managed-agent-archive.d.ts.map +1 -1
- package/dist/agent-installation/managed-agent-archive.js +18 -20
- package/dist/agent-installation/managed-agent-archive.js.map +1 -1
- package/dist/agent-installation/managed-npm-package.d.ts.map +1 -1
- package/dist/agent-installation/managed-npm-package.js +8 -13
- package/dist/agent-installation/managed-npm-package.js.map +1 -1
- package/dist/agent-installation/opencode-managed-release.d.ts.map +1 -1
- package/dist/agent-installation/opencode-managed-release.js.map +1 -1
- package/dist/agent-installation/pi-managed-packages.js.map +1 -1
- package/dist/agent-installation/verified-download.d.ts +0 -4
- package/dist/agent-installation/verified-download.d.ts.map +1 -1
- package/dist/agent-installation/verified-download.js +5 -5
- package/dist/agent-installation/verified-download.js.map +1 -1
- package/dist/agent-installation/workbuddy-managed-package.d.ts.map +1 -1
- package/dist/agent-installation/workbuddy-managed-package.js +1 -3
- package/dist/agent-installation/workbuddy-managed-package.js.map +1 -1
- package/dist/audit/audit-store.d.ts.map +1 -1
- package/dist/audit/audit-store.js +1 -3
- package/dist/audit/audit-store.js.map +1 -1
- package/dist/authorization/local-authorization-error.d.ts.map +1 -1
- package/dist/authorization/local-authorization-error.js.map +1 -1
- package/dist/authorization/workspace-directory.d.ts.map +1 -1
- package/dist/authorization/workspace-directory.js +30 -21
- package/dist/authorization/workspace-directory.js.map +1 -1
- package/dist/cli.js +1295 -3431
- package/dist/cli.js.map +4 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -2
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1238 -3355
- package/dist/index.js.map +4 -4
- package/dist/native-sessions/codex-history.d.ts.map +1 -1
- package/dist/native-sessions/codex-history.js +26 -17
- package/dist/native-sessions/codex-history.js.map +1 -1
- package/dist/native-sessions/service.d.ts.map +1 -1
- package/dist/native-sessions/service.js +46 -36
- package/dist/native-sessions/service.js.map +1 -1
- package/dist/pairing/pair-local-machine.d.ts.map +1 -1
- package/dist/pairing/pair-local-machine.js +16 -29
- package/dist/pairing/pair-local-machine.js.map +1 -1
- package/dist/process/executable.d.ts.map +1 -1
- package/dist/process/executable.js +16 -15
- package/dist/process/executable.js.map +1 -1
- package/dist/prompt-artifact-resolver.d.ts +13 -0
- package/dist/prompt-artifact-resolver.d.ts.map +1 -0
- package/dist/prompt-artifact-resolver.js +205 -0
- package/dist/prompt-artifact-resolver.js.map +1 -0
- package/dist/relay-connection/connect.d.ts.map +1 -1
- package/dist/relay-connection/connect.js +3 -1
- package/dist/relay-connection/connect.js.map +1 -1
- package/dist/relay-connection/liveness.d.ts.map +1 -1
- package/dist/relay-connection/liveness.js +1 -2
- package/dist/relay-connection/liveness.js.map +1 -1
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -1
- package/dist/relay-connection/session-event-outbox.js +7 -19
- package/dist/relay-connection/session-event-outbox.js.map +1 -1
- package/dist/relay-connection/timer.d.ts.map +1 -1
- package/dist/relay-connection/timer.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +202 -87
- package/dist/run-daemon.js.map +1 -1
- package/dist/storage/state-directory.d.ts.map +1 -1
- package/dist/storage/state-directory.js.map +1 -1
- package/package.json +55 -55
- package/dist/agent-installation/automatic-adapter-provisioner.d.ts +0 -19
- package/dist/agent-installation/automatic-adapter-provisioner.d.ts.map +0 -1
- package/dist/agent-installation/automatic-adapter-provisioner.js +0 -125
- package/dist/agent-installation/automatic-adapter-provisioner.js.map +0 -1
- package/dist/agent-installation/fixed-agent-install-recipe.d.ts +0 -20
- package/dist/agent-installation/fixed-agent-install-recipe.d.ts.map +0 -1
- package/dist/agent-installation/fixed-agent-install-recipe.js +0 -18
- package/dist/agent-installation/fixed-agent-install-recipe.js.map +0 -1
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts +0 -26
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +0 -1
- package/dist/agent-installation/fixed-agent-install-recipes.js +0 -301
- package/dist/agent-installation/fixed-agent-install-recipes.js.map +0 -1
- package/dist/agent-installation/grok-build-install-recipe.d.ts +0 -12
- package/dist/agent-installation/grok-build-install-recipe.d.ts.map +0 -1
- package/dist/agent-installation/grok-build-install-recipe.js +0 -102
- package/dist/agent-installation/grok-build-install-recipe.js.map +0 -1
- package/dist/agent-installation/workbuddy-install-recipe.d.ts +0 -12
- package/dist/agent-installation/workbuddy-install-recipe.d.ts.map +0 -1
- package/dist/agent-installation/workbuddy-install-recipe.js +0 -51
- package/dist/agent-installation/workbuddy-install-recipe.js.map +0 -1
package/dist/run-daemon.js
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
2
|
import { styleText } from "node:util";
|
|
3
3
|
import { AGENT_ACTIVITY_KIND, AGENT_INSTALL_CANCEL_KIND, AGENT_INSTALL_CANCELLED_KIND, AGENT_INSTALL_COMPLETED_KIND, AGENT_INSTALL_FAILED_KIND, AGENT_INSTALL_PROGRESS_KIND, AGENT_INSTALL_REQUEST_KIND, AGENT_INSTALL_STARTED_KIND, AGENT_MESSAGE_DELTA_KIND, decodeAgentInstallCancelCommand, decodeAgentInstallRequestCommand, decodeMessageKind, decodeNativeSessionCancel, decodeNativeSessionCommand, decodeRuntimeHeartbeatAckEvent, decodeRuntimeLivenessReadyEvent, decodeSessionCancelCommand, decodeSessionConfigureCommand, decodeSessionElicitationRespondCommand, decodeSessionEventAcknowledgement, decodeSessionPermissionRespondCommand, decodeSessionPrepareCommand, decodeSessionPromptCommand, decodeWorkspaceListCommand, encodeAgentActivityEvent, encodeAgentContentEvent, encodeAgentInstallCancelledEvent, encodeAgentInstallCompletedEvent, encodeAgentInstallFailedEvent, encodeAgentInstallProgressEvent, encodeAgentInstallStartedEvent, encodeAgentMessageDeltaEvent, encodeNativeSessionResult, encodeSessionCommandsUpdatedEvent, encodeSessionCompletedEvent, encodeSessionConfigUpdatedEvent, encodeSessionElicitationRequestedEvent, encodeSessionElicitationResolvedEvent, encodeSessionFailedEvent, encodeSessionInfoUpdatedEvent, encodeSessionOperationFailedEvent, encodeSessionPermissionRequestedEvent, encodeSessionPermissionResolvedEvent, encodeSessionReadyEvent, encodeSessionStartedEvent, encodeSessionUsageUpdatedEvent, encodeWorkspaceEntriesEvent, NATIVE_SESSION_CANCEL_KIND, NATIVE_SESSION_REQUEST_KIND, RUNTIME_HEARTBEAT_ACK_KIND, RUNTIME_LIVENESS_READY_KIND, SESSION_CANCEL_KIND, SESSION_COMPLETED_KIND, SESSION_CONFIGURE_KIND, SESSION_ELICITATION_RESPOND_KIND, SESSION_EVENT_ACK_KIND, SESSION_FAILED_KIND, SESSION_PERMISSION_RESPOND_KIND, SESSION_PREPARE_KIND, SESSION_PROMPT_KIND, SESSION_STARTED_KIND, WORKSPACE_LIST_KIND, } from "@moxt-ai/mobius-protocol";
|
|
4
|
-
import { WebSocket } from "undici";
|
|
5
|
-
import { AcpExecutionError, AcpSessionManager
|
|
4
|
+
import { fetch, WebSocket } from "undici";
|
|
5
|
+
import { AcpExecutionError, AcpSessionManager } from "./acp/session-manager.js";
|
|
6
6
|
import { SqliteAcpSessionStore } from "./acp/session-store.js";
|
|
7
7
|
import { supportedLocalAgentSpecifications } from "./agent-catalog/discover-local-agents.js";
|
|
8
8
|
import { LocalAgentCatalogError } from "./agent-catalog/local-agent.js";
|
|
9
9
|
import { publishAgentCatalog } from "./agent-catalog/publish-agent-catalog.js";
|
|
10
10
|
import { AgentInstallationManager, CancelledInstallation, FailedInstallation, RequestedInstallation, RunningInstallation, SucceededInstallation, } from "./agent-installation/agent-installation-manager.js";
|
|
11
|
-
import { AutomaticAdapterProvisioner } from "./agent-installation/automatic-adapter-provisioner.js";
|
|
12
11
|
import { FixedInstallationExecutor } from "./agent-installation/fixed-installation-executor.js";
|
|
13
|
-
import { ManagedAdapterInstaller } from "./agent-installation/managed-adapter-installer.js";
|
|
14
12
|
import { LocalAuthorizationError } from "./authorization/local-authorization-error.js";
|
|
15
13
|
import { WorkspaceDirectoryService } from "./authorization/workspace-directory.js";
|
|
16
14
|
import { NativeSessionService } from "./native-sessions/service.js";
|
|
15
|
+
import { environmentProxyDispatcher } from "./network/environment-proxy.js";
|
|
16
|
+
import { PromptArtifactError, resolvePromptArtifacts } from "./prompt-artifact-resolver.js";
|
|
17
17
|
import { connectRelay } from "./relay-connection/connect.js";
|
|
18
18
|
import { RelayConnectionLiveness } from "./relay-connection/liveness.js";
|
|
19
19
|
import { SessionEventOutbox } from "./relay-connection/session-event-outbox.js";
|
|
20
|
-
import { systemDaemonTimer
|
|
20
|
+
import { systemDaemonTimer } from "./relay-connection/timer.js";
|
|
21
21
|
import { readStateDirectory } from "./storage/state-directory.js";
|
|
22
22
|
const RELAY_RECONNECT_DELAY_MILLISECONDS = 500;
|
|
23
23
|
const RELAY_CONNECTION_REFRESH_MILLISECONDS = 20 * 60 * 1_000;
|
|
24
|
+
const ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS = 20_000;
|
|
25
|
+
const ACTIVE_TURN_RECONCILIATION_CLOSE_CODE = 4009;
|
|
24
26
|
class RelayConnectionRefreshState {
|
|
25
27
|
}
|
|
26
28
|
class ScheduledRelayConnectionRefreshState extends RelayConnectionRefreshState {
|
|
@@ -200,7 +202,7 @@ class DaemonInstallationObserver {
|
|
|
200
202
|
}));
|
|
201
203
|
return Promise.resolve();
|
|
202
204
|
}
|
|
203
|
-
throw new Error("Unsupported Agent installation state");
|
|
205
|
+
throw new Error("Unsupported Agent integration installation state");
|
|
204
206
|
};
|
|
205
207
|
}
|
|
206
208
|
class ResolvedSessionDirectories {
|
|
@@ -214,18 +216,21 @@ class ResolvedSessionDirectories {
|
|
|
214
216
|
}
|
|
215
217
|
}
|
|
216
218
|
class ActiveDaemonTurn {
|
|
219
|
+
attemptId;
|
|
217
220
|
command;
|
|
218
|
-
#
|
|
221
|
+
#controller;
|
|
222
|
+
#finished = Promise.withResolvers();
|
|
219
223
|
#cancellationRequested = false;
|
|
220
|
-
constructor(command,
|
|
224
|
+
constructor(command, attemptId) {
|
|
225
|
+
this.attemptId = attemptId;
|
|
221
226
|
this.command = command;
|
|
222
|
-
this.#
|
|
227
|
+
this.#controller = new AbortController();
|
|
223
228
|
}
|
|
224
|
-
|
|
225
|
-
this.#
|
|
229
|
+
abortDaemon = () => {
|
|
230
|
+
this.#controller.abort();
|
|
226
231
|
};
|
|
227
|
-
|
|
228
|
-
|
|
232
|
+
finish = () => this.#finished.resolve();
|
|
233
|
+
matches = (cancellation) => cancellation.commandId === this.command.commandId && cancellation.sessionId === this.command.sessionId;
|
|
229
234
|
requestCancellation = () => {
|
|
230
235
|
if (this.#cancellationRequested) {
|
|
231
236
|
return false;
|
|
@@ -234,23 +239,128 @@ class ActiveDaemonTurn {
|
|
|
234
239
|
return true;
|
|
235
240
|
};
|
|
236
241
|
get signal() {
|
|
237
|
-
return this.#
|
|
242
|
+
return this.#controller.signal;
|
|
243
|
+
}
|
|
244
|
+
get completion() {
|
|
245
|
+
return this.#finished.promise;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
class ActiveTurnReconciliationError extends Error {
|
|
249
|
+
code = "active_turn_reconciliation_failed";
|
|
250
|
+
constructor(message, options = {}) {
|
|
251
|
+
super(message, options);
|
|
252
|
+
this.name = "ActiveTurnReconciliationError";
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function activeTurnReconciliationEndpoint(config, turn) {
|
|
256
|
+
const endpoint = new URL(config.relayUrl);
|
|
257
|
+
endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
|
|
258
|
+
if (!endpoint.pathname.endsWith("/daemon")) {
|
|
259
|
+
throw new ActiveTurnReconciliationError("The Relay URL is invalid");
|
|
260
|
+
}
|
|
261
|
+
endpoint.pathname = `${endpoint.pathname.slice(0, -"/daemon".length)}/sessions/${encodeURIComponent(turn.command.sessionId)}/attempts/${encodeURIComponent(turn.attemptId)}/reconciliation`;
|
|
262
|
+
endpoint.searchParams.delete("liveness");
|
|
263
|
+
return endpoint;
|
|
264
|
+
}
|
|
265
|
+
async function reconcileActiveTurn(config, turn, signal) {
|
|
266
|
+
signal.throwIfAborted();
|
|
267
|
+
const timeoutSignal = AbortSignal.timeout(ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS);
|
|
268
|
+
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
269
|
+
let response;
|
|
270
|
+
try {
|
|
271
|
+
response = await fetch(activeTurnReconciliationEndpoint(config, turn), {
|
|
272
|
+
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
273
|
+
dispatcher: environmentProxyDispatcher,
|
|
274
|
+
headers: { "content-type": "application/json" },
|
|
275
|
+
method: "POST",
|
|
276
|
+
signal: requestSignal,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
if (signal.aborted) {
|
|
281
|
+
signal.throwIfAborted();
|
|
282
|
+
}
|
|
283
|
+
throw new ActiveTurnReconciliationError(timeoutSignal.aborted
|
|
284
|
+
? "The active Agent turn reconciliation timed out"
|
|
285
|
+
: "The active Agent turn could not be reconciled", { cause: error });
|
|
286
|
+
}
|
|
287
|
+
await response.body?.cancel();
|
|
288
|
+
if (!response.ok) {
|
|
289
|
+
throw new ActiveTurnReconciliationError(`The Relay rejected the active Agent turn reconciliation with status ${response.status.toString()}`);
|
|
238
290
|
}
|
|
239
291
|
}
|
|
292
|
+
async function reconcileActiveTurns(config, turns, signal) {
|
|
293
|
+
await Promise.all(turns.map(async (turn) => await reconcileActiveTurn(config, turn, signal)));
|
|
294
|
+
}
|
|
240
295
|
function send(socket, message) {
|
|
241
296
|
if (socket.readyState !== WebSocket.OPEN) {
|
|
242
297
|
throw new Error("Relay connection is not open");
|
|
243
298
|
}
|
|
244
299
|
socket.send(message);
|
|
245
300
|
}
|
|
246
|
-
function
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
301
|
+
function closeRelaySocket(socket, code, reason) {
|
|
302
|
+
try {
|
|
303
|
+
socket.close(code, reason);
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
console.error("Mobius daemon could not close the Relay WebSocket", error);
|
|
307
|
+
try {
|
|
308
|
+
socket.close();
|
|
309
|
+
}
|
|
310
|
+
catch (fallbackError) {
|
|
311
|
+
console.error("Mobius daemon could not release the Relay WebSocket", fallbackError);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
class DaemonSessionEventConnectionState {
|
|
316
|
+
}
|
|
317
|
+
class DisconnectedDaemonSessionEventState extends DaemonSessionEventConnectionState {
|
|
318
|
+
disconnect = () => this;
|
|
319
|
+
send = () => undefined;
|
|
320
|
+
}
|
|
321
|
+
class ConnectedDaemonSessionEventState extends DaemonSessionEventConnectionState {
|
|
322
|
+
#socket;
|
|
323
|
+
constructor(socket) {
|
|
324
|
+
super();
|
|
325
|
+
this.#socket = socket;
|
|
326
|
+
}
|
|
327
|
+
disconnect = (socket) => socket === this.#socket ? new DisconnectedDaemonSessionEventState() : this;
|
|
328
|
+
send = (message) => {
|
|
329
|
+
if (this.#socket.readyState === WebSocket.OPEN) {
|
|
330
|
+
try {
|
|
331
|
+
this.#socket.send(message);
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
// The durable outbox retains the event for the replacement connection.
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
class DaemonSessionEventPublisher {
|
|
340
|
+
#outbox;
|
|
341
|
+
#connection = new DisconnectedDaemonSessionEventState();
|
|
342
|
+
constructor(outbox) {
|
|
343
|
+
this.#outbox = outbox;
|
|
250
344
|
}
|
|
345
|
+
connect = (socket) => {
|
|
346
|
+
const connection = new ConnectedDaemonSessionEventState(socket);
|
|
347
|
+
this.#connection = connection;
|
|
348
|
+
for (const pending of this.#outbox.pending()) {
|
|
349
|
+
connection.send(pending);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
disconnect = (socket) => {
|
|
353
|
+
this.#connection = this.#connection.disconnect(socket);
|
|
354
|
+
};
|
|
355
|
+
recordAttempt = (sessionId, payload, attemptId) => {
|
|
356
|
+
this.#connection.send(this.#outbox.enqueue(sessionId, payload, attemptId));
|
|
357
|
+
};
|
|
358
|
+
recordRuntime = (sessionId, payload) => {
|
|
359
|
+
this.#connection.send(this.#outbox.enqueue(sessionId, payload));
|
|
360
|
+
};
|
|
251
361
|
}
|
|
252
|
-
function reportFailure(
|
|
253
|
-
|
|
362
|
+
function reportFailure(publisher, command, code, message, attemptId) {
|
|
363
|
+
publisher.recordAttempt(command.sessionId, encodeSessionFailedEvent({
|
|
254
364
|
code,
|
|
255
365
|
commandId: command.commandId,
|
|
256
366
|
kind: SESSION_FAILED_KIND,
|
|
@@ -261,7 +371,8 @@ function reportFailure(outbox, socket, command, code, message, attemptId = null)
|
|
|
261
371
|
function operationErrorCode(error) {
|
|
262
372
|
if (error instanceof AcpExecutionError ||
|
|
263
373
|
error instanceof LocalAuthorizationError ||
|
|
264
|
-
error instanceof LocalAgentCatalogError
|
|
374
|
+
error instanceof LocalAgentCatalogError ||
|
|
375
|
+
error instanceof PromptArtifactError) {
|
|
265
376
|
return error.code;
|
|
266
377
|
}
|
|
267
378
|
return "session_operation_failed";
|
|
@@ -269,7 +380,8 @@ function operationErrorCode(error) {
|
|
|
269
380
|
function operationErrorMessage(error) {
|
|
270
381
|
if (error instanceof AcpExecutionError ||
|
|
271
382
|
error instanceof LocalAuthorizationError ||
|
|
272
|
-
error instanceof LocalAgentCatalogError
|
|
383
|
+
error instanceof LocalAgentCatalogError ||
|
|
384
|
+
error instanceof PromptArtifactError) {
|
|
273
385
|
return error.message;
|
|
274
386
|
}
|
|
275
387
|
return "The local agent operation could not be completed";
|
|
@@ -327,7 +439,7 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
|
|
|
327
439
|
reportOperationFailure(socket, command.requestId, "", error);
|
|
328
440
|
}
|
|
329
441
|
}
|
|
330
|
-
async function executeSessionPrepare(
|
|
442
|
+
async function executeSessionPrepare(publisher, socket, command, config, directories, audit, sessions, signal) {
|
|
331
443
|
try {
|
|
332
444
|
const resolved = await resolveSessionDirectories(directories, config.bindingId, command.directoryId, command.additionalDirectoryIds, signal);
|
|
333
445
|
const agent = config.catalog.find(command.agentId);
|
|
@@ -344,7 +456,7 @@ async function executeSessionPrepare(outbox, socket, command, config, directorie
|
|
|
344
456
|
event: "session_prepared",
|
|
345
457
|
sessionId: command.sessionId,
|
|
346
458
|
});
|
|
347
|
-
|
|
459
|
+
publisher.recordRuntime(command.sessionId, encodeSessionReadyEvent({
|
|
348
460
|
additionalDirectories: resolved.additionalDirectoryEntries,
|
|
349
461
|
agentId: command.agentId,
|
|
350
462
|
agentName: prepared.agentName,
|
|
@@ -373,7 +485,7 @@ async function executeSessionPrepare(outbox, socket, command, config, directorie
|
|
|
373
485
|
reportOperationFailure(socket, command.requestId, command.sessionId, error);
|
|
374
486
|
}
|
|
375
487
|
}
|
|
376
|
-
async function executeSessionConfigure(
|
|
488
|
+
async function executeSessionConfigure(publisher, socket, command, config, directories, audit, sessions, signal) {
|
|
377
489
|
try {
|
|
378
490
|
const resolved = await resolveSessionDirectories(directories, config.bindingId, command.directoryId, command.additionalDirectoryIds, signal);
|
|
379
491
|
const configOptions = await sessions.configureSession({
|
|
@@ -393,7 +505,7 @@ async function executeSessionConfigure(outbox, socket, command, config, director
|
|
|
393
505
|
event: "session_configured",
|
|
394
506
|
sessionId: command.sessionId,
|
|
395
507
|
});
|
|
396
|
-
|
|
508
|
+
publisher.recordRuntime(command.sessionId, encodeSessionConfigUpdatedEvent({
|
|
397
509
|
configOptions,
|
|
398
510
|
kind: "session.config.updated",
|
|
399
511
|
requestId: command.requestId,
|
|
@@ -404,7 +516,7 @@ async function executeSessionConfigure(outbox, socket, command, config, director
|
|
|
404
516
|
reportOperationFailure(socket, command.requestId, command.sessionId, error);
|
|
405
517
|
}
|
|
406
518
|
}
|
|
407
|
-
async function executePrompt(outbox,
|
|
519
|
+
async function executePrompt(outbox, publisher, command, config, directories, audit, sessions, attemptId, signal) {
|
|
408
520
|
try {
|
|
409
521
|
const resolved = await resolveSessionDirectories(directories, config.bindingId, command.directoryId, command.additionalDirectoryIds, signal);
|
|
410
522
|
const agent = config.catalog.find(command.agentId);
|
|
@@ -414,20 +526,21 @@ async function executePrompt(outbox, socket, command, config, directories, audit
|
|
|
414
526
|
sessionId: command.sessionId,
|
|
415
527
|
});
|
|
416
528
|
outbox.transitionExecution(command.commandId, "running");
|
|
417
|
-
|
|
529
|
+
publisher.recordAttempt(command.sessionId, encodeSessionStartedEvent({
|
|
418
530
|
commandId: command.commandId,
|
|
419
531
|
kind: SESSION_STARTED_KIND,
|
|
420
532
|
attemptId,
|
|
421
533
|
sessionId: command.sessionId,
|
|
422
534
|
}), attemptId);
|
|
535
|
+
const attachments = await resolvePromptArtifacts(config, command, signal);
|
|
423
536
|
const result = await sessions.runPrompt({
|
|
424
537
|
additionalDirectories: resolved.additionalDirectories,
|
|
425
538
|
agent,
|
|
426
539
|
commandId: command.commandId,
|
|
427
540
|
cwd: resolved.cwd,
|
|
428
|
-
images:
|
|
541
|
+
images: attachments.images,
|
|
429
542
|
onActivity: (activity) => {
|
|
430
|
-
|
|
543
|
+
publisher.recordAttempt(command.sessionId, encodeAgentActivityEvent({
|
|
431
544
|
activityId: activity.activityId,
|
|
432
545
|
activityType: activity.activityType,
|
|
433
546
|
commandId: command.commandId,
|
|
@@ -447,7 +560,7 @@ async function executePrompt(outbox, socket, command, config, directories, audit
|
|
|
447
560
|
return Promise.resolve();
|
|
448
561
|
},
|
|
449
562
|
onText: (text) => {
|
|
450
|
-
|
|
563
|
+
publisher.recordAttempt(command.sessionId, encodeAgentMessageDeltaEvent({
|
|
451
564
|
commandId: command.commandId,
|
|
452
565
|
kind: AGENT_MESSAGE_DELTA_KIND,
|
|
453
566
|
sessionId: command.sessionId,
|
|
@@ -456,11 +569,11 @@ async function executePrompt(outbox, socket, command, config, directories, audit
|
|
|
456
569
|
return Promise.resolve();
|
|
457
570
|
},
|
|
458
571
|
prompt: command.prompt,
|
|
459
|
-
resources:
|
|
572
|
+
resources: attachments.resources,
|
|
460
573
|
sessionId: command.sessionId,
|
|
461
574
|
signal,
|
|
462
575
|
});
|
|
463
|
-
|
|
576
|
+
publisher.recordAttempt(command.sessionId, encodeSessionCompletedEvent({
|
|
464
577
|
commandId: command.commandId,
|
|
465
578
|
kind: SESSION_COMPLETED_KIND,
|
|
466
579
|
sessionId: command.sessionId,
|
|
@@ -469,9 +582,7 @@ async function executePrompt(outbox, socket, command, config, directories, audit
|
|
|
469
582
|
outbox.transitionExecution(command.commandId, result.stopReason === "cancelled" ? "cancelled" : "succeeded");
|
|
470
583
|
audit.record({
|
|
471
584
|
commandId: command.commandId,
|
|
472
|
-
event: result.stopReason === "cancelled"
|
|
473
|
-
? "session_cancelled"
|
|
474
|
-
: "session_completed",
|
|
585
|
+
event: result.stopReason === "cancelled" ? "session_cancelled" : "session_completed",
|
|
475
586
|
sessionId: command.sessionId,
|
|
476
587
|
});
|
|
477
588
|
}
|
|
@@ -482,7 +593,7 @@ async function executePrompt(outbox, socket, command, config, directories, audit
|
|
|
482
593
|
sessionId: command.sessionId,
|
|
483
594
|
});
|
|
484
595
|
const code = operationErrorCode(error);
|
|
485
|
-
reportFailure(
|
|
596
|
+
reportFailure(publisher, command, code === "session_operation_failed" ? "agent_execution_failed" : code, code === "session_operation_failed"
|
|
486
597
|
? "The local agent could not complete the request"
|
|
487
598
|
: operationErrorMessage(error), attemptId);
|
|
488
599
|
outbox.transitionExecution(command.commandId, "failed");
|
|
@@ -527,23 +638,15 @@ async function publishAgentCatalogUntilAvailable(config, signal, timer) {
|
|
|
527
638
|
}
|
|
528
639
|
}
|
|
529
640
|
}
|
|
530
|
-
async function runRelayConnection(config, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, onConnected, signal, timer) {
|
|
641
|
+
async function runRelayConnection(config, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, activeTurns, activeAttemptIds, onConnected, signal, timer) {
|
|
531
642
|
const relayUrl = new URL(config.relayUrl);
|
|
532
643
|
relayUrl.searchParams.set("liveness", "1");
|
|
533
644
|
const socket = await connectRelay(relayUrl, signal);
|
|
645
|
+
const reconnectingTurns = [...activeTurns.values()];
|
|
534
646
|
onConnected();
|
|
535
|
-
const activeTurns = new Map();
|
|
536
|
-
const activeAttemptIds = new Map();
|
|
537
647
|
const connectionController = new AbortController();
|
|
538
648
|
const nativeRequests = new Map();
|
|
539
|
-
const record = (sessionId, payload) => {
|
|
540
|
-
recordSessionEvent(outbox, socket, sessionId, payload, activeAttemptIds.get(sessionId) ?? null);
|
|
541
|
-
};
|
|
542
|
-
sessions.setObserver(new DaemonAcpObserver(record));
|
|
543
649
|
installationObserver.connect(socket);
|
|
544
|
-
for (const pending of outbox.pending()) {
|
|
545
|
-
send(socket, pending);
|
|
546
|
-
}
|
|
547
650
|
try {
|
|
548
651
|
await new Promise((resolve, reject) => {
|
|
549
652
|
let finished = false;
|
|
@@ -555,11 +658,8 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
555
658
|
socket.removeEventListener("error", handleError);
|
|
556
659
|
socket.removeEventListener("message", handleMessage);
|
|
557
660
|
installationObserver.disconnect(socket);
|
|
661
|
+
publisher.disconnect(socket);
|
|
558
662
|
connectionController.abort();
|
|
559
|
-
for (const turn of activeTurns.values()) {
|
|
560
|
-
turn.abortConnection();
|
|
561
|
-
}
|
|
562
|
-
activeTurns.clear();
|
|
563
663
|
};
|
|
564
664
|
const resolveConnection = () => {
|
|
565
665
|
if (finished) {
|
|
@@ -578,17 +678,17 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
578
678
|
reject(new Error("Relay WebSocket failed"));
|
|
579
679
|
};
|
|
580
680
|
const stop = () => {
|
|
581
|
-
socket
|
|
681
|
+
closeRelaySocket(socket, 1000, "Daemon stopped");
|
|
582
682
|
resolveConnection();
|
|
583
683
|
};
|
|
584
684
|
const refreshConnection = () => {
|
|
585
|
-
socket
|
|
685
|
+
closeRelaySocket(socket, 1000, "Refreshing idle relay connection");
|
|
586
686
|
resolveConnection();
|
|
587
687
|
};
|
|
588
688
|
const connectionLiveness = new RelayConnectionLiveness(timer, {
|
|
589
689
|
send: (message) => send(socket, message),
|
|
590
690
|
unresponsive: () => {
|
|
591
|
-
socket
|
|
691
|
+
closeRelaySocket(socket, 4001, "Relay liveness check timed out");
|
|
592
692
|
resolveConnection();
|
|
593
693
|
},
|
|
594
694
|
});
|
|
@@ -607,7 +707,7 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
607
707
|
const handleMessage = (event) => {
|
|
608
708
|
const encoded = event.data;
|
|
609
709
|
if (typeof encoded !== "string") {
|
|
610
|
-
socket
|
|
710
|
+
closeRelaySocket(socket, 4003, "Text message required");
|
|
611
711
|
rejectConnection();
|
|
612
712
|
return;
|
|
613
713
|
}
|
|
@@ -620,8 +720,9 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
620
720
|
if (kind === NATIVE_SESSION_CANCEL_KIND) {
|
|
621
721
|
const command = decodeNativeSessionCancel(encoded);
|
|
622
722
|
const pending = nativeRequests.get(command.requestId);
|
|
623
|
-
if (pending?.sessionId === command.sessionId)
|
|
723
|
+
if (pending?.sessionId === command.sessionId) {
|
|
624
724
|
pending.controller.abort(new AcpExecutionError("Native session operation cancelled", {}, "native_session_cancelled"));
|
|
725
|
+
}
|
|
625
726
|
return;
|
|
626
727
|
}
|
|
627
728
|
if (kind === NATIVE_SESSION_REQUEST_KIND) {
|
|
@@ -634,10 +735,7 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
634
735
|
return;
|
|
635
736
|
}
|
|
636
737
|
const controller = new AbortController();
|
|
637
|
-
const operationSignal = AbortSignal.any([
|
|
638
|
-
connectionController.signal,
|
|
639
|
-
controller.signal,
|
|
640
|
-
]);
|
|
738
|
+
const operationSignal = AbortSignal.any([connectionController.signal, controller.signal]);
|
|
641
739
|
const timeout = timer.schedule(() => controller.abort(new AcpExecutionError("Native session operation timed out", {}, "native_session_timeout")), 90_000);
|
|
642
740
|
const completion = (async () => {
|
|
643
741
|
try {
|
|
@@ -659,8 +757,9 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
659
757
|
}
|
|
660
758
|
operationSignal.throwIfAborted();
|
|
661
759
|
const result = await nativeSessions.execute(command, operationSignal);
|
|
662
|
-
if (socket.readyState === WebSocket.OPEN)
|
|
760
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
663
761
|
send(socket, encodeNativeSessionResult(result));
|
|
762
|
+
}
|
|
664
763
|
}
|
|
665
764
|
catch (error) {
|
|
666
765
|
const failure = operationSignal.aborted
|
|
@@ -712,9 +811,7 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
712
811
|
event: "session_cancellation_requested",
|
|
713
812
|
sessionId: cancellation.sessionId,
|
|
714
813
|
});
|
|
715
|
-
void sessions
|
|
716
|
-
.cancelPrompt(cancellation.sessionId)
|
|
717
|
-
.catch((error) => {
|
|
814
|
+
void sessions.cancelPrompt(cancellation.sessionId).catch((error) => {
|
|
718
815
|
console.error("Mobius daemon could not cancel the agent turn", error);
|
|
719
816
|
});
|
|
720
817
|
return;
|
|
@@ -726,12 +823,12 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
726
823
|
}
|
|
727
824
|
if (kind === SESSION_PREPARE_KIND) {
|
|
728
825
|
const command = decodeSessionPrepareCommand(encoded);
|
|
729
|
-
void executeSessionPrepare(
|
|
826
|
+
void executeSessionPrepare(publisher, socket, command, config, directories, audit, sessions, connectionController.signal);
|
|
730
827
|
return;
|
|
731
828
|
}
|
|
732
829
|
if (kind === SESSION_CONFIGURE_KIND) {
|
|
733
830
|
const command = decodeSessionConfigureCommand(encoded);
|
|
734
|
-
void executeSessionConfigure(
|
|
831
|
+
void executeSessionConfigure(publisher, socket, command, config, directories, audit, sessions, connectionController.signal);
|
|
735
832
|
return;
|
|
736
833
|
}
|
|
737
834
|
if (kind === SESSION_PERMISSION_RESPOND_KIND) {
|
|
@@ -768,18 +865,14 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
768
865
|
}
|
|
769
866
|
if (kind === AGENT_INSTALL_REQUEST_KIND) {
|
|
770
867
|
const command = decodeAgentInstallRequestCommand(encoded);
|
|
771
|
-
void installations
|
|
772
|
-
.
|
|
773
|
-
.catch((error) => {
|
|
774
|
-
console.error("Mobius Agent installation failed", error);
|
|
868
|
+
void installations.request(command, signal).catch((error) => {
|
|
869
|
+
console.error("Mobius Agent integration installation failed", error);
|
|
775
870
|
});
|
|
776
871
|
return;
|
|
777
872
|
}
|
|
778
873
|
if (kind === AGENT_INSTALL_CANCEL_KIND) {
|
|
779
874
|
const command = decodeAgentInstallCancelCommand(encoded);
|
|
780
|
-
void installations
|
|
781
|
-
.cancel(command.requestId)
|
|
782
|
-
.catch((error) => {
|
|
875
|
+
void installations.cancel(command.requestId).catch((error) => {
|
|
783
876
|
reportOperationFailure(socket, command.requestId, "", error);
|
|
784
877
|
});
|
|
785
878
|
return;
|
|
@@ -795,10 +888,10 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
795
888
|
if (receipt.kind === "duplicate") {
|
|
796
889
|
return;
|
|
797
890
|
}
|
|
798
|
-
const turn = new ActiveDaemonTurn(command,
|
|
891
|
+
const turn = new ActiveDaemonTurn(command, receipt.attemptId);
|
|
799
892
|
activeTurns.set(command.commandId, turn);
|
|
800
893
|
activeAttemptIds.set(command.sessionId, receipt.attemptId);
|
|
801
|
-
void executePrompt(outbox,
|
|
894
|
+
void executePrompt(outbox, publisher, command, config, directories, audit, sessions, receipt.attemptId, turn.signal)
|
|
802
895
|
.catch((error) => {
|
|
803
896
|
console.error("Mobius daemon turn failed", error);
|
|
804
897
|
})
|
|
@@ -807,18 +900,33 @@ async function runRelayConnection(config, directories, audit, sessions, installa
|
|
|
807
900
|
if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
|
|
808
901
|
activeAttemptIds.delete(command.sessionId);
|
|
809
902
|
}
|
|
903
|
+
turn.finish();
|
|
810
904
|
connectionRefresh.afterTurnFinished();
|
|
811
905
|
});
|
|
812
906
|
}
|
|
813
907
|
catch (error) {
|
|
814
908
|
console.error("Mobius daemon rejected a message", error);
|
|
815
|
-
socket
|
|
909
|
+
closeRelaySocket(socket, 4008, "Invalid protocol message");
|
|
816
910
|
rejectConnection();
|
|
817
911
|
}
|
|
818
912
|
};
|
|
819
913
|
socket.addEventListener("close", handleClose);
|
|
820
914
|
socket.addEventListener("error", handleError);
|
|
821
915
|
socket.addEventListener("message", handleMessage);
|
|
916
|
+
void reconcileActiveTurns(config, reconnectingTurns, connectionController.signal).then(() => {
|
|
917
|
+
if (finished) {
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
publisher.connect(socket);
|
|
921
|
+
void Promise.all(reconnectingTurns.map((turn) => turn.completion)).then(connectionRefresh.afterTurnFinished);
|
|
922
|
+
}, (error) => {
|
|
923
|
+
if (finished) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
console.error("Mobius daemon could not reconcile active Agent turns", error);
|
|
927
|
+
closeRelaySocket(socket, ACTIVE_TURN_RECONCILIATION_CLOSE_CODE, "Active Agent turn reconciliation failed");
|
|
928
|
+
rejectConnection();
|
|
929
|
+
});
|
|
822
930
|
if (signal.aborted) {
|
|
823
931
|
stop();
|
|
824
932
|
}
|
|
@@ -841,18 +949,20 @@ export async function runDaemon(config, audit, signal, timer = systemDaemonTimer
|
|
|
841
949
|
publishCatalog: async (installationSignal) => await publishAgentCatalog(config, installationSignal),
|
|
842
950
|
stateDirectory,
|
|
843
951
|
});
|
|
844
|
-
await new AutomaticAdapterProvisioner({
|
|
845
|
-
defaultWorkspace: config.defaultWorkspace,
|
|
846
|
-
audit: installationAudit,
|
|
847
|
-
catalog: config.catalog,
|
|
848
|
-
environment: process.env,
|
|
849
|
-
}, new ManagedAdapterInstaller({
|
|
850
|
-
environment: process.env,
|
|
851
|
-
stateDirectory,
|
|
852
|
-
}), specifications).prepare(signal);
|
|
853
952
|
const sessionStore = new SqliteAcpSessionStore(config.auditDatabasePath);
|
|
854
953
|
const outbox = new SessionEventOutbox(config.auditDatabasePath);
|
|
855
|
-
const
|
|
954
|
+
const publisher = new DaemonSessionEventPublisher(outbox);
|
|
955
|
+
const activeTurns = new Map();
|
|
956
|
+
const activeAttemptIds = new Map();
|
|
957
|
+
const recordSessionEvent = (sessionId, payload) => {
|
|
958
|
+
const attemptId = activeAttemptIds.get(sessionId);
|
|
959
|
+
if (attemptId === undefined) {
|
|
960
|
+
publisher.recordRuntime(sessionId, payload);
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
publisher.recordAttempt(sessionId, payload, attemptId);
|
|
964
|
+
};
|
|
965
|
+
const sessions = new AcpSessionManager(new DaemonAcpObserver(recordSessionEvent), sessionStore);
|
|
856
966
|
const directories = new WorkspaceDirectoryService(config.bindingId, config.defaultWorkspace);
|
|
857
967
|
const installationObserver = new DaemonInstallationObserver();
|
|
858
968
|
const nativeSessions = new NativeSessionService(config, directories, sessions, audit);
|
|
@@ -872,7 +982,7 @@ export async function runDaemon(config, audit, signal, timer = systemDaemonTimer
|
|
|
872
982
|
try {
|
|
873
983
|
while (!signal.aborted) {
|
|
874
984
|
try {
|
|
875
|
-
await runRelayConnection(config, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, announceConnection, signal, timer);
|
|
985
|
+
await runRelayConnection(config, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, activeTurns, activeAttemptIds, announceConnection, signal, timer);
|
|
876
986
|
retryAnnounced = false;
|
|
877
987
|
}
|
|
878
988
|
catch {
|
|
@@ -888,6 +998,11 @@ export async function runDaemon(config, audit, signal, timer = systemDaemonTimer
|
|
|
888
998
|
}
|
|
889
999
|
}
|
|
890
1000
|
finally {
|
|
1001
|
+
const turns = [...activeTurns.values()];
|
|
1002
|
+
for (const turn of turns) {
|
|
1003
|
+
turn.abortDaemon();
|
|
1004
|
+
}
|
|
1005
|
+
await Promise.all(turns.map((turn) => turn.completion));
|
|
891
1006
|
try {
|
|
892
1007
|
await catalogPublication;
|
|
893
1008
|
}
|