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/README.md +74 -0
- package/package.json +37 -0
- package/src/agentlip.ts +2255 -0
- package/src/index.ts +114 -0
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
|
+
}
|