@autopilot-harness/cli 0.1.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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/assets/autopilot-harness-hook.mjs +193 -0
  4. package/assets/vendor/migrations/001_initial.sql +62 -0
  5. package/assets/vendor/migrations/002_pending_followup.sql +4 -0
  6. package/assets/vendor/migrations/003_reviewing_item.sql +1 -0
  7. package/assets/vendor/runtime.mjs +5524 -0
  8. package/dist/assets/autopilot-harness-hook.mjs +193 -0
  9. package/dist/assets/vendor/migrations/001_initial.sql +62 -0
  10. package/dist/assets/vendor/migrations/002_pending_followup.sql +4 -0
  11. package/dist/assets/vendor/migrations/003_reviewing_item.sql +1 -0
  12. package/dist/assets/vendor/runtime.mjs +5524 -0
  13. package/dist/bin.d.ts +3 -0
  14. package/dist/bin.d.ts.map +1 -0
  15. package/dist/bin.js +300 -0
  16. package/dist/bin.js.map +1 -0
  17. package/dist/index.d.ts +23 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +13 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/init/config-merge.d.ts +27 -0
  22. package/dist/init/config-merge.d.ts.map +1 -0
  23. package/dist/init/config-merge.js +115 -0
  24. package/dist/init/config-merge.js.map +1 -0
  25. package/dist/init/default-config.d.ts +17 -0
  26. package/dist/init/default-config.d.ts.map +1 -0
  27. package/dist/init/default-config.js +101 -0
  28. package/dist/init/default-config.js.map +1 -0
  29. package/dist/init/hooks-merge.d.ts +25 -0
  30. package/dist/init/hooks-merge.d.ts.map +1 -0
  31. package/dist/init/hooks-merge.js +134 -0
  32. package/dist/init/hooks-merge.js.map +1 -0
  33. package/dist/init/install.d.ts +31 -0
  34. package/dist/init/install.d.ts.map +1 -0
  35. package/dist/init/install.js +829 -0
  36. package/dist/init/install.js.map +1 -0
  37. package/dist/init/platforms.d.ts +60 -0
  38. package/dist/init/platforms.d.ts.map +1 -0
  39. package/dist/init/platforms.js +275 -0
  40. package/dist/init/platforms.js.map +1 -0
  41. package/dist/init/tui.d.ts +65 -0
  42. package/dist/init/tui.d.ts.map +1 -0
  43. package/dist/init/tui.js +549 -0
  44. package/dist/init/tui.js.map +1 -0
  45. package/dist/init/types.d.ts +75 -0
  46. package/dist/init/types.d.ts.map +1 -0
  47. package/dist/init/types.js +9 -0
  48. package/dist/init/types.js.map +1 -0
  49. package/dist/init/wizard-copy.d.ts +74 -0
  50. package/dist/init/wizard-copy.d.ts.map +1 -0
  51. package/dist/init/wizard-copy.js +173 -0
  52. package/dist/init/wizard-copy.js.map +1 -0
  53. package/dist/init/wizard-helpers.d.ts +103 -0
  54. package/dist/init/wizard-helpers.d.ts.map +1 -0
  55. package/dist/init/wizard-helpers.js +724 -0
  56. package/dist/init/wizard-helpers.js.map +1 -0
  57. package/dist/locale-set.d.ts +24 -0
  58. package/dist/locale-set.d.ts.map +1 -0
  59. package/dist/locale-set.js +286 -0
  60. package/dist/locale-set.js.map +1 -0
  61. package/dist/names.d.ts +5 -0
  62. package/dist/names.d.ts.map +1 -0
  63. package/dist/names.js +5 -0
  64. package/dist/names.js.map +1 -0
  65. package/dist/project-fs.d.ts +48 -0
  66. package/dist/project-fs.d.ts.map +1 -0
  67. package/dist/project-fs.js +210 -0
  68. package/dist/project-fs.js.map +1 -0
  69. package/dist/read-untrusted-file.d.ts +41 -0
  70. package/dist/read-untrusted-file.d.ts.map +1 -0
  71. package/dist/read-untrusted-file.js +362 -0
  72. package/dist/read-untrusted-file.js.map +1 -0
  73. package/dist/session.d.ts +38 -0
  74. package/dist/session.d.ts.map +1 -0
  75. package/dist/session.js +242 -0
  76. package/dist/session.js.map +1 -0
  77. package/dist/status-doctor.d.ts +22 -0
  78. package/dist/status-doctor.d.ts.map +1 -0
  79. package/dist/status-doctor.js +712 -0
  80. package/dist/status-doctor.js.map +1 -0
  81. package/dist/uninstall.d.ts +31 -0
  82. package/dist/uninstall.d.ts.map +1 -0
  83. package/dist/uninstall.js +333 -0
  84. package/dist/uninstall.js.map +1 -0
  85. package/dist/upgrade.d.ts +29 -0
  86. package/dist/upgrade.d.ts.map +1 -0
  87. package/dist/upgrade.js +290 -0
  88. package/dist/upgrade.js.map +1 -0
  89. package/dist/vendor-entry.d.ts +6 -0
  90. package/dist/vendor-entry.d.ts.map +1 -0
  91. package/dist/vendor-entry.js +16 -0
  92. package/dist/vendor-entry.js.map +1 -0
  93. package/package.json +54 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-fs.js","sourceRoot":"","sources":["../src/project-fs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /** Default size cap for untrusted project text files (config.yml, hooks.json, …). */
2
+ export declare const MAX_UNTRUSTED_TEXT_BYTES = 1000000;
3
+ /**
4
+ * O_NOFOLLOW when the platform provides it; 0 on Windows (callers must
5
+ * assertNotSymlink + post-open identity checks). Override for tests.
6
+ */
7
+ export declare function resolveNofollowFlag(override?: number): number;
8
+ /** Refuse writing through a symlink (incl. dangling — existsSync lies). */
9
+ export declare function assertNotSymlink(filePath: string, label: string): void;
10
+ /**
11
+ * Move tmp → dest. Handles EXDEV (stage+rename) and Windows EPERM/EEXIST
12
+ * (park dest via lstat, incl. dangling symlink). Never writes through a
13
+ * symlink at dest.
14
+ */
15
+ export declare function renameReplaceSync(tmp: string, dest: string): void;
16
+ /**
17
+ * Write text via exclusive tmp (wx) + renameReplaceSync.
18
+ * wx refuses a pre-planted symlink at the staging path (no write-through).
19
+ */
20
+ export declare function writeFileReplaceSync(dest: string, contents: string): void;
21
+ /**
22
+ * Copy via exclusive tmp (nofollow) + renameReplaceSync.
23
+ * Source is opened O_NOFOLLOW (no read-through); staging path uses O_EXCL.
24
+ */
25
+ export declare function copyFileReplaceSync(src: string, dest: string): void;
26
+ /**
27
+ * Copy src → dest with O_CREAT|O_EXCL on dest, without following a symlink at src.
28
+ * Node's copyFileSync follows source symlinks; this is for hostile-workspace
29
+ * backups (e.g. state.db → state.db.bak) where TOCTOU swap must fail closed.
30
+ */
31
+ export declare function copyFileNoFollowExclSync(src: string, dest: string, label: string, opts?: {
32
+ nofollow?: number;
33
+ }): void;
34
+ /**
35
+ * Read untrusted text: no symlink follow, size-capped (fstat + readSync).
36
+ * Throws on symlink / non-regular file / oversize.
37
+ */
38
+ export declare function readUntrustedUtf8File(filePath: string, maxBytes: number, label: string, opts?: {
39
+ nofollow?: number;
40
+ }): string;
41
+ //# sourceMappingURL=read-untrusted-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-untrusted-file.d.ts","sourceRoot":"","sources":["../src/read-untrusted-file.ts"],"names":[],"mappings":"AAGA,qFAAqF;AACrF,eAAO,MAAM,wBAAwB,UAAY,CAAC;AAElD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAY7D;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAUtE;AAmGD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBjE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAazE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAanE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3B,IAAI,CA0FN;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3B,MAAM,CA4DR"}
@@ -0,0 +1,362 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import fs from "node:fs";
3
+ /** Default size cap for untrusted project text files (config.yml, hooks.json, …). */
4
+ export const MAX_UNTRUSTED_TEXT_BYTES = 1_000_000;
5
+ /**
6
+ * O_NOFOLLOW when the platform provides it; 0 on Windows (callers must
7
+ * assertNotSymlink + post-open identity checks). Override for tests.
8
+ */
9
+ export function resolveNofollowFlag(override) {
10
+ const platform = typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0;
11
+ if (override !== undefined) {
12
+ // Test-only: allow simulating Windows (0) or forcing the platform flag.
13
+ // Reject arbitrary bitmasks — `O_RDONLY | weird` can change open mode.
14
+ if (!Number.isInteger(override) || (override !== 0 && override !== platform)) {
15
+ throw new Error("invalid nofollow override");
16
+ }
17
+ return override;
18
+ }
19
+ return platform;
20
+ }
21
+ /** Refuse writing through a symlink (incl. dangling — existsSync lies). */
22
+ export function assertNotSymlink(filePath, label) {
23
+ try {
24
+ if (fs.lstatSync(filePath).isSymbolicLink()) {
25
+ throw new Error(`${label} is a symlink; refusing to open`);
26
+ }
27
+ }
28
+ catch (err) {
29
+ const code = err?.code;
30
+ if (code === "ENOENT")
31
+ return;
32
+ throw err;
33
+ }
34
+ }
35
+ /** Unpredictable sibling path for exclusive staging (same directory as dest). */
36
+ function exclusiveSiblingPath(dest, kind) {
37
+ return `${dest}.${process.pid}.${randomBytes(8).toString("hex")}.${kind}`;
38
+ }
39
+ function pathPresentViaLstat(p) {
40
+ try {
41
+ fs.lstatSync(p);
42
+ return true;
43
+ }
44
+ catch {
45
+ return false;
46
+ }
47
+ }
48
+ /**
49
+ * Park dest (incl. dangling symlink via lstat), then rename tmp → dest.
50
+ * Never copyFileSync onto dest (that follows a raced symlink = write-through).
51
+ */
52
+ function parkAndRename(tmp, dest, first) {
53
+ if (!pathPresentViaLstat(dest) || !pathPresentViaLstat(tmp)) {
54
+ throw first instanceof Error ? first : new Error(String(first));
55
+ }
56
+ const bak = exclusiveSiblingPath(dest, "bak");
57
+ fs.renameSync(dest, bak);
58
+ try {
59
+ fs.renameSync(tmp, dest);
60
+ }
61
+ catch (err) {
62
+ try {
63
+ fs.unlinkSync(dest);
64
+ }
65
+ catch {
66
+ /* may not exist */
67
+ }
68
+ try {
69
+ fs.renameSync(bak, dest);
70
+ }
71
+ catch {
72
+ /* leave bak for manual recovery */
73
+ }
74
+ throw err;
75
+ }
76
+ try {
77
+ fs.unlinkSync(bak);
78
+ }
79
+ catch {
80
+ /* best-effort */
81
+ }
82
+ }
83
+ /**
84
+ * Cross-device: copy onto a unique same-dir stage (nofollow + O_EXCL), then rename.
85
+ * Never copyFileSync(tmp, dest) or copyFileSync(tmp, stage) — both follow a
86
+ * raced symlink at tmp (read-through into the committed bytes).
87
+ */
88
+ function commitViaSameFsStage(tmp, dest) {
89
+ const stage = exclusiveSiblingPath(dest, "exdev-stage");
90
+ try {
91
+ // O_NOFOLLOW on tmp: a symlink swap between create and EXDEV fallback
92
+ // must not copy the link target's bytes into stage.
93
+ copyFileNoFollowExclSync(tmp, stage, "exdev-stage-src");
94
+ }
95
+ catch (err) {
96
+ try {
97
+ fs.unlinkSync(stage);
98
+ }
99
+ catch {
100
+ /* ignore */
101
+ }
102
+ throw err;
103
+ }
104
+ try {
105
+ fs.unlinkSync(tmp);
106
+ }
107
+ catch {
108
+ /* stage holds the bytes */
109
+ }
110
+ try {
111
+ fs.renameSync(stage, dest);
112
+ return;
113
+ }
114
+ catch (first) {
115
+ const code = first?.code;
116
+ if (code === "EPERM" || code === "EEXIST") {
117
+ try {
118
+ parkAndRename(stage, dest, first);
119
+ return;
120
+ }
121
+ catch (err) {
122
+ try {
123
+ fs.unlinkSync(stage);
124
+ }
125
+ catch {
126
+ /* ignore */
127
+ }
128
+ throw err;
129
+ }
130
+ }
131
+ try {
132
+ fs.unlinkSync(stage);
133
+ }
134
+ catch {
135
+ /* ignore */
136
+ }
137
+ throw first;
138
+ }
139
+ }
140
+ /**
141
+ * Move tmp → dest. Handles EXDEV (stage+rename) and Windows EPERM/EEXIST
142
+ * (park dest via lstat, incl. dangling symlink). Never writes through a
143
+ * symlink at dest.
144
+ */
145
+ export function renameReplaceSync(tmp, dest) {
146
+ try {
147
+ fs.renameSync(tmp, dest);
148
+ return;
149
+ }
150
+ catch (first) {
151
+ const code = first?.code;
152
+ if (code === "EXDEV") {
153
+ commitViaSameFsStage(tmp, dest);
154
+ return;
155
+ }
156
+ if (code === "EPERM" || code === "EEXIST") {
157
+ parkAndRename(tmp, dest, first);
158
+ return;
159
+ }
160
+ throw first;
161
+ }
162
+ }
163
+ /**
164
+ * Write text via exclusive tmp (wx) + renameReplaceSync.
165
+ * wx refuses a pre-planted symlink at the staging path (no write-through).
166
+ */
167
+ export function writeFileReplaceSync(dest, contents) {
168
+ const tmp = exclusiveSiblingPath(dest, "tmp");
169
+ try {
170
+ fs.writeFileSync(tmp, contents, { encoding: "utf8", flag: "wx" });
171
+ renameReplaceSync(tmp, dest);
172
+ }
173
+ catch (err) {
174
+ try {
175
+ fs.unlinkSync(tmp);
176
+ }
177
+ catch {
178
+ /* ignore cleanup */
179
+ }
180
+ throw err;
181
+ }
182
+ }
183
+ /**
184
+ * Copy via exclusive tmp (nofollow) + renameReplaceSync.
185
+ * Source is opened O_NOFOLLOW (no read-through); staging path uses O_EXCL.
186
+ */
187
+ export function copyFileReplaceSync(src, dest) {
188
+ const tmp = exclusiveSiblingPath(dest, "tmp");
189
+ try {
190
+ copyFileNoFollowExclSync(src, tmp, "copy-src");
191
+ renameReplaceSync(tmp, dest);
192
+ }
193
+ catch (err) {
194
+ try {
195
+ fs.unlinkSync(tmp);
196
+ }
197
+ catch {
198
+ /* ignore cleanup */
199
+ }
200
+ throw err;
201
+ }
202
+ }
203
+ /**
204
+ * Copy src → dest with O_CREAT|O_EXCL on dest, without following a symlink at src.
205
+ * Node's copyFileSync follows source symlinks; this is for hostile-workspace
206
+ * backups (e.g. state.db → state.db.bak) where TOCTOU swap must fail closed.
207
+ */
208
+ export function copyFileNoFollowExclSync(src, dest, label, opts) {
209
+ const nofollow = resolveNofollowFlag(opts?.nofollow);
210
+ if (nofollow === 0) {
211
+ assertNotSymlink(src, label);
212
+ }
213
+ let srcFd;
214
+ try {
215
+ srcFd = fs.openSync(src, fs.constants.O_RDONLY | nofollow);
216
+ }
217
+ catch (err) {
218
+ if (nofollow !== 0 && err?.code === "ELOOP") {
219
+ throw new Error(`${label} is a symlink; refusing to open`);
220
+ }
221
+ throw err;
222
+ }
223
+ let outFd;
224
+ try {
225
+ const st = fs.fstatSync(srcFd);
226
+ if (!st.isFile()) {
227
+ throw new Error(`${label} is not a regular file`);
228
+ }
229
+ let lst;
230
+ try {
231
+ lst = fs.lstatSync(src);
232
+ }
233
+ catch {
234
+ throw new Error(`${label} disappeared during read`);
235
+ }
236
+ if (lst.isSymbolicLink()) {
237
+ throw new Error(`${label} is a symlink; refusing to open`);
238
+ }
239
+ if (typeof lst.ino === "number" &&
240
+ typeof st.ino === "number" &&
241
+ (lst.ino !== 0 || st.ino !== 0) &&
242
+ (lst.ino !== st.ino || lst.dev !== st.dev)) {
243
+ throw new Error(`${label} changed during read`);
244
+ }
245
+ outFd = fs.openSync(dest, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL);
246
+ const buf = Buffer.alloc(64 * 1024);
247
+ let copied = 0;
248
+ while (copied < st.size) {
249
+ const toRead = Math.min(buf.length, st.size - copied);
250
+ const n = fs.readSync(srcFd, buf, 0, toRead, copied);
251
+ if (n === 0) {
252
+ throw new Error(`${label} read incomplete (${copied}/${st.size} bytes)`);
253
+ }
254
+ fs.writeSync(outFd, buf, 0, n);
255
+ copied += n;
256
+ }
257
+ const stAfter = fs.fstatSync(srcFd);
258
+ if (stAfter.size !== st.size) {
259
+ throw new Error(`${label} changed during read`);
260
+ }
261
+ }
262
+ catch (err) {
263
+ if (outFd !== undefined) {
264
+ try {
265
+ fs.closeSync(outFd);
266
+ }
267
+ catch {
268
+ /* ignore */
269
+ }
270
+ outFd = undefined;
271
+ try {
272
+ fs.unlinkSync(dest);
273
+ }
274
+ catch {
275
+ /* ignore */
276
+ }
277
+ }
278
+ throw err;
279
+ }
280
+ finally {
281
+ if (outFd !== undefined) {
282
+ try {
283
+ fs.closeSync(outFd);
284
+ }
285
+ catch {
286
+ /* ignore */
287
+ }
288
+ }
289
+ try {
290
+ fs.closeSync(srcFd);
291
+ }
292
+ catch {
293
+ /* ignore */
294
+ }
295
+ }
296
+ }
297
+ /**
298
+ * Read untrusted text: no symlink follow, size-capped (fstat + readSync).
299
+ * Throws on symlink / non-regular file / oversize.
300
+ */
301
+ export function readUntrustedUtf8File(filePath, maxBytes, label, opts) {
302
+ if (!Number.isInteger(maxBytes) || maxBytes <= 0) {
303
+ throw new Error(`${label}: invalid maxBytes`);
304
+ }
305
+ const nofollow = resolveNofollowFlag(opts?.nofollow);
306
+ if (nofollow === 0) {
307
+ assertNotSymlink(filePath, label);
308
+ }
309
+ let fd;
310
+ try {
311
+ fd = fs.openSync(filePath, fs.constants.O_RDONLY | nofollow);
312
+ }
313
+ catch (err) {
314
+ if (nofollow !== 0 && err?.code === "ELOOP") {
315
+ throw new Error(`${label} is a symlink; refusing to open`);
316
+ }
317
+ throw err;
318
+ }
319
+ try {
320
+ const st = fs.fstatSync(fd);
321
+ if (!st.isFile()) {
322
+ throw new Error(`${label} is not a regular file`);
323
+ }
324
+ // Re-check path identity after open: without O_NOFOLLOW (e.g. Windows),
325
+ // a symlink swap between assertNotSymlink and open would follow the link.
326
+ // lstat symlink → refuse; ino/dev mismatch → path no longer the opened file.
327
+ let lst;
328
+ try {
329
+ lst = fs.lstatSync(filePath);
330
+ }
331
+ catch {
332
+ throw new Error(`${label} disappeared during read`);
333
+ }
334
+ if (lst.isSymbolicLink()) {
335
+ throw new Error(`${label} is a symlink; refusing to open`);
336
+ }
337
+ if (typeof lst.ino === "number" &&
338
+ typeof st.ino === "number" &&
339
+ (lst.ino !== 0 || st.ino !== 0) &&
340
+ (lst.ino !== st.ino || lst.dev !== st.dev)) {
341
+ throw new Error(`${label} changed during read`);
342
+ }
343
+ if (st.size > maxBytes) {
344
+ throw new Error(`${label} is too large (>${maxBytes} bytes)`);
345
+ }
346
+ const buf = Buffer.alloc(st.size);
347
+ const n = fs.readSync(fd, buf, 0, st.size, 0);
348
+ if (n !== st.size) {
349
+ throw new Error(`${label} read incomplete (${n}/${st.size} bytes)`);
350
+ }
351
+ // Concurrent truncate/grow after fstat → refuse (fail closed).
352
+ const stAfter = fs.fstatSync(fd);
353
+ if (stAfter.size !== st.size) {
354
+ throw new Error(`${label} changed during read`);
355
+ }
356
+ return buf.toString("utf8");
357
+ }
358
+ finally {
359
+ fs.closeSync(fd);
360
+ }
361
+ }
362
+ //# sourceMappingURL=read-untrusted-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-untrusted-file.js","sourceRoot":"","sources":["../src/read-untrusted-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { shortConversationId } from "@autopilot-harness/core";
2
+ export { shortConversationId as shortSessionId };
3
+ export type SessionCmdOk = {
4
+ ok: true;
5
+ };
6
+ export type SessionCmdFail = {
7
+ ok: false;
8
+ error: string;
9
+ };
10
+ export type SessionCmdResult = SessionCmdOk | SessionCmdFail;
11
+ export type SessionListOk = {
12
+ ok: true;
13
+ lines: string[];
14
+ };
15
+ export type SessionListResult = SessionListOk | SessionCmdFail;
16
+ export declare function formatSessionDisplayName(row: {
17
+ track_title: string | null;
18
+ session_title: string | null;
19
+ track_id: string;
20
+ }): string;
21
+ export declare function formatSessionList(opts: {
22
+ projectRoot: string;
23
+ staleAfterHours?: number;
24
+ }): SessionListResult;
25
+ export declare function renameProjectSession(opts: {
26
+ projectRoot: string;
27
+ id: string;
28
+ title: string;
29
+ }): SessionCmdResult;
30
+ export declare function purgeProjectSession(opts: {
31
+ projectRoot: string;
32
+ id: string;
33
+ }): SessionCmdResult;
34
+ export declare function resetProjectSessionReview(opts: {
35
+ projectRoot: string;
36
+ id: string;
37
+ }): SessionCmdResult;
38
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,mBAAmB,EAGpB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,mBAAmB,IAAI,cAAc,EAAE,CAAC;AAEjD,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CAAC;AACxC,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,cAAc,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAC1D,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,cAAc,CAAC;AA2F/D,wBAAgB,wBAAwB,CAAC,GAAG,EAAE;IAC5C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAWT;AAkCD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,iBAAiB,CA2CpB;AAyBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,gBAAgB,CAqBnB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,gBAAgB,CAOnB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,gBAAgB,CAOnB"}