/** * ZCode App tasks-index sync: let the App UI see ACP-created sessions. * * The ZCode App's session list reads from `~/.zcode/v2/tasks-index.sqlite` * (the `tasks` table), NOT from the CLI's `~/.zcode/cli/db/db.sqlite`. These * are independent stores — the App's Electron host maintains tasks-index; the * headless app-server (which we drive) writes only to cli/db. As a result, * every session created via ACP is invisible in the App's UI until the App * happens to reindex. * * This module bridges that gap by writing a tasks-index row directly after * session/create. The App picks it up on its next list refresh. INSERT OR * IGNORE avoids clobbering rows the App already manages. * * Best-effort side-channel: failures (locked DB, schema drift) are logged and * swallowed so they never break the session/create path. */ /** * Insert (or refresh) a row in tasks-index.sqlite so the App UI shows it. * Called after a successful session/create. Uses INSERT OR IGNORE so it never * overwrites a row the App is actively managing (e.g. user-renamed titles). * * Returns true if written, false on failure (logged, never thrown). */ export declare function upsertSessionTask(opts: { workspaceKey: string; taskId: string; title: string; traceId?: string; model?: string; status?: string; }): Promise; /** * User-driven rename (remote rename endpoint): pins the title with * title_overridden=1 — the same marker the App's own rename flow sets — so no * later automatic write can touch it. Best-effort: returns false when the row * is missing or the index is unavailable. */ export declare function renameSessionTask(taskId: string, title: string): Promise; /** * Update a session's title + searchable_text after the first turn. * * session/create leaves title empty; once the first prompt completes, set a * meaningful title. Respects title_overridden: if the user already renamed in * the App, their title wins (but searchable_text is still refreshed — it's not * user-controlled). * * `searchableText` feeds the App's full-text search (the App builds it via * `buildSearchableTextFromMessages`: each message's content trimmed + joined * by newlines, capped at 200k chars). We pass the first user prompt here; the * App later overwrites it with the full conversation when it reindexes, but * having it non-empty from the start means the row shows up in search and * matches the shape of App-created rows. */ export declare function updateSessionTitle(taskId: string, title: string, searchableText?: string): Promise; /** * Soft-delete one session — the upstream App's own delete semantics * ("将已持久化 task 标记为列表不可见;CLI session 内容继续保留"): the tasks * row gets deleted=1, every reader (this bridge's listings, the hub's project * list, the desktop App sidebar) hides it, and the backend store keeps the * conversation intact. Reversible by clearing the flag; there is no * physical-delete path. * * A session with no tasks row yet (pre-sync era, App never reindexed) gets a * minimal tombstone row first — INSERT OR IGNORE never touches an existing * row's title/overrides; the UPDATE then flips the flag (idempotent). */ export declare function softDeleteTask(opts: { taskId: string; workspacePath: string; title?: string; }): Promise; /** * Soft-delete EVERY task row of a workspace — "delete the project" is just * "delete its sessions" en masse: the hub's project list derives from * deleted=0 rows, so the project disappears until a new session runs there * again (a hide, not a ban). Idempotent; returns the number of rows flipped. */ export declare function softDeleteWorkspaceTasks(workspacePath: string, dbPath?: string): Promise; /** * Clear delete tombstones when their sessions become USED again (ADR-0031's * amendment: a delete is a list-hide, and touching the project/session again * cancels it — "undelete = a flag flip", now automatic). * * Workspace scope: when EVERY row of the workspace is list-hidden (no * deleted=0 AND archived=0 row — the state a project delete leaves), any * session activity in it revives ALL its deleted rows at once: reopening a * project with the CLI/editor and touching any conversation (or creating a * new one) brings the whole project back. Runs BEFORE the task-scope flip — * reviving the one used session first would make the workspace visible again * and suppress the project-wide revival. * * Task scope: a single tombstoned session that is used again (load with * history, resume, a prompt turn) revives itself — the same self-heal * doctrine as discovery retirement (ADR-0006). Individually deleted sessions * of a VISIBLE workspace stay deleted: the workspace branch runs only at full * invisibility, and this branch touches exactly one task id. * * Archived rows are never revived — `archived=1` is the desktop App's own * archive marker (un-deleting would not even unhide them). * * Returns the number of rows revived (0 when there is nothing to revive, no * index, or the write fails — best-effort, never throws). */ export declare function reviveTombstonesOnActivity(opts: { taskId?: string; workspacePath?: string; }, dbPath?: string): Promise; /** * Task-ids whose tasks rows are list-hidden (deleted or archived tombstones). * The sessions listing consults this BEFORE sorting/pagination so pages stay * dense and cursors keep naming the exact next row. Silent best-effort: any * failure (no index, sqlite unavailable) means "nothing hidden" — listings * degrade to showing everything rather than erroring. */ export declare function hiddenTaskIds(dbPath?: string): Promise>; /** * Whether a session's tasks row carries the deleted tombstone — guards the * hub's resume path so a stale client cannot resurrect a deleted thread. * False when the row or index is absent (unknown ≠ deleted). */ export declare function isTaskDeleted(taskId: string, dbPath?: string): Promise; /** * Whether the tasks-index row marks this conversation's title as manually * renamed (`title_overridden=1`, set by renameSessionTask). Read-only consult * for the title listener: the bridge's in-memory rename pin is lost on * restart, but the durable flag keeps a later backend `generated` title push * from overriding the user's rename. False when the index or row is absent. */ export declare function isTitleOverridden(taskId: string): Promise; /** One known project workspace, as recorded by the App's tasks index. */ export interface KnownWorkspace { workspacePath: string; sessions: number; lastActive: number; } /** * Whether a recorded workspace path may be offered for remote session * creation. Excludes: degenerate roots, system temp trees (macOS /tmp is a * symlink to /private/tmp — both spellings; $TMPDIR lives under /var/folders), * and the ZCode data root itself (the config home, not a project). The * directory must still exist — a moved/deleted project disappears from the * list. */ export declare function isSelectableWorkspace(p: string): boolean; /** * Every project workspace the tasks index has ever recorded a VISIBLE session * for — the machine's known-projects list. Serves the hub's remote * session-create API: the list gates which projects POST /api/instances * accepts. A convenience bound, not a security boundary — bridge-side session * materialization writes rows too, and a token holder can drive an * editor-bridge session in any cwd (the real boundary is the token). * * Rows the session listing hides (deleted OR archived tombstones) do not make * a workspace known: a project whose every row is archived renders as an * empty entry in the remote project list (nothing to resume), so it stays off * the list until a new unarchived session records it again — same hide-≠-ban * semantics as the delete tombstones. * * Read-only and best-effort: node:sqlite unavailable → empty list; lock * contention retries via withSqliteRetry; other failures warn and return * empty. `dbPath` defaults to the App's index (tests inject a fixture). */ export declare function listKnownWorkspaces(dbPath?: string): Promise; //# sourceMappingURL=tasks-index.d.ts.map