@yak-io/javascript 0.9.0 → 0.10.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/README.md +7 -8
- package/dist/client.d.ts +9 -47
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +15 -71
- package/dist/embed.d.ts.map +1 -1
- package/dist/embed.js +3 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/toolset.d.ts +45 -0
- package/dist/toolset.d.ts.map +1 -0
- package/dist/toolset.js +119 -0
- package/dist/types/config.d.ts +3 -5
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/messaging.d.ts +1 -17
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/tools.d.ts +35 -42
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/voice-session.d.ts +12 -14
- package/dist/voice-session.d.ts.map +1 -1
- package/dist/voice-session.js +22 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,8 @@ pnpm add @yak-io/javascript
|
|
|
19
19
|
| `YakEmbed` | class | Drop-in widget: trigger pill + chat panel + voice, all wired. Start here. |
|
|
20
20
|
| `YakClient` | class | Headless chat-only iframe client (no DOM). Advanced. |
|
|
21
21
|
| `YakVoiceSession` | class | Headless WebRTC voice session. Advanced. |
|
|
22
|
+
| `createYakToolset` | fn | Compose tool adapters (GraphQL, REST, tRPC, custom) into one merged manifest + one routed `onToolCall`. |
|
|
23
|
+
| `createYakServerAdapter` | fn | Wrap a server handler endpoint (`createYakHandler`) as a `ToolAdapter` for `createYakToolset`. |
|
|
22
24
|
| `enableYakLogging` / `disableYakLogging` / `isYakLoggingEnabled` | fn | Toggle verbose SDK logging. |
|
|
23
25
|
| `EMBED_PROTOCOL_VERSION` | const | Host ↔ iframe protocol version. |
|
|
24
26
|
| Types | — | `YakEmbedConfig`, `YakClientConfig`, `Theme`, `WidgetMode`, `VoiceState`, `VoiceMachine`, `ToolCallEvent`, `ChatConfig`, and more (see [Types](#types)). |
|
|
@@ -92,9 +94,7 @@ const stopVoice = embed.onVoiceStateChange((m) => console.log(m.state));
|
|
|
92
94
|
| `trigger` | `boolean \| TriggerButtonConfig` | `true` | Show the floating pill. `false` = headless. `TriggerButtonConfig` recolors it. |
|
|
93
95
|
| `theme` | `Theme` | — | Position, color mode, and colors. |
|
|
94
96
|
| `getConfig` | `ChatConfigProvider` | — | Async provider of `{ routes, tools? }`. Called on open and on each voice start. |
|
|
95
|
-
| `onToolCall` | `ToolCallHandler` | — | Executes a tool the assistant calls. |
|
|
96
|
-
| `onGraphQLSchemaCall` | `GraphQLSchemaHandler` | — | Handles GraphQL schema tool calls. |
|
|
97
|
-
| `onRESTSchemaCall` | `RESTSchemaHandler` | — | Handles REST/OpenAPI schema tool calls. |
|
|
97
|
+
| `onToolCall` | `ToolCallHandler` | — | Executes a tool the assistant calls. Compose adapters with `createYakToolset`. |
|
|
98
98
|
| `onRedirect` | `(path: string) => void` | `window.location.assign` | Handle navigation requested by the assistant. |
|
|
99
99
|
| `onToolCallComplete` | `(event: ToolCallEvent) => void` | — | Fires after every tool call (use for cache invalidation). |
|
|
100
100
|
| `user` | `UserIdentity` | — | Signed end-user identity for server-side conversation persistence. See [end-user identity](https://docs.yak.io/docs/customization/end-user-identity). |
|
|
@@ -159,7 +159,7 @@ export const { GET, POST } = createYakHandler({
|
|
|
159
159
|
});
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
`routes` and `tools` each accept a single source or an array of sources, so you can compose filesystem routes with adapters like [`@yak-io/trpc`](https://docs.yak.io/docs/tool-adapters/trpc) or [`@yak-io/prismic`](https://docs.yak.io/docs/
|
|
162
|
+
`routes` and `tools` each accept a single source or an array of sources, so you can compose filesystem routes with adapters like [`@yak-io/trpc`](https://docs.yak.io/docs/tool-adapters/trpc) or [`@yak-io/prismic`](https://docs.yak.io/docs/sdks/prismic).
|
|
163
163
|
|
|
164
164
|
## Logging
|
|
165
165
|
|
|
@@ -169,7 +169,7 @@ import { enableYakLogging, disableYakLogging, isYakLoggingEnabled } from "@yak-i
|
|
|
169
169
|
enableYakLogging(); // verbose SDK logs
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
To point the widget at a non-production chat UI (for example one running on `localhost`), pass the `origin` option: `new YakEmbed({ appId, origin: "http://localhost:3001" })`.
|
|
173
173
|
|
|
174
174
|
## Types
|
|
175
175
|
|
|
@@ -195,9 +195,8 @@ import type {
|
|
|
195
195
|
ToolDefinition,
|
|
196
196
|
ToolCallHandler,
|
|
197
197
|
ToolCallEvent,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
SchemaSource,
|
|
198
|
+
ToolAdapter,
|
|
199
|
+
YakToolset,
|
|
201
200
|
} from "@yak-io/javascript";
|
|
202
201
|
```
|
|
203
202
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChatConfig } from "./types/config.js";
|
|
2
2
|
import type { Theme, UserIdentity } from "./types/messaging.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ToolCallEventListener, ToolCallHandler } from "./types/tools.js";
|
|
4
4
|
declare global {
|
|
5
5
|
interface Window {
|
|
6
6
|
__YAK_INTERNAL_DEV__?: boolean;
|
|
@@ -9,6 +9,12 @@ declare global {
|
|
|
9
9
|
}
|
|
10
10
|
export interface YakClientConfig {
|
|
11
11
|
appId: string;
|
|
12
|
+
/**
|
|
13
|
+
* Override the origin the chat widget iframe loads from. Defaults to
|
|
14
|
+
* `https://chat.yak.io`. Most integrators never set this — it exists for
|
|
15
|
+
* non-production environments (e.g. a chat UI running on localhost).
|
|
16
|
+
*/
|
|
17
|
+
origin?: string;
|
|
12
18
|
/**
|
|
13
19
|
* Handler for tool calls from the chat widget.
|
|
14
20
|
* The consuming platform decides how to execute (browser, server fetch, etc.)
|
|
@@ -38,48 +44,6 @@ export interface YakClientConfig {
|
|
|
38
44
|
* ```
|
|
39
45
|
*/
|
|
40
46
|
onToolCall?: ToolCallHandler;
|
|
41
|
-
/**
|
|
42
|
-
* Handler for GraphQL schema-based tool calls.
|
|
43
|
-
* Called when the LLM generates a GraphQL request based on a provided schema.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```ts
|
|
47
|
-
* onGraphQLSchemaCall: async (schemaName, request) => {
|
|
48
|
-
* const res = await fetch("/graphql", {
|
|
49
|
-
* method: "POST",
|
|
50
|
-
* headers: { "Content-Type": "application/json" },
|
|
51
|
-
* body: JSON.stringify({
|
|
52
|
-
* query: request.query,
|
|
53
|
-
* variables: request.variables,
|
|
54
|
-
* }),
|
|
55
|
-
* });
|
|
56
|
-
* return res.json();
|
|
57
|
-
* }
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
onGraphQLSchemaCall?: GraphQLSchemaHandler;
|
|
61
|
-
/**
|
|
62
|
-
* Handler for REST/OpenAPI schema-based tool calls.
|
|
63
|
-
* Called when the LLM generates a REST request based on a provided schema.
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```ts
|
|
67
|
-
* onRESTSchemaCall: async (schemaName, request) => {
|
|
68
|
-
* const url = new URL(`https://api.example.com${request.path}`);
|
|
69
|
-
* if (request.query) {
|
|
70
|
-
* for (const [key, value] of Object.entries(request.query)) {
|
|
71
|
-
* url.searchParams.set(key, value);
|
|
72
|
-
* }
|
|
73
|
-
* }
|
|
74
|
-
* const res = await fetch(url.toString(), {
|
|
75
|
-
* method: request.method,
|
|
76
|
-
* body: request.body ? JSON.stringify(request.body) : undefined,
|
|
77
|
-
* });
|
|
78
|
-
* return res.json();
|
|
79
|
-
* }
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
onRESTSchemaCall?: RESTSchemaHandler;
|
|
83
47
|
theme?: Theme;
|
|
84
48
|
chatConfig?: ChatConfig;
|
|
85
49
|
onRedirect?: (path: string) => void;
|
|
@@ -139,8 +103,8 @@ export declare class YakClient {
|
|
|
139
103
|
constructor(config: YakClientConfig);
|
|
140
104
|
updateConfig(newConfig: Partial<YakClientConfig>): void;
|
|
141
105
|
/**
|
|
142
|
-
* Get the iframe origin URL (base URL for the chat widget)
|
|
143
|
-
*
|
|
106
|
+
* Get the iframe origin URL (base URL for the chat widget). Recomputed on
|
|
107
|
+
* each call so environment-dependent defaults resolve correctly.
|
|
144
108
|
*/
|
|
145
109
|
getIframeOrigin(): string;
|
|
146
110
|
/**
|
|
@@ -198,8 +162,6 @@ export declare class YakClient {
|
|
|
198
162
|
private sendConfigToIframe;
|
|
199
163
|
private sendPageContext;
|
|
200
164
|
private handleToolCall;
|
|
201
|
-
private handleGraphQLSchemaCall;
|
|
202
|
-
private handleRESTSchemaCall;
|
|
203
165
|
private sendToolResultToIframe;
|
|
204
166
|
/**
|
|
205
167
|
* Convert a value to a serializable form by stripping functions and other non-cloneable values.
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAGV,KAAK,EACL,YAAY,EACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAGV,KAAK,EACL,YAAY,EACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AA2D/E,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,uBAAuB,CAAC,EAAE,OAAO,CAAC;KACnC;CACF;AAkBD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,kBAAkB,CAAC,EAAE,qBAAqB,CAAC;IAC3C,iCAAiC;IACjC,OAAO,CAAC,EAAE;QACR,uDAAuD;QACvD,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAChC,CAAC;IACF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAmD;IACtE,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAiC;gBAErC,MAAM,EAAE,eAAe;IAQ5B,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,eAAe,CAAC;IAUvD;;;OAGG;IACI,eAAe,IAAI,MAAM;IAIhC;;;;;;;;;OASG;IACI,WAAW,IAAI,MAAM;IAuB5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;OAEG;IACI,QAAQ,IAAI,MAAM;IAIzB;;OAEG;IACI,QAAQ,IAAI,KAAK,GAAG,SAAS;IAIpC;;;;;;;;;;OAUG;IACI,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAavC;;;OAGG;IACI,SAAS,IAAI,IAAI;IAYxB;;OAEG;IACI,OAAO,IAAI,OAAO;IAIlB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOrC,aAAa,CAAC,MAAM,EAAE,OAAO;IAa7B,KAAK;IAOL,OAAO;IAQd,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,cAAc,CAGpB;IAEF,OAAO,CAAC,aAAa,CAsHnB;IAEF,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,eAAe;YAoBT,cAAc;IA4B5B,OAAO,CAAC,sBAAsB;IAuB9B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,mBAAmB;IAU3B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CAsB1B"}
|
package/dist/client.js
CHANGED
|
@@ -56,29 +56,20 @@ function clearStoredConversationPointer(appId) {
|
|
|
56
56
|
// localStorage can throw in private-browsing modes; silently ignore.
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
+
/** Production chat origin — where the widget iframe loads from by default. */
|
|
60
|
+
const DEFAULT_CHAT_ORIGIN = "https://chat.yak.io";
|
|
59
61
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* - Everything else (including external developers on localhost) -> https://chat.yak.io
|
|
62
|
+
* Resolves the iframe origin when no explicit `origin` is configured. Points at
|
|
63
|
+
* a local chat UI during yak's own local development; production otherwise.
|
|
64
|
+
* Integrators override the result with the `origin` config option.
|
|
64
65
|
*/
|
|
65
|
-
function
|
|
66
|
-
if (typeof window !== "undefined"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// Internal development only: localhost when running on a yak domain locally
|
|
73
|
-
// This is detected by checking if we're on localhost AND the referrer/opener is a yak domain
|
|
74
|
-
// For simplicity, we check if running on localhost with a specific dev flag
|
|
75
|
-
if ((hostname === "localhost" || hostname === "127.0.0.1") &&
|
|
76
|
-
typeof window.__YAK_INTERNAL_DEV__ !== "undefined") {
|
|
77
|
-
return "http://localhost:3001";
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Default to production - external developers on localhost will connect to prod
|
|
81
|
-
return "https://chat.yak.io";
|
|
66
|
+
function getDefaultIframeOrigin() {
|
|
67
|
+
if (typeof window !== "undefined" &&
|
|
68
|
+
(window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") &&
|
|
69
|
+
typeof window.__YAK_INTERNAL_DEV__ !== "undefined") {
|
|
70
|
+
return "http://localhost:3001";
|
|
71
|
+
}
|
|
72
|
+
return DEFAULT_CHAT_ORIGIN;
|
|
82
73
|
}
|
|
83
74
|
export class YakClient {
|
|
84
75
|
config;
|
|
@@ -106,11 +97,11 @@ export class YakClient {
|
|
|
106
97
|
}
|
|
107
98
|
}
|
|
108
99
|
/**
|
|
109
|
-
* Get the iframe origin URL (base URL for the chat widget)
|
|
110
|
-
*
|
|
100
|
+
* Get the iframe origin URL (base URL for the chat widget). Recomputed on
|
|
101
|
+
* each call so environment-dependent defaults resolve correctly.
|
|
111
102
|
*/
|
|
112
103
|
getIframeOrigin() {
|
|
113
|
-
return
|
|
104
|
+
return this.config.origin ?? getDefaultIframeOrigin();
|
|
114
105
|
}
|
|
115
106
|
/**
|
|
116
107
|
* Get the full iframe embed URL for the chatbot
|
|
@@ -336,16 +327,6 @@ export class YakClient {
|
|
|
336
327
|
void this.handleToolCall(id, name, args);
|
|
337
328
|
break;
|
|
338
329
|
}
|
|
339
|
-
case "yak:graphql_schema_call": {
|
|
340
|
-
const { id, schemaName, request } = message.payload;
|
|
341
|
-
void this.handleGraphQLSchemaCall(id, schemaName, request);
|
|
342
|
-
break;
|
|
343
|
-
}
|
|
344
|
-
case "yak:rest_schema_call": {
|
|
345
|
-
const { id, schemaName, request } = message.payload;
|
|
346
|
-
void this.handleRESTSchemaCall(id, schemaName, request);
|
|
347
|
-
break;
|
|
348
|
-
}
|
|
349
330
|
case "yak:redirect": {
|
|
350
331
|
const { path } = message.payload;
|
|
351
332
|
logger.debug("Redirect request received:", path);
|
|
@@ -404,7 +385,6 @@ export class YakClient {
|
|
|
404
385
|
theme: this.config.theme,
|
|
405
386
|
toolManifest: this.config.chatConfig?.tools ?? undefined,
|
|
406
387
|
routeManifest: this.config.chatConfig?.routes ?? undefined,
|
|
407
|
-
schemaSources: this.config.chatConfig?.schemaSources ?? undefined,
|
|
408
388
|
options: this.config.options,
|
|
409
389
|
loggingEnabled,
|
|
410
390
|
user: this.config.user,
|
|
@@ -418,8 +398,6 @@ export class YakClient {
|
|
|
418
398
|
hasToolManifest: Boolean(this.config.chatConfig?.tools),
|
|
419
399
|
toolCount: this.config.chatConfig?.tools?.tools.length ?? 0,
|
|
420
400
|
hasRouteManifest: Boolean(this.config.chatConfig?.routes),
|
|
421
|
-
hasSchemaSources: Boolean(this.config.chatConfig?.schemaSources),
|
|
422
|
-
schemaCount: this.config.chatConfig?.schemaSources?.length ?? 0,
|
|
423
401
|
});
|
|
424
402
|
targetWindow.postMessage(configMessage, targetOrigin);
|
|
425
403
|
}
|
|
@@ -469,40 +447,6 @@ export class YakClient {
|
|
|
469
447
|
this.config.onToolCallComplete?.({ name, args, ok: false, error: errorMessage });
|
|
470
448
|
}
|
|
471
449
|
}
|
|
472
|
-
async handleGraphQLSchemaCall(id, schemaName, request) {
|
|
473
|
-
logger.debug(`GraphQL schema call received: ${schemaName}`, { id, request });
|
|
474
|
-
if (!this.config.onGraphQLSchemaCall) {
|
|
475
|
-
logger.error("GraphQL schema call received but no onGraphQLSchemaCall handler configured");
|
|
476
|
-
this.sendToolResultToIframe(id, false, undefined, "No GraphQL schema handler configured");
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
try {
|
|
480
|
-
const result = await this.config.onGraphQLSchemaCall(schemaName, request);
|
|
481
|
-
logger.debug(`GraphQL schema call succeeded: ${schemaName}`, { id });
|
|
482
|
-
this.sendToolResultToIframe(id, true, result);
|
|
483
|
-
}
|
|
484
|
-
catch (error) {
|
|
485
|
-
logger.error(`GraphQL schema call failed: ${schemaName}`, { id, error });
|
|
486
|
-
this.sendToolResultToIframe(id, false, undefined, this.extractErrorMessage(error));
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
async handleRESTSchemaCall(id, schemaName, request) {
|
|
490
|
-
logger.debug(`REST schema call received: ${schemaName}`, { id, request });
|
|
491
|
-
if (!this.config.onRESTSchemaCall) {
|
|
492
|
-
logger.error("REST schema call received but no onRESTSchemaCall handler configured");
|
|
493
|
-
this.sendToolResultToIframe(id, false, undefined, "No REST schema handler configured");
|
|
494
|
-
return;
|
|
495
|
-
}
|
|
496
|
-
try {
|
|
497
|
-
const result = await this.config.onRESTSchemaCall(schemaName, request);
|
|
498
|
-
logger.debug(`REST schema call succeeded: ${schemaName}`, { id });
|
|
499
|
-
this.sendToolResultToIframe(id, true, result);
|
|
500
|
-
}
|
|
501
|
-
catch (error) {
|
|
502
|
-
logger.error(`REST schema call failed: ${schemaName}`, { id, error });
|
|
503
|
-
this.sendToolResultToIframe(id, false, undefined, this.extractErrorMessage(error));
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
450
|
sendToolResultToIframe(id, ok, result, error) {
|
|
507
451
|
if (!this.iframeWindow)
|
|
508
452
|
return;
|
package/dist/embed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAyB,KAAK,YAAY,EAAmB,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EACL,KAAK,kBAAkB,EACvB,eAAe,EAEhB,MAAM,oBAAoB,CAAC;AAI5B;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAOnD,MAAM,MAAM,mBAAmB,GAAG;IAChC,4CAA4C;IAC5C,WAAW,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE,2CAA2C;IAC3C,UAAU,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvE,CAAC;AAIF,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG;IAC7C,wEAAwE;IACxE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IACxC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC,CAAC;AAIF,MAAM,MAAM,aAAa,GAAG;IAC1B,sCAAsC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AA2QnE;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAGlC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,WAAW,CAAkC;IAGrD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAuC;IAG3D,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,aAAa,CAAmD;IACxE,OAAO,CAAC,aAAa,CAA4C;gBAErD,MAAM,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"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"}
|
package/dist/embed.js
CHANGED
|
@@ -331,11 +331,12 @@ export class YakEmbed {
|
|
|
331
331
|
if (this.mode !== "chat") {
|
|
332
332
|
const voiceConfig = {
|
|
333
333
|
appId: config.appId,
|
|
334
|
+
// A single `origin` on the embed drives both surfaces: chat (iframe)
|
|
335
|
+
// and voice (mint endpoint).
|
|
336
|
+
apiOrigin: config.origin,
|
|
334
337
|
getConfig: config.getConfig,
|
|
335
338
|
chatConfig: config.chatConfig,
|
|
336
339
|
onToolCall: config.onToolCall,
|
|
337
|
-
onGraphQLSchemaCall: config.onGraphQLSchemaCall,
|
|
338
|
-
onRESTSchemaCall: config.onRESTSchemaCall,
|
|
339
340
|
onRedirect: config.onRedirect,
|
|
340
341
|
};
|
|
341
342
|
this.voice = new YakVoiceSession(voiceConfig);
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export { YakClient } from "./client.js";
|
|
|
3
3
|
export type { TriggerButtonConfig, WidgetMode, YakEmbedConfig, YakEmbedState, YakEmbedStateListener, } from "./embed.js";
|
|
4
4
|
export { YakEmbed } from "./embed.js";
|
|
5
5
|
export { disableYakLogging, enableYakLogging, isYakLoggingEnabled, logger } from "./logger.js";
|
|
6
|
+
export type { YakServerAdapterConfig } from "./toolset.js";
|
|
7
|
+
export { createYakServerAdapter, createYakToolset } from "./toolset.js";
|
|
6
8
|
export * from "./types/config.js";
|
|
7
9
|
export * from "./types/messaging.js";
|
|
8
10
|
export * from "./types/routes.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,aAAa,EACb,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,aAAa,EACb,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE/F,YAAY,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACxE,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { YakClient } from "./client.js";
|
|
|
5
5
|
export { YakEmbed } from "./embed.js";
|
|
6
6
|
// Logging utilities
|
|
7
7
|
export { disableYakLogging, enableYakLogging, isYakLoggingEnabled, logger } from "./logger.js";
|
|
8
|
+
export { createYakServerAdapter, createYakToolset } from "./toolset.js";
|
|
8
9
|
export * from "./types/config.js";
|
|
9
10
|
export * from "./types/messaging.js";
|
|
10
11
|
export * from "./types/routes.js";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ToolAdapter, YakToolset } from "./types/tools.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compose client-side {@link ToolAdapter}s into ONE merged tool manifest and ONE
|
|
4
|
+
* routed `onToolCall`. This is the single injection point for "available tools"
|
|
5
|
+
* into the iframe: every adapter — client-side (GraphQL/REST/custom, run by your own
|
|
6
|
+
* `execute` callback) or server-relayed ({@link createYakServerAdapter}) — contributes
|
|
7
|
+
* its tools to the merged manifest and its executor to the routed handler. Because every
|
|
8
|
+
* tool now flows through `onToolCall`, they all surface through `onToolCallComplete` /
|
|
9
|
+
* `useYakToolEvent`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const toolset = createYakToolset([
|
|
14
|
+
* createYakServerAdapter({ endpoint: "/api/yak" }), // tRPC + custom server tools
|
|
15
|
+
* createGraphQLToolAdapter({ name: "shop", schema, execute: runShopQuery }),
|
|
16
|
+
* createRESTToolAdapter({ name: "billing", spec, execute: callBillingApi }),
|
|
17
|
+
* ]);
|
|
18
|
+
*
|
|
19
|
+
* <YakProvider
|
|
20
|
+
* getConfig={async () => ({ routes, ...(await toolset.getConfig()) })}
|
|
21
|
+
* onToolCall={toolset.onToolCall}
|
|
22
|
+
* />;
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function createYakToolset(adapters: ToolAdapter[]): YakToolset;
|
|
26
|
+
/** Config for {@link createYakServerAdapter}. */
|
|
27
|
+
export type YakServerAdapterConfig = {
|
|
28
|
+
/**
|
|
29
|
+
* Endpoint mounting `createYakHandler` / `createNextYakHandler`. GET returns the
|
|
30
|
+
* tool manifest; POST `{ name, args }` executes a tool. Default: `"/api/yak"`.
|
|
31
|
+
*/
|
|
32
|
+
endpoint?: string;
|
|
33
|
+
/** Stable id for diagnostics. Default: `"server"`. */
|
|
34
|
+
id?: string;
|
|
35
|
+
/** Extra headers (e.g. auth) applied to both the GET manifest load and POST execution. */
|
|
36
|
+
headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Bridge a server-side yak handler ({@link createYakHandler} /
|
|
40
|
+
* `createNextYakHandler`, e.g. fronting the `@yak-io/trpc` adapter) into a
|
|
41
|
+
* client-side {@link ToolAdapter}, so server-relayed tools merge into the same
|
|
42
|
+
* manifest + `onToolCall` as browser-executed adapters.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createYakServerAdapter(config?: YakServerAdapterConfig): ToolAdapter;
|
|
45
|
+
//# sourceMappingURL=toolset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolset.d.ts","sourceRoot":"","sources":["../src/toolset.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EAIX,UAAU,EACX,MAAM,kBAAkB,CAAC;AAO1B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,UAAU,CA4DpE;AAED,iDAAiD;AACjD,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0FAA0F;IAC1F,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;CACpE,CAAC;AAgBF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,sBAA2B,GAAG,WAAW,CA8BvF"}
|
package/dist/toolset.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { logger } from "./logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compose client-side {@link ToolAdapter}s into ONE merged tool manifest and ONE
|
|
4
|
+
* routed `onToolCall`. This is the single injection point for "available tools"
|
|
5
|
+
* into the iframe: every adapter — client-side (GraphQL/REST/custom, run by your own
|
|
6
|
+
* `execute` callback) or server-relayed ({@link createYakServerAdapter}) — contributes
|
|
7
|
+
* its tools to the merged manifest and its executor to the routed handler. Because every
|
|
8
|
+
* tool now flows through `onToolCall`, they all surface through `onToolCallComplete` /
|
|
9
|
+
* `useYakToolEvent`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const toolset = createYakToolset([
|
|
14
|
+
* createYakServerAdapter({ endpoint: "/api/yak" }), // tRPC + custom server tools
|
|
15
|
+
* createGraphQLToolAdapter({ name: "shop", schema, execute: runShopQuery }),
|
|
16
|
+
* createRESTToolAdapter({ name: "billing", spec, execute: callBillingApi }),
|
|
17
|
+
* ]);
|
|
18
|
+
*
|
|
19
|
+
* <YakProvider
|
|
20
|
+
* getConfig={async () => ({ routes, ...(await toolset.getConfig()) })}
|
|
21
|
+
* onToolCall={toolset.onToolCall}
|
|
22
|
+
* />;
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function createYakToolset(adapters) {
|
|
26
|
+
let cache = null;
|
|
27
|
+
async function resolve(force = false) {
|
|
28
|
+
if (cache && !force)
|
|
29
|
+
return cache;
|
|
30
|
+
cache = await Promise.all(adapters.map(async (adapter) => ({ adapter, tools: await adapter.getTools() })));
|
|
31
|
+
return cache;
|
|
32
|
+
}
|
|
33
|
+
async function getConfig() {
|
|
34
|
+
// Refresh on every config load — tools may depend on page/user.
|
|
35
|
+
const resolved = await resolve(true);
|
|
36
|
+
const tools = [];
|
|
37
|
+
const seen = new Set();
|
|
38
|
+
for (const { adapter, tools: adapterTools } of resolved) {
|
|
39
|
+
for (const tool of adapterTools) {
|
|
40
|
+
if (seen.has(tool.name)) {
|
|
41
|
+
logger.warn(`Duplicate tool name "${tool.name}"; keeping the first and ignoring the one from adapter "${adapter.id ?? "unknown"}".`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
seen.add(tool.name);
|
|
45
|
+
tools.push(tool);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
tools: {
|
|
50
|
+
tools,
|
|
51
|
+
sources: resolved.map(({ adapter, tools: adapterTools }, index) => ({
|
|
52
|
+
id: adapter.id ?? `adapter-${index}`,
|
|
53
|
+
count: adapterTools.length,
|
|
54
|
+
})),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const onToolCall = async (name, args) => {
|
|
59
|
+
// Fast path: explicit ownership predicates need no resolution.
|
|
60
|
+
for (const adapter of adapters) {
|
|
61
|
+
if (adapter.ownsTool?.(name)) {
|
|
62
|
+
return adapter.execute(name, args);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Otherwise route by the adapter's resolved tool names.
|
|
66
|
+
const resolved = await resolve();
|
|
67
|
+
for (const { adapter, tools } of resolved) {
|
|
68
|
+
if (adapter.ownsTool)
|
|
69
|
+
continue; // already consulted above
|
|
70
|
+
if (tools.some((tool) => tool.name === name)) {
|
|
71
|
+
return adapter.execute(name, args);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
75
|
+
};
|
|
76
|
+
return { getConfig, onToolCall };
|
|
77
|
+
}
|
|
78
|
+
async function buildHeaders(source, base) {
|
|
79
|
+
const headers = new Headers(base);
|
|
80
|
+
const resolved = typeof source === "function" ? await source() : source;
|
|
81
|
+
if (resolved) {
|
|
82
|
+
for (const [key, value] of new Headers(resolved)) {
|
|
83
|
+
headers.set(key, value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return headers;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Bridge a server-side yak handler ({@link createYakHandler} /
|
|
90
|
+
* `createNextYakHandler`, e.g. fronting the `@yak-io/trpc` adapter) into a
|
|
91
|
+
* client-side {@link ToolAdapter}, so server-relayed tools merge into the same
|
|
92
|
+
* manifest + `onToolCall` as browser-executed adapters.
|
|
93
|
+
*/
|
|
94
|
+
export function createYakServerAdapter(config = {}) {
|
|
95
|
+
const endpoint = config.endpoint ?? "/api/yak";
|
|
96
|
+
return {
|
|
97
|
+
id: config.id ?? "server",
|
|
98
|
+
getTools: async () => {
|
|
99
|
+
const res = await fetch(endpoint, { headers: await buildHeaders(config.headers) });
|
|
100
|
+
if (!res.ok) {
|
|
101
|
+
throw new Error(`Failed to load tools from ${endpoint} (${res.status})`);
|
|
102
|
+
}
|
|
103
|
+
const chatConfig = (await res.json());
|
|
104
|
+
return chatConfig.tools?.tools ?? [];
|
|
105
|
+
},
|
|
106
|
+
execute: async (name, args) => {
|
|
107
|
+
const res = await fetch(endpoint, {
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: await buildHeaders(config.headers, { "Content-Type": "application/json" }),
|
|
110
|
+
body: JSON.stringify({ name, args }),
|
|
111
|
+
});
|
|
112
|
+
const data = (await res.json().catch(() => ({})));
|
|
113
|
+
if (!res.ok || !data.ok) {
|
|
114
|
+
throw new Error(data.error ?? `Tool "${name}" failed (${res.status})`);
|
|
115
|
+
}
|
|
116
|
+
return data.result;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import type { RouteManifest } from "./routes.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ToolManifest } from "./tools.js";
|
|
3
3
|
/**
|
|
4
|
-
* Combined configuration for the chatbot including routes
|
|
4
|
+
* Combined configuration for the chatbot including routes and tools.
|
|
5
5
|
*/
|
|
6
6
|
export type ChatConfig = {
|
|
7
7
|
/** Route manifest */
|
|
8
8
|
routes: RouteManifest;
|
|
9
|
-
/** Optional tool manifest (tRPC, GraphQL, etc.) */
|
|
9
|
+
/** Optional tool manifest (tRPC, GraphQL, REST, custom, etc.) */
|
|
10
10
|
tools?: ToolManifest;
|
|
11
|
-
/** Optional schema sources (GraphQL SDL, OpenAPI specs) passed as context to the LLM */
|
|
12
|
-
schemaSources?: SchemaSource[];
|
|
13
11
|
};
|
|
14
12
|
/**
|
|
15
13
|
* Function that provides the chat configuration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,qBAAqB;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,iEAAiE;IACjE,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EmbedProtocolVersion } from "../version.js";
|
|
2
2
|
import type { RouteManifest } from "./routes.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ToolManifest } from "./tools.js";
|
|
4
4
|
/**
|
|
5
5
|
* Color values for a single mode (light or dark).
|
|
6
6
|
* Applied as CSS variables within the chat UI.
|
|
@@ -88,8 +88,6 @@ export type IframeMessageFromHost = {
|
|
|
88
88
|
theme?: Theme;
|
|
89
89
|
toolManifest?: ToolManifest;
|
|
90
90
|
routeManifest?: RouteManifest;
|
|
91
|
-
/** Schema sources passed as context to the LLM */
|
|
92
|
-
schemaSources?: SchemaSource[];
|
|
93
91
|
/** Chat configuration options */
|
|
94
92
|
options?: ChatOptions;
|
|
95
93
|
/** Logging enabled flag from host (for cross-origin sync) */
|
|
@@ -159,20 +157,6 @@ export type IframeMessageToHost = {
|
|
|
159
157
|
name: string;
|
|
160
158
|
args: unknown;
|
|
161
159
|
};
|
|
162
|
-
} | {
|
|
163
|
-
type: "yak:graphql_schema_call";
|
|
164
|
-
payload: {
|
|
165
|
-
id: string;
|
|
166
|
-
schemaName: string;
|
|
167
|
-
request: GraphQLRequest;
|
|
168
|
-
};
|
|
169
|
-
} | {
|
|
170
|
-
type: "yak:rest_schema_call";
|
|
171
|
-
payload: {
|
|
172
|
-
id: string;
|
|
173
|
-
schemaName: string;
|
|
174
|
-
request: RESTRequest;
|
|
175
|
-
};
|
|
176
160
|
} | {
|
|
177
161
|
type: "yak:redirect";
|
|
178
162
|
payload: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/types/messaging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/types/messaging.ts"],"names":[],"mappings":"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"}
|
package/dist/types/tools.d.ts
CHANGED
|
@@ -2,30 +2,6 @@
|
|
|
2
2
|
* Generic JSON Schema type
|
|
3
3
|
*/
|
|
4
4
|
export type JSONSchema = Record<string, unknown>;
|
|
5
|
-
/**
|
|
6
|
-
* GraphQL schema source for providing API context to the LLM
|
|
7
|
-
*/
|
|
8
|
-
export type GraphQLSchemaSource = {
|
|
9
|
-
/** Unique identifier for this schema (used in callbacks) */
|
|
10
|
-
name: string;
|
|
11
|
-
type: "graphql";
|
|
12
|
-
/** The GraphQL schema in SDL format */
|
|
13
|
-
schema: string;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* OpenAPI spec source for providing API context to the LLM
|
|
17
|
-
*/
|
|
18
|
-
export type OpenAPISchemaSource = {
|
|
19
|
-
/** Unique identifier for this schema (used in callbacks) */
|
|
20
|
-
name: string;
|
|
21
|
-
type: "openapi";
|
|
22
|
-
/** OpenAPI spec as JSON object or YAML string */
|
|
23
|
-
spec: Record<string, unknown> | string;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Union type for schema sources
|
|
27
|
-
*/
|
|
28
|
-
export type SchemaSource = GraphQLSchemaSource | OpenAPISchemaSource;
|
|
29
5
|
/**
|
|
30
6
|
* GraphQL request generated by the LLM
|
|
31
7
|
*/
|
|
@@ -50,24 +26,6 @@ export type RESTRequest = {
|
|
|
50
26
|
/** Request body */
|
|
51
27
|
body?: unknown;
|
|
52
28
|
};
|
|
53
|
-
/**
|
|
54
|
-
* Handler for GraphQL schema tool calls.
|
|
55
|
-
* The LLM generates the query based on the schema context.
|
|
56
|
-
*
|
|
57
|
-
* @param schemaName - The name of the schema (from SchemaSource.name)
|
|
58
|
-
* @param request - The GraphQL request generated by the LLM
|
|
59
|
-
* @returns The result of executing the GraphQL operation
|
|
60
|
-
*/
|
|
61
|
-
export type GraphQLSchemaHandler = (schemaName: string, request: GraphQLRequest) => Promise<unknown>;
|
|
62
|
-
/**
|
|
63
|
-
* Handler for OpenAPI/REST schema tool calls.
|
|
64
|
-
* The LLM generates the request based on the schema context.
|
|
65
|
-
*
|
|
66
|
-
* @param schemaName - The name of the schema (from SchemaSource.name)
|
|
67
|
-
* @param request - The REST request generated by the LLM
|
|
68
|
-
* @returns The result of executing the REST request
|
|
69
|
-
*/
|
|
70
|
-
export type RESTSchemaHandler = (schemaName: string, request: RESTRequest) => Promise<unknown>;
|
|
71
29
|
/**
|
|
72
30
|
* Payload for a tool call request from the iframe
|
|
73
31
|
*/
|
|
@@ -155,4 +113,39 @@ export type ToolCallEvent = {
|
|
|
155
113
|
* Called after every tool call completes, regardless of success/failure.
|
|
156
114
|
*/
|
|
157
115
|
export type ToolCallEventListener = (event: ToolCallEvent) => void;
|
|
116
|
+
/**
|
|
117
|
+
* Client-side tool adapter — the browser-side analogue of the server `ToolSource`.
|
|
118
|
+
*
|
|
119
|
+
* An adapter contributes tool definitions to the single merged manifest injected
|
|
120
|
+
* into the iframe AND knows how to execute the tools it owns. Adapters are composed
|
|
121
|
+
* with {@link createYakToolset} into one manifest + one `onToolCall` funnel, so
|
|
122
|
+
* GraphQL, REST, tRPC (server-relayed via {@link createYakServerAdapter}), and custom
|
|
123
|
+
* tools all flow through the same path — and therefore all surface through
|
|
124
|
+
* `onToolCallComplete` / `useYakToolEvent`.
|
|
125
|
+
*/
|
|
126
|
+
export type ToolAdapter = {
|
|
127
|
+
/** Stable id for diagnostics / manifest source attribution. */
|
|
128
|
+
id?: string;
|
|
129
|
+
/** Tool definitions this adapter contributes to the merged manifest. */
|
|
130
|
+
getTools: () => ToolDefinition[] | Promise<ToolDefinition[]>;
|
|
131
|
+
/** Execute a tool this adapter owns. Same signature as {@link ToolCallHandler}. */
|
|
132
|
+
execute: ToolCallHandler;
|
|
133
|
+
/**
|
|
134
|
+
* Whether this adapter owns `name`. When omitted, ownership defaults to
|
|
135
|
+
* membership in the names returned by {@link ToolAdapter.getTools}.
|
|
136
|
+
*/
|
|
137
|
+
ownsTool?: (name: string) => boolean;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* The result of composing {@link ToolAdapter}s with {@link createYakToolset}:
|
|
141
|
+
* a merged tool manifest for `getConfig()` and a single routed `onToolCall`.
|
|
142
|
+
*/
|
|
143
|
+
export type YakToolset = {
|
|
144
|
+
/** Resolved, merged + deduped tool manifest — spread into `getConfig().tools`. */
|
|
145
|
+
getConfig: () => Promise<{
|
|
146
|
+
tools: ToolManifest;
|
|
147
|
+
}>;
|
|
148
|
+
/** Single routed funnel for `YakProvider.onToolCall` / `YakClientConfig.onToolCall`. */
|
|
149
|
+
onToolCall: ToolCallHandler;
|
|
150
|
+
};
|
|
158
151
|
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/types/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/types/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/voice-session.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChatConfig, ChatConfigProvider } from "./types/config.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ToolCallHandler } from "./types/tools.js";
|
|
3
3
|
import { type VoiceMachine } from "./voice-machine.js";
|
|
4
4
|
declare global {
|
|
5
5
|
interface Window {
|
|
@@ -11,8 +11,6 @@ export interface YakVoiceSessionConfig {
|
|
|
11
11
|
appId: string;
|
|
12
12
|
/** Tool call handler. Same shape as `YakClientConfig.onToolCall`. */
|
|
13
13
|
onToolCall?: ToolCallHandler;
|
|
14
|
-
onGraphQLSchemaCall?: GraphQLSchemaHandler;
|
|
15
|
-
onRESTSchemaCall?: RESTSchemaHandler;
|
|
16
14
|
onRedirect?: (path: string) => void;
|
|
17
15
|
/**
|
|
18
16
|
* Static chat config (routes + tools). Sent to the mint endpoint so the LLM
|
|
@@ -26,8 +24,8 @@ export interface YakVoiceSessionConfig {
|
|
|
26
24
|
*/
|
|
27
25
|
getConfig?: ChatConfigProvider;
|
|
28
26
|
/**
|
|
29
|
-
* Override the API origin
|
|
30
|
-
*
|
|
27
|
+
* Override the API origin (where voice sessions are minted). Defaults to
|
|
28
|
+
* `https://chat.yak.io`. Most integrators never set this.
|
|
31
29
|
*/
|
|
32
30
|
apiOrigin?: string;
|
|
33
31
|
}
|
|
@@ -48,18 +46,16 @@ export declare class YakVoiceSession {
|
|
|
48
46
|
private toolNameById;
|
|
49
47
|
constructor(config: YakVoiceSessionConfig);
|
|
50
48
|
/**
|
|
51
|
-
* Resolve the API origin lazily on each call.
|
|
52
|
-
* (
|
|
53
|
-
*
|
|
54
|
-
* bake in the production URL.
|
|
49
|
+
* Resolve the API origin lazily on each call. Environment-dependent defaults
|
|
50
|
+
* (e.g. a local chat UI) may not be ready at construction time, so resolving
|
|
51
|
+
* eagerly would risk baking in the production URL.
|
|
55
52
|
*/
|
|
56
53
|
private get apiOrigin();
|
|
57
54
|
/** Update mutable config fields (handlers, getConfig). */
|
|
58
55
|
updateConfig(patch: Partial<YakVoiceSessionConfig>): void;
|
|
59
56
|
getState(): VoiceMachine;
|
|
60
57
|
/**
|
|
61
|
-
* The current API origin (`chat.yak.io
|
|
62
|
-
* `http://localhost:3001` when `__YAK_INTERNAL_DEV__` is set). Useful for
|
|
58
|
+
* The current API origin (defaults to `https://chat.yak.io`). Useful for
|
|
63
59
|
* building URLs to static assets like the brand logo.
|
|
64
60
|
*/
|
|
65
61
|
getApiOrigin(): string;
|
|
@@ -85,9 +81,11 @@ export declare class YakVoiceSession {
|
|
|
85
81
|
private execMcpTool;
|
|
86
82
|
private mintToken;
|
|
87
83
|
/**
|
|
88
|
-
* Decorate the host's tool manifest
|
|
89
|
-
*
|
|
90
|
-
*
|
|
84
|
+
* Decorate the host's tool manifest with hashed ids and populate
|
|
85
|
+
* `this.toolNameById` for reverse lookup. Mirrors the decoration the chat-ui
|
|
86
|
+
* iframe applies before sending tools to `/api/chat`. GraphQL/REST tools are
|
|
87
|
+
* ordinary manifest entries here (contributed by their adapters), so no
|
|
88
|
+
* special-casing is needed.
|
|
91
89
|
*/
|
|
92
90
|
private buildDecoratedManifest;
|
|
93
91
|
private exchangeSdp;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voice-session.d.ts","sourceRoot":"","sources":["../src/voice-session.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"voice-session.d.ts","sourceRoot":"","sources":["../src/voice-session.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAKL,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAChC;CACF;AAiBD,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,eAAe,CAA6B;IACpD,6EAA6E;IAC7E,OAAO,CAAC,KAAK,CAAkC;IAC/C;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAA6B;gBAErC,MAAM,EAAE,qBAAqB;IAKzC;;;;OAIG;IACH,OAAO,KAAK,SAAS,GAEpB;IAED,0DAA0D;IACnD,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,IAAI;IAIzD,QAAQ,IAAI,YAAY;IAI/B;;;OAGG;IACI,YAAY,IAAI,MAAM;IAItB,aAAa,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI;IAO9D;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwJnC,oDAAoD;IACvC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMlC,2FAA2F;IACpF,OAAO,IAAI,IAAI;IAWtB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,mBAAmB;YAeb,aAAa;IA8B3B;;;;OAIG;YACW,WAAW;YAwBX,SAAS;IAsBvB;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;YAchB,WAAW;IAmBzB,OAAO,CAAC,kBAAkB;YAWZ,gBAAgB;YA2BhB,QAAQ;YAuCR,QAAQ;IAMtB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,cAAc;CAevB"}
|
package/dist/voice-session.js
CHANGED
|
@@ -4,18 +4,18 @@ import { generateToolId } from "./tool-name.js";
|
|
|
4
4
|
import { handleRealtimeMessage, INITIAL_VOICE_MACHINE, voiceReducer, } from "./voice-machine.js";
|
|
5
5
|
const DEFAULT_REALTIME_MODEL = "gpt-realtime";
|
|
6
6
|
const REALTIME_CALLS_URL = "https://api.openai.com/v1/realtime/calls";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
const DEFAULT_API_ORIGIN = "https://chat.yak.io";
|
|
8
|
+
/**
|
|
9
|
+
* Resolves the API origin when no explicit `apiOrigin` is configured. Points at
|
|
10
|
+
* a local chat UI during yak's own local development; production otherwise.
|
|
11
|
+
*/
|
|
12
|
+
function getDefaultApiOrigin() {
|
|
13
|
+
if (typeof window !== "undefined" &&
|
|
14
|
+
(window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") &&
|
|
15
|
+
typeof window.__YAK_INTERNAL_DEV__ !== "undefined") {
|
|
16
|
+
return "http://localhost:3001";
|
|
17
17
|
}
|
|
18
|
-
return
|
|
18
|
+
return DEFAULT_API_ORIGIN;
|
|
19
19
|
}
|
|
20
20
|
const EMPTY_RESOURCES = {
|
|
21
21
|
pc: null,
|
|
@@ -56,13 +56,12 @@ export class YakVoiceSession {
|
|
|
56
56
|
this.attachPageHide();
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Resolve the API origin lazily on each call.
|
|
60
|
-
* (
|
|
61
|
-
*
|
|
62
|
-
* bake in the production URL.
|
|
59
|
+
* Resolve the API origin lazily on each call. Environment-dependent defaults
|
|
60
|
+
* (e.g. a local chat UI) may not be ready at construction time, so resolving
|
|
61
|
+
* eagerly would risk baking in the production URL.
|
|
63
62
|
*/
|
|
64
63
|
get apiOrigin() {
|
|
65
|
-
return this.config.apiOrigin ??
|
|
64
|
+
return this.config.apiOrigin ?? getDefaultApiOrigin();
|
|
66
65
|
}
|
|
67
66
|
/** Update mutable config fields (handlers, getConfig). */
|
|
68
67
|
updateConfig(patch) {
|
|
@@ -72,8 +71,7 @@ export class YakVoiceSession {
|
|
|
72
71
|
return this.machine;
|
|
73
72
|
}
|
|
74
73
|
/**
|
|
75
|
-
* The current API origin (`chat.yak.io
|
|
76
|
-
* `http://localhost:3001` when `__YAK_INTERNAL_DEV__` is set). Useful for
|
|
74
|
+
* The current API origin (defaults to `https://chat.yak.io`). Useful for
|
|
77
75
|
* building URLs to static assets like the brand logo.
|
|
78
76
|
*/
|
|
79
77
|
getApiOrigin() {
|
|
@@ -102,7 +100,6 @@ export class YakVoiceSession {
|
|
|
102
100
|
logger.debug("Voice: getConfig() resolved", {
|
|
103
101
|
toolCount: chatConfig?.tools?.tools.length ?? 0,
|
|
104
102
|
routeCount: chatConfig?.routes?.routes.length ?? 0,
|
|
105
|
-
hasSchemas: !!chatConfig?.schemaSources?.length,
|
|
106
103
|
});
|
|
107
104
|
}
|
|
108
105
|
catch (err) {
|
|
@@ -113,7 +110,6 @@ export class YakVoiceSession {
|
|
|
113
110
|
logger.debug("Voice: using static chatConfig", {
|
|
114
111
|
toolCount: chatConfig.tools?.tools.length ?? 0,
|
|
115
112
|
routeCount: chatConfig.routes?.routes.length ?? 0,
|
|
116
|
-
hasSchemas: !!chatConfig.schemaSources?.length,
|
|
117
113
|
});
|
|
118
114
|
}
|
|
119
115
|
else {
|
|
@@ -324,14 +320,6 @@ export class YakVoiceSession {
|
|
|
324
320
|
}
|
|
325
321
|
return { success: true, redirected: true, path };
|
|
326
322
|
}
|
|
327
|
-
if (name.startsWith("graphql_") && this.config.onGraphQLSchemaCall) {
|
|
328
|
-
const schemaName = name.slice("graphql_".length);
|
|
329
|
-
return await this.config.onGraphQLSchemaCall(schemaName, args);
|
|
330
|
-
}
|
|
331
|
-
if (name.startsWith("rest_") && this.config.onRESTSchemaCall) {
|
|
332
|
-
const schemaName = name.slice("rest_".length);
|
|
333
|
-
return await this.config.onRESTSchemaCall(schemaName, args);
|
|
334
|
-
}
|
|
335
323
|
if (this.config.onToolCall) {
|
|
336
324
|
return await this.config.onToolCall(name, args);
|
|
337
325
|
}
|
|
@@ -375,7 +363,6 @@ export class YakVoiceSession {
|
|
|
375
363
|
pageContext,
|
|
376
364
|
toolManifest: decoratedManifest,
|
|
377
365
|
routeManifest: chatConfig?.routes,
|
|
378
|
-
schemaSources: chatConfig?.schemaSources,
|
|
379
366
|
}),
|
|
380
367
|
});
|
|
381
368
|
if (!res.ok) {
|
|
@@ -385,9 +372,11 @@ export class YakVoiceSession {
|
|
|
385
372
|
return (await res.json());
|
|
386
373
|
}
|
|
387
374
|
/**
|
|
388
|
-
* Decorate the host's tool manifest
|
|
389
|
-
*
|
|
390
|
-
*
|
|
375
|
+
* Decorate the host's tool manifest with hashed ids and populate
|
|
376
|
+
* `this.toolNameById` for reverse lookup. Mirrors the decoration the chat-ui
|
|
377
|
+
* iframe applies before sending tools to `/api/chat`. GraphQL/REST tools are
|
|
378
|
+
* ordinary manifest entries here (contributed by their adapters), so no
|
|
379
|
+
* special-casing is needed.
|
|
391
380
|
*/
|
|
392
381
|
buildDecoratedManifest(chatConfig) {
|
|
393
382
|
this.toolNameById.clear();
|
|
@@ -396,19 +385,7 @@ export class YakVoiceSession {
|
|
|
396
385
|
this.toolNameById.set(id, t.name);
|
|
397
386
|
return { ...t, id };
|
|
398
387
|
});
|
|
399
|
-
|
|
400
|
-
const name = source.type === "graphql" ? `graphql_${source.name}` : `rest_${source.name}`;
|
|
401
|
-
const id = generateToolId(name);
|
|
402
|
-
this.toolNameById.set(id, name);
|
|
403
|
-
return {
|
|
404
|
-
id,
|
|
405
|
-
name,
|
|
406
|
-
description: source.type === "graphql"
|
|
407
|
-
? `Execute GraphQL operations against ${source.name}`
|
|
408
|
-
: `Make REST API calls to ${source.name}`,
|
|
409
|
-
};
|
|
410
|
-
});
|
|
411
|
-
return { tools: [...decoratedHostTools, ...decoratedSchemaTools] };
|
|
388
|
+
return { tools: decoratedHostTools };
|
|
412
389
|
}
|
|
413
390
|
async exchangeSdp(offer, clientSecret) {
|
|
414
391
|
const sdpResponse = await fetch(`${REALTIME_CALLS_URL}?model=${DEFAULT_REALTIME_MODEL}`, {
|