@yak-io/graphql 0.1.2 → 0.2.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.
- package/dist/adapters.d.ts +18 -2
- package/dist/adapters.d.ts.map +1 -1
- package/dist/index.cjs +86 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.js +63 -2
- package/dist/index.js.map +7 -0
- package/package.json +5 -4
- package/dist/adapters.js +0 -68
package/dist/adapters.d.ts
CHANGED
|
@@ -3,8 +3,13 @@ import type { GraphQLRequest, ToolAdapter } from "@yak-io/javascript";
|
|
|
3
3
|
export type GraphQLToolAdapterConfig = {
|
|
4
4
|
/** Schema name — the tool is exposed to the LLM as `graphql_<name>`. */
|
|
5
5
|
name: string;
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* GraphQL schema as SDL — either a literal string, or a resolver that returns it (sync or
|
|
8
|
+
* async). Use a resolver when your SDL comes from introspection or any other deferred source:
|
|
9
|
+
* it runs once on first `getTools()` and the resulting SDL is cached, so the network call is
|
|
10
|
+
* paid lazily, not at construction. A literal string is embedded eagerly with no async overhead.
|
|
11
|
+
*/
|
|
12
|
+
schema: string | (() => string | Promise<string>);
|
|
8
13
|
/**
|
|
9
14
|
* Execute the LLM-authored GraphQL request with YOUR client. Yak builds the tool and the
|
|
10
15
|
* request payload (query / variables / operationName) but never makes the call itself — your
|
|
@@ -33,6 +38,17 @@ export type GraphQLToolAdapterConfig = {
|
|
|
33
38
|
* execute: (req) => myGraphQLClient.request(req.query, req.variables),
|
|
34
39
|
* });
|
|
35
40
|
* ```
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* // Lazy: resolve SDL from introspection once, on first use. The factory stays synchronous —
|
|
45
|
+
* // the network call is paid when the toolset first materializes its tools, then cached.
|
|
46
|
+
* const shop = createGraphQLToolAdapter({
|
|
47
|
+
* name: "shop",
|
|
48
|
+
* schema: async () => printSchema(buildClientSchema(await introspect(endpoint))),
|
|
49
|
+
* execute: (req) => myGraphQLClient.request(req.query, req.variables),
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
36
52
|
*/
|
|
37
53
|
export declare function createGraphQLToolAdapter(config: GraphQLToolAdapterConfig): ToolAdapter;
|
|
38
54
|
//# sourceMappingURL=adapters.d.ts.map
|
package/dist/adapters.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAc,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AAElG,mDAAmD;AACnD,MAAM,MAAM,wBAAwB,GAAG;IACrC,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAc,WAAW,EAAkB,MAAM,oBAAoB,CAAC;AAElG,mDAAmD;AACnD,MAAM,MAAM,wBAAwB,GAAG;IACrC,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD;;;;;;OAMG;IACH,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,4DAA4D;IAC5D,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AA6BF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,wBAAwB,GAAG,WAAW,CA8CtF"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
createGraphQLToolAdapter: () => createGraphQLToolAdapter
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/adapters.ts
|
|
28
|
+
var GRAPHQL_INPUT_SCHEMA = {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
query: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "The GraphQL query or mutation string. Use $variableName syntax for all dynamic values."
|
|
34
|
+
},
|
|
35
|
+
variables: {
|
|
36
|
+
type: "object",
|
|
37
|
+
description: "Variables object with values for all $variableName references in the query.",
|
|
38
|
+
additionalProperties: true
|
|
39
|
+
},
|
|
40
|
+
operationName: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Optional operation name if the query contains multiple operations."
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
required: ["query"],
|
|
46
|
+
additionalProperties: false
|
|
47
|
+
};
|
|
48
|
+
function createGraphQLToolAdapter(config) {
|
|
49
|
+
const toolName = `graphql_${config.name}`;
|
|
50
|
+
const buildTool = (sdl) => ({
|
|
51
|
+
name: toolName,
|
|
52
|
+
description: `Execute a GraphQL query or mutation against the ${config.name} API. You MUST use GraphQL variables for all dynamic values \u2014 never hardcode values directly in the query string. Define variables with $variableName syntax and pass them in the variables object.
|
|
53
|
+
|
|
54
|
+
Schema (SDL):
|
|
55
|
+
\`\`\`graphql
|
|
56
|
+
${sdl}
|
|
57
|
+
\`\`\``,
|
|
58
|
+
inputSchema: GRAPHQL_INPUT_SCHEMA
|
|
59
|
+
});
|
|
60
|
+
const eager = typeof config.schema === "string" ? [buildTool(config.schema)] : void 0;
|
|
61
|
+
let pending;
|
|
62
|
+
return {
|
|
63
|
+
id: config.id ?? toolName,
|
|
64
|
+
getTools: () => {
|
|
65
|
+
if (eager) return eager;
|
|
66
|
+
if (!pending) {
|
|
67
|
+
const resolve = config.schema;
|
|
68
|
+
pending = Promise.resolve().then(resolve).then((sdl) => [buildTool(sdl)]);
|
|
69
|
+
pending.catch(() => {
|
|
70
|
+
pending = void 0;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return pending;
|
|
74
|
+
},
|
|
75
|
+
ownsTool: (name) => name === toolName,
|
|
76
|
+
execute: async (_name, args) => {
|
|
77
|
+
const request = args ?? {};
|
|
78
|
+
return config.execute({
|
|
79
|
+
query: request.query,
|
|
80
|
+
variables: request.variables,
|
|
81
|
+
operationName: request.operationName
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts", "../src/adapters.ts"],
|
|
4
|
+
"sourcesContent": ["// GraphQL tool adapter for the yak client toolset\nexport { createGraphQLToolAdapter } from \"./adapters.js\";\nexport type { GraphQLToolAdapterConfig } from \"./adapters.js\";\n\n// Shared types from core\nexport type { GraphQLRequest, ToolAdapter, ToolDefinition } from \"@yak-io/javascript\";\n", "import type { GraphQLRequest, JSONSchema, ToolAdapter, ToolDefinition } from \"@yak-io/javascript\";\n\n/** Config for {@link createGraphQLToolAdapter}. */\nexport type GraphQLToolAdapterConfig = {\n /** Schema name \u2014 the tool is exposed to the LLM as `graphql_<name>`. */\n name: string;\n /**\n * GraphQL schema as SDL \u2014 either a literal string, or a resolver that returns it (sync or\n * async). Use a resolver when your SDL comes from introspection or any other deferred source:\n * it runs once on first `getTools()` and the resulting SDL is cached, so the network call is\n * paid lazily, not at construction. A literal string is embedded eagerly with no async overhead.\n */\n schema: string | (() => string | Promise<string>);\n /**\n * Execute the LLM-authored GraphQL request with YOUR client. Yak builds the tool and the\n * request payload (query / variables / operationName) but never makes the call itself \u2014 your\n * client owns transport, auth, retries, and error handling. Use whatever you already have\n * (Apollo, urql, graphql-request, a signed `fetch`, \u2026). Return the result the assistant should\n * see (typically the `data` field); throw to surface an error to the model.\n */\n execute: (request: GraphQLRequest) => unknown | Promise<unknown>;\n /** Stable id for diagnostics. Defaults to the tool name. */\n id?: string;\n};\n\n/**\n * Generic input schema for a GraphQL tool. The LLM authors the query + variables;\n * the adapter hands them to your `execute` client. Do NOT inject `_reason` here \u2014 the\n * chat-ui / voice runtimes inject it when registering the tool with the model.\n */\nconst GRAPHQL_INPUT_SCHEMA: JSONSchema = {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description:\n \"The GraphQL query or mutation string. Use $variableName syntax for all dynamic values.\",\n },\n variables: {\n type: \"object\",\n description: \"Variables object with values for all $variableName references in the query.\",\n additionalProperties: true,\n },\n operationName: {\n type: \"string\",\n description: \"Optional operation name if the query contains multiple operations.\",\n },\n },\n required: [\"query\"],\n additionalProperties: false,\n};\n\n/**\n * Create a GraphQL {@link ToolAdapter}. Compose it into a {@link createYakToolset} so the\n * generated `graphql_<name>` tool joins the single merged manifest + `onToolCall` funnel\n * (and therefore surfaces through `onToolCallComplete` / `useYakToolEvent`).\n *\n * The model authors a query/mutation from the SDL you provide; the adapter hands the request\n * to your `execute` callback, which runs it with whatever client you already use. Yak never\n * constructs the HTTP call \u2014 your client owns the endpoint, auth, and transport.\n *\n * @example\n * ```ts\n * const shop = createGraphQLToolAdapter({\n * name: \"shop\",\n * schema: typeDefs,\n * execute: (req) => myGraphQLClient.request(req.query, req.variables),\n * });\n * ```\n *\n * @example\n * ```ts\n * // Lazy: resolve SDL from introspection once, on first use. The factory stays synchronous \u2014\n * // the network call is paid when the toolset first materializes its tools, then cached.\n * const shop = createGraphQLToolAdapter({\n * name: \"shop\",\n * schema: async () => printSchema(buildClientSchema(await introspect(endpoint))),\n * execute: (req) => myGraphQLClient.request(req.query, req.variables),\n * });\n * ```\n */\nexport function createGraphQLToolAdapter(config: GraphQLToolAdapterConfig): ToolAdapter {\n const toolName = `graphql_${config.name}`;\n\n const buildTool = (sdl: string): ToolDefinition => ({\n name: toolName,\n description:\n `Execute a GraphQL query or mutation against the ${config.name} API. ` +\n \"You MUST use GraphQL variables for all dynamic values \u2014 never hardcode values directly in \" +\n \"the query string. Define variables with $variableName syntax and pass them in the variables \" +\n `object.\\n\\nSchema (SDL):\\n\\`\\`\\`graphql\\n${sdl}\\n\\`\\`\\``,\n inputSchema: GRAPHQL_INPUT_SCHEMA,\n });\n\n // A literal SDL builds the tool eagerly (no async overhead, identical to before). A resolver\n // runs once on first getTools() and the [tool] result is cached; a rejection is NOT cached, so\n // a later getTools() can retry \u2014 a transient introspection failure doesn't wedge the toolset.\n const eager = typeof config.schema === \"string\" ? [buildTool(config.schema)] : undefined;\n let pending: Promise<ToolDefinition[]> | undefined;\n\n return {\n id: config.id ?? toolName,\n getTools: () => {\n if (eager) return eager;\n if (!pending) {\n const resolve = config.schema as () => string | Promise<string>;\n // Promise.resolve().then(resolve) so a synchronous throw also surfaces as a rejection.\n pending = Promise.resolve()\n .then(resolve)\n .then((sdl) => [buildTool(sdl)]);\n pending.catch(() => {\n pending = undefined; // don't cache failures \u2014 allow retry on the next getTools()\n });\n }\n return pending;\n },\n ownsTool: (name) => name === toolName,\n execute: async (_name, args) => {\n const request = (args ?? {}) as GraphQLRequest;\n // Hand a clean request to the caller's client \u2014 never forward the runtime-injected `_reason`.\n return config.execute({\n query: request.query,\n variables: request.variables,\n operationName: request.operationName,\n });\n },\n };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC8BA,IAAM,uBAAmC;AAAA,EACvC,MAAM;AAAA,EACN,YAAY;AAAA,IACV,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,sBAAsB;AAAA,IACxB;AAAA,IACA,eAAe;AAAA,MACb,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU,CAAC,OAAO;AAAA,EAClB,sBAAsB;AACxB;AA+BO,SAAS,yBAAyB,QAA+C;AACtF,QAAM,WAAW,WAAW,OAAO,IAAI;AAEvC,QAAM,YAAY,CAAC,SAAiC;AAAA,IAClD,MAAM;AAAA,IACN,aACE,mDAAmD,OAAO,IAAI;AAAA;AAAA;AAAA;AAAA,EAGlB,GAAG;AAAA;AAAA,IACjD,aAAa;AAAA,EACf;AAKA,QAAM,QAAQ,OAAO,OAAO,WAAW,WAAW,CAAC,UAAU,OAAO,MAAM,CAAC,IAAI;AAC/E,MAAI;AAEJ,SAAO;AAAA,IACL,IAAI,OAAO,MAAM;AAAA,IACjB,UAAU,MAAM;AACd,UAAI,MAAO,QAAO;AAClB,UAAI,CAAC,SAAS;AACZ,cAAM,UAAU,OAAO;AAEvB,kBAAU,QAAQ,QAAQ,EACvB,KAAK,OAAO,EACZ,KAAK,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC;AACjC,gBAAQ,MAAM,MAAM;AAClB,oBAAU;AAAA,QACZ,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAAA,IACA,UAAU,CAAC,SAAS,SAAS;AAAA,IAC7B,SAAS,OAAO,OAAO,SAAS;AAC9B,YAAM,UAAW,QAAQ,CAAC;AAE1B,aAAO,OAAO,QAAQ;AAAA,QACpB,OAAO,QAAQ;AAAA,QACf,WAAW,QAAQ;AAAA,QACnB,eAAe,QAAQ;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,63 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
1
|
+
// src/adapters.ts
|
|
2
|
+
var GRAPHQL_INPUT_SCHEMA = {
|
|
3
|
+
type: "object",
|
|
4
|
+
properties: {
|
|
5
|
+
query: {
|
|
6
|
+
type: "string",
|
|
7
|
+
description: "The GraphQL query or mutation string. Use $variableName syntax for all dynamic values."
|
|
8
|
+
},
|
|
9
|
+
variables: {
|
|
10
|
+
type: "object",
|
|
11
|
+
description: "Variables object with values for all $variableName references in the query.",
|
|
12
|
+
additionalProperties: true
|
|
13
|
+
},
|
|
14
|
+
operationName: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Optional operation name if the query contains multiple operations."
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
required: ["query"],
|
|
20
|
+
additionalProperties: false
|
|
21
|
+
};
|
|
22
|
+
function createGraphQLToolAdapter(config) {
|
|
23
|
+
const toolName = `graphql_${config.name}`;
|
|
24
|
+
const buildTool = (sdl) => ({
|
|
25
|
+
name: toolName,
|
|
26
|
+
description: `Execute a GraphQL query or mutation against the ${config.name} API. You MUST use GraphQL variables for all dynamic values \u2014 never hardcode values directly in the query string. Define variables with $variableName syntax and pass them in the variables object.
|
|
27
|
+
|
|
28
|
+
Schema (SDL):
|
|
29
|
+
\`\`\`graphql
|
|
30
|
+
${sdl}
|
|
31
|
+
\`\`\``,
|
|
32
|
+
inputSchema: GRAPHQL_INPUT_SCHEMA
|
|
33
|
+
});
|
|
34
|
+
const eager = typeof config.schema === "string" ? [buildTool(config.schema)] : void 0;
|
|
35
|
+
let pending;
|
|
36
|
+
return {
|
|
37
|
+
id: config.id ?? toolName,
|
|
38
|
+
getTools: () => {
|
|
39
|
+
if (eager) return eager;
|
|
40
|
+
if (!pending) {
|
|
41
|
+
const resolve = config.schema;
|
|
42
|
+
pending = Promise.resolve().then(resolve).then((sdl) => [buildTool(sdl)]);
|
|
43
|
+
pending.catch(() => {
|
|
44
|
+
pending = void 0;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return pending;
|
|
48
|
+
},
|
|
49
|
+
ownsTool: (name) => name === toolName,
|
|
50
|
+
execute: async (_name, args) => {
|
|
51
|
+
const request = args ?? {};
|
|
52
|
+
return config.execute({
|
|
53
|
+
query: request.query,
|
|
54
|
+
variables: request.variables,
|
|
55
|
+
operationName: request.operationName
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
createGraphQLToolAdapter
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/adapters.ts"],
|
|
4
|
+
"sourcesContent": ["import type { GraphQLRequest, JSONSchema, ToolAdapter, ToolDefinition } from \"@yak-io/javascript\";\n\n/** Config for {@link createGraphQLToolAdapter}. */\nexport type GraphQLToolAdapterConfig = {\n /** Schema name \u2014 the tool is exposed to the LLM as `graphql_<name>`. */\n name: string;\n /**\n * GraphQL schema as SDL \u2014 either a literal string, or a resolver that returns it (sync or\n * async). Use a resolver when your SDL comes from introspection or any other deferred source:\n * it runs once on first `getTools()` and the resulting SDL is cached, so the network call is\n * paid lazily, not at construction. A literal string is embedded eagerly with no async overhead.\n */\n schema: string | (() => string | Promise<string>);\n /**\n * Execute the LLM-authored GraphQL request with YOUR client. Yak builds the tool and the\n * request payload (query / variables / operationName) but never makes the call itself \u2014 your\n * client owns transport, auth, retries, and error handling. Use whatever you already have\n * (Apollo, urql, graphql-request, a signed `fetch`, \u2026). Return the result the assistant should\n * see (typically the `data` field); throw to surface an error to the model.\n */\n execute: (request: GraphQLRequest) => unknown | Promise<unknown>;\n /** Stable id for diagnostics. Defaults to the tool name. */\n id?: string;\n};\n\n/**\n * Generic input schema for a GraphQL tool. The LLM authors the query + variables;\n * the adapter hands them to your `execute` client. Do NOT inject `_reason` here \u2014 the\n * chat-ui / voice runtimes inject it when registering the tool with the model.\n */\nconst GRAPHQL_INPUT_SCHEMA: JSONSchema = {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description:\n \"The GraphQL query or mutation string. Use $variableName syntax for all dynamic values.\",\n },\n variables: {\n type: \"object\",\n description: \"Variables object with values for all $variableName references in the query.\",\n additionalProperties: true,\n },\n operationName: {\n type: \"string\",\n description: \"Optional operation name if the query contains multiple operations.\",\n },\n },\n required: [\"query\"],\n additionalProperties: false,\n};\n\n/**\n * Create a GraphQL {@link ToolAdapter}. Compose it into a {@link createYakToolset} so the\n * generated `graphql_<name>` tool joins the single merged manifest + `onToolCall` funnel\n * (and therefore surfaces through `onToolCallComplete` / `useYakToolEvent`).\n *\n * The model authors a query/mutation from the SDL you provide; the adapter hands the request\n * to your `execute` callback, which runs it with whatever client you already use. Yak never\n * constructs the HTTP call \u2014 your client owns the endpoint, auth, and transport.\n *\n * @example\n * ```ts\n * const shop = createGraphQLToolAdapter({\n * name: \"shop\",\n * schema: typeDefs,\n * execute: (req) => myGraphQLClient.request(req.query, req.variables),\n * });\n * ```\n *\n * @example\n * ```ts\n * // Lazy: resolve SDL from introspection once, on first use. The factory stays synchronous \u2014\n * // the network call is paid when the toolset first materializes its tools, then cached.\n * const shop = createGraphQLToolAdapter({\n * name: \"shop\",\n * schema: async () => printSchema(buildClientSchema(await introspect(endpoint))),\n * execute: (req) => myGraphQLClient.request(req.query, req.variables),\n * });\n * ```\n */\nexport function createGraphQLToolAdapter(config: GraphQLToolAdapterConfig): ToolAdapter {\n const toolName = `graphql_${config.name}`;\n\n const buildTool = (sdl: string): ToolDefinition => ({\n name: toolName,\n description:\n `Execute a GraphQL query or mutation against the ${config.name} API. ` +\n \"You MUST use GraphQL variables for all dynamic values \u2014 never hardcode values directly in \" +\n \"the query string. Define variables with $variableName syntax and pass them in the variables \" +\n `object.\\n\\nSchema (SDL):\\n\\`\\`\\`graphql\\n${sdl}\\n\\`\\`\\``,\n inputSchema: GRAPHQL_INPUT_SCHEMA,\n });\n\n // A literal SDL builds the tool eagerly (no async overhead, identical to before). A resolver\n // runs once on first getTools() and the [tool] result is cached; a rejection is NOT cached, so\n // a later getTools() can retry \u2014 a transient introspection failure doesn't wedge the toolset.\n const eager = typeof config.schema === \"string\" ? [buildTool(config.schema)] : undefined;\n let pending: Promise<ToolDefinition[]> | undefined;\n\n return {\n id: config.id ?? toolName,\n getTools: () => {\n if (eager) return eager;\n if (!pending) {\n const resolve = config.schema as () => string | Promise<string>;\n // Promise.resolve().then(resolve) so a synchronous throw also surfaces as a rejection.\n pending = Promise.resolve()\n .then(resolve)\n .then((sdl) => [buildTool(sdl)]);\n pending.catch(() => {\n pending = undefined; // don't cache failures \u2014 allow retry on the next getTools()\n });\n }\n return pending;\n },\n ownsTool: (name) => name === toolName,\n execute: async (_name, args) => {\n const request = (args ?? {}) as GraphQLRequest;\n // Hand a clean request to the caller's client \u2014 never forward the runtime-injected `_reason`.\n return config.execute({\n query: request.query,\n variables: request.variables,\n operationName: request.operationName,\n });\n },\n };\n}\n"],
|
|
5
|
+
"mappings": ";AA8BA,IAAM,uBAAmC;AAAA,EACvC,MAAM;AAAA,EACN,YAAY;AAAA,IACV,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,sBAAsB;AAAA,IACxB;AAAA,IACA,eAAe;AAAA,MACb,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU,CAAC,OAAO;AAAA,EAClB,sBAAsB;AACxB;AA+BO,SAAS,yBAAyB,QAA+C;AACtF,QAAM,WAAW,WAAW,OAAO,IAAI;AAEvC,QAAM,YAAY,CAAC,SAAiC;AAAA,IAClD,MAAM;AAAA,IACN,aACE,mDAAmD,OAAO,IAAI;AAAA;AAAA;AAAA;AAAA,EAGlB,GAAG;AAAA;AAAA,IACjD,aAAa;AAAA,EACf;AAKA,QAAM,QAAQ,OAAO,OAAO,WAAW,WAAW,CAAC,UAAU,OAAO,MAAM,CAAC,IAAI;AAC/E,MAAI;AAEJ,SAAO;AAAA,IACL,IAAI,OAAO,MAAM;AAAA,IACjB,UAAU,MAAM;AACd,UAAI,MAAO,QAAO;AAClB,UAAI,CAAC,SAAS;AACZ,cAAM,UAAU,OAAO;AAEvB,kBAAU,QAAQ,QAAQ,EACvB,KAAK,OAAO,EACZ,KAAK,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC;AACjC,gBAAQ,MAAM,MAAM;AAClB,oBAAU;AAAA,QACZ,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAAA,IACA,UAAU,CAAC,SAAS,SAAS;AAAA,IAC7B,SAAS,OAAO,OAAO,SAAS;AAC9B,YAAM,UAAW,QAAQ,CAAC;AAE1B,aAAO,OAAO,QAAQ;AAAA,QACpB,OAAO,QAAQ;AAAA,QACf,WAAW,QAAQ;AAAA,QACnB,eAAe,QAAQ;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yak-io/graphql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "GraphQL adapter for yak chatbot - exposes a GraphQL API as a chatbot tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -29,19 +29,20 @@
|
|
|
29
29
|
"LICENSE"
|
|
30
30
|
],
|
|
31
31
|
"sideEffects": false,
|
|
32
|
-
"main": "./dist/index.
|
|
32
|
+
"main": "./dist/index.cjs",
|
|
33
33
|
"module": "./dist/index.js",
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
35
|
"exports": {
|
|
36
36
|
".": {
|
|
37
37
|
"types": "./dist/index.d.ts",
|
|
38
38
|
"import": "./dist/index.js",
|
|
39
|
+
"require": "./dist/index.cjs",
|
|
39
40
|
"default": "./dist/index.js"
|
|
40
41
|
},
|
|
41
42
|
"./package.json": "./package.json"
|
|
42
43
|
},
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@yak-io/javascript": "0.
|
|
45
|
+
"@yak-io/javascript": "0.11.0"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@types/node": "^24.12.4",
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
},
|
|
51
52
|
"homepage": "https://docs.yak.io/docs/tool-adapters/graphql",
|
|
52
53
|
"scripts": {
|
|
53
|
-
"build": "tsc",
|
|
54
|
+
"build": "node ../../scripts/build-package.mjs && tsc --emitDeclarationOnly",
|
|
54
55
|
"check-types": "tsc --noEmit",
|
|
55
56
|
"test": "vitest run",
|
|
56
57
|
"lint": "biome lint ./src --fix",
|
package/dist/adapters.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic input schema for a GraphQL tool. The LLM authors the query + variables;
|
|
3
|
-
* the adapter hands them to your `execute` client. Do NOT inject `_reason` here — the
|
|
4
|
-
* chat-ui / voice runtimes inject it when registering the tool with the model.
|
|
5
|
-
*/
|
|
6
|
-
const GRAPHQL_INPUT_SCHEMA = {
|
|
7
|
-
type: "object",
|
|
8
|
-
properties: {
|
|
9
|
-
query: {
|
|
10
|
-
type: "string",
|
|
11
|
-
description: "The GraphQL query or mutation string. Use $variableName syntax for all dynamic values.",
|
|
12
|
-
},
|
|
13
|
-
variables: {
|
|
14
|
-
type: "object",
|
|
15
|
-
description: "Variables object with values for all $variableName references in the query.",
|
|
16
|
-
additionalProperties: true,
|
|
17
|
-
},
|
|
18
|
-
operationName: {
|
|
19
|
-
type: "string",
|
|
20
|
-
description: "Optional operation name if the query contains multiple operations.",
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
required: ["query"],
|
|
24
|
-
additionalProperties: false,
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Create a GraphQL {@link ToolAdapter}. Compose it into a {@link createYakToolset} so the
|
|
28
|
-
* generated `graphql_<name>` tool joins the single merged manifest + `onToolCall` funnel
|
|
29
|
-
* (and therefore surfaces through `onToolCallComplete` / `useYakToolEvent`).
|
|
30
|
-
*
|
|
31
|
-
* The model authors a query/mutation from the SDL you provide; the adapter hands the request
|
|
32
|
-
* to your `execute` callback, which runs it with whatever client you already use. Yak never
|
|
33
|
-
* constructs the HTTP call — your client owns the endpoint, auth, and transport.
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```ts
|
|
37
|
-
* const shop = createGraphQLToolAdapter({
|
|
38
|
-
* name: "shop",
|
|
39
|
-
* schema: typeDefs,
|
|
40
|
-
* execute: (req) => myGraphQLClient.request(req.query, req.variables),
|
|
41
|
-
* });
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export function createGraphQLToolAdapter(config) {
|
|
45
|
-
const toolName = `graphql_${config.name}`;
|
|
46
|
-
const tool = {
|
|
47
|
-
name: toolName,
|
|
48
|
-
description: `Execute a GraphQL query or mutation against the ${config.name} API. ` +
|
|
49
|
-
"You MUST use GraphQL variables for all dynamic values — never hardcode values directly in " +
|
|
50
|
-
"the query string. Define variables with $variableName syntax and pass them in the variables " +
|
|
51
|
-
`object.\n\nSchema (SDL):\n\`\`\`graphql\n${config.schema}\n\`\`\``,
|
|
52
|
-
inputSchema: GRAPHQL_INPUT_SCHEMA,
|
|
53
|
-
};
|
|
54
|
-
return {
|
|
55
|
-
id: config.id ?? toolName,
|
|
56
|
-
getTools: () => [tool],
|
|
57
|
-
ownsTool: (name) => name === toolName,
|
|
58
|
-
execute: async (_name, args) => {
|
|
59
|
-
const request = (args ?? {});
|
|
60
|
-
// Hand a clean request to the caller's client — never forward the runtime-injected `_reason`.
|
|
61
|
-
return config.execute({
|
|
62
|
-
query: request.query,
|
|
63
|
-
variables: request.variables,
|
|
64
|
-
operationName: request.operationName,
|
|
65
|
-
});
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
}
|