{"version":3,"file":"pi.cjs","names":["fs","path","fs","path","createDoomIgnoreMatcher","createDoomTelemetry","filesStatusKey","SUBAGENT_CHILD_ENV","DOOM_UI_HUB_SERVICE","requireDoomUiHub","createFileEditDependencies","defineRoot","defineRoutedContribution","defineCliHook","defineCliHook","defineCliHook","definePiExtension","rootSession","composeRootHooks","commandFileEdits","hookSessionStart","hookToolExecutionEnd","hookToolExecutionStart"],"sources":["../../src/constants/package.ts","../../src/services/sessionStateSweep/index.ts","../../src/services/fileEditRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../src/extensions/workspaces/sessions/(backend)/command/file-edits.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli.ts","../../generated/pi.ts"],"sourcesContent":["export const FILES_COMMAND = 'file-edits';\nexport const PACKAGE_SOURCE = '@agimon-ai/doompi-file-edit';\nexport const DOOM_IGNORE_FILE = '.doomignore';\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\n\n/**\n * Remove the state sessions left behind when they never got to clean up.\n *\n * A session clears its own timeline and snapshots on shutdown, which covers the\n * ordinary case and nothing else: a killed process, a crash, or a machine that\n * lost power leaves both behind, and nothing ever looked at the directory\n * again. One week of that filled a real checkout with hundreds of megabytes.\n *\n * Age is the only signal used, because it is the only one that is true from\n * another process. A running session appends as it works, so its timeline is\n * recent; a dead one stops moving at the moment it died.\n */\n\n/**\n * How long state may sit untouched before a later session removes it.\n *\n * Generous on purpose. The cost of waiting is disk, and the cost of being wrong\n * is deleting a live session's history, so this is set far beyond any plausible\n * gap between two appends rather than close to it.\n */\nexport const STATE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\nconst TIMELINE_SUFFIX = '.jsonl';\nconst SNAPSHOTS_SUFFIX = '.blobs';\n\nexport interface SweepSessionStateOptions {\n  directory: string;\n  /** The caller's own timeline, which is never a candidate however it looks. */\n  keep?: string;\n  /** Remove the directory itself once nothing is left in it. */\n  removeDirectory?: boolean;\n  now?: number;\n  maxAgeMs?: number;\n}\n\nasync function remove(target: string): Promise<void> {\n  await fs.rm(target, { recursive: true, force: true });\n}\n\n/** The most recent time anything under this session's state moved. */\nasync function lastTouched(paths: readonly string[]): Promise<number | undefined> {\n  let newest: number | undefined;\n  for (const target of paths) {\n    try {\n      const stat = await fs.stat(target);\n      if (newest === undefined || stat.mtimeMs > newest) newest = stat.mtimeMs;\n    } catch {\n      // Not there is not a reason to keep the rest.\n    }\n  }\n  return newest;\n}\n\n/** How many sessions' worth of state was removed. */\nexport async function sweepSessionState(options: SweepSessionStateOptions): Promise<number> {\n  const { directory, keep, removeDirectory = false, now = Date.now(), maxAgeMs = STATE_MAX_AGE_MS } = options;\n  let entries: string[];\n  try {\n    entries = await fs.readdir(directory);\n  } catch {\n    return 0;\n  }\n  const floor = now - maxAgeMs;\n  const timelines = new Set(entries.filter((entry) => entry.endsWith(TIMELINE_SUFFIX)));\n  let removed = 0;\n\n  for (const entry of timelines) {\n    const timelinePath = path.join(directory, entry);\n    if (keep !== undefined && timelinePath === keep) continue;\n    const snapshotsPath = `${timelinePath.slice(0, -TIMELINE_SUFFIX.length)}${SNAPSHOTS_SUFFIX}`;\n    const lockPath = `${timelinePath}.lock`;\n    const touched = await lastTouched([timelinePath, snapshotsPath, lockPath]);\n    if (touched === undefined || touched >= floor) continue;\n    // Content first. A crash between the two leaves a timeline whose snapshots\n    // are gone, which reads as a session whose diffs expired. The other order\n    // leaves a blob tree nothing will ever name again, which is the shape of\n    // the leak this exists to clear.\n    await remove(snapshotsPath);\n    await remove(timelinePath);\n    await remove(lockPath);\n    removed += 1;\n  }\n\n  // A blob tree whose timeline is already gone is exactly what a half-finished\n  // cleanup leaves, and nothing else will ever look for it.\n  for (const entry of entries) {\n    if (!entry.endsWith(SNAPSHOTS_SUFFIX)) continue;\n    if (timelines.has(`${entry.slice(0, -SNAPSHOTS_SUFFIX.length)}${TIMELINE_SUFFIX}`)) continue;\n    const orphan = path.join(directory, entry);\n    const touched = await lastTouched([orphan]);\n    if (touched === undefined || touched >= floor) continue;\n    await remove(orphan);\n  }\n\n  if (removeDirectory) {\n    try {\n      await fs.rmdir(directory);\n    } catch {\n      // Still holding something, so it is not this sweep's to remove.\n    }\n  }\n  return removed;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { SUBAGENT_CHILD_ENV } from '@agimon-ai/doompi-core/childProcess';\nimport type { LeaderContribution } from '@agimon-ai/doompi-core/leader';\nimport type { PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/uiHub';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { FILES_COMMAND, PACKAGE_SOURCE, DOOM_IGNORE_FILE } from '../../constants/package';\nimport { createDoomIgnoreMatcher } from '../../services/doomIgnore';\nimport { sweepSessionState } from '../../services/sessionStateSweep';\nimport type { FileEditDependencies } from '../../types';\nimport { filesStatusKey } from '../../types/webFiles';\n/**\n * The project's ignore rules as a test over absolute paths, or nothing when the\n * file is absent, empty, or unreadable.\n *\n * Read once per session, like the exclude list it is passed beside. The web\n * reader re-reads the same file per request, so a mid-session edit reaches the\n * list before it reaches the recorder; that is a pre-existing difference and\n * not one this read introduces.\n */\nfunction readDoomIgnore(cwd: string): ((filePath: string) => boolean) | undefined {\n  let content: string;\n  try {\n    content = fs.readFileSync(path.join(cwd, DOOM_IGNORE_FILE), 'utf8');\n  } catch {\n    return undefined;\n  }\n  const matcher = createDoomIgnoreMatcher(content);\n  if (matcher === undefined) return undefined;\n  return (filePath: string): boolean => matcher(path.relative(cwd, filePath));\n}\n\nexport const FILE_EDIT_LEADER_CONTRIBUTION = {\n  source: PACKAGE_SOURCE,\n  bindings: [\n    {\n      id: 'editor.files',\n      path: [\n        { key: 'e', label: 'extension', detail: 'tools, skills and config', order: 50 },\n        { key: 'f', label: 'files', detail: 'session edits' },\n      ],\n      command: { name: FILES_COMMAND },\n    },\n  ],\n} as const satisfies LeaderContribution;\nexport function createFileEditRuntime(dependencies: FileEditDependencies): PiPluginContributions {\n  const { paths, timeline, snapshots, editTracker: tracker, workflow } = dependencies;\n  const telemetry: DoomTelemetry = createDoomTelemetry({\n    serviceName: 'doom-file-edit',\n    packageName: PACKAGE_SOURCE,\n    env: process.env,\n    enableLogs: true,\n    enableTraces: true,\n  });\n  const toolStartedAt = new Map<string, number>();\n  let active = true;\n  let sessionGeneration = 0;\n  let sessionContext: ExtensionContext | undefined;\n\n  /**\n   * Publishes the count the cockpit's activity group keys off. The group is\n   * hidden until this status exists, so it is written on every append rather\n   * than only when the count changes.\n   */\n  const publishStatus = async (): Promise<void> => {\n    if (!active || !sessionContext?.hasUI) return;\n    const entries = await timeline.list();\n    sessionContext.ui.setStatus(\n      filesStatusKey,\n      entries.length === 0 ? '' : `${entries.length} ${entries.length === 1 ? 'file' : 'files'}`,\n    );\n  };\n\n  const dispose = async () => {\n    active = false;\n    sessionGeneration += 1;\n    toolStartedAt.clear();\n    // A scan deferred by the last bash call would otherwise append after the\n    // clear below and leave a timeline no session owns.\n    await tracker.flush();\n    tracker.reset();\n    const closing = sessionContext;\n    sessionContext = undefined;\n    try {\n      if (!process.env[SUBAGENT_CHILD_ENV]) {\n        await timeline.clear();\n        // The snapshots exist only to diff this session, so they go with it\n        // rather than accumulating a copy of the tree on every run.\n        await snapshots.clear();\n      }\n      if (closing?.hasUI) closing.ui.setStatus(filesStatusKey, undefined);\n      await telemetry.recordEvent('doom_file_edit.timeline_finished', { outcome: 'closed' });\n    } finally {\n      await telemetry.shutdown();\n    }\n  };\n\n  /**\n   * Clears state no session will claim again. Never awaited and never allowed\n   * to throw: a sweep that cannot run is not a reason to fail a session.\n   */\n  const sweepAbandonedState = async (cwd: string, keep: string): Promise<void> => {\n    try {\n      await sweepSessionState({ directory: paths.stateDirectory(), keep });\n      const legacy = paths.legacyStateDirectory(cwd);\n      if (legacy === undefined || legacy === paths.stateDirectory()) return;\n      // Same age rule, so a build still running against the old location is\n      // not robbed of the session it is in the middle of.\n      await sweepSessionState({ directory: legacy, removeDirectory: true });\n    } catch {\n      // Nothing here is worth interrupting a session that is starting.\n    }\n  };\n  return {\n    onDispose: dispose,\n    services: [\n      (cordis: Context) => {\n        cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n          const contribution = requireDoomUiHub(uiContext).registerLeader(FILE_EDIT_LEADER_CONTRIBUTION);\n          return () => contribution.dispose();\n        });\n      },\n    ],\n    commands: [\n      [\n        FILES_COMMAND,\n        {\n          description: 'Review files edited in this session',\n          handler: async (_args, ctx) => {\n            if (!active) return;\n            if (!ctx.hasUI) {\n              ctx.ui.notify('/file-edits requires interactive mode', 'error');\n              return;\n            }\n            await workflow.open(ctx);\n          },\n        },\n      ],\n    ],\n    events: {\n      session_start: (_event, ctx) => {\n        if (!active) return;\n        sessionGeneration += 1;\n        toolStartedAt.clear();\n        sessionContext = ctx;\n        const sessionKey = paths.sessionKey(ctx.sessionManager.getSessionId());\n        const timelinePath = paths.timelinePath(ctx.cwd, sessionKey);\n        const snapshotsPath = paths.snapshotsPath(ctx.cwd, sessionKey);\n        timeline.initialize(timelinePath);\n        snapshots.initialize(snapshotsPath);\n        // Inside a git worktree these land under the repository's own git\n        // directory, which can sit inside the tree the tracker walks. Naming them\n        // here is what stops the package's bookkeeping reading as session edits.\n        // Whatever earlier sessions were killed before they could clean up, plus\n        // anything an older build left in the repository's own git directory.\n        void sweepAbandonedState(ctx.cwd, timelinePath);\n        const isIgnored = readDoomIgnore(ctx.cwd);\n        tracker.reset({\n          exclude: [timelinePath, `${timelinePath}.lock`, snapshotsPath],\n          ...(isIgnored === undefined ? {} : { isIgnored }),\n        });\n        // A resumed session already has a timeline, so the group must show its\n        // count from the first paint rather than waiting for the next edit.\n        void publishStatus();\n        void telemetry.recordEvent('doom_file_edit.timeline_started', { outcome: 'initialized' });\n      },\n      tool_execution_start: async (event, ctx) => {\n        if (!active) return;\n        const ownGeneration = sessionGeneration;\n        toolStartedAt.set(event.toolCallId, Date.now());\n        const hookStartedAt = Date.now();\n        await tracker.start(event.toolCallId, event.toolName, event.args, ctx.cwd);\n        const hookMs = Date.now() - hookStartedAt;\n        if (!active || ownGeneration !== sessionGeneration) {\n          toolStartedAt.delete(event.toolCallId);\n          return;\n        }\n        void telemetry.recordEvent('doom_file_edit.edit_started', {\n          'tool.name': event.toolName,\n          hook_ms: hookMs,\n        });\n      },\n      tool_execution_end: async (event, ctx) => {\n        if (!active) return;\n        const startedAt = toolStartedAt.get(event.toolCallId);\n        toolStartedAt.delete(event.toolCallId);\n        // Measured separately from the tool's own duration: this is the part of\n        // the wait that belongs to this package rather than to the tool.\n        const hookStartedAt = Date.now();\n        await tracker.end(event.toolCallId, event.isError, ctx.cwd);\n        if (!active) return;\n        await publishStatus();\n        const hookMs = Date.now() - hookStartedAt;\n        void telemetry.recordEvent('doom_file_edit.edit_finished', {\n          'tool.name': event.toolName,\n          'tool.result.error': event.isError,\n          ...(startedAt === undefined ? {} : { duration_ms: Date.now() - startedAt }),\n          hook_ms: hookMs,\n          outcome: event.isError ? 'failed' : 'completed',\n        });\n      },\n    },\n  };\n}\n","import { createFileEditRuntime } from '../../../../../services/fileEditRuntime';\nimport { createFileEditDependencies } from '../../../../../tui/fileEditDependencies';\nexport const createFileEditPiRoot = () => {\n  const runtime = createFileEditRuntime(createFileEditDependencies());\n  return { value: runtime, services: runtime.services, onDispose: runtime.onDispose };\n};\nexport type FileEditPiScope = Awaited<ReturnType<typeof createFileEditPiRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createFileEditPiRoot } from './_lib/piRoot';\n\nexport default defineRoot(createFileEditPiRoot);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineRoutedContribution(\n  (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => [context.root.commands![0]!] as const,\n  { cardinality: 'many' },\n);\n","import { defineCliHook, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineCliHook(\n  (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => context.root.events!.session_start!,\n);\n","import { defineCliHook, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineCliHook(\n  (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => context.root.events!.tool_execution_end!,\n);\n","import { defineCliHook, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineCliHook(\n  (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => context.root.events!.tool_execution_start!,\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\nimport commandFileEdits from '../src/extensions/workspaces/sessions/(backend)/command/file-edits.cli';\nimport hookSessionStart from '../src/extensions/workspaces/sessions/(backend)/hook/session-start.cli';\nimport hookToolExecutionEnd from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli';\nimport hookToolExecutionStart from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession> | OptionsOf<typeof commandFileEdits> | OptionsOf<typeof hookSessionStart> | OptionsOf<typeof hookToolExecutionEnd> | OptionsOf<typeof hookToolExecutionStart>, undefined>;\ntype Intersect<Union> =\n  (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n  typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n  const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n  return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-file-edit', async (context) => {\n  const scopeSession = await rootSession(context);\n  const contextSession = { ...context, root: scopeSession.value };\n  return {\n    ...composeRootHooks(scopeSession),\n    get commands(): PiPluginContributions['commands'] { return [...many(commandFileEdits, contextSession)]; },\n    events: {\n      session_start: at(hookSessionStart, contextSession) as NonNullable<PiPluginContributions['events']>['session_start'],\n      tool_execution_end: at(hookToolExecutionEnd, contextSession) as NonNullable<PiPluginContributions['events']>['tool_execution_end'],\n      tool_execution_start: at(hookToolExecutionStart, contextSession) as NonNullable<PiPluginContributions['events']>['tool_execution_start'],\n    },\n    services: [...(scopeSession.services ?? [])],\n  };\n});\n\nexport default extension;\n"],"mappings":"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"}