162c9ca422
- Added `src/export/share.ts`: `/share` now snapshots the session JSON, gzips and seals it with a fresh AES-256-GCM key, and pushes the blob to a secret gist or the share server (1 MB cap with image/string/entry truncation via `sealToFit`); links are `<serverUrl>/<id>#<key>` with the key only in the fragment. - Added `share-loader.js` and `scripts/generate-share-viewer.ts` building the static viewer the relay serves at `GET /s/<id>`: it fetches the sealed blob, decrypts in-browser, and hands the JSON to the export template via `window.__OMP_SESSION_DATA__`. - Reworked the `/share` command in `command-controller.ts`/`builtin-registry.ts` off the plaintext-gist HTML upload, exported `LoadedCustomShare`, and exposed the session `SecretObfuscator` getter on `AgentSession` for redaction. - Added `share.serverUrl` and `share.redactSecrets` settings backed by `DEFAULT_SHARE_URL` from pi-wire. - HTML exports now embed subagent transcripts: `collectSubSessions` walks `<session>/<AgentId>.jsonl` recursively into `SessionData.subSessions`, with `includeSubSessions` opt-out and the exported `buildSessionData` reused by share snapshots. - Added `share.test.ts` (snapshot/seal/server-url contracts) and `export-subsessions.test.ts`.
35 lines
1.6 KiB
TypeScript
Executable File
35 lines
1.6 KiB
TypeScript
Executable File
#!/usr/bin/env bun
|
|
/**
|
|
* Build the standalone share-viewer page the omp relay serves at `GET /s/<id>`.
|
|
*
|
|
* Same template as HTML exports, but with no embedded session: share-loader.js
|
|
* (injected right after the empty #session-data tag) fetches the sealed blob
|
|
* (gist or relay store), decrypts it with the `#<key>` fragment in-browser, and
|
|
* hands the JSON to template.js via `window.__OMP_SESSION_DATA__`.
|
|
*
|
|
* The relay repo's build script runs this and embeds the output via go:embed.
|
|
*/
|
|
import * as path from "node:path";
|
|
import { generateThemeVars, getTemplate } from "../src/export/html";
|
|
|
|
const outPath = process.argv[2];
|
|
if (!outPath) {
|
|
console.error("usage: bun scripts/generate-share-viewer.ts <output.html>");
|
|
process.exit(2);
|
|
}
|
|
|
|
const loaderJs = await Bun.file(new URL("../src/export/html/share-loader.js", import.meta.url).pathname).text();
|
|
// Pin a built-in theme: the viewer is a public artifact, not a per-user export.
|
|
const themeVars = await generateThemeVars("dark");
|
|
|
|
const html = getTemplate()
|
|
.replace("<theme-vars/>", () => `<style>:root { ${themeVars} }</style>`)
|
|
.replace("<title>Session Export</title>", () => "<title>omp session</title>")
|
|
.replace("{{SESSION_DATA}}</script>", () => `</script>\n <script>${loaderJs}</script>`);
|
|
|
|
if (html.includes("{{SESSION_DATA}}")) throw new Error("session-data placeholder survived substitution");
|
|
if (!html.includes("__OMP_SESSION_DATA__")) throw new Error("share loader not injected");
|
|
|
|
await Bun.write(outPath, html);
|
|
console.log(`Generated ${path.resolve(outPath)} (${(html.length / 1024).toFixed(0)} KB)`);
|