Integrate current master before rich ACP foundation review

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* commit '53aad90b9':
  fix: retry sandbox ACP input delivery after gateway failures (#14485)
  fix: retain project defaults in partial workspace overrides (#14502)
  test: control Telegram subscription retry timing (#14501)
  fix: retain diagnostic reasons for native runner failures (#14481)
  fix: prevent run identity locks from blocking audit checks (#14478)
  fix: preserve company context across browser hot reload (#14482)
  feat(ui): improve task composer controls and pending input (#14322)
  Improve task artifacts with rich cards and editable stories (#14469)
This commit is contained in:
DottaandPaperclip committed 2026-09-29 07:50:49 -05:00
commit 9774086a73
111 files changed
+7338 -1164

No files matched your search

+45 -2
View File
@@ -1,11 +1,54 @@
import { createRequire } from "node:module";
import { createHash } from "node:crypto";
/** Build-only: reuse the API worker and finite preset contract, never a browser renderer. */
/** Render avatar presets with the API worker in dev and package them in builds. */
export function storybookAgentAvatarAssets() {
return {
name: "storybook-agent-avatar-assets",
apply: "build",
configureServer(server) {
let rendererPromise;
const images = new Map();
const renderer = () => rendererPromise ??= (async () => {
const serverRequire = createRequire(new URL("../server/package.json", import.meta.url));
const { tsImport } = await import(serverRequire.resolve("tsx/esm/api"));
const { createAgentAvatarPool } = await tsImport("../server/src/services/agent-avatar-pool.ts", import.meta.url);
const { AGENT_PALETTE_IDS, AGENT_AVATAR_SIZES, CHARACTER_STATES, appearanceForPalette } =
await tsImport("../packages/shared/src/agent-appearance.ts", import.meta.url);
return { pool: createAgentAvatarPool(2), AGENT_PALETTE_IDS, AGENT_AVATAR_SIZES, CHARACTER_STATES, appearanceForPalette };
})();
server.middlewares.use((req, res, next) => {
const pathname = new URL(req.url ?? "/", "http://storybook.local").pathname;
const match = /^\/agent-avatar-images\/cap-v1\/([^/]+)\/([^/]+)-(\d+)-([12])\.png$/.exec(pathname);
if (!match) return next();
void (async () => {
const [, palette, pose, sizeText, scaleText] = match;
const { pool, AGENT_PALETTE_IDS, AGENT_AVATAR_SIZES, CHARACTER_STATES, appearanceForPalette } = await renderer();
const size = Number(sizeText);
const scale = Number(scaleText);
const muted = palette === "muted-dream";
if (!(muted || AGENT_PALETTE_IDS.includes(palette)) || !CHARACTER_STATES.includes(pose) || !AGENT_AVATAR_SIZES.includes(size)) {
res.statusCode = 404;
res.end();
return;
}
if (!images.has(pathname)) {
const appearance = appearanceForPalette(muted ? AGENT_PALETTE_IDS[0] : palette);
images.set(pathname, pool.render({ appearance, size, scale, pose, muted }).catch((error) => {
images.delete(pathname);
throw error;
}));
}
const png = await images.get(pathname);
res.setHeader("Content-Type", "image/png");
res.setHeader("Cache-Control", "public, max-age=3600");
res.end(png);
})().catch(() => {
res.statusCode = 500;
res.end("Avatar rendering failed");
});
});
server.httpServer?.once("close", () => { void rendererPromise?.then(({ pool }) => pool.close()); });
},
async generateBundle() {
const serverRequire = createRequire(new URL("../server/package.json", import.meta.url));
const { tsImport } = await import(serverRequire.resolve("tsx/esm/api"));