@yak-io/javascript 0.1.0

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.
Files changed (44) hide show
  1. package/LICENSE +36 -0
  2. package/dist/client.d.ts +175 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +504 -0
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +9 -0
  8. package/dist/index.server.d.ts +2 -0
  9. package/dist/index.server.d.ts.map +1 -0
  10. package/dist/index.server.js +1 -0
  11. package/dist/logger.d.ts +12 -0
  12. package/dist/logger.d.ts.map +1 -0
  13. package/dist/logger.js +44 -0
  14. package/dist/page-context.d.ts +10 -0
  15. package/dist/page-context.d.ts.map +1 -0
  16. package/dist/page-context.js +69 -0
  17. package/dist/schema-parser.d.ts +21 -0
  18. package/dist/schema-parser.d.ts.map +1 -0
  19. package/dist/schema-parser.js +341 -0
  20. package/dist/server/createYakHandler.d.ts +19 -0
  21. package/dist/server/createYakHandler.d.ts.map +1 -0
  22. package/dist/server/createYakHandler.js +185 -0
  23. package/dist/server/index.d.ts +8 -0
  24. package/dist/server/index.d.ts.map +1 -0
  25. package/dist/server/index.js +2 -0
  26. package/dist/server/sources.d.ts +24 -0
  27. package/dist/server/sources.d.ts.map +1 -0
  28. package/dist/server/sources.js +116 -0
  29. package/dist/types/config.d.ts +19 -0
  30. package/dist/types/config.d.ts.map +1 -0
  31. package/dist/types/config.js +1 -0
  32. package/dist/types/messaging.d.ts +153 -0
  33. package/dist/types/messaging.d.ts.map +1 -0
  34. package/dist/types/messaging.js +1 -0
  35. package/dist/types/routes.d.ts +26 -0
  36. package/dist/types/routes.d.ts.map +1 -0
  37. package/dist/types/routes.js +1 -0
  38. package/dist/types/tools.d.ts +137 -0
  39. package/dist/types/tools.d.ts.map +1 -0
  40. package/dist/types/tools.js +1 -0
  41. package/dist/version.d.ts +23 -0
  42. package/dist/version.d.ts.map +1 -0
  43. package/dist/version.js +18 -0
  44. package/package.json +53 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Client-side Schema Parser
