fifony 0.1.26 → 0.1.27-next.84df008

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.
Files changed (36) hide show
  1. package/README.md +152 -129
  2. package/app/dist/assets/{KeyboardShortcutsHelp-lTNj9GiT.js → KeyboardShortcutsHelp-By0KcDhZ.js} +1 -1
  3. package/app/dist/assets/OnboardingWizard-5cz7Onsu.js +1 -0
  4. package/app/dist/assets/{analytics.lazy-C42PFRzr.js → analytics.lazy-ArFwnOEn.js} +1 -1
  5. package/app/dist/assets/{createLucideIcon-BWC-guQt.js → createLucideIcon-DgMTp0yx.js} +1 -1
  6. package/app/dist/assets/index-59O8esMr.js +45 -0
  7. package/app/dist/assets/{index-Qr2OPvRO.css → index-DuBwUsuf.css} +1 -1
  8. package/app/dist/assets/vendor-D-IqxHHu.js +9 -0
  9. package/app/dist/dinofffaur.webp +0 -0
  10. package/app/dist/index.html +4 -4
  11. package/app/dist/service-worker.js +1 -1
  12. package/dist/agent/run-local.js +57 -144
  13. package/dist/agent-KMXNVDRO.js +74 -0
  14. package/dist/chunk-FJR4ALEN.js +847 -0
  15. package/dist/{chunk-2F3Q2MAG.js → chunk-HSGUPFTV.js} +1224 -611
  16. package/dist/chunk-O5AEQXUV.js +311 -0
  17. package/dist/chunk-OONOOWNC.js +123 -0
  18. package/dist/{chunk-NFHVAIPW.js → chunk-UYCDOH6S.js} +380 -795
  19. package/dist/chunk-XENKNHFS.js +295 -0
  20. package/dist/cli.js +6 -4
  21. package/dist/issue-runner-JJAFMHKV.js +15 -0
  22. package/dist/{issue-state-machine-OWABY5S2.js → issue-state-machine-ACMUJSXC.js} +5 -3
  23. package/dist/issues-VDFXBK3N.js +40 -0
  24. package/dist/mcp/server.js +23 -121
  25. package/dist/queue-workers-U47CVPTO.js +23 -0
  26. package/dist/scheduler-MEXEDV4M.js +21 -0
  27. package/dist/{store-WN47MDT5.js → store-AG6LLYJ7.js} +7 -5
  28. package/dist/workspace-474CCKTW.js +44 -0
  29. package/package.json +6 -6
  30. package/app/dist/assets/OnboardingWizard-B6LlJR9B.js +0 -1
  31. package/app/dist/assets/index-fVSxs9d5.js +0 -43
  32. package/app/dist/assets/vendor-BTlTWMUF.js +0 -9
  33. package/dist/chunk-AMOGDOM7.js +0 -796
  34. package/dist/chunk-IA7IMQ5F.js +0 -91
  35. package/dist/issue-runner-DA4IDLKX.js +0 -13
  36. package/dist/queue-workers-JIH5ZMNQ.js +0 -20
Binary file
@@ -13,11 +13,11 @@
13
13
  <link rel="manifest" href="/assets/manifest.webmanifest" />
14
14
  <link rel="icon" href="/assets/icon.svg" type="image/svg+xml" />
15
15
  <link rel="apple-touch-icon" href="/assets/icon.svg" />
16
- <script type="module" crossorigin src="/assets/assets/index-fVSxs9d5.js"></script>
16
+ <script type="module" crossorigin src="/assets/assets/index-59O8esMr.js"></script>
17
17
  <link rel="modulepreload" crossorigin href="/assets/assets/rolldown-runtime-DF2fYuay.js">
18
- <link rel="modulepreload" crossorigin href="/assets/assets/vendor-BTlTWMUF.js">
19
- <link rel="modulepreload" crossorigin href="/assets/assets/createLucideIcon-BWC-guQt.js">
20
- <link rel="stylesheet" crossorigin href="/assets/assets/index-Qr2OPvRO.css">
18
+ <link rel="modulepreload" crossorigin href="/assets/assets/vendor-D-IqxHHu.js">
19
+ <link rel="modulepreload" crossorigin href="/assets/assets/createLucideIcon-DgMTp0yx.js">
20
+ <link rel="stylesheet" crossorigin href="/assets/assets/index-DuBwUsuf.css">
21
21
  </head>
