@runfusion/fusion 0.8.1 → 0.8.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 +604 -484
- package/dist/client/assets/{AgentDetailView-CLzxf6Z7.js → AgentDetailView-B6wfIQ9j.js} +1 -1
- package/dist/client/assets/{AgentsView-CXaYJX_G.js → AgentsView-Fcym0XCw.js} +3 -3
- package/dist/client/assets/{ChatView-iXxGAaN1.js → ChatView-DEckS3f3.js} +1 -1
- package/dist/client/assets/{DevServerView-BeXfFkF4.js → DevServerView-CmMS4D6V.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-BMn5fjn9.js → DirectoryPicker-CQtE-YyA.js} +1 -1
- package/dist/client/assets/{DocumentsView-CjrtI3TX.js → DocumentsView-C4HDkN_0.js} +1 -1
- package/dist/client/assets/{InsightsView-BkfQ-TV1.js → InsightsView-oNQ7h5e8.js} +1 -1
- package/dist/client/assets/{MemoryView-1G0zWu1i.js → MemoryView-DPYGW09y.js} +1 -1
- package/dist/client/assets/{NodesView-Bn_1R73N.js → NodesView-DsM-c8RF.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-CqGOtQnR.js → PiExtensionsManager-DHgMjjRE.js} +1 -1
- package/dist/client/assets/{PluginManager-CM5QGvSG.js → PluginManager-N-7Sw_tE.js} +1 -1
- package/dist/client/assets/{RoadmapsView-B4VnQP83.js → RoadmapsView-BgX79uYM.js} +1 -1
- package/dist/client/assets/{SettingsModal-C3LckzfT.js → SettingsModal-BIKEMPwb.js} +1 -1
- package/dist/client/assets/{SettingsModal-BiLA-BeG.js → SettingsModal-C4EwtN6K.js} +3 -3
- package/dist/client/assets/{SetupWizardModal-Bk_8HfLm.js → SetupWizardModal-D2m0i9Io.js} +1 -1
- package/dist/client/assets/{SkillsView-CRvqF8P1.js → SkillsView-Eb1Mngnt.js} +1 -1
- package/dist/client/assets/{TodoView-Vzui5Eha.js → TodoView-BN8FQYyp.js} +1 -1
- package/dist/client/assets/{folder-open-CMF89prE.js → folder-open-BqZBHfoZ.js} +1 -1
- package/dist/client/assets/{index-B8kH5y4Q.js → index-DlHPhpDu.js} +3 -3
- package/dist/client/assets/{list-checks-M95d1uAy.js → list-checks-D2EURsP0.js} +1 -1
- package/dist/client/assets/{star-DHhJD6ow.js → star-CNQlAD8p.js} +1 -1
- package/dist/client/assets/{upload-CEq8jic8.js → upload-uoxlYkig.js} +1 -1
- package/dist/client/assets/{users-CUA8Tv-d.js → users-BLvidusm.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/version.json +1 -1
- package/dist/extension.js +313 -155
- package/dist/pi-claude-cli/package.json +1 -4
- package/package.json +1 -1
- package/dist/pi-claude-cli/src/types/cross-spawn.d.ts +0 -7
package/dist/extension.js
CHANGED
|
@@ -6484,9 +6484,9 @@ var init_global_settings = __esm({
|
|
|
6484
6484
|
* Serialize operations via promise chain to prevent lost-update races.
|
|
6485
6485
|
*/
|
|
6486
6486
|
withLock(fn) {
|
|
6487
|
-
let
|
|
6487
|
+
let resolve19;
|
|
6488
6488
|
const next = new Promise((r) => {
|
|
6489
|
-
|
|
6489
|
+
resolve19 = r;
|
|
6490
6490
|
});
|
|
6491
6491
|
const prev = this.lock;
|
|
6492
6492
|
this.lock = next;
|
|
@@ -6494,7 +6494,7 @@ var init_global_settings = __esm({
|
|
|
6494
6494
|
try {
|
|
6495
6495
|
return await fn();
|
|
6496
6496
|
} finally {
|
|
6497
|
-
|
|
6497
|
+
resolve19();
|
|
6498
6498
|
}
|
|
6499
6499
|
});
|
|
6500
6500
|
}
|
|
@@ -11804,8 +11804,8 @@ import { join as join8, dirname as dirname2 } from "node:path";
|
|
|
11804
11804
|
import { fileURLToPath } from "node:url";
|
|
11805
11805
|
function getAppVersion() {
|
|
11806
11806
|
if (cachedVersion !== null) return cachedVersion;
|
|
11807
|
-
const
|
|
11808
|
-
let currentDir =
|
|
11807
|
+
const __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
11808
|
+
let currentDir = __dirname2;
|
|
11809
11809
|
for (let i = 0; i < 10; i++) {
|
|
11810
11810
|
try {
|
|
11811
11811
|
const pkgPath = join8(currentDir, "package.json");
|
|
@@ -27790,9 +27790,9 @@ var init_automation_store = __esm({
|
|
|
27790
27790
|
*/
|
|
27791
27791
|
withScheduleLock(id, fn) {
|
|
27792
27792
|
const prev = this.scheduleLocks.get(id) ?? Promise.resolve();
|
|
27793
|
-
let
|
|
27793
|
+
let resolve19;
|
|
27794
27794
|
const next = new Promise((r) => {
|
|
27795
|
-
|
|
27795
|
+
resolve19 = r;
|
|
27796
27796
|
});
|
|
27797
27797
|
this.scheduleLocks.set(id, next);
|
|
27798
27798
|
return prev.then(async () => {
|
|
@@ -27802,7 +27802,7 @@ var init_automation_store = __esm({
|
|
|
27802
27802
|
if (this.scheduleLocks.get(id) === next) {
|
|
27803
27803
|
this.scheduleLocks.delete(id);
|
|
27804
27804
|
}
|
|
27805
|
-
|
|
27805
|
+
resolve19();
|
|
27806
27806
|
}
|
|
27807
27807
|
});
|
|
27808
27808
|
}
|
|
@@ -29590,7 +29590,7 @@ var init_project_memory = __esm({
|
|
|
29590
29590
|
// ../core/src/run-command.ts
|
|
29591
29591
|
import { spawn } from "node:child_process";
|
|
29592
29592
|
function runCommandAsync(command, options = {}) {
|
|
29593
|
-
return new Promise((
|
|
29593
|
+
return new Promise((resolve19) => {
|
|
29594
29594
|
const maxBuffer = options.maxBuffer ?? DEFAULT_MAX_BUFFER;
|
|
29595
29595
|
let stdout = "";
|
|
29596
29596
|
let stderr = "";
|
|
@@ -29649,7 +29649,7 @@ function runCommandAsync(command, options = {}) {
|
|
|
29649
29649
|
clearTimeout(forceKillTimer);
|
|
29650
29650
|
forceKillTimer = null;
|
|
29651
29651
|
}
|
|
29652
|
-
|
|
29652
|
+
resolve19({
|
|
29653
29653
|
stdout,
|
|
29654
29654
|
stderr,
|
|
29655
29655
|
exitCode: null,
|
|
@@ -29667,7 +29667,7 @@ function runCommandAsync(command, options = {}) {
|
|
|
29667
29667
|
}
|
|
29668
29668
|
signalProcessGroup("SIGTERM");
|
|
29669
29669
|
scheduleForceKill(NORMAL_CLEANUP_FORCE_KILL_DELAY_MS);
|
|
29670
|
-
|
|
29670
|
+
resolve19({
|
|
29671
29671
|
stdout,
|
|
29672
29672
|
stderr,
|
|
29673
29673
|
exitCode: code,
|
|
@@ -30817,9 +30817,9 @@ ${outcome}`;
|
|
|
30817
30817
|
* lost-update races on the nextId counter.
|
|
30818
30818
|
*/
|
|
30819
30819
|
withConfigLock(fn) {
|
|
30820
|
-
let
|
|
30820
|
+
let resolve19;
|
|
30821
30821
|
const next = new Promise((r) => {
|
|
30822
|
-
|
|
30822
|
+
resolve19 = r;
|
|
30823
30823
|
});
|
|
30824
30824
|
const prev = this.configLock;
|
|
30825
30825
|
this.configLock = next;
|
|
@@ -30827,7 +30827,7 @@ ${outcome}`;
|
|
|
30827
30827
|
try {
|
|
30828
30828
|
return await fn();
|
|
30829
30829
|
} finally {
|
|
30830
|
-
|
|
30830
|
+
resolve19();
|
|
30831
30831
|
}
|
|
30832
30832
|
});
|
|
30833
30833
|
}
|
|
@@ -30837,9 +30837,9 @@ ${outcome}`;
|
|
|
30837
30837
|
*/
|
|
30838
30838
|
withTaskLock(id, fn) {
|
|
30839
30839
|
const prev = this.taskLocks.get(id) ?? Promise.resolve();
|
|
30840
|
-
let
|
|
30840
|
+
let resolve19;
|
|
30841
30841
|
const next = new Promise((r) => {
|
|
30842
|
-
|
|
30842
|
+
resolve19 = r;
|
|
30843
30843
|
});
|
|
30844
30844
|
this.taskLocks.set(id, next);
|
|
30845
30845
|
return prev.then(async () => {
|
|
@@ -30849,7 +30849,7 @@ ${outcome}`;
|
|
|
30849
30849
|
if (this.taskLocks.get(id) === next) {
|
|
30850
30850
|
this.taskLocks.delete(id);
|
|
30851
30851
|
}
|
|
30852
|
-
|
|
30852
|
+
resolve19();
|
|
30853
30853
|
}
|
|
30854
30854
|
});
|
|
30855
30855
|
}
|
|
@@ -33004,7 +33004,7 @@ ${task.description}
|
|
|
33004
33004
|
}
|
|
33005
33005
|
}
|
|
33006
33006
|
}
|
|
33007
|
-
await new Promise((
|
|
33007
|
+
await new Promise((resolve19) => setImmediate(resolve19));
|
|
33008
33008
|
const selectClause = this.getTaskSelectClause(true);
|
|
33009
33009
|
const changedRows = this.lastPollTime ? this.db.prepare(`SELECT ${selectClause} FROM tasks WHERE updatedAt > ? OR columnMovedAt > ?`).all(this.lastPollTime, this.lastPollTime) : this.db.prepare(`SELECT ${selectClause} FROM tasks`).all();
|
|
33010
33010
|
this.lastPollTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -33024,7 +33024,7 @@ ${task.description}
|
|
|
33024
33024
|
this.emit("task:updated", task);
|
|
33025
33025
|
}
|
|
33026
33026
|
if (i > 0 && i % 50 === 0) {
|
|
33027
|
-
await new Promise((
|
|
33027
|
+
await new Promise((resolve19) => setImmediate(resolve19));
|
|
33028
33028
|
}
|
|
33029
33029
|
}
|
|
33030
33030
|
const elapsed = Date.now() - startTime;
|
|
@@ -34850,7 +34850,7 @@ function runGh(args, cwd) {
|
|
|
34850
34850
|
}
|
|
34851
34851
|
function runGhAsync(args, cwdOrOptions) {
|
|
34852
34852
|
const { cwd, signal: externalSignal, timeoutMs = DEFAULT_GH_TIMEOUT_MS } = normalizeRunGhOptions(cwdOrOptions);
|
|
34853
|
-
return new Promise((
|
|
34853
|
+
return new Promise((resolve19, reject) => {
|
|
34854
34854
|
if (externalSignal?.aborted) {
|
|
34855
34855
|
reject(makeGhError(`gh command aborted: ${describeAbortReason(externalSignal.reason)}`, "ABORT_ERR"));
|
|
34856
34856
|
return;
|
|
@@ -34901,7 +34901,7 @@ function runGhAsync(args, cwdOrOptions) {
|
|
|
34901
34901
|
ghError.stderr = stderr ?? "";
|
|
34902
34902
|
reject(ghError);
|
|
34903
34903
|
} else {
|
|
34904
|
-
|
|
34904
|
+
resolve19(stdout ?? "");
|
|
34905
34905
|
}
|
|
34906
34906
|
}
|
|
34907
34907
|
);
|
|
@@ -35189,9 +35189,9 @@ var init_routine_store = __esm({
|
|
|
35189
35189
|
*/
|
|
35190
35190
|
withRoutineLock(id, fn) {
|
|
35191
35191
|
const prev = this.routineLocks.get(id) ?? Promise.resolve();
|
|
35192
|
-
let
|
|
35192
|
+
let resolve19;
|
|
35193
35193
|
const next = new Promise((r) => {
|
|
35194
|
-
|
|
35194
|
+
resolve19 = r;
|
|
35195
35195
|
});
|
|
35196
35196
|
this.routineLocks.set(id, next);
|
|
35197
35197
|
return prev.then(async () => {
|
|
@@ -35201,7 +35201,7 @@ var init_routine_store = __esm({
|
|
|
35201
35201
|
if (this.routineLocks.get(id) === next) {
|
|
35202
35202
|
this.routineLocks.delete(id);
|
|
35203
35203
|
}
|
|
35204
|
-
|
|
35204
|
+
resolve19();
|
|
35205
35205
|
}
|
|
35206
35206
|
});
|
|
35207
35207
|
}
|
|
@@ -35800,13 +35800,13 @@ var init_plugin_loader = __esm({
|
|
|
35800
35800
|
* Execute a promise with a timeout.
|
|
35801
35801
|
*/
|
|
35802
35802
|
withTimeout(promise, ms, timeoutMessage) {
|
|
35803
|
-
return new Promise((
|
|
35803
|
+
return new Promise((resolve19, reject) => {
|
|
35804
35804
|
const timer = setTimeout(() => {
|
|
35805
35805
|
reject(new Error(timeoutMessage));
|
|
35806
35806
|
}, ms);
|
|
35807
35807
|
promise.then((result) => {
|
|
35808
35808
|
clearTimeout(timer);
|
|
35809
|
-
|
|
35809
|
+
resolve19(result);
|
|
35810
35810
|
}).catch((err) => {
|
|
35811
35811
|
clearTimeout(timer);
|
|
35812
35812
|
reject(err);
|
|
@@ -39013,7 +39013,7 @@ var require_get_stream = __commonJS({
|
|
|
39013
39013
|
};
|
|
39014
39014
|
const { maxBuffer } = options;
|
|
39015
39015
|
let stream;
|
|
39016
|
-
await new Promise((
|
|
39016
|
+
await new Promise((resolve19, reject) => {
|
|
39017
39017
|
const rejectPromise = (error) => {
|
|
39018
39018
|
if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
|
|
39019
39019
|
error.bufferedData = stream.getBufferedValue();
|
|
@@ -39025,7 +39025,7 @@ var require_get_stream = __commonJS({
|
|
|
39025
39025
|
rejectPromise(error);
|
|
39026
39026
|
return;
|
|
39027
39027
|
}
|
|
39028
|
-
|
|
39028
|
+
resolve19();
|
|
39029
39029
|
});
|
|
39030
39030
|
stream.on("data", () => {
|
|
39031
39031
|
if (stream.getBufferedLength() > maxBuffer) {
|
|
@@ -40319,7 +40319,7 @@ var require_extract_zip = __commonJS({
|
|
|
40319
40319
|
debug("opening", this.zipPath, "with opts", this.opts);
|
|
40320
40320
|
this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
|
|
40321
40321
|
this.canceled = false;
|
|
40322
|
-
return new Promise((
|
|
40322
|
+
return new Promise((resolve19, reject) => {
|
|
40323
40323
|
this.zipfile.on("error", (err) => {
|
|
40324
40324
|
this.canceled = true;
|
|
40325
40325
|
reject(err);
|
|
@@ -40328,7 +40328,7 @@ var require_extract_zip = __commonJS({
|
|
|
40328
40328
|
this.zipfile.on("close", () => {
|
|
40329
40329
|
if (!this.canceled) {
|
|
40330
40330
|
debug("zip extraction complete");
|
|
40331
|
-
|
|
40331
|
+
resolve19();
|
|
40332
40332
|
}
|
|
40333
40333
|
});
|
|
40334
40334
|
this.zipfile.on("entry", async (entry) => {
|
|
@@ -50377,12 +50377,12 @@ var init_concurrency = __esm({
|
|
|
50377
50377
|
this._active++;
|
|
50378
50378
|
return Promise.resolve();
|
|
50379
50379
|
}
|
|
50380
|
-
return new Promise((
|
|
50380
|
+
return new Promise((resolve19) => {
|
|
50381
50381
|
this._waiters.push({
|
|
50382
50382
|
priority,
|
|
50383
50383
|
resolve: () => {
|
|
50384
50384
|
this._active++;
|
|
50385
|
-
|
|
50385
|
+
resolve19();
|
|
50386
50386
|
}
|
|
50387
50387
|
});
|
|
50388
50388
|
});
|
|
@@ -52803,20 +52803,20 @@ async function withRateLimitRetry(fn, options = {}) {
|
|
|
52803
52803
|
throw lastError ?? new Error("withRateLimitRetry: unexpected state");
|
|
52804
52804
|
}
|
|
52805
52805
|
function sleep(ms, signal) {
|
|
52806
|
-
return new Promise((
|
|
52806
|
+
return new Promise((resolve19, reject) => {
|
|
52807
52807
|
if (signal?.aborted) {
|
|
52808
52808
|
reject(signal.reason ?? new Error("Aborted"));
|
|
52809
52809
|
return;
|
|
52810
52810
|
}
|
|
52811
|
-
const timer = setTimeout(
|
|
52811
|
+
const timer = setTimeout(resolve19, ms);
|
|
52812
52812
|
if (signal) {
|
|
52813
52813
|
const onAbort = () => {
|
|
52814
52814
|
clearTimeout(timer);
|
|
52815
52815
|
reject(signal.reason ?? new Error("Aborted"));
|
|
52816
52816
|
};
|
|
52817
52817
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
52818
|
-
const origResolve =
|
|
52819
|
-
|
|
52818
|
+
const origResolve = resolve19;
|
|
52819
|
+
resolve19 = () => {
|
|
52820
52820
|
signal.removeEventListener("abort", onAbort);
|
|
52821
52821
|
origResolve();
|
|
52822
52822
|
};
|
|
@@ -52896,9 +52896,9 @@ async function readAttachmentContents(rootDir, taskId, attachments) {
|
|
|
52896
52896
|
return { attachmentContents, imageContents };
|
|
52897
52897
|
}
|
|
52898
52898
|
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
52899
|
-
const { join:
|
|
52899
|
+
const { join: join38 } = await import("node:path");
|
|
52900
52900
|
for (const att of attachments) {
|
|
52901
|
-
const filePath =
|
|
52901
|
+
const filePath = join38(
|
|
52902
52902
|
rootDir,
|
|
52903
52903
|
".fusion",
|
|
52904
52904
|
"tasks",
|
|
@@ -54412,9 +54412,9 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
54412
54412
|
}
|
|
54413
54413
|
try {
|
|
54414
54414
|
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
54415
|
-
const { join:
|
|
54415
|
+
const { join: join38 } = await import("node:path");
|
|
54416
54416
|
const promptContent = await readFile19(
|
|
54417
|
-
|
|
54417
|
+
join38(rootDir, promptPath),
|
|
54418
54418
|
"utf-8"
|
|
54419
54419
|
).catch((err) => {
|
|
54420
54420
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -54783,7 +54783,7 @@ import { existsSync as existsSync21 } from "node:fs";
|
|
|
54783
54783
|
import { join as join26 } from "node:path";
|
|
54784
54784
|
import { Type as Type3 } from "typebox";
|
|
54785
54785
|
async function execWithProcessGroup(command, options) {
|
|
54786
|
-
return new Promise((
|
|
54786
|
+
return new Promise((resolve19, reject) => {
|
|
54787
54787
|
if (options.signal?.aborted) {
|
|
54788
54788
|
reject(Object.assign(
|
|
54789
54789
|
new Error(`Command aborted before start: ${command}`),
|
|
@@ -54876,7 +54876,7 @@ async function execWithProcessGroup(command, options) {
|
|
|
54876
54876
|
return;
|
|
54877
54877
|
}
|
|
54878
54878
|
if (code === 0) {
|
|
54879
|
-
|
|
54879
|
+
resolve19({ stdout, stderr, bufferOverflow: stdoutOverflow || stderrOverflow });
|
|
54880
54880
|
return;
|
|
54881
54881
|
}
|
|
54882
54882
|
reject(Object.assign(
|
|
@@ -58845,7 +58845,7 @@ function resolveExecutorModelPair(taskModelProvider, taskModelId, settings) {
|
|
|
58845
58845
|
return { provider: void 0, modelId: void 0 };
|
|
58846
58846
|
}
|
|
58847
58847
|
function sleep2(ms) {
|
|
58848
|
-
return new Promise((
|
|
58848
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
58849
58849
|
}
|
|
58850
58850
|
var execAsync4, stepExecLog, MAX_STEP_RETRIES, RETRY_DELAYS_MS, NOOP_TASK_STORE, StepSessionExecutor;
|
|
58851
58851
|
var init_step_session_executor = __esm({
|
|
@@ -59729,7 +59729,7 @@ function detectReviewHandoffIntent(commentText) {
|
|
|
59729
59729
|
];
|
|
59730
59730
|
return handoffPhrases.some((phrase) => text.includes(phrase));
|
|
59731
59731
|
}
|
|
59732
|
-
var execAsync5, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, MAX_TASK_DONE_SESSION_RETRIES, MAX_TASK_DONE_REQUEUE_RETRIES, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
|
|
59732
|
+
var execAsync5, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, MAX_TASK_DONE_SESSION_RETRIES, MAX_TASK_DONE_REQUEUE_RETRIES, COMPLETED_TASK_WATCHDOG_MS, WORKFLOW_RERUN_WATCHDOG_MS, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
|
|
59733
59733
|
var init_executor = __esm({
|
|
59734
59734
|
"../engine/src/executor.ts"() {
|
|
59735
59735
|
"use strict";
|
|
@@ -59765,6 +59765,8 @@ var init_executor = __esm({
|
|
|
59765
59765
|
MAX_WORKFLOW_STEP_RETRIES = 3;
|
|
59766
59766
|
MAX_TASK_DONE_SESSION_RETRIES = 3;
|
|
59767
59767
|
MAX_TASK_DONE_REQUEUE_RETRIES = 3;
|
|
59768
|
+
COMPLETED_TASK_WATCHDOG_MS = 6e4;
|
|
59769
|
+
WORKFLOW_RERUN_WATCHDOG_MS = 15e3;
|
|
59768
59770
|
WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2 = 4e3;
|
|
59769
59771
|
NonRetryableWorktreeError = class extends Error {
|
|
59770
59772
|
};
|
|
@@ -59975,6 +59977,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
59975
59977
|
store.on("task:moved", ({ task, from, to }) => {
|
|
59976
59978
|
executorLog.log(`[event:task:moved] ${task.id}: ${from} \u2192 ${to}`);
|
|
59977
59979
|
if (to === "in-progress") {
|
|
59980
|
+
this.clearWorkflowRerunWatchdog(task.id);
|
|
59978
59981
|
executorLog.log(`[event:task:moved] Initiating execute() for ${task.id}`);
|
|
59979
59982
|
void (async () => {
|
|
59980
59983
|
const taskForExecution = await this.resetMergeStateIfNeeded(task, from);
|
|
@@ -59983,6 +59986,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
59983
59986
|
(err) => executorLog.error(`Failed to start ${task.id}:`, err)
|
|
59984
59987
|
);
|
|
59985
59988
|
} else if (from === "in-progress") {
|
|
59989
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
59986
59990
|
if (this.activeSessions.has(task.id)) {
|
|
59987
59991
|
executorLog.log(`${task.id} moved from in-progress to ${to} \u2014 terminating agent session`);
|
|
59988
59992
|
this.pausedAborted.add(task.id);
|
|
@@ -60174,6 +60178,10 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
60174
60178
|
spawnedAgents = /* @__PURE__ */ new Map();
|
|
60175
60179
|
/** Per-task baseline of session stats used for delta persistence across repeated updates. */
|
|
60176
60180
|
tokenUsageBaselines = /* @__PURE__ */ new Map();
|
|
60181
|
+
/** One-shot watchdogs for completed tasks that should have transitioned to in-review. */
|
|
60182
|
+
completedTaskWatchdogs = /* @__PURE__ */ new Map();
|
|
60183
|
+
/** One-shot watchdogs for workflow reruns that should have bounced back to in-progress. */
|
|
60184
|
+
workflowRerunWatchdogs = /* @__PURE__ */ new Map();
|
|
60177
60185
|
async finalizeAlreadyReviewedTask(taskId) {
|
|
60178
60186
|
const latestTask = await this.store.getTask(taskId);
|
|
60179
60187
|
if (!latestTask || latestTask.column !== "in-review") {
|
|
@@ -60329,6 +60337,120 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
60329
60337
|
await this.store.updateTask(task.id, updates);
|
|
60330
60338
|
}
|
|
60331
60339
|
}
|
|
60340
|
+
clearCompletedTaskWatchdog(taskId) {
|
|
60341
|
+
const handle = this.completedTaskWatchdogs.get(taskId);
|
|
60342
|
+
if (!handle) return;
|
|
60343
|
+
clearTimeout(handle);
|
|
60344
|
+
this.completedTaskWatchdogs.delete(taskId);
|
|
60345
|
+
}
|
|
60346
|
+
clearWorkflowRerunWatchdog(taskId) {
|
|
60347
|
+
const handle = this.workflowRerunWatchdogs.get(taskId);
|
|
60348
|
+
if (!handle) return;
|
|
60349
|
+
clearTimeout(handle);
|
|
60350
|
+
this.workflowRerunWatchdogs.delete(taskId);
|
|
60351
|
+
}
|
|
60352
|
+
scheduleCompletedTaskWatchdog(taskId, trigger) {
|
|
60353
|
+
this.clearCompletedTaskWatchdog(taskId);
|
|
60354
|
+
const handle = setTimeout(async () => {
|
|
60355
|
+
this.completedTaskWatchdogs.delete(taskId);
|
|
60356
|
+
let currentTask = null;
|
|
60357
|
+
try {
|
|
60358
|
+
currentTask = await this.store.getTask(taskId);
|
|
60359
|
+
} catch (err) {
|
|
60360
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
60361
|
+
executorLog.warn(`${taskId}: completed-task watchdog could not read latest task state: ${errorMessage}`);
|
|
60362
|
+
return;
|
|
60363
|
+
}
|
|
60364
|
+
if (!currentTask || currentTask.column !== "in-progress" || currentTask.paused) {
|
|
60365
|
+
return;
|
|
60366
|
+
}
|
|
60367
|
+
if (this.activeSessions.has(taskId) || this.activeStepExecutors.has(taskId) || this.recoveringCompleted.has(taskId)) {
|
|
60368
|
+
return;
|
|
60369
|
+
}
|
|
60370
|
+
if (!this.isTaskWorkComplete(currentTask)) {
|
|
60371
|
+
return;
|
|
60372
|
+
}
|
|
60373
|
+
executorLog.warn(
|
|
60374
|
+
`${taskId}: completed-task watchdog fired after ${COMPLETED_TASK_WATCHDOG_MS / 1e3}s (${trigger}) \u2014 attempting direct recovery to in-review`
|
|
60375
|
+
);
|
|
60376
|
+
await this.store.logEntry(
|
|
60377
|
+
taskId,
|
|
60378
|
+
`Watchdog: task remained in-progress ${COMPLETED_TASK_WATCHDOG_MS / 1e3}s after ${trigger} \u2014 attempting direct recovery to in-review`
|
|
60379
|
+
).catch(() => void 0);
|
|
60380
|
+
this.recoveringCompleted.add(taskId);
|
|
60381
|
+
try {
|
|
60382
|
+
const recovered = await this.recoverCompletedTask(currentTask);
|
|
60383
|
+
if (!recovered) {
|
|
60384
|
+
await this.store.logEntry(
|
|
60385
|
+
taskId,
|
|
60386
|
+
"Watchdog recovery attempt could not finalize completed task \u2014 leaving for follow-up recovery"
|
|
60387
|
+
).catch(() => void 0);
|
|
60388
|
+
}
|
|
60389
|
+
} finally {
|
|
60390
|
+
this.recoveringCompleted.delete(taskId);
|
|
60391
|
+
}
|
|
60392
|
+
}, COMPLETED_TASK_WATCHDOG_MS);
|
|
60393
|
+
this.completedTaskWatchdogs.set(taskId, handle);
|
|
60394
|
+
}
|
|
60395
|
+
async performWorkflowRerunBounce(taskId, worktreePath) {
|
|
60396
|
+
const latestTask = await this.store.getTask(taskId);
|
|
60397
|
+
if (!latestTask) {
|
|
60398
|
+
throw new Error("task missing during workflow rerun bounce");
|
|
60399
|
+
}
|
|
60400
|
+
if (latestTask.column === "in-progress") {
|
|
60401
|
+
await this.store.moveTask(taskId, "todo");
|
|
60402
|
+
await this.store.updateTask(taskId, { worktree: worktreePath });
|
|
60403
|
+
await this.store.moveTask(taskId, "in-progress");
|
|
60404
|
+
return;
|
|
60405
|
+
}
|
|
60406
|
+
if (latestTask.column === "todo") {
|
|
60407
|
+
await this.store.updateTask(taskId, { worktree: worktreePath });
|
|
60408
|
+
await this.store.moveTask(taskId, "in-progress");
|
|
60409
|
+
return;
|
|
60410
|
+
}
|
|
60411
|
+
throw new Error(`task is in '${latestTask.column}', cannot bounce to in-progress`);
|
|
60412
|
+
}
|
|
60413
|
+
scheduleWorkflowRerun(taskId, worktreePath, successMessage) {
|
|
60414
|
+
this.clearWorkflowRerunWatchdog(taskId);
|
|
60415
|
+
setTimeout(async () => {
|
|
60416
|
+
try {
|
|
60417
|
+
await this.performWorkflowRerunBounce(taskId, worktreePath);
|
|
60418
|
+
executorLog.log(successMessage);
|
|
60419
|
+
} catch (err) {
|
|
60420
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
60421
|
+
executorLog.error(`${taskId}: failed to schedule rerun bounce: ${errorMessage}`);
|
|
60422
|
+
}
|
|
60423
|
+
}, 0);
|
|
60424
|
+
const watchdog = setTimeout(async () => {
|
|
60425
|
+
this.workflowRerunWatchdogs.delete(taskId);
|
|
60426
|
+
let currentTask = null;
|
|
60427
|
+
try {
|
|
60428
|
+
currentTask = await this.store.getTask(taskId);
|
|
60429
|
+
} catch (err) {
|
|
60430
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
60431
|
+
executorLog.warn(`${taskId}: workflow rerun watchdog could not read latest task state: ${errorMessage}`);
|
|
60432
|
+
return;
|
|
60433
|
+
}
|
|
60434
|
+
if (!currentTask || currentTask.paused || currentTask.column === "in-progress") {
|
|
60435
|
+
return;
|
|
60436
|
+
}
|
|
60437
|
+
executorLog.warn(
|
|
60438
|
+
`${taskId}: workflow rerun watchdog fired after ${WORKFLOW_RERUN_WATCHDOG_MS / 1e3}s \u2014 task is still ${currentTask.column}; retrying handoff once`
|
|
60439
|
+
);
|
|
60440
|
+
await this.store.logEntry(
|
|
60441
|
+
taskId,
|
|
60442
|
+
`Watchdog: workflow rerun handoff stalled for ${WORKFLOW_RERUN_WATCHDOG_MS / 1e3}s (still ${currentTask.column}) \u2014 retrying once`
|
|
60443
|
+
).catch(() => void 0);
|
|
60444
|
+
try {
|
|
60445
|
+
await this.performWorkflowRerunBounce(taskId, worktreePath);
|
|
60446
|
+
executorLog.warn(`${taskId}: workflow rerun watchdog retry succeeded`);
|
|
60447
|
+
} catch (err) {
|
|
60448
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
60449
|
+
executorLog.error(`${taskId}: workflow rerun watchdog retry failed: ${errorMessage}`);
|
|
60450
|
+
}
|
|
60451
|
+
}, WORKFLOW_RERUN_WATCHDOG_MS);
|
|
60452
|
+
this.workflowRerunWatchdogs.set(taskId, watchdog);
|
|
60453
|
+
}
|
|
60332
60454
|
async shouldFinalizeCompletedTask(taskId, taskDone) {
|
|
60333
60455
|
const task = await this.store.getTask(taskId);
|
|
60334
60456
|
const completionBlocker = await this.getTaskCompletionBlocker(task);
|
|
@@ -60462,6 +60584,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
60462
60584
|
}
|
|
60463
60585
|
await this.persistTokenUsage(task.id);
|
|
60464
60586
|
await this.store.moveTask(task.id, "in-review");
|
|
60587
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
60465
60588
|
await this.store.logEntry(task.id, "Auto-recovered: task work was complete but stuck in in-progress \u2014 moved to in-review");
|
|
60466
60589
|
executorLog.log(`\u2713 ${task.id} auto-recovered completed task \u2192 in-review`);
|
|
60467
60590
|
this.options.onComplete?.(task);
|
|
@@ -60958,6 +61081,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
60958
61081
|
executorLog.log(`${task.id}: captured ${modifiedFiles.length} modified files`);
|
|
60959
61082
|
await audit.filesystem({ type: "file:capture-modified", target: task.id, metadata: { files: modifiedFiles } });
|
|
60960
61083
|
}
|
|
61084
|
+
this.scheduleCompletedTaskWatchdog(task.id, "step-session completion");
|
|
60961
61085
|
if (executionMode !== "fast") {
|
|
60962
61086
|
const workflowResult = await this.runWorkflowSteps(task, worktreePath, settings);
|
|
60963
61087
|
if (!workflowResult.allPassed) {
|
|
@@ -60978,6 +61102,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
60978
61102
|
}
|
|
60979
61103
|
await this.store.updateTask(task.id, { workflowStepRetries: void 0, taskDoneRetryCount: null });
|
|
60980
61104
|
await this.store.moveTask(task.id, "in-review");
|
|
61105
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
60981
61106
|
await audit.database({ type: "task:move", target: task.id, metadata: { to: "in-review" } });
|
|
60982
61107
|
executorLog.log(`\u2713 ${task.id} completed (step-session) \u2192 in-review`);
|
|
60983
61108
|
this.options.onComplete?.(task);
|
|
@@ -61314,6 +61439,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61314
61439
|
await this.store.logEntry(task.id, "Execution paused after completion \u2014 finalizing to in-review");
|
|
61315
61440
|
await this.persistTokenUsage(task.id);
|
|
61316
61441
|
await this.store.moveTask(task.id, "in-review");
|
|
61442
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
61317
61443
|
this.options.onComplete?.(task);
|
|
61318
61444
|
} else {
|
|
61319
61445
|
executorLog.log(`${task.id} paused (graceful session exit) \u2014 moving to todo`);
|
|
@@ -61334,6 +61460,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61334
61460
|
taskDone = true;
|
|
61335
61461
|
executorLog.log(`${task.id} all steps done \u2014 treating as implicit fn_task_done`);
|
|
61336
61462
|
await this.store.logEntry(task.id, "All steps complete \u2014 implicit fn_task_done (agent did not call tool explicitly)", void 0, this.currentRunContext);
|
|
61463
|
+
this.scheduleCompletedTaskWatchdog(task.id, "implicit fn_task_done");
|
|
61337
61464
|
}
|
|
61338
61465
|
}
|
|
61339
61466
|
if (taskDone) {
|
|
@@ -61343,6 +61470,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61343
61470
|
await this.store.updateTask(task.id, { modifiedFiles });
|
|
61344
61471
|
executorLog.log(`${task.id}: captured ${modifiedFiles.length} modified files`);
|
|
61345
61472
|
}
|
|
61473
|
+
this.scheduleCompletedTaskWatchdog(task.id, "task completion");
|
|
61346
61474
|
if (executionMode !== "fast") {
|
|
61347
61475
|
const workflowResult = await this.runWorkflowSteps(task, worktreePath, settings);
|
|
61348
61476
|
if (!workflowResult.allPassed) {
|
|
@@ -61364,6 +61492,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61364
61492
|
await this.store.updateTask(task.id, { workflowStepRetries: void 0, taskDoneRetryCount: null });
|
|
61365
61493
|
await this.persistTokenUsage(task.id);
|
|
61366
61494
|
await this.store.moveTask(task.id, "in-review");
|
|
61495
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
61367
61496
|
executorLog.log(`\u2713 ${task.id} completed \u2192 in-review`);
|
|
61368
61497
|
this.options.onComplete?.(task);
|
|
61369
61498
|
} else {
|
|
@@ -61437,6 +61566,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61437
61566
|
taskDone = true;
|
|
61438
61567
|
executorLog.log(`${task.id} all steps done \u2014 treating as implicit fn_task_done`);
|
|
61439
61568
|
await this.store.logEntry(task.id, "All steps complete \u2014 implicit fn_task_done (agent did not call tool explicitly)", void 0, this.currentRunContext);
|
|
61569
|
+
this.scheduleCompletedTaskWatchdog(task.id, "implicit fn_task_done");
|
|
61440
61570
|
}
|
|
61441
61571
|
}
|
|
61442
61572
|
}
|
|
@@ -61447,6 +61577,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61447
61577
|
await this.store.updateTask(task.id, { modifiedFiles });
|
|
61448
61578
|
executorLog.log(`${task.id}: captured ${modifiedFiles.length} modified files`);
|
|
61449
61579
|
}
|
|
61580
|
+
this.scheduleCompletedTaskWatchdog(task.id, "task completion retry");
|
|
61450
61581
|
if (executionMode !== "fast") {
|
|
61451
61582
|
const workflowResult = await this.runWorkflowSteps(task, worktreePath, settings);
|
|
61452
61583
|
if (!workflowResult.allPassed) {
|
|
@@ -61464,6 +61595,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61464
61595
|
await this.store.updateTask(task.id, { workflowStepRetries: void 0, taskDoneRetryCount: null });
|
|
61465
61596
|
await this.persistTokenUsage(task.id);
|
|
61466
61597
|
await this.store.moveTask(task.id, "in-review");
|
|
61598
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
61467
61599
|
executorLog.log(`\u2713 ${task.id} completed on retry \u2192 in-review`);
|
|
61468
61600
|
this.options.onComplete?.(task);
|
|
61469
61601
|
} else {
|
|
@@ -61891,6 +62023,7 @@ Lint, tests, and typecheck are also hard quality gates:
|
|
|
61891
62023
|
await store.updateTask(taskId, { summary: params.summary });
|
|
61892
62024
|
}
|
|
61893
62025
|
await store.logEntry(taskId, "Task marked done by agent");
|
|
62026
|
+
this.scheduleCompletedTaskWatchdog(taskId, "fn_task_done");
|
|
61894
62027
|
const successMessage = params.summary ? "Task marked complete with summary. All steps done. Moving to in-review." : "Task marked complete. All steps done. Moving to in-review.";
|
|
61895
62028
|
return {
|
|
61896
62029
|
content: [{ type: "text", text: successMessage }],
|
|
@@ -62117,6 +62250,7 @@ Take a different approach. Do NOT repeat the rejected strategy. Re-read the step
|
|
|
62117
62250
|
*/
|
|
62118
62251
|
async handleWorkflowRevisionRequest(task, worktreePath, feedback, stepName) {
|
|
62119
62252
|
executorLog.log(`${task.id}: workflow revision requested by step "${stepName}"`);
|
|
62253
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
62120
62254
|
const updatedTask = await this.store.getTask(task.id);
|
|
62121
62255
|
const reopen = await this.reopenLastStepForRevision(task.id, updatedTask);
|
|
62122
62256
|
const reopenSummary = reopen ? `re-opening Step ${reopen.index + 1} ("${reopen.name}") for in-place fix` : "no step to re-open (none were completed)";
|
|
@@ -62131,21 +62265,11 @@ Take a different approach. Do NOT repeat the rejected strategy. Re-read the step
|
|
|
62131
62265
|
sessionFile: null
|
|
62132
62266
|
});
|
|
62133
62267
|
executorLog.log(`${task.id}: scheduling fresh execution after revision request`);
|
|
62134
|
-
|
|
62135
|
-
|
|
62136
|
-
|
|
62137
|
-
|
|
62138
|
-
|
|
62139
|
-
executorLog.log(`${task.id}: revision rerun scheduled \u2014 moved to todo then in-progress`);
|
|
62140
|
-
} catch (err) {
|
|
62141
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
62142
|
-
executorLog.error(`${task.id}: failed to schedule revision rerun: ${errorMessage}`);
|
|
62143
|
-
await this.store.logEntry(
|
|
62144
|
-
task.id,
|
|
62145
|
-
"Workflow revision requested \u2014 executor ready for fresh execution"
|
|
62146
|
-
);
|
|
62147
|
-
}
|
|
62148
|
-
}, 0);
|
|
62268
|
+
this.scheduleWorkflowRerun(
|
|
62269
|
+
task.id,
|
|
62270
|
+
worktreePath,
|
|
62271
|
+
`${task.id}: revision rerun scheduled \u2014 moved to todo then in-progress`
|
|
62272
|
+
);
|
|
62149
62273
|
}
|
|
62150
62274
|
/**
|
|
62151
62275
|
* Re-open the last non-pending step so a revision/failure handler gives the
|
|
@@ -62232,6 +62356,7 @@ ${feedback}
|
|
|
62232
62356
|
* @returns true if a retry was scheduled, false if retries are exhausted
|
|
62233
62357
|
*/
|
|
62234
62358
|
async handleWorkflowStepFailure(task, worktreePath, failureFeedback, stepName) {
|
|
62359
|
+
this.clearCompletedTaskWatchdog(task.id);
|
|
62235
62360
|
const currentRetries = task.workflowStepRetries ?? 0;
|
|
62236
62361
|
if (currentRetries >= MAX_WORKFLOW_STEP_RETRIES) {
|
|
62237
62362
|
executorLog.warn(`${task.id}: workflow step "${stepName}" failed \u2014 retries exhausted (${MAX_WORKFLOW_STEP_RETRIES}/${MAX_WORKFLOW_STEP_RETRIES})`);
|
|
@@ -62250,21 +62375,11 @@ ${feedback}
|
|
|
62250
62375
|
sessionFile: null
|
|
62251
62376
|
});
|
|
62252
62377
|
executorLog.log(`${task.id}: scheduling fresh execution after workflow step failure (retry ${retryCount}/${MAX_WORKFLOW_STEP_RETRIES})`);
|
|
62253
|
-
|
|
62254
|
-
|
|
62255
|
-
|
|
62256
|
-
|
|
62257
|
-
|
|
62258
|
-
executorLog.log(`${task.id}: workflow step retry scheduled \u2014 moved to todo then in-progress`);
|
|
62259
|
-
} catch (err) {
|
|
62260
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
62261
|
-
executorLog.error(`${task.id}: failed to schedule workflow step retry: ${errorMessage}`);
|
|
62262
|
-
await this.store.logEntry(
|
|
62263
|
-
task.id,
|
|
62264
|
-
"Workflow step failed \u2014 executor ready for fresh execution"
|
|
62265
|
-
);
|
|
62266
|
-
}
|
|
62267
|
-
}, 0);
|
|
62378
|
+
this.scheduleWorkflowRerun(
|
|
62379
|
+
task.id,
|
|
62380
|
+
worktreePath,
|
|
62381
|
+
`${task.id}: workflow step retry scheduled \u2014 moved to todo then in-progress`
|
|
62382
|
+
);
|
|
62268
62383
|
return true;
|
|
62269
62384
|
}
|
|
62270
62385
|
/**
|
|
@@ -62274,6 +62389,7 @@ ${feedback}
|
|
|
62274
62389
|
*/
|
|
62275
62390
|
async sendTaskBackForFix(task, worktreePath, failureFeedback, stepName, reason) {
|
|
62276
62391
|
const taskId = task.id;
|
|
62392
|
+
this.clearCompletedTaskWatchdog(taskId);
|
|
62277
62393
|
await this.store.addTaskComment(
|
|
62278
62394
|
taskId,
|
|
62279
62395
|
`${reason}. The failing workflow step was "${stepName}". Feedback:
|
|
@@ -62295,17 +62411,11 @@ Please fix the issues so the verification can pass on the next attempt.`,
|
|
|
62295
62411
|
sessionFile: null,
|
|
62296
62412
|
workflowStepRetries: 0
|
|
62297
62413
|
});
|
|
62298
|
-
|
|
62299
|
-
|
|
62300
|
-
|
|
62301
|
-
|
|
62302
|
-
|
|
62303
|
-
executorLog.log(`${taskId}: sent back to in-progress for remediation`);
|
|
62304
|
-
} catch (err) {
|
|
62305
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
62306
|
-
executorLog.error(`${taskId}: failed to move back to in-progress: ${errorMessage}`);
|
|
62307
|
-
}
|
|
62308
|
-
}, 0);
|
|
62414
|
+
this.scheduleWorkflowRerun(
|
|
62415
|
+
taskId,
|
|
62416
|
+
worktreePath,
|
|
62417
|
+
`${taskId}: sent back to in-progress for remediation`
|
|
62418
|
+
);
|
|
62309
62419
|
}
|
|
62310
62420
|
/**
|
|
62311
62421
|
* Inject or update the "Workflow Step Failure" section in PROMPT.md.
|
|
@@ -62856,7 +62966,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
|
|
|
62856
62966
|
);
|
|
62857
62967
|
}
|
|
62858
62968
|
const delay2 = this.WORKTREE_RETRY_DELAYS[attempt] || 1e3;
|
|
62859
|
-
await new Promise((
|
|
62969
|
+
await new Promise((resolve19) => setTimeout(resolve19, delay2));
|
|
62860
62970
|
}
|
|
62861
62971
|
}
|
|
62862
62972
|
throw new Error("Unexpected exit from worktree creation retry loop");
|
|
@@ -72180,13 +72290,13 @@ var init_plugin_runner = __esm({
|
|
|
72180
72290
|
* Returns the result on success, throws on timeout.
|
|
72181
72291
|
*/
|
|
72182
72292
|
withTimeout(promise, ms, timeoutMessage) {
|
|
72183
|
-
return new Promise((
|
|
72293
|
+
return new Promise((resolve19, reject) => {
|
|
72184
72294
|
const timer = setTimeout(() => {
|
|
72185
72295
|
reject(new Error(timeoutMessage));
|
|
72186
72296
|
}, ms);
|
|
72187
72297
|
promise.then((result) => {
|
|
72188
72298
|
clearTimeout(timer);
|
|
72189
|
-
|
|
72299
|
+
resolve19(result);
|
|
72190
72300
|
}).catch((err) => {
|
|
72191
72301
|
clearTimeout(timer);
|
|
72192
72302
|
reject(err);
|
|
@@ -72855,7 +72965,7 @@ var init_in_process_runtime = __esm({
|
|
|
72855
72965
|
runtimeLog.log(
|
|
72856
72966
|
`Waiting for ${metrics.inFlightTasks} in-flight tasks to complete...`
|
|
72857
72967
|
);
|
|
72858
|
-
await new Promise((
|
|
72968
|
+
await new Promise((resolve19) => setTimeout(resolve19, 1e3));
|
|
72859
72969
|
}
|
|
72860
72970
|
const finalMetrics = this.getMetrics();
|
|
72861
72971
|
if (finalMetrics.inFlightTasks > 0) {
|
|
@@ -73252,13 +73362,13 @@ var init_ipc_host = __esm({
|
|
|
73252
73362
|
}
|
|
73253
73363
|
const id = generateCorrelationId();
|
|
73254
73364
|
const message = { type, id, payload };
|
|
73255
|
-
return new Promise((
|
|
73365
|
+
return new Promise((resolve19, reject) => {
|
|
73256
73366
|
const timeout = setTimeout(() => {
|
|
73257
73367
|
this.pendingCommands.delete(id);
|
|
73258
73368
|
reject(new Error(`Command ${type} timed out after ${timeoutMs ?? this.commandTimeoutMs}ms`));
|
|
73259
73369
|
}, timeoutMs ?? this.commandTimeoutMs);
|
|
73260
73370
|
this.pendingCommands.set(id, {
|
|
73261
|
-
resolve:
|
|
73371
|
+
resolve: resolve19,
|
|
73262
73372
|
reject,
|
|
73263
73373
|
timeout,
|
|
73264
73374
|
type
|
|
@@ -74067,8 +74177,8 @@ var init_remote_node_client = __esm({
|
|
|
74067
74177
|
return error instanceof TypeError;
|
|
74068
74178
|
}
|
|
74069
74179
|
async sleep(ms) {
|
|
74070
|
-
await new Promise((
|
|
74071
|
-
setTimeout(
|
|
74180
|
+
await new Promise((resolve19) => {
|
|
74181
|
+
setTimeout(resolve19, ms);
|
|
74072
74182
|
});
|
|
74073
74183
|
}
|
|
74074
74184
|
};
|
|
@@ -74332,14 +74442,14 @@ var init_remote_node_runtime = __esm({
|
|
|
74332
74442
|
return error instanceof Error ? error : new Error(String(error));
|
|
74333
74443
|
}
|
|
74334
74444
|
async sleep(ms, signal) {
|
|
74335
|
-
await new Promise((
|
|
74445
|
+
await new Promise((resolve19) => {
|
|
74336
74446
|
const timeout = setTimeout(() => {
|
|
74337
74447
|
cleanup();
|
|
74338
|
-
|
|
74448
|
+
resolve19();
|
|
74339
74449
|
}, ms);
|
|
74340
74450
|
const onAbort = () => {
|
|
74341
74451
|
cleanup();
|
|
74342
|
-
|
|
74452
|
+
resolve19();
|
|
74343
74453
|
};
|
|
74344
74454
|
const cleanup = () => {
|
|
74345
74455
|
clearTimeout(timeout);
|
|
@@ -75226,10 +75336,10 @@ var init_tunnel_process_manager = __esm({
|
|
|
75226
75336
|
lastError: null
|
|
75227
75337
|
});
|
|
75228
75338
|
this.emitLog("info", "manager", `Stopping ${currentHandle.provider} tunnel (pid=${currentHandle.child.pid ?? "n/a"})`);
|
|
75229
|
-
this.activeStopPromise = new Promise((
|
|
75339
|
+
this.activeStopPromise = new Promise((resolve19) => {
|
|
75230
75340
|
const onClose = () => {
|
|
75231
75341
|
currentHandle.child.removeListener("close", onClose);
|
|
75232
|
-
|
|
75342
|
+
resolve19();
|
|
75233
75343
|
};
|
|
75234
75344
|
currentHandle.child.once("close", onClose);
|
|
75235
75345
|
killManagedProcess(currentHandle.child, "SIGTERM");
|
|
@@ -75785,12 +75895,12 @@ ${detail}`
|
|
|
75785
75895
|
*/
|
|
75786
75896
|
async onMerge(taskId) {
|
|
75787
75897
|
if (this.mergeActive.has(taskId)) {
|
|
75788
|
-
return new Promise((
|
|
75789
|
-
this.manualMergeResolvers.set(taskId, { resolve:
|
|
75898
|
+
return new Promise((resolve19, reject) => {
|
|
75899
|
+
this.manualMergeResolvers.set(taskId, { resolve: resolve19, reject });
|
|
75790
75900
|
});
|
|
75791
75901
|
}
|
|
75792
|
-
return new Promise((
|
|
75793
|
-
this.manualMergeResolvers.set(taskId, { resolve:
|
|
75902
|
+
return new Promise((resolve19, reject) => {
|
|
75903
|
+
this.manualMergeResolvers.set(taskId, { resolve: resolve19, reject });
|
|
75794
75904
|
this.internalEnqueueMerge(taskId);
|
|
75795
75905
|
});
|
|
75796
75906
|
}
|
|
@@ -79314,7 +79424,7 @@ function buildHermesArgs(prompt, settings, resumeSessionId) {
|
|
|
79314
79424
|
async function invokeHermesCli(prompt, settings, resumeSessionId, signal) {
|
|
79315
79425
|
const args = buildHermesArgs(prompt, settings, resumeSessionId);
|
|
79316
79426
|
const binary = resolveBinaryForSpawn(settings.binaryPath);
|
|
79317
|
-
return new Promise((
|
|
79427
|
+
return new Promise((resolve19, reject) => {
|
|
79318
79428
|
let settled = false;
|
|
79319
79429
|
const spawnEnv = { ...process.env, PYTHONUNBUFFERED: "1" };
|
|
79320
79430
|
if (settings.profile) {
|
|
@@ -79382,7 +79492,7 @@ ${combined}`));
|
|
|
79382
79492
|
return;
|
|
79383
79493
|
}
|
|
79384
79494
|
try {
|
|
79385
|
-
|
|
79495
|
+
resolve19(parseHermesOutput(stdout, stderr));
|
|
79386
79496
|
} catch (parseErr) {
|
|
79387
79497
|
reject(parseErr);
|
|
79388
79498
|
}
|
|
@@ -79608,7 +79718,7 @@ async function promptCli(session, message, config, callbacks, signal) {
|
|
|
79608
79718
|
const args = buildOpenClawArgs(config, session.sessionId, message);
|
|
79609
79719
|
const cb = { ...session.callbacks, ...callbacks };
|
|
79610
79720
|
cb.onToolStart?.("openclaw.agent", { sessionId: session.sessionId });
|
|
79611
|
-
return new Promise((
|
|
79721
|
+
return new Promise((resolve19, reject) => {
|
|
79612
79722
|
let settled = false;
|
|
79613
79723
|
const child = spawn5(config.binaryPath, args, {
|
|
79614
79724
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -79701,7 +79811,7 @@ async function promptCli(session, message, config, callbacks, signal) {
|
|
|
79701
79811
|
...metaError ? { error: metaError } : {},
|
|
79702
79812
|
...errorText.length > 0 ? { toolErrors: errorText } : {}
|
|
79703
79813
|
});
|
|
79704
|
-
|
|
79814
|
+
resolve19();
|
|
79705
79815
|
});
|
|
79706
79816
|
});
|
|
79707
79817
|
}
|
|
@@ -80012,7 +80122,7 @@ var init_register_messaging_scripts = __esm({
|
|
|
80012
80122
|
|
|
80013
80123
|
// ../dashboard/src/github.ts
|
|
80014
80124
|
function delay(ms) {
|
|
80015
|
-
return new Promise((
|
|
80125
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
80016
80126
|
}
|
|
80017
80127
|
function normalizeCheckState(state) {
|
|
80018
80128
|
switch ((state ?? "").toLowerCase()) {
|
|
@@ -82723,7 +82833,7 @@ async function spawnPaperclipCliJson(args, opts) {
|
|
|
82723
82833
|
}
|
|
82724
82834
|
const timeoutMs = opts.cliTimeoutMs ?? 15e3;
|
|
82725
82835
|
const label = ["paperclipai", ...args].join(" ");
|
|
82726
|
-
return new Promise((
|
|
82836
|
+
return new Promise((resolve19, reject) => {
|
|
82727
82837
|
let child;
|
|
82728
82838
|
try {
|
|
82729
82839
|
child = spawn10(bin, fullArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -82769,7 +82879,7 @@ async function spawnPaperclipCliJson(args, opts) {
|
|
|
82769
82879
|
return;
|
|
82770
82880
|
}
|
|
82771
82881
|
try {
|
|
82772
|
-
|
|
82882
|
+
resolve19(JSON.parse(cleaned));
|
|
82773
82883
|
} catch {
|
|
82774
82884
|
reject(new Error(`${label} returned non-JSON output: ${cleaned.slice(0, 200)}`));
|
|
82775
82885
|
}
|
|
@@ -82839,7 +82949,7 @@ var init_paperclip_client = __esm({
|
|
|
82839
82949
|
// ../../plugins/fusion-plugin-paperclip-runtime/dist/runtime-adapter.js
|
|
82840
82950
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
82841
82951
|
function sleep3(ms) {
|
|
82842
|
-
return new Promise((
|
|
82952
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
82843
82953
|
}
|
|
82844
82954
|
function asString2(value) {
|
|
82845
82955
|
return typeof value === "string" ? value : void 0;
|
|
@@ -83248,22 +83358,29 @@ var init_update_check = __esm({
|
|
|
83248
83358
|
});
|
|
83249
83359
|
|
|
83250
83360
|
// ../dashboard/src/routes/register-update-check-routes.ts
|
|
83251
|
-
import { readFileSync as readFileSync7 } from "node:fs";
|
|
83252
|
-
import { dirname as dirname9,
|
|
83361
|
+
import { existsSync as existsSync28, readFileSync as readFileSync7 } from "node:fs";
|
|
83362
|
+
import { dirname as dirname9, resolve as resolve15 } from "node:path";
|
|
83253
83363
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
83254
|
-
var
|
|
83364
|
+
var CLI_PACKAGE_VERSION;
|
|
83255
83365
|
var init_register_update_check_routes = __esm({
|
|
83256
83366
|
"../dashboard/src/routes/register-update-check-routes.ts"() {
|
|
83257
83367
|
"use strict";
|
|
83258
83368
|
init_src();
|
|
83259
83369
|
init_update_check();
|
|
83260
|
-
__dirname = dirname9(fileURLToPath3(import.meta.url));
|
|
83261
83370
|
CLI_PACKAGE_VERSION = (() => {
|
|
83262
83371
|
try {
|
|
83263
|
-
|
|
83264
|
-
|
|
83265
|
-
|
|
83266
|
-
|
|
83372
|
+
let cur = dirname9(fileURLToPath3(import.meta.url));
|
|
83373
|
+
for (let i = 0; i < 8; i++) {
|
|
83374
|
+
const pkgPath = resolve15(cur, "package.json");
|
|
83375
|
+
if (existsSync28(pkgPath)) {
|
|
83376
|
+
const parsed = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
83377
|
+
if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
83378
|
+
return parsed.version;
|
|
83379
|
+
}
|
|
83380
|
+
}
|
|
83381
|
+
const parent = resolve15(cur, "..");
|
|
83382
|
+
if (parent === cur) break;
|
|
83383
|
+
cur = parent;
|
|
83267
83384
|
}
|
|
83268
83385
|
} catch {
|
|
83269
83386
|
}
|
|
@@ -87295,8 +87412,8 @@ var init_auth_middleware = __esm({
|
|
|
87295
87412
|
|
|
87296
87413
|
// ../dashboard/src/server.ts
|
|
87297
87414
|
import express from "express";
|
|
87298
|
-
import { join as
|
|
87299
|
-
import { existsSync as
|
|
87415
|
+
import { join as join35, dirname as dirname10, resolve as resolve16 } from "node:path";
|
|
87416
|
+
import { existsSync as existsSync29, readFileSync as readFileSync8 } from "node:fs";
|
|
87300
87417
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
87301
87418
|
function clearAiSessionCleanupInterval() {
|
|
87302
87419
|
if (!aiSessionCleanupIntervalHandle) {
|
|
@@ -87305,7 +87422,7 @@ function clearAiSessionCleanupInterval() {
|
|
|
87305
87422
|
clearInterval(aiSessionCleanupIntervalHandle);
|
|
87306
87423
|
aiSessionCleanupIntervalHandle = void 0;
|
|
87307
87424
|
}
|
|
87308
|
-
var
|
|
87425
|
+
var __dirname, PACKAGE_VERSION, CLI_PACKAGE_VERSION2, MIN_AI_SESSION_TTL_MS, MAX_AI_SESSION_TTL_MS, MIN_AI_SESSION_CLEANUP_INTERVAL_MS, MAX_AI_SESSION_CLEANUP_INTERVAL_MS, aiSessionCleanupIntervalHandle;
|
|
87309
87426
|
var init_server = __esm({
|
|
87310
87427
|
"../dashboard/src/server.ts"() {
|
|
87311
87428
|
"use strict";
|
|
@@ -87331,10 +87448,10 @@ var init_server = __esm({
|
|
|
87331
87448
|
init_dev_server_routes();
|
|
87332
87449
|
init_auth_middleware();
|
|
87333
87450
|
init_remote_auth();
|
|
87334
|
-
|
|
87451
|
+
__dirname = dirname10(fileURLToPath4(import.meta.url));
|
|
87335
87452
|
PACKAGE_VERSION = (() => {
|
|
87336
87453
|
try {
|
|
87337
|
-
const packageJsonPath =
|
|
87454
|
+
const packageJsonPath = join35(__dirname, "..", "package.json");
|
|
87338
87455
|
const packageJson = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
|
|
87339
87456
|
if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
|
|
87340
87457
|
return packageJson.version;
|
|
@@ -87345,10 +87462,18 @@ var init_server = __esm({
|
|
|
87345
87462
|
})();
|
|
87346
87463
|
CLI_PACKAGE_VERSION2 = (() => {
|
|
87347
87464
|
try {
|
|
87348
|
-
|
|
87349
|
-
|
|
87350
|
-
|
|
87351
|
-
|
|
87465
|
+
let cur = __dirname;
|
|
87466
|
+
for (let i = 0; i < 8; i++) {
|
|
87467
|
+
const pkgPath = resolve16(cur, "package.json");
|
|
87468
|
+
if (existsSync29(pkgPath)) {
|
|
87469
|
+
const parsed = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
87470
|
+
if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
87471
|
+
return parsed.version;
|
|
87472
|
+
}
|
|
87473
|
+
}
|
|
87474
|
+
const parent = resolve16(cur, "..");
|
|
87475
|
+
if (parent === cur) break;
|
|
87476
|
+
cur = parent;
|
|
87352
87477
|
}
|
|
87353
87478
|
} catch {
|
|
87354
87479
|
}
|
|
@@ -87424,8 +87549,8 @@ var init_src4 = __esm({
|
|
|
87424
87549
|
});
|
|
87425
87550
|
|
|
87426
87551
|
// src/project-context.ts
|
|
87427
|
-
import { resolve as
|
|
87428
|
-
import { existsSync as
|
|
87552
|
+
import { resolve as resolve17, dirname as dirname11 } from "node:path";
|
|
87553
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
87429
87554
|
async function resolveProject(projectNameFlag, cwd = process.cwd(), globalDir) {
|
|
87430
87555
|
const central = new CentralCore(globalDir);
|
|
87431
87556
|
await central.init();
|
|
@@ -87501,10 +87626,10 @@ async function clearDefaultProject(globalDir) {
|
|
|
87501
87626
|
await globalStore.updateSettings(rest);
|
|
87502
87627
|
}
|
|
87503
87628
|
async function detectProjectFromCwd(cwd, central) {
|
|
87504
|
-
let currentDir =
|
|
87629
|
+
let currentDir = resolve17(cwd);
|
|
87505
87630
|
while (true) {
|
|
87506
|
-
const kbPath =
|
|
87507
|
-
if (
|
|
87631
|
+
const kbPath = resolve17(currentDir, ".fusion", "fusion.db");
|
|
87632
|
+
if (existsSync30(kbPath)) {
|
|
87508
87633
|
const project = await central.getProjectByPath(currentDir);
|
|
87509
87634
|
if (project) {
|
|
87510
87635
|
return project;
|
|
@@ -87604,8 +87729,8 @@ __export(task_exports, {
|
|
|
87604
87729
|
runTaskUpdate: () => runTaskUpdate
|
|
87605
87730
|
});
|
|
87606
87731
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
87607
|
-
import { watchFile, unwatchFile, statSync as statSync6, existsSync as
|
|
87608
|
-
import { join as
|
|
87732
|
+
import { watchFile, unwatchFile, statSync as statSync6, existsSync as existsSync31, readFileSync as readFileSync9 } from "node:fs";
|
|
87733
|
+
import { join as join36 } from "node:path";
|
|
87609
87734
|
function asLocalProjectContext(store) {
|
|
87610
87735
|
const cwd = process.cwd();
|
|
87611
87736
|
return {
|
|
@@ -87725,9 +87850,9 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName,
|
|
|
87725
87850
|
console.log(` Path: .fusion/tasks/${task.id}/`);
|
|
87726
87851
|
if (attachFiles && attachFiles.length > 0) {
|
|
87727
87852
|
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
87728
|
-
const { basename: basename9, extname: extname3, resolve:
|
|
87853
|
+
const { basename: basename9, extname: extname3, resolve: resolve19 } = await import("node:path");
|
|
87729
87854
|
for (const filePath of attachFiles) {
|
|
87730
|
-
const resolvedPath =
|
|
87855
|
+
const resolvedPath = resolve19(filePath);
|
|
87731
87856
|
const filename = basename9(resolvedPath);
|
|
87732
87857
|
const ext = extname3(filename).toLowerCase();
|
|
87733
87858
|
const mimeType = MIME_TYPES[ext];
|
|
@@ -87861,8 +87986,8 @@ async function runTaskLogs(id, options = {}, projectName) {
|
|
|
87861
87986
|
printEntries(filteredEntries);
|
|
87862
87987
|
if (options.follow) {
|
|
87863
87988
|
const projectPath = projectContext?.projectPath ?? process.cwd();
|
|
87864
|
-
const logPath =
|
|
87865
|
-
if (!
|
|
87989
|
+
const logPath = join36(projectPath, ".fusion", "tasks", id, "agent.log");
|
|
87990
|
+
if (!existsSync31(logPath)) {
|
|
87866
87991
|
console.log(`
|
|
87867
87992
|
Waiting for log file to be created...`);
|
|
87868
87993
|
}
|
|
@@ -88021,8 +88146,8 @@ async function runTaskMerge(id, projectName) {
|
|
|
88021
88146
|
async function runTaskAttach(id, filePath, projectName) {
|
|
88022
88147
|
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
88023
88148
|
const { basename: basename9, extname: extname3 } = await import("node:path");
|
|
88024
|
-
const { resolve:
|
|
88025
|
-
const resolvedPath =
|
|
88149
|
+
const { resolve: resolve19 } = await import("node:path");
|
|
88150
|
+
const resolvedPath = resolve19(filePath);
|
|
88026
88151
|
const filename = basename9(resolvedPath);
|
|
88027
88152
|
const ext = extname3(filename).toLowerCase();
|
|
88028
88153
|
const mimeType = MIME_TYPES[ext];
|
|
@@ -88553,12 +88678,12 @@ async function promptText(question) {
|
|
|
88553
88678
|
console.log(" (Enter your response. Type DONE on its own line when finished):\n");
|
|
88554
88679
|
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
88555
88680
|
const lines = [];
|
|
88556
|
-
return new Promise((
|
|
88681
|
+
return new Promise((resolve19) => {
|
|
88557
88682
|
const askLine = () => {
|
|
88558
88683
|
rl.question(" ").then((line) => {
|
|
88559
88684
|
if (line.trim() === "DONE") {
|
|
88560
88685
|
rl.close();
|
|
88561
|
-
|
|
88686
|
+
resolve19(lines.join("\n"));
|
|
88562
88687
|
} else {
|
|
88563
88688
|
lines.push(line);
|
|
88564
88689
|
askLine();
|
|
@@ -88962,9 +89087,9 @@ async function runSkillsInstall(args, options) {
|
|
|
88962
89087
|
stdio: "inherit",
|
|
88963
89088
|
shell: true
|
|
88964
89089
|
});
|
|
88965
|
-
const exitCode = await new Promise((
|
|
89090
|
+
const exitCode = await new Promise((resolve19, reject) => {
|
|
88966
89091
|
child.on("exit", (code) => {
|
|
88967
|
-
|
|
89092
|
+
resolve19(code ?? 1);
|
|
88968
89093
|
});
|
|
88969
89094
|
child.on("error", (err) => {
|
|
88970
89095
|
reject(err);
|
|
@@ -88991,9 +89116,9 @@ init_src();
|
|
|
88991
89116
|
init_gh_cli();
|
|
88992
89117
|
import { Type as Type7 } from "typebox";
|
|
88993
89118
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
88994
|
-
import { resolve as
|
|
89119
|
+
import { resolve as resolve18, basename as basename8, extname as extname2, join as join37 } from "node:path";
|
|
88995
89120
|
import { readFile as readFile18 } from "node:fs/promises";
|
|
88996
|
-
import { existsSync as
|
|
89121
|
+
import { existsSync as existsSync32 } from "node:fs";
|
|
88997
89122
|
import { spawn as spawn9 } from "node:child_process";
|
|
88998
89123
|
var MIME_TYPES2 = {
|
|
88999
89124
|
".png": "image/png",
|
|
@@ -89011,14 +89136,14 @@ var MIME_TYPES2 = {
|
|
|
89011
89136
|
".xml": "application/xml"
|
|
89012
89137
|
};
|
|
89013
89138
|
function resolveProjectRoot(cwd) {
|
|
89014
|
-
let current =
|
|
89139
|
+
let current = resolve18(cwd);
|
|
89015
89140
|
while (true) {
|
|
89016
|
-
if (
|
|
89141
|
+
if (existsSync32(join37(current, ".fusion"))) {
|
|
89017
89142
|
return current;
|
|
89018
89143
|
}
|
|
89019
|
-
const parent =
|
|
89144
|
+
const parent = resolve18(current, "..");
|
|
89020
89145
|
if (parent === current) {
|
|
89021
|
-
return
|
|
89146
|
+
return resolve18(cwd);
|
|
89022
89147
|
}
|
|
89023
89148
|
current = parent;
|
|
89024
89149
|
}
|
|
@@ -89034,7 +89159,20 @@ async function getStore2(cwd) {
|
|
|
89034
89159
|
return store;
|
|
89035
89160
|
}
|
|
89036
89161
|
function getFusionDir(cwd) {
|
|
89037
|
-
return
|
|
89162
|
+
return join37(resolveProjectRoot(cwd), ".fusion");
|
|
89163
|
+
}
|
|
89164
|
+
async function validateAssignableAgentId(cwd, agentId) {
|
|
89165
|
+
const { AgentStore: AgentStore2, isEphemeralAgent: isEphemeralAgent2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
89166
|
+
const agentStore = new AgentStore2({ rootDir: getFusionDir(cwd) });
|
|
89167
|
+
await agentStore.init();
|
|
89168
|
+
const agent = await agentStore.getAgent(agentId);
|
|
89169
|
+
if (!agent) {
|
|
89170
|
+
return `Agent ${agentId} not found`;
|
|
89171
|
+
}
|
|
89172
|
+
if (isEphemeralAgent2(agent)) {
|
|
89173
|
+
return `Cannot assign task to ephemeral/runtime agent ${agentId}`;
|
|
89174
|
+
}
|
|
89175
|
+
return null;
|
|
89038
89176
|
}
|
|
89039
89177
|
function formatTaskLine(t) {
|
|
89040
89178
|
const label = t.title || t.description.slice(0, 60) + (t.description.length > 60 ? "\u2026" : "");
|
|
@@ -89097,6 +89235,16 @@ function kbExtension(pi) {
|
|
|
89097
89235
|
}),
|
|
89098
89236
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
89099
89237
|
const store = await getStore2(ctx.cwd);
|
|
89238
|
+
if (params.agentId !== void 0) {
|
|
89239
|
+
const error = await validateAssignableAgentId(ctx.cwd, params.agentId);
|
|
89240
|
+
if (error) {
|
|
89241
|
+
return {
|
|
89242
|
+
content: [{ type: "text", text: error }],
|
|
89243
|
+
isError: true,
|
|
89244
|
+
details: { error }
|
|
89245
|
+
};
|
|
89246
|
+
}
|
|
89247
|
+
}
|
|
89100
89248
|
const task = await store.createTask({
|
|
89101
89249
|
description: params.description.trim(),
|
|
89102
89250
|
dependencies: params.depends,
|
|
@@ -89182,6 +89330,16 @@ Column: triage
|
|
|
89182
89330
|
updatedFields.push("dependencies");
|
|
89183
89331
|
}
|
|
89184
89332
|
if (params.agentId !== void 0) {
|
|
89333
|
+
if (params.agentId !== null) {
|
|
89334
|
+
const error = await validateAssignableAgentId(ctx.cwd, params.agentId);
|
|
89335
|
+
if (error) {
|
|
89336
|
+
return {
|
|
89337
|
+
content: [{ type: "text", text: error }],
|
|
89338
|
+
isError: true,
|
|
89339
|
+
details: { error }
|
|
89340
|
+
};
|
|
89341
|
+
}
|
|
89342
|
+
}
|
|
89185
89343
|
updates.assignedAgentId = params.agentId;
|
|
89186
89344
|
updatedFields.push("agentId");
|
|
89187
89345
|
}
|
|
@@ -89329,7 +89487,7 @@ Column: triage
|
|
|
89329
89487
|
path: Type7.String({ description: "Path to the file to attach" })
|
|
89330
89488
|
}),
|
|
89331
89489
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
89332
|
-
const filePath =
|
|
89490
|
+
const filePath = resolve18(ctx.cwd, params.path.replace(/^@/, ""));
|
|
89333
89491
|
const filename = basename8(filePath);
|
|
89334
89492
|
const ext = extname2(filename).toLowerCase();
|
|
89335
89493
|
const mimeType = MIME_TYPES2[ext];
|
|
@@ -90438,12 +90596,12 @@ Status: ${updated.status}`
|
|
|
90438
90596
|
child.stderr?.on("data", (data) => {
|
|
90439
90597
|
stderr += data.toString();
|
|
90440
90598
|
});
|
|
90441
|
-
const exitCode = await new Promise((
|
|
90599
|
+
const exitCode = await new Promise((resolve19) => {
|
|
90442
90600
|
child.on("exit", (code) => {
|
|
90443
|
-
|
|
90601
|
+
resolve19(code ?? 1);
|
|
90444
90602
|
});
|
|
90445
90603
|
child.on("error", () => {
|
|
90446
|
-
|
|
90604
|
+
resolve19(1);
|
|
90447
90605
|
});
|
|
90448
90606
|
});
|
|
90449
90607
|
try {
|