3
+ *
4
+ * Parses GraphQL schemas and OpenAPI specs into ToolDefinitions.
5
+ * This is a simplified version suitable for browser environments.
6
+ */
7
+ import type { ToolDefinition, SchemaSource, ToolManifest } from "./types/tools.js";
8
+ /**
9
+ * Parses schema sources into tool definitions
10
+ */
11
+ export declare function parseSchemaSources(sources: SchemaSource[]): ToolDefinition[];
12
+ /**
13
+ * Expands a tool manifest by parsing any schema sources into tool definitions.
14
+ * Use this to pre-process the manifest before passing to YakProvider.
15
+ */
16
+ export declare function expandToolManifest(manifest: ToolManifest): ToolManifest;
17
+ /**
18
+ * Builds an executable request from a tool definition and provided arguments.
19
+ */
20
+ export declare function buildExecutableRequest(tool: ToolDefinition, args: Record<string, unknown>): import("./types/tools.js").ExecutableRequest | undefined;
21
+ //# sourceMappingURL=schema-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-parser.d.ts","sourceRoot":"","sources":["../src/schema-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,cAAc,EAGd,YAAY,EAEZ,YAAY,EACb,MAAM,kBAAkB,CAAC;AAyV1B;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAgB5E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,YAAY,CAavE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,kBAAkB,EAAE,iBAAiB,GAAG,SAAS,CAuD1D"}
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Client-side Schema Parser
3
+ *
4
+ * Parses GraphQL schemas and OpenAPI specs into ToolDefinitions.
5
+ * This is a simplified version suitable for browser environments.
6
+ */
7
+ function graphqlTypeToJsonSchema(type) {
8
+ const baseType = type.replace(/!/g, "").replace(/\[|\]/g, "").trim();
9
+ const isArray = type.includes("[");
10
+ let schema;
11
+ switch (baseType.toLowerCase()) {
12
+ case "string":
13
+ case "id":
14
+ schema = { type: "string" };
15
+ break;
16
+ case "int":
17
+ schema = { type: "integer" };
18
+ break;
19
+ case "float":
20
+ schema = { type: "number" };
21
+ break;
22
+ case "boolean":
23
+ schema = { type: "boolean" };
24
+ break;
25
+ default:
26
+ schema = { type: "object" };
27
+ }
28
+ if (isArray) {
29
+ schema = { type: "array", items: schema };
30
+ }
31
+ return schema;
32
+ }
33
+ function parseGraphQLSDL(sdl) {
34
+ const result = { queries: [], mutations: [] };
35
+ const fieldPattern = /(\w+)\s*(?:\(([^)]*)\))?\s*:\s*([^\n}]+)/g;
36
+ const argPattern = /(\w+)\s*:\s*([^,)]+)/g;
37
+ const queryMatch = sdl.match(/type\s+Query\s*\{([^}]+)\}/s);
38
+ if (queryMatch?.[1]) {
39
+ const queryBody = queryMatch[1];
40
+ let fieldMatch = null;
41
+ fieldPattern.lastIndex = 0;
42
+ while ((fieldMatch = fieldPattern.exec(queryBody)) !== null) {
43
+ const name = fieldMatch[1];
44
+ const argsStr = fieldMatch[2];
45
+ const returnType = fieldMatch[3];
46
+ if (!name || !returnType)
47
+ continue;
48
+ const args = [];
49
+ if (argsStr) {
50
+ let argMatch = null;
51
+ argPattern.lastIndex = 0;
52
+ while ((argMatch = argPattern.exec(argsStr)) !== null) {
53
+ const argName = argMatch[1];
54
+ const argType = argMatch[2];
55
+ if (!argName || !argType)
56
+ continue;
57
+ args.push({
58
+ name: argName,
59
+ type: argType.trim(),
60
+ required: argType.includes("!"),
61
+ });
62
+ }
63
+ }
64
+ result.queries.push({ name, type: returnType.trim(), args });
65
+ }
66
+ }
67
+ const mutationMatch = sdl.match(/type\s+Mutation\s*\{([^}]+)\}/s);
68
+ if (mutationMatch?.[1]) {
69
+ const mutationBody = mutationMatch[1];
70
+ let fieldMatch = null;
71
+ fieldPattern.lastIndex = 0;
72
+ while ((fieldMatch = fieldPattern.exec(mutationBody)) !== null) {
73
+ const name = fieldMatch[1];
74
+ const argsStr = fieldMatch[2];
75
+ const returnType = fieldMatch[3];
76
+ if (!name || !returnType)
77
+ continue;
78
+ const args = [];
79
+ if (argsStr) {
80
+ let argMatch = null;
81
+ argPattern.lastIndex = 0;
82
+ while ((argMatch = argPattern.exec(argsStr)) !== null) {
83
+ const argName = argMatch[1];
84
+ const argType = argMatch[2];
85
+ if (!argName || !argType)
86
+ continue;
87
+ args.push({
88
+ name: argName,
89
+ type: argType.trim(),
90
+ required: argType.includes("!"),
91
+ });
92
+ }
93
+ }
94
+ result.mutations.push({ name, type: returnType.trim(), args });
95
+ }
96
+ }
97
+ return result;
98
+ }
99
+ function generateGraphQLOperation(field, operationType) {
100
+ const args = field.args.map((arg) => `$${arg.name}: ${arg.type}`).join(", ");
101
+ const variables = field.args.map((arg) => `${arg.name}: $${arg.name}`).join(", ");
102
+ const argsDecl = args ? `(${args})` : "";
103
+ const varsUsage = variables ? `(${variables})` : "";
104
+ return `${operationType}${argsDecl} { ${field.name}${varsUsage} }`;
105
+ }
106
+ function parseGraphQLSchema(source) {
107
+ const tools = [];
108
+ const parsed = parseGraphQLSDL(source.schema);
109
+ const includeSet = source.include ? new Set(source.include) : null;
110
+ const excludeSet = source.exclude ? new Set(source.exclude) : null;
111
+ const opTypes = source.operationTypes ?? ["query", "mutation"];
112
+ const processField = (field, operationType) => {
113
+ if (includeSet && !includeSet.has(field.name))
114
+ return;
115
+ if (excludeSet && excludeSet.has(field.name))
116
+ return;
117
+ const properties = {};
118
+ const required = [];
119
+ for (const arg of field.args) {
120
+ properties[arg.name] = {
121
+ ...graphqlTypeToJsonSchema(arg.type),
122
+ description: arg.description,
123
+ };
124
+ if (arg.required) {
125
+ required.push(arg.name);
126
+ }
127
+ }
128
+ const inputSchema = {
129
+ type: "object",
130
+ properties,
131
+ required: required.length > 0 ? required : undefined,
132
+ additionalProperties: false,
133
+ };
134
+ const operation = generateGraphQLOperation(field, operationType);
135
+ tools.push({
136
+ name: `graphql.${field.name}`,
137
+ displayName: field.name,
138
+ description: field.description ?? `${operationType === "query" ? "Query" : "Mutate"}: ${field.name}`,
139
+ inputSchema,
140
+ requestTemplate: {
141
+ type: "graphql",
142
+ endpoint: source.endpoint,
143
+ operation,
144
+ },
145
+ source: `graphql:${field.name}`,
146
+ });
147
+ };
148
+ if (opTypes.includes("query")) {
149
+ for (const query of parsed.queries) {
150
+ processField(query, "query");
151
+ }
152
+ }
153
+ if (opTypes.includes("mutation")) {
154
+ for (const mutation of parsed.mutations) {
155
+ processField(mutation, "mutation");
156
+ }
157
+ }
158
+ return tools;
159
+ }
160
+ function parseOpenAPISpec(spec) {
161
+ if (typeof spec === "string") {
162
+ try {
163
+ return JSON.parse(spec);
164
+ }
165
+ catch {
166
+ console.warn("[yak] OpenAPI spec must be valid JSON");
167
+ return { paths: {} };
168
+ }
169
+ }
170
+ return spec;
171
+ }
172
+ function parseOpenAPISchema(source) {
173
+ const tools = [];
174
+ const spec = parseOpenAPISpec(source.spec);
175
+ const baseUrl = source.baseUrl ?? spec.servers?.[0]?.url ?? "";
176
+ const includeSet = source.include ? new Set(source.include) : null;
177
+ const excludeSet = source.exclude ? new Set(source.exclude) : null;
178
+ const methods = source.methods ?? ["get", "post", "put", "patch", "delete"];
179
+ if (!spec.paths)
180
+ return tools;
181
+ for (const [path, pathItem] of Object.entries(spec.paths)) {
182
+ for (const method of methods) {
183
+ const operation = pathItem[method];
184
+ if (!operation)
185
+ continue;
186
+ const operationId = operation.operationId ?? `${method}_${path.replace(/[^a-zA-Z0-9]/g, "_")}`;
187
+ if (includeSet && !includeSet.has(operationId))
188
+ continue;
189
+ if (excludeSet && excludeSet.has(operationId))
190
+ continue;
191
+ const properties = {};
192
+ const required = [];
193
+ const pathParams = {};
194
+ const queryParams = {};
195
+ if (operation.parameters) {
196
+ for (const param of operation.parameters) {
197
+ properties[param.name] = {
198
+ ...(param.schema ?? { type: "string" }),
199
+ description: param.description,
200
+ };
201
+ if (param.required) {
202
+ required.push(param.name);
203
+ }
204
+ if (param.in === "path") {
205
+ pathParams[param.name] = param.name;
206
+ }
207
+ else if (param.in === "query") {
208
+ queryParams[param.name] = param.name;
209
+ }
210
+ }
211
+ }
212
+ let bodyParams;
213
+ const bodySchema = operation.requestBody?.content?.["application/json"]?.schema;
214
+ if (bodySchema?.properties) {
215
+ bodyParams = {};
216
+ for (const [propName, propSchema] of Object.entries(bodySchema.properties)) {
217
+ properties[propName] = propSchema;
218
+ bodyParams[propName] = propName;
219
+ }
220
+ if (bodySchema.required) {
221
+ required.push(...bodySchema.required);
222
+ }
223
+ }
224
+ const inputSchema = {
225
+ type: "object",
226
+ properties,
227
+ required: required.length > 0 ? required : undefined,
228
+ additionalProperties: false,
229
+ };
230
+ tools.push({
231
+ name: `api.${operationId}`,
232
+ displayName: operation.summary ?? operationId,
233
+ description: operation.description ?? operation.summary ?? `${method.toUpperCase()} ${path}`,
234
+ inputSchema,
235
+ requestTemplate: {
236
+ type: "rest",
237
+ url: `${baseUrl}${path}`,
238
+ method: method.toUpperCase(),
239
+ ...(Object.keys(pathParams).length > 0 && { pathParams }),
240
+ ...(Object.keys(queryParams).length > 0 && { queryParams }),
241
+ ...(bodyParams && { bodyParams }),
242
+ },
243
+ source: `openapi:${operationId}`,
244
+ });
245
+ }
246
+ }
247
+ return tools;
248
+ }
249
+ // =============================================================================
250
+ // Public API
251
+ // =============================================================================
252
+ /**
253
+ * Parses schema sources into tool definitions
254
+ */
255
+ export function parseSchemaSources(sources) {
256
+ const tools = [];
257
+ for (const source of sources) {
258
+ try {
259
+ if (source.type === "graphql") {
260
+ tools.push(...parseGraphQLSchema(source));
261
+ }
262
+ else if (source.type === "openapi") {
263
+ tools.push(...parseOpenAPISchema(source));
264
+ }
265
+ }
266
+ catch (error) {
267
+ console.error(`[yak] Failed to parse ${source.type} schema:`, error);
268
+ }
269
+ }
270
+ return tools;
271
+ }
272
+ /**
273
+ * Expands a tool manifest by parsing any schema sources into tool definitions.
274
+ * Use this to pre-process the manifest before passing to YakProvider.
275
+ */
276
+ export function expandToolManifest(manifest) {
277
+ if (!manifest.schemaSources?.length) {
278
+ return manifest;
279
+ }
280
+ const expandedTools = parseSchemaSources(manifest.schemaSources);
281
+ return {
282
+ ...manifest,
283
+ tools: [...manifest.tools, ...expandedTools],
284
+ // Clear schemaSources since they've been expanded
285
+ schemaSources: undefined,
286
+ };
287
+ }
288
+ /**
289
+ * Builds an executable request from a tool definition and provided arguments.
290
+ */
291
+ export function buildExecutableRequest(tool, args) {
292
+ const template = tool.requestTemplate;
293
+ if (!template)
294
+ return undefined;
295
+ if (template.type === "graphql") {
296
+ return {
297
+ type: "graphql",
298
+ endpoint: template.endpoint,
299
+ query: template.operation,
300
+ variables: args,
301
+ };
302
+ }
303
+ // REST request
304
+ let url = template.url;
305
+ if (template.pathParams) {
306
+ for (const [param, argName] of Object.entries(template.pathParams)) {
307
+ const value = args[argName];
308
+ if (value !== undefined) {
309
+ url = url.replace(`{${param}}`, String(value));
310
+ }
311
+ }
312
+ }
313
+ if (template.queryParams) {
314
+ const queryEntries = [];
315
+ for (const [, argName] of Object.entries(template.queryParams)) {
316
+ const value = args[argName];
317
+ if (value !== undefined) {
318
+ queryEntries.push(`${encodeURIComponent(argName)}=${encodeURIComponent(String(value))}`);
319
+ }
320
+ }
321
+ if (queryEntries.length > 0) {
322
+ url += (url.includes("?") ? "&" : "?") + queryEntries.join("&");
323
+ }
324
+ }
325
+ let body;
326
+ if (template.bodyParams) {
327
+ body = {};
328
+ for (const [, argName] of Object.entries(template.bodyParams)) {
329
+ if (args[argName] !== undefined) {
330
+ body[argName] = args[argName];
331
+ }
332
+ }
333
+ }
334
+ return {
335
+ type: "rest",
336
+ url,
337
+ method: template.method,
338
+ headers: { "Content-Type": "application/json" },
339
+ body: body && Object.keys(body).length > 0 ? body : undefined,
340
+ };
341
+ }
@@ -0,0 +1,19 @@
1
+ import type { RouteSourceInput, ToolSourceInput } from "./sources.js";
2
+ export type YakHandlerConfig = {
3
+ routes: RouteSourceInput;
4
+ tools?: ToolSourceInput;
5
+ };
6
+ export declare function createYakHandler(config: YakHandlerConfig): {
7
+ GET: (_req: Request) => Promise<Response>;
8
+ POST: (req: Request) => Promise<Response>;
9
+ };
10
+ export type YakConfigHandlerConfig = {
11
+ routes: RouteSourceInput;
12
+ tools?: ToolSourceInput;
13
+ };
14
+ export declare function createYakConfigHandler(config: YakConfigHandlerConfig): (_req: Request) => Promise<Response>;
15
+ export type YakToolsHandlerConfig = {
16
+ tools: ToolSourceInput;
17
+ };
18
+ export declare function createYakToolsHandler(config: YakToolsHandlerConfig): (req: Request) => Promise<Response>;
19
+ //# sourceMappingURL=createYakHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createYakHandler.d.ts","sourceRoot":"","sources":["../../src/server/createYakHandler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAe,eAAe,EAAc,MAAM,cAAc,CAAC;AAE/F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB;gBAIT,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;gBAezB,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;EA6C5E;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,IAIhC,MAAM,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAcrE;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,eAAe,CAAC;CACxB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,IAO/B,KAAK,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAsCnE"}
@@ -0,0 +1,185 @@
1
+ import { normalizeRouteSources, normalizeToolSources } from "./sources.js";
2
+ export function createYakHandler(config) {
3
+ const routeSources = normalizeRouteSources(config.routes);
4
+ const toolSources = normalizeToolSources(config.tools);
5
+ const GET = async function handleConfig(_req) {
6
+ const chatConfig = {
7
+ routes: await buildRouteManifest(routeSources),
8
+ };
9
+ if (toolSources.length > 0) {
10
+ const { manifest } = await buildToolRegistry(toolSources);
11
+ chatConfig.tools = manifest;
12
+ }
13
+ return jsonResponse(chatConfig, 200, {
14
+ "Cache-Control": "no-store",
15
+ });
16
+ };
17
+ const POST = async function handleToolCall(req) {
18
+ if (toolSources.length === 0) {
19
+ return errorResponse("Tool execution is not configured", 501);
20
+ }
21
+ let payload;
22
+ try {
23
+ payload = await req.json();
24
+ }
25
+ catch {
26
+ return errorResponse("Invalid JSON payload", 400);
27
+ }
28
+ if (!isHostToolCallPayload(payload)) {
29
+ return errorResponse("Invalid tool call payload", 400);
30
+ }
31
+ try {
32
+ const { lookup } = await buildToolRegistry(toolSources);
33
+ const owner = lookup.get(payload.name);
34
+ if (!owner) {
35
+ return createToolErrorResponse(`Tool '${payload.name}' is not registered`);
36
+ }
37
+ if (!owner.executeTool) {
38
+ return createToolErrorResponse(`Tool '${payload.name}' does not expose an executor`);
39
+ }
40
+ const result = await owner.executeTool(payload.name, payload.args, req);
41
+ const successResult = {
42
+ ok: true,
43
+ result,
44
+ };
45
+ return jsonResponse(successResult);
46
+ }
47
+ catch (error) {
48
+ return createToolErrorResponse(extractErrorMessage(error));
49
+ }
50
+ };
51
+ return { GET, POST };
52
+ }
53
+ export function createYakConfigHandler(config) {
54
+ const routeSources = normalizeRouteSources(config.routes);
55
+ const toolSources = normalizeToolSources(config.tools);
56
+ return async function handleConfig(_req) {
57
+ const chatConfig = {
58
+ routes: await buildRouteManifest(routeSources),
59
+ };
60
+ if (toolSources.length > 0) {
61
+ const { manifest } = await buildToolRegistry(toolSources);
62
+ chatConfig.tools = manifest;
63
+ }
64
+ return jsonResponse(chatConfig, 200, {
65
+ "Cache-Control": "no-store",
66
+ });
67
+ };
68
+ }
69
+ export function createYakToolsHandler(config) {
70
+ const toolSources = normalizeToolSources(config.tools);
71
+ if (toolSources.length === 0) {
72
+ throw new Error("createYakToolsHandler requires at least one tool source");
73
+ }
74
+ return async function handleTools(req) {
75
+ let payload;
76
+ try {
77
+ payload = await req.json();
78
+ }
79
+ catch {
80
+ return errorResponse("Invalid JSON payload", 400);
81
+ }
82
+ if (!isHostToolCallPayload(payload)) {
83
+ return errorResponse("Invalid tool call payload", 400);
84
+ }
85
+ try {
86
+ const { lookup } = await buildToolRegistry(toolSources);
87
+ const owner = lookup.get(payload.name);
88
+ if (!owner) {
89
+ return createToolErrorResponse(`Tool '${payload.name}' is not registered`);
90
+ }
91
+ if (!owner.executeTool) {
92
+ return createToolErrorResponse(`Tool '${payload.name}' does not expose an executor`);
93
+ }
94
+ const result = await owner.executeTool(payload.name, payload.args, req);
95
+ const successResult = {
96
+ ok: true,
97
+ result,
98
+ };
99
+ return jsonResponse(successResult);
100
+ }
101
+ catch (error) {
102
+ return createToolErrorResponse(extractErrorMessage(error));
103
+ }
104
+ };
105
+ }
106
+ async function buildRouteManifest(routeSources) {
107
+ const entries = await Promise.all(routeSources.map(async (source) => ({
108
+ id: source.id ?? "routes",
109
+ routes: await source.getRoutes(),
110
+ })));
111
+ const merged = [];
112
+ const seen = new Set();
113
+ for (const entry of entries) {
114
+ for (const route of entry.routes) {
115
+ const key = route.path;
116
+ if (!seen.has(key)) {
117
+ seen.add(key);
118
+ merged.push(route);
119
+ }
120
+ }
121
+ }
122
+ merged.sort((a, b) => a.path.localeCompare(b.path));
123
+ return {
124
+ routes: merged,
125
+ generated_at: new Date().toISOString(),
126
+ sources: entries.map((entry) => ({ id: entry.id, count: entry.routes.length })),
127
+ };
128
+ }
129
+ async function buildToolRegistry(toolSources) {
130
+ const entries = await Promise.all(toolSources.map(async (source) => ({
131
+ id: source.id ?? "tools",
132
+ source,
133
+ tools: await source.getTools(),
134
+ })));
135
+ const manifestTools = [];
136
+ const lookup = new Map();
137
+ for (const entry of entries) {
138
+ for (const tool of entry.tools) {
139
+ manifestTools.push(tool);
140
+ lookup.set(tool.name, entry.source);
141
+ }
142
+ }
143
+ return {
144
+ manifest: {
145
+ tools: manifestTools,
146
+ generated_at: new Date().toISOString(),
147
+ sources: entries.map((entry) => ({ id: entry.id, count: entry.tools.length })),
148
+ },
149
+ lookup,
150
+ };
151
+ }
152
+ function isHostToolCallPayload(payload) {
153
+ return (typeof payload === "object" &&
154
+ payload !== null &&
155
+ typeof payload.name === "string" &&
156
+ "args" in payload);
157
+ }
158
+ function extractErrorMessage(error) {
159
+ if (error instanceof Error) {
160
+ return error.message;
161
+ }
162
+ if (typeof error === "string") {
163
+ return error;
164
+ }
165
+ return "An unknown error occurred";
166
+ }
167
+ function jsonResponse(body, status = 200, headers = {}) {
168
+ return new Response(JSON.stringify(body), {
169
+ status,
170
+ headers: {
171
+ "Content-Type": "application/json",
172
+ ...headers,
173
+ },
174
+ });
175
+ }
176
+ function errorResponse(message, status) {
177
+ return jsonResponse({ error: message }, status);
178
+ }
179
+ function createToolErrorResponse(error) {
180
+ const errorResult = {
181
+ ok: false,
182
+ error,
183
+ };
184
+ return jsonResponse(errorResult);
185
+ }
@@ -0,0 +1,8 @@
1
+ export { createYakHandler, createYakConfigHandler, createYakToolsHandler, } from "./createYakHandler.js";
2
+ export type { YakHandlerConfig, YakConfigHandlerConfig, YakToolsHandlerConfig, } from "./createYakHandler.js";
3
+ export { normalizeRouteSources, normalizeToolSources, } from "./sources.js";
4
+ export type { RouteSource, RouteSourceInput, ToolSource, ToolSourceInput } from "./sources.js";
5
+ export type { ToolExecutor, ToolDefinition, ToolManifest, ToolCallPayload, ToolCallResult, } from "../types/tools.js";
6
+ export type { RouteInfo, RouteManifest } from "../types/routes.js";
7
+ export type { ChatConfig } from "../types/config.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/F,YAAY,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,eAAe,EACf,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createYakHandler, createYakConfigHandler, createYakToolsHandler, } from "./createYakHandler.js";
2
+ export { normalizeRouteSources, normalizeToolSources, } from "./sources.js";
@@ -0,0 +1,24 @@
1
+ import type { RouteInfo } from "../types/routes.js";
2
+ import type { ToolDefinition, ToolManifest, ToolExecutor } from "../types/tools.js";
3
+ export type RouteSource = {
4
+ id?: string;
5
+ getRoutes: () => Promise<RouteInfo[]>;
6
+ };
7
+ type RouteSourceFn = () => Promise<RouteInfo[]>;
8
+ type RouteSourceInputItem = RouteSource | RouteSourceFn | RouteInfo[];
9
+ export type RouteSourceInput = RouteSourceInputItem | RouteSourceInputItem[];
10
+ export type ToolSource = {
11
+ id?: string;
12
+ getTools: () => Promise<ToolDefinition[]>;
13
+ executeTool?: ToolExecutor;
14
+ };
15
+ type ToolSourceFn = () => Promise<ToolDefinition[] | ToolManifest>;
16
+ type ToolSourceInputItem = ToolSource | ToolSourceFn | ToolDefinition[] | ToolManifest | {
17
+ getTools: ToolSourceFn;
18
+ executeTool?: ToolExecutor;
19
+ };
20
+ export type ToolSourceInput = ToolSourceInputItem | ToolSourceInputItem[];
21
+ export declare function normalizeRouteSources(input: RouteSourceInput): RouteSource[];
22
+ export declare function normalizeToolSources(input?: ToolSourceInput): ToolSource[];
23
+ export {};
24
+ //# sourceMappingURL=sources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/server/sources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpF,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CACvC,CAAC;AAEF,KAAK,aAAa,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,EAAE,CAAC;AAEtE,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,oBAAoB,EAAE,CAAC;AAE7E,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC1C,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,KAAK,YAAY,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,GAAG,YAAY,CAAC,CAAC;AAEnE,KAAK,mBAAmB,GACpB,UAAU,GACV,YAAY,GACZ,cAAc,EAAE,GAChB,YAAY,GACZ;IACE,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEN,MAAM,MAAM,eAAe,GAAG,mBAAmB,GAAG,mBAAmB,EAAE,CAAC;AAqC1E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,EAAE,CAY5E;AA4ED,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,eAAe,GAAG,UAAU,EAAE,CAe1E"}