22
22
  <body>
23
23
  <div id="root"></div>
@@ -1,4 +1,4 @@
1
- const CACHE_VERSION = "1774027644110";
1
+ const CACHE_VERSION = "1774159196271";
2
2
  const CORE_CACHE = `fifony-core-${CACHE_VERSION}`;
3
3
  const ASSET_CACHE = `fifony-assets-${CACHE_VERSION}`;
4
4
  const APP_SHELL_ROUTES = ["/kanban", "/issues", "/agents", "/settings", "/onboarding"];
@@ -5,18 +5,14 @@ import {
5
5
  applyWorkflowConfig,
6
6
  buildQueueTitle,
7
7
  buildRuntimeState,
8
- cleanStalePidFile,
9
8
  closeStateStore,
10
9
  createContainer,
11
10
  deriveConfig,
12
11
  detectProjectName,
13
- ensureNotStale,
14
12
  hasTerminalQueue,
15
13
  hydrate,
16
14
  initStateStore,
17
15
  installGracefulShutdown,
18
- isAgentStillRunning,
19
- isShuttingDown,
20
16
  loadPersistedState,
21
17
  loadRuntimeSettings,
22
18
  persistDetectedProvidersSetting,
@@ -27,58 +23,47 @@ import {
27
23
  startApiServer,
28
24
  syncRuntimeConfigSettings,
29
25
  validateConfig
30
- } from "../chunk-2F3Q2MAG.js";
26
+ } from "../chunk-HSGUPFTV.js";
31
27
  import {
32
- enqueueForExecution,
33
- enqueueForPlanning,
34
- enqueueForReview,
35
- initQueueWorkers,
36
- stopQueueWorkers
37
- } from "../chunk-IA7IMQ5F.js";
28
+ computeMetrics
29
+ } from "../chunk-FJR4ALEN.js";
38
30
  import {
39
- cleanWorkspace,
40
- computeMetrics,
41
31
  detectAvailableProviders,
42
32
  detectDefaultBranch,
43
- executeTransition,
44
33
  getProviderDefaultCommand,
45
- hasDirtyState,
46
34
  resolveDefaultProvider,
47
35
  setSkipSource
48
- } from "../chunk-NFHVAIPW.js";
36
+ } from "../chunk-UYCDOH6S.js";
49
37
  import {
50
- CLI_ARGS,
51
- PACKAGE_ROOT,
52
- STATE_ROOT,
53
- TARGET_ROOT,
54
38
  debugBoot,
55
39
  fail,
56
40
  now,
57
- parseIntArg,
58
- sleep
59
- } from "../chunk-AMOGDOM7.js";
41
+ parseIntArg
42
+ } from "../chunk-O5AEQXUV.js";
43
+ import {
44
+ cleanTerminalWorkspaces,
45
+ initQueueWorkers,
46
+ recoverOrphans,
47
+ recoverState,
48
+ stopQueueWorkers
49
+ } from "../chunk-XENKNHFS.js";
60
50
  import {
61
51
  initLogger,
62
52
  logger
63
53
  } from "../chunk-DVU3CXWA.js";
54
+ import {
55
+ CLI_ARGS,
56
+ PACKAGE_ROOT,
57
+ STATE_ROOT,
58
+ TARGET_ROOT
59
+ } from "../chunk-OONOOWNC.js";
64
60
 
65
61
  // src/boot.ts
66
- import { mkdirSync } from "fs";
62
+ import { mkdirSync, readFileSync } from "fs";
67
63
  import { env, exit, argv } from "process";
64
+
65
+ // src/persistence/plugins/dev-server.ts
68
66
  import { resolve } from "path";
