@flink-app/flink 2.0.0-alpha.91 → 2.0.0-alpha.93
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 +47 -0
- package/dist/src/FlinkApp.d.ts +17 -0
- package/dist/src/FlinkApp.js +4 -2
- package/dist/src/ai/AgentRunner.d.ts +9 -2
- package/dist/src/ai/AgentRunner.js +507 -363
- package/dist/src/ai/FlinkAgent.d.ts +100 -1
- package/dist/src/ai/FlinkAgent.js +16 -3
- package/package.json +1 -1
- package/spec/AgentObserver.spec.ts +266 -0
- package/src/FlinkApp.ts +22 -1
- package/src/ai/AgentRunner.ts +141 -15
- package/src/ai/FlinkAgent.ts +112 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# @flink-app/flink
|
|
2
2
|
|
|
3
|
+
## 2.0.0-alpha.93
|
|
4
|
+
|
|
5
|
+
## 2.0.0-alpha.92
|
|
6
|
+
|
|
7
|
+
### Minor Changes
|
|
8
|
+
|
|
9
|
+
- 8d23d56: Add global `AgentObserver` for app-level agent tracing
|
|
10
|
+
|
|
11
|
+
A new `observer` option on `FlinkOptions.ai` lets applications register a single, app-wide hook that fires for every agent execution — covering both streamed and awaited (`response.result`) callers without per-agent plumbing.
|
|
12
|
+
|
|
13
|
+
Events expose data that was previously only internal to `AgentRunner`:
|
|
14
|
+
|
|
15
|
+
- `onRun` — pre-loop, with resolved system instructions and initial messages.
|
|
16
|
+
- `onLlmCall` — per step, immediately before the adapter call. `messages` reflects post-compaction state and `tools` reflects per-step permission filtering.
|
|
17
|
+
- `onStep` — per step end, with `assistantText`, per-step `toolCalls`, and `usage`.
|
|
18
|
+
- `onFinish` — post-loop (success or error), with the final result, total `durationMs`, and the error message on failure.
|
|
19
|
+
|
|
20
|
+
All events share a stable `runId` per execution; the same ID is now also returned on `AgentExecuteResult.runId` so apps can correlate persisted results with observer traces.
|
|
21
|
+
|
|
22
|
+
Observer callbacks are fire-and-forget: they may return a promise but the framework does not await them, and any thrown/rejected errors are caught and logged without affecting agent execution.
|
|
23
|
+
|
|
24
|
+
The existing per-agent `beforeRun` / `onStep` / `afterRun` hooks remain unchanged — use the observer for cross-cutting concerns (tracing, APM, cost accounting, dev tools) and per-agent hooks for business logic that needs to block or mutate state (conversation persistence, guardrails).
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
new FlinkApp({
|
|
30
|
+
ai: {
|
|
31
|
+
llms: { default: new AnthropicAdapter({ ... }) },
|
|
32
|
+
observer: {
|
|
33
|
+
onRun(e) {
|
|
34
|
+
trace.start(e.runId, { agentId: e.agentId, instructions: e.instructions });
|
|
35
|
+
},
|
|
36
|
+
onLlmCall(e) {
|
|
37
|
+
trace.recordLlmCall(e.runId, e.step, e.messages, e.tools);
|
|
38
|
+
},
|
|
39
|
+
onStep(e) {
|
|
40
|
+
trace.recordStep(e.runId, e.step, e.assistantText, e.toolCalls, e.usage);
|
|
41
|
+
},
|
|
42
|
+
onFinish(e) {
|
|
43
|
+
trace.finish(e.runId, { result: e.result, error: e.error, durationMs: e.durationMs });
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
3
50
|
## 2.0.0-alpha.91
|
|
4
51
|
|
|
5
52
|
## 2.0.0-alpha.90
|
package/dist/src/FlinkApp.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Db, MongoClient } from "mongodb";
|
|
|
6
6
|
import { ToadScheduler } from "toad-scheduler";
|
|
7
7
|
import { FlinkAgentFile } from "./ai/FlinkAgent";
|
|
8
8
|
import { FlinkToolFile } from "./ai/FlinkTool";
|
|
9
|
+
import { AgentObserver } from "./ai/FlinkAgent";
|
|
9
10
|
import { LLMAdapter } from "./ai/LLMAdapter";
|
|
10
11
|
import { FlinkAuthPlugin } from "./auth/FlinkAuthPlugin";
|
|
11
12
|
import { FlinkContext } from "./FlinkContext";
|
|
@@ -178,6 +179,21 @@ export interface FlinkOptions {
|
|
|
178
179
|
llms?: {
|
|
179
180
|
[id: string]: LLMAdapter;
|
|
180
181
|
};
|
|
182
|
+
/**
|
|
183
|
+
* Global agent observer for app-level tracing, APM, cost accounting, dev tools, etc.
|
|
184
|
+
*
|
|
185
|
+
* Fires for every agent execution in the app. Observer callbacks are invoked
|
|
186
|
+
* fire-and-forget — they may return a Promise but the framework does not await
|
|
187
|
+
* them, and any thrown/rejected errors are caught and logged without affecting
|
|
188
|
+
* agent execution.
|
|
189
|
+
*
|
|
190
|
+
* Events: `onRun` (pre-loop), `onLlmCall` (per step, pre-adapter call),
|
|
191
|
+
* `onStep` (per step end), `onFinish` (post-loop, including error path).
|
|
192
|
+
*
|
|
193
|
+
* For agent-local business logic (conversation persistence, guardrails) use the
|
|
194
|
+
* per-agent `beforeRun` / `onStep` / `afterRun` hooks on `FlinkAgent` instead.
|
|
195
|
+
*/
|
|
196
|
+
observer?: AgentObserver;
|
|
181
197
|
};
|
|
182
198
|
/**
|
|
183
199
|
* If true, the HTTP server will be disabled.
|
|
@@ -290,6 +306,7 @@ export declare class FlinkApp<C extends FlinkContext> {
|
|
|
290
306
|
private repos;
|
|
291
307
|
private services;
|
|
292
308
|
private llmAdapters;
|
|
309
|
+
private agentObserver?;
|
|
293
310
|
private tools;
|
|
294
311
|
private agents;
|
|
295
312
|
/**
|
package/dist/src/FlinkApp.js
CHANGED
|
@@ -117,7 +117,7 @@ exports.autoRegisteredAgents = [];
|
|
|
117
117
|
exports.autoRegisteredServices = [];
|
|
118
118
|
var FlinkApp = /** @class */ (function () {
|
|
119
119
|
function FlinkApp(opts) {
|
|
120
|
-
var _a;
|
|
120
|
+
var _a, _b;
|
|
121
121
|
this.handlers = [];
|
|
122
122
|
this.started = false;
|
|
123
123
|
this.debug = false;
|
|
@@ -160,6 +160,8 @@ var FlinkApp = /** @class */ (function () {
|
|
|
160
160
|
// Convert plain object to Map for internal use
|
|
161
161
|
this.llmAdapters = new Map(Object.entries(opts.ai.llms));
|
|
162
162
|
}
|
|
163
|
+
// Register global agent observer if configured
|
|
164
|
+
this.agentObserver = (_b = opts.ai) === null || _b === void 0 ? void 0 : _b.observer;
|
|
163
165
|
}
|
|
164
166
|
Object.defineProperty(FlinkApp.prototype, "ctx", {
|
|
165
167
|
get: function () {
|
|
@@ -1208,7 +1210,7 @@ var FlinkApp = /** @class */ (function () {
|
|
|
1208
1210
|
for (_i = 0, _a = Object.values(this.agents); _i < _a.length; _i++) {
|
|
1209
1211
|
agent = _a[_i];
|
|
1210
1212
|
agent.ctx = this.ctx;
|
|
1211
|
-
agent.__init(this.llmAdapters, this.tools);
|
|
1213
|
+
agent.__init(this.llmAdapters, this.tools, this.agentObserver);
|
|
1212
1214
|
}
|
|
1213
1215
|
return [2 /*return*/];
|
|
1214
1216
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FlinkAgentProps, AgentExecuteInput, StreamChunk } from "./FlinkAgent";
|
|
1
|
+
import { FlinkAgentProps, AgentExecuteInput, StreamChunk, AgentObserver } from "./FlinkAgent";
|
|
2
2
|
import { ToolExecutor } from "./ToolExecutor";
|
|
3
3
|
import { LLMAdapter } from "./LLMAdapter";
|
|
4
4
|
export declare class AgentRunner {
|
|
@@ -6,14 +6,21 @@ export declare class AgentRunner {
|
|
|
6
6
|
private tools;
|
|
7
7
|
private agentName?;
|
|
8
8
|
private ctx?;
|
|
9
|
+
private observer?;
|
|
9
10
|
private llmAdapter;
|
|
10
11
|
private maxTokens;
|
|
11
12
|
private temperature;
|
|
12
13
|
private maxSteps;
|
|
13
14
|
private timeoutMs;
|
|
14
15
|
constructor(agentProps: FlinkAgentProps<any>, tools: Map<string, ToolExecutor<any>>, llmAdapters: Map<string, LLMAdapter>, agentName?: string | undefined, // Optional agent name for logging
|
|
15
|
-
ctx?: any)
|
|
16
|
+
ctx?: any, // FlinkContext for instruction callbacks (any for flexibility)
|
|
17
|
+
observer?: AgentObserver | undefined);
|
|
16
18
|
streamGenerator(input: AgentExecuteInput): AsyncGenerator<StreamChunk>;
|
|
19
|
+
/**
|
|
20
|
+
* Fire-and-forget observer dispatch: catches synchronous throws and
|
|
21
|
+
* rejected promises so observer failures never break agent execution.
|
|
22
|
+
*/
|
|
23
|
+
private safeDispatch;
|
|
17
24
|
/**
|
|
18
25
|
* Convert Message[] to LLM message format
|
|
19
26
|
* Supports multi-turn conversations with history
|