@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/index.js
CHANGED
|
@@ -20766,9 +20766,17 @@ function decodeSessionQueuedEvent(encoded) {
|
|
|
20766
20766
|
}
|
|
20767
20767
|
function decodeRuntimeLivenessReadyEvent(encoded) {
|
|
20768
20768
|
const value = parseJson2(encoded);
|
|
20769
|
-
assertExactKeys(value, ["kind"]);
|
|
20770
20769
|
assertKind(value, RUNTIME_LIVENESS_READY_KIND);
|
|
20771
|
-
|
|
20770
|
+
if (value["sessionEventDelivery"] === void 0) {
|
|
20771
|
+
assertExactKeys(value, ["kind"]);
|
|
20772
|
+
return { kind: RUNTIME_LIVENESS_READY_KIND };
|
|
20773
|
+
}
|
|
20774
|
+
assertExactKeys(value, ["kind", "sessionEventDelivery"]);
|
|
20775
|
+
const sessionEventDelivery = readString(value, "sessionEventDelivery", 32);
|
|
20776
|
+
if (sessionEventDelivery !== "reliable-v1") {
|
|
20777
|
+
throw new ProtocolMessageError("Unsupported Session event delivery mode");
|
|
20778
|
+
}
|
|
20779
|
+
return { kind: RUNTIME_LIVENESS_READY_KIND, sessionEventDelivery };
|
|
20772
20780
|
}
|
|
20773
20781
|
function decodeRuntimeHeartbeatEvent(encoded) {
|
|
20774
20782
|
const value = parseJson2(encoded);
|
|
@@ -21100,6 +21108,12 @@ var nativeSessionRequestSchema = external_exports.discriminatedUnion("action", [
|
|
|
21100
21108
|
entryId: identifierStringSchema,
|
|
21101
21109
|
targetSessionId: identifierStringSchema
|
|
21102
21110
|
}).readonly(),
|
|
21111
|
+
external_exports.strictObject({
|
|
21112
|
+
...identity,
|
|
21113
|
+
action: external_exports.literal("fork-recorded"),
|
|
21114
|
+
targetSessionId: identifierStringSchema,
|
|
21115
|
+
throughCommandId: identifierStringSchema
|
|
21116
|
+
}).readonly(),
|
|
21103
21117
|
external_exports.strictObject({
|
|
21104
21118
|
...identity,
|
|
21105
21119
|
action: external_exports.literal("delete"),
|
|
@@ -21123,6 +21137,12 @@ var nativeSessionCommandSchema = external_exports.discriminatedUnion("action", [
|
|
|
21123
21137
|
entryId: identifierStringSchema,
|
|
21124
21138
|
targetSessionId: identifierStringSchema
|
|
21125
21139
|
}).readonly(),
|
|
21140
|
+
external_exports.strictObject({
|
|
21141
|
+
...identity,
|
|
21142
|
+
action: external_exports.literal("fork-recorded"),
|
|
21143
|
+
targetSessionId: identifierStringSchema,
|
|
21144
|
+
throughCommandId: identifierStringSchema
|
|
21145
|
+
}).readonly(),
|
|
21126
21146
|
external_exports.strictObject({
|
|
21127
21147
|
...identity,
|
|
21128
21148
|
action: external_exports.literal("delete"),
|
|
@@ -21172,7 +21192,7 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
|
|
|
21172
21192
|
}).readonly(),
|
|
21173
21193
|
external_exports.strictObject({
|
|
21174
21194
|
...resultEnvelope,
|
|
21175
|
-
action: external_exports.enum(["import", "fork"]),
|
|
21195
|
+
action: external_exports.enum(["import", "fork", "fork-recorded"]),
|
|
21176
21196
|
targetSessionId: identifierStringSchema,
|
|
21177
21197
|
ready: sessionReadyEventSchema,
|
|
21178
21198
|
title: external_exports.string().max(500)
|
|
@@ -21218,14 +21238,68 @@ var encodeNativeSessionCancel = (value) => JSON.stringify(nativeSessionCancelSch
|
|
|
21218
21238
|
|
|
21219
21239
|
// ../protocol/src/session-events.ts
|
|
21220
21240
|
var SESSION_EVENT_KIND = "session.event";
|
|
21241
|
+
var SESSION_EVENT_ACK_KIND = "session.event.ack";
|
|
21242
|
+
var SESSION_EVENT_DEFERRED_KIND = "session.event.deferred";
|
|
21243
|
+
var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
|
|
21244
|
+
var SESSION_FORKED_KIND = "session.forked";
|
|
21245
|
+
var SessionEventRejectionCode = {
|
|
21246
|
+
IdempotencyConflict: "idempotency_conflict",
|
|
21247
|
+
InvalidEvent: "invalid_event",
|
|
21248
|
+
RecordingRejected: "recording_rejected"
|
|
21249
|
+
};
|
|
21221
21250
|
var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
|
|
21222
|
-
var
|
|
21251
|
+
var ephemeralEventEnvelopeSchema = external_exports.strictObject({
|
|
21223
21252
|
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
21224
21253
|
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
21225
21254
|
sessionId: identifierStringSchema
|
|
21226
21255
|
}).readonly();
|
|
21256
|
+
var reliableDeliverySchema = external_exports.strictObject({
|
|
21257
|
+
eventId: identifierStringSchema,
|
|
21258
|
+
kind: external_exports.literal("reliable"),
|
|
21259
|
+
sourceSeq: external_exports.string().regex(/^(?:0|[1-9][0-9]*)$/u).max(40),
|
|
21260
|
+
streamId: identifierStringSchema
|
|
21261
|
+
}).readonly();
|
|
21262
|
+
var reliableSessionEventEnvelopeSchema = external_exports.strictObject({
|
|
21263
|
+
delivery: reliableDeliverySchema,
|
|
21264
|
+
kind: external_exports.literal(SESSION_EVENT_KIND),
|
|
21265
|
+
payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
|
|
21266
|
+
sessionId: identifierStringSchema
|
|
21267
|
+
}).readonly();
|
|
21268
|
+
var eventEnvelopeSchema = external_exports.union([ephemeralEventEnvelopeSchema, reliableSessionEventEnvelopeSchema]).readonly();
|
|
21269
|
+
var acknowledgementOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
21270
|
+
external_exports.strictObject({ kind: external_exports.literal("relayed") }).readonly(),
|
|
21271
|
+
external_exports.strictObject({
|
|
21272
|
+
kind: external_exports.literal("recorded"),
|
|
21273
|
+
providerId: identifierStringSchema,
|
|
21274
|
+
recordingEpoch: identifierStringSchema
|
|
21275
|
+
}).readonly()
|
|
21276
|
+
]);
|
|
21277
|
+
var eventAcknowledgementSchema = external_exports.strictObject({
|
|
21278
|
+
eventId: identifierStringSchema,
|
|
21279
|
+
kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
|
|
21280
|
+
outcome: acknowledgementOutcomeSchema,
|
|
21281
|
+
sessionId: identifierStringSchema
|
|
21282
|
+
}).readonly();
|
|
21283
|
+
var eventDeferredSchema = external_exports.strictObject({
|
|
21284
|
+
eventId: identifierStringSchema,
|
|
21285
|
+
kind: external_exports.literal(SESSION_EVENT_DEFERRED_KIND),
|
|
21286
|
+
retryAfterMilliseconds: external_exports.number().int().min(100).max(6e4),
|
|
21287
|
+
sessionId: identifierStringSchema
|
|
21288
|
+
}).readonly();
|
|
21289
|
+
var eventRejectedSchema = external_exports.strictObject({
|
|
21290
|
+
code: external_exports.enum(SessionEventRejectionCode),
|
|
21291
|
+
eventId: identifierStringSchema,
|
|
21292
|
+
kind: external_exports.literal(SESSION_EVENT_REJECTED_KIND),
|
|
21293
|
+
sessionId: identifierStringSchema
|
|
21294
|
+
}).readonly();
|
|
21227
21295
|
var SESSION_QUEUE_CHANGED_KIND = "session.queue.changed";
|
|
21228
21296
|
var sessionQueueChangedSchema = external_exports.strictObject({ kind: external_exports.literal(SESSION_QUEUE_CHANGED_KIND), sessionId: identifierStringSchema }).readonly();
|
|
21297
|
+
var sessionForkedSchema = external_exports.strictObject({
|
|
21298
|
+
kind: external_exports.literal(SESSION_FORKED_KIND),
|
|
21299
|
+
sessionId: identifierStringSchema,
|
|
21300
|
+
sourceSessionId: identifierStringSchema,
|
|
21301
|
+
throughCommandId: identifierStringSchema
|
|
21302
|
+
}).readonly();
|
|
21229
21303
|
function decode5(encoded, schema) {
|
|
21230
21304
|
let value;
|
|
21231
21305
|
try {
|
|
@@ -21252,11 +21326,19 @@ var encode4 = (message, schema) => {
|
|
|
21252
21326
|
};
|
|
21253
21327
|
var decodeSessionEventEnvelope = (encoded) => decode5(encoded, eventEnvelopeSchema);
|
|
21254
21328
|
var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
|
|
21329
|
+
var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
|
|
21330
|
+
var encodeSessionEventAcknowledgement = (message) => encode4(message, eventAcknowledgementSchema);
|
|
21331
|
+
var decodeSessionEventDeferred = (encoded) => decode5(encoded, eventDeferredSchema);
|
|
21332
|
+
var encodeSessionEventDeferred = (message) => encode4(message, eventDeferredSchema);
|
|
21333
|
+
var decodeSessionEventRejected = (encoded) => decode5(encoded, eventRejectedSchema);
|
|
21334
|
+
var encodeSessionEventRejected = (message) => encode4(message, eventRejectedSchema);
|
|
21255
21335
|
function decodeRecordedSessionEvent(encoded) {
|
|
21256
21336
|
const kind = decodeMessageKind(encoded);
|
|
21257
21337
|
switch (kind) {
|
|
21258
21338
|
case SESSION_QUEUE_CHANGED_KIND:
|
|
21259
21339
|
return decode5(encoded, sessionQueueChangedSchema);
|
|
21340
|
+
case SESSION_FORKED_KIND:
|
|
21341
|
+
return decode5(encoded, sessionForkedSchema);
|
|
21260
21342
|
case AGENT_ACTIVITY_KIND:
|
|
21261
21343
|
return decodeAgentActivityEvent(encoded);
|
|
21262
21344
|
case AGENT_ACTIVITY_NARRATION_KIND:
|
|
@@ -21423,6 +21505,21 @@ var serviceToDaemonSignatures = {
|
|
|
21423
21505
|
encodeSessionElicitationRespondCommand,
|
|
21424
21506
|
decodeSessionElicitationRespondCommand
|
|
21425
21507
|
),
|
|
21508
|
+
[SESSION_EVENT_ACK_KIND]: defineMessageSignature(
|
|
21509
|
+
SESSION_EVENT_ACK_KIND,
|
|
21510
|
+
encodeSessionEventAcknowledgement,
|
|
21511
|
+
decodeSessionEventAcknowledgement
|
|
21512
|
+
),
|
|
21513
|
+
[SESSION_EVENT_DEFERRED_KIND]: defineMessageSignature(
|
|
21514
|
+
SESSION_EVENT_DEFERRED_KIND,
|
|
21515
|
+
encodeSessionEventDeferred,
|
|
21516
|
+
decodeSessionEventDeferred
|
|
21517
|
+
),
|
|
21518
|
+
[SESSION_EVENT_REJECTED_KIND]: defineMessageSignature(
|
|
21519
|
+
SESSION_EVENT_REJECTED_KIND,
|
|
21520
|
+
encodeSessionEventRejected,
|
|
21521
|
+
decodeSessionEventRejected
|
|
21522
|
+
),
|
|
21426
21523
|
[SESSION_LIVE_HISTORY_LOAD_KIND]: defineMessageSignature(
|
|
21427
21524
|
SESSION_LIVE_HISTORY_LOAD_KIND,
|
|
21428
21525
|
encodeSessionLiveHistoryLoad,
|
|
@@ -24021,13 +24118,15 @@ var AcpPreparedSession = class {
|
|
|
24021
24118
|
capabilities;
|
|
24022
24119
|
commands;
|
|
24023
24120
|
configOptions;
|
|
24121
|
+
prompted;
|
|
24024
24122
|
restored;
|
|
24025
|
-
constructor(agentName, agentVersion, capabilities, commands, configOptions, restored) {
|
|
24123
|
+
constructor(agentName, agentVersion, capabilities, commands, configOptions, prompted, restored) {
|
|
24026
24124
|
this.agentName = agentName;
|
|
24027
24125
|
this.agentVersion = agentVersion;
|
|
24028
24126
|
this.capabilities = capabilities;
|
|
24029
24127
|
this.commands = commands;
|
|
24030
24128
|
this.configOptions = configOptions;
|
|
24129
|
+
this.prompted = prompted;
|
|
24031
24130
|
this.restored = restored;
|
|
24032
24131
|
}
|
|
24033
24132
|
};
|
|
@@ -30254,6 +30353,10 @@ var acpSessionStoreMigrations = [
|
|
|
30254
30353
|
{
|
|
30255
30354
|
"name": "0000_slimy_captain_midlands.sql",
|
|
30256
30355
|
"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"
|
|
30356
|
+
},
|
|
30357
|
+
{
|
|
30358
|
+
"name": "0001_regular_ultimates.sql",
|
|
30359
|
+
"sql": "ALTER TABLE `acp_session` ADD `last_terminal_command_id` text;"
|
|
30257
30360
|
}
|
|
30258
30361
|
];
|
|
30259
30362
|
|
|
@@ -30271,6 +30374,7 @@ var acpSession = sqliteTable("acp_session", {
|
|
|
30271
30374
|
nativeSessionId: text("native_session_id").notNull(),
|
|
30272
30375
|
cwd: text("cwd").notNull(),
|
|
30273
30376
|
additionalDirectories: text("additional_directories").notNull(),
|
|
30377
|
+
lastTerminalCommandId: text("last_terminal_command_id"),
|
|
30274
30378
|
prompted: integer2("prompted", { mode: "boolean" }).notNull(),
|
|
30275
30379
|
title: text("title").notNull(),
|
|
30276
30380
|
updatedAt: text("updated_at").notNull()
|
|
@@ -30286,15 +30390,17 @@ var AcpStoredSession = class {
|
|
|
30286
30390
|
additionalDirectories;
|
|
30287
30391
|
agentId;
|
|
30288
30392
|
cwd;
|
|
30393
|
+
lastTerminalCommandId;
|
|
30289
30394
|
nativeSessionId;
|
|
30290
30395
|
prompted;
|
|
30291
30396
|
sessionId;
|
|
30292
30397
|
title;
|
|
30293
30398
|
updatedAt;
|
|
30294
|
-
constructor(sessionId, agentId, nativeSessionId, cwd, additionalDirectories, prompted, title2, updatedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
30399
|
+
constructor(sessionId, agentId, nativeSessionId, cwd, additionalDirectories, prompted, title2, updatedAt = (/* @__PURE__ */ new Date()).toISOString(), lastTerminalCommandId = null) {
|
|
30295
30400
|
this.additionalDirectories = [...additionalDirectories];
|
|
30296
30401
|
this.agentId = agentId;
|
|
30297
30402
|
this.cwd = cwd;
|
|
30403
|
+
this.lastTerminalCommandId = lastTerminalCommandId;
|
|
30298
30404
|
this.nativeSessionId = nativeSessionId;
|
|
30299
30405
|
this.prompted = prompted;
|
|
30300
30406
|
this.sessionId = sessionId;
|
|
@@ -30355,6 +30461,7 @@ var storedSessionRowSchema = external_exports.object({
|
|
|
30355
30461
|
additionalDirectories: external_exports.string(),
|
|
30356
30462
|
agentId: external_exports.string(),
|
|
30357
30463
|
cwd: external_exports.string(),
|
|
30464
|
+
lastTerminalCommandId: external_exports.string().nullable(),
|
|
30358
30465
|
nativeSessionId: external_exports.string(),
|
|
30359
30466
|
prompted: external_exports.boolean(),
|
|
30360
30467
|
sessionId: external_exports.string(),
|
|
@@ -30374,7 +30481,8 @@ function decodeStoredSession(value) {
|
|
|
30374
30481
|
additionalDirectories,
|
|
30375
30482
|
row.prompted,
|
|
30376
30483
|
row.title,
|
|
30377
|
-
row.updatedAt
|
|
30484
|
+
row.updatedAt,
|
|
30485
|
+
row.lastTerminalCommandId
|
|
30378
30486
|
);
|
|
30379
30487
|
}
|
|
30380
30488
|
var SqliteAcpSessionStore = class {
|
|
@@ -30441,6 +30549,7 @@ var SqliteAcpSessionStore = class {
|
|
|
30441
30549
|
additionalDirectories: JSON.stringify(session.additionalDirectories),
|
|
30442
30550
|
agentId: session.agentId,
|
|
30443
30551
|
cwd: session.cwd,
|
|
30552
|
+
lastTerminalCommandId: session.lastTerminalCommandId,
|
|
30444
30553
|
nativeSessionId: session.nativeSessionId,
|
|
30445
30554
|
prompted: session.prompted,
|
|
30446
30555
|
sessionId: session.sessionId,
|
|
@@ -30493,6 +30602,7 @@ var AgentSession = class _AgentSession {
|
|
|
30493
30602
|
#commands = [];
|
|
30494
30603
|
#configRevision = 0;
|
|
30495
30604
|
#configOptions = [];
|
|
30605
|
+
#lastTerminalCommandId = null;
|
|
30496
30606
|
#prompted = false;
|
|
30497
30607
|
#nativePrompt = null;
|
|
30498
30608
|
#sessionLoad = { kind: "not-requested" };
|
|
@@ -30596,6 +30706,7 @@ var AgentSession = class _AgentSession {
|
|
|
30596
30706
|
this.#capabilities,
|
|
30597
30707
|
this.#commands,
|
|
30598
30708
|
this.#configOptions,
|
|
30709
|
+
this.#prompted,
|
|
30599
30710
|
this.#restored
|
|
30600
30711
|
);
|
|
30601
30712
|
loadHistory = async (signal) => {
|
|
@@ -30829,6 +30940,7 @@ var AgentSession = class _AgentSession {
|
|
|
30829
30940
|
} else if (stored instanceof FoundAcpStoredSession && stored.session.agentId === this.#agentId && stored.session.cwd === this.#cwd && arraysEqual(stored.session.additionalDirectories, this.#additionalDirectories)) {
|
|
30830
30941
|
this.selectNativeSession(stored.session.nativeSessionId);
|
|
30831
30942
|
this.#prompted = stored.session.prompted;
|
|
30943
|
+
this.#lastTerminalCommandId = stored.session.lastTerminalCommandId;
|
|
30832
30944
|
this.#sessionTitle = stored.session.title;
|
|
30833
30945
|
this.#restored = true;
|
|
30834
30946
|
if (this.#capabilities.resumeSession) {
|
|
@@ -30902,7 +31014,9 @@ var AgentSession = class _AgentSession {
|
|
|
30902
31014
|
this.#cwd,
|
|
30903
31015
|
this.#additionalDirectories,
|
|
30904
31016
|
this.#prompted,
|
|
30905
|
-
this.#sessionTitle ?? ""
|
|
31017
|
+
this.#sessionTitle ?? "",
|
|
31018
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
31019
|
+
this.#lastTerminalCommandId
|
|
30906
31020
|
)
|
|
30907
31021
|
);
|
|
30908
31022
|
};
|
|
@@ -31102,7 +31216,9 @@ var AgentSession = class _AgentSession {
|
|
|
31102
31216
|
this.#cwd,
|
|
31103
31217
|
this.#additionalDirectories,
|
|
31104
31218
|
true,
|
|
31105
|
-
this.#sessionTitle
|
|
31219
|
+
this.#sessionTitle,
|
|
31220
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
31221
|
+
this.#lastTerminalCommandId
|
|
31106
31222
|
)
|
|
31107
31223
|
);
|
|
31108
31224
|
this.#prompted = true;
|
|
@@ -31154,6 +31270,20 @@ var AgentSession = class _AgentSession {
|
|
|
31154
31270
|
usage: result.usage ?? null
|
|
31155
31271
|
});
|
|
31156
31272
|
}
|
|
31273
|
+
this.#lastTerminalCommandId = options.commandId;
|
|
31274
|
+
this.#store.write(
|
|
31275
|
+
new AcpStoredSession(
|
|
31276
|
+
this.#mobiusSessionId,
|
|
31277
|
+
this.#agentId,
|
|
31278
|
+
this.#updates.sessionId(),
|
|
31279
|
+
this.#cwd,
|
|
31280
|
+
this.#additionalDirectories,
|
|
31281
|
+
true,
|
|
31282
|
+
this.#sessionTitle ?? "",
|
|
31283
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
31284
|
+
this.#lastTerminalCommandId
|
|
31285
|
+
)
|
|
31286
|
+
);
|
|
31157
31287
|
return result;
|
|
31158
31288
|
} catch (error62) {
|
|
31159
31289
|
await running.activities.finish();
|
|
@@ -31346,7 +31476,9 @@ var AgentSession = class _AgentSession {
|
|
|
31346
31476
|
this.#cwd,
|
|
31347
31477
|
this.#additionalDirectories,
|
|
31348
31478
|
this.#prompted,
|
|
31349
|
-
this.#sessionTitle ?? ""
|
|
31479
|
+
this.#sessionTitle ?? "",
|
|
31480
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
31481
|
+
this.#lastTerminalCommandId
|
|
31350
31482
|
)
|
|
31351
31483
|
);
|
|
31352
31484
|
}
|
|
@@ -32392,9 +32524,17 @@ var AgentRuntimeManager = class {
|
|
|
32392
32524
|
const openedKey = `${options2.agent.id}:${runtime.nativeSessionId()}`;
|
|
32393
32525
|
this.#nativeOperations.add(openedKey);
|
|
32394
32526
|
try {
|
|
32527
|
+
const prepared = runtime.prepared();
|
|
32528
|
+
if (origin.kind === "fork" && options2.agent.id === "claude") {
|
|
32529
|
+
await this.#retireSessionProcess(
|
|
32530
|
+
options2.sessionId,
|
|
32531
|
+
runtime,
|
|
32532
|
+
async () => await runtime.closeProcess()
|
|
32533
|
+
);
|
|
32534
|
+
}
|
|
32395
32535
|
return {
|
|
32396
32536
|
sessionId: options2.sessionId,
|
|
32397
|
-
prepared
|
|
32537
|
+
prepared
|
|
32398
32538
|
};
|
|
32399
32539
|
} finally {
|
|
32400
32540
|
this.#nativeOperations.delete(openedKey);
|
|
@@ -37515,7 +37655,7 @@ function isRuntimeRelayRevocation(closeCode, closeReason) {
|
|
|
37515
37655
|
}
|
|
37516
37656
|
|
|
37517
37657
|
// src/run-daemon.ts
|
|
37518
|
-
import { createHash as createHash6, randomUUID as
|
|
37658
|
+
import { createHash as createHash6, randomUUID as randomUUID8 } from "node:crypto";
|
|
37519
37659
|
import { join as join18 } from "node:path";
|
|
37520
37660
|
import { styleText } from "node:util";
|
|
37521
37661
|
|
|
@@ -39861,6 +40001,7 @@ var readCodexFullHistory = async (agent, cwd, nativeSessionId, signal, nativeTur
|
|
|
39861
40001
|
|
|
39862
40002
|
// src/native-sessions/service.ts
|
|
39863
40003
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
40004
|
+
import { basename as basename5 } from "node:path";
|
|
39864
40005
|
|
|
39865
40006
|
// src/native-sessions/acp-history.ts
|
|
39866
40007
|
async function readAcpHistory(sessions, directories, bindingId, options, nativeSessionId) {
|
|
@@ -40001,6 +40142,64 @@ var NativeSessionService = class {
|
|
|
40001
40142
|
sessionId: command.sessionId
|
|
40002
40143
|
};
|
|
40003
40144
|
}
|
|
40145
|
+
if (command.action === "fork-recorded") {
|
|
40146
|
+
const source = this.#sessions.findSessions([command.sessionId])[0];
|
|
40147
|
+
if (source === void 0 || !source.prompted) {
|
|
40148
|
+
throw new AcpExecutionError(
|
|
40149
|
+
"The source conversation has no resumable native Agent session",
|
|
40150
|
+
{},
|
|
40151
|
+
"native_session_not_found"
|
|
40152
|
+
);
|
|
40153
|
+
}
|
|
40154
|
+
if (source.agentId !== command.agentId || source.cwd !== cwd || source.additionalDirectories.length !== additionalDirectories.length || source.additionalDirectories.some((path2, index) => path2 !== additionalDirectories[index])) {
|
|
40155
|
+
throw new AcpExecutionError(
|
|
40156
|
+
"The source conversation execution target does not match the fork request",
|
|
40157
|
+
{},
|
|
40158
|
+
"native_session_target_changed"
|
|
40159
|
+
);
|
|
40160
|
+
}
|
|
40161
|
+
if (source.lastTerminalCommandId !== command.throughCommandId) {
|
|
40162
|
+
throw new AcpExecutionError(
|
|
40163
|
+
"The selected Turn is no longer the source conversation head",
|
|
40164
|
+
{},
|
|
40165
|
+
"fork_point_stale"
|
|
40166
|
+
);
|
|
40167
|
+
}
|
|
40168
|
+
const opened2 = await this.#sessions.openNativeSession(
|
|
40169
|
+
{ ...options, sessionId: command.targetSessionId },
|
|
40170
|
+
{ kind: "fork", nativeSessionId: source.nativeSessionId }
|
|
40171
|
+
);
|
|
40172
|
+
signal.throwIfAborted();
|
|
40173
|
+
const directory = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
|
|
40174
|
+
const ready2 = {
|
|
40175
|
+
additionalDirectories: additionalDirectories.map((path2, index) => ({
|
|
40176
|
+
directoryId: command.additionalDirectoryIds[index] ?? command.directoryId,
|
|
40177
|
+
name: basename5(path2) || path2
|
|
40178
|
+
})),
|
|
40179
|
+
agentId: command.agentId,
|
|
40180
|
+
agentName: opened2.prepared.agentName,
|
|
40181
|
+
agentVersion: opened2.prepared.agentVersion,
|
|
40182
|
+
capabilities: opened2.prepared.capabilities,
|
|
40183
|
+
commands: opened2.prepared.commands,
|
|
40184
|
+
configOptions: opened2.prepared.configOptions,
|
|
40185
|
+
directoryId: command.directoryId,
|
|
40186
|
+
directoryLabel: directory.directoryLabel,
|
|
40187
|
+
kind: "session.ready",
|
|
40188
|
+
requestId: command.requestId,
|
|
40189
|
+
restored: true,
|
|
40190
|
+
sessionId: opened2.sessionId
|
|
40191
|
+
};
|
|
40192
|
+
this.record(command, "native_recorded_session_forked");
|
|
40193
|
+
return {
|
|
40194
|
+
action: "fork-recorded",
|
|
40195
|
+
kind: "native.session.result",
|
|
40196
|
+
ready: ready2,
|
|
40197
|
+
requestId: command.requestId,
|
|
40198
|
+
sessionId: command.sessionId,
|
|
40199
|
+
targetSessionId: command.targetSessionId,
|
|
40200
|
+
title: source.title || "Untitled session"
|
|
40201
|
+
};
|
|
40202
|
+
}
|
|
40004
40203
|
const prepared = await this.#sessions.prepareNativeSessionBrowser(options);
|
|
40005
40204
|
if (!prepared.capabilities.listSessions) {
|
|
40006
40205
|
throw new AcpExecutionError(
|
|
@@ -41322,7 +41521,7 @@ function createAgentSettingsDiscoveryHandler(dependencies) {
|
|
|
41322
41521
|
// src/artifacts/local-file-streamer.ts
|
|
41323
41522
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
41324
41523
|
import { realpath as realpath9, stat as stat8 } from "node:fs/promises";
|
|
41325
|
-
import { basename as
|
|
41524
|
+
import { basename as basename6, isAbsolute as isAbsolute10, normalize as normalize4, resolve as resolve7 } from "node:path";
|
|
41326
41525
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
41327
41526
|
var CHUNK_BYTES = 192 * 1024;
|
|
41328
41527
|
function requestedPath(value) {
|
|
@@ -41373,7 +41572,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
|
|
|
41373
41572
|
kind: FILE_BEGIN_KIND,
|
|
41374
41573
|
mediaType: raster?.mimeType ?? "application/octet-stream",
|
|
41375
41574
|
modifiedAt: before.mtime.toISOString(),
|
|
41376
|
-
name:
|
|
41575
|
+
name: basename6(target) || "file",
|
|
41377
41576
|
requestId: command.requestId,
|
|
41378
41577
|
sessionId: command.sessionId
|
|
41379
41578
|
});
|
|
@@ -41403,7 +41602,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
|
|
|
41403
41602
|
}
|
|
41404
41603
|
|
|
41405
41604
|
// src/authorization/resolve-session-directories.ts
|
|
41406
|
-
import { basename as
|
|
41605
|
+
import { basename as basename7 } from "node:path";
|
|
41407
41606
|
var ResolvedSessionDirectories = class {
|
|
41408
41607
|
additionalDirectories;
|
|
41409
41608
|
additionalDirectoryEntries;
|
|
@@ -41428,7 +41627,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
|
|
|
41428
41627
|
additionalDirectories.push(directory);
|
|
41429
41628
|
additionalDirectoryEntries.push({
|
|
41430
41629
|
directoryId: additionalDirectoryId,
|
|
41431
|
-
name:
|
|
41630
|
+
name: basename7(directory)
|
|
41432
41631
|
});
|
|
41433
41632
|
}
|
|
41434
41633
|
return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
|
|
@@ -42165,14 +42364,15 @@ async function executePrompt({
|
|
|
42165
42364
|
const appliedSettings = command.sessionConfigurations === void 0 ? void 0 : agentForSessionConfiguration(agent, command.sessionConfigurations);
|
|
42166
42365
|
const executionAgent = appliedSettings?.agent ?? agent;
|
|
42167
42366
|
const sessionConfigurations = appliedSettings?.sessionConfigurations;
|
|
42367
|
+
const preparation = {
|
|
42368
|
+
additionalDirectories: resolved.additionalDirectories,
|
|
42369
|
+
agent: executionAgent,
|
|
42370
|
+
cwd: resolved.cwd,
|
|
42371
|
+
sessionId: command.sessionId,
|
|
42372
|
+
signal
|
|
42373
|
+
};
|
|
42374
|
+
let prepared = await sessions.prepareExecutionSession(preparation);
|
|
42168
42375
|
if (command.sessionConfigurations !== void 0) {
|
|
42169
|
-
const prepared = await sessions.prepareExecutionSession({
|
|
42170
|
-
additionalDirectories: resolved.additionalDirectories,
|
|
42171
|
-
agent: executionAgent,
|
|
42172
|
-
cwd: resolved.cwd,
|
|
42173
|
-
sessionId: command.sessionId,
|
|
42174
|
-
signal
|
|
42175
|
-
});
|
|
42176
42376
|
if (availability.disposition === SessionPromptDisposition.Steer) {
|
|
42177
42377
|
assertAppliedSessionConfiguration(prepared.configOptions, sessionConfigurations ?? []);
|
|
42178
42378
|
} else {
|
|
@@ -42188,6 +42388,7 @@ async function executePrompt({
|
|
|
42188
42388
|
command.sessionId,
|
|
42189
42389
|
signal
|
|
42190
42390
|
);
|
|
42391
|
+
prepared = await sessions.prepareExecutionSession(preparation);
|
|
42191
42392
|
}
|
|
42192
42393
|
}
|
|
42193
42394
|
audit.record({
|
|
@@ -42206,6 +42407,24 @@ async function executePrompt({
|
|
|
42206
42407
|
}
|
|
42207
42408
|
}
|
|
42208
42409
|
const stream = activateAttempt();
|
|
42410
|
+
if (!prepared.prompted) {
|
|
42411
|
+
const listing = await directories.list(config2.bindingId, command.directoryId, signal);
|
|
42412
|
+
publisher.publish(command.sessionId, {
|
|
42413
|
+
additionalDirectories: resolved.additionalDirectoryEntries,
|
|
42414
|
+
agentId: command.agentId,
|
|
42415
|
+
agentName: prepared.agentName,
|
|
42416
|
+
agentVersion: prepared.agentVersion,
|
|
42417
|
+
capabilities: prepared.capabilities,
|
|
42418
|
+
commands: prepared.commands,
|
|
42419
|
+
configOptions: prepared.configOptions,
|
|
42420
|
+
directoryId: command.directoryId,
|
|
42421
|
+
directoryLabel: listing.directoryLabel,
|
|
42422
|
+
kind: SESSION_READY_KIND,
|
|
42423
|
+
requestId: command.commandId,
|
|
42424
|
+
restored: prepared.restored,
|
|
42425
|
+
sessionId: command.sessionId
|
|
42426
|
+
});
|
|
42427
|
+
}
|
|
42209
42428
|
publisher.publish(command.sessionId, {
|
|
42210
42429
|
commandId: command.commandId,
|
|
42211
42430
|
epoch: stream.epoch,
|
|
@@ -42459,7 +42678,7 @@ async function executeSessionConfigure(publisher, socket, command, config2, dire
|
|
|
42459
42678
|
// src/native-sessions/handle-native-requests.ts
|
|
42460
42679
|
import { WebSocket as WebSocket5 } from "undici";
|
|
42461
42680
|
function createNativeSessionRequestHandler(dependencies) {
|
|
42462
|
-
const { audit, diagnostics, nativeSessions, signal, socket, timer } = dependencies;
|
|
42681
|
+
const { audit, diagnostics, nativeSessions, publisher, signal, socket, timer } = dependencies;
|
|
42463
42682
|
const pending = /* @__PURE__ */ new Map();
|
|
42464
42683
|
const cancel = (command) => {
|
|
42465
42684
|
const request = pending.get(command.requestId);
|
|
@@ -42511,6 +42730,17 @@ function createNativeSessionRequestHandler(dependencies) {
|
|
|
42511
42730
|
}
|
|
42512
42731
|
operationSignal.throwIfAborted();
|
|
42513
42732
|
const result = await nativeSessions.execute(command, operationSignal);
|
|
42733
|
+
if (command.action === "fork-recorded" && result.action === "fork-recorded") {
|
|
42734
|
+
publisher.publishBatch(result.ready.sessionId, [
|
|
42735
|
+
result.ready,
|
|
42736
|
+
{
|
|
42737
|
+
kind: "session.forked",
|
|
42738
|
+
sessionId: result.ready.sessionId,
|
|
42739
|
+
sourceSessionId: command.sessionId,
|
|
42740
|
+
throughCommandId: command.throughCommandId
|
|
42741
|
+
}
|
|
42742
|
+
]);
|
|
42743
|
+
}
|
|
42514
42744
|
if (socket.readyState === WebSocket5.OPEN) {
|
|
42515
42745
|
send(socket, result);
|
|
42516
42746
|
}
|
|
@@ -42596,6 +42826,7 @@ function createDaemonCommandHandler({
|
|
|
42596
42826
|
audit,
|
|
42597
42827
|
diagnostics,
|
|
42598
42828
|
nativeSessions,
|
|
42829
|
+
publisher,
|
|
42599
42830
|
signal,
|
|
42600
42831
|
socket,
|
|
42601
42832
|
timer
|
|
@@ -43098,6 +43329,7 @@ async function runRelayConnection({
|
|
|
43098
43329
|
}) {
|
|
43099
43330
|
const relayUrl = new URL(config2.relayUrl);
|
|
43100
43331
|
relayUrl.searchParams.set("liveness", "1");
|
|
43332
|
+
relayUrl.searchParams.set("sessionEventDelivery", "reliable-v1");
|
|
43101
43333
|
const socket = await connectRelay(relayUrl, signal);
|
|
43102
43334
|
diagnostics.connectionOpened(connectionEpoch);
|
|
43103
43335
|
const connectionController = new AbortController();
|
|
@@ -43217,6 +43449,10 @@ async function runRelayConnection({
|
|
|
43217
43449
|
const message = decodeServiceToDaemonMessage(encoded);
|
|
43218
43450
|
const kind = message.kind;
|
|
43219
43451
|
if (kind === RUNTIME_LIVENESS_READY_KIND) {
|
|
43452
|
+
publisher.connect(
|
|
43453
|
+
socket,
|
|
43454
|
+
message.sessionEventDelivery === "reliable-v1" ? "reliable" : "ephemeral"
|
|
43455
|
+
);
|
|
43220
43456
|
connectionLiveness.start();
|
|
43221
43457
|
return;
|
|
43222
43458
|
}
|
|
@@ -43224,6 +43460,18 @@ async function runRelayConnection({
|
|
|
43224
43460
|
connectionLiveness.acknowledge(message);
|
|
43225
43461
|
return;
|
|
43226
43462
|
}
|
|
43463
|
+
if (kind === SESSION_EVENT_ACK_KIND) {
|
|
43464
|
+
publisher.acknowledge(message);
|
|
43465
|
+
return;
|
|
43466
|
+
}
|
|
43467
|
+
if (kind === SESSION_EVENT_DEFERRED_KIND) {
|
|
43468
|
+
publisher.defer(message);
|
|
43469
|
+
return;
|
|
43470
|
+
}
|
|
43471
|
+
if (kind === SESSION_EVENT_REJECTED_KIND) {
|
|
43472
|
+
publisher.quarantine(message);
|
|
43473
|
+
return;
|
|
43474
|
+
}
|
|
43227
43475
|
commands.handle(message);
|
|
43228
43476
|
} catch (error62) {
|
|
43229
43477
|
console.error("Mobius daemon rejected a message", error62);
|
|
@@ -43238,7 +43486,6 @@ async function runRelayConnection({
|
|
|
43238
43486
|
socket.addEventListener("close", handleClose);
|
|
43239
43487
|
socket.addEventListener("error", handleError);
|
|
43240
43488
|
socket.addEventListener("message", handleMessage);
|
|
43241
|
-
publisher.connect(socket);
|
|
43242
43489
|
if (signal.aborted) {
|
|
43243
43490
|
stop();
|
|
43244
43491
|
}
|
|
@@ -43249,54 +43496,405 @@ async function runRelayConnection({
|
|
|
43249
43496
|
}
|
|
43250
43497
|
}
|
|
43251
43498
|
|
|
43499
|
+
// src/relay-connection/session-event-outbox.ts
|
|
43500
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
43501
|
+
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
43502
|
+
import { dirname as dirname6 } from "node:path";
|
|
43503
|
+
import { DatabaseSync } from "node:sqlite";
|
|
43504
|
+
var DEFAULT_STANDARD_EVENT_BYTES = 96 * 1024 * 1024;
|
|
43505
|
+
var DEFAULT_CRITICAL_EVENT_BYTES = 128 * 1024 * 1024;
|
|
43506
|
+
var MAX_DEAD_LETTERS = 1024;
|
|
43507
|
+
var DEFAULT_LIMITS = {
|
|
43508
|
+
criticalEventBytes: DEFAULT_CRITICAL_EVENT_BYTES,
|
|
43509
|
+
standardEventBytes: DEFAULT_STANDARD_EVENT_BYTES
|
|
43510
|
+
};
|
|
43511
|
+
var SessionEventOutboxCapacityError = class extends Error {
|
|
43512
|
+
code = "session_event_outbox_full";
|
|
43513
|
+
constructor() {
|
|
43514
|
+
super("The persistent Session event outbox is full");
|
|
43515
|
+
this.name = "SessionEventOutboxCapacityError";
|
|
43516
|
+
}
|
|
43517
|
+
};
|
|
43518
|
+
function rowNumber(row, field) {
|
|
43519
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
43520
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
43521
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
43522
|
+
}
|
|
43523
|
+
return value;
|
|
43524
|
+
}
|
|
43525
|
+
function rowString(row, field) {
|
|
43526
|
+
const value = typeof row === "object" && row !== null ? Reflect.get(row, field) : void 0;
|
|
43527
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
43528
|
+
throw new Error(`SQLite returned an invalid ${field} value`);
|
|
43529
|
+
}
|
|
43530
|
+
return value;
|
|
43531
|
+
}
|
|
43532
|
+
function validateLimits(limits) {
|
|
43533
|
+
if (!Number.isSafeInteger(limits.standardEventBytes) || limits.standardEventBytes < 1 || !Number.isSafeInteger(limits.criticalEventBytes) || limits.criticalEventBytes < limits.standardEventBytes) {
|
|
43534
|
+
throw new Error("Session event outbox limits are invalid");
|
|
43535
|
+
}
|
|
43536
|
+
}
|
|
43537
|
+
var SessionEventOutbox = class {
|
|
43538
|
+
#database;
|
|
43539
|
+
#limits;
|
|
43540
|
+
constructor(path2, limits = DEFAULT_LIMITS) {
|
|
43541
|
+
validateLimits(limits);
|
|
43542
|
+
mkdirSync3(dirname6(path2), { mode: 448, recursive: true });
|
|
43543
|
+
this.#limits = limits;
|
|
43544
|
+
this.#database = new DatabaseSync(path2);
|
|
43545
|
+
this.#database.exec("PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL; PRAGMA busy_timeout = 5000;");
|
|
43546
|
+
this.#database.exec(`
|
|
43547
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
|
|
43548
|
+
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43549
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
43550
|
+
session_id TEXT NOT NULL,
|
|
43551
|
+
source_seq INTEGER NOT NULL UNIQUE,
|
|
43552
|
+
byte_length INTEGER NOT NULL,
|
|
43553
|
+
envelope_json TEXT NOT NULL
|
|
43554
|
+
) STRICT;
|
|
43555
|
+
CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
|
|
43556
|
+
ON relay_session_event_outbox(source_seq);
|
|
43557
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_outbox_state (
|
|
43558
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
43559
|
+
stream_id TEXT NOT NULL,
|
|
43560
|
+
next_source_seq INTEGER NOT NULL,
|
|
43561
|
+
total_bytes INTEGER NOT NULL
|
|
43562
|
+
) STRICT;
|
|
43563
|
+
CREATE TABLE IF NOT EXISTS relay_session_event_dead_letters (
|
|
43564
|
+
ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43565
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
43566
|
+
session_id TEXT NOT NULL,
|
|
43567
|
+
rejection_code TEXT NOT NULL,
|
|
43568
|
+
envelope_json TEXT NOT NULL
|
|
43569
|
+
) STRICT;
|
|
43570
|
+
`);
|
|
43571
|
+
this.#database.prepare(
|
|
43572
|
+
`INSERT OR IGNORE INTO relay_session_event_outbox_state (
|
|
43573
|
+
singleton, stream_id, next_source_seq, total_bytes
|
|
43574
|
+
) VALUES (1, ?, 1, 0)`
|
|
43575
|
+
).run(randomUUID7());
|
|
43576
|
+
}
|
|
43577
|
+
acknowledge = (acknowledgement) => this.#remove(acknowledgement.eventId, acknowledgement.sessionId);
|
|
43578
|
+
close = () => {
|
|
43579
|
+
this.#database.close();
|
|
43580
|
+
};
|
|
43581
|
+
enqueue = (sessionId, payload, critical) => {
|
|
43582
|
+
const envelope2 = this.enqueueBatch(sessionId, [payload], critical)[0];
|
|
43583
|
+
if (envelope2 === void 0) {
|
|
43584
|
+
throw new Error("The Session event outbox did not enqueue the event");
|
|
43585
|
+
}
|
|
43586
|
+
return envelope2;
|
|
43587
|
+
};
|
|
43588
|
+
enqueueBatch = (sessionId, payloads, critical) => {
|
|
43589
|
+
if (payloads.length < 1 || payloads.length > 32) {
|
|
43590
|
+
throw new Error("A Session event batch must contain between 1 and 32 events");
|
|
43591
|
+
}
|
|
43592
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
43593
|
+
try {
|
|
43594
|
+
const state = this.#database.prepare(
|
|
43595
|
+
`SELECT stream_id, next_source_seq, total_bytes
|
|
43596
|
+
FROM relay_session_event_outbox_state
|
|
43597
|
+
WHERE singleton = 1`
|
|
43598
|
+
).get();
|
|
43599
|
+
const sourceSeq = rowNumber(state, "next_source_seq");
|
|
43600
|
+
if (sourceSeq < 1 || !Number.isSafeInteger(sourceSeq + payloads.length)) {
|
|
43601
|
+
throw new Error("The Session event source sequence is exhausted");
|
|
43602
|
+
}
|
|
43603
|
+
const streamId = rowString(state, "stream_id");
|
|
43604
|
+
const stored = payloads.map((payload, index) => {
|
|
43605
|
+
const envelope2 = {
|
|
43606
|
+
delivery: {
|
|
43607
|
+
eventId: randomUUID7(),
|
|
43608
|
+
kind: "reliable",
|
|
43609
|
+
sourceSeq: (sourceSeq + index).toString(),
|
|
43610
|
+
streamId
|
|
43611
|
+
},
|
|
43612
|
+
kind: SESSION_EVENT_KIND,
|
|
43613
|
+
payload,
|
|
43614
|
+
sessionId
|
|
43615
|
+
};
|
|
43616
|
+
const encoded = encodeSessionEventEnvelope(envelope2);
|
|
43617
|
+
return { byteLength: Buffer.byteLength(encoded, "utf8"), encoded, envelope: envelope2 };
|
|
43618
|
+
});
|
|
43619
|
+
const byteLength = stored.reduce((total, entry) => total + entry.byteLength, 0);
|
|
43620
|
+
const maximumBytes = critical ? this.#limits.criticalEventBytes : this.#limits.standardEventBytes;
|
|
43621
|
+
if (rowNumber(state, "total_bytes") + byteLength > maximumBytes) {
|
|
43622
|
+
throw new SessionEventOutboxCapacityError();
|
|
43623
|
+
}
|
|
43624
|
+
const insert = this.#database.prepare(
|
|
43625
|
+
`INSERT INTO relay_session_event_outbox (
|
|
43626
|
+
event_id, session_id, source_seq, byte_length, envelope_json
|
|
43627
|
+
) VALUES (?, ?, ?, ?, ?)`
|
|
43628
|
+
);
|
|
43629
|
+
for (const entry of stored) {
|
|
43630
|
+
insert.run(
|
|
43631
|
+
entry.envelope.delivery.eventId,
|
|
43632
|
+
sessionId,
|
|
43633
|
+
Number(entry.envelope.delivery.sourceSeq),
|
|
43634
|
+
entry.byteLength,
|
|
43635
|
+
entry.encoded
|
|
43636
|
+
);
|
|
43637
|
+
}
|
|
43638
|
+
this.#database.prepare(
|
|
43639
|
+
`UPDATE relay_session_event_outbox_state
|
|
43640
|
+
SET next_source_seq = next_source_seq + ?,
|
|
43641
|
+
total_bytes = total_bytes + ?
|
|
43642
|
+
WHERE singleton = 1`
|
|
43643
|
+
).run(stored.length, byteLength);
|
|
43644
|
+
this.#database.exec("COMMIT");
|
|
43645
|
+
return stored.map((entry) => entry.envelope);
|
|
43646
|
+
} catch (error62) {
|
|
43647
|
+
this.#database.exec("ROLLBACK");
|
|
43648
|
+
throw error62;
|
|
43649
|
+
}
|
|
43650
|
+
};
|
|
43651
|
+
pending = (limit, excludedEventIds) => {
|
|
43652
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
43653
|
+
throw new Error("Session event replay limit must be a positive integer");
|
|
43654
|
+
}
|
|
43655
|
+
const exclusion = excludedEventIds.length === 0 ? "" : `WHERE event_id NOT IN (${excludedEventIds.map(() => "?").join(", ")})`;
|
|
43656
|
+
return this.#database.prepare(
|
|
43657
|
+
`SELECT envelope_json
|
|
43658
|
+
FROM relay_session_event_outbox
|
|
43659
|
+
${exclusion}
|
|
43660
|
+
ORDER BY source_seq
|
|
43661
|
+
LIMIT ?`
|
|
43662
|
+
).all(...excludedEventIds, limit).map((row) => {
|
|
43663
|
+
const envelope2 = decodeSessionEventEnvelope(rowString(row, "envelope_json"));
|
|
43664
|
+
if (!("delivery" in envelope2)) {
|
|
43665
|
+
throw new Error("SQLite returned an invalid reliable Session event envelope");
|
|
43666
|
+
}
|
|
43667
|
+
return envelope2;
|
|
43668
|
+
});
|
|
43669
|
+
};
|
|
43670
|
+
quarantine = (rejection) => {
|
|
43671
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
43672
|
+
try {
|
|
43673
|
+
const stored = this.#database.prepare(
|
|
43674
|
+
`SELECT byte_length, envelope_json
|
|
43675
|
+
FROM relay_session_event_outbox
|
|
43676
|
+
WHERE event_id = ? AND session_id = ?`
|
|
43677
|
+
).get(rejection.eventId, rejection.sessionId);
|
|
43678
|
+
if (stored === void 0) {
|
|
43679
|
+
this.#database.exec("COMMIT");
|
|
43680
|
+
return false;
|
|
43681
|
+
}
|
|
43682
|
+
this.#database.prepare(
|
|
43683
|
+
`INSERT INTO relay_session_event_dead_letters (
|
|
43684
|
+
event_id, session_id, rejection_code, envelope_json
|
|
43685
|
+
) VALUES (?, ?, ?, ?)`
|
|
43686
|
+
).run(rejection.eventId, rejection.sessionId, rejection.code, rowString(stored, "envelope_json"));
|
|
43687
|
+
this.#deleteStored(rejection.eventId, rejection.sessionId, rowNumber(stored, "byte_length"));
|
|
43688
|
+
this.#database.prepare(
|
|
43689
|
+
`DELETE FROM relay_session_event_dead_letters
|
|
43690
|
+
WHERE ordinal NOT IN (
|
|
43691
|
+
SELECT ordinal FROM relay_session_event_dead_letters
|
|
43692
|
+
ORDER BY ordinal DESC LIMIT ?
|
|
43693
|
+
)`
|
|
43694
|
+
).run(MAX_DEAD_LETTERS);
|
|
43695
|
+
this.#database.exec("COMMIT");
|
|
43696
|
+
return true;
|
|
43697
|
+
} catch (error62) {
|
|
43698
|
+
this.#database.exec("ROLLBACK");
|
|
43699
|
+
throw error62;
|
|
43700
|
+
}
|
|
43701
|
+
};
|
|
43702
|
+
#deleteStored = (eventId, sessionId, byteLength) => {
|
|
43703
|
+
const deletion = this.#database.prepare(
|
|
43704
|
+
`DELETE FROM relay_session_event_outbox
|
|
43705
|
+
WHERE event_id = ? AND session_id = ?`
|
|
43706
|
+
).run(eventId, sessionId);
|
|
43707
|
+
if (deletion.changes !== 1) {
|
|
43708
|
+
throw new Error("The Session event could not be removed from the outbox");
|
|
43709
|
+
}
|
|
43710
|
+
const state = this.#database.prepare(
|
|
43711
|
+
`UPDATE relay_session_event_outbox_state
|
|
43712
|
+
SET total_bytes = total_bytes - ?
|
|
43713
|
+
WHERE singleton = 1 AND total_bytes >= ?`
|
|
43714
|
+
).run(byteLength, byteLength);
|
|
43715
|
+
if (state.changes !== 1) {
|
|
43716
|
+
throw new Error("The Session event outbox capacity state is inconsistent");
|
|
43717
|
+
}
|
|
43718
|
+
};
|
|
43719
|
+
#remove = (eventId, sessionId) => {
|
|
43720
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
43721
|
+
try {
|
|
43722
|
+
const stored = this.#database.prepare(
|
|
43723
|
+
`SELECT byte_length
|
|
43724
|
+
FROM relay_session_event_outbox
|
|
43725
|
+
WHERE event_id = ? AND session_id = ?`
|
|
43726
|
+
).get(eventId, sessionId);
|
|
43727
|
+
if (stored === void 0) {
|
|
43728
|
+
this.#database.exec("COMMIT");
|
|
43729
|
+
return false;
|
|
43730
|
+
}
|
|
43731
|
+
this.#deleteStored(eventId, sessionId, rowNumber(stored, "byte_length"));
|
|
43732
|
+
this.#database.exec("COMMIT");
|
|
43733
|
+
return true;
|
|
43734
|
+
} catch (error62) {
|
|
43735
|
+
this.#database.exec("ROLLBACK");
|
|
43736
|
+
throw error62;
|
|
43737
|
+
}
|
|
43738
|
+
};
|
|
43739
|
+
};
|
|
43740
|
+
|
|
43252
43741
|
// src/relay-connection/session-event-publisher.ts
|
|
43253
43742
|
import { WebSocket as WebSocket9 } from "undici";
|
|
43254
|
-
var
|
|
43743
|
+
var SESSION_EVENT_REPLAY_WINDOW = 16;
|
|
43744
|
+
var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
43745
|
+
function reservesSessionEventCapacity(event) {
|
|
43746
|
+
if (event.kind === SESSION_COMPLETED_KIND || event.kind === SESSION_FAILED_KIND || event.kind === SESSION_FORKED_KIND || event.kind === SESSION_READY_KIND) {
|
|
43747
|
+
return true;
|
|
43748
|
+
}
|
|
43749
|
+
return event.kind === AGENT_ACTIVITY_KIND && (event.activityType === "progress" || event.activityType === "reasoning") && (event.status === "completed" || event.status === "failed");
|
|
43750
|
+
}
|
|
43255
43751
|
var DaemonSessionEventPublisher = class {
|
|
43256
|
-
#
|
|
43257
|
-
#
|
|
43258
|
-
|
|
43259
|
-
|
|
43260
|
-
|
|
43752
|
+
#inFlight = /* @__PURE__ */ new Map();
|
|
43753
|
+
#outbox;
|
|
43754
|
+
#reportedCapacityKinds = /* @__PURE__ */ new Set();
|
|
43755
|
+
#timer;
|
|
43756
|
+
#connection = { kind: "disconnected" };
|
|
43757
|
+
#deferredReplay = null;
|
|
43758
|
+
#inFlightBytes = 0;
|
|
43759
|
+
constructor(outbox, timer) {
|
|
43760
|
+
this.#outbox = outbox;
|
|
43761
|
+
this.#timer = timer;
|
|
43762
|
+
}
|
|
43763
|
+
acknowledge = (acknowledgement) => {
|
|
43764
|
+
if (!this.#outbox.acknowledge(acknowledgement)) {
|
|
43765
|
+
return;
|
|
43766
|
+
}
|
|
43767
|
+
this.#removeInFlight(acknowledgement.eventId);
|
|
43768
|
+
this.#publishNextBatch();
|
|
43769
|
+
};
|
|
43770
|
+
close = () => {
|
|
43771
|
+
this.#deferredReplay?.cancel();
|
|
43772
|
+
this.#deferredReplay = null;
|
|
43773
|
+
this.#connection = { kind: "disconnected" };
|
|
43774
|
+
this.#clearInFlight();
|
|
43775
|
+
this.#outbox.close();
|
|
43776
|
+
};
|
|
43777
|
+
connect = (socket, delivery) => {
|
|
43778
|
+
this.#connection = { delivery, kind: "connected", socket };
|
|
43779
|
+
this.#clearInFlight();
|
|
43780
|
+
this.#publishNextBatch();
|
|
43781
|
+
};
|
|
43782
|
+
defer = (deferred) => {
|
|
43783
|
+
if (!this.#inFlight.has(deferred.eventId)) {
|
|
43784
|
+
return;
|
|
43785
|
+
}
|
|
43786
|
+
this.#clearInFlight();
|
|
43787
|
+
if (this.#deferredReplay !== null) {
|
|
43788
|
+
return;
|
|
43789
|
+
}
|
|
43790
|
+
this.#deferredReplay = this.#timer.schedule(() => {
|
|
43791
|
+
this.#deferredReplay = null;
|
|
43792
|
+
this.#publishNextBatch();
|
|
43793
|
+
}, deferred.retryAfterMilliseconds);
|
|
43261
43794
|
};
|
|
43262
43795
|
disconnect = (socket) => {
|
|
43263
|
-
if (this.#socket
|
|
43264
|
-
|
|
43796
|
+
if (this.#connection.kind !== "connected" || this.#connection.socket !== socket) {
|
|
43797
|
+
return;
|
|
43265
43798
|
}
|
|
43799
|
+
this.#connection = { kind: "disconnected" };
|
|
43800
|
+
this.#clearInFlight();
|
|
43266
43801
|
};
|
|
43267
43802
|
publish = (sessionId, event) => {
|
|
43268
|
-
|
|
43269
|
-
|
|
43270
|
-
|
|
43803
|
+
try {
|
|
43804
|
+
this.#outbox.enqueue(sessionId, encodeRecordedSessionEvent(event), reservesSessionEventCapacity(event));
|
|
43805
|
+
} catch (error62) {
|
|
43806
|
+
if (!(error62 instanceof SessionEventOutboxCapacityError)) {
|
|
43807
|
+
throw error62;
|
|
43808
|
+
}
|
|
43809
|
+
if (!this.#reportedCapacityKinds.has(event.kind)) {
|
|
43810
|
+
this.#reportedCapacityKinds.add(event.kind);
|
|
43811
|
+
console.warn(
|
|
43812
|
+
`Mobius daemon could not persist "${event.kind}" because the Session event outbox is full`
|
|
43813
|
+
);
|
|
43814
|
+
}
|
|
43271
43815
|
return;
|
|
43272
43816
|
}
|
|
43273
|
-
|
|
43274
|
-
|
|
43275
|
-
|
|
43276
|
-
|
|
43817
|
+
this.#publishNextBatch();
|
|
43818
|
+
};
|
|
43819
|
+
publishBatch = (sessionId, events) => {
|
|
43820
|
+
const critical = events.some(reservesSessionEventCapacity);
|
|
43821
|
+
this.#outbox.enqueueBatch(sessionId, events.map(encodeRecordedSessionEvent), critical);
|
|
43822
|
+
this.#publishNextBatch();
|
|
43823
|
+
};
|
|
43824
|
+
quarantine = (rejection) => {
|
|
43825
|
+
if (!this.#outbox.quarantine(rejection)) {
|
|
43277
43826
|
return;
|
|
43278
43827
|
}
|
|
43279
|
-
|
|
43280
|
-
|
|
43281
|
-
|
|
43282
|
-
kind: SESSION_EVENT_KIND,
|
|
43283
|
-
payload: encodeRecordedSessionEvent(event),
|
|
43284
|
-
sessionId
|
|
43285
|
-
})
|
|
43286
|
-
);
|
|
43287
|
-
} catch {
|
|
43288
|
-
this.#reportDrop();
|
|
43289
|
-
}
|
|
43828
|
+
this.#removeInFlight(rejection.eventId);
|
|
43829
|
+
console.error(`Mobius Relay rejected Session event ${rejection.eventId} with code ${rejection.code}`);
|
|
43830
|
+
this.#publishNextBatch();
|
|
43290
43831
|
};
|
|
43291
|
-
|
|
43292
|
-
this.#
|
|
43832
|
+
#clearInFlight = () => {
|
|
43833
|
+
this.#inFlight.clear();
|
|
43834
|
+
this.#inFlightBytes = 0;
|
|
43835
|
+
};
|
|
43836
|
+
#publishNextBatch = () => {
|
|
43837
|
+
if (this.#deferredReplay !== null || this.#connection.kind !== "connected") {
|
|
43838
|
+
return;
|
|
43839
|
+
}
|
|
43840
|
+
while (this.#inFlight.size < SESSION_EVENT_REPLAY_WINDOW) {
|
|
43841
|
+
const batch = this.#outbox.pending(SESSION_EVENT_REPLAY_WINDOW - this.#inFlight.size, [
|
|
43842
|
+
...this.#inFlight.keys()
|
|
43843
|
+
]);
|
|
43844
|
+
let sent = 0;
|
|
43845
|
+
for (const envelope2 of batch) {
|
|
43846
|
+
const encoded = encodeDaemonToServiceMessage(
|
|
43847
|
+
this.#connection.delivery === "reliable" ? envelope2 : {
|
|
43848
|
+
kind: envelope2.kind,
|
|
43849
|
+
payload: envelope2.payload,
|
|
43850
|
+
sessionId: envelope2.sessionId
|
|
43851
|
+
}
|
|
43852
|
+
);
|
|
43853
|
+
const byteLength = Buffer.byteLength(encoded, "utf8");
|
|
43854
|
+
if (this.#inFlightBytes + byteLength > SESSION_EVENT_REPLAY_BYTE_LIMIT) {
|
|
43855
|
+
return;
|
|
43856
|
+
}
|
|
43857
|
+
if (!this.#send(encoded)) {
|
|
43858
|
+
this.#clearInFlight();
|
|
43859
|
+
return;
|
|
43860
|
+
}
|
|
43861
|
+
if (this.#connection.delivery === "ephemeral") {
|
|
43862
|
+
this.#outbox.acknowledge({
|
|
43863
|
+
eventId: envelope2.delivery.eventId,
|
|
43864
|
+
kind: "session.event.ack",
|
|
43865
|
+
outcome: { kind: "relayed" },
|
|
43866
|
+
sessionId: envelope2.sessionId
|
|
43867
|
+
});
|
|
43868
|
+
sent += 1;
|
|
43869
|
+
continue;
|
|
43870
|
+
}
|
|
43871
|
+
this.#inFlight.set(envelope2.delivery.eventId, { byteLength });
|
|
43872
|
+
this.#inFlightBytes += byteLength;
|
|
43873
|
+
sent += 1;
|
|
43874
|
+
}
|
|
43875
|
+
if (sent === 0) {
|
|
43876
|
+
return;
|
|
43877
|
+
}
|
|
43878
|
+
}
|
|
43293
43879
|
};
|
|
43294
|
-
#
|
|
43295
|
-
|
|
43880
|
+
#removeInFlight = (eventId) => {
|
|
43881
|
+
const inFlight = this.#inFlight.get(eventId);
|
|
43882
|
+
if (inFlight === void 0) {
|
|
43296
43883
|
return;
|
|
43297
43884
|
}
|
|
43298
|
-
this.#
|
|
43299
|
-
|
|
43885
|
+
this.#inFlight.delete(eventId);
|
|
43886
|
+
this.#inFlightBytes -= inFlight.byteLength;
|
|
43887
|
+
};
|
|
43888
|
+
#send = (encoded) => {
|
|
43889
|
+
if (this.#connection.kind !== "connected" || this.#connection.socket.readyState !== WebSocket9.OPEN) {
|
|
43890
|
+
return false;
|
|
43891
|
+
}
|
|
43892
|
+
try {
|
|
43893
|
+
this.#connection.socket.send(encoded);
|
|
43894
|
+
return true;
|
|
43895
|
+
} catch {
|
|
43896
|
+
return false;
|
|
43897
|
+
}
|
|
43300
43898
|
};
|
|
43301
43899
|
};
|
|
43302
43900
|
|
|
@@ -43357,7 +43955,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
|
|
|
43357
43955
|
{
|
|
43358
43956
|
agentId: agent.id,
|
|
43359
43957
|
kind: AGENT_INSTALL_REQUEST_KIND,
|
|
43360
|
-
requestId: `automatic-integration-${
|
|
43958
|
+
requestId: `automatic-integration-${randomUUID8()}`
|
|
43361
43959
|
},
|
|
43362
43960
|
signal
|
|
43363
43961
|
);
|
|
@@ -43379,7 +43977,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
43379
43977
|
join18(stateDirectory, "sessions", `${createHash6("sha256").update(config2.channelId).digest("hex")}.sqlite`)
|
|
43380
43978
|
);
|
|
43381
43979
|
const operations = new DaemonOperationState();
|
|
43382
|
-
const
|
|
43980
|
+
const channelHash = createHash6("sha256").update(config2.channelId).digest("hex");
|
|
43981
|
+
const publisher = new DaemonSessionEventPublisher(
|
|
43982
|
+
new SessionEventOutbox(join18(stateDirectory, "events", `${channelHash}.sqlite`)),
|
|
43983
|
+
timer
|
|
43984
|
+
);
|
|
43383
43985
|
const activeTurns = new DaemonTurnRegistry(operations);
|
|
43384
43986
|
const recordSessionEvent = (sessionId, event) => {
|
|
43385
43987
|
publisher.publish(sessionId, activeTurns.recordEvent(event));
|