69
- function parsePort(args) {
70
- for (let i = 0; i < args.length; i += 1) {
71
- const arg = args[i];
72
- if (arg === "--port") {
73
- const value = args[i + 1];
74
- if (!value || !/^\d+$/.test(value)) {
75
- fail(`Invalid value for --port: ${value ?? "<empty>"}`);
76
- }
77
- return parseIntArg(value, 4040);
78
- }
79
- }
80
- return void 0;
81
- }
82
67
  async function startDevFrontend(apiPort, devPort) {
83
68
  const VITE_CONFIG_PATH = resolve(PACKAGE_ROOT, "app/vite.config.js");
84
69
  let createViteServer;
@@ -150,6 +135,22 @@ async function startDevFrontend(apiPort, devPort) {
150
135
  logger.warn(`Failed to start Vite dev server: ${String(error)}`);
151
136
  }
152
137
  }
138
+
139
+ // src/boot.ts
140
+ import { join } from "path";
141
+ function parsePort(args) {
142
+ for (let i = 0; i < args.length; i += 1) {
143
+ const arg = args[i];
144
+ if (arg === "--port") {
145
+ const value = args[i + 1];
146
+ if (!value || !/^\d+$/.test(value)) {
147
+ fail(`Invalid value for --port: ${value ?? "<empty>"}`);
148
+ }
149
+ return parseIntArg(value, 4040);
150
+ }
151
+ }
152
+ return void 0;
153
+ }
153
154
  function usage() {
154
155
  console.log(
155
156
  `Usage: ${argv[1]} [options]
@@ -258,37 +259,23 @@ async function main() {
258
259
  state.config.dashboardPort = dashboardPort ? String(dashboardPort) : void 0;
259
260
  state.updatedAt = now();
260
261
  state.booting = false;
261
- try {
262
- const { getIssueStateMachinePlugin, ISSUE_STATE_MACHINE_ID } = await import("../issue-state-machine-OWABY5S2.js");
263
- const fsmPlugin = getIssueStateMachinePlugin();
264
- if (fsmPlugin?.getState) {
265
- for (const issue of state.issues) {
266
- try {
267
- const fsmState = await fsmPlugin.getState(ISSUE_STATE_MACHINE_ID, issue.id);
268
- if (fsmState && fsmState !== issue.state) {
269
- logger.warn({ issueId: issue.id, memoryState: issue.state, fsmState }, "[Boot] Reconciling desync \u2014 FSM is source of truth");
270
- issue.state = fsmState;
271
- }
272
- } catch {
273
- }
274
- }
275
- }
276
- } catch {
277
- }
278
262
  if (!state.config.defaultBranch) {
279
263
  try {
280
- const detectedBranch = detectDefaultBranch(TARGET_ROOT);
281
- state.config.defaultBranch = detectedBranch;
282
- logger.info({ defaultBranch: detectedBranch }, "[Agent] Default branch detected");
264
+ state.config.defaultBranch = detectDefaultBranch(TARGET_ROOT);
265
+ logger.info({ defaultBranch: state.config.defaultBranch }, "[Boot] Default branch detected");
283
266
  } catch {
284
267
  }
285
268
  }
286
- if (state.config.agentCommand) {
287
- state.notes.push(`Using agent command: ${state.config.agentCommand}`);
269
+ if (!state.config.testCommand) {
270
+ try {
271
+ const pkg = JSON.parse(readFileSync(join(TARGET_ROOT, "package.json"), "utf8"));
272
+ if (pkg?.scripts?.test && !pkg.scripts.test.includes("no test specified")) {
273
+ state.config.testCommand = "pnpm test";
274
+ logger.info({ testCommand: state.config.testCommand }, "[Boot] Test command auto-detected");
275
+ }
276
+ } catch {
277
+ }
288
278
  }
289
- state.notes.push(`Agent session max turns: ${state.config.maxTurns}`);
290
- state.notes.push(`Agent provider: ${state.config.agentProvider}`);
291
- state.notes.push(`Interface mode: ${interfaceMode}`);
292
279
  if (!state.config.agentCommand.trim()) {
293
280
  const available = detectedProviders.filter((p) => p.available).map((p) => p.name);
294
281
  fail(
@@ -299,48 +286,8 @@ async function main() {
299
286
  if (configErrors.length > 0) {
300
287
  for (const err of configErrors) logger.warn(`Config validation: ${err}`);
301
288
  }
302
- const terminalIssues = state.issues.filter((i) => i.state === "Merged" || i.state === "Cancelled");
303
- if (terminalIssues.length > 0) {
304
- logger.info(`Scheduling cleanup of ${terminalIssues.length} terminal workspace(s) in background...`);
305
- setImmediate(async () => {
306
- for (const issue of terminalIssues) {
307
- try {
308
- await cleanWorkspace(issue.id, issue, state);
309
- } catch {
310
- }
311
- }
312
- logger.info("Background workspace cleanup complete.");
313
- });
314
- }
315
- if (!skipRecovery) {
316
- logger.debug({ issueCount: state.issues.filter((i) => i.state === "Running" || i.state === "Queued").length }, "[Boot] Checking for orphaned agent processes");
317
- for (const issue of state.issues) {
318
- if (issue.state === "Running" || issue.state === "Queued") {
319
- const { alive, pid } = isAgentStillRunning(issue);
320
- if (alive && pid) {
321
- logger.info(`Agent for ${issue.identifier} still alive (PID ${pid.pid}), keeping state as Running.`);
322
- if (issue.state !== "Running") {
323
- try {
324
- await executeTransition(issue, "RUN", { issue, note: `Orphaned agent detected (PID ${pid.pid}), still alive \u2014 tracking resumed.` });
325
- } catch {
326
- issue.state = "Running";
327
- }
328
- }
329
- addEvent(state, issue.id, "info", `Orphaned agent detected (PID ${pid.pid}), still alive \u2014 tracking resumed.`);
330
- } else {
331
- if (issue.workspacePath) cleanStalePidFile(issue.workspacePath);
332
- if (issue.state === "Running") {
333
- try {
334
- await executeTransition(issue, "REQUEUE", { issue, note: `Agent process not found on boot \u2014 marked Queued.` });
335
- } catch {
336
- issue.state = "Queued";
337
- }
338
- addEvent(state, issue.id, "info", `Agent for ${issue.identifier} not found, marked Queued.`);
339
- }
340
- }
341
- }
342
- }
343
- }
289
+ cleanTerminalWorkspaces();
290
+ if (!skipRecovery) await recoverOrphans();
344
291
  state.metrics = computeMetrics(state.issues);
345
292
  if (dashboardPort) {
346
293
  Object.assign(apiState, state);
@@ -354,8 +301,7 @@ async function main() {
354
301
  } catch (error) {
355
302
  logger.warn({ err: error }, "[Boot] Queue workers failed to initialize \u2014 continuing without queue-based dispatch");
356
303
  }
357
- const running = /* @__PURE__ */ new Set();
358
- installGracefulShutdown(state, running);
304
+ installGracefulShutdown(state);
359
305
  logger.info("[Boot] Runtime ready");
360
306
  hydrate(state.issues);
361
307
  logger.info(`Loaded issues: ${state.issues.length}`);
@@ -367,47 +313,14 @@ async function main() {
367
313
  try {
368
314
  addEvent(state, void 0, "info", `Runtime started in local-only mode (filesystem tracker).`);
369
315
  const runForever = !runOnce && (Boolean(dashboardPort) || interfaceMode === "mcp");
370
- logger.info({ runForever, runOnce, dashboardPort, interfaceMode }, "[Boot] Entering queue supervisor loop");
371
- for (const issue of state.issues) {
372
- try {
373
- if (issue.state === "Planning" && issue.planningStatus !== "planning") {
374
- await enqueueForPlanning(issue);
375
- } else if (issue.state === "Queued" || issue.state === "Running") {
376
- await enqueueForExecution(issue);
377
- } else if (issue.state === "Reviewing") {
378
- await enqueueForReview(issue);
379
- }
380
- } catch (err) {
381
- logger.error({ err, issueId: issue.id, state: issue.state }, "[Boot] Failed to enqueue issue for recovery");
382
- }
383
- }
384
- const PERSIST_DEBOUNCE_MS = 5e3;
385
- let lastPersistAt = 0;
316
+ logger.info({ runForever, runOnce, dashboardPort, interfaceMode }, "[Boot] Queue-driven dispatch active");
317
+ await recoverState();
386
318
  if (runForever) {
387
- while (!isShuttingDown()) {
388
- const statesBefore = new Map(state.issues.map((i) => [i.id, i.state]));
389
- await ensureNotStale(state, state.config.staleInProgressTimeoutMs);
390
- for (const issue of state.issues) {
391
- const prev = statesBefore.get(issue.id);
392
- if (prev !== issue.state) {
393
- if (issue.state === "Queued") enqueueForExecution(issue).catch(() => {
394
- });
395
- else if (issue.state === "Reviewing") enqueueForReview(issue).catch(() => {
396
- });
397
- else if (issue.state === "Planning") enqueueForPlanning(issue).catch(() => {
398
- });
399
- }
400
- }
401
- state.updatedAt = now();
402
- if (hasDirtyState() || Date.now() - lastPersistAt > PERSIST_DEBOUNCE_MS) {
403
- await persistState(state);
404
- lastPersistAt = Date.now();
405
- }
406
- await sleep(1e3);
407
- }
319
+ await new Promise(() => {
320
+ });
408
321
  } else {
409
322
  while (!hasTerminalQueue(state)) {
410
- await sleep(state.config.pollIntervalMs);
323
+ await new Promise((r) => setTimeout(r, state.config.pollIntervalMs));
411
324
  }
412
325
  }
413
326
  } catch (error) {
@@ -0,0 +1,74 @@
1
+ import {
2
+ addTokenUsage,
3
+ cleanStalePidFile,
4
+ extractTokenUsage,
5
+ isAgentStillRunning,
6
+ isProcessAlive,
7
+ issueHasResumableSession,
8
+ loadAgentPipelineSnapshotForIssue,
9
+ loadAgentPipelineState,
10
+ loadAgentSessionSnapshotsForIssue,
11
+ readAgentDirective,
12
+ readAgentPid,
13
+ runAgentPipeline,
14
+ runAgentSession,
15
+ runIssueOnce,
16
+ runPlanningJob,
17
+ tryParseJsonOutput
18
+ } from "./chunk-HSGUPFTV.js";
19
+ import "./chunk-FJR4ALEN.js";
20
+ import {
21
+ buildPrompt,
22
+ buildProviderBasePrompt,
23
+ buildTurnPrompt,
24
+ cleanWorkspace,
25
+ computeDiffStats,
26
+ createGitWorktree,
27
+ ensureWorktreeCommitted,
28
+ hydrateIssuePathsFromWorkspace,
29
+ inferChangedWorkspacePaths,
30
+ mergeWorkspace,
31
+ parseDiffStats,
32
+ prepareWorkspace,
33
+ runCommandWithTimeout,
34
+ runHook,
35
+ shouldSkipMergePath
36
+ } from "./chunk-UYCDOH6S.js";
37
+ import "./chunk-O5AEQXUV.js";
38
+ import "./chunk-XENKNHFS.js";
39
+ import "./chunk-DVU3CXWA.js";
40
+ import "./chunk-OONOOWNC.js";
41
+ export {
42
+ addTokenUsage,
43
+ buildPrompt,
44
+ buildProviderBasePrompt,
45
+ buildTurnPrompt,
46
+ cleanStalePidFile,
47
+ cleanWorkspace,
48
+ computeDiffStats,
49
+ createGitWorktree,
50
+ ensureWorktreeCommitted,
51
+ extractTokenUsage,
52
+ hydrateIssuePathsFromWorkspace,
53
+ inferChangedWorkspacePaths,
54
+ isAgentStillRunning,
55
+ isProcessAlive,
56
+ issueHasResumableSession,
57
+ loadAgentPipelineSnapshotForIssue,
58
+ loadAgentPipelineState,
59
+ loadAgentSessionSnapshotsForIssue,
60
+ mergeWorkspace,
61
+ parseDiffStats,
62
+ prepareWorkspace,
63
+ readAgentDirective,
64
+ readAgentPid,
65
+ runAgentPipeline,
66
+ runAgentSession,
67
+ runCommandWithTimeout,
68
+ runHook,
69
+ runIssueOnce,
70
+ runPlanningJob,
71
+ shouldSkipMergePath,
72
+ tryParseJsonOutput
73
+ };
74
+ //# sourceMappingURL=agent-KMXNVDRO.js.map