@providerprotocol/agents 0.0.1 → 0.0.3

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.
Files changed (74) hide show
  1. package/README.md +333 -6
  2. package/dist/checkpoint/index.d.ts +43 -0
  3. package/dist/checkpoint/index.js +64 -0
  4. package/dist/checkpoint/index.js.map +1 -0
  5. package/{src/execution/loop.ts → dist/chunk-4ESYN66B.js} +54 -162
  6. package/dist/chunk-4ESYN66B.js.map +1 -0
  7. package/dist/chunk-EKRXMSDX.js +8 -0
  8. package/dist/chunk-EKRXMSDX.js.map +1 -0
  9. package/dist/chunk-PHI5ULBV.js +427 -0
  10. package/dist/chunk-PHI5ULBV.js.map +1 -0
  11. package/dist/execution/index.d.ts +105 -0
  12. package/dist/execution/index.js +679 -0
  13. package/dist/execution/index.js.map +1 -0
  14. package/dist/index-qsPwbY86.d.ts +65 -0
  15. package/dist/index.d.ts +101 -0
  16. package/dist/index.js +218 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/middleware/index.d.ts +23 -0
  19. package/dist/middleware/index.js +82 -0
  20. package/dist/middleware/index.js.map +1 -0
  21. package/dist/thread-tree/index.d.ts +115 -0
  22. package/dist/thread-tree/index.js +4 -0
  23. package/dist/thread-tree/index.js.map +1 -0
  24. package/dist/types-2Vsthzyu.d.ts +163 -0
  25. package/dist/types-BhX9uD_d.d.ts +91 -0
  26. package/dist/types-DR02gtFv.d.ts +270 -0
  27. package/dist/types-NGQMdnaD.d.ts +65 -0
  28. package/package.json +40 -8
  29. package/.claude/settings.local.json +0 -27
  30. package/AGENTS.md +0 -681
  31. package/CLAUDE.md +0 -681
  32. package/bun.lock +0 -472
  33. package/eslint.config.js +0 -75
  34. package/index.ts +0 -1
  35. package/llms.md +0 -796
  36. package/specs/UAP-1.0.md +0 -2355
  37. package/src/agent/index.ts +0 -384
  38. package/src/agent/types.ts +0 -91
  39. package/src/checkpoint/file.ts +0 -126
  40. package/src/checkpoint/index.ts +0 -40
  41. package/src/checkpoint/types.ts +0 -95
  42. package/src/execution/index.ts +0 -37
  43. package/src/execution/plan.ts +0 -497
  44. package/src/execution/react.ts +0 -340
  45. package/src/execution/tool-ordering.ts +0 -186
  46. package/src/execution/types.ts +0 -315
  47. package/src/index.ts +0 -80
  48. package/src/middleware/index.ts +0 -7
  49. package/src/middleware/logging.ts +0 -123
  50. package/src/middleware/types.ts +0 -69
  51. package/src/state/index.ts +0 -301
  52. package/src/state/types.ts +0 -173
  53. package/src/thread-tree/index.ts +0 -249
  54. package/src/thread-tree/types.ts +0 -29
  55. package/src/utils/uuid.ts +0 -7
  56. package/tests/live/agent-anthropic.test.ts +0 -288
  57. package/tests/live/agent-strategy-hooks.test.ts +0 -268
  58. package/tests/live/checkpoint.test.ts +0 -243
  59. package/tests/live/execution-strategies.test.ts +0 -255
  60. package/tests/live/plan-strategy.test.ts +0 -160
  61. package/tests/live/subagent-events.live.test.ts +0 -249
  62. package/tests/live/thread-tree.test.ts +0 -186
  63. package/tests/unit/agent.test.ts +0 -703
  64. package/tests/unit/checkpoint.test.ts +0 -232
  65. package/tests/unit/execution/equivalence.test.ts +0 -402
  66. package/tests/unit/execution/loop.test.ts +0 -437
  67. package/tests/unit/execution/plan.test.ts +0 -590
  68. package/tests/unit/execution/react.test.ts +0 -604
  69. package/tests/unit/execution/subagent-events.test.ts +0 -235
  70. package/tests/unit/execution/tool-ordering.test.ts +0 -310
  71. package/tests/unit/middleware/logging.test.ts +0 -276
  72. package/tests/unit/state.test.ts +0 -573
  73. package/tests/unit/thread-tree.test.ts +0 -249
  74. package/tsconfig.json +0 -29
