@runfusion/fusion 0.75.1-beta.1 → 0.75.1-beta.2
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 +264 -136
- package/dist/child-process-worker.js +138 -38
- package/dist/client/.vite/manifest.json +253 -253
- package/dist/client/assets/{AgentDetailView-CE_7nvDT.js → AgentDetailView-ltOG8f0-.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-DYr3dk5X.js → AgentPermissionPolicyEditor-CC_rrbbG.js} +1 -1
- package/dist/client/assets/{AgentsView-DZoYoiaD.js → AgentsView-DWUdi27N.js} +3 -3
- package/dist/client/assets/{ChatView-BE9zMzYZ.js → ChatView-mFKfoegS.js} +1 -1
- package/dist/client/assets/{CommandCenter-DnLsp4_S.js → CommandCenter-C2wvDq_N.js} +1 -1
- package/dist/client/assets/{DevServerView-CI-3j-lH.js → DevServerView-0MWEJM7o.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-D1ADu0Av.js → DirectoryPicker-BjMPhCdh.js} +1 -1
- package/dist/client/assets/{DocumentsView-CF8y1gob.js → DocumentsView-ckH3rjmd.js} +1 -1
- package/dist/client/assets/{EvalsView-C9vLiM2_.js → EvalsView-NyA644VF.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CX_2Hjh0.js → ExperimentalAgentOnboardingModal-D0ZfbBRN.js} +1 -1
- package/dist/client/assets/{GoalsView-DJIA3k8q.js → GoalsView-Ctt5P_yo.js} +1 -1
- package/dist/client/assets/{InsightsView--TCeutLO.js → InsightsView-NDp0bdNB.js} +1 -1
- package/dist/client/assets/{MemoryView-Btp4m7pK.js → MemoryView-BKbA4Bm4.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-DXdfh-Uf.js → PiExtensionsManager-V3AFWMHm.js} +1 -1
- package/dist/client/assets/{PluginManager-BDFelFY6.js → PluginManager-D88G_TZh.js} +1 -1
- package/dist/client/assets/{PullRequestView-TSNKGSAg.js → PullRequestView-DQQmFFYC.js} +1 -1
- package/dist/client/assets/{ReportModal-DhXMNHDL.js → ReportModal-Clh1S8RF.js} +1 -1
- package/dist/client/assets/{ResearchView-0w30HikQ.js → ResearchView-kxvq4zp5.js} +1 -1
- package/dist/client/assets/SecretsView-Dm0Vk8SA.js +1 -0
- package/dist/client/assets/{SessionTerminal-CF6_uy2u.js → SessionTerminal-DJO4JTEX.js} +1 -1
- package/dist/client/assets/{SettingsModal-BMAPX_7v.js → SettingsModal-BN5mL_ym.js} +1 -1
- package/dist/client/assets/SettingsModal-CTf5voEW.js +21 -0
- package/dist/client/assets/{SettingsTextareaRow-LqXxpJl5.js → SettingsTextareaRow-CvKszqO-.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-D1ZvGOcK.js → SetupWizardModal-D5hVZh1G.js} +2 -2
- package/dist/client/assets/{SkillsView-CfO5B7SO.js → SkillsView-DQVz21w2.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-CjdK9fFS.js → WorkflowNodeEditor-CpKIi6Tb.js} +1 -1
- package/dist/client/assets/{agent-import-generation-DqTzyLOZ.js → agent-import-generation-DGUNF3nd.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-CHkolL_b.js → architectureDiagram-3BPJPVTR-CV83wubP.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-BFRYQi8H.js → blockDiagram-GPEHLZMM-CNQsA3dD.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-D9mMEYbR.js → c4Diagram-AAUBKEIU-CXe7ii5H.js} +1 -1
- package/dist/client/assets/channel-DoX862zl.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CCv6QaQn.js → chunk-2J33WTMH-BS6W9bWv.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-Bfe22y5T.js → chunk-4BX2VUAB-DbehRhdW.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CwicrA9V.js → chunk-55IACEB6-DMI5SR42.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DlIpTC03.js → chunk-727SXJPM-D1d-GBVj.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CRX4mFVq.js → chunk-AQP2D5EJ-BzO6K3Uf.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DzG-bovU.js → chunk-FMBD7UC4-BVRLV3lK.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-D5F2jtpM.js → chunk-ND2GUHAM-DdWByQfn.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-BmSaCwG6.js → chunk-QZHKN3VN-1ia12cRV.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-mb2IeAGN.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-mb2IeAGN.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BbKTljui.js → cose-bilkent-S5V4N54A-BPDT41HR.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-u0hwXb_T.js → dagre-BM42HDAG-Cktn26EH.js} +1 -1
- package/dist/client/assets/{dashboard-view-BfYZZ9Ms.js → dashboard-view-8o0EUcRX.js} +1 -1
- package/dist/client/assets/{dashboard-view-faKSXA4_.js → dashboard-view-CkCerlVJ.js} +1 -1
- package/dist/client/assets/{dashboard-view-BjPZG2Fv.js → dashboard-view-D_HC4lnr.js} +1 -1
- package/dist/client/assets/{dashboard-view-oCjWDGbW.js → dashboard-view-zd8GxC49.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-Q7towbBl.js → diagram-2AECGRRQ-But4Lvf-.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-UAwBmAxb.js → diagram-5GNKFQAL-2bpQAGFc.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BL1n0pkf.js → diagram-KO2AKTUF-Ckn9Qd1u.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-O-v_IZUJ.js → diagram-LMA3HP47-Bjn8h84N.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CAYSE2Mz.js → diagram-OG6HWLK6-BI6541hx.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-Cr_DgCyp.js → erDiagram-TEJ5UH35-BqMiwHiM.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-TdLzHKPW.js → flowDiagram-I6XJVG4X-Q_SAB10M.js} +1 -1
- package/dist/client/assets/{folder-open-BoddkTkv.js → folder-open-CHiAJbTN.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CO1ErtJY.js → ganttDiagram-6RSMTGT7-CqWFSfPF.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-C8_Kx0Yh.js → gitGraphDiagram-PVQCEYII-B1o4uEjO.js} +1 -1
- package/dist/client/assets/index-Bdw5eNKV.css +1 -0
- package/dist/client/assets/index-kwRywd9M.js +2767 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-Dd6Zo7Dh.js → infoDiagram-5YYISTIA-BzaMa0c2.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BE9JCLb5.js → ishikawaDiagram-YF4QCWOH-I38yge00.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-B6RIZGDq.js → journeyDiagram-JHISSGLW-WVQSgx4P.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CPXff-h-.js → kanban-definition-UN3LZRKU-BWtPQ3AH.js} +1 -1
- package/dist/client/assets/{mermaid.core-CbGj7iEw.js → mermaid.core-D1hnBtbi.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DF5LZmsH.js → mindmap-definition-RKZ34NQL-DqiSLkW7.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-Dpy0Xm9T.js → pieDiagram-4H26LBE5-CcgwbdIN.js} +1 -1
- package/dist/client/assets/{puzzle-BZa4U8-N.js → puzzle-BhXUaTQl.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BTLAQFpz.js → quadrantDiagram-W4KKPZXB-MsqQQfDN.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DSUV9ySs.js → requirementDiagram-4Y6WPE33-CILGjMMA.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Fmfn0XDL.js → sankeyDiagram-5OEKKPKP-c14fWbtR.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-_343I_b4.js → sequenceDiagram-3UESZ5HK-BD5bxMom.js} +1 -1
- package/dist/client/assets/{shield-alert-CdJ55UvI.js → shield-alert-C9W2WywS.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-r03dZ5Z0.js → standing-instructions-template-CJdbDSyg.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-C9EbWegm.js → stateDiagram-AJRCARHV-CZ5YqeOn.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-Bmh2GRh6.js → stateDiagram-v2-BHNVJYJU-mdMN-PNX.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-q86S9wyl.js → timeline-definition-PNZ67QCA-DHKay9uj.js} +1 -1
- package/dist/client/assets/{upload-DS9-qtCF.js → upload-DxEwowRU.js} +1 -1
- package/dist/client/assets/{users-DP5Sngeg.js → users-mNFgW_Zd.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BFq8uIt3.js → vennDiagram-CIIHVFJN-X29K9hWM.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BL_sLGYI.js → wardley-L42UT6IY-yEoTrfmN.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BEKJJ9Vi.js → wardleyDiagram-YWT4CUSO-ny4k3kG0.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DsvFnlxK.js → xychartDiagram-2RQKCTM6-DC8ODtRJ.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 +225 -93
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +2 -1
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/SecretsView-DgMu7279.js +0 -1
- package/dist/client/assets/SettingsModal-Dckls6LL.js +0 -21
- package/dist/client/assets/channel-CLdamWm5.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BYWknNX0.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BYWknNX0.js +0 -1
- package/dist/client/assets/index-C7KY0q8Q.js +0 -2767
- package/dist/client/assets/index-DHk_s6rA.css +0 -1
package/dist/extension.js
CHANGED
|
@@ -1103,6 +1103,9 @@ function isFusionSiblingBranch(branch) {
|
|
|
1103
1103
|
function resolveEffectiveAutoMerge(task, settings) {
|
|
1104
1104
|
return task.autoMerge ?? settings.autoMerge;
|
|
1105
1105
|
}
|
|
1106
|
+
function hasUserAutoMergeHold(task) {
|
|
1107
|
+
return task.autoMerge === false && task.autoMergeProvenance === "user";
|
|
1108
|
+
}
|
|
1106
1109
|
function allowsAutoMergeProcessing(task, settings) {
|
|
1107
1110
|
return (settings.autoMerge !== false || task.autoMerge === true) && !taskHasManualOpenPullRequest(task);
|
|
1108
1111
|
}
|
|
@@ -63343,7 +63346,7 @@ function rowToTask(row) {
|
|
|
63343
63346
|
executionStartBranch: row.executionStartBranch || void 0,
|
|
63344
63347
|
branch: row.branch || void 0,
|
|
63345
63348
|
autoMerge: row.autoMerge === null ? void 0 : row.autoMerge === 1,
|
|
63346
|
-
autoMergeProvenance: row.autoMergeProvenance === "user" || row.autoMergeProvenance === "legacy-stamp" ? row.autoMergeProvenance : void 0,
|
|
63349
|
+
autoMergeProvenance: row.autoMergeProvenance === "user" || row.autoMergeProvenance === "mission" || row.autoMergeProvenance === "legacy-stamp" ? row.autoMergeProvenance : void 0,
|
|
63347
63350
|
baseCommitSha: row.baseCommitSha || void 0,
|
|
63348
63351
|
scopeOverride: row.scopeOverride ? true : void 0,
|
|
63349
63352
|
scopeOverrideReason: row.scopeOverrideReason || void 0,
|
|
@@ -72859,10 +72862,10 @@ ${feature.acceptanceCriteria}`);
|
|
|
72859
72862
|
Apply the selected Missions header workflow atomically during TaskStore.createTask so newly triaged features land in the intended workflow lane. Duplicate-guard reuses skip this create path, preserving existing duplicate tasks without workflow mutation.
|
|
72860
72863
|
*/
|
|
72861
72864
|
/*
|
|
72862
|
-
FNXC:MissionAutoMerge 2026-
|
|
72863
|
-
An autoMerge:false mission stamps each newly triaged task so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override.
|
|
72865
|
+
FNXC:MissionAutoMerge 2026-08-05-22:50:
|
|
72866
|
+
An autoMerge:false mission stamps each newly triaged task as mission policy so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override; policy must not impersonate an operator manual-hold choice.
|
|
72864
72867
|
*/
|
|
72865
|
-
...mission?.autoMerge === false ? { autoMerge: false } : {},
|
|
72868
|
+
...mission?.autoMerge === false ? { autoMerge: false, autoMergeProvenance: "mission" } : {},
|
|
72866
72869
|
// FNXC:MissionTaskPrefix 2026-07-26-12:00: thread the mission's optional taskPrefix into TaskCreateInput for distributed id minting.
|
|
72867
72870
|
...mission?.taskPrefix ? { taskPrefix: mission.taskPrefix } : {},
|
|
72868
72871
|
...branchOptions?.workflowId !== void 0 ? { workflowId: branchOptions.workflowId } : {}
|
|
@@ -76040,10 +76043,10 @@ ${feature.acceptanceCriteria}`);
|
|
|
76040
76043
|
}
|
|
76041
76044
|
} : {},
|
|
76042
76045
|
/*
|
|
76043
|
-
FNXC:MissionAutoMerge 2026-
|
|
76044
|
-
An autoMerge:false mission stamps each newly triaged task so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override.
|
|
76046
|
+
FNXC:MissionAutoMerge 2026-08-05-22:50:
|
|
76047
|
+
An autoMerge:false mission stamps each newly triaged task as mission policy so its shared branch produces one PR instead of per-task auto-merges. Duplicate reuse intentionally bypasses this create-only override; policy must not impersonate an operator manual-hold choice.
|
|
76045
76048
|
*/
|
|
76046
|
-
...mission?.autoMerge === false ? { autoMerge: false } : {},
|
|
76049
|
+
...mission?.autoMerge === false ? { autoMerge: false, autoMergeProvenance: "mission" } : {},
|
|
76047
76050
|
// FNXC:MissionTaskPrefix 2026-07-26-12:00: thread the mission's optional taskPrefix into TaskCreateInput so the distributed allocator mints ERR-N (etc.) instead of the project prefix.
|
|
76048
76051
|
...mission?.taskPrefix ? { taskPrefix: mission.taskPrefix } : {},
|
|
76049
76052
|
...branchOptions?.workflowId !== void 0 ? { workflowId: branchOptions.workflowId } : {}
|
|
@@ -86394,7 +86397,9 @@ async function _createTaskInternalBackendImpl(store, input, title, resolvedWorkf
|
|
|
86394
86397
|
sourceMetadata: withTaskBranchContextInSourceMetadata(input.source?.sourceMetadata, input.branchContext),
|
|
86395
86398
|
branchContext: input.branchContext,
|
|
86396
86399
|
autoMerge: input.autoMerge,
|
|
86397
|
-
|
|
86400
|
+
// FNXC:SharedBranchMemberHold 2026-08-05-22:50: trusted mission creation
|
|
86401
|
+
// preserves policy provenance; operator/API create requests retain user provenance.
|
|
86402
|
+
autoMergeProvenance: input.autoMerge === void 0 ? void 0 : input.autoMergeProvenance ?? "user",
|
|
86398
86403
|
// FNXC:CodingIdeasWorkflow 2026-07-05-19:45: land the task in its
|
|
86399
86404
|
// workflow's manual intake column (e.g. Coding (Ideas) → "ideas") when
|
|
86400
86405
|
// no explicit column is given (main FN-7591 parity).
|
|
@@ -127272,6 +127277,7 @@ var init_task_timing = __esm({
|
|
|
127272
127277
|
});
|
|
127273
127278
|
|
|
127274
127279
|
// ../core/src/session-identity-registry.ts
|
|
127280
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
127275
127281
|
import { resolve as resolve21 } from "node:path";
|
|
127276
127282
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
127277
127283
|
function getRegistry() {
|
|
@@ -127283,6 +127289,16 @@ function getRegistry() {
|
|
|
127283
127289
|
}
|
|
127284
127290
|
return registry3;
|
|
127285
127291
|
}
|
|
127292
|
+
function getActiveInvocationStorage() {
|
|
127293
|
+
const holder = globalThis;
|
|
127294
|
+
const existing = holder[ACTIVE_INVOCATION_KEY];
|
|
127295
|
+
if (existing instanceof AsyncLocalStorage) {
|
|
127296
|
+
return existing;
|
|
127297
|
+
}
|
|
127298
|
+
const storage = new AsyncLocalStorage();
|
|
127299
|
+
holder[ACTIVE_INVOCATION_KEY] = storage;
|
|
127300
|
+
return storage;
|
|
127301
|
+
}
|
|
127286
127302
|
function canonicalizeCwd(cwd) {
|
|
127287
127303
|
const resolved = resolve21(cwd);
|
|
127288
127304
|
try {
|
|
@@ -127310,8 +127326,13 @@ function registerFusionSessionIdentity(cwd, identity) {
|
|
|
127310
127326
|
};
|
|
127311
127327
|
}
|
|
127312
127328
|
function resolveFusionSessionPrincipal(cwd) {
|
|
127329
|
+
const canonicalCwd = canonicalizeCwd(cwd);
|
|
127330
|
+
const activeInvocation = getActiveInvocationStorage().getStore();
|
|
127331
|
+
if (activeInvocation?.cwdKeys.has(canonicalCwd)) {
|
|
127332
|
+
return { kind: "agent", identity: activeInvocation.identity };
|
|
127333
|
+
}
|
|
127313
127334
|
const registry3 = getRegistry();
|
|
127314
|
-
const list = registry3.get(
|
|
127335
|
+
const list = registry3.get(canonicalCwd);
|
|
127315
127336
|
if (!list || list.length === 0) {
|
|
127316
127337
|
return { kind: "operator" };
|
|
127317
127338
|
}
|
|
@@ -127320,14 +127341,24 @@ function resolveFusionSessionPrincipal(cwd) {
|
|
|
127320
127341
|
}
|
|
127321
127342
|
return { kind: "ambiguous", identities: [...list] };
|
|
127322
127343
|
}
|
|
127344
|
+
function runWithFusionSessionIdentity(cwdKeys, identity, callback) {
|
|
127345
|
+
const invocation = {
|
|
127346
|
+
identity: { ...identity, registeredAt: Date.now() },
|
|
127347
|
+
cwdKeys: new Set(cwdKeys.map(canonicalizeCwd))
|
|
127348
|
+
};
|
|
127349
|
+
return getActiveInvocationStorage().run(invocation, callback);
|
|
127350
|
+
}
|
|
127323
127351
|
function __clearFusionSessionIdentityRegistryForTests() {
|
|
127324
|
-
|
|
127352
|
+
const holder = globalThis;
|
|
127353
|
+
holder[REGISTRY_KEY] = /* @__PURE__ */ new Map();
|
|
127354
|
+
holder[ACTIVE_INVOCATION_KEY] = new AsyncLocalStorage();
|
|
127325
127355
|
}
|
|
127326
|
-
var REGISTRY_KEY;
|
|
127356
|
+
var REGISTRY_KEY, ACTIVE_INVOCATION_KEY;
|
|
127327
127357
|
var init_session_identity_registry = __esm({
|
|
127328
127358
|
"../core/src/session-identity-registry.ts"() {
|
|
127329
127359
|
"use strict";
|
|
127330
127360
|
REGISTRY_KEY = "__FUSION_SESSION_IDENTITY_REGISTRY_V1__";
|
|
127361
|
+
ACTIVE_INVOCATION_KEY = "__FUSION_SESSION_IDENTITY_ACTIVE_INVOCATION_V1__";
|
|
127331
127362
|
}
|
|
127332
127363
|
});
|
|
127333
127364
|
|
|
@@ -128298,6 +128329,7 @@ __export(src_exports, {
|
|
|
128298
128329
|
hasRoleOverrides: () => hasRoleOverrides,
|
|
128299
128330
|
hasSyncPassphraseConfigured: () => hasSyncPassphraseConfigured,
|
|
128300
128331
|
hasTitleIdDrift: () => hasTitleIdDrift,
|
|
128332
|
+
hasUserAutoMergeHold: () => hasUserAutoMergeHold,
|
|
128301
128333
|
hashWorkflowIr: () => hashWorkflowIr,
|
|
128302
128334
|
healSchemaDrift: () => healSchemaDrift,
|
|
128303
128335
|
importMcpServersJson: () => importMcpServersJson,
|
|
@@ -128758,6 +128790,7 @@ __export(src_exports, {
|
|
|
128758
128790
|
runMemoryBackupCommand: () => runMemoryBackupCommand,
|
|
128759
128791
|
runReconciliationAbort: () => runReconciliationAbort,
|
|
128760
128792
|
runScheduledEvalBatch: () => runScheduledEvalBatch,
|
|
128793
|
+
runWithFusionSessionIdentity: () => runWithFusionSessionIdentity,
|
|
128761
128794
|
sanitizeBranchSegment: () => sanitizeBranchSegment,
|
|
128762
128795
|
sanitizeCliAgentSettings: () => sanitizeCliAgentSettings,
|
|
128763
128796
|
sanitizeCliAgentsSettings: () => sanitizeCliAgentsSettings,
|
|
@@ -157407,6 +157440,7 @@ import { existsSync as existsSync43, readFileSync as readFileSync15, realpathSyn
|
|
|
157407
157440
|
import { exec as exec2, execFile as execFile7 } from "node:child_process";
|
|
157408
157441
|
import { promisify as promisify6 } from "node:util";
|
|
157409
157442
|
import { createRequire as createRequire5 } from "node:module";
|
|
157443
|
+
import { randomUUID as randomUUID42 } from "node:crypto";
|
|
157410
157444
|
import { basename as basename13, dirname as dirname21, join as join56, relative as relative6, isAbsolute as isAbsolute8, resolve as resolve24 } from "node:path";
|
|
157411
157445
|
import {
|
|
157412
157446
|
createAgentSession,
|
|
@@ -159117,7 +159151,8 @@ async function createFnAgent2(options) {
|
|
|
159117
159151
|
});
|
|
159118
159152
|
};
|
|
159119
159153
|
const sessionIdentity = (() => {
|
|
159120
|
-
const
|
|
159154
|
+
const namedAgentId = options.actionGateContext?.agentId ?? options.permanentAgentGating?.requester?.actorId;
|
|
159155
|
+
const principalAgentId = namedAgentId ?? `engine-session-${randomUUID42()}`;
|
|
159121
159156
|
const principalAgentName = options.actionGateContext?.agentName ?? options.permanentAgentGating?.requester?.actorName;
|
|
159122
159157
|
return {
|
|
159123
159158
|
agentId: principalAgentId,
|
|
@@ -159129,6 +159164,14 @@ async function createFnAgent2(options) {
|
|
|
159129
159164
|
const sessionIdentityKeys = [...new Set([options.cwd, resolvedProjectRoot].filter((key) => Boolean(key)))];
|
|
159130
159165
|
const attachSessionIdentity = (session) => {
|
|
159131
159166
|
const identityDisposers = sessionIdentityKeys.map((key) => registerFusionSessionIdentity(key, sessionIdentity));
|
|
159167
|
+
const sessionInvocations = session;
|
|
159168
|
+
const wrapInvocation = (methodName) => {
|
|
159169
|
+
const original = sessionInvocations[methodName];
|
|
159170
|
+
if (typeof original !== "function") return;
|
|
159171
|
+
sessionInvocations[methodName] = (...args) => runWithFusionSessionIdentity(sessionIdentityKeys, sessionIdentity, () => original.apply(session, args));
|
|
159172
|
+
};
|
|
159173
|
+
wrapInvocation("prompt");
|
|
159174
|
+
wrapInvocation("promptWithFallback");
|
|
159132
159175
|
const disposeBeforeIdentity = typeof session.dispose === "function" ? session.dispose.bind(session) : () => void 0;
|
|
159133
159176
|
session.dispose = async () => {
|
|
159134
159177
|
for (const disposeIdentity of identityDisposers) {
|
|
@@ -167328,10 +167371,11 @@ function createMergeAttemptHandler(deps) {
|
|
|
167328
167371
|
);
|
|
167329
167372
|
};
|
|
167330
167373
|
}
|
|
167331
|
-
function createMergeGateHandler() {
|
|
167374
|
+
function createMergeGateHandler(deps = {}) {
|
|
167332
167375
|
return async (_node, ctx) => {
|
|
167333
167376
|
const settingsAutoMerge = ctx.settings?.autoMerge;
|
|
167334
|
-
const
|
|
167377
|
+
const settings = { autoMerge: settingsAutoMerge ?? true };
|
|
167378
|
+
const autoMerge = !hasUserAutoMergeHold(ctx.task) && (await deps.isLiveSharedBranchMember?.(ctx.task, settings) === true || ctx.task.autoMerge !== false && settings.autoMerge !== false);
|
|
167335
167379
|
return {
|
|
167336
167380
|
outcome: "success",
|
|
167337
167381
|
value: autoMerge ? "auto-on" : "auto-off"
|
|
@@ -167341,6 +167385,7 @@ function createMergeGateHandler() {
|
|
|
167341
167385
|
var init_merge_runner = __esm({
|
|
167342
167386
|
"../engine/src/workflow-node-runners/merge-runner.ts"() {
|
|
167343
167387
|
"use strict";
|
|
167388
|
+
init_src2();
|
|
167344
167389
|
init_workflow_merge_nodes();
|
|
167345
167390
|
}
|
|
167346
167391
|
});
|
|
@@ -167684,7 +167729,7 @@ function createDefaultNodeHandlers(seams, runCustomNode, deps) {
|
|
|
167684
167729
|
"parse-steps": parseSteps,
|
|
167685
167730
|
code: createCodeNodeHandler(deps?.runCode),
|
|
167686
167731
|
notify: createNotifyHandler(deps?.notifyDispatch),
|
|
167687
|
-
"merge-gate": createMergeGateHandler(),
|
|
167732
|
+
"merge-gate": createMergeGateHandler({ isLiveSharedBranchMember: deps?.isLiveSharedBranchMember }),
|
|
167688
167733
|
"merge-attempt": createMergeAttemptHandler({
|
|
167689
167734
|
primitives: deps?.primitives,
|
|
167690
167735
|
seams,
|
|
@@ -168082,7 +168127,7 @@ var init_code_node_runner = __esm({
|
|
|
168082
168127
|
// ../engine/src/agent-tools.ts
|
|
168083
168128
|
import { appendFile as appendFile3, mkdir as mkdir26, readFile as readFile32, readdir as readdir9, realpath, stat as stat9, writeFile as writeFile24 } from "node:fs/promises";
|
|
168084
168129
|
import { existsSync as existsSync50 } from "node:fs";
|
|
168085
|
-
import { createHash as createHash19, randomUUID as
|
|
168130
|
+
import { createHash as createHash19, randomUUID as randomUUID43 } from "node:crypto";
|
|
168086
168131
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
168087
168132
|
import { extname as extname3, isAbsolute as isAbsolute12, join as join62, relative as relative11, resolve as resolve33, sep as sep9 } from "node:path";
|
|
168088
168133
|
import { Type as Type2 } from "@earendil-works/pi-ai";
|
|
@@ -168728,7 +168773,7 @@ function createTaskCreateTool(store, provenance, options) {
|
|
|
168728
168773
|
toType: "user",
|
|
168729
168774
|
type: "agent-to-user",
|
|
168730
168775
|
content: `Task proposal awaiting validation: ${title}`,
|
|
168731
|
-
metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey:
|
|
168776
|
+
metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey: randomUUID43(), taskId: options.sourceTaskId, proposedTask: { title, description: params.description, priority: params.priority, workflowId: params.workflow_id, dependencies: params.dependencies } }
|
|
168732
168777
|
});
|
|
168733
168778
|
return { content: [{ type: "text", text: "Task proposal submitted to the operator for validation; no task was created." }], details: { proposed: true } };
|
|
168734
168779
|
}
|
|
@@ -202305,16 +202350,29 @@ var init_self_healing = __esm({
|
|
|
202305
202350
|
activeWork: await this.resolveActiveWorkColumnsFor(taskId, cache)
|
|
202306
202351
|
};
|
|
202307
202352
|
}
|
|
202308
|
-
|
|
202353
|
+
/*
|
|
202354
|
+
FNXC:SharedBranchMemberHold 2026-08-05-23:35:
|
|
202355
|
+
Pause-abort recovery must resolve the same live intermediate-group predicate as
|
|
202356
|
+
merge admission. Shared metadata alone is stale after group closure or a
|
|
202357
|
+
default-branch collision, so it cannot suppress that task's standalone hold.
|
|
202358
|
+
*/
|
|
202359
|
+
async isLiveSharedMemberIntegration(task, settings) {
|
|
202360
|
+
const groupId = task.branchContext?.groupId?.trim();
|
|
202361
|
+
const group = groupId ? await this.store.getBranchGroup?.(groupId) : null;
|
|
202362
|
+
const defaultBranch = await resolveIntegrationBranch(this.options.rootDir, settings);
|
|
202363
|
+
return isLiveSharedBranchGroupMemberIntegration(task, group, defaultBranch);
|
|
202364
|
+
}
|
|
202365
|
+
async classifyPausedAbortWorkflowRecovery(task, settings, isExecuting, columns) {
|
|
202309
202366
|
const isPausedAbortPark = task.status === "failed" && typeof task.error === "string" && task.error.includes(PAUSE_ABORT_PARK_OPERATOR_MARKER) && task.error.includes(PAUSE_ABORT_PARK_ERROR_MARKER);
|
|
202310
202367
|
if (!isPausedAbortPark) return { kind: "no-action", reason: "not-pause-abort" };
|
|
202311
202368
|
if (task.paused || task.userPaused || isExecuting) return { kind: "no-action", reason: "unsafe-or-not-routable" };
|
|
202312
202369
|
const errorText = typeof task.error === "string" ? task.error.toLowerCase() : "";
|
|
202313
202370
|
const isTerminalMergePark = errorText.includes("conflict") || errorText.includes("contamination") || errorText.includes("foreign") || errorText.includes("retry-exhausted") || errorText.includes("retries exhausted") || errorText.includes("max retries");
|
|
202314
202371
|
const completedSteps = task.steps.length > 0 && task.steps.every((step) => step.status === "done" || step.status === "skipped");
|
|
202315
|
-
const
|
|
202316
|
-
const
|
|
202317
|
-
const
|
|
202372
|
+
const liveSharedBranchMember = await this.isLiveSharedMemberIntegration(task, settings);
|
|
202373
|
+
const autoMergeProcessing = allowsAutoMergeProcessing(task, settings) || liveSharedBranchMember;
|
|
202374
|
+
const hasReviewProgress = columns.review.has(task.column) && autoMergeProcessing && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
|
|
202375
|
+
const hasManualMergeHoldProgress = columns.review.has(task.column) && (hasUserAutoMergeHold(task) || !allowsAutoMergeProcessing(task, settings) || resolveEffectiveAutoMerge(task, settings) === false) && (!liveSharedBranchMember || hasUserAutoMergeHold(task)) && task.mergeDetails?.mergeConfirmed !== true && !isTerminalMergePark && completedSteps;
|
|
202318
202376
|
if (hasManualMergeHoldProgress) {
|
|
202319
202377
|
return { kind: "work-item-resume", reason: "pause-abort-manual-merge-hold" };
|
|
202320
202378
|
}
|
|
@@ -207982,8 +208040,23 @@ var init_self_healing = __esm({
|
|
|
207982
208040
|
return own.length > 0 ? new Set(own) : /* @__PURE__ */ new Set(["in-review"]);
|
|
207983
208041
|
};
|
|
207984
208042
|
const executingIds = this.options.getExecutingTaskIds?.() ?? /* @__PURE__ */ new Set();
|
|
208043
|
+
const canRecoverMergeableReviewTask = async (task) => {
|
|
208044
|
+
if (hasUserAutoMergeHold(task)) return false;
|
|
208045
|
+
const groupId = task.branchContext?.groupId?.trim();
|
|
208046
|
+
const branchGroup = groupId ? await this.store.getBranchGroup(groupId) : null;
|
|
208047
|
+
const projectDefaultBranch = await resolveIntegrationBranch(this.options.rootDir, settings);
|
|
208048
|
+
if (isLiveSharedBranchGroupMemberIntegration(task, branchGroup, projectDefaultBranch)) {
|
|
208049
|
+
return true;
|
|
208050
|
+
}
|
|
208051
|
+
return allowsAutoMergeProcessing(task, settings) && resolveEffectiveAutoMerge(task, settings) !== false;
|
|
208052
|
+
};
|
|
208053
|
+
const mergeAdmission = await Promise.all(tasks2.map(async (task) => [
|
|
208054
|
+
task.id,
|
|
208055
|
+
await canRecoverMergeableReviewTask(task)
|
|
208056
|
+
]));
|
|
208057
|
+
const mergeAdmissionByTaskId = new Map(mergeAdmission);
|
|
207985
208058
|
const mergeable = tasks2.filter(
|
|
207986
|
-
(t) =>
|
|
208059
|
+
(t) => mergeAdmissionByTaskId.get(t.id) === true && !t.paused && !executingIds.has(t.id) && t.status !== "failed" && // Exclude transient merge statuses. Active merges should be left alone;
|
|
207987
208060
|
// stale ones are handled by recoverStaleMergingStatus().
|
|
207988
208061
|
t.status !== "merging" && t.status !== "merging-pr" && // FNXC:Workspace 2026-06-22-09:30 (Phase D U1, KTD1 — admit workspace tasks):
|
|
207989
208062
|
// A workspace task has task.worktree===null (its worktrees live per-repo in
|
|
@@ -211030,7 +211103,7 @@ var init_self_healing = __esm({
|
|
|
211030
211103
|
for (const t of tasks2) {
|
|
211031
211104
|
if (!this.isPauseAbortParkCandidate(t)) continue;
|
|
211032
211105
|
const columns = await this.resolvePauseAbortColumnsFor(t.id, columnCache);
|
|
211033
|
-
if (this.classifyPausedAbortWorkflowRecovery(t, settings, executingIds.has(t.id), columns).kind !== "no-action") {
|
|
211106
|
+
if ((await this.classifyPausedAbortWorkflowRecovery(t, settings, executingIds.has(t.id), columns)).kind !== "no-action") {
|
|
211034
211107
|
parked.push(t);
|
|
211035
211108
|
}
|
|
211036
211109
|
}
|
|
@@ -211047,7 +211120,7 @@ var init_self_healing = __esm({
|
|
|
211047
211120
|
continue;
|
|
211048
211121
|
}
|
|
211049
211122
|
const freshColumns = await this.resolvePauseAbortColumnsFor(fresh.id, columnCache);
|
|
211050
|
-
const route = this.classifyPausedAbortWorkflowRecovery(fresh, settings, latestExecutingIds.has(fresh.id), freshColumns);
|
|
211123
|
+
const route = await this.classifyPausedAbortWorkflowRecovery(fresh, settings, latestExecutingIds.has(fresh.id), freshColumns);
|
|
211051
211124
|
if (route.kind === "no-action") {
|
|
211052
211125
|
continue;
|
|
211053
211126
|
}
|
|
@@ -218098,7 +218171,8 @@ var init_workflow_graph_executor = __esm({
|
|
|
218098
218171
|
parseSteps: deps.parseStepsDeps,
|
|
218099
218172
|
runCode: deps.runCode,
|
|
218100
218173
|
notifyDispatch: deps.notifyDispatch,
|
|
218101
|
-
prNodes: deps.prNodes
|
|
218174
|
+
prNodes: deps.prNodes,
|
|
218175
|
+
isLiveSharedBranchMember: deps.isLiveSharedBranchMember
|
|
218102
218176
|
}),
|
|
218103
218177
|
...deps.runnerRegistry?.toHandlers() ?? {},
|
|
218104
218178
|
...deps.handlers ?? {}
|
|
@@ -219334,6 +219408,10 @@ var init_workflow_graph_task_runner = __esm({
|
|
|
219334
219408
|
runCode: this.deps.runCode,
|
|
219335
219409
|
notifyDispatch: this.deps.notifyDispatch,
|
|
219336
219410
|
prNodes: this.deps.prNodes,
|
|
219411
|
+
// FNXC:SharedBranchMemberHold 2026-08-06-00:24: carry the executor's
|
|
219412
|
+
// live group resolver into the graph merge gate; omitting it turns
|
|
219413
|
+
// mission-policy members into manual holds before integration.
|
|
219414
|
+
isLiveSharedBranchMember: this.deps.isLiveSharedBranchMember,
|
|
219337
219415
|
/*
|
|
219338
219416
|
FNXC:WorkflowResume 2026-06-29-08:49:
|
|
219339
219417
|
Production graph runs must fetch live task steps during foreach replay. The runner is the workflow boundary that has store access, so it supplies the fresh projection seam instead of making executor self-healing guess after a stale step node fails.
|
|
@@ -227446,6 +227524,7 @@ ${feedback}`,
|
|
|
227446
227524
|
if (info.phase !== "pre-merge") return false;
|
|
227447
227525
|
if (info.status !== "advisory_failure" && info.status !== "failed") return false;
|
|
227448
227526
|
const liveTask = await this.store.getTask(taskId).catch(() => fallbackTask);
|
|
227527
|
+
if (hasUserAutoMergeHold(liveTask)) return false;
|
|
227449
227528
|
const missingArtifactKeys = parseRequiredArtifactMissingValue(info.failureValue);
|
|
227450
227529
|
if (missingArtifactKeys) {
|
|
227451
227530
|
await this.recoverMissingRequiredArtifacts(liveTask, missingArtifactKeys, {
|
|
@@ -227702,6 +227781,7 @@ ${info.feedback}`, revisionKey),
|
|
|
227702
227781
|
*/
|
|
227703
227782
|
async recoverFailedPreMergeWorkflowStep(task) {
|
|
227704
227783
|
try {
|
|
227784
|
+
if (hasUserAutoMergeHold(task)) return false;
|
|
227705
227785
|
const failed = (task.workflowStepResults ?? []).filter((r) => (r.phase || "pre-merge") === "pre-merge" && r.status === "failed").sort((a, b3) => {
|
|
227706
227786
|
const aTs = Date.parse(a.completedAt || a.startedAt || "");
|
|
227707
227787
|
const bTs = Date.parse(b3.completedAt || b3.startedAt || "");
|
|
@@ -228228,6 +228308,7 @@ ${info.feedback}`, revisionKey),
|
|
|
228228
228308
|
getTask: (taskId) => this.store.getTask(taskId)
|
|
228229
228309
|
},
|
|
228230
228310
|
runId: resolvedRunId,
|
|
228311
|
+
isLiveSharedBranchMember: (nodeTask) => this.isLiveSharedBranchGroupMember(nodeTask),
|
|
228231
228312
|
primitives: this.createAuthoritativeWorkflowPrimitives(settings),
|
|
228232
228313
|
seams: this.createAuthoritativeWorkflowSeams(settings),
|
|
228233
228314
|
prepareNodeExecution: (node, nodeTask, requirement) => this.prepareGraphNodeExecution(node, nodeTask, settings, requirement),
|
|
@@ -231169,6 +231250,7 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
231169
231250
|
} catch {
|
|
231170
231251
|
return false;
|
|
231171
231252
|
}
|
|
231253
|
+
if (hasUserAutoMergeHold(live)) return false;
|
|
231172
231254
|
const sharedBranchMember = await this.isLiveSharedBranchGroupMember(live);
|
|
231173
231255
|
if (!sharedBranchMember && !allowsAutoMergeProcessing(live, settings)) return false;
|
|
231174
231256
|
if (!sharedBranchMember && resolveEffectiveAutoMerge(live, settings) === false) return false;
|
|
@@ -231230,8 +231312,8 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
231230
231312
|
} catch {
|
|
231231
231313
|
return false;
|
|
231232
231314
|
}
|
|
231233
|
-
if (await this.isLiveSharedBranchGroupMember(live)) return false;
|
|
231234
|
-
return !allowsAutoMergeProcessing(live, settings) || resolveEffectiveAutoMerge(live, settings) === false;
|
|
231315
|
+
if (await this.isLiveSharedBranchGroupMember(live) && !hasUserAutoMergeHold(live)) return false;
|
|
231316
|
+
return hasUserAutoMergeHold(live) || !allowsAutoMergeProcessing(live, settings) || resolveEffectiveAutoMerge(live, settings) === false;
|
|
231235
231317
|
}
|
|
231236
231318
|
async handleStaleInReviewPlanPauseAbortReplay(live, result2, abortProvenance, pausedAborted, userCanceled, resumeLanesMemo) {
|
|
231237
231319
|
if (!pausedAborted) return false;
|
|
@@ -231395,9 +231477,9 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
231395
231477
|
if (settings.globalPause === true) return false;
|
|
231396
231478
|
}
|
|
231397
231479
|
if (live.column === resumeLanes.review) {
|
|
231398
|
-
if (live.autoMerge === false) return false;
|
|
231399
231480
|
if (!settings) return false;
|
|
231400
231481
|
const sharedBranchMember = await this.isLiveSharedBranchGroupMember(live);
|
|
231482
|
+
if (hasUserAutoMergeHold(live) || live.autoMerge === false && !sharedBranchMember) return false;
|
|
231401
231483
|
if (!sharedBranchMember && !allowsAutoMergeProcessing(live, settings)) return false;
|
|
231402
231484
|
if (live.mergeDetails?.mergeConfirmed === true) return false;
|
|
231403
231485
|
}
|
|
@@ -248472,7 +248554,7 @@ var init_metric_parser = __esm({
|
|
|
248472
248554
|
});
|
|
248473
248555
|
|
|
248474
248556
|
// ../engine/src/eval/experiment-executor.ts
|
|
248475
|
-
import { randomUUID as
|
|
248557
|
+
import { randomUUID as randomUUID44 } from "node:crypto";
|
|
248476
248558
|
var ExperimentMaxIterationsError, ExperimentGitNotConfiguredError, ExperimentExecutor;
|
|
248477
248559
|
var init_experiment_executor = __esm({
|
|
248478
248560
|
"../engine/src/eval/experiment-executor.ts"() {
|
|
@@ -248540,7 +248622,7 @@ var init_experiment_executor = __esm({
|
|
|
248540
248622
|
}
|
|
248541
248623
|
await this.semaphore.acquire();
|
|
248542
248624
|
const controller = new AbortController();
|
|
248543
|
-
const runHandle =
|
|
248625
|
+
const runHandle = randomUUID44();
|
|
248544
248626
|
if (opts?.abortSignal) {
|
|
248545
248627
|
opts.abortSignal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
248546
248628
|
}
|
|
@@ -257547,6 +257629,7 @@ var init_in_process_runtime = __esm({
|
|
|
257547
257629
|
}
|
|
257548
257630
|
}
|
|
257549
257631
|
const prNodeGithubOps = this.config.prNodeGithubOps;
|
|
257632
|
+
const secretsStore = await this.taskStore.getSecretsStore();
|
|
257550
257633
|
const executorOptions = {
|
|
257551
257634
|
/*
|
|
257552
257635
|
FNXC:PlanReviewLease 2026-07-26-21:12:
|
|
@@ -257562,6 +257645,7 @@ var init_in_process_runtime = __esm({
|
|
|
257562
257645
|
cliAgentRuntime: this.cliAgentRuntime?.bundle,
|
|
257563
257646
|
pluginRunner: this.pluginRunner,
|
|
257564
257647
|
messageStore: this.messageStore,
|
|
257648
|
+
secretsStore,
|
|
257565
257649
|
missionStore,
|
|
257566
257650
|
reflectionService,
|
|
257567
257651
|
// PR-entity nodes (U3): assemble the handler deps from the CLI-injected
|
|
@@ -257663,6 +257747,7 @@ var init_in_process_runtime = __esm({
|
|
|
257663
257747
|
reflectionService,
|
|
257664
257748
|
selfImproveService,
|
|
257665
257749
|
credentialRotator: this.credentialRotator,
|
|
257750
|
+
secretsStore,
|
|
257666
257751
|
snapshotManager: autoClaimSnapshotManager,
|
|
257667
257752
|
onMissed: (agentId, reason) => {
|
|
257668
257753
|
runtimeLog.warn(`Agent ${agentId} missed heartbeat: ${reason}`);
|
|
@@ -261524,7 +261609,21 @@ var init_project_engine = __esm({
|
|
|
261524
261609
|
Cleared on the first non-busy outcome (success path resets it).
|
|
261525
261610
|
*/
|
|
261526
261611
|
workspaceBusyReenqueues = /* @__PURE__ */ new Map();
|
|
261612
|
+
workspaceBusyReenqueueTimers = /* @__PURE__ */ new Set();
|
|
261527
261613
|
static WORKSPACE_BUSY_MAX_REENQUEUES = 10;
|
|
261614
|
+
/*
|
|
261615
|
+
FNXC:WorkspaceMergeDispatch 2026-08-05-23:56:
|
|
261616
|
+
Workspace lease-contention retries are engine-owned lifecycle work, not detached callbacks.
|
|
261617
|
+
Track only these busy re-enqueue timers so stop() can cancel them and tests can measure the
|
|
261618
|
+
capped workspace ladder without confusing it with merge-body or maintenance timers.
|
|
261619
|
+
*/
|
|
261620
|
+
scheduleWorkspaceBusyReenqueue(taskId, delayMs) {
|
|
261621
|
+
const timer2 = setTimeout(() => {
|
|
261622
|
+
this.workspaceBusyReenqueueTimers.delete(timer2);
|
|
261623
|
+
if (!this.shuttingDown) this.internalEnqueueMerge(taskId);
|
|
261624
|
+
}, delayMs);
|
|
261625
|
+
this.workspaceBusyReenqueueTimers.add(timer2);
|
|
261626
|
+
}
|
|
261528
261627
|
/**
|
|
261529
261628
|
* Pending manual merge resolvers — keyed by taskId.
|
|
261530
261629
|
* When `onMerge` is called, the task is enqueued like auto-merge but a
|
|
@@ -262059,6 +262158,10 @@ ${detail}`);
|
|
|
262059
262158
|
clearInterval(this.mergeActiveReconcileTimer);
|
|
262060
262159
|
this.mergeActiveReconcileTimer = null;
|
|
262061
262160
|
}
|
|
262161
|
+
for (const timer2 of this.workspaceBusyReenqueueTimers) {
|
|
262162
|
+
clearTimeout(timer2);
|
|
262163
|
+
}
|
|
262164
|
+
this.workspaceBusyReenqueueTimers.clear();
|
|
262062
262165
|
for (const [taskId, deferred] of this.capacityDeferredMerges) {
|
|
262063
262166
|
clearTimeout(deferred.timer);
|
|
262064
262167
|
for (const resolver of deferred.resolvers) {
|
|
@@ -263358,16 +263461,15 @@ ${detail}`);
|
|
|
263358
263461
|
* older low-priority task would start before a later urgent one.
|
|
263359
263462
|
*/
|
|
263360
263463
|
async allowInReviewMergeProcessing(task, settings, store = this.runtime.getTaskStore()) {
|
|
263361
|
-
if (
|
|
263362
|
-
return true;
|
|
263363
|
-
}
|
|
263464
|
+
if (hasUserAutoMergeHold(task)) return false;
|
|
263364
263465
|
const groupId = task.branchContext?.groupId?.trim();
|
|
263365
263466
|
const branchGroup = groupId ? await store.getBranchGroup?.(groupId) : null;
|
|
263366
|
-
if (!branchGroup || branchGroup.status !== "open" || !branchGroup.branchName.trim()) {
|
|
263367
|
-
return false;
|
|
263368
|
-
}
|
|
263369
263467
|
const projectDefaultBranch = await resolveIntegrationBranch(this.config.workingDirectory, settings);
|
|
263370
|
-
|
|
263468
|
+
if (isLiveSharedBranchGroupMemberIntegration(task, branchGroup, projectDefaultBranch)) {
|
|
263469
|
+
return true;
|
|
263470
|
+
}
|
|
263471
|
+
if (task.autoMerge === false && groupId) return false;
|
|
263472
|
+
return allowsAutoMergeProcessing(task, settings);
|
|
263371
263473
|
}
|
|
263372
263474
|
async emitLegacyAutoMergeStampAdvisory(store) {
|
|
263373
263475
|
if (this.legacyAutoMergeStampAdvisoryEmitted) {
|
|
@@ -264320,9 +264422,7 @@ ${detail}`);
|
|
|
264320
264422
|
runtimeLog.log(
|
|
264321
264423
|
`Workspace land busy re-enqueue ${busyCount + 1}/${_ProjectEngine.WORKSPACE_BUSY_MAX_REENQUEUES} for ${taskId} in ${delayMs / 1e3}s (no mergeRetry consumed \u2014 pure lease contention)`
|
|
264322
264424
|
);
|
|
264323
|
-
|
|
264324
|
-
if (!this.shuttingDown) this.internalEnqueueMerge(taskId);
|
|
264325
|
-
}, delayMs);
|
|
264425
|
+
this.scheduleWorkspaceBusyReenqueue(taskId, delayMs);
|
|
264326
264426
|
} else {
|
|
264327
264427
|
this.workspaceBusyReenqueues.delete(taskId);
|
|
264328
264428
|
await store.updateTask(taskId, { status: "failed", error: errorMsg }).catch(() => void 0);
|
|
@@ -267814,7 +267914,7 @@ var init_task_lifecycle_lanes = __esm({
|
|
|
267814
267914
|
});
|
|
267815
267915
|
|
|
267816
267916
|
// ../dashboard/src/ai-session-diagnostics.ts
|
|
267817
|
-
import { randomUUID as
|
|
267917
|
+
import { randomUUID as randomUUID45 } from "node:crypto";
|
|
267818
267918
|
function defaultSink(level, scope, message, context) {
|
|
267819
267919
|
const log41 = createLogger(scope);
|
|
267820
267920
|
try {
|
|
@@ -267857,7 +267957,7 @@ function emit(level, scope, message, context) {
|
|
|
267857
267957
|
const fullContext = {
|
|
267858
267958
|
...context,
|
|
267859
267959
|
_emittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
267860
|
-
_diagnosticsId:
|
|
267960
|
+
_diagnosticsId: randomUUID45()
|
|
267861
267961
|
};
|
|
267862
267962
|
try {
|
|
267863
267963
|
_sink(level, scope, message, fullContext);
|
|
@@ -268573,7 +268673,7 @@ var init_planning_board_tools = __esm({
|
|
|
268573
268673
|
});
|
|
268574
268674
|
|
|
268575
268675
|
// ../dashboard/src/planning.ts
|
|
268576
|
-
import { randomUUID as
|
|
268676
|
+
import { randomUUID as randomUUID46 } from "node:crypto";
|
|
268577
268677
|
import { EventEmitter as EventEmitter34 } from "node:events";
|
|
268578
268678
|
async function createPlanningRuntimeSession(options) {
|
|
268579
268679
|
const { pluginRunner, runtimeHint, settings, ...runtimeOptions } = options ?? {};
|
|
@@ -268956,7 +269056,7 @@ async function createSession(ip, initialPlan, store, rootDir, promptOverrides, p
|
|
|
268956
269056
|
if (!store) {
|
|
268957
269057
|
throw new Error("store is required for AI-powered planning sessions");
|
|
268958
269058
|
}
|
|
268959
|
-
const sessionId =
|
|
269059
|
+
const sessionId = randomUUID46();
|
|
268960
269060
|
const session = {
|
|
268961
269061
|
id: sessionId,
|
|
268962
269062
|
ip,
|
|
@@ -269526,7 +269626,7 @@ function normalizePlanningQuestion(input, userInput = "") {
|
|
|
269526
269626
|
const type = source.type === "multi_select" || source.type === "single_select" ? source.type : "single_select";
|
|
269527
269627
|
const question = typeof source.question === "string" && source.question.trim() ? source.question.trim() : fallback.question;
|
|
269528
269628
|
const normalized = {
|
|
269529
|
-
id: typeof source.id === "string" && source.id.trim() ? source.id :
|
|
269629
|
+
id: typeof source.id === "string" && source.id.trim() ? source.id : randomUUID46(),
|
|
269530
269630
|
type,
|
|
269531
269631
|
question,
|
|
269532
269632
|
...typeof source.description === "string" && source.description.trim() ? { description: source.description.trim() } : {}
|
|
@@ -269552,7 +269652,7 @@ function normalizePlanningQuestion(input, userInput = "") {
|
|
|
269552
269652
|
}
|
|
269553
269653
|
function coerceQuestionResponse(response, session) {
|
|
269554
269654
|
if (response.type === "question") return normalizePlanningQuestion(response.data, session.initialPlan);
|
|
269555
|
-
return normalizePlanningQuestion({ id:
|
|
269655
|
+
return normalizePlanningQuestion({ id: randomUUID46(), type: "single_select", question: planningFallbackCopy(session.initialPlan).question }, session.initialPlan);
|
|
269556
269656
|
}
|
|
269557
269657
|
async function validateSession(sessionId) {
|
|
269558
269658
|
const session = await getSession(sessionId);
|
|
@@ -270300,7 +270400,7 @@ async function createTaskFromPlanSession(sessionId, store, options) {
|
|
|
270300
270400
|
throw new InvalidSessionStateError("PLANNING_CREATED_TASK_MISSING");
|
|
270301
270401
|
}
|
|
270302
270402
|
}
|
|
270303
|
-
const claimOwnerToken =
|
|
270403
|
+
const claimOwnerToken = randomUUID46();
|
|
270304
270404
|
let claimed = await claimPlanningTaskCreation(sessionId, claimOwnerToken, (/* @__PURE__ */ new Date()).toISOString(), claimEpoch);
|
|
270305
270405
|
if (!claimed) {
|
|
270306
270406
|
session = await getDurablePlanningSession(sessionId).catch(() => void 0) ?? session;
|
|
@@ -282888,7 +282988,7 @@ var init_register_gitlab = __esm({
|
|
|
282888
282988
|
|
|
282889
282989
|
// ../dashboard/src/terminal.ts
|
|
282890
282990
|
import { spawn as spawn11 } from "node:child_process";
|
|
282891
|
-
import { randomUUID as
|
|
282991
|
+
import { randomUUID as randomUUID47 } from "node:crypto";
|
|
282892
282992
|
import { EventEmitter as EventEmitter41 } from "node:events";
|
|
282893
282993
|
function extractBaseCommand(command) {
|
|
282894
282994
|
let trimmed = command.trim();
|
|
@@ -283048,7 +283148,7 @@ var init_terminal = __esm({
|
|
|
283048
283148
|
if (!validation.valid) {
|
|
283049
283149
|
return { sessionId: "", error: validation.error };
|
|
283050
283150
|
}
|
|
283051
|
-
const sessionId =
|
|
283151
|
+
const sessionId = randomUUID47();
|
|
283052
283152
|
const childProcess5 = spawn11(command, [], {
|
|
283053
283153
|
cwd,
|
|
283054
283154
|
shell: true,
|
|
@@ -284520,7 +284620,7 @@ var init_src8 = __esm({
|
|
|
284520
284620
|
|
|
284521
284621
|
// ../../plugins/fusion-plugin-openclaw-runtime/src/pi-module.ts
|
|
284522
284622
|
import { spawn as spawn13 } from "node:child_process";
|
|
284523
|
-
import { randomUUID as
|
|
284623
|
+
import { randomUUID as randomUUID48 } from "node:crypto";
|
|
284524
284624
|
import { readFile as readFile44 } from "node:fs/promises";
|
|
284525
284625
|
function asString2(v2) {
|
|
284526
284626
|
return typeof v2 === "string" && v2.trim() !== "" ? v2.trim() : void 0;
|
|
@@ -284580,7 +284680,7 @@ function extractStderrError(stderr, stdout) {
|
|
|
284580
284680
|
}
|
|
284581
284681
|
function createCliSession(opts) {
|
|
284582
284682
|
return {
|
|
284583
|
-
sessionId:
|
|
284683
|
+
sessionId: randomUUID48(),
|
|
284584
284684
|
agentId: opts.agentId ?? DEFAULT_AGENT_ID,
|
|
284585
284685
|
systemPrompt: opts.systemPrompt,
|
|
284586
284686
|
messages: [{ role: "developer", content: opts.systemPrompt }],
|
|
@@ -284775,7 +284875,7 @@ var init_mcp_config2 = __esm({
|
|
|
284775
284875
|
});
|
|
284776
284876
|
|
|
284777
284877
|
// ../../plugins/fusion-plugin-openclaw-runtime/src/runtime-adapter.ts
|
|
284778
|
-
import { randomUUID as
|
|
284878
|
+
import { randomUUID as randomUUID49 } from "node:crypto";
|
|
284779
284879
|
var OpenClawRuntimeAdapter;
|
|
284780
284880
|
var init_runtime_adapter2 = __esm({
|
|
284781
284881
|
"../../plugins/fusion-plugin-openclaw-runtime/src/runtime-adapter.ts"() {
|
|
@@ -284798,8 +284898,8 @@ var init_runtime_adapter2 = __esm({
|
|
|
284798
284898
|
let mcpProfile;
|
|
284799
284899
|
let mcpConfigPath;
|
|
284800
284900
|
if (toolDefs.length > 0) {
|
|
284801
|
-
const bridge = writeOpenClawMcpBridgeFiles(toolDefs,
|
|
284802
|
-
mcpProfile = `fusion-${
|
|
284901
|
+
const bridge = writeOpenClawMcpBridgeFiles(toolDefs, randomUUID49());
|
|
284902
|
+
mcpProfile = `fusion-${randomUUID49()}`;
|
|
284803
284903
|
mcpConfigPath = bridge.serverConfigPath;
|
|
284804
284904
|
await configureOpenClawMcpServer({
|
|
284805
284905
|
binaryPath: this.config.binaryPath,
|
|
@@ -287273,7 +287373,7 @@ import { existsSync as existsSync73, writeFileSync as writeFileSync15 } from "no
|
|
|
287273
287373
|
import { tmpdir as tmpdir16 } from "node:os";
|
|
287274
287374
|
import { dirname as dirname41, join as join93 } from "node:path";
|
|
287275
287375
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
287276
|
-
import { randomUUID as
|
|
287376
|
+
import { randomUUID as randomUUID50 } from "node:crypto";
|
|
287277
287377
|
function toolsToMcpToolDefs2(tools) {
|
|
287278
287378
|
if (!Array.isArray(tools)) return [];
|
|
287279
287379
|
return tools.filter((tool) => tool && typeof tool.name === "string" && tool.name.trim().length > 0 && !BUILT_IN_TOOL_NAMES2.has(tool.name)).map((tool) => ({
|
|
@@ -287324,7 +287424,7 @@ async function startFusionToolBridge(tools) {
|
|
|
287324
287424
|
byName.set(tool.name, tool);
|
|
287325
287425
|
}
|
|
287326
287426
|
}
|
|
287327
|
-
const schemaPath = join93(tmpdir16(), `fusion-grok-mcp-schemas-${process.pid}-${
|
|
287427
|
+
const schemaPath = join93(tmpdir16(), `fusion-grok-mcp-schemas-${process.pid}-${randomUUID50()}.json`);
|
|
287328
287428
|
writeFileSync15(schemaPath, JSON.stringify(defs));
|
|
287329
287429
|
const server = createServer2(async (req, res) => {
|
|
287330
287430
|
if (req.method !== "POST" || req.url !== "/tool-call") {
|
|
@@ -287350,7 +287450,7 @@ async function startFusionToolBridge(tools) {
|
|
|
287350
287450
|
return;
|
|
287351
287451
|
}
|
|
287352
287452
|
try {
|
|
287353
|
-
const result2 = await tool.execute(`grok-mcp-${
|
|
287453
|
+
const result2 = await tool.execute(`grok-mcp-${randomUUID50()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
|
|
287354
287454
|
res.statusCode = 200;
|
|
287355
287455
|
res.setHeader("content-type", "application/json");
|
|
287356
287456
|
res.end(
|
|
@@ -289394,7 +289494,7 @@ import { existsSync as existsSync77, rmSync as rmSync13, writeFileSync as writeF
|
|
|
289394
289494
|
import { tmpdir as tmpdir18 } from "node:os";
|
|
289395
289495
|
import { dirname as dirname46, join as join98 } from "node:path";
|
|
289396
289496
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
289397
|
-
import { randomBytes as randomBytes7, randomUUID as
|
|
289497
|
+
import { randomBytes as randomBytes7, randomUUID as randomUUID51 } from "node:crypto";
|
|
289398
289498
|
function toolsToMcpToolDefs3(tools) {
|
|
289399
289499
|
if (!Array.isArray(tools)) return [];
|
|
289400
289500
|
return tools.filter((tool) => tool && typeof tool.name === "string" && tool.name.trim().length > 0 && !BUILT_IN_TOOL_NAMES3.has(tool.name)).map((tool) => ({
|
|
@@ -289445,7 +289545,7 @@ async function startFusionToolBridge2(tools, options = {}) {
|
|
|
289445
289545
|
byName.set(tool.name, tool);
|
|
289446
289546
|
}
|
|
289447
289547
|
}
|
|
289448
|
-
const schemaPath = join98(tmpdir18(), `fusion-claude-mcp-schemas-${process.pid}-${
|
|
289548
|
+
const schemaPath = join98(tmpdir18(), `fusion-claude-mcp-schemas-${process.pid}-${randomUUID51()}.json`);
|
|
289449
289549
|
writeFileSync17(schemaPath, JSON.stringify(defs));
|
|
289450
289550
|
const capabilityToken = randomBytes7(32).toString("base64url");
|
|
289451
289551
|
const server = createServer3(async (req, res) => {
|
|
@@ -289510,7 +289610,7 @@ async function startFusionToolBridge2(tools, options = {}) {
|
|
|
289510
289610
|
return;
|
|
289511
289611
|
}
|
|
289512
289612
|
try {
|
|
289513
|
-
const result2 = await tool.execute(`claude-mcp-${
|
|
289613
|
+
const result2 = await tool.execute(`claude-mcp-${randomUUID51()}`, parsed.arguments ?? {}, void 0, void 0, void 0);
|
|
289514
289614
|
res.statusCode = 200;
|
|
289515
289615
|
res.setHeader("content-type", "application/json");
|
|
289516
289616
|
res.end(
|
|
@@ -291587,7 +291687,7 @@ import { existsSync as existsSync79, unlinkSync as unlinkSync5, writeFileSync as
|
|
|
291587
291687
|
import { tmpdir as tmpdir19 } from "node:os";
|
|
291588
291688
|
import { dirname as dirname49, join as join101 } from "node:path";
|
|
291589
291689
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
291590
|
-
import { randomUUID as
|
|
291690
|
+
import { randomUUID as randomUUID52 } from "node:crypto";
|
|
291591
291691
|
function toolsToMcpToolDefs4(tools) {
|
|
291592
291692
|
if (!Array.isArray(tools)) return [];
|
|
291593
291693
|
return tools.filter(
|
|
@@ -291644,7 +291744,7 @@ async function startFusionToolBridge3(tools) {
|
|
|
291644
291744
|
byName.set(tool.name, tool);
|
|
291645
291745
|
}
|
|
291646
291746
|
}
|
|
291647
|
-
const schemaPath = join101(tmpdir19(), `fusion-omp-mcp-schemas-${process.pid}-${
|
|
291747
|
+
const schemaPath = join101(tmpdir19(), `fusion-omp-mcp-schemas-${process.pid}-${randomUUID52()}.json`);
|
|
291648
291748
|
writeFileSync18(schemaPath, JSON.stringify(defs));
|
|
291649
291749
|
const server = createServer4(async (req, res) => {
|
|
291650
291750
|
if (req.method !== "POST" || req.url !== "/tool-call") {
|
|
@@ -291671,7 +291771,7 @@ async function startFusionToolBridge3(tools) {
|
|
|
291671
291771
|
}
|
|
291672
291772
|
try {
|
|
291673
291773
|
const result2 = await tool.execute(
|
|
291674
|
-
`omp-mcp-${
|
|
291774
|
+
`omp-mcp-${randomUUID52()}`,
|
|
291675
291775
|
parsed.arguments ?? {},
|
|
291676
291776
|
void 0,
|
|
291677
291777
|
void 0,
|
|
@@ -292564,7 +292664,7 @@ var init_paperclip_client = __esm({
|
|
|
292564
292664
|
});
|
|
292565
292665
|
|
|
292566
292666
|
// ../../plugins/fusion-plugin-paperclip-runtime/src/runtime-adapter.ts
|
|
292567
|
-
import { randomUUID as
|
|
292667
|
+
import { randomUUID as randomUUID53 } from "node:crypto";
|
|
292568
292668
|
function sleep7(ms2) {
|
|
292569
292669
|
return new Promise((resolve54) => setTimeout(resolve54, ms2));
|
|
292570
292670
|
}
|
|
@@ -292693,7 +292793,7 @@ var init_runtime_adapter10 = __esm({
|
|
|
292693
292793
|
apiKey: effectiveApiKey,
|
|
292694
292794
|
agentId,
|
|
292695
292795
|
companyId,
|
|
292696
|
-
sessionId:
|
|
292796
|
+
sessionId: randomUUID53(),
|
|
292697
292797
|
systemPrompt: options.systemPrompt,
|
|
292698
292798
|
cwd: options.cwd,
|
|
292699
292799
|
mode: normalizeMode3(this.config.mode),
|
|
@@ -293371,7 +293471,7 @@ var init_types5 = __esm({
|
|
|
293371
293471
|
});
|
|
293372
293472
|
|
|
293373
293473
|
// ../dashboard/src/stt/model-manager.ts
|
|
293374
|
-
import { createHash as createHash28, randomUUID as
|
|
293474
|
+
import { createHash as createHash28, randomUUID as randomUUID54 } from "node:crypto";
|
|
293375
293475
|
import { mkdir as mkdir31, open as open4, readFile as readFile46, readdir as readdir11, rename as rename10, rm as rm17, stat as stat12, writeFile as writeFile33 } from "node:fs/promises";
|
|
293376
293476
|
import { join as join102, relative as relative19, resolve as resolve51, sep as sep15 } from "node:path";
|
|
293377
293477
|
function parseSafeTarListing(listing) {
|
|
@@ -293452,8 +293552,8 @@ function createVoiceModelManager(options = {}) {
|
|
|
293452
293552
|
if (!current(g2, signal)) return state;
|
|
293453
293553
|
await mkdir31(cacheDir(), { recursive: true });
|
|
293454
293554
|
if (!current(g2, signal)) return state;
|
|
293455
|
-
partial2 = join102(cacheDir(), `.partial-${g2}-${
|
|
293456
|
-
staging = join102(cacheDir(), `.staging-${g2}-${
|
|
293555
|
+
partial2 = join102(cacheDir(), `.partial-${g2}-${randomUUID54()}`);
|
|
293556
|
+
staging = join102(cacheDir(), `.staging-${g2}-${randomUUID54()}`);
|
|
293457
293557
|
const file = await open4(partial2, "wx");
|
|
293458
293558
|
try {
|
|
293459
293559
|
const response = await (options.fetch ?? globalThis.fetch)(asset.url, { signal });
|
|
@@ -293501,7 +293601,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
293501
293601
|
await writeFile33(join102(staging, "manifest.json"), JSON.stringify({ filename: asset.filename, sha256: asset.sha256, installedAt: (/* @__PURE__ */ new Date()).toISOString(), expectedFiles: asset.expectedFiles }));
|
|
293502
293602
|
await options.beforePromote?.(signal);
|
|
293503
293603
|
if (!current(g2, signal)) return state;
|
|
293504
|
-
const backup = join102(cacheDir(), `.backup-${g2}-${
|
|
293604
|
+
const backup = join102(cacheDir(), `.backup-${g2}-${randomUUID54()}`);
|
|
293505
293605
|
let movedPrevious = false;
|
|
293506
293606
|
try {
|
|
293507
293607
|
try {
|
|
@@ -293722,7 +293822,7 @@ var init_parakeet_service = __esm({
|
|
|
293722
293822
|
});
|
|
293723
293823
|
|
|
293724
293824
|
// ../dashboard/src/routes/register-voice-routes.ts
|
|
293725
|
-
import { randomUUID as
|
|
293825
|
+
import { randomUUID as randomUUID55 } from "node:crypto";
|
|
293726
293826
|
import express from "express";
|
|
293727
293827
|
async function settingsFor(ctx, req) {
|
|
293728
293828
|
const scoped = await ctx.getScopedStore(req);
|
|
@@ -293801,7 +293901,7 @@ function createRegisterVoiceRoutes(deps = {}) {
|
|
|
293801
293901
|
recognizer.close();
|
|
293802
293902
|
return error2(res, 409, { error: "unavailable", reason: "model-removed" });
|
|
293803
293903
|
}
|
|
293804
|
-
const id =
|
|
293904
|
+
const id = randomUUID55();
|
|
293805
293905
|
const now = Date.now();
|
|
293806
293906
|
sessions6.set(id, { projectId, recognizer, next: 0, bytes: 0, last: now, expires: now + 3e5 });
|
|
293807
293907
|
res.status(201).json({ sessionId: id, expiresAt: new Date(now + 3e5).toISOString(), modelId: model.id, language: language.language });
|
|
@@ -297127,14 +297227,14 @@ init_src2();
|
|
|
297127
297227
|
init_gh_cli();
|
|
297128
297228
|
init_src5();
|
|
297129
297229
|
init_src15();
|
|
297130
|
-
import { randomUUID as
|
|
297230
|
+
import { randomUUID as randomUUID56 } from "node:crypto";
|
|
297131
297231
|
import { Type as Type9 } from "typebox";
|
|
297132
297232
|
import { StringEnum } from "@earendil-works/pi-ai";
|
|
297133
297233
|
import { resolve as resolve53, relative as relative20, isAbsolute as isAbsolute26, sep as sep16, basename as basename29, extname as extname4, join as join105 } from "node:path";
|
|
297134
297234
|
import { readFile as readFile47 } from "node:fs/promises";
|
|
297135
297235
|
import { existsSync as existsSync82 } from "node:fs";
|
|
297136
297236
|
import { spawn as spawn23 } from "node:child_process";
|
|
297137
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
297237
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
297138
297238
|
function truncateAgentDiagnosticText(value, maxChars) {
|
|
297139
297239
|
return value.length > maxChars ? `${value.slice(0, maxChars)}\u2026` : value;
|
|
297140
297240
|
}
|
|
@@ -297239,7 +297339,7 @@ var storeCache2 = extensionStoreState.cache;
|
|
|
297239
297339
|
var storeBootInflight = extensionStoreState.bootInflight;
|
|
297240
297340
|
var storeBootFailureCooldown = extensionStoreState.bootFailureCooldown;
|
|
297241
297341
|
var BOOT_FAILURE_COOLDOWN_MS = 5e3;
|
|
297242
|
-
var extensionToolSignal = new
|
|
297342
|
+
var extensionToolSignal = new AsyncLocalStorage2();
|
|
297243
297343
|
var EXTENSION_STORE_BOOT_TIMEOUT_MS = 3e4;
|
|
297244
297344
|
var EXTENSION_TOOL_TIMEOUT_MS = 6e4;
|
|
297245
297345
|
var SKILLS_INSTALL_TIMEOUT_MS = 3e5;
|
|
@@ -297541,6 +297641,28 @@ async function isEphemeralCallerAgent(cwd, callerAgentId) {
|
|
|
297541
297641
|
}
|
|
297542
297642
|
}
|
|
297543
297643
|
var AMBIGUOUS_AGENT_PRINCIPAL_ID = "unknown-agent";
|
|
297644
|
+
function resolveSecretAccessPrincipal(ctx) {
|
|
297645
|
+
const principal = resolveExtensionCallerPrincipal(ctx);
|
|
297646
|
+
if (principal.kind === "ambiguous") return { kind: "ambiguous" };
|
|
297647
|
+
if (principal.kind === "operator") {
|
|
297648
|
+
return {
|
|
297649
|
+
kind: "resolved",
|
|
297650
|
+
actor: { actorId: "user", actorType: "user", actorName: "CLI User" },
|
|
297651
|
+
agentId: null
|
|
297652
|
+
};
|
|
297653
|
+
}
|
|
297654
|
+
return {
|
|
297655
|
+
kind: "resolved",
|
|
297656
|
+
actor: {
|
|
297657
|
+
actorId: principal.identity.agentId,
|
|
297658
|
+
actorType: "agent",
|
|
297659
|
+
actorName: principal.identity.agentName ?? principal.identity.agentId
|
|
297660
|
+
},
|
|
297661
|
+
agentId: principal.identity.agentId,
|
|
297662
|
+
...principal.identity.agentName ? { agentName: principal.identity.agentName } : {},
|
|
297663
|
+
...principal.identity.taskId ? { taskId: principal.identity.taskId } : {}
|
|
297664
|
+
};
|
|
297665
|
+
}
|
|
297544
297666
|
function resolveExtensionCallerPrincipal(ctx) {
|
|
297545
297667
|
const explicitAgentId = typeof ctx.agentId === "string" && ctx.agentId.trim().length > 0 ? ctx.agentId.trim() : void 0;
|
|
297546
297668
|
if (explicitAgentId) {
|
|
@@ -298100,7 +298222,7 @@ function kbExtension(pi2) {
|
|
|
298100
298222
|
const layer = store.getAsyncLayer();
|
|
298101
298223
|
const messageStore = layer ? new MessageStore(null, { asyncLayer: layer }) : new MessageStore(store.getDatabase());
|
|
298102
298224
|
const title = params.description.split(/\r?\n/, 1)[0]?.trim().slice(0, 80) || "Follow-up task";
|
|
298103
|
-
await messageStore.sendMessage({ fromId: fnCtx.agentId ?? "ephemeral-worker", fromType: "agent", toId: DASHBOARD_USER_ID, toType: "user", type: "agent-to-user", content: `Task proposal awaiting validation: ${title}`, metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey:
|
|
298225
|
+
await messageStore.sendMessage({ fromId: fnCtx.agentId ?? "ephemeral-worker", fromType: "agent", toId: DASHBOARD_USER_ID, toType: "user", type: "agent-to-user", content: `Task proposal awaiting validation: ${title}`, metadata: { kind: "task-proposal", proposalStatus: "pending", proposalIdempotencyKey: randomUUID56(), proposedTask: { title, description: params.description, priority: params.priority, workflowId: params.workflow_id, dependencies: params.depends } } });
|
|
298104
298226
|
return { content: [{ type: "text", text: "Task proposal submitted to the operator for validation; no task was created." }], details: { proposed: true } };
|
|
298105
298227
|
}
|
|
298106
298228
|
}
|
|
@@ -299350,6 +299472,20 @@ Planning session completed. Task ${taskId} is now in planning and will be auto-p
|
|
|
299350
299472
|
}),
|
|
299351
299473
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
299352
299474
|
const fnCtx = ctx;
|
|
299475
|
+
const secretPrincipal = resolveSecretAccessPrincipal(fnCtx);
|
|
299476
|
+
if (secretPrincipal.kind === "ambiguous") {
|
|
299477
|
+
return {
|
|
299478
|
+
content: [{ type: "text", text: "Secret access was not requested because the calling agent identity is ambiguous. End one concurrent session and retry." }],
|
|
299479
|
+
isError: true,
|
|
299480
|
+
details: { error: "ambiguous-caller-identity", key: params.key, scope: params.scope ?? null }
|
|
299481
|
+
};
|
|
299482
|
+
}
|
|
299483
|
+
const effectiveCtx = {
|
|
299484
|
+
...secretPrincipal.agentId ? { agentId: secretPrincipal.agentId } : {},
|
|
299485
|
+
...secretPrincipal.agentName ? { agentName: secretPrincipal.agentName } : {},
|
|
299486
|
+
...typeof fnCtx.taskId === "string" ? { taskId: fnCtx.taskId } : secretPrincipal.taskId ? { taskId: secretPrincipal.taskId } : {},
|
|
299487
|
+
...typeof fnCtx.runId === "string" ? { runId: fnCtx.runId } : {}
|
|
299488
|
+
};
|
|
299353
299489
|
const store = await getStore(ctx.cwd);
|
|
299354
299490
|
const secretsStore = await store.getSecretsStore();
|
|
299355
299491
|
const scopes = params.scope ? [params.scope] : ["project", "global"];
|
|
@@ -299372,36 +299508,32 @@ Planning session completed. Task ${taskId} is now in planning and will be auto-p
|
|
|
299372
299508
|
settings: { secretsAccessPolicy: globalSettings.secretsAccessPolicy }
|
|
299373
299509
|
});
|
|
299374
299510
|
if (decision.policy === "deny") {
|
|
299375
|
-
emitSecretAudit(store,
|
|
299511
|
+
emitSecretAudit(store, effectiveCtx, "secret:approval-denied", `${resolvedScope}:${params.key}`);
|
|
299376
299512
|
return { content: [{ type: "text", text: "Secret access denied by policy." }], details: { error: "denied", key: params.key, scope: resolvedScope, policySource: decision.source } };
|
|
299377
299513
|
}
|
|
299378
299514
|
if (decision.policy === "prompt") {
|
|
299379
299515
|
const cliLayer = requireProjectLayer(store, "CLI secret approval store");
|
|
299380
299516
|
const approvalStore = new ApprovalRequestStore(null, { asyncLayer: cliLayer });
|
|
299381
|
-
const
|
|
299382
|
-
const requesterActorId =
|
|
299383
|
-
const
|
|
299384
|
-
|
|
299385
|
-
actorType: "agent",
|
|
299386
|
-
actorName: fnCtx.agentName ?? fnCtx.agentId
|
|
299387
|
-
} : { actorId: "user", actorType: "user", actorName: "CLI User" };
|
|
299388
|
-
const existing = await findLatestApprovalRequestByDedupeKey(approvalStore, { requesterActorId, ...fnCtx.taskId ? { taskId: fnCtx.taskId } : {}, dedupeKey });
|
|
299517
|
+
const requesterSnapshot = secretPrincipal.actor;
|
|
299518
|
+
const requesterActorId = requesterSnapshot.actorId;
|
|
299519
|
+
const dedupeKey = `secret-read:${resolvedScope}:${params.key}:${requesterActorId}`;
|
|
299520
|
+
const existing = await findLatestApprovalRequestByDedupeKey(approvalStore, { requesterActorId, ...effectiveCtx.taskId ? { taskId: effectiveCtx.taskId } : {}, dedupeKey });
|
|
299389
299521
|
if (existing?.status === "pending") {
|
|
299390
|
-
emitSecretAudit(store,
|
|
299522
|
+
emitSecretAudit(store, effectiveCtx, "secret:approval-requested", `${resolvedScope}:${params.key}`);
|
|
299391
299523
|
return {
|
|
299392
299524
|
content: [{ type: "text", text: `Secret access approval request ${existing.id} is still pending. Approve via POST /api/approvals/:id/decision.` }],
|
|
299393
299525
|
details: { outcome: "pending_approval", approvalRequestId: existing.id, key: params.key, scope: resolvedScope }
|
|
299394
299526
|
};
|
|
299395
299527
|
}
|
|
299396
299528
|
if (existing?.status === "denied") {
|
|
299397
|
-
emitSecretAudit(store,
|
|
299529
|
+
emitSecretAudit(store, effectiveCtx, "secret:approval-denied", `${resolvedScope}:${params.key}`);
|
|
299398
299530
|
return {
|
|
299399
299531
|
content: [{ type: "text", text: `Secret access request ${existing.id} was denied by the operator. Do not retry without operator direction.` }],
|
|
299400
299532
|
details: { outcome: "denied", approvalRequestId: existing.id, key: params.key, scope: resolvedScope }
|
|
299401
299533
|
};
|
|
299402
299534
|
}
|
|
299403
299535
|
if (existing?.status === "approved") {
|
|
299404
|
-
const revealedAfterApproval = await secretsStore.revealSecret(record2.id, resolvedScope, { agentId:
|
|
299536
|
+
const revealedAfterApproval = await secretsStore.revealSecret(record2.id, resolvedScope, { agentId: secretPrincipal.agentId });
|
|
299405
299537
|
await approvalStore.markCompleted(existing.id, {
|
|
299406
299538
|
actor: requesterSnapshot,
|
|
299407
299539
|
note: "Secret revealed after approval",
|
|
@@ -299409,7 +299541,7 @@ Planning session completed. Task ${taskId} is now in planning and will be auto-p
|
|
|
299409
299541
|
// get the same expectedRequesterActorId enforcement as the gate path.
|
|
299410
299542
|
expectedRequesterActorId: requesterActorId
|
|
299411
299543
|
});
|
|
299412
|
-
emitSecretAudit(store,
|
|
299544
|
+
emitSecretAudit(store, effectiveCtx, "secret:read", `${resolvedScope}:${params.key}`, { key: params.key, scope: resolvedScope, approvalRequestId: existing.id });
|
|
299413
299545
|
return {
|
|
299414
299546
|
content: [{ type: "text", text: `Loaded secret '${params.key}' from ${resolvedScope} scope (approval ${existing.id} consumed).` }],
|
|
299415
299547
|
details: { key: params.key, value: revealedAfterApproval.plaintextValue, scope: resolvedScope, approvalRequestId: existing.id }
|
|
@@ -299425,17 +299557,17 @@ Planning session completed. Task ${taskId} is now in planning and will be auto-p
|
|
|
299425
299557
|
resourceId: record2.id,
|
|
299426
299558
|
context: { approvalDedupeKey: dedupeKey, key: params.key, scope: resolvedScope }
|
|
299427
299559
|
},
|
|
299428
|
-
...
|
|
299429
|
-
...
|
|
299560
|
+
...effectiveCtx.runId ? { runId: effectiveCtx.runId } : {},
|
|
299561
|
+
...effectiveCtx.taskId ? { taskId: effectiveCtx.taskId } : {}
|
|
299430
299562
|
});
|
|
299431
|
-
emitSecretAudit(store,
|
|
299563
|
+
emitSecretAudit(store, effectiveCtx, "secret:approval-requested", `${resolvedScope}:${params.key}`);
|
|
299432
299564
|
return {
|
|
299433
299565
|
content: [{ type: "text", text: `Secret access requires approval. Request ${request2.id} is pending. Approve via POST /api/approvals/:id/decision.` }],
|
|
299434
299566
|
details: { outcome: "pending_approval", approvalRequestId: request2.id, key: params.key, scope: resolvedScope }
|
|
299435
299567
|
};
|
|
299436
299568
|
}
|
|
299437
|
-
const revealed = await secretsStore.revealSecret(record2.id, resolvedScope, { agentId:
|
|
299438
|
-
emitSecretAudit(store,
|
|
299569
|
+
const revealed = await secretsStore.revealSecret(record2.id, resolvedScope, { agentId: secretPrincipal.agentId });
|
|
299570
|
+
emitSecretAudit(store, effectiveCtx, "secret:read", `${resolvedScope}:${params.key}`, { key: params.key, scope: resolvedScope });
|
|
299439
299571
|
return {
|
|
299440
299572
|
content: [{ type: "text", text: `Loaded secret '${params.key}' from ${resolvedScope} scope.` }],
|
|
299441
299573
|
details: { key: params.key, value: revealed.plaintextValue, scope: resolvedScope }
|