@runfusion/fusion 0.47.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +153 -85
- package/dist/client/.vite/manifest.json +242 -242
- package/dist/client/assets/{AgentDetailView-D9lYcdOS.js → AgentDetailView-CF6isJ51.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-Bn_PEeQW.js → AgentPermissionPolicyEditor-DFldf6aS.js} +1 -1
- package/dist/client/assets/{AgentsView-BRbnFmv3.js → AgentsView-DiGseTuo.js} +3 -3
- package/dist/client/assets/{ChatView-Batci7-w.js → ChatView-BjQBbDyo.js} +1 -1
- package/dist/client/assets/{CommandCenter-DAUgvVMX.js → CommandCenter-DwpiADSX.js} +1 -1
- package/dist/client/assets/{DevServerView-HdEXR5UB.js → DevServerView-D6RFaGPU.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DrCiUJlF.js → DirectoryPicker-DNBB-viz.js} +1 -1
- package/dist/client/assets/{DocumentsView-C0KxPWex.js → DocumentsView-DXG-sctG.js} +1 -1
- package/dist/client/assets/{EvalsView-wCfi9Rkj.js → EvalsView-Ol6ECKz5.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-Crck6eJe.js → ExperimentalAgentOnboardingModal-BQc3GaE_.js} +1 -1
- package/dist/client/assets/{GoalsView-sFGHX3Wt.js → GoalsView-C_m90anC.js} +1 -1
- package/dist/client/assets/{InsightsView-jl0cX1um.js → InsightsView-BbFgPsDH.js} +1 -1
- package/dist/client/assets/{MemoryView-Bwv99M_s.js → MemoryView-CRS7AjWK.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BsA3tCZh.js → PiExtensionsManager-BEj5xu45.js} +1 -1
- package/dist/client/assets/{PluginManager-Bgd8Hj0a.js → PluginManager-CzCM3XUY.js} +1 -1
- package/dist/client/assets/{PullRequestView-CqO16SNt.js → PullRequestView-9yNYCunb.js} +1 -1
- package/dist/client/assets/{ResearchView-CfRsbJWS.js → ResearchView-BKdirpiw.js} +1 -1
- package/dist/client/assets/{SecretsView-CHomYGnm.js → SecretsView-qGjo-0Cp.js} +1 -1
- package/dist/client/assets/{SessionTerminal-DcYUuwbV.js → SessionTerminal-C7YlkdGJ.js} +1 -1
- package/dist/client/assets/{SettingsModal-CX5GLed_.js → SettingsModal-DihNd7g8.js} +1 -1
- package/dist/client/assets/{SettingsModal-ybSf6HDn.js → SettingsModal-DpaptT6t.js} +3 -3
- package/dist/client/assets/{SetupWizardModal-D2BQL0df.js → SetupWizardModal-MovTj5pY.js} +2 -2
- package/dist/client/assets/{ShadcnColorPicker-B-8x0Gci.js → ShadcnColorPicker-Bnf5n5R4.js} +1 -1
- package/dist/client/assets/{SkillsView-4iqYHf9N.js → SkillsView-Br2LkA3x.js} +1 -1
- package/dist/client/assets/{TodoView-BJsknVS6.js → TodoView-BEdk6FTU.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-QdwW4bY5.js → WorkflowNodeEditor-e-eR6yzw.js} +1 -1
- package/dist/client/assets/{agentSkills-CwR8s-gl.js → agentSkills-D5nDZPRY.js} +1 -1
- package/dist/client/assets/{app-BJGkp7Tt.js → app-BM6bAO0b.js} +1 -1
- package/dist/client/assets/{app-CZQ_fFNf.js → app-BglOELbc.js} +1 -1
- package/dist/client/assets/{app-BaoNC9zg.js → app-ChkCVQpq.js} +1 -1
- package/dist/client/assets/{app-DgezOJub.js → app-DMn7Jt9g.js} +1 -1
- package/dist/client/assets/{app-DAu3AzsS.js → app-D_IT9Buz.js} +1 -1
- package/dist/client/assets/{app-BKLUvvm8.js → app-S8fehQv8.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-rav0thhm.js → architectureDiagram-3BPJPVTR-BbkXWBni.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-x9Opikul.js → blockDiagram-GPEHLZMM-DhaqpHqZ.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BGrWtNPI.js → c4Diagram-AAUBKEIU-qC0WSHMZ.js} +1 -1
- package/dist/client/assets/channel-CCKvUami.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BMFvL-OW.js → chunk-2J33WTMH-Dah9zMeT.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-CWTOrH7n.js → chunk-4BX2VUAB-epHwnUb_.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-l48k3a4l.js → chunk-55IACEB6-DpYBy44g.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DeynG6ym.js → chunk-727SXJPM-B9b8698e.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-B9ndyq3h.js → chunk-AQP2D5EJ-DrM8nnhR.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DV2d1-q1.js → chunk-FMBD7UC4-jyT6Scwe.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-D0Dl37Mc.js → chunk-ND2GUHAM-EoPfF-PK.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-NGiOWxhM.js → chunk-QZHKN3VN-qMwLVfgJ.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C_HqY7AI.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C_HqY7AI.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-2ojNpRS8.js → cose-bilkent-S5V4N54A-DmPFKoVD.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BaIP71Bo.js → dagre-BM42HDAG-DeHxd-ej.js} +1 -1
- package/dist/client/assets/{dashboard-view-hB7ta6sK.js → dashboard-view-Cw5mMJay.js} +1 -1
- package/dist/client/assets/{dashboard-view-CC2QtNhx.js → dashboard-view-DXjNQ5IF.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DQfEScya.js → diagram-2AECGRRQ-C04A2mhr.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-B5iw3WNT.js → diagram-5GNKFQAL-DqtOwADI.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-C5mMn4JH.js → diagram-KO2AKTUF-CH0har-Z.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CaMhdmPl.js → diagram-LMA3HP47-CxN-U-0W.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-D2ed8-Fx.js → diagram-OG6HWLK6-42A7wpwF.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CZl07SyK.js → erDiagram-TEJ5UH35-CnZI5YlN.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Dz7RLhaG.js → flowDiagram-I6XJVG4X-BKfQhMVF.js} +1 -1
- package/dist/client/assets/{folder-open-DCNfEqr1.js → folder-open-STXgbemw.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-C3ny-S6Q.js → ganttDiagram-6RSMTGT7-BfA0pME8.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BjHF5C7t.js → gitGraphDiagram-PVQCEYII-BgDFB7PS.js} +1 -1
- package/dist/client/assets/index-BnfnLXyO.css +1 -0
- package/dist/client/assets/index-CHy0WNjH.js +1301 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BTYecWEx.js → infoDiagram-5YYISTIA-Bb5F155s.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BBNOAxJa.js → ishikawaDiagram-YF4QCWOH-8Oati7l_.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DrjdbyT5.js → journeyDiagram-JHISSGLW-DhHTHXTM.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CgTNTfT7.js → kanban-definition-UN3LZRKU-BWB9EtUX.js} +1 -1
- package/dist/client/assets/{mermaid.core-CyFmJxTj.js → mermaid.core-BD-L2gUQ.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-C95r0KZv.js → mindmap-definition-RKZ34NQL-BSKGd7LE.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-CmYuIsZ-.js → pieDiagram-4H26LBE5-BtBFPvSW.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BFLFwHMa.js → quadrantDiagram-W4KKPZXB-aWQWYPto.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-G0s0AfQq.js → requirementDiagram-4Y6WPE33-CprlEpIa.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-D8OLAFhm.js → sankeyDiagram-5OEKKPKP-Cw-AcRAV.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-6fDSosvV.js → sequenceDiagram-3UESZ5HK-BMW5slyv.js} +1 -1
- package/dist/client/assets/{shield-alert-CBAzSycj.js → shield-alert-Bzf8yNOc.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-BfNs5lJU.js → stateDiagram-AJRCARHV-CcxvIVwM.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-Bt0-CBqz.js → stateDiagram-v2-BHNVJYJU-awOfoFOB.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DmKYLILn.js → timeline-definition-PNZ67QCA-DIEAc2YP.js} +1 -1
- package/dist/client/assets/{upload--9MWYfcA.js → upload-DuwyPTKe.js} +1 -1
- package/dist/client/assets/{users-vOsWas_i.js → users-D1Qhfyro.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-D3jx9PAk.js → vennDiagram-CIIHVFJN-DOkqg5Wi.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BGRnyThw.js → wardley-L42UT6IY-DoPK1Q6d.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-pwLVIgII.js → wardleyDiagram-YWT4CUSO-l1vun-m2.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-ltxtDdDp.js → xychartDiagram-2RQKCTM6-DcUOUKvl.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 +104 -77
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugins/fusion-plugin-acp-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-hermes-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-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/channel-BFVfY8Ks.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-pfX_P8V9.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-pfX_P8V9.js +0 -1
- package/dist/client/assets/index-CUY6xXXv.js +0 -1292
- package/dist/client/assets/index-CXlzJfKU.css +0 -1
package/dist/bin.js
CHANGED
|
@@ -71211,9 +71211,6 @@ function evaluateInterpreterCutoverReadiness(input) {
|
|
|
71211
71211
|
if (!input.authoritativeFlagEnabled) {
|
|
71212
71212
|
reasons.push("experimentalFeatures.workflowInterpreterAuthoritative is disabled");
|
|
71213
71213
|
}
|
|
71214
|
-
if (!input.dualObserveEnabled) {
|
|
71215
|
-
reasons.push("experimentalFeatures.workflowInterpreterDualObserve is disabled");
|
|
71216
|
-
}
|
|
71217
71214
|
const paritySummary = input.paritySummary;
|
|
71218
71215
|
if (!paritySummary) {
|
|
71219
71216
|
reasons.push("workflow parity summary unavailable");
|
|
@@ -160189,7 +160186,6 @@ var init_workflow_authoritative_driver = __esm({
|
|
|
160189
160186
|
"use strict";
|
|
160190
160187
|
init_src();
|
|
160191
160188
|
init_logger2();
|
|
160192
|
-
init_workflow_parity_observer();
|
|
160193
160189
|
init_workflow_graph_task_runner();
|
|
160194
160190
|
AUTHORITATIVE_WORKFLOW_ID = "workflow-interpreter-authoritative";
|
|
160195
160191
|
WorkflowAuthoritativeDriver = class {
|
|
@@ -160216,13 +160212,8 @@ var init_workflow_authoritative_driver = __esm({
|
|
|
160216
160212
|
settings,
|
|
160217
160213
|
WORKFLOW_INTERPRETER_AUTHORITATIVE_FLAG
|
|
160218
160214
|
);
|
|
160219
|
-
const dualObserveEnabled = isExperimentalFeatureEnabled(
|
|
160220
|
-
settings,
|
|
160221
|
-
WORKFLOW_INTERPRETER_DUAL_OBSERVE_FLAG
|
|
160222
|
-
);
|
|
160223
160215
|
const readiness = evaluateInterpreterCutoverReadiness({
|
|
160224
160216
|
authoritativeFlagEnabled,
|
|
160225
|
-
dualObserveEnabled,
|
|
160226
160217
|
paritySummary,
|
|
160227
160218
|
minimumObservedRuns: this.deps.minimumObservedRuns
|
|
160228
160219
|
});
|
|
@@ -183130,8 +183121,8 @@ async function getFirstQuestionFromAgent(session, message) {
|
|
|
183130
183121
|
}
|
|
183131
183122
|
}
|
|
183132
183123
|
if (!parsed) {
|
|
183133
|
-
|
|
183134
|
-
|
|
183124
|
+
const errorMessage = buildRetryableParseErrorMessage(lastError);
|
|
183125
|
+
setSessionError(session, errorMessage);
|
|
183135
183126
|
try {
|
|
183136
183127
|
await session.agent.session.dispose?.();
|
|
183137
183128
|
} catch (disposeErr) {
|
|
@@ -183142,9 +183133,7 @@ async function getFirstQuestionFromAgent(session, message) {
|
|
|
183142
183133
|
});
|
|
183143
183134
|
}
|
|
183144
183135
|
session.agent = void 0;
|
|
183145
|
-
throw new Error(
|
|
183146
|
-
`Failed to get first question from AI: ${lastError?.message || "Unknown error"}`
|
|
183147
|
-
);
|
|
183136
|
+
throw new Error(`Failed to get first question from AI: ${errorMessage}`);
|
|
183148
183137
|
}
|
|
183149
183138
|
if (parsed.type === "complete") {
|
|
183150
183139
|
const summary = parsed.data;
|
|
@@ -183515,6 +183504,10 @@ async function maybeNotifyPlanningAwaitingInput(session, question) {
|
|
|
183515
183504
|
});
|
|
183516
183505
|
}
|
|
183517
183506
|
}
|
|
183507
|
+
function buildRetryableParseErrorMessage(error) {
|
|
183508
|
+
const baseMessage = (error?.message || "Failed to parse AI response").replace(/\s*Please try again\.?\s*$/i, "").trim();
|
|
183509
|
+
return `${baseMessage}. Retry this planning session or start a new one.`;
|
|
183510
|
+
}
|
|
183518
183511
|
function setSessionError(session, message) {
|
|
183519
183512
|
session.error = message;
|
|
183520
183513
|
session.updatedAt = /* @__PURE__ */ new Date();
|
|
@@ -183647,18 +183640,12 @@ async function continueAgentConversation(session, message) {
|
|
|
183647
183640
|
}
|
|
183648
183641
|
}
|
|
183649
183642
|
if (!parsed) {
|
|
183650
|
-
const errorMsg =
|
|
183643
|
+
const errorMsg = buildRetryableParseErrorMessage(lastError);
|
|
183651
183644
|
diagnostics2.error(
|
|
183652
183645
|
"All parse attempts exhausted for session",
|
|
183653
183646
|
{ sessionId: session.id, message: errorMsg, operation: "parse-exhausted" }
|
|
183654
183647
|
);
|
|
183655
|
-
session
|
|
183656
|
-
session.updatedAt = /* @__PURE__ */ new Date();
|
|
183657
|
-
persistSession(session, "error", errorMsg);
|
|
183658
|
-
planningStreamManager.broadcast(session.id, {
|
|
183659
|
-
type: "error",
|
|
183660
|
-
data: errorMsg
|
|
183661
|
-
});
|
|
183648
|
+
setSessionError(session, errorMsg);
|
|
183662
183649
|
return;
|
|
183663
183650
|
}
|
|
183664
183651
|
if (parsed.type === "question") {
|
|
@@ -183695,13 +183682,33 @@ async function continueAgentConversation(session, message) {
|
|
|
183695
183682
|
setSessionError(session, errorMessage);
|
|
183696
183683
|
}
|
|
183697
183684
|
}
|
|
183685
|
+
function isPlanningResponseShape(parsed) {
|
|
183686
|
+
if (typeof parsed !== "object" || parsed === null || !("type" in parsed) || !("data" in parsed)) {
|
|
183687
|
+
return false;
|
|
183688
|
+
}
|
|
183689
|
+
const typed = parsed;
|
|
183690
|
+
return (typed.type === "question" || typed.type === "complete") && typed.data !== null && typed.data !== void 0;
|
|
183691
|
+
}
|
|
183692
|
+
function parseJsonCandidateForShape(candidate) {
|
|
183693
|
+
try {
|
|
183694
|
+
return JSON.parse(candidate);
|
|
183695
|
+
} catch {
|
|
183696
|
+
try {
|
|
183697
|
+
return JSON.parse(repairJson2(candidate));
|
|
183698
|
+
} catch {
|
|
183699
|
+
return void 0;
|
|
183700
|
+
}
|
|
183701
|
+
}
|
|
183702
|
+
}
|
|
183698
183703
|
function extractJsonCandidate2(text) {
|
|
183699
183704
|
if (!text || !text.trim()) return null;
|
|
183700
|
-
const
|
|
183701
|
-
|
|
183702
|
-
|
|
183703
|
-
|
|
183704
|
-
|
|
183705
|
+
const codeBlockMatches = [...text.matchAll(/```(?:json)?\s*([\s\S]*?)\s*```/g)];
|
|
183706
|
+
const codeBlockCandidates = codeBlockMatches.map((match) => match[1]?.trim()).filter((candidate) => Boolean(candidate?.startsWith("{")));
|
|
183707
|
+
const planningCodeBlock = codeBlockCandidates.find(
|
|
183708
|
+
(candidate) => isPlanningResponseShape(parseJsonCandidateForShape(candidate))
|
|
183709
|
+
);
|
|
183710
|
+
if (planningCodeBlock) return planningCodeBlock;
|
|
183711
|
+
if (codeBlockCandidates.length > 0) return codeBlockCandidates[0];
|
|
183705
183712
|
const candidates = [];
|
|
183706
183713
|
for (let i = 0; i < text.length; i++) {
|
|
183707
183714
|
if (text[i] === "{") {
|
|
@@ -183727,19 +183734,18 @@ function extractJsonCandidate2(text) {
|
|
|
183727
183734
|
if (ch === "}") depth--;
|
|
183728
183735
|
if (depth === 0) {
|
|
183729
183736
|
const candidate = text.slice(i, j2 + 1).trim();
|
|
183730
|
-
|
|
183731
|
-
JSON.parse(candidate);
|
|
183732
|
-
candidates.push({ start: i, end: j2, text: candidate });
|
|
183733
|
-
} catch {
|
|
183734
|
-
}
|
|
183737
|
+
candidates.push({ start: i, end: j2, text: candidate, parsed: parseJsonCandidateForShape(candidate) });
|
|
183735
183738
|
break;
|
|
183736
183739
|
}
|
|
183737
183740
|
}
|
|
183738
183741
|
}
|
|
183739
183742
|
}
|
|
183740
|
-
|
|
183741
|
-
|
|
183742
|
-
|
|
183743
|
+
const planningCandidate = candidates.find((candidate) => isPlanningResponseShape(candidate.parsed));
|
|
183744
|
+
if (planningCandidate) return planningCandidate.text;
|
|
183745
|
+
const validCandidates = candidates.filter((candidate) => candidate.parsed !== void 0);
|
|
183746
|
+
if (validCandidates.length > 0) {
|
|
183747
|
+
validCandidates.sort((a, b2) => b2.text.length - a.text.length || a.start - b2.start);
|
|
183748
|
+
return validCandidates[0].text;
|
|
183743
183749
|
}
|
|
183744
183750
|
const trimmed = text.trim();
|
|
183745
183751
|
if (trimmed.startsWith("{")) return trimmed;
|
|
@@ -183824,11 +183830,8 @@ function parseAgentResponse2(text) {
|
|
|
183824
183830
|
);
|
|
183825
183831
|
}
|
|
183826
183832
|
}
|
|
183827
|
-
if (
|
|
183828
|
-
|
|
183829
|
-
if ((typed.type === "question" || typed.type === "complete") && typed.data !== null && typed.data !== void 0) {
|
|
183830
|
-
return parsed;
|
|
183831
|
-
}
|
|
183833
|
+
if (isPlanningResponseShape(parsed)) {
|
|
183834
|
+
return parsed;
|
|
183832
183835
|
}
|
|
183833
183836
|
diagnostics2.error("Invalid response structure from AI", { parsedSnippet: JSON.stringify(parsed).slice(0, 500), operation: "parse-validate" });
|
|
183834
183837
|
throw new Error("AI returned an invalid response structure. Please try again.");
|
|
@@ -190655,6 +190658,13 @@ function parseIssueUrl(stdout) {
|
|
|
190655
190658
|
url
|
|
190656
190659
|
};
|
|
190657
190660
|
}
|
|
190661
|
+
function requireNonEmptyPrBody(body) {
|
|
190662
|
+
const trimmed = body?.trim() ?? "";
|
|
190663
|
+
if (!trimmed) {
|
|
190664
|
+
throw new Error("PR body is required when creating a pull request");
|
|
190665
|
+
}
|
|
190666
|
+
return trimmed;
|
|
190667
|
+
}
|
|
190658
190668
|
function normalizeCheckState(state) {
|
|
190659
190669
|
switch ((state ?? "").toLowerCase()) {
|
|
190660
190670
|
case "success":
|
|
@@ -191133,6 +191143,7 @@ var init_github = __esm({
|
|
|
191133
191143
|
createPrWithGh(params) {
|
|
191134
191144
|
const { owner: paramOwner, repo: paramRepo, title, body, head, base, draft, reviewers } = params;
|
|
191135
191145
|
const { owner, repo } = this.resolveRepo(paramOwner, paramRepo);
|
|
191146
|
+
const prBody = requireNonEmptyPrBody(body);
|
|
191136
191147
|
const args = [
|
|
191137
191148
|
"pr",
|
|
191138
191149
|
"create",
|
|
@@ -191141,11 +191152,10 @@ var init_github = __esm({
|
|
|
191141
191152
|
"--title",
|
|
191142
191153
|
title,
|
|
191143
191154
|
"--head",
|
|
191144
|
-
head
|
|
191155
|
+
head,
|
|
191156
|
+
"--body",
|
|
191157
|
+
prBody
|
|
191145
191158
|
];
|
|
191146
|
-
if (body) {
|
|
191147
|
-
args.push("--body", body);
|
|
191148
|
-
}
|
|
191149
191159
|
if (base) {
|
|
191150
191160
|
args.push("--base", base);
|
|
191151
191161
|
}
|
|
@@ -191175,6 +191185,7 @@ var init_github = __esm({
|
|
|
191175
191185
|
async createPrWithApi(params) {
|
|
191176
191186
|
const { owner: paramOwner, repo: paramRepo, title, body, head, base = "main", draft, reviewers } = params;
|
|
191177
191187
|
const { owner, repo } = this.resolveRepo(paramOwner, paramRepo);
|
|
191188
|
+
const prBody = requireNonEmptyPrBody(body);
|
|
191178
191189
|
const url = `${this.baseUrl}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls`;
|
|
191179
191190
|
const headers = this.buildHeaders();
|
|
191180
191191
|
const response = await fetch(url, {
|
|
@@ -191182,7 +191193,7 @@ var init_github = __esm({
|
|
|
191182
191193
|
headers,
|
|
191183
191194
|
body: JSON.stringify({
|
|
191184
191195
|
title,
|
|
191185
|
-
body:
|
|
191196
|
+
body: prBody,
|
|
191186
191197
|
head,
|
|
191187
191198
|
base,
|
|
191188
191199
|
draft: draft === true
|
|
@@ -195704,7 +195715,7 @@ import { promisify as promisify54 } from "node:util";
|
|
|
195704
195715
|
import { exec as execCb } from "node:child_process";
|
|
195705
195716
|
import { access as access9, readFile as readFile27 } from "node:fs/promises";
|
|
195706
195717
|
import { join as join63 } from "node:path";
|
|
195707
|
-
function
|
|
195718
|
+
function buildFallbackPrMetadata(task) {
|
|
195708
195719
|
return {
|
|
195709
195720
|
title: task.title ?? task.id,
|
|
195710
195721
|
body: [
|
|
@@ -195808,12 +195819,13 @@ Closes ${taskId}`.trim()]
|
|
|
195808
195819
|
return out.join("\n");
|
|
195809
195820
|
}
|
|
195810
195821
|
async function runCommand(command, cwd, signal) {
|
|
195811
|
-
const
|
|
195822
|
+
const commandPromise = execAsync36(command, {
|
|
195812
195823
|
cwd,
|
|
195813
195824
|
timeout: 15e3,
|
|
195814
195825
|
maxBuffer: 10 * 1024 * 1024,
|
|
195815
195826
|
signal
|
|
195816
195827
|
});
|
|
195828
|
+
const { stdout } = signal ? await raceWithAbort(commandPromise, signal) : await commandPromise;
|
|
195817
195829
|
return stdout.trim();
|
|
195818
195830
|
}
|
|
195819
195831
|
function createAbortError3() {
|
|
@@ -195827,19 +195839,41 @@ function throwIfAborted3(signal) {
|
|
|
195827
195839
|
}
|
|
195828
195840
|
throw signal.reason instanceof Error ? signal.reason : createAbortError3();
|
|
195829
195841
|
}
|
|
195830
|
-
function
|
|
195831
|
-
return
|
|
195832
|
-
|
|
195833
|
-
|
|
195834
|
-
|
|
195835
|
-
|
|
195836
|
-
|
|
195837
|
-
|
|
195838
|
-
|
|
195839
|
-
|
|
195842
|
+
function getAbortReason(signal) {
|
|
195843
|
+
return signal.reason instanceof Error ? signal.reason : createAbortError3();
|
|
195844
|
+
}
|
|
195845
|
+
function raceWithAbort(operation, signal) {
|
|
195846
|
+
if (signal.aborted) {
|
|
195847
|
+
return Promise.reject(getAbortReason(signal));
|
|
195848
|
+
}
|
|
195849
|
+
return new Promise((resolve70, reject2) => {
|
|
195850
|
+
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
195851
|
+
const onAbort = () => {
|
|
195852
|
+
cleanup();
|
|
195853
|
+
reject2(getAbortReason(signal));
|
|
195854
|
+
};
|
|
195855
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
195856
|
+
Promise.resolve(operation).then(
|
|
195857
|
+
(value) => {
|
|
195858
|
+
cleanup();
|
|
195859
|
+
resolve70(value);
|
|
195860
|
+
},
|
|
195861
|
+
(error) => {
|
|
195862
|
+
cleanup();
|
|
195863
|
+
reject2(error);
|
|
195864
|
+
}
|
|
195840
195865
|
);
|
|
195841
195866
|
});
|
|
195842
195867
|
}
|
|
195868
|
+
function disposeSessionBestEffort(session) {
|
|
195869
|
+
try {
|
|
195870
|
+
const disposeResult = session.dispose?.();
|
|
195871
|
+
if (disposeResult && typeof disposeResult.catch === "function") {
|
|
195872
|
+
void disposeResult.catch(() => void 0);
|
|
195873
|
+
}
|
|
195874
|
+
} catch {
|
|
195875
|
+
}
|
|
195876
|
+
}
|
|
195843
195877
|
function isAbortLikeError(error) {
|
|
195844
195878
|
return Boolean(
|
|
195845
195879
|
error && typeof error === "object" && ("name" in error ? error.name === "AbortError" : false)
|
|
@@ -195858,7 +195892,7 @@ async function resolveBaseBranch(task, repoRoot, signal) {
|
|
|
195858
195892
|
}
|
|
195859
195893
|
async function generatePrMetadata(input) {
|
|
195860
195894
|
const { task, repoRoot, settings, signal, timeoutMs = PR_METADATA_TIMEOUT_MS } = input;
|
|
195861
|
-
const fallback2 =
|
|
195895
|
+
const fallback2 = buildFallbackPrMetadata(task);
|
|
195862
195896
|
const controller = new AbortController();
|
|
195863
195897
|
const abortFromCaller = () => controller.abort(signal?.reason instanceof Error ? signal.reason : createAbortError3());
|
|
195864
195898
|
const timeoutId = setTimeout(() => controller.abort(createAbortError3()), timeoutMs);
|
|
@@ -195873,24 +195907,24 @@ async function generatePrMetadata(input) {
|
|
|
195873
195907
|
}
|
|
195874
195908
|
try {
|
|
195875
195909
|
throwIfAborted3(combinedSignal);
|
|
195876
|
-
const baseBranch = await resolveBaseBranch(task, repoRoot, combinedSignal);
|
|
195877
|
-
const [logOut, diffStatOut] = await Promise.all([
|
|
195910
|
+
const baseBranch = await raceWithAbort(resolveBaseBranch(task, repoRoot, combinedSignal), combinedSignal);
|
|
195911
|
+
const [logOut, diffStatOut] = await raceWithAbort(Promise.all([
|
|
195878
195912
|
runCommand(`git log --no-merges ${baseBranch}..HEAD --format=%s%n%b`, repoRoot, combinedSignal).catch(() => ""),
|
|
195879
195913
|
runCommand(`git diff --stat ${baseBranch}..HEAD`, repoRoot, combinedSignal).catch(() => "")
|
|
195880
|
-
]);
|
|
195914
|
+
]), combinedSignal);
|
|
195881
195915
|
let promptContent = "";
|
|
195882
195916
|
try {
|
|
195883
195917
|
const promptPath = join63(repoRoot, ".fusion", "tasks", task.id, "PROMPT.md");
|
|
195884
|
-
promptContent = (await readFile27(promptPath, "utf8")).trim();
|
|
195918
|
+
promptContent = (await raceWithAbort(readFile27(promptPath, "utf8"), combinedSignal)).trim();
|
|
195885
195919
|
} catch {
|
|
195886
195920
|
promptContent = "";
|
|
195887
195921
|
}
|
|
195888
195922
|
const templatePath = join63(repoRoot, ".github", "pull_request_template.md");
|
|
195889
|
-
const templateExists = await access9(templatePath).then(() => true).catch(() => false);
|
|
195890
|
-
const template = templateExists ? await readFile27(templatePath, "utf8") : "";
|
|
195923
|
+
const templateExists = await raceWithAbort(access9(templatePath).then(() => true).catch(() => false), combinedSignal);
|
|
195924
|
+
const template = templateExists ? await raceWithAbort(readFile27(templatePath, "utf8"), combinedSignal) : "";
|
|
195891
195925
|
const model = resolveTitleSummarizerSettingsModel(settings);
|
|
195892
195926
|
let aiText = "";
|
|
195893
|
-
const { session } = await createFnAgent2({
|
|
195927
|
+
const { session } = await raceWithAbort(createFnAgent2({
|
|
195894
195928
|
cwd: repoRoot,
|
|
195895
195929
|
tools: "readonly",
|
|
195896
195930
|
defaultProvider: model.provider,
|
|
@@ -195903,7 +195937,7 @@ async function generatePrMetadata(input) {
|
|
|
195903
195937
|
onText: (delta) => {
|
|
195904
195938
|
aiText += delta;
|
|
195905
195939
|
}
|
|
195906
|
-
});
|
|
195940
|
+
}), combinedSignal);
|
|
195907
195941
|
try {
|
|
195908
195942
|
const contextPrompt = [
|
|
195909
195943
|
`Task ID: ${task.id}`,
|
|
@@ -195918,15 +195952,12 @@ async function generatePrMetadata(input) {
|
|
|
195918
195952
|
promptContent || "(none)"
|
|
195919
195953
|
].join("\n\n");
|
|
195920
195954
|
throwIfAborted3(combinedSignal);
|
|
195921
|
-
await
|
|
195955
|
+
await raceWithAbort(
|
|
195922
195956
|
session.prompt(contextPrompt, { signal: combinedSignal }),
|
|
195923
|
-
|
|
195924
|
-
|
|
195957
|
+
combinedSignal
|
|
195958
|
+
);
|
|
195925
195959
|
} finally {
|
|
195926
|
-
|
|
195927
|
-
session.dispose();
|
|
195928
|
-
} catch {
|
|
195929
|
-
}
|
|
195960
|
+
disposeSessionBestEffort(session);
|
|
195930
195961
|
}
|
|
195931
195962
|
const parsed = parseAiResult(aiText);
|
|
195932
195963
|
if (!parsed) {
|
|
@@ -199940,13 +199971,18 @@ ${body}`;
|
|
|
199940
199971
|
try {
|
|
199941
199972
|
const { store: scopedStore } = await getProjectContext3(req);
|
|
199942
199973
|
const { title, body, base } = req.body;
|
|
199943
|
-
if (!title || typeof title !== "string") {
|
|
199944
|
-
throw badRequest("title is required and must be a string");
|
|
199945
|
-
}
|
|
199946
199974
|
const task = await scopedStore.getTask(req.params.id);
|
|
199947
199975
|
if (task.column !== "in-review") {
|
|
199948
199976
|
throw badRequest("Task must be in 'in-review' column to create a PR");
|
|
199949
199977
|
}
|
|
199978
|
+
if (!title || typeof title !== "string") {
|
|
199979
|
+
throw badRequest("title is required and must be a string");
|
|
199980
|
+
}
|
|
199981
|
+
if (!body || typeof body !== "string" || !body.trim()) {
|
|
199982
|
+
throw badRequest("body is required and must be a non-empty string");
|
|
199983
|
+
}
|
|
199984
|
+
const prTitle = title.trim();
|
|
199985
|
+
const prBody = body.trim();
|
|
199950
199986
|
const existingPrs = getTaskPrList(task);
|
|
199951
199987
|
const branchName = `fusion/${task.id.toLowerCase()}`;
|
|
199952
199988
|
let owner;
|
|
@@ -199983,8 +200019,8 @@ ${body}`;
|
|
|
199983
200019
|
prInfo = await client.createPr({
|
|
199984
200020
|
owner,
|
|
199985
200021
|
repo,
|
|
199986
|
-
title,
|
|
199987
|
-
body,
|
|
200022
|
+
title: prTitle,
|
|
200023
|
+
body: prBody,
|
|
199988
200024
|
head: branchName,
|
|
199989
200025
|
base
|
|
199990
200026
|
});
|
|
@@ -200125,19 +200161,48 @@ ${body}`;
|
|
|
200125
200161
|
});
|
|
200126
200162
|
router.post("/tasks/:id/pr/generate-metadata", async (req, res) => {
|
|
200127
200163
|
const controller = new AbortController();
|
|
200128
|
-
|
|
200129
|
-
|
|
200164
|
+
let responseCompleted = false;
|
|
200165
|
+
const abortRequest = () => {
|
|
200166
|
+
if (!responseCompleted && !controller.signal.aborted) {
|
|
200167
|
+
const error = new Error("PR metadata request aborted");
|
|
200168
|
+
error.name = "AbortError";
|
|
200169
|
+
controller.abort(error);
|
|
200170
|
+
}
|
|
200171
|
+
};
|
|
200172
|
+
const markCompleted = () => {
|
|
200173
|
+
responseCompleted = true;
|
|
200174
|
+
};
|
|
200175
|
+
req.on("aborted", abortRequest);
|
|
200176
|
+
res.on("close", abortRequest);
|
|
200177
|
+
res.on("finish", markCompleted);
|
|
200130
200178
|
try {
|
|
200131
200179
|
const { store: scopedStore } = await getProjectContext3(req);
|
|
200132
200180
|
const task = await scopedStore.getTask(req.params.id);
|
|
200133
200181
|
const settings = await scopedStore.getSettings();
|
|
200134
|
-
|
|
200182
|
+
let timeoutId;
|
|
200183
|
+
const generatorPromise = generatePrMetadata({
|
|
200135
200184
|
task,
|
|
200136
200185
|
repoRoot: scopedStore.getRootDir(),
|
|
200137
200186
|
settings,
|
|
200138
|
-
signal: controller.signal
|
|
200187
|
+
signal: controller.signal,
|
|
200188
|
+
timeoutMs: PR_METADATA_ROUTE_TIMEOUT_MS
|
|
200189
|
+
});
|
|
200190
|
+
void generatorPromise.catch(() => void 0);
|
|
200191
|
+
const timeoutFallbackPromise = new Promise((resolve70) => {
|
|
200192
|
+
timeoutId = setTimeout(() => {
|
|
200193
|
+
abortRequest();
|
|
200194
|
+
resolve70(buildFallbackPrMetadata(task));
|
|
200195
|
+
}, PR_METADATA_ROUTE_TIMEOUT_MS);
|
|
200139
200196
|
});
|
|
200140
|
-
|
|
200197
|
+
let metadata;
|
|
200198
|
+
try {
|
|
200199
|
+
metadata = await Promise.race([generatorPromise, timeoutFallbackPromise]);
|
|
200200
|
+
} finally {
|
|
200201
|
+
if (timeoutId) {
|
|
200202
|
+
clearTimeout(timeoutId);
|
|
200203
|
+
}
|
|
200204
|
+
}
|
|
200205
|
+
if (res.writableEnded || res.writableFinished || res.destroyed) {
|
|
200141
200206
|
return;
|
|
200142
200207
|
}
|
|
200143
200208
|
res.json(metadata);
|
|
@@ -200150,7 +200215,9 @@ ${body}`;
|
|
|
200150
200215
|
}
|
|
200151
200216
|
rethrowAsApiError9(err, "Failed to generate PR metadata");
|
|
200152
200217
|
} finally {
|
|
200153
|
-
req.
|
|
200218
|
+
req.removeListener("aborted", abortRequest);
|
|
200219
|
+
res.removeListener("close", abortRequest);
|
|
200220
|
+
res.removeListener("finish", markCompleted);
|
|
200154
200221
|
}
|
|
200155
200222
|
});
|
|
200156
200223
|
router.get("/tasks/:id/pr/preflight", async (req, res) => {
|
|
@@ -200719,7 +200786,7 @@ ${body}`;
|
|
|
200719
200786
|
}
|
|
200720
200787
|
});
|
|
200721
200788
|
}
|
|
200722
|
-
var execAsync37, PR_ROUTE_MAX_BUFFER_BYTES, PR_PREFLIGHT_TIMEOUT_MS, PR_OPTIONS_TIMEOUT_MS, SAFE_GIT_REF_PATTERN, GITHUB_TRACKING_RECONCILE_INTERVAL_MS, RECENT_ISSUES_CACHE_TTL_MS, recentIssuesCache, prRouteCommandRunner, batchImportWindowMs, batchImportInstances, batchImportCleanupInterval;
|
|
200789
|
+
var execAsync37, PR_ROUTE_MAX_BUFFER_BYTES, PR_PREFLIGHT_TIMEOUT_MS, PR_OPTIONS_TIMEOUT_MS, PR_METADATA_ROUTE_TIMEOUT_MS, SAFE_GIT_REF_PATTERN, GITHUB_TRACKING_RECONCILE_INTERVAL_MS, RECENT_ISSUES_CACHE_TTL_MS, recentIssuesCache, prRouteCommandRunner, batchImportWindowMs, batchImportInstances, batchImportCleanupInterval;
|
|
200723
200790
|
var init_register_git_github = __esm({
|
|
200724
200791
|
"../dashboard/src/routes/register-git-github.ts"() {
|
|
200725
200792
|
"use strict";
|
|
@@ -200743,6 +200810,7 @@ var init_register_git_github = __esm({
|
|
|
200743
200810
|
PR_ROUTE_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
200744
200811
|
PR_PREFLIGHT_TIMEOUT_MS = 15e3;
|
|
200745
200812
|
PR_OPTIONS_TIMEOUT_MS = 1e4;
|
|
200813
|
+
PR_METADATA_ROUTE_TIMEOUT_MS = 25e3;
|
|
200746
200814
|
SAFE_GIT_REF_PATTERN = /^[A-Za-z0-9._/-]+$/;
|
|
200747
200815
|
GITHUB_TRACKING_RECONCILE_INTERVAL_MS = 15 * 60 * 1e3;
|
|
200748
200816
|
RECENT_ISSUES_CACHE_TTL_MS = 6e4;
|