@moxt-ai/mobius 0.0.4 → 0.0.6
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/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 +226 -41
- 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/agent-diagnostics.d.ts +3 -0
- package/dist/agent-catalog/agent-diagnostics.d.ts.map +1 -0
- package/dist/agent-catalog/agent-diagnostics.js +62 -0
- package/dist/agent-catalog/agent-diagnostics.js.map +1 -0
- package/dist/agent-catalog/discover-local-agents.d.ts +77 -0
- package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -0
- package/dist/agent-catalog/discover-local-agents.js +467 -0
- package/dist/agent-catalog/discover-local-agents.js.map +1 -0
- package/dist/agent-catalog/local-agent.d.ts +38 -0
- package/dist/agent-catalog/local-agent.d.ts.map +1 -0
- package/dist/agent-catalog/local-agent.js +93 -0
- package/dist/agent-catalog/local-agent.js.map +1 -0
- package/dist/agent-catalog/publish-agent-catalog.d.ts +3 -0
- package/dist/agent-catalog/publish-agent-catalog.d.ts.map +1 -0
- package/dist/agent-catalog/publish-agent-catalog.js +58 -0
- package/dist/agent-catalog/publish-agent-catalog.js.map +1 -0
- package/dist/agent-installation/agent-installation-manager.d.ts +60 -0
- package/dist/agent-installation/agent-installation-manager.d.ts.map +1 -0
- package/dist/agent-installation/agent-installation-manager.js +242 -0
- package/dist/agent-installation/agent-installation-manager.js.map +1 -0
- package/dist/agent-installation/automatic-adapter-provisioner.d.ts +18 -0
- package/dist/agent-installation/automatic-adapter-provisioner.d.ts.map +1 -0
- package/dist/agent-installation/automatic-adapter-provisioner.js +116 -0
- package/dist/agent-installation/automatic-adapter-provisioner.js.map +1 -0
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts +20 -0
- package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +1 -0
- package/dist/agent-installation/fixed-agent-install-recipes.js +163 -0
- package/dist/agent-installation/fixed-agent-install-recipes.js.map +1 -0
- package/dist/agent-installation/fixed-installation-executor.d.ts +20 -0
- package/dist/agent-installation/fixed-installation-executor.d.ts.map +1 -0
- package/dist/agent-installation/fixed-installation-executor.js +204 -0
- package/dist/agent-installation/fixed-installation-executor.js.map +1 -0
- package/dist/agent-installation/installation-grants.d.ts +2 -0
- package/dist/agent-installation/installation-grants.d.ts.map +1 -0
- package/dist/agent-installation/installation-grants.js +52 -0
- package/dist/agent-installation/installation-grants.js.map +1 -0
- package/dist/agent-installation/local-installation-authorizer.d.ts +7 -0
- package/dist/agent-installation/local-installation-authorizer.d.ts.map +1 -0
- package/dist/agent-installation/local-installation-authorizer.js +32 -0
- package/dist/agent-installation/local-installation-authorizer.js.map +1 -0
- package/dist/agent-installation/managed-adapter-installer.d.ts +20 -0
- package/dist/agent-installation/managed-adapter-installer.d.ts.map +1 -0
- package/dist/agent-installation/managed-adapter-installer.js +159 -0
- package/dist/agent-installation/managed-adapter-installer.js.map +1 -0
- package/dist/agent-installation/verified-download.d.ts +24 -0
- package/dist/agent-installation/verified-download.d.ts.map +1 -0
- package/dist/agent-installation/verified-download.js +158 -0
- package/dist/agent-installation/verified-download.js.map +1 -0
- package/dist/audit/audit-store.d.ts +1 -0
- package/dist/audit/audit-store.d.ts.map +1 -1
- package/dist/audit/audit-store.js +12 -4
- package/dist/audit/audit-store.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 +6289 -2124
- package/dist/cli.js.map +4 -4
- package/dist/config.d.ts +8 -12
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -55
- 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 +4894 -852
- 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 +249 -0
- package/dist/native-sessions/service.js.map +1 -0
- package/dist/pairing/pair-local-machine.d.ts +2 -2
- package/dist/pairing/pair-local-machine.d.ts.map +1 -1
- package/dist/pairing/pair-local-machine.js +65 -41
- package/dist/pairing/pair-local-machine.js.map +1 -1
- package/dist/process/executable.d.ts +40 -0
- package/dist/process/executable.d.ts.map +1 -0
- package/dist/process/executable.js +305 -0
- package/dist/process/executable.js.map +1 -0
- package/dist/run-daemon.d.ts +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +431 -180
- package/dist/run-daemon.js.map +1 -1
- package/dist/storage/state-directory.d.ts +2 -0
- package/dist/storage/state-directory.d.ts.map +1 -0
- package/dist/storage/state-directory.js +10 -0
- package/dist/storage/state-directory.js.map +1 -0
- package/package.json +5 -6
- 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
|
-
import { once } from "node:events";
|
|
3
2
|
import { methods, ndJsonStream, PROTOCOL_VERSION, } from "@agentclientprotocol/sdk";
|
|
4
|
-
import { AGENT_CONTENT_KIND, MOBIUS_PROTOCOL_VERSION, 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";
|
|
3
|
+
import { AGENT_CONTENT_KIND, decodeAgentPromptResponse, MOBIUS_PROTOCOL_VERSION, 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
|
+
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 {
|
|
@@ -117,31 +119,6 @@ export function createWritableAcpStream(output) {
|
|
|
117
119
|
},
|
|
118
120
|
});
|
|
119
121
|
}
|
|
120
|
-
async function stopAgentProcess(child) {
|
|
121
|
-
child.stdin?.end();
|
|
122
|
-
if (child.exitCode !== null) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
child.kill("SIGTERM");
|
|
126
|
-
try {
|
|
127
|
-
await once(child, "exit", {
|
|
128
|
-
signal: AbortSignal.timeout(PROCESS_STOP_TIMEOUT_MILLISECONDS),
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
catch {
|
|
132
|
-
if (child.exitCode === null) {
|
|
133
|
-
child.kill("SIGKILL");
|
|
134
|
-
try {
|
|
135
|
-
await once(child, "exit", {
|
|
136
|
-
signal: AbortSignal.timeout(PROCESS_STOP_TIMEOUT_MILLISECONDS),
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
// Teardown must not wait forever for a process the OS did not reap.
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
122
|
function truncate(value, maximumLength) {
|
|
146
123
|
return value.length <= maximumLength
|
|
147
124
|
? value
|
|
@@ -299,6 +276,7 @@ function normalizeCapabilities(capabilities) {
|
|
|
299
276
|
listSessions: session?.list != null,
|
|
300
277
|
loadSession: capabilities.loadSession === true,
|
|
301
278
|
resumeSession: session?.resume != null,
|
|
279
|
+
unstableForkSession: session?.fork != null,
|
|
302
280
|
};
|
|
303
281
|
}
|
|
304
282
|
function elicitationFieldType(value) {
|
|
@@ -607,14 +585,17 @@ class AcpProcessSession {
|
|
|
607
585
|
listSessions: false,
|
|
608
586
|
loadSession: false,
|
|
609
587
|
resumeSession: false,
|
|
588
|
+
unstableForkSession: false,
|
|
610
589
|
};
|
|
611
590
|
#commands = [];
|
|
612
591
|
#configOptions = [];
|
|
613
592
|
#nativeSessionId = "";
|
|
614
593
|
#prompted = false;
|
|
615
|
-
#
|
|
594
|
+
#replay = {
|
|
595
|
+
kind: "idle",
|
|
596
|
+
};
|
|
616
597
|
#restored = false;
|
|
617
|
-
#sessionTitle =
|
|
598
|
+
#sessionTitle = null;
|
|
618
599
|
#sessionUpdatedAt = "";
|
|
619
600
|
#turn = new IdleAcpTurn();
|
|
620
601
|
#updateTail = Promise.resolve();
|
|
@@ -625,8 +606,11 @@ class AcpProcessSession {
|
|
|
625
606
|
this.#getObserver = getObserver;
|
|
626
607
|
this.#mobiusSessionId = mobiusSessionId;
|
|
627
608
|
this.#store = store;
|
|
628
|
-
this.#child = spawn(agent.
|
|
609
|
+
this.#child = spawn(agent.adapterPath, [...agent.arguments], {
|
|
629
610
|
cwd,
|
|
611
|
+
detached: process.platform !== "win32",
|
|
612
|
+
env: { ...process.env, ...agent.environment },
|
|
613
|
+
shell: false,
|
|
630
614
|
stdio: ["pipe", "pipe", "pipe"],
|
|
631
615
|
});
|
|
632
616
|
const stdin = this.#child.stdin;
|
|
@@ -649,13 +633,22 @@ class AcpProcessSession {
|
|
|
649
633
|
}
|
|
650
634
|
static start = async (options, getObserver, store) => {
|
|
651
635
|
options.signal.throwIfAborted();
|
|
636
|
+
const [adapterUnchanged, agentUnchanged] = await Promise.all([
|
|
637
|
+
revalidateExecutable(options.agent.adapterIdentity),
|
|
638
|
+
revalidateExecutable(options.agent.agentIdentity),
|
|
639
|
+
]);
|
|
640
|
+
options.signal.throwIfAborted();
|
|
641
|
+
if (!adapterUnchanged || !agentUnchanged) {
|
|
642
|
+
throw new AcpExecutionError("The local Agent runtime changed; restart Mobius before starting a new conversation", {}, "agent_runtime_changed");
|
|
643
|
+
}
|
|
652
644
|
const runtime = new AcpProcessSession(options.agent, options.cwd, options.additionalDirectories, options.sessionId, getObserver, store);
|
|
653
645
|
try {
|
|
654
|
-
await runtime.initialize(options.signal);
|
|
646
|
+
await runtime.initialize(options.signal, options.origin);
|
|
655
647
|
return runtime;
|
|
656
648
|
}
|
|
657
649
|
catch (error) {
|
|
658
650
|
await runtime.closeProcess();
|
|
651
|
+
options.signal.throwIfAborted();
|
|
659
652
|
if (error instanceof AcpExecutionError) {
|
|
660
653
|
throw error;
|
|
661
654
|
}
|
|
@@ -669,14 +662,34 @@ class AcpProcessSession {
|
|
|
669
662
|
arraysEqual(this.#additionalDirectories, additionalDirectories);
|
|
670
663
|
canRebind = () => !this.#prompted && !this.#turn.running;
|
|
671
664
|
prepared = () => new AcpPreparedSession(this.#agentName, this.#agentVersion, this.#capabilities, this.#commands, this.#configOptions, this.#restored);
|
|
672
|
-
|
|
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) => {
|
|
673
686
|
const initialized = await this.race(this.#connection.agent.request(methods.agent.initialize, {
|
|
674
687
|
clientCapabilities: {
|
|
675
688
|
elicitation: { form: {}, url: {} },
|
|
676
689
|
plan: {},
|
|
677
690
|
session: { configOptions: { boolean: {} } },
|
|
678
691
|
},
|
|
679
|
-
clientInfo: { name: "mobius", version: "0.0.
|
|
692
|
+
clientInfo: { name: "mobius", version: "0.0.3" },
|
|
680
693
|
protocolVersion: PROTOCOL_VERSION,
|
|
681
694
|
}, { cancellationSignal: signal }), "ACP agent exited during initialization", signal);
|
|
682
695
|
if (initialized.protocolVersion !== PROTOCOL_VERSION) {
|
|
@@ -688,9 +701,31 @@ class AcpProcessSession {
|
|
|
688
701
|
initialized.agentInfo?.name ??
|
|
689
702
|
this.#agentId, 255);
|
|
690
703
|
this.#agentVersion = truncate(initialized.agentInfo?.version ?? "", 128);
|
|
691
|
-
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");
|
|
692
709
|
let lifecycleResponse;
|
|
693
|
-
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 &&
|
|
694
729
|
stored.session.agentId === this.#agentId &&
|
|
695
730
|
stored.session.cwd === this.#cwd &&
|
|
696
731
|
arraysEqual(stored.session.additionalDirectories, this.#additionalDirectories)) {
|
|
@@ -706,7 +741,7 @@ class AcpProcessSession {
|
|
|
706
741
|
}, { cancellationSignal: signal }), "ACP agent exited while resuming a session", signal);
|
|
707
742
|
}
|
|
708
743
|
else if (this.#capabilities.loadSession) {
|
|
709
|
-
this.#
|
|
744
|
+
this.#replay = { kind: "discard" };
|
|
710
745
|
try {
|
|
711
746
|
lifecycleResponse = await this.race(this.#connection.agent.request(methods.agent.session.load, {
|
|
712
747
|
additionalDirectories: [...this.#additionalDirectories],
|
|
@@ -716,7 +751,8 @@ class AcpProcessSession {
|
|
|
716
751
|
}, { cancellationSignal: signal }), "ACP agent exited while loading a session", signal);
|
|
717
752
|
}
|
|
718
753
|
finally {
|
|
719
|
-
this.#
|
|
754
|
+
await this.#updateTail;
|
|
755
|
+
this.#replay = { kind: "idle" };
|
|
720
756
|
}
|
|
721
757
|
}
|
|
722
758
|
else {
|
|
@@ -745,7 +781,23 @@ class AcpProcessSession {
|
|
|
745
781
|
this.#configOptions = normalizeConfigOptions(lifecycleRecord["configOptions"], lifecycleRecord["modes"]);
|
|
746
782
|
await this.#updateTail;
|
|
747
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;
|
|
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);
|
|
748
799
|
};
|
|
800
|
+
nativeSessionId = () => this.#nativeSessionId;
|
|
749
801
|
configure = async (options) => {
|
|
750
802
|
const existing = this.#configOptions.find((option) => option.id === options.configId);
|
|
751
803
|
if (existing === undefined || existing.type !== options.valueType) {
|
|
@@ -835,7 +887,25 @@ class AcpProcessSession {
|
|
|
835
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);
|
|
836
888
|
await this.#updateTail;
|
|
837
889
|
await running.activities.finish();
|
|
838
|
-
|
|
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
|
+
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
903
|
+
sessionId: this.#mobiusSessionId,
|
|
904
|
+
source: "prompt",
|
|
905
|
+
usage: result.usage ?? null,
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
return result;
|
|
839
909
|
}
|
|
840
910
|
catch (error) {
|
|
841
911
|
await running.activities.finish();
|
|
@@ -1024,7 +1094,9 @@ class AcpProcessSession {
|
|
|
1024
1094
|
processUpdate = async (notification) => {
|
|
1025
1095
|
this.assertNativeSession(notification.sessionId);
|
|
1026
1096
|
const update = notification.update;
|
|
1027
|
-
if (this.#
|
|
1097
|
+
if (this.#replay.kind === "capture")
|
|
1098
|
+
this.#replay.history.record(update);
|
|
1099
|
+
if (this.#replay.kind !== "idle" &&
|
|
1028
1100
|
(update.sessionUpdate === "user_message_chunk" ||
|
|
1029
1101
|
update.sessionUpdate === "agent_message_chunk" ||
|
|
1030
1102
|
update.sessionUpdate === "agent_thought_chunk" ||
|
|
@@ -1140,6 +1212,7 @@ class AcpProcessSession {
|
|
|
1140
1212
|
protocolVersion: MOBIUS_PROTOCOL_VERSION,
|
|
1141
1213
|
sessionId: this.#mobiusSessionId,
|
|
1142
1214
|
size: Math.max(0, Math.trunc(update.size)),
|
|
1215
|
+
source: "context",
|
|
1143
1216
|
used: Math.max(0, Math.trunc(update.used)),
|
|
1144
1217
|
});
|
|
1145
1218
|
}
|
|
@@ -1160,7 +1233,7 @@ class AcpProcessSession {
|
|
|
1160
1233
|
};
|
|
1161
1234
|
closeProcess = async () => {
|
|
1162
1235
|
this.#connection.close();
|
|
1163
|
-
await
|
|
1236
|
+
await stopProcessTree(this.#child);
|
|
1164
1237
|
};
|
|
1165
1238
|
race = async (operation, exitMessage, signal) => {
|
|
1166
1239
|
signal.throwIfAborted();
|
|
@@ -1253,6 +1326,7 @@ class AcpProcessSession {
|
|
|
1253
1326
|
};
|
|
1254
1327
|
}
|
|
1255
1328
|
export class AcpSessionManager {
|
|
1329
|
+
#nativeOperations = new Set();
|
|
1256
1330
|
#activeSessionIds = new Set();
|
|
1257
1331
|
#cancellationRequests = new Set();
|
|
1258
1332
|
#preparing = new Map();
|
|
@@ -1298,6 +1372,12 @@ export class AcpSessionManager {
|
|
|
1298
1372
|
return await operation;
|
|
1299
1373
|
}
|
|
1300
1374
|
prepareSession = async (options) => {
|
|
1375
|
+
const stored = this.#store.read(options.sessionId);
|
|
1376
|
+
if (stored instanceof DeletedAcpStoredSession)
|
|
1377
|
+
throw new AcpExecutionError("The native Agent session was deleted. Start a new chat.", {}, "native_session_deleted");
|
|
1378
|
+
if (stored instanceof FoundAcpStoredSession &&
|
|
1379
|
+
this.#nativeOperations.has(`${stored.session.agentId}:${stored.session.nativeSessionId}`))
|
|
1380
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1301
1381
|
const pending = this.#preparing.get(options.sessionId);
|
|
1302
1382
|
if (pending !== undefined) {
|
|
1303
1383
|
const runtime = await pending;
|
|
@@ -1332,6 +1412,11 @@ export class AcpSessionManager {
|
|
|
1332
1412
|
}
|
|
1333
1413
|
};
|
|
1334
1414
|
runPrompt = async (options) => {
|
|
1415
|
+
const stored = this.#store.read(options.sessionId);
|
|
1416
|
+
if (stored instanceof FoundAcpStoredSession &&
|
|
1417
|
+
this.#nativeOperations.has(`${stored.session.agentId}:${stored.session.nativeSessionId}`)) {
|
|
1418
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1419
|
+
}
|
|
1335
1420
|
if (this.#activeSessionIds.has(options.sessionId)) {
|
|
1336
1421
|
throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
|
|
1337
1422
|
}
|
|
@@ -1341,6 +1426,8 @@ export class AcpSessionManager {
|
|
|
1341
1426
|
return { stopReason: "cancelled" };
|
|
1342
1427
|
}
|
|
1343
1428
|
const runtime = await this.ensureSession(options);
|
|
1429
|
+
if (this.#nativeOperations.has(`${options.agent.id}:${runtime.nativeSessionId()}`))
|
|
1430
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1344
1431
|
if (this.#cancellationRequests.has(options.sessionId)) {
|
|
1345
1432
|
return { stopReason: "cancelled" };
|
|
1346
1433
|
}
|
|
@@ -1398,5 +1485,103 @@ export class AcpSessionManager {
|
|
|
1398
1485
|
}
|
|
1399
1486
|
return started;
|
|
1400
1487
|
};
|
|
1488
|
+
listNativeSessions = async (options, cursor) => await (await this.ensureSession(options)).listNativeSessions(cursor, options.signal);
|
|
1489
|
+
openNativeSession = async (options, origin) => {
|
|
1490
|
+
const key = `${options.agent.id}:${origin.nativeSessionId}`;
|
|
1491
|
+
if (this.#nativeOperations.has(key))
|
|
1492
|
+
throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
|
|
1493
|
+
const linked = this.#store.findNative(options.agent.id, origin.nativeSessionId);
|
|
1494
|
+
if (linked.some((entry) => this.#activeSessionIds.has(entry.sessionId) ||
|
|
1495
|
+
this.#preparing.has(entry.sessionId)))
|
|
1496
|
+
throw new AcpExecutionError("Wait for the native session's running operation to finish", {}, "session_busy");
|
|
1497
|
+
const existing = linked[0];
|
|
1498
|
+
if (origin.kind === "import" && existing !== undefined) {
|
|
1499
|
+
const runtime = await this.ensureSession({
|
|
1500
|
+
...options,
|
|
1501
|
+
sessionId: existing.sessionId,
|
|
1502
|
+
});
|
|
1503
|
+
if (this.#activeSessionIds.has(existing.sessionId) ||
|
|
1504
|
+
this.#nativeOperations.has(key))
|
|
1505
|
+
throw new AcpExecutionError("Wait for the native session's running operation to finish", {}, "session_busy");
|
|
1506
|
+
this.#nativeOperations.add(key);
|
|
1507
|
+
try {
|
|
1508
|
+
const history = await runtime.loadHistory(options.signal);
|
|
1509
|
+
return {
|
|
1510
|
+
prepared: runtime.prepared(),
|
|
1511
|
+
sessionId: existing.sessionId,
|
|
1512
|
+
history,
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
catch (error) {
|
|
1516
|
+
this.#sessions.delete(existing.sessionId);
|
|
1517
|
+
await runtime.closeProcess();
|
|
1518
|
+
throw error;
|
|
1519
|
+
}
|
|
1520
|
+
finally {
|
|
1521
|
+
this.#nativeOperations.delete(key);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
if (this.#sessions.has(options.sessionId) ||
|
|
1525
|
+
this.#preparing.has(options.sessionId) ||
|
|
1526
|
+
this.#store.read(options.sessionId) instanceof FoundAcpStoredSession ||
|
|
1527
|
+
this.#store.read(options.sessionId) instanceof DeletedAcpStoredSession)
|
|
1528
|
+
throw new AcpExecutionError("The destination conversation already exists", {}, "session_identity_mismatch");
|
|
1529
|
+
this.#nativeOperations.add(key);
|
|
1530
|
+
try {
|
|
1531
|
+
const runtime = await this.#startPreparation({ ...options, origin });
|
|
1532
|
+
const openedKey = `${options.agent.id}:${runtime.nativeSessionId()}`;
|
|
1533
|
+
this.#nativeOperations.add(openedKey);
|
|
1534
|
+
try {
|
|
1535
|
+
const history = await runtime.loadHistory(options.signal);
|
|
1536
|
+
return {
|
|
1537
|
+
sessionId: options.sessionId,
|
|
1538
|
+
prepared: runtime.prepared(),
|
|
1539
|
+
history,
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
catch (error) {
|
|
1543
|
+
this.#sessions.delete(options.sessionId);
|
|
1544
|
+
this.#store.remove(options.sessionId);
|
|
1545
|
+
await runtime.closeProcess();
|
|
1546
|
+
throw error;
|
|
1547
|
+
}
|
|
1548
|
+
finally {
|
|
1549
|
+
this.#nativeOperations.delete(openedKey);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
finally {
|
|
1553
|
+
this.#nativeOperations.delete(key);
|
|
1554
|
+
}
|
|
1555
|
+
};
|
|
1556
|
+
deleteNativeSession = async (options, nativeSessionId) => {
|
|
1557
|
+
const runtime = await this.ensureSession(options);
|
|
1558
|
+
const key = `${options.agent.id}:${nativeSessionId}`;
|
|
1559
|
+
const linked = this.#store.findNative(options.agent.id, nativeSessionId);
|
|
1560
|
+
if (this.#nativeOperations.has(key) ||
|
|
1561
|
+
linked.some((entry) => this.#activeSessionIds.has(entry.sessionId) ||
|
|
1562
|
+
this.#preparing.has(entry.sessionId)))
|
|
1563
|
+
throw new AcpExecutionError("Wait for the native session's running operation to finish", {}, "session_busy");
|
|
1564
|
+
this.#nativeOperations.add(key);
|
|
1565
|
+
try {
|
|
1566
|
+
for (const entry of linked) {
|
|
1567
|
+
const active = this.#sessions.get(entry.sessionId);
|
|
1568
|
+
if (active !== undefined && active !== runtime) {
|
|
1569
|
+
this.#sessions.delete(entry.sessionId);
|
|
1570
|
+
await active.close();
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
options.signal.throwIfAborted();
|
|
1574
|
+
await runtime.deleteNativeSession(nativeSessionId, options.signal);
|
|
1575
|
+
const deleted = this.#store.markDeleted(options.agent.id, nativeSessionId);
|
|
1576
|
+
if (runtime.nativeSessionId() === nativeSessionId) {
|
|
1577
|
+
this.#sessions.delete(options.sessionId);
|
|
1578
|
+
await runtime.close();
|
|
1579
|
+
}
|
|
1580
|
+
return deleted;
|
|
1581
|
+
}
|
|
1582
|
+
finally {
|
|
1583
|
+
this.#nativeOperations.delete(key);
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1401
1586
|
}
|
|
1402
1587
|
//# sourceMappingURL=session-manager.js.map
|