@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
|
@@ -2145,6 +2145,8 @@ var init_settings_schema = __esm({
|
|
|
2145
2145
|
DEFAULT_PROJECT_SETTINGS = {
|
|
2146
2146
|
// FNXC:TaskRecommendations 2026-08-08-05:02: completion follows-ups stay bounded by default; 0 disables writing them.
|
|
2147
2147
|
maxRecommendationsPerTask: 3,
|
|
2148
|
+
// FNXC:TaskRecommendations 2026-08-13-03:56: surface completed-task proposals by default; operators can suppress the notice without suppressing capture.
|
|
2149
|
+
recommendationMailboxNoticeEnabled: true,
|
|
2148
2150
|
globalPause: false,
|
|
2149
2151
|
globalPauseReason: void 0,
|
|
2150
2152
|
defaultWorkflowId: void 0,
|
|
@@ -21717,9 +21719,14 @@ var init_project = __esm({
|
|
|
21717
21719
|
// now keyed per-project on `project_id` (the effective PK). `id` is retained
|
|
21718
21720
|
// for column-shape parity (always 1) but is no longer the PK and no longer
|
|
21719
21721
|
// CHECK-constrained. Single-project / SQLite-parity callers leave project_id
|
|
21720
|
-
//
|
|
21722
|
+
// through the database ownership trigger, preserving the pre-isolation behavior.
|
|
21723
|
+
/*
|
|
21724
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
21725
|
+
Migration 0006 owns config's project_id default and leaves its catalog PK as (project_id).
|
|
21726
|
+
Drizzle emits DEFAULT while the database GUC/trigger selects the effective ownership partition.
|
|
21727
|
+
*/
|
|
21721
21728
|
id: integer("id").default(1),
|
|
21722
|
-
projectId: text("project_id").notNull().default(
|
|
21729
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`).primaryKey(),
|
|
21723
21730
|
nextId: integer("next_id").default(1),
|
|
21724
21731
|
nextWorkflowStepId: integer("next_workflow_step_id").default(1),
|
|
21725
21732
|
// FNXC:SqliteFinalRemoval 2026-06-28:
|
|
@@ -22113,9 +22120,13 @@ var init_project = __esm({
|
|
|
22113
22120
|
automations = projectSchema.table("automations", {
|
|
22114
22121
|
/*
|
|
22115
22122
|
* FNXC:AutomationIsolation 2026-07-13-22:37:
|
|
22116
|
-
* 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.
|
|
22123
|
+
* 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.
|
|
22124
|
+
*
|
|
22125
|
+
* FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
22126
|
+
* Migration 0006 owns the default through the database GUC/trigger; Drizzle emits DEFAULT
|
|
22127
|
+
* without replacing the physical legacy fallback or the fail-closed bound writer contract.
|
|
22117
22128
|
*/
|
|
22118
|
-
projectId: text("project_id").notNull().default(
|
|
22129
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22119
22130
|
id: text("id").notNull(),
|
|
22120
22131
|
name: text("name").notNull(),
|
|
22121
22132
|
description: text("description"),
|
|
@@ -22414,7 +22425,8 @@ var init_project = __esm({
|
|
|
22414
22425
|
index("idxTaskDocumentsTaskId").on(t.taskId)
|
|
22415
22426
|
]);
|
|
22416
22427
|
artifacts = projectSchema.table("artifacts", {
|
|
22417
|
-
|
|
22428
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22429
|
+
id: text("id").notNull(),
|
|
22418
22430
|
type: text("type").notNull(),
|
|
22419
22431
|
title: text("title").notNull(),
|
|
22420
22432
|
description: text("description"),
|
|
@@ -22429,7 +22441,8 @@ var init_project = __esm({
|
|
|
22429
22441
|
createdAt: text("created_at").notNull(),
|
|
22430
22442
|
updatedAt: text("updated_at").notNull()
|
|
22431
22443
|
}, (t) => [
|
|
22432
|
-
|
|
22444
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
22445
|
+
foreignKey({ name: "artifacts_task_id_fkey", columns: [t.projectId, t.taskId], foreignColumns: [tasks.projectId, tasks.id] }).onDelete("cascade"),
|
|
22433
22446
|
index("idxArtifactsTaskId").on(t.taskId),
|
|
22434
22447
|
index("idxArtifactsAuthorId").on(t.authorId),
|
|
22435
22448
|
index("idxArtifactsType").on(t.type),
|
|
@@ -22619,7 +22632,8 @@ var init_project = __esm({
|
|
|
22619
22632
|
index("idxEvalRunEventsRunIdSeq").on(t.runId, t.seq)
|
|
22620
22633
|
]);
|
|
22621
22634
|
secrets = projectSchema.table("secrets", {
|
|
22622
|
-
|
|
22635
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22636
|
+
id: text("id").notNull(),
|
|
22623
22637
|
key: text("key").notNull(),
|
|
22624
22638
|
valueCiphertext: bytea("value_ciphertext").notNull(),
|
|
22625
22639
|
nonce: bytea("nonce").notNull(),
|
|
@@ -22632,7 +22646,8 @@ var init_project = __esm({
|
|
|
22632
22646
|
lastReadAt: text("last_read_at"),
|
|
22633
22647
|
lastReadBy: text("last_read_by")
|
|
22634
22648
|
}, (t) => [
|
|
22635
|
-
|
|
22649
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
22650
|
+
unique("secrets_key_unique").on(t.projectId, t.key),
|
|
22636
22651
|
check("secrets_access_policy_check", sql`${t.accessPolicy} IN ('auto', 'prompt', 'deny')`),
|
|
22637
22652
|
check("secrets_env_exportable_check", sql`${t.envExportable} IN (0, 1)`)
|
|
22638
22653
|
]);
|
|
@@ -22674,10 +22689,11 @@ var init_project = __esm({
|
|
|
22674
22689
|
updatedAt: text("updated_at").notNull()
|
|
22675
22690
|
}, (t) => [primaryKey({ columns: [t.projectId, t.id] })]);
|
|
22676
22691
|
branchGroups = projectSchema.table("branch_groups", {
|
|
22677
|
-
|
|
22692
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
22693
|
+
id: text("id").notNull(),
|
|
22678
22694
|
sourceType: text("source_type").notNull(),
|
|
22679
22695
|
sourceId: text("source_id").notNull(),
|
|
22680
|
-
branchName: text("branch_name").notNull()
|
|
22696
|
+
branchName: text("branch_name").notNull(),
|
|
22681
22697
|
worktreePath: text("worktree_path"),
|
|
22682
22698
|
autoMerge: integer("auto_merge").notNull().default(0),
|
|
22683
22699
|
prState: text("pr_state").notNull().default("none"),
|
|
@@ -22693,6 +22709,8 @@ var init_project = __esm({
|
|
|
22693
22709
|
updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
|
|
22694
22710
|
closedAt: bigint("closed_at", { mode: "number" })
|
|
22695
22711
|
}, (t) => [
|
|
22712
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
22713
|
+
unique("branch_groups_branch_name_key").on(t.projectId, t.branchName),
|
|
22696
22714
|
check("branch_groups_source_type_check", sql`${t.sourceType} IN ('mission','planning','new-task')`),
|
|
22697
22715
|
check("branch_groups_pr_state_check", sql`${t.prState} IN ('none','open','merged','closed')`),
|
|
22698
22716
|
check("branch_groups_status_check", sql`${t.status} IN ('open','finalized','abandoned')`),
|
|
@@ -23094,12 +23112,14 @@ var init_project = __esm({
|
|
|
23094
23112
|
index("idxUsageEventsKindTs").on(t.kind, t.ts)
|
|
23095
23113
|
]);
|
|
23096
23114
|
pluginActivations = projectSchema.table("plugin_activations", {
|
|
23097
|
-
|
|
23115
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23116
|
+
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23098
23117
|
pluginId: text("plugin_id").notNull(),
|
|
23099
23118
|
source: text("source").notNull(),
|
|
23100
23119
|
pluginVersion: text("plugin_version"),
|
|
23101
23120
|
activatedAt: text("activated_at").notNull()
|
|
23102
23121
|
}, (t) => [
|
|
23122
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23103
23123
|
index("idxPluginActivationsActivatedAt").on(t.activatedAt),
|
|
23104
23124
|
index("idxPluginActivationsPluginId").on(t.pluginId)
|
|
23105
23125
|
]);
|
|
@@ -23124,8 +23144,13 @@ var init_project = __esm({
|
|
|
23124
23144
|
index("idxKnowledgePagesUpdatedAt").on(t.updatedAt)
|
|
23125
23145
|
]);
|
|
23126
23146
|
deployments = projectSchema.table("deployments", {
|
|
23127
|
-
id: integer("id").generatedAlwaysAsIdentity().
|
|
23128
|
-
|
|
23147
|
+
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23148
|
+
/*
|
|
23149
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
23150
|
+
Migration 0006 rebuilt deployments_pkey as (project_id, id). Drizzle emits DEFAULT while the
|
|
23151
|
+
database GUC/trigger keeps ownership stamping and the physical legacy fallback authoritative.
|
|
23152
|
+
*/
|
|
23153
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23129
23154
|
deploymentId: text("deployment_id").notNull(),
|
|
23130
23155
|
service: text("service"),
|
|
23131
23156
|
environment: text("environment"),
|
|
@@ -23136,6 +23161,7 @@ var init_project = __esm({
|
|
|
23136
23161
|
meta: jsonb("meta"),
|
|
23137
23162
|
createdAt: text("created_at").notNull()
|
|
23138
23163
|
}, (t) => [
|
|
23164
|
+
primaryKey({ columns: [t.projectId, t.id], name: "deployments_pkey" }),
|
|
23139
23165
|
uniqueIndex("idxDeploymentsProjectDeploymentId").on(t.projectId, t.deploymentId),
|
|
23140
23166
|
index("idxDeploymentsProjectDeployedAt").on(t.projectId, t.deployedAt),
|
|
23141
23167
|
index("idxDeploymentsDeployedAt").on(t.deployedAt),
|
|
@@ -23143,7 +23169,12 @@ var init_project = __esm({
|
|
|
23143
23169
|
]);
|
|
23144
23170
|
githubCheckStates = projectSchema.table("github_check_states", {
|
|
23145
23171
|
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23146
|
-
|
|
23172
|
+
/*
|
|
23173
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
23174
|
+
Migration 0048 post-dated 0006, so FN-9004 reconciles its physical default to the ownership
|
|
23175
|
+
expression. Drizzle emits DEFAULT while the database GUC/trigger remains the stamping authority.
|
|
23176
|
+
*/
|
|
23177
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23147
23178
|
repo: text("repo").notNull(),
|
|
23148
23179
|
headSha: text("head_sha").notNull(),
|
|
23149
23180
|
checkName: text("check_name").notNull(),
|
|
@@ -23163,9 +23194,14 @@ var init_project = __esm({
|
|
|
23163
23194
|
index("idxGithubCheckStatesProjectReceived").on(t.projectId, t.receivedAt)
|
|
23164
23195
|
]);
|
|
23165
23196
|
incidents = projectSchema.table("incidents", {
|
|
23166
|
-
id: integer("id").generatedAlwaysAsIdentity().
|
|
23167
|
-
|
|
23168
|
-
|
|
23197
|
+
id: integer("id").generatedAlwaysAsIdentity().notNull(),
|
|
23198
|
+
/*
|
|
23199
|
+
FNXC:MultiProjectIsolation 2026-08-12-15:43:
|
|
23200
|
+
Migration 0006 rebuilt incident keys with project_id first. Drizzle emits DEFAULT while the
|
|
23201
|
+
database GUC/trigger retains ownership stamping and its physical legacy fallback.
|
|
23202
|
+
*/
|
|
23203
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23204
|
+
incidentId: text("incident_id").notNull(),
|
|
23169
23205
|
groupingKey: text("grouping_key").notNull(),
|
|
23170
23206
|
title: text("title").notNull(),
|
|
23171
23207
|
severity: text("severity"),
|
|
@@ -23179,6 +23215,8 @@ var init_project = __esm({
|
|
|
23179
23215
|
createdAt: text("created_at").notNull(),
|
|
23180
23216
|
updatedAt: text("updated_at").notNull()
|
|
23181
23217
|
}, (t) => [
|
|
23218
|
+
primaryKey({ columns: [t.projectId, t.id], name: "incidents_pkey" }),
|
|
23219
|
+
unique("incidents_incident_id_key").on(t.projectId, t.incidentId),
|
|
23182
23220
|
index("idxIncidentsProjectOpenedAt").on(t.projectId, t.openedAt),
|
|
23183
23221
|
index("idxIncidentsProjectStatus").on(t.projectId, t.status),
|
|
23184
23222
|
index("idxIncidentsGroupingKey").on(t.groupingKey),
|
|
@@ -23233,12 +23271,14 @@ var init_project = __esm({
|
|
|
23233
23271
|
content: text("content").notNull(),
|
|
23234
23272
|
type: text("type").notNull(),
|
|
23235
23273
|
read: integer("read").default(0),
|
|
23274
|
+
archived: integer("archived").default(0),
|
|
23236
23275
|
metadata: jsonb("metadata"),
|
|
23237
23276
|
createdAt: text("created_at").notNull(),
|
|
23238
23277
|
updatedAt: text("updated_at").notNull()
|
|
23239
23278
|
}, (t) => [
|
|
23240
23279
|
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23241
23280
|
index("idxMessagesTo").on(t.toId, t.toType, t.read),
|
|
23281
|
+
index("idxMessagesToArchived").on(t.toId, t.toType, t.archived),
|
|
23242
23282
|
index("idxMessagesFrom").on(t.fromId, t.fromType),
|
|
23243
23283
|
index("idxMessagesCreatedAt").on(t.createdAt)
|
|
23244
23284
|
]);
|
|
@@ -23339,7 +23379,8 @@ var init_project = __esm({
|
|
|
23339
23379
|
index("idx_cli_sessions_project_state").on(t.projectId, t.agentState)
|
|
23340
23380
|
]);
|
|
23341
23381
|
chatMessages = projectSchema.table("chat_messages", {
|
|
23342
|
-
|
|
23382
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23383
|
+
id: text("id").notNull(),
|
|
23343
23384
|
sessionId: text("session_id").notNull(),
|
|
23344
23385
|
role: text("role").notNull(),
|
|
23345
23386
|
content: text("content").notNull(),
|
|
@@ -23348,6 +23389,7 @@ var init_project = __esm({
|
|
|
23348
23389
|
createdAt: text("created_at").notNull(),
|
|
23349
23390
|
attachments: jsonb("attachments")
|
|
23350
23391
|
}, (t) => [
|
|
23392
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23351
23393
|
index("idxChatMessagesSessionId").on(t.sessionId),
|
|
23352
23394
|
index("idxChatMessagesCreatedAt").on(t.createdAt)
|
|
23353
23395
|
]);
|
|
@@ -23373,7 +23415,8 @@ var init_project = __esm({
|
|
|
23373
23415
|
index("idxChatTokenUsageCreatedAt").on(t.createdAt)
|
|
23374
23416
|
]);
|
|
23375
23417
|
runAuditEvents = projectSchema.table("run_audit_events", {
|
|
23376
|
-
|
|
23418
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23419
|
+
id: text("id").notNull(),
|
|
23377
23420
|
timestamp: text("timestamp").notNull(),
|
|
23378
23421
|
taskId: text("task_id"),
|
|
23379
23422
|
agentId: text("agent_id").notNull(),
|
|
@@ -23383,6 +23426,7 @@ var init_project = __esm({
|
|
|
23383
23426
|
target: text("target").notNull(),
|
|
23384
23427
|
metadata: jsonb("metadata")
|
|
23385
23428
|
}, (t) => [
|
|
23429
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23386
23430
|
index("idxRunAuditEventsRunIdTimestamp").on(t.runId, t.timestamp),
|
|
23387
23431
|
index("idxRunAuditEventsTaskIdTimestamp").on(t.taskId, t.timestamp),
|
|
23388
23432
|
index("idxRunAuditEventsTimestamp").on(t.timestamp)
|
|
@@ -23483,13 +23527,14 @@ var init_project = __esm({
|
|
|
23483
23527
|
index("idxMissionLineageStopsMissionId").on(t.projectId, t.missionId)
|
|
23484
23528
|
]);
|
|
23485
23529
|
verificationCache = projectSchema.table("verification_cache", {
|
|
23530
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23486
23531
|
treeSha: text("tree_sha").notNull(),
|
|
23487
23532
|
testCommand: text("test_command").notNull().default(""),
|
|
23488
23533
|
buildCommand: text("build_command").notNull().default(""),
|
|
23489
23534
|
recordedAt: text("recorded_at").notNull(),
|
|
23490
23535
|
taskId: text("task_id")
|
|
23491
23536
|
}, (t) => [
|
|
23492
|
-
primaryKey({ columns: [t.treeSha, t.testCommand, t.buildCommand] }),
|
|
23537
|
+
primaryKey({ columns: [t.projectId, t.treeSha, t.testCommand, t.buildCommand] }),
|
|
23493
23538
|
index("idxVerificationCacheRecordedAt").on(t.recordedAt)
|
|
23494
23539
|
]);
|
|
23495
23540
|
importTranslationCache = projectSchema.table("import_translation_cache", {
|
|
@@ -23522,7 +23567,8 @@ var init_project = __esm({
|
|
|
23522
23567
|
index("idxImportTranslationCacheRecordedAt").on(t.recordedAt)
|
|
23523
23568
|
]);
|
|
23524
23569
|
approvalRequests = projectSchema.table("approval_requests", {
|
|
23525
|
-
|
|
23570
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23571
|
+
id: text("id").notNull(),
|
|
23526
23572
|
status: text("status").notNull(),
|
|
23527
23573
|
requesterActorId: text("requester_actor_id").notNull(),
|
|
23528
23574
|
requesterActorType: text("requester_actor_type").notNull(),
|
|
@@ -23541,13 +23587,14 @@ var init_project = __esm({
|
|
|
23541
23587
|
createdAt: text("created_at").notNull(),
|
|
23542
23588
|
updatedAt: text("updated_at").notNull()
|
|
23543
23589
|
}, (t) => [
|
|
23590
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23544
23591
|
index("idxApprovalRequestsStatusCreatedAt").on(t.status, t.createdAt),
|
|
23545
23592
|
index("idxApprovalRequestsRequesterCreatedAt").on(t.requesterActorId, t.createdAt),
|
|
23546
23593
|
index("idxApprovalRequestsTaskCreatedAt").on(t.taskId, t.createdAt)
|
|
23547
23594
|
]);
|
|
23548
23595
|
approvalRequestAuditEvents = projectSchema.table("approval_request_audit_events", {
|
|
23549
|
-
projectId: text("project_id").notNull().default(
|
|
23550
|
-
id: text("id").
|
|
23596
|
+
projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
|
|
23597
|
+
id: text("id").notNull(),
|
|
23551
23598
|
requestId: text("request_id").notNull(),
|
|
23552
23599
|
eventType: text("event_type").notNull(),
|
|
23553
23600
|
actorId: text("actor_id").notNull(),
|
|
@@ -23556,6 +23603,7 @@ var init_project = __esm({
|
|
|
23556
23603
|
note: text("note"),
|
|
23557
23604
|
createdAt: text("created_at").notNull()
|
|
23558
23605
|
}, (t) => [
|
|
23606
|
+
primaryKey({ columns: [t.projectId, t.id] }),
|
|
23559
23607
|
index("idxApprovalRequestAuditRequestCreatedAt").on(t.requestId, t.createdAt, t.id),
|
|
23560
23608
|
index("idxApprovalRequestAuditProjectCreatedAt").on(t.projectId, t.createdAt)
|
|
23561
23609
|
]);
|
|
@@ -27045,6 +27093,27 @@ var init_grok_provider = __esm({
|
|
|
27045
27093
|
apiKey: "$GROK_API_KEY",
|
|
27046
27094
|
api: "openai-completions",
|
|
27047
27095
|
models: [
|
|
27096
|
+
/*
|
|
27097
|
+
FNXC:ModelRegistry 2026-08-12-20:17:
|
|
27098
|
+
FN-9008 requires Grok 4.6 to be selectable in every model area. Keep it in this shared
|
|
27099
|
+
catalog because pi's registerProvider() replaces provider model lists wholesale, while every
|
|
27100
|
+
Fusion host seeds and re-merges this export. xAI's model docs verify grok-4.6, its 500k-token
|
|
27101
|
+
context window, and configurable reasoning; max output and per-model image input remain
|
|
27102
|
+
upstream-pending-verification, so retain the conservative text-only and 65536-token defaults.
|
|
27103
|
+
Source: https://docs.x.ai/developers/models
|
|
27104
|
+
*/
|
|
27105
|
+
{
|
|
27106
|
+
id: "grok-4.6",
|
|
27107
|
+
name: "Grok 4.6",
|
|
27108
|
+
reasoning: true,
|
|
27109
|
+
input: ["text"],
|
|
27110
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
27111
|
+
contextWindow: 5e5,
|
|
27112
|
+
maxTokens: 65536,
|
|
27113
|
+
compat: {
|
|
27114
|
+
supportsDeveloperRole: false
|
|
27115
|
+
}
|
|
27116
|
+
},
|
|
27048
27117
|
{
|
|
27049
27118
|
id: "grok-4.5",
|
|
27050
27119
|
name: "Grok 4.5",
|
|
@@ -35003,6 +35072,7 @@ function rowToMessage(row) {
|
|
|
35003
35072
|
content: row.content,
|
|
35004
35073
|
type: row.type,
|
|
35005
35074
|
read: (row.read ?? 0) === 1,
|
|
35075
|
+
archived: (row.archived ?? 0) === 1,
|
|
35006
35076
|
metadata: row.metadata ?? void 0,
|
|
35007
35077
|
createdAt: row.createdAt,
|
|
35008
35078
|
updatedAt: row.updatedAt
|
|
@@ -35014,6 +35084,11 @@ function participantIdsForLookup(ownerId, ownerType) {
|
|
|
35014
35084
|
}
|
|
35015
35085
|
return [ownerId];
|
|
35016
35086
|
}
|
|
35087
|
+
function archivedCondition(archived) {
|
|
35088
|
+
if (archived === true) return eq(project_exports.messages.archived, 1);
|
|
35089
|
+
if (archived === false) return or(eq(project_exports.messages.archived, 0), sql`${project_exports.messages.archived} IS NULL`);
|
|
35090
|
+
return or(eq(project_exports.messages.archived, 0), sql`${project_exports.messages.archived} IS NULL`);
|
|
35091
|
+
}
|
|
35017
35092
|
async function sendMessage(handle, message) {
|
|
35018
35093
|
const sanitizedContent = sanitizeTextValue(message.content);
|
|
35019
35094
|
const sanitizedMetadata = sanitizeJsonbValue(message.metadata);
|
|
@@ -35026,6 +35101,7 @@ async function sendMessage(handle, message) {
|
|
|
35026
35101
|
content: sanitizedContent,
|
|
35027
35102
|
type: message.type,
|
|
35028
35103
|
read: message.read ? 1 : 0,
|
|
35104
|
+
archived: message.archived ? 1 : 0,
|
|
35029
35105
|
metadata: sanitizedMetadata,
|
|
35030
35106
|
createdAt: message.createdAt,
|
|
35031
35107
|
updatedAt: message.updatedAt
|
|
@@ -35034,7 +35110,8 @@ async function sendMessage(handle, message) {
|
|
|
35034
35110
|
...message,
|
|
35035
35111
|
content: sanitizedContent,
|
|
35036
35112
|
metadata: sanitizedMetadata,
|
|
35037
|
-
read: message.read ? 1 : 0
|
|
35113
|
+
read: message.read ? 1 : 0,
|
|
35114
|
+
archived: message.archived ? 1 : 0
|
|
35038
35115
|
});
|
|
35039
35116
|
}
|
|
35040
35117
|
async function sendMessageOnce(handle, message) {
|
|
@@ -35047,6 +35124,7 @@ async function sendMessageOnce(handle, message) {
|
|
|
35047
35124
|
content: message.content,
|
|
35048
35125
|
type: message.type,
|
|
35049
35126
|
read: message.read ? 1 : 0,
|
|
35127
|
+
archived: message.archived ? 1 : 0,
|
|
35050
35128
|
metadata: message.metadata,
|
|
35051
35129
|
createdAt: message.createdAt,
|
|
35052
35130
|
updatedAt: message.updatedAt
|
|
@@ -35098,6 +35176,7 @@ async function queryMessagesByParticipant(handle, direction, ownerId, ownerType,
|
|
|
35098
35176
|
if (filter?.read !== void 0) {
|
|
35099
35177
|
conditions.push(eq(project_exports.messages.read, filter.read ? 1 : 0));
|
|
35100
35178
|
}
|
|
35179
|
+
conditions.push(archivedCondition(filter?.archived));
|
|
35101
35180
|
const limit = filter?.limit ?? 100;
|
|
35102
35181
|
const offset = filter?.offset ?? 0;
|
|
35103
35182
|
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(limit).offset(offset);
|
|
@@ -35111,6 +35190,13 @@ async function markMessageAsRead(handle, messageId) {
|
|
|
35111
35190
|
await handle.update(project_exports.messages).set({ read: 1, updatedAt: now }).where(eq(project_exports.messages.id, messageId));
|
|
35112
35191
|
return await getMessage(handle, messageId);
|
|
35113
35192
|
}
|
|
35193
|
+
async function setMessageArchived(handle, id, archived) {
|
|
35194
|
+
const existing = await getMessage(handle, id);
|
|
35195
|
+
if (!existing) return null;
|
|
35196
|
+
if (existing.archived === archived) return existing;
|
|
35197
|
+
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);
|
|
35198
|
+
return rows[0] ? rowToMessage(rows[0]) : null;
|
|
35199
|
+
}
|
|
35114
35200
|
async function markAllMessagesAsRead(handle, ownerId, ownerType) {
|
|
35115
35201
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
35116
35202
|
const participantIds = participantIdsForLookup(ownerId, ownerType);
|
|
@@ -35118,7 +35204,8 @@ async function markAllMessagesAsRead(handle, ownerId, ownerType) {
|
|
|
35118
35204
|
and(
|
|
35119
35205
|
inArray(project_exports.messages.toId, participantIds),
|
|
35120
35206
|
eq(project_exports.messages.toType, ownerType),
|
|
35121
|
-
eq(project_exports.messages.read, 0)
|
|
35207
|
+
eq(project_exports.messages.read, 0),
|
|
35208
|
+
archivedCondition()
|
|
35122
35209
|
)
|
|
35123
35210
|
);
|
|
35124
35211
|
const count2 = countRows[0]?.count ?? 0;
|
|
@@ -35126,7 +35213,8 @@ async function markAllMessagesAsRead(handle, ownerId, ownerType) {
|
|
|
35126
35213
|
and(
|
|
35127
35214
|
inArray(project_exports.messages.toId, participantIds),
|
|
35128
35215
|
eq(project_exports.messages.toType, ownerType),
|
|
35129
|
-
eq(project_exports.messages.read, 0)
|
|
35216
|
+
eq(project_exports.messages.read, 0),
|
|
35217
|
+
archivedCondition()
|
|
35130
35218
|
)
|
|
35131
35219
|
);
|
|
35132
35220
|
return count2;
|
|
@@ -35148,19 +35236,22 @@ async function getConversation(handle, participantA, participantB, options) {
|
|
|
35148
35236
|
const aIds = participantIdsForLookup(participantA.id, participantA.type);
|
|
35149
35237
|
const bIds = participantIdsForLookup(participantB.id, participantB.type);
|
|
35150
35238
|
const rows = await handle.select(messageColumns).from(project_exports.messages).where(
|
|
35151
|
-
|
|
35152
|
-
|
|
35153
|
-
|
|
35154
|
-
|
|
35155
|
-
|
|
35156
|
-
|
|
35239
|
+
and(
|
|
35240
|
+
or(
|
|
35241
|
+
and(
|
|
35242
|
+
inArray(project_exports.messages.fromId, aIds),
|
|
35243
|
+
eq(project_exports.messages.fromType, participantA.type),
|
|
35244
|
+
inArray(project_exports.messages.toId, bIds),
|
|
35245
|
+
eq(project_exports.messages.toType, participantB.type)
|
|
35246
|
+
),
|
|
35247
|
+
and(
|
|
35248
|
+
inArray(project_exports.messages.fromId, bIds),
|
|
35249
|
+
eq(project_exports.messages.fromType, participantB.type),
|
|
35250
|
+
inArray(project_exports.messages.toId, aIds),
|
|
35251
|
+
eq(project_exports.messages.toType, participantA.type)
|
|
35252
|
+
)
|
|
35157
35253
|
),
|
|
35158
|
-
|
|
35159
|
-
inArray(project_exports.messages.fromId, bIds),
|
|
35160
|
-
eq(project_exports.messages.fromType, participantB.type),
|
|
35161
|
-
inArray(project_exports.messages.toId, aIds),
|
|
35162
|
-
eq(project_exports.messages.toType, participantA.type)
|
|
35163
|
-
)
|
|
35254
|
+
archivedCondition(options?.archived)
|
|
35164
35255
|
)
|
|
35165
35256
|
).orderBy(desc(project_exports.messages.createdAt)).limit(limit);
|
|
35166
35257
|
return rows.reverse().map((row) => rowToMessage(row));
|
|
@@ -35171,14 +35262,16 @@ async function getMailbox(handle, ownerId, ownerType) {
|
|
|
35171
35262
|
and(
|
|
35172
35263
|
inArray(project_exports.messages.toId, participantIds),
|
|
35173
35264
|
eq(project_exports.messages.toType, ownerType),
|
|
35174
|
-
eq(project_exports.messages.read, 0)
|
|
35265
|
+
eq(project_exports.messages.read, 0),
|
|
35266
|
+
archivedCondition()
|
|
35175
35267
|
)
|
|
35176
35268
|
);
|
|
35177
35269
|
const unreadCount = unreadRows[0]?.count ?? 0;
|
|
35178
35270
|
const lastRows = await handle.select(messageColumns).from(project_exports.messages).where(
|
|
35179
35271
|
and(
|
|
35180
35272
|
inArray(project_exports.messages.toId, participantIds),
|
|
35181
|
-
eq(project_exports.messages.toType, ownerType)
|
|
35273
|
+
eq(project_exports.messages.toType, ownerType),
|
|
35274
|
+
archivedCondition()
|
|
35182
35275
|
)
|
|
35183
35276
|
).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id)).limit(1);
|
|
35184
35277
|
return {
|
|
@@ -35188,15 +35281,16 @@ async function getMailbox(handle, ownerId, ownerType) {
|
|
|
35188
35281
|
lastMessage: lastRows[0] ? rowToMessage(lastRows[0]) : void 0
|
|
35189
35282
|
};
|
|
35190
35283
|
}
|
|
35191
|
-
async function getAllAgentToAgentMessages(handle) {
|
|
35192
|
-
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));
|
|
35284
|
+
async function getAllAgentToAgentMessages(handle, filter) {
|
|
35285
|
+
const rows = await handle.select(messageColumns).from(project_exports.messages).where(and(eq(project_exports.messages.type, "agent-to-agent"), archivedCondition(filter?.archived))).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id));
|
|
35193
35286
|
return rows.map((row) => rowToMessage(row));
|
|
35194
35287
|
}
|
|
35195
35288
|
async function getUnreadAgentToAgentCount(handle) {
|
|
35196
35289
|
const rows = await handle.select({ count: sql`count(*)::int` }).from(project_exports.messages).where(
|
|
35197
35290
|
and(
|
|
35198
35291
|
eq(project_exports.messages.type, "agent-to-agent"),
|
|
35199
|
-
eq(project_exports.messages.read, 0)
|
|
35292
|
+
eq(project_exports.messages.read, 0),
|
|
35293
|
+
archivedCondition()
|
|
35200
35294
|
)
|
|
35201
35295
|
);
|
|
35202
35296
|
return rows[0]?.count ?? 0;
|
|
@@ -35218,6 +35312,7 @@ var init_async_message_store = __esm({
|
|
|
35218
35312
|
content: project_exports.messages.content,
|
|
35219
35313
|
type: project_exports.messages.type,
|
|
35220
35314
|
read: project_exports.messages.read,
|
|
35315
|
+
archived: project_exports.messages.archived,
|
|
35221
35316
|
metadata: project_exports.messages.metadata,
|
|
35222
35317
|
createdAt: project_exports.messages.createdAt,
|
|
35223
35318
|
updatedAt: project_exports.messages.updatedAt
|
|
@@ -35403,12 +35498,12 @@ var init_message_store = __esm({
|
|
|
35403
35498
|
}
|
|
35404
35499
|
const sqliteDb = this.db;
|
|
35405
35500
|
this.stmtInsert = sqliteDb.prepare(`
|
|
35406
|
-
INSERT INTO messages (id, fromId, fromType, toId, toType, content, type, read, metadata, createdAt, updatedAt)
|
|
35407
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35501
|
+
INSERT INTO messages (id, fromId, fromType, toId, toType, content, type, read, archived, metadata, createdAt, updatedAt)
|
|
35502
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35408
35503
|
`);
|
|
35409
35504
|
this.stmtInsertOnce = sqliteDb.prepare(`
|
|
35410
|
-
INSERT OR IGNORE INTO messages (id, fromId, fromType, toId, toType, content, type, read, metadata, createdAt, updatedAt)
|
|
35411
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35505
|
+
INSERT OR IGNORE INTO messages (id, fromId, fromType, toId, toType, content, type, read, archived, metadata, createdAt, updatedAt)
|
|
35506
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
35412
35507
|
`);
|
|
35413
35508
|
this.stmtGetById = sqliteDb.prepare(`
|
|
35414
35509
|
SELECT * FROM messages WHERE id = ?
|
|
@@ -35446,6 +35541,7 @@ var init_message_store = __esm({
|
|
|
35446
35541
|
content: row.content,
|
|
35447
35542
|
type: row.type,
|
|
35448
35543
|
read: row.read === 1,
|
|
35544
|
+
archived: (row.archived ?? 0) === 1,
|
|
35449
35545
|
metadata: fromJson(row.metadata),
|
|
35450
35546
|
createdAt: row.createdAt,
|
|
35451
35547
|
updatedAt: row.updatedAt
|
|
@@ -35479,6 +35575,7 @@ var init_message_store = __esm({
|
|
|
35479
35575
|
content: sanitizeTextValue(input.content),
|
|
35480
35576
|
type: input.type,
|
|
35481
35577
|
read: false,
|
|
35578
|
+
archived: false,
|
|
35482
35579
|
metadata: sanitizeJsonbValue(input.metadata),
|
|
35483
35580
|
createdAt: now,
|
|
35484
35581
|
updatedAt: now
|
|
@@ -35494,6 +35591,7 @@ var init_message_store = __esm({
|
|
|
35494
35591
|
content: message.content,
|
|
35495
35592
|
type: message.type,
|
|
35496
35593
|
read: message.read,
|
|
35594
|
+
archived: message.archived,
|
|
35497
35595
|
metadata: message.metadata ?? null,
|
|
35498
35596
|
createdAt: message.createdAt,
|
|
35499
35597
|
updatedAt: message.updatedAt
|
|
@@ -35508,6 +35606,7 @@ var init_message_store = __esm({
|
|
|
35508
35606
|
message.content,
|
|
35509
35607
|
message.type,
|
|
35510
35608
|
message.read ? 1 : 0,
|
|
35609
|
+
message.archived ? 1 : 0,
|
|
35511
35610
|
toJsonNullable(message.metadata),
|
|
35512
35611
|
message.createdAt,
|
|
35513
35612
|
message.updatedAt
|
|
@@ -35566,6 +35665,7 @@ var init_message_store = __esm({
|
|
|
35566
35665
|
content: sanitizeTextValue(input.content),
|
|
35567
35666
|
type: input.type,
|
|
35568
35667
|
read: false,
|
|
35668
|
+
archived: false,
|
|
35569
35669
|
metadata: sanitizeJsonbValue(input.metadata),
|
|
35570
35670
|
createdAt: now,
|
|
35571
35671
|
updatedAt: now
|
|
@@ -35586,6 +35686,7 @@ var init_message_store = __esm({
|
|
|
35586
35686
|
message.content,
|
|
35587
35687
|
message.type,
|
|
35588
35688
|
0,
|
|
35689
|
+
0,
|
|
35589
35690
|
toJsonNullable(message.metadata),
|
|
35590
35691
|
message.createdAt,
|
|
35591
35692
|
message.updatedAt
|
|
@@ -35717,6 +35818,7 @@ var init_message_store = __esm({
|
|
|
35717
35818
|
whereClauses.push("read = ?");
|
|
35718
35819
|
params.push(filter.read ? 1 : 0);
|
|
35719
35820
|
}
|
|
35821
|
+
whereClauses.push(filter?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)");
|
|
35720
35822
|
const whereSql = whereClauses.join(" AND ");
|
|
35721
35823
|
const limit = filter?.limit ?? 100;
|
|
35722
35824
|
const offset = filter?.offset ?? 0;
|
|
@@ -35767,15 +35869,39 @@ var init_message_store = __esm({
|
|
|
35767
35869
|
const participantIds = this.getParticipantIdsForLookup(ownerId, ownerType);
|
|
35768
35870
|
const toIdPredicate = participantIds.length === 1 ? "toId = ?" : `toId IN (${participantIds.map(() => "?").join(", ")})`;
|
|
35769
35871
|
const unreadRow = this.db.prepare(`
|
|
35770
|
-
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0
|
|
35872
|
+
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35771
35873
|
`).get(...participantIds, ownerType);
|
|
35772
35874
|
const count2 = unreadRow?.count ?? 0;
|
|
35773
35875
|
this.db.prepare(`
|
|
35774
|
-
UPDATE messages SET read = 1, updatedAt = ? WHERE ${toIdPredicate} AND toType = ? AND read = 0
|
|
35876
|
+
UPDATE messages SET read = 1, updatedAt = ? WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35775
35877
|
`).run(now, ...participantIds, ownerType);
|
|
35776
35878
|
this.db.bumpLastModified();
|
|
35777
35879
|
return count2;
|
|
35778
35880
|
}
|
|
35881
|
+
/** Archive a message without destroying its correspondence history. */
|
|
35882
|
+
async archiveMessage(id) {
|
|
35883
|
+
return this.setMessageArchived(id, true);
|
|
35884
|
+
}
|
|
35885
|
+
/** Restore a previously archived message to default mailbox lists. */
|
|
35886
|
+
async unarchiveMessage(id) {
|
|
35887
|
+
return this.setMessageArchived(id, false);
|
|
35888
|
+
}
|
|
35889
|
+
async setMessageArchived(id, archived) {
|
|
35890
|
+
if (this.asyncLayer) {
|
|
35891
|
+
const updated2 = await setMessageArchived(this.asyncLayer.db, id, archived);
|
|
35892
|
+
if (!updated2) throw new Error(`Message ${id} not found`);
|
|
35893
|
+
this.emit(archived ? "message:archived" : "message:unarchived", updated2);
|
|
35894
|
+
return updated2;
|
|
35895
|
+
}
|
|
35896
|
+
const existing = await this.getMessage(id);
|
|
35897
|
+
if (!existing) throw new Error(`Message ${id} not found`);
|
|
35898
|
+
if (existing.archived === archived) return existing;
|
|
35899
|
+
this.db.prepare("UPDATE messages SET archived = ?, updatedAt = ? WHERE id = ?").run(archived ? 1 : 0, (/* @__PURE__ */ new Date()).toISOString(), id);
|
|
35900
|
+
this.db.bumpLastModified();
|
|
35901
|
+
const updated = await this.getMessage(id);
|
|
35902
|
+
this.emit(archived ? "message:archived" : "message:unarchived", updated);
|
|
35903
|
+
return updated;
|
|
35904
|
+
}
|
|
35779
35905
|
/**
|
|
35780
35906
|
* Delete a message by ID.
|
|
35781
35907
|
* @param id - The message ID
|
|
@@ -35866,7 +35992,7 @@ var init_message_store = __esm({
|
|
|
35866
35992
|
(${participantAFromPredicate} AND fromType = ? AND ${participantBToPredicate} AND toType = ?)
|
|
35867
35993
|
OR
|
|
35868
35994
|
(${participantBFromPredicate} AND fromType = ? AND ${participantAToPredicate} AND toType = ?)
|
|
35869
|
-
)
|
|
35995
|
+
) AND ${options?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)"}
|
|
35870
35996
|
ORDER BY createdAt DESC
|
|
35871
35997
|
LIMIT ?
|
|
35872
35998
|
`).all(
|
|
@@ -35901,11 +36027,11 @@ var init_message_store = __esm({
|
|
|
35901
36027
|
const participantIds = this.getParticipantIdsForLookup(ownerId, ownerType);
|
|
35902
36028
|
const toIdPredicate = participantIds.length === 1 ? "toId = ?" : `toId IN (${participantIds.map(() => "?").join(", ")})`;
|
|
35903
36029
|
const unreadRow = this.db.prepare(`
|
|
35904
|
-
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0
|
|
36030
|
+
SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35905
36031
|
`).get(...participantIds, ownerType);
|
|
35906
36032
|
const unreadCount = unreadRow?.count ?? 0;
|
|
35907
36033
|
const lastRow = this.db.prepare(`
|
|
35908
|
-
SELECT * FROM messages WHERE ${toIdPredicate} AND toType = ? ORDER BY createdAt DESC, rowid DESC LIMIT 1
|
|
36034
|
+
SELECT * FROM messages WHERE ${toIdPredicate} AND toType = ? AND (archived = 0 OR archived IS NULL) ORDER BY createdAt DESC, rowid DESC LIMIT 1
|
|
35909
36035
|
`).get(...participantIds, ownerType);
|
|
35910
36036
|
const lastMessage = lastRow ? this.rowToMessage(lastRow) : void 0;
|
|
35911
36037
|
return {
|
|
@@ -35919,13 +36045,13 @@ var init_message_store = __esm({
|
|
|
35919
36045
|
* Get all agent-to-agent messages across all agents.
|
|
35920
36046
|
* @returns Array of messages (newest first)
|
|
35921
36047
|
*/
|
|
35922
|
-
async getAllAgentToAgentMessages() {
|
|
36048
|
+
async getAllAgentToAgentMessages(filter) {
|
|
35923
36049
|
if (this.asyncLayer) {
|
|
35924
|
-
return getAllAgentToAgentMessages(this.asyncLayer.db);
|
|
36050
|
+
return getAllAgentToAgentMessages(this.asyncLayer.db, filter);
|
|
35925
36051
|
}
|
|
35926
36052
|
const rows = this.db.prepare(`
|
|
35927
36053
|
SELECT * FROM messages
|
|
35928
|
-
WHERE type = ?
|
|
36054
|
+
WHERE type = ? AND ${filter?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)"}
|
|
35929
36055
|
ORDER BY createdAt DESC, rowid DESC
|
|
35930
36056
|
`).all("agent-to-agent");
|
|
35931
36057
|
return rows.map((row) => this.rowToMessage(row));
|
|
@@ -35939,7 +36065,7 @@ var init_message_store = __esm({
|
|
|
35939
36065
|
}
|
|
35940
36066
|
const row = this.db.prepare(`
|
|
35941
36067
|
SELECT COUNT(*) as count FROM messages
|
|
35942
|
-
WHERE type = ? AND read = 0
|
|
36068
|
+
WHERE type = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
|
|
35943
36069
|
`).get("agent-to-agent");
|
|
35944
36070
|
return row?.count ?? 0;
|
|
35945
36071
|
}
|
|
@@ -36038,6 +36164,7 @@ async function createApprovalRequest(layer, input) {
|
|
|
36038
36164
|
};
|
|
36039
36165
|
await layer.transactionImmediate(async (tx) => {
|
|
36040
36166
|
await tx.insert(project_exports.approvalRequests).values({
|
|
36167
|
+
...layer.projectId?.trim() ? { projectId: layer.projectId } : {},
|
|
36041
36168
|
id: request.id,
|
|
36042
36169
|
status: request.status,
|
|
36043
36170
|
requesterActorId: request.requester.actorId,
|
|
@@ -36061,12 +36188,12 @@ async function createApprovalRequest(layer, input) {
|
|
|
36061
36188
|
});
|
|
36062
36189
|
return request;
|
|
36063
36190
|
}
|
|
36064
|
-
async function getApprovalRequest(handle, id) {
|
|
36065
|
-
const rows = await handle.select().from(project_exports.approvalRequests).where(eq(project_exports.approvalRequests.id, id));
|
|
36191
|
+
async function getApprovalRequest(handle, id, projectId2) {
|
|
36192
|
+
const rows = await handle.select().from(project_exports.approvalRequests).where(and(eq(project_exports.approvalRequests.id, id), projectScopeFor(project_exports.approvalRequests.projectId, projectId2)));
|
|
36066
36193
|
return rows[0] ? rowToRequest(rows[0]) : null;
|
|
36067
36194
|
}
|
|
36068
|
-
async function listApprovalRequests(handle, input = {}) {
|
|
36069
|
-
const conditions = [];
|
|
36195
|
+
async function listApprovalRequests(handle, input = {}, projectId2) {
|
|
36196
|
+
const conditions = [projectScopeFor(project_exports.approvalRequests.projectId, projectId2)];
|
|
36070
36197
|
if (input.status) conditions.push(eq(project_exports.approvalRequests.status, input.status));
|
|
36071
36198
|
if (input.requesterActorId) conditions.push(eq(project_exports.approvalRequests.requesterActorId, input.requesterActorId));
|
|
36072
36199
|
if (input.taskId) conditions.push(eq(project_exports.approvalRequests.taskId, input.taskId));
|
|
@@ -36080,7 +36207,7 @@ async function listApprovalRequests(handle, input = {}) {
|
|
|
36080
36207
|
async function decideApprovalRequest(layer, requestId, status, input) {
|
|
36081
36208
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36082
36209
|
return layer.transactionImmediate(async (tx) => {
|
|
36083
|
-
const existing = await getApprovalRequest(tx, requestId);
|
|
36210
|
+
const existing = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36084
36211
|
if (!existing) throw new Error(`Approval request ${requestId} not found`);
|
|
36085
36212
|
if (!isValidApprovalRequestTransition(existing.status, status)) {
|
|
36086
36213
|
throw new Error(`Invalid approval request transition: ${existing.status} -> ${status}`);
|
|
@@ -36091,23 +36218,24 @@ async function decideApprovalRequest(layer, requestId, status, input) {
|
|
|
36091
36218
|
const updatedRows = await tx.update(project_exports.approvalRequests).set({ status, decidedAt: now, updatedAt: now }).where(
|
|
36092
36219
|
and(
|
|
36093
36220
|
eq(project_exports.approvalRequests.id, requestId),
|
|
36094
|
-
eq(project_exports.approvalRequests.status, existing.status)
|
|
36221
|
+
eq(project_exports.approvalRequests.status, existing.status),
|
|
36222
|
+
projectScopeFor(project_exports.approvalRequests.projectId, layer.projectId)
|
|
36095
36223
|
)
|
|
36096
36224
|
).returning({ id: project_exports.approvalRequests.id });
|
|
36097
36225
|
if (updatedRows.length === 0) {
|
|
36098
|
-
const raced = await getApprovalRequest(tx, requestId);
|
|
36226
|
+
const raced = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36099
36227
|
throw new Error(
|
|
36100
36228
|
`Invalid approval request transition: ${raced?.status ?? existing.status} -> ${status}`
|
|
36101
36229
|
);
|
|
36102
36230
|
}
|
|
36103
36231
|
await appendAuditEvent(tx, layer.projectId ?? "", requestId, status, input.actor, now, input.note);
|
|
36104
|
-
return await getApprovalRequest(tx, requestId);
|
|
36232
|
+
return await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36105
36233
|
});
|
|
36106
36234
|
}
|
|
36107
36235
|
async function markApprovalRequestCompleted(layer, requestId, input) {
|
|
36108
36236
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36109
36237
|
return layer.transactionImmediate(async (tx) => {
|
|
36110
|
-
const existing = await getApprovalRequest(tx, requestId);
|
|
36238
|
+
const existing = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36111
36239
|
if (!existing) throw new Error(`Approval request ${requestId} not found`);
|
|
36112
36240
|
if (!isValidApprovalRequestTransition(existing.status, "completed")) {
|
|
36113
36241
|
throw new Error(`Invalid approval request transition: ${existing.status} -> completed`);
|
|
@@ -36121,21 +36249,22 @@ async function markApprovalRequestCompleted(layer, requestId, input) {
|
|
|
36121
36249
|
const updatedRows = await tx.update(project_exports.approvalRequests).set({ status: "completed", completedAt: now, updatedAt: now }).where(
|
|
36122
36250
|
and(
|
|
36123
36251
|
eq(project_exports.approvalRequests.id, requestId),
|
|
36124
|
-
eq(project_exports.approvalRequests.status, existing.status)
|
|
36252
|
+
eq(project_exports.approvalRequests.status, existing.status),
|
|
36253
|
+
projectScopeFor(project_exports.approvalRequests.projectId, layer.projectId)
|
|
36125
36254
|
)
|
|
36126
36255
|
).returning({ id: project_exports.approvalRequests.id });
|
|
36127
36256
|
if (updatedRows.length === 0) {
|
|
36128
|
-
const raced = await getApprovalRequest(tx, requestId);
|
|
36257
|
+
const raced = await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36129
36258
|
throw new Error(
|
|
36130
36259
|
`Invalid approval request transition: ${raced?.status ?? existing.status} -> completed`
|
|
36131
36260
|
);
|
|
36132
36261
|
}
|
|
36133
36262
|
await appendAuditEvent(tx, layer.projectId ?? "", requestId, "completed", input.actor, now, input.note);
|
|
36134
|
-
return await getApprovalRequest(tx, requestId);
|
|
36263
|
+
return await getApprovalRequest(tx, requestId, layer.projectId);
|
|
36135
36264
|
});
|
|
36136
36265
|
}
|
|
36137
|
-
async function getApprovalAuditHistory(handle, requestId) {
|
|
36138
|
-
const rows = await handle.select().from(project_exports.approvalRequestAuditEvents).where(eq(project_exports.approvalRequestAuditEvents.requestId, requestId)).orderBy(
|
|
36266
|
+
async function getApprovalAuditHistory(handle, requestId, projectId2) {
|
|
36267
|
+
const rows = await handle.select().from(project_exports.approvalRequestAuditEvents).where(and(eq(project_exports.approvalRequestAuditEvents.requestId, requestId), projectScopeFor(project_exports.approvalRequestAuditEvents.projectId, projectId2))).orderBy(
|
|
36139
36268
|
sql`${project_exports.approvalRequestAuditEvents.createdAt} ASC, ${project_exports.approvalRequestAuditEvents.id} ASC`
|
|
36140
36269
|
);
|
|
36141
36270
|
return rows.map((row) => rowToAuditEvent(row));
|
|
@@ -36145,6 +36274,7 @@ var init_async_approval_request_store = __esm({
|
|
|
36145
36274
|
"use strict";
|
|
36146
36275
|
init_drizzle_orm();
|
|
36147
36276
|
init_schema2();
|
|
36277
|
+
init_data_layer();
|
|
36148
36278
|
init_agents();
|
|
36149
36279
|
init_types();
|
|
36150
36280
|
}
|
|
@@ -36158,6 +36288,7 @@ var init_approval_request_store = __esm({
|
|
|
36158
36288
|
"use strict";
|
|
36159
36289
|
init_drizzle_orm();
|
|
36160
36290
|
init_db2();
|
|
36291
|
+
init_data_layer();
|
|
36161
36292
|
init_async_approval_request_store();
|
|
36162
36293
|
init_schema2();
|
|
36163
36294
|
init_async_agent_activity();
|
|
@@ -36286,23 +36417,26 @@ var init_approval_request_store = __esm({
|
|
|
36286
36417
|
return created;
|
|
36287
36418
|
}
|
|
36288
36419
|
async get(id) {
|
|
36289
|
-
return getApprovalRequest(this.asyncLayer.db, id);
|
|
36420
|
+
return getApprovalRequest(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
36290
36421
|
}
|
|
36291
36422
|
async list(input = {}) {
|
|
36292
|
-
return listApprovalRequests(this.asyncLayer.db, input);
|
|
36423
|
+
return listApprovalRequests(this.asyncLayer.db, input, this.asyncLayer.projectId);
|
|
36293
36424
|
}
|
|
36294
36425
|
async getPendingCountsByActor() {
|
|
36295
36426
|
const table = project_exports.approvalRequests;
|
|
36296
36427
|
const rows = await this.asyncLayer.db.select({
|
|
36297
36428
|
actorId: table.requesterActorId,
|
|
36298
36429
|
requestCount: count()
|
|
36299
|
-
}).from(table).where(eq(table.status, "pending")).groupBy(table.requesterActorId);
|
|
36430
|
+
}).from(table).where(and(eq(table.status, "pending"), projectScopeFor(table.projectId, this.asyncLayer.projectId))).groupBy(table.requesterActorId);
|
|
36300
36431
|
return new Map(rows.map((row) => [row.actorId, Number(row.requestCount)]));
|
|
36301
36432
|
}
|
|
36302
36433
|
async findLatestByDedupeKey(input) {
|
|
36303
36434
|
if (this.backendMode) {
|
|
36304
36435
|
const table = project_exports.approvalRequests;
|
|
36305
|
-
const conditions = [
|
|
36436
|
+
const conditions = [
|
|
36437
|
+
eq(table.requesterActorId, input.requesterActorId),
|
|
36438
|
+
projectScopeFor(table.projectId, this.asyncLayer.projectId)
|
|
36439
|
+
];
|
|
36306
36440
|
if (input.taskId !== void 0) {
|
|
36307
36441
|
conditions.push(eq(table.taskId, input.taskId));
|
|
36308
36442
|
}
|
|
@@ -36341,7 +36475,7 @@ var init_approval_request_store = __esm({
|
|
|
36341
36475
|
return markApprovalRequestCompleted(this.asyncLayer, requestId, input);
|
|
36342
36476
|
}
|
|
36343
36477
|
async getAuditHistory(requestId) {
|
|
36344
|
-
return getApprovalAuditHistory(this.asyncLayer.db, requestId);
|
|
36478
|
+
return getApprovalAuditHistory(this.asyncLayer.db, requestId, this.asyncLayer.projectId);
|
|
36345
36479
|
}
|
|
36346
36480
|
};
|
|
36347
36481
|
}
|
|
@@ -40527,6 +40661,8 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
40527
40661
|
const agentRatingProjectIsolationAlreadyApplied = applied.includes(AGENT_RATING_PROJECT_ISOLATION_VERSION);
|
|
40528
40662
|
const agentRatingsProjectPartitionAlreadyApplied = applied.includes(AGENT_RATINGS_PROJECT_PARTITION_VERSION);
|
|
40529
40663
|
const projectOwnershipDeclarationDriftAlreadyApplied = applied.includes(PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION);
|
|
40664
|
+
const projectOwnershipDefaultReconciliationAlreadyApplied = applied.includes(PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION);
|
|
40665
|
+
const messageArchiveSchemaAlreadyApplied = applied.includes(MESSAGE_ARCHIVE_SCHEMA_VERSION);
|
|
40530
40666
|
assertBinaryNotOlderThanDatabase(applied);
|
|
40531
40667
|
let schemaChanged = false;
|
|
40532
40668
|
if (!baselineAlreadyApplied) {
|
|
@@ -41010,17 +41146,29 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
41010
41146
|
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
41011
41147
|
schemaChanged = true;
|
|
41012
41148
|
}
|
|
41149
|
+
if (!projectOwnershipDefaultReconciliationAlreadyApplied) {
|
|
41150
|
+
const migrationSql = await readFile4(PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH, "utf8");
|
|
41151
|
+
await tx.execute(sql.raw(migrationSql));
|
|
41152
|
+
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
41153
|
+
schemaChanged = true;
|
|
41154
|
+
}
|
|
41155
|
+
if (!messageArchiveSchemaAlreadyApplied) {
|
|
41156
|
+
const migrationSql = await readFile4(MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH, "utf8");
|
|
41157
|
+
await tx.execute(sql.raw(migrationSql));
|
|
41158
|
+
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${MESSAGE_ARCHIVE_SCHEMA_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
41159
|
+
schemaChanged = true;
|
|
41160
|
+
}
|
|
41013
41161
|
return { applied: schemaChanged, pluginHooksRun: pluginHooks.length };
|
|
41014
41162
|
});
|
|
41015
41163
|
}
|
|
41016
|
-
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;
|
|
41164
|
+
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;
|
|
41017
41165
|
var init_schema_applier = __esm({
|
|
41018
41166
|
"../core/src/postgres/schema-applier.ts"() {
|
|
41019
41167
|
"use strict";
|
|
41020
41168
|
init_drizzle_orm();
|
|
41021
41169
|
init_plugin_schema_hook();
|
|
41022
41170
|
init_advisory_locks();
|
|
41023
|
-
SCHEMA_BASELINE_VERSION = "
|
|
41171
|
+
SCHEMA_BASELINE_VERSION = "0058";
|
|
41024
41172
|
TASK_DECLARED_SYMBOLS_VERSION = "0028";
|
|
41025
41173
|
INITIAL_SCHEMA_VERSION = "0000";
|
|
41026
41174
|
AUTOMATION_ISOLATION_SCHEMA_VERSION = "0001";
|
|
@@ -41077,6 +41225,8 @@ var init_schema_applier = __esm({
|
|
|
41077
41225
|
AGENT_RATING_PROJECT_ISOLATION_VERSION = "0054";
|
|
41078
41226
|
AGENT_RATINGS_PROJECT_PARTITION_VERSION = "0055";
|
|
41079
41227
|
PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION = "0056";
|
|
41228
|
+
PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION = "0057";
|
|
41229
|
+
MESSAGE_ARCHIVE_SCHEMA_VERSION = "0058";
|
|
41080
41230
|
LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION = "fusion_mark_legacy_adoption_drained";
|
|
41081
41231
|
StaleBinarySchemaError = class extends Error {
|
|
41082
41232
|
constructor(databaseVersion, binaryVersion) {
|
|
@@ -41213,6 +41363,8 @@ var init_schema_applier = __esm({
|
|
|
41213
41363
|
AGENT_RATING_PROJECT_ISOLATION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0054_fn_8957_agent_rating_project_isolation.sql");
|
|
41214
41364
|
AGENT_RATINGS_PROJECT_PARTITION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0055_fn_8988_agent_ratings_project_partition.sql");
|
|
41215
41365
|
PROJECT_OWNERSHIP_DECLARATION_DRIFT_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0056_fn_8997_project_ownership_declaration_drift.sql");
|
|
41366
|
+
PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0057_fn_9004_project_ownership_default_reconciliation.sql");
|
|
41367
|
+
MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0058_fn_9014_message_archive.sql");
|
|
41216
41368
|
}
|
|
41217
41369
|
});
|
|
41218
41370
|
|
|
@@ -68568,20 +68720,32 @@ async function replaceActiveTaskWorkflowContinuation(layer, input) {
|
|
|
68568
68720
|
return upsertWorkflowWorkItem(layer, input, tx);
|
|
68569
68721
|
}));
|
|
68570
68722
|
}
|
|
68571
|
-
async function seedStrandedPlanReviewContinuation(layer, input) {
|
|
68723
|
+
async function seedStrandedPlanReviewContinuation(layer, input, options = {}) {
|
|
68572
68724
|
return layer.transactionImmediate(async (tx) => withTaskWorkflowSerialization(tx, layer.projectId, input.taskId, async () => {
|
|
68573
68725
|
const active2 = await tx.select({ id: project_exports.workflowWorkItems.id }).from(project_exports.workflowWorkItems).where(and(
|
|
68574
68726
|
projectScopeFor(project_exports.workflowWorkItems.projectId, layer.projectId),
|
|
68575
68727
|
eq(project_exports.workflowWorkItems.taskId, input.taskId),
|
|
68576
68728
|
inArray(project_exports.workflowWorkItems.state, [...ACTIVE_WORKFLOW_WORK_ITEM_STATES])
|
|
68577
68729
|
));
|
|
68578
|
-
|
|
68730
|
+
const blocking = options.retirePredecessorId ? active2.filter((row) => row.id !== options.retirePredecessorId) : active2;
|
|
68731
|
+
if (blocking.length > 0) return { seeded: false, reason: "active-continuation" };
|
|
68579
68732
|
const taskRows = await tx.select({ workflowStepResults: project_exports.tasks.workflowStepResults }).from(project_exports.tasks).where(and(
|
|
68580
68733
|
projectScopeFor(project_exports.tasks.projectId, layer.projectId),
|
|
68581
68734
|
eq(project_exports.tasks.id, input.taskId)
|
|
68582
68735
|
)).limit(1);
|
|
68583
68736
|
const results = taskRows[0]?.workflowStepResults;
|
|
68584
68737
|
if (results?.some(isPlanReviewSatisfied)) return { seeded: false, reason: "plan-review-passed" };
|
|
68738
|
+
if (options.retirePredecessorId) {
|
|
68739
|
+
const predRows = await tx.select().from(project_exports.workflowWorkItems).where(and(
|
|
68740
|
+
projectScopeFor(project_exports.workflowWorkItems.projectId, layer.projectId),
|
|
68741
|
+
eq(project_exports.workflowWorkItems.id, options.retirePredecessorId),
|
|
68742
|
+
eq(project_exports.workflowWorkItems.taskId, input.taskId)
|
|
68743
|
+
)).limit(1);
|
|
68744
|
+
const pred = predRows[0];
|
|
68745
|
+
if (pred && !isTerminalWorkflowWorkItemState(normalizeWorkflowWorkItemState(pred.state))) {
|
|
68746
|
+
await transitionWorkflowWorkItem(layer, pred.id, "succeeded", { leaseOwner: null, leaseExpiresAt: null, lastError: null }, tx);
|
|
68747
|
+
}
|
|
68748
|
+
}
|
|
68585
68749
|
const item = await upsertWorkflowWorkItem(layer, input, tx);
|
|
68586
68750
|
return { seeded: true, workItemId: item.id };
|
|
68587
68751
|
}));
|
|
@@ -68745,8 +68909,10 @@ function safeJsonParse(value) {
|
|
|
68745
68909
|
return null;
|
|
68746
68910
|
}
|
|
68747
68911
|
}
|
|
68748
|
-
async function queryRunAuditEvents(db, filter = {}) {
|
|
68749
|
-
const conditions = []
|
|
68912
|
+
async function queryRunAuditEvents(db, filter = {}, projectId2) {
|
|
68913
|
+
const conditions = [projectScopeFor(project_exports.runAuditEvents.projectId, projectId2)].filter(
|
|
68914
|
+
(condition) => condition !== void 0
|
|
68915
|
+
);
|
|
68750
68916
|
if (filter.runId) {
|
|
68751
68917
|
conditions.push(eq(project_exports.runAuditEvents.runId, filter.runId));
|
|
68752
68918
|
}
|
|
@@ -68892,6 +69058,7 @@ var init_async_audit = __esm({
|
|
|
68892
69058
|
init_drizzle_orm();
|
|
68893
69059
|
init_schema2();
|
|
68894
69060
|
init_data_layer();
|
|
69061
|
+
init_data_layer();
|
|
68895
69062
|
LEGACY_REVIEW_LANES3 = ["in-review"];
|
|
68896
69063
|
LEGACY_COMPLETE_LANES = ["done"];
|
|
68897
69064
|
}
|
|
@@ -69281,7 +69448,10 @@ async function insertArtifactRow(layer, input, stored, archivedColumns) {
|
|
|
69281
69448
|
createdAt: now,
|
|
69282
69449
|
updatedAt: now
|
|
69283
69450
|
});
|
|
69284
|
-
const rows = await tx.select().from(project_exports.artifacts).where(
|
|
69451
|
+
const rows = await tx.select().from(project_exports.artifacts).where(and(
|
|
69452
|
+
eq(project_exports.artifacts.id, id),
|
|
69453
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
69454
|
+
)).limit(1);
|
|
69285
69455
|
const row = rows[0];
|
|
69286
69456
|
if (!row) throw new Error(`Failed to register artifact ${id}`);
|
|
69287
69457
|
return rowToArtifact2(row);
|
|
@@ -69289,7 +69459,7 @@ async function insertArtifactRow(layer, input, stored, archivedColumns) {
|
|
|
69289
69459
|
}
|
|
69290
69460
|
async function updateArtifactRow(layer, id, updates, archivedColumns) {
|
|
69291
69461
|
return layer.transactionImmediate(async (tx) => {
|
|
69292
|
-
const existing = await getArtifact(tx, id);
|
|
69462
|
+
const existing = await getArtifact(tx, id, layer.projectId);
|
|
69293
69463
|
if (!existing) {
|
|
69294
69464
|
throw new Error(`Artifact ${id} not found`);
|
|
69295
69465
|
}
|
|
@@ -69309,29 +69479,38 @@ async function updateArtifactRow(layer, id, updates, archivedColumns) {
|
|
|
69309
69479
|
description: updates.description !== void 0 ? updates.description : existing.description ?? null,
|
|
69310
69480
|
content: updates.content !== void 0 ? updates.content : existing.content ?? null,
|
|
69311
69481
|
updatedAt: now
|
|
69312
|
-
}).where(
|
|
69313
|
-
|
|
69482
|
+
}).where(and(
|
|
69483
|
+
eq(project_exports.artifacts.id, id),
|
|
69484
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
69485
|
+
));
|
|
69486
|
+
const updated = await getArtifact(tx, id, layer.projectId);
|
|
69314
69487
|
if (!updated) {
|
|
69315
69488
|
throw new Error(`Failed to update artifact ${id}`);
|
|
69316
69489
|
}
|
|
69317
69490
|
return updated;
|
|
69318
69491
|
});
|
|
69319
69492
|
}
|
|
69320
|
-
async function getArtifact(db, id) {
|
|
69321
|
-
const rows = await db.select().from(project_exports.artifacts).where(
|
|
69493
|
+
async function getArtifact(db, id, projectId2) {
|
|
69494
|
+
const rows = await db.select().from(project_exports.artifacts).where(and(
|
|
69495
|
+
eq(project_exports.artifacts.id, id),
|
|
69496
|
+
projectScopeFor(project_exports.artifacts.projectId, projectId2)
|
|
69497
|
+
)).limit(1);
|
|
69322
69498
|
const row = rows[0];
|
|
69323
69499
|
return row ? rowToArtifact2(row) : null;
|
|
69324
69500
|
}
|
|
69325
69501
|
async function getArtifacts(db, taskId, projectId2, archivedColumns) {
|
|
69326
69502
|
const column = await getLiveTaskColumn(db, taskId, projectId2, archivedColumns);
|
|
69327
69503
|
if (column === null || column === "archived") return [];
|
|
69328
|
-
const rows = await db.select().from(project_exports.artifacts).where(
|
|
69504
|
+
const rows = await db.select().from(project_exports.artifacts).where(and(
|
|
69505
|
+
eq(project_exports.artifacts.taskId, taskId),
|
|
69506
|
+
projectScopeFor(project_exports.artifacts.projectId, projectId2)
|
|
69507
|
+
)).orderBy(desc(project_exports.artifacts.createdAt));
|
|
69329
69508
|
return rows.map((row) => rowToArtifact2(row));
|
|
69330
69509
|
}
|
|
69331
|
-
async function listArtifacts(db, options) {
|
|
69510
|
+
async function listArtifacts(db, options, projectId2) {
|
|
69332
69511
|
const limit = Math.min(Math.max(1, options?.limit ?? 200), 1e3);
|
|
69333
69512
|
const offset = Math.max(0, options?.offset ?? 0);
|
|
69334
|
-
const conditions = [];
|
|
69513
|
+
const conditions = [projectScopeFor(project_exports.artifacts.projectId, projectId2)];
|
|
69335
69514
|
if (options?.type) {
|
|
69336
69515
|
conditions.push(eq(project_exports.artifacts.type, options.type));
|
|
69337
69516
|
}
|
|
@@ -69370,7 +69549,10 @@ async function listArtifacts(db, options) {
|
|
|
69370
69549
|
taskColumn: project_exports.tasks.column
|
|
69371
69550
|
}).from(project_exports.artifacts).leftJoin(
|
|
69372
69551
|
project_exports.tasks,
|
|
69373
|
-
|
|
69552
|
+
and(
|
|
69553
|
+
eq(project_exports.artifacts.taskId, project_exports.tasks.id),
|
|
69554
|
+
eq(project_exports.artifacts.projectId, project_exports.tasks.projectId)
|
|
69555
|
+
)
|
|
69374
69556
|
).where(and(...conditions)).orderBy(desc(project_exports.artifacts.createdAt)).limit(limit).offset(offset);
|
|
69375
69557
|
return rows.map((row) => {
|
|
69376
69558
|
const artifact = rowToArtifact2(row);
|
|
@@ -70535,7 +70717,7 @@ function rowToBranchGroup2(row) {
|
|
|
70535
70717
|
closedAt: row.closedAt ?? void 0
|
|
70536
70718
|
};
|
|
70537
70719
|
}
|
|
70538
|
-
async function createBranchGroup(db, input) {
|
|
70720
|
+
async function createBranchGroup(db, input, projectId2) {
|
|
70539
70721
|
validateBranchGroupBranchName(input.branchName);
|
|
70540
70722
|
const now = Date.now();
|
|
70541
70723
|
const id = generateBranchGroupId2();
|
|
@@ -70554,44 +70736,52 @@ async function createBranchGroup(db, input) {
|
|
|
70554
70736
|
updatedAt: now,
|
|
70555
70737
|
closedAt: input.closedAt ?? null
|
|
70556
70738
|
});
|
|
70557
|
-
const created = await getBranchGroup(db, id);
|
|
70739
|
+
const created = await getBranchGroup(db, id, projectId2);
|
|
70558
70740
|
if (!created) throw new Error(`Failed to read branch group ${id} after create`);
|
|
70559
70741
|
return created;
|
|
70560
70742
|
}
|
|
70561
|
-
async function getBranchGroup(db, id) {
|
|
70562
|
-
const rows = await db.select().from(project_exports.branchGroups).where(
|
|
70743
|
+
async function getBranchGroup(db, id, projectId2) {
|
|
70744
|
+
const rows = await db.select().from(project_exports.branchGroups).where(and(
|
|
70745
|
+
eq(project_exports.branchGroups.id, id),
|
|
70746
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70747
|
+
)).limit(1);
|
|
70563
70748
|
const row = rows[0];
|
|
70564
70749
|
return row ? rowToBranchGroup2(row) : null;
|
|
70565
70750
|
}
|
|
70566
|
-
async function getBranchGroupBySource(db, sourceType, sourceId) {
|
|
70751
|
+
async function getBranchGroupBySource(db, sourceType, sourceId, projectId2) {
|
|
70567
70752
|
const rows = await db.select().from(project_exports.branchGroups).where(
|
|
70568
70753
|
and(
|
|
70569
70754
|
eq(project_exports.branchGroups.sourceType, sourceType),
|
|
70570
|
-
eq(project_exports.branchGroups.sourceId, sourceId)
|
|
70755
|
+
eq(project_exports.branchGroups.sourceId, sourceId),
|
|
70756
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70571
70757
|
)
|
|
70572
70758
|
).limit(1);
|
|
70573
70759
|
const row = rows[0];
|
|
70574
70760
|
return row ? rowToBranchGroup2(row) : null;
|
|
70575
70761
|
}
|
|
70576
|
-
async function getBranchGroupByBranchName(db, branchName) {
|
|
70577
|
-
const rows = await db.select().from(project_exports.branchGroups).where(
|
|
70762
|
+
async function getBranchGroupByBranchName(db, branchName, projectId2) {
|
|
70763
|
+
const rows = await db.select().from(project_exports.branchGroups).where(and(
|
|
70764
|
+
eq(project_exports.branchGroups.branchName, branchName),
|
|
70765
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70766
|
+
)).orderBy(sql`${project_exports.branchGroups.createdAt} DESC`).limit(1);
|
|
70578
70767
|
const row = rows[0];
|
|
70579
70768
|
return row ? rowToBranchGroup2(row) : null;
|
|
70580
70769
|
}
|
|
70581
|
-
async function ensureBranchGroupForSource(db, sourceType, sourceId, init) {
|
|
70582
|
-
const existing = await getBranchGroupBySource(db, sourceType, sourceId);
|
|
70770
|
+
async function ensureBranchGroupForSource(db, sourceType, sourceId, init, projectId2) {
|
|
70771
|
+
const existing = await getBranchGroupBySource(db, sourceType, sourceId, projectId2);
|
|
70583
70772
|
if (existing) return existing;
|
|
70584
|
-
const existingByBranch = await getBranchGroupByBranchName(db, init.branchName);
|
|
70773
|
+
const existingByBranch = await getBranchGroupByBranchName(db, init.branchName, projectId2);
|
|
70585
70774
|
if (existingByBranch) return existingByBranch;
|
|
70586
|
-
return createBranchGroup(db, { sourceType, sourceId, ...init });
|
|
70775
|
+
return createBranchGroup(db, { sourceType, sourceId, ...init }, projectId2);
|
|
70587
70776
|
}
|
|
70588
|
-
async function listBranchGroups(db, options) {
|
|
70589
|
-
const
|
|
70590
|
-
|
|
70777
|
+
async function listBranchGroups(db, options, projectId2) {
|
|
70778
|
+
const conditions = [projectScopeFor(project_exports.branchGroups.projectId, projectId2)];
|
|
70779
|
+
if (options?.status) conditions.push(eq(project_exports.branchGroups.status, options.status));
|
|
70780
|
+
const rows = await db.select().from(project_exports.branchGroups).where(and(...conditions)).orderBy(asc(project_exports.branchGroups.createdAt));
|
|
70591
70781
|
return rows.map((row) => rowToBranchGroup2(row));
|
|
70592
70782
|
}
|
|
70593
|
-
async function updateBranchGroup(db, id, patch) {
|
|
70594
|
-
const current = await getBranchGroup(db, id);
|
|
70783
|
+
async function updateBranchGroup(db, id, patch, projectId2) {
|
|
70784
|
+
const current = await getBranchGroup(db, id, projectId2);
|
|
70595
70785
|
if (!current) throw new Error(`Branch group ${id} not found`);
|
|
70596
70786
|
if (patch.branchName !== void 0) {
|
|
70597
70787
|
validateBranchGroupBranchName(patch.branchName);
|
|
@@ -70610,8 +70800,11 @@ async function updateBranchGroup(db, id, patch) {
|
|
|
70610
70800
|
status: nextStatus,
|
|
70611
70801
|
updatedAt: now,
|
|
70612
70802
|
closedAt: nextClosedAt
|
|
70613
|
-
}).where(
|
|
70614
|
-
|
|
70803
|
+
}).where(and(
|
|
70804
|
+
eq(project_exports.branchGroups.id, id),
|
|
70805
|
+
projectScopeFor(project_exports.branchGroups.projectId, projectId2)
|
|
70806
|
+
));
|
|
70807
|
+
const updated = await getBranchGroup(db, id, projectId2);
|
|
70615
70808
|
if (!updated) throw new Error(`Branch group ${id} disappeared after update`);
|
|
70616
70809
|
return updated;
|
|
70617
70810
|
}
|
|
@@ -70768,6 +70961,7 @@ var init_async_branch_groups = __esm({
|
|
|
70768
70961
|
"use strict";
|
|
70769
70962
|
init_drizzle_orm();
|
|
70770
70963
|
init_schema2();
|
|
70964
|
+
init_data_layer();
|
|
70771
70965
|
init_branch_assignment();
|
|
70772
70966
|
}
|
|
70773
70967
|
});
|
|
@@ -80581,6 +80775,9 @@ import { randomUUID as randomUUID21 } from "node:crypto";
|
|
|
80581
80775
|
function tableForScope(scope) {
|
|
80582
80776
|
return scope === "project" ? project_exports.secrets : central_exports.secretsGlobal;
|
|
80583
80777
|
}
|
|
80778
|
+
function scopeForSecretTable(scope, table, projectId2) {
|
|
80779
|
+
return scope === "project" ? projectScopeFor(table.projectId, projectId2) : void 0;
|
|
80780
|
+
}
|
|
80584
80781
|
function isAccessPolicy(value) {
|
|
80585
80782
|
return value === "auto" || value === "prompt" || value === "deny";
|
|
80586
80783
|
}
|
|
@@ -80603,23 +80800,23 @@ function rowToRecord2(row, scope) {
|
|
|
80603
80800
|
lastReadBy: row.lastReadBy
|
|
80604
80801
|
};
|
|
80605
80802
|
}
|
|
80606
|
-
async function getSecretMetadata(handle, id, scope) {
|
|
80803
|
+
async function getSecretMetadata(handle, id, scope, projectId2) {
|
|
80607
80804
|
const table = tableForScope(scope);
|
|
80608
|
-
const rows = await handle.select(metadataColumns(table)).from(table).where(eq(table.id, id)).limit(1);
|
|
80805
|
+
const rows = await handle.select(metadataColumns(table)).from(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2))).limit(1);
|
|
80609
80806
|
const row = rows[0];
|
|
80610
80807
|
return row ? rowToRecord2(row, scope) : null;
|
|
80611
80808
|
}
|
|
80612
|
-
async function listSecrets(handle, scope) {
|
|
80809
|
+
async function listSecrets(handle, scope, projectId2) {
|
|
80613
80810
|
if (scope) {
|
|
80614
80811
|
const table = tableForScope(scope);
|
|
80615
|
-
const rows = await handle.select(metadataColumns(table)).from(table).orderBy(asc(sql`lower(${table.key})`));
|
|
80812
|
+
const rows = await handle.select(metadataColumns(table)).from(table).where(scopeForSecretTable(scope, table, projectId2)).orderBy(asc(sql`lower(${table.key})`));
|
|
80616
80813
|
return rows.map((row) => rowToRecord2(row, scope));
|
|
80617
80814
|
}
|
|
80618
|
-
const project = await listSecrets(handle, "project");
|
|
80619
|
-
const global2 = await listSecrets(handle, "global");
|
|
80815
|
+
const project = await listSecrets(handle, "project", projectId2);
|
|
80816
|
+
const global2 = await listSecrets(handle, "global", projectId2);
|
|
80620
80817
|
return [...project, ...global2];
|
|
80621
80818
|
}
|
|
80622
|
-
async function createSecret(handle, cipher, input) {
|
|
80819
|
+
async function createSecret(handle, cipher, input, projectId2) {
|
|
80623
80820
|
const key = input.key.trim();
|
|
80624
80821
|
if (!key) {
|
|
80625
80822
|
throw new SecretsStoreError({ code: "invalid-key", message: "Secret key is required" });
|
|
@@ -80633,6 +80830,7 @@ async function createSecret(handle, cipher, input) {
|
|
|
80633
80830
|
const table = tableForScope(input.scope);
|
|
80634
80831
|
try {
|
|
80635
80832
|
await handle.insert(table).values({
|
|
80833
|
+
...input.scope === "project" && projectId2?.trim() ? { projectId: projectId2 } : {},
|
|
80636
80834
|
id,
|
|
80637
80835
|
key,
|
|
80638
80836
|
valueCiphertext: encrypted.ciphertext,
|
|
@@ -80652,14 +80850,14 @@ async function createSecret(handle, cipher, input) {
|
|
|
80652
80850
|
}
|
|
80653
80851
|
throw error2;
|
|
80654
80852
|
}
|
|
80655
|
-
const created = await getSecretMetadata(handle, id, input.scope);
|
|
80853
|
+
const created = await getSecretMetadata(handle, id, input.scope, projectId2);
|
|
80656
80854
|
if (!created) {
|
|
80657
80855
|
throw new SecretsStoreError({ code: "not-found", message: "Secret insert succeeded but row could not be read back" });
|
|
80658
80856
|
}
|
|
80659
80857
|
return created;
|
|
80660
80858
|
}
|
|
80661
|
-
async function updateSecret(handle, cipher, id, scope, patch) {
|
|
80662
|
-
const existing = await getSecretMetadata(handle, id, scope);
|
|
80859
|
+
async function updateSecret(handle, cipher, id, scope, patch, projectId2) {
|
|
80860
|
+
const existing = await getSecretMetadata(handle, id, scope, projectId2);
|
|
80663
80861
|
if (!existing) {
|
|
80664
80862
|
throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
|
|
80665
80863
|
}
|
|
@@ -80693,34 +80891,34 @@ async function updateSecret(handle, cipher, id, scope, patch) {
|
|
|
80693
80891
|
updates.nonce = encrypted.nonce;
|
|
80694
80892
|
}
|
|
80695
80893
|
try {
|
|
80696
|
-
await handle.update(table).set(updates).where(eq(table.id, id));
|
|
80894
|
+
await handle.update(table).set(updates).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
|
|
80697
80895
|
} catch (error2) {
|
|
80698
80896
|
if (isPostgresUniqueError(error2)) {
|
|
80699
80897
|
throw new SecretsStoreError({ code: "duplicate-key", message: "Secret key already exists" });
|
|
80700
80898
|
}
|
|
80701
80899
|
throw error2;
|
|
80702
80900
|
}
|
|
80703
|
-
const updated = await getSecretMetadata(handle, id, scope);
|
|
80901
|
+
const updated = await getSecretMetadata(handle, id, scope, projectId2);
|
|
80704
80902
|
if (!updated) {
|
|
80705
80903
|
throw new SecretsStoreError({ code: "not-found", message: "Secret update succeeded but row could not be read back" });
|
|
80706
80904
|
}
|
|
80707
80905
|
return updated;
|
|
80708
80906
|
}
|
|
80709
|
-
async function deleteSecret(handle, id, scope) {
|
|
80710
|
-
const existing = await getSecretMetadata(handle, id, scope);
|
|
80907
|
+
async function deleteSecret(handle, id, scope, projectId2) {
|
|
80908
|
+
const existing = await getSecretMetadata(handle, id, scope, projectId2);
|
|
80711
80909
|
if (!existing) {
|
|
80712
80910
|
throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
|
|
80713
80911
|
}
|
|
80714
80912
|
const table = tableForScope(scope);
|
|
80715
|
-
await handle.delete(table).where(eq(table.id, id));
|
|
80913
|
+
await handle.delete(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
|
|
80716
80914
|
}
|
|
80717
|
-
async function revealSecret(handle, cipher, id, scope, reader) {
|
|
80915
|
+
async function revealSecret(handle, cipher, id, scope, reader, projectId2) {
|
|
80718
80916
|
const table = tableForScope(scope);
|
|
80719
80917
|
const rows = await handle.select({
|
|
80720
80918
|
...metadataColumns(table),
|
|
80721
80919
|
valueCiphertext: table.valueCiphertext,
|
|
80722
80920
|
nonce: table.nonce
|
|
80723
|
-
}).from(table).where(eq(table.id, id)).limit(1);
|
|
80921
|
+
}).from(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2))).limit(1);
|
|
80724
80922
|
const row = rows[0];
|
|
80725
80923
|
if (!row) {
|
|
80726
80924
|
throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
|
|
@@ -80739,7 +80937,7 @@ async function revealSecret(handle, cipher, id, scope, reader) {
|
|
|
80739
80937
|
}
|
|
80740
80938
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
80741
80939
|
const lastReadBy = reader.userId ?? reader.agentId ?? null;
|
|
80742
|
-
await handle.update(table).set({ lastReadAt: now, lastReadBy, updatedAt: now }).where(eq(table.id, id));
|
|
80940
|
+
await handle.update(table).set({ lastReadAt: now, lastReadBy, updatedAt: now }).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
|
|
80743
80941
|
return { key: row.key, plaintextValue };
|
|
80744
80942
|
}
|
|
80745
80943
|
var severityAuditLog10, SecretsStoreError, metadataColumns;
|
|
@@ -80750,6 +80948,7 @@ var init_async_secrets_store = __esm({
|
|
|
80750
80948
|
init_drizzle_orm();
|
|
80751
80949
|
init_postgres_errors();
|
|
80752
80950
|
init_schema2();
|
|
80951
|
+
init_data_layer();
|
|
80753
80952
|
init_secrets_crypto();
|
|
80754
80953
|
severityAuditLog10 = createLogger2("core-async-secrets-store");
|
|
80755
80954
|
SecretsStoreError = class extends Error {
|
|
@@ -80845,7 +81044,7 @@ var init_secrets_store = __esm({
|
|
|
80845
81044
|
};
|
|
80846
81045
|
}
|
|
80847
81046
|
async listSecrets(scope) {
|
|
80848
|
-
return listSecrets(this.asyncLayer.db, scope);
|
|
81047
|
+
return listSecrets(this.asyncLayer.db, scope, this.asyncLayer.projectId);
|
|
80849
81048
|
}
|
|
80850
81049
|
async listEnvExportable(opts) {
|
|
80851
81050
|
const keyPrefix = opts?.keyPrefix;
|
|
@@ -80888,7 +81087,7 @@ var init_secrets_store = __esm({
|
|
|
80888
81087
|
return [...exported.values()];
|
|
80889
81088
|
}
|
|
80890
81089
|
async getSecretMetadata(id, scope) {
|
|
80891
|
-
return getSecretMetadata(this.asyncLayer.db, id, scope);
|
|
81090
|
+
return getSecretMetadata(this.asyncLayer.db, id, scope, this.asyncLayer.projectId);
|
|
80892
81091
|
}
|
|
80893
81092
|
async createSecret(input) {
|
|
80894
81093
|
const key = input.key.trim();
|
|
@@ -80898,12 +81097,12 @@ var init_secrets_store = __esm({
|
|
|
80898
81097
|
if (input.accessPolicy && !isAccessPolicy2(input.accessPolicy)) {
|
|
80899
81098
|
throw new SecretsStoreError2({ code: "invalid-policy", message: "Invalid access policy" });
|
|
80900
81099
|
}
|
|
80901
|
-
const created = await createSecret(this.asyncLayer.db, this.cipher, input);
|
|
81100
|
+
const created = await createSecret(this.asyncLayer.db, this.cipher, input, this.asyncLayer.projectId);
|
|
80902
81101
|
this.emitAudit({ mutationType: "secret:create", scope: input.scope, secretId: created.id, key: created.key });
|
|
80903
81102
|
return created;
|
|
80904
81103
|
}
|
|
80905
81104
|
async updateSecret(id, scope, patch) {
|
|
80906
|
-
const updated = await updateSecret(this.asyncLayer.db, this.cipher, id, scope, patch);
|
|
81105
|
+
const updated = await updateSecret(this.asyncLayer.db, this.cipher, id, scope, patch, this.asyncLayer.projectId);
|
|
80907
81106
|
this.emitAudit({ mutationType: "secret:update", scope, secretId: updated.id, key: updated.key });
|
|
80908
81107
|
return updated;
|
|
80909
81108
|
}
|
|
@@ -80912,12 +81111,12 @@ var init_secrets_store = __esm({
|
|
|
80912
81111
|
if (!existing) {
|
|
80913
81112
|
throw new SecretsStoreError2({ code: "not-found", message: "Secret not found" });
|
|
80914
81113
|
}
|
|
80915
|
-
await deleteSecret(this.asyncLayer.db, id, scope);
|
|
81114
|
+
await deleteSecret(this.asyncLayer.db, id, scope, this.asyncLayer.projectId);
|
|
80916
81115
|
this.emitAudit({ mutationType: "secret:delete", scope, secretId: id, key: existing.key });
|
|
80917
81116
|
return;
|
|
80918
81117
|
}
|
|
80919
81118
|
async revealSecret(id, scope, reader) {
|
|
80920
|
-
const revealed = await revealSecret(this.asyncLayer.db, this.cipher, id, scope, reader);
|
|
81119
|
+
const revealed = await revealSecret(this.asyncLayer.db, this.cipher, id, scope, reader, this.asyncLayer.projectId);
|
|
80921
81120
|
this.emitAudit({ mutationType: "secret:read", scope, secretId: id, key: revealed.key, actor: reader });
|
|
80922
81121
|
return revealed;
|
|
80923
81122
|
}
|
|
@@ -82018,6 +82217,7 @@ async function getVerificationCacheHitImpl(store, treeSha, testCommand, buildCom
|
|
|
82018
82217
|
const normalizedBuild = buildCommand2 ?? "";
|
|
82019
82218
|
const table = project_exports.verificationCache;
|
|
82020
82219
|
const rows = await store.asyncLayer.db.select({ recordedAt: table.recordedAt, taskId: table.taskId }).from(table).where(and(
|
|
82220
|
+
projectScopeFor(table.projectId, store.asyncLayer.projectId),
|
|
82021
82221
|
eq(table.treeSha, treeSha),
|
|
82022
82222
|
eq(table.testCommand, normalizedTest),
|
|
82023
82223
|
eq(table.buildCommand, normalizedBuild)
|
|
@@ -82760,7 +82960,7 @@ async function invokeTaskCreatedHookImpl(store, task) {
|
|
|
82760
82960
|
}
|
|
82761
82961
|
async function createBranchGroupImpl(store, input) {
|
|
82762
82962
|
const layer = store.asyncLayer;
|
|
82763
|
-
return createBranchGroup(layer.db, input);
|
|
82963
|
+
return createBranchGroup(layer.db, input, layer.projectId);
|
|
82764
82964
|
}
|
|
82765
82965
|
var init_task_id_integrity2 = __esm({
|
|
82766
82966
|
"../core/src/task-store/task-id-integrity.ts"() {
|
|
@@ -82845,22 +83045,23 @@ import { readFile as readFile7, writeFile as writeFile5 } from "node:fs/promises
|
|
|
82845
83045
|
import { join as join23 } from "node:path";
|
|
82846
83046
|
async function getBranchGroupImpl(store, id) {
|
|
82847
83047
|
const layer = store.asyncLayer;
|
|
82848
|
-
return getBranchGroup(layer.db, id);
|
|
83048
|
+
return getBranchGroup(layer.db, id, layer.projectId);
|
|
82849
83049
|
}
|
|
82850
83050
|
async function getBranchGroupBySourceImpl(store, sourceType, sourceId) {
|
|
82851
83051
|
const layer = store.asyncLayer;
|
|
82852
|
-
return getBranchGroupBySource(layer.db, sourceType, sourceId);
|
|
83052
|
+
return getBranchGroupBySource(layer.db, sourceType, sourceId, layer.projectId);
|
|
82853
83053
|
}
|
|
82854
83054
|
async function getBranchGroupByBranchNameImpl(store, branchName) {
|
|
82855
83055
|
const layer = store.asyncLayer;
|
|
82856
|
-
return getBranchGroupByBranchName(layer.db, branchName);
|
|
83056
|
+
return getBranchGroupByBranchName(layer.db, branchName, layer.projectId);
|
|
82857
83057
|
}
|
|
82858
83058
|
async function ensureBranchGroupForSourceImpl(store, sourceType, sourceId, init) {
|
|
82859
|
-
|
|
83059
|
+
const layer = store.asyncLayer;
|
|
83060
|
+
return ensureBranchGroupForSource(layer.db, sourceType, sourceId, init, layer.projectId);
|
|
82860
83061
|
}
|
|
82861
83062
|
async function listBranchGroupsImpl(store, options) {
|
|
82862
83063
|
const layer = store.asyncLayer;
|
|
82863
|
-
return listBranchGroups(layer.db, options);
|
|
83064
|
+
return listBranchGroups(layer.db, options, layer.projectId);
|
|
82864
83065
|
}
|
|
82865
83066
|
async function listTasksByBranchGroupImpl(store, groupId) {
|
|
82866
83067
|
const tasks2 = await store.listTasks({ includeArchived: true, slim: false });
|
|
@@ -84402,7 +84603,7 @@ function insertArtifactRowImpl(store, input, id, now, stored) {
|
|
|
84402
84603
|
}
|
|
84403
84604
|
async function getArtifactImpl(store, id) {
|
|
84404
84605
|
const layer = store.asyncLayer;
|
|
84405
|
-
return getArtifact(layer.db, id);
|
|
84606
|
+
return getArtifact(layer.db, id, layer.projectId);
|
|
84406
84607
|
}
|
|
84407
84608
|
async function updateArtifactImpl(store, id, updates) {
|
|
84408
84609
|
const layer = store.asyncLayer;
|
|
@@ -89271,6 +89472,7 @@ var init_async_archive_lineage = __esm({
|
|
|
89271
89472
|
"use strict";
|
|
89272
89473
|
init_drizzle_orm();
|
|
89273
89474
|
init_schema2();
|
|
89475
|
+
init_data_layer();
|
|
89274
89476
|
init_async_persistence();
|
|
89275
89477
|
init_async_lifecycle();
|
|
89276
89478
|
init_lineage_approval_invalidation();
|
|
@@ -92738,7 +92940,7 @@ async function _maybeAutoArchiveSameAgentDuplicateBackendImpl(store, task, input
|
|
|
92738
92940
|
}
|
|
92739
92941
|
async function updateBranchGroupImpl(store, id, patch) {
|
|
92740
92942
|
const layer = store.asyncLayer;
|
|
92741
|
-
return updateBranchGroup(layer.db, id, patch);
|
|
92943
|
+
return updateBranchGroup(layer.db, id, patch, layer.projectId);
|
|
92742
92944
|
}
|
|
92743
92945
|
async function updatePrEntityImpl(store, id, patch) {
|
|
92744
92946
|
const layer = store.asyncLayer;
|
|
@@ -93248,13 +93450,19 @@ async function deleteAttachmentArtifactRows(store, taskId, filename) {
|
|
|
93248
93450
|
const linkedArtifactIds = artifacts2.filter((artifact) => artifact.metadata?.source === "attachment" && artifact.metadata.attachmentFilename === filename).map((artifact) => artifact.id);
|
|
93249
93451
|
if (linkedArtifactIds.length === 0) return;
|
|
93250
93452
|
for (const artifactId of linkedArtifactIds) {
|
|
93251
|
-
await layer.db.delete(project_exports.artifacts).where(
|
|
93453
|
+
await layer.db.delete(project_exports.artifacts).where(and(
|
|
93454
|
+
eq(project_exports.artifacts.id, artifactId),
|
|
93455
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
93456
|
+
));
|
|
93252
93457
|
}
|
|
93253
93458
|
return;
|
|
93254
93459
|
}
|
|
93255
93460
|
async function getArtifactsForAttachmentCleanup(store, taskId) {
|
|
93256
93461
|
const layer = store.asyncLayer;
|
|
93257
|
-
const rows = await layer.db.select().from(project_exports.artifacts).where(
|
|
93462
|
+
const rows = await layer.db.select().from(project_exports.artifacts).where(and(
|
|
93463
|
+
eq(project_exports.artifacts.taskId, taskId),
|
|
93464
|
+
projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
|
|
93465
|
+
));
|
|
93258
93466
|
return rows;
|
|
93259
93467
|
}
|
|
93260
93468
|
async function deleteAttachmentImpl(store, id, filename) {
|
|
@@ -95670,7 +95878,7 @@ function clearLinkedAgentTaskIdsImpl(store, taskId, updatedAt = (/* @__PURE__ */
|
|
|
95670
95878
|
`).run(updatedAt, updatedAt, taskId);
|
|
95671
95879
|
}
|
|
95672
95880
|
async function listArtifactsImpl(store, options) {
|
|
95673
|
-
return listArtifacts(store.asyncLayer.db, options);
|
|
95881
|
+
return listArtifacts(store.asyncLayer.db, options, store.asyncLayer.projectId);
|
|
95674
95882
|
}
|
|
95675
95883
|
async function rehomeOccupantImpl(store, taskId, targetColumn, reason, metadata) {
|
|
95676
95884
|
let current;
|
|
@@ -96915,8 +97123,8 @@ async function upsertWorkflowWorkItemImpl(store, input, tx) {
|
|
|
96915
97123
|
async function replaceActiveTaskWorkflowContinuationImpl(store, input) {
|
|
96916
97124
|
return replaceActiveTaskWorkflowContinuation(store.asyncLayer, input);
|
|
96917
97125
|
}
|
|
96918
|
-
async function seedStrandedPlanReviewContinuationImpl(store, input) {
|
|
96919
|
-
return seedStrandedPlanReviewContinuation(store.asyncLayer, input);
|
|
97126
|
+
async function seedStrandedPlanReviewContinuationImpl(store, input, options = {}) {
|
|
97127
|
+
return seedStrandedPlanReviewContinuation(store.asyncLayer, input, options);
|
|
96920
97128
|
}
|
|
96921
97129
|
async function transitionWorkflowWorkItemImpl(store, id, state, patch = {}, tx) {
|
|
96922
97130
|
return transitionWorkflowWorkItem(store.asyncLayer, id, state, patch, tx);
|
|
@@ -101059,6 +101267,37 @@ async function getTaskVerificationRequestAsyncImpl(store, taskId) {
|
|
|
101059
101267
|
const row = rows[0];
|
|
101060
101268
|
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;
|
|
101061
101269
|
}
|
|
101270
|
+
async function listTaskRecommendationsImpl(store, options) {
|
|
101271
|
+
const layer = store.asyncLayer;
|
|
101272
|
+
const completeColumns = options?.completeColumns ?? await resolveProjectColumnsForRoles(store, ["complete"]);
|
|
101273
|
+
const rawLimit = options?.limit;
|
|
101274
|
+
const rawOffset = options?.offset;
|
|
101275
|
+
const limit = typeof rawLimit === "number" && Number.isFinite(rawLimit) ? Math.min(200, Math.max(1, Math.trunc(rawLimit))) : 50;
|
|
101276
|
+
const offset = typeof rawOffset === "number" && Number.isFinite(rawOffset) ? Math.max(0, Math.trunc(rawOffset)) : 0;
|
|
101277
|
+
const columns = [...completeColumns];
|
|
101278
|
+
if (columns.length === 0) return { items: [], rowOffset: offset, rowLimit: limit, returnedRowCount: 0, totalRowCount: 0, hasMore: false };
|
|
101279
|
+
const filter = and(
|
|
101280
|
+
taskProjectScope(layer),
|
|
101281
|
+
isNull(project_exports.tasks.deletedAt),
|
|
101282
|
+
inArray(project_exports.tasks.column, columns),
|
|
101283
|
+
isNotNull(project_exports.tasks.recommendations),
|
|
101284
|
+
sql`jsonb_array_length(${project_exports.tasks.recommendations}) > 0`
|
|
101285
|
+
);
|
|
101286
|
+
const [countRows, rows] = await Promise.all([
|
|
101287
|
+
layer.db.select({ count: sql`count(*)` }).from(project_exports.tasks).where(filter),
|
|
101288
|
+
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(filter).orderBy(desc(project_exports.tasks.updatedAt), desc(project_exports.tasks.id)).limit(limit).offset(offset)
|
|
101289
|
+
]);
|
|
101290
|
+
const items = [];
|
|
101291
|
+
for (const row of rows) {
|
|
101292
|
+
if (!Array.isArray(row.recommendations) || row.recommendations.length === 0) continue;
|
|
101293
|
+
for (const recommendation of row.recommendations) {
|
|
101294
|
+
items.push({ taskId: row.id, taskTitle: row.title ?? void 0, taskColumn: row.column, updatedAt: row.updatedAt, recommendation });
|
|
101295
|
+
}
|
|
101296
|
+
}
|
|
101297
|
+
const totalRowCount = Number(countRows[0]?.count ?? 0);
|
|
101298
|
+
const returnedRowCount = rows.length;
|
|
101299
|
+
return { items, rowOffset: offset, rowLimit: limit, returnedRowCount, totalRowCount, hasMore: offset + returnedRowCount < totalRowCount };
|
|
101300
|
+
}
|
|
101062
101301
|
var LEGACY_REVIEW_LANES5, LEGACY_ARCHIVE_LANES2;
|
|
101063
101302
|
var init_reads = __esm({
|
|
101064
101303
|
"../core/src/task-store/reads.ts"() {
|
|
@@ -101081,6 +101320,7 @@ var init_reads = __esm({
|
|
|
101081
101320
|
init_retry_summary();
|
|
101082
101321
|
init_errors3();
|
|
101083
101322
|
init_project_lane_vocabulary();
|
|
101323
|
+
init_data_layer();
|
|
101084
101324
|
init_async_persistence();
|
|
101085
101325
|
init_async_search();
|
|
101086
101326
|
init_async_archive_db();
|
|
@@ -103187,6 +103427,9 @@ var init_store = __esm({
|
|
|
103187
103427
|
async clearWorkflowRunStepInstancesAsync(taskId, keepRunId) {
|
|
103188
103428
|
return clearWorkflowRunStepInstancesAsyncImpl(this, taskId, keepRunId);
|
|
103189
103429
|
}
|
|
103430
|
+
async listTaskRecommendations(options) {
|
|
103431
|
+
return listTaskRecommendationsImpl(this, options);
|
|
103432
|
+
}
|
|
103190
103433
|
async listTasksForGithubTrackingReconcile(options) {
|
|
103191
103434
|
return listTasksForGithubTrackingReconcileImpl(this, options);
|
|
103192
103435
|
}
|
|
@@ -103913,8 +104156,8 @@ var init_store = __esm({
|
|
|
103913
104156
|
async replaceActiveTaskWorkflowContinuation(input) {
|
|
103914
104157
|
return replaceActiveTaskWorkflowContinuationImpl(this, input);
|
|
103915
104158
|
}
|
|
103916
|
-
async seedStrandedPlanReviewContinuation(input) {
|
|
103917
|
-
return seedStrandedPlanReviewContinuationImpl(this, input);
|
|
104159
|
+
async seedStrandedPlanReviewContinuation(input, options = {}) {
|
|
104160
|
+
return seedStrandedPlanReviewContinuationImpl(this, input, options);
|
|
103918
104161
|
}
|
|
103919
104162
|
async transitionWorkflowWorkItem(id, state, patch = {}, tx) {
|
|
103920
104163
|
return transitionWorkflowWorkItemImpl(this, id, state, patch, tx);
|
|
@@ -103997,7 +104240,11 @@ var init_store = __esm({
|
|
|
103997
104240
|
/** PostgreSQL-authoritative audit reader; sync fallback remains for test doubles. */
|
|
103998
104241
|
async getRunAuditEventsAsync(options = {}) {
|
|
103999
104242
|
if (this.asyncLayer) {
|
|
104000
|
-
const events = await queryRunAuditEvents(
|
|
104243
|
+
const events = await queryRunAuditEvents(
|
|
104244
|
+
this.asyncLayer.db,
|
|
104245
|
+
options,
|
|
104246
|
+
this.asyncLayer.projectId
|
|
104247
|
+
);
|
|
104001
104248
|
return events.map((event) => ({
|
|
104002
104249
|
...event,
|
|
104003
104250
|
taskId: event.taskId ?? void 0,
|
|
@@ -107575,7 +107822,9 @@ function rangeWhere(query) {
|
|
|
107575
107822
|
async function aggregatePluginActivations(dbOrLayer, query = {}) {
|
|
107576
107823
|
if ("ping" in dbOrLayer) {
|
|
107577
107824
|
const layer = dbOrLayer;
|
|
107578
|
-
const conditions = []
|
|
107825
|
+
const conditions = [projectScopeFor(project_exports.pluginActivations.projectId, layer.projectId)].filter(
|
|
107826
|
+
(condition) => condition !== void 0
|
|
107827
|
+
);
|
|
107579
107828
|
if (query.from !== void 0) conditions.push(gte(project_exports.pluginActivations.activatedAt, query.from));
|
|
107580
107829
|
if (query.to !== void 0) conditions.push(lte(project_exports.pluginActivations.activatedAt, query.to));
|
|
107581
107830
|
const where2 = conditions.length > 0 ? and(...conditions) : void 0;
|
|
@@ -107614,6 +107863,7 @@ async function aggregatePluginActivations(dbOrLayer, query = {}) {
|
|
|
107614
107863
|
var init_plugin_activation_analytics = __esm({
|
|
107615
107864
|
"../core/src/plugins/plugin-activation-analytics.ts"() {
|
|
107616
107865
|
"use strict";
|
|
107866
|
+
init_data_layer();
|
|
107617
107867
|
init_drizzle_orm();
|
|
107618
107868
|
init_schema2();
|
|
107619
107869
|
}
|
|
@@ -130611,6 +130861,18 @@ function rowToMessage2(row) {
|
|
|
130611
130861
|
createdAt: row.createdAt
|
|
130612
130862
|
};
|
|
130613
130863
|
}
|
|
130864
|
+
function chatMessageProjectConditions(handle, projectId2) {
|
|
130865
|
+
const messageScope = projectScopeFor(project_exports.chatMessages.projectId, projectId2);
|
|
130866
|
+
const sessionScope = projectScopeFor(project_exports.chatSessions.projectId, projectId2);
|
|
130867
|
+
if (!messageScope || !sessionScope) return [];
|
|
130868
|
+
return [
|
|
130869
|
+
messageScope,
|
|
130870
|
+
exists(handle.select({ id: project_exports.chatSessions.id }).from(project_exports.chatSessions).where(and(
|
|
130871
|
+
eq(project_exports.chatSessions.id, project_exports.chatMessages.sessionId),
|
|
130872
|
+
sessionScope
|
|
130873
|
+
)))
|
|
130874
|
+
];
|
|
130875
|
+
}
|
|
130614
130876
|
function rowToRoom(row) {
|
|
130615
130877
|
return {
|
|
130616
130878
|
id: row.id,
|
|
@@ -130782,7 +131044,7 @@ async function replaceChatSessionTags(layer, sessionId, projectId2, tagIds) {
|
|
|
130782
131044
|
return attachTags(tx, session);
|
|
130783
131045
|
});
|
|
130784
131046
|
}
|
|
130785
|
-
async function addChatMessage(handle, message) {
|
|
131047
|
+
async function addChatMessage(handle, message, projectId2) {
|
|
130786
131048
|
const sanitizedAttachments = message.attachments === void 0 ? void 0 : sanitizeJsonbValue(message.attachments);
|
|
130787
131049
|
const sanitized = {
|
|
130788
131050
|
...message,
|
|
@@ -130801,15 +131063,24 @@ async function addChatMessage(handle, message) {
|
|
|
130801
131063
|
attachments: sanitizedAttachments ?? null,
|
|
130802
131064
|
createdAt: sanitized.createdAt
|
|
130803
131065
|
});
|
|
130804
|
-
await handle.update(project_exports.chatSessions).set({ updatedAt: sanitized.createdAt }).where(
|
|
131066
|
+
await handle.update(project_exports.chatSessions).set({ updatedAt: sanitized.createdAt }).where(and(
|
|
131067
|
+
eq(project_exports.chatSessions.id, sanitized.sessionId),
|
|
131068
|
+
projectScopeFor(project_exports.chatSessions.projectId, projectId2)
|
|
131069
|
+
));
|
|
130805
131070
|
return sanitized;
|
|
130806
131071
|
}
|
|
130807
|
-
async function getChatMessage(handle, id) {
|
|
130808
|
-
const rows = await handle.select().from(project_exports.chatMessages).where(
|
|
131072
|
+
async function getChatMessage(handle, id, projectId2) {
|
|
131073
|
+
const rows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131074
|
+
eq(project_exports.chatMessages.id, id),
|
|
131075
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131076
|
+
));
|
|
130809
131077
|
return rows[0] ? rowToMessage2(rows[0]) : void 0;
|
|
130810
131078
|
}
|
|
130811
|
-
async function getChatMessages(handle, sessionId, filter) {
|
|
130812
|
-
const conditions = [
|
|
131079
|
+
async function getChatMessages(handle, sessionId, filter, projectId2) {
|
|
131080
|
+
const conditions = [
|
|
131081
|
+
eq(project_exports.chatMessages.sessionId, sessionId),
|
|
131082
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131083
|
+
];
|
|
130813
131084
|
if (filter?.before) {
|
|
130814
131085
|
conditions.push(lte(project_exports.chatMessages.createdAt, filter.before));
|
|
130815
131086
|
}
|
|
@@ -130819,9 +131090,12 @@ async function getChatMessages(handle, sessionId, filter) {
|
|
|
130819
131090
|
const rows = await handle.select().from(project_exports.chatMessages).where(and(...conditions)).orderBy(filter?.order === "desc" ? desc(orderCol) : asc(orderCol)).limit(limit).offset(offset);
|
|
130820
131091
|
return rows.map(rowToMessage2);
|
|
130821
131092
|
}
|
|
130822
|
-
async function getLastMessageForSessions(handle, sessionIds) {
|
|
131093
|
+
async function getLastMessageForSessions(handle, sessionIds, projectId2) {
|
|
130823
131094
|
if (sessionIds.length === 0) return /* @__PURE__ */ new Map();
|
|
130824
|
-
const rows = await handle.select().from(project_exports.chatMessages).where(
|
|
131095
|
+
const rows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131096
|
+
inArray(project_exports.chatMessages.sessionId, sessionIds),
|
|
131097
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131098
|
+
)).orderBy(
|
|
130825
131099
|
desc(project_exports.chatMessages.createdAt),
|
|
130826
131100
|
desc(project_exports.chatMessages.id)
|
|
130827
131101
|
);
|
|
@@ -130987,8 +131261,8 @@ async function setInFlightGeneration(handle, id, inFlightGeneration) {
|
|
|
130987
131261
|
await handle.update(project_exports.chatSessions).set({ inFlightGeneration: sanitizedInFlightGeneration }).where(eq(project_exports.chatSessions.id, id));
|
|
130988
131262
|
return getChatSession(handle, id);
|
|
130989
131263
|
}
|
|
130990
|
-
async function addChatMessageAttachment(handle, sessionId, messageId, attachment) {
|
|
130991
|
-
const message = await getChatMessage(handle, messageId);
|
|
131264
|
+
async function addChatMessageAttachment(handle, sessionId, messageId, attachment, projectId2) {
|
|
131265
|
+
const message = await getChatMessage(handle, messageId, projectId2);
|
|
130992
131266
|
if (!message || message.sessionId !== sessionId) {
|
|
130993
131267
|
throw new Error(`Message ${messageId} not found in session ${sessionId}`);
|
|
130994
131268
|
}
|
|
@@ -130996,25 +131270,35 @@ async function addChatMessageAttachment(handle, sessionId, messageId, attachment
|
|
|
130996
131270
|
...message.attachments ?? [],
|
|
130997
131271
|
attachment
|
|
130998
131272
|
]);
|
|
130999
|
-
await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(
|
|
131000
|
-
|
|
131273
|
+
await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(and(
|
|
131274
|
+
eq(project_exports.chatMessages.id, messageId),
|
|
131275
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131276
|
+
));
|
|
131277
|
+
const updated = await getChatMessage(handle, messageId, projectId2);
|
|
131001
131278
|
if (!updated) throw new Error(`Failed to update message ${messageId}`);
|
|
131002
131279
|
return updated;
|
|
131003
131280
|
}
|
|
131004
|
-
async function deleteChatMessage(handle, id) {
|
|
131005
|
-
const existing = await getChatMessage(handle, id);
|
|
131281
|
+
async function deleteChatMessage(handle, id, projectId2) {
|
|
131282
|
+
const existing = await getChatMessage(handle, id, projectId2);
|
|
131006
131283
|
if (!existing) return false;
|
|
131007
|
-
await handle.delete(project_exports.chatMessages).where(
|
|
131008
|
-
|
|
131284
|
+
await handle.delete(project_exports.chatMessages).where(and(
|
|
131285
|
+
eq(project_exports.chatMessages.id, id),
|
|
131286
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131287
|
+
));
|
|
131288
|
+
await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(
|
|
131289
|
+
eq(project_exports.chatSessions.id, existing.sessionId),
|
|
131290
|
+
projectScopeFor(project_exports.chatSessions.projectId, projectId2)
|
|
131291
|
+
));
|
|
131009
131292
|
return true;
|
|
131010
131293
|
}
|
|
131011
|
-
async function searchChatSessionsByMessageContent(handle, query, sessionIds) {
|
|
131294
|
+
async function searchChatSessionsByMessageContent(handle, query, sessionIds, projectId2) {
|
|
131012
131295
|
const trimmed = query.trim();
|
|
131013
131296
|
if (!trimmed || sessionIds.length === 0) return /* @__PURE__ */ new Map();
|
|
131014
131297
|
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
131015
131298
|
const rows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131016
131299
|
inArray(project_exports.chatMessages.sessionId, sessionIds),
|
|
131017
|
-
ilike(project_exports.chatMessages.content, `%${escaped}%`)
|
|
131300
|
+
ilike(project_exports.chatMessages.content, `%${escaped}%`),
|
|
131301
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131018
131302
|
)).orderBy(
|
|
131019
131303
|
desc(project_exports.chatMessages.createdAt),
|
|
131020
131304
|
desc(project_exports.chatMessages.id)
|
|
@@ -131028,13 +131312,16 @@ async function searchChatSessionsByMessageContent(handle, query, sessionIds) {
|
|
|
131028
131312
|
}
|
|
131029
131313
|
return result;
|
|
131030
131314
|
}
|
|
131031
|
-
async function deleteChatMessagesFrom(handle, sessionId, fromMessageId) {
|
|
131032
|
-
const orderedRows = await handle.select().from(project_exports.chatMessages).where(
|
|
131315
|
+
async function deleteChatMessagesFrom(handle, sessionId, fromMessageId, projectId2) {
|
|
131316
|
+
const orderedRows = await handle.select().from(project_exports.chatMessages).where(and(
|
|
131317
|
+
eq(project_exports.chatMessages.sessionId, sessionId),
|
|
131318
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131319
|
+
)).orderBy(
|
|
131033
131320
|
asc(project_exports.chatMessages.createdAt),
|
|
131034
131321
|
asc(project_exports.chatMessages.id)
|
|
131035
131322
|
);
|
|
131036
131323
|
const ordered2 = orderedRows.map(rowToMessage2);
|
|
131037
|
-
const target = await getChatMessage(handle, fromMessageId);
|
|
131324
|
+
const target = await getChatMessage(handle, fromMessageId, projectId2);
|
|
131038
131325
|
if (!target || target.sessionId !== sessionId) {
|
|
131039
131326
|
return { deletedIds: [], retained: ordered2 };
|
|
131040
131327
|
}
|
|
@@ -131047,19 +131334,28 @@ async function deleteChatMessagesFrom(handle, sessionId, fromMessageId) {
|
|
|
131047
131334
|
if (deletedIds.length === 0) {
|
|
131048
131335
|
return { deletedIds: [], retained };
|
|
131049
131336
|
}
|
|
131050
|
-
await handle.delete(project_exports.chatMessages).where(
|
|
131051
|
-
|
|
131337
|
+
await handle.delete(project_exports.chatMessages).where(and(
|
|
131338
|
+
inArray(project_exports.chatMessages.id, deletedIds),
|
|
131339
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131340
|
+
));
|
|
131341
|
+
await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(
|
|
131342
|
+
eq(project_exports.chatSessions.id, sessionId),
|
|
131343
|
+
projectScopeFor(project_exports.chatSessions.projectId, projectId2)
|
|
131344
|
+
));
|
|
131052
131345
|
return { deletedIds, retained };
|
|
131053
131346
|
}
|
|
131054
|
-
async function updateChatMessageMetadata(handle, messageId, metadata, options) {
|
|
131055
|
-
const existing = await getChatMessage(handle, messageId);
|
|
131347
|
+
async function updateChatMessageMetadata(handle, messageId, metadata, options, projectId2) {
|
|
131348
|
+
const existing = await getChatMessage(handle, messageId, projectId2);
|
|
131056
131349
|
if (!existing) {
|
|
131057
131350
|
throw new Error(`Message ${messageId} not found`);
|
|
131058
131351
|
}
|
|
131059
131352
|
const merge2 = options?.merge !== false;
|
|
131060
131353
|
const nextMetadata = metadata === null ? merge2 ? existing.metadata : null : merge2 ? { ...existing.metadata ?? {}, ...metadata } : metadata;
|
|
131061
|
-
await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(
|
|
131062
|
-
|
|
131354
|
+
await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(and(
|
|
131355
|
+
eq(project_exports.chatMessages.id, messageId),
|
|
131356
|
+
...chatMessageProjectConditions(handle, projectId2)
|
|
131357
|
+
));
|
|
131358
|
+
const updated = await getChatMessage(handle, messageId, projectId2);
|
|
131063
131359
|
if (!updated) {
|
|
131064
131360
|
throw new Error(`Failed to update message ${messageId}`);
|
|
131065
131361
|
}
|
|
@@ -131441,7 +131737,7 @@ var init_chat_store = __esm({
|
|
|
131441
131737
|
attachments: input.attachments,
|
|
131442
131738
|
createdAt: now
|
|
131443
131739
|
};
|
|
131444
|
-
const created = await addChatMessage(this.asyncLayer.db, message);
|
|
131740
|
+
const created = await addChatMessage(this.asyncLayer.db, message, this.asyncLayer.projectId);
|
|
131445
131741
|
this.emit("chat:message:added", created);
|
|
131446
131742
|
return created;
|
|
131447
131743
|
}
|
|
@@ -131449,7 +131745,7 @@ var init_chat_store = __esm({
|
|
|
131449
131745
|
* Append a file attachment metadata record to an existing message.
|
|
131450
131746
|
*/
|
|
131451
131747
|
async addMessageAttachment(sessionId, messageId, attachment) {
|
|
131452
|
-
const updated = await addChatMessageAttachment(this.asyncLayer.db, sessionId, messageId, attachment);
|
|
131748
|
+
const updated = await addChatMessageAttachment(this.asyncLayer.db, sessionId, messageId, attachment, this.asyncLayer.projectId);
|
|
131453
131749
|
this.emit("chat:message:updated", updated);
|
|
131454
131750
|
return updated;
|
|
131455
131751
|
}
|
|
@@ -131461,7 +131757,7 @@ var init_chat_store = __esm({
|
|
|
131461
131757
|
* @returns Array of messages ordered by createdAt ASC (default) or DESC
|
|
131462
131758
|
*/
|
|
131463
131759
|
async getMessages(sessionId, filter) {
|
|
131464
|
-
return getChatMessages(this.asyncLayer.db, sessionId, filter);
|
|
131760
|
+
return getChatMessages(this.asyncLayer.db, sessionId, filter, this.asyncLayer.projectId);
|
|
131465
131761
|
}
|
|
131466
131762
|
/**
|
|
131467
131763
|
* Get a message by ID.
|
|
@@ -131470,7 +131766,7 @@ var init_chat_store = __esm({
|
|
|
131470
131766
|
* @returns The message, or undefined if not found
|
|
131471
131767
|
*/
|
|
131472
131768
|
async getMessage(id) {
|
|
131473
|
-
return getChatMessage(this.asyncLayer.db, id);
|
|
131769
|
+
return getChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
131474
131770
|
}
|
|
131475
131771
|
/**
|
|
131476
131772
|
* Get the latest message for each session in the provided list.
|
|
@@ -131480,10 +131776,10 @@ var init_chat_store = __esm({
|
|
|
131480
131776
|
* @returns Map of sessionId -> latest ChatMessage for that session
|
|
131481
131777
|
*/
|
|
131482
131778
|
async getLastMessageForSessions(sessionIds) {
|
|
131483
|
-
return getLastMessageForSessions(this.asyncLayer.db, sessionIds);
|
|
131779
|
+
return getLastMessageForSessions(this.asyncLayer.db, sessionIds, this.asyncLayer.projectId);
|
|
131484
131780
|
}
|
|
131485
131781
|
async hasMessages(sessionId) {
|
|
131486
|
-
return (await getChatMessages(this.asyncLayer.db, sessionId, { limit: 1 })).length > 0;
|
|
131782
|
+
return (await getChatMessages(this.asyncLayer.db, sessionId, { limit: 1 }, this.asyncLayer.projectId)).length > 0;
|
|
131487
131783
|
}
|
|
131488
131784
|
/**
|
|
131489
131785
|
* Search sessions by message content (not just title/agentId).
|
|
@@ -131511,7 +131807,7 @@ var init_chat_store = __esm({
|
|
|
131511
131807
|
if (!trimmed || !sessionIds || sessionIds.length === 0) {
|
|
131512
131808
|
return /* @__PURE__ */ new Map();
|
|
131513
131809
|
}
|
|
131514
|
-
return searchChatSessionsByMessageContent(this.asyncLayer.db, trimmed, sessionIds);
|
|
131810
|
+
return searchChatSessionsByMessageContent(this.asyncLayer.db, trimmed, sessionIds, this.asyncLayer.projectId);
|
|
131515
131811
|
}
|
|
131516
131812
|
/**
|
|
131517
131813
|
* Delete a message by ID.
|
|
@@ -131520,9 +131816,9 @@ var init_chat_store = __esm({
|
|
|
131520
131816
|
* @returns true if deleted, false if not found
|
|
131521
131817
|
*/
|
|
131522
131818
|
async deleteMessage(id) {
|
|
131523
|
-
const existing = await getChatMessage(this.asyncLayer.db, id);
|
|
131819
|
+
const existing = await getChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
131524
131820
|
if (!existing) return false;
|
|
131525
|
-
const deleted = await deleteChatMessage(this.asyncLayer.db, id);
|
|
131821
|
+
const deleted = await deleteChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
|
|
131526
131822
|
if (deleted) {
|
|
131527
131823
|
this.emit("chat:message:deleted", id);
|
|
131528
131824
|
const updatedSession = await this.getSession(existing.sessionId);
|
|
@@ -131545,7 +131841,7 @@ var init_chat_store = __esm({
|
|
|
131545
131841
|
* @returns deletedIds (in ASC order) and retained messages (pre-edit history, ASC order)
|
|
131546
131842
|
*/
|
|
131547
131843
|
async deleteMessagesFrom(sessionId, fromMessageId) {
|
|
131548
|
-
const result = await deleteChatMessagesFrom(this.asyncLayer.db, sessionId, fromMessageId);
|
|
131844
|
+
const result = await deleteChatMessagesFrom(this.asyncLayer.db, sessionId, fromMessageId, this.asyncLayer.projectId);
|
|
131549
131845
|
if (result.deletedIds.length > 0) {
|
|
131550
131846
|
for (const id of result.deletedIds) {
|
|
131551
131847
|
this.emit("chat:message:deleted", id);
|
|
@@ -131563,7 +131859,7 @@ var init_chat_store = __esm({
|
|
|
131563
131859
|
* is what lets a later edit rewind losslessly via SessionManager.branch()/resetLeaf().
|
|
131564
131860
|
*/
|
|
131565
131861
|
async updateMessageMetadata(messageId, metadata, options) {
|
|
131566
|
-
const updated = await updateChatMessageMetadata(this.asyncLayer.db, messageId, metadata, options);
|
|
131862
|
+
const updated = await updateChatMessageMetadata(this.asyncLayer.db, messageId, metadata, options, this.asyncLayer.projectId);
|
|
131567
131863
|
this.emit("chat:message:updated", updated);
|
|
131568
131864
|
return updated;
|
|
131569
131865
|
}
|
|
@@ -132999,6 +133295,77 @@ var init_task_timing = __esm({
|
|
|
132999
133295
|
}
|
|
133000
133296
|
});
|
|
133001
133297
|
|
|
133298
|
+
// ../core/src/task-recommendation-notice.ts
|
|
133299
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
133300
|
+
function registerTaskRecommendationNoticeMailbox(store, mailbox) {
|
|
133301
|
+
mailboxes2.set(store, mailbox);
|
|
133302
|
+
return () => {
|
|
133303
|
+
if (mailboxes2.get(store) === mailbox) mailboxes2.delete(store);
|
|
133304
|
+
};
|
|
133305
|
+
}
|
|
133306
|
+
function getTaskRecommendationNoticeMailbox(store) {
|
|
133307
|
+
return mailboxes2.get(store);
|
|
133308
|
+
}
|
|
133309
|
+
function buildTaskRecommendationNoticeContent(task, recommendations) {
|
|
133310
|
+
const title = task.title?.trim();
|
|
133311
|
+
const heading = title ? `## Recommendations from ${task.id} \u2014 ${title}` : `## Recommendations from ${task.id}`;
|
|
133312
|
+
return [
|
|
133313
|
+
heading,
|
|
133314
|
+
"",
|
|
133315
|
+
"These are optional, non-blocking out-of-scope proposals that were **not** executed.",
|
|
133316
|
+
"",
|
|
133317
|
+
...recommendations.map((recommendation) => `- **${recommendation.title}** \u2014 \`${recommendation.category}\`: ${recommendation.description}`),
|
|
133318
|
+
"",
|
|
133319
|
+
`Open ${task.id}'s **Recommendations** tab to review them. **Create task** files one through normal guarded intake.`
|
|
133320
|
+
].join("\n");
|
|
133321
|
+
}
|
|
133322
|
+
function buildTaskRecommendationNoticeIdempotencyKey(taskId, recommendations) {
|
|
133323
|
+
const ids = recommendations.map(({ id }) => id).sort().join("\n");
|
|
133324
|
+
const digest = createHash20("sha256").update(ids, "utf8").digest("hex").slice(0, 16);
|
|
133325
|
+
return `task-recommendation-notice:${taskId}:${digest}`;
|
|
133326
|
+
}
|
|
133327
|
+
async function notifyOperatorOfTaskRecommendations(store, task, recommendations, settings) {
|
|
133328
|
+
try {
|
|
133329
|
+
if (settings.recommendationMailboxNoticeEnabled === false || !recommendations?.length) return false;
|
|
133330
|
+
const mailbox = mailboxes2.get(store);
|
|
133331
|
+
if (!mailbox) return false;
|
|
133332
|
+
await mailbox.sendMessageOnce(
|
|
133333
|
+
{
|
|
133334
|
+
fromId: "system",
|
|
133335
|
+
fromType: "system",
|
|
133336
|
+
toId: DASHBOARD_USER_ID,
|
|
133337
|
+
toType: "user",
|
|
133338
|
+
type: "system",
|
|
133339
|
+
content: buildTaskRecommendationNoticeContent(task, recommendations),
|
|
133340
|
+
metadata: {
|
|
133341
|
+
kind: "task-recommendation-notice",
|
|
133342
|
+
taskId: task.id,
|
|
133343
|
+
recommendationCount: recommendations.length,
|
|
133344
|
+
recommendationIds: recommendations.map(({ id }) => id),
|
|
133345
|
+
categories: recommendations.map(({ category }) => category)
|
|
133346
|
+
}
|
|
133347
|
+
},
|
|
133348
|
+
buildTaskRecommendationNoticeIdempotencyKey(task.id, recommendations)
|
|
133349
|
+
);
|
|
133350
|
+
return true;
|
|
133351
|
+
} catch (error2) {
|
|
133352
|
+
noticeLog2.warn(
|
|
133353
|
+
`Operator recommendation notice failed for ${task.id}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
133354
|
+
);
|
|
133355
|
+
return false;
|
|
133356
|
+
}
|
|
133357
|
+
}
|
|
133358
|
+
var noticeLog2, mailboxes2;
|
|
133359
|
+
var init_task_recommendation_notice = __esm({
|
|
133360
|
+
"../core/src/task-recommendation-notice.ts"() {
|
|
133361
|
+
"use strict";
|
|
133362
|
+
init_logger2();
|
|
133363
|
+
init_types();
|
|
133364
|
+
noticeLog2 = createLogger2("task-recommendation-notice");
|
|
133365
|
+
mailboxes2 = /* @__PURE__ */ new WeakMap();
|
|
133366
|
+
}
|
|
133367
|
+
});
|
|
133368
|
+
|
|
133002
133369
|
// ../core/src/session-identity-registry.ts
|
|
133003
133370
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
133004
133371
|
import { resolve as resolve23 } from "node:path";
|
|
@@ -133848,6 +134215,8 @@ __export(src_exports, {
|
|
|
133848
134215
|
buildTaskDeleteNoticeContent: () => buildTaskDeleteNoticeContent,
|
|
133849
134216
|
buildTaskDeleteNoticeIdempotencyKey: () => buildTaskDeleteNoticeIdempotencyKey,
|
|
133850
134217
|
buildTaskLineageTrailer: () => buildTaskLineageTrailer,
|
|
134218
|
+
buildTaskRecommendationNoticeContent: () => buildTaskRecommendationNoticeContent,
|
|
134219
|
+
buildTaskRecommendationNoticeIdempotencyKey: () => buildTaskRecommendationNoticeIdempotencyKey,
|
|
133851
134220
|
buildToolOutputTruncationMarker: () => buildToolOutputTruncationMarker,
|
|
133852
134221
|
buildTriageHeartbeatGuidance: () => buildTriageHeartbeatGuidance,
|
|
133853
134222
|
buildTriageMemoryInstructions: () => buildTriageMemoryInstructions,
|
|
@@ -134178,6 +134547,7 @@ __export(src_exports, {
|
|
|
134178
134547
|
getTaskMergeBlocker: () => getTaskMergeBlocker,
|
|
134179
134548
|
getTaskMoveDisposer: () => getTaskMoveDisposer,
|
|
134180
134549
|
getTaskPriorityRank: () => getTaskPriorityRank,
|
|
134550
|
+
getTaskRecommendationNoticeMailbox: () => getTaskRecommendationNoticeMailbox,
|
|
134181
134551
|
getTemplatesForRole: () => getTemplatesForRole,
|
|
134182
134552
|
getTotalAgentActiveMs: () => getTotalAgentActiveMs,
|
|
134183
134553
|
getTrait: () => getTrait,
|
|
@@ -134428,6 +134798,7 @@ __export(src_exports, {
|
|
|
134428
134798
|
normalizeWorkflowPromptOverrides: () => normalizeWorkflowPromptOverrides,
|
|
134429
134799
|
normalizeWorkflowReviewFindings: () => normalizeWorkflowReviewFindings,
|
|
134430
134800
|
notifyOperatorOfNonOperatorDelete: () => notifyOperatorOfNonOperatorDelete,
|
|
134801
|
+
notifyOperatorOfTaskRecommendations: () => notifyOperatorOfTaskRecommendations,
|
|
134431
134802
|
overseerAdviceSeverityRank: () => overseerAdviceSeverityRank,
|
|
134432
134803
|
parseAgentManifest: () => parseAgentManifest,
|
|
134433
134804
|
parseCompanyArchive: () => parseCompanyArchive,
|
|
@@ -134537,6 +134908,7 @@ __export(src_exports, {
|
|
|
134537
134908
|
registerStepParser: () => registerStepParser,
|
|
134538
134909
|
registerTaskDeleteNoticeMailbox: () => registerTaskDeleteNoticeMailbox,
|
|
134539
134910
|
registerTaskMoveDisposer: () => registerTaskMoveDisposer,
|
|
134911
|
+
registerTaskRecommendationNoticeMailbox: () => registerTaskRecommendationNoticeMailbox,
|
|
134540
134912
|
registerTraitHookImpl: () => registerTraitHookImpl,
|
|
134541
134913
|
rekeyFallbackProjectPartition: () => rekeyFallbackProjectPartition,
|
|
134542
134914
|
releaseEmbeddedRuntimeLease: () => releaseEmbeddedRuntimeLease,
|
|
@@ -135164,6 +135536,7 @@ var init_src2 = __esm({
|
|
|
135164
135536
|
init_task_document_concurrency();
|
|
135165
135537
|
init_task_delete_attribution();
|
|
135166
135538
|
init_task_delete_notice();
|
|
135539
|
+
init_task_recommendation_notice();
|
|
135167
135540
|
init_session_identity_registry();
|
|
135168
135541
|
init_task_lifecycle_event_retention();
|
|
135169
135542
|
init_task_lifecycle_consumer_identity();
|
|
@@ -138534,7 +138907,7 @@ ${getErrorStderr(error2) ?? ""}`;
|
|
|
138534
138907
|
});
|
|
138535
138908
|
|
|
138536
138909
|
// ../engine/src/worktree/secrets-env-writer.ts
|
|
138537
|
-
import { createHash as
|
|
138910
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
138538
138911
|
import { execFile as execFile7 } from "node:child_process";
|
|
138539
138912
|
import { promises as fs5 } from "node:fs";
|
|
138540
138913
|
import path2 from "node:path";
|
|
@@ -138543,7 +138916,7 @@ function isValidFilename(filename) {
|
|
|
138543
138916
|
return !!filename && !filename.includes("/") && !filename.includes("\\") && !filename.includes("..") && !filename.includes("\0") && filename !== FINGERPRINT_FILE;
|
|
138544
138917
|
}
|
|
138545
138918
|
function sha2562(content) {
|
|
138546
|
-
return
|
|
138919
|
+
return createHash21("sha256").update(Buffer.from(content, "utf8")).digest("hex");
|
|
138547
138920
|
}
|
|
138548
138921
|
function quote(value) {
|
|
138549
138922
|
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t")}"`;
|
|
@@ -141206,11 +141579,11 @@ var init_planning_handoff_recovery = __esm({
|
|
|
141206
141579
|
// ../engine/src/plan-review-continuation.ts
|
|
141207
141580
|
async function seedPreReleasePlanReviewContinuation(store, task, ir2, options = {}) {
|
|
141208
141581
|
const node = resolvePreReleasePlanReviewNode(ir2);
|
|
141209
|
-
if (!node || node.column !== task.column) return { seeded: false };
|
|
141582
|
+
if (!node || node.column !== task.column) return { seeded: false, reason: "no-pre-release-plan-review" };
|
|
141210
141583
|
if (isTaskBlockedOnApproval(task)) return { seeded: false, reason: "awaiting-approval" };
|
|
141211
141584
|
if (task.paused === true || task.userPaused === true) return { seeded: false, reason: "paused" };
|
|
141212
141585
|
const items = await store.listWorkflowWorkItemsForTask(task.id);
|
|
141213
|
-
const active2 = items.filter((item2) => ACTIVE_WORKFLOW_WORK_ITEM_STATES.includes(item2.state));
|
|
141586
|
+
const active2 = items.filter((item2) => ACTIVE_WORKFLOW_WORK_ITEM_STATES.includes(item2.state) && item2.id !== options.retirePredecessorId);
|
|
141214
141587
|
if (active2.length > 0) return { seeded: false, reason: "active-continuation" };
|
|
141215
141588
|
const continuationSequence = items.length;
|
|
141216
141589
|
const input = {
|
|
@@ -141226,6 +141599,9 @@ async function seedPreReleasePlanReviewContinuation(store, task, ir2, options =
|
|
|
141226
141599
|
targetColumn: task.column,
|
|
141227
141600
|
irHash: computeWorkflowIrPin(ir2, node.id).irHash
|
|
141228
141601
|
};
|
|
141602
|
+
if (options.retirePredecessorId) {
|
|
141603
|
+
return store.seedStrandedPlanReviewContinuation(input, { retirePredecessorId: options.retirePredecessorId });
|
|
141604
|
+
}
|
|
141229
141605
|
if (options.atomic) return store.seedStrandedPlanReviewContinuation(input);
|
|
141230
141606
|
const item = await store.replaceActiveTaskWorkflowContinuation(input);
|
|
141231
141607
|
return { seeded: true, workItemId: item.id };
|
|
@@ -141265,7 +141641,7 @@ var init_plan_review_continuation = __esm({
|
|
|
141265
141641
|
});
|
|
141266
141642
|
|
|
141267
141643
|
// ../engine/src/execution/hold-release.ts
|
|
141268
|
-
import { createHash as
|
|
141644
|
+
import { createHash as createHash22 } from "node:crypto";
|
|
141269
141645
|
import { readFile as readFile33 } from "node:fs/promises";
|
|
141270
141646
|
function findColumn2(ir2, columnId) {
|
|
141271
141647
|
if (ir2.version !== "v2") return void 0;
|
|
@@ -141303,9 +141679,9 @@ async function checkAndRecordUnplannedExecutionBlock(store, task, ir2) {
|
|
|
141303
141679
|
promptContent = "";
|
|
141304
141680
|
}
|
|
141305
141681
|
}
|
|
141306
|
-
const promptMarker = promptContent.length > 0 ?
|
|
141682
|
+
const promptMarker = promptContent.length > 0 ? createHash22("sha256").update(promptContent).digest("hex") : "missing";
|
|
141307
141683
|
const dependencies = [...task.dependencies ?? []].sort();
|
|
141308
|
-
const episode =
|
|
141684
|
+
const episode = createHash22("sha256").update(JSON.stringify({
|
|
141309
141685
|
planReviewNode,
|
|
141310
141686
|
promptMarker,
|
|
141311
141687
|
dependencies,
|
|
@@ -144276,32 +144652,36 @@ var init_scheduler = __esm({
|
|
|
144276
144652
|
const hierarchy = await missionStore.getMissionWithHierarchy(mission.id);
|
|
144277
144653
|
if (!hierarchy) continue;
|
|
144278
144654
|
for (const slice of hierarchy.milestones.flatMap((milestone) => milestone.slices).filter((slice2) => slice2.status === "active")) {
|
|
144279
|
-
|
|
144280
|
-
|
|
144281
|
-
|
|
144282
|
-
|
|
144283
|
-
|
|
144284
|
-
|
|
144285
|
-
|
|
144655
|
+
try {
|
|
144656
|
+
const superseded = await missionStore.reconcileSupersededGeneratedFixFeatures(slice.id);
|
|
144657
|
+
fixed += superseded.supersededCount;
|
|
144658
|
+
if (superseded.supersededCount > 0) {
|
|
144659
|
+
const refreshed = await missionStore.getSlice(slice.id);
|
|
144660
|
+
if (refreshed?.status === "complete") {
|
|
144661
|
+
await this.onSliceComplete(refreshed);
|
|
144662
|
+
continue;
|
|
144663
|
+
}
|
|
144286
144664
|
}
|
|
144287
|
-
|
|
144288
|
-
|
|
144289
|
-
|
|
144290
|
-
|
|
144291
|
-
|
|
144292
|
-
|
|
144293
|
-
|
|
144294
|
-
|
|
144295
|
-
|
|
144665
|
+
const listFeatures2 = missionStore.listFeatures;
|
|
144666
|
+
const features = listFeatures2 ? await listFeatures2.call(missionStore, slice.id) : slice.features;
|
|
144667
|
+
const supersededFeatureIds = new Set(superseded.featureIds ?? []);
|
|
144668
|
+
const autoTriage = mission.autopilotEnabled === true || mission.autoAdvance === true;
|
|
144669
|
+
for (const feature of features) {
|
|
144670
|
+
if (supersededFeatureIds.has(feature.id) || feature.taskId || !autoTriage || feature.status === "blocked") continue;
|
|
144671
|
+
if (feature.status !== "defined" && this.isGeneratedFixFeature(feature)) {
|
|
144672
|
+
await missionStore.updateFeature(feature.id, { status: "blocked", loopState: "blocked", taskId: void 0 });
|
|
144673
|
+
fixed++;
|
|
144674
|
+
continue;
|
|
144675
|
+
}
|
|
144676
|
+
if (feature.status !== "defined" && feature.status !== "triaged" && feature.status !== "in-progress") continue;
|
|
144677
|
+
const ready = feature.status === "defined" ? feature : await missionStore.updateFeature(feature.id, { status: "defined", loopState: "idle", taskId: void 0 });
|
|
144678
|
+
if (ready !== feature) fixed++;
|
|
144679
|
+
const triaged = await missionStore.triageFeature(ready.id);
|
|
144296
144680
|
fixed++;
|
|
144297
|
-
|
|
144681
|
+
if (triaged.taskId) await this.emitStrandedFeatureTriageAudit(mission.id, slice.id, triaged.id, triaged.taskId);
|
|
144298
144682
|
}
|
|
144299
|
-
|
|
144300
|
-
|
|
144301
|
-
if (ready !== feature) fixed++;
|
|
144302
|
-
const triaged = await missionStore.triageFeature(ready.id);
|
|
144303
|
-
fixed++;
|
|
144304
|
-
if (triaged.taskId) await this.emitStrandedFeatureTriageAudit(mission.id, slice.id, triaged.id, triaged.taskId);
|
|
144683
|
+
} catch (error2) {
|
|
144684
|
+
schedulerLog.error(`Error during active mission recovery reconciliation for slice ${slice.id}:`, error2);
|
|
144305
144685
|
}
|
|
144306
144686
|
}
|
|
144307
144687
|
}
|
|
@@ -144342,7 +144722,7 @@ var init_scheduler = __esm({
|
|
|
144342
144722
|
});
|
|
144343
144723
|
|
|
144344
144724
|
// ../engine/src/agents/agent-logger.ts
|
|
144345
|
-
import { createHash as
|
|
144725
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
144346
144726
|
function truncateToolResultDetail(value) {
|
|
144347
144727
|
if (value.length <= TOOL_RESULT_DETAIL_LIMIT) return value;
|
|
144348
144728
|
return `${value.slice(0, TOOL_RESULT_DETAIL_LIMIT)}${TOOL_RESULT_DETAIL_TRUNCATION_NOTICE}`;
|
|
@@ -144431,7 +144811,7 @@ function summarizeToolArgs(name2, args) {
|
|
|
144431
144811
|
const json2 = JSON.stringify(args);
|
|
144432
144812
|
if (!json2 || json2 === "{}" || json2 === "[]") return void 0;
|
|
144433
144813
|
if (json2.length <= STRUCTURED_ARG_SUMMARY_MAX) return json2;
|
|
144434
|
-
const hash3 =
|
|
144814
|
+
const hash3 = createHash23("sha256").update(json2).digest("hex").slice(0, STRUCTURED_ARG_HASH_HEX_LEN);
|
|
144435
144815
|
const suffix = `\u2026#${hash3}`;
|
|
144436
144816
|
const keep = Math.max(0, STRUCTURED_ARG_SUMMARY_MAX - suffix.length);
|
|
144437
144817
|
return `${json2.slice(0, keep)}${suffix}`;
|
|
@@ -148783,7 +149163,13 @@ var init_gating_classifications = __esm({
|
|
|
148783
149163
|
"fn_post_room_message",
|
|
148784
149164
|
"fn_update_identity",
|
|
148785
149165
|
"fn_reflect_on_performance",
|
|
148786
|
-
|
|
149166
|
+
/*
|
|
149167
|
+
FNXC:ToolGovernance 2026-08-12-22:11:
|
|
149168
|
+
fn_agent_read_evaluations is a subtree-scoped read. Authorization is enforced by
|
|
149169
|
+
the extension tool's getChainOfCommand boundary, not by this action classifier.
|
|
149170
|
+
*/
|
|
149171
|
+
"fn_read_evaluations",
|
|
149172
|
+
"fn_agent_read_evaluations"
|
|
148787
149173
|
]);
|
|
148788
149174
|
COORDINATION_EXEMPT_TOOLS = [
|
|
148789
149175
|
"read",
|
|
@@ -148843,6 +149229,8 @@ var init_gating_classifications = __esm({
|
|
|
148843
149229
|
"fn_post_room_message",
|
|
148844
149230
|
"fn_memory_append",
|
|
148845
149231
|
"fn_read_evaluations",
|
|
149232
|
+
// 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.
|
|
149233
|
+
"fn_agent_read_evaluations",
|
|
148846
149234
|
"fn_update_identity",
|
|
148847
149235
|
"fn_reflect_on_performance"
|
|
148848
149236
|
];
|
|
@@ -148867,7 +149255,7 @@ var init_gating_classifications = __esm({
|
|
|
148867
149255
|
});
|
|
148868
149256
|
|
|
148869
149257
|
// ../engine/src/agents/agent-action-gate.ts
|
|
148870
|
-
import { createHash as
|
|
149258
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
148871
149259
|
function getExemptTools() {
|
|
148872
149260
|
if (!_exemptTools) {
|
|
148873
149261
|
_exemptTools = new Set(DEFAULT_EXEMPT_TOOLS);
|
|
@@ -148901,7 +149289,7 @@ function evaluateAgentActionGate(params) {
|
|
|
148901
149289
|
if (params.toolName === "bash") {
|
|
148902
149290
|
const command = extractShellCommand(args);
|
|
148903
149291
|
const git7 = classifyGitCommand(command);
|
|
148904
|
-
resourceId = command ? `cmd:${
|
|
149292
|
+
resourceId = command ? `cmd:${createHash24("sha256").update(command).digest("hex").slice(0, 16)}` : void 0;
|
|
148905
149293
|
if (git7?.write) {
|
|
148906
149294
|
category = "git_write";
|
|
148907
149295
|
operation = git7.operation;
|
|
@@ -177423,7 +177811,7 @@ var init_code_node_runner = __esm({
|
|
|
177423
177811
|
// ../engine/src/agent-tools.ts
|
|
177424
177812
|
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";
|
|
177425
177813
|
import { existsSync as existsSync52 } from "node:fs";
|
|
177426
|
-
import { createHash as
|
|
177814
|
+
import { createHash as createHash25, randomUUID as randomUUID46 } from "node:crypto";
|
|
177427
177815
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
177428
177816
|
import { extname as extname4, isAbsolute as isAbsolute14, join as join66, relative as relative14, resolve as resolve37, sep as sep10 } from "node:path";
|
|
177429
177817
|
import { Type as Type2 } from "@earendil-works/pi-ai";
|
|
@@ -177467,7 +177855,7 @@ async function readAgentMemoryWorkspaceLongTerm(rootDir, agentId) {
|
|
|
177467
177855
|
}
|
|
177468
177856
|
}
|
|
177469
177857
|
function qmdAgentMemoryCollectionName2(rootDir, agentId) {
|
|
177470
|
-
const hash3 =
|
|
177858
|
+
const hash3 = createHash25("sha1").update(`${rootDir}:${agentId}`).digest("hex").slice(0, 12);
|
|
177471
177859
|
return `fusion-agent-memory-${sanitizeAgentMemoryId(agentId).toLowerCase()}-${hash3}`;
|
|
177472
177860
|
}
|
|
177473
177861
|
function buildQmdAgentMemoryCollectionAddArgs(rootDir, agentId) {
|
|
@@ -187582,7 +187970,7 @@ var init_verification_utils = __esm({
|
|
|
187582
187970
|
|
|
187583
187971
|
// ../engine/src/merge/merge-dependency-sync.ts
|
|
187584
187972
|
import { exec as exec25 } from "node:child_process";
|
|
187585
|
-
import { createHash as
|
|
187973
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
187586
187974
|
import { existsSync as existsSync54, readFileSync as readFileSync17, writeFileSync as writeFileSync6 } from "node:fs";
|
|
187587
187975
|
import { join as join68 } from "node:path";
|
|
187588
187976
|
import { promisify as promisify35 } from "node:util";
|
|
@@ -187609,7 +187997,7 @@ function computeLockfileHash(rootDir) {
|
|
|
187609
187997
|
const p2 = join68(rootDir, name2);
|
|
187610
187998
|
if (existsSync54(p2)) {
|
|
187611
187999
|
try {
|
|
187612
|
-
return
|
|
188000
|
+
return createHash27("sha256").update(readFileSync17(p2)).digest("hex");
|
|
187613
188001
|
} catch {
|
|
187614
188002
|
return null;
|
|
187615
188003
|
}
|
|
@@ -190146,7 +190534,7 @@ var init_mesh_lease_manager = __esm({
|
|
|
190146
190534
|
});
|
|
190147
190535
|
|
|
190148
190536
|
// ../engine/src/merge/merger-integration-worktree.ts
|
|
190149
|
-
import { createHash as
|
|
190537
|
+
import { createHash as createHash28 } from "node:crypto";
|
|
190150
190538
|
import { exec as exec31, execFile as execFile22 } from "node:child_process";
|
|
190151
190539
|
import { promisify as promisify45 } from "node:util";
|
|
190152
190540
|
function quoteAutostashArg(value) {
|
|
@@ -190269,7 +190657,7 @@ async function gitDirtyFingerprintLocal(rootDir) {
|
|
|
190269
190657
|
)
|
|
190270
190658
|
]);
|
|
190271
190659
|
if (!diffOut && !statusOut) return "";
|
|
190272
|
-
return
|
|
190660
|
+
return createHash28("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
190273
190661
|
} catch {
|
|
190274
190662
|
return "";
|
|
190275
190663
|
}
|
|
@@ -191255,7 +191643,7 @@ import { execSync as execSync5, exec as exec33 } from "node:child_process";
|
|
|
191255
191643
|
import * as childProcess4 from "node:child_process";
|
|
191256
191644
|
import { promisify as promisify48 } from "node:util";
|
|
191257
191645
|
import { existsSync as existsSync57, readFileSync as readFileSync20, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
191258
|
-
import { createHash as
|
|
191646
|
+
import { createHash as createHash29 } from "node:crypto";
|
|
191259
191647
|
import { join as join72, resolve as resolve43 } from "node:path";
|
|
191260
191648
|
import { hostname as hostname2 } from "node:os";
|
|
191261
191649
|
import { Type as Type4 } from "typebox";
|
|
@@ -191503,7 +191891,7 @@ async function gitDirtyFingerprint(rootDir) {
|
|
|
191503
191891
|
)
|
|
191504
191892
|
]);
|
|
191505
191893
|
if (!diffOut && !statusOut) return "";
|
|
191506
|
-
return
|
|
191894
|
+
return createHash29("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
191507
191895
|
} catch {
|
|
191508
191896
|
return "";
|
|
191509
191897
|
}
|
|
@@ -200390,7 +200778,7 @@ import { promisify as promisify79 } from "node:util";
|
|
|
200390
200778
|
// ../engine/src/runtimes/in-process-runtime.ts
|
|
200391
200779
|
init_src2();
|
|
200392
200780
|
init_scheduler();
|
|
200393
|
-
import { createHash as
|
|
200781
|
+
import { createHash as createHash32 } from "node:crypto";
|
|
200394
200782
|
import { EventEmitter as EventEmitter27 } from "node:events";
|
|
200395
200783
|
|
|
200396
200784
|
// ../engine/src/executor/public-reexports.ts
|
|
@@ -203117,7 +203505,7 @@ init_agent_tools();
|
|
|
203117
203505
|
init_agent_logger();
|
|
203118
203506
|
init_agent_usage_telemetry();
|
|
203119
203507
|
import { Type as Type3 } from "@earendil-works/pi-ai";
|
|
203120
|
-
import { createHash as
|
|
203508
|
+
import { createHash as createHash26 } from "node:crypto";
|
|
203121
203509
|
|
|
203122
203510
|
// ../engine/src/agents/approval-mail.ts
|
|
203123
203511
|
init_src2();
|
|
@@ -204745,7 +205133,7 @@ function truncatePrompt(text2, maxChars) {
|
|
|
204745
205133
|
... (truncated, ${text2.length} chars)`;
|
|
204746
205134
|
}
|
|
204747
205135
|
function shortContentHash(value) {
|
|
204748
|
-
return
|
|
205136
|
+
return createHash26("sha256").update(value).digest("hex").slice(0, 8);
|
|
204749
205137
|
}
|
|
204750
205138
|
function buildIdentitySnapshot(args) {
|
|
204751
205139
|
const { agent, resolvedInstructions, workspaceMemory } = args;
|
|
@@ -233233,6 +233621,34 @@ init_effective_settings();
|
|
|
233233
233621
|
init_run_audit();
|
|
233234
233622
|
init_logger();
|
|
233235
233623
|
init_lifecycle_columns();
|
|
233624
|
+
|
|
233625
|
+
// ../engine/src/executor/completion-recommendation-notice.ts
|
|
233626
|
+
init_src2();
|
|
233627
|
+
var pendingNotices = /* @__PURE__ */ new Set();
|
|
233628
|
+
function dispatchAcceptedCompletionRecommendationNotice(args) {
|
|
233629
|
+
if (!args.recommendations?.length) return;
|
|
233630
|
+
const pending = (async () => {
|
|
233631
|
+
const settings = args.settings ?? await args.store.getSettings();
|
|
233632
|
+
const task = await args.store.getTask(args.taskId);
|
|
233633
|
+
if (!task || task.deletedAt) return;
|
|
233634
|
+
await notifyOperatorOfTaskRecommendations(
|
|
233635
|
+
args.store,
|
|
233636
|
+
{ id: args.taskId, title: args.taskTitle ?? task.title },
|
|
233637
|
+
args.recommendations,
|
|
233638
|
+
settings
|
|
233639
|
+
);
|
|
233640
|
+
})();
|
|
233641
|
+
pendingNotices.add(pending);
|
|
233642
|
+
void pending.catch((error2) => {
|
|
233643
|
+
args.log?.warn(
|
|
233644
|
+
`Failed to dispatch recommendation mailbox notice for ${args.taskId}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
233645
|
+
);
|
|
233646
|
+
}).finally(() => {
|
|
233647
|
+
pendingNotices.delete(pending);
|
|
233648
|
+
});
|
|
233649
|
+
}
|
|
233650
|
+
|
|
233651
|
+
// ../engine/src/executor/create-task-done-tool.ts
|
|
233236
233652
|
function createTaskDoneTool(deps, taskId, worktreePath, promptContent, codeReviewVerdicts, onDone, audit) {
|
|
233237
233653
|
const store = deps.store;
|
|
233238
233654
|
return {
|
|
@@ -233567,6 +233983,16 @@ ${rerunSuffix}`
|
|
|
233567
233983
|
bulkCompletionRefusalAt: null
|
|
233568
233984
|
});
|
|
233569
233985
|
await store.logEntry(taskId, "Task marked done by agent", void 0, deps.getRunContextFor(taskId));
|
|
233986
|
+
if (completionRecommendations !== void 0) {
|
|
233987
|
+
dispatchAcceptedCompletionRecommendationNotice({
|
|
233988
|
+
store,
|
|
233989
|
+
taskId,
|
|
233990
|
+
taskTitle: task.title,
|
|
233991
|
+
recommendations: completionRecommendations,
|
|
233992
|
+
settings,
|
|
233993
|
+
log: executorLog
|
|
233994
|
+
});
|
|
233995
|
+
}
|
|
233570
233996
|
const latestTask = await store.getTask(taskId);
|
|
233571
233997
|
let latestColumn = latestTask.column;
|
|
233572
233998
|
if (latestColumn === await resolveReboundColumnFor(store, taskId)) {
|
|
@@ -245399,6 +245825,16 @@ ${rerunSuffix}` });
|
|
|
245399
245825
|
if (latestColumn === await resolveWipTargetForTask(deps.store, task.id) && !hardPauseActive && beforeWatchdog && !beforeWatchdog.deletedAt && !(rejectIfPaused && (beforeWatchdog.paused || beforeWatchdog.userPaused))) {
|
|
245400
245826
|
deps.scheduleCompletedTaskWatchdog(task.id, "fn_task_done");
|
|
245401
245827
|
}
|
|
245828
|
+
if (recommendations !== void 0) {
|
|
245829
|
+
dispatchAcceptedCompletionRecommendationNotice({
|
|
245830
|
+
store: deps.store,
|
|
245831
|
+
taskId: task.id,
|
|
245832
|
+
taskTitle: task.title,
|
|
245833
|
+
recommendations,
|
|
245834
|
+
settings,
|
|
245835
|
+
log: executorLog
|
|
245836
|
+
});
|
|
245837
|
+
}
|
|
245402
245838
|
return { completed: true, hardPauseActive };
|
|
245403
245839
|
} catch (error2) {
|
|
245404
245840
|
await restoreNoCommitsExpected();
|
|
@@ -250612,7 +251048,7 @@ init_notifier();
|
|
|
250612
251048
|
|
|
250613
251049
|
// ../engine/src/healing/stuck-task-detector.ts
|
|
250614
251050
|
init_logger();
|
|
250615
|
-
import { createHash as
|
|
251051
|
+
import { createHash as createHash30 } from "node:crypto";
|
|
250616
251052
|
var stuckLog = createLogger("stuck-detector");
|
|
250617
251053
|
var LOOP_ACTIVITY_THRESHOLD = 60;
|
|
250618
251054
|
var LOOP_IGNORED_STEP_MIN = 10;
|
|
@@ -250623,7 +251059,7 @@ var TOOL_DETAIL_HASH_HEX_LEN = 16;
|
|
|
250623
251059
|
var NO_PROGRESS_CHURN_THRESHOLD = 25;
|
|
250624
251060
|
var VERIFICATION_DEADLINE_GRACE_MS = 5e3;
|
|
250625
251061
|
function hashToolDetail(detail) {
|
|
250626
|
-
return
|
|
251062
|
+
return createHash30("sha256").update(detail).digest("hex").slice(0, TOOL_DETAIL_HASH_HEX_LEN);
|
|
250627
251063
|
}
|
|
250628
251064
|
function buildToolFingerprint(toolName, toolDetail) {
|
|
250629
251065
|
const name2 = toolName.trim().toLowerCase() || "tool";
|
|
@@ -253373,7 +253809,7 @@ var MissionAutopilot = class {
|
|
|
253373
253809
|
// ../engine/src/missions/mission-execution-loop.ts
|
|
253374
253810
|
init_src2();
|
|
253375
253811
|
import { EventEmitter as EventEmitter26 } from "node:events";
|
|
253376
|
-
import { createHash as
|
|
253812
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
253377
253813
|
|
|
253378
253814
|
// ../engine/src/missions/mission-verification.ts
|
|
253379
253815
|
init_sandbox();
|
|
@@ -253445,7 +253881,7 @@ var MAX_VALIDATION_RESPONSE_BYTES = 256 * 1024;
|
|
|
253445
253881
|
var MAX_VALIDATION_JSON_CANDIDATES = 8;
|
|
253446
253882
|
var VALIDATION_FAILURE_BUDGET_PER_FINGERPRINT = 3;
|
|
253447
253883
|
function fingerprintMissionValidationInput(landedSha, provider, modelId, systemPrompt, userPrompt) {
|
|
253448
|
-
return
|
|
253884
|
+
return createHash31("sha256").update(Buffer.from(JSON.stringify(["mission-validation-input-v1", landedSha, provider, modelId, systemPrompt, userPrompt]), "utf8")).digest("hex");
|
|
253449
253885
|
}
|
|
253450
253886
|
var MissionExecutionLoop = class extends EventEmitter26 {
|
|
253451
253887
|
running = false;
|
|
@@ -257161,7 +257597,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
257161
257597
|
}
|
|
257162
257598
|
return;
|
|
257163
257599
|
}
|
|
257164
|
-
const duplicateReport = { outcome: "parked" };
|
|
257600
|
+
const duplicateReport = { outcome: "parked", planningWorkItemId };
|
|
257165
257601
|
if (await this.tryFinalizeExplicitDuplicateMarker(task, written, settings, {
|
|
257166
257602
|
isReplan,
|
|
257167
257603
|
feedback
|
|
@@ -257180,6 +257616,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
257180
257616
|
isReplan,
|
|
257181
257617
|
feedback
|
|
257182
257618
|
});
|
|
257619
|
+
finalizeReport.planningWorkItemId = planningWorkItemId;
|
|
257183
257620
|
this.options.onSpecifyComplete?.(task, finalizeReport);
|
|
257184
257621
|
} finally {
|
|
257185
257622
|
this.activeSessions.delete(task.id);
|
|
@@ -258754,11 +259191,46 @@ async function reactToSpecificationComplete(deps) {
|
|
|
258754
259191
|
return;
|
|
258755
259192
|
}
|
|
258756
259193
|
deps.log(`Specified ${deps.taskId} \u2192 todo`);
|
|
258757
|
-
const
|
|
258758
|
-
|
|
258759
|
-
|
|
258760
|
-
|
|
258761
|
-
|
|
259194
|
+
const sleep7 = deps.sleep ?? ((ms2) => new Promise((resolve47) => setTimeout(resolve47, ms2)));
|
|
259195
|
+
const QUIET_PARK_REASONS = /* @__PURE__ */ new Set([
|
|
259196
|
+
"no-pre-release-plan-review",
|
|
259197
|
+
"awaiting-approval",
|
|
259198
|
+
"paused",
|
|
259199
|
+
"plan-review-passed"
|
|
259200
|
+
]);
|
|
259201
|
+
const RETRY_DELAYS_MS2 = [1e3, 5e3];
|
|
259202
|
+
for (let attempt = 0; ; attempt++) {
|
|
259203
|
+
let failure = null;
|
|
259204
|
+
try {
|
|
259205
|
+
const live = await deps.getTask(deps.taskId);
|
|
259206
|
+
if (!live || live.paused || live.userPaused) return;
|
|
259207
|
+
if (live.status === "needs-replan") {
|
|
259208
|
+
deps.log(`Plan Review handoff for ${deps.taskId} not armed (needs-replan)`);
|
|
259209
|
+
return;
|
|
259210
|
+
}
|
|
259211
|
+
const ir2 = await deps.resolveIr(live.id);
|
|
259212
|
+
const result = await deps.seed(live, ir2);
|
|
259213
|
+
if (result.seeded) {
|
|
259214
|
+
deps.kick();
|
|
259215
|
+
return;
|
|
259216
|
+
}
|
|
259217
|
+
if (result.reason && QUIET_PARK_REASONS.has(result.reason)) {
|
|
259218
|
+
deps.log(`Plan Review handoff for ${deps.taskId} not armed (${result.reason})`);
|
|
259219
|
+
return;
|
|
259220
|
+
}
|
|
259221
|
+
failure = result.reason ?? "not-seeded";
|
|
259222
|
+
} catch (error2) {
|
|
259223
|
+
failure = error2 instanceof Error ? error2.message : String(error2);
|
|
259224
|
+
}
|
|
259225
|
+
if (attempt >= RETRY_DELAYS_MS2.length) {
|
|
259226
|
+
deps.warn(
|
|
259227
|
+
`Plan Review handoff for ${deps.taskId} failed after ${attempt + 1} attempts (${failure}) \u2014 stranded-continuation self-healing will recover it`
|
|
259228
|
+
);
|
|
259229
|
+
return;
|
|
259230
|
+
}
|
|
259231
|
+
deps.warn(`Plan Review handoff for ${deps.taskId} did not seed (${failure}) \u2014 retrying`);
|
|
259232
|
+
await sleep7(RETRY_DELAYS_MS2[attempt]);
|
|
259233
|
+
}
|
|
258762
259234
|
}
|
|
258763
259235
|
async function drainDuePlanningContinuations(deps) {
|
|
258764
259236
|
const items = await deps.listDue();
|
|
@@ -258895,7 +259367,7 @@ function stableNotificationJson(value) {
|
|
|
258895
259367
|
return `{${fields.join(",")}}`;
|
|
258896
259368
|
}
|
|
258897
259369
|
function buildCliAgentNotificationDedupeKey(input) {
|
|
258898
|
-
const notificationFingerprint =
|
|
259370
|
+
const notificationFingerprint = createHash32("sha256").update(stableNotificationJson(input.info.notification ?? null)).digest("hex").slice(0, 16);
|
|
258899
259371
|
const waitingEpoch = input.session?.updatedAt ?? "unknown-waiting-epoch";
|
|
258900
259372
|
return [
|
|
258901
259373
|
"cli-agent",
|
|
@@ -259007,6 +259479,8 @@ var InProcessRuntime = class extends EventEmitter27 {
|
|
|
259007
259479
|
messageStore;
|
|
259008
259480
|
/** FNXC:TaskDeleteNotice 2026-07-26-16:10: identity-guarded teardown for the delete-notice mailbox seam. */
|
|
259009
259481
|
unregisterTaskDeleteNoticeMailbox;
|
|
259482
|
+
/** FNXC:TaskRecommendations 2026-08-13-03:56: identity-guarded teardown for the store-scoped recommendation notice seam. */
|
|
259483
|
+
unregisterTaskRecommendationNoticeMailbox;
|
|
259010
259484
|
chatStore;
|
|
259011
259485
|
detachAgentLinkSync;
|
|
259012
259486
|
/**
|
|
@@ -259065,7 +259539,8 @@ var InProcessRuntime = class extends EventEmitter27 {
|
|
|
259065
259539
|
createTaskStoreForBackend: createTaskStoreForBackend2,
|
|
259066
259540
|
buildConsumerId: buildConsumerId2,
|
|
259067
259541
|
createProjectScopedPluginMcpProvider: createProjectScopedPluginMcpProvider2,
|
|
259068
|
-
registerTaskDeleteNoticeMailbox: registerTaskDeleteNoticeMailbox2
|
|
259542
|
+
registerTaskDeleteNoticeMailbox: registerTaskDeleteNoticeMailbox2,
|
|
259543
|
+
registerTaskRecommendationNoticeMailbox: registerTaskRecommendationNoticeMailbox2
|
|
259069
259544
|
} = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
259070
259545
|
if (this.config.externalTaskStore) {
|
|
259071
259546
|
this.taskStore = this.config.externalTaskStore;
|
|
@@ -259124,6 +259599,10 @@ var InProcessRuntime = class extends EventEmitter27 {
|
|
|
259124
259599
|
this.taskStore,
|
|
259125
259600
|
this.messageStore
|
|
259126
259601
|
);
|
|
259602
|
+
this.unregisterTaskRecommendationNoticeMailbox = registerTaskRecommendationNoticeMailbox2(
|
|
259603
|
+
this.taskStore,
|
|
259604
|
+
this.messageStore
|
|
259605
|
+
);
|
|
259127
259606
|
await yieldEventLoop4();
|
|
259128
259607
|
const pluginLayer = this.taskStore.getAsyncLayer();
|
|
259129
259608
|
if (!pluginLayer) {
|
|
@@ -259615,9 +260094,19 @@ var InProcessRuntime = class extends EventEmitter27 {
|
|
|
259615
260094
|
outcome: report2.outcome,
|
|
259616
260095
|
getTask: (id) => Promise.resolve(this.taskStore.getTask(id)),
|
|
259617
260096
|
resolveIr: (id) => resolveWorkflowIrForTask(this.taskStore, id),
|
|
259618
|
-
|
|
260097
|
+
/*
|
|
260098
|
+
FNXC:PlanningHandoffAtomicity 2026-08-13-03:49:
|
|
260099
|
+
The report carries the planning session's own durable work item id so the
|
|
260100
|
+
seeder can retire that exact predecessor row atomically with the successor
|
|
260101
|
+
install. Without it the seeder raced triage's finally-block terminal
|
|
260102
|
+
transition and bailed on its own caller (529 stranded cards in 18 days).
|
|
260103
|
+
*/
|
|
260104
|
+
seed: (task, ir2) => seedPreReleasePlanReviewContinuation(this.taskStore, task, ir2, {
|
|
260105
|
+
retirePredecessorId: report2.planningWorkItemId
|
|
260106
|
+
}),
|
|
259619
260107
|
kick: () => this.kickWorkflowContinuationProcessor(),
|
|
259620
|
-
log: (message) => runtimeLog.log(message)
|
|
260108
|
+
log: (message) => runtimeLog.log(message),
|
|
260109
|
+
warn: (message) => runtimeLog.warn(message)
|
|
259621
260110
|
}).catch((error2) => {
|
|
259622
260111
|
runtimeLog.error(`Failed to start Todo plan review for ${t.id}:`, error2);
|
|
259623
260112
|
});
|
|
@@ -259905,6 +260394,8 @@ var InProcessRuntime = class extends EventEmitter27 {
|
|
|
259905
260394
|
this.backendShutdown = void 0;
|
|
259906
260395
|
this.unregisterTaskDeleteNoticeMailbox?.();
|
|
259907
260396
|
this.unregisterTaskDeleteNoticeMailbox = void 0;
|
|
260397
|
+
this.unregisterTaskRecommendationNoticeMailbox?.();
|
|
260398
|
+
this.unregisterTaskRecommendationNoticeMailbox = void 0;
|
|
259908
260399
|
let stopError;
|
|
259909
260400
|
try {
|
|
259910
260401
|
if (this.workflowContinuationTimer) {
|