pi2dsh 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +122 -0
- package/README.zh.md +122 -0
- package/dist/cli.d.mts +2 -0
- package/dist/cli.mjs +128 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/compat/pi-ai.d.mts +2597 -0
- package/dist/compat/pi-ai.d.mts.map +1 -0
- package/dist/compat/pi-ai.mjs +4669 -0
- package/dist/compat/pi-ai.mjs.map +1 -0
- package/dist/compat/pi-coding-agent.d.mts +745 -0
- package/dist/compat/pi-coding-agent.d.mts.map +1 -0
- package/dist/compat/pi-coding-agent.mjs +4 -0
- package/dist/compat/pi-tui.d.mts +3 -0
- package/dist/compat/pi-tui.mjs +3622 -0
- package/dist/compat/pi-tui.mjs.map +1 -0
- package/dist/host.d.mts +35 -0
- package/dist/host.d.mts.map +1 -0
- package/dist/host.mjs +197 -0
- package/dist/host.mjs.map +1 -0
- package/dist/index.d.mts +69 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +5 -0
- package/dist/mcp-config-jL9w70It.mjs +1535 -0
- package/dist/mcp-config-jL9w70It.mjs.map +1 -0
- package/dist/pi-coding-agent-Dsg6_0ua.mjs +2060 -0
- package/dist/pi-coding-agent-Dsg6_0ua.mjs.map +1 -0
- package/dist/pi-config-shim-CZ1wFzqM.mjs +27 -0
- package/dist/pi-config-shim-CZ1wFzqM.mjs.map +1 -0
- package/dist/pi-tui-iHoF2tFc.d.mts +1043 -0
- package/dist/pi-tui-iHoF2tFc.d.mts.map +1 -0
- package/dist/pi-tui-utils-CcaVtm-3.mjs +895 -0
- package/dist/pi-tui-utils-CcaVtm-3.mjs.map +1 -0
- package/dist/pi-types-KazmR2O5.d.mts +62 -0
- package/dist/pi-types-KazmR2O5.d.mts.map +1 -0
- package/dist/pi-uuid-Db8ShZsK.mjs +47 -0
- package/dist/pi-uuid-Db8ShZsK.mjs.map +1 -0
- package/dist/rolldown-runtime-C2Q2p085.mjs +15 -0
- package/dist/runtime-D84Hv_3m.mjs +1499 -0
- package/dist/runtime-D84Hv_3m.mjs.map +1 -0
- package/dist/runtime.d.mts +31 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +3 -0
- package/dist/source-D7Ir-rPT.mjs +154 -0
- package/dist/source-D7Ir-rPT.mjs.map +1 -0
- package/dist/types-7IWJPPvS.d.mts +59 -0
- package/dist/types-7IWJPPvS.d.mts.map +1 -0
- package/package.json +135 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-coding-agent-Dsg6_0ua.mjs","names":["getDefaultAgentDir","join","existsSync","stat","readdir","resolve","agentDirOf"],"sources":["../src/compat/vendor/pi-messages.ts","../src/compat/vendor/pi-session-manager.ts","../src/compat/vendor/pi-truncate.ts","../src/compat/vendor/pi-file-mutation-queue.ts","../src/compat/pi-coding-agent.ts"],"sourcesContent":["// @ts-nocheck — vendored Pi source; checked upstream under Pi's own tsconfig.\n/**\n * Custom message types and transformers for the coding agent.\n *\n * Extends the base AgentMessage type with coding-agent specific message types,\n * and provides a transformer to convert them to LLM-compatible messages.\n */\n\nimport type { AgentMessage, ImageContent, Message, TextContent } from \"./pi-types.ts\";\n\nexport const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:\n\n<summary>\n`;\n\nexport const COMPACTION_SUMMARY_SUFFIX = `\n</summary>`;\n\nexport const BRANCH_SUMMARY_PREFIX = `The following is a summary of a branch that this conversation came back from:\n\n<summary>\n`;\n\nexport const BRANCH_SUMMARY_SUFFIX = `</summary>`;\n\n/**\n * Message type for bash executions via the ! command.\n */\nexport interface BashExecutionMessage {\n\trole: \"bashExecution\";\n\tcommand: string;\n\toutput: string;\n\texitCode: number | undefined;\n\tcancelled: boolean;\n\ttruncated: boolean;\n\tfullOutputPath?: string;\n\ttimestamp: number;\n\t/** If true, this message is excluded from LLM context (!! prefix) */\n\texcludeFromContext?: boolean;\n}\n\n/**\n * Message type for extension-injected messages via sendMessage().\n * These are custom messages that extensions can inject into the conversation.\n */\nexport interface CustomMessage<T = unknown> {\n\trole: \"custom\";\n\tcustomType: string;\n\tcontent: string | (TextContent | ImageContent)[];\n\tdisplay: boolean;\n\tdetails?: T;\n\ttimestamp: number;\n}\n\nexport interface BranchSummaryMessage {\n\trole: \"branchSummary\";\n\tsummary: string;\n\tfromId: string;\n\ttimestamp: number;\n}\n\nexport interface CompactionSummaryMessage {\n\trole: \"compactionSummary\";\n\tsummary: string;\n\ttokensBefore: number;\n\ttimestamp: number;\n}\n\n\n/**\n * Convert a BashExecutionMessage to user message text for LLM context.\n */\nexport function bashExecutionToText(msg: BashExecutionMessage): string {\n\tlet text = `Ran \\`${msg.command}\\`\\n`;\n\tif (msg.output) {\n\t\ttext += `\\`\\`\\`\\n${msg.output}\\n\\`\\`\\``;\n\t} else {\n\t\ttext += \"(no output)\";\n\t}\n\tif (msg.cancelled) {\n\t\ttext += \"\\n\\n(command cancelled)\";\n\t} else if (msg.exitCode !== null && msg.exitCode !== undefined && msg.exitCode !== 0) {\n\t\ttext += `\\n\\nCommand exited with code ${msg.exitCode}`;\n\t}\n\tif (msg.truncated && msg.fullOutputPath) {\n\t\ttext += `\\n\\n[Output truncated. Full output: ${msg.fullOutputPath}]`;\n\t}\n\treturn text;\n}\n\nexport function createBranchSummaryMessage(summary: string, fromId: string, timestamp: string): BranchSummaryMessage {\n\treturn {\n\t\trole: \"branchSummary\",\n\t\tsummary,\n\t\tfromId,\n\t\ttimestamp: new Date(timestamp).getTime(),\n\t};\n}\n\nexport function createCompactionSummaryMessage(\n\tsummary: string,\n\ttokensBefore: number,\n\ttimestamp: string,\n): CompactionSummaryMessage {\n\treturn {\n\t\trole: \"compactionSummary\",\n\t\tsummary: summary,\n\t\ttokensBefore,\n\t\ttimestamp: new Date(timestamp).getTime(),\n\t};\n}\n\n/** Convert CustomMessageEntry to AgentMessage format */\nexport function createCustomMessage(\n\tcustomType: string,\n\tcontent: string | (TextContent | ImageContent)[],\n\tdisplay: boolean,\n\tdetails: unknown | undefined,\n\ttimestamp: string,\n): CustomMessage {\n\treturn {\n\t\trole: \"custom\",\n\t\tcustomType,\n\t\tcontent,\n\t\tdisplay,\n\t\tdetails,\n\t\ttimestamp: new Date(timestamp).getTime(),\n\t};\n}\n\n/**\n * Transform AgentMessages (including custom types) to LLM-compatible Messages.\n *\n * This is used by:\n * - Agent's transormToLlm option (for prompt calls and queued messages)\n * - Compaction's generateSummary (for summarization)\n * - Custom extensions and tools\n */\nexport function convertToLlm(messages: AgentMessage[]): Message[] {\n\treturn messages\n\t\t.map((m): Message | undefined => {\n\t\t\tswitch (m.role) {\n\t\t\t\tcase \"bashExecution\":\n\t\t\t\t\t// Skip messages excluded from context (!! prefix)\n\t\t\t\t\tif (m.excludeFromContext) {\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: bashExecutionToText(m) }],\n\t\t\t\t\t\ttimestamp: m.timestamp,\n\t\t\t\t\t};\n\t\t\t\tcase \"custom\": {\n\t\t\t\t\tconst content = typeof m.content === \"string\" ? [{ type: \"text\" as const, text: m.content }] : m.content;\n\t\t\t\t\treturn {\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent,\n\t\t\t\t\t\ttimestamp: m.timestamp,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcase \"branchSummary\":\n\t\t\t\t\treturn {\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: BRANCH_SUMMARY_PREFIX + m.summary + BRANCH_SUMMARY_SUFFIX }],\n\t\t\t\t\t\ttimestamp: m.timestamp,\n\t\t\t\t\t};\n\t\t\t\tcase \"compactionSummary\":\n\t\t\t\t\treturn {\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{ type: \"text\" as const, text: COMPACTION_SUMMARY_PREFIX + m.summary + COMPACTION_SUMMARY_SUFFIX },\n\t\t\t\t\t\t],\n\t\t\t\t\t\ttimestamp: m.timestamp,\n\t\t\t\t\t};\n\t\t\t\tcase \"user\":\n\t\t\t\tcase \"assistant\":\n\t\t\t\tcase \"toolResult\":\n\t\t\t\t\treturn m;\n\t\t\t\tdefault:\n\t\t\t\t\t// biome-ignore lint/correctness/noSwitchDeclarations: fine\n\t\t\t\t\tconst _exhaustiveCheck: never = m;\n\t\t\t\t\treturn undefined;\n\t\t\t}\n\t\t})\n\t\t.filter((m) => m !== undefined);\n}\n","// @ts-nocheck — vendored Pi source; checked upstream under Pi's own tsconfig.\nimport type { AgentMessage } from \"./pi-types.ts\";\nimport type { ImageContent, Message, TextContent, Usage } from \"./pi-types.ts\";\nimport { uuidv7 } from \"./pi-uuid.ts\";\nimport { randomUUID } from \"crypto\";\nimport {\n\tappendFileSync,\n\tcloseSync,\n\tcreateReadStream,\n\texistsSync,\n\tmkdirSync,\n\topenSync,\n\treaddirSync,\n\treadSync,\n\tstatSync,\n\twriteFileSync,\n} from \"fs\";\nimport { readdir, stat } from \"fs/promises\";\nimport { join, resolve } from \"path\";\nimport { createInterface } from \"readline\";\nimport { StringDecoder } from \"string_decoder\";\nimport { getAgentDir as getDefaultAgentDir, getSessionsDir, normalizePath, resolvePath } from \"./pi-config-shim.ts\";\nimport {\n\ttype BashExecutionMessage,\n\ttype CustomMessage,\n\tcreateBranchSummaryMessage,\n\tcreateCompactionSummaryMessage,\n\tcreateCustomMessage,\n} from \"./pi-messages.ts\";\n\nexport const CURRENT_SESSION_VERSION = 3;\n\nexport interface SessionHeader {\n\ttype: \"session\";\n\tversion?: number; // v1 sessions don't have this\n\tid: string;\n\ttimestamp: string;\n\tcwd: string;\n\tparentSession?: string;\n}\n\nexport interface NewSessionOptions {\n\tid?: string;\n\tparentSession?: string;\n}\n\nexport interface SessionEntryBase {\n\ttype: string;\n\tid: string;\n\tparentId: string | null;\n\ttimestamp: string;\n}\n\nexport interface SessionMessageEntry extends SessionEntryBase {\n\ttype: \"message\";\n\tmessage: AgentMessage;\n}\n\nexport interface ThinkingLevelChangeEntry extends SessionEntryBase {\n\ttype: \"thinking_level_change\";\n\tthinkingLevel: string;\n}\n\nexport interface ModelChangeEntry extends SessionEntryBase {\n\ttype: \"model_change\";\n\tprovider: string;\n\tmodelId: string;\n}\n\nexport interface CompactionEntry<T = unknown> extends SessionEntryBase {\n\ttype: \"compaction\";\n\tsummary: string;\n\tfirstKeptEntryId: string;\n\ttokensBefore: number;\n\t/** Extension-specific data (e.g., ArtifactIndex, version markers for structured compaction) */\n\tdetails?: T;\n\t/** Usage from the LLM call(s) that generated this summary, if available */\n\tusage?: Usage;\n\t/** True if generated by an extension, undefined/false if pi-generated (backward compatible) */\n\tfromHook?: boolean;\n}\n\nexport interface BranchSummaryEntry<T = unknown> extends SessionEntryBase {\n\ttype: \"branch_summary\";\n\tfromId: string;\n\tsummary: string;\n\t/** Extension-specific data (not sent to LLM) */\n\tdetails?: T;\n\t/** Usage from the LLM call that generated this summary, if available */\n\tusage?: Usage;\n\t/** True if generated by an extension, false if pi-generated */\n\tfromHook?: boolean;\n}\n\n/**\n * Custom entry for extensions to store extension-specific data in the session.\n * Use customType to identify your extension's entries.\n *\n * Purpose: Persist extension state across session reloads. On reload, extensions can\n * scan entries for their customType and reconstruct internal state.\n *\n * Does NOT participate in LLM context (ignored by buildSessionContext).\n * For injecting content into context, see CustomMessageEntry.\n */\nexport interface CustomEntry<T = unknown> extends SessionEntryBase {\n\ttype: \"custom\";\n\tcustomType: string;\n\tdata?: T;\n}\n\n/** Label entry for user-defined bookmarks/markers on entries. */\nexport interface LabelEntry extends SessionEntryBase {\n\ttype: \"label\";\n\ttargetId: string;\n\tlabel: string | undefined;\n}\n\n/** Session metadata entry (e.g., user-defined display name). */\nexport interface SessionInfoEntry extends SessionEntryBase {\n\ttype: \"session_info\";\n\tname?: string;\n}\n\n/**\n * Custom message entry for extensions to inject messages into LLM context.\n * Use customType to identify your extension's entries.\n *\n * Unlike CustomEntry, this DOES participate in LLM context.\n * The content is converted to a user message in buildSessionContext().\n * Use details for extension-specific metadata (not sent to LLM).\n *\n * display controls TUI rendering:\n * - false: hidden entirely\n * - true: rendered with distinct styling (different from user messages)\n */\nexport interface CustomMessageEntry<T = unknown> extends SessionEntryBase {\n\ttype: \"custom_message\";\n\tcustomType: string;\n\tcontent: string | (TextContent | ImageContent)[];\n\tdetails?: T;\n\tdisplay: boolean;\n}\n\n/** Session entry - has id/parentId for tree structure (returned by \"read\" methods in SessionManager) */\nexport type SessionEntry =\n\t| SessionMessageEntry\n\t| ThinkingLevelChangeEntry\n\t| ModelChangeEntry\n\t| CompactionEntry\n\t| BranchSummaryEntry\n\t| CustomEntry\n\t| CustomMessageEntry\n\t| LabelEntry\n\t| SessionInfoEntry;\n\n/** Raw file entry (includes header) */\nexport type FileEntry = SessionHeader | SessionEntry;\n\n/** Tree node for getTree() - defensive copy of session structure */\nexport interface SessionTreeNode {\n\tentry: SessionEntry;\n\tchildren: SessionTreeNode[];\n\t/** Resolved label for this entry, if any */\n\tlabel?: string;\n\t/** Timestamp of the latest label change for this entry, if any */\n\tlabelTimestamp?: string;\n}\n\nexport interface SessionContext {\n\tmessages: AgentMessage[];\n\tthinkingLevel: string;\n\tmodel: { provider: string; modelId: string } | null;\n}\n\nexport interface SessionInfo {\n\tpath: string;\n\tid: string;\n\t/** Working directory where the session was started. Empty string for old sessions. */\n\tcwd: string;\n\t/** User-defined display name from session_info entries. */\n\tname?: string;\n\t/** Path to the parent session (if this session was forked). */\n\tparentSessionPath?: string;\n\tcreated: Date;\n\tmodified: Date;\n\tmessageCount: number;\n\tfirstMessage: string;\n\tallMessagesText: string;\n}\n\nexport type ReadonlySessionManager = Pick<\n\tSessionManager,\n\t| \"getCwd\"\n\t| \"getSessionDir\"\n\t| \"getSessionId\"\n\t| \"getSessionFile\"\n\t| \"getLeafId\"\n\t| \"getLeafEntry\"\n\t| \"getEntry\"\n\t| \"getLabel\"\n\t| \"getBranch\"\n\t| \"buildContextEntries\"\n\t| \"getHeader\"\n\t| \"getEntries\"\n\t| \"getTree\"\n\t| \"getSessionName\"\n>;\n\nfunction createSessionId(): string {\n\treturn uuidv7();\n}\n\nexport function assertValidSessionId(id: string): void {\n\tif (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {\n\t\tthrow new Error(\n\t\t\t\"Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character\",\n\t\t);\n\t}\n}\n\n/** Generate a unique short ID (8 hex chars, collision-checked) */\nfunction generateId(byId: { has(id: string): boolean }): string {\n\tfor (let i = 0; i < 100; i++) {\n\t\tconst id = randomUUID().slice(0, 8);\n\t\tif (!byId.has(id)) return id;\n\t}\n\t// Fallback to full UUID if somehow we have collisions\n\treturn randomUUID();\n}\n\n/** Migrate v1 → v2: add id/parentId tree structure. Mutates in place. */\nfunction migrateV1ToV2(entries: FileEntry[]): void {\n\tconst ids = new Set<string>();\n\tlet prevId: string | null = null;\n\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"session\") {\n\t\t\tentry.version = 2;\n\t\t\tcontinue;\n\t\t}\n\n\t\tentry.id = generateId(ids);\n\t\tentry.parentId = prevId;\n\t\tprevId = entry.id;\n\n\t\t// Convert firstKeptEntryIndex to firstKeptEntryId for compaction\n\t\tif (entry.type === \"compaction\") {\n\t\t\tconst comp = entry as CompactionEntry & { firstKeptEntryIndex?: number };\n\t\t\tif (typeof comp.firstKeptEntryIndex === \"number\") {\n\t\t\t\tconst targetEntry = entries[comp.firstKeptEntryIndex];\n\t\t\t\tif (targetEntry && targetEntry.type !== \"session\") {\n\t\t\t\t\tcomp.firstKeptEntryId = targetEntry.id;\n\t\t\t\t}\n\t\t\t\tdelete comp.firstKeptEntryIndex;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Migrate v2 → v3: rename hookMessage role to custom. Mutates in place. */\nfunction migrateV2ToV3(entries: FileEntry[]): void {\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"session\") {\n\t\t\tentry.version = 3;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Update message entries with hookMessage role\n\t\tif (entry.type === \"message\") {\n\t\t\tconst msgEntry = entry as SessionMessageEntry;\n\t\t\tif (msgEntry.message && (msgEntry.message as { role: string }).role === \"hookMessage\") {\n\t\t\t\t(msgEntry.message as { role: string }).role = \"custom\";\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Run all necessary migrations to bring entries to current version.\n * Mutates entries in place. Returns true if any migration was applied.\n */\nfunction migrateToCurrentVersion(entries: FileEntry[]): boolean {\n\tconst header = entries.find((e) => e.type === \"session\") as SessionHeader | undefined;\n\tconst version = header?.version ?? 1;\n\n\tif (version >= CURRENT_SESSION_VERSION) return false;\n\n\tif (version < 2) migrateV1ToV2(entries);\n\tif (version < 3) migrateV2ToV3(entries);\n\n\treturn true;\n}\n\n/** Exported for testing */\nexport function migrateSessionEntries(entries: FileEntry[]): void {\n\tmigrateToCurrentVersion(entries);\n}\n\n/** Exported for compaction.test.ts */\nexport function parseSessionEntries(content: string): FileEntry[] {\n\tconst entries: FileEntry[] = [];\n\tconst lines = content.trim().split(\"\\n\");\n\n\tfor (const line of lines) {\n\t\tif (!line.trim()) continue;\n\t\ttry {\n\t\t\tconst entry = JSON.parse(line) as FileEntry;\n\t\t\tentries.push(entry);\n\t\t} catch {\n\t\t\t// Skip malformed lines\n\t\t}\n\t}\n\n\treturn entries;\n}\n\nexport function getLatestCompactionEntry(entries: SessionEntry[]): CompactionEntry | null {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tif (entries[i].type === \"compaction\") {\n\t\t\treturn entries[i] as CompactionEntry;\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction buildEntryIndex(entries: SessionEntry[], byId?: Map<string, SessionEntry>): Map<string, SessionEntry> {\n\tif (byId) return byId;\n\tconst index = new Map<string, SessionEntry>();\n\tfor (const entry of entries) {\n\t\tindex.set(entry.id, entry);\n\t}\n\treturn index;\n}\n\nfunction buildSessionPath(\n\tentries: SessionEntry[],\n\tleafId?: string | null,\n\tbyId?: Map<string, SessionEntry>,\n): SessionEntry[] {\n\tconst index = buildEntryIndex(entries, byId);\n\tlet leaf: SessionEntry | undefined;\n\tif (leafId === null) {\n\t\treturn [];\n\t}\n\tif (leafId) {\n\t\tleaf = index.get(leafId);\n\t}\n\tleaf ??= entries[entries.length - 1];\n\tif (!leaf) {\n\t\treturn [];\n\t}\n\n\tconst path: SessionEntry[] = [];\n\tlet current: SessionEntry | undefined = leaf;\n\twhile (current) {\n\t\tpath.push(current);\n\t\tcurrent = current.parentId ? index.get(current.parentId) : undefined;\n\t}\n\tpath.reverse();\n\treturn path;\n}\n\nfunction getSessionContextSettings(path: SessionEntry[]): Pick<SessionContext, \"thinkingLevel\" | \"model\"> {\n\tlet thinkingLevel = \"off\";\n\tlet model: { provider: string; modelId: string } | null = null;\n\n\tfor (const entry of path) {\n\t\tif (entry.type === \"thinking_level_change\") {\n\t\t\tthinkingLevel = entry.thinkingLevel;\n\t\t} else if (entry.type === \"model_change\") {\n\t\t\tmodel = { provider: entry.provider, modelId: entry.modelId };\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tmodel = { provider: entry.message.provider, modelId: entry.message.model };\n\t\t}\n\t}\n\n\treturn { thinkingLevel, model };\n}\n\n/**\n * Project one selected session entry into LLM/runtime messages.\n * Plain custom entries are display/state entries and do not participate in context.\n */\nexport function sessionEntryToContextMessages(entry: SessionEntry): AgentMessage[] {\n\tif (entry.type === \"message\") {\n\t\tconst message = entry.message;\n\t\t// Session files are parsed without validation; old versions, forks, or\n\t\t// hand-edited files can contain messages with null/missing content.\n\t\tif (\n\t\t\t(message.role === \"user\" || message.role === \"assistant\" || message.role === \"toolResult\") &&\n\t\t\tmessage.content == null\n\t\t) {\n\t\t\treturn [{ ...message, content: [] }];\n\t\t}\n\t\treturn [message];\n\t}\n\tif (entry.type === \"custom_message\") {\n\t\treturn [\n\t\t\tcreateCustomMessage(entry.customType, entry.content ?? [], entry.display, entry.details, entry.timestamp),\n\t\t];\n\t}\n\tif (entry.type === \"branch_summary\" && entry.summary) {\n\t\treturn [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];\n\t}\n\tif (entry.type === \"compaction\") {\n\t\treturn [createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp)];\n\t}\n\treturn [];\n}\n\n/**\n * Build the active, compaction-aware session entry list.\n *\n * This follows the current leaf path. If the path contains compaction entries,\n * the latest compaction is represented by the compaction entry itself, followed\n * by the kept entries starting at firstKeptEntryId and all entries after the\n * compaction entry. Older summarized entries are omitted.\n */\nexport function buildContextEntries(\n\tentries: SessionEntry[],\n\tleafId?: string | null,\n\tbyId?: Map<string, SessionEntry>,\n): SessionEntry[] {\n\tconst path = buildSessionPath(entries, leafId, byId);\n\tlet compaction: CompactionEntry | null = null;\n\n\tfor (const entry of path) {\n\t\tif (entry.type === \"compaction\") {\n\t\t\tcompaction = entry;\n\t\t}\n\t}\n\n\tif (!compaction) {\n\t\treturn path;\n\t}\n\n\tconst compactionIdx = path.findIndex((entry) => entry.id === compaction.id);\n\tif (compactionIdx < 0) {\n\t\treturn path;\n\t}\n\n\tconst contextEntries: SessionEntry[] = [compaction];\n\tlet foundFirstKept = false;\n\tfor (let i = 0; i < compactionIdx; i++) {\n\t\tconst entry = path[i];\n\t\tif (entry.id === compaction.firstKeptEntryId) {\n\t\t\tfoundFirstKept = true;\n\t\t}\n\t\tif (foundFirstKept) {\n\t\t\tcontextEntries.push(entry);\n\t\t}\n\t}\n\tcontextEntries.push(...path.slice(compactionIdx + 1));\n\treturn contextEntries;\n}\n\n/**\n * Build the session context from entries using tree traversal.\n * If leafId is provided, walks from that entry to root.\n * Handles compaction and branch summaries along the path.\n */\nexport function buildSessionContext(\n\tentries: SessionEntry[],\n\tleafId?: string | null,\n\tbyId?: Map<string, SessionEntry>,\n): SessionContext {\n\tconst path = buildSessionPath(entries, leafId, byId);\n\tconst { thinkingLevel, model } = getSessionContextSettings(path);\n\tconst messages = buildContextEntries(entries, leafId, byId).flatMap(sessionEntryToContextMessages);\n\treturn { messages, thinkingLevel, model };\n}\n\n/**\n * Compute the default session directory for a cwd.\n * Encodes cwd into a safe directory name under ~/.pi/agent/sessions/.\n */\nfunction getDefaultSessionDirPath(cwd: string, agentDir: string = getDefaultAgentDir()): string {\n\tconst resolvedCwd = resolvePath(cwd);\n\tconst resolvedAgentDir = resolvePath(agentDir);\n\tconst safePath = `--${resolvedCwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\treturn join(resolvedAgentDir, \"sessions\", safePath);\n}\n\nexport function getDefaultSessionDir(cwd: string, agentDir: string = getDefaultAgentDir()): string {\n\tconst sessionDir = getDefaultSessionDirPath(cwd, agentDir);\n\tif (!existsSync(sessionDir)) {\n\t\tmkdirSync(sessionDir, { recursive: true });\n\t}\n\treturn sessionDir;\n}\n\nconst SESSION_READ_BUFFER_SIZE = 1024 * 1024;\nconst SESSION_HEADER_READ_BUFFER_SIZE = 4096;\n/** Bound synchronous header discovery while allowing large cwd and custom metadata fields. */\nconst MAX_SESSION_HEADER_SCAN_BYTES = 1024 * 1024;\n\nclass SessionHeaderScanLimitError extends Error {\n\tconstructor(filePath: string) {\n\t\tsuper(`Session header exceeds ${MAX_SESSION_HEADER_SCAN_BYTES}-byte scan limit: ${filePath}`);\n\t\tthis.name = \"SessionHeaderScanLimitError\";\n\t}\n}\n\nfunction parseSessionEntryLine(line: string): FileEntry | null {\n\tif (!line.trim()) return null;\n\ttry {\n\t\treturn JSON.parse(line) as FileEntry;\n\t} catch {\n\t\t// Skip malformed lines\n\t\treturn null;\n\t}\n}\n\n/** Exported for testing */\nexport function loadEntriesFromFile(filePath: string): FileEntry[] {\n\tconst resolvedFilePath = normalizePath(filePath);\n\tif (!existsSync(resolvedFilePath)) return [];\n\n\tconst entries: FileEntry[] = [];\n\tconst fd = openSync(resolvedFilePath, \"r\");\n\ttry {\n\t\tconst decoder = new StringDecoder(\"utf8\");\n\t\tconst buffer = Buffer.allocUnsafe(SESSION_READ_BUFFER_SIZE);\n\t\tlet pending = \"\";\n\n\t\twhile (true) {\n\t\t\tconst bytesRead = readSync(fd, buffer, 0, buffer.length, null);\n\t\t\tif (bytesRead === 0) break;\n\n\t\t\tpending += decoder.write(buffer.subarray(0, bytesRead));\n\t\t\tlet lineStart = 0;\n\t\t\tlet newlineIndex = pending.indexOf(\"\\n\", lineStart);\n\t\t\twhile (newlineIndex !== -1) {\n\t\t\t\tconst entry = parseSessionEntryLine(pending.slice(lineStart, newlineIndex));\n\t\t\t\tif (entry) entries.push(entry);\n\t\t\t\tlineStart = newlineIndex + 1;\n\t\t\t\tnewlineIndex = pending.indexOf(\"\\n\", lineStart);\n\t\t\t}\n\t\t\tpending = pending.slice(lineStart);\n\t\t}\n\n\t\tpending += decoder.end();\n\t\tconst finalEntry = parseSessionEntryLine(pending);\n\t\tif (finalEntry) entries.push(finalEntry);\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\n\t// Validate session header\n\tif (entries.length === 0) return entries;\n\tconst header = entries[0];\n\tif (header.type !== \"session\" || typeof (header as { id?: unknown }).id !== \"string\") {\n\t\treturn [];\n\t}\n\n\treturn entries;\n}\n\n/**\n * Inspect a physical line while searching for the first parsed session entry.\n * Blank and malformed lines are skipped to match loadEntriesFromFile().\n * Returns undefined to keep scanning, null for a parsed non-header entry, or the header.\n */\nfunction parseSessionHeaderCandidate(line: string): SessionHeader | null | undefined {\n\tif (!line.trim()) return undefined;\n\tconst entry = parseSessionEntryLine(line);\n\tif (!entry) return undefined;\n\tif (entry.type !== \"session\" || typeof (entry as { id?: unknown }).id !== \"string\") return null;\n\treturn entry;\n}\n\nfunction readSessionHeader(filePath: string): SessionHeader | null {\n\tconst fd = openSync(filePath, \"r\");\n\ttry {\n\t\tconst decoder = new StringDecoder(\"utf8\");\n\t\tconst buffer = Buffer.allocUnsafe(SESSION_HEADER_READ_BUFFER_SIZE);\n\t\tconst lineChunks: string[] = [];\n\t\tlet scannedBytes = 0;\n\n\t\twhile (scannedBytes < MAX_SESSION_HEADER_SCAN_BYTES) {\n\t\t\tconst readLength = Math.min(buffer.length, MAX_SESSION_HEADER_SCAN_BYTES - scannedBytes);\n\t\t\tconst bytesRead = readSync(fd, buffer, 0, readLength, null);\n\t\t\tif (bytesRead === 0) {\n\t\t\t\tlineChunks.push(decoder.end());\n\t\t\t\treturn parseSessionHeaderCandidate(lineChunks.join(\"\")) ?? null;\n\t\t\t}\n\t\t\tscannedBytes += bytesRead;\n\n\t\t\tconst chunk = decoder.write(buffer.subarray(0, bytesRead));\n\t\t\tlet lineStart = 0;\n\t\t\tlet newlineIndex = chunk.indexOf(\"\\n\", lineStart);\n\t\t\twhile (newlineIndex !== -1) {\n\t\t\t\tlineChunks.push(chunk.slice(lineStart, newlineIndex));\n\t\t\t\tconst header = parseSessionHeaderCandidate(lineChunks.join(\"\"));\n\t\t\t\tif (header !== undefined) return header;\n\t\t\t\tlineChunks.length = 0;\n\t\t\t\tlineStart = newlineIndex + 1;\n\t\t\t\tnewlineIndex = chunk.indexOf(\"\\n\", lineStart);\n\t\t\t}\n\t\t\tlineChunks.push(chunk.slice(lineStart));\n\t\t}\n\n\t\t// Probe for EOF so a final header without a newline is allowed when it ends\n\t\t// exactly at the scan limit. Any additional byte exceeds the bounded scan.\n\t\tconst probe = Buffer.allocUnsafe(1);\n\t\tif (readSync(fd, probe, 0, probe.length, null) === 0) {\n\t\t\tlineChunks.push(decoder.end());\n\t\t\treturn parseSessionHeaderCandidate(lineChunks.join(\"\")) ?? null;\n\t\t}\n\t\tthrow new SessionHeaderScanLimitError(filePath);\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n}\n\nfunction readSessionHeaderForDiscovery(filePath: string): SessionHeader | null {\n\ttry {\n\t\treturn readSessionHeader(filePath);\n\t} catch {\n\t\t// Discovery is best-effort: unreadable or oversized files are not sessions,\n\t\t// and one corrupt file must not prevent other sessions from being found.\n\t\treturn null;\n\t}\n}\n\nfunction getSessionHeaderCwd(header: SessionHeader): string | undefined {\n\tconst cwd = (header as { cwd?: unknown }).cwd;\n\treturn typeof cwd === \"string\" ? cwd : undefined;\n}\n\nfunction sessionCwdMatches(cwd: string | undefined, resolvedCwd: string): boolean {\n\treturn cwd !== undefined && cwd !== \"\" && resolvePath(cwd) === resolvedCwd;\n}\n\n/** Exported for testing */\nexport function findMostRecentSession(sessionDir: string, cwd?: string): string | null {\n\tconst resolvedSessionDir = normalizePath(sessionDir);\n\tconst resolvedCwd = cwd ? resolvePath(cwd) : undefined;\n\ttry {\n\t\tconst files = readdirSync(resolvedSessionDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(resolvedSessionDir, f))\n\t\t\t.map((path) => ({ path, header: readSessionHeaderForDiscovery(path) }))\n\t\t\t.filter(\n\t\t\t\t(file): file is { path: string; header: SessionHeader } =>\n\t\t\t\t\tfile.header !== null &&\n\t\t\t\t\t(!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(file.header), resolvedCwd)),\n\t\t\t)\n\t\t\t.map(({ path }) => ({ path, mtime: statSync(path).mtime }))\n\t\t\t.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());\n\n\t\treturn files[0]?.path || null;\n\t} catch {\n\t\t// Directory access and stat races make recent-session discovery unavailable.\n\t\treturn null;\n\t}\n}\n\nfunction isMessageWithContent(message: AgentMessage): message is Message {\n\treturn typeof (message as Message).role === \"string\" && \"content\" in message;\n}\n\nfunction extractTextContent(message: Message): string {\n\tconst content = message.content;\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\treturn content\n\t\t.filter((block): block is TextContent => block.type === \"text\")\n\t\t.map((block) => block.text)\n\t\t.join(\" \");\n}\n\nfunction getMessageActivityTime(entry: SessionMessageEntry): number | undefined {\n\tconst message = entry.message;\n\tif (!isMessageWithContent(message)) return undefined;\n\tif (message.role !== \"user\" && message.role !== \"assistant\") return undefined;\n\n\tconst msgTimestamp = (message as { timestamp?: number }).timestamp;\n\tif (typeof msgTimestamp === \"number\") {\n\t\treturn msgTimestamp;\n\t}\n\n\tconst t = new Date(entry.timestamp).getTime();\n\treturn Number.isNaN(t) ? undefined : t;\n}\n\nasync function buildSessionInfo(filePath: string): Promise<SessionInfo | null> {\n\ttry {\n\t\tconst stats = await stat(filePath);\n\t\tlet header: SessionHeader | null = null;\n\t\tlet messageCount = 0;\n\t\tlet firstMessage = \"\";\n\t\tconst allMessages: string[] = [];\n\t\tlet name: string | undefined;\n\t\tlet lastActivityTime: number | undefined;\n\n\t\tconst rl = createInterface({\n\t\t\tinput: createReadStream(filePath, { encoding: \"utf8\" }),\n\t\t\tcrlfDelay: Infinity,\n\t\t});\n\n\t\tfor await (const line of rl) {\n\t\t\tconst entry = parseSessionEntryLine(line);\n\t\t\tif (!entry) continue;\n\n\t\t\tif (!header) {\n\t\t\t\tif (entry.type !== \"session\") return null;\n\t\t\t\theader = entry;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Extract session name (use latest, including explicit clears)\n\t\t\tif (entry.type === \"session_info\") {\n\t\t\t\tname = entry.name?.trim() || undefined;\n\t\t\t}\n\n\t\t\tif (entry.type !== \"message\") continue;\n\t\t\tmessageCount++;\n\n\t\t\tconst activityTime = getMessageActivityTime(entry);\n\t\t\tif (typeof activityTime === \"number\") {\n\t\t\t\tlastActivityTime = Math.max(lastActivityTime ?? 0, activityTime);\n\t\t\t}\n\n\t\t\tconst message = entry.message;\n\t\t\tif (!isMessageWithContent(message)) continue;\n\t\t\tif (message.role !== \"user\" && message.role !== \"assistant\") continue;\n\n\t\t\tconst textContent = extractTextContent(message);\n\t\t\tif (!textContent) continue;\n\n\t\t\tallMessages.push(textContent);\n\t\t\tif (!firstMessage && message.role === \"user\") {\n\t\t\t\tfirstMessage = textContent;\n\t\t\t}\n\t\t}\n\n\t\tif (!header) return null;\n\n\t\tconst cwd = typeof header.cwd === \"string\" ? header.cwd : \"\";\n\t\tconst parentSessionPath = header.parentSession;\n\t\tconst headerTime = typeof header.timestamp === \"string\" ? new Date(header.timestamp).getTime() : NaN;\n\t\tconst modified =\n\t\t\ttypeof lastActivityTime === \"number\" && lastActivityTime > 0\n\t\t\t\t? new Date(lastActivityTime)\n\t\t\t\t: !Number.isNaN(headerTime)\n\t\t\t\t\t? new Date(headerTime)\n\t\t\t\t\t: stats.mtime;\n\n\t\treturn {\n\t\t\tpath: filePath,\n\t\t\tid: header.id,\n\t\t\tcwd,\n\t\t\tname,\n\t\t\tparentSessionPath,\n\t\t\tcreated: new Date(header.timestamp),\n\t\t\tmodified,\n\t\t\tmessageCount,\n\t\t\tfirstMessage: firstMessage || \"(no messages)\",\n\t\t\tallMessagesText: allMessages.join(\" \"),\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport type SessionListProgress = (loaded: number, total: number) => void;\n\nconst MAX_CONCURRENT_SESSION_INFO_LOADS = 10;\n\nasync function buildSessionInfosWithConcurrency(\n\tfiles: string[],\n\tonLoaded: () => void,\n): Promise<(SessionInfo | null)[]> {\n\tconst results: (SessionInfo | null)[] = new Array(files.length).fill(null);\n\tconst inFlight = new Set<Promise<void>>();\n\tlet nextIndex = 0;\n\n\tconst startNext = (): void => {\n\t\tconst index = nextIndex++;\n\t\tconst file = files[index];\n\t\tif (!file) return;\n\n\t\tlet task: Promise<void>;\n\t\ttask = buildSessionInfo(file)\n\t\t\t.then((info) => {\n\t\t\t\tresults[index] = info;\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tresults[index] = null;\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tinFlight.delete(task);\n\t\t\t\tonLoaded();\n\t\t\t});\n\t\tinFlight.add(task);\n\t};\n\n\twhile (nextIndex < files.length || inFlight.size > 0) {\n\t\twhile (nextIndex < files.length && inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {\n\t\t\tstartNext();\n\t\t}\n\t\tif (inFlight.size > 0) {\n\t\t\tawait Promise.race(inFlight);\n\t\t}\n\t}\n\n\treturn results;\n}\n\nasync function listSessionsFromDir(\n\tdir: string,\n\tonProgress?: SessionListProgress,\n\tprogressOffset = 0,\n\tprogressTotal?: number,\n): Promise<SessionInfo[]> {\n\tconst sessions: SessionInfo[] = [];\n\tif (!existsSync(dir)) {\n\t\treturn sessions;\n\t}\n\n\ttry {\n\t\tconst dirEntries = await readdir(dir);\n\t\tconst files = dirEntries.filter((f) => f.endsWith(\".jsonl\")).map((f) => join(dir, f));\n\t\tconst total = progressTotal ?? files.length;\n\n\t\tlet loaded = 0;\n\t\tconst results = await buildSessionInfosWithConcurrency(files, () => {\n\t\t\tloaded++;\n\t\t\tonProgress?.(progressOffset + loaded, total);\n\t\t});\n\t\tfor (const info of results) {\n\t\t\tif (info) {\n\t\t\t\tsessions.push(info);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Return empty list on error\n\t}\n\n\treturn sessions;\n}\n\n/**\n * Manages conversation sessions as append-only trees stored in JSONL files.\n *\n * Each session entry has an id and parentId forming a tree structure. The \"leaf\"\n * pointer tracks the current position. Appending creates a child of the current leaf.\n * Branching moves the leaf to an earlier entry, allowing new branches without\n * modifying history.\n *\n * Use buildSessionContext() to get the resolved message list for the LLM, which\n * handles compaction summaries and follows the path from root to current leaf.\n */\nexport class SessionManager {\n\tprivate sessionId: string = \"\";\n\tprivate sessionFile: string | undefined;\n\tprivate sessionDir: string;\n\tprivate cwd: string;\n\tprivate persist: boolean;\n\tprivate flushed: boolean = false;\n\tprivate fileEntries: FileEntry[] = [];\n\tprivate byId: Map<string, SessionEntry> = new Map();\n\tprivate labelsById: Map<string, string> = new Map();\n\tprivate labelTimestampsById: Map<string, string> = new Map();\n\tprivate leafId: string | null = null;\n\n\tprivate constructor(\n\t\tcwd: string,\n\t\tsessionDir: string,\n\t\tsessionFile: string | undefined,\n\t\tpersist: boolean,\n\t\tnewSessionOptions?: NewSessionOptions,\n\t\tpreloadedFileEntries?: FileEntry[],\n\t) {\n\t\tthis.cwd = resolvePath(cwd);\n\t\tthis.sessionDir = normalizePath(sessionDir);\n\t\tthis.persist = persist;\n\t\tif (persist && this.sessionDir && !existsSync(this.sessionDir)) {\n\t\t\tmkdirSync(this.sessionDir, { recursive: true });\n\t\t}\n\n\t\tif (sessionFile) {\n\t\t\tthis._setSessionFile(sessionFile, preloadedFileEntries);\n\t\t} else {\n\t\t\tthis.newSession(newSessionOptions);\n\t\t}\n\t}\n\n\t/** Switch to a different session file (used for resume and branching) */\n\tsetSessionFile(sessionFile: string): void {\n\t\tthis._setSessionFile(sessionFile);\n\t}\n\n\tprivate _setSessionFile(sessionFile: string, preloadedFileEntries?: FileEntry[]): void {\n\t\tthis.sessionFile = resolvePath(sessionFile);\n\t\tif (existsSync(this.sessionFile)) {\n\t\t\tthis.fileEntries = preloadedFileEntries ?? loadEntriesFromFile(this.sessionFile);\n\n\t\t\t// If file was empty, initialize it with a valid session header. If it was\n\t\t\t// non-empty but did not parse as a pi session, fail without modifying it.\n\t\t\tif (this.fileEntries.length === 0) {\n\t\t\t\tconst explicitPath = this.sessionFile;\n\t\t\t\tif (statSync(explicitPath).size > 0) {\n\t\t\t\t\tthrow new Error(`Session file is not a valid pi session: ${explicitPath}`);\n\t\t\t\t}\n\t\t\t\tthis.newSession();\n\t\t\t\tthis.sessionFile = explicitPath;\n\t\t\t\tthis._rewriteFile();\n\t\t\t\tthis.flushed = true;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst header = this.fileEntries.find((e) => e.type === \"session\") as SessionHeader | undefined;\n\t\t\tthis.sessionId = header?.id ?? createSessionId();\n\n\t\t\tif (migrateToCurrentVersion(this.fileEntries)) {\n\t\t\t\tthis._rewriteFile();\n\t\t\t}\n\n\t\t\tthis._buildIndex();\n\t\t\tthis.flushed = true;\n\t\t} else {\n\t\t\tconst explicitPath = this.sessionFile;\n\t\t\tthis.newSession();\n\t\t\tthis.sessionFile = explicitPath; // preserve explicit path from --session flag\n\t\t}\n\t}\n\n\tnewSession(options?: NewSessionOptions): string | undefined {\n\t\tif (options?.id !== undefined) {\n\t\t\tassertValidSessionId(options.id);\n\t\t}\n\t\tthis.sessionId = options?.id ?? createSessionId();\n\t\tconst timestamp = new Date().toISOString();\n\t\tconst header: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: CURRENT_SESSION_VERSION,\n\t\t\tid: this.sessionId,\n\t\t\ttimestamp,\n\t\t\tcwd: this.cwd,\n\t\t\tparentSession: options?.parentSession,\n\t\t};\n\t\tthis.fileEntries = [header];\n\t\tthis.byId.clear();\n\t\tthis.labelsById.clear();\n\t\tthis.labelTimestampsById.clear();\n\t\tthis.leafId = null;\n\t\tthis.flushed = false;\n\n\t\tif (this.persist) {\n\t\t\tconst fileTimestamp = timestamp.replace(/[:.]/g, \"-\");\n\t\t\tthis.sessionFile = join(this.getSessionDir(), `${fileTimestamp}_${this.sessionId}.jsonl`);\n\t\t}\n\t\treturn this.sessionFile;\n\t}\n\n\tprivate _buildIndex(): void {\n\t\tthis.byId.clear();\n\t\tthis.labelsById.clear();\n\t\tthis.labelTimestampsById.clear();\n\t\tthis.leafId = null;\n\t\tfor (const entry of this.fileEntries) {\n\t\t\tif (entry.type === \"session\") continue;\n\t\t\tthis.byId.set(entry.id, entry);\n\t\t\tthis.leafId = entry.id;\n\t\t\tif (entry.type === \"label\") {\n\t\t\t\tif (entry.label) {\n\t\t\t\t\tthis.labelsById.set(entry.targetId, entry.label);\n\t\t\t\t\tthis.labelTimestampsById.set(entry.targetId, entry.timestamp);\n\t\t\t\t} else {\n\t\t\t\t\tthis.labelsById.delete(entry.targetId);\n\t\t\t\t\tthis.labelTimestampsById.delete(entry.targetId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _rewriteFile(): void {\n\t\tif (!this.persist || !this.sessionFile) return;\n\t\tconst fd = openSync(this.sessionFile, \"w\");\n\t\ttry {\n\t\t\tfor (const entry of this.fileEntries) {\n\t\t\t\twriteFileSync(fd, `${JSON.stringify(entry)}\\n`);\n\t\t\t}\n\t\t} finally {\n\t\t\tcloseSync(fd);\n\t\t}\n\t}\n\n\tisPersisted(): boolean {\n\t\treturn this.persist;\n\t}\n\n\tgetCwd(): string {\n\t\treturn this.cwd;\n\t}\n\n\tgetSessionDir(): string {\n\t\treturn this.sessionDir;\n\t}\n\n\tusesDefaultSessionDir(): boolean {\n\t\treturn this.sessionDir === getDefaultSessionDirPath(this.cwd);\n\t}\n\n\tgetSessionId(): string {\n\t\treturn this.sessionId;\n\t}\n\n\tgetSessionFile(): string | undefined {\n\t\treturn this.sessionFile;\n\t}\n\n\t_persist(entry: SessionEntry): void {\n\t\tif (!this.persist || !this.sessionFile) return;\n\n\t\tconst hasAssistant = this.fileEntries.some((e) => e.type === \"message\" && e.message.role === \"assistant\");\n\t\tif (!hasAssistant) {\n\t\t\tif (this.flushed) {\n\t\t\t\tappendFileSync(this.sessionFile, `${JSON.stringify(entry)}\\n`);\n\t\t\t} else {\n\t\t\t\t// Mark as not flushed so when assistant arrives, all entries get written\n\t\t\t\tthis.flushed = false;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.flushed) {\n\t\t\tconst fd = openSync(this.sessionFile, \"wx\");\n\t\t\ttry {\n\t\t\t\tfor (const e of this.fileEntries) {\n\t\t\t\t\twriteFileSync(fd, `${JSON.stringify(e)}\\n`);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t\tthis.flushed = true;\n\t\t} else {\n\t\t\tappendFileSync(this.sessionFile, `${JSON.stringify(entry)}\\n`);\n\t\t}\n\t}\n\n\tprivate _appendEntry(entry: SessionEntry): void {\n\t\tthis.fileEntries.push(entry);\n\t\tthis.byId.set(entry.id, entry);\n\t\tthis.leafId = entry.id;\n\t\tthis._persist(entry);\n\t}\n\n\t/** Append a message as child of current leaf, then advance leaf. Returns entry id.\n\t * Does not allow writing CompactionSummaryMessage and BranchSummaryMessage directly.\n\t * Reason: we want these to be top-level entries in the session, not message session entries,\n\t * so it is easier to find them.\n\t * These need to be appended via appendCompaction() and appendBranchSummary() methods.\n\t */\n\tappendMessage(message: Message | CustomMessage | BashExecutionMessage): string {\n\t\tconst entry: SessionMessageEntry = {\n\t\t\ttype: \"message\",\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tmessage,\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t/** Append a thinking level change as child of current leaf, then advance leaf. Returns entry id. */\n\tappendThinkingLevelChange(thinkingLevel: string): string {\n\t\tconst entry: ThinkingLevelChangeEntry = {\n\t\t\ttype: \"thinking_level_change\",\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tthinkingLevel,\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t/** Append a model change as child of current leaf, then advance leaf. Returns entry id. */\n\tappendModelChange(provider: string, modelId: string): string {\n\t\tconst entry: ModelChangeEntry = {\n\t\t\ttype: \"model_change\",\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tprovider,\n\t\t\tmodelId,\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t/** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */\n\tappendCompaction<T = unknown>(\n\t\tsummary: string,\n\t\tfirstKeptEntryId: string,\n\t\ttokensBefore: number,\n\t\tdetails?: T,\n\t\tfromHook?: boolean,\n\t\tusage?: Usage,\n\t): string {\n\t\tconst entry: CompactionEntry<T> = {\n\t\t\ttype: \"compaction\",\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tsummary,\n\t\t\tfirstKeptEntryId,\n\t\t\ttokensBefore,\n\t\t\tdetails,\n\t\t\tusage,\n\t\t\tfromHook,\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t/** Append a custom entry (for extensions) as child of current leaf, then advance leaf. Returns entry id. */\n\tappendCustomEntry(customType: string, data?: unknown): string {\n\t\tconst entry: CustomEntry = {\n\t\t\ttype: \"custom\",\n\t\t\tcustomType,\n\t\t\tdata,\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t/** Append a session info entry (e.g., display name). Returns entry id. */\n\tappendSessionInfo(name: string): string {\n\t\tconst sanitizedName = name.replace(/[\\r\\n]+/g, \" \").trim();\n\t\tconst entry: SessionInfoEntry = {\n\t\t\ttype: \"session_info\",\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tname: sanitizedName,\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t/** Get the current session name from the latest session_info entry, if any. */\n\tgetSessionName(): string | undefined {\n\t\t// Walk entries in reverse to find the latest session_info entry.\n\t\t// Empty names explicitly clear the session title.\n\t\tconst entries = this.getEntries();\n\t\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\t\tconst entry = entries[i];\n\t\t\tif (entry.type === \"session_info\") {\n\t\t\t\treturn entry.name?.trim() || undefined;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Append a custom message entry (for extensions) that participates in LLM context.\n\t * @param customType Extension identifier for filtering on reload\n\t * @param content Message content (string or TextContent/ImageContent array)\n\t * @param display Whether to show in TUI (true = styled display, false = hidden)\n\t * @param details Optional extension-specific metadata (not sent to LLM)\n\t * @returns Entry id\n\t */\n\tappendCustomMessageEntry<T = unknown>(\n\t\tcustomType: string,\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\tdisplay: boolean,\n\t\tdetails?: T,\n\t): string {\n\t\tconst entry: CustomMessageEntry<T> = {\n\t\t\ttype: \"custom_message\",\n\t\t\tcustomType,\n\t\t\tcontent,\n\t\t\tdisplay,\n\t\t\tdetails,\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t// =========================================================================\n\t// Tree Traversal\n\t// =========================================================================\n\n\tgetLeafId(): string | null {\n\t\treturn this.leafId;\n\t}\n\n\tgetLeafEntry(): SessionEntry | undefined {\n\t\treturn this.leafId ? this.byId.get(this.leafId) : undefined;\n\t}\n\n\tgetEntry(id: string): SessionEntry | undefined {\n\t\treturn this.byId.get(id);\n\t}\n\n\t/**\n\t * Get all direct children of an entry.\n\t */\n\tgetChildren(parentId: string): SessionEntry[] {\n\t\tconst children: SessionEntry[] = [];\n\t\tfor (const entry of this.byId.values()) {\n\t\t\tif (entry.parentId === parentId) {\n\t\t\t\tchildren.push(entry);\n\t\t\t}\n\t\t}\n\t\treturn children;\n\t}\n\n\t/**\n\t * Get the label for an entry, if any.\n\t */\n\tgetLabel(id: string): string | undefined {\n\t\treturn this.labelsById.get(id);\n\t}\n\n\t/**\n\t * Set or clear a label on an entry.\n\t * Labels are user-defined markers for bookmarking/navigation.\n\t * Pass undefined or empty string to clear the label.\n\t */\n\tappendLabelChange(targetId: string, label: string | undefined): string {\n\t\tif (!this.byId.has(targetId)) {\n\t\t\tthrow new Error(`Entry ${targetId} not found`);\n\t\t}\n\t\tconst entry: LabelEntry = {\n\t\t\ttype: \"label\",\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttargetId,\n\t\t\tlabel,\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\tif (label) {\n\t\t\tthis.labelsById.set(targetId, label);\n\t\t\tthis.labelTimestampsById.set(targetId, entry.timestamp);\n\t\t} else {\n\t\t\tthis.labelsById.delete(targetId);\n\t\t\tthis.labelTimestampsById.delete(targetId);\n\t\t}\n\t\treturn entry.id;\n\t}\n\n\t/**\n\t * Walk from entry to root, returning all entries in path order.\n\t * Includes all entry types (messages, compaction, model changes, etc.).\n\t * Use buildSessionContext() to get the resolved messages for the LLM.\n\t */\n\tgetBranch(fromId?: string): SessionEntry[] {\n\t\tconst path: SessionEntry[] = [];\n\t\tconst startId = fromId ?? this.leafId;\n\t\tlet current = startId ? this.byId.get(startId) : undefined;\n\t\twhile (current) {\n\t\t\tpath.push(current);\n\t\t\tcurrent = current.parentId ? this.byId.get(current.parentId) : undefined;\n\t\t}\n\t\tpath.reverse();\n\t\treturn path;\n\t}\n\n\t/**\n\t * Build the active, compaction-aware entry list for context/rendering.\n\t * Uses tree traversal from current leaf.\n\t */\n\tbuildContextEntries(): SessionEntry[] {\n\t\treturn buildContextEntries(this.getEntries(), this.leafId, this.byId);\n\t}\n\n\t/**\n\t * Build the session context (what gets sent to the LLM).\n\t * Uses tree traversal from current leaf.\n\t */\n\tbuildSessionContext(): SessionContext {\n\t\treturn buildSessionContext(this.getEntries(), this.leafId, this.byId);\n\t}\n\n\t/**\n\t * Get session header.\n\t */\n\tgetHeader(): SessionHeader | null {\n\t\tconst h = this.fileEntries.find((e) => e.type === \"session\");\n\t\treturn h ? (h as SessionHeader) : null;\n\t}\n\n\t/**\n\t * Get all session entries (excludes header). Returns a shallow copy.\n\t * The session is append-only: use appendXXX() to add entries, branch() to\n\t * change the leaf pointer. Entries cannot be modified or deleted.\n\t */\n\tgetEntries(): SessionEntry[] {\n\t\treturn this.fileEntries.filter((e): e is SessionEntry => e.type !== \"session\");\n\t}\n\n\t/**\n\t * Get the session as a tree structure. Returns a shallow defensive copy of all entries.\n\t * A well-formed session has exactly one root (first entry with parentId === null).\n\t * Orphaned entries (broken parent chain) are also returned as roots.\n\t */\n\tgetTree(): SessionTreeNode[] {\n\t\tconst entries = this.getEntries();\n\t\tconst nodeMap = new Map<string, SessionTreeNode>();\n\t\tconst roots: SessionTreeNode[] = [];\n\n\t\t// Create nodes with resolved labels\n\t\tfor (const entry of entries) {\n\t\t\tconst label = this.labelsById.get(entry.id);\n\t\t\tconst labelTimestamp = this.labelTimestampsById.get(entry.id);\n\t\t\tnodeMap.set(entry.id, { entry, children: [], label, labelTimestamp });\n\t\t}\n\n\t\t// Build tree\n\t\tfor (const entry of entries) {\n\t\t\tconst node = nodeMap.get(entry.id)!;\n\t\t\tif (entry.parentId === null || entry.parentId === entry.id) {\n\t\t\t\troots.push(node);\n\t\t\t} else {\n\t\t\t\tconst parent = nodeMap.get(entry.parentId);\n\t\t\t\tif (parent) {\n\t\t\t\t\tparent.children.push(node);\n\t\t\t\t} else {\n\t\t\t\t\t// Orphan - treat as root\n\t\t\t\t\troots.push(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Sort children by timestamp (oldest first, newest at bottom)\n\t\t// Use iterative approach to avoid stack overflow on deep trees\n\t\tconst stack: SessionTreeNode[] = [...roots];\n\t\twhile (stack.length > 0) {\n\t\t\tconst node = stack.pop()!;\n\t\t\tnode.children.sort((a, b) => new Date(a.entry.timestamp).getTime() - new Date(b.entry.timestamp).getTime());\n\t\t\tstack.push(...node.children);\n\t\t}\n\n\t\treturn roots;\n\t}\n\n\t// =========================================================================\n\t// Branching\n\t// =========================================================================\n\n\t/**\n\t * Start a new branch from an earlier entry.\n\t * Moves the leaf pointer to the specified entry. The next appendXXX() call\n\t * will create a child of that entry, forming a new branch. Existing entries\n\t * are not modified or deleted.\n\t */\n\tbranch(branchFromId: string): void {\n\t\tif (!this.byId.has(branchFromId)) {\n\t\t\tthrow new Error(`Entry ${branchFromId} not found`);\n\t\t}\n\t\tthis.leafId = branchFromId;\n\t}\n\n\t/**\n\t * Reset the leaf pointer to null (before any entries).\n\t * The next appendXXX() call will create a new root entry (parentId = null).\n\t * Use this when navigating to re-edit the first user message.\n\t */\n\tresetLeaf(): void {\n\t\tthis.leafId = null;\n\t}\n\n\t/**\n\t * Start a new branch with a summary of the abandoned path.\n\t * Same as branch(), but also appends a branch_summary entry that captures\n\t * context from the abandoned conversation path.\n\t */\n\tbranchWithSummary(\n\t\tbranchFromId: string | null,\n\t\tsummary: string,\n\t\tdetails?: unknown,\n\t\tfromHook?: boolean,\n\t\tusage?: Usage,\n\t): string {\n\t\tif (branchFromId !== null && !this.byId.has(branchFromId)) {\n\t\t\tthrow new Error(`Entry ${branchFromId} not found`);\n\t\t}\n\t\tthis.leafId = branchFromId;\n\t\tconst entry: BranchSummaryEntry = {\n\t\t\ttype: \"branch_summary\",\n\t\t\tid: generateId(this.byId),\n\t\t\tparentId: branchFromId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tfromId: branchFromId ?? \"root\",\n\t\t\tsummary,\n\t\t\tdetails,\n\t\t\tusage,\n\t\t\tfromHook,\n\t\t};\n\t\tthis._appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\t/**\n\t * Create a new session file containing only the path from root to the specified leaf.\n\t * Useful for extracting a single conversation path from a branched session.\n\t * Returns the new session file path, or undefined if not persisting.\n\t */\n\tcreateBranchedSession(leafId: string): string | undefined {\n\t\tconst previousSessionFile = this.sessionFile;\n\t\tconst path = this.getBranch(leafId);\n\t\tif (path.length === 0) {\n\t\t\tthrow new Error(`Entry ${leafId} not found`);\n\t\t}\n\n\t\t// Filter out LabelEntry from path - we'll recreate them from the resolved map.\n\t\t// Because labels are real tree entries, later entries can be children of labels;\n\t\t// removing labels requires re-chaining the retained path to avoid orphaned subtrees.\n\t\tconst pathWithoutLabels: SessionEntry[] = [];\n\t\tlet pathParentId: string | null = null;\n\t\tfor (const entry of path) {\n\t\t\tif (entry.type === \"label\") continue;\n\t\t\tpathWithoutLabels.push({ ...entry, parentId: pathParentId });\n\t\t\tpathParentId = entry.id;\n\t\t}\n\n\t\tconst newSessionId = createSessionId();\n\t\tconst timestamp = new Date().toISOString();\n\t\tconst fileTimestamp = timestamp.replace(/[:.]/g, \"-\");\n\t\tconst newSessionFile = join(this.getSessionDir(), `${fileTimestamp}_${newSessionId}.jsonl`);\n\n\t\tconst header: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: CURRENT_SESSION_VERSION,\n\t\t\tid: newSessionId,\n\t\t\ttimestamp,\n\t\t\tcwd: this.cwd,\n\t\t\tparentSession: this.persist ? previousSessionFile : undefined,\n\t\t};\n\n\t\t// Collect labels for entries in the path\n\t\tconst pathEntryIds = new Set(pathWithoutLabels.map((e) => e.id));\n\t\tconst labelsToWrite: Array<{ targetId: string; label: string; timestamp: string }> = [];\n\t\tfor (const [targetId, label] of this.labelsById) {\n\t\t\tif (pathEntryIds.has(targetId)) {\n\t\t\t\tlabelsToWrite.push({ targetId, label, timestamp: this.labelTimestampsById.get(targetId)! });\n\t\t\t}\n\t\t}\n\n\t\tif (this.persist) {\n\t\t\t// Build label entries\n\t\t\tconst lastEntryId = pathWithoutLabels[pathWithoutLabels.length - 1]?.id || null;\n\t\t\tlet parentId = lastEntryId;\n\t\t\tconst labelEntries: LabelEntry[] = [];\n\t\t\tfor (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {\n\t\t\t\tconst labelEntry: LabelEntry = {\n\t\t\t\t\ttype: \"label\",\n\t\t\t\t\tid: generateId(new Set(pathEntryIds)),\n\t\t\t\t\tparentId,\n\t\t\t\t\ttimestamp: labelTimestamp,\n\t\t\t\t\ttargetId,\n\t\t\t\t\tlabel,\n\t\t\t\t};\n\t\t\t\tpathEntryIds.add(labelEntry.id);\n\t\t\t\tlabelEntries.push(labelEntry);\n\t\t\t\tparentId = labelEntry.id;\n\t\t\t}\n\n\t\t\tthis.fileEntries = [header, ...pathWithoutLabels, ...labelEntries];\n\t\t\tthis.sessionId = newSessionId;\n\t\t\tthis.sessionFile = newSessionFile;\n\t\t\tthis._buildIndex();\n\n\t\t\t// Only write the file now if it contains an assistant message.\n\t\t\t// Otherwise defer to _persist(), which creates the file on the\n\t\t\t// first assistant response, matching the newSession() contract\n\t\t\t// and avoiding the duplicate-header bug when _persist()'s\n\t\t\t// no-assistant guard later resets flushed to false.\n\t\t\tconst hasAssistant = this.fileEntries.some((e) => e.type === \"message\" && e.message.role === \"assistant\");\n\t\t\tif (hasAssistant) {\n\t\t\t\tthis._rewriteFile();\n\t\t\t\tthis.flushed = true;\n\t\t\t} else {\n\t\t\t\tthis.flushed = false;\n\t\t\t}\n\n\t\t\treturn newSessionFile;\n\t\t}\n\n\t\t// In-memory mode: replace current session with the path + labels\n\t\tconst labelEntries: LabelEntry[] = [];\n\t\tlet parentId = pathWithoutLabels[pathWithoutLabels.length - 1]?.id || null;\n\t\tfor (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {\n\t\t\tconst labelEntry: LabelEntry = {\n\t\t\t\ttype: \"label\",\n\t\t\t\tid: generateId(new Set([...pathEntryIds, ...labelEntries.map((e) => e.id)])),\n\t\t\t\tparentId,\n\t\t\t\ttimestamp: labelTimestamp,\n\t\t\t\ttargetId,\n\t\t\t\tlabel,\n\t\t\t};\n\t\t\tlabelEntries.push(labelEntry);\n\t\t\tparentId = labelEntry.id;\n\t\t}\n\t\tthis.fileEntries = [header, ...pathWithoutLabels, ...labelEntries];\n\t\tthis.sessionId = newSessionId;\n\t\tthis._buildIndex();\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Create a new session.\n\t * @param cwd Working directory (stored in session header)\n\t * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).\n\t */\n\tstatic create(cwd: string, sessionDir?: string, options?: NewSessionOptions): SessionManager {\n\t\tconst dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);\n\t\treturn new SessionManager(cwd, dir, undefined, true, options);\n\t}\n\n\t/**\n\t * Open a specific session file.\n\t * @param path Path to session file\n\t * @param sessionDir Optional session directory for /new or /branch. If omitted, derives from file's parent.\n\t * @param cwdOverride Optional cwd override instead of the session header cwd.\n\t */\n\tstatic open(path: string, sessionDir?: string, cwdOverride?: string): SessionManager {\n\t\tconst resolvedPath = resolvePath(path);\n\t\tlet header: SessionHeader | null = null;\n\t\tlet preloadedFileEntries: FileEntry[] | undefined;\n\t\tif (cwdOverride === undefined && existsSync(resolvedPath)) {\n\t\t\ttry {\n\t\t\t\theader = readSessionHeader(resolvedPath);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof SessionHeaderScanLimitError)) throw error;\n\t\t\t\t// The bounded scan is only a discovery optimization. A full load remains\n\t\t\t\t// authoritative for legacy files with very large headers or prefixes.\n\t\t\t\tpreloadedFileEntries = loadEntriesFromFile(resolvedPath);\n\t\t\t\tconst firstEntry = preloadedFileEntries[0];\n\t\t\t\theader = firstEntry?.type === \"session\" ? firstEntry : null;\n\t\t\t}\n\t\t}\n\t\tconst cwd = cwdOverride ?? (header ? getSessionHeaderCwd(header) : undefined) ?? process.cwd();\n\t\t// If no sessionDir provided, derive from file's parent directory\n\t\tconst dir = sessionDir ? normalizePath(sessionDir) : resolve(resolvedPath, \"..\");\n\t\treturn new SessionManager(cwd, dir, resolvedPath, true, undefined, preloadedFileEntries);\n\t}\n\n\t/**\n\t * Continue the most recent session, or create new if none.\n\t * @param cwd Working directory\n\t * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).\n\t */\n\tstatic continueRecent(cwd: string, sessionDir?: string): SessionManager {\n\t\tconst dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);\n\t\tconst filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);\n\t\tconst mostRecent = findMostRecentSession(dir, filterCwd ? cwd : undefined);\n\t\tif (mostRecent) {\n\t\t\treturn new SessionManager(cwd, dir, mostRecent, true);\n\t\t}\n\t\treturn new SessionManager(cwd, dir, undefined, true);\n\t}\n\n\t/** Create an in-memory session (no file persistence) */\n\tstatic inMemory(cwd: string = process.cwd(), options?: NewSessionOptions): SessionManager {\n\t\treturn new SessionManager(cwd, \"\", undefined, false, options);\n\t}\n\n\t/**\n\t * Fork a session from another project directory into the current project.\n\t * Creates a new session in the target cwd with the full history from the source session.\n\t * @param sourcePath Path to the source session file\n\t * @param targetCwd Target working directory (where the new session will be stored)\n\t * @param sessionDir Optional session directory. If omitted, uses default for targetCwd.\n\t */\n\tstatic forkFrom(\n\t\tsourcePath: string,\n\t\ttargetCwd: string,\n\t\tsessionDir?: string,\n\t\toptions?: NewSessionOptions,\n\t): SessionManager {\n\t\tconst resolvedSourcePath = resolvePath(sourcePath);\n\t\tconst resolvedTargetCwd = resolvePath(targetCwd);\n\t\tconst sourceEntries = loadEntriesFromFile(resolvedSourcePath);\n\t\tif (sourceEntries.length === 0) {\n\t\t\tthrow new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);\n\t\t}\n\n\t\tconst sourceHeader = sourceEntries.find((e) => e.type === \"session\") as SessionHeader | undefined;\n\t\tif (!sourceHeader) {\n\t\t\tthrow new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);\n\t\t}\n\n\t\tconst dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(resolvedTargetCwd);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\n\t\t// Create new session file with new ID but forked content\n\t\tif (options?.id !== undefined) {\n\t\t\tassertValidSessionId(options.id);\n\t\t}\n\t\tconst newSessionId = options?.id ?? createSessionId();\n\t\tconst timestamp = new Date().toISOString();\n\t\tconst fileTimestamp = timestamp.replace(/[:.]/g, \"-\");\n\t\tconst newSessionFile = join(dir, `${fileTimestamp}_${newSessionId}.jsonl`);\n\n\t\t// Write new header pointing to source as parent, with updated cwd\n\t\tconst newHeader: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: CURRENT_SESSION_VERSION,\n\t\t\tid: newSessionId,\n\t\t\ttimestamp,\n\t\t\tcwd: resolvedTargetCwd,\n\t\t\tparentSession: resolvedSourcePath,\n\t\t};\n\t\twriteFileSync(newSessionFile, `${JSON.stringify(newHeader)}\\n`, { flag: \"wx\" });\n\n\t\t// Copy all non-header entries from source\n\t\tfor (const entry of sourceEntries) {\n\t\t\tif (entry.type !== \"session\") {\n\t\t\t\tappendFileSync(newSessionFile, `${JSON.stringify(entry)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\treturn new SessionManager(resolvedTargetCwd, dir, newSessionFile, true);\n\t}\n\n\t/**\n\t * List all sessions for a directory.\n\t * @param cwd Working directory (used to compute default session directory)\n\t * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).\n\t * @param onProgress Optional callback for progress updates (loaded, total)\n\t */\n\tstatic async list(cwd: string, sessionDir?: string, onProgress?: SessionListProgress): Promise<SessionInfo[]> {\n\t\tconst dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);\n\t\tconst filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);\n\t\tconst resolvedCwd = resolvePath(cwd);\n\t\tconst sessions = (await listSessionsFromDir(dir, onProgress)).filter(\n\t\t\t(session) => !filterCwd || sessionCwdMatches(session.cwd, resolvedCwd),\n\t\t);\n\t\tsessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());\n\t\treturn sessions;\n\t}\n\n\t/**\n\t * List all sessions across all project directories.\n\t * @param onProgress Optional callback for progress updates (loaded, total)\n\t */\n\tstatic async listAll(onProgress?: SessionListProgress): Promise<SessionInfo[]>;\n\tstatic async listAll(sessionDir?: string, onProgress?: SessionListProgress): Promise<SessionInfo[]>;\n\tstatic async listAll(\n\t\tsessionDirOrOnProgress?: string | SessionListProgress,\n\t\tonProgress?: SessionListProgress,\n\t): Promise<SessionInfo[]> {\n\t\tconst customSessionDir =\n\t\t\ttypeof sessionDirOrOnProgress === \"string\" ? normalizePath(sessionDirOrOnProgress) : undefined;\n\t\tconst progress = typeof sessionDirOrOnProgress === \"function\" ? sessionDirOrOnProgress : onProgress;\n\t\tif (customSessionDir) {\n\t\t\tconst sessions = await listSessionsFromDir(customSessionDir, progress);\n\t\t\tsessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());\n\t\t\treturn sessions;\n\t\t}\n\n\t\tconst sessionsDir = getSessionsDir();\n\n\t\ttry {\n\t\t\tif (!existsSync(sessionsDir)) {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\tconst entries = await readdir(sessionsDir, { withFileTypes: true });\n\t\t\tconst dirs = entries\n\t\t\t\t.filter((entry) => entry.isDirectory() || entry.isSymbolicLink())\n\t\t\t\t.map((entry) => join(sessionsDir, entry.name));\n\n\t\t\t// Count total files first for accurate progress\n\t\t\tlet totalFiles = 0;\n\t\t\tconst dirFiles: string[][] = [];\n\t\t\tfor (const dir of dirs) {\n\t\t\t\ttry {\n\t\t\t\t\tconst files = (await readdir(dir)).filter((f) => f.endsWith(\".jsonl\"));\n\t\t\t\t\tdirFiles.push(files.map((f) => join(dir, f)));\n\t\t\t\t\ttotalFiles += files.length;\n\t\t\t\t} catch {\n\t\t\t\t\tdirFiles.push([]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Process all files with progress tracking\n\t\t\tlet loaded = 0;\n\t\t\tconst sessions: SessionInfo[] = [];\n\t\t\tconst allFiles = dirFiles.flat();\n\n\t\t\tconst results = await buildSessionInfosWithConcurrency(allFiles, () => {\n\t\t\t\tloaded++;\n\t\t\t\tprogress?.(loaded, totalFiles);\n\t\t\t});\n\n\t\t\tfor (const info of results) {\n\t\t\t\tif (info) {\n\t\t\t\t\tsessions.push(info);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());\n\t\t\treturn sessions;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}\n}\n","// @ts-nocheck — vendored Pi source; checked upstream under Pi's own tsconfig.\n/**\n * Shared truncation utilities for tool outputs.\n *\n * Truncation is based on two independent limits - whichever is hit first wins:\n * - Line limit (default: 2000 lines)\n * - Byte limit (default: 50KB)\n *\n * Never returns partial lines (except bash tail truncation edge case).\n */\n\nexport const DEFAULT_MAX_LINES = 2000;\nexport const DEFAULT_MAX_BYTES = 50 * 1024; // 50KB\nexport const GREP_MAX_LINE_LENGTH = 500; // Max chars per grep match line\n\nexport interface TruncationResult {\n\t/** The truncated content */\n\tcontent: string;\n\t/** Whether truncation occurred */\n\ttruncated: boolean;\n\t/** Which limit was hit: \"lines\", \"bytes\", or null if not truncated */\n\ttruncatedBy: \"lines\" | \"bytes\" | null;\n\t/** Total number of lines in the original content */\n\ttotalLines: number;\n\t/** Total number of bytes in the original content */\n\ttotalBytes: number;\n\t/** Number of complete lines in the truncated output */\n\toutputLines: number;\n\t/** Number of bytes in the truncated output */\n\toutputBytes: number;\n\t/** Whether the last line was partially truncated (only for tail truncation edge case) */\n\tlastLinePartial: boolean;\n\t/** Whether the first line exceeded the byte limit (for head truncation) */\n\tfirstLineExceedsLimit: boolean;\n\t/** The max lines limit that was applied */\n\tmaxLines: number;\n\t/** The max bytes limit that was applied */\n\tmaxBytes: number;\n}\n\nexport interface TruncationOptions {\n\t/** Maximum number of lines (default: 2000) */\n\tmaxLines?: number;\n\t/** Maximum number of bytes (default: 50KB) */\n\tmaxBytes?: number;\n}\n\nfunction splitLinesForCounting(content: string): string[] {\n\tif (content.length === 0) {\n\t\treturn [];\n\t}\n\tconst lines = content.split(\"\\n\");\n\tif (content.endsWith(\"\\n\")) {\n\t\tlines.pop();\n\t}\n\treturn lines;\n}\n\n/**\n * Format bytes as human-readable size.\n */\nexport function formatSize(bytes: number): string {\n\tif (bytes < 1024) {\n\t\treturn `${bytes}B`;\n\t} else if (bytes < 1024 * 1024) {\n\t\treturn `${(bytes / 1024).toFixed(1)}KB`;\n\t} else {\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n\t}\n}\n\n/**\n * Truncate content from the head (keep first N lines/bytes).\n * Suitable for file reads where you want to see the beginning.\n *\n * Never returns partial lines. If first line exceeds byte limit,\n * returns empty content with firstLineExceedsLimit=true.\n */\nexport function truncateHead(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Check if first line alone exceeds byte limit\n\tconst firstLineBytes = Buffer.byteLength(lines[0], \"utf-8\");\n\tif (firstLineBytes > maxBytes) {\n\t\treturn {\n\t\t\tcontent: \"\",\n\t\t\ttruncated: true,\n\t\t\ttruncatedBy: \"bytes\",\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: 0,\n\t\t\toutputBytes: 0,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: true,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Collect complete lines that fit\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\n\tfor (let i = 0; i < lines.length && i < maxLines; i++) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (i > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.push(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial: false,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate content from the tail (keep last N lines/bytes).\n * Suitable for bash output where you want to see the end (errors, final results).\n *\n * May return partial first line if the last line of original content exceeds byte limit.\n */\nexport function truncateTail(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Work backwards from the end\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\tlet lastLinePartial = false;\n\n\tfor (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (outputLinesArr.length > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\t// Edge case: if we haven't added ANY lines yet and this line exceeds maxBytes,\n\t\t\t// take the end of the line (partial)\n\t\t\tif (outputLinesArr.length === 0) {\n\t\t\t\tconst truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);\n\t\t\t\toutputLinesArr.unshift(truncatedLine);\n\t\t\t\toutputBytesCount = Buffer.byteLength(truncatedLine, \"utf-8\");\n\t\t\t\tlastLinePartial = true;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.unshift(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate a string to fit within a byte limit (from the end).\n * Handles multi-byte UTF-8 characters correctly.\n */\nfunction truncateStringToBytesFromEnd(str: string, maxBytes: number): string {\n\tconst buf = Buffer.from(str, \"utf-8\");\n\tif (buf.length <= maxBytes) {\n\t\treturn str;\n\t}\n\n\t// Start from the end, skip maxBytes back\n\tlet start = buf.length - maxBytes;\n\n\t// Find a valid UTF-8 boundary (start of a character)\n\twhile (start < buf.length && (buf[start] & 0xc0) === 0x80) {\n\t\tstart++;\n\t}\n\n\treturn buf.slice(start).toString(\"utf-8\");\n}\n\n/**\n * Truncate a single line to max characters, adding [truncated] suffix.\n * Used for grep match lines.\n */\nexport function truncateLine(\n\tline: string,\n\tmaxChars: number = GREP_MAX_LINE_LENGTH,\n): { text: string; wasTruncated: boolean } {\n\tif (line.length <= maxChars) {\n\t\treturn { text: line, wasTruncated: false };\n\t}\n\treturn { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };\n}\n","// @ts-nocheck — vendored Pi source; checked upstream under Pi's own tsconfig.\nimport { realpath } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nconst fileMutationQueues = new Map<string, Promise<void>>();\nlet registrationQueue = Promise.resolve();\n\nfunction isMissingPathError(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error.code === \"ENOENT\" || error.code === \"ENOTDIR\")\n\t);\n}\n\nasync function getMutationQueueKey(filePath: string): Promise<string> {\n\tconst resolvedPath = resolve(filePath);\n\ttry {\n\t\treturn await realpath(resolvedPath);\n\t} catch (error) {\n\t\tif (isMissingPathError(error)) {\n\t\t\treturn resolvedPath;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Serialize file mutation operations targeting the same file.\n * Operations for different files still run in parallel.\n */\nexport async function withFileMutationQueue<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n\tconst registration = registrationQueue.then(async () => {\n\t\tconst key = await getMutationQueueKey(filePath);\n\t\tconst currentQueue = fileMutationQueues.get(key) ?? Promise.resolve();\n\n\t\tlet releaseNext!: () => void;\n\t\tconst nextQueue = new Promise<void>((resolveQueue) => {\n\t\t\treleaseNext = resolveQueue;\n\t\t});\n\t\tconst chainedQueue = currentQueue.then(() => nextQueue);\n\t\tfileMutationQueues.set(key, chainedQueue);\n\n\t\treturn { key, currentQueue, chainedQueue, releaseNext };\n\t});\n\tregistrationQueue = registration.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\n\tconst { key, currentQueue, chainedQueue, releaseNext } = await registration;\n\tawait currentQueue;\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\treleaseNext();\n\t\tif (fileMutationQueues.get(key) === chainedQueue) {\n\t\t\tfileMutationQueues.delete(key);\n\t\t}\n\t}\n}\n","// Headless @earendil-works/pi-coding-agent compatibility surface.\n//\n// Three tiers, all package-agnostic:\n// 1. Vendored Pi source (SessionManager, message transforms, truncation,\n// file-mutation queue) — byte-level Pi semantics, see ./vendor/PI-LICENSE.\n// 2. Headless reimplementations (Theme, settings, shell/clipboard/image\n// helpers) — same signatures, no terminal or Pi-global state.\n// 3. Explicit-failure stubs (AgentSession runtime, resource loaders) —\n// importable and constructible so packages load, but running them\n// requires a native DSH port and fails with a clear message instead of\n// silently faking success.\n\nexport {\n SessionManager,\n CURRENT_SESSION_VERSION,\n parseSessionEntries,\n migrateSessionEntries,\n getLatestCompactionEntry,\n sessionEntryToContextMessages,\n buildContextEntries,\n buildSessionContext,\n loadEntriesFromFile,\n findMostRecentSession,\n getDefaultSessionDir,\n assertValidSessionId,\n} from './vendor/pi-session-manager.js'\nexport type {\n SessionEntry,\n SessionHeader,\n SessionTreeNode,\n SessionContext,\n SessionInfo,\n SessionMessageEntry,\n CompactionEntry,\n BranchSummaryEntry,\n CustomEntry,\n CustomMessageEntry,\n LabelEntry,\n SessionInfoEntry,\n ThinkingLevelChangeEntry,\n ModelChangeEntry,\n} from './vendor/pi-session-manager.js'\nexport {\n convertToLlm,\n createBranchSummaryMessage,\n createCompactionSummaryMessage,\n createCustomMessage,\n bashExecutionToText,\n COMPACTION_SUMMARY_PREFIX,\n COMPACTION_SUMMARY_SUFFIX,\n BRANCH_SUMMARY_PREFIX,\n BRANCH_SUMMARY_SUFFIX,\n} from './vendor/pi-messages.js'\nexport type {\n BashExecutionMessage,\n CustomMessage,\n BranchSummaryMessage,\n CompactionSummaryMessage,\n} from './vendor/pi-messages.js'\nexport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n truncateHead,\n truncateLine,\n truncateTail,\n} from './vendor/pi-truncate.js'\nexport type { TruncationOptions, TruncationResult } from './vendor/pi-truncate.js'\nexport { withFileMutationQueue } from './vendor/pi-file-mutation-queue.js'\nexport { getAgentDir } from './vendor/pi-config-shim.js'\n\nimport { homedir } from 'node:os'\nimport { join, delimiter } from 'node:path'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { execFile } from 'node:child_process'\nimport type { AgentMessage } from './vendor/pi-types.js'\nimport type { Component, SettingsListTheme, SelectListTheme } from './pi-tui.js'\nimport { visibleWidth, truncateToWidth } from './vendor/pi-tui-utils.js'\nimport { getAgentDir as agentDirOf } from './vendor/pi-config-shim.js'\n\nexport const CONFIG_DIR_NAME = '.pi'\nexport const VERSION = 'pi2dsh-compat'\n\nexport function defineTool<T>(tool: T): T {\n return tool\n}\n\nfunction unsupportedRuntime(name: string): never {\n throw new Error(\n `pi2dsh: ${name} belongs to Pi's internal agent runtime and has no verified DSH mapping; `\n + 'use the DSH-native service instead (see the pi2dsh compatibility report)',\n )\n}\n\n// ---------------------------------------------------------------------------\n// Theme system (headless)\n// ---------------------------------------------------------------------------\n\nconst identity = (text: string): string => text\n\nexport type ThemeColor = string\nexport type ThemeBg = string\nexport type ColorMode = 'truecolor' | '256' | '16' | 'none'\n\nexport class Theme {\n constructor(public name = 'pi2dsh-headless') {}\n fg(_color: ThemeColor, text: string): string {\n return text\n }\n bg(_color: ThemeBg, text: string): string {\n return text\n }\n bold(text: string): string {\n return text\n }\n italic(text: string): string {\n return text\n }\n underline(text: string): string {\n return text\n }\n inverse(text: string): string {\n return text\n }\n strikethrough(text: string): string {\n return text\n }\n getFgAnsi(_color: ThemeColor): string {\n return ''\n }\n getBgAnsi(_color: ThemeBg): string {\n return ''\n }\n getColorMode(): ColorMode {\n return 'none'\n }\n getThinkingBorderColor(_level: unknown): (str: string) => string {\n return identity\n }\n getBashModeBorderColor(): (str: string) => string {\n return identity\n }\n}\n\nexport const theme = new Theme()\n\nexport function initTheme(_themeName?: string, _enableWatcher = false): void {}\n\nexport function getSettingsListTheme(): SettingsListTheme {\n return {\n label: (text: string, _selected: boolean) => text,\n value: (text: string, _selected: boolean) => text,\n description: (text: string) => text,\n cursor: '→ ',\n hint: (text: string) => text,\n }\n}\n\nexport function getSelectListTheme(): SelectListTheme {\n return {\n selectedPrefix: '→ ',\n selectedText: identity,\n description: identity,\n scrollInfo: identity,\n noMatch: identity,\n }\n}\n\nexport function getMarkdownTheme(): Record<string, unknown> {\n return {\n heading: identity, link: identity, linkUrl: identity, code: identity, codeBlock: identity,\n codeBlockBorder: identity, quote: identity, quoteBorder: identity, hr: identity,\n listBullet: identity, bold: identity, italic: identity, underline: identity,\n strikethrough: identity, highlightCode: (code: string) => code.split('\\n'),\n }\n}\n\nconst LANGUAGE_BY_EXTENSION: Record<string, string> = {\n '.ts': 'typescript', '.tsx': 'typescript', '.js': 'javascript', '.jsx': 'javascript',\n '.mjs': 'javascript', '.cjs': 'javascript', '.py': 'python', '.rb': 'ruby', '.go': 'go',\n '.rs': 'rust', '.java': 'java', '.c': 'c', '.h': 'c', '.cpp': 'cpp', '.hpp': 'cpp',\n '.cs': 'csharp', '.sh': 'bash', '.bash': 'bash', '.zsh': 'bash', '.json': 'json',\n '.yaml': 'yaml', '.yml': 'yaml', '.toml': 'ini', '.md': 'markdown', '.html': 'xml',\n '.xml': 'xml', '.css': 'css', '.scss': 'scss', '.sql': 'sql', '.php': 'php',\n '.swift': 'swift', '.kt': 'kotlin', '.scala': 'scala', '.lua': 'lua', '.r': 'r',\n}\n\nexport function getLanguageFromPath(filePath: string): string | undefined {\n const dot = filePath.lastIndexOf('.')\n if (dot === -1) return undefined\n return LANGUAGE_BY_EXTENSION[filePath.slice(dot).toLowerCase()]\n}\n\nexport function highlightCode(code: string, _lang?: string): string[] {\n return code.split('\\n')\n}\n\nexport class DynamicBorder implements Component {\n constructor(private color: (str: string) => string = identity) {}\n render(width: number): string[] {\n return [this.color('─'.repeat(Math.max(1, width)))]\n }\n invalidate(): void {}\n}\n\n// ---------------------------------------------------------------------------\n// Message / compaction helpers\n// ---------------------------------------------------------------------------\n\nfunction contentChars(content: unknown): number {\n if (typeof content === 'string') return content.length\n if (!Array.isArray(content)) return 0\n let chars = 0\n for (const block of content) {\n if (typeof block !== 'object' || block === null) continue\n const record = block as Record<string, unknown>\n if (typeof record.text === 'string') chars += record.text.length\n else if (typeof record.thinking === 'string') chars += record.thinking.length\n else if (record.type === 'image') chars += 1600\n else if (record.arguments !== undefined) chars += JSON.stringify(record.arguments ?? {}).length\n }\n return chars\n}\n\n// chars/4 heuristic, matching Pi's estimateTokens semantics.\nexport function estimateTokens(message: AgentMessage): number {\n const record = message as Record<string, unknown>\n let chars = contentChars(record.content)\n if (typeof record.summary === 'string') chars += (record.summary as string).length\n if (record.role === 'bashExecution') {\n chars += String(record.command ?? '').length + String(record.output ?? '').length\n }\n return Math.ceil(chars / 4)\n}\n\nexport function calculateContextTokens(messages: AgentMessage[]): number {\n return messages.reduce((total, message) => total + estimateTokens(message), 0)\n}\n\nexport const DEFAULT_COMPACTION_SETTINGS = Object.freeze({\n enabled: true,\n reserveTokens: 30_000,\n keepRecentTokens: 20_000,\n})\n\nexport function shouldCompact(..._args: unknown[]): boolean {\n return false\n}\n\nexport function compact(..._args: unknown[]): never {\n return unsupportedRuntime('compact()')\n}\n\nexport function findCutPoint(..._args: unknown[]): never {\n return unsupportedRuntime('findCutPoint()')\n}\n\nexport function generateSummary(..._args: unknown[]): never {\n return unsupportedRuntime('generateSummary()')\n}\n\nexport function generateSummaryWithUsage(..._args: unknown[]): never {\n return unsupportedRuntime('generateSummaryWithUsage()')\n}\n\nexport function generateBranchSummary(..._args: unknown[]): never {\n return unsupportedRuntime('generateBranchSummary()')\n}\n\nexport function serializeConversation(messages: AgentMessage[]): string {\n return JSON.stringify(messages)\n}\n\n// ---------------------------------------------------------------------------\n// Frontmatter\n// ---------------------------------------------------------------------------\n\nexport function parseFrontmatter(text: string): { attributes: Record<string, string>; body: string } {\n const normalized = text.replace(/\\r\\n?/gu, '\\n')\n if (!normalized.startsWith('---')) return { attributes: {}, body: normalized }\n const endIndex = normalized.indexOf('\\n---', 3)\n if (endIndex === -1) return { attributes: {}, body: normalized }\n const attributes: Record<string, string> = {}\n for (const line of normalized.slice(4, endIndex).split('\\n')) {\n const separator = line.indexOf(':')\n if (separator === -1) continue\n const key = line.slice(0, separator).trim()\n let value = line.slice(separator + 1).trim()\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1)\n }\n if (key.length > 0) attributes[key] = value\n }\n return { attributes, body: normalized.slice(endIndex + 4).replace(/^\\n/u, '') }\n}\n\nexport function stripFrontmatter(text: string): string {\n return parseFrontmatter(text).body\n}\n\n// ---------------------------------------------------------------------------\n// Clipboard / image / shell helpers\n// ---------------------------------------------------------------------------\n\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const attempt = (command: string, args: string[]): Promise<boolean> =>\n new Promise(resolve => {\n const child = execFile(command, args, error => resolve(error === null))\n child.stdin?.write(text)\n child.stdin?.end()\n })\n if (process.platform === 'darwin') return attempt('pbcopy', [])\n if (process.platform === 'win32') return attempt('clip', [])\n if (await attempt('wl-copy', [])) return true\n return attempt('xclip', ['-selection', 'clipboard'])\n}\n\nexport interface ImageResizeOptions {\n maxWidth?: number\n maxHeight?: number\n [key: string]: unknown\n}\n\nexport interface ResizedImage {\n data: string\n mimeType: string\n width?: number\n height?: number\n [key: string]: unknown\n}\n\n// Headless degradation: images pass through un-resized. Pi resizes only to\n// save tokens, so returning the original preserves correctness.\nexport async function resizeImage(\n data: string,\n mimeType: string,\n _options: ImageResizeOptions = {},\n): Promise<ResizedImage> {\n return { data, mimeType }\n}\n\nexport async function convertToPng(data: string, mimeType: string): Promise<ResizedImage> {\n if (mimeType === 'image/png') return { data, mimeType }\n return unsupportedRuntime('convertToPng() for non-PNG input')\n}\n\nexport interface ShellConfig {\n shell: string\n args: string[]\n}\n\nexport function getShellConfig(): ShellConfig {\n if (process.platform === 'win32') {\n return { shell: process.env.COMSPEC ?? 'cmd.exe', args: ['/d', '/s', '/c'] }\n }\n const preferred = process.env.SHELL\n if (preferred !== undefined && preferred.length > 0 && existsSync(preferred)) {\n return { shell: preferred, args: ['-c'] }\n }\n for (const candidate of ['/bin/bash', '/bin/zsh', '/bin/sh']) {\n if (existsSync(candidate)) return { shell: candidate, args: ['-c'] }\n }\n return { shell: 'sh', args: ['-c'] }\n}\n\n// Pi's install-directory locator: PI_PACKAGE_DIR override, else a stable\n// bridge-owned location (Pi itself falls back to its executable's directory,\n// which has no meaningful equivalent inside DSH).\nexport function getPackageDir(): string {\n const override = process.env.PI_PACKAGE_DIR\n if (override !== undefined && override.length > 0) return override\n return join(agentDirOf(), 'package')\n}\n\nexport interface StoredCredential {\n type?: string\n [key: string]: unknown\n}\n\n// Pi's one-off synchronous auth.json read, against the pi2dsh-owned agent\n// directory. DSH credentials stay authoritative for DSH model calls; this\n// serves packages that manage their own provider credentials Pi-style.\nexport function readStoredCredential(\n providerId: string,\n authPath: string = join(agentDirOf(), 'auth.json'),\n): StoredCredential | undefined {\n try {\n const data = JSON.parse(readFileSync(authPath, 'utf8')) as Record<string, StoredCredential>\n return data[providerId]\n } catch {\n return undefined\n }\n}\n\nexport interface ParsedSkillBlock {\n name: string\n content: string\n [key: string]: unknown\n}\n\n// Pi's <skill_content name=\"...\"> block parser, reimplemented over the same\n// wire shape.\nexport function parseSkillBlock(text: string): ParsedSkillBlock | null {\n const match = /<skill_content\\b[^>]*\\bname=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\/skill_content>/u.exec(text)\n if (match === null) return null\n return { name: match[1]!, content: match[2]!.trim() }\n}\n\nexport function wrapRegisteredTool(..._args: unknown[]): never {\n return unsupportedRuntime('wrapRegisteredTool()')\n}\n\nexport function getBinDir(): string {\n const parts = (process.env.PATH ?? '').split(delimiter)\n return parts[0] ?? join(homedir(), '.local', 'bin')\n}\n\n// ---------------------------------------------------------------------------\n// Settings (in-memory, layered global/project like Pi)\n// ---------------------------------------------------------------------------\n\ntype SettingsRecord = Record<string, unknown>\n\nexport interface SettingsManagerCreateOptions {\n [key: string]: unknown\n}\n\nexport interface RetrySettings {\n enabled: boolean\n maxRetries: number\n baseDelayMs: number\n}\n\nexport interface CompactionSettings {\n enabled: boolean\n reserveTokens: number\n keepRecentTokens: number\n}\n\nexport type DefaultProjectTrust = 'ask' | 'always' | 'never'\nexport type TuiMode = 'regular' | 'fullscreen'\nexport type PackageSource = string | Record<string, unknown>\n\nexport class SettingsManager {\n private constructor(\n private globalSettings: SettingsRecord,\n private projectSettings: SettingsRecord,\n ) {}\n\n static create(_cwd?: string, _agentDir?: string, options: SettingsManagerCreateOptions = {}): SettingsManager {\n return SettingsManager.inMemory({}, options)\n }\n\n static fromStorage(_storage: unknown, options: SettingsManagerCreateOptions = {}): SettingsManager {\n return SettingsManager.inMemory({}, options)\n }\n\n static inMemory(settings: SettingsRecord = {}, _options: SettingsManagerCreateOptions = {}): SettingsManager {\n return new SettingsManager({ ...settings }, {})\n }\n\n private get merged(): SettingsRecord {\n return { ...this.globalSettings, ...this.projectSettings }\n }\n\n private read<T>(key: string, fallback: T): T {\n const value = this.merged[key]\n return value === undefined ? fallback : value as T\n }\n\n async reload(): Promise<void> {}\n async flush(): Promise<void> {}\n drainErrors(): unknown[] {\n return []\n }\n applyOverrides(overrides: SettingsRecord): void {\n Object.assign(this.globalSettings, overrides)\n }\n getGlobalSettings(): SettingsRecord {\n return { ...this.globalSettings }\n }\n getProjectSettings(): SettingsRecord {\n return { ...this.projectSettings }\n }\n isProjectTrusted(): boolean {\n return this.read('projectTrusted', false)\n }\n setProjectTrusted(trusted: boolean): void {\n this.projectSettings.projectTrusted = trusted\n }\n getDefaultProjectTrust(): DefaultProjectTrust {\n return this.read('defaultProjectTrust', 'ask')\n }\n getDefaultProvider(): string | undefined {\n return this.read('defaultProvider', undefined)\n }\n getDefaultModel(): string | undefined {\n return this.read('defaultModel', undefined)\n }\n setDefaultProvider(provider: string): void {\n this.globalSettings.defaultProvider = provider\n }\n setDefaultModel(model: string): void {\n this.globalSettings.defaultModel = model\n }\n setDefaultModelAndProvider(model: string, provider: string): void {\n this.setDefaultModel(model)\n this.setDefaultProvider(provider)\n }\n getDefaultThinkingLevel(): string | undefined {\n return this.read('defaultThinkingLevel', undefined)\n }\n getThemeSetting(): string | undefined {\n return this.read('theme', undefined)\n }\n getTheme(): string | undefined {\n return this.getThemeSetting()\n }\n setTheme(themeName: string): void {\n this.globalSettings.theme = themeName\n }\n getCompactionSettings(): CompactionSettings {\n return this.read('compaction', { ...DEFAULT_COMPACTION_SETTINGS })\n }\n getBranchSummarySettings(): { reserveTokens: number; skipPrompt: boolean } {\n return this.read('branchSummary', { reserveTokens: 8000, skipPrompt: false })\n }\n getRetrySettings(): RetrySettings {\n return this.read('retry', { enabled: true, maxRetries: 3, baseDelayMs: 1000 })\n }\n getProviderRetrySettings(): RetrySettings {\n return this.getRetrySettings()\n }\n getHttpIdleTimeoutMs(): number {\n return this.read('httpIdleTimeoutMs', 120_000)\n }\n getWebSocketConnectTimeoutMs(): number {\n return this.read('webSocketConnectTimeoutMs', 30_000)\n }\n getPackages(): PackageSource[] {\n return this.read('packages', [])\n }\n getExtensionPaths(): string[] {\n return this.read('extensions', [])\n }\n getSkillPaths(): string[] {\n return this.read('skills', [])\n }\n getPromptTemplatePaths(): string[] {\n return this.read('prompts', [])\n }\n getThemePaths(): string[] {\n return this.read('themes', [])\n }\n getTuiMode(): TuiMode {\n return this.read('tuiMode', 'regular')\n }\n getShowImages(): boolean {\n return this.read('showImages', false)\n }\n getImageWidthCells(): number {\n return this.read('imageWidthCells', 40)\n }\n getClearOnShrink(): boolean {\n return this.read('clearOnShrink', false)\n }\n getShowTerminalProgress(): boolean {\n return this.read('showTerminalProgress', false)\n }\n getHideThinkingBlock(): boolean {\n return this.read('hideThinkingBlock', false)\n }\n getExternalEditorCommand(): string | undefined {\n return this.read('externalEditorCommand', undefined)\n }\n getSteeringMode(): 'all' | 'one-at-a-time' {\n return this.read('steeringMode', 'all')\n }\n getFollowUpMode(): string {\n return this.read('followUpMode', 'queue')\n }\n getShellPath(): string | undefined {\n return this.read('shellPath', undefined)\n }\n getShellCommandPrefix(): string | undefined {\n return this.read('shellCommandPrefix', undefined)\n }\n getNpmCommand(): string[] | undefined {\n return this.read('npmCommand', undefined)\n }\n getEnableSkillCommands(): boolean {\n return this.read('enableSkillCommands', true)\n }\n getEnableAnalytics(): boolean {\n return false\n }\n getTrackingId(): string | undefined {\n return undefined\n }\n}\n\nexport class InMemorySettingsStorage {\n constructor(public settings: SettingsRecord = {}) {}\n async withLock<T>(_scope: string, fn: () => Promise<T> | T): Promise<T> {\n return fn()\n }\n}\n\nexport class FileSettingsStorage extends InMemorySettingsStorage {}\n\n// ---------------------------------------------------------------------------\n// Explicit-failure stubs for Pi's internal agent runtime\n// ---------------------------------------------------------------------------\n\nfunction runtimeStubClass(name: string): new (...args: unknown[]) => never {\n return class {\n constructor() {\n return unsupportedRuntime(`new ${name}()`)\n }\n } as never\n}\n\nexport const ProjectTrustStore = runtimeStubClass('ProjectTrustStore')\nexport const DefaultResourceLoader = runtimeStubClass('DefaultResourceLoader')\nexport const DefaultPackageManager = runtimeStubClass('DefaultPackageManager')\nexport const ModelRuntime = runtimeStubClass('ModelRuntime')\n\nexport class ModelRegistry {\n private models = new Map<string, unknown>()\n register(id: string, model: unknown): void {\n this.models.set(id, model)\n }\n get(id: string): unknown {\n return this.models.get(id)\n }\n list(): unknown[] {\n return [...this.models.values()]\n }\n}\n\nexport function createAgentSession(..._args: unknown[]): never {\n return unsupportedRuntime('createAgentSession()')\n}\n\nexport function createCodingTools(..._args: unknown[]): never {\n return unsupportedRuntime('createCodingTools()')\n}\n\nexport function createReadOnlyTools(..._args: unknown[]): never {\n return unsupportedRuntime('createReadOnlyTools()')\n}\n\nexport function createBashTool(..._args: unknown[]): never {\n return unsupportedRuntime('createBashTool()')\n}\n\nexport function createReadTool(..._args: unknown[]): never {\n return unsupportedRuntime('createReadTool()')\n}\n\nexport function createEditTool(..._args: unknown[]): never {\n return unsupportedRuntime('createEditTool()')\n}\n\nexport function createWriteTool(..._args: unknown[]): never {\n return unsupportedRuntime('createWriteTool()')\n}\n\nexport function createGrepTool(..._args: unknown[]): never {\n return unsupportedRuntime('createGrepTool()')\n}\n\nexport function createFindTool(..._args: unknown[]): never {\n return unsupportedRuntime('createFindTool()')\n}\n\nexport function createLsTool(..._args: unknown[]): never {\n return unsupportedRuntime('createLsTool()')\n}\n\nexport function loadSkills(..._args: unknown[]): never {\n return unsupportedRuntime('loadSkills()')\n}\n\nexport function loadSkillsFromDir(..._args: unknown[]): never {\n return unsupportedRuntime('loadSkillsFromDir()')\n}\n\nexport function formatSkillsForPrompt(..._args: unknown[]): never {\n return unsupportedRuntime('formatSkillsForPrompt()')\n}\n\nexport function createEventBus(): {\n emit(channel: string, data: unknown): void\n on(channel: string, handler: (data: unknown) => void): () => void\n clear(): void\n} {\n const handlers = new Map<string, Set<(data: unknown) => void>>()\n return {\n emit(channel, data) {\n for (const handler of handlers.get(channel) ?? []) {\n Promise.resolve().then(() => handler(data)).catch(error => console.error(error))\n }\n },\n on(channel, handler) {\n const set = handlers.get(channel) ?? new Set()\n set.add(handler)\n handlers.set(channel, set)\n return () => {\n set.delete(handler)\n }\n },\n clear() {\n handlers.clear()\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Interactive-mode UI components (headless)\n// ---------------------------------------------------------------------------\n\nclass HeadlessComponent implements Component {\n render(_width: number): string[] {\n return []\n }\n invalidate(): void {}\n}\n\nexport class ToolExecutionComponent extends HeadlessComponent {}\nexport class FooterComponent extends HeadlessComponent {}\nexport class BorderedLoader extends HeadlessComponent {\n start(): void {}\n stop(): void {}\n dispose(): void {}\n}\nexport class CustomMessageComponent extends HeadlessComponent {}\nexport class AssistantMessageComponent extends HeadlessComponent {}\nexport class UserMessageComponent extends HeadlessComponent {}\nexport class ExtensionSelectorComponent extends HeadlessComponent {}\nexport class ExtensionInputComponent extends HeadlessComponent {}\nexport class ExtensionEditorComponent extends HeadlessComponent {}\nexport class SettingsSelectorComponent extends HeadlessComponent {}\n\nexport class CustomEditor extends HeadlessComponent {\n private text = ''\n onSubmit?: (text: string) => void\n onChange?: (text: string) => void\n getText(): string {\n return this.text\n }\n setText(text: string): void {\n this.text = text\n this.onChange?.(text)\n }\n handleInput(data: string): void {\n if (data === '\\r' || data === '\\n') {\n this.onSubmit?.(this.text)\n return\n }\n if (data >= ' ') this.setText(this.text + data)\n }\n}\n\nexport interface ToolExecutionOptions {\n [key: string]: unknown\n}\nexport interface SettingsConfig {\n [key: string]: unknown\n}\nexport interface SettingsCallbacks {\n [key: string]: unknown\n}\nexport interface RenderDiffOptions {\n [key: string]: unknown\n}\n\nexport function renderDiff(oldText: string, newText: string, _options: RenderDiffOptions = {}): string[] {\n const removed = oldText.split('\\n').map(line => `- ${line}`)\n const added = newText.split('\\n').map(line => `+ ${line}`)\n return [...removed, ...added]\n}\n\nexport interface VisualTruncateResult {\n visualLines: string[]\n skippedCount: number\n}\n\nexport function truncateToVisualLines(\n text: string,\n maxVisualLines: number,\n width: number,\n paddingX = 0,\n): VisualTruncateResult {\n const inner = Math.max(1, width - paddingX * 2)\n const lines = text.split('\\n').map(line =>\n visibleWidth(line) > inner ? truncateToWidth(line, inner) : line)\n return {\n visualLines: lines.slice(0, Math.max(0, maxVisualLines)),\n skippedCount: Math.max(0, lines.length - maxVisualLines),\n }\n}\n\nexport function keyHint(keybinding: string, description: string): string {\n return `${keybinding} ${description}`\n}\n\nexport function keyText(keybinding: string): string {\n return keybinding\n}\n\nexport function rawKeyHint(key: string, description: string): string {\n return `${key} ${description}`\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
//#region src/compat/vendor/pi-config-shim.ts
|
|
5
|
+
function getAgentDir() {
|
|
6
|
+
if (process.env.PI_CODING_AGENT_DIR) return process.env.PI_CODING_AGENT_DIR;
|
|
7
|
+
const dshHome = process.env.DSH_HOME ?? join(homedir(), ".dsh");
|
|
8
|
+
return join(dshHome, "pi2dsh", "agent");
|
|
9
|
+
}
|
|
10
|
+
function getSessionsDir() {
|
|
11
|
+
return join(getAgentDir(), "sessions");
|
|
12
|
+
}
|
|
13
|
+
function normalizePath(input) {
|
|
14
|
+
const home = homedir();
|
|
15
|
+
if (input === "~") return home;
|
|
16
|
+
if (input.startsWith("~/")) return join(home, input.slice(2));
|
|
17
|
+
return input;
|
|
18
|
+
}
|
|
19
|
+
function resolvePath(input, baseDir = process.cwd()) {
|
|
20
|
+
const normalized = normalizePath(input);
|
|
21
|
+
const normalizedBase = normalizePath(baseDir);
|
|
22
|
+
return isAbsolute(normalized) ? resolve(normalized) : resolve(normalizedBase, normalized);
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { resolvePath as i, getSessionsDir as n, normalizePath as r, getAgentDir as t };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=pi-config-shim-CZ1wFzqM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-config-shim-CZ1wFzqM.mjs","names":["nodeResolvePath"],"sources":["../src/compat/vendor/pi-config-shim.ts"],"sourcesContent":["// @ts-nocheck — vendored Pi source; checked upstream under Pi's own tsconfig.\n// Minimal stand-ins for pi-coding-agent's config.ts and utils/paths.ts,\n// scoped to what the vendored SessionManager consumes. The agent directory is\n// redirected into DSH's home so migrated state never collides with a real Pi\n// installation on the same machine.\nimport { homedir } from 'node:os'\nimport { isAbsolute, join, resolve as nodeResolvePath } from 'node:path'\n\nexport function getAgentDir(): string {\n if (process.env.PI_CODING_AGENT_DIR) return process.env.PI_CODING_AGENT_DIR\n const dshHome = process.env.DSH_HOME ?? join(homedir(), '.dsh')\n return join(dshHome, 'pi2dsh', 'agent')\n}\n\nexport function getSessionsDir(): string {\n return join(getAgentDir(), 'sessions')\n}\n\nexport function normalizePath(input: string): string {\n const home = homedir()\n if (input === '~') return home\n if (input.startsWith('~/')) return join(home, input.slice(2))\n return input\n}\n\nexport function resolvePath(input: string, baseDir: string = process.cwd()): string {\n const normalized = normalizePath(input)\n const normalizedBase = normalizePath(baseDir)\n return isAbsolute(normalized) ? nodeResolvePath(normalized) : nodeResolvePath(normalizedBase, normalized)\n}\n"],"mappings":";;;;AAQA,SAAgB,cAAsB;CACpC,IAAI,QAAQ,IAAI,qBAAqB,OAAO,QAAQ,IAAI;CACxD,MAAM,UAAU,QAAQ,IAAI,YAAY,KAAK,QAAQ,GAAG,MAAM;CAC9D,OAAO,KAAK,SAAS,UAAU,OAAO;AACxC;AAEA,SAAgB,iBAAyB;CACvC,OAAO,KAAK,YAAY,GAAG,UAAU;AACvC;AAEA,SAAgB,cAAc,OAAuB;CACnD,MAAM,OAAO,QAAQ;CACrB,IAAI,UAAU,KAAK,OAAO;CAC1B,IAAI,MAAM,WAAW,IAAI,GAAG,OAAO,KAAK,MAAM,MAAM,MAAM,CAAC,CAAC;CAC5D,OAAO;AACT;AAEA,SAAgB,YAAY,OAAe,UAAkB,QAAQ,IAAI,GAAW;CAClF,MAAM,aAAa,cAAc,KAAK;CACtC,MAAM,iBAAiB,cAAc,OAAO;CAC5C,OAAO,WAAW,UAAU,IAAIA,QAAgB,UAAU,IAAIA,QAAgB,gBAAgB,UAAU;AAC1G"}
|