@runfusion/fusion 0.75.0-beta.2 → 0.75.1-beta.0
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/bin.js +184 -48
- package/dist/child-process-worker.js +39 -25
- package/dist/client/.vite/manifest.json +248 -248
- package/dist/client/assets/{AgentDetailView-C4Xpag_i.js → AgentDetailView-swTdiyeE.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-D-Fp7-sy.js → AgentPermissionPolicyEditor-Dq-KuDaA.js} +1 -1
- package/dist/client/assets/{AgentsView-BmFsoY1Q.js → AgentsView-D1GEHyH0.js} +3 -3
- package/dist/client/assets/{ChatView-5KsB3BVO.js → ChatView-D1czGvvT.js} +1 -1
- package/dist/client/assets/{CommandCenter-CacGI8AV.js → CommandCenter-DWZ7OTOB.js} +1 -1
- package/dist/client/assets/{DevServerView-DufjauVn.js → DevServerView-CAcUKOXd.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DvwqfQDS.js → DirectoryPicker-DVUl5jOk.js} +1 -1
- package/dist/client/assets/{DocumentsView-BbYJFIQ1.js → DocumentsView-CnexOxtr.js} +1 -1
- package/dist/client/assets/{EvalsView-NBC8kOc-.js → EvalsView-rTupzcDf.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-C809yXXY.js → ExperimentalAgentOnboardingModal-CXE6Bj3V.js} +1 -1
- package/dist/client/assets/{GoalsView-CpNO9eI0.js → GoalsView-CjHwnnIi.js} +1 -1
- package/dist/client/assets/{InsightsView-Cahy5FcR.js → InsightsView-C3XocYP-.js} +1 -1
- package/dist/client/assets/{MemoryView-BNJAQjqn.js → MemoryView-CsNHcx_d.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-DCHTyOmJ.js → PiExtensionsManager-BPTPoZBI.js} +1 -1
- package/dist/client/assets/{PluginManager-CBt-CqUz.js → PluginManager-CXadn8JE.js} +1 -1
- package/dist/client/assets/{PullRequestView-Dsb9RwmX.js → PullRequestView-CC03CtZJ.js} +1 -1
- package/dist/client/assets/{ReportModal-8FjZOcbC.js → ReportModal-Ci0na1eI.js} +1 -1
- package/dist/client/assets/{ResearchView-DlSG7dOd.js → ResearchView-DGWyAo8p.js} +1 -1
- package/dist/client/assets/{SecretsView-BSajNE-f.js → SecretsView-Cv2IuqFO.js} +1 -1
- package/dist/client/assets/{SessionTerminal-M2fIpHrL.js → SessionTerminal-B22RlQeo.js} +1 -1
- package/dist/client/assets/{SettingsModal-z6gOf7dG.js → SettingsModal-BkgBQZ19.js} +1 -1
- package/dist/client/assets/{SettingsModal-DLcvlp44.js → SettingsModal-CPRpRK71.js} +3 -3
- package/dist/client/assets/{SettingsTextareaRow-DeC19053.js → SettingsTextareaRow-0LXwMUQR.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-BOjMePFh.js → SetupWizardModal-CyW3AlRO.js} +2 -2
- package/dist/client/assets/{SkillsView-BSBEC-Xm.js → SkillsView-3oqB1ubq.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-DZ9-RBqo.js → WorkflowNodeEditor-CfUK_xs1.js} +1 -1
- package/dist/client/assets/{agent-import-generation-COItiXMT.js → agent-import-generation-C7-Cmo3M.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-BwlCePoB.js → architectureDiagram-3BPJPVTR-BQ7ZN1r_.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-KKrLi9v4.js → blockDiagram-GPEHLZMM-Debw1Xka.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CkIDt_8M.js → c4Diagram-AAUBKEIU-CiU212s3.js} +1 -1
- package/dist/client/assets/channel-D-O4mRXx.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-D9sbdaqY.js → chunk-2J33WTMH-BUJQ86zb.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-D3DtFoAY.js → chunk-4BX2VUAB-C6GdEm1z.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-gxblxRIN.js → chunk-55IACEB6-CImvrxQL.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-D0AEDoHN.js → chunk-727SXJPM-Dt-A3pkM.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-BweoM7qY.js → chunk-AQP2D5EJ-DDj4oXTx.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-sjblhrjI.js → chunk-FMBD7UC4-BD4r1ukC.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-CYuRENSs.js → chunk-ND2GUHAM-DFSteefi.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-CFKJr4kG.js → chunk-QZHKN3VN-t2zF8tjB.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BhHdSetA.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BhHdSetA.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-6Jb6SgHM.js → cose-bilkent-S5V4N54A-tkvDkXQA.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-FQJ87Ol3.js → dagre-BM42HDAG-DD2rW7wo.js} +1 -1
- package/dist/client/assets/{dashboard-view-DgLbkn5n.js → dashboard-view-B1vduc8x.js} +1 -1
- package/dist/client/assets/{dashboard-view-DVMZNVoc.js → dashboard-view-C7jJ1lA4.js} +1 -1
- package/dist/client/assets/{dashboard-view-DH1Zo0m4.js → dashboard-view-CciuDS5A.js} +1 -1
- package/dist/client/assets/{dashboard-view-B1Rq2-73.js → dashboard-view-DruCruAc.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-CKYOu9to.js → diagram-2AECGRRQ-DASuxGNc.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-DPwjFnde.js → diagram-5GNKFQAL-f9WtiIUk.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DzZS9Nk3.js → diagram-KO2AKTUF-QivICYCd.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DW9e5YSP.js → diagram-LMA3HP47-CMwcDFHR.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-C7V3Mj63.js → diagram-OG6HWLK6-C-vPMeHZ.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DSQzBA0e.js → erDiagram-TEJ5UH35-CxGtk9vj.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-BUuOq9tO.js → flowDiagram-I6XJVG4X-qBZRZoV1.js} +1 -1
- package/dist/client/assets/{folder-open-DXNu4ED4.js → folder-open-Dysi9Zzg.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-Bc32G_Ef.js → ganttDiagram-6RSMTGT7-DAaXroiu.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-Cvfa0W6a.js → gitGraphDiagram-PVQCEYII-DNUNQot_.js} +1 -1
- package/dist/client/assets/{index-C5YdAqNQ.js → index-D0QgE5F5.js} +299 -299
- package/dist/client/assets/{infoDiagram-5YYISTIA-TqRUTfvy.js → infoDiagram-5YYISTIA-BSJmWLwh.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-D33iop1_.js → ishikawaDiagram-YF4QCWOH-AyVKvoDq.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DH-TDR5Y.js → journeyDiagram-JHISSGLW-972txzzd.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CAcebzyW.js → kanban-definition-UN3LZRKU-1xiNvIqK.js} +1 -1
- package/dist/client/assets/{mermaid.core-C3Nh1Sak.js → mermaid.core-oeDA8jOm.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-CSIccWV8.js → mindmap-definition-RKZ34NQL-DcktmI8s.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-hXJ3G3MR.js → pieDiagram-4H26LBE5-ekBwLt-O.js} +1 -1
- package/dist/client/assets/{puzzle-DI3elldh.js → puzzle-I6pr6ZrW.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-B3wpvneC.js → quadrantDiagram-W4KKPZXB-D_wjTsvn.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DPpYL2ca.js → requirementDiagram-4Y6WPE33-CKGHyiJ1.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BS9QXSEF.js → sankeyDiagram-5OEKKPKP-CtiZFNk5.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-C_fqU0MW.js → sequenceDiagram-3UESZ5HK-B6OMrfGk.js} +1 -1
- package/dist/client/assets/{shield-alert-CzZYSqmH.js → shield-alert-CVMmviMG.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-CsXA4WMZ.js → standing-instructions-template-Cg1a3tjW.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-DbSZrprS.js → stateDiagram-AJRCARHV-CyTY2M_7.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-Cf_ckwmM.js → stateDiagram-v2-BHNVJYJU-NWPCCiqC.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-B1ohvKjs.js → timeline-definition-PNZ67QCA-DU4TVYpw.js} +1 -1
- package/dist/client/assets/{upload-D7nNe9wD.js → upload-VCzeCiFH.js} +1 -1
- package/dist/client/assets/{users-B79Dvre4.js → users-DB3knZtm.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-CxZYCQ72.js → vennDiagram-CIIHVFJN-DX0Ppll6.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-clJem8VU.js → wardley-L42UT6IY-CBoWxpDv.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-zE8lyaWe.js → wardleyDiagram-YWT4CUSO-B_eVqdhC.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DsdjuSxQ.js → xychartDiagram-2RQKCTM6-DeZzEX0f.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +54 -25
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +1 -1
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/channel-CeYcnOtQ.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CZwh2k1X.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CZwh2k1X.js +0 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/.bundled.reload-3.js +0 -19167
package/dist/bin.js
CHANGED
|
@@ -32882,14 +32882,17 @@ function deepStripNulChars(value) {
|
|
|
32882
32882
|
return stripNulChars(value);
|
|
32883
32883
|
}
|
|
32884
32884
|
if (Array.isArray(value)) {
|
|
32885
|
-
|
|
32885
|
+
const sanitized = value.map(deepStripNulChars);
|
|
32886
|
+
return sanitized.some((entry, index3) => entry !== value[index3]) ? sanitized : value;
|
|
32886
32887
|
}
|
|
32887
32888
|
if (value !== null && typeof value === "object") {
|
|
32888
|
-
|
|
32889
|
-
|
|
32890
|
-
|
|
32891
|
-
)
|
|
32892
|
-
);
|
|
32889
|
+
const entries = Object.entries(value);
|
|
32890
|
+
const sanitizedEntries = entries.map(([key, entry]) => [
|
|
32891
|
+
stripNulChars(key),
|
|
32892
|
+
deepStripNulChars(entry)
|
|
32893
|
+
]);
|
|
32894
|
+
const changed = sanitizedEntries.some(([key, entry], index3) => key !== entries[index3]?.[0] || entry !== entries[index3]?.[1]);
|
|
32895
|
+
return changed ? Object.fromEntries(sanitizedEntries) : value;
|
|
32893
32896
|
}
|
|
32894
32897
|
return value;
|
|
32895
32898
|
}
|
|
@@ -124947,24 +124950,28 @@ function rowToRoomMessage(row) {
|
|
|
124947
124950
|
};
|
|
124948
124951
|
}
|
|
124949
124952
|
async function createChatSession(handle, session) {
|
|
124953
|
+
const sanitized = {
|
|
124954
|
+
...session,
|
|
124955
|
+
inFlightGeneration: sanitizeJsonbValue(session.inFlightGeneration)
|
|
124956
|
+
};
|
|
124950
124957
|
await handle.insert(project_exports.chatSessions).values({
|
|
124951
|
-
id:
|
|
124952
|
-
agentId:
|
|
124953
|
-
title:
|
|
124954
|
-
status:
|
|
124958
|
+
id: sanitized.id,
|
|
124959
|
+
agentId: sanitized.agentId,
|
|
124960
|
+
title: sanitized.title,
|
|
124961
|
+
status: sanitized.status,
|
|
124955
124962
|
// FNXC:MultiProjectIsolation 2026-07-15-23:40: write the caller's domain project to owner_project_id and never project_id — the trigger/GUC owns the partition.
|
|
124956
|
-
ownerProjectId:
|
|
124957
|
-
modelProvider:
|
|
124958
|
-
modelId:
|
|
124959
|
-
thinkingLevel:
|
|
124960
|
-
createdAt:
|
|
124961
|
-
updatedAt:
|
|
124962
|
-
pinnedAt:
|
|
124963
|
-
cliSessionFile:
|
|
124964
|
-
inFlightGeneration:
|
|
124965
|
-
cliExecutorAdapterId:
|
|
124963
|
+
ownerProjectId: sanitized.projectId,
|
|
124964
|
+
modelProvider: sanitized.modelProvider,
|
|
124965
|
+
modelId: sanitized.modelId,
|
|
124966
|
+
thinkingLevel: sanitized.thinkingLevel ?? null,
|
|
124967
|
+
createdAt: sanitized.createdAt,
|
|
124968
|
+
updatedAt: sanitized.updatedAt,
|
|
124969
|
+
pinnedAt: sanitized.pinnedAt,
|
|
124970
|
+
cliSessionFile: sanitized.cliSessionFile,
|
|
124971
|
+
inFlightGeneration: sanitized.inFlightGeneration,
|
|
124972
|
+
cliExecutorAdapterId: sanitized.cliExecutorAdapterId
|
|
124966
124973
|
});
|
|
124967
|
-
return
|
|
124974
|
+
return sanitized;
|
|
124968
124975
|
}
|
|
124969
124976
|
async function getChatSession(handle, id) {
|
|
124970
124977
|
const rows = await handle.select().from(project_exports.chatSessions).where(eq(project_exports.chatSessions.id, id));
|
|
@@ -125272,7 +125279,8 @@ async function setCliExecutorAdapterId(handle, id, adapterId) {
|
|
|
125272
125279
|
async function setInFlightGeneration(handle, id, inFlightGeneration) {
|
|
125273
125280
|
const existing = await getChatSession(handle, id);
|
|
125274
125281
|
if (!existing) return void 0;
|
|
125275
|
-
|
|
125282
|
+
const sanitizedInFlightGeneration = sanitizeJsonbValue(inFlightGeneration);
|
|
125283
|
+
await handle.update(project_exports.chatSessions).set({ inFlightGeneration: sanitizedInFlightGeneration }).where(eq(project_exports.chatSessions.id, id));
|
|
125276
125284
|
return getChatSession(handle, id);
|
|
125277
125285
|
}
|
|
125278
125286
|
async function addChatMessageAttachment(handle, sessionId, messageId, attachment) {
|
|
@@ -125280,7 +125288,10 @@ async function addChatMessageAttachment(handle, sessionId, messageId, attachment
|
|
|
125280
125288
|
if (!message || message.sessionId !== sessionId) {
|
|
125281
125289
|
throw new Error(`Message ${messageId} not found in session ${sessionId}`);
|
|
125282
125290
|
}
|
|
125283
|
-
const updatedAttachments = [
|
|
125291
|
+
const updatedAttachments = sanitizeJsonbValue([
|
|
125292
|
+
...message.attachments ?? [],
|
|
125293
|
+
attachment
|
|
125294
|
+
]);
|
|
125284
125295
|
await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(eq(project_exports.chatMessages.id, messageId));
|
|
125285
125296
|
const updated = await getChatMessage(handle, messageId);
|
|
125286
125297
|
if (!updated) throw new Error(`Failed to update message ${messageId}`);
|
|
@@ -125343,7 +125354,7 @@ async function updateChatMessageMetadata(handle, messageId, metadata, options) {
|
|
|
125343
125354
|
}
|
|
125344
125355
|
const merge2 = options?.merge !== false;
|
|
125345
125356
|
const nextMetadata = metadata === null ? merge2 ? existing.metadata : null : merge2 ? { ...existing.metadata ?? {}, ...metadata } : metadata;
|
|
125346
|
-
await handle.update(project_exports.chatMessages).set({ metadata: nextMetadata ?? null }).where(eq(project_exports.chatMessages.id, messageId));
|
|
125357
|
+
await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(eq(project_exports.chatMessages.id, messageId));
|
|
125347
125358
|
const updated = await getChatMessage(handle, messageId);
|
|
125348
125359
|
if (!updated) {
|
|
125349
125360
|
throw new Error(`Failed to update message ${messageId}`);
|
|
@@ -125412,7 +125423,10 @@ async function addChatRoomMessageAttachment(handle, roomId, messageId, attachmen
|
|
|
125412
125423
|
if (!message || message.roomId !== roomId) {
|
|
125413
125424
|
throw new Error(`Message ${messageId} not found in room ${roomId}`);
|
|
125414
125425
|
}
|
|
125415
|
-
const updatedAttachments = [
|
|
125426
|
+
const updatedAttachments = sanitizeJsonbValue([
|
|
125427
|
+
...message.attachments ?? [],
|
|
125428
|
+
attachment
|
|
125429
|
+
]);
|
|
125416
125430
|
await handle.update(project_exports.chatRoomMessages).set({ attachments: updatedAttachments }).where(eq(project_exports.chatRoomMessages.id, messageId));
|
|
125417
125431
|
await handle.update(project_exports.chatRooms).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(project_exports.chatRooms.id, roomId));
|
|
125418
125432
|
const updated = await getChatRoomMessage(handle, messageId);
|
|
@@ -134435,6 +134449,19 @@ async function seedPreReleasePlanReviewContinuation(store, task, ir2, options =
|
|
|
134435
134449
|
const item = await store.replaceActiveTaskWorkflowContinuation(input);
|
|
134436
134450
|
return { seeded: true, workItemId: item.id };
|
|
134437
134451
|
}
|
|
134452
|
+
async function resumeApprovedPlanReviewHandoff(store, task, ir2) {
|
|
134453
|
+
const node = resolvePreReleasePlanReviewNode(ir2);
|
|
134454
|
+
if (!node || node.column !== task.column) return { resumed: false, reason: "not-plan-in-place" };
|
|
134455
|
+
if (isTaskBlockedOnApproval(task)) return { resumed: false, reason: "awaiting-approval" };
|
|
134456
|
+
if (task.paused === true || task.userPaused === true) return { resumed: false, reason: "paused" };
|
|
134457
|
+
if (task.status === "needs-replan") return { resumed: false, reason: "needs-replan" };
|
|
134458
|
+
const seeded = await seedPreReleasePlanReviewContinuation(store, task, ir2, { atomic: true });
|
|
134459
|
+
if (seeded.seeded) return { resumed: true, reason: "seeded", workItemId: seeded.workItemId };
|
|
134460
|
+
return {
|
|
134461
|
+
resumed: false,
|
|
134462
|
+
reason: seeded.reason ?? "not-plan-in-place"
|
|
134463
|
+
};
|
|
134464
|
+
}
|
|
134438
134465
|
function evaluateStrandedHoldContinuation(input) {
|
|
134439
134466
|
if (!input.columnFlags.hold) return { stranded: false, candidate: false, reason: "not-hold-column" };
|
|
134440
134467
|
const review = resolvePreReleasePlanReviewNode(input.ir);
|
|
@@ -268177,6 +268204,7 @@ __export(src_exports2, {
|
|
|
268177
268204
|
resolveWorkspaceTaskRevertCommits: () => resolveWorkspaceTaskRevertCommits,
|
|
268178
268205
|
resolveWorktrunkBinary: () => resolveWorktrunkBinary,
|
|
268179
268206
|
restoreUnrelatedRootDirChanges: () => restoreUnrelatedRootDirChanges,
|
|
268207
|
+
resumeApprovedPlanReviewHandoff: () => resumeApprovedPlanReviewHandoff,
|
|
268180
268208
|
revertWorkspaceTask: () => revertWorkspaceTask,
|
|
268181
268209
|
reviewStep: () => reviewStep,
|
|
268182
268210
|
runAiMerge: () => runAiMerge,
|
|
@@ -268381,6 +268409,7 @@ var init_src5 = __esm({
|
|
|
268381
268409
|
init_remote_node_client();
|
|
268382
268410
|
init_remote_node_runtime();
|
|
268383
268411
|
init_hold_release();
|
|
268412
|
+
init_plan_review_continuation();
|
|
268384
268413
|
init_step_session_executor();
|
|
268385
268414
|
init_step_runner();
|
|
268386
268415
|
init_pty_native();
|
|
@@ -292320,6 +292349,7 @@ var init_auth_middleware = __esm({
|
|
|
292320
292349
|
});
|
|
292321
292350
|
|
|
292322
292351
|
// ../dashboard/src/routes/register-task-workflow-routes.ts
|
|
292352
|
+
import { createHash as createHash29 } from "node:crypto";
|
|
292323
292353
|
import { createReadStream } from "node:fs";
|
|
292324
292354
|
import { readFile as readFile46, stat as stat11 } from "node:fs/promises";
|
|
292325
292355
|
import { join as join89 } from "node:path";
|
|
@@ -292672,7 +292702,71 @@ function buildReviewerAgentItemId(input) {
|
|
|
292672
292702
|
const timePart = (input.createdAt ?? "na").replace(/[:.]/g, "-");
|
|
292673
292703
|
return `reviewer-${input.reviewType}-${stepPart}-${verdictPart}-${timePart}-${input.index + 1}`;
|
|
292674
292704
|
}
|
|
292705
|
+
function parseTaskReviewVerdict(value) {
|
|
292706
|
+
switch (value) {
|
|
292707
|
+
case "APPROVE":
|
|
292708
|
+
case "APPROVE_WITH_NOTES":
|
|
292709
|
+
case "REVISE":
|
|
292710
|
+
case "RETHINK":
|
|
292711
|
+
case "UNAVAILABLE":
|
|
292712
|
+
return value;
|
|
292713
|
+
default:
|
|
292714
|
+
return void 0;
|
|
292715
|
+
}
|
|
292716
|
+
}
|
|
292717
|
+
function isCurrentWorkflowReviewResult(result2) {
|
|
292718
|
+
return CURRENT_WORKFLOW_REVIEW_STEP_IDS.has(result2.workflowStepId) && CURRENT_WORKFLOW_REVIEW_STATUSES.has(result2.status) && result2.verdict !== void 0 && result2.supersededAt === void 0 && result2.bypassedBy === void 0 && result2.bypassedAt === void 0 && result2.bypassReason === void 0 && result2.bypassedFromStatus === void 0 && result2.bypassedFromVerdict === void 0;
|
|
292719
|
+
}
|
|
292720
|
+
function buildWorkflowReviewItemId(task, result2) {
|
|
292721
|
+
const identity = JSON.stringify({
|
|
292722
|
+
taskId: task.id,
|
|
292723
|
+
workflowStepId: result2.workflowStepId,
|
|
292724
|
+
workflowStepName: result2.workflowStepName,
|
|
292725
|
+
phase: result2.phase,
|
|
292726
|
+
status: result2.status,
|
|
292727
|
+
verdict: result2.verdict,
|
|
292728
|
+
completedAt: result2.completedAt,
|
|
292729
|
+
startedAt: result2.startedAt,
|
|
292730
|
+
output: result2.output,
|
|
292731
|
+
notes: result2.notes
|
|
292732
|
+
});
|
|
292733
|
+
return `workflow-review-${createHash29("sha256").update(identity).digest("hex").slice(0, 24)}`;
|
|
292734
|
+
}
|
|
292735
|
+
function buildWorkflowReviewItems(task) {
|
|
292736
|
+
return (task.workflowStepResults ?? []).filter(isCurrentWorkflowReviewResult).map((result2) => {
|
|
292737
|
+
const reviewType = result2.workflowStepId === "plan-review" ? "plan" : "code";
|
|
292738
|
+
const body = result2.output?.trim() || result2.notes?.trim() || "No written feedback was provided by this review step.";
|
|
292739
|
+
const timestamp2 = result2.completedAt ?? result2.startedAt ?? task.updatedAt ?? task.createdAt;
|
|
292740
|
+
return {
|
|
292741
|
+
itemId: buildWorkflowReviewItemId(task, result2),
|
|
292742
|
+
sourceMode: "reviewer-agent",
|
|
292743
|
+
title: `${result2.workflowStepName || result2.workflowStepId} ${result2.verdict}`,
|
|
292744
|
+
body,
|
|
292745
|
+
author: "reviewer-agent",
|
|
292746
|
+
createdAt: timestamp2,
|
|
292747
|
+
updatedAt: timestamp2,
|
|
292748
|
+
reviewState: result2.verdict,
|
|
292749
|
+
verdict: result2.verdict,
|
|
292750
|
+
reviewType,
|
|
292751
|
+
progressStatus: null
|
|
292752
|
+
};
|
|
292753
|
+
}).sort((a, b3) => Date.parse(b3.createdAt ?? "") - Date.parse(a.createdAt ?? "") || a.itemId.localeCompare(b3.itemId));
|
|
292754
|
+
}
|
|
292755
|
+
function buildDirectReviewSummary(items) {
|
|
292756
|
+
const latest = items[0];
|
|
292757
|
+
return latest ? { summary: latest.title, verdict: latest.verdict } : null;
|
|
292758
|
+
}
|
|
292675
292759
|
async function buildDirectTaskReviewData(task, store) {
|
|
292760
|
+
const structuredItems = buildWorkflowReviewItems(task);
|
|
292761
|
+
if (structuredItems.length > 0) {
|
|
292762
|
+
return {
|
|
292763
|
+
mode: "reviewer-agent",
|
|
292764
|
+
refreshable: true,
|
|
292765
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
292766
|
+
summary: buildDirectReviewSummary(structuredItems),
|
|
292767
|
+
items: structuredItems
|
|
292768
|
+
};
|
|
292769
|
+
}
|
|
292676
292770
|
const agentLogs = await store.getAgentLogs(task.id);
|
|
292677
292771
|
const reviewerText = agentLogs.filter((entry) => entry.agent === "reviewer" && entry.type === "text").map((entry) => entry.text).join("\n");
|
|
292678
292772
|
const fallbackLogs = (task.log ?? []).filter((entry) => REVIEW_STEP_RE.test(entry.action));
|
|
@@ -292694,6 +292788,8 @@ async function buildDirectTaskReviewData(task, store) {
|
|
|
292694
292788
|
createdAt,
|
|
292695
292789
|
updatedAt: createdAt,
|
|
292696
292790
|
reviewState: verdict ?? null,
|
|
292791
|
+
verdict: parseTaskReviewVerdict(verdict),
|
|
292792
|
+
reviewType,
|
|
292697
292793
|
progressStatus: null
|
|
292698
292794
|
});
|
|
292699
292795
|
}
|
|
@@ -292711,21 +292807,18 @@ async function buildDirectTaskReviewData(task, store) {
|
|
|
292711
292807
|
createdAt: entry.timestamp,
|
|
292712
292808
|
updatedAt: entry.timestamp,
|
|
292713
292809
|
reviewState: verdict ?? null,
|
|
292810
|
+
verdict: parseTaskReviewVerdict(verdict),
|
|
292811
|
+
reviewType,
|
|
292714
292812
|
progressStatus: null
|
|
292715
292813
|
});
|
|
292716
292814
|
});
|
|
292717
292815
|
}
|
|
292718
|
-
const sorted = [...items].sort((a, b3) => Date.parse(b3.createdAt ?? "") - Date.parse(a.createdAt ?? ""));
|
|
292719
|
-
const latest = sorted[0];
|
|
292720
|
-
const summary = latest ? {
|
|
292721
|
-
summary: latest.title,
|
|
292722
|
-
verdict: latest.reviewState ?? void 0
|
|
292723
|
-
} : null;
|
|
292816
|
+
const sorted = [...items].sort((a, b3) => Date.parse(b3.createdAt ?? "") - Date.parse(a.createdAt ?? "") || a.itemId.localeCompare(b3.itemId));
|
|
292724
292817
|
return {
|
|
292725
292818
|
mode: "reviewer-agent",
|
|
292726
292819
|
refreshable: true,
|
|
292727
292820
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
292728
|
-
summary,
|
|
292821
|
+
summary: buildDirectReviewSummary(sorted),
|
|
292729
292822
|
items: sorted
|
|
292730
292823
|
};
|
|
292731
292824
|
}
|
|
@@ -294942,6 +295035,13 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
294942
295035
|
await scopedStore.moveTask(task.id, reboundColumn);
|
|
294943
295036
|
}
|
|
294944
295037
|
const approved = await scopedStore.updateTask(task.id, approvalPatch);
|
|
295038
|
+
const approvedWorkflow = await resolveWorkflowIrForTask(scopedStore, approved.id);
|
|
295039
|
+
const handoff = await resumeApprovedPlanReviewHandoff(
|
|
295040
|
+
scopedStore,
|
|
295041
|
+
approved,
|
|
295042
|
+
approvedWorkflow
|
|
295043
|
+
);
|
|
295044
|
+
void handoff;
|
|
294945
295045
|
await scopedStore.logEntry(task.id, "Plan approved by user").catch((error3) => {
|
|
294946
295046
|
severityAuditLog33.warn(`Failed to record plan approval activity for ${task.id}: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
294947
295047
|
});
|
|
@@ -296335,7 +296435,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296335
296435
|
const selectedItems = Array.isArray(req.body?.selectedItems) ? req.body.selectedItems.filter((value) => {
|
|
296336
296436
|
if (!value || typeof value !== "object") return false;
|
|
296337
296437
|
const item = value;
|
|
296338
|
-
return typeof item.id === "string" && item.id.trim().length > 0 && typeof item.
|
|
296438
|
+
return typeof item.id === "string" && item.id.trim().length > 0 && typeof item.source === "string";
|
|
296339
296439
|
}) : [];
|
|
296340
296440
|
if (selectedItems.length === 0) {
|
|
296341
296441
|
throw badRequest("selectedItems must be a non-empty array of review items");
|
|
@@ -296370,7 +296470,9 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296370
296470
|
htmlUrl: item.url,
|
|
296371
296471
|
state: item.reviewState ?? void 0,
|
|
296372
296472
|
isResolved: item.isResolved,
|
|
296373
|
-
source: item.sourceMode === "reviewer-agent" ? "reviewer-agent" : "github-pr"
|
|
296473
|
+
source: item.sourceMode === "reviewer-agent" ? "reviewer-agent" : "github-pr",
|
|
296474
|
+
verdict: item.verdict,
|
|
296475
|
+
reviewType: item.reviewType
|
|
296374
296476
|
}));
|
|
296375
296477
|
const reviewState = {
|
|
296376
296478
|
source: canonicalReviewData.mode,
|
|
@@ -296394,8 +296496,24 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296394
296496
|
if (hasUnknownSelection) {
|
|
296395
296497
|
throw badRequest("selectedItems must reference existing review items");
|
|
296396
296498
|
}
|
|
296397
|
-
const
|
|
296398
|
-
const
|
|
296499
|
+
const canonicalById = new Map(reviewState.items.map((item) => [item.id, item]));
|
|
296500
|
+
const canonicalSelections = selectedItems.map((selected) => {
|
|
296501
|
+
const item = canonicalById.get(selected.id);
|
|
296502
|
+
if (!item) throw badRequest("selectedItems must reference existing review items");
|
|
296503
|
+
return {
|
|
296504
|
+
id: item.id,
|
|
296505
|
+
source: expectedSource,
|
|
296506
|
+
summary: item.summary ?? item.body.slice(0, 120),
|
|
296507
|
+
body: item.body,
|
|
296508
|
+
author: item.author.login,
|
|
296509
|
+
filePath: item.path,
|
|
296510
|
+
lineNumber: item.line,
|
|
296511
|
+
threadId: item.threadId,
|
|
296512
|
+
url: item.htmlUrl
|
|
296513
|
+
};
|
|
296514
|
+
});
|
|
296515
|
+
const modeSummary = `${reviewState.source === "pull-request" ? "pull-request" : "reviewer-agent"} \xB7 ${canonicalSelections.length} selected item(s)`;
|
|
296516
|
+
const steeringItems = canonicalSelections.map((item, index3) => {
|
|
296399
296517
|
const location = item.filePath ? `${item.filePath}${typeof item.lineNumber === "number" ? `:${item.lineNumber}` : ""}` : void 0;
|
|
296400
296518
|
const snippetSource = item.body.trim() || item.summary.trim();
|
|
296401
296519
|
const snippet = snippetSource.length > 220 ? `${snippetSource.slice(0, 220)}\u2026` : snippetSource;
|
|
@@ -296406,7 +296524,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296406
296524
|
const priorAddressingById = new Map(reviewState.addressing.map((record2) => [record2.itemId, record2]));
|
|
296407
296525
|
const nextAddressing = [
|
|
296408
296526
|
...reviewState.addressing.filter((record2) => !selectedSet.has(record2.itemId)),
|
|
296409
|
-
...
|
|
296527
|
+
...canonicalSelections.map((item) => {
|
|
296410
296528
|
const existing = priorAddressingById.get(item.id);
|
|
296411
296529
|
return {
|
|
296412
296530
|
itemId: item.id,
|
|
@@ -296717,7 +296835,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
296717
296835
|
}
|
|
296718
296836
|
});
|
|
296719
296837
|
}
|
|
296720
|
-
var severityAuditLog33, AWAITING_PLANNING_ENRICH_LIMIT, LEGACY_WIP_LANES3, LEGACY_ARCHIVE_LANES5, REVIEW_BLOCK_RE, REVIEW_VERDICT_RE, REVIEW_STEP_RE, DUPLICATE_STOPWORDS, ARTIFACT_TYPES, ADDRESS_PR_FEEDBACK_PROMPT, __fingerprintCreateLocksForTests, RESET_TASK_FIELDS, RESET_DRIFT_CORRECTION_FIELDS;
|
|
296838
|
+
var severityAuditLog33, AWAITING_PLANNING_ENRICH_LIMIT, LEGACY_WIP_LANES3, LEGACY_ARCHIVE_LANES5, REVIEW_BLOCK_RE, REVIEW_VERDICT_RE, REVIEW_STEP_RE, DUPLICATE_STOPWORDS, ARTIFACT_TYPES, ADDRESS_PR_FEEDBACK_PROMPT, __fingerprintCreateLocksForTests, RESET_TASK_FIELDS, RESET_DRIFT_CORRECTION_FIELDS, CURRENT_WORKFLOW_REVIEW_STEP_IDS, CURRENT_WORKFLOW_REVIEW_STATUSES;
|
|
296721
296839
|
var init_register_task_workflow_routes = __esm({
|
|
296722
296840
|
"../dashboard/src/routes/register-task-workflow-routes.ts"() {
|
|
296723
296841
|
"use strict";
|
|
@@ -296779,6 +296897,8 @@ var init_register_task_workflow_routes = __esm({
|
|
|
296779
296897
|
worktreeSessionRetryCount: null,
|
|
296780
296898
|
sessionFile: null
|
|
296781
296899
|
};
|
|
296900
|
+
CURRENT_WORKFLOW_REVIEW_STEP_IDS = /* @__PURE__ */ new Set(["code-review", "plan-review"]);
|
|
296901
|
+
CURRENT_WORKFLOW_REVIEW_STATUSES = /* @__PURE__ */ new Set(["passed", "failed", "advisory_failure"]);
|
|
296782
296902
|
}
|
|
296783
296903
|
});
|
|
296784
296904
|
|
|
@@ -300695,6 +300815,22 @@ When you need structured input, or whenever you present options, choices, or a d
|
|
|
300695
300815
|
this.cliChatRunner = runner;
|
|
300696
300816
|
this.cliChatProjectId = projectId;
|
|
300697
300817
|
}
|
|
300818
|
+
/*
|
|
300819
|
+
FNXC:ChatPersistence 2026-08-05-01:54:
|
|
300820
|
+
Checkpoint snapshots contain environment-controlled tool output. Persistence
|
|
300821
|
+
is best-effort for crash recovery, but every fire-and-forget write must have
|
|
300822
|
+
its rejection observed so one failed jsonb write cannot become a process-wide
|
|
300823
|
+
unhandled rejection or interrupt the streaming turn.
|
|
300824
|
+
*/
|
|
300825
|
+
persistInFlightGeneration(sessionId, snapshot) {
|
|
300826
|
+
try {
|
|
300827
|
+
void this.chatStore.setInFlightGeneration(sessionId, snapshot).catch(() => {
|
|
300828
|
+
diagnostics6.warn(`Failed to persist in-flight chat checkpoint for session ${sessionId}`);
|
|
300829
|
+
});
|
|
300830
|
+
} catch {
|
|
300831
|
+
diagnostics6.warn(`Failed to persist in-flight chat checkpoint for session ${sessionId}`);
|
|
300832
|
+
}
|
|
300833
|
+
}
|
|
300698
300834
|
queueInFlightGenerationPersist(sessionId, snapshot) {
|
|
300699
300835
|
const existingTimer = this.inFlightPersistTimers.get(sessionId);
|
|
300700
300836
|
if (existingTimer) {
|
|
@@ -300702,7 +300838,7 @@ When you need structured input, or whenever you present options, choices, or a d
|
|
|
300702
300838
|
}
|
|
300703
300839
|
const timer2 = setTimeout(() => {
|
|
300704
300840
|
this.inFlightPersistTimers.delete(sessionId);
|
|
300705
|
-
this.
|
|
300841
|
+
this.persistInFlightGeneration(sessionId, snapshot);
|
|
300706
300842
|
}, IN_FLIGHT_PERSIST_DEBOUNCE_MS);
|
|
300707
300843
|
this.inFlightPersistTimers.set(sessionId, timer2);
|
|
300708
300844
|
}
|
|
@@ -300712,7 +300848,7 @@ When you need structured input, or whenever you present options, choices, or a d
|
|
|
300712
300848
|
clearTimeout(existingTimer);
|
|
300713
300849
|
this.inFlightPersistTimers.delete(sessionId);
|
|
300714
300850
|
}
|
|
300715
|
-
this.
|
|
300851
|
+
this.persistInFlightGeneration(sessionId, snapshot);
|
|
300716
300852
|
}
|
|
300717
300853
|
async getChatModelSettings() {
|
|
300718
300854
|
if (!this.getSettings) {
|
|
@@ -341606,8 +341742,8 @@ var init_register_settings_sync_routes = __esm({
|
|
|
341606
341742
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
341607
341743
|
version: 1
|
|
341608
341744
|
};
|
|
341609
|
-
const { createHash:
|
|
341610
|
-
const checksum =
|
|
341745
|
+
const { createHash: createHash32 } = await import("node:crypto");
|
|
341746
|
+
const checksum = createHash32("sha256").update(JSON.stringify(payloadWithoutChecksum)).digest("hex");
|
|
341611
341747
|
const localPeerInfo = await central.getLocalPeerInfo();
|
|
341612
341748
|
await fetchFromRemoteNode(node, "/api/settings/sync-receive", {
|
|
341613
341749
|
method: "POST",
|
|
@@ -341678,7 +341814,7 @@ var init_register_settings_sync_routes = __esm({
|
|
|
341678
341814
|
});
|
|
341679
341815
|
return;
|
|
341680
341816
|
}
|
|
341681
|
-
const { createHash:
|
|
341817
|
+
const { createHash: createHash32 } = await import("node:crypto");
|
|
341682
341818
|
const exportedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
341683
341819
|
const payloadWithoutChecksum = {
|
|
341684
341820
|
global: remoteSettings.global,
|
|
@@ -341687,7 +341823,7 @@ var init_register_settings_sync_routes = __esm({
|
|
|
341687
341823
|
exportedAt,
|
|
341688
341824
|
version: 1
|
|
341689
341825
|
};
|
|
341690
|
-
const checksum =
|
|
341826
|
+
const checksum = createHash32("sha256").update(JSON.stringify(payloadWithoutChecksum)).digest("hex");
|
|
341691
341827
|
const result2 = await central.applyRemoteSettings({
|
|
341692
341828
|
...payloadWithoutChecksum,
|
|
341693
341829
|
checksum
|
|
@@ -368064,7 +368200,7 @@ var init_report_scrub = __esm({
|
|
|
368064
368200
|
});
|
|
368065
368201
|
|
|
368066
368202
|
// ../dashboard/src/report-pipeline.ts
|
|
368067
|
-
import { createHash as
|
|
368203
|
+
import { createHash as createHash30 } from "node:crypto";
|
|
368068
368204
|
function resolveReportMode(actionType, settings) {
|
|
368069
368205
|
return settings.reportModeByAction?.[actionType] ?? settings.reportMode ?? "draft-review";
|
|
368070
368206
|
}
|
|
@@ -368180,7 +368316,7 @@ async function embedScreenshot(args) {
|
|
|
368180
368316
|
try {
|
|
368181
368317
|
const extension = EXT_BY_MIME[attachment.mimeType];
|
|
368182
368318
|
if (!extension) return args.report;
|
|
368183
|
-
const safeId2 =
|
|
368319
|
+
const safeId2 = createHash30("sha256").update(`${args.report.sessionToken ?? ""}:${attachment.artifactId}`).digest("hex").slice(0, 32);
|
|
368184
368320
|
const path14 = `.fusion-reports/${safeId2}/screenshot.${extension}`;
|
|
368185
368321
|
const uploaded = await args.client.uploadImageAsset({ owner: args.owner, repo: args.repo, path: path14, contentBase64: Buffer.from(attachment.bytes).toString("base64"), message: "chore: add Fusion report screenshot", mimeType: attachment.mimeType });
|
|
368186
368322
|
const alt = markdownEscapeImageAlt(scrubReportText(attachment.filename, args.scrubContext) || "Report screenshot");
|
|
@@ -371283,7 +371419,7 @@ var init_types6 = __esm({
|
|
|
371283
371419
|
});
|
|
371284
371420
|
|
|
371285
371421
|
// ../dashboard/src/stt/model-manager.ts
|
|
371286
|
-
import { createHash as
|
|
371422
|
+
import { createHash as createHash31, randomUUID as randomUUID64 } from "node:crypto";
|
|
371287
371423
|
import { mkdir as mkdir38, open as open4, readFile as readFile56, readdir as readdir14, rename as rename10, rm as rm21, stat as stat16, writeFile as writeFile37 } from "node:fs/promises";
|
|
371288
371424
|
import { join as join118, relative as relative22, resolve as resolve68, sep as sep18 } from "node:path";
|
|
371289
371425
|
function parseSafeTarListing(listing) {
|
|
@@ -371372,7 +371508,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
371372
371508
|
if (!response.ok || !response.body) throw Object.assign(new Error("download failed"), { voiceReason: "network" });
|
|
371373
371509
|
if (!current(g2, signal)) return state;
|
|
371374
371510
|
const total = Number(response.headers.get("content-length")) || void 0;
|
|
371375
|
-
const hash =
|
|
371511
|
+
const hash = createHash31("sha256");
|
|
371376
371512
|
let bytes = 0;
|
|
371377
371513
|
for await (const chunk of response.body) {
|
|
371378
371514
|
if (!current(g2, signal)) return state;
|
|
@@ -32880,14 +32880,17 @@ function deepStripNulChars(value) {
|
|
|
32880
32880
|
return stripNulChars(value);
|
|
32881
32881
|
}
|
|
32882
32882
|
if (Array.isArray(value)) {
|
|
32883
|
-
|
|
32883
|
+
const sanitized = value.map(deepStripNulChars);
|
|
32884
|
+
return sanitized.some((entry, index2) => entry !== value[index2]) ? sanitized : value;
|
|
32884
32885
|
}
|
|
32885
32886
|
if (value !== null && typeof value === "object") {
|
|
32886
|
-
|
|
32887
|
-
|
|
32888
|
-
|
|
32889
|
-
)
|
|
32890
|
-
);
|
|
32887
|
+
const entries = Object.entries(value);
|
|
32888
|
+
const sanitizedEntries = entries.map(([key, entry]) => [
|
|
32889
|
+
stripNulChars(key),
|
|
32890
|
+
deepStripNulChars(entry)
|
|
32891
|
+
]);
|
|
32892
|
+
const changed = sanitizedEntries.some(([key, entry], index2) => key !== entries[index2]?.[0] || entry !== entries[index2]?.[1]);
|
|
32893
|
+
return changed ? Object.fromEntries(sanitizedEntries) : value;
|
|
32891
32894
|
}
|
|
32892
32895
|
return value;
|
|
32893
32896
|
}
|
|
@@ -124945,24 +124948,28 @@ function rowToRoomMessage(row) {
|
|
|
124945
124948
|
};
|
|
124946
124949
|
}
|
|
124947
124950
|
async function createChatSession(handle, session) {
|
|
124951
|
+
const sanitized = {
|
|
124952
|
+
...session,
|
|
124953
|
+
inFlightGeneration: sanitizeJsonbValue(session.inFlightGeneration)
|
|
124954
|
+
};
|
|
124948
124955
|
await handle.insert(project_exports.chatSessions).values({
|
|
124949
|
-
id:
|
|
124950
|
-
agentId:
|
|
124951
|
-
title:
|
|
124952
|
-
status:
|
|
124956
|
+
id: sanitized.id,
|
|
124957
|
+
agentId: sanitized.agentId,
|
|
124958
|
+
title: sanitized.title,
|
|
124959
|
+
status: sanitized.status,
|
|
124953
124960
|
// FNXC:MultiProjectIsolation 2026-07-15-23:40: write the caller's domain project to owner_project_id and never project_id — the trigger/GUC owns the partition.
|
|
124954
|
-
ownerProjectId:
|
|
124955
|
-
modelProvider:
|
|
124956
|
-
modelId:
|
|
124957
|
-
thinkingLevel:
|
|
124958
|
-
createdAt:
|
|
124959
|
-
updatedAt:
|
|
124960
|
-
pinnedAt:
|
|
124961
|
-
cliSessionFile:
|
|
124962
|
-
inFlightGeneration:
|
|
124963
|
-
cliExecutorAdapterId:
|
|
124961
|
+
ownerProjectId: sanitized.projectId,
|
|
124962
|
+
modelProvider: sanitized.modelProvider,
|
|
124963
|
+
modelId: sanitized.modelId,
|
|
124964
|
+
thinkingLevel: sanitized.thinkingLevel ?? null,
|
|
124965
|
+
createdAt: sanitized.createdAt,
|
|
124966
|
+
updatedAt: sanitized.updatedAt,
|
|
124967
|
+
pinnedAt: sanitized.pinnedAt,
|
|
124968
|
+
cliSessionFile: sanitized.cliSessionFile,
|
|
124969
|
+
inFlightGeneration: sanitized.inFlightGeneration,
|
|
124970
|
+
cliExecutorAdapterId: sanitized.cliExecutorAdapterId
|
|
124964
124971
|
});
|
|
124965
|
-
return
|
|
124972
|
+
return sanitized;
|
|
124966
124973
|
}
|
|
124967
124974
|
async function getChatSession(handle, id) {
|
|
124968
124975
|
const rows = await handle.select().from(project_exports.chatSessions).where(eq(project_exports.chatSessions.id, id));
|
|
@@ -125270,7 +125277,8 @@ async function setCliExecutorAdapterId(handle, id, adapterId) {
|
|
|
125270
125277
|
async function setInFlightGeneration(handle, id, inFlightGeneration) {
|
|
125271
125278
|
const existing = await getChatSession(handle, id);
|
|
125272
125279
|
if (!existing) return void 0;
|
|
125273
|
-
|
|
125280
|
+
const sanitizedInFlightGeneration = sanitizeJsonbValue(inFlightGeneration);
|
|
125281
|
+
await handle.update(project_exports.chatSessions).set({ inFlightGeneration: sanitizedInFlightGeneration }).where(eq(project_exports.chatSessions.id, id));
|
|
125274
125282
|
return getChatSession(handle, id);
|
|
125275
125283
|
}
|
|
125276
125284
|
async function addChatMessageAttachment(handle, sessionId, messageId, attachment) {
|
|
@@ -125278,7 +125286,10 @@ async function addChatMessageAttachment(handle, sessionId, messageId, attachment
|
|
|
125278
125286
|
if (!message || message.sessionId !== sessionId) {
|
|
125279
125287
|
throw new Error(`Message ${messageId} not found in session ${sessionId}`);
|
|
125280
125288
|
}
|
|
125281
|
-
const updatedAttachments = [
|
|
125289
|
+
const updatedAttachments = sanitizeJsonbValue([
|
|
125290
|
+
...message.attachments ?? [],
|
|
125291
|
+
attachment
|
|
125292
|
+
]);
|
|
125282
125293
|
await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(eq(project_exports.chatMessages.id, messageId));
|
|
125283
125294
|
const updated = await getChatMessage(handle, messageId);
|
|
125284
125295
|
if (!updated) throw new Error(`Failed to update message ${messageId}`);
|
|
@@ -125341,7 +125352,7 @@ async function updateChatMessageMetadata(handle, messageId, metadata, options) {
|
|
|
125341
125352
|
}
|
|
125342
125353
|
const merge2 = options?.merge !== false;
|
|
125343
125354
|
const nextMetadata = metadata === null ? merge2 ? existing.metadata : null : merge2 ? { ...existing.metadata ?? {}, ...metadata } : metadata;
|
|
125344
|
-
await handle.update(project_exports.chatMessages).set({ metadata: nextMetadata ?? null }).where(eq(project_exports.chatMessages.id, messageId));
|
|
125355
|
+
await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(eq(project_exports.chatMessages.id, messageId));
|
|
125345
125356
|
const updated = await getChatMessage(handle, messageId);
|
|
125346
125357
|
if (!updated) {
|
|
125347
125358
|
throw new Error(`Failed to update message ${messageId}`);
|
|
@@ -125410,7 +125421,10 @@ async function addChatRoomMessageAttachment(handle, roomId, messageId, attachmen
|
|
|
125410
125421
|
if (!message || message.roomId !== roomId) {
|
|
125411
125422
|
throw new Error(`Message ${messageId} not found in room ${roomId}`);
|
|
125412
125423
|
}
|
|
125413
|
-
const updatedAttachments = [
|
|
125424
|
+
const updatedAttachments = sanitizeJsonbValue([
|
|
125425
|
+
...message.attachments ?? [],
|
|
125426
|
+
attachment
|
|
125427
|
+
]);
|
|
125414
125428
|
await handle.update(project_exports.chatRoomMessages).set({ attachments: updatedAttachments }).where(eq(project_exports.chatRoomMessages.id, messageId));
|
|
125415
125429
|
await handle.update(project_exports.chatRooms).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(project_exports.chatRooms.id, roomId));
|
|
125416
125430
|
const updated = await getChatRoomMessage(handle, messageId);
|