@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.
- package/README.md +333 -6
- package/dist/checkpoint/index.d.ts +43 -0
- package/dist/checkpoint/index.js +64 -0
- package/dist/checkpoint/index.js.map +1 -0
- package/{src/execution/loop.ts → dist/chunk-4ESYN66B.js} +54 -162
- package/dist/chunk-4ESYN66B.js.map +1 -0
- package/dist/chunk-EKRXMSDX.js +8 -0
- package/dist/chunk-EKRXMSDX.js.map +1 -0
- package/dist/chunk-PHI5ULBV.js +427 -0
- package/dist/chunk-PHI5ULBV.js.map +1 -0
- package/dist/execution/index.d.ts +105 -0
- package/dist/execution/index.js +679 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/index-qsPwbY86.d.ts +65 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.js +218 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/index.d.ts +23 -0
- package/dist/middleware/index.js +82 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/thread-tree/index.d.ts +115 -0
- package/dist/thread-tree/index.js +4 -0
- package/dist/thread-tree/index.js.map +1 -0
- package/dist/types-2Vsthzyu.d.ts +163 -0
- package/dist/types-BhX9uD_d.d.ts +91 -0
- package/dist/types-DR02gtFv.d.ts +270 -0
- package/dist/types-NGQMdnaD.d.ts +65 -0
- package/package.json +40 -8
- package/.claude/settings.local.json +0 -27
- package/AGENTS.md +0 -681
- package/CLAUDE.md +0 -681
- package/bun.lock +0 -472
- package/eslint.config.js +0 -75
- package/index.ts +0 -1
- package/llms.md +0 -796
- package/specs/UAP-1.0.md +0 -2355
- package/src/agent/index.ts +0 -384
- package/src/agent/types.ts +0 -91
- package/src/checkpoint/file.ts +0 -126
- package/src/checkpoint/index.ts +0 -40
- package/src/checkpoint/types.ts +0 -95
- package/src/execution/index.ts +0 -37
- package/src/execution/plan.ts +0 -497
- package/src/execution/react.ts +0 -340
- package/src/execution/tool-ordering.ts +0 -186
- package/src/execution/types.ts +0 -315
- package/src/index.ts +0 -80
- package/src/middleware/index.ts +0 -7
- package/src/middleware/logging.ts +0 -123
- package/src/middleware/types.ts +0 -69
- package/src/state/index.ts +0 -301
- package/src/state/types.ts +0 -173
- package/src/thread-tree/index.ts +0 -249
- package/src/thread-tree/types.ts +0 -29
- package/src/utils/uuid.ts +0 -7
- package/tests/live/agent-anthropic.test.ts +0 -288
- package/tests/live/agent-strategy-hooks.test.ts +0 -268
- package/tests/live/checkpoint.test.ts +0 -243
- package/tests/live/execution-strategies.test.ts +0 -255
- package/tests/live/plan-strategy.test.ts +0 -160
- package/tests/live/subagent-events.live.test.ts +0 -249
- package/tests/live/thread-tree.test.ts +0 -186
- package/tests/unit/agent.test.ts +0 -703
- package/tests/unit/checkpoint.test.ts +0 -232
- package/tests/unit/execution/equivalence.test.ts +0 -402
- package/tests/unit/execution/loop.test.ts +0 -437
- package/tests/unit/execution/plan.test.ts +0 -590
- package/tests/unit/execution/react.test.ts +0 -604
- package/tests/unit/execution/subagent-events.test.ts +0 -235
- package/tests/unit/execution/tool-ordering.test.ts +0 -310
- package/tests/unit/middleware/logging.test.ts +0 -276
- package/tests/unit/state.test.ts +0 -573
- package/tests/unit/thread-tree.test.ts +0 -249
- package/tsconfig.json +0 -29
package/src/agent/index.ts
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
llm,
|
|
3
|
-
UserMessage,
|
|
4
|
-
} from '@providerprotocol/ai';
|
|
5
|
-
import type {
|
|
6
|
-
LLMInstance,
|
|
7
|
-
Message,
|
|
8
|
-
Turn,
|
|
9
|
-
} from '@providerprotocol/ai';
|
|
10
|
-
import { generateUUID } from '../utils/uuid.ts';
|
|
11
|
-
import { AgentState } from '../state/index.ts';
|
|
12
|
-
import { loop } from '../execution/loop.ts';
|
|
13
|
-
import type {
|
|
14
|
-
ExecutionContext,
|
|
15
|
-
GenerateResult,
|
|
16
|
-
AgentStreamResult,
|
|
17
|
-
AgentStrategy,
|
|
18
|
-
} from '../execution/types.ts';
|
|
19
|
-
import type { Middleware, MiddlewareContext } from '../middleware/types.ts';
|
|
20
|
-
import type { Agent, AgentOptions } from './types.ts';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Create an agent instance.
|
|
24
|
-
*
|
|
25
|
-
* @param options - Agent configuration
|
|
26
|
-
* @returns Agent instance
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```typescript
|
|
30
|
-
* import { agent, AgentState } from '@providerprotocol/agents';
|
|
31
|
-
* import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
32
|
-
*
|
|
33
|
-
* const coder = agent({
|
|
34
|
-
* model: anthropic('claude-sonnet-4-20250514'),
|
|
35
|
-
* tools: [Bash, Read, Write],
|
|
36
|
-
* system: 'You are a coding assistant.',
|
|
37
|
-
* });
|
|
38
|
-
*
|
|
39
|
-
* const state = AgentState.initial();
|
|
40
|
-
* const { turn, state: newState } = await coder.generate('Hello', state);
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
export function agent(options: AgentOptions): Agent {
|
|
44
|
-
const {
|
|
45
|
-
// UAP-specific options
|
|
46
|
-
execution = loop(),
|
|
47
|
-
middleware = [],
|
|
48
|
-
strategy = {},
|
|
49
|
-
checkpoints,
|
|
50
|
-
sessionId: providedSessionId,
|
|
51
|
-
_llmInstance,
|
|
52
|
-
// LLM options (passthrough to UPP)
|
|
53
|
-
model,
|
|
54
|
-
params = {},
|
|
55
|
-
config,
|
|
56
|
-
tools = [],
|
|
57
|
-
system,
|
|
58
|
-
structure,
|
|
59
|
-
toolStrategy,
|
|
60
|
-
} = options;
|
|
61
|
-
|
|
62
|
-
const agentId = generateUUID();
|
|
63
|
-
// Generate sessionId (UUIDv4) if checkpoints provided but no sessionId
|
|
64
|
-
// Per UAP spec Section 3.4: Session IDs MUST be UUIDv4
|
|
65
|
-
const sessionId = checkpoints ? (providedSessionId ?? generateUUID()) : providedSessionId;
|
|
66
|
-
|
|
67
|
-
// Create the LLM instance with full UPP passthrough (or use injected instance for testing)
|
|
68
|
-
const llmInstance: LLMInstance = _llmInstance ?? llm({
|
|
69
|
-
model,
|
|
70
|
-
params,
|
|
71
|
-
config,
|
|
72
|
-
system,
|
|
73
|
-
structure,
|
|
74
|
-
tools,
|
|
75
|
-
toolStrategy,
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Normalize input to a Message.
|
|
80
|
-
*/
|
|
81
|
-
function normalizeInput(input: string | Message): Message {
|
|
82
|
-
if (typeof input === 'string') {
|
|
83
|
-
return new UserMessage(input);
|
|
84
|
-
}
|
|
85
|
-
return input;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Run middleware before hooks.
|
|
90
|
-
*/
|
|
91
|
-
async function runBeforeMiddleware(
|
|
92
|
-
middlewares: Middleware[],
|
|
93
|
-
context: MiddlewareContext,
|
|
94
|
-
): Promise<MiddlewareContext> {
|
|
95
|
-
let currentContext = context;
|
|
96
|
-
|
|
97
|
-
for (const mw of middlewares) {
|
|
98
|
-
if (mw.before) {
|
|
99
|
-
const result = await mw.before(currentContext);
|
|
100
|
-
if (result) {
|
|
101
|
-
currentContext = result;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return currentContext;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Run middleware after hooks (in reverse order).
|
|
111
|
-
*/
|
|
112
|
-
async function runAfterMiddleware(
|
|
113
|
-
middlewares: Middleware[],
|
|
114
|
-
context: MiddlewareContext,
|
|
115
|
-
result: GenerateResult,
|
|
116
|
-
): Promise<GenerateResult> {
|
|
117
|
-
let currentResult = result;
|
|
118
|
-
|
|
119
|
-
// Run in reverse order
|
|
120
|
-
for (let i = middlewares.length - 1; i >= 0; i--) {
|
|
121
|
-
const mw = middlewares[i];
|
|
122
|
-
if (mw?.after) {
|
|
123
|
-
currentResult = await mw.after(context, currentResult);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return currentResult;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Run middleware error hooks (in reverse order).
|
|
132
|
-
*/
|
|
133
|
-
async function runErrorMiddleware(
|
|
134
|
-
middlewares: Middleware[],
|
|
135
|
-
context: MiddlewareContext,
|
|
136
|
-
error: Error,
|
|
137
|
-
): Promise<GenerateResult | undefined> {
|
|
138
|
-
// Run in reverse order
|
|
139
|
-
for (let i = middlewares.length - 1; i >= 0; i--) {
|
|
140
|
-
const mw = middlewares[i];
|
|
141
|
-
if (mw?.onError) {
|
|
142
|
-
const result = await mw.onError(context, error);
|
|
143
|
-
if (result) {
|
|
144
|
-
return result;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Build execution context.
|
|
154
|
-
*/
|
|
155
|
-
function buildExecutionContext(
|
|
156
|
-
input: Message,
|
|
157
|
-
state: AgentState,
|
|
158
|
-
resolvedStrategy: AgentStrategy,
|
|
159
|
-
signal?: AbortSignal,
|
|
160
|
-
): ExecutionContext {
|
|
161
|
-
return {
|
|
162
|
-
agent: { id: agentId, system },
|
|
163
|
-
llm: llmInstance,
|
|
164
|
-
input,
|
|
165
|
-
state,
|
|
166
|
-
tools,
|
|
167
|
-
strategy: resolvedStrategy,
|
|
168
|
-
signal,
|
|
169
|
-
checkpoints,
|
|
170
|
-
sessionId,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const agentInstance: Agent = {
|
|
175
|
-
id: agentId,
|
|
176
|
-
model,
|
|
177
|
-
tools,
|
|
178
|
-
system,
|
|
179
|
-
|
|
180
|
-
async generate(
|
|
181
|
-
input: string | Message,
|
|
182
|
-
state: AgentState,
|
|
183
|
-
): Promise<GenerateResult> {
|
|
184
|
-
const normalizedInput = normalizeInput(input);
|
|
185
|
-
|
|
186
|
-
// Create middleware context
|
|
187
|
-
const middlewareContext: MiddlewareContext = {
|
|
188
|
-
agent: { id: agentId, system },
|
|
189
|
-
input: normalizedInput,
|
|
190
|
-
state,
|
|
191
|
-
metadata: new Map(),
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
// Run before middleware
|
|
196
|
-
const processedContext = await runBeforeMiddleware(middleware, middlewareContext);
|
|
197
|
-
|
|
198
|
-
// Build execution context
|
|
199
|
-
const executionContext = buildExecutionContext(
|
|
200
|
-
processedContext.input,
|
|
201
|
-
processedContext.state,
|
|
202
|
-
strategy,
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
// Execute strategy
|
|
206
|
-
const result = await execution.execute(executionContext);
|
|
207
|
-
|
|
208
|
-
// Run after middleware
|
|
209
|
-
const finalResult = await runAfterMiddleware(
|
|
210
|
-
middleware,
|
|
211
|
-
processedContext,
|
|
212
|
-
result,
|
|
213
|
-
);
|
|
214
|
-
|
|
215
|
-
return finalResult;
|
|
216
|
-
} catch (error) {
|
|
217
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
218
|
-
|
|
219
|
-
// Try to recover with error middleware
|
|
220
|
-
const recovered = await runErrorMiddleware(middleware, middlewareContext, err);
|
|
221
|
-
if (recovered) {
|
|
222
|
-
return recovered;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
throw err;
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
stream(
|
|
230
|
-
input: string | Message,
|
|
231
|
-
state: AgentState,
|
|
232
|
-
): AgentStreamResult {
|
|
233
|
-
const normalizedInput = normalizeInput(input);
|
|
234
|
-
|
|
235
|
-
// Create middleware context
|
|
236
|
-
const middlewareContext: MiddlewareContext = {
|
|
237
|
-
agent: { id: agentId, system },
|
|
238
|
-
input: normalizedInput,
|
|
239
|
-
state,
|
|
240
|
-
metadata: new Map(),
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
// We need to run before middleware synchronously enough to get the context
|
|
244
|
-
// but streaming is inherently async. We'll handle this by wrapping the stream.
|
|
245
|
-
let aborted = false;
|
|
246
|
-
const abortController = new AbortController();
|
|
247
|
-
|
|
248
|
-
let resolveResult: (result: GenerateResult) => void;
|
|
249
|
-
let rejectResult: (error: Error) => void;
|
|
250
|
-
|
|
251
|
-
const resultPromise = new Promise<GenerateResult>((resolve, reject) => {
|
|
252
|
-
resolveResult = resolve;
|
|
253
|
-
rejectResult = reject;
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
const createStream = async function* () {
|
|
257
|
-
try {
|
|
258
|
-
// Run before middleware
|
|
259
|
-
const processedContext = await runBeforeMiddleware(middleware, middlewareContext);
|
|
260
|
-
|
|
261
|
-
// Build execution context
|
|
262
|
-
const executionContext = buildExecutionContext(
|
|
263
|
-
processedContext.input,
|
|
264
|
-
processedContext.state,
|
|
265
|
-
strategy,
|
|
266
|
-
abortController.signal,
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
// Get the stream from the execution strategy
|
|
270
|
-
const streamResult = execution.stream(executionContext);
|
|
271
|
-
|
|
272
|
-
// Yield events from the stream
|
|
273
|
-
for await (const event of streamResult) {
|
|
274
|
-
if (aborted) {
|
|
275
|
-
break;
|
|
276
|
-
}
|
|
277
|
-
yield event;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Get the final result
|
|
281
|
-
const result = await streamResult.result;
|
|
282
|
-
|
|
283
|
-
// Run after middleware
|
|
284
|
-
const finalResult = await runAfterMiddleware(
|
|
285
|
-
middleware,
|
|
286
|
-
processedContext,
|
|
287
|
-
result,
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
resolveResult(finalResult);
|
|
291
|
-
} catch (error) {
|
|
292
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
293
|
-
|
|
294
|
-
// Try to recover with error middleware
|
|
295
|
-
const recovered = await runErrorMiddleware(middleware, middlewareContext, err);
|
|
296
|
-
if (recovered) {
|
|
297
|
-
resolveResult(recovered);
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
rejectResult(err);
|
|
302
|
-
throw err;
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const iterator = createStream();
|
|
307
|
-
|
|
308
|
-
return {
|
|
309
|
-
[Symbol.asyncIterator]() {
|
|
310
|
-
return iterator;
|
|
311
|
-
},
|
|
312
|
-
result: resultPromise,
|
|
313
|
-
abort() {
|
|
314
|
-
aborted = true;
|
|
315
|
-
abortController.abort();
|
|
316
|
-
},
|
|
317
|
-
};
|
|
318
|
-
},
|
|
319
|
-
|
|
320
|
-
async ask(
|
|
321
|
-
input: string | Message,
|
|
322
|
-
state: AgentState,
|
|
323
|
-
): Promise<GenerateResult> {
|
|
324
|
-
const normalizedInput = normalizeInput(input);
|
|
325
|
-
|
|
326
|
-
// Generate with original state - execution strategy adds input to LLM call
|
|
327
|
-
const result = await agentInstance.generate(normalizedInput, state);
|
|
328
|
-
|
|
329
|
-
// Build final state with correct message order:
|
|
330
|
-
// original messages + input + response messages from this turn
|
|
331
|
-
const responseMessages = result.state.messages.slice(state.messages.length);
|
|
332
|
-
const finalState = state
|
|
333
|
-
.withMessage(normalizedInput)
|
|
334
|
-
.withMessages(responseMessages)
|
|
335
|
-
.withStep(result.state.step);
|
|
336
|
-
|
|
337
|
-
// Preserve metadata from execution
|
|
338
|
-
let stateWithMetadata = finalState;
|
|
339
|
-
for (const [key, value] of Object.entries(result.state.metadata)) {
|
|
340
|
-
stateWithMetadata = stateWithMetadata.withMetadata(key, value);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Preserve reasoning traces
|
|
344
|
-
for (const reasoning of result.state.reasoning) {
|
|
345
|
-
stateWithMetadata = stateWithMetadata.withReasoning(reasoning);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Preserve plan if present
|
|
349
|
-
if (result.state.plan) {
|
|
350
|
-
stateWithMetadata = stateWithMetadata.withPlan([...result.state.plan]);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return {
|
|
354
|
-
turn: result.turn,
|
|
355
|
-
state: stateWithMetadata,
|
|
356
|
-
};
|
|
357
|
-
},
|
|
358
|
-
|
|
359
|
-
async query(input: string | Message): Promise<Turn> {
|
|
360
|
-
const initialState = AgentState.initial();
|
|
361
|
-
const result = await agentInstance.generate(input, initialState);
|
|
362
|
-
return result.turn;
|
|
363
|
-
},
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
return agentInstance;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
export type { Agent, AgentOptions } from './types.ts';
|
|
370
|
-
export type {
|
|
371
|
-
GenerateResult,
|
|
372
|
-
AgentStreamResult,
|
|
373
|
-
AgentStreamEvent,
|
|
374
|
-
UAPEventType,
|
|
375
|
-
AgentStrategy,
|
|
376
|
-
// Sub-agent event types (Section 8.7)
|
|
377
|
-
SubagentEventType,
|
|
378
|
-
SubagentEventBase,
|
|
379
|
-
SubagentStartEvent,
|
|
380
|
-
SubagentInnerEvent,
|
|
381
|
-
SubagentEndEvent,
|
|
382
|
-
SubagentEvent,
|
|
383
|
-
OnSubagentEvent,
|
|
384
|
-
} from '../execution/types.ts';
|
package/src/agent/types.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ModelReference,
|
|
3
|
-
Tool,
|
|
4
|
-
Turn,
|
|
5
|
-
Message,
|
|
6
|
-
LLMInstance,
|
|
7
|
-
LLMOptions,
|
|
8
|
-
} from '@providerprotocol/ai';
|
|
9
|
-
import type { AgentState } from '../state/index.ts';
|
|
10
|
-
import type {
|
|
11
|
-
ExecutionStrategy,
|
|
12
|
-
AgentStrategy,
|
|
13
|
-
GenerateResult,
|
|
14
|
-
AgentStreamResult,
|
|
15
|
-
} from '../execution/types.ts';
|
|
16
|
-
import type { Middleware } from '../middleware/types.ts';
|
|
17
|
-
import type { CheckpointStore } from '../checkpoint/types.ts';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Options for creating an agent.
|
|
21
|
-
* Extends LLMOptions for full UPP passthrough.
|
|
22
|
-
*/
|
|
23
|
-
export interface AgentOptions extends Partial<Omit<LLMOptions, 'model'>> {
|
|
24
|
-
/** Model reference from a UPP provider factory */
|
|
25
|
-
model: ModelReference;
|
|
26
|
-
/** Execution strategy. Default: loop() */
|
|
27
|
-
execution?: ExecutionStrategy;
|
|
28
|
-
/** Ordered middleware pipeline */
|
|
29
|
-
middleware?: Middleware[];
|
|
30
|
-
/** Agent lifecycle hooks */
|
|
31
|
-
strategy?: AgentStrategy;
|
|
32
|
-
/** Checkpoint store for step-level persistence */
|
|
33
|
-
checkpoints?: CheckpointStore;
|
|
34
|
-
/** Session identifier for checkpointing (auto-generated if not provided) */
|
|
35
|
-
sessionId?: string;
|
|
36
|
-
/** @internal Pre-created LLM instance for testing */
|
|
37
|
-
_llmInstance?: LLMInstance;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Agent interface.
|
|
42
|
-
*/
|
|
43
|
-
export interface Agent {
|
|
44
|
-
/** Unique agent identifier (UUIDv4) */
|
|
45
|
-
readonly id: string;
|
|
46
|
-
/** The bound model */
|
|
47
|
-
readonly model: ModelReference;
|
|
48
|
-
/** Available tools */
|
|
49
|
-
readonly tools: Tool[];
|
|
50
|
-
/** System prompt */
|
|
51
|
-
readonly system?: string;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Execute agent and return Turn with new state.
|
|
55
|
-
*
|
|
56
|
-
* @param input - User input (string or Message)
|
|
57
|
-
* @param state - Current immutable state
|
|
58
|
-
* @returns Promise resolving to { turn, state }
|
|
59
|
-
*/
|
|
60
|
-
generate(input: string | Message, state: AgentState): Promise<GenerateResult>;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Execute agent with streaming.
|
|
64
|
-
*
|
|
65
|
-
* @param input - User input (string or Message)
|
|
66
|
-
* @param state - Current immutable state
|
|
67
|
-
* @returns AgentStreamResult with async iterator and result promise
|
|
68
|
-
*/
|
|
69
|
-
stream(input: string | Message, state: AgentState): AgentStreamResult;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Multi-turn execution with automatic history management.
|
|
73
|
-
* Appends input to state, calls generate(), appends response to returned state.
|
|
74
|
-
*
|
|
75
|
-
* @param input - User input (string or Message)
|
|
76
|
-
* @param state - Current immutable state
|
|
77
|
-
* @returns Promise resolving to { turn, state }
|
|
78
|
-
*/
|
|
79
|
-
ask(input: string | Message, state: AgentState): Promise<GenerateResult>;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Stateless single-turn execution.
|
|
83
|
-
* Creates ephemeral state, executes, and discards state.
|
|
84
|
-
*
|
|
85
|
-
* @param input - User input (string or Message)
|
|
86
|
-
* @returns Promise resolving to Turn
|
|
87
|
-
*/
|
|
88
|
-
query(input: string | Message): Promise<Turn>;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export type { GenerateResult, AgentStreamResult, AgentStrategy } from '../execution/types.ts';
|
package/src/checkpoint/file.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File-based Checkpoint Store
|
|
3
|
-
*
|
|
4
|
-
* Reference implementation of CheckpointStore using the filesystem.
|
|
5
|
-
*
|
|
6
|
-
* @see UAP-1.0 Spec Section 12.4.3
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { mkdir, readdir, rm } from 'node:fs/promises';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
import type { AgentStateJSON } from '../state/types.ts';
|
|
12
|
-
import type { CheckpointStore, FileCheckpointOptions, CheckpointMetadata } from './types.ts';
|
|
13
|
-
import { generateUUID } from '../utils/uuid.ts';
|
|
14
|
-
|
|
15
|
-
const DEFAULT_DIR = '.checkpoints';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Create a file-based checkpoint store.
|
|
19
|
-
*
|
|
20
|
-
* Stores checkpoints as JSON files in a directory structure:
|
|
21
|
-
* ```
|
|
22
|
-
* {dir}/
|
|
23
|
-
* {sessionId}/
|
|
24
|
-
* checkpoint.json # Latest state
|
|
25
|
-
* metadata.json # Session metadata
|
|
26
|
-
* ```
|
|
27
|
-
*
|
|
28
|
-
* @param options - Configuration options
|
|
29
|
-
* @returns CheckpointStore implementation
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```typescript
|
|
33
|
-
* import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';
|
|
34
|
-
*
|
|
35
|
-
* const store = fileCheckpoints({ dir: './my-checkpoints' });
|
|
36
|
-
*
|
|
37
|
-
* // Save a checkpoint
|
|
38
|
-
* await store.save('session-123', state.toJSON());
|
|
39
|
-
*
|
|
40
|
-
* // Load a checkpoint
|
|
41
|
-
* const saved = await store.load('session-123');
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export function fileCheckpoints(options: FileCheckpointOptions = {}): CheckpointStore {
|
|
45
|
-
const dir = options.dir ?? DEFAULT_DIR;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Ensure session directory exists.
|
|
49
|
-
*/
|
|
50
|
-
async function ensureSessionDir(sessionId: string): Promise<string> {
|
|
51
|
-
const sessionDir = join(dir, sessionId);
|
|
52
|
-
await mkdir(sessionDir, { recursive: true });
|
|
53
|
-
return sessionDir;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get paths for checkpoint files.
|
|
58
|
-
*/
|
|
59
|
-
function getPaths(sessionId: string): { checkpointPath: string; metadataPath: string } {
|
|
60
|
-
const sessionDir = join(dir, sessionId);
|
|
61
|
-
return {
|
|
62
|
-
checkpointPath: join(sessionDir, 'checkpoint.json'),
|
|
63
|
-
metadataPath: join(sessionDir, 'metadata.json'),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
async save(sessionId: string, state: AgentStateJSON): Promise<void> {
|
|
69
|
-
await ensureSessionDir(sessionId);
|
|
70
|
-
const { checkpointPath, metadataPath } = getPaths(sessionId);
|
|
71
|
-
|
|
72
|
-
// Build metadata
|
|
73
|
-
const metadata: CheckpointMetadata = {
|
|
74
|
-
sessionId,
|
|
75
|
-
checkpointId: generateUUID(),
|
|
76
|
-
timestamp: new Date().toISOString(),
|
|
77
|
-
step: state.step,
|
|
78
|
-
agentId: state.metadata.agentId as string ?? 'unknown',
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Write checkpoint first, then metadata (sequential to avoid race conditions)
|
|
82
|
-
await Bun.write(checkpointPath, JSON.stringify(state, null, 2));
|
|
83
|
-
await Bun.write(metadataPath, JSON.stringify(metadata, null, 2));
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
async load(sessionId: string): Promise<AgentStateJSON | null> {
|
|
87
|
-
const { checkpointPath } = getPaths(sessionId);
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
const file = Bun.file(checkpointPath);
|
|
91
|
-
const exists = await file.exists();
|
|
92
|
-
if (!exists) {
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
const content = await file.text();
|
|
96
|
-
return JSON.parse(content) as AgentStateJSON;
|
|
97
|
-
} catch {
|
|
98
|
-
// File doesn't exist or is invalid
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
async delete(sessionId: string): Promise<void> {
|
|
104
|
-
const sessionDir = join(dir, sessionId);
|
|
105
|
-
try {
|
|
106
|
-
await rm(sessionDir, { recursive: true, force: true });
|
|
107
|
-
} catch {
|
|
108
|
-
// Directory might not exist, ignore
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
async list(): Promise<string[]> {
|
|
113
|
-
try {
|
|
114
|
-
// Ensure base directory exists
|
|
115
|
-
await mkdir(dir, { recursive: true });
|
|
116
|
-
|
|
117
|
-
const entries = await readdir(dir, { withFileTypes: true });
|
|
118
|
-
return entries
|
|
119
|
-
.filter((entry) => entry.isDirectory())
|
|
120
|
-
.map((entry) => entry.name);
|
|
121
|
-
} catch {
|
|
122
|
-
return [];
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
}
|
package/src/checkpoint/index.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checkpoint Module
|
|
3
|
-
*
|
|
4
|
-
* Step-level persistence for crash recovery and session resume.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```typescript
|
|
8
|
-
* import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';
|
|
9
|
-
* import { agent, AgentState } from '@providerprotocol/agents';
|
|
10
|
-
*
|
|
11
|
-
* const store = fileCheckpoints({ dir: './checkpoints' });
|
|
12
|
-
*
|
|
13
|
-
* // Resume or start fresh
|
|
14
|
-
* const saved = await store.load('my-session');
|
|
15
|
-
* const initialState = saved
|
|
16
|
-
* ? AgentState.fromJSON(saved)
|
|
17
|
-
* : AgentState.initial();
|
|
18
|
-
*
|
|
19
|
-
* // Execute with checkpointing
|
|
20
|
-
* const coder = agent({
|
|
21
|
-
* model: anthropic('claude-sonnet-4-20250514'),
|
|
22
|
-
* tools: [Bash, Read],
|
|
23
|
-
* checkpoints: store,
|
|
24
|
-
* sessionId: 'my-session',
|
|
25
|
-
* });
|
|
26
|
-
*
|
|
27
|
-
* const { turn, state } = await coder.generate('Fix the bug', initialState);
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* @packageDocumentation
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
export { fileCheckpoints } from './file.ts';
|
|
34
|
-
|
|
35
|
-
export type {
|
|
36
|
-
CheckpointStore,
|
|
37
|
-
FileCheckpointOptions,
|
|
38
|
-
CheckpointMetadata,
|
|
39
|
-
CheckpointData,
|
|
40
|
-
} from './types.ts';
|