@moxt-ai/mobius 0.0.23 → 0.0.24
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/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 +724 -137
- package/dist/cli.js.map +3 -3
- package/dist/index.js +715 -128
- package/dist/index.js.map +3 -3
- 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/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 +154 -51
- package/dist/run-daemon.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { mkdir as mkdir5 } from "node:fs/promises";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@moxt-ai/mobius",
|
|
14
|
-
version: "0.0.
|
|
14
|
+
version: "0.0.24",
|
|
15
15
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
16
16
|
type: "module",
|
|
17
17
|
bin: {
|
|
@@ -71,6 +71,16 @@ var package_default = {
|
|
|
71
71
|
import { realpathSync, statSync } from "node:fs";
|
|
72
72
|
|
|
73
73
|
// src/acp/session-capabilities.ts
|
|
74
|
+
function isRecord(value) {
|
|
75
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
76
|
+
}
|
|
77
|
+
function hasTrueChildField(value, childKey, fieldKey) {
|
|
78
|
+
if (!isRecord(value)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
const child = Reflect.get(value, childKey);
|
|
82
|
+
return isRecord(child) && Reflect.get(child, fieldKey) === true;
|
|
83
|
+
}
|
|
74
84
|
function unsupportedSessionCapabilities() {
|
|
75
85
|
return Object.freeze({
|
|
76
86
|
additionalDirectories: false,
|
|
@@ -81,11 +91,14 @@ function unsupportedSessionCapabilities() {
|
|
|
81
91
|
imagePrompt: false,
|
|
82
92
|
listSessions: false,
|
|
83
93
|
loadSession: false,
|
|
94
|
+
promptQueueing: false,
|
|
84
95
|
resumeSession: false,
|
|
96
|
+
steering: false,
|
|
85
97
|
unstableForkSession: false
|
|
86
98
|
});
|
|
87
99
|
}
|
|
88
|
-
function normalizeAcpCapabilities(
|
|
100
|
+
function normalizeAcpCapabilities(initialized) {
|
|
101
|
+
const capabilities = initialized.agentCapabilities ?? {};
|
|
89
102
|
const session = capabilities.sessionCapabilities;
|
|
90
103
|
const prompt = capabilities.promptCapabilities;
|
|
91
104
|
return Object.freeze({
|
|
@@ -97,7 +110,9 @@ function normalizeAcpCapabilities(capabilities) {
|
|
|
97
110
|
imagePrompt: prompt?.image === true,
|
|
98
111
|
listSessions: session?.list != null,
|
|
99
112
|
loadSession: capabilities.loadSession === true,
|
|
113
|
+
promptQueueing: hasTrueChildField(capabilities._meta, "claudeCode", "promptQueueing"),
|
|
100
114
|
resumeSession: session?.resume != null,
|
|
115
|
+
steering: hasTrueChildField(initialized._meta, "steering", "supported"),
|
|
101
116
|
unstableForkSession: session?.fork != null
|
|
102
117
|
});
|
|
103
118
|
}
|
|
@@ -865,7 +880,7 @@ var ManagedNpmPackageError = class extends Error {
|
|
|
865
880
|
this.name = "ManagedNpmPackageError";
|
|
866
881
|
}
|
|
867
882
|
};
|
|
868
|
-
function
|
|
883
|
+
function isRecord2(value) {
|
|
869
884
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
870
885
|
}
|
|
871
886
|
function packagePath(root, packageName) {
|
|
@@ -887,7 +902,7 @@ async function readJsonRecord(path2, maximumBytes) {
|
|
|
887
902
|
);
|
|
888
903
|
}
|
|
889
904
|
const value = JSON.parse(await handle.readFile({ encoding: "utf8" }));
|
|
890
|
-
if (!
|
|
905
|
+
if (!isRecord2(value)) {
|
|
891
906
|
throw new ManagedNpmPackageError(
|
|
892
907
|
"managed_package_verification_failed",
|
|
893
908
|
"The managed npm package metadata is invalid"
|
|
@@ -913,7 +928,7 @@ function readBinPath(packageMetadata, executableName) {
|
|
|
913
928
|
if (typeof bin === "string") {
|
|
914
929
|
return bin;
|
|
915
930
|
}
|
|
916
|
-
if (
|
|
931
|
+
if (isRecord2(bin) && typeof bin[executableName] === "string") {
|
|
917
932
|
return bin[executableName];
|
|
918
933
|
}
|
|
919
934
|
throw new ManagedNpmPackageError(
|
|
@@ -929,7 +944,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
|
|
|
929
944
|
);
|
|
930
945
|
}
|
|
931
946
|
const packages = lock["packages"];
|
|
932
|
-
if (!
|
|
947
|
+
if (!isRecord2(packages)) {
|
|
933
948
|
throw new ManagedNpmPackageError(
|
|
934
949
|
"managed_package_verification_failed",
|
|
935
950
|
"The managed npm package lockfile is invalid"
|
|
@@ -943,7 +958,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
|
|
|
943
958
|
if (verifyDependencyClosure && normalizedKey.length > 0) {
|
|
944
959
|
let resolved;
|
|
945
960
|
try {
|
|
946
|
-
if (!normalizedKey.split("/").includes("node_modules") || !
|
|
961
|
+
if (!normalizedKey.split("/").includes("node_modules") || !isRecord2(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
|
|
947
962
|
throw new Error("Invalid locked dependency");
|
|
948
963
|
}
|
|
949
964
|
resolved = new URL(candidate["resolved"]);
|
|
@@ -966,7 +981,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
|
|
|
966
981
|
matches += 1;
|
|
967
982
|
}
|
|
968
983
|
}
|
|
969
|
-
if (matches !== 1 || !
|
|
984
|
+
if (matches !== 1 || !isRecord2(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
|
|
970
985
|
throw new ManagedNpmPackageError(
|
|
971
986
|
"managed_package_verification_failed",
|
|
972
987
|
"The managed npm package lockfile does not match the pinned artifact"
|
|
@@ -1607,7 +1622,7 @@ var ManagedAgentArchiveError = class extends Error {
|
|
|
1607
1622
|
this.name = "ManagedAgentArchiveError";
|
|
1608
1623
|
}
|
|
1609
1624
|
};
|
|
1610
|
-
function
|
|
1625
|
+
function isRecord3(value) {
|
|
1611
1626
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1612
1627
|
}
|
|
1613
1628
|
function isContainedPath3(root, candidate) {
|
|
@@ -1664,7 +1679,7 @@ async function readManifest(path2) {
|
|
|
1664
1679
|
);
|
|
1665
1680
|
}
|
|
1666
1681
|
const parsed = JSON.parse(await handle.readFile({ encoding: "utf8" }));
|
|
1667
|
-
if (!
|
|
1682
|
+
if (!isRecord3(parsed)) {
|
|
1668
1683
|
throw new ManagedAgentArchiveError(
|
|
1669
1684
|
"managed_archive_verification_failed",
|
|
1670
1685
|
"The managed Agent archive manifest is invalid"
|
|
@@ -2384,7 +2399,7 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
|
|
|
2384
2399
|
await specification.verifyAcp(connection, initialized, defaultWorkspace, controller.signal);
|
|
2385
2400
|
return new VerifiedAcpReadiness(
|
|
2386
2401
|
normalizedVersion(initialized.agentInfo?.version ?? ""),
|
|
2387
|
-
normalizeAcpCapabilities(initialized
|
|
2402
|
+
normalizeAcpCapabilities(initialized)
|
|
2388
2403
|
);
|
|
2389
2404
|
} catch (error61) {
|
|
2390
2405
|
if (signal.aborted) {
|
|
@@ -2624,7 +2639,7 @@ var BotMessageCommandError = class extends Error {
|
|
|
2624
2639
|
this.name = "BotMessageCommandError";
|
|
2625
2640
|
}
|
|
2626
2641
|
};
|
|
2627
|
-
function
|
|
2642
|
+
function isRecord4(value) {
|
|
2628
2643
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2629
2644
|
}
|
|
2630
2645
|
function requiredEnvironment(environment, name) {
|
|
@@ -2675,14 +2690,14 @@ function decodeResponse(encoded) {
|
|
|
2675
2690
|
cause
|
|
2676
2691
|
});
|
|
2677
2692
|
}
|
|
2678
|
-
if (!
|
|
2693
|
+
if (!isRecord4(value) || typeof value["ok"] !== "boolean") {
|
|
2679
2694
|
throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data");
|
|
2680
2695
|
}
|
|
2681
2696
|
if (value["ok"] === true && typeof value["outboundMessageId"] === "string") {
|
|
2682
2697
|
return value["outboundMessageId"];
|
|
2683
2698
|
}
|
|
2684
2699
|
const error61 = value["error"];
|
|
2685
|
-
if (value["ok"] === false &&
|
|
2700
|
+
if (value["ok"] === false && isRecord4(error61) && typeof error61["code"] === "string" && typeof error61["message"] === "string") {
|
|
2686
2701
|
throw new BotMessageCommandError(error61["code"], error61["message"]);
|
|
2687
2702
|
}
|
|
2688
2703
|
throw new BotMessageCommandError("bot_service_unavailable", "The local Bot service returned invalid data");
|
|
@@ -21743,7 +21758,9 @@ var sessionCapabilitiesSchema = external_exports.strictObject({
|
|
|
21743
21758
|
imagePrompt: external_exports.boolean(),
|
|
21744
21759
|
listSessions: external_exports.boolean(),
|
|
21745
21760
|
loadSession: external_exports.boolean(),
|
|
21761
|
+
promptQueueing: external_exports.boolean().default(false),
|
|
21746
21762
|
resumeSession: external_exports.boolean(),
|
|
21763
|
+
steering: external_exports.boolean().default(false),
|
|
21747
21764
|
unstableForkSession: external_exports.boolean().default(false)
|
|
21748
21765
|
}).readonly();
|
|
21749
21766
|
var sessionCommandSchema = external_exports.strictObject({
|
|
@@ -22085,6 +22102,11 @@ var AGENT_ACTIVITY_LOCATION_LIMIT = 12;
|
|
|
22085
22102
|
var AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT = 1024;
|
|
22086
22103
|
var SESSION_COMPLETED_KIND = "session.completed";
|
|
22087
22104
|
var SESSION_FAILED_KIND = "session.failed";
|
|
22105
|
+
var SessionPromptDisposition = Object.freeze({
|
|
22106
|
+
Queue: "queue",
|
|
22107
|
+
Reject: "reject",
|
|
22108
|
+
Steer: "steer"
|
|
22109
|
+
});
|
|
22088
22110
|
|
|
22089
22111
|
// ../protocol/src/codecs/messages.ts
|
|
22090
22112
|
var IDENTIFIER_PATTERN2 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
@@ -22114,7 +22136,7 @@ var ProtocolMessageError = class extends Error {
|
|
|
22114
22136
|
this.name = "ProtocolMessageError";
|
|
22115
22137
|
}
|
|
22116
22138
|
};
|
|
22117
|
-
function
|
|
22139
|
+
function isRecord5(value) {
|
|
22118
22140
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22119
22141
|
}
|
|
22120
22142
|
function parseJson2(encoded) {
|
|
@@ -22126,7 +22148,7 @@ function parseJson2(encoded) {
|
|
|
22126
22148
|
cause: error61
|
|
22127
22149
|
});
|
|
22128
22150
|
}
|
|
22129
|
-
if (!
|
|
22151
|
+
if (!isRecord5(value)) {
|
|
22130
22152
|
throw new ProtocolMessageError("Message must be a JSON object");
|
|
22131
22153
|
}
|
|
22132
22154
|
return value;
|
|
@@ -22159,6 +22181,19 @@ function readAllowedString(value, key, allowedValues) {
|
|
|
22159
22181
|
}
|
|
22160
22182
|
return field;
|
|
22161
22183
|
}
|
|
22184
|
+
function readPromptDisposition(value) {
|
|
22185
|
+
const field = value["disposition"];
|
|
22186
|
+
if (field === void 0 || field === SessionPromptDisposition.Reject) {
|
|
22187
|
+
return SessionPromptDisposition.Reject;
|
|
22188
|
+
}
|
|
22189
|
+
if (field === SessionPromptDisposition.Queue) {
|
|
22190
|
+
return SessionPromptDisposition.Queue;
|
|
22191
|
+
}
|
|
22192
|
+
if (field === SessionPromptDisposition.Steer) {
|
|
22193
|
+
return SessionPromptDisposition.Steer;
|
|
22194
|
+
}
|
|
22195
|
+
throw new ProtocolMessageError("Invalid value field: disposition");
|
|
22196
|
+
}
|
|
22162
22197
|
function readSequence(value, key) {
|
|
22163
22198
|
const field = value[key];
|
|
22164
22199
|
if (typeof field !== "number" || !Number.isSafeInteger(field) || field < 0) {
|
|
@@ -22210,7 +22245,7 @@ function readActivityContent(value) {
|
|
|
22210
22245
|
}
|
|
22211
22246
|
function readActivityDetail(value) {
|
|
22212
22247
|
const field = value["detail"];
|
|
22213
|
-
if (!
|
|
22248
|
+
if (!isRecord5(field)) {
|
|
22214
22249
|
throw new ProtocolMessageError("Invalid activity detail field");
|
|
22215
22250
|
}
|
|
22216
22251
|
const kind = readString(field, "kind", 32);
|
|
@@ -22283,11 +22318,13 @@ function decodeSessionPromptCommand(encoded) {
|
|
|
22283
22318
|
"bindingId",
|
|
22284
22319
|
"commandId",
|
|
22285
22320
|
"directoryId",
|
|
22321
|
+
"disposition",
|
|
22286
22322
|
"images",
|
|
22287
22323
|
"kind",
|
|
22288
22324
|
"prompt",
|
|
22289
22325
|
"resources",
|
|
22290
|
-
"sessionId"
|
|
22326
|
+
"sessionId",
|
|
22327
|
+
"targetCommandId"
|
|
22291
22328
|
]);
|
|
22292
22329
|
assertKind(value, SESSION_PROMPT_KIND);
|
|
22293
22330
|
const prompt = readText(value, "prompt", MAX_PROMPT_LENGTH);
|
|
@@ -22300,17 +22337,25 @@ function decodeSessionPromptCommand(encoded) {
|
|
|
22300
22337
|
if (prompt.trim().length === 0 && images.length === 0 && resources.length === 0) {
|
|
22301
22338
|
throw new ProtocolMessageError("Prompt must contain content");
|
|
22302
22339
|
}
|
|
22340
|
+
const disposition = readPromptDisposition(value);
|
|
22341
|
+
const rawTargetCommandId = value["targetCommandId"];
|
|
22342
|
+
const targetCommandId = rawTargetCommandId === void 0 ? "" : readText(value, "targetCommandId", 128);
|
|
22343
|
+
if (disposition === SessionPromptDisposition.Reject && targetCommandId.length > 0 || disposition !== SessionPromptDisposition.Reject && !IDENTIFIER_PATTERN2.test(targetCommandId)) {
|
|
22344
|
+
throw new ProtocolMessageError("Prompt disposition has an invalid target command");
|
|
22345
|
+
}
|
|
22303
22346
|
return {
|
|
22304
22347
|
additionalDirectoryIds: readDirectoryIdentifiers(value, "additionalDirectoryIds", 16),
|
|
22305
22348
|
agentId: readIdentifier(value, "agentId"),
|
|
22306
22349
|
bindingId: readIdentifier(value, "bindingId"),
|
|
22307
22350
|
commandId: readIdentifier(value, "commandId"),
|
|
22308
22351
|
directoryId: readDirectoryIdentifier(value, "directoryId"),
|
|
22352
|
+
disposition,
|
|
22309
22353
|
images,
|
|
22310
22354
|
kind: SESSION_PROMPT_KIND,
|
|
22311
22355
|
prompt,
|
|
22312
22356
|
resources,
|
|
22313
|
-
sessionId: readIdentifier(value, "sessionId")
|
|
22357
|
+
sessionId: readIdentifier(value, "sessionId"),
|
|
22358
|
+
targetCommandId
|
|
22314
22359
|
};
|
|
22315
22360
|
}
|
|
22316
22361
|
function decodeSessionCancelCommand(encoded) {
|
|
@@ -22360,11 +22405,12 @@ function decodeSessionStartedEvent(encoded) {
|
|
|
22360
22405
|
}
|
|
22361
22406
|
function decodeAgentMessageDeltaEvent(encoded) {
|
|
22362
22407
|
const value = parseJson2(encoded);
|
|
22363
|
-
assertExactKeys(value, ["commandId", "kind", "sessionId", "text"]);
|
|
22408
|
+
assertExactKeys(value, ["commandId", "kind", "messageId", "sessionId", "text"]);
|
|
22364
22409
|
assertKind(value, AGENT_MESSAGE_DELTA_KIND);
|
|
22365
22410
|
return {
|
|
22366
22411
|
commandId: readIdentifier(value, "commandId"),
|
|
22367
22412
|
kind: AGENT_MESSAGE_DELTA_KIND,
|
|
22413
|
+
messageId: value["messageId"] === void 0 ? "" : readText(value, "messageId", 255),
|
|
22368
22414
|
sessionId: readIdentifier(value, "sessionId"),
|
|
22369
22415
|
text: readString(value, "text", MAX_EVENT_TEXT_LENGTH)
|
|
22370
22416
|
};
|
|
@@ -22629,7 +22675,7 @@ var BotSessionPromptCommand = class {
|
|
|
22629
22675
|
this.replyRoute = replyRoute;
|
|
22630
22676
|
}
|
|
22631
22677
|
};
|
|
22632
|
-
function
|
|
22678
|
+
function isRecord6(value) {
|
|
22633
22679
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22634
22680
|
}
|
|
22635
22681
|
function parseJson3(encoded) {
|
|
@@ -22639,7 +22685,7 @@ function parseJson3(encoded) {
|
|
|
22639
22685
|
} catch (cause) {
|
|
22640
22686
|
throw new ProtocolMessageError("Message is not valid JSON", { cause });
|
|
22641
22687
|
}
|
|
22642
|
-
if (!
|
|
22688
|
+
if (!isRecord6(value)) {
|
|
22643
22689
|
throw new ProtocolMessageError("Message must be a JSON object");
|
|
22644
22690
|
}
|
|
22645
22691
|
return value;
|
|
@@ -22724,7 +22770,7 @@ function readTargets(value, key) {
|
|
|
22724
22770
|
const identifiers = /* @__PURE__ */ new Set();
|
|
22725
22771
|
const aliases = /* @__PURE__ */ new Set();
|
|
22726
22772
|
for (const candidate of field) {
|
|
22727
|
-
if (!
|
|
22773
|
+
if (!isRecord6(candidate)) {
|
|
22728
22774
|
throw new ProtocolMessageError(`Invalid Bot delivery targets: ${key}`);
|
|
22729
22775
|
}
|
|
22730
22776
|
assertExactKeys2(candidate, ["alias", "deliveryTargetId"]);
|
|
@@ -22740,7 +22786,7 @@ function readTargets(value, key) {
|
|
|
22740
22786
|
return Object.freeze(targets);
|
|
22741
22787
|
}
|
|
22742
22788
|
function readCompletionPolicy(value) {
|
|
22743
|
-
if (!
|
|
22789
|
+
if (!isRecord6(value)) {
|
|
22744
22790
|
throw new ProtocolMessageError("Invalid Bot completion policy");
|
|
22745
22791
|
}
|
|
22746
22792
|
const kind = readText2(value, "kind", 32, false);
|
|
@@ -22758,7 +22804,7 @@ function readCompletionPolicy(value) {
|
|
|
22758
22804
|
throw new ProtocolMessageError("Invalid Bot completion policy");
|
|
22759
22805
|
}
|
|
22760
22806
|
function readReplyRoute(value) {
|
|
22761
|
-
if (!
|
|
22807
|
+
if (!isRecord6(value)) {
|
|
22762
22808
|
throw new ProtocolMessageError("Invalid Bot reply route");
|
|
22763
22809
|
}
|
|
22764
22810
|
const kind = readText2(value, "kind", 32, false);
|
|
@@ -23010,6 +23056,8 @@ var sessionHistorySchema = external_exports.discriminatedUnion("status", [
|
|
|
23010
23056
|
var NATIVE_SESSION_REQUEST_KIND = "native.session.request";
|
|
23011
23057
|
var NATIVE_SESSION_RESULT_KIND = "native.session.result";
|
|
23012
23058
|
var NATIVE_SESSION_CANCEL_KIND = "native.session.cancel";
|
|
23059
|
+
var NATIVE_SESSION_TURN_FORK_REQUEST_KIND = "native.session.turn-fork.request";
|
|
23060
|
+
var NATIVE_SESSION_TURN_FORK_KIND = "native.session.turn-fork";
|
|
23013
23061
|
var identifier = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/);
|
|
23014
23062
|
var directoryId = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/);
|
|
23015
23063
|
var envelope = {
|
|
@@ -23024,6 +23072,28 @@ var identity = {
|
|
|
23024
23072
|
bindingId: identifier,
|
|
23025
23073
|
directoryId
|
|
23026
23074
|
};
|
|
23075
|
+
var turnForkIdentity = {
|
|
23076
|
+
additionalDirectoryIds: external_exports.array(directoryId).max(16).readonly(),
|
|
23077
|
+
agentId: identifier,
|
|
23078
|
+
bindingId: identifier,
|
|
23079
|
+
directoryId,
|
|
23080
|
+
requestId: identifier,
|
|
23081
|
+
sessionId: identifier,
|
|
23082
|
+
sourceCommandId: identifier,
|
|
23083
|
+
targetSessionId: identifier
|
|
23084
|
+
};
|
|
23085
|
+
var nativeSessionTurnForkRequestSchema = external_exports.strictObject({
|
|
23086
|
+
...turnForkIdentity,
|
|
23087
|
+
kind: external_exports.literal(NATIVE_SESSION_TURN_FORK_REQUEST_KIND)
|
|
23088
|
+
}).readonly();
|
|
23089
|
+
var nativeSessionTurnForkCommandSchema = external_exports.strictObject({
|
|
23090
|
+
...turnForkIdentity,
|
|
23091
|
+
kind: external_exports.literal(NATIVE_SESSION_TURN_FORK_KIND),
|
|
23092
|
+
messageFingerprint: external_exports.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
23093
|
+
messageId: external_exports.string().min(1).max(255),
|
|
23094
|
+
messageOccurrence: external_exports.number().int().positive(),
|
|
23095
|
+
title: external_exports.string().max(500)
|
|
23096
|
+
}).readonly();
|
|
23027
23097
|
var nativeSessionCommandSchema = external_exports.discriminatedUnion("action", [
|
|
23028
23098
|
external_exports.strictObject({
|
|
23029
23099
|
...identity,
|
|
@@ -23098,6 +23168,7 @@ function decode4(schema, encoded) {
|
|
|
23098
23168
|
var decodeNativeSessionCommand = (encoded) => decode4(nativeSessionCommandSchema, encoded);
|
|
23099
23169
|
var encodeNativeSessionResult = (value) => JSON.stringify(nativeSessionResultSchema.parse(value));
|
|
23100
23170
|
var decodeNativeSessionCancel = (encoded) => decode4(nativeSessionCancelSchema, encoded);
|
|
23171
|
+
var decodeNativeSessionTurnForkCommand = (encoded) => decode4(nativeSessionTurnForkCommandSchema, encoded);
|
|
23101
23172
|
|
|
23102
23173
|
// ../protocol/src/session-events.ts
|
|
23103
23174
|
var SESSION_EVENT_KIND = "session.event";
|
|
@@ -23221,7 +23292,7 @@ var PairingClientError = class extends Error {
|
|
|
23221
23292
|
this.name = "PairingClientError";
|
|
23222
23293
|
}
|
|
23223
23294
|
};
|
|
23224
|
-
function
|
|
23295
|
+
function isRecord7(value) {
|
|
23225
23296
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23226
23297
|
}
|
|
23227
23298
|
function hasExactKeys(value, expectedKeys) {
|
|
@@ -23337,9 +23408,9 @@ async function readJsonResponse(response) {
|
|
|
23337
23408
|
}
|
|
23338
23409
|
}
|
|
23339
23410
|
function readRelayError(value) {
|
|
23340
|
-
if (
|
|
23411
|
+
if (isRecord7(value)) {
|
|
23341
23412
|
const error61 = value["error"];
|
|
23342
|
-
if (
|
|
23413
|
+
if (isRecord7(error61)) {
|
|
23343
23414
|
const code = error61["code"];
|
|
23344
23415
|
const message = error61["message"];
|
|
23345
23416
|
if (typeof code === "string" && typeof message === "string") {
|
|
@@ -23350,7 +23421,7 @@ function readRelayError(value) {
|
|
|
23350
23421
|
return new PairingClientError("pairing_failed", "The relay could not pair this machine");
|
|
23351
23422
|
}
|
|
23352
23423
|
function decodeClaimResponse(value) {
|
|
23353
|
-
if (!
|
|
23424
|
+
if (!isRecord7(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
|
|
23354
23425
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
23355
23426
|
}
|
|
23356
23427
|
const channelId = value["channelId"];
|
|
@@ -23418,7 +23489,7 @@ async function persistConnection(channelId, relayOrigin, daemonToken2, defaultWo
|
|
|
23418
23489
|
return connectionPath;
|
|
23419
23490
|
}
|
|
23420
23491
|
function decodeSavedConnection(value, expectedChannelId) {
|
|
23421
|
-
if (!
|
|
23492
|
+
if (!isRecord7(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
|
|
23422
23493
|
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
23423
23494
|
}
|
|
23424
23495
|
const defaultWorkspace = value["defaultWorkspace"];
|
|
@@ -23533,7 +23604,7 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
|
|
|
23533
23604
|
|
|
23534
23605
|
// src/run-daemon.ts
|
|
23535
23606
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
23536
|
-
import { basename as
|
|
23607
|
+
import { basename as basename4, join as join16 } from "node:path";
|
|
23537
23608
|
import { styleText } from "node:util";
|
|
23538
23609
|
import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
|
|
23539
23610
|
|
|
@@ -23548,7 +23619,7 @@ import {
|
|
|
23548
23619
|
|
|
23549
23620
|
// src/acp/activity.ts
|
|
23550
23621
|
var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
|
|
23551
|
-
function
|
|
23622
|
+
function isRecord8(value) {
|
|
23552
23623
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23553
23624
|
}
|
|
23554
23625
|
var AcpActivity = class _AcpActivity {
|
|
@@ -23815,7 +23886,7 @@ function contentPhase(content) {
|
|
|
23815
23886
|
return "";
|
|
23816
23887
|
}
|
|
23817
23888
|
const codex = metadata["codex"];
|
|
23818
|
-
if (!
|
|
23889
|
+
if (!isRecord8(codex)) {
|
|
23819
23890
|
return "";
|
|
23820
23891
|
}
|
|
23821
23892
|
const phase = codex["phase"];
|
|
@@ -24053,7 +24124,7 @@ var SessionConfigProtocolError = class extends Error {
|
|
|
24053
24124
|
this.name = "SessionConfigProtocolError";
|
|
24054
24125
|
}
|
|
24055
24126
|
};
|
|
24056
|
-
function
|
|
24127
|
+
function isRecord9(value) {
|
|
24057
24128
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24058
24129
|
}
|
|
24059
24130
|
function readString2(value, fallback = "") {
|
|
@@ -24080,7 +24151,7 @@ function normalizeConfigValues(value) {
|
|
|
24080
24151
|
}
|
|
24081
24152
|
const normalized = [];
|
|
24082
24153
|
for (const entry of value) {
|
|
24083
|
-
if (!
|
|
24154
|
+
if (!isRecord9(entry)) {
|
|
24084
24155
|
continue;
|
|
24085
24156
|
}
|
|
24086
24157
|
const groupedOptions = entry["options"];
|
|
@@ -24088,7 +24159,7 @@ function normalizeConfigValues(value) {
|
|
|
24088
24159
|
const groupId = readString2(entry["group"]);
|
|
24089
24160
|
const groupName = readString2(entry["name"]);
|
|
24090
24161
|
for (const groupedOption of groupedOptions) {
|
|
24091
|
-
if (
|
|
24162
|
+
if (isRecord9(groupedOption)) {
|
|
24092
24163
|
normalized.push(normalizeConfigValue(groupedOption, groupId, groupName));
|
|
24093
24164
|
}
|
|
24094
24165
|
}
|
|
@@ -24102,7 +24173,7 @@ function normalizeConfigOptions(value, modes) {
|
|
|
24102
24173
|
const normalized = [];
|
|
24103
24174
|
if (Array.isArray(value)) {
|
|
24104
24175
|
for (const option2 of value) {
|
|
24105
|
-
if (!
|
|
24176
|
+
if (!isRecord9(option2)) {
|
|
24106
24177
|
continue;
|
|
24107
24178
|
}
|
|
24108
24179
|
const id = truncate2(readString2(option2["id"]), 128);
|
|
@@ -24141,12 +24212,12 @@ function normalizeConfigOptions(value, modes) {
|
|
|
24141
24212
|
}
|
|
24142
24213
|
}
|
|
24143
24214
|
}
|
|
24144
|
-
if (
|
|
24215
|
+
if (isRecord9(modes)) {
|
|
24145
24216
|
const values = [];
|
|
24146
24217
|
const availableModes = modes["availableModes"];
|
|
24147
24218
|
if (Array.isArray(availableModes)) {
|
|
24148
24219
|
for (const mode of availableModes) {
|
|
24149
|
-
if (!
|
|
24220
|
+
if (!isRecord9(mode)) {
|
|
24150
24221
|
continue;
|
|
24151
24222
|
}
|
|
24152
24223
|
const id = truncate2(readString2(mode["id"]), 500);
|
|
@@ -24224,7 +24295,7 @@ function ensureReasoningEffortOption(current) {
|
|
|
24224
24295
|
return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 2), model, unavailable];
|
|
24225
24296
|
}
|
|
24226
24297
|
function normalizeStandardLifecycle(response) {
|
|
24227
|
-
const lifecycle =
|
|
24298
|
+
const lifecycle = isRecord9(response) ? response : {};
|
|
24228
24299
|
return ensureReasoningEffortOption(normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]));
|
|
24229
24300
|
}
|
|
24230
24301
|
function replaceStandardConfigOptions(current, value) {
|
|
@@ -24266,7 +24337,7 @@ var StandardSessionConfigProtocol = class {
|
|
|
24266
24337
|
"ACP agent exited while changing session configuration",
|
|
24267
24338
|
change.signal
|
|
24268
24339
|
);
|
|
24269
|
-
if (!
|
|
24340
|
+
if (!isRecord9(response) || !Array.isArray(response["configOptions"])) {
|
|
24270
24341
|
throw new SessionConfigProtocolError("The Agent returned an invalid session configuration response");
|
|
24271
24342
|
}
|
|
24272
24343
|
return replaceStandardConfigOptions(current, response["configOptions"]);
|
|
@@ -24280,18 +24351,18 @@ var standardSessionConfigProtocol = new StandardSessionConfigProtocol();
|
|
|
24280
24351
|
var LEGACY_MODEL_CONFIG_ID = "grok_build_legacy_model";
|
|
24281
24352
|
var LEGACY_REASONING_EFFORT_CONFIG_ID = "grok_build_legacy_reasoning_effort";
|
|
24282
24353
|
function legacyOptions(response) {
|
|
24283
|
-
if (!
|
|
24354
|
+
if (!isRecord9(response)) {
|
|
24284
24355
|
return [];
|
|
24285
24356
|
}
|
|
24286
24357
|
const metadata = response["_meta"];
|
|
24287
|
-
if (!
|
|
24358
|
+
if (!isRecord9(metadata)) {
|
|
24288
24359
|
return [];
|
|
24289
24360
|
}
|
|
24290
24361
|
const sessionConfig = metadata["x.ai/sessionConfig"];
|
|
24291
|
-
if (!
|
|
24362
|
+
if (!isRecord9(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
|
|
24292
24363
|
return [];
|
|
24293
24364
|
}
|
|
24294
|
-
return sessionConfig["options"].slice(0, 500).filter(
|
|
24365
|
+
return sessionConfig["options"].slice(0, 500).filter(isRecord9);
|
|
24295
24366
|
}
|
|
24296
24367
|
function legacyValue(option2) {
|
|
24297
24368
|
const value = readString2(option2["id"]);
|
|
@@ -24304,7 +24375,7 @@ function legacyValue(option2) {
|
|
|
24304
24375
|
};
|
|
24305
24376
|
}
|
|
24306
24377
|
function modelsRecord(response) {
|
|
24307
|
-
if (!
|
|
24378
|
+
if (!isRecord9(response) || !isRecord9(response["models"])) {
|
|
24308
24379
|
return {};
|
|
24309
24380
|
}
|
|
24310
24381
|
return response["models"];
|
|
@@ -24323,7 +24394,7 @@ function legacyModelOptions(response) {
|
|
|
24323
24394
|
}
|
|
24324
24395
|
if (values.length === 0 && Array.isArray(models["availableModels"])) {
|
|
24325
24396
|
for (const model of models["availableModels"]) {
|
|
24326
|
-
if (!
|
|
24397
|
+
if (!isRecord9(model)) {
|
|
24327
24398
|
continue;
|
|
24328
24399
|
}
|
|
24329
24400
|
const value = readString2(model["modelId"]).slice(0, 500);
|
|
@@ -24403,7 +24474,7 @@ function legacyReasoningEffortOptions(response) {
|
|
|
24403
24474
|
return [result];
|
|
24404
24475
|
}
|
|
24405
24476
|
function normalizeGrokLifecycle(response) {
|
|
24406
|
-
const lifecycle =
|
|
24477
|
+
const lifecycle = isRecord9(response) ? response : {};
|
|
24407
24478
|
const standard = normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"]);
|
|
24408
24479
|
const normalized = [...standard];
|
|
24409
24480
|
if (!normalized.some((option2) => option2.category === "model")) {
|
|
@@ -24422,11 +24493,11 @@ function updateCurrentValue2(current, category, value) {
|
|
|
24422
24493
|
return current.map((option2) => option2.category === category ? { ...option2, currentValue: value } : option2);
|
|
24423
24494
|
}
|
|
24424
24495
|
function validateGrokResponse(response, modelId) {
|
|
24425
|
-
if (!
|
|
24496
|
+
if (!isRecord9(response) || !isRecord9(response["_meta"])) {
|
|
24426
24497
|
throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
|
|
24427
24498
|
}
|
|
24428
24499
|
const model = response["_meta"]["model"];
|
|
24429
|
-
const appliedModel =
|
|
24500
|
+
const appliedModel = isRecord9(model) ? model["Ok"] : model;
|
|
24430
24501
|
if (appliedModel !== modelId) {
|
|
24431
24502
|
throw new SessionConfigProtocolError("Grok Build returned an invalid session configuration response");
|
|
24432
24503
|
}
|
|
@@ -24869,7 +24940,7 @@ function createWritableAcpStream(output2) {
|
|
|
24869
24940
|
function truncate3(value, maximumLength) {
|
|
24870
24941
|
return value.length <= maximumLength ? value : `${value.slice(0, Math.max(0, maximumLength - 1))}\u2026`;
|
|
24871
24942
|
}
|
|
24872
|
-
function
|
|
24943
|
+
function isRecord10(value) {
|
|
24873
24944
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24874
24945
|
}
|
|
24875
24946
|
function readString4(value, fallback = "") {
|
|
@@ -24878,6 +24949,11 @@ function readString4(value, fallback = "") {
|
|
|
24878
24949
|
function arraysEqual(left, right) {
|
|
24879
24950
|
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
24880
24951
|
}
|
|
24952
|
+
function recordsEqual(left, right) {
|
|
24953
|
+
const leftEntries = Object.entries(left);
|
|
24954
|
+
const rightEntries = Object.entries(right);
|
|
24955
|
+
return leftEntries.length === rightEntries.length && leftEntries.every(([name, value]) => right[name] === value);
|
|
24956
|
+
}
|
|
24881
24957
|
function elicitationFieldType(value) {
|
|
24882
24958
|
if (value === "boolean") {
|
|
24883
24959
|
return "boolean";
|
|
@@ -24898,7 +24974,7 @@ function normalizeElicitationOptions(schema) {
|
|
|
24898
24974
|
const oneOf = schema["oneOf"];
|
|
24899
24975
|
if (Array.isArray(oneOf)) {
|
|
24900
24976
|
for (const option2 of oneOf) {
|
|
24901
|
-
if (
|
|
24977
|
+
if (isRecord10(option2) && typeof option2["const"] === "string") {
|
|
24902
24978
|
normalized.push({
|
|
24903
24979
|
description: truncate3(readString4(option2["description"]), 500),
|
|
24904
24980
|
label: truncate3(readString4(option2["title"], option2["const"]), 255),
|
|
@@ -24918,7 +24994,7 @@ function normalizeElicitationOptions(schema) {
|
|
|
24918
24994
|
return normalized.slice(0, 200);
|
|
24919
24995
|
}
|
|
24920
24996
|
const items = schema["items"];
|
|
24921
|
-
if (!
|
|
24997
|
+
if (!isRecord10(items)) {
|
|
24922
24998
|
return normalized;
|
|
24923
24999
|
}
|
|
24924
25000
|
const anyOf = items["anyOf"];
|
|
@@ -24931,7 +25007,7 @@ function numericString(value) {
|
|
|
24931
25007
|
return typeof value === "number" && Number.isFinite(value) ? value.toString() : "";
|
|
24932
25008
|
}
|
|
24933
25009
|
function normalizeElicitationFields(requestedSchema) {
|
|
24934
|
-
if (!
|
|
25010
|
+
if (!isRecord10(requestedSchema) || !isRecord10(requestedSchema["properties"])) {
|
|
24935
25011
|
return [];
|
|
24936
25012
|
}
|
|
24937
25013
|
const properties = requestedSchema["properties"];
|
|
@@ -24941,7 +25017,7 @@ function normalizeElicitationFields(requestedSchema) {
|
|
|
24941
25017
|
);
|
|
24942
25018
|
const normalized = [];
|
|
24943
25019
|
for (const [name, property] of Object.entries(properties)) {
|
|
24944
|
-
if (!
|
|
25020
|
+
if (!isRecord10(property)) {
|
|
24945
25021
|
continue;
|
|
24946
25022
|
}
|
|
24947
25023
|
const type = elicitationFieldType(property["type"]);
|
|
@@ -25032,7 +25108,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
25032
25108
|
"invalid_elicitation_response"
|
|
25033
25109
|
);
|
|
25034
25110
|
}
|
|
25035
|
-
if (!
|
|
25111
|
+
if (!isRecord10(decoded) || !isRecord10(requestedSchema) || !isRecord10(requestedSchema["properties"])) {
|
|
25036
25112
|
throw new AcpExecutionError(
|
|
25037
25113
|
"Elicitation response does not match the requested form",
|
|
25038
25114
|
{},
|
|
@@ -25052,7 +25128,7 @@ function validateElicitationContent(encoded, requestedSchema) {
|
|
|
25052
25128
|
const validated = {};
|
|
25053
25129
|
for (const [name, value] of Object.entries(decoded)) {
|
|
25054
25130
|
const property = properties[name];
|
|
25055
|
-
if (!
|
|
25131
|
+
if (!isRecord10(property)) {
|
|
25056
25132
|
throw new AcpExecutionError(
|
|
25057
25133
|
`Elicitation field ${name} was not requested`,
|
|
25058
25134
|
{},
|
|
@@ -25194,6 +25270,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25194
25270
|
#child;
|
|
25195
25271
|
#connection;
|
|
25196
25272
|
#cwd;
|
|
25273
|
+
#environment;
|
|
25197
25274
|
#getObserver;
|
|
25198
25275
|
#mobiusSessionId;
|
|
25199
25276
|
#pendingElicitations = /* @__PURE__ */ new Map();
|
|
@@ -25215,7 +25292,9 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25215
25292
|
imagePrompt: false,
|
|
25216
25293
|
listSessions: false,
|
|
25217
25294
|
loadSession: false,
|
|
25295
|
+
promptQueueing: false,
|
|
25218
25296
|
resumeSession: false,
|
|
25297
|
+
steering: false,
|
|
25219
25298
|
unstableForkSession: false
|
|
25220
25299
|
};
|
|
25221
25300
|
#commands = [];
|
|
@@ -25235,6 +25314,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25235
25314
|
this.#additionalDirectories = [...additionalDirectories];
|
|
25236
25315
|
this.#agentId = agent.id;
|
|
25237
25316
|
this.#cwd = cwd;
|
|
25317
|
+
this.#environment = agent.environment;
|
|
25238
25318
|
this.#getObserver = getObserver;
|
|
25239
25319
|
this.#mobiusSessionId = mobiusSessionId;
|
|
25240
25320
|
this.#sessionConfigProtocol = sessionConfigProtocolForAgent(agent.id);
|
|
@@ -25320,7 +25400,18 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25320
25400
|
store,
|
|
25321
25401
|
async (runtime) => await runtime.#initializeAgent(options.signal)
|
|
25322
25402
|
);
|
|
25403
|
+
static startSessionForkAtTurn = async (options, sourceNativeSessionId, forkPoint, getObserver, store) => await _AcpProcessSession.#start(
|
|
25404
|
+
options,
|
|
25405
|
+
getObserver,
|
|
25406
|
+
store,
|
|
25407
|
+
async (runtime) => await runtime.initialize(
|
|
25408
|
+
options.signal,
|
|
25409
|
+
{ kind: "fork", nativeSessionId: sourceNativeSessionId },
|
|
25410
|
+
forkPoint
|
|
25411
|
+
)
|
|
25412
|
+
);
|
|
25323
25413
|
belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId && this.#cwd === cwd && arraysEqual(this.#additionalDirectories, additionalDirectories);
|
|
25414
|
+
usesEnvironment = (environment) => recordsEqual(this.#environment, environment);
|
|
25324
25415
|
canRebind = () => !this.#prompted && !this.#turn.running;
|
|
25325
25416
|
prepared = () => new AcpPreparedSession(
|
|
25326
25417
|
this.#agentName,
|
|
@@ -25386,15 +25477,14 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25386
25477
|
"unsupported_acp_protocol"
|
|
25387
25478
|
);
|
|
25388
25479
|
}
|
|
25389
|
-
|
|
25390
|
-
this.#capabilities = normalizeAcpCapabilities(capabilities);
|
|
25480
|
+
this.#capabilities = normalizeAcpCapabilities(initialized);
|
|
25391
25481
|
this.#agentName = truncate3(initialized.agentInfo?.title ?? initialized.agentInfo?.name ?? this.#agentId, 255);
|
|
25392
25482
|
this.#agentVersion = truncate3(
|
|
25393
25483
|
this.#verifiedAgentVersion.length > 0 ? this.#verifiedAgentVersion : initialized.agentInfo?.version ?? "",
|
|
25394
25484
|
128
|
|
25395
25485
|
);
|
|
25396
25486
|
}
|
|
25397
|
-
initialize = async (signal, origin) => {
|
|
25487
|
+
initialize = async (signal, origin, forkPoint) => {
|
|
25398
25488
|
await this.#initializeAgent(signal);
|
|
25399
25489
|
let stored = origin?.kind === "import" ? new FoundAcpStoredSession(
|
|
25400
25490
|
new AcpStoredSession(
|
|
@@ -25426,6 +25516,13 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25426
25516
|
"native_session_unsupported"
|
|
25427
25517
|
);
|
|
25428
25518
|
}
|
|
25519
|
+
if (this.#additionalDirectories.length > 0 && !this.#capabilities.additionalDirectories) {
|
|
25520
|
+
throw new AcpExecutionError(
|
|
25521
|
+
"This Agent cannot restore additional working directories",
|
|
25522
|
+
{},
|
|
25523
|
+
"native_session_unsupported"
|
|
25524
|
+
);
|
|
25525
|
+
}
|
|
25429
25526
|
const forked = await this.race(
|
|
25430
25527
|
this.#connection.agent.request(
|
|
25431
25528
|
methods6.agent.session.fork,
|
|
@@ -25433,7 +25530,21 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25433
25530
|
sessionId: nativeSessionIdSchema.parse(origin.nativeSessionId),
|
|
25434
25531
|
cwd: this.#cwd,
|
|
25435
25532
|
additionalDirectories: [...this.#additionalDirectories],
|
|
25436
|
-
mcpServers: []
|
|
25533
|
+
mcpServers: [],
|
|
25534
|
+
...forkPoint === void 0 ? {} : {
|
|
25535
|
+
_meta: {
|
|
25536
|
+
jetbrains: {
|
|
25537
|
+
air: {
|
|
25538
|
+
fork: {
|
|
25539
|
+
version: 1,
|
|
25540
|
+
messageFingerprint: forkPoint.messageFingerprint,
|
|
25541
|
+
messageId: forkPoint.messageId,
|
|
25542
|
+
messageOccurrence: forkPoint.messageOccurrence
|
|
25543
|
+
}
|
|
25544
|
+
}
|
|
25545
|
+
}
|
|
25546
|
+
}
|
|
25547
|
+
}
|
|
25437
25548
|
},
|
|
25438
25549
|
{ cancellationSignal: signal }
|
|
25439
25550
|
),
|
|
@@ -25638,10 +25749,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25638
25749
|
}
|
|
25639
25750
|
return this.#configOptions;
|
|
25640
25751
|
};
|
|
25641
|
-
|
|
25642
|
-
if (this.#turn.running) {
|
|
25643
|
-
throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
|
|
25644
|
-
}
|
|
25752
|
+
buildPrompt = (options) => {
|
|
25645
25753
|
if (options.images.length > 0 && !this.#capabilities.imagePrompt) {
|
|
25646
25754
|
throw new AcpExecutionError(
|
|
25647
25755
|
"The selected agent does not accept image prompts",
|
|
@@ -25690,6 +25798,13 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25690
25798
|
if (prompt.length === 0) {
|
|
25691
25799
|
throw new AcpExecutionError("A prompt must contain text or an attachment", {}, "empty_prompt");
|
|
25692
25800
|
}
|
|
25801
|
+
return prompt;
|
|
25802
|
+
};
|
|
25803
|
+
prompt = async (options) => {
|
|
25804
|
+
if (this.#turn.running) {
|
|
25805
|
+
throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
|
|
25806
|
+
}
|
|
25807
|
+
const prompt = this.buildPrompt(options);
|
|
25693
25808
|
this.#store.write(
|
|
25694
25809
|
new AcpStoredSession(
|
|
25695
25810
|
this.#mobiusSessionId,
|
|
@@ -25748,6 +25863,54 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25748
25863
|
this.#turn = new IdleAcpTurn();
|
|
25749
25864
|
}
|
|
25750
25865
|
};
|
|
25866
|
+
steer = async (options) => {
|
|
25867
|
+
if (!this.#capabilities.steering) {
|
|
25868
|
+
throw new AcpExecutionError(
|
|
25869
|
+
"The selected agent does not support mid-turn steering",
|
|
25870
|
+
{},
|
|
25871
|
+
"steering_unsupported"
|
|
25872
|
+
);
|
|
25873
|
+
}
|
|
25874
|
+
if (!this.#turn.running || this.#turn.commandId !== options.targetCommandId) {
|
|
25875
|
+
throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
|
|
25876
|
+
}
|
|
25877
|
+
const prompt = this.buildPrompt(options);
|
|
25878
|
+
const response = await this.race(
|
|
25879
|
+
this.#connection.agent.request("_session/steering", {
|
|
25880
|
+
_meta: { steering: { idleBehavior: "promptRequired" } },
|
|
25881
|
+
prompt,
|
|
25882
|
+
sessionId: this.#nativeSessionId
|
|
25883
|
+
}),
|
|
25884
|
+
"ACP agent exited during steering",
|
|
25885
|
+
options.signal
|
|
25886
|
+
);
|
|
25887
|
+
if (!isRecord10(response)) {
|
|
25888
|
+
throw new AcpExecutionError(
|
|
25889
|
+
"ACP agent returned an invalid steering response",
|
|
25890
|
+
{},
|
|
25891
|
+
"acp_invalid_steering_response"
|
|
25892
|
+
);
|
|
25893
|
+
}
|
|
25894
|
+
const outcome = response["outcome"];
|
|
25895
|
+
if (outcome === "injected" || outcome === "startedNewTurn") {
|
|
25896
|
+
return outcome;
|
|
25897
|
+
}
|
|
25898
|
+
if (outcome === "promptRequired") {
|
|
25899
|
+
throw new AcpExecutionError(
|
|
25900
|
+
"The target turn finished before steering could be injected",
|
|
25901
|
+
{},
|
|
25902
|
+
"steering_target_unavailable"
|
|
25903
|
+
);
|
|
25904
|
+
}
|
|
25905
|
+
if (outcome === "failed") {
|
|
25906
|
+
throw new AcpExecutionError("The Agent could not inject steering", {}, "steering_failed");
|
|
25907
|
+
}
|
|
25908
|
+
throw new AcpExecutionError(
|
|
25909
|
+
"ACP agent returned an invalid steering response",
|
|
25910
|
+
{},
|
|
25911
|
+
"acp_invalid_steering_response"
|
|
25912
|
+
);
|
|
25913
|
+
};
|
|
25751
25914
|
cancel = async () => {
|
|
25752
25915
|
const capturedProcesses = await captureProcessTree(this.#child);
|
|
25753
25916
|
try {
|
|
@@ -25988,7 +26151,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25988
26151
|
);
|
|
25989
26152
|
} else {
|
|
25990
26153
|
await this.#turn.activities.finishNarrative();
|
|
25991
|
-
await this.#turn.onText(update.content.text);
|
|
26154
|
+
await this.#turn.onText(update.content.text, truncate3(update.messageId ?? "", 255));
|
|
25992
26155
|
}
|
|
25993
26156
|
} else {
|
|
25994
26157
|
await this.#turn.activities.finishNarrative();
|
|
@@ -26214,6 +26377,7 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
26214
26377
|
};
|
|
26215
26378
|
};
|
|
26216
26379
|
var AcpSessionManager = class {
|
|
26380
|
+
#activeCommandIds = /* @__PURE__ */ new Map();
|
|
26217
26381
|
#nativeOperations = /* @__PURE__ */ new Set();
|
|
26218
26382
|
#nativeBrowserObserver = new NullAcpSessionObserver();
|
|
26219
26383
|
#nativeBrowserPreparing = /* @__PURE__ */ new Map();
|
|
@@ -26282,6 +26446,25 @@ var AcpSessionManager = class {
|
|
|
26282
26446
|
this.#preparing.set(options.sessionId, operation);
|
|
26283
26447
|
return await operation;
|
|
26284
26448
|
}
|
|
26449
|
+
async #startSessionForkAtTurnPreparation(options, sourceNativeSessionId, forkPoint) {
|
|
26450
|
+
const operation = (async () => {
|
|
26451
|
+
try {
|
|
26452
|
+
const runtime = await AcpProcessSession.startSessionForkAtTurn(
|
|
26453
|
+
options,
|
|
26454
|
+
sourceNativeSessionId,
|
|
26455
|
+
forkPoint,
|
|
26456
|
+
() => this.#observer,
|
|
26457
|
+
this.#store
|
|
26458
|
+
);
|
|
26459
|
+
this.#sessions.set(options.sessionId, runtime);
|
|
26460
|
+
return runtime;
|
|
26461
|
+
} finally {
|
|
26462
|
+
this.#preparing.delete(options.sessionId);
|
|
26463
|
+
}
|
|
26464
|
+
})();
|
|
26465
|
+
this.#preparing.set(options.sessionId, operation);
|
|
26466
|
+
return await operation;
|
|
26467
|
+
}
|
|
26285
26468
|
async #replacePreparation(existing, options) {
|
|
26286
26469
|
const operation = (async () => {
|
|
26287
26470
|
try {
|
|
@@ -26298,6 +26481,58 @@ var AcpSessionManager = class {
|
|
|
26298
26481
|
this.#preparing.set(options.sessionId, operation);
|
|
26299
26482
|
return await operation;
|
|
26300
26483
|
}
|
|
26484
|
+
async #replaceExecutionPreparation(existing, options) {
|
|
26485
|
+
const desiredConfigOptions = existing.prepared().configOptions;
|
|
26486
|
+
const operation = (async () => {
|
|
26487
|
+
try {
|
|
26488
|
+
this.#sessions.delete(options.sessionId);
|
|
26489
|
+
await existing.close();
|
|
26490
|
+
this.#store.remove(options.sessionId);
|
|
26491
|
+
const runtime = await AcpProcessSession.start(options, () => this.#observer, this.#store);
|
|
26492
|
+
try {
|
|
26493
|
+
for (const desired of desiredConfigOptions) {
|
|
26494
|
+
const current = runtime.prepared().configOptions.find((option2) => option2.id === desired.id);
|
|
26495
|
+
if (current === void 0 || current.type !== desired.type) {
|
|
26496
|
+
continue;
|
|
26497
|
+
}
|
|
26498
|
+
if (desired.type === "boolean") {
|
|
26499
|
+
if (current.booleanValue !== desired.booleanValue) {
|
|
26500
|
+
await runtime.configure({
|
|
26501
|
+
...options,
|
|
26502
|
+
booleanValue: desired.booleanValue,
|
|
26503
|
+
configId: desired.id,
|
|
26504
|
+
requestId: `execution-prepare-${desired.id}`,
|
|
26505
|
+
value: "",
|
|
26506
|
+
valueType: "boolean"
|
|
26507
|
+
});
|
|
26508
|
+
}
|
|
26509
|
+
continue;
|
|
26510
|
+
}
|
|
26511
|
+
if (current.currentValue !== desired.currentValue && current.values.some((value) => value.value === desired.currentValue)) {
|
|
26512
|
+
await runtime.configure({
|
|
26513
|
+
...options,
|
|
26514
|
+
booleanValue: false,
|
|
26515
|
+
configId: desired.id,
|
|
26516
|
+
requestId: `execution-prepare-${desired.id}`,
|
|
26517
|
+
value: desired.currentValue,
|
|
26518
|
+
valueType: "select"
|
|
26519
|
+
});
|
|
26520
|
+
}
|
|
26521
|
+
}
|
|
26522
|
+
} catch (error61) {
|
|
26523
|
+
await runtime.close();
|
|
26524
|
+
this.#store.remove(options.sessionId);
|
|
26525
|
+
throw error61;
|
|
26526
|
+
}
|
|
26527
|
+
this.#sessions.set(options.sessionId, runtime);
|
|
26528
|
+
return runtime;
|
|
26529
|
+
} finally {
|
|
26530
|
+
this.#preparing.delete(options.sessionId);
|
|
26531
|
+
}
|
|
26532
|
+
})();
|
|
26533
|
+
this.#preparing.set(options.sessionId, operation);
|
|
26534
|
+
return await operation;
|
|
26535
|
+
}
|
|
26301
26536
|
prepareSession = async (options) => {
|
|
26302
26537
|
const stored = this.#store.read(options.sessionId);
|
|
26303
26538
|
if (stored instanceof DeletedAcpStoredSession) {
|
|
@@ -26336,6 +26571,35 @@ var AcpSessionManager = class {
|
|
|
26336
26571
|
const runtime = await this.#startPreparation(options);
|
|
26337
26572
|
return runtime.prepared();
|
|
26338
26573
|
};
|
|
26574
|
+
prepareExecutionSession = async (options) => {
|
|
26575
|
+
const pending = this.#preparing.get(options.sessionId);
|
|
26576
|
+
if (pending !== void 0) {
|
|
26577
|
+
await pending;
|
|
26578
|
+
return await this.prepareExecutionSession(options);
|
|
26579
|
+
}
|
|
26580
|
+
const existing = this.#sessions.get(options.sessionId);
|
|
26581
|
+
if (existing === void 0) {
|
|
26582
|
+
return (await this.#startPreparation(options)).prepared();
|
|
26583
|
+
}
|
|
26584
|
+
if (!existing.belongsTo(options.agent.id, options.cwd, options.additionalDirectories)) {
|
|
26585
|
+
throw new AcpExecutionError(
|
|
26586
|
+
"The agent or workspace cannot change after a conversation has started",
|
|
26587
|
+
{},
|
|
26588
|
+
"session_identity_mismatch"
|
|
26589
|
+
);
|
|
26590
|
+
}
|
|
26591
|
+
if (existing.usesEnvironment(options.agent.environment)) {
|
|
26592
|
+
return existing.prepared();
|
|
26593
|
+
}
|
|
26594
|
+
if (!existing.canRebind()) {
|
|
26595
|
+
throw new AcpExecutionError(
|
|
26596
|
+
"The execution environment cannot change after a conversation has started",
|
|
26597
|
+
{},
|
|
26598
|
+
"session_identity_mismatch"
|
|
26599
|
+
);
|
|
26600
|
+
}
|
|
26601
|
+
return (await this.#replaceExecutionPreparation(existing, options)).prepared();
|
|
26602
|
+
};
|
|
26339
26603
|
prepareNativeSessionBrowser = async (options) => {
|
|
26340
26604
|
const pending = this.#nativeBrowserPreparing.get(options.sessionId);
|
|
26341
26605
|
if (pending !== void 0) {
|
|
@@ -26380,6 +26644,47 @@ var AcpSessionManager = class {
|
|
|
26380
26644
|
}
|
|
26381
26645
|
}
|
|
26382
26646
|
};
|
|
26647
|
+
steerPrompt = async (options) => {
|
|
26648
|
+
if (this.#activeCommandIds.get(options.sessionId) !== options.targetCommandId) {
|
|
26649
|
+
throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
|
|
26650
|
+
}
|
|
26651
|
+
const pending = this.#preparing.get(options.sessionId);
|
|
26652
|
+
if (pending !== void 0) {
|
|
26653
|
+
await pending;
|
|
26654
|
+
}
|
|
26655
|
+
if (this.#activeCommandIds.get(options.sessionId) !== options.targetCommandId) {
|
|
26656
|
+
throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
|
|
26657
|
+
}
|
|
26658
|
+
const runtime = this.#sessions.get(options.sessionId);
|
|
26659
|
+
if (runtime === void 0 || !runtime.belongsTo(options.agent.id, options.cwd, options.additionalDirectories)) {
|
|
26660
|
+
throw new AcpExecutionError(
|
|
26661
|
+
"The target turn execution context is unavailable",
|
|
26662
|
+
{},
|
|
26663
|
+
"steering_target_unavailable"
|
|
26664
|
+
);
|
|
26665
|
+
}
|
|
26666
|
+
const deadlineController = new AbortController();
|
|
26667
|
+
const deadline = setTimeout(
|
|
26668
|
+
() => deadlineController.abort(
|
|
26669
|
+
new AcpExecutionError("The steering request exceeded its deadline", {}, "steering_timeout")
|
|
26670
|
+
),
|
|
26671
|
+
options.agent.promptTimeoutMilliseconds
|
|
26672
|
+
);
|
|
26673
|
+
deadline.unref();
|
|
26674
|
+
try {
|
|
26675
|
+
return await runtime.steer({
|
|
26676
|
+
...options,
|
|
26677
|
+
signal: AbortSignal.any([options.signal, deadlineController.signal])
|
|
26678
|
+
});
|
|
26679
|
+
} catch (error61) {
|
|
26680
|
+
if (error61 instanceof AcpExecutionError) {
|
|
26681
|
+
throw error61;
|
|
26682
|
+
}
|
|
26683
|
+
throw new AcpExecutionError("ACP agent steering failed", { cause: error61 }, "steering_failed");
|
|
26684
|
+
} finally {
|
|
26685
|
+
clearTimeout(deadline);
|
|
26686
|
+
}
|
|
26687
|
+
};
|
|
26383
26688
|
runPrompt = async (options) => {
|
|
26384
26689
|
const stored = this.#store.read(options.sessionId);
|
|
26385
26690
|
if (stored instanceof FoundAcpStoredSession && this.#nativeOperations.has(`${stored.session.agentId}:${stored.session.nativeSessionId}`)) {
|
|
@@ -26404,6 +26709,7 @@ var AcpSessionManager = class {
|
|
|
26404
26709
|
signal: AbortSignal.any([options.signal, deadlineController.signal])
|
|
26405
26710
|
};
|
|
26406
26711
|
this.#activeSessionIds.add(options.sessionId);
|
|
26712
|
+
this.#activeCommandIds.set(options.sessionId, options.commandId);
|
|
26407
26713
|
try {
|
|
26408
26714
|
if (this.#cancellationRequests.has(options.sessionId)) {
|
|
26409
26715
|
return { stopReason: "cancelled" };
|
|
@@ -26443,6 +26749,9 @@ var AcpSessionManager = class {
|
|
|
26443
26749
|
} finally {
|
|
26444
26750
|
clearTimeout(deadline);
|
|
26445
26751
|
this.#activeSessionIds.delete(options.sessionId);
|
|
26752
|
+
if (this.#activeCommandIds.get(options.sessionId) === options.commandId) {
|
|
26753
|
+
this.#activeCommandIds.delete(options.sessionId);
|
|
26754
|
+
}
|
|
26446
26755
|
this.#cancellationRequests.delete(options.sessionId);
|
|
26447
26756
|
}
|
|
26448
26757
|
};
|
|
@@ -26467,6 +26776,7 @@ var AcpSessionManager = class {
|
|
|
26467
26776
|
this.#nativeBrowserSessions.clear();
|
|
26468
26777
|
await Promise.all([...sessions, ...nativeBrowserSessions].map(async (session) => await session.close()));
|
|
26469
26778
|
};
|
|
26779
|
+
hasPreparedSession = (sessionId, agentId, cwd, additionalDirectories) => this.#sessions.get(sessionId)?.belongsTo(agentId, cwd, additionalDirectories) === true;
|
|
26470
26780
|
ensureSession = async (options) => {
|
|
26471
26781
|
const existing = this.#sessions.get(options.sessionId);
|
|
26472
26782
|
if (existing !== void 0) {
|
|
@@ -26575,6 +26885,68 @@ var AcpSessionManager = class {
|
|
|
26575
26885
|
this.#nativeOperations.delete(key);
|
|
26576
26886
|
}
|
|
26577
26887
|
};
|
|
26888
|
+
forkSessionAtTurn = async (options, sourceSessionId, forkPoint) => {
|
|
26889
|
+
if (sourceSessionId === options.sessionId) {
|
|
26890
|
+
throw new AcpExecutionError(
|
|
26891
|
+
"The fork destination must be a new conversation",
|
|
26892
|
+
{},
|
|
26893
|
+
"session_identity_mismatch"
|
|
26894
|
+
);
|
|
26895
|
+
}
|
|
26896
|
+
const source = this.#store.read(sourceSessionId);
|
|
26897
|
+
if (!(source instanceof FoundAcpStoredSession) || !source.session.prompted) {
|
|
26898
|
+
throw new AcpExecutionError(
|
|
26899
|
+
"The source conversation has no resumable native Agent session",
|
|
26900
|
+
{},
|
|
26901
|
+
"native_session_not_found"
|
|
26902
|
+
);
|
|
26903
|
+
}
|
|
26904
|
+
if (source.session.agentId !== options.agent.id || source.session.cwd !== options.cwd || !arraysEqual(source.session.additionalDirectories, options.additionalDirectories)) {
|
|
26905
|
+
throw new AcpExecutionError(
|
|
26906
|
+
"The source conversation execution target does not match the fork request",
|
|
26907
|
+
{},
|
|
26908
|
+
"native_session_target_changed"
|
|
26909
|
+
);
|
|
26910
|
+
}
|
|
26911
|
+
const key = `${options.agent.id}:${source.session.nativeSessionId}`;
|
|
26912
|
+
const linked = this.#store.findNative(options.agent.id, source.session.nativeSessionId);
|
|
26913
|
+
if (this.#nativeOperations.has(key) || linked.some((entry) => this.#activeSessionIds.has(entry.sessionId) || this.#preparing.has(entry.sessionId))) {
|
|
26914
|
+
throw new AcpExecutionError(
|
|
26915
|
+
"Wait for the source conversation's running operation to finish",
|
|
26916
|
+
{},
|
|
26917
|
+
"session_busy"
|
|
26918
|
+
);
|
|
26919
|
+
}
|
|
26920
|
+
if (this.#sessions.has(options.sessionId) || this.#preparing.has(options.sessionId) || this.#store.read(options.sessionId) instanceof FoundAcpStoredSession || this.#store.read(options.sessionId) instanceof DeletedAcpStoredSession) {
|
|
26921
|
+
throw new AcpExecutionError("The destination conversation already exists", {}, "session_identity_mismatch");
|
|
26922
|
+
}
|
|
26923
|
+
this.#nativeOperations.add(key);
|
|
26924
|
+
try {
|
|
26925
|
+
const runtime = await this.#startSessionForkAtTurnPreparation(
|
|
26926
|
+
options,
|
|
26927
|
+
source.session.nativeSessionId,
|
|
26928
|
+
forkPoint
|
|
26929
|
+
);
|
|
26930
|
+
const openedKey = `${options.agent.id}:${runtime.nativeSessionId()}`;
|
|
26931
|
+
this.#nativeOperations.add(openedKey);
|
|
26932
|
+
try {
|
|
26933
|
+
return {
|
|
26934
|
+
history: await runtime.loadHistory(options.signal),
|
|
26935
|
+
prepared: runtime.prepared(),
|
|
26936
|
+
sessionId: options.sessionId
|
|
26937
|
+
};
|
|
26938
|
+
} catch (error61) {
|
|
26939
|
+
this.#sessions.delete(options.sessionId);
|
|
26940
|
+
this.#store.remove(options.sessionId);
|
|
26941
|
+
await runtime.closeProcess();
|
|
26942
|
+
throw error61;
|
|
26943
|
+
} finally {
|
|
26944
|
+
this.#nativeOperations.delete(openedKey);
|
|
26945
|
+
}
|
|
26946
|
+
} finally {
|
|
26947
|
+
this.#nativeOperations.delete(key);
|
|
26948
|
+
}
|
|
26949
|
+
};
|
|
26578
26950
|
deleteNativeSession = async (options, nativeSessionId) => {
|
|
26579
26951
|
const runtime = await this.#ensureNativeSessionBrowser(options);
|
|
26580
26952
|
const key = `${options.agent.id}:${nativeSessionId}`;
|
|
@@ -27317,7 +27689,8 @@ var LocalBotGrant = class {
|
|
|
27317
27689
|
revocationEpoch;
|
|
27318
27690
|
workspaceIdentityDigest;
|
|
27319
27691
|
workspacePath;
|
|
27320
|
-
|
|
27692
|
+
workspaceRef;
|
|
27693
|
+
constructor(localGrantId, botId, behaviorRevisionId, behaviorDigest, bindingId, bindingRevision, agent, agentIdentityDigest, workspaceRef, workspacePath, workspaceIdentityDigest, allowedDeliveryTargetIds, expiresAt, revocationEpoch) {
|
|
27321
27694
|
this.localGrantId = localGrantId;
|
|
27322
27695
|
this.botId = botId;
|
|
27323
27696
|
this.behaviorRevisionId = behaviorRevisionId;
|
|
@@ -27326,6 +27699,7 @@ var LocalBotGrant = class {
|
|
|
27326
27699
|
this.bindingRevision = bindingRevision;
|
|
27327
27700
|
this.agent = agent;
|
|
27328
27701
|
this.agentIdentityDigest = agentIdentityDigest;
|
|
27702
|
+
this.workspaceRef = workspaceRef;
|
|
27329
27703
|
this.workspacePath = workspacePath;
|
|
27330
27704
|
this.workspaceIdentityDigest = workspaceIdentityDigest;
|
|
27331
27705
|
this.allowedDeliveryTargetIds = Object.freeze([...allowedDeliveryTargetIds]);
|
|
@@ -27510,7 +27884,7 @@ var LocalBotGrantStore = class {
|
|
|
27510
27884
|
WHERE local_grant_id = ? AND bot_id = ?
|
|
27511
27885
|
AND behavior_revision_id = ? AND behavior_digest = ?
|
|
27512
27886
|
AND binding_id = ? AND binding_revision = ?
|
|
27513
|
-
AND agent_ref = ?
|
|
27887
|
+
AND agent_ref = ?
|
|
27514
27888
|
AND revoked_at IS NULL AND expires_at > ?`
|
|
27515
27889
|
).get(
|
|
27516
27890
|
command.localGrantId,
|
|
@@ -27520,7 +27894,6 @@ var LocalBotGrantStore = class {
|
|
|
27520
27894
|
command.bindingId,
|
|
27521
27895
|
command.bindingRevision,
|
|
27522
27896
|
command.agentId,
|
|
27523
|
-
command.directoryId,
|
|
27524
27897
|
now
|
|
27525
27898
|
);
|
|
27526
27899
|
if (row === void 0) {
|
|
@@ -27543,7 +27916,8 @@ var LocalBotGrantStore = class {
|
|
|
27543
27916
|
revalidateExecutable(agent.agentIdentity)
|
|
27544
27917
|
]);
|
|
27545
27918
|
signal.throwIfAborted();
|
|
27546
|
-
const
|
|
27919
|
+
const workspaceRef = rowString(row, "workspace_ref");
|
|
27920
|
+
const workspacePath = await directories.resolve(bindingAuthorityId, workspaceRef, signal);
|
|
27547
27921
|
const currentAgentDigest = agentDigest(agent);
|
|
27548
27922
|
const currentWorkspaceDigest = await workspaceDigest(workspacePath);
|
|
27549
27923
|
signal.throwIfAborted();
|
|
@@ -27569,6 +27943,7 @@ var LocalBotGrantStore = class {
|
|
|
27569
27943
|
command.bindingRevision,
|
|
27570
27944
|
agent,
|
|
27571
27945
|
currentAgentDigest,
|
|
27946
|
+
workspaceRef,
|
|
27572
27947
|
workspacePath,
|
|
27573
27948
|
currentWorkspaceDigest,
|
|
27574
27949
|
approvedTargets,
|
|
@@ -27783,7 +28158,7 @@ var BotOutboundIpcRequest = class {
|
|
|
27783
28158
|
this.text = text;
|
|
27784
28159
|
}
|
|
27785
28160
|
};
|
|
27786
|
-
function
|
|
28161
|
+
function isRecord11(value) {
|
|
27787
28162
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27788
28163
|
}
|
|
27789
28164
|
function decodeRequest(encoded) {
|
|
@@ -27793,7 +28168,7 @@ function decodeRequest(encoded) {
|
|
|
27793
28168
|
} catch (cause) {
|
|
27794
28169
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid", { cause });
|
|
27795
28170
|
}
|
|
27796
|
-
if (!
|
|
28171
|
+
if (!isRecord11(value)) {
|
|
27797
28172
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
|
|
27798
28173
|
}
|
|
27799
28174
|
const keys = Object.keys(value);
|
|
@@ -27843,10 +28218,10 @@ async function decodeRelayResponse(response) {
|
|
|
27843
28218
|
cause
|
|
27844
28219
|
});
|
|
27845
28220
|
}
|
|
27846
|
-
if (response.status === 202 &&
|
|
28221
|
+
if (response.status === 202 && isRecord11(value) && typeof value["outboundMessageId"] === "string") {
|
|
27847
28222
|
return value["outboundMessageId"];
|
|
27848
28223
|
}
|
|
27849
|
-
if (
|
|
28224
|
+
if (isRecord11(value) && isRecord11(value["error"])) {
|
|
27850
28225
|
const error61 = value["error"];
|
|
27851
28226
|
if (typeof error61["code"] === "string" && typeof error61["message"] === "string") {
|
|
27852
28227
|
throw new LocalBotAuthorizationError(error61["code"], error61["message"]);
|
|
@@ -27879,7 +28254,7 @@ var BotOutboundIpcServer = class {
|
|
|
27879
28254
|
if (this.#usesFilesystemSocket) {
|
|
27880
28255
|
await mkdir4(dirname6(this.#socketPath), { mode: 448, recursive: true });
|
|
27881
28256
|
await unlink(this.#socketPath).catch((error61) => {
|
|
27882
|
-
if (!
|
|
28257
|
+
if (!isRecord11(error61) || error61["code"] !== "ENOENT") {
|
|
27883
28258
|
throw error61;
|
|
27884
28259
|
}
|
|
27885
28260
|
});
|
|
@@ -27914,7 +28289,7 @@ var BotOutboundIpcServer = class {
|
|
|
27914
28289
|
}
|
|
27915
28290
|
if (this.#usesFilesystemSocket) {
|
|
27916
28291
|
await unlink(this.#socketPath).catch((error61) => {
|
|
27917
|
-
if (!
|
|
28292
|
+
if (!isRecord11(error61) || error61["code"] !== "ENOENT") {
|
|
27918
28293
|
throw error61;
|
|
27919
28294
|
}
|
|
27920
28295
|
});
|
|
@@ -28002,6 +28377,7 @@ var BotOutboundIpcServer = class {
|
|
|
28002
28377
|
|
|
28003
28378
|
// src/native-sessions/service.ts
|
|
28004
28379
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
28380
|
+
import { basename as basename3 } from "node:path";
|
|
28005
28381
|
|
|
28006
28382
|
// src/native-sessions/codex-history.ts
|
|
28007
28383
|
import { spawn as spawn4 } from "node:child_process";
|
|
@@ -28479,6 +28855,74 @@ var NativeSessionService = class {
|
|
|
28479
28855
|
history: opened.history
|
|
28480
28856
|
};
|
|
28481
28857
|
};
|
|
28858
|
+
executeTurnFork = async (command, signal) => {
|
|
28859
|
+
signal.throwIfAborted();
|
|
28860
|
+
const cwd = await this.#directories.resolve(this.#config.bindingId, command.directoryId, signal);
|
|
28861
|
+
const additionalDirectories = [];
|
|
28862
|
+
const additionalEntries = [];
|
|
28863
|
+
const resolvedPaths = /* @__PURE__ */ new Set([cwd]);
|
|
28864
|
+
for (const directoryId2 of command.additionalDirectoryIds) {
|
|
28865
|
+
const path2 = await this.#directories.resolve(this.#config.bindingId, directoryId2, signal);
|
|
28866
|
+
if (resolvedPaths.has(path2)) {
|
|
28867
|
+
throw new LocalAuthorizationError("Workspace directories must resolve to distinct locations");
|
|
28868
|
+
}
|
|
28869
|
+
resolvedPaths.add(path2);
|
|
28870
|
+
additionalDirectories.push(path2);
|
|
28871
|
+
additionalEntries.push({ directoryId: directoryId2, name: basename3(path2) });
|
|
28872
|
+
}
|
|
28873
|
+
const listing = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
|
|
28874
|
+
const opened = await this.#sessions.forkSessionAtTurn(
|
|
28875
|
+
{
|
|
28876
|
+
additionalDirectories,
|
|
28877
|
+
agent: this.#config.catalog.find(command.agentId),
|
|
28878
|
+
cwd,
|
|
28879
|
+
sessionId: command.targetSessionId,
|
|
28880
|
+
signal
|
|
28881
|
+
},
|
|
28882
|
+
command.sessionId,
|
|
28883
|
+
{
|
|
28884
|
+
messageFingerprint: command.messageFingerprint,
|
|
28885
|
+
messageId: command.messageId,
|
|
28886
|
+
messageOccurrence: command.messageOccurrence
|
|
28887
|
+
}
|
|
28888
|
+
);
|
|
28889
|
+
signal.throwIfAborted();
|
|
28890
|
+
const ready = {
|
|
28891
|
+
additionalDirectories: additionalEntries,
|
|
28892
|
+
agentId: command.agentId,
|
|
28893
|
+
agentName: opened.prepared.agentName,
|
|
28894
|
+
agentVersion: opened.prepared.agentVersion,
|
|
28895
|
+
capabilities: opened.prepared.capabilities,
|
|
28896
|
+
commands: opened.prepared.commands,
|
|
28897
|
+
configOptions: opened.prepared.configOptions,
|
|
28898
|
+
directoryId: command.directoryId,
|
|
28899
|
+
directoryLabel: listing.directoryLabel,
|
|
28900
|
+
kind: "session.ready",
|
|
28901
|
+
requestId: command.requestId,
|
|
28902
|
+
restored: true,
|
|
28903
|
+
sessionId: opened.sessionId
|
|
28904
|
+
};
|
|
28905
|
+
this.#audit.record({
|
|
28906
|
+
commandId: command.requestId,
|
|
28907
|
+
details: {
|
|
28908
|
+
agentId: command.agentId,
|
|
28909
|
+
messageId: command.messageId,
|
|
28910
|
+
sourceCommandId: command.sourceCommandId
|
|
28911
|
+
},
|
|
28912
|
+
event: "native_session_turn_forked",
|
|
28913
|
+
sessionId: command.sessionId
|
|
28914
|
+
});
|
|
28915
|
+
return {
|
|
28916
|
+
action: "fork",
|
|
28917
|
+
history: opened.history,
|
|
28918
|
+
kind: "native.session.result",
|
|
28919
|
+
ready,
|
|
28920
|
+
requestId: command.requestId,
|
|
28921
|
+
sessionId: command.sessionId,
|
|
28922
|
+
targetSessionId: command.targetSessionId,
|
|
28923
|
+
title: command.title
|
|
28924
|
+
};
|
|
28925
|
+
};
|
|
28482
28926
|
authorizeEntry = async (command, options, info) => {
|
|
28483
28927
|
try {
|
|
28484
28928
|
const primary = await this.#directories.identify(command.bindingId, info.cwd, options.signal);
|
|
@@ -29043,6 +29487,11 @@ var SessionEventOutbox = class {
|
|
|
29043
29487
|
}
|
|
29044
29488
|
this.#database.prepare(`UPDATE relay_turn_receipts SET state = ? WHERE command_id = ?`).run(state, commandId);
|
|
29045
29489
|
};
|
|
29490
|
+
isTerminalExecution = (commandId, sessionId) => {
|
|
29491
|
+
const row = this.#database.prepare(`SELECT state FROM relay_turn_receipts WHERE command_id = ? AND session_id = ?`).get(commandId, sessionId);
|
|
29492
|
+
const state = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
|
|
29493
|
+
return state === "succeeded" || state === "failed" || state === "cancelled";
|
|
29494
|
+
};
|
|
29046
29495
|
acknowledge = (acknowledgement) => {
|
|
29047
29496
|
this.#database.prepare(
|
|
29048
29497
|
`DELETE FROM relay_session_event_outbox
|
|
@@ -29555,7 +30004,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
|
|
|
29555
30004
|
additionalDirectories.push(directory);
|
|
29556
30005
|
additionalDirectoryEntries.push({
|
|
29557
30006
|
directoryId: additionalDirectoryId,
|
|
29558
|
-
name:
|
|
30007
|
+
name: basename4(directory)
|
|
29559
30008
|
});
|
|
29560
30009
|
}
|
|
29561
30010
|
return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
|
|
@@ -29704,68 +30153,96 @@ async function executePrompt(outbox, publisher, command, config2, directories, a
|
|
|
29704
30153
|
attemptId
|
|
29705
30154
|
);
|
|
29706
30155
|
const attachments = await resolvePromptArtifacts(config2, command, signal);
|
|
29707
|
-
|
|
29708
|
-
|
|
29709
|
-
|
|
29710
|
-
|
|
29711
|
-
|
|
29712
|
-
|
|
29713
|
-
|
|
29714
|
-
|
|
29715
|
-
|
|
29716
|
-
|
|
29717
|
-
|
|
29718
|
-
|
|
29719
|
-
|
|
29720
|
-
|
|
29721
|
-
|
|
29722
|
-
|
|
29723
|
-
|
|
29724
|
-
|
|
29725
|
-
|
|
29726
|
-
|
|
29727
|
-
|
|
29728
|
-
sessionId: command.sessionId,
|
|
29729
|
-
status: activity.status,
|
|
29730
|
-
title: activity.title,
|
|
29731
|
-
toolKind: activity.toolKind
|
|
29732
|
-
}),
|
|
29733
|
-
attemptId
|
|
29734
|
-
);
|
|
29735
|
-
return Promise.resolve();
|
|
29736
|
-
},
|
|
29737
|
-
onText: (text) => {
|
|
29738
|
-
publisher.recordAttempt(
|
|
29739
|
-
command.sessionId,
|
|
29740
|
-
encodeAgentMessageDeltaEvent({
|
|
29741
|
-
commandId: command.commandId,
|
|
29742
|
-
kind: AGENT_MESSAGE_DELTA_KIND,
|
|
29743
|
-
sessionId: command.sessionId,
|
|
29744
|
-
text
|
|
29745
|
-
}),
|
|
29746
|
-
attemptId
|
|
30156
|
+
let stopReason;
|
|
30157
|
+
if (command.disposition === SessionPromptDisposition.Steer) {
|
|
30158
|
+
await sessions.steerPrompt({
|
|
30159
|
+
additionalDirectories: resolved.additionalDirectories,
|
|
30160
|
+
agent,
|
|
30161
|
+
commandId: command.commandId,
|
|
30162
|
+
cwd: resolved.cwd,
|
|
30163
|
+
images: attachments.images,
|
|
30164
|
+
prompt: command.prompt,
|
|
30165
|
+
resources: attachments.resources,
|
|
30166
|
+
sessionId: command.sessionId,
|
|
30167
|
+
signal,
|
|
30168
|
+
targetCommandId: command.targetCommandId
|
|
30169
|
+
});
|
|
30170
|
+
stopReason = "steered";
|
|
30171
|
+
} else {
|
|
30172
|
+
if (command.disposition === SessionPromptDisposition.Queue && !outbox.isTerminalExecution(command.targetCommandId, command.sessionId)) {
|
|
30173
|
+
throw new AcpExecutionError(
|
|
30174
|
+
"The queued prompt target is unavailable",
|
|
30175
|
+
{},
|
|
30176
|
+
"prompt_queue_target_unavailable"
|
|
29747
30177
|
);
|
|
29748
|
-
|
|
29749
|
-
|
|
29750
|
-
|
|
29751
|
-
|
|
29752
|
-
|
|
29753
|
-
|
|
29754
|
-
|
|
30178
|
+
}
|
|
30179
|
+
const result = await sessions.runPrompt({
|
|
30180
|
+
additionalDirectories: resolved.additionalDirectories,
|
|
30181
|
+
agent,
|
|
30182
|
+
commandId: command.commandId,
|
|
30183
|
+
cwd: resolved.cwd,
|
|
30184
|
+
disposition: command.disposition,
|
|
30185
|
+
images: attachments.images,
|
|
30186
|
+
onActivity: (activity) => {
|
|
30187
|
+
publisher.recordAttempt(
|
|
30188
|
+
command.sessionId,
|
|
30189
|
+
encodeAgentActivityEvent({
|
|
30190
|
+
activityId: activity.activityId,
|
|
30191
|
+
activityType: activity.activityType,
|
|
30192
|
+
commandId: command.commandId,
|
|
30193
|
+
content: activity.content,
|
|
30194
|
+
detail: activity.detail,
|
|
30195
|
+
input: activity.input,
|
|
30196
|
+
kind: AGENT_ACTIVITY_KIND,
|
|
30197
|
+
locations: activity.locations,
|
|
30198
|
+
name: activity.name,
|
|
30199
|
+
output: activity.output,
|
|
30200
|
+
sequence: activity.sequence,
|
|
30201
|
+
sessionId: command.sessionId,
|
|
30202
|
+
status: activity.status,
|
|
30203
|
+
title: activity.title,
|
|
30204
|
+
toolKind: activity.toolKind
|
|
30205
|
+
}),
|
|
30206
|
+
attemptId
|
|
30207
|
+
);
|
|
30208
|
+
return Promise.resolve();
|
|
30209
|
+
},
|
|
30210
|
+
onText: (text, messageId) => {
|
|
30211
|
+
publisher.recordAttempt(
|
|
30212
|
+
command.sessionId,
|
|
30213
|
+
encodeAgentMessageDeltaEvent({
|
|
30214
|
+
commandId: command.commandId,
|
|
30215
|
+
kind: AGENT_MESSAGE_DELTA_KIND,
|
|
30216
|
+
messageId,
|
|
30217
|
+
sessionId: command.sessionId,
|
|
30218
|
+
text
|
|
30219
|
+
}),
|
|
30220
|
+
attemptId
|
|
30221
|
+
);
|
|
30222
|
+
return Promise.resolve();
|
|
30223
|
+
},
|
|
30224
|
+
prompt: command.prompt,
|
|
30225
|
+
resources: attachments.resources,
|
|
30226
|
+
sessionId: command.sessionId,
|
|
30227
|
+
signal,
|
|
30228
|
+
targetCommandId: command.targetCommandId
|
|
30229
|
+
});
|
|
30230
|
+
stopReason = result.stopReason;
|
|
30231
|
+
}
|
|
29755
30232
|
publisher.recordAttempt(
|
|
29756
30233
|
command.sessionId,
|
|
29757
30234
|
encodeSessionCompletedEvent({
|
|
29758
30235
|
commandId: command.commandId,
|
|
29759
30236
|
kind: SESSION_COMPLETED_KIND,
|
|
29760
30237
|
sessionId: command.sessionId,
|
|
29761
|
-
stopReason
|
|
30238
|
+
stopReason
|
|
29762
30239
|
}),
|
|
29763
30240
|
attemptId
|
|
29764
30241
|
);
|
|
29765
|
-
outbox.transitionExecution(command.commandId,
|
|
30242
|
+
outbox.transitionExecution(command.commandId, stopReason === "cancelled" ? "cancelled" : "succeeded");
|
|
29766
30243
|
audit.record({
|
|
29767
30244
|
commandId: command.commandId,
|
|
29768
|
-
event:
|
|
30245
|
+
event: stopReason === "cancelled" ? "session_cancelled" : "session_completed",
|
|
29769
30246
|
sessionId: command.sessionId
|
|
29770
30247
|
});
|
|
29771
30248
|
} catch (error61) {
|
|
@@ -29809,12 +30286,6 @@ function botExecutionAgent(agent, contextHandle, socketPath) {
|
|
|
29809
30286
|
}
|
|
29810
30287
|
async function executeBotPrompt(outbox, publisher, command, config2, directories, audit, sessions, grants, contexts, applicator, ipc, attemptId, signal) {
|
|
29811
30288
|
try {
|
|
29812
|
-
if (command.additionalDirectoryIds.length > 0) {
|
|
29813
|
-
throw new LocalBotAuthorizationError(
|
|
29814
|
-
"binding_not_approved",
|
|
29815
|
-
"The Bot execution requested unapproved additional directories"
|
|
29816
|
-
);
|
|
29817
|
-
}
|
|
29818
30289
|
const deadline = Date.parse(command.executionDeadlineAt);
|
|
29819
30290
|
const remaining = deadline - Date.now();
|
|
29820
30291
|
if (!Number.isSafeInteger(deadline) || remaining <= 0) {
|
|
@@ -29828,6 +30299,32 @@ async function executeBotPrompt(outbox, publisher, command, config2, directories
|
|
|
29828
30299
|
Date.now(),
|
|
29829
30300
|
signal
|
|
29830
30301
|
);
|
|
30302
|
+
const requestedExecutionTargetOverridden = command.directoryId !== grant.workspaceRef || command.additionalDirectoryIds.length > 0;
|
|
30303
|
+
if (requestedExecutionTargetOverridden && !(command.replyRoute instanceof OwnerBotReplyRoute)) {
|
|
30304
|
+
throw new LocalBotAuthorizationError(
|
|
30305
|
+
"binding_not_approved",
|
|
30306
|
+
"Only a paired owner conversation can override the approved Bot workspace"
|
|
30307
|
+
);
|
|
30308
|
+
}
|
|
30309
|
+
const resolved = await resolveSessionDirectories(
|
|
30310
|
+
directories,
|
|
30311
|
+
config2.bindingId,
|
|
30312
|
+
command.directoryId,
|
|
30313
|
+
command.additionalDirectoryIds,
|
|
30314
|
+
signal
|
|
30315
|
+
);
|
|
30316
|
+
const executionTargetOverridden = resolved.cwd !== grant.workspacePath || resolved.additionalDirectories.length > 0;
|
|
30317
|
+
if (executionTargetOverridden && !sessions.hasPreparedSession(
|
|
30318
|
+
command.sessionId,
|
|
30319
|
+
grant.agent.id,
|
|
30320
|
+
resolved.cwd,
|
|
30321
|
+
resolved.additionalDirectories
|
|
30322
|
+
)) {
|
|
30323
|
+
throw new LocalBotAuthorizationError(
|
|
30324
|
+
"local_approval_required",
|
|
30325
|
+
"Open this Bot conversation in the paired local Web app before using the selected workspace"
|
|
30326
|
+
);
|
|
30327
|
+
}
|
|
29831
30328
|
const attachments = await resolvePromptArtifacts(config2, command, signal);
|
|
29832
30329
|
const applied = await applicator.apply(command, grant, attachments.resources, signal);
|
|
29833
30330
|
const lease = contexts.activate(command);
|
|
@@ -29835,6 +30332,13 @@ async function executeBotPrompt(outbox, publisher, command, config2, directories
|
|
|
29835
30332
|
const deadlineSignal = AbortSignal.timeout(remaining);
|
|
29836
30333
|
const executionSignal = AbortSignal.any([signal, deadlineSignal]);
|
|
29837
30334
|
const agent = botExecutionAgent(grant.agent, lease.context.contextHandle, ipc.socketPath);
|
|
30335
|
+
await sessions.prepareExecutionSession({
|
|
30336
|
+
additionalDirectories: resolved.additionalDirectories,
|
|
30337
|
+
agent,
|
|
30338
|
+
cwd: resolved.cwd,
|
|
30339
|
+
sessionId: command.sessionId,
|
|
30340
|
+
signal: executionSignal
|
|
30341
|
+
});
|
|
29838
30342
|
audit.record({
|
|
29839
30343
|
commandId: command.commandId,
|
|
29840
30344
|
details: {
|
|
@@ -29859,10 +30363,10 @@ async function executeBotPrompt(outbox, publisher, command, config2, directories
|
|
|
29859
30363
|
attemptId
|
|
29860
30364
|
);
|
|
29861
30365
|
const result = await sessions.runPrompt({
|
|
29862
|
-
additionalDirectories:
|
|
30366
|
+
additionalDirectories: resolved.additionalDirectories,
|
|
29863
30367
|
agent,
|
|
29864
30368
|
commandId: command.commandId,
|
|
29865
|
-
cwd:
|
|
30369
|
+
cwd: resolved.cwd,
|
|
29866
30370
|
images: attachments.images,
|
|
29867
30371
|
onActivity: (activity) => {
|
|
29868
30372
|
publisher.recordAttempt(
|
|
@@ -29888,12 +30392,13 @@ async function executeBotPrompt(outbox, publisher, command, config2, directories
|
|
|
29888
30392
|
);
|
|
29889
30393
|
return Promise.resolve();
|
|
29890
30394
|
},
|
|
29891
|
-
onText: (text) => {
|
|
30395
|
+
onText: (text, messageId) => {
|
|
29892
30396
|
publisher.recordAttempt(
|
|
29893
30397
|
command.sessionId,
|
|
29894
30398
|
encodeAgentMessageDeltaEvent({
|
|
29895
30399
|
commandId: command.commandId,
|
|
29896
30400
|
kind: AGENT_MESSAGE_DELTA_KIND,
|
|
30401
|
+
messageId,
|
|
29897
30402
|
sessionId: command.sessionId,
|
|
29898
30403
|
text
|
|
29899
30404
|
}),
|
|
@@ -30248,6 +30753,86 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30248
30753
|
});
|
|
30249
30754
|
return;
|
|
30250
30755
|
}
|
|
30756
|
+
if (kind === NATIVE_SESSION_TURN_FORK_KIND) {
|
|
30757
|
+
const command2 = decodeNativeSessionTurnForkCommand(encoded);
|
|
30758
|
+
const previous = [...nativeRequests.values()].filter(
|
|
30759
|
+
(request) => request.agentId === command2.agentId
|
|
30760
|
+
);
|
|
30761
|
+
if (nativeRequests.has(command2.requestId) || nativeRequests.size >= 4 || previous.some((request) => !request.controller.signal.aborted)) {
|
|
30762
|
+
reportOperationFailure(
|
|
30763
|
+
socket,
|
|
30764
|
+
command2.requestId,
|
|
30765
|
+
command2.sessionId,
|
|
30766
|
+
new AcpExecutionError(
|
|
30767
|
+
"Another native session operation is running",
|
|
30768
|
+
{},
|
|
30769
|
+
"native_session_busy"
|
|
30770
|
+
)
|
|
30771
|
+
);
|
|
30772
|
+
return;
|
|
30773
|
+
}
|
|
30774
|
+
const controller = new AbortController();
|
|
30775
|
+
const operationSignal = AbortSignal.any([connectionController.signal, controller.signal]);
|
|
30776
|
+
const timeout = timer.schedule(
|
|
30777
|
+
() => controller.abort(
|
|
30778
|
+
new AcpExecutionError(
|
|
30779
|
+
"Native session operation timed out",
|
|
30780
|
+
{},
|
|
30781
|
+
"native_session_timeout"
|
|
30782
|
+
)
|
|
30783
|
+
),
|
|
30784
|
+
9e4
|
|
30785
|
+
);
|
|
30786
|
+
const completion = (async () => {
|
|
30787
|
+
try {
|
|
30788
|
+
operationSignal.throwIfAborted();
|
|
30789
|
+
if (previous.length > 0) {
|
|
30790
|
+
await new Promise((resolve6, reject2) => {
|
|
30791
|
+
const cancel = () => reject2(operationSignal.reason);
|
|
30792
|
+
operationSignal.addEventListener("abort", cancel, { once: true });
|
|
30793
|
+
void Promise.all(previous.map((request) => request.completion)).then(
|
|
30794
|
+
() => {
|
|
30795
|
+
operationSignal.removeEventListener("abort", cancel);
|
|
30796
|
+
resolve6();
|
|
30797
|
+
},
|
|
30798
|
+
(error61) => {
|
|
30799
|
+
operationSignal.removeEventListener("abort", cancel);
|
|
30800
|
+
reject2(error61);
|
|
30801
|
+
}
|
|
30802
|
+
);
|
|
30803
|
+
});
|
|
30804
|
+
}
|
|
30805
|
+
operationSignal.throwIfAborted();
|
|
30806
|
+
const result = await nativeSessions.executeTurnFork(command2, operationSignal);
|
|
30807
|
+
if (socket.readyState === WebSocket2.OPEN) {
|
|
30808
|
+
send(socket, encodeNativeSessionResult(result));
|
|
30809
|
+
}
|
|
30810
|
+
} catch (error61) {
|
|
30811
|
+
const failure = operationSignal.aborted ? controller.signal.reason ?? new AcpExecutionError(
|
|
30812
|
+
"Native session operation cancelled",
|
|
30813
|
+
{},
|
|
30814
|
+
"native_session_cancelled"
|
|
30815
|
+
) : error61;
|
|
30816
|
+
audit.record({
|
|
30817
|
+
commandId: command2.requestId,
|
|
30818
|
+
details: { code: operationErrorCode(failure) },
|
|
30819
|
+
event: "native_session_turn_fork_failed",
|
|
30820
|
+
sessionId: command2.sessionId
|
|
30821
|
+
});
|
|
30822
|
+
reportOperationFailure(socket, command2.requestId, command2.sessionId, failure);
|
|
30823
|
+
} finally {
|
|
30824
|
+
timeout.cancel();
|
|
30825
|
+
nativeRequests.delete(command2.requestId);
|
|
30826
|
+
}
|
|
30827
|
+
})();
|
|
30828
|
+
nativeRequests.set(command2.requestId, {
|
|
30829
|
+
agentId: command2.agentId,
|
|
30830
|
+
completion,
|
|
30831
|
+
controller,
|
|
30832
|
+
sessionId: command2.sessionId
|
|
30833
|
+
});
|
|
30834
|
+
return;
|
|
30835
|
+
}
|
|
30251
30836
|
if (kind === RUNTIME_LIVENESS_READY_KIND) {
|
|
30252
30837
|
decodeRuntimeLivenessReadyEvent(encoded);
|
|
30253
30838
|
connectionLiveness.start();
|
|
@@ -30401,7 +30986,9 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
30401
30986
|
}
|
|
30402
30987
|
const turn = new ActiveDaemonTurn(command, receipt.attemptId);
|
|
30403
30988
|
activeTurns.set(command.commandId, turn);
|
|
30404
|
-
|
|
30989
|
+
if (command.disposition !== SessionPromptDisposition.Steer) {
|
|
30990
|
+
activeAttemptIds.set(command.sessionId, receipt.attemptId);
|
|
30991
|
+
}
|
|
30405
30992
|
void executePrompt(
|
|
30406
30993
|
outbox,
|
|
30407
30994
|
publisher,
|