@zaly/agent 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/{agent-DlhEEMPU.mjs → agent-GXRF7DUP.mjs} +7 -11
  2. package/dist/agent-GXRF7DUP.mjs.map +1 -0
  3. package/dist/{bash-DSy03sAj.mjs → bash-CB_VXpyd.mjs} +2 -2
  4. package/dist/{bash-DSy03sAj.mjs.map → bash-CB_VXpyd.mjs.map} +1 -1
  5. package/dist/{compactions-BpvQk4CG.mjs → compactions-92bMlcxJ.mjs} +3 -3
  6. package/dist/{compactions-BpvQk4CG.mjs.map → compactions-92bMlcxJ.mjs.map} +1 -1
  7. package/dist/{edit-DT672zIy.mjs → edit-gkb6MCW-.mjs} +2 -2
  8. package/dist/{edit-DT672zIy.mjs.map → edit-gkb6MCW-.mjs.map} +1 -1
  9. package/dist/{fetch-BrtIqrid.mjs → fetch-D_GzL2yy.mjs} +4 -4
  10. package/dist/{fetch-BrtIqrid.mjs.map → fetch-D_GzL2yy.mjs.map} +1 -1
  11. package/dist/{find-B-vvdlHu.mjs → find-DlrYUTXT.mjs} +2 -2
  12. package/dist/{find-B-vvdlHu.mjs.map → find-DlrYUTXT.mjs.map} +1 -1
  13. package/dist/{grep-rvZ5S319.mjs → grep-BI8Rou2q.mjs} +2 -2
  14. package/dist/{grep-rvZ5S319.mjs.map → grep-BI8Rou2q.mjs.map} +1 -1
  15. package/dist/{html-VrAsoGBK.mjs → html-B-Lr-9W6.mjs} +9457 -4826
  16. package/dist/html-B-Lr-9W6.mjs.map +1 -0
  17. package/dist/{index-node-esm-BwaOzhXB.mjs → index-node-esm-75XSYyIw.mjs} +16 -13
  18. package/dist/index-node-esm-75XSYyIw.mjs.map +1 -0
  19. package/dist/index.d.mts +11 -4
  20. package/dist/index.d.mts.map +1 -1
  21. package/dist/index.mjs +2 -2
  22. package/dist/{manager-1zEE5WiA.mjs → manager-CEociHy_.mjs} +2 -2
  23. package/dist/{manager-1zEE5WiA.mjs.map → manager-CEociHy_.mjs.map} +1 -1
  24. package/dist/{masker-B97uwYXG.mjs → masker-DWuL2Fjs.mjs} +16 -5
  25. package/dist/{masker-B97uwYXG.mjs.map → masker-DWuL2Fjs.mjs.map} +1 -1
  26. package/dist/{read-C5keKntU.mjs → read-DLtNq4XJ.mjs} +2 -2
  27. package/dist/{read-C5keKntU.mjs.map → read-DLtNq4XJ.mjs.map} +1 -1
  28. package/dist/{registry-CntkeXlo.mjs → registry-7mJQhyBA.mjs} +3 -3
  29. package/dist/{registry-CntkeXlo.mjs.map → registry-7mJQhyBA.mjs.map} +1 -1
  30. package/dist/{rolldown-runtime-DYf_mQCB.mjs → rolldown-runtime-BVN1G_yT.mjs} +4 -4
  31. package/dist/{session-CUE48QWX.mjs → session-C5ra-Hi1.mjs} +2 -2
  32. package/dist/{session-CUE48QWX.mjs.map → session-C5ra-Hi1.mjs.map} +1 -1
  33. package/dist/{session-DY9mF9Vb.d.mts → session-WtXqtAaq.d.mts} +2 -2
  34. package/dist/{session-DY9mF9Vb.d.mts.map → session-WtXqtAaq.d.mts.map} +1 -1
  35. package/dist/session.d.mts +1 -1
  36. package/dist/session.mjs +1 -1
  37. package/dist/{src-DJoqT9yP.mjs → src-Di-H3Oya.mjs} +71 -41
  38. package/dist/src-Di-H3Oya.mjs.map +1 -0
  39. package/dist/{subagent-D-TYaX38.mjs → subagent-BOK4GFd4.mjs} +3 -3
  40. package/dist/{subagent-D-TYaX38.mjs.map → subagent-BOK4GFd4.mjs.map} +1 -1
  41. package/dist/{tasks-Dgsiuh0Q.mjs → tasks-BUFqFoh6.mjs} +2 -2
  42. package/dist/{tasks-Dgsiuh0Q.mjs.map → tasks-BUFqFoh6.mjs.map} +1 -1
  43. package/dist/{tasks-D76WXWr2.mjs → tasks-CkDWJk_3.mjs} +4 -4
  44. package/dist/tasks-CkDWJk_3.mjs.map +1 -0
  45. package/dist/{tools-DmoUYORG.mjs → tools-Ca7VsMg3.mjs} +2 -2
  46. package/dist/{tools-DmoUYORG.mjs.map → tools-Ca7VsMg3.mjs.map} +1 -1
  47. package/dist/{write-BRQFfWAn.mjs → write-y93TC5ng.mjs} +2 -2
  48. package/dist/{write-BRQFfWAn.mjs.map → write-y93TC5ng.mjs.map} +1 -1
  49. package/package.json +11 -11
  50. package/dist/agent-DlhEEMPU.mjs.map +0 -1
  51. package/dist/html-VrAsoGBK.mjs.map +0 -1
  52. package/dist/index-node-esm-BwaOzhXB.mjs.map +0 -1
  53. package/dist/src-DJoqT9yP.mjs.map +0 -1
  54. package/dist/tasks-D76WXWr2.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"session-CUE48QWX.mjs","names":[],"sources":["../src/session/memory.ts","../src/session/session.ts"],"sourcesContent":["import type { SessionStore } from \"./store.ts\"\nimport type { SessionNode } from \"./types.ts\"\n\n/**\n * In-memory `SessionStore` — a `Map<uuid, SessionNode>` plus a `root`\n * pointer. No persistence. Construction takes optional initial nodes\n * for tests, replay tools, and the Claude session importer.\n */\nexport class MemoryStore implements SessionStore {\n readonly #nodes: Map<string, SessionNode>\n #root?: SessionNode\n\n constructor(nodes?: Iterable<SessionNode>) {\n this.#nodes = new Map()\n if (nodes) {\n for (const node of nodes) {\n this.#nodes.set(node.uuid, node)\n this.#root = node\n }\n }\n }\n\n get root(): SessionNode | undefined {\n return this.#root\n }\n\n async get(id: string): Promise<SessionNode | undefined> {\n return this.#nodes.get(id)\n }\n\n async write(node: SessionNode): Promise<void> {\n this.#nodes.set(node.uuid, node)\n this.#root = node\n }\n\n *all(): Iterable<SessionNode> {\n yield* this.#nodes.values()\n }\n}\n","import type { Message } from \"@zaly/ai\"\nimport type { SessionStore } from \"./store.ts\"\nimport type {\n MaskCheckpoint,\n PartialNode,\n SessionEvents,\n SessionInit,\n SessionMessage,\n SessionNode,\n SessionNodeView,\n SessionOptions,\n SessionSettings,\n SessionUpdate,\n SessionView,\n} from \"./types.ts\"\n\nimport { Emitter, normPath } from \"@zaly/shared\"\nimport { zalyPaths } from \"@zaly/shared/paths\"\nimport { isDeepStrictEqual } from \"node:util\"\nimport { join } from \"pathe\"\nimport { uuidv7 } from \"../utils/uuid.ts\"\nimport { JsonlStore } from \"./jsonl.ts\"\nimport { MemoryStore } from \"./memory.ts\"\n\nconst VERSION = 2\n\n/**\n * Conversation primitive. Owns a DAG of message + compaction + meta\n * nodes via a `SessionStore` backend; the *active* message list is\n * whatever you get by walking `parentUuid` backwards from the store's\n * root until you hit a `compact` node (or the start).\n *\n * **Meta is snapshot-based.** `session-meta` nodes carry the full\n * cumulative meta as of their commit time. Other node types (start,\n * resume, message, compact) don't carry meta — `Session` reconstructs\n * the cumulative meta at any point by finding the most recent\n * `session-meta` ancestor in a forward pass over the chain. Public\n * APIs return `SessionNodeView` (raw node + decorated `meta`).\n *\n * Designed so the loop, the persistor, the TUI, and any replay tool\n * all read from one source of truth and never mutate the DAG behind\n * each other's backs:\n *\n * - **Run loop** (`Agent`) calls `add()` on each new message and\n * `compact()` on overflow.\n * - **TUI** subscribes to the `node` event for streaming render.\n * - **Persistor** is the `SessionStore` — `MemoryStore` for ephemeral\n * sessions, `JsonlStore` for file-backed.\n *\n * Construction:\n * - Use `await Session.load(opts)` for the recommended path — picks\n * the right store (Memory if no path, JSONL if path).\n * - For tests / direct embedding, `new Session({ store })` works with\n * any pre-built store.\n */\nexport class Session<T extends SessionStore = SessionStore> extends Emitter<SessionEvents> {\n readonly #store: T\n #opts: SessionInit<T>\n #id: string\n #dir: string\n #settings: SessionSettings = {}\n #view: SessionView = { messages: [], nodes: new Map() }\n #closed = false\n #started = false\n #path?: string\n #head?: string\n #mutations?: Promise<void>\n\n protected constructor(opts: SessionInit<T>) {\n super()\n this.#opts = opts\n this.#path = opts.path\n this.#store = opts.store\n this.#id = opts.defaults?.sessionId ?? uuidv7()\n this.#dir = normPath(opts.dir ?? join(zalyPaths.env.tmp, \"sessions\", this.#id))\n }\n\n /** Recommended one-step path: pick the right store backend, hydrate\n * if applicable, return a ready-to-use session.\n *\n * - `path` provided → `JsonlStore` (file-backed, hydrates from disk\n * if the file exists, opens for append either way).\n * - No `path` → `MemoryStore` (ephemeral, no persistence). */\n static async load<T extends SessionStore = SessionStore>(\n opts: SessionOptions<T> & { store: T }\n ): Promise<Session<T>>\n static async load(opts: SessionOptions & { path: string }): Promise<Session<JsonlStore>>\n static async load(opts?: SessionOptions & {}): Promise<Session<MemoryStore>>\n static async load(opts: SessionOptions = {}): Promise<Session> {\n const session = await Session.create(opts)\n await session.#rebuild()\n return session\n }\n\n private static async create(opts: SessionOptions = {}): Promise<Session> {\n const path = opts.path ? normPath(opts.path) : undefined\n const store: SessionStore =\n opts.store ?? (path ? await JsonlStore.load(path) : new MemoryStore())\n const init: SessionInit = { ...opts, path, store }\n return new Session(init)\n }\n\n /** Efficiently fetch the most recent user message by walking backward until we hit\n * a user message, without reconstructing the full chain. Useful for a session picker. */\n static async lastMessage(opts: SessionOptions = {}): Promise<Message<\"user\"> | undefined> {\n const session = await Session.create(opts)\n let ret: Message<\"user\"> | undefined\n await session.#chain({\n stop: (node) => {\n if (node.type === \"message\" && node.message.role === \"user\") {\n ret = node.message\n return true\n }\n return false\n },\n })\n void session.close()\n return ret\n }\n\n async #rebuild(): Promise<void> {\n const chain = await this.#chain()\n this.#view = chain\n this.#settings = chain.settings\n this.#id = chain.settings.sessionId ?? this.#id\n }\n\n // ── Read ──────────────────────────────────────────────────────────────\n\n /** Active conversation — chain from current head back to the most\n * recent compact (exclusive), in chronological order. This is what\n * the agent sees on the next request. */\n get messages(): readonly Message[] {\n return this.#view.messages\n }\n\n get maskCheckpoint(): MaskCheckpoint | undefined {\n return this.#view.maskCheckpoint\n }\n\n get id(): string {\n return this.#id\n }\n\n get dir(): string {\n return this.#dir\n }\n\n get path(): string | undefined {\n return this.#path\n }\n\n get started(): boolean {\n return this.#started\n }\n\n /** Current session settings, merged with defaults. */\n get settings(): SessionSettings {\n return { ...this.#opts.defaults, ...this.#settings }\n }\n\n async update(settings: SessionUpdate, opts?: { force?: boolean }): Promise<string> {\n return this.#mutate(() => this.#commit({ settings, type: \"session-settings\" }, opts))\n }\n\n /** Lazily emits `session-start` on a fresh session or `session-resume`\n * on a hydrated one. Called from `#commit` before the first non-marker\n * node lands so the start/resume marker always heads the chain. */\n async #autostart(): Promise<void> {\n if (!this.#started) await this.#start()\n }\n\n /** Explicitly mark the session as started — writes a `session-start`\n * marker on a fresh session, `session-resume` on a hydrated one.\n * Idempotent; subsequent calls are no-ops. Optional `meta` is\n * applied via `update()` after the marker lands. */\n async start(settings?: SessionUpdate): Promise<string | undefined> {\n return this.#mutate(() => this.#start(settings))\n }\n\n async #start(settings?: SessionUpdate): Promise<string | undefined> {\n if (this.#started)\n return settings\n ? this.#commit({ settings, type: \"session-settings\" })\n : this.#store.root?.uuid\n this.#started = true\n const type = this.messages.length > 0 ? (\"session-resume\" as const) : (\"session-start\" as const)\n await this.#commit({ type })\n void this.emit(type)\n await this.#commit({ settings: settings ?? {}, type: \"session-settings\" })\n return this.#store.root?.uuid\n }\n\n /** Look up the decorated view for a node id — raw node plus the\n * cumulative meta as of that node's position. Returns the\n * message-typed view, or `undefined` if the id doesn't refer to a\n * message in this session. */\n async node(id?: string | Message): Promise<(SessionNodeView & { type: \"message\" }) | undefined> {\n const m = typeof id === \"string\" ? { id } : id\n if (!m?.id) return undefined\n const ret = this.#view.nodes.get(m.id)\n return ret?.type === \"message\" ? ret : undefined\n }\n\n /** Current head uuid — the root of the store, which is the most\n * recently appended node. */\n get head(): string | undefined {\n return this.#head ?? this.#store.root?.uuid\n }\n\n /** Full DAG iterator — backed by `store.all()`. Yields raw nodes\n * (no meta decoration). */\n nodes(): Iterable<SessionNode> | AsyncIterable<SessionNode> {\n return this.#store.all?.() ?? []\n }\n\n get root(): SessionNode | undefined {\n return this.#store.root\n }\n\n // ── Mutate ────────────────────────────────────────────────────────────\n\n /** Append a message. The new node is parented to the current head,\n * head advances, and a `node` event fires. Optional `meta` carries\n * usage / model / finish info — populate it for assistant turns\n * the agent commits after a step. Returns the assigned uuid.\n *\n * If `message.id` / `message.ts` are set (e.g. round-tripped from a\n * prior load), they're used as the node's uuid / timestamp; otherwise\n * fresh values are generated. The committed message always carries\n * both — `m.id === node.uuid` and `m.ts === node.ts`. */\n async add(message: Message): Promise<string> {\n const uuid = message.id ?? uuidv7()\n const ts = message.ts ?? Date.now()\n const m = { ...message, id: uuid, ts }\n return this.#mutate(() => this.#commit({ message: m, type: \"message\" }))\n }\n\n /** Summarize an active prefix through a message ID, preserving everything\n * appended after it. Boundary validation and tail calculation share the\n * serialized commit with the new summary. Legacy tail-only calls remain\n * supported. Original history stays in the store; a fresh settings anchor\n * follows the compact node for reconstruction. */\n async compact(opts: {\n trigger?: \"manual\" | \"auto\"\n preTokens?: number\n durationMs?: number\n /** Cancel a queued compaction before its commit begins. */\n signal?: AbortSignal\n /** Prefer an explicit boundary; tail-only calls remain supported. */\n to?: string\n /** Expected first message of the snapshot, including a prior summary if present. */\n from?: string\n tail?: number\n summary: Message<\"system\">\n }): Promise<string> {\n return this.#mutate(async () => {\n opts.signal?.throwIfAborted()\n let tail = opts.tail\n if (opts.to !== undefined) {\n const index = this.messages.findIndex((m) => m.id === opts.to)\n if (index === -1 || (opts.from !== undefined && this.messages[0]?.id !== opts.from)) {\n throw new Error(\"Compaction snapshot is no longer part of the active history\")\n }\n tail = this.messages.length - index - 1\n }\n if (tail === undefined || !Number.isInteger(tail) || tail < 0) {\n throw new Error(\"Compaction requires a message boundary or a non-negative integer tail\")\n }\n const compactUuid = await this.#commit({\n durationMs: opts.durationMs,\n from: opts.from,\n preTokens: opts.preTokens,\n summary: opts.summary,\n tail,\n to: opts.to,\n trigger: opts.trigger ?? \"manual\",\n type: \"compact\",\n })\n await this.#commit({ settings: {}, type: \"session-settings\" }, { force: true })\n await this.#rebuild()\n const node = this.#view.compact!\n void this.emit(\"compact\", { node })\n return compactUuid\n })\n }\n\n async addMaskCheckpoint(opts: MaskCheckpoint): Promise<string> {\n return this.#mutate(async () => {\n this.#view.maskCheckpoint = opts\n return this.#commit({ ...opts, type: \"mask-checkpoint\" })\n })\n }\n\n async checkout(uuid: string): Promise<void> {\n return this.#mutate(async () => {\n if (this.#closed) throw new Error(\"Session is closed\")\n this.#head = uuid\n await this.#rebuild()\n })\n }\n\n /** Pre-active history of the current chain — messages from before\n * the most recent compact (and earlier compacts), in chronological\n * order. Useful for TUI scrollback that wants to render context the\n * agent itself no longer sees.\n *\n * `limit` truncates from the front (oldest), so the most recent\n * history messages always make it through. */\n async history(limit?: number): Promise<readonly Message[]> {\n const chain = await this.#chain({ active: false, limit })\n return chain.messages\n }\n\n /** Flush + close the underlying store. Subsequent writes throw. */\n async close(): Promise<void> {\n return this.#mutate(async () => {\n if (this.#closed) return\n this.#closed = true\n await this.#store.close?.()\n })\n }\n\n // ── Internals ────────────────────────────────────────────────────────\n\n // Keep commits and view rebuilds together so appends cannot race a compaction.\n #mutate<R>(fn: () => Promise<R>): Promise<R> {\n const pending = this.#mutations ? this.#mutations.then(fn) : fn()\n const settled = pending.then(\n () => {},\n () => {}\n )\n this.#mutations = settled\n void settled.then(() => {\n if (this.#mutations === settled) this.#mutations = undefined\n })\n return pending\n }\n\n /** Atomically commit a node: register it in the store, update active\n * messages, persist, and emit. Single chokepoint for all mutations. */\n async #commit(n: PartialNode, opts: { force?: boolean } = {}): Promise<string> {\n let node: SessionNode = {\n ...n,\n parentUuid: this.head,\n ts: n.type === \"message\" ? (n.message.ts ?? Date.now()) : Date.now(),\n uuid: n.type === \"message\" ? (n.message.id ?? uuidv7()) : uuidv7(),\n }\n\n if (!this.#started && node.type !== \"session-start\" && node.type !== \"session-resume\") {\n await this.#autostart()\n }\n if (this.#closed) throw new Error(\"Session is closed\")\n\n const next: SessionSettings = {\n ...this.#opts.defaults,\n ...this.#settings,\n ...(node.type === \"session-settings\" ? node.settings : {}),\n sessionId: this.#id,\n version: VERSION,\n }\n if (next.cwd) next.cwd = normPath(next.cwd)\n if (next.workspace) next.workspace = normPath(next.workspace)\n\n if (node.type === \"session-settings\") {\n if (!opts.force && isDeepStrictEqual(this.#settings, next)) return this.#store.root!.uuid\n node = { ...node, settings: next }\n }\n\n node = { ...node, parentUuid: this.head }\n await this.#store.write(node)\n this.#head = undefined // invalidate head cache so it reflects the store's root on next read\n\n // Decorate the new node with cumulative meta and append to the\n // active chain view\n this.#view.nodes.set(node.uuid, { ...node, settings: next })\n if (node.type === \"message\") this.#view.messages.push(node.message)\n\n // cwd / meta event signaling\n if (node.type === \"session-settings\") {\n const prev = this.#settings\n this.#settings = next\n this.#emitChanges(prev)\n }\n\n void this.emit(\"node\", { node })\n return node.uuid\n }\n\n #emitChanges(prev: SessionSettings): void {\n const next = this.#settings\n if (next.cwd && next.cwd !== prev.cwd) void this.emit(\"cwd\", { cwd: next.cwd, prev: prev.cwd })\n if (next.modelId && next.modelId !== prev.modelId)\n void this.emit(\"model\", { model: next.modelId, prev: prev.modelId })\n if (next.reasoning && next.reasoning !== prev.reasoning)\n void this.emit(\"reasoning\", { effort: next.reasoning, prev: prev.reasoning })\n }\n\n /** Walk `parentUuid` from the given node back toward the root,\n * returning the chain as decorated views (each with cumulative meta).\n * The `active` flag controls what counts:\n * - `true` — only the active chain (stops at first compact /\n * session-start, with the kept tail spliced in via\n * the compact's `tail` field, summary substituted\n * in place of the compact node).\n * - `false` — includes everything back to the root\n * Returns chronological order. */\n async #chain(\n opts: {\n active?: boolean\n limit?: number\n uuid?: string\n stop?: (node: SessionNode) => boolean\n } = {}\n ): Promise<SessionView & { settings: SessionSettings }> {\n // Backward pass: collect raw nodes (new to old)\n const reverse: SessionNode[] = []\n let cursor = opts.uuid ?? this.head\n let limit = opts.limit ?? Infinity\n let compact: SessionNode<\"compact\"> | undefined\n const messageNodes: SessionNode<\"message\">[] = []\n let maskCheckpoint: SessionNode<\"mask-checkpoint\"> | undefined\n\n // Walk backward from the head until we hit a compact or the start, collecting nodes.\n while (cursor) {\n // eslint-disable-next-line no-await-in-loop\n const node = await this.#store.get(cursor)\n if (!node || (node.type === \"message\" && messageNodes.length + 1 > limit)) break\n cursor = node.parentUuid\n reverse.push(node)\n // Keep track if the last mask-checkpoint, until we hit a compaction.\n if (node.type === \"mask-checkpoint\" && !compact && !maskCheckpoint) maskCheckpoint = node\n if (node.type === \"message\") messageNodes.push(node)\n if (node.type === \"compact\" && (opts.active ?? true)) {\n compact ??= node\n // Earlier compactions may contain part of the kept tail. Walk through\n // their preserved messages, but never resurrect their summarized history.\n limit = Math.min(limit, messageNodes.length + node.tail)\n }\n if (opts.stop?.(node)) break\n }\n\n // Forward pass: decorate with cumulative meta. session-meta nodes\n // redefine the meta; everything else inherits the running snapshot.\n const nodes = new Map<string, SessionNodeView>()\n let settings: SessionSettings = {}\n for (const n of reverse.toReversed()) {\n if (n.type === \"session-settings\") settings = n.settings\n nodes.set(n.uuid, { ...n, settings })\n }\n\n this.#migrate(nodes)\n\n const messages: SessionMessage[] = []\n for (const n of messageNodes) {\n // add `id`, `ts` and `modelId` (if assistant turn) to the message\n const m = { ...n.message, id: n.uuid, ts: n.ts }\n if (m.role === \"assistant\") {\n // Add missing modelId to assistant messages if not present\n const s = nodes.get(n.uuid)?.settings ?? {}\n m.meta = { ...m.meta, modelId: m.meta?.modelId ?? s.modelId }\n }\n n.message = m\n messages.push(m)\n }\n\n // Add compaction summary as the first message\n if (compact) {\n messages.push({ ...compact.summary, id: compact.uuid, ts: compact.ts })\n nodes.set(compact.uuid, {\n message: compact.summary,\n parentUuid: compact.parentUuid,\n settings: nodes.get(compact.uuid)?.settings ?? {},\n ts: compact.ts,\n type: \"message\",\n uuid: compact.uuid,\n })\n }\n\n return {\n compact,\n maskCheckpoint,\n messages: messages.toReversed(),\n nodes,\n settings,\n }\n }\n\n #migrate(nodes: Map<string, SessionNodeView>) {\n for (const n of nodes.values()) {\n const version = n.settings.version ?? 0\n if (version === VERSION) continue\n n.settings = { ...n.settings, version: VERSION }\n\n if (n.type === \"compact\") {\n n.summary.meta = { kind: \"compaction-summary\", ...n.summary.meta }\n continue\n }\n\n if (n.type !== \"message\") continue\n const m = n.message\n\n if (\n m.role === \"system\" &&\n Array.isArray(m.content) &&\n m.content[0].type === \"meta\" &&\n m.content[0].tag === \"task\"\n ) {\n // Missing task meta data kind\n m.meta = { kind: \"task\", ...m.meta }\n }\n\n n.message = m\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"session-C5ra-Hi1.mjs","names":[],"sources":["../src/session/memory.ts","../src/session/session.ts"],"sourcesContent":["import type { SessionStore } from \"./store.ts\"\nimport type { SessionNode } from \"./types.ts\"\n\n/**\n * In-memory `SessionStore` — a `Map<uuid, SessionNode>` plus a `root`\n * pointer. No persistence. Construction takes optional initial nodes\n * for tests, replay tools, and the Claude session importer.\n */\nexport class MemoryStore implements SessionStore {\n readonly #nodes: Map<string, SessionNode>\n #root?: SessionNode\n\n constructor(nodes?: Iterable<SessionNode>) {\n this.#nodes = new Map()\n if (nodes) {\n for (const node of nodes) {\n this.#nodes.set(node.uuid, node)\n this.#root = node\n }\n }\n }\n\n get root(): SessionNode | undefined {\n return this.#root\n }\n\n async get(id: string): Promise<SessionNode | undefined> {\n return this.#nodes.get(id)\n }\n\n async write(node: SessionNode): Promise<void> {\n this.#nodes.set(node.uuid, node)\n this.#root = node\n }\n\n *all(): Iterable<SessionNode> {\n yield* this.#nodes.values()\n }\n}\n","import type { Message } from \"@zaly/ai\"\nimport type { SessionStore } from \"./store.ts\"\nimport type {\n MaskCheckpoint,\n PartialNode,\n SessionEvents,\n SessionInit,\n SessionMessage,\n SessionNode,\n SessionNodeView,\n SessionOptions,\n SessionSettings,\n SessionUpdate,\n SessionView,\n} from \"./types.ts\"\n\nimport { Emitter, normPath } from \"@zaly/shared\"\nimport { zalyPaths } from \"@zaly/shared/paths\"\nimport { isDeepStrictEqual } from \"node:util\"\nimport { join } from \"pathe\"\nimport { uuidv7 } from \"../utils/uuid.ts\"\nimport { JsonlStore } from \"./jsonl.ts\"\nimport { MemoryStore } from \"./memory.ts\"\n\nconst VERSION = 2\n\n/**\n * Conversation primitive. Owns a DAG of message + compaction + meta\n * nodes via a `SessionStore` backend; the *active* message list is\n * whatever you get by walking `parentUuid` backwards from the store's\n * root until you hit a `compact` node (or the start).\n *\n * **Meta is snapshot-based.** `session-meta` nodes carry the full\n * cumulative meta as of their commit time. Other node types (start,\n * resume, message, compact) don't carry meta — `Session` reconstructs\n * the cumulative meta at any point by finding the most recent\n * `session-meta` ancestor in a forward pass over the chain. Public\n * APIs return `SessionNodeView` (raw node + decorated `meta`).\n *\n * Designed so the loop, the persistor, the TUI, and any replay tool\n * all read from one source of truth and never mutate the DAG behind\n * each other's backs:\n *\n * - **Run loop** (`Agent`) calls `add()` on each new message and\n * `compact()` on overflow.\n * - **TUI** subscribes to the `node` event for streaming render.\n * - **Persistor** is the `SessionStore` — `MemoryStore` for ephemeral\n * sessions, `JsonlStore` for file-backed.\n *\n * Construction:\n * - Use `await Session.load(opts)` for the recommended path — picks\n * the right store (Memory if no path, JSONL if path).\n * - For tests / direct embedding, `new Session({ store })` works with\n * any pre-built store.\n */\nexport class Session<T extends SessionStore = SessionStore> extends Emitter<SessionEvents> {\n readonly #store: T\n #opts: SessionInit<T>\n #id: string\n #dir: string\n #settings: SessionSettings = {}\n #view: SessionView = { messages: [], nodes: new Map() }\n #closed = false\n #started = false\n #path?: string\n #head?: string\n #mutations?: Promise<void>\n\n protected constructor(opts: SessionInit<T>) {\n super()\n this.#opts = opts\n this.#path = opts.path\n this.#store = opts.store\n this.#id = opts.defaults?.sessionId ?? uuidv7()\n this.#dir = normPath(opts.dir ?? join(zalyPaths.env.tmp, \"sessions\", this.#id))\n }\n\n /** Recommended one-step path: pick the right store backend, hydrate\n * if applicable, return a ready-to-use session.\n *\n * - `path` provided → `JsonlStore` (file-backed, hydrates from disk\n * if the file exists, opens for append either way).\n * - No `path` → `MemoryStore` (ephemeral, no persistence). */\n static async load<T extends SessionStore = SessionStore>(\n opts: SessionOptions<T> & { store: T }\n ): Promise<Session<T>>\n static async load(opts: SessionOptions & { path: string }): Promise<Session<JsonlStore>>\n static async load(opts?: SessionOptions & {}): Promise<Session<MemoryStore>>\n static async load(opts: SessionOptions = {}): Promise<Session> {\n const session = await Session.create(opts)\n await session.#rebuild()\n return session\n }\n\n private static async create(opts: SessionOptions = {}): Promise<Session> {\n const path = opts.path ? normPath(opts.path) : undefined\n const store: SessionStore =\n opts.store ?? (path ? await JsonlStore.load(path) : new MemoryStore())\n const init: SessionInit = { ...opts, path, store }\n return new Session(init)\n }\n\n /** Efficiently fetch the most recent user message by walking backward until we hit\n * a user message, without reconstructing the full chain. Useful for a session picker. */\n static async lastMessage(opts: SessionOptions = {}): Promise<Message<\"user\"> | undefined> {\n const session = await Session.create(opts)\n let ret: Message<\"user\"> | undefined\n await session.#chain({\n stop: (node) => {\n if (node.type === \"message\" && node.message.role === \"user\") {\n ret = node.message\n return true\n }\n return false\n },\n })\n void session.close()\n return ret\n }\n\n async #rebuild(): Promise<void> {\n const chain = await this.#chain()\n this.#view = chain\n this.#settings = chain.settings\n this.#id = chain.settings.sessionId ?? this.#id\n }\n\n // ── Read ──────────────────────────────────────────────────────────────\n\n /** Active conversation — chain from current head back to the most\n * recent compact (exclusive), in chronological order. This is what\n * the agent sees on the next request. */\n get messages(): readonly Message[] {\n return this.#view.messages\n }\n\n get maskCheckpoint(): MaskCheckpoint | undefined {\n return this.#view.maskCheckpoint\n }\n\n get id(): string {\n return this.#id\n }\n\n get dir(): string {\n return this.#dir\n }\n\n get path(): string | undefined {\n return this.#path\n }\n\n get started(): boolean {\n return this.#started\n }\n\n /** Current session settings, merged with defaults. */\n get settings(): SessionSettings {\n return { ...this.#opts.defaults, ...this.#settings }\n }\n\n async update(settings: SessionUpdate, opts?: { force?: boolean }): Promise<string> {\n return this.#mutate(() => this.#commit({ settings, type: \"session-settings\" }, opts))\n }\n\n /** Lazily emits `session-start` on a fresh session or `session-resume`\n * on a hydrated one. Called from `#commit` before the first non-marker\n * node lands so the start/resume marker always heads the chain. */\n async #autostart(): Promise<void> {\n if (!this.#started) await this.#start()\n }\n\n /** Explicitly mark the session as started — writes a `session-start`\n * marker on a fresh session, `session-resume` on a hydrated one.\n * Idempotent; subsequent calls are no-ops. Optional `meta` is\n * applied via `update()` after the marker lands. */\n async start(settings?: SessionUpdate): Promise<string | undefined> {\n return this.#mutate(() => this.#start(settings))\n }\n\n async #start(settings?: SessionUpdate): Promise<string | undefined> {\n if (this.#started)\n return settings\n ? this.#commit({ settings, type: \"session-settings\" })\n : this.#store.root?.uuid\n this.#started = true\n const type = this.messages.length > 0 ? (\"session-resume\" as const) : (\"session-start\" as const)\n await this.#commit({ type })\n void this.emit(type)\n await this.#commit({ settings: settings ?? {}, type: \"session-settings\" })\n return this.#store.root?.uuid\n }\n\n /** Look up the decorated view for a node id — raw node plus the\n * cumulative meta as of that node's position. Returns the\n * message-typed view, or `undefined` if the id doesn't refer to a\n * message in this session. */\n async node(id?: string | Message): Promise<(SessionNodeView & { type: \"message\" }) | undefined> {\n const m = typeof id === \"string\" ? { id } : id\n if (!m?.id) return undefined\n const ret = this.#view.nodes.get(m.id)\n return ret?.type === \"message\" ? ret : undefined\n }\n\n /** Current head uuid — the root of the store, which is the most\n * recently appended node. */\n get head(): string | undefined {\n return this.#head ?? this.#store.root?.uuid\n }\n\n /** Full DAG iterator — backed by `store.all()`. Yields raw nodes\n * (no meta decoration). */\n nodes(): Iterable<SessionNode> | AsyncIterable<SessionNode> {\n return this.#store.all?.() ?? []\n }\n\n get root(): SessionNode | undefined {\n return this.#store.root\n }\n\n // ── Mutate ────────────────────────────────────────────────────────────\n\n /** Append a message. The new node is parented to the current head,\n * head advances, and a `node` event fires. Optional `meta` carries\n * usage / model / finish info — populate it for assistant turns\n * the agent commits after a step. Returns the assigned uuid.\n *\n * If `message.id` / `message.ts` are set (e.g. round-tripped from a\n * prior load), they're used as the node's uuid / timestamp; otherwise\n * fresh values are generated. The committed message always carries\n * both — `m.id === node.uuid` and `m.ts === node.ts`. */\n async add(message: Message): Promise<string> {\n const uuid = message.id ?? uuidv7()\n const ts = message.ts ?? Date.now()\n const m = { ...message, id: uuid, ts }\n return this.#mutate(() => this.#commit({ message: m, type: \"message\" }))\n }\n\n /** Summarize an active prefix through a message ID, preserving everything\n * appended after it. Boundary validation and tail calculation share the\n * serialized commit with the new summary. Legacy tail-only calls remain\n * supported. Original history stays in the store; a fresh settings anchor\n * follows the compact node for reconstruction. */\n async compact(opts: {\n trigger?: \"manual\" | \"auto\"\n preTokens?: number\n durationMs?: number\n /** Cancel a queued compaction before its commit begins. */\n signal?: AbortSignal\n /** Prefer an explicit boundary; tail-only calls remain supported. */\n to?: string\n /** Expected first message of the snapshot, including a prior summary if present. */\n from?: string\n tail?: number\n summary: Message<\"system\">\n }): Promise<string> {\n return this.#mutate(async () => {\n opts.signal?.throwIfAborted()\n let tail = opts.tail\n if (opts.to !== undefined) {\n const index = this.messages.findIndex((m) => m.id === opts.to)\n if (index === -1 || (opts.from !== undefined && this.messages[0]?.id !== opts.from)) {\n throw new Error(\"Compaction snapshot is no longer part of the active history\")\n }\n tail = this.messages.length - index - 1\n }\n if (tail === undefined || !Number.isInteger(tail) || tail < 0) {\n throw new Error(\"Compaction requires a message boundary or a non-negative integer tail\")\n }\n const compactUuid = await this.#commit({\n durationMs: opts.durationMs,\n from: opts.from,\n preTokens: opts.preTokens,\n summary: opts.summary,\n tail,\n to: opts.to,\n trigger: opts.trigger ?? \"manual\",\n type: \"compact\",\n })\n await this.#commit({ settings: {}, type: \"session-settings\" }, { force: true })\n await this.#rebuild()\n const node = this.#view.compact!\n void this.emit(\"compact\", { node })\n return compactUuid\n })\n }\n\n async addMaskCheckpoint(opts: MaskCheckpoint): Promise<string> {\n return this.#mutate(async () => {\n this.#view.maskCheckpoint = opts\n return this.#commit({ ...opts, type: \"mask-checkpoint\" })\n })\n }\n\n async checkout(uuid: string): Promise<void> {\n return this.#mutate(async () => {\n if (this.#closed) throw new Error(\"Session is closed\")\n this.#head = uuid\n await this.#rebuild()\n })\n }\n\n /** Pre-active history of the current chain — messages from before\n * the most recent compact (and earlier compacts), in chronological\n * order. Useful for TUI scrollback that wants to render context the\n * agent itself no longer sees.\n *\n * `limit` truncates from the front (oldest), so the most recent\n * history messages always make it through. */\n async history(limit?: number): Promise<readonly Message[]> {\n const chain = await this.#chain({ active: false, limit })\n return chain.messages\n }\n\n /** Flush + close the underlying store. Subsequent writes throw. */\n async close(): Promise<void> {\n return this.#mutate(async () => {\n if (this.#closed) return\n this.#closed = true\n await this.#store.close?.()\n })\n }\n\n // ── Internals ────────────────────────────────────────────────────────\n\n // Keep commits and view rebuilds together so appends cannot race a compaction.\n #mutate<R>(fn: () => Promise<R>): Promise<R> {\n const pending = this.#mutations ? this.#mutations.then(fn) : fn()\n const settled = pending.then(\n () => {},\n () => {}\n )\n this.#mutations = settled\n void settled.then(() => {\n if (this.#mutations === settled) this.#mutations = undefined\n })\n return pending\n }\n\n /** Atomically commit a node: register it in the store, update active\n * messages, persist, and emit. Single chokepoint for all mutations. */\n async #commit(n: PartialNode, opts: { force?: boolean } = {}): Promise<string> {\n let node: SessionNode = {\n ...n,\n parentUuid: this.head,\n ts: n.type === \"message\" ? (n.message.ts ?? Date.now()) : Date.now(),\n uuid: n.type === \"message\" ? (n.message.id ?? uuidv7()) : uuidv7(),\n }\n\n if (!this.#started && node.type !== \"session-start\" && node.type !== \"session-resume\") {\n await this.#autostart()\n }\n if (this.#closed) throw new Error(\"Session is closed\")\n\n const next: SessionSettings = {\n ...this.#opts.defaults,\n ...this.#settings,\n ...(node.type === \"session-settings\" ? node.settings : {}),\n sessionId: this.#id,\n version: VERSION,\n }\n if (next.cwd) next.cwd = normPath(next.cwd)\n if (next.workspace) next.workspace = normPath(next.workspace)\n\n if (node.type === \"session-settings\") {\n if (!opts.force && isDeepStrictEqual(this.#settings, next)) return this.#store.root!.uuid\n node = { ...node, settings: next }\n }\n\n node = { ...node, parentUuid: this.head }\n await this.#store.write(node)\n this.#head = undefined // invalidate head cache so it reflects the store's root on next read\n\n // Decorate the new node with cumulative meta and append to the\n // active chain view\n this.#view.nodes.set(node.uuid, { ...node, settings: next })\n if (node.type === \"message\") this.#view.messages.push(node.message)\n\n // cwd / meta event signaling\n if (node.type === \"session-settings\") {\n const prev = this.#settings\n this.#settings = next\n this.#emitChanges(prev)\n }\n\n void this.emit(\"node\", { node })\n return node.uuid\n }\n\n #emitChanges(prev: SessionSettings): void {\n const next = this.#settings\n if (next.cwd && next.cwd !== prev.cwd) void this.emit(\"cwd\", { cwd: next.cwd, prev: prev.cwd })\n if (next.modelId && next.modelId !== prev.modelId)\n void this.emit(\"model\", { model: next.modelId, prev: prev.modelId })\n if (next.reasoning && next.reasoning !== prev.reasoning)\n void this.emit(\"reasoning\", { effort: next.reasoning, prev: prev.reasoning })\n }\n\n /** Walk `parentUuid` from the given node back toward the root,\n * returning the chain as decorated views (each with cumulative meta).\n * The `active` flag controls what counts:\n * - `true` — only the active chain (stops at first compact /\n * session-start, with the kept tail spliced in via\n * the compact's `tail` field, summary substituted\n * in place of the compact node).\n * - `false` — includes everything back to the root\n * Returns chronological order. */\n async #chain(\n opts: {\n active?: boolean\n limit?: number\n uuid?: string\n stop?: (node: SessionNode) => boolean\n } = {}\n ): Promise<SessionView & { settings: SessionSettings }> {\n // Backward pass: collect raw nodes (new to old)\n const reverse: SessionNode[] = []\n let cursor = opts.uuid ?? this.head\n let limit = opts.limit ?? Infinity\n let compact: SessionNode<\"compact\"> | undefined\n const messageNodes: SessionNode<\"message\">[] = []\n let maskCheckpoint: SessionNode<\"mask-checkpoint\"> | undefined\n\n // Walk backward from the head until we hit a compact or the start, collecting nodes.\n while (cursor) {\n // eslint-disable-next-line no-await-in-loop\n const node = await this.#store.get(cursor)\n if (!node || (node.type === \"message\" && messageNodes.length + 1 > limit)) break\n cursor = node.parentUuid\n reverse.push(node)\n // Keep track if the last mask-checkpoint, until we hit a compaction.\n if (node.type === \"mask-checkpoint\" && !compact && !maskCheckpoint) maskCheckpoint = node\n if (node.type === \"message\") messageNodes.push(node)\n if (node.type === \"compact\" && (opts.active ?? true)) {\n compact ??= node\n // Earlier compactions may contain part of the kept tail. Walk through\n // their preserved messages, but never resurrect their summarized history.\n limit = Math.min(limit, messageNodes.length + node.tail)\n }\n if (opts.stop?.(node)) break\n }\n\n // Forward pass: decorate with cumulative meta. session-meta nodes\n // redefine the meta; everything else inherits the running snapshot.\n const nodes = new Map<string, SessionNodeView>()\n let settings: SessionSettings = {}\n for (const n of reverse.toReversed()) {\n if (n.type === \"session-settings\") settings = n.settings\n nodes.set(n.uuid, { ...n, settings })\n }\n\n this.#migrate(nodes)\n\n const messages: SessionMessage[] = []\n for (const n of messageNodes) {\n // add `id`, `ts` and `modelId` (if assistant turn) to the message\n const m = { ...n.message, id: n.uuid, ts: n.ts }\n if (m.role === \"assistant\") {\n // Add missing modelId to assistant messages if not present\n const s = nodes.get(n.uuid)?.settings ?? {}\n m.meta = { ...m.meta, modelId: m.meta?.modelId ?? s.modelId }\n }\n n.message = m\n messages.push(m)\n }\n\n // Add compaction summary as the first message\n if (compact) {\n messages.push({ ...compact.summary, id: compact.uuid, ts: compact.ts })\n nodes.set(compact.uuid, {\n message: compact.summary,\n parentUuid: compact.parentUuid,\n settings: nodes.get(compact.uuid)?.settings ?? {},\n ts: compact.ts,\n type: \"message\",\n uuid: compact.uuid,\n })\n }\n\n return {\n compact,\n maskCheckpoint,\n messages: messages.toReversed(),\n nodes,\n settings,\n }\n }\n\n #migrate(nodes: Map<string, SessionNodeView>) {\n for (const n of nodes.values()) {\n const version = n.settings.version ?? 0\n if (version === VERSION) continue\n n.settings = { ...n.settings, version: VERSION }\n\n if (n.type === \"compact\") {\n n.summary.meta = { kind: \"compaction-summary\", ...n.summary.meta }\n continue\n }\n\n if (n.type !== \"message\") continue\n const m = n.message\n\n if (\n m.role === \"system\" &&\n Array.isArray(m.content) &&\n m.content[0].type === \"meta\" &&\n m.content[0].tag === \"task\"\n ) {\n // Missing task meta data kind\n m.meta = { kind: \"task\", ...m.meta }\n }\n\n n.message = m\n }\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { Emitter } from "@zaly/shared";
2
1
  import { Message, ReasoningEffort } from "@zaly/ai";
2
+ import { Emitter } from "@zaly/shared";
3
3
  /** A single node in the session DAG. Same shape on disk (JSONL) as in
4
4
  * memory — what we persist *is* what we navigate. Session settings live ONLY on
5
5
  * `session-settings` nodes as a full snapshot of the cumulative session
@@ -342,4 +342,4 @@ declare class Session<T extends SessionStore = SessionStore> extends Emitter<Ses
342
342
  close(): Promise<void>;
343
343
  }
344
344
  export { SessionStore as a, SessionEvents as c, SessionNode as d, SessionNodeView as f, SessionView as g, SessionUpdate as h, JsonlStore as i, SessionInit as l, SessionSettings as m, MemoryStore as n, MaskCheckpoint as o, SessionOptions as p, JsonlReader as r, PartialNode as s, Session as t, SessionMessage as u };
345
- //# sourceMappingURL=session-DY9mF9Vb.d.mts.map
345
+ //# sourceMappingURL=session-WtXqtAaq.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-DY9mF9Vb.d.mts","names":[],"sources":["../src/session/types.ts","../src/session/store.ts","../src/session/jsonl.ts","../src/session/memory.ts","../src/session/session.ts"],"mappings":";;;;;;;;;KAYK;EACH;;EAEA;;EAEA;;EAEI;;EACA;;EACA;EAA0B,UAAU;;EACpC;EAAiB,SAAS;;EAC1B;EAAyB;EAAmB;;EAE5C;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;;EAKA,SAAS;;KAGV,kBAAkB;KAEX;EAAmB;EAAmB;;KAEtC,iBAAiB;EAAY;EAAY;;KAEzC,YAAY,UAAU,kBAAkB,mBAAmB,QACrE;EACE,MAAM;;;;;KAME,kBAAkB;EAAgB,UAAU;;KAE5C;EACV,UAAU;EACV,OAAO,YAAY;EACnB,UAAU;EACV,iBAAiB;;KAGP;EACV;EACA;EACA;EACA;EACA;EACA,YAAY;;KAGF,gBAAgB,KAAK;KAE5B,iBAAiB,GAAG,UAAU,eAAe,oBAAoB,KAAK,GAAG;KAElE,cAAc,iBAAiB;;;KAM/B;EACV;IAAQ,MAAM;;EACd;IAAY;IAA0B,mBAAmB;;EACzD;IAAW,MAAM;;EAEjB;IAAO;IAAa;;EACpB;IAAS;IAAe;;EACxB;IAAa,QAAQ;IAAiB,OAAO;;EAE7C;EACA;;KAKU,eAAe,UAAU,eAAe;EAClD,QAAQ;;;;;EAKR;;;;;EAKA;;;EAGA,WAAW,KAAK;;KAGN,YAAY,UAAU,eAAe,gBAAgB;;;EAG/D,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;UCjGQ;;;WAGN,MAAM;;EAGf,MAAM,eAAe,QAAQ;;;;EAK7B,QAAQ,MAAM,gBAAgB;;EAG9B,cAAc;;;;EAKd,YAAY,SAAS,eAAe,cAAc;;;;;;;;;;;;;;cCvBvC,sBAAsB;;WACxB;EAKT,YAAY;;;;SAQC,KAAK,eAAe,QAAQ;MAmBrC,QAAQ;EAIN,IAAI,aAAa,QAAQ;EAIzB,MAAM,MAAM,cAAc;EAS1B,SAAS;EAIR,OAAO,cAAc;;cAMjB,YAAY;;WAMF;EAArB,YAAqB;UAsBN;EAgCT,QAAQ,QAAQ;EAMhB,SAAK;;;;;;;cC3IA,uBAAuB;;EAIlC,YAAY,QAAQ,SAAS;MAUzB,QAAQ;EAIN,IAAI,aAAa,QAAQ;EAIzB,MAAM,MAAM,cAAc;EAK/B,OAAO,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCoBN,QAAQ,UAAU,eAAe,sBAAsB,QAAQ;;YAajE,YAAa,MAAM,YAAY;;;;;;;SAe3B,KAAK,UAAU,eAAe,cACzC,MAAM,eAAe;IAAO,OAAO;MAClC,QAAQ,QAAQ;SACN,KAAK,MAAM;IAAmB;MAAiB,QAAQ,QAAQ;SAC/D,KAAK,OAAO,sBAAsB,QAAQ,QAAQ;iBAO1C;;;SAUR,YAAY,OAAM,iBAAsB,QAAQ;;;;MA4BzD,qBAAqB;MAIrB,kBAAkB;MAIlB;MAIA;MAIA;MAIA;;MAKA,YAAY;EAIV,OAAO,UAAU,eAAe;IAAS;MAAoB;;;;;EAe7D,MAAM,WAAW,gBAAgB;;;;;EAqBjC,KAAK,cAAc,UAAU,SAAS;IAAoB;;;;MAS5D;;;EAMJ,SAAS,SAAS,eAAe,cAAc;MAI3C,QAAQ;;;;;;;;;;EAeN,IAAI,SAAS,UAAU;;;;;;EAYvB,QAAQ;IACZ;IACA;IACA;;IAEA,SAAS;;IAET;;IAEA;IACA;IACA,SAAS;MACP;EAgCE,kBAAkB,MAAM,iBAAiB;EAOzC,SAAS,eAAe;;;;;;;;EAexB,QAAQ,iBAAiB,iBAAiB;;EAM1C,SAAS"}
1
+ {"version":3,"file":"session-WtXqtAaq.d.mts","names":[],"sources":["../src/session/types.ts","../src/session/store.ts","../src/session/jsonl.ts","../src/session/memory.ts","../src/session/session.ts"],"mappings":";;;;;;;;;KAYK;EACH;;EAEA;;EAEA;;EAEI;;EACA;;EACA;EAA0B,UAAU;;EACpC;EAAiB,SAAS;;EAC1B;EAAyB;EAAmB;;EAE5C;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;;EAKA,SAAS;;KAGV,kBAAkB;KAEX;EAAmB;EAAmB;;KAEtC,iBAAiB;EAAY;EAAY;;KAEzC,YAAY,UAAU,kBAAkB,mBAAmB,QACrE;EACE,MAAM;;;;;KAME,kBAAkB;EAAgB,UAAU;;KAE5C;EACV,UAAU;EACV,OAAO,YAAY;EACnB,UAAU;EACV,iBAAiB;;KAGP;EACV;EACA;EACA;EACA;EACA;EACA,YAAY;;KAGF,gBAAgB,KAAK;KAE5B,iBAAiB,GAAG,UAAU,eAAe,oBAAoB,KAAK,GAAG;KAElE,cAAc,iBAAiB;;;KAM/B;EACV;IAAQ,MAAM;;EACd;IAAY;IAA0B,mBAAmB;;EACzD;IAAW,MAAM;;EAEjB;IAAO;IAAa;;EACpB;IAAS;IAAe;;EACxB;IAAa,QAAQ;IAAiB,OAAO;;EAE7C;EACA;;KAKU,eAAe,UAAU,eAAe;EAClD,QAAQ;;;;;EAKR;;;;;EAKA;;;EAGA,WAAW,KAAK;;KAGN,YAAY,UAAU,eAAe,gBAAgB;;;EAG/D,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;UCjGQ;;;WAGN,MAAM;;EAGf,MAAM,eAAe,QAAQ;;;;EAK7B,QAAQ,MAAM,gBAAgB;;EAG9B,cAAc;;;;EAKd,YAAY,SAAS,eAAe,cAAc;;;;;;;;;;;;;;cCvBvC,sBAAsB;;WACxB;EAKT,YAAY;;;;SAQC,KAAK,eAAe,QAAQ;MAmBrC,QAAQ;EAIN,IAAI,aAAa,QAAQ;EAIzB,MAAM,MAAM,cAAc;EAS1B,SAAS;EAIR,OAAO,cAAc;;cAMjB,YAAY;;WAMF;EAArB,YAAqB;UAsBN;EAgCT,QAAQ,QAAQ;EAMhB,SAAK;;;;;;;cC3IA,uBAAuB;;EAIlC,YAAY,QAAQ,SAAS;MAUzB,QAAQ;EAIN,IAAI,aAAa,QAAQ;EAIzB,MAAM,MAAM,cAAc;EAK/B,OAAO,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCoBN,QAAQ,UAAU,eAAe,sBAAsB,QAAQ;;YAajE,YAAa,MAAM,YAAY;;;;;;;SAe3B,KAAK,UAAU,eAAe,cACzC,MAAM,eAAe;IAAO,OAAO;MAClC,QAAQ,QAAQ;SACN,KAAK,MAAM;IAAmB;MAAiB,QAAQ,QAAQ;SAC/D,KAAK,OAAO,sBAAsB,QAAQ,QAAQ;iBAO1C;;;SAUR,YAAY,OAAM,iBAAsB,QAAQ;;;;MA4BzD,qBAAqB;MAIrB,kBAAkB;MAIlB;MAIA;MAIA;MAIA;;MAKA,YAAY;EAIV,OAAO,UAAU,eAAe;IAAS;MAAoB;;;;;EAe7D,MAAM,WAAW,gBAAgB;;;;;EAqBjC,KAAK,cAAc,UAAU,SAAS;IAAoB;;;;MAS5D;;;EAMJ,SAAS,SAAS,eAAe,cAAc;MAI3C,QAAQ;;;;;;;;;;EAeN,IAAI,SAAS,UAAU;;;;;;EAYvB,QAAQ;IACZ;IACA;IACA;;IAEA,SAAS;;IAET;;IAEA;IACA;IACA,SAAS;MACP;EAgCE,kBAAkB,MAAM,iBAAiB;EAOzC,SAAS,eAAe;;;;;;;;EAexB,QAAQ,iBAAiB,iBAAiB;;EAM1C,SAAS"}
@@ -1,4 +1,4 @@
1
- import { a as SessionStore, c as SessionEvents, d as SessionNode, f as SessionNodeView, g as SessionView, h as SessionUpdate, i as JsonlStore, l as SessionInit, m as SessionSettings, n as MemoryStore, o as MaskCheckpoint, p as SessionOptions, r as JsonlReader, s as PartialNode, t as Session, u as SessionMessage } from "./session-DY9mF9Vb.mjs";
1
+ import { a as SessionStore, c as SessionEvents, d as SessionNode, f as SessionNodeView, g as SessionView, h as SessionUpdate, i as JsonlStore, l as SessionInit, m as SessionSettings, n as MemoryStore, o as MaskCheckpoint, p as SessionOptions, r as JsonlReader, s as PartialNode, t as Session, u as SessionMessage } from "./session-WtXqtAaq.mjs";
2
2
  import { Stats } from "node:fs";
3
3
  export type SessionInfo = {
4
4
  /** uuidv7 session id. Absent for non-managed external paths until the
package/dist/session.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { n as isUuidv7Like, r as uuidv7 } from "./uuid-rfbQ9ad2.mjs";
2
+ import { r as MemoryStore, t as Session } from "./session-C5ra-Hi1.mjs";
2
3
  import { n as JsonlStore, t as JsonlReader } from "./jsonl-BGt7eqPK.mjs";
3
- import { r as MemoryStore, t as Session } from "./session-CUE48QWX.mjs";
4
4
  import { decodePath, encodePath, normPath, safeStatAsync } from "@zaly/shared";
5
5
  import { basename, dirname, join, relative } from "pathe";
6
6
  import { glob } from "@zaly/shared/glob";
@@ -1,22 +1,18 @@
1
- import { n as __exportAll } from "./rolldown-runtime-DYf_mQCB.mjs";
2
- import { n as parseBash, t as TOOLS } from "./tools-DmoUYORG.mjs";
3
- import "./registry-CntkeXlo.mjs";
1
+ import { n as __exportAll } from "./rolldown-runtime-BVN1G_yT.mjs";
2
+ import "./registry-7mJQhyBA.mjs";
3
+ import { n as parseBash, t as TOOLS } from "./tools-Ca7VsMg3.mjs";
4
+ import { AiError, ContentTransform, attachmentToMeta, defineTool, errorToMeta, extractToolCalls, extractToolResults, metaToText, resolveReasoning, safeParseToolParams, sanitizeText, stringifyContent, toXml } from "@zaly/ai";
4
5
  import { Emitter, formatDuration, isInstance, normPath, prettyPath, safeReadFile, safeStatAsync, safeStringify, toError } from "@zaly/shared";
5
6
  import { LazyCache } from "@zaly/shared/cache";
6
7
  import { BaseCollection } from "@zaly/shared/collection";
7
8
  import { createRegistry } from "@zaly/shared/registry";
8
9
  import { basename, dirname } from "pathe";
9
- import { AiError, ContentTransform, attachmentToMeta, defineTool, errorToMeta, extractToolCalls, extractToolResults, metaToText, safeParseToolParams, sanitizeText, stringifyContent, toXml } from "@zaly/ai";
10
10
  import { glob } from "@zaly/shared/glob";
11
11
  import { readFile } from "node:fs/promises";
12
12
  import { isDeepStrictEqual } from "node:util";
13
13
  import { Type } from "typebox";
14
14
  // src/ctx.ts
15
- var ctx_exports = /* @__PURE__ */ __exportAll({
16
- AgentContext: () => AgentContext,
17
- createAgent: () => createAgent,
18
- createAgentContext: () => createAgentContext
19
- });
15
+ var ctx_exports = /* @__PURE__ */ __exportAll({ createAgent: () => createAgent });
20
16
  var AgentContext = class extends Emitter {
21
17
  #agent;
22
18
  #opts;
@@ -32,7 +28,7 @@ var AgentContext = class extends Emitter {
32
28
  super();
33
29
  this.#opts = opts;
34
30
  this.#cwd = normPath(opts.cwd);
35
- this.#reasoning = opts.request?.reasoning?.effort ?? "medium";
31
+ this.#reasoning = opts.request?.reasoning ?? "medium";
36
32
  this.#session = opts.session;
37
33
  this.#model = opts.model;
38
34
  this.#skills = opts.skills;
@@ -98,14 +94,15 @@ var AgentContext = class extends Emitter {
98
94
  return this.#agent;
99
95
  }
100
96
  get reasoning() {
101
- return this.#reasoning;
97
+ return this.#model ? resolveReasoning(this.#model.spec, this.#reasoning) ?? "off" : this.#reasoning;
102
98
  }
103
99
  set reasoning(r) {
104
100
  if (r === this.#reasoning) return;
105
- const prev = this.#reasoning;
101
+ const prev = this.reasoning;
106
102
  this.#reasoning = r;
107
- this.emit("reasoning", {
108
- effort: r,
103
+ const effort = this.reasoning;
104
+ if (effort !== prev) this.emit("reasoning", {
105
+ effort,
109
106
  prev
110
107
  });
111
108
  }
@@ -141,11 +138,16 @@ var AgentContext = class extends Emitter {
141
138
  set model(m) {
142
139
  if (m === this.#model) return;
143
140
  const prev = this.#model;
141
+ const reasoning = this.reasoning;
144
142
  this.#model = m;
145
143
  this.emit("model", {
146
144
  model: m,
147
145
  prev
148
146
  });
147
+ if (this.reasoning !== reasoning) this.emit("reasoning", {
148
+ effort: this.reasoning,
149
+ prev: reasoning
150
+ });
149
151
  }
150
152
  set tools(tools) {
151
153
  this.#tools = tools;
@@ -181,13 +183,13 @@ var AgentContext = class extends Emitter {
181
183
  }
182
184
  async masker() {
183
185
  return this.#cache.want("masker", async (opts) => {
184
- const { Masker } = await import("./masker-B97uwYXG.mjs");
186
+ const { Masker } = await import("./masker-DWuL2Fjs.mjs");
185
187
  return new Masker(this.agent, opts);
186
188
  }, this.#opts.mask);
187
189
  }
188
190
  async permissions() {
189
191
  return this.#cache.need("permissions", async (opts) => {
190
- const { PermissionManager } = await import("./manager-1zEE5WiA.mjs");
192
+ const { PermissionManager } = await import("./manager-CEociHy_.mjs");
191
193
  return new PermissionManager({
192
194
  ...opts,
193
195
  cwd: this.cwd
@@ -198,7 +200,7 @@ var AgentContext = class extends Emitter {
198
200
  async function loadSession(spec) {
199
201
  if (isInstance(spec)) return spec;
200
202
  else {
201
- const { Session } = await import("./session-CUE48QWX.mjs").then((n) => n.n);
203
+ const { Session } = await import("./session-C5ra-Hi1.mjs").then((n) => n.n);
202
204
  return await Session.load({ ...spec });
203
205
  }
204
206
  }
@@ -210,7 +212,7 @@ async function createAgentContext(opts) {
210
212
  });
211
213
  }
212
214
  async function createAgent(opts) {
213
- const [{ Agent }, ctx] = await Promise.all([import("./agent-DlhEEMPU.mjs"), createAgentContext(opts)]);
215
+ const [{ Agent }, ctx] = await Promise.all([import("./agent-GXRF7DUP.mjs"), createAgentContext(opts)]);
214
216
  return new Agent(ctx);
215
217
  }
216
218
  const promptRegistry = createRegistry("prompt").from({
@@ -257,19 +259,19 @@ async function promptCollection() {
257
259
  const toolRegistry = createRegistry("tool").from({
258
260
  agent_send: () => import("./swarm-D823Yumk.mjs").then((m) => m.agentSendTool),
259
261
  agent_spawn: () => import("./swarm-D823Yumk.mjs").then((m) => m.agentSpawnTool),
260
- bash: () => import("./bash-DSy03sAj.mjs").then((m) => m.bashTool),
261
- edit: () => import("./edit-DT672zIy.mjs").then((m) => m.editTool),
262
- fetch: () => import("./fetch-BrtIqrid.mjs").then((m) => m.fetchTool),
263
- find: () => import("./find-B-vvdlHu.mjs").then((m) => m.findTool),
264
- grep: () => import("./grep-rvZ5S319.mjs").then((m) => m.grepTool),
265
- read: () => import("./read-C5keKntU.mjs").then((m) => m.readTool),
262
+ bash: () => import("./bash-CB_VXpyd.mjs").then((m) => m.bashTool),
263
+ edit: () => import("./edit-gkb6MCW-.mjs").then((m) => m.editTool),
264
+ fetch: () => import("./fetch-D_GzL2yy.mjs").then((m) => m.fetchTool),
265
+ find: () => import("./find-DlrYUTXT.mjs").then((m) => m.findTool),
266
+ grep: () => import("./grep-BI8Rou2q.mjs").then((m) => m.grepTool),
267
+ read: () => import("./read-DLtNq4XJ.mjs").then((m) => m.readTool),
266
268
  search: () => import("./search-B-89W3SM.mjs").then((m) => m.searchTool),
267
- subagent: () => import("./subagent-D-TYaX38.mjs").then((m) => m.subagentTool),
268
- task_list: () => import("./tasks-Dgsiuh0Q.mjs").then((m) => m.taskListTool),
269
- task_poll: () => import("./tasks-Dgsiuh0Q.mjs").then((m) => m.taskPollTool),
270
- task_stop: () => import("./tasks-Dgsiuh0Q.mjs").then((m) => m.taskStopTool),
269
+ subagent: () => import("./subagent-BOK4GFd4.mjs").then((m) => m.subagentTool),
270
+ task_list: () => import("./tasks-BUFqFoh6.mjs").then((m) => m.taskListTool),
271
+ task_poll: () => import("./tasks-BUFqFoh6.mjs").then((m) => m.taskPollTool),
272
+ task_stop: () => import("./tasks-BUFqFoh6.mjs").then((m) => m.taskStopTool),
271
273
  wakeup: () => import("./wakeup-CFr1nu_L.mjs").then((m) => m.wakeupTool),
272
- write: () => import("./write-BRQFfWAn.mjs").then((m) => m.writeTool)
274
+ write: () => import("./write-y93TC5ng.mjs").then((m) => m.writeTool)
273
275
  });
274
276
  var ToolCollection = class extends BaseCollection {
275
277
  list() {
@@ -803,9 +805,34 @@ function fromText(text) {
803
805
  function sumTokens(stats) {
804
806
  return stats.reduce((sum, s) => sum + s.tokens, 0);
805
807
  }
806
- function estimatePart(p) {
808
+ function estimateReasoning(part, ctx) {
809
+ let reasoning = ctx.reasoning;
810
+ if (ctx.model) {
811
+ let requested = "medium";
812
+ if (typeof reasoning === "string") requested = reasoning;
813
+ else if (reasoning === false) requested = "off";
814
+ reasoning = resolveReasoning(ctx.model, requested);
815
+ }
816
+ if (!(reasoning !== "off" && reasoning !== false && (!ctx.model || ctx.model.reasoning === true))) return 0;
817
+ if (ctx.message?.role === "assistant") {
818
+ if (ctx.model && ctx.message.meta?.modelId !== ctx.model.id) return 0;
819
+ const parts = Array.isArray(ctx.message.content) ? ctx.message.content.filter((p) => p.type === "reasoning") : [];
820
+ if (!parts.includes(part)) throw new Error("Reasoning part not found in message content");
821
+ const signed = parts.filter((p) => p.signature);
822
+ const reported = ctx.message.meta?.usage?.reasoning;
823
+ if (signed.length && reported !== void 0 && Number.isFinite(reported) && reported >= 0) {
824
+ if (part !== signed.at(0)) return 0;
825
+ return reported;
826
+ }
827
+ }
828
+ return fromText(part.text);
829
+ }
830
+ function estimatePart(p, ctx = {}) {
807
831
  switch (p.type) {
808
- case "reasoning":
832
+ case "reasoning": return {
833
+ tokens: estimateReasoning(p, ctx),
834
+ type: p.type
835
+ };
809
836
  case "text": return {
810
837
  tokens: fromText(p.text),
811
838
  type: p.type
@@ -816,7 +843,7 @@ function estimatePart(p) {
816
843
  type: p.type
817
844
  };
818
845
  case "tool-result": {
819
- const children = estimateContent(p.content);
846
+ const children = estimateContent(p.content, ctx);
820
847
  return {
821
848
  children,
822
849
  kind: p.name,
@@ -832,7 +859,7 @@ function estimatePart(p) {
832
859
  type: p.type
833
860
  };
834
861
  case "meta": return {
835
- children: p.content ? estimateContent(p.content) : void 0,
862
+ children: p.content ? estimateContent(p.content, ctx) : void 0,
836
863
  kind: p.tag,
837
864
  tokens: fromText(stringifyContent(p)),
838
865
  type: p.type
@@ -844,7 +871,7 @@ function estimatePart(p) {
844
871
  default: throw new Error(`Unknown part type: ${p.type}`);
845
872
  }
846
873
  }
847
- function estimateContent(content) {
874
+ function estimateContent(content, ctx) {
848
875
  if (typeof content === "string") return [{
849
876
  tokens: fromText(content),
850
877
  type: "text"
@@ -852,15 +879,18 @@ function estimateContent(content) {
852
879
  let tokens = 0;
853
880
  const children = [];
854
881
  for (const p of content) {
855
- const partStats = estimatePart(p);
882
+ const partStats = estimatePart(p, ctx);
856
883
  tokens += partStats.tokens;
857
884
  children.push(partStats);
858
885
  }
859
886
  return children;
860
887
  }
861
- function estimateMessage(m) {
888
+ function estimateMessage(m, ctx) {
862
889
  const type = m.role;
863
- const children = estimateContent(m.content);
890
+ const children = estimateContent(m.content, {
891
+ ...ctx,
892
+ message: m
893
+ });
864
894
  return {
865
895
  children,
866
896
  kind: m.role === "system" ? m.meta?.kind : void 0,
@@ -876,7 +906,7 @@ function estimatePrompt(prompt, tools) {
876
906
  }));
877
907
  children.push(...tools?.map((t) => ({
878
908
  kind: t.name,
879
- tokens: fromText(t.name) + fromText(JSON.stringify(t.params ?? {})),
909
+ tokens: fromText(t.name) + fromText(t.desc ?? "") + fromText(JSON.stringify(t.params ?? {})),
880
910
  type: "tool-schema"
881
911
  })) ?? []);
882
912
  return {
@@ -914,8 +944,8 @@ function tokenStats(msgs, opts = {}) {
914
944
  tokens: 0
915
945
  };
916
946
  const counts = [];
917
- if (opts.prompt) counts.push(estimatePrompt(opts.prompt, opts.tools));
918
- counts.push(...msgs.map(estimateMessage));
947
+ if (opts.prompt || opts.tools) counts.push(estimatePrompt(opts.prompt ?? [], opts.tools));
948
+ counts.push(...msgs.map((message) => estimateMessage(message, opts)));
919
949
  for (const stats of counts) {
920
950
  root.tokens += stats.tokens;
921
951
  root.count++;
@@ -946,4 +976,4 @@ function fmt(n) {
946
976
  }
947
977
  export { ctx_exports as _, extractConversation as a, formatFileUsage as c, Commands as d, toolCollection as f, createAgent as g, promptRegistry as h, extractBashUsage as i, messageTail as l, promptCollection as m, formatTokenStats as n, extractFileUsage as o, toolRegistry as p, tokenStats as r, formatBashUsage as s, estimatePart as t, Skills as u };
948
978
 
949
- //# sourceMappingURL=src-DJoqT9yP.mjs.map
979
+ //# sourceMappingURL=src-Di-H3Oya.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src-Di-H3Oya.mjs","names":["builtin"],"sources":["../src/ctx.ts","../src/prompt/registry.ts","../src/tools/registry.ts","../src/commands.ts","../src/skills.ts","../src/compaction/utils.ts","../src/context/tokens.ts"],"sourcesContent":["import type { Model, ReasoningEffort, Tool } from \"@zaly/ai\"\nimport type { Agent } from \"./agent.ts\"\nimport type { AgentStatus } from \"./events.ts\"\nimport type { Masker } from \"./masker.ts\"\nimport type { Notifier, NotifyOptions } from \"./notify.ts\"\nimport type { PermissionManager, PermissionOptions } from \"./permissions/manager.ts\"\nimport type { Session } from \"./session/session.ts\"\nimport type { Skills } from \"./skills.ts\"\nimport type { Swarm } from \"./swarm.ts\"\nimport type { AgentOptions } from \"./types.ts\"\n\nimport { resolveReasoning } from \"@zaly/ai\"\nimport { Emitter, isInstance, normPath } from \"@zaly/shared\"\nimport { LazyCache } from \"@zaly/shared/cache\"\n\ntype AgentContextOptions = Omit<AgentOptions, \"session\"> & { session: Session }\n\ntype Slots = {\n notifier: Notifier\n masker: Masker\n permissions: PermissionManager\n swarm: Swarm\n}\n\nexport type AgentContextEvents = {\n model: { model?: Model; prev?: Model }\n reasoning: { effort: ReasoningEffort; prev?: ReasoningEffort }\n session: { session: Session; prev?: Session }\n cwd: { cwd: string; prev?: string }\n skills: { skills?: Skills }\n}\n\nexport class AgentContext extends Emitter<AgentContextEvents> {\n #agent?: Agent\n #opts: AgentOptions\n #model?: Model\n #session: Session\n #reasoning: ReasoningEffort\n #cwd: string\n #cache = new LazyCache<Slots>()\n #tools: Tool[]\n #skills?: Skills\n #prompt: string[]\n\n constructor(opts: AgentContextOptions) {\n super()\n this.#opts = opts\n this.#cwd = normPath(opts.cwd)\n this.#reasoning = opts.request?.reasoning ?? \"medium\"\n this.#session = opts.session\n this.#model = opts.model\n this.#skills = opts.skills\n this.#prompt = opts.prompt ?? []\n\n this.#tools = opts.tools ?? []\n this.onEmitError = (error) => this.#opts.logger?.child(\"context\").error(error)\n\n this.on(\"model\", async ({ model }) => {\n if (!this.#session.started) return\n if (model) await this.session.update({ modelId: model.id })\n })\n .on(\"reasoning\", async ({ effort }) => {\n if (!this.#session.started) return\n await this.session.update({ reasoning: effort })\n })\n .on(\"cwd\", ({ cwd }) => {\n if (!this.#session.started) return\n this.#cache.forget(\"permissions\") // reset permissions to force reload with new cwd\n void this.session.update({ cwd })\n })\n }\n\n private async start() {\n const [_masker, notifier] = await Promise.all([this.masker(), this.notifier()])\n\n if (!this.model) throw new Error(\"model is required to start agent session\")\n\n if (notifier) notifier.attach(this.agent)\n\n await this.session.start({\n cwd: this.cwd,\n modelId: this.model.id,\n reasoning: this.reasoning,\n })\n // oxlint-disable-next-line no-await-in-loop\n for (const m of this.#opts.messages ?? []) await this.session.add(m)\n }\n\n attach(agent: Agent) {\n if (this.#agent === agent) return\n if (this.#agent) throw new Error(\"agent already attached to context\")\n if (agent.started) throw new Error(\"cannot attach agent that has already started\")\n this.#agent = agent\n agent.once(\"start\", () => this.start())\n }\n\n get messages() {\n return this.session.messages\n }\n\n get status(): AgentStatus | undefined {\n return this.#agent?.status\n }\n\n get opts() {\n return this.#opts\n }\n\n get cwd() {\n return this.#cwd\n }\n\n set cwd(c: string) {\n if (c === this.#cwd) return\n const prev = this.#cwd\n this.#cwd = normPath(c)\n void this.emit(\"cwd\", { cwd: this.#cwd, prev })\n }\n\n get signal() {\n return this.#agent?.signal\n }\n\n get agent() {\n if (!this.#agent) throw new Error(\"agent not attached to context\")\n return this.#agent\n }\n\n get reasoning(): ReasoningEffort {\n return this.#model\n ? (resolveReasoning(this.#model.spec, this.#reasoning) ?? \"off\")\n : this.#reasoning\n }\n\n set reasoning(r: ReasoningEffort) {\n if (r === this.#reasoning) return\n const prev = this.reasoning\n this.#reasoning = r\n const effort = this.reasoning\n if (effort !== prev) void this.emit(\"reasoning\", { effort, prev })\n }\n\n get session(): Session {\n return this.#session\n }\n\n async useSession(s: Session): Promise<void> {\n const prev = this.#session\n this.#session = s\n const modelId = s.settings.modelId\n if (modelId && modelId !== this.model?.id) {\n if (this.#opts.loadModel) {\n this.model = await this.#opts.loadModel(modelId)\n } else {\n const { loadModel } = await import(\"@zaly/ai\")\n this.model = await loadModel(modelId)\n }\n }\n this.cwd = s.settings.cwd ?? this.cwd\n this.reasoning = s.settings.reasoning ?? this.reasoning\n await this.emit(\"session\", { prev, session: s })\n if (this.#agent?.started)\n await s.start({\n cwd: this.cwd,\n modelId: this.model?.id,\n reasoning: this.reasoning,\n })\n }\n\n get model() {\n return this.#model\n }\n\n set model(m: Model | undefined) {\n if (m === this.#model) return\n const prev = this.#model\n const reasoning = this.reasoning\n this.#model = m\n void this.emit(\"model\", { model: m, prev })\n if (this.reasoning !== reasoning)\n void this.emit(\"reasoning\", { effort: this.reasoning, prev: reasoning })\n }\n\n set tools(tools: Tool[]) {\n this.#tools = tools\n }\n\n get tools(): Tool[] {\n return [...this.#tools, ...(this.skills?.tool ? [this.skills.tool] : [])]\n }\n\n get prompt(): string[] {\n return this.#prompt\n }\n\n set prompt(p: string[]) {\n this.#prompt = p\n }\n\n async swarm() {\n return this.#cache.need(\n \"swarm\",\n async () => {\n const { Swarm } = await import(\"./swarm.ts\")\n return new Swarm()\n },\n this.#opts.swarm\n )\n }\n\n set skills(s: Skills | undefined) {\n if (s === this.#skills) return\n this.#skills = s\n void this.emit(\"skills\", { skills: s })\n }\n\n get skills(): Skills | undefined {\n return this.#skills\n }\n\n private async notifier(): Promise<Notifier | undefined> {\n return this.#cache.want(\n \"notifier\",\n async (opts?: NotifyOptions) => {\n const { Notifier } = await import(\"./notify.ts\")\n return new Notifier(opts)\n },\n this.#opts.notify\n )\n }\n\n async masker(): Promise<Masker | undefined> {\n return this.#cache.want(\n \"masker\",\n async (opts?: AgentOptions[\"mask\"]) => {\n const { Masker } = await import(\"./masker.ts\")\n return new Masker(this.agent, opts)\n },\n this.#opts.mask\n )\n }\n\n async permissions(): Promise<PermissionManager> {\n return this.#cache.need(\n \"permissions\",\n async (opts?: PermissionOptions) => {\n const { PermissionManager } = await import(\"./permissions/manager.ts\")\n return new PermissionManager({ ...opts, cwd: this.cwd })\n },\n this.#opts.permissions\n )\n }\n}\n\nasync function loadSession(spec?: AgentOptions[\"session\"]): Promise<Session> {\n if (isInstance<Session>(spec)) return spec\n else {\n const { Session } = await import(\"./session/session.ts\")\n return await Session.load({ ...spec })\n }\n}\n\nexport async function createAgentContext(opts: AgentOptions): Promise<AgentContext> {\n const session = await loadSession(opts.session)\n return new AgentContext({ ...opts, session })\n}\n\nexport async function createAgent(opts: AgentOptions): Promise<Agent> {\n const [{ Agent }, ctx] = await Promise.all([import(\"./agent.ts\"), createAgentContext(opts)])\n return new Agent(ctx)\n}\n","import type { Model } from \"@zaly/ai\"\n\nimport { BaseCollection } from \"@zaly/shared/collection\"\nimport { createRegistry } from \"@zaly/shared/registry\"\n\nexport interface PromptCtx {\n model: Model\n cwd: string\n}\n\nexport type PromptLoader = (ctx: PromptCtx) => Promise<string>\nexport type Prompt<T extends string | PromptLoader = string | PromptLoader> = {\n name: string\n text: T\n}\nexport type { PromptCollection }\n\nconst builtin = {\n \"AGENTS.md\": (ctx) => import(\"./markdown.ts\").then((m) => m.agentsMdPrompt(ctx)),\n \"MEMORY.md\": (ctx) => import(\"./markdown.ts\").then((m) => m.memoryMdPrompt(ctx)),\n agent: () => import(\"./agent.ts\").then((m) => m.agentPrompt),\n env: (ctx) => import(\"./env.ts\").then((m) => m.prompt(ctx)),\n model: (ctx) => import(\"./model.ts\").then((m) => m.prompt(ctx)),\n} as const satisfies Record<string, PromptLoader>\n\nexport type BuiltinPrompt = keyof typeof builtin\nexport type AnyPrompt = BuiltinPrompt | (string & {})\n\nexport const promptRegistry = createRegistry<PromptLoader>(\"prompt\").from(builtin)\n\nclass PromptCollection extends BaseCollection<AnyPrompt[], Prompt[], Prompt> {\n list(): Prompt[] {\n const ret = new Map<string, Prompt>()\n for (const k of promptRegistry.keys())\n ret.set(k, {\n name: k,\n text: (ctx) => promptRegistry.load(k, ctx),\n })\n for (const r of this.registered) ret.set(r.name, r)\n return [...ret.values()]\n }\n\n async render(ctx: PromptCtx & { prompts?: string[] }): Promise<Prompt<string>[]> {\n const all = new Map(this.list().map((p) => [p.name, p]))\n const ret = await Promise.all(\n (ctx.prompts ?? this.active).map(async (p) => {\n const def = all.get(p)\n if (!def) throw new Error(`Unknown prompt: ${p}`)\n return {\n name: def.name,\n text: typeof def.text === \"string\" ? def.text : await def.text(ctx),\n }\n })\n )\n return ret.map((p) => ({ name: p.name, text: p.text.trim() })).filter((p) => p.text.length > 0)\n }\n}\n\nexport async function promptCollection(): Promise<PromptCollection> {\n return new PromptCollection([\"agent\", \"env\", \"model\", \"AGENTS.md\", \"MEMORY.md\"])\n}\n","import type { Model, Tool } from \"@zaly/ai\"\nimport type { AnyKey } from \"@zaly/shared/registry\"\n\nimport { BaseCollection } from \"@zaly/shared/collection\"\nimport { createRegistry } from \"@zaly/shared/registry\"\n\n/** Per-load context handed to every tool factory. Lets factories\n * customise the tool — typically schema descriptions — based on the\n * agent's model and working directory. Tools that don't care about\n * init just ignore the arg. */\nexport interface ToolInit {\n model: Model\n cwd: string\n}\n\nexport type { ToolCollection }\nexport type ToolLoader = () => Promise<Tool>\nexport type BuiltinTool = keyof typeof builtin\nexport type AnyTool = AnyKey<BuiltinTool>\n\n// PERF: `import(\"./x\")` makes TS load the full module type.\n// The `as string` erases the dynamic import type while emitting the same JS.\nconst builtin = {\n agent_send: () => import(\"./swarm.ts\" as string).then((m) => m.agentSendTool as Tool),\n agent_spawn: () => import(\"./swarm.ts\" as string).then((m) => m.agentSpawnTool as Tool),\n bash: () => import(\"./bash.ts\" as string).then((m) => m.bashTool as Tool),\n edit: () => import(\"./edit.ts\" as string).then((m) => m.editTool as Tool),\n fetch: () => import(\"./fetch.ts\" as string).then((m) => m.fetchTool as Tool),\n find: () => import(\"./find.ts\" as string).then((m) => m.findTool as Tool),\n grep: () => import(\"./grep.ts\" as string).then((m) => m.grepTool as Tool),\n read: () => import(\"./read.ts\" as string).then((m) => m.readTool as Tool),\n search: () => import(\"./search.ts\" as string).then((m) => m.searchTool as Tool),\n subagent: () => import(\"./subagent.ts\" as string).then((m) => m.subagentTool as Tool),\n task_list: () => import(\"./tasks.ts\" as string).then((m) => m.taskListTool as Tool),\n task_poll: () => import(\"./tasks.ts\" as string).then((m) => m.taskPollTool as Tool),\n task_stop: () => import(\"./tasks.ts\" as string).then((m) => m.taskStopTool as Tool),\n wakeup: () => import(\"./wakeup.ts\" as string).then((m) => m.wakeupTool as Tool),\n write: () => import(\"./write.ts\" as string).then((m) => m.writeTool as Tool),\n} as const satisfies Record<string, ToolLoader>\n\nexport const toolRegistry = createRegistry<ToolLoader>(\"tool\").from(builtin)\n\nclass ToolCollection extends BaseCollection<AnyTool[], AnyTool[], Tool> {\n list(): AnyTool[] {\n const ret = new Set(toolRegistry.keys())\n for (const r of this.registered) ret.add(r.name)\n return [...ret]\n }\n\n async load(tools?: AnyTool[]): Promise<Tool[]> {\n const load = async (t: string) =>\n this.registered.findLast((r) => r.name === t) ?? toolRegistry.load(t)\n return await Promise.all((tools ?? this.active).map((t) => load(t)))\n }\n}\n\nexport async function toolCollection(): Promise<ToolCollection> {\n return new ToolCollection([])\n}\n","// oxlint-disable no-await-in-loop\nimport type { ArgsOpts, ArgsResult } from \"@zaly/shared/args\"\nimport type { Logger } from \"@zaly/shared/logger\"\n\nimport { normPath, prettyPath, safeReadFile, toError } from \"@zaly/shared\"\nimport { basename } from \"pathe\"\n\nexport type Command = {\n name: string\n body: string\n path: string\n description?: string\n args: ArgsOpts\n}\n\nexport interface CommandsOptions {\n /** cmd.md paths, sorted from highest to lowest precedence. */\n paths?: string[]\n logger?: Logger\n /** Bash execution of commands:\n * - `true`: Use the system default bash shell.\n * - `false`: Disable bash execution.\n * - `string[]`: Use a custom bash shell with the provided arguments. */\n bash?: boolean | string[]\n /** When `false`, template expressions are disabled and only simple variable interpolation is allowed. */\n expr?: boolean\n}\n\ntype Token =\n | { type: \"text\"; value: string }\n | { type: \"block\"; value: string; lang?: string; body: string }\n | { type: \"script\"; value: string }\n\nconst BASH_RE = /^!`(.*)`$/\n\nexport class Commands {\n #opts: CommandsOptions\n readonly catalog = new Map<string, Command>()\n #logger?: Logger\n\n constructor(opts: CommandsOptions = {}) {\n this.#opts = opts\n this.#logger = opts.logger\n }\n\n async load(): Promise<this> {\n const paths = this.#opts.paths ?? []\n await Promise.all(paths.map(async (path) => await this.add(path)))\n return this\n }\n\n async add(path: string): Promise<void> {\n path = normPath(path)\n const name = basename(path, \".md\")\n const { parseFrontmatter } = await import(\"@zaly/shared/yaml\")\n try {\n const content = await safeReadFile(path)\n if (!content) throw new Error(`Failed to read command file at ${path}`)\n\n const { fm, body } = await parseFrontmatter(content)\n\n const args: ArgsOpts = {}\n const fmArgs = (fm.args ?? {}) as Record<string, Partial<ArgsOpts[string]>>\n\n for (const [o, opt] of Object.entries(fmArgs)) {\n // Set default values for boolean\n if (opt.type === \"boolean\") opt.default ??= false\n // Make string options required if no default is provided\n else if (opt.type === \"string\") opt.required ??= opt.default === undefined\n else {\n this.#logger?.warn(\n `Unsupported argument type for \\`--${o}\\` in command **${name}** at \\`${prettyPath(path)}\\`\\nOnly \\`string\\` and \\`boolean\\` are supported. Skipping this argument.`\n )\n continue\n }\n args[o] = opt as ArgsOpts[string]\n }\n\n const cmd: Command = {\n ...fm,\n args,\n body,\n name,\n path,\n }\n if (this.catalog.has(name)) return\n this.catalog.set(name, cmd)\n } catch (error) {\n this.#logger?.error(`Error loading **command** from ${path}: ${(error as Error).message}`)\n }\n }\n\n get(name: string): Command | undefined {\n return this.catalog.get(name)\n }\n\n async format(input: string | ArgsResult, cmd: Command): Promise<string> {\n let args: ArgsResult\n if (typeof input === \"string\") {\n const { argsParse } = await import(\"@zaly/shared/args\")\n args = await argsParse(input, cmd.args)\n } else args = input\n\n const { createTemplate } = await import(\"@zaly/shared/template\")\n const tpl = createTemplate(cmd.body, {\n expr: this.#opts.expr,\n format: (value) => {\n if (value === args._) return args._.join(\" \")\n },\n name: cmd.name,\n })\n\n const vars = {\n ...args,\n args: args._,\n raw: args.$,\n }\n\n const rendered = tpl(vars)\n if (this.#opts.bash === false) return rendered\n const bash = Array.isArray(this.#opts.bash) ? this.#opts.bash : [\"bash\"]\n\n const lines = rendered.split(\"\\n\")\n\n const ret: string[] = []\n for (const token of this.#tokenize(lines, cmd)) {\n let text: string | undefined\n if (token.type === \"script\") text = await exec(token.value, { bash })\n else if (token.type === \"block\" && /^bash\\s*!$/.test(token.lang ?? \"\"))\n text = await exec(token.body, { bash })\n ret.push(text ?? token.value)\n }\n\n return ret.join(\"\\n\")\n }\n\n *#tokenize(lines: string[], cmd: Command): Generator<Token> {\n let block: string[] = []\n let marker: RegExp | undefined = undefined\n let lang: string | undefined = undefined\n for (const line of lines) {\n const m = line.match(/^\\s*(`{3,}|~{3,})(.*)$/)\n const script = line.match(BASH_RE)\n if (marker && line.match(marker)) {\n block.push(line)\n yield {\n body: block.slice(1, -1).join(\"\\n\"),\n lang,\n type: \"block\",\n value: block.join(\"\\n\"),\n }\n marker = undefined // end of code block\n } else if (!marker && m) {\n marker = new RegExp(`^\\\\s*${m[1]}\\\\s*$`) // start of code block\n lang = m[2].trim() || undefined\n block = [line]\n } else if (marker) block.push(line)\n else if (script) yield { type: \"script\", value: script[1] }\n else yield { type: \"text\", value: line }\n }\n if (marker) throw new Error(`Unclosed code block in command **${cmd.name}**`)\n }\n}\n\nasync function exec(script: string, opts: { bash?: string[] } = {}): Promise<string | undefined> {\n if (!script.trim()) return\n const { spawnCmd } = await import(\"@zaly/shared/process\")\n let result: string\n try {\n const r = await spawnCmd(script, { bash: opts.bash ?? true, throw: true })\n result = r?.trim() ?? \"\"\n } catch (error) {\n result = toError(error).message.trim()\n }\n const md: string[] = []\n if (script.includes(\"\\n\")) {\n md.push(\"```bash\")\n md.push(script)\n md.push(\"```\")\n md.push(\"\")\n md.push(\"```shellsession\")\n md.push(result)\n md.push(\"```\")\n } else {\n md.push(\"```shellsession\")\n md.push(`$ ${script}`)\n md.push(result)\n md.push(\"```\")\n }\n md.push(\"\")\n return md.join(\"\\n\")\n}\n","import type { MetaPart, TextPart, Tool, ToolContext } from \"@zaly/ai\"\nimport type { Agent } from \"./agent.ts\"\n\nimport { AiError, defineTool, extractToolResults } from \"@zaly/ai\"\nimport { safeStatAsync } from \"@zaly/shared\"\nimport { glob } from \"@zaly/shared/glob\"\nimport { readFile } from \"node:fs/promises\"\nimport { isDeepStrictEqual } from \"node:util\"\nimport { dirname } from \"pathe\"\nimport { Type } from \"typebox\"\n\nexport type SkillMeta = {\n name: string\n mtime: number\n desc: string\n path: string\n unchanged?: boolean\n}\n\nexport type SkillTool = Tool<{ name: string }, unknown, SkillMeta>\n\n/**\n * Agent Skills support — discovery, catalog, and the activation tool.\n *\n * Locations scanned (subdirectories containing `SKILL.md`):\n * - `${cwd}/.agent/skills/` — project\n * - `${homedir()}/.agent/skills/` — user (cross-project)\n *\n * Project shadows user on name collision.\n *\n * Progressive disclosure (per the Agent Skills spec):\n * - Catalog (name + description) lives in the tool's schema /\n * description. The model sees this from the start.\n * - Body of the SKILL.md is loaded only when the tool is invoked.\n * - References (files under the skill's directory) are *enumerated*\n * at activation, not read — the model reads them via the `read`\n * tool when its instructions call for it.\n *\n * Lifecycle:\n * - Construct with `new Skills({ cwd })` — no I/O yet.\n * - Call `await skills.load()` to populate the catalog. Idempotent;\n * re-call to pick up newly installed skills (`/reload-plugins`).\n * - `skills.tool` returns the current activation tool, or undefined\n * when the catalog is empty. Lazily built; invalidated on reload.\n */\n\nexport interface SkillEntry {\n name: string\n desc: string\n mtime: number\n body: string\n /** Absolute path to the SKILL.md file. */\n path: string\n /** Absolute path to the skill's base directory (parent of SKILL.md).\n * Used as the workspace anchor for permissions and as the root for\n * resolving references. */\n dir: string\n}\n\nexport interface SkillsOptions {\n /** SKILL.md paths, sorted from highest to lowest precedence. */\n paths?: string[]\n}\n\nexport class Skills {\n readonly catalog = new Map<string, SkillEntry>()\n #tool?: Tool\n #opts: SkillsOptions\n\n protected constructor(opts: SkillsOptions = {}) {\n this.#opts = opts\n }\n\n static async load(opts?: SkillsOptions): Promise<Skills> {\n return new Skills(opts).reload()\n }\n\n /** (Re)scan project + user `.agent/skills/` directories. Wipes the\n * current catalog and the cached tool, then repopulates. Safe to\n * call mid-session — agent uses `this.tool` per-step so the next\n * request after reload picks up the change. */\n async reload(): Promise<this> {\n this.catalog.clear()\n this.#tool = undefined\n const paths = this.#opts.paths ?? []\n // Load all skills in parallel, but add them to the catalog in order so\n // that the first one wins on name collision.\n const skills = await Promise.all(paths.map(async (path) => await this.#load(path)))\n for (const skill of skills)\n if (skill && !this.catalog.has(skill.name)) this.catalog.set(skill.name, skill)\n return this\n }\n\n async #load(path: string): Promise<SkillEntry | undefined> {\n if (!path.endsWith(\"SKILL.md\")) return\n const dir = dirname(path)\n try {\n const { meta, mtime, body } = await readSkill(path)\n if (!meta.name || !meta.description || this.catalog.has(meta.name)) return\n return {\n body,\n desc: meta.description,\n dir,\n mtime,\n name: meta.name,\n path,\n }\n } catch {}\n }\n\n async #update(entry: SkillEntry): Promise<SkillEntry> {\n const updated = (await this.#load(entry.path)) ?? entry\n if (isDeepStrictEqual(updated, entry)) return entry\n this.catalog.set(entry.name, updated)\n this.#tool = undefined\n return updated\n }\n\n /** Skill base directories — pass each to `agent.permissions.addWorkspace`\n * so the model can read bundled `references/` files without tripping\n * permission asks. */\n get dirs(): readonly string[] {\n return [...this.catalog.values()].map((s) => s.dir)\n }\n\n /** The activation tool. Returns `undefined` when the catalog is empty\n * (the agent then omits skills entirely from the model's tool list,\n * per the spec). Lazily built on first access; invalidated by\n * `load()`. */\n get tool(): Tool | undefined {\n if (this.catalog.size === 0) return undefined\n return (this.#tool ??= this.#buildTool())\n }\n\n #buildTool(): SkillTool {\n const names = [...this.catalog.keys()]\n // oxlint-disable-next-line sort-keys -- semantic field order: name, desc, params, call\n return defineTool({\n name: \"skill\",\n desc: this.#buildCatalogDesc(),\n parallel: true,\n params: Type.Object({\n name: Type.Union(\n names.map((n) => Type.Literal(n)),\n {\n description:\n \"Name of the skill to activate. The full SKILL.md \" +\n \"instructions are loaded as the tool result; bundled \" +\n \"files in the skill's directory are listed but not read \" +\n \"— fetch them via the `read` tool when the skill's \" +\n \"instructions require them.\",\n }\n ),\n }),\n call: (args, ctx: ToolContext<SkillMeta>) => this.#call(args.name as string, ctx),\n })\n }\n\n async #call(requested: string, ctx: ToolContext<SkillMeta>): Promise<(MetaPart | TextPart)[]> {\n let skill = this.catalog.get(requested)\n if (!skill) {\n const available = [...this.catalog.keys()]\n throw new AiError({\n code: \"UNKNOWN_SKILL\",\n data: { available, name: requested },\n message: `no skill named \"${requested}\". Available: ${available.join(\", \")}`,\n })\n }\n\n // Refresh the skill entry so we have an up-to-date mtime for staleness checks in `isActivated`.\n skill = await this.#update(skill)\n\n ctx.meta = { desc: skill.desc, mtime: skill.mtime, name: skill.name, path: skill.path }\n const activated = await this.isActivated(skill, ctx)\n if (activated) {\n // Already activated and fresh — no need to reload or update the tool result.\n ctx.meta.unchanged = true\n return [\n {\n content: `skill \"${skill.name}\" unchanged since last read: ${skill.path}`,\n tag: \"unchanged\",\n type: \"meta\",\n },\n ]\n }\n\n const references = await listReferences(skill.dir)\n return [\n {\n data: { dir: skill.dir, name: skill.name, references },\n tag: \"skill\",\n type: \"meta\",\n },\n { text: skill.body, type: \"text\" },\n ]\n }\n\n async isActivated(skill: SkillEntry, ctx: ToolContext<SkillMeta>): Promise<boolean> {\n const messages = ctx.messages ?? []\n for (const { m, $p, p } of extractToolResults<SkillMeta, \"skill\">(messages, [\"skill\"])) {\n const id = m.id\n if (!id || !p.meta || ctx.isMasked?.(id, $p)) continue\n if (p.meta.unchanged) continue\n if (p.meta.name === skill.name) return p.meta.mtime === skill.mtime\n }\n return false\n }\n\n async activate(name: string, agent: Agent) {\n const ret = await agent.useTool<SkillTool>(\n \"skill\",\n { name },\n `Skill \"${name}\" was activated by the user.`\n )\n if (ret.result.meta?.unchanged) return\n return ret\n }\n\n #buildCatalogDesc(): string {\n const header =\n \"Activate one of the available skills below. The skill's full \" +\n \"SKILL.md instructions are loaded as the tool result; the model \" +\n \"should follow them directly. Bundled files are listed in the \" +\n \"result but not eagerly read — fetch the ones the skill's \" +\n \"instructions reference via the `read` tool.\"\n const lines = [...this.catalog.values()].map((s) => `- ${s.name}: ${s.desc}`)\n return `${header}\\n\\nAvailable skills:\\n${lines.join(\"\\n\")}`\n }\n}\n\n// ── Discovery ──────────────────────────────────────────────────────────\n\nasync function readSkill(\n path: string\n): Promise<{ meta: { name?: string; description?: string }; body: string; mtime: number }> {\n const s = await safeStatAsync(path)\n if (!s?.isFile()) throw new Error(`Skill file not found at ${path}`)\n const raw = await readFile(path, \"utf8\")\n const { parseFrontmatter } = await import(\"@zaly/shared/yaml\")\n const { fm, body } = await parseFrontmatter(raw)\n return { body, meta: fm, mtime: s.mtimeMs }\n}\n\nasync function listReferences(dir: string): Promise<string[]> {\n const out: string[] = []\n for await (const rel of glob(\"**\", { cwd: dir, depth: 4, type: \"file\" })) {\n if (rel === \"SKILL.md\" || rel.endsWith(\"/SKILL.md\")) continue\n out.push(rel)\n if (out.length >= 200) break\n }\n return out.toSorted()\n}\n","import type { AnyPart, Message } from \"@zaly/ai\"\nimport type { BashTool } from \"../tools/bash.ts\"\nimport type { EditToolMeta } from \"../tools/edit.ts\"\nimport type { ReadToolMeta } from \"../tools/read.ts\"\nimport type { WriteToolMeta } from \"../tools/write.ts\"\n\nimport {\n attachmentToMeta,\n ContentTransform,\n errorToMeta,\n extractToolCalls,\n extractToolResults,\n metaToText,\n safeParseToolParams,\n sanitizeText,\n stringifyContent,\n toXml,\n} from \"@zaly/ai\"\nimport { safeStringify, formatDuration } from \"@zaly/shared\"\nimport { parseBash } from \"../utils/bash/parser.ts\"\nimport { TOOLS } from \"../utils/bash/tools.ts\"\n\nexport type ToolStat = {\n count: number\n score: number\n /** Turns ago at the most recent occurrence (0 = current/last turn).\n * Use with `lastTs` to give the agent both an \"in-experience\" recency\n * signal and a wall-clock staleness signal. */\n lastTurn: number\n /** Wall-clock ms timestamp of the most recent occurrence. `0` if no\n * occurrence carried a timestamp. */\n lastTs: number\n}\n\n/** Per-file activity tally produced by `extractFiles`. Each entry is a\n * path that the agent touched, with per-kind counts and a frecency\n * `score` that downweights older touches and weights writes/edits\n * more than reads. Sort the top-N by `score` to surface the active\n * working set; `reads` / `writes` / `edits` give the per-kind detail\n * for display. */\nexport type FileUsage = ToolStat & {\n path: string\n reads: number\n writes: number\n edits: number\n}\n\n/** Per-command activity tally produced by `extractBashCommands`. `count`\n * is raw invocations; `score` is the same number but exp-decay-weighted\n * by turn distance from the end of the conversation, so recently-used\n * commands rank above old hot ones. */\nexport type BashUsage = ToolStat & {\n command: string\n}\n\n// ── Frecency tuning ───────────────────────────────────────────────────\n// Half-life measured in user turns, not wall time — what matters for\n// compaction context is what's been hot in the agent's *recent\n// experience*, regardless of how long the user spent between turns.\n// 60 turns is a middle ground: actively-iterated work stays at the top\n// while recurring workflow patterns (git stash, test-runner flags) still\n// clear the minScore filter instead of getting buried under one-shot\n// noise from earlier in the session.\nconst HALF_LIFE_TURN = 60\nconst LAMBDA = Math.LN2 / HALF_LIFE_TURN\n// Per-kind weights — writes are the strongest intent signal (full-file\n// authorship), edits the iteration signal, reads the informational one.\nconst KIND_WEIGHTS = { edit: 2, read: 1, write: 3 } as const\n\nexport type ToolStatOptions = {\n minCount?: number\n minScore?: number\n limit?: number\n sort?: \"score\" | \"count\" | \"key\"\n}\n\nconst sorters = {\n count: (a: [string, ToolStat], b: [string, ToolStat]) => b[1].count - a[1].count,\n key: (a: [string, ToolStat], b: [string, ToolStat]) => a[0].localeCompare(b[0]),\n score: (a: [string, ToolStat], b: [string, ToolStat]) => b[1].score - a[1].score,\n} as const satisfies Record<string, (a: [string, ToolStat], b: [string, ToolStat]) => number>\n\nfunction turnInfo(messages: readonly Message[]) {\n const weights: number[] = []\n const turns: number[] = []\n let turn = 0\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i]\n if (m.role === \"assistant\") turn++\n weights[i] = Math.exp(-LAMBDA * turn)\n turns[i] = turn\n }\n return { turns, weights }\n}\n\nfunction toolStats<T extends ToolStat = ToolStat>(\n map: Map<string, T>,\n opts: ToolStatOptions = {}\n): T[] {\n const limit = opts.limit ?? 50\n const sorter = sorters[opts.sort ?? \"score\"]\n const sorted = [...map.entries()].toSorted(sorter).map(([, stat]) => stat)\n return sorted\n .filter((stat) => stat.count >= (opts.minCount ?? 1))\n .filter((stat) => stat.score >= (opts.minScore ?? 0))\n .slice(0, limit)\n}\n\n/** Walk assistant tool-calls for `read` / `write` / `edit` and tally\n * per-path activity with frecency-weighted scoring. Returns the top-N\n * by score. Each entry carries the per-kind breakdown so the\n * summarizer can describe the *kind* of activity (\"heavily edited\",\n * \"read once, then written\", \"iteratively refined\").\n *\n * Paths are canonicalized via the cwd recorded on each call's session\n * node — relative paths are resolved against the cwd that was active\n * when the call ran, and `~` is expanded. Calls under different cwds\n * that target the same file thus collapse into one bucket. */\nexport function extractFileUsage(\n messages: readonly Message[],\n opts: ToolStatOptions = {}\n): FileUsage[] {\n opts = { minScore: 0.5, ...opts }\n const map = new Map<string, FileUsage>()\n const { turns, weights } = turnInfo(messages)\n\n for (const { m, p, $m: idx } of extractToolResults<EditToolMeta | ReadToolMeta | WriteToolMeta>(\n messages,\n [\"read\", \"write\", \"edit\"]\n )) {\n const path = p.meta?.path\n if (!path) continue\n const entry = map.get(path) ?? {\n count: 0,\n edits: 0,\n lastTs: 0,\n lastTurn: Infinity,\n path,\n reads: 0,\n score: 0,\n writes: 0,\n }\n if (p.name === \"read\") entry.reads++\n else if (p.name === \"write\") entry.writes++\n else entry.edits++\n entry.count++\n entry.score += weights[idx] * KIND_WEIGHTS[p.name as keyof typeof KIND_WEIGHTS]\n if (turns[idx] < entry.lastTurn) entry.lastTurn = turns[idx]\n if (m.ts && m.ts > entry.lastTs) entry.lastTs = m.ts\n map.set(path, entry)\n }\n return toolStats(map, opts)\n}\n\n/** Walk assistant tool-calls for `bash`, parse each command line, and\n * tally per-command frecency. Plumbing commands (cat, head, grep, awk,\n * sed, …) are filtered out — they dominate raw counts but carry no\n * operational signal a summarizer would describe. Returns the top-N\n * by frecency `score`. */\nexport function extractBashUsage(\n messages: readonly Message[],\n opts: ToolStatOptions = {}\n): BashUsage[] {\n opts = { minCount: 2, minScore: 0.5, ...opts } // bash commands are noisier, so default to minCount=2\n const { turns, weights } = turnInfo(messages)\n const map = new Map<string, BashUsage>()\n for (const { m, p, $m: idx } of extractToolCalls(messages, [\"bash\"])) {\n const params = safeParseToolParams<BashTool>(p.params)\n const cmd = params?.command\n if (!cmd) continue\n const result = parseBash(cmd)\n if (!result.ok) continue\n const w = weights[idx] ?? 0\n const t = turns[idx] ?? Infinity\n for (const seg of result.segments) {\n if (TOOLS[seg.cmd]) continue\n const key = `${seg.cmd} ${seg.args.join(\" \")}`\n if (key.includes(\"\\n\")) continue\n const entry = map.get(key) ?? {\n command: key,\n count: 0,\n lastTs: 0,\n lastTurn: Infinity,\n score: 0,\n }\n entry.count++\n entry.score += w\n if (t < entry.lastTurn) entry.lastTurn = t\n if (m.ts && m.ts > entry.lastTs) entry.lastTs = m.ts\n map.set(key, entry)\n }\n }\n return toolStats(map, opts)\n}\n\n// ── Transcript ────────────────────────────────────────────────────────\n\nfunction truncate(text: string, len: number): string {\n return text.length <= len ? text : `${text.slice(0, len)}…`\n}\n\n/** Flatten a list of messages into a single tagged transcript. */\nexport function extractConversation(\n messages: readonly Message[],\n opts: { maxToolResultLen?: number } = {}\n): string {\n const transform = ContentTransform.create<AnyPart>()\n .drop(\"reasoning\")\n .map(\"tool-call\", (part) => ({\n content: [\n {\n text: `${part.name}(${safeStringify(part.params)})`,\n type: \"text\" as const,\n },\n ],\n tag: \"tool-call\",\n type: \"meta\",\n }))\n .map(\"tool-result\", (part) => {\n const text = truncate(stringifyContent(part.content), opts.maxToolResultLen ?? 2000)\n return {\n content: text === \"\" ? undefined : [{ text, type: \"text\" as const }],\n data: { tool: part.name, ...(part.isError ? { error: true } : {}) },\n tag: \"tool-result\",\n type: \"meta\" as const,\n }\n })\n .pipe(attachmentToMeta(\"image\", \"pdf\", \"audio\", \"video\"))\n .pipe(errorToMeta())\n .pipe(metaToText())\n .pipe(sanitizeText())\n\n const blocks: string[] = []\n let role: string | undefined = undefined\n for (const m of messages) {\n const parts =\n typeof m.content === \"string\" ? [{ text: m.content, type: \"text\" as const }] : m.content\n const transformed = transform.runSync(parts)\n const text = stringifyContent(transformed).trim()\n if (!text) continue\n let currentRole = m.role.charAt(0).toUpperCase() + m.role.slice(1) // capitalize\n currentRole = currentRole === \"Tool\" ? \"Assistant\" : currentRole // re-label \"Tool\" as \"Assistant\" for summarization purposes\n blocks.push(role === currentRole ? text : `\\n[${currentRole}]: ${text}`)\n role = currentRole\n }\n const text = blocks.join(\"\\n\").replace(/^\\s+$/gm, \"\").trim()\n return toXml(text, \"conversation\", { indent: false })\n}\n\n// ── Tail selection ────────────────────────────────────────────────────\n\nexport function messageTail(\n messages: readonly Message[],\n opts: { keepTokens?: number }\n): Message[] {\n const maxTokens = opts.keepTokens ?? 20_000\n messages = messages.toReversed()\n const tail: Message[] = []\n const queue: Message[] = []\n\n let used = 0\n let last: number | undefined = undefined\n\n for (const m of messages) {\n queue.unshift(m)\n const usage = m.role === \"assistant\" ? m.meta?.usage : undefined\n if (!usage) continue\n const current = usage.input + usage.output + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)\n // clamp for masker and similar events that might shrink the context size\n const delta = Math.max(0, (last ?? current) - current)\n if (used + delta > maxTokens) break\n used += delta\n last = current\n tail.unshift(...queue.splice(0))\n }\n return tail\n}\n\n// -- Formatting helpers -────────────────────────────────────────────────────────\n\nconst lastCol = (lastTurn: number, lastTs: number): string => {\n const turn = lastTurn === Infinity ? \"?\" : `${lastTurn}t`\n const wall = lastTs > 0 ? formatDuration(lastTs) : \"?\"\n return `${turn} / ${wall}`\n}\n\nexport function formatBashUsage(commands: BashUsage[]): string {\n if (commands.length === 0) return \"(no bash commands found)\"\n const lines: string[] = []\n lines.push(\"=== Top bash commands (sorted by frecency) ===\")\n lines.push(` ${\"score\".padStart(7)} ${\"count\".padStart(5)} ${\"last\".padEnd(14)} command`)\n for (const c of commands) {\n lines.push(\n ` ${c.score.toFixed(2).padStart(7)} ${String(c.count).padStart(5)} ${lastCol(c.lastTurn, c.lastTs).padEnd(14)} ${c.command}`\n )\n }\n const text = lines.join(\"\\n\")\n return toXml(text, \"bash-commands\", { indent: false })\n}\n\nexport function formatFileUsage(files: FileUsage[]): string {\n if (files.length === 0) return \"(no file ops found)\"\n const lines: string[] = []\n lines.push(\"=== Top files touched (sorted by frecency) ===\")\n lines.push(\n ` ${\"score\".padStart(7)} ${\"total\".padStart(5)} r/w/e ${\"last\".padEnd(14)} path`\n )\n for (const f of files) {\n const rwe = `${f.reads}/${f.writes}/${f.edits}`.padEnd(12)\n lines.push(\n ` ${f.score.toFixed(2).padStart(7)} ${String(f.count).padStart(5)} ${rwe} ${lastCol(f.lastTurn, f.lastTs).padEnd(14)} ${f.path}`\n )\n }\n const text = lines.join(\"\\n\")\n return toXml(text, \"files\", { indent: false })\n}\n","import type {\n AnyPart,\n AnyType,\n Attachment,\n Message,\n ModelSpec,\n ReasoningEffort,\n ReasoningPart,\n Tool,\n} from \"@zaly/ai\"\nimport type { Prompt } from \"../prompt/registry.ts\"\n\nimport { resolveReasoning, stringifyContent } from \"@zaly/ai\"\n\nexport type TokenContext = {\n reasoning?: ReasoningEffort | boolean\n model?: ModelSpec\n}\n\nexport type MessageTokenContext = TokenContext & {\n message?: Message\n}\n\nexport type TokenCount = {\n type: AnyType | Message[\"role\"] | \"prompt\" | \"tool-schema\" | \"system-prompt\"\n kind?: string\n tokens: number\n children?: TokenCount[]\n}\n\nexport type TokenStats = {\n key: string\n tokens: number\n count: number\n children?: Map<string, TokenStats>\n}\n\n// ── token estimation ───────────────────────────────────────────────────\n\nconst CHARS_PER_TOKEN = 4\n\nconst ATTACHMENT_TOKENS: Record<Attachment[\"type\"], number> = {\n audio: 3000,\n image: 1500,\n pdf: 8000,\n video: 5000,\n}\n\nfunction fromText(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN)\n}\n\nfunction sumTokens(stats: TokenCount[]): number {\n return stats.reduce((sum, s) => sum + s.tokens, 0)\n}\n\nfunction estimateReasoning(part: ReasoningPart, ctx: MessageTokenContext): number {\n let reasoning = ctx.reasoning\n if (ctx.model) {\n let requested: ReasoningEffort = \"medium\"\n if (typeof reasoning === \"string\") requested = reasoning\n else if (reasoning === false) requested = \"off\"\n reasoning = resolveReasoning(ctx.model, requested)\n }\n const enabled =\n reasoning !== \"off\" && reasoning !== false && (!ctx.model || ctx.model.reasoning === true)\n if (!enabled) return 0\n\n if (ctx.message?.role === \"assistant\") {\n // Reasoning parts are for the same model?\n if (ctx.model && ctx.message.meta?.modelId !== ctx.model.id) return 0\n\n const parts = Array.isArray(ctx.message.content)\n ? ctx.message.content.filter((p) => p.type === \"reasoning\")\n : []\n\n // Sanity check\n if (!parts.includes(part)) throw new Error(\"Reasoning part not found in message content\")\n\n const signed = parts.filter((p) => p.signature)\n const reported = ctx.message.meta?.usage?.reasoning\n\n // If the reasoning part is signed, and the message has a reported reasoning token count,\n // attribute the reported reasoning token count to the first signed reasoning part.\n if (signed.length && reported !== undefined && Number.isFinite(reported) && reported >= 0) {\n const first = signed.at(0)\n if (part !== first) return 0\n return reported\n }\n }\n\n // If the reasoning part is not signed, or the message does not have a reported reasoning token count,\n // estimate the token count based on the text length.\n return fromText(part.text)\n}\n\nexport function estimatePart(p: AnyPart, ctx: MessageTokenContext = {}): TokenCount {\n switch (p.type) {\n case \"reasoning\": {\n return { tokens: estimateReasoning(p, ctx), type: p.type }\n }\n case \"text\": {\n return { tokens: fromText(p.text), type: p.type }\n }\n case \"tool-call\": {\n return {\n kind: p.name,\n tokens: fromText(p.name) + fromText(JSON.stringify(p.params ?? {})),\n type: p.type,\n }\n }\n case \"tool-result\": {\n const children = estimateContent(p.content, ctx)\n return {\n children,\n kind: p.name,\n tokens: fromText(p.name) + sumTokens(children),\n type: p.type,\n }\n }\n case \"image\":\n case \"pdf\":\n case \"audio\":\n case \"video\": {\n return { tokens: ATTACHMENT_TOKENS[p.type], type: p.type }\n }\n case \"meta\": {\n const children = p.content ? estimateContent(p.content, ctx) : undefined\n return {\n children,\n kind: p.tag,\n tokens: fromText(stringifyContent(p)),\n type: p.type,\n }\n }\n case \"error\": {\n return { tokens: fromText(stringifyContent(p)), type: p.type }\n }\n default: {\n // @ts-expect-error: exhaustive check\n throw new Error(`Unknown part type: ${p.type}`)\n }\n }\n}\n\nfunction estimateContent(\n content: string | readonly AnyPart[],\n ctx: MessageTokenContext\n): TokenCount[] {\n if (typeof content === \"string\") return [{ tokens: fromText(content), type: \"text\" }]\n let tokens = 0\n const children: TokenCount[] = []\n for (const p of content) {\n const partStats = estimatePart(p, ctx)\n tokens += partStats.tokens\n children.push(partStats)\n }\n return children\n}\n\nfunction estimateMessage(m: Message, ctx: TokenContext): TokenCount {\n const type = m.role\n const children = estimateContent(m.content, { ...ctx, message: m })\n const kind = m.role === \"system\" ? m.meta?.kind : undefined\n return {\n children,\n kind,\n tokens: sumTokens(children),\n type,\n }\n}\n\nfunction estimatePrompt(prompt: (string | Prompt<string>)[], tools?: Tool[]): TokenCount {\n const children: TokenCount[] = prompt.map((p) => ({\n kind: typeof p === \"string\" ? undefined : p.name,\n tokens: fromText(typeof p === \"string\" ? p : p.text),\n type: \"prompt\" as const,\n }))\n children.push(\n ...(tools?.map((t) => ({\n kind: t.name,\n tokens: fromText(t.name) + fromText(t.desc ?? \"\") + fromText(JSON.stringify(t.params ?? {})),\n type: \"tool-schema\" as const,\n })) ?? [])\n )\n return {\n children,\n tokens: sumTokens(children),\n type: \"system-prompt\" as const,\n }\n}\n\nfunction addCount(stat: TokenCount, parent: TokenStats, expand?: (c: TokenCount) => boolean): void {\n const keys = stat.kind ? [stat.type, stat.kind] : [stat.type]\n let child: TokenStats | undefined\n\n for (const key of keys) {\n parent.children ??= new Map()\n child = parent.children.get(key)\n if (!child) {\n child = { children: new Map(), count: 0, key, tokens: 0 }\n parent.children.set(key, child)\n }\n child.tokens += stat.tokens\n child.count++\n parent = child\n }\n\n if (stat.children && child && (!expand || expand(stat))) {\n for (const c of stat.children) addCount(c, child, expand)\n }\n}\n\nexport function tokenStats(\n msgs: readonly Message[],\n opts: {\n prompt?: (string | Prompt<string>)[]\n tools?: Tool[]\n expand?: (c: TokenCount) => boolean\n } & TokenContext = {}\n): TokenStats {\n const root: TokenStats = { children: new Map(), count: 0, key: \"TOTAL\", tokens: 0 }\n const counts: TokenCount[] = []\n if (opts.prompt || opts.tools) counts.push(estimatePrompt(opts.prompt ?? [], opts.tools))\n counts.push(...msgs.map((message) => estimateMessage(message, opts)))\n for (const stats of counts) {\n root.tokens += stats.tokens\n root.count++\n addCount(stats, root, opts.expand)\n }\n return root\n}\n\n// ── stats ──────────────────────────────────────────────────────────────\n\nfunction fmtStats(s: TokenStats, indent = 0): string {\n const header = \" \".repeat(indent) + s.key\n return `${header.padEnd(28)} ${fmt(s.count).padStart(6)}x ${fmt(s.tokens).padStart(14)}`\n}\n\nexport function formatTokenStats(s: TokenStats, indent = 0): string {\n const ret: string[] = []\n const children = s.children\n ? [...s.children.values()].toSorted((a, b) => b.tokens - a.tokens)\n : []\n for (const c of children) {\n ret.push(fmtStats(c, indent))\n if (c.children?.size) ret.push(formatTokenStats(c, indent + 1))\n if (indent === 0) ret.push(\"─\".repeat(51))\n }\n if (indent === 0) {\n ret.unshift(\"─\".repeat(51))\n ret.push(fmtStats(s, indent))\n ret.push(\"─\".repeat(51))\n }\n return ret.join(\"\\n\")\n}\n\nfunction fmt(n: number): string {\n return n.toLocaleString(\"en-US\").replace(/,/g, \"_\")\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgCA,IAAa,eAAb,cAAkC,QAA4B;CAC5D;CACA;CACA;CACA;CACA;CACA;CACA,SAAS,IAAI,UAAiB;CAC9B;CACA;CACA;CAEA,YAAY,MAA2B;EACrC,MAAM;EACN,KAAK,QAAQ;EACb,KAAK,OAAO,SAAS,KAAK,GAAG;EAC7B,KAAK,aAAa,KAAK,SAAS,aAAa;EAC7C,KAAK,WAAW,KAAK;EACrB,KAAK,SAAS,KAAK;EACnB,KAAK,UAAU,KAAK;EACpB,KAAK,UAAU,KAAK,UAAU,CAAC;EAE/B,KAAK,SAAS,KAAK,SAAS,CAAC;EAC7B,KAAK,eAAe,UAAU,KAAK,MAAM,QAAQ,MAAM,SAAS,CAAC,CAAC,MAAM,KAAK;EAE7E,KAAK,GAAG,SAAS,OAAO,EAAE,YAAY;GACpC,IAAI,CAAC,KAAK,SAAS,SAAS;GAC5B,IAAI,OAAO,MAAM,KAAK,QAAQ,OAAO,EAAE,SAAS,MAAM,GAAG,CAAC;EAC5D,CAAC,CAAC,CACC,GAAG,aAAa,OAAO,EAAE,aAAa;GACrC,IAAI,CAAC,KAAK,SAAS,SAAS;GAC5B,MAAM,KAAK,QAAQ,OAAO,EAAE,WAAW,OAAO,CAAC;EACjD,CAAC,CAAC,CACD,GAAG,QAAQ,EAAE,UAAU;GACtB,IAAI,CAAC,KAAK,SAAS,SAAS;GAC5B,KAAK,OAAO,OAAO,aAAa;GAChC,KAAU,QAAQ,OAAO,EAAE,IAAI,CAAC;EAClC,CAAC;CACL;CAEA,MAAc,QAAQ;EACpB,MAAM,CAAC,SAAS,YAAY,MAAM,QAAQ,IAAI,CAAC,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC;EAE9E,IAAI,CAAC,KAAK,OAAO,MAAM,IAAI,MAAM,0CAA0C;EAE3E,IAAI,UAAU,SAAS,OAAO,KAAK,KAAK;EAExC,MAAM,KAAK,QAAQ,MAAM;GACvB,KAAK,KAAK;GACV,SAAS,KAAK,MAAM;GACpB,WAAW,KAAK;EAClB,CAAC;EAED,KAAK,MAAM,KAAK,KAAK,MAAM,YAAY,CAAC,GAAG,MAAM,KAAK,QAAQ,IAAI,CAAC;CACrE;CAEA,OAAO,OAAc;EACnB,IAAI,KAAK,WAAW,OAAO;EAC3B,IAAI,KAAK,QAAQ,MAAM,IAAI,MAAM,mCAAmC;EACpE,IAAI,MAAM,SAAS,MAAM,IAAI,MAAM,8CAA8C;EACjF,KAAK,SAAS;EACd,MAAM,KAAK,eAAe,KAAK,MAAM,CAAC;CACxC;CAEA,IAAI,WAAW;EACb,OAAO,KAAK,QAAQ;CACtB;CAEA,IAAI,SAAkC;EACpC,OAAO,KAAK,QAAQ;CACtB;CAEA,IAAI,OAAO;EACT,OAAO,KAAK;CACd;CAEA,IAAI,MAAM;EACR,OAAO,KAAK;CACd;CAEA,IAAI,IAAI,GAAW;EACjB,IAAI,MAAM,KAAK,MAAM;EACrB,MAAM,OAAO,KAAK;EAClB,KAAK,OAAO,SAAS,CAAC;EACtB,KAAU,KAAK,OAAO;GAAE,KAAK,KAAK;GAAM;EAAK,CAAC;CAChD;CAEA,IAAI,SAAS;EACX,OAAO,KAAK,QAAQ;CACtB;CAEA,IAAI,QAAQ;EACV,IAAI,CAAC,KAAK,QAAQ,MAAM,IAAI,MAAM,+BAA+B;EACjE,OAAO,KAAK;CACd;CAEA,IAAI,YAA6B;EAC/B,OAAO,KAAK,SACP,iBAAiB,KAAK,OAAO,MAAM,KAAK,UAAU,KAAK,QACxD,KAAK;CACX;CAEA,IAAI,UAAU,GAAoB;EAChC,IAAI,MAAM,KAAK,YAAY;EAC3B,MAAM,OAAO,KAAK;EAClB,KAAK,aAAa;EAClB,MAAM,SAAS,KAAK;EACpB,IAAI,WAAW,MAAM,KAAU,KAAK,aAAa;GAAE;GAAQ;EAAK,CAAC;CACnE;CAEA,IAAI,UAAmB;EACrB,OAAO,KAAK;CACd;CAEA,MAAM,WAAW,GAA2B;EAC1C,MAAM,OAAO,KAAK;EAClB,KAAK,WAAW;EAChB,MAAM,UAAU,EAAE,SAAS;EAC3B,IAAI,WAAW,YAAY,KAAK,OAAO,IAAI;GACzC,IAAI,KAAK,MAAM,WACb,KAAK,QAAQ,MAAM,KAAK,MAAM,UAAU,OAAO;QAC1C;IACL,MAAM,EAAE,cAAc,MAAM,OAAO;IACnC,KAAK,QAAQ,MAAM,UAAU,OAAO;GACtC;EACF;EACA,KAAK,MAAM,EAAE,SAAS,OAAO,KAAK;EAClC,KAAK,YAAY,EAAE,SAAS,aAAa,KAAK;EAC9C,MAAM,KAAK,KAAK,WAAW;GAAE;GAAM,SAAS;EAAE,CAAC;EAC/C,IAAI,KAAK,QAAQ,SACf,MAAM,EAAE,MAAM;GACZ,KAAK,KAAK;GACV,SAAS,KAAK,OAAO;GACrB,WAAW,KAAK;EAClB,CAAC;CACL;CAEA,IAAI,QAAQ;EACV,OAAO,KAAK;CACd;CAEA,IAAI,MAAM,GAAsB;EAC9B,IAAI,MAAM,KAAK,QAAQ;EACvB,MAAM,OAAO,KAAK;EAClB,MAAM,YAAY,KAAK;EACvB,KAAK,SAAS;EACd,KAAU,KAAK,SAAS;GAAE,OAAO;GAAG;EAAK,CAAC;EAC1C,IAAI,KAAK,cAAc,WACrB,KAAU,KAAK,aAAa;GAAE,QAAQ,KAAK;GAAW,MAAM;EAAU,CAAC;CAC3E;CAEA,IAAI,MAAM,OAAe;EACvB,KAAK,SAAS;CAChB;CAEA,IAAI,QAAgB;EAClB,OAAO,CAAC,GAAG,KAAK,QAAQ,GAAI,KAAK,QAAQ,OAAO,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,CAAE;CAC1E;CAEA,IAAI,SAAmB;EACrB,OAAO,KAAK;CACd;CAEA,IAAI,OAAO,GAAa;EACtB,KAAK,UAAU;CACjB;CAEA,MAAM,QAAQ;EACZ,OAAO,KAAK,OAAO,KACjB,SACA,YAAY;GACV,MAAM,EAAE,UAAU,MAAM,OAAO;GAC/B,OAAO,IAAI,MAAM;EACnB,GACA,KAAK,MAAM,KACb;CACF;CAEA,IAAI,OAAO,GAAuB;EAChC,IAAI,MAAM,KAAK,SAAS;EACxB,KAAK,UAAU;EACf,KAAU,KAAK,UAAU,EAAE,QAAQ,EAAE,CAAC;CACxC;CAEA,IAAI,SAA6B;EAC/B,OAAO,KAAK;CACd;CAEA,MAAc,WAA0C;EACtD,OAAO,KAAK,OAAO,KACjB,YACA,OAAO,SAAyB;GAC9B,MAAM,EAAE,aAAa,MAAM,OAAO;GAClC,OAAO,IAAI,SAAS,IAAI;EAC1B,GACA,KAAK,MAAM,MACb;CACF;CAEA,MAAM,SAAsC;EAC1C,OAAO,KAAK,OAAO,KACjB,UACA,OAAO,SAAgC;GACrC,MAAM,EAAE,WAAW,MAAM,OAAO;GAChC,OAAO,IAAI,OAAO,KAAK,OAAO,IAAI;EACpC,GACA,KAAK,MAAM,IACb;CACF;CAEA,MAAM,cAA0C;EAC9C,OAAO,KAAK,OAAO,KACjB,eACA,OAAO,SAA6B;GAClC,MAAM,EAAE,sBAAsB,MAAM,OAAO;GAC3C,OAAO,IAAI,kBAAkB;IAAE,GAAG;IAAM,KAAK,KAAK;GAAI,CAAC;EACzD,GACA,KAAK,MAAM,WACb;CACF;AACF;AAEA,eAAe,YAAY,MAAkD;CAC3E,IAAI,WAAoB,IAAI,GAAG,OAAO;MACjC;EACH,MAAM,EAAE,YAAY,MAAM,OAAO,yBAAuB,CAAA,MAAA,MAAA,EAAA,CAAA;EACxD,OAAO,MAAM,QAAQ,KAAK,EAAE,GAAG,KAAK,CAAC;CACvC;AACF;AAEA,eAAsB,mBAAmB,MAA2C;CAClF,MAAM,UAAU,MAAM,YAAY,KAAK,OAAO;CAC9C,OAAO,IAAI,aAAa;EAAE,GAAG;EAAM;CAAQ,CAAC;AAC9C;AAEA,eAAsB,YAAY,MAAoC;CACpE,MAAM,CAAC,EAAE,SAAS,OAAO,MAAM,QAAQ,IAAI,CAAC,OAAO,yBAAe,mBAAmB,IAAI,CAAC,CAAC;CAC3F,OAAO,IAAI,MAAM,GAAG;AACtB;AClPA,MAAa,iBAAiB,eAA6B,QAAQ,CAAC,CAAC,KAAKA;CAVxE,cAAc,QAAQ,OAAO,0BAAgB,CAAC,MAAM,MAAM,EAAE,eAAe,GAAG,CAAC;CAC/E,cAAc,QAAQ,OAAO,0BAAgB,CAAC,MAAM,MAAM,EAAE,eAAe,GAAG,CAAC;CAC/E,aAAa,OAAO,uBAAa,CAAC,MAAM,MAAM,EAAE,WAAW;CAC3D,MAAM,QAAQ,OAAO,qBAAW,CAAC,MAAM,MAAM,EAAE,OAAO,GAAG,CAAC;CAC1D,QAAQ,QAAQ,OAAO,uBAAa,CAAC,MAAM,MAAM,EAAE,OAAO,GAAG,CAAC;AAMUA,CAAO;AAEjF,IAAM,mBAAN,cAA+B,eAA8C;CAC3E,OAAiB;EACf,MAAM,sBAAM,IAAI,IAAoB;EACpC,KAAK,MAAM,KAAK,eAAe,KAAK,GAClC,IAAI,IAAI,GAAG;GACT,MAAM;GACN,OAAO,QAAQ,eAAe,KAAK,GAAG,GAAG;EAC3C,CAAC;EACH,KAAK,MAAM,KAAK,KAAK,YAAY,IAAI,IAAI,EAAE,MAAM,CAAC;EAClD,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC;CACzB;CAEA,MAAM,OAAO,KAAoE;EAC/E,MAAM,MAAM,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;EAWvD,QAAO,MAVW,QAAQ,KACvB,IAAI,WAAW,KAAK,OAAA,CAAQ,IAAI,OAAO,MAAM;GAC5C,MAAM,MAAM,IAAI,IAAI,CAAC;GACrB,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,mBAAmB,GAAG;GAChD,OAAO;IACL,MAAM,IAAI;IACV,MAAM,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,MAAM,IAAI,KAAK,GAAG;GACpE;EACF,CAAC,CACH,EAAA,CACW,KAAK,OAAO;GAAE,MAAM,EAAE;GAAM,MAAM,EAAE,KAAK,KAAK;EAAE,EAAE,CAAC,CAAC,QAAQ,MAAM,EAAE,KAAK,SAAS,CAAC;CAChG;AACF;AAEA,eAAsB,mBAA8C;CAClE,OAAO,IAAI,iBAAiB;EAAC;EAAS;EAAO;EAAS;EAAa;CAAW,CAAC;AACjF;ACpBA,MAAa,eAAe,eAA2B,MAAM,CAAC,CAAC,KAAK;CAjBlE,kBAAkB,OAAO,uBAAuB,CAAC,MAAM,MAAM,EAAE,aAAqB;CACpF,mBAAmB,OAAO,uBAAuB,CAAC,MAAM,MAAM,EAAE,cAAsB;CACtF,YAAY,OAAO,sBAAsB,CAAC,MAAM,MAAM,EAAE,QAAgB;CACxE,YAAY,OAAO,sBAAsB,CAAC,MAAM,MAAM,EAAE,QAAgB;CACxE,aAAa,OAAO,uBAAuB,CAAC,MAAM,MAAM,EAAE,SAAiB;CAC3E,YAAY,OAAO,sBAAsB,CAAC,MAAM,MAAM,EAAE,QAAgB;CACxE,YAAY,OAAO,sBAAsB,CAAC,MAAM,MAAM,EAAE,QAAgB;CACxE,YAAY,OAAO,sBAAsB,CAAC,MAAM,MAAM,EAAE,QAAgB;CACxE,cAAc,OAAO,wBAAwB,CAAC,MAAM,MAAM,EAAE,UAAkB;CAC9E,gBAAgB,OAAO,0BAA0B,CAAC,MAAM,MAAM,EAAE,YAAoB;CACpF,iBAAiB,OAAO,uBAAuB,CAAC,MAAM,MAAM,EAAE,YAAoB;CAClF,iBAAiB,OAAO,uBAAuB,CAAC,MAAM,MAAM,EAAE,YAAoB;CAClF,iBAAiB,OAAO,uBAAuB,CAAC,MAAM,MAAM,EAAE,YAAoB;CAClF,cAAc,OAAO,wBAAwB,CAAC,MAAM,MAAM,EAAE,UAAkB;CAC9E,aAAa,OAAO,uBAAuB,CAAC,MAAM,MAAM,EAAE,SAAiB;AAGT,CAAO;AAE3E,IAAM,iBAAN,cAA6B,eAA2C;CACtE,OAAkB;EAChB,MAAM,MAAM,IAAI,IAAI,aAAa,KAAK,CAAC;EACvC,KAAK,MAAM,KAAK,KAAK,YAAY,IAAI,IAAI,EAAE,IAAI;EAC/C,OAAO,CAAC,GAAG,GAAG;CAChB;CAEA,MAAM,KAAK,OAAoC;EAC7C,MAAM,OAAO,OAAO,MAClB,KAAK,WAAW,UAAU,MAAM,EAAE,SAAS,CAAC,KAAK,aAAa,KAAK,CAAC;EACtE,OAAO,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAA,CAAQ,KAAK,MAAM,KAAK,CAAC,CAAC,CAAC;CACrE;AACF;AAEA,eAAsB,iBAA0C;CAC9D,OAAO,IAAI,eAAe,CAAC,CAAC;AAC9B;;ACzBA,MAAM,UAAU;AAEhB,IAAa,WAAb,MAAsB;CACpB;CACA,0BAAmB,IAAI,IAAqB;CAC5C;CAEA,YAAY,OAAwB,CAAC,GAAG;EACtC,KAAK,QAAQ;EACb,KAAK,UAAU,KAAK;CACtB;CAEA,MAAM,OAAsB;EAC1B,MAAM,QAAQ,KAAK,MAAM,SAAS,CAAC;EACnC,MAAM,QAAQ,IAAI,MAAM,IAAI,OAAO,SAAS,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC;EACjE,OAAO;CACT;CAEA,MAAM,IAAI,MAA6B;EACrC,OAAO,SAAS,IAAI;EACpB,MAAM,OAAO,SAAS,MAAM,KAAK;EACjC,MAAM,EAAE,qBAAqB,MAAM,OAAO;EAC1C,IAAI;GACF,MAAM,UAAU,MAAM,aAAa,IAAI;GACvC,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,kCAAkC,MAAM;GAEtE,MAAM,EAAE,IAAI,SAAS,MAAM,iBAAiB,OAAO;GAEnD,MAAM,OAAiB,CAAC;GACxB,MAAM,SAAU,GAAG,QAAQ,CAAC;GAE5B,KAAK,MAAM,CAAC,GAAG,QAAQ,OAAO,QAAQ,MAAM,GAAG;IAE7C,IAAI,IAAI,SAAS,WAAW,IAAI,YAAY;SAEvC,IAAI,IAAI,SAAS,UAAU,IAAI,aAAa,IAAI,YAAY,KAAA;SAC5D;KACH,KAAK,SAAS,KACZ,qCAAqC,EAAE,kBAAkB,KAAK,UAAU,WAAW,IAAI,EAAE,2EAC3F;KACA;IACF;IACA,KAAK,KAAK;GACZ;GAEA,MAAM,MAAe;IACnB,GAAG;IACH;IACA;IACA;IACA;GACF;GACA,IAAI,KAAK,QAAQ,IAAI,IAAI,GAAG;GAC5B,KAAK,QAAQ,IAAI,MAAM,GAAG;EAC5B,SAAS,OAAO;GACd,KAAK,SAAS,MAAM,kCAAkC,KAAK,IAAK,MAAgB,SAAS;EAC3F;CACF;CAEA,IAAI,MAAmC;EACrC,OAAO,KAAK,QAAQ,IAAI,IAAI;CAC9B;CAEA,MAAM,OAAO,OAA4B,KAA+B;EACtE,IAAI;EACJ,IAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,EAAE,cAAc,MAAM,OAAO;GACnC,OAAO,MAAM,UAAU,OAAO,IAAI,IAAI;EACxC,OAAO,OAAO;EAEd,MAAM,EAAE,mBAAmB,MAAM,OAAO;EAexC,MAAM,WAdM,eAAe,IAAI,MAAM;GACnC,MAAM,KAAK,MAAM;GACjB,SAAS,UAAU;IACjB,IAAI,UAAU,KAAK,GAAG,OAAO,KAAK,EAAE,KAAK,GAAG;GAC9C;GACA,MAAM,IAAI;EACZ,CAQmB,CAAC,CAAC;GALnB,GAAG;GACH,MAAM,KAAK;GACX,KAAK,KAAK;EAGY,CAAC;EACzB,IAAI,KAAK,MAAM,SAAS,OAAO,OAAO;EACtC,MAAM,OAAO,MAAM,QAAQ,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,OAAO,CAAC,MAAM;EAEvE,MAAM,QAAQ,SAAS,MAAM,IAAI;EAEjC,MAAM,MAAgB,CAAC;EACvB,KAAK,MAAM,SAAS,KAAK,UAAU,OAAO,GAAG,GAAG;GAC9C,IAAI;GACJ,IAAI,MAAM,SAAS,UAAU,OAAO,MAAM,KAAK,MAAM,OAAO,EAAE,KAAK,CAAC;QAC/D,IAAI,MAAM,SAAS,WAAW,aAAa,KAAK,MAAM,QAAQ,EAAE,GACnE,OAAO,MAAM,KAAK,MAAM,MAAM,EAAE,KAAK,CAAC;GACxC,IAAI,KAAK,QAAQ,MAAM,KAAK;EAC9B;EAEA,OAAO,IAAI,KAAK,IAAI;CACtB;CAEA,CAAC,UAAU,OAAiB,KAAgC;EAC1D,IAAI,QAAkB,CAAC;EACvB,IAAI,SAA6B,KAAA;EACjC,IAAI,OAA2B,KAAA;EAC/B,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,IAAI,KAAK,MAAM,wBAAwB;GAC7C,MAAM,SAAS,KAAK,MAAM,OAAO;GACjC,IAAI,UAAU,KAAK,MAAM,MAAM,GAAG;IAChC,MAAM,KAAK,IAAI;IACf,MAAM;KACJ,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,IAAI;KAClC;KACA,MAAM;KACN,OAAO,MAAM,KAAK,IAAI;IACxB;IACA,SAAS,KAAA;GACX,OAAO,IAAI,CAAC,UAAU,GAAG;IACvB,SAAS,IAAI,OAAO,QAAQ,EAAE,GAAG,MAAM;IACvC,OAAO,EAAE,EAAE,CAAC,KAAK,KAAK,KAAA;IACtB,QAAQ,CAAC,IAAI;GACf,OAAO,IAAI,QAAQ,MAAM,KAAK,IAAI;QAC7B,IAAI,QAAQ,MAAM;IAAE,MAAM;IAAU,OAAO,OAAO;GAAG;QACrD,MAAM;IAAE,MAAM;IAAQ,OAAO;GAAK;EACzC;EACA,IAAI,QAAQ,MAAM,IAAI,MAAM,oCAAoC,IAAI,KAAK,GAAG;CAC9E;AACF;AAEA,eAAe,KAAK,QAAgB,OAA4B,CAAC,GAAgC;CAC/F,IAAI,CAAC,OAAO,KAAK,GAAG;CACpB,MAAM,EAAE,aAAa,MAAM,OAAO;CAClC,IAAI;CACJ,IAAI;EAEF,UAAS,MADO,SAAS,QAAQ;GAAE,MAAM,KAAK,QAAQ;GAAM,OAAO;EAAK,CAAC,EAAA,EAC7D,KAAK,KAAK;CACxB,SAAS,OAAO;EACd,SAAS,QAAQ,KAAK,CAAC,CAAC,QAAQ,KAAK;CACvC;CACA,MAAM,KAAe,CAAC;CACtB,IAAI,OAAO,SAAS,IAAI,GAAG;EACzB,GAAG,KAAK,SAAS;EACjB,GAAG,KAAK,MAAM;EACd,GAAG,KAAK,KAAK;EACb,GAAG,KAAK,EAAE;EACV,GAAG,KAAK,iBAAiB;EACzB,GAAG,KAAK,MAAM;EACd,GAAG,KAAK,KAAK;CACf,OAAO;EACL,GAAG,KAAK,iBAAiB;EACzB,GAAG,KAAK,KAAK,QAAQ;EACrB,GAAG,KAAK,MAAM;EACd,GAAG,KAAK,KAAK;CACf;CACA,GAAG,KAAK,EAAE;CACV,OAAO,GAAG,KAAK,IAAI;AACrB;;AC/HA,IAAa,SAAb,MAAa,OAAO;CAClB,0BAAmB,IAAI,IAAwB;CAC/C;CACA;CAEA,YAAsB,OAAsB,CAAC,GAAG;EAC9C,KAAK,QAAQ;CACf;CAEA,aAAa,KAAK,MAAuC;EACvD,OAAO,IAAI,OAAO,IAAI,CAAC,CAAC,OAAO;CACjC;;;;;CAMA,MAAM,SAAwB;EAC5B,KAAK,QAAQ,MAAM;EACnB,KAAK,QAAQ,KAAA;EACb,MAAM,QAAQ,KAAK,MAAM,SAAS,CAAC;EAGnC,MAAM,SAAS,MAAM,QAAQ,IAAI,MAAM,IAAI,OAAO,SAAS,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC;EAClF,KAAK,MAAM,SAAS,QAClB,IAAI,SAAS,CAAC,KAAK,QAAQ,IAAI,MAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,MAAM,MAAM,KAAK;EAChF,OAAO;CACT;CAEA,MAAM,MAAM,MAA+C;EACzD,IAAI,CAAC,KAAK,SAAS,UAAU,GAAG;EAChC,MAAM,MAAM,QAAQ,IAAI;EACxB,IAAI;GACF,MAAM,EAAE,MAAM,OAAO,SAAS,MAAM,UAAU,IAAI;GAClD,IAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,eAAe,KAAK,QAAQ,IAAI,KAAK,IAAI,GAAG;GACpE,OAAO;IACL;IACA,MAAM,KAAK;IACX;IACA;IACA,MAAM,KAAK;IACX;GACF;EACF,QAAQ,CAAC;CACX;CAEA,MAAM,QAAQ,OAAwC;EACpD,MAAM,UAAW,MAAM,KAAK,MAAM,MAAM,IAAI,KAAM;EAClD,IAAI,kBAAkB,SAAS,KAAK,GAAG,OAAO;EAC9C,KAAK,QAAQ,IAAI,MAAM,MAAM,OAAO;EACpC,KAAK,QAAQ,KAAA;EACb,OAAO;CACT;;;;CAKA,IAAI,OAA0B;EAC5B,OAAO,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,GAAG;CACpD;;;;;CAMA,IAAI,OAAyB;EAC3B,IAAI,KAAK,QAAQ,SAAS,GAAG,OAAO,KAAA;EACpC,OAAQ,KAAK,UAAU,KAAK,WAAW;CACzC;CAEA,aAAwB;EACtB,MAAM,QAAQ,CAAC,GAAG,KAAK,QAAQ,KAAK,CAAC;EAErC,OAAO,WAAW;GAChB,MAAM;GACN,MAAM,KAAK,kBAAkB;GAC7B,UAAU;GACV,QAAQ,KAAK,OAAO,EAClB,MAAM,KAAK,MACT,MAAM,KAAK,MAAM,KAAK,QAAQ,CAAC,CAAC,GAChC,EACE,aACE,2OAKJ,CACF,EACF,CAAC;GACD,OAAO,MAAM,QAAgC,KAAK,MAAM,KAAK,MAAgB,GAAG;EAClF,CAAC;CACH;CAEA,MAAM,MAAM,WAAmB,KAA+D;EAC5F,IAAI,QAAQ,KAAK,QAAQ,IAAI,SAAS;EACtC,IAAI,CAAC,OAAO;GACV,MAAM,YAAY,CAAC,GAAG,KAAK,QAAQ,KAAK,CAAC;GACzC,MAAM,IAAI,QAAQ;IAChB,MAAM;IACN,MAAM;KAAE;KAAW,MAAM;IAAU;IACnC,SAAS,mBAAmB,UAAU,gBAAgB,UAAU,KAAK,IAAI;GAC3E,CAAC;EACH;EAGA,QAAQ,MAAM,KAAK,QAAQ,KAAK;EAEhC,IAAI,OAAO;GAAE,MAAM,MAAM;GAAM,OAAO,MAAM;GAAO,MAAM,MAAM;GAAM,MAAM,MAAM;EAAK;EAEtF,IAAI,MADoB,KAAK,YAAY,OAAO,GAAG,GACpC;GAEb,IAAI,KAAK,YAAY;GACrB,OAAO,CACL;IACE,SAAS,UAAU,MAAM,KAAK,+BAA+B,MAAM;IACnE,KAAK;IACL,MAAM;GACR,CACF;EACF;EAEA,MAAM,aAAa,MAAM,eAAe,MAAM,GAAG;EACjD,OAAO,CACL;GACE,MAAM;IAAE,KAAK,MAAM;IAAK,MAAM,MAAM;IAAM;GAAW;GACrD,KAAK;GACL,MAAM;EACR,GACA;GAAE,MAAM,MAAM;GAAM,MAAM;EAAO,CACnC;CACF;CAEA,MAAM,YAAY,OAAmB,KAA+C;EAClF,MAAM,WAAW,IAAI,YAAY,CAAC;EAClC,KAAK,MAAM,EAAE,GAAG,IAAI,OAAO,mBAAuC,UAAU,CAAC,OAAO,CAAC,GAAG;GACtF,MAAM,KAAK,EAAE;GACb,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,IAAI,WAAW,IAAI,EAAE,GAAG;GAC9C,IAAI,EAAE,KAAK,WAAW;GACtB,IAAI,EAAE,KAAK,SAAS,MAAM,MAAM,OAAO,EAAE,KAAK,UAAU,MAAM;EAChE;EACA,OAAO;CACT;CAEA,MAAM,SAAS,MAAc,OAAc;EACzC,MAAM,MAAM,MAAM,MAAM,QACtB,SACA,EAAE,KAAK,GACP,UAAU,KAAK,6BACjB;EACA,IAAI,IAAI,OAAO,MAAM,WAAW;EAChC,OAAO;CACT;CAEA,oBAA4B;EAQ1B,OAAO,yTADO,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,KAAK,EAAE,KAAK,IAAI,EAAE,MACxB,CAAC,CAAC,KAAK,IAAI;CAC3D;AACF;AAIA,eAAe,UACb,MACyF;CACzF,MAAM,IAAI,MAAM,cAAc,IAAI;CAClC,IAAI,CAAC,GAAG,OAAO,GAAG,MAAM,IAAI,MAAM,2BAA2B,MAAM;CACnE,MAAM,MAAM,MAAM,SAAS,MAAM,MAAM;CACvC,MAAM,EAAE,qBAAqB,MAAM,OAAO;CAC1C,MAAM,EAAE,IAAI,SAAS,MAAM,iBAAiB,GAAG;CAC/C,OAAO;EAAE;EAAM,MAAM;EAAI,OAAO,EAAE;CAAQ;AAC5C;AAEA,eAAe,eAAe,KAAgC;CAC5D,MAAM,MAAgB,CAAC;CACvB,WAAW,MAAM,OAAO,KAAK,MAAM;EAAE,KAAK;EAAK,OAAO;EAAG,MAAM;CAAO,CAAC,GAAG;EACxE,IAAI,QAAQ,cAAc,IAAI,SAAS,WAAW,GAAG;EACrD,IAAI,KAAK,GAAG;EACZ,IAAI,IAAI,UAAU,KAAK;CACzB;CACA,OAAO,IAAI,SAAS;AACtB;;AC3LA,MAAM,SAAS,KAAK,MAAM;AAG1B,MAAM,eAAe;CAAE,MAAM;CAAG,MAAM;CAAG,OAAO;AAAE;AASlD,MAAM,UAAU;CACd,QAAQ,GAAuB,MAA0B,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;CAC3E,MAAM,GAAuB,MAA0B,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE;CAC9E,QAAQ,GAAuB,MAA0B,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC7E;AAEA,SAAS,SAAS,UAA8B;CAC9C,MAAM,UAAoB,CAAC;CAC3B,MAAM,QAAkB,CAAC;CACzB,IAAI,OAAO;CACX,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;EAE7C,IADU,SAAS,EACd,CAAC,SAAS,aAAa;EAC5B,QAAQ,KAAK,KAAK,IAAI,CAAC,SAAS,IAAI;EACpC,MAAM,KAAK;CACb;CACA,OAAO;EAAE;EAAO;CAAQ;AAC1B;AAEA,SAAS,UACP,KACA,OAAwB,CAAC,GACpB;CACL,MAAM,QAAQ,KAAK,SAAS;CAC5B,MAAM,SAAS,QAAQ,KAAK,QAAQ;CAEpC,OADe,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,KAAK,GAAG,UAAU,IACzD,CAAC,CACV,QAAQ,SAAS,KAAK,UAAU,KAAK,YAAY,EAAE,CAAC,CACpD,QAAQ,SAAS,KAAK,UAAU,KAAK,YAAY,EAAE,CAAC,CACpD,MAAM,GAAG,KAAK;AACnB;;;;;;;;;;;AAYA,SAAgB,iBACd,UACA,OAAwB,CAAC,GACZ;CACb,OAAO;EAAE,UAAU;EAAK,GAAG;CAAK;CAChC,MAAM,sBAAM,IAAI,IAAuB;CACvC,MAAM,EAAE,OAAO,YAAY,SAAS,QAAQ;CAE5C,KAAK,MAAM,EAAE,GAAG,GAAG,IAAI,SAAS,mBAC9B,UACA;EAAC;EAAQ;EAAS;CAAM,CAC1B,GAAG;EACD,MAAM,OAAO,EAAE,MAAM;EACrB,IAAI,CAAC,MAAM;EACX,MAAM,QAAQ,IAAI,IAAI,IAAI,KAAK;GAC7B,OAAO;GACP,OAAO;GACP,QAAQ;GACR,UAAU;GACV;GACA,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA,IAAI,EAAE,SAAS,QAAQ,MAAM;OACxB,IAAI,EAAE,SAAS,SAAS,MAAM;OAC9B,MAAM;EACX,MAAM;EACN,MAAM,SAAS,QAAQ,OAAO,aAAa,EAAE;EAC7C,IAAI,MAAM,OAAO,MAAM,UAAU,MAAM,WAAW,MAAM;EACxD,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,QAAQ,MAAM,SAAS,EAAE;EAClD,IAAI,IAAI,MAAM,KAAK;CACrB;CACA,OAAO,UAAU,KAAK,IAAI;AAC5B;;;;;;AAOA,SAAgB,iBACd,UACA,OAAwB,CAAC,GACZ;CACb,OAAO;EAAE,UAAU;EAAG,UAAU;EAAK,GAAG;CAAK;CAC7C,MAAM,EAAE,OAAO,YAAY,SAAS,QAAQ;CAC5C,MAAM,sBAAM,IAAI,IAAuB;CACvC,KAAK,MAAM,EAAE,GAAG,GAAG,IAAI,SAAS,iBAAiB,UAAU,CAAC,MAAM,CAAC,GAAG;EAEpE,MAAM,MADS,oBAA8B,EAAE,MAC9B,CAAC,EAAE;EACpB,IAAI,CAAC,KAAK;EACV,MAAM,SAAS,UAAU,GAAG;EAC5B,IAAI,CAAC,OAAO,IAAI;EAChB,MAAM,IAAI,QAAQ,QAAQ;EAC1B,MAAM,IAAI,MAAM,QAAQ;EACxB,KAAK,MAAM,OAAO,OAAO,UAAU;GACjC,IAAI,MAAM,IAAI,MAAM;GACpB,MAAM,MAAM,GAAG,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;GAC3C,IAAI,IAAI,SAAS,IAAI,GAAG;GACxB,MAAM,QAAQ,IAAI,IAAI,GAAG,KAAK;IAC5B,SAAS;IACT,OAAO;IACP,QAAQ;IACR,UAAU;IACV,OAAO;GACT;GACA,MAAM;GACN,MAAM,SAAS;GACf,IAAI,IAAI,MAAM,UAAU,MAAM,WAAW;GACzC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,QAAQ,MAAM,SAAS,EAAE;GAClD,IAAI,IAAI,KAAK,KAAK;EACpB;CACF;CACA,OAAO,UAAU,KAAK,IAAI;AAC5B;AAIA,SAAS,SAAS,MAAc,KAAqB;CACnD,OAAO,KAAK,UAAU,MAAM,OAAO,GAAG,KAAK,MAAM,GAAG,GAAG,EAAE;AAC3D;;AAGA,SAAgB,oBACd,UACA,OAAsC,CAAC,GAC/B;CACR,MAAM,YAAY,iBAAiB,OAAgB,CAAC,CACjD,KAAK,WAAW,CAAC,CACjB,IAAI,cAAc,UAAU;EAC3B,SAAS,CACP;GACE,MAAM,GAAG,KAAK,KAAK,GAAG,cAAc,KAAK,MAAM,EAAE;GACjD,MAAM;EACR,CACF;EACA,KAAK;EACL,MAAM;CACR,EAAE,CAAC,CACF,IAAI,gBAAgB,SAAS;EAC5B,MAAM,OAAO,SAAS,iBAAiB,KAAK,OAAO,GAAG,KAAK,oBAAoB,GAAI;EACnF,OAAO;GACL,SAAS,SAAS,KAAK,KAAA,IAAY,CAAC;IAAE;IAAM,MAAM;GAAgB,CAAC;GACnE,MAAM;IAAE,MAAM,KAAK;IAAM,GAAI,KAAK,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;GAAG;GAClE,KAAK;GACL,MAAM;EACR;CACF,CAAC,CAAC,CACD,KAAK,iBAAiB,SAAS,OAAO,SAAS,OAAO,CAAC,CAAC,CACxD,KAAK,YAAY,CAAC,CAAC,CACnB,KAAK,WAAW,CAAC,CAAC,CAClB,KAAK,aAAa,CAAC;CAEtB,MAAM,SAAmB,CAAC;CAC1B,IAAI,OAA2B,KAAA;CAC/B,KAAK,MAAM,KAAK,UAAU;EACxB,MAAM,QACJ,OAAO,EAAE,YAAY,WAAW,CAAC;GAAE,MAAM,EAAE;GAAS,MAAM;EAAgB,CAAC,IAAI,EAAE;EACnF,MAAM,cAAc,UAAU,QAAQ,KAAK;EAC3C,MAAM,OAAO,iBAAiB,WAAW,CAAC,CAAC,KAAK;EAChD,IAAI,CAAC,MAAM;EACX,IAAI,cAAc,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,KAAK,MAAM,CAAC;EACjE,cAAc,gBAAgB,SAAS,cAAc;EACrD,OAAO,KAAK,SAAS,cAAc,OAAO,MAAM,YAAY,KAAK,MAAM;EACvE,OAAO;CACT;CACA,MAAM,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,QAAQ,WAAW,EAAE,CAAC,CAAC,KAAK;CAC3D,OAAO,MAAM,MAAM,gBAAgB,EAAE,QAAQ,MAAM,CAAC;AACtD;AAIA,SAAgB,YACd,UACA,MACW;CACX,MAAM,YAAY,KAAK,cAAc;CACrC,WAAW,SAAS,WAAW;CAC/B,MAAM,OAAkB,CAAC;CACzB,MAAM,QAAmB,CAAC;CAE1B,IAAI,OAAO;CACX,IAAI,OAA2B,KAAA;CAE/B,KAAK,MAAM,KAAK,UAAU;EACxB,MAAM,QAAQ,CAAC;EACf,MAAM,QAAQ,EAAE,SAAS,cAAc,EAAE,MAAM,QAAQ,KAAA;EACvD,IAAI,CAAC,OAAO;EACZ,MAAM,UAAU,MAAM,QAAQ,MAAM,UAAU,MAAM,aAAa,MAAM,MAAM,cAAc;EAE3F,MAAM,QAAQ,KAAK,IAAI,IAAI,QAAQ,WAAW,OAAO;EACrD,IAAI,OAAO,QAAQ,WAAW;EAC9B,QAAQ;EACR,OAAO;EACP,KAAK,QAAQ,GAAG,MAAM,OAAO,CAAC,CAAC;CACjC;CACA,OAAO;AACT;AAIA,MAAM,WAAW,UAAkB,WAA2B;CAG5D,OAAO,GAFM,aAAa,WAAW,MAAM,GAAG,SAAS,GAExC,KADF,SAAS,IAAI,eAAe,MAAM,IAAI;AAErD;AAEA,SAAgB,gBAAgB,UAA+B;CAC7D,IAAI,SAAS,WAAW,GAAG,OAAO;CAClC,MAAM,QAAkB,CAAC;CACzB,MAAM,KAAK,gDAAgD;CAC3D,MAAM,KAAK,KAAK,QAAQ,SAAS,CAAC,EAAE,IAAI,QAAQ,SAAS,CAAC,EAAE,IAAI,OAAO,OAAO,EAAE,EAAE,UAAU;CAC5F,KAAK,MAAM,KAAK,UACd,MAAM,KACJ,KAAK,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SACzH;CAEF,MAAM,OAAO,MAAM,KAAK,IAAI;CAC5B,OAAO,MAAM,MAAM,iBAAiB,EAAE,QAAQ,MAAM,CAAC;AACvD;AAEA,SAAgB,gBAAgB,OAA4B;CAC1D,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,QAAkB,CAAC;CACzB,MAAM,KAAK,gDAAgD;CAC3D,MAAM,KACJ,KAAK,QAAQ,SAAS,CAAC,EAAE,IAAI,QAAQ,SAAS,CAAC,EAAE,kBAAkB,OAAO,OAAO,EAAE,EAAE,OACvF;CACA,KAAK,MAAM,KAAK,OAAO;EACrB,MAAM,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;EACzD,MAAM,KACJ,KAAK,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,IAAI,IAAI,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MACjI;CACF;CACA,MAAM,OAAO,MAAM,KAAK,IAAI;CAC5B,OAAO,MAAM,MAAM,SAAS,EAAE,QAAQ,MAAM,CAAC;AAC/C;;ACpRA,MAAM,kBAAkB;AAExB,MAAM,oBAAwD;CAC5D,OAAO;CACP,OAAO;CACP,KAAK;CACL,OAAO;AACT;AAEA,SAAS,SAAS,MAAsB;CACtC,OAAO,KAAK,KAAK,KAAK,SAAS,eAAe;AAChD;AAEA,SAAS,UAAU,OAA6B;CAC9C,OAAO,MAAM,QAAQ,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACnD;AAEA,SAAS,kBAAkB,MAAqB,KAAkC;CAChF,IAAI,YAAY,IAAI;CACpB,IAAI,IAAI,OAAO;EACb,IAAI,YAA6B;EACjC,IAAI,OAAO,cAAc,UAAU,YAAY;OAC1C,IAAI,cAAc,OAAO,YAAY;EAC1C,YAAY,iBAAiB,IAAI,OAAO,SAAS;CACnD;CAGA,IAAI,EADF,cAAc,SAAS,cAAc,UAAU,CAAC,IAAI,SAAS,IAAI,MAAM,cAAc,QACzE,OAAO;CAErB,IAAI,IAAI,SAAS,SAAS,aAAa;EAErC,IAAI,IAAI,SAAS,IAAI,QAAQ,MAAM,YAAY,IAAI,MAAM,IAAI,OAAO;EAEpE,MAAM,QAAQ,MAAM,QAAQ,IAAI,QAAQ,OAAO,IAC3C,IAAI,QAAQ,QAAQ,QAAQ,MAAM,EAAE,SAAS,WAAW,IACxD,CAAC;EAGL,IAAI,CAAC,MAAM,SAAS,IAAI,GAAG,MAAM,IAAI,MAAM,6CAA6C;EAExF,MAAM,SAAS,MAAM,QAAQ,MAAM,EAAE,SAAS;EAC9C,MAAM,WAAW,IAAI,QAAQ,MAAM,OAAO;EAI1C,IAAI,OAAO,UAAU,aAAa,KAAA,KAAa,OAAO,SAAS,QAAQ,KAAK,YAAY,GAAG;GAEzF,IAAI,SADU,OAAO,GAAG,CACP,GAAG,OAAO;GAC3B,OAAO;EACT;CACF;CAIA,OAAO,SAAS,KAAK,IAAI;AAC3B;AAEA,SAAgB,aAAa,GAAY,MAA2B,CAAC,GAAe;CAClF,QAAQ,EAAE,MAAV;EACE,KAAK,aACH,OAAO;GAAE,QAAQ,kBAAkB,GAAG,GAAG;GAAG,MAAM,EAAE;EAAK;EAE3D,KAAK,QACH,OAAO;GAAE,QAAQ,SAAS,EAAE,IAAI;GAAG,MAAM,EAAE;EAAK;EAElD,KAAK,aACH,OAAO;GACL,MAAM,EAAE;GACR,QAAQ,SAAS,EAAE,IAAI,IAAI,SAAS,KAAK,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;GAClE,MAAM,EAAE;EACV;EAEF,KAAK,eAAe;GAClB,MAAM,WAAW,gBAAgB,EAAE,SAAS,GAAG;GAC/C,OAAO;IACL;IACA,MAAM,EAAE;IACR,QAAQ,SAAS,EAAE,IAAI,IAAI,UAAU,QAAQ;IAC7C,MAAM,EAAE;GACV;EACF;EACA,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH,OAAO;GAAE,QAAQ,kBAAkB,EAAE;GAAO,MAAM,EAAE;EAAK;EAE3D,KAAK,QAEH,OAAO;GACL,UAFe,EAAE,UAAU,gBAAgB,EAAE,SAAS,GAAG,IAAI,KAAA;GAG7D,MAAM,EAAE;GACR,QAAQ,SAAS,iBAAiB,CAAC,CAAC;GACpC,MAAM,EAAE;EACV;EAEF,KAAK,SACH,OAAO;GAAE,QAAQ,SAAS,iBAAiB,CAAC,CAAC;GAAG,MAAM,EAAE;EAAK;EAE/D,SAEE,MAAM,IAAI,MAAM,sBAAsB,EAAE,MAAM;CAElD;AACF;AAEA,SAAS,gBACP,SACA,KACc;CACd,IAAI,OAAO,YAAY,UAAU,OAAO,CAAC;EAAE,QAAQ,SAAS,OAAO;EAAG,MAAM;CAAO,CAAC;CACpF,IAAI,SAAS;CACb,MAAM,WAAyB,CAAC;CAChC,KAAK,MAAM,KAAK,SAAS;EACvB,MAAM,YAAY,aAAa,GAAG,GAAG;EACrC,UAAU,UAAU;EACpB,SAAS,KAAK,SAAS;CACzB;CACA,OAAO;AACT;AAEA,SAAS,gBAAgB,GAAY,KAA+B;CAClE,MAAM,OAAO,EAAE;CACf,MAAM,WAAW,gBAAgB,EAAE,SAAS;EAAE,GAAG;EAAK,SAAS;CAAE,CAAC;CAElE,OAAO;EACL;EACA,MAHW,EAAE,SAAS,WAAW,EAAE,MAAM,OAAO,KAAA;EAIhD,QAAQ,UAAU,QAAQ;EAC1B;CACF;AACF;AAEA,SAAS,eAAe,QAAqC,OAA4B;CACvF,MAAM,WAAyB,OAAO,KAAK,OAAO;EAChD,MAAM,OAAO,MAAM,WAAW,KAAA,IAAY,EAAE;EAC5C,QAAQ,SAAS,OAAO,MAAM,WAAW,IAAI,EAAE,IAAI;EACnD,MAAM;CACR,EAAE;CACF,SAAS,KACP,GAAI,OAAO,KAAK,OAAO;EACrB,MAAM,EAAE;EACR,QAAQ,SAAS,EAAE,IAAI,IAAI,SAAS,EAAE,QAAQ,EAAE,IAAI,SAAS,KAAK,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;EAC3F,MAAM;CACR,EAAE,KAAK,CAAC,CACV;CACA,OAAO;EACL;EACA,QAAQ,UAAU,QAAQ;EAC1B,MAAM;CACR;AACF;AAEA,SAAS,SAAS,MAAkB,QAAoB,QAA2C;CACjG,MAAM,OAAO,KAAK,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI;CAC5D,IAAI;CAEJ,KAAK,MAAM,OAAO,MAAM;EACtB,OAAO,6BAAa,IAAI,IAAI;EAC5B,QAAQ,OAAO,SAAS,IAAI,GAAG;EAC/B,IAAI,CAAC,OAAO;GACV,QAAQ;IAAE,0BAAU,IAAI,IAAI;IAAG,OAAO;IAAG;IAAK,QAAQ;GAAE;GACxD,OAAO,SAAS,IAAI,KAAK,KAAK;EAChC;EACA,MAAM,UAAU,KAAK;EACrB,MAAM;EACN,SAAS;CACX;CAEA,IAAI,KAAK,YAAY,UAAU,CAAC,UAAU,OAAO,IAAI,IACnD,KAAK,MAAM,KAAK,KAAK,UAAU,SAAS,GAAG,OAAO,MAAM;AAE5D;AAEA,SAAgB,WACd,MACA,OAImB,CAAC,GACR;CACZ,MAAM,OAAmB;EAAE,0BAAU,IAAI,IAAI;EAAG,OAAO;EAAG,KAAK;EAAS,QAAQ;CAAE;CAClF,MAAM,SAAuB,CAAC;CAC9B,IAAI,KAAK,UAAU,KAAK,OAAO,OAAO,KAAK,eAAe,KAAK,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC;CACxF,OAAO,KAAK,GAAG,KAAK,KAAK,YAAY,gBAAgB,SAAS,IAAI,CAAC,CAAC;CACpE,KAAK,MAAM,SAAS,QAAQ;EAC1B,KAAK,UAAU,MAAM;EACrB,KAAK;EACL,SAAS,OAAO,MAAM,KAAK,MAAM;CACnC;CACA,OAAO;AACT;AAIA,SAAS,SAAS,GAAe,SAAS,GAAW;CAEnD,OAAO,IADQ,KAAK,OAAO,MAAM,IAAI,EAAE,IAAA,CACtB,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC,SAAS,EAAE;AACvF;AAEA,SAAgB,iBAAiB,GAAe,SAAS,GAAW;CAClE,MAAM,MAAgB,CAAC;CACvB,MAAM,WAAW,EAAE,WACf,CAAC,GAAG,EAAE,SAAS,OAAO,CAAC,CAAC,CAAC,UAAU,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,IAC/D,CAAC;CACL,KAAK,MAAM,KAAK,UAAU;EACxB,IAAI,KAAK,SAAS,GAAG,MAAM,CAAC;EAC5B,IAAI,EAAE,UAAU,MAAM,IAAI,KAAK,iBAAiB,GAAG,SAAS,CAAC,CAAC;EAC9D,IAAI,WAAW,GAAG,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;CAC3C;CACA,IAAI,WAAW,GAAG;EAChB,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;EAC1B,IAAI,KAAK,SAAS,GAAG,MAAM,CAAC;EAC5B,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;CACzB;CACA,OAAO,IAAI,KAAK,IAAI;AACtB;AAEA,SAAS,IAAI,GAAmB;CAC9B,OAAO,EAAE,eAAe,OAAO,CAAC,CAAC,QAAQ,MAAM,GAAG;AACpD"}