mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-30 02:20:38 +00:00
feat(cron): support custom session IDs and auto-bind to current session (#16511)
feat(cron): support persistent session targets for cron jobs (#9765) Add support for `sessionTarget: "current"` and `session:<id>` so cron jobs can bind to the creating session or a persistent named session instead of only `main` or ephemeral `isolated` sessions. Also: - preserve custom session targets across reloads and restarts - update gateway validation and normalization for the new target forms - add cron coverage for current/custom session targets and fallback behavior - fix merged CI regressions in Discord and diffs tests - add a changelog entry for the new cron session behavior Co-authored-by: kkhomej33-netizen <kkhomej33-netizen@users.noreply.github.com> Co-authored-by: ImLukeF <92253590+ImLukeF@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
61d171ab0b
commit
e7d9648fba
@@ -23,8 +23,7 @@ describe("renderDiffDocument", () => {
|
||||
expect(rendered.html).toContain("data-openclaw-diff-root");
|
||||
expect(rendered.html).toContain("src/example.ts");
|
||||
expect(rendered.html).toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(rendered.imageHtml).not.toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(rendered.imageHtml).toContain('data-openclaw-diffs-ready="true"');
|
||||
expect(rendered.imageHtml).toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(rendered.imageHtml).toContain("max-width: 960px;");
|
||||
expect(rendered.imageHtml).toContain("--diffs-font-size: 16px;");
|
||||
expect(rendered.html).toContain("min-height: 100vh;");
|
||||
|
||||
@@ -241,14 +241,6 @@ function renderDiffCard(payload: DiffViewerPayload): string {
|
||||
</section>`;
|
||||
}
|
||||
|
||||
function renderStaticDiffCard(prerenderedHTML: string): string {
|
||||
return `<section class="oc-diff-card">
|
||||
<diffs-container class="oc-diff-host" data-openclaw-diff-host>
|
||||
<template shadowrootmode="open">${prerenderedHTML}</template>
|
||||
</diffs-container>
|
||||
</section>`;
|
||||
}
|
||||
|
||||
function buildHtmlDocument(params: {
|
||||
title: string;
|
||||
bodyHtml: string;
|
||||
@@ -257,7 +249,7 @@ function buildHtmlDocument(params: {
|
||||
runtimeMode: "viewer" | "image";
|
||||
}): string {
|
||||
return `<!doctype html>
|
||||
<html lang="en"${params.runtimeMode === "image" ? ' data-openclaw-diffs-ready="true"' : ""}>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
@@ -349,7 +341,7 @@ function buildHtmlDocument(params: {
|
||||
${params.bodyHtml}
|
||||
</div>
|
||||
</main>
|
||||
${params.runtimeMode === "viewer" ? `<script type="module" src="${VIEWER_LOADER_PATH}"></script>` : ""}
|
||||
<script type="module" src="${VIEWER_LOADER_PATH}"></script>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
@@ -360,16 +352,12 @@ type RenderedSection = {
|
||||
};
|
||||
|
||||
function buildRenderedSection(params: {
|
||||
viewerPrerenderedHtml: string;
|
||||
imagePrerenderedHtml: string;
|
||||
payload: Omit<DiffViewerPayload, "prerenderedHTML">;
|
||||
viewerPayload: DiffViewerPayload;
|
||||
imagePayload: DiffViewerPayload;
|
||||
}): RenderedSection {
|
||||
return {
|
||||
viewer: renderDiffCard({
|
||||
prerenderedHTML: params.viewerPrerenderedHtml,
|
||||
...params.payload,
|
||||
}),
|
||||
image: renderStaticDiffCard(params.imagePrerenderedHtml),
|
||||
viewer: renderDiffCard(params.viewerPayload),
|
||||
image: renderDiffCard(params.imagePayload),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -401,21 +389,20 @@ async function renderBeforeAfterDiff(
|
||||
};
|
||||
const { viewerOptions, imageOptions } = buildRenderVariants(options);
|
||||
const [viewerResult, imageResult] = await Promise.all([
|
||||
preloadMultiFileDiff({
|
||||
preloadMultiFileDiffWithFallback({
|
||||
oldFile,
|
||||
newFile,
|
||||
options: viewerOptions,
|
||||
}),
|
||||
preloadMultiFileDiff({
|
||||
preloadMultiFileDiffWithFallback({
|
||||
oldFile,
|
||||
newFile,
|
||||
options: imageOptions,
|
||||
}),
|
||||
]);
|
||||
const section = buildRenderedSection({
|
||||
viewerPrerenderedHtml: viewerResult.prerenderedHTML,
|
||||
imagePrerenderedHtml: imageResult.prerenderedHTML,
|
||||
payload: {
|
||||
viewerPayload: {
|
||||
prerenderedHTML: viewerResult.prerenderedHTML,
|
||||
oldFile: viewerResult.oldFile,
|
||||
newFile: viewerResult.newFile,
|
||||
options: viewerOptions,
|
||||
@@ -424,6 +411,16 @@ async function renderBeforeAfterDiff(
|
||||
newFile: viewerResult.newFile,
|
||||
}),
|
||||
},
|
||||
imagePayload: {
|
||||
prerenderedHTML: imageResult.prerenderedHTML,
|
||||
oldFile: imageResult.oldFile,
|
||||
newFile: imageResult.newFile,
|
||||
options: imageOptions,
|
||||
langs: buildPayloadLanguages({
|
||||
oldFile: imageResult.oldFile,
|
||||
newFile: imageResult.newFile,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -456,24 +453,29 @@ async function renderPatchDiff(
|
||||
const sections = await Promise.all(
|
||||
files.map(async (fileDiff) => {
|
||||
const [viewerResult, imageResult] = await Promise.all([
|
||||
preloadFileDiff({
|
||||
preloadFileDiffWithFallback({
|
||||
fileDiff,
|
||||
options: viewerOptions,
|
||||
}),
|
||||
preloadFileDiff({
|
||||
preloadFileDiffWithFallback({
|
||||
fileDiff,
|
||||
options: imageOptions,
|
||||
}),
|
||||
]);
|
||||
|
||||
return buildRenderedSection({
|
||||
viewerPrerenderedHtml: viewerResult.prerenderedHTML,
|
||||
imagePrerenderedHtml: imageResult.prerenderedHTML,
|
||||
payload: {
|
||||
viewerPayload: {
|
||||
prerenderedHTML: viewerResult.prerenderedHTML,
|
||||
fileDiff: viewerResult.fileDiff,
|
||||
options: viewerOptions,
|
||||
langs: buildPayloadLanguages({ fileDiff: viewerResult.fileDiff }),
|
||||
},
|
||||
imagePayload: {
|
||||
prerenderedHTML: imageResult.prerenderedHTML,
|
||||
fileDiff: imageResult.fileDiff,
|
||||
options: imageOptions,
|
||||
langs: buildPayloadLanguages({ fileDiff: imageResult.fileDiff }),
|
||||
},
|
||||
});
|
||||
}),
|
||||
);
|
||||
@@ -514,3 +516,49 @@ export async function renderDiffDocument(
|
||||
inputKind: input.kind,
|
||||
};
|
||||
}
|
||||
|
||||
type PreloadedFileDiffResult = Awaited<ReturnType<typeof preloadFileDiff>>;
|
||||
type PreloadedMultiFileDiffResult = Awaited<ReturnType<typeof preloadMultiFileDiff>>;
|
||||
|
||||
function shouldFallbackToClientHydration(error: unknown): boolean {
|
||||
return (
|
||||
error instanceof TypeError &&
|
||||
error.message.includes('needs an import attribute of "type: json"')
|
||||
);
|
||||
}
|
||||
|
||||
async function preloadFileDiffWithFallback(params: {
|
||||
fileDiff: FileDiffMetadata;
|
||||
options: DiffViewerOptions;
|
||||
}): Promise<PreloadedFileDiffResult> {
|
||||
try {
|
||||
return await preloadFileDiff(params);
|
||||
} catch (error) {
|
||||
if (!shouldFallbackToClientHydration(error)) {
|
||||
throw error;
|
||||
}
|
||||
return {
|
||||
fileDiff: params.fileDiff,
|
||||
prerenderedHTML: "",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function preloadMultiFileDiffWithFallback(params: {
|
||||
oldFile: FileContents;
|
||||
newFile: FileContents;
|
||||
options: DiffViewerOptions;
|
||||
}): Promise<PreloadedMultiFileDiffResult> {
|
||||
try {
|
||||
return await preloadMultiFileDiff(params);
|
||||
} catch (error) {
|
||||
if (!shouldFallbackToClientHydration(error)) {
|
||||
throw error;
|
||||
}
|
||||
return {
|
||||
oldFile: params.oldFile,
|
||||
newFile: params.newFile,
|
||||
prerenderedHTML: "",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ describe("diffs tool", () => {
|
||||
const cleanupSpy = vi.spyOn(store, "scheduleCleanup");
|
||||
const screenshotter = createPngScreenshotter({
|
||||
assertHtml: (html) => {
|
||||
expect(html).not.toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(html).toContain("/plugins/diffs/assets/viewer.js");
|
||||
},
|
||||
assertImage: (image) => {
|
||||
expect(image).toMatchObject({
|
||||
@@ -332,13 +332,13 @@ describe("diffs tool", () => {
|
||||
const html = await store.readHtml(id);
|
||||
expect(html).toContain('body data-theme="light"');
|
||||
expect(html).toContain("--diffs-font-size: 17px;");
|
||||
expect(html).toContain('--diffs-font-family: "JetBrains Mono"');
|
||||
expect(html).toContain("JetBrains Mono");
|
||||
});
|
||||
|
||||
it("prefers explicit tool params over configured defaults", async () => {
|
||||
const screenshotter = createPngScreenshotter({
|
||||
assertHtml: (html) => {
|
||||
expect(html).not.toContain("/plugins/diffs/assets/viewer.js");
|
||||
expect(html).toContain("/plugins/diffs/assets/viewer.js");
|
||||
},
|
||||
assertImage: (image) => {
|
||||
expect(image).toMatchObject({
|
||||
|
||||
Reference in New Issue
Block a user