artifact-cafe 0.0.9 → 0.0.10
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/index.js +482 -384
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -83,11 +83,27 @@ var artifactListResponseSchema = z.object({
|
|
|
83
83
|
artifacts: z.array(artifactListItemSchema)
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
// ../shared/src/avatars.ts
|
|
87
|
+
import { z as z2 } from "zod";
|
|
88
|
+
var AVATAR_CONTENT_TYPES = [
|
|
89
|
+
"image/png",
|
|
90
|
+
"image/jpeg",
|
|
91
|
+
"image/webp"
|
|
92
|
+
];
|
|
93
|
+
var AVATAR_MAX_BYTES = 2 * 1024 * 1024;
|
|
94
|
+
var avatarContentTypeSchema = z2.enum(AVATAR_CONTENT_TYPES);
|
|
95
|
+
var userAvatarResponseSchema = z2.object({
|
|
96
|
+
image: z2.string().nullable()
|
|
97
|
+
});
|
|
98
|
+
var workspaceAvatarResponseSchema = z2.object({
|
|
99
|
+
logo: z2.string().nullable()
|
|
100
|
+
});
|
|
101
|
+
|
|
86
102
|
// ../shared/src/comments.ts
|
|
87
|
-
import { z as
|
|
103
|
+
import { z as z4 } from "zod";
|
|
88
104
|
|
|
89
105
|
// ../shared/src/publish.ts
|
|
90
|
-
import { z as
|
|
106
|
+
import { z as z3 } from "zod";
|
|
91
107
|
function isSafeArtifactPath(p) {
|
|
92
108
|
if (p.length === 0 || p.length > 1024) {
|
|
93
109
|
return false;
|
|
@@ -100,244 +116,258 @@ function isSafeArtifactPath(p) {
|
|
|
100
116
|
}
|
|
101
117
|
return p.split("/").every((seg) => seg.length > 0 && seg !== "." && seg !== "..");
|
|
102
118
|
}
|
|
103
|
-
var manifestFileSchema =
|
|
104
|
-
hash:
|
|
105
|
-
mimeType:
|
|
106
|
-
path:
|
|
119
|
+
var manifestFileSchema = z3.object({
|
|
120
|
+
hash: z3.string().regex(/^sha256_[a-f0-9]{64}$/),
|
|
121
|
+
mimeType: z3.string().regex(/^[-\w.+]+\/[-\w.+]+$/, { message: "invalid MIME type" }),
|
|
122
|
+
path: z3.string().min(1).max(1024).refine(isSafeArtifactPath, {
|
|
107
123
|
message: "path must be a safe relative path"
|
|
108
124
|
}),
|
|
109
|
-
size:
|
|
125
|
+
size: z3.number().int().positive()
|
|
110
126
|
});
|
|
111
|
-
var publishSourceSchema =
|
|
112
|
-
agent:
|
|
113
|
-
runId:
|
|
114
|
-
type:
|
|
127
|
+
var publishSourceSchema = z3.object({
|
|
128
|
+
agent: z3.string().optional(),
|
|
129
|
+
runId: z3.string().optional(),
|
|
130
|
+
type: z3.literal("cli")
|
|
115
131
|
});
|
|
116
|
-
var createPublishSessionSchema =
|
|
117
|
-
artifactId:
|
|
118
|
-
entryPath:
|
|
119
|
-
files:
|
|
132
|
+
var createPublishSessionSchema = z3.object({
|
|
133
|
+
artifactId: z3.string().nullable(),
|
|
134
|
+
entryPath: z3.string().optional(),
|
|
135
|
+
files: z3.array(manifestFileSchema).min(1).max(1e3),
|
|
120
136
|
// SPEC-2 §6.4 — workspace placement is available only to authenticated
|
|
121
137
|
// members; the API enforces membership and folder ownership. folderId
|
|
122
138
|
// without workspaceId resolves against the account's personal workspace.
|
|
123
|
-
folderId:
|
|
139
|
+
folderId: z3.string().min(1).optional(),
|
|
140
|
+
// Bullet-point changelog for this version, authored by the publisher.
|
|
141
|
+
// Optional on every publish (incl. v1); stored immutably on the version.
|
|
142
|
+
notes: z3.string().max(4e3).optional(),
|
|
124
143
|
source: publishSourceSchema,
|
|
125
|
-
title:
|
|
126
|
-
workspaceId:
|
|
127
|
-
});
|
|
128
|
-
var publishSessionResponseSchema =
|
|
129
|
-
artifactId:
|
|
130
|
-
expiresAt:
|
|
131
|
-
filesToUpload:
|
|
132
|
-
|
|
133
|
-
method:
|
|
134
|
-
path:
|
|
135
|
-
uploadUrl:
|
|
144
|
+
title: z3.string().max(200).optional(),
|
|
145
|
+
workspaceId: z3.string().min(1).optional()
|
|
146
|
+
});
|
|
147
|
+
var publishSessionResponseSchema = z3.object({
|
|
148
|
+
artifactId: z3.string(),
|
|
149
|
+
expiresAt: z3.string(),
|
|
150
|
+
filesToUpload: z3.array(
|
|
151
|
+
z3.object({
|
|
152
|
+
method: z3.literal("PUT"),
|
|
153
|
+
path: z3.string(),
|
|
154
|
+
uploadUrl: z3.string().url()
|
|
136
155
|
})
|
|
137
156
|
),
|
|
138
|
-
publishSessionId:
|
|
139
|
-
skippedFiles:
|
|
140
|
-
versionId:
|
|
157
|
+
publishSessionId: z3.string(),
|
|
158
|
+
skippedFiles: z3.array(z3.string()),
|
|
159
|
+
versionId: z3.string()
|
|
141
160
|
});
|
|
142
|
-
var finalizeResponseSchema =
|
|
143
|
-
artifactId:
|
|
161
|
+
var finalizeResponseSchema = z3.object({
|
|
162
|
+
artifactId: z3.string(),
|
|
144
163
|
// API-key publishes create the artifact already claimed (SPEC §5.4) —
|
|
145
164
|
// the CLI uses this to tell "claim URL pending" from "already yours".
|
|
146
|
-
claimed:
|
|
165
|
+
claimed: z3.boolean(),
|
|
147
166
|
// Returned only on first publish of a new artifact (one-time).
|
|
148
|
-
claimUrl:
|
|
149
|
-
publishToken:
|
|
150
|
-
url:
|
|
151
|
-
versionId:
|
|
152
|
-
versionNumber:
|
|
153
|
-
});
|
|
154
|
-
var artifactResponseSchema =
|
|
155
|
-
claimed:
|
|
156
|
-
currentVersion:
|
|
157
|
-
entryUrl:
|
|
158
|
-
id:
|
|
159
|
-
versionNumber:
|
|
167
|
+
claimUrl: z3.string().url().optional(),
|
|
168
|
+
publishToken: z3.string().optional(),
|
|
169
|
+
url: z3.string().url(),
|
|
170
|
+
versionId: z3.string(),
|
|
171
|
+
versionNumber: z3.number().int().positive()
|
|
172
|
+
});
|
|
173
|
+
var artifactResponseSchema = z3.object({
|
|
174
|
+
claimed: z3.boolean(),
|
|
175
|
+
currentVersion: z3.object({
|
|
176
|
+
entryUrl: z3.string().url(),
|
|
177
|
+
id: z3.string(),
|
|
178
|
+
versionNumber: z3.number().int().positive()
|
|
160
179
|
}).nullable(),
|
|
161
180
|
// SPEC-2 §6.4 — placement + visibility surface on the artifact.
|
|
162
|
-
folderId:
|
|
163
|
-
id:
|
|
164
|
-
slug:
|
|
165
|
-
title:
|
|
166
|
-
visibility:
|
|
167
|
-
workspaceId:
|
|
181
|
+
folderId: z3.string().nullable(),
|
|
182
|
+
id: z3.string(),
|
|
183
|
+
slug: z3.string(),
|
|
184
|
+
title: z3.string(),
|
|
185
|
+
visibility: z3.enum(["public", "unlisted", "workspace"]),
|
|
186
|
+
workspaceId: z3.string().nullable()
|
|
168
187
|
});
|
|
169
188
|
|
|
170
189
|
// ../shared/src/comments.ts
|
|
171
|
-
var anchorPageSchema =
|
|
190
|
+
var anchorPageSchema = z4.string().max(1024).refine(isSafeArtifactPath, {
|
|
172
191
|
message: "page must be a safe relative path"
|
|
173
192
|
}).optional();
|
|
174
|
-
var elementSnapshotSchema =
|
|
175
|
-
classes:
|
|
176
|
-
id:
|
|
177
|
-
tag:
|
|
178
|
-
text:
|
|
193
|
+
var elementSnapshotSchema = z4.object({
|
|
194
|
+
classes: z4.string().max(256).optional(),
|
|
195
|
+
id: z4.string().max(256).optional(),
|
|
196
|
+
tag: z4.string().min(1).max(128),
|
|
197
|
+
text: z4.string().max(200).optional()
|
|
179
198
|
});
|
|
180
|
-
var pointAnchorSchema =
|
|
199
|
+
var pointAnchorSchema = z4.object({
|
|
181
200
|
element: elementSnapshotSchema.optional(),
|
|
182
201
|
// elementPath is the primary anchor; x/y are offsets within the
|
|
183
202
|
// element's box, normalized 0..1 (SPEC.md §8.1).
|
|
184
|
-
elementPath:
|
|
203
|
+
elementPath: z4.string().max(2048),
|
|
185
204
|
page: anchorPageSchema,
|
|
186
|
-
type:
|
|
187
|
-
viewportHeight:
|
|
188
|
-
viewportWidth:
|
|
189
|
-
x:
|
|
190
|
-
y:
|
|
191
|
-
});
|
|
192
|
-
var textAnchorSchema =
|
|
193
|
-
elementPath:
|
|
194
|
-
endOffset:
|
|
205
|
+
type: z4.literal("point"),
|
|
206
|
+
viewportHeight: z4.number().int().positive().max(1e5),
|
|
207
|
+
viewportWidth: z4.number().int().positive().max(1e5),
|
|
208
|
+
x: z4.number().min(0).max(1),
|
|
209
|
+
y: z4.number().min(0).max(1)
|
|
210
|
+
});
|
|
211
|
+
var textAnchorSchema = z4.object({
|
|
212
|
+
elementPath: z4.string().max(2048),
|
|
213
|
+
endOffset: z4.number().int().nonnegative().max(1e8),
|
|
195
214
|
page: anchorPageSchema,
|
|
196
|
-
prefix:
|
|
197
|
-
quote:
|
|
198
|
-
startOffset:
|
|
199
|
-
suffix:
|
|
200
|
-
type:
|
|
215
|
+
prefix: z4.string().max(200).optional(),
|
|
216
|
+
quote: z4.string().min(1).max(1e3),
|
|
217
|
+
startOffset: z4.number().int().nonnegative().max(1e8),
|
|
218
|
+
suffix: z4.string().max(200).optional(),
|
|
219
|
+
type: z4.literal("text")
|
|
201
220
|
});
|
|
202
|
-
var pageAnchorSchema =
|
|
221
|
+
var pageAnchorSchema = z4.object({
|
|
203
222
|
page: anchorPageSchema,
|
|
204
|
-
type:
|
|
223
|
+
type: z4.literal("page")
|
|
205
224
|
});
|
|
206
|
-
var anchorSchema =
|
|
225
|
+
var anchorSchema = z4.discriminatedUnion("type", [
|
|
207
226
|
pointAnchorSchema,
|
|
208
227
|
textAnchorSchema,
|
|
209
228
|
pageAnchorSchema
|
|
210
229
|
]);
|
|
211
|
-
var displayNameSchema =
|
|
212
|
-
var guestSchema =
|
|
230
|
+
var displayNameSchema = z4.string().trim().min(1).max(64);
|
|
231
|
+
var guestSchema = z4.object({
|
|
213
232
|
displayName: displayNameSchema,
|
|
214
|
-
guestId:
|
|
233
|
+
guestId: z4.string().min(16)
|
|
215
234
|
});
|
|
216
|
-
var viaLabelSchema =
|
|
217
|
-
var createCommentThreadSchema =
|
|
235
|
+
var viaLabelSchema = z4.string().trim().min(1).max(64);
|
|
236
|
+
var createCommentThreadSchema = z4.object({
|
|
218
237
|
anchor: anchorSchema,
|
|
219
|
-
body:
|
|
238
|
+
body: z4.string().min(1).max(1e4),
|
|
220
239
|
guest: guestSchema.optional(),
|
|
221
|
-
versionId:
|
|
240
|
+
versionId: z4.string(),
|
|
222
241
|
via: viaLabelSchema.optional()
|
|
223
242
|
});
|
|
224
|
-
var createCommentMessageSchema =
|
|
225
|
-
body:
|
|
243
|
+
var createCommentMessageSchema = z4.object({
|
|
244
|
+
body: z4.string().min(1).max(1e4),
|
|
226
245
|
guest: guestSchema.optional(),
|
|
227
246
|
via: viaLabelSchema.optional()
|
|
228
247
|
});
|
|
229
|
-
var editCommentMessageSchema =
|
|
230
|
-
body:
|
|
248
|
+
var editCommentMessageSchema = z4.object({
|
|
249
|
+
body: z4.string().min(1).max(1e4),
|
|
231
250
|
guest: guestSchema.optional()
|
|
232
251
|
});
|
|
233
|
-
var threadActionSchema =
|
|
252
|
+
var threadActionSchema = z4.object({
|
|
234
253
|
guest: guestSchema.optional()
|
|
235
254
|
});
|
|
236
|
-
var
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
"
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
"\u{1F680}",
|
|
244
|
-
"\u2615"
|
|
245
|
-
];
|
|
246
|
-
var reactionEmojiSchema = z3.enum(REACTION_EMOJI);
|
|
247
|
-
var toggleReactionSchema = z3.object({
|
|
255
|
+
var SINGLE_EMOJI = new RegExp("^\\p{RGI_Emoji}$", "v");
|
|
256
|
+
var REDUNDANT_VS16 = new RegExp("(\\p{Emoji_Presentation})\\uFE0F", "gu");
|
|
257
|
+
function canonicalizeEmoji(s) {
|
|
258
|
+
return s.replace(REDUNDANT_VS16, "$1");
|
|
259
|
+
}
|
|
260
|
+
var reactionEmojiSchema = z4.string().max(64).transform(canonicalizeEmoji).refine((s) => SINGLE_EMOJI.test(s), { message: "Must be a single emoji." }).describe("A single emoji, e.g. \u{1F44D}");
|
|
261
|
+
var toggleReactionSchema = z4.object({
|
|
248
262
|
emoji: reactionEmojiSchema,
|
|
249
263
|
guest: guestSchema.optional()
|
|
250
264
|
});
|
|
251
|
-
var commentAuthorSchema =
|
|
252
|
-
avatarUrl:
|
|
253
|
-
displayName:
|
|
254
|
-
guestId:
|
|
255
|
-
isViewer:
|
|
256
|
-
kind:
|
|
265
|
+
var commentAuthorSchema = z4.object({
|
|
266
|
+
avatarUrl: z4.string().nullable(),
|
|
267
|
+
displayName: z4.string(),
|
|
268
|
+
guestId: z4.string().nullable(),
|
|
269
|
+
isViewer: z4.boolean(),
|
|
270
|
+
kind: z4.enum(["member", "guest"]),
|
|
257
271
|
// Optional "via" attribution (§6.4). Null for plain comments; a bounded
|
|
258
272
|
// label the shell appends after the display name.
|
|
259
|
-
via:
|
|
273
|
+
via: z4.string().nullable()
|
|
260
274
|
});
|
|
261
|
-
var messageReactionSchema =
|
|
262
|
-
emoji:
|
|
263
|
-
reactors:
|
|
275
|
+
var messageReactionSchema = z4.object({
|
|
276
|
+
emoji: z4.string(),
|
|
277
|
+
reactors: z4.array(commentAuthorSchema)
|
|
264
278
|
});
|
|
265
|
-
var commentMessageSchema =
|
|
279
|
+
var commentMessageSchema = z4.object({
|
|
266
280
|
author: commentAuthorSchema,
|
|
267
281
|
// Empty string for a deleted message — the body is stripped server-side
|
|
268
282
|
// (§6.7.1 tombstone), never sent to the client and hidden there.
|
|
269
|
-
body:
|
|
270
|
-
createdAt:
|
|
283
|
+
body: z4.string(),
|
|
284
|
+
createdAt: z4.string(),
|
|
271
285
|
// Soft-deleted (§6.7.1). A tombstone keeps thread structure and replies;
|
|
272
286
|
// the shell renders "Comment deleted" instead of the (absent) body.
|
|
273
|
-
deleted:
|
|
287
|
+
deleted: z4.boolean(),
|
|
274
288
|
// Last edit time (§6.7.1), or null if never edited — drives the "edited"
|
|
275
289
|
// badge. No edit history is kept.
|
|
276
|
-
editedAt:
|
|
277
|
-
id:
|
|
290
|
+
editedAt: z4.string().nullable(),
|
|
291
|
+
id: z4.string(),
|
|
278
292
|
// Defaulted, not required: a new CLI parsing an older server's
|
|
279
293
|
// response must not fail on the missing key.
|
|
280
|
-
reactions:
|
|
281
|
-
});
|
|
282
|
-
var
|
|
294
|
+
reactions: z4.array(messageReactionSchema).default([])
|
|
295
|
+
});
|
|
296
|
+
var threadActorSchema = z4.object({
|
|
297
|
+
displayName: z4.string(),
|
|
298
|
+
kind: z4.enum(["member", "guest", "agent"])
|
|
299
|
+
});
|
|
300
|
+
var commentThreadSchema = z4.object({
|
|
301
|
+
// §6.6.1 — set while open to signal "seen, working on it"; cleared on
|
|
302
|
+
// reopen, kept (but superseded in display) once resolved. Defaulted so
|
|
303
|
+
// clients parsing an older server's response don't fail.
|
|
304
|
+
acknowledgedAt: z4.string().nullable().default(null),
|
|
305
|
+
acknowledgedBy: threadActorSchema.nullable().default(null),
|
|
283
306
|
anchor: anchorSchema,
|
|
284
|
-
artifactId:
|
|
285
|
-
createdAt:
|
|
307
|
+
artifactId: z4.string(),
|
|
308
|
+
createdAt: z4.string(),
|
|
286
309
|
createdBy: commentAuthorSchema,
|
|
287
|
-
id:
|
|
288
|
-
messages:
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
});
|
|
295
|
-
var
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
310
|
+
id: z4.string(),
|
|
311
|
+
messages: z4.array(commentMessageSchema),
|
|
312
|
+
// Null on threads resolved before actor recording existed, and always
|
|
313
|
+
// null while open.
|
|
314
|
+
resolvedBy: threadActorSchema.nullable().default(null),
|
|
315
|
+
status: z4.enum(["open", "resolved"]),
|
|
316
|
+
versionId: z4.string()
|
|
317
|
+
});
|
|
318
|
+
var commentThreadListSchema = z4.object({
|
|
319
|
+
threads: z4.array(commentThreadSchema)
|
|
320
|
+
});
|
|
321
|
+
var commentExportQuerySchema = z4.object({
|
|
322
|
+
status: z4.enum(["open", "resolved", "all"]).default("open"),
|
|
323
|
+
version: z4.enum(["current", "all"]).default("current")
|
|
324
|
+
});
|
|
325
|
+
var exportReactionSchema = z4.object({
|
|
326
|
+
count: z4.number().int().positive(),
|
|
327
|
+
emoji: z4.string()
|
|
328
|
+
});
|
|
329
|
+
var commentExportReplySchema = z4.object({
|
|
330
|
+
author: z4.string(),
|
|
331
|
+
authorKind: z4.enum(["member", "guest"]),
|
|
332
|
+
body: z4.string(),
|
|
333
|
+
createdAt: z4.string(),
|
|
308
334
|
// Soft-delete tombstone (§6.7.1): body is "" when true.
|
|
309
|
-
deleted:
|
|
310
|
-
editedAt:
|
|
335
|
+
deleted: z4.boolean(),
|
|
336
|
+
editedAt: z4.string().nullable(),
|
|
311
337
|
// The message id — what `edit`/`delete` target (§5.1).
|
|
312
|
-
id:
|
|
313
|
-
reactions:
|
|
338
|
+
id: z4.string(),
|
|
339
|
+
reactions: z4.array(exportReactionSchema).optional()
|
|
314
340
|
});
|
|
315
|
-
var commentExportThreadSchema =
|
|
341
|
+
var commentExportThreadSchema = z4.object({
|
|
342
|
+
// §6.6.1 — lets a polling agent skip threads it already acknowledged
|
|
343
|
+
// (acknowledged threads stay in status=open exports on purpose).
|
|
344
|
+
acknowledgedAt: z4.string().nullable().default(null),
|
|
316
345
|
anchor: anchorSchema,
|
|
317
|
-
author:
|
|
318
|
-
authorKind:
|
|
319
|
-
body:
|
|
320
|
-
createdAt:
|
|
321
|
-
deleted:
|
|
322
|
-
editedAt:
|
|
323
|
-
id:
|
|
346
|
+
author: z4.string(),
|
|
347
|
+
authorKind: z4.enum(["member", "guest"]),
|
|
348
|
+
body: z4.string(),
|
|
349
|
+
createdAt: z4.string(),
|
|
350
|
+
deleted: z4.boolean(),
|
|
351
|
+
editedAt: z4.string().nullable(),
|
|
352
|
+
id: z4.string(),
|
|
324
353
|
// The opening message's id (distinct from the thread `id`) — `edit`/
|
|
325
354
|
// `delete` operate on messages, so the CLI needs it to target the first
|
|
326
355
|
// comment, not just the replies.
|
|
327
|
-
messageId:
|
|
328
|
-
reactions:
|
|
329
|
-
replies:
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
356
|
+
messageId: z4.string(),
|
|
357
|
+
reactions: z4.array(exportReactionSchema).optional(),
|
|
358
|
+
replies: z4.array(commentExportReplySchema),
|
|
359
|
+
resolvedBy: threadActorSchema.nullable().default(null),
|
|
360
|
+
status: z4.enum(["open", "resolved"]),
|
|
361
|
+
versionNumber: z4.number().int().positive()
|
|
362
|
+
});
|
|
363
|
+
var commentExportSchema = z4.object({
|
|
364
|
+
artifactId: z4.string(),
|
|
365
|
+
comments: z4.array(commentExportThreadSchema),
|
|
336
366
|
// The artifact's current version (null before the first finalize).
|
|
337
|
-
versionNumber:
|
|
367
|
+
versionNumber: z4.number().int().positive().nullable()
|
|
338
368
|
});
|
|
339
|
-
var commentReadResponseSchema =
|
|
340
|
-
lastSeenAt:
|
|
369
|
+
var commentReadResponseSchema = z4.object({
|
|
370
|
+
lastSeenAt: z4.string()
|
|
341
371
|
});
|
|
342
372
|
function elementLabel(el) {
|
|
343
373
|
if (el.id) {
|
|
@@ -348,163 +378,166 @@ function elementLabel(el) {
|
|
|
348
378
|
}
|
|
349
379
|
|
|
350
380
|
// ../shared/src/errors.ts
|
|
351
|
-
import { z as
|
|
352
|
-
var apiErrorSchema =
|
|
353
|
-
code:
|
|
354
|
-
docsUrl:
|
|
355
|
-
message:
|
|
356
|
-
retryAfter:
|
|
381
|
+
import { z as z5 } from "zod";
|
|
382
|
+
var apiErrorSchema = z5.object({
|
|
383
|
+
code: z5.string(),
|
|
384
|
+
docsUrl: z5.string().url(),
|
|
385
|
+
message: z5.string(),
|
|
386
|
+
retryAfter: z5.number().int().positive().optional()
|
|
357
387
|
});
|
|
358
388
|
|
|
359
389
|
// ../shared/src/feedback.ts
|
|
360
|
-
import { z as
|
|
361
|
-
var feedbackRequestSchema =
|
|
362
|
-
email:
|
|
363
|
-
message:
|
|
390
|
+
import { z as z6 } from "zod";
|
|
391
|
+
var feedbackRequestSchema = z6.object({
|
|
392
|
+
email: z6.string().trim().toLowerCase().email().optional().or(z6.literal("")),
|
|
393
|
+
message: z6.string().trim().min(1).max(4e3)
|
|
364
394
|
});
|
|
365
|
-
var feedbackResponseSchema =
|
|
366
|
-
sent:
|
|
395
|
+
var feedbackResponseSchema = z6.object({
|
|
396
|
+
sent: z6.literal(true)
|
|
367
397
|
});
|
|
368
398
|
|
|
369
399
|
// ../shared/src/me.ts
|
|
370
|
-
import { z as
|
|
371
|
-
var ownArtifactSchema =
|
|
372
|
-
createdAt:
|
|
373
|
-
currentVersionNumber:
|
|
400
|
+
import { z as z7 } from "zod";
|
|
401
|
+
var ownArtifactSchema = z7.object({
|
|
402
|
+
createdAt: z7.string(),
|
|
403
|
+
currentVersionNumber: z7.number().nullable(),
|
|
374
404
|
// Owned artifacts normally never expire; non-null only while an
|
|
375
405
|
// expiry is still set (e.g. an unclaimed publish surfaced here later).
|
|
376
|
-
expiresAt:
|
|
406
|
+
expiresAt: z7.string().nullable(),
|
|
377
407
|
// SPEC-2 §8.4 — the containing folder for workspace-owned artifacts;
|
|
378
408
|
// both null for personal artifacts. `folderId` drives the dashboard's
|
|
379
409
|
// move control and folder filter; `folderName` is the display label.
|
|
380
|
-
folderId:
|
|
381
|
-
folderName:
|
|
410
|
+
folderId: z7.string().nullable(),
|
|
411
|
+
folderName: z7.string().nullable(),
|
|
382
412
|
// Whether a publish token is still active — revocable from the
|
|
383
413
|
// dashboard (§6.18); the token itself is never returned.
|
|
384
|
-
hasPublishToken:
|
|
385
|
-
id:
|
|
386
|
-
openThreads:
|
|
387
|
-
protected:
|
|
388
|
-
slug:
|
|
389
|
-
title:
|
|
390
|
-
totalViews:
|
|
414
|
+
hasPublishToken: z7.boolean(),
|
|
415
|
+
id: z7.string(),
|
|
416
|
+
openThreads: z7.number(),
|
|
417
|
+
protected: z7.boolean(),
|
|
418
|
+
slug: z7.string(),
|
|
419
|
+
title: z7.string(),
|
|
420
|
+
totalViews: z7.number(),
|
|
391
421
|
// SPEC §6.20 — messages by others newer than the viewer's last-seen
|
|
392
422
|
// watermark. 0 for signed-out/API-key-less contexts.
|
|
393
|
-
unreadComments:
|
|
394
|
-
updatedAt:
|
|
395
|
-
url:
|
|
396
|
-
versionCount:
|
|
423
|
+
unreadComments: z7.number(),
|
|
424
|
+
updatedAt: z7.string(),
|
|
425
|
+
url: z7.string(),
|
|
426
|
+
versionCount: z7.number()
|
|
397
427
|
});
|
|
398
|
-
var ownArtifactsResponseSchema =
|
|
399
|
-
artifacts:
|
|
428
|
+
var ownArtifactsResponseSchema = z7.object({
|
|
429
|
+
artifacts: z7.array(ownArtifactSchema)
|
|
400
430
|
});
|
|
401
|
-
var revokePublishTokenResponseSchema =
|
|
402
|
-
revoked:
|
|
431
|
+
var revokePublishTokenResponseSchema = z7.object({
|
|
432
|
+
revoked: z7.boolean()
|
|
403
433
|
});
|
|
404
434
|
|
|
405
435
|
// ../shared/src/owner.ts
|
|
406
|
-
import { z as
|
|
436
|
+
import { z as z9 } from "zod";
|
|
407
437
|
|
|
408
438
|
// ../shared/src/workspaces.ts
|
|
409
|
-
import { z as
|
|
439
|
+
import { z as z8 } from "zod";
|
|
410
440
|
var WORKSPACE_HANDLE_PATTERN = /^[a-z0-9](?:[a-z0-9-]{1,30}[a-z0-9])$/;
|
|
411
|
-
var workspaceRoleSchema =
|
|
412
|
-
var workspaceInviteRoleSchema =
|
|
413
|
-
var workspaceHandleSchema =
|
|
441
|
+
var workspaceRoleSchema = z8.enum(["owner", "admin", "member"]);
|
|
442
|
+
var workspaceInviteRoleSchema = z8.enum(["admin", "member"]);
|
|
443
|
+
var workspaceHandleSchema = z8.string().min(3).max(32).regex(WORKSPACE_HANDLE_PATTERN, {
|
|
414
444
|
message: "handle must be lowercase letters, digits, and hyphens, with no leading/trailing hyphen"
|
|
415
445
|
});
|
|
416
|
-
var createWorkspaceSchema =
|
|
446
|
+
var createWorkspaceSchema = z8.object({
|
|
417
447
|
handle: workspaceHandleSchema.optional(),
|
|
418
|
-
name:
|
|
448
|
+
name: z8.string().trim().min(1).max(100)
|
|
419
449
|
});
|
|
420
|
-
var updateWorkspaceSchema =
|
|
450
|
+
var updateWorkspaceSchema = z8.object({
|
|
421
451
|
handle: workspaceHandleSchema.optional(),
|
|
422
|
-
name:
|
|
452
|
+
name: z8.string().trim().min(1).max(100).optional()
|
|
423
453
|
}).refine((body) => body.handle !== void 0 || body.name !== void 0, {
|
|
424
454
|
message: "provide at least one of name or handle"
|
|
425
455
|
});
|
|
426
|
-
var workspaceSchema =
|
|
427
|
-
createdAt:
|
|
428
|
-
handle:
|
|
429
|
-
id:
|
|
456
|
+
var workspaceSchema = z8.object({
|
|
457
|
+
createdAt: z8.string(),
|
|
458
|
+
handle: z8.string(),
|
|
459
|
+
id: z8.string(),
|
|
430
460
|
// Auto-provisioned solo workspace, one per user: non-deletable, takes
|
|
431
461
|
// no members, renameable like any workspace.
|
|
432
|
-
isPersonal:
|
|
433
|
-
|
|
462
|
+
isPersonal: z8.boolean(),
|
|
463
|
+
// Uploaded logo URL, or null for the initials fallback. Set through the
|
|
464
|
+
// dedicated /workspaces/:id/avatar route, never the generic update.
|
|
465
|
+
logo: z8.string().nullable(),
|
|
466
|
+
name: z8.string(),
|
|
434
467
|
role: workspaceRoleSchema.nullable(),
|
|
435
|
-
updatedAt:
|
|
468
|
+
updatedAt: z8.string()
|
|
436
469
|
});
|
|
437
|
-
var workspaceListResponseSchema =
|
|
438
|
-
workspaces:
|
|
470
|
+
var workspaceListResponseSchema = z8.object({
|
|
471
|
+
workspaces: z8.array(workspaceSchema)
|
|
439
472
|
});
|
|
440
|
-
var deleteWorkspaceResponseSchema =
|
|
441
|
-
deleted:
|
|
473
|
+
var deleteWorkspaceResponseSchema = z8.object({
|
|
474
|
+
deleted: z8.literal(true)
|
|
442
475
|
});
|
|
443
|
-
var workspaceMemberSchema =
|
|
444
|
-
createdAt:
|
|
445
|
-
email:
|
|
446
|
-
image:
|
|
447
|
-
name:
|
|
476
|
+
var workspaceMemberSchema = z8.object({
|
|
477
|
+
createdAt: z8.string(),
|
|
478
|
+
email: z8.string().email(),
|
|
479
|
+
image: z8.string().nullable(),
|
|
480
|
+
name: z8.string(),
|
|
448
481
|
role: workspaceRoleSchema,
|
|
449
|
-
userId:
|
|
482
|
+
userId: z8.string()
|
|
450
483
|
});
|
|
451
|
-
var workspaceMemberListResponseSchema =
|
|
452
|
-
members:
|
|
484
|
+
var workspaceMemberListResponseSchema = z8.object({
|
|
485
|
+
members: z8.array(workspaceMemberSchema)
|
|
453
486
|
});
|
|
454
|
-
var updateWorkspaceMemberSchema =
|
|
487
|
+
var updateWorkspaceMemberSchema = z8.object({
|
|
455
488
|
role: workspaceRoleSchema
|
|
456
489
|
});
|
|
457
|
-
var removeWorkspaceMemberResponseSchema =
|
|
458
|
-
removed:
|
|
490
|
+
var removeWorkspaceMemberResponseSchema = z8.object({
|
|
491
|
+
removed: z8.literal(true)
|
|
459
492
|
});
|
|
460
|
-
var createWorkspaceInviteSchema =
|
|
461
|
-
email:
|
|
462
|
-
expiresAt:
|
|
463
|
-
maxUses:
|
|
493
|
+
var createWorkspaceInviteSchema = z8.object({
|
|
494
|
+
email: z8.string().trim().toLowerCase().email().optional(),
|
|
495
|
+
expiresAt: z8.string().datetime(),
|
|
496
|
+
maxUses: z8.number().int().positive().optional(),
|
|
464
497
|
role: workspaceInviteRoleSchema
|
|
465
498
|
});
|
|
466
|
-
var workspaceInviteSchema =
|
|
467
|
-
createdAt:
|
|
468
|
-
email:
|
|
469
|
-
expiresAt:
|
|
470
|
-
id:
|
|
471
|
-
maxUses:
|
|
499
|
+
var workspaceInviteSchema = z8.object({
|
|
500
|
+
createdAt: z8.string(),
|
|
501
|
+
email: z8.string().email().nullable(),
|
|
502
|
+
expiresAt: z8.string(),
|
|
503
|
+
id: z8.string(),
|
|
504
|
+
maxUses: z8.number().int().positive().nullable(),
|
|
472
505
|
role: workspaceInviteRoleSchema,
|
|
473
|
-
tokenPrefix:
|
|
474
|
-
useCount:
|
|
506
|
+
tokenPrefix: z8.string(),
|
|
507
|
+
useCount: z8.number().int().nonnegative()
|
|
475
508
|
});
|
|
476
509
|
var createdWorkspaceInviteSchema = workspaceInviteSchema.extend({
|
|
477
|
-
url:
|
|
510
|
+
url: z8.string().url()
|
|
478
511
|
});
|
|
479
|
-
var workspaceInviteListResponseSchema =
|
|
480
|
-
invites:
|
|
512
|
+
var workspaceInviteListResponseSchema = z8.object({
|
|
513
|
+
invites: z8.array(workspaceInviteSchema)
|
|
481
514
|
});
|
|
482
|
-
var revokeWorkspaceInviteResponseSchema =
|
|
483
|
-
revoked:
|
|
515
|
+
var revokeWorkspaceInviteResponseSchema = z8.object({
|
|
516
|
+
revoked: z8.literal(true)
|
|
484
517
|
});
|
|
485
|
-
var acceptWorkspaceInviteSchema =
|
|
486
|
-
token:
|
|
518
|
+
var acceptWorkspaceInviteSchema = z8.object({
|
|
519
|
+
token: z8.string().min(1)
|
|
487
520
|
});
|
|
488
|
-
var acceptWorkspaceInviteResponseSchema =
|
|
521
|
+
var acceptWorkspaceInviteResponseSchema = z8.object({
|
|
489
522
|
role: workspaceRoleSchema,
|
|
490
523
|
workspace: workspaceSchema
|
|
491
524
|
});
|
|
492
|
-
var folderVisibilitySchema =
|
|
493
|
-
var artifactVisibilitySchema =
|
|
525
|
+
var folderVisibilitySchema = z8.enum(["public", "workspace"]);
|
|
526
|
+
var artifactVisibilitySchema = z8.enum([
|
|
494
527
|
"public",
|
|
495
528
|
"unlisted",
|
|
496
529
|
"workspace"
|
|
497
530
|
]);
|
|
498
|
-
var createFolderSchema =
|
|
499
|
-
name:
|
|
531
|
+
var createFolderSchema = z8.object({
|
|
532
|
+
name: z8.string().trim().min(1).max(100),
|
|
500
533
|
visibility: folderVisibilitySchema
|
|
501
534
|
});
|
|
502
|
-
var updateFolderSchema =
|
|
535
|
+
var updateFolderSchema = z8.object({
|
|
503
536
|
// With `visibility`: bulk-update the folder's artifacts to match
|
|
504
537
|
// (SPEC-2 §3.4 "Changing a folder's visibility offers a bulk update").
|
|
505
|
-
cascade:
|
|
506
|
-
name:
|
|
507
|
-
sortOrder:
|
|
538
|
+
cascade: z8.boolean().optional(),
|
|
539
|
+
name: z8.string().trim().min(1).max(100).optional(),
|
|
540
|
+
sortOrder: z8.number().int().min(0).optional(),
|
|
508
541
|
visibility: folderVisibilitySchema.optional()
|
|
509
542
|
}).refine(
|
|
510
543
|
(body) => body.name !== void 0 || body.visibility !== void 0 || body.sortOrder !== void 0,
|
|
@@ -512,168 +545,170 @@ var updateFolderSchema = z7.object({
|
|
|
512
545
|
).refine((body) => !body.cascade || body.visibility !== void 0, {
|
|
513
546
|
message: "cascade requires visibility"
|
|
514
547
|
});
|
|
515
|
-
var folderSchema =
|
|
516
|
-
createdAt:
|
|
517
|
-
id:
|
|
518
|
-
name:
|
|
548
|
+
var folderSchema = z8.object({
|
|
549
|
+
createdAt: z8.string(),
|
|
550
|
+
id: z8.string(),
|
|
551
|
+
name: z8.string(),
|
|
519
552
|
// Permalink segment for the public folder page (/w/{handle}/f/{slug}).
|
|
520
553
|
// Server-derived from the name; renames regenerate it.
|
|
521
|
-
slug:
|
|
522
|
-
sortOrder:
|
|
523
|
-
updatedAt:
|
|
554
|
+
slug: z8.string(),
|
|
555
|
+
sortOrder: z8.number().int(),
|
|
556
|
+
updatedAt: z8.string(),
|
|
524
557
|
visibility: folderVisibilitySchema,
|
|
525
|
-
workspaceId:
|
|
558
|
+
workspaceId: z8.string()
|
|
526
559
|
});
|
|
527
|
-
var folderListResponseSchema =
|
|
528
|
-
folders:
|
|
560
|
+
var folderListResponseSchema = z8.object({
|
|
561
|
+
folders: z8.array(folderSchema)
|
|
529
562
|
});
|
|
530
|
-
var deleteFolderResponseSchema =
|
|
531
|
-
deleted:
|
|
563
|
+
var deleteFolderResponseSchema = z8.object({
|
|
564
|
+
deleted: z8.literal(true)
|
|
532
565
|
});
|
|
533
|
-
var workspaceArtifactSchema =
|
|
534
|
-
createdAt:
|
|
535
|
-
currentVersionNumber:
|
|
536
|
-
folderId:
|
|
537
|
-
id:
|
|
538
|
-
openCommentCount:
|
|
539
|
-
slug:
|
|
540
|
-
title:
|
|
541
|
-
updatedAt:
|
|
542
|
-
url:
|
|
543
|
-
versionCount:
|
|
566
|
+
var workspaceArtifactSchema = z8.object({
|
|
567
|
+
createdAt: z8.string(),
|
|
568
|
+
currentVersionNumber: z8.number().int().nullable(),
|
|
569
|
+
folderId: z8.string().nullable(),
|
|
570
|
+
id: z8.string(),
|
|
571
|
+
openCommentCount: z8.number().int().nonnegative(),
|
|
572
|
+
slug: z8.string(),
|
|
573
|
+
title: z8.string(),
|
|
574
|
+
updatedAt: z8.string(),
|
|
575
|
+
url: z8.string().url(),
|
|
576
|
+
versionCount: z8.number().int().nonnegative(),
|
|
544
577
|
visibility: artifactVisibilitySchema
|
|
545
578
|
});
|
|
546
|
-
var workspaceArtifactListResponseSchema =
|
|
547
|
-
artifacts:
|
|
579
|
+
var workspaceArtifactListResponseSchema = z8.object({
|
|
580
|
+
artifacts: z8.array(workspaceArtifactSchema)
|
|
548
581
|
});
|
|
549
582
|
|
|
550
583
|
// ../shared/src/owner.ts
|
|
551
584
|
var SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])$/;
|
|
552
|
-
var claimResponseSchema =
|
|
553
|
-
artifactId:
|
|
554
|
-
slug:
|
|
555
|
-
title:
|
|
556
|
-
url:
|
|
585
|
+
var claimResponseSchema = z9.object({
|
|
586
|
+
artifactId: z9.string(),
|
|
587
|
+
slug: z9.string(),
|
|
588
|
+
title: z9.string(),
|
|
589
|
+
url: z9.string().url()
|
|
557
590
|
});
|
|
558
|
-
var updateArtifactSchema =
|
|
591
|
+
var updateArtifactSchema = z9.object({
|
|
559
592
|
// SPEC-2 §6.4 — placement + visibility. `folderId: null` clears the
|
|
560
593
|
// folder; `workspaceId: null` moves the artifact out of its workspace
|
|
561
594
|
// (§5.5 ownership transfer).
|
|
562
|
-
folderId:
|
|
563
|
-
slug:
|
|
595
|
+
folderId: z9.string().min(1).nullable().optional(),
|
|
596
|
+
slug: z9.string().min(3).max(63).regex(SLUG_PATTERN, {
|
|
564
597
|
message: "slug must be lowercase letters, digits, and hyphens, with no leading/trailing hyphen"
|
|
565
598
|
}).optional(),
|
|
566
|
-
title:
|
|
599
|
+
title: z9.string().min(1).max(200).optional(),
|
|
567
600
|
visibility: artifactVisibilitySchema.optional(),
|
|
568
|
-
workspaceId:
|
|
601
|
+
workspaceId: z9.string().min(1).nullable().optional()
|
|
569
602
|
}).refine(
|
|
570
603
|
(body) => body.title !== void 0 || body.slug !== void 0 || body.visibility !== void 0 || body.folderId !== void 0 || body.workspaceId !== void 0,
|
|
571
604
|
{
|
|
572
605
|
message: "provide at least one of title, slug, visibility, folderId, workspaceId"
|
|
573
606
|
}
|
|
574
607
|
);
|
|
575
|
-
var deleteArtifactResponseSchema =
|
|
576
|
-
deleted:
|
|
608
|
+
var deleteArtifactResponseSchema = z9.object({
|
|
609
|
+
deleted: z9.literal(true)
|
|
577
610
|
});
|
|
578
611
|
|
|
579
612
|
// ../shared/src/presence.ts
|
|
580
|
-
import { z as
|
|
613
|
+
import { z as z10 } from "zod";
|
|
581
614
|
var AGENT_PRESENCE = {
|
|
582
615
|
heartbeatSeconds: 15,
|
|
583
616
|
shellPollSeconds: 15,
|
|
584
617
|
ttlSeconds: 45
|
|
585
618
|
};
|
|
586
|
-
var agentHeartbeatResponseSchema =
|
|
587
|
-
listening:
|
|
588
|
-
ttlSeconds:
|
|
619
|
+
var agentHeartbeatResponseSchema = z10.object({
|
|
620
|
+
listening: z10.literal(true),
|
|
621
|
+
ttlSeconds: z10.number().int().positive()
|
|
589
622
|
});
|
|
590
|
-
var agentPresenceSchema =
|
|
591
|
-
listening:
|
|
592
|
-
versionNumber:
|
|
623
|
+
var agentPresenceSchema = z10.object({
|
|
624
|
+
listening: z10.boolean(),
|
|
625
|
+
versionNumber: z10.number().int().positive().nullable()
|
|
593
626
|
});
|
|
594
627
|
|
|
595
628
|
// ../shared/src/protection.ts
|
|
596
|
-
import { z as
|
|
629
|
+
import { z as z11 } from "zod";
|
|
597
630
|
var PASSWORD_MIN = 6;
|
|
598
631
|
var PASSWORD_MAX = 128;
|
|
599
|
-
var gatePasswordSchema =
|
|
600
|
-
var setProtectionSchema =
|
|
632
|
+
var gatePasswordSchema = z11.string().min(PASSWORD_MIN, `Password must be at least ${PASSWORD_MIN} characters.`).max(PASSWORD_MAX, `Password must be at most ${PASSWORD_MAX} characters.`);
|
|
633
|
+
var setProtectionSchema = z11.object({
|
|
601
634
|
password: gatePasswordSchema.nullable()
|
|
602
635
|
});
|
|
603
|
-
var protectionResponseSchema =
|
|
604
|
-
protected:
|
|
636
|
+
var protectionResponseSchema = z11.object({
|
|
637
|
+
protected: z11.boolean()
|
|
605
638
|
});
|
|
606
|
-
var unlockSchema =
|
|
607
|
-
password:
|
|
639
|
+
var unlockSchema = z11.object({
|
|
640
|
+
password: z11.string().min(1).max(1024)
|
|
608
641
|
});
|
|
609
|
-
var unlockResponseSchema =
|
|
610
|
-
unlocked:
|
|
642
|
+
var unlockResponseSchema = z11.object({
|
|
643
|
+
unlocked: z11.literal(true)
|
|
611
644
|
});
|
|
612
645
|
|
|
613
646
|
// ../shared/src/report.ts
|
|
614
|
-
import { z as
|
|
615
|
-
var reportRequestSchema =
|
|
616
|
-
reason:
|
|
647
|
+
import { z as z12 } from "zod";
|
|
648
|
+
var reportRequestSchema = z12.object({
|
|
649
|
+
reason: z12.string().max(1e3).optional()
|
|
617
650
|
});
|
|
618
|
-
var reportResponseSchema =
|
|
619
|
-
reported:
|
|
651
|
+
var reportResponseSchema = z12.object({
|
|
652
|
+
reported: z12.literal(true)
|
|
620
653
|
});
|
|
621
654
|
|
|
622
655
|
// ../shared/src/stats.ts
|
|
623
|
-
import { z as
|
|
624
|
-
var avgViewSecondsSchema =
|
|
625
|
-
var versionViewStatsSchema =
|
|
656
|
+
import { z as z13 } from "zod";
|
|
657
|
+
var avgViewSecondsSchema = z13.number().int().nonnegative().nullable();
|
|
658
|
+
var versionViewStatsSchema = z13.object({
|
|
626
659
|
avgViewSeconds: avgViewSecondsSchema,
|
|
627
660
|
// Views from inside the review shell's iframe vs. direct visits to
|
|
628
661
|
// the render URL. views = embeddedViews + directViews.
|
|
629
|
-
directViews:
|
|
630
|
-
embeddedViews:
|
|
662
|
+
directViews: z13.number().int().nonnegative(),
|
|
663
|
+
embeddedViews: z13.number().int().nonnegative(),
|
|
631
664
|
// Distinct hashed viewer IPs across the version's lifetime.
|
|
632
|
-
uniqueViewers:
|
|
633
|
-
versionNumber:
|
|
634
|
-
views:
|
|
665
|
+
uniqueViewers: z13.number().int().nonnegative(),
|
|
666
|
+
versionNumber: z13.number().int().positive(),
|
|
667
|
+
views: z13.number().int().nonnegative()
|
|
635
668
|
});
|
|
636
|
-
var dailyViewsSchema =
|
|
669
|
+
var dailyViewsSchema = z13.object({
|
|
637
670
|
avgViewSeconds: avgViewSecondsSchema,
|
|
638
671
|
// UTC day, YYYY-MM-DD.
|
|
639
|
-
day:
|
|
640
|
-
uniqueViewers:
|
|
641
|
-
views:
|
|
672
|
+
day: z13.string(),
|
|
673
|
+
uniqueViewers: z13.number().int().nonnegative(),
|
|
674
|
+
views: z13.number().int().nonnegative()
|
|
642
675
|
});
|
|
643
|
-
var artifactStatsResponseSchema =
|
|
676
|
+
var artifactStatsResponseSchema = z13.object({
|
|
644
677
|
avgViewSeconds: avgViewSecondsSchema,
|
|
645
|
-
daily:
|
|
678
|
+
daily: z13.array(dailyViewsSchema),
|
|
646
679
|
// Distinct hashed viewer IPs across all versions and days.
|
|
647
|
-
totalUniqueViewers:
|
|
648
|
-
totalViews:
|
|
649
|
-
versions:
|
|
680
|
+
totalUniqueViewers: z13.number().int().nonnegative(),
|
|
681
|
+
totalViews: z13.number().int().nonnegative(),
|
|
682
|
+
versions: z13.array(versionViewStatsSchema)
|
|
650
683
|
});
|
|
651
684
|
|
|
652
685
|
// ../shared/src/versions.ts
|
|
653
|
-
import { z as
|
|
654
|
-
var versionSourceSchema =
|
|
655
|
-
agentName:
|
|
656
|
-
type:
|
|
686
|
+
import { z as z14 } from "zod";
|
|
687
|
+
var versionSourceSchema = z14.object({
|
|
688
|
+
agentName: z14.string().nullable(),
|
|
689
|
+
type: z14.string()
|
|
657
690
|
});
|
|
658
|
-
var versionChangesSchema =
|
|
659
|
-
added:
|
|
660
|
-
changed:
|
|
661
|
-
removed:
|
|
691
|
+
var versionChangesSchema = z14.object({
|
|
692
|
+
added: z14.array(z14.string()),
|
|
693
|
+
changed: z14.array(z14.string()),
|
|
694
|
+
removed: z14.array(z14.string())
|
|
662
695
|
});
|
|
663
|
-
var versionSummarySchema =
|
|
696
|
+
var versionSummarySchema = z14.object({
|
|
664
697
|
// Absent for the first version — there is no previous version to diff against.
|
|
665
698
|
changes: versionChangesSchema.nullable(),
|
|
666
|
-
createdAt:
|
|
667
|
-
entryUrl:
|
|
668
|
-
fileCount:
|
|
669
|
-
id:
|
|
670
|
-
isCurrent:
|
|
699
|
+
createdAt: z14.string(),
|
|
700
|
+
entryUrl: z14.string().url(),
|
|
701
|
+
fileCount: z14.number().int().nonnegative(),
|
|
702
|
+
id: z14.string(),
|
|
703
|
+
isCurrent: z14.boolean(),
|
|
704
|
+
// Author-supplied bullet-point changelog; null when the publish omitted it.
|
|
705
|
+
notes: z14.string().nullable(),
|
|
671
706
|
source: versionSourceSchema,
|
|
672
|
-
totalSizeBytes:
|
|
673
|
-
versionNumber:
|
|
707
|
+
totalSizeBytes: z14.number().int().nonnegative(),
|
|
708
|
+
versionNumber: z14.number().int().positive()
|
|
674
709
|
});
|
|
675
|
-
var versionListResponseSchema =
|
|
676
|
-
versions:
|
|
710
|
+
var versionListResponseSchema = z14.object({
|
|
711
|
+
versions: z14.array(versionSummarySchema)
|
|
677
712
|
});
|
|
678
713
|
|
|
679
714
|
// src/api.ts
|
|
@@ -729,6 +764,16 @@ function createApiClient(apiUrl2, publishToken) {
|
|
|
729
764
|
return {
|
|
730
765
|
// SPEC §6.19 — mark the agent as actively waiting for feedback.
|
|
731
766
|
// Authorized by the publish token this client was created with.
|
|
767
|
+
// SPEC §6.6.1 — mark an open thread acknowledged ("seen, working on
|
|
768
|
+
// it") without resolving it. Publish token or account key only —
|
|
769
|
+
// the server rejects guests.
|
|
770
|
+
async acknowledgeThread(threadId) {
|
|
771
|
+
return request(
|
|
772
|
+
`${base}/api/v1/comment-threads/${threadId}/acknowledge`,
|
|
773
|
+
{ body: "{}", headers, method: "POST" },
|
|
774
|
+
(d) => commentThreadSchema.parse(d)
|
|
775
|
+
);
|
|
776
|
+
},
|
|
732
777
|
async agentHeartbeat(artifactId) {
|
|
733
778
|
return request(
|
|
734
779
|
`${base}/api/v1/artifacts/${artifactId}/agent-presence`,
|
|
@@ -894,17 +939,17 @@ import {
|
|
|
894
939
|
writeFileSync as writeFileSync2
|
|
895
940
|
} from "fs";
|
|
896
941
|
import path2 from "path";
|
|
897
|
-
import { z as
|
|
942
|
+
import { z as z16 } from "zod";
|
|
898
943
|
|
|
899
944
|
// src/credentials.ts
|
|
900
945
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
901
946
|
import { homedir } from "os";
|
|
902
947
|
import path from "path";
|
|
903
|
-
import { z as
|
|
948
|
+
import { z as z15 } from "zod";
|
|
904
949
|
var DEFAULT_API_URL = "https://artifact.cafe";
|
|
905
|
-
var credentialsSchema =
|
|
906
|
-
keys:
|
|
907
|
-
version:
|
|
950
|
+
var credentialsSchema = z15.object({
|
|
951
|
+
keys: z15.record(z15.string(), z15.string()),
|
|
952
|
+
version: z15.literal(1)
|
|
908
953
|
});
|
|
909
954
|
function credentialsPath() {
|
|
910
955
|
return path.join(homedir(), ".artifactcafe", "credentials");
|
|
@@ -954,24 +999,24 @@ function resolveApiKey(apiUrl2, flag) {
|
|
|
954
999
|
}
|
|
955
1000
|
|
|
956
1001
|
// src/config.ts
|
|
957
|
-
var configSchema =
|
|
958
|
-
apiUrl:
|
|
959
|
-
artifactId:
|
|
960
|
-
folder:
|
|
961
|
-
folderId:
|
|
1002
|
+
var configSchema = z16.object({
|
|
1003
|
+
apiUrl: z16.string(),
|
|
1004
|
+
artifactId: z16.string(),
|
|
1005
|
+
folder: z16.string().optional(),
|
|
1006
|
+
folderId: z16.string().optional(),
|
|
962
1007
|
// Optional: a folder linked by `link` to an artifact you own carries no
|
|
963
1008
|
// token — owner actions authorize via your stored login instead. A first
|
|
964
1009
|
// publish still writes the anonymous-mode token here.
|
|
965
|
-
publishToken:
|
|
966
|
-
slug:
|
|
967
|
-
url:
|
|
968
|
-
workspace:
|
|
969
|
-
workspaceId:
|
|
970
|
-
workspaceKind:
|
|
971
|
-
});
|
|
972
|
-
var projectConfigSchema =
|
|
973
|
-
folder:
|
|
974
|
-
workspace:
|
|
1010
|
+
publishToken: z16.string().optional(),
|
|
1011
|
+
slug: z16.string(),
|
|
1012
|
+
url: z16.string(),
|
|
1013
|
+
workspace: z16.string().optional(),
|
|
1014
|
+
workspaceId: z16.string().optional(),
|
|
1015
|
+
workspaceKind: z16.enum(["personal", "workspace"]).optional()
|
|
1016
|
+
});
|
|
1017
|
+
var projectConfigSchema = z16.object({
|
|
1018
|
+
folder: z16.string().trim().min(1).optional(),
|
|
1019
|
+
workspace: z16.string().trim().min(1)
|
|
975
1020
|
}).strict();
|
|
976
1021
|
var CONFIG_DIR = ".artifactcafe";
|
|
977
1022
|
var CONFIG_FILE = "config.json";
|
|
@@ -1007,7 +1052,7 @@ function readProjectConfig(dir) {
|
|
|
1007
1052
|
JSON.parse(readFileSync2(file, "utf8"))
|
|
1008
1053
|
);
|
|
1009
1054
|
} catch (error) {
|
|
1010
|
-
const message = error instanceof
|
|
1055
|
+
const message = error instanceof z16.ZodError ? error.issues[0]?.message ?? "invalid project target" : "invalid JSON";
|
|
1011
1056
|
throw new Error(`Invalid ${file}: ${message}.`);
|
|
1012
1057
|
}
|
|
1013
1058
|
}
|
|
@@ -1356,8 +1401,14 @@ function printThread(t) {
|
|
|
1356
1401
|
const marker = t.status === "resolved" ? "\u2713" : "\u25CF";
|
|
1357
1402
|
const date = t.createdAt.slice(0, 10);
|
|
1358
1403
|
const edited = t.editedAt && !t.deleted ? " \xB7 edited" : "";
|
|
1404
|
+
let state = "";
|
|
1405
|
+
if (t.status === "resolved" && t.resolvedBy) {
|
|
1406
|
+
state = ` \xB7 resolved by ${t.resolvedBy.displayName}`;
|
|
1407
|
+
} else if (t.status === "open" && t.acknowledgedAt) {
|
|
1408
|
+
state = " \xB7 acknowledged";
|
|
1409
|
+
}
|
|
1359
1410
|
console.log(
|
|
1360
|
-
`${marker} ${t.author} \xB7 v${t.versionNumber} \xB7 ${date} \xB7 ${t.id}${edited}`
|
|
1411
|
+
`${marker} ${t.author} \xB7 v${t.versionNumber} \xB7 ${date} \xB7 ${t.id}${edited}${state}`
|
|
1361
1412
|
);
|
|
1362
1413
|
if (t.anchor.type === "text") {
|
|
1363
1414
|
console.log(` \u21B3 "${t.anchor.quote}"`);
|
|
@@ -1558,6 +1609,9 @@ async function publish(opts) {
|
|
|
1558
1609
|
entryPath,
|
|
1559
1610
|
files: files.map(({ absPath: _absPath, ...manifest }) => manifest),
|
|
1560
1611
|
...placement.folderId ? { folderId: placement.folderId } : {},
|
|
1612
|
+
// Agents often pass a double-quoted string where "\n" is a literal
|
|
1613
|
+
// backslash-n; turn those back into real newlines so bullets survive.
|
|
1614
|
+
...opts.notes?.trim() ? { notes: opts.notes.replace(/\\n/g, "\n").trim() } : {},
|
|
1561
1615
|
source: {
|
|
1562
1616
|
agent: process.env.ARTIFACT_CAFE_AGENT,
|
|
1563
1617
|
runId: process.env.ARTIFACT_CAFE_RUN_ID,
|
|
@@ -2442,10 +2496,29 @@ async function changeThreadStatus(opts) {
|
|
|
2442
2496
|
artifact: opts.artifact
|
|
2443
2497
|
});
|
|
2444
2498
|
const client = createApiClient(target.apiUrl, target.credential);
|
|
2445
|
-
const
|
|
2499
|
+
const call = {
|
|
2500
|
+
ack: () => client.acknowledgeThread(threadId),
|
|
2501
|
+
reopen: () => client.reopenThread(threadId),
|
|
2502
|
+
resolve: () => client.resolveThread(threadId)
|
|
2503
|
+
}[opts.action];
|
|
2504
|
+
const thread = await call();
|
|
2446
2505
|
if (opts.json) {
|
|
2447
2506
|
console.log(
|
|
2448
|
-
JSON.stringify(
|
|
2507
|
+
JSON.stringify(
|
|
2508
|
+
{
|
|
2509
|
+
acknowledgedAt: thread.acknowledgedAt,
|
|
2510
|
+
id: thread.id,
|
|
2511
|
+
status: thread.status
|
|
2512
|
+
},
|
|
2513
|
+
null,
|
|
2514
|
+
2
|
|
2515
|
+
)
|
|
2516
|
+
);
|
|
2517
|
+
return;
|
|
2518
|
+
}
|
|
2519
|
+
if (opts.action === "ack") {
|
|
2520
|
+
console.log(
|
|
2521
|
+
`\u2713 Acknowledged ${thread.id} \u2014 reviewers now see it as being handled.`
|
|
2449
2522
|
);
|
|
2450
2523
|
return;
|
|
2451
2524
|
}
|
|
@@ -2458,18 +2531,18 @@ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as rea
|
|
|
2458
2531
|
import { createRequire } from "module";
|
|
2459
2532
|
import { homedir as homedir2 } from "os";
|
|
2460
2533
|
import path14 from "path";
|
|
2461
|
-
import { z as
|
|
2534
|
+
import { z as z17 } from "zod";
|
|
2462
2535
|
var REGISTRY_LATEST_URL = "https://registry.npmjs.org/artifact-cafe/latest";
|
|
2463
2536
|
var SKILL_SOURCE_URL = "https://raw.githubusercontent.com/Artifact-Cafe/skill/main/artifact-cafe/SKILL.md";
|
|
2464
2537
|
var SKILL_UPDATE_COMMAND = "npx skills add artifact-cafe/skill --skill artifact-cafe -g";
|
|
2465
2538
|
var CHECK_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2466
2539
|
var FETCH_TIMEOUT_MS = 2e3;
|
|
2467
2540
|
var SKILL_VERSION_PATTERN = /\*\*Skill version:\s*(\d+\.\d+\.\d+)\*\*/;
|
|
2468
|
-
var cacheSchema =
|
|
2469
|
-
checkedAt:
|
|
2470
|
-
cliLatest:
|
|
2471
|
-
skillLatest:
|
|
2472
|
-
version:
|
|
2541
|
+
var cacheSchema = z17.object({
|
|
2542
|
+
checkedAt: z17.number(),
|
|
2543
|
+
cliLatest: z17.string().nullable(),
|
|
2544
|
+
skillLatest: z17.string().nullable(),
|
|
2545
|
+
version: z17.literal(1)
|
|
2473
2546
|
});
|
|
2474
2547
|
function cliVersion() {
|
|
2475
2548
|
const pkg = createRequire(import.meta.url)("../package.json");
|
|
@@ -2524,7 +2597,7 @@ async function fetchText(url) {
|
|
|
2524
2597
|
}
|
|
2525
2598
|
async function fetchLatestVersions(previous) {
|
|
2526
2599
|
const [cli, skill] = await Promise.all([
|
|
2527
|
-
fetchJson(REGISTRY_LATEST_URL).then((body) =>
|
|
2600
|
+
fetchJson(REGISTRY_LATEST_URL).then((body) => z17.object({ version: z17.string() }).parse(body).version).catch(() => null),
|
|
2528
2601
|
fetchText(SKILL_SOURCE_URL).then((body) => SKILL_VERSION_PATTERN.exec(body)?.[1] ?? null).catch(() => null)
|
|
2529
2602
|
]);
|
|
2530
2603
|
return {
|
|
@@ -2637,6 +2710,20 @@ function printWorkspace(workspace) {
|
|
|
2637
2710
|
}
|
|
2638
2711
|
|
|
2639
2712
|
// src/index.ts
|
|
2713
|
+
function readNotesArg(argv) {
|
|
2714
|
+
for (let i = 0; i < argv.length; i++) {
|
|
2715
|
+
const token = argv[i];
|
|
2716
|
+
if (token === void 0) {
|
|
2717
|
+
continue;
|
|
2718
|
+
}
|
|
2719
|
+
if (token === "--notes") {
|
|
2720
|
+
return argv[i + 1];
|
|
2721
|
+
}
|
|
2722
|
+
if (token.startsWith("--notes=")) {
|
|
2723
|
+
return token.slice("--notes=".length);
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2640
2727
|
var publish2 = defineCommand({
|
|
2641
2728
|
args: {
|
|
2642
2729
|
"api-key": {
|
|
@@ -2659,6 +2746,10 @@ var publish2 = defineCommand({
|
|
|
2659
2746
|
},
|
|
2660
2747
|
json: { description: "Machine-readable output", type: "boolean" },
|
|
2661
2748
|
"no-open": { description: "Don't open the review URL", type: "boolean" },
|
|
2749
|
+
notes: {
|
|
2750
|
+
description: "Version notes \u2014 bullet-point changelog of what changed (newline-separated)",
|
|
2751
|
+
type: "string"
|
|
2752
|
+
},
|
|
2662
2753
|
password: {
|
|
2663
2754
|
description: "Password-protect the artifact (min 6 chars)",
|
|
2664
2755
|
type: "string"
|
|
@@ -2679,6 +2770,7 @@ var publish2 = defineCommand({
|
|
|
2679
2770
|
entry: args.entry,
|
|
2680
2771
|
folder: args.folder,
|
|
2681
2772
|
json: Boolean(args.json),
|
|
2773
|
+
notes: readNotesArg(process.argv.slice(2)),
|
|
2682
2774
|
open: !args["no-open"],
|
|
2683
2775
|
password: args.password,
|
|
2684
2776
|
title: args.title,
|
|
@@ -3046,7 +3138,11 @@ var threadStatusCommand = (action) => defineCommand({
|
|
|
3046
3138
|
}
|
|
3047
3139
|
},
|
|
3048
3140
|
meta: {
|
|
3049
|
-
description:
|
|
3141
|
+
description: {
|
|
3142
|
+
ack: "Mark a thread acknowledged (seen, working on it)",
|
|
3143
|
+
reopen: "Reopen a resolved comment thread",
|
|
3144
|
+
resolve: "Mark a comment thread resolved"
|
|
3145
|
+
}[action],
|
|
3050
3146
|
name: action
|
|
3051
3147
|
},
|
|
3052
3148
|
async run({ args }) {
|
|
@@ -3067,6 +3163,7 @@ var threadStatusCommand = (action) => defineCommand({
|
|
|
3067
3163
|
});
|
|
3068
3164
|
var resolve = threadStatusCommand("resolve");
|
|
3069
3165
|
var reopen = threadStatusCommand("reopen");
|
|
3166
|
+
var ack = threadStatusCommand("ack");
|
|
3070
3167
|
var reply = defineCommand({
|
|
3071
3168
|
args: {
|
|
3072
3169
|
"api-key": {
|
|
@@ -3333,6 +3430,7 @@ var main = defineCommand({
|
|
|
3333
3430
|
await showUsage(cmd);
|
|
3334
3431
|
},
|
|
3335
3432
|
subCommands: {
|
|
3433
|
+
ack,
|
|
3336
3434
|
comment: comment2,
|
|
3337
3435
|
comments: comments2,
|
|
3338
3436
|
dashboard,
|