package/README.md CHANGED
@@ -1,15 +1,342 @@
1
- # providerprotocol-agents
1
+ # @providerprotocol/agents
2
2
 
3
- To install dependencies:
3
+ A powerful, flexible agent framework implementing the Unified Agent Protocol (UAP) 1.0. Built on top of [@providerprotocol/ai](https://github.com/providerprotocol/ai) for seamless multi-provider LLM support.
4
+
5
+ ## Features
6
+
7
+ - **Functional State Management** - Immutable state with explicit data flow
8
+ - **Execution Strategies** - Choose from `loop`, `react`, or `plan` patterns
9
+ - **Middleware Pipeline** - Composable before/after hooks for logging, guardrails, etc.
10
+ - **Multi-Provider Support** - Works with Anthropic, OpenAI, Google, Ollama, and more
11
+ - **Streaming** - Full streaming support with UAP and UPP events
12
+ - **Checkpointing** - Built-in session persistence and recovery
13
+ - **Thread Trees** - Branching conversation support
14
+ - **Type-Safe** - 100% TypeScript with full type inference
15
+
16
+ ## Installation
4
17
 
5
18
  ```bash
6
- bun install
19
+ bun install @providerprotocol/agents @providerprotocol/ai
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ```typescript
25
+ import { agent, AgentState } from '@providerprotocol/agents';
26
+ import { anthropic } from '@providerprotocol/ai/anthropic';
27
+
28
+ // Create an agent
29
+ const assistant = agent({
30
+ model: anthropic('claude-sonnet-4-20250514'),
31
+ params: { max_tokens: 4096 },
32
+ system: 'You are a helpful assistant.',
33
+ });
34
+
35
+ // Single query (stateless)
36
+ const turn = await assistant.query('What is the capital of France?');
37
+ console.log(turn.response.text);
38
+
39
+ // Multi-turn conversation (stateful)
40
+ let state = AgentState.initial();
41
+ const r1 = await assistant.ask('My name is Alice.', state);
42
+ state = r1.state;
43
+
44
+ const r2 = await assistant.ask('What is my name?', state);
45
+ console.log(r2.turn.response.text); // "Alice"
46
+ ```
47
+
48
+ ## Adding Tools
49
+
50
+ ```typescript
51
+ import { agent, AgentState } from '@providerprotocol/agents';
52
+ import { anthropic } from '@providerprotocol/ai/anthropic';
53
+
54
+ const calculator = {
55
+ name: 'calculate',
56
+ description: 'Evaluate a math expression',
57
+ parameters: {
58
+ type: 'object' as const,
59
+ properties: {
60
+ expression: { type: 'string' as const },
61
+ },
62
+ required: ['expression'],
63
+ },
64
+ run: async (params: { expression: string }) => {
65
+ // Use a proper math parser in production
66
+ return String(eval(params.expression));
67
+ },
68
+ };
69
+
70
+ const mathBot = agent({
71
+ model: anthropic('claude-sonnet-4-20250514'),
72
+ params: { max_tokens: 1000 },
73
+ tools: [calculator],
74
+ });
75
+
76
+ const turn = await mathBot.query('What is 42 * 17?');
77
+ console.log(turn.response.text);
78
+ console.log(turn.toolExecutions); // Shows calculator was used
79
+ ```
80
+
81
+ ## Execution Strategies
82
+
83
+ Choose how your agent thinks and acts:
84
+
85
+ ### Loop (Default)
86
+
87
+ Simple tool loop - keeps executing until no more tool calls.
88
+
89
+ ```typescript
90
+ import { loop } from '@providerprotocol/agents/execution';
91
+
92
+ const myAgent = agent({
93
+ model: anthropic('claude-sonnet-4-20250514'),
94
+ execution: loop({ maxIterations: 10 }),
95
+ });
96
+ ```
97
+
98
+ ### ReAct
99
+
100
+ Reason-Act-Observe pattern with explicit reasoning phase.
101
+
102
+ ```typescript
103
+ import { react } from '@providerprotocol/agents/execution';
104
+
105
+ const myAgent = agent({
106
+ model: anthropic('claude-sonnet-4-20250514'),
107
+ execution: react({ maxSteps: 20 }),
108
+ });
109
+ ```
110
+
111
+ ### Plan
112
+
113
+ Generate a structured plan, then execute steps with dependencies.
114
+
115
+ ```typescript
116
+ import { plan } from '@providerprotocol/agents/execution';
117
+
118
+ const myAgent = agent({
119
+ model: anthropic('claude-sonnet-4-20250514'),
120
+ execution: plan({ maxPlanSteps: 10, allowReplan: true }),
121
+ });
122
+ ```
123
+
124
+ ## Streaming
125
+
126
+ ```typescript
127
+ const stream = myAgent.stream('Explain quantum computing', state);
128
+
129
+ for await (const event of stream) {
130
+ if (event.source === 'upp' && event.upp?.type === 'text_delta') {
131
+ process.stdout.write(event.upp.delta.text ?? '');
132
+ }
133
+ }
134
+
135
+ const { turn, state: newState } = await stream.result;
136
+ ```
137
+
138
+ ## Middleware
139
+
140
+ ```typescript
141
+ import { logging } from '@providerprotocol/agents/middleware';
142
+
143
+ const myAgent = agent({
144
+ model: anthropic('claude-sonnet-4-20250514'),
145
+ middleware: [
146
+ logging({ level: 'info', includeTiming: true }),
147
+ ],
148
+ });
149
+ ```
150
+
151
+ Create custom middleware:
152
+
153
+ ```typescript
154
+ import type { Middleware } from '@providerprotocol/agents/middleware';
155
+
156
+ const rateLimiter: Middleware = {
157
+ name: 'rate-limiter',
158
+ async before(context) {
159
+ await checkRateLimit(context.agent.id);
160
+ return context;
161
+ },
162
+ async after(context, result) {
163
+ recordUsage(result.turn.usage);
164
+ return result;
165
+ },
166
+ };
7
167
  ```
8
168
 
9
- To run:
169
+ ## Checkpointing
170
+
171
+ Persist agent sessions for recovery:
172
+
173
+ ```typescript
174
+ import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';
175
+
176
+ const store = fileCheckpoints({ dir: '.checkpoints' });
177
+
178
+ const myAgent = agent({
179
+ model: anthropic('claude-sonnet-4-20250514'),
180
+ checkpoints: store,
181
+ sessionId: 'my-session',
182
+ });
183
+
184
+ // Execute - state automatically saved after each step
185
+ await myAgent.generate('Hello', AgentState.initial());
186
+
187
+ // Later: restore and continue
188
+ const saved = await store.load('my-session');
189
+ if (saved) {
190
+ const state = AgentState.fromJSON(saved);
191
+ await myAgent.generate('Continue...', state);
192
+ }
193
+ ```
194
+
195
+ ## Lifecycle Hooks
196
+
197
+ ```typescript
198
+ const myAgent = agent({
199
+ model: anthropic('claude-sonnet-4-20250514'),
200
+ strategy: {
201
+ stopCondition: (state) => state.step > 50,
202
+ onStepStart: (step, state) => console.log(`Step ${step}`),
203
+ onAct: (step, toolCalls) => console.log('Tools:', toolCalls),
204
+ onComplete: (result) => console.log('Done!'),
205
+ onError: (error, state) => console.error(error),
206
+ },
207
+ });
208
+ ```
209
+
210
+ ## Provider Support
211
+
212
+ Works with all providers from `@providerprotocol/ai`:
213
+
214
+ ```typescript
215
+ import { anthropic } from '@providerprotocol/ai/anthropic';
216
+ import { openai } from '@providerprotocol/ai/openai';
217
+ import { google } from '@providerprotocol/ai/google';
218
+ import { ollama } from '@providerprotocol/ai/ollama';
219
+
220
+ // Anthropic
221
+ agent({ model: anthropic('claude-sonnet-4-20250514'), params: { max_tokens: 4096 } });
222
+
223
+ // OpenAI
224
+ agent({ model: openai('gpt-4o'), params: { max_output_tokens: 4096 } });
225
+
226
+ // Google
227
+ agent({ model: google('gemini-2.0-flash'), params: { maxOutputTokens: 4096 } });
228
+
229
+ // Ollama (local)
230
+ agent({ model: ollama('llama3:8b'), params: { num_predict: 4096 } });
231
+ ```
232
+
233
+ ## Environment Variables
234
+
235
+ Create a `.env` file with your API keys:
236
+
237
+ ```env
238
+ ANTHROPIC_API_KEY=sk-ant-...
239
+ OPENAI_API_KEY=sk-...
240
+ GOOGLE_API_KEY=AI...
241
+ ```
242
+
243
+ ## API Reference
244
+
245
+ ### agent(options)
246
+
247
+ Creates an agent instance.
248
+
249
+ | Option | Type | Description |
250
+ |--------|------|-------------|
251
+ | `model` | `ModelReference` | Required. Model from UPP provider |
252
+ | `params` | `object` | LLM parameters (provider-specific) |
253
+ | `system` | `string` | System prompt |
254
+ | `tools` | `Tool[]` | Available tools |
255
+ | `execution` | `ExecutionStrategy` | Strategy: `loop()`, `react()`, `plan()` |
256
+ | `middleware` | `Middleware[]` | Middleware pipeline |
257
+ | `strategy` | `AgentStrategy` | Lifecycle hooks |
258
+ | `checkpoints` | `CheckpointStore` | Session persistence |
259
+ | `sessionId` | `string` | Session identifier |
260
+
261
+ ### Agent Methods
262
+
263
+ | Method | Returns | Description |
264
+ |--------|---------|-------------|
265
+ | `generate(input, state)` | `Promise<GenerateResult>` | Execute with state |
266
+ | `stream(input, state)` | `AgentStreamResult` | Stream execution |
267
+ | `ask(input, state)` | `Promise<GenerateResult>` | Multi-turn convenience |
268
+ | `query(input)` | `Promise<Turn>` | Stateless single-turn |
269
+
270
+ ### AgentState
271
+
272
+ Immutable state with chainable operations:
273
+
274
+ ```typescript
275
+ state.withMessage(msg) // Add message
276
+ state.withMessages(msgs) // Add messages
277
+ state.withContext(msgs) // Replace all messages
278
+ state.withStep(n) // Set step number
279
+ state.withMetadata(k, v) // Add metadata
280
+ state.withReasoning(text) // Add reasoning trace
281
+ state.withPlan(steps) // Set execution plan
282
+ state.toJSON() // Serialize
283
+ AgentState.fromJSON(json) // Deserialize
284
+ ```
285
+
286
+ ## Examples
287
+
288
+ See the [`examples/`](./examples) directory for complete examples:
289
+
290
+ - **coding-agent** - A Claude Code-style coding assistant with file operations, bash, search, and sub-agents
291
+
292
+ Run the coding agent example:
10
293
 
11
294
  ```bash
12
- bun run index.ts
295
+ ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts "List all TypeScript files"
13
296
  ```
14
297
 
15
- This project was created using `bun init` in bun v1.3.5. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
298
+ Interactive mode:
299
+
300
+ ```bash
301
+ ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts -i
302
+ ```
303
+
304
+ TUI mode:
305
+
306
+ ```bash
307
+ ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts --tui
308
+ ```
309
+
310
+ ## Testing
311
+
312
+ ```bash
313
+ bun test # All tests
314
+ bun test:unit # Unit tests
315
+ bun test:live # Live API tests
316
+ bun lint # Lint
317
+ bun typecheck # Type check
318
+ ```
319
+
320
+ ## Philosophy
321
+
322
+ **"UAP is a pipe, not a nanny."**
323
+
324
+ This framework provides orchestration primitives with sensible defaults but no artificial limits. By default:
325
+
326
+ - Execution continues until naturally complete (no max iterations)
327
+ - State is explicit and immutable
328
+ - All UPP types flow through without abstraction
329
+ - You control safety, budgets, and constraints
330
+
331
+ ## Documentation
332
+
333
+ - [llms.md](./llms.md) - Comprehensive API documentation for LLMs and developers
334
+ - [CLAUDE.md](./CLAUDE.md) - Project coding guidelines and @providerprotocol/ai usage
335
+
336
+ ## License
337
+
338
+ MIT
339
+
340
+ ## Related
341
+
342
+ - [@providerprotocol/ai](https://github.com/providerprotocol/ai) - Unified Provider Protocol for LLM inference
@@ -0,0 +1,43 @@
1
+ import { F as FileCheckpointOptions, C as CheckpointStore } from '../types-BhX9uD_d.js';
2
+ export { b as CheckpointData, a as CheckpointMetadata } from '../types-BhX9uD_d.js';
3
+ import '../types-2Vsthzyu.js';
4
+ import '@providerprotocol/ai';
5
+
6
+ /**
7
+ * File-based Checkpoint Store
8
+ *
9
+ * Reference implementation of CheckpointStore using the filesystem.
10
+ *
11
+ * @see UAP-1.0 Spec Section 12.4.3
12
+ */
13
+
14
+ /**
15
+ * Create a file-based checkpoint store.
16
+ *
17
+ * Stores checkpoints as JSON files in a directory structure:
18
+ * ```
19
+ * {dir}/
20
+ * {sessionId}/
21
+ * checkpoint.json # Latest state
22
+ * metadata.json # Session metadata
23
+ * ```
24
+ *
25
+ * @param options - Configuration options
26
+ * @returns CheckpointStore implementation
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';
31
+ *
32
+ * const store = fileCheckpoints({ dir: './my-checkpoints' });
33
+ *
34
+ * // Save a checkpoint
35
+ * await store.save('session-123', state.toJSON());
36
+ *
37
+ * // Load a checkpoint
38
+ * const saved = await store.load('session-123');
39
+ * ```
40
+ */
41
+ declare function fileCheckpoints(options?: FileCheckpointOptions): CheckpointStore;
42
+
43
+ export { CheckpointStore, FileCheckpointOptions, fileCheckpoints };
@@ -0,0 +1,64 @@
1
+ import { generateUUID } from '../chunk-EKRXMSDX.js';
2
+ import { mkdir, readdir, rm, readFile, writeFile } from 'fs/promises';
3
+ import { join } from 'path';
4
+
5
+ var DEFAULT_DIR = ".checkpoints";
6
+ function fileCheckpoints(options = {}) {
7
+ const dir = options.dir ?? DEFAULT_DIR;
8
+ async function ensureSessionDir(sessionId) {
9
+ const sessionDir = join(dir, sessionId);
10
+ await mkdir(sessionDir, { recursive: true });
11
+ return sessionDir;
12
+ }
13
+ function getPaths(sessionId) {
14
+ const sessionDir = join(dir, sessionId);
15
+ return {
16
+ checkpointPath: join(sessionDir, "checkpoint.json"),
17
+ metadataPath: join(sessionDir, "metadata.json")
18
+ };
19
+ }
20
+ return {
21
+ async save(sessionId, state) {
22
+ await ensureSessionDir(sessionId);
23
+ const { checkpointPath, metadataPath } = getPaths(sessionId);
24
+ const metadata = {
25
+ sessionId,
26
+ checkpointId: generateUUID(),
27
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
28
+ step: state.step,
29
+ agentId: state.metadata.agentId ?? "unknown"
30
+ };
31
+ await writeFile(checkpointPath, JSON.stringify(state, null, 2), "utf-8");
32
+ await writeFile(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
33
+ },
34
+ async load(sessionId) {
35
+ const { checkpointPath } = getPaths(sessionId);
36
+ try {
37
+ const content = await readFile(checkpointPath, "utf-8");
38
+ return JSON.parse(content);
39
+ } catch {
40
+ return null;
41
+ }
42
+ },
43
+ async delete(sessionId) {
44
+ const sessionDir = join(dir, sessionId);
45
+ try {
46
+ await rm(sessionDir, { recursive: true, force: true });
47
+ } catch {
48
+ }
49
+ },
50
+ async list() {
51
+ try {
52
+ await mkdir(dir, { recursive: true });
53
+ const entries = await readdir(dir, { withFileTypes: true });
54
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
55
+ } catch {
56
+ return [];
57
+ }
58
+ }
59
+ };
60
+ }
61
+
62
+ export { fileCheckpoints };
63
+ //# sourceMappingURL=index.js.map
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/checkpoint/file.ts"],"names":[],"mappings":";;;;AAcA,IAAM,WAAA,GAAc,cAAA;AA6Bb,SAAS,eAAA,CAAgB,OAAA,GAAiC,EAAC,EAAoB;AACpF,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,IAAO,WAAA;AAK3B,EAAA,eAAe,iBAAiB,SAAA,EAAoC;AAClE,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA;AACtC,IAAA,MAAM,KAAA,CAAM,UAAA,EAAY,EAAE,SAAA,EAAW,MAAM,CAAA;AAC3C,IAAA,OAAO,UAAA;AAAA,EACT;AAKA,EAAA,SAAS,SAAS,SAAA,EAAqE;AACrF,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA;AACtC,IAAA,OAAO;AAAA,MACL,cAAA,EAAgB,IAAA,CAAK,UAAA,EAAY,iBAAiB,CAAA;AAAA,MAClD,YAAA,EAAc,IAAA,CAAK,UAAA,EAAY,eAAe;AAAA,KAChD;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,SAAA,EAAmB,KAAA,EAAsC;AAClE,MAAA,MAAM,iBAAiB,SAAS,CAAA;AAChC,MAAA,MAAM,EAAE,cAAA,EAAgB,YAAA,EAAa,GAAI,SAAS,SAAS,CAAA;AAG3D,MAAA,MAAM,QAAA,GAA+B;AAAA,QACnC,SAAA;AAAA,QACA,cAAc,YAAA,EAAa;AAAA,QAC3B,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,OAAA,EAAS,KAAA,CAAM,QAAA,CAAS,OAAA,IAAqB;AAAA,OAC/C;AAGA,MAAA,MAAM,SAAA,CAAU,gBAAgB,IAAA,CAAK,SAAA,CAAU,OAAO,IAAA,EAAM,CAAC,GAAG,OAAO,CAAA;AACvE,MAAA,MAAM,SAAA,CAAU,cAAc,IAAA,CAAK,SAAA,CAAU,UAAU,IAAA,EAAM,CAAC,GAAG,OAAO,CAAA;AAAA,IAC1E,CAAA;AAAA,IAEA,MAAM,KAAK,SAAA,EAAmD;AAC5D,MAAA,MAAM,EAAE,cAAA,EAAe,GAAI,QAAA,CAAS,SAAS,CAAA;AAE7C,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,cAAA,EAAgB,OAAO,CAAA;AACtD,QAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC3B,CAAA,CAAA,MAAQ;AAEN,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,OAAO,SAAA,EAAkC;AAC7C,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA;AACtC,MAAA,IAAI;AACF,QAAA,MAAM,GAAG,UAAA,EAAY,EAAE,WAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAAA,MACvD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,IAAA,GAA0B;AAC9B,MAAA,IAAI;AAEF,QAAA,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAEpC,QAAA,MAAM,UAAU,MAAM,OAAA,CAAQ,KAAK,EAAE,aAAA,EAAe,MAAM,CAAA;AAC1D,QAAA,OAAO,OAAA,CACJ,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,WAAA,EAAa,CAAA,CACrC,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,IAAI,CAAA;AAAA,MAC9B,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,EAAC;AAAA,MACV;AAAA,IACF;AAAA,GACF;AACF","file":"index.js","sourcesContent":["/**\n * File-based Checkpoint Store\n *\n * Reference implementation of CheckpointStore using the filesystem.\n *\n * @see UAP-1.0 Spec Section 12.4.3\n */\n\nimport { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { AgentStateJSON } from '../state/types.ts';\nimport type { CheckpointStore, FileCheckpointOptions, CheckpointMetadata } from './types.ts';\nimport { generateUUID } from '../utils/uuid.ts';\n\nconst DEFAULT_DIR = '.checkpoints';\n\n/**\n * Create a file-based checkpoint store.\n *\n * Stores checkpoints as JSON files in a directory structure:\n * ```\n * {dir}/\n * {sessionId}/\n * checkpoint.json # Latest state\n * metadata.json # Session metadata\n * ```\n *\n * @param options - Configuration options\n * @returns CheckpointStore implementation\n *\n * @example\n * ```typescript\n * import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';\n *\n * const store = fileCheckpoints({ dir: './my-checkpoints' });\n *\n * // Save a checkpoint\n * await store.save('session-123', state.toJSON());\n *\n * // Load a checkpoint\n * const saved = await store.load('session-123');\n * ```\n */\nexport function fileCheckpoints(options: FileCheckpointOptions = {}): CheckpointStore {\n const dir = options.dir ?? DEFAULT_DIR;\n\n /**\n * Ensure session directory exists.\n */\n async function ensureSessionDir(sessionId: string): Promise<string> {\n const sessionDir = join(dir, sessionId);\n await mkdir(sessionDir, { recursive: true });\n return sessionDir;\n }\n\n /**\n * Get paths for checkpoint files.\n */\n function getPaths(sessionId: string): { checkpointPath: string; metadataPath: string } {\n const sessionDir = join(dir, sessionId);\n return {\n checkpointPath: join(sessionDir, 'checkpoint.json'),\n metadataPath: join(sessionDir, 'metadata.json'),\n };\n }\n\n return {\n async save(sessionId: string, state: AgentStateJSON): Promise<void> {\n await ensureSessionDir(sessionId);\n const { checkpointPath, metadataPath } = getPaths(sessionId);\n\n // Build metadata\n const metadata: CheckpointMetadata = {\n sessionId,\n checkpointId: generateUUID(),\n timestamp: new Date().toISOString(),\n step: state.step,\n agentId: state.metadata.agentId as string ?? 'unknown',\n };\n\n // Write checkpoint first, then metadata (sequential to avoid race conditions)\n await writeFile(checkpointPath, JSON.stringify(state, null, 2), 'utf-8');\n await writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8');\n },\n\n async load(sessionId: string): Promise<AgentStateJSON | null> {\n const { checkpointPath } = getPaths(sessionId);\n\n try {\n const content = await readFile(checkpointPath, 'utf-8');\n return JSON.parse(content) as AgentStateJSON;\n } catch {\n // File doesn't exist or is invalid\n return null;\n }\n },\n\n async delete(sessionId: string): Promise<void> {\n const sessionDir = join(dir, sessionId);\n try {\n await rm(sessionDir, { recursive: true, force: true });\n } catch {\n // Directory might not exist, ignore\n }\n },\n\n async list(): Promise<string[]> {\n try {\n // Ensure base directory exists\n await mkdir(dir, { recursive: true });\n\n const entries = await readdir(dir, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name);\n } catch {\n return [];\n }\n },\n };\n}\n"]}