@f5-sales-demo/pi-agent-core 20.2.3 → 20.2.6
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/CHANGELOG.md +10 -1
- package/README.md +67 -67
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
5
|
## [14.0.1] - 2026-04-08
|
|
6
|
+
|
|
6
7
|
### Added
|
|
7
8
|
|
|
8
9
|
- Added `onAssistantMessageEvent` callback option to inspect assistant streaming events before they are emitted, enabling abort decisions before buffered events continue flowing
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
- Fixed stale forced toolChoice being passed to provider after tools are refreshed mid-turn
|
|
26
27
|
|
|
27
28
|
## [13.9.16] - 2026-03-10
|
|
29
|
+
|
|
28
30
|
### Added
|
|
29
31
|
|
|
30
32
|
- Added `onPayload` option to `AgentOptions` to inspect or replace provider payloads before they are sent
|
|
@@ -43,11 +45,13 @@
|
|
|
43
45
|
- Updated `setThinkingLevel()` method to accept `Effort | undefined` instead of `ThinkingLevel` string
|
|
44
46
|
|
|
45
47
|
## [13.4.0] - 2026-03-01
|
|
48
|
+
|
|
46
49
|
### Added
|
|
47
50
|
|
|
48
51
|
- Added `getToolChoice` option to dynamically override tool choice per LLM call
|
|
49
52
|
|
|
50
53
|
## [13.3.8] - 2026-02-28
|
|
54
|
+
|
|
51
55
|
### Changed
|
|
52
56
|
|
|
53
57
|
- Changed intent field name from `agent__intent` to `_i` in tool schemas
|
|
@@ -55,12 +59,15 @@
|
|
|
55
59
|
### Fixed
|
|
56
60
|
|
|
57
61
|
- Fixed synthetic tool result text formatting so aborted/error tool results no longer emit `Tool execution was aborted.: Request was aborted` style punctuation.
|
|
62
|
+
|
|
58
63
|
## [13.3.7] - 2026-02-27
|
|
64
|
+
|
|
59
65
|
### Added
|
|
60
66
|
|
|
61
67
|
- Added `lenientArgValidation` option to tools to allow graceful handling of argument validation errors by passing raw arguments to execute() instead of returning an error to the LLM
|
|
62
68
|
|
|
63
69
|
## [13.3.1] - 2026-02-26
|
|
70
|
+
|
|
64
71
|
### Added
|
|
65
72
|
|
|
66
73
|
- Added `topP`, `topK`, `minP`, `presencePenalty`, and `repetitionPenalty` options to `AgentOptions` for fine-grained sampling control
|
|
@@ -71,7 +78,9 @@
|
|
|
71
78
|
### Changed
|
|
72
79
|
|
|
73
80
|
- Removed per-tool `agent__intent` field description from injected schema to reduce token usage; intent format is now documented once in the system prompt instead of repeated in every tool definition
|
|
81
|
+
|
|
74
82
|
## [12.19.0] - 2026-02-22
|
|
83
|
+
|
|
75
84
|
### Changed
|
|
76
85
|
|
|
77
86
|
- Updated tool result messages to include error details when tool execution fails
|
|
@@ -316,4 +325,4 @@ Initial release under @oh-my-pi scope. See previous releases at [badlogic/pi-mon
|
|
|
316
325
|
|
|
317
326
|
- `Agent` constructor now has all options optional (empty options use defaults).
|
|
318
327
|
|
|
319
|
-
- `queueMessage()` is now synchronous (no longer returns a Promise).
|
|
328
|
+
- `queueMessage()` is now synchronous (no longer returns a Promise).
|
package/README.md
CHANGED
|
@@ -15,17 +15,17 @@ import { Agent } from "@f5-sales-demo/pi-agent";
|
|
|
15
15
|
import { getModel } from "@f5-sales-demo/pi-ai";
|
|
16
16
|
|
|
17
17
|
const agent = new Agent({
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
initialState: {
|
|
19
|
+
systemPrompt: "You are a helpful assistant.",
|
|
20
|
+
model: getModel("anthropic", "claude-sonnet-4-20250514"),
|
|
21
|
+
},
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
agent.subscribe((event) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
26
|
+
// Stream just the new text chunk
|
|
27
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
28
|
+
}
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
await agent.prompt("Hello!");
|
|
@@ -163,15 +163,15 @@ const agent = new Agent({
|
|
|
163
163
|
|
|
164
164
|
```typescript
|
|
165
165
|
interface AgentState {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
166
|
+
systemPrompt: string;
|
|
167
|
+
model: Model;
|
|
168
|
+
thinkingLevel: ThinkingLevel;
|
|
169
|
+
tools: AgentTool<any>[];
|
|
170
|
+
messages: AgentMessage[];
|
|
171
|
+
isStreaming: boolean;
|
|
172
|
+
streamMessage: AgentMessage | null; // Current partial during streaming
|
|
173
|
+
pendingToolCalls: Set<string>;
|
|
174
|
+
error?: string;
|
|
175
175
|
}
|
|
176
176
|
```
|
|
177
177
|
|
|
@@ -219,7 +219,7 @@ await agent.waitForIdle(); // Wait for completion
|
|
|
219
219
|
|
|
220
220
|
```typescript
|
|
221
221
|
const unsubscribe = agent.subscribe((event) => {
|
|
222
|
-
|
|
222
|
+
console.log(event.type);
|
|
223
223
|
});
|
|
224
224
|
unsubscribe();
|
|
225
225
|
```
|
|
@@ -234,16 +234,16 @@ agent.setInterruptMode("immediate");
|
|
|
234
234
|
|
|
235
235
|
// While agent is running tools
|
|
236
236
|
agent.steer({
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
role: "user",
|
|
238
|
+
content: "Stop! Do this instead.",
|
|
239
|
+
timestamp: Date.now(),
|
|
240
240
|
});
|
|
241
241
|
|
|
242
242
|
// Queue a follow-up to run after the current turn completes
|
|
243
243
|
agent.followUp({
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
244
|
+
role: "user",
|
|
245
|
+
content: "After that, summarize the changes.",
|
|
246
|
+
timestamp: Date.now(),
|
|
247
247
|
});
|
|
248
248
|
```
|
|
249
249
|
|
|
@@ -256,9 +256,9 @@ Extend `AgentMessage` via declaration merging:
|
|
|
256
256
|
|
|
257
257
|
```typescript
|
|
258
258
|
declare module "@f5-sales-demo/pi-agent" {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
interface CustomAgentMessages {
|
|
260
|
+
notification: { role: "notification"; text: string; timestamp: number };
|
|
261
|
+
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
// Now valid
|
|
@@ -269,11 +269,11 @@ Handle custom types in `convertToLlm`:
|
|
|
269
269
|
|
|
270
270
|
```typescript
|
|
271
271
|
const agent = new Agent({
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
272
|
+
convertToLlm: (messages) =>
|
|
273
|
+
messages.flatMap((m) => {
|
|
274
|
+
if (m.role === "notification") return []; // Filter out
|
|
275
|
+
return [m];
|
|
276
|
+
}),
|
|
277
277
|
});
|
|
278
278
|
```
|
|
279
279
|
|
|
@@ -285,23 +285,23 @@ Define tools using `AgentTool`:
|
|
|
285
285
|
import { Type } from "@sinclair/typebox";
|
|
286
286
|
|
|
287
287
|
const readFileTool: AgentTool = {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
288
|
+
name: "read_file",
|
|
289
|
+
label: "Read File", // For UI display
|
|
290
|
+
description: "Read a file's contents",
|
|
291
|
+
parameters: Type.Object({
|
|
292
|
+
path: Type.String({ description: "File path" }),
|
|
293
|
+
}),
|
|
294
|
+
execute: async (toolCallId, params, signal, onUpdate, context) => {
|
|
295
|
+
const content = await fs.readFile(params.path, "utf-8");
|
|
296
|
+
|
|
297
|
+
// Optional: stream progress
|
|
298
|
+
onUpdate?.({ content: [{ type: "text", text: "Reading..." }], details: {} });
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
content: [{ type: "text", text: content }],
|
|
302
|
+
details: { path: params.path, size: content.length },
|
|
303
|
+
};
|
|
304
|
+
},
|
|
305
305
|
};
|
|
306
306
|
|
|
307
307
|
agent.setTools([readFileTool]);
|
|
@@ -313,11 +313,11 @@ agent.setTools([readFileTool]);
|
|
|
313
313
|
|
|
314
314
|
```typescript
|
|
315
315
|
execute: async (toolCallId, params, signal, onUpdate) => {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
316
|
+
if (!fs.existsSync(params.path)) {
|
|
317
|
+
throw new Error(`File not found: ${params.path}`);
|
|
318
|
+
}
|
|
319
|
+
// Return content only on success
|
|
320
|
+
return { content: [{ type: "text", text: "..." }] };
|
|
321
321
|
};
|
|
322
322
|
```
|
|
323
323
|
|
|
@@ -331,12 +331,12 @@ For browser apps that proxy through a backend:
|
|
|
331
331
|
import { Agent, streamProxy } from "@f5-sales-demo/pi-agent";
|
|
332
332
|
|
|
333
333
|
const agent = new Agent({
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
334
|
+
streamFn: (model, context, options) =>
|
|
335
|
+
streamProxy(model, context, {
|
|
336
|
+
...options,
|
|
337
|
+
authToken: "...",
|
|
338
|
+
proxyUrl: "https://your-server.com",
|
|
339
|
+
}),
|
|
340
340
|
});
|
|
341
341
|
```
|
|
342
342
|
|
|
@@ -348,25 +348,25 @@ For direct control without the Agent class:
|
|
|
348
348
|
import { agentLoop, agentLoopContinue } from "@f5-sales-demo/pi-agent";
|
|
349
349
|
|
|
350
350
|
const context: AgentContext = {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
351
|
+
systemPrompt: "You are helpful.",
|
|
352
|
+
messages: [],
|
|
353
|
+
tools: [],
|
|
354
354
|
};
|
|
355
355
|
|
|
356
356
|
const config: AgentLoopConfig = {
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
model: getModel("openai", "gpt-4o"),
|
|
358
|
+
convertToLlm: (msgs) => msgs.filter((m) => ["user", "assistant", "toolResult"].includes(m.role)),
|
|
359
359
|
};
|
|
360
360
|
|
|
361
361
|
const userMessage = { role: "user", content: "Hello", timestamp: Date.now() };
|
|
362
362
|
|
|
363
363
|
for await (const event of agentLoop([userMessage], context, config)) {
|
|
364
|
-
|
|
364
|
+
console.log(event.type);
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
// Continue from existing context
|
|
368
368
|
for await (const event of agentLoopContinue(context, config)) {
|
|
369
|
-
|
|
369
|
+
console.log(event.type);
|
|
370
370
|
}
|
|
371
371
|
```
|
|
372
372
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5-sales-demo/pi-agent-core",
|
|
4
|
-
"version": "20.2.
|
|
4
|
+
"version": "20.2.6",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"homepage": "https://github.com/f5-sales-demo/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"fmt": "biome format --write ."
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@f5-sales-demo/pi-ai": "20.2.
|
|
39
|
-
"@f5-sales-demo/pi-utils": "20.2.
|
|
38
|
+
"@f5-sales-demo/pi-ai": "20.2.6",
|
|
39
|
+
"@f5-sales-demo/pi-utils": "20.2.6"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@sinclair/typebox": "^0.34",
|