veryfront 0.1.64 → 0.1.65
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/esm/deno.js +1 -1
- package/esm/src/agent/runtime/index.d.ts +1 -0
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +10 -2
- package/esm/src/channels/control-plane.d.ts +259 -0
- package/esm/src/channels/control-plane.d.ts.map +1 -0
- package/esm/src/channels/control-plane.js +212 -0
- package/esm/src/channels/invoke.d.ts +3 -40
- package/esm/src/channels/invoke.d.ts.map +1 -1
- package/esm/src/channels/invoke.js +9 -106
- package/esm/src/internal-agents/ag-ui-sse.d.ts +35 -0
- package/esm/src/internal-agents/ag-ui-sse.d.ts.map +1 -0
- package/esm/src/internal-agents/ag-ui-sse.js +263 -0
- package/esm/src/internal-agents/control-plane-auth.d.ts +20 -0
- package/esm/src/internal-agents/control-plane-auth.d.ts.map +1 -0
- package/esm/src/internal-agents/control-plane-auth.js +56 -0
- package/esm/src/internal-agents/request-body.d.ts +9 -0
- package/esm/src/internal-agents/request-body.d.ts.map +1 -0
- package/esm/src/internal-agents/request-body.js +28 -0
- package/esm/src/internal-agents/run-stream.d.ts +14 -0
- package/esm/src/internal-agents/run-stream.d.ts.map +1 -0
- package/esm/src/internal-agents/run-stream.js +259 -0
- package/esm/src/internal-agents/schema.d.ts +268 -0
- package/esm/src/internal-agents/schema.d.ts.map +1 -0
- package/esm/src/internal-agents/schema.js +71 -0
- package/esm/src/internal-agents/session-manager.d.ts +63 -0
- package/esm/src/internal-agents/session-manager.d.ts.map +1 -0
- package/esm/src/internal-agents/session-manager.js +258 -0
- package/esm/src/platform/adapters/runtime/deno/adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/runtime/deno/adapter.js +4 -13
- package/esm/src/platform/compat/process.d.ts.map +1 -1
- package/esm/src/platform/compat/process.js +42 -5
- package/esm/src/server/handlers/request/agent-run-cancel.handler.d.ts +11 -0
- package/esm/src/server/handlers/request/agent-run-cancel.handler.d.ts.map +1 -0
- package/esm/src/server/handlers/request/agent-run-cancel.handler.js +62 -0
- package/esm/src/server/handlers/request/agent-run-resume.handler.d.ts +11 -0
- package/esm/src/server/handlers/request/agent-run-resume.handler.d.ts.map +1 -0
- package/esm/src/server/handlers/request/agent-run-resume.handler.js +77 -0
- package/esm/src/server/handlers/request/agent-stream.handler.d.ts +14 -0
- package/esm/src/server/handlers/request/agent-stream.handler.d.ts.map +1 -0
- package/esm/src/server/handlers/request/agent-stream.handler.js +86 -0
- package/esm/src/server/handlers/request/{channel-assistants.handler.d.ts → internal-agents-list.handler.d.ts} +4 -4
- package/esm/src/server/handlers/request/internal-agents-list.handler.d.ts.map +1 -0
- package/esm/src/server/handlers/request/internal-agents-list.handler.js +73 -0
- package/esm/src/server/runtime-handler/index.d.ts.map +1 -1
- package/esm/src/server/runtime-handler/index.js +8 -2
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/agent/runtime/index.ts +12 -2
- package/src/src/channels/control-plane.ts +332 -0
- package/src/src/channels/invoke.ts +12 -157
- package/src/src/internal-agents/ag-ui-sse.ts +327 -0
- package/src/src/internal-agents/control-plane-auth.ts +82 -0
- package/src/src/internal-agents/request-body.ts +42 -0
- package/src/src/internal-agents/run-stream.ts +354 -0
- package/src/src/internal-agents/schema.ts +102 -0
- package/src/src/internal-agents/session-manager.ts +358 -0
- package/src/src/platform/adapters/runtime/deno/adapter.ts +9 -11
- package/src/src/platform/compat/process.ts +56 -3
- package/src/src/server/handlers/request/agent-run-cancel.handler.ts +86 -0
- package/src/src/server/handlers/request/agent-run-resume.handler.ts +108 -0
- package/src/src/server/handlers/request/agent-stream.handler.ts +125 -0
- package/src/src/server/handlers/request/internal-agents-list.handler.ts +100 -0
- package/src/src/server/runtime-handler/index.ts +8 -2
- package/esm/src/server/handlers/request/channel-assistants.handler.d.ts.map +0 -1
- package/esm/src/server/handlers/request/channel-assistants.handler.js +0 -71
- package/src/src/server/handlers/request/channel-assistants.handler.ts +0 -94
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import * as dntShim from "../../_dnt.shims.js";
|
|
2
1
|
import { fromError } from "../errors/veryfront-error.js";
|
|
3
2
|
import { serverLogger } from "../utils/index.js";
|
|
4
|
-
import { base64urlEncodeBytes } from "../utils/base64url.js";
|
|
5
3
|
import { z } from "zod";
|
|
6
4
|
import { getAgent as getRegisteredAgent, getAllAgentIds as getRegisteredAgentIds, } from "../agent/composition/composition.js";
|
|
5
|
+
import { listRuntimeAgents } from "./control-plane.js";
|
|
7
6
|
import { ensureProjectDiscovery as ensureProjectDiscoveryForProject } from "../server/handlers/request/api/project-discovery.js";
|
|
8
7
|
const logger = serverLogger.component("channels-invoke");
|
|
9
|
-
const SIGNATURE_SKEW_SECONDS = 5;
|
|
10
8
|
const rawHistoryPartSchema = z.object({
|
|
11
9
|
type: z.string(),
|
|
12
10
|
}).passthrough();
|
|
@@ -103,117 +101,22 @@ export const ChannelInvokeResponseSchema = z.object({
|
|
|
103
101
|
retryable: z.boolean(),
|
|
104
102
|
}).optional(),
|
|
105
103
|
});
|
|
106
|
-
const dispatchHeaderSchema = z.object({
|
|
107
|
-
alg: z.literal("EdDSA"),
|
|
108
|
-
typ: z.string().optional(),
|
|
109
|
-
kid: z.string().optional(),
|
|
110
|
-
});
|
|
111
|
-
const dispatchClaimsSchema = z.object({
|
|
112
|
-
iss: z.string(),
|
|
113
|
-
aud: z.string(),
|
|
114
|
-
sub: z.string(),
|
|
115
|
-
project_id: z.string(),
|
|
116
|
-
platform: z.string(),
|
|
117
|
-
body_sha256: z.string(),
|
|
118
|
-
iat: z.number().int(),
|
|
119
|
-
exp: z.number().int(),
|
|
120
|
-
});
|
|
121
104
|
export const defaultChannelInvokeDeps = {
|
|
122
105
|
ensureProjectDiscovery: ensureProjectDiscoveryForProject,
|
|
123
106
|
getAgent: getRegisteredAgent,
|
|
124
107
|
getAllAgentIds: getRegisteredAgentIds,
|
|
125
108
|
};
|
|
126
|
-
function getAssistantMetadata(agent) {
|
|
127
|
-
const rawConfig = agent.config;
|
|
128
|
-
return ChannelAssistantSchema.parse({
|
|
129
|
-
id: agent.id,
|
|
130
|
-
name: typeof rawConfig.name === "string" && rawConfig.name.trim().length > 0
|
|
131
|
-
? rawConfig.name
|
|
132
|
-
: agent.id,
|
|
133
|
-
description: typeof rawConfig.description === "string" ? rawConfig.description : null,
|
|
134
|
-
model: agent.config.model ?? null,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
109
|
export async function listChannelAssistants(ctx, deps) {
|
|
138
|
-
await
|
|
139
|
-
const assistants =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
.
|
|
143
|
-
.
|
|
110
|
+
const response = await listRuntimeAgents(ctx, deps);
|
|
111
|
+
const assistants = response.agents.map((agent) => ChannelAssistantSchema.parse({
|
|
112
|
+
id: agent.id,
|
|
113
|
+
name: agent.name,
|
|
114
|
+
description: agent.description ?? null,
|
|
115
|
+
model: agent.model ?? null,
|
|
116
|
+
}));
|
|
144
117
|
return ChannelAssistantsResponseSchema.parse({ assistants });
|
|
145
118
|
}
|
|
146
|
-
|
|
147
|
-
const normalized = input
|
|
148
|
-
.replaceAll("-", "+")
|
|
149
|
-
.replaceAll("_", "/")
|
|
150
|
-
.padEnd(Math.ceil(input.length / 4) * 4, "=");
|
|
151
|
-
return toArrayBuffer(Uint8Array.from(atob(normalized), (char) => char.charCodeAt(0)));
|
|
152
|
-
}
|
|
153
|
-
function toArrayBuffer(bytes) {
|
|
154
|
-
const buffer = new ArrayBuffer(bytes.byteLength);
|
|
155
|
-
new Uint8Array(buffer).set(bytes);
|
|
156
|
-
return buffer;
|
|
157
|
-
}
|
|
158
|
-
function pemToDer(pem, label) {
|
|
159
|
-
const body = pem
|
|
160
|
-
.replace(`-----BEGIN ${label}-----`, "")
|
|
161
|
-
.replace(`-----END ${label}-----`, "")
|
|
162
|
-
.replace(/\s/g, "");
|
|
163
|
-
return toArrayBuffer(Uint8Array.from(atob(body), (char) => char.charCodeAt(0)));
|
|
164
|
-
}
|
|
165
|
-
async function importEd25519PublicKey(pem) {
|
|
166
|
-
return dntShim.crypto.subtle.importKey("spki", pemToDer(pem, "PUBLIC KEY"), "Ed25519", false, ["verify"]);
|
|
167
|
-
}
|
|
168
|
-
async function sha256Base64url(body) {
|
|
169
|
-
const hash = await dntShim.crypto.subtle.digest("SHA-256", new TextEncoder().encode(body));
|
|
170
|
-
return base64urlEncodeBytes(new Uint8Array(hash));
|
|
171
|
-
}
|
|
172
|
-
export async function verifyDispatchJws(jws, body, options) {
|
|
173
|
-
const parts = jws.split(".");
|
|
174
|
-
if (parts.length !== 3) {
|
|
175
|
-
throw new Error("Channel dispatch signature must be a compact JWS");
|
|
176
|
-
}
|
|
177
|
-
const encodedHeader = parts[0];
|
|
178
|
-
const encodedPayload = parts[1];
|
|
179
|
-
const encodedSignature = parts[2];
|
|
180
|
-
if (!encodedHeader || !encodedPayload || !encodedSignature) {
|
|
181
|
-
throw new Error("Channel dispatch signature must include header, payload, and signature");
|
|
182
|
-
}
|
|
183
|
-
const header = dispatchHeaderSchema.parse(JSON.parse(new TextDecoder().decode(base64urlDecodeToBytes(encodedHeader))));
|
|
184
|
-
const claims = dispatchClaimsSchema.parse(JSON.parse(new TextDecoder().decode(base64urlDecodeToBytes(encodedPayload))));
|
|
185
|
-
if (header.alg !== "EdDSA") {
|
|
186
|
-
throw new Error("Unsupported channel dispatch JWS algorithm");
|
|
187
|
-
}
|
|
188
|
-
const signingInput = new TextEncoder().encode(`${encodedHeader}.${encodedPayload}`);
|
|
189
|
-
const signature = base64urlDecodeToBytes(encodedSignature);
|
|
190
|
-
const publicKey = await importEd25519PublicKey(options.publicKeyPem);
|
|
191
|
-
const verified = await dntShim.crypto.subtle.verify("Ed25519", publicKey, signature, signingInput);
|
|
192
|
-
if (!verified) {
|
|
193
|
-
throw new Error("Channel dispatch signature verification failed");
|
|
194
|
-
}
|
|
195
|
-
if (claims.aud !== options.audience) {
|
|
196
|
-
throw new Error("Channel dispatch audience mismatch");
|
|
197
|
-
}
|
|
198
|
-
if (options.expectedProjectId && claims.project_id !== options.expectedProjectId) {
|
|
199
|
-
throw new Error("Channel dispatch project mismatch");
|
|
200
|
-
}
|
|
201
|
-
const now = Math.floor(Date.now() / 1000);
|
|
202
|
-
if (claims.exp <= now) {
|
|
203
|
-
throw new Error("Channel dispatch signature expired");
|
|
204
|
-
}
|
|
205
|
-
if (claims.iat > now + SIGNATURE_SKEW_SECONDS) {
|
|
206
|
-
throw new Error("Channel dispatch signature issued in the future");
|
|
207
|
-
}
|
|
208
|
-
if (now - claims.iat > options.maxAgeSeconds) {
|
|
209
|
-
throw new Error("Channel dispatch signature is too old");
|
|
210
|
-
}
|
|
211
|
-
const bodySha256 = await sha256Base64url(body);
|
|
212
|
-
if (claims.body_sha256 !== bodySha256) {
|
|
213
|
-
throw new Error("Channel dispatch body hash mismatch");
|
|
214
|
-
}
|
|
215
|
-
return claims;
|
|
216
|
-
}
|
|
119
|
+
export { verifyDispatchJws } from "./control-plane.js";
|
|
217
120
|
function normalizeConversationPart(part) {
|
|
218
121
|
if (part.type === "text" && typeof part.text === "string") {
|
|
219
122
|
return { type: "text", text: part.text };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AgentResponse } from "../agent/index.js";
|
|
2
|
+
type RuntimeDataEvent = Record<string, unknown> & {
|
|
3
|
+
type: string;
|
|
4
|
+
};
|
|
5
|
+
export interface RunFinishedMetadata {
|
|
6
|
+
provider?: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
inputTokens?: number;
|
|
9
|
+
outputTokens?: number;
|
|
10
|
+
totalTokens?: number;
|
|
11
|
+
finishReason?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface StreamTransformState {
|
|
14
|
+
messageId: string | null;
|
|
15
|
+
textOpen: boolean;
|
|
16
|
+
stepIndex: number;
|
|
17
|
+
sawTerminalError: boolean;
|
|
18
|
+
metadata: RunFinishedMetadata;
|
|
19
|
+
}
|
|
20
|
+
export declare function createStreamTransformState(): StreamTransformState;
|
|
21
|
+
export declare function formatAgUiEvent(event: string, payload: Record<string, unknown>): Uint8Array;
|
|
22
|
+
export declare function parseSseJsonEvents(chunk: string): {
|
|
23
|
+
events: RuntimeDataEvent[];
|
|
24
|
+
remainder: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function mapRuntimeEventToAgUi(state: StreamTransformState, event: RuntimeDataEvent): Array<{
|
|
27
|
+
event: string;
|
|
28
|
+
payload: Record<string, unknown>;
|
|
29
|
+
}>;
|
|
30
|
+
export declare function finalizeRunEvents(state: StreamTransformState, response: AgentResponse | null): Array<{
|
|
31
|
+
event: string;
|
|
32
|
+
payload: Record<string, unknown>;
|
|
33
|
+
}>;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=ag-ui-sse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ag-ui-sse.d.ts","sourceRoot":"","sources":["../../../src/src/internal-agents/ag-ui-sse.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOvD,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED,wBAAgB,0BAA0B,IAAI,oBAAoB,CAQjE;AA2DD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAI3F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IACjD,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB,CAyBA;AAkDD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,oBAAoB,EAC3B,KAAK,EAAE,gBAAgB,GACtB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAoH5D;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,oBAAoB,EAC3B,QAAQ,EAAE,aAAa,GAAG,IAAI,GAC7B,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAwB5D"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import { serverLogger } from "../utils/index.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
const logger = serverLogger.component("internal-agents-ag-ui-sse");
|
|
6
|
+
export function createStreamTransformState() {
|
|
7
|
+
return {
|
|
8
|
+
messageId: null,
|
|
9
|
+
textOpen: false,
|
|
10
|
+
stepIndex: 0,
|
|
11
|
+
sawTerminalError: false,
|
|
12
|
+
metadata: {},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const agUiEventPayloadSchemas = {
|
|
16
|
+
RunStarted: z.object({
|
|
17
|
+
runId: z.string().min(1),
|
|
18
|
+
threadId: z.string().min(1),
|
|
19
|
+
agentId: z.string().min(1),
|
|
20
|
+
}),
|
|
21
|
+
TextMessageStart: z.object({
|
|
22
|
+
messageId: z.string().min(1),
|
|
23
|
+
role: z.literal("assistant"),
|
|
24
|
+
}),
|
|
25
|
+
TextMessageContent: z.object({
|
|
26
|
+
messageId: z.string().min(1),
|
|
27
|
+
delta: z.string(),
|
|
28
|
+
}),
|
|
29
|
+
TextMessageEnd: z.object({
|
|
30
|
+
messageId: z.string().min(1),
|
|
31
|
+
}),
|
|
32
|
+
ToolCallStart: z.object({
|
|
33
|
+
toolCallId: z.string().min(1),
|
|
34
|
+
toolCallName: z.string().min(1),
|
|
35
|
+
}),
|
|
36
|
+
ToolCallArgs: z.object({
|
|
37
|
+
toolCallId: z.string().min(1),
|
|
38
|
+
delta: z.string(),
|
|
39
|
+
}),
|
|
40
|
+
ToolCallEnd: z.object({
|
|
41
|
+
toolCallId: z.string().min(1),
|
|
42
|
+
}),
|
|
43
|
+
ToolCallResult: z.object({
|
|
44
|
+
toolCallId: z.string().min(1),
|
|
45
|
+
result: z.unknown(),
|
|
46
|
+
isError: z.boolean().optional(),
|
|
47
|
+
}),
|
|
48
|
+
StepStarted: z.object({
|
|
49
|
+
stepIndex: z.number().int().positive(),
|
|
50
|
+
}),
|
|
51
|
+
StepFinished: z.object({
|
|
52
|
+
stepIndex: z.number().int().positive(),
|
|
53
|
+
}),
|
|
54
|
+
RunError: z.object({
|
|
55
|
+
code: z.string().min(1).optional(),
|
|
56
|
+
message: z.string().min(1),
|
|
57
|
+
}),
|
|
58
|
+
RunFinished: z.object({
|
|
59
|
+
metadata: z.object({
|
|
60
|
+
provider: z.string().optional(),
|
|
61
|
+
model: z.string().optional(),
|
|
62
|
+
inputTokens: z.number().int().nonnegative().optional(),
|
|
63
|
+
outputTokens: z.number().int().nonnegative().optional(),
|
|
64
|
+
totalTokens: z.number().int().nonnegative().optional(),
|
|
65
|
+
finishReason: z.string().optional(),
|
|
66
|
+
}),
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
69
|
+
export function formatAgUiEvent(event, payload) {
|
|
70
|
+
const schema = agUiEventPayloadSchemas[event];
|
|
71
|
+
const validatedPayload = schema ? schema.parse(payload) : payload;
|
|
72
|
+
return encoder.encode(`event: ${event}\ndata: ${JSON.stringify(validatedPayload)}\n\n`);
|
|
73
|
+
}
|
|
74
|
+
export function parseSseJsonEvents(chunk) {
|
|
75
|
+
const blocks = chunk.split("\n\n");
|
|
76
|
+
const remainder = blocks.pop() ?? "";
|
|
77
|
+
const events = blocks.flatMap((block) => {
|
|
78
|
+
const dataLines = block.split("\n")
|
|
79
|
+
.filter((line) => line.startsWith("data:"))
|
|
80
|
+
.map((line) => line.slice(5).trimStart());
|
|
81
|
+
if (!dataLines.length) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const payload = JSON.parse(dataLines.join("\n"));
|
|
86
|
+
return [payload];
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
logger.warn("Skipping malformed runtime SSE event payload", {
|
|
90
|
+
error,
|
|
91
|
+
dataLength: dataLines.join("\n").length,
|
|
92
|
+
});
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return { events, remainder };
|
|
97
|
+
}
|
|
98
|
+
function getMessageId(state, event) {
|
|
99
|
+
if (typeof event.messageId === "string") {
|
|
100
|
+
state.messageId = event.messageId;
|
|
101
|
+
return event.messageId;
|
|
102
|
+
}
|
|
103
|
+
if (!state.messageId && typeof event.id === "string") {
|
|
104
|
+
state.messageId = event.id;
|
|
105
|
+
}
|
|
106
|
+
if (!state.messageId) {
|
|
107
|
+
state.messageId = dntShim.crypto.randomUUID();
|
|
108
|
+
}
|
|
109
|
+
return state.messageId;
|
|
110
|
+
}
|
|
111
|
+
function applyDataMetadata(state, event) {
|
|
112
|
+
const data = event.data && typeof event.data === "object" && !Array.isArray(event.data)
|
|
113
|
+
? event.data
|
|
114
|
+
: event;
|
|
115
|
+
if (typeof data.model === "string") {
|
|
116
|
+
state.metadata.model = data.model;
|
|
117
|
+
const provider = data.model.split("/")[0];
|
|
118
|
+
if (provider) {
|
|
119
|
+
state.metadata.provider = provider;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function applyResponseMetadata(state, response) {
|
|
124
|
+
if (!response)
|
|
125
|
+
return;
|
|
126
|
+
if (response.usage) {
|
|
127
|
+
state.metadata.inputTokens = response.usage.promptTokens;
|
|
128
|
+
state.metadata.outputTokens = response.usage.completionTokens;
|
|
129
|
+
state.metadata.totalTokens = response.usage.totalTokens;
|
|
130
|
+
}
|
|
131
|
+
const finishReason = response.metadata && typeof response.metadata === "object"
|
|
132
|
+
? response.metadata.finishReason
|
|
133
|
+
: undefined;
|
|
134
|
+
if (typeof finishReason === "string") {
|
|
135
|
+
state.metadata.finishReason = finishReason;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export function mapRuntimeEventToAgUi(state, event) {
|
|
139
|
+
switch (event.type) {
|
|
140
|
+
case "message-start":
|
|
141
|
+
getMessageId(state, event);
|
|
142
|
+
return [];
|
|
143
|
+
case "text-start": {
|
|
144
|
+
if (state.textOpen)
|
|
145
|
+
return [];
|
|
146
|
+
const messageId = getMessageId(state, event);
|
|
147
|
+
state.textOpen = true;
|
|
148
|
+
return [{
|
|
149
|
+
event: "TextMessageStart",
|
|
150
|
+
payload: { messageId, role: "assistant" },
|
|
151
|
+
}];
|
|
152
|
+
}
|
|
153
|
+
case "text-delta": {
|
|
154
|
+
const messageId = getMessageId(state, event);
|
|
155
|
+
if (!state.textOpen) {
|
|
156
|
+
state.textOpen = true;
|
|
157
|
+
return [
|
|
158
|
+
{ event: "TextMessageStart", payload: { messageId, role: "assistant" } },
|
|
159
|
+
{
|
|
160
|
+
event: "TextMessageContent",
|
|
161
|
+
payload: { messageId, delta: typeof event.delta === "string" ? event.delta : "" },
|
|
162
|
+
},
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
return [{
|
|
166
|
+
event: "TextMessageContent",
|
|
167
|
+
payload: { messageId, delta: typeof event.delta === "string" ? event.delta : "" },
|
|
168
|
+
}];
|
|
169
|
+
}
|
|
170
|
+
case "text-end": {
|
|
171
|
+
if (!state.textOpen)
|
|
172
|
+
return [];
|
|
173
|
+
state.textOpen = false;
|
|
174
|
+
return [{
|
|
175
|
+
event: "TextMessageEnd",
|
|
176
|
+
payload: { messageId: getMessageId(state, event) },
|
|
177
|
+
}];
|
|
178
|
+
}
|
|
179
|
+
case "tool-input-start":
|
|
180
|
+
return [{
|
|
181
|
+
event: "ToolCallStart",
|
|
182
|
+
payload: {
|
|
183
|
+
toolCallId: event.toolCallId,
|
|
184
|
+
toolCallName: event.toolName,
|
|
185
|
+
},
|
|
186
|
+
}];
|
|
187
|
+
case "tool-input-delta":
|
|
188
|
+
return [{
|
|
189
|
+
event: "ToolCallArgs",
|
|
190
|
+
payload: {
|
|
191
|
+
toolCallId: event.toolCallId,
|
|
192
|
+
delta: typeof event.inputTextDelta === "string" ? event.inputTextDelta : "",
|
|
193
|
+
},
|
|
194
|
+
}];
|
|
195
|
+
case "tool-input-available":
|
|
196
|
+
return [{
|
|
197
|
+
event: "ToolCallEnd",
|
|
198
|
+
payload: { toolCallId: event.toolCallId },
|
|
199
|
+
}];
|
|
200
|
+
case "tool-output-available":
|
|
201
|
+
return [{
|
|
202
|
+
event: "ToolCallResult",
|
|
203
|
+
payload: {
|
|
204
|
+
toolCallId: event.toolCallId,
|
|
205
|
+
result: event.output,
|
|
206
|
+
},
|
|
207
|
+
}];
|
|
208
|
+
case "tool-output-error":
|
|
209
|
+
return [{
|
|
210
|
+
event: "ToolCallResult",
|
|
211
|
+
payload: {
|
|
212
|
+
toolCallId: event.toolCallId,
|
|
213
|
+
result: { error: event.errorText },
|
|
214
|
+
isError: true,
|
|
215
|
+
},
|
|
216
|
+
}];
|
|
217
|
+
case "step-start":
|
|
218
|
+
state.stepIndex += 1;
|
|
219
|
+
return [{
|
|
220
|
+
event: "StepStarted",
|
|
221
|
+
payload: { stepIndex: state.stepIndex },
|
|
222
|
+
}];
|
|
223
|
+
case "step-end":
|
|
224
|
+
return [{
|
|
225
|
+
event: "StepFinished",
|
|
226
|
+
payload: { stepIndex: state.stepIndex },
|
|
227
|
+
}];
|
|
228
|
+
case "data":
|
|
229
|
+
applyDataMetadata(state, event);
|
|
230
|
+
return [];
|
|
231
|
+
case "error":
|
|
232
|
+
state.sawTerminalError = true;
|
|
233
|
+
return [{
|
|
234
|
+
event: "RunError",
|
|
235
|
+
payload: {
|
|
236
|
+
message: typeof event.error === "string" ? event.error : "Agent run failed",
|
|
237
|
+
},
|
|
238
|
+
}];
|
|
239
|
+
default:
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
export function finalizeRunEvents(state, response) {
|
|
244
|
+
applyResponseMetadata(state, response);
|
|
245
|
+
if (state.sawTerminalError) {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
const events = [];
|
|
249
|
+
if (state.textOpen) {
|
|
250
|
+
state.textOpen = false;
|
|
251
|
+
events.push({
|
|
252
|
+
event: "TextMessageEnd",
|
|
253
|
+
payload: { messageId: getMessageId(state, { type: "text-end" }) },
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
events.push({
|
|
257
|
+
event: "RunFinished",
|
|
258
|
+
payload: {
|
|
259
|
+
metadata: state.metadata,
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
return events;
|
|
263
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import type { HandlerContext } from "../types/index.js";
|
|
3
|
+
export declare class ControlPlaneRequestError extends Error {
|
|
4
|
+
readonly status: number;
|
|
5
|
+
constructor(status: number, message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare function verifyControlPlaneRequest(req: dntShim.Request, ctx: HandlerContext, rawBody: string, options?: {
|
|
8
|
+
expectedSubject?: string;
|
|
9
|
+
expectedSurface?: "studio" | "channels" | "a2a" | "mcp";
|
|
10
|
+
}): Promise<{
|
|
11
|
+
project_id: string;
|
|
12
|
+
sub: string;
|
|
13
|
+
surface: "mcp" | "studio" | "channels" | "a2a";
|
|
14
|
+
iss: string;
|
|
15
|
+
aud: string;
|
|
16
|
+
iat: number;
|
|
17
|
+
exp: number;
|
|
18
|
+
request_hash: string;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=control-plane-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-plane-auth.d.ts","sourceRoot":"","sources":["../../../src/src/internal-agents/control-plane-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAE/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQxD,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C;AAED,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,OAAO,CAAC,OAAO,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,CAAC;CACpD;;;;;;;;;GAsDP"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { verifyControlPlaneJws } from "../channels/control-plane.js";
|
|
2
|
+
import { serverLogger } from "../utils/index.js";
|
|
3
|
+
import { HTTP_INTERNAL_SERVER_ERROR } from "../utils/constants/index.js";
|
|
4
|
+
const CONTROL_PLANE_JWS_HEADER = "x-veryfront-control-plane-jws";
|
|
5
|
+
const MAX_CONTROL_PLANE_SIGNATURE_AGE_SECONDS = 60;
|
|
6
|
+
const logger = serverLogger.component("internal-agents-auth");
|
|
7
|
+
export class ControlPlaneRequestError extends Error {
|
|
8
|
+
status;
|
|
9
|
+
constructor(status, message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.status = status;
|
|
12
|
+
this.name = "ControlPlaneRequestError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function verifyControlPlaneRequest(req, ctx, rawBody, options = {}) {
|
|
16
|
+
const publicKeyPem = ctx.adapter.env.get("CHANNEL_DISPATCH_SIGNING_PUBLIC_KEY");
|
|
17
|
+
if (!publicKeyPem) {
|
|
18
|
+
throw new ControlPlaneRequestError(HTTP_INTERNAL_SERVER_ERROR, "Control-plane verification is not configured");
|
|
19
|
+
}
|
|
20
|
+
const projectSlug = ctx.projectSlug;
|
|
21
|
+
if (!projectSlug) {
|
|
22
|
+
throw new ControlPlaneRequestError(400, "Project context is unavailable");
|
|
23
|
+
}
|
|
24
|
+
const controlPlaneJws = req.headers.get(CONTROL_PLANE_JWS_HEADER);
|
|
25
|
+
if (!controlPlaneJws) {
|
|
26
|
+
throw new ControlPlaneRequestError(401, "Missing control-plane signature");
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
return await verifyControlPlaneJws(controlPlaneJws, rawBody, {
|
|
30
|
+
audience: projectSlug,
|
|
31
|
+
expectedProjectId: ctx.projectId,
|
|
32
|
+
expectedSubject: options.expectedSubject,
|
|
33
|
+
expectedSurface: options.expectedSurface,
|
|
34
|
+
publicKeyPem,
|
|
35
|
+
maxAgeSeconds: MAX_CONTROL_PLANE_SIGNATURE_AGE_SECONDS,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const isAuthError = error instanceof Error && (error.message.includes("Control-plane") ||
|
|
40
|
+
error.message.includes("Unsupported"));
|
|
41
|
+
if (isAuthError) {
|
|
42
|
+
logger.warn("Invalid control-plane signature", {
|
|
43
|
+
error,
|
|
44
|
+
projectSlug,
|
|
45
|
+
expectedSubject: options.expectedSubject,
|
|
46
|
+
expectedSurface: options.expectedSurface,
|
|
47
|
+
});
|
|
48
|
+
throw new ControlPlaneRequestError(401, "Invalid control-plane signature");
|
|
49
|
+
}
|
|
50
|
+
logger.error("Unexpected error during control-plane verification", {
|
|
51
|
+
error,
|
|
52
|
+
projectSlug,
|
|
53
|
+
});
|
|
54
|
+
throw new ControlPlaneRequestError(HTTP_INTERNAL_SERVER_ERROR, "Internal error during request verification");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
export declare const INTERNAL_AGENT_STREAM_MAX_BODY_BYTES: number;
|
|
3
|
+
export declare const INTERNAL_AGENT_CONTROL_PLANE_MAX_BODY_BYTES: number;
|
|
4
|
+
export declare class InternalAgentRequestBodyTooLargeError extends Error {
|
|
5
|
+
readonly status = 413;
|
|
6
|
+
constructor(message?: string);
|
|
7
|
+
}
|
|
8
|
+
export declare function readInternalAgentRequestBody(request: dntShim.Request, maxBodyBytes?: number): Promise<string>;
|
|
9
|
+
//# sourceMappingURL=request-body.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-body.d.ts","sourceRoot":"","sources":["../../../src/src/internal-agents/request-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAQ/C,eAAO,MAAM,oCAAoC,QAA8B,CAAC;AAChF,eAAO,MAAM,2CAA2C,QAAa,CAAC;AAEtE,qBAAa,qCAAsC,SAAQ,KAAK;IAC9D,QAAQ,CAAC,MAAM,OAA0B;gBAE7B,OAAO,SAAsB;CAI1C;AAED,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,OAAO,CAAC,OAAO,EACxB,YAAY,SAAuC,GAClD,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { VeryfrontError } from "../errors/types.js";
|
|
2
|
+
import { readBodyWithLimit } from "../security/index.js";
|
|
3
|
+
import { DEFAULT_MAX_BODY_SIZE_BYTES, HTTP_PAYLOAD_TOO_LARGE, } from "../utils/constants/index.js";
|
|
4
|
+
export const INTERNAL_AGENT_STREAM_MAX_BODY_BYTES = DEFAULT_MAX_BODY_SIZE_BYTES;
|
|
5
|
+
export const INTERNAL_AGENT_CONTROL_PLANE_MAX_BODY_BYTES = 128 * 1024;
|
|
6
|
+
export class InternalAgentRequestBodyTooLargeError extends Error {
|
|
7
|
+
status = HTTP_PAYLOAD_TOO_LARGE;
|
|
8
|
+
constructor(message = "Payload too large") {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "InternalAgentRequestBodyTooLargeError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function readInternalAgentRequestBody(request, maxBodyBytes = INTERNAL_AGENT_STREAM_MAX_BODY_BYTES) {
|
|
14
|
+
if (!request.body) {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
return await readBodyWithLimit(request, maxBodyBytes);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (error instanceof VeryfrontError &&
|
|
22
|
+
error.slug === "input-validation-failed" &&
|
|
23
|
+
error.detail === "Request body exceeds size limit") {
|
|
24
|
+
throw new InternalAgentRequestBodyTooLargeError();
|
|
25
|
+
}
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import { type Agent, type AgentMessage as Message, type AgentResponse } from "../agent/index.js";
|
|
3
|
+
import { type AgentRunSessionManager } from "./session-manager.js";
|
|
4
|
+
import type { RuntimeRunAgentInput } from "./schema.js";
|
|
5
|
+
export interface RuntimeAgentStreamExecutionDeps {
|
|
6
|
+
sessionManager: AgentRunSessionManager;
|
|
7
|
+
createRuntime?: (agent: Agent, mergedTools: Agent["config"]["tools"]) => {
|
|
8
|
+
stream: (messages: Message[], context?: Record<string, unknown>, callbacks?: {
|
|
9
|
+
onFinish?: (response: AgentResponse) => void;
|
|
10
|
+
}) => Promise<ReadableStream<Uint8Array>>;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare function createRuntimeAgentStreamResponse(input: RuntimeRunAgentInput, agent: Agent, deps: RuntimeAgentStreamExecutionDeps): Promise<dntShim.Response>;
|
|
14
|
+
//# sourceMappingURL=run-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../../src/src/internal-agents/run-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EACL,KAAK,KAAK,EACV,KAAK,YAAY,IAAI,OAAO,EAC5B,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAC;AAW3B,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAIxD,MAAM,WAAW,+BAA+B;IAC9C,cAAc,EAAE,sBAAsB,CAAC;IACvC,aAAa,CAAC,EAAE,CACd,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAClC;QACH,MAAM,EAAE,CACN,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE;YACV,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;SAC9C,KACE,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;KAC1C,CAAC;CACH;AAsKD,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,oBAAoB,EAC3B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,+BAA+B,GACpC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAmJ3B"}
|