mainflow 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { $ as setFindingStatus, A as addAction, C as setCriterionText, D as updateTask, E as supersedeDecision, F as setSessionArchived, J as createFinding, K as appendOps, L as setSessionStatus, M as handoffSession, O as sessionBriefing, P as readSession, Q as setFindingArchived, S as setCriterion, V as updateAction, X as planIssue, Y as createIssue, Z as reopenIssue, _ as createTask, b as setArchived, ct as TASK_FILE, et as setIssueArchived, f as acceptDecision, g as createMainline, h as createDecision, l as migrateHub, m as addRepo, nt as loadHub, p as addHub, pt as findHubRoot, q as closeIssue, st as MAINLINE_FILE, tt as HubError, ut as WriteError, v as dropChecklistItem, w as setMainlineStatus, x as setChecklistItem, y as initHub, z as startSession } from "./host-PrRNECbf.js";
2
+ import { $ as setFindingStatus, A as addAction, C as setCriterionText, D as updateTask, E as supersedeDecision, F as setSessionArchived, J as createFinding, K as appendOps, L as setSessionStatus, M as handoffSession, O as sessionBriefing, P as readSession, Q as setFindingArchived, S as setCriterion, V as updateAction, X as planIssue, Y as createIssue, Z as reopenIssue, _ as createTask, b as setArchived, ct as TASK_FILE, et as setIssueArchived, f as acceptDecision, g as createMainline, h as createDecision, l as migrateHub, m as addRepo, nt as loadHub, p as addHub, pt as findHubRoot, q as closeIssue, st as MAINLINE_FILE, tt as HubError, ut as WriteError, v as dropChecklistItem, w as setMainlineStatus, x as setChecklistItem, y as initHub, z as startSession } from "./host-CKtr4Wu3.js";
3
3
  import { N as parseRef, P as refExample } from "./dist-BQmXEfAf.js";
4
4
  import { t as listProgress } from "./progress-1BfPg2zN.js";
5
5
  import { COMMAND_SPECS, OPTIONS } from "./facts.js";
6
6
  import { runHook } from "./hooks.js";
