@chainingintention/pi-web-cn 1.202606.27 → 1.202607.0
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/client/assets/{CodeViewer-hxitRRG6.js → CodeViewer-B8UDBbru.js} +1 -1
- package/dist/client/assets/{TerminalPanel-DTn18hoY.js → TerminalPanel-BG0-cSjI.js} +1 -1
- package/dist/client/assets/{UnifiedDiffViewer-DTCywBXP.js → UnifiedDiffViewer-C9IllVsZ.js} +1 -1
- package/dist/client/assets/{index-B2qK0xv5.js → index-DFaXWsru.js} +199 -199
- package/dist/client/index.html +1 -1
- package/dist/server/sessions/piSessionService.js +239 -10
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionArchiveStore.js +51 -22
- package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +35 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/shared/apiTypes.d.ts +24 -0
- package/dist/shared/apiTypes.js +1 -0
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +3 -2
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +2 -0
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/package.json +1 -1
package/dist/client/index.html
CHANGED
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--pi-bg); color: var(--pi-text); }
|
|
54
54
|
body { min-height: 100dvh; }
|
|
55
55
|
</style>
|
|
56
|
-
<script type="module" crossorigin src="/assets/index-
|
|
56
|
+
<script type="module" crossorigin src="/assets/index-DFaXWsru.js"></script>
|
|
57
57
|
<link rel="modulepreload" crossorigin href="/assets/vendor-editor-core-C7aWiQy0.js">
|
|
58
58
|
<link rel="modulepreload" crossorigin href="/assets/vendor-editor-languages-EW34FfVy.js">
|
|
59
59
|
</head>
|
|
@@ -260,10 +260,12 @@ export class PiSessionService {
|
|
|
260
260
|
}
|
|
261
261
|
async cleanup(request) {
|
|
262
262
|
const plan = await this.cleanupPlan(request);
|
|
263
|
-
if (plan.deleteRecords.length > 0 && this.archiveStore.deleteArchived === undefined)
|
|
263
|
+
if (plan.deleteRecords.length > 0 && this.archiveStore.deleteArchived === undefined && this.archiveStore.deleteArchivedMany === undefined)
|
|
264
264
|
throw new Error("Archive store does not support deletion");
|
|
265
265
|
const archiveInputs = [];
|
|
266
|
+
const readyArchiveInputs = [];
|
|
266
267
|
const deleteRecords = [];
|
|
268
|
+
const readyDeleteRecords = [];
|
|
267
269
|
const skippedBusySessionIds = new Set(plan.skippedBusySessionIds);
|
|
268
270
|
for (const input of plan.archiveInputs) {
|
|
269
271
|
if (this.activeSessionHasWork(input.sessionId)) {
|
|
@@ -271,20 +273,21 @@ export class PiSessionService {
|
|
|
271
273
|
continue;
|
|
272
274
|
}
|
|
273
275
|
await this.closeActive(input.sessionId);
|
|
274
|
-
|
|
275
|
-
archiveInputs.push(input);
|
|
276
|
+
readyArchiveInputs.push(input);
|
|
276
277
|
}
|
|
278
|
+
await this.archiveStoreArchiveMany(readyArchiveInputs);
|
|
279
|
+
archiveInputs.push(...readyArchiveInputs);
|
|
277
280
|
for (const record of plan.deleteRecords) {
|
|
278
281
|
if (this.activeSessionHasWork(record.sessionId)) {
|
|
279
282
|
skippedBusySessionIds.add(record.sessionId);
|
|
280
283
|
continue;
|
|
281
284
|
}
|
|
282
285
|
await this.closeActive(record.sessionId);
|
|
283
|
-
|
|
284
|
-
await this.ensureArchivedRecordMoved(record);
|
|
285
|
-
await this.archiveStore.deleteArchived?.(record.sessionId);
|
|
286
|
-
deleteRecords.push(record);
|
|
286
|
+
readyDeleteRecords.push(record);
|
|
287
287
|
}
|
|
288
|
+
await this.ensureArchivedRecordsMoved(readyDeleteRecords);
|
|
289
|
+
const deletedSessionIds = new Set(await this.archiveStoreDeleteArchivedMany(readyDeleteRecords.map((record) => record.sessionId)));
|
|
290
|
+
deleteRecords.push(...readyDeleteRecords.filter((record) => deletedSessionIds.has(record.sessionId)));
|
|
288
291
|
return summarizeSessionCleanupExecution({
|
|
289
292
|
archiveInputs,
|
|
290
293
|
deleteRecords,
|
|
@@ -920,6 +923,69 @@ export class PiSessionService {
|
|
|
920
923
|
await this.closeActive(session.sessionId);
|
|
921
924
|
await this.archiveStore.archive(archiveInput);
|
|
922
925
|
}
|
|
926
|
+
async archiveMany(refs) {
|
|
927
|
+
const uniqueRefs = uniqueBulkSessionRefs(refs);
|
|
928
|
+
const [archivedRecords, sessionContext] = await Promise.all([
|
|
929
|
+
this.archiveStore.list(),
|
|
930
|
+
this.bulkSessionLookupContext(uniqueRefs),
|
|
931
|
+
]);
|
|
932
|
+
const failures = [];
|
|
933
|
+
const alreadyArchivedSessionIds = [];
|
|
934
|
+
const planItems = [];
|
|
935
|
+
for (const ref of uniqueRefs) {
|
|
936
|
+
const archived = findArchivedRecordForBulkRef(archivedRecords, ref);
|
|
937
|
+
if (archived !== undefined) {
|
|
938
|
+
alreadyArchivedSessionIds.push(archived.sessionId);
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
941
|
+
const active = this.activeForLookup(bulkRefToLookup(ref));
|
|
942
|
+
const listed = findListedSessionForBulkRef(sessionContext, ref);
|
|
943
|
+
const resolvedSessionId = active?.runtime.session.sessionId ?? listed?.id ?? ref.id;
|
|
944
|
+
if (active !== undefined && this.hasActiveWork(active.runtime.session)) {
|
|
945
|
+
failures.push({ sessionId: resolvedSessionId, error: "Stop current session activity before archiving" });
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
try {
|
|
949
|
+
if (listed !== undefined) {
|
|
950
|
+
planItems.push({ input: archiveInputFromListEntry(listed) });
|
|
951
|
+
}
|
|
952
|
+
else if (active !== undefined) {
|
|
953
|
+
planItems.push({ input: archiveInputFromActiveSession(active.runtime.session) });
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
failures.push({ sessionId: ref.id, error: "Session not found" });
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
catch (error) {
|
|
960
|
+
failures.push({ sessionId: resolvedSessionId, error: errorMessage(error) });
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
const readyInputs = [];
|
|
964
|
+
for (const item of planItems) {
|
|
965
|
+
try {
|
|
966
|
+
await this.closeActive(item.input.sessionId);
|
|
967
|
+
readyInputs.push(item.input);
|
|
968
|
+
}
|
|
969
|
+
catch (error) {
|
|
970
|
+
failures.push({ sessionId: item.input.sessionId, error: errorMessage(error) });
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
const archivedSessionIds = [...alreadyArchivedSessionIds];
|
|
974
|
+
try {
|
|
975
|
+
const archived = await this.archiveStoreArchiveMany(readyInputs);
|
|
976
|
+
archivedSessionIds.push(...archived.map((record) => record.sessionId));
|
|
977
|
+
}
|
|
978
|
+
catch (error) {
|
|
979
|
+
for (const input of readyInputs)
|
|
980
|
+
failures.push({ sessionId: input.sessionId, error: errorMessage(error) });
|
|
981
|
+
}
|
|
982
|
+
return {
|
|
983
|
+
archived: true,
|
|
984
|
+
archivedSessionIds: uniqueStrings(archivedSessionIds),
|
|
985
|
+
failures,
|
|
986
|
+
generatedAt: new Date().toISOString(),
|
|
987
|
+
};
|
|
988
|
+
}
|
|
923
989
|
async archiveTree(ref) {
|
|
924
990
|
const session = await this.getOrOpen(ref);
|
|
925
991
|
const catalog = await this.workspaceArchiveCandidates(session.sessionManager.getCwd());
|
|
@@ -931,8 +997,7 @@ export class PiSessionService {
|
|
|
931
997
|
const archiveInputs = plan.unarchivedTargets.map((target) => archiveInputFromCandidate(target));
|
|
932
998
|
for (const input of archiveInputs)
|
|
933
999
|
await this.closeActive(input.sessionId);
|
|
934
|
-
|
|
935
|
-
await this.archiveStore.archive(input);
|
|
1000
|
+
await this.archiveStoreArchiveMany(archiveInputs);
|
|
936
1001
|
return {
|
|
937
1002
|
archived: true,
|
|
938
1003
|
sessionIds: archiveInputs.map((input) => input.sessionId),
|
|
@@ -958,6 +1023,57 @@ export class PiSessionService {
|
|
|
958
1023
|
await this.ensureArchivedRecordMoved(record);
|
|
959
1024
|
await this.archiveStore.deleteArchived(record.sessionId);
|
|
960
1025
|
}
|
|
1026
|
+
async deleteArchivedMany(refs) {
|
|
1027
|
+
if (this.archiveStore.deleteArchived === undefined && this.archiveStore.deleteArchivedMany === undefined)
|
|
1028
|
+
throw new Error("Archive store does not support deletion");
|
|
1029
|
+
const uniqueRefs = uniqueBulkSessionRefs(refs);
|
|
1030
|
+
const archivedRecords = await this.archiveStore.list();
|
|
1031
|
+
const failures = [];
|
|
1032
|
+
const planItems = [];
|
|
1033
|
+
for (const ref of uniqueRefs) {
|
|
1034
|
+
const record = findArchivedRecordForBulkRef(archivedRecords, ref);
|
|
1035
|
+
if (record === undefined) {
|
|
1036
|
+
failures.push({ sessionId: ref.id, error: "Archived session not found" });
|
|
1037
|
+
continue;
|
|
1038
|
+
}
|
|
1039
|
+
const active = this.activeForLookup({ id: record.sessionId, cwd: record.cwd });
|
|
1040
|
+
if (active !== undefined && this.hasActiveWork(active.runtime.session)) {
|
|
1041
|
+
failures.push({ sessionId: record.sessionId, error: "Stop current session activity before deleting archived session" });
|
|
1042
|
+
continue;
|
|
1043
|
+
}
|
|
1044
|
+
planItems.push({ record });
|
|
1045
|
+
}
|
|
1046
|
+
const readyRecords = [];
|
|
1047
|
+
for (const item of planItems) {
|
|
1048
|
+
try {
|
|
1049
|
+
await this.closeActive(item.record.sessionId);
|
|
1050
|
+
readyRecords.push(item.record);
|
|
1051
|
+
}
|
|
1052
|
+
catch (error) {
|
|
1053
|
+
failures.push({ sessionId: item.record.sessionId, error: errorMessage(error) });
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
const moveFailures = await this.moveLegacyArchivedRecordsForDelete(readyRecords);
|
|
1057
|
+
failures.push(...moveFailures);
|
|
1058
|
+
const moveFailureIds = new Set(moveFailures.map((failure) => failure.sessionId));
|
|
1059
|
+
const deleteIds = readyRecords
|
|
1060
|
+
.map((record) => record.sessionId)
|
|
1061
|
+
.filter((sessionId) => !moveFailureIds.has(sessionId));
|
|
1062
|
+
let deletedSessionIds = [];
|
|
1063
|
+
try {
|
|
1064
|
+
deletedSessionIds = await this.archiveStoreDeleteArchivedMany(deleteIds);
|
|
1065
|
+
}
|
|
1066
|
+
catch (error) {
|
|
1067
|
+
for (const sessionId of deleteIds)
|
|
1068
|
+
failures.push({ sessionId, error: errorMessage(error) });
|
|
1069
|
+
}
|
|
1070
|
+
return {
|
|
1071
|
+
deleted: true,
|
|
1072
|
+
deletedSessionIds,
|
|
1073
|
+
failures,
|
|
1074
|
+
generatedAt: new Date().toISOString(),
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
961
1077
|
async reload(ref) {
|
|
962
1078
|
await this.assertWritable(ref);
|
|
963
1079
|
const session = await this.getOrOpen(ref);
|
|
@@ -995,6 +1111,75 @@ export class PiSessionService {
|
|
|
995
1111
|
// Best-effort shutdown; callers that need errors await closeActive directly.
|
|
996
1112
|
});
|
|
997
1113
|
}
|
|
1114
|
+
async bulkSessionLookupContext(refs) {
|
|
1115
|
+
const cwdSet = new Set();
|
|
1116
|
+
let needsAllSessions = false;
|
|
1117
|
+
for (const ref of refs) {
|
|
1118
|
+
if (ref.cwd === undefined)
|
|
1119
|
+
needsAllSessions = true;
|
|
1120
|
+
else
|
|
1121
|
+
cwdSet.add(ref.cwd);
|
|
1122
|
+
}
|
|
1123
|
+
const [sessionsByCwd, allSessions] = await Promise.all([
|
|
1124
|
+
this.listSessionsByCwd([...cwdSet]),
|
|
1125
|
+
needsAllSessions ? this.sessionManager.listAll?.() ?? Promise.resolve([]) : Promise.resolve(undefined),
|
|
1126
|
+
]);
|
|
1127
|
+
return allSessions === undefined ? { sessionsByCwd } : { sessionsByCwd, allSessions };
|
|
1128
|
+
}
|
|
1129
|
+
async listSessionsByCwd(cwds) {
|
|
1130
|
+
const uniqueCwds = uniqueStrings(cwds);
|
|
1131
|
+
const entries = await Promise.all(uniqueCwds.map(async (cwd) => [cwd, await this.sessionManager.list(cwd)]));
|
|
1132
|
+
return new Map(entries);
|
|
1133
|
+
}
|
|
1134
|
+
async archiveStoreArchiveMany(inputs) {
|
|
1135
|
+
if (inputs.length === 0)
|
|
1136
|
+
return [];
|
|
1137
|
+
if (this.archiveStore.archiveMany !== undefined)
|
|
1138
|
+
return this.archiveStore.archiveMany(inputs);
|
|
1139
|
+
const records = [];
|
|
1140
|
+
for (const input of inputs)
|
|
1141
|
+
records.push(await this.archiveStore.archive(input));
|
|
1142
|
+
return records;
|
|
1143
|
+
}
|
|
1144
|
+
async archiveStoreDeleteArchivedMany(sessionIds) {
|
|
1145
|
+
if (sessionIds.length === 0)
|
|
1146
|
+
return [];
|
|
1147
|
+
if (this.archiveStore.deleteArchivedMany !== undefined)
|
|
1148
|
+
return this.archiveStore.deleteArchivedMany(sessionIds);
|
|
1149
|
+
if (this.archiveStore.deleteArchived === undefined)
|
|
1150
|
+
throw new Error("Archive store does not support deletion");
|
|
1151
|
+
for (const sessionId of sessionIds)
|
|
1152
|
+
await this.archiveStore.deleteArchived(sessionId);
|
|
1153
|
+
return [...sessionIds];
|
|
1154
|
+
}
|
|
1155
|
+
async moveLegacyArchivedRecordsForDelete(records) {
|
|
1156
|
+
const legacyRecords = records.filter((record) => record.archivePath === undefined);
|
|
1157
|
+
if (legacyRecords.length === 0)
|
|
1158
|
+
return [];
|
|
1159
|
+
let sessionsByCwd;
|
|
1160
|
+
try {
|
|
1161
|
+
sessionsByCwd = await this.listSessionsByCwd(legacyRecords.map((record) => record.cwd));
|
|
1162
|
+
}
|
|
1163
|
+
catch (error) {
|
|
1164
|
+
return legacyRecords.map((record) => ({ sessionId: record.sessionId, error: errorMessage(error) }));
|
|
1165
|
+
}
|
|
1166
|
+
const moveInputs = legacyRecords
|
|
1167
|
+
.map((record) => findSessionByIdOrPrefix(sessionsByCwd.get(record.cwd) ?? [], record.sessionId))
|
|
1168
|
+
.filter(isDefined)
|
|
1169
|
+
.map(archiveInputFromListEntry);
|
|
1170
|
+
if (moveInputs.length === 0)
|
|
1171
|
+
return [];
|
|
1172
|
+
try {
|
|
1173
|
+
await this.archiveStoreArchiveMany(moveInputs);
|
|
1174
|
+
return [];
|
|
1175
|
+
}
|
|
1176
|
+
catch (error) {
|
|
1177
|
+
const failedIds = new Set(moveInputs.map((input) => input.sessionId));
|
|
1178
|
+
return legacyRecords
|
|
1179
|
+
.filter((record) => failedIds.has(record.sessionId))
|
|
1180
|
+
.map((record) => ({ sessionId: record.sessionId, error: errorMessage(error) }));
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
998
1183
|
async cleanupPlan(request) {
|
|
999
1184
|
const [sessions, archivedRecords] = await Promise.all([this.sessionManager.listAll?.() ?? [], this.archiveStore.list()]);
|
|
1000
1185
|
return planSessionCleanup({
|
|
@@ -1039,7 +1224,19 @@ export class PiSessionService {
|
|
|
1039
1224
|
const session = (await this.sessionManager.list(record.cwd)).find((candidate) => candidate.id === record.sessionId);
|
|
1040
1225
|
if (session === undefined)
|
|
1041
1226
|
return record;
|
|
1042
|
-
|
|
1227
|
+
const [moved] = await this.archiveStoreArchiveMany([archiveInputFromListEntry(session)]);
|
|
1228
|
+
return moved ?? record;
|
|
1229
|
+
}
|
|
1230
|
+
async ensureArchivedRecordsMoved(records) {
|
|
1231
|
+
const legacyRecords = records.filter((record) => record.archivePath === undefined);
|
|
1232
|
+
if (legacyRecords.length === 0)
|
|
1233
|
+
return;
|
|
1234
|
+
const sessionsByCwd = await this.listSessionsByCwd(legacyRecords.map((record) => record.cwd));
|
|
1235
|
+
const moveInputs = legacyRecords
|
|
1236
|
+
.map((record) => sessionsByCwd.get(record.cwd)?.find((candidate) => candidate.id === record.sessionId))
|
|
1237
|
+
.filter(isDefined)
|
|
1238
|
+
.map(archiveInputFromListEntry);
|
|
1239
|
+
await this.archiveStoreArchiveMany(moveInputs);
|
|
1043
1240
|
}
|
|
1044
1241
|
async archiveInputForSession(session) {
|
|
1045
1242
|
const cwd = session.sessionManager.getCwd();
|
|
@@ -1507,6 +1704,38 @@ function previewResponseFromPlan(plan) {
|
|
|
1507
1704
|
...(plan.skippedBusySessionIds.length === 0 ? {} : { skippedBusySessionIds: plan.skippedBusySessionIds }),
|
|
1508
1705
|
};
|
|
1509
1706
|
}
|
|
1707
|
+
function uniqueBulkSessionRefs(refs) {
|
|
1708
|
+
const seen = new Set();
|
|
1709
|
+
const unique = [];
|
|
1710
|
+
for (const ref of refs) {
|
|
1711
|
+
const key = `${ref.cwd ?? ""}\0${ref.id}`;
|
|
1712
|
+
if (seen.has(key))
|
|
1713
|
+
continue;
|
|
1714
|
+
seen.add(key);
|
|
1715
|
+
unique.push(ref);
|
|
1716
|
+
}
|
|
1717
|
+
return unique;
|
|
1718
|
+
}
|
|
1719
|
+
function bulkRefToLookup(ref) {
|
|
1720
|
+
return ref.cwd === undefined ? ref.id : { id: ref.id, cwd: ref.cwd };
|
|
1721
|
+
}
|
|
1722
|
+
function findArchivedRecordForBulkRef(records, ref) {
|
|
1723
|
+
return records.find((record) => (ref.cwd === undefined || record.cwd === ref.cwd) && (record.sessionId === ref.id || record.sessionId.startsWith(ref.id)));
|
|
1724
|
+
}
|
|
1725
|
+
function findListedSessionForBulkRef(context, ref) {
|
|
1726
|
+
if (ref.cwd !== undefined)
|
|
1727
|
+
return findSessionByIdOrPrefix(context.sessionsByCwd.get(ref.cwd) ?? [], ref.id);
|
|
1728
|
+
return context.allSessions === undefined ? undefined : findSessionByIdOrPrefix(context.allSessions, ref.id);
|
|
1729
|
+
}
|
|
1730
|
+
function findSessionByIdOrPrefix(sessions, sessionId) {
|
|
1731
|
+
return sessions.find((session) => session.id === sessionId) ?? sessions.find((session) => session.id.startsWith(sessionId));
|
|
1732
|
+
}
|
|
1733
|
+
function uniqueStrings(values) {
|
|
1734
|
+
return [...new Set(values)];
|
|
1735
|
+
}
|
|
1736
|
+
function errorMessage(error) {
|
|
1737
|
+
return error instanceof Error ? error.message : String(error);
|
|
1738
|
+
}
|
|
1510
1739
|
function modelToClientModel(model) {
|
|
1511
1740
|
if (model === undefined)
|
|
1512
1741
|
return {};
|