fifony 0.1.40 → 0.1.41
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/README.md +12 -11
- package/app/dist/assets/{CommandPalette-dMSFpGLm.js → CommandPalette-DNR5umI1.js} +1 -1
- package/app/dist/assets/{KeyboardShortcutsHelp-CH5aYlDe.js → KeyboardShortcutsHelp-Dpl19F20.js} +1 -1
- package/app/dist/assets/OnboardingWizard-CijMhJDW.js +1 -0
- package/app/dist/assets/analytics.lazy-Dq90a756.js +1 -0
- package/app/dist/assets/index-Dy_fM427.js +54 -0
- package/app/dist/assets/{index-BatA8x-K.css → index-Q9jBP0Pz.css} +1 -1
- package/app/dist/index.html +2 -2
- package/app/dist/service-worker.js +53 -2
- package/dist/agent/run-local.js +25 -9
- package/dist/{agent-KDPOZCI5.js → agent-3NXSH3K3.js} +8 -7
- package/dist/{chunk-EPY5TTQK.js → chunk-2CVTK5F2.js} +6 -6
- package/dist/{chunk-LYAI5RPK.js → chunk-7F2SO6LO.js} +3548 -3368
- package/dist/{chunk-UXXUTDGV.js → chunk-EKTVD4JS.js} +33 -17
- package/dist/chunk-I2UHVKHS.js +104 -0
- package/dist/{chunk-O3FGX4J6.js → chunk-LKCD6T6N.js} +115 -24
- package/dist/{chunk-3QL4QAQ5.js → chunk-OJ5DRPWW.js} +14 -14
- package/dist/cli.js +7 -6
- package/dist/issue-runner-WJLBV5ZF.js +16 -0
- package/dist/{issue-state-machine-KOZE5JWX.js → issue-state-machine-NB6NLAX2.js} +5 -5
- package/dist/{issues-7HQC7OIN.js → issues-WWHNHXXK.js} +8 -7
- package/dist/mcp/server.js +1 -1
- package/dist/{queue-workers-ZEZHDX7M.js → queue-workers-3RTEU5EW.js} +3 -3
- package/dist/{scheduler-4R4ZAF25.js → scheduler-UBWYIIAN.js} +8 -7
- package/dist/settings-QSKX6J5K.js +74 -0
- package/dist/{store-FNUWCFOX.js → store-XQOXIGVN.js} +8 -7
- package/dist/web-push-CRVDJKWR.js +28 -0
- package/dist/{workspace-AOHHNWL5.js → workspace-74FGSSKX.js} +8 -4
- package/package.json +6 -2
- package/app/dist/assets/OnboardingWizard-CdJHsRny.js +0 -1
- package/app/dist/assets/analytics.lazy-CKu4136R.js +0 -1
- package/app/dist/assets/index-C13WwYFD.js +0 -54
- package/dist/issue-runner-YZM6WQMY.js +0 -15
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeDiffStats,
|
|
3
|
+
removeTestWorkspace,
|
|
3
4
|
syncIssueDiffStatsToStore
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import {
|
|
6
|
-
logger
|
|
7
|
-
} from "./chunk-DVU3CXWA.js";
|
|
5
|
+
} from "./chunk-LKCD6T6N.js";
|
|
8
6
|
import {
|
|
9
7
|
isoWeek,
|
|
10
8
|
now
|
|
11
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2CVTK5F2.js";
|
|
12
10
|
import {
|
|
13
11
|
S3DB_ISSUE_RESOURCE,
|
|
14
|
-
TARGET_ROOT,
|
|
15
12
|
TERMINAL_STATES
|
|
16
13
|
} from "./chunk-37N5OFHM.js";
|
|
14
|
+
import {
|
|
15
|
+
logger
|
|
16
|
+
} from "./chunk-DVU3CXWA.js";
|
|
17
17
|
|
|
18
18
|
// src/agents/failure-analyzer.ts
|
|
19
19
|
function extractFilePaths(output) {
|
|
@@ -311,22 +311,19 @@ function markAllEventsDirty(ids) {
|
|
|
311
311
|
|
|
312
312
|
// src/persistence/plugins/issue-state-machine.ts
|
|
313
313
|
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
314
|
-
import { execSync } from "child_process";
|
|
315
314
|
import { join } from "path";
|
|
316
315
|
var fsmEventEmitter = null;
|
|
317
316
|
function setFsmEventEmitter(emitter) {
|
|
318
317
|
fsmEventEmitter = emitter;
|
|
319
318
|
}
|
|
320
|
-
function
|
|
319
|
+
function cleanupActiveTestWorkspace(issue) {
|
|
321
320
|
if (!issue.testApplied) return;
|
|
322
321
|
try {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
logger.info({ issueId: issue.id }, "[FSM] Auto-reverted test squash from TARGET_ROOT");
|
|
322
|
+
removeTestWorkspace(issue);
|
|
323
|
+
logger.info({ issueId: issue.id }, "[FSM] Removed isolated test workspace");
|
|
326
324
|
} catch (err) {
|
|
327
|
-
logger.warn({ err: String(err), issueId: issue.id }, "[FSM] Failed to
|
|
325
|
+
logger.warn({ err: String(err), issueId: issue.id }, "[FSM] Failed to remove isolated test workspace");
|
|
328
326
|
}
|
|
329
|
-
issue.testApplied = false;
|
|
330
327
|
}
|
|
331
328
|
function emitFsmEvent(issueId, kind, message) {
|
|
332
329
|
if (fsmEventEmitter) {
|
|
@@ -335,6 +332,25 @@ function emitFsmEvent(issueId, kind, message) {
|
|
|
335
332
|
} catch {
|
|
336
333
|
}
|
|
337
334
|
}
|
|
335
|
+
if (kind === "state") {
|
|
336
|
+
import("./web-push-CRVDJKWR.js").then(({ sendPushToAll, isWebPushReady, SETTING_ID_PUSH_SUBSCRIPTIONS }) => {
|
|
337
|
+
if (!isWebPushReady()) return;
|
|
338
|
+
import("./settings-QSKX6J5K.js").then(({ persistSetting }) => {
|
|
339
|
+
sendPushToAll(
|
|
340
|
+
{ title: "fifony", body: message, tag: issueId, url: "/kanban" },
|
|
341
|
+
async (subs) => {
|
|
342
|
+
await persistSetting(SETTING_ID_PUSH_SUBSCRIPTIONS, subs, {
|
|
343
|
+
scope: "system",
|
|
344
|
+
source: "system"
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
).catch(() => {
|
|
348
|
+
});
|
|
349
|
+
}).catch(() => {
|
|
350
|
+
});
|
|
351
|
+
}).catch(() => {
|
|
352
|
+
});
|
|
353
|
+
}
|
|
338
354
|
}
|
|
339
355
|
var enqueueFn = null;
|
|
340
356
|
function setEnqueueFn(fn) {
|
|
@@ -447,7 +463,7 @@ var issueStateMachineConfig = {
|
|
|
447
463
|
onEnterPlanning: async (context, _event, _machine) => {
|
|
448
464
|
const issue = resolveIssue(context);
|
|
449
465
|
if (issue) {
|
|
450
|
-
|
|
466
|
+
cleanupActiveTestWorkspace(issue);
|
|
451
467
|
issue.planningStatus = "idle";
|
|
452
468
|
issue.planningError = void 0;
|
|
453
469
|
issue.nextRetryAt = void 0;
|
|
@@ -476,7 +492,7 @@ var issueStateMachineConfig = {
|
|
|
476
492
|
onEnterQueued: async (context, event, _machine) => {
|
|
477
493
|
const issue = resolveIssue(context);
|
|
478
494
|
if (issue) {
|
|
479
|
-
|
|
495
|
+
cleanupActiveTestWorkspace(issue);
|
|
480
496
|
if (event === "REQUEUE") {
|
|
481
497
|
const feedback = typeof context.note === "string" ? context.note : void 0;
|
|
482
498
|
if (feedback) issue.lastError = feedback;
|
|
@@ -616,7 +632,7 @@ var issueStateMachineConfig = {
|
|
|
616
632
|
const week = isoWeek();
|
|
617
633
|
const reason = typeof context.reason === "string" ? context.reason : typeof context.note === "string" ? context.note : void 0;
|
|
618
634
|
if (issue) {
|
|
619
|
-
|
|
635
|
+
cleanupActiveTestWorkspace(issue);
|
|
620
636
|
issue.completedAt = ts;
|
|
621
637
|
issue.terminalWeek = week;
|
|
622
638
|
issue.nextRetryAt = void 0;
|
|
@@ -875,4 +891,4 @@ export {
|
|
|
875
891
|
canTransitionIssue,
|
|
876
892
|
visualizeStateMachine
|
|
877
893
|
};
|
|
878
|
-
//# sourceMappingURL=chunk-
|
|
894
|
+
//# sourceMappingURL=chunk-EKTVD4JS.js.map
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
logger
|
|
3
|
+
} from "./chunk-DVU3CXWA.js";
|
|
4
|
+
|
|
5
|
+
// src/domains/web-push.ts
|
|
6
|
+
import webpush from "web-push";
|
|
7
|
+
var vapidKeys = null;
|
|
8
|
+
var vapidConfigured = false;
|
|
9
|
+
var subscriptions = /* @__PURE__ */ new Map();
|
|
10
|
+
var SETTING_ID_VAPID_PUBLIC = "system.push.vapidPublicKey";
|
|
11
|
+
var SETTING_ID_VAPID_PRIVATE = "system.push.vapidPrivateKey";
|
|
12
|
+
var SETTING_ID_PUSH_SUBSCRIPTIONS = "system.push.subscriptions";
|
|
13
|
+
var SETTING_ID_PUSH_CONTACT = "system.push.contact";
|
|
14
|
+
function getVapidPublicKey() {
|
|
15
|
+
return vapidKeys?.publicKey ?? null;
|
|
16
|
+
}
|
|
17
|
+
function isWebPushReady() {
|
|
18
|
+
return vapidConfigured && vapidKeys !== null;
|
|
19
|
+
}
|
|
20
|
+
async function initWebPush(loadSetting, saveSetting) {
|
|
21
|
+
try {
|
|
22
|
+
let publicKey = await loadSetting(SETTING_ID_VAPID_PUBLIC);
|
|
23
|
+
let privateKey = await loadSetting(SETTING_ID_VAPID_PRIVATE);
|
|
24
|
+
if (!publicKey || !privateKey) {
|
|
25
|
+
const generated = webpush.generateVAPIDKeys();
|
|
26
|
+
publicKey = generated.publicKey;
|
|
27
|
+
privateKey = generated.privateKey;
|
|
28
|
+
await saveSetting(SETTING_ID_VAPID_PUBLIC, publicKey, "system");
|
|
29
|
+
await saveSetting(SETTING_ID_VAPID_PRIVATE, privateKey, "system");
|
|
30
|
+
logger.info("[WebPush] Generated and saved new VAPID keys");
|
|
31
|
+
}
|
|
32
|
+
const contact = await loadSetting(SETTING_ID_PUSH_CONTACT) || "mailto:fifony@localhost";
|
|
33
|
+
webpush.setVapidDetails(contact, publicKey, privateKey);
|
|
34
|
+
vapidKeys = { publicKey, privateKey };
|
|
35
|
+
vapidConfigured = true;
|
|
36
|
+
const saved = await loadSetting(SETTING_ID_PUSH_SUBSCRIPTIONS);
|
|
37
|
+
if (Array.isArray(saved)) {
|
|
38
|
+
for (const sub of saved) {
|
|
39
|
+
if (sub.endpoint) subscriptions.set(sub.endpoint, sub);
|
|
40
|
+
}
|
|
41
|
+
logger.info({ count: subscriptions.size }, "[WebPush] Restored push subscriptions");
|
|
42
|
+
}
|
|
43
|
+
logger.info("[WebPush] Initialized");
|
|
44
|
+
} catch (err) {
|
|
45
|
+
logger.warn({ err: String(err) }, "[WebPush] Failed to initialize \u2014 push notifications disabled");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function addSubscription(sub, persistSubscriptions) {
|
|
49
|
+
subscriptions.set(sub.endpoint, sub);
|
|
50
|
+
await persistSubscriptions([...subscriptions.values()]);
|
|
51
|
+
logger.info({ endpoint: sub.endpoint.slice(0, 60) }, "[WebPush] Subscription added");
|
|
52
|
+
}
|
|
53
|
+
async function removeSubscription(endpoint, persistSubscriptions) {
|
|
54
|
+
subscriptions.delete(endpoint);
|
|
55
|
+
await persistSubscriptions([...subscriptions.values()]);
|
|
56
|
+
logger.debug({ endpoint: endpoint.slice(0, 60) }, "[WebPush] Subscription removed");
|
|
57
|
+
}
|
|
58
|
+
function getSubscriptionCount() {
|
|
59
|
+
return subscriptions.size;
|
|
60
|
+
}
|
|
61
|
+
async function sendPushToAll(payload, persistSubscriptions) {
|
|
62
|
+
if (!vapidConfigured || subscriptions.size === 0) return 0;
|
|
63
|
+
const jsonPayload = JSON.stringify(payload);
|
|
64
|
+
let sent = 0;
|
|
65
|
+
let removed = 0;
|
|
66
|
+
const results = await Promise.allSettled(
|
|
67
|
+
[...subscriptions.values()].map(async (sub) => {
|
|
68
|
+
try {
|
|
69
|
+
await webpush.sendNotification(sub, jsonPayload, { TTL: 3600 });
|
|
70
|
+
sent++;
|
|
71
|
+
} catch (err) {
|
|
72
|
+
if (err?.statusCode === 410 || err?.statusCode === 404) {
|
|
73
|
+
subscriptions.delete(sub.endpoint);
|
|
74
|
+
removed++;
|
|
75
|
+
} else {
|
|
76
|
+
logger.debug({ err: String(err), endpoint: sub.endpoint.slice(0, 60) }, "[WebPush] Failed to send");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
if (removed > 0) {
|
|
82
|
+
await persistSubscriptions([...subscriptions.values()]);
|
|
83
|
+
logger.debug({ removed }, "[WebPush] Cleaned stale subscriptions");
|
|
84
|
+
}
|
|
85
|
+
if (sent > 0) {
|
|
86
|
+
logger.debug({ sent, total: subscriptions.size, tag: payload.tag }, "[WebPush] Push delivered");
|
|
87
|
+
}
|
|
88
|
+
return sent;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
SETTING_ID_VAPID_PUBLIC,
|
|
93
|
+
SETTING_ID_VAPID_PRIVATE,
|
|
94
|
+
SETTING_ID_PUSH_SUBSCRIPTIONS,
|
|
95
|
+
SETTING_ID_PUSH_CONTACT,
|
|
96
|
+
getVapidPublicKey,
|
|
97
|
+
isWebPushReady,
|
|
98
|
+
initWebPush,
|
|
99
|
+
addSubscription,
|
|
100
|
+
removeSubscription,
|
|
101
|
+
getSubscriptionCount,
|
|
102
|
+
sendPushToAll
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=chunk-I2UHVKHS.js.map
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logger
|
|
3
|
-
} from "./chunk-DVU3CXWA.js";
|
|
4
1
|
import {
|
|
5
2
|
appendFileTail,
|
|
6
3
|
idToSafePath,
|
|
7
4
|
now,
|
|
8
5
|
renderPrompt
|
|
9
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2CVTK5F2.js";
|
|
10
7
|
import {
|
|
11
8
|
SOURCE_MARKER,
|
|
12
9
|
SOURCE_ROOT,
|
|
13
10
|
TARGET_ROOT,
|
|
14
11
|
WORKSPACE_ROOT
|
|
15
12
|
} from "./chunk-37N5OFHM.js";
|
|
13
|
+
import {
|
|
14
|
+
logger
|
|
15
|
+
} from "./chunk-DVU3CXWA.js";
|
|
16
16
|
|
|
17
17
|
// src/domains/workspace.ts
|
|
18
18
|
import {
|
|
@@ -263,8 +263,15 @@ function buildExecutionPayload(issue, provider, plan, workspacePath) {
|
|
|
263
263
|
mitigation: r.mitigation || ""
|
|
264
264
|
})),
|
|
265
265
|
tooling: {
|
|
266
|
-
skills: plan.suggestedSkills || []
|
|
267
|
-
|
|
266
|
+
skills: (plan.suggestedSkills || []).map((name) => ({
|
|
267
|
+
name,
|
|
268
|
+
why: "Suggested by the planner for this issue."
|
|
269
|
+
})),
|
|
270
|
+
subagents: (plan.suggestedAgents || []).map((name) => ({
|
|
271
|
+
name,
|
|
272
|
+
role: "specialist",
|
|
273
|
+
why: "Suggested by the planner for parallel or specialized work."
|
|
274
|
+
}))
|
|
268
275
|
},
|
|
269
276
|
targetPaths: plan.suggestedPaths || [],
|
|
270
277
|
workspacePath,
|
|
@@ -837,7 +844,7 @@ var collectClaudeUsageFromCli = () => collectProviderUsageSnapshotFromCli("claud
|
|
|
837
844
|
"--dangerously-skip-permissions"
|
|
838
845
|
]);
|
|
839
846
|
function buildClaudeCommand(options) {
|
|
840
|
-
const parts = ["claude", "--print"
|
|
847
|
+
const parts = ["claude", "--print"];
|
|
841
848
|
if (options.readOnly) {
|
|
842
849
|
parts.push("--permission-mode plan");
|
|
843
850
|
} else if (!options.noToolAccess) {
|
|
@@ -901,7 +908,7 @@ async function compile(issue, provider, plan, config, workspacePath, skillContex
|
|
|
901
908
|
const env3 = {
|
|
902
909
|
FIFONY_PLAN_COMPLEXITY: plan.estimatedComplexity,
|
|
903
910
|
FIFONY_PLAN_STEPS: String(plan.steps.length),
|
|
904
|
-
FIFONY_EXECUTION_PAYLOAD_FILE: "
|
|
911
|
+
FIFONY_EXECUTION_PAYLOAD_FILE: "execution-payload.json"
|
|
905
912
|
};
|
|
906
913
|
if (plan.suggestedPaths?.length) env3.FIFONY_PLAN_PATHS = plan.suggestedPaths.join(",");
|
|
907
914
|
if (plan.suggestedSkills?.length) {
|
|
@@ -1455,6 +1462,27 @@ function getEffectiveAgentProviders(state, issue, _workflowDefinition, workflowC
|
|
|
1455
1462
|
}
|
|
1456
1463
|
|
|
1457
1464
|
// src/agents/command-executor.ts
|
|
1465
|
+
var HOOK_RUNTIME_CONFIG = {
|
|
1466
|
+
pollIntervalMs: 0,
|
|
1467
|
+
workerConcurrency: 1,
|
|
1468
|
+
maxConcurrentByState: {},
|
|
1469
|
+
commandTimeoutMs: 18e5,
|
|
1470
|
+
maxAttemptsDefault: 1,
|
|
1471
|
+
maxTurns: 1,
|
|
1472
|
+
retryDelayMs: 0,
|
|
1473
|
+
staleInProgressTimeoutMs: 0,
|
|
1474
|
+
logLinesTail: 12e3,
|
|
1475
|
+
maxPreviousOutputChars: 12e3,
|
|
1476
|
+
agentProvider: "codex",
|
|
1477
|
+
agentCommand: "",
|
|
1478
|
+
defaultEffort: { default: "medium" },
|
|
1479
|
+
runMode: "filesystem",
|
|
1480
|
+
autoReviewApproval: true,
|
|
1481
|
+
afterCreateHook: "",
|
|
1482
|
+
beforeRunHook: "",
|
|
1483
|
+
afterRunHook: "",
|
|
1484
|
+
beforeRemoveHook: ""
|
|
1485
|
+
};
|
|
1458
1486
|
async function runCommandWithTimeout(command, workspacePath, issue, config, promptText, promptFile, extraEnv = {}, outputFile) {
|
|
1459
1487
|
return new Promise((resolve2) => {
|
|
1460
1488
|
const started = Date.now();
|
|
@@ -1542,7 +1570,7 @@ async function runCommandWithTimeout(command, workspacePath, issue, config, prom
|
|
|
1542
1570
|
};
|
|
1543
1571
|
child.stdout?.on("data", onChunk);
|
|
1544
1572
|
child.stderr?.on("data", onChunk);
|
|
1545
|
-
const AGENT_STALE_OUTPUT_MS =
|
|
1573
|
+
const AGENT_STALE_OUTPUT_MS = 18e5;
|
|
1546
1574
|
const timer = setTimeout(() => {
|
|
1547
1575
|
timedOut = true;
|
|
1548
1576
|
if (pid) {
|
|
@@ -1639,19 +1667,9 @@ Command exit code ${code ?? "unknown"} after ${duration}ms.`) });
|
|
|
1639
1667
|
async function runHook(command, workspacePath, issue, hookName, extraEnv = {}) {
|
|
1640
1668
|
if (!command.trim()) return;
|
|
1641
1669
|
const result = await runCommandWithTimeout(command, workspacePath, issue, {
|
|
1642
|
-
|
|
1643
|
-
workerConcurrency: 1,
|
|
1644
|
-
maxConcurrentByState: {},
|
|
1645
|
-
commandTimeoutMs: 3e5,
|
|
1646
|
-
maxAttemptsDefault: 1,
|
|
1647
|
-
retryDelayMs: 0,
|
|
1648
|
-
staleInProgressTimeoutMs: 0,
|
|
1649
|
-
logLinesTail: 12e3,
|
|
1670
|
+
...HOOK_RUNTIME_CONFIG,
|
|
1650
1671
|
agentProvider: normalizeAgentProvider(env2.FIFONY_AGENT_PROVIDER ?? "codex"),
|
|
1651
|
-
agentCommand: command
|
|
1652
|
-
maxTurns: 1,
|
|
1653
|
-
runMode: "filesystem",
|
|
1654
|
-
autoReviewApproval: true
|
|
1672
|
+
agentCommand: command
|
|
1655
1673
|
}, "", "", { FIFONY_HOOK_NAME: hookName, ...extraEnv });
|
|
1656
1674
|
if (!result.success) {
|
|
1657
1675
|
throw new Error(`${hookName} hook failed: ${result.output}`);
|
|
@@ -1986,6 +2004,69 @@ function copyCliConfigDirs(sourceRoot, worktreePath) {
|
|
|
1986
2004
|
}
|
|
1987
2005
|
}
|
|
1988
2006
|
}
|
|
2007
|
+
function isGitWorkingTree(dir) {
|
|
2008
|
+
try {
|
|
2009
|
+
execSync("git rev-parse --git-dir", { cwd: dir, stdio: "pipe", timeout: 5e3 });
|
|
2010
|
+
return true;
|
|
2011
|
+
} catch {
|
|
2012
|
+
return false;
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
function resolveTestWorkspacePath(issue) {
|
|
2016
|
+
const workspaceRoot = issue.workspacePath ?? join7(WORKSPACE_ROOT, idToSafePath(issue.id));
|
|
2017
|
+
return join7(workspaceRoot, "test-worktree");
|
|
2018
|
+
}
|
|
2019
|
+
function createTestWorkspace(issue) {
|
|
2020
|
+
ensureGitRepoReadyForWorktrees(TARGET_ROOT, "create isolated test workspaces");
|
|
2021
|
+
assertIssueHasGitWorktree(issue, "create a test workspace");
|
|
2022
|
+
const workspaceRoot = issue.workspacePath ?? join7(WORKSPACE_ROOT, idToSafePath(issue.id));
|
|
2023
|
+
const testWorkspacePath = issue.testWorkspacePath ?? resolveTestWorkspacePath(issue);
|
|
2024
|
+
mkdirSync(workspaceRoot, { recursive: true });
|
|
2025
|
+
if (existsSync7(testWorkspacePath)) {
|
|
2026
|
+
if (isGitWorkingTree(testWorkspacePath)) {
|
|
2027
|
+
issue.testWorkspacePath = testWorkspacePath;
|
|
2028
|
+
issue.testApplied = true;
|
|
2029
|
+
return testWorkspacePath;
|
|
2030
|
+
}
|
|
2031
|
+
rmSync2(testWorkspacePath, { recursive: true, force: true });
|
|
2032
|
+
}
|
|
2033
|
+
try {
|
|
2034
|
+
execSync(`git worktree add --detach "${testWorkspacePath}" "${issue.branchName}"`, {
|
|
2035
|
+
cwd: TARGET_ROOT,
|
|
2036
|
+
stdio: "pipe",
|
|
2037
|
+
timeout: 3e4
|
|
2038
|
+
});
|
|
2039
|
+
} catch (err) {
|
|
2040
|
+
const msg = err.stderr || err.stdout || String(err);
|
|
2041
|
+
throw new Error(`Failed to create isolated test workspace: ${msg}`);
|
|
2042
|
+
}
|
|
2043
|
+
copyCliConfigDirs(TARGET_ROOT, testWorkspacePath);
|
|
2044
|
+
issue.testWorkspacePath = testWorkspacePath;
|
|
2045
|
+
issue.testApplied = true;
|
|
2046
|
+
return testWorkspacePath;
|
|
2047
|
+
}
|
|
2048
|
+
function removeTestWorkspace(issue) {
|
|
2049
|
+
const testWorkspacePath = issue.testWorkspacePath;
|
|
2050
|
+
issue.testApplied = false;
|
|
2051
|
+
issue.testWorkspacePath = void 0;
|
|
2052
|
+
if (!testWorkspacePath) return;
|
|
2053
|
+
try {
|
|
2054
|
+
execSync(`git worktree remove --force "${testWorkspacePath}"`, {
|
|
2055
|
+
cwd: TARGET_ROOT,
|
|
2056
|
+
stdio: "pipe",
|
|
2057
|
+
timeout: 3e4
|
|
2058
|
+
});
|
|
2059
|
+
logger.info({ issueId: issue.id, testWorkspacePath }, "[Workspace] Removed isolated test workspace");
|
|
2060
|
+
return;
|
|
2061
|
+
} catch (error) {
|
|
2062
|
+
logger.warn({ issueId: issue.id, testWorkspacePath, err: String(error) }, "[Workspace] Failed to remove isolated test workspace via git worktree");
|
|
2063
|
+
}
|
|
2064
|
+
try {
|
|
2065
|
+
rmSync2(testWorkspacePath, { recursive: true, force: true });
|
|
2066
|
+
} catch (error) {
|
|
2067
|
+
logger.warn({ issueId: issue.id, testWorkspacePath, err: String(error) }, "[Workspace] Failed to remove isolated test workspace directory");
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
1989
2070
|
async function createGitWorktree(issue, worktreePath, baseBranch) {
|
|
1990
2071
|
let headCommitAtStart = "";
|
|
1991
2072
|
const resolvedBaseBranch = baseBranch ?? detectDefaultBranch(TARGET_ROOT);
|
|
@@ -2056,6 +2137,9 @@ async function cleanWorkspace(issueId, issue, state) {
|
|
|
2056
2137
|
logger.warn(`before_remove hook failed for ${issueId}: ${String(error)}`);
|
|
2057
2138
|
}
|
|
2058
2139
|
}
|
|
2140
|
+
if (issue?.testWorkspacePath) {
|
|
2141
|
+
removeTestWorkspace(issue);
|
|
2142
|
+
}
|
|
2059
2143
|
if (issue?.branchName && issue.worktreePath) {
|
|
2060
2144
|
try {
|
|
2061
2145
|
execSync(`git worktree remove --force "${issue.worktreePath}"`, { cwd: TARGET_ROOT, stdio: "pipe" });
|
|
@@ -2130,7 +2214,7 @@ function parseDiffStats(issue, raw) {
|
|
|
2130
2214
|
}
|
|
2131
2215
|
async function syncIssueDiffStatsToStore(issue) {
|
|
2132
2216
|
if (!issue?.id) return;
|
|
2133
|
-
const { getIssueStateResource } = await import("./store-
|
|
2217
|
+
const { getIssueStateResource } = await import("./store-XQOXIGVN.js");
|
|
2134
2218
|
const issueResource = getIssueStateResource();
|
|
2135
2219
|
if (!issueResource) return;
|
|
2136
2220
|
const toNumber = (value) => {
|
|
@@ -2296,8 +2380,13 @@ function dryMerge(issue) {
|
|
|
2296
2380
|
execSync("git merge --abort", { cwd: TARGET_ROOT, stdio: "pipe" });
|
|
2297
2381
|
} catch {
|
|
2298
2382
|
try {
|
|
2299
|
-
execSync("git reset --
|
|
2383
|
+
execSync("git reset --merge ORIG_HEAD", { cwd: TARGET_ROOT, stdio: "pipe" });
|
|
2300
2384
|
} catch {
|
|
2385
|
+
try {
|
|
2386
|
+
execSync("git reset --merge", { cwd: TARGET_ROOT, stdio: "pipe" });
|
|
2387
|
+
} catch (error) {
|
|
2388
|
+
logger.warn({ issueId: issue.id, err: String(error) }, "[Workspace] Failed to safely clean dry-merge state");
|
|
2389
|
+
}
|
|
2301
2390
|
}
|
|
2302
2391
|
}
|
|
2303
2392
|
let changedFiles = 0;
|
|
@@ -2382,6 +2471,8 @@ export {
|
|
|
2382
2471
|
initializeGitRepoForWorktrees,
|
|
2383
2472
|
assertIssueHasGitWorktree,
|
|
2384
2473
|
detectDefaultBranch,
|
|
2474
|
+
createTestWorkspace,
|
|
2475
|
+
removeTestWorkspace,
|
|
2385
2476
|
createGitWorktree,
|
|
2386
2477
|
prepareWorkspace,
|
|
2387
2478
|
cleanWorkspace,
|
|
@@ -2397,4 +2488,4 @@ export {
|
|
|
2397
2488
|
hydrateIssuePathsFromWorkspace,
|
|
2398
2489
|
writeVersionedArtifacts
|
|
2399
2490
|
};
|
|
2400
|
-
//# sourceMappingURL=chunk-
|
|
2491
|
+
//# sourceMappingURL=chunk-LKCD6T6N.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logger
|
|
3
|
-
} from "./chunk-DVU3CXWA.js";
|
|
4
1
|
import {
|
|
5
2
|
TERMINAL_STATES
|
|
6
3
|
} from "./chunk-37N5OFHM.js";
|
|
4
|
+
import {
|
|
5
|
+
logger
|
|
6
|
+
} from "./chunk-DVU3CXWA.js";
|
|
7
7
|
|
|
8
8
|
// src/persistence/plugins/queue-workers.ts
|
|
9
9
|
var PHASE_ORDER = { review: 0, execute: 1, plan: 2 };
|
|
@@ -26,7 +26,7 @@ async function initQueueWorkers(state) {
|
|
|
26
26
|
}, 3e4);
|
|
27
27
|
persistInterval = setInterval(() => {
|
|
28
28
|
if (!active || !runtimeState) return;
|
|
29
|
-
import("./store-
|
|
29
|
+
import("./store-XQOXIGVN.js").then(
|
|
30
30
|
({ persistState }) => persistState(runtimeState).catch(() => {
|
|
31
31
|
})
|
|
32
32
|
).catch(() => {
|
|
@@ -116,11 +116,11 @@ function sortQueue() {
|
|
|
116
116
|
}
|
|
117
117
|
async function dispatchPlan(issue) {
|
|
118
118
|
logger.info({ issueId: issue.id, identifier: issue.identifier }, "[Queue] Dispatching plan job");
|
|
119
|
-
const { runPlanningJob } = await import("./issue-runner-
|
|
119
|
+
const { runPlanningJob } = await import("./issue-runner-WJLBV5ZF.js");
|
|
120
120
|
await runPlanningJob(runtimeState, issue);
|
|
121
121
|
}
|
|
122
122
|
async function dispatchExecute(issue) {
|
|
123
|
-
const { runIssueOnce } = await import("./issue-runner-
|
|
123
|
+
const { runIssueOnce } = await import("./issue-runner-WJLBV5ZF.js");
|
|
124
124
|
while (active && runtimeState) {
|
|
125
125
|
const current = getCurrentIssue(issue.id);
|
|
126
126
|
if (!current || current.state !== "Queued" && current.state !== "Running") break;
|
|
@@ -130,12 +130,12 @@ async function dispatchExecute(issue) {
|
|
|
130
130
|
}
|
|
131
131
|
async function dispatchReview(issue) {
|
|
132
132
|
logger.info({ issueId: issue.id, identifier: issue.identifier }, "[Queue] Dispatching review job");
|
|
133
|
-
const { runIssueOnce } = await import("./issue-runner-
|
|
133
|
+
const { runIssueOnce } = await import("./issue-runner-WJLBV5ZF.js");
|
|
134
134
|
await runIssueOnce(runtimeState, issue, running);
|
|
135
135
|
}
|
|
136
136
|
async function checkStaleIssues() {
|
|
137
137
|
if (!runtimeState) return;
|
|
138
|
-
const { ensureNotStale } = await import("./scheduler-
|
|
138
|
+
const { ensureNotStale } = await import("./scheduler-UBWYIIAN.js");
|
|
139
139
|
await ensureNotStale(runtimeState, runtimeState.config.staleInProgressTimeoutMs);
|
|
140
140
|
}
|
|
141
141
|
var draining = false;
|
|
@@ -188,7 +188,7 @@ async function enqueue(issue, job) {
|
|
|
188
188
|
async function recoverState() {
|
|
189
189
|
if (!runtimeState) return;
|
|
190
190
|
try {
|
|
191
|
-
const { getIssueStateMachinePlugin, ISSUE_STATE_MACHINE_ID } = await import("./issue-state-machine-
|
|
191
|
+
const { getIssueStateMachinePlugin, ISSUE_STATE_MACHINE_ID } = await import("./issue-state-machine-NB6NLAX2.js");
|
|
192
192
|
const fsmPlugin = getIssueStateMachinePlugin();
|
|
193
193
|
if (fsmPlugin?.getState) {
|
|
194
194
|
for (const issue of runtimeState.issues) {
|
|
@@ -226,9 +226,9 @@ async function recoverState() {
|
|
|
226
226
|
}
|
|
227
227
|
async function recoverOrphans() {
|
|
228
228
|
if (!runtimeState) return;
|
|
229
|
-
const { isAgentStillRunning, cleanStalePidFile } = await import("./agent-
|
|
230
|
-
const { executeTransition } = await import("./issue-state-machine-
|
|
231
|
-
const { addEvent } = await import("./issues-
|
|
229
|
+
const { isAgentStillRunning, cleanStalePidFile } = await import("./agent-3NXSH3K3.js");
|
|
230
|
+
const { executeTransition } = await import("./issue-state-machine-NB6NLAX2.js");
|
|
231
|
+
const { addEvent } = await import("./issues-WWHNHXXK.js");
|
|
232
232
|
const candidates = runtimeState.issues.filter((i) => i.state === "Running" || i.state === "Queued");
|
|
233
233
|
logger.debug({ count: candidates.length }, "[Queue] Checking for orphaned agent processes");
|
|
234
234
|
for (const issue of candidates) {
|
|
@@ -266,7 +266,7 @@ function cleanTerminalWorkspaces() {
|
|
|
266
266
|
logger.info({ count: terminals.length }, "[Queue] Scheduling terminal workspace cleanup in background");
|
|
267
267
|
const state = runtimeState;
|
|
268
268
|
setImmediate(async () => {
|
|
269
|
-
const { cleanWorkspace } = await import("./agent-
|
|
269
|
+
const { cleanWorkspace } = await import("./agent-3NXSH3K3.js");
|
|
270
270
|
for (const issue of terminals) {
|
|
271
271
|
try {
|
|
272
272
|
await cleanWorkspace(issue.id, issue, state);
|
|
@@ -300,4 +300,4 @@ export {
|
|
|
300
300
|
cleanTerminalWorkspaces,
|
|
301
301
|
getQueueStats
|
|
302
302
|
};
|
|
303
|
-
//# sourceMappingURL=chunk-
|
|
303
|
+
//# sourceMappingURL=chunk-OJ5DRPWW.js.map
|
package/dist/cli.js
CHANGED
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
importReferenceArtifacts,
|
|
4
4
|
listReferenceRepositories,
|
|
5
5
|
syncReferenceRepositories
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-7F2SO6LO.js";
|
|
7
|
+
import "./chunk-OJ5DRPWW.js";
|
|
8
|
+
import "./chunk-I2UHVKHS.js";
|
|
9
|
+
import "./chunk-EKTVD4JS.js";
|
|
10
|
+
import "./chunk-LKCD6T6N.js";
|
|
11
|
+
import "./chunk-2CVTK5F2.js";
|
|
12
12
|
import "./chunk-37N5OFHM.js";
|
|
13
|
+
import "./chunk-DVU3CXWA.js";
|
|
13
14
|
|
|
14
15
|
// src/cli.ts
|
|
15
16
|
import { spawn } from "child_process";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runIssueOnce,
|
|
3
|
+
runPlanningJob
|
|
4
|
+
} from "./chunk-7F2SO6LO.js";
|
|
5
|
+
import "./chunk-OJ5DRPWW.js";
|
|
6
|
+
import "./chunk-I2UHVKHS.js";
|
|
7
|
+
import "./chunk-EKTVD4JS.js";
|
|
8
|
+
import "./chunk-LKCD6T6N.js";
|
|
9
|
+
import "./chunk-2CVTK5F2.js";
|
|
10
|
+
import "./chunk-37N5OFHM.js";
|
|
11
|
+
import "./chunk-DVU3CXWA.js";
|
|
12
|
+
export {
|
|
13
|
+
runIssueOnce,
|
|
14
|
+
runPlanningJob
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=issue-runner-WJLBV5ZF.js.map
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
setIssueResourceStateApi,
|
|
17
17
|
setIssueStateMachinePlugin,
|
|
18
18
|
visualizeStateMachine
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-EPY5TTQK.js";
|
|
19
|
+
} from "./chunk-EKTVD4JS.js";
|
|
20
|
+
import "./chunk-LKCD6T6N.js";
|
|
21
|
+
import "./chunk-2CVTK5F2.js";
|
|
23
22
|
import "./chunk-37N5OFHM.js";
|
|
23
|
+
import "./chunk-DVU3CXWA.js";
|
|
24
24
|
export {
|
|
25
25
|
ISSUE_STATE_MACHINE_ID,
|
|
26
26
|
canTransitionIssue,
|
|
@@ -40,4 +40,4 @@ export {
|
|
|
40
40
|
setIssueStateMachinePlugin,
|
|
41
41
|
visualizeStateMachine
|
|
42
42
|
};
|
|
43
|
-
//# sourceMappingURL=issue-state-machine-
|
|
43
|
+
//# sourceMappingURL=issue-state-machine-NB6NLAX2.js.map
|
|
@@ -11,15 +11,16 @@ import {
|
|
|
11
11
|
normalizeIssue,
|
|
12
12
|
transitionIssue,
|
|
13
13
|
validateConfig
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-7F2SO6LO.js";
|
|
15
|
+
import "./chunk-OJ5DRPWW.js";
|
|
16
|
+
import "./chunk-I2UHVKHS.js";
|
|
16
17
|
import {
|
|
17
18
|
computeMetrics
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-EPY5TTQK.js";
|
|
19
|
+
} from "./chunk-EKTVD4JS.js";
|
|
20
|
+
import "./chunk-LKCD6T6N.js";
|
|
21
|
+
import "./chunk-2CVTK5F2.js";
|
|
22
22
|
import "./chunk-37N5OFHM.js";
|
|
23
|
+
import "./chunk-DVU3CXWA.js";
|
|
23
24
|
export {
|
|
24
25
|
addEvent,
|
|
25
26
|
applyWorkflowConfig,
|
|
@@ -35,4 +36,4 @@ export {
|
|
|
35
36
|
transitionIssue,
|
|
36
37
|
validateConfig
|
|
37
38
|
};
|
|
38
|
-
//# sourceMappingURL=issues-
|
|
39
|
+
//# sourceMappingURL=issues-WWHNHXXK.js.map
|
package/dist/mcp/server.js
CHANGED
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
recoverOrphans,
|
|
8
8
|
recoverState,
|
|
9
9
|
stopQueueWorkers
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-DVU3CXWA.js";
|
|
10
|
+
} from "./chunk-OJ5DRPWW.js";
|
|
12
11
|
import "./chunk-37N5OFHM.js";
|
|
12
|
+
import "./chunk-DVU3CXWA.js";
|
|
13
13
|
export {
|
|
14
14
|
areQueueWorkersActive,
|
|
15
15
|
cleanTerminalWorkspaces,
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
recoverState,
|
|
21
21
|
stopQueueWorkers
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=queue-workers-
|
|
23
|
+
//# sourceMappingURL=queue-workers-3RTEU5EW.js.map
|
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
hasTerminalQueue,
|
|
5
5
|
installGracefulShutdown,
|
|
6
6
|
isShuttingDown
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-7F2SO6LO.js";
|
|
8
|
+
import "./chunk-OJ5DRPWW.js";
|
|
9
|
+
import "./chunk-I2UHVKHS.js";
|
|
10
|
+
import "./chunk-EKTVD4JS.js";
|
|
11
|
+
import "./chunk-LKCD6T6N.js";
|
|
12
|
+
import "./chunk-2CVTK5F2.js";
|
|
13
13
|
import "./chunk-37N5OFHM.js";
|
|
14
|
+
import "./chunk-DVU3CXWA.js";
|
|
14
15
|
export {
|
|
15
16
|
analyzeParallelizability,
|
|
16
17
|
ensureNotStale,
|
|
@@ -18,4 +19,4 @@ export {
|
|
|
18
19
|
installGracefulShutdown,
|
|
19
20
|
isShuttingDown
|
|
20
21
|
};
|
|
21
|
-
//# sourceMappingURL=scheduler-
|
|
22
|
+
//# sourceMappingURL=scheduler-UBWYIIAN.js.map
|