@jamesaphoenix/tx 0.1.0 → 0.4.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 +42 -98
- package/dist/create-tx.d.ts +147 -0
- package/dist/create-tx.d.ts.map +1 -0
- package/dist/create-tx.js +102 -0
- package/dist/create-tx.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -16
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +35 -34
- package/LICENSE +0 -21
- package/dist/cli.js +0 -868
- package/dist/cli.js.map +0 -1
- package/dist/db.js +0 -70
- package/dist/db.js.map +0 -1
- package/dist/errors.js +0 -22
- package/dist/errors.js.map +0 -1
- package/dist/id.js +0 -19
- package/dist/id.js.map +0 -1
- package/dist/layer.js +0 -20
- package/dist/layer.js.map +0 -1
- package/dist/mcp/server.js +0 -453
- package/dist/mcp/server.js.map +0 -1
- package/dist/repo/dep-repo.js +0 -104
- package/dist/repo/dep-repo.js.map +0 -1
- package/dist/repo/task-repo.js +0 -140
- package/dist/repo/task-repo.js.map +0 -1
- package/dist/schema.js +0 -37
- package/dist/schema.js.map +0 -1
- package/dist/schemas/sync.js +0 -55
- package/dist/schemas/sync.js.map +0 -1
- package/dist/services/dep-service.js +0 -34
- package/dist/services/dep-service.js.map +0 -1
- package/dist/services/hierarchy-service.js +0 -66
- package/dist/services/hierarchy-service.js.map +0 -1
- package/dist/services/ready-service.js +0 -70
- package/dist/services/ready-service.js.map +0 -1
- package/dist/services/score-service.js +0 -82
- package/dist/services/score-service.js.map +0 -1
- package/dist/services/sync-service.js +0 -244
- package/dist/services/sync-service.js.map +0 -1
- package/dist/services/task-service.js +0 -201
- package/dist/services/task-service.js.map +0 -1
- package/migrations/001_initial.sql +0 -57
package/README.md
CHANGED
|
@@ -1,124 +1,68 @@
|
|
|
1
|
-
# tx
|
|
1
|
+
# @jamesaphoenix/tx
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**TanStack for AI agents.** Headless primitives for memory, tasks, and orchestration.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
**tx** gives agents a persistent, queryable, dependency-aware task store that works across sessions and can be programmatically manipulated through CLI, MCP, or TypeScript API.
|
|
10
|
-
|
|
11
|
-
## Core Ideas
|
|
12
|
-
|
|
13
|
-
- **Persistent** -- Tasks survive across agent sessions and machine restarts via SQLite
|
|
14
|
-
- **Fast** -- Sub-100ms queries for common operations (list, ready, get)
|
|
15
|
-
- **Dependency-aware** -- Explicit blocking relationships so agents never work on blocked tasks
|
|
16
|
-
- **Ready detection** -- `tx ready` returns the highest-priority unblocked tasks, sorted by score
|
|
17
|
-
- **Hierarchical** -- Flexible N-level nesting (epics, milestones, tasks, subtasks)
|
|
18
|
-
- **Multi-interface** -- CLI for humans, MCP server for Claude Code, TypeScript API for custom agents
|
|
19
|
-
- **Minimal** -- Single dependency (SQLite), no external services required for core features
|
|
20
|
-
- **LLM-optional** -- Core commands work without an API key; LLM features (dedupe, compact, reprioritize) use Claude when available
|
|
21
|
-
|
|
22
|
-
## How It Works
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
tx add "Implement authentication" --score 800
|
|
26
|
-
tx add "Design auth schema" --parent tx-a1b2c3
|
|
27
|
-
tx block tx-d4e5f6 tx-a1b2c3
|
|
28
|
-
tx ready # returns highest-priority unblocked tasks
|
|
29
|
-
tx done tx-a1b2c3 # completes task, unblocks dependents
|
|
7
|
+
```bash
|
|
8
|
+
npm install @jamesaphoenix/tx better-sqlite3 effect
|
|
30
9
|
```
|
|
31
10
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## Architecture
|
|
11
|
+
## Quick Start
|
|
35
12
|
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
|
|
|
39
|
-
Service Layer (Effect-TS)
|
|
40
|
-
TaskService, ReadyService, ScoreService, HierarchyService
|
|
41
|
-
|
|
|
42
|
-
Repository Layer
|
|
43
|
-
TaskRepository, DependencyRepository
|
|
44
|
-
|
|
|
45
|
-
SQLite (better-sqlite3, WAL mode)
|
|
46
|
-
```
|
|
13
|
+
```typescript
|
|
14
|
+
import { createTx } from '@jamesaphoenix/tx'
|
|
47
15
|
|
|
48
|
-
|
|
16
|
+
// Initialize tx
|
|
17
|
+
const tx = createTx()
|
|
49
18
|
|
|
50
|
-
|
|
51
|
-
|
|
19
|
+
// Create a task
|
|
20
|
+
const task = await tx.add({
|
|
21
|
+
title: 'Implement feature X',
|
|
22
|
+
status: 'ready'
|
|
23
|
+
})
|
|
52
24
|
|
|
53
|
-
|
|
25
|
+
// Get next workable task
|
|
26
|
+
const next = await tx.ready()
|
|
54
27
|
|
|
28
|
+
// Complete a task
|
|
29
|
+
await tx.done(task.id)
|
|
55
30
|
```
|
|
56
|
-
backlog -> ready -> planning -> active -> blocked -> review -> human_needs_to_review -> done
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
A task is **ready** when its status is workable and all blockers have status `done`.
|
|
60
|
-
|
|
61
|
-
## Interfaces
|
|
62
31
|
|
|
63
|
-
|
|
64
|
-
|-----------|----------|----------|
|
|
65
|
-
| CLI (`tx`) | Humans, scripts | stdin/stdout (text or JSON) |
|
|
66
|
-
| MCP Server | Claude Code | JSON-RPC over stdio |
|
|
67
|
-
| TypeScript API | Custom agents | Effect types |
|
|
68
|
-
| Agent SDK | Anthropic SDK | Tool definitions |
|
|
32
|
+
## CLI Usage
|
|
69
33
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
34
|
+
```bash
|
|
35
|
+
# Install globally
|
|
36
|
+
npm install -g @jamesaphoenix/tx
|
|
73
37
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
- **`tx reprioritize`** -- LLM recalculates scores based on context
|
|
38
|
+
# Create tasks
|
|
39
|
+
tx add "Implement feature X"
|
|
77
40
|
|
|
78
|
-
|
|
41
|
+
# Get next ready task
|
|
42
|
+
tx ready
|
|
79
43
|
|
|
80
|
-
|
|
44
|
+
# Complete a task
|
|
45
|
+
tx done <task-id>
|
|
81
46
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
./scripts/ralph.sh --max 10 # Run at most 10 iterations
|
|
47
|
+
# View task tree
|
|
48
|
+
tx tree <task-id>
|
|
85
49
|
```
|
|
86
50
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
### Specialized Agents
|
|
90
|
-
|
|
91
|
-
Agents are defined as markdown files in `.claude/agents/`:
|
|
51
|
+
## Philosophy: Primitives, Not Frameworks
|
|
92
52
|
|
|
93
|
-
|
|
94
|
-
|-------|------|
|
|
95
|
-
| `tx-planner` | Research codebase, create implementation plan, decompose into subtasks |
|
|
96
|
-
| `tx-implementer` | Write Effect-TS code for a single task, following doctrine |
|
|
97
|
-
| `tx-reviewer` | Review code changes against all 7 doctrine rules |
|
|
98
|
-
| `tx-tester` | Write integration tests with SHA256 deterministic fixtures |
|
|
99
|
-
| `tx-decomposer` | Break large tasks into atomic subtasks for single iterations |
|
|
53
|
+
tx provides headless infrastructure for AI agent orchestration. You own your orchestration logic - tx owns the primitives.
|
|
100
54
|
|
|
101
|
-
|
|
55
|
+
| Primitive | Purpose |
|
|
56
|
+
|-----------|---------|
|
|
57
|
+
| `tx ready` | Get next workable task (unblocked, highest priority) |
|
|
58
|
+
| `tx claim <id>` | Mark task as being worked by an agent |
|
|
59
|
+
| `tx done <id>` | Complete task, potentially unblocking others |
|
|
60
|
+
| `tx block <id> <blocker>` | Declare dependencies |
|
|
61
|
+
| `tx handoff <id> --to <agent>` | Transfer task with context |
|
|
102
62
|
|
|
103
|
-
##
|
|
63
|
+
## Documentation
|
|
104
64
|
|
|
105
|
-
|
|
106
|
-
tx/
|
|
107
|
-
├── CLAUDE.md # Doctrine, PRDs, design docs
|
|
108
|
-
├── .claude/
|
|
109
|
-
│ └── agents/ # Specialized agent definitions
|
|
110
|
-
│ ├── tx-planner.md
|
|
111
|
-
│ ├── tx-implementer.md
|
|
112
|
-
│ ├── tx-reviewer.md
|
|
113
|
-
│ ├── tx-tester.md
|
|
114
|
-
│ └── tx-decomposer.md
|
|
115
|
-
├── scripts/
|
|
116
|
-
│ └── ralph.sh # RALPH loop orchestrator
|
|
117
|
-
├── docs/
|
|
118
|
-
│ ├── prd/ # Product Requirements Documents
|
|
119
|
-
│ └── design/ # Design Documents
|
|
120
|
-
└── src/ # Implementation
|
|
121
|
-
```
|
|
65
|
+
Full documentation: [github.com/jamesaphoenix/tx](https://github.com/jamesaphoenix/tx)
|
|
122
66
|
|
|
123
67
|
## License
|
|
124
68
|
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createTx - Factory function to create a configured tx client
|
|
3
|
+
*
|
|
4
|
+
* This module provides the main entry point for SDK consumers who want
|
|
5
|
+
* to customize tx behavior, such as providing a custom retriever.
|
|
6
|
+
*
|
|
7
|
+
* @example Basic usage
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { createTx } from "@jamesaphoenix/tx";
|
|
10
|
+
*
|
|
11
|
+
* const tx = createTx();
|
|
12
|
+
* const ready = await tx.run(tasks.getReady({ limit: 5 }));
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @example Custom retriever
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { createTx, RetrieverService } from "@jamesaphoenix/tx";
|
|
18
|
+
* import { Effect, Layer } from "effect";
|
|
19
|
+
*
|
|
20
|
+
* const myRetriever = Layer.succeed(RetrieverService, {
|
|
21
|
+
* search: (query, options) => Effect.gen(function* () {
|
|
22
|
+
* return yield* pineconeQuery(query);
|
|
23
|
+
* }),
|
|
24
|
+
* isAvailable: () => Effect.succeed(true)
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const tx = createTx({ retriever: myRetriever });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import { Effect, Exit, Layer } from "effect";
|
|
31
|
+
import { RetrieverService } from "@tx/core";
|
|
32
|
+
/**
|
|
33
|
+
* Options for configuring createTx().
|
|
34
|
+
*
|
|
35
|
+
* All options are optional - defaults provide a fully functional tx instance.
|
|
36
|
+
*/
|
|
37
|
+
export interface CreateTxOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Path to SQLite database file.
|
|
40
|
+
* @default ".tx/tasks.db"
|
|
41
|
+
*/
|
|
42
|
+
readonly dbPath?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Custom retriever layer to use instead of the default BM25+vector hybrid.
|
|
45
|
+
*
|
|
46
|
+
* When provided, this layer replaces RetrieverServiceLive entirely.
|
|
47
|
+
* The layer must satisfy the RetrieverService interface.
|
|
48
|
+
*
|
|
49
|
+
* @example Pinecone retriever
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const myRetriever = Layer.succeed(RetrieverService, {
|
|
52
|
+
* search: (query, options) => Effect.gen(function* () {
|
|
53
|
+
* const results = yield* pineconeQuery(query);
|
|
54
|
+
* return results.map(toLearningWithScore);
|
|
55
|
+
* }),
|
|
56
|
+
* isAvailable: () => Effect.succeed(true)
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* const tx = createTx({ retriever: myRetriever });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
readonly retriever?: Layer.Layer<RetrieverService>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The tx client returned by createTx().
|
|
66
|
+
*
|
|
67
|
+
* Provides methods to run Effects against the configured layer
|
|
68
|
+
* and access commonly-used services directly.
|
|
69
|
+
*/
|
|
70
|
+
export interface TxClient {
|
|
71
|
+
/**
|
|
72
|
+
* Run an Effect against the configured tx layer.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const ready = await tx.run(
|
|
77
|
+
* Effect.gen(function* () {
|
|
78
|
+
* const tasks = yield* TaskService;
|
|
79
|
+
* return yield* tasks.getReady({ limit: 5 });
|
|
80
|
+
* })
|
|
81
|
+
* );
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
readonly run: <A, E>(effect: Effect.Effect<A, E, never>) => Promise<A>;
|
|
85
|
+
/**
|
|
86
|
+
* Run an Effect and return an Exit (success or failure).
|
|
87
|
+
* Useful when you need to handle errors programmatically.
|
|
88
|
+
*/
|
|
89
|
+
readonly runExit: <A, E>(effect: Effect.Effect<A, E, never>) => Promise<Exit.Exit<A, unknown>>;
|
|
90
|
+
/**
|
|
91
|
+
* The composed Layer for advanced use cases.
|
|
92
|
+
* Can be used with Effect.provide() directly.
|
|
93
|
+
*/
|
|
94
|
+
readonly layer: Layer.Layer<any, any, any>;
|
|
95
|
+
/**
|
|
96
|
+
* Clean up resources (close database, etc.).
|
|
97
|
+
* Call this when done using the client.
|
|
98
|
+
*/
|
|
99
|
+
readonly close: () => Promise<void>;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Create a tx client with optional configuration.
|
|
103
|
+
*
|
|
104
|
+
* This is the main entry point for SDK consumers who want to:
|
|
105
|
+
* - Use a custom database path
|
|
106
|
+
* - Provide a custom retriever (Pinecone, Weaviate, etc.)
|
|
107
|
+
*
|
|
108
|
+
* @param options - Configuration options (all optional)
|
|
109
|
+
* @returns A TxClient for running Effects against the configured layer
|
|
110
|
+
*
|
|
111
|
+
* @example Basic usage (defaults)
|
|
112
|
+
* ```typescript
|
|
113
|
+
* const tx = createTx();
|
|
114
|
+
*
|
|
115
|
+
* const ready = await tx.run(
|
|
116
|
+
* Effect.gen(function* () {
|
|
117
|
+
* const tasks = yield* TaskService;
|
|
118
|
+
* return yield* tasks.getReady({ limit: 5 });
|
|
119
|
+
* })
|
|
120
|
+
* );
|
|
121
|
+
*
|
|
122
|
+
* await tx.close();
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @example Custom retriever
|
|
126
|
+
* ```typescript
|
|
127
|
+
* import { createTx, RetrieverService } from "@jamesaphoenix/tx";
|
|
128
|
+
* import { Effect, Layer } from "effect";
|
|
129
|
+
*
|
|
130
|
+
* const pineconeRetriever = Layer.succeed(RetrieverService, {
|
|
131
|
+
* search: (query, options) => Effect.gen(function* () {
|
|
132
|
+
* // Your Pinecone/Weaviate/Chroma implementation
|
|
133
|
+
* const results = yield* queryExternalVectorDB(query, options);
|
|
134
|
+
* return results;
|
|
135
|
+
* }),
|
|
136
|
+
* isAvailable: () => Effect.succeed(true)
|
|
137
|
+
* });
|
|
138
|
+
*
|
|
139
|
+
* const tx = createTx({
|
|
140
|
+
* dbPath: "./my-app/.tx/tasks.db",
|
|
141
|
+
* retriever: pineconeRetriever
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export declare const createTx: (options?: CreateTxOptions) => TxClient;
|
|
146
|
+
export { RetrieverService } from "@tx/core";
|
|
147
|
+
//# sourceMappingURL=create-tx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-tx.d.ts","sourceRoot":"","sources":["../src/create-tx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAA;AAC5D,OAAO,EAEL,gBAAgB,EACjB,MAAM,UAAU,CAAA;AAEjB;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAExB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;CACnD;AAED;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;IAEtE;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;IAE9F;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAE1C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAS,eAAoB,KAAG,QAiCxD,CAAA;AAGD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createTx - Factory function to create a configured tx client
|
|
3
|
+
*
|
|
4
|
+
* This module provides the main entry point for SDK consumers who want
|
|
5
|
+
* to customize tx behavior, such as providing a custom retriever.
|
|
6
|
+
*
|
|
7
|
+
* @example Basic usage
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { createTx } from "@jamesaphoenix/tx";
|
|
10
|
+
*
|
|
11
|
+
* const tx = createTx();
|
|
12
|
+
* const ready = await tx.run(tasks.getReady({ limit: 5 }));
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @example Custom retriever
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { createTx, RetrieverService } from "@jamesaphoenix/tx";
|
|
18
|
+
* import { Effect, Layer } from "effect";
|
|
19
|
+
*
|
|
20
|
+
* const myRetriever = Layer.succeed(RetrieverService, {
|
|
21
|
+
* search: (query, options) => Effect.gen(function* () {
|
|
22
|
+
* return yield* pineconeQuery(query);
|
|
23
|
+
* }),
|
|
24
|
+
* isAvailable: () => Effect.succeed(true)
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const tx = createTx({ retriever: myRetriever });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import { Layer, ManagedRuntime } from "effect";
|
|
31
|
+
import { makeAppLayer } from "@tx/core";
|
|
32
|
+
/**
|
|
33
|
+
* Create a tx client with optional configuration.
|
|
34
|
+
*
|
|
35
|
+
* This is the main entry point for SDK consumers who want to:
|
|
36
|
+
* - Use a custom database path
|
|
37
|
+
* - Provide a custom retriever (Pinecone, Weaviate, etc.)
|
|
38
|
+
*
|
|
39
|
+
* @param options - Configuration options (all optional)
|
|
40
|
+
* @returns A TxClient for running Effects against the configured layer
|
|
41
|
+
*
|
|
42
|
+
* @example Basic usage (defaults)
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const tx = createTx();
|
|
45
|
+
*
|
|
46
|
+
* const ready = await tx.run(
|
|
47
|
+
* Effect.gen(function* () {
|
|
48
|
+
* const tasks = yield* TaskService;
|
|
49
|
+
* return yield* tasks.getReady({ limit: 5 });
|
|
50
|
+
* })
|
|
51
|
+
* );
|
|
52
|
+
*
|
|
53
|
+
* await tx.close();
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @example Custom retriever
|
|
57
|
+
* ```typescript
|
|
58
|
+
* import { createTx, RetrieverService } from "@jamesaphoenix/tx";
|
|
59
|
+
* import { Effect, Layer } from "effect";
|
|
60
|
+
*
|
|
61
|
+
* const pineconeRetriever = Layer.succeed(RetrieverService, {
|
|
62
|
+
* search: (query, options) => Effect.gen(function* () {
|
|
63
|
+
* // Your Pinecone/Weaviate/Chroma implementation
|
|
64
|
+
* const results = yield* queryExternalVectorDB(query, options);
|
|
65
|
+
* return results;
|
|
66
|
+
* }),
|
|
67
|
+
* isAvailable: () => Effect.succeed(true)
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* const tx = createTx({
|
|
71
|
+
* dbPath: "./my-app/.tx/tasks.db",
|
|
72
|
+
* retriever: pineconeRetriever
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export const createTx = (options = {}) => {
|
|
77
|
+
const { dbPath = ".tx/tasks.db", retriever } = options;
|
|
78
|
+
// Build the base app layer
|
|
79
|
+
const baseLayer = makeAppLayer(dbPath);
|
|
80
|
+
// If custom retriever provided, merge it on top to override the default
|
|
81
|
+
// Layer.provideMerge gives priority to the first layer for overlapping services
|
|
82
|
+
const appLayer = retriever
|
|
83
|
+
? Layer.provideMerge(retriever, baseLayer)
|
|
84
|
+
: baseLayer;
|
|
85
|
+
// Create a managed runtime that handles resource lifecycle
|
|
86
|
+
const managedRuntime = ManagedRuntime.make(appLayer);
|
|
87
|
+
return {
|
|
88
|
+
run: async (effect) => {
|
|
89
|
+
return managedRuntime.runPromise(effect);
|
|
90
|
+
},
|
|
91
|
+
runExit: async (effect) => {
|
|
92
|
+
return managedRuntime.runPromiseExit(effect);
|
|
93
|
+
},
|
|
94
|
+
layer: appLayer,
|
|
95
|
+
close: async () => {
|
|
96
|
+
await managedRuntime.dispose();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
// Re-export RetrieverService for custom retriever implementations
|
|
101
|
+
export { RetrieverService } from "@tx/core";
|
|
102
|
+
//# sourceMappingURL=create-tx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-tx.js","sourceRoot":"","sources":["../src/create-tx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAgB,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAC5D,OAAO,EACL,YAAY,EAEb,MAAM,UAAU,CAAA;AA6EjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,UAA2B,EAAE,EAAY,EAAE;IAClE,MAAM,EACJ,MAAM,GAAG,cAAc,EACvB,SAAS,EACV,GAAG,OAAO,CAAA;IAEX,2BAA2B;IAC3B,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IAEtC,wEAAwE;IACxE,gFAAgF;IAChF,MAAM,QAAQ,GAAG,SAAS;QACxB,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC;QAC1C,CAAC,CAAC,SAAS,CAAA;IAEb,2DAA2D;IAC3D,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAEpD,OAAO;QACL,GAAG,EAAE,KAAK,EAAQ,MAAkC,EAAc,EAAE;YAClE,OAAO,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QAC1C,CAAC;QAED,OAAO,EAAE,KAAK,EAAQ,MAAkC,EAAkC,EAAE;YAC1F,OAAO,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;QAC9C,CAAC;QAED,KAAK,EAAE,QAAQ;QAEf,KAAK,EAAE,KAAK,IAAmB,EAAE;YAC/B,MAAM,cAAc,CAAC,OAAO,EAAE,CAAA;QAChC,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED,kEAAkE;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jamesaphoenix/tx - TanStack for AI agents
|
|
3
|
+
*
|
|
4
|
+
* Headless primitives for memory, tasks, and orchestration.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { TaskService, LearningService, makeAppLayer } from "@jamesaphoenix/tx";
|
|
9
|
+
* import { Effect } from "effect";
|
|
10
|
+
*
|
|
11
|
+
* const program = Effect.gen(function* () {
|
|
12
|
+
* const tasks = yield* TaskService;
|
|
13
|
+
* const ready = yield* tasks.getReady({ limit: 5 });
|
|
14
|
+
* return ready;
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Custom Retriever
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { createTx, RetrieverService } from "@jamesaphoenix/tx";
|
|
21
|
+
* import { Effect, Layer } from "effect";
|
|
22
|
+
*
|
|
23
|
+
* // Custom Pinecone retriever
|
|
24
|
+
* const myRetriever = Layer.succeed(RetrieverService, {
|
|
25
|
+
* search: (query, options) => Effect.gen(function* () {
|
|
26
|
+
* const results = yield* pineconeQuery(query);
|
|
27
|
+
* return results.map(toLearningWithScore);
|
|
28
|
+
* }),
|
|
29
|
+
* isAvailable: () => Effect.succeed(true)
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const tx = createTx({
|
|
33
|
+
* retriever: myRetriever // optional override
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export * from "@tx/core";
|
|
38
|
+
export { createTx, type CreateTxOptions, type TxClient } from "./create-tx.js";
|
|
39
|
+
export type { TaskStatus, TaskId, Task, TaskWithDeps, TaskTree, TaskDependency, CreateTaskInput, UpdateTaskInput, TaskFilter, LearningSourceType, LearningId, Learning, LearningWithScore, CreateLearningInput, UpdateLearningInput, LearningQuery, ContextOptions, ContextResult, RetrievalOptions, AttemptOutcome, AttemptId, Attempt, CreateAttemptInput, RunId, RunStatus, Run, CreateRunInput, UpdateRunInput, AnchorId, AnchorType, AnchorStatus, Anchor, CreateAnchorInput, EdgeId, NodeType, EdgeType, Edge, CreateEdgeInput, } from "@tx/types";
|
|
40
|
+
export { TASK_STATUSES, VALID_TRANSITIONS, LEARNING_SOURCE_TYPES, ATTEMPT_OUTCOMES, RUN_STATUSES, ANCHOR_TYPES, ANCHOR_STATUSES, NODE_TYPES, EDGE_TYPES, } from "@tx/types";
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,cAAc,UAAU,CAAC;AAGzB,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG/E,YAAY,EAEV,UAAU,EACV,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,eAAe,EACf,eAAe,EACf,UAAU,EAEV,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,aAAa,EACb,gBAAgB,EAEhB,cAAc,EACd,SAAS,EACT,OAAO,EACP,kBAAkB,EAElB,KAAK,EACL,SAAS,EACT,GAAG,EACH,cAAc,EACd,cAAc,EAEd,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,MAAM,EACN,iBAAiB,EAEjB,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,eAAe,GAChB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,UAAU,EACV,UAAU,GACX,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @jamesaphoenix/tx - TanStack for AI agents
|
|
3
|
+
*
|
|
4
|
+
* Headless primitives for memory, tasks, and orchestration.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { TaskService, LearningService, makeAppLayer } from "@jamesaphoenix/tx";
|
|
9
|
+
* import { Effect } from "effect";
|
|
10
|
+
*
|
|
11
|
+
* const program = Effect.gen(function* () {
|
|
12
|
+
* const tasks = yield* TaskService;
|
|
13
|
+
* const ready = yield* tasks.getReady({ limit: 5 });
|
|
14
|
+
* return ready;
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Custom Retriever
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { createTx, RetrieverService } from "@jamesaphoenix/tx";
|
|
21
|
+
* import { Effect, Layer } from "effect";
|
|
22
|
+
*
|
|
23
|
+
* // Custom Pinecone retriever
|
|
24
|
+
* const myRetriever = Layer.succeed(RetrieverService, {
|
|
25
|
+
* search: (query, options) => Effect.gen(function* () {
|
|
26
|
+
* const results = yield* pineconeQuery(query);
|
|
27
|
+
* return results.map(toLearningWithScore);
|
|
28
|
+
* }),
|
|
29
|
+
* isAvailable: () => Effect.succeed(true)
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const tx = createTx({
|
|
33
|
+
* retriever: myRetriever // optional override
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
// Re-export everything from @tx/core
|
|
38
|
+
export * from "@tx/core";
|
|
39
|
+
// Export createTx and related types
|
|
40
|
+
export { createTx } from "./create-tx.js";
|
|
41
|
+
// Re-export constants from types
|
|
42
|
+
export { TASK_STATUSES, VALID_TRANSITIONS, LEARNING_SOURCE_TYPES, ATTEMPT_OUTCOMES, RUN_STATUSES, ANCHOR_TYPES, ANCHOR_STATUSES, NODE_TYPES, EDGE_TYPES, } from "@tx/types";
|
|
17
43
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,qCAAqC;AACrC,cAAc,UAAU,CAAC;AAEzB,oCAAoC;AACpC,OAAO,EAAE,QAAQ,EAAuC,MAAM,gBAAgB,CAAC;AAkD/E,iCAAiC;AACjC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,UAAU,EACV,UAAU,GACX,MAAM,WAAW,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-only exports for @jamesaphoenix/tx
|
|
3
|
+
*
|
|
4
|
+
* Use this for type-only imports when you don't need runtime code.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import type { Task, Learning } from "@jamesaphoenix/tx/types";
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export * from "@tx/types";
|
|
12
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,WAAW,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-only exports for @jamesaphoenix/tx
|
|
3
|
+
*
|
|
4
|
+
* Use this for type-only imports when you don't need runtime code.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import type { Task, Learning } from "@jamesaphoenix/tx/types";
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export * from "@tx/types";
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jamesaphoenix/tx",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "TanStack for AI agents - headless primitives for memory, tasks, and orchestration",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"tx": "./dist/cli.js"
|
|
8
|
-
},
|
|
9
6
|
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./types": {
|
|
14
|
+
"types": "./dist/types.d.ts",
|
|
15
|
+
"import": "./dist/types.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
10
18
|
"files": [
|
|
11
19
|
"dist",
|
|
12
|
-
"
|
|
20
|
+
"README.md"
|
|
13
21
|
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -b",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@tx/core": "*",
|
|
29
|
+
"@tx/types": "*"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"better-sqlite3": "^11.0.0",
|
|
33
|
+
"effect": "^3.0.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependenciesMeta": {
|
|
36
|
+
"better-sqlite3": {
|
|
37
|
+
"optional": false
|
|
38
|
+
}
|
|
39
|
+
},
|
|
14
40
|
"repository": {
|
|
15
41
|
"type": "git",
|
|
16
42
|
"url": "https://github.com/jamesaphoenix/tx.git"
|
|
@@ -18,35 +44,10 @@
|
|
|
18
44
|
"keywords": [
|
|
19
45
|
"task-management",
|
|
20
46
|
"ai-agents",
|
|
21
|
-
"cli",
|
|
22
47
|
"effect-ts",
|
|
23
|
-
"mcp"
|
|
48
|
+
"mcp",
|
|
49
|
+
"orchestration"
|
|
24
50
|
],
|
|
25
51
|
"author": "James Phoenix",
|
|
26
|
-
"license": "MIT"
|
|
27
|
-
"scripts": {
|
|
28
|
-
"build": "tsc",
|
|
29
|
-
"dev": "tsx src/cli.ts",
|
|
30
|
-
"test": "vitest --run",
|
|
31
|
-
"test:watch": "vitest",
|
|
32
|
-
"validate": "npm run build && npm test && npm link"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@effect/cli": "^0.73.1",
|
|
36
|
-
"@effect/platform": "^0.94.2",
|
|
37
|
-
"@effect/platform-node": "^0.104.1",
|
|
38
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
39
|
-
"better-sqlite3": "^11.7.0",
|
|
40
|
-
"effect": "^3.19.15"
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@types/better-sqlite3": "^7.6.12",
|
|
44
|
-
"@types/node": "^22.10.0",
|
|
45
|
-
"tsx": "^4.19.0",
|
|
46
|
-
"typescript": "^5.7.0",
|
|
47
|
-
"vitest": "^3.0.0"
|
|
48
|
-
},
|
|
49
|
-
"engines": {
|
|
50
|
-
"node": ">=20"
|
|
51
|
-
}
|
|
52
|
+
"license": "MIT"
|
|
52
53
|
}
|