@aparte/angular 0.24.0 → 0.26.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 +12 -9
- package/dist/README.md +12 -9
- package/dist/fesm2022/aparte-angular.mjs +311 -137
- package/dist/fesm2022/aparte-angular.mjs.map +1 -1
- package/dist/generated/element.directives.d.ts +13 -7
- package/dist/index.d.ts +3 -1
- package/dist/lib/aparte-bubble.directive.d.ts +27 -0
- package/dist/lib/aparte-chat.component.d.ts +58 -51
- package/dist/lib/aparte-tool-ui.directive.d.ts +63 -0
- package/dist/lib/aparte-ui.component.d.ts +7 -0
- package/dist/lib/conversation-manager.service.d.ts +2 -2
- package/package.json +9 -8
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* a plain host listener when you need `stopPropagation`.
|
|
12
12
|
*/
|
|
13
13
|
import { ElementRef, EventEmitter } from '@angular/core';
|
|
14
|
-
import type { AparteActionClickEventDetail, AparteActionEventDetail, AparteAttachmentPreviewEventDetail, AparteBranchNavigateEventDetail, AparteCompactEventDetail, AparteComposerChangeEventDetail, AparteContextThresholdEventDetail, AparteConversationArchiveDetail, AparteConversationDeleteDetail, AparteConversationPinDetail, AparteConversationRenameDetail, AparteConversationSelectDetail, AparteEditEventDetail, AparteFeedbackEventDetail, AparteLinkClickEventDetail, AparteMessageInfoEventDetail, AparteOptgroupToggleEventDetail, ApartePathChangedEventDetail, AparteRetryEventDetail, AparteScrollRailJumpDetail, AparteSegmentUpdateEventDetail, AparteSelectChangeDetail, AparteSendEventDetail, AparteSidebarToggleDetail, AparteSplitResizeDetail, AparteSuggestionEventDetail } from '@aparte/core';
|
|
14
|
+
import type { AparteActionClickEventDetail, AparteActionEventDetail, AparteAttachmentPreviewEventDetail, AparteBranchNavigateEventDetail, AparteCompactEventDetail, AparteComposerChangeEventDetail, AparteContextThresholdEventDetail, AparteConversationArchiveDetail, AparteConversationDeleteDetail, AparteConversationListItem, AparteConversationPinDetail, AparteConversationRenameDetail, AparteConversationSelectDetail, AparteEditEventDetail, AparteFeedbackEventDetail, AparteLinkClickEventDetail, AparteMessageInfoEventDetail, AparteOptgroupToggleEventDetail, ApartePathChangedEventDetail, AparteRetryEventDetail, AparteScrollRailJumpDetail, AparteSegmentUpdateEventDetail, AparteSelectChangeDetail, AparteSendEventDetail, AparteSidebarToggleDetail, AparteSplitResizeDetail, AparteSuggestionEventDetail } from '@aparte/core';
|
|
15
15
|
import * as i0 from "@angular/core";
|
|
16
16
|
/**
|
|
17
17
|
* Writes one declared attribute onto the host element.
|
|
@@ -41,6 +41,8 @@ export declare class AparteChatBubbleDirective extends AparteElementBase {
|
|
|
41
41
|
set streaming(v: boolean);
|
|
42
42
|
/** Who wrote the message: shown in the header, and the message's accessible name ("Message from {name}"). Leave it out for the reader and the assistant, whose names come from the locale. */
|
|
43
43
|
set name(v: string | undefined);
|
|
44
|
+
/** Why the compaction failed, beside `data-checkpoint="failed"`: the separator gives it as the failure's tooltip and to screen readers. Set and cleared with `data-checkpoint`; read it, do not write it. */
|
|
45
|
+
set dataCheckpointReason(v: string | undefined);
|
|
44
46
|
/** An attached image was clicked, asking the app to open it full-size. */
|
|
45
47
|
readonly attachmentPreview: EventEmitter<AparteAttachmentPreviewEventDetail>;
|
|
46
48
|
/** A custom action-bar button was pressed. */
|
|
@@ -66,7 +68,7 @@ export declare class AparteChatBubbleDirective extends AparteElementBase {
|
|
|
66
68
|
protected onBranchNavigate(e: CustomEvent<AparteBranchNavigateEventDetail>): void;
|
|
67
69
|
protected onLinkClick(e: CustomEvent<AparteLinkClickEventDetail>): void;
|
|
68
70
|
static ɵfac: i0.ɵɵFactoryDeclaration<AparteChatBubbleDirective, never>;
|
|
69
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteChatBubbleDirective, "aparte-chat-bubble", never, { "messageRole": { "alias": "messageRole"; "required": false; }; "content": { "alias": "content"; "required": false; }; "timestamp": { "alias": "timestamp"; "required": false; }; "messageId": { "alias": "messageId"; "required": false; }; "streaming": { "alias": "streaming"; "required": false; }; "name": { "alias": "name"; "required": false; }; }, { "attachmentPreview": "attachmentPreview"; "action": "action"; "retry": "retry"; "feedback": "feedback"; "messageInfo": "messageInfo"; "edit": "edit"; "branchNavigate": "branchNavigate"; "linkClick": "linkClick"; }, never, never, true, never>;
|
|
71
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteChatBubbleDirective, "aparte-chat-bubble", never, { "messageRole": { "alias": "messageRole"; "required": false; }; "content": { "alias": "content"; "required": false; }; "timestamp": { "alias": "timestamp"; "required": false; }; "messageId": { "alias": "messageId"; "required": false; }; "streaming": { "alias": "streaming"; "required": false; }; "name": { "alias": "name"; "required": false; }; "dataCheckpointReason": { "alias": "dataCheckpointReason"; "required": false; }; }, { "attachmentPreview": "attachmentPreview"; "action": "action"; "retry": "retry"; "feedback": "feedback"; "messageInfo": "messageInfo"; "edit": "edit"; "branchNavigate": "branchNavigate"; "linkClick": "linkClick"; }, never, never, true, never>;
|
|
70
72
|
static ngAcceptInputType_streaming: unknown;
|
|
71
73
|
}
|
|
72
74
|
/** `<aparte-chat-status>` — A standalone status line — a light-DOM indicator the APP owns. Nothing in core turns it on: the framework host only ever flips it back OFF (on the first streamed token), and the four wrappers render one inside the viewport driven by their own `isTyping` prop. */
|
|
@@ -230,7 +232,7 @@ export declare class AparteComposerToolbarDirective {
|
|
|
230
232
|
static ɵfac: i0.ɵɵFactoryDeclaration<AparteComposerToolbarDirective, never>;
|
|
231
233
|
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteComposerToolbarDirective, "aparte-composer-toolbar", never, {}, {}, never, never, true, never>;
|
|
232
234
|
}
|
|
233
|
-
/** `<aparte-context>` — A gauge of the model's context window: how much of it the conversation uses. */
|
|
235
|
+
/** `<aparte-context>` — A gauge of the model's context window: how much of it the conversation uses, and what fills it. */
|
|
234
236
|
export declare class AparteContextDirective extends AparteElementBase {
|
|
235
237
|
/** The context window, in tokens. Overrides the current model's `contextWindow`. */
|
|
236
238
|
set window(v: number);
|
|
@@ -244,20 +246,22 @@ export declare class AparteContextDirective extends AparteElementBase {
|
|
|
244
246
|
set variant(v: string | undefined);
|
|
245
247
|
/** Tokens in use before a turn of this page has reported any: a restored conversation's last usage. The next turn's usage replaces it. */
|
|
246
248
|
set used(v: number);
|
|
247
|
-
/** Dispatch `aparte-compact` on each turn that ends in `danger`, one request at a time. */
|
|
249
|
+
/** Deprecated, still works. Dispatch `aparte-compact` (with `auto: true`) on each turn that ends in `danger`, one request at a time. `@aparte/plugin-compaction` decides when to compact by itself now, so leave this off. */
|
|
248
250
|
set autoCompact(v: boolean);
|
|
249
251
|
/** Reflected BY the element: `ok`, `warn` or `danger`. Read-only. */
|
|
250
252
|
set dataLevel(v: string | undefined);
|
|
251
253
|
/** Reflected BY the element while it has nothing to show. Read-only. */
|
|
252
254
|
set dataEmpty(v: boolean);
|
|
255
|
+
/** Reflected BY the element while this chat is being compacted (`running`) and after a compaction failed (`failed`). Read-only. */
|
|
256
|
+
set dataCompact(v: string | undefined);
|
|
253
257
|
/** The level changed. Bubbles. */
|
|
254
258
|
readonly contextThreshold: EventEmitter<AparteContextThresholdEventDetail>;
|
|
255
|
-
/** Dispatched on `window` when `auto-compact` is set and a turn ends in `danger
|
|
259
|
+
/** Dispatched on `window` when the deprecated `auto-compact` is set and a turn ends in `danger` (`auto: true`, with the `window` it measured against), and by Retry in the panel when no compactor is registered. One automatic request at a time — the next turn in `danger` asks again once the plugin has answered. `@aparte/plugin-compaction` answers it; with no listener nothing happens. */
|
|
256
260
|
readonly compact: EventEmitter<AparteCompactEventDetail>;
|
|
257
261
|
protected onContextThreshold(e: CustomEvent<AparteContextThresholdEventDetail>): void;
|
|
258
262
|
protected onCompact(e: CustomEvent<AparteCompactEventDetail>): void;
|
|
259
263
|
static ɵfac: i0.ɵɵFactoryDeclaration<AparteContextDirective, never>;
|
|
260
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteContextDirective, "aparte-context", never, { "window": { "alias": "window"; "required": false; }; "warn": { "alias": "warn"; "required": false; }; "danger": { "alias": "danger"; "required": false; }; "target": { "alias": "target"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "used": { "alias": "used"; "required": false; }; "autoCompact": { "alias": "autoCompact"; "required": false; }; "dataLevel": { "alias": "dataLevel"; "required": false; }; "dataEmpty": { "alias": "dataEmpty"; "required": false; }; }, { "contextThreshold": "contextThreshold"; "compact": "compact"; }, never, never, true, never>;
|
|
264
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteContextDirective, "aparte-context", never, { "window": { "alias": "window"; "required": false; }; "warn": { "alias": "warn"; "required": false; }; "danger": { "alias": "danger"; "required": false; }; "target": { "alias": "target"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "used": { "alias": "used"; "required": false; }; "autoCompact": { "alias": "autoCompact"; "required": false; }; "dataLevel": { "alias": "dataLevel"; "required": false; }; "dataEmpty": { "alias": "dataEmpty"; "required": false; }; "dataCompact": { "alias": "dataCompact"; "required": false; }; }, { "contextThreshold": "contextThreshold"; "compact": "compact"; }, never, never, true, never>;
|
|
261
265
|
static ngAcceptInputType_window: unknown;
|
|
262
266
|
static ngAcceptInputType_warn: unknown;
|
|
263
267
|
static ngAcceptInputType_danger: unknown;
|
|
@@ -275,6 +279,8 @@ export declare class AparteConversationListDirective extends AparteElementBase {
|
|
|
275
279
|
set loading(v: boolean);
|
|
276
280
|
/** Let the list finish the gesture: rename, pin, unpin, archive, unarchive and delete are performed on the conversation manager registered with `setConversationManager()`, instead of leaving you six listeners to write. The event still fires first, and `preventDefault()` on it takes the gesture back. Off by default, and selecting stays yours either way. */
|
|
277
281
|
set manage(v: boolean);
|
|
282
|
+
/** Set the list of conversations to display. Triggers a re-render. */
|
|
283
|
+
set conversations(v: AparteConversationListItem[] | undefined);
|
|
278
284
|
/** A row's title was activated; the host loads that conversation. */
|
|
279
285
|
readonly conversationSelect: EventEmitter<AparteConversationSelectDetail>;
|
|
280
286
|
/** A rename was committed with a new, non-empty title. Cancelable: `preventDefault()` takes the gesture back from `manage`. Angular: this Output emits the detail, so preventDefault() is not on it — bind the DOM event for that: (aparte-conversation-rename)="$event.preventDefault()". */
|
|
@@ -297,7 +303,7 @@ export declare class AparteConversationListDirective extends AparteElementBase {
|
|
|
297
303
|
protected onConversationUnarchive(e: CustomEvent<AparteConversationArchiveDetail>): void;
|
|
298
304
|
protected onConversationDelete(e: CustomEvent<AparteConversationDeleteDetail>): void;
|
|
299
305
|
static ɵfac: i0.ɵɵFactoryDeclaration<AparteConversationListDirective, never>;
|
|
300
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteConversationListDirective, "aparte-conversation-list", never, { "activeId": { "alias": "activeId"; "required": false; }; "flat": { "alias": "flat"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "manage": { "alias": "manage"; "required": false; }; }, { "conversationSelect": "conversationSelect"; "conversationRename": "conversationRename"; "conversationPin": "conversationPin"; "conversationUnpin": "conversationUnpin"; "conversationArchive": "conversationArchive"; "conversationUnarchive": "conversationUnarchive"; "conversationDelete": "conversationDelete"; }, never, never, true, never>;
|
|
306
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteConversationListDirective, "aparte-conversation-list", never, { "activeId": { "alias": "activeId"; "required": false; }; "flat": { "alias": "flat"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "manage": { "alias": "manage"; "required": false; }; "conversations": { "alias": "conversations"; "required": false; }; }, { "conversationSelect": "conversationSelect"; "conversationRename": "conversationRename"; "conversationPin": "conversationPin"; "conversationUnpin": "conversationUnpin"; "conversationArchive": "conversationArchive"; "conversationUnarchive": "conversationUnarchive"; "conversationDelete": "conversationDelete"; }, never, never, true, never>;
|
|
301
307
|
static ngAcceptInputType_flat: unknown;
|
|
302
308
|
static ngAcceptInputType_loading: unknown;
|
|
303
309
|
static ngAcceptInputType_manage: unknown;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
export { provideAparte, APARTE_CONFIG_TOKEN } from './lib/provide-aparte';
|
|
6
6
|
export type { ProvideAparteOptions, ApartePluginLoader } from './lib/provide-aparte';
|
|
7
7
|
export { AparteChatComponent } from './lib/aparte-chat.component';
|
|
8
|
+
export { AparteBubbleDirective } from './lib/aparte-bubble.directive';
|
|
9
|
+
export { AparteToolUIDirective, AparteSegmentUIDirective } from './lib/aparte-tool-ui.directive';
|
|
8
10
|
export { AparteUiComponent } from './lib/aparte-ui.component';
|
|
9
11
|
export type { AparteUiHandle, AparteUiProps } from './lib/aparte-ui.component';
|
|
10
12
|
export * from './generated/element.directives';
|
|
11
13
|
export { AparteAiService, APARTE_CLIENT_OPTIONS } from './lib/aparte-ai.service';
|
|
12
14
|
export { ConversationManagerService } from './lib/conversation-manager.service';
|
|
13
|
-
export type { AparteMessage, AparteSendEventDetail, AparteActionEventDetail, AparteSegment, AparteTextSegment, AparteCodeSegment, AparteThinkingSegment, AparteChatImperativeApi, } from '@aparte/core';
|
|
15
|
+
export type { AparteMessage, AparteSendEventDetail, AparteActionEventDetail, AparteSegment, AparteTextSegment, AparteCodeSegment, AparteThinkingSegment, AparteChatImperativeApi, AparteToolCallView, } from '@aparte/core';
|
|
14
16
|
export { aparteGlobalConfig } from '@aparte/core';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TemplateRef } from '@angular/core';
|
|
2
|
+
import type { AparteMessage } from '@aparte/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Marks the template `<aparte-chat>` draws each message with, in place of
|
|
6
|
+
* `<aparte-chat-bubble>`: write it as content of the chat, the message as `$implicit`.
|
|
7
|
+
*
|
|
8
|
+
* ```html
|
|
9
|
+
* <aparte-chat [messages]="messages">
|
|
10
|
+
* <ng-template aparteBubble let-message>
|
|
11
|
+
* <app-bubble [message]="message" />
|
|
12
|
+
* </ng-template>
|
|
13
|
+
* </aparte-chat>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* The same thing as passing a `TemplateRef` to `[bubbleTemplate]`, written where Angular
|
|
17
|
+
* developers write a per-item template. When both are given, `[bubbleTemplate]` wins.
|
|
18
|
+
* The built-in action bar (retry, edit, the version picker) belongs to the native bubble;
|
|
19
|
+
* a template of yours owns whatever it wires.
|
|
20
|
+
*/
|
|
21
|
+
export declare class AparteBubbleDirective {
|
|
22
|
+
readonly template: TemplateRef<{
|
|
23
|
+
$implicit: AparteMessage;
|
|
24
|
+
}>;
|
|
25
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AparteBubbleDirective, never>;
|
|
26
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteBubbleDirective, "ng-template[aparteBubble]", never, {}, {}, never, never, true, never>;
|
|
27
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { ElementRef, OnDestroy, QueryList,
|
|
1
|
+
import { AfterViewInit, ElementRef, OnDestroy, QueryList, TemplateRef } from '@angular/core';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteConfig, AparteActionEventDetail, AparteChatImperativeApi } from '@aparte/core';
|
|
4
4
|
import { isAwaitingReply } from '@aparte/core';
|
|
5
|
+
import { AparteBubbleDirective } from './aparte-bubble.directive';
|
|
5
6
|
import * as i0 from "@angular/core";
|
|
6
7
|
/**
|
|
7
|
-
* AparteChatComponent — Angular 19
|
|
8
|
+
* AparteChatComponent — the Angular wrapper (19.2 to 21, zone or zoneless)
|
|
8
9
|
*
|
|
9
10
|
* Standalone component wrapping aparté Web Components with Angular Signals.
|
|
10
11
|
* The streaming / branch-navigation / host-method orchestration (orphan-stream
|
|
@@ -15,25 +16,35 @@ import * as i0 from "@angular/core";
|
|
|
15
16
|
*/
|
|
16
17
|
export declare class AparteChatComponent implements AfterViewInit, OnDestroy, AparteChatImperativeApi {
|
|
17
18
|
constructor();
|
|
19
|
+
ngAfterViewInit(): void;
|
|
18
20
|
private elementRef;
|
|
21
|
+
private readonly _injector;
|
|
22
|
+
private readonly _isBrowser;
|
|
19
23
|
/**
|
|
20
24
|
* Template bridge to core's shared `isAwaitingReply` (an Angular template can't
|
|
21
25
|
* call an imported function). One rule for the four wrappers and core itself,
|
|
22
26
|
* so "is this bubble in flight" can't drift between them.
|
|
23
27
|
*/
|
|
24
28
|
readonly awaitingReply: typeof isAwaitingReply;
|
|
25
|
-
/** Messages to display */
|
|
26
|
-
|
|
29
|
+
/** Messages to display. Two-way: `[(messages)]`, with `(messagesChange)` reporting the chat's own changes. */
|
|
30
|
+
readonly messagesInput: import("@angular/core").InputSignal<AparteMessage[]>;
|
|
31
|
+
/** Every list the host reported — read only by the render-cache rule below. */
|
|
32
|
+
private readonly _emitted;
|
|
33
|
+
/**
|
|
34
|
+
* Under `[(messages)]` each report comes back through the input — possibly an EARLIER one,
|
|
35
|
+
* after the chat appended without reporting (an optimistic append, or core's append right
|
|
36
|
+
* after a flush) — and an echo is not the parent's word: it keeps the local list. The host
|
|
37
|
+
* tells them apart (`takeEcho`), the rule React, Vue and Svelte apply, so a list the parent
|
|
38
|
+
* restores later (a reopened conversation, an undo) is applied. Before the host exists
|
|
39
|
+
* nothing was reported, so the input is taken as it is.
|
|
40
|
+
*/
|
|
27
41
|
readonly messages: import("@angular/core").WritableSignal<AparteMessage[]>;
|
|
28
42
|
/** Input placeholder text */
|
|
29
|
-
|
|
30
|
-
readonly placeholder: import("@angular/core").WritableSignal<string>;
|
|
43
|
+
readonly placeholder: import("@angular/core").InputSignal<string>;
|
|
31
44
|
/** Whether the input is disabled */
|
|
32
|
-
|
|
33
|
-
readonly disabled: import("@angular/core").WritableSignal<boolean>;
|
|
45
|
+
readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
34
46
|
/** When false, Shift+Enter submits and a bare Enter inserts a newline. */
|
|
35
|
-
|
|
36
|
-
readonly submitOnEnter: import("@angular/core").WritableSignal<boolean>;
|
|
47
|
+
readonly submitOnEnter: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
37
48
|
/**
|
|
38
49
|
* Opt in to the "centered composer when empty" layout: the composer sits
|
|
39
50
|
* vertically centered with the `[slot='empty-state']` content above it while
|
|
@@ -41,21 +52,27 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
41
52
|
* Off by default — additive (adds the `--auto-center` modifier + a
|
|
42
53
|
* `data-aparte-empty` attribute the shipped `aparte.css` recipe keys off).
|
|
43
54
|
*/
|
|
44
|
-
|
|
45
|
-
readonly centerWhenEmpty: import("@angular/core").WritableSignal<boolean>;
|
|
55
|
+
readonly centerWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
46
56
|
/**
|
|
47
57
|
* The conversation is on its way: the viewport draws two skeleton turns, the empty
|
|
48
58
|
* state stays off and the composer is disabled until it lands. The conversation
|
|
49
59
|
* controller sets this itself while it fetches through your adapter's `loadFull()`;
|
|
50
60
|
* the input is for a wait of your own. Off by default.
|
|
51
61
|
*/
|
|
52
|
-
|
|
53
|
-
readonly loading: import("@angular/core").WritableSignal<boolean>;
|
|
62
|
+
readonly loading: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
54
63
|
/** The controller's wait (a conversation fetched through the adapter). */
|
|
55
64
|
readonly hostLoading: import("@angular/core").WritableSignal<boolean>;
|
|
56
65
|
readonly waiting: import("@angular/core").Signal<boolean>;
|
|
57
66
|
/** Bumped on every config change, so the two locale strings below follow a language switch under OnPush. */
|
|
58
67
|
private readonly _localeTick;
|
|
68
|
+
/**
|
|
69
|
+
* True until the host is built — on the server always, and in the browser only while Angular
|
|
70
|
+
* hydrates the server's HTML: the host element is then the one the server sent, still carrying
|
|
71
|
+
* the attribute. A client-only render holds nothing, so a component projected into the empty
|
|
72
|
+
* state (built in an @if, after the host binding) talks to live elements in its own
|
|
73
|
+
* ngAfterViewInit, which runs before this component's.
|
|
74
|
+
*/
|
|
75
|
+
protected readonly hydrating: import("@angular/core").WritableSignal<boolean>;
|
|
59
76
|
private _unsubscribeLocale?;
|
|
60
77
|
get loadingText(): string;
|
|
61
78
|
/**
|
|
@@ -70,11 +87,9 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
70
87
|
* selector on Angular alone. This input is that parity. Additive: the recipe's
|
|
71
88
|
* own classes stay.
|
|
72
89
|
*/
|
|
73
|
-
|
|
74
|
-
readonly containerClass: import("@angular/core").WritableSignal<string>;
|
|
90
|
+
readonly containerClass: import("@angular/core").InputSignalWithTransform<string, string | null | undefined>;
|
|
75
91
|
/** Inline style for the same div — a string or a `{ prop: value }` map. */
|
|
76
|
-
|
|
77
|
-
readonly containerStyle: import("@angular/core").WritableSignal<string | Record<string, string>>;
|
|
92
|
+
readonly containerStyle: import("@angular/core").InputSignalWithTransform<string | Record<string, string> | null, string | Record<string, string> | null | undefined>;
|
|
78
93
|
/**
|
|
79
94
|
* Overlay the composer on the transcript (the ChatGPT anatomy): the scroll
|
|
80
95
|
* surface spans the whole column, the scrollbar runs edge to edge, and the
|
|
@@ -83,8 +98,7 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
83
98
|
* core's recipe and the viewport's measurement both key on the attribute
|
|
84
99
|
* there. Read when the viewport mounts.
|
|
85
100
|
*/
|
|
86
|
-
|
|
87
|
-
readonly overlayComposer: import("@angular/core").WritableSignal<boolean>;
|
|
101
|
+
readonly overlayComposer: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
88
102
|
/**
|
|
89
103
|
* Add the file picker + chips strip to the default composer shell. **Off by
|
|
90
104
|
* default**, because the capability needs a host that consumes the files: an
|
|
@@ -94,8 +108,7 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
94
108
|
* project a `[slot='composer']` (drop `<aparte-composer-add-attachment>` and
|
|
95
109
|
* `<aparte-composer-attachments>` in it yourself).
|
|
96
110
|
*/
|
|
97
|
-
|
|
98
|
-
readonly attachments: import("@angular/core").WritableSignal<boolean>;
|
|
111
|
+
readonly attachments: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
99
112
|
/**
|
|
100
113
|
* Render the `<aparte-elicitation>` presenter inside the host — on by default, as
|
|
101
114
|
* it is in `<aparte-chat>`: the built-in approval gate and `requestUserInput()`
|
|
@@ -103,46 +116,47 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
103
116
|
* when you mount a presenter of your own (`setElicitationPresenter`) or place the
|
|
104
117
|
* element yourself.
|
|
105
118
|
*/
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
set isTypingInput(val: boolean);
|
|
119
|
+
readonly elicitation: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
120
|
+
/** Whether the assistant is currently typing/streaming. The host turns it off on the first token. */
|
|
121
|
+
readonly isTypingInput: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
110
122
|
readonly isTyping: import("@angular/core").WritableSignal<boolean>;
|
|
111
123
|
/** Text to show in the typing status */
|
|
112
|
-
|
|
113
|
-
readonly typingText: import("@angular/core").WritableSignal<string>;
|
|
124
|
+
readonly typingText: import("@angular/core").InputSignal<string | undefined>;
|
|
114
125
|
/** The status line's word: the input, else the locale's, like the rest of the chat. */
|
|
115
126
|
get typingLabel(): string;
|
|
116
|
-
/** Duration in ms to freeze spacer recalculation after a conversation swap. */
|
|
117
|
-
layoutTransitionMs: number
|
|
127
|
+
/** Duration in ms to freeze spacer recalculation after a conversation swap. Read when the host is created. */
|
|
128
|
+
readonly layoutTransitionMs: import("@angular/core").InputSignalWithTransform<number, unknown>;
|
|
118
129
|
/**
|
|
119
130
|
* Active conversation id. When provided, the host attaches an
|
|
120
131
|
* `AparteConversationController` that loads/persists messages via the
|
|
121
132
|
* `AparteConversationManager` registered in `aparteGlobalConfig`. Setting a different id
|
|
122
133
|
* mid-stream aborts the previous request; `null` deselects.
|
|
123
134
|
*/
|
|
124
|
-
|
|
135
|
+
readonly conversationIdInput: import("@angular/core").InputSignal<string | null | undefined>;
|
|
125
136
|
private _conversationId;
|
|
126
137
|
/**
|
|
127
138
|
* Instance {@link AparteConfig} for this chat. When set, aparté components
|
|
128
139
|
* inside resolve THIS config instead of `aparteGlobalConfig`, so
|
|
129
140
|
* several independently-configured chats can coexist on one page. Omit for the
|
|
130
|
-
* global config. Read once
|
|
141
|
+
* global config. Read once, when the host is created after the first render.
|
|
131
142
|
*/
|
|
132
|
-
config
|
|
143
|
+
readonly config: import("@angular/core").InputSignal<AparteConfig | undefined>;
|
|
133
144
|
/**
|
|
134
145
|
* Render your OWN element per message in place of `<aparte-chat-bubble>`.
|
|
135
|
-
* Opt-in — provide a `<ng-template let-message>` and pass its ref
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
146
|
+
* Opt-in — provide a `<ng-template let-message>` and pass its ref, or write the
|
|
147
|
+
* template as content with {@link AparteBubbleDirective} (`<ng-template aparteBubble
|
|
148
|
+
* let-message>`); this input wins when both are given. Driven by the reactive
|
|
149
|
+
* `messages()` signal, so it updates live during streaming. The built-in action bar
|
|
150
|
+
* (retry/edit/branch) belongs to the native bubble; a custom bubble owns whatever it wires.
|
|
139
151
|
* @example
|
|
140
152
|
* <aparte-chat [bubbleTemplate]="tpl" />
|
|
141
153
|
* <ng-template #tpl let-message>{{ message.content }}</ng-template>
|
|
142
154
|
*/
|
|
143
|
-
bubbleTemplate
|
|
155
|
+
readonly bubbleTemplate: import("@angular/core").InputSignal<TemplateRef<{
|
|
144
156
|
$implicit: AparteMessage;
|
|
145
|
-
}>;
|
|
157
|
+
}> | undefined>;
|
|
158
|
+
/** The `<ng-template aparteBubble>` written as content, if any. */
|
|
159
|
+
readonly bubbleDirective: import("@angular/core").Signal<AparteBubbleDirective | undefined>;
|
|
146
160
|
/**
|
|
147
161
|
* User submitted a message from the composer. It is **appended to the thread
|
|
148
162
|
* automatically** (optimistic UI) before this fires — do NOT add it again in
|
|
@@ -173,13 +187,15 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
173
187
|
readonly isStreaming: import("@angular/core").Signal<boolean>;
|
|
174
188
|
/** rAF id used to coalesce rapid signal updates during streaming */
|
|
175
189
|
private _syncRafId;
|
|
176
|
-
/** The framework-agnostic chat-host orchestrator (created in
|
|
190
|
+
/** The framework-agnostic chat-host orchestrator (created after the first render, in the browser). */
|
|
177
191
|
private _host?;
|
|
178
192
|
private _unbindHost?;
|
|
179
193
|
/** QueryList.changes subscription — released in ngOnDestroy so SPA route
|
|
180
194
|
* churn doesn't leak a live subscription per mount. */
|
|
181
195
|
private _bubbleRefsSub?;
|
|
182
|
-
|
|
196
|
+
/** Set by ngOnDestroy: an afterNextRender that lands after a destroy must not build a host. */
|
|
197
|
+
private _destroyed;
|
|
198
|
+
private _createHost;
|
|
183
199
|
private readonly _onAction;
|
|
184
200
|
ngOnDestroy(): void;
|
|
185
201
|
/** Append a message optimistically — `{ historical: true }` for one restored from your own store. */
|
|
@@ -248,14 +264,5 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
248
264
|
/** Handle aparte-send event from the composer Web Component. */
|
|
249
265
|
onAparteSend(event: Event): void;
|
|
250
266
|
static ɵfac: i0.ɵɵFactoryDeclaration<AparteChatComponent, never>;
|
|
251
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<AparteChatComponent, "aparte-chat", never, { "messagesInput": { "alias": "messages"; "required": false; }; "
|
|
252
|
-
static ngAcceptInputType_disabledInput: unknown;
|
|
253
|
-
static ngAcceptInputType_submitOnEnterInput: unknown;
|
|
254
|
-
static ngAcceptInputType_centerWhenEmptyInput: unknown;
|
|
255
|
-
static ngAcceptInputType_loadingInput: unknown;
|
|
256
|
-
static ngAcceptInputType_overlayComposerInput: unknown;
|
|
257
|
-
static ngAcceptInputType_attachmentsInput: unknown;
|
|
258
|
-
static ngAcceptInputType_elicitationInput: unknown;
|
|
259
|
-
static ngAcceptInputType_isTypingInput: unknown;
|
|
260
|
-
static ngAcceptInputType_layoutTransitionMs: unknown;
|
|
267
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AparteChatComponent, "aparte-chat", never, { "messagesInput": { "alias": "messages"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "submitOnEnter": { "alias": "submitOnEnter"; "required": false; "isSignal": true; }; "centerWhenEmpty": { "alias": "centerWhenEmpty"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "containerClass": { "alias": "containerClass"; "required": false; "isSignal": true; }; "containerStyle": { "alias": "containerStyle"; "required": false; "isSignal": true; }; "overlayComposer": { "alias": "overlayComposer"; "required": false; "isSignal": true; }; "attachments": { "alias": "attachments"; "required": false; "isSignal": true; }; "elicitation": { "alias": "elicitation"; "required": false; "isSignal": true; }; "isTypingInput": { "alias": "isTyping"; "required": false; "isSignal": true; }; "typingText": { "alias": "typingText"; "required": false; "isSignal": true; }; "layoutTransitionMs": { "alias": "layoutTransitionMs"; "required": false; "isSignal": true; }; "conversationIdInput": { "alias": "conversationId"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; "bubbleTemplate": { "alias": "bubbleTemplate"; "required": false; "isSignal": true; }; }, { "messageSent": "messageSent"; "action": "action"; "messagesChange": "messagesChange"; "messageAppended": "messageAppended"; "typingChange": "typingChange"; "conversationCreated": "conversationCreated"; }, ["bubbleDirective"], ["[slot='empty-state']", "[slot='above-composer']", "[slot='toolbar']", "[slot='composer']"], true, never>;
|
|
261
268
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type AparteConfig, type AparteSegmentBase, type AparteToolCallView, type AparteToolMatcher } from '@aparte/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Draws a tool call with your own template, for as long as the template is in the page.
|
|
5
|
+
*
|
|
6
|
+
* ```html
|
|
7
|
+
* <ng-template aparteToolUI="get_weather" let-tool>
|
|
8
|
+
* <app-weather-card [tool]="tool" />
|
|
9
|
+
* </ng-template>
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* `let-tool` is an `AparteToolCallView`; its `input` is the model's arguments, `unknown` until
|
|
13
|
+
* the card narrows it — give the card the view (`input.required<AparteToolCallView>()`) and type
|
|
14
|
+
* its arguments there.
|
|
15
|
+
*
|
|
16
|
+
* Every `get_weather` call is drawn with the template, the call's view as `$implicit`, and
|
|
17
|
+
* given back to core's row when the template leaves. The view is created where you declare
|
|
18
|
+
* the template, so the components in it inject what your app provides there. Underneath it is
|
|
19
|
+
* core's `overrideToolRenderer` + `defineMountedToolRenderer`; nothing is declared in a server
|
|
20
|
+
* render, and the cards are drawn in the browser.
|
|
21
|
+
*/
|
|
22
|
+
export declare class AparteToolUIDirective {
|
|
23
|
+
/** The tool this draws: a name, a `RegExp`, or `'*'` for every tool. */
|
|
24
|
+
readonly name: import("@angular/core").InputSignal<AparteToolMatcher>;
|
|
25
|
+
/** The config to declare it on. Defaults to the global one. */
|
|
26
|
+
readonly config: import("@angular/core").InputSignal<AparteConfig | undefined>;
|
|
27
|
+
private readonly template;
|
|
28
|
+
private readonly container;
|
|
29
|
+
constructor();
|
|
30
|
+
/** Types `let-tool` in a strict template. */
|
|
31
|
+
static ngTemplateContextGuard(_dir: AparteToolUIDirective, _ctx: unknown): _ctx is {
|
|
32
|
+
$implicit: AparteToolCallView;
|
|
33
|
+
};
|
|
34
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AparteToolUIDirective, never>;
|
|
35
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteToolUIDirective, "ng-template[aparteToolUI]", never, { "name": { "alias": "aparteToolUI"; "required": true; "isSignal": true; }; "config": { "alias": "aparteToolUIConfig"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Draws a segment type with your own template — one your stream emits, or a built-in such as
|
|
39
|
+
* `code` — the segment as `$implicit`. Taking the last declaration off a built-in type gives it
|
|
40
|
+
* back to core's renderer.
|
|
41
|
+
*
|
|
42
|
+
* ```html
|
|
43
|
+
* <ng-template aparteSegmentUI="chart" let-segment>
|
|
44
|
+
* <app-chart [segment]="segment" />
|
|
45
|
+
* </ng-template>
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* `let-segment` is the base segment with its own fields: the component it is handed to types it.
|
|
49
|
+
*/
|
|
50
|
+
export declare class AparteSegmentUIDirective {
|
|
51
|
+
/** The segment `type` this draws. */
|
|
52
|
+
readonly type: import("@angular/core").InputSignal<string>;
|
|
53
|
+
/** The config to declare it on. Defaults to the global one. */
|
|
54
|
+
readonly config: import("@angular/core").InputSignal<AparteConfig | undefined>;
|
|
55
|
+
private readonly template;
|
|
56
|
+
private readonly container;
|
|
57
|
+
constructor();
|
|
58
|
+
static ngTemplateContextGuard(_dir: AparteSegmentUIDirective, _ctx: unknown): _ctx is {
|
|
59
|
+
$implicit: AparteSegmentBase & Record<string, unknown>;
|
|
60
|
+
};
|
|
61
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AparteSegmentUIDirective, never>;
|
|
62
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteSegmentUIDirective, "ng-template[aparteSegmentUI]", never, { "type": { "alias": "aparteSegmentUI"; "required": true; "isSignal": true; }; "config": { "alias": "aparteSegmentUIConfig"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
63
|
+
}
|
|
@@ -76,6 +76,13 @@ export declare class AparteUiComponent implements AfterViewInit, OnChanges, OnDe
|
|
|
76
76
|
readonly elementEvent: import("@angular/core").OutputEmitterRef<CustomEvent<any>>;
|
|
77
77
|
/** The dynamically created Web Component element */
|
|
78
78
|
private element;
|
|
79
|
+
/**
|
|
80
|
+
* On a server the element is not built: it would be serialized into the HTML without its
|
|
81
|
+
* props or listeners, hydration would keep it, and the browser would append its own beside
|
|
82
|
+
* it — two counters, two pickers. React, Vue and Svelte build theirs in an effect or onMount,
|
|
83
|
+
* which a server never runs.
|
|
84
|
+
*/
|
|
85
|
+
private readonly isBrowser;
|
|
79
86
|
/** Cleanup functions for event listeners */
|
|
80
87
|
private eventCleanups;
|
|
81
88
|
/** Joined key of the bound event set, so a fresh inline `[events]` array
|
|
@@ -30,9 +30,9 @@ export declare class ConversationManagerService implements OnDestroy {
|
|
|
30
30
|
/** Archived conversations, newest first. */
|
|
31
31
|
readonly archivedConversations: import("@angular/core").Signal<AparteConversation[]>;
|
|
32
32
|
/** Currently active conversation id. */
|
|
33
|
-
readonly activeId: import("@angular/core").WritableSignal<string>;
|
|
33
|
+
readonly activeId: import("@angular/core").WritableSignal<string | null>;
|
|
34
34
|
/** The active conversation object (null when no conv is selected). */
|
|
35
|
-
readonly activeConversation: import("@angular/core").Signal<AparteConversation>;
|
|
35
|
+
readonly activeConversation: import("@angular/core").Signal<AparteConversation | null>;
|
|
36
36
|
/**
|
|
37
37
|
* Initialise the service with a storage adapter.
|
|
38
38
|
* Call once in your root component or app initialiser.
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aparte/angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"homepage": "https://apartejs.dev/frameworks/angular/",
|
|
5
|
-
"description": "Angular
|
|
5
|
+
"description": "Angular wrapper for aparté (Angular 19.2 to 21, zone or zoneless) — an ergonomic <aparte-chat> component plus services over the framework-agnostic web components.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"main": "./dist/fesm2022/aparte-angular.mjs",
|
|
@@ -28,25 +28,26 @@
|
|
|
28
28
|
"node": ">=18"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@angular/common": "^19.2.0",
|
|
32
|
-
"@angular/core": "^19.2.0",
|
|
33
|
-
"@aparte/core": ">=0.
|
|
31
|
+
"@angular/common": "^19.2.0 || ^20.0.0 || ^21.0.0",
|
|
32
|
+
"@angular/core": "^19.2.0 || ^20.0.0 || ^21.0.0",
|
|
33
|
+
"@aparte/core": ">=0.26.0 <1.0.0",
|
|
34
34
|
"rxjs": "^7.8.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@analogjs/vitest-angular": "^2.2.2",
|
|
38
37
|
"@angular/common": "^19.2.0",
|
|
39
38
|
"@angular/compiler": "^19.2.0",
|
|
40
39
|
"@angular/compiler-cli": "^19.2.0",
|
|
41
40
|
"@angular/core": "^19.2.0",
|
|
42
41
|
"@angular/platform-browser": "^19.2.0",
|
|
42
|
+
"@angular/platform-server": "^19.2.0",
|
|
43
43
|
"jsdom": "^22.1.0",
|
|
44
44
|
"ng-packagr": "^19.2.0",
|
|
45
45
|
"rxjs": "^7.8.2",
|
|
46
46
|
"typescript": "^5.4.0",
|
|
47
47
|
"vite": "^6.0.0",
|
|
48
48
|
"zone.js": "~0.15.0",
|
|
49
|
-
"@aparte/core": "0.
|
|
49
|
+
"@aparte/core": "0.26.0",
|
|
50
|
+
"@aparte/provider-scenario": "0.26.0"
|
|
50
51
|
},
|
|
51
52
|
"keywords": [
|
|
52
53
|
"angular",
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
"url": "https://github.com/apartejs/aparte/issues"
|
|
68
69
|
},
|
|
69
70
|
"scripts": {
|
|
70
|
-
"build": "ng-packagr -p ng-package.json && node ../../../scripts/stamp-dist.mjs",
|
|
71
|
+
"build": "ng-packagr -p ng-package.json -c tsconfig.lib.json && node ../../../scripts/stamp-dist.mjs",
|
|
71
72
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
72
73
|
"typecheck:tests": "tsc -p tsconfig.spec.json --noEmit",
|
|
73
74
|
"test": "vitest",
|