{"version":3,"sources":["../src/human-plus/events.ts","../src/human-plus/file-store.ts"],"names":["readFile","mkdir","dirname","open","writeFile","rename"],"mappings":"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","file":"human-plus-node.cjs","sourcesContent":["export type HumanPlusActor = { kind: \"human\" | \"agent\" | \"system\"; id: string; name?: string };\nexport type HumanPlusPriority = \"background\" | \"normal\" | \"attention\" | \"blocking\";\nexport type HumanPlusDisposition = \"seen\" | \"handled\" | \"rejected\" | \"ignored\";\n\nexport interface HumanPlusEvent<T = unknown> {\n  id: string;\n  sequence: number;\n  timestamp: number;\n  appId: string;\n  surfaceId: string;\n  sessionId?: string;\n  type: string;\n  payload: T;\n  actor: HumanPlusActor;\n  priority: HumanPlusPriority;\n  correlationId?: string;\n  causationId?: string;\n}\nexport type NewHumanPlusEvent<T = unknown> = Omit<HumanPlusEvent<T>, \"id\" | \"sequence\" | \"timestamp\"> & Partial<Pick<HumanPlusEvent<T>, \"id\" | \"timestamp\">>;\nexport interface HumanPlusEventQuery { consumerId: string; after?: number; limit?: number; unacknowledgedOnly?: boolean; types?: string[]; surfaces?: string[]; }\nexport interface HumanPlusEventPage { events: HumanPlusEvent[]; nextCursor: number; }\nexport type HumanPlusEventListener = (event: HumanPlusEvent) => void;\n\nexport interface HumanPlusEventStore {\n  append(event: NewHumanPlusEvent): Promise<HumanPlusEvent>;\n  list(query: HumanPlusEventQuery): Promise<HumanPlusEventPage>;\n  acknowledge(consumerId: string, eventIds: string[], disposition: HumanPlusDisposition): Promise<void>;\n  subscribe(listener: HumanPlusEventListener): () => void;\n  compact?(options?: { before?: number; keepLast?: number }): Promise<void>;\n}\n\nexport class MemoryHumanPlusEventStore implements HumanPlusEventStore {\n  protected events: HumanPlusEvent[] = [];\n  protected acknowledgements = new Map<string, Map<string, HumanPlusDisposition>>();\n  protected listeners = new Set<HumanPlusEventListener>();\n  protected nextSequence = 1;\n\n  async append(input: NewHumanPlusEvent): Promise<HumanPlusEvent> {\n    const event: HumanPlusEvent = { ...input, id: input.id ?? globalThis.crypto.randomUUID(), timestamp: input.timestamp ?? Date.now(), sequence: this.nextSequence++ };\n    this.events.push(event); this.listeners.forEach((listener) => listener(event)); return event;\n  }\n  async list(query: HumanPlusEventQuery): Promise<HumanPlusEventPage> {\n    const acknowledged = this.acknowledgements.get(query.consumerId);\n    const events = this.events.filter((event) => event.sequence > (query.after ?? 0)\n      && (!query.unacknowledgedOnly || !acknowledged?.has(event.id))\n      && (!query.types?.length || query.types.includes(event.type))\n      && (!query.surfaces?.length || query.surfaces.includes(event.surfaceId)))\n      .slice(0, Math.max(1, Math.min(500, query.limit ?? 50)));\n    return { events, nextCursor: events.at(-1)?.sequence ?? query.after ?? 0 };\n  }\n  async acknowledge(consumerId: string, eventIds: string[], disposition: HumanPlusDisposition): Promise<void> {\n    let values = this.acknowledgements.get(consumerId); if (!values) { values = new Map(); this.acknowledgements.set(consumerId, values); }\n    eventIds.forEach((id) => values!.set(id, disposition));\n  }\n  subscribe(listener: HumanPlusEventListener): () => void { this.listeners.add(listener); return () => this.listeners.delete(listener); }\n  async compact(options: { before?: number; keepLast?: number } = {}): Promise<void> {\n    const cutoff = options.before ?? Number.POSITIVE_INFINITY; const keep = options.keepLast ?? 1000;\n    const removable = Math.max(0, this.events.length - keep);\n    this.events = this.events.filter((event, index) => index >= removable || event.timestamp >= cutoff);\n    const ids = new Set(this.events.map((event) => event.id));\n    for (const values of this.acknowledgements.values()) for (const id of values.keys()) if (!ids.has(id)) values.delete(id);\n  }\n}\n","import { mkdir, open, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { MemoryHumanPlusEventStore, type HumanPlusDisposition, type HumanPlusEvent, type NewHumanPlusEvent } from \"./events\";\n\ntype JournalRecord = { kind: \"event\"; event: HumanPlusEvent } | { kind: \"ack\"; consumerId: string; eventIds: string[]; disposition: HumanPlusDisposition };\n\n/** Single-process append-only JSONL store for local terminal applications. */\nexport class FileHumanPlusEventStore extends MemoryHumanPlusEventStore {\n  private ready: Promise<void>;\n  private writes = Promise.resolve();\n  constructor(private readonly path: string) { super(); this.ready = this.load(); }\n  private async load() {\n    let source = \"\"; try { source = await readFile(this.path, \"utf8\"); } catch (error: any) { if (error?.code !== \"ENOENT\") throw error; }\n    for (const line of source.split(\"\\n\")) {\n      if (!line.trim()) continue;\n      try { const record = JSON.parse(line) as JournalRecord; if (record.kind === \"event\") { this.events.push(record.event); this.nextSequence = Math.max(this.nextSequence, record.event.sequence + 1); } else await super.acknowledge(record.consumerId, record.eventIds, record.disposition); } catch { /* isolate truncated/corrupt records */ }\n    }\n  }\n  private enqueue(record: JournalRecord) {\n    this.writes = this.writes.then(async () => { await mkdir(dirname(this.path), { recursive: true }); const handle = await open(this.path, \"a\"); try { await handle.appendFile(`${JSON.stringify(record)}\\n`, \"utf8\"); await handle.sync(); } finally { await handle.close(); } });\n    return this.writes;\n  }\n  override async append(input: NewHumanPlusEvent) { await this.ready; const event = await super.append(input); await this.enqueue({ kind: \"event\", event }); return event; }\n  override async list(query: Parameters<MemoryHumanPlusEventStore[\"list\"]>[0]) { await this.ready; await this.writes; return super.list(query); }\n  override async acknowledge(consumerId: string, eventIds: string[], disposition: HumanPlusDisposition) { await this.ready; await super.acknowledge(consumerId, eventIds, disposition); await this.enqueue({ kind: \"ack\", consumerId, eventIds, disposition }); }\n  override async compact(options: Parameters<MemoryHumanPlusEventStore[\"compact\"]>[0] = {}) {\n    await this.ready; await this.writes; await super.compact(options);\n    const records: JournalRecord[] = this.events.map((event) => ({ kind: \"event\", event }));\n    for (const [consumerId, values] of this.acknowledgements) for (const [id, disposition] of values) records.push({ kind: \"ack\", consumerId, eventIds: [id], disposition });\n    const temporary = `${this.path}.${process.pid}.tmp`; await mkdir(dirname(this.path), { recursive: true }); await writeFile(temporary, records.map((x) => JSON.stringify(x)).join(\"\\n\") + \"\\n\", \"utf8\"); await rename(temporary, this.path);\n  }\n}\n"]}