@moxt-ai/mobius 0.0.5 → 0.0.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/acp/activity.d.ts +7 -2
- package/dist/acp/activity.d.ts.map +1 -1
- package/dist/acp/activity.js +95 -7
- package/dist/acp/activity.js.map +1 -1
- package/dist/acp/native-session.d.ts +30 -0
- package/dist/acp/native-session.d.ts.map +1 -0
- package/dist/acp/native-session.js +25 -0
- package/dist/acp/native-session.js.map +1 -0
- package/dist/acp/session-history.d.ts +9 -0
- package/dist/acp/session-history.d.ts.map +1 -0
- package/dist/acp/session-history.js +69 -0
- package/dist/acp/session-history.js.map +1 -0
- package/dist/acp/session-manager.d.ts +16 -5
- package/dist/acp/session-manager.d.ts.map +1 -1
- package/dist/acp/session-manager.js +210 -25
- package/dist/acp/session-manager.js.map +1 -1
- package/dist/acp/session-store.d.ts +9 -0
- package/dist/acp/session-store.d.ts.map +1 -1
- package/dist/acp/session-store.js +43 -0
- package/dist/acp/session-store.js.map +1 -1
- package/dist/agent-catalog/discover-local-agents.d.ts +1 -1
- package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
- package/dist/agent-catalog/discover-local-agents.js +19 -30
- package/dist/agent-catalog/discover-local-agents.js.map +1 -1
- package/dist/agent-installation/automatic-adapter-provisioner.d.ts +1 -1
- package/dist/agent-installation/automatic-adapter-provisioner.d.ts.map +1 -1
- package/dist/agent-installation/automatic-adapter-provisioner.js +1 -1
- package/dist/agent-installation/automatic-adapter-provisioner.js.map +1 -1
- package/dist/agent-installation/fixed-installation-executor.d.ts +1 -1
- package/dist/agent-installation/fixed-installation-executor.d.ts.map +1 -1
- package/dist/agent-installation/fixed-installation-executor.js +9 -18
- package/dist/agent-installation/fixed-installation-executor.js.map +1 -1
- package/dist/agent-installation/installation-grants.d.ts.map +1 -1
- package/dist/agent-installation/installation-grants.js +1 -2
- package/dist/agent-installation/installation-grants.js.map +1 -1
- package/dist/agent-installation/managed-adapter-installer.d.ts +0 -1
- package/dist/agent-installation/managed-adapter-installer.d.ts.map +1 -1
- package/dist/agent-installation/managed-adapter-installer.js +1 -3
- package/dist/agent-installation/managed-adapter-installer.js.map +1 -1
- package/dist/authorization/local-authorization-error.d.ts +5 -0
- package/dist/authorization/local-authorization-error.d.ts.map +1 -0
- package/dist/authorization/local-authorization-error.js +8 -0
- package/dist/authorization/local-authorization-error.js.map +1 -0
- package/dist/authorization/workspace-directory.d.ts +16 -5
- package/dist/authorization/workspace-directory.d.ts.map +1 -1
- package/dist/authorization/workspace-directory.js +109 -119
- package/dist/authorization/workspace-directory.js.map +1 -1
- package/dist/cli.js +2881 -739
- package/dist/cli.js.map +4 -4
- package/dist/config.d.ts +3 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -6
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2895 -788
- package/dist/index.js.map +4 -4
- package/dist/native-sessions/codex-history.d.ts +11 -0
- package/dist/native-sessions/codex-history.d.ts.map +1 -0
- package/dist/native-sessions/codex-history.js +223 -0
- package/dist/native-sessions/codex-history.js.map +1 -0
- package/dist/native-sessions/service.d.ts +14 -0
- package/dist/native-sessions/service.d.ts.map +1 -0
- package/dist/native-sessions/service.js +254 -0
- package/dist/native-sessions/service.js.map +1 -0
- package/dist/pairing/pair-local-machine.d.ts.map +1 -1
- package/dist/pairing/pair-local-machine.js +41 -31
- package/dist/pairing/pair-local-machine.js.map +1 -1
- package/dist/process/executable.d.ts +1 -1
- package/dist/process/executable.d.ts.map +1 -1
- package/dist/process/executable.js +3 -11
- package/dist/process/executable.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 +19 -0
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -0
- package/dist/relay-connection/session-event-outbox.js +182 -0
- package/dist/relay-connection/session-event-outbox.js.map +1 -0
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +340 -244
- package/dist/run-daemon.js.map +1 -1
- package/package.json +3 -2
- package/dist/authorization/authorize-binding.d.ts +0 -6
- package/dist/authorization/authorize-binding.d.ts.map +0 -1
- package/dist/authorization/authorize-binding.js +0 -30
- package/dist/authorization/authorize-binding.js.map +0 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { methods, ndJsonStream, PROTOCOL_VERSION, } from "@agentclientprotocol/sdk";
|
|
3
|
-
import { AGENT_CONTENT_KIND,
|
|
3
|
+
import { AGENT_CONTENT_KIND, decodeAgentPromptResponse, SESSION_COMMANDS_UPDATED_KIND, SESSION_CONFIG_UPDATED_KIND, SESSION_ELICITATION_REQUESTED_KIND, SESSION_ELICITATION_RESOLVED_KIND, SESSION_INFO_UPDATED_KIND, SESSION_PERMISSION_REQUESTED_KIND, SESSION_PERMISSION_RESOLVED_KIND, SESSION_USAGE_UPDATED_KIND, } from "@moxt-ai/mobius-protocol";
|
|
4
4
|
import { revalidateExecutable, stopProcessTree, } from "../process/executable.js";
|
|
5
5
|
import { AcpActivityTracker, isProgressMessage, normalizeContentBlock, } from "./activity.js";
|
|
6
6
|
import { createAcpClient } from "./create-client.js";
|
|
7
|
-
import {
|
|
7
|
+
import { nativeSessionIdSchema, nativeSessionPageSchema, } from "./native-session.js";
|
|
8
|
+
import { AcpHistoryReplay } from "./session-history.js";
|
|
9
|
+
import { AcpStoredSession, DeletedAcpStoredSession, FoundAcpStoredSession, MemoryAcpSessionStore, } from "./session-store.js";
|
|
8
10
|
const PROCESS_STOP_TIMEOUT_MILLISECONDS = 1_000;
|
|
9
11
|
const SESSION_CONTROL_COMMAND_ID = "session-control";
|
|
10
12
|
export class NullAcpSessionObserver {
|
|
@@ -274,6 +276,7 @@ function normalizeCapabilities(capabilities) {
|
|
|
274
276
|
listSessions: session?.list != null,
|
|
275
277
|
loadSession: capabilities.loadSession === true,
|
|
276
278
|
resumeSession: session?.resume != null,
|
|
279
|
+
unstableForkSession: session?.fork != null,
|
|
277
280
|
};
|
|
278
281
|
}
|
|
279
282
|
function elicitationFieldType(value) {
|
|
@@ -582,14 +585,17 @@ class AcpProcessSession {
|
|
|
582
585
|
listSessions: false,
|
|
583
586
|
loadSession: false,
|
|
584
587
|
resumeSession: false,
|
|
588
|
+
unstableForkSession: false,
|
|
585
589
|
};
|
|
586
590
|
#commands = [];
|
|
587
591
|
#configOptions = [];
|
|
588
592
|
#nativeSessionId = "";
|
|
589
593
|
#prompted = false;
|
|
590
|
-
#
|
|
594
|
+
#replay = {
|
|
595
|
+
kind: "idle",
|
|
596
|
+
};
|
|
591
597
|
#restored = false;
|
|
592
|
-
#sessionTitle =
|
|
598
|
+
#sessionTitle = null;
|
|
593
599
|
#sessionUpdatedAt = "";
|
|
594
600
|
#turn = new IdleAcpTurn();
|
|
595
601
|
#updateTail = Promise.resolve();
|
|
@@ -637,11 +643,12 @@ class AcpProcessSession {
|
|
|
637
643
|
}
|
|
638
644
|
const runtime = new AcpProcessSession(options.agent, options.cwd, options.additionalDirectories, options.sessionId, getObserver, store);
|
|
639
645
|
try {
|
|
640
|
-
await runtime.initialize(options.signal);
|
|
646
|
+
await runtime.initialize(options.signal, options.origin);
|
|
641
647
|
return runtime;
|
|
642
648
|
}
|
|
643
649
|
catch (error) {
|
|
644
650
|
await runtime.closeProcess();
|
|
651
|
+
options.signal.throwIfAborted();
|
|
645
652
|
if (error instanceof AcpExecutionError) {
|
|
646
653
|
throw error;
|
|
647
654
|
}
|
|
@@ -655,7 +662,27 @@ class AcpProcessSession {
|
|
|
655
662
|
arraysEqual(this.#additionalDirectories, additionalDirectories);
|
|
656
663
|
canRebind = () => !this.#prompted && !this.#turn.running;
|
|
657
664
|
prepared = () => new AcpPreparedSession(this.#agentName, this.#agentVersion, this.#capabilities, this.#commands, this.#configOptions, this.#restored);
|
|
658
|
-
|
|
665
|
+
loadHistory = async (signal) => {
|
|
666
|
+
if (!this.#capabilities.loadSession)
|
|
667
|
+
return { status: "unavailable" };
|
|
668
|
+
const history = new AcpHistoryReplay();
|
|
669
|
+
this.#replay = { kind: "capture", history };
|
|
670
|
+
try {
|
|
671
|
+
await this.race(this.#connection.agent.request(methods.agent.session.load, {
|
|
672
|
+
additionalDirectories: [...this.#additionalDirectories],
|
|
673
|
+
cwd: this.#cwd,
|
|
674
|
+
mcpServers: [],
|
|
675
|
+
sessionId: this.#nativeSessionId,
|
|
676
|
+
}, { cancellationSignal: signal }), "ACP agent exited while loading history", signal);
|
|
677
|
+
await this.#updateTail;
|
|
678
|
+
signal.throwIfAborted();
|
|
679
|
+
return history.snapshot();
|
|
680
|
+
}
|
|
681
|
+
finally {
|
|
682
|
+
this.#replay = { kind: "idle" };
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
initialize = async (signal, origin) => {
|
|
659
686
|
const initialized = await this.race(this.#connection.agent.request(methods.agent.initialize, {
|
|
660
687
|
clientCapabilities: {
|
|
661
688
|
elicitation: { form: {}, url: {} },
|
|
@@ -674,9 +701,31 @@ class AcpProcessSession {
|
|
|
674
701
|
initialized.agentInfo?.name ??
|
|
675
702
|
this.#agentId, 255);
|
|
676
703
|
this.#agentVersion = truncate(initialized.agentInfo?.version ?? "", 128);
|
|
677
|
-
const stored =
|
|
704
|
+
const stored = origin?.kind === "import"
|
|
705
|
+
? new FoundAcpStoredSession(new AcpStoredSession(this.#mobiusSessionId, this.#agentId, nativeSessionIdSchema.parse(origin.nativeSessionId), this.#cwd, this.#additionalDirectories, true))
|
|
706
|
+
: this.#store.read(this.#mobiusSessionId);
|
|
707
|
+
if (stored instanceof DeletedAcpStoredSession)
|
|
708
|
+
throw new AcpExecutionError("The native Agent session was deleted. Start a new chat.", {}, "native_session_deleted");
|
|
678
709
|
let lifecycleResponse;
|
|
679
|
-
if (
|
|
710
|
+
if (origin?.kind === "fork") {
|
|
711
|
+
if (!this.#capabilities.unstableForkSession)
|
|
712
|
+
throw new AcpExecutionError("This Agent does not support session forking", {}, "native_session_unsupported");
|
|
713
|
+
const forked = await this.race(this.#connection.agent.request(methods.agent.session.fork, {
|
|
714
|
+
sessionId: nativeSessionIdSchema.parse(origin.nativeSessionId),
|
|
715
|
+
cwd: this.#cwd,
|
|
716
|
+
additionalDirectories: [...this.#additionalDirectories],
|
|
717
|
+
mcpServers: [],
|
|
718
|
+
}, { cancellationSignal: signal }), "ACP agent exited while forking a session", signal);
|
|
719
|
+
this.#nativeSessionId = nativeSessionIdSchema.parse(forked.sessionId);
|
|
720
|
+
if (this.#nativeSessionId === origin.nativeSessionId ||
|
|
721
|
+
this.#store.findNative(this.#agentId, this.#nativeSessionId).length > 0) {
|
|
722
|
+
throw new AcpExecutionError("The Agent did not create an independent fork", {}, "invalid_native_session_response");
|
|
723
|
+
}
|
|
724
|
+
this.#prompted = true;
|
|
725
|
+
this.#restored = true;
|
|
726
|
+
lifecycleResponse = forked;
|
|
727
|
+
}
|
|
728
|
+
else if (stored instanceof FoundAcpStoredSession &&
|
|
680
729
|
stored.session.agentId === this.#agentId &&
|
|
681
730
|
stored.session.cwd === this.#cwd &&
|
|
682
731
|
arraysEqual(stored.session.additionalDirectories, this.#additionalDirectories)) {
|
|
@@ -692,7 +741,7 @@ class AcpProcessSession {
|
|
|
692
741
|
}, { cancellationSignal: signal }), "ACP agent exited while resuming a session", signal);
|
|
693
742
|
}
|
|
694
743
|
else if (this.#capabilities.loadSession) {
|
|
695
|
-
this.#
|
|
744
|
+
this.#replay = { kind: "discard" };
|
|
696
745
|
try {
|
|
697
746
|
lifecycleResponse = await this.race(this.#connection.agent.request(methods.agent.session.load, {
|
|
698
747
|
additionalDirectories: [...this.#additionalDirectories],
|
|
@@ -702,7 +751,8 @@ class AcpProcessSession {
|
|
|
702
751
|
}, { cancellationSignal: signal }), "ACP agent exited while loading a session", signal);
|
|
703
752
|
}
|
|
704
753
|
finally {
|
|
705
|
-
this.#
|
|
754
|
+
await this.#updateTail;
|
|
755
|
+
this.#replay = { kind: "idle" };
|
|
706
756
|
}
|
|
707
757
|
}
|
|
708
758
|
else {
|
|
@@ -731,7 +781,23 @@ class AcpProcessSession {
|
|
|
731
781
|
this.#configOptions = normalizeConfigOptions(lifecycleRecord["configOptions"], lifecycleRecord["modes"]);
|
|
732
782
|
await this.#updateTail;
|
|
733
783
|
signal.throwIfAborted();
|
|
784
|
+
this.#store.write(new AcpStoredSession(this.#mobiusSessionId, this.#agentId, this.#nativeSessionId, this.#cwd, this.#additionalDirectories, this.#prompted));
|
|
785
|
+
};
|
|
786
|
+
listNativeSessions = async (cursor, signal) => {
|
|
787
|
+
if (!this.#capabilities.listSessions)
|
|
788
|
+
throw new AcpExecutionError("This Agent does not support native session listing", {}, "native_session_unsupported");
|
|
789
|
+
const response = await this.race(this.#connection.agent.request(methods.agent.session.list, cursor === null ? {} : { cursor }, { cancellationSignal: signal }), "ACP agent exited while listing sessions", signal);
|
|
790
|
+
const decoded = nativeSessionPageSchema.safeParse(response);
|
|
791
|
+
if (!decoded.success)
|
|
792
|
+
throw new AcpExecutionError("The Agent returned an invalid native session list", { cause: decoded.error }, "invalid_native_session_response");
|
|
793
|
+
return decoded.data;
|
|
734
794
|
};
|
|
795
|
+
deleteNativeSession = async (nativeSessionId, signal) => {
|
|
796
|
+
if (!this.#capabilities.deleteSession || !this.#capabilities.listSessions)
|
|
797
|
+
throw new AcpExecutionError("This Agent does not support native session deletion", {}, "native_session_unsupported");
|
|
798
|
+
await this.race(this.#connection.agent.request(methods.agent.session.delete, { sessionId: nativeSessionIdSchema.parse(nativeSessionId) }, { cancellationSignal: signal }), "ACP agent exited while deleting a session", signal);
|
|
799
|
+
};
|
|
800
|
+
nativeSessionId = () => this.#nativeSessionId;
|
|
735
801
|
configure = async (options) => {
|
|
736
802
|
const existing = this.#configOptions.find((option) => option.id === options.configId);
|
|
737
803
|
if (existing === undefined || existing.type !== options.valueType) {
|
|
@@ -821,7 +887,24 @@ class AcpProcessSession {
|
|
|
821
887
|
const response = await this.race(this.#connection.agent.request(methods.agent.session.prompt, { prompt, sessionId: this.#nativeSessionId }, { cancellationSignal: options.signal }), "ACP agent exited during a prompt", options.signal);
|
|
822
888
|
await this.#updateTail;
|
|
823
889
|
await running.activities.finish();
|
|
824
|
-
|
|
890
|
+
let result;
|
|
891
|
+
try {
|
|
892
|
+
result = decodeAgentPromptResponse(response);
|
|
893
|
+
}
|
|
894
|
+
catch (cause) {
|
|
895
|
+
throw new AcpExecutionError("ACP agent returned an invalid prompt response", { cause }, "acp_invalid_prompt_response");
|
|
896
|
+
}
|
|
897
|
+
if (result.usage != null || result._meta?.quota !== undefined) {
|
|
898
|
+
await this.#getObserver().onUsage({
|
|
899
|
+
_meta: result._meta ?? null,
|
|
900
|
+
commandId: options.commandId,
|
|
901
|
+
kind: SESSION_USAGE_UPDATED_KIND,
|
|
902
|
+
sessionId: this.#mobiusSessionId,
|
|
903
|
+
source: "prompt",
|
|
904
|
+
usage: result.usage ?? null,
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
return result;
|
|
825
908
|
}
|
|
826
909
|
catch (error) {
|
|
827
910
|
await running.activities.finish();
|
|
@@ -866,7 +949,6 @@ class AcpProcessSession {
|
|
|
866
949
|
kind: SESSION_PERMISSION_RESOLVED_KIND,
|
|
867
950
|
optionId: options.outcome === "selected" ? options.optionId : "",
|
|
868
951
|
outcome: options.outcome,
|
|
869
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
870
952
|
sessionId: this.#mobiusSessionId,
|
|
871
953
|
});
|
|
872
954
|
};
|
|
@@ -901,7 +983,6 @@ class AcpProcessSession {
|
|
|
901
983
|
action: options.action,
|
|
902
984
|
interactionId: options.interactionId,
|
|
903
985
|
kind: SESSION_ELICITATION_RESOLVED_KIND,
|
|
904
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
905
986
|
sessionId: this.#mobiusSessionId,
|
|
906
987
|
});
|
|
907
988
|
};
|
|
@@ -930,7 +1011,6 @@ class AcpProcessSession {
|
|
|
930
1011
|
interactionId,
|
|
931
1012
|
kind: SESSION_PERMISSION_REQUESTED_KIND,
|
|
932
1013
|
options,
|
|
933
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
934
1014
|
sessionId: this.#mobiusSessionId,
|
|
935
1015
|
title: truncate(request.toolCall.title ?? "Permission required", 500),
|
|
936
1016
|
toolCallId: truncate(request.toolCall.toolCallId, 255),
|
|
@@ -975,7 +1055,6 @@ class AcpProcessSession {
|
|
|
975
1055
|
kind: SESSION_ELICITATION_REQUESTED_KIND,
|
|
976
1056
|
message: truncate(request.message, 2_000),
|
|
977
1057
|
mode: request.mode,
|
|
978
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
979
1058
|
sessionId: this.#mobiusSessionId,
|
|
980
1059
|
url: request.mode === "url" &&
|
|
981
1060
|
typeof Reflect.get(request, "url") === "string"
|
|
@@ -999,7 +1078,6 @@ class AcpProcessSession {
|
|
|
999
1078
|
action: "complete",
|
|
1000
1079
|
interactionId,
|
|
1001
1080
|
kind: SESSION_ELICITATION_RESOLVED_KIND,
|
|
1002
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1003
1081
|
sessionId: this.#mobiusSessionId,
|
|
1004
1082
|
});
|
|
1005
1083
|
};
|
|
@@ -1010,7 +1088,9 @@ class AcpProcessSession {
|
|
|
1010
1088
|
processUpdate = async (notification) => {
|
|
1011
1089
|
this.assertNativeSession(notification.sessionId);
|
|
1012
1090
|
const update = notification.update;
|
|
1013
|
-
if (this.#
|
|
1091
|
+
if (this.#replay.kind === "capture")
|
|
1092
|
+
this.#replay.history.record(update);
|
|
1093
|
+
if (this.#replay.kind !== "idle" &&
|
|
1014
1094
|
(update.sessionUpdate === "user_message_chunk" ||
|
|
1015
1095
|
update.sessionUpdate === "agent_message_chunk" ||
|
|
1016
1096
|
update.sessionUpdate === "agent_thought_chunk" ||
|
|
@@ -1039,7 +1119,6 @@ class AcpProcessSession {
|
|
|
1039
1119
|
contentId: `content-${crypto.randomUUID()}`,
|
|
1040
1120
|
kind: AGENT_CONTENT_KIND,
|
|
1041
1121
|
messageId: truncate(update.messageId ?? "", 255),
|
|
1042
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1043
1122
|
sessionId: this.#mobiusSessionId,
|
|
1044
1123
|
});
|
|
1045
1124
|
}
|
|
@@ -1084,7 +1163,6 @@ class AcpProcessSession {
|
|
|
1084
1163
|
await this.#getObserver().onCommands({
|
|
1085
1164
|
commands,
|
|
1086
1165
|
kind: SESSION_COMMANDS_UPDATED_KIND,
|
|
1087
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1088
1166
|
sessionId: this.#mobiusSessionId,
|
|
1089
1167
|
});
|
|
1090
1168
|
return;
|
|
@@ -1110,7 +1188,6 @@ class AcpProcessSession {
|
|
|
1110
1188
|
}
|
|
1111
1189
|
await this.#getObserver().onInfo({
|
|
1112
1190
|
kind: SESSION_INFO_UPDATED_KIND,
|
|
1113
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1114
1191
|
sessionId: this.#mobiusSessionId,
|
|
1115
1192
|
title: this.#sessionTitle,
|
|
1116
1193
|
updatedAt: this.#sessionUpdatedAt,
|
|
@@ -1123,9 +1200,9 @@ class AcpProcessSession {
|
|
|
1123
1200
|
costCurrency: truncate(update.cost?.currency ?? "", 16),
|
|
1124
1201
|
hasCost: update.cost !== undefined && update.cost !== null,
|
|
1125
1202
|
kind: SESSION_USAGE_UPDATED_KIND,
|
|
1126
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1127
1203
|
sessionId: this.#mobiusSessionId,
|
|
1128
1204
|
size: Math.max(0, Math.trunc(update.size)),
|
|
1205
|
+
source: "context",
|
|
1129
1206
|
used: Math.max(0, Math.trunc(update.used)),
|
|
1130
1207
|
});
|
|
1131
1208
|
}
|
|
@@ -1182,7 +1259,6 @@ class AcpProcessSession {
|
|
|
1182
1259
|
await this.#getObserver().onConfig({
|
|
1183
1260
|
configOptions: this.#configOptions,
|
|
1184
1261
|
kind: SESSION_CONFIG_UPDATED_KIND,
|
|
1185
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1186
1262
|
requestId: `agent-update-${crypto.randomUUID()}`,
|
|
1187
1263
|
sessionId: this.#mobiusSessionId,
|
|
1188
1264
|
});
|
|
@@ -1198,7 +1274,6 @@ class AcpProcessSession {
|
|
|
1198
1274
|
kind: SESSION_PERMISSION_RESOLVED_KIND,
|
|
1199
1275
|
optionId: "",
|
|
1200
1276
|
outcome: "cancelled",
|
|
1201
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1202
1277
|
sessionId: this.#mobiusSessionId,
|
|
1203
1278
|
});
|
|
1204
1279
|
};
|
|
@@ -1212,7 +1287,6 @@ class AcpProcessSession {
|
|
|
1212
1287
|
action: "cancel",
|
|
1213
1288
|
interactionId,
|
|
1214
1289
|
kind: SESSION_ELICITATION_RESOLVED_KIND,
|
|
1215
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1216
1290
|
sessionId: this.#mobiusSessionId,
|
|
1217
1291
|
});
|
|
1218
1292
|
};
|
|
@@ -1232,13 +1306,13 @@ class AcpProcessSession {
|
|
|
1232
1306
|
action: "cancel",
|
|
1233
1307
|
interactionId,
|
|
1234
1308
|
kind: SESSION_ELICITATION_RESOLVED_KIND,
|
|
1235
|
-
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1236
1309
|
sessionId: this.#mobiusSessionId,
|
|
1237
1310
|
});
|
|
1238
1311
|
}
|
|
1239
1312
|
};
|
|
1240
1313
|
}
|
|
1241
1314
|
export class AcpSessionManager {
|
|
1315
|
+
#nativeOperations = new Set();
|
|
1242
1316
|
#activeSessionIds = new Set();
|
|
1243
1317
|
#cancellationRequests = new Set();
|
|
1244
1318
|
#preparing = new Map();
|
|
@@ -1284,6 +1358,12 @@ export class AcpSessionManager {
|
|
|
1284
1358
|
return await operation;
|
|
1285
1359
|
}
|
|
1286
1360
|
prepareSession = async (options) => {
|
|
1361
|
+
const stored = this.#store.read(options.sessionId);
|
|
1362
|
+
if (stored instanceof DeletedAcpStoredSession)
|
|
1363
|
+
throw new AcpExecutionError("The native Agent session was deleted. Start a new chat.", {}, "native_session_deleted");
|
|
1364
|
+
if (stored instanceof FoundAcpStoredSession &&
|
|
1365
|
+
this.#nativeOperations.has(`${stored.session.agentId}:${stored.session.nativeSessionId}`))
|
|
1366
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1287
1367
|
const pending = this.#preparing.get(options.sessionId);
|
|
1288
1368
|
if (pending !== undefined) {
|
|
1289
1369
|
const runtime = await pending;
|
|
@@ -1318,6 +1398,11 @@ export class AcpSessionManager {
|
|
|
1318
1398
|
}
|
|
1319
1399
|
};
|
|
1320
1400
|
runPrompt = async (options) => {
|
|
1401
|
+
const stored = this.#store.read(options.sessionId);
|
|
1402
|
+
if (stored instanceof FoundAcpStoredSession &&
|
|
1403
|
+
this.#nativeOperations.has(`${stored.session.agentId}:${stored.session.nativeSessionId}`)) {
|
|
1404
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1405
|
+
}
|
|
1321
1406
|
if (this.#activeSessionIds.has(options.sessionId)) {
|
|
1322
1407
|
throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
|
|
1323
1408
|
}
|
|
@@ -1327,6 +1412,8 @@ export class AcpSessionManager {
|
|
|
1327
1412
|
return { stopReason: "cancelled" };
|
|
1328
1413
|
}
|
|
1329
1414
|
const runtime = await this.ensureSession(options);
|
|
1415
|
+
if (this.#nativeOperations.has(`${options.agent.id}:${runtime.nativeSessionId()}`))
|
|
1416
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1330
1417
|
if (this.#cancellationRequests.has(options.sessionId)) {
|
|
1331
1418
|
return { stopReason: "cancelled" };
|
|
1332
1419
|
}
|
|
@@ -1384,5 +1471,103 @@ export class AcpSessionManager {
|
|
|
1384
1471
|
}
|
|
1385
1472
|
return started;
|
|
1386
1473
|
};
|
|
1474
|
+
listNativeSessions = async (options, cursor) => await (await this.ensureSession(options)).listNativeSessions(cursor, options.signal);
|
|
1475
|
+
openNativeSession = async (options, origin) => {
|
|
1476
|
+
const key = `${options.agent.id}:${origin.nativeSessionId}`;
|
|
1477
|
+
if (this.#nativeOperations.has(key))
|
|
1478
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1479
|
+
const linked = this.#store.findNative(options.agent.id, origin.nativeSessionId);
|
|
1480
|
+
if (linked.some((entry) => this.#activeSessionIds.has(entry.sessionId) ||
|
|
1481
|
+
this.#preparing.has(entry.sessionId)))
|
|
1482
|
+
throw new AcpExecutionError("Wait for the native session's running operation to finish", {}, "session_busy");
|
|
1483
|
+
const existing = linked[0];
|
|
1484
|
+
if (origin.kind === "import" && existing !== undefined) {
|
|
1485
|
+
const runtime = await this.ensureSession({
|
|
1486
|
+
...options,
|
|
1487
|
+
sessionId: existing.sessionId,
|
|
1488
|
+
});
|
|
1489
|
+
if (this.#activeSessionIds.has(existing.sessionId) ||
|
|
1490
|
+
this.#nativeOperations.has(key))
|
|
1491
|
+
throw new AcpExecutionError("Wait for the native session's running operation to finish", {}, "session_busy");
|
|
1492
|
+
this.#nativeOperations.add(key);
|
|
1493
|
+
try {
|
|
1494
|
+
const history = await runtime.loadHistory(options.signal);
|
|
1495
|
+
return {
|
|
1496
|
+
prepared: runtime.prepared(),
|
|
1497
|
+
sessionId: existing.sessionId,
|
|
1498
|
+
history,
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
catch (error) {
|
|
1502
|
+
this.#sessions.delete(existing.sessionId);
|
|
1503
|
+
await runtime.closeProcess();
|
|
1504
|
+
throw error;
|
|
1505
|
+
}
|
|
1506
|
+
finally {
|
|
1507
|
+
this.#nativeOperations.delete(key);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
if (this.#sessions.has(options.sessionId) ||
|
|
1511
|
+
this.#preparing.has(options.sessionId) ||
|
|
1512
|
+
this.#store.read(options.sessionId) instanceof FoundAcpStoredSession ||
|
|
1513
|
+
this.#store.read(options.sessionId) instanceof DeletedAcpStoredSession)
|
|
1514
|
+
throw new AcpExecutionError("The destination conversation already exists", {}, "session_identity_mismatch");
|
|
1515
|
+
this.#nativeOperations.add(key);
|
|
1516
|
+
try {
|
|
1517
|
+
const runtime = await this.#startPreparation({ ...options, origin });
|
|
1518
|
+
const openedKey = `${options.agent.id}:${runtime.nativeSessionId()}`;
|
|
1519
|
+
this.#nativeOperations.add(openedKey);
|
|
1520
|
+
try {
|
|
1521
|
+
const history = await runtime.loadHistory(options.signal);
|
|
1522
|
+
return {
|
|
1523
|
+
sessionId: options.sessionId,
|
|
1524
|
+
prepared: runtime.prepared(),
|
|
1525
|
+
history,
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
catch (error) {
|
|
1529
|
+
this.#sessions.delete(options.sessionId);
|
|
1530
|
+
this.#store.remove(options.sessionId);
|
|
1531
|
+
await runtime.closeProcess();
|
|
1532
|
+
throw error;
|
|
1533
|
+
}
|
|
1534
|
+
finally {
|
|
1535
|
+
this.#nativeOperations.delete(openedKey);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
finally {
|
|
1539
|
+
this.#nativeOperations.delete(key);
|
|
1540
|
+
}
|
|
1541
|
+
};
|
|
1542
|
+
deleteNativeSession = async (options, nativeSessionId) => {
|
|
1543
|
+
const runtime = await this.ensureSession(options);
|
|
1544
|
+
const key = `${options.agent.id}:${nativeSessionId}`;
|
|
1545
|
+
const linked = this.#store.findNative(options.agent.id, nativeSessionId);
|
|
1546
|
+
if (this.#nativeOperations.has(key) ||
|
|
1547
|
+
linked.some((entry) => this.#activeSessionIds.has(entry.sessionId) ||
|
|
1548
|
+
this.#preparing.has(entry.sessionId)))
|
|
1549
|
+
throw new AcpExecutionError("Wait for the native session's running operation to finish", {}, "session_busy");
|
|
1550
|
+
this.#nativeOperations.add(key);
|
|
1551
|
+
try {
|
|
1552
|
+
for (const entry of linked) {
|
|
1553
|
+
const active = this.#sessions.get(entry.sessionId);
|
|
1554
|
+
if (active !== undefined && active !== runtime) {
|
|
1555
|
+
this.#sessions.delete(entry.sessionId);
|
|
1556
|
+
await active.close();
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
options.signal.throwIfAborted();
|
|
1560
|
+
await runtime.deleteNativeSession(nativeSessionId, options.signal);
|
|
1561
|
+
const deleted = this.#store.markDeleted(options.agent.id, nativeSessionId);
|
|
1562
|
+
if (runtime.nativeSessionId() === nativeSessionId) {
|
|
1563
|
+
this.#sessions.delete(options.sessionId);
|
|
1564
|
+
await runtime.close();
|
|
1565
|
+
}
|
|
1566
|
+
return deleted;
|
|
1567
|
+
}
|
|
1568
|
+
finally {
|
|
1569
|
+
this.#nativeOperations.delete(key);
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1387
1572
|
}
|
|
1388
1573
|
//# sourceMappingURL=session-manager.js.map
|