agentlip 0.1.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/src/index.ts ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * agentlip - CLI utilities for Agentlip
3
+ *
4
+ * Provides:
5
+ * - Workspace discovery (reusing @agentlip/workspace)
6
+ * - Read-only DB opening with query_only=ON
7
+ */
8
+
9
+ import { discoverWorkspaceRoot } from "@agentlip/workspace";
10
+ import { openDb } from "@agentlip/kernel";
11
+ import type { Database } from "bun:sqlite";
12
+
13
+ // Re-export workspace discovery for convenience
14
+ export { discoverWorkspaceRoot } from "@agentlip/workspace";
15
+
16
+ /**
17
+ * Error thrown when no workspace is found
18
+ */
19
+ export class WorkspaceNotFoundError extends Error {
20
+ constructor(startPath: string) {
21
+ super(`No workspace found (no .agentlip/db.sqlite3 in directory tree starting from ${startPath})`);
22
+ this.name = "WorkspaceNotFoundError";
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Error thrown when DB does not exist at expected path
28
+ */
29
+ export class DatabaseNotFoundError extends Error {
30
+ constructor(dbPath: string) {
31
+ super(`Database not found at ${dbPath}`);
32
+ this.name = "DatabaseNotFoundError";
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Result of opening workspace DB in read-only mode
38
+ */
39
+ export interface WorkspaceDbResult {
40
+ /** Database instance (readonly, query_only=ON) */
41
+ db: Database;
42
+ /** Absolute path to workspace root directory */
43
+ workspaceRoot: string;
44
+ /** Absolute path to db.sqlite3 file */
45
+ dbPath: string;
46
+ }
47
+
48
+ /**
49
+ * Options for opening workspace DB in read-only mode
50
+ */
51
+ export interface OpenWorkspaceDbReadonlyOptions {
52
+ /** Explicit workspace path (otherwise auto-discover from cwd) */
53
+ workspace?: string;
54
+ }
55
+
56
+ /**
57
+ * Open workspace database in read-only mode.
58
+ *
59
+ * This function:
60
+ * 1. Discovers workspace root by walking upward from workspace (or cwd)
61
+ * 2. Opens the database with readonly=true
62
+ * 3. Sets PRAGMA query_only=ON (via @agentlip/kernel)
63
+ *
64
+ * The database is opened read-only and cannot be mutated.
65
+ * This is safe for CLI queries while hub may be running.
66
+ *
67
+ * @param options - Optional workspace path override
68
+ * @returns Database instance, workspace root, and DB path
69
+ * @throws WorkspaceNotFoundError if no workspace found
70
+ * @throws DatabaseNotFoundError if DB file doesn't exist
71
+ */
72
+ export async function openWorkspaceDbReadonly(
73
+ options: OpenWorkspaceDbReadonlyOptions = {}
74
+ ): Promise<WorkspaceDbResult> {
75
+ const startPath = options.workspace ?? process.cwd();
76
+
77
+ // Discover workspace root
78
+ const discovered = await discoverWorkspaceRoot(startPath);
79
+
80
+ if (!discovered) {
81
+ throw new WorkspaceNotFoundError(startPath);
82
+ }
83
+
84
+ const { root: workspaceRoot, dbPath } = discovered;
85
+
86
+ // Verify DB file exists before attempting to open
87
+ const { existsSync } = await import("node:fs");
88
+ if (!existsSync(dbPath)) {
89
+ throw new DatabaseNotFoundError(dbPath);
90
+ }
91
+
92
+ // Open database in read-only mode
93
+ // @agentlip/kernel openDb sets query_only=ON when readonly=true
94
+ const db = openDb({ dbPath, readonly: true });
95
+
96
+ return {
97
+ db,
98
+ workspaceRoot,
99
+ dbPath,
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Verify that a database has query_only=ON.
105
+ *
106
+ * Useful for testing that the DB is truly read-only.
107
+ *
108
+ * @param db - Database instance to check
109
+ * @returns true if query_only is enabled
110
+ */
111
+ export function isQueryOnly(db: Database): boolean {
112
+ const result = db.query<{ query_only: number }, []>("PRAGMA query_only").get();
113
+ return result?.query_only === 1;
114
+ }