@aparte/vue 0.24.0 → 0.25.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 +4 -0
- package/dist/components/AparteChat.vue.d.ts.map +1 -1
- package/dist/components/AparteSegmentUI.vue.d.ts +23 -0
- package/dist/components/AparteSegmentUI.vue.d.ts.map +1 -0
- package/dist/components/AparteToolUI.vue.d.ts +25 -0
- package/dist/components/AparteToolUI.vue.d.ts.map +1 -0
- package/dist/composables/useMountedViews.d.ts +20 -0
- package/dist/composables/useMountedViews.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +117 -12
- package/dist/index.js.map +1 -1
- package/dist/is-aparte-element.d.ts +11 -0
- package/dist/is-aparte-element.d.ts.map +1 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -4,6 +4,10 @@ The **Vue AI chat component** of [aparté](https://github.com/apartejs/aparte)
|
|
|
4
4
|
`<AparteChat>` (Vue 3.5+) plus composables (`useAparteChat`, `useAparteClient`, `useConversationManager`) over the
|
|
5
5
|
framework-agnostic web components in `@aparte/core`.
|
|
6
6
|
|
|
7
|
+
Tested in CI with Vue 3.5, and in a Nuxt 3 page rendered on the server and hydrated with no
|
|
8
|
+
mismatch. `<AparteToolUI name="…" v-slot="{ tool }">` draws a tool call with your own component,
|
|
9
|
+
with what your app provides.
|
|
10
|
+
|
|
7
11
|
```bash
|
|
8
12
|
npm install @aparte/vue @aparte/core vue
|
|
9
13
|
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AparteChat.vue.d.ts","sourceRoot":"","sources":["../../src/components/AparteChat.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AparteChat.vue.d.ts","sourceRoot":"","sources":["../../src/components/AparteChat.vue"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AparteConfig, AparteSegmentBase } from '@aparte/core';
|
|
2
|
+
type AnySegment = AparteSegmentBase & Record<string, unknown>;
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
/** The segment `type` this draws. */
|
|
5
|
+
type: string;
|
|
6
|
+
/** The config to declare it on. Defaults to the global one. */
|
|
7
|
+
config?: AparteConfig;
|
|
8
|
+
};
|
|
9
|
+
type __VLS_Slots = {
|
|
10
|
+
/** What to draw for one segment, handed its latest state. */
|
|
11
|
+
default(props: {
|
|
12
|
+
segment: AnySegment;
|
|
13
|
+
}): unknown;
|
|
14
|
+
};
|
|
15
|
+
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
17
|
+
export default _default;
|
|
18
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
19
|
+
new (): {
|
|
20
|
+
$slots: S;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=AparteSegmentUI.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AparteSegmentUI.vue.d.ts","sourceRoot":"","sources":["../../src/components/AparteSegmentUI.vue"],"names":[],"mappings":"AA6DA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGpE,KAAK,UAAU,GAAG,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9D,KAAK,WAAW,GAAG;IACf,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,CAAC,EAAE,YAAY,CAAC;CACzB,CAAC;AAGF,KAAK,WAAW,GAAG;IACf,6DAA6D;IAC7D,OAAO,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC;CACpD,CAAC;AA4DF,QAAA,MAAM,eAAe,kSAMnB,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAQ1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AparteConfig, AparteToolCallView, AparteToolMatcher } from '@aparte/core';
|
|
2
|
+
declare const _default: <I = unknown, R = unknown>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
3
|
+
props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & {
|
|
4
|
+
/** The tool this draws: a name, a `RegExp`, or `'*'` for every tool. */
|
|
5
|
+
name: AparteToolMatcher;
|
|
6
|
+
/** The config to declare it on. Defaults to the global one. */
|
|
7
|
+
config?: AparteConfig;
|
|
8
|
+
} & Partial<{}>> & import("vue").PublicProps;
|
|
9
|
+
expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
|
|
10
|
+
attrs: any;
|
|
11
|
+
slots: {
|
|
12
|
+
/** What to draw for one call: its id, name, input, status, result and the rest. */
|
|
13
|
+
default(props: {
|
|
14
|
+
tool: AparteToolCallView<I, R>;
|
|
15
|
+
}): unknown;
|
|
16
|
+
};
|
|
17
|
+
emit: {};
|
|
18
|
+
}>) => import("vue").VNode & {
|
|
19
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
20
|
+
};
|
|
21
|
+
export default _default;
|
|
22
|
+
type __VLS_PrettifyLocal<T> = {
|
|
23
|
+
[K in keyof T]: T[K];
|
|
24
|
+
} & {};
|
|
25
|
+
//# sourceMappingURL=AparteToolUI.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AparteToolUI.vue.d.ts","sourceRoot":"","sources":["../../src/components/AparteToolUI.vue"],"names":[],"mappings":"AA6DA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;yBAGvE,CAAC,YAAY,CAAC,yBACjB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,cAClD,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,iBAC5F,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;WA4E1D,mBAAmB,CAAC;QAzExB,wEAAwE;cAClE,iBAAiB;QACvB,+DAA+D;iBACtD,YAAY;QAsEwC,OAAO,IAAsB,CAAC,4BAA2B;oBACzG,OAAO,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,IAAI;WAClD,GAAG;;QAnEP,mFAAmF;uBACpE;YAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;SAAE,GAAG,OAAO;;UAoExD,EAAE;OAGG,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,WAAW,CAAC,CAAA;CAAE;AAtFzE,wBAsF4E;AAC5E,KAAK,mBAAmB,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ShallowRef, type WatchSource } from 'vue';
|
|
2
|
+
import type { AparteMountedView } from '@aparte/core';
|
|
3
|
+
/** One element core handed a declaration: where to teleport, what to draw, and a stable key. */
|
|
4
|
+
export interface MountedEntry<V> {
|
|
5
|
+
host: HTMLElement;
|
|
6
|
+
view: V;
|
|
7
|
+
key: number;
|
|
8
|
+
}
|
|
9
|
+
type Mount<V> = (host: HTMLElement, view: V) => AparteMountedView<V>;
|
|
10
|
+
/**
|
|
11
|
+
* The elements core hands one `<AparteToolUI>` / `<AparteSegmentUI>`, as a list the template
|
|
12
|
+
* teleports into.
|
|
13
|
+
*
|
|
14
|
+
* `register` is called in the browser only (`onMounted` never runs in a server render), again
|
|
15
|
+
* whenever one of `sources` changes, and its restore function on unmount — so a declaration lives
|
|
16
|
+
* exactly as long as the component, and a server render declares nothing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useMountedViews<V>(sources: WatchSource<unknown>[], register: (mount: Mount<V>) => () => void): ShallowRef<readonly MountedEntry<V>[]>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=useMountedViews.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMountedViews.d.ts","sourceRoot":"","sources":["../../src/composables/useMountedViews.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiD,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,gGAAgG;AAChG,MAAM,WAAW,YAAY,CAAC,CAAC;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,CAAC,CAAC;IACR,GAAG,EAAE,MAAM,CAAC;CACf;AAED,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,KAAK,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAErE;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAG7B,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,EAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,GAC1C,UAAU,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAyBxC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export { useConversationManager } from './composables/useConversationManager.js'
|
|
|
11
11
|
import AparteUi from './components/AparteUi.vue';
|
|
12
12
|
export { AparteUi };
|
|
13
13
|
export type { AparteUiProps, AparteUiHandle } from './types.js';
|
|
14
|
+
import AparteToolUI from './components/AparteToolUI.vue';
|
|
15
|
+
import AparteSegmentUI from './components/AparteSegmentUI.vue';
|
|
16
|
+
export { AparteToolUI, AparteSegmentUI };
|
|
17
|
+
export type { AparteToolCallView } from '@aparte/core';
|
|
18
|
+
export { isAparteElement } from './is-aparte-element.js';
|
|
14
19
|
export type { AparteMessage, AparteSendEventDetail, AparteActionEventDetail, AparteSegment, AparteTextSegment, AparteCodeSegment, AparteThinkingSegment } from './types.js';
|
|
15
20
|
import type { DefineComponent } from 'vue';
|
|
16
21
|
import type { AparteElementAttributes, AparteElementTagName, AparteTemplateAttrs } from '@aparte/core';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,UAAU,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,CAAC;AAGtB,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAK/D,YAAY,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,UAAU,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,CAAC;AAGtB,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAK/D,YAAY,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGhE,OAAO,YAAY,MAAM,+BAA+B,CAAC;AACzD,OAAO,eAAe,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC;AACzC,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,YAAY,EACR,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACxB,MAAM,YAAY,CAAC;AAiBpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEvG,KAAK,iBAAiB,GAAG;KACpB,CAAC,IAAI,oBAAoB,GAAG,eAAe,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC;CAChG,CAAC;AAEF,OAAO,QAAQ,KAAK,CAAC;IACjB,UAAU,gBAAiB,SAAQ,iBAAiB;KAAG;CAC1D"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineComponent, useId, ref, computed, onMounted, toRaw, onBeforeUnmount, watch, nextTick, openBlock, createElementBlock, unref, normalizeClass, createElementVNode, createStaticVNode, createCommentVNode, toDisplayString, renderSlot, Fragment, renderList } from "vue";
|
|
2
|
-
import { aparteGlobalConfig, AparteChatHost, isAwaitingReply, AparteClient, AparteConversationManager, APARTE_DEFAULT_UI_EVENTS, applyElementProps } from "@aparte/core";
|
|
3
|
-
const _hoisted_1 = ["overlay-composer", "data-aparte-empty", "id"];
|
|
1
|
+
import { defineComponent, useId, ref, computed, onMounted, toRaw, onBeforeUnmount, watch, nextTick, openBlock, createElementBlock, unref, normalizeClass, createElementVNode, createStaticVNode, createCommentVNode, toDisplayString, renderSlot, Fragment, renderList, shallowRef, createBlock, Teleport } from "vue";
|
|
2
|
+
import { aparteGlobalConfig, AparteChatHost, isAwaitingReply, releaseDeferredHydration, AparteClient, AparteConversationManager, APARTE_DEFAULT_UI_EVENTS, applyElementProps, defineMountedToolRenderer, defineMountedSegmentRenderer, overrideSegmentRenderer } from "@aparte/core";
|
|
3
|
+
const _hoisted_1 = ["defer-hydration", "overlay-composer", "data-aparte-empty", "id"];
|
|
4
4
|
const _hoisted_2 = ["loading"];
|
|
5
5
|
const _hoisted_3 = {
|
|
6
6
|
key: 0,
|
|
@@ -21,7 +21,7 @@ const _hoisted_10 = { key: 0 };
|
|
|
21
21
|
const _hoisted_11 = { class: "aparte-composer-row" };
|
|
22
22
|
const _hoisted_12 = { key: 0 };
|
|
23
23
|
const _hoisted_13 = { key: 1 };
|
|
24
|
-
const _sfc_main$
|
|
24
|
+
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
25
25
|
__name: "AparteChat",
|
|
26
26
|
props: {
|
|
27
27
|
id: {},
|
|
@@ -46,10 +46,15 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
46
46
|
const emit = __emit;
|
|
47
47
|
const hostId = props.id ?? `aparte-chat-${useId()}`;
|
|
48
48
|
const rootRef = ref();
|
|
49
|
+
const hydrating = ref(true);
|
|
50
|
+
function setRoot(el) {
|
|
51
|
+
if (!(el instanceof HTMLElement)) return;
|
|
52
|
+
rootRef.value = el;
|
|
53
|
+
releaseDeferredHydration(el);
|
|
54
|
+
}
|
|
49
55
|
const viewportRef = ref();
|
|
50
56
|
const composerRef = ref();
|
|
51
57
|
const internalMessages = ref([...props.messages]);
|
|
52
|
-
const emitted = /* @__PURE__ */ new WeakSet();
|
|
53
58
|
const typingActive = ref(props.isTyping);
|
|
54
59
|
let host = null;
|
|
55
60
|
let teardown = null;
|
|
@@ -67,6 +72,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
67
72
|
const loadingText = computed(() => (localeTick.value, (props.config ?? aparteGlobalConfig).t("loadingConversation")));
|
|
68
73
|
const typingLabel = computed(() => (localeTick.value, props.typingText ?? (props.config ?? aparteGlobalConfig).t("typing")));
|
|
69
74
|
onMounted(() => {
|
|
75
|
+
hydrating.value = false;
|
|
70
76
|
unsubscribeLocale = (props.config ? toRaw(props.config) : aparteGlobalConfig).subscribe(() => {
|
|
71
77
|
localeTick.value++;
|
|
72
78
|
});
|
|
@@ -79,7 +85,6 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
79
85
|
internalMessages.value = m;
|
|
80
86
|
},
|
|
81
87
|
onMessagesChange: (m) => {
|
|
82
|
-
emitted.add(m);
|
|
83
88
|
emit("messagesChange", m);
|
|
84
89
|
emit("update:messages", m);
|
|
85
90
|
},
|
|
@@ -123,7 +128,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
123
128
|
});
|
|
124
129
|
watch(() => props.messages, (m) => {
|
|
125
130
|
const raw = toRaw(m);
|
|
126
|
-
|
|
131
|
+
const echo = host?.takeEcho(raw) ?? false;
|
|
132
|
+
if (echo || raw === toRaw(internalMessages.value)) return;
|
|
127
133
|
internalMessages.value = [...m];
|
|
128
134
|
if (m.length === 0) host?.clearRenderCache();
|
|
129
135
|
});
|
|
@@ -182,11 +188,11 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
182
188
|
return openBlock(), createElementBlock("div", {
|
|
183
189
|
class: normalizeClass(["aparte-chat-container", { "aparte-chat-container--auto-center": __props.centerWhenEmpty }]),
|
|
184
190
|
"data-aparte-chat": "",
|
|
191
|
+
"defer-hydration": hydrating.value ? "" : null,
|
|
185
192
|
"overlay-composer": __props.overlayComposer ? "" : null,
|
|
186
193
|
"data-aparte-empty": __props.centerWhenEmpty && internalMessages.value.length === 0 && !waiting.value ? "" : null,
|
|
187
194
|
id: unref(hostId),
|
|
188
|
-
|
|
189
|
-
ref: rootRef
|
|
195
|
+
ref: setRoot
|
|
190
196
|
}, [
|
|
191
197
|
createElementVNode("aparte-chat-viewport", {
|
|
192
198
|
ref_key: "viewportRef",
|
|
@@ -341,7 +347,7 @@ function useConversationManager() {
|
|
|
341
347
|
updateTitle: (id, title) => assert().updateTitle(id, title)
|
|
342
348
|
};
|
|
343
349
|
}
|
|
344
|
-
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
350
|
+
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
345
351
|
__name: "AparteUi",
|
|
346
352
|
props: {
|
|
347
353
|
name: {},
|
|
@@ -403,9 +409,108 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
403
409
|
};
|
|
404
410
|
}
|
|
405
411
|
});
|
|
412
|
+
function useMountedViews(sources, register) {
|
|
413
|
+
const entries = shallowRef([]);
|
|
414
|
+
let serial = 0;
|
|
415
|
+
const mount = (host, view) => {
|
|
416
|
+
const key = ++serial;
|
|
417
|
+
entries.value = [...entries.value, { host, view, key }];
|
|
418
|
+
return {
|
|
419
|
+
update: (next) => {
|
|
420
|
+
entries.value = entries.value.map((e) => e.host === host ? { host, view: next, key: e.key } : e);
|
|
421
|
+
},
|
|
422
|
+
destroy: () => {
|
|
423
|
+
entries.value = entries.value.filter((e) => e.host !== host);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
let restore = null;
|
|
428
|
+
onMounted(() => {
|
|
429
|
+
watch(sources, () => {
|
|
430
|
+
restore?.();
|
|
431
|
+
restore = register(mount);
|
|
432
|
+
}, { immediate: true });
|
|
433
|
+
});
|
|
434
|
+
onBeforeUnmount(() => {
|
|
435
|
+
restore?.();
|
|
436
|
+
restore = null;
|
|
437
|
+
});
|
|
438
|
+
return entries;
|
|
439
|
+
}
|
|
440
|
+
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
441
|
+
__name: "AparteToolUI",
|
|
442
|
+
props: {
|
|
443
|
+
name: {},
|
|
444
|
+
config: {}
|
|
445
|
+
},
|
|
446
|
+
setup(__props) {
|
|
447
|
+
const props = __props;
|
|
448
|
+
const config = () => props.config ? toRaw(props.config) : aparteGlobalConfig;
|
|
449
|
+
const entries = useMountedViews(
|
|
450
|
+
[() => typeof props.name === "string" ? props.name : String(props.name), config],
|
|
451
|
+
(mount) => config().overrideToolRenderer(props.name, defineMountedToolRenderer(mount))
|
|
452
|
+
);
|
|
453
|
+
return (_ctx, _cache) => {
|
|
454
|
+
return openBlock(true), createElementBlock(Fragment, null, renderList(unref(entries), (entry) => {
|
|
455
|
+
return openBlock(), createBlock(Teleport, {
|
|
456
|
+
key: entry.key,
|
|
457
|
+
to: entry.host
|
|
458
|
+
}, [
|
|
459
|
+
renderSlot(_ctx.$slots, "default", {
|
|
460
|
+
tool: entry.view
|
|
461
|
+
})
|
|
462
|
+
], 8, ["to"]);
|
|
463
|
+
}), 128);
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
468
|
+
__name: "AparteSegmentUI",
|
|
469
|
+
props: {
|
|
470
|
+
type: {},
|
|
471
|
+
config: {}
|
|
472
|
+
},
|
|
473
|
+
setup(__props) {
|
|
474
|
+
const props = __props;
|
|
475
|
+
const config = () => props.config ? toRaw(props.config) : void 0;
|
|
476
|
+
const entries = useMountedViews(
|
|
477
|
+
[() => props.type, config],
|
|
478
|
+
(mount) => {
|
|
479
|
+
const renderer = defineMountedSegmentRenderer(props.type, mount);
|
|
480
|
+
const target = config();
|
|
481
|
+
return target ? overrideSegmentRenderer(renderer, target) : overrideSegmentRenderer(renderer);
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
return (_ctx, _cache) => {
|
|
485
|
+
return openBlock(true), createElementBlock(Fragment, null, renderList(unref(entries), (entry) => {
|
|
486
|
+
return openBlock(), createBlock(Teleport, {
|
|
487
|
+
key: entry.key,
|
|
488
|
+
to: entry.host
|
|
489
|
+
}, [
|
|
490
|
+
renderSlot(_ctx.$slots, "default", {
|
|
491
|
+
segment: entry.view
|
|
492
|
+
})
|
|
493
|
+
], 8, ["to"]);
|
|
494
|
+
}), 128);
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
const WRAPPER_COMPONENTS = /* @__PURE__ */ new Set([
|
|
499
|
+
"aparte-ui",
|
|
500
|
+
"aparte-tool-ui",
|
|
501
|
+
"aparte-tool-u-i",
|
|
502
|
+
"aparte-segment-ui",
|
|
503
|
+
"aparte-segment-u-i"
|
|
504
|
+
]);
|
|
505
|
+
function isAparteElement(tag) {
|
|
506
|
+
return tag.startsWith("aparte-") && !WRAPPER_COMPONENTS.has(tag);
|
|
507
|
+
}
|
|
406
508
|
export {
|
|
407
|
-
_sfc_main$
|
|
408
|
-
_sfc_main as
|
|
509
|
+
_sfc_main$3 as AparteChat,
|
|
510
|
+
_sfc_main as AparteSegmentUI,
|
|
511
|
+
_sfc_main$1 as AparteToolUI,
|
|
512
|
+
_sfc_main$2 as AparteUi,
|
|
513
|
+
isAparteElement,
|
|
409
514
|
useAparteChat,
|
|
410
515
|
useAparteClient,
|
|
411
516
|
useConversationManager
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/components/AparteChat.vue","../src/composables/useAparteChat.ts","../src/composables/useAparteClient.ts","../src/composables/useConversationManager.ts","../src/components/AparteUi.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, useId, toRaw } from 'vue';\nimport { AparteChatHost, aparteGlobalConfig, isAwaitingReply, type AparteChatHostBinding, type AparteConfig, type AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteActionEventDetail } from '../types.js';\n\ninterface Props {\n /**\n * The host element's `id`, and therefore the `targetId` every event this chat\n * dispatches carries. Generated when omitted — but it used to be generated and\n * neither accepted nor exposed, which made `AparteClientOptions.scopeToTargetId`\n * unreachable from this component.\n */\n id?: string;\n /** Optional: omit for an uncontrolled chat (defaults to []); use `v-model:messages` to control. */\n messages?: AparteMessage[];\n placeholder?: string;\n disabled?: boolean;\n isTyping?: boolean;\n typingText?: string;\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n submitOnEnter?: boolean;\n /** Freeze viewport spacer recalculation for this many ms after a conv swap. */\n layoutTransitionMs?: number;\n /**\n * Opt in to the \"centered composer when empty\" layout: the composer sits\n * vertically centered with the `empty-state` slot above it while the list is\n * empty, then slides to the bottom on the first message (~0.3s). Off by\n * default — additive (adds the `--auto-center` modifier + a `data-aparte-empty`\n * attribute the shipped `aparte.css` recipe keys off).\n */\n centerWhenEmpty?: boolean;\n /**\n * The conversation is on its way: the viewport draws two skeleton turns, the empty\n * state stays off and the composer is disabled until it lands. The conversation\n * controller sets this itself while it fetches through your adapter's `loadFull()`;\n * the prop is for a wait of your own. Off by default.\n */\n loading?: boolean;\n /** Overlay the composer on the transcript: full-column scroll surface, edge-to-edge scrollbar, floating composer. Read when the viewport mounts. */\n overlayComposer?: boolean;\n /**\n * Add the file picker + chips strip to the default composer shell. **Off by\n * default**, because the capability needs a host that consumes the files: an\n * `AparteClient` inlines them per its `rawFileInject` option, but if you drive\n * your own loop you must read `event.files` on `messageSent` — otherwise the file\n * the user deliberately attached is dropped in silence. No effect when you fill\n * the `composer` slot (drop `<aparte-composer-add-attachment>` and\n * `<aparte-composer-attachments>` in it yourself).\n */\n attachments?: boolean;\n /**\n * Render the `<aparte-elicitation>` presenter inside the host — **on by default**,\n * as it is in `<aparte-chat>`: the built-in approval gate and `requestUserInput()`\n * ask through it, and it renders nothing until something asks. Pass `false` when\n * you mount a presenter of your own (`setElicitationPresenter`) or place the\n * element yourself.\n */\n elicitation?: boolean;\n /** Active conversation id (loads/persists via the registered AparteConversationManager). */\n conversationId?: string | null;\n /**\n * Instance {@link AparteConfig} for this chat. When set, aparté components\n * inside resolve THIS config instead of `aparteGlobalConfig`, so\n * several independently-configured chats can coexist on one page. Omit for the\n * global config. Read once when the host mounts.\n */\n config?: AparteConfig;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n messages: () => [],\n placeholder: 'Type a message...',\n disabled: false,\n isTyping: false,\n typingText: undefined,\n submitOnEnter: true,\n layoutTransitionMs: 0,\n centerWhenEmpty: false,\n loading: false,\n overlayComposer: false,\n attachments: false,\n elicitation: true,\n conversationId: null,\n});\n\nconst emit = defineEmits<{\n /**\n * User submitted a message from the composer. The message is **appended to\n * the thread automatically** (optimistic UI) before this fires — do NOT add\n * it again in the handler (uncontrolled → duplicates; controlled → mirror it\n * into your own `messages`). For side-effects: scroll, analytics, send.\n */\n messageSent: [event: AparteSendEventDetail];\n /** A custom bubble action (registerBubbleAction) was clicked — typed aparte-action. */\n action: [detail: AparteActionEventDetail];\n /** Active path changed (branch nav/edit/retry/streaming) — bind back to `messages`. */\n messagesChange: [messages: AparteMessage[]];\n /** Same payload as `messagesChange`, enabling `v-model:messages`. */\n 'update:messages': [messages: AparteMessage[]];\n messageAppended: [message: AparteMessage];\n /** The typing/\"thinking\" indicator toggled (the host flips it off on the first streamed token). */\n typingChange: [isTyping: boolean];\n conversationCreated: [id: string];\n}>();\n\n// useId() (Vue 3.5+) is SSR-stable — server and client agree, no hydration mismatch.\n// A caller-supplied `id` wins, so `scopeToTargetId` has something to match; the\n// generated one stays SSR-stable for the common case.\nconst hostId = props.id ?? `aparte-chat-${useId()}`;\nconst rootRef = ref<HTMLElement>();\nconst viewportRef = ref<HTMLElement>();\nconst composerRef = ref<HTMLElement>();\nconst internalMessages = ref<AparteMessage[]>([...props.messages]);\n// Every list the host emitted: the prop comes back as one of them, possibly an EARLIER\n// one when the parent lands late, and an echo is not the parent's word (see the watch).\nconst emitted = new WeakSet<AparteMessage[]>();\nconst typingActive = ref(props.isTyping);\n\nlet host: AparteChatHost | null = null;\nlet teardown: (() => void) | null = null;\n\nfunction onSend(e: Event) {\n (viewportRef.value as unknown as { requestSmoothScroll?: () => void })?.requestSmoothScroll?.();\n emit('messageSent', (e as CustomEvent<AparteSendEventDetail>).detail);\n}\n\n// Custom bubble actions bubble to the root as `aparte-action` — surface them typed.\nfunction onAction(e: Event) {\n emit('action', (e as CustomEvent<AparteActionEventDetail>).detail);\n}\n\n// The controller's wait (a conversation fetched through the adapter) OR the consumer's.\nconst hostLoading = ref(false);\nconst waiting = computed(() => props.loading || hostLoading.value);\n// Bumped on every config change: the two strings below are locale text, and a computed does not\n// see the config — a language switch left them in the old language.\nconst localeTick = ref(0);\nlet unsubscribeLocale: (() => void) | null = null;\nconst loadingText = computed(() => (localeTick.value, (props.config ?? aparteGlobalConfig).t('loadingConversation')));\n// The status line's word, from the locale like the rest of the chat, unless the prop says.\nconst typingLabel = computed(() => (localeTick.value, props.typingText ?? (props.config ?? aparteGlobalConfig).t('typing')));\n\nonMounted(() => {\n unsubscribeLocale = (props.config ? toRaw(props.config) : aparteGlobalConfig).subscribe(() => { localeTick.value++; });\n const binding: AparteChatHostBinding = {\n hostId,\n host: rootRef.value as HTMLElement,\n viewport: viewportRef.value ?? null,\n getMessages: () => internalMessages.value,\n setMessages: (m) => { internalMessages.value = m as AparteMessage[]; },\n onMessagesChange: (m) => {\n emitted.add(m as AparteMessage[]);\n emit('messagesChange', m as AparteMessage[]);\n emit('update:messages', m as AparteMessage[]);\n },\n onMessageAppended: (m) => emit('messageAppended', m as AparteMessage),\n onTypingChange: (t) => { typingActive.value = t; emit('typingChange', t); },\n onStreamingChange: () => { /* exposed via isStreaming() */ },\n afterRender: (cb) => { void nextTick(cb); },\n resetComposer: () => (composerRef.value as unknown as { reset?: () => void })?.reset?.(),\n onLoadingChange: (on) => { hostLoading.value = on; },\n };\n host = new AparteChatHost(binding, {\n layoutTransitionMs: props.layoutTransitionMs,\n conversationId: props.conversationId ?? null,\n onConversationCreated: (id) => emit('conversationCreated', id),\n // Unwrap Vue's reactive proxy: the config is a plain class with internal\n // Map registries the host/components must operate on directly, not through a\n // deep reactive proxy (which would wrap those Maps and break lookups).\n config: props.config ? toRaw(props.config) : undefined,\n });\n teardown = host.bind();\n host.syncBubbles();\n composerRef.value?.addEventListener('aparte-send', onSend);\n rootRef.value?.addEventListener('aparte-action', onAction);\n});\n\nonBeforeUnmount(() => {\n unsubscribeLocale?.();\n unsubscribeLocale = null;\n composerRef.value?.removeEventListener('aparte-send', onSend);\n rootRef.value?.removeEventListener('aparte-action', onAction);\n teardown?.();\n teardown = null;\n host = null;\n});\n\n// Parent push → internal list, unless it is the host's own emit coming back, current or\n// stale — applying a stale one rolled the list back under the host's next write. Raw, as\n// a parent's `ref` hands the emitted array back wrapped in a reactive proxy.\nwatch(() => props.messages, (m) => {\n const raw = toRaw(m);\n if (raw === toRaw(internalMessages.value) || emitted.has(raw)) return;\n internalMessages.value = [...m];\n if (m.length === 0) host?.clearRenderCache();\n});\n\n// Reconcile bubbles after the rendered list changes (host queries the DOM).\nwatch(internalMessages, () => { void nextTick(() => host?.syncBubbles()); });\n\nwatch(() => props.isTyping, (t) => { typingActive.value = t; });\nwatch(() => props.conversationId, (id) => { void host?.setConversationId(id ?? null); });\n\n// ── Imperative API (forwards to the host) ──\nconst appendMessage = (m: AparteMessage, o?: { historical?: boolean }) => host?.appendMessage(m, o);\nconst updateMessage = (id: string, u: Partial<AparteMessage>) => host?.updateMessage(id, u);\nconst updateLastMessage = (c: string, o?: { append?: boolean }) => host?.updateLastMessage(c, o);\nconst addSegment = (s: AparteSegment) => host?.addSegment(s);\nconst updateSegment = (id: string, u: Partial<AparteSegment>) => host?.updateSegment(id, u);\nconst removeSegment = (id: string) => host?.removeSegment(id);\nconst appendToSegment = (id: string, c: string) => host?.appendToSegment(id, c);\nconst getMessages = () => host?.getMessages() ?? internalMessages.value;\nconst clearMessages = (options?: { revokeAttachments?: boolean }) => host?.clearMessages(options);\nconst addBranch = (id: string) => host?.addBranch(id) ?? 0;\nconst addSiblingOf = (id: string, m: AparteMessage) => host?.addSiblingOf(id, m) ?? null;\nconst truncateFrom = (id: string) => host?.truncateFrom(id);\nconst truncateResponsesAfter = (id: string) => host?.truncateResponsesAfter(id);\nconst injectTokenStream = (id: string, tokens: AsyncIterable<string>) =>\n host?.streamTokens(id, tokens) ?? Promise.resolve();\nconst stopTokenStream = () => host?.stopTokenStream();\nconst setConversationId = (id: string | null) => host?.setConversationId(id) ?? Promise.resolve();\nconst scrollToBottom = () => (viewportRef.value as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.();\nconst focusInput = () => (composerRef.value as unknown as { focus?: () => void })?.focus?.();\nconst isStreaming = () => host?.isStreaming ?? false;\n\n// `getViewport()` (not a raw `viewport` ref): the same accessor on all four\n// wrappers — Svelte 4 can only expose functions, so the shared name is one.\nconst getViewport = () => viewportRef.value ?? null;\n\n// `satisfies` makes a dropped or mistyped method a compile error — the canonical\n// AparteChatImperativeApi is enforced here, not just aliased for consumers.\ndefineExpose({\n appendMessage, updateMessage, updateLastMessage, addSegment, updateSegment, removeSegment,\n appendToSegment, getMessages, clearMessages, addBranch, addSiblingOf, truncateFrom,\n truncateResponsesAfter, injectTokenStream, stopTokenStream, setConversationId,\n scrollToBottom, focusInput, isStreaming, getViewport,\n} satisfies AparteChatImperativeApi);\n</script>\n\n<template>\n <div\n :class=\"['aparte-chat-container', { 'aparte-chat-container--auto-center': centerWhenEmpty }]\"\n data-aparte-chat\n :overlay-composer=\"overlayComposer ? '' : null\"\n :data-aparte-empty=\"centerWhenEmpty && internalMessages.length === 0 && !waiting ? '' : null\"\n :id=\"hostId\"\n ref=\"rootRef\"\n >\n <aparte-chat-viewport ref=\"viewportRef\" framework-managed=\"\" :loading=\"waiting ? '' : null\">\n <!-- The wait, drawn here because this DOM is Vue's: the kit's skeleton recipe,\n and a line for a screen reader. -->\n <div v-if=\"waiting\" class=\"aparte-viewport-loading\" aria-hidden=\"true\">\n <span class=\"aparte-skeleton aparte-skeleton--rect aparte-viewport-loading__user\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text aparte-viewport-loading__last\"></span>\n </div>\n <span v-if=\"waiting\" class=\"aparte-viewport-loading-status aparte-sr-only\" role=\"status\">{{ loadingText }}</span>\n <!-- Welcome / placeholder shown inside the viewport while there are no\n messages (a real empty-state region). -->\n <slot v-if=\"internalMessages.length === 0 && !waiting\" name=\"empty-state\" />\n <!-- `bubble` scoped slot renders your OWN element per message in place of\n <aparte-chat-bubble>; driven by the reactive list so it streams live. -->\n <template v-for=\"m in internalMessages\" :key=\"m.id\">\n <slot name=\"bubble\" :message=\"m\">\n <aparte-chat-bubble\n :message-id=\"m.id\"\n :data-role=\"m.role\"\n :data-kind=\"m.compaction ? 'compaction' : undefined\"\n :timestamp=\"m.timestamp\"\n :content=\"m.content\"\n :streaming=\"isAwaitingReply(m) ? '' : null\"\n />\n </slot>\n </template>\n <aparte-chat-status :visible=\"typingActive ? '' : null\" :text=\"typingLabel\" />\n </aparte-chat-viewport>\n\n <!-- The presenter for a request to the human (approval gate, ask_user…). Renders\n nothing until something asks; on by default as in <aparte-chat>. -->\n <aparte-elicitation v-if=\"elicitation\"></aparte-elicitation>\n\n <!-- Content above the composer (banner, disclaimer, context chip). -->\n <slot name=\"above-composer\" />\n\n <!-- `.attr` forces attribute-setting, and stays: the attribute IS the state\n core's composer parts read (`getAttribute('placeholder')`, `hasAttribute\n ('disabled')`). Core gained the matching setters in 0.16.12 — before that\n they were getter-only and Vue's default property-set on a custom element\n threw — so this is now a direct write rather than a way around a crash. -->\n <aparte-composer\n ref=\"composerRef\"\n :target=\"hostId\"\n :placeholder.attr=\"placeholder\"\n :disabled.attr=\"disabled || waiting ? '' : null\"\n :submit-on-enter=\"submitOnEnter ? null : 'false'\"\n >\n <!-- Custom composer via the `composer` slot; falls back to the default\n shell (input · send, plus the attachment primitives when `attachments`\n is set). Compose the headless aparte-composer-* primitives freely for a\n skin-specific layout. -->\n <slot name=\"composer\">\n <div class=\"aparte-composer-shell\">\n <aparte-composer-attachments v-if=\"attachments\"></aparte-composer-attachments>\n <div class=\"aparte-composer-row\">\n <aparte-composer-add-attachment v-if=\"attachments\"></aparte-composer-add-attachment>\n <aparte-composer-input></aparte-composer-input>\n <aparte-composer-send></aparte-composer-send>\n </div>\n <!-- The composer's bottom row. ONE slot: placement is the DOM order, and\n `margin-inline-start: auto` pushes a control to the end (a logical\n property, so it reads correctly in RTL). Nothing is rendered at all when\n the slot is unused. -->\n <aparte-composer-toolbar v-if=\"$slots.toolbar\">\n <slot name=\"toolbar\" />\n </aparte-composer-toolbar>\n </div>\n </slot>\n </aparte-composer>\n </div>\n</template>\n","import { ref, type Ref } from 'vue';\nimport type { AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment } from '../types.js';\n\n/**\n * Idiomatic Vue ergonomics for `<AparteChat>`. Owns the `messages` ref and a\n * component template ref so the consumer skips the manual\n * `@messages-change` → `messages` round-trip.\n *\n * @example\n * const chat = useAparteChat();\n * // template:\n * // <AparteChat :ref=\"chat.chatRef\" :messages=\"chat.messages.value\"\n * // @messages-change=\"chat.onMessagesChange\" />\n */\nexport function useAparteChat(initial: AparteMessage[] = []) {\n const messages = ref<AparteMessage[]>([...initial]) as Ref<AparteMessage[]>;\n const chatRef = ref<AparteChatImperativeApi | null>(null);\n const c = () => chatRef.value;\n const onMessagesChange = (m: AparteMessage[]) => { messages.value = m; };\n\n return {\n messages,\n chatRef,\n onMessagesChange,\n appendMessage: (m: AparteMessage, o?: { historical?: boolean }) => c()?.appendMessage(m, o),\n updateMessage: (id: string, u: Partial<AparteMessage>) => c()?.updateMessage(id, u),\n updateLastMessage: (content: string, o?: { append?: boolean }) => c()?.updateLastMessage(content, o),\n addSegment: (s: AparteSegment) => c()?.addSegment(s),\n updateSegment: (id: string, u: Partial<AparteSegment>) => c()?.updateSegment(id, u),\n removeSegment: (id: string) => c()?.removeSegment(id),\n appendToSegment: (id: string, content: string) => c()?.appendToSegment(id, content),\n // The host's list — the authority, and mid-stream a frame ahead of the\n // `messages` ref, which is synced once per paint rather than per token.\n getMessages: (): AparteMessage[] => c()?.getMessages() ?? messages.value,\n clearMessages: (options?: { revokeAttachments?: boolean }) => c()?.clearMessages(options),\n addBranch: (id: string) => c()?.addBranch(id) ?? 0,\n addSiblingOf: (id: string, m: AparteMessage) => c()?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id: string) => c()?.truncateFrom(id),\n truncateResponsesAfter: (id: string) => c()?.truncateResponsesAfter(id),\n injectTokenStream: (id: string, tokens: AsyncIterable<string>) =>\n c()?.injectTokenStream(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => c()?.stopTokenStream(),\n setConversationId: (id: string | null) => c()?.setConversationId(id) ?? Promise.resolve(),\n isStreaming: () => c()?.isStreaming() ?? false,\n scrollToBottom: () => c()?.scrollToBottom(),\n focusInput: () => c()?.focusInput(),\n /** The `<aparte-chat-viewport>` element — same accessor on all four wrappers. */\n getViewport: (): HTMLElement | null => c()?.getViewport() ?? null,\n };\n}\n","import { onMounted, onBeforeUnmount } from 'vue';\nimport { AparteClient, type AparteClientOptions } from '@aparte/core';\n\n/**\n * Mounts an `AparteClient` that bridges `aparte-send` events to the configured AI\n * providers. Starts on mount, stops on unmount. Vue equivalent of Angular's\n * `AparteAiService`.\n */\nexport function useAparteClient(options?: AparteClientOptions) {\n const client = new AparteClient(options ?? {});\n onMounted(() => client.start());\n onBeforeUnmount(() => client.stop());\n return { client, abort: () => client.abort() };\n}\n","import { ref, computed, onBeforeUnmount, type Ref } from 'vue';\nimport {\n aparteGlobalConfig,\n type AparteConfig,\n AparteConversationManager,\n type AparteConversation,\n type AparteStorageAdapter,\n type ConversationManagerOptions,\n} from '@aparte/core';\nimport type { AparteMessage } from '../types.js';\n\n/**\n * Vue-reactive wrapper around the core `AparteConversationManager`. The active\n * conversation is owned by the chat component's controller; switch by binding\n * `conversationId` on `<AparteChat>`. Vue equivalent of Angular's\n * `ConversationManagerService`.\n */\nexport function useConversationManager() {\n let manager: AparteConversationManager | null = null;\n let unsub: (() => void) | null = null;\n\n const conversations = ref<AparteConversation[]>([]) as Ref<AparteConversation[]>;\n const activeId = ref<string | null>(null);\n\n const activeConversations = computed(() =>\n conversations.value.filter((c) => !c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const archivedConversations = computed(() =>\n conversations.value.filter((c) => !!c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const activeConversation = computed(() =>\n activeId.value ? conversations.value.find((c) => c.id === activeId.value) ?? null : null,\n );\n\n onBeforeUnmount(() => unsub?.());\n\n const assert = (): AparteConversationManager => {\n if (!manager) throw new Error('[useConversationManager] Not initialised. Call init(adapter) first.');\n return manager;\n };\n\n /**\n * Initialise with a storage adapter.\n *\n * `config` defaults to the global singleton. Pass the SAME config you gave\n * `<AparteChat config={…}>`: the controller resolves the config governing its\n * host element, so a manager registered on the global is invisible to a chat\n * with its own — persistence silently does nothing while the optimistic UI\n * keeps working.\n */\n const init = async (adapter: AparteStorageAdapter, config: AparteConfig = aparteGlobalConfig, options?: ConversationManagerOptions): Promise<void> => {\n const m = new AparteConversationManager(adapter, options);\n manager = m;\n unsub = m.subscribe((convs) => {\n conversations.value = [...convs];\n activeId.value = m.activeId;\n });\n await m.init();\n activeId.value = m.activeId;\n config.setConversationManager(m);\n };\n\n return {\n conversations,\n activeConversations,\n archivedConversations,\n activeId,\n activeConversation,\n init,\n /** The core manager, once `init` has run (`null` before): for what this does not mirror. Read it as `cm.manager` after `init` — a destructured copy keeps the `null` it had, and it is not reactive. */\n get manager(): AparteConversationManager | null { return manager; },\n createNew: (title?: string) => assert().createNew(title),\n addMessage: (convId: string, message: AparteMessage) => assert().addMessage(convId, message),\n updateMessages: (convId: string, messages: AparteMessage[]) => assert().updateMessages(convId, messages),\n delete: (id: string) => assert().delete(id),\n archive: (id: string) => assert().archive(id),\n unarchive: (id: string) => assert().unarchive(id),\n pin: (id: string) => assert().pin(id),\n unpin: (id: string) => assert().unpin(id),\n updateTitle: (id: string, title: string) => assert().updateTitle(id, title),\n };\n}\n","<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, toRaw } from 'vue';\nimport { applyElementProps, APARTE_DEFAULT_UI_EVENTS } from '@aparte/core';\nimport type { AparteUiHandle } from '../types.js';\n\nconst p = defineProps<{\n /** The custom element tag name (e.g. 'aparte-model-selector'). */\n name: string;\n /** Props to apply. Keys starting with `--` become CSS variables. */\n props?: Record<string, unknown>;\n /**\n * Which custom events to forward through `elementEvent`. Defaults to the\n * interactive aparté surface (APARTE_DEFAULT_UI_EVENTS); pass your own list to listen to\n * other events (e.g. ['aparte-composer-change'] for attachments).\n */\n events?: string[];\n}>();\n\nconst emit = defineEmits<{ elementEvent: [event: CustomEvent] }>();\n\n// A stable key so a fresh inline `:events` array doesn't thrash the element —\n// only a real change to the event names rebinds (mirrors React's evtsKey).\nconst evtsKey = computed(() => (p.events ?? APARTE_DEFAULT_UI_EVENTS).join('|'));\n\nconst hostRef = ref<HTMLElement>();\nlet el: HTMLElement | null = null;\nlet cleanups: Array<() => void> = [];\n\n// Vue passes `toRaw` so objects are unwrapped from the reactive proxy before\n// reaching the plain custom element (a deep proxy breaks Maps/class internals).\nfunction applyProps() {\n if (el) applyElementProps(el, p.props ?? {}, toRaw);\n}\n\nfunction create() {\n if (!hostRef.value) return;\n el = document.createElement(p.name);\n applyProps();\n for (const ev of evtsKey.value.split('|').filter(Boolean)) {\n const listener = (e: Event) => emit('elementEvent', e as CustomEvent);\n el.addEventListener(ev, listener);\n cleanups.push(() => el?.removeEventListener(ev, listener));\n }\n hostRef.value.appendChild(el);\n}\n\nfunction destroy() {\n for (const c of cleanups) c();\n cleanups = [];\n el?.remove();\n el = null;\n}\n\nonMounted(create);\nonBeforeUnmount(destroy);\nwatch(() => p.name, () => { destroy(); create(); });\nwatch(evtsKey, () => { destroy(); create(); });\nwatch(() => p.props, applyProps, { deep: true });\n\n/*\n * Typed as `AparteUiHandle`, the way React's `useImperativeHandle` already is.\n *\n * It used to be a bare object literal, so the exposed `getElement` returned\n * `HTMLElement | null` instead of the interface's `<T extends HTMLElement>() => T | null`\n * — and the barrel exports that interface with a docblock promising \"the same contract on\n * all four wrappers\". A consumer following the documented `ref` pattern got a type error\n * on Vue and Svelte and none on React or Angular. Found by a cold audit that compiled it\n * rather than read it.\n *\n * `as never` is the same bridge React uses at AparteUi.tsx:85: the value really is the\n * element, and only the caller knows which subtype it asked for.\n */\ndefineExpose<AparteUiHandle>({\n getElement: () => el as never,\n callMethod: (methodName: string, ...args: unknown[]) => {\n const fn = (el as unknown as Record<string, unknown>)?.[methodName];\n return (typeof fn === 'function' ? (fn as (...a: unknown[]) => unknown).apply(el, args) : undefined) as never;\n },\n});\n</script>\n\n<template>\n <span ref=\"hostRef\" style=\"display: contents\"></span>\n</template>\n"],"names":["_createElementBlock","_unref","_createElementVNode","_openBlock","_toDisplayString","_renderSlot","_Fragment","_renderList","$slots"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/components/AparteChat.vue","../src/composables/useAparteChat.ts","../src/composables/useAparteClient.ts","../src/composables/useConversationManager.ts","../src/components/AparteUi.vue","../src/composables/useMountedViews.ts","../src/components/AparteToolUI.vue","../src/components/AparteSegmentUI.vue","../src/is-aparte-element.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, useId, toRaw, type ComponentPublicInstance } from 'vue';\nimport { AparteChatHost, aparteGlobalConfig, isAwaitingReply, releaseDeferredHydration, type AparteChatHostBinding, type AparteConfig, type AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteActionEventDetail } from '../types.js';\n\ninterface Props {\n /**\n * The host element's `id`, and therefore the `targetId` every event this chat\n * dispatches carries. Generated when omitted — but it used to be generated and\n * neither accepted nor exposed, which made `AparteClientOptions.scopeToTargetId`\n * unreachable from this component.\n */\n id?: string;\n /** Optional: omit for an uncontrolled chat (defaults to []); use `v-model:messages` to control. */\n messages?: AparteMessage[];\n placeholder?: string;\n disabled?: boolean;\n isTyping?: boolean;\n typingText?: string;\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n submitOnEnter?: boolean;\n /** Freeze viewport spacer recalculation for this many ms after a conv swap. */\n layoutTransitionMs?: number;\n /**\n * Opt in to the \"centered composer when empty\" layout: the composer sits\n * vertically centered with the `empty-state` slot above it while the list is\n * empty, then slides to the bottom on the first message (~0.3s). Off by\n * default — additive (adds the `--auto-center` modifier + a `data-aparte-empty`\n * attribute the shipped `aparte.css` recipe keys off).\n */\n centerWhenEmpty?: boolean;\n /**\n * The conversation is on its way: the viewport draws two skeleton turns, the empty\n * state stays off and the composer is disabled until it lands. The conversation\n * controller sets this itself while it fetches through your adapter's `loadFull()`;\n * the prop is for a wait of your own. Off by default.\n */\n loading?: boolean;\n /** Overlay the composer on the transcript: full-column scroll surface, edge-to-edge scrollbar, floating composer. Read when the viewport mounts. */\n overlayComposer?: boolean;\n /**\n * Add the file picker + chips strip to the default composer shell. **Off by\n * default**, because the capability needs a host that consumes the files: an\n * `AparteClient` inlines them per its `rawFileInject` option, but if you drive\n * your own loop you must read `event.files` on `messageSent` — otherwise the file\n * the user deliberately attached is dropped in silence. No effect when you fill\n * the `composer` slot (drop `<aparte-composer-add-attachment>` and\n * `<aparte-composer-attachments>` in it yourself).\n */\n attachments?: boolean;\n /**\n * Render the `<aparte-elicitation>` presenter inside the host — **on by default**,\n * as it is in `<aparte-chat>`: the built-in approval gate and `requestUserInput()`\n * ask through it, and it renders nothing until something asks. Pass `false` when\n * you mount a presenter of your own (`setElicitationPresenter`) or place the\n * element yourself.\n */\n elicitation?: boolean;\n /** Active conversation id (loads/persists via the registered AparteConversationManager). */\n conversationId?: string | null;\n /**\n * Instance {@link AparteConfig} for this chat. When set, aparté components\n * inside resolve THIS config instead of `aparteGlobalConfig`, so\n * several independently-configured chats can coexist on one page. Omit for the\n * global config. Read once when the host mounts.\n */\n config?: AparteConfig;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n messages: () => [],\n placeholder: 'Type a message...',\n disabled: false,\n isTyping: false,\n typingText: undefined,\n submitOnEnter: true,\n layoutTransitionMs: 0,\n centerWhenEmpty: false,\n loading: false,\n overlayComposer: false,\n attachments: false,\n elicitation: true,\n conversationId: null,\n});\n\nconst emit = defineEmits<{\n /**\n * User submitted a message from the composer. The message is **appended to\n * the thread automatically** (optimistic UI) before this fires — do NOT add\n * it again in the handler (uncontrolled → duplicates; controlled → mirror it\n * into your own `messages`). For side-effects: scroll, analytics, send.\n */\n messageSent: [event: AparteSendEventDetail];\n /** A custom bubble action (registerBubbleAction) was clicked — typed aparte-action. */\n action: [detail: AparteActionEventDetail];\n /** Active path changed (branch nav/edit/retry/streaming) — bind back to `messages`. */\n messagesChange: [messages: AparteMessage[]];\n /** Same payload as `messagesChange`, enabling `v-model:messages`. */\n 'update:messages': [messages: AparteMessage[]];\n messageAppended: [message: AparteMessage];\n /** The typing/\"thinking\" indicator toggled (the host flips it off on the first streamed token). */\n typingChange: [isTyping: boolean];\n conversationCreated: [id: string];\n}>();\n\n// useId() (Vue 3.5+) is SSR-stable — server and client agree, no hydration mismatch.\n// A caller-supplied `id` wins, so `scopeToTargetId` has something to match; the\n// generated one stays SSR-stable for the common case.\nconst hostId = props.id ?? `aparte-chat-${useId()}`;\nconst rootRef = ref<HTMLElement>();\n// True until mounted — in the server render and in the render that hydrates it. While true the\n// root carries `defer-hydration`, so core's elements leave the server's DOM alone until Vue has it.\nconst hydrating = ref(true);\n// The root, handed over by Vue as soon as the chat's tree is in place — hydrated or rendered —\n// and BEFORE any onMounted, a slot component's included: a slot's own mount hook runs before\n// the chat's, so the elements a server render left waiting are released here, not there, and\n// whatever a slot does on mount talks to live elements. A client-only render holds nothing.\nfunction setRoot(el: Element | ComponentPublicInstance | null): void {\n if (!(el instanceof HTMLElement)) return;\n rootRef.value = el;\n releaseDeferredHydration(el);\n}\nconst viewportRef = ref<HTMLElement>();\nconst composerRef = ref<HTMLElement>();\nconst internalMessages = ref<AparteMessage[]>([...props.messages]);\nconst typingActive = ref(props.isTyping);\n\nlet host: AparteChatHost | null = null;\nlet teardown: (() => void) | null = null;\n\nfunction onSend(e: Event) {\n (viewportRef.value as unknown as { requestSmoothScroll?: () => void })?.requestSmoothScroll?.();\n emit('messageSent', (e as CustomEvent<AparteSendEventDetail>).detail);\n}\n\n// Custom bubble actions bubble to the root as `aparte-action` — surface them typed.\nfunction onAction(e: Event) {\n emit('action', (e as CustomEvent<AparteActionEventDetail>).detail);\n}\n\n// The controller's wait (a conversation fetched through the adapter) OR the consumer's.\nconst hostLoading = ref(false);\nconst waiting = computed(() => props.loading || hostLoading.value);\n// Bumped on every config change: the two strings below are locale text, and a computed does not\n// see the config — a language switch left them in the old language.\nconst localeTick = ref(0);\nlet unsubscribeLocale: (() => void) | null = null;\nconst loadingText = computed(() => (localeTick.value, (props.config ?? aparteGlobalConfig).t('loadingConversation')));\n// The status line's word, from the locale like the rest of the chat, unless the prop says.\nconst typingLabel = computed(() => (localeTick.value, props.typingText ?? (props.config ?? aparteGlobalConfig).t('typing')));\n\nonMounted(() => {\n // The elements a server render left waiting were upgraded in `setRoot`; the attribute\n // the next render would draw goes too.\n hydrating.value = false;\n unsubscribeLocale = (props.config ? toRaw(props.config) : aparteGlobalConfig).subscribe(() => { localeTick.value++; });\n const binding: AparteChatHostBinding = {\n hostId,\n host: rootRef.value as HTMLElement,\n viewport: viewportRef.value ?? null,\n getMessages: () => internalMessages.value,\n setMessages: (m) => { internalMessages.value = m as AparteMessage[]; },\n onMessagesChange: (m) => {\n emit('messagesChange', m as AparteMessage[]);\n emit('update:messages', m as AparteMessage[]);\n },\n onMessageAppended: (m) => emit('messageAppended', m as AparteMessage),\n onTypingChange: (t) => { typingActive.value = t; emit('typingChange', t); },\n onStreamingChange: () => { /* exposed via isStreaming() */ },\n afterRender: (cb) => { void nextTick(cb); },\n resetComposer: () => (composerRef.value as unknown as { reset?: () => void })?.reset?.(),\n onLoadingChange: (on) => { hostLoading.value = on; },\n };\n host = new AparteChatHost(binding, {\n layoutTransitionMs: props.layoutTransitionMs,\n conversationId: props.conversationId ?? null,\n onConversationCreated: (id) => emit('conversationCreated', id),\n // Unwrap Vue's reactive proxy: the config is a plain class with internal\n // Map registries the host/components must operate on directly, not through a\n // deep reactive proxy (which would wrap those Maps and break lookups).\n config: props.config ? toRaw(props.config) : undefined,\n });\n teardown = host.bind();\n host.syncBubbles();\n composerRef.value?.addEventListener('aparte-send', onSend);\n rootRef.value?.addEventListener('aparte-action', onAction);\n});\n\nonBeforeUnmount(() => {\n unsubscribeLocale?.();\n unsubscribeLocale = null;\n composerRef.value?.removeEventListener('aparte-send', onSend);\n rootRef.value?.removeEventListener('aparte-action', onAction);\n teardown?.();\n teardown = null;\n host = null;\n});\n\n// Parent push → internal list, unless it is the host's own report coming back — possibly an\n// EARLIER one when the parent lands late; applying it rolled the list back under the host's\n// next write. The host tells them apart (`takeEcho`): asked first, always, so a list the parent\n// restores later (a reopened conversation) is not mistaken for one. Raw, as a parent's `ref`\n// hands the emitted array back wrapped in a reactive proxy.\nwatch(() => props.messages, (m) => {\n const raw = toRaw(m);\n const echo = host?.takeEcho(raw) ?? false;\n if (echo || raw === toRaw(internalMessages.value)) return;\n internalMessages.value = [...m];\n if (m.length === 0) host?.clearRenderCache();\n});\n\n// Reconcile bubbles after the rendered list changes (host queries the DOM).\nwatch(internalMessages, () => { void nextTick(() => host?.syncBubbles()); });\n\nwatch(() => props.isTyping, (t) => { typingActive.value = t; });\nwatch(() => props.conversationId, (id) => { void host?.setConversationId(id ?? null); });\n\n// ── Imperative API (forwards to the host) ──\nconst appendMessage = (m: AparteMessage, o?: { historical?: boolean }) => host?.appendMessage(m, o);\nconst updateMessage = (id: string, u: Partial<AparteMessage>) => host?.updateMessage(id, u);\nconst updateLastMessage = (c: string, o?: { append?: boolean }) => host?.updateLastMessage(c, o);\nconst addSegment = (s: AparteSegment) => host?.addSegment(s);\nconst updateSegment = (id: string, u: Partial<AparteSegment>) => host?.updateSegment(id, u);\nconst removeSegment = (id: string) => host?.removeSegment(id);\nconst appendToSegment = (id: string, c: string) => host?.appendToSegment(id, c);\nconst getMessages = () => host?.getMessages() ?? internalMessages.value;\nconst clearMessages = (options?: { revokeAttachments?: boolean }) => host?.clearMessages(options);\nconst addBranch = (id: string) => host?.addBranch(id) ?? 0;\nconst addSiblingOf = (id: string, m: AparteMessage) => host?.addSiblingOf(id, m) ?? null;\nconst truncateFrom = (id: string) => host?.truncateFrom(id);\nconst truncateResponsesAfter = (id: string) => host?.truncateResponsesAfter(id);\nconst injectTokenStream = (id: string, tokens: AsyncIterable<string>) =>\n host?.streamTokens(id, tokens) ?? Promise.resolve();\nconst stopTokenStream = () => host?.stopTokenStream();\nconst setConversationId = (id: string | null) => host?.setConversationId(id) ?? Promise.resolve();\nconst scrollToBottom = () => (viewportRef.value as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.();\nconst focusInput = () => (composerRef.value as unknown as { focus?: () => void })?.focus?.();\nconst isStreaming = () => host?.isStreaming ?? false;\n\n// `getViewport()` (not a raw `viewport` ref): the same accessor on all four\n// wrappers — Svelte 4 can only expose functions, so the shared name is one.\nconst getViewport = () => viewportRef.value ?? null;\n\n// `satisfies` makes a dropped or mistyped method a compile error — the canonical\n// AparteChatImperativeApi is enforced here, not just aliased for consumers.\ndefineExpose({\n appendMessage, updateMessage, updateLastMessage, addSegment, updateSegment, removeSegment,\n appendToSegment, getMessages, clearMessages, addBranch, addSiblingOf, truncateFrom,\n truncateResponsesAfter, injectTokenStream, stopTokenStream, setConversationId,\n scrollToBottom, focusInput, isStreaming, getViewport,\n} satisfies AparteChatImperativeApi);\n</script>\n\n<template>\n <div\n :class=\"['aparte-chat-container', { 'aparte-chat-container--auto-center': centerWhenEmpty }]\"\n data-aparte-chat\n :defer-hydration=\"hydrating ? '' : null\"\n :overlay-composer=\"overlayComposer ? '' : null\"\n :data-aparte-empty=\"centerWhenEmpty && internalMessages.length === 0 && !waiting ? '' : null\"\n :id=\"hostId\"\n :ref=\"setRoot\"\n >\n <aparte-chat-viewport ref=\"viewportRef\" framework-managed=\"\" :loading=\"waiting ? '' : null\">\n <!-- The wait, drawn here because this DOM is Vue's: the kit's skeleton recipe,\n and a line for a screen reader. -->\n <div v-if=\"waiting\" class=\"aparte-viewport-loading\" aria-hidden=\"true\">\n <span class=\"aparte-skeleton aparte-skeleton--rect aparte-viewport-loading__user\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text aparte-viewport-loading__last\"></span>\n </div>\n <span v-if=\"waiting\" class=\"aparte-viewport-loading-status aparte-sr-only\" role=\"status\">{{ loadingText }}</span>\n <!-- Welcome / placeholder shown inside the viewport while there are no\n messages (a real empty-state region). -->\n <slot v-if=\"internalMessages.length === 0 && !waiting\" name=\"empty-state\" />\n <!-- `bubble` scoped slot renders your OWN element per message in place of\n <aparte-chat-bubble>; driven by the reactive list so it streams live. -->\n <template v-for=\"m in internalMessages\" :key=\"m.id\">\n <slot name=\"bubble\" :message=\"m\">\n <aparte-chat-bubble\n :message-id=\"m.id\"\n :data-role=\"m.role\"\n :data-kind=\"m.compaction ? 'compaction' : undefined\"\n :timestamp=\"m.timestamp\"\n :content=\"m.content\"\n :streaming=\"isAwaitingReply(m) ? '' : null\"\n />\n </slot>\n </template>\n <aparte-chat-status :visible=\"typingActive ? '' : null\" :text=\"typingLabel\" />\n </aparte-chat-viewport>\n\n <!-- The presenter for a request to the human (approval gate, ask_user…). Renders\n nothing until something asks; on by default as in <aparte-chat>. -->\n <aparte-elicitation v-if=\"elicitation\"></aparte-elicitation>\n\n <!-- Content above the composer (banner, disclaimer, context chip). -->\n <slot name=\"above-composer\" />\n\n <!-- `.attr` forces attribute-setting, and stays: the attribute IS the state\n core's composer parts read (`getAttribute('placeholder')`, `hasAttribute\n ('disabled')`). Core gained the matching setters in 0.16.12 — before that\n they were getter-only and Vue's default property-set on a custom element\n threw — so this is now a direct write rather than a way around a crash. -->\n <aparte-composer\n ref=\"composerRef\"\n :target=\"hostId\"\n :placeholder.attr=\"placeholder\"\n :disabled.attr=\"disabled || waiting ? '' : null\"\n :submit-on-enter=\"submitOnEnter ? null : 'false'\"\n >\n <!-- Custom composer via the `composer` slot; falls back to the default\n shell (input · send, plus the attachment primitives when `attachments`\n is set). Compose the headless aparte-composer-* primitives freely for a\n skin-specific layout. -->\n <slot name=\"composer\">\n <div class=\"aparte-composer-shell\">\n <aparte-composer-attachments v-if=\"attachments\"></aparte-composer-attachments>\n <div class=\"aparte-composer-row\">\n <aparte-composer-add-attachment v-if=\"attachments\"></aparte-composer-add-attachment>\n <aparte-composer-input></aparte-composer-input>\n <aparte-composer-send></aparte-composer-send>\n </div>\n <!-- The composer's bottom row. ONE slot: placement is the DOM order, and\n `margin-inline-start: auto` pushes a control to the end (a logical\n property, so it reads correctly in RTL). Nothing is rendered at all when\n the slot is unused. -->\n <aparte-composer-toolbar v-if=\"$slots.toolbar\">\n <slot name=\"toolbar\" />\n </aparte-composer-toolbar>\n </div>\n </slot>\n </aparte-composer>\n </div>\n</template>\n","import { ref, type Ref } from 'vue';\nimport type { AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment } from '../types.js';\n\n/**\n * Idiomatic Vue ergonomics for `<AparteChat>`. Owns the `messages` ref and a\n * component template ref so the consumer skips the manual\n * `@messages-change` → `messages` round-trip.\n *\n * @example\n * const chat = useAparteChat();\n * // template:\n * // <AparteChat :ref=\"chat.chatRef\" :messages=\"chat.messages.value\"\n * // @messages-change=\"chat.onMessagesChange\" />\n */\nexport function useAparteChat(initial: AparteMessage[] = []) {\n const messages = ref<AparteMessage[]>([...initial]) as Ref<AparteMessage[]>;\n const chatRef = ref<AparteChatImperativeApi | null>(null);\n const c = () => chatRef.value;\n const onMessagesChange = (m: AparteMessage[]) => { messages.value = m; };\n\n return {\n messages,\n chatRef,\n onMessagesChange,\n appendMessage: (m: AparteMessage, o?: { historical?: boolean }) => c()?.appendMessage(m, o),\n updateMessage: (id: string, u: Partial<AparteMessage>) => c()?.updateMessage(id, u),\n updateLastMessage: (content: string, o?: { append?: boolean }) => c()?.updateLastMessage(content, o),\n addSegment: (s: AparteSegment) => c()?.addSegment(s),\n updateSegment: (id: string, u: Partial<AparteSegment>) => c()?.updateSegment(id, u),\n removeSegment: (id: string) => c()?.removeSegment(id),\n appendToSegment: (id: string, content: string) => c()?.appendToSegment(id, content),\n // The host's list — the authority, and mid-stream a frame ahead of the\n // `messages` ref, which is synced once per paint rather than per token.\n getMessages: (): AparteMessage[] => c()?.getMessages() ?? messages.value,\n clearMessages: (options?: { revokeAttachments?: boolean }) => c()?.clearMessages(options),\n addBranch: (id: string) => c()?.addBranch(id) ?? 0,\n addSiblingOf: (id: string, m: AparteMessage) => c()?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id: string) => c()?.truncateFrom(id),\n truncateResponsesAfter: (id: string) => c()?.truncateResponsesAfter(id),\n injectTokenStream: (id: string, tokens: AsyncIterable<string>) =>\n c()?.injectTokenStream(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => c()?.stopTokenStream(),\n setConversationId: (id: string | null) => c()?.setConversationId(id) ?? Promise.resolve(),\n isStreaming: () => c()?.isStreaming() ?? false,\n scrollToBottom: () => c()?.scrollToBottom(),\n focusInput: () => c()?.focusInput(),\n /** The `<aparte-chat-viewport>` element — same accessor on all four wrappers. */\n getViewport: (): HTMLElement | null => c()?.getViewport() ?? null,\n };\n}\n","import { onMounted, onBeforeUnmount } from 'vue';\nimport { AparteClient, type AparteClientOptions } from '@aparte/core';\n\n/**\n * Mounts an `AparteClient` that bridges `aparte-send` events to the configured AI\n * providers. Starts on mount, stops on unmount. Vue equivalent of Angular's\n * `AparteAiService`.\n */\nexport function useAparteClient(options?: AparteClientOptions) {\n const client = new AparteClient(options ?? {});\n onMounted(() => client.start());\n onBeforeUnmount(() => client.stop());\n return { client, abort: () => client.abort() };\n}\n","import { ref, computed, onBeforeUnmount, type Ref } from 'vue';\nimport {\n aparteGlobalConfig,\n type AparteConfig,\n AparteConversationManager,\n type AparteConversation,\n type AparteStorageAdapter,\n type ConversationManagerOptions,\n} from '@aparte/core';\nimport type { AparteMessage } from '../types.js';\n\n/**\n * Vue-reactive wrapper around the core `AparteConversationManager`. The active\n * conversation is owned by the chat component's controller; switch by binding\n * `conversationId` on `<AparteChat>`. Vue equivalent of Angular's\n * `ConversationManagerService`.\n */\nexport function useConversationManager() {\n let manager: AparteConversationManager | null = null;\n let unsub: (() => void) | null = null;\n\n const conversations = ref<AparteConversation[]>([]) as Ref<AparteConversation[]>;\n const activeId = ref<string | null>(null);\n\n const activeConversations = computed(() =>\n conversations.value.filter((c) => !c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const archivedConversations = computed(() =>\n conversations.value.filter((c) => !!c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const activeConversation = computed(() =>\n activeId.value ? conversations.value.find((c) => c.id === activeId.value) ?? null : null,\n );\n\n onBeforeUnmount(() => unsub?.());\n\n const assert = (): AparteConversationManager => {\n if (!manager) throw new Error('[useConversationManager] Not initialised. Call init(adapter) first.');\n return manager;\n };\n\n /**\n * Initialise with a storage adapter.\n *\n * `config` defaults to the global singleton. Pass the SAME config you gave\n * `<AparteChat config={…}>`: the controller resolves the config governing its\n * host element, so a manager registered on the global is invisible to a chat\n * with its own — persistence silently does nothing while the optimistic UI\n * keeps working.\n */\n const init = async (adapter: AparteStorageAdapter, config: AparteConfig = aparteGlobalConfig, options?: ConversationManagerOptions): Promise<void> => {\n const m = new AparteConversationManager(adapter, options);\n manager = m;\n unsub = m.subscribe((convs) => {\n conversations.value = [...convs];\n activeId.value = m.activeId;\n });\n await m.init();\n activeId.value = m.activeId;\n config.setConversationManager(m);\n };\n\n return {\n conversations,\n activeConversations,\n archivedConversations,\n activeId,\n activeConversation,\n init,\n /** The core manager, once `init` has run (`null` before): for what this does not mirror. Read it as `cm.manager` after `init` — a destructured copy keeps the `null` it had, and it is not reactive. */\n get manager(): AparteConversationManager | null { return manager; },\n createNew: (title?: string) => assert().createNew(title),\n addMessage: (convId: string, message: AparteMessage) => assert().addMessage(convId, message),\n updateMessages: (convId: string, messages: AparteMessage[]) => assert().updateMessages(convId, messages),\n delete: (id: string) => assert().delete(id),\n archive: (id: string) => assert().archive(id),\n unarchive: (id: string) => assert().unarchive(id),\n pin: (id: string) => assert().pin(id),\n unpin: (id: string) => assert().unpin(id),\n updateTitle: (id: string, title: string) => assert().updateTitle(id, title),\n };\n}\n","<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, toRaw } from 'vue';\nimport { applyElementProps, APARTE_DEFAULT_UI_EVENTS } from '@aparte/core';\nimport type { AparteUiHandle } from '../types.js';\n\nconst p = defineProps<{\n /** The custom element tag name (e.g. 'aparte-model-selector'). */\n name: string;\n /** Props to apply. Keys starting with `--` become CSS variables. */\n props?: Record<string, unknown>;\n /**\n * Which custom events to forward through `elementEvent`. Defaults to the\n * interactive aparté surface (APARTE_DEFAULT_UI_EVENTS); pass your own list to listen to\n * other events (e.g. ['aparte-composer-change'] for attachments).\n */\n events?: string[];\n}>();\n\nconst emit = defineEmits<{ elementEvent: [event: CustomEvent] }>();\n\n// A stable key so a fresh inline `:events` array doesn't thrash the element —\n// only a real change to the event names rebinds (mirrors React's evtsKey).\nconst evtsKey = computed(() => (p.events ?? APARTE_DEFAULT_UI_EVENTS).join('|'));\n\nconst hostRef = ref<HTMLElement>();\nlet el: HTMLElement | null = null;\nlet cleanups: Array<() => void> = [];\n\n// Vue passes `toRaw` so objects are unwrapped from the reactive proxy before\n// reaching the plain custom element (a deep proxy breaks Maps/class internals).\nfunction applyProps() {\n if (el) applyElementProps(el, p.props ?? {}, toRaw);\n}\n\nfunction create() {\n if (!hostRef.value) return;\n el = document.createElement(p.name);\n applyProps();\n for (const ev of evtsKey.value.split('|').filter(Boolean)) {\n const listener = (e: Event) => emit('elementEvent', e as CustomEvent);\n el.addEventListener(ev, listener);\n cleanups.push(() => el?.removeEventListener(ev, listener));\n }\n hostRef.value.appendChild(el);\n}\n\nfunction destroy() {\n for (const c of cleanups) c();\n cleanups = [];\n el?.remove();\n el = null;\n}\n\nonMounted(create);\nonBeforeUnmount(destroy);\nwatch(() => p.name, () => { destroy(); create(); });\nwatch(evtsKey, () => { destroy(); create(); });\nwatch(() => p.props, applyProps, { deep: true });\n\n/*\n * Typed as `AparteUiHandle`, the way React's `useImperativeHandle` already is.\n *\n * It used to be a bare object literal, so the exposed `getElement` returned\n * `HTMLElement | null` instead of the interface's `<T extends HTMLElement>() => T | null`\n * — and the barrel exports that interface with a docblock promising \"the same contract on\n * all four wrappers\". A consumer following the documented `ref` pattern got a type error\n * on Vue and Svelte and none on React or Angular. Found by a cold audit that compiled it\n * rather than read it.\n *\n * `as never` is the same bridge React uses at AparteUi.tsx:85: the value really is the\n * element, and only the caller knows which subtype it asked for.\n */\ndefineExpose<AparteUiHandle>({\n getElement: () => el as never,\n callMethod: (methodName: string, ...args: unknown[]) => {\n const fn = (el as unknown as Record<string, unknown>)?.[methodName];\n return (typeof fn === 'function' ? (fn as (...a: unknown[]) => unknown).apply(el, args) : undefined) as never;\n },\n});\n</script>\n\n<template>\n <span ref=\"hostRef\" style=\"display: contents\"></span>\n</template>\n","import { onBeforeUnmount, onMounted, shallowRef, watch, type ShallowRef, type WatchSource } from 'vue';\nimport type { AparteMountedView } from '@aparte/core';\n\n/** One element core handed a declaration: where to teleport, what to draw, and a stable key. */\nexport interface MountedEntry<V> {\n host: HTMLElement;\n view: V;\n key: number;\n}\n\ntype Mount<V> = (host: HTMLElement, view: V) => AparteMountedView<V>;\n\n/**\n * The elements core hands one `<AparteToolUI>` / `<AparteSegmentUI>`, as a list the template\n * teleports into.\n *\n * `register` is called in the browser only (`onMounted` never runs in a server render), again\n * whenever one of `sources` changes, and its restore function on unmount — so a declaration lives\n * exactly as long as the component, and a server render declares nothing.\n */\nexport function useMountedViews<V>(\n // Several sources, which Vue compares one by one: a single getter returning an array would\n // be a new array — a change — on every run.\n sources: WatchSource<unknown>[],\n register: (mount: Mount<V>) => () => void,\n): ShallowRef<readonly MountedEntry<V>[]> {\n const entries = shallowRef<readonly MountedEntry<V>[]>([]);\n // A key per element, not the call's id: a model can issue `call_0` on every turn.\n let serial = 0;\n\n const mount: Mount<V> = (host, view) => {\n const key = ++serial;\n entries.value = [...entries.value, { host, view, key }];\n return {\n update: (next) => {\n entries.value = entries.value.map((e) => (e.host === host ? { host, view: next, key: e.key } : e));\n },\n destroy: () => {\n entries.value = entries.value.filter((e) => e.host !== host);\n },\n };\n };\n\n let restore: (() => void) | null = null;\n onMounted(() => {\n watch(sources, () => { restore?.(); restore = register(mount); }, { immediate: true });\n });\n onBeforeUnmount(() => { restore?.(); restore = null; });\n\n return entries;\n}\n","<script setup lang=\"ts\" generic=\"I = unknown, R = unknown\">\n/**\n * Your own Vue component in a tool call.\n *\n * `<AparteToolUI name=\"get_weather\" v-slot=\"{ tool }\"><WeatherCard :tool=\"tool\" /></AparteToolUI>`\n * draws every `get_weather` call with your component for as long as it is mounted, and gives\n * the calls back to core's row when it unmounts. The slot is teleported into each card, so it\n * renders from where you put the declaration: `inject` reads what your app provides there.\n *\n * Underneath it is core's `overrideToolRenderer` + `defineMountedToolRenderer`. Nothing is\n * declared in a server render; the cards are drawn in the browser.\n */\nimport { toRaw } from 'vue';\nimport { aparteGlobalConfig, defineMountedToolRenderer } from '@aparte/core';\nimport type { AparteConfig, AparteToolCallView, AparteToolMatcher } from '@aparte/core';\nimport { useMountedViews } from '../composables/useMountedViews.js';\n\nconst props = defineProps<{\n /** The tool this draws: a name, a `RegExp`, or `'*'` for every tool. */\n name: AparteToolMatcher;\n /** The config to declare it on. Defaults to the global one. */\n config?: AparteConfig;\n}>();\n\ndefineSlots<{\n /** What to draw for one call: its id, name, input, status, result and the rest. */\n default(props: { tool: AparteToolCallView<I, R> }): unknown;\n}>();\n\n// The config unwrapped: a config held in a ref reaches here as Vue's reactive proxy, and core\n// keys its registries by the instance the chat holds.\nconst config = () => (props.config ? toRaw(props.config) : aparteGlobalConfig);\n\n// Two sources, compared one by one: the matcher by its text — a `RegExp` built in a render is a\n// new object every time, the same declaration — and the config.\nconst entries = useMountedViews<AparteToolCallView>(\n [() => (typeof props.name === 'string' ? props.name : String(props.name)), config],\n (mount) => config().overrideToolRenderer(props.name, defineMountedToolRenderer(mount)),\n);\n</script>\n\n<template>\n <Teleport v-for=\"entry in entries\" :key=\"entry.key\" :to=\"entry.host\">\n <slot :tool=\"(entry.view as AparteToolCallView<I, R>)\" />\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Your own Vue component for a segment type — one your stream emits, or a built-in such as\n * `code`. Teleported into each segment like `<AparteToolUI>`; taking the last declaration off\n * a built-in type gives it back to core's renderer.\n *\n * The segment's shape is the app's: the slot hands it as a base segment with its own fields,\n * so a typed template narrows it — `(segment as ChartSegment).points`. A Vue template cannot pass\n * a type argument, and the `type` prop cannot carry one.\n */\nimport { toRaw } from 'vue';\nimport { defineMountedSegmentRenderer, overrideSegmentRenderer } from '@aparte/core';\nimport type { AparteConfig, AparteSegmentBase } from '@aparte/core';\nimport { useMountedViews } from '../composables/useMountedViews.js';\n\ntype AnySegment = AparteSegmentBase & Record<string, unknown>;\n\nconst props = defineProps<{\n /** The segment `type` this draws. */\n type: string;\n /** The config to declare it on. Defaults to the global one. */\n config?: AparteConfig;\n}>();\n\ndefineSlots<{\n /** What to draw for one segment, handed its latest state. */\n default(props: { segment: AnySegment }): unknown;\n}>();\n\n// The config unwrapped: a config held in a ref reaches here as Vue's reactive proxy, and core\n// keys its registries by the instance the chat holds.\nconst config = () => (props.config ? toRaw(props.config) : undefined);\n\nconst entries = useMountedViews<AnySegment>(\n [() => props.type, config],\n (mount) => {\n const renderer = defineMountedSegmentRenderer<AnySegment>(props.type, mount);\n const target = config();\n return target ? overrideSegmentRenderer(renderer, target) : overrideSegmentRenderer(renderer);\n },\n);\n</script>\n\n<template>\n <Teleport v-for=\"entry in entries\" :key=\"entry.key\" :to=\"entry.host\">\n <slot :segment=\"entry.view\" />\n </Teleport>\n</template>\n","/**\n * The wrapper's own components in kebab case. They share the prefix and are not elements, so\n * they are left to Vue: `<aparte-ui>` and `<aparte-tool-u-i>` resolve to `AparteUi` and\n * `AparteToolUI`; `<aparte-tool-ui>` resolves to nothing (Vue reads it as `AparteToolUi`), and\n * left to Vue it gets Vue's \"failed to resolve\" warning rather than becoming an inert element —\n * write the components in PascalCase. (`<aparte-chat>` is not here: that tag is core's element.)\n */\nconst WRAPPER_COMPONENTS = new Set([\n 'aparte-ui',\n 'aparte-tool-ui', 'aparte-tool-u-i',\n 'aparte-segment-ui', 'aparte-segment-u-i',\n]);\n\n/**\n * Whether a template tag is one of aparté's elements, for Vue's `isCustomElement`: Vue then\n * leaves `<aparte-icon>` and the rest to the browser instead of looking for a component of that\n * name. A prefix, not a list, so a plugin's element (`<aparte-approval-mode>`) is included.\n *\n * @example\n * // vite.config.ts\n * vue({ template: { compilerOptions: { isCustomElement: isAparteElement } } })\n */\nexport function isAparteElement(tag: string): boolean {\n return tag.startsWith('aparte-') && !WRAPPER_COMPONENTS.has(tag);\n}\n"],"names":["_createElementBlock","_unref","_createElementVNode","_openBlock","_toDisplayString","_renderSlot","_Fragment","_renderList","$slots","_createBlock","_Teleport"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a template tag is one of aparté's elements, for Vue's `isCustomElement`: Vue then
|
|
3
|
+
* leaves `<aparte-icon>` and the rest to the browser instead of looking for a component of that
|
|
4
|
+
* name. A prefix, not a list, so a plugin's element (`<aparte-approval-mode>`) is included.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // vite.config.ts
|
|
8
|
+
* vue({ template: { compilerOptions: { isCustomElement: isAparteElement } } })
|
|
9
|
+
*/
|
|
10
|
+
export declare function isAparteElement(tag: string): boolean;
|
|
11
|
+
//# sourceMappingURL=is-aparte-element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-aparte-element.d.ts","sourceRoot":"","sources":["../src/is-aparte-element.ts"],"names":[],"mappings":"AAaA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aparte/vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"homepage": "https://apartejs.dev/frameworks/vue/",
|
|
5
5
|
"description": "Vue 3 wrapper for aparté — an ergonomic <AparteChat> component plus composables over the framework-agnostic web components.",
|
|
6
6
|
"type": "module",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"node": ">=18"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@aparte/core": ">=0.
|
|
28
|
+
"@aparte/core": ">=0.25.0 <1.0.0",
|
|
29
29
|
"vue": "^3.5.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"vite": "^6.0.0",
|
|
37
37
|
"vue": "^3.5.0",
|
|
38
38
|
"vue-tsc": "^2.0.0",
|
|
39
|
-
"@aparte/core": "0.
|
|
39
|
+
"@aparte/core": "0.25.0",
|
|
40
|
+
"@aparte/provider-scenario": "0.25.0"
|
|
40
41
|
},
|
|
41
42
|
"keywords": [
|
|
42
43
|
"vue",
|