@moxt-ai/mobius 0.0.166 → 0.0.168
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-query-processes.d.ts +2 -1
- package/dist/acp/agent-query-processes.d.ts.map +1 -1
- package/dist/acp/agent-query-processes.js +6 -4
- package/dist/acp/agent-query-processes.js.map +1 -1
- package/dist/acp/agent-runtime-manager.d.ts +2 -1
- package/dist/acp/agent-runtime-manager.d.ts.map +1 -1
- package/dist/acp/agent-runtime-manager.js +11 -6
- package/dist/acp/agent-runtime-manager.js.map +1 -1
- package/dist/acp/agent-session.d.ts +3 -2
- package/dist/acp/agent-session.d.ts.map +1 -1
- package/dist/acp/agent-session.js +10 -7
- package/dist/acp/agent-session.js.map +1 -1
- package/dist/artifacts/local-file-streamer.d.ts +2 -1
- package/dist/artifacts/local-file-streamer.d.ts.map +1 -1
- package/dist/artifacts/local-file-streamer.js +6 -5
- package/dist/artifacts/local-file-streamer.js.map +1 -1
- package/dist/authorization/local-raster.d.ts +1 -0
- package/dist/authorization/local-raster.d.ts.map +1 -1
- package/dist/authorization/local-raster.js +1 -1
- package/dist/authorization/local-raster.js.map +1 -1
- package/dist/cli.js +565 -99
- package/dist/cli.js.map +4 -4
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/daemon-command-handler.d.ts +3 -1
- package/dist/daemon-command-handler.d.ts.map +1 -1
- package/dist/daemon-command-handler.js +2 -2
- package/dist/daemon-command-handler.js.map +1 -1
- package/dist/external-content/acp-content-externalizer.d.ts +12 -0
- package/dist/external-content/acp-content-externalizer.d.ts.map +1 -0
- package/dist/external-content/acp-content-externalizer.js +233 -0
- package/dist/external-content/acp-content-externalizer.js.map +1 -0
- package/dist/external-content/local-external-content-store.d.ts +34 -0
- package/dist/external-content/local-external-content-store.d.ts.map +1 -0
- package/dist/external-content/local-external-content-store.js +174 -0
- package/dist/external-content/local-external-content-store.js.map +1 -0
- package/dist/index.js +639 -179
- package/dist/index.js.map +4 -4
- package/dist/relay-connection/run-relay-connection.d.ts +3 -1
- package/dist/relay-connection/run-relay-connection.d.ts.map +1 -1
- package/dist/relay-connection/run-relay-connection.js +2 -1
- package/dist/relay-connection/run-relay-connection.js.map +1 -1
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +208 -140
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.d.ts +2 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +572 -111
- package/dist/runtime.js.map +4 -4
- package/package.json +16 -10
package/dist/runtime.js
CHANGED
|
@@ -5,7 +5,7 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/runtime.ts
|
|
8
|
-
import { mkdir as
|
|
8
|
+
import { mkdir as mkdir7, realpath as realpath11, stat as stat10 } from "node:fs/promises";
|
|
9
9
|
import { resolve as resolve8 } from "node:path";
|
|
10
10
|
|
|
11
11
|
// ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/external.js
|
|
@@ -21189,6 +21189,7 @@ var MAX_JSON_KEYS = 1e3;
|
|
|
21189
21189
|
var SESSION_EVENT_V2_KIND = "session.event.v2";
|
|
21190
21190
|
var boundedString = external_exports.string().max(MAX_CONTENT_LENGTH);
|
|
21191
21191
|
var shortString = external_exports.string().max(2048);
|
|
21192
|
+
var externalContentKeySchema = external_exports.string().regex(/^[a-f0-9]{64}$/u);
|
|
21192
21193
|
function boundedJsonIssue(value, depth = 0) {
|
|
21193
21194
|
if (depth > MAX_JSON_DEPTH) {
|
|
21194
21195
|
return "JSON nesting exceeds the maximum depth";
|
|
@@ -21256,6 +21257,30 @@ var imageContentSchema = external_exports.object({
|
|
|
21256
21257
|
uri: boundedString.nullable().optional()
|
|
21257
21258
|
}).readonly();
|
|
21258
21259
|
var audioContentSchema = external_exports.object({ ...contentFields, data: boundedString, mimeType: shortString, type: external_exports.literal("audio") }).readonly();
|
|
21260
|
+
var externalImageContentSchema = external_exports.strictObject({
|
|
21261
|
+
...contentFields,
|
|
21262
|
+
byteLength: external_exports.number().int().positive().safe(),
|
|
21263
|
+
imageKey: externalContentKeySchema,
|
|
21264
|
+
mimeType: shortString,
|
|
21265
|
+
type: external_exports.literal("external_image"),
|
|
21266
|
+
uri: boundedString.nullable().optional()
|
|
21267
|
+
}).readonly();
|
|
21268
|
+
var externalAudioContentSchema = external_exports.strictObject({
|
|
21269
|
+
...contentFields,
|
|
21270
|
+
audioKey: externalContentKeySchema,
|
|
21271
|
+
byteLength: external_exports.number().int().positive().safe(),
|
|
21272
|
+
mimeType: shortString,
|
|
21273
|
+
type: external_exports.literal("external_audio")
|
|
21274
|
+
}).readonly();
|
|
21275
|
+
var externalResourceContentSchema = external_exports.strictObject({
|
|
21276
|
+
...contentFields,
|
|
21277
|
+
byteLength: external_exports.number().int().positive().safe(),
|
|
21278
|
+
encoding: external_exports.enum(["binary", "text"]),
|
|
21279
|
+
mimeType: shortString.nullable().optional(),
|
|
21280
|
+
resourceKey: externalContentKeySchema,
|
|
21281
|
+
type: external_exports.literal("external_resource"),
|
|
21282
|
+
uri: boundedString
|
|
21283
|
+
}).readonly();
|
|
21259
21284
|
var resourceLinkSchema = external_exports.object({
|
|
21260
21285
|
...contentFields,
|
|
21261
21286
|
description: boundedString.nullable().optional(),
|
|
@@ -21288,7 +21313,10 @@ var contentBlockV2Schema = external_exports.discriminatedUnion("type", [
|
|
|
21288
21313
|
imageContentSchema,
|
|
21289
21314
|
audioContentSchema,
|
|
21290
21315
|
resourceLinkSchema,
|
|
21291
|
-
embeddedResourceSchema
|
|
21316
|
+
embeddedResourceSchema,
|
|
21317
|
+
externalImageContentSchema,
|
|
21318
|
+
externalAudioContentSchema,
|
|
21319
|
+
externalResourceContentSchema
|
|
21292
21320
|
]);
|
|
21293
21321
|
var toolCallContentSchema = external_exports.discriminatedUnion("type", [
|
|
21294
21322
|
external_exports.object({ _meta: optionalMetadata, content: contentBlockV2Schema, type: external_exports.literal("content") }).readonly(),
|
|
@@ -27183,8 +27211,8 @@ function createDaemonConfig(connection, agents = [], installableAgents = [], loc
|
|
|
27183
27211
|
}
|
|
27184
27212
|
|
|
27185
27213
|
// src/run-daemon.ts
|
|
27186
|
-
import { createHash as
|
|
27187
|
-
import { join as
|
|
27214
|
+
import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
|
|
27215
|
+
import { join as join18 } from "node:path";
|
|
27188
27216
|
import { styleText } from "node:util";
|
|
27189
27217
|
|
|
27190
27218
|
// src/acp/active-executions.ts
|
|
@@ -30556,7 +30584,7 @@ function sql(strings, ...params) {
|
|
|
30556
30584
|
return new SQL([new StringChunk(str)]);
|
|
30557
30585
|
}
|
|
30558
30586
|
sql2.raw = raw;
|
|
30559
|
-
function
|
|
30587
|
+
function join20(chunks, separator) {
|
|
30560
30588
|
const result = [];
|
|
30561
30589
|
for (const [i, chunk] of chunks.entries()) {
|
|
30562
30590
|
if (i > 0 && separator !== void 0) {
|
|
@@ -30566,7 +30594,7 @@ function sql(strings, ...params) {
|
|
|
30566
30594
|
}
|
|
30567
30595
|
return new SQL(result);
|
|
30568
30596
|
}
|
|
30569
|
-
sql2.join =
|
|
30597
|
+
sql2.join = join20;
|
|
30570
30598
|
function identifier(value) {
|
|
30571
30599
|
return new Name(value);
|
|
30572
30600
|
}
|
|
@@ -33110,7 +33138,7 @@ var SQLiteSelectQueryBuilderBase = class extends TypedQueryBuilder {
|
|
|
33110
33138
|
const baseTableName = this.tableName;
|
|
33111
33139
|
const tableName = getTableLikeName(table);
|
|
33112
33140
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
33113
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
33141
|
+
if (typeof tableName === "string" && this.config.joins?.some((join20) => join20.alias === tableName)) {
|
|
33114
33142
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
33115
33143
|
}
|
|
33116
33144
|
if (!this.isPartialSelect) {
|
|
@@ -33969,7 +33997,7 @@ var SQLiteUpdateBase = class extends QueryPromise {
|
|
|
33969
33997
|
createJoin(joinType) {
|
|
33970
33998
|
return (table, on) => {
|
|
33971
33999
|
const tableName = getTableLikeName(table);
|
|
33972
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
34000
|
+
if (typeof tableName === "string" && this.config.joins.some((join20) => join20.alias === tableName)) {
|
|
33973
34001
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
33974
34002
|
}
|
|
33975
34003
|
if (typeof on === "function") {
|
|
@@ -35292,6 +35320,7 @@ function recordsEqual(left, right) {
|
|
|
35292
35320
|
}
|
|
35293
35321
|
var AgentSession = class _AgentSession {
|
|
35294
35322
|
#connection;
|
|
35323
|
+
#contentExternalizer;
|
|
35295
35324
|
#interactions;
|
|
35296
35325
|
#additionalDirectories;
|
|
35297
35326
|
#agentId;
|
|
@@ -35319,7 +35348,7 @@ var AgentSession = class _AgentSession {
|
|
|
35319
35348
|
#sessionTitle = null;
|
|
35320
35349
|
#sessionUpdatedAt = "";
|
|
35321
35350
|
#turn = new IdleAcpTurn();
|
|
35322
|
-
constructor(agent, cwd, additionalDirectories, mobiusSessionId, getObserver, store, metrics) {
|
|
35351
|
+
constructor(agent, cwd, additionalDirectories, mobiusSessionId, getObserver, store, metrics, contentExternalizer) {
|
|
35323
35352
|
this.#updates = new AgentUpdateStream((notification) => this.#processUpdate(notification));
|
|
35324
35353
|
this.#additionalDirectories = [...additionalDirectories];
|
|
35325
35354
|
this.#agentId = agent.id;
|
|
@@ -35339,8 +35368,9 @@ var AgentSession = class _AgentSession {
|
|
|
35339
35368
|
observer: getObserver
|
|
35340
35369
|
});
|
|
35341
35370
|
this.#connection = new AgentConnection(agent, cwd, this);
|
|
35371
|
+
this.#contentExternalizer = contentExternalizer;
|
|
35342
35372
|
}
|
|
35343
|
-
static async #start(options, getObserver, store, initialize, metrics) {
|
|
35373
|
+
static async #start(options, getObserver, store, initialize, metrics, contentExternalizer) {
|
|
35344
35374
|
for (let attempt = 1; attempt <= 2; attempt += 1) {
|
|
35345
35375
|
options.signal.throwIfAborted();
|
|
35346
35376
|
const unchanged = await metrics.measure(
|
|
@@ -35368,7 +35398,8 @@ var AgentSession = class _AgentSession {
|
|
|
35368
35398
|
options.sessionId,
|
|
35369
35399
|
getObserver,
|
|
35370
35400
|
store,
|
|
35371
|
-
metrics
|
|
35401
|
+
metrics,
|
|
35402
|
+
contentExternalizer
|
|
35372
35403
|
)
|
|
35373
35404
|
);
|
|
35374
35405
|
try {
|
|
@@ -35391,19 +35422,21 @@ var AgentSession = class _AgentSession {
|
|
|
35391
35422
|
}
|
|
35392
35423
|
throw new AcpExecutionError("ACP agent initialization failed");
|
|
35393
35424
|
}
|
|
35394
|
-
static start = async (options, getObserver, store, metrics
|
|
35425
|
+
static start = async (options, getObserver, store, metrics, contentExternalizer) => await _AgentSession.#start(
|
|
35395
35426
|
options,
|
|
35396
35427
|
getObserver,
|
|
35397
35428
|
store,
|
|
35398
35429
|
async (runtime) => await runtime.initialize(options.signal, options.origin),
|
|
35399
|
-
metrics
|
|
35430
|
+
metrics,
|
|
35431
|
+
contentExternalizer
|
|
35400
35432
|
);
|
|
35401
|
-
static startNativeSessionBrowser = async (options, getObserver, store) => await _AgentSession.#start(
|
|
35433
|
+
static startNativeSessionBrowser = async (options, getObserver, store, contentExternalizer) => await _AgentSession.#start(
|
|
35402
35434
|
options,
|
|
35403
35435
|
getObserver,
|
|
35404
35436
|
store,
|
|
35405
35437
|
async (runtime) => await runtime.#initializeAgent(options.signal),
|
|
35406
|
-
unmeasuredOperationMetrics
|
|
35438
|
+
unmeasuredOperationMetrics,
|
|
35439
|
+
contentExternalizer
|
|
35407
35440
|
);
|
|
35408
35441
|
belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId && this.#cwd === cwd && arraysEqual(this.#additionalDirectories, additionalDirectories);
|
|
35409
35442
|
usesEnvironment = (environment) => recordsEqual(this.#environment, environment);
|
|
@@ -36107,8 +36140,13 @@ var AgentSession = class _AgentSession {
|
|
|
36107
36140
|
};
|
|
36108
36141
|
#processUpdate = async (notification) => {
|
|
36109
36142
|
this.assertNativeSession(notification.sessionId);
|
|
36110
|
-
const
|
|
36111
|
-
|
|
36143
|
+
const externalized = await this.#contentExternalizer.update(
|
|
36144
|
+
this.#mobiusSessionId,
|
|
36145
|
+
notification.update,
|
|
36146
|
+
AbortSignal.timeout(3e4)
|
|
36147
|
+
);
|
|
36148
|
+
const update = externalized.agent;
|
|
36149
|
+
const rawUpdate = decodeAcpSessionUpdateV2(JSON.stringify(externalized.event));
|
|
36112
36150
|
if (this.#sessionLoad.kind === "capturing") {
|
|
36113
36151
|
await this.#sessionLoad.history.record(update, rawUpdate);
|
|
36114
36152
|
} else {
|
|
@@ -36395,8 +36433,10 @@ var AgentQueryProcesses = class {
|
|
|
36395
36433
|
#processes;
|
|
36396
36434
|
#observer = new NullAcpSessionObserver();
|
|
36397
36435
|
#store = new MemoryAcpSessionStore();
|
|
36398
|
-
|
|
36436
|
+
#contentExternalizer;
|
|
36437
|
+
constructor(processes, contentExternalizer) {
|
|
36399
36438
|
this.#processes = processes;
|
|
36439
|
+
this.#contentExternalizer = contentExternalizer;
|
|
36400
36440
|
this.#processesByQuery = new RetainedAgentProcesses({
|
|
36401
36441
|
touch: processes.touch,
|
|
36402
36442
|
changed: processes.notifyChanged
|
|
@@ -36412,7 +36452,12 @@ var AgentQueryProcesses = class {
|
|
|
36412
36452
|
async #startRetained(options) {
|
|
36413
36453
|
const runtime = await this.#processes.startRetained(
|
|
36414
36454
|
options.signal,
|
|
36415
|
-
() => AgentSession.startNativeSessionBrowser(
|
|
36455
|
+
() => AgentSession.startNativeSessionBrowser(
|
|
36456
|
+
options,
|
|
36457
|
+
() => this.#observer,
|
|
36458
|
+
this.#store,
|
|
36459
|
+
this.#contentExternalizer
|
|
36460
|
+
),
|
|
36416
36461
|
{
|
|
36417
36462
|
isBusy: () => this.#processesByQuery.isBusy(options.sessionId),
|
|
36418
36463
|
retire: (runtime2) => this.retire(options.sessionId, runtime2)
|
|
@@ -36488,7 +36533,8 @@ var AgentQueryProcesses = class {
|
|
|
36488
36533
|
async () => await AgentSession.startNativeSessionBrowser(
|
|
36489
36534
|
options,
|
|
36490
36535
|
() => this.#observer,
|
|
36491
|
-
new MemoryAcpSessionStore()
|
|
36536
|
+
new MemoryAcpSessionStore(),
|
|
36537
|
+
this.#contentExternalizer
|
|
36492
36538
|
),
|
|
36493
36539
|
async (runtime) => {
|
|
36494
36540
|
runtime.selectNativeSession(nativeSessionId);
|
|
@@ -36503,7 +36549,8 @@ var AgentQueryProcesses = class {
|
|
|
36503
36549
|
async () => await AgentSession.startNativeSessionBrowser(
|
|
36504
36550
|
options,
|
|
36505
36551
|
() => this.#observer,
|
|
36506
|
-
new MemoryAcpSessionStore()
|
|
36552
|
+
new MemoryAcpSessionStore(),
|
|
36553
|
+
this.#contentExternalizer
|
|
36507
36554
|
),
|
|
36508
36555
|
async (runtime) => {
|
|
36509
36556
|
runtime.selectNativeSession(nativeSessionId);
|
|
@@ -36519,6 +36566,393 @@ var AgentQueryProcesses = class {
|
|
|
36519
36566
|
};
|
|
36520
36567
|
};
|
|
36521
36568
|
|
|
36569
|
+
// src/external-content/acp-content-externalizer.ts
|
|
36570
|
+
var MAXIMUM_ENCODED_CONTENT_CHARACTERS = 4e6;
|
|
36571
|
+
function decodeBase64(data) {
|
|
36572
|
+
if (data.length > MAXIMUM_ENCODED_CONTENT_CHARACTERS || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/u.test(data)) {
|
|
36573
|
+
throw new Error("The ACP embedded content is not valid bounded base64");
|
|
36574
|
+
}
|
|
36575
|
+
const bytes = Buffer.from(data, "base64");
|
|
36576
|
+
if (bytes.toString("base64") !== data) {
|
|
36577
|
+
throw new Error("The ACP embedded content is not canonical base64");
|
|
36578
|
+
}
|
|
36579
|
+
return bytes;
|
|
36580
|
+
}
|
|
36581
|
+
var embeddedImageSchema = external_exports.looseObject({
|
|
36582
|
+
type: external_exports.literal("image"),
|
|
36583
|
+
data: external_exports.string(),
|
|
36584
|
+
mimeType: external_exports.string()
|
|
36585
|
+
});
|
|
36586
|
+
function isRecord8(value) {
|
|
36587
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36588
|
+
}
|
|
36589
|
+
var AcpContentExternalizer = class {
|
|
36590
|
+
#store;
|
|
36591
|
+
constructor(store) {
|
|
36592
|
+
this.#store = store;
|
|
36593
|
+
}
|
|
36594
|
+
async #content(sessionId, content, signal) {
|
|
36595
|
+
switch (content.type) {
|
|
36596
|
+
case "text":
|
|
36597
|
+
case "resource_link":
|
|
36598
|
+
return { agent: content, event: content };
|
|
36599
|
+
case "image": {
|
|
36600
|
+
if (content.data.length === 0) {
|
|
36601
|
+
return { agent: content, event: content };
|
|
36602
|
+
}
|
|
36603
|
+
try {
|
|
36604
|
+
const bytes = decodeBase64(content.data);
|
|
36605
|
+
if (sniffRasterMime(bytes) !== content.mimeType) {
|
|
36606
|
+
throw new Error("Embedded image bytes do not match a supported image MIME type");
|
|
36607
|
+
}
|
|
36608
|
+
const stored = await this.#store.put({
|
|
36609
|
+
bytes,
|
|
36610
|
+
kind: "image",
|
|
36611
|
+
mediaType: content.mimeType,
|
|
36612
|
+
name: "image",
|
|
36613
|
+
sessionId,
|
|
36614
|
+
signal
|
|
36615
|
+
});
|
|
36616
|
+
return {
|
|
36617
|
+
agent: { ...content, data: "", uri: `mobius-content:image:${stored.key}` },
|
|
36618
|
+
event: {
|
|
36619
|
+
_meta: content._meta,
|
|
36620
|
+
annotations: content.annotations,
|
|
36621
|
+
byteLength: stored.byteLength,
|
|
36622
|
+
imageKey: stored.key,
|
|
36623
|
+
mimeType: content.mimeType,
|
|
36624
|
+
type: "external_image",
|
|
36625
|
+
uri: content.uri
|
|
36626
|
+
}
|
|
36627
|
+
};
|
|
36628
|
+
} catch {
|
|
36629
|
+
signal.throwIfAborted();
|
|
36630
|
+
const unavailable = { type: "text", text: "[Image unavailable]" };
|
|
36631
|
+
return { agent: unavailable, event: unavailable };
|
|
36632
|
+
}
|
|
36633
|
+
}
|
|
36634
|
+
case "audio": {
|
|
36635
|
+
if (content.data.length === 0) {
|
|
36636
|
+
return { agent: content, event: content };
|
|
36637
|
+
}
|
|
36638
|
+
const stored = await this.#store.put({
|
|
36639
|
+
bytes: decodeBase64(content.data),
|
|
36640
|
+
kind: "audio",
|
|
36641
|
+
mediaType: content.mimeType,
|
|
36642
|
+
name: "audio",
|
|
36643
|
+
sessionId,
|
|
36644
|
+
signal
|
|
36645
|
+
});
|
|
36646
|
+
return {
|
|
36647
|
+
agent: content,
|
|
36648
|
+
event: {
|
|
36649
|
+
_meta: content._meta,
|
|
36650
|
+
annotations: content.annotations,
|
|
36651
|
+
audioKey: stored.key,
|
|
36652
|
+
byteLength: stored.byteLength,
|
|
36653
|
+
mimeType: content.mimeType,
|
|
36654
|
+
type: "external_audio"
|
|
36655
|
+
}
|
|
36656
|
+
};
|
|
36657
|
+
}
|
|
36658
|
+
case "resource": {
|
|
36659
|
+
const embedded = content.resource;
|
|
36660
|
+
const encoding = "text" in embedded ? "text" : "binary";
|
|
36661
|
+
const bytes = "text" in embedded ? Buffer.from(embedded.text, "utf8") : decodeBase64(embedded.blob);
|
|
36662
|
+
if (bytes.byteLength === 0) {
|
|
36663
|
+
return { agent: content, event: content };
|
|
36664
|
+
}
|
|
36665
|
+
const mediaType = embedded.mimeType ?? "application/octet-stream";
|
|
36666
|
+
const stored = await this.#store.put({
|
|
36667
|
+
bytes,
|
|
36668
|
+
kind: "resource",
|
|
36669
|
+
mediaType,
|
|
36670
|
+
name: "resource",
|
|
36671
|
+
sessionId,
|
|
36672
|
+
signal
|
|
36673
|
+
});
|
|
36674
|
+
return {
|
|
36675
|
+
agent: content,
|
|
36676
|
+
event: {
|
|
36677
|
+
_meta: content._meta,
|
|
36678
|
+
annotations: content.annotations,
|
|
36679
|
+
byteLength: stored.byteLength,
|
|
36680
|
+
encoding,
|
|
36681
|
+
mimeType: embedded.mimeType,
|
|
36682
|
+
resourceKey: stored.key,
|
|
36683
|
+
type: "external_resource",
|
|
36684
|
+
uri: embedded.uri
|
|
36685
|
+
}
|
|
36686
|
+
};
|
|
36687
|
+
}
|
|
36688
|
+
}
|
|
36689
|
+
}
|
|
36690
|
+
async #rawOutput(sessionId, value, images, signal, depth = 0) {
|
|
36691
|
+
signal.throwIfAborted();
|
|
36692
|
+
if (depth > 16) {
|
|
36693
|
+
throw new Error("ACP tool output exceeds the maximum nesting depth");
|
|
36694
|
+
}
|
|
36695
|
+
if (Array.isArray(value)) {
|
|
36696
|
+
const result2 = [];
|
|
36697
|
+
for (const item of value) {
|
|
36698
|
+
result2.push(await this.#rawOutput(sessionId, item, images, signal, depth + 1));
|
|
36699
|
+
}
|
|
36700
|
+
return result2;
|
|
36701
|
+
}
|
|
36702
|
+
if (!isRecord8(value)) {
|
|
36703
|
+
return value;
|
|
36704
|
+
}
|
|
36705
|
+
const image = embeddedImageSchema.safeParse(value);
|
|
36706
|
+
if (image.success && image.data.data.length > 0) {
|
|
36707
|
+
const prepared = await this.#content(sessionId, image.data, signal);
|
|
36708
|
+
if (isRecord8(prepared.event) && typeof prepared.event["imageKey"] === "string") {
|
|
36709
|
+
images.set(prepared.event["imageKey"], prepared);
|
|
36710
|
+
} else {
|
|
36711
|
+
images.set(`unavailable:${images.size}`, prepared);
|
|
36712
|
+
}
|
|
36713
|
+
return prepared.event;
|
|
36714
|
+
}
|
|
36715
|
+
const result = {};
|
|
36716
|
+
for (const [key, item] of Object.entries(value)) {
|
|
36717
|
+
result[key] = await this.#rawOutput(sessionId, item, images, signal, depth + 1);
|
|
36718
|
+
}
|
|
36719
|
+
return result;
|
|
36720
|
+
}
|
|
36721
|
+
async #toolUpdate(sessionId, update, signal) {
|
|
36722
|
+
const images = /* @__PURE__ */ new Map();
|
|
36723
|
+
const rawOutput = update.rawOutput === void 0 ? void 0 : await this.#rawOutput(sessionId, update.rawOutput, images, signal);
|
|
36724
|
+
const originalJson = images.size === 0 ? void 0 : JSON.stringify(update.rawOutput);
|
|
36725
|
+
const rewrittenJson = images.size === 0 ? void 0 : JSON.stringify(rawOutput);
|
|
36726
|
+
const agentContent = [];
|
|
36727
|
+
const eventContent = [];
|
|
36728
|
+
for (const item of update.content ?? []) {
|
|
36729
|
+
if (item.type !== "content") {
|
|
36730
|
+
agentContent.push(item);
|
|
36731
|
+
eventContent.push(item);
|
|
36732
|
+
continue;
|
|
36733
|
+
}
|
|
36734
|
+
const content = item.content.type === "text" && item.content.text === originalJson && rewrittenJson !== void 0 ? { ...item.content, text: rewrittenJson } : item.content;
|
|
36735
|
+
const prepared = await this.#content(sessionId, content, signal);
|
|
36736
|
+
agentContent.push({ ...item, content: prepared.agent });
|
|
36737
|
+
eventContent.push({ ...item, content: prepared.event });
|
|
36738
|
+
if (isRecord8(prepared.event) && typeof prepared.event["imageKey"] === "string") {
|
|
36739
|
+
images.delete(prepared.event["imageKey"]);
|
|
36740
|
+
}
|
|
36741
|
+
}
|
|
36742
|
+
for (const prepared of images.values()) {
|
|
36743
|
+
agentContent.push({ type: "content", content: prepared.agent });
|
|
36744
|
+
eventContent.push({ type: "content", content: prepared.event });
|
|
36745
|
+
}
|
|
36746
|
+
const output2 = update.rawOutput === void 0 ? {} : { rawOutput };
|
|
36747
|
+
const hasContent = update.content !== void 0 && update.content !== null || agentContent.length > 0;
|
|
36748
|
+
return {
|
|
36749
|
+
agent: { ...update, ...output2, ...hasContent ? { content: agentContent } : {} },
|
|
36750
|
+
event: { ...update, ...output2, ...hasContent ? { content: eventContent } : {} }
|
|
36751
|
+
};
|
|
36752
|
+
}
|
|
36753
|
+
update = async (sessionId, update, signal) => {
|
|
36754
|
+
switch (update.sessionUpdate) {
|
|
36755
|
+
case "user_message_chunk":
|
|
36756
|
+
case "agent_message_chunk":
|
|
36757
|
+
case "agent_thought_chunk":
|
|
36758
|
+
case "compaction_summary_chunk": {
|
|
36759
|
+
const content = await this.#content(sessionId, update.content, signal);
|
|
36760
|
+
return {
|
|
36761
|
+
agent: { ...update, content: content.agent },
|
|
36762
|
+
event: { ...update, content: content.event }
|
|
36763
|
+
};
|
|
36764
|
+
}
|
|
36765
|
+
case "tool_call":
|
|
36766
|
+
case "tool_call_update":
|
|
36767
|
+
return await this.#toolUpdate(sessionId, update, signal);
|
|
36768
|
+
case "compaction_update": {
|
|
36769
|
+
if (update.summary === void 0 || update.summary === null) {
|
|
36770
|
+
return { agent: update, event: update };
|
|
36771
|
+
}
|
|
36772
|
+
const content = await Promise.all(
|
|
36773
|
+
update.summary.map(async (item) => await this.#content(sessionId, item, signal))
|
|
36774
|
+
);
|
|
36775
|
+
return {
|
|
36776
|
+
agent: { ...update, summary: content.map((item) => item.agent) },
|
|
36777
|
+
event: { ...update, summary: content.map((item) => item.event) }
|
|
36778
|
+
};
|
|
36779
|
+
}
|
|
36780
|
+
case "plan":
|
|
36781
|
+
case "plan_update":
|
|
36782
|
+
case "plan_removed":
|
|
36783
|
+
case "available_commands_update":
|
|
36784
|
+
case "current_mode_update":
|
|
36785
|
+
case "config_option_update":
|
|
36786
|
+
case "session_info_update":
|
|
36787
|
+
case "usage_update":
|
|
36788
|
+
return { agent: update, event: update };
|
|
36789
|
+
}
|
|
36790
|
+
};
|
|
36791
|
+
};
|
|
36792
|
+
|
|
36793
|
+
// src/external-content/local-external-content-store.ts
|
|
36794
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
36795
|
+
import { lstat, mkdir as mkdir4, readdir as readdir2, realpath as realpath7, rename as rename3, rm as rm3, stat as stat6, utimes, writeFile as writeFile3 } from "node:fs/promises";
|
|
36796
|
+
import { dirname as dirname4, join as join15 } from "node:path";
|
|
36797
|
+
var contentRequest = /^mobius-content:(image|audio|resource):([a-f0-9]{64})$/u;
|
|
36798
|
+
var CONTENT_LIFETIME_MILLISECONDS = 24 * 60 * 60 * 1e3;
|
|
36799
|
+
var metadataSchema2 = external_exports.strictObject({
|
|
36800
|
+
kind: external_exports.enum(["image", "audio", "resource"]),
|
|
36801
|
+
mediaType: external_exports.string().min(1).max(2048).regex(/^[\u0020-\u007e]+$/u),
|
|
36802
|
+
name: external_exports.string().min(1).max(500)
|
|
36803
|
+
});
|
|
36804
|
+
var UnretainedExternalContentStore = class {
|
|
36805
|
+
put = async ({ bytes, signal }) => {
|
|
36806
|
+
signal.throwIfAborted();
|
|
36807
|
+
return { byteLength: bytes.byteLength, key: createHash2("sha256").update(bytes).digest("hex") };
|
|
36808
|
+
};
|
|
36809
|
+
resolve = (_sessionId, _request, signal) => {
|
|
36810
|
+
signal.throwIfAborted();
|
|
36811
|
+
return Promise.resolve(null);
|
|
36812
|
+
};
|
|
36813
|
+
};
|
|
36814
|
+
async function atomicWrite(path2, bytes, signal) {
|
|
36815
|
+
const temporary = `${path2}.${randomUUID()}.tmp`;
|
|
36816
|
+
try {
|
|
36817
|
+
await writeFile3(temporary, bytes, { mode: 384, signal });
|
|
36818
|
+
signal.throwIfAborted();
|
|
36819
|
+
await rename3(temporary, path2);
|
|
36820
|
+
} finally {
|
|
36821
|
+
await rm3(temporary, { force: true });
|
|
36822
|
+
}
|
|
36823
|
+
}
|
|
36824
|
+
var LocalExternalContentStore = class {
|
|
36825
|
+
#root;
|
|
36826
|
+
#entries = /* @__PURE__ */ new Map();
|
|
36827
|
+
#operations = /* @__PURE__ */ new Set();
|
|
36828
|
+
#lifetime = new AbortController();
|
|
36829
|
+
#expirationTimer;
|
|
36830
|
+
#cleanup = Promise.resolve();
|
|
36831
|
+
constructor(stateDirectory) {
|
|
36832
|
+
this.#root = join15(stateDirectory, "tmp", "session-content", randomUUID());
|
|
36833
|
+
this.#expirationTimer = setInterval(() => {
|
|
36834
|
+
void this.#expire().catch(() => void 0);
|
|
36835
|
+
}, 6e4);
|
|
36836
|
+
this.#expirationTimer.unref();
|
|
36837
|
+
}
|
|
36838
|
+
#expire = () => {
|
|
36839
|
+
this.#cleanup = this.#cleanup.catch(() => void 0).then(async () => {
|
|
36840
|
+
await mkdir4(this.#root, { mode: 448, recursive: true });
|
|
36841
|
+
const now = /* @__PURE__ */ new Date();
|
|
36842
|
+
await utimes(this.#root, now, now);
|
|
36843
|
+
for (const directory of await readdir2(dirname4(this.#root), { withFileTypes: true })) {
|
|
36844
|
+
if (!directory.isDirectory() || !/^[a-f0-9-]{36}$/u.test(directory.name)) {
|
|
36845
|
+
continue;
|
|
36846
|
+
}
|
|
36847
|
+
const path2 = join15(dirname4(this.#root), directory.name);
|
|
36848
|
+
if (path2 === this.#root) {
|
|
36849
|
+
continue;
|
|
36850
|
+
}
|
|
36851
|
+
const modified = await stat6(path2).then(
|
|
36852
|
+
(entry) => entry.mtimeMs,
|
|
36853
|
+
() => Date.now()
|
|
36854
|
+
);
|
|
36855
|
+
if (modified + CONTENT_LIFETIME_MILLISECONDS <= Date.now()) {
|
|
36856
|
+
await rm3(path2, { force: true, recursive: true });
|
|
36857
|
+
}
|
|
36858
|
+
}
|
|
36859
|
+
for (const [request, entry] of this.#entries) {
|
|
36860
|
+
if (entry.expiresAt > Date.now()) {
|
|
36861
|
+
continue;
|
|
36862
|
+
}
|
|
36863
|
+
await rm3(entry.path, { force: true });
|
|
36864
|
+
this.#entries.delete(request);
|
|
36865
|
+
}
|
|
36866
|
+
});
|
|
36867
|
+
return this.#cleanup;
|
|
36868
|
+
};
|
|
36869
|
+
#track = async (operation) => {
|
|
36870
|
+
this.#lifetime.signal.throwIfAborted();
|
|
36871
|
+
const pending = operation();
|
|
36872
|
+
this.#operations.add(pending);
|
|
36873
|
+
try {
|
|
36874
|
+
return await pending;
|
|
36875
|
+
} finally {
|
|
36876
|
+
this.#operations.delete(pending);
|
|
36877
|
+
}
|
|
36878
|
+
};
|
|
36879
|
+
put = (input2) => this.#track(() => this.#put(input2));
|
|
36880
|
+
#put = async ({ bytes, kind, mediaType, name, sessionId, signal }) => {
|
|
36881
|
+
const active = AbortSignal.any([signal, this.#lifetime.signal]);
|
|
36882
|
+
active.throwIfAborted();
|
|
36883
|
+
const metadata = metadataSchema2.parse({ kind, mediaType, name });
|
|
36884
|
+
const key = createHash2("sha256").update(bytes).digest("hex");
|
|
36885
|
+
const request = `mobius-content:${kind}:${key}`;
|
|
36886
|
+
const existing = this.#entries.get(request);
|
|
36887
|
+
if (existing !== void 0 && existing.expiresAt > Date.now()) {
|
|
36888
|
+
this.#entries.set(request, {
|
|
36889
|
+
...existing,
|
|
36890
|
+
expiresAt: Date.now() + CONTENT_LIFETIME_MILLISECONDS,
|
|
36891
|
+
sessions: /* @__PURE__ */ new Set([...existing.sessions, sessionId])
|
|
36892
|
+
});
|
|
36893
|
+
return { byteLength: existing.byteLength, key };
|
|
36894
|
+
}
|
|
36895
|
+
await this.#expire();
|
|
36896
|
+
active.throwIfAborted();
|
|
36897
|
+
const directory = join15(this.#root, kind);
|
|
36898
|
+
await mkdir4(directory, { mode: 448, recursive: true });
|
|
36899
|
+
active.throwIfAborted();
|
|
36900
|
+
const path2 = join15(directory, key);
|
|
36901
|
+
const write = atomicWrite(path2, bytes, active);
|
|
36902
|
+
await write;
|
|
36903
|
+
active.throwIfAborted();
|
|
36904
|
+
const retained = this.#entries.get(request);
|
|
36905
|
+
this.#entries.set(request, {
|
|
36906
|
+
byteLength: bytes.byteLength,
|
|
36907
|
+
expiresAt: Date.now() + CONTENT_LIFETIME_MILLISECONDS,
|
|
36908
|
+
mediaType: metadata.mediaType,
|
|
36909
|
+
name: metadata.name,
|
|
36910
|
+
path: path2,
|
|
36911
|
+
sessions: /* @__PURE__ */ new Set([...retained?.sessions ?? [], sessionId])
|
|
36912
|
+
});
|
|
36913
|
+
return { byteLength: bytes.byteLength, key };
|
|
36914
|
+
};
|
|
36915
|
+
resolve = (sessionId, request, signal) => this.#track(() => this.#resolve(sessionId, request, AbortSignal.any([signal, this.#lifetime.signal])));
|
|
36916
|
+
#resolve = async (sessionId, request, signal) => {
|
|
36917
|
+
signal.throwIfAborted();
|
|
36918
|
+
this.#lifetime.signal.throwIfAborted();
|
|
36919
|
+
if (!contentRequest.test(request)) {
|
|
36920
|
+
return null;
|
|
36921
|
+
}
|
|
36922
|
+
const entry = this.#entries.get(request);
|
|
36923
|
+
if (entry === void 0 || !entry.sessions.has(sessionId)) {
|
|
36924
|
+
return null;
|
|
36925
|
+
}
|
|
36926
|
+
if (entry.expiresAt <= Date.now()) {
|
|
36927
|
+
await this.#expire();
|
|
36928
|
+
signal.throwIfAborted();
|
|
36929
|
+
return null;
|
|
36930
|
+
}
|
|
36931
|
+
try {
|
|
36932
|
+
const [resolvedDirectory, resolvedPath, file2] = await Promise.all([
|
|
36933
|
+
realpath7(dirname4(entry.path)),
|
|
36934
|
+
realpath7(entry.path),
|
|
36935
|
+
lstat(entry.path)
|
|
36936
|
+
]);
|
|
36937
|
+
signal.throwIfAborted();
|
|
36938
|
+
if (!file2.isFile() || file2.isSymbolicLink() || dirname4(resolvedPath) !== resolvedDirectory) {
|
|
36939
|
+
return null;
|
|
36940
|
+
}
|
|
36941
|
+
return { mediaType: entry.mediaType, name: entry.name, path: resolvedPath };
|
|
36942
|
+
} catch {
|
|
36943
|
+
signal.throwIfAborted();
|
|
36944
|
+
return null;
|
|
36945
|
+
}
|
|
36946
|
+
};
|
|
36947
|
+
[Symbol.asyncDispose] = async () => {
|
|
36948
|
+
clearInterval(this.#expirationTimer);
|
|
36949
|
+
this.#lifetime.abort();
|
|
36950
|
+
await Promise.allSettled([...this.#operations, this.#cleanup]);
|
|
36951
|
+
this.#entries.clear();
|
|
36952
|
+
await rm3(this.#root, { force: true, recursive: true });
|
|
36953
|
+
};
|
|
36954
|
+
};
|
|
36955
|
+
|
|
36522
36956
|
// src/native-sessions/chat-agent.ts
|
|
36523
36957
|
function supportsNativeChat(agentId) {
|
|
36524
36958
|
return agentId === "codex" || agentId === "claude" || agentId === "opencode" || agentId === "pi";
|
|
@@ -36735,7 +37169,7 @@ var AgentRuntimeManager = class {
|
|
|
36735
37169
|
touch: this.#processes.touch,
|
|
36736
37170
|
changed: this.#processes.notifyChanged
|
|
36737
37171
|
});
|
|
36738
|
-
#queryProcesses
|
|
37172
|
+
#queryProcesses;
|
|
36739
37173
|
#executions = new ActiveExecutions();
|
|
36740
37174
|
#agentSettingsObserver = new NullAcpSessionObserver();
|
|
36741
37175
|
#nativeOperations = /* @__PURE__ */ new Set();
|
|
@@ -36743,13 +37177,16 @@ var AgentRuntimeManager = class {
|
|
|
36743
37177
|
#nativeHistoryReader;
|
|
36744
37178
|
#sessionIdentity;
|
|
36745
37179
|
#onSessionStatusChanged;
|
|
37180
|
+
#contentExternalizer;
|
|
36746
37181
|
#observer;
|
|
36747
|
-
constructor(observer = new NullAcpSessionObserver(), store = new MemoryAcpSessionStore(), nativeHistoryReader = null, sessionIdentity = "assigned", onSessionStatusChanged = () => void 0) {
|
|
37182
|
+
constructor(observer = new NullAcpSessionObserver(), store = new MemoryAcpSessionStore(), nativeHistoryReader = null, sessionIdentity = "assigned", onSessionStatusChanged = () => void 0, contentExternalizer = new AcpContentExternalizer(new UnretainedExternalContentStore())) {
|
|
36748
37183
|
this.#observer = observer;
|
|
36749
37184
|
this.#store = store;
|
|
36750
37185
|
this.#nativeHistoryReader = nativeHistoryReader;
|
|
36751
37186
|
this.#sessionIdentity = sessionIdentity;
|
|
36752
37187
|
this.#onSessionStatusChanged = onSessionStatusChanged;
|
|
37188
|
+
this.#contentExternalizer = contentExternalizer;
|
|
37189
|
+
this.#queryProcesses = new AgentQueryProcesses(this.#processes, contentExternalizer);
|
|
36753
37190
|
}
|
|
36754
37191
|
setObserver = (observer) => {
|
|
36755
37192
|
this.#observer = observer;
|
|
@@ -36790,7 +37227,8 @@ var AgentRuntimeManager = class {
|
|
|
36790
37227
|
options.origin === void 0 && this.#sessionIdentity === "native" && isNativeChatSessionId(options.agent.id, options.sessionId) && this.#store.read(options.sessionId) instanceof MissingAcpStoredSession ? { ...options, origin: { kind: "import", nativeSessionId: options.sessionId } } : options,
|
|
36791
37228
|
() => this.#observer,
|
|
36792
37229
|
this.#store,
|
|
36793
|
-
metrics
|
|
37230
|
+
metrics,
|
|
37231
|
+
this.#contentExternalizer
|
|
36794
37232
|
)
|
|
36795
37233
|
);
|
|
36796
37234
|
});
|
|
@@ -36805,7 +37243,13 @@ var AgentRuntimeManager = class {
|
|
|
36805
37243
|
this.#store.remove(options.sessionId);
|
|
36806
37244
|
return await this.#startRetainedSessionProcess(
|
|
36807
37245
|
options,
|
|
36808
|
-
async () => await AgentSession.start(
|
|
37246
|
+
async () => await AgentSession.start(
|
|
37247
|
+
options,
|
|
37248
|
+
() => this.#observer,
|
|
37249
|
+
this.#store,
|
|
37250
|
+
metrics,
|
|
37251
|
+
this.#contentExternalizer
|
|
37252
|
+
)
|
|
36809
37253
|
);
|
|
36810
37254
|
});
|
|
36811
37255
|
}
|
|
@@ -36815,7 +37259,13 @@ var AgentRuntimeManager = class {
|
|
|
36815
37259
|
await this.#retireSessionProcess(options.sessionId, existing, async () => await existing.close());
|
|
36816
37260
|
const runtime = await this.#startRetainedSessionProcess(
|
|
36817
37261
|
options,
|
|
36818
|
-
async () => await AgentSession.start(
|
|
37262
|
+
async () => await AgentSession.start(
|
|
37263
|
+
options,
|
|
37264
|
+
() => this.#observer,
|
|
37265
|
+
this.#store,
|
|
37266
|
+
unmeasuredOperationMetrics,
|
|
37267
|
+
this.#contentExternalizer
|
|
37268
|
+
)
|
|
36819
37269
|
);
|
|
36820
37270
|
try {
|
|
36821
37271
|
for (const desired of desiredConfigOptions) {
|
|
@@ -36911,7 +37361,9 @@ var AgentRuntimeManager = class {
|
|
|
36911
37361
|
sessionId: `agent-settings-${crypto.randomUUID()}`
|
|
36912
37362
|
},
|
|
36913
37363
|
() => this.#agentSettingsObserver,
|
|
36914
|
-
new MemoryAcpSessionStore()
|
|
37364
|
+
new MemoryAcpSessionStore(),
|
|
37365
|
+
unmeasuredOperationMetrics,
|
|
37366
|
+
this.#contentExternalizer
|
|
36915
37367
|
),
|
|
36916
37368
|
async (runtime) => {
|
|
36917
37369
|
const prepared = runtime.prepared();
|
|
@@ -37420,7 +37872,7 @@ var AgentCatalogPublishError = class extends Error {
|
|
|
37420
37872
|
this.name = "AgentCatalogPublishError";
|
|
37421
37873
|
}
|
|
37422
37874
|
};
|
|
37423
|
-
function
|
|
37875
|
+
function isRecord9(value) {
|
|
37424
37876
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37425
37877
|
}
|
|
37426
37878
|
function isSafeRelayErrorMessage(value) {
|
|
@@ -37433,7 +37885,7 @@ async function rejectedCatalogError(response) {
|
|
|
37433
37885
|
} catch {
|
|
37434
37886
|
return new AgentCatalogPublishError("The Relay rejected the Agent catalog update");
|
|
37435
37887
|
}
|
|
37436
|
-
if (!
|
|
37888
|
+
if (!isRecord9(value) || !isRecord9(value["error"])) {
|
|
37437
37889
|
return new AgentCatalogPublishError("The Relay rejected the Agent catalog update");
|
|
37438
37890
|
}
|
|
37439
37891
|
const code = value["error"]["code"];
|
|
@@ -37964,9 +38416,9 @@ var FixedInstallationExecutor = class {
|
|
|
37964
38416
|
};
|
|
37965
38417
|
|
|
37966
38418
|
// src/authorization/workspace-directory.ts
|
|
37967
|
-
import { readdir as
|
|
38419
|
+
import { readdir as readdir3, realpath as realpath8, stat as stat7 } from "node:fs/promises";
|
|
37968
38420
|
import { homedir as homedir2 } from "node:os";
|
|
37969
|
-
import { basename as basename3, dirname as
|
|
38421
|
+
import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute9, join as join16, normalize as normalize3, relative as relative4 } from "node:path";
|
|
37970
38422
|
|
|
37971
38423
|
// src/authorization/local-authorization-error.ts
|
|
37972
38424
|
var LocalAuthorizationError = class extends Error {
|
|
@@ -38045,9 +38497,9 @@ var WorkspaceDirectoryService = class {
|
|
|
38045
38497
|
throw new LocalAuthorizationError("The local directory path is invalid");
|
|
38046
38498
|
}
|
|
38047
38499
|
try {
|
|
38048
|
-
const target = await
|
|
38500
|
+
const target = await realpath8(requested);
|
|
38049
38501
|
signal.throwIfAborted();
|
|
38050
|
-
const metadata = await
|
|
38502
|
+
const metadata = await stat7(target);
|
|
38051
38503
|
signal.throwIfAborted();
|
|
38052
38504
|
if (!isAbsolute9(target) || normalize3(target) !== target || !metadata.isDirectory()) {
|
|
38053
38505
|
throw new LocalAuthorizationError("The selected location is not a directory");
|
|
@@ -38084,7 +38536,7 @@ var WorkspaceDirectoryService = class {
|
|
|
38084
38536
|
list = async (bindingId, id, signal) => {
|
|
38085
38537
|
const target = await this.resolve(bindingId, id, signal);
|
|
38086
38538
|
try {
|
|
38087
|
-
const children = await
|
|
38539
|
+
const children = await readdir3(target, { withFileTypes: true });
|
|
38088
38540
|
signal.throwIfAborted();
|
|
38089
38541
|
const entries = [];
|
|
38090
38542
|
for (const child2 of children) {
|
|
@@ -38095,7 +38547,7 @@ var WorkspaceDirectoryService = class {
|
|
|
38095
38547
|
continue;
|
|
38096
38548
|
}
|
|
38097
38549
|
try {
|
|
38098
|
-
const path2 = await this.resolvePath(
|
|
38550
|
+
const path2 = await this.resolvePath(join16(target, child2.name), signal);
|
|
38099
38551
|
entries.push({ directoryId: encodePath(path2), name: child2.name });
|
|
38100
38552
|
} catch (cause) {
|
|
38101
38553
|
signal.throwIfAborted();
|
|
@@ -38105,7 +38557,7 @@ var WorkspaceDirectoryService = class {
|
|
|
38105
38557
|
}
|
|
38106
38558
|
}
|
|
38107
38559
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
38108
|
-
const parent =
|
|
38560
|
+
const parent = dirname5(target);
|
|
38109
38561
|
return new WorkspaceDirectoryListing(
|
|
38110
38562
|
id,
|
|
38111
38563
|
this.label(target),
|
|
@@ -38131,15 +38583,15 @@ var WorkspaceDirectoryService = class {
|
|
|
38131
38583
|
|
|
38132
38584
|
// src/daemon-diagnostic-log.ts
|
|
38133
38585
|
import { appendFileSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, statSync as statSync3, writeFileSync } from "node:fs";
|
|
38134
|
-
import { join as
|
|
38586
|
+
import { join as join17 } from "node:path";
|
|
38135
38587
|
var MAXIMUM_DAEMON_LOG_BYTES = 1 * 1024 * 1024;
|
|
38136
38588
|
var DaemonDiagnosticLog = class {
|
|
38137
38589
|
#directory;
|
|
38138
38590
|
#path;
|
|
38139
38591
|
#maximumBytes;
|
|
38140
38592
|
constructor(stateDirectory, maximumBytes = MAXIMUM_DAEMON_LOG_BYTES) {
|
|
38141
|
-
this.#directory =
|
|
38142
|
-
this.#path =
|
|
38593
|
+
this.#directory = join17(stateDirectory, "logs");
|
|
38594
|
+
this.#path = join17(this.#directory, "daemon.log");
|
|
38143
38595
|
this.#maximumBytes = maximumBytes;
|
|
38144
38596
|
}
|
|
38145
38597
|
record = (diagnostic) => {
|
|
@@ -38184,7 +38636,7 @@ import { WebSocket as WebSocket2 } from "undici";
|
|
|
38184
38636
|
import { WebSocket } from "undici";
|
|
38185
38637
|
|
|
38186
38638
|
// src/prompt-artifact-resolver.ts
|
|
38187
|
-
import { createHash as
|
|
38639
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
38188
38640
|
import { fetch as fetch3 } from "undici";
|
|
38189
38641
|
var ARTIFACT_SCHEME = "mobius-artifact:";
|
|
38190
38642
|
var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
@@ -38322,7 +38774,7 @@ async function download(config2, command, reference, signal) {
|
|
|
38322
38774
|
);
|
|
38323
38775
|
}
|
|
38324
38776
|
const bytes = await responseBytes(response, reference.byteLength, requestSignal);
|
|
38325
|
-
if (
|
|
38777
|
+
if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
|
|
38326
38778
|
throw new PromptArtifactError(
|
|
38327
38779
|
"artifact_integrity_failed",
|
|
38328
38780
|
"The prompt artifact failed integrity validation"
|
|
@@ -38627,7 +39079,7 @@ var DaemonInstallationObserver = class {
|
|
|
38627
39079
|
};
|
|
38628
39080
|
|
|
38629
39081
|
// src/daemon-active-turn.ts
|
|
38630
|
-
import { randomUUID } from "node:crypto";
|
|
39082
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
38631
39083
|
function activeMessageCharacters(message) {
|
|
38632
39084
|
return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
|
|
38633
39085
|
}
|
|
@@ -38661,7 +39113,7 @@ var ActiveDaemonTurn = class {
|
|
|
38661
39113
|
#timeline;
|
|
38662
39114
|
#sequence = 0;
|
|
38663
39115
|
#interaction = null;
|
|
38664
|
-
#epoch = decodeIdentifier(
|
|
39116
|
+
#epoch = decodeIdentifier(randomUUID2());
|
|
38665
39117
|
constructor(command, attemptId) {
|
|
38666
39118
|
this.attemptId = attemptId;
|
|
38667
39119
|
this.command = command;
|
|
@@ -38723,7 +39175,7 @@ var ActiveDaemonTurn = class {
|
|
|
38723
39175
|
if (!this.#activities.has(event.activityId)) {
|
|
38724
39176
|
this.#timeline = [
|
|
38725
39177
|
...this.#timeline,
|
|
38726
|
-
{ activityId: event.activityId, id: decodeIdentifier(
|
|
39178
|
+
{ activityId: event.activityId, id: decodeIdentifier(randomUUID2()), kind: "activity" }
|
|
38727
39179
|
];
|
|
38728
39180
|
}
|
|
38729
39181
|
this.#activities.set(event.activityId, {
|
|
@@ -38744,7 +39196,7 @@ var ActiveDaemonTurn = class {
|
|
|
38744
39196
|
if (previous === void 0) {
|
|
38745
39197
|
this.#timeline = [
|
|
38746
39198
|
...this.#timeline,
|
|
38747
|
-
{ activityId: event.activityId, id: decodeIdentifier(
|
|
39199
|
+
{ activityId: event.activityId, id: decodeIdentifier(randomUUID2()), kind: "activity" }
|
|
38748
39200
|
];
|
|
38749
39201
|
}
|
|
38750
39202
|
this.#activities.set(event.activityId, {
|
|
@@ -38769,7 +39221,7 @@ var ActiveDaemonTurn = class {
|
|
|
38769
39221
|
...this.#timeline,
|
|
38770
39222
|
{
|
|
38771
39223
|
content: /* @__PURE__ */ new Map([[event.contentId, event.content]]),
|
|
38772
|
-
id: decodeIdentifier(
|
|
39224
|
+
id: decodeIdentifier(randomUUID2()),
|
|
38773
39225
|
kind: "message",
|
|
38774
39226
|
sourceMessageId: event.messageId,
|
|
38775
39227
|
text: ""
|
|
@@ -38809,7 +39261,7 @@ var ActiveDaemonTurn = class {
|
|
|
38809
39261
|
...this.#timeline,
|
|
38810
39262
|
{
|
|
38811
39263
|
content: /* @__PURE__ */ new Map(),
|
|
38812
|
-
id: decodeIdentifier(
|
|
39264
|
+
id: decodeIdentifier(randomUUID2()),
|
|
38813
39265
|
kind: "message",
|
|
38814
39266
|
sourceMessageId: messageId,
|
|
38815
39267
|
text: remaining.slice(0, ACTIVE_TURN_TEXT_CHUNK_LIMIT)
|
|
@@ -39785,7 +40237,7 @@ var readCodexFullHistory = async (agent, cwd, nativeSessionId, signal, nativeTur
|
|
|
39785
40237
|
});
|
|
39786
40238
|
|
|
39787
40239
|
// src/native-sessions/service.ts
|
|
39788
|
-
import { randomUUID as
|
|
40240
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
39789
40241
|
import { basename as basename4 } from "node:path";
|
|
39790
40242
|
|
|
39791
40243
|
// src/native-sessions/acp-history.ts
|
|
@@ -40000,7 +40452,7 @@ var NativeSessionService = class {
|
|
|
40000
40452
|
if (authorized === null) {
|
|
40001
40453
|
return null;
|
|
40002
40454
|
}
|
|
40003
|
-
const entryId = decodeIdentifier(
|
|
40455
|
+
const entryId = decodeIdentifier(randomUUID3());
|
|
40004
40456
|
if (this.#entries.size >= 5e3) {
|
|
40005
40457
|
this.#entries.clear();
|
|
40006
40458
|
}
|
|
@@ -40056,7 +40508,7 @@ var NativeSessionService = class {
|
|
|
40056
40508
|
"invalid_native_session_response"
|
|
40057
40509
|
);
|
|
40058
40510
|
}
|
|
40059
|
-
nextCursor = decodeIdentifier(
|
|
40511
|
+
nextCursor = decodeIdentifier(randomUUID3());
|
|
40060
40512
|
if (this.#cursors.size >= 500) {
|
|
40061
40513
|
this.#cursors.clear();
|
|
40062
40514
|
}
|
|
@@ -40338,7 +40790,7 @@ var NativeSessionService = class {
|
|
|
40338
40790
|
};
|
|
40339
40791
|
|
|
40340
40792
|
// src/relay-connection/daemon-operation-state.ts
|
|
40341
|
-
import { createHash as
|
|
40793
|
+
import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
|
|
40342
40794
|
var MAX_TERMINAL_RECEIPTS = 1024;
|
|
40343
40795
|
function isTerminal(state) {
|
|
40344
40796
|
return state === "succeeded" || state === "failed" || state === "cancelled";
|
|
@@ -40347,7 +40799,7 @@ var DaemonOperationState = class {
|
|
|
40347
40799
|
#executions = /* @__PURE__ */ new Map();
|
|
40348
40800
|
#terminalCount = 0;
|
|
40349
40801
|
claimExecution = (commandId, sessionId, commandJson) => {
|
|
40350
|
-
const commandHash =
|
|
40802
|
+
const commandHash = createHash4("sha256").update(commandJson).digest("hex");
|
|
40351
40803
|
const existing = this.#executions.get(commandId);
|
|
40352
40804
|
if (existing !== void 0) {
|
|
40353
40805
|
if (existing.sessionId !== sessionId || existing.commandHash !== commandHash) {
|
|
@@ -40355,7 +40807,7 @@ var DaemonOperationState = class {
|
|
|
40355
40807
|
}
|
|
40356
40808
|
return { attemptId: existing.attemptId, commandId, kind: "duplicate", state: existing.state };
|
|
40357
40809
|
}
|
|
40358
|
-
const attemptId =
|
|
40810
|
+
const attemptId = randomUUID4();
|
|
40359
40811
|
this.#executions.set(commandId, { attemptId, commandHash, sessionId, state: "dispatching" });
|
|
40360
40812
|
return { attemptId, commandId, kind: "accepted", state: "dispatching" };
|
|
40361
40813
|
};
|
|
@@ -40691,7 +41143,7 @@ function createAgentCatalogRefreshHandler(dependencies) {
|
|
|
40691
41143
|
import { WebSocket as WebSocket4 } from "undici";
|
|
40692
41144
|
|
|
40693
41145
|
// src/agent-catalog/discover-agent-settings.ts
|
|
40694
|
-
import { createHash as
|
|
41146
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
40695
41147
|
|
|
40696
41148
|
// src/agent-catalog/agent-settings-base.ts
|
|
40697
41149
|
var AgentSettingsConfigurationError = class extends Error {
|
|
@@ -41155,7 +41607,7 @@ function settingsRevision(agent, reportedAgentVersion, settings, modelEffort) {
|
|
|
41155
41607
|
unsupportedModelIds: modelEffort.unsupportedModelIds,
|
|
41156
41608
|
valuesByModel: {}
|
|
41157
41609
|
};
|
|
41158
|
-
return
|
|
41610
|
+
return createHash5("sha256").update(
|
|
41159
41611
|
JSON.stringify({
|
|
41160
41612
|
adapterVersion: agent.kind === "acp-adapter-process" ? agent.adapterVersion : agent.agentVersion,
|
|
41161
41613
|
agentId: agent.id,
|
|
@@ -41306,7 +41758,7 @@ function createAgentSettingsDiscoveryHandler(dependencies) {
|
|
|
41306
41758
|
|
|
41307
41759
|
// src/artifacts/local-file-streamer.ts
|
|
41308
41760
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
41309
|
-
import { realpath as
|
|
41761
|
+
import { realpath as realpath9, stat as stat8 } from "node:fs/promises";
|
|
41310
41762
|
import { basename as basename5, isAbsolute as isAbsolute10, normalize as normalize4, resolve as resolve5 } from "node:path";
|
|
41311
41763
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
41312
41764
|
var CHUNK_BYTES = 192 * 1024;
|
|
@@ -41334,7 +41786,7 @@ async function resolveFile(value, workingDirectory, signal) {
|
|
|
41334
41786
|
return null;
|
|
41335
41787
|
}
|
|
41336
41788
|
try {
|
|
41337
|
-
const target = await
|
|
41789
|
+
const target = await realpath9(requested);
|
|
41338
41790
|
signal.throwIfAborted();
|
|
41339
41791
|
return isAbsolute10(target) && normalize4(target) === target ? target : null;
|
|
41340
41792
|
} catch {
|
|
@@ -41342,23 +41794,24 @@ async function resolveFile(value, workingDirectory, signal) {
|
|
|
41342
41794
|
return null;
|
|
41343
41795
|
}
|
|
41344
41796
|
}
|
|
41345
|
-
async function streamLocalFile(command, send2, signal, workingDirectory) {
|
|
41346
|
-
const
|
|
41797
|
+
async function streamLocalFile(command, send2, signal, workingDirectory, externalContent) {
|
|
41798
|
+
const external = await externalContent.resolve(command.sessionId, command.path, signal);
|
|
41799
|
+
const target = external?.path ?? await resolveFile(command.path, workingDirectory, signal);
|
|
41347
41800
|
if (target === null) {
|
|
41348
41801
|
throw new Error("The local file is unavailable");
|
|
41349
41802
|
}
|
|
41350
|
-
const before = await
|
|
41803
|
+
const before = await stat8(target);
|
|
41351
41804
|
signal.throwIfAborted();
|
|
41352
41805
|
if (!before.isFile() || before.size < 1 || before.size > command.maxBytes) {
|
|
41353
41806
|
throw new Error("The local file is too large to read");
|
|
41354
41807
|
}
|
|
41355
|
-
const raster = await readLocalRaster(target, signal);
|
|
41808
|
+
const raster = external === null ? await readLocalRaster(target, signal) : null;
|
|
41356
41809
|
send2({
|
|
41357
41810
|
byteLength: before.size,
|
|
41358
41811
|
kind: FILE_BEGIN_KIND,
|
|
41359
|
-
mediaType: raster?.mimeType ?? "application/octet-stream",
|
|
41812
|
+
mediaType: external?.mediaType ?? raster?.mimeType ?? "application/octet-stream",
|
|
41360
41813
|
modifiedAt: before.mtime.toISOString(),
|
|
41361
|
-
name: basename5(target) || "file",
|
|
41814
|
+
name: external?.name ?? (basename5(target) || "file"),
|
|
41362
41815
|
requestId: command.requestId,
|
|
41363
41816
|
sessionId: command.sessionId
|
|
41364
41817
|
});
|
|
@@ -41375,7 +41828,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
|
|
|
41375
41828
|
});
|
|
41376
41829
|
sequence += 1;
|
|
41377
41830
|
}
|
|
41378
|
-
const after = await
|
|
41831
|
+
const after = await stat8(target);
|
|
41379
41832
|
signal.throwIfAborted();
|
|
41380
41833
|
if (after.size !== before.size || after.mtimeMs !== before.mtimeMs) {
|
|
41381
41834
|
throw new Error("The local file changed during transfer");
|
|
@@ -41388,7 +41841,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
|
|
|
41388
41841
|
}
|
|
41389
41842
|
|
|
41390
41843
|
// src/daemon-history-commands.ts
|
|
41391
|
-
import { createHash as
|
|
41844
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
41392
41845
|
|
|
41393
41846
|
// src/authorization/resolve-session-directories.ts
|
|
41394
41847
|
import { basename as basename6 } from "node:path";
|
|
@@ -41782,7 +42235,7 @@ async function executeSessionLiveHistoryPageLoad(socket, command, config2, direc
|
|
|
41782
42235
|
}
|
|
41783
42236
|
function replayEvent(sessionId, position, update) {
|
|
41784
42237
|
const encoded = JSON.stringify(update);
|
|
41785
|
-
const eventId = `native-${
|
|
42238
|
+
const eventId = `native-${createHash6("sha256").update(sessionId).update(":").update(position.toString()).update(":").update(encoded).digest("hex")}`;
|
|
41786
42239
|
return {
|
|
41787
42240
|
eventId,
|
|
41788
42241
|
payload: update,
|
|
@@ -41865,7 +42318,7 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
|
|
|
41865
42318
|
}
|
|
41866
42319
|
|
|
41867
42320
|
// src/acp/session-config/apply-session-configuration.ts
|
|
41868
|
-
import { randomUUID as
|
|
42321
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
41869
42322
|
function invalidSessionConfiguration(message) {
|
|
41870
42323
|
return new AcpExecutionError(message, {}, "invalid_session_configuration");
|
|
41871
42324
|
}
|
|
@@ -42006,7 +42459,7 @@ async function applySessionConfigurationSelection(sessions, audit, options, sele
|
|
|
42006
42459
|
booleanValue: selection.booleanValue,
|
|
42007
42460
|
configId: selection.configId,
|
|
42008
42461
|
cwd,
|
|
42009
|
-
requestId: `cfg_${
|
|
42462
|
+
requestId: `cfg_${randomUUID5()}`,
|
|
42010
42463
|
sessionId,
|
|
42011
42464
|
signal,
|
|
42012
42465
|
value: selection.value,
|
|
@@ -42680,6 +43133,7 @@ function createDaemonCommandHandler({
|
|
|
42680
43133
|
operations,
|
|
42681
43134
|
publisher,
|
|
42682
43135
|
eventLogV2,
|
|
43136
|
+
externalContent,
|
|
42683
43137
|
activeTurns,
|
|
42684
43138
|
diagnostics,
|
|
42685
43139
|
socket,
|
|
@@ -42788,7 +43242,8 @@ function createDaemonCommandHandler({
|
|
|
42788
43242
|
command2,
|
|
42789
43243
|
(message2) => send(socket, message2),
|
|
42790
43244
|
signal,
|
|
42791
|
-
sessions.findSessions([command2.sessionId])[0]?.cwd ?? null
|
|
43245
|
+
sessions.findSessions([command2.sessionId])[0]?.cwd ?? null,
|
|
43246
|
+
externalContent
|
|
42792
43247
|
).catch((error62) => {
|
|
42793
43248
|
if (socket.readyState !== WebSocket6.OPEN || signal.aborted) {
|
|
42794
43249
|
return;
|
|
@@ -43127,7 +43582,7 @@ function connectRelay(url2, signal) {
|
|
|
43127
43582
|
}
|
|
43128
43583
|
|
|
43129
43584
|
// src/relay-connection/liveness.ts
|
|
43130
|
-
import { randomUUID as
|
|
43585
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
43131
43586
|
var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
|
|
43132
43587
|
var HEARTBEAT_INTERVAL_MILLISECONDS = 2e4;
|
|
43133
43588
|
var RelayLivenessState = class {
|
|
@@ -43216,7 +43671,7 @@ var RelayConnectionLiveness = class {
|
|
|
43216
43671
|
}
|
|
43217
43672
|
throw new Error("Heartbeat was scheduled in an invalid state");
|
|
43218
43673
|
}
|
|
43219
|
-
const heartbeatId =
|
|
43674
|
+
const heartbeatId = randomUUID6();
|
|
43220
43675
|
this.#state = new AwaitingHeartbeatAckState(
|
|
43221
43676
|
heartbeatId,
|
|
43222
43677
|
this.#timer.schedule(this.#handleTimeout, HEARTBEAT_ACK_TIMEOUT_MILLISECONDS)
|
|
@@ -43256,6 +43711,7 @@ async function runRelayConnection({
|
|
|
43256
43711
|
operations,
|
|
43257
43712
|
publisher,
|
|
43258
43713
|
eventLogV2,
|
|
43714
|
+
externalContent,
|
|
43259
43715
|
activeTurns,
|
|
43260
43716
|
connectionEpoch,
|
|
43261
43717
|
diagnostics,
|
|
@@ -43279,6 +43735,7 @@ async function runRelayConnection({
|
|
|
43279
43735
|
operations,
|
|
43280
43736
|
publisher,
|
|
43281
43737
|
eventLogV2,
|
|
43738
|
+
externalContent,
|
|
43282
43739
|
activeTurns,
|
|
43283
43740
|
diagnostics,
|
|
43284
43741
|
socket,
|
|
@@ -43757,7 +44214,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
|
|
|
43757
44214
|
{
|
|
43758
44215
|
agentId: agent.id,
|
|
43759
44216
|
kind: AGENT_INSTALL_REQUEST_KIND,
|
|
43760
|
-
requestId: `automatic-integration-${
|
|
44217
|
+
requestId: `automatic-integration-${randomUUID7()}`
|
|
43761
44218
|
},
|
|
43762
44219
|
signal
|
|
43763
44220
|
);
|
|
@@ -43776,8 +44233,9 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
43776
44233
|
stateDirectory
|
|
43777
44234
|
});
|
|
43778
44235
|
const sessionStore = new SqliteAcpSessionStore(
|
|
43779
|
-
|
|
44236
|
+
join18(stateDirectory, "sessions", `${createHash7("sha256").update(config2.channelId).digest("hex")}.sqlite`)
|
|
43780
44237
|
);
|
|
44238
|
+
await using externalContent = new LocalExternalContentStore(stateDirectory);
|
|
43781
44239
|
const operations = new DaemonOperationState();
|
|
43782
44240
|
const publisher = new DaemonSessionEventPublisher(sessionStore);
|
|
43783
44241
|
const eventLogV2 = new DaemonSessionEventLogV2(publisher, sessionStore);
|
|
@@ -43798,7 +44256,8 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
43798
44256
|
)).history : null
|
|
43799
44257
|
},
|
|
43800
44258
|
"native",
|
|
43801
|
-
publisher.publishStatus
|
|
44259
|
+
publisher.publishStatus,
|
|
44260
|
+
new AcpContentExternalizer(externalContent)
|
|
43802
44261
|
);
|
|
43803
44262
|
const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
|
|
43804
44263
|
const installationObserver = new DaemonInstallationObserver();
|
|
@@ -43912,6 +44371,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
43912
44371
|
operations,
|
|
43913
44372
|
publisher,
|
|
43914
44373
|
eventLogV2,
|
|
44374
|
+
externalContent,
|
|
43915
44375
|
activeTurns,
|
|
43916
44376
|
connectionEpoch,
|
|
43917
44377
|
diagnostics,
|
|
@@ -43968,15 +44428,15 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
|
|
|
43968
44428
|
}
|
|
43969
44429
|
|
|
43970
44430
|
// src/pairing/pair-local-machine.ts
|
|
43971
|
-
import { mkdir as
|
|
44431
|
+
import { mkdir as mkdir6, realpath as realpath10, stat as stat9 } from "node:fs/promises";
|
|
43972
44432
|
import { hostname as hostname3 } from "node:os";
|
|
43973
44433
|
import { basename as basename7, resolve as resolve7 } from "node:path";
|
|
43974
44434
|
import { fetch as fetch4 } from "undici";
|
|
43975
44435
|
|
|
43976
44436
|
// src/storage/runtime-installation-store.ts
|
|
43977
|
-
import { createHash as
|
|
43978
|
-
import { mkdir as
|
|
43979
|
-
import { dirname as
|
|
44437
|
+
import { createHash as createHash8, randomUUID as randomUUID8 } from "node:crypto";
|
|
44438
|
+
import { mkdir as mkdir5, open as open5, readdir as readdir4, rename as rename4, unlink, writeFile as writeFile4 } from "node:fs/promises";
|
|
44439
|
+
import { dirname as dirname6, join as join19, resolve as resolve6 } from "node:path";
|
|
43980
44440
|
var APPLICATION_ID_PATTERN = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+){1,31}$/;
|
|
43981
44441
|
var CONNECTION_ID_PATTERN = /^mcn_[a-f0-9]{32}$/;
|
|
43982
44442
|
var INSTALLATION_ID_PATTERN = /^min_[a-f0-9]{32}$/;
|
|
@@ -44040,7 +44500,7 @@ var VerifiedRuntimeConnection = class {
|
|
|
44040
44500
|
this.runtimeId = runtimeId;
|
|
44041
44501
|
}
|
|
44042
44502
|
};
|
|
44043
|
-
function
|
|
44503
|
+
function isRecord10(value) {
|
|
44044
44504
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44045
44505
|
}
|
|
44046
44506
|
function hasExactKeys(value, expectedKeys) {
|
|
@@ -44104,16 +44564,16 @@ function parseRelayOrigin(value) {
|
|
|
44104
44564
|
return origin;
|
|
44105
44565
|
}
|
|
44106
44566
|
function connectionId() {
|
|
44107
|
-
return `mcn_${
|
|
44567
|
+
return `mcn_${randomUUID8().replaceAll("-", "")}`;
|
|
44108
44568
|
}
|
|
44109
44569
|
function installationId() {
|
|
44110
|
-
return `min_${
|
|
44570
|
+
return `min_${randomUUID8().replaceAll("-", "")}`;
|
|
44111
44571
|
}
|
|
44112
44572
|
function channelIndexFileName(channelId) {
|
|
44113
|
-
return `mci_${
|
|
44573
|
+
return `mci_${createHash8("sha256").update(channelId).digest("hex")}.json`;
|
|
44114
44574
|
}
|
|
44115
44575
|
function decodeInstallationPointer(value) {
|
|
44116
|
-
if (!
|
|
44576
|
+
if (!isRecord10(value) || !hasExactKeys(value, INSTALLATION_POINTER_KEYS) || value["version"] !== 1) {
|
|
44117
44577
|
throw new RuntimeInstallationStoreError("invalid_installation", "The local installation record is invalid");
|
|
44118
44578
|
}
|
|
44119
44579
|
const storedInstallationId = value["installationId"];
|
|
@@ -44123,7 +44583,7 @@ function decodeInstallationPointer(value) {
|
|
|
44123
44583
|
return { installationId: validateInstallationId(storedInstallationId) };
|
|
44124
44584
|
}
|
|
44125
44585
|
function decodeChannelIndex(value) {
|
|
44126
|
-
if (!
|
|
44586
|
+
if (!isRecord10(value) || !hasExactKeys(value, CHANNEL_INDEX_KEYS) || value["version"] !== 1) {
|
|
44127
44587
|
throw new RuntimeInstallationStoreError("invalid_connection", "The saved Runtime connection is invalid");
|
|
44128
44588
|
}
|
|
44129
44589
|
const applicationId = value["applicationId"];
|
|
@@ -44173,7 +44633,7 @@ function decodeVerifiedConnection(value) {
|
|
|
44173
44633
|
);
|
|
44174
44634
|
}
|
|
44175
44635
|
function decodeConnection(value) {
|
|
44176
|
-
if (!
|
|
44636
|
+
if (!isRecord10(value)) {
|
|
44177
44637
|
throw new RuntimeInstallationStoreError("invalid_connection", "The saved Runtime connection is invalid");
|
|
44178
44638
|
}
|
|
44179
44639
|
return decodeVerifiedConnection(value);
|
|
@@ -44218,15 +44678,15 @@ async function readJsonFile(path2, signal, missingCode) {
|
|
|
44218
44678
|
}
|
|
44219
44679
|
async function writeJsonAtomically(path2, value, signal) {
|
|
44220
44680
|
signal.throwIfAborted();
|
|
44221
|
-
const directory =
|
|
44222
|
-
const temporaryPath =
|
|
44681
|
+
const directory = dirname6(path2);
|
|
44682
|
+
const temporaryPath = join19(directory, `.${randomUUID8()}.tmp`);
|
|
44223
44683
|
try {
|
|
44224
|
-
await
|
|
44684
|
+
await mkdir5(directory, { mode: 448, recursive: true });
|
|
44225
44685
|
signal.throwIfAborted();
|
|
44226
|
-
await
|
|
44686
|
+
await writeFile4(temporaryPath, `${JSON.stringify(value, null, 2)}
|
|
44227
44687
|
`, { flag: "wx", mode: 384 });
|
|
44228
44688
|
signal.throwIfAborted();
|
|
44229
|
-
await
|
|
44689
|
+
await rename4(temporaryPath, path2);
|
|
44230
44690
|
} catch (cause) {
|
|
44231
44691
|
await unlink(temporaryPath).catch(() => void 0);
|
|
44232
44692
|
signal.throwIfAborted();
|
|
@@ -44245,16 +44705,16 @@ var RuntimeInstallationStore = class _RuntimeInstallationStore {
|
|
|
44245
44705
|
this.applicationId = applicationId;
|
|
44246
44706
|
this.installationId = installationId2;
|
|
44247
44707
|
this.stateDirectory = stateDirectory;
|
|
44248
|
-
this.#channelDirectory =
|
|
44249
|
-
this.#connectionDirectory =
|
|
44708
|
+
this.#channelDirectory = join19(stateDirectory, "channels");
|
|
44709
|
+
this.#connectionDirectory = join19(stateDirectory, "connections");
|
|
44250
44710
|
}
|
|
44251
44711
|
static open = async (options, signal) => {
|
|
44252
44712
|
signal.throwIfAborted();
|
|
44253
44713
|
const applicationId = validateApplicationId(options.applicationId);
|
|
44254
44714
|
const rootDirectory = resolve6(options.stateDirectory);
|
|
44255
|
-
const applicationDirectory =
|
|
44715
|
+
const applicationDirectory = join19(rootDirectory, "installations", applicationId);
|
|
44256
44716
|
try {
|
|
44257
|
-
await
|
|
44717
|
+
await mkdir5(applicationDirectory, { mode: 448, recursive: true });
|
|
44258
44718
|
} catch (cause) {
|
|
44259
44719
|
throw new RuntimeInstallationStoreError(
|
|
44260
44720
|
"installation_unavailable",
|
|
@@ -44265,9 +44725,9 @@ var RuntimeInstallationStore = class _RuntimeInstallationStore {
|
|
|
44265
44725
|
);
|
|
44266
44726
|
}
|
|
44267
44727
|
const storedInstallationId = await readOrCreateInstallationId(applicationDirectory, signal);
|
|
44268
|
-
const stateDirectory =
|
|
44728
|
+
const stateDirectory = join19(applicationDirectory, storedInstallationId);
|
|
44269
44729
|
try {
|
|
44270
|
-
await
|
|
44730
|
+
await mkdir5(stateDirectory, { mode: 448, recursive: true });
|
|
44271
44731
|
} catch (cause) {
|
|
44272
44732
|
throw new RuntimeInstallationStoreError(
|
|
44273
44733
|
"installation_unavailable",
|
|
@@ -44280,8 +44740,8 @@ var RuntimeInstallationStore = class _RuntimeInstallationStore {
|
|
|
44280
44740
|
signal.throwIfAborted();
|
|
44281
44741
|
return new _RuntimeInstallationStore(applicationId, storedInstallationId, stateDirectory);
|
|
44282
44742
|
};
|
|
44283
|
-
connectionPath = (connectionId2) =>
|
|
44284
|
-
channelIndexPath = (channelId) =>
|
|
44743
|
+
connectionPath = (connectionId2) => join19(this.#connectionDirectory, `${validateConnectionId(connectionId2)}.json`);
|
|
44744
|
+
channelIndexPath = (channelId) => join19(this.#channelDirectory, channelIndexFileName(validateIdentifier(channelId, "invalid_channel_id")));
|
|
44285
44745
|
readConnection = async (connectionId2, signal) => {
|
|
44286
44746
|
const stored = decodeConnection(
|
|
44287
44747
|
await readJsonFile(this.connectionPath(connectionId2), signal, "connection_not_found")
|
|
@@ -44354,7 +44814,7 @@ var RuntimeInstallationStore = class _RuntimeInstallationStore {
|
|
|
44354
44814
|
signal.throwIfAborted();
|
|
44355
44815
|
let entries;
|
|
44356
44816
|
try {
|
|
44357
|
-
entries = await
|
|
44817
|
+
entries = await readdir4(this.#connectionDirectory);
|
|
44358
44818
|
} catch (cause) {
|
|
44359
44819
|
if (isNodeError(cause, "ENOENT")) {
|
|
44360
44820
|
return [];
|
|
@@ -44443,7 +44903,7 @@ var RuntimeInstallationStore = class _RuntimeInstallationStore {
|
|
|
44443
44903
|
};
|
|
44444
44904
|
};
|
|
44445
44905
|
async function readOrCreateInstallationId(applicationDirectory, signal) {
|
|
44446
|
-
const pointerPath =
|
|
44906
|
+
const pointerPath = join19(applicationDirectory, "current.json");
|
|
44447
44907
|
try {
|
|
44448
44908
|
return decodeInstallationPointer(await readJsonFile(pointerPath, signal, "installation_not_found")).installationId;
|
|
44449
44909
|
} catch (cause) {
|
|
@@ -44453,7 +44913,7 @@ async function readOrCreateInstallationId(applicationDirectory, signal) {
|
|
|
44453
44913
|
}
|
|
44454
44914
|
const candidate = installationId();
|
|
44455
44915
|
try {
|
|
44456
|
-
await
|
|
44916
|
+
await writeFile4(pointerPath, `${JSON.stringify({ installationId: candidate, version: 1 })}
|
|
44457
44917
|
`, {
|
|
44458
44918
|
flag: "wx",
|
|
44459
44919
|
mode: 384
|
|
@@ -44490,7 +44950,7 @@ var PairingClientError = class extends Error {
|
|
|
44490
44950
|
this.name = "PairingClientError";
|
|
44491
44951
|
}
|
|
44492
44952
|
};
|
|
44493
|
-
function
|
|
44953
|
+
function isRecord11(value) {
|
|
44494
44954
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44495
44955
|
}
|
|
44496
44956
|
function hasExactKeys2(value, expectedKeys) {
|
|
@@ -44537,9 +44997,9 @@ function validatePairingId(value) {
|
|
|
44537
44997
|
async function resolveDefaultWorkspace2(path2) {
|
|
44538
44998
|
const requestedWorkspace = resolve7(path2);
|
|
44539
44999
|
try {
|
|
44540
|
-
await
|
|
44541
|
-
const defaultWorkspace = await
|
|
44542
|
-
const metadata = await
|
|
45000
|
+
await mkdir6(requestedWorkspace, { recursive: true, mode: 448 });
|
|
45001
|
+
const defaultWorkspace = await realpath10(requestedWorkspace);
|
|
45002
|
+
const metadata = await stat9(defaultWorkspace);
|
|
44543
45003
|
if (!metadata.isDirectory()) {
|
|
44544
45004
|
throw new PairingClientError("invalid_workspace", "The default workspace is not a directory");
|
|
44545
45005
|
}
|
|
@@ -44568,9 +45028,9 @@ async function readJsonResponse(response) {
|
|
|
44568
45028
|
}
|
|
44569
45029
|
}
|
|
44570
45030
|
function readRelayError(value) {
|
|
44571
|
-
if (
|
|
45031
|
+
if (isRecord11(value)) {
|
|
44572
45032
|
const error62 = value["error"];
|
|
44573
|
-
if (
|
|
45033
|
+
if (isRecord11(error62)) {
|
|
44574
45034
|
const code = error62["code"];
|
|
44575
45035
|
const message = error62["message"];
|
|
44576
45036
|
if (typeof code === "string" && typeof message === "string") {
|
|
@@ -44581,7 +45041,7 @@ function readRelayError(value) {
|
|
|
44581
45041
|
return new PairingClientError("pairing_failed", "The relay could not pair this machine");
|
|
44582
45042
|
}
|
|
44583
45043
|
function decodePairingResponse(value, credentialField, expectedKeys) {
|
|
44584
|
-
if (!
|
|
45044
|
+
if (!isRecord11(value) || !hasExactKeys2(value, expectedKeys)) {
|
|
44585
45045
|
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
44586
45046
|
}
|
|
44587
45047
|
const appId = value["appId"];
|
|
@@ -44773,9 +45233,9 @@ function loadMobiusRuntimeConnection(environment = process.env) {
|
|
|
44773
45233
|
async function resolveWorkspace(path2) {
|
|
44774
45234
|
const requested = resolve8(path2);
|
|
44775
45235
|
try {
|
|
44776
|
-
await
|
|
44777
|
-
const resolved = await
|
|
44778
|
-
const metadata = await
|
|
45236
|
+
await mkdir7(requested, { recursive: true, mode: 448 });
|
|
45237
|
+
const resolved = await realpath11(requested);
|
|
45238
|
+
const metadata = await stat10(resolved);
|
|
44779
45239
|
if (!metadata.isDirectory()) {
|
|
44780
45240
|
throw new MobiusRuntimeConfigurationError("The Runtime workspace is not a directory");
|
|
44781
45241
|
}
|
|
@@ -44843,6 +45303,7 @@ var MobiusRuntimeEngine = class {
|
|
|
44843
45303
|
export {
|
|
44844
45304
|
DaemonLocalContext,
|
|
44845
45305
|
DaemonReconnectTarget,
|
|
45306
|
+
InProcessAcpAgentDefinition,
|
|
44846
45307
|
MobiusRuntimeConfigurationError,
|
|
44847
45308
|
MobiusRuntimeEngine,
|
|
44848
45309
|
OpaqueDaemonReconnectTarget,
|