@agimon-ai/po-artifact 0.0.0-alpha.1

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.
@@ -0,0 +1,561 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
+ key = keys[i];
15
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ //#endregion
27
+ let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
28
+ let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
29
+ let node_timers = require("node:timers");
30
+ let node_fs = require("node:fs");
31
+ let node_fs_promises = require("node:fs/promises");
32
+ node_fs_promises = __toESM(node_fs_promises, 1);
33
+ let node_path = require("node:path");
34
+ node_path = __toESM(node_path, 1);
35
+ let _agimon_ai_po_core_piSettings = require("@agimon-ai/po-core/piSettings");
36
+ let hono = require("hono");
37
+ //#region src/constants/artifacts.ts
38
+ const ARTIFACT_DIRECTORY = "doom-artifacts";
39
+ const ARTIFACT_REFRESH_MS = 2e3;
40
+ const ARTIFACT_CONTENT_TYPES = {
41
+ ".avif": "image/avif",
42
+ ".bmp": "image/bmp",
43
+ ".gif": "image/gif",
44
+ ".jpeg": "image/jpeg",
45
+ ".jpg": "image/jpeg",
46
+ ".png": "image/png",
47
+ ".svg": "image/svg+xml",
48
+ ".webp": "image/webp",
49
+ ".ico": "image/vnd.microsoft.icon",
50
+ ".mp3": "audio/mpeg",
51
+ ".wav": "audio/wav",
52
+ ".m4a": "audio/mp4",
53
+ ".ogg": "audio/ogg",
54
+ ".m4v": "video/mp4",
55
+ ".mov": "video/quicktime",
56
+ ".mp4": "video/mp4",
57
+ ".webm": "video/webm",
58
+ ".pdf": "application/pdf",
59
+ ".md": "text/markdown; charset=utf-8",
60
+ ".markdown": "text/markdown; charset=utf-8",
61
+ ".txt": "text/plain; charset=utf-8",
62
+ ".html": "text/html; charset=utf-8",
63
+ ".htm": "text/html; charset=utf-8"
64
+ };
65
+ //#endregion
66
+ //#region src/types/artifacts.ts
67
+ const artifactsChannelType = "artifacts";
68
+ //#endregion
69
+ //#region src/services/artifactFiles/index.ts
70
+ var ArtifactAccessError = class extends Error {
71
+ status;
72
+ constructor(message, status) {
73
+ super(message);
74
+ this.status = status;
75
+ }
76
+ };
77
+ function artifactRoot(sessionId, environment) {
78
+ if (!/^[a-zA-Z0-9_-]+$/u.test(sessionId)) throw new ArtifactAccessError("Invalid artifact session identity.", 400);
79
+ return node_path.default.join((0, _agimon_ai_po_core_piSettings.piAgentDirectory)(environment, environment.HOME), ARTIFACT_DIRECTORY, sessionId);
80
+ }
81
+ function inside(root, candidate) {
82
+ const relative = node_path.default.relative(root, candidate);
83
+ return relative !== ".." && !relative.startsWith(`..${node_path.default.sep}`) && !node_path.default.isAbsolute(relative);
84
+ }
85
+ function codeOf(error) {
86
+ return error instanceof Error && "code" in error ? String(error.code) : void 0;
87
+ }
88
+ /** The owned directories must not redirect artifact access through a symlink. */
89
+ async function checkedRoot(root) {
90
+ const base = node_path.default.dirname(root);
91
+ for (const directory of [base, root]) {
92
+ const stat = await node_fs_promises.default.lstat(directory);
93
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw new ArtifactAccessError("The artifact folder is unavailable.", 403);
94
+ }
95
+ const realBase = await node_fs_promises.default.realpath(base);
96
+ const realRoot = await node_fs_promises.default.realpath(root);
97
+ if (!inside(realBase, realRoot)) throw new ArtifactAccessError("The artifact folder is outside its storage directory.", 403);
98
+ return realRoot;
99
+ }
100
+ async function ensureArtifactRoot(root) {
101
+ await node_fs_promises.default.mkdir(node_path.default.dirname(root), {
102
+ recursive: true,
103
+ mode: 448
104
+ });
105
+ await node_fs_promises.default.mkdir(root, {
106
+ recursive: true,
107
+ mode: 448
108
+ });
109
+ await checkedRoot(root);
110
+ }
111
+ function artifactMimeType(relativePath) {
112
+ return ARTIFACT_CONTENT_TYPES[node_path.default.extname(relativePath).toLowerCase()] ?? "application/octet-stream";
113
+ }
114
+ /** Open without following mutable ancestors. Node exposes no portable openat API. */
115
+ async function openContained(root, segments) {
116
+ if (process.platform === "darwin") return node_fs_promises.default.open(node_path.default.join(root, ...segments), node_fs.constants.O_RDONLY | node_fs.constants.O_NONBLOCK | 536870912);
117
+ if (process.platform !== "linux") throw new ArtifactAccessError("Secure artifact reads require macOS or Linux.", 403);
118
+ const flags = node_fs.constants.O_RDONLY | node_fs.constants.O_DIRECTORY | node_fs.constants.O_NOFOLLOW;
119
+ let directory = await node_fs_promises.default.open(node_path.default.dirname(root), flags);
120
+ try {
121
+ for (const segment of [node_path.default.basename(root), ...segments.slice(0, -1)]) {
122
+ const child = await node_fs_promises.default.open(`/proc/self/fd/${directory.fd}/${segment}`, flags);
123
+ await directory.close();
124
+ directory = child;
125
+ }
126
+ return await node_fs_promises.default.open(`/proc/self/fd/${directory.fd}/${segments.at(-1)}`, node_fs.constants.O_RDONLY | node_fs.constants.O_NOFOLLOW | node_fs.constants.O_NONBLOCK);
127
+ } finally {
128
+ await directory.close();
129
+ }
130
+ }
131
+ /** One guarded open shared by metadata, text and byte reads. The caller closes the handle. */
132
+ async function openArtifact(root, requested) {
133
+ if (!requested || requested.includes("\0") || requested.includes("\\") || node_path.default.isAbsolute(requested) || requested.split("/").some((part) => part === ".." || part === "." || part === "")) throw new ArtifactAccessError("Invalid artifact path.", 400);
134
+ try {
135
+ const realRoot = await checkedRoot(root);
136
+ const candidate = node_path.default.resolve(realRoot, requested);
137
+ if (!inside(realRoot, candidate)) throw new ArtifactAccessError("The artifact is outside this session folder.", 403);
138
+ let current = realRoot;
139
+ const segments = requested.split("/");
140
+ for (let index = 0; index < segments.length; index += 1) {
141
+ current = node_path.default.join(current, segments[index]);
142
+ const stat = await node_fs_promises.default.lstat(current);
143
+ if (stat.isSymbolicLink()) throw new ArtifactAccessError("Artifact symlinks cannot be read.", 403);
144
+ if (index < segments.length - 1 ? !stat.isDirectory() : !stat.isFile()) throw new ArtifactAccessError("The artifact is not a regular file.", 404);
145
+ }
146
+ const real = await node_fs_promises.default.realpath(candidate);
147
+ if (!inside(realRoot, real)) throw new ArtifactAccessError("The artifact is outside this session folder.", 403);
148
+ const expected = await node_fs_promises.default.lstat(real);
149
+ const handle = await openContained(realRoot, segments);
150
+ try {
151
+ const stat = await handle.stat();
152
+ if (!stat.isFile() || stat.dev !== expected.dev || stat.ino !== expected.ino) throw new ArtifactAccessError("The artifact changed while it was opened. Try again.", 403);
153
+ return {
154
+ handle,
155
+ stat,
156
+ path: requested,
157
+ mimeType: artifactMimeType(requested)
158
+ };
159
+ } catch (error) {
160
+ await handle.close();
161
+ throw error;
162
+ }
163
+ } catch (error) {
164
+ if (error instanceof ArtifactAccessError) throw error;
165
+ if (codeOf(error) === "ENOENT" || codeOf(error) === "ENOTDIR") throw new ArtifactAccessError("The artifact no longer exists.", 404);
166
+ if (codeOf(error) === "EACCES" || codeOf(error) === "EPERM" || codeOf(error) === "ELOOP") throw new ArtifactAccessError("The artifact cannot be read.", 403);
167
+ throw error;
168
+ }
169
+ }
170
+ /** Bound allocation and read length even when the file grows after its metadata was read. */
171
+ async function readArtifactBytes(handle, size, offset = 0) {
172
+ const bytes = new Uint8Array(size);
173
+ let read = 0;
174
+ while (read < size) {
175
+ const result = await handle.read(bytes, read, size - read, offset + read);
176
+ if (result.bytesRead === 0) break;
177
+ read += result.bytesRead;
178
+ }
179
+ return bytes.subarray(0, read);
180
+ }
181
+ async function listArtifacts(root) {
182
+ const items = [];
183
+ try {
184
+ const realRoot = await checkedRoot(root);
185
+ const visit = async (directory) => {
186
+ for (const entry of await node_fs_promises.default.readdir(directory, { withFileTypes: true })) {
187
+ const location = node_path.default.join(directory, entry.name);
188
+ if (entry.isDirectory()) {
189
+ const stat = await node_fs_promises.default.lstat(location);
190
+ if (!stat.isDirectory() || stat.isSymbolicLink()) continue;
191
+ const real = await node_fs_promises.default.realpath(location);
192
+ if (inside(realRoot, real)) await visit(real);
193
+ } else if (entry.isFile()) {
194
+ const relativePath = node_path.default.relative(realRoot, location).split(node_path.default.sep).join("/");
195
+ try {
196
+ const file = await openArtifact(root, relativePath);
197
+ try {
198
+ items.push({
199
+ path: relativePath,
200
+ name: entry.name,
201
+ size: file.stat.size,
202
+ modifiedAt: file.stat.mtimeMs
203
+ });
204
+ } finally {
205
+ await file.handle.close();
206
+ }
207
+ } catch (error) {
208
+ if (error instanceof ArtifactAccessError && (error.status === 404 || error.status === 403)) continue;
209
+ throw error;
210
+ }
211
+ }
212
+ }
213
+ };
214
+ await visit(realRoot);
215
+ items.sort((left, right) => right.modifiedAt - left.modifiedAt || (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));
216
+ return { items };
217
+ } catch (error) {
218
+ if (codeOf(error) === "ENOENT") return { items: [] };
219
+ return {
220
+ items: [],
221
+ error: error instanceof Error ? error.message : "The artifact folder could not be read."
222
+ };
223
+ }
224
+ }
225
+ //#endregion
226
+ //#region src/services/artifactSession/index.ts
227
+ function createArtifactSession({ host }) {
228
+ const environment = Object.freeze({ ...host.context.environment });
229
+ let active;
230
+ let timer;
231
+ let pending;
232
+ let closed = false;
233
+ const refresh = () => {
234
+ if (pending) return pending;
235
+ const runtime = active;
236
+ if (!runtime || closed) return Promise.resolve();
237
+ pending = (async () => {
238
+ const snapshot = await listArtifacts(runtime.root);
239
+ if (closed || active !== runtime) return;
240
+ const fingerprint = JSON.stringify(snapshot);
241
+ if (fingerprint === runtime.fingerprint) return;
242
+ runtime.fingerprint = fingerprint;
243
+ host.context.directEvents?.publish(artifactsChannelType, runtime.context.sessionId, snapshot);
244
+ })().finally(() => {
245
+ pending = void 0;
246
+ });
247
+ return pending;
248
+ };
249
+ const schedule = () => {
250
+ if (!active || closed) return;
251
+ timer = (0, node_timers.setTimeout)(() => {
252
+ timer = void 0;
253
+ refresh().finally(schedule);
254
+ }, ARTIFACT_REFRESH_MS);
255
+ };
256
+ const stop = async () => {
257
+ active = void 0;
258
+ if (timer !== void 0) (0, node_timers.clearTimeout)(timer);
259
+ timer = void 0;
260
+ await pending;
261
+ };
262
+ return {
263
+ activities: [{
264
+ name: "artifacts",
265
+ async start(context) {
266
+ if (closed) throw new Error("Artifact session is closed.");
267
+ await stop();
268
+ const root = artifactRoot(context.sessionId, environment);
269
+ await ensureArtifactRoot(root);
270
+ if (closed) throw new Error("Artifact session is closed.");
271
+ active = {
272
+ context,
273
+ root
274
+ };
275
+ await refresh();
276
+ schedule();
277
+ return stop;
278
+ }
279
+ }],
280
+ beforeAgentStart: {
281
+ event: "before_agent_start",
282
+ async handle(event, context) {
283
+ const root = artifactRoot(context.sessionId, environment);
284
+ await ensureArtifactRoot(root);
285
+ const systemPrompt = typeof event.systemPrompt === "string" ? event.systemPrompt : "";
286
+ const declaration = `Session artifact folder: ${root}`;
287
+ if (systemPrompt.includes(declaration)) return { systemPrompt };
288
+ return { systemPrompt: `${systemPrompt}\n\n${declaration}\nSave user-designated artifacts and important deliverable documents in this folder, using descriptive filenames. Keep ordinary repository source edits in their existing locations. Do not move existing documents or overwrite artifacts without the user's intent. This folder belongs only to the current session.`.trim() };
289
+ }
290
+ },
291
+ toolExecutionEnd: {
292
+ event: "tool_execution_end",
293
+ handle(_event, context) {
294
+ return active?.context.sessionId === context.sessionId ? refresh() : void 0;
295
+ }
296
+ },
297
+ onDispose: async () => {
298
+ closed = true;
299
+ await stop();
300
+ }
301
+ };
302
+ }
303
+ //#endregion
304
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts
305
+ const createArtifactServerRoot = (context) => {
306
+ const runtime = createArtifactSession(context);
307
+ return {
308
+ value: runtime,
309
+ activities: runtime.activities,
310
+ onDispose: runtime.onDispose
311
+ };
312
+ };
313
+ //#endregion
314
+ //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
315
+ var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)(createArtifactServerRoot);
316
+ //#endregion
317
+ //#region src/services/artifactChannel/index.ts
318
+ function snapshotOf(value) {
319
+ if (typeof value !== "object" || value === null) return false;
320
+ const snapshot = value;
321
+ return Array.isArray(snapshot.items) && (snapshot.error === void 0 || typeof snapshot.error === "string") && snapshot.items.every((item) => typeof item === "object" && item !== null && typeof item.path === "string" && typeof item.name === "string" && typeof item.size === "number" && Number.isFinite(item.size) && typeof item.modifiedAt === "number" && Number.isFinite(item.modifiedAt));
322
+ }
323
+ function createArtifactsChannel() {
324
+ return {
325
+ frameType: artifactsChannelType,
326
+ start(host) {
327
+ const sessions = /* @__PURE__ */ new Map();
328
+ return {
329
+ payloadFor(scope) {
330
+ return sessions.get(scope.sessionId)?.snapshot;
331
+ },
332
+ sessionAdded(scope) {
333
+ sessions.get(scope.sessionId)?.unsubscribe();
334
+ const state = { unsubscribe: () => void 0 };
335
+ sessions.set(scope.sessionId, state);
336
+ state.unsubscribe = host.directEvents.subscribe(artifactsChannelType, scope.sessionId, (snapshot) => {
337
+ if (!snapshotOf(snapshot) || sessions.get(scope.sessionId) !== state) return;
338
+ state.snapshot = snapshot;
339
+ host.publish(scope.sessionId, snapshot);
340
+ }, { replayLatest: true });
341
+ (async () => {
342
+ let snapshot;
343
+ try {
344
+ snapshot = await listArtifacts(artifactRoot(scope.sessionId, scope.environment ?? {}));
345
+ } catch (error) {
346
+ snapshot = {
347
+ items: [],
348
+ error: error instanceof Error ? error.message : "The artifact folder could not be read."
349
+ };
350
+ }
351
+ if (sessions.get(scope.sessionId) !== state || state.snapshot !== void 0) return;
352
+ state.snapshot = snapshot;
353
+ host.publish(scope.sessionId, snapshot);
354
+ })();
355
+ },
356
+ sessionRemoved(sessionId) {
357
+ sessions.get(sessionId)?.unsubscribe();
358
+ sessions.delete(sessionId);
359
+ },
360
+ close() {
361
+ for (const state of sessions.values()) state.unsubscribe();
362
+ sessions.clear();
363
+ }
364
+ };
365
+ }
366
+ };
367
+ }
368
+ //#endregion
369
+ //#region src/extensions/(backend)/channel/artifacts.server.ts
370
+ var artifacts_server_default = (0, _agimon_ai_po_core_extensionFile.defineChannel)(createArtifactsChannel);
371
+ //#endregion
372
+ //#region src/types/apiRoutes.ts
373
+ const routes = {
374
+ list: {
375
+ method: "GET",
376
+ path: "/",
377
+ response: void 0
378
+ },
379
+ preview: {
380
+ method: "GET",
381
+ path: "/preview",
382
+ query: ["path"],
383
+ response: void 0
384
+ },
385
+ content: {
386
+ method: "GET",
387
+ path: "/content",
388
+ query: ["path"],
389
+ raw: true
390
+ }
391
+ };
392
+ //#endregion
393
+ //#region src/services/artifactsApi/index.ts
394
+ function createArtifactsApi(root) {
395
+ const app = new hono.Hono();
396
+ app.onError((error, context) => context.json({ error: error instanceof ArtifactAccessError ? error.message : "The artifact could not be read." }, error instanceof ArtifactAccessError ? error.status : 500));
397
+ app.get(routes.list.path, async (context) => {
398
+ const snapshot = await listArtifacts(root);
399
+ return context.json(snapshot, snapshot.error === void 0 ? 200 : 500);
400
+ });
401
+ app.get(routes.preview.path, async (context) => {
402
+ const file = await openArtifact(root, context.req.query("path"));
403
+ try {
404
+ const preview = {
405
+ path: file.path,
406
+ content: "",
407
+ mimeType: file.mimeType
408
+ };
409
+ if (file.stat.size > 1048576) return context.json({
410
+ ...preview,
411
+ unavailable: true,
412
+ reason: "This artifact is too large for a text preview."
413
+ });
414
+ const bytes = await readArtifactBytes(file.handle, 1048577);
415
+ if (bytes.byteLength > 1048576) return context.json({
416
+ ...preview,
417
+ unavailable: true,
418
+ reason: "This artifact is too large for a text preview."
419
+ });
420
+ if (bytes.subarray(0, 8192).includes(0)) return context.json({
421
+ ...preview,
422
+ unavailable: true,
423
+ reason: "This artifact is binary."
424
+ });
425
+ return context.json({
426
+ ...preview,
427
+ content: new TextDecoder().decode(bytes)
428
+ });
429
+ } finally {
430
+ await file.handle.close();
431
+ }
432
+ });
433
+ app.get(routes.content.path, async (context) => {
434
+ const file = await openArtifact(root, context.req.query("path"));
435
+ try {
436
+ if (file.stat.size > 26214400) throw new ArtifactAccessError("This artifact is too large to download.", 413);
437
+ const version = `"${file.stat.dev}-${file.stat.ino}-${file.stat.size}-${file.stat.mtimeMs}-${file.stat.ctimeMs}"`;
438
+ const name = encodeURIComponent(node_path.default.basename(file.path)).replace(/[!'()*]/gu, (value) => `%${value.charCodeAt(0).toString(16).toUpperCase()}`);
439
+ const headers = new Headers({
440
+ "content-type": file.mimeType,
441
+ "content-disposition": `attachment; filename*=UTF-8''${name}`,
442
+ "cache-control": "no-store",
443
+ "x-content-type-options": "nosniff",
444
+ "content-security-policy": "default-src 'none'; sandbox",
445
+ "accept-ranges": "bytes",
446
+ etag: version
447
+ });
448
+ const expectedVersion = context.req.header("if-match");
449
+ if (expectedVersion !== void 0 && expectedVersion !== version) return new Response(null, {
450
+ status: 412,
451
+ headers
452
+ });
453
+ let start = 0;
454
+ let end = file.stat.size - 1;
455
+ const range = context.req.header("range");
456
+ if (range !== void 0) {
457
+ const match = /^bytes=(\d*)-(\d*)$/u.exec(range);
458
+ if (!match || !match[1] && !match[2] || file.stat.size === 0 || [match[1], match[2]].some((value) => value !== "" && !Number.isSafeInteger(Number(value)))) {
459
+ headers.set("content-range", `bytes */${file.stat.size}`);
460
+ return new Response(null, {
461
+ status: 416,
462
+ headers
463
+ });
464
+ }
465
+ if (match[1] === "") {
466
+ const suffix = Number(match[2]);
467
+ start = suffix > 0 ? Math.max(0, file.stat.size - suffix) : file.stat.size;
468
+ } else {
469
+ start = Number(match[1]);
470
+ end = match[2] === "" ? end : Math.min(end, Number(match[2]));
471
+ }
472
+ if (start > end || start >= file.stat.size) {
473
+ headers.set("content-range", `bytes */${file.stat.size}`);
474
+ return new Response(null, {
475
+ status: 416,
476
+ headers
477
+ });
478
+ }
479
+ headers.set("content-range", `bytes ${start}-${end}/${file.stat.size}`);
480
+ }
481
+ const bytes = await readArtifactBytes(file.handle, Math.max(0, end - start + 1), start);
482
+ const after = await file.handle.stat();
483
+ if (after.size !== file.stat.size || after.mtimeMs !== file.stat.mtimeMs || after.ctimeMs !== file.stat.ctimeMs) return new Response(null, {
484
+ status: 412,
485
+ headers
486
+ });
487
+ headers.set("content-length", String(bytes.byteLength));
488
+ return new Response(bytes, {
489
+ status: range === void 0 ? 200 : 206,
490
+ headers
491
+ });
492
+ } finally {
493
+ await file.handle.close();
494
+ }
495
+ });
496
+ return app;
497
+ }
498
+ //#endregion
499
+ //#region src/extensions/workspaces/sessions/(backend)/api/artifacts/route.server.ts
500
+ var route_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoute)({
501
+ basePath: "artifacts",
502
+ start(context) {
503
+ if (!context.sessionId) throw new Error("Artifacts requires a session identity.");
504
+ const app = createArtifactsApi(artifactRoot(context.sessionId, context.environment ?? {}));
505
+ return {
506
+ fetch: (request) => app.fetch(request),
507
+ close: () => void 0
508
+ };
509
+ }
510
+ });
511
+ //#endregion
512
+ //#region src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.server.ts
513
+ var before_agent_start_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.beforeAgentStart);
514
+ //#endregion
515
+ //#region src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.ts
516
+ var tool_execution_end_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.toolExecutionEnd);
517
+ //#endregion
518
+ //#region generated/server.ts
519
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
520
+ const via = (identity, value) => value === void 0 ? void 0 : {
521
+ ...identity,
522
+ ...value
523
+ };
524
+ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
525
+ name: "@agimon-ai/po-artifact",
526
+ providerOverrides: (0, _agimon_ai_po_core_serverFacet.composeServerProviderOverrides)(root_server_default),
527
+ global: () => ({ get channels() {
528
+ return [() => via({ frameType: "artifacts" }, artifacts_server_default())];
529
+ } }),
530
+ workspace: () => ({ get channels() {
531
+ return [() => via({ frameType: "artifacts" }, artifacts_server_default())];
532
+ } }),
533
+ session: async (context) => {
534
+ const scopeSession = await root_server_default(context);
535
+ const contextSession = {
536
+ ...context,
537
+ root: scopeSession.value
538
+ };
539
+ return {
540
+ ...(0, _agimon_ai_po_core_extensionFile.composeRootHooks)(scopeSession),
541
+ get api() {
542
+ return [at(route_server_default, contextSession)];
543
+ },
544
+ get channels() {
545
+ return [() => via({ frameType: "artifacts" }, artifacts_server_default())];
546
+ },
547
+ get hooks() {
548
+ return [via({ event: "before_agent_start" }, at(before_agent_start_server_default, contextSession)), via({ event: "tool_execution_end" }, at(tool_execution_end_server_default, contextSession))];
549
+ },
550
+ services: [...scopeSession.services ?? []],
551
+ get activities() {
552
+ return [...scopeSession.activities ?? []];
553
+ }
554
+ };
555
+ }
556
+ });
557
+ //#endregion
558
+ exports.default = facet;
559
+ exports.facet = facet;
560
+
561
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.cjs","names":["path","piAgentDirectory","fs","constants","setTimeout","defineRoot","defineChannel","Hono","path","defineRoute","defineHook","defineHook","defineServerPlugin","composeServerProviderOverrides","rootSession","channelArtifacts","composeRootHooks","apiRoute","hookBeforeAgentStart","hookToolExecutionEnd"],"sources":["../../src/constants/artifacts.ts","../../src/types/artifacts.ts","../../src/services/artifactFiles/index.ts","../../src/services/artifactSession/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/artifactChannel/index.ts","../../src/extensions/(backend)/channel/artifacts.server.ts","../../src/types/apiRoutes.ts","../../src/services/artifactsApi/index.ts","../../src/extensions/workspaces/sessions/(backend)/api/artifacts/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.ts","../../generated/server.ts"],"sourcesContent":["export const ARTIFACT_DIRECTORY = 'doom-artifacts';\nexport const MAX_PREVIEW_BYTES = 1024 * 1024;\nexport const MAX_CONTENT_BYTES = 25 * 1024 * 1024;\nexport const ARTIFACT_REFRESH_MS = 2000;\n\nexport const ARTIFACT_CONTENT_TYPES: Readonly<Record<string, string>> = {\n '.avif': 'image/avif',\n '.bmp': 'image/bmp',\n '.gif': 'image/gif',\n '.jpeg': 'image/jpeg',\n '.jpg': 'image/jpeg',\n '.png': 'image/png',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.ico': 'image/vnd.microsoft.icon',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.m4a': 'audio/mp4',\n '.ogg': 'audio/ogg',\n '.m4v': 'video/mp4',\n '.mov': 'video/quicktime',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.pdf': 'application/pdf',\n '.md': 'text/markdown; charset=utf-8',\n '.markdown': 'text/markdown; charset=utf-8',\n '.txt': 'text/plain; charset=utf-8',\n '.html': 'text/html; charset=utf-8',\n '.htm': 'text/html; charset=utf-8',\n};\n","export interface ArtifactItem {\n /** Relative to the current session's artifact directory. */\n path: string;\n name: string;\n size: number;\n modifiedAt: number;\n}\n\nexport interface ArtifactSnapshot {\n items: ArtifactItem[];\n error?: string;\n}\n\nexport interface ArtifactPreview {\n path: string;\n content: string;\n mimeType: string;\n unavailable?: boolean;\n reason?: string;\n}\n\nexport const artifactsChannelType = 'artifacts';\n","import { constants } from 'node:fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { piAgentDirectory } from '@agimon-ai/po-core/piSettings';\n\nimport { ARTIFACT_CONTENT_TYPES, ARTIFACT_DIRECTORY } from '../../constants/artifacts';\nimport type { ArtifactItem, ArtifactSnapshot } from '../../types/artifacts';\n\nexport class ArtifactAccessError extends Error {\n constructor(\n message: string,\n readonly status: 400 | 403 | 404 | 413,\n ) {\n super(message);\n }\n}\n\nexport function artifactRoot(sessionId: string, environment: Readonly<Record<string, string | undefined>>): string {\n if (!/^[a-zA-Z0-9_-]+$/u.test(sessionId)) throw new ArtifactAccessError('Invalid artifact session identity.', 400);\n return path.join(piAgentDirectory(environment, environment.HOME), ARTIFACT_DIRECTORY, sessionId);\n}\n\nfunction inside(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);\n}\n\nfunction codeOf(error: unknown): string | undefined {\n return error instanceof Error && 'code' in error ? String(error.code) : undefined;\n}\n\n/** The owned directories must not redirect artifact access through a symlink. */\nasync function checkedRoot(root: string): Promise<string> {\n const base = path.dirname(root);\n for (const directory of [base, root]) {\n const stat = await fs.lstat(directory);\n if (!stat.isDirectory() || stat.isSymbolicLink())\n throw new ArtifactAccessError('The artifact folder is unavailable.', 403);\n }\n const realBase = await fs.realpath(base);\n const realRoot = await fs.realpath(root);\n if (!inside(realBase, realRoot))\n throw new ArtifactAccessError('The artifact folder is outside its storage directory.', 403);\n return realRoot;\n}\n\nexport async function ensureArtifactRoot(root: string): Promise<void> {\n await fs.mkdir(path.dirname(root), { recursive: true, mode: 0o700 });\n await fs.mkdir(root, { recursive: true, mode: 0o700 });\n await checkedRoot(root);\n}\n\nexport function artifactMimeType(relativePath: string): string {\n return ARTIFACT_CONTENT_TYPES[path.extname(relativePath).toLowerCase()] ?? 'application/octet-stream';\n}\n\n/** Open without following mutable ancestors. Node exposes no portable openat API. */\nasync function openContained(root: string, segments: string[]): Promise<fs.FileHandle> {\n if (process.platform === 'darwin') {\n // Darwin O_NOFOLLOW_ANY checks every component atomically. Do not combine it with O_NOFOLLOW.\n return fs.open(path.join(root, ...segments), constants.O_RDONLY | constants.O_NONBLOCK | 0x20000000);\n }\n if (process.platform !== 'linux') throw new ArtifactAccessError('Secure artifact reads require macOS or Linux.', 403);\n const flags = constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW;\n let directory = await fs.open(path.dirname(root), flags);\n try {\n for (const segment of [path.basename(root), ...segments.slice(0, -1)]) {\n const child = await fs.open(`/proc/self/fd/${directory.fd}/${segment}`, flags);\n await directory.close();\n directory = child;\n }\n return await fs.open(\n `/proc/self/fd/${directory.fd}/${segments.at(-1)!}`,\n constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,\n );\n } finally {\n await directory.close();\n }\n}\n\n/** One guarded open shared by metadata, text and byte reads. The caller closes the handle. */\nexport async function openArtifact(root: string, requested: string | undefined) {\n if (\n !requested ||\n requested.includes('\\0') ||\n requested.includes('\\\\') ||\n path.isAbsolute(requested) ||\n requested.split('/').some((part) => part === '..' || part === '.' || part === '')\n )\n throw new ArtifactAccessError('Invalid artifact path.', 400);\n try {\n const realRoot = await checkedRoot(root);\n const candidate = path.resolve(realRoot, requested);\n if (!inside(realRoot, candidate))\n throw new ArtifactAccessError('The artifact is outside this session folder.', 403);\n let current = realRoot;\n const segments = requested.split('/');\n for (let index = 0; index < segments.length; index += 1) {\n current = path.join(current, segments[index]!);\n const stat = await fs.lstat(current);\n if (stat.isSymbolicLink()) throw new ArtifactAccessError('Artifact symlinks cannot be read.', 403);\n if (index < segments.length - 1 ? !stat.isDirectory() : !stat.isFile())\n throw new ArtifactAccessError('The artifact is not a regular file.', 404);\n }\n const real = await fs.realpath(candidate);\n if (!inside(realRoot, real)) throw new ArtifactAccessError('The artifact is outside this session folder.', 403);\n const expected = await fs.lstat(real);\n const handle = await openContained(realRoot, segments);\n try {\n const stat = await handle.stat();\n if (!stat.isFile() || stat.dev !== expected.dev || stat.ino !== expected.ino)\n throw new ArtifactAccessError('The artifact changed while it was opened. Try again.', 403);\n return { handle, stat, path: requested, mimeType: artifactMimeType(requested) };\n } catch (error) {\n await handle.close();\n throw error;\n }\n } catch (error) {\n if (error instanceof ArtifactAccessError) throw error;\n if (codeOf(error) === 'ENOENT' || codeOf(error) === 'ENOTDIR')\n throw new ArtifactAccessError('The artifact no longer exists.', 404);\n if (codeOf(error) === 'EACCES' || codeOf(error) === 'EPERM' || codeOf(error) === 'ELOOP')\n throw new ArtifactAccessError('The artifact cannot be read.', 403);\n throw error;\n }\n}\n\n/** Bound allocation and read length even when the file grows after its metadata was read. */\nexport async function readArtifactBytes(handle: fs.FileHandle, size: number, offset = 0): Promise<Uint8Array> {\n const bytes = new Uint8Array(size);\n let read = 0;\n while (read < size) {\n const result = await handle.read(bytes, read, size - read, offset + read);\n if (result.bytesRead === 0) break;\n read += result.bytesRead;\n }\n return bytes.subarray(0, read);\n}\n\nexport async function listArtifacts(root: string): Promise<ArtifactSnapshot> {\n const items: ArtifactItem[] = [];\n try {\n const realRoot = await checkedRoot(root);\n const visit = async (directory: string): Promise<void> => {\n for (const entry of await fs.readdir(directory, { withFileTypes: true })) {\n const location = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n // Recheck each directory rather than trusting a readdir entry across a rename.\n const stat = await fs.lstat(location);\n if (!stat.isDirectory() || stat.isSymbolicLink()) continue;\n const real = await fs.realpath(location);\n if (inside(realRoot, real)) await visit(real);\n } else if (entry.isFile()) {\n const relativePath = path.relative(realRoot, location).split(path.sep).join('/');\n try {\n const file = await openArtifact(root, relativePath);\n try {\n items.push({ path: relativePath, name: entry.name, size: file.stat.size, modifiedAt: file.stat.mtimeMs });\n } finally {\n await file.handle.close();\n }\n } catch (error) {\n if (error instanceof ArtifactAccessError && (error.status === 404 || error.status === 403)) continue;\n throw error;\n }\n }\n }\n };\n await visit(realRoot);\n items.sort(\n (left, right) =>\n right.modifiedAt - left.modifiedAt || (left.path < right.path ? -1 : left.path > right.path ? 1 : 0),\n );\n return { items };\n } catch (error) {\n if (codeOf(error) === 'ENOENT') return { items: [] };\n return { items: [], error: error instanceof Error ? error.message : 'The artifact folder could not be read.' };\n }\n}\n","import { clearTimeout, setTimeout } from 'node:timers';\n\nimport type { DoomHeadlessActivity, DoomHeadlessExecutionContext, DoomHeadlessHook } from '@agimon-ai/po-core/headless';\nimport type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\n\nimport { ARTIFACT_REFRESH_MS } from '../../constants/artifacts';\nimport { artifactsChannelType } from '../../types/artifacts';\nimport { artifactRoot, ensureArtifactRoot, listArtifacts } from '../artifactFiles';\n\nexport function createArtifactSession({ host }: DoomServerPluginContext) {\n const environment = Object.freeze({ ...host.context.environment });\n let active: { context: DoomHeadlessExecutionContext; root: string; fingerprint?: string } | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let pending: Promise<void> | undefined;\n let closed = false;\n\n const refresh = (): Promise<void> => {\n if (pending) return pending;\n const runtime = active;\n if (!runtime || closed) return Promise.resolve();\n pending = (async () => {\n const snapshot = await listArtifacts(runtime.root);\n if (closed || active !== runtime) return;\n const fingerprint = JSON.stringify(snapshot);\n if (fingerprint === runtime.fingerprint) return;\n runtime.fingerprint = fingerprint;\n host.context.directEvents?.publish(artifactsChannelType, runtime.context.sessionId, snapshot);\n })().finally(() => {\n pending = undefined;\n });\n return pending;\n };\n const schedule = (): void => {\n if (!active || closed) return;\n timer = setTimeout(() => {\n timer = undefined;\n void refresh().finally(schedule);\n }, ARTIFACT_REFRESH_MS);\n };\n const stop = async (): Promise<void> => {\n active = undefined;\n if (timer !== undefined) clearTimeout(timer);\n timer = undefined;\n await pending;\n };\n const activity: DoomHeadlessActivity = {\n name: 'artifacts',\n async start(context) {\n if (closed) throw new Error('Artifact session is closed.');\n await stop();\n const root = artifactRoot(context.sessionId, environment);\n await ensureArtifactRoot(root);\n if (closed) throw new Error('Artifact session is closed.');\n active = { context, root };\n await refresh();\n schedule();\n return stop;\n },\n };\n const beforeAgentStart: DoomHeadlessHook = {\n event: 'before_agent_start',\n async handle(event, context) {\n const root = artifactRoot(context.sessionId, environment);\n await ensureArtifactRoot(root);\n const systemPrompt = typeof event.systemPrompt === 'string' ? event.systemPrompt : '';\n const declaration = `Session artifact folder: ${root}`;\n if (systemPrompt.includes(declaration)) return { systemPrompt };\n return {\n systemPrompt:\n `${systemPrompt}\\n\\n${declaration}\\nSave user-designated artifacts and important deliverable documents in this folder, using descriptive filenames. Keep ordinary repository source edits in their existing locations. Do not move existing documents or overwrite artifacts without the user's intent. This folder belongs only to the current session.`.trim(),\n };\n },\n };\n const toolExecutionEnd: DoomHeadlessHook = {\n event: 'tool_execution_end',\n handle(_event, context) {\n return active?.context.sessionId === context.sessionId ? refresh() : undefined;\n },\n };\n return {\n activities: [activity],\n beforeAgentStart,\n toolExecutionEnd,\n onDispose: async () => {\n closed = true;\n await stop();\n },\n };\n}\n","import type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\n\nimport { createArtifactSession } from '../../../../../services/artifactSession';\n\nexport const createArtifactServerRoot = (context: DoomServerPluginContext) => {\n const runtime = createArtifactSession(context);\n return { value: runtime, activities: runtime.activities, onDispose: runtime.onDispose };\n};\nexport type ArtifactServerScope = ReturnType<typeof createArtifactServerRoot>['value'];\n","import { defineRoot } from '@agimon-ai/po-core/extensionFile';\n\nimport { createArtifactServerRoot } from './_lib/serverRoot';\n\nexport default defineRoot(createArtifactServerRoot);\n","import type { DoomHubChannel } from '@agimon-ai/po-core/hubChannel';\n\nimport { artifactsChannelType, type ArtifactSnapshot } from '../../types/artifacts';\nimport { artifactRoot, listArtifacts } from '../artifactFiles';\n\nfunction snapshotOf(value: unknown): value is ArtifactSnapshot {\n if (typeof value !== 'object' || value === null) return false;\n const snapshot = value as Partial<ArtifactSnapshot>;\n return (\n Array.isArray(snapshot.items) &&\n (snapshot.error === undefined || typeof snapshot.error === 'string') &&\n snapshot.items.every(\n (item) =>\n typeof item === 'object' &&\n item !== null &&\n typeof item.path === 'string' &&\n typeof item.name === 'string' &&\n typeof item.size === 'number' &&\n Number.isFinite(item.size) &&\n typeof item.modifiedAt === 'number' &&\n Number.isFinite(item.modifiedAt),\n )\n );\n}\n\nexport function createArtifactsChannel(): DoomHubChannel {\n return {\n frameType: artifactsChannelType,\n start(host) {\n const sessions = new Map<string, { snapshot?: ArtifactSnapshot; unsubscribe: () => void }>();\n return {\n payloadFor(scope) {\n return sessions.get(scope.sessionId)?.snapshot;\n },\n sessionAdded(scope) {\n sessions.get(scope.sessionId)?.unsubscribe();\n const state: { snapshot?: ArtifactSnapshot; unsubscribe: () => void } = { unsubscribe: () => undefined };\n sessions.set(scope.sessionId, state);\n state.unsubscribe = host.directEvents.subscribe(\n artifactsChannelType,\n scope.sessionId,\n (snapshot) => {\n if (!snapshotOf(snapshot) || sessions.get(scope.sessionId) !== state) return;\n state.snapshot = snapshot;\n host.publish(scope.sessionId, snapshot);\n },\n { replayLatest: true },\n );\n void (async () => {\n let snapshot: ArtifactSnapshot;\n try {\n snapshot = await listArtifacts(artifactRoot(scope.sessionId, scope.environment ?? {}));\n } catch (error) {\n snapshot = {\n items: [],\n error: error instanceof Error ? error.message : 'The artifact folder could not be read.',\n };\n }\n // A live session event wins over the earlier seed read.\n if (sessions.get(scope.sessionId) !== state || state.snapshot !== undefined) return;\n state.snapshot = snapshot;\n host.publish(scope.sessionId, snapshot);\n })();\n },\n sessionRemoved(sessionId) {\n sessions.get(sessionId)?.unsubscribe();\n sessions.delete(sessionId);\n },\n close() {\n for (const state of sessions.values()) state.unsubscribe();\n sessions.clear();\n },\n };\n },\n };\n}\n","import { defineChannel } from '@agimon-ai/po-core/extensionFile';\n\nimport { createArtifactsChannel } from '../../../services/artifactChannel';\n\nexport default defineChannel(createArtifactsChannel);\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport type { ArtifactPreview, ArtifactSnapshot } from './artifacts';\n\nconst routes = {\n list: {\n method: 'GET',\n path: '/',\n response: undefined as unknown as ApiResponseOf<ArtifactSnapshot>,\n },\n preview: {\n method: 'GET',\n path: '/preview',\n query: ['path'],\n response: undefined as unknown as ApiResponseOf<ArtifactPreview>,\n },\n content: {\n method: 'GET',\n path: '/content',\n query: ['path'],\n raw: true,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\n","import path from 'node:path';\n\nimport type { DoomApi, DoomApiContext } from '@agimon-ai/po-core/packageApi';\nimport { Hono } from 'hono';\n\nimport { MAX_CONTENT_BYTES, MAX_PREVIEW_BYTES } from '../../constants/artifacts';\nimport routes from '../../types/apiRoutes';\nimport type { ArtifactPreview } from '../../types/artifacts';\nimport { ArtifactAccessError, artifactRoot, listArtifacts, openArtifact, readArtifactBytes } from '../artifactFiles';\n\nexport function createArtifactsApi(root: string): Hono {\n const app = new Hono();\n app.onError((error, context) =>\n context.json(\n { error: error instanceof ArtifactAccessError ? error.message : 'The artifact could not be read.' },\n error instanceof ArtifactAccessError ? error.status : 500,\n ),\n );\n app.get(routes.list.path, async (context) => {\n const snapshot = await listArtifacts(root);\n return context.json(snapshot, snapshot.error === undefined ? 200 : 500);\n });\n app.get(routes.preview.path, async (context) => {\n const file = await openArtifact(root, context.req.query('path'));\n try {\n const preview: ArtifactPreview = { path: file.path, content: '', mimeType: file.mimeType };\n if (file.stat.size > MAX_PREVIEW_BYTES) {\n return context.json({\n ...preview,\n unavailable: true,\n reason: 'This artifact is too large for a text preview.',\n });\n }\n const bytes = await readArtifactBytes(file.handle, MAX_PREVIEW_BYTES + 1);\n if (bytes.byteLength > MAX_PREVIEW_BYTES)\n return context.json({\n ...preview,\n unavailable: true,\n reason: 'This artifact is too large for a text preview.',\n });\n if (bytes.subarray(0, 8192).includes(0))\n return context.json({ ...preview, unavailable: true, reason: 'This artifact is binary.' });\n return context.json({ ...preview, content: new TextDecoder().decode(bytes) });\n } finally {\n await file.handle.close();\n }\n });\n app.get(routes.content.path, async (context) => {\n const file = await openArtifact(root, context.req.query('path'));\n try {\n if (file.stat.size > MAX_CONTENT_BYTES)\n throw new ArtifactAccessError('This artifact is too large to download.', 413);\n const version = `\"${file.stat.dev}-${file.stat.ino}-${file.stat.size}-${file.stat.mtimeMs}-${file.stat.ctimeMs}\"`;\n const name = encodeURIComponent(path.basename(file.path)).replace(\n /[!'()*]/gu,\n (value) => `%${value.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n const headers = new Headers({\n 'content-type': file.mimeType,\n 'content-disposition': `attachment; filename*=UTF-8''${name}`,\n 'cache-control': 'no-store',\n 'x-content-type-options': 'nosniff',\n 'content-security-policy': \"default-src 'none'; sandbox\",\n 'accept-ranges': 'bytes',\n etag: version,\n });\n const expectedVersion = context.req.header('if-match');\n if (expectedVersion !== undefined && expectedVersion !== version)\n return new Response(null, { status: 412, headers });\n let start = 0;\n let end = file.stat.size - 1;\n const range = context.req.header('range');\n if (range !== undefined) {\n const match = /^bytes=(\\d*)-(\\d*)$/u.exec(range);\n if (\n !match ||\n (!match[1] && !match[2]) ||\n file.stat.size === 0 ||\n [match[1], match[2]].some((value) => value !== '' && !Number.isSafeInteger(Number(value)))\n ) {\n headers.set('content-range', `bytes */${file.stat.size}`);\n return new Response(null, { status: 416, headers });\n }\n if (match[1] === '') {\n const suffix = Number(match[2]);\n start = suffix > 0 ? Math.max(0, file.stat.size - suffix) : file.stat.size;\n } else {\n start = Number(match[1]);\n end = match[2] === '' ? end : Math.min(end, Number(match[2]));\n }\n if (start > end || start >= file.stat.size) {\n headers.set('content-range', `bytes */${file.stat.size}`);\n return new Response(null, { status: 416, headers });\n }\n headers.set('content-range', `bytes ${start}-${end}/${file.stat.size}`);\n }\n const bytes = await readArtifactBytes(file.handle, Math.max(0, end - start + 1), start);\n const after = await file.handle.stat();\n if (after.size !== file.stat.size || after.mtimeMs !== file.stat.mtimeMs || after.ctimeMs !== file.stat.ctimeMs)\n return new Response(null, { status: 412, headers });\n headers.set('content-length', String(bytes.byteLength));\n return new Response(bytes, { status: range === undefined ? 200 : 206, headers });\n } finally {\n await file.handle.close();\n }\n });\n return app;\n}\n\nexport const api: DoomApi = {\n basePath: 'artifacts',\n start(context: DoomApiContext) {\n if (!context.sessionId) throw new Error('Artifacts requires a session identity.');\n const app = createArtifactsApi(artifactRoot(context.sessionId, context.environment ?? {}));\n return { fetch: (request) => app.fetch(request), close: () => undefined };\n },\n};\n","import { defineRoute } from '@agimon-ai/po-core/extensionFile';\n\nimport { api } from '../../../../../../services/artifactsApi';\n\nexport default defineRoute(api);\n","import { defineHook, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\n\nimport type { ArtifactServerScope } from '../_lib/serverRoot';\n\nexport default defineHook(\n (context: WithRoot<DoomServerPluginContext, ArtifactServerScope>) => context.root.beforeAgentStart,\n);\n","import { defineHook, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\n\nimport type { ArtifactServerScope } from '../_lib/serverRoot';\n\nexport default defineHook(\n (context: WithRoot<DoomServerPluginContext, ArtifactServerScope>) => context.root.toolExecutionEnd,\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport channelArtifacts from '../src/extensions/(backend)/channel/artifacts.server';\nimport apiRoute from '../src/extensions/workspaces/sessions/(backend)/api/artifacts/route.server';\nimport hookBeforeAgentStart from '../src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.server';\nimport hookToolExecutionEnd from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/po-artifact',\n providerOverrides: composeServerProviderOverrides(rootSession),\n global: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'artifacts' }, channelArtifacts())]; },\n }),\n workspace: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'artifacts' }, channelArtifacts())]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, contextSession)]; },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'artifacts' }, channelArtifacts())]; },\n get hooks(): DoomServerSessionPlugin['hooks'] { return [via({ event: 'before_agent_start' }, at(hookBeforeAgentStart, contextSession)), via({ event: 'tool_execution_end' }, at(hookToolExecutionEnd, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region generated/server.d.ts
2
+ export declare const facet: import("@agimon-ai/po-core/serverFacet").DoomServerFacet;
3
+ //#endregion
4
+ export { facet as default };
5
+ //# sourceMappingURL=server.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAiBa,gDAAK"}