@runfusion/fusion 0.1.3 → 0.2.1
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 +4155 -1194
- package/dist/client/assets/AgentDetailView-BMrHuWGs.css +1 -0
- package/dist/client/assets/AgentDetailView-CkuuGA1O.js +28 -0
- package/dist/client/assets/AgentsView-CWFLMIDP.js +522 -0
- package/dist/client/assets/AgentsView-DETxUmHS.css +1 -0
- package/dist/client/assets/ChatView-C_T91ebd.js +1 -0
- package/dist/client/assets/DevServerView-ChWTzTvy.js +11 -0
- package/dist/client/assets/DevServerView-ZeBGQkLI.css +1 -0
- package/dist/client/assets/DirectoryPicker-BMJIT7HD.js +1 -0
- package/dist/client/assets/DocumentsView-CjfVl8mZ.js +1 -0
- package/dist/client/assets/DocumentsView-Co9to4Zp.css +1 -0
- package/dist/client/assets/InsightsView-Egu71gmh.css +1 -0
- package/dist/client/assets/InsightsView-Rb735C9_.js +11 -0
- package/dist/client/assets/MemoryView-DhinauGs.css +1 -0
- package/dist/client/assets/MemoryView-LLc_uNtG.js +2 -0
- package/dist/client/assets/NodesView-BYVG2yY-.css +1 -0
- package/dist/client/assets/NodesView-BviqBWRA.js +14 -0
- package/dist/client/assets/PiExtensionsManager-CPgmJgDk.css +1 -0
- package/dist/client/assets/PiExtensionsManager-CriZBkQe.js +11 -0
- package/dist/client/assets/PluginManager-BywTPbLB.js +1 -0
- package/dist/client/assets/PluginManager-D64RIzmL.css +1 -0
- package/dist/client/assets/RoadmapsView-BOYnyMCh.css +1 -0
- package/dist/client/assets/RoadmapsView-Dhl--4vY.js +6 -0
- package/dist/client/assets/SetupWizardModal-CVtmwoJC.js +1 -0
- package/dist/client/assets/SkillsView-CG9y4fsE.js +1 -0
- package/dist/client/assets/SkillsView-Cytf009Z.css +1 -0
- package/dist/client/assets/folder-open-BVDq27HP.js +6 -0
- package/dist/client/assets/index-CikysL-d.js +644 -0
- package/dist/client/assets/index-Da1qmtc7.css +1 -0
- package/dist/client/assets/upload-BDvpReDO.js +6 -0
- package/dist/client/index.html +2 -2
- package/dist/extension.js +187 -76
- package/dist/pi-claude-cli/src/__tests__/control-handler.test.ts +191 -0
- package/dist/pi-claude-cli/src/__tests__/event-bridge.test.ts +1244 -0
- package/dist/pi-claude-cli/src/__tests__/mcp-config.test.ts +272 -0
- package/dist/pi-claude-cli/src/__tests__/process-manager.test.ts +619 -0
- package/dist/pi-claude-cli/src/__tests__/prompt-builder.test.ts +1067 -0
- package/dist/pi-claude-cli/src/__tests__/provider.test.ts +1902 -0
- package/dist/pi-claude-cli/src/__tests__/stream-parser.test.ts +188 -0
- package/dist/pi-claude-cli/src/__tests__/thinking-config.test.ts +141 -0
- package/dist/pi-claude-cli/src/__tests__/tool-mapping.test.ts +252 -0
- package/package.json +11 -5
- package/dist/client/assets/index-BuenKJX0.css +0 -1
- package/dist/client/assets/index-CjGu8HRV.js +0 -1250
package/dist/extension.js
CHANGED
|
@@ -60,6 +60,7 @@ var init_settings_schema = __esm({
|
|
|
60
60
|
defaultThinkingLevel: void 0,
|
|
61
61
|
ntfyEnabled: false,
|
|
62
62
|
ntfyTopic: void 0,
|
|
63
|
+
ntfyBaseUrl: void 0,
|
|
63
64
|
ntfyEvents: ["in-review", "merged", "failed", "awaiting-approval", "awaiting-user-review", "planning-awaiting-input"],
|
|
64
65
|
ntfyDashboardHost: void 0,
|
|
65
66
|
defaultProjectId: void 0,
|
|
@@ -47985,7 +47986,7 @@ var init_src = __esm({
|
|
|
47985
47986
|
}
|
|
47986
47987
|
});
|
|
47987
47988
|
|
|
47988
|
-
// ../engine/src/logger.
|
|
47989
|
+
// ../engine/src/logger.ts
|
|
47989
47990
|
function withSeverityMarker2(level, payload) {
|
|
47990
47991
|
return `${LOG_LEVEL_MARKER_PREFIX2}${level}${LOG_LEVEL_MARKER_SUFFIX2}${payload}`;
|
|
47991
47992
|
}
|
|
@@ -47993,13 +47994,13 @@ function createLogger2(prefix) {
|
|
|
47993
47994
|
const tag = `[${prefix}]`;
|
|
47994
47995
|
return {
|
|
47995
47996
|
log(message, ...args) {
|
|
47996
|
-
|
|
47997
|
+
console.error(withSeverityMarker2("info", `${tag} ${message}`), ...args);
|
|
47997
47998
|
},
|
|
47998
47999
|
warn(message, ...args) {
|
|
47999
|
-
|
|
48000
|
+
console.warn(withSeverityMarker2("warn", `${tag} ${message}`), ...args);
|
|
48000
48001
|
},
|
|
48001
48002
|
error(message, ...args) {
|
|
48002
|
-
|
|
48003
|
+
console.error(withSeverityMarker2("error", `${tag} ${message}`), ...args);
|
|
48003
48004
|
}
|
|
48004
48005
|
};
|
|
48005
48006
|
}
|
|
@@ -48025,7 +48026,7 @@ ${stack}` : message2;
|
|
|
48025
48026
|
}
|
|
48026
48027
|
var LOG_LEVEL_MARKER_PREFIX2, LOG_LEVEL_MARKER_SUFFIX2, schedulerLog, executorLog, triageLog, piLog, extensionsLog, mergerLog, worktreePoolLog, reviewerLog, prMonitorLog, runtimeLog, ipcLog, projectManagerLog, hybridExecutorLog, autopilotLog, heartbeatLog, remoteNodeLog, nodeHealthMonitorLog, peerExchangeLog;
|
|
48027
48028
|
var init_logger2 = __esm({
|
|
48028
|
-
"../engine/src/logger.
|
|
48029
|
+
"../engine/src/logger.ts"() {
|
|
48029
48030
|
"use strict";
|
|
48030
48031
|
LOG_LEVEL_MARKER_PREFIX2 = "\0fnlvl=";
|
|
48031
48032
|
LOG_LEVEL_MARKER_SUFFIX2 = "\0";
|
|
@@ -49184,7 +49185,7 @@ var init_concurrency = __esm({
|
|
|
49184
49185
|
}
|
|
49185
49186
|
});
|
|
49186
49187
|
|
|
49187
|
-
// ../engine/src/skill-resolver.
|
|
49188
|
+
// ../engine/src/skill-resolver.ts
|
|
49188
49189
|
import { existsSync as existsSync18, readFileSync as readFileSync4 } from "node:fs";
|
|
49189
49190
|
import { join as join22 } from "node:path";
|
|
49190
49191
|
function readJsonObject(path) {
|
|
@@ -49308,9 +49309,13 @@ function createSkillsOverrideFromSelection(selection, options = {}) {
|
|
|
49308
49309
|
let filteredSkills;
|
|
49309
49310
|
if (hasRequestedNames) {
|
|
49310
49311
|
const requestedNamesLower = new Set(requestedSkillNames.map((n) => n.toLowerCase()));
|
|
49311
|
-
filteredSkills = base.skills.filter(
|
|
49312
|
+
filteredSkills = base.skills.filter(
|
|
49313
|
+
(skill) => requestedNamesLower.has(skill.name.toLowerCase()) && !excludedSkillPaths.has(skill.filePath)
|
|
49314
|
+
);
|
|
49312
49315
|
} else if (hasPatterns) {
|
|
49313
|
-
filteredSkills = base.skills.filter(
|
|
49316
|
+
filteredSkills = base.skills.filter(
|
|
49317
|
+
(skill) => allowedSkillPaths.has(skill.filePath) && !excludedSkillPaths.has(skill.filePath)
|
|
49318
|
+
);
|
|
49314
49319
|
} else if (hasExcluded) {
|
|
49315
49320
|
filteredSkills = base.skills.filter((skill) => !excludedSkillPaths.has(skill.filePath));
|
|
49316
49321
|
} else {
|
|
@@ -49350,6 +49355,7 @@ function createSkillsOverrideFromSelection(selection, options = {}) {
|
|
|
49350
49355
|
}
|
|
49351
49356
|
}
|
|
49352
49357
|
if (newDiagnostics.length > 0) {
|
|
49358
|
+
const _purpose = sessionPurpose ? `[${sessionPurpose}]` : "skills";
|
|
49353
49359
|
for (const diag of newDiagnostics) {
|
|
49354
49360
|
piLog.warn(`[skills] ${diag.type}: ${diag.message}`);
|
|
49355
49361
|
}
|
|
@@ -49361,21 +49367,20 @@ function createSkillsOverrideFromSelection(selection, options = {}) {
|
|
|
49361
49367
|
};
|
|
49362
49368
|
}
|
|
49363
49369
|
var init_skill_resolver = __esm({
|
|
49364
|
-
"../engine/src/skill-resolver.
|
|
49370
|
+
"../engine/src/skill-resolver.ts"() {
|
|
49365
49371
|
"use strict";
|
|
49366
49372
|
init_logger2();
|
|
49367
49373
|
}
|
|
49368
49374
|
});
|
|
49369
49375
|
|
|
49370
|
-
// ../engine/src/context-limit-detector.
|
|
49376
|
+
// ../engine/src/context-limit-detector.ts
|
|
49371
49377
|
function isContextLimitError(message) {
|
|
49372
|
-
if (!message)
|
|
49373
|
-
return false;
|
|
49378
|
+
if (!message) return false;
|
|
49374
49379
|
return CONTEXT_OVERFLOW_PATTERNS.some((pattern) => pattern.test(message));
|
|
49375
49380
|
}
|
|
49376
49381
|
var CONTEXT_OVERFLOW_PATTERNS;
|
|
49377
49382
|
var init_context_limit_detector = __esm({
|
|
49378
|
-
"../engine/src/context-limit-detector.
|
|
49383
|
+
"../engine/src/context-limit-detector.ts"() {
|
|
49379
49384
|
"use strict";
|
|
49380
49385
|
CONTEXT_OVERFLOW_PATTERNS = [
|
|
49381
49386
|
// Anthropic: "prompt is too long: X tokens > Y maximum"
|
|
@@ -49412,14 +49417,14 @@ var init_context_limit_detector = __esm({
|
|
|
49412
49417
|
}
|
|
49413
49418
|
});
|
|
49414
49419
|
|
|
49415
|
-
// ../engine/src/auth-storage.
|
|
49420
|
+
// ../engine/src/auth-storage.ts
|
|
49416
49421
|
import { existsSync as existsSync19, readFileSync as readFileSync5 } from "node:fs";
|
|
49417
49422
|
import { homedir as homedir4 } from "node:os";
|
|
49418
49423
|
import { join as join23 } from "node:path";
|
|
49419
49424
|
import { AuthStorage } from "@mariozechner/pi-coding-agent";
|
|
49420
49425
|
import { getOAuthProvider } from "@mariozechner/pi-ai/oauth";
|
|
49421
49426
|
function getHomeDir2() {
|
|
49422
|
-
return
|
|
49427
|
+
return process.env.HOME || process.env.USERPROFILE || homedir4();
|
|
49423
49428
|
}
|
|
49424
49429
|
function getFusionAuthPath(home = getHomeDir2()) {
|
|
49425
49430
|
return join23(home, ".fusion", "agent", "auth.json");
|
|
@@ -49463,9 +49468,8 @@ function readLegacyCredentials(authPaths = getLegacyAuthPaths()) {
|
|
|
49463
49468
|
return credentials;
|
|
49464
49469
|
}
|
|
49465
49470
|
function resolveStoredApiKey(key) {
|
|
49466
|
-
if (!key)
|
|
49467
|
-
|
|
49468
|
-
return globalThis.process.env[key] ?? key;
|
|
49471
|
+
if (!key) return void 0;
|
|
49472
|
+
return process.env[key] ?? key;
|
|
49469
49473
|
}
|
|
49470
49474
|
function resolveOAuthApiKey(providerId, credential) {
|
|
49471
49475
|
if (credential.type !== "oauth" || typeof credential.access !== "string" || typeof credential.refresh !== "string" || typeof credential.expires !== "number" || Date.now() >= credential.expires) {
|
|
@@ -49511,8 +49515,7 @@ function createFusionAuthStorage() {
|
|
|
49511
49515
|
if (prop === "getApiKey") {
|
|
49512
49516
|
return async (provider) => {
|
|
49513
49517
|
const primaryKey = await target.getApiKey(provider);
|
|
49514
|
-
if (primaryKey)
|
|
49515
|
-
return primaryKey;
|
|
49518
|
+
if (primaryKey) return primaryKey;
|
|
49516
49519
|
return resolveStoredCredentialApiKey(provider, legacyCredentials[provider]);
|
|
49517
49520
|
};
|
|
49518
49521
|
}
|
|
@@ -49521,12 +49524,12 @@ function createFusionAuthStorage() {
|
|
|
49521
49524
|
});
|
|
49522
49525
|
}
|
|
49523
49526
|
var init_auth_storage = __esm({
|
|
49524
|
-
"../engine/src/auth-storage.
|
|
49527
|
+
"../engine/src/auth-storage.ts"() {
|
|
49525
49528
|
"use strict";
|
|
49526
49529
|
}
|
|
49527
49530
|
});
|
|
49528
49531
|
|
|
49529
|
-
// ../engine/src/pi.
|
|
49532
|
+
// ../engine/src/pi.ts
|
|
49530
49533
|
var pi_exports = {};
|
|
49531
49534
|
__export(pi_exports, {
|
|
49532
49535
|
COMPACTION_FALLBACK_INSTRUCTIONS: () => COMPACTION_FALLBACK_INSTRUCTIONS,
|
|
@@ -49540,19 +49543,35 @@ import { existsSync as existsSync20, readFileSync as readFileSync6 } from "node:
|
|
|
49540
49543
|
import { exec } from "node:child_process";
|
|
49541
49544
|
import { promisify as promisify2 } from "node:util";
|
|
49542
49545
|
import { basename as basename7, dirname as dirname7, join as join24, relative as relative3, isAbsolute as isAbsolute6, resolve as resolve10 } from "node:path";
|
|
49543
|
-
import {
|
|
49546
|
+
import {
|
|
49547
|
+
createAgentSession,
|
|
49548
|
+
createCodingTools,
|
|
49549
|
+
createExtensionRuntime,
|
|
49550
|
+
createReadOnlyTools,
|
|
49551
|
+
DefaultResourceLoader,
|
|
49552
|
+
DefaultPackageManager,
|
|
49553
|
+
discoverAndLoadExtensions,
|
|
49554
|
+
ModelRegistry,
|
|
49555
|
+
SessionManager,
|
|
49556
|
+
SettingsManager
|
|
49557
|
+
} from "@mariozechner/pi-coding-agent";
|
|
49544
49558
|
function getSessionStateError(session) {
|
|
49545
|
-
const
|
|
49559
|
+
const state = session.state;
|
|
49560
|
+
const error = state?.errorMessage ?? state?.error;
|
|
49546
49561
|
return typeof error === "string" ? error : "";
|
|
49547
49562
|
}
|
|
49548
49563
|
function clearSessionStateError(session) {
|
|
49549
49564
|
const state = session.state;
|
|
49550
|
-
if (!state || typeof state !== "object"
|
|
49565
|
+
if (!state || typeof state !== "object") {
|
|
49551
49566
|
return;
|
|
49552
49567
|
}
|
|
49553
|
-
|
|
49554
|
-
|
|
49555
|
-
|
|
49568
|
+
for (const key of ["errorMessage", "error"]) {
|
|
49569
|
+
if (key in state) {
|
|
49570
|
+
try {
|
|
49571
|
+
state[key] = void 0;
|
|
49572
|
+
} catch {
|
|
49573
|
+
}
|
|
49574
|
+
}
|
|
49556
49575
|
}
|
|
49557
49576
|
}
|
|
49558
49577
|
async function promptSessionAndCheck(session, prompt, options) {
|
|
@@ -49564,6 +49583,29 @@ async function promptSessionAndCheck(session, prompt, options) {
|
|
|
49564
49583
|
}
|
|
49565
49584
|
const stateError = getSessionStateError(session);
|
|
49566
49585
|
if (stateError) {
|
|
49586
|
+
if (/Cannot read propert(y|ies) of (undefined|null)/i.test(stateError)) {
|
|
49587
|
+
try {
|
|
49588
|
+
const messages = session.agent?.state?.messages ?? session.state?.messages;
|
|
49589
|
+
if (Array.isArray(messages)) {
|
|
49590
|
+
const recent = messages.slice(-6).map((m, idx) => {
|
|
49591
|
+
const i = messages.length - 6 + idx;
|
|
49592
|
+
const content = m?.content;
|
|
49593
|
+
return {
|
|
49594
|
+
index: i < 0 ? idx : i,
|
|
49595
|
+
role: m?.role,
|
|
49596
|
+
contentType: Array.isArray(content) ? `array(len=${content.length})` : typeof content,
|
|
49597
|
+
toolName: m.toolName,
|
|
49598
|
+
stopReason: m.stopReason
|
|
49599
|
+
};
|
|
49600
|
+
});
|
|
49601
|
+
piLog.error(`pi state error \u2014 transcript tail (${messages.length} msgs total): ${JSON.stringify(recent)}`);
|
|
49602
|
+
} else {
|
|
49603
|
+
piLog.error(`pi state error \u2014 state.messages is not an array: ${typeof messages}`);
|
|
49604
|
+
}
|
|
49605
|
+
} catch (inspectErr) {
|
|
49606
|
+
piLog.warn(`pi state error \u2014 failed to inspect transcript: ${inspectErr instanceof Error ? inspectErr.message : String(inspectErr)}`);
|
|
49607
|
+
}
|
|
49608
|
+
}
|
|
49567
49609
|
throw new Error(stateError);
|
|
49568
49610
|
}
|
|
49569
49611
|
}
|
|
@@ -49615,8 +49657,7 @@ async function promptWithFallback(session, prompt, options) {
|
|
|
49615
49657
|
}
|
|
49616
49658
|
function describeModel(session) {
|
|
49617
49659
|
const model = session.model;
|
|
49618
|
-
if (!model)
|
|
49619
|
-
return "unknown model";
|
|
49660
|
+
if (!model) return "unknown model";
|
|
49620
49661
|
return `${model.provider}/${model.id}`;
|
|
49621
49662
|
}
|
|
49622
49663
|
function compactMarkdownMemorySection(sectionBody) {
|
|
@@ -49669,7 +49710,9 @@ async function retryWithCompactedPromptMemory(session, prompt, options) {
|
|
|
49669
49710
|
if (!compactedPrompt) {
|
|
49670
49711
|
return { recovered: false };
|
|
49671
49712
|
}
|
|
49672
|
-
piLog.log(
|
|
49713
|
+
piLog.log(
|
|
49714
|
+
`promptWithFallback: retrying with compacted prompt memory (${prompt.length} \u2192 ${compactedPrompt.length} chars)`
|
|
49715
|
+
);
|
|
49673
49716
|
try {
|
|
49674
49717
|
await promptSessionAndCheck(session, compactedPrompt, options);
|
|
49675
49718
|
piLog.log("promptWithFallback: prompt completed after prompt-memory compaction");
|
|
@@ -49686,7 +49729,7 @@ async function flushMemoryBeforeSessionCompaction(session) {
|
|
|
49686
49729
|
}
|
|
49687
49730
|
const flushPrompt = [
|
|
49688
49731
|
"Before context compaction, preserve only unresolved durable memory if needed.",
|
|
49689
|
-
"If
|
|
49732
|
+
"If fn_memory_append is available and you learned reusable project decisions, conventions, pitfalls, or open loops that are not already saved, append them now.",
|
|
49690
49733
|
'Use layer="long-term" for durable facts and layer="daily" for running notes/open loops.',
|
|
49691
49734
|
"If there is nothing durable to save, reply exactly: NONE."
|
|
49692
49735
|
].join("\n");
|
|
@@ -49731,7 +49774,9 @@ function resolveConfiguredModel(modelRegistry, kind, provider, modelId) {
|
|
|
49731
49774
|
piLog.warn(`${kind} model ${provider}/${modelId} not in registry; using provider base model as template`);
|
|
49732
49775
|
return { ...baseModel, id: modelId, name: modelId };
|
|
49733
49776
|
}
|
|
49734
|
-
throw new Error(
|
|
49777
|
+
throw new Error(
|
|
49778
|
+
`Configured ${kind} model ${provider}/${modelId} was not found in the pi model registry. Open Settings and choose a model from /api/models, or update your pi model configuration.`
|
|
49779
|
+
);
|
|
49735
49780
|
}
|
|
49736
49781
|
function isRetryableModelSelectionError(message) {
|
|
49737
49782
|
const normalized = message.toLowerCase();
|
|
@@ -49776,11 +49821,18 @@ function normalizeAssistantOrToolResultMessage(message) {
|
|
|
49776
49821
|
return false;
|
|
49777
49822
|
}
|
|
49778
49823
|
const role = message.role;
|
|
49779
|
-
if (role !== "assistant" && role !== "toolResult") {
|
|
49824
|
+
if (role !== "assistant" && role !== "toolResult" && role !== "user") {
|
|
49780
49825
|
return false;
|
|
49781
49826
|
}
|
|
49782
|
-
|
|
49783
|
-
|
|
49827
|
+
const obj = message;
|
|
49828
|
+
if (role === "user") {
|
|
49829
|
+
if (typeof obj.content !== "string" && !Array.isArray(obj.content)) {
|
|
49830
|
+
obj.content = [];
|
|
49831
|
+
}
|
|
49832
|
+
return true;
|
|
49833
|
+
}
|
|
49834
|
+
if (!Array.isArray(obj.content)) {
|
|
49835
|
+
obj.content = [];
|
|
49784
49836
|
}
|
|
49785
49837
|
return true;
|
|
49786
49838
|
}
|
|
@@ -49837,6 +49889,12 @@ function installMessageContentGuard(session, sessionManager) {
|
|
|
49837
49889
|
if (session.__fusionMessageContentGuardInstalled) {
|
|
49838
49890
|
return;
|
|
49839
49891
|
}
|
|
49892
|
+
const existingMessages = session.agent?.state?.messages;
|
|
49893
|
+
if (Array.isArray(existingMessages)) {
|
|
49894
|
+
for (const candidate of existingMessages) {
|
|
49895
|
+
normalizeAssistantOrToolResultMessage(candidate);
|
|
49896
|
+
}
|
|
49897
|
+
}
|
|
49840
49898
|
if (typeof session.subscribe === "function") {
|
|
49841
49899
|
session.subscribe((event) => {
|
|
49842
49900
|
if (!event || typeof event !== "object" || event.type !== "message_end") {
|
|
@@ -49879,8 +49937,8 @@ function createReadOnlyPiSettingsView(cwd, agentDir) {
|
|
|
49879
49937
|
const fusionProjectSettings = readJsonObject2(join24(projectRoot, ".fusion", "settings.json"));
|
|
49880
49938
|
const mergedSettings = { ...globalSettings, ...fusionProjectSettings };
|
|
49881
49939
|
return {
|
|
49882
|
-
getGlobalSettings: () =>
|
|
49883
|
-
getProjectSettings: () =>
|
|
49940
|
+
getGlobalSettings: () => structuredClone(globalSettings),
|
|
49941
|
+
getProjectSettings: () => structuredClone(fusionProjectSettings),
|
|
49884
49942
|
getNpmCommand: () => Array.isArray(mergedSettings.npmCommand) ? [...mergedSettings.npmCommand] : void 0
|
|
49885
49943
|
};
|
|
49886
49944
|
}
|
|
@@ -49907,7 +49965,11 @@ async function registerExtensionProviders(cwd, modelRegistry) {
|
|
|
49907
49965
|
});
|
|
49908
49966
|
const resolvedPaths = await packageManager.resolve();
|
|
49909
49967
|
const packageExtensionPaths = resolvedPaths.extensions.filter((resource) => resource.enabled).map((resource) => resource.path);
|
|
49910
|
-
const extensionsResult = await discoverAndLoadExtensions(
|
|
49968
|
+
const extensionsResult = await discoverAndLoadExtensions(
|
|
49969
|
+
[...getEnabledPiExtensionPaths(cwd), ...packageExtensionPaths],
|
|
49970
|
+
cwd,
|
|
49971
|
+
join24(resolvePiExtensionProjectRoot(cwd), ".fusion", "disabled-auto-extension-discovery")
|
|
49972
|
+
);
|
|
49911
49973
|
for (const { path, error } of extensionsResult.errors) {
|
|
49912
49974
|
extensionsLog.warn(`Failed to load ${path}: ${error}`);
|
|
49913
49975
|
}
|
|
@@ -49942,7 +50004,9 @@ async function isRegisteredGitWorktree(projectRoot, worktreePath) {
|
|
|
49942
50004
|
encoding: "utf-8"
|
|
49943
50005
|
});
|
|
49944
50006
|
const resolvedWorktree = resolve10(worktreePath);
|
|
49945
|
-
return stdout.split("\n").some(
|
|
50007
|
+
return stdout.split("\n").some(
|
|
50008
|
+
(line) => line.startsWith("worktree ") && resolve10(line.slice("worktree ".length)) === resolvedWorktree
|
|
50009
|
+
);
|
|
49946
50010
|
} catch {
|
|
49947
50011
|
return false;
|
|
49948
50012
|
}
|
|
@@ -49969,7 +50033,7 @@ async function assertValidWorktreeSession(cwd, projectRoot) {
|
|
|
49969
50033
|
throw new Error(`Refusing to start coding agent in unregistered git worktree: ${cwd}`);
|
|
49970
50034
|
}
|
|
49971
50035
|
}
|
|
49972
|
-
function isWorktreeAllowedPath(worktreePath, projectRoot, requestedPath) {
|
|
50036
|
+
function isWorktreeAllowedPath(worktreePath, projectRoot, requestedPath, toolName) {
|
|
49973
50037
|
const worktreeResolved = resolve10(worktreePath);
|
|
49974
50038
|
const projectRootResolved = resolve10(projectRoot);
|
|
49975
50039
|
const requestedResolved = isAbsolute6(requestedPath) ? resolve10(requestedPath) : resolve10(worktreeResolved, requestedPath);
|
|
@@ -49984,8 +50048,20 @@ function isWorktreeAllowedPath(worktreePath, projectRoot, requestedPath) {
|
|
|
49984
50048
|
if (relToProjectRoot.match(/^\.fusion\/tasks\/[^/]+\/attachments\//)) {
|
|
49985
50049
|
return true;
|
|
49986
50050
|
}
|
|
50051
|
+
const readOnlyTools = /* @__PURE__ */ new Set(["read", "glob", "grep"]);
|
|
50052
|
+
if (toolName && readOnlyTools.has(toolName) && /^\.fusion\/tasks\/[^/]+\/(PROMPT\.md|task\.json)$/.test(relToProjectRoot)) {
|
|
50053
|
+
return true;
|
|
50054
|
+
}
|
|
49987
50055
|
return false;
|
|
49988
50056
|
}
|
|
50057
|
+
function boundaryRejection(message) {
|
|
50058
|
+
return {
|
|
50059
|
+
content: [{ type: "text", text: message }],
|
|
50060
|
+
isError: true,
|
|
50061
|
+
ok: false,
|
|
50062
|
+
error: message
|
|
50063
|
+
};
|
|
50064
|
+
}
|
|
49989
50065
|
function wrapToolsWithBoundary(tools, worktreePath, projectRoot) {
|
|
49990
50066
|
if (!worktreePath || !projectRoot) {
|
|
49991
50067
|
return tools;
|
|
@@ -49999,21 +50075,21 @@ function wrapToolsWithBoundary(tools, worktreePath, projectRoot) {
|
|
|
49999
50075
|
return {
|
|
50000
50076
|
...tool,
|
|
50001
50077
|
execute: async (...args) => {
|
|
50078
|
+
const _toolCallId = args[0];
|
|
50002
50079
|
const params = args[1];
|
|
50080
|
+
const _signal = args[2];
|
|
50003
50081
|
const pathArg = params.path;
|
|
50004
|
-
if (pathArg && !isWorktreeAllowedPath(worktreePath, projectRoot, pathArg)) {
|
|
50082
|
+
if (pathArg && !isWorktreeAllowedPath(worktreePath, projectRoot, pathArg, tool.name)) {
|
|
50005
50083
|
const relToProject = relative3(projectRoot, pathArg);
|
|
50006
|
-
return
|
|
50007
|
-
|
|
50008
|
-
|
|
50009
|
-
};
|
|
50084
|
+
return boundaryRejection(
|
|
50085
|
+
`Path "${relToProject}" is outside the worktree boundary. Coding agents can only modify files inside the current worktree. Exceptions (read-only): .fusion/memory/, .fusion/tasks/*/attachments/, and .fusion/tasks/*/{PROMPT.md,task.json} for dependency context.`
|
|
50086
|
+
);
|
|
50010
50087
|
}
|
|
50011
50088
|
const cwdArg = params.cwd;
|
|
50012
|
-
if (tool.name === "bash" && cwdArg && !isWorktreeAllowedPath(worktreePath, projectRoot, cwdArg)) {
|
|
50013
|
-
return
|
|
50014
|
-
|
|
50015
|
-
|
|
50016
|
-
};
|
|
50089
|
+
if (tool.name === "bash" && cwdArg && !isWorktreeAllowedPath(worktreePath, projectRoot, cwdArg, tool.name)) {
|
|
50090
|
+
return boundaryRejection(
|
|
50091
|
+
`Working directory is outside the worktree boundary. Commands must run inside the worktree.`
|
|
50092
|
+
);
|
|
50017
50093
|
}
|
|
50018
50094
|
return originalExecute(...args);
|
|
50019
50095
|
}
|
|
@@ -50023,7 +50099,7 @@ function wrapToolsWithBoundary(tools, worktreePath, projectRoot) {
|
|
|
50023
50099
|
async function createFnAgent2(options) {
|
|
50024
50100
|
piLog.log(`createFnAgent called (cwd=${options.cwd}, tools=${options.tools}, provider=${options.defaultProvider}, model=${options.defaultModelId})`);
|
|
50025
50101
|
const authStorage = createFusionAuthStorage();
|
|
50026
|
-
const modelRegistry =
|
|
50102
|
+
const modelRegistry = ModelRegistry.create(authStorage, getModelRegistryModelsPath());
|
|
50027
50103
|
await registerExtensionProviders(options.cwd, modelRegistry);
|
|
50028
50104
|
const tools = options.tools === "readonly" ? createReadOnlyTools(options.cwd) : createCodingTools(options.cwd);
|
|
50029
50105
|
const worktreePath = options.cwd;
|
|
@@ -50036,8 +50112,18 @@ async function createFnAgent2(options) {
|
|
|
50036
50112
|
compaction: { enabled: true },
|
|
50037
50113
|
retry: { enabled: true, maxRetries: 3 }
|
|
50038
50114
|
});
|
|
50039
|
-
const selectedModel = resolveConfiguredModel(
|
|
50040
|
-
|
|
50115
|
+
const selectedModel = resolveConfiguredModel(
|
|
50116
|
+
modelRegistry,
|
|
50117
|
+
"primary",
|
|
50118
|
+
options.defaultProvider,
|
|
50119
|
+
options.defaultModelId
|
|
50120
|
+
);
|
|
50121
|
+
const fallbackModel = resolveConfiguredModel(
|
|
50122
|
+
modelRegistry,
|
|
50123
|
+
"fallback",
|
|
50124
|
+
options.fallbackProvider,
|
|
50125
|
+
options.fallbackModelId
|
|
50126
|
+
);
|
|
50041
50127
|
let effectiveSkillSelection = options.skillSelection;
|
|
50042
50128
|
if (!effectiveSkillSelection && options.skills && options.skills.length > 0) {
|
|
50043
50129
|
piLog.log(`Using skills from convenience parameter: [${options.skills.join(", ")}]`);
|
|
@@ -50063,6 +50149,7 @@ async function createFnAgent2(options) {
|
|
|
50063
50149
|
}
|
|
50064
50150
|
const resourceLoader = new DefaultResourceLoader({
|
|
50065
50151
|
cwd: options.cwd,
|
|
50152
|
+
agentDir: getFusionAgentDir(),
|
|
50066
50153
|
settingsManager,
|
|
50067
50154
|
systemPromptOverride: () => options.systemPrompt,
|
|
50068
50155
|
appendSystemPromptOverride: () => [],
|
|
@@ -50072,13 +50159,17 @@ async function createFnAgent2(options) {
|
|
|
50072
50159
|
const sessionManager = options.sessionManager ?? SessionManager.inMemory();
|
|
50073
50160
|
normalizeSessionHistoryEntries(sessionManager);
|
|
50074
50161
|
const createSessionWithModel = async (modelOverride) => {
|
|
50162
|
+
const customToolList = [
|
|
50163
|
+
...wrappedTools,
|
|
50164
|
+
...options.customTools ?? []
|
|
50165
|
+
];
|
|
50075
50166
|
return createAgentSession({
|
|
50076
50167
|
cwd: options.cwd,
|
|
50077
50168
|
authStorage,
|
|
50078
50169
|
modelRegistry,
|
|
50079
50170
|
resourceLoader,
|
|
50080
|
-
|
|
50081
|
-
customTools:
|
|
50171
|
+
noTools: "builtin",
|
|
50172
|
+
customTools: customToolList,
|
|
50082
50173
|
sessionManager,
|
|
50083
50174
|
settingsManager,
|
|
50084
50175
|
...modelOverride ? { model: modelOverride } : {}
|
|
@@ -50102,7 +50193,7 @@ async function createFnAgent2(options) {
|
|
|
50102
50193
|
const { session } = sessionResult;
|
|
50103
50194
|
installToolResultContentGuard(session);
|
|
50104
50195
|
installMessageContentGuard(session, sessionManager);
|
|
50105
|
-
session.__fusionMemoryAppendAvailable = options.customTools?.some((tool) => tool.name ===
|
|
50196
|
+
session.__fusionMemoryAppendAvailable = options.customTools?.some((tool) => tool.name === FN_MEMORY_APPEND_TOOL_NAME) === true;
|
|
50106
50197
|
const promptableSession = session;
|
|
50107
50198
|
promptableSession.promptWithFallback = async (prompt, promptOptions) => {
|
|
50108
50199
|
try {
|
|
@@ -50152,8 +50243,11 @@ async function createFnAgent2(options) {
|
|
|
50152
50243
|
const fallbackSessionResult = await createSessionWithModel(fallbackModel);
|
|
50153
50244
|
const fallbackSession = fallbackSessionResult.session;
|
|
50154
50245
|
installToolResultContentGuard(fallbackSession);
|
|
50155
|
-
installMessageContentGuard(
|
|
50156
|
-
|
|
50246
|
+
installMessageContentGuard(
|
|
50247
|
+
fallbackSession,
|
|
50248
|
+
sessionManager
|
|
50249
|
+
);
|
|
50250
|
+
fallbackSession.__fusionMemoryAppendAvailable = options.customTools?.some((tool) => tool.name === FN_MEMORY_APPEND_TOOL_NAME) === true;
|
|
50157
50251
|
if (options.defaultThinkingLevel) {
|
|
50158
50252
|
fallbackSession.setThinkingLevel(options.defaultThinkingLevel);
|
|
50159
50253
|
}
|
|
@@ -50235,9 +50329,9 @@ async function createFnAgent2(options) {
|
|
|
50235
50329
|
});
|
|
50236
50330
|
return { session: promptableSession, sessionFile: promptableSession.sessionFile };
|
|
50237
50331
|
}
|
|
50238
|
-
var execAsync, COMPACTION_FALLBACK_INSTRUCTIONS, MAX_COMPACTED_PROMPT_MEMORY_CHARS;
|
|
50332
|
+
var execAsync, FN_MEMORY_APPEND_TOOL_NAME, COMPACTION_FALLBACK_INSTRUCTIONS, MAX_COMPACTED_PROMPT_MEMORY_CHARS;
|
|
50239
50333
|
var init_pi = __esm({
|
|
50240
|
-
"../engine/src/pi.
|
|
50334
|
+
"../engine/src/pi.ts"() {
|
|
50241
50335
|
"use strict";
|
|
50242
50336
|
init_src();
|
|
50243
50337
|
init_skill_resolver();
|
|
@@ -50245,6 +50339,7 @@ var init_pi = __esm({
|
|
|
50245
50339
|
init_auth_storage();
|
|
50246
50340
|
init_logger2();
|
|
50247
50341
|
execAsync = promisify2(exec);
|
|
50342
|
+
FN_MEMORY_APPEND_TOOL_NAME = "fn_memory_append";
|
|
50248
50343
|
COMPACTION_FALLBACK_INSTRUCTIONS = [
|
|
50249
50344
|
"Summarize all completed steps concisely.",
|
|
50250
50345
|
"Preserve the current step number and any in-progress work details.",
|
|
@@ -63639,6 +63734,13 @@ function formatTaskIdentifier(task) {
|
|
|
63639
63734
|
const snippet = task.description.length > maxLen ? task.description.slice(0, maxLen) + "..." : task.description;
|
|
63640
63735
|
return `${task.id}: ${snippet}`;
|
|
63641
63736
|
}
|
|
63737
|
+
function resolveNtfyBaseUrl(baseUrl, fallback = DEFAULT_NTFY_BASE_URL) {
|
|
63738
|
+
const trimmed = baseUrl?.trim();
|
|
63739
|
+
if (!trimmed) {
|
|
63740
|
+
return fallback;
|
|
63741
|
+
}
|
|
63742
|
+
return trimmed.replace(/\/+$/, "");
|
|
63743
|
+
}
|
|
63642
63744
|
function resolveNtfyEvents(events) {
|
|
63643
63745
|
return events ? [...events] : [...DEFAULT_NTFY_EVENTS];
|
|
63644
63746
|
}
|
|
@@ -63662,7 +63764,7 @@ function buildNtfyClickUrl(options) {
|
|
|
63662
63764
|
return query ? `${normalizedHost}/?${query}` : `${normalizedHost}/`;
|
|
63663
63765
|
}
|
|
63664
63766
|
async function sendNtfyNotification({
|
|
63665
|
-
ntfyBaseUrl
|
|
63767
|
+
ntfyBaseUrl,
|
|
63666
63768
|
topic,
|
|
63667
63769
|
title,
|
|
63668
63770
|
message,
|
|
@@ -63679,7 +63781,8 @@ async function sendNtfyNotification({
|
|
|
63679
63781
|
if (clickUrl) {
|
|
63680
63782
|
headers.Click = clickUrl;
|
|
63681
63783
|
}
|
|
63682
|
-
const
|
|
63784
|
+
const resolvedBaseUrl = resolveNtfyBaseUrl(ntfyBaseUrl);
|
|
63785
|
+
const response = await fetch(`${resolvedBaseUrl}/${topic}`, {
|
|
63683
63786
|
method: "POST",
|
|
63684
63787
|
headers,
|
|
63685
63788
|
body: message,
|
|
@@ -63695,11 +63798,12 @@ async function sendNtfyNotification({
|
|
|
63695
63798
|
schedulerLog.log(`Failed to send ntfy notification: ${err}`);
|
|
63696
63799
|
}
|
|
63697
63800
|
}
|
|
63698
|
-
var DEFAULT_NTFY_EVENTS, NtfyNotifier;
|
|
63801
|
+
var DEFAULT_NTFY_BASE_URL, DEFAULT_NTFY_EVENTS, NtfyNotifier;
|
|
63699
63802
|
var init_notifier = __esm({
|
|
63700
63803
|
"../engine/src/notifier.ts"() {
|
|
63701
63804
|
"use strict";
|
|
63702
63805
|
init_logger2();
|
|
63806
|
+
DEFAULT_NTFY_BASE_URL = "https://ntfy.sh";
|
|
63703
63807
|
DEFAULT_NTFY_EVENTS = [
|
|
63704
63808
|
"in-review",
|
|
63705
63809
|
"merged",
|
|
@@ -63711,7 +63815,8 @@ var init_notifier = __esm({
|
|
|
63711
63815
|
NtfyNotifier = class {
|
|
63712
63816
|
constructor(store, options = {}) {
|
|
63713
63817
|
this.store = store;
|
|
63714
|
-
this.
|
|
63818
|
+
this.defaultNtfyBaseUrl = resolveNtfyBaseUrl(options.ntfyBaseUrl);
|
|
63819
|
+
this.ntfyBaseUrl = this.defaultNtfyBaseUrl;
|
|
63715
63820
|
this.projectId = options.projectId;
|
|
63716
63821
|
}
|
|
63717
63822
|
config = {
|
|
@@ -63721,6 +63826,7 @@ var init_notifier = __esm({
|
|
|
63721
63826
|
events: [...DEFAULT_NTFY_EVENTS]
|
|
63722
63827
|
};
|
|
63723
63828
|
ntfyBaseUrl;
|
|
63829
|
+
defaultNtfyBaseUrl;
|
|
63724
63830
|
projectId;
|
|
63725
63831
|
notifiedEvents = /* @__PURE__ */ new Set();
|
|
63726
63832
|
abortController = null;
|
|
@@ -63859,7 +63965,7 @@ var init_notifier = __esm({
|
|
|
63859
63965
|
};
|
|
63860
63966
|
handleSettingsUpdated = (data) => {
|
|
63861
63967
|
const { settings, previous } = data;
|
|
63862
|
-
if (settings.ntfyEnabled !== previous.ntfyEnabled || settings.ntfyTopic !== previous.ntfyTopic || settings.ntfyDashboardHost !== previous.ntfyDashboardHost || JSON.stringify(settings.ntfyEvents) !== JSON.stringify(previous.ntfyEvents)) {
|
|
63968
|
+
if (settings.ntfyEnabled !== previous.ntfyEnabled || settings.ntfyTopic !== previous.ntfyTopic || settings.ntfyBaseUrl !== previous.ntfyBaseUrl || settings.ntfyDashboardHost !== previous.ntfyDashboardHost || JSON.stringify(settings.ntfyEvents) !== JSON.stringify(previous.ntfyEvents)) {
|
|
63863
63969
|
const wasEnabled = this.config.enabled;
|
|
63864
63970
|
this.loadConfig(settings);
|
|
63865
63971
|
if (this.config.enabled && !wasEnabled) {
|
|
@@ -63868,6 +63974,8 @@ var init_notifier = __esm({
|
|
|
63868
63974
|
schedulerLog.log("NtfyNotifier disabled");
|
|
63869
63975
|
} else if (this.config.topic !== previous.ntfyTopic) {
|
|
63870
63976
|
schedulerLog.log("NtfyNotifier topic updated");
|
|
63977
|
+
} else if (this.ntfyBaseUrl !== resolveNtfyBaseUrl(previous.ntfyBaseUrl)) {
|
|
63978
|
+
schedulerLog.log("NtfyNotifier base URL updated");
|
|
63871
63979
|
} else if (this.config.dashboardHost !== previous.ntfyDashboardHost) {
|
|
63872
63980
|
schedulerLog.log("NtfyNotifier dashboard host updated");
|
|
63873
63981
|
} else if (JSON.stringify(this.config.events) !== JSON.stringify(previous.ntfyEvents)) {
|
|
@@ -63882,6 +63990,7 @@ var init_notifier = __esm({
|
|
|
63882
63990
|
dashboardHost: settings.ntfyDashboardHost,
|
|
63883
63991
|
events: resolveNtfyEvents(settings.ntfyEvents)
|
|
63884
63992
|
};
|
|
63993
|
+
this.ntfyBaseUrl = resolveNtfyBaseUrl(settings.ntfyBaseUrl, this.defaultNtfyBaseUrl);
|
|
63885
63994
|
}
|
|
63886
63995
|
isEventEnabled(event) {
|
|
63887
63996
|
return isNtfyEventEnabled(this.config.events, event);
|
|
@@ -67228,7 +67337,7 @@ var init_self_healing = __esm({
|
|
|
67228
67337
|
const recoverFn = this.options.recoverCompletedTask;
|
|
67229
67338
|
if (!recoverFn) return 0;
|
|
67230
67339
|
try {
|
|
67231
|
-
const tasks = await this.store.listTasks({ column: "in-progress" });
|
|
67340
|
+
const tasks = await this.store.listTasks({ column: "in-progress", slim: true });
|
|
67232
67341
|
const executingIds = this.options.getExecutingTaskIds?.() ?? /* @__PURE__ */ new Set();
|
|
67233
67342
|
const stuckCompleted = tasks.filter(
|
|
67234
67343
|
(t) => t.column === "in-progress" && !t.paused && !executingIds.has(t.id) && t.steps.length > 0 && t.steps.every((s) => s.status === "done" || s.status === "skipped")
|
|
@@ -67262,7 +67371,7 @@ var init_self_healing = __esm({
|
|
|
67262
67371
|
*/
|
|
67263
67372
|
async recoverMergeableReviewTasks() {
|
|
67264
67373
|
try {
|
|
67265
|
-
const tasks = await this.store.listTasks({ column: "in-review" });
|
|
67374
|
+
const tasks = await this.store.listTasks({ column: "in-review", slim: true });
|
|
67266
67375
|
const mergeable = tasks.filter(
|
|
67267
67376
|
(t) => t.column === "in-review" && Boolean(t.worktree) && t.mergeDetails?.mergeConfirmed !== true && getTaskMergeBlocker(t) === void 0
|
|
67268
67377
|
);
|
|
@@ -67319,7 +67428,7 @@ var init_self_healing = __esm({
|
|
|
67319
67428
|
const settings = await this.store.getSettings();
|
|
67320
67429
|
const maxFixes = settings.maxPostReviewFixes ?? 1;
|
|
67321
67430
|
if (!Number.isFinite(maxFixes) || maxFixes <= 0) return 0;
|
|
67322
|
-
const tasks = await this.store.listTasks({ column: "in-review" });
|
|
67431
|
+
const tasks = await this.store.listTasks({ column: "in-review", slim: true });
|
|
67323
67432
|
const executingIds = this.options.getExecutingTaskIds?.() ?? /* @__PURE__ */ new Set();
|
|
67324
67433
|
const candidates = tasks.filter((task) => {
|
|
67325
67434
|
if (task.column !== "in-review") return false;
|
|
@@ -67384,7 +67493,7 @@ var init_self_healing = __esm({
|
|
|
67384
67493
|
const timeoutMs = settings.taskStuckTimeoutMs;
|
|
67385
67494
|
if (!timeoutMs || timeoutMs <= 0) return 0;
|
|
67386
67495
|
const now = Date.now();
|
|
67387
|
-
const tasks = await this.store.listTasks({ column: "in-review" });
|
|
67496
|
+
const tasks = await this.store.listTasks({ column: "in-review", slim: true });
|
|
67388
67497
|
const staleIncomplete = tasks.filter(
|
|
67389
67498
|
(task) => task.column === "in-review" && !task.paused && !task.status && task.steps.length > 0 && task.steps.some((step) => NON_TERMINAL_STEP_STATUSES2.has(step.status)) && now - new Date(task.updatedAt).getTime() >= timeoutMs
|
|
67390
67499
|
);
|
|
@@ -67431,7 +67540,7 @@ var init_self_healing = __esm({
|
|
|
67431
67540
|
const settings = await this.store.getSettings();
|
|
67432
67541
|
const timeoutMs = settings.taskStuckTimeoutMs;
|
|
67433
67542
|
if (!timeoutMs || timeoutMs <= 0) return 0;
|
|
67434
|
-
const tasks = await this.store.listTasks({ column: "in-review" });
|
|
67543
|
+
const tasks = await this.store.listTasks({ column: "in-review", slim: true });
|
|
67435
67544
|
const candidates = tasks.filter(
|
|
67436
67545
|
(task) => task.column === "in-review" && Boolean(task.status && ACTIVE_MERGE_STATUSES.has(task.status)) && this.isPastInterruptedMergeGrace(task, timeoutMs)
|
|
67437
67546
|
);
|
|
@@ -67502,7 +67611,7 @@ var init_self_healing = __esm({
|
|
|
67502
67611
|
*/
|
|
67503
67612
|
async recoverMergedReviewTasks() {
|
|
67504
67613
|
try {
|
|
67505
|
-
const tasks = await this.store.listTasks({ column: "in-review" });
|
|
67614
|
+
const tasks = await this.store.listTasks({ column: "in-review", slim: true });
|
|
67506
67615
|
const mergedButNotDone = tasks.filter(
|
|
67507
67616
|
(t) => t.column === "in-review" && t.mergeDetails?.mergeConfirmed === true
|
|
67508
67617
|
);
|
|
@@ -67550,7 +67659,7 @@ var init_self_healing = __esm({
|
|
|
67550
67659
|
*/
|
|
67551
67660
|
async recoverMisclassifiedFailures() {
|
|
67552
67661
|
try {
|
|
67553
|
-
const tasks = await this.store.listTasks({ column: "in-review" });
|
|
67662
|
+
const tasks = await this.store.listTasks({ column: "in-review", slim: true });
|
|
67554
67663
|
const misclassified = tasks.filter(
|
|
67555
67664
|
(t) => t.column === "in-review" && t.status === "failed" && t.error?.includes("without calling task_done") && t.steps.length > 0 && t.steps.every((s) => s.status === "done" || s.status === "skipped")
|
|
67556
67665
|
);
|
|
@@ -67591,7 +67700,7 @@ var init_self_healing = __esm({
|
|
|
67591
67700
|
*/
|
|
67592
67701
|
async recoverOrphanedExecutions() {
|
|
67593
67702
|
try {
|
|
67594
|
-
const tasks = await this.store.listTasks({ column: "in-progress" });
|
|
67703
|
+
const tasks = await this.store.listTasks({ column: "in-progress", slim: true });
|
|
67595
67704
|
const executingIds = this.options.getExecutingTaskIds?.() ?? /* @__PURE__ */ new Set();
|
|
67596
67705
|
const now = Date.now();
|
|
67597
67706
|
const orphaned = tasks.filter((t) => {
|
|
@@ -67648,7 +67757,7 @@ var init_self_healing = __esm({
|
|
|
67648
67757
|
*/
|
|
67649
67758
|
async recoverNoProgressNoTaskDoneFailures() {
|
|
67650
67759
|
try {
|
|
67651
|
-
const tasks = await this.store.listTasks({ column: "in-progress" });
|
|
67760
|
+
const tasks = await this.store.listTasks({ column: "in-progress", slim: true });
|
|
67652
67761
|
const executingIds = this.options.getExecutingTaskIds?.() ?? /* @__PURE__ */ new Set();
|
|
67653
67762
|
const candidates = tasks.filter(
|
|
67654
67763
|
(task) => task.column === "in-progress" && task.status === "failed" && isNoTaskDoneFailure(task) && !task.paused && !executingIds.has(task.id) && !isTaskWorkComplete(task) && !hasStepProgress(task)
|
|
@@ -67710,7 +67819,7 @@ var init_self_healing = __esm({
|
|
|
67710
67819
|
*/
|
|
67711
67820
|
async recoverPartialProgressNoTaskDoneFailures() {
|
|
67712
67821
|
try {
|
|
67713
|
-
const tasks = await this.store.listTasks({ column: "in-review" });
|
|
67822
|
+
const tasks = await this.store.listTasks({ column: "in-review", slim: true });
|
|
67714
67823
|
const candidates = tasks.filter(
|
|
67715
67824
|
(task) => task.column === "in-review" && task.status === "failed" && isNoTaskDoneFailure(task) && !task.paused && !isTaskWorkComplete(task) && hasStepProgress(task) && (task.taskDoneRetryCount ?? 0) < MAX_TASK_DONE_RETRIES
|
|
67716
67825
|
);
|
|
@@ -74135,9 +74244,11 @@ Output ONLY the prompt text (no markdown, no explanations).`;
|
|
|
74135
74244
|
});
|
|
74136
74245
|
|
|
74137
74246
|
// ../dashboard/src/sse.ts
|
|
74247
|
+
var SSE_MAX_BUFFERED_BYTES;
|
|
74138
74248
|
var init_sse = __esm({
|
|
74139
74249
|
"../dashboard/src/sse.ts"() {
|
|
74140
74250
|
"use strict";
|
|
74251
|
+
SSE_MAX_BUFFERED_BYTES = 4 * 1024 * 1024;
|
|
74141
74252
|
}
|
|
74142
74253
|
});
|
|
74143
74254
|
|