chatroom-cli 1.98.3 → 1.98.4
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/index.js +399 -341
- package/dist/index.js.map +23 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -110259,49 +110259,6 @@ var init_file_content_subscription = __esm(() => {
|
|
|
110259
110259
|
init_daemon_services();
|
|
110260
110260
|
});
|
|
110261
110261
|
|
|
110262
|
-
// ../../services/backend/src/domain/workspace-file-tree/types.ts
|
|
110263
|
-
var MAX_TREE_JSON_BYTES;
|
|
110264
|
-
var init_types2 = __esm(() => {
|
|
110265
|
-
MAX_TREE_JSON_BYTES = 900 * 1024;
|
|
110266
|
-
});
|
|
110267
|
-
// ../../services/backend/src/domain/workspace-file-tree/select-strategy.ts
|
|
110268
|
-
function treeJsonByteLength(tree) {
|
|
110269
|
-
return Buffer.byteLength(JSON.stringify(tree), "utf8");
|
|
110270
|
-
}
|
|
110271
|
-
function selectFileTreeSnapshotStrategyId(tree) {
|
|
110272
|
-
return treeJsonByteLength(tree) > MAX_TREE_JSON_BYTES ? "sharded" : "blob";
|
|
110273
|
-
}
|
|
110274
|
-
var init_select_strategy = __esm(() => {
|
|
110275
|
-
init_types2();
|
|
110276
|
-
});
|
|
110277
|
-
|
|
110278
|
-
// ../../services/backend/src/domain/workspace-file-tree/registry.ts
|
|
110279
|
-
var init_registry5 = __esm(() => {
|
|
110280
|
-
init_select_strategy();
|
|
110281
|
-
});
|
|
110282
|
-
// ../../services/backend/src/domain/workspace-file-tree/transport/blob-snapshot.ts
|
|
110283
|
-
function toLegacyBlobSyncArgs(payload) {
|
|
110284
|
-
return { data: payload.data, dataHash: payload.dataHash, scannedAt: payload.scannedAt };
|
|
110285
|
-
}
|
|
110286
|
-
|
|
110287
|
-
// ../../services/backend/src/domain/workspace-file-tree/transport/sharded-snapshot.ts
|
|
110288
|
-
function toLegacyShardBatchItem(shard) {
|
|
110289
|
-
return { ...shard };
|
|
110290
|
-
}
|
|
110291
|
-
function toLegacyManifestSyncArgs(manifest) {
|
|
110292
|
-
return { ...manifest };
|
|
110293
|
-
}
|
|
110294
|
-
// ../../services/backend/src/domain/workspace-file-tree/transport/index.ts
|
|
110295
|
-
var init_transport = () => {};
|
|
110296
|
-
|
|
110297
|
-
// ../../services/backend/src/domain/workspace-file-tree/index.ts
|
|
110298
|
-
var init_workspace_file_tree = __esm(() => {
|
|
110299
|
-
init_types2();
|
|
110300
|
-
init_select_strategy();
|
|
110301
|
-
init_registry5();
|
|
110302
|
-
init_transport();
|
|
110303
|
-
});
|
|
110304
|
-
|
|
110305
110262
|
// src/infrastructure/services/workspace/file-tree-data-hash.ts
|
|
110306
110263
|
import { createHash as createHash6 } from "node:crypto";
|
|
110307
110264
|
function computeFileTreeDataHash(tree) {
|
|
@@ -110309,168 +110266,6 @@ function computeFileTreeDataHash(tree) {
|
|
|
110309
110266
|
}
|
|
110310
110267
|
var init_file_tree_data_hash = () => {};
|
|
110311
110268
|
|
|
110312
|
-
// src/infrastructure/services/workspace/transport/blob-snapshot-publish.ts
|
|
110313
|
-
import { gzipSync as gzipSync2 } from "node:zlib";
|
|
110314
|
-
function buildBlobSnapshotPayload(tree, dataHash) {
|
|
110315
|
-
const compressed = gzipSync2(Buffer.from(JSON.stringify(tree))).toString("base64");
|
|
110316
|
-
return {
|
|
110317
|
-
data: { compression: "gzip", content: compressed },
|
|
110318
|
-
dataHash,
|
|
110319
|
-
scannedAt: tree.scannedAt
|
|
110320
|
-
};
|
|
110321
|
-
}
|
|
110322
|
-
async function publishBlobSnapshot(session2, workingDir, payload) {
|
|
110323
|
-
await session2.backend.mutation(api.workspaceFiles.syncFileTreeV2, {
|
|
110324
|
-
sessionId: session2.sessionId,
|
|
110325
|
-
machineId: session2.machineId,
|
|
110326
|
-
workingDir,
|
|
110327
|
-
...toLegacyBlobSyncArgs(payload)
|
|
110328
|
-
});
|
|
110329
|
-
return {
|
|
110330
|
-
strategyId: "blob",
|
|
110331
|
-
snapshotId: payload.dataHash,
|
|
110332
|
-
scannedAt: payload.scannedAt,
|
|
110333
|
-
entryCount: 0
|
|
110334
|
-
};
|
|
110335
|
-
}
|
|
110336
|
-
var init_blob_snapshot_publish = __esm(() => {
|
|
110337
|
-
init_api3();
|
|
110338
|
-
});
|
|
110339
|
-
|
|
110340
|
-
// src/infrastructure/services/workspace/file-tree-partition.ts
|
|
110341
|
-
import { createHash as createHash7 } from "node:crypto";
|
|
110342
|
-
import { gzipSync as gzipSync3 } from "node:zlib";
|
|
110343
|
-
function computeShardDataHash(payload) {
|
|
110344
|
-
return createHash7("md5").update(JSON.stringify(payload)).digest("hex");
|
|
110345
|
-
}
|
|
110346
|
-
function shardIdForPath(path3) {
|
|
110347
|
-
const slash = path3.indexOf("/");
|
|
110348
|
-
return slash === -1 ? "__root__" : path3.slice(0, slash);
|
|
110349
|
-
}
|
|
110350
|
-
function childShardId(path3, parentShardId) {
|
|
110351
|
-
if (parentShardId === "__root__") {
|
|
110352
|
-
return shardIdForPath(path3);
|
|
110353
|
-
}
|
|
110354
|
-
if (path3 === parentShardId) {
|
|
110355
|
-
return parentShardId;
|
|
110356
|
-
}
|
|
110357
|
-
const prefix = `${parentShardId}/`;
|
|
110358
|
-
if (!path3.startsWith(prefix)) {
|
|
110359
|
-
return parentShardId;
|
|
110360
|
-
}
|
|
110361
|
-
const remainder = path3.slice(prefix.length);
|
|
110362
|
-
const slash = remainder.indexOf("/");
|
|
110363
|
-
return slash === -1 ? parentShardId : `${parentShardId}/${remainder.slice(0, slash)}`;
|
|
110364
|
-
}
|
|
110365
|
-
function groupEntriesByShardId(entries2, parentShardId) {
|
|
110366
|
-
const groups = new Map;
|
|
110367
|
-
for (const entry of entries2) {
|
|
110368
|
-
const shardId = parentShardId === "__root__" ? shardIdForPath(entry.path) : childShardId(entry.path, parentShardId);
|
|
110369
|
-
const group = groups.get(shardId) ?? [];
|
|
110370
|
-
group.push(entry);
|
|
110371
|
-
groups.set(shardId, group);
|
|
110372
|
-
}
|
|
110373
|
-
return groups;
|
|
110374
|
-
}
|
|
110375
|
-
function buildPreparedShard(shardId, payload) {
|
|
110376
|
-
const compressed = gzipSync3(Buffer.from(JSON.stringify(payload))).toString("base64");
|
|
110377
|
-
return {
|
|
110378
|
-
shardId,
|
|
110379
|
-
payload,
|
|
110380
|
-
dataHash: computeShardDataHash(payload),
|
|
110381
|
-
entryCount: payload.entries.length,
|
|
110382
|
-
data: { compression: "gzip", content: compressed }
|
|
110383
|
-
};
|
|
110384
|
-
}
|
|
110385
|
-
function subdivideShardGroup(subgroups, tree) {
|
|
110386
|
-
const shards = [];
|
|
110387
|
-
for (const [subId, subEntries] of subgroups) {
|
|
110388
|
-
shards.push(...prepareShardGroup(subEntries, subId, tree));
|
|
110389
|
-
}
|
|
110390
|
-
return shards;
|
|
110391
|
-
}
|
|
110392
|
-
function shouldSkipParentCompression(subgroups, entryCount) {
|
|
110393
|
-
return subgroups.size > 1 && entryCount > LARGE_SHARD_ENTRY_THRESHOLD;
|
|
110394
|
-
}
|
|
110395
|
-
function prepareShardGroup(entries2, shardId, tree) {
|
|
110396
|
-
const subgroups = groupEntriesByShardId(entries2, shardId);
|
|
110397
|
-
if (shouldSkipParentCompression(subgroups, entries2.length)) {
|
|
110398
|
-
return subdivideShardGroup(subgroups, tree);
|
|
110399
|
-
}
|
|
110400
|
-
const payload = {
|
|
110401
|
-
entries: entries2,
|
|
110402
|
-
scannedAt: tree.scannedAt,
|
|
110403
|
-
rootDir: tree.rootDir
|
|
110404
|
-
};
|
|
110405
|
-
const compressed = gzipSync3(Buffer.from(JSON.stringify(payload))).toString("base64");
|
|
110406
|
-
if (Buffer.byteLength(compressed, "utf8") <= MAX_SHARD_JSON_BYTES || subgroups.size <= 1) {
|
|
110407
|
-
return [buildPreparedShard(shardId, payload)];
|
|
110408
|
-
}
|
|
110409
|
-
return subdivideShardGroup(subgroups, tree);
|
|
110410
|
-
}
|
|
110411
|
-
function partitionFileTree(tree) {
|
|
110412
|
-
const topGroups = groupEntriesByShardId(tree.entries, "__root__");
|
|
110413
|
-
const shards = [];
|
|
110414
|
-
for (const [shardId, entries2] of topGroups) {
|
|
110415
|
-
shards.push(...prepareShardGroup(entries2, shardId, tree));
|
|
110416
|
-
}
|
|
110417
|
-
return shards;
|
|
110418
|
-
}
|
|
110419
|
-
var MAX_TREE_JSON_BYTES2, MAX_SHARD_JSON_BYTES, MAX_SHARD_BATCH_SIZE = 8, LARGE_SHARD_ENTRY_THRESHOLD = 50000;
|
|
110420
|
-
var init_file_tree_partition = __esm(() => {
|
|
110421
|
-
init_workspace_file_tree();
|
|
110422
|
-
MAX_TREE_JSON_BYTES2 = 900 * 1024;
|
|
110423
|
-
MAX_SHARD_JSON_BYTES = 800 * 1024;
|
|
110424
|
-
});
|
|
110425
|
-
|
|
110426
|
-
// src/infrastructure/services/workspace/transport/sharded-snapshot-publish.ts
|
|
110427
|
-
async function publishShardedSnapshot(session2, workingDir, tree, syncGeneration) {
|
|
110428
|
-
const shards = partitionFileTree(tree);
|
|
110429
|
-
const shardIds = [];
|
|
110430
|
-
for (let i2 = 0;i2 < shards.length; i2 += MAX_SHARD_BATCH_SIZE) {
|
|
110431
|
-
const batch = shards.slice(i2, i2 + MAX_SHARD_BATCH_SIZE);
|
|
110432
|
-
const items = batch.map((s) => ({
|
|
110433
|
-
shardId: s.shardId,
|
|
110434
|
-
data: s.data,
|
|
110435
|
-
dataHash: s.dataHash,
|
|
110436
|
-
scannedAt: tree.scannedAt,
|
|
110437
|
-
entryCount: s.entryCount
|
|
110438
|
-
}));
|
|
110439
|
-
await session2.backend.mutation(api.workspaceFiles.syncFileTreeShardV3Batch, {
|
|
110440
|
-
sessionId: session2.sessionId,
|
|
110441
|
-
machineId: session2.machineId,
|
|
110442
|
-
workingDir,
|
|
110443
|
-
syncGeneration,
|
|
110444
|
-
items: items.map(toLegacyShardBatchItem)
|
|
110445
|
-
});
|
|
110446
|
-
for (const s of batch)
|
|
110447
|
-
shardIds.push(s.shardId);
|
|
110448
|
-
}
|
|
110449
|
-
const manifest = {
|
|
110450
|
-
syncGeneration,
|
|
110451
|
-
shardIds,
|
|
110452
|
-
totalEntryCount: tree.entries.length,
|
|
110453
|
-
complete: true,
|
|
110454
|
-
scannedAt: tree.scannedAt
|
|
110455
|
-
};
|
|
110456
|
-
await session2.backend.mutation(api.workspaceFiles.syncFileTreeManifestV3, {
|
|
110457
|
-
sessionId: session2.sessionId,
|
|
110458
|
-
machineId: session2.machineId,
|
|
110459
|
-
workingDir,
|
|
110460
|
-
...toLegacyManifestSyncArgs(manifest)
|
|
110461
|
-
});
|
|
110462
|
-
return {
|
|
110463
|
-
strategyId: "sharded",
|
|
110464
|
-
snapshotId: syncGeneration,
|
|
110465
|
-
scannedAt: tree.scannedAt,
|
|
110466
|
-
entryCount: tree.entries.length
|
|
110467
|
-
};
|
|
110468
|
-
}
|
|
110469
|
-
var init_sharded_snapshot_publish = __esm(() => {
|
|
110470
|
-
init_api3();
|
|
110471
|
-
init_file_tree_partition();
|
|
110472
|
-
});
|
|
110473
|
-
|
|
110474
110269
|
// src/infrastructure/services/workspace/file-tree-sync-ranker.ts
|
|
110475
110270
|
function fileExtension(p) {
|
|
110476
110271
|
const b = (p.split("/").pop() ?? p).toLowerCase();
|
|
@@ -113598,13 +113393,13 @@ function diffPathIndexes(previous, next4) {
|
|
|
113598
113393
|
}
|
|
113599
113394
|
|
|
113600
113395
|
// src/infrastructure/services/workspace/workspace-sync-state.ts
|
|
113601
|
-
import { createHash as
|
|
113396
|
+
import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
|
|
113602
113397
|
import * as fs11 from "node:fs/promises";
|
|
113603
113398
|
import { homedir as homedir8 } from "node:os";
|
|
113604
113399
|
import { join as join24 } from "node:path";
|
|
113605
113400
|
function workspaceKeyFor(workingDir) {
|
|
113606
113401
|
const normalized = normalizeWorkingDirForLookup(workingDir);
|
|
113607
|
-
return
|
|
113402
|
+
return createHash7("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
113608
113403
|
}
|
|
113609
113404
|
function buildPathIndex(entries2) {
|
|
113610
113405
|
const paths = {};
|
|
@@ -114045,6 +113840,45 @@ var init_workspace_sync_queue = __esm(() => {
|
|
|
114045
113840
|
lastCompletedAtByKey = new Map;
|
|
114046
113841
|
});
|
|
114047
113842
|
|
|
113843
|
+
// src/daemon/infrastructure/outbox/lib/durable-coalescing-state-schema.ts
|
|
113844
|
+
var DURABLE_COALESCING_STATE_MIGRATIONS;
|
|
113845
|
+
var init_durable_coalescing_state_schema = __esm(() => {
|
|
113846
|
+
DURABLE_COALESCING_STATE_MIGRATIONS = [
|
|
113847
|
+
`CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`,
|
|
113848
|
+
`CREATE TABLE IF NOT EXISTS coalescing_outbox_entries (delivery_key TEXT PRIMARY KEY, payload_json TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', attempts INTEGER NOT NULL DEFAULT 0, last_error TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`
|
|
113849
|
+
];
|
|
113850
|
+
});
|
|
113851
|
+
|
|
113852
|
+
// src/daemon/infrastructure/outbox/lib/durable-coalescing-state-store.ts
|
|
113853
|
+
import { mkdirSync as mkdirSync6 } from "node:fs";
|
|
113854
|
+
import { dirname as dirname12 } from "node:path";
|
|
113855
|
+
import { DatabaseSync } from "node:sqlite";
|
|
113856
|
+
function openDurableCoalescingStateStore(path8) {
|
|
113857
|
+
mkdirSync6(dirname12(path8), { recursive: true });
|
|
113858
|
+
const db = new DatabaseSync(path8);
|
|
113859
|
+
for (const sql of DURABLE_COALESCING_STATE_MIGRATIONS)
|
|
113860
|
+
db.exec(sql);
|
|
113861
|
+
db.prepare("UPDATE coalescing_outbox_entries SET status='pending' WHERE status='in_flight'").run();
|
|
113862
|
+
return { upsertPending: (key, payload) => {
|
|
113863
|
+
const now = Date.now();
|
|
113864
|
+
db.prepare("INSERT INTO coalescing_outbox_entries(delivery_key,payload_json,status,created_at,updated_at) VALUES(?,?,'pending',?,?) ON CONFLICT(delivery_key) DO UPDATE SET payload_json=excluded.payload_json,status='pending',updated_at=excluded.updated_at").run(key, payload, now, now);
|
|
113865
|
+
}, getPending: (key) => db.prepare("SELECT payload_json as payloadJson, attempts FROM coalescing_outbox_entries WHERE delivery_key=? AND status IN ('pending','in_flight')").get(key) ?? null, markDone: (key) => {
|
|
113866
|
+
db.prepare("DELETE FROM coalescing_outbox_entries WHERE delivery_key=?").run(key);
|
|
113867
|
+
}, markPendingRetry: (key, error51) => {
|
|
113868
|
+
db.prepare("UPDATE coalescing_outbox_entries SET status='pending',last_error=?,attempts=attempts+1,updated_at=? WHERE delivery_key=?").run(String(error51), Date.now(), key);
|
|
113869
|
+
}, listPendingKeys: () => db.prepare("SELECT delivery_key as key FROM coalescing_outbox_entries WHERE status IN ('pending','in_flight')").all().map((r) => String(r.key)), close: () => db.close() };
|
|
113870
|
+
}
|
|
113871
|
+
var init_durable_coalescing_state_store = __esm(() => {
|
|
113872
|
+
init_durable_coalescing_state_schema();
|
|
113873
|
+
});
|
|
113874
|
+
|
|
113875
|
+
// src/daemon/infrastructure/outbox/lib/outbox-retry-backoff.ts
|
|
113876
|
+
function computeExponentialRetryDelayMs(attempt, retryDelayMs, maxRetryDelayMs) {
|
|
113877
|
+
const exponent = Math.min(Math.max(0, attempt), MAX_RETRY_EXPONENT);
|
|
113878
|
+
return Math.min(retryDelayMs * 2 ** exponent, maxRetryDelayMs);
|
|
113879
|
+
}
|
|
113880
|
+
var MAX_RETRY_EXPONENT = 20;
|
|
113881
|
+
|
|
114048
113882
|
// src/daemon/infrastructure/outbox/lib/coalescing-state-outbox.ts
|
|
114049
113883
|
function createCoalescingStateOutbox(options) {
|
|
114050
113884
|
const durable = [options.store, options.deliveryKey, options.serialize, options.deserialize];
|
|
@@ -114061,8 +113895,10 @@ function createCoalescingStateOutbox(options) {
|
|
|
114061
113895
|
let stopped = false;
|
|
114062
113896
|
if (options.store && options.deliveryKey && options.deserialize) {
|
|
114063
113897
|
const recovered = options.store.getPending(options.deliveryKey);
|
|
114064
|
-
if (recovered)
|
|
113898
|
+
if (recovered) {
|
|
114065
113899
|
pending3 = { state: options.deserialize(recovered.payloadJson), waiters: [] };
|
|
113900
|
+
retryAttempt = recovered.attempts;
|
|
113901
|
+
}
|
|
114066
113902
|
}
|
|
114067
113903
|
const rejectWaiters = (waiters, error51) => {
|
|
114068
113904
|
for (const waiter of waiters)
|
|
@@ -114088,8 +113924,9 @@ function createCoalescingStateOutbox(options) {
|
|
|
114088
113924
|
}, Math.max(0, delayMs));
|
|
114089
113925
|
timer.unref?.();
|
|
114090
113926
|
};
|
|
114091
|
-
if (pending3)
|
|
114092
|
-
schedule2(0);
|
|
113927
|
+
if (pending3) {
|
|
113928
|
+
schedule2(retryAttempt > 0 ? computeExponentialRetryDelayMs(retryAttempt - 1, retryDelayMs, maxRetryDelayMs) : 0);
|
|
113929
|
+
}
|
|
114093
113930
|
async function drain2() {
|
|
114094
113931
|
if (stopped || !pending3 || inFlight2)
|
|
114095
113932
|
return;
|
|
@@ -114098,18 +113935,22 @@ function createCoalescingStateOutbox(options) {
|
|
|
114098
113935
|
const sendPromise = Promise.resolve().then(() => options.send(batch.state));
|
|
114099
113936
|
inFlight2 = { ...batch, promise: sendPromise };
|
|
114100
113937
|
let retryDelay = null;
|
|
113938
|
+
const store = options.store;
|
|
113939
|
+
const deliveryKey = options.deliveryKey;
|
|
114101
113940
|
try {
|
|
114102
113941
|
const result = await sendPromise;
|
|
114103
113942
|
lastSentAt = Date.now();
|
|
114104
113943
|
retryAttempt = 0;
|
|
114105
|
-
|
|
113944
|
+
if (store && deliveryKey)
|
|
113945
|
+
store.markDone(deliveryKey);
|
|
114106
113946
|
for (const waiter of batch.waiters)
|
|
114107
113947
|
waiter.resolve(result);
|
|
114108
113948
|
} catch (error51) {
|
|
114109
113949
|
options.onError?.(error51);
|
|
114110
|
-
|
|
113950
|
+
if (store && deliveryKey)
|
|
113951
|
+
store.markPendingRetry(deliveryKey, error51);
|
|
114111
113952
|
pending3 = mergePending(batch, pending3);
|
|
114112
|
-
retryDelay =
|
|
113953
|
+
retryDelay = computeExponentialRetryDelayMs(retryAttempt, retryDelayMs, maxRetryDelayMs);
|
|
114113
113954
|
retryAttempt++;
|
|
114114
113955
|
throw error51;
|
|
114115
113956
|
} finally {
|
|
@@ -114130,7 +113971,9 @@ function createCoalescingStateOutbox(options) {
|
|
|
114130
113971
|
} else {
|
|
114131
113972
|
pending3 = { state, waiters: [waiter] };
|
|
114132
113973
|
}
|
|
114133
|
-
options.store
|
|
113974
|
+
if (options.store && options.deliveryKey && options.serialize) {
|
|
113975
|
+
options.store.upsertPending(options.deliveryKey, options.serialize(state));
|
|
113976
|
+
}
|
|
114134
113977
|
});
|
|
114135
113978
|
if (!inFlight2 && !timer) {
|
|
114136
113979
|
const delay3 = lastSentAt === 0 ? 0 : Math.max(0, minIntervalMs - (Date.now() - lastSentAt));
|
|
@@ -114168,6 +114011,7 @@ function createCoalescingStateOutbox(options) {
|
|
|
114168
114011
|
return { enqueue, flushNow, stop: stop4 };
|
|
114169
114012
|
}
|
|
114170
114013
|
var DEFAULT_MIN_INTERVAL_MS = 5000, DEFAULT_RETRY_DELAY_MS = 500, DEFAULT_MAX_RETRY_DELAY_MS = 5000;
|
|
114014
|
+
var init_coalescing_state_outbox = () => {};
|
|
114171
114015
|
|
|
114172
114016
|
// src/daemon/infrastructure/outbox/lib/keyed-coalescing-state-outbox-registry.ts
|
|
114173
114017
|
function createKeyedCoalescingStateOutboxRegistry(options) {
|
|
@@ -114207,7 +114051,9 @@ function createKeyedCoalescingStateOutboxRegistry(options) {
|
|
|
114207
114051
|
}
|
|
114208
114052
|
};
|
|
114209
114053
|
}
|
|
114210
|
-
var init_keyed_coalescing_state_outbox_registry = () => {
|
|
114054
|
+
var init_keyed_coalescing_state_outbox_registry = __esm(() => {
|
|
114055
|
+
init_coalescing_state_outbox();
|
|
114056
|
+
});
|
|
114211
114057
|
|
|
114212
114058
|
// src/daemon/infrastructure/outbox/outbox-db-path.ts
|
|
114213
114059
|
import { homedir as homedir9 } from "node:os";
|
|
@@ -114217,54 +114063,25 @@ function resolveOutboxDbPath(machineId, kind) {
|
|
|
114217
114063
|
}
|
|
114218
114064
|
var init_outbox_db_path = () => {};
|
|
114219
114065
|
|
|
114220
|
-
// src/daemon/infrastructure/outbox/
|
|
114221
|
-
|
|
114222
|
-
|
|
114223
|
-
|
|
114224
|
-
|
|
114225
|
-
|
|
114226
|
-
|
|
114227
|
-
|
|
114228
|
-
|
|
114229
|
-
|
|
114230
|
-
|
|
114231
|
-
|
|
114232
|
-
|
|
114233
|
-
|
|
114234
|
-
|
|
114235
|
-
|
|
114236
|
-
|
|
114237
|
-
|
|
114238
|
-
|
|
114239
|
-
return { upsertPending: (key, payload) => {
|
|
114240
|
-
const now = Date.now();
|
|
114241
|
-
db.prepare("INSERT INTO coalescing_outbox_entries(delivery_key,payload_json,status,created_at,updated_at) VALUES(?,?,'pending',?,?) ON CONFLICT(delivery_key) DO UPDATE SET payload_json=excluded.payload_json,status='pending',updated_at=excluded.updated_at").run(key, payload, now, now);
|
|
114242
|
-
}, getPending: (key) => db.prepare("SELECT payload_json as payloadJson, attempts FROM coalescing_outbox_entries WHERE delivery_key=? AND status IN ('pending','in_flight')").get(key) ?? null, markDone: (key) => {
|
|
114243
|
-
db.prepare("DELETE FROM coalescing_outbox_entries WHERE delivery_key=?").run(key);
|
|
114244
|
-
}, markPendingRetry: (key, error51) => {
|
|
114245
|
-
db.prepare("UPDATE coalescing_outbox_entries SET status='pending',last_error=?,attempts=attempts+1,updated_at=? WHERE delivery_key=?").run(String(error51), Date.now(), key);
|
|
114246
|
-
}, listPendingKeys: () => db.prepare("SELECT delivery_key as key FROM coalescing_outbox_entries WHERE status IN ('pending','in_flight')").all().map((r) => String(r.key)), close: () => db.close() };
|
|
114247
|
-
}
|
|
114248
|
-
var init_durable_coalescing_state_store = __esm(() => {
|
|
114249
|
-
init_durable_coalescing_state_schema();
|
|
114250
|
-
});
|
|
114251
|
-
|
|
114252
|
-
// src/daemon/infrastructure/outbox/workspace-file-tree-checkpoint-outbox.ts
|
|
114253
|
-
function createWorkspaceFileTreeCheckpointOutboxRegistry(machineId, createSend, options) {
|
|
114254
|
-
return createKeyedCoalescingStateOutboxRegistry({
|
|
114255
|
-
store: openDurableCoalescingStateStore(resolveOutboxDbPath(machineId, "file-tree-checkpoint")),
|
|
114256
|
-
serialize: JSON.stringify,
|
|
114257
|
-
deserialize: JSON.parse,
|
|
114258
|
-
createSend,
|
|
114259
|
-
minIntervalMs: WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MIN_INTERVAL_MS,
|
|
114260
|
-
onError: options?.onError
|
|
114261
|
-
});
|
|
114262
|
-
}
|
|
114263
|
-
var WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MIN_INTERVAL_MS = 5000;
|
|
114264
|
-
var init_workspace_file_tree_checkpoint_outbox = __esm(() => {
|
|
114265
|
-
init_keyed_coalescing_state_outbox_registry();
|
|
114266
|
-
init_outbox_db_path();
|
|
114267
|
-
init_durable_coalescing_state_store();
|
|
114066
|
+
// src/daemon/infrastructure/outbox/workspace-file-tree-checkpoint-outbox.ts
|
|
114067
|
+
function createWorkspaceFileTreeCheckpointOutboxRegistry(machineId, createSend, options) {
|
|
114068
|
+
return createKeyedCoalescingStateOutboxRegistry({
|
|
114069
|
+
store: openDurableCoalescingStateStore(resolveOutboxDbPath(machineId, "file-tree-checkpoint")),
|
|
114070
|
+
serialize: JSON.stringify,
|
|
114071
|
+
deserialize: JSON.parse,
|
|
114072
|
+
createSend,
|
|
114073
|
+
minIntervalMs: WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MIN_INTERVAL_MS,
|
|
114074
|
+
retryDelayMs: WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_RETRY_DELAY_MS,
|
|
114075
|
+
maxRetryDelayMs: WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MAX_RETRY_DELAY_MS,
|
|
114076
|
+
onError: options?.onError
|
|
114077
|
+
});
|
|
114078
|
+
}
|
|
114079
|
+
var WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MIN_INTERVAL_MS = 5000, WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_RETRY_DELAY_MS = 5000, WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MAX_RETRY_DELAY_MS;
|
|
114080
|
+
var init_workspace_file_tree_checkpoint_outbox = __esm(() => {
|
|
114081
|
+
init_durable_coalescing_state_store();
|
|
114082
|
+
init_keyed_coalescing_state_outbox_registry();
|
|
114083
|
+
init_outbox_db_path();
|
|
114084
|
+
WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MAX_RETRY_DELAY_MS = 5 * 60000;
|
|
114268
114085
|
});
|
|
114269
114086
|
|
|
114270
114087
|
// src/daemon/infrastructure/outbox/lib/durable-fifo-queue-schema.ts
|
|
@@ -114320,7 +114137,7 @@ function createFifoBatchedOutbox(o) {
|
|
|
114320
114137
|
let stopped = false;
|
|
114321
114138
|
let retryTimer;
|
|
114322
114139
|
let retryAttempt = 0;
|
|
114323
|
-
const retryDelay = () =>
|
|
114140
|
+
const retryDelay = () => computeExponentialRetryDelayMs(retryAttempt++, o.retryDelayMs ?? 500, o.maxRetryDelayMs ?? 5000);
|
|
114324
114141
|
const scheduleRetry = () => {
|
|
114325
114142
|
if (!stopped && !retryTimer) {
|
|
114326
114143
|
retryTimer = setTimeout(() => {
|
|
@@ -114362,6 +114179,7 @@ function createFifoBatchedOutbox(o) {
|
|
|
114362
114179
|
scheduleRetry();
|
|
114363
114180
|
break;
|
|
114364
114181
|
}
|
|
114182
|
+
retryAttempt = 0;
|
|
114365
114183
|
} catch (e) {
|
|
114366
114184
|
o.onError?.(e);
|
|
114367
114185
|
for (const r of rows2)
|
|
@@ -114401,6 +114219,7 @@ function createFifoBatchedOutbox(o) {
|
|
|
114401
114219
|
};
|
|
114402
114220
|
return { enqueue, flushNow, stop: stop4 };
|
|
114403
114221
|
}
|
|
114222
|
+
var init_fifo_batched_outbox = () => {};
|
|
114404
114223
|
|
|
114405
114224
|
// src/daemon/infrastructure/outbox/lib/keyed-fifo-batched-outbox-registry.ts
|
|
114406
114225
|
function createKeyedFifoBatchedOutboxRegistry(o) {
|
|
@@ -114415,6 +114234,8 @@ function createKeyedFifoBatchedOutboxRegistry(o) {
|
|
|
114415
114234
|
deliveryKey: key,
|
|
114416
114235
|
serialize: o.serialize,
|
|
114417
114236
|
deserialize: o.deserialize,
|
|
114237
|
+
retryDelayMs: o.retryDelayMs,
|
|
114238
|
+
maxRetryDelayMs: o.maxRetryDelayMs,
|
|
114418
114239
|
onError: (e) => o.onError?.(key, e),
|
|
114419
114240
|
classifyOutcome: o.classifyOutcome
|
|
114420
114241
|
});
|
|
@@ -114447,7 +114268,7 @@ function createKeyedFifoBatchedOutboxRegistry(o) {
|
|
|
114447
114268
|
};
|
|
114448
114269
|
}
|
|
114449
114270
|
var init_keyed_fifo_batched_outbox_registry = __esm(() => {
|
|
114450
|
-
|
|
114271
|
+
init_fifo_batched_outbox();
|
|
114451
114272
|
});
|
|
114452
114273
|
|
|
114453
114274
|
// src/daemon/infrastructure/outbox/workspace-file-tree-delta-outbox.ts
|
|
@@ -114466,15 +114287,18 @@ function createWorkspaceFileTreeDeltaOutboxRegistry(machineId, createSend, optio
|
|
|
114466
114287
|
},
|
|
114467
114288
|
serialize: JSON.stringify,
|
|
114468
114289
|
deserialize: JSON.parse,
|
|
114290
|
+
retryDelayMs: WORKSPACE_FILE_TREE_DELTA_OUTBOX_RETRY_DELAY_MS,
|
|
114291
|
+
maxRetryDelayMs: WORKSPACE_FILE_TREE_DELTA_OUTBOX_MAX_RETRY_DELAY_MS,
|
|
114469
114292
|
onError: options?.onError,
|
|
114470
114293
|
classifyOutcome: (result, unit) => result.status === "conflict" ? { kind: "retry", item: { ...unit, baseRevision: result.revision } } : { kind: "success" }
|
|
114471
114294
|
});
|
|
114472
114295
|
}
|
|
114473
|
-
var WORKSPACE_FILE_TREE_DELTA_OUTBOX_BATCH_SIZE = 5;
|
|
114296
|
+
var WORKSPACE_FILE_TREE_DELTA_OUTBOX_BATCH_SIZE = 5, WORKSPACE_FILE_TREE_DELTA_OUTBOX_RETRY_DELAY_MS = 5000, WORKSPACE_FILE_TREE_DELTA_OUTBOX_MAX_RETRY_DELAY_MS;
|
|
114474
114297
|
var init_workspace_file_tree_delta_outbox = __esm(() => {
|
|
114475
|
-
init_outbox_db_path();
|
|
114476
114298
|
init_durable_fifo_queue_store();
|
|
114477
114299
|
init_keyed_fifo_batched_outbox_registry();
|
|
114300
|
+
init_outbox_db_path();
|
|
114301
|
+
WORKSPACE_FILE_TREE_DELTA_OUTBOX_MAX_RETRY_DELAY_MS = 5 * 60000;
|
|
114478
114302
|
});
|
|
114479
114303
|
|
|
114480
114304
|
// src/daemon/infrastructure/outbox/index.ts
|
|
@@ -114483,8 +114307,303 @@ var init_outbox = __esm(() => {
|
|
|
114483
114307
|
init_workspace_file_tree_delta_outbox();
|
|
114484
114308
|
});
|
|
114485
114309
|
|
|
114486
|
-
//
|
|
114310
|
+
// ../../services/backend/src/domain/workspace-file-tree/types.ts
|
|
114311
|
+
var MAX_TREE_JSON_BYTES;
|
|
114312
|
+
var init_types2 = __esm(() => {
|
|
114313
|
+
MAX_TREE_JSON_BYTES = 900 * 1024;
|
|
114314
|
+
});
|
|
114315
|
+
// ../../services/backend/src/domain/workspace-file-tree/select-strategy.ts
|
|
114316
|
+
function treeJsonByteLength(tree) {
|
|
114317
|
+
return Buffer.byteLength(JSON.stringify(tree), "utf8");
|
|
114318
|
+
}
|
|
114319
|
+
function selectFileTreeSnapshotStrategyId(tree) {
|
|
114320
|
+
return treeJsonByteLength(tree) > MAX_TREE_JSON_BYTES ? "sharded" : "blob";
|
|
114321
|
+
}
|
|
114322
|
+
var init_select_strategy = __esm(() => {
|
|
114323
|
+
init_types2();
|
|
114324
|
+
});
|
|
114325
|
+
|
|
114326
|
+
// ../../services/backend/src/domain/workspace-file-tree/registry.ts
|
|
114327
|
+
var init_registry5 = __esm(() => {
|
|
114328
|
+
init_select_strategy();
|
|
114329
|
+
});
|
|
114330
|
+
// ../../services/backend/src/domain/workspace-file-tree/transport/blob-snapshot.ts
|
|
114331
|
+
function toLegacyBlobSyncArgs(payload) {
|
|
114332
|
+
return { data: payload.data, dataHash: payload.dataHash, scannedAt: payload.scannedAt };
|
|
114333
|
+
}
|
|
114334
|
+
|
|
114335
|
+
// ../../services/backend/src/domain/workspace-file-tree/transport/sharded-snapshot.ts
|
|
114336
|
+
function toLegacyShardBatchItem(shard) {
|
|
114337
|
+
return { ...shard };
|
|
114338
|
+
}
|
|
114339
|
+
function toLegacyManifestSyncArgs(manifest) {
|
|
114340
|
+
return { ...manifest };
|
|
114341
|
+
}
|
|
114342
|
+
// ../../services/backend/src/domain/workspace-file-tree/transport/index.ts
|
|
114343
|
+
var init_transport = () => {};
|
|
114344
|
+
|
|
114345
|
+
// ../../services/backend/src/domain/workspace-file-tree/index.ts
|
|
114346
|
+
var init_workspace_file_tree = __esm(() => {
|
|
114347
|
+
init_types2();
|
|
114348
|
+
init_select_strategy();
|
|
114349
|
+
init_registry5();
|
|
114350
|
+
init_transport();
|
|
114351
|
+
});
|
|
114352
|
+
|
|
114353
|
+
// src/infrastructure/services/workspace/transport/blob-snapshot-publish.ts
|
|
114354
|
+
import { gzipSync as gzipSync2 } from "node:zlib";
|
|
114355
|
+
function buildBlobSnapshotPayload(tree, dataHash) {
|
|
114356
|
+
const compressed = gzipSync2(Buffer.from(JSON.stringify(tree))).toString("base64");
|
|
114357
|
+
return {
|
|
114358
|
+
data: { compression: "gzip", content: compressed },
|
|
114359
|
+
dataHash,
|
|
114360
|
+
scannedAt: tree.scannedAt
|
|
114361
|
+
};
|
|
114362
|
+
}
|
|
114363
|
+
async function publishBlobSnapshot(session2, workingDir, payload) {
|
|
114364
|
+
await session2.backend.mutation(api.workspaceFiles.syncFileTreeV2, {
|
|
114365
|
+
sessionId: session2.sessionId,
|
|
114366
|
+
machineId: session2.machineId,
|
|
114367
|
+
workingDir,
|
|
114368
|
+
...toLegacyBlobSyncArgs(payload)
|
|
114369
|
+
});
|
|
114370
|
+
return {
|
|
114371
|
+
strategyId: "blob",
|
|
114372
|
+
snapshotId: payload.dataHash,
|
|
114373
|
+
scannedAt: payload.scannedAt,
|
|
114374
|
+
entryCount: 0
|
|
114375
|
+
};
|
|
114376
|
+
}
|
|
114377
|
+
var init_blob_snapshot_publish = __esm(() => {
|
|
114378
|
+
init_api3();
|
|
114379
|
+
});
|
|
114380
|
+
|
|
114381
|
+
// src/infrastructure/services/workspace/file-tree-partition.ts
|
|
114382
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
114383
|
+
import { gzipSync as gzipSync3 } from "node:zlib";
|
|
114384
|
+
function computeShardDataHash(payload) {
|
|
114385
|
+
return createHash8("md5").update(JSON.stringify(payload)).digest("hex");
|
|
114386
|
+
}
|
|
114387
|
+
function shardIdForPath(path8) {
|
|
114388
|
+
const slash = path8.indexOf("/");
|
|
114389
|
+
return slash === -1 ? "__root__" : path8.slice(0, slash);
|
|
114390
|
+
}
|
|
114391
|
+
function childShardId(path8, parentShardId) {
|
|
114392
|
+
if (parentShardId === "__root__") {
|
|
114393
|
+
return shardIdForPath(path8);
|
|
114394
|
+
}
|
|
114395
|
+
if (path8 === parentShardId) {
|
|
114396
|
+
return parentShardId;
|
|
114397
|
+
}
|
|
114398
|
+
const prefix = `${parentShardId}/`;
|
|
114399
|
+
if (!path8.startsWith(prefix)) {
|
|
114400
|
+
return parentShardId;
|
|
114401
|
+
}
|
|
114402
|
+
const remainder = path8.slice(prefix.length);
|
|
114403
|
+
const slash = remainder.indexOf("/");
|
|
114404
|
+
return slash === -1 ? parentShardId : `${parentShardId}/${remainder.slice(0, slash)}`;
|
|
114405
|
+
}
|
|
114406
|
+
function groupEntriesByShardId(entries2, parentShardId) {
|
|
114407
|
+
const groups = new Map;
|
|
114408
|
+
for (const entry of entries2) {
|
|
114409
|
+
const shardId = parentShardId === "__root__" ? shardIdForPath(entry.path) : childShardId(entry.path, parentShardId);
|
|
114410
|
+
const group = groups.get(shardId) ?? [];
|
|
114411
|
+
group.push(entry);
|
|
114412
|
+
groups.set(shardId, group);
|
|
114413
|
+
}
|
|
114414
|
+
return groups;
|
|
114415
|
+
}
|
|
114416
|
+
function buildPreparedShard(shardId, payload) {
|
|
114417
|
+
const compressed = gzipSync3(Buffer.from(JSON.stringify(payload))).toString("base64");
|
|
114418
|
+
return {
|
|
114419
|
+
shardId,
|
|
114420
|
+
payload,
|
|
114421
|
+
dataHash: computeShardDataHash(payload),
|
|
114422
|
+
entryCount: payload.entries.length,
|
|
114423
|
+
data: { compression: "gzip", content: compressed }
|
|
114424
|
+
};
|
|
114425
|
+
}
|
|
114426
|
+
function subdivideShardGroup(subgroups, tree) {
|
|
114427
|
+
const shards = [];
|
|
114428
|
+
for (const [subId, subEntries] of subgroups) {
|
|
114429
|
+
shards.push(...prepareShardGroup(subEntries, subId, tree));
|
|
114430
|
+
}
|
|
114431
|
+
return shards;
|
|
114432
|
+
}
|
|
114433
|
+
function shouldSkipParentCompression(subgroups, entryCount) {
|
|
114434
|
+
return subgroups.size > 1 && entryCount > LARGE_SHARD_ENTRY_THRESHOLD;
|
|
114435
|
+
}
|
|
114436
|
+
function prepareShardGroup(entries2, shardId, tree) {
|
|
114437
|
+
const subgroups = groupEntriesByShardId(entries2, shardId);
|
|
114438
|
+
if (shouldSkipParentCompression(subgroups, entries2.length)) {
|
|
114439
|
+
return subdivideShardGroup(subgroups, tree);
|
|
114440
|
+
}
|
|
114441
|
+
const payload = {
|
|
114442
|
+
entries: entries2,
|
|
114443
|
+
scannedAt: tree.scannedAt,
|
|
114444
|
+
rootDir: tree.rootDir
|
|
114445
|
+
};
|
|
114446
|
+
const compressed = gzipSync3(Buffer.from(JSON.stringify(payload))).toString("base64");
|
|
114447
|
+
if (Buffer.byteLength(compressed, "utf8") <= MAX_SHARD_JSON_BYTES || subgroups.size <= 1) {
|
|
114448
|
+
return [buildPreparedShard(shardId, payload)];
|
|
114449
|
+
}
|
|
114450
|
+
return subdivideShardGroup(subgroups, tree);
|
|
114451
|
+
}
|
|
114452
|
+
function partitionFileTree(tree) {
|
|
114453
|
+
const topGroups = groupEntriesByShardId(tree.entries, "__root__");
|
|
114454
|
+
const shards = [];
|
|
114455
|
+
for (const [shardId, entries2] of topGroups) {
|
|
114456
|
+
shards.push(...prepareShardGroup(entries2, shardId, tree));
|
|
114457
|
+
}
|
|
114458
|
+
return shards;
|
|
114459
|
+
}
|
|
114460
|
+
var MAX_TREE_JSON_BYTES2, MAX_SHARD_JSON_BYTES, MAX_SHARD_BATCH_SIZE = 8, LARGE_SHARD_ENTRY_THRESHOLD = 50000;
|
|
114461
|
+
var init_file_tree_partition = __esm(() => {
|
|
114462
|
+
init_workspace_file_tree();
|
|
114463
|
+
MAX_TREE_JSON_BYTES2 = 900 * 1024;
|
|
114464
|
+
MAX_SHARD_JSON_BYTES = 800 * 1024;
|
|
114465
|
+
});
|
|
114466
|
+
|
|
114467
|
+
// src/infrastructure/services/workspace/transport/sharded-snapshot-publish.ts
|
|
114468
|
+
async function publishShardedSnapshot(session2, workingDir, tree, syncGeneration) {
|
|
114469
|
+
const shards = partitionFileTree(tree);
|
|
114470
|
+
const shardIds = [];
|
|
114471
|
+
for (let i2 = 0;i2 < shards.length; i2 += MAX_SHARD_BATCH_SIZE) {
|
|
114472
|
+
const batch = shards.slice(i2, i2 + MAX_SHARD_BATCH_SIZE);
|
|
114473
|
+
const items = batch.map((s) => ({
|
|
114474
|
+
shardId: s.shardId,
|
|
114475
|
+
data: s.data,
|
|
114476
|
+
dataHash: s.dataHash,
|
|
114477
|
+
scannedAt: tree.scannedAt,
|
|
114478
|
+
entryCount: s.entryCount
|
|
114479
|
+
}));
|
|
114480
|
+
await session2.backend.mutation(api.workspaceFiles.syncFileTreeShardV3Batch, {
|
|
114481
|
+
sessionId: session2.sessionId,
|
|
114482
|
+
machineId: session2.machineId,
|
|
114483
|
+
workingDir,
|
|
114484
|
+
syncGeneration,
|
|
114485
|
+
items: items.map(toLegacyShardBatchItem)
|
|
114486
|
+
});
|
|
114487
|
+
for (const s of batch)
|
|
114488
|
+
shardIds.push(s.shardId);
|
|
114489
|
+
}
|
|
114490
|
+
const manifest = {
|
|
114491
|
+
syncGeneration,
|
|
114492
|
+
shardIds,
|
|
114493
|
+
totalEntryCount: tree.entries.length,
|
|
114494
|
+
complete: true,
|
|
114495
|
+
scannedAt: tree.scannedAt
|
|
114496
|
+
};
|
|
114497
|
+
await session2.backend.mutation(api.workspaceFiles.syncFileTreeManifestV3, {
|
|
114498
|
+
sessionId: session2.sessionId,
|
|
114499
|
+
machineId: session2.machineId,
|
|
114500
|
+
workingDir,
|
|
114501
|
+
...toLegacyManifestSyncArgs(manifest)
|
|
114502
|
+
});
|
|
114503
|
+
return {
|
|
114504
|
+
strategyId: "sharded",
|
|
114505
|
+
snapshotId: syncGeneration,
|
|
114506
|
+
scannedAt: tree.scannedAt,
|
|
114507
|
+
entryCount: tree.entries.length
|
|
114508
|
+
};
|
|
114509
|
+
}
|
|
114510
|
+
var init_sharded_snapshot_publish = __esm(() => {
|
|
114511
|
+
init_api3();
|
|
114512
|
+
init_file_tree_partition();
|
|
114513
|
+
});
|
|
114514
|
+
|
|
114515
|
+
// src/daemon/infrastructure/outbox/workspace-file-tree-checkpoint-send.ts
|
|
114487
114516
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
114517
|
+
function needsMoreCheckpointPrune(result) {
|
|
114518
|
+
return (result.status === "published" || result.status === "unchanged") && result.pruneComplete === false;
|
|
114519
|
+
}
|
|
114520
|
+
function assertCheckpointAccepted(result) {
|
|
114521
|
+
if (result.status === "snapshot-missing" || result.status === "resync-required") {
|
|
114522
|
+
throw new Error(`File tree checkpoint rejected: ${result.status}`);
|
|
114523
|
+
}
|
|
114524
|
+
}
|
|
114525
|
+
async function syncScannedFileTree(session2, normalizedWorkingDir, tree, dataHash, syncGeneration) {
|
|
114526
|
+
if (selectFileTreeSnapshotStrategyId(tree) === "sharded") {
|
|
114527
|
+
const ref2 = await publishShardedSnapshot(session2, normalizedWorkingDir, tree, syncGeneration);
|
|
114528
|
+
return { strategyId: ref2.strategyId, snapshotId: ref2.snapshotId };
|
|
114529
|
+
}
|
|
114530
|
+
const ref = await publishBlobSnapshot(session2, normalizedWorkingDir, buildBlobSnapshotPayload(tree, dataHash));
|
|
114531
|
+
return { strategyId: ref.strategyId, snapshotId: ref.snapshotId };
|
|
114532
|
+
}
|
|
114533
|
+
async function publishCheckpointUntilPruned(session2, normalizedWorkingDir, snapshot, revision) {
|
|
114534
|
+
let checkpointRevision = revision;
|
|
114535
|
+
const publish = () => session2.backend.mutation(api.workspaceFiles.publishFileTreeCheckpoint, {
|
|
114536
|
+
sessionId: session2.sessionId,
|
|
114537
|
+
machineId: session2.machineId,
|
|
114538
|
+
workingDir: normalizedWorkingDir,
|
|
114539
|
+
revision: checkpointRevision,
|
|
114540
|
+
...snapshot
|
|
114541
|
+
});
|
|
114542
|
+
let result = await publish();
|
|
114543
|
+
if (result.status === "resync-required") {
|
|
114544
|
+
checkpointRevision = result.expectedRevision + 1;
|
|
114545
|
+
result = await publish();
|
|
114546
|
+
}
|
|
114547
|
+
while (needsMoreCheckpointPrune(result))
|
|
114548
|
+
result = await publish();
|
|
114549
|
+
assertCheckpointAccepted(result);
|
|
114550
|
+
return checkpointRevision;
|
|
114551
|
+
}
|
|
114552
|
+
function createWorkspaceFileTreeCheckpointSend(session2, normalizedWorkingDir) {
|
|
114553
|
+
return async (state) => {
|
|
114554
|
+
const snapshot = await syncScannedFileTree(session2, normalizedWorkingDir, state.tree, computeFileTreeDataHash(state.tree), randomUUID11());
|
|
114555
|
+
const revision = await publishCheckpointUntilPruned(session2, normalizedWorkingDir, snapshot, state.revision);
|
|
114556
|
+
return { revision };
|
|
114557
|
+
};
|
|
114558
|
+
}
|
|
114559
|
+
var init_workspace_file_tree_checkpoint_send = __esm(() => {
|
|
114560
|
+
init_workspace_file_tree();
|
|
114561
|
+
init_api3();
|
|
114562
|
+
init_file_tree_data_hash();
|
|
114563
|
+
init_blob_snapshot_publish();
|
|
114564
|
+
init_sharded_snapshot_publish();
|
|
114565
|
+
});
|
|
114566
|
+
|
|
114567
|
+
// src/daemon/infrastructure/outbox/workspace-file-tree-delta-send.ts
|
|
114568
|
+
function toDeltaOperations(delta) {
|
|
114569
|
+
return [
|
|
114570
|
+
...delta.added.map((entry) => ({
|
|
114571
|
+
o: "a",
|
|
114572
|
+
p: entry.path,
|
|
114573
|
+
e: entry.type === "directory" ? "d" : "f"
|
|
114574
|
+
})),
|
|
114575
|
+
...delta.removed.map((entryPath) => ({
|
|
114576
|
+
o: "r",
|
|
114577
|
+
p: entryPath
|
|
114578
|
+
})),
|
|
114579
|
+
...delta.typeChanged.map((entry) => ({
|
|
114580
|
+
o: "t",
|
|
114581
|
+
p: entry.path,
|
|
114582
|
+
e: entry.type === "directory" ? "d" : "f"
|
|
114583
|
+
}))
|
|
114584
|
+
];
|
|
114585
|
+
}
|
|
114586
|
+
function createWorkspaceFileTreeDeltaSend(session2, normalizedWorkingDir) {
|
|
114587
|
+
return async (unit) => {
|
|
114588
|
+
const result = await session2.backend.mutation(api.workspaceFiles.applyFileTreeDeltaBatch, {
|
|
114589
|
+
sessionId: session2.sessionId,
|
|
114590
|
+
machineId: session2.machineId,
|
|
114591
|
+
workingDir: normalizedWorkingDir,
|
|
114592
|
+
operationId: unit.delta.operationId,
|
|
114593
|
+
baseRevision: unit.baseRevision,
|
|
114594
|
+
operations: toDeltaOperations(unit.delta)
|
|
114595
|
+
});
|
|
114596
|
+
if (result.status === "resync-required") {
|
|
114597
|
+
return { status: "conflict", revision: result.expectedRevision };
|
|
114598
|
+
}
|
|
114599
|
+
return result;
|
|
114600
|
+
};
|
|
114601
|
+
}
|
|
114602
|
+
var init_workspace_file_tree_delta_send = __esm(() => {
|
|
114603
|
+
init_api3();
|
|
114604
|
+
});
|
|
114605
|
+
|
|
114606
|
+
// src/daemon/entry/files/file-tree-subscription.ts
|
|
114488
114607
|
function logSubscriptionWarn(label, err) {
|
|
114489
114608
|
console.warn(`[${formatTimestamp()}] ⚠️ ${label}: ${getErrorMessage(err)}`);
|
|
114490
114609
|
}
|
|
@@ -114552,79 +114671,20 @@ async function drainPendingFileTreeRequests(session2, coordinators, ensureCoordi
|
|
|
114552
114671
|
});
|
|
114553
114672
|
await processPendingFileTreeRequests(session2, coordinators, ensureCoordinator, requests);
|
|
114554
114673
|
}
|
|
114555
|
-
async function syncScannedFileTree(session2, normalizedWorkingDir, tree, dataHash, syncGeneration) {
|
|
114556
|
-
if (selectFileTreeSnapshotStrategyId(tree) === "sharded") {
|
|
114557
|
-
const ref2 = await publishShardedSnapshot(session2, normalizedWorkingDir, tree, syncGeneration);
|
|
114558
|
-
return { strategyId: ref2.strategyId, snapshotId: ref2.snapshotId };
|
|
114559
|
-
}
|
|
114560
|
-
const ref = await publishBlobSnapshot(session2, normalizedWorkingDir, buildBlobSnapshotPayload(tree, dataHash));
|
|
114561
|
-
return { strategyId: ref.strategyId, snapshotId: ref.snapshotId };
|
|
114562
|
-
}
|
|
114563
|
-
function toDeltaOperations(delta) {
|
|
114564
|
-
return [
|
|
114565
|
-
...delta.added.map((entry) => ({
|
|
114566
|
-
o: "a",
|
|
114567
|
-
p: entry.path,
|
|
114568
|
-
e: entry.type === "directory" ? "d" : "f"
|
|
114569
|
-
})),
|
|
114570
|
-
...delta.removed.map((entryPath) => ({
|
|
114571
|
-
o: "r",
|
|
114572
|
-
p: entryPath
|
|
114573
|
-
})),
|
|
114574
|
-
...delta.typeChanged.map((entry) => ({
|
|
114575
|
-
o: "t",
|
|
114576
|
-
p: entry.path,
|
|
114577
|
-
e: entry.type === "directory" ? "d" : "f"
|
|
114578
|
-
}))
|
|
114579
|
-
];
|
|
114580
|
-
}
|
|
114581
|
-
async function publishCheckpoint(session2, normalizedWorkingDir, tree, revision) {
|
|
114582
|
-
const dataHash = computeFileTreeDataHash(tree);
|
|
114583
|
-
const syncGeneration = randomUUID11();
|
|
114584
|
-
const snapshot = await syncScannedFileTree(session2, normalizedWorkingDir, tree, dataHash, syncGeneration);
|
|
114585
|
-
let checkpointRevision = revision;
|
|
114586
|
-
let result = await session2.backend.mutation(api.workspaceFiles.publishFileTreeCheckpoint, {
|
|
114587
|
-
sessionId: session2.sessionId,
|
|
114588
|
-
machineId: session2.machineId,
|
|
114589
|
-
workingDir: normalizedWorkingDir,
|
|
114590
|
-
revision: checkpointRevision,
|
|
114591
|
-
...snapshot
|
|
114592
|
-
});
|
|
114593
|
-
if (result.status === "resync-required") {
|
|
114594
|
-
checkpointRevision = result.expectedRevision + 1;
|
|
114595
|
-
result = await session2.backend.mutation(api.workspaceFiles.publishFileTreeCheckpoint, {
|
|
114596
|
-
sessionId: session2.sessionId,
|
|
114597
|
-
machineId: session2.machineId,
|
|
114598
|
-
workingDir: normalizedWorkingDir,
|
|
114599
|
-
revision: checkpointRevision,
|
|
114600
|
-
...snapshot
|
|
114601
|
-
});
|
|
114602
|
-
}
|
|
114603
|
-
if (result.status === "snapshot-missing") {
|
|
114604
|
-
throw new Error(`File tree checkpoint rejected: ${result.status}`);
|
|
114605
|
-
}
|
|
114606
|
-
console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree checkpoint: ${normalizedWorkingDir} (${tree.entries.length} entries, revision ${checkpointRevision})`);
|
|
114607
|
-
return { revision: checkpointRevision };
|
|
114608
|
-
}
|
|
114609
114674
|
var startFileTreeSubscriptionEffect = () => exports_Effect.gen(function* () {
|
|
114610
114675
|
const session2 = yield* DaemonSessionService;
|
|
114611
114676
|
const coordinators = new Map;
|
|
114612
|
-
const checkpointOutboxRegistry = createWorkspaceFileTreeCheckpointOutboxRegistry(session2.machineId, (normalized) =>
|
|
114677
|
+
const checkpointOutboxRegistry = createWorkspaceFileTreeCheckpointOutboxRegistry(session2.machineId, (normalized) => {
|
|
114678
|
+
const send = createWorkspaceFileTreeCheckpointSend(session2, normalized);
|
|
114679
|
+
return async (state) => {
|
|
114680
|
+
const result = await send(state);
|
|
114681
|
+
console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree checkpoint: ${normalized} (${state.tree.entries.length} entries, revision ${result.revision})`);
|
|
114682
|
+
return result;
|
|
114683
|
+
};
|
|
114684
|
+
}, {
|
|
114613
114685
|
onError: (normalized, error51) => logSubscriptionWarn(`File tree checkpoint outbox failed for ${normalized}`, error51)
|
|
114614
114686
|
});
|
|
114615
|
-
const deltaOutboxRegistry = createWorkspaceFileTreeDeltaOutboxRegistry(session2.machineId, (normalized) =>
|
|
114616
|
-
const result = await session2.backend.mutation(api.workspaceFiles.applyFileTreeDeltaBatch, {
|
|
114617
|
-
sessionId: session2.sessionId,
|
|
114618
|
-
machineId: session2.machineId,
|
|
114619
|
-
workingDir: normalized,
|
|
114620
|
-
operationId: unit.delta.operationId,
|
|
114621
|
-
baseRevision: unit.baseRevision,
|
|
114622
|
-
operations: toDeltaOperations(unit.delta)
|
|
114623
|
-
});
|
|
114624
|
-
if (result.status === "resync-required")
|
|
114625
|
-
return { status: "conflict", revision: result.expectedRevision };
|
|
114626
|
-
return result;
|
|
114627
|
-
});
|
|
114687
|
+
const deltaOutboxRegistry = createWorkspaceFileTreeDeltaOutboxRegistry(session2.machineId, (normalized) => createWorkspaceFileTreeDeltaSend(session2, normalized));
|
|
114628
114688
|
const ensureCoordinator = (workingDir, forceReconcile) => {
|
|
114629
114689
|
const normalized = normalizeWorkingDirForLookup(workingDir);
|
|
114630
114690
|
let coordinatorPromise = coordinators.get(normalized);
|
|
@@ -114672,16 +114732,14 @@ var startFileTreeSubscriptionEffect = () => exports_Effect.gen(function* () {
|
|
|
114672
114732
|
};
|
|
114673
114733
|
});
|
|
114674
114734
|
var init_file_tree_subscription = __esm(() => {
|
|
114675
|
-
init_workspace_file_tree();
|
|
114676
114735
|
init_esm();
|
|
114677
114736
|
init_api3();
|
|
114678
|
-
init_file_tree_data_hash();
|
|
114679
|
-
init_blob_snapshot_publish();
|
|
114680
|
-
init_sharded_snapshot_publish();
|
|
114681
114737
|
init_workspace_file_tree_coordinator();
|
|
114682
114738
|
init_workspace_sync_queue();
|
|
114683
114739
|
init_convex_error();
|
|
114684
114740
|
init_outbox();
|
|
114741
|
+
init_workspace_file_tree_checkpoint_send();
|
|
114742
|
+
init_workspace_file_tree_delta_send();
|
|
114685
114743
|
init_daemon_services();
|
|
114686
114744
|
});
|
|
114687
114745
|
|
|
@@ -134066,4 +134124,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
134066
134124
|
});
|
|
134067
134125
|
program2.parse();
|
|
134068
134126
|
|
|
134069
|
-
//# debugId=
|
|
134127
|
+
//# debugId=6381A1F83F16A2C964756E2164756E21
|