7
- import { l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-CAsUTVOc.js";
7
+ import { l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-BCgTLATl.js";
8
8
  import { readFileSync, realpathSync } from "node:fs";
9
9
  import { join, relative } from "node:path";
10
10
  import { fileURLToPath } from "node:url";
package/dist/hooks.js CHANGED
@@ -1,4 +1,4 @@
1
- import { G as mayDecorate, H as decorateReply, I as setSessionInfo, L as setSessionStatus, O as sessionBriefing, P as readSession, R as settleSession, U as endsWithMarker, W as headerLine, dt as DATA_DIR, ft as currentBranch, i as hostName, j as ensureSession, k as turnReminder, mt as worktreesOf, nt as loadHub, pt as findHubRoot, tt as HubError } from "./host-PrRNECbf.js";
1
+ import { G as mayDecorate, H as decorateReply, I as setSessionInfo, L as setSessionStatus, O as sessionBriefing, P as readSession, R as settleSession, U as endsWithMarker, W as headerLine, dt as DATA_DIR, ft as currentBranch, i as hostName, j as ensureSession, k as turnReminder, mt as worktreesOf, nt as loadHub, pt as findHubRoot, tt as HubError } from "./host-CKtr4Wu3.js";
2
2
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
3
3
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  //#region src/hooks.ts
@@ -1343,27 +1343,29 @@ function setSessionStatus(root, id, status) {
1343
1343
  }
1344
1344
  /**
1345
1345
  * Settle a session when its turn ends. A session that tracked no action, and whose subagents tracked none, leaves
1346
- * no record, since nothing in it points at the hub's work. An active session whose actions are all done or dropped
1347
- * and whose subagents have all stopped ends. The next prompt or action brings it back.
1346
+ * no record, since nothing in it points at the hub's work. Then every active main session with no action left to
1347
+ * do and no subagent still running ends, the others as well as this one: another session may have finished its
1348
+ * last action, or it was closed before its own turn could settle it. The next prompt or action brings it back.
1348
1349
  */
1349
1350
  function settleSession(root, id) {
1350
1351
  return withLock(root, () => {
1351
- const session = readSession(root, id);
1352
- if (!session) return "kept";
1353
1352
  const { sessions } = loadSessions(root);
1354
1353
  const subagents = (parent) => sessions.filter((s) => s.delegatedFrom === parent).flatMap((s) => [s, ...subagents(s.id)]);
1355
- const family = [session, ...subagents(id)];
1356
- if (family.every((s) => s.actions.length === 0)) {
1357
- for (const s of family) rmSync(sessionFile(root, s.id), { force: true });
1358
- return "removed";
1354
+ const family = sessions.some((s) => s.id === id) ? [sessions.find((s) => s.id === id), ...subagents(id)] : [];
1355
+ const removed = family.length > 0 && family.every((s) => s.actions.length === 0);
1356
+ if (removed) for (const s of family) rmSync(sessionFile(root, s.id), { force: true });
1357
+ let result = removed ? "removed" : "kept";
1358
+ for (const s of sessions) {
1359
+ if (s.status !== "active" || s.delegatedFrom || removed && s.id === id) continue;
1360
+ if (!s.actions.every((a) => a.status === "done" || a.status === "dropped") || subagents(s.id).some((x) => x.status === "active")) continue;
1361
+ if (s.id === id && s.actions.length === 0) continue;
1362
+ writeAtomic(sessionFile(root, s.id), toYaml(validate(sessionSchema, {
1363
+ ...s,
1364
+ status: "ended"
1365
+ }, sessionFile(root, s.id))));
1366
+ if (s.id === id) result = "ended";
1359
1367
  }
1360
- const finished = session.actions.length > 0 && session.actions.every((a) => a.status === "done" || a.status === "dropped");
1361
- if (session.status !== "active" || !finished || family.slice(1).some((s) => s.status === "active")) return "kept";
1362
- writeAtomic(sessionFile(root, id), toYaml(validate(sessionSchema, {
1363
- ...session,
1364
- status: "ended"
1365
- }, sessionFile(root, id))));
1366
- return "ended";
1368
+ return result;
1367
1369
  });
1368
1370
  }
1369
1371
  /** Archive or unarchive a session; the status stays as it is, so an ended session is visible until archived. */
package/dist/host.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as openInApp, c as syncHost, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, r as caddySites, s as siteBlock, t as APP_BUNDLE_ID } from "./host-PrRNECbf.js";
1
+ import { a as openInApp, c as syncHost, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, r as caddySites, s as siteBlock, t as APP_BUNDLE_ID } from "./host-CKtr4Wu3.js";
2
2
  export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, removeHostLink, siteBlock, syncHost };
@@ -1,4 +1,4 @@
1
- import { c as syncHost, dt as DATA_DIR, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, ut as WriteError } from "./host-PrRNECbf.js";
1
+ import { c as syncHost, dt as DATA_DIR, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, ut as WriteError } from "./host-CKtr4Wu3.js";
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { spawn, spawnSync } from "node:child_process";
@@ -176,7 +176,7 @@ async function launchUi(root, hub, configured, options) {
176
176
  }
177
177
  let server;
178
178
  if (!reuse) {
179
- const { serveUi } = await import("./ui-DKH8q5oP.js");
179
+ const { serveUi } = await import("./ui-DuY6LtfH.js");
180
180
  server = await serveUi(root, choice.port);
181
181
  writeUiRecord(root, {
182
182
  port: choice.port,
package/dist/launch.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as portCandidates, c as watchHubGone, i as networkProbe, n as choosePort, o as readUiRecord, r as launchUi, s as startUiInBackground, t as PORT_SPAN } from "./launch-CAsUTVOc.js";
1
+ import { a as portCandidates, c as watchHubGone, i as networkProbe, n as choosePort, o as readUiRecord, r as launchUi, s as startUiInBackground, t as PORT_SPAN } from "./launch-BCgTLATl.js";
2
2
  export { PORT_SPAN, choosePort, launchUi, networkProbe, portCandidates, readUiRecord, startUiInBackground, watchHubGone };
@@ -1,6 +1,6 @@
1
- import { B as transcriptPath, D as updateTask, F as setSessionArchived, N as loadSessions, P as readSession, Q as setFindingArchived, S as setCriterion, T as setMainlineTitle, a as openInApp, at as linksInto, b as setArchived, d as setArchivedMany, dt as DATA_DIR, et as setIssueArchived, it as mainlineEdges, lt as ConflictError, nt as loadHub, ot as refIndex, rt as dependencyGraph, u as ARCHIVE_KINDS, ut as WriteError, w as setMainlineStatus, x as setChecklistItem } from "./host-PrRNECbf.js";
1
+ import { B as transcriptPath, D as updateTask, F as setSessionArchived, N as loadSessions, P as readSession, Q as setFindingArchived, S as setCriterion, T as setMainlineTitle, a as openInApp, at as linksInto, b as setArchived, d as setArchivedMany, dt as DATA_DIR, et as setIssueArchived, it as mainlineEdges, lt as ConflictError, nt as loadHub, ot as refIndex, rt as dependencyGraph, u as ARCHIVE_KINDS, ut as WriteError, w as setMainlineStatus, x as setChecklistItem } from "./host-CKtr4Wu3.js";
2
2
  import { t as listProgress } from "./progress-1BfPg2zN.js";
3
- import { l as CLI_VERSION } from "./launch-CAsUTVOc.js";
3
+ import { l as CLI_VERSION } from "./launch-BCgTLATl.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { closeSync, existsSync, openSync, readFileSync, readSync, statSync, watch } from "node:fs";
6
6
  import { basename, dirname, extname, join, normalize, relative, sep } from "node:path";
@@ -135,8 +135,9 @@ function readTail(file, bytes) {
135
135
  function latestTitle(text) {
136
136
  let custom;
137
137
  let agent;
138
+ let ai;
138
139
  for (const line of text.split("\n")) {
139
- if (!line.includes("\"custom-title\"") && !line.includes("\"agent-name\"")) continue;
140
+ if (!line.includes("\"custom-title\"") && !line.includes("\"agent-name\"") && !line.includes("\"ai-title\"")) continue;
140
141
  let record;
141
142
  try {
142
143
  record = JSON.parse(line);
@@ -145,12 +146,13 @@ function latestTitle(text) {
145
146
  }
146
147
  if (record.type === "custom-title" && record.customTitle?.trim()) custom = record.customTitle.trim();
147
148
  if (record.type === "agent-name" && record.agentName?.trim()) agent = record.agentName.trim();
149
+ if (record.type === "ai-title" && record.aiTitle?.trim()) ai = record.aiTitle.trim();
148
150
  }
149
- return custom ?? agent;
151
+ return custom ?? agent ?? ai;
150
152
  }
151
153
  /**
152
154
  * The name the conversation goes by: the latest title the user gave it, else the latest name the platform
153
- * generated. Only the end of the file is read unless it holds no title.
155
+ * gave the session, else the latest title the platform generated from the conversation. Only the end of the file is read unless it holds no title.
154
156
  */
155
157
  function transcriptTitle(file) {
156
158
  if (!existsSync(file)) return void 0;