mainflow 0.36.0 → 0.37.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,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { G as parseRef, K as parseUntil, N as UNTIL_FORMS, et as stampMs, n as CLOSED_STATUS, q as refExample } from "./dist-ud09dzZo.js";
3
- import { $ as nowMinute, B as applyOperation, C as readSession, H as HubError, Q as unavailableHubs, S as loadSessions, V as checkHubName, W as loadHub, Y as memberOfGroup, Z as remoteMembers, _ as initHub, _t as findHubRoot, at as MAX_FILE_BYTES, b as sessionBriefing, bt as DATA_DIR, d as retroReport, f as retroReportFromReceiver, ht as requireSlug, m as RETRY_RULES, mt as TASK_FILE, p as receiverFromEnv, pt as MAINLINE_FILE, tt as nodeStorage, u as migrateHub, v as untilState, xt as WriteError, y as duplicateClaimLines } from "./host-BauijAdm.js";
3
+ import { $ as nowMinute, B as applyOperation, C as readSession, Ct as WriteError, H as HubError, Q as unavailableHubs, S as loadSessions, St as DATA_DIR, V as checkHubName, W as loadHub, Y as memberOfGroup, Z as remoteMembers, _ as initHub, _t as requireSlug, at as MAX_FILE_BYTES, b as sessionBriefing, d as retroReport, f as retroReportFromReceiver, gt as TASK_FILE, ht as MAINLINE_FILE, m as RETRY_RULES, p as receiverFromEnv, tt as nodeStorage, u as migrateHub, v as untilState, y as duplicateClaimLines, yt as findHubRoot } from "./host-lY8ytTbw.js";
4
4
  import { t as listProgress } from "./progress-1BfPg2zN.js";
5
- import { C as ServerError, D as syncSettings, E as hubName, O as SETTINGS_FILE, S as ServerApi, T as earlierToken, _ as readDaemon, a as remoteMode, b as readRemote, c as planAnnounce, d as toolCallOf, f as startDaemon, g as probeDaemon, h as callDaemon, i as queuedCount, j as syncPaths, l as planFetch, m as DaemonUnavailable, n as hubWriter, o as fetchDenial, p as DaemonRunning, r as writtenLines, s as hookAnswer, t as CONFIRM_MS, u as planFlush, v as silentHint, w as ENV, x as oversizedFiles } from "./operation-DGRH4iBE.js";
5
+ import { C as ServerError, D as syncSettings, E as hubName, O as SETTINGS_FILE, S as ServerApi, T as earlierToken, _ as readDaemon, a as remoteMode, b as readRemote, c as planAnnounce, d as toolCallOf, f as startDaemon, g as probeDaemon, h as callDaemon, i as queuedCount, j as syncPaths, l as planFetch, m as DaemonUnavailable, n as hubWriter, o as fetchDenial, p as DaemonRunning, r as writtenLines, s as hookAnswer, t as CONFIRM_MS, u as planFlush, v as silentHint, w as ENV, x as oversizedFiles } from "./operation-BZ7CHB6J.js";
6
6
  import { COMMAND_SPECS, OPTIONS } from "./facts.js";
7
7
  import { hookFallback, parsePayload, runHook } from "./hooks.js";
8
- import { f as CLI_VERSION, i as launchUi, l as startUiInBackground, r as exitCodeFor, u as watchHubGone } from "./launch-n2ZDF0BF.js";
8
+ import { f as CLI_VERSION, i as launchUi, l as startUiInBackground, r as exitCodeFor, u as watchHubGone } from "./launch-3HLHjQF0.js";
9
9
  import { randomBytes } from "node:crypto";
