{"version":3,"file":"treeManifest-CtKbEtkE.cjs","names":["path","createHash","SUBAGENT_CHILD_ENV","SUBAGENT_PARENT_SESSION_ENV","path","os","fs","execFileSync","promisify","execFile","path","hasCode","fs","createHash","path","fs","path","fs"],"sources":["../src/services/lineDiff/index.ts","../src/services/editTracker/index.ts","../src/services/fileEditPaths/index.ts","../src/services/gitStatus/index.ts","../src/services/snapshotStore/index.ts","../src/services/fileChanges/index.ts","../src/services/timelineStore/index.ts","../src/services/treeManifest/index.ts"],"sourcesContent":["import type { FileEditsDiffHunk, FileEditsDiffRow } from '../../types/fileEditsApi';\n\n/**\n * The line difference between two versions of a file, as bounded hunks.\n *\n * This is deliberately the package's own rather than Pi's `generateDiffString`:\n * that helper reaches the session process through an optional peer dependency,\n * and these routes run in a host that imports only the built entry, so its\n * presence is an assumption rather than a fact. A line diff is small enough to\n * own outright, and owning it means the wire carries structured rows instead of\n * a formatted string the browser has to parse back apart.\n *\n * Bounded twice over. Common prefix and suffix are trimmed first, which is what\n * makes a one-line change in a large file cheap. What remains is matched with a\n * longest-common-subsequence table, and only while that table stays under\n * MAX_MATRIX_CELLS: past it the changed region is reported as one replacement\n * rather than growing a matrix that would outweigh the file.\n */\n\n/** Lines of unchanged context kept either side of a change. */\nconst CONTEXT_LINES = 3;\n\n/** The largest LCS table worth building; past it the changed region is one replacement. */\nconst MAX_MATRIX_CELLS = 1_000_000;\n\nexport interface LineDiffResult {\n  hunks: FileEditsDiffHunk[];\n  additions: number;\n  removals: number;\n  /** True when the changed region was too large to match line by line. */\n  approximate: boolean;\n}\n\n/** One step of the match, before it is grouped into hunks. */\ninterface DiffStep {\n  marker: '+' | '-' | ' ';\n  content: string;\n  /** Line number in whichever side owns the step, 1-based. */\n  line: number;\n}\n\nfunction splitLines(text: string): string[] {\n  const normalized = text.replaceAll('\\r\\n', '\\n').replaceAll('\\r', '\\n');\n  return normalized === '' ? [] : normalized.split('\\n');\n}\n\n/** How many leading lines the two sides share. */\nfunction commonPrefix(before: readonly string[], after: readonly string[]): number {\n  const limit = Math.min(before.length, after.length);\n  let count = 0;\n  while (count < limit && before[count] === after[count]) count += 1;\n  return count;\n}\n\n/** How many trailing lines the two sides share, never overlapping the prefix. */\nfunction commonSuffix(before: readonly string[], after: readonly string[], prefix: number): number {\n  const limit = Math.min(before.length, after.length) - prefix;\n  let count = 0;\n  while (count < limit && before[before.length - 1 - count] === after[after.length - 1 - count]) count += 1;\n  return count;\n}\n\n/**\n * The classic LCS length table. Only ever called once the caller has checked\n * the region against MAX_MATRIX_CELLS, so the allocation is bounded.\n */\nfunction lcsTable(before: readonly string[], after: readonly string[]): Uint32Array {\n  const rows = before.length + 1;\n  const columns = after.length + 1;\n  const table = new Uint32Array(rows * columns);\n  for (let row = before.length - 1; row >= 0; row -= 1) {\n    for (let column = after.length - 1; column >= 0; column -= 1) {\n      const index = row * columns + column;\n      table[index] =\n        before[row] === after[column]\n          ? (table[index + columns + 1] ?? 0) + 1\n          : Math.max(table[index + columns] ?? 0, table[index + 1] ?? 0);\n    }\n  }\n  return table;\n}\n\n/** Walks the table to turn it back into an ordered run of keeps, removals and additions. */\nfunction backtrack(\n  before: readonly string[],\n  after: readonly string[],\n  beforeStart: number,\n  afterStart: number,\n): DiffStep[] {\n  const table = lcsTable(before, after);\n  const columns = after.length + 1;\n  const steps: DiffStep[] = [];\n  let row = 0;\n  let column = 0;\n  while (row < before.length && column < after.length) {\n    if (before[row] === after[column]) {\n      steps.push({ marker: ' ', content: after[column] ?? '', line: afterStart + column });\n      row += 1;\n      column += 1;\n      continue;\n    }\n    if ((table[(row + 1) * columns + column] ?? 0) >= (table[row * columns + column + 1] ?? 0)) {\n      steps.push({ marker: '-', content: before[row] ?? '', line: beforeStart + row });\n      row += 1;\n      continue;\n    }\n    steps.push({ marker: '+', content: after[column] ?? '', line: afterStart + column });\n    column += 1;\n  }\n  while (row < before.length) {\n    steps.push({ marker: '-', content: before[row] ?? '', line: beforeStart + row });\n    row += 1;\n  }\n  while (column < after.length) {\n    steps.push({ marker: '+', content: after[column] ?? '', line: afterStart + column });\n    column += 1;\n  }\n  return steps;\n}\n\n/** The whole changed region as one replacement, for a region too large to match. */\nfunction wholesale(\n  before: readonly string[],\n  after: readonly string[],\n  beforeStart: number,\n  afterStart: number,\n): DiffStep[] {\n  return [\n    ...before.map((content, offset) => ({ marker: '-' as const, content, line: beforeStart + offset })),\n    ...after.map((content, offset) => ({ marker: '+' as const, content, line: afterStart + offset })),\n  ];\n}\n\n/** Groups the steps into hunks, keeping CONTEXT_LINES of unchanged text either side of a change. */\nfunction toHunks(steps: readonly DiffStep[]): FileEditsDiffHunk[] {\n  const keep: boolean[] = Array.from({ length: steps.length }, () => false);\n  for (const [index, step] of steps.entries()) {\n    if (step.marker === ' ') continue;\n    const from = Math.max(0, index - CONTEXT_LINES);\n    const to = Math.min(steps.length - 1, index + CONTEXT_LINES);\n    for (let cursor = from; cursor <= to; cursor += 1) keep[cursor] = true;\n  }\n\n  const hunks: FileEditsDiffHunk[] = [];\n  let rows: FileEditsDiffRow[] = [];\n  for (const [index, step] of steps.entries()) {\n    if (!keep[index]) {\n      if (rows.length > 0) {\n        hunks.push({ start: rows[0]?.line ?? 1, rows });\n        rows = [];\n      }\n      continue;\n    }\n    rows.push({ marker: step.marker, line: step.line, content: step.content });\n  }\n  if (rows.length > 0) hunks.push({ start: rows[0]?.line ?? 1, rows });\n  return hunks;\n}\n\n/**\n * The difference between a file that did not exist and the one that now does.\n *\n * Kept separate from a two-sided diff because an empty baseline is the one case\n * where the trailing newline matters. `splitLines` reads \"a\\n\" as a line and\n * then an empty one, which is invisible in a normal diff because both sides\n * carry it and it cancels, but against nothing it would report a file of three\n * lines as four. A creation is counted on the lines the file actually holds.\n */\nexport function lineDiffFromEmpty(after: string): LineDiffResult {\n  return lineDiff('', after.endsWith('\\n') ? after.slice(0, -1) : after);\n}\n\n/**\n * The difference between two versions of a file.\n *\n * Line numbers are the new file's for context and additions, and the old\n * file's for removals, which is the pairing a reader expects: the number\n * beside a line is where that line actually lives.\n */\nexport function lineDiff(before: string, after: string): LineDiffResult {\n  const beforeLines = splitLines(before);\n  const afterLines = splitLines(after);\n  const prefix = commonPrefix(beforeLines, afterLines);\n  const suffix = commonSuffix(beforeLines, afterLines, prefix);\n  const beforeMiddle = beforeLines.slice(prefix, beforeLines.length - suffix);\n  const afterMiddle = afterLines.slice(prefix, afterLines.length - suffix);\n\n  const approximate = beforeMiddle.length * afterMiddle.length > MAX_MATRIX_CELLS;\n  const middle = approximate\n    ? wholesale(beforeMiddle, afterMiddle, prefix + 1, prefix + 1)\n    : backtrack(beforeMiddle, afterMiddle, prefix + 1, prefix + 1);\n\n  const head: DiffStep[] = beforeLines\n    .slice(0, prefix)\n    .map((content, offset) => ({ marker: ' ' as const, content, line: offset + 1 }));\n  const tail: DiffStep[] = afterLines\n    .slice(afterLines.length - suffix)\n    .map((content, offset) => ({ marker: ' ' as const, content, line: afterLines.length - suffix + offset + 1 }));\n\n  const steps = [...head, ...middle, ...tail];\n  return {\n    hunks: toHunks(steps),\n    additions: steps.filter((step) => step.marker === '+').length,\n    removals: steps.filter((step) => step.marker === '-').length,\n    approximate,\n  };\n}\n","import path from 'node:path';\n\nimport type { FileEditTool, TimelineEvent } from '../../types/domain';\nimport type { IEditTracker } from '../../types/editTracker';\nimport type { GitStatusPort } from '../../types/gitStatus';\nimport type { SnapshotStorePort } from '../../types/snapshotStore';\nimport type { ITimelineStore } from '../../types/timelineStore';\nimport type { TreeManifest, TreeManifestPort } from '../../types/treeManifest';\nimport { lineDiff, lineDiffFromEmpty } from '../lineDiff';\n\nconst EDIT_TOOL = 'edit';\nconst WRITE_TOOL = 'write';\nconst BASH_TOOL = 'bash';\n\n/**\n * Records what the session changed, and captures enough of it to be diffed.\n *\n * Two mechanisms, because one is not enough. `edit` and `write` name their file\n * in the call arguments, so the content is read before the tool runs and both\n * sides of the change are known exactly. `bash` names nothing reliable: the\n * agent can write a script and run it, and reading path-shaped tokens out of\n * the command would miss every file that script touches. So a bash call is\n * bracketed by tree manifests instead, and whatever moved between them is\n * recorded, however it was written.\n *\n * A manifest-found path is recorded without a baseline, because it was only\n * identified after it had already changed. That is a real limit and the wire\n * carries it as `origin: 'scan'` rather than pretending a diff exists.\n *\n * A manifest compares size and modification time, and it compares the tree as\n * this tracker last walked it against the tree now, so it answers whether a\n * file differs, never when it moved. A path a previous session left dirty, or\n * one a checkout or an install rewrote, differs exactly like a path the command\n * just wrote. So a candidate is called verified only when something actually\n * proves its bytes moved: it appeared, it vanished, its recorded size differs,\n * or its content hash differs from one this session already took. Absence of\n * proof is not proof, so a candidate that shows none of those is still\n * recorded, because the timeline is the evidence, but it goes out unverified\n * and every surface leaves it out.\n */\ninterface PendingEdit {\n  tool: 'edit' | 'write';\n  filePath: string;\n  before: string | undefined;\n  /**\n   * Whether the file was there when the call began. A missing `before` cannot\n   * say on its own: content is left uncaptured both for a file that does not\n   * exist and for one too large or too binary to store.\n   */\n  existed: boolean;\n}\n\nfunction objectValue(value: unknown, key: string): string | undefined {\n  if (!value || typeof value !== 'object') return undefined;\n  const found = (value as Record<string, unknown>)[key];\n  return typeof found === 'string' ? found : undefined;\n}\n\nexport interface EditTrackerOptions {\n  /** Injectable so a test can pin the recorded timestamps. */\n  now?: () => number;\n  /**\n   * Decides whether a first-seen scan candidate actually changed. Optional:\n   * without it the tracker keeps recording every candidate it cannot disprove.\n   */\n  git?: GitStatusPort;\n}\n\n/**\n * How far before a call started a write may claim to have happened and still be\n * attributed to it. A working tree can sit on a filesystem that stores whole\n * seconds, which floors a write made just after the call began to a stamp just\n * before it, and the cost of being generous here is one second of the staleness\n * this check exists to remove.\n */\nconst MODIFIED_TOLERANCE_MS = 1000;\n\nexport class EditTracker implements IEditTracker {\n  private readonly pending = new Map<string, PendingEdit>();\n  /** Start time per in-flight bash call, so its end knows what it may claim. */\n  private readonly bracketed = new Map<string, number>();\n  /**\n   * The tree as this tracker last saw it. A bash call compares against it and\n   * then replaces it, so each call costs one walk rather than two, and a change\n   * made between calls is still noticed on the next one.\n   */\n  private manifest: TreeManifest | undefined;\n  /**\n   * This package's own storage, which the walk must never report. The timeline\n   * and its snapshots can land inside the tree being watched, and recording\n   * them would make every change cause another one.\n   */\n  private excluded: readonly string[] = [];\n  /**\n   * The project's own ignore rules. A path the project disowns is not worth a\n   * git call, a read, or a stored copy of its content, so it is dropped before\n   * it costs any of them.\n   */\n  private isIgnored: ((filePath: string) => boolean) | undefined;\n  /**\n   * The last content hash this session saw per path, from either mechanism.\n   * A candidate whose hash has not moved was touched, not edited.\n   */\n  private readonly contents = new Map<string, string>();\n  private readonly now: () => number;\n  private readonly git: GitStatusPort | undefined;\n  /**\n   * The scan deferred by the last bash call. Every bracket joins this chain, so\n   * at most one walk runs at a time and each one sees the baseline the previous\n   * one left behind.\n   */\n  private scanning: Promise<void> = Promise.resolve();\n\n  constructor(\n    private readonly timeline: ITimelineStore,\n    private readonly snapshots: SnapshotStorePort,\n    private readonly manifests: TreeManifestPort,\n    options: EditTrackerOptions = {},\n  ) {\n    this.now = options.now ?? Date.now;\n    this.git = options.git;\n  }\n\n  /**\n   * Forgets the previous session's tree so a new one does not inherit its\n   * baseline, and takes the paths this session's own bookkeeping occupies.\n   */\n  reset(options: { exclude?: readonly string[]; isIgnored?: (filePath: string) => boolean } = {}): void {\n    this.pending.clear();\n    this.bracketed.clear();\n    this.contents.clear();\n    this.manifest = undefined;\n    this.scanning = Promise.resolve();\n    this.excluded = options.exclude ?? [];\n    this.isIgnored = options.isIgnored;\n  }\n\n  /**\n   * Awaits a scan still running in the background. A caller that is about to\n   * clear the timeline needs this, or the scan appends after the clear.\n   */\n  async flush(): Promise<void> {\n    await this.scanning;\n  }\n  async start(id: string, tool: string, args: unknown, cwd: string): Promise<void> {\n    // A deferred scan still owns the baseline manifest, so it settles before\n    // this bracket reads or replaces it.\n    await this.scanning;\n    if (tool === EDIT_TOOL || tool === WRITE_TOOL) {\n      const supplied = objectValue(args, 'path');\n      if (!supplied) return;\n      const filePath = path.resolve(cwd, supplied);\n      // Both are read before the tool runs. The fingerprint is the only thing\n      // that tells a file being created from one whose content could not be\n      // captured, because a capture answers undefined for either.\n      const [before, fingerprint] = await Promise.all([\n        this.snapshots.capture(filePath),\n        this.manifests.fingerprint(filePath),\n      ]);\n      this.pending.set(id, { tool, filePath, before, existed: fingerprint !== undefined });\n      return;\n    }\n    if (tool !== BASH_TOOL) return;\n    // Read before the baseline walk, which is the one thing here that can take\n    // long enough to matter: a write that races it belongs to this call.\n    this.bracketed.set(id, this.now());\n    // The first bash call of a session has nothing to compare against, so it\n    // pays for the baseline walk; every later call reuses the previous end.\n    this.manifest ??= await this.manifests.take(cwd, this.excluded);\n  }\n\n  async end(id: string, isError: boolean, cwd: string): Promise<void> {\n    const pending = this.pending.get(id);\n    this.pending.delete(id);\n    const startedAt = this.bracketed.get(id);\n    this.bracketed.delete(id);\n    if (pending) {\n      // A failed edit or write never landed, and its arguments named the file,\n      // so there is nothing left to look for.\n      if (!isError) await this.recordTool(pending);\n      return;\n    }\n    // A failed command may still have written before it failed. Skipping the\n    // walk would leave the baseline stale and hand those writes to whichever\n    // call closes next.\n    if (startedAt === undefined) return;\n    // The walk is the expensive half of this hook and pi awaits the hook before\n    // it hands the tool result back to the model. Deferring it onto the chain\n    // moves that cost into the model's own thinking time instead of the user's\n    // wait; start() joins the same chain, so ordering still holds.\n    this.scanning = this.scanning.then(async () => {\n      try {\n        await this.recordScan(cwd, startedAt);\n      } catch {\n        // One failed scan must not poison the chain for every later call.\n      }\n    });\n  }\n\n  /** An `edit` or `write` whose file was read on both sides of the call. */\n  private async recordTool(pending: PendingEdit): Promise<void> {\n    const after = await this.snapshots.capture(pending.filePath);\n    const created = !pending.existed;\n    const counts = await this.countChanges(pending.before, after, created);\n    if (after !== undefined) this.contents.set(pending.filePath, after);\n    await this.append({\n      version: 2,\n      path: pending.filePath,\n      tool: pending.tool,\n      at: this.now(),\n      origin: 'tool',\n      ...(pending.before === undefined ? {} : { before: pending.before }),\n      ...(after === undefined ? {} : { after }),\n      ...(created ? { created: true } : {}),\n      ...counts,\n    });\n    // The tool already accounted for this path, so the next bash comparison\n    // must not report it a second time under its own name.\n    await this.remember(pending.filePath);\n  }\n\n  /** Whatever a bash call actually edited, however the command wrote it. */\n  private async recordScan(cwd: string, startedAt: number): Promise<void> {\n    const before = this.manifest;\n    if (before === undefined) return;\n    const after = await this.manifests.take(cwd, this.excluded);\n    this.manifest = after;\n    const disowned = this.isIgnored;\n    const named = this.manifests\n      .changed(before, after)\n      .filter((filePath) => disowned === undefined || !disowned(filePath));\n    const candidates = await this.writtenDuring(named, startedAt);\n    if (candidates.length === 0) return;\n    const unchanged = await this.unchangedInGit(cwd, candidates);\n    for (const filePath of candidates) {\n      const known = this.contents.get(filePath);\n      // Asked before the file is read: a path git vouches for is worth neither\n      // the read nor the stored copy that reading it leaves behind.\n      if (known === undefined && unchanged.has(filePath)) continue;\n      const beforePrint = before.entries.get(filePath);\n      const afterPrint = after.entries.get(filePath);\n      // A path that is gone has nothing to read, and reading it back would only\n      // confirm that.\n      const captured = afterPrint === undefined ? undefined : await this.snapshots.capture(filePath);\n      if (captured !== undefined) this.contents.set(filePath, captured);\n      // The bytes are the ones this session already recorded: the call moved the\n      // modification time and nothing else.\n      if (captured !== undefined && captured === known) continue;\n      const proven =\n        beforePrint === undefined ||\n        afterPrint === undefined ||\n        this.manifests.sizeChanged(beforePrint, afterPrint) ||\n        (known !== undefined && captured !== undefined && captured !== known);\n      await this.append({\n        version: 2,\n        path: filePath,\n        tool: BASH_TOOL,\n        at: this.now(),\n        origin: 'scan',\n        ...(proven ? { verified: true } : {}),\n        ...(captured === undefined ? {} : { after: captured }),\n      });\n    }\n  }\n\n  /**\n   * Narrows candidates to the ones that could have been written by the call\n   * being closed.\n   *\n   * This is what keeps a working tree that was already dirty out of the list. A\n   * file whose bytes were last written before the call began was differed by\n   * something else, whatever moved its fingerprint. A file that is no longer\n   * there has no time to read and a delete is a change the call may well have\n   * made, so it stays a candidate.\n   */\n  private async writtenDuring(candidates: readonly string[], startedAt: number): Promise<string[]> {\n    const floor = startedAt - MODIFIED_TOLERANCE_MS;\n    const written: string[] = [];\n    for (const filePath of candidates) {\n      const modifiedAt = await this.manifests.modifiedAt(filePath);\n      if (modifiedAt === undefined || modifiedAt >= floor) written.push(filePath);\n    }\n    return written;\n  }\n\n  /** Which candidates git tracks and reports as untouched; empty when it cannot say. */\n  private async unchangedInGit(cwd: string, candidates: readonly string[]): Promise<ReadonlySet<string>> {\n    const unseen = candidates.filter((filePath) => !this.contents.has(filePath));\n    if (this.git === undefined || unseen.length === 0) return new Set();\n    return this.git.unchanged(cwd, unseen);\n  }\n\n  /** How many lines moved, when there is enough captured content to say. */\n  private async countChanges(\n    before: string | undefined,\n    after: string | undefined,\n    created: boolean,\n  ): Promise<{ additions?: number; removals?: number }> {\n    if (after === undefined) return {};\n    if (before === undefined) {\n      // A file that did not exist has an empty baseline, so every line it now\n      // holds is an addition. A file that existed but went uncaptured has no\n      // baseline to count against at all.\n      if (!created) return {};\n      const createdText = await this.snapshots.read(after);\n      if (createdText === undefined) return {};\n      const fresh = lineDiffFromEmpty(createdText);\n      return { additions: fresh.additions, removals: fresh.removals };\n    }\n    if (before === after) return { additions: 0, removals: 0 };\n    const [beforeText, afterText] = await Promise.all([this.snapshots.read(before), this.snapshots.read(after)]);\n    if (beforeText === undefined || afterText === undefined) return {};\n    const diff = lineDiff(beforeText, afterText);\n    return { additions: diff.additions, removals: diff.removals };\n  }\n\n  /** Records the change unless it turned out to be no change at all. */\n  private async append(event: TimelineEvent): Promise<void> {\n    if (event.before !== undefined && event.before === event.after) return;\n    await this.timeline.append(event);\n  }\n\n  /**\n   * Folds a path the tool layer just handled into the tracked manifest, so the\n   * next bash comparison sees it as already accounted for.\n   *\n   * The fingerprint has to be the one a walk would read, not a stand-in, or the\n   * next comparison reports the file again under bash and every tool edit is\n   * recorded twice.\n   */\n  private async remember(filePath: string): Promise<void> {\n    if (this.manifest === undefined) return;\n    const entries = new Map(this.manifest.entries);\n    const fingerprint = await this.manifests.fingerprint(filePath);\n    if (fingerprint === undefined) entries.delete(filePath);\n    else entries.set(filePath, fingerprint);\n    this.manifest = { entries, truncated: this.manifest.truncated };\n  }\n}\n\n/** The tools this tracker knows how to attribute a change to. */\nexport const TRACKED_TOOLS: readonly FileEditTool[] = [EDIT_TOOL, WRITE_TOOL, BASH_TOOL];\n","import { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { SUBAGENT_CHILD_ENV, SUBAGENT_PARENT_SESSION_ENV } from '@agimon-ai/doompi-core/childProcess';\n\nimport type { IFileEditPaths } from '../../types/fileEditPaths';\n\n/** The directory this package owns, under whichever root holds agent state. */\nconst STATE_DIRECTORY = 'doom-file-edit';\nconst AGENT_DIRECTORY = ['.pi', 'agent'];\n\nfunction hash(value: string): string {\n  return createHash('sha256').update(value).digest('hex').slice(0, 16);\n}\n\nexport class FileEditPaths implements IFileEditPaths {\n  sessionKey(sessionId: string, env: NodeJS.ProcessEnv = process.env): string {\n    if (env[SUBAGENT_CHILD_ENV]) {\n      const parent = env[SUBAGENT_PARENT_SESSION_ENV];\n      if (parent) return parent;\n    }\n    return sessionId;\n  }\n\n  /**\n   * Where every session's state lives: the Pi agent directory, the same root\n   * every other Doom package writes to, and never inside the working tree.\n   *\n   * An earlier layout put this in the repository's git common directory. That\n   * is git's own storage: nothing in git's lifecycle prunes a directory we add\n   * to it, a linked worktree writes into the main checkout rather than its own,\n   * a submodule writes inside `.git/modules`, and `PI_CODING_AGENT_DIR` was\n   * ignored outright. The snapshots are verbatim copies of files the session\n   * touched, so where they land is a question about handling content, not a\n   * question about convenience.\n   */\n  stateDirectory(): string {\n    const configured = process.env.PI_CODING_AGENT_DIR?.trim();\n    const root =\n      configured === undefined || configured === '' ? path.join(os.homedir(), ...AGENT_DIRECTORY) : configured;\n    return path.join(root, STATE_DIRECTORY);\n  }\n\n  /**\n   * One session's timeline, named from its working directory and its session so\n   * the hub and the session API can find it from another process knowing only\n   * those two things.\n   */\n  timelinePath(cwd: string, sessionKey: string): string {\n    const directory = this.stateDirectory();\n    fs.mkdirSync(directory, { recursive: true });\n    return path.join(directory, `${hash(fs.realpathSync(cwd))}-${hash(sessionKey)}.jsonl`);\n  }\n\n  /**\n   * Where this session's content snapshots live: beside its timeline and named\n   * after it, so the two are found together and cleared together.\n   */\n  snapshotsPath(cwd: string, sessionKey: string): string {\n    return `${this.timelinePath(cwd, sessionKey).replace(/\\.jsonl$/u, '')}.blobs`;\n  }\n\n  legacyStateDirectory(cwd: string): string | undefined {\n    const common = this.gitCommonDirectory(cwd);\n    return common === undefined ? undefined : path.join(common, STATE_DIRECTORY);\n  }\n\n  /** Only still read so the state an older build left behind can be cleared away. */\n  private gitCommonDirectory(cwd: string): string | undefined {\n    try {\n      const result = execFileSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], {\n        cwd,\n        encoding: 'utf8',\n        stdio: ['ignore', 'pipe', 'ignore'],\n      }).trim();\n      return result || undefined;\n    } catch (error) {\n      if (error instanceof Error) return undefined;\n      throw error;\n    }\n  }\n}\n","import { execFile } from 'node:child_process';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\n\nimport type { GitStatusPort } from '../../types/gitStatus';\n\n/**\n * Answers the unchanged question with git, in two batched calls per chunk.\n *\n * One technology per adapter. This is where git enters the scan path; the\n * tracker that depends on the capability keeps importing the port.\n *\n * `ls-files` names which of the given paths git tracks at all, and `status`\n * names which of those moved. Everything else, an ignored build artefact, a\n * temporary file, a tree with no repository, falls out of both answers and is\n * therefore never reported as unchanged: the caller must keep recording it,\n * because git has nothing to say about a file it never saw.\n */\n\n/** Paths per git invocation, so a large scan cannot overflow the argument list. */\nconst CHUNK = 200;\nconst MAX_BUFFER = 4 * 1024 * 1024;\n\nconst run = promisify(execFile);\n\nfunction chunked<T>(values: readonly T[], size: number): T[][] {\n  const groups: T[][] = [];\n  for (let index = 0; index < values.length; index += size) groups.push(values.slice(index, index + size));\n  return groups;\n}\n\nfunction splitRecords(output: string): string[] {\n  return output.split('\\0').filter((entry) => entry !== '');\n}\n\n/**\n * The paths named by `status --porcelain -z`, whose records carry a two-letter\n * code and a space. A rename adds a bare second record; keeping it is harmless,\n * because every path in this set is one the caller records anyway.\n */\nfunction statusPaths(output: string): string[] {\n  return splitRecords(output).map((record) => (record.length > 3 && record[2] === ' ' ? record.slice(3) : record));\n}\n\nfunction isInside(root: string, filePath: string): boolean {\n  const relative = path.relative(root, filePath);\n  return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative);\n}\n\nexport class NodeGitStatusAdapter implements GitStatusPort {\n  async unchanged(cwd: string, filePaths: readonly string[]): Promise<ReadonlySet<string>> {\n    const clean = new Set<string>();\n    if (filePaths.length === 0) return clean;\n    const root = await this.topLevel(cwd);\n    if (root === undefined) return clean;\n\n    for (const group of chunked(\n      filePaths.filter((filePath) => isInside(root, filePath)),\n      CHUNK,\n    )) {\n      const relative = group.map((filePath) => path.relative(root, filePath));\n      const tracked = await this.git(root, ['ls-files', '-z', '--', ...relative]);\n      if (tracked === undefined) continue;\n      const dirty = await this.git(root, ['status', '--porcelain', '-z', '--untracked-files=no', '--', ...relative]);\n      if (dirty === undefined) continue;\n      const moved = new Set(statusPaths(dirty));\n      for (const entry of splitRecords(tracked)) {\n        if (!moved.has(entry)) clean.add(path.resolve(root, entry));\n      }\n    }\n    return clean;\n  }\n\n  /** The repository root, or undefined when this tree is not one. */\n  private async topLevel(cwd: string): Promise<string | undefined> {\n    const output = await this.git(cwd, ['rev-parse', '--show-toplevel']);\n    const root = output?.trim();\n    return root === undefined || root === '' ? undefined : path.resolve(root);\n  }\n\n  /** Git's stdout, or undefined when the call failed for any reason at all. */\n  private async git(cwd: string, args: readonly string[]): Promise<string | undefined> {\n    try {\n      const { stdout } = await run('git', [...args], { cwd, encoding: 'utf8', maxBuffer: MAX_BUFFER });\n      return stdout;\n    } catch {\n      return undefined;\n    }\n  }\n}\n","import { createHash } from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { SnapshotStorePort } from '../../types/snapshotStore';\n\n/**\n * Store and read the file content this session's diffs are built from.\n *\n * One technology per adapter. This is where node enters the package; the\n * services that depend on the capability keep importing the port.\n *\n * Snapshots are content-addressed, so a file written twice with the same bytes\n * occupies one blob and the second capture is a hash and an exists check. The\n * whole directory goes when the session's timeline does, which is what keeps\n * this from growing without bound across a machine's lifetime.\n */\n\n/** Past this, a file is listed as changed without content rather than snapshotted. */\nexport const MAX_SNAPSHOT_BYTES = 1024 * 1024;\n\n/** How much of a file is read before deciding it is binary. */\nconst BINARY_SAMPLE_BYTES = 8192;\n\nconst MISSING_CODES = new Set(['ENOENT', 'ENOTDIR', 'EISDIR', 'ENAMETOOLONG']);\n\nfunction hasCode(error: unknown, codes: ReadonlySet<string>): boolean {\n  return error instanceof Error && 'code' in error && typeof error.code === 'string' && codes.has(error.code);\n}\n\nexport class NodeSnapshotStoreAdapter implements SnapshotStorePort {\n  private directory: string | undefined;\n\n  initialize(directory: string): void {\n    this.directory = directory;\n  }\n\n  async capture(filePath: string): Promise<string | undefined> {\n    let raw: Buffer;\n    try {\n      raw = await fs.readFile(filePath);\n    } catch (error) {\n      if (hasCode(error, MISSING_CODES)) return undefined;\n      throw error;\n    }\n    if (raw.byteLength > MAX_SNAPSHOT_BYTES) return undefined;\n    if (raw.subarray(0, BINARY_SAMPLE_BYTES).includes(0)) return undefined;\n    return this.put(raw.toString('utf8'));\n  }\n\n  async put(content: string): Promise<string> {\n    const hash = createHash('sha256').update(content, 'utf8').digest('hex');\n    const blobPath = path.join(this.requireDirectory(), hash);\n    // An existing blob already holds exactly this content, by construction, so\n    // rewriting it would only cost a write.\n    try {\n      await fs.access(blobPath);\n      return hash;\n    } catch (error) {\n      if (!hasCode(error, MISSING_CODES)) throw error;\n    }\n    await fs.mkdir(this.requireDirectory(), { recursive: true });\n    await fs.writeFile(blobPath, content, 'utf8');\n    return hash;\n  }\n\n  async read(hash: string): Promise<string | undefined> {\n    if (!/^[0-9a-f]{64}$/u.test(hash)) return undefined;\n    try {\n      return await fs.readFile(path.join(this.requireDirectory(), hash), 'utf8');\n    } catch (error) {\n      if (hasCode(error, MISSING_CODES)) return undefined;\n      throw error;\n    }\n  }\n\n  async clear(): Promise<void> {\n    if (this.directory === undefined) return;\n    await fs.rm(this.directory, { recursive: true, force: true });\n  }\n\n  private requireDirectory(): string {\n    if (this.directory === undefined) throw new Error('Snapshot store is not initialized');\n    return this.directory;\n  }\n}\n","import type { FileEditEntry, FileEditVersion, LegacyTimelineEvent, TimelineEvent } from '../../types/domain';\n\n/**\n * Fold a session's recorded changes into the per-file rows and version\n * histories the surfaces show.\n *\n * The timeline is append-only, one line per change, so every reader folds it\n * the same way and the folding belongs somewhere both the store and its tests\n * can reach without a filesystem. Version 1 lines are still read: a session\n * already running when the package updates keeps appending to the file it\n * opened, and dropping its earlier lines would blank a list mid-session.\n */\n\n/** Either shape the timeline file can hold. */\nexport type AnyTimelineEvent = TimelineEvent | LegacyTimelineEvent;\n\nconst TOOLS = new Set(['edit', 'write', 'bash', 'user']);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction optionalString(value: unknown): string | undefined {\n  return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction optionalCount(value: unknown): number | undefined {\n  return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;\n}\n\n/** Narrows one parsed line, or answers null so a malformed line can be skipped. */\nexport function parseTimelineEvent(value: unknown): AnyTimelineEvent | null {\n  if (!isRecord(value)) return null;\n  const { version, path: filePath, tool, at } = value;\n  if (typeof filePath !== 'string' || filePath === '') return null;\n  if (typeof at !== 'number' || !Number.isFinite(at)) return null;\n  if (typeof tool !== 'string' || !TOOLS.has(tool)) return null;\n\n  if (version === 1) {\n    if (tool === 'user') return null; // The version 1 vocabulary had no manual saves.\n    return { version: 1, path: filePath, tool: tool as LegacyTimelineEvent['tool'], at };\n  }\n  if (version !== 2) return null;\n  const origin = value.origin === 'scan' ? 'scan' : 'tool';\n  return {\n    version: 2,\n    path: filePath,\n    tool: tool as TimelineEvent['tool'],\n    at,\n    origin,\n    ...(optionalString(value.before) === undefined ? {} : { before: value.before as string }),\n    ...(optionalString(value.after) === undefined ? {} : { after: value.after as string }),\n    ...(optionalCount(value.additions) === undefined ? {} : { additions: value.additions as number }),\n    ...(optionalCount(value.removals) === undefined ? {} : { removals: value.removals as number }),\n    ...(value.verified === true ? { verified: true } : {}),\n    ...(value.created === true ? { created: true } : {}),\n  };\n}\n\n/** Every recorded line of the timeline, malformed ones dropped, in file order. */\nexport function parseTimeline(content: string, onMalformed?: (line: string) => void): AnyTimelineEvent[] {\n  const events: AnyTimelineEvent[] = [];\n  for (const line of content.split('\\n')) {\n    if (line === '') continue;\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(line);\n    } catch {\n      onMalformed?.(line);\n      continue;\n    }\n    const event = parseTimelineEvent(parsed);\n    if (event === null) onMalformed?.(line);\n    else events.push(event);\n  }\n  return events;\n}\n\n/**\n * Whether a recorded change is evidence that the file's content actually moved.\n *\n * A tool change names its file and reads both sides, so it always is. A scan\n * change is a tree comparison of size and modification time, which a checkout,\n * an install, or a command that merely touched a file moves as readily as an\n * edit does; only a scan the tracker confirmed carries `verified`. Version 1\n * lines predate the distinction entirely, so a bash one cannot be trusted.\n */\nexport function isConfirmedChange(event: AnyTimelineEvent): boolean {\n  if (event.version !== 2) return event.tool !== 'bash';\n  return event.origin !== 'scan' || event.verified === true;\n}\n\n/** The recorded changes worth listing, which is every change but an unconfirmed touch. */\nexport function confirmedChanges(events: readonly AnyTimelineEvent[]): AnyTimelineEvent[] {\n  return events.filter(isConfirmedChange);\n}\n/** One row per file, newest change first, which is the order both docks list in. */\nexport function foldEntries(events: readonly AnyTimelineEvent[]): FileEditEntry[] {\n  const folded = new Map<string, FileEditEntry>();\n  for (const event of events) {\n    const current = folded.get(event.path);\n    folded.set(event.path, {\n      path: event.path,\n      tool: event.at >= (current?.at ?? 0) ? event.tool : (current?.tool ?? event.tool),\n      at: Math.max(event.at, current?.at ?? 0),\n      count: (current?.count ?? 0) + 1,\n    });\n  }\n  return [...folded.values()].sort((left, right) => right.at - left.at);\n}\n\n/** One file's history, oldest first, numbered so a reader can name a version. */\nexport function foldVersions(events: readonly AnyTimelineEvent[], filePath: string): FileEditVersion[] {\n  return events\n    .filter((event) => event.path === filePath)\n    .sort((left, right) => left.at - right.at)\n    .map((event, offset) => {\n      const version: FileEditVersion = {\n        index: offset + 1,\n        tool: event.tool,\n        at: event.at,\n        origin: event.version === 2 ? event.origin : 'scan',\n      };\n      if (event.version !== 2) return version;\n      return {\n        ...version,\n        ...(event.before === undefined ? {} : { before: event.before }),\n        ...(event.after === undefined ? {} : { after: event.after }),\n        ...(event.additions === undefined ? {} : { additions: event.additions }),\n        ...(event.removals === undefined ? {} : { removals: event.removals }),\n        ...(event.verified === true ? { verified: true } : {}),\n        ...(event.created === true ? { created: true } : {}),\n      };\n    });\n}\n\n/**\n * Whether a file can be diffed at all: some version has to give the diff a\n * starting point. A captured baseline is one. So is a version that created the\n * file, whose starting point is nothing at all.\n *\n * A file only ever seen after the fact, which is every file a bash script\n * wrote, still cannot be.\n */\nexport function isDiffable(versions: readonly FileEditVersion[]): boolean {\n  return versions.some((version) => version.before !== undefined || version.created === true);\n}\n\n/** The oldest captured baseline for a file, which is what the whole-session diff starts from. */\nexport function baselineOf(versions: readonly FileEditVersion[]): string | undefined {\n  return versions.find((version) => version.before !== undefined)?.before;\n}\n","import fs, { type FileHandle } from 'node:fs/promises';\n\nimport type { FileEditEntry, FileEditVersion, TimelineEvent } from '../../types/domain';\nimport type { ITimelineStore } from '../../types/timelineStore';\nimport { type AnyTimelineEvent, confirmedChanges, foldEntries, foldVersions, parseTimeline } from '../fileChanges';\n\nconst LOCK_RETRY_MS = 25;\nconst LOCK_RETRIES = 400;\n/**\n * How long a lock file may sit untouched before a waiter treats it as abandoned.\n *\n * An append writes one line, so a holder that has been there for half a minute\n * is a process that died without unlinking. Without this, that one file would\n * block every later append to the same timeline permanently.\n */\nconst LOCK_STALE_MS = 30_000;\n\nfunction hasCode(error: unknown, code: string): boolean {\n  return error instanceof Error && 'code' in error && error.code === code;\n}\n\nexport class TimelineStore implements ITimelineStore {\n  private filePath: string | undefined;\n\n  initialize(filePath: string): void {\n    this.filePath = filePath;\n  }\n\n  async append(event: TimelineEvent): Promise<void> {\n    await this.withLock(async () => fs.appendFile(this.requirePath(), `${JSON.stringify(event)}\\n`, 'utf8'));\n  }\n\n  async list(): Promise<FileEditEntry[]> {\n    // Listing shows what was edited, so a path a command only touched is left out.\n    return foldEntries(confirmedChanges(await this.events()));\n  }\n\n  async versions(filePath: string): Promise<FileEditVersion[]> {\n    // Same bar as the listing above: a file's history must not reintroduce the\n    // touches the list already left out.\n    return foldVersions(confirmedChanges(await this.events()), filePath);\n  }\n\n  async clear(): Promise<void> {\n    try {\n      await fs.unlink(this.requirePath());\n    } catch (error) {\n      if (!hasCode(error, 'ENOENT')) throw error;\n    }\n  }\n\n  /** Every recorded change, or none at all when the session has not written yet. */\n  private async events(): Promise<AnyTimelineEvent[]> {\n    let content: string;\n    try {\n      content = await fs.readFile(this.requirePath(), 'utf8');\n    } catch (error) {\n      if (hasCode(error, 'ENOENT')) return [];\n      throw error;\n    }\n    return parseTimeline(content, (line) =>\n      console.warn(`Ignoring malformed file edit timeline line: ${line.slice(0, 200)}`),\n    );\n  }\n\n  private requirePath(): string {\n    if (!this.filePath) throw new Error('Timeline store is not initialized');\n    return this.filePath;\n  }\n\n  private async withLock<T>(operation: () => Promise<T>): Promise<T> {\n    const lockPath = `${this.requirePath()}.lock`;\n    const lock = await this.acquire(lockPath);\n    try {\n      return await operation();\n    } finally {\n      await lock.close();\n      await this.release(lockPath);\n    }\n  }\n\n  /** Waits for the lock file, breaking one an earlier process left behind. */\n  private async acquire(lockPath: string): Promise<FileHandle> {\n    for (let attempt = 0; attempt < LOCK_RETRIES; attempt += 1) {\n      try {\n        return await fs.open(lockPath, 'wx');\n      } catch (error) {\n        if (!hasCode(error, 'EEXIST')) throw error;\n        if (await this.breakStale(lockPath)) continue;\n        await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));\n      }\n    }\n    throw new Error(`Timed out acquiring timeline lock ${lockPath}`);\n  }\n\n  /** Whether the lock is now free to take, having removed it when its holder is gone. */\n  private async breakStale(lockPath: string): Promise<boolean> {\n    try {\n      const stats = await fs.stat(lockPath);\n      if (Date.now() - stats.mtimeMs < LOCK_STALE_MS) return false;\n      await fs.unlink(lockPath);\n      return true;\n    } catch (error) {\n      // Already gone, or another waiter broke it first: either way, try again.\n      if (hasCode(error, 'ENOENT')) return true;\n      throw error;\n    }\n  }\n\n  private async release(lockPath: string): Promise<void> {\n    try {\n      await fs.unlink(lockPath);\n    } catch (error) {\n      if (!hasCode(error, 'ENOENT')) console.warn(`Could not remove timeline lock: ${String(error)}`);\n    }\n  }\n}\n","import type { Dirent } from 'node:fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { TreeManifest, TreeManifestPort } from '../../types/treeManifest';\n\n/**\n * Take a bounded manifest of a working tree and report which files moved\n * between two of them.\n *\n * One technology per adapter. This is where node enters the package; the\n * services that depend on the capability keep importing the port.\n *\n * The caps are the whole design. An unbounded walk of a working directory is\n * dominated by dependency and build trees, which change constantly and tell a\n * reader nothing, so those are skipped by name; what remains is capped on both\n * entries and depth so the walk stays a fixed cost rather than a function of\n * how large the checkout grew. Hitting a cap is reported, never hidden.\n */\n\n/**\n * Directories a working tree fills with output nobody wants listed as an edit.\n *\n * Two kinds live here. Most are the build and dependency trees every checkout\n * grows. The rest are where tooling, including this agent's own, writes while a\n * session runs: a telemetry log under `logs`, a test run's artifacts under\n * `test-results` and `playwright-report`, scratch space under `tmp`, and agent\n * state under `.pi`. Those are skipped by construction rather than judged file\n * by file, because a walk that enters them reports the session watching itself.\n */\nexport const IGNORED_DIRECTORIES: ReadonlySet<string> = new Set([\n  '.git',\n  '.hg',\n  '.svn',\n  '.cache',\n  '.gradle',\n  '.next',\n  '.nuxt',\n  '.nx',\n  '.pi',\n  '.pnpm-store',\n  '.turbo',\n  '.venv',\n  '__pycache__',\n  'build',\n  'coverage',\n  'dist',\n  'logs',\n  'node_modules',\n  'out',\n  'playwright-report',\n  'target',\n  'test-results',\n  'tmp',\n  'vendor',\n  'venv',\n]);\n\nexport const MAX_ENTRIES = 20_000;\nexport const MAX_DEPTH = 12;\n\n/**\n * How a file is summarised. Size and modification time are what a walk can read\n * cheaply for thousands of files; hashing every one of them would turn a scan\n * into a read of the whole tree.\n */\nfunction fingerprintOf(size: number, modifiedMs: number): string {\n  return `${size}:${modifiedMs}`;\n}\n\n/** The size half of a fingerprint, which only the adapter that wrote it can read. */\nfunction sizeOf(fingerprint: string): string {\n  const separator = fingerprint.indexOf(':');\n  return separator === -1 ? fingerprint : fingerprint.slice(0, separator);\n}\n\nexport interface NodeTreeManifestOptions {\n  maxEntries?: number;\n  maxDepth?: number;\n  ignoredDirectories?: ReadonlySet<string>;\n}\n\nexport class NodeTreeManifestAdapter implements TreeManifestPort {\n  private readonly maxEntries: number;\n  private readonly maxDepth: number;\n  private readonly ignored: ReadonlySet<string>;\n\n  constructor(options: NodeTreeManifestOptions = {}) {\n    this.maxEntries = options.maxEntries ?? MAX_ENTRIES;\n    this.maxDepth = options.maxDepth ?? MAX_DEPTH;\n    this.ignored = options.ignoredDirectories ?? IGNORED_DIRECTORIES;\n  }\n\n  async take(root: string, exclude: readonly string[] = []): Promise<TreeManifest> {\n    const entries = new Map<string, string>();\n    const skipped = new Set(exclude.map((entry) => path.resolve(entry)));\n    const truncated = await this.walk(root, 0, entries, skipped);\n    return { entries, truncated };\n  }\n\n  async fingerprint(filePath: string): Promise<string | undefined> {\n    try {\n      const stat = await fs.stat(filePath);\n      return stat.isFile() ? fingerprintOf(stat.size, stat.mtimeMs) : undefined;\n    } catch {\n      return undefined;\n    }\n  }\n\n  async modifiedAt(filePath: string): Promise<number | undefined> {\n    try {\n      const stat = await fs.stat(filePath);\n      return stat.isFile() ? stat.mtimeMs : undefined;\n    } catch {\n      return undefined;\n    }\n  }\n\n  changed(before: TreeManifest, after: TreeManifest): string[] {\n    const moved = new Set<string>();\n    for (const [filePath, fingerprint] of after.entries) {\n      if (before.entries.get(filePath) !== fingerprint) moved.add(filePath);\n    }\n    for (const filePath of before.entries.keys()) {\n      if (!after.entries.has(filePath)) moved.add(filePath);\n    }\n    return [...moved].sort();\n  }\n\n  sizeChanged(before: string | undefined, after: string | undefined): boolean {\n    if (before === undefined || after === undefined) return false;\n    return sizeOf(before) !== sizeOf(after);\n  }\n  /** Fills `entries` depth-first and answers whether a cap cut the walk short. */\n  private async walk(\n    directory: string,\n    depth: number,\n    entries: Map<string, string>,\n    skipped: ReadonlySet<string>,\n  ): Promise<boolean> {\n    if (depth > this.maxDepth) return true;\n    let listing: Dirent[];\n    try {\n      listing = await fs.readdir(directory, { withFileTypes: true });\n    } catch {\n      // A directory that vanished or refused a read is not the walk's problem;\n      // the rest of the tree is still worth reporting.\n      return false;\n    }\n    let truncated = false;\n    for (const entry of listing) {\n      if (entries.size >= this.maxEntries) return true;\n      const entryPath = path.join(directory, entry.name);\n      if (skipped.has(entryPath)) continue;\n      // Symlinks are never followed: a link into a parent turns the walk into a\n      // cycle, and a link out of the tree reports a file this session does not own.\n      if (entry.isSymbolicLink()) continue;\n      if (entry.isDirectory()) {\n        if (this.ignored.has(entry.name)) continue;\n        truncated = (await this.walk(entryPath, depth + 1, entries, skipped)) || truncated;\n        continue;\n      }\n      if (!entry.isFile()) continue;\n      try {\n        const stat = await fs.stat(entryPath);\n        entries.set(entryPath, fingerprintOf(stat.size, stat.mtimeMs));\n      } catch {\n        // Raced with a delete between readdir and stat; it is simply not there.\n      }\n    }\n    return truncated;\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,gBAAgB;;AAGtB,MAAM,mBAAmB;AAkBzB,SAAS,WAAW,MAAwB;CAC1C,MAAM,aAAa,KAAK,WAAW,QAAQ,IAAI,CAAC,CAAC,WAAW,MAAM,IAAI;CACtE,OAAO,eAAe,KAAK,CAAC,IAAI,WAAW,MAAM,IAAI;AACvD;;AAGA,SAAS,aAAa,QAA2B,OAAkC;CACjF,MAAM,QAAQ,KAAK,IAAI,OAAO,QAAQ,MAAM,MAAM;CAClD,IAAI,QAAQ;CACZ,OAAO,QAAQ,SAAS,OAAO,WAAW,MAAM,QAAQ,SAAS;CACjE,OAAO;AACT;;AAGA,SAAS,aAAa,QAA2B,OAA0B,QAAwB;CACjG,MAAM,QAAQ,KAAK,IAAI,OAAO,QAAQ,MAAM,MAAM,IAAI;CACtD,IAAI,QAAQ;CACZ,OAAO,QAAQ,SAAS,OAAO,OAAO,SAAS,IAAI,WAAW,MAAM,MAAM,SAAS,IAAI,QAAQ,SAAS;CACxG,OAAO;AACT;;;;;AAMA,SAAS,SAAS,QAA2B,OAAuC;CAClF,MAAM,OAAO,OAAO,SAAS;CAC7B,MAAM,UAAU,MAAM,SAAS;CAC/B,MAAM,QAAQ,IAAI,YAAY,OAAO,OAAO;CAC5C,KAAK,IAAI,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,OAAO,GACjD,KAAK,IAAI,SAAS,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG;EAC5D,MAAM,QAAQ,MAAM,UAAU;EAC9B,MAAM,SACJ,OAAO,SAAS,MAAM,WACjB,MAAM,QAAQ,UAAU,MAAM,KAAK,IACpC,KAAK,IAAI,MAAM,QAAQ,YAAY,GAAG,MAAM,QAAQ,MAAM,CAAC;CACnE;CAEF,OAAO;AACT;;AAGA,SAAS,UACP,QACA,OACA,aACA,YACY;CACZ,MAAM,QAAQ,SAAS,QAAQ,KAAK;CACpC,MAAM,UAAU,MAAM,SAAS;CAC/B,MAAM,QAAoB,CAAC;CAC3B,IAAI,MAAM;CACV,IAAI,SAAS;CACb,OAAO,MAAM,OAAO,UAAU,SAAS,MAAM,QAAQ;EACnD,IAAI,OAAO,SAAS,MAAM,SAAS;GACjC,MAAM,KAAK;IAAE,QAAQ;IAAK,SAAS,MAAM,WAAW;IAAI,MAAM,aAAa;GAAO,CAAC;GACnF,OAAO;GACP,UAAU;GACV;EACF;EACA,KAAK,OAAO,MAAM,KAAK,UAAU,WAAW,OAAO,MAAM,MAAM,UAAU,SAAS,MAAM,IAAI;GAC1F,MAAM,KAAK;IAAE,QAAQ;IAAK,SAAS,OAAO,QAAQ;IAAI,MAAM,cAAc;GAAI,CAAC;GAC/E,OAAO;GACP;EACF;EACA,MAAM,KAAK;GAAE,QAAQ;GAAK,SAAS,MAAM,WAAW;GAAI,MAAM,aAAa;EAAO,CAAC;EACnF,UAAU;CACZ;CACA,OAAO,MAAM,OAAO,QAAQ;EAC1B,MAAM,KAAK;GAAE,QAAQ;GAAK,SAAS,OAAO,QAAQ;GAAI,MAAM,cAAc;EAAI,CAAC;EAC/E,OAAO;CACT;CACA,OAAO,SAAS,MAAM,QAAQ;EAC5B,MAAM,KAAK;GAAE,QAAQ;GAAK,SAAS,MAAM,WAAW;GAAI,MAAM,aAAa;EAAO,CAAC;EACnF,UAAU;CACZ;CACA,OAAO;AACT;;AAGA,SAAS,UACP,QACA,OACA,aACA,YACY;CACZ,OAAO,CACL,GAAG,OAAO,KAAK,SAAS,YAAY;EAAE,QAAQ;EAAc;EAAS,MAAM,cAAc;CAAO,EAAE,GAClG,GAAG,MAAM,KAAK,SAAS,YAAY;EAAE,QAAQ;EAAc;EAAS,MAAM,aAAa;CAAO,EAAE,CAClG;AACF;;AAGA,SAAS,QAAQ,OAAiD;CAChE,MAAM,OAAkB,MAAM,KAAK,EAAE,QAAQ,MAAM,OAAO,SAAS,KAAK;CACxE,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,QAAQ,GAAG;EAC3C,IAAI,KAAK,WAAW,KAAK;EACzB,MAAM,OAAO,KAAK,IAAI,GAAG,QAAQ,aAAa;EAC9C,MAAM,KAAK,KAAK,IAAI,MAAM,SAAS,GAAG,QAAQ,aAAa;EAC3D,KAAK,IAAI,SAAS,MAAM,UAAU,IAAI,UAAU,GAAG,KAAK,UAAU;CACpE;CAEA,MAAM,QAA6B,CAAC;CACpC,IAAI,OAA2B,CAAC;CAChC,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,QAAQ,GAAG;EAC3C,IAAI,CAAC,KAAK,QAAQ;GAChB,IAAI,KAAK,SAAS,GAAG;IACnB,MAAM,KAAK;KAAE,OAAO,KAAK,EAAE,EAAE,QAAQ;KAAG;IAAK,CAAC;IAC9C,OAAO,CAAC;GACV;GACA;EACF;EACA,KAAK,KAAK;GAAE,QAAQ,KAAK;GAAQ,MAAM,KAAK;GAAM,SAAS,KAAK;EAAQ,CAAC;CAC3E;CACA,IAAI,KAAK,SAAS,GAAG,MAAM,KAAK;EAAE,OAAO,KAAK,EAAE,EAAE,QAAQ;EAAG;CAAK,CAAC;CACnE,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,kBAAkB,OAA+B;CAC/D,OAAO,SAAS,IAAI,MAAM,SAAS,IAAI,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI,KAAK;AACvE;;;;;;;;AASA,SAAgB,SAAS,QAAgB,OAA+B;CACtE,MAAM,cAAc,WAAW,MAAM;CACrC,MAAM,aAAa,WAAW,KAAK;CACnC,MAAM,SAAS,aAAa,aAAa,UAAU;CACnD,MAAM,SAAS,aAAa,aAAa,YAAY,MAAM;CAC3D,MAAM,eAAe,YAAY,MAAM,QAAQ,YAAY,SAAS,MAAM;CAC1E,MAAM,cAAc,WAAW,MAAM,QAAQ,WAAW,SAAS,MAAM;CAEvE,MAAM,cAAc,aAAa,SAAS,YAAY,SAAS;CAC/D,MAAM,SAAS,cACX,UAAU,cAAc,aAAa,SAAS,GAAG,SAAS,CAAC,IAC3D,UAAU,cAAc,aAAa,SAAS,GAAG,SAAS,CAAC;CAE/D,MAAM,OAAmB,YACtB,MAAM,GAAG,MAAM,CAAC,CAChB,KAAK,SAAS,YAAY;EAAE,QAAQ;EAAc;EAAS,MAAM,SAAS;CAAE,EAAE;CACjF,MAAM,OAAmB,WACtB,MAAM,WAAW,SAAS,MAAM,CAAC,CACjC,KAAK,SAAS,YAAY;EAAE,QAAQ;EAAc;EAAS,MAAM,WAAW,SAAS,SAAS,SAAS;CAAE,EAAE;CAE9G,MAAM,QAAQ;EAAC,GAAG;EAAM,GAAG;EAAQ,GAAG;CAAI;CAC1C,OAAO;EACL,OAAO,QAAQ,KAAK;EACpB,WAAW,MAAM,QAAQ,SAAS,KAAK,WAAW,GAAG,CAAC,CAAC;EACvD,UAAU,MAAM,QAAQ,SAAS,KAAK,WAAW,GAAG,CAAC,CAAC;EACtD;CACF;AACF;;;ACpMA,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,YAAY;AAwClB,SAAS,YAAY,OAAgB,KAAiC;CACpE,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,KAAA;CAChD,MAAM,QAAS,MAAkC;CACjD,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;AAC7C;;;;;;;;AAmBA,MAAM,wBAAwB;AAE9B,IAAa,cAAb,MAAiD;CAqC5B;CACA;CACA;CAtCnB,0BAA2B,IAAI,IAAyB;;CAExD,4BAA6B,IAAI,IAAoB;;;;;;CAMrD;;;;;;CAMA,WAAsC,CAAC;;;;;;CAMvC;;;;;CAKA,2BAA4B,IAAI,IAAoB;CACpD;CACA;;;;;;CAMA,WAAkC,QAAQ,QAAQ;CAElD,YACE,UACA,WACA,WACA,UAA8B,CAAC,GAC/B;EAJiB,KAAA,WAAA;EACA,KAAA,YAAA;EACA,KAAA,YAAA;EAGjB,KAAK,MAAM,QAAQ,OAAO,KAAK;EAC/B,KAAK,MAAM,QAAQ;CACrB;;;;;CAMA,MAAM,UAAsF,CAAC,GAAS;EACpG,KAAK,QAAQ,MAAM;EACnB,KAAK,UAAU,MAAM;EACrB,KAAK,SAAS,MAAM;EACpB,KAAK,WAAW,KAAA;EAChB,KAAK,WAAW,QAAQ,QAAQ;EAChC,KAAK,WAAW,QAAQ,WAAW,CAAC;EACpC,KAAK,YAAY,QAAQ;CAC3B;;;;;CAMA,MAAM,QAAuB;EAC3B,MAAM,KAAK;CACb;CACA,MAAM,MAAM,IAAY,MAAc,MAAe,KAA4B;EAG/E,MAAM,KAAK;EACX,IAAI,SAAS,aAAa,SAAS,YAAY;GAC7C,MAAM,WAAW,YAAY,MAAM,MAAM;GACzC,IAAI,CAAC,UAAU;GACf,MAAM,WAAWA,UAAAA,QAAK,QAAQ,KAAK,QAAQ;GAI3C,MAAM,CAAC,QAAQ,eAAe,MAAM,QAAQ,IAAI,CAC9C,KAAK,UAAU,QAAQ,QAAQ,GAC/B,KAAK,UAAU,YAAY,QAAQ,CACrC,CAAC;GACD,KAAK,QAAQ,IAAI,IAAI;IAAE;IAAM;IAAU;IAAQ,SAAS,gBAAgB,KAAA;GAAU,CAAC;GACnF;EACF;EACA,IAAI,SAAS,WAAW;EAGxB,KAAK,UAAU,IAAI,IAAI,KAAK,IAAI,CAAC;EAGjC,KAAK,aAAa,MAAM,KAAK,UAAU,KAAK,KAAK,KAAK,QAAQ;CAChE;CAEA,MAAM,IAAI,IAAY,SAAkB,KAA4B;EAClE,MAAM,UAAU,KAAK,QAAQ,IAAI,EAAE;EACnC,KAAK,QAAQ,OAAO,EAAE;EACtB,MAAM,YAAY,KAAK,UAAU,IAAI,EAAE;EACvC,KAAK,UAAU,OAAO,EAAE;EACxB,IAAI,SAAS;GAGX,IAAI,CAAC,SAAS,MAAM,KAAK,WAAW,OAAO;GAC3C;EACF;EAIA,IAAI,cAAc,KAAA,GAAW;EAK7B,KAAK,WAAW,KAAK,SAAS,KAAK,YAAY;GAC7C,IAAI;IACF,MAAM,KAAK,WAAW,KAAK,SAAS;GACtC,QAAQ,CAER;EACF,CAAC;CACH;;CAGA,MAAc,WAAW,SAAqC;EAC5D,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,QAAQ,QAAQ;EAC3D,MAAM,UAAU,CAAC,QAAQ;EACzB,MAAM,SAAS,MAAM,KAAK,aAAa,QAAQ,QAAQ,OAAO,OAAO;EACrE,IAAI,UAAU,KAAA,GAAW,KAAK,SAAS,IAAI,QAAQ,UAAU,KAAK;EAClE,MAAM,KAAK,OAAO;GAChB,SAAS;GACT,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd,IAAI,KAAK,IAAI;GACb,QAAQ;GACR,GAAI,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;GACjE,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;GACvC,GAAI,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;GACnC,GAAG;EACL,CAAC;EAGD,MAAM,KAAK,SAAS,QAAQ,QAAQ;CACtC;;CAGA,MAAc,WAAW,KAAa,WAAkC;EACtE,MAAM,SAAS,KAAK;EACpB,IAAI,WAAW,KAAA,GAAW;EAC1B,MAAM,QAAQ,MAAM,KAAK,UAAU,KAAK,KAAK,KAAK,QAAQ;EAC1D,KAAK,WAAW;EAChB,MAAM,WAAW,KAAK;EACtB,MAAM,QAAQ,KAAK,UAChB,QAAQ,QAAQ,KAAK,CAAC,CACtB,QAAQ,aAAa,aAAa,KAAA,KAAa,CAAC,SAAS,QAAQ,CAAC;EACrE,MAAM,aAAa,MAAM,KAAK,cAAc,OAAO,SAAS;EAC5D,IAAI,WAAW,WAAW,GAAG;EAC7B,MAAM,YAAY,MAAM,KAAK,eAAe,KAAK,UAAU;EAC3D,KAAK,MAAM,YAAY,YAAY;GACjC,MAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ;GAGxC,IAAI,UAAU,KAAA,KAAa,UAAU,IAAI,QAAQ,GAAG;GACpD,MAAM,cAAc,OAAO,QAAQ,IAAI,QAAQ;GAC/C,MAAM,aAAa,MAAM,QAAQ,IAAI,QAAQ;GAG7C,MAAM,WAAW,eAAe,KAAA,IAAY,KAAA,IAAY,MAAM,KAAK,UAAU,QAAQ,QAAQ;GAC7F,IAAI,aAAa,KAAA,GAAW,KAAK,SAAS,IAAI,UAAU,QAAQ;GAGhE,IAAI,aAAa,KAAA,KAAa,aAAa,OAAO;GAClD,MAAM,SACJ,gBAAgB,KAAA,KAChB,eAAe,KAAA,KACf,KAAK,UAAU,YAAY,aAAa,UAAU,KACjD,UAAU,KAAA,KAAa,aAAa,KAAA,KAAa,aAAa;GACjE,MAAM,KAAK,OAAO;IAChB,SAAS;IACT,MAAM;IACN,MAAM;IACN,IAAI,KAAK,IAAI;IACb,QAAQ;IACR,GAAI,SAAS,EAAE,UAAU,KAAK,IAAI,CAAC;IACnC,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,SAAS;GACtD,CAAC;EACH;CACF;;;;;;;;;;;CAYA,MAAc,cAAc,YAA+B,WAAsC;EAC/F,MAAM,QAAQ,YAAY;EAC1B,MAAM,UAAoB,CAAC;EAC3B,KAAK,MAAM,YAAY,YAAY;GACjC,MAAM,aAAa,MAAM,KAAK,UAAU,WAAW,QAAQ;GAC3D,IAAI,eAAe,KAAA,KAAa,cAAc,OAAO,QAAQ,KAAK,QAAQ;EAC5E;EACA,OAAO;CACT;;CAGA,MAAc,eAAe,KAAa,YAA6D;EACrG,MAAM,SAAS,WAAW,QAAQ,aAAa,CAAC,KAAK,SAAS,IAAI,QAAQ,CAAC;EAC3E,IAAI,KAAK,QAAQ,KAAA,KAAa,OAAO,WAAW,GAAG,uBAAO,IAAI,IAAI;EAClE,OAAO,KAAK,IAAI,UAAU,KAAK,MAAM;CACvC;;CAGA,MAAc,aACZ,QACA,OACA,SACoD;EACpD,IAAI,UAAU,KAAA,GAAW,OAAO,CAAC;EACjC,IAAI,WAAW,KAAA,GAAW;GAIxB,IAAI,CAAC,SAAS,OAAO,CAAC;GACtB,MAAM,cAAc,MAAM,KAAK,UAAU,KAAK,KAAK;GACnD,IAAI,gBAAgB,KAAA,GAAW,OAAO,CAAC;GACvC,MAAM,QAAQ,kBAAkB,WAAW;GAC3C,OAAO;IAAE,WAAW,MAAM;IAAW,UAAU,MAAM;GAAS;EAChE;EACA,IAAI,WAAW,OAAO,OAAO;GAAE,WAAW;GAAG,UAAU;EAAE;EACzD,MAAM,CAAC,YAAY,aAAa,MAAM,QAAQ,IAAI,CAAC,KAAK,UAAU,KAAK,MAAM,GAAG,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC;EAC3G,IAAI,eAAe,KAAA,KAAa,cAAc,KAAA,GAAW,OAAO,CAAC;EACjE,MAAM,OAAO,SAAS,YAAY,SAAS;EAC3C,OAAO;GAAE,WAAW,KAAK;GAAW,UAAU,KAAK;EAAS;CAC9D;;CAGA,MAAc,OAAO,OAAqC;EACxD,IAAI,MAAM,WAAW,KAAA,KAAa,MAAM,WAAW,MAAM,OAAO;EAChE,MAAM,KAAK,SAAS,OAAO,KAAK;CAClC;;;;;;;;;CAUA,MAAc,SAAS,UAAiC;EACtD,IAAI,KAAK,aAAa,KAAA,GAAW;EACjC,MAAM,UAAU,IAAI,IAAI,KAAK,SAAS,OAAO;EAC7C,MAAM,cAAc,MAAM,KAAK,UAAU,YAAY,QAAQ;EAC7D,IAAI,gBAAgB,KAAA,GAAW,QAAQ,OAAO,QAAQ;OACjD,QAAQ,IAAI,UAAU,WAAW;EACtC,KAAK,WAAW;GAAE;GAAS,WAAW,KAAK,SAAS;EAAU;CAChE;AACF;;;;ACvUA,MAAM,kBAAkB;AACxB,MAAM,kBAAkB,CAAC,OAAO,OAAO;AAEvC,SAAS,KAAK,OAAuB;CACnC,QAAA,GAAOC,YAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;AACrE;AAEA,IAAa,gBAAb,MAAqD;CACnD,WAAW,WAAmB,MAAyB,QAAQ,KAAa;EAC1E,IAAI,IAAIC,oCAAAA,qBAAqB;GAC3B,MAAM,SAAS,IAAIC,oCAAAA;GACnB,IAAI,QAAQ,OAAO;EACrB;EACA,OAAO;CACT;;;;;;;;;;;;;CAcA,iBAAyB;EACvB,MAAM,aAAa,QAAQ,IAAI,qBAAqB,KAAK;EACzD,MAAM,OACJ,eAAe,KAAA,KAAa,eAAe,KAAKC,UAAAA,QAAK,KAAKC,QAAAA,QAAG,QAAQ,GAAG,GAAG,eAAe,IAAI;EAChG,OAAOD,UAAAA,QAAK,KAAK,MAAM,eAAe;CACxC;;;;;;CAOA,aAAa,KAAa,YAA4B;EACpD,MAAM,YAAY,KAAK,eAAe;EACtC,QAAA,QAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;EAC3C,OAAOA,UAAAA,QAAK,KAAK,WAAW,GAAG,KAAKE,QAAAA,QAAG,aAAa,GAAG,CAAC,EAAE,GAAG,KAAK,UAAU,EAAE,OAAO;CACvF;;;;;CAMA,cAAc,KAAa,YAA4B;EACrD,OAAO,GAAG,KAAK,aAAa,KAAK,UAAU,CAAC,CAAC,QAAQ,aAAa,EAAE,EAAE;CACxE;CAEA,qBAAqB,KAAiC;EACpD,MAAM,SAAS,KAAK,mBAAmB,GAAG;EAC1C,OAAO,WAAW,KAAA,IAAY,KAAA,IAAYF,UAAAA,QAAK,KAAK,QAAQ,eAAe;CAC7E;;CAGA,mBAA2B,KAAiC;EAC1D,IAAI;GAMF,QAAA,GALeG,mBAAAA,aAAAA,CAAa,OAAO;IAAC;IAAa;IAA0B;GAAkB,GAAG;IAC9F;IACA,UAAU;IACV,OAAO;KAAC;KAAU;KAAQ;IAAQ;GACpC,CAAC,CAAC,CAAC,KACS,KAAK,KAAA;EACnB,SAAS,OAAO;GACd,IAAI,iBAAiB,OAAO,OAAO,KAAA;GACnC,MAAM;EACR;CACF;AACF;;;;;;;;;;;;;;;;AChEA,MAAM,QAAQ;AACd,MAAM,aAAa;AAEnB,MAAM,OAAA,GAAMC,UAAAA,UAAAA,CAAUC,mBAAAA,QAAQ;AAE9B,SAAS,QAAW,QAAsB,MAAqB;CAC7D,MAAM,SAAgB,CAAC;CACvB,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,MAAM,OAAO,KAAK,OAAO,MAAM,OAAO,QAAQ,IAAI,CAAC;CACvG,OAAO;AACT;AAEA,SAAS,aAAa,QAA0B;CAC9C,OAAO,OAAO,MAAM,IAAI,CAAC,CAAC,QAAQ,UAAU,UAAU,EAAE;AAC1D;;;;;;AAOA,SAAS,YAAY,QAA0B;CAC7C,OAAO,aAAa,MAAM,CAAC,CAAC,KAAK,WAAY,OAAO,SAAS,KAAK,OAAO,OAAO,MAAM,OAAO,MAAM,CAAC,IAAI,MAAO;AACjH;AAEA,SAAS,SAAS,MAAc,UAA2B;CACzD,MAAM,WAAWC,UAAAA,QAAK,SAAS,MAAM,QAAQ;CAC7C,OAAO,aAAa,MAAM,CAAC,SAAS,WAAW,IAAI,KAAK,CAACA,UAAAA,QAAK,WAAW,QAAQ;AACnF;AAEA,IAAa,uBAAb,MAA2D;CACzD,MAAM,UAAU,KAAa,WAA4D;EACvF,MAAM,wBAAQ,IAAI,IAAY;EAC9B,IAAI,UAAU,WAAW,GAAG,OAAO;EACnC,MAAM,OAAO,MAAM,KAAK,SAAS,GAAG;EACpC,IAAI,SAAS,KAAA,GAAW,OAAO;EAE/B,KAAK,MAAM,SAAS,QAClB,UAAU,QAAQ,aAAa,SAAS,MAAM,QAAQ,CAAC,GACvD,KACF,GAAG;GACD,MAAM,WAAW,MAAM,KAAK,aAAaA,UAAAA,QAAK,SAAS,MAAM,QAAQ,CAAC;GACtE,MAAM,UAAU,MAAM,KAAK,IAAI,MAAM;IAAC;IAAY;IAAM;IAAM,GAAG;GAAQ,CAAC;GAC1E,IAAI,YAAY,KAAA,GAAW;GAC3B,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM;IAAC;IAAU;IAAe;IAAM;IAAwB;IAAM,GAAG;GAAQ,CAAC;GAC7G,IAAI,UAAU,KAAA,GAAW;GACzB,MAAM,QAAQ,IAAI,IAAI,YAAY,KAAK,CAAC;GACxC,KAAK,MAAM,SAAS,aAAa,OAAO,GACtC,IAAI,CAAC,MAAM,IAAI,KAAK,GAAG,MAAM,IAAIA,UAAAA,QAAK,QAAQ,MAAM,KAAK,CAAC;EAE9D;EACA,OAAO;CACT;;CAGA,MAAc,SAAS,KAA0C;EAE/D,MAAM,QAAO,MADQ,KAAK,IAAI,KAAK,CAAC,aAAa,iBAAiB,CAAC,EAAA,EAC9C,KAAK;EAC1B,OAAO,SAAS,KAAA,KAAa,SAAS,KAAK,KAAA,IAAYA,UAAAA,QAAK,QAAQ,IAAI;CAC1E;;CAGA,MAAc,IAAI,KAAa,MAAsD;EACnF,IAAI;GACF,MAAM,EAAE,WAAW,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG;IAAE;IAAK,UAAU;IAAQ,WAAW;GAAW,CAAC;GAC/F,OAAO;EACT,QAAQ;GACN;EACF;CACF;AACF;;ACnEA,MAAM,sBAAsB;AAE5B,MAAM,gCAAgB,IAAI,IAAI;CAAC;CAAU;CAAW;CAAU;AAAc,CAAC;AAE7E,SAASC,UAAQ,OAAgB,OAAqC;CACpE,OAAO,iBAAiB,SAAS,UAAU,SAAS,OAAO,MAAM,SAAS,YAAY,MAAM,IAAI,MAAM,IAAI;AAC5G;AAEA,IAAa,2BAAb,MAAmE;CACjE;CAEA,WAAW,WAAyB;EAClC,KAAK,YAAY;CACnB;CAEA,MAAM,QAAQ,UAA+C;EAC3D,IAAI;EACJ,IAAI;GACF,MAAM,MAAMC,iBAAAA,QAAG,SAAS,QAAQ;EAClC,SAAS,OAAO;GACd,IAAID,UAAQ,OAAO,aAAa,GAAG,OAAO,KAAA;GAC1C,MAAM;EACR;EACA,IAAI,IAAI,aAAA,SAAiC,OAAO,KAAA;EAChD,IAAI,IAAI,SAAS,GAAG,mBAAmB,CAAC,CAAC,SAAS,CAAC,GAAG,OAAO,KAAA;EAC7D,OAAO,KAAK,IAAI,IAAI,SAAS,MAAM,CAAC;CACtC;CAEA,MAAM,IAAI,SAAkC;EAC1C,MAAM,QAAA,GAAOE,YAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,SAAS,MAAM,CAAC,CAAC,OAAO,KAAK;EACtE,MAAM,WAAWC,UAAAA,QAAK,KAAK,KAAK,iBAAiB,GAAG,IAAI;EAGxD,IAAI;GACF,MAAMF,iBAAAA,QAAG,OAAO,QAAQ;GACxB,OAAO;EACT,SAAS,OAAO;GACd,IAAI,CAACD,UAAQ,OAAO,aAAa,GAAG,MAAM;EAC5C;EACA,MAAMC,iBAAAA,QAAG,MAAM,KAAK,iBAAiB,GAAG,EAAE,WAAW,KAAK,CAAC;EAC3D,MAAMA,iBAAAA,QAAG,UAAU,UAAU,SAAS,MAAM;EAC5C,OAAO;CACT;CAEA,MAAM,KAAK,MAA2C;EACpD,IAAI,CAAC,kBAAkB,KAAK,IAAI,GAAG,OAAO,KAAA;EAC1C,IAAI;GACF,OAAO,MAAMA,iBAAAA,QAAG,SAASE,UAAAA,QAAK,KAAK,KAAK,iBAAiB,GAAG,IAAI,GAAG,MAAM;EAC3E,SAAS,OAAO;GACd,IAAIH,UAAQ,OAAO,aAAa,GAAG,OAAO,KAAA;GAC1C,MAAM;EACR;CACF;CAEA,MAAM,QAAuB;EAC3B,IAAI,KAAK,cAAc,KAAA,GAAW;EAClC,MAAMC,iBAAAA,QAAG,GAAG,KAAK,WAAW;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;CAC9D;CAEA,mBAAmC;EACjC,IAAI,KAAK,cAAc,KAAA,GAAW,MAAM,IAAI,MAAM,mCAAmC;EACrF,OAAO,KAAK;CACd;AACF;;;ACrEA,MAAM,wBAAQ,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAQ;AAAM,CAAC;AAEvD,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,eAAe,OAAoC;CAC1D,OAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ,KAAA;AAC7D;AAEA,SAAS,cAAc,OAAoC;CACzD,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,QAAQ,KAAA;AACrF;;AAGA,SAAgB,mBAAmB,OAAyC;CAC1E,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;CAC7B,MAAM,EAAE,SAAS,MAAM,UAAU,MAAM,OAAO;CAC9C,IAAI,OAAO,aAAa,YAAY,aAAa,IAAI,OAAO;CAC5D,IAAI,OAAO,OAAO,YAAY,CAAC,OAAO,SAAS,EAAE,GAAG,OAAO;CAC3D,IAAI,OAAO,SAAS,YAAY,CAAC,MAAM,IAAI,IAAI,GAAG,OAAO;CAEzD,IAAI,YAAY,GAAG;EACjB,IAAI,SAAS,QAAQ,OAAO;EAC5B,OAAO;GAAE,SAAS;GAAG,MAAM;GAAgB;GAAqC;EAAG;CACrF;CACA,IAAI,YAAY,GAAG,OAAO;CAE1B,OAAO;EACL,SAAS;EACT,MAAM;EACA;EACN;EACA,QANa,MAAM,WAAW,SAAS,SAAS;EAOhD,GAAI,eAAe,MAAM,MAAM,MAAM,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAiB;EACvF,GAAI,eAAe,MAAM,KAAK,MAAM,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,MAAM,MAAgB;EACpF,GAAI,cAAc,MAAM,SAAS,MAAM,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAoB;EAC/F,GAAI,cAAc,MAAM,QAAQ,MAAM,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAmB;EAC5F,GAAI,MAAM,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;EACpD,GAAI,MAAM,YAAY,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;CACpD;AACF;;AAGA,SAAgB,cAAc,SAAiB,aAA0D;CACvG,MAAM,SAA6B,CAAC;CACpC,KAAK,MAAM,QAAQ,QAAQ,MAAM,IAAI,GAAG;EACtC,IAAI,SAAS,IAAI;EACjB,IAAI;EACJ,IAAI;GACF,SAAS,KAAK,MAAM,IAAI;EAC1B,QAAQ;GACN,cAAc,IAAI;GAClB;EACF;EACA,MAAM,QAAQ,mBAAmB,MAAM;EACvC,IAAI,UAAU,MAAM,cAAc,IAAI;OACjC,OAAO,KAAK,KAAK;CACxB;CACA,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,kBAAkB,OAAkC;CAClE,IAAI,MAAM,YAAY,GAAG,OAAO,MAAM,SAAS;CAC/C,OAAO,MAAM,WAAW,UAAU,MAAM,aAAa;AACvD;;AAGA,SAAgB,iBAAiB,QAAyD;CACxF,OAAO,OAAO,OAAO,iBAAiB;AACxC;;AAEA,SAAgB,YAAY,QAAsD;CAChF,MAAM,yBAAS,IAAI,IAA2B;CAC9C,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,UAAU,OAAO,IAAI,MAAM,IAAI;EACrC,OAAO,IAAI,MAAM,MAAM;GACrB,MAAM,MAAM;GACZ,MAAM,MAAM,OAAO,SAAS,MAAM,KAAK,MAAM,OAAQ,SAAS,QAAQ,MAAM;GAC5E,IAAI,KAAK,IAAI,MAAM,IAAI,SAAS,MAAM,CAAC;GACvC,QAAQ,SAAS,SAAS,KAAK;EACjC,CAAC;CACH;CACA,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,UAAU,MAAM,KAAK,KAAK,EAAE;AACtE;;AAGA,SAAgB,aAAa,QAAqC,UAAqC;CACrG,OAAO,OACJ,QAAQ,UAAU,MAAM,SAAS,QAAQ,CAAC,CAC1C,MAAM,MAAM,UAAU,KAAK,KAAK,MAAM,EAAE,CAAC,CACzC,KAAK,OAAO,WAAW;EACtB,MAAM,UAA2B;GAC/B,OAAO,SAAS;GAChB,MAAM,MAAM;GACZ,IAAI,MAAM;GACV,QAAQ,MAAM,YAAY,IAAI,MAAM,SAAS;EAC/C;EACA,IAAI,MAAM,YAAY,GAAG,OAAO;EAChC,OAAO;GACL,GAAG;GACH,GAAI,MAAM,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAO;GAC7D,GAAI,MAAM,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,MAAM,MAAM;GAC1D,GAAI,MAAM,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;GACtE,GAAI,MAAM,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;GACnE,GAAI,MAAM,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;GACpD,GAAI,MAAM,YAAY,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;EACpD;CACF,CAAC;AACL;;;;;;;;;AAUA,SAAgB,WAAW,UAA+C;CACxE,OAAO,SAAS,MAAM,YAAY,QAAQ,WAAW,KAAA,KAAa,QAAQ,YAAY,IAAI;AAC5F;;AAGA,SAAgB,WAAW,UAA0D;CACnF,OAAO,SAAS,MAAM,YAAY,QAAQ,WAAW,KAAA,CAAS,CAAC,EAAE;AACnE;;;ACjJA,MAAM,gBAAgB;AACtB,MAAM,eAAe;;;;;;;;AAQrB,MAAM,gBAAgB;AAEtB,SAAS,QAAQ,OAAgB,MAAuB;CACtD,OAAO,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS;AACrE;AAEA,IAAa,gBAAb,MAAqD;CACnD;CAEA,WAAW,UAAwB;EACjC,KAAK,WAAW;CAClB;CAEA,MAAM,OAAO,OAAqC;EAChD,MAAM,KAAK,SAAS,YAAYG,iBAAAA,QAAG,WAAW,KAAK,YAAY,GAAG,GAAG,KAAK,UAAU,KAAK,EAAE,KAAK,MAAM,CAAC;CACzG;CAEA,MAAM,OAAiC;EAErC,OAAO,YAAY,iBAAiB,MAAM,KAAK,OAAO,CAAC,CAAC;CAC1D;CAEA,MAAM,SAAS,UAA8C;EAG3D,OAAO,aAAa,iBAAiB,MAAM,KAAK,OAAO,CAAC,GAAG,QAAQ;CACrE;CAEA,MAAM,QAAuB;EAC3B,IAAI;GACF,MAAMA,iBAAAA,QAAG,OAAO,KAAK,YAAY,CAAC;EACpC,SAAS,OAAO;GACd,IAAI,CAAC,QAAQ,OAAO,QAAQ,GAAG,MAAM;EACvC;CACF;;CAGA,MAAc,SAAsC;EAClD,IAAI;EACJ,IAAI;GACF,UAAU,MAAMA,iBAAAA,QAAG,SAAS,KAAK,YAAY,GAAG,MAAM;EACxD,SAAS,OAAO;GACd,IAAI,QAAQ,OAAO,QAAQ,GAAG,OAAO,CAAC;GACtC,MAAM;EACR;EACA,OAAO,cAAc,UAAU,SAC7B,QAAQ,KAAK,+CAA+C,KAAK,MAAM,GAAG,GAAG,GAAG,CAClF;CACF;CAEA,cAA8B;EAC5B,IAAI,CAAC,KAAK,UAAU,MAAM,IAAI,MAAM,mCAAmC;EACvE,OAAO,KAAK;CACd;CAEA,MAAc,SAAY,WAAyC;EACjE,MAAM,WAAW,GAAG,KAAK,YAAY,EAAE;EACvC,MAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ;EACxC,IAAI;GACF,OAAO,MAAM,UAAU;EACzB,UAAU;GACR,MAAM,KAAK,MAAM;GACjB,MAAM,KAAK,QAAQ,QAAQ;EAC7B;CACF;;CAGA,MAAc,QAAQ,UAAuC;EAC3D,KAAK,IAAI,UAAU,GAAG,UAAU,cAAc,WAAW,GACvD,IAAI;GACF,OAAO,MAAMA,iBAAAA,QAAG,KAAK,UAAU,IAAI;EACrC,SAAS,OAAO;GACd,IAAI,CAAC,QAAQ,OAAO,QAAQ,GAAG,MAAM;GACrC,IAAI,MAAM,KAAK,WAAW,QAAQ,GAAG;GACrC,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,aAAa,CAAC;EACnE;EAEF,MAAM,IAAI,MAAM,qCAAqC,UAAU;CACjE;;CAGA,MAAc,WAAW,UAAoC;EAC3D,IAAI;GACF,MAAM,QAAQ,MAAMA,iBAAAA,QAAG,KAAK,QAAQ;GACpC,IAAI,KAAK,IAAI,IAAI,MAAM,UAAU,eAAe,OAAO;GACvD,MAAMA,iBAAAA,QAAG,OAAO,QAAQ;GACxB,OAAO;EACT,SAAS,OAAO;GAEd,IAAI,QAAQ,OAAO,QAAQ,GAAG,OAAO;GACrC,MAAM;EACR;CACF;CAEA,MAAc,QAAQ,UAAiC;EACrD,IAAI;GACF,MAAMA,iBAAAA,QAAG,OAAO,QAAQ;EAC1B,SAAS,OAAO;GACd,IAAI,CAAC,QAAQ,OAAO,QAAQ,GAAG,QAAQ,KAAK,mCAAmC,OAAO,KAAK,GAAG;EAChG;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;ACtFA,MAAa,sCAA2C,IAAI,IAAI;CAC9D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;AAUD,SAAS,cAAc,MAAc,YAA4B;CAC/D,OAAO,GAAG,KAAK,GAAG;AACpB;;AAGA,SAAS,OAAO,aAA6B;CAC3C,MAAM,YAAY,YAAY,QAAQ,GAAG;CACzC,OAAO,cAAc,KAAK,cAAc,YAAY,MAAM,GAAG,SAAS;AACxE;AAQA,IAAa,0BAAb,MAAiE;CAC/D;CACA;CACA;CAEA,YAAY,UAAmC,CAAC,GAAG;EACjD,KAAK,aAAa,QAAQ,cAAA;EAC1B,KAAK,WAAW,QAAQ,YAAA;EACxB,KAAK,UAAU,QAAQ,sBAAsB;CAC/C;CAEA,MAAM,KAAK,MAAc,UAA6B,CAAC,GAA0B;EAC/E,MAAM,0BAAU,IAAI,IAAoB;EACxC,MAAM,UAAU,IAAI,IAAI,QAAQ,KAAK,UAAUC,UAAAA,QAAK,QAAQ,KAAK,CAAC,CAAC;EAEnE,OAAO;GAAE;GAAS,WAAA,MADM,KAAK,KAAK,MAAM,GAAG,SAAS,OAAO;EAC/B;CAC9B;CAEA,MAAM,YAAY,UAA+C;EAC/D,IAAI;GACF,MAAM,OAAO,MAAMC,iBAAAA,QAAG,KAAK,QAAQ;GACnC,OAAO,KAAK,OAAO,IAAI,cAAc,KAAK,MAAM,KAAK,OAAO,IAAI,KAAA;EAClE,QAAQ;GACN;EACF;CACF;CAEA,MAAM,WAAW,UAA+C;EAC9D,IAAI;GACF,MAAM,OAAO,MAAMA,iBAAAA,QAAG,KAAK,QAAQ;GACnC,OAAO,KAAK,OAAO,IAAI,KAAK,UAAU,KAAA;EACxC,QAAQ;GACN;EACF;CACF;CAEA,QAAQ,QAAsB,OAA+B;EAC3D,MAAM,wBAAQ,IAAI,IAAY;EAC9B,KAAK,MAAM,CAAC,UAAU,gBAAgB,MAAM,SAC1C,IAAI,OAAO,QAAQ,IAAI,QAAQ,MAAM,aAAa,MAAM,IAAI,QAAQ;EAEtE,KAAK,MAAM,YAAY,OAAO,QAAQ,KAAK,GACzC,IAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,GAAG,MAAM,IAAI,QAAQ;EAEtD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK;CACzB;CAEA,YAAY,QAA4B,OAAoC;EAC1E,IAAI,WAAW,KAAA,KAAa,UAAU,KAAA,GAAW,OAAO;EACxD,OAAO,OAAO,MAAM,MAAM,OAAO,KAAK;CACxC;;CAEA,MAAc,KACZ,WACA,OACA,SACA,SACkB;EAClB,IAAI,QAAQ,KAAK,UAAU,OAAO;EAClC,IAAI;EACJ,IAAI;GACF,UAAU,MAAMA,iBAAAA,QAAG,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;EAC/D,QAAQ;GAGN,OAAO;EACT;EACA,IAAI,YAAY;EAChB,KAAK,MAAM,SAAS,SAAS;GAC3B,IAAI,QAAQ,QAAQ,KAAK,YAAY,OAAO;GAC5C,MAAM,YAAYD,UAAAA,QAAK,KAAK,WAAW,MAAM,IAAI;GACjD,IAAI,QAAQ,IAAI,SAAS,GAAG;GAG5B,IAAI,MAAM,eAAe,GAAG;GAC5B,IAAI,MAAM,YAAY,GAAG;IACvB,IAAI,KAAK,QAAQ,IAAI,MAAM,IAAI,GAAG;IAClC,YAAa,MAAM,KAAK,KAAK,WAAW,QAAQ,GAAG,SAAS,OAAO,KAAM;IACzE;GACF;GACA,IAAI,CAAC,MAAM,OAAO,GAAG;GACrB,IAAI;IACF,MAAM,OAAO,MAAMC,iBAAAA,QAAG,KAAK,SAAS;IACpC,QAAQ,IAAI,WAAW,cAAc,KAAK,MAAM,KAAK,OAAO,CAAC;GAC/D,QAAQ,CAER;EACF;EACA,OAAO;CACT;AACF"}