@mduan/paseo-cli 0.11.0-fork.34 → 0.11.0-fork.35
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/node_modules/@getpaseo/client/package.json +3 -3
- package/node_modules/@getpaseo/highlight/package.json +1 -1
- package/node_modules/@getpaseo/plugin/package.json +3 -3
- package/node_modules/@getpaseo/protocol/dist/generated/validation/ws-outbound.aot.js +190 -0
- package/node_modules/@getpaseo/protocol/dist/messages.d.ts +381 -0
- package/node_modules/@getpaseo/protocol/dist/messages.js +9 -0
- package/node_modules/@getpaseo/protocol/dist/validation/ws-outbound-schema-metadata.d.ts +90 -0
- package/node_modules/@getpaseo/protocol/package.json +1 -1
- package/node_modules/@getpaseo/relay/package.json +1 -1
- package/node_modules/@getpaseo/server/dist/server/builtin-plugins/package.json +1 -1
- package/node_modules/@getpaseo/server/dist/server/server/bootstrap.js +7 -0
- package/node_modules/@getpaseo/server/dist/server/server/session.d.ts +7 -0
- package/node_modules/@getpaseo/server/dist/server/server/session.js +37 -0
- package/node_modules/@getpaseo/server/dist/server/server/websocket-server.js +2 -0
- package/node_modules/@getpaseo/server/dist/server/server/workspace-git-service.d.ts +8 -2
- package/node_modules/@getpaseo/server/dist/server/server/workspace-git-service.js +55 -14
- package/node_modules/@getpaseo/server/dist/server/server/workspace-reconciliation-service.js +6 -2
- package/node_modules/@getpaseo/server/dist/server/server/workspace-registry.d.ts +2 -0
- package/node_modules/@getpaseo/server/dist/server/server/workspace-registry.js +4 -0
- package/node_modules/@getpaseo/server/dist/server/server/workspace-response-recorder.d.ts +13 -0
- package/node_modules/@getpaseo/server/dist/server/server/workspace-response-recorder.js +21 -0
- package/node_modules/@getpaseo/server/dist/server/utils/git-process-scheduler.d.ts +5 -3
- package/node_modules/@getpaseo/server/dist/server/utils/git-process-scheduler.js +26 -23
- package/node_modules/@getpaseo/server/dist/server/utils/run-git-command.d.ts +6 -1
- package/node_modules/@getpaseo/server/dist/server/utils/run-git-command.js +12 -9
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-ffe0cd60080175f6fb2dec3200390aec.js → desktop-attachment-bridge-e52f9cb2de89e698c51c18241d12cb99.js} +1 -1
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-ffe0cd60080175f6fb2dec3200390aec.js.br → desktop-attachment-bridge-e52f9cb2de89e698c51c18241d12cb99.js.br} +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-e52f9cb2de89e698c51c18241d12cb99.js.gz +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-4d76abbc28cb391667944e7e96595e46.js → desktop-attachment-store-8cb998792f7a176d7612229dafb2c2d3.js} +1 -1
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-4d76abbc28cb391667944e7e96595e46.js.br → desktop-attachment-store-8cb998792f7a176d7612229dafb2c2d3.js.br} +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-8cb998792f7a176d7612229dafb2c2d3.js.gz +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{index-52db3c28898b127e24f9b06f05f60336.js → index-c5f0ae884c9004e9301096d186baee98.js} +963 -961
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/index-c5f0ae884c9004e9301096d186baee98.js.br +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{index-52db3c28898b127e24f9b06f05f60336.js.gz → index-c5f0ae884c9004e9301096d186baee98.js.gz} +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-9b53f73c1bb6949c2c9ef911ef57ab87.js → indexeddb-attachment-store-cf65163fc7d8cd4c646c36e83771e937.js} +1 -1
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-cf65163fc7d8cd4c646c36e83771e937.js.br +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-9b53f73c1bb6949c2c9ef911ef57ab87.js.gz → indexeddb-attachment-store-cf65163fc7d8cd4c646c36e83771e937.js.gz} +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-ccf24f3ad53e8871f63d8e9c5417c2d7.js → native-file-attachment-store-da2a50627d6e788990a7f324838c24d2.js} +3 -3
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-da2a50627d6e788990a7f324838c24d2.js.br +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-da2a50627d6e788990a7f324838c24d2.js.gz +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/index.html +1 -1
- package/node_modules/@getpaseo/server/dist/server/web-ui/index.html.br +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/index.html.gz +0 -0
- package/node_modules/@getpaseo/server/package.json +6 -6
- package/package.json +7 -7
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-ffe0cd60080175f6fb2dec3200390aec.js.gz +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-4d76abbc28cb391667944e7e96595e46.js.gz +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/index-52db3c28898b127e24f9b06f05f60336.js.br +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-9b53f73c1bb6949c2c9ef911ef57ab87.js.br +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-ccf24f3ad53e8871f63d8e9c5417c2d7.js.br +0 -0
- package/node_modules/@getpaseo/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-ccf24f3ad53e8871f63d8e9c5417c2d7.js.gz +0 -0
|
@@ -10,7 +10,7 @@ import { createForgeService } from "../services/forge-registry.js";
|
|
|
10
10
|
import { createForgeResolver, } from "../services/forge-resolver.js";
|
|
11
11
|
import { parseGitRevParsePath } from "../utils/git-rev-parse-path.js";
|
|
12
12
|
import { createRealpathAwarePathMatcher, getRealpathAwareRelativePath, isPathInsideRoot, isRealpathInsideRoot, looksLikeDefiniteWindowsPath, } from "../utils/path.js";
|
|
13
|
-
import { createRunGitCommand, runGitCommand, } from "../utils/run-git-command.js";
|
|
13
|
+
import { createRunGitCommand, runGitCommand, runWithGitCommandPriority, } from "../utils/run-git-command.js";
|
|
14
14
|
import { branchNameFromRef } from "../utils/worktree-metadata.js";
|
|
15
15
|
import { listPaseoWorktrees } from "../utils/worktree.js";
|
|
16
16
|
import { READ_ONLY_GIT_ENV } from "./checkout-git-utils.js";
|
|
@@ -86,6 +86,16 @@ export function getWorkspaceGitObservationReensurePhaseMs(cwd) {
|
|
|
86
86
|
}
|
|
87
87
|
// Kept for local diagnostic fixtures that only use the stable phase calculation.
|
|
88
88
|
export const getWorkspaceGitSelfHealPhaseMs = getWorkspaceGitObservationReensurePhaseMs;
|
|
89
|
+
// Demand refreshes keep the caller's Git lane; watcher and poll refreshes run in background.
|
|
90
|
+
var WorkspaceGitRefreshOrigin;
|
|
91
|
+
(function (WorkspaceGitRefreshOrigin) {
|
|
92
|
+
WorkspaceGitRefreshOrigin["Demand"] = "demand";
|
|
93
|
+
WorkspaceGitRefreshOrigin["Observation"] = "observation";
|
|
94
|
+
})(WorkspaceGitRefreshOrigin || (WorkspaceGitRefreshOrigin = {}));
|
|
95
|
+
// A caller waiting on a merged refresh keeps it out of the background lane.
|
|
96
|
+
function mergeRefreshOrigins(pending, request) {
|
|
97
|
+
return pending === WorkspaceGitRefreshOrigin.Demand ? pending : request;
|
|
98
|
+
}
|
|
89
99
|
class WorkspaceGitServiceDisposedError extends Error {
|
|
90
100
|
constructor() {
|
|
91
101
|
super("WorkspaceGitService is disposed");
|
|
@@ -255,14 +265,17 @@ export class WorkspaceGitServiceImpl {
|
|
|
255
265
|
}
|
|
256
266
|
return this.requestWorkspaceSnapshot(target, request);
|
|
257
267
|
}
|
|
258
|
-
async getCheckout(cwd) {
|
|
268
|
+
async getCheckout(cwd, options) {
|
|
259
269
|
this.assertNotDisposed();
|
|
260
270
|
const normalizedCwd = resolve(cwd);
|
|
261
|
-
const
|
|
271
|
+
const readStatus = () => this.deps.getCheckoutStatus(normalizedCwd, {
|
|
262
272
|
paseoHome: this.paseoHome,
|
|
263
273
|
worktreesRoot: this.worktreesRoot,
|
|
264
274
|
logger: this.logger,
|
|
265
275
|
});
|
|
276
|
+
const status = await (options?.priority
|
|
277
|
+
? runWithGitCommandPriority(options.priority, readStatus)
|
|
278
|
+
: readStatus());
|
|
266
279
|
if (!status.isGit) {
|
|
267
280
|
return checkoutLiteFromGitSnapshot(normalizedCwd, {
|
|
268
281
|
isGit: false,
|
|
@@ -407,6 +420,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
407
420
|
cwd = resolve(cwd);
|
|
408
421
|
const target = this.ensureWorkspaceTarget(cwd);
|
|
409
422
|
await this.refreshWorkspaceTarget(target, {
|
|
423
|
+
origin: WorkspaceGitRefreshOrigin.Demand,
|
|
410
424
|
force: false,
|
|
411
425
|
refreshStructure: true,
|
|
412
426
|
refreshWorktree: true,
|
|
@@ -435,7 +449,10 @@ export class WorkspaceGitServiceImpl {
|
|
|
435
449
|
cwd = resolve(cwd);
|
|
436
450
|
const target = this.workspaceTargets.get(cwd);
|
|
437
451
|
if (target) {
|
|
438
|
-
this.scheduleWorkspaceRefresh(target, {
|
|
452
|
+
this.scheduleWorkspaceRefresh(target, {
|
|
453
|
+
origin: WorkspaceGitRefreshOrigin.Demand,
|
|
454
|
+
queueIfBusy: false,
|
|
455
|
+
});
|
|
439
456
|
}
|
|
440
457
|
}
|
|
441
458
|
onWorkspaceStateMayHaveChanged(cwd) {
|
|
@@ -447,6 +464,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
447
464
|
}
|
|
448
465
|
this.invalidateForge(normalizedCwd);
|
|
449
466
|
this.scheduleWorkspaceRefresh(target, {
|
|
467
|
+
origin: WorkspaceGitRefreshOrigin.Demand,
|
|
450
468
|
force: true,
|
|
451
469
|
includeForge: true,
|
|
452
470
|
reason: "external-state-change",
|
|
@@ -632,6 +650,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
632
650
|
return;
|
|
633
651
|
}
|
|
634
652
|
void this.refreshWorkspaceTarget(target, {
|
|
653
|
+
origin: WorkspaceGitRefreshOrigin.Demand,
|
|
635
654
|
force: false,
|
|
636
655
|
refreshStructure: true,
|
|
637
656
|
refreshWorktree: true,
|
|
@@ -958,6 +977,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
958
977
|
return false;
|
|
959
978
|
}
|
|
960
979
|
const changed = await this.refreshDegradedPollTarget(workspaceTarget, {
|
|
980
|
+
origin: WorkspaceGitRefreshOrigin.Observation,
|
|
961
981
|
force: false,
|
|
962
982
|
refreshStructure: target.repoRoot === null,
|
|
963
983
|
refreshWorktree: true,
|
|
@@ -1383,7 +1403,11 @@ export class WorkspaceGitServiceImpl {
|
|
|
1383
1403
|
for (const workspaceKey of target.workspaceKeys) {
|
|
1384
1404
|
const workspaceTarget = this.workspaceTargets.get(workspaceKey);
|
|
1385
1405
|
if (workspaceTarget) {
|
|
1386
|
-
this.scheduleWorkspaceRefresh(workspaceTarget, {
|
|
1406
|
+
this.scheduleWorkspaceRefresh(workspaceTarget, {
|
|
1407
|
+
origin: WorkspaceGitRefreshOrigin.Observation,
|
|
1408
|
+
scope: "worktree",
|
|
1409
|
+
reason,
|
|
1410
|
+
});
|
|
1387
1411
|
}
|
|
1388
1412
|
}
|
|
1389
1413
|
}
|
|
@@ -1818,6 +1842,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
1818
1842
|
}
|
|
1819
1843
|
}
|
|
1820
1844
|
this.scheduleWorkspaceRefresh(workspaceTarget, {
|
|
1845
|
+
origin: WorkspaceGitRefreshOrigin.Observation,
|
|
1821
1846
|
scope,
|
|
1822
1847
|
emitUnchanged: refresh.refreshBase,
|
|
1823
1848
|
reason,
|
|
@@ -1856,6 +1881,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
1856
1881
|
workingTreeTargets.add(workingTreeTarget);
|
|
1857
1882
|
}
|
|
1858
1883
|
return await this.refreshDegradedPollTarget(workspaceTarget, {
|
|
1884
|
+
origin: WorkspaceGitRefreshOrigin.Observation,
|
|
1859
1885
|
force: false,
|
|
1860
1886
|
refreshStructure: true,
|
|
1861
1887
|
refreshWorktree: true,
|
|
@@ -2141,6 +2167,8 @@ export class WorkspaceGitServiceImpl {
|
|
|
2141
2167
|
if (request.queueIfBusy || addsWork) {
|
|
2142
2168
|
target.refreshState.queued = this.mergeRefreshRequests(target.refreshState.queued, request);
|
|
2143
2169
|
}
|
|
2170
|
+
// The caller now waits on this refresh — promote its remaining Git work.
|
|
2171
|
+
active.origin = mergeRefreshOrigins(active.origin, request.origin);
|
|
2144
2172
|
return target.refreshState.promise;
|
|
2145
2173
|
}
|
|
2146
2174
|
if (!request.force && !request.queueIfBusy && this.shouldThrottleNonForcedRefresh(target)) {
|
|
@@ -2166,6 +2194,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
2166
2194
|
}
|
|
2167
2195
|
const force = options?.force === true;
|
|
2168
2196
|
return {
|
|
2197
|
+
origin: WorkspaceGitRefreshOrigin.Demand,
|
|
2169
2198
|
force,
|
|
2170
2199
|
refreshStructure: options?.refreshGit !== false,
|
|
2171
2200
|
refreshWorktree: options?.refreshGit !== false,
|
|
@@ -2183,17 +2212,18 @@ export class WorkspaceGitServiceImpl {
|
|
|
2183
2212
|
return this.deps.now().getTime() - target.lastShellOutAtMs < WORKSPACE_GIT_INTERNAL_MIN_GAP_MS;
|
|
2184
2213
|
}
|
|
2185
2214
|
buildScheduledRefreshRequest(options) {
|
|
2186
|
-
const scope = options
|
|
2215
|
+
const scope = options.scope;
|
|
2187
2216
|
return {
|
|
2188
|
-
|
|
2217
|
+
origin: options.origin,
|
|
2218
|
+
force: options.force === true,
|
|
2189
2219
|
refreshStructure: scope !== "worktree" && scope !== "refs",
|
|
2190
2220
|
refreshWorktree: scope !== "structure" && scope !== "refs",
|
|
2191
|
-
includeForge: options
|
|
2192
|
-
emitUnchanged: options
|
|
2193
|
-
reason: options
|
|
2221
|
+
includeForge: options.includeForge ?? false,
|
|
2222
|
+
emitUnchanged: options.emitUnchanged,
|
|
2223
|
+
reason: options.reason ?? "watch",
|
|
2194
2224
|
notify: true,
|
|
2195
|
-
queueIfBusy: options
|
|
2196
|
-
movedRemoteRefs: new Set(options
|
|
2225
|
+
queueIfBusy: options.queueIfBusy ?? true,
|
|
2226
|
+
movedRemoteRefs: new Set(options.movedRemoteRefs),
|
|
2197
2227
|
};
|
|
2198
2228
|
}
|
|
2199
2229
|
mergeRefreshRequests(pending, request) {
|
|
@@ -2208,6 +2238,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
2208
2238
|
const upgradesEmit = request.emitUnchanged === true && pending.emitUnchanged !== true;
|
|
2209
2239
|
const { merged: movedRemoteRefs, added: upgradesMovedRefs } = mergeSets(pending.movedRemoteRefs, request.movedRemoteRefs);
|
|
2210
2240
|
return {
|
|
2241
|
+
origin: mergeRefreshOrigins(pending.origin, request.origin),
|
|
2211
2242
|
force,
|
|
2212
2243
|
refreshStructure: pending.refreshStructure || request.refreshStructure,
|
|
2213
2244
|
refreshWorktree: pending.refreshWorktree || request.refreshWorktree,
|
|
@@ -2240,7 +2271,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
2240
2271
|
});
|
|
2241
2272
|
}
|
|
2242
2273
|
try {
|
|
2243
|
-
const runRefreshGitCommand =
|
|
2274
|
+
const runRefreshGitCommand = this.createRefreshGitCommand(request);
|
|
2244
2275
|
const admittedSnapshot = await this.workspaceRefreshLimit(() => {
|
|
2245
2276
|
if (target.closed || this.workspaceTargets.get(target.cwd) !== target) {
|
|
2246
2277
|
return null;
|
|
@@ -2276,6 +2307,16 @@ export class WorkspaceGitServiceImpl {
|
|
|
2276
2307
|
}
|
|
2277
2308
|
return snapshot;
|
|
2278
2309
|
}
|
|
2310
|
+
// Origin is read per command so a joining demand caller promotes the rest of the refresh.
|
|
2311
|
+
// Demand uses the ambient lane so a "high" user action is not demoted.
|
|
2312
|
+
createRefreshGitCommand(request) {
|
|
2313
|
+
const provenance = `workspace-refresh:${request.reason}`;
|
|
2314
|
+
const runDemand = createRunGitCommand(provenance);
|
|
2315
|
+
const runObservation = createRunGitCommand(provenance, { priority: "background" });
|
|
2316
|
+
return (args, options) => request.origin === WorkspaceGitRefreshOrigin.Observation
|
|
2317
|
+
? runObservation(args, options)
|
|
2318
|
+
: runDemand(args, options);
|
|
2319
|
+
}
|
|
2279
2320
|
async refreshSnapshot(target, request, runRefreshGitCommand) {
|
|
2280
2321
|
let facts = target.latestFacts;
|
|
2281
2322
|
if (request.movedRemoteRefs.size > 0 && !request.refreshStructure && !request.refreshWorktree) {
|
|
@@ -2531,7 +2572,7 @@ export class WorkspaceGitServiceImpl {
|
|
|
2531
2572
|
eventsBeforeFetchSnapshot.push(...events);
|
|
2532
2573
|
}
|
|
2533
2574
|
},
|
|
2534
|
-
}, createRunGitCommand("background-fetch"));
|
|
2575
|
+
}, createRunGitCommand("background-fetch", { priority: "background" }));
|
|
2535
2576
|
}
|
|
2536
2577
|
catch (error) {
|
|
2537
2578
|
this.logger.warn({ err: error, repoGitRoot: target.repoGitRoot, cwd: target.cwd }, "Background git fetch failed");
|
package/node_modules/@getpaseo/server/dist/server/server/workspace-reconciliation-service.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { statSync, watch as watchPath } from "node:fs";
|
|
2
|
+
import pLimit from "p-limit";
|
|
2
3
|
import { areEquivalentPaths } from "../utils/path.js";
|
|
3
4
|
import { deriveProjectKind, reconcileWorkspacePlacement, } from "./workspace-registry-model.js";
|
|
4
5
|
import { workspaceIdsForProjects } from "./workspace-directory.js";
|
|
5
6
|
import { deriveProjectKey } from "./project-key.js";
|
|
6
7
|
const DEFAULT_RESCAN_INTERVAL_MS = 5 * 60000;
|
|
7
8
|
const DEFAULT_DEBOUNCE_MS = 100;
|
|
9
|
+
// ~15 Git commands per read — unbounded sibling reads queued 1,000+ commands per rescan.
|
|
10
|
+
const CHECKOUT_READ_CONCURRENCY = 4;
|
|
8
11
|
const systemClock = {
|
|
9
12
|
setTimeout: (callback, delayMs) => setTimeout(() => void callback(), delayMs),
|
|
10
13
|
clearTimeout: (timer) => clearTimeout(timer),
|
|
@@ -169,11 +172,12 @@ export class WorkspaceReconciliationService {
|
|
|
169
172
|
}
|
|
170
173
|
async reconcileGitMetadataForProjects(projectsToReconcile, workspacesByProject, changes) {
|
|
171
174
|
const checkoutReads = [];
|
|
175
|
+
const checkoutReadLimit = pLimit(CHECKOUT_READ_CONCURRENCY);
|
|
172
176
|
const readCheckout = (cwd) => {
|
|
173
177
|
const existing = checkoutReads.find((read) => areEquivalentPaths(read.cwd, cwd));
|
|
174
178
|
if (existing)
|
|
175
179
|
return existing.checkout;
|
|
176
|
-
const checkout = this.readCheckout(cwd);
|
|
180
|
+
const checkout = checkoutReadLimit(() => this.readCheckout(cwd));
|
|
177
181
|
checkoutReads.push({ cwd, checkout });
|
|
178
182
|
return checkout;
|
|
179
183
|
};
|
|
@@ -367,7 +371,7 @@ export class WorkspaceReconciliationService {
|
|
|
367
371
|
mainRepoRoot: null,
|
|
368
372
|
};
|
|
369
373
|
}
|
|
370
|
-
return this.workspaceGitService.getCheckout(cwd);
|
|
374
|
+
return this.workspaceGitService.getCheckout(cwd, { priority: "background" });
|
|
371
375
|
}
|
|
372
376
|
inspectDirectory(targetPath) {
|
|
373
377
|
try {
|
|
@@ -58,6 +58,8 @@ declare const PersistedWorkspaceRecordSchema: z.ZodObject<{
|
|
|
58
58
|
color: z.ZodString;
|
|
59
59
|
}, z.core.$strip>>;
|
|
60
60
|
}, z.core.$strip>>>;
|
|
61
|
+
lastHumanPromptAt: z.ZodOptional<z.ZodString>;
|
|
62
|
+
lastAgentResponseAt: z.ZodOptional<z.ZodString>;
|
|
61
63
|
untrustedSource: z.ZodOptional<z.ZodObject<{
|
|
62
64
|
kind: z.ZodLiteral<"change_request">;
|
|
63
65
|
forge: z.ZodString;
|
|
@@ -98,6 +98,10 @@ const PersistedWorkspaceRecordSchema = z.object({
|
|
|
98
98
|
.transform((value) => value ?? null),
|
|
99
99
|
labels: z.array(z.string()).optional(),
|
|
100
100
|
linearIssues: z.array(LinearIssueSchema).optional(),
|
|
101
|
+
// Last client-sent prompt; automated prompts never set it — see `recordHumanPrompt`.
|
|
102
|
+
lastHumanPromptAt: z.string().optional(),
|
|
103
|
+
// Last completed agent turn, whoever prompted it — see `attachWorkspaceResponseRecorder`.
|
|
104
|
+
lastAgentResponseAt: z.string().optional(),
|
|
101
105
|
untrustedSource: UntrustedWorkspaceSourceSchema.optional(),
|
|
102
106
|
});
|
|
103
107
|
class FileBackedRegistry {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Logger } from "pino";
|
|
2
|
+
import type { AgentManager } from "./agent/agent-manager.js";
|
|
3
|
+
import type { WorkspaceRegistry } from "./workspace-registry.js";
|
|
4
|
+
/**
|
|
5
|
+
* Stamps `lastAgentResponseAt` on the owning workspace each time a live agent turn completes,
|
|
6
|
+
* whoever prompted it. History replays never reach subscribers, so restarts don't move it.
|
|
7
|
+
*/
|
|
8
|
+
export declare function attachWorkspaceResponseRecorder(input: {
|
|
9
|
+
logger: Logger;
|
|
10
|
+
agentManager: Pick<AgentManager, "subscribe" | "getAgent">;
|
|
11
|
+
workspaceRegistry: Pick<WorkspaceRegistry, "update">;
|
|
12
|
+
}): () => void;
|
|
13
|
+
//# sourceMappingURL=workspace-response-recorder.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stamps `lastAgentResponseAt` on the owning workspace each time a live agent turn completes,
|
|
3
|
+
* whoever prompted it. History replays never reach subscribers, so restarts don't move it.
|
|
4
|
+
*/
|
|
5
|
+
export function attachWorkspaceResponseRecorder(input) {
|
|
6
|
+
const { logger, agentManager, workspaceRegistry } = input;
|
|
7
|
+
return agentManager.subscribe((event) => {
|
|
8
|
+
if (event.type !== "agent_stream" || event.event.type !== "turn_completed")
|
|
9
|
+
return;
|
|
10
|
+
const agent = agentManager.getAgent(event.agentId);
|
|
11
|
+
if (!agent?.workspaceId || agent.internal)
|
|
12
|
+
return;
|
|
13
|
+
const lastAgentResponseAt = event.timestamp ?? new Date().toISOString();
|
|
14
|
+
void workspaceRegistry
|
|
15
|
+
.update(agent.workspaceId, (existing) => ({ ...existing, lastAgentResponseAt }))
|
|
16
|
+
.catch((error) => {
|
|
17
|
+
logger.warn({ err: error, agentId: event.agentId, workspaceId: agent.workspaceId }, "Failed to record agent response time");
|
|
18
|
+
});
|
|
19
|
+
}, { replayState: false });
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=workspace-response-recorder.js.map
|
|
@@ -7,7 +7,7 @@ export interface ScheduledGitProcess<T> {
|
|
|
7
7
|
result: Promise<T>;
|
|
8
8
|
exited: Promise<void>;
|
|
9
9
|
}
|
|
10
|
-
export type GitProcessPriority = "normal" | "
|
|
10
|
+
export type GitProcessPriority = "high" | "normal" | "background";
|
|
11
11
|
export declare function resolveGitProcessPolicy(input: {
|
|
12
12
|
env: NodeJS.ProcessEnv;
|
|
13
13
|
persisted?: Partial<GitProcessPolicy>;
|
|
@@ -15,9 +15,9 @@ export declare function resolveGitProcessPolicy(input: {
|
|
|
15
15
|
export declare class GitProcessScheduler {
|
|
16
16
|
readonly policy: GitProcessPolicy;
|
|
17
17
|
private readonly startThrottled;
|
|
18
|
-
private readonly
|
|
19
|
-
private readonly normalPriorityQueue;
|
|
18
|
+
private readonly queues;
|
|
20
19
|
private admitted;
|
|
20
|
+
private reservedStarts;
|
|
21
21
|
private running;
|
|
22
22
|
private waiting;
|
|
23
23
|
private drainScheduled;
|
|
@@ -27,8 +27,10 @@ export declare class GitProcessScheduler {
|
|
|
27
27
|
run<T>(start: () => ScheduledGitProcess<T>, options?: {
|
|
28
28
|
priority?: GitProcessPriority;
|
|
29
29
|
}): Promise<T>;
|
|
30
|
+
private canReserveStart;
|
|
30
31
|
private scheduleDrain;
|
|
31
32
|
private drainOne;
|
|
33
|
+
private startNext;
|
|
32
34
|
private execute;
|
|
33
35
|
}
|
|
34
36
|
//# sourceMappingURL=git-process-scheduler.d.ts.map
|
|
@@ -23,12 +23,18 @@ export function resolveGitProcessPolicy(input) {
|
|
|
23
23
|
DEFAULT_GIT_PROCESS_POLICY.maxProcessConcurrency,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
// Admission reserves a slot and a start-rate token; the job is chosen when the token fires, so
|
|
27
|
+
// work submitted while background reservations wait on the rate limit takes the next start.
|
|
26
28
|
export class GitProcessScheduler {
|
|
27
29
|
constructor(policy) {
|
|
28
30
|
this.policy = policy;
|
|
29
|
-
this.
|
|
30
|
-
|
|
31
|
+
this.queues = {
|
|
32
|
+
high: [],
|
|
33
|
+
normal: [],
|
|
34
|
+
background: [],
|
|
35
|
+
};
|
|
31
36
|
this.admitted = 0;
|
|
37
|
+
this.reservedStarts = 0;
|
|
32
38
|
this.running = 0;
|
|
33
39
|
this.waiting = 0;
|
|
34
40
|
this.drainScheduled = false;
|
|
@@ -37,7 +43,7 @@ export class GitProcessScheduler {
|
|
|
37
43
|
interval: 1000,
|
|
38
44
|
strict: true,
|
|
39
45
|
});
|
|
40
|
-
this.startThrottled = throttle((
|
|
46
|
+
this.startThrottled = throttle(() => this.startNext());
|
|
41
47
|
}
|
|
42
48
|
get activeCount() {
|
|
43
49
|
return this.running;
|
|
@@ -48,16 +54,7 @@ export class GitProcessScheduler {
|
|
|
48
54
|
run(start, options) {
|
|
49
55
|
this.waiting += 1;
|
|
50
56
|
return new Promise((resolve, reject) => {
|
|
51
|
-
|
|
52
|
-
void this.startThrottled(() => this.execute(start, resolve, reject)).catch((error) => {
|
|
53
|
-
this.waiting = Math.max(0, this.waiting - 1);
|
|
54
|
-
this.admitted = Math.max(0, this.admitted - 1);
|
|
55
|
-
reject(error);
|
|
56
|
-
this.scheduleDrain();
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
|
-
const queue = options?.priority === "high" ? this.highPriorityQueue : this.normalPriorityQueue;
|
|
60
|
-
queue.push(admit);
|
|
57
|
+
this.queues[options?.priority ?? "normal"].push(() => this.execute(start, resolve, reject));
|
|
61
58
|
if (this.admitted === 0 && !this.drainScheduled) {
|
|
62
59
|
this.drainOne();
|
|
63
60
|
}
|
|
@@ -66,11 +63,12 @@ export class GitProcessScheduler {
|
|
|
66
63
|
}
|
|
67
64
|
});
|
|
68
65
|
}
|
|
66
|
+
// Every reservation is backed by a queued job: jobs leave the queues only in startNext.
|
|
67
|
+
canReserveStart() {
|
|
68
|
+
return this.admitted < this.policy.maxProcessConcurrency && this.waiting > this.reservedStarts;
|
|
69
|
+
}
|
|
69
70
|
scheduleDrain() {
|
|
70
|
-
if (this.drainScheduled || this.
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
if (this.highPriorityQueue.length === 0 && this.normalPriorityQueue.length === 0) {
|
|
71
|
+
if (this.drainScheduled || !this.canReserveStart()) {
|
|
74
72
|
return;
|
|
75
73
|
}
|
|
76
74
|
this.drainScheduled = true;
|
|
@@ -78,19 +76,24 @@ export class GitProcessScheduler {
|
|
|
78
76
|
}
|
|
79
77
|
drainOne() {
|
|
80
78
|
this.drainScheduled = false;
|
|
81
|
-
if (this.
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const admit = this.highPriorityQueue.shift() ?? this.normalPriorityQueue.shift();
|
|
85
|
-
if (!admit) {
|
|
79
|
+
if (!this.canReserveStart()) {
|
|
86
80
|
return;
|
|
87
81
|
}
|
|
88
82
|
this.admitted += 1;
|
|
89
|
-
|
|
83
|
+
this.reservedStarts += 1;
|
|
84
|
+
void this.startThrottled();
|
|
90
85
|
// Spawning can be synchronous and expensive on a throttled host. Let timers,
|
|
91
86
|
// sockets, and child exits run before admitting another Git process.
|
|
92
87
|
this.scheduleDrain();
|
|
93
88
|
}
|
|
89
|
+
startNext() {
|
|
90
|
+
this.reservedStarts -= 1;
|
|
91
|
+
const next = this.queues.high.shift() ?? this.queues.normal.shift() ?? this.queues.background.shift();
|
|
92
|
+
if (!next) {
|
|
93
|
+
throw new Error("Git process start fired without a queued process");
|
|
94
|
+
}
|
|
95
|
+
return next();
|
|
96
|
+
}
|
|
94
97
|
async execute(start, resolve, reject) {
|
|
95
98
|
this.waiting = Math.max(0, this.waiting - 1);
|
|
96
99
|
this.running += 1;
|
|
@@ -22,7 +22,11 @@ export interface GitCommandResult<Output = string> {
|
|
|
22
22
|
signal: NodeJS.Signals | null;
|
|
23
23
|
}
|
|
24
24
|
export type RunGitCommand = (args: string[], options: GitCommandOptions) => Promise<GitCommandResult>;
|
|
25
|
-
export
|
|
25
|
+
export interface GitCommandRunnerOptions {
|
|
26
|
+
/** Overrides the ambient `runWithGitCommandPriority` lane for every command this runner starts. */
|
|
27
|
+
priority?: GitProcessPriority;
|
|
28
|
+
}
|
|
29
|
+
export declare function createRunGitCommand(provenance: string, runnerOptions?: GitCommandRunnerOptions): RunGitCommand;
|
|
26
30
|
export interface GitCommandMetric {
|
|
27
31
|
args: string[];
|
|
28
32
|
cwd: string;
|
|
@@ -47,6 +51,7 @@ export interface GitCommandMetricsSnapshot {
|
|
|
47
51
|
export interface GitCommandSubmissionMetric {
|
|
48
52
|
args: string[];
|
|
49
53
|
cwd: string;
|
|
54
|
+
priority: GitProcessPriority;
|
|
50
55
|
}
|
|
51
56
|
export declare function startGitCommandMetrics(): void;
|
|
52
57
|
export declare function stopGitCommandMetrics(): GitCommandMetricsSnapshot;
|
|
@@ -23,8 +23,12 @@ export function configureGitProcessPolicy(policy) {
|
|
|
23
23
|
gitProcessScheduler = new GitProcessScheduler(policy);
|
|
24
24
|
gitRuntimeMetrics = createGitCommandRuntimeMetricsWindow(policy);
|
|
25
25
|
}
|
|
26
|
-
export function createRunGitCommand(provenance) {
|
|
27
|
-
|
|
26
|
+
export function createRunGitCommand(provenance, runnerOptions) {
|
|
27
|
+
const priority = runnerOptions?.priority;
|
|
28
|
+
if (!priority) {
|
|
29
|
+
return (args, options) => runGitCommandWithProvenance(args, options, provenance);
|
|
30
|
+
}
|
|
31
|
+
return (args, options) => runWithGitCommandPriority(priority, () => runGitCommandWithProvenance(args, options, provenance));
|
|
28
32
|
}
|
|
29
33
|
let gitCommandMetricsState = null;
|
|
30
34
|
export function startGitCommandMetrics() {
|
|
@@ -92,8 +96,8 @@ function snapshotGitCommandMetricsState(state) {
|
|
|
92
96
|
return {
|
|
93
97
|
commands: [...state.commands],
|
|
94
98
|
submissions: state.submissions.map((submission) => ({
|
|
99
|
+
...submission,
|
|
95
100
|
args: [...submission.args],
|
|
96
|
-
cwd: submission.cwd,
|
|
97
101
|
})),
|
|
98
102
|
submitted: state.submitted,
|
|
99
103
|
started: state.started,
|
|
@@ -111,12 +115,12 @@ export function snapshotGitCommandRuntimeMetrics() {
|
|
|
111
115
|
pending: gitProcessScheduler.pendingCount,
|
|
112
116
|
});
|
|
113
117
|
}
|
|
114
|
-
function submitGitCommandMetric(
|
|
118
|
+
function submitGitCommandMetric(submission) {
|
|
115
119
|
const state = gitCommandMetricsState;
|
|
116
120
|
if (!state) {
|
|
117
121
|
return null;
|
|
118
122
|
}
|
|
119
|
-
state.submissions.push({ args: [...args]
|
|
123
|
+
state.submissions.push({ ...submission, args: [...submission.args] });
|
|
120
124
|
state.submitted += 1;
|
|
121
125
|
state.lastSubmittedAtMs = Date.now();
|
|
122
126
|
return state;
|
|
@@ -157,7 +161,8 @@ export function runGitCommandBytes(args, options) {
|
|
|
157
161
|
return executeGitCommand(args, options, (output) => output);
|
|
158
162
|
}
|
|
159
163
|
function executeGitCommand(args, options, decode, provenance) {
|
|
160
|
-
const
|
|
164
|
+
const priority = gitCommandPriority.getStore() ?? "normal";
|
|
165
|
+
const metricsState = submitGitCommandMetric({ args, cwd: options.cwd, priority });
|
|
161
166
|
const commandTrace = submitGitCommandTrace(args, options.cwd, {
|
|
162
167
|
active: gitProcessScheduler.activeCount,
|
|
163
168
|
pending: gitProcessScheduler.pendingCount,
|
|
@@ -394,9 +399,7 @@ function executeGitCommand(args, options, decode, provenance) {
|
|
|
394
399
|
});
|
|
395
400
|
return { result: resultPromise, exited };
|
|
396
401
|
};
|
|
397
|
-
const promise = gitProcessScheduler.run(startCommand, {
|
|
398
|
-
priority: gitCommandPriority.getStore() ?? "normal",
|
|
399
|
-
});
|
|
402
|
+
const promise = gitProcessScheduler.run(startCommand, { priority });
|
|
400
403
|
gitRuntimeMetrics.observeLimiter(gitProcessScheduler.activeCount, gitProcessScheduler.pendingCount);
|
|
401
404
|
return promise;
|
|
402
405
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentBridge=function(){const l=(0,s.createDesktopPreviewUrlResolver)({reader:(0,s.createDesktopFileReader)(),objectUrls:(0,s.createBrowserObjectUrlMinter)()});return{copyFile:t.copyDesktopAttachmentFile,writeBase64:t.writeDesktopAttachmentBase64,writeBytes:t.writeDesktopAttachmentBytes,deleteFile:t.deleteDesktopAttachmentFile,garbageCollect:t.garbageCollectDesktopAttachmentFiles,readFileBase64:s.readDesktopFileBase64,resolvePreviewUrl:t=>l.resolve(t),releasePreviewUrl:t=>l.release(t)}};var t=r(d[0]),s=r(d[1])},
|
|
1
|
+
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentBridge=function(){const l=(0,s.createDesktopPreviewUrlResolver)({reader:(0,s.createDesktopFileReader)(),objectUrls:(0,s.createBrowserObjectUrlMinter)()});return{copyFile:t.copyDesktopAttachmentFile,writeBase64:t.writeDesktopAttachmentBase64,writeBytes:t.writeDesktopAttachmentBytes,deleteFile:t.deleteDesktopAttachmentFile,garbageCollect:t.garbageCollectDesktopAttachmentFiles,readFileBase64:s.readDesktopFileBase64,resolvePreviewUrl:t=>l.resolve(t),releasePreviewUrl:t=>l.release(t)}};var t=r(d[0]),s=r(d[1])},5200,[4426,4427]);
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentStore=function(n){return{storageType:"desktop-file",async save(s){const o=s.id??(0,t.generateAttachmentId)(),l=s.fileName??null;if("file_uri"===s.source.kind)return await c(n,{id:o,uri:s.source.uri,mimeType:s.mimeType,fileName:l});if("data_url"===s.source.kind){const c=(0,t.parseDataUrl)(s.source.dataUrl),p=(0,t.normalizeMimeType)(s.mimeType??c.mimeType);return await y(n,{id:o,base64:c.base64,mimeType:p,fileName:l})}if("bytes"===s.source.kind){const c=(0,t.normalizeMimeType)(s.mimeType);return await p(n,{id:o,bytes:s.source.bytes,mimeType:c,fileName:l})}const f=(0,t.normalizeMimeType)(s.mimeType??s.source.blob.type),u=await(0,t.blobToBase64)(s.source.blob);return await y(n,{id:o,base64:u,mimeType:f,fileName:l})},encodeBase64:async({attachment:t})=>(f(t),await n.readFileBase64(t.storageKey)),resolvePreviewUrl:async({attachment:t})=>(f(t),await n.resolvePreviewUrl(t)),async releasePreviewUrl({attachment:t,url:s}){f(t),await n.releasePreviewUrl({url:s})},async delete({attachment:t}){f(t),await n.deleteFile({path:t.storageKey})},async garbageCollect({referencedIds:t}){await n.garbageCollect({referencedIds:Array.from(t)})}}};var t=r(d[0]);const n={"image/png":".png","image/jpeg":".jpg","image/jpg":".jpg","image/gif":".gif","image/webp":".webp","image/avif":".avif","image/heic":".heic","image/heif":".heif","image/tiff":".tiff","image/bmp":".bmp","image/svg+xml":".svg"};function s(t){const n=t.replace(/\\/g,"/").split("/"),s=n[n.length-1];return s&&s.length>0?s:null}function o(s){const o=(0,t.getFileExtensionFromName)(s.fileName);if(o)return o;const l=(0,t.getFileExtensionFromName)(s.sourcePath);return l||(n[s.mimeType]??".img")}function l(t){return{id:t.id,mimeType:t.mimeType,storageType:"desktop-file",storageKey:t.storagePath,fileName:t.fileName??null,byteSize:t.byteSize,createdAt:Date.now()}}async function c(n,c){const y=(0,t.fileUriToPath)(c.uri),p=c.fileName??s(y),f=(0,t.normalizeMimeType)(c.mimeType),u=o({fileName:p,sourcePath:y,mimeType:f}),T=await n.copyFile({attachmentId:c.id,sourcePath:y,extension:u});return l({id:c.id,mimeType:f,storagePath:T.path,byteSize:T.byteSize,fileName:p})}async function y(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBase64({attachmentId:n.id,base64:n.base64,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}async function p(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBytes({attachmentId:n.id,bytes:n.bytes,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}function f(t){if("desktop-file"!==t.storageType)throw new Error(`Unsupported desktop attachment storage type '${t.storageType}'.`)}},
|
|
1
|
+
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentStore=function(n){return{storageType:"desktop-file",async save(s){const o=s.id??(0,t.generateAttachmentId)(),l=s.fileName??null;if("file_uri"===s.source.kind)return await c(n,{id:o,uri:s.source.uri,mimeType:s.mimeType,fileName:l});if("data_url"===s.source.kind){const c=(0,t.parseDataUrl)(s.source.dataUrl),p=(0,t.normalizeMimeType)(s.mimeType??c.mimeType);return await y(n,{id:o,base64:c.base64,mimeType:p,fileName:l})}if("bytes"===s.source.kind){const c=(0,t.normalizeMimeType)(s.mimeType);return await p(n,{id:o,bytes:s.source.bytes,mimeType:c,fileName:l})}const f=(0,t.normalizeMimeType)(s.mimeType??s.source.blob.type),u=await(0,t.blobToBase64)(s.source.blob);return await y(n,{id:o,base64:u,mimeType:f,fileName:l})},encodeBase64:async({attachment:t})=>(f(t),await n.readFileBase64(t.storageKey)),resolvePreviewUrl:async({attachment:t})=>(f(t),await n.resolvePreviewUrl(t)),async releasePreviewUrl({attachment:t,url:s}){f(t),await n.releasePreviewUrl({url:s})},async delete({attachment:t}){f(t),await n.deleteFile({path:t.storageKey})},async garbageCollect({referencedIds:t}){await n.garbageCollect({referencedIds:Array.from(t)})}}};var t=r(d[0]);const n={"image/png":".png","image/jpeg":".jpg","image/jpg":".jpg","image/gif":".gif","image/webp":".webp","image/avif":".avif","image/heic":".heic","image/heif":".heif","image/tiff":".tiff","image/bmp":".bmp","image/svg+xml":".svg"};function s(t){const n=t.replace(/\\/g,"/").split("/"),s=n[n.length-1];return s&&s.length>0?s:null}function o(s){const o=(0,t.getFileExtensionFromName)(s.fileName);if(o)return o;const l=(0,t.getFileExtensionFromName)(s.sourcePath);return l||(n[s.mimeType]??".img")}function l(t){return{id:t.id,mimeType:t.mimeType,storageType:"desktop-file",storageKey:t.storagePath,fileName:t.fileName??null,byteSize:t.byteSize,createdAt:Date.now()}}async function c(n,c){const y=(0,t.fileUriToPath)(c.uri),p=c.fileName??s(y),f=(0,t.normalizeMimeType)(c.mimeType),u=o({fileName:p,sourcePath:y,mimeType:f}),T=await n.copyFile({attachmentId:c.id,sourcePath:y,extension:u});return l({id:c.id,mimeType:f,storagePath:T.path,byteSize:T.byteSize,fileName:p})}async function y(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBase64({attachmentId:n.id,base64:n.base64,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}async function p(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBytes({attachmentId:n.id,bytes:n.bytes,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}function f(t){if("desktop-file"!==t.storageType)throw new Error(`Unsupported desktop attachment storage type '${t.storageType}'.`)}},5199,[4301]);
|