10
10
  import { existsSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
11
11
  import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
package/dist/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { F as configSchema, it as describeRequest } from "./dist-ud09dzZo.js";
2
- import { A as mayDecorate, C as readSession, D as decorateReply, E as matchGrants, H as HubError, O as endsWithMarker, S as loadSessions, T as grantScope, W as loadHub, _t as findHubRoot, b as sessionBriefing, bt as DATA_DIR, et as readYaml, gt as currentBranch, i as hostName, k as headerLine, vt as worktreesOf, x as turnReminder } from "./host-BauijAdm.js";
3
- import { n as hubWriter, r as writtenLines } from "./operation-DGRH4iBE.js";
2
+ import { A as mayDecorate, C as readSession, D as decorateReply, E as matchGrants, H as HubError, O as endsWithMarker, S as loadSessions, St as DATA_DIR, T as grantScope, W as loadHub, b as sessionBriefing, bt as worktreesOf, et as readYaml, i as hostName, k as headerLine, mt as hubFormatVersion, pt as formatMismatch, tt as nodeStorage, vt as currentBranch, x as turnReminder, yt as findHubRoot } from "./host-lY8ytTbw.js";
3
+ import { n as hubWriter, r as writtenLines } from "./operation-BZ7CHB6J.js";
4
4
  import { resolveFixed, scanCommand, scopedCwd } from "./grant-commands.js";
5
5
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
6
6
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
@@ -425,6 +425,18 @@ const PROJECT_HUB_EVENTS = /* @__PURE__ */ new Set(["pre-tool-use"]);
425
425
  function hubRootFor(event, ctx) {
426
426
  return (PROJECT_HUB_EVENTS.has(event) && ctx.projectDir && isAbsolute(ctx.projectDir) ? findHubRoot(ctx.projectDir) : null) ?? findHubRoot(typeof ctx.payload.cwd === "string" ? ctx.payload.cwd : process.cwd());
427
427
  }
428
+ /** Events whose output reaches the model before it works, so they carry the notice that the hub's data format does not match this CLI. */
429
+ const FORMAT_NOTICE_EVENTS = /* @__PURE__ */ new Set(["session-start", "user-prompt-submit"]);
430
+ /** What the model is told when the hub's data format is not the one this CLI reads and writes; null when it is. */
431
+ function formatNotice(root, cli) {
432
+ const found = hubFormatVersion(nodeStorage(root));
433
+ const reason = found === null ? null : formatMismatch(found);
434
+ if (found === null || reason === null) return null;
435
+ return {
436
+ text: found < 3 ? `[mainflow] 這個 hub 的資料格式是 ${found},這版 mainflow 讀寫的是 3,要先跑 ${cli} migrate 才能讀寫紀錄。` : `[mainflow] 這個 hub 的資料格式是 ${found},比這版 mainflow 讀寫的 3 新,要先在這個 hub 安裝對應版本的 mainflow 才能讀寫紀錄。`,
437
+ reason
438
+ };
439
+ }
428
440
  /** What an event prints when it cannot run its handler; null for the events that stay silent. */
429
441
  function hookFallback(platform, event, ctx, failure) {
430
442
  const fallback = HOOK_FALLBACKS[platform]?.[event];
@@ -461,6 +473,11 @@ async function runHook(platform, event, ctx) {
461
473
  for (const line of writtenLines(written)) if (line.startsWith("!")) warn(`mainflow hook ${platform} ${event}: ${line.slice(2)}`);
462
474
  return written;
463
475
  };
476
+ const notice = FORMAT_NOTICE_EVENTS.has(event) ? formatNotice(root, ctx.cli) : null;
477
+ if (notice) return {
478
+ stdout: notice.text,
479
+ error: errorText(`mainflow hook ${platform} ${event}: ${notice.reason}`)
480
+ };
464
481
  return {
465
482
  stdout: await handler(root, {
466
483
  ...ctx,
@@ -137,6 +137,91 @@ const offlineIds = {
137
137
  next: (request) => fresh(request, true)
138
138
  };
139
139
  //#endregion
140
+ //#region ../core/dist/ops/unknown.js
141
+ const isPlain = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
142
+ const idOf = (value) => isPlain(value) && typeof value.id === "string" ? value.id : void 0;
143
+ /** Keys that would reach the prototype instead of the data when assigned. */
144
+ const UNSAFE_KEYS = /* @__PURE__ */ new Set([
145
+ "__proto__",
146
+ "constructor",
147
+ "prototype"
148
+ ]);
149
+ function diff(raw, parsed) {
150
+ if (isPlain(raw) && isPlain(parsed)) {
151
+ const fields = /* @__PURE__ */ new Map();
152
+ for (const [key, value] of Object.entries(raw)) if (!Object.hasOwn(parsed, key)) fields.set(key, {
153
+ kind: "value",
154
+ value
155
+ });
156
+ else {
157
+ const inner = diff(value, parsed[key]);
158
+ if (inner) fields.set(key, inner);
159
+ }
160
+ return fields.size > 0 ? {
161
+ kind: "object",
162
+ fields
163
+ } : void 0;
164
+ }
165
+ if (Array.isArray(raw) && Array.isArray(parsed)) {
166
+ const counts = /* @__PURE__ */ new Map();
167
+ for (const element of raw) {
168
+ const id = idOf(element);
169
+ if (id !== void 0) counts.set(id, (counts.get(id) ?? 0) + 1);
170
+ }
171
+ const byId = /* @__PURE__ */ new Map();
172
+ for (const element of raw) {
173
+ const id = idOf(element);
174
+ if (id === void 0 || counts.get(id) !== 1) continue;
175
+ const matches = parsed.filter((p) => idOf(p) === id);
176
+ if (matches.length !== 1) continue;
177
+ const inner = diff(element, matches[0]);
178
+ if (inner) byId.set(id, inner);
179
+ }
180
+ return byId.size > 0 ? {
181
+ kind: "array",
182
+ byId
183
+ } : void 0;
184
+ }
185
+ }
186
+ /** The parts of `raw`, as it was read, that validation left out of `parsed`; undefined when nothing was dropped. */
187
+ function strippedOf(raw, parsed) {
188
+ return diff(raw, parsed);
189
+ }
190
+ function put(target, stripped) {
191
+ if (stripped.kind === "object" && isPlain(target)) for (const [key, inner] of stripped.fields) {
192
+ if (UNSAFE_KEYS.has(key)) {
193
+ if (inner.kind === "value" && !Object.hasOwn(target, key)) Object.defineProperty(target, key, {
194
+ value: structuredClone(inner.value),
195
+ enumerable: true,
196
+ writable: true,
197
+ configurable: true
198
+ });
199
+ continue;
200
+ }
201
+ if (inner.kind === "value") {
202
+ if (!Object.hasOwn(target, key)) target[key] = structuredClone(inner.value);
203
+ } else if (Object.hasOwn(target, key)) put(target[key], inner);
204
+ }
205
+ else if (stripped.kind === "array" && Array.isArray(target)) {
206
+ const counts = /* @__PURE__ */ new Map();
207
+ for (const element of target) {
208
+ const id = idOf(element);
209
+ if (id !== void 0) counts.set(id, (counts.get(id) ?? 0) + 1);
210
+ }
211
+ for (const element of target) {
212
+ const id = idOf(element);
213
+ const inner = id === void 0 || counts.get(id) !== 1 ? void 0 : stripped.byId.get(id);
214
+ if (inner) put(element, inner);
215
+ }
216
+ }
217
+ }
218
+ /** A copy of `next` with the stripped parts put back where the data has no value of its own. */
219
+ function graft(next, stripped) {
220
+ const copy = structuredClone(next);
221
+ if (stripped) put(copy, stripped);
222
+ return copy;
223
+ }
224
+ //#endregion
140
225
  //#region ../core/dist/ops/draft.js
141
226
  const normalize$1 = (path) => path.split("/").filter(Boolean).join("/");
142
227
  const parentOf = (path) => normalize$1(path).split("/").slice(0, -1).join("/");
@@ -263,7 +348,11 @@ function commit(storage, changes) {
263
348
  case "remove": storage.remove(change.path);
264
349
  }
265
350
  }
266
- /** Run an operation on the hub as it is under the lock and apply its changes before the lock is released. */
351
+ /**
352
+ * Run an operation on the hub as it is under the lock and apply its changes before the lock is released. It does not
353
+ * check the hub's data format: migrate must write a hub of another format, and the sync server's text patches
354
+ * keep every field. The entries for operations (`runOp`, `applyOperation`) check it before they call this.
355
+ */
267
356
  function applyOp(storage, run) {
268
357
  return storage.lock(() => {
269
358
  const result = run(storage);
@@ -288,14 +377,20 @@ function readYamlIn(hub, path, schema) {
288
377
  function readFrontMatterIn(hub, path, schema) {
289
378
  return validate(schema, splitFrontMatter(requireText(hub, path)).data, hub.where(path));
290
379
  }
380
+ /** `next` with the fields the YAML document at `path` has beyond its schema put back; `current` is that document as validated. */
381
+ function yamlKeeping(hub, path, current, next) {
382
+ return graft(next, strippedOf(parse$1(requireText(hub, path)), current));
383
+ }
291
384
  /** Mutate, validate and stage a YAML document; `expectedVersion` refuses the change when the file moved on. */
292
385
  function editYaml(draft, path, schema, mutate, expectedVersion) {
293
386
  const text = requireText(draft, path);
294
387
  checkVersion(draft, path, text, expectedVersion);
295
- const data = validate(schema, parse$1(text), draft.where(path));
388
+ const raw = parse$1(text);
389
+ const data = validate(schema, raw, draft.where(path));
390
+ const stripped = strippedOf(raw, data);
296
391
  mutate(data);
297
392
  const next = validate(schema, data, draft.where(path));
298
- draft.write(path, toYaml(next));
393
+ draft.write(path, toYaml(graft(next, stripped)));
299
394
  return next;
300
395
  }
301
396
  /** Mutate, validate and stage the front matter of a Markdown document; the body is kept unless `mutate` returns a new one. */
@@ -304,9 +399,10 @@ function editFrontMatter(draft, path, schema, mutate, expectedVersion) {
304
399
  checkVersion(draft, path, text, expectedVersion);
305
400
  const { data, body } = splitFrontMatter(text);
306
401
  const current = validate(schema, data, draft.where(path));
402
+ const stripped = strippedOf(data, current);
307
403
  const nextBody = mutate(current, body) ?? body;
308
404
  const next = validate(schema, current, draft.where(path));
309
- draft.write(path, frontMatterText(next, nextBody));
405
+ draft.write(path, frontMatterText(graft(next, stripped), nextBody));
310
406
  return next;
311
407
  }
312
408
  //#endregion
@@ -364,6 +460,40 @@ function decisionFileIn(hub, mainline, decision) {
364
460
  }
365
461
  const sessionFileIn = (id) => `${SESSIONS_DIR}/${id}.yaml`;
366
462
  //#endregion
463
+ //#region ../core/dist/ops/format.js
464
+ /** Why a hub whose data format is `found` cannot be written by this CLI; null when it can. */
465
+ function formatMismatch(found) {
466
+ if (found === 3) return null;
467
+ return found < 3 ? `data format version ${found} is older than this CLI's (3); run "mainflow migrate --dry-run" to preview the conversion, then "mainflow migrate"` : `data format version ${found} is newer than this CLI supports (3); install the matching mainflow version in this hub`;
468
+ }
469
+ /**
470
+ * The data format config.yaml declares; null when the hub has no config.yaml or it names no number, which loading
471
+ * the config reports. A config.yaml that is not YAML is a WriteError, so the sync server refuses the request
472
+ * instead of failing on it.
473
+ */
474
+ function hubFormatVersion(hub) {
475
+ const text = hub.read(CONFIG_FILE);
476
+ if (text === null) return null;
477
+ let data;
478
+ try {
479
+ data = parse$1(text);
480
+ } catch (error) {
481
+ throw new WriteError(`refusing to write: ${hub.where(CONFIG_FILE)} cannot be parsed as YAML: ${error.message}`);
482
+ }
483
+ const found = data?.formatVersion;
484
+ return typeof found === "number" ? found : null;
485
+ }
486
+ /**
487
+ * Refuse a write to a hub whose data format is not the one this CLI writes: rewriting a document would drop what
488
+ * another format keeps there. A hub without config.yaml is not checked, since `init` writes it.
489
+ */
490
+ function requireWritableFormat(hub) {
491
+ const found = hubFormatVersion(hub);
492
+ if (found === null) return;
493
+ const reason = formatMismatch(found);
494
+ if (reason) throw new WriteError(`refusing to write: ${reason}`);
495
+ }
496
+ //#endregion
367
497
  //#region ../core/dist/ops/protocol.js
368
498
  /** `now` of a request: a local minute and its offset from UTC, `Z` for UTC itself. */
369
499
  const REQUEST_TIME = new RegExp(`^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})(${OFFSET})$`);
@@ -584,7 +714,10 @@ const localContext = () => ({ now: nowMinute() });
584
714
  /** Run an operation on the hub at `root` under its write lock, apply its changes and return what it reports. */
585
715
  function runOp(root, run) {
586
716
  const ctx = localContext();
587
- return applyOp(nodeStorage(root), (hub) => run(hub, ctx)).value;
717
+ return applyOp(nodeStorage(root), (hub) => {
718
+ requireWritableFormat(hub);
719
+ return run(hub, ctx);
720
+ }).value;
588
721
  }
589
722
  /** Run an operation that must not take the lock, such as one creating the hub the lock would live in. */
590
723
  function runUnlocked(root, run) {
@@ -1031,7 +1164,8 @@ function loadConfig(root) {
1031
1164
  message: issue.message
1032
1165
  })));
1033
1166
  const config = result.data;
1034
- if (config.formatVersion !== 3) throw new HubError(config.formatVersion < 3 ? `data format version ${config.formatVersion} is older than this CLI's (3); run "mainflow migrate --dry-run" to preview the conversion, then "mainflow migrate"` : `data format version ${config.formatVersion} is newer than this CLI supports (3); install the matching mainflow version in this hub`, []);
1167
+ const mismatch = formatMismatch(config.formatVersion);
1168
+ if (mismatch) throw new HubError(mismatch, []);
1035
1169
  return config;
1036
1170
  }
1037
1171
  function loadHub(root, options = {}) {
@@ -2591,11 +2725,11 @@ function takeUnfinished(draft, ctx, from, to, existing, at) {
2591
2725
  doneAt: at
2592
2726
  };
2593
2727
  });
2594
- draft.write(previousFile, toYaml(validate(sessionSchema, {
2728
+ draft.write(previousFile, toYaml(yamlKeeping(draft, previousFile, previous, validate(sessionSchema, {
2595
2729
  ...previous,
2596
2730
  status: "handed-off",
2597
2731
  actions: left
2598
- }, draft.where(previousFile))));
2732
+ }, draft.where(previousFile)))));
2599
2733
  return carried;
2600
2734
  }
2601
2735
  /**
@@ -2678,7 +2812,7 @@ function handoffSession(hub, input, ctx) {
2678
2812
  handoffFrom: from,
2679
2813
  actions: [...session.actions, ...carried]
2680
2814
  }, draft.where(file));
2681
- draft.write(file, toYaml(next));
2815
+ draft.write(file, toYaml(yamlKeeping(draft, file, session, next)));
2682
2816
  return draft.result(next);
2683
2817
  }
2684
2818
  function setSessionInfo(hub, input) {
@@ -2721,10 +2855,10 @@ function settleSession(hub, input) {
2721
2855
  if (s.status !== "active" || s.delegatedFrom || removed && s.id === id) continue;
2722
2856
  if (!s.actions.every((a) => a.status === "done" || a.status === "dropped") || subagents(s.id).some((x) => x.status === "active")) continue;
2723
2857
  if (s.id === id && s.actions.length === 0) continue;
2724
- draft.write(sessionFileIn(s.id), toYaml(validate(sessionSchema, {
2858
+ draft.write(sessionFileIn(s.id), toYaml(yamlKeeping(draft, sessionFileIn(s.id), s, validate(sessionSchema, {
2725
2859
  ...s,
2726
2860
  status: "ended"
2727
- }, draft.where(sessionFileIn(s.id)))));
2861
+ }, draft.where(sessionFileIn(s.id))))));
2728
2862
  if (s.id === id) result = "ended";
2729
2863
  }
2730
2864
  return draft.result(result);
@@ -3076,7 +3210,10 @@ const OPERATIONS = {
3076
3210
  function applyOperation(storage, name, input, ctx) {
3077
3211
  const operation = OPERATIONS[name];
3078
3212
  if (!operation) throw new Error(`unknown operation "${String(name)}"`);
3079
- return applyOp(storage, (hub) => operation(hub, input, ctx));
3213
+ return applyOp(storage, (hub) => {
3214
+ requireWritableFormat(hub);
3215
+ return operation(hub, input, ctx);
3216
+ });
3080
3217
  }
3081
3218
  //#endregion
3082
3219
  //#region ../core/dist/ids/renumber.js
@@ -8102,4 +8239,4 @@ function openInApp(hub, target, closeAfterMs = 150) {
8102
8239
  return true;
8103
8240
  }
8104
8241
  //#endregion
8105
- export { nowMinute as $, mayDecorate as A, applyOperation as B, readSession as C, splitFrontMatter as Ct, decorateReply as D, matchGrants as E, renumberRequest as F, sectionText as G, HubError as H, renumberFiles as I, linksInto as J, dependencyGraph as K, renumberPath as L, traceTranscript as M, transcriptTitle as N, endsWithMarker as O, applyOffline as P, unavailableHubs as Q, renumberText as R, loadSessions as S, contentHash as St, grantScope as T, loadConfig as U, checkHubName as V, loadHub as W, refIndex as X, memberOfGroup as Y, remoteMembers as Z, initHub as _, findHubRoot as _t, openInApp as a, MAX_FILE_BYTES as at, sessionBriefing as b, DATA_DIR as bt, siteBlock as c, comparePaths as ct, retroReport as d, requestTime as dt, readYaml as et, retroReportFromReceiver as f, textBytes as ft, setArchivedMany as g, currentBranch as gt, ARCHIVE_KINDS as h, requireSlug as ht, hostName as i, MAX_BLOB_BYTES as it, attributeTrace as j, headerLine as k, syncHost as l, exceedsFileLimit as lt, RETRY_RULES as m, TASK_FILE as mt, DEFAULT_UI_PORT as n, ACCESS_HEADERS as nt, removeDanglingLinks as o, ROUTES as ot, receiverFromEnv as p, MAINLINE_FILE as pt, mainlineEdges as q, caddySites as r, BLOB_HASH as rt, removeHostLink as s, SOCKET_MAX_AGE_CLOSE as st, APP_BUNDLE_ID as t, nodeStorage as tt, migrateHub as u, readsAsText as ut, untilState as v, worktreesOf as vt, transcriptPath as w, turnReminder as x, WriteError as xt, duplicateClaimLines as y, ConflictError as yt, scopeOfPath as z };
8242
+ export { nowMinute as $, mayDecorate as A, applyOperation as B, readSession as C, WriteError as Ct, decorateReply as D, matchGrants as E, renumberRequest as F, sectionText as G, HubError as H, renumberFiles as I, linksInto as J, dependencyGraph as K, renumberPath as L, traceTranscript as M, transcriptTitle as N, endsWithMarker as O, applyOffline as P, unavailableHubs as Q, renumberText as R, loadSessions as S, DATA_DIR as St, grantScope as T, splitFrontMatter as Tt, loadConfig as U, checkHubName as V, loadHub as W, refIndex as X, memberOfGroup as Y, remoteMembers as Z, initHub as _, requireSlug as _t, openInApp as a, MAX_FILE_BYTES as at, sessionBriefing as b, worktreesOf as bt, siteBlock as c, comparePaths as ct, retroReport as d, requestTime as dt, readYaml as et, retroReportFromReceiver as f, textBytes as ft, setArchivedMany as g, TASK_FILE as gt, ARCHIVE_KINDS as h, MAINLINE_FILE as ht, hostName as i, MAX_BLOB_BYTES as it, attributeTrace as j, headerLine as k, syncHost as l, exceedsFileLimit as lt, RETRY_RULES as m, hubFormatVersion as mt, DEFAULT_UI_PORT as n, ACCESS_HEADERS as nt, removeDanglingLinks as o, ROUTES as ot, receiverFromEnv as p, formatMismatch as pt, mainlineEdges as q, caddySites as r, BLOB_HASH as rt, removeHostLink as s, SOCKET_MAX_AGE_CLOSE as st, APP_BUNDLE_ID as t, nodeStorage as tt, migrateHub as u, readsAsText as ut, untilState as v, currentBranch as vt, transcriptPath as w, contentHash as wt, turnReminder as x, ConflictError as xt, duplicateClaimLines as y, findHubRoot as yt, scopeOfPath as z };
package/dist/host.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as openInApp, c as siteBlock, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, o as removeDanglingLinks, r as caddySites, s as removeHostLink, t as APP_BUNDLE_ID } from "./host-BauijAdm.js";
1
+ import { a as openInApp, c as siteBlock, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, o as removeDanglingLinks, r as caddySites, s as removeHostLink, t as APP_BUNDLE_ID } from "./host-lY8ytTbw.js";
2
2
  export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, removeDanglingLinks, removeHostLink, siteBlock, syncHost };
@@ -1,4 +1,4 @@
1
- import { bt as DATA_DIR, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, s as removeHostLink, xt as WriteError } from "./host-BauijAdm.js";
1
+ import { Ct as WriteError, St as DATA_DIR, i as hostName, l as syncHost, n as DEFAULT_UI_PORT, s as removeHostLink } from "./host-lY8ytTbw.js";
2
2
  import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
3
3
  import { join, resolve } from "node:path";
4
4
  import { spawn, spawnSync } from "node:child_process";
@@ -276,7 +276,7 @@ async function launchUi(root, hub, configured, options) {
276
276
  }
277
277
  let server;
278
278
  if (!reuse) {
279
- const { serveUi } = await import("./ui-C-laSyqU.js");
279
+ const { serveUi } = await import("./ui-AhBsqtZe.js");
280
280
  server = await serveUi(root, choice.port);
281
281
  writeUiRecord(root, {
282
282
  port: choice.port,
package/dist/launch.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as networkProbe, c as realRoot, d as withUiLock, i as launchUi, l as startUiInBackground, n as choosePort, o as portCandidates, r as exitCodeFor, s as readUiRecord, t as PORT_SPAN, u as watchHubGone } from "./launch-n2ZDF0BF.js";
1
+ import { a as networkProbe, c as realRoot, d as withUiLock, i as launchUi, l as startUiInBackground, n as choosePort, o as portCandidates, r as exitCodeFor, s as readUiRecord, t as PORT_SPAN, u as watchHubGone } from "./launch-3HLHjQF0.js";
2
2
  export { PORT_SPAN, choosePort, exitCodeFor, launchUi, networkProbe, portCandidates, readUiRecord, realRoot, startUiInBackground, watchHubGone, withUiLock };
@@ -1,4 +1,4 @@
1
- import { $ as nowMinute, B as applyOperation, Ct as splitFrontMatter, F as renumberRequest, I as renumberFiles, L as renumberPath, P as applyOffline, R as renumberText, St as contentHash, at as MAX_FILE_BYTES, bt as DATA_DIR, ct as comparePaths, dt as requestTime, ft as textBytes, it as MAX_BLOB_BYTES, lt as exceedsFileLimit, nt as ACCESS_HEADERS, ot as ROUTES, rt as BLOB_HASH, st as SOCKET_MAX_AGE_CLOSE, tt as nodeStorage, ut as readsAsText, xt as WriteError, yt as ConflictError, z as scopeOfPath } from "./host-BauijAdm.js";
1
+ import { $ as nowMinute, B as applyOperation, Ct as WriteError, F as renumberRequest, I as renumberFiles, L as renumberPath, P as applyOffline, R as renumberText, St as DATA_DIR, Tt as splitFrontMatter, at as MAX_FILE_BYTES, ct as comparePaths, dt as requestTime, ft as textBytes, it as MAX_BLOB_BYTES, lt as exceedsFileLimit, nt as ACCESS_HEADERS, ot as ROUTES, rt as BLOB_HASH, st as SOCKET_MAX_AGE_CLOSE, tt as nodeStorage, ut as readsAsText, wt as contentHash, xt as ConflictError, z as scopeOfPath } from "./host-lY8ytTbw.js";
2
2
  import { createHash, randomBytes } from "node:crypto";
3
3
  import { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, linkSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
4
4
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -1,8 +1,8 @@
1
1
  import { F as configSchema, f as GROUP_SECTIONS } from "./dist-ud09dzZo.js";
2
- import { C as readSession, G as sectionText, H as HubError, J as linksInto, K as dependencyGraph, M as traceTranscript, N as transcriptTitle, S as loadSessions, U as loadConfig, W as loadHub, X as refIndex, Z as remoteMembers, a as openInApp, bt as DATA_DIR, et as readYaml, g as setArchivedMany, h as ARCHIVE_KINDS, j as attributeTrace, q as mainlineEdges, w as transcriptPath, xt as WriteError, yt as ConflictError } from "./host-BauijAdm.js";
2
+ import { C as readSession, Ct as WriteError, G as sectionText, H as HubError, J as linksInto, K as dependencyGraph, M as traceTranscript, N as transcriptTitle, S as loadSessions, St as DATA_DIR, U as loadConfig, W as loadHub, X as refIndex, Z as remoteMembers, a as openInApp, et as readYaml, g as setArchivedMany, h as ARCHIVE_KINDS, j as attributeTrace, q as mainlineEdges, w as transcriptPath, xt as ConflictError } from "./host-lY8ytTbw.js";
3
3
  import { t as listProgress } from "./progress-1BfPg2zN.js";
4
- import { A as isSynced, _ as readDaemon, a as remoteMode, b as readRemote, h as callDaemon, j as syncPaths, k as SYNC_DIR, m as DaemonUnavailable, n as hubWriter, r as writtenLines, y as watchTree } from "./operation-DGRH4iBE.js";
5
- import { c as realRoot, f as CLI_VERSION, s as readUiRecord } from "./launch-n2ZDF0BF.js";
4
+ import { A as isSynced, _ as readDaemon, a as remoteMode, b as readRemote, h as callDaemon, j as syncPaths, k as SYNC_DIR, m as DaemonUnavailable, n as hubWriter, r as writtenLines, y as watchTree } from "./operation-BZ7CHB6J.js";
5
+ import { c as realRoot, f as CLI_VERSION, s as readUiRecord } from "./launch-3HLHjQF0.js";
6
6
  import { createRequire } from "node:module";
7
7
  import { closeSync, existsSync, lstatSync, openSync, readFileSync, readSync, realpathSync, statSync } from "node:fs";
8
8
  import { basename, dirname, extname, join, normalize, relative, resolve, sep } from "node:path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mainflow",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "description": "本機多 AI 協作的主脈絡任務管理:CLI 與介面",
5
5
  "license": "MIT",
6
6
  "type": "module",