@moxt-ai/mobius 0.0.149 → 0.0.152
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/agent-runtime-manager.d.ts.map +1 -1
- package/dist/acp/agent-runtime-manager.js +8 -1
- package/dist/acp/agent-runtime-manager.js.map +1 -1
- package/dist/acp/agent-session.d.ts.map +1 -1
- package/dist/acp/agent-session.js +8 -4
- package/dist/acp/agent-session.js.map +1 -1
- package/dist/acp/session-contracts.d.ts +2 -1
- package/dist/acp/session-contracts.d.ts.map +1 -1
- package/dist/acp/session-contracts.js +3 -1
- package/dist/acp/session-contracts.js.map +1 -1
- package/dist/acp/session-store.d.ts +2 -1
- package/dist/acp/session-store.d.ts.map +1 -1
- package/dist/acp/session-store.js +6 -2
- package/dist/acp/session-store.js.map +1 -1
- package/dist/cli.js +662 -60
- package/dist/cli.js.map +4 -4
- package/dist/daemon-command-handler.d.ts.map +1 -1
- package/dist/daemon-command-handler.js +1 -0
- package/dist/daemon-command-handler.js.map +1 -1
- package/dist/daemon-prompt-executor.d.ts.map +1 -1
- package/dist/daemon-prompt-executor.js +28 -8
- package/dist/daemon-prompt-executor.js.map +1 -1
- package/dist/generated/acp-session-store-migrations.d.ts +3 -0
- package/dist/generated/acp-session-store-migrations.d.ts.map +1 -1
- package/dist/generated/acp-session-store-migrations.js +5 -1
- package/dist/generated/acp-session-store-migrations.js.map +1 -1
- package/dist/index.js +661 -59
- package/dist/index.js.map +4 -4
- package/dist/native-sessions/handle-native-requests.d.ts +2 -0
- package/dist/native-sessions/handle-native-requests.d.ts.map +1 -1
- package/dist/native-sessions/handle-native-requests.js +12 -1
- package/dist/native-sessions/handle-native-requests.js.map +1 -1
- package/dist/native-sessions/service.d.ts.map +1 -1
- package/dist/native-sessions/service.js +47 -0
- package/dist/native-sessions/service.js.map +1 -1
- package/dist/relay-connection/run-relay-connection.d.ts.map +1 -1
- package/dist/relay-connection/run-relay-connection.js +15 -2
- package/dist/relay-connection/run-relay-connection.js.map +1 -1
- package/dist/relay-connection/session-event-outbox.d.ts +20 -0
- package/dist/relay-connection/session-event-outbox.d.ts.map +1 -0
- package/dist/relay-connection/session-event-outbox.js +243 -0
- package/dist/relay-connection/session-event-outbox.js.map +1 -0
- package/dist/relay-connection/session-event-publisher.d.ts +11 -4
- package/dist/relay-connection/session-event-publisher.d.ts.map +1 -1
- package/dist/relay-connection/session-event-publisher.js +148 -32
- package/dist/relay-connection/session-event-publisher.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +3 -1
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.js +669 -67
- package/dist/runtime.js.map +4 -4
- package/dist/schema/acp-session-store/acp-session.d.ts +19 -0
- package/dist/schema/acp-session-store/acp-session.d.ts.map +1 -1
- package/dist/schema/acp-session-store/acp-session.js +1 -0
- package/dist/schema/acp-session-store/acp-session.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3381,7 +3381,7 @@ var program = new Command();
|
|
|
3381
3381
|
// package.json
|
|
3382
3382
|
var package_default = {
|
|
3383
3383
|
name: "@moxt-ai/mobius",
|
|
3384
|
-
version: "0.0.
|
|
3384
|
+
version: "0.0.152",
|
|
3385
3385
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
3386
3386
|
type: "module",
|
|
3387
3387
|
bin: {
|
|
@@ -29330,9 +29330,17 @@ function decodeSessionQueuedEvent(encoded) {
|
|
|
29330
29330
|
}
|
|
29331
29331
|
function decodeRuntimeLivenessReadyEvent(encoded) {
|
|
29332
29332
|
const value = parseJson2(encoded);
|
|
29333
|
-
assertExactKeys(value, ["kind"]);
|
|
29334
29333
|
assertKind(value, RUNTIME_LIVENESS_READY_KIND);
|
|
29335
|
-
|
|
29334
|
+
if (value["sessionEventDelivery"] === void 0) {
|
|
29335
|
+
assertExactKeys(value, ["kind"]);
|
|
29336
|
+
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
29337
|
+
}
|
|
29338
|
+
assertExactKeys(value, ["kind", "sessionEventDelivery"]);
|
|
29339
|
+
const sessionEventDelivery = readString2(value, "sessionEventDelivery", 32);
|
|
29340
|
+
if (sessionEventDelivery !== "reliable-v1") {
|
|
29341
|
+
throw new ProtocolMessageError("Unsupported Session event delivery mode");
|
|
29342
|
+
}
|
|
29343
|
+
return { kind: RUNTIME_LIVENESS_READY_KIND, sessionEventDelivery };
|
|
29336
29344
|
}
|
|
29337
29345
|
function decodeRuntimeHeartbeatEvent(encoded) {
|
|
29338
29346
|
const value = parseJson2(encoded);
|
|
@@ -29664,6 +29672,12 @@ var nativeSessionRequestSchema = external_exports.discriminatedUnion("action", [
|
|
|
29664
29672
|
entryId: identifierStringSchema,
|
|
29665
29673
|
targetSessionId: identifierStringSchema
|
|
29666
29674
|
}).readonly(),
|
|
29675
|
+
external_exports.strictObject({
|
|
29676
|
+
...identity,
|
|
29677
|
+
action: external_exports.literal("fork-recorded"),
|
|
29678
|
+
targetSessionId: identifierStringSchema,
|
|
29679
|
+
throughCommandId: identifierStringSchema
|
|
29680
|
+
}).readonly(),
|
|
29667
29681
|
external_exports.strictObject({
|
|
29668
29682
|
...identity,
|
|
29669
29683
|
action: external_exports.literal("delete"),
|
|
@@ -29687,6 +29701,12 @@ var nativeSessionCommandSchema = external_exports.discriminatedUnion("action", [
|
|
|
29687
29701
|
entryId: identifierStringSchema,
|
|
29688
29702
|
targetSessionId: identifierStringSchema
|
|
29689
29703
|
}).readonly(),
|
|
29704
|
+
external_exports.strictObject({
|
|
29705
|
+
...identity,
|
|
29706
|
+
action: external_exports.literal("fork-recorded"),
|
|
29707
|
+
targetSessionId: identifierStringSchema,
|
|
29708
|
+
throughCommandId: identifierStringSchema
|
|
29709
|
+
}).readonly(),
|
|
29690
29710
|
external_exports.strictObject({
|
|
29691
29711
|
...identity,
|
|
29692
29712
|
action: external_exports.literal("delete"),
|
|
@@ -29736,7 +29756,7 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
|
|
|
29736
29756
|
}).readonly(),
|
|
29737
29757
|
external_exports.strictObject({
|
|
29738
29758
|
...resultEnvelope,
|
|
29739
|
-
action: external_exports.enum(["import", "fork"]),
|
|
29759
|
+
action: external_exports.enum(["import", "fork", "fork-recorded"]),
|
|
29740
29760
|
targetSessionId: identifierStringSchema,
|
|
29741
29761
|
ready: sessionReadyEventSchema,
|
|
29742
29762
|
title: external_exports.string().max(500)
|
|
@@ -29782,14 +29802,68 @@ var encodeNativeSessionCancel = (value) => JSON.stringify(nativeSessionCancelSch
|
|
|
29782
29802
|
|
|
29783
29803
|
// ../protocol/src/session-events.ts
|
|
29784
29804
|
var SESSION_EVENT_KIND = "session.event";
|
|
29805
|
+
var SESSION_EVENT_ACK_KIND = "session.event.ack";
|
|
29806
|
+
var SESSION_EVENT_DEFERRED_KIND = "session.event.deferred";
|
|
29807
|
+
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
29808
|
+
var SESSION_FORKED_KIND = "session.forked";
|
|
29809
|
+
var SessionEventRejectionCode = {
|
|
29810
|
+
IdempotencyConflict: "idempotency_conflict",
|
|
29811
|
+
InvalidEvent: "invalid_event",
|
|
29812
|
+
RecordingRejected: "recording_rejected"
|
|
29813
|
+
};
|
|
29785
29814
|
var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
|
|
29786
|
-
var
|
|
29815
|
+
var ephemeralEventEnvelopeSchema = external_exports.strictObject({
|
|
29787
29816
|
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
29788
29817
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
29789
29818
|
sessionId: identifierStringSchema
|
|
29790
29819
|
}).readonly();
|
|
29820
|
+
var reliableDeliverySchema = external_exports.strictObject({
|
|
29821
|
+
eventId: identifierStringSchema,
|
|
29822
|
+
kind: external_exports.literal("reliable"),
|
|
29823
|
+
sourceSeq: external_exports.string().regex(/^(?:0|[1-9][0-9]*)$/u).max(40),
|
|
29824
|
+
streamId: identifierStringSchema
|
|
29825
|
+
}).readonly();
|
|
29826
|
+
var reliableSessionEventEnvelopeSchema = external_exports.strictObject({
|
|
29827
|
+
delivery: reliableDeliverySchema,
|
|
29828
|
+
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
29829
|
+
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
29830
|
+
sessionId: identifierStringSchema
|
|
29831
|
+
}).readonly();
|
|
29832
|
+
var eventEnvelopeSchema = external_exports.union([ephemeralEventEnvelopeSchema, reliableSessionEventEnvelopeSchema]).readonly();
|
|
29833
|
+
var acknowledgementOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
29834
|
+
external_exports.strictObject({ kind: external_exports.literal("relayed") }).readonly(),
|
|
29835
|
+
external_exports.strictObject({
|
|
29836
|
+
kind: external_exports.literal("recorded"),
|
|
29837
|
+
providerId: identifierStringSchema,
|
|
29838
|
+
recordingEpoch: identifierStringSchema
|
|
29839
|
+
}).readonly()
|
|
29840
|
+
]);
|
|
29841
|
+
var eventAcknowledgementSchema = external_exports.strictObject({
|
|
29842
|
+
eventId: identifierStringSchema,
|
|
29843
|
+
kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
|
|
29844
|
+
outcome: acknowledgementOutcomeSchema,
|
|
29845
|
+
sessionId: identifierStringSchema
|
|
29846
|
+
}).readonly();
|
|
29847
|
+
var eventDeferredSchema = external_exports.strictObject({
|
|
29848
|
+
eventId: identifierStringSchema,
|
|
29849
|
+
kind: external_exports.literal(SESSION_EVENT_DEFERRED_KIND),
|
|
29850
|
+
retryAfterMilliseconds: external_exports.number().int().min(100).max(6e4),
|
|
29851
|
+
sessionId: identifierStringSchema
|
|
29852
|
+
}).readonly();
|
|
29853
|
+
var eventRejectedSchema = external_exports.strictObject({
|
|
29854
|
+
code: external_exports.enum(SessionEventRejectionCode),
|
|
29855
|
+
eventId: identifierStringSchema,
|
|
29856
|
+
kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
|
|
29857
|
+
sessionId: identifierStringSchema
|
|
29858
|
+
}).readonly();
|
|
29791
29859
|
var SESSION_QUEUE_CHANGED_KIND = "session.queue.changed";
|
|
29792
29860
|
var sessionQueueChangedSchema = external_exports.strictObject({ kind: external_exports.literal(SESSION_QUEUE_CHANGED_KIND), sessionId: identifierStringSchema }).readonly();
|
|
29861
|
+
var sessionForkedSchema = external_exports.strictObject({
|
|
29862
|
+
kind: external_exports.literal(SESSION_FORKED_KIND),
|
|
29863
|
+
sessionId: identifierStringSchema,
|
|
29864
|
+
sourceSessionId: identifierStringSchema,
|
|
29865
|
+
throughCommandId: identifierStringSchema
|
|
29866
|
+
}).readonly();
|
|
29793
29867
|
function decode5(encoded, schema) {
|
|
29794
29868
|
let value;
|
|
29795
29869
|
try {
|
|
@@ -29816,11 +29890,19 @@ var encode4 = (message, schema) => {
|
|
|
29816
29890
|
};
|
|
29817
29891
|
var decodeSessionEventEnvelope = (encoded) => decode5(encoded, eventEnvelopeSchema);
|
|
29818
29892
|
var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
|
|
29893
|
+
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
29894
|
+
var encodeSessionEventAcknowledgement = (message) => encode4(message, eventAcknowledgementSchema);
|
|
29895
|
+
var decodeSessionEventDeferred = (encoded) => decode5(encoded, eventDeferredSchema);
|
|
29896
|
+
var encodeSessionEventDeferred = (message) => encode4(message, eventDeferredSchema);
|
|
29897
|
+
var decodeSessionEventRejected = (encoded) => decode5(encoded, eventRejectedSchema);
|
|
29898
|
+
var encodeSessionEventRejected = (message) => encode4(message, eventRejectedSchema);
|
|
29819
29899
|
function decodeRecordedSessionEvent(encoded) {
|
|
29820
29900
|
const kind = decodeMessageKind(encoded);
|
|
29821
29901
|
switch (kind) {
|
|
29822
29902
|
case SESSION_QUEUE_CHANGED_KIND:
|
|
29823
29903
|
return decode5(encoded, sessionQueueChangedSchema);
|
|
29904
|
+
case SESSION_FORKED_KIND:
|
|
29905
|
+
return decode5(encoded, sessionForkedSchema);
|
|
29824
29906
|
case AGENT_ACTIVITY_KIND:
|
|
29825
29907
|
return decodeAgentActivityEvent(encoded);
|
|
29826
29908
|
case AGENT_ACTIVITY_NARRATION_KIND:
|
|
@@ -29987,6 +30069,21 @@ var serviceToDaemonSignatures = {
|
|
|
29987
30069
|
encodeSessionElicitationRespondCommand,
|
|
29988
30070
|
decodeSessionElicitationRespondCommand
|
|
29989
30071
|
),
|
|
30072
|
+
[SESSION_EVENT_ACK_KIND]: defineMessageSignature(
|
|
30073
|
+
SESSION_EVENT_ACK_KIND,
|
|
30074
|
+
encodeSessionEventAcknowledgement,
|
|
30075
|
+
decodeSessionEventAcknowledgement
|
|
30076
|
+
),
|
|
30077
|
+
[SESSION_EVENT_DEFERRED_KIND]: defineMessageSignature(
|
|
30078
|
+
SESSION_EVENT_DEFERRED_KIND,
|
|
30079
|
+
encodeSessionEventDeferred,
|
|
30080
|
+
decodeSessionEventDeferred
|
|
30081
|
+
),
|
|
30082
|
+
[SESSION_EVENT_REJECTED_KIND]: defineMessageSignature(
|
|
30083
|
+
SESSION_EVENT_REJECTED_KIND,
|
|
30084
|
+
encodeSessionEventRejected,
|
|
30085
|
+
decodeSessionEventRejected
|
|
30086
|
+
),
|
|
29990
30087
|
[SESSION_LIVE_HISTORY_LOAD_KIND]: defineMessageSignature(
|
|
29991
30088
|
SESSION_LIVE_HISTORY_LOAD_KIND,
|
|
29992
30089
|
encodeSessionLiveHistoryLoad,
|
|
@@ -31045,7 +31142,7 @@ var AuditStore = class {
|
|
|
31045
31142
|
};
|
|
31046
31143
|
|
|
31047
31144
|
// src/run-daemon.ts
|
|
31048
|
-
import { createHash as createHash6, randomUUID as
|
|
31145
|
+
import { createHash as createHash6, randomUUID as randomUUID8 } from "node:crypto";
|
|
31049
31146
|
import { join as join18 } from "node:path";
|
|
31050
31147
|
import { styleText } from "node:util";
|
|
31051
31148
|
|
|
@@ -32610,13 +32707,15 @@ var AcpPreparedSession = class {
|
|
|
32610
32707
|
capabilities;
|
|
32611
32708
|
commands;
|
|
32612
32709
|
configOptions;
|
|
32710
|
+
prompted;
|
|
32613
32711
|
restored;
|
|
32614
|
-
constructor(agentName, agentVersion, capabilities, commands, configOptions, restored) {
|
|
32712
|
+
constructor(agentName, agentVersion, capabilities, commands, configOptions, prompted, restored) {
|
|
32615
32713
|
this.agentName = agentName;
|
|
32616
32714
|
this.agentVersion = agentVersion;
|
|
32617
32715
|
this.capabilities = capabilities;
|
|
32618
32716
|
this.commands = commands;
|
|
32619
32717
|
this.configOptions = configOptions;
|
|
32718
|
+
this.prompted = prompted;
|
|
32620
32719
|
this.restored = restored;
|
|
32621
32720
|
}
|
|
32622
32721
|
};
|
|
@@ -38786,6 +38885,10 @@ var acpSessionStoreMigrations = [
|
|
|
38786
38885
|
{
|
|
38787
38886
|
"name": "0000_slimy_captain_midlands.sql",
|
|
38788
38887
|
"sql": "CREATE TABLE `acp_session` (\n `session_id` text PRIMARY KEY NOT NULL,\n `agent_id` text NOT NULL,\n `native_session_id` text NOT NULL,\n `cwd` text NOT NULL,\n `additional_directories` text NOT NULL,\n `prompted` integer NOT NULL,\n `title` text NOT NULL,\n `updated_at` text NOT NULL\n);\n--> statement-breakpoint\nCREATE TABLE `deleted_acp_session` (\n `session_id` text PRIMARY KEY NOT NULL\n);\n"
|
|
38888
|
+
},
|
|
38889
|
+
{
|
|
38890
|
+
"name": "0001_regular_ultimates.sql",
|
|
38891
|
+
"sql": "ALTER TABLE `acp_session` ADD `last_terminal_command_id` text;"
|
|
38789
38892
|
}
|
|
38790
38893
|
];
|
|
38791
38894
|
|
|
@@ -38803,6 +38906,7 @@ var acpSession = sqliteTable("acp_session", {
|
|
|
38803
38906
|
nativeSessionId: text("native_session_id").notNull(),
|
|
38804
38907
|
cwd: text("cwd").notNull(),
|
|
38805
38908
|
additionalDirectories: text("additional_directories").notNull(),
|
|
38909
|
+
lastTerminalCommandId: text("last_terminal_command_id"),
|
|
38806
38910
|
prompted: integer2("prompted", { mode: "boolean" }).notNull(),
|
|
38807
38911
|
title: text("title").notNull(),
|
|
38808
38912
|
updatedAt: text("updated_at").notNull()
|
|
@@ -38818,15 +38922,17 @@ var AcpStoredSession = class {
|
|
|
38818
38922
|
additionalDirectories;
|
|
38819
38923
|
agentId;
|
|
38820
38924
|
cwd;
|
|
38925
|
+
lastTerminalCommandId;
|
|
38821
38926
|
nativeSessionId;
|
|
38822
38927
|
prompted;
|
|
38823
38928
|
sessionId;
|
|
38824
38929
|
title;
|
|
38825
38930
|
updatedAt;
|
|
38826
|
-
constructor(sessionId, agentId, nativeSessionId, cwd, additionalDirectories, prompted, title2, updatedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
38931
|
+
constructor(sessionId, agentId, nativeSessionId, cwd, additionalDirectories, prompted, title2, updatedAt = (/* @__PURE__ */ new Date()).toISOString(), lastTerminalCommandId = null) {
|
|
38827
38932
|
this.additionalDirectories = [...additionalDirectories];
|
|
38828
38933
|
this.agentId = agentId;
|
|
38829
38934
|
this.cwd = cwd;
|
|
38935
|
+
this.lastTerminalCommandId = lastTerminalCommandId;
|
|
38830
38936
|
this.nativeSessionId = nativeSessionId;
|
|
38831
38937
|
this.prompted = prompted;
|
|
38832
38938
|
this.sessionId = sessionId;
|
|
@@ -38887,6 +38993,7 @@ var storedSessionRowSchema = external_exports.object({
|
|
|
38887
38993
|
additionalDirectories: external_exports.string(),
|
|
38888
38994
|
agentId: external_exports.string(),
|
|
38889
38995
|
cwd: external_exports.string(),
|
|
38996
|
+
lastTerminalCommandId: external_exports.string().nullable(),
|
|
38890
38997
|
nativeSessionId: external_exports.string(),
|
|
38891
38998
|
prompted: external_exports.boolean(),
|
|
38892
38999
|
sessionId: external_exports.string(),
|
|
@@ -38906,7 +39013,8 @@ function decodeStoredSession(value) {
|
|
|
38906
39013
|
additionalDirectories,
|
|
38907
39014
|
row.prompted,
|
|
38908
39015
|
row.title,
|
|
38909
|
-
row.updatedAt
|
|
39016
|
+
row.updatedAt,
|
|
39017
|
+
row.lastTerminalCommandId
|
|
38910
39018
|
);
|
|
38911
39019
|
}
|
|
38912
39020
|
var SqliteAcpSessionStore = class {
|
|
@@ -38973,6 +39081,7 @@ var SqliteAcpSessionStore = class {
|
|
|
38973
39081
|
additionalDirectories: JSON.stringify(session.additionalDirectories),
|
|
38974
39082
|
agentId: session.agentId,
|
|
38975
39083
|
cwd: session.cwd,
|
|
39084
|
+
lastTerminalCommandId: session.lastTerminalCommandId,
|
|
38976
39085
|
nativeSessionId: session.nativeSessionId,
|
|
38977
39086
|
prompted: session.prompted,
|
|
38978
39087
|
sessionId: session.sessionId,
|
|
@@ -39025,6 +39134,7 @@ var AgentSession = class _AgentSession {
|
|
|
39025
39134
|
#commands = [];
|
|
39026
39135
|
#configRevision = 0;
|
|
39027
39136
|
#configOptions = [];
|
|
39137
|
+
#lastTerminalCommandId = null;
|
|
39028
39138
|
#prompted = false;
|
|
39029
39139
|
#nativePrompt = null;
|
|
39030
39140
|
#sessionLoad = { kind: "not-requested" };
|
|
@@ -39128,6 +39238,7 @@ var AgentSession = class _AgentSession {
|
|
|
39128
39238
|
this.#capabilities,
|
|
39129
39239
|
this.#commands,
|
|
39130
39240
|
this.#configOptions,
|
|
39241
|
+
this.#prompted,
|
|
39131
39242
|
this.#restored
|
|
39132
39243
|
);
|
|
39133
39244
|
loadHistory = async (signal) => {
|
|
@@ -39361,6 +39472,7 @@ var AgentSession = class _AgentSession {
|
|
|
39361
39472
|
} else if (stored instanceof FoundAcpStoredSession && stored.session.agentId === this.#agentId && stored.session.cwd === this.#cwd && arraysEqual(stored.session.additionalDirectories, this.#additionalDirectories)) {
|
|
39362
39473
|
this.selectNativeSession(stored.session.nativeSessionId);
|
|
39363
39474
|
this.#prompted = stored.session.prompted;
|
|
39475
|
+
this.#lastTerminalCommandId = stored.session.lastTerminalCommandId;
|
|
39364
39476
|
this.#sessionTitle = stored.session.title;
|
|
39365
39477
|
this.#restored = true;
|
|
39366
39478
|
if (this.#capabilities.resumeSession) {
|
|
@@ -39434,7 +39546,9 @@ var AgentSession = class _AgentSession {
|
|
|
39434
39546
|
this.#cwd,
|
|
39435
39547
|
this.#additionalDirectories,
|
|
39436
39548
|
this.#prompted,
|
|
39437
|
-
this.#sessionTitle ?? ""
|
|
39549
|
+
this.#sessionTitle ?? "",
|
|
39550
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
39551
|
+
this.#lastTerminalCommandId
|
|
39438
39552
|
)
|
|
39439
39553
|
);
|
|
39440
39554
|
};
|
|
@@ -39634,7 +39748,9 @@ var AgentSession = class _AgentSession {
|
|
|
39634
39748
|
this.#cwd,
|
|
39635
39749
|
this.#additionalDirectories,
|
|
39636
39750
|
true,
|
|
39637
|
-
this.#sessionTitle
|
|
39751
|
+
this.#sessionTitle,
|
|
39752
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
39753
|
+
this.#lastTerminalCommandId
|
|
39638
39754
|
)
|
|
39639
39755
|
);
|
|
39640
39756
|
this.#prompted = true;
|
|
@@ -39686,6 +39802,20 @@ var AgentSession = class _AgentSession {
|
|
|
39686
39802
|
usage: result.usage ?? null
|
|
39687
39803
|
});
|
|
39688
39804
|
}
|
|
39805
|
+
this.#lastTerminalCommandId = options.commandId;
|
|
39806
|
+
this.#store.write(
|
|
39807
|
+
new AcpStoredSession(
|
|
39808
|
+
this.#mobiusSessionId,
|
|
39809
|
+
this.#agentId,
|
|
39810
|
+
this.#updates.sessionId(),
|
|
39811
|
+
this.#cwd,
|
|
39812
|
+
this.#additionalDirectories,
|
|
39813
|
+
true,
|
|
39814
|
+
this.#sessionTitle ?? "",
|
|
39815
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
39816
|
+
this.#lastTerminalCommandId
|
|
39817
|
+
)
|
|
39818
|
+
);
|
|
39689
39819
|
return result;
|
|
39690
39820
|
} catch (error62) {
|
|
39691
39821
|
await running.activities.finish();
|
|
@@ -39878,7 +40008,9 @@ var AgentSession = class _AgentSession {
|
|
|
39878
40008
|
this.#cwd,
|
|
39879
40009
|
this.#additionalDirectories,
|
|
39880
40010
|
this.#prompted,
|
|
39881
|
-
this.#sessionTitle ?? ""
|
|
40011
|
+
this.#sessionTitle ?? "",
|
|
40012
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
40013
|
+
this.#lastTerminalCommandId
|
|
39882
40014
|
)
|
|
39883
40015
|
);
|
|
39884
40016
|
}
|
|
@@ -40924,9 +41056,17 @@ var AgentRuntimeManager = class {
|
|
|
40924
41056
|
const openedKey = `${options2.agent.id}:${runtime.nativeSessionId()}`;
|
|
40925
41057
|
this.#nativeOperations.add(openedKey);
|
|
40926
41058
|
try {
|
|
41059
|
+
const prepared = runtime.prepared();
|
|
41060
|
+
if (origin.kind === "fork" && options2.agent.id === "claude") {
|
|
41061
|
+
await this.#retireSessionProcess(
|
|
41062
|
+
options2.sessionId,
|
|
41063
|
+
runtime,
|
|
41064
|
+
async () => await runtime.closeProcess()
|
|
41065
|
+
);
|
|
41066
|
+
}
|
|
40927
41067
|
return {
|
|
40928
41068
|
sessionId: options2.sessionId,
|
|
40929
|
-
prepared
|
|
41069
|
+
prepared
|
|
40930
41070
|
};
|
|
40931
41071
|
} finally {
|
|
40932
41072
|
this.#nativeOperations.delete(openedKey);
|
|
@@ -43337,6 +43477,7 @@ var readCodexFullHistory = async (agent, cwd, nativeSessionId, signal, nativeTur
|
|
|
43337
43477
|
|
|
43338
43478
|
// src/native-sessions/service.ts
|
|
43339
43479
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
43480
|
+
import { basename as basename5 } from "node:path";
|
|
43340
43481
|
|
|
43341
43482
|
// src/native-sessions/acp-history.ts
|
|
43342
43483
|
async function readAcpHistory(sessions, directories, bindingId, options, nativeSessionId) {
|
|
@@ -43477,6 +43618,64 @@ var NativeSessionService = class {
|
|
|
43477
43618
|
sessionId: command.sessionId
|
|
43478
43619
|
};
|
|
43479
43620
|
}
|
|
43621
|
+
if (command.action === "fork-recorded") {
|
|
43622
|
+
const source = this.#sessions.findSessions([command.sessionId])[0];
|
|
43623
|
+
if (source === void 0 || !source.prompted) {
|
|
43624
|
+
throw new AcpExecutionError(
|
|
43625
|
+
"The source conversation has no resumable native Agent session",
|
|
43626
|
+
{},
|
|
43627
|
+
"native_session_not_found"
|
|
43628
|
+
);
|
|
43629
|
+
}
|
|
43630
|
+
if (source.agentId !== command.agentId || source.cwd !== cwd || source.additionalDirectories.length !== additionalDirectories.length || source.additionalDirectories.some((path3, index) => path3 !== additionalDirectories[index])) {
|
|
43631
|
+
throw new AcpExecutionError(
|
|
43632
|
+
"The source conversation execution target does not match the fork request",
|
|
43633
|
+
{},
|
|
43634
|
+
"native_session_target_changed"
|
|
43635
|
+
);
|
|
43636
|
+
}
|
|
43637
|
+
if (source.lastTerminalCommandId !== command.throughCommandId) {
|
|
43638
|
+
throw new AcpExecutionError(
|
|
43639
|
+
"The selected Turn is no longer the source conversation head",
|
|
43640
|
+
{},
|
|
43641
|
+
"fork_point_stale"
|
|
43642
|
+
);
|
|
43643
|
+
}
|
|
43644
|
+
const opened2 = await this.#sessions.openNativeSession(
|
|
43645
|
+
{ ...options, sessionId: command.targetSessionId },
|
|
43646
|
+
{ kind: "fork", nativeSessionId: source.nativeSessionId }
|
|
43647
|
+
);
|
|
43648
|
+
signal.throwIfAborted();
|
|
43649
|
+
const directory = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
|
|
43650
|
+
const ready2 = {
|
|
43651
|
+
additionalDirectories: additionalDirectories.map((path3, index) => ({
|
|
43652
|
+
directoryId: command.additionalDirectoryIds[index] ?? command.directoryId,
|
|
43653
|
+
name: basename5(path3) || path3
|
|
43654
|
+
})),
|
|
43655
|
+
agentId: command.agentId,
|
|
43656
|
+
agentName: opened2.prepared.agentName,
|
|
43657
|
+
agentVersion: opened2.prepared.agentVersion,
|
|
43658
|
+
capabilities: opened2.prepared.capabilities,
|
|
43659
|
+
commands: opened2.prepared.commands,
|
|
43660
|
+
configOptions: opened2.prepared.configOptions,
|
|
43661
|
+
directoryId: command.directoryId,
|
|
43662
|
+
directoryLabel: directory.directoryLabel,
|
|
43663
|
+
kind: "session.ready",
|
|
43664
|
+
requestId: command.requestId,
|
|
43665
|
+
restored: true,
|
|
43666
|
+
sessionId: opened2.sessionId
|
|
43667
|
+
};
|
|
43668
|
+
this.record(command, "native_recorded_session_forked");
|
|
43669
|
+
return {
|
|
43670
|
+
action: "fork-recorded",
|
|
43671
|
+
kind: "native.session.result",
|
|
43672
|
+
ready: ready2,
|
|
43673
|
+
requestId: command.requestId,
|
|
43674
|
+
sessionId: command.sessionId,
|
|
43675
|
+
targetSessionId: command.targetSessionId,
|
|
43676
|
+
title: source.title || "Untitled session"
|
|
43677
|
+
};
|
|
43678
|
+
}
|
|
43480
43679
|
const prepared = await this.#sessions.prepareNativeSessionBrowser(options);
|
|
43481
43680
|
if (!prepared.capabilities.listSessions) {
|
|
43482
43681
|
throw new AcpExecutionError(
|
|
@@ -44798,7 +44997,7 @@ function createAgentSettingsDiscoveryHandler(dependencies) {
|
|
|
44798
44997
|
// src/artifacts/local-file-streamer.ts
|
|
44799
44998
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
44800
44999
|
import { realpath as realpath9, stat as stat8 } from "node:fs/promises";
|
|
44801
|
-
import { basename as
|
|
45000
|
+
import { basename as basename6, isAbsolute as isAbsolute10, normalize as normalize4, resolve as resolve7 } from "node:path";
|
|
44802
45001
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
44803
45002
|
var CHUNK_BYTES = 192 * 1024;
|
|
44804
45003
|
function requestedPath(value) {
|
|
@@ -44849,7 +45048,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
|
|
|
44849
45048
|
kind: FILE_BEGIN_KIND,
|
|
44850
45049
|
mediaType: raster?.mimeType ?? "application/octet-stream",
|
|
44851
45050
|
modifiedAt: before.mtime.toISOString(),
|
|
44852
|
-
name:
|
|
45051
|
+
name: basename6(target) || "file",
|
|
44853
45052
|
requestId: command.requestId,
|
|
44854
45053
|
sessionId: command.sessionId
|
|
44855
45054
|
});
|
|
@@ -44879,7 +45078,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
|
|
|
44879
45078
|
}
|
|
44880
45079
|
|
|
44881
45080
|
// src/authorization/resolve-session-directories.ts
|
|
44882
|
-
import { basename as
|
|
45081
|
+
import { basename as basename7 } from "node:path";
|
|
44883
45082
|
var ResolvedSessionDirectories = class {
|
|
44884
45083
|
additionalDirectories;
|
|
44885
45084
|
additionalDirectoryEntries;
|
|
@@ -44904,7 +45103,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
|
|
|
44904
45103
|
additionalDirectories.push(directory);
|
|
44905
45104
|
additionalDirectoryEntries.push({
|
|
44906
45105
|
directoryId: additionalDirectoryId,
|
|
44907
|
-
name:
|
|
45106
|
+
name: basename7(directory)
|
|
44908
45107
|
});
|
|
44909
45108
|
}
|
|
44910
45109
|
return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
|
|
@@ -45641,14 +45840,15 @@ async function executePrompt({
|
|
|
45641
45840
|
const appliedSettings = command.sessionConfigurations === void 0 ? void 0 : agentForSessionConfiguration(agent, command.sessionConfigurations);
|
|
45642
45841
|
const executionAgent = appliedSettings?.agent ?? agent;
|
|
45643
45842
|
const sessionConfigurations = appliedSettings?.sessionConfigurations;
|
|
45843
|
+
const preparation = {
|
|
45844
|
+
additionalDirectories: resolved.additionalDirectories,
|
|
45845
|
+
agent: executionAgent,
|
|
45846
|
+
cwd: resolved.cwd,
|
|
45847
|
+
sessionId: command.sessionId,
|
|
45848
|
+
signal
|
|
45849
|
+
};
|
|
45850
|
+
let prepared = await sessions.prepareExecutionSession(preparation);
|
|
45644
45851
|
if (command.sessionConfigurations !== void 0) {
|
|
45645
|
-
const prepared = await sessions.prepareExecutionSession({
|
|
45646
|
-
additionalDirectories: resolved.additionalDirectories,
|
|
45647
|
-
agent: executionAgent,
|
|
45648
|
-
cwd: resolved.cwd,
|
|
45649
|
-
sessionId: command.sessionId,
|
|
45650
|
-
signal
|
|
45651
|
-
});
|
|
45652
45852
|
if (availability.disposition === SessionPromptDisposition.Steer) {
|
|
45653
45853
|
assertAppliedSessionConfiguration(prepared.configOptions, sessionConfigurations ?? []);
|
|
45654
45854
|
} else {
|
|
@@ -45664,6 +45864,7 @@ async function executePrompt({
|
|
|
45664
45864
|
command.sessionId,
|
|
45665
45865
|
signal
|
|
45666
45866
|
);
|
|
45867
|
+
prepared = await sessions.prepareExecutionSession(preparation);
|
|
45667
45868
|
}
|
|
45668
45869
|
}
|
|
45669
45870
|
audit.record({
|
|
@@ -45682,6 +45883,24 @@ async function executePrompt({
|
|
|
45682
45883
|
}
|
|
45683
45884
|
}
|
|
45684
45885
|
const stream = activateAttempt();
|
|
45886
|
+
if (!prepared.prompted) {
|
|
45887
|
+
const listing = await directories.list(config2.bindingId, command.directoryId, signal);
|
|
45888
|
+
publisher.publish(command.sessionId, {
|
|
45889
|
+
additionalDirectories: resolved.additionalDirectoryEntries,
|
|
45890
|
+
agentId: command.agentId,
|
|
45891
|
+
agentName: prepared.agentName,
|
|
45892
|
+
agentVersion: prepared.agentVersion,
|
|
45893
|
+
capabilities: prepared.capabilities,
|
|
45894
|
+
commands: prepared.commands,
|
|
45895
|
+
configOptions: prepared.configOptions,
|
|
45896
|
+
directoryId: command.directoryId,
|
|
45897
|
+
directoryLabel: listing.directoryLabel,
|
|
45898
|
+
kind: SESSION_READY_KIND,
|
|
45899
|
+
requestId: command.commandId,
|
|
45900
|
+
restored: prepared.restored,
|
|
45901
|
+
sessionId: command.sessionId
|
|
45902
|
+
});
|
|
45903
|
+
}
|
|
45685
45904
|
publisher.publish(command.sessionId, {
|
|
45686
45905
|
commandId: command.commandId,
|
|
45687
45906
|
epoch: stream.epoch,
|
|
@@ -45935,7 +46154,7 @@ async function executeSessionConfigure(publisher, socket, command, config2, dire
|
|
|
45935
46154
|
// src/native-sessions/handle-native-requests.ts
|
|
45936
46155
|
import { WebSocket as WebSocket5 } from "undici";
|
|
45937
46156
|
function createNativeSessionRequestHandler(dependencies) {
|
|
45938
|
-
const { audit, diagnostics, nativeSessions, signal, socket, timer } = dependencies;
|
|
46157
|
+
const { audit, diagnostics, nativeSessions, publisher, signal, socket, timer } = dependencies;
|
|
45939
46158
|
const pending = /* @__PURE__ */ new Map();
|
|
45940
46159
|
const cancel = (command) => {
|
|
45941
46160
|
const request = pending.get(command.requestId);
|
|
@@ -45987,6 +46206,17 @@ function createNativeSessionRequestHandler(dependencies) {
|
|
|
45987
46206
|
}
|
|
45988
46207
|
operationSignal.throwIfAborted();
|
|
45989
46208
|
const result = await nativeSessions.execute(command, operationSignal);
|
|
46209
|
+
if (command.action === "fork-recorded" && result.action === "fork-recorded") {
|
|
46210
|
+
publisher.publishBatch(result.ready.sessionId, [
|
|
46211
|
+
result.ready,
|
|
46212
|
+
{
|
|
46213
|
+
kind: "session.forked",
|
|
46214
|
+
sessionId: result.ready.sessionId,
|
|
46215
|
+
sourceSessionId: command.sessionId,
|
|
46216
|
+
throughCommandId: command.throughCommandId
|
|
46217
|
+
}
|
|
46218
|
+
]);
|
|
46219
|
+
}
|
|
45990
46220
|
if (socket.readyState === WebSocket5.OPEN) {
|
|
45991
46221
|
send(socket, result);
|
|
45992
46222
|
}
|
|
@@ -46072,6 +46302,7 @@ function createDaemonCommandHandler({
|
|
|
46072
46302
|
audit,
|
|
46073
46303
|
diagnostics,
|
|
46074
46304
|
nativeSessions,
|
|
46305
|
+
publisher,
|
|
46075
46306
|
signal,
|
|
46076
46307
|
socket,
|
|
46077
46308
|
timer
|
|
@@ -46594,6 +46825,7 @@ async function runRelayConnection({
|
|
|
46594
46825
|
}) {
|
|
46595
46826
|
const relayUrl = new URL(config2.relayUrl);
|
|
46596
46827
|
relayUrl.searchParams.set("liveness", "1");
|
|
46828
|
+
relayUrl.searchParams.set("sessionEventDelivery", "reliable-v1");
|
|
46597
46829
|
const socket = await connectRelay(relayUrl, signal);
|
|
46598
46830
|
diagnostics.connectionOpened(connectionEpoch);
|
|
46599
46831
|
const connectionController = new AbortController();
|
|
@@ -46713,6 +46945,10 @@ async function runRelayConnection({
|
|
|
46713
46945
|
const message = decodeServiceToDaemonMessage(encoded);
|
|
46714
46946
|
const kind = message.kind;
|
|
46715
46947
|
if (kind === RUNTIME_LIVENESS_READY_KIND) {
|
|
46948
|
+
publisher.connect(
|
|
46949
|
+
socket,
|
|
46950
|
+
message.sessionEventDelivery === "reliable-v1" ? "reliable" : "ephemeral"
|
|
46951
|
+
);
|
|
46716
46952
|
connectionLiveness.start();
|
|
46717
46953
|
return;
|
|
46718
46954
|
}
|
|
@@ -46720,6 +46956,18 @@ async function runRelayConnection({
|
|
|
46720
46956
|
connectionLiveness.acknowledge(message);
|
|
46721
46957
|
return;
|
|
46722
46958
|
}
|
|
46959
|
+
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
46960
|
+
publisher.acknowledge(message);
|
|
46961
|
+
return;
|
|
46962
|
+
}
|
|
46963
|
+
if (kind === SESSION_EVENT_DEFERRED_KIND) {
|
|
46964
|
+
publisher.defer(message);
|
|
46965
|
+
return;
|
|
46966
|
+
}
|
|
46967
|
+
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
46968
|
+
publisher.quarantine(message);
|
|
46969
|
+
return;
|
|
46970
|
+
}
|
|
46723
46971
|
commands.handle(message);
|
|
46724
46972
|
} catch (error62) {
|
|
46725
46973
|
console.error("Mobius daemon rejected a message", error62);
|
|
@@ -46734,7 +46982,6 @@ async function runRelayConnection({
|
|
|
46734
46982
|
socket.addEventListener("close", handleClose);
|
|
46735
46983
|
socket.addEventListener("error", handleError);
|
|
46736
46984
|
socket.addEventListener("message", handleMessage);
|
|
46737
|
-
publisher.connect(socket);
|
|
46738
46985
|
if (signal.aborted) {
|
|
46739
46986
|
stop();
|
|
46740
46987
|
}
|
|
@@ -46745,54 +46992,405 @@ async function runRelayConnection({
|
|
|
46745
46992
|
}
|
|
46746
46993
|
}
|
|
46747
46994
|
|
|
46995
|
+
// src/relay-connection/session-event-outbox.ts
|
|
46996
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
46997
|
+
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
46998
|
+
import { dirname as dirname6 } from "node:path";
|
|
46999
|
+
import { DatabaseSync } from "node:sqlite";
|
|
47000
|
+
var DEFAULT_STANDARD_EVENT_BYTES = 96 * 1024 * 1024;
|
|
47001
|
+
var DEFAULT_CRITICAL_EVENT_BYTES = 128 * 1024 * 1024;
|
|
47002
|
+
var MAX_DEAD_LETTERS = 1024;
|
|
47003
|
+
var DEFAULT_LIMITS = {
|
|
47004
|
+
criticalEventBytes: DEFAULT_CRITICAL_EVENT_BYTES,
|
|
47005
|
+
standardEventBytes: DEFAULT_STANDARD_EVENT_BYTES
|
|
47006
|
+
};
|
|
47007
|
+
var SessionEventOutboxCapacityError = class extends Error {
|
|
47008
|
+
code = "session_event_outbox_full";
|
|
47009
|
+
constructor() {
|
|
47010
|
+
super("The persistent Session event outbox is full");
|
|
47011
|
+
this.name = "SessionEventOutboxCapacityError";
|
|
47012
|
+
}
|
|
47013
|
+
};
|
|
47014
|
+
function rowNumber(row, field) {
|
|
47015
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
47016
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
47017
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
47018
|
+
}
|
|
47019
|
+
return value;
|
|
47020
|
+
}
|
|
47021
|
+
function rowString(row, field) {
|
|
47022
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
47023
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
47024
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
47025
|
+
}
|
|
47026
|
+
return value;
|
|
47027
|
+
}
|
|
47028
|
+
function validateLimits(limits) {
|
|
47029
|
+
if (!Number.isSafeInteger(limits.standardEventBytes) || limits.standardEventBytes < 1 || !Number.isSafeInteger(limits.criticalEventBytes) || limits.criticalEventBytes < limits.standardEventBytes) {
|
|
47030
|
+
throw new Error("Session event outbox limits are invalid");
|
|
47031
|
+
}
|
|
47032
|
+
}
|
|
47033
|
+
var SessionEventOutbox = class {
|
|
47034
|
+
#database;
|
|
47035
|
+
#limits;
|
|
47036
|
+
constructor(path3, limits = DEFAULT_LIMITS) {
|
|
47037
|
+
validateLimits(limits);
|
|
47038
|
+
mkdirSync3(dirname6(path3), { mode: 448, recursive: true });
|
|
47039
|
+
this.#limits = limits;
|
|
47040
|
+
this.#database = new DatabaseSync(path3);
|
|
47041
|
+
this.#database.exec("PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL; PRAGMA busy_timeout = 5000;");
|
|
47042
|
+
this.#database.exec(`
|
|
47043
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
|
|
47044
|
+
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47045
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
47046
|
+
session_id TEXT NOT NULL,
|
|
47047
|
+
source_seq INTEGER NOT NULL UNIQUE,
|
|
47048
|
+
byte_length INTEGER NOT NULL,
|
|
47049
|
+
envelope_json TEXT NOT NULL
|
|
47050
|
+
) STRICT;
|
|
47051
|
+
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
47052
|
+
ON relay_session_event_outbox(source_seq);
|
|
47053
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
47054
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
47055
|
+
stream_id TEXT NOT NULL,
|
|
47056
|
+
next_source_seq INTEGER NOT NULL,
|
|
47057
|
+
total_bytes INTEGER NOT NULL
|
|
47058
|
+
) STRICT;
|
|
47059
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_dead_letters (
|
|
47060
|
+
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47061
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
47062
|
+
session_id TEXT NOT NULL,
|
|
47063
|
+
rejection_code TEXT NOT NULL,
|
|
47064
|
+
envelope_json TEXT NOT NULL
|
|
47065
|
+
) STRICT;
|
|
47066
|
+
`);
|
|
47067
|
+
this.#database.prepare(
|
|
47068
|
+
`INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
47069
|
+
singleton, stream_id, next_source_seq, total_bytes
|
|
47070
|
+
) VALUES (1, ?, 1, 0)`
|
|
47071
|
+
).run(randomUUID7());
|
|
47072
|
+
}
|
|
47073
|
+
acknowledge = (acknowledgement) => this.#remove(acknowledgement.eventId, acknowledgement.sessionId);
|
|
47074
|
+
close = () => {
|
|
47075
|
+
this.#database.close();
|
|
47076
|
+
};
|
|
47077
|
+
enqueue = (sessionId, payload, critical) => {
|
|
47078
|
+
const envelope2 = this.enqueueBatch(sessionId, [payload], critical)[0];
|
|
47079
|
+
if (envelope2 === void 0) {
|
|
47080
|
+
throw new Error("The Session event outbox did not enqueue the event");
|
|
47081
|
+
}
|
|
47082
|
+
return envelope2;
|
|
47083
|
+
};
|
|
47084
|
+
enqueueBatch = (sessionId, payloads, critical) => {
|
|
47085
|
+
if (payloads.length < 1 || payloads.length > 32) {
|
|
47086
|
+
throw new Error("A Session event batch must contain between 1 and 32 events");
|
|
47087
|
+
}
|
|
47088
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
47089
|
+
try {
|
|
47090
|
+
const state = this.#database.prepare(
|
|
47091
|
+
`SELECT stream_id, next_source_seq, total_bytes
|
|
47092
|
+
FROM relay_session_event_outbox_state
|
|
47093
|
+
WHERE singleton = 1`
|
|
47094
|
+
).get();
|
|
47095
|
+
const sourceSeq = rowNumber(state, "next_source_seq");
|
|
47096
|
+
if (sourceSeq < 1 || !Number.isSafeInteger(sourceSeq + payloads.length)) {
|
|
47097
|
+
throw new Error("The Session event source sequence is exhausted");
|
|
47098
|
+
}
|
|
47099
|
+
const streamId = rowString(state, "stream_id");
|
|
47100
|
+
const stored = payloads.map((payload, index) => {
|
|
47101
|
+
const envelope2 = {
|
|
47102
|
+
delivery: {
|
|
47103
|
+
eventId: randomUUID7(),
|
|
47104
|
+
kind: "reliable",
|
|
47105
|
+
sourceSeq: (sourceSeq + index).toString(),
|
|
47106
|
+
streamId
|
|
47107
|
+
},
|
|
47108
|
+
kind: SESSION_EVENT_KIND,
|
|
47109
|
+
payload,
|
|
47110
|
+
sessionId
|
|
47111
|
+
};
|
|
47112
|
+
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
47113
|
+
return { byteLength: Buffer.byteLength(encoded, "utf8"), encoded, envelope: envelope2 };
|
|
47114
|
+
});
|
|
47115
|
+
const byteLength = stored.reduce((total, entry) => total + entry.byteLength, 0);
|
|
47116
|
+
const maximumBytes = critical ? this.#limits.criticalEventBytes : this.#limits.standardEventBytes;
|
|
47117
|
+
if (rowNumber(state, "total_bytes") + byteLength > maximumBytes) {
|
|
47118
|
+
throw new SessionEventOutboxCapacityError();
|
|
47119
|
+
}
|
|
47120
|
+
const insert = this.#database.prepare(
|
|
47121
|
+
`INSERT INTO relay_session_event_outbox (
|
|
47122
|
+
event_id, session_id, source_seq, byte_length, envelope_json
|
|
47123
|
+
) VALUES (?, ?, ?, ?, ?)`
|
|
47124
|
+
);
|
|
47125
|
+
for (const entry of stored) {
|
|
47126
|
+
insert.run(
|
|
47127
|
+
entry.envelope.delivery.eventId,
|
|
47128
|
+
sessionId,
|
|
47129
|
+
Number(entry.envelope.delivery.sourceSeq),
|
|
47130
|
+
entry.byteLength,
|
|
47131
|
+
entry.encoded
|
|
47132
|
+
);
|
|
47133
|
+
}
|
|
47134
|
+
this.#database.prepare(
|
|
47135
|
+
`UPDATE relay_session_event_outbox_state
|
|
47136
|
+
SET next_source_seq = next_source_seq + ?,
|
|
47137
|
+
total_bytes = total_bytes + ?
|
|
47138
|
+
WHERE singleton = 1`
|
|
47139
|
+
).run(stored.length, byteLength);
|
|
47140
|
+
this.#database.exec("COMMIT");
|
|
47141
|
+
return stored.map((entry) => entry.envelope);
|
|
47142
|
+
} catch (error62) {
|
|
47143
|
+
this.#database.exec("ROLLBACK");
|
|
47144
|
+
throw error62;
|
|
47145
|
+
}
|
|
47146
|
+
};
|
|
47147
|
+
pending = (limit, excludedEventIds) => {
|
|
47148
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
47149
|
+
throw new Error("Session event replay limit must be a positive integer");
|
|
47150
|
+
}
|
|
47151
|
+
const exclusion = excludedEventIds.length === 0 ? "" : `WHERE event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`;
|
|
47152
|
+
return this.#database.prepare(
|
|
47153
|
+
`SELECT envelope_json
|
|
47154
|
+
FROM relay_session_event_outbox
|
|
47155
|
+
${exclusion}
|
|
47156
|
+
ORDER BY source_seq
|
|
47157
|
+
LIMIT ?`
|
|
47158
|
+
).all(...excludedEventIds, limit).map((row) => {
|
|
47159
|
+
const envelope2 = decodeSessionEventEnvelope(rowString(row, "envelope_json"));
|
|
47160
|
+
if (!("delivery" in envelope2)) {
|
|
47161
|
+
throw new Error("SQLite returned an invalid reliable Session event envelope");
|
|
47162
|
+
}
|
|
47163
|
+
return envelope2;
|
|
47164
|
+
});
|
|
47165
|
+
};
|
|
47166
|
+
quarantine = (rejection) => {
|
|
47167
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
47168
|
+
try {
|
|
47169
|
+
const stored = this.#database.prepare(
|
|
47170
|
+
`SELECT byte_length, envelope_json
|
|
47171
|
+
FROM relay_session_event_outbox
|
|
47172
|
+
WHERE event_id = ? AND session_id = ?`
|
|
47173
|
+
).get(rejection.eventId, rejection.sessionId);
|
|
47174
|
+
if (stored === void 0) {
|
|
47175
|
+
this.#database.exec("COMMIT");
|
|
47176
|
+
return false;
|
|
47177
|
+
}
|
|
47178
|
+
this.#database.prepare(
|
|
47179
|
+
`INSERT INTO relay_session_event_dead_letters (
|
|
47180
|
+
event_id, session_id, rejection_code, envelope_json
|
|
47181
|
+
) VALUES (?, ?, ?, ?)`
|
|
47182
|
+
).run(rejection.eventId, rejection.sessionId, rejection.code, rowString(stored, "envelope_json"));
|
|
47183
|
+
this.#deleteStored(rejection.eventId, rejection.sessionId, rowNumber(stored, "byte_length"));
|
|
47184
|
+
this.#database.prepare(
|
|
47185
|
+
`DELETE FROM relay_session_event_dead_letters
|
|
47186
|
+
WHERE ordinal NOT IN (
|
|
47187
|
+
SELECT ordinal FROM relay_session_event_dead_letters
|
|
47188
|
+
ORDER BY ordinal DESC LIMIT ?
|
|
47189
|
+
)`
|
|
47190
|
+
).run(MAX_DEAD_LETTERS);
|
|
47191
|
+
this.#database.exec("COMMIT");
|
|
47192
|
+
return true;
|
|
47193
|
+
} catch (error62) {
|
|
47194
|
+
this.#database.exec("ROLLBACK");
|
|
47195
|
+
throw error62;
|
|
47196
|
+
}
|
|
47197
|
+
};
|
|
47198
|
+
#deleteStored = (eventId, sessionId, byteLength) => {
|
|
47199
|
+
const deletion = this.#database.prepare(
|
|
47200
|
+
`DELETE FROM relay_session_event_outbox
|
|
47201
|
+
WHERE event_id = ? AND session_id = ?`
|
|
47202
|
+
).run(eventId, sessionId);
|
|
47203
|
+
if (deletion.changes !== 1) {
|
|
47204
|
+
throw new Error("The Session event could not be removed from the outbox");
|
|
47205
|
+
}
|
|
47206
|
+
const state = this.#database.prepare(
|
|
47207
|
+
`UPDATE relay_session_event_outbox_state
|
|
47208
|
+
SET total_bytes = total_bytes - ?
|
|
47209
|
+
WHERE singleton = 1 AND total_bytes >= ?`
|
|
47210
|
+
).run(byteLength, byteLength);
|
|
47211
|
+
if (state.changes !== 1) {
|
|
47212
|
+
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
47213
|
+
}
|
|
47214
|
+
};
|
|
47215
|
+
#remove = (eventId, sessionId) => {
|
|
47216
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
47217
|
+
try {
|
|
47218
|
+
const stored = this.#database.prepare(
|
|
47219
|
+
`SELECT byte_length
|
|
47220
|
+
FROM relay_session_event_outbox
|
|
47221
|
+
WHERE event_id = ? AND session_id = ?`
|
|
47222
|
+
).get(eventId, sessionId);
|
|
47223
|
+
if (stored === void 0) {
|
|
47224
|
+
this.#database.exec("COMMIT");
|
|
47225
|
+
return false;
|
|
47226
|
+
}
|
|
47227
|
+
this.#deleteStored(eventId, sessionId, rowNumber(stored, "byte_length"));
|
|
47228
|
+
this.#database.exec("COMMIT");
|
|
47229
|
+
return true;
|
|
47230
|
+
} catch (error62) {
|
|
47231
|
+
this.#database.exec("ROLLBACK");
|
|
47232
|
+
throw error62;
|
|
47233
|
+
}
|
|
47234
|
+
};
|
|
47235
|
+
};
|
|
47236
|
+
|
|
46748
47237
|
// src/relay-connection/session-event-publisher.ts
|
|
46749
47238
|
import { WebSocket as WebSocket9 } from "undici";
|
|
46750
|
-
var
|
|
47239
|
+
var SESSION_EVENT_REPLAY_WINDOW = 16;
|
|
47240
|
+
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
47241
|
+
function reservesSessionEventCapacity(event) {
|
|
47242
|
+
if (event.kind === SESSION_COMPLETED_KIND || event.kind === SESSION_FAILED_KIND || event.kind === SESSION_FORKED_KIND || event.kind === SESSION_READY_KIND) {
|
|
47243
|
+
return true;
|
|
47244
|
+
}
|
|
47245
|
+
return event.kind === AGENT_ACTIVITY_KIND && (event.activityType === "progress" || event.activityType === "reasoning") && (event.status === "completed" || event.status === "failed");
|
|
47246
|
+
}
|
|
46751
47247
|
var DaemonSessionEventPublisher = class {
|
|
46752
|
-
#
|
|
46753
|
-
#
|
|
46754
|
-
|
|
46755
|
-
|
|
46756
|
-
|
|
47248
|
+
#inFlight = /* @__PURE__ */ new Map();
|
|
47249
|
+
#outbox;
|
|
47250
|
+
#reportedCapacityKinds = /* @__PURE__ */ new Set();
|
|
47251
|
+
#timer;
|
|
47252
|
+
#connection = { kind: "disconnected" };
|
|
47253
|
+
#deferredReplay = null;
|
|
47254
|
+
#inFlightBytes = 0;
|
|
47255
|
+
constructor(outbox, timer) {
|
|
47256
|
+
this.#outbox = outbox;
|
|
47257
|
+
this.#timer = timer;
|
|
47258
|
+
}
|
|
47259
|
+
acknowledge = (acknowledgement) => {
|
|
47260
|
+
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
47261
|
+
return;
|
|
47262
|
+
}
|
|
47263
|
+
this.#removeInFlight(acknowledgement.eventId);
|
|
47264
|
+
this.#publishNextBatch();
|
|
47265
|
+
};
|
|
47266
|
+
close = () => {
|
|
47267
|
+
this.#deferredReplay?.cancel();
|
|
47268
|
+
this.#deferredReplay = null;
|
|
47269
|
+
this.#connection = { kind: "disconnected" };
|
|
47270
|
+
this.#clearInFlight();
|
|
47271
|
+
this.#outbox.close();
|
|
47272
|
+
};
|
|
47273
|
+
connect = (socket, delivery) => {
|
|
47274
|
+
this.#connection = { delivery, kind: "connected", socket };
|
|
47275
|
+
this.#clearInFlight();
|
|
47276
|
+
this.#publishNextBatch();
|
|
47277
|
+
};
|
|
47278
|
+
defer = (deferred) => {
|
|
47279
|
+
if (!this.#inFlight.has(deferred.eventId)) {
|
|
47280
|
+
return;
|
|
47281
|
+
}
|
|
47282
|
+
this.#clearInFlight();
|
|
47283
|
+
if (this.#deferredReplay !== null) {
|
|
47284
|
+
return;
|
|
47285
|
+
}
|
|
47286
|
+
this.#deferredReplay = this.#timer.schedule(() => {
|
|
47287
|
+
this.#deferredReplay = null;
|
|
47288
|
+
this.#publishNextBatch();
|
|
47289
|
+
}, deferred.retryAfterMilliseconds);
|
|
46757
47290
|
};
|
|
46758
47291
|
disconnect = (socket) => {
|
|
46759
|
-
if (this.#socket
|
|
46760
|
-
|
|
47292
|
+
if (this.#connection.kind !== "connected" || this.#connection.socket !== socket) {
|
|
47293
|
+
return;
|
|
46761
47294
|
}
|
|
47295
|
+
this.#connection = { kind: "disconnected" };
|
|
47296
|
+
this.#clearInFlight();
|
|
46762
47297
|
};
|
|
46763
47298
|
publish = (sessionId, event) => {
|
|
46764
|
-
|
|
46765
|
-
|
|
46766
|
-
|
|
47299
|
+
try {
|
|
47300
|
+
this.#outbox.enqueue(sessionId, encodeRecordedSessionEvent(event), reservesSessionEventCapacity(event));
|
|
47301
|
+
} catch (error62) {
|
|
47302
|
+
if (!(error62 instanceof SessionEventOutboxCapacityError)) {
|
|
47303
|
+
throw error62;
|
|
47304
|
+
}
|
|
47305
|
+
if (!this.#reportedCapacityKinds.has(event.kind)) {
|
|
47306
|
+
this.#reportedCapacityKinds.add(event.kind);
|
|
47307
|
+
console.warn(
|
|
47308
|
+
`Mobius daemon could not persist "${event.kind}" because the Session event outbox is full`
|
|
47309
|
+
);
|
|
47310
|
+
}
|
|
46767
47311
|
return;
|
|
46768
47312
|
}
|
|
46769
|
-
|
|
46770
|
-
|
|
46771
|
-
|
|
46772
|
-
|
|
47313
|
+
this.#publishNextBatch();
|
|
47314
|
+
};
|
|
47315
|
+
publishBatch = (sessionId, events) => {
|
|
47316
|
+
const critical = events.some(reservesSessionEventCapacity);
|
|
47317
|
+
this.#outbox.enqueueBatch(sessionId, events.map(encodeRecordedSessionEvent), critical);
|
|
47318
|
+
this.#publishNextBatch();
|
|
47319
|
+
};
|
|
47320
|
+
quarantine = (rejection) => {
|
|
47321
|
+
if (!this.#outbox.quarantine(rejection)) {
|
|
46773
47322
|
return;
|
|
46774
47323
|
}
|
|
46775
|
-
|
|
46776
|
-
|
|
46777
|
-
|
|
46778
|
-
kind: SESSION_EVENT_KIND,
|
|
46779
|
-
payload: encodeRecordedSessionEvent(event),
|
|
46780
|
-
sessionId
|
|
46781
|
-
})
|
|
46782
|
-
);
|
|
46783
|
-
} catch {
|
|
46784
|
-
this.#reportDrop();
|
|
46785
|
-
}
|
|
47324
|
+
this.#removeInFlight(rejection.eventId);
|
|
47325
|
+
console.error(`Mobius Relay rejected Session event ${rejection.eventId} with code ${rejection.code}`);
|
|
47326
|
+
this.#publishNextBatch();
|
|
46786
47327
|
};
|
|
46787
|
-
|
|
46788
|
-
this.#
|
|
47328
|
+
#clearInFlight = () => {
|
|
47329
|
+
this.#inFlight.clear();
|
|
47330
|
+
this.#inFlightBytes = 0;
|
|
47331
|
+
};
|
|
47332
|
+
#publishNextBatch = () => {
|
|
47333
|
+
if (this.#deferredReplay !== null || this.#connection.kind !== "connected") {
|
|
47334
|
+
return;
|
|
47335
|
+
}
|
|
47336
|
+
while (this.#inFlight.size < SESSION_EVENT_REPLAY_WINDOW) {
|
|
47337
|
+
const batch = this.#outbox.pending(SESSION_EVENT_REPLAY_WINDOW - this.#inFlight.size, [
|
|
47338
|
+
...this.#inFlight.keys()
|
|
47339
|
+
]);
|
|
47340
|
+
let sent = 0;
|
|
47341
|
+
for (const envelope2 of batch) {
|
|
47342
|
+
const encoded = encodeDaemonToServiceMessage(
|
|
47343
|
+
this.#connection.delivery === "reliable" ? envelope2 : {
|
|
47344
|
+
kind: envelope2.kind,
|
|
47345
|
+
payload: envelope2.payload,
|
|
47346
|
+
sessionId: envelope2.sessionId
|
|
47347
|
+
}
|
|
47348
|
+
);
|
|
47349
|
+
const byteLength = Buffer.byteLength(encoded, "utf8");
|
|
47350
|
+
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
47351
|
+
return;
|
|
47352
|
+
}
|
|
47353
|
+
if (!this.#send(encoded)) {
|
|
47354
|
+
this.#clearInFlight();
|
|
47355
|
+
return;
|
|
47356
|
+
}
|
|
47357
|
+
if (this.#connection.delivery === "ephemeral") {
|
|
47358
|
+
this.#outbox.acknowledge({
|
|
47359
|
+
eventId: envelope2.delivery.eventId,
|
|
47360
|
+
kind: "session.event.ack",
|
|
47361
|
+
outcome: { kind: "relayed" },
|
|
47362
|
+
sessionId: envelope2.sessionId
|
|
47363
|
+
});
|
|
47364
|
+
sent += 1;
|
|
47365
|
+
continue;
|
|
47366
|
+
}
|
|
47367
|
+
this.#inFlight.set(envelope2.delivery.eventId, { byteLength });
|
|
47368
|
+
this.#inFlightBytes += byteLength;
|
|
47369
|
+
sent += 1;
|
|
47370
|
+
}
|
|
47371
|
+
if (sent === 0) {
|
|
47372
|
+
return;
|
|
47373
|
+
}
|
|
47374
|
+
}
|
|
46789
47375
|
};
|
|
46790
|
-
#
|
|
46791
|
-
|
|
47376
|
+
#removeInFlight = (eventId) => {
|
|
47377
|
+
const inFlight = this.#inFlight.get(eventId);
|
|
47378
|
+
if (inFlight === void 0) {
|
|
46792
47379
|
return;
|
|
46793
47380
|
}
|
|
46794
|
-
this.#
|
|
46795
|
-
|
|
47381
|
+
this.#inFlight.delete(eventId);
|
|
47382
|
+
this.#inFlightBytes -= inFlight.byteLength;
|
|
47383
|
+
};
|
|
47384
|
+
#send = (encoded) => {
|
|
47385
|
+
if (this.#connection.kind !== "connected" || this.#connection.socket.readyState !== WebSocket9.OPEN) {
|
|
47386
|
+
return false;
|
|
47387
|
+
}
|
|
47388
|
+
try {
|
|
47389
|
+
this.#connection.socket.send(encoded);
|
|
47390
|
+
return true;
|
|
47391
|
+
} catch {
|
|
47392
|
+
return false;
|
|
47393
|
+
}
|
|
46796
47394
|
};
|
|
46797
47395
|
};
|
|
46798
47396
|
|
|
@@ -46853,7 +47451,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
|
|
|
46853
47451
|
{
|
|
46854
47452
|
agentId: agent.id,
|
|
46855
47453
|
kind: AGENT_INSTALL_REQUEST_KIND,
|
|
46856
|
-
requestId: `automatic-integration-${
|
|
47454
|
+
requestId: `automatic-integration-${randomUUID8()}`
|
|
46857
47455
|
},
|
|
46858
47456
|
signal
|
|
46859
47457
|
);
|
|
@@ -46875,7 +47473,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
46875
47473
|
join18(stateDirectory, "sessions", `${createHash6("sha256").update(config2.channelId).digest("hex")}.sqlite`)
|
|
46876
47474
|
);
|
|
46877
47475
|
const operations = new DaemonOperationState();
|
|
46878
|
-
const
|
|
47476
|
+
const channelHash = createHash6("sha256").update(config2.channelId).digest("hex");
|
|
47477
|
+
const publisher = new DaemonSessionEventPublisher(
|
|
47478
|
+
new SessionEventOutbox(join18(stateDirectory, "events", `${channelHash}.sqlite`)),
|
|
47479
|
+
timer
|
|
47480
|
+
);
|
|
46879
47481
|
const activeTurns = new DaemonTurnRegistry(operations);
|
|
46880
47482
|
const recordSessionEvent = (sessionId, event) => {
|
|
46881
47483
|
publisher.publish(sessionId, activeTurns.recordEvent(event));
|