@newheap/platform-ai-chat 0.4.0 → 0.6.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/fesm2022/newheap-platform-ai-chat-admin.mjs +21 -21
- package/fesm2022/newheap-platform-ai-chat-testing.mjs +323 -18
- package/fesm2022/newheap-platform-ai-chat-testing.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat.mjs +1977 -364
- package/fesm2022/newheap-platform-ai-chat.mjs.map +1 -1
- package/i18n/en.json +92 -9
- package/i18n/nl.json +92 -9
- package/index.d.ts +547 -38
- package/package.json +5 -1
- package/push/nh-assistant-push-worker.js +70 -0
- package/testing/index.d.ts +102 -11
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newheap/platform-ai-chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/cdk": "^20.2.14",
|
|
6
6
|
"@angular/common": "^20.3.28",
|
|
7
7
|
"@angular/core": "^20.3.28",
|
|
8
8
|
"@angular/router": "^20.3.28",
|
|
9
|
+
"@microsoft/signalr": "^10.0.11",
|
|
9
10
|
"@ngx-translate/core": "^17.0.0",
|
|
10
11
|
"dompurify": "^3.4.0",
|
|
11
12
|
"marked": "^18.0.0",
|
|
@@ -19,6 +20,9 @@
|
|
|
19
20
|
"./i18n/*.json": {
|
|
20
21
|
"default": "./i18n/*.json"
|
|
21
22
|
},
|
|
23
|
+
"./push/*": {
|
|
24
|
+
"default": "./push/*"
|
|
25
|
+
},
|
|
22
26
|
"./package.json": {
|
|
23
27
|
"default": "./package.json"
|
|
24
28
|
},
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Web Push worker of @newheap/platform-ai-chat.
|
|
3
|
+
*
|
|
4
|
+
* Copy this file into the application's assets, for example to /nh-assistant/, and set
|
|
5
|
+
* `push.serviceWorkerUrl` in `provideNhAssistant`. The assistant registers it with its own
|
|
6
|
+
* scope, so it never controls pages and does not conflict with an application service worker.
|
|
7
|
+
*
|
|
8
|
+
* It shows a notification only when no window of the application is focused; otherwise it
|
|
9
|
+
* forwards the message to the open windows, which already show the conversation live. A click
|
|
10
|
+
* focuses an open window and opens the conversation there, or opens `app` with the conversation
|
|
11
|
+
* in the URL fragment. Notifications carry a conversation id and short texts only.
|
|
12
|
+
*/
|
|
13
|
+
const settings = new URL(self.location.href).searchParams;
|
|
14
|
+
const appUrl = settings.get('app') || '/';
|
|
15
|
+
const iconUrl = settings.get('icon') || undefined;
|
|
16
|
+
|
|
17
|
+
self.addEventListener('install', () => self.skipWaiting());
|
|
18
|
+
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()));
|
|
19
|
+
|
|
20
|
+
self.addEventListener('push', event => {
|
|
21
|
+
let payload = null;
|
|
22
|
+
try {
|
|
23
|
+
payload = event.data ? event.data.json() : null;
|
|
24
|
+
} catch {
|
|
25
|
+
payload = null;
|
|
26
|
+
}
|
|
27
|
+
if (!payload || payload.type !== 'nh-assistant' || typeof payload.conversationId !== 'string') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
event.waitUntil((async () => {
|
|
32
|
+
const windows = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
|
|
33
|
+
if (windows.some(client => client.focused && client.visibilityState === 'visible')) {
|
|
34
|
+
for (const client of windows) {
|
|
35
|
+
client.postMessage({ type: 'nh-assistant.push', kind: payload.kind, conversationId: payload.conversationId });
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await self.registration.showNotification(String(payload.title || ''), {
|
|
41
|
+
body: String(payload.body || ''),
|
|
42
|
+
tag: String(payload.tag || `nh-assistant:${payload.conversationId}`),
|
|
43
|
+
renotify: true,
|
|
44
|
+
icon: iconUrl,
|
|
45
|
+
data: { conversationId: payload.conversationId }
|
|
46
|
+
});
|
|
47
|
+
})());
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
self.addEventListener('notificationclick', event => {
|
|
51
|
+
event.notification.close();
|
|
52
|
+
const conversationId = event.notification.data && event.notification.data.conversationId;
|
|
53
|
+
if (typeof conversationId !== 'string') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
event.waitUntil((async () => {
|
|
58
|
+
const windows = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
|
|
59
|
+
const target = windows.find(client => client.focused) || windows[0];
|
|
60
|
+
if (target) {
|
|
61
|
+
await target.focus();
|
|
62
|
+
target.postMessage({ type: 'nh-assistant.open-conversation', conversationId });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const url = new URL(appUrl, self.location.origin);
|
|
67
|
+
url.hash = `nh-assistant-conversation=${encodeURIComponent(conversationId)}`;
|
|
68
|
+
await self.clients.openWindow(url.href);
|
|
69
|
+
})());
|
|
70
|
+
});
|
package/testing/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { AssistantStatus, AgentSummary, Conversation, ClientContext, AssistantPreferences, ToolCatalogEntry, AdminAgentInput, McpServerInput } from '@newheap/platform-ai-chat';
|
|
2
|
-
import * as
|
|
1
|
+
import { AssistantStatus, AgentSummary, Conversation, ClientContext, AssistantPreferences, ToolCatalogEntry, AdminAgentInput, McpServerInput, LiveConversationChanged, LiveConversationRead, LiveConversationRemoved, LiveConversationEvent, NhAssistantLiveService, NhAssistantLiveState } from '@newheap/platform-ai-chat';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
3
|
import { InjectionToken, EnvironmentProviders } from '@angular/core';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
4
5
|
|
|
5
6
|
/** Streams text as `message.delta` events, split into word-sized pieces. */
|
|
6
7
|
interface NhAssistantMockTextStep {
|
|
@@ -112,6 +113,25 @@ interface NhAssistantMockAdminScenario {
|
|
|
112
113
|
/** Hosts that may receive the user's token (`forward-user-token`). Default: none. */
|
|
113
114
|
forwardUserTokenHosts?: string[];
|
|
114
115
|
}
|
|
116
|
+
/** A person in the simulated organization. */
|
|
117
|
+
interface NhAssistantMockPerson {
|
|
118
|
+
actorId: string;
|
|
119
|
+
displayName: string;
|
|
120
|
+
/** Short distinguishing text the directory shows, such as a department. */
|
|
121
|
+
detail?: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Sharing, live updates and notifications of the mock. The mock always offers invitation links
|
|
125
|
+
* and live updates; with `directory` it also offers direct invitations.
|
|
126
|
+
*/
|
|
127
|
+
interface NhAssistantMockCollaboration {
|
|
128
|
+
/** The signed-in user. Default `{ actorId: 'mock-user', displayName: 'You' }`. */
|
|
129
|
+
currentUser?: NhAssistantMockPerson;
|
|
130
|
+
/** Colleagues the directory finds; enables direct invitations. */
|
|
131
|
+
directory?: NhAssistantMockPerson[];
|
|
132
|
+
/** Default 20. */
|
|
133
|
+
maxParticipants?: number;
|
|
134
|
+
}
|
|
115
135
|
/** The scenario the mock API plays without a back-end. */
|
|
116
136
|
interface NhAssistantMockScenario {
|
|
117
137
|
/** Default `true`. */
|
|
@@ -126,6 +146,7 @@ interface NhAssistantMockScenario {
|
|
|
126
146
|
/** Stored preferences of the caller. Default: default style, informal, normal length. */
|
|
127
147
|
preferences?: AssistantPreferences;
|
|
128
148
|
admin?: NhAssistantMockAdminScenario;
|
|
149
|
+
collaboration?: NhAssistantMockCollaboration;
|
|
129
150
|
}
|
|
130
151
|
/** One request the mock API received, for assertions in tests. */
|
|
131
152
|
interface NhAssistantMockRequest {
|
|
@@ -136,6 +157,22 @@ interface NhAssistantMockRequest {
|
|
|
136
157
|
}
|
|
137
158
|
|
|
138
159
|
declare const NH_ASSISTANT_MOCK_SCENARIO: InjectionToken<NhAssistantMockScenario>;
|
|
160
|
+
/** Path the mock reports as hub; the mock live service answers it in memory. */
|
|
161
|
+
declare const NH_ASSISTANT_MOCK_HUB_PATH = "/hub/assistant-mock";
|
|
162
|
+
/** One live update of the mock, as the assistant hub would send it. */
|
|
163
|
+
type NhAssistantMockLiveMessage = {
|
|
164
|
+
kind: 'changed';
|
|
165
|
+
data: LiveConversationChanged;
|
|
166
|
+
} | {
|
|
167
|
+
kind: 'read';
|
|
168
|
+
data: LiveConversationRead;
|
|
169
|
+
} | {
|
|
170
|
+
kind: 'removed';
|
|
171
|
+
data: LiveConversationRemoved;
|
|
172
|
+
} | {
|
|
173
|
+
kind: 'event';
|
|
174
|
+
data: LiveConversationEvent;
|
|
175
|
+
};
|
|
139
176
|
/**
|
|
140
177
|
* In-memory implementation of the assistant HTTP API and its event streams. It keeps
|
|
141
178
|
* conversations, plays scripted turns as contract events through a real
|
|
@@ -152,12 +189,27 @@ declare class NhAssistantMockBackend {
|
|
|
152
189
|
private readonly enabledState;
|
|
153
190
|
private readonly admin;
|
|
154
191
|
private readonly canAdministerState;
|
|
192
|
+
private readonly currentUser;
|
|
193
|
+
private readonly members;
|
|
194
|
+
private readonly readPositions;
|
|
195
|
+
private readonly shareTokens;
|
|
196
|
+
private readonly activeActors;
|
|
197
|
+
private readonly liveSubject;
|
|
198
|
+
private pushEnabled;
|
|
155
199
|
private sequence;
|
|
156
200
|
/** Requests received so far, oldest first. */
|
|
157
201
|
readonly requests: NhAssistantMockRequest[];
|
|
158
|
-
readonly enabled:
|
|
159
|
-
readonly canAdminister:
|
|
202
|
+
readonly enabled: i0.Signal<boolean>;
|
|
203
|
+
readonly canAdminister: i0.Signal<boolean>;
|
|
204
|
+
/** Live updates for the mock live service, in the order the hub would send them. */
|
|
205
|
+
readonly live$: Observable<NhAssistantMockLiveMessage>;
|
|
160
206
|
constructor();
|
|
207
|
+
/**
|
|
208
|
+
* Plays a scripted turn as another person in the conversation, as if a colleague with an
|
|
209
|
+
* invitation sent a message: the conversation becomes shared, and the message and the
|
|
210
|
+
* answer arrive as live updates. Resolves when the turn ends.
|
|
211
|
+
*/
|
|
212
|
+
simulateParticipantTurn(conversationId: string, person: NhAssistantMockPerson, text: string): Promise<void>;
|
|
161
213
|
/** Switches the simulated `NewHeap:AI:Assistant:Enabled` flag. */
|
|
162
214
|
setEnabled(enabled: boolean): void;
|
|
163
215
|
/** Switches whether the caller passes the admin policy (`canAdminister`, `admin/*`). */
|
|
@@ -177,22 +229,61 @@ declare class NhAssistantMockBackend {
|
|
|
177
229
|
private stream;
|
|
178
230
|
private findTurn;
|
|
179
231
|
private update;
|
|
232
|
+
/** The conversation as the signed-in user sees it. */
|
|
233
|
+
private view;
|
|
234
|
+
private summary;
|
|
235
|
+
private markRead;
|
|
236
|
+
private candidates;
|
|
237
|
+
private invite;
|
|
238
|
+
private addMember;
|
|
239
|
+
private removeMember;
|
|
240
|
+
private emitChanged;
|
|
241
|
+
private emitLive;
|
|
242
|
+
private maxParticipants;
|
|
243
|
+
private error;
|
|
180
244
|
private nextId;
|
|
181
245
|
private result;
|
|
182
246
|
private json;
|
|
183
247
|
private empty;
|
|
184
|
-
static ɵfac:
|
|
185
|
-
static ɵprov:
|
|
248
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NhAssistantMockBackend, never>;
|
|
249
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NhAssistantMockBackend>;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
type NhAssistantLiveSurface = Pick<NhAssistantLiveService, 'changed$' | 'read$' | 'removed$' | 'events$' | 'resync$' | 'state' | 'connect' | 'stop'>;
|
|
253
|
+
/**
|
|
254
|
+
* Stands in for the SignalR live service: it delivers the mock back-end's live updates in
|
|
255
|
+
* memory, so shared conversations, other tabs and parallel turns behave as with a real hub.
|
|
256
|
+
*/
|
|
257
|
+
declare class NhAssistantMockLiveService implements NhAssistantLiveSurface {
|
|
258
|
+
private readonly backend;
|
|
259
|
+
private readonly changedSubject;
|
|
260
|
+
private readonly readSubject;
|
|
261
|
+
private readonly removedSubject;
|
|
262
|
+
private readonly eventSubject;
|
|
263
|
+
private readonly resyncSubject;
|
|
264
|
+
private readonly stateSignal;
|
|
265
|
+
private subscription?;
|
|
266
|
+
readonly changed$: Observable<LiveConversationChanged>;
|
|
267
|
+
readonly read$: Observable<LiveConversationRead>;
|
|
268
|
+
readonly removed$: Observable<LiveConversationRemoved>;
|
|
269
|
+
readonly events$: Observable<LiveConversationEvent>;
|
|
270
|
+
readonly resync$: Observable<void>;
|
|
271
|
+
readonly state: i0.Signal<NhAssistantLiveState>;
|
|
272
|
+
constructor();
|
|
273
|
+
connect(hubPath: string | null): Promise<void>;
|
|
274
|
+
stop(): Promise<void>;
|
|
275
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NhAssistantMockLiveService, never>;
|
|
276
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NhAssistantMockLiveService>;
|
|
186
277
|
}
|
|
187
278
|
|
|
188
279
|
/**
|
|
189
280
|
* Replaces the assistant transport with an in-memory back-end that plays `script`.
|
|
190
281
|
* Register it after `provideNhAssistant(...)` in the same injector. Every client feature
|
|
191
|
-
* (status, agents, conversations, streamed turns, approvals, cancellation
|
|
192
|
-
* without a server. Inject `NhAssistantMockBackend` to
|
|
193
|
-
* inspect the received requests.
|
|
282
|
+
* (status, agents, conversations, streamed turns, approvals, cancellation, sharing, read
|
|
283
|
+
* state and live updates) then works without a server. Inject `NhAssistantMockBackend` to
|
|
284
|
+
* switch the feature flag, simulate a colleague or inspect the received requests.
|
|
194
285
|
*/
|
|
195
286
|
declare function provideNhAssistantMockApi(script: NhAssistantMockScenario): EnvironmentProviders;
|
|
196
287
|
|
|
197
|
-
export { NH_ASSISTANT_MOCK_SCENARIO, NhAssistantMockBackend, provideNhAssistantMockApi };
|
|
198
|
-
export type { NhAssistantMockAdminAgent, NhAssistantMockAdminScenario, NhAssistantMockApprovalStep, NhAssistantMockErrorStep, NhAssistantMockFailStep, NhAssistantMockMcpServer, NhAssistantMockRemoteTool, NhAssistantMockRequest, NhAssistantMockScenario, NhAssistantMockStep, NhAssistantMockTextStep, NhAssistantMockTiming, NhAssistantMockToolStep, NhAssistantMockTurn };
|
|
288
|
+
export { NH_ASSISTANT_MOCK_HUB_PATH, NH_ASSISTANT_MOCK_SCENARIO, NhAssistantMockBackend, NhAssistantMockLiveService, provideNhAssistantMockApi };
|
|
289
|
+
export type { NhAssistantMockAdminAgent, NhAssistantMockAdminScenario, NhAssistantMockApprovalStep, NhAssistantMockCollaboration, NhAssistantMockErrorStep, NhAssistantMockFailStep, NhAssistantMockLiveMessage, NhAssistantMockMcpServer, NhAssistantMockPerson, NhAssistantMockRemoteTool, NhAssistantMockRequest, NhAssistantMockScenario, NhAssistantMockStep, NhAssistantMockTextStep, NhAssistantMockTiming, NhAssistantMockToolStep, NhAssistantMockTurn };
|