veryfront 0.1.62 → 0.1.64
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/cli/templates/manifest.js +37 -37
- package/esm/deno.d.ts +3 -0
- package/esm/deno.js +6 -3
- package/esm/src/agent/composition/composition.d.ts.map +1 -1
- package/esm/src/agent/composition/composition.js +13 -3
- package/esm/src/agent/factory.d.ts.map +1 -1
- package/esm/src/agent/factory.js +3 -3
- package/esm/src/agent/middleware/security/validator.d.ts +92 -0
- package/esm/src/agent/middleware/security/validator.d.ts.map +1 -0
- package/esm/src/agent/middleware/security/validator.js +187 -0
- package/esm/src/agent/runtime/index.d.ts +3 -2
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +16 -8
- package/esm/src/agent/types.d.ts +4 -0
- package/esm/src/agent/types.d.ts.map +1 -1
- package/esm/src/channels/invoke.d.ts +491 -0
- package/esm/src/channels/invoke.d.ts.map +1 -0
- package/esm/src/channels/invoke.js +417 -0
- package/esm/src/embedding/embedding.js +2 -2
- package/esm/src/integrations/endpoint-executor.d.ts +1 -0
- package/esm/src/integrations/endpoint-executor.d.ts.map +1 -1
- package/esm/src/integrations/endpoint-executor.js +44 -0
- package/esm/src/integrations/schema.d.ts +2 -2
- package/esm/src/oauth/handlers/init-handler.d.ts +6 -2
- package/esm/src/oauth/handlers/init-handler.d.ts.map +1 -1
- package/esm/src/oauth/handlers/init-handler.js +8 -2
- package/esm/src/platform/compat/opaque-deps.d.ts.map +1 -1
- package/esm/src/platform/compat/opaque-deps.js +10 -1
- package/esm/src/prompt/factory.d.ts.map +1 -1
- package/esm/src/prompt/factory.js +9 -1
- package/esm/src/react/components/ai/markdown.d.ts.map +1 -1
- package/esm/src/react/components/ai/markdown.js +4 -4
- package/esm/src/server/handlers/dev/framework-candidates.generated.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/framework-candidates.generated.js +5 -4
- package/esm/src/server/handlers/preview/markdown-html-generator.js +1 -1
- package/esm/src/server/handlers/request/api/api-handler-wrapper.d.ts.map +1 -1
- package/esm/src/server/handlers/request/api/api-handler-wrapper.js +1 -74
- package/esm/src/server/handlers/request/api/project-discovery.d.ts +9 -0
- package/esm/src/server/handlers/request/api/project-discovery.d.ts.map +1 -0
- package/esm/src/server/handlers/request/api/project-discovery.js +74 -0
- package/esm/src/server/handlers/request/channel-assistants.handler.d.ts +11 -0
- package/esm/src/server/handlers/request/channel-assistants.handler.d.ts.map +1 -0
- package/esm/src/server/handlers/request/channel-assistants.handler.js +71 -0
- package/esm/src/server/handlers/request/channel-invoke.handler.d.ts +11 -0
- package/esm/src/server/handlers/request/channel-invoke.handler.d.ts.map +1 -0
- package/esm/src/server/handlers/request/channel-invoke.handler.js +72 -0
- package/esm/src/server/runtime-handler/index.d.ts.map +1 -1
- package/esm/src/server/runtime-handler/index.js +4 -0
- package/esm/src/transforms/md/compiler/md-compiler.d.ts.map +1 -1
- package/esm/src/transforms/md/compiler/md-compiler.js +25 -1
- package/package.json +3 -1
- package/src/cli/templates/manifest.js +37 -37
- package/src/deno.js +6 -3
- package/src/src/agent/composition/composition.ts +15 -3
- package/src/src/agent/factory.ts +19 -6
- package/src/src/agent/middleware/security/validator.ts +288 -0
- package/src/src/agent/runtime/index.ts +26 -3
- package/src/src/agent/types.ts +4 -0
- package/src/src/channels/invoke.ts +546 -0
- package/src/src/embedding/embedding.ts +2 -2
- package/src/src/integrations/endpoint-executor.ts +51 -0
- package/src/src/oauth/handlers/init-handler.ts +20 -5
- package/src/src/platform/compat/opaque-deps.ts +19 -4
- package/src/src/prompt/factory.ts +10 -1
- package/src/src/react/components/ai/markdown.tsx +5 -4
- package/src/src/server/handlers/dev/framework-candidates.generated.ts +5 -4
- package/src/src/server/handlers/preview/markdown-html-generator.ts +1 -1
- package/src/src/server/handlers/request/api/api-handler-wrapper.ts +1 -85
- package/src/src/server/handlers/request/api/project-discovery.ts +86 -0
- package/src/src/server/handlers/request/channel-assistants.handler.ts +94 -0
- package/src/src/server/handlers/request/channel-invoke.handler.ts +95 -0
- package/src/src/server/runtime-handler/index.ts +4 -0
- package/src/src/transforms/md/compiler/md-compiler.ts +27 -1
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import { fromError } from "../errors/veryfront-error.js";
|
|
3
|
+
import { serverLogger } from "../utils/index.js";
|
|
4
|
+
import { base64urlEncodeBytes } from "../utils/base64url.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { getAgent as getRegisteredAgent, getAllAgentIds as getRegisteredAgentIds, } from "../agent/composition/composition.js";
|
|
7
|
+
import { ensureProjectDiscovery as ensureProjectDiscoveryForProject } from "../server/handlers/request/api/project-discovery.js";
|
|
8
|
+
const logger = serverLogger.component("channels-invoke");
|
|
9
|
+
const SIGNATURE_SKEW_SECONDS = 5;
|
|
10
|
+
const rawHistoryPartSchema = z.object({
|
|
11
|
+
type: z.string(),
|
|
12
|
+
}).passthrough();
|
|
13
|
+
const channelAttachmentSchema = z.object({
|
|
14
|
+
id: z.string(),
|
|
15
|
+
kind: z.enum(["image", "file"]),
|
|
16
|
+
filename: z.string().optional(),
|
|
17
|
+
mediaType: z.string().optional(),
|
|
18
|
+
privateUrl: z.string().optional(),
|
|
19
|
+
});
|
|
20
|
+
const channelInvokeHistoryMessageSchema = z.object({
|
|
21
|
+
id: z.string(),
|
|
22
|
+
role: z.enum(["user", "assistant", "system", "tool"]),
|
|
23
|
+
parts: z.array(rawHistoryPartSchema),
|
|
24
|
+
metadata: z.record(z.unknown()).optional(),
|
|
25
|
+
createdAt: z.string().optional(),
|
|
26
|
+
});
|
|
27
|
+
const channelInvokeRequestWireSchema = z.object({
|
|
28
|
+
dispatchId: z.string().min(1),
|
|
29
|
+
conversationId: z.string().min(1),
|
|
30
|
+
projectId: z.string().min(1),
|
|
31
|
+
assistantId: z.string().min(1),
|
|
32
|
+
platform: z.literal("slack"),
|
|
33
|
+
inboundMessage: z.object({
|
|
34
|
+
text: z.string(),
|
|
35
|
+
userId: z.string(),
|
|
36
|
+
userName: z.string(),
|
|
37
|
+
isDirectMessage: z.boolean(),
|
|
38
|
+
attachments: z.array(channelAttachmentSchema).optional(),
|
|
39
|
+
}),
|
|
40
|
+
conversationHistory: z.array(channelInvokeHistoryMessageSchema),
|
|
41
|
+
generation: z.object({
|
|
42
|
+
maxResponseTokens: z.number().int().positive().max(16384).optional(),
|
|
43
|
+
}).optional(),
|
|
44
|
+
});
|
|
45
|
+
export const ChannelInvokeRequestSchema = channelInvokeRequestWireSchema;
|
|
46
|
+
export const ChannelAssistantsRequestSchema = z.object({
|
|
47
|
+
requestId: z.string().min(1),
|
|
48
|
+
projectId: z.string().min(1),
|
|
49
|
+
platform: z.literal("slack"),
|
|
50
|
+
});
|
|
51
|
+
export const ChannelAssistantSchema = z.object({
|
|
52
|
+
id: z.string().min(1),
|
|
53
|
+
name: z.string().min(1),
|
|
54
|
+
description: z.string().nullable().optional(),
|
|
55
|
+
model: z.string().nullable().optional(),
|
|
56
|
+
});
|
|
57
|
+
export const ChannelAssistantsResponseSchema = z.object({
|
|
58
|
+
assistants: z.array(ChannelAssistantSchema),
|
|
59
|
+
});
|
|
60
|
+
const channelTextPartSchema = z.object({
|
|
61
|
+
type: z.literal("text"),
|
|
62
|
+
text: z.string(),
|
|
63
|
+
});
|
|
64
|
+
const channelToolCallPartSchema = z.object({
|
|
65
|
+
type: z.literal("tool_call"),
|
|
66
|
+
id: z.string(),
|
|
67
|
+
name: z.string(),
|
|
68
|
+
input: z.record(z.unknown()),
|
|
69
|
+
state: z.enum(["streaming", "pending", "completed", "error"]),
|
|
70
|
+
});
|
|
71
|
+
const channelToolResultPartSchema = z.object({
|
|
72
|
+
type: z.literal("tool_result"),
|
|
73
|
+
tool_call_id: z.string(),
|
|
74
|
+
output: z.unknown(),
|
|
75
|
+
is_error: z.boolean().optional(),
|
|
76
|
+
});
|
|
77
|
+
const channelReasoningPartSchema = z.object({
|
|
78
|
+
type: z.literal("reasoning"),
|
|
79
|
+
text: z.string(),
|
|
80
|
+
});
|
|
81
|
+
const channelErrorPartSchema = z.object({
|
|
82
|
+
type: z.literal("error"),
|
|
83
|
+
code: z.string(),
|
|
84
|
+
message: z.string(),
|
|
85
|
+
});
|
|
86
|
+
export const ChannelResponsePartSchema = z.discriminatedUnion("type", [
|
|
87
|
+
channelTextPartSchema,
|
|
88
|
+
channelToolCallPartSchema,
|
|
89
|
+
channelToolResultPartSchema,
|
|
90
|
+
channelReasoningPartSchema,
|
|
91
|
+
channelErrorPartSchema,
|
|
92
|
+
]);
|
|
93
|
+
export const ChannelInvokeResponseSchema = z.object({
|
|
94
|
+
ignored: z.boolean(),
|
|
95
|
+
responseParts: z.array(ChannelResponsePartSchema).optional(),
|
|
96
|
+
tokenUsage: z.object({
|
|
97
|
+
inputTokens: z.number().int().nonnegative().optional(),
|
|
98
|
+
outputTokens: z.number().int().nonnegative().optional(),
|
|
99
|
+
totalTokens: z.number().int().nonnegative().optional(),
|
|
100
|
+
}).optional(),
|
|
101
|
+
error: z.object({
|
|
102
|
+
code: z.enum(["provider_error", "internal_error"]),
|
|
103
|
+
retryable: z.boolean(),
|
|
104
|
+
}).optional(),
|
|
105
|
+
});
|
|
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
|
+
export const defaultChannelInvokeDeps = {
|
|
122
|
+
ensureProjectDiscovery: ensureProjectDiscoveryForProject,
|
|
123
|
+
getAgent: getRegisteredAgent,
|
|
124
|
+
getAllAgentIds: getRegisteredAgentIds,
|
|
125
|
+
};
|
|
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
|
+
export async function listChannelAssistants(ctx, deps) {
|
|
138
|
+
await deps.ensureProjectDiscovery(ctx);
|
|
139
|
+
const assistants = deps.getAllAgentIds()
|
|
140
|
+
.map((id) => deps.getAgent(id))
|
|
141
|
+
.filter((agent) => Boolean(agent))
|
|
142
|
+
.map(getAssistantMetadata)
|
|
143
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
144
|
+
return ChannelAssistantsResponseSchema.parse({ assistants });
|
|
145
|
+
}
|
|
146
|
+
function base64urlDecodeToBytes(input) {
|
|
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
|
+
}
|
|
217
|
+
function normalizeConversationPart(part) {
|
|
218
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
219
|
+
return { type: "text", text: part.text };
|
|
220
|
+
}
|
|
221
|
+
if (part.type === "tool_call" &&
|
|
222
|
+
typeof part.id === "string" &&
|
|
223
|
+
typeof part.name === "string" &&
|
|
224
|
+
part.input &&
|
|
225
|
+
typeof part.input === "object" &&
|
|
226
|
+
!Array.isArray(part.input)) {
|
|
227
|
+
return {
|
|
228
|
+
type: `tool-${part.name}`,
|
|
229
|
+
toolCallId: part.id,
|
|
230
|
+
toolName: part.name,
|
|
231
|
+
args: part.input,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
if (part.type === "tool_result" && typeof part.tool_call_id === "string") {
|
|
235
|
+
return {
|
|
236
|
+
type: "tool-result",
|
|
237
|
+
toolCallId: part.tool_call_id,
|
|
238
|
+
toolName: typeof part.tool_name === "string" ? part.tool_name : "unknown",
|
|
239
|
+
result: "output" in part ? part.output : undefined,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
export function normalizeConversationHistoryForRuntime(messages) {
|
|
245
|
+
return messages.map((message) => ({
|
|
246
|
+
id: message.id,
|
|
247
|
+
role: message.role,
|
|
248
|
+
parts: message.parts
|
|
249
|
+
.map((part) => normalizeConversationPart(part))
|
|
250
|
+
.filter((part) => part !== null),
|
|
251
|
+
...(message.createdAt ? { timestamp: Date.parse(message.createdAt) || undefined } : {}),
|
|
252
|
+
...(message.metadata ? { metadata: message.metadata } : {}),
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
export function resolveChannelInvokeAgent(assistantId, deps) {
|
|
256
|
+
return deps.getAgent(assistantId);
|
|
257
|
+
}
|
|
258
|
+
function normalizeToolCallState(status) {
|
|
259
|
+
switch (status) {
|
|
260
|
+
case "completed":
|
|
261
|
+
return "completed";
|
|
262
|
+
case "error":
|
|
263
|
+
return "error";
|
|
264
|
+
default:
|
|
265
|
+
return "pending";
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function convertAssistantPartToChannelResponsePart(part, knownToolCallIds) {
|
|
269
|
+
if (part.type === "text" && "text" in part) {
|
|
270
|
+
return channelTextPartSchema.parse({
|
|
271
|
+
type: "text",
|
|
272
|
+
text: part.text,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
const isToolCallPart = part.type === "tool-call" ||
|
|
276
|
+
(part.type.startsWith("tool-") && part.type !== "tool-result");
|
|
277
|
+
if (isToolCallPart &&
|
|
278
|
+
"toolCallId" in part &&
|
|
279
|
+
"toolName" in part &&
|
|
280
|
+
!knownToolCallIds.has(part.toolCallId)) {
|
|
281
|
+
return channelToolCallPartSchema.parse({
|
|
282
|
+
type: "tool_call",
|
|
283
|
+
id: part.toolCallId,
|
|
284
|
+
name: part.toolName,
|
|
285
|
+
input: "args" in part ? part.args : ("input" in part ? part.input : {}),
|
|
286
|
+
state: "pending",
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
function findLastAssistantMessage(messages) {
|
|
292
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
293
|
+
if (messages[index]?.role === "assistant") {
|
|
294
|
+
return messages[index];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
export function buildChannelResponseParts(response) {
|
|
300
|
+
const responseParts = [];
|
|
301
|
+
const knownToolCallIds = new Set();
|
|
302
|
+
if (response.thinking?.trim()) {
|
|
303
|
+
responseParts.push(channelReasoningPartSchema.parse({
|
|
304
|
+
type: "reasoning",
|
|
305
|
+
text: response.thinking,
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
for (const toolCall of response.toolCalls) {
|
|
309
|
+
knownToolCallIds.add(toolCall.id);
|
|
310
|
+
responseParts.push(channelToolCallPartSchema.parse({
|
|
311
|
+
type: "tool_call",
|
|
312
|
+
id: toolCall.id,
|
|
313
|
+
name: toolCall.name,
|
|
314
|
+
input: toolCall.args,
|
|
315
|
+
state: normalizeToolCallState(toolCall.status),
|
|
316
|
+
}));
|
|
317
|
+
if (toolCall.status === "completed" || toolCall.status === "error") {
|
|
318
|
+
responseParts.push(channelToolResultPartSchema.parse({
|
|
319
|
+
type: "tool_result",
|
|
320
|
+
tool_call_id: toolCall.id,
|
|
321
|
+
output: toolCall.status === "error"
|
|
322
|
+
? { error: toolCall.error ?? "Tool execution failed" }
|
|
323
|
+
: toolCall.result,
|
|
324
|
+
...(toolCall.status === "error" ? { is_error: true } : {}),
|
|
325
|
+
}));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const lastAssistantMessage = findLastAssistantMessage(response.messages);
|
|
329
|
+
if (lastAssistantMessage) {
|
|
330
|
+
for (const part of lastAssistantMessage.parts) {
|
|
331
|
+
const converted = convertAssistantPartToChannelResponsePart(part, knownToolCallIds);
|
|
332
|
+
if (converted) {
|
|
333
|
+
responseParts.push(converted);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
else if (response.text.trim()) {
|
|
338
|
+
responseParts.push(channelTextPartSchema.parse({
|
|
339
|
+
type: "text",
|
|
340
|
+
text: response.text,
|
|
341
|
+
}));
|
|
342
|
+
}
|
|
343
|
+
return responseParts;
|
|
344
|
+
}
|
|
345
|
+
function classifyRuntimeError(error) {
|
|
346
|
+
const veryfrontError = fromError(error);
|
|
347
|
+
if (veryfrontError?.type === "no_ai_available") {
|
|
348
|
+
return { code: "provider_error", retryable: false };
|
|
349
|
+
}
|
|
350
|
+
if (veryfrontError?.type === "api" || veryfrontError?.type === "network") {
|
|
351
|
+
return { code: "provider_error", retryable: true };
|
|
352
|
+
}
|
|
353
|
+
return { code: "internal_error", retryable: true };
|
|
354
|
+
}
|
|
355
|
+
export async function executeChannelInvoke(payload, ctx, deps) {
|
|
356
|
+
await deps.ensureProjectDiscovery(ctx);
|
|
357
|
+
const agent = resolveChannelInvokeAgent(payload.assistantId, deps);
|
|
358
|
+
if (!agent) {
|
|
359
|
+
logger.error("Channel invoke could not resolve a runtime agent for the request", {
|
|
360
|
+
requestedAssistantId: payload.assistantId,
|
|
361
|
+
discoveredAgentIds: deps.getAllAgentIds(),
|
|
362
|
+
projectSlug: ctx.projectSlug,
|
|
363
|
+
projectId: ctx.projectId,
|
|
364
|
+
});
|
|
365
|
+
return {
|
|
366
|
+
ignored: false,
|
|
367
|
+
error: {
|
|
368
|
+
code: "internal_error",
|
|
369
|
+
retryable: false,
|
|
370
|
+
},
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
const messages = normalizeConversationHistoryForRuntime(payload.conversationHistory);
|
|
374
|
+
await agent.clearMemory();
|
|
375
|
+
try {
|
|
376
|
+
const result = await agent.generate({
|
|
377
|
+
input: messages,
|
|
378
|
+
context: {
|
|
379
|
+
requestId: payload.dispatchId,
|
|
380
|
+
dispatchId: payload.dispatchId,
|
|
381
|
+
conversationId: payload.conversationId,
|
|
382
|
+
projectId: payload.projectId,
|
|
383
|
+
assistantId: payload.assistantId,
|
|
384
|
+
channel: payload.inboundMessage,
|
|
385
|
+
},
|
|
386
|
+
...(payload.generation?.maxResponseTokens
|
|
387
|
+
? {
|
|
388
|
+
maxOutputTokens: payload.generation.maxResponseTokens,
|
|
389
|
+
}
|
|
390
|
+
: {}),
|
|
391
|
+
});
|
|
392
|
+
return ChannelInvokeResponseSchema.parse({
|
|
393
|
+
ignored: false,
|
|
394
|
+
responseParts: buildChannelResponseParts(result),
|
|
395
|
+
tokenUsage: result.usage
|
|
396
|
+
? {
|
|
397
|
+
inputTokens: result.usage.promptTokens,
|
|
398
|
+
outputTokens: result.usage.completionTokens,
|
|
399
|
+
totalTokens: result.usage.totalTokens,
|
|
400
|
+
}
|
|
401
|
+
: undefined,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
catch (error) {
|
|
405
|
+
logger.error("Channel invoke runtime execution failed", {
|
|
406
|
+
error: error instanceof Error ? error.message : String(error),
|
|
407
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
408
|
+
projectSlug: ctx.projectSlug,
|
|
409
|
+
projectId: ctx.projectId,
|
|
410
|
+
dispatchId: payload.dispatchId,
|
|
411
|
+
});
|
|
412
|
+
return {
|
|
413
|
+
ignored: false,
|
|
414
|
+
error: classifyRuntimeError(error),
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
}
|
|
@@ -30,10 +30,10 @@ export function embedding(config) {
|
|
|
30
30
|
return {
|
|
31
31
|
model: modelId,
|
|
32
32
|
async embed(text) {
|
|
33
|
-
|
|
34
|
-
if (!value.trim()) {
|
|
33
|
+
if (!text.trim()) {
|
|
35
34
|
throw new Error("Cannot embed an empty string");
|
|
36
35
|
}
|
|
36
|
+
const value = queryPrefix + text;
|
|
37
37
|
const result = await embed({ model, value });
|
|
38
38
|
return result.embedding;
|
|
39
39
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint-executor.d.ts","sourceRoot":"","sources":["../../../src/src/integrations/endpoint-executor.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"endpoint-executor.d.ts","sourceRoot":"","sources":["../../../src/src/integrations/endpoint-executor.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAetD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAiCrD;AAED,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAK9C"}
|
|
@@ -8,6 +8,48 @@
|
|
|
8
8
|
import * as dntShim from "../../_dnt.shims.js";
|
|
9
9
|
import { logger } from "../utils/index.js";
|
|
10
10
|
import { INVALID_ARGUMENT } from "../errors/index.js";
|
|
11
|
+
const PRIVATE_IP_RANGES = [
|
|
12
|
+
/^127\./, // 127.0.0.0/8
|
|
13
|
+
/^10\./, // 10.0.0.0/8
|
|
14
|
+
/^172\.(1[6-9]|2\d|3[01])\./, // 172.16.0.0/12
|
|
15
|
+
/^192\.168\./, // 192.168.0.0/16
|
|
16
|
+
/^169\.254\./, // 169.254.0.0/16
|
|
17
|
+
/^0\./, // 0.0.0.0/8
|
|
18
|
+
/^::1$/, // IPv6 loopback
|
|
19
|
+
/^f[cd][0-9a-f]{2}:/i, // IPv6 unique local (fc00::/7)
|
|
20
|
+
/^fe80:/i, // IPv6 link-local (fe80::/10)
|
|
21
|
+
];
|
|
22
|
+
export function validateEndpointUrl(url) {
|
|
23
|
+
let parsed;
|
|
24
|
+
try {
|
|
25
|
+
parsed = new URL(url);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw INVALID_ARGUMENT.create({ detail: `Invalid endpoint URL: ${url}` });
|
|
29
|
+
}
|
|
30
|
+
if (parsed.protocol !== "https:") {
|
|
31
|
+
throw INVALID_ARGUMENT.create({
|
|
32
|
+
detail: `Endpoint URL must use HTTPS: ${parsed.protocol}`,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
36
|
+
if (hostname === "localhost") {
|
|
37
|
+
throw INVALID_ARGUMENT.create({
|
|
38
|
+
detail: "Endpoint URL must not target localhost",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// Strip IPv6 brackets for regex matching
|
|
42
|
+
const bare = hostname.startsWith("[") && hostname.endsWith("]")
|
|
43
|
+
? hostname.slice(1, -1)
|
|
44
|
+
: hostname;
|
|
45
|
+
for (const range of PRIVATE_IP_RANGES) {
|
|
46
|
+
if (range.test(bare)) {
|
|
47
|
+
throw INVALID_ARGUMENT.create({
|
|
48
|
+
detail: "Endpoint URL must not target private/internal networks",
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
11
53
|
export async function executeEndpoint(endpoint, args, accessToken, ctx) {
|
|
12
54
|
if (endpoint.type === "graphql") {
|
|
13
55
|
return executeGraphQL(endpoint, args, accessToken, ctx);
|
|
@@ -40,6 +82,7 @@ async function executeGraphQL(endpoint, args, accessToken, ctx) {
|
|
|
40
82
|
headers[key] = args[key] !== undefined ? String(args[key]) : String(def.default ?? "");
|
|
41
83
|
}
|
|
42
84
|
}
|
|
85
|
+
validateEndpointUrl(endpoint.url);
|
|
43
86
|
logger.debug("Executing GraphQL endpoint", {
|
|
44
87
|
integration: ctx.integration,
|
|
45
88
|
tool: ctx.toolId,
|
|
@@ -112,6 +155,7 @@ async function executeRest(endpoint, args, accessToken, ctx) {
|
|
|
112
155
|
body = JSON.stringify(bodyObj);
|
|
113
156
|
headers["Content-Type"] = endpoint.contentType ?? "application/json";
|
|
114
157
|
}
|
|
158
|
+
validateEndpointUrl(urlObj.toString());
|
|
115
159
|
logger.debug("Executing REST endpoint", {
|
|
116
160
|
integration: ctx.integration,
|
|
117
161
|
tool: ctx.toolId,
|
|
@@ -458,7 +458,7 @@ export declare const IntegrationConfigSchema: z.ZodObject<{
|
|
|
458
458
|
id?: string | undefined;
|
|
459
459
|
requiresWrite?: boolean | undefined;
|
|
460
460
|
}[];
|
|
461
|
-
name: "github" | "aws" | "twitter" | "zoom" | "anthropic" | "linear" | "gmail" | "calendar" | "sheets" | "drive" | "outlook" | "teams" | "sharepoint" | "onedrive" | "jira" | "confluence" | "bitbucket" | "
|
|
461
|
+
name: "github" | "aws" | "twitter" | "zoom" | "anthropic" | "linear" | "slack" | "gmail" | "calendar" | "sheets" | "drive" | "outlook" | "teams" | "sharepoint" | "onedrive" | "jira" | "confluence" | "bitbucket" | "notion" | "figma" | "discord" | "gitlab" | "airtable" | "dropbox" | "hubspot" | "salesforce" | "asana" | "monday" | "intercom" | "freshdesk" | "mailchimp" | "shopify" | "quickbooks" | "xero" | "box" | "webex" | "trello" | "clickup" | "pipedrive" | "servicenow" | "supabase" | "neon" | "stripe" | "sentry" | "posthog" | "zendesk" | "docs-google" | "snowflake" | "mixpanel" | "twilio";
|
|
462
462
|
displayName: string;
|
|
463
463
|
category?: string | undefined;
|
|
464
464
|
icon?: string | undefined;
|
|
@@ -524,7 +524,7 @@ export declare const IntegrationConfigSchema: z.ZodObject<{
|
|
|
524
524
|
id?: string | undefined;
|
|
525
525
|
requiresWrite?: boolean | undefined;
|
|
526
526
|
}[];
|
|
527
|
-
name: "github" | "aws" | "twitter" | "zoom" | "anthropic" | "linear" | "gmail" | "calendar" | "sheets" | "drive" | "outlook" | "teams" | "sharepoint" | "onedrive" | "jira" | "confluence" | "bitbucket" | "
|
|
527
|
+
name: "github" | "aws" | "twitter" | "zoom" | "anthropic" | "linear" | "slack" | "gmail" | "calendar" | "sheets" | "drive" | "outlook" | "teams" | "sharepoint" | "onedrive" | "jira" | "confluence" | "bitbucket" | "notion" | "figma" | "discord" | "gitlab" | "airtable" | "dropbox" | "hubspot" | "salesforce" | "asana" | "monday" | "intercom" | "freshdesk" | "mailchimp" | "shopify" | "quickbooks" | "xero" | "box" | "webex" | "trello" | "clickup" | "pipedrive" | "servicenow" | "supabase" | "neon" | "stripe" | "sentry" | "posthog" | "zendesk" | "docs-google" | "snowflake" | "mixpanel" | "twilio";
|
|
528
528
|
displayName: string;
|
|
529
529
|
category?: string | undefined;
|
|
530
530
|
icon?: string | undefined;
|
|
@@ -20,9 +20,13 @@ export interface OAuthStatusHandlerOptions {
|
|
|
20
20
|
tokenStore?: TokenStore;
|
|
21
21
|
/** EnvReader for dynamic env vars (defaults to getEnv) */
|
|
22
22
|
envReader?: EnvReader;
|
|
23
|
+
/** Optional authentication check — return true if the request is authenticated */
|
|
24
|
+
isAuthenticated?: (req: dntShim.Request) => boolean | Promise<boolean>;
|
|
23
25
|
}
|
|
24
|
-
export declare function createOAuthStatusHandler(config: OAuthServiceConfig, options?: OAuthStatusHandlerOptions): () => Promise<dntShim.Response>;
|
|
26
|
+
export declare function createOAuthStatusHandler(config: OAuthServiceConfig, options?: OAuthStatusHandlerOptions): (req: dntShim.Request) => Promise<dntShim.Response>;
|
|
25
27
|
export declare function createOAuthDisconnectHandler(config: OAuthServiceConfig, options?: {
|
|
26
28
|
tokenStore?: TokenStore;
|
|
27
|
-
|
|
29
|
+
/** Optional authentication check — return true if the request is authenticated */
|
|
30
|
+
isAuthenticated?: (req: dntShim.Request) => boolean | Promise<boolean>;
|
|
31
|
+
}): (req: dntShim.Request) => Promise<dntShim.Response>;
|
|
28
32
|
//# sourceMappingURL=init-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/oauth/handlers/init-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAElD,OAAO,EACL,KAAK,iBAAiB,EAEvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK3F,MAAM,WAAW,uBAAuB;IACtC,oDAAoD;IACpD,UAAU,CAAC,EAAE,UAAU,CAAC;IAExB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uCAAuC;IACvC,WAAW,CAAC,EAAE,uBAAuB,CAAC;IAEtC,gFAAgF;IAChF,GAAG,CAAC,EAAE,iBAAiB,CAAC;IAExB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,uBAA4B,GACpC,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAsCjC;AAED,MAAM,WAAW,yBAAyB;IACxC,oDAAoD;IACpD,UAAU,CAAC,EAAE,UAAU,CAAC;IAExB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"init-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/oauth/handlers/init-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAElD,OAAO,EACL,KAAK,iBAAiB,EAEvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK3F,MAAM,WAAW,uBAAuB;IACtC,oDAAoD;IACpD,UAAU,CAAC,EAAE,UAAU,CAAC;IAExB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uCAAuC;IACvC,WAAW,CAAC,EAAE,uBAAuB,CAAC;IAEtC,gFAAgF;IAChF,GAAG,CAAC,EAAE,iBAAiB,CAAC;IAExB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,uBAA4B,GACpC,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAsCjC;AAED,MAAM,WAAW,yBAAyB;IACxC,oDAAoD;IACpD,UAAU,CAAC,EAAE,UAAU,CAAC;IAExB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,kFAAkF;IAClF,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,yBAA8B,GACtC,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAwBrD;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,kFAAkF;IAClF,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE,GACL,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAerD"}
|
|
@@ -37,7 +37,10 @@ export function createOAuthInitHandler(config, options = {}) {
|
|
|
37
37
|
export function createOAuthStatusHandler(config, options = {}) {
|
|
38
38
|
const tokenStore = options.tokenStore ?? memoryTokenStore;
|
|
39
39
|
const envReader = options.envReader ?? getEnv;
|
|
40
|
-
return async function handler() {
|
|
40
|
+
return async function handler(req) {
|
|
41
|
+
if (options.isAuthenticated && !(await options.isAuthenticated(req))) {
|
|
42
|
+
return dntShim.Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
43
|
+
}
|
|
41
44
|
const tokens = await tokenStore.getTokens(config.serviceId);
|
|
42
45
|
const isConnected = !!tokens?.accessToken;
|
|
43
46
|
const isExpired = tokens?.expiresAt ? Date.now() > tokens.expiresAt : false;
|
|
@@ -54,7 +57,10 @@ export function createOAuthStatusHandler(config, options = {}) {
|
|
|
54
57
|
}
|
|
55
58
|
export function createOAuthDisconnectHandler(config, options = {}) {
|
|
56
59
|
const tokenStore = options.tokenStore ?? memoryTokenStore;
|
|
57
|
-
return async function handler() {
|
|
60
|
+
return async function handler(req) {
|
|
61
|
+
if (options.isAuthenticated && !(await options.isAuthenticated(req))) {
|
|
62
|
+
return dntShim.Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
63
|
+
}
|
|
58
64
|
await tokenStore.clearTokens(config.serviceId);
|
|
59
65
|
return dntShim.Response.json({
|
|
60
66
|
success: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opaque-deps.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/opaque-deps.ts"],"names":[],"mappings":"AA2BA,KAAK,YAAY,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"opaque-deps.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/opaque-deps.ts"],"names":[],"mappings":"AA2BA,KAAK,YAAY,GAAG,GAAG,CAAC;AAUxB,yEAAyE;AACzE,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC,CAE1D;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAK5D;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,YAAY,EAAE,CACZ,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnC,CAAC,CAkBD"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* @module platform/compat
|
|
16
16
|
*/
|
|
17
17
|
import * as dntShim from "../../../_dnt.shims.js";
|
|
18
|
-
import { isDeno } from "./runtime.js";
|
|
18
|
+
import { isDeno, isDenoCompiled } from "./runtime.js";
|
|
19
19
|
import { dynamicImport } from "./dynamic-import.js";
|
|
20
20
|
function resolve(pkg, version) {
|
|
21
21
|
return isDeno ? `npm:${pkg}@${version}` : pkg;
|
|
@@ -45,6 +45,15 @@ export async function importKreuzberg() {
|
|
|
45
45
|
if (isDeno) {
|
|
46
46
|
// Regular import — visible to deno compile, resolved via deno.json import map
|
|
47
47
|
const mod = await import("@kreuzberg/wasm");
|
|
48
|
+
if (isDenoCompiled) {
|
|
49
|
+
// Kreuzberg's initWasm() internally uses a computed dynamic import() to
|
|
50
|
+
// load the WASM glue module (kreuzberg_wasm.js). deno compile cannot
|
|
51
|
+
// trace computed import() paths, so the glue module is absent from the
|
|
52
|
+
// binary's embedded module graph. Pre-importing it here populates Deno's
|
|
53
|
+
// in-process module cache so the subsequent import() inside initWasm()
|
|
54
|
+
// resolves from cache instead of hitting the missing file.
|
|
55
|
+
await import("@kreuzberg/wasm/dist/pkg/kreuzberg_wasm.js");
|
|
56
|
+
}
|
|
48
57
|
await mod.initWasm?.();
|
|
49
58
|
return mod;
|
|
50
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/prompt/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/prompt/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAIvD,wBAAgB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA0BnD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createError, toError } from "../errors/veryfront-error.js";
|
|
2
|
+
import { COMMON_BLOCKED_PATTERNS } from "../agent/middleware/security/validator.js";
|
|
2
3
|
export function prompt(config) {
|
|
3
4
|
const id = config.id ?? generatePromptId();
|
|
4
5
|
return {
|
|
@@ -24,9 +25,16 @@ let promptIdCounter = 0;
|
|
|
24
25
|
function generatePromptId() {
|
|
25
26
|
return `prompt_${Date.now()}_${promptIdCounter++}`;
|
|
26
27
|
}
|
|
28
|
+
function sanitizeVariableValue(value) {
|
|
29
|
+
let sanitized = value;
|
|
30
|
+
for (const pattern of COMMON_BLOCKED_PATTERNS.promptInjection) {
|
|
31
|
+
sanitized = sanitized.replace(pattern, "");
|
|
32
|
+
}
|
|
33
|
+
return sanitized;
|
|
34
|
+
}
|
|
27
35
|
function interpolateVariables(template, variables) {
|
|
28
36
|
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
|
29
37
|
const value = variables[key];
|
|
30
|
-
return value != null ? String(value) : match;
|
|
38
|
+
return value != null ? sanitizeVariableValue(String(value)) : match;
|
|
31
39
|
});
|
|
32
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ai/markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iCAAiC;IACjC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,KAAK,CAAC,SAAS,CAAC;CAC9D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ai/markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iCAAiC;IACjC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,KAAK,CAAC,SAAS,CAAC;CAC9D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmJD,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,EACR,SAAS,EACT,aAAoB,EACpB,eAAe,GAChB,EAAE,aAAa,GAAG,KAAK,CAAC,YAAY,CA+FpC"}
|
|
@@ -3,10 +3,10 @@ import { cn } from "./theme.js";
|
|
|
3
3
|
import { isBrowserEnvironment } from "../../../platform/compat/runtime.js";
|
|
4
4
|
import { validateTrustedHtml } from "../../../security/client/html-sanitizer.js";
|
|
5
5
|
import { RichCodeBlock } from "./chat/components/code-block.js";
|
|
6
|
-
const ESM_REACT_MARKDOWN = "https://esm.sh/react-markdown@9?external=react&target=es2022";
|
|
7
|
-
const ESM_REMARK_GFM = "https://esm.sh/remark-gfm@4?target=es2022";
|
|
8
|
-
const ESM_REHYPE_HIGHLIGHT = "https://esm.sh/rehype-highlight@7?target=es2022";
|
|
9
|
-
const ESM_MERMAID = "https://esm.sh/mermaid@11";
|
|
6
|
+
const ESM_REACT_MARKDOWN = "https://esm.sh/react-markdown@9.0.3?external=react&target=es2022&pin=v135";
|
|
7
|
+
const ESM_REMARK_GFM = "https://esm.sh/remark-gfm@4.0.1?target=es2022&pin=v135";
|
|
8
|
+
const ESM_REHYPE_HIGHLIGHT = "https://esm.sh/rehype-highlight@7.0.2?target=es2022&pin=v135";
|
|
9
|
+
const ESM_MERMAID = "https://esm.sh/mermaid@11.4.1?pin=v135";
|
|
10
10
|
const dynamicImport = new Function("url", "return import(url)");
|
|
11
11
|
// deno-lint-ignore no-explicit-any
|
|
12
12
|
let ReactMarkdown = null;
|