@moxt-ai/mobius 0.0.23 → 0.0.25
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/session-capabilities.d.ts +2 -2
- package/dist/acp/session-capabilities.d.ts.map +1 -1
- package/dist/acp/session-capabilities.js +16 -1
- package/dist/acp/session-capabilities.js.map +1 -1
- package/dist/acp/session-manager.d.ts +47 -6
- package/dist/acp/session-manager.d.ts.map +1 -1
- package/dist/acp/session-manager.js +250 -8
- package/dist/acp/session-manager.js.map +1 -1
- package/dist/agent-catalog/acp-readiness-probe.js +1 -1
- package/dist/agent-catalog/acp-readiness-probe.js.map +1 -1
- package/dist/agent-catalog/publish-agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog/publish-agent-catalog.js +12 -7
- package/dist/agent-catalog/publish-agent-catalog.js.map +1 -1
- package/dist/bots/local-bot-grant-store.d.ts +2 -1
- package/dist/bots/local-bot-grant-store.d.ts.map +1 -1
- package/dist/bots/local-bot-grant-store.js +8 -5
- package/dist/bots/local-bot-grant-store.js.map +1 -1
- package/dist/cli.js +949 -260
- package/dist/cli.js.map +4 -4
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1002 -216
- package/dist/index.js.map +4 -4
- package/dist/native-sessions/service.d.ts +2 -1
- package/dist/native-sessions/service.d.ts.map +1 -1
- package/dist/native-sessions/service.js +65 -0
- package/dist/native-sessions/service.js.map +1 -1
- package/dist/pairing/pair-local-machine.d.ts +8 -0
- package/dist/pairing/pair-local-machine.d.ts.map +1 -1
- package/dist/pairing/pair-local-machine.js +64 -37
- package/dist/pairing/pair-local-machine.js.map +1 -1
- package/dist/prompt-artifact-resolver.d.ts.map +1 -1
- package/dist/prompt-artifact-resolver.js +11 -3
- package/dist/prompt-artifact-resolver.js.map +1 -1
- package/dist/relay-connection/connect.d.ts.map +1 -1
- package/dist/relay-connection/connect.js +9 -1
- package/dist/relay-connection/connect.js.map +1 -1
- package/dist/relay-connection/session-event-outbox.d.ts +1 -0
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -1
- package/dist/relay-connection/session-event-outbox.js +7 -0
- package/dist/relay-connection/session-event-outbox.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +165 -54
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.d.ts +23 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +31046 -0
- package/dist/runtime.js.map +7 -0
- package/package.json +6 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InitializeResponse } from "@agentclientprotocol/sdk";
|
|
2
2
|
import type { SessionCapabilities } from "@moxt-ai/mobius-protocol";
|
|
3
3
|
export declare function unsupportedSessionCapabilities(): SessionCapabilities;
|
|
4
|
-
export declare function normalizeAcpCapabilities(
|
|
4
|
+
export declare function normalizeAcpCapabilities(initialized: InitializeResponse): SessionCapabilities;
|
|
5
5
|
//# sourceMappingURL=session-capabilities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-capabilities.d.ts","sourceRoot":"","sources":["../../src/acp/session-capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"session-capabilities.d.ts","sourceRoot":"","sources":["../../src/acp/session-capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAcpE,wBAAgB,8BAA8B,IAAI,mBAAmB,CAepE;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,kBAAkB,GAAG,mBAAmB,CAkB7F"}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function hasTrueChildField(value, childKey, fieldKey) {
|
|
5
|
+
if (!isRecord(value)) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const child = Reflect.get(value, childKey);
|
|
9
|
+
return isRecord(child) && Reflect.get(child, fieldKey) === true;
|
|
10
|
+
}
|
|
1
11
|
export function unsupportedSessionCapabilities() {
|
|
2
12
|
return Object.freeze({
|
|
3
13
|
additionalDirectories: false,
|
|
@@ -8,11 +18,14 @@ export function unsupportedSessionCapabilities() {
|
|
|
8
18
|
imagePrompt: false,
|
|
9
19
|
listSessions: false,
|
|
10
20
|
loadSession: false,
|
|
21
|
+
promptQueueing: false,
|
|
11
22
|
resumeSession: false,
|
|
23
|
+
steering: false,
|
|
12
24
|
unstableForkSession: false,
|
|
13
25
|
});
|
|
14
26
|
}
|
|
15
|
-
export function normalizeAcpCapabilities(
|
|
27
|
+
export function normalizeAcpCapabilities(initialized) {
|
|
28
|
+
const capabilities = initialized.agentCapabilities ?? {};
|
|
16
29
|
const session = capabilities.sessionCapabilities;
|
|
17
30
|
const prompt = capabilities.promptCapabilities;
|
|
18
31
|
return Object.freeze({
|
|
@@ -24,7 +37,9 @@ export function normalizeAcpCapabilities(capabilities) {
|
|
|
24
37
|
imagePrompt: prompt?.image === true,
|
|
25
38
|
listSessions: session?.list != null,
|
|
26
39
|
loadSession: capabilities.loadSession === true,
|
|
40
|
+
promptQueueing: hasTrueChildField(capabilities._meta, "claudeCode", "promptQueueing"),
|
|
27
41
|
resumeSession: session?.resume != null,
|
|
42
|
+
steering: hasTrueChildField(initialized._meta, "steering", "supported"),
|
|
28
43
|
unstableForkSession: session?.fork != null,
|
|
29
44
|
});
|
|
30
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-capabilities.js","sourceRoot":"","sources":["../../src/acp/session-capabilities.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,8BAA8B;IAC1C,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,qBAAqB,EAAE,KAAK;QAC5B,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,KAAK;QACpB,qBAAqB,EAAE,KAAK;QAC5B,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE,KAAK;QACpB,mBAAmB,EAAE,KAAK;KAC7B,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,
|
|
1
|
+
{"version":3,"file":"session-capabilities.js","sourceRoot":"","sources":["../../src/acp/session-capabilities.ts"],"names":[],"mappings":"AAGA,SAAS,QAAQ,CAAC,KAAc;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,QAAgB,EAAE,QAAgB;IACzE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC3C,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC1C,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,qBAAqB,EAAE,KAAK;QAC5B,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,KAAK;QACpB,qBAAqB,EAAE,KAAK;QAC5B,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,KAAK;QAClB,cAAc,EAAE,KAAK;QACrB,aAAa,EAAE,KAAK;QACpB,QAAQ,EAAE,KAAK;QACf,mBAAmB,EAAE,KAAK;KAC7B,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,WAA+B;IACpE,MAAM,YAAY,GAAG,WAAW,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACzD,MAAM,OAAO,GAAG,YAAY,CAAC,mBAAmB,CAAC;IACjD,MAAM,MAAM,GAAG,YAAY,CAAC,kBAAkB,CAAC;IAC/C,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,qBAAqB,EAAE,OAAO,EAAE,qBAAqB,IAAI,IAAI;QAC7D,WAAW,EAAE,MAAM,EAAE,KAAK,KAAK,IAAI;QACnC,YAAY,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;QACpC,aAAa,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;QACtC,qBAAqB,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI;QACvD,WAAW,EAAE,MAAM,EAAE,KAAK,KAAK,IAAI;QACnC,YAAY,EAAE,OAAO,EAAE,IAAI,IAAI,IAAI;QACnC,WAAW,EAAE,YAAY,CAAC,WAAW,KAAK,IAAI;QAC9C,cAAc,EAAE,iBAAiB,CAAC,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,gBAAgB,CAAC;QACrF,aAAa,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;QACtC,QAAQ,EAAE,iBAAiB,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC;QACvE,mBAAmB,EAAE,OAAO,EAAE,IAAI,IAAI,IAAI;KAC7C,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CompleteElicitationNotification, type CreateElicitationRequest, type CreateElicitationResponse, type RequestPermissionRequest, type RequestPermissionResponse, type SessionNotification } from "@agentclientprotocol/sdk";
|
|
1
|
+
import { type CompleteElicitationNotification, type ContentBlock, type CreateElicitationRequest, type CreateElicitationResponse, type RequestPermissionRequest, type RequestPermissionResponse, type SessionNotification } from "@agentclientprotocol/sdk";
|
|
2
2
|
import { type AgentContentEvent, type AgentPromptResponse, type NativeSessionHistory, type PromptImage, type PromptResource, type SessionCapabilities, type SessionCommand, type SessionCommandsUpdatedEvent, type SessionConfigOption, type SessionConfigUpdatedEvent, type SessionElicitationRequestedEvent, type SessionElicitationResolvedEvent, type SessionInfoUpdatedEvent, type SessionPermissionRequestedEvent, type SessionPermissionResolvedEvent, type SessionUsageUpdatedEvent } from "@moxt-ai/mobius-protocol";
|
|
3
3
|
import type { LocalAgentDefinition } from "../config.ts";
|
|
4
4
|
import { type ProcessTreeIdentity } from "../process/executable.ts";
|
|
@@ -21,14 +21,27 @@ export interface AcpConfigureOptions extends AcpPrepareOptions {
|
|
|
21
21
|
readonly value: string;
|
|
22
22
|
readonly valueType: SessionConfigOption["type"];
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
readonly commandId: string;
|
|
24
|
+
interface AcpPromptContentOptions {
|
|
26
25
|
readonly images: readonly PromptImage[];
|
|
27
|
-
readonly onActivity: (activity: AcpActivity) => Promise<void>;
|
|
28
|
-
readonly onText: (text: string) => Promise<void>;
|
|
29
26
|
readonly prompt: string;
|
|
30
27
|
readonly resources: readonly PromptResource[];
|
|
31
28
|
}
|
|
29
|
+
export interface AcpTurnOptions extends AcpPrepareOptions, AcpPromptContentOptions {
|
|
30
|
+
readonly commandId: string;
|
|
31
|
+
readonly disposition?: string;
|
|
32
|
+
readonly onActivity: (activity: AcpActivity) => Promise<void>;
|
|
33
|
+
readonly onText: (text: string, messageId: string) => Promise<void>;
|
|
34
|
+
readonly targetCommandId?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface AcpSteerOptions extends AcpPrepareOptions, AcpPromptContentOptions {
|
|
37
|
+
readonly commandId: string;
|
|
38
|
+
readonly targetCommandId: string;
|
|
39
|
+
}
|
|
40
|
+
export interface AcpSessionForkPoint {
|
|
41
|
+
readonly messageFingerprint: string;
|
|
42
|
+
readonly messageId: string;
|
|
43
|
+
readonly messageOccurrence: number;
|
|
44
|
+
}
|
|
32
45
|
export interface AcpPermissionResponseOptions {
|
|
33
46
|
readonly interactionId: string;
|
|
34
47
|
readonly optionId: string;
|
|
@@ -83,16 +96,20 @@ declare class AcpProcessSession implements AcpClientHandler {
|
|
|
83
96
|
private constructor();
|
|
84
97
|
static readonly start: (options: AcpPrepareOptions, getObserver: () => AcpSessionObserver, store: AcpSessionStore) => Promise<AcpProcessSession>;
|
|
85
98
|
static readonly startNativeSessionBrowser: (options: AcpPrepareOptions, getObserver: () => AcpSessionObserver, store: AcpSessionStore) => Promise<AcpProcessSession>;
|
|
99
|
+
static readonly startSessionForkAtTurn: (options: AcpPrepareOptions, sourceNativeSessionId: string, forkPoint: AcpSessionForkPoint, getObserver: () => AcpSessionObserver, store: AcpSessionStore) => Promise<AcpProcessSession>;
|
|
86
100
|
readonly belongsTo: (agentId: string, cwd: string, additionalDirectories: readonly string[]) => boolean;
|
|
101
|
+
readonly usesEnvironment: (environment: Readonly<Record<string, string>>) => boolean;
|
|
87
102
|
readonly canRebind: () => boolean;
|
|
88
103
|
readonly prepared: () => AcpPreparedSession;
|
|
89
104
|
readonly loadHistory: (signal: AbortSignal) => Promise<NativeSessionHistory>;
|
|
90
|
-
readonly initialize: (signal: AbortSignal, origin?: NativeSessionOrigin) => Promise<void>;
|
|
105
|
+
readonly initialize: (signal: AbortSignal, origin?: NativeSessionOrigin, forkPoint?: AcpSessionForkPoint) => Promise<void>;
|
|
91
106
|
readonly listNativeSessions: (cursor: string | null, signal: AbortSignal) => Promise<NativeSessionPage>;
|
|
92
107
|
readonly deleteNativeSession: (nativeSessionId: string, signal: AbortSignal) => Promise<void>;
|
|
93
108
|
readonly nativeSessionId: () => string;
|
|
94
109
|
readonly configure: (options: AcpConfigureOptions) => Promise<readonly SessionConfigOption[]>;
|
|
110
|
+
readonly buildPrompt: (options: AcpPromptContentOptions) => ContentBlock[];
|
|
95
111
|
readonly prompt: (options: AcpTurnOptions) => Promise<AcpPromptResult>;
|
|
112
|
+
readonly steer: (options: AcpSteerOptions) => Promise<string>;
|
|
96
113
|
readonly cancel: () => Promise<void>;
|
|
97
114
|
readonly respondPermission: (options: AcpPermissionResponseOptions) => Promise<void>;
|
|
98
115
|
readonly respondElicitation: (options: AcpElicitationResponseOptions) => Promise<void>;
|
|
@@ -117,13 +134,16 @@ export declare class AcpSessionManager {
|
|
|
117
134
|
constructor(observer?: AcpSessionObserver, store?: AcpSessionStore);
|
|
118
135
|
readonly setObserver: (observer: AcpSessionObserver) => void;
|
|
119
136
|
readonly prepareSession: (options: AcpPrepareOptions) => Promise<AcpPreparedSession>;
|
|
137
|
+
readonly prepareExecutionSession: (options: AcpPrepareOptions) => Promise<AcpPreparedSession>;
|
|
120
138
|
readonly prepareNativeSessionBrowser: (options: AcpPrepareOptions) => Promise<AcpPreparedSession>;
|
|
121
139
|
readonly configureSession: (options: AcpConfigureOptions) => Promise<readonly SessionConfigOption[]>;
|
|
122
140
|
readonly cancelPrompt: (sessionId: string) => Promise<void>;
|
|
141
|
+
readonly steerPrompt: (options: AcpSteerOptions) => Promise<string>;
|
|
123
142
|
readonly runPrompt: (options: AcpTurnOptions) => Promise<AcpPromptResult>;
|
|
124
143
|
readonly respondPermission: (options: AcpPermissionResponseOptions) => Promise<void>;
|
|
125
144
|
readonly respondElicitation: (options: AcpElicitationResponseOptions) => Promise<void>;
|
|
126
145
|
readonly close: () => Promise<void>;
|
|
146
|
+
readonly hasPreparedSession: (sessionId: string, agentId: string, cwd: string, additionalDirectories: readonly string[]) => boolean;
|
|
127
147
|
readonly ensureSession: (options: AcpPrepareOptions) => Promise<AcpProcessSession>;
|
|
128
148
|
readonly listNativeSessions: (options: AcpPrepareOptions, cursor: string | null) => Promise<NativeSessionPage>;
|
|
129
149
|
readonly openNativeSession: (options: AcpPrepareOptions, origin: NativeSessionOrigin) => Promise<{
|
|
@@ -131,6 +151,27 @@ export declare class AcpSessionManager {
|
|
|
131
151
|
readonly prepared: AcpPreparedSession;
|
|
132
152
|
readonly history: NativeSessionHistory;
|
|
133
153
|
}>;
|
|
154
|
+
readonly forkSessionAtTurn: (options: AcpPrepareOptions, sourceSessionId: string, forkPoint: AcpSessionForkPoint) => Promise<{
|
|
155
|
+
history: Readonly<{
|
|
156
|
+
status: "available";
|
|
157
|
+
messages: readonly Readonly<{
|
|
158
|
+
role: "assistant" | "user";
|
|
159
|
+
text: string;
|
|
160
|
+
images?: readonly Readonly<{
|
|
161
|
+
data: string;
|
|
162
|
+
mimeType: "image/gif" | "image/jpeg" | "image/png" | "image/webp";
|
|
163
|
+
name: string;
|
|
164
|
+
}>[] | undefined;
|
|
165
|
+
}>[];
|
|
166
|
+
truncated: boolean;
|
|
167
|
+
coveredCommandIds: readonly string[];
|
|
168
|
+
coveredMessageIds: readonly string[];
|
|
169
|
+
}> | Readonly<{
|
|
170
|
+
status: "unavailable";
|
|
171
|
+
}>;
|
|
172
|
+
prepared: AcpPreparedSession;
|
|
173
|
+
sessionId: string;
|
|
174
|
+
}>;
|
|
134
175
|
readonly deleteNativeSession: (options: AcpPrepareOptions, nativeSessionId: string) => Promise<readonly string[]>;
|
|
135
176
|
}
|
|
136
177
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/acp/session-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,+BAA+B,
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/acp/session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -142,6 +142,11 @@ function readString(value, fallback = "") {
|
|
|
142
142
|
function arraysEqual(left, right) {
|
|
143
143
|
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
144
144
|
}
|
|
145
|
+
function recordsEqual(left, right) {
|
|
146
|
+
const leftEntries = Object.entries(left);
|
|
147
|
+
const rightEntries = Object.entries(right);
|
|
148
|
+
return leftEntries.length === rightEntries.length && leftEntries.every(([name, value]) => right[name] === value);
|
|
149
|
+
}
|
|
145
150
|
function elicitationFieldType(value) {
|
|
146
151
|
if (value === "boolean") {
|
|
147
152
|
return "boolean";
|
|
@@ -416,6 +421,7 @@ class AcpProcessSession {
|
|
|
416
421
|
#child;
|
|
417
422
|
#connection;
|
|
418
423
|
#cwd;
|
|
424
|
+
#environment;
|
|
419
425
|
#getObserver;
|
|
420
426
|
#mobiusSessionId;
|
|
421
427
|
#pendingElicitations = new Map();
|
|
@@ -437,7 +443,9 @@ class AcpProcessSession {
|
|
|
437
443
|
imagePrompt: false,
|
|
438
444
|
listSessions: false,
|
|
439
445
|
loadSession: false,
|
|
446
|
+
promptQueueing: false,
|
|
440
447
|
resumeSession: false,
|
|
448
|
+
steering: false,
|
|
441
449
|
unstableForkSession: false,
|
|
442
450
|
};
|
|
443
451
|
#commands = [];
|
|
@@ -457,6 +465,7 @@ class AcpProcessSession {
|
|
|
457
465
|
this.#additionalDirectories = [...additionalDirectories];
|
|
458
466
|
this.#agentId = agent.id;
|
|
459
467
|
this.#cwd = cwd;
|
|
468
|
+
this.#environment = agent.environment;
|
|
460
469
|
this.#getObserver = getObserver;
|
|
461
470
|
this.#mobiusSessionId = mobiusSessionId;
|
|
462
471
|
this.#sessionConfigProtocol = sessionConfigProtocolForAgent(agent.id);
|
|
@@ -522,9 +531,11 @@ class AcpProcessSession {
|
|
|
522
531
|
}
|
|
523
532
|
static start = async (options, getObserver, store) => await AcpProcessSession.#start(options, getObserver, store, async (runtime) => await runtime.initialize(options.signal, options.origin));
|
|
524
533
|
static startNativeSessionBrowser = async (options, getObserver, store) => await AcpProcessSession.#start(options, getObserver, store, async (runtime) => await runtime.#initializeAgent(options.signal));
|
|
534
|
+
static startSessionForkAtTurn = async (options, sourceNativeSessionId, forkPoint, getObserver, store) => await AcpProcessSession.#start(options, getObserver, store, async (runtime) => await runtime.initialize(options.signal, { kind: "fork", nativeSessionId: sourceNativeSessionId }, forkPoint));
|
|
525
535
|
belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId &&
|
|
526
536
|
this.#cwd === cwd &&
|
|
527
537
|
arraysEqual(this.#additionalDirectories, additionalDirectories);
|
|
538
|
+
usesEnvironment = (environment) => recordsEqual(this.#environment, environment);
|
|
528
539
|
canRebind = () => !this.#prompted && !this.#turn.running;
|
|
529
540
|
prepared = () => new AcpPreparedSession(this.#agentName, this.#agentVersion, this.#capabilities, this.#commands, this.#configOptions, this.#restored);
|
|
530
541
|
loadHistory = async (signal) => {
|
|
@@ -564,12 +575,11 @@ class AcpProcessSession {
|
|
|
564
575
|
if (initialized.protocolVersion !== PROTOCOL_VERSION) {
|
|
565
576
|
throw new AcpExecutionError("ACP agent selected an unsupported protocol version", {}, "unsupported_acp_protocol");
|
|
566
577
|
}
|
|
567
|
-
|
|
568
|
-
this.#capabilities = normalizeAcpCapabilities(capabilities);
|
|
578
|
+
this.#capabilities = normalizeAcpCapabilities(initialized);
|
|
569
579
|
this.#agentName = truncate(initialized.agentInfo?.title ?? initialized.agentInfo?.name ?? this.#agentId, 255);
|
|
570
580
|
this.#agentVersion = truncate(this.#verifiedAgentVersion.length > 0 ? this.#verifiedAgentVersion : (initialized.agentInfo?.version ?? ""), 128);
|
|
571
581
|
}
|
|
572
|
-
initialize = async (signal, origin) => {
|
|
582
|
+
initialize = async (signal, origin, forkPoint) => {
|
|
573
583
|
await this.#initializeAgent(signal);
|
|
574
584
|
let stored = origin?.kind === "import"
|
|
575
585
|
? new FoundAcpStoredSession(new AcpStoredSession(this.#mobiusSessionId, this.#agentId, nativeSessionIdSchema.parse(origin.nativeSessionId), this.#cwd, this.#additionalDirectories, true))
|
|
@@ -586,11 +596,30 @@ class AcpProcessSession {
|
|
|
586
596
|
if (!this.#capabilities.unstableForkSession) {
|
|
587
597
|
throw new AcpExecutionError("This Agent does not support session forking", {}, "native_session_unsupported");
|
|
588
598
|
}
|
|
599
|
+
if (this.#additionalDirectories.length > 0 && !this.#capabilities.additionalDirectories) {
|
|
600
|
+
throw new AcpExecutionError("This Agent cannot restore additional working directories", {}, "native_session_unsupported");
|
|
601
|
+
}
|
|
589
602
|
const forked = await this.race(this.#connection.agent.request(methods.agent.session.fork, {
|
|
590
603
|
sessionId: nativeSessionIdSchema.parse(origin.nativeSessionId),
|
|
591
604
|
cwd: this.#cwd,
|
|
592
605
|
additionalDirectories: [...this.#additionalDirectories],
|
|
593
606
|
mcpServers: [],
|
|
607
|
+
...(forkPoint === undefined
|
|
608
|
+
? {}
|
|
609
|
+
: {
|
|
610
|
+
_meta: {
|
|
611
|
+
jetbrains: {
|
|
612
|
+
air: {
|
|
613
|
+
fork: {
|
|
614
|
+
version: 1,
|
|
615
|
+
messageFingerprint: forkPoint.messageFingerprint,
|
|
616
|
+
messageId: forkPoint.messageId,
|
|
617
|
+
messageOccurrence: forkPoint.messageOccurrence,
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
}),
|
|
594
623
|
}, { cancellationSignal: signal }), "ACP agent exited while forking a session", signal);
|
|
595
624
|
this.selectNativeSession(forked.sessionId);
|
|
596
625
|
if (this.#nativeSessionId === origin.nativeSessionId ||
|
|
@@ -710,10 +739,7 @@ class AcpProcessSession {
|
|
|
710
739
|
}
|
|
711
740
|
return this.#configOptions;
|
|
712
741
|
};
|
|
713
|
-
|
|
714
|
-
if (this.#turn.running) {
|
|
715
|
-
throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
|
|
716
|
-
}
|
|
742
|
+
buildPrompt = (options) => {
|
|
717
743
|
if (options.images.length > 0 && !this.#capabilities.imagePrompt) {
|
|
718
744
|
throw new AcpExecutionError("The selected agent does not accept image prompts", {}, "unsupported_prompt_content");
|
|
719
745
|
}
|
|
@@ -756,6 +782,13 @@ class AcpProcessSession {
|
|
|
756
782
|
if (prompt.length === 0) {
|
|
757
783
|
throw new AcpExecutionError("A prompt must contain text or an attachment", {}, "empty_prompt");
|
|
758
784
|
}
|
|
785
|
+
return prompt;
|
|
786
|
+
};
|
|
787
|
+
prompt = async (options) => {
|
|
788
|
+
if (this.#turn.running) {
|
|
789
|
+
throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
|
|
790
|
+
}
|
|
791
|
+
const prompt = this.buildPrompt(options);
|
|
759
792
|
this.#store.write(new AcpStoredSession(this.#mobiusSessionId, this.#agentId, this.#nativeSessionId, this.#cwd, this.#additionalDirectories, true));
|
|
760
793
|
this.#prompted = true;
|
|
761
794
|
const running = new RunningAcpTurn(options.commandId, options.onActivity, options.onText);
|
|
@@ -796,6 +829,34 @@ class AcpProcessSession {
|
|
|
796
829
|
this.#turn = new IdleAcpTurn();
|
|
797
830
|
}
|
|
798
831
|
};
|
|
832
|
+
steer = async (options) => {
|
|
833
|
+
if (!this.#capabilities.steering) {
|
|
834
|
+
throw new AcpExecutionError("The selected agent does not support mid-turn steering", {}, "steering_unsupported");
|
|
835
|
+
}
|
|
836
|
+
if (!this.#turn.running || this.#turn.commandId !== options.targetCommandId) {
|
|
837
|
+
throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
|
|
838
|
+
}
|
|
839
|
+
const prompt = this.buildPrompt(options);
|
|
840
|
+
const response = await this.race(this.#connection.agent.request("_session/steering", {
|
|
841
|
+
_meta: { steering: { idleBehavior: "promptRequired" } },
|
|
842
|
+
prompt,
|
|
843
|
+
sessionId: this.#nativeSessionId,
|
|
844
|
+
}), "ACP agent exited during steering", options.signal);
|
|
845
|
+
if (!isRecord(response)) {
|
|
846
|
+
throw new AcpExecutionError("ACP agent returned an invalid steering response", {}, "acp_invalid_steering_response");
|
|
847
|
+
}
|
|
848
|
+
const outcome = response["outcome"];
|
|
849
|
+
if (outcome === "injected" || outcome === "startedNewTurn") {
|
|
850
|
+
return outcome;
|
|
851
|
+
}
|
|
852
|
+
if (outcome === "promptRequired") {
|
|
853
|
+
throw new AcpExecutionError("The target turn finished before steering could be injected", {}, "steering_target_unavailable");
|
|
854
|
+
}
|
|
855
|
+
if (outcome === "failed") {
|
|
856
|
+
throw new AcpExecutionError("The Agent could not inject steering", {}, "steering_failed");
|
|
857
|
+
}
|
|
858
|
+
throw new AcpExecutionError("ACP agent returned an invalid steering response", {}, "acp_invalid_steering_response");
|
|
859
|
+
};
|
|
799
860
|
cancel = async () => {
|
|
800
861
|
const capturedProcesses = await captureProcessTree(this.#child);
|
|
801
862
|
try {
|
|
@@ -1008,7 +1069,7 @@ class AcpProcessSession {
|
|
|
1008
1069
|
}
|
|
1009
1070
|
else {
|
|
1010
1071
|
await this.#turn.activities.finishNarrative();
|
|
1011
|
-
await this.#turn.onText(update.content.text);
|
|
1072
|
+
await this.#turn.onText(update.content.text, truncate(update.messageId ?? "", 255));
|
|
1012
1073
|
}
|
|
1013
1074
|
}
|
|
1014
1075
|
else {
|
|
@@ -1225,6 +1286,7 @@ class AcpProcessSession {
|
|
|
1225
1286
|
};
|
|
1226
1287
|
}
|
|
1227
1288
|
export class AcpSessionManager {
|
|
1289
|
+
#activeCommandIds = new Map();
|
|
1228
1290
|
#nativeOperations = new Set();
|
|
1229
1291
|
#nativeBrowserObserver = new NullAcpSessionObserver();
|
|
1230
1292
|
#nativeBrowserPreparing = new Map();
|
|
@@ -1288,6 +1350,20 @@ export class AcpSessionManager {
|
|
|
1288
1350
|
this.#preparing.set(options.sessionId, operation);
|
|
1289
1351
|
return await operation;
|
|
1290
1352
|
}
|
|
1353
|
+
async #startSessionForkAtTurnPreparation(options, sourceNativeSessionId, forkPoint) {
|
|
1354
|
+
const operation = (async () => {
|
|
1355
|
+
try {
|
|
1356
|
+
const runtime = await AcpProcessSession.startSessionForkAtTurn(options, sourceNativeSessionId, forkPoint, () => this.#observer, this.#store);
|
|
1357
|
+
this.#sessions.set(options.sessionId, runtime);
|
|
1358
|
+
return runtime;
|
|
1359
|
+
}
|
|
1360
|
+
finally {
|
|
1361
|
+
this.#preparing.delete(options.sessionId);
|
|
1362
|
+
}
|
|
1363
|
+
})();
|
|
1364
|
+
this.#preparing.set(options.sessionId, operation);
|
|
1365
|
+
return await operation;
|
|
1366
|
+
}
|
|
1291
1367
|
async #replacePreparation(existing, options) {
|
|
1292
1368
|
const operation = (async () => {
|
|
1293
1369
|
try {
|
|
@@ -1305,6 +1381,61 @@ export class AcpSessionManager {
|
|
|
1305
1381
|
this.#preparing.set(options.sessionId, operation);
|
|
1306
1382
|
return await operation;
|
|
1307
1383
|
}
|
|
1384
|
+
async #replaceExecutionPreparation(existing, options) {
|
|
1385
|
+
const desiredConfigOptions = existing.prepared().configOptions;
|
|
1386
|
+
const operation = (async () => {
|
|
1387
|
+
try {
|
|
1388
|
+
this.#sessions.delete(options.sessionId);
|
|
1389
|
+
await existing.close();
|
|
1390
|
+
this.#store.remove(options.sessionId);
|
|
1391
|
+
const runtime = await AcpProcessSession.start(options, () => this.#observer, this.#store);
|
|
1392
|
+
try {
|
|
1393
|
+
for (const desired of desiredConfigOptions) {
|
|
1394
|
+
const current = runtime.prepared().configOptions.find((option) => option.id === desired.id);
|
|
1395
|
+
if (current === undefined || current.type !== desired.type) {
|
|
1396
|
+
continue;
|
|
1397
|
+
}
|
|
1398
|
+
if (desired.type === "boolean") {
|
|
1399
|
+
if (current.booleanValue !== desired.booleanValue) {
|
|
1400
|
+
await runtime.configure({
|
|
1401
|
+
...options,
|
|
1402
|
+
booleanValue: desired.booleanValue,
|
|
1403
|
+
configId: desired.id,
|
|
1404
|
+
requestId: `execution-prepare-${desired.id}`,
|
|
1405
|
+
value: "",
|
|
1406
|
+
valueType: "boolean",
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
continue;
|
|
1410
|
+
}
|
|
1411
|
+
if (current.currentValue !== desired.currentValue &&
|
|
1412
|
+
current.values.some((value) => value.value === desired.currentValue)) {
|
|
1413
|
+
await runtime.configure({
|
|
1414
|
+
...options,
|
|
1415
|
+
booleanValue: false,
|
|
1416
|
+
configId: desired.id,
|
|
1417
|
+
requestId: `execution-prepare-${desired.id}`,
|
|
1418
|
+
value: desired.currentValue,
|
|
1419
|
+
valueType: "select",
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
catch (error) {
|
|
1425
|
+
await runtime.close();
|
|
1426
|
+
this.#store.remove(options.sessionId);
|
|
1427
|
+
throw error;
|
|
1428
|
+
}
|
|
1429
|
+
this.#sessions.set(options.sessionId, runtime);
|
|
1430
|
+
return runtime;
|
|
1431
|
+
}
|
|
1432
|
+
finally {
|
|
1433
|
+
this.#preparing.delete(options.sessionId);
|
|
1434
|
+
}
|
|
1435
|
+
})();
|
|
1436
|
+
this.#preparing.set(options.sessionId, operation);
|
|
1437
|
+
return await operation;
|
|
1438
|
+
}
|
|
1308
1439
|
prepareSession = async (options) => {
|
|
1309
1440
|
const stored = this.#store.read(options.sessionId);
|
|
1310
1441
|
if (stored instanceof DeletedAcpStoredSession) {
|
|
@@ -1336,6 +1467,27 @@ export class AcpSessionManager {
|
|
|
1336
1467
|
const runtime = await this.#startPreparation(options);
|
|
1337
1468
|
return runtime.prepared();
|
|
1338
1469
|
};
|
|
1470
|
+
prepareExecutionSession = async (options) => {
|
|
1471
|
+
const pending = this.#preparing.get(options.sessionId);
|
|
1472
|
+
if (pending !== undefined) {
|
|
1473
|
+
await pending;
|
|
1474
|
+
return await this.prepareExecutionSession(options);
|
|
1475
|
+
}
|
|
1476
|
+
const existing = this.#sessions.get(options.sessionId);
|
|
1477
|
+
if (existing === undefined) {
|
|
1478
|
+
return (await this.#startPreparation(options)).prepared();
|
|
1479
|
+
}
|
|
1480
|
+
if (!existing.belongsTo(options.agent.id, options.cwd, options.additionalDirectories)) {
|
|
1481
|
+
throw new AcpExecutionError("The agent or workspace cannot change after a conversation has started", {}, "session_identity_mismatch");
|
|
1482
|
+
}
|
|
1483
|
+
if (existing.usesEnvironment(options.agent.environment)) {
|
|
1484
|
+
return existing.prepared();
|
|
1485
|
+
}
|
|
1486
|
+
if (!existing.canRebind()) {
|
|
1487
|
+
throw new AcpExecutionError("The execution environment cannot change after a conversation has started", {}, "session_identity_mismatch");
|
|
1488
|
+
}
|
|
1489
|
+
return (await this.#replaceExecutionPreparation(existing, options)).prepared();
|
|
1490
|
+
};
|
|
1339
1491
|
prepareNativeSessionBrowser = async (options) => {
|
|
1340
1492
|
const pending = this.#nativeBrowserPreparing.get(options.sessionId);
|
|
1341
1493
|
if (pending !== undefined) {
|
|
@@ -1377,6 +1529,40 @@ export class AcpSessionManager {
|
|
|
1377
1529
|
}
|
|
1378
1530
|
}
|
|
1379
1531
|
};
|
|
1532
|
+
steerPrompt = async (options) => {
|
|
1533
|
+
if (this.#activeCommandIds.get(options.sessionId) !== options.targetCommandId) {
|
|
1534
|
+
throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
|
|
1535
|
+
}
|
|
1536
|
+
const pending = this.#preparing.get(options.sessionId);
|
|
1537
|
+
if (pending !== undefined) {
|
|
1538
|
+
await pending;
|
|
1539
|
+
}
|
|
1540
|
+
if (this.#activeCommandIds.get(options.sessionId) !== options.targetCommandId) {
|
|
1541
|
+
throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
|
|
1542
|
+
}
|
|
1543
|
+
const runtime = this.#sessions.get(options.sessionId);
|
|
1544
|
+
if (runtime === undefined || !runtime.belongsTo(options.agent.id, options.cwd, options.additionalDirectories)) {
|
|
1545
|
+
throw new AcpExecutionError("The target turn execution context is unavailable", {}, "steering_target_unavailable");
|
|
1546
|
+
}
|
|
1547
|
+
const deadlineController = new AbortController();
|
|
1548
|
+
const deadline = setTimeout(() => deadlineController.abort(new AcpExecutionError("The steering request exceeded its deadline", {}, "steering_timeout")), options.agent.promptTimeoutMilliseconds);
|
|
1549
|
+
deadline.unref();
|
|
1550
|
+
try {
|
|
1551
|
+
return await runtime.steer({
|
|
1552
|
+
...options,
|
|
1553
|
+
signal: AbortSignal.any([options.signal, deadlineController.signal]),
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
catch (error) {
|
|
1557
|
+
if (error instanceof AcpExecutionError) {
|
|
1558
|
+
throw error;
|
|
1559
|
+
}
|
|
1560
|
+
throw new AcpExecutionError("ACP agent steering failed", { cause: error }, "steering_failed");
|
|
1561
|
+
}
|
|
1562
|
+
finally {
|
|
1563
|
+
clearTimeout(deadline);
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1380
1566
|
runPrompt = async (options) => {
|
|
1381
1567
|
const stored = this.#store.read(options.sessionId);
|
|
1382
1568
|
if (stored instanceof FoundAcpStoredSession &&
|
|
@@ -1395,6 +1581,7 @@ export class AcpSessionManager {
|
|
|
1395
1581
|
signal: AbortSignal.any([options.signal, deadlineController.signal]),
|
|
1396
1582
|
};
|
|
1397
1583
|
this.#activeSessionIds.add(options.sessionId);
|
|
1584
|
+
this.#activeCommandIds.set(options.sessionId, options.commandId);
|
|
1398
1585
|
try {
|
|
1399
1586
|
if (this.#cancellationRequests.has(options.sessionId)) {
|
|
1400
1587
|
return { stopReason: "cancelled" };
|
|
@@ -1437,6 +1624,9 @@ export class AcpSessionManager {
|
|
|
1437
1624
|
finally {
|
|
1438
1625
|
clearTimeout(deadline);
|
|
1439
1626
|
this.#activeSessionIds.delete(options.sessionId);
|
|
1627
|
+
if (this.#activeCommandIds.get(options.sessionId) === options.commandId) {
|
|
1628
|
+
this.#activeCommandIds.delete(options.sessionId);
|
|
1629
|
+
}
|
|
1440
1630
|
this.#cancellationRequests.delete(options.sessionId);
|
|
1441
1631
|
}
|
|
1442
1632
|
};
|
|
@@ -1461,6 +1651,7 @@ export class AcpSessionManager {
|
|
|
1461
1651
|
this.#nativeBrowserSessions.clear();
|
|
1462
1652
|
await Promise.all([...sessions, ...nativeBrowserSessions].map(async (session) => await session.close()));
|
|
1463
1653
|
};
|
|
1654
|
+
hasPreparedSession = (sessionId, agentId, cwd, additionalDirectories) => this.#sessions.get(sessionId)?.belongsTo(agentId, cwd, additionalDirectories) === true;
|
|
1464
1655
|
ensureSession = async (options) => {
|
|
1465
1656
|
const existing = this.#sessions.get(options.sessionId);
|
|
1466
1657
|
if (existing !== undefined) {
|
|
@@ -1561,6 +1752,57 @@ export class AcpSessionManager {
|
|
|
1561
1752
|
this.#nativeOperations.delete(key);
|
|
1562
1753
|
}
|
|
1563
1754
|
};
|
|
1755
|
+
forkSessionAtTurn = async (options, sourceSessionId, forkPoint) => {
|
|
1756
|
+
if (sourceSessionId === options.sessionId) {
|
|
1757
|
+
throw new AcpExecutionError("The fork destination must be a new conversation", {}, "session_identity_mismatch");
|
|
1758
|
+
}
|
|
1759
|
+
const source = this.#store.read(sourceSessionId);
|
|
1760
|
+
if (!(source instanceof FoundAcpStoredSession) || !source.session.prompted) {
|
|
1761
|
+
throw new AcpExecutionError("The source conversation has no resumable native Agent session", {}, "native_session_not_found");
|
|
1762
|
+
}
|
|
1763
|
+
if (source.session.agentId !== options.agent.id ||
|
|
1764
|
+
source.session.cwd !== options.cwd ||
|
|
1765
|
+
!arraysEqual(source.session.additionalDirectories, options.additionalDirectories)) {
|
|
1766
|
+
throw new AcpExecutionError("The source conversation execution target does not match the fork request", {}, "native_session_target_changed");
|
|
1767
|
+
}
|
|
1768
|
+
const key = `${options.agent.id}:${source.session.nativeSessionId}`;
|
|
1769
|
+
const linked = this.#store.findNative(options.agent.id, source.session.nativeSessionId);
|
|
1770
|
+
if (this.#nativeOperations.has(key) ||
|
|
1771
|
+
linked.some((entry) => this.#activeSessionIds.has(entry.sessionId) || this.#preparing.has(entry.sessionId))) {
|
|
1772
|
+
throw new AcpExecutionError("Wait for the source conversation's running operation to finish", {}, "session_busy");
|
|
1773
|
+
}
|
|
1774
|
+
if (this.#sessions.has(options.sessionId) ||
|
|
1775
|
+
this.#preparing.has(options.sessionId) ||
|
|
1776
|
+
this.#store.read(options.sessionId) instanceof FoundAcpStoredSession ||
|
|
1777
|
+
this.#store.read(options.sessionId) instanceof DeletedAcpStoredSession) {
|
|
1778
|
+
throw new AcpExecutionError("The destination conversation already exists", {}, "session_identity_mismatch");
|
|
1779
|
+
}
|
|
1780
|
+
this.#nativeOperations.add(key);
|
|
1781
|
+
try {
|
|
1782
|
+
const runtime = await this.#startSessionForkAtTurnPreparation(options, source.session.nativeSessionId, forkPoint);
|
|
1783
|
+
const openedKey = `${options.agent.id}:${runtime.nativeSessionId()}`;
|
|
1784
|
+
this.#nativeOperations.add(openedKey);
|
|
1785
|
+
try {
|
|
1786
|
+
return {
|
|
1787
|
+
history: await runtime.loadHistory(options.signal),
|
|
1788
|
+
prepared: runtime.prepared(),
|
|
1789
|
+
sessionId: options.sessionId,
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
catch (error) {
|
|
1793
|
+
this.#sessions.delete(options.sessionId);
|
|
1794
|
+
this.#store.remove(options.sessionId);
|
|
1795
|
+
await runtime.closeProcess();
|
|
1796
|
+
throw error;
|
|
1797
|
+
}
|
|
1798
|
+
finally {
|
|
1799
|
+
this.#nativeOperations.delete(openedKey);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
finally {
|
|
1803
|
+
this.#nativeOperations.delete(key);
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1564
1806
|
deleteNativeSession = async (options, nativeSessionId) => {
|
|
1565
1807
|
const runtime = await this.#ensureNativeSessionBrowser(options);
|
|
1566
1808
|
const key = `${options.agent.id}:${nativeSessionId}`;
|