@heyditto/cli 2.42.0 → 3.0.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/README.md +21 -18
- package/dist/cli.js +2 -3
- package/dist/cli.js.map +1 -1
- package/dist/remote/plugin-server.d.ts +11 -0
- package/dist/remote/plugin-server.js +77 -0
- package/dist/remote/plugin-server.js.map +1 -0
- package/dist/remote/session-link.d.ts +5 -0
- package/dist/remote/session-link.js +7 -0
- package/dist/remote/session-link.js.map +1 -0
- package/dist/review-commands.js +12 -5
- package/dist/review-commands.js.map +1 -1
- package/dist/teleport/api.d.ts +2 -2
- package/dist/teleport/archive.d.ts +88 -0
- package/dist/teleport/archive.js +280 -0
- package/dist/teleport/archive.js.map +1 -0
- package/dist/teleport/commands.d.ts +9 -0
- package/dist/teleport/commands.js +71 -0
- package/dist/teleport/commands.js.map +1 -1
- package/dist/update-lock.json +1 -1
- package/package.json +2 -2
package/dist/teleport/api.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Manifest } from "./types.js";
|
|
|
2
2
|
export interface Capsule {
|
|
3
3
|
id: string;
|
|
4
4
|
name: string;
|
|
5
|
-
rootKind: "repo" | "folder";
|
|
5
|
+
rootKind: "repo" | "folder" | "archive";
|
|
6
6
|
harnessKind?: string;
|
|
7
7
|
harnessSessionId?: string | null;
|
|
8
8
|
headGeneration: number;
|
|
@@ -96,7 +96,7 @@ export type CommittedBy = "cli" | "runner";
|
|
|
96
96
|
export declare function listCapsules(): Promise<Capsule[]>;
|
|
97
97
|
export declare function createCapsule(input: {
|
|
98
98
|
name: string;
|
|
99
|
-
rootKind: "repo" | "folder";
|
|
99
|
+
rootKind: "repo" | "folder" | "archive";
|
|
100
100
|
harnessKind?: string;
|
|
101
101
|
harnessSessionId?: string;
|
|
102
102
|
mirrorPolicy?: Capsule["mirrorPolicy"];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type ChunkRef } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Archive capsules back up trees that only grow: coding-agent session
|
|
4
|
+
* history and local recovery data. Each source is one tar stream, cut into
|
|
5
|
+
* content-defined chunks (gear rolling hash) so an append or an edit only
|
|
6
|
+
* changes the chunks around it, and every chunk is zstd-compressed on its own
|
|
7
|
+
* so it dedupes by content and restores without its neighbours. The manifest
|
|
8
|
+
* lists the chunks in order; restore decompresses and concatenates them.
|
|
9
|
+
*/
|
|
10
|
+
export interface ArchiveSource {
|
|
11
|
+
/** Unique name in the capsule, e.g. "claude-code". */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Directory whose contents are archived (paths stored relative to it). */
|
|
14
|
+
dir: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ArchiveEntry {
|
|
17
|
+
name: string;
|
|
18
|
+
format: "tar";
|
|
19
|
+
chunkCompression: "zstd";
|
|
20
|
+
chunks: ChunkRef[];
|
|
21
|
+
entries: number;
|
|
22
|
+
bytes: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ArchiveManifest {
|
|
25
|
+
v: number;
|
|
26
|
+
capsuleId: string;
|
|
27
|
+
generation: number;
|
|
28
|
+
parentGeneration: number;
|
|
29
|
+
createdAt: string;
|
|
30
|
+
machine: Record<string, unknown>;
|
|
31
|
+
root: {
|
|
32
|
+
kind: "archive";
|
|
33
|
+
name: string;
|
|
34
|
+
};
|
|
35
|
+
repos: [];
|
|
36
|
+
archives: ArchiveEntry[];
|
|
37
|
+
harness: {
|
|
38
|
+
kind: "none";
|
|
39
|
+
chunks: [];
|
|
40
|
+
};
|
|
41
|
+
totals: {
|
|
42
|
+
chunks: number;
|
|
43
|
+
bytes: number;
|
|
44
|
+
dedupedBytes?: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Content-defined boundaries over a buffer: a cut where the rolling hash's low
|
|
49
|
+
* bits are zero, bounded by MIN_CHUNK and MAX_CHUNK. Exported for tests.
|
|
50
|
+
*/
|
|
51
|
+
export declare function cdcBoundaries(buf: Buffer): number[];
|
|
52
|
+
export interface BuiltArchive {
|
|
53
|
+
entry: ArchiveEntry;
|
|
54
|
+
/** sha256 → compressed bytes on disk, for upload. */
|
|
55
|
+
files: Map<string, string>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Tars `src.dir` and writes each compressed chunk into `outDir`. The tar is
|
|
59
|
+
* read through a window of at most MAX_CHUNK + one read, so memory stays
|
|
60
|
+
* bounded however large the source grows; boundaries match cdcBoundaries.
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildArchive(src: ArchiveSource, outDir: string): Promise<BuiltArchive>;
|
|
63
|
+
export interface ArchivePushOutput {
|
|
64
|
+
generation: number;
|
|
65
|
+
logicalBytes: number;
|
|
66
|
+
storedBytes: number;
|
|
67
|
+
uploadedBytes: number;
|
|
68
|
+
uploaded: number;
|
|
69
|
+
reused: number;
|
|
70
|
+
archives: {
|
|
71
|
+
name: string;
|
|
72
|
+
entries: number;
|
|
73
|
+
bytes: number;
|
|
74
|
+
chunks: number;
|
|
75
|
+
}[];
|
|
76
|
+
}
|
|
77
|
+
/** Builds every source, uploads only chunks the server lacks, commits a generation. */
|
|
78
|
+
export declare function pushArchive(capsuleId: string, rootName: string, sources: ArchiveSource[], parentGeneration: number): Promise<ArchivePushOutput>;
|
|
79
|
+
/**
|
|
80
|
+
* Restores one archive of a generation into `dest` (which must not exist):
|
|
81
|
+
* downloads each chunk, checks its sha256, decompresses and untars.
|
|
82
|
+
*/
|
|
83
|
+
export declare function restoreArchive(capsuleId: string, name: string, dest: string, generation?: number): Promise<{
|
|
84
|
+
entries: number;
|
|
85
|
+
bytes: number;
|
|
86
|
+
}>;
|
|
87
|
+
/** Default sources: agent session history and infinite-disk's retained recovery data. */
|
|
88
|
+
export declare function defaultArchiveSources(home?: string): ArchiveSource[];
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { createReadStream, createWriteStream } from "node:fs";
|
|
4
|
+
import { mkdir, mkdtemp, open, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { zstdCompressSync, zstdDecompressSync } from "node:zlib";
|
|
8
|
+
import { packageVersion } from "../config.js";
|
|
9
|
+
import * as tapi from "./api.js";
|
|
10
|
+
import { CHUNK_BYTES, MANIFEST_VERSION, machineInfo } from "./types.js";
|
|
11
|
+
const MIN_CHUNK = 512 * 1024;
|
|
12
|
+
const AVG_BITS = 21; // ~2 MiB average
|
|
13
|
+
const MAX_CHUNK = 8 * 1024 * 1024;
|
|
14
|
+
const MASK = (1 << AVG_BITS) - 1;
|
|
15
|
+
const NEGOTIATE_BATCH = 200;
|
|
16
|
+
const PUT_CONCURRENCY = 4;
|
|
17
|
+
/** Deterministic gear table: chunk boundaries must match across machines. */
|
|
18
|
+
const GEAR = (() => {
|
|
19
|
+
const t = new Uint32Array(256);
|
|
20
|
+
for (let i = 0; i < 256; i++) {
|
|
21
|
+
t[i] = createHash("sha256").update(`ditto-archive-gear-${i}`).digest().readUInt32LE(0);
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
})();
|
|
25
|
+
/**
|
|
26
|
+
* Content-defined boundaries over a buffer: a cut where the rolling hash's low
|
|
27
|
+
* bits are zero, bounded by MIN_CHUNK and MAX_CHUNK. Exported for tests.
|
|
28
|
+
*/
|
|
29
|
+
export function cdcBoundaries(buf) {
|
|
30
|
+
const cuts = [];
|
|
31
|
+
let start = 0;
|
|
32
|
+
while (start < buf.length) {
|
|
33
|
+
const end = Math.min(buf.length, start + MAX_CHUNK);
|
|
34
|
+
let cut = end;
|
|
35
|
+
let h = 0;
|
|
36
|
+
for (let i = start + MIN_CHUNK; i < end; i++) {
|
|
37
|
+
h = ((h << 1) + GEAR[buf[i]]) >>> 0;
|
|
38
|
+
if ((h & MASK) === 0) {
|
|
39
|
+
cut = i + 1;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
cuts.push(cut);
|
|
44
|
+
start = cut;
|
|
45
|
+
}
|
|
46
|
+
return cuts;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Tars `src.dir` and writes each compressed chunk into `outDir`. The tar is
|
|
50
|
+
* read through a window of at most MAX_CHUNK + one read, so memory stays
|
|
51
|
+
* bounded however large the source grows; boundaries match cdcBoundaries.
|
|
52
|
+
*/
|
|
53
|
+
export async function buildArchive(src, outDir) {
|
|
54
|
+
const tarFile = path.join(outDir, `${safe(src.name)}.tar`);
|
|
55
|
+
const entries = await tarDirectory(src.dir, tarFile);
|
|
56
|
+
const chunks = [];
|
|
57
|
+
const files = new Map();
|
|
58
|
+
let bytes = 0;
|
|
59
|
+
const emit = async (piece) => {
|
|
60
|
+
const z = zstdCompressSync(piece);
|
|
61
|
+
if (z.length > CHUNK_BYTES)
|
|
62
|
+
throw new Error(`compressed chunk exceeds ${CHUNK_BYTES} bytes`);
|
|
63
|
+
const sha = createHash("sha256").update(z).digest("hex");
|
|
64
|
+
chunks.push({ sha256: sha, size: z.length });
|
|
65
|
+
if (!files.has(sha)) {
|
|
66
|
+
const file = path.join(outDir, sha);
|
|
67
|
+
await writeFile(file, z);
|
|
68
|
+
files.set(sha, file);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
let pending = Buffer.alloc(0);
|
|
73
|
+
for await (const piece of createReadStream(tarFile, { highWaterMark: 1 << 20 })) {
|
|
74
|
+
const buf = piece;
|
|
75
|
+
bytes += buf.length;
|
|
76
|
+
pending = pending.length === 0 ? buf : Buffer.concat([pending, buf]);
|
|
77
|
+
// A cut is final once MAX_CHUNK bytes follow its start: later data
|
|
78
|
+
// can't move it. Keep the unfinished tail.
|
|
79
|
+
while (pending.length >= MAX_CHUNK) {
|
|
80
|
+
const cut = cdcBoundaries(pending.subarray(0, MAX_CHUNK))[0];
|
|
81
|
+
await emit(Buffer.from(pending.subarray(0, cut)));
|
|
82
|
+
pending = Buffer.from(pending.subarray(cut));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// The tail is under MAX_CHUNK; its cuts are offsets into this buffer.
|
|
86
|
+
let start = 0;
|
|
87
|
+
for (const cut of cdcBoundaries(pending)) {
|
|
88
|
+
await emit(Buffer.from(pending.subarray(start, cut)));
|
|
89
|
+
start = cut;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await rm(tarFile, { force: true });
|
|
94
|
+
}
|
|
95
|
+
return { entry: { name: src.name, format: "tar", chunkCompression: "zstd", chunks, entries, bytes }, files };
|
|
96
|
+
}
|
|
97
|
+
/** tar with paths relative to `dir`; returns the entry count. */
|
|
98
|
+
async function tarDirectory(dir, outFile) {
|
|
99
|
+
const info = await stat(dir);
|
|
100
|
+
if (!info.isDirectory())
|
|
101
|
+
throw new Error(`${dir} is not a directory`);
|
|
102
|
+
const list = await run("tar", ["-c", "-f", outFile, "-C", dir, "."]);
|
|
103
|
+
if (list.code !== 0)
|
|
104
|
+
throw new Error(`tar failed for ${dir}: ${list.stderr.trim()}`);
|
|
105
|
+
const count = await run("tar", ["-t", "-f", outFile]);
|
|
106
|
+
return count.stdout.split("\n").filter((l) => l && !l.endsWith("/")).length;
|
|
107
|
+
}
|
|
108
|
+
/** Builds every source, uploads only chunks the server lacks, commits a generation. */
|
|
109
|
+
export async function pushArchive(capsuleId, rootName, sources, parentGeneration) {
|
|
110
|
+
const tmp = await mkdtemp(path.join(os.tmpdir(), "teleport-archive-"));
|
|
111
|
+
try {
|
|
112
|
+
const archives = [];
|
|
113
|
+
const files = new Map();
|
|
114
|
+
for (const src of sources) {
|
|
115
|
+
const built = await buildArchive(src, tmp);
|
|
116
|
+
archives.push(built.entry);
|
|
117
|
+
for (const [sha, file] of built.files)
|
|
118
|
+
files.set(sha, file);
|
|
119
|
+
}
|
|
120
|
+
const all = archives.flatMap((a) => a.chunks);
|
|
121
|
+
const distinct = new Map();
|
|
122
|
+
for (const c of all)
|
|
123
|
+
distinct.set(c.sha256, c);
|
|
124
|
+
const generation = parentGeneration + 1;
|
|
125
|
+
const manifest = {
|
|
126
|
+
v: MANIFEST_VERSION,
|
|
127
|
+
capsuleId,
|
|
128
|
+
generation,
|
|
129
|
+
parentGeneration,
|
|
130
|
+
createdAt: new Date().toISOString(),
|
|
131
|
+
machine: machineInfo(packageVersion),
|
|
132
|
+
root: { kind: "archive", name: rootName },
|
|
133
|
+
repos: [],
|
|
134
|
+
archives,
|
|
135
|
+
harness: { kind: "none", chunks: [] },
|
|
136
|
+
totals: { chunks: distinct.size, bytes: [...distinct.values()].reduce((n, c) => n + c.size, 0) },
|
|
137
|
+
};
|
|
138
|
+
const manifestBytes = Buffer.from(JSON.stringify(manifest));
|
|
139
|
+
const manifestSha = createHash("sha256").update(manifestBytes).digest("hex");
|
|
140
|
+
const manifestFile = path.join(tmp, "manifest.json");
|
|
141
|
+
const fh = await open(manifestFile, "w");
|
|
142
|
+
await fh.writeFile(manifestBytes);
|
|
143
|
+
await fh.close();
|
|
144
|
+
files.set(manifestSha, manifestFile);
|
|
145
|
+
distinct.set(manifestSha, { sha256: manifestSha, size: manifestBytes.length });
|
|
146
|
+
const wanted = [...distinct.values()];
|
|
147
|
+
let uploaded = 0;
|
|
148
|
+
let uploadedBytes = 0;
|
|
149
|
+
for (let i = 0; i < wanted.length; i += NEGOTIATE_BATCH) {
|
|
150
|
+
const neg = await tapi.negotiate(capsuleId, wanted.slice(i, i + NEGOTIATE_BATCH));
|
|
151
|
+
await uploadAll(neg.missing, files);
|
|
152
|
+
uploaded += neg.missing.length;
|
|
153
|
+
for (const m of neg.missing)
|
|
154
|
+
uploadedBytes += m.size;
|
|
155
|
+
}
|
|
156
|
+
const committed = await tapi.commit(capsuleId, { manifest: manifest, manifestSha256: manifestSha, committedBy: "cli" });
|
|
157
|
+
return {
|
|
158
|
+
generation: committed.generation?.generation ?? generation,
|
|
159
|
+
logicalBytes: archives.reduce((n, a) => n + a.bytes, 0),
|
|
160
|
+
storedBytes: manifest.totals.bytes,
|
|
161
|
+
uploadedBytes,
|
|
162
|
+
uploaded,
|
|
163
|
+
reused: wanted.length - uploaded,
|
|
164
|
+
archives: archives.map((a) => ({ name: a.name, entries: a.entries, bytes: a.bytes, chunks: a.chunks.length })),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
await rm(tmp, { recursive: true, force: true });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Restores one archive of a generation into `dest` (which must not exist):
|
|
173
|
+
* downloads each chunk, checks its sha256, decompresses and untars.
|
|
174
|
+
*/
|
|
175
|
+
export async function restoreArchive(capsuleId, name, dest, generation) {
|
|
176
|
+
const res = await tapi.resolveGeneration(capsuleId, generation);
|
|
177
|
+
const manifest = res.manifest;
|
|
178
|
+
const archive = manifest.archives?.find((a) => a.name === name);
|
|
179
|
+
if (!archive)
|
|
180
|
+
throw new Error(`generation ${res.generation} has no archive named "${name}"`);
|
|
181
|
+
const urls = new Map(res.chunks.map((c) => [c.sha256, c.getUrl]));
|
|
182
|
+
// Claim the destination atomically: a non-recursive mkdir fails if it exists.
|
|
183
|
+
await mkdir(path.dirname(dest), { recursive: true });
|
|
184
|
+
try {
|
|
185
|
+
await mkdir(dest);
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
if (e.code === "EEXIST")
|
|
189
|
+
throw new Error(`${dest} already exists; restore never overwrites`);
|
|
190
|
+
throw e;
|
|
191
|
+
}
|
|
192
|
+
const tmp = await mkdtemp(path.join(os.tmpdir(), "teleport-archive-restore-"));
|
|
193
|
+
try {
|
|
194
|
+
const tarFile = path.join(tmp, "archive.tar");
|
|
195
|
+
const out = createWriteStream(tarFile);
|
|
196
|
+
const finished = new Promise((resolve, reject) => {
|
|
197
|
+
out.once("error", reject);
|
|
198
|
+
out.once("finish", resolve);
|
|
199
|
+
});
|
|
200
|
+
finished.catch(() => undefined);
|
|
201
|
+
let bytes = 0;
|
|
202
|
+
for (const c of archive.chunks) {
|
|
203
|
+
const url = urls.get(c.sha256);
|
|
204
|
+
if (!url)
|
|
205
|
+
throw new Error(`no download URL for chunk ${c.sha256.slice(0, 12)}`);
|
|
206
|
+
const body = Buffer.from(await (await fetchOk(url)).arrayBuffer());
|
|
207
|
+
if (createHash("sha256").update(body).digest("hex") !== c.sha256)
|
|
208
|
+
throw new Error(`chunk ${c.sha256.slice(0, 12)} failed its checksum`);
|
|
209
|
+
const plain = zstdDecompressSync(body);
|
|
210
|
+
bytes += plain.length;
|
|
211
|
+
if (!out.write(plain))
|
|
212
|
+
await Promise.race([new Promise((r) => out.once("drain", r)), finished]);
|
|
213
|
+
}
|
|
214
|
+
out.end();
|
|
215
|
+
await finished;
|
|
216
|
+
const x = await run("tar", ["-x", "-k", "-f", tarFile, "-C", dest]);
|
|
217
|
+
if (x.code !== 0)
|
|
218
|
+
throw new Error(`tar extract failed: ${x.stderr.trim()}`);
|
|
219
|
+
return { entries: archive.entries, bytes };
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
await rm(tmp, { recursive: true, force: true });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async function uploadAll(missing, files) {
|
|
226
|
+
let cursor = 0;
|
|
227
|
+
const workers = Array.from({ length: Math.min(PUT_CONCURRENCY, missing.length) }, async () => {
|
|
228
|
+
for (;;) {
|
|
229
|
+
const i = cursor++;
|
|
230
|
+
if (i >= missing.length)
|
|
231
|
+
return;
|
|
232
|
+
const file = files.get(missing[i].sha256);
|
|
233
|
+
if (!file)
|
|
234
|
+
throw new Error(`server asked for an unknown chunk ${missing[i].sha256}`);
|
|
235
|
+
const body = await readFile(file);
|
|
236
|
+
let delay = 400;
|
|
237
|
+
for (let attempt = 1;; attempt++) {
|
|
238
|
+
const r = await fetch(missing[i].putUrl, { method: "PUT", body });
|
|
239
|
+
if (r.ok)
|
|
240
|
+
break;
|
|
241
|
+
await r.body?.cancel().catch(() => undefined);
|
|
242
|
+
if (attempt >= 4 || (r.status < 500 && r.status !== 429))
|
|
243
|
+
throw new Error(`chunk upload failed: HTTP ${r.status}`);
|
|
244
|
+
await new Promise((s) => setTimeout(s, delay));
|
|
245
|
+
delay *= 2;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
await Promise.all(workers);
|
|
250
|
+
}
|
|
251
|
+
async function fetchOk(url) {
|
|
252
|
+
const r = await fetch(url);
|
|
253
|
+
if (!r.ok)
|
|
254
|
+
throw new Error(`chunk download failed: HTTP ${r.status}`);
|
|
255
|
+
return r;
|
|
256
|
+
}
|
|
257
|
+
function run(cmd, args) {
|
|
258
|
+
return new Promise((resolve, reject) => {
|
|
259
|
+
const p = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
260
|
+
let stdout = "";
|
|
261
|
+
let stderr = "";
|
|
262
|
+
p.stdout.on("data", (d) => (stdout += d));
|
|
263
|
+
p.stderr.on("data", (d) => (stderr += d));
|
|
264
|
+
p.on("error", reject);
|
|
265
|
+
p.on("close", (code) => resolve({ code: code ?? 1, stdout, stderr }));
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function safe(name) {
|
|
269
|
+
return name.replace(/[^A-Za-z0-9._-]/g, "_") || "archive";
|
|
270
|
+
}
|
|
271
|
+
/** Default sources: agent session history and infinite-disk's retained recovery data. */
|
|
272
|
+
export function defaultArchiveSources(home = os.homedir()) {
|
|
273
|
+
return [
|
|
274
|
+
{ name: "claude-code", dir: path.join(home, ".claude", "projects") },
|
|
275
|
+
{ name: "codex", dir: path.join(home, ".codex", "sessions") },
|
|
276
|
+
{ name: "infinite-disk-recovery", dir: path.join(home, ".local", "share", "infinite-disk", "recovery-consolidated") },
|
|
277
|
+
{ name: "infinite-disk-sessions", dir: path.join(home, ".local", "share", "infinite-disk", "session-backups") },
|
|
278
|
+
];
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/teleport/archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvF,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,IAAI,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAyCvF,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,CAAC;AAC7B,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,iBAAiB;AACtC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAClC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;AACjC,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,6EAA6E;AAC7E,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE;IACjB,MAAM,CAAC,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC,EAAE,CAAC;AAEL;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;QACpD,IAAI,GAAG,GAAG,GAAG,CAAC;QACd,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrB,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;gBACZ,MAAM;YACR,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAQD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAkB,EAAE,MAAc;IACnE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,IAAI,GAAG,KAAK,EAAE,KAAa,EAAE,EAAE;QACnC,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,CAAC,MAAM,GAAG,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,WAAW,QAAQ,CAAC,CAAC;QAC7F,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACpC,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACzB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC;QACH,IAAI,OAAO,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,gBAAgB,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;YAChF,MAAM,GAAG,GAAG,KAAe,CAAC;YAC5B,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC;YACpB,OAAO,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YACrE,mEAAmE;YACnE,2CAA2C;YAC3C,OAAO,OAAO,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;gBACnC,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7D,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAClD,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QACD,sEAAsE;QACtE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YACtD,KAAK,GAAG,GAAG,CAAC;QACd,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC;AAC/G,CAAC;AAED,iEAAiE;AACjE,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,OAAe;IACtD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,qBAAqB,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACrE,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AAC9E,CAAC;AAYD,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB,EAAE,QAAgB,EAAE,OAAwB,EAAE,gBAAwB;IACvH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAmB,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK;gBAAE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;QAC7C,KAAK,MAAM,CAAC,IAAI,GAAG;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,gBAAgB,GAAG,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAoB;YAChC,CAAC,EAAE,gBAAgB;YACnB,SAAS;YACT,UAAU;YACV,gBAAgB;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,WAAW,CAAC,cAAc,CAAuC;YAC1E,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzC,KAAK,EAAE,EAAE;YACT,QAAQ;YACR,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;YACrC,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE;SACjG,CAAC;QACF,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACrD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QACzC,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAClC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QACrC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;QAE/E,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACtC,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;YACxD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC;YAClF,MAAM,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACpC,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;YAC/B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO;gBAAE,aAAa,IAAI,CAAC,CAAC,IAAI,CAAC;QACvD,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QACjI,OAAO;YACL,UAAU,EAAE,SAAS,CAAC,UAAU,EAAE,UAAU,IAAI,UAAU;YAC1D,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACvD,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK;YAClC,aAAa;YACb,QAAQ;YACR,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ;YAChC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;SAC/G,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,SAAiB,EAAE,IAAY,EAAE,IAAY,EAAE,UAAmB;IACrG,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAsC,CAAC;IAC5D,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAChE,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,UAAU,0BAA0B,IAAI,GAAG,CAAC,CAAC;IAC7F,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAClE,8EAA8E;IAC9E,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,2CAA2C,CAAC,CAAC;QACxH,MAAM,CAAC,CAAC;IACV,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,2BAA2B,CAAC,CAAC,CAAC;IAC/E,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrD,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAChC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;YAChF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YACnE,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,sBAAsB,CAAC,CAAC;YACxI,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YACvC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;gBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QAClG,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,MAAM,QAAQ,CAAC;QACf,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5E,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,OAA0C,EAAE,KAA0B;IAC7F,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;QAC3F,SAAS,CAAC;YACR,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;YACnB,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM;gBAAE,OAAO;YAChC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACrF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,KAAK,GAAG,GAAG,CAAC;YAChB,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;gBAClC,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,CAAC,EAAE;oBAAE,MAAM;gBAChB,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC9C,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;gBACnH,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC/C,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,GAAW;IAChC,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,GAAG,CAAC,GAAW,EAAE,IAAc;IACtC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAClE,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACtB,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,IAAI,CAAC,IAAY;IACxB,OAAO,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;AAC5D,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,qBAAqB,CAAC,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE;IACvD,OAAO;QACL,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE;QACpE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE;QAC7D,EAAE,IAAI,EAAE,wBAAwB,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,uBAAuB,CAAC,EAAE;QACrH,EAAE,IAAI,EAAE,wBAAwB,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,iBAAiB,CAAC,EAAE;KAChH,CAAC;AACJ,CAAC"}
|
|
@@ -75,6 +75,15 @@ export declare function cmdStorageList(options: OutputOptions): Promise<void>;
|
|
|
75
75
|
export declare function cmdStorageTest(ref: string, options: OutputOptions): Promise<void>;
|
|
76
76
|
export declare function cmdStorageRemove(ref: string): Promise<void>;
|
|
77
77
|
export declare function cmdStorageMirror(ref: string, targetsArg: string): Promise<void>;
|
|
78
|
+
interface ArchiveOptions extends OutputOptions {
|
|
79
|
+
name?: string;
|
|
80
|
+
source?: string[];
|
|
81
|
+
}
|
|
82
|
+
export declare function cmdTeleportArchive(options: ArchiveOptions): Promise<void>;
|
|
83
|
+
export declare function cmdTeleportArchiveRestore(archiveName: string, dest: string, options: {
|
|
84
|
+
name?: string;
|
|
85
|
+
generation?: string;
|
|
86
|
+
}): Promise<void>;
|
|
78
87
|
export declare function registerTeleportCommands(program: Command, addExamples: (c: Command, ex: string) => Command): void;
|
|
79
88
|
/**
|
|
80
89
|
* Remote Control checkpoint: push the session's root as a new generation and
|
|
@@ -14,6 +14,8 @@ import { discoverRepos } from "../teleport/discover.js";
|
|
|
14
14
|
import { offloadBlockers, planCapture } from "../teleport/workspace.js";
|
|
15
15
|
import { formatCapturePlan } from "../dittoconfig/commands.js";
|
|
16
16
|
import { formatBytes } from "../teleport/types.js";
|
|
17
|
+
import { defaultArchiveSources, pushArchive, restoreArchive } from "../teleport/archive.js";
|
|
18
|
+
import { stat } from "node:fs/promises";
|
|
17
19
|
function out(line) {
|
|
18
20
|
process.stdout.write(`${line}\n`);
|
|
19
21
|
}
|
|
@@ -438,6 +440,63 @@ function jsonAlias() {
|
|
|
438
440
|
function withOutput(c) {
|
|
439
441
|
return c.addOption(outputOption()).addOption(jsonAlias());
|
|
440
442
|
}
|
|
443
|
+
/** Parses repeatable --source name=dir; defaults to agent history and infinite-disk recovery data. */
|
|
444
|
+
async function archiveSources(options) {
|
|
445
|
+
const names = new Set();
|
|
446
|
+
const sources = options.source?.length
|
|
447
|
+
? options.source.map((s) => {
|
|
448
|
+
const at = s.indexOf("=");
|
|
449
|
+
const dir = s.slice(at + 1);
|
|
450
|
+
if (at <= 0 || !dir)
|
|
451
|
+
throw new Error(`--source must be name=dir, got "${s}"`);
|
|
452
|
+
const name = s.slice(0, at);
|
|
453
|
+
if (names.has(name))
|
|
454
|
+
throw new Error(`duplicate --source name "${name}"`);
|
|
455
|
+
names.add(name);
|
|
456
|
+
return { name, dir: path.resolve(dir) };
|
|
457
|
+
})
|
|
458
|
+
: defaultArchiveSources();
|
|
459
|
+
const present = [];
|
|
460
|
+
for (const src of sources) {
|
|
461
|
+
const info = await stat(src.dir).catch(() => undefined);
|
|
462
|
+
if (info?.isDirectory())
|
|
463
|
+
present.push(src);
|
|
464
|
+
else if (options.source?.length)
|
|
465
|
+
throw new Error(`${src.dir} is not a directory`);
|
|
466
|
+
}
|
|
467
|
+
if (present.length === 0)
|
|
468
|
+
throw new Error("nothing to archive: no source directory exists");
|
|
469
|
+
return present;
|
|
470
|
+
}
|
|
471
|
+
export async function cmdTeleportArchive(options) {
|
|
472
|
+
const name = options.name ?? "agent-traces";
|
|
473
|
+
const sources = await archiveSources(options);
|
|
474
|
+
let capsule = (await tapi.listCapsules()).find((c) => c.name === name && c.status !== "deleted");
|
|
475
|
+
if (capsule && capsule.rootKind !== "archive") {
|
|
476
|
+
throw new Error(`capsule "${name}" is a ${capsule.rootKind} capsule; choose another --name for the archive`);
|
|
477
|
+
}
|
|
478
|
+
if (!capsule)
|
|
479
|
+
capsule = await tapi.createCapsule({ name, rootKind: "archive" });
|
|
480
|
+
if (!json(options)) {
|
|
481
|
+
err(`Archiving ${sources.map((s) => s.name).join(", ")} into "${name}" (generation ${capsule.headGeneration + 1})…`);
|
|
482
|
+
}
|
|
483
|
+
const res = await pushArchive(capsule.id, name, sources, capsule.headGeneration);
|
|
484
|
+
if (json(options)) {
|
|
485
|
+
out(JSON.stringify({ capsule: capsule.id, ...res }));
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
for (const a of res.archives)
|
|
489
|
+
out(` ${pad(a.name, 24)} ${pad(String(a.entries), 7)} files ${formatBytes(a.bytes)}`);
|
|
490
|
+
out(`Generation ${res.generation}: ${formatBytes(res.logicalBytes)} archived, ${formatBytes(res.storedBytes)} stored compressed, ${formatBytes(res.uploadedBytes)} uploaded (${res.reused} chunks already stored).`);
|
|
491
|
+
out("Billed as storage on your plan; restore with `heyditto teleport archive-restore`.");
|
|
492
|
+
}
|
|
493
|
+
export async function cmdTeleportArchiveRestore(archiveName, dest, options) {
|
|
494
|
+
const generation = options.generation === undefined ? undefined : Number(options.generation);
|
|
495
|
+
if (generation !== undefined && (!Number.isInteger(generation) || generation < 1))
|
|
496
|
+
throw new Error("--generation must be a positive integer");
|
|
497
|
+
const res = await restoreArchive(options.name ?? "agent-traces", archiveName, path.resolve(dest), generation);
|
|
498
|
+
out(`Restored ${res.entries} files (${formatBytes(res.bytes)}) into ${path.resolve(dest)}.`);
|
|
499
|
+
}
|
|
441
500
|
export function registerTeleportCommands(program, addExamples) {
|
|
442
501
|
const teleport = withOutput(program
|
|
443
502
|
.command("teleport")
|
|
@@ -491,6 +550,18 @@ export function registerTeleportCommands(program, addExamples) {
|
|
|
491
550
|
for (const line of formatCapturePlan(plan))
|
|
492
551
|
out(line);
|
|
493
552
|
}));
|
|
553
|
+
withOutput(teleport
|
|
554
|
+
.command("archive")
|
|
555
|
+
.description("back up agent session history and recovery data as storage (no capsule slot)")
|
|
556
|
+
.option("--name <capsule>", "archive capsule name", "agent-traces")
|
|
557
|
+
.option("--source <name=dir...>", "archive these directories instead of the defaults (~/.claude/projects, ~/.codex/sessions, infinite-disk recovery data)")
|
|
558
|
+
.action(cmdTeleportArchive));
|
|
559
|
+
teleport
|
|
560
|
+
.command("archive-restore <archive> <dest>")
|
|
561
|
+
.description("restore one archive (e.g. claude-code) into a new directory; never overwrites")
|
|
562
|
+
.option("--name <capsule>", "archive capsule name", "agent-traces")
|
|
563
|
+
.option("--generation <n>", "generation to restore (default: latest)")
|
|
564
|
+
.action(cmdTeleportArchiveRestore);
|
|
494
565
|
withOutput(teleport.command("rm <capsule>").description("delete a capsule and its generations").option("--yes", "skip the confirmation").action(cmdTeleportRm));
|
|
495
566
|
addExamples(teleport, ` heyditto teleport push the current directory
|
|
496
567
|
heyditto teleport --cloud --endpoint work push, then resume in Ditto Code
|