@24klynx/core 0.1.0 → 0.1.4
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/dist/index.d.mts +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.d.mts
CHANGED
|
@@ -95,7 +95,7 @@ interface Session {
|
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Serializable record of a tool being invoked.
|
|
98
|
-
* The full tool descriptor lives in @
|
|
98
|
+
* The full tool descriptor lives in @24klynx/tools; core only stores
|
|
99
99
|
* the invocation trace needed for session replay.
|
|
100
100
|
*/
|
|
101
101
|
interface ToolCall {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/types.ts","../src/errors.ts","../src/paths.ts","../src/db.ts","../src/migrate.ts"],"sourcesContent":["/**\n * Core type definitions for the Lynx agent system.\n * All other packages depend on these interfaces — keep them stable.\n */\n\n// ── Identifiers ────────────────────────────────────\n\n/** Opaque session identifier (UUID v4). */\nexport type SessionId = string & { readonly __brand: \"SessionId\" };\n\n/** Opaque message identifier (UUID v4). */\nexport type MessageId = string & { readonly __brand: \"MessageId\" };\n\n// ── Content blocks ─────────────────────────────────\n\n/**\n * Discriminated union of all content types an LLM can emit or receive.\n * The `reasoning` variant captures chain-of-thought from models like\n * DeepSeek R1 and OpenAI o1.\n */\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ReasoningBlock;\n\nexport interface TextBlock {\n type: \"text\";\n /** Plain text content emitted by the LLM. */\n text: string;\n}\n\nexport interface ToolUseBlock {\n type: \"tool_use\";\n /** Unique ID for matching tool results back to calls. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: Record<string, unknown>;\n}\n\nexport interface ToolResultBlock {\n type: \"tool_result\";\n /** Matches the `id` of the corresponding `tool_use` block. */\n toolUseId: string;\n /** Text or structured output from the tool execution. */\n content: string;\n /** Set to true when the tool execution failed. */\n isError?: boolean;\n}\n\nexport interface ReasoningBlock {\n type: \"reasoning\";\n /** Chain-of-thought text (e.g. DeepSeek R1, OpenAI o1). */\n text: string;\n}\n\n// ── Messages ───────────────────────────────────────\n\nexport interface Message {\n /** Unique identifier (UUID v4). */\n id: MessageId;\n /** Who sent this message — user, assistant, or system. */\n role: \"user\" | \"assistant\" | \"system\";\n /** Content blocks making up the message body. */\n content: ContentBlock[];\n /** Unix timestamp in milliseconds. */\n timestamp: number;\n /** Zero-based index within the session's message list. */\n turnIndex: number;\n}\n\n// ── Sessions ───────────────────────────────────────\n\n/**\n * Flexible metadata bag attached to every session.\n * Keys are strings to allow extension without breaking DB rows.\n */\nexport interface SessionMetadata {\n /** Whether the last session run was interrupted (crash / SIGKILL). */\n crashed?: boolean;\n /** Model identifier used for this session (e.g. \"deepseek-v3\"). */\n model?: string;\n /** Active permission mode when the session was last saved. */\n permissionMode?: string;\n /** Additional entries injected by plugins or migrations. */\n [key: string]: unknown;\n}\n\nexport interface Session {\n /** Unique session identifier (UUID v4). */\n id: SessionId;\n /** User-visible label shown in the session picker. */\n label: string;\n /** Absolute path to the workspace directory. */\n workspace: string;\n /** Ordered message history. */\n messages: Message[];\n /** The session this one was forked from, if any. */\n parentSessionId?: SessionId;\n /** Message count at the time of fork. */\n forkedFromMessageCount?: number;\n /** Unix ms — set on create. */\n createdAt: number;\n /** Unix ms — bumped on every mutation. */\n updatedAt: number;\n /** Flexible metadata bag (model, permission mode, crash state, etc.). */\n metadata: SessionMetadata;\n}\n\n// ── Tool invocation (minimal forward-declaration) ───\n\n/**\n * Serializable record of a tool being invoked.\n * The full tool descriptor lives in @lynx/tools; core only stores\n * the invocation trace needed for session replay.\n */\nexport interface ToolCall {\n /** Matches the `id` in `ToolUseBlock`. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments supplied by the LLM. */\n input: Record<string, unknown>;\n /** Unix ms when the tool started executing. */\n startedAt: number;\n /** Unix ms when the tool finished (undefined if still running). */\n finishedAt?: number;\n}\n\nexport interface ToolResult {\n /** Matches `ToolCall.id`. */\n toolCallId: string;\n /** Text or structured output from the tool. */\n output: string;\n /** Whether the tool execution ended in an error. */\n isError: boolean;\n /** Unix ms when execution completed. */\n finishedAt: number;\n}\n\n// ── Convenience helpers ────────────────────────────\n\n/** Create a new SessionId from a UUID string. */\nexport function asSessionId(id: string): SessionId {\n return id as SessionId;\n}\n\n/** Create a new MessageId from a UUID string. */\nexport function asMessageId(id: string): MessageId {\n return id as MessageId;\n}\n","/* oxlint-disable max-classes-per-file — error taxonomy by design */\n/**\n * Layered error system for Lynx.\n *\n * Layer 1 — LynxError subclasses: typed, machine‑actionable errors\n * each carries recoverable / retryable / userVisible / diagnosticHint.\n * Layer 2 — ErrorEnvelope: cross‑boundary wrapper with category + severity.\n * Layer 3 — Top‑level catch in lynx‑cli/entry.ts formats and routes.\n */\n\n// ── Error categories ───────────────────────────────\n\n/**\n * Which subsystem raised the error.\n * Used by error reporters and /doctor to route diagnostics.\n */\nexport type ErrorCategory =\n | \"tool\"\n | \"llm\"\n | \"session\"\n | \"plugin\"\n | \"channel\"\n | \"config\"\n | \"storage\";\n\n/**\n * Severity level for log routing and user notification.\n * \"debug\"/\"info\" are suppressed in production; \"fatal\" triggers process exit.\n */\nexport type ErrorSeverity = \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n\n// ── Layer 1: LynxError base ────────────────────────\n\n/** Configuration for constructing a LynxError. */\nexport interface LynxErrorOptions {\n /** Which subsystem raised this error. */\n category: ErrorCategory;\n /** Whether the system can recover without user intervention. */\n recoverable?: boolean;\n /** Whether retrying the same operation might succeed. */\n retryable?: boolean;\n /** Whether the message should be shown to the user. */\n userVisible?: boolean;\n /** Pointer to a /doctor check (e.g. \"storage_migration_failed\"). */\n diagnosticHint?: string;\n}\n\nexport class LynxError extends Error {\n /** Which subsystem raised this error. */\n readonly category: ErrorCategory;\n /** Whether the system can recover without user intervention. */\n readonly recoverable: boolean;\n /** Whether retrying the same operation might succeed. */\n readonly retryable: boolean;\n /** Whether the message should be shown to the user. */\n readonly userVisible: boolean;\n /** Pointer to a /doctor check (e.g. \"storage_migration_failed\"). */\n readonly diagnosticHint: string | undefined;\n\n constructor(message: string, opts: LynxErrorOptions) {\n super(message);\n this.name = \"LynxError\";\n this.category = opts.category;\n this.recoverable = opts.recoverable ?? false;\n this.retryable = opts.retryable ?? false;\n this.userVisible = opts.userVisible ?? true;\n this.diagnosticHint = opts.diagnosticHint;\n }\n}\n\n// ── Layer 1: Subclasses ────────────────────────────\n\nexport class ToolError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"tool\", recoverable: false, retryable: false, ...opts });\n this.name = \"ToolError\";\n }\n}\n\nexport class ToolTimeoutError extends ToolError {\n constructor(message = \"Tool execution timed out (60s)\") {\n super(message, { userVisible: false, diagnosticHint: \"tool_timeout\" });\n this.name = \"ToolTimeoutError\";\n }\n}\n\nexport class ToolAbortedError extends ToolError {\n constructor(message = \"Tool execution was cancelled\") {\n super(message, { userVisible: true });\n this.name = \"ToolAbortedError\";\n }\n}\n\nexport class ToolPermissionError extends ToolError {\n constructor(message = \"Permission denied for tool execution\") {\n super(message, { userVisible: true });\n this.name = \"ToolPermissionError\";\n }\n}\n\nexport class LlmError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"llm\", recoverable: true, retryable: true, ...opts });\n this.name = \"LlmError\";\n }\n}\n\nexport class LlmRateLimitError extends LlmError {\n /** HTTP status code (429 for rate limit, 529 for overload). */\n status: number;\n\n constructor(message = \"LLM rate limited (429 / 529)\", status = 429) {\n super(message, { diagnosticHint: \"llm_rate_limit\" });\n this.name = \"LlmRateLimitError\";\n this.status = status;\n }\n}\n\nexport class LlmAuthError extends LlmError {\n constructor(message = \"LLM authentication failed (401 / 403)\") {\n super(message, { recoverable: true, retryable: false, diagnosticHint: \"llm_auth\" });\n this.name = \"LlmAuthError\";\n }\n}\n\nexport class LlmContextOverflowError extends LlmError {\n constructor(message = \"Prompt exceeds model context window\") {\n super(message, { recoverable: true, retryable: true, diagnosticHint: \"llm_context_overflow\" });\n this.name = \"LlmContextOverflowError\";\n }\n}\n\nexport class SessionError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"session\", recoverable: false, retryable: false, ...opts });\n this.name = \"SessionError\";\n }\n}\n\nexport class SessionNotFoundError extends SessionError {\n constructor(sessionId: string) {\n super(`Session not found: ${sessionId}`, { userVisible: true });\n this.name = \"SessionNotFoundError\";\n }\n}\n\nexport class SessionLockedError extends SessionError {\n constructor(sessionId: string) {\n super(`Session locked (concurrent write): ${sessionId}`, {\n recoverable: true,\n retryable: true,\n });\n this.name = \"SessionLockedError\";\n }\n}\n\nexport class AgentError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"llm\", recoverable: true, retryable: false, ...opts });\n this.name = \"AgentError\";\n }\n}\n\nexport class PluginError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"plugin\", recoverable: true, retryable: false, ...opts });\n this.name = \"PluginError\";\n }\n}\n\nexport class PluginLoadError extends PluginError {\n constructor(pluginName: string, cause?: unknown) {\n super(`Plugin \"${pluginName}\" failed to load: ${String(cause)}`, { userVisible: true });\n this.name = \"PluginLoadError\";\n }\n}\n\nexport class PluginHookError extends PluginError {\n constructor(hookName: string, cause?: unknown) {\n super(`Hook \"${hookName}\" threw: ${String(cause)}`, { userVisible: false });\n this.name = \"PluginHookError\";\n }\n}\n\nexport class ChannelError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"channel\", recoverable: true, retryable: true, ...opts });\n this.name = \"ChannelError\";\n }\n}\n\nexport class ConfigError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"config\", recoverable: false, retryable: false, ...opts });\n this.name = \"ConfigError\";\n }\n}\n\nexport class StorageError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"storage\", recoverable: false, retryable: false, ...opts });\n this.name = \"StorageError\";\n }\n}\n\nexport class StorageCorruptedError extends StorageError {\n constructor(message = \"Database file is corrupted\") {\n super(message, { diagnosticHint: \"storage_corrupted\" });\n this.name = \"StorageCorruptedError\";\n }\n}\n\nexport class StorageFullError extends StorageError {\n constructor(message = \"Disk full — cannot write to storage\") {\n super(message, { userVisible: true, diagnosticHint: \"storage_full\" });\n this.name = \"StorageFullError\";\n }\n}\n\n// ── Layer 2: ErrorEnvelope ─────────────────────────\n\nexport interface ErrorEnvelope {\n category: ErrorCategory;\n severity: ErrorSeverity;\n recoverable: boolean;\n retryable: boolean;\n /** Machine‑readable error code, e.g. \"LLM_RATE_LIMIT\". */\n code: string;\n /** Human‑readable message. */\n message: string;\n /** Chained cause, if this error wraps another. */\n cause?: ErrorEnvelope;\n /** Opaque trace id for correlating logs with user reports. */\n traceId?: string;\n /** Current operation span (agent_loop / tool_exec / model_call). */\n spanId?: string;\n /** Session this error occurred in, if applicable. */\n sessionId?: string;\n /** Unix ms when the error was captured. */\n wallTime?: number;\n}\n\n/** Lift any Error into a safe ErrorEnvelope for cross‑boundary transport. */\nexport function toErrorEnvelope(err: unknown, overrides?: Partial<ErrorEnvelope>): ErrorEnvelope {\n if (err instanceof LynxError) {\n return {\n category: err.category,\n severity: \"error\",\n recoverable: err.recoverable,\n retryable: err.retryable,\n code: err.name.toUpperCase(),\n message: err.message,\n wallTime: Date.now(),\n ...overrides,\n };\n }\n\n if (err instanceof Error) {\n return {\n category: \"storage\",\n severity: \"error\",\n recoverable: false,\n retryable: false,\n code: \"UNKNOWN\",\n message: err.message,\n wallTime: Date.now(),\n ...overrides,\n };\n }\n\n return {\n category: \"storage\",\n severity: \"fatal\",\n recoverable: false,\n retryable: false,\n code: \"UNKNOWN\",\n message: String(err),\n wallTime: Date.now(),\n ...overrides,\n };\n}\n\n// ── Development‑only marker ────────────────────────\n\n/**\n * Throw this when a function body is intentionally not implemented yet.\n * CI detects remaining `NotImplementedError` throws and fails the Phase gate.\n */\nexport class NotImplementedError extends Error {\n constructor(feature: string) {\n super(`Not implemented: ${feature}`);\n this.name = \"NotImplementedError\";\n }\n}\n","/**\n * Centralised path resolution for all Lynx data directories.\n *\n * Default root is `~/.lynx` (or `%USERPROFILE%/.lynx` on Windows).\n * Every sub‑directory can be overridden individually via environment variables\n * so that state, logs, config, and skills can live on separate volumes.\n */\n\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n// ── Helpers ────────────────────────────────────────\n\n/**\n * Normalise path separators to forward slashes.\n * Node.js on Windows accepts both `C:\\Users` and `C:/Users`,\n * but we want consistent POSIX‑style paths across the codebase.\n */\nfunction posix(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/** Default data root. */\nconst DEFAULT_HOME = posix(join(homedir(), \".lynx\"));\n\n// ── Public API ──────────────────────────────────────\n\nexport interface LynxPaths {\n /** Root data directory (~/.lynx or $LYNX_HOME). */\n home: string;\n /** Main JSON configuration file. */\n configFile: string;\n /** User preference file (theme, keybinds). */\n settingsFile: string;\n /** TUI‑specific preferences (survive across projects). */\n tuiFile: string;\n /** SQLite state database path. */\n stateDb: string;\n /** Directory holding per‑session JSON files. */\n sessionsDir: string;\n /** Log output directory. */\n logDir: string;\n /** Security audit log (JSONL). */\n auditLog: string;\n /** Capacity memory records. */\n memoryDir: string;\n /** Workspace snapshots (git side‑repo). */\n snapshotsDir: string;\n /** User‑level skills. */\n skillsDir: string;\n /** Shell completion cache. */\n completionsDir: string;\n /** Input history file. */\n composerHistory: string;\n /** Ctrl+S stash file. */\n composerStash: string;\n /** Update concurrency lock file. */\n updateLock: string;\n}\n\n/**\n * Resolve every data path from environment variables.\n * Called once at startup; result is immutable for the lifetime of the process.\n */\nexport function resolvePaths(env: NodeJS.ProcessEnv = process.env): LynxPaths {\n const home = env.LYNX_HOME ?? DEFAULT_HOME;\n const stateDir = env.LYNX_STATE_DIR ?? posix(join(home, \"sessions\"));\n const logDir = env.LYNX_LOG_DIR ?? posix(join(home, \"logs\"));\n\n return {\n home,\n configFile: env.LYNX_CONFIG_PATH ?? posix(join(home, \"config.json\")),\n settingsFile: posix(join(home, \"settings.json\")),\n tuiFile: posix(join(home, \"tui.json\")),\n stateDb: posix(join(home, \"state.db\")),\n sessionsDir: stateDir,\n logDir,\n auditLog: posix(join(home, \"audit.log\")),\n memoryDir: posix(join(home, \"memory\")),\n snapshotsDir: posix(join(home, \"snapshots\")),\n skillsDir: posix(join(home, \"skills\")),\n completionsDir: posix(join(home, \"completions\")),\n composerHistory: posix(join(home, \"composer_history.txt\")),\n composerStash: posix(join(home, \"composer_stash.jsonl\")),\n updateLock: posix(join(home, \".update.lock\")),\n };\n}\n","/**\n * Single entry‑point for opening the Lynx SQLite database.\n *\n * Every WAL‑mode pragma is set here so that all consumers (SessionManager,\n * PluginRegistry, TaskManager) share the same connection settings without\n * repeating the configuration.\n */\n\nimport Database from \"better-sqlite3\";\nimport { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n// ── Constants ──────────────────────────────────────\n\n/** Wait up to 5 seconds when a write lock is contended. */\nconst BUSY_TIMEOUT_MS = 5_000;\n\n/** Maximum WAL file size before auto‑checkpoint (64 MiB). */\nconst JOURNAL_SIZE_LIMIT_BYTES = 67_108_864;\n\n/** Page cache size in KB. Negative value = KB, so -8000 = 8 MiB. */\nconst CACHE_SIZE_KB = -8_000;\n\n/** Memory‑mapped I/O window (256 MiB). */\nconst MMAP_SIZE_BYTES = 268_435_456;\n\n/** Trigger passive checkpoint every N write operations. */\nconst WAL_AUTOCHECKPOINT = 1000;\n\n// ── Configuration ──────────────────────────────────\n\nexport interface DbConfig {\n /** Absolute path to the .db file. */\n dbPath: string;\n /** If true (default), journal_mode = WAL. */\n walMode?: boolean;\n}\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * Open (or create) the Lynx state database with WAL mode enabled.\n * Call this once per process in the bootstrap phase.\n */\nexport function openDatabase(config: DbConfig): Database.Database {\n // Ensure parent directory exists with restricted permissions\n const dir = dirname(config.dbPath);\n mkdirSync(dir, { mode: 0o700, recursive: true });\n\n const db = new Database(config.dbPath);\n\n // Enable WAL by default — critical for concurrent read/write workloads\n // (e.g. draft auto‑save doesn't block the TUI session list)\n if (config.walMode !== false) {\n db.pragma(\"journal_mode = WAL\");\n }\n\n db.pragma(\"synchronous = NORMAL\");\n db.pragma(\"foreign_keys = ON\");\n db.pragma(`busy_timeout = ${BUSY_TIMEOUT_MS}`);\n db.pragma(`journal_size_limit = ${JOURNAL_SIZE_LIMIT_BYTES}`);\n db.pragma(`cache_size = ${CACHE_SIZE_KB}`);\n db.pragma(`mmap_size = ${MMAP_SIZE_BYTES}`);\n db.pragma(`wal_autocheckpoint = ${WAL_AUTOCHECKPOINT}`);\n\n return db;\n}\n","/**\n * Forward‑only schema migration system for Lynx's SQLite database.\n *\n * Each migration runs inside its own transaction. The `user_version` pragma\n * tracks which version the database is at. If the on‑disk version is newer\n * than the code expects, we throw — the user must upgrade Lynx.\n */\n\nimport type Database from \"better-sqlite3\";\nimport { StorageError } from \"./errors.js\";\n\n// ── Types ──────────────────────────────────────────\n\nexport interface Migration {\n /** Monotonically‑increasing schema version. */\n version: number;\n /** Human‑readable summary of what this migration does. */\n description: string;\n /** SQL statements executed inside a transaction. */\n sql: string;\n /** Optional rollback SQL. If omitted, a failed migration leaves the DB dirty. */\n rollback?: string;\n}\n\n// ── Migration registry ─────────────────────────────\n\nexport const MIGRATIONS: Migration[] = [\n {\n version: 1,\n description: \"Initial schema: sessions\",\n sql: `\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n label TEXT NOT NULL,\n workspace TEXT NOT NULL,\n parent_id TEXT,\n forked_from_message_count INTEGER,\n message_count INTEGER DEFAULT 0,\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n FOREIGN KEY (parent_id) REFERENCES sessions(id) ON DELETE SET NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_sessions_updated_at\n ON sessions(updated_at DESC);\n\n CREATE INDEX IF NOT EXISTS idx_sessions_parent_id\n ON sessions(parent_id);\n `,\n },\n {\n version: 2,\n description: \"Draft auto‑save table\",\n sql: `\n CREATE TABLE IF NOT EXISTS drafts (\n session_id TEXT PRIMARY KEY,\n messages_json TEXT NOT NULL,\n updated_at INTEGER NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n `,\n rollback: \"DROP TABLE IF EXISTS drafts;\",\n },\n {\n version: 3,\n description: \"Messages persistence table\",\n sql: `\n CREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n role TEXT NOT NULL CHECK(role IN ('user', 'assistant', 'system')),\n content_json TEXT NOT NULL,\n turn_index INTEGER NOT NULL DEFAULT 0,\n timestamp INTEGER NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n\n CREATE INDEX IF NOT EXISTS idx_messages_session_id\n ON messages(session_id);\n\n CREATE INDEX IF NOT EXISTS idx_messages_session_turn\n ON messages(session_id, turn_index);\n `,\n rollback: \"DROP TABLE IF EXISTS messages;\",\n },\n];\n\n/** The schema version this build of Lynx expects. */\nexport const EXPECTED_VERSION: number = MIGRATIONS[MIGRATIONS.length - 1].version;\n\n// ── Migration runner ───────────────────────────────\n\n/**\n * Apply any pending migrations to bring `db` up to EXPECTED_VERSION.\n * Safe to call on every startup — no‑op if already current.\n */\nexport function migrate(db: Database.Database): void {\n runMigrations(db, MIGRATIONS, EXPECTED_VERSION);\n}\n\n/**\n * Run migrations with an explicit list and target version.\n * Exported for testability — production code should use `migrate()`.\n */\nexport function runMigrations(\n db: Database.Database,\n migrations: Migration[],\n expectedVersion: number,\n): void {\n const currentVersion = db.pragma(\"user_version\", { simple: true }) as number;\n\n if (currentVersion > expectedVersion) {\n throw new StorageError(\n `Database schema v${currentVersion} is newer than this Lynx build expects (v${expectedVersion}). ` +\n \"Please upgrade Lynx to the latest version.\",\n { recoverable: false, retryable: false, userVisible: true },\n );\n }\n\n if (currentVersion === expectedVersion) {\n return;\n }\n\n const pending = migrations.filter((m) => m.version > currentVersion);\n\n for (const migration of pending) {\n const apply = db.transaction(() => {\n db.exec(migration.sql);\n db.pragma(`user_version = ${migration.version}`);\n });\n\n try {\n apply();\n } catch (err) {\n // Best‑effort rollback\n if (migration.rollback) {\n try {\n db.exec(migration.rollback);\n } catch {\n // Rollback itself failed — DB may be in an inconsistent state.\n // The user should restore from the pre‑migration backup.\n }\n }\n throw new StorageError(\n `Migration v${migration.version} (${migration.description}) failed: ${(err as Error).message}`,\n {\n recoverable: false,\n retryable: false,\n userVisible: true,\n diagnosticHint: \"storage_migration_failed\",\n },\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/types.ts","../src/errors.ts","../src/paths.ts","../src/db.ts","../src/migrate.ts"],"sourcesContent":["/**\n * Core type definitions for the Lynx agent system.\n * All other packages depend on these interfaces — keep them stable.\n */\n\n// ── Identifiers ────────────────────────────────────\n\n/** Opaque session identifier (UUID v4). */\nexport type SessionId = string & { readonly __brand: \"SessionId\" };\n\n/** Opaque message identifier (UUID v4). */\nexport type MessageId = string & { readonly __brand: \"MessageId\" };\n\n// ── Content blocks ─────────────────────────────────\n\n/**\n * Discriminated union of all content types an LLM can emit or receive.\n * The `reasoning` variant captures chain-of-thought from models like\n * DeepSeek R1 and OpenAI o1.\n */\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ReasoningBlock;\n\nexport interface TextBlock {\n type: \"text\";\n /** Plain text content emitted by the LLM. */\n text: string;\n}\n\nexport interface ToolUseBlock {\n type: \"tool_use\";\n /** Unique ID for matching tool results back to calls. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: Record<string, unknown>;\n}\n\nexport interface ToolResultBlock {\n type: \"tool_result\";\n /** Matches the `id` of the corresponding `tool_use` block. */\n toolUseId: string;\n /** Text or structured output from the tool execution. */\n content: string;\n /** Set to true when the tool execution failed. */\n isError?: boolean;\n}\n\nexport interface ReasoningBlock {\n type: \"reasoning\";\n /** Chain-of-thought text (e.g. DeepSeek R1, OpenAI o1). */\n text: string;\n}\n\n// ── Messages ───────────────────────────────────────\n\nexport interface Message {\n /** Unique identifier (UUID v4). */\n id: MessageId;\n /** Who sent this message — user, assistant, or system. */\n role: \"user\" | \"assistant\" | \"system\";\n /** Content blocks making up the message body. */\n content: ContentBlock[];\n /** Unix timestamp in milliseconds. */\n timestamp: number;\n /** Zero-based index within the session's message list. */\n turnIndex: number;\n}\n\n// ── Sessions ───────────────────────────────────────\n\n/**\n * Flexible metadata bag attached to every session.\n * Keys are strings to allow extension without breaking DB rows.\n */\nexport interface SessionMetadata {\n /** Whether the last session run was interrupted (crash / SIGKILL). */\n crashed?: boolean;\n /** Model identifier used for this session (e.g. \"deepseek-v3\"). */\n model?: string;\n /** Active permission mode when the session was last saved. */\n permissionMode?: string;\n /** Additional entries injected by plugins or migrations. */\n [key: string]: unknown;\n}\n\nexport interface Session {\n /** Unique session identifier (UUID v4). */\n id: SessionId;\n /** User-visible label shown in the session picker. */\n label: string;\n /** Absolute path to the workspace directory. */\n workspace: string;\n /** Ordered message history. */\n messages: Message[];\n /** The session this one was forked from, if any. */\n parentSessionId?: SessionId;\n /** Message count at the time of fork. */\n forkedFromMessageCount?: number;\n /** Unix ms — set on create. */\n createdAt: number;\n /** Unix ms — bumped on every mutation. */\n updatedAt: number;\n /** Flexible metadata bag (model, permission mode, crash state, etc.). */\n metadata: SessionMetadata;\n}\n\n// ── Tool invocation (minimal forward-declaration) ───\n\n/**\n * Serializable record of a tool being invoked.\n * The full tool descriptor lives in @24klynx/tools; core only stores\n * the invocation trace needed for session replay.\n */\nexport interface ToolCall {\n /** Matches the `id` in `ToolUseBlock`. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments supplied by the LLM. */\n input: Record<string, unknown>;\n /** Unix ms when the tool started executing. */\n startedAt: number;\n /** Unix ms when the tool finished (undefined if still running). */\n finishedAt?: number;\n}\n\nexport interface ToolResult {\n /** Matches `ToolCall.id`. */\n toolCallId: string;\n /** Text or structured output from the tool. */\n output: string;\n /** Whether the tool execution ended in an error. */\n isError: boolean;\n /** Unix ms when execution completed. */\n finishedAt: number;\n}\n\n// ── Convenience helpers ────────────────────────────\n\n/** Create a new SessionId from a UUID string. */\nexport function asSessionId(id: string): SessionId {\n return id as SessionId;\n}\n\n/** Create a new MessageId from a UUID string. */\nexport function asMessageId(id: string): MessageId {\n return id as MessageId;\n}\n","/* oxlint-disable max-classes-per-file — error taxonomy by design */\n/**\n * Layered error system for Lynx.\n *\n * Layer 1 — LynxError subclasses: typed, machine‑actionable errors\n * each carries recoverable / retryable / userVisible / diagnosticHint.\n * Layer 2 — ErrorEnvelope: cross‑boundary wrapper with category + severity.\n * Layer 3 — Top‑level catch in lynx‑cli/entry.ts formats and routes.\n */\n\n// ── Error categories ───────────────────────────────\n\n/**\n * Which subsystem raised the error.\n * Used by error reporters and /doctor to route diagnostics.\n */\nexport type ErrorCategory =\n | \"tool\"\n | \"llm\"\n | \"session\"\n | \"plugin\"\n | \"channel\"\n | \"config\"\n | \"storage\";\n\n/**\n * Severity level for log routing and user notification.\n * \"debug\"/\"info\" are suppressed in production; \"fatal\" triggers process exit.\n */\nexport type ErrorSeverity = \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n\n// ── Layer 1: LynxError base ────────────────────────\n\n/** Configuration for constructing a LynxError. */\nexport interface LynxErrorOptions {\n /** Which subsystem raised this error. */\n category: ErrorCategory;\n /** Whether the system can recover without user intervention. */\n recoverable?: boolean;\n /** Whether retrying the same operation might succeed. */\n retryable?: boolean;\n /** Whether the message should be shown to the user. */\n userVisible?: boolean;\n /** Pointer to a /doctor check (e.g. \"storage_migration_failed\"). */\n diagnosticHint?: string;\n}\n\nexport class LynxError extends Error {\n /** Which subsystem raised this error. */\n readonly category: ErrorCategory;\n /** Whether the system can recover without user intervention. */\n readonly recoverable: boolean;\n /** Whether retrying the same operation might succeed. */\n readonly retryable: boolean;\n /** Whether the message should be shown to the user. */\n readonly userVisible: boolean;\n /** Pointer to a /doctor check (e.g. \"storage_migration_failed\"). */\n readonly diagnosticHint: string | undefined;\n\n constructor(message: string, opts: LynxErrorOptions) {\n super(message);\n this.name = \"LynxError\";\n this.category = opts.category;\n this.recoverable = opts.recoverable ?? false;\n this.retryable = opts.retryable ?? false;\n this.userVisible = opts.userVisible ?? true;\n this.diagnosticHint = opts.diagnosticHint;\n }\n}\n\n// ── Layer 1: Subclasses ────────────────────────────\n\nexport class ToolError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"tool\", recoverable: false, retryable: false, ...opts });\n this.name = \"ToolError\";\n }\n}\n\nexport class ToolTimeoutError extends ToolError {\n constructor(message = \"Tool execution timed out (60s)\") {\n super(message, { userVisible: false, diagnosticHint: \"tool_timeout\" });\n this.name = \"ToolTimeoutError\";\n }\n}\n\nexport class ToolAbortedError extends ToolError {\n constructor(message = \"Tool execution was cancelled\") {\n super(message, { userVisible: true });\n this.name = \"ToolAbortedError\";\n }\n}\n\nexport class ToolPermissionError extends ToolError {\n constructor(message = \"Permission denied for tool execution\") {\n super(message, { userVisible: true });\n this.name = \"ToolPermissionError\";\n }\n}\n\nexport class LlmError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"llm\", recoverable: true, retryable: true, ...opts });\n this.name = \"LlmError\";\n }\n}\n\nexport class LlmRateLimitError extends LlmError {\n /** HTTP status code (429 for rate limit, 529 for overload). */\n status: number;\n\n constructor(message = \"LLM rate limited (429 / 529)\", status = 429) {\n super(message, { diagnosticHint: \"llm_rate_limit\" });\n this.name = \"LlmRateLimitError\";\n this.status = status;\n }\n}\n\nexport class LlmAuthError extends LlmError {\n constructor(message = \"LLM authentication failed (401 / 403)\") {\n super(message, { recoverable: true, retryable: false, diagnosticHint: \"llm_auth\" });\n this.name = \"LlmAuthError\";\n }\n}\n\nexport class LlmContextOverflowError extends LlmError {\n constructor(message = \"Prompt exceeds model context window\") {\n super(message, { recoverable: true, retryable: true, diagnosticHint: \"llm_context_overflow\" });\n this.name = \"LlmContextOverflowError\";\n }\n}\n\nexport class SessionError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"session\", recoverable: false, retryable: false, ...opts });\n this.name = \"SessionError\";\n }\n}\n\nexport class SessionNotFoundError extends SessionError {\n constructor(sessionId: string) {\n super(`Session not found: ${sessionId}`, { userVisible: true });\n this.name = \"SessionNotFoundError\";\n }\n}\n\nexport class SessionLockedError extends SessionError {\n constructor(sessionId: string) {\n super(`Session locked (concurrent write): ${sessionId}`, {\n recoverable: true,\n retryable: true,\n });\n this.name = \"SessionLockedError\";\n }\n}\n\nexport class AgentError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"llm\", recoverable: true, retryable: false, ...opts });\n this.name = \"AgentError\";\n }\n}\n\nexport class PluginError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"plugin\", recoverable: true, retryable: false, ...opts });\n this.name = \"PluginError\";\n }\n}\n\nexport class PluginLoadError extends PluginError {\n constructor(pluginName: string, cause?: unknown) {\n super(`Plugin \"${pluginName}\" failed to load: ${String(cause)}`, { userVisible: true });\n this.name = \"PluginLoadError\";\n }\n}\n\nexport class PluginHookError extends PluginError {\n constructor(hookName: string, cause?: unknown) {\n super(`Hook \"${hookName}\" threw: ${String(cause)}`, { userVisible: false });\n this.name = \"PluginHookError\";\n }\n}\n\nexport class ChannelError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"channel\", recoverable: true, retryable: true, ...opts });\n this.name = \"ChannelError\";\n }\n}\n\nexport class ConfigError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"config\", recoverable: false, retryable: false, ...opts });\n this.name = \"ConfigError\";\n }\n}\n\nexport class StorageError extends LynxError {\n constructor(message: string, opts?: Partial<LynxErrorOptions>) {\n super(message, { category: \"storage\", recoverable: false, retryable: false, ...opts });\n this.name = \"StorageError\";\n }\n}\n\nexport class StorageCorruptedError extends StorageError {\n constructor(message = \"Database file is corrupted\") {\n super(message, { diagnosticHint: \"storage_corrupted\" });\n this.name = \"StorageCorruptedError\";\n }\n}\n\nexport class StorageFullError extends StorageError {\n constructor(message = \"Disk full — cannot write to storage\") {\n super(message, { userVisible: true, diagnosticHint: \"storage_full\" });\n this.name = \"StorageFullError\";\n }\n}\n\n// ── Layer 2: ErrorEnvelope ─────────────────────────\n\nexport interface ErrorEnvelope {\n category: ErrorCategory;\n severity: ErrorSeverity;\n recoverable: boolean;\n retryable: boolean;\n /** Machine‑readable error code, e.g. \"LLM_RATE_LIMIT\". */\n code: string;\n /** Human‑readable message. */\n message: string;\n /** Chained cause, if this error wraps another. */\n cause?: ErrorEnvelope;\n /** Opaque trace id for correlating logs with user reports. */\n traceId?: string;\n /** Current operation span (agent_loop / tool_exec / model_call). */\n spanId?: string;\n /** Session this error occurred in, if applicable. */\n sessionId?: string;\n /** Unix ms when the error was captured. */\n wallTime?: number;\n}\n\n/** Lift any Error into a safe ErrorEnvelope for cross‑boundary transport. */\nexport function toErrorEnvelope(err: unknown, overrides?: Partial<ErrorEnvelope>): ErrorEnvelope {\n if (err instanceof LynxError) {\n return {\n category: err.category,\n severity: \"error\",\n recoverable: err.recoverable,\n retryable: err.retryable,\n code: err.name.toUpperCase(),\n message: err.message,\n wallTime: Date.now(),\n ...overrides,\n };\n }\n\n if (err instanceof Error) {\n return {\n category: \"storage\",\n severity: \"error\",\n recoverable: false,\n retryable: false,\n code: \"UNKNOWN\",\n message: err.message,\n wallTime: Date.now(),\n ...overrides,\n };\n }\n\n return {\n category: \"storage\",\n severity: \"fatal\",\n recoverable: false,\n retryable: false,\n code: \"UNKNOWN\",\n message: String(err),\n wallTime: Date.now(),\n ...overrides,\n };\n}\n\n// ── Development‑only marker ────────────────────────\n\n/**\n * Throw this when a function body is intentionally not implemented yet.\n * CI detects remaining `NotImplementedError` throws and fails the Phase gate.\n */\nexport class NotImplementedError extends Error {\n constructor(feature: string) {\n super(`Not implemented: ${feature}`);\n this.name = \"NotImplementedError\";\n }\n}\n","/**\n * Centralised path resolution for all Lynx data directories.\n *\n * Default root is `~/.lynx` (or `%USERPROFILE%/.lynx` on Windows).\n * Every sub‑directory can be overridden individually via environment variables\n * so that state, logs, config, and skills can live on separate volumes.\n */\n\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n// ── Helpers ────────────────────────────────────────\n\n/**\n * Normalise path separators to forward slashes.\n * Node.js on Windows accepts both `C:\\Users` and `C:/Users`,\n * but we want consistent POSIX‑style paths across the codebase.\n */\nfunction posix(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/** Default data root. */\nconst DEFAULT_HOME = posix(join(homedir(), \".lynx\"));\n\n// ── Public API ──────────────────────────────────────\n\nexport interface LynxPaths {\n /** Root data directory (~/.lynx or $LYNX_HOME). */\n home: string;\n /** Main JSON configuration file. */\n configFile: string;\n /** User preference file (theme, keybinds). */\n settingsFile: string;\n /** TUI‑specific preferences (survive across projects). */\n tuiFile: string;\n /** SQLite state database path. */\n stateDb: string;\n /** Directory holding per‑session JSON files. */\n sessionsDir: string;\n /** Log output directory. */\n logDir: string;\n /** Security audit log (JSONL). */\n auditLog: string;\n /** Capacity memory records. */\n memoryDir: string;\n /** Workspace snapshots (git side‑repo). */\n snapshotsDir: string;\n /** User‑level skills. */\n skillsDir: string;\n /** Shell completion cache. */\n completionsDir: string;\n /** Input history file. */\n composerHistory: string;\n /** Ctrl+S stash file. */\n composerStash: string;\n /** Update concurrency lock file. */\n updateLock: string;\n}\n\n/**\n * Resolve every data path from environment variables.\n * Called once at startup; result is immutable for the lifetime of the process.\n */\nexport function resolvePaths(env: NodeJS.ProcessEnv = process.env): LynxPaths {\n const home = env.LYNX_HOME ?? DEFAULT_HOME;\n const stateDir = env.LYNX_STATE_DIR ?? posix(join(home, \"sessions\"));\n const logDir = env.LYNX_LOG_DIR ?? posix(join(home, \"logs\"));\n\n return {\n home,\n configFile: env.LYNX_CONFIG_PATH ?? posix(join(home, \"config.json\")),\n settingsFile: posix(join(home, \"settings.json\")),\n tuiFile: posix(join(home, \"tui.json\")),\n stateDb: posix(join(home, \"state.db\")),\n sessionsDir: stateDir,\n logDir,\n auditLog: posix(join(home, \"audit.log\")),\n memoryDir: posix(join(home, \"memory\")),\n snapshotsDir: posix(join(home, \"snapshots\")),\n skillsDir: posix(join(home, \"skills\")),\n completionsDir: posix(join(home, \"completions\")),\n composerHistory: posix(join(home, \"composer_history.txt\")),\n composerStash: posix(join(home, \"composer_stash.jsonl\")),\n updateLock: posix(join(home, \".update.lock\")),\n };\n}\n","/**\n * Single entry‑point for opening the Lynx SQLite database.\n *\n * Every WAL‑mode pragma is set here so that all consumers (SessionManager,\n * PluginRegistry, TaskManager) share the same connection settings without\n * repeating the configuration.\n */\n\nimport Database from \"better-sqlite3\";\nimport { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n// ── Constants ──────────────────────────────────────\n\n/** Wait up to 5 seconds when a write lock is contended. */\nconst BUSY_TIMEOUT_MS = 5_000;\n\n/** Maximum WAL file size before auto‑checkpoint (64 MiB). */\nconst JOURNAL_SIZE_LIMIT_BYTES = 67_108_864;\n\n/** Page cache size in KB. Negative value = KB, so -8000 = 8 MiB. */\nconst CACHE_SIZE_KB = -8_000;\n\n/** Memory‑mapped I/O window (256 MiB). */\nconst MMAP_SIZE_BYTES = 268_435_456;\n\n/** Trigger passive checkpoint every N write operations. */\nconst WAL_AUTOCHECKPOINT = 1000;\n\n// ── Configuration ──────────────────────────────────\n\nexport interface DbConfig {\n /** Absolute path to the .db file. */\n dbPath: string;\n /** If true (default), journal_mode = WAL. */\n walMode?: boolean;\n}\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * Open (or create) the Lynx state database with WAL mode enabled.\n * Call this once per process in the bootstrap phase.\n */\nexport function openDatabase(config: DbConfig): Database.Database {\n // Ensure parent directory exists with restricted permissions\n const dir = dirname(config.dbPath);\n mkdirSync(dir, { mode: 0o700, recursive: true });\n\n const db = new Database(config.dbPath);\n\n // Enable WAL by default — critical for concurrent read/write workloads\n // (e.g. draft auto‑save doesn't block the TUI session list)\n if (config.walMode !== false) {\n db.pragma(\"journal_mode = WAL\");\n }\n\n db.pragma(\"synchronous = NORMAL\");\n db.pragma(\"foreign_keys = ON\");\n db.pragma(`busy_timeout = ${BUSY_TIMEOUT_MS}`);\n db.pragma(`journal_size_limit = ${JOURNAL_SIZE_LIMIT_BYTES}`);\n db.pragma(`cache_size = ${CACHE_SIZE_KB}`);\n db.pragma(`mmap_size = ${MMAP_SIZE_BYTES}`);\n db.pragma(`wal_autocheckpoint = ${WAL_AUTOCHECKPOINT}`);\n\n return db;\n}\n","/**\n * Forward‑only schema migration system for Lynx's SQLite database.\n *\n * Each migration runs inside its own transaction. The `user_version` pragma\n * tracks which version the database is at. If the on‑disk version is newer\n * than the code expects, we throw — the user must upgrade Lynx.\n */\n\nimport type Database from \"better-sqlite3\";\nimport { StorageError } from \"./errors.js\";\n\n// ── Types ──────────────────────────────────────────\n\nexport interface Migration {\n /** Monotonically‑increasing schema version. */\n version: number;\n /** Human‑readable summary of what this migration does. */\n description: string;\n /** SQL statements executed inside a transaction. */\n sql: string;\n /** Optional rollback SQL. If omitted, a failed migration leaves the DB dirty. */\n rollback?: string;\n}\n\n// ── Migration registry ─────────────────────────────\n\nexport const MIGRATIONS: Migration[] = [\n {\n version: 1,\n description: \"Initial schema: sessions\",\n sql: `\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n label TEXT NOT NULL,\n workspace TEXT NOT NULL,\n parent_id TEXT,\n forked_from_message_count INTEGER,\n message_count INTEGER DEFAULT 0,\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n FOREIGN KEY (parent_id) REFERENCES sessions(id) ON DELETE SET NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_sessions_updated_at\n ON sessions(updated_at DESC);\n\n CREATE INDEX IF NOT EXISTS idx_sessions_parent_id\n ON sessions(parent_id);\n `,\n },\n {\n version: 2,\n description: \"Draft auto‑save table\",\n sql: `\n CREATE TABLE IF NOT EXISTS drafts (\n session_id TEXT PRIMARY KEY,\n messages_json TEXT NOT NULL,\n updated_at INTEGER NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n `,\n rollback: \"DROP TABLE IF EXISTS drafts;\",\n },\n {\n version: 3,\n description: \"Messages persistence table\",\n sql: `\n CREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n role TEXT NOT NULL CHECK(role IN ('user', 'assistant', 'system')),\n content_json TEXT NOT NULL,\n turn_index INTEGER NOT NULL DEFAULT 0,\n timestamp INTEGER NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n\n CREATE INDEX IF NOT EXISTS idx_messages_session_id\n ON messages(session_id);\n\n CREATE INDEX IF NOT EXISTS idx_messages_session_turn\n ON messages(session_id, turn_index);\n `,\n rollback: \"DROP TABLE IF EXISTS messages;\",\n },\n];\n\n/** The schema version this build of Lynx expects. */\nexport const EXPECTED_VERSION: number = MIGRATIONS[MIGRATIONS.length - 1].version;\n\n// ── Migration runner ───────────────────────────────\n\n/**\n * Apply any pending migrations to bring `db` up to EXPECTED_VERSION.\n * Safe to call on every startup — no‑op if already current.\n */\nexport function migrate(db: Database.Database): void {\n runMigrations(db, MIGRATIONS, EXPECTED_VERSION);\n}\n\n/**\n * Run migrations with an explicit list and target version.\n * Exported for testability — production code should use `migrate()`.\n */\nexport function runMigrations(\n db: Database.Database,\n migrations: Migration[],\n expectedVersion: number,\n): void {\n const currentVersion = db.pragma(\"user_version\", { simple: true }) as number;\n\n if (currentVersion > expectedVersion) {\n throw new StorageError(\n `Database schema v${currentVersion} is newer than this Lynx build expects (v${expectedVersion}). ` +\n \"Please upgrade Lynx to the latest version.\",\n { recoverable: false, retryable: false, userVisible: true },\n );\n }\n\n if (currentVersion === expectedVersion) {\n return;\n }\n\n const pending = migrations.filter((m) => m.version > currentVersion);\n\n for (const migration of pending) {\n const apply = db.transaction(() => {\n db.exec(migration.sql);\n db.pragma(`user_version = ${migration.version}`);\n });\n\n try {\n apply();\n } catch (err) {\n // Best‑effort rollback\n if (migration.rollback) {\n try {\n db.exec(migration.rollback);\n } catch {\n // Rollback itself failed — DB may be in an inconsistent state.\n // The user should restore from the pre‑migration backup.\n }\n }\n throw new StorageError(\n `Migration v${migration.version} (${migration.description}) failed: ${(err as Error).message}`,\n {\n recoverable: false,\n retryable: false,\n userVisible: true,\n diagnosticHint: \"storage_migration_failed\",\n },\n );\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@24klynx/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Shared types and error infrastructure — zero dependencies",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
5
8
|
"type": "module",
|
|
6
9
|
"main": "./dist/index.mjs",
|
|
7
10
|
"types": "./dist/index.d.mts",
|
|
@@ -11,6 +14,9 @@
|
|
|
11
14
|
"types": "./dist/index.d.mts"
|
|
12
15
|
}
|
|
13
16
|
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
14
20
|
"dependencies": {
|
|
15
21
|
"better-sqlite3": "^12.10.0"
|
|
16
22
|
},
|
|
@@ -18,12 +24,6 @@
|
|
|
18
24
|
"@types/better-sqlite3": "^7.6.13",
|
|
19
25
|
"@types/node": "^25.9.1"
|
|
20
26
|
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist"
|
|
23
|
-
],
|
|
24
|
-
"publishConfig": {
|
|
25
|
-
"access": "public"
|
|
26
|
-
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsdown --config-loader tsx",
|
|
29
29
|
"test": "vitest run --passWithNoTests",
|