@duke-dsh-plugins/dsh-archive-manager 1.3.5 → 1.4.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 +19 -1
- package/client.js +928 -530
- package/index.js +276 -276
- package/package.json +4 -3
- package/typert.host.js +278 -224
package/typert.host.js
CHANGED
|
@@ -1,224 +1,278 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dsh-archive-manager — Typert Host manifest.
|
|
3
|
-
*
|
|
4
|
-
* Hand-written TYPERT manifest (the format the DSH typert-loader consumes from
|
|
5
|
-
* the package's `./typert` export). It describes the `archiveManager` Remote
|
|
6
|
-
* service the Host half publishes so the browser Client half can call it
|
|
7
|
-
* through `ctx.remote.archiveManager.{restore,delete,state}`.
|
|
8
|
-
*
|
|
9
|
-
* Keep the invocation ids, service/namespace names and method names in sync
|
|
10
|
-
* with `index.js` (ArchiveManagerService) and `client.js`.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}).readonly(),
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}).readonly(),
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
{
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
1
|
+
/**
|
|
2
|
+
* dsh-archive-manager — Typert Host manifest.
|
|
3
|
+
*
|
|
4
|
+
* Hand-written TYPERT manifest (the format the DSH typert-loader consumes from
|
|
5
|
+
* the package's `./typert` export). It describes the `archiveManager` Remote
|
|
6
|
+
* service the Host half publishes so the browser Client half can call it
|
|
7
|
+
* through `ctx.remote.archiveManager.{restore,delete,state}`.
|
|
8
|
+
*
|
|
9
|
+
* Keep the invocation ids, service/namespace names and method names in sync
|
|
10
|
+
* with `index.js` (ArchiveManagerService) and `client.js`.
|
|
11
|
+
*
|
|
12
|
+
* Cross-version note: strict codecs carry BOTH `schema` (DSH < 0.1.7 reads
|
|
13
|
+
* the zod instance) and `create` (DSH >= 0.1.7 requires the factory) — see
|
|
14
|
+
* the codec contract comment below before touching any codec.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
|
|
19
|
+
// ---- shared shapes ---------------------------------------------------------
|
|
20
|
+
//
|
|
21
|
+
// DSH-versioned codec contract (the ONE field that differs across DSH builds):
|
|
22
|
+
// - DSH < 0.1.7 (typert-loader / typert-registry): a strict codec must carry
|
|
23
|
+
// `codec.schema` — a zod v4 INSTANCE (`_zod` + `parse`) — and the runtime
|
|
24
|
+
// calls `codec.schema.parse(...)`.
|
|
25
|
+
// - DSH >= 0.1.7: a strict codec must carry `codec.create` — a FACTORY
|
|
26
|
+
// function returning a zod schema — and the runtime calls
|
|
27
|
+
// `codec.create().parse(...)`; a plain instance in `schema` fails
|
|
28
|
+
// validation with "strict codec has no create() factory".
|
|
29
|
+
// Every codec below therefore carries BOTH: `schema` (materialized instance,
|
|
30
|
+
// read by <0.1.7) and `create` (memoized factory, read by >=0.1.7). Each
|
|
31
|
+
// version's validator only inspects its own field, so the extra field is
|
|
32
|
+
// ignored everywhere. Same for TYPERT.schemas entries (0.1.7 requires
|
|
33
|
+
// `create`; our list stays empty, which satisfies both).
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Memoize one zod schema behind a `create()`-style factory: repeated calls
|
|
37
|
+
* return the same instance (the official 0.1.7 manifests use this exact
|
|
38
|
+
* `value ??= build()` pattern).
|
|
39
|
+
*
|
|
40
|
+
* @param {() => object} build - constructs the zod schema once.
|
|
41
|
+
* @returns {() => object} the factory.
|
|
42
|
+
*/
|
|
43
|
+
function lazy(build) {
|
|
44
|
+
let value;
|
|
45
|
+
return () => (value ??= build());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const sessionIdSchema = lazy(() => z.intersection(z.string(), z.unknown()).readonly());
|
|
49
|
+
|
|
50
|
+
const restoreResultSchema = lazy(() =>
|
|
51
|
+
z.union([
|
|
52
|
+
z.object({
|
|
53
|
+
ok: z.literal(true).readonly(),
|
|
54
|
+
value: z.object({
|
|
55
|
+
restored: z.literal(true).readonly(),
|
|
56
|
+
}).readonly(),
|
|
57
|
+
}).readonly(),
|
|
58
|
+
z.object({
|
|
59
|
+
ok: z.literal(false).readonly(),
|
|
60
|
+
error: z.object({
|
|
61
|
+
code: z.string().readonly(),
|
|
62
|
+
message: z.string().readonly().optional(),
|
|
63
|
+
}).readonly(),
|
|
64
|
+
}).readonly(),
|
|
65
|
+
])
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const deleteResultSchema = lazy(() =>
|
|
69
|
+
z.union([
|
|
70
|
+
z.object({
|
|
71
|
+
ok: z.literal(true).readonly(),
|
|
72
|
+
value: z.object({
|
|
73
|
+
fileRemoved: z.boolean().readonly(),
|
|
74
|
+
live: z.boolean().readonly(),
|
|
75
|
+
}).readonly(),
|
|
76
|
+
}).readonly(),
|
|
77
|
+
z.object({
|
|
78
|
+
ok: z.literal(false).readonly(),
|
|
79
|
+
error: z.object({
|
|
80
|
+
code: z.string().readonly(),
|
|
81
|
+
message: z.string().readonly().optional(),
|
|
82
|
+
}).readonly(),
|
|
83
|
+
}).readonly(),
|
|
84
|
+
])
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const stateResultSchema = lazy(() =>
|
|
88
|
+
z.union([
|
|
89
|
+
z.object({
|
|
90
|
+
ok: z.literal(true).readonly(),
|
|
91
|
+
value: z.object({
|
|
92
|
+
ghostIds: z.array(sessionIdSchema()).readonly(),
|
|
93
|
+
}).readonly(),
|
|
94
|
+
}).readonly(),
|
|
95
|
+
z.object({
|
|
96
|
+
ok: z.literal(false).readonly(),
|
|
97
|
+
error: z.object({
|
|
98
|
+
code: z.string().readonly(),
|
|
99
|
+
message: z.string().readonly().optional(),
|
|
100
|
+
}).readonly(),
|
|
101
|
+
}).readonly(),
|
|
102
|
+
])
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// ---- per-invocation parameter/result schemas -------------------------------
|
|
106
|
+
|
|
107
|
+
const restoreRequestSchema = lazy(() =>
|
|
108
|
+
z.object({
|
|
109
|
+
sessionId: sessionIdSchema(),
|
|
110
|
+
})
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const deleteRequestSchema = lazy(() =>
|
|
114
|
+
z.object({
|
|
115
|
+
sessionId: sessionIdSchema(),
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Build the dual-version strict codec: `schema` for DSH < 0.1.7 (instance
|
|
121
|
+
* read at validation time), `create` for DSH >= 0.1.7 (factory invoked by
|
|
122
|
+
* the runtime). Both point at the same memoized instance.
|
|
123
|
+
*
|
|
124
|
+
* @param {string} typeSymbol - wire type symbol.
|
|
125
|
+
* @param {() => object} factory - the memoized schema factory.
|
|
126
|
+
* @returns {object} the codec descriptor.
|
|
127
|
+
*/
|
|
128
|
+
function strictCodec(typeSymbol, factory) {
|
|
129
|
+
return {
|
|
130
|
+
mode: "strict",
|
|
131
|
+
typeSymbol,
|
|
132
|
+
schema: factory(),
|
|
133
|
+
create: factory,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export const TYPERT = {
|
|
138
|
+
package: "@duke-dsh-plugins/dsh-archive-manager",
|
|
139
|
+
face: "host",
|
|
140
|
+
schemas: [],
|
|
141
|
+
invocations: [
|
|
142
|
+
{
|
|
143
|
+
id: "dsh-archive-manager#archiveManager/restore",
|
|
144
|
+
service: "archiveManager",
|
|
145
|
+
namespace: "archiveManager",
|
|
146
|
+
method: "restore",
|
|
147
|
+
invocation: { kind: "direct" },
|
|
148
|
+
parameters: [
|
|
149
|
+
{
|
|
150
|
+
name: "request",
|
|
151
|
+
wire: "request",
|
|
152
|
+
source: "json",
|
|
153
|
+
codec: strictCodec(
|
|
154
|
+
"dsh-archive-manager#ArchiveManagerRestoreRequest",
|
|
155
|
+
restoreRequestSchema
|
|
156
|
+
),
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
result: strictCodec(
|
|
160
|
+
"dsh-archive-manager#ArchiveManagerRestoreResult",
|
|
161
|
+
restoreResultSchema
|
|
162
|
+
),
|
|
163
|
+
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "dsh-archive-manager#archiveManager/delete",
|
|
167
|
+
service: "archiveManager",
|
|
168
|
+
namespace: "archiveManager",
|
|
169
|
+
method: "delete",
|
|
170
|
+
invocation: { kind: "direct" },
|
|
171
|
+
parameters: [
|
|
172
|
+
{
|
|
173
|
+
name: "request",
|
|
174
|
+
wire: "request",
|
|
175
|
+
source: "json",
|
|
176
|
+
codec: strictCodec(
|
|
177
|
+
"dsh-archive-manager#ArchiveManagerDeleteRequest",
|
|
178
|
+
deleteRequestSchema
|
|
179
|
+
),
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
result: strictCodec(
|
|
183
|
+
"dsh-archive-manager#ArchiveManagerDeleteResult",
|
|
184
|
+
deleteResultSchema
|
|
185
|
+
),
|
|
186
|
+
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: "dsh-archive-manager#archiveManager/state",
|
|
190
|
+
service: "archiveManager",
|
|
191
|
+
namespace: "archiveManager",
|
|
192
|
+
method: "state",
|
|
193
|
+
invocation: { kind: "direct" },
|
|
194
|
+
parameters: [],
|
|
195
|
+
result: strictCodec(
|
|
196
|
+
"dsh-archive-manager#ArchiveManagerStateResult",
|
|
197
|
+
stateResultSchema
|
|
198
|
+
),
|
|
199
|
+
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
model: {
|
|
203
|
+
services: [
|
|
204
|
+
{
|
|
205
|
+
description:
|
|
206
|
+
"Archive manager service: restore, delete and inspect archived sessions for the DeepSeek Harness web UI.",
|
|
207
|
+
summary: "Archive manager service.",
|
|
208
|
+
tags: [],
|
|
209
|
+
jsDoc:
|
|
210
|
+
"/**\n * Archive manager service: restore, delete and inspect archived sessions.\n */",
|
|
211
|
+
key: "archiveManager",
|
|
212
|
+
exportName: "ArchiveManagerService",
|
|
213
|
+
members: [
|
|
214
|
+
{
|
|
215
|
+
kind: "method",
|
|
216
|
+
name: "restore",
|
|
217
|
+
signature:
|
|
218
|
+
"@Remote('restore') async restore(request: ArchiveManagerRestoreRequest): Promise<ArchiveManagerRestoreResult>",
|
|
219
|
+
summary: "Remove one session from the archive set so it returns to its project slot.",
|
|
220
|
+
jsDoc:
|
|
221
|
+
"/**\n * Remove one session from the archive set so it returns to its project slot.\n * @param request - target session id.\n * @returns success or a business failure.\n */",
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
kind: "method",
|
|
225
|
+
name: "delete",
|
|
226
|
+
signature:
|
|
227
|
+
"@Remote('delete') async delete(request: ArchiveManagerDeleteRequest): Promise<ArchiveManagerDeleteResult>",
|
|
228
|
+
summary: "Permanently delete one archived session's log directory and clear its archive entry.",
|
|
229
|
+
jsDoc:
|
|
230
|
+
"/**\n * Permanently delete one archived session's log directory and clear its archive\n * entry. Refuses sessions whose agent is running; live-but-idle sessions keep\n * their entry (ghost) until restart.\n * @param request - target session id.\n * @returns success or a business failure.\n */",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
kind: "method",
|
|
234
|
+
name: "state",
|
|
235
|
+
signature:
|
|
236
|
+
"@Remote('state') async state(): Promise<ArchiveManagerStateResult>",
|
|
237
|
+
summary: "Report archived sessions that are live in memory but whose logs are gone.",
|
|
238
|
+
jsDoc:
|
|
239
|
+
"/**\n * Report archived sessions that are still live in memory while their log files\n * no longer exist (ghost records the client hides).\n * @returns the ghost session ids.\n */",
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
types: [
|
|
243
|
+
{
|
|
244
|
+
name: "ArchiveManagerRestoreRequest",
|
|
245
|
+
declaration:
|
|
246
|
+
"export interface ArchiveManagerRestoreRequest {\n readonly sessionId: SessionId;\n}",
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: "ArchiveManagerRestoreResult",
|
|
250
|
+
declaration:
|
|
251
|
+
"export type ArchiveManagerRestoreResult = { ok: true; value: { restored: true } } | { ok: false; error: { code: string; message?: string } };",
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
name: "ArchiveManagerDeleteRequest",
|
|
255
|
+
declaration:
|
|
256
|
+
"export interface ArchiveManagerDeleteRequest {\n readonly sessionId: SessionId;\n}",
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: "ArchiveManagerDeleteResult",
|
|
260
|
+
declaration:
|
|
261
|
+
"export type ArchiveManagerDeleteResult = { ok: true; value: { fileRemoved: boolean; live: boolean } } | { ok: false; error: { code: string; message?: string } };",
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
name: "ArchiveManagerStateResult",
|
|
265
|
+
declaration:
|
|
266
|
+
"export type ArchiveManagerStateResult = { ok: true; value: { ghostIds: readonly SessionId[] } } | { ok: false; error: { code: string; message?: string } };",
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: "SessionId",
|
|
270
|
+
declaration: "export type SessionId = Branded<'SessionId'>;",
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
events: [],
|
|
276
|
+
objects: [],
|
|
277
|
+
},
|
|
278
|
+
};
|