@providerprotocol/agents 0.0.2 → 0.0.4
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/LICENSE +21 -0
- package/dist/checkpoint/index.d.ts +43 -0
- package/dist/checkpoint/index.js +73 -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-T47B3VAF.js +427 -0
- package/dist/chunk-T47B3VAF.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-BiyEVOnf.d.ts +65 -0
- package/dist/types-D1egxttz.d.ts +270 -0
- package/dist/types-DChRdQoX.d.ts +98 -0
- package/package.json +41 -9
- package/.claude/settings.local.json +0 -29
- 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/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, 2026 ProviderProtocol
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { F as FileCheckpointOptions, C as CheckpointStore } from '../types-DChRdQoX.js';
|
|
2
|
+
export { b as CheckpointData, a as CheckpointMetadata } from '../types-DChRdQoX.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,73 @@
|
|
|
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 loadMetadata(sessionId) {
|
|
44
|
+
const { metadataPath } = getPaths(sessionId);
|
|
45
|
+
try {
|
|
46
|
+
const content = await readFile(metadataPath, "utf-8");
|
|
47
|
+
return JSON.parse(content);
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
async delete(sessionId) {
|
|
53
|
+
const sessionDir = join(dir, sessionId);
|
|
54
|
+
try {
|
|
55
|
+
await rm(sessionDir, { recursive: true, force: true });
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
async list() {
|
|
60
|
+
try {
|
|
61
|
+
await mkdir(dir, { recursive: true });
|
|
62
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
63
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
64
|
+
} catch {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { fileCheckpoints };
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/checkpoint/file.ts"],"names":[],"mappings":"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","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 loadMetadata(sessionId: string): Promise<CheckpointMetadata | null> {\n const { metadataPath } = getPaths(sessionId);\n\n try {\n const content = await readFile(metadataPath, 'utf-8');\n return JSON.parse(content) as CheckpointMetadata;\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"]}
|
|
@@ -1,288 +1,178 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
ExecutionContext,
|
|
5
|
-
ExecutionResult,
|
|
6
|
-
LoopOptions,
|
|
7
|
-
AgentStreamResult,
|
|
8
|
-
AgentStreamEvent,
|
|
9
|
-
} from './types.ts';
|
|
10
|
-
|
|
11
|
-
const DEFAULT_LOOP_OPTIONS: Required<LoopOptions> = {
|
|
12
|
-
maxIterations: Infinity,
|
|
1
|
+
// src/execution/loop.ts
|
|
2
|
+
var DEFAULT_LOOP_OPTIONS = {
|
|
3
|
+
maxIterations: Infinity
|
|
13
4
|
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Create a loop execution strategy.
|
|
17
|
-
* The simplest strategy - equivalent to UPP's tool loop behavior.
|
|
18
|
-
*
|
|
19
|
-
* Behavior:
|
|
20
|
-
* 1. Send input to LLM
|
|
21
|
-
* 2. If response has tool calls, execute tools and loop
|
|
22
|
-
* 3. Continue until no tool calls or maxIterations reached
|
|
23
|
-
* 4. Return final response as UPP Turn
|
|
24
|
-
*
|
|
25
|
-
* @param options - Loop configuration options
|
|
26
|
-
* @returns ExecutionStrategy
|
|
27
|
-
*/
|
|
28
|
-
export function loop(options: LoopOptions = {}): ExecutionStrategy {
|
|
5
|
+
function loop(options = {}) {
|
|
29
6
|
const opts = { ...DEFAULT_LOOP_OPTIONS, ...options };
|
|
30
|
-
|
|
31
7
|
return {
|
|
32
|
-
name:
|
|
33
|
-
|
|
34
|
-
async execute(context: ExecutionContext): Promise<ExecutionResult> {
|
|
8
|
+
name: "loop",
|
|
9
|
+
async execute(context) {
|
|
35
10
|
const { llm, input, state, strategy, signal } = context;
|
|
36
|
-
|
|
37
|
-
// Add input message to state and set agentId in metadata
|
|
38
|
-
// This ensures checkpoints include the full conversation
|
|
39
|
-
let currentState = state
|
|
40
|
-
.withMessage(input)
|
|
41
|
-
.withMetadata('agentId', context.agent.id);
|
|
11
|
+
let currentState = state.withMessage(input).withMetadata("agentId", context.agent.id);
|
|
42
12
|
let iteration = 0;
|
|
43
|
-
let finalTurn
|
|
44
|
-
|
|
45
|
-
// Messages for LLM generation (includes input we just added)
|
|
13
|
+
let finalTurn;
|
|
46
14
|
const inputMessages = [...currentState.messages];
|
|
47
|
-
|
|
48
15
|
while (true) {
|
|
49
16
|
iteration++;
|
|
50
17
|
currentState = currentState.withStep(iteration);
|
|
51
|
-
|
|
52
|
-
// Check abort signal
|
|
53
18
|
if (signal?.aborted) {
|
|
54
|
-
throw new Error(
|
|
19
|
+
throw new Error("Execution aborted");
|
|
55
20
|
}
|
|
56
|
-
|
|
57
|
-
// Call strategy hooks
|
|
58
21
|
strategy.onStepStart?.(iteration, currentState);
|
|
59
|
-
|
|
60
|
-
// Generate response - llm.generate uses rest params, pass messages array
|
|
61
22
|
const turn = await llm.generate(inputMessages);
|
|
62
23
|
finalTurn = turn;
|
|
63
|
-
|
|
64
|
-
// Update state with messages from this turn
|
|
65
24
|
currentState = currentState.withMessages(turn.messages);
|
|
66
|
-
|
|
67
|
-
// Call action hook if there were tool calls
|
|
68
25
|
if (turn.response.hasToolCalls) {
|
|
69
26
|
strategy.onAct?.(iteration, turn.response.toolCalls ?? []);
|
|
70
27
|
}
|
|
71
|
-
|
|
72
|
-
// Call observe hook if there were tool executions
|
|
73
28
|
if (turn.toolExecutions && turn.toolExecutions.length > 0) {
|
|
74
29
|
strategy.onObserve?.(iteration, turn.toolExecutions);
|
|
75
30
|
}
|
|
76
|
-
|
|
77
|
-
// Call step end hook
|
|
78
31
|
strategy.onStepEnd?.(iteration, { turn, state: currentState });
|
|
79
|
-
|
|
80
|
-
// Save checkpoint after step completes (fire-and-forget, log errors)
|
|
81
32
|
if (context.checkpoints && context.sessionId) {
|
|
82
33
|
context.checkpoints.save(context.sessionId, currentState.toJSON()).catch((err) => {
|
|
83
|
-
console.error(
|
|
34
|
+
console.error("[UAP] Checkpoint save failed:", err);
|
|
84
35
|
});
|
|
85
36
|
}
|
|
86
|
-
|
|
87
|
-
// Check stop condition
|
|
88
37
|
const shouldStop = await strategy.stopCondition?.(currentState);
|
|
89
38
|
if (shouldStop) {
|
|
90
39
|
break;
|
|
91
40
|
}
|
|
92
|
-
|
|
93
|
-
// Check if there are more tool calls to process
|
|
94
|
-
// UPP's llm.generate handles the tool loop internally,
|
|
95
|
-
// so we only need one iteration unless we're doing multi-step
|
|
96
41
|
if (!turn.response.hasToolCalls) {
|
|
97
42
|
break;
|
|
98
43
|
}
|
|
99
|
-
|
|
100
|
-
// Check iteration limit
|
|
101
44
|
if (opts.maxIterations !== Infinity && iteration >= opts.maxIterations) {
|
|
102
45
|
break;
|
|
103
46
|
}
|
|
104
|
-
|
|
105
|
-
// For next iteration, use the updated messages
|
|
106
47
|
inputMessages.length = 0;
|
|
107
48
|
inputMessages.push(...currentState.messages);
|
|
108
49
|
}
|
|
109
|
-
|
|
110
50
|
if (!finalTurn) {
|
|
111
|
-
throw new Error(
|
|
51
|
+
throw new Error("No turn generated");
|
|
112
52
|
}
|
|
113
|
-
|
|
114
|
-
// Include sessionId in state metadata if checkpointing is enabled
|
|
115
|
-
// Per UAP spec Section 3.4: sessionId MUST be included in state.metadata
|
|
116
53
|
let finalState = currentState;
|
|
117
54
|
if (context.sessionId) {
|
|
118
|
-
finalState = currentState.withMetadata(
|
|
55
|
+
finalState = currentState.withMetadata("sessionId", context.sessionId);
|
|
119
56
|
}
|
|
120
|
-
|
|
121
|
-
const result: ExecutionResult = {
|
|
57
|
+
const result = {
|
|
122
58
|
turn: finalTurn,
|
|
123
|
-
state: finalState
|
|
59
|
+
state: finalState
|
|
124
60
|
};
|
|
125
|
-
|
|
126
61
|
strategy.onComplete?.(result);
|
|
127
|
-
|
|
128
62
|
return result;
|
|
129
63
|
},
|
|
130
|
-
|
|
131
|
-
stream(context: ExecutionContext): AgentStreamResult {
|
|
64
|
+
stream(context) {
|
|
132
65
|
const { llm, input, state, strategy, signal } = context;
|
|
133
66
|
const agentId = context.agent.id;
|
|
134
|
-
|
|
135
67
|
let aborted = false;
|
|
136
68
|
const abortController = new AbortController();
|
|
137
|
-
|
|
138
|
-
// Combine signals if one was provided
|
|
139
69
|
if (signal) {
|
|
140
|
-
signal.addEventListener(
|
|
70
|
+
signal.addEventListener("abort", () => abortController.abort());
|
|
141
71
|
}
|
|
142
|
-
|
|
143
|
-
let
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const resultPromise = new Promise<ExecutionResult>((resolve, reject) => {
|
|
72
|
+
let resolveResult;
|
|
73
|
+
let rejectResult;
|
|
74
|
+
const resultPromise = new Promise((resolve, reject) => {
|
|
147
75
|
resolveResult = resolve;
|
|
148
76
|
rejectResult = reject;
|
|
149
77
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// Add input message to state and set agentId in metadata
|
|
153
|
-
// This ensures checkpoints include the full conversation
|
|
154
|
-
let currentState = state
|
|
155
|
-
.withMessage(input)
|
|
156
|
-
.withMetadata('agentId', context.agent.id);
|
|
78
|
+
async function* generateEvents() {
|
|
79
|
+
let currentState = state.withMessage(input).withMetadata("agentId", context.agent.id);
|
|
157
80
|
let iteration = 0;
|
|
158
|
-
let finalTurn
|
|
159
|
-
|
|
160
|
-
// Messages for LLM generation (includes input we just added)
|
|
81
|
+
let finalTurn;
|
|
161
82
|
const inputMessages = [...currentState.messages];
|
|
162
|
-
|
|
163
83
|
try {
|
|
164
84
|
while (!aborted) {
|
|
165
85
|
iteration++;
|
|
166
86
|
currentState = currentState.withStep(iteration);
|
|
167
|
-
|
|
168
87
|
if (abortController.signal.aborted) {
|
|
169
|
-
throw new Error(
|
|
88
|
+
throw new Error("Execution aborted");
|
|
170
89
|
}
|
|
171
|
-
|
|
172
90
|
strategy.onStepStart?.(iteration, currentState);
|
|
173
|
-
|
|
174
|
-
// Emit step start event
|
|
175
91
|
yield {
|
|
176
|
-
source:
|
|
92
|
+
source: "uap",
|
|
177
93
|
uap: {
|
|
178
|
-
type:
|
|
94
|
+
type: "step_start",
|
|
179
95
|
step: iteration,
|
|
180
96
|
agentId,
|
|
181
|
-
data: { iteration }
|
|
182
|
-
}
|
|
97
|
+
data: { iteration }
|
|
98
|
+
}
|
|
183
99
|
};
|
|
184
|
-
|
|
185
|
-
// Stream the LLM response
|
|
186
100
|
const streamResult = llm.stream(inputMessages);
|
|
187
|
-
|
|
188
|
-
for await (const event of streamResult as AsyncIterable<StreamEvent>) {
|
|
101
|
+
for await (const event of streamResult) {
|
|
189
102
|
if (abortController.signal.aborted) {
|
|
190
|
-
throw new Error(
|
|
103
|
+
throw new Error("Execution aborted");
|
|
191
104
|
}
|
|
192
|
-
|
|
193
|
-
// Yield UPP events
|
|
194
105
|
yield {
|
|
195
|
-
source:
|
|
196
|
-
upp: event
|
|
106
|
+
source: "upp",
|
|
107
|
+
upp: event
|
|
197
108
|
};
|
|
198
109
|
}
|
|
199
|
-
|
|
200
|
-
// Get the final turn from the stream
|
|
201
110
|
const turn = await streamResult.turn;
|
|
202
111
|
finalTurn = turn;
|
|
203
|
-
|
|
204
112
|
currentState = currentState.withMessages(turn.messages);
|
|
205
|
-
|
|
206
113
|
if (turn.response.hasToolCalls) {
|
|
207
114
|
strategy.onAct?.(iteration, turn.response.toolCalls ?? []);
|
|
208
|
-
|
|
209
115
|
yield {
|
|
210
|
-
source:
|
|
116
|
+
source: "uap",
|
|
211
117
|
uap: {
|
|
212
|
-
type:
|
|
118
|
+
type: "action",
|
|
213
119
|
step: iteration,
|
|
214
120
|
agentId,
|
|
215
|
-
data: { toolCalls: turn.response.toolCalls }
|
|
216
|
-
}
|
|
121
|
+
data: { toolCalls: turn.response.toolCalls }
|
|
122
|
+
}
|
|
217
123
|
};
|
|
218
124
|
}
|
|
219
|
-
|
|
220
125
|
if (turn.toolExecutions && turn.toolExecutions.length > 0) {
|
|
221
126
|
strategy.onObserve?.(iteration, turn.toolExecutions);
|
|
222
|
-
|
|
223
127
|
yield {
|
|
224
|
-
source:
|
|
128
|
+
source: "uap",
|
|
225
129
|
uap: {
|
|
226
|
-
type:
|
|
130
|
+
type: "observation",
|
|
227
131
|
step: iteration,
|
|
228
132
|
agentId,
|
|
229
|
-
data: { observations: turn.toolExecutions }
|
|
230
|
-
}
|
|
133
|
+
data: { observations: turn.toolExecutions }
|
|
134
|
+
}
|
|
231
135
|
};
|
|
232
136
|
}
|
|
233
|
-
|
|
234
137
|
strategy.onStepEnd?.(iteration, { turn, state: currentState });
|
|
235
|
-
|
|
236
|
-
// Save checkpoint after step completes (fire-and-forget, log errors)
|
|
237
138
|
if (context.checkpoints && context.sessionId) {
|
|
238
139
|
context.checkpoints.save(context.sessionId, currentState.toJSON()).catch((err) => {
|
|
239
|
-
console.error(
|
|
140
|
+
console.error("[UAP] Checkpoint save failed:", err);
|
|
240
141
|
});
|
|
241
142
|
}
|
|
242
|
-
|
|
243
143
|
yield {
|
|
244
|
-
source:
|
|
144
|
+
source: "uap",
|
|
245
145
|
uap: {
|
|
246
|
-
type:
|
|
146
|
+
type: "step_end",
|
|
247
147
|
step: iteration,
|
|
248
148
|
agentId,
|
|
249
|
-
data: { iteration }
|
|
250
|
-
}
|
|
149
|
+
data: { iteration }
|
|
150
|
+
}
|
|
251
151
|
};
|
|
252
|
-
|
|
253
152
|
const shouldStop = await strategy.stopCondition?.(currentState);
|
|
254
153
|
if (shouldStop) {
|
|
255
154
|
break;
|
|
256
155
|
}
|
|
257
|
-
|
|
258
156
|
if (!turn.response.hasToolCalls) {
|
|
259
157
|
break;
|
|
260
158
|
}
|
|
261
|
-
|
|
262
159
|
if (opts.maxIterations !== Infinity && iteration >= opts.maxIterations) {
|
|
263
160
|
break;
|
|
264
161
|
}
|
|
265
|
-
|
|
266
162
|
inputMessages.length = 0;
|
|
267
163
|
inputMessages.push(...currentState.messages);
|
|
268
164
|
}
|
|
269
|
-
|
|
270
165
|
if (!finalTurn) {
|
|
271
|
-
throw new Error(
|
|
166
|
+
throw new Error("No turn generated");
|
|
272
167
|
}
|
|
273
|
-
|
|
274
|
-
// Include sessionId in state metadata if checkpointing is enabled
|
|
275
|
-
// Per UAP spec Section 3.4: sessionId MUST be included in state.metadata
|
|
276
168
|
let finalState = currentState;
|
|
277
169
|
if (context.sessionId) {
|
|
278
|
-
finalState = currentState.withMetadata(
|
|
170
|
+
finalState = currentState.withMetadata("sessionId", context.sessionId);
|
|
279
171
|
}
|
|
280
|
-
|
|
281
|
-
const result: ExecutionResult = {
|
|
172
|
+
const result = {
|
|
282
173
|
turn: finalTurn,
|
|
283
|
-
state: finalState
|
|
174
|
+
state: finalState
|
|
284
175
|
};
|
|
285
|
-
|
|
286
176
|
strategy.onComplete?.(result);
|
|
287
177
|
resolveResult(result);
|
|
288
178
|
} catch (error) {
|
|
@@ -292,9 +182,7 @@ export function loop(options: LoopOptions = {}): ExecutionStrategy {
|
|
|
292
182
|
throw err;
|
|
293
183
|
}
|
|
294
184
|
}
|
|
295
|
-
|
|
296
185
|
const iterator = generateEvents();
|
|
297
|
-
|
|
298
186
|
return {
|
|
299
187
|
[Symbol.asyncIterator]() {
|
|
300
188
|
return iterator;
|
|
@@ -303,8 +191,12 @@ export function loop(options: LoopOptions = {}): ExecutionStrategy {
|
|
|
303
191
|
abort() {
|
|
304
192
|
aborted = true;
|
|
305
193
|
abortController.abort();
|
|
306
|
-
}
|
|
194
|
+
}
|
|
307
195
|
};
|
|
308
|
-
}
|
|
196
|
+
}
|
|
309
197
|
};
|
|
310
198
|
}
|
|
199
|
+
|
|
200
|
+
export { loop };
|
|
201
|
+
//# sourceMappingURL=chunk-4ESYN66B.js.map
|
|
202
|
+
//# sourceMappingURL=chunk-4ESYN66B.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/execution/loop.ts"],"names":[],"mappings":";AAUA,IAAM,oBAAA,GAA8C;AAAA,EAClD,aAAA,EAAe;AACjB,CAAA;AAeO,SAAS,IAAA,CAAK,OAAA,GAAuB,EAAC,EAAsB;AACjE,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,oBAAA,EAAsB,GAAG,OAAA,EAAQ;AAEnD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,MAAA;AAAA,IAEN,MAAM,QAAQ,OAAA,EAAqD;AACjE,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU,QAAO,GAAI,OAAA;AAIhD,MAAA,IAAI,YAAA,GAAe,MAChB,WAAA,CAAY,KAAK,EACjB,YAAA,CAAa,SAAA,EAAW,OAAA,CAAQ,KAAA,CAAM,EAAE,CAAA;AAC3C,MAAA,IAAI,SAAA,GAAY,CAAA;AAChB,MAAA,IAAI,SAAA;AAGJ,MAAA,MAAM,aAAA,GAAgB,CAAC,GAAG,YAAA,CAAa,QAAQ,CAAA;AAE/C,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,SAAA,EAAA;AACA,QAAA,YAAA,GAAe,YAAA,CAAa,SAAS,SAAS,CAAA;AAG9C,QAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,UAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,QACrC;AAGA,QAAA,QAAA,CAAS,WAAA,GAAc,WAAW,YAAY,CAAA;AAG9C,QAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,QAAA,CAAS,aAAa,CAAA;AAC7C,QAAA,SAAA,GAAY,IAAA;AAGZ,QAAA,YAAA,GAAe,YAAA,CAAa,YAAA,CAAa,IAAA,CAAK,QAAQ,CAAA;AAGtD,QAAA,IAAI,IAAA,CAAK,SAAS,YAAA,EAAc;AAC9B,UAAA,QAAA,CAAS,QAAQ,SAAA,EAAW,IAAA,CAAK,QAAA,CAAS,SAAA,IAAa,EAAE,CAAA;AAAA,QAC3D;AAGA,QAAA,IAAI,IAAA,CAAK,cAAA,IAAkB,IAAA,CAAK,cAAA,CAAe,SAAS,CAAA,EAAG;AACzD,UAAA,QAAA,CAAS,SAAA,GAAY,SAAA,EAAW,IAAA,CAAK,cAAc,CAAA;AAAA,QACrD;AAGA,QAAA,QAAA,CAAS,YAAY,SAAA,EAAW,EAAE,IAAA,EAAM,KAAA,EAAO,cAAc,CAAA;AAG7D,QAAA,IAAI,OAAA,CAAQ,WAAA,IAAe,OAAA,CAAQ,SAAA,EAAW;AAC5C,UAAA,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,YAAA,CAAa,QAAQ,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAChF,YAAA,OAAA,CAAQ,KAAA,CAAM,iCAAiC,GAAG,CAAA;AAAA,UACpD,CAAC,CAAA;AAAA,QACH;AAGA,QAAA,MAAM,UAAA,GAAa,MAAM,QAAA,CAAS,aAAA,GAAgB,YAAY,CAAA;AAC9D,QAAA,IAAI,UAAA,EAAY;AACd,UAAA;AAAA,QACF;AAKA,QAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,YAAA,EAAc;AAC/B,UAAA;AAAA,QACF;AAGA,QAAA,IAAI,IAAA,CAAK,aAAA,KAAkB,QAAA,IAAY,SAAA,IAAa,KAAK,aAAA,EAAe;AACtE,UAAA;AAAA,QACF;AAGA,QAAA,aAAA,CAAc,MAAA,GAAS,CAAA;AACvB,QAAA,aAAA,CAAc,IAAA,CAAK,GAAG,YAAA,CAAa,QAAQ,CAAA;AAAA,MAC7C;AAEA,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,MACrC;AAIA,MAAA,IAAI,UAAA,GAAa,YAAA;AACjB,MAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,QAAA,UAAA,GAAa,YAAA,CAAa,YAAA,CAAa,WAAA,EAAa,OAAA,CAAQ,SAAS,CAAA;AAAA,MACvE;AAEA,MAAA,MAAM,MAAA,GAA0B;AAAA,QAC9B,IAAA,EAAM,SAAA;AAAA,QACN,KAAA,EAAO;AAAA,OACT;AAEA,MAAA,QAAA,CAAS,aAAa,MAAM,CAAA;AAE5B,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IAEA,OAAO,OAAA,EAA8C;AACnD,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU,QAAO,GAAI,OAAA;AAChD,MAAA,MAAM,OAAA,GAAU,QAAQ,KAAA,CAAM,EAAA;AAE9B,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,MAAM,eAAA,GAAkB,IAAI,eAAA,EAAgB;AAG5C,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,MAAA,CAAO,gBAAA,CAAiB,OAAA,EAAS,MAAM,eAAA,CAAgB,OAAO,CAAA;AAAA,MAChE;AAEA,MAAA,IAAI,aAAA;AACJ,MAAA,IAAI,YAAA;AAEJ,MAAA,MAAM,aAAA,GAAgB,IAAI,OAAA,CAAyB,CAAC,SAAS,MAAA,KAAW;AACtE,QAAA,aAAA,GAAgB,OAAA;AAChB,QAAA,YAAA,GAAe,MAAA;AAAA,MACjB,CAAC,CAAA;AAED,MAAA,gBAAgB,cAAA,GAAmD;AAGjE,QAAA,IAAI,YAAA,GAAe,MAChB,WAAA,CAAY,KAAK,EACjB,YAAA,CAAa,SAAA,EAAW,OAAA,CAAQ,KAAA,CAAM,EAAE,CAAA;AAC3C,QAAA,IAAI,SAAA,GAAY,CAAA;AAChB,QAAA,IAAI,SAAA;AAGJ,QAAA,MAAM,aAAA,GAAgB,CAAC,GAAG,YAAA,CAAa,QAAQ,CAAA;AAE/C,QAAA,IAAI;AACF,UAAA,OAAO,CAAC,OAAA,EAAS;AACf,YAAA,SAAA,EAAA;AACA,YAAA,YAAA,GAAe,YAAA,CAAa,SAAS,SAAS,CAAA;AAE9C,YAAA,IAAI,eAAA,CAAgB,OAAO,OAAA,EAAS;AAClC,cAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,YACrC;AAEA,YAAA,QAAA,CAAS,WAAA,GAAc,WAAW,YAAY,CAAA;AAG9C,YAAA,MAAM;AAAA,cACJ,MAAA,EAAQ,KAAA;AAAA,cACR,GAAA,EAAK;AAAA,gBACH,IAAA,EAAM,YAAA;AAAA,gBACN,IAAA,EAAM,SAAA;AAAA,gBACN,OAAA;AAAA,gBACA,IAAA,EAAM,EAAE,SAAA;AAAU;AACpB,aACF;AAGA,YAAA,MAAM,YAAA,GAAe,GAAA,CAAI,MAAA,CAAO,aAAa,CAAA;AAE7C,YAAA,WAAA,MAAiB,SAAS,YAAA,EAA4C;AACpE,cAAA,IAAI,eAAA,CAAgB,OAAO,OAAA,EAAS;AAClC,gBAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,cACrC;AAGA,cAAA,MAAM;AAAA,gBACJ,MAAA,EAAQ,KAAA;AAAA,gBACR,GAAA,EAAK;AAAA,eACP;AAAA,YACF;AAGA,YAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAa,IAAA;AAChC,YAAA,SAAA,GAAY,IAAA;AAEZ,YAAA,YAAA,GAAe,YAAA,CAAa,YAAA,CAAa,IAAA,CAAK,QAAQ,CAAA;AAEtD,YAAA,IAAI,IAAA,CAAK,SAAS,YAAA,EAAc;AAC9B,cAAA,QAAA,CAAS,QAAQ,SAAA,EAAW,IAAA,CAAK,QAAA,CAAS,SAAA,IAAa,EAAE,CAAA;AAEzD,cAAA,MAAM;AAAA,gBACJ,MAAA,EAAQ,KAAA;AAAA,gBACR,GAAA,EAAK;AAAA,kBACH,IAAA,EAAM,QAAA;AAAA,kBACN,IAAA,EAAM,SAAA;AAAA,kBACN,OAAA;AAAA,kBACA,IAAA,EAAM,EAAE,SAAA,EAAW,IAAA,CAAK,SAAS,SAAA;AAAU;AAC7C,eACF;AAAA,YACF;AAEA,YAAA,IAAI,IAAA,CAAK,cAAA,IAAkB,IAAA,CAAK,cAAA,CAAe,SAAS,CAAA,EAAG;AACzD,cAAA,QAAA,CAAS,SAAA,GAAY,SAAA,EAAW,IAAA,CAAK,cAAc,CAAA;AAEnD,cAAA,MAAM;AAAA,gBACJ,MAAA,EAAQ,KAAA;AAAA,gBACR,GAAA,EAAK;AAAA,kBACH,IAAA,EAAM,aAAA;AAAA,kBACN,IAAA,EAAM,SAAA;AAAA,kBACN,OAAA;AAAA,kBACA,IAAA,EAAM,EAAE,YAAA,EAAc,IAAA,CAAK,cAAA;AAAe;AAC5C,eACF;AAAA,YACF;AAEA,YAAA,QAAA,CAAS,YAAY,SAAA,EAAW,EAAE,IAAA,EAAM,KAAA,EAAO,cAAc,CAAA;AAG7D,YAAA,IAAI,OAAA,CAAQ,WAAA,IAAe,OAAA,CAAQ,SAAA,EAAW;AAC5C,cAAA,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,YAAA,CAAa,QAAQ,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAChF,gBAAA,OAAA,CAAQ,KAAA,CAAM,iCAAiC,GAAG,CAAA;AAAA,cACpD,CAAC,CAAA;AAAA,YACH;AAEA,YAAA,MAAM;AAAA,cACJ,MAAA,EAAQ,KAAA;AAAA,cACR,GAAA,EAAK;AAAA,gBACH,IAAA,EAAM,UAAA;AAAA,gBACN,IAAA,EAAM,SAAA;AAAA,gBACN,OAAA;AAAA,gBACA,IAAA,EAAM,EAAE,SAAA;AAAU;AACpB,aACF;AAEA,YAAA,MAAM,UAAA,GAAa,MAAM,QAAA,CAAS,aAAA,GAAgB,YAAY,CAAA;AAC9D,YAAA,IAAI,UAAA,EAAY;AACd,cAAA;AAAA,YACF;AAEA,YAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,YAAA,EAAc;AAC/B,cAAA;AAAA,YACF;AAEA,YAAA,IAAI,IAAA,CAAK,aAAA,KAAkB,QAAA,IAAY,SAAA,IAAa,KAAK,aAAA,EAAe;AACtE,cAAA;AAAA,YACF;AAEA,YAAA,aAAA,CAAc,MAAA,GAAS,CAAA;AACvB,YAAA,aAAA,CAAc,IAAA,CAAK,GAAG,YAAA,CAAa,QAAQ,CAAA;AAAA,UAC7C;AAEA,UAAA,IAAI,CAAC,SAAA,EAAW;AACd,YAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,UACrC;AAIA,UAAA,IAAI,UAAA,GAAa,YAAA;AACjB,UAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,YAAA,UAAA,GAAa,YAAA,CAAa,YAAA,CAAa,WAAA,EAAa,OAAA,CAAQ,SAAS,CAAA;AAAA,UACvE;AAEA,UAAA,MAAM,MAAA,GAA0B;AAAA,YAC9B,IAAA,EAAM,SAAA;AAAA,YACN,KAAA,EAAO;AAAA,WACT;AAEA,UAAA,QAAA,CAAS,aAAa,MAAM,CAAA;AAC5B,UAAA,aAAA,CAAc,MAAM,CAAA;AAAA,QACtB,SAAS,KAAA,EAAO;AACd,UAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpE,UAAA,QAAA,CAAS,OAAA,GAAU,KAAK,YAAY,CAAA;AACpC,UAAA,YAAA,CAAa,GAAG,CAAA;AAChB,UAAA,MAAM,GAAA;AAAA,QACR;AAAA,MACF;AAEA,MAAA,MAAM,WAAW,cAAA,EAAe;AAEhC,MAAA,OAAO;AAAA,QACL,CAAC,MAAA,CAAO,aAAa,CAAA,GAAI;AACvB,UAAA,OAAO,QAAA;AAAA,QACT,CAAA;AAAA,QACA,MAAA,EAAQ,aAAA;AAAA,QACR,KAAA,GAAQ;AACN,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,eAAA,CAAgB,KAAA,EAAM;AAAA,QACxB;AAAA,OACF;AAAA,IACF;AAAA,GACF;AACF","file":"chunk-4ESYN66B.js","sourcesContent":["import type { Turn, StreamEvent } from '@providerprotocol/ai';\nimport type {\n ExecutionStrategy,\n ExecutionContext,\n ExecutionResult,\n LoopOptions,\n AgentStreamResult,\n AgentStreamEvent,\n} from './types.ts';\n\nconst DEFAULT_LOOP_OPTIONS: Required<LoopOptions> = {\n maxIterations: Infinity,\n};\n\n/**\n * Create a loop execution strategy.\n * The simplest strategy - equivalent to UPP's tool loop behavior.\n *\n * Behavior:\n * 1. Send input to LLM\n * 2. If response has tool calls, execute tools and loop\n * 3. Continue until no tool calls or maxIterations reached\n * 4. Return final response as UPP Turn\n *\n * @param options - Loop configuration options\n * @returns ExecutionStrategy\n */\nexport function loop(options: LoopOptions = {}): ExecutionStrategy {\n const opts = { ...DEFAULT_LOOP_OPTIONS, ...options };\n\n return {\n name: 'loop',\n\n async execute(context: ExecutionContext): Promise<ExecutionResult> {\n const { llm, input, state, strategy, signal } = context;\n\n // Add input message to state and set agentId in metadata\n // This ensures checkpoints include the full conversation\n let currentState = state\n .withMessage(input)\n .withMetadata('agentId', context.agent.id);\n let iteration = 0;\n let finalTurn: Turn | undefined;\n\n // Messages for LLM generation (includes input we just added)\n const inputMessages = [...currentState.messages];\n\n while (true) {\n iteration++;\n currentState = currentState.withStep(iteration);\n\n // Check abort signal\n if (signal?.aborted) {\n throw new Error('Execution aborted');\n }\n\n // Call strategy hooks\n strategy.onStepStart?.(iteration, currentState);\n\n // Generate response - llm.generate uses rest params, pass messages array\n const turn = await llm.generate(inputMessages);\n finalTurn = turn;\n\n // Update state with messages from this turn\n currentState = currentState.withMessages(turn.messages);\n\n // Call action hook if there were tool calls\n if (turn.response.hasToolCalls) {\n strategy.onAct?.(iteration, turn.response.toolCalls ?? []);\n }\n\n // Call observe hook if there were tool executions\n if (turn.toolExecutions && turn.toolExecutions.length > 0) {\n strategy.onObserve?.(iteration, turn.toolExecutions);\n }\n\n // Call step end hook\n strategy.onStepEnd?.(iteration, { turn, state: currentState });\n\n // Save checkpoint after step completes (fire-and-forget, log errors)\n if (context.checkpoints && context.sessionId) {\n context.checkpoints.save(context.sessionId, currentState.toJSON()).catch((err) => {\n console.error('[UAP] Checkpoint save failed:', err);\n });\n }\n\n // Check stop condition\n const shouldStop = await strategy.stopCondition?.(currentState);\n if (shouldStop) {\n break;\n }\n\n // Check if there are more tool calls to process\n // UPP's llm.generate handles the tool loop internally,\n // so we only need one iteration unless we're doing multi-step\n if (!turn.response.hasToolCalls) {\n break;\n }\n\n // Check iteration limit\n if (opts.maxIterations !== Infinity && iteration >= opts.maxIterations) {\n break;\n }\n\n // For next iteration, use the updated messages\n inputMessages.length = 0;\n inputMessages.push(...currentState.messages);\n }\n\n if (!finalTurn) {\n throw new Error('No turn generated');\n }\n\n // Include sessionId in state metadata if checkpointing is enabled\n // Per UAP spec Section 3.4: sessionId MUST be included in state.metadata\n let finalState = currentState;\n if (context.sessionId) {\n finalState = currentState.withMetadata('sessionId', context.sessionId);\n }\n\n const result: ExecutionResult = {\n turn: finalTurn,\n state: finalState,\n };\n\n strategy.onComplete?.(result);\n\n return result;\n },\n\n stream(context: ExecutionContext): AgentStreamResult {\n const { llm, input, state, strategy, signal } = context;\n const agentId = context.agent.id;\n\n let aborted = false;\n const abortController = new AbortController();\n\n // Combine signals if one was provided\n if (signal) {\n signal.addEventListener('abort', () => abortController.abort());\n }\n\n let resolveResult: (result: ExecutionResult) => void;\n let rejectResult: (error: Error) => void;\n\n const resultPromise = new Promise<ExecutionResult>((resolve, reject) => {\n resolveResult = resolve;\n rejectResult = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<AgentStreamEvent> {\n // Add input message to state and set agentId in metadata\n // This ensures checkpoints include the full conversation\n let currentState = state\n .withMessage(input)\n .withMetadata('agentId', context.agent.id);\n let iteration = 0;\n let finalTurn: Turn | undefined;\n\n // Messages for LLM generation (includes input we just added)\n const inputMessages = [...currentState.messages];\n\n try {\n while (!aborted) {\n iteration++;\n currentState = currentState.withStep(iteration);\n\n if (abortController.signal.aborted) {\n throw new Error('Execution aborted');\n }\n\n strategy.onStepStart?.(iteration, currentState);\n\n // Emit step start event\n yield {\n source: 'uap',\n uap: {\n type: 'step_start',\n step: iteration,\n agentId,\n data: { iteration },\n },\n };\n\n // Stream the LLM response\n const streamResult = llm.stream(inputMessages);\n\n for await (const event of streamResult as AsyncIterable<StreamEvent>) {\n if (abortController.signal.aborted) {\n throw new Error('Execution aborted');\n }\n\n // Yield UPP events\n yield {\n source: 'upp',\n upp: event,\n };\n }\n\n // Get the final turn from the stream\n const turn = await streamResult.turn;\n finalTurn = turn;\n\n currentState = currentState.withMessages(turn.messages);\n\n if (turn.response.hasToolCalls) {\n strategy.onAct?.(iteration, turn.response.toolCalls ?? []);\n\n yield {\n source: 'uap',\n uap: {\n type: 'action',\n step: iteration,\n agentId,\n data: { toolCalls: turn.response.toolCalls },\n },\n };\n }\n\n if (turn.toolExecutions && turn.toolExecutions.length > 0) {\n strategy.onObserve?.(iteration, turn.toolExecutions);\n\n yield {\n source: 'uap',\n uap: {\n type: 'observation',\n step: iteration,\n agentId,\n data: { observations: turn.toolExecutions },\n },\n };\n }\n\n strategy.onStepEnd?.(iteration, { turn, state: currentState });\n\n // Save checkpoint after step completes (fire-and-forget, log errors)\n if (context.checkpoints && context.sessionId) {\n context.checkpoints.save(context.sessionId, currentState.toJSON()).catch((err) => {\n console.error('[UAP] Checkpoint save failed:', err);\n });\n }\n\n yield {\n source: 'uap',\n uap: {\n type: 'step_end',\n step: iteration,\n agentId,\n data: { iteration },\n },\n };\n\n const shouldStop = await strategy.stopCondition?.(currentState);\n if (shouldStop) {\n break;\n }\n\n if (!turn.response.hasToolCalls) {\n break;\n }\n\n if (opts.maxIterations !== Infinity && iteration >= opts.maxIterations) {\n break;\n }\n\n inputMessages.length = 0;\n inputMessages.push(...currentState.messages);\n }\n\n if (!finalTurn) {\n throw new Error('No turn generated');\n }\n\n // Include sessionId in state metadata if checkpointing is enabled\n // Per UAP spec Section 3.4: sessionId MUST be included in state.metadata\n let finalState = currentState;\n if (context.sessionId) {\n finalState = currentState.withMetadata('sessionId', context.sessionId);\n }\n\n const result: ExecutionResult = {\n turn: finalTurn,\n state: finalState,\n };\n\n strategy.onComplete?.(result);\n resolveResult(result);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n strategy.onError?.(err, currentState);\n rejectResult(err);\n throw err;\n }\n }\n\n const iterator = generateEvents();\n\n return {\n [Symbol.asyncIterator]() {\n return iterator;\n },\n result: resultPromise,\n abort() {\n aborted = true;\n abortController.abort();\n },\n };\n },\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/uuid.ts"],"names":[],"mappings":";AAIO,SAAS,YAAA,GAAuB;AACrC,EAAA,OAAO,UAAA,CAAW,OAAO,UAAA,EAAW;AACtC","file":"chunk-EKRXMSDX.js","sourcesContent":["/**\n * Generate a UUIDv4 identifier.\n * Uses the native crypto.randomUUID() which is available in Bun and modern Node.js.\n */\nexport function generateUUID(): string {\n return globalThis.crypto.randomUUID();\n}\n"]}
|