@flink-app/flink 0.14.3 → 2.0.0-alpha.100
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 +1051 -0
- package/SCHEMA_EXTRACTION_ANALYSIS.md +494 -0
- package/SIMPLE_AST_FEASIBILITY.md +570 -0
- package/bin/flink.ts +13 -2
- package/cli/build.ts +24 -44
- package/cli/clean.ts +13 -25
- package/cli/cli-utils.ts +190 -17
- package/cli/dev.ts +252 -0
- package/cli/loadEnvFiles.ts +116 -0
- package/cli/run.ts +45 -62
- package/dist/bin/flink.js +61 -2
- package/dist/cli/build.js +20 -25
- package/dist/cli/clean.js +12 -10
- package/dist/cli/cli-utils.d.ts +34 -3
- package/dist/cli/cli-utils.js +193 -12
- package/dist/cli/dev.d.ts +2 -0
- package/dist/cli/dev.js +279 -0
- package/dist/cli/loadEnvFiles.d.ts +30 -0
- package/dist/cli/loadEnvFiles.js +113 -0
- package/dist/cli/run.js +47 -46
- package/dist/src/DependencyTracker.d.ts +44 -0
- package/dist/src/DependencyTracker.js +239 -0
- package/dist/src/FlinkApp.d.ts +163 -10
- package/dist/src/FlinkApp.js +847 -184
- package/dist/src/FlinkContext.d.ts +41 -0
- package/dist/src/FlinkErrors.d.ts +19 -6
- package/dist/src/FlinkErrors.js +36 -42
- package/dist/src/FlinkHttpHandler.d.ts +219 -26
- package/dist/src/FlinkHttpHandler.js +37 -1
- package/dist/src/FlinkJob.d.ts +10 -0
- package/dist/src/FlinkLog.d.ts +82 -18
- package/dist/src/FlinkLog.js +165 -13
- package/dist/src/FlinkLogFactory.d.ts +288 -0
- package/dist/src/FlinkLogFactory.js +619 -0
- package/dist/src/FlinkRepo.d.ts +10 -2
- package/dist/src/FlinkRepo.js +11 -1
- package/dist/src/FlinkRequestContext.d.ts +63 -0
- package/dist/src/FlinkRequestContext.js +74 -0
- package/dist/src/FlinkResponse.d.ts +6 -0
- package/dist/src/FlinkService.d.ts +38 -0
- package/dist/src/FlinkService.js +46 -0
- package/dist/src/LeaderElection.d.ts +45 -0
- package/dist/src/LeaderElection.js +269 -0
- package/dist/src/SchemaCache.d.ts +84 -0
- package/dist/src/SchemaCache.js +289 -0
- package/dist/src/TypeScriptCompiler.d.ts +161 -51
- package/dist/src/TypeScriptCompiler.js +1253 -617
- package/dist/src/TypeScriptUtils.js +4 -0
- package/dist/src/ai/AgentRunner.d.ts +39 -0
- package/dist/src/ai/AgentRunner.js +760 -0
- package/dist/src/ai/ConversationAgent.d.ts +279 -0
- package/dist/src/ai/ConversationAgent.js +404 -0
- package/dist/src/ai/ConversationFlinkAgent.d.ts +278 -0
- package/dist/src/ai/ConversationFlinkAgent.js +404 -0
- package/dist/src/ai/FlinkAgent.d.ts +690 -0
- package/dist/src/ai/FlinkAgent.js +729 -0
- package/dist/src/ai/FlinkTool.d.ts +135 -0
- package/dist/src/ai/FlinkTool.js +2 -0
- package/dist/src/ai/InMemoryConversationAgent.d.ts +121 -0
- package/dist/src/ai/InMemoryConversationAgent.js +209 -0
- package/dist/src/ai/LLMAdapter.d.ts +148 -0
- package/dist/src/ai/LLMAdapter.js +2 -0
- package/dist/src/ai/PersistentFlinkAgent.d.ts +278 -0
- package/dist/src/ai/PersistentFlinkAgent.js +403 -0
- package/dist/src/ai/SubAgentExecutor.d.ts +38 -0
- package/dist/src/ai/SubAgentExecutor.js +223 -0
- package/dist/src/ai/ToolExecutor.d.ts +64 -0
- package/dist/src/ai/ToolExecutor.js +497 -0
- package/dist/src/ai/agentInstructions.d.ts +68 -0
- package/dist/src/ai/agentInstructions.js +286 -0
- package/dist/src/ai/index.d.ts +8 -0
- package/dist/src/ai/index.js +26 -0
- package/dist/src/ai/instructionFileLoader.d.ts +44 -0
- package/dist/src/ai/instructionFileLoader.js +179 -0
- package/dist/src/auth/FlinkAuthPlugin.d.ts +1 -1
- package/dist/src/handlers/StreamWriterFactory.d.ts +20 -0
- package/dist/src/handlers/StreamWriterFactory.js +83 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.js +17 -0
- package/dist/src/loadPluginSchemas.d.ts +45 -0
- package/dist/src/loadPluginSchemas.js +143 -0
- package/dist/src/schema-extraction/ComplexTypeDetection.d.ts +40 -0
- package/dist/src/schema-extraction/ComplexTypeDetection.js +75 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.d.ts +321 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.js +925 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.spec.d.ts +1 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.spec.js +233 -0
- package/dist/src/schema-extraction/TypeScriptTokenizer.d.ts +57 -0
- package/dist/src/schema-extraction/TypeScriptTokenizer.js +177 -0
- package/dist/src/schema-extraction/index.d.ts +2 -0
- package/dist/src/schema-extraction/index.js +20 -0
- package/dist/src/schema-extraction/types.d.ts +31 -0
- package/dist/src/schema-extraction/types.js +2 -0
- package/dist/src/utils/loadFlinkConfig.d.ts +53 -0
- package/dist/src/utils/loadFlinkConfig.js +77 -0
- package/dist/src/utils.d.ts +30 -0
- package/dist/src/utils.js +52 -0
- package/dist/src/workers/SchemaGeneratorWorker.d.ts +1 -0
- package/dist/src/workers/SchemaGeneratorWorker.js +49 -0
- package/dist/src/workers/WorkerPool.d.ts +60 -0
- package/dist/src/workers/WorkerPool.js +306 -0
- package/examples/logging-hierarchical-example.ts +125 -0
- package/package.json +29 -4
- package/readme.md +499 -0
- package/spec/AgentDescendantDetection.spec.ts +335 -0
- package/spec/AgentDuplicateDetection.spec.ts +112 -0
- package/spec/AgentObserver.spec.ts +266 -0
- package/spec/AgentRunner.spec.ts +1062 -0
- package/spec/AsyncLocalStorageContext.spec.ts +223 -0
- package/spec/ConversationHooks.spec.ts +257 -0
- package/spec/FlinkAgent.spec.ts +681 -0
- package/spec/FlinkApp.htmlResponse.spec.ts +260 -0
- package/spec/FlinkApp.onError.invocation.spec.ts +151 -0
- package/spec/FlinkApp.onError.spec.ts +1 -2
- package/spec/FlinkApp.query.spec.ts +107 -0
- package/spec/FlinkApp.routeOrdering.spec.ts +61 -0
- package/spec/FlinkApp.undefinedResponse.spec.ts +123 -0
- package/spec/FlinkApp.validationMode.spec.ts +155 -0
- package/spec/FlinkJob.spec.ts +171 -0
- package/spec/FlinkLogFactory.spec.ts +337 -0
- package/spec/FlinkRepo.spec.ts +1 -1
- package/spec/LeaderElection.spec.ts +174 -0
- package/spec/StreamingIntegration.spec.ts +139 -0
- package/spec/ToolExecutor.spec.ts +465 -0
- package/spec/TypeScriptCompiler.spec.ts +1 -1
- package/spec/TypeScriptSourceParser.spec.ts +1215 -0
- package/spec/TypeScriptTokenizer.spec.ts +366 -0
- package/spec/ai/ContextCompaction.spec.ts +405 -0
- package/spec/ai/ConversationAgent.spec.ts +520 -0
- package/spec/ai/InMemoryConversationAgent.spec.ts +144 -0
- package/spec/ai/agentInstructions.spec.ts +358 -0
- package/spec/fixtures/agent-instructions/TestAgent.ts +24 -0
- package/spec/fixtures/agent-instructions/simple.md +3 -0
- package/spec/fixtures/agent-instructions/template.md +18 -0
- package/spec/fixtures/agent-instructions/yaml-format.yaml +9 -0
- package/spec/mock-project/dist/.tsbuildinfo +1 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar.js +56 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar2.js +58 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema.js +52 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema2.js +52 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema3.js +52 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema2.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile2.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler.js +53 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler2.js +55 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchCar.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOnboardingSession.js +75 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOrderWithComplexTypes.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchProductWithIntersection.js +58 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchUserWithUnion.js +58 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PostCar.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogin.js +55 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogout.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PutCar.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/index.js +83 -0
- package/spec/mock-project/dist/spec/mock-project/src/repos/CarRepo.js +26 -0
- package/spec/mock-project/dist/spec/mock-project/src/schemas/Car.js +2 -0
- package/spec/mock-project/dist/spec/mock-project/src/schemas/DefaultExportSchema.js +2 -0
- package/spec/mock-project/dist/spec/mock-project/src/schemas/FileWithTwoSchemas.js +2 -0
- package/spec/mock-project/dist/src/FlinkApp.js +1000 -0
- package/spec/mock-project/dist/src/FlinkContext.js +2 -0
- package/spec/mock-project/dist/src/FlinkErrors.js +143 -0
- package/spec/mock-project/dist/src/FlinkHttpHandler.js +47 -0
- package/spec/mock-project/dist/src/FlinkJob.js +2 -0
- package/spec/mock-project/dist/src/FlinkLog.js +119 -0
- package/spec/mock-project/dist/src/FlinkLogFactory.js +617 -0
- package/spec/mock-project/dist/src/FlinkPlugin.js +2 -0
- package/spec/mock-project/dist/src/FlinkRepo.js +224 -0
- package/spec/mock-project/dist/src/FlinkRequestContext.js +74 -0
- package/spec/mock-project/dist/src/FlinkResponse.js +2 -0
- package/spec/mock-project/dist/src/ai/AgentExecutor.js +279 -0
- package/spec/mock-project/dist/src/ai/AgentRunner.js +632 -0
- package/spec/mock-project/dist/src/ai/ConversationAgent.js +402 -0
- package/spec/mock-project/dist/src/ai/ConversationFlinkAgent.js +422 -0
- package/spec/mock-project/dist/src/ai/FlinkAgent.js +699 -0
- package/spec/mock-project/dist/src/ai/FlinkTool.js +2 -0
- package/spec/mock-project/dist/src/ai/InMemoryConversationAgent.js +209 -0
- package/spec/mock-project/dist/src/ai/LLMAdapter.js +2 -0
- package/spec/mock-project/dist/src/ai/SubAgentExecutor.js +223 -0
- package/spec/mock-project/dist/src/ai/ToolExecutor.js +412 -0
- package/spec/mock-project/dist/src/ai/agentInstructions.js +246 -0
- package/spec/mock-project/dist/src/auth/FlinkAuthPlugin.js +2 -0
- package/spec/mock-project/dist/src/auth/FlinkAuthUser.js +2 -0
- package/spec/mock-project/dist/src/handlers/GetCar.js +26 -52
- package/spec/mock-project/dist/src/handlers/GetCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCar2.js +32 -54
- package/spec/mock-project/dist/src/handlers/GetCar2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js +26 -48
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js +28 -48
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js +29 -48
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js +26 -50
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js +28 -50
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js +27 -53
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js +29 -53
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js +16 -49
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js +25 -50
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchCar.js +27 -53
- package/spec/mock-project/dist/src/handlers/PatchCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchOnboardingSession.js +44 -70
- package/spec/mock-project/dist/src/handlers/PatchOnboardingSession.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchOrderWithComplexTypes.js +27 -53
- package/spec/mock-project/dist/src/handlers/PatchOrderWithComplexTypes.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchProductWithIntersection.js +28 -54
- package/spec/mock-project/dist/src/handlers/PatchProductWithIntersection.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchUserWithUnion.js +28 -54
- package/spec/mock-project/dist/src/handlers/PatchUserWithUnion.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PostCar.js +24 -50
- package/spec/mock-project/dist/src/handlers/PostCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PostLogin.js +25 -51
- package/spec/mock-project/dist/src/handlers/PostLogin.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PostLogout.js +24 -50
- package/spec/mock-project/dist/src/handlers/PostLogout.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PutCar.js +24 -50
- package/spec/mock-project/dist/src/handlers/PutCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/StreamWriterFactory.js +83 -0
- package/spec/mock-project/dist/src/index.js +52 -76
- package/spec/mock-project/dist/src/index.js.map +1 -0
- package/spec/mock-project/dist/src/mock-data-generator.js +9 -0
- package/spec/mock-project/dist/src/repos/CarRepo.js +12 -24
- package/spec/mock-project/dist/src/repos/CarRepo.js.map +1 -0
- package/spec/mock-project/dist/src/schemas/Car.js +3 -1
- package/spec/mock-project/dist/src/schemas/Car.js.map +1 -0
- package/spec/mock-project/dist/src/schemas/DefaultExportSchema.js +3 -1
- package/spec/mock-project/dist/src/schemas/DefaultExportSchema.js.map +1 -0
- package/spec/mock-project/dist/src/schemas/FileWithTwoSchemas.js +3 -1
- package/spec/mock-project/dist/src/schemas/FileWithTwoSchemas.js.map +1 -0
- package/spec/mock-project/dist/src/utils.js +290 -0
- package/spec/mock-project/tsconfig.json +6 -1
- package/spec/schema-generation-nested-objects.spec.ts +97 -0
- package/spec/testHelpers.ts +49 -0
- package/spec/utils.caseConversion.spec.ts +78 -0
- package/spec/utils.spec.ts +13 -13
- package/src/DependencyTracker.ts +166 -0
- package/src/FlinkApp.ts +919 -155
- package/src/FlinkContext.ts +43 -0
- package/src/FlinkErrors.ts +32 -12
- package/src/FlinkHttpHandler.ts +246 -28
- package/src/FlinkJob.ts +11 -0
- package/src/FlinkLog.ts +119 -12
- package/src/FlinkLogFactory.ts +699 -0
- package/src/FlinkRepo.ts +10 -3
- package/src/FlinkRequestContext.ts +95 -0
- package/src/FlinkResponse.ts +6 -0
- package/src/FlinkService.ts +49 -0
- package/src/LeaderElection.ts +203 -0
- package/src/SchemaCache.ts +232 -0
- package/src/TypeScriptCompiler.ts +1347 -610
- package/src/TypeScriptUtils.ts +5 -0
- package/src/ai/AgentRunner.ts +646 -0
- package/src/ai/ConversationAgent.ts +413 -0
- package/src/ai/FlinkAgent.ts +1069 -0
- package/src/ai/FlinkTool.ts +165 -0
- package/src/ai/InMemoryConversationAgent.ts +149 -0
- package/src/ai/LLMAdapter.ts +126 -0
- package/src/ai/ToolExecutor.ts +485 -0
- package/src/ai/agentInstructions.ts +245 -0
- package/src/ai/index.ts +8 -0
- package/src/ai/instructionFileLoader.ts +156 -0
- package/src/auth/FlinkAuthPlugin.ts +2 -1
- package/src/handlers/StreamWriterFactory.ts +84 -0
- package/src/index.ts +14 -0
- package/src/loadPluginSchemas.ts +141 -0
- package/src/schema-extraction/TypeScriptSourceParser.ts +1058 -0
- package/src/schema-extraction/TypeScriptTokenizer.ts +205 -0
- package/src/schema-extraction/index.ts +2 -0
- package/src/schema-extraction/types.ts +34 -0
- package/src/utils/loadFlinkConfig.ts +89 -0
- package/src/utils.ts +52 -0
- package/tsconfig.json +6 -1
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
AgentExecuteInput,
|
|
4
|
+
AgentObserver,
|
|
5
|
+
FlinkAgent,
|
|
6
|
+
} from "../src/ai/FlinkAgent";
|
|
7
|
+
import { FlinkToolProps } from "../src/ai/FlinkTool";
|
|
8
|
+
import { LLMAdapter, LLMMessage, LLMStreamChunk } from "../src/ai/LLMAdapter";
|
|
9
|
+
import { ToolExecutor } from "../src/ai/ToolExecutor";
|
|
10
|
+
import { FlinkContext } from "../src/FlinkContext";
|
|
11
|
+
import { createStreamingMock } from "./testHelpers";
|
|
12
|
+
|
|
13
|
+
function makeAgent(opts: {
|
|
14
|
+
adapter: LLMAdapter;
|
|
15
|
+
tools?: { [id: string]: ToolExecutor<any> };
|
|
16
|
+
declaredToolNames?: string[];
|
|
17
|
+
observer?: AgentObserver;
|
|
18
|
+
compact?: boolean;
|
|
19
|
+
ctx?: FlinkContext;
|
|
20
|
+
permissions?: string | string[] | ((user?: any) => boolean);
|
|
21
|
+
}) {
|
|
22
|
+
const ctx: FlinkContext = opts.ctx ?? { repos: {}, plugins: {}, agents: {} };
|
|
23
|
+
const declared = opts.declaredToolNames ?? Object.keys(opts.tools ?? {});
|
|
24
|
+
|
|
25
|
+
class TestAgent extends FlinkAgent<FlinkContext> {
|
|
26
|
+
id = "test-agent";
|
|
27
|
+
description = "Test agent";
|
|
28
|
+
instructions() {
|
|
29
|
+
return "Test instructions";
|
|
30
|
+
}
|
|
31
|
+
tools: string[] = declared;
|
|
32
|
+
|
|
33
|
+
permissions = opts.permissions;
|
|
34
|
+
|
|
35
|
+
// Force compaction to a single-message window to verify onLlmCall sees post-compaction state
|
|
36
|
+
protected shouldCompact = opts.compact ? () => true : undefined;
|
|
37
|
+
protected compactHistory = opts.compact ? (msgs: LLMMessage[]) => msgs.slice(-1) : undefined;
|
|
38
|
+
|
|
39
|
+
async query(input: AgentExecuteInput) {
|
|
40
|
+
const response = this.execute(input);
|
|
41
|
+
return await response.result;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const agent = new TestAgent();
|
|
46
|
+
(agent as any).ctx = ctx;
|
|
47
|
+
agent.__init(
|
|
48
|
+
new Map([["default", opts.adapter]]),
|
|
49
|
+
opts.tools ?? {},
|
|
50
|
+
opts.observer
|
|
51
|
+
);
|
|
52
|
+
return agent;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
describe("AgentObserver", () => {
|
|
56
|
+
let mockCtx: FlinkContext;
|
|
57
|
+
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
mockCtx = { repos: {}, plugins: {}, agents: {} };
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("fires onRun once with resolved instructions and initial messages", async () => {
|
|
63
|
+
const onRun = jasmine.createSpy("onRun");
|
|
64
|
+
const adapter = createStreamingMock([
|
|
65
|
+
{ textContent: "Hello", toolCalls: [], usage: { inputTokens: 1, outputTokens: 2 }, stopReason: "end_turn" },
|
|
66
|
+
]);
|
|
67
|
+
const agent = makeAgent({ adapter, observer: { onRun }, ctx: mockCtx });
|
|
68
|
+
|
|
69
|
+
await (agent as any).query({ message: "hi" });
|
|
70
|
+
|
|
71
|
+
expect(onRun).toHaveBeenCalledTimes(1);
|
|
72
|
+
const event = onRun.calls.mostRecent().args[0];
|
|
73
|
+
expect(event.agentId).toBe("test-agent");
|
|
74
|
+
expect(event.instructions).toBe("Test instructions");
|
|
75
|
+
expect(event.messages.length).toBe(1);
|
|
76
|
+
expect(event.messages[0].content).toBe("hi");
|
|
77
|
+
expect(typeof event.runId).toBe("string");
|
|
78
|
+
expect(event.runId.length).toBeGreaterThan(0);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("fires onLlmCall per step with post-compaction messages", async () => {
|
|
82
|
+
const onLlmCall = jasmine.createSpy("onLlmCall");
|
|
83
|
+
const adapter = createStreamingMock([
|
|
84
|
+
{ textContent: "done", toolCalls: [], usage: { inputTokens: 1, outputTokens: 2 }, stopReason: "end_turn" },
|
|
85
|
+
]);
|
|
86
|
+
const agent = makeAgent({ adapter, observer: { onLlmCall }, compact: true, ctx: mockCtx });
|
|
87
|
+
|
|
88
|
+
await (agent as any).query({
|
|
89
|
+
message: "new",
|
|
90
|
+
history: [
|
|
91
|
+
{ role: "user", content: "1" },
|
|
92
|
+
{ role: "assistant", content: "2" },
|
|
93
|
+
{ role: "user", content: "3" },
|
|
94
|
+
],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(onLlmCall).toHaveBeenCalledTimes(1);
|
|
98
|
+
const event = onLlmCall.calls.mostRecent().args[0];
|
|
99
|
+
// Compaction takes slice(-1) so only one message is sent to the LLM
|
|
100
|
+
expect(event.messages.length).toBe(1);
|
|
101
|
+
expect(event.step).toBe(1);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("fires onStep per step with assistantText, per-step toolCalls, usage", async () => {
|
|
105
|
+
const onStep = jasmine.createSpy("onStep");
|
|
106
|
+
|
|
107
|
+
const toolProps: FlinkToolProps = {
|
|
108
|
+
id: "t",
|
|
109
|
+
description: "test",
|
|
110
|
+
inputSchema: z.object({}),
|
|
111
|
+
};
|
|
112
|
+
const toolFn = jasmine.createSpy("toolFn").and.returnValue(Promise.resolve({ success: true, data: { ok: true } }));
|
|
113
|
+
const toolExecutor = new ToolExecutor(toolProps, toolFn as any, mockCtx);
|
|
114
|
+
|
|
115
|
+
const adapter = createStreamingMock([
|
|
116
|
+
{
|
|
117
|
+
textContent: "thinking",
|
|
118
|
+
toolCalls: [{ id: "a", name: "t", input: {} }],
|
|
119
|
+
usage: { inputTokens: 10, outputTokens: 5 },
|
|
120
|
+
stopReason: "tool_use",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
textContent: "done",
|
|
124
|
+
toolCalls: [],
|
|
125
|
+
usage: { inputTokens: 2, outputTokens: 3 },
|
|
126
|
+
stopReason: "end_turn",
|
|
127
|
+
},
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
const agent = makeAgent({
|
|
131
|
+
adapter,
|
|
132
|
+
observer: { onStep },
|
|
133
|
+
tools: { t: toolExecutor },
|
|
134
|
+
declaredToolNames: ["t"],
|
|
135
|
+
ctx: mockCtx,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await (agent as any).query({ message: "go" });
|
|
139
|
+
|
|
140
|
+
expect(onStep).toHaveBeenCalledTimes(2);
|
|
141
|
+
const step1 = onStep.calls.all()[0].args[0];
|
|
142
|
+
const step2 = onStep.calls.all()[1].args[0];
|
|
143
|
+
|
|
144
|
+
expect(step1.step).toBe(1);
|
|
145
|
+
expect(step1.assistantText).toBe("thinking");
|
|
146
|
+
expect(step1.toolCalls.length).toBe(1);
|
|
147
|
+
expect(step1.toolCalls[0].name).toBe("t");
|
|
148
|
+
expect(step1.usage).toEqual(jasmine.objectContaining({ inputTokens: 10, outputTokens: 5 }));
|
|
149
|
+
|
|
150
|
+
expect(step2.step).toBe(2);
|
|
151
|
+
expect(step2.assistantText).toBe("done");
|
|
152
|
+
// step2 has no new tool calls
|
|
153
|
+
expect(step2.toolCalls.length).toBe(0);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("fires onFinish with result.runId matching earlier events' runId", async () => {
|
|
157
|
+
const events: any[] = [];
|
|
158
|
+
const adapter = createStreamingMock([
|
|
159
|
+
{ textContent: "ok", toolCalls: [], usage: { inputTokens: 1, outputTokens: 2 }, stopReason: "end_turn" },
|
|
160
|
+
]);
|
|
161
|
+
const observer: AgentObserver = {
|
|
162
|
+
onRun: (e) => { events.push({ kind: "run", runId: e.runId }); },
|
|
163
|
+
onLlmCall: (e) => { events.push({ kind: "llm", runId: e.runId }); },
|
|
164
|
+
onStep: (e) => { events.push({ kind: "step", runId: e.runId }); },
|
|
165
|
+
onFinish: (e) => { events.push({ kind: "finish", runId: e.runId, resultRunId: e.result.runId }); },
|
|
166
|
+
};
|
|
167
|
+
const agent = makeAgent({ adapter, observer, ctx: mockCtx });
|
|
168
|
+
|
|
169
|
+
const result = await (agent as any).query({ message: "hi" });
|
|
170
|
+
|
|
171
|
+
const runIds = new Set(events.map((e) => e.runId));
|
|
172
|
+
expect(runIds.size).toBe(1);
|
|
173
|
+
const runId = events[0].runId;
|
|
174
|
+
expect(result.runId).toBe(runId);
|
|
175
|
+
const finish = events.find((e) => e.kind === "finish");
|
|
176
|
+
expect(finish.resultRunId).toBe(runId);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("fires onFinish with error populated when adapter throws", async () => {
|
|
180
|
+
const onFinish = jasmine.createSpy("onFinish");
|
|
181
|
+
const adapter: LLMAdapter = {
|
|
182
|
+
stream: jasmine.createSpy("stream").and.callFake(async function* () {
|
|
183
|
+
throw new Error("adapter boom");
|
|
184
|
+
yield {} as LLMStreamChunk; // unreachable, makes TS happy
|
|
185
|
+
}),
|
|
186
|
+
};
|
|
187
|
+
const agent = makeAgent({ adapter, observer: { onFinish }, ctx: mockCtx });
|
|
188
|
+
|
|
189
|
+
await expectAsync((agent as any).query({ message: "hi" })).toBeRejectedWithError(/adapter boom/);
|
|
190
|
+
|
|
191
|
+
expect(onFinish).toHaveBeenCalledTimes(1);
|
|
192
|
+
const event = onFinish.calls.mostRecent().args[0];
|
|
193
|
+
expect(event.error).toMatch(/adapter boom/);
|
|
194
|
+
expect(typeof event.runId).toBe("string");
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("swallowed observer errors do not break execution", async () => {
|
|
198
|
+
const adapter = createStreamingMock([
|
|
199
|
+
{ textContent: "ok", toolCalls: [], usage: { inputTokens: 1, outputTokens: 2 }, stopReason: "end_turn" },
|
|
200
|
+
]);
|
|
201
|
+
const observer: AgentObserver = {
|
|
202
|
+
onRun: () => { throw new Error("sync boom"); },
|
|
203
|
+
onLlmCall: async () => { throw new Error("async boom"); },
|
|
204
|
+
onStep: () => { throw new Error("step boom"); },
|
|
205
|
+
onFinish: () => { throw new Error("finish boom"); },
|
|
206
|
+
};
|
|
207
|
+
const agent = makeAgent({ adapter, observer, ctx: mockCtx });
|
|
208
|
+
|
|
209
|
+
const result = await (agent as any).query({ message: "hi" });
|
|
210
|
+
expect(result.message).toBe("ok");
|
|
211
|
+
expect(result.runId).toBeDefined();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("AgentExecuteResult.runId is populated on success", async () => {
|
|
215
|
+
const adapter = createStreamingMock([
|
|
216
|
+
{ textContent: "ok", toolCalls: [], usage: { inputTokens: 1, outputTokens: 2 }, stopReason: "end_turn" },
|
|
217
|
+
]);
|
|
218
|
+
const agent = makeAgent({ adapter, ctx: mockCtx });
|
|
219
|
+
|
|
220
|
+
const result = await (agent as any).query({ message: "hi" });
|
|
221
|
+
expect(typeof result.runId).toBe("string");
|
|
222
|
+
expect(result.runId.length).toBeGreaterThan(0);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("onLlmCall.tools reflects permission filtering", async () => {
|
|
226
|
+
const onLlmCall = jasmine.createSpy("onLlmCall");
|
|
227
|
+
|
|
228
|
+
const allowedProps: FlinkToolProps = {
|
|
229
|
+
id: "allowed",
|
|
230
|
+
description: "no perms required",
|
|
231
|
+
inputSchema: z.object({}),
|
|
232
|
+
};
|
|
233
|
+
const deniedProps: FlinkToolProps = {
|
|
234
|
+
id: "denied",
|
|
235
|
+
description: "requires admin",
|
|
236
|
+
inputSchema: z.object({}),
|
|
237
|
+
permissions: ["admin"],
|
|
238
|
+
};
|
|
239
|
+
const allowedFn = jasmine.createSpy("allowedFn").and.returnValue(Promise.resolve({ success: true, data: {} }));
|
|
240
|
+
const deniedFn = jasmine.createSpy("deniedFn").and.returnValue(Promise.resolve({ success: true, data: {} }));
|
|
241
|
+
|
|
242
|
+
const allowed = new ToolExecutor(allowedProps, allowedFn as any, mockCtx);
|
|
243
|
+
const denied = new ToolExecutor(deniedProps, deniedFn as any, mockCtx);
|
|
244
|
+
|
|
245
|
+
const adapter = createStreamingMock([
|
|
246
|
+
{ textContent: "ok", toolCalls: [], usage: { inputTokens: 1, outputTokens: 2 }, stopReason: "end_turn" },
|
|
247
|
+
]);
|
|
248
|
+
const agent = makeAgent({
|
|
249
|
+
adapter,
|
|
250
|
+
observer: { onLlmCall },
|
|
251
|
+
tools: { allowed, denied },
|
|
252
|
+
declaredToolNames: ["allowed", "denied"],
|
|
253
|
+
ctx: mockCtx,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
await (agent as any).query({
|
|
257
|
+
message: "hi",
|
|
258
|
+
user: { id: "u1" },
|
|
259
|
+
userPermissions: [], // no admin perm → denied tool filtered out
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
const event = onLlmCall.calls.mostRecent().args[0];
|
|
263
|
+
expect(event.tools).toContain("allowed");
|
|
264
|
+
expect(event.tools).not.toContain("denied");
|
|
265
|
+
});
|
|
266
|
+
});
|