@runfusion/fusion 0.76.0-beta.1 → 0.76.0-beta.3
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 +826 -272
- package/dist/child-process-worker.js +740 -249
- package/dist/client/.vite/manifest.json +261 -261
- package/dist/client/assets/{AgentDetailView-Cbl1sw6i.js → AgentDetailView-T767kKTg.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-DD1U5M9p.js → AgentPermissionPolicyEditor--u9jyUf2.js} +1 -1
- package/dist/client/assets/{AgentsView-BMcCbple.js → AgentsView-6Ifu7qDr.js} +5 -5
- package/dist/client/assets/ChatView-BV3lixQi.js +13 -0
- package/dist/client/assets/{CommandCenter-D7mcD61V.js → CommandCenter-CSRYoveB.js} +1 -1
- package/dist/client/assets/{DevServerView-DaqCn0p5.js → DevServerView-B9So_oYx.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-CLdqqqYN.js → DirectoryPicker-BhyDL_2m.js} +1 -1
- package/dist/client/assets/{DocumentsView-BOROVxPm.js → DocumentsView-pbERA7O-.js} +1 -1
- package/dist/client/assets/{EvalsView-BQMXRUlQ.js → EvalsView-DJQ4ltCg.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-1GNeCIQT.js → ExperimentalAgentOnboardingModal-BwJuzkzB.js} +1 -1
- package/dist/client/assets/{GoalsView-Cr3c_2GC.js → GoalsView-B6X5_0Ve.js} +1 -1
- package/dist/client/assets/InsightsView-CJgI0J7S.js +11 -0
- package/dist/client/assets/{InsightsView-Gn5lOBA0.css → InsightsView-DAAXuX4v.css} +1 -1
- package/dist/client/assets/{MemoryView-C0VzzMSw.js → MemoryView-BHq1AHPu.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-D1kkkVtP.js → PiExtensionsManager-B8At6fO8.js} +1 -1
- package/dist/client/assets/{PluginManager-BW-_Zyo5.js → PluginManager-k7hV7_9e.js} +1 -1
- package/dist/client/assets/{PullRequestView-Cmlo4nWA.js → PullRequestView-B1hZFrWo.js} +1 -1
- package/dist/client/assets/{ReportModal-BWuaroTF.js → ReportModal-C46V_zEa.js} +1 -1
- package/dist/client/assets/{ResearchView-BmkF_vZU.js → ResearchView-D8G85BYN.js} +2 -2
- package/dist/client/assets/{SecretsView-DVc8Hky0.js → SecretsView-CTri9LRK.js} +1 -1
- package/dist/client/assets/{SessionTerminal-DCXrxA57.js → SessionTerminal-BRf6r4Vp.js} +1 -1
- package/dist/client/assets/SettingsModal-D0RBeZik.js +21 -0
- package/dist/client/assets/{SettingsModal-DqwpLnDU.js → SettingsModal-rUQcSTJp.js} +1 -1
- package/dist/client/assets/{SettingsTextareaRow-B5spAoOY.js → SettingsTextareaRow-BirlBcem.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-VTBLyFzr.js → SetupWizardModal-xnCBM9EL.js} +2 -2
- package/dist/client/assets/{SkillsView-CR91ey9d.js → SkillsView-O5U0ep50.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-BzGh_Fd9.js → WorkflowNodeEditor-BX4d2qqF.js} +3 -3
- package/dist/client/assets/{agent-import-generation-D27NKQsr.js → agent-import-generation-DnqVkPkz.js} +1 -1
- package/dist/client/assets/{agentsOrgChartLayout-C2K_M3x3.js → agentsOrgChartLayout-CKuzbhFf.js} +1 -1
- package/dist/client/assets/app-B2FwULu2.js +5 -0
- package/dist/client/assets/{app-BA9gw9hx.js → app-B6nJaqAl.js} +2 -2
- package/dist/client/assets/{app-B_lScKc1.js → app-CGXZeIRc.js} +2 -2
- package/dist/client/assets/{app-DG_vjDw5.js → app-CGtkeBF5.js} +3 -3
- package/dist/client/assets/{app-GBgoY-oh.js → app-CNzN1Plu.js} +2 -2
- package/dist/client/assets/{app-B0KFGP8D.js → app-DLs-f5yM.js} +3 -3
- package/dist/client/assets/{app-DeHIOCEP.js → app-DsvtcRUG.js} +2 -2
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-BQy8UcRx.js → architectureDiagram-3BPJPVTR-gi467xY0.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-CZG1bqFQ.js → blockDiagram-GPEHLZMM-B_gpcYiR.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CZmO_kg3.js → c4Diagram-AAUBKEIU-DeylEYsQ.js} +1 -1
- package/dist/client/assets/channel-BoE8DeM4.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-jsad6DTE.js → chunk-2J33WTMH-BL2WY0HN.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-DX7SuvwP.js → chunk-4BX2VUAB-BkLExGMe.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-De20xFgU.js → chunk-55IACEB6-CSTvCF5T.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-CNiri9yW.js → chunk-727SXJPM-9J8pKk4x.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DvDqG-ax.js → chunk-AQP2D5EJ-DXC1vPWr.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DkMdKaUq.js → chunk-FMBD7UC4-CFRUb-zD.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-Do5BwIrI.js → chunk-ND2GUHAM-B87HFYS8.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-BnJgt9vl.js → chunk-QZHKN3VN-CTjHiGbd.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-qnbLX_9_.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-qnbLX_9_.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-D-ivAzzF.js → cose-bilkent-S5V4N54A-D3Edq3L9.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-Bpd9L0or.js → dagre-BM42HDAG-CwwbeQfN.js} +1 -1
- package/dist/client/assets/{dashboard-view-CgBo8Ctn.js → dashboard-view-BLAoW3D4.js} +1 -1
- package/dist/client/assets/{dashboard-view-DbaRE8Ma.js → dashboard-view-DAlJxqiJ.js} +1 -1
- package/dist/client/assets/{dashboard-view-DSvVO6Vr.js → dashboard-view-QxQwJFLz.js} +1 -1
- package/dist/client/assets/{dashboard-view-C-XU9CVv.js → dashboard-view-aPzfv99T.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-B6TT1NWU.js → diagram-2AECGRRQ-koJWWXE4.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-DpRS2yRw.js → diagram-5GNKFQAL-Yob5cOKT.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BVbZr02C.js → diagram-KO2AKTUF-DelvFSkK.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DzENbfal.js → diagram-LMA3HP47-CMput2h2.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BIePG5SY.js → diagram-OG6HWLK6-04VXDl79.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CQo3WBwo.js → erDiagram-TEJ5UH35-C9iP8Uyp.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Ct2H4jYo.js → flowDiagram-I6XJVG4X-DENQvu_t.js} +1 -1
- package/dist/client/assets/{folder-open-DAh8mpTX.js → folder-open-D-554oji.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DyOLCG4B.js → ganttDiagram-6RSMTGT7-BqOttZAT.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-sC28-su3.js → gitGraphDiagram-PVQCEYII-CDcydi-5.js} +1 -1
- package/dist/client/assets/{index-BzAldNrK.css → index-CXTd3LAB.css} +1 -1
- package/dist/client/assets/index-CtYRoouR.js +2818 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-Q81_5aBZ.js → infoDiagram-5YYISTIA-B5LQQnxt.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-Cwkjs0z5.js → ishikawaDiagram-YF4QCWOH-DpFEt7D2.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BXcBV1Bc.js → journeyDiagram-JHISSGLW-MELtgu22.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-BI7hW892.js → kanban-definition-UN3LZRKU-h33PLATd.js} +1 -1
- package/dist/client/assets/{mermaid.core-B8oDA6jj.js → mermaid.core-Dk2mUPOq.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-COG6_9eD.js → mindmap-definition-RKZ34NQL-B_T4O2-B.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-D11brZ_N.js → pieDiagram-4H26LBE5-B1YIFkRl.js} +1 -1
- package/dist/client/assets/{puzzle-D3_Z_rlW.js → puzzle-hvecxlpJ.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-jmhDVZcv.js → quadrantDiagram-W4KKPZXB-BoGQR_hO.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-BKCUWI1E.js → requirementDiagram-4Y6WPE33-BSDmUBIx.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-HsZdEl2t.js → sankeyDiagram-5OEKKPKP-Dz_GqOa5.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-CsDf7Fup.js → sequenceDiagram-3UESZ5HK-B6twjYUH.js} +1 -1
- package/dist/client/assets/{shield-alert-C16k8wNu.js → shield-alert-BX4WRJOv.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-BqAyftqe.js → standing-instructions-template-BJY317CC.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-fvzWhltB.js → stateDiagram-AJRCARHV-DuwqWLx-.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-cnt42Sr_.js → stateDiagram-v2-BHNVJYJU-Bu8Sk187.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DsZFCSMb.js → timeline-definition-PNZ67QCA-BS6VnqSI.js} +1 -1
- package/dist/client/assets/{upload-_s5sL5Pq.js → upload-CaDoyaMW.js} +1 -1
- package/dist/client/assets/{users-DH1U5ISc.js → users-C5uCLwVM.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-B3KDWS-e.js → vennDiagram-CIIHVFJN-CUbzqT5Y.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BKs5MtQS.js → wardley-L42UT6IY-Mv-NotFS.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CNsEoXVB.js → wardleyDiagram-YWT4CUSO-DuYpvLZX.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-kq_gW4QC.js → xychartDiagram-2RQKCTM6-24_7QXdw.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +932 -254
- package/dist/migrations/0057_fn_9004_project_ownership_default_reconciliation.sql +13 -0
- package/dist/migrations/0058_fn_9014_message_archive.sql +13 -0
- package/dist/pi-claude-cli/package.json +5 -5
- package/dist/plugin-sdk/index.d.ts +23 -0
- package/dist/plugin-sdk/index.js +71 -23
- package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +73 -25
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +71 -23
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +3 -3
- package/skill/fusion/SKILL.md +1 -1
- package/skill/fusion/references/extension-tools.md +22 -0
- package/skill/fusion/references/fusion-capabilities.md +2 -0
- package/dist/client/assets/ChatView-DcM-ARpZ.js +0 -13
- package/dist/client/assets/InsightsView-DgVBVQM4.js +0 -11
- package/dist/client/assets/SettingsModal-DZ32F1c-.js +0 -21
- package/dist/client/assets/app-DBCGrz-f.js +0 -5
- package/dist/client/assets/channel-Cwl9FefC.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BZtWCoHC.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BZtWCoHC.js +0 -1
- package/dist/client/assets/index-BlGpMJSZ.js +0 -2818
package/dist/bin.js
CHANGED
|
@@ -2184,6 +2184,8 @@ var init_settings_schema = __esm({
|
|
|
2184
2184
|
DEFAULT_PROJECT_SETTINGS = {
|
|
2185
2185
|
// FNXC:TaskRecommendations 2026-08-08-05:02: completion follows-ups stay bounded by default; 0 disables writing them.
|
|
2186
2186
|
maxRecommendationsPerTask: 3,
|
|
2187
|
+
// FNXC:TaskRecommendations 2026-08-13-03:56: surface completed-task proposals by default; operators can suppress the notice without suppressing capture.
|
|
2188
|
+
recommendationMailboxNoticeEnabled: true,
|
|
2187
2189
|
globalPause: false,
|
|
2188
2190
|
globalPauseReason: void 0,
|
|
2189
2191
|
defaultWorkflowId: void 0,
|
|
@@ -21756,9 +21758,14 @@ var init_project = __esm({
|
|
|
21756
21758
|
// now keyed per-project on `project_id` (the effective PK). `id` is retained
|
|
21757
21759
|
// for column-shape parity (always 1) but is no longer the PK and no longer
|
|
21758
21760
|
// CHECK-constrained. Single-project / SQLite-parity callers leave project_id
|
|
21759
|
-
//
|
|
21761
|
+
// through the database ownership trigger, preserving the pre-isolation behavior.
|
|
21762
|
+
/*
|
|
21763
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
21764
|
+
Migration 0006 owns config's project_id default and leaves its catalog PK as (project_id).
|
|
21765
|
+
Drizzle emits DEFAULT while the database GUC/trigger selects the effective ownership partition.
|
|
21766
|
+
*/
|
|
21760
21767
|
id: integer("id").default(1),
|
|
21761
|
-
projectId: text("project_id").notNull().default(
|
|
21768
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`).primaryKey(),
|
|
21762
21769
|
nextId: integer("next_id").default(1),
|
|
21763
21770
|
nextWorkflowStepId: integer("next_workflow_step_id").default(1),
|
|
21764
21771
|
// FNXC:SqliteFinalRemoval 2026-06-28:
|
|
@@ -22152,9 +22159,13 @@ var init_project = __esm({
|
|
|
22152
22159
|
automations = projectSchema.table("automations", {
|
|
22153
22160
|
/*
|
|
22154
22161
|
* FNXC:AutomationIsolation 2026-07-13-22:37:
|
|
22155
|
-
* Automations are partitioned by the AsyncDataLayer's project ID because embedded PostgreSQL consolidates the per-project SQLite files into one table. The composite key deliberately permits the same automation ID in two projects without allowing either project's CRUD or cron-claim path to address the other row.
|
|
22162
|
+
* Automations are partitioned by the AsyncDataLayer's project ID because embedded PostgreSQL consolidates the per-project SQLite files into one table. The composite key deliberately permits the same automation ID in two projects without allowing either project's CRUD or cron-claim path to address the other row.
|
|
22163
|
+
*
|
|
22164
|
+
* FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
22165
|
+
* Migration 0006 owns the default through the database GUC/trigger; Drizzle emits DEFAULT
|
|
22166
|
+
* without replacing the physical legacy fallback or the fail-closed bound writer contract.
|
|
22156
22167
|
*/
|
|
22157
|
-
projectId: text("project_id").notNull().default(
|
|
22168
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22158
22169
|
id: text("id").notNull(),
|
|
22159
22170
|
name: text("name").notNull(),
|
|
22160
22171
|
description: text("description"),
|
|
@@ -22453,7 +22464,8 @@ var init_project = __esm({
|
|
|
22453
22464
|
index("idxTaskDocumentsTaskId").on(t.taskId)
|
|
22454
22465
|
]);
|
|
22455
22466
|
artifacts = projectSchema.table("artifacts", {
|
|
22456
|
-
|
|
22467
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22468
|
+
id: text("id").notNull(),
|
|
22457
22469
|
type: text("type").notNull(),
|
|
22458
22470
|
title: text("title").notNull(),
|
|
22459
22471
|
description: text("description"),
|
|
@@ -22468,7 +22480,8 @@ var init_project = __esm({
|
|
|
22468
22480
|
createdAt: text("created_at").notNull(),
|
|
22469
22481
|
updatedAt: text("updated_at").notNull()
|
|
22470
22482
|
}, (t) => [
|
|
22471
|
-
|
|
22483
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
22484
|
+
foreignKey({ name: "artifacts_task_id_fkey", columns: [t.projectId, t.taskId], foreignColumns: [tasks.projectId, tasks.id] }).onDelete("cascade"),
|
|
22472
22485
|
index("idxArtifactsTaskId").on(t.taskId),
|
|
22473
22486
|
index("idxArtifactsAuthorId").on(t.authorId),
|
|
22474
22487
|
index("idxArtifactsType").on(t.type),
|
|
@@ -22658,7 +22671,8 @@ var init_project = __esm({
|
|
|
22658
22671
|
index("idxEvalRunEventsRunIdSeq").on(t.runId, t.seq)
|
|
22659
22672
|
]);
|
|
22660
22673
|
secrets = projectSchema.table("secrets", {
|
|
22661
|
-
|
|
22674
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22675
|
+
id: text("id").notNull(),
|
|
22662
22676
|
key: text("key").notNull(),
|
|
22663
22677
|
valueCiphertext: bytea("value_ciphertext").notNull(),
|
|
22664
22678
|
nonce: bytea("nonce").notNull(),
|
|
@@ -22671,7 +22685,8 @@ var init_project = __esm({
|
|
|
22671
22685
|
lastReadAt: text("last_read_at"),
|
|
22672
22686
|
lastReadBy: text("last_read_by")
|
|
22673
22687
|
}, (t) => [
|
|
22674
|
-
|
|
22688
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
22689
|
+
unique("secrets_key_unique").on(t.projectId, t.key),
|
|
22675
22690
|
check("secrets_access_policy_check", sql`${t.accessPolicy} IN ('auto', 'prompt', 'deny')`),
|
|
22676
22691
|
check("secrets_env_exportable_check", sql`${t.envExportable} IN (0, 1)`)
|
|
22677
22692
|
]);
|
|
@@ -22713,10 +22728,11 @@ var init_project = __esm({
|
|
|
22713
22728
|
updatedAt: text("updated_at").notNull()
|
|
22714
22729
|
}, (t) => [primaryKey({ columns: [t.projectId, t.id] })]);
|
|
22715
22730
|
branchGroups = projectSchema.table("branch_groups", {
|
|
22716
|
-
|
|
22731
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22732
|
+
id: text("id").notNull(),
|
|
22717
22733
|
sourceType: text("source_type").notNull(),
|
|
22718
22734
|
sourceId: text("source_id").notNull(),
|
|
22719
|
-
branchName: text("branch_name").notNull()
|
|
22735
|
+
branchName: text("branch_name").notNull(),
|
|
22720
22736
|
worktreePath: text("worktree_path"),
|
|
22721
22737
|
autoMerge: integer("auto_merge").notNull().default(0),
|
|
22722
22738
|
prState: text("pr_state").notNull().default("none"),
|
|
@@ -22732,6 +22748,8 @@ var init_project = __esm({
|
|
|
22732
22748
|
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
22733
22749
|
closedAt: bigint("closed_at", { mode: "number" })
|
|
22734
22750
|
}, (t) => [
|
|
22751
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
22752
|
+
unique("branch_groups_branch_name_key").on(t.projectId, t.branchName),
|
|
22735
22753
|
check("branch_groups_source_type_check", sql`${t.sourceType} IN ('mission','planning','new-task')`),
|
|
22736
22754
|
check("branch_groups_pr_state_check", sql`${t.prState} IN ('none','open','merged','closed')`),
|
|
22737
22755
|
check("branch_groups_status_check", sql`${t.status} IN ('open','finalized','abandoned')`),
|
|
@@ -23133,12 +23151,14 @@ var init_project = __esm({
|
|
|
23133
23151
|
index("idxUsageEventsKindTs").on(t.kind, t.ts)
|
|
23134
23152
|
]);
|
|
23135
23153
|
pluginActivations = projectSchema.table("plugin_activations", {
|
|
23136
|
-
|
|
23154
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23155
|
+
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23137
23156
|
pluginId: text("plugin_id").notNull(),
|
|
23138
23157
|
source: text("source").notNull(),
|
|
23139
23158
|
pluginVersion: text("plugin_version"),
|
|
23140
23159
|
activatedAt: text("activated_at").notNull()
|
|
23141
23160
|
}, (t) => [
|
|
23161
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23142
23162
|
index("idxPluginActivationsActivatedAt").on(t.activatedAt),
|
|
23143
23163
|
index("idxPluginActivationsPluginId").on(t.pluginId)
|
|
23144
23164
|
]);
|
|
@@ -23163,8 +23183,13 @@ var init_project = __esm({
|
|
|
23163
23183
|
index("idxKnowledgePagesUpdatedAt").on(t.updatedAt)
|
|
23164
23184
|
]);
|
|
23165
23185
|
deployments = projectSchema.table("deployments", {
|
|
23166
|
-
id: integer("id").generatedAlwaysAsIdentity().
|
|
23167
|
-
|
|
23186
|
+
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23187
|
+
/*
|
|
23188
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
23189
|
+
Migration 0006 rebuilt deployments_pkey as (project_id, id). Drizzle emits DEFAULT while the
|
|
23190
|
+
database GUC/trigger keeps ownership stamping and the physical legacy fallback authoritative.
|
|
23191
|
+
*/
|
|
23192
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23168
23193
|
deploymentId: text("deployment_id").notNull(),
|
|
23169
23194
|
service: text("service"),
|
|
23170
23195
|
environment: text("environment"),
|
|
@@ -23175,6 +23200,7 @@ var init_project = __esm({
|
|
|
23175
23200
|
meta: jsonb("meta"),
|
|
23176
23201
|
createdAt: text("created_at").notNull()
|
|
23177
23202
|
}, (t) => [
|
|
23203
|
+
primaryKey({ columns: [t.projectId, t.id], name: "deployments_pkey" }),
|
|
23178
23204
|
uniqueIndex("idxDeploymentsProjectDeploymentId").on(t.projectId, t.deploymentId),
|
|
23179
23205
|
index("idxDeploymentsProjectDeployedAt").on(t.projectId, t.deployedAt),
|
|
23180
23206
|
index("idxDeploymentsDeployedAt").on(t.deployedAt),
|
|
@@ -23182,7 +23208,12 @@ var init_project = __esm({
|
|
|
23182
23208
|
]);
|
|
23183
23209
|
githubCheckStates = projectSchema.table("github_check_states", {
|
|
23184
23210
|
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23185
|
-
|
|
23211
|
+
/*
|
|
23212
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
23213
|
+
Migration 0048 post-dated 0006, so FN-9004 reconciles its physical default to the ownership
|
|
23214
|
+
expression. Drizzle emits DEFAULT while the database GUC/trigger remains the stamping authority.
|
|
23215
|
+
*/
|
|
23216
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23186
23217
|
repo: text("repo").notNull(),
|
|
23187
23218
|
headSha: text("head_sha").notNull(),
|
|
23188
23219
|
checkName: text("check_name").notNull(),
|
|
@@ -23202,9 +23233,14 @@ var init_project = __esm({
|
|
|
23202
23233
|
index("idxGithubCheckStatesProjectReceived").on(t.projectId, t.receivedAt)
|
|
23203
23234
|
]);
|
|
23204
23235
|
incidents = projectSchema.table("incidents", {
|
|
23205
|
-
id: integer("id").generatedAlwaysAsIdentity().
|
|
23206
|
-
|
|
23207
|
-
|
|
23236
|
+
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23237
|
+
/*
|
|
23238
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
23239
|
+
Migration 0006 rebuilt incident keys with project_id first. Drizzle emits DEFAULT while the
|
|
23240
|
+
database GUC/trigger retains ownership stamping and its physical legacy fallback.
|
|
23241
|
+
*/
|
|
23242
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23243
|
+
incidentId: text("incident_id").notNull(),
|
|
23208
23244
|
groupingKey: text("grouping_key").notNull(),
|
|
23209
23245
|
title: text("title").notNull(),
|
|
23210
23246
|
severity: text("severity"),
|
|
@@ -23218,6 +23254,8 @@ var init_project = __esm({
|
|
|
23218
23254
|
createdAt: text("created_at").notNull(),
|
|
23219
23255
|
updatedAt: text("updated_at").notNull()
|
|
23220
23256
|
}, (t) => [
|
|
23257
|
+
primaryKey({ columns: [t.projectId, t.id], name: "incidents_pkey" }),
|
|
23258
|
+
unique("incidents_incident_id_key").on(t.projectId, t.incidentId),
|
|
23221
23259
|
index("idxIncidentsProjectOpenedAt").on(t.projectId, t.openedAt),
|
|
23222
23260
|
index("idxIncidentsProjectStatus").on(t.projectId, t.status),
|
|
23223
23261
|
index("idxIncidentsGroupingKey").on(t.groupingKey),
|
|
@@ -23272,12 +23310,14 @@ var init_project = __esm({
|
|
|
23272
23310
|
content: text("content").notNull(),
|
|
23273
23311
|
type: text("type").notNull(),
|
|
23274
23312
|
read: integer("read").default(0),
|
|
23313
|
+
archived: integer("archived").default(0),
|
|
23275
23314
|
metadata: jsonb("metadata"),
|
|
23276
23315
|
createdAt: text("created_at").notNull(),
|
|
23277
23316
|
updatedAt: text("updated_at").notNull()
|
|
23278
23317
|
}, (t) => [
|
|
23279
23318
|
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23280
23319
|
index("idxMessagesTo").on(t.toId, t.toType, t.read),
|
|
23320
|
+
index("idxMessagesToArchived").on(t.toId, t.toType, t.archived),
|
|
23281
23321
|
index("idxMessagesFrom").on(t.fromId, t.fromType),
|
|
23282
23322
|
index("idxMessagesCreatedAt").on(t.createdAt)
|
|
23283
23323
|
]);
|
|
@@ -23378,7 +23418,8 @@ var init_project = __esm({
|
|
|
23378
23418
|
index("idx_cli_sessions_project_state").on(t.projectId, t.agentState)
|
|
23379
23419
|
]);
|
|
23380
23420
|
chatMessages = projectSchema.table("chat_messages", {
|
|
23381
|
-
|
|
23421
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23422
|
+
id: text("id").notNull(),
|
|
23382
23423
|
sessionId: text("session_id").notNull(),
|
|
23383
23424
|
role: text("role").notNull(),
|
|
23384
23425
|
content: text("content").notNull(),
|
|
@@ -23387,6 +23428,7 @@ var init_project = __esm({
|
|
|
23387
23428
|
createdAt: text("created_at").notNull(),
|
|
23388
23429
|
attachments: jsonb("attachments")
|
|
23389
23430
|
}, (t) => [
|
|
23431
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23390
23432
|
index("idxChatMessagesSessionId").on(t.sessionId),
|
|
23391
23433
|
index("idxChatMessagesCreatedAt").on(t.createdAt)
|
|
23392
23434
|
]);
|
|
@@ -23412,7 +23454,8 @@ var init_project = __esm({
|
|
|
23412
23454
|
index("idxChatTokenUsageCreatedAt").on(t.createdAt)
|
|
23413
23455
|
]);
|
|
23414
23456
|
runAuditEvents = projectSchema.table("run_audit_events", {
|
|
23415
|
-
|
|
23457
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23458
|
+
id: text("id").notNull(),
|
|
23416
23459
|
timestamp: text("timestamp").notNull(),
|
|
23417
23460
|
taskId: text("task_id"),
|
|
23418
23461
|
agentId: text("agent_id").notNull(),
|
|
@@ -23422,6 +23465,7 @@ var init_project = __esm({
|
|
|
23422
23465
|
target: text("target").notNull(),
|
|
23423
23466
|
metadata: jsonb("metadata")
|
|
23424
23467
|
}, (t) => [
|
|
23468
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23425
23469
|
index("idxRunAuditEventsRunIdTimestamp").on(t.runId, t.timestamp),
|
|
23426
23470
|
index("idxRunAuditEventsTaskIdTimestamp").on(t.taskId, t.timestamp),
|
|
23427
23471
|
index("idxRunAuditEventsTimestamp").on(t.timestamp)
|
|
@@ -23522,13 +23566,14 @@ var init_project = __esm({
|
|
|
23522
23566
|
index("idxMissionLineageStopsMissionId").on(t.projectId, t.missionId)
|
|
23523
23567
|
]);
|
|
23524
23568
|
verificationCache = projectSchema.table("verification_cache", {
|
|
23569
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23525
23570
|
treeSha: text("tree_sha").notNull(),
|
|
23526
23571
|
testCommand: text("test_command").notNull().default(""),
|
|
23527
23572
|
buildCommand: text("build_command").notNull().default(""),
|
|
23528
23573
|
recordedAt: text("recorded_at").notNull(),
|
|
23529
23574
|
taskId: text("task_id")
|
|
23530
23575
|
}, (t) => [
|
|
23531
|
-
primaryKey({ columns: [t.treeSha, t.testCommand, t.buildCommand] }),
|
|
23576
|
+
primaryKey({ columns: [t.projectId, t.treeSha, t.testCommand, t.buildCommand] }),
|
|
23532
23577
|
index("idxVerificationCacheRecordedAt").on(t.recordedAt)
|
|
23533
23578
|
]);
|
|
23534
23579
|
importTranslationCache = projectSchema.table("import_translation_cache", {
|
|
@@ -23561,7 +23606,8 @@ var init_project = __esm({
|
|
|
23561
23606
|
index("idxImportTranslationCacheRecordedAt").on(t.recordedAt)
|
|
23562
23607
|
]);
|
|
23563
23608
|
approvalRequests = projectSchema.table("approval_requests", {
|
|
23564
|
-
|
|
23609
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23610
|
+
id: text("id").notNull(),
|
|
23565
23611
|
status: text("status").notNull(),
|
|
23566
23612
|
requesterActorId: text("requester_actor_id").notNull(),
|
|
23567
23613
|
requesterActorType: text("requester_actor_type").notNull(),
|
|
@@ -23580,13 +23626,14 @@ var init_project = __esm({
|
|
|
23580
23626
|
createdAt: text("created_at").notNull(),
|
|
23581
23627
|
updatedAt: text("updated_at").notNull()
|
|
23582
23628
|
}, (t) => [
|
|
23629
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23583
23630
|
index("idxApprovalRequestsStatusCreatedAt").on(t.status, t.createdAt),
|
|
23584
23631
|
index("idxApprovalRequestsRequesterCreatedAt").on(t.requesterActorId, t.createdAt),
|
|
23585
23632
|
index("idxApprovalRequestsTaskCreatedAt").on(t.taskId, t.createdAt)
|
|
23586
23633
|
]);
|
|
23587
23634
|
approvalRequestAuditEvents = projectSchema.table("approval_request_audit_events", {
|
|
23588
|
-
projectId: text("project_id").notNull().default(
|
|
23589
|
-
id: text("id").
|
|
23635
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23636
|
+
id: text("id").notNull(),
|
|
23590
23637
|
requestId: text("request_id").notNull(),
|
|
23591
23638
|
eventType: text("event_type").notNull(),
|
|
23592
23639
|
actorId: text("actor_id").notNull(),
|
|
@@ -23595,6 +23642,7 @@ var init_project = __esm({
|
|
|
23595
23642
|
note: text("note"),
|
|
23596
23643
|
createdAt: text("created_at").notNull()
|
|
23597
23644
|
}, (t) => [
|
|
23645
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23598
23646
|
index("idxApprovalRequestAuditRequestCreatedAt").on(t.requestId, t.createdAt, t.id),
|
|
23599
23647
|
index("idxApprovalRequestAuditProjectCreatedAt").on(t.projectId, t.createdAt)
|
|
23600
23648
|
]);
|
|
@@ -27084,6 +27132,27 @@ var init_grok_provider = __esm({
|
|
|
27084
27132
|
apiKey: "$GROK_API_KEY",
|
|
27085
27133
|
api: "openai-completions",
|
|
27086
27134
|
models: [
|
|
27135
|
+
/*
|
|
27136
|
+
FNXC:ModelRegistry 2026-08-12-20:17:
|
|
27137
|
+
FN-9008 requires Grok 4.6 to be selectable in every model area. Keep it in this shared
|
|
27138
|
+
catalog because pi's registerProvider() replaces provider model lists wholesale, while every
|
|
27139
|
+
Fusion host seeds and re-merges this export. xAI's model docs verify grok-4.6, its 500k-token
|
|
27140
|
+
context window, and configurable reasoning; max output and per-model image input remain
|
|
27141
|
+
upstream-pending-verification, so retain the conservative text-only and 65536-token defaults.
|
|
27142
|
+
Source: https://docs.x.ai/developers/models
|
|
27143
|
+
*/
|
|
27144
|
+
{
|
|
27145
|
+
id: "grok-4.6",
|
|
27146
|
+
name: "Grok 4.6",
|
|
27147
|
+
reasoning: true,
|
|
27148
|
+
input: ["text"],
|
|
27149
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
27150
|
+
contextWindow: 5e5,
|
|
27151
|
+
maxTokens: 65536,
|
|
27152
|
+
compat: {
|
|
27153
|
+
supportsDeveloperRole: false
|
|
27154
|
+
}
|
|
27155
|
+
},
|
|
27087
27156
|
{
|
|
27088
27157
|
id: "grok-4.5",
|
|
27089
27158
|
name: "Grok 4.5",
|
|
@@ -35042,6 +35111,7 @@ function rowToMessage(row) {
|
|
|
35042
35111
|
content: row.content,
|
|
35043
35112
|
type: row.type,
|
|
35044
35113
|
read: (row.read ?? 0) === 1,
|
|
35114
|
+
archived: (row.archived ?? 0) === 1,
|
|
35045
35115
|
metadata: row.metadata ?? void 0,
|
|
35046
35116
|
createdAt: row.createdAt,
|
|
35047
35117
|
updatedAt: row.updatedAt
|
|
@@ -35053,6 +35123,11 @@ function participantIdsForLookup(ownerId, ownerType) {
|
|
|
35053
35123
|
}
|
|
35054
35124
|
return [ownerId];
|
|
35055
35125
|
}
|
|
35126
|
+
function archivedCondition(archived) {
|
|
35127
|
+
if (archived === true) return eq(project_exports.messages.archived, 1);
|
|
35128
|
+
if (archived === false) return or(eq(project_exports.messages.archived, 0), sql`${project_exports.messages.archived} IS NULL`);
|
|
35129
|
+
return or(eq(project_exports.messages.archived, 0), sql`${project_exports.messages.archived} IS NULL`);
|
|
35130
|
+
}
|
|
35056
35131
|
async function sendMessage(handle, message) {
|
|
35057
35132
|
const sanitizedContent = sanitizeTextValue(message.content);
|
|
35058
35133
|
const sanitizedMetadata = sanitizeJsonbValue(message.metadata);
|
|
@@ -35065,6 +35140,7 @@ async function sendMessage(handle, message) {
|
|
|
35065
35140
|
content: sanitizedContent,
|
|
35066
35141
|
type: message.type,
|
|
35067
35142
|
read: message.read ? 1 : 0,
|
|
35143
|
+
archived: message.archived ? 1 : 0,
|
|
35068
35144
|
metadata: sanitizedMetadata,
|
|
35069
35145
|
createdAt: message.createdAt,
|
|
35070
35146
|
updatedAt: message.updatedAt
|
|
@@ -35073,7 +35149,8 @@ async function sendMessage(handle, message) {
|
|
|
35073
35149
|
...message,
|
|
35074
35150
|
content: sanitizedContent,
|
|
35075
35151
|
metadata: sanitizedMetadata,
|
|
35076
|
-
read: message.read ? 1 : 0
|
|
35152
|
+
read: message.read ? 1 : 0,
|
|
35153
|
+
archived: message.archived ? 1 : 0
|
|
35077
35154
|
});
|
|
35078
35155
|
}
|
|
35079
35156
|
async function sendMessageOnce(handle, message) {
|
|
@@ -35086,6 +35163,7 @@ async function sendMessageOnce(handle, message) {
|
|
|
35086
35163
|
content: message.content,
|
|
35087
35164
|
type: message.type,
|
|
35088
35165
|
read: message.read ? 1 : 0,
|
|
35166
|
+
archived: message.archived ? 1 : 0,
|
|
35089
35167
|
metadata: message.metadata,
|
|
35090
35168
|
createdAt: message.createdAt,
|
|
35091
35169
|
updatedAt: message.updatedAt
|
|
@@ -35137,6 +35215,7 @@ async function queryMessagesByParticipant(handle, direction, ownerId, ownerType,
|
|
|
35137
35215
|
if (filter2?.read !== void 0) {
|
|
35138
35216
|
conditions.push(eq(project_exports.messages.read, filter2.read ? 1 : 0));
|
|
35139
35217
|
}
|
|
35218
|
+
conditions.push(archivedCondition(filter2?.archived));
|
|
35140
35219
|
const limit2 = filter2?.limit ?? 100;
|
|
35141
35220
|
const offset = filter2?.offset ?? 0;
|
|
35142
35221
|
const rows = await handle.select(messageColumns).from(project_exports.messages).where(and(...conditions)).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id)).limit(limit2).offset(offset);
|
|
@@ -35150,6 +35229,13 @@ async function markMessageAsRead(handle, messageId) {
|
|
|
35150
35229
|
await handle.update(project_exports.messages).set({ read: 1, updatedAt: now }).where(eq(project_exports.messages.id, messageId));
|
|
35151
35230
|
return await getMessage(handle, messageId);
|
|
35152
35231
|
}
|
|
35232
|
+
async function setMessageArchived(handle, id, archived) {
|
|
35233
|
+
const existing = await getMessage(handle, id);
|
|
35234
|
+
if (!existing) return null;
|
|
35235
|
+
if (existing.archived === archived) return existing;
|
|
35236
|
+
const rows = await handle.update(project_exports.messages).set({ archived: archived ? 1 : 0, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(project_exports.messages.id, id)).returning(messageColumns);
|
|
35237
|
+
return rows[0] ? rowToMessage(rows[0]) : null;
|
|
35238
|
+
}
|
|
35153
35239
|
async function markAllMessagesAsRead(handle, ownerId, ownerType) {
|
|
35154
35240
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
35155
35241
|
const participantIds = participantIdsForLookup(ownerId, ownerType);
|
|
@@ -35157,7 +35243,8 @@ async function markAllMessagesAsRead(handle, ownerId, ownerType) {
|
|
|
35157
35243
|
and(
|
|
35158
35244
|
inArray(project_exports.messages.toId, participantIds),
|
|
35159
35245
|
eq(project_exports.messages.toType, ownerType),
|
|
35160
|
-
eq(project_exports.messages.read, 0)
|
|
35246
|
+
eq(project_exports.messages.read, 0),
|
|
35247
|
+
archivedCondition()
|
|
35161
35248
|
)
|
|
35162
35249
|
);
|
|
35163
35250
|
const count2 = countRows[0]?.count ?? 0;
|
|
@@ -35165,7 +35252,8 @@ async function markAllMessagesAsRead(handle, ownerId, ownerType) {
|
|
|
35165
35252
|
and(
|
|
35166
35253
|
inArray(project_exports.messages.toId, participantIds),
|
|
35167
35254
|
eq(project_exports.messages.toType, ownerType),
|
|
35168
|
-
eq(project_exports.messages.read, 0)
|
|
35255
|
+
eq(project_exports.messages.read, 0),
|
|
35256
|
+
archivedCondition()
|
|
35169
35257
|
)
|
|
35170
35258
|
);
|
|
35171
35259
|
return count2;
|
|
@@ -35187,19 +35275,22 @@ async function getConversation(handle, participantA, participantB, options) {
|
|
|
35187
35275
|
const aIds = participantIdsForLookup(participantA.id, participantA.type);
|
|
35188
35276
|
const bIds = participantIdsForLookup(participantB.id, participantB.type);
|
|
35189
35277
|
const rows = await handle.select(messageColumns).from(project_exports.messages).where(
|
|
35190
|
-
|
|
35191
|
-
|
|
35192
|
-
|
|
35193
|
-
|
|
35194
|
-
|
|
35195
|
-
|
|
35278
|
+
and(
|
|
35279
|
+
or(
|
|
35280
|
+
and(
|
|
35281
|
+
inArray(project_exports.messages.fromId, aIds),
|
|
35282
|
+
eq(project_exports.messages.fromType, participantA.type),
|
|
35283
|
+
inArray(project_exports.messages.toId, bIds),
|
|
35284
|
+
eq(project_exports.messages.toType, participantB.type)
|
|
35285
|
+
),
|
|
35286
|
+
and(
|
|
35287
|
+
inArray(project_exports.messages.fromId, bIds),
|
|
35288
|
+
eq(project_exports.messages.fromType, participantB.type),
|
|
35289
|
+
inArray(project_exports.messages.toId, aIds),
|
|
35290
|
+
eq(project_exports.messages.toType, participantA.type)
|
|
35291
|
+
)
|
|
35196
35292
|
),
|
|
35197
|
-
|
|
35198
|
-
inArray(project_exports.messages.fromId, bIds),
|
|
35199
|
-
eq(project_exports.messages.fromType, participantB.type),
|
|
35200
|
-
inArray(project_exports.messages.toId, aIds),
|
|
35201
|
-
eq(project_exports.messages.toType, participantA.type)
|
|
35202
|
-
)
|
|
35293
|
+
archivedCondition(options?.archived)
|
|
35203
35294
|
)
|
|
35204
35295
|
).orderBy(desc(project_exports.messages.createdAt)).limit(limit2);
|
|
35205
35296
|
return rows.reverse().map((row) => rowToMessage(row));
|
|
@@ -35210,14 +35301,16 @@ async function getMailbox(handle, ownerId, ownerType) {
|
|
|
35210
35301
|
and(
|
|
35211
35302
|
inArray(project_exports.messages.toId, participantIds),
|
|
35212
35303
|
eq(project_exports.messages.toType, ownerType),
|
|
35213
|
-
eq(project_exports.messages.read, 0)
|
|
35304
|
+
eq(project_exports.messages.read, 0),
|
|
35305
|
+
archivedCondition()
|
|
35214
35306
|
)
|
|
35215
35307
|
);
|
|
35216
35308
|
const unreadCount = unreadRows[0]?.count ?? 0;
|
|
35217
35309
|
const lastRows = await handle.select(messageColumns).from(project_exports.messages).where(
|
|
35218
35310
|
and(
|
|
35219
35311
|
inArray(project_exports.messages.toId, participantIds),
|
|
35220
|
-
eq(project_exports.messages.toType, ownerType)
|
|
35312
|
+
eq(project_exports.messages.toType, ownerType),
|
|
35313
|
+
archivedCondition()
|
|
35221
35314
|
)
|
|
35222
35315
|
).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id)).limit(1);
|
|
35223
35316
|
return {
|
|
@@ -35227,15 +35320,16 @@ async function getMailbox(handle, ownerId, ownerType) {
|
|
|
35227
35320
|
lastMessage: lastRows[0] ? rowToMessage(lastRows[0]) : void 0
|
|
35228
35321
|
};
|
|
35229
35322
|
}
|
|
35230
|
-
async function getAllAgentToAgentMessages(handle) {
|
|
35231
|
-
const rows = await handle.select(messageColumns).from(project_exports.messages).where(eq(project_exports.messages.type, "agent-to-agent")).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id));
|
|
35323
|
+
async function getAllAgentToAgentMessages(handle, filter2) {
|
|
35324
|
+
const rows = await handle.select(messageColumns).from(project_exports.messages).where(and(eq(project_exports.messages.type, "agent-to-agent"), archivedCondition(filter2?.archived))).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id));
|
|
35232
35325
|
return rows.map((row) => rowToMessage(row));
|
|
35233
35326
|
}
|
|
35234
35327
|
async function getUnreadAgentToAgentCount(handle) {
|
|
35235
35328
|
const rows = await handle.select({ count: sql`count(*)::int` }).from(project_exports.messages).where(
|
|
35236
35329
|
and(
|
|
35237
35330
|
eq(project_exports.messages.type, "agent-to-agent"),
|
|
35238
|
-
eq(project_exports.messages.read, 0)
|
|
35331
|
+
eq(project_exports.messages.read, 0),
|
|
35332
|
+
archivedCondition()
|
|
35239
35333
|
)
|
|
35240
35334
|
);
|
|
35241
35335
|
return rows[0]?.count ?? 0;
|
|
@@ -35257,6 +35351,7 @@ var init_async_message_store = __esm({
|
|
|
35257
35351
|
content: project_exports.messages.content,
|
|
35258
35352
|
type: project_exports.messages.type,
|
|
35259
35353
|
read: project_exports.messages.read,
|
|
35354
|
+
archived: project_exports.messages.archived,
|
|
35260
35355
|
metadata: project_exports.messages.metadata,
|
|
35261
35356
|
createdAt: project_exports.messages.createdAt,
|
|
35262
35357
|
updatedAt: project_exports.messages.updatedAt
|
|
@@ -35442,12 +35537,12 @@ var init_message_store = __esm({
|
|
|
35442
35537
|
}
|
|
35443
35538
|
const sqliteDb = this.db;
|
|
35444
35539
|
this.stmtInsert = sqliteDb.prepare(`
|
|
35445
|
-
INSERT INTO messages (id, fromId, fromType, toId, toType, content, type, read, metadata, createdAt, updatedAt)
|
|
35446
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35540
|
+
INSERT INTO messages (id, fromId, fromType, toId, toType, content, type, read, archived, metadata, createdAt, updatedAt)
|
|
35541
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35447
35542
|
`);
|
|
35448
35543
|
this.stmtInsertOnce = sqliteDb.prepare(`
|
|
35449
|
-
INSERT OR IGNORE INTO messages (id, fromId, fromType, toId, toType, content, type, read, metadata, createdAt, updatedAt)
|
|
35450
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35544
|
+
INSERT OR IGNORE INTO messages (id, fromId, fromType, toId, toType, content, type, read, archived, metadata, createdAt, updatedAt)
|
|
35545
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35451
35546
|
`);
|
|
35452
35547
|
this.stmtGetById = sqliteDb.prepare(`
|
|
35453
35548
|
SELECT * FROM messages WHERE id = ?
|
|
@@ -35485,6 +35580,7 @@ var init_message_store = __esm({
|
|
|
35485
35580
|
content: row.content,
|
|
35486
35581
|
type: row.type,
|
|
35487
35582
|
read: row.read === 1,
|
|
35583
|
+
archived: (row.archived ?? 0) === 1,
|
|
35488
35584
|
metadata: fromJson(row.metadata),
|
|
35489
35585
|
createdAt: row.createdAt,
|
|
35490
35586
|
updatedAt: row.updatedAt
|
|
@@ -35518,6 +35614,7 @@ var init_message_store = __esm({
|
|
|
35518
35614
|
content: sanitizeTextValue(input.content),
|
|
35519
35615
|
type: input.type,
|
|
35520
35616
|
read: false,
|
|
35617
|
+
archived: false,
|
|
35521
35618
|
metadata: sanitizeJsonbValue(input.metadata),
|
|
35522
35619
|
createdAt: now,
|
|
35523
35620
|
updatedAt: now
|
|
@@ -35533,6 +35630,7 @@ var init_message_store = __esm({
|
|
|
35533
35630
|
content: message.content,
|
|
35534
35631
|
type: message.type,
|
|
35535
35632
|
read: message.read,
|
|
35633
|
+
archived: message.archived,
|
|
35536
35634
|
metadata: message.metadata ?? null,
|
|
35537
35635
|
createdAt: message.createdAt,
|
|
35538
35636
|
updatedAt: message.updatedAt
|
|
@@ -35547,6 +35645,7 @@ var init_message_store = __esm({
|
|
|
35547
35645
|
message.content,
|
|
35548
35646
|
message.type,
|
|
35549
35647
|
message.read ? 1 : 0,
|
|
35648
|
+
message.archived ? 1 : 0,
|
|
35550
35649
|
toJsonNullable(message.metadata),
|
|
35551
35650
|
message.createdAt,
|
|
35552
35651
|
message.updatedAt
|
|
@@ -35605,6 +35704,7 @@ var init_message_store = __esm({
|
|
|
35605
35704
|
content: sanitizeTextValue(input.content),
|
|
35606
35705
|
type: input.type,
|
|
35607
35706
|
read: false,
|
|
35707
|
+
archived: false,
|
|
35608
35708
|
metadata: sanitizeJsonbValue(input.metadata),
|
|
35609
35709
|
createdAt: now,
|
|
35610
35710
|
updatedAt: now
|
|
@@ -35625,6 +35725,7 @@ var init_message_store = __esm({
|
|
|
35625
35725
|
message.content,
|
|
35626
35726
|
message.type,
|
|
35627
35727
|
0,
|
|
35728
|
+
0,
|
|
35628
35729
|
toJsonNullable(message.metadata),
|
|
35629
35730
|
message.createdAt,
|
|
35630
35731
|
message.updatedAt
|
|
@@ -35756,6 +35857,7 @@ var init_message_store = __esm({
|
|
|
35756
35857
|
whereClauses.push("read = ?");
|
|
35757
35858
|
params.push(filter2.read ? 1 : 0);
|
|
35758
35859
|
}
|
|
35860
|
+
whereClauses.push(filter2?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)");
|
|
35759
35861
|
const whereSql = whereClauses.join(" AND ");
|
|
35760
35862
|
const limit2 = filter2?.limit ?? 100;
|
|
35761
35863
|
const offset = filter2?.offset ?? 0;
|
|
@@ -35806,15 +35908,39 @@ var init_message_store = __esm({
|
|
|
35806
35908
|
const participantIds = this.getParticipantIdsForLookup(ownerId, ownerType);
|
|
35807
35909
|
const toIdPredicate = participantIds.length === 1 ? "toId = ?" : `toId IN (${participantIds.map(() => "?").join(", ")})`;
|
|
35808
35910
|
const unreadRow = this.db.prepare(`
|
|
35809
|
-
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0
|
|
35911
|
+
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35810
35912
|
`).get(...participantIds, ownerType);
|
|
35811
35913
|
const count2 = unreadRow?.count ?? 0;
|
|
35812
35914
|
this.db.prepare(`
|
|
35813
|
-
UPDATE messages SET read = 1, updatedAt = ? WHERE ${toIdPredicate} AND toType = ? AND read = 0
|
|
35915
|
+
UPDATE messages SET read = 1, updatedAt = ? WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35814
35916
|
`).run(now, ...participantIds, ownerType);
|
|
35815
35917
|
this.db.bumpLastModified();
|
|
35816
35918
|
return count2;
|
|
35817
35919
|
}
|
|
35920
|
+
/** Archive a message without destroying its correspondence history. */
|
|
35921
|
+
async archiveMessage(id) {
|
|
35922
|
+
return this.setMessageArchived(id, true);
|
|
35923
|
+
}
|
|
35924
|
+
/** Restore a previously archived message to default mailbox lists. */
|
|
35925
|
+
async unarchiveMessage(id) {
|
|
35926
|
+
return this.setMessageArchived(id, false);
|
|
35927
|
+
}
|
|
35928
|
+
async setMessageArchived(id, archived) {
|
|
35929
|
+
if (this.asyncLayer) {
|
|
35930
|
+
const updated2 = await setMessageArchived(this.asyncLayer.db, id, archived);
|
|
35931
|
+
if (!updated2) throw new Error(`Message ${id} not found`);
|
|
35932
|
+
this.emit(archived ? "message:archived" : "message:unarchived", updated2);
|
|
35933
|
+
return updated2;
|
|
35934
|
+
}
|
|
35935
|
+
const existing = await this.getMessage(id);
|
|
35936
|
+
if (!existing) throw new Error(`Message ${id} not found`);
|
|
35937
|
+
if (existing.archived === archived) return existing;
|
|
35938
|
+
this.db.prepare("UPDATE messages SET archived = ?, updatedAt = ? WHERE id = ?").run(archived ? 1 : 0, (/* @__PURE__ */ new Date()).toISOString(), id);
|
|
35939
|
+
this.db.bumpLastModified();
|
|
35940
|
+
const updated = await this.getMessage(id);
|
|
35941
|
+
this.emit(archived ? "message:archived" : "message:unarchived", updated);
|
|
35942
|
+
return updated;
|
|
35943
|
+
}
|
|
35818
35944
|
/**
|
|
35819
35945
|
* Delete a message by ID.
|
|
35820
35946
|
* @param id - The message ID
|
|
@@ -35905,7 +36031,7 @@ var init_message_store = __esm({
|
|
|
35905
36031
|
(${participantAFromPredicate} AND fromType = ? AND ${participantBToPredicate} AND toType = ?)
|
|
35906
36032
|
OR
|
|
35907
36033
|
(${participantBFromPredicate} AND fromType = ? AND ${participantAToPredicate} AND toType = ?)
|
|
35908
|
-
)
|
|
36034
|
+
) AND ${options?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)"}
|
|
35909
36035
|
ORDER BY createdAt DESC
|
|
35910
36036
|
LIMIT ?
|
|
35911
36037
|
`).all(
|
|
@@ -35940,11 +36066,11 @@ var init_message_store = __esm({
|
|
|
35940
36066
|
const participantIds = this.getParticipantIdsForLookup(ownerId, ownerType);
|
|
35941
36067
|
const toIdPredicate = participantIds.length === 1 ? "toId = ?" : `toId IN (${participantIds.map(() => "?").join(", ")})`;
|
|
35942
36068
|
const unreadRow = this.db.prepare(`
|
|
35943
|
-
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0
|
|
36069
|
+
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35944
36070
|
`).get(...participantIds, ownerType);
|
|
35945
36071
|
const unreadCount = unreadRow?.count ?? 0;
|
|
35946
36072
|
const lastRow = this.db.prepare(`
|
|
35947
|
-
SELECT * FROM messages WHERE ${toIdPredicate} AND toType = ? ORDER BY createdAt DESC, rowid DESC LIMIT 1
|
|
36073
|
+
SELECT * FROM messages WHERE ${toIdPredicate} AND toType = ? AND (archived = 0 OR archived IS NULL) ORDER BY createdAt DESC, rowid DESC LIMIT 1
|
|
35948
36074
|
`).get(...participantIds, ownerType);
|
|
35949
36075
|
const lastMessage = lastRow ? this.rowToMessage(lastRow) : void 0;
|
|
35950
36076
|
return {
|
|
@@ -35958,13 +36084,13 @@ var init_message_store = __esm({
|
|
|
35958
36084
|
* Get all agent-to-agent messages across all agents.
|
|
35959
36085
|
* @returns Array of messages (newest first)
|
|
35960
36086
|
*/
|
|
35961
|
-
async getAllAgentToAgentMessages() {
|
|
36087
|
+
async getAllAgentToAgentMessages(filter2) {
|
|
35962
36088
|
if (this.asyncLayer) {
|
|
35963
|
-
return getAllAgentToAgentMessages(this.asyncLayer.db);
|
|
36089
|
+
return getAllAgentToAgentMessages(this.asyncLayer.db, filter2);
|
|
35964
36090
|
}
|
|
35965
36091
|
const rows = this.db.prepare(`
|
|
35966
36092
|
SELECT * FROM messages
|
|
35967
|
-
WHERE type = ?
|
|
36093
|
+
WHERE type = ? AND ${filter2?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)"}
|
|
35968
36094
|
ORDER BY createdAt DESC, rowid DESC
|
|
35969
36095
|
`).all("agent-to-agent");
|
|
35970
36096
|
return rows.map((row) => this.rowToMessage(row));
|
|
@@ -35978,7 +36104,7 @@ var init_message_store = __esm({
|
|
|
35978
36104
|
}
|
|
35979
36105
|
const row = this.db.prepare(`
|
|
35980
36106
|
SELECT COUNT(*) as count FROM messages
|
|
35981
|
-
WHERE type = ? AND read = 0
|
|
36107
|
+
WHERE type = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35982
36108
|
`).get("agent-to-agent");
|
|
35983
36109
|
return row?.count ?? 0;
|
|
35984
36110
|
}
|
|
@@ -36077,6 +36203,7 @@ async function createApprovalRequest(layer, input) {
|
|
|
36077
36203
|
};
|
|
36078
36204
|
await layer.transactionImmediate(async (tx) => {
|
|
36079
36205
|
await tx.insert(project_exports.approvalRequests).values({
|
|
36206
|
+
...layer.projectId?.trim() ? { projectId: layer.projectId } : {},
|
|
36080
36207
|
id: request3.id,
|
|
36081
36208
|
status: request3.status,
|
|
36082
36209
|
requesterActorId: request3.requester.actorId,
|
|
@@ -36100,12 +36227,12 @@ async function createApprovalRequest(layer, input) {
|
|
|
36100
36227
|
});
|
|
36101
36228
|
return request3;
|
|
36102
36229
|
}
|
|
36103
|
-
async function getApprovalRequest(handle, id) {
|
|
36104
|
-
const rows = await handle.select().from(project_exports.approvalRequests).where(eq(project_exports.approvalRequests.id, id));
|
|
36230
|
+
async function getApprovalRequest(handle, id, projectId2) {
|
|
36231
|
+
const rows = await handle.select().from(project_exports.approvalRequests).where(and(eq(project_exports.approvalRequests.id, id), projectScopeFor(project_exports.approvalRequests.projectId, projectId2)));
|
|
36105
36232
|
return rows[0] ? rowToRequest(rows[0]) : null;
|
|
36106
36233
|
}
|
|
36107
|
-
async function listApprovalRequests(handle, input = {}) {
|
|
36108
|
-
const conditions = [];
|
|
36234
|
+
async function listApprovalRequests(handle, input = {}, projectId2) {
|
|
36235
|
+
const conditions = [projectScopeFor(project_exports.approvalRequests.projectId, projectId2)];
|
|
36109
36236
|
if (input.status) conditions.push(eq(project_exports.approvalRequests.status, input.status));
|
|
36110
36237
|
if (input.requesterActorId) conditions.push(eq(project_exports.approvalRequests.requesterActorId, input.requesterActorId));
|
|
36111
36238
|
if (input.taskId) conditions.push(eq(project_exports.approvalRequests.taskId, input.taskId));
|
|
@@ -36119,7 +36246,7 @@ async function listApprovalRequests(handle, input = {}) {
|
|
|
36119
36246
|
async function decideApprovalRequest(layer, requestId, status, input) {
|
|
36120
36247
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36121
36248
|
return layer.transactionImmediate(async (tx) => {
|
|
36122
|
-
const existing = await getApprovalRequest(tx, requestId);
|
|
36249
|
+
const existing = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36123
36250
|
if (!existing) throw new Error(`Approval request ${requestId} not found`);
|
|
36124
36251
|
if (!isValidApprovalRequestTransition(existing.status, status)) {
|
|
36125
36252
|
throw new Error(`Invalid approval request transition: ${existing.status} -> ${status}`);
|
|
@@ -36130,23 +36257,24 @@ async function decideApprovalRequest(layer, requestId, status, input) {
|
|
|
36130
36257
|
const updatedRows = await tx.update(project_exports.approvalRequests).set({ status, decidedAt: now, updatedAt: now }).where(
|
|
36131
36258
|
and(
|
|
36132
36259
|
eq(project_exports.approvalRequests.id, requestId),
|
|
36133
|
-
eq(project_exports.approvalRequests.status, existing.status)
|
|
36260
|
+
eq(project_exports.approvalRequests.status, existing.status),
|
|
36261
|
+
projectScopeFor(project_exports.approvalRequests.projectId, layer.projectId)
|
|
36134
36262
|
)
|
|
36135
36263
|
).returning({ id: project_exports.approvalRequests.id });
|
|
36136
36264
|
if (updatedRows.length === 0) {
|
|
36137
|
-
const raced = await getApprovalRequest(tx, requestId);
|
|
36265
|
+
const raced = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36138
36266
|
throw new Error(
|
|
36139
36267
|
`Invalid approval request transition: ${raced?.status ?? existing.status} -> ${status}`
|
|
36140
36268
|
);
|
|
36141
36269
|
}
|
|
36142
36270
|
await appendAuditEvent(tx, layer.projectId ?? "", requestId, status, input.actor, now, input.note);
|
|
36143
|
-
return await getApprovalRequest(tx, requestId);
|
|
36271
|
+
return await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36144
36272
|
});
|
|
36145
36273
|
}
|
|
36146
36274
|
async function markApprovalRequestCompleted(layer, requestId, input) {
|
|
36147
36275
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36148
36276
|
return layer.transactionImmediate(async (tx) => {
|
|
36149
|
-
const existing = await getApprovalRequest(tx, requestId);
|
|
36277
|
+
const existing = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36150
36278
|
if (!existing) throw new Error(`Approval request ${requestId} not found`);
|
|
36151
36279
|
if (!isValidApprovalRequestTransition(existing.status, "completed")) {
|
|
36152
36280
|
throw new Error(`Invalid approval request transition: ${existing.status} -> completed`);
|
|
@@ -36160,21 +36288,22 @@ async function markApprovalRequestCompleted(layer, requestId, input) {
|
|
|
36160
36288
|
const updatedRows = await tx.update(project_exports.approvalRequests).set({ status: "completed", completedAt: now, updatedAt: now }).where(
|
|
36161
36289
|
and(
|
|
36162
36290
|
eq(project_exports.approvalRequests.id, requestId),
|
|
36163
|
-
eq(project_exports.approvalRequests.status, existing.status)
|
|
36291
|
+
eq(project_exports.approvalRequests.status, existing.status),
|
|
36292
|
+
projectScopeFor(project_exports.approvalRequests.projectId, layer.projectId)
|
|
36164
36293
|
)
|
|
36165
36294
|
).returning({ id: project_exports.approvalRequests.id });
|
|
36166
36295
|
if (updatedRows.length === 0) {
|
|
36167
|
-
const raced = await getApprovalRequest(tx, requestId);
|
|
36296
|
+
const raced = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36168
36297
|
throw new Error(
|
|
36169
36298
|
`Invalid approval request transition: ${raced?.status ?? existing.status} -> completed`
|
|
36170
36299
|
);
|
|
36171
36300
|
}
|
|
36172
36301
|
await appendAuditEvent(tx, layer.projectId ?? "", requestId, "completed", input.actor, now, input.note);
|
|
36173
|
-
return await getApprovalRequest(tx, requestId);
|
|
36302
|
+
return await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36174
36303
|
});
|
|
36175
36304
|
}
|
|
36176
|
-
async function getApprovalAuditHistory(handle, requestId) {
|
|
36177
|
-
const rows = await handle.select().from(project_exports.approvalRequestAuditEvents).where(eq(project_exports.approvalRequestAuditEvents.requestId, requestId)).orderBy(
|
|
36305
|
+
async function getApprovalAuditHistory(handle, requestId, projectId2) {
|
|
36306
|
+
const rows = await handle.select().from(project_exports.approvalRequestAuditEvents).where(and(eq(project_exports.approvalRequestAuditEvents.requestId, requestId), projectScopeFor(project_exports.approvalRequestAuditEvents.projectId, projectId2))).orderBy(
|
|
36178
36307
|
sql`${project_exports.approvalRequestAuditEvents.createdAt} ASC, ${project_exports.approvalRequestAuditEvents.id} ASC`
|
|
36179
36308
|
);
|
|
36180
36309
|
return rows.map((row) => rowToAuditEvent(row));
|
|
@@ -36184,6 +36313,7 @@ var init_async_approval_request_store = __esm({
|
|
|
36184
36313
|
"use strict";
|
|
36185
36314
|
init_drizzle_orm();
|
|
36186
36315
|
init_schema2();
|
|
36316
|
+
init_data_layer();
|
|
36187
36317
|
init_agents();
|
|
36188
36318
|
init_types();
|
|
36189
36319
|
}
|
|
@@ -36197,6 +36327,7 @@ var init_approval_request_store = __esm({
|
|
|
36197
36327
|
"use strict";
|
|
36198
36328
|
init_drizzle_orm();
|
|
36199
36329
|
init_db2();
|
|
36330
|
+
init_data_layer();
|
|
36200
36331
|
init_async_approval_request_store();
|
|
36201
36332
|
init_schema2();
|
|
36202
36333
|
init_async_agent_activity();
|
|
@@ -36325,23 +36456,26 @@ var init_approval_request_store = __esm({
|
|
|
36325
36456
|
return created;
|
|
36326
36457
|
}
|
|
36327
36458
|
async get(id) {
|
|
36328
|
-
return getApprovalRequest(this.asyncLayer.db, id);
|
|
36459
|
+
return getApprovalRequest(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
36329
36460
|
}
|
|
36330
36461
|
async list(input = {}) {
|
|
36331
|
-
return listApprovalRequests(this.asyncLayer.db, input);
|
|
36462
|
+
return listApprovalRequests(this.asyncLayer.db, input, this.asyncLayer.projectId);
|
|
36332
36463
|
}
|
|
36333
36464
|
async getPendingCountsByActor() {
|
|
36334
36465
|
const table = project_exports.approvalRequests;
|
|
36335
36466
|
const rows = await this.asyncLayer.db.select({
|
|
36336
36467
|
actorId: table.requesterActorId,
|
|
36337
36468
|
requestCount: count()
|
|
36338
|
-
}).from(table).where(eq(table.status, "pending")).groupBy(table.requesterActorId);
|
|
36469
|
+
}).from(table).where(and(eq(table.status, "pending"), projectScopeFor(table.projectId, this.asyncLayer.projectId))).groupBy(table.requesterActorId);
|
|
36339
36470
|
return new Map(rows.map((row) => [row.actorId, Number(row.requestCount)]));
|
|
36340
36471
|
}
|
|
36341
36472
|
async findLatestByDedupeKey(input) {
|
|
36342
36473
|
if (this.backendMode) {
|
|
36343
36474
|
const table = project_exports.approvalRequests;
|
|
36344
|
-
const conditions = [
|
|
36475
|
+
const conditions = [
|
|
36476
|
+
eq(table.requesterActorId, input.requesterActorId),
|
|
36477
|
+
projectScopeFor(table.projectId, this.asyncLayer.projectId)
|
|
36478
|
+
];
|
|
36345
36479
|
if (input.taskId !== void 0) {
|
|
36346
36480
|
conditions.push(eq(table.taskId, input.taskId));
|
|
36347
36481
|
}
|
|
@@ -36380,7 +36514,7 @@ var init_approval_request_store = __esm({
|
|
|
36380
36514
|
return markApprovalRequestCompleted(this.asyncLayer, requestId, input);
|
|
36381
36515
|
}
|
|
36382
36516
|
async getAuditHistory(requestId) {
|
|
36383
|
-
return getApprovalAuditHistory(this.asyncLayer.db, requestId);
|
|
36517
|
+
return getApprovalAuditHistory(this.asyncLayer.db, requestId, this.asyncLayer.projectId);
|
|
36384
36518
|
}
|
|
36385
36519
|
};
|
|
36386
36520
|
}
|
|
@@ -40566,6 +40700,8 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
40566
40700
|
const agentRatingProjectIsolationAlreadyApplied = applied.includes(AGENT_RATING_PROJECT_ISOLATION_VERSION);
|
|
40567
40701
|
const agentRatingsProjectPartitionAlreadyApplied = applied.includes(AGENT_RATINGS_PROJECT_PARTITION_VERSION);
|
|
40568
40702
|
const projectOwnershipDeclarationDriftAlreadyApplied = applied.includes(PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION);
|
|
40703
|
+
const projectOwnershipDefaultReconciliationAlreadyApplied = applied.includes(PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION);
|
|
40704
|
+
const messageArchiveSchemaAlreadyApplied = applied.includes(MESSAGE_ARCHIVE_SCHEMA_VERSION);
|
|
40569
40705
|
assertBinaryNotOlderThanDatabase(applied);
|
|
40570
40706
|
let schemaChanged = false;
|
|
40571
40707
|
if (!baselineAlreadyApplied) {
|
|
@@ -41049,17 +41185,29 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
41049
41185
|
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
41050
41186
|
schemaChanged = true;
|
|
41051
41187
|
}
|
|
41188
|
+
if (!projectOwnershipDefaultReconciliationAlreadyApplied) {
|
|
41189
|
+
const migrationSql = await readFile4(PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH, "utf8");
|
|
41190
|
+
await tx.execute(sql.raw(migrationSql));
|
|
41191
|
+
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
41192
|
+
schemaChanged = true;
|
|
41193
|
+
}
|
|
41194
|
+
if (!messageArchiveSchemaAlreadyApplied) {
|
|
41195
|
+
const migrationSql = await readFile4(MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH, "utf8");
|
|
41196
|
+
await tx.execute(sql.raw(migrationSql));
|
|
41197
|
+
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${MESSAGE_ARCHIVE_SCHEMA_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
41198
|
+
schemaChanged = true;
|
|
41199
|
+
}
|
|
41052
41200
|
return { applied: schemaChanged, pluginHooksRun: pluginHooks.length };
|
|
41053
41201
|
});
|
|
41054
41202
|
}
|
|
41055
|
-
var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, TASK_WEDGE_NOTIFICATION_VERSION, MILESTONE_ASSERTION_PROVENANCE_VERSION, MISSION_LINEAGE_STOP_VERSION, CHAT_SESSION_TAGS_VERSION, DROP_GLOBAL_CONCURRENCY_VERSION, MISSION_TASK_PREFIX_VERSION, CREDENTIAL_INSTANCE_SELECTION_VERSION, TASK_LIFECYCLE_OUTBOX_VERSION, TASK_LIFECYCLE_CONSUMERS_VERSION, VALIDATOR_INPUT_FINGERPRINT_VERSION, UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION, QUEUED_EPISODE_SIGNATURE_VERSION, MULTI_ROLE_WORKFLOW_AGENTS_VERSION, WORKFLOW_PRINCIPAL_FENCE_VERSION, TASK_RECOMMENDATIONS_VERSION, GITHUB_CHECK_STATES_VERSION, AGENT_ACTIVITY_EVENTS_VERSION, SPEC_LOCK_DRIFT_REPORT_VERSION, SPEC_LOCK_SOURCE_REVISION_BIGINT_VERSION, MEMORY_RECALL_RECORDS_VERSION, MISSION_FEATURE_SPEC_ALIGNMENT_VERSION, AGENT_RATING_PROJECT_ISOLATION_VERSION, AGENT_RATINGS_PROJECT_PARTITION_VERSION, PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH, TASK_WEDGE_NOTIFICATION_MIGRATION_PATH, MILESTONE_ASSERTION_PROVENANCE_MIGRATION_PATH, MISSION_LINEAGE_STOP_MIGRATION_PATH, CHAT_SESSION_TAGS_MIGRATION_PATH, DROP_GLOBAL_CONCURRENCY_MIGRATION_PATH, MISSION_TASK_PREFIX_MIGRATION_PATH, CREDENTIAL_INSTANCE_SELECTION_MIGRATION_PATH, TASK_LIFECYCLE_OUTBOX_MIGRATION_PATH, TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH, VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH, UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH, QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH, MULTI_ROLE_WORKFLOW_AGENTS_MIGRATION_PATH, WORKFLOW_PRINCIPAL_FENCE_MIGRATION_PATH, TASK_RECOMMENDATIONS_MIGRATION_PATH, GITHUB_CHECK_STATES_MIGRATION_PATH, AGENT_ACTIVITY_EVENTS_MIGRATION_PATH, SPEC_LOCK_DRIFT_REPORT_MIGRATION_PATH, SPEC_LOCK_SOURCE_REVISION_BIGINT_MIGRATION_PATH, MEMORY_RECALL_RECORDS_MIGRATION_PATH, MISSION_FEATURE_SPEC_ALIGNMENT_MIGRATION_PATH, AGENT_RATING_PROJECT_ISOLATION_MIGRATION_PATH, AGENT_RATINGS_PROJECT_PARTITION_MIGRATION_PATH, PROJECT_OWNERSHIP_DECLARATION_DRIFT_MIGRATION_PATH;
|
|
41203
|
+
var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, TASK_WEDGE_NOTIFICATION_VERSION, MILESTONE_ASSERTION_PROVENANCE_VERSION, MISSION_LINEAGE_STOP_VERSION, CHAT_SESSION_TAGS_VERSION, DROP_GLOBAL_CONCURRENCY_VERSION, MISSION_TASK_PREFIX_VERSION, CREDENTIAL_INSTANCE_SELECTION_VERSION, TASK_LIFECYCLE_OUTBOX_VERSION, TASK_LIFECYCLE_CONSUMERS_VERSION, VALIDATOR_INPUT_FINGERPRINT_VERSION, UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION, QUEUED_EPISODE_SIGNATURE_VERSION, MULTI_ROLE_WORKFLOW_AGENTS_VERSION, WORKFLOW_PRINCIPAL_FENCE_VERSION, TASK_RECOMMENDATIONS_VERSION, GITHUB_CHECK_STATES_VERSION, AGENT_ACTIVITY_EVENTS_VERSION, SPEC_LOCK_DRIFT_REPORT_VERSION, SPEC_LOCK_SOURCE_REVISION_BIGINT_VERSION, MEMORY_RECALL_RECORDS_VERSION, MISSION_FEATURE_SPEC_ALIGNMENT_VERSION, AGENT_RATING_PROJECT_ISOLATION_VERSION, AGENT_RATINGS_PROJECT_PARTITION_VERSION, PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION, PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION, MESSAGE_ARCHIVE_SCHEMA_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH, TASK_WEDGE_NOTIFICATION_MIGRATION_PATH, MILESTONE_ASSERTION_PROVENANCE_MIGRATION_PATH, MISSION_LINEAGE_STOP_MIGRATION_PATH, CHAT_SESSION_TAGS_MIGRATION_PATH, DROP_GLOBAL_CONCURRENCY_MIGRATION_PATH, MISSION_TASK_PREFIX_MIGRATION_PATH, CREDENTIAL_INSTANCE_SELECTION_MIGRATION_PATH, TASK_LIFECYCLE_OUTBOX_MIGRATION_PATH, TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH, VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH, UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH, QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH, MULTI_ROLE_WORKFLOW_AGENTS_MIGRATION_PATH, WORKFLOW_PRINCIPAL_FENCE_MIGRATION_PATH, TASK_RECOMMENDATIONS_MIGRATION_PATH, GITHUB_CHECK_STATES_MIGRATION_PATH, AGENT_ACTIVITY_EVENTS_MIGRATION_PATH, SPEC_LOCK_DRIFT_REPORT_MIGRATION_PATH, SPEC_LOCK_SOURCE_REVISION_BIGINT_MIGRATION_PATH, MEMORY_RECALL_RECORDS_MIGRATION_PATH, MISSION_FEATURE_SPEC_ALIGNMENT_MIGRATION_PATH, AGENT_RATING_PROJECT_ISOLATION_MIGRATION_PATH, AGENT_RATINGS_PROJECT_PARTITION_MIGRATION_PATH, PROJECT_OWNERSHIP_DECLARATION_DRIFT_MIGRATION_PATH, PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH, MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH;
|
|
41056
41204
|
var init_schema_applier = __esm({
|
|
41057
41205
|
"../core/src/postgres/schema-applier.ts"() {
|
|
41058
41206
|
"use strict";
|
|
41059
41207
|
init_drizzle_orm();
|
|
41060
41208
|
init_plugin_schema_hook();
|
|
41061
41209
|
init_advisory_locks();
|
|
41062
|
-
SCHEMA_BASELINE_VERSION = "
|
|
41210
|
+
SCHEMA_BASELINE_VERSION = "0058";
|
|
41063
41211
|
TASK_DECLARED_SYMBOLS_VERSION = "0028";
|
|
41064
41212
|
INITIAL_SCHEMA_VERSION = "0000";
|
|
41065
41213
|
AUTOMATION_ISOLATION_SCHEMA_VERSION = "0001";
|
|
@@ -41116,6 +41264,8 @@ var init_schema_applier = __esm({
|
|
|
41116
41264
|
AGENT_RATING_PROJECT_ISOLATION_VERSION = "0054";
|
|
41117
41265
|
AGENT_RATINGS_PROJECT_PARTITION_VERSION = "0055";
|
|
41118
41266
|
PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION = "0056";
|
|
41267
|
+
PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION = "0057";
|
|
41268
|
+
MESSAGE_ARCHIVE_SCHEMA_VERSION = "0058";
|
|
41119
41269
|
LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION = "fusion_mark_legacy_adoption_drained";
|
|
41120
41270
|
StaleBinarySchemaError = class extends Error {
|
|
41121
41271
|
constructor(databaseVersion, binaryVersion) {
|
|
@@ -41252,6 +41402,8 @@ var init_schema_applier = __esm({
|
|
|
41252
41402
|
AGENT_RATING_PROJECT_ISOLATION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0054_fn_8957_agent_rating_project_isolation.sql");
|
|
41253
41403
|
AGENT_RATINGS_PROJECT_PARTITION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0055_fn_8988_agent_ratings_project_partition.sql");
|
|
41254
41404
|
PROJECT_OWNERSHIP_DECLARATION_DRIFT_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0056_fn_8997_project_ownership_declaration_drift.sql");
|
|
41405
|
+
PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0057_fn_9004_project_ownership_default_reconciliation.sql");
|
|
41406
|
+
MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0058_fn_9014_message_archive.sql");
|
|
41255
41407
|
}
|
|
41256
41408
|
});
|
|
41257
41409
|
|
|
@@ -68607,20 +68759,32 @@ async function replaceActiveTaskWorkflowContinuation(layer, input) {
|
|
|
68607
68759
|
return upsertWorkflowWorkItem(layer, input, tx);
|
|
68608
68760
|
}));
|
|
68609
68761
|
}
|
|
68610
|
-
async function seedStrandedPlanReviewContinuation(layer, input) {
|
|
68762
|
+
async function seedStrandedPlanReviewContinuation(layer, input, options = {}) {
|
|
68611
68763
|
return layer.transactionImmediate(async (tx) => withTaskWorkflowSerialization(tx, layer.projectId, input.taskId, async () => {
|
|
68612
68764
|
const active2 = await tx.select({ id: project_exports.workflowWorkItems.id }).from(project_exports.workflowWorkItems).where(and(
|
|
68613
68765
|
projectScopeFor(project_exports.workflowWorkItems.projectId, layer.projectId),
|
|
68614
68766
|
eq(project_exports.workflowWorkItems.taskId, input.taskId),
|
|
68615
68767
|
inArray(project_exports.workflowWorkItems.state, [...ACTIVE_WORKFLOW_WORK_ITEM_STATES])
|
|
68616
68768
|
));
|
|
68617
|
-
|
|
68769
|
+
const blocking = options.retirePredecessorId ? active2.filter((row) => row.id !== options.retirePredecessorId) : active2;
|
|
68770
|
+
if (blocking.length > 0) return { seeded: false, reason: "active-continuation" };
|
|
68618
68771
|
const taskRows = await tx.select({ workflowStepResults: project_exports.tasks.workflowStepResults }).from(project_exports.tasks).where(and(
|
|
68619
68772
|
projectScopeFor(project_exports.tasks.projectId, layer.projectId),
|
|
68620
68773
|
eq(project_exports.tasks.id, input.taskId)
|
|
68621
68774
|
)).limit(1);
|
|
68622
68775
|
const results = taskRows[0]?.workflowStepResults;
|
|
68623
68776
|
if (results?.some(isPlanReviewSatisfied)) return { seeded: false, reason: "plan-review-passed" };
|
|
68777
|
+
if (options.retirePredecessorId) {
|
|
68778
|
+
const predRows = await tx.select().from(project_exports.workflowWorkItems).where(and(
|
|
68779
|
+
projectScopeFor(project_exports.workflowWorkItems.projectId, layer.projectId),
|
|
68780
|
+
eq(project_exports.workflowWorkItems.id, options.retirePredecessorId),
|
|
68781
|
+
eq(project_exports.workflowWorkItems.taskId, input.taskId)
|
|
68782
|
+
)).limit(1);
|
|
68783
|
+
const pred = predRows[0];
|
|
68784
|
+
if (pred && !isTerminalWorkflowWorkItemState(normalizeWorkflowWorkItemState(pred.state))) {
|
|
68785
|
+
await transitionWorkflowWorkItem(layer, pred.id, "succeeded", { leaseOwner: null, leaseExpiresAt: null, lastError: null }, tx);
|
|
68786
|
+
}
|
|
68787
|
+
}
|
|
68624
68788
|
const item = await upsertWorkflowWorkItem(layer, input, tx);
|
|
68625
68789
|
return { seeded: true, workItemId: item.id };
|
|
68626
68790
|
}));
|
|
@@ -68784,8 +68948,10 @@ function safeJsonParse(value2) {
|
|
|
68784
68948
|
return null;
|
|
68785
68949
|
}
|
|
68786
68950
|
}
|
|
68787
|
-
async function queryRunAuditEvents(db, filter2 = {}) {
|
|
68788
|
-
const conditions = []
|
|
68951
|
+
async function queryRunAuditEvents(db, filter2 = {}, projectId2) {
|
|
68952
|
+
const conditions = [projectScopeFor(project_exports.runAuditEvents.projectId, projectId2)].filter(
|
|
68953
|
+
(condition) => condition !== void 0
|
|
68954
|
+
);
|
|
68789
68955
|
if (filter2.runId) {
|
|
68790
68956
|
conditions.push(eq(project_exports.runAuditEvents.runId, filter2.runId));
|
|
68791
68957
|
}
|
|
@@ -68931,6 +69097,7 @@ var init_async_audit = __esm({
|
|
|
68931
69097
|
init_drizzle_orm();
|
|
68932
69098
|
init_schema2();
|
|
68933
69099
|
init_data_layer();
|
|
69100
|
+
init_data_layer();
|
|
68934
69101
|
LEGACY_REVIEW_LANES3 = ["in-review"];
|
|
68935
69102
|
LEGACY_COMPLETE_LANES = ["done"];
|
|
68936
69103
|
}
|
|
@@ -69320,7 +69487,10 @@ async function insertArtifactRow(layer, input, stored, archivedColumns) {
|
|
|
69320
69487
|
createdAt: now,
|
|
69321
69488
|
updatedAt: now
|
|
69322
69489
|
});
|
|
69323
|
-
const rows = await tx.select().from(project_exports.artifacts).where(
|
|
69490
|
+
const rows = await tx.select().from(project_exports.artifacts).where(and(
|
|
69491
|
+
eq(project_exports.artifacts.id, id),
|
|
69492
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
69493
|
+
)).limit(1);
|
|
69324
69494
|
const row = rows[0];
|
|
69325
69495
|
if (!row) throw new Error(`Failed to register artifact ${id}`);
|
|
69326
69496
|
return rowToArtifact2(row);
|
|
@@ -69328,7 +69498,7 @@ async function insertArtifactRow(layer, input, stored, archivedColumns) {
|
|
|
69328
69498
|
}
|
|
69329
69499
|
async function updateArtifactRow(layer, id, updates, archivedColumns) {
|
|
69330
69500
|
return layer.transactionImmediate(async (tx) => {
|
|
69331
|
-
const existing = await getArtifact(tx, id);
|
|
69501
|
+
const existing = await getArtifact(tx, id, layer.projectId);
|
|
69332
69502
|
if (!existing) {
|
|
69333
69503
|
throw new Error(`Artifact ${id} not found`);
|
|
69334
69504
|
}
|
|
@@ -69348,29 +69518,38 @@ async function updateArtifactRow(layer, id, updates, archivedColumns) {
|
|
|
69348
69518
|
description: updates.description !== void 0 ? updates.description : existing.description ?? null,
|
|
69349
69519
|
content: updates.content !== void 0 ? updates.content : existing.content ?? null,
|
|
69350
69520
|
updatedAt: now
|
|
69351
|
-
}).where(
|
|
69352
|
-
|
|
69521
|
+
}).where(and(
|
|
69522
|
+
eq(project_exports.artifacts.id, id),
|
|
69523
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
69524
|
+
));
|
|
69525
|
+
const updated = await getArtifact(tx, id, layer.projectId);
|
|
69353
69526
|
if (!updated) {
|
|
69354
69527
|
throw new Error(`Failed to update artifact ${id}`);
|
|
69355
69528
|
}
|
|
69356
69529
|
return updated;
|
|
69357
69530
|
});
|
|
69358
69531
|
}
|
|
69359
|
-
async function getArtifact(db, id) {
|
|
69360
|
-
const rows = await db.select().from(project_exports.artifacts).where(
|
|
69532
|
+
async function getArtifact(db, id, projectId2) {
|
|
69533
|
+
const rows = await db.select().from(project_exports.artifacts).where(and(
|
|
69534
|
+
eq(project_exports.artifacts.id, id),
|
|
69535
|
+
projectScopeFor(project_exports.artifacts.projectId, projectId2)
|
|
69536
|
+
)).limit(1);
|
|
69361
69537
|
const row = rows[0];
|
|
69362
69538
|
return row ? rowToArtifact2(row) : null;
|
|
69363
69539
|
}
|
|
69364
69540
|
async function getArtifacts(db, taskId, projectId2, archivedColumns) {
|
|
69365
69541
|
const column = await getLiveTaskColumn(db, taskId, projectId2, archivedColumns);
|
|
69366
69542
|
if (column === null || column === "archived") return [];
|
|
69367
|
-
const rows = await db.select().from(project_exports.artifacts).where(
|
|
69543
|
+
const rows = await db.select().from(project_exports.artifacts).where(and(
|
|
69544
|
+
eq(project_exports.artifacts.taskId, taskId),
|
|
69545
|
+
projectScopeFor(project_exports.artifacts.projectId, projectId2)
|
|
69546
|
+
)).orderBy(desc(project_exports.artifacts.createdAt));
|
|
69368
69547
|
return rows.map((row) => rowToArtifact2(row));
|
|
69369
69548
|
}
|
|
69370
|
-
async function listArtifacts(db, options) {
|
|
69549
|
+
async function listArtifacts(db, options, projectId2) {
|
|
69371
69550
|
const limit2 = Math.min(Math.max(1, options?.limit ?? 200), 1e3);
|
|
69372
69551
|
const offset = Math.max(0, options?.offset ?? 0);
|
|
69373
|
-
const conditions = [];
|
|
69552
|
+
const conditions = [projectScopeFor(project_exports.artifacts.projectId, projectId2)];
|
|
69374
69553
|
if (options?.type) {
|
|
69375
69554
|
conditions.push(eq(project_exports.artifacts.type, options.type));
|
|
69376
69555
|
}
|
|
@@ -69409,7 +69588,10 @@ async function listArtifacts(db, options) {
|
|
|
69409
69588
|
taskColumn: project_exports.tasks.column
|
|
69410
69589
|
}).from(project_exports.artifacts).leftJoin(
|
|
69411
69590
|
project_exports.tasks,
|
|
69412
|
-
|
|
69591
|
+
and(
|
|
69592
|
+
eq(project_exports.artifacts.taskId, project_exports.tasks.id),
|
|
69593
|
+
eq(project_exports.artifacts.projectId, project_exports.tasks.projectId)
|
|
69594
|
+
)
|
|
69413
69595
|
).where(and(...conditions)).orderBy(desc(project_exports.artifacts.createdAt)).limit(limit2).offset(offset);
|
|
69414
69596
|
return rows.map((row) => {
|
|
69415
69597
|
const artifact = rowToArtifact2(row);
|
|
@@ -70574,7 +70756,7 @@ function rowToBranchGroup2(row) {
|
|
|
70574
70756
|
closedAt: row.closedAt ?? void 0
|
|
70575
70757
|
};
|
|
70576
70758
|
}
|
|
70577
|
-
async function createBranchGroup(db, input) {
|
|
70759
|
+
async function createBranchGroup(db, input, projectId2) {
|
|
70578
70760
|
validateBranchGroupBranchName(input.branchName);
|
|
70579
70761
|
const now = Date.now();
|
|
70580
70762
|
const id = generateBranchGroupId2();
|
|
@@ -70593,44 +70775,52 @@ async function createBranchGroup(db, input) {
|
|
|
70593
70775
|
updatedAt: now,
|
|
70594
70776
|
closedAt: input.closedAt ?? null
|
|
70595
70777
|
});
|
|
70596
|
-
const created = await getBranchGroup(db, id);
|
|
70778
|
+
const created = await getBranchGroup(db, id, projectId2);
|
|
70597
70779
|
if (!created) throw new Error(`Failed to read branch group ${id} after create`);
|
|
70598
70780
|
return created;
|
|
70599
70781
|
}
|
|
70600
|
-
async function getBranchGroup(db, id) {
|
|
70601
|
-
const rows = await db.select().from(project_exports.branchGroups).where(
|
|
70782
|
+
async function getBranchGroup(db, id, projectId2) {
|
|
70783
|
+
const rows = await db.select().from(project_exports.branchGroups).where(and(
|
|
70784
|
+
eq(project_exports.branchGroups.id, id),
|
|
70785
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70786
|
+
)).limit(1);
|
|
70602
70787
|
const row = rows[0];
|
|
70603
70788
|
return row ? rowToBranchGroup2(row) : null;
|
|
70604
70789
|
}
|
|
70605
|
-
async function getBranchGroupBySource(db, sourceType, sourceId) {
|
|
70790
|
+
async function getBranchGroupBySource(db, sourceType, sourceId, projectId2) {
|
|
70606
70791
|
const rows = await db.select().from(project_exports.branchGroups).where(
|
|
70607
70792
|
and(
|
|
70608
70793
|
eq(project_exports.branchGroups.sourceType, sourceType),
|
|
70609
|
-
eq(project_exports.branchGroups.sourceId, sourceId)
|
|
70794
|
+
eq(project_exports.branchGroups.sourceId, sourceId),
|
|
70795
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70610
70796
|
)
|
|
70611
70797
|
).limit(1);
|
|
70612
70798
|
const row = rows[0];
|
|
70613
70799
|
return row ? rowToBranchGroup2(row) : null;
|
|
70614
70800
|
}
|
|
70615
|
-
async function getBranchGroupByBranchName(db, branchName) {
|
|
70616
|
-
const rows = await db.select().from(project_exports.branchGroups).where(
|
|
70801
|
+
async function getBranchGroupByBranchName(db, branchName, projectId2) {
|
|
70802
|
+
const rows = await db.select().from(project_exports.branchGroups).where(and(
|
|
70803
|
+
eq(project_exports.branchGroups.branchName, branchName),
|
|
70804
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70805
|
+
)).orderBy(sql`${project_exports.branchGroups.createdAt} DESC`).limit(1);
|
|
70617
70806
|
const row = rows[0];
|
|
70618
70807
|
return row ? rowToBranchGroup2(row) : null;
|
|
70619
70808
|
}
|
|
70620
|
-
async function ensureBranchGroupForSource(db, sourceType, sourceId, init) {
|
|
70621
|
-
const existing = await getBranchGroupBySource(db, sourceType, sourceId);
|
|
70809
|
+
async function ensureBranchGroupForSource(db, sourceType, sourceId, init, projectId2) {
|
|
70810
|
+
const existing = await getBranchGroupBySource(db, sourceType, sourceId, projectId2);
|
|
70622
70811
|
if (existing) return existing;
|
|
70623
|
-
const existingByBranch = await getBranchGroupByBranchName(db, init.branchName);
|
|
70812
|
+
const existingByBranch = await getBranchGroupByBranchName(db, init.branchName, projectId2);
|
|
70624
70813
|
if (existingByBranch) return existingByBranch;
|
|
70625
|
-
return createBranchGroup(db, { sourceType, sourceId, ...init });
|
|
70814
|
+
return createBranchGroup(db, { sourceType, sourceId, ...init }, projectId2);
|
|
70626
70815
|
}
|
|
70627
|
-
async function listBranchGroups(db, options) {
|
|
70628
|
-
const
|
|
70629
|
-
|
|
70816
|
+
async function listBranchGroups(db, options, projectId2) {
|
|
70817
|
+
const conditions = [projectScopeFor(project_exports.branchGroups.projectId, projectId2)];
|
|
70818
|
+
if (options?.status) conditions.push(eq(project_exports.branchGroups.status, options.status));
|
|
70819
|
+
const rows = await db.select().from(project_exports.branchGroups).where(and(...conditions)).orderBy(asc(project_exports.branchGroups.createdAt));
|
|
70630
70820
|
return rows.map((row) => rowToBranchGroup2(row));
|
|
70631
70821
|
}
|
|
70632
|
-
async function updateBranchGroup(db, id, patch) {
|
|
70633
|
-
const current = await getBranchGroup(db, id);
|
|
70822
|
+
async function updateBranchGroup(db, id, patch, projectId2) {
|
|
70823
|
+
const current = await getBranchGroup(db, id, projectId2);
|
|
70634
70824
|
if (!current) throw new Error(`Branch group ${id} not found`);
|
|
70635
70825
|
if (patch.branchName !== void 0) {
|
|
70636
70826
|
validateBranchGroupBranchName(patch.branchName);
|
|
@@ -70649,8 +70839,11 @@ async function updateBranchGroup(db, id, patch) {
|
|
|
70649
70839
|
status: nextStatus,
|
|
70650
70840
|
updatedAt: now,
|
|
70651
70841
|
closedAt: nextClosedAt
|
|
70652
|
-
}).where(
|
|
70653
|
-
|
|
70842
|
+
}).where(and(
|
|
70843
|
+
eq(project_exports.branchGroups.id, id),
|
|
70844
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70845
|
+
));
|
|
70846
|
+
const updated = await getBranchGroup(db, id, projectId2);
|
|
70654
70847
|
if (!updated) throw new Error(`Branch group ${id} disappeared after update`);
|
|
70655
70848
|
return updated;
|
|
70656
70849
|
}
|
|
@@ -70807,6 +71000,7 @@ var init_async_branch_groups = __esm({
|
|
|
70807
71000
|
"use strict";
|
|
70808
71001
|
init_drizzle_orm();
|
|
70809
71002
|
init_schema2();
|
|
71003
|
+
init_data_layer();
|
|
70810
71004
|
init_branch_assignment();
|
|
70811
71005
|
}
|
|
70812
71006
|
});
|
|
@@ -80620,6 +80814,9 @@ import { randomUUID as randomUUID21 } from "node:crypto";
|
|
|
80620
80814
|
function tableForScope(scope) {
|
|
80621
80815
|
return scope === "project" ? project_exports.secrets : central_exports.secretsGlobal;
|
|
80622
80816
|
}
|
|
80817
|
+
function scopeForSecretTable(scope, table, projectId2) {
|
|
80818
|
+
return scope === "project" ? projectScopeFor(table.projectId, projectId2) : void 0;
|
|
80819
|
+
}
|
|
80623
80820
|
function isAccessPolicy(value2) {
|
|
80624
80821
|
return value2 === "auto" || value2 === "prompt" || value2 === "deny";
|
|
80625
80822
|
}
|
|
@@ -80642,23 +80839,23 @@ function rowToRecord2(row, scope) {
|
|
|
80642
80839
|
lastReadBy: row.lastReadBy
|
|
80643
80840
|
};
|
|
80644
80841
|
}
|
|
80645
|
-
async function getSecretMetadata(handle, id, scope) {
|
|
80842
|
+
async function getSecretMetadata(handle, id, scope, projectId2) {
|
|
80646
80843
|
const table = tableForScope(scope);
|
|
80647
|
-
const rows = await handle.select(metadataColumns(table)).from(table).where(eq(table.id, id)).limit(1);
|
|
80844
|
+
const rows = await handle.select(metadataColumns(table)).from(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2))).limit(1);
|
|
80648
80845
|
const row = rows[0];
|
|
80649
80846
|
return row ? rowToRecord2(row, scope) : null;
|
|
80650
80847
|
}
|
|
80651
|
-
async function listSecrets(handle, scope) {
|
|
80848
|
+
async function listSecrets(handle, scope, projectId2) {
|
|
80652
80849
|
if (scope) {
|
|
80653
80850
|
const table = tableForScope(scope);
|
|
80654
|
-
const rows = await handle.select(metadataColumns(table)).from(table).orderBy(asc(sql`lower(${table.key})`));
|
|
80851
|
+
const rows = await handle.select(metadataColumns(table)).from(table).where(scopeForSecretTable(scope, table, projectId2)).orderBy(asc(sql`lower(${table.key})`));
|
|
80655
80852
|
return rows.map((row) => rowToRecord2(row, scope));
|
|
80656
80853
|
}
|
|
80657
|
-
const project = await listSecrets(handle, "project");
|
|
80658
|
-
const global2 = await listSecrets(handle, "global");
|
|
80854
|
+
const project = await listSecrets(handle, "project", projectId2);
|
|
80855
|
+
const global2 = await listSecrets(handle, "global", projectId2);
|
|
80659
80856
|
return [...project, ...global2];
|
|
80660
80857
|
}
|
|
80661
|
-
async function createSecret(handle, cipher, input) {
|
|
80858
|
+
async function createSecret(handle, cipher, input, projectId2) {
|
|
80662
80859
|
const key = input.key.trim();
|
|
80663
80860
|
if (!key) {
|
|
80664
80861
|
throw new SecretsStoreError({ code: "invalid-key", message: "Secret key is required" });
|
|
@@ -80672,6 +80869,7 @@ async function createSecret(handle, cipher, input) {
|
|
|
80672
80869
|
const table = tableForScope(input.scope);
|
|
80673
80870
|
try {
|
|
80674
80871
|
await handle.insert(table).values({
|
|
80872
|
+
...input.scope === "project" && projectId2?.trim() ? { projectId: projectId2 } : {},
|
|
80675
80873
|
id,
|
|
80676
80874
|
key,
|
|
80677
80875
|
valueCiphertext: encrypted.ciphertext,
|
|
@@ -80691,14 +80889,14 @@ async function createSecret(handle, cipher, input) {
|
|
|
80691
80889
|
}
|
|
80692
80890
|
throw error3;
|
|
80693
80891
|
}
|
|
80694
|
-
const created = await getSecretMetadata(handle, id, input.scope);
|
|
80892
|
+
const created = await getSecretMetadata(handle, id, input.scope, projectId2);
|
|
80695
80893
|
if (!created) {
|
|
80696
80894
|
throw new SecretsStoreError({ code: "not-found", message: "Secret insert succeeded but row could not be read back" });
|
|
80697
80895
|
}
|
|
80698
80896
|
return created;
|
|
80699
80897
|
}
|
|
80700
|
-
async function updateSecret(handle, cipher, id, scope, patch) {
|
|
80701
|
-
const existing = await getSecretMetadata(handle, id, scope);
|
|
80898
|
+
async function updateSecret(handle, cipher, id, scope, patch, projectId2) {
|
|
80899
|
+
const existing = await getSecretMetadata(handle, id, scope, projectId2);
|
|
80702
80900
|
if (!existing) {
|
|
80703
80901
|
throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
|
|
80704
80902
|
}
|
|
@@ -80732,34 +80930,34 @@ async function updateSecret(handle, cipher, id, scope, patch) {
|
|
|
80732
80930
|
updates.nonce = encrypted.nonce;
|
|
80733
80931
|
}
|
|
80734
80932
|
try {
|
|
80735
|
-
await handle.update(table).set(updates).where(eq(table.id, id));
|
|
80933
|
+
await handle.update(table).set(updates).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
|
|
80736
80934
|
} catch (error3) {
|
|
80737
80935
|
if (isPostgresUniqueError(error3)) {
|
|
80738
80936
|
throw new SecretsStoreError({ code: "duplicate-key", message: "Secret key already exists" });
|
|
80739
80937
|
}
|
|
80740
80938
|
throw error3;
|
|
80741
80939
|
}
|
|
80742
|
-
const updated = await getSecretMetadata(handle, id, scope);
|
|
80940
|
+
const updated = await getSecretMetadata(handle, id, scope, projectId2);
|
|
80743
80941
|
if (!updated) {
|
|
80744
80942
|
throw new SecretsStoreError({ code: "not-found", message: "Secret update succeeded but row could not be read back" });
|
|
80745
80943
|
}
|
|
80746
80944
|
return updated;
|
|
80747
80945
|
}
|
|
80748
|
-
async function deleteSecret(handle, id, scope) {
|
|
80749
|
-
const existing = await getSecretMetadata(handle, id, scope);
|
|
80946
|
+
async function deleteSecret(handle, id, scope, projectId2) {
|
|
80947
|
+
const existing = await getSecretMetadata(handle, id, scope, projectId2);
|
|
80750
80948
|
if (!existing) {
|
|
80751
80949
|
throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
|
|
80752
80950
|
}
|
|
80753
80951
|
const table = tableForScope(scope);
|
|
80754
|
-
await handle.delete(table).where(eq(table.id, id));
|
|
80952
|
+
await handle.delete(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
|
|
80755
80953
|
}
|
|
80756
|
-
async function revealSecret(handle, cipher, id, scope, reader) {
|
|
80954
|
+
async function revealSecret(handle, cipher, id, scope, reader, projectId2) {
|
|
80757
80955
|
const table = tableForScope(scope);
|
|
80758
80956
|
const rows = await handle.select({
|
|
80759
80957
|
...metadataColumns(table),
|
|
80760
80958
|
valueCiphertext: table.valueCiphertext,
|
|
80761
80959
|
nonce: table.nonce
|
|
80762
|
-
}).from(table).where(eq(table.id, id)).limit(1);
|
|
80960
|
+
}).from(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2))).limit(1);
|
|
80763
80961
|
const row = rows[0];
|
|
80764
80962
|
if (!row) {
|
|
80765
80963
|
throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
|
|
@@ -80778,7 +80976,7 @@ async function revealSecret(handle, cipher, id, scope, reader) {
|
|
|
80778
80976
|
}
|
|
80779
80977
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
80780
80978
|
const lastReadBy = reader.userId ?? reader.agentId ?? null;
|
|
80781
|
-
await handle.update(table).set({ lastReadAt: now, lastReadBy, updatedAt: now }).where(eq(table.id, id));
|
|
80979
|
+
await handle.update(table).set({ lastReadAt: now, lastReadBy, updatedAt: now }).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
|
|
80782
80980
|
return { key: row.key, plaintextValue };
|
|
80783
80981
|
}
|
|
80784
80982
|
var severityAuditLog10, SecretsStoreError, metadataColumns;
|
|
@@ -80789,6 +80987,7 @@ var init_async_secrets_store = __esm({
|
|
|
80789
80987
|
init_drizzle_orm();
|
|
80790
80988
|
init_postgres_errors();
|
|
80791
80989
|
init_schema2();
|
|
80990
|
+
init_data_layer();
|
|
80792
80991
|
init_secrets_crypto();
|
|
80793
80992
|
severityAuditLog10 = createLogger("core-async-secrets-store");
|
|
80794
80993
|
SecretsStoreError = class extends Error {
|
|
@@ -80884,7 +81083,7 @@ var init_secrets_store = __esm({
|
|
|
80884
81083
|
};
|
|
80885
81084
|
}
|
|
80886
81085
|
async listSecrets(scope) {
|
|
80887
|
-
return listSecrets(this.asyncLayer.db, scope);
|
|
81086
|
+
return listSecrets(this.asyncLayer.db, scope, this.asyncLayer.projectId);
|
|
80888
81087
|
}
|
|
80889
81088
|
async listEnvExportable(opts) {
|
|
80890
81089
|
const keyPrefix = opts?.keyPrefix;
|
|
@@ -80927,7 +81126,7 @@ var init_secrets_store = __esm({
|
|
|
80927
81126
|
return [...exported.values()];
|
|
80928
81127
|
}
|
|
80929
81128
|
async getSecretMetadata(id, scope) {
|
|
80930
|
-
return getSecretMetadata(this.asyncLayer.db, id, scope);
|
|
81129
|
+
return getSecretMetadata(this.asyncLayer.db, id, scope, this.asyncLayer.projectId);
|
|
80931
81130
|
}
|
|
80932
81131
|
async createSecret(input) {
|
|
80933
81132
|
const key = input.key.trim();
|
|
@@ -80937,12 +81136,12 @@ var init_secrets_store = __esm({
|
|
|
80937
81136
|
if (input.accessPolicy && !isAccessPolicy2(input.accessPolicy)) {
|
|
80938
81137
|
throw new SecretsStoreError2({ code: "invalid-policy", message: "Invalid access policy" });
|
|
80939
81138
|
}
|
|
80940
|
-
const created = await createSecret(this.asyncLayer.db, this.cipher, input);
|
|
81139
|
+
const created = await createSecret(this.asyncLayer.db, this.cipher, input, this.asyncLayer.projectId);
|
|
80941
81140
|
this.emitAudit({ mutationType: "secret:create", scope: input.scope, secretId: created.id, key: created.key });
|
|
80942
81141
|
return created;
|
|
80943
81142
|
}
|
|
80944
81143
|
async updateSecret(id, scope, patch) {
|
|
80945
|
-
const updated = await updateSecret(this.asyncLayer.db, this.cipher, id, scope, patch);
|
|
81144
|
+
const updated = await updateSecret(this.asyncLayer.db, this.cipher, id, scope, patch, this.asyncLayer.projectId);
|
|
80946
81145
|
this.emitAudit({ mutationType: "secret:update", scope, secretId: updated.id, key: updated.key });
|
|
80947
81146
|
return updated;
|
|
80948
81147
|
}
|
|
@@ -80951,12 +81150,12 @@ var init_secrets_store = __esm({
|
|
|
80951
81150
|
if (!existing) {
|
|
80952
81151
|
throw new SecretsStoreError2({ code: "not-found", message: "Secret not found" });
|
|
80953
81152
|
}
|
|
80954
|
-
await deleteSecret(this.asyncLayer.db, id, scope);
|
|
81153
|
+
await deleteSecret(this.asyncLayer.db, id, scope, this.asyncLayer.projectId);
|
|
80955
81154
|
this.emitAudit({ mutationType: "secret:delete", scope, secretId: id, key: existing.key });
|
|
80956
81155
|
return;
|
|
80957
81156
|
}
|
|
80958
81157
|
async revealSecret(id, scope, reader) {
|
|
80959
|
-
const revealed = await revealSecret(this.asyncLayer.db, this.cipher, id, scope, reader);
|
|
81158
|
+
const revealed = await revealSecret(this.asyncLayer.db, this.cipher, id, scope, reader, this.asyncLayer.projectId);
|
|
80960
81159
|
this.emitAudit({ mutationType: "secret:read", scope, secretId: id, key: revealed.key, actor: reader });
|
|
80961
81160
|
return revealed;
|
|
80962
81161
|
}
|
|
@@ -82057,6 +82256,7 @@ async function getVerificationCacheHitImpl(store, treeSha, testCommand, buildCom
|
|
|
82057
82256
|
const normalizedBuild = buildCommand2 ?? "";
|
|
82058
82257
|
const table = project_exports.verificationCache;
|
|
82059
82258
|
const rows = await store.asyncLayer.db.select({ recordedAt: table.recordedAt, taskId: table.taskId }).from(table).where(and(
|
|
82259
|
+
projectScopeFor(table.projectId, store.asyncLayer.projectId),
|
|
82060
82260
|
eq(table.treeSha, treeSha),
|
|
82061
82261
|
eq(table.testCommand, normalizedTest),
|
|
82062
82262
|
eq(table.buildCommand, normalizedBuild)
|
|
@@ -82799,7 +82999,7 @@ async function invokeTaskCreatedHookImpl(store, task) {
|
|
|
82799
82999
|
}
|
|
82800
83000
|
async function createBranchGroupImpl(store, input) {
|
|
82801
83001
|
const layer = store.asyncLayer;
|
|
82802
|
-
return createBranchGroup(layer.db, input);
|
|
83002
|
+
return createBranchGroup(layer.db, input, layer.projectId);
|
|
82803
83003
|
}
|
|
82804
83004
|
var init_task_id_integrity2 = __esm({
|
|
82805
83005
|
"../core/src/task-store/task-id-integrity.ts"() {
|
|
@@ -82884,22 +83084,23 @@ import { readFile as readFile7, writeFile as writeFile5 } from "node:fs/promises
|
|
|
82884
83084
|
import { join as join23 } from "node:path";
|
|
82885
83085
|
async function getBranchGroupImpl(store, id) {
|
|
82886
83086
|
const layer = store.asyncLayer;
|
|
82887
|
-
return getBranchGroup(layer.db, id);
|
|
83087
|
+
return getBranchGroup(layer.db, id, layer.projectId);
|
|
82888
83088
|
}
|
|
82889
83089
|
async function getBranchGroupBySourceImpl(store, sourceType, sourceId) {
|
|
82890
83090
|
const layer = store.asyncLayer;
|
|
82891
|
-
return getBranchGroupBySource(layer.db, sourceType, sourceId);
|
|
83091
|
+
return getBranchGroupBySource(layer.db, sourceType, sourceId, layer.projectId);
|
|
82892
83092
|
}
|
|
82893
83093
|
async function getBranchGroupByBranchNameImpl(store, branchName) {
|
|
82894
83094
|
const layer = store.asyncLayer;
|
|
82895
|
-
return getBranchGroupByBranchName(layer.db, branchName);
|
|
83095
|
+
return getBranchGroupByBranchName(layer.db, branchName, layer.projectId);
|
|
82896
83096
|
}
|
|
82897
83097
|
async function ensureBranchGroupForSourceImpl(store, sourceType, sourceId, init) {
|
|
82898
|
-
|
|
83098
|
+
const layer = store.asyncLayer;
|
|
83099
|
+
return ensureBranchGroupForSource(layer.db, sourceType, sourceId, init, layer.projectId);
|
|
82899
83100
|
}
|
|
82900
83101
|
async function listBranchGroupsImpl(store, options) {
|
|
82901
83102
|
const layer = store.asyncLayer;
|
|
82902
|
-
return listBranchGroups(layer.db, options);
|
|
83103
|
+
return listBranchGroups(layer.db, options, layer.projectId);
|
|
82903
83104
|
}
|
|
82904
83105
|
async function listTasksByBranchGroupImpl(store, groupId) {
|
|
82905
83106
|
const tasks2 = await store.listTasks({ includeArchived: true, slim: false });
|
|
@@ -84441,7 +84642,7 @@ function insertArtifactRowImpl(store, input, id, now, stored) {
|
|
|
84441
84642
|
}
|
|
84442
84643
|
async function getArtifactImpl(store, id) {
|
|
84443
84644
|
const layer = store.asyncLayer;
|
|
84444
|
-
return getArtifact(layer.db, id);
|
|
84645
|
+
return getArtifact(layer.db, id, layer.projectId);
|
|
84445
84646
|
}
|
|
84446
84647
|
async function updateArtifactImpl(store, id, updates) {
|
|
84447
84648
|
const layer = store.asyncLayer;
|
|
@@ -89310,6 +89511,7 @@ var init_async_archive_lineage = __esm({
|
|
|
89310
89511
|
"use strict";
|
|
89311
89512
|
init_drizzle_orm();
|
|
89312
89513
|
init_schema2();
|
|
89514
|
+
init_data_layer();
|
|
89313
89515
|
init_async_persistence();
|
|
89314
89516
|
init_async_lifecycle();
|
|
89315
89517
|
init_lineage_approval_invalidation();
|
|
@@ -92777,7 +92979,7 @@ async function _maybeAutoArchiveSameAgentDuplicateBackendImpl(store, task, input
|
|
|
92777
92979
|
}
|
|
92778
92980
|
async function updateBranchGroupImpl(store, id, patch) {
|
|
92779
92981
|
const layer = store.asyncLayer;
|
|
92780
|
-
return updateBranchGroup(layer.db, id, patch);
|
|
92982
|
+
return updateBranchGroup(layer.db, id, patch, layer.projectId);
|
|
92781
92983
|
}
|
|
92782
92984
|
async function updatePrEntityImpl(store, id, patch) {
|
|
92783
92985
|
const layer = store.asyncLayer;
|
|
@@ -93287,13 +93489,19 @@ async function deleteAttachmentArtifactRows(store, taskId, filename) {
|
|
|
93287
93489
|
const linkedArtifactIds = artifacts2.filter((artifact) => artifact.metadata?.source === "attachment" && artifact.metadata.attachmentFilename === filename).map((artifact) => artifact.id);
|
|
93288
93490
|
if (linkedArtifactIds.length === 0) return;
|
|
93289
93491
|
for (const artifactId of linkedArtifactIds) {
|
|
93290
|
-
await layer.db.delete(project_exports.artifacts).where(
|
|
93492
|
+
await layer.db.delete(project_exports.artifacts).where(and(
|
|
93493
|
+
eq(project_exports.artifacts.id, artifactId),
|
|
93494
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
93495
|
+
));
|
|
93291
93496
|
}
|
|
93292
93497
|
return;
|
|
93293
93498
|
}
|
|
93294
93499
|
async function getArtifactsForAttachmentCleanup(store, taskId) {
|
|
93295
93500
|
const layer = store.asyncLayer;
|
|
93296
|
-
const rows = await layer.db.select().from(project_exports.artifacts).where(
|
|
93501
|
+
const rows = await layer.db.select().from(project_exports.artifacts).where(and(
|
|
93502
|
+
eq(project_exports.artifacts.taskId, taskId),
|
|
93503
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
93504
|
+
));
|
|
93297
93505
|
return rows;
|
|
93298
93506
|
}
|
|
93299
93507
|
async function deleteAttachmentImpl(store, id, filename) {
|
|
@@ -95709,7 +95917,7 @@ function clearLinkedAgentTaskIdsImpl(store, taskId, updatedAt = (/* @__PURE__ */
|
|
|
95709
95917
|
`).run(updatedAt, updatedAt, taskId);
|
|
95710
95918
|
}
|
|
95711
95919
|
async function listArtifactsImpl(store, options) {
|
|
95712
|
-
return listArtifacts(store.asyncLayer.db, options);
|
|
95920
|
+
return listArtifacts(store.asyncLayer.db, options, store.asyncLayer.projectId);
|
|
95713
95921
|
}
|
|
95714
95922
|
async function rehomeOccupantImpl(store, taskId, targetColumn, reason, metadata) {
|
|
95715
95923
|
let current;
|
|
@@ -96954,8 +97162,8 @@ async function upsertWorkflowWorkItemImpl(store, input, tx) {
|
|
|
96954
97162
|
async function replaceActiveTaskWorkflowContinuationImpl(store, input) {
|
|
96955
97163
|
return replaceActiveTaskWorkflowContinuation(store.asyncLayer, input);
|
|
96956
97164
|
}
|
|
96957
|
-
async function seedStrandedPlanReviewContinuationImpl(store, input) {
|
|
96958
|
-
return seedStrandedPlanReviewContinuation(store.asyncLayer, input);
|
|
97165
|
+
async function seedStrandedPlanReviewContinuationImpl(store, input, options = {}) {
|
|
97166
|
+
return seedStrandedPlanReviewContinuation(store.asyncLayer, input, options);
|
|
96959
97167
|
}
|
|
96960
97168
|
async function transitionWorkflowWorkItemImpl(store, id, state, patch = {}, tx) {
|
|
96961
97169
|
return transitionWorkflowWorkItem(store.asyncLayer, id, state, patch, tx);
|
|
@@ -101098,6 +101306,37 @@ async function getTaskVerificationRequestAsyncImpl(store, taskId) {
|
|
|
101098
101306
|
const row = rows[0];
|
|
101099
101307
|
return row ? { taskId: row.taskId, requestId: row.requestId, status: row.status, profile: row.profile, command: row.command, scope: row.scope, requestedBy: row.requestedBy, requestedAt: row.requestedAt, ...row.startedAt ? { startedAt: row.startedAt } : {}, ...row.completedAt ? { completedAt: row.completedAt } : {}, ...row.result ? { result: row.result } : {}, ...row.rejectionReason ? { rejectionReason: row.rejectionReason } : {} } : null;
|
|
101100
101308
|
}
|
|
101309
|
+
async function listTaskRecommendationsImpl(store, options) {
|
|
101310
|
+
const layer = store.asyncLayer;
|
|
101311
|
+
const completeColumns = options?.completeColumns ?? await resolveProjectColumnsForRoles(store, ["complete"]);
|
|
101312
|
+
const rawLimit = options?.limit;
|
|
101313
|
+
const rawOffset = options?.offset;
|
|
101314
|
+
const limit2 = typeof rawLimit === "number" && Number.isFinite(rawLimit) ? Math.min(200, Math.max(1, Math.trunc(rawLimit))) : 50;
|
|
101315
|
+
const offset = typeof rawOffset === "number" && Number.isFinite(rawOffset) ? Math.max(0, Math.trunc(rawOffset)) : 0;
|
|
101316
|
+
const columns = [...completeColumns];
|
|
101317
|
+
if (columns.length === 0) return { items: [], rowOffset: offset, rowLimit: limit2, returnedRowCount: 0, totalRowCount: 0, hasMore: false };
|
|
101318
|
+
const filter2 = and(
|
|
101319
|
+
taskProjectScope(layer),
|
|
101320
|
+
isNull(project_exports.tasks.deletedAt),
|
|
101321
|
+
inArray(project_exports.tasks.column, columns),
|
|
101322
|
+
isNotNull(project_exports.tasks.recommendations),
|
|
101323
|
+
sql`jsonb_array_length(${project_exports.tasks.recommendations}) > 0`
|
|
101324
|
+
);
|
|
101325
|
+
const [countRows, rows] = await Promise.all([
|
|
101326
|
+
layer.db.select({ count: sql`count(*)` }).from(project_exports.tasks).where(filter2),
|
|
101327
|
+
layer.db.select({ id: project_exports.tasks.id, title: project_exports.tasks.title, column: project_exports.tasks.column, updatedAt: project_exports.tasks.updatedAt, recommendations: project_exports.tasks.recommendations }).from(project_exports.tasks).where(filter2).orderBy(desc(project_exports.tasks.updatedAt), desc(project_exports.tasks.id)).limit(limit2).offset(offset)
|
|
101328
|
+
]);
|
|
101329
|
+
const items = [];
|
|
101330
|
+
for (const row of rows) {
|
|
101331
|
+
if (!Array.isArray(row.recommendations) || row.recommendations.length === 0) continue;
|
|
101332
|
+
for (const recommendation of row.recommendations) {
|
|
101333
|
+
items.push({ taskId: row.id, taskTitle: row.title ?? void 0, taskColumn: row.column, updatedAt: row.updatedAt, recommendation });
|
|
101334
|
+
}
|
|
101335
|
+
}
|
|
101336
|
+
const totalRowCount = Number(countRows[0]?.count ?? 0);
|
|
101337
|
+
const returnedRowCount = rows.length;
|
|
101338
|
+
return { items, rowOffset: offset, rowLimit: limit2, returnedRowCount, totalRowCount, hasMore: offset + returnedRowCount < totalRowCount };
|
|
101339
|
+
}
|
|
101101
101340
|
var LEGACY_REVIEW_LANES5, LEGACY_ARCHIVE_LANES2;
|
|
101102
101341
|
var init_reads = __esm({
|
|
101103
101342
|
"../core/src/task-store/reads.ts"() {
|
|
@@ -101120,6 +101359,7 @@ var init_reads = __esm({
|
|
|
101120
101359
|
init_retry_summary();
|
|
101121
101360
|
init_errors3();
|
|
101122
101361
|
init_project_lane_vocabulary();
|
|
101362
|
+
init_data_layer();
|
|
101123
101363
|
init_async_persistence();
|
|
101124
101364
|
init_async_search();
|
|
101125
101365
|
init_async_archive_db();
|
|
@@ -103226,6 +103466,9 @@ var init_store = __esm({
|
|
|
103226
103466
|
async clearWorkflowRunStepInstancesAsync(taskId, keepRunId) {
|
|
103227
103467
|
return clearWorkflowRunStepInstancesAsyncImpl(this, taskId, keepRunId);
|
|
103228
103468
|
}
|
|
103469
|
+
async listTaskRecommendations(options) {
|
|
103470
|
+
return listTaskRecommendationsImpl(this, options);
|
|
103471
|
+
}
|
|
103229
103472
|
async listTasksForGithubTrackingReconcile(options) {
|
|
103230
103473
|
return listTasksForGithubTrackingReconcileImpl(this, options);
|
|
103231
103474
|
}
|
|
@@ -103952,8 +104195,8 @@ var init_store = __esm({
|
|
|
103952
104195
|
async replaceActiveTaskWorkflowContinuation(input) {
|
|
103953
104196
|
return replaceActiveTaskWorkflowContinuationImpl(this, input);
|
|
103954
104197
|
}
|
|
103955
|
-
async seedStrandedPlanReviewContinuation(input) {
|
|
103956
|
-
return seedStrandedPlanReviewContinuationImpl(this, input);
|
|
104198
|
+
async seedStrandedPlanReviewContinuation(input, options = {}) {
|
|
104199
|
+
return seedStrandedPlanReviewContinuationImpl(this, input, options);
|
|
103957
104200
|
}
|
|
103958
104201
|
async transitionWorkflowWorkItem(id, state, patch = {}, tx) {
|
|
103959
104202
|
return transitionWorkflowWorkItemImpl(this, id, state, patch, tx);
|
|
@@ -104036,7 +104279,11 @@ var init_store = __esm({
|
|
|
104036
104279
|
/** PostgreSQL-authoritative audit reader; sync fallback remains for test doubles. */
|
|
104037
104280
|
async getRunAuditEventsAsync(options = {}) {
|
|
104038
104281
|
if (this.asyncLayer) {
|
|
104039
|
-
const events = await queryRunAuditEvents(
|
|
104282
|
+
const events = await queryRunAuditEvents(
|
|
104283
|
+
this.asyncLayer.db,
|
|
104284
|
+
options,
|
|
104285
|
+
this.asyncLayer.projectId
|
|
104286
|
+
);
|
|
104040
104287
|
return events.map((event) => ({
|
|
104041
104288
|
...event,
|
|
104042
104289
|
taskId: event.taskId ?? void 0,
|
|
@@ -107614,7 +107861,9 @@ function rangeWhere(query) {
|
|
|
107614
107861
|
async function aggregatePluginActivations(dbOrLayer, query = {}) {
|
|
107615
107862
|
if ("ping" in dbOrLayer) {
|
|
107616
107863
|
const layer = dbOrLayer;
|
|
107617
|
-
const conditions = []
|
|
107864
|
+
const conditions = [projectScopeFor(project_exports.pluginActivations.projectId, layer.projectId)].filter(
|
|
107865
|
+
(condition) => condition !== void 0
|
|
107866
|
+
);
|
|
107618
107867
|
if (query.from !== void 0) conditions.push(gte(project_exports.pluginActivations.activatedAt, query.from));
|
|
107619
107868
|
if (query.to !== void 0) conditions.push(lte(project_exports.pluginActivations.activatedAt, query.to));
|
|
107620
107869
|
const where2 = conditions.length > 0 ? and(...conditions) : void 0;
|
|
@@ -107653,6 +107902,7 @@ async function aggregatePluginActivations(dbOrLayer, query = {}) {
|
|
|
107653
107902
|
var init_plugin_activation_analytics = __esm({
|
|
107654
107903
|
"../core/src/plugins/plugin-activation-analytics.ts"() {
|
|
107655
107904
|
"use strict";
|
|
107905
|
+
init_data_layer();
|
|
107656
107906
|
init_drizzle_orm();
|
|
107657
107907
|
init_schema2();
|
|
107658
107908
|
}
|
|
@@ -130650,6 +130900,18 @@ function rowToMessage2(row) {
|
|
|
130650
130900
|
createdAt: row.createdAt
|
|
130651
130901
|
};
|
|
130652
130902
|
}
|
|
130903
|
+
function chatMessageProjectConditions(handle, projectId2) {
|
|
130904
|
+
const messageScope = projectScopeFor(project_exports.chatMessages.projectId, projectId2);
|
|
130905
|
+
const sessionScope = projectScopeFor(project_exports.chatSessions.projectId, projectId2);
|
|
130906
|
+
if (!messageScope || !sessionScope) return [];
|
|
130907
|
+
return [
|
|
130908
|
+
messageScope,
|
|
130909
|
+
exists(handle.select({ id: project_exports.chatSessions.id }).from(project_exports.chatSessions).where(and(
|
|
130910
|
+
eq(project_exports.chatSessions.id, project_exports.chatMessages.sessionId),
|
|
130911
|
+
sessionScope
|
|
130912
|
+
)))
|
|
130913
|
+
];
|
|
130914
|
+
}
|
|
130653
130915
|
function rowToRoom(row) {
|
|
130654
130916
|
return {
|
|
130655
130917
|
id: row.id,
|
|
@@ -130821,7 +131083,7 @@ async function replaceChatSessionTags(layer, sessionId, projectId2, tagIds) {
|
|
|
130821
131083
|
return attachTags(tx, session);
|
|
130822
131084
|
});
|
|
130823
131085
|
}
|
|
130824
|
-
async function addChatMessage(handle, message) {
|
|
131086
|
+
async function addChatMessage(handle, message, projectId2) {
|
|
130825
131087
|
const sanitizedAttachments = message.attachments === void 0 ? void 0 : sanitizeJsonbValue(message.attachments);
|
|
130826
131088
|
const sanitized = {
|
|
130827
131089
|
...message,
|
|
@@ -130840,15 +131102,24 @@ async function addChatMessage(handle, message) {
|
|
|
130840
131102
|
attachments: sanitizedAttachments ?? null,
|
|
130841
131103
|
createdAt: sanitized.createdAt
|
|
130842
131104
|
});
|
|
130843
|
-
await handle.update(project_exports.chatSessions).set({ updatedAt: sanitized.createdAt }).where(
|
|
131105
|
+
await handle.update(project_exports.chatSessions).set({ updatedAt: sanitized.createdAt }).where(and(
|
|
131106
|
+
eq(project_exports.chatSessions.id, sanitized.sessionId),
|
|
131107
|
+
projectScopeFor(project_exports.chatSessions.projectId, projectId2)
|
|
131108
|
+
));
|
|
130844
131109
|
return sanitized;
|
|
130845
131110
|
}
|
|
130846
|
-
async function getChatMessage(handle, id) {
|
|
130847
|
-
const rows = await handle.select().from(project_exports.chatMessages).where(
|
|
131111
|
+
async function getChatMessage(handle, id, projectId2) {
|
|
131112
|
+
const rows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131113
|
+
eq(project_exports.chatMessages.id, id),
|
|
131114
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131115
|
+
));
|
|
130848
131116
|
return rows[0] ? rowToMessage2(rows[0]) : void 0;
|
|
130849
131117
|
}
|
|
130850
|
-
async function getChatMessages(handle, sessionId, filter2) {
|
|
130851
|
-
const conditions = [
|
|
131118
|
+
async function getChatMessages(handle, sessionId, filter2, projectId2) {
|
|
131119
|
+
const conditions = [
|
|
131120
|
+
eq(project_exports.chatMessages.sessionId, sessionId),
|
|
131121
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131122
|
+
];
|
|
130852
131123
|
if (filter2?.before) {
|
|
130853
131124
|
conditions.push(lte(project_exports.chatMessages.createdAt, filter2.before));
|
|
130854
131125
|
}
|
|
@@ -130858,9 +131129,12 @@ async function getChatMessages(handle, sessionId, filter2) {
|
|
|
130858
131129
|
const rows = await handle.select().from(project_exports.chatMessages).where(and(...conditions)).orderBy(filter2?.order === "desc" ? desc(orderCol) : asc(orderCol)).limit(limit2).offset(offset);
|
|
130859
131130
|
return rows.map(rowToMessage2);
|
|
130860
131131
|
}
|
|
130861
|
-
async function getLastMessageForSessions(handle, sessionIds) {
|
|
131132
|
+
async function getLastMessageForSessions(handle, sessionIds, projectId2) {
|
|
130862
131133
|
if (sessionIds.length === 0) return /* @__PURE__ */ new Map();
|
|
130863
|
-
const rows = await handle.select().from(project_exports.chatMessages).where(
|
|
131134
|
+
const rows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131135
|
+
inArray(project_exports.chatMessages.sessionId, sessionIds),
|
|
131136
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131137
|
+
)).orderBy(
|
|
130864
131138
|
desc(project_exports.chatMessages.createdAt),
|
|
130865
131139
|
desc(project_exports.chatMessages.id)
|
|
130866
131140
|
);
|
|
@@ -131026,8 +131300,8 @@ async function setInFlightGeneration(handle, id, inFlightGeneration) {
|
|
|
131026
131300
|
await handle.update(project_exports.chatSessions).set({ inFlightGeneration: sanitizedInFlightGeneration }).where(eq(project_exports.chatSessions.id, id));
|
|
131027
131301
|
return getChatSession(handle, id);
|
|
131028
131302
|
}
|
|
131029
|
-
async function addChatMessageAttachment(handle, sessionId, messageId, attachment) {
|
|
131030
|
-
const message = await getChatMessage(handle, messageId);
|
|
131303
|
+
async function addChatMessageAttachment(handle, sessionId, messageId, attachment, projectId2) {
|
|
131304
|
+
const message = await getChatMessage(handle, messageId, projectId2);
|
|
131031
131305
|
if (!message || message.sessionId !== sessionId) {
|
|
131032
131306
|
throw new Error(`Message ${messageId} not found in session ${sessionId}`);
|
|
131033
131307
|
}
|
|
@@ -131035,25 +131309,35 @@ async function addChatMessageAttachment(handle, sessionId, messageId, attachment
|
|
|
131035
131309
|
...message.attachments ?? [],
|
|
131036
131310
|
attachment
|
|
131037
131311
|
]);
|
|
131038
|
-
await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(
|
|
131039
|
-
|
|
131312
|
+
await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(and(
|
|
131313
|
+
eq(project_exports.chatMessages.id, messageId),
|
|
131314
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131315
|
+
));
|
|
131316
|
+
const updated = await getChatMessage(handle, messageId, projectId2);
|
|
131040
131317
|
if (!updated) throw new Error(`Failed to update message ${messageId}`);
|
|
131041
131318
|
return updated;
|
|
131042
131319
|
}
|
|
131043
|
-
async function deleteChatMessage(handle, id) {
|
|
131044
|
-
const existing = await getChatMessage(handle, id);
|
|
131320
|
+
async function deleteChatMessage(handle, id, projectId2) {
|
|
131321
|
+
const existing = await getChatMessage(handle, id, projectId2);
|
|
131045
131322
|
if (!existing) return false;
|
|
131046
|
-
await handle.delete(project_exports.chatMessages).where(
|
|
131047
|
-
|
|
131323
|
+
await handle.delete(project_exports.chatMessages).where(and(
|
|
131324
|
+
eq(project_exports.chatMessages.id, id),
|
|
131325
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131326
|
+
));
|
|
131327
|
+
await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(
|
|
131328
|
+
eq(project_exports.chatSessions.id, existing.sessionId),
|
|
131329
|
+
projectScopeFor(project_exports.chatSessions.projectId, projectId2)
|
|
131330
|
+
));
|
|
131048
131331
|
return true;
|
|
131049
131332
|
}
|
|
131050
|
-
async function searchChatSessionsByMessageContent(handle, query, sessionIds) {
|
|
131333
|
+
async function searchChatSessionsByMessageContent(handle, query, sessionIds, projectId2) {
|
|
131051
131334
|
const trimmed = query.trim();
|
|
131052
131335
|
if (!trimmed || sessionIds.length === 0) return /* @__PURE__ */ new Map();
|
|
131053
131336
|
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
131054
131337
|
const rows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131055
131338
|
inArray(project_exports.chatMessages.sessionId, sessionIds),
|
|
131056
|
-
ilike(project_exports.chatMessages.content, `%${escaped}%`)
|
|
131339
|
+
ilike(project_exports.chatMessages.content, `%${escaped}%`),
|
|
131340
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131057
131341
|
)).orderBy(
|
|
131058
131342
|
desc(project_exports.chatMessages.createdAt),
|
|
131059
131343
|
desc(project_exports.chatMessages.id)
|
|
@@ -131067,13 +131351,16 @@ async function searchChatSessionsByMessageContent(handle, query, sessionIds) {
|
|
|
131067
131351
|
}
|
|
131068
131352
|
return result2;
|
|
131069
131353
|
}
|
|
131070
|
-
async function deleteChatMessagesFrom(handle, sessionId, fromMessageId) {
|
|
131071
|
-
const orderedRows = await handle.select().from(project_exports.chatMessages).where(
|
|
131354
|
+
async function deleteChatMessagesFrom(handle, sessionId, fromMessageId, projectId2) {
|
|
131355
|
+
const orderedRows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131356
|
+
eq(project_exports.chatMessages.sessionId, sessionId),
|
|
131357
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131358
|
+
)).orderBy(
|
|
131072
131359
|
asc(project_exports.chatMessages.createdAt),
|
|
131073
131360
|
asc(project_exports.chatMessages.id)
|
|
131074
131361
|
);
|
|
131075
131362
|
const ordered2 = orderedRows.map(rowToMessage2);
|
|
131076
|
-
const target = await getChatMessage(handle, fromMessageId);
|
|
131363
|
+
const target = await getChatMessage(handle, fromMessageId, projectId2);
|
|
131077
131364
|
if (!target || target.sessionId !== sessionId) {
|
|
131078
131365
|
return { deletedIds: [], retained: ordered2 };
|
|
131079
131366
|
}
|
|
@@ -131086,19 +131373,28 @@ async function deleteChatMessagesFrom(handle, sessionId, fromMessageId) {
|
|
|
131086
131373
|
if (deletedIds.length === 0) {
|
|
131087
131374
|
return { deletedIds: [], retained };
|
|
131088
131375
|
}
|
|
131089
|
-
await handle.delete(project_exports.chatMessages).where(
|
|
131090
|
-
|
|
131376
|
+
await handle.delete(project_exports.chatMessages).where(and(
|
|
131377
|
+
inArray(project_exports.chatMessages.id, deletedIds),
|
|
131378
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131379
|
+
));
|
|
131380
|
+
await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(
|
|
131381
|
+
eq(project_exports.chatSessions.id, sessionId),
|
|
131382
|
+
projectScopeFor(project_exports.chatSessions.projectId, projectId2)
|
|
131383
|
+
));
|
|
131091
131384
|
return { deletedIds, retained };
|
|
131092
131385
|
}
|
|
131093
|
-
async function updateChatMessageMetadata(handle, messageId, metadata, options) {
|
|
131094
|
-
const existing = await getChatMessage(handle, messageId);
|
|
131386
|
+
async function updateChatMessageMetadata(handle, messageId, metadata, options, projectId2) {
|
|
131387
|
+
const existing = await getChatMessage(handle, messageId, projectId2);
|
|
131095
131388
|
if (!existing) {
|
|
131096
131389
|
throw new Error(`Message ${messageId} not found`);
|
|
131097
131390
|
}
|
|
131098
131391
|
const merge2 = options?.merge !== false;
|
|
131099
131392
|
const nextMetadata = metadata === null ? merge2 ? existing.metadata : null : merge2 ? { ...existing.metadata ?? {}, ...metadata } : metadata;
|
|
131100
|
-
await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(
|
|
131101
|
-
|
|
131393
|
+
await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(and(
|
|
131394
|
+
eq(project_exports.chatMessages.id, messageId),
|
|
131395
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131396
|
+
));
|
|
131397
|
+
const updated = await getChatMessage(handle, messageId, projectId2);
|
|
131102
131398
|
if (!updated) {
|
|
131103
131399
|
throw new Error(`Failed to update message ${messageId}`);
|
|
131104
131400
|
}
|
|
@@ -131480,7 +131776,7 @@ var init_chat_store = __esm({
|
|
|
131480
131776
|
attachments: input.attachments,
|
|
131481
131777
|
createdAt: now
|
|
131482
131778
|
};
|
|
131483
|
-
const created = await addChatMessage(this.asyncLayer.db, message);
|
|
131779
|
+
const created = await addChatMessage(this.asyncLayer.db, message, this.asyncLayer.projectId);
|
|
131484
131780
|
this.emit("chat:message:added", created);
|
|
131485
131781
|
return created;
|
|
131486
131782
|
}
|
|
@@ -131488,7 +131784,7 @@ var init_chat_store = __esm({
|
|
|
131488
131784
|
* Append a file attachment metadata record to an existing message.
|
|
131489
131785
|
*/
|
|
131490
131786
|
async addMessageAttachment(sessionId, messageId, attachment) {
|
|
131491
|
-
const updated = await addChatMessageAttachment(this.asyncLayer.db, sessionId, messageId, attachment);
|
|
131787
|
+
const updated = await addChatMessageAttachment(this.asyncLayer.db, sessionId, messageId, attachment, this.asyncLayer.projectId);
|
|
131492
131788
|
this.emit("chat:message:updated", updated);
|
|
131493
131789
|
return updated;
|
|
131494
131790
|
}
|
|
@@ -131500,7 +131796,7 @@ var init_chat_store = __esm({
|
|
|
131500
131796
|
* @returns Array of messages ordered by createdAt ASC (default) or DESC
|
|
131501
131797
|
*/
|
|
131502
131798
|
async getMessages(sessionId, filter2) {
|
|
131503
|
-
return getChatMessages(this.asyncLayer.db, sessionId, filter2);
|
|
131799
|
+
return getChatMessages(this.asyncLayer.db, sessionId, filter2, this.asyncLayer.projectId);
|
|
131504
131800
|
}
|
|
131505
131801
|
/**
|
|
131506
131802
|
* Get a message by ID.
|
|
@@ -131509,7 +131805,7 @@ var init_chat_store = __esm({
|
|
|
131509
131805
|
* @returns The message, or undefined if not found
|
|
131510
131806
|
*/
|
|
131511
131807
|
async getMessage(id) {
|
|
131512
|
-
return getChatMessage(this.asyncLayer.db, id);
|
|
131808
|
+
return getChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
131513
131809
|
}
|
|
131514
131810
|
/**
|
|
131515
131811
|
* Get the latest message for each session in the provided list.
|
|
@@ -131519,10 +131815,10 @@ var init_chat_store = __esm({
|
|
|
131519
131815
|
* @returns Map of sessionId -> latest ChatMessage for that session
|
|
131520
131816
|
*/
|
|
131521
131817
|
async getLastMessageForSessions(sessionIds) {
|
|
131522
|
-
return getLastMessageForSessions(this.asyncLayer.db, sessionIds);
|
|
131818
|
+
return getLastMessageForSessions(this.asyncLayer.db, sessionIds, this.asyncLayer.projectId);
|
|
131523
131819
|
}
|
|
131524
131820
|
async hasMessages(sessionId) {
|
|
131525
|
-
return (await getChatMessages(this.asyncLayer.db, sessionId, { limit: 1 })).length > 0;
|
|
131821
|
+
return (await getChatMessages(this.asyncLayer.db, sessionId, { limit: 1 }, this.asyncLayer.projectId)).length > 0;
|
|
131526
131822
|
}
|
|
131527
131823
|
/**
|
|
131528
131824
|
* Search sessions by message content (not just title/agentId).
|
|
@@ -131550,7 +131846,7 @@ var init_chat_store = __esm({
|
|
|
131550
131846
|
if (!trimmed || !sessionIds || sessionIds.length === 0) {
|
|
131551
131847
|
return /* @__PURE__ */ new Map();
|
|
131552
131848
|
}
|
|
131553
|
-
return searchChatSessionsByMessageContent(this.asyncLayer.db, trimmed, sessionIds);
|
|
131849
|
+
return searchChatSessionsByMessageContent(this.asyncLayer.db, trimmed, sessionIds, this.asyncLayer.projectId);
|
|
131554
131850
|
}
|
|
131555
131851
|
/**
|
|
131556
131852
|
* Delete a message by ID.
|
|
@@ -131559,9 +131855,9 @@ var init_chat_store = __esm({
|
|
|
131559
131855
|
* @returns true if deleted, false if not found
|
|
131560
131856
|
*/
|
|
131561
131857
|
async deleteMessage(id) {
|
|
131562
|
-
const existing = await getChatMessage(this.asyncLayer.db, id);
|
|
131858
|
+
const existing = await getChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
131563
131859
|
if (!existing) return false;
|
|
131564
|
-
const deleted = await deleteChatMessage(this.asyncLayer.db, id);
|
|
131860
|
+
const deleted = await deleteChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
131565
131861
|
if (deleted) {
|
|
131566
131862
|
this.emit("chat:message:deleted", id);
|
|
131567
131863
|
const updatedSession = await this.getSession(existing.sessionId);
|
|
@@ -131584,7 +131880,7 @@ var init_chat_store = __esm({
|
|
|
131584
131880
|
* @returns deletedIds (in ASC order) and retained messages (pre-edit history, ASC order)
|
|
131585
131881
|
*/
|
|
131586
131882
|
async deleteMessagesFrom(sessionId, fromMessageId) {
|
|
131587
|
-
const result2 = await deleteChatMessagesFrom(this.asyncLayer.db, sessionId, fromMessageId);
|
|
131883
|
+
const result2 = await deleteChatMessagesFrom(this.asyncLayer.db, sessionId, fromMessageId, this.asyncLayer.projectId);
|
|
131588
131884
|
if (result2.deletedIds.length > 0) {
|
|
131589
131885
|
for (const id of result2.deletedIds) {
|
|
131590
131886
|
this.emit("chat:message:deleted", id);
|
|
@@ -131602,7 +131898,7 @@ var init_chat_store = __esm({
|
|
|
131602
131898
|
* is what lets a later edit rewind losslessly via SessionManager.branch()/resetLeaf().
|
|
131603
131899
|
*/
|
|
131604
131900
|
async updateMessageMetadata(messageId, metadata, options) {
|
|
131605
|
-
const updated = await updateChatMessageMetadata(this.asyncLayer.db, messageId, metadata, options);
|
|
131901
|
+
const updated = await updateChatMessageMetadata(this.asyncLayer.db, messageId, metadata, options, this.asyncLayer.projectId);
|
|
131606
131902
|
this.emit("chat:message:updated", updated);
|
|
131607
131903
|
return updated;
|
|
131608
131904
|
}
|
|
@@ -133038,6 +133334,77 @@ var init_task_timing = __esm({
|
|
|
133038
133334
|
}
|
|
133039
133335
|
});
|
|
133040
133336
|
|
|
133337
|
+
// ../core/src/task-recommendation-notice.ts
|
|
133338
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
133339
|
+
function registerTaskRecommendationNoticeMailbox(store, mailbox) {
|
|
133340
|
+
mailboxes2.set(store, mailbox);
|
|
133341
|
+
return () => {
|
|
133342
|
+
if (mailboxes2.get(store) === mailbox) mailboxes2.delete(store);
|
|
133343
|
+
};
|
|
133344
|
+
}
|
|
133345
|
+
function getTaskRecommendationNoticeMailbox(store) {
|
|
133346
|
+
return mailboxes2.get(store);
|
|
133347
|
+
}
|
|
133348
|
+
function buildTaskRecommendationNoticeContent(task, recommendations) {
|
|
133349
|
+
const title2 = task.title?.trim();
|
|
133350
|
+
const heading = title2 ? `## Recommendations from ${task.id} \u2014 ${title2}` : `## Recommendations from ${task.id}`;
|
|
133351
|
+
return [
|
|
133352
|
+
heading,
|
|
133353
|
+
"",
|
|
133354
|
+
"These are optional, non-blocking out-of-scope proposals that were **not** executed.",
|
|
133355
|
+
"",
|
|
133356
|
+
...recommendations.map((recommendation) => `- **${recommendation.title}** \u2014 \`${recommendation.category}\`: ${recommendation.description}`),
|
|
133357
|
+
"",
|
|
133358
|
+
`Open ${task.id}'s **Recommendations** tab to review them. **Create task** files one through normal guarded intake.`
|
|
133359
|
+
].join("\n");
|
|
133360
|
+
}
|
|
133361
|
+
function buildTaskRecommendationNoticeIdempotencyKey(taskId, recommendations) {
|
|
133362
|
+
const ids = recommendations.map(({ id }) => id).sort().join("\n");
|
|
133363
|
+
const digest = createHash20("sha256").update(ids, "utf8").digest("hex").slice(0, 16);
|
|
133364
|
+
return `task-recommendation-notice:${taskId}:${digest}`;
|
|
133365
|
+
}
|
|
133366
|
+
async function notifyOperatorOfTaskRecommendations(store, task, recommendations, settings) {
|
|
133367
|
+
try {
|
|
133368
|
+
if (settings.recommendationMailboxNoticeEnabled === false || !recommendations?.length) return false;
|
|
133369
|
+
const mailbox = mailboxes2.get(store);
|
|
133370
|
+
if (!mailbox) return false;
|
|
133371
|
+
await mailbox.sendMessageOnce(
|
|
133372
|
+
{
|
|
133373
|
+
fromId: "system",
|
|
133374
|
+
fromType: "system",
|
|
133375
|
+
toId: DASHBOARD_USER_ID,
|
|
133376
|
+
toType: "user",
|
|
133377
|
+
type: "system",
|
|
133378
|
+
content: buildTaskRecommendationNoticeContent(task, recommendations),
|
|
133379
|
+
metadata: {
|
|
133380
|
+
kind: "task-recommendation-notice",
|
|
133381
|
+
taskId: task.id,
|
|
133382
|
+
recommendationCount: recommendations.length,
|
|
133383
|
+
recommendationIds: recommendations.map(({ id }) => id),
|
|
133384
|
+
categories: recommendations.map(({ category }) => category)
|
|
133385
|
+
}
|
|
133386
|
+
},
|
|
133387
|
+
buildTaskRecommendationNoticeIdempotencyKey(task.id, recommendations)
|
|
133388
|
+
);
|
|
133389
|
+
return true;
|
|
133390
|
+
} catch (error3) {
|
|
133391
|
+
noticeLog2.warn(
|
|
133392
|
+
`Operator recommendation notice failed for ${task.id}: ${error3 instanceof Error ? error3.message : String(error3)}`
|
|
133393
|
+
);
|
|
133394
|
+
return false;
|
|
133395
|
+
}
|
|
133396
|
+
}
|
|
133397
|
+
var noticeLog2, mailboxes2;
|
|
133398
|
+
var init_task_recommendation_notice = __esm({
|
|
133399
|
+
"../core/src/task-recommendation-notice.ts"() {
|
|
133400
|
+
"use strict";
|
|
133401
|
+
init_logger();
|
|
133402
|
+
init_types();
|
|
133403
|
+
noticeLog2 = createLogger("task-recommendation-notice");
|
|
133404
|
+
mailboxes2 = /* @__PURE__ */ new WeakMap();
|
|
133405
|
+
}
|
|
133406
|
+
});
|
|
133407
|
+
|
|
133041
133408
|
// ../core/src/session-identity-registry.ts
|
|
133042
133409
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
133043
133410
|
import { resolve as resolve24 } from "node:path";
|
|
@@ -133887,6 +134254,8 @@ __export(src_exports, {
|
|
|
133887
134254
|
buildTaskDeleteNoticeContent: () => buildTaskDeleteNoticeContent,
|
|
133888
134255
|
buildTaskDeleteNoticeIdempotencyKey: () => buildTaskDeleteNoticeIdempotencyKey,
|
|
133889
134256
|
buildTaskLineageTrailer: () => buildTaskLineageTrailer,
|
|
134257
|
+
buildTaskRecommendationNoticeContent: () => buildTaskRecommendationNoticeContent,
|
|
134258
|
+
buildTaskRecommendationNoticeIdempotencyKey: () => buildTaskRecommendationNoticeIdempotencyKey,
|
|
133890
134259
|
buildToolOutputTruncationMarker: () => buildToolOutputTruncationMarker,
|
|
133891
134260
|
buildTriageHeartbeatGuidance: () => buildTriageHeartbeatGuidance,
|
|
133892
134261
|
buildTriageMemoryInstructions: () => buildTriageMemoryInstructions,
|
|
@@ -134217,6 +134586,7 @@ __export(src_exports, {
|
|
|
134217
134586
|
getTaskMergeBlocker: () => getTaskMergeBlocker,
|
|
134218
134587
|
getTaskMoveDisposer: () => getTaskMoveDisposer,
|
|
134219
134588
|
getTaskPriorityRank: () => getTaskPriorityRank,
|
|
134589
|
+
getTaskRecommendationNoticeMailbox: () => getTaskRecommendationNoticeMailbox,
|
|
134220
134590
|
getTemplatesForRole: () => getTemplatesForRole,
|
|
134221
134591
|
getTotalAgentActiveMs: () => getTotalAgentActiveMs,
|
|
134222
134592
|
getTrait: () => getTrait,
|
|
@@ -134467,6 +134837,7 @@ __export(src_exports, {
|
|
|
134467
134837
|
normalizeWorkflowPromptOverrides: () => normalizeWorkflowPromptOverrides,
|
|
134468
134838
|
normalizeWorkflowReviewFindings: () => normalizeWorkflowReviewFindings,
|
|
134469
134839
|
notifyOperatorOfNonOperatorDelete: () => notifyOperatorOfNonOperatorDelete,
|
|
134840
|
+
notifyOperatorOfTaskRecommendations: () => notifyOperatorOfTaskRecommendations,
|
|
134470
134841
|
overseerAdviceSeverityRank: () => overseerAdviceSeverityRank,
|
|
134471
134842
|
parseAgentManifest: () => parseAgentManifest,
|
|
134472
134843
|
parseCompanyArchive: () => parseCompanyArchive,
|
|
@@ -134576,6 +134947,7 @@ __export(src_exports, {
|
|
|
134576
134947
|
registerStepParser: () => registerStepParser,
|
|
134577
134948
|
registerTaskDeleteNoticeMailbox: () => registerTaskDeleteNoticeMailbox,
|
|
134578
134949
|
registerTaskMoveDisposer: () => registerTaskMoveDisposer,
|
|
134950
|
+
registerTaskRecommendationNoticeMailbox: () => registerTaskRecommendationNoticeMailbox,
|
|
134579
134951
|
registerTraitHookImpl: () => registerTraitHookImpl,
|
|
134580
134952
|
rekeyFallbackProjectPartition: () => rekeyFallbackProjectPartition,
|
|
134581
134953
|
releaseEmbeddedRuntimeLease: () => releaseEmbeddedRuntimeLease,
|
|
@@ -135203,6 +135575,7 @@ var init_src2 = __esm({
|
|
|
135203
135575
|
init_task_document_concurrency();
|
|
135204
135576
|
init_task_delete_attribution();
|
|
135205
135577
|
init_task_delete_notice();
|
|
135578
|
+
init_task_recommendation_notice();
|
|
135206
135579
|
init_session_identity_registry();
|
|
135207
135580
|
init_task_lifecycle_event_retention();
|
|
135208
135581
|
init_task_lifecycle_consumer_identity();
|
|
@@ -136040,7 +136413,7 @@ var init_logger3 = __esm({
|
|
|
136040
136413
|
});
|
|
136041
136414
|
|
|
136042
136415
|
// ../engine/src/agents/agent-logger.ts
|
|
136043
|
-
import { createHash as
|
|
136416
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
136044
136417
|
function truncateToolResultDetail(value2) {
|
|
136045
136418
|
if (value2.length <= TOOL_RESULT_DETAIL_LIMIT) return value2;
|
|
136046
136419
|
return `${value2.slice(0, TOOL_RESULT_DETAIL_LIMIT)}${TOOL_RESULT_DETAIL_TRUNCATION_NOTICE}`;
|
|
@@ -136129,7 +136502,7 @@ function summarizeToolArgs(name2, args) {
|
|
|
136129
136502
|
const json2 = JSON.stringify(args);
|
|
136130
136503
|
if (!json2 || json2 === "{}" || json2 === "[]") return void 0;
|
|
136131
136504
|
if (json2.length <= STRUCTURED_ARG_SUMMARY_MAX) return json2;
|
|
136132
|
-
const hash3 =
|
|
136505
|
+
const hash3 = createHash21("sha256").update(json2).digest("hex").slice(0, STRUCTURED_ARG_HASH_HEX_LEN);
|
|
136133
136506
|
const suffix = `\u2026#${hash3}`;
|
|
136134
136507
|
const keep = Math.max(0, STRUCTURED_ARG_SUMMARY_MAX - suffix.length);
|
|
136135
136508
|
return `${json2.slice(0, keep)}${suffix}`;
|
|
@@ -136817,7 +137190,13 @@ var init_gating_classifications = __esm({
|
|
|
136817
137190
|
"fn_post_room_message",
|
|
136818
137191
|
"fn_update_identity",
|
|
136819
137192
|
"fn_reflect_on_performance",
|
|
136820
|
-
|
|
137193
|
+
/*
|
|
137194
|
+
FNXC:ToolGovernance 2026-08-12-22:11:
|
|
137195
|
+
fn_agent_read_evaluations is a subtree-scoped read. Authorization is enforced by
|
|
137196
|
+
the extension tool's getChainOfCommand boundary, not by this action classifier.
|
|
137197
|
+
*/
|
|
137198
|
+
"fn_read_evaluations",
|
|
137199
|
+
"fn_agent_read_evaluations"
|
|
136821
137200
|
]);
|
|
136822
137201
|
COORDINATION_EXEMPT_TOOLS = [
|
|
136823
137202
|
"read",
|
|
@@ -136877,6 +137256,8 @@ var init_gating_classifications = __esm({
|
|
|
136877
137256
|
"fn_post_room_message",
|
|
136878
137257
|
"fn_memory_append",
|
|
136879
137258
|
"fn_read_evaluations",
|
|
137259
|
+
// FNXC:ToolGovernance 2026-08-12-22:11: The manager read is subtree-authorized in extension.ts; follow-up remains absent so it falls back to task_agent_mutation policy.
|
|
137260
|
+
"fn_agent_read_evaluations",
|
|
136880
137261
|
"fn_update_identity",
|
|
136881
137262
|
"fn_reflect_on_performance"
|
|
136882
137263
|
];
|
|
@@ -136901,7 +137282,7 @@ var init_gating_classifications = __esm({
|
|
|
136901
137282
|
});
|
|
136902
137283
|
|
|
136903
137284
|
// ../engine/src/agents/agent-action-gate.ts
|
|
136904
|
-
import { createHash as
|
|
137285
|
+
import { createHash as createHash22 } from "node:crypto";
|
|
136905
137286
|
function getExemptTools() {
|
|
136906
137287
|
if (!_exemptTools) {
|
|
136907
137288
|
_exemptTools = new Set(DEFAULT_EXEMPT_TOOLS);
|
|
@@ -136953,7 +137334,7 @@ function evaluateAgentActionGate(params) {
|
|
|
136953
137334
|
if (params.toolName === "bash") {
|
|
136954
137335
|
const command2 = extractShellCommand(args);
|
|
136955
137336
|
const git7 = classifyGitCommand(command2);
|
|
136956
|
-
resourceId = command2 ? `cmd:${
|
|
137337
|
+
resourceId = command2 ? `cmd:${createHash22("sha256").update(command2).digest("hex").slice(0, 16)}` : void 0;
|
|
136957
137338
|
if (git7?.write) {
|
|
136958
137339
|
category = "git_write";
|
|
136959
137340
|
operation = git7.operation;
|
|
@@ -140485,11 +140866,11 @@ var init_planning_handoff_recovery = __esm({
|
|
|
140485
140866
|
// ../engine/src/plan-review-continuation.ts
|
|
140486
140867
|
async function seedPreReleasePlanReviewContinuation(store, task, ir2, options = {}) {
|
|
140487
140868
|
const node = resolvePreReleasePlanReviewNode(ir2);
|
|
140488
|
-
if (!node || node.column !== task.column) return { seeded: false };
|
|
140869
|
+
if (!node || node.column !== task.column) return { seeded: false, reason: "no-pre-release-plan-review" };
|
|
140489
140870
|
if (isTaskBlockedOnApproval(task)) return { seeded: false, reason: "awaiting-approval" };
|
|
140490
140871
|
if (task.paused === true || task.userPaused === true) return { seeded: false, reason: "paused" };
|
|
140491
140872
|
const items = await store.listWorkflowWorkItemsForTask(task.id);
|
|
140492
|
-
const active2 = items.filter((item2) => ACTIVE_WORKFLOW_WORK_ITEM_STATES.includes(item2.state));
|
|
140873
|
+
const active2 = items.filter((item2) => ACTIVE_WORKFLOW_WORK_ITEM_STATES.includes(item2.state) && item2.id !== options.retirePredecessorId);
|
|
140493
140874
|
if (active2.length > 0) return { seeded: false, reason: "active-continuation" };
|
|
140494
140875
|
const continuationSequence = items.length;
|
|
140495
140876
|
const input = {
|
|
@@ -140505,6 +140886,9 @@ async function seedPreReleasePlanReviewContinuation(store, task, ir2, options =
|
|
|
140505
140886
|
targetColumn: task.column,
|
|
140506
140887
|
irHash: computeWorkflowIrPin(ir2, node.id).irHash
|
|
140507
140888
|
};
|
|
140889
|
+
if (options.retirePredecessorId) {
|
|
140890
|
+
return store.seedStrandedPlanReviewContinuation(input, { retirePredecessorId: options.retirePredecessorId });
|
|
140891
|
+
}
|
|
140508
140892
|
if (options.atomic) return store.seedStrandedPlanReviewContinuation(input);
|
|
140509
140893
|
const item = await store.replaceActiveTaskWorkflowContinuation(input);
|
|
140510
140894
|
return { seeded: true, workItemId: item.id };
|
|
@@ -140519,7 +140903,7 @@ async function resumeApprovedPlanReviewHandoff(store, task, ir2) {
|
|
|
140519
140903
|
if (seeded.seeded) return { resumed: true, reason: "seeded", workItemId: seeded.workItemId };
|
|
140520
140904
|
return {
|
|
140521
140905
|
resumed: false,
|
|
140522
|
-
reason: seeded.reason
|
|
140906
|
+
reason: seeded.reason === void 0 || seeded.reason === "no-pre-release-plan-review" ? "not-plan-in-place" : seeded.reason
|
|
140523
140907
|
};
|
|
140524
140908
|
}
|
|
140525
140909
|
function evaluateStrandedHoldContinuation(input) {
|
|
@@ -140557,7 +140941,7 @@ var init_plan_review_continuation = __esm({
|
|
|
140557
140941
|
});
|
|
140558
140942
|
|
|
140559
140943
|
// ../engine/src/execution/hold-release.ts
|
|
140560
|
-
import { createHash as
|
|
140944
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
140561
140945
|
import { readFile as readFile31 } from "node:fs/promises";
|
|
140562
140946
|
function findColumn2(ir2, columnId) {
|
|
140563
140947
|
if (ir2.version !== "v2") return void 0;
|
|
@@ -140595,9 +140979,9 @@ async function checkAndRecordUnplannedExecutionBlock(store, task, ir2) {
|
|
|
140595
140979
|
promptContent = "";
|
|
140596
140980
|
}
|
|
140597
140981
|
}
|
|
140598
|
-
const promptMarker = promptContent.length > 0 ?
|
|
140982
|
+
const promptMarker = promptContent.length > 0 ? createHash23("sha256").update(promptContent).digest("hex") : "missing";
|
|
140599
140983
|
const dependencies = [...task.dependencies ?? []].sort();
|
|
140600
|
-
const episode =
|
|
140984
|
+
const episode = createHash23("sha256").update(JSON.stringify({
|
|
140601
140985
|
planReviewNode,
|
|
140602
140986
|
promptMarker,
|
|
140603
140987
|
dependencies,
|
|
@@ -170717,7 +171101,7 @@ ${getErrorStderr(error3) ?? ""}`;
|
|
|
170717
171101
|
});
|
|
170718
171102
|
|
|
170719
171103
|
// ../engine/src/worktree/secrets-env-writer.ts
|
|
170720
|
-
import { createHash as
|
|
171104
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
170721
171105
|
import { execFile as execFile8 } from "node:child_process";
|
|
170722
171106
|
import { promises as fs6 } from "node:fs";
|
|
170723
171107
|
import path2 from "node:path";
|
|
@@ -170726,7 +171110,7 @@ function isValidFilename(filename) {
|
|
|
170726
171110
|
return !!filename && !filename.includes("/") && !filename.includes("\\") && !filename.includes("..") && !filename.includes("\0") && filename !== FINGERPRINT_FILE;
|
|
170727
171111
|
}
|
|
170728
171112
|
function sha2562(content) {
|
|
170729
|
-
return
|
|
171113
|
+
return createHash24("sha256").update(Buffer.from(content, "utf8")).digest("hex");
|
|
170730
171114
|
}
|
|
170731
171115
|
function quote(value2) {
|
|
170732
171116
|
return `"${value2.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t")}"`;
|
|
@@ -178866,32 +179250,36 @@ var init_scheduler = __esm({
|
|
|
178866
179250
|
const hierarchy = await missionStore.getMissionWithHierarchy(mission.id);
|
|
178867
179251
|
if (!hierarchy) continue;
|
|
178868
179252
|
for (const slice of hierarchy.milestones.flatMap((milestone) => milestone.slices).filter((slice2) => slice2.status === "active")) {
|
|
178869
|
-
|
|
178870
|
-
|
|
178871
|
-
|
|
178872
|
-
|
|
178873
|
-
|
|
178874
|
-
|
|
178875
|
-
|
|
179253
|
+
try {
|
|
179254
|
+
const superseded = await missionStore.reconcileSupersededGeneratedFixFeatures(slice.id);
|
|
179255
|
+
fixed += superseded.supersededCount;
|
|
179256
|
+
if (superseded.supersededCount > 0) {
|
|
179257
|
+
const refreshed = await missionStore.getSlice(slice.id);
|
|
179258
|
+
if (refreshed?.status === "complete") {
|
|
179259
|
+
await this.onSliceComplete(refreshed);
|
|
179260
|
+
continue;
|
|
179261
|
+
}
|
|
178876
179262
|
}
|
|
178877
|
-
|
|
178878
|
-
|
|
178879
|
-
|
|
178880
|
-
|
|
178881
|
-
|
|
178882
|
-
|
|
178883
|
-
|
|
178884
|
-
|
|
178885
|
-
|
|
179263
|
+
const listFeatures2 = missionStore.listFeatures;
|
|
179264
|
+
const features = listFeatures2 ? await listFeatures2.call(missionStore, slice.id) : slice.features;
|
|
179265
|
+
const supersededFeatureIds = new Set(superseded.featureIds ?? []);
|
|
179266
|
+
const autoTriage = mission.autopilotEnabled === true || mission.autoAdvance === true;
|
|
179267
|
+
for (const feature of features) {
|
|
179268
|
+
if (supersededFeatureIds.has(feature.id) || feature.taskId || !autoTriage || feature.status === "blocked") continue;
|
|
179269
|
+
if (feature.status !== "defined" && this.isGeneratedFixFeature(feature)) {
|
|
179270
|
+
await missionStore.updateFeature(feature.id, { status: "blocked", loopState: "blocked", taskId: void 0 });
|
|
179271
|
+
fixed++;
|
|
179272
|
+
continue;
|
|
179273
|
+
}
|
|
179274
|
+
if (feature.status !== "defined" && feature.status !== "triaged" && feature.status !== "in-progress") continue;
|
|
179275
|
+
const ready = feature.status === "defined" ? feature : await missionStore.updateFeature(feature.id, { status: "defined", loopState: "idle", taskId: void 0 });
|
|
179276
|
+
if (ready !== feature) fixed++;
|
|
179277
|
+
const triaged = await missionStore.triageFeature(ready.id);
|
|
178886
179278
|
fixed++;
|
|
178887
|
-
|
|
179279
|
+
if (triaged.taskId) await this.emitStrandedFeatureTriageAudit(mission.id, slice.id, triaged.id, triaged.taskId);
|
|
178888
179280
|
}
|
|
178889
|
-
|
|
178890
|
-
|
|
178891
|
-
if (ready !== feature) fixed++;
|
|
178892
|
-
const triaged = await missionStore.triageFeature(ready.id);
|
|
178893
|
-
fixed++;
|
|
178894
|
-
if (triaged.taskId) await this.emitStrandedFeatureTriageAudit(mission.id, slice.id, triaged.id, triaged.taskId);
|
|
179281
|
+
} catch (error3) {
|
|
179282
|
+
schedulerLog.error(`Error during active mission recovery reconciliation for slice ${slice.id}:`, error3);
|
|
178895
179283
|
}
|
|
178896
179284
|
}
|
|
178897
179285
|
}
|
|
@@ -179129,7 +179517,7 @@ var init_mission_feature_sync = __esm({
|
|
|
179129
179517
|
// ../engine/src/agent-tools.ts
|
|
179130
179518
|
import { appendFile as appendFile3, mkdir as mkdir28, readFile as readFile38, readdir as readdir11, realpath as realpath2, stat as stat11, writeFile as writeFile26 } from "node:fs/promises";
|
|
179131
179519
|
import { existsSync as existsSync53 } from "node:fs";
|
|
179132
|
-
import { createHash as
|
|
179520
|
+
import { createHash as createHash25, randomUUID as randomUUID47 } from "node:crypto";
|
|
179133
179521
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
179134
179522
|
import { extname as extname4, isAbsolute as isAbsolute14, join as join66, relative as relative14, resolve as resolve38, sep as sep10 } from "node:path";
|
|
179135
179523
|
import { Type as Type2 } from "@earendil-works/pi-ai";
|
|
@@ -179173,7 +179561,7 @@ async function readAgentMemoryWorkspaceLongTerm(rootDir, agentId) {
|
|
|
179173
179561
|
}
|
|
179174
179562
|
}
|
|
179175
179563
|
function qmdAgentMemoryCollectionName2(rootDir, agentId) {
|
|
179176
|
-
const hash3 =
|
|
179564
|
+
const hash3 = createHash25("sha1").update(`${rootDir}:${agentId}`).digest("hex").slice(0, 12);
|
|
179177
179565
|
return `fusion-agent-memory-${sanitizeAgentMemoryId(agentId).toLowerCase()}-${hash3}`;
|
|
179178
179566
|
}
|
|
179179
179567
|
function buildQmdAgentMemoryCollectionAddArgs(rootDir, agentId) {
|
|
@@ -190750,7 +191138,7 @@ var init_agent_heartbeat_error_recovery = __esm({
|
|
|
190750
191138
|
|
|
190751
191139
|
// ../engine/src/agent-heartbeat.ts
|
|
190752
191140
|
import { Type as Type3 } from "@earendil-works/pi-ai";
|
|
190753
|
-
import { createHash as
|
|
191141
|
+
import { createHash as createHash26 } from "node:crypto";
|
|
190754
191142
|
async function resolveHeartbeatReboundColumn(taskStore, taskId) {
|
|
190755
191143
|
try {
|
|
190756
191144
|
return resolveReboundTarget(await resolveWorkflowIrForTask(taskStore, taskId)) ?? "todo";
|
|
@@ -190905,7 +191293,7 @@ function truncatePrompt(text3, maxChars) {
|
|
|
190905
191293
|
... (truncated, ${text3.length} chars)`;
|
|
190906
191294
|
}
|
|
190907
191295
|
function shortContentHash(value2) {
|
|
190908
|
-
return
|
|
191296
|
+
return createHash26("sha256").update(value2).digest("hex").slice(0, 8);
|
|
190909
191297
|
}
|
|
190910
191298
|
function buildIdentitySnapshot(args) {
|
|
190911
191299
|
const { agent, resolvedInstructions, workspaceMemory } = args;
|
|
@@ -198794,7 +199182,7 @@ var init_verification_utils = __esm({
|
|
|
198794
199182
|
|
|
198795
199183
|
// ../engine/src/merge/merge-dependency-sync.ts
|
|
198796
199184
|
import { exec as exec25 } from "node:child_process";
|
|
198797
|
-
import { createHash as
|
|
199185
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
198798
199186
|
import { existsSync as existsSync56, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
|
|
198799
199187
|
import { join as join69 } from "node:path";
|
|
198800
199188
|
import { promisify as promisify35 } from "node:util";
|
|
@@ -198821,7 +199209,7 @@ function computeLockfileHash(rootDir) {
|
|
|
198821
199209
|
const p2 = join69(rootDir, name2);
|
|
198822
199210
|
if (existsSync56(p2)) {
|
|
198823
199211
|
try {
|
|
198824
|
-
return
|
|
199212
|
+
return createHash27("sha256").update(readFileSync18(p2)).digest("hex");
|
|
198825
199213
|
} catch {
|
|
198826
199214
|
return null;
|
|
198827
199215
|
}
|
|
@@ -201363,7 +201751,7 @@ var init_mesh_lease_manager = __esm({
|
|
|
201363
201751
|
});
|
|
201364
201752
|
|
|
201365
201753
|
// ../engine/src/merge/merger-integration-worktree.ts
|
|
201366
|
-
import { createHash as
|
|
201754
|
+
import { createHash as createHash28 } from "node:crypto";
|
|
201367
201755
|
import { exec as exec31, execFile as execFile22 } from "node:child_process";
|
|
201368
201756
|
import { promisify as promisify45 } from "node:util";
|
|
201369
201757
|
function quoteAutostashArg(value2) {
|
|
@@ -201486,7 +201874,7 @@ async function gitDirtyFingerprintLocal(rootDir) {
|
|
|
201486
201874
|
)
|
|
201487
201875
|
]);
|
|
201488
201876
|
if (!diffOut && !statusOut) return "";
|
|
201489
|
-
return
|
|
201877
|
+
return createHash28("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
201490
201878
|
} catch {
|
|
201491
201879
|
return "";
|
|
201492
201880
|
}
|
|
@@ -202472,7 +202860,7 @@ import { execSync as execSync5, exec as exec33 } from "node:child_process";
|
|
|
202472
202860
|
import * as childProcess4 from "node:child_process";
|
|
202473
202861
|
import { promisify as promisify48 } from "node:util";
|
|
202474
202862
|
import { existsSync as existsSync59, readFileSync as readFileSync21, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
202475
|
-
import { createHash as
|
|
202863
|
+
import { createHash as createHash29 } from "node:crypto";
|
|
202476
202864
|
import { join as join73, resolve as resolve44 } from "node:path";
|
|
202477
202865
|
import { hostname as hostname2 } from "node:os";
|
|
202478
202866
|
import { Type as Type4 } from "typebox";
|
|
@@ -202720,7 +203108,7 @@ async function gitDirtyFingerprint(rootDir) {
|
|
|
202720
203108
|
)
|
|
202721
203109
|
]);
|
|
202722
203110
|
if (!diffOut && !statusOut) return "";
|
|
202723
|
-
return
|
|
203111
|
+
return createHash29("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
202724
203112
|
} catch {
|
|
202725
203113
|
return "";
|
|
202726
203114
|
}
|
|
@@ -225143,7 +225531,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
225143
225531
|
}
|
|
225144
225532
|
return;
|
|
225145
225533
|
}
|
|
225146
|
-
const duplicateReport = { outcome: "parked" };
|
|
225534
|
+
const duplicateReport = { outcome: "parked", planningWorkItemId };
|
|
225147
225535
|
if (await this.tryFinalizeExplicitDuplicateMarker(task, written, settings, {
|
|
225148
225536
|
isReplan,
|
|
225149
225537
|
feedback
|
|
@@ -225162,6 +225550,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
225162
225550
|
isReplan,
|
|
225163
225551
|
feedback
|
|
225164
225552
|
});
|
|
225553
|
+
finalizeReport.planningWorkItemId = planningWorkItemId;
|
|
225165
225554
|
this.options.onSpecifyComplete?.(task, finalizeReport);
|
|
225166
225555
|
} finally {
|
|
225167
225556
|
this.activeSessions.delete(task.id);
|
|
@@ -240733,6 +241122,38 @@ var init_execution_block_classifier = __esm({
|
|
|
240733
241122
|
}
|
|
240734
241123
|
});
|
|
240735
241124
|
|
|
241125
|
+
// ../engine/src/executor/completion-recommendation-notice.ts
|
|
241126
|
+
function dispatchAcceptedCompletionRecommendationNotice(args) {
|
|
241127
|
+
if (!args.recommendations?.length) return;
|
|
241128
|
+
const pending = (async () => {
|
|
241129
|
+
const settings = args.settings ?? await args.store.getSettings();
|
|
241130
|
+
const task = await args.store.getTask(args.taskId);
|
|
241131
|
+
if (!task || task.deletedAt) return;
|
|
241132
|
+
await notifyOperatorOfTaskRecommendations(
|
|
241133
|
+
args.store,
|
|
241134
|
+
{ id: args.taskId, title: args.taskTitle ?? task.title },
|
|
241135
|
+
args.recommendations,
|
|
241136
|
+
settings
|
|
241137
|
+
);
|
|
241138
|
+
})();
|
|
241139
|
+
pendingNotices.add(pending);
|
|
241140
|
+
void pending.catch((error3) => {
|
|
241141
|
+
args.log?.warn(
|
|
241142
|
+
`Failed to dispatch recommendation mailbox notice for ${args.taskId}: ${error3 instanceof Error ? error3.message : String(error3)}`
|
|
241143
|
+
);
|
|
241144
|
+
}).finally(() => {
|
|
241145
|
+
pendingNotices.delete(pending);
|
|
241146
|
+
});
|
|
241147
|
+
}
|
|
241148
|
+
var pendingNotices;
|
|
241149
|
+
var init_completion_recommendation_notice = __esm({
|
|
241150
|
+
"../engine/src/executor/completion-recommendation-notice.ts"() {
|
|
241151
|
+
"use strict";
|
|
241152
|
+
init_src2();
|
|
241153
|
+
pendingNotices = /* @__PURE__ */ new Set();
|
|
241154
|
+
}
|
|
241155
|
+
});
|
|
241156
|
+
|
|
240736
241157
|
// ../engine/src/executor/create-task-done-tool.ts
|
|
240737
241158
|
import { Type as Type9 } from "@earendil-works/pi-ai";
|
|
240738
241159
|
function createTaskDoneTool(deps, taskId, worktreePath, promptContent, codeReviewVerdicts, onDone, audit) {
|
|
@@ -241069,6 +241490,16 @@ ${rerunSuffix}`
|
|
|
241069
241490
|
bulkCompletionRefusalAt: null
|
|
241070
241491
|
});
|
|
241071
241492
|
await store.logEntry(taskId, "Task marked done by agent", void 0, deps.getRunContextFor(taskId));
|
|
241493
|
+
if (completionRecommendations !== void 0) {
|
|
241494
|
+
dispatchAcceptedCompletionRecommendationNotice({
|
|
241495
|
+
store,
|
|
241496
|
+
taskId,
|
|
241497
|
+
taskTitle: task.title,
|
|
241498
|
+
recommendations: completionRecommendations,
|
|
241499
|
+
settings,
|
|
241500
|
+
log: executorLog
|
|
241501
|
+
});
|
|
241502
|
+
}
|
|
241072
241503
|
const latestTask = await store.getTask(taskId);
|
|
241073
241504
|
let latestColumn = latestTask.column;
|
|
241074
241505
|
if (latestColumn === await resolveReboundColumnFor(store, taskId)) {
|
|
@@ -241107,6 +241538,7 @@ var init_create_task_done_tool = __esm({
|
|
|
241107
241538
|
init_completion_predicates();
|
|
241108
241539
|
init_task_done_refusal_handler();
|
|
241109
241540
|
init_validate_completion_recommendations();
|
|
241541
|
+
init_completion_recommendation_notice();
|
|
241110
241542
|
}
|
|
241111
241543
|
});
|
|
241112
241544
|
|
|
@@ -252433,6 +252865,16 @@ ${rerunSuffix}` });
|
|
|
252433
252865
|
if (latestColumn === await resolveWipTargetForTask(deps.store, task.id) && !hardPauseActive && beforeWatchdog && !beforeWatchdog.deletedAt && !(rejectIfPaused && (beforeWatchdog.paused || beforeWatchdog.userPaused))) {
|
|
252434
252866
|
deps.scheduleCompletedTaskWatchdog(task.id, "fn_task_done");
|
|
252435
252867
|
}
|
|
252868
|
+
if (recommendations !== void 0) {
|
|
252869
|
+
dispatchAcceptedCompletionRecommendationNotice({
|
|
252870
|
+
store: deps.store,
|
|
252871
|
+
taskId: task.id,
|
|
252872
|
+
taskTitle: task.title,
|
|
252873
|
+
recommendations,
|
|
252874
|
+
settings,
|
|
252875
|
+
log: executorLog
|
|
252876
|
+
});
|
|
252877
|
+
}
|
|
252436
252878
|
return { completed: true, hardPauseActive };
|
|
252437
252879
|
} catch (error3) {
|
|
252438
252880
|
await restoreNoCommitsExpected();
|
|
@@ -252491,6 +252933,7 @@ var init_plan_review_no_op = __esm({
|
|
|
252491
252933
|
init_src2();
|
|
252492
252934
|
init_logger3();
|
|
252493
252935
|
init_lifecycle_columns();
|
|
252936
|
+
init_completion_recommendation_notice();
|
|
252494
252937
|
}
|
|
252495
252938
|
});
|
|
252496
252939
|
|
|
@@ -255999,14 +256442,14 @@ ${stdout.trim()}`);
|
|
|
255999
256442
|
|
|
256000
256443
|
// ../engine/src/missions/mission-execution-loop.ts
|
|
256001
256444
|
import { EventEmitter as EventEmitter26 } from "node:events";
|
|
256002
|
-
import { createHash as
|
|
256445
|
+
import { createHash as createHash30 } from "node:crypto";
|
|
256003
256446
|
import { exec as exec56 } from "node:child_process";
|
|
256004
256447
|
import { promisify as promisify74 } from "node:util";
|
|
256005
256448
|
function quoteShellArg7(value2) {
|
|
256006
256449
|
return `'${value2.replace(/'/g, `'\\''`)}'`;
|
|
256007
256450
|
}
|
|
256008
256451
|
function fingerprintMissionValidationInput(landedSha, provider, modelId, systemPrompt, userPrompt) {
|
|
256009
|
-
return
|
|
256452
|
+
return createHash30("sha256").update(Buffer.from(JSON.stringify(["mission-validation-input-v1", landedSha, provider, modelId, systemPrompt, userPrompt]), "utf8")).digest("hex");
|
|
256010
256453
|
}
|
|
256011
256454
|
var execAsync53, loopLog, VALIDATION_TIMEOUT_MS, MAX_VALIDATION_RESPONSE_BYTES, MAX_VALIDATION_JSON_CANDIDATES, VALIDATION_FAILURE_BUDGET_PER_FINGERPRINT, MissionExecutionLoop;
|
|
256012
256455
|
var init_mission_execution_loop = __esm({
|
|
@@ -267545,9 +267988,9 @@ var init_routine_scheduler = __esm({
|
|
|
267545
267988
|
});
|
|
267546
267989
|
|
|
267547
267990
|
// ../engine/src/healing/stuck-task-detector.ts
|
|
267548
|
-
import { createHash as
|
|
267991
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
267549
267992
|
function hashToolDetail(detail) {
|
|
267550
|
-
return
|
|
267993
|
+
return createHash31("sha256").update(detail).digest("hex").slice(0, TOOL_DETAIL_HASH_HEX_LEN);
|
|
267551
267994
|
}
|
|
267552
267995
|
function buildToolFingerprint(toolName, toolDetail) {
|
|
267553
267996
|
const name2 = toolName.trim().toLowerCase() || "tool";
|
|
@@ -271125,7 +271568,7 @@ var init_node_dispatch_validation = __esm({
|
|
|
271125
271568
|
});
|
|
271126
271569
|
|
|
271127
271570
|
// ../engine/src/runtimes/in-process-runtime.ts
|
|
271128
|
-
import { createHash as
|
|
271571
|
+
import { createHash as createHash32 } from "node:crypto";
|
|
271129
271572
|
import { EventEmitter as EventEmitter27 } from "node:events";
|
|
271130
271573
|
import { setImmediate as setImmediateCb4 } from "node:timers";
|
|
271131
271574
|
function createDiscoveryPluginLoaderOptions(scopedStore) {
|
|
@@ -271216,11 +271659,46 @@ async function reactToSpecificationComplete(deps) {
|
|
|
271216
271659
|
return;
|
|
271217
271660
|
}
|
|
271218
271661
|
deps.log(`Specified ${deps.taskId} \u2192 todo`);
|
|
271219
|
-
const
|
|
271220
|
-
|
|
271221
|
-
|
|
271222
|
-
|
|
271223
|
-
|
|
271662
|
+
const sleep10 = deps.sleep ?? ((ms2) => new Promise((resolve110) => setTimeout(resolve110, ms2)));
|
|
271663
|
+
const QUIET_PARK_REASONS = /* @__PURE__ */ new Set([
|
|
271664
|
+
"no-pre-release-plan-review",
|
|
271665
|
+
"awaiting-approval",
|
|
271666
|
+
"paused",
|
|
271667
|
+
"plan-review-passed"
|
|
271668
|
+
]);
|
|
271669
|
+
const RETRY_DELAYS_MS2 = [1e3, 5e3];
|
|
271670
|
+
for (let attempt = 0; ; attempt++) {
|
|
271671
|
+
let failure = null;
|
|
271672
|
+
try {
|
|
271673
|
+
const live = await deps.getTask(deps.taskId);
|
|
271674
|
+
if (!live || live.paused || live.userPaused) return;
|
|
271675
|
+
if (live.status === "needs-replan") {
|
|
271676
|
+
deps.log(`Plan Review handoff for ${deps.taskId} not armed (needs-replan)`);
|
|
271677
|
+
return;
|
|
271678
|
+
}
|
|
271679
|
+
const ir2 = await deps.resolveIr(live.id);
|
|
271680
|
+
const result2 = await deps.seed(live, ir2);
|
|
271681
|
+
if (result2.seeded) {
|
|
271682
|
+
deps.kick();
|
|
271683
|
+
return;
|
|
271684
|
+
}
|
|
271685
|
+
if (result2.reason && QUIET_PARK_REASONS.has(result2.reason)) {
|
|
271686
|
+
deps.log(`Plan Review handoff for ${deps.taskId} not armed (${result2.reason})`);
|
|
271687
|
+
return;
|
|
271688
|
+
}
|
|
271689
|
+
failure = result2.reason ?? "not-seeded";
|
|
271690
|
+
} catch (error3) {
|
|
271691
|
+
failure = error3 instanceof Error ? error3.message : String(error3);
|
|
271692
|
+
}
|
|
271693
|
+
if (attempt >= RETRY_DELAYS_MS2.length) {
|
|
271694
|
+
deps.warn(
|
|
271695
|
+
`Plan Review handoff for ${deps.taskId} failed after ${attempt + 1} attempts (${failure}) \u2014 stranded-continuation self-healing will recover it`
|
|
271696
|
+
);
|
|
271697
|
+
return;
|
|
271698
|
+
}
|
|
271699
|
+
deps.warn(`Plan Review handoff for ${deps.taskId} did not seed (${failure}) \u2014 retrying`);
|
|
271700
|
+
await sleep10(RETRY_DELAYS_MS2[attempt]);
|
|
271701
|
+
}
|
|
271224
271702
|
}
|
|
271225
271703
|
async function drainDuePlanningContinuations(deps) {
|
|
271226
271704
|
const items = await deps.listDue();
|
|
@@ -271355,7 +271833,7 @@ function stableNotificationJson(value2) {
|
|
|
271355
271833
|
return `{${fields.join(",")}}`;
|
|
271356
271834
|
}
|
|
271357
271835
|
function buildCliAgentNotificationDedupeKey(input) {
|
|
271358
|
-
const notificationFingerprint =
|
|
271836
|
+
const notificationFingerprint = createHash32("sha256").update(stableNotificationJson(input.info.notification ?? null)).digest("hex").slice(0, 16);
|
|
271359
271837
|
const waitingEpoch = input.session?.updatedAt ?? "unknown-waiting-epoch";
|
|
271360
271838
|
return [
|
|
271361
271839
|
"cli-agent",
|
|
@@ -271510,6 +271988,8 @@ var init_in_process_runtime = __esm({
|
|
|
271510
271988
|
messageStore;
|
|
271511
271989
|
/** FNXC:TaskDeleteNotice 2026-07-26-16:10: identity-guarded teardown for the delete-notice mailbox seam. */
|
|
271512
271990
|
unregisterTaskDeleteNoticeMailbox;
|
|
271991
|
+
/** FNXC:TaskRecommendations 2026-08-13-03:56: identity-guarded teardown for the store-scoped recommendation notice seam. */
|
|
271992
|
+
unregisterTaskRecommendationNoticeMailbox;
|
|
271513
271993
|
chatStore;
|
|
271514
271994
|
detachAgentLinkSync;
|
|
271515
271995
|
/**
|
|
@@ -271568,7 +272048,8 @@ var init_in_process_runtime = __esm({
|
|
|
271568
272048
|
createTaskStoreForBackend: createTaskStoreForBackend2,
|
|
271569
272049
|
buildConsumerId: buildConsumerId2,
|
|
271570
272050
|
createProjectScopedPluginMcpProvider: createProjectScopedPluginMcpProvider2,
|
|
271571
|
-
registerTaskDeleteNoticeMailbox: registerTaskDeleteNoticeMailbox2
|
|
272051
|
+
registerTaskDeleteNoticeMailbox: registerTaskDeleteNoticeMailbox2,
|
|
272052
|
+
registerTaskRecommendationNoticeMailbox: registerTaskRecommendationNoticeMailbox2
|
|
271572
272053
|
} = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
271573
272054
|
if (this.config.externalTaskStore) {
|
|
271574
272055
|
this.taskStore = this.config.externalTaskStore;
|
|
@@ -271627,6 +272108,10 @@ var init_in_process_runtime = __esm({
|
|
|
271627
272108
|
this.taskStore,
|
|
271628
272109
|
this.messageStore
|
|
271629
272110
|
);
|
|
272111
|
+
this.unregisterTaskRecommendationNoticeMailbox = registerTaskRecommendationNoticeMailbox2(
|
|
272112
|
+
this.taskStore,
|
|
272113
|
+
this.messageStore
|
|
272114
|
+
);
|
|
271630
272115
|
await yieldEventLoop4();
|
|
271631
272116
|
const pluginLayer = this.taskStore.getAsyncLayer();
|
|
271632
272117
|
if (!pluginLayer) {
|
|
@@ -272118,9 +272603,19 @@ var init_in_process_runtime = __esm({
|
|
|
272118
272603
|
outcome: report2.outcome,
|
|
272119
272604
|
getTask: (id) => Promise.resolve(this.taskStore.getTask(id)),
|
|
272120
272605
|
resolveIr: (id) => resolveWorkflowIrForTask(this.taskStore, id),
|
|
272121
|
-
|
|
272606
|
+
/*
|
|
272607
|
+
FNXC:PlanningHandoffAtomicity 2026-08-13-03:49:
|
|
272608
|
+
The report carries the planning session's own durable work item id so the
|
|
272609
|
+
seeder can retire that exact predecessor row atomically with the successor
|
|
272610
|
+
install. Without it the seeder raced triage's finally-block terminal
|
|
272611
|
+
transition and bailed on its own caller (529 stranded cards in 18 days).
|
|
272612
|
+
*/
|
|
272613
|
+
seed: (task, ir2) => seedPreReleasePlanReviewContinuation(this.taskStore, task, ir2, {
|
|
272614
|
+
retirePredecessorId: report2.planningWorkItemId
|
|
272615
|
+
}),
|
|
272122
272616
|
kick: () => this.kickWorkflowContinuationProcessor(),
|
|
272123
|
-
log: (message) => runtimeLog.log(message)
|
|
272617
|
+
log: (message) => runtimeLog.log(message),
|
|
272618
|
+
warn: (message) => runtimeLog.warn(message)
|
|
272124
272619
|
}).catch((error3) => {
|
|
272125
272620
|
runtimeLog.error(`Failed to start Todo plan review for ${t.id}:`, error3);
|
|
272126
272621
|
});
|
|
@@ -272408,6 +272903,8 @@ var init_in_process_runtime = __esm({
|
|
|
272408
272903
|
this.backendShutdown = void 0;
|
|
272409
272904
|
this.unregisterTaskDeleteNoticeMailbox?.();
|
|
272410
272905
|
this.unregisterTaskDeleteNoticeMailbox = void 0;
|
|
272906
|
+
this.unregisterTaskRecommendationNoticeMailbox?.();
|
|
272907
|
+
this.unregisterTaskRecommendationNoticeMailbox = void 0;
|
|
272411
272908
|
let stopError;
|
|
272412
272909
|
try {
|
|
272413
272910
|
if (this.workflowContinuationTimer) {
|
|
@@ -280201,9 +280698,9 @@ import { access as access10, unlink as unlink11, writeFile as writeFile33 } from
|
|
|
280201
280698
|
import net2 from "node:net";
|
|
280202
280699
|
import { platform as platform3, tmpdir as tmpdir12 } from "node:os";
|
|
280203
280700
|
import { join as join91 } from "node:path";
|
|
280204
|
-
import { createHash as
|
|
280701
|
+
import { createHash as createHash33 } from "node:crypto";
|
|
280205
280702
|
function projectHash(projectId2) {
|
|
280206
|
-
return
|
|
280703
|
+
return createHash33("sha1").update(projectId2).digest("hex").slice(0, 16);
|
|
280207
280704
|
}
|
|
280208
280705
|
function computeEngineSocketPath(projectId2) {
|
|
280209
280706
|
const hash3 = projectHash(projectId2);
|
|
@@ -293422,6 +293919,13 @@ function sseDebug(message) {
|
|
|
293422
293919
|
if (!isSseDebugEnabled()) return;
|
|
293423
293920
|
sseLog.debug(message);
|
|
293424
293921
|
}
|
|
293922
|
+
function resolveAgentActivityPollMs() {
|
|
293923
|
+
const raw = process.env.FUSION_AGENT_ACTIVITY_POLL_MS?.trim();
|
|
293924
|
+
if (!raw) return 2e3;
|
|
293925
|
+
const parsed = Number(raw);
|
|
293926
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return 2e3;
|
|
293927
|
+
return Math.max(10, Math.floor(parsed));
|
|
293928
|
+
}
|
|
293425
293929
|
function normalizeSSEClientId(value2) {
|
|
293426
293930
|
const raw = Array.isArray(value2) ? value2[0] : value2;
|
|
293427
293931
|
if (typeof raw !== "string") return void 0;
|
|
@@ -293729,7 +294233,7 @@ data: ${JSON.stringify(payload)}
|
|
|
293729
294233
|
}
|
|
293730
294234
|
void drainAgentActivity();
|
|
293731
294235
|
};
|
|
293732
|
-
const agentActivityPoll = setInterval(onAgentActivityNudge,
|
|
294236
|
+
const agentActivityPoll = setInterval(onAgentActivityNudge, resolveAgentActivityPollMs());
|
|
293733
294237
|
agentActivityPoll.unref?.();
|
|
293734
294238
|
const onCreated = (task) => {
|
|
293735
294239
|
send(`event: task:created
|
|
@@ -300006,9 +300510,9 @@ __export(import_translate_service_exports, {
|
|
|
300006
300510
|
selectEligibleItems: () => selectEligibleItems,
|
|
300007
300511
|
translateImportItems: () => translateImportItems
|
|
300008
300512
|
});
|
|
300009
|
-
import { createHash as
|
|
300513
|
+
import { createHash as createHash34 } from "node:crypto";
|
|
300010
300514
|
function hashSourceContent(title2, body) {
|
|
300011
|
-
return
|
|
300515
|
+
return createHash34("sha256").update(`${title2}\0${body}`).digest("hex");
|
|
300012
300516
|
}
|
|
300013
300517
|
function resolveTargetLocale(settingsLocale, requestLocale, globalLanguage) {
|
|
300014
300518
|
if (isLocale(settingsLocale)) return settingsLocale;
|
|
@@ -307010,7 +307514,7 @@ var init_auth_middleware = __esm({
|
|
|
307010
307514
|
});
|
|
307011
307515
|
|
|
307012
307516
|
// ../dashboard/src/routes/register-task-workflow-routes.ts
|
|
307013
|
-
import { createHash as
|
|
307517
|
+
import { createHash as createHash35 } from "node:crypto";
|
|
307014
307518
|
import { createReadStream } from "node:fs";
|
|
307015
307519
|
import { readFile as readFile53, stat as stat13 } from "node:fs/promises";
|
|
307016
307520
|
import { join as join96 } from "node:path";
|
|
@@ -307416,7 +307920,7 @@ function buildWorkflowReviewItemId(task, result2, findingId, resolution) {
|
|
|
307416
307920
|
findingId,
|
|
307417
307921
|
resolution
|
|
307418
307922
|
});
|
|
307419
|
-
return `workflow-review-${
|
|
307923
|
+
return `workflow-review-${createHash35("sha256").update(identity).digest("hex").slice(0, 24)}`;
|
|
307420
307924
|
}
|
|
307421
307925
|
async function buildWorkflowReviewItems(task, store) {
|
|
307422
307926
|
const declaredTopLevelReviewResultSources = await getDeclaredTopLevelReviewResultSources(task, store);
|
|
@@ -307865,6 +308369,32 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
307865
308369
|
rethrowAsApiError8(err);
|
|
307866
308370
|
}
|
|
307867
308371
|
});
|
|
308372
|
+
router.get("/tasks/recommendations", async (req, res) => {
|
|
308373
|
+
try {
|
|
308374
|
+
const { store: scopedStore } = await getProjectContext2(req);
|
|
308375
|
+
const parsePageNumber = (value2, name2) => {
|
|
308376
|
+
if (value2 === void 0) return void 0;
|
|
308377
|
+
if (typeof value2 !== "string" || value2.trim() === "" || !Number.isInteger(Number(value2)) || Number(value2) < 0) {
|
|
308378
|
+
throw badRequest(`${name2} must be a non-negative integer`);
|
|
308379
|
+
}
|
|
308380
|
+
return Number(value2);
|
|
308381
|
+
};
|
|
308382
|
+
const requestedLimit = parsePageNumber(req.query.limit, "limit");
|
|
308383
|
+
const offset = parsePageNumber(req.query.offset, "offset");
|
|
308384
|
+
if (requestedLimit === 0) throw badRequest("limit must be a positive integer");
|
|
308385
|
+
const limit2 = requestedLimit === void 0 ? void 0 : Math.min(200, requestedLimit);
|
|
308386
|
+
let completeColumns;
|
|
308387
|
+
try {
|
|
308388
|
+
completeColumns = await resolveProjectColumnsForRoles(scopedStore, ["complete"]);
|
|
308389
|
+
} catch {
|
|
308390
|
+
completeColumns = /* @__PURE__ */ new Set(["done"]);
|
|
308391
|
+
}
|
|
308392
|
+
res.json(await scopedStore.listTaskRecommendations({ completeColumns, limit: limit2, offset }));
|
|
308393
|
+
} catch (err) {
|
|
308394
|
+
if (err instanceof ApiError) throw err;
|
|
308395
|
+
rethrowAsApiError8(err);
|
|
308396
|
+
}
|
|
308397
|
+
});
|
|
307868
308398
|
router.post("/tasks/duplicate-check", async (req, res) => {
|
|
307869
308399
|
try {
|
|
307870
308400
|
const { store: scopedStore } = await getProjectContext2(req);
|
|
@@ -326179,6 +326709,7 @@ function registerMessagingScriptRoutes(ctx) {
|
|
|
326179
326709
|
limit: parseInt(req.query.limit) || 20,
|
|
326180
326710
|
offset: parseInt(req.query.offset) || 0,
|
|
326181
326711
|
read: req.query.unreadOnly === "true" ? false : void 0,
|
|
326712
|
+
archived: req.query.archived === "true",
|
|
326182
326713
|
type: req.query.type
|
|
326183
326714
|
};
|
|
326184
326715
|
const messages3 = await msgStore.getInbox(DASHBOARD_USER_ID, "user", filter2);
|
|
@@ -326197,6 +326728,7 @@ function registerMessagingScriptRoutes(ctx) {
|
|
|
326197
326728
|
const filter2 = {
|
|
326198
326729
|
limit: parseInt(req.query.limit) || 20,
|
|
326199
326730
|
offset: parseInt(req.query.offset) || 0,
|
|
326731
|
+
archived: req.query.archived === "true",
|
|
326200
326732
|
type: req.query.type
|
|
326201
326733
|
};
|
|
326202
326734
|
const messages3 = await msgStore.getOutbox(DASHBOARD_USER_ID, "user", filter2);
|
|
@@ -326313,7 +326845,8 @@ function registerMessagingScriptRoutes(ctx) {
|
|
|
326313
326845
|
const msgStore = await getMessageStore(req);
|
|
326314
326846
|
const messages3 = await msgStore.getConversation(
|
|
326315
326847
|
{ id: DASHBOARD_USER_ID, type: "user" },
|
|
326316
|
-
{ id: participantId, type: participantType }
|
|
326848
|
+
{ id: participantId, type: participantType },
|
|
326849
|
+
{ archived: req.query.archived === "true" }
|
|
326317
326850
|
);
|
|
326318
326851
|
res.json(messages3);
|
|
326319
326852
|
} catch (err) {
|
|
@@ -326405,6 +326938,26 @@ function registerMessagingScriptRoutes(ctx) {
|
|
|
326405
326938
|
rethrowAsApiError8(err);
|
|
326406
326939
|
}
|
|
326407
326940
|
});
|
|
326941
|
+
router.post("/messages/:id/archive", async (req, res) => {
|
|
326942
|
+
try {
|
|
326943
|
+
const message = await (await getMessageStore(req)).archiveMessage(req.params.id);
|
|
326944
|
+
res.json(message);
|
|
326945
|
+
} catch (err) {
|
|
326946
|
+
if (err instanceof ApiError) throw err;
|
|
326947
|
+
if ((err instanceof Error ? err.message : String(err)).includes("not found")) throw notFound(err instanceof Error ? err.message : String(err));
|
|
326948
|
+
rethrowAsApiError8(err);
|
|
326949
|
+
}
|
|
326950
|
+
});
|
|
326951
|
+
router.post("/messages/:id/unarchive", async (req, res) => {
|
|
326952
|
+
try {
|
|
326953
|
+
const message = await (await getMessageStore(req)).unarchiveMessage(req.params.id);
|
|
326954
|
+
res.json(message);
|
|
326955
|
+
} catch (err) {
|
|
326956
|
+
if (err instanceof ApiError) throw err;
|
|
326957
|
+
if ((err instanceof Error ? err.message : String(err)).includes("not found")) throw notFound(err instanceof Error ? err.message : String(err));
|
|
326958
|
+
rethrowAsApiError8(err);
|
|
326959
|
+
}
|
|
326960
|
+
});
|
|
326408
326961
|
router.post("/messages/:id/read", async (req, res) => {
|
|
326409
326962
|
try {
|
|
326410
326963
|
const msgStore = await getMessageStore(req);
|
|
@@ -326438,7 +326991,7 @@ function registerMessagingScriptRoutes(ctx) {
|
|
|
326438
326991
|
router.get("/agents/mailbox/all", async (req, res) => {
|
|
326439
326992
|
try {
|
|
326440
326993
|
const msgStore = await getMessageStore(req);
|
|
326441
|
-
const messages3 = await msgStore.getAllAgentToAgentMessages();
|
|
326994
|
+
const messages3 = await msgStore.getAllAgentToAgentMessages({ archived: req.query.archived === "true" });
|
|
326442
326995
|
const unreadCount = await msgStore.getUnreadAgentToAgentCount();
|
|
326443
326996
|
res.json({ messages: messages3, total: messages3.length, unreadCount });
|
|
326444
326997
|
} catch (err) {
|
|
@@ -326453,8 +327006,9 @@ function registerMessagingScriptRoutes(ctx) {
|
|
|
326453
327006
|
const msgStore = await getMessageStore(req);
|
|
326454
327007
|
const agentId = req.params.id;
|
|
326455
327008
|
const mailbox = await msgStore.getMailbox(agentId, "agent");
|
|
326456
|
-
const
|
|
326457
|
-
const
|
|
327009
|
+
const archived = req.query.archived === "true";
|
|
327010
|
+
const inbox = await msgStore.getInbox(agentId, "agent", { archived });
|
|
327011
|
+
const outbox = await msgStore.getOutbox(agentId, "agent", { archived });
|
|
326458
327012
|
res.json({ ...mailbox, messages: inbox, inbox, outbox });
|
|
326459
327013
|
} catch (err) {
|
|
326460
327014
|
if (err instanceof ApiError) {
|
|
@@ -357028,8 +357582,8 @@ var init_register_settings_sync_routes = __esm({
|
|
|
357028
357582
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
357029
357583
|
version: 1
|
|
357030
357584
|
};
|
|
357031
|
-
const { createHash:
|
|
357032
|
-
const checksum =
|
|
357585
|
+
const { createHash: createHash39 } = await import("node:crypto");
|
|
357586
|
+
const checksum = createHash39("sha256").update(JSON.stringify(payloadWithoutChecksum)).digest("hex");
|
|
357033
357587
|
const localPeerInfo = await central.getLocalPeerInfo();
|
|
357034
357588
|
await fetchFromRemoteNode(node, "/api/settings/sync-receive", {
|
|
357035
357589
|
method: "POST",
|
|
@@ -357100,7 +357654,7 @@ var init_register_settings_sync_routes = __esm({
|
|
|
357100
357654
|
});
|
|
357101
357655
|
return;
|
|
357102
357656
|
}
|
|
357103
|
-
const { createHash:
|
|
357657
|
+
const { createHash: createHash39 } = await import("node:crypto");
|
|
357104
357658
|
const exportedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
357105
357659
|
const payloadWithoutChecksum = {
|
|
357106
357660
|
global: remoteSettings.global,
|
|
@@ -357109,7 +357663,7 @@ var init_register_settings_sync_routes = __esm({
|
|
|
357109
357663
|
exportedAt,
|
|
357110
357664
|
version: 1
|
|
357111
357665
|
};
|
|
357112
|
-
const checksum =
|
|
357666
|
+
const checksum = createHash39("sha256").update(JSON.stringify(payloadWithoutChecksum)).digest("hex");
|
|
357113
357667
|
const result2 = await central.applyRemoteSettings({
|
|
357114
357668
|
...payloadWithoutChecksum,
|
|
357115
357669
|
checksum
|
|
@@ -383863,7 +384417,7 @@ var init_report_scrub = __esm({
|
|
|
383863
384417
|
});
|
|
383864
384418
|
|
|
383865
384419
|
// ../dashboard/src/report-pipeline.ts
|
|
383866
|
-
import { createHash as
|
|
384420
|
+
import { createHash as createHash36 } from "node:crypto";
|
|
383867
384421
|
function resolveReportMode(actionType, settings) {
|
|
383868
384422
|
return settings.reportModeByAction?.[actionType] ?? settings.reportMode ?? "draft-review";
|
|
383869
384423
|
}
|
|
@@ -383979,7 +384533,7 @@ async function embedScreenshot(args) {
|
|
|
383979
384533
|
try {
|
|
383980
384534
|
const extension = EXT_BY_MIME[attachment.mimeType];
|
|
383981
384535
|
if (!extension) return args.report;
|
|
383982
|
-
const safeId2 =
|
|
384536
|
+
const safeId2 = createHash36("sha256").update(`${args.report.sessionToken ?? ""}:${attachment.artifactId}`).digest("hex").slice(0, 32);
|
|
383983
384537
|
const path14 = `.fusion-reports/${safeId2}/screenshot.${extension}`;
|
|
383984
384538
|
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 });
|
|
383985
384539
|
const alt = markdownEscapeImageAlt(scrubReportText(attachment.filename, args.scrubContext) || "Report screenshot");
|
|
@@ -387093,7 +387647,7 @@ var init_types6 = __esm({
|
|
|
387093
387647
|
});
|
|
387094
387648
|
|
|
387095
387649
|
// ../dashboard/src/stt/model-manager.ts
|
|
387096
|
-
import { createHash as
|
|
387650
|
+
import { createHash as createHash37, randomUUID as randomUUID68 } from "node:crypto";
|
|
387097
387651
|
import { mkdir as mkdir40, open as open4, readFile as readFile63, readdir as readdir16, rename as rename12, rm as rm24, stat as stat18, writeFile as writeFile39 } from "node:fs/promises";
|
|
387098
387652
|
import { join as join125, relative as relative26, resolve as resolve75, sep as sep20 } from "node:path";
|
|
387099
387653
|
function parseSafeTarListing(listing) {
|
|
@@ -387182,7 +387736,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
387182
387736
|
if (!response.ok || !response.body) throw Object.assign(new Error("download failed"), { voiceReason: "network" });
|
|
387183
387737
|
if (!current(g2, signal)) return state;
|
|
387184
387738
|
const total = Number(response.headers.get("content-length")) || void 0;
|
|
387185
|
-
const hash3 =
|
|
387739
|
+
const hash3 = createHash37("sha256");
|
|
387186
387740
|
let bytes = 0;
|
|
387187
387741
|
for await (const chunk of response.body) {
|
|
387188
387742
|
if (!current(g2, signal)) return state;
|
|
@@ -400841,7 +401395,7 @@ data: ${JSON.stringify({ type: event.type, data: event.data })}
|
|
|
400841
401395
|
const endIso = new Date(nowMs).toISOString();
|
|
400842
401396
|
const auditFilter = { startTime: startIso, endTime: endIso, limit: 5e4 };
|
|
400843
401397
|
const asyncLayer = scopedStore.getAsyncLayer();
|
|
400844
|
-
const runAuditEventsPromise = asyncLayer ? queryRunAuditEvents(asyncLayer.db, auditFilter).then((events) => events.map((event) => ({
|
|
401398
|
+
const runAuditEventsPromise = asyncLayer ? queryRunAuditEvents(asyncLayer.db, auditFilter, asyncLayer.projectId).then((events) => events.map((event) => ({
|
|
400845
401399
|
...event,
|
|
400846
401400
|
domain: event.domain,
|
|
400847
401401
|
mutationType: event.mutationType,
|
|
@@ -402428,7 +402982,7 @@ var init_extension = __esm({
|
|
|
402428
402982
|
});
|
|
402429
402983
|
|
|
402430
402984
|
// src/commands/task-lifecycle.ts
|
|
402431
|
-
import { createHash as
|
|
402985
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
402432
402986
|
import { exec as exec63 } from "node:child_process";
|
|
402433
402987
|
import * as childProcess5 from "node:child_process";
|
|
402434
402988
|
import { mkdir as mkdir43, realpath as realpath7, rm as rm25 } from "node:fs/promises";
|
|
@@ -402601,7 +403155,7 @@ async function refreshAutomatedPrHead(input) {
|
|
|
402601
403155
|
await mkdir43(refreshWorktreesDir, { recursive: true });
|
|
402602
403156
|
temporary = join135(
|
|
402603
403157
|
refreshWorktreesDir,
|
|
402604
|
-
`pr-refresh-${
|
|
403158
|
+
`pr-refresh-${createHash38("sha256").update(input.headBranch).digest("hex").slice(0, 16)}`
|
|
402605
403159
|
);
|
|
402606
403160
|
const reservationDir = join135(root, ".fusion", "pr-refresh-reservations");
|
|
402607
403161
|
await mkdir43(reservationDir, { recursive: true });
|