@jamesaphoenix/tx-test-utils 0.5.1 → 0.5.2
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 +16 -4
- package/dist/adapters/better-sqlite3-adapter.d.ts +36 -0
- package/dist/adapters/better-sqlite3-adapter.d.ts.map +1 -0
- package/dist/adapters/better-sqlite3-adapter.js +78 -0
- package/dist/adapters/better-sqlite3-adapter.js.map +1 -0
- package/dist/helpers/shared-test-layer.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,14 @@ npm install -g @jamesaphoenix/tx-cli
|
|
|
9
9
|
tx init
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
Agent onboarding (optional, both supported):
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
tx init --claude # CLAUDE.md + .claude/skills
|
|
16
|
+
tx init --codex # AGENTS.md + .codex/agents
|
|
17
|
+
tx init --claude --codex # scaffold both
|
|
18
|
+
```
|
|
19
|
+
|
|
12
20
|
---
|
|
13
21
|
|
|
14
22
|
## The Problem
|
|
@@ -132,18 +140,20 @@ We ship **example loops**, not **the loop**:
|
|
|
132
140
|
|
|
133
141
|
```bash
|
|
134
142
|
# Simple: one agent, one task
|
|
143
|
+
AGENT_CMD=${AGENT_CMD:-codex} # or: claude
|
|
135
144
|
while task=$(tx ready --limit 1 --json | jq -r '.[0].id'); do
|
|
136
|
-
|
|
145
|
+
"$AGENT_CMD" "Work on task $task, then run: tx done $task"
|
|
137
146
|
done
|
|
138
147
|
```
|
|
139
148
|
|
|
140
149
|
```bash
|
|
141
150
|
# Parallel: N agents with claims
|
|
151
|
+
AGENT_CMD=${AGENT_CMD:-codex} # or: claude
|
|
142
152
|
for i in {1..5}; do
|
|
143
153
|
(while task=$(tx ready --json --limit 1 | jq -r '.[0].id // empty'); do
|
|
144
154
|
[ -z "$task" ] && break
|
|
145
155
|
tx claim "$task" "worker-$i" || continue
|
|
146
|
-
|
|
156
|
+
"$AGENT_CMD" "Complete $task" && tx done "$task"
|
|
147
157
|
done) &
|
|
148
158
|
done
|
|
149
159
|
wait
|
|
@@ -151,9 +161,10 @@ wait
|
|
|
151
161
|
|
|
152
162
|
```bash
|
|
153
163
|
# Human-in-loop: agent proposes, human approves
|
|
164
|
+
AGENT_CMD=${AGENT_CMD:-codex} # or: claude
|
|
154
165
|
task=$(tx ready --json --limit 1 | jq -r '.[0].id')
|
|
155
|
-
|
|
156
|
-
read -p "Approve? [y/n] " &&
|
|
166
|
+
"$AGENT_CMD" "Plan implementation for $task" > plan.md
|
|
167
|
+
read -p "Approve? [y/n] " && "$AGENT_CMD" "Execute plan.md"
|
|
157
168
|
tx done $task
|
|
158
169
|
```
|
|
159
170
|
|
|
@@ -326,6 +337,7 @@ Local SQLite for speed. JSONL for git sync. Branch your knowledge with your code
|
|
|
326
337
|
|
|
327
338
|
- **[txdocs.dev](https://txdocs.dev)**: Documentation
|
|
328
339
|
- **[CLAUDE.md](CLAUDE.md)**: Doctrine and quick reference
|
|
340
|
+
- **[AGENTS.md](AGENTS.md)**: Codex onboarding and quick reference
|
|
329
341
|
- **[docs/](docs/)**: PRDs and Design Docs
|
|
330
342
|
|
|
331
343
|
---
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* better-sqlite3 adapter for Vitest compatibility
|
|
3
|
+
*
|
|
4
|
+
* Wraps better-sqlite3 to match the SqliteDatabase interface used by @tx/core.
|
|
5
|
+
* This allows tests to use Vitest (with proper parallelization) while production
|
|
6
|
+
* uses bun:sqlite.
|
|
7
|
+
*
|
|
8
|
+
* The SqliteDatabase interface abstracts away the implementation, so this adapter
|
|
9
|
+
* makes better-sqlite3 compatible with the existing code.
|
|
10
|
+
*/
|
|
11
|
+
import type { SqliteDatabase } from "@jamesaphoenix/tx-core";
|
|
12
|
+
type BetterSqlite3Database = {
|
|
13
|
+
prepare(sql: string): {
|
|
14
|
+
run(...params: unknown[]): {
|
|
15
|
+
lastInsertRowid: number | bigint;
|
|
16
|
+
changes: number;
|
|
17
|
+
};
|
|
18
|
+
get(...params: unknown[]): unknown;
|
|
19
|
+
all(...params: unknown[]): unknown[];
|
|
20
|
+
};
|
|
21
|
+
exec(sql: string): void;
|
|
22
|
+
close(): void;
|
|
23
|
+
pragma(key: string, value?: unknown): unknown;
|
|
24
|
+
transaction<T>(fn: () => T): () => T;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Wrap a better-sqlite3 Database to match SqliteDatabase interface
|
|
28
|
+
*/
|
|
29
|
+
export declare function wrapBetterSqlite3(db: BetterSqlite3Database): SqliteDatabase;
|
|
30
|
+
/**
|
|
31
|
+
* Create an in-memory better-sqlite3 database wrapped as SqliteDatabase
|
|
32
|
+
* with migrations applied.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createBetterSqlite3Database(): Promise<SqliteDatabase>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=better-sqlite3-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"better-sqlite3-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/better-sqlite3-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAoC,MAAM,wBAAwB,CAAA;AAG9F,KAAK,qBAAqB,GAAG;IAC3B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QACpB,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG;YAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;QAChF,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;QAClC,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAA;KACrC,CAAA;IACD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,KAAK,IAAI,IAAI,CAAA;IACb,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC7C,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,CAAA;CACrC,CAAA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,qBAAqB,GAAG,cAAc,CA8C3E;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,cAAc,CAAC,CAe3E"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* better-sqlite3 adapter for Vitest compatibility
|
|
3
|
+
*
|
|
4
|
+
* Wraps better-sqlite3 to match the SqliteDatabase interface used by @tx/core.
|
|
5
|
+
* This allows tests to use Vitest (with proper parallelization) while production
|
|
6
|
+
* uses bun:sqlite.
|
|
7
|
+
*
|
|
8
|
+
* The SqliteDatabase interface abstracts away the implementation, so this adapter
|
|
9
|
+
* makes better-sqlite3 compatible with the existing code.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Wrap a better-sqlite3 Database to match SqliteDatabase interface
|
|
13
|
+
*/
|
|
14
|
+
export function wrapBetterSqlite3(db) {
|
|
15
|
+
return {
|
|
16
|
+
prepare(sql) {
|
|
17
|
+
const stmt = db.prepare(sql);
|
|
18
|
+
return {
|
|
19
|
+
run(...params) {
|
|
20
|
+
const result = stmt.run(...params);
|
|
21
|
+
return {
|
|
22
|
+
lastInsertRowid: result.lastInsertRowid ?? 0,
|
|
23
|
+
changes: result.changes ?? 0
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
get(...params) {
|
|
27
|
+
return stmt.get(...params) ?? null;
|
|
28
|
+
},
|
|
29
|
+
all(...params) {
|
|
30
|
+
return stmt.all(...params);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
run(sql, ...params) {
|
|
35
|
+
// Handle PRAGMA statements — better-sqlite3 uses .pragma("key = value") as a single string
|
|
36
|
+
const trimmed = sql.trim();
|
|
37
|
+
if (trimmed.toUpperCase().startsWith("PRAGMA")) {
|
|
38
|
+
// Strip the "PRAGMA " prefix and pass the rest directly to .pragma()
|
|
39
|
+
const pragmaArg = trimmed.slice(6).trim();
|
|
40
|
+
db.pragma(pragmaArg);
|
|
41
|
+
return { lastInsertRowid: 0, changes: 0 };
|
|
42
|
+
}
|
|
43
|
+
// Regular SQL statements
|
|
44
|
+
const result = db.prepare(sql).run(...params);
|
|
45
|
+
return {
|
|
46
|
+
lastInsertRowid: result.lastInsertRowid ?? 0,
|
|
47
|
+
changes: result.changes ?? 0
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
exec(sql) {
|
|
51
|
+
db.exec(sql);
|
|
52
|
+
},
|
|
53
|
+
close() {
|
|
54
|
+
db.close();
|
|
55
|
+
},
|
|
56
|
+
transaction(fn) {
|
|
57
|
+
return db.transaction(fn);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create an in-memory better-sqlite3 database wrapped as SqliteDatabase
|
|
63
|
+
* with migrations applied.
|
|
64
|
+
*/
|
|
65
|
+
export async function createBetterSqlite3Database() {
|
|
66
|
+
// Dynamic import to avoid requiring better-sqlite3 at module load time
|
|
67
|
+
// (only needed when running tests with Vitest)
|
|
68
|
+
const Database = (await import("better-sqlite3")).default;
|
|
69
|
+
const { applyMigrations } = await import("@jamesaphoenix/tx-core");
|
|
70
|
+
const db = new Database(":memory:");
|
|
71
|
+
db.pragma("journal_mode = WAL");
|
|
72
|
+
db.pragma("foreign_keys = ON");
|
|
73
|
+
db.pragma("busy_timeout = 5000");
|
|
74
|
+
const wrapped = wrapBetterSqlite3(db);
|
|
75
|
+
applyMigrations(wrapped);
|
|
76
|
+
return wrapped;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=better-sqlite3-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"better-sqlite3-adapter.js","sourceRoot":"","sources":["../../src/adapters/better-sqlite3-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAiBH;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAyB;IACzD,OAAO;QACL,OAAO,CAAc,GAAW;YAC9B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAC5B,OAAO;gBACL,GAAG,CAAC,GAAG,MAAiB;oBACtB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAA0D,CAAA;oBAC3F,OAAO;wBACL,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,CAAC;wBAC5C,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC;qBAC7B,CAAA;gBACH,CAAC;gBACD,GAAG,CAAC,GAAG,MAAiB;oBACtB,OAAQ,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAO,IAAI,IAAI,CAAA;gBAC3C,CAAC;gBACD,GAAG,CAAC,GAAG,MAAiB;oBACtB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAQ,CAAA;gBACnC,CAAC;aACF,CAAA;QACH,CAAC;QACD,GAAG,CAAC,GAAW,EAAE,GAAG,MAAiB;YACnC,2FAA2F;YAC3F,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;YAC1B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/C,qEAAqE;gBACrE,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;gBACzC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;gBACpB,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;YAC3C,CAAC;YACD,yBAAyB;YACzB,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAA0D,CAAA;YACtG,OAAO;gBACL,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,CAAC;gBAC5C,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC;aAC7B,CAAA;QACH,CAAC;QACD,IAAI,CAAC,GAAW;YACd,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACd,CAAC;QACD,KAAK;YACH,EAAE,CAAC,KAAK,EAAE,CAAA;QACZ,CAAC;QACD,WAAW,CAAI,EAAW;YACxB,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QAC3B,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B;IAC/C,uEAAuE;IACvE,+CAA+C;IAC/C,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAA;IACzD,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAA;IAElE,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAA;IACnC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;IAC/B,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAC9B,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAEhC,MAAM,OAAO,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAA;IACrC,eAAe,CAAC,OAAO,CAAC,CAAA;IAExB,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -56,7 +56,7 @@ export interface SharedTestLayer<L> {
|
|
|
56
56
|
* ```
|
|
57
57
|
*/
|
|
58
58
|
export declare const createSharedTestLayer: () => Promise<{
|
|
59
|
-
layer: Layer.Layer<import("@jamesaphoenix/tx-core").
|
|
59
|
+
layer: Layer.Layer<import("@jamesaphoenix/tx-core").EdgeRepository | import("@jamesaphoenix/tx-core").SqliteClient | import("@jamesaphoenix/tx-core").TaskService | import("@jamesaphoenix/tx-core").TaskRepository | import("@jamesaphoenix/tx-core").DependencyRepository | import("@jamesaphoenix/tx-core").DependencyService | import("@jamesaphoenix/tx-core").ReadyService | import("@jamesaphoenix/tx-core").HierarchyService | import("@jamesaphoenix/tx-core").LearningService | import("@jamesaphoenix/tx-core").LearningRepository | import("@jamesaphoenix/tx-core").RetrieverService | import("@jamesaphoenix/tx-core").FileLearningService | import("@jamesaphoenix/tx-core").FileLearningRepository | import("@jamesaphoenix/tx-core").AttemptService | import("@jamesaphoenix/tx-core").AttemptRepository | import("@jamesaphoenix/tx-core").AnchorService | import("@jamesaphoenix/tx-core").AnchorRepository | import("@jamesaphoenix/tx-core").DeduplicationService | import("@jamesaphoenix/tx-core").DeduplicationRepository | import("@jamesaphoenix/tx-core").RunRepository | import("@jamesaphoenix/tx-core").CandidateRepository | import("@jamesaphoenix/tx-core").TrackedProjectRepository | import("@jamesaphoenix/tx-core").WorkerRepository | import("@jamesaphoenix/tx-core").ClaimRepository | import("@jamesaphoenix/tx-core").OrchestratorStateRepository | import("@jamesaphoenix/tx-core").CompactionRepository | import("@jamesaphoenix/tx-core").MessageRepository | import("@jamesaphoenix/tx-core").DocRepository | import("@jamesaphoenix/tx-core").DiversifierService | import("@jamesaphoenix/tx-core").GraphExpansionService | import("@jamesaphoenix/tx-core").FeedbackTrackerService | import("@jamesaphoenix/tx-core").EdgeService | import("@jamesaphoenix/tx-core").SyncService | import("@jamesaphoenix/tx-core").AnchorVerificationService | import("@jamesaphoenix/tx-core").SwarmVerificationService | import("@jamesaphoenix/tx-core").PromotionService | import("@jamesaphoenix/tx-core").WorkerService | import("@jamesaphoenix/tx-core").ClaimService | import("@jamesaphoenix/tx-core").OrchestratorService | import("@jamesaphoenix/tx-core").DaemonService | import("@jamesaphoenix/tx-core").TracingService | import("@jamesaphoenix/tx-core").CompactionService | import("@jamesaphoenix/tx-core").ValidationService | import("@jamesaphoenix/tx-core").MessageService | import("@jamesaphoenix/tx-core").DocService | import("@jamesaphoenix/tx-core").MigrationService, import("@jamesaphoenix/tx-core").DatabaseError, never>;
|
|
60
60
|
reset: () => Promise<void>;
|
|
61
61
|
close: () => Promise<void>;
|
|
62
62
|
getDb: () => Database;
|