@yak-io/vue 0.3.0 β 0.4.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 +94 -67
- package/dist/composables.d.ts +15 -0
- package/dist/composables.d.ts.map +1 -1
- package/dist/composables.js +5 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
# @yak-io/vue
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> π **Full documentation:** https://docs.yak.io/docs/sdks/vue
|
|
4
|
+
>
|
|
5
|
+
> π€ **For LLMs / AI agents:** https://docs.yak.io/llms.txt
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
Vue 3 SDK for [Yak](https://docs.yak.io) β an embeddable AI assistant (text chat **and** push-to-talk voice) for web apps. Call `createYakProvider` once in your root component; reactive state is exposed as Vue refs and shared with descendants via `provide`/`inject`.
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
pnpm add @yak-io/vue
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## Exports
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
| Export | Kind | Purpose |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `createYakProvider(options)` | fn | Initialize the widget in your root component. Returns a `YakApi`. Auto-mounts/unmounts. |
|
|
18
|
+
| `useYak()` | fn | Inject the `YakApi` in any descendant component. |
|
|
19
|
+
| `useYakToolEvent(handler)` | fn | Run a callback after each tool call (auto-unsubscribes on unmount). |
|
|
20
|
+
| `enableYakLogging` / `disableYakLogging` / `isYakLoggingEnabled` | fn | Toggle verbose SDK logging. |
|
|
21
|
+
| Types | β | `YakProviderOptions`, `YakApi`, `ToolCallEventHandler`, plus core types from `@yak-io/javascript`. |
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
## Quickstart
|
|
24
|
+
|
|
25
|
+
```vue
|
|
26
|
+
<!-- App.vue -->
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { useRouter } from "vue-router";
|
|
17
29
|
import { createYakProvider } from "@yak-io/vue";
|
|
18
30
|
|
|
31
|
+
const router = useRouter();
|
|
32
|
+
|
|
19
33
|
createYakProvider({
|
|
20
34
|
appId: import.meta.env.VITE_YAK_APP_ID,
|
|
35
|
+
mode: "both", // "chat" | "voice" | "both" β default "chat"
|
|
36
|
+
trigger: true, // show the floating launcher pill
|
|
21
37
|
theme: { position: "bottom-right", colorMode: "system" },
|
|
22
|
-
trigger: { label: "Ask with AI" },
|
|
23
38
|
getConfig: async () => {
|
|
24
39
|
const res = await fetch("/api/yak");
|
|
25
40
|
return res.json();
|
|
@@ -34,100 +49,110 @@ createYakProvider({
|
|
|
34
49
|
if (!data.ok) throw new Error(data.error);
|
|
35
50
|
return data.result;
|
|
36
51
|
},
|
|
37
|
-
onRedirect: (path) =>
|
|
38
|
-
router.push(path);
|
|
39
|
-
},
|
|
52
|
+
onRedirect: (path) => router.push(path),
|
|
40
53
|
});
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<RouterView />
|
|
58
|
+
</template>
|
|
41
59
|
```
|
|
42
60
|
|
|
43
|
-
`createYakProvider`
|
|
61
|
+
`createYakProvider` registers `onMounted`/`onUnmounted` for you β no manual lifecycle needed.
|
|
44
62
|
|
|
45
|
-
|
|
63
|
+
## Programmatic control
|
|
46
64
|
|
|
47
|
-
```
|
|
48
|
-
|
|
65
|
+
```vue
|
|
66
|
+
<script setup lang="ts">
|
|
49
67
|
import { useYak } from "@yak-io/vue";
|
|
50
68
|
|
|
51
|
-
const { open, openWithPrompt, isOpen
|
|
69
|
+
const { open, openWithPrompt, isOpen } = useYak();
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<button @click="open">Open chat</button>
|
|
74
|
+
<button @click="openWithPrompt('How do I get started?')">Get help</button>
|
|
75
|
+
<span v-if="isOpen">Chat is open</span>
|
|
76
|
+
</template>
|
|
52
77
|
```
|
|
53
78
|
|
|
54
|
-
`isOpen
|
|
79
|
+
`isOpen`/`isReady` are `readonly` refs β use them directly in templates.
|
|
80
|
+
|
|
81
|
+
## Voice
|
|
82
|
+
|
|
83
|
+
Set `mode: "voice"` or `mode: "both"`, then drive the session. `voiceStart()` must run from a user gesture (browser mic requirement).
|
|
84
|
+
|
|
85
|
+
```vue
|
|
86
|
+
<script setup lang="ts">
|
|
87
|
+
import { useYak } from "@yak-io/vue";
|
|
88
|
+
|
|
89
|
+
const { voiceToggle, voiceLoading, voiceMachine } = useYak();
|
|
90
|
+
</script>
|
|
55
91
|
|
|
56
|
-
```html
|
|
57
92
|
<template>
|
|
58
|
-
<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<p v-if="!isReady && isOpen">Loadingβ¦</p>
|
|
62
|
-
</div>
|
|
93
|
+
<button @click="voiceToggle" :disabled="voiceLoading">
|
|
94
|
+
{{ voiceMachine.state === "idle" ? "Start voice" : `Stop (${voiceMachine.state})` }}
|
|
95
|
+
</button>
|
|
63
96
|
</template>
|
|
64
97
|
```
|
|
65
98
|
|
|
66
|
-
|
|
99
|
+
## Tool events
|
|
67
100
|
|
|
68
101
|
```ts
|
|
69
102
|
import { useYakToolEvent } from "@yak-io/vue";
|
|
70
103
|
|
|
71
104
|
useYakToolEvent((event) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
105
|
+
// { name, args, ok, result?, error? }
|
|
106
|
+
if (event.ok && event.name.startsWith("tasks.")) refreshTasks();
|
|
75
107
|
});
|
|
76
108
|
```
|
|
77
109
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
## API Reference
|
|
110
|
+
## API reference
|
|
81
111
|
|
|
82
112
|
### `createYakProvider(options)`
|
|
83
113
|
|
|
84
|
-
Call once in your root
|
|
114
|
+
Call once in your root component. Returns a `YakApi` (same object `useYak()` injects).
|
|
85
115
|
|
|
86
|
-
|
|
116
|
+
| Option | Type | Default | Description |
|
|
117
|
+
| --- | --- | --- | --- |
|
|
118
|
+
| `appId` | `string` | β | Your Yak app ID (required). |
|
|
119
|
+
| `mode` | `"chat" \| "voice" \| "both"` | `"chat"` | Which surfaces the widget exposes. |
|
|
120
|
+
| `trigger` | `boolean \| TriggerButtonConfig` | `false` | Show the floating pill. **Set `true`** to display it; `TriggerButtonConfig` recolors it. |
|
|
121
|
+
| `getConfig` | `ChatConfigProvider` | β | Async provider of routes + tools. Called on open / voice start. |
|
|
122
|
+
| `onToolCall` | `ToolCallHandler` | β | Executes a tool the assistant calls. |
|
|
123
|
+
| `onGraphQLSchemaCall` | `GraphQLSchemaHandler` | β | Handles GraphQL schema tool calls. |
|
|
124
|
+
| `onRESTSchemaCall` | `RESTSchemaHandler` | β | Handles REST/OpenAPI schema tool calls. |
|
|
125
|
+
| `theme` | `Theme` | β | Position, color mode, and colors. |
|
|
126
|
+
| `onRedirect` | `(path: string) => void` | `window.location.assign` | Navigation handler. |
|
|
127
|
+
| `disableRestartButton` | `boolean` | `false` | Hide the restart-session button. |
|
|
87
128
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
| Option | Type | Description |
|
|
91
|
-
|--------|------|-------------|
|
|
92
|
-
| `appId` | `string` | Your Yak app ID |
|
|
93
|
-
| `getConfig` | `ChatConfigProvider` | Async function returning routes + tools. Called on first open. |
|
|
94
|
-
| `onToolCall` | `ToolCallHandler` | Handle tool invocations from the assistant |
|
|
95
|
-
| `onGraphQLSchemaCall` | `GraphQLSchemaHandler` | Handle GraphQL schema tool calls |
|
|
96
|
-
| `onRESTSchemaCall` | `RESTSchemaHandler` | Handle REST/OpenAPI schema tool calls |
|
|
97
|
-
| `theme` | `Theme` | Position, color mode, and custom colors |
|
|
98
|
-
| `onRedirect` | `(path: string) => void` | Navigation handler (defaults to `window.location.assign`) |
|
|
99
|
-
| `disableRestartButton` | `boolean` | Hide the restart session button |
|
|
100
|
-
| `trigger` | `boolean \| TriggerButtonConfig` | Built-in trigger button |
|
|
101
|
-
|
|
102
|
-
### `useYak()`
|
|
103
|
-
|
|
104
|
-
Inject the widget API in any descendant component.
|
|
129
|
+
### `YakApi`
|
|
105
130
|
|
|
106
131
|
```ts
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
132
|
+
type YakApi = {
|
|
133
|
+
// chat
|
|
134
|
+
isOpen: DeepReadonly<Ref<boolean>>;
|
|
135
|
+
isReady: DeepReadonly<Ref<boolean>>;
|
|
136
|
+
chatLoading: DeepReadonly<Ref<boolean>>; // isOpen && !isReady
|
|
137
|
+
open: () => void;
|
|
138
|
+
close: () => void;
|
|
139
|
+
openWithPrompt: (prompt: string) => void;
|
|
140
|
+
subscribeToToolEvents: (handler: ToolCallEventHandler) => () => void;
|
|
141
|
+
// voice
|
|
142
|
+
voiceMachine: DeepReadonly<Ref<VoiceMachine>>; // { state, errorMessage? }
|
|
143
|
+
voiceLoading: DeepReadonly<Ref<boolean>>; // state === "connecting"
|
|
144
|
+
voiceStart: () => Promise<void>;
|
|
145
|
+
voiceStop: () => Promise<void>;
|
|
146
|
+
voiceToggle: () => Promise<void>;
|
|
147
|
+
};
|
|
115
148
|
```
|
|
116
149
|
|
|
117
|
-
Throws if called outside a component tree where `createYakProvider` was used.
|
|
118
|
-
|
|
119
|
-
### `useYakToolEvent(handler)`
|
|
120
|
-
|
|
121
|
-
Subscribe to tool call completion events. Unsubscribes automatically on component unmount.
|
|
122
|
-
|
|
123
150
|
## Logging
|
|
124
151
|
|
|
125
152
|
```ts
|
|
126
153
|
import { enableYakLogging, disableYakLogging, isYakLoggingEnabled } from "@yak-io/vue";
|
|
127
154
|
|
|
128
|
-
enableYakLogging();
|
|
129
|
-
disableYakLogging(); // Disable SDK logs
|
|
130
|
-
isYakLoggingEnabled(); // β boolean
|
|
155
|
+
enableYakLogging(); // verbose SDK logs
|
|
131
156
|
```
|
|
132
157
|
|
|
133
158
|
## Types
|
|
@@ -141,11 +166,13 @@ import type {
|
|
|
141
166
|
ToolCallHandler,
|
|
142
167
|
ToolCallEvent,
|
|
143
168
|
Theme,
|
|
144
|
-
|
|
169
|
+
WidgetMode,
|
|
145
170
|
WidgetPosition,
|
|
171
|
+
VoiceState,
|
|
172
|
+
VoiceMachine,
|
|
146
173
|
} from "@yak-io/vue";
|
|
147
174
|
```
|
|
148
175
|
|
|
149
176
|
## License
|
|
150
177
|
|
|
151
|
-
Proprietary β see LICENSE
|
|
178
|
+
Proprietary β see [LICENSE](./LICENSE).
|
package/dist/composables.d.ts
CHANGED
|
@@ -13,16 +13,31 @@ export type YakProviderOptions = {
|
|
|
13
13
|
disableRestartButton?: boolean;
|
|
14
14
|
trigger?: boolean | TriggerButtonConfig;
|
|
15
15
|
};
|
|
16
|
+
/** Reactive handle for controlling the Yak widget β chat + voice β from Vue. */
|
|
16
17
|
export type YakApi = {
|
|
18
|
+
/** Whether the chat panel is currently open. */
|
|
17
19
|
isOpen: DeepReadonly<Ref<boolean>>;
|
|
20
|
+
/** Whether the chat iframe is ready to receive messages. */
|
|
18
21
|
isReady: DeepReadonly<Ref<boolean>>;
|
|
22
|
+
/** Whether the chat is opening but not yet interactive (`isOpen && !isReady`). */
|
|
23
|
+
chatLoading: DeepReadonly<Ref<boolean>>;
|
|
24
|
+
/** Open the chat panel. */
|
|
19
25
|
open: () => void;
|
|
26
|
+
/** Close the chat panel. */
|
|
20
27
|
close: () => void;
|
|
28
|
+
/** Open the chat panel and send a specific prompt. */
|
|
21
29
|
openWithPrompt: (prompt: string) => void;
|
|
30
|
+
/** Subscribe to tool-call completion events; returns an unsubscribe function. */
|
|
22
31
|
subscribeToToolEvents: (handler: ToolCallEventHandler) => () => void;
|
|
32
|
+
/** Current voice state-machine snapshot. `idle` when mode is `chat`. */
|
|
23
33
|
voiceMachine: DeepReadonly<Ref<VoiceMachine>>;
|
|
34
|
+
/** Whether the voice session is establishing its connection (`state === "connecting"`). */
|
|
35
|
+
voiceLoading: DeepReadonly<Ref<boolean>>;
|
|
36
|
+
/** Start a voice session. Must be invoked from a user gesture. */
|
|
24
37
|
voiceStart: () => Promise<void>;
|
|
38
|
+
/** Stop the current voice session. */
|
|
25
39
|
voiceStop: () => Promise<void>;
|
|
40
|
+
/** Toggle voice: start if idle/error, stop if active. */
|
|
26
41
|
voiceToggle: () => Promise<void>;
|
|
27
42
|
};
|
|
28
43
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composables.d.ts","sourceRoot":"","sources":["../src/composables.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAGzB,KAAK,iBAAiB,EACtB,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"composables.d.ts","sourceRoot":"","sources":["../src/composables.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAGzB,KAAK,iBAAiB,EACtB,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,YAAY,EAMjB,KAAK,GAAG,EAGT,MAAM,KAAK,CAAC;AAIb,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAElE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,mBAAmB,CAAC,EAAE,oBAAoB,CAAC;IAC3C,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;CACzC,CAAC;AAEF,gFAAgF;AAChF,MAAM,MAAM,MAAM,GAAG;IAEnB,gDAAgD;IAChD,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACnC,4DAA4D;IAC5D,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,kFAAkF;IAClF,WAAW,EAAE,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACxC,2BAA2B;IAC3B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,sDAAsD;IACtD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,iFAAiF;IACjF,qBAAqB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,MAAM,IAAI,CAAC;IAErE,wEAAwE;IACxE,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9C,2FAA2F;IAC3F,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACzC,kEAAkE;IAClE,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,sCAAsC;IACtC,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,yDAAyD;IACzD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAQF;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAkHrE;AAID;;;;GAIG;AACH,wBAAgB,MAAM,IAAI,MAAM,CAM/B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAUnE"}
|
package/dist/composables.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { INITIAL_VOICE_MACHINE, logger, YakEmbed, } from "@yak-io/javascript";
|
|
2
|
-
import { inject, onMounted, onUnmounted, provide, readonly, ref, } from "vue";
|
|
2
|
+
import { computed, inject, onMounted, onUnmounted, provide, readonly, ref, } from "vue";
|
|
3
3
|
// ββ Injection key βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
4
4
|
const YAK_KEY = Symbol("yak");
|
|
5
5
|
// ββ Provider composable βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -92,9 +92,12 @@ export function createYakProvider(options) {
|
|
|
92
92
|
logger.warn("Voice start failed", err);
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
|
+
const chatLoading = computed(() => isOpen.value && !isReady.value);
|
|
96
|
+
const voiceLoading = computed(() => voiceMachine.value.state === "connecting");
|
|
95
97
|
const api = {
|
|
96
98
|
isOpen: readonly(isOpen),
|
|
97
99
|
isReady: readonly(isReady),
|
|
100
|
+
chatLoading,
|
|
98
101
|
open: () => embed.open(),
|
|
99
102
|
close: () => embed.close(),
|
|
100
103
|
openWithPrompt: (prompt) => embed.openWithPrompt(prompt),
|
|
@@ -105,6 +108,7 @@ export function createYakProvider(options) {
|
|
|
105
108
|
};
|
|
106
109
|
},
|
|
107
110
|
voiceMachine: readonly(voiceMachine),
|
|
111
|
+
voiceLoading,
|
|
108
112
|
voiceStart,
|
|
109
113
|
voiceStop: () => embed.voiceStop(),
|
|
110
114
|
voiceToggle: () => embed.voiceToggle(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yak-io/vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Vue SDK for embedding yak chatbot",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"node": ">=18"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
+
"README.md",
|
|
28
29
|
"dist",
|
|
29
30
|
"LICENSE"
|
|
30
31
|
],
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"./package.json": "./package.json"
|
|
42
43
|
},
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@yak-io/javascript": "0.
|
|
45
|
+
"@yak-io/javascript": "0.9.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
48
|
"vue": "^3.3.0"
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"vue": "^3.5.34",
|
|
53
54
|
"@repo/typescript-config": "0.0.0"
|
|
54
55
|
},
|
|
56
|
+
"homepage": "https://docs.yak.io/docs/sdks/vue",
|
|
55
57
|
"scripts": {
|
|
56
58
|
"build": "tsc",
|
|
57
59
|
"check-types": "tsc --noEmit",
|