@tagit/ai-client-core 0.4.1 → 0.6.0-beta.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 +73 -19
- package/dist/client.d.ts +16 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +138 -38
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +82 -26
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -2
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/transport.d.ts +1 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +2 -1
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +68 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/dist/client.test.d.ts +0 -2
- package/dist/client.test.d.ts.map +0 -1
- package/dist/client.test.js +0 -545
- package/dist/client.test.js.map +0 -1
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/config.test.js +0 -29
- package/dist/config.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -52,6 +52,18 @@ import { AIClient, createDefaultConfig } from '@tagit/ai-client-core';
|
|
|
52
52
|
|
|
53
53
|
const client = new AIClient(
|
|
54
54
|
createDefaultConfig('uc-default-1lji40', 'https://ai.tagit.live', {
|
|
55
|
+
user: {
|
|
56
|
+
entityId: 'anonymous-or-authenticated-user-id',
|
|
57
|
+
userId: 'optional-friendly-user-id',
|
|
58
|
+
entityidType: 'internal_user_id',
|
|
59
|
+
entityidAlgo: 'native',
|
|
60
|
+
entityidOwner: 'your-service',
|
|
61
|
+
},
|
|
62
|
+
conversation: {
|
|
63
|
+
conversationId: 'optional-durable-conversation-id',
|
|
64
|
+
title: 'Optional conversation title',
|
|
65
|
+
memoryMaxTurns: 6,
|
|
66
|
+
},
|
|
55
67
|
orchestrator: {
|
|
56
68
|
apiKey: import.meta.env.VITE_TAGIT_AI_ORCHESTRATOR_API_KEY,
|
|
57
69
|
},
|
|
@@ -68,7 +80,7 @@ const client = new AIClient(
|
|
|
68
80
|
|
|
69
81
|
`AIClient` is the stateful engine:
|
|
70
82
|
|
|
71
|
-
- builds the `/
|
|
83
|
+
- builds the `/v2/chat` request
|
|
72
84
|
- manages the conversation transcript
|
|
73
85
|
- streams assistant output
|
|
74
86
|
- retries transient failures
|
|
@@ -81,7 +93,7 @@ const client = new AIClient(
|
|
|
81
93
|
|
|
82
94
|
### `OrchestratorRequest`
|
|
83
95
|
|
|
84
|
-
`OrchestratorRequest` is the payload posted to the orchestrator `/
|
|
96
|
+
`OrchestratorRequest` is the payload posted to the orchestrator `/v2/chat` endpoint.
|
|
85
97
|
|
|
86
98
|
### `OrchestratorChunk`
|
|
87
99
|
|
|
@@ -106,14 +118,38 @@ const config = createDefaultConfig('uc-default-1lji40', 'https://ai.tagit.live',
|
|
|
106
118
|
| Field | Type / values | Default | What it does | Example |
|
|
107
119
|
|---|---|---:|---|---|
|
|
108
120
|
| `useCaseId` | `string` | required | Runtime use case identifier used by the orchestrator. | `'uc-default-1lji40'` |
|
|
109
|
-
| `orchestratorUrl` | URL string | required | Base URL for the orchestrator. Do not include `/
|
|
121
|
+
| `orchestratorUrl` | URL string | required | Base URL for the orchestrator. Do not include `/v2/chat`. | `'https://ai.tagit.live'` |
|
|
110
122
|
| `options.orchestrator` | partial orchestrator config | `undefined` | Overrides specific orchestrator fields. | `{ apiKey: '...' }` |
|
|
123
|
+
| `options.user` | user identity config | `undefined` | Shared identity used by orchestrator memory and collector events. | `{ entityId: 'user_123' }` |
|
|
124
|
+
| `options.conversation` | conversation config | `undefined` | Durable conversation id, title, and memory window. | `{ memoryMaxTurns: 6 }` |
|
|
111
125
|
| `options.collector` | partial collector config | `undefined` | Enables or customizes collector emission. | `{ enabled: false }` |
|
|
112
126
|
| `options.ui` | partial UI config | `undefined` | Overrides client UI/runtime behavior. | `{ streaming: true }` |
|
|
113
127
|
|
|
128
|
+
### Shared User Config
|
|
129
|
+
|
|
130
|
+
The `user` block is the single identity source for V2. At minimum, production integrations should provide `user.entityId`. When `user.userId` is omitted, the SDK uses `user.entityId` as the orchestrator `user_id` and collector `content.contentData.userId`.
|
|
131
|
+
|
|
132
|
+
| Field | Type / values | Required | What it does | Example |
|
|
133
|
+
|---|---|---:|---|---|
|
|
134
|
+
| `user.entityId` | string | yes for production | Primary user or anonymous entity identifier supplied by the host app. | `visitor_abc123` |
|
|
135
|
+
| `user.userId` | string | no | Optional friendly/application user id. Defaults to `entityId`. | `sandro` |
|
|
136
|
+
| `user.entityidType` | string | no | Entity type metadata for collector normalization. | `internal_user_id` |
|
|
137
|
+
| `user.entityidAlgo` | string | no | Entity ID algorithm metadata. | `native` |
|
|
138
|
+
| `user.entityidOwner` | string | no | Entity owner metadata. | `tagit.live` |
|
|
139
|
+
|
|
140
|
+
### Shared Conversation Config
|
|
141
|
+
|
|
142
|
+
The `conversation` block controls durable memory. The SDK sends only the current user message to the orchestrator; the orchestrator rehydrates recent history server-side using `conversationId` and `userId`.
|
|
143
|
+
|
|
144
|
+
| Field | Type / values | Required | What it does | Example |
|
|
145
|
+
|---|---|---:|---|---|
|
|
146
|
+
| `conversation.conversationId` | string | no | Durable conversation identifier. Generated locally when omitted. | `conv-homepage-001` |
|
|
147
|
+
| `conversation.title` | string | no | Optional user-facing title sent to the orchestrator. | `Homepage assistant` |
|
|
148
|
+
| `conversation.memoryMaxTurns` | nonnegative integer | no | Server-side recent-history window. Use `0` to disable rehydration. | `6` |
|
|
149
|
+
|
|
114
150
|
### Orchestrator Config
|
|
115
151
|
|
|
116
|
-
`orchestrator.baseUrl` should point to the orchestrator root URL, not `/
|
|
152
|
+
`orchestrator.baseUrl` should point to the orchestrator root URL, not `/v2/chat`. The client appends `/v2/chat` internally.
|
|
117
153
|
|
|
118
154
|
| Field | Type / values | Required | What it does | Example |
|
|
119
155
|
|---|---|---:|---|---|
|
|
@@ -134,17 +170,14 @@ Collector is optional and can be disabled. When enabled, the client emits a TagI
|
|
|
134
170
|
| `collector.baseUrl` | URL string | yes | Collector endpoint base URL. | `https://collector.tagit.live` |
|
|
135
171
|
| `collector.tagId` | string | yes | Tag identifier used to route and classify collector events. | `tagit-site-demo` |
|
|
136
172
|
| `collector.acceptCookies` | `boolean` | no | Whether the widget should request/set cookies when emitting collector events. | `true` |
|
|
137
|
-
| `collector.
|
|
138
|
-
| `collector.
|
|
139
|
-
| `collector.
|
|
140
|
-
| `collector.entityidType` | string | no | Entity type metadata. | `account` |
|
|
141
|
-
| `collector.entityidAlgo` | string | no | Entity ID algorithm metadata. | `sha256` |
|
|
142
|
-
| `collector.entityidOwner` | string | no | Entity owner metadata. | `tagit` |
|
|
143
|
-
| `collector.spaceId` | string | no | Optional space/context identifier. | `website-homepage` |
|
|
144
|
-
| `collector.sessionId` | string | no | Optional session identifier. | `session_abc123` |
|
|
173
|
+
| `collector.agentId` | string | no | Optional collector agent identity. Defaults to the request use case id. | `uc-default-1lji40` |
|
|
174
|
+
| `collector.eventSubContext` | string | no | Optional sub-context identifier for the event surface. | `website-homepage` |
|
|
175
|
+
| `collector.sessionId` | string | no | Optional collector session identifier. It is not the primary durable conversation id when `conversation.conversationId` exists. | `session_abc123` |
|
|
145
176
|
| `collector.privacy.jurisdiction` | string | no | Privacy jurisdiction metadata. | `US-CA` |
|
|
146
177
|
| `collector.privacy.purposesConsent.analytics` | `boolean` | no | Consent flag for analytics collection. | `true` |
|
|
147
178
|
|
|
179
|
+
Legacy collector identity fields are still accepted for migration compatibility, but new integrations should put identity in the shared `user` block.
|
|
180
|
+
|
|
148
181
|
### UI Config
|
|
149
182
|
|
|
150
183
|
| Field | Type / values | Default | What it does | Example |
|
|
@@ -177,7 +210,7 @@ const client = new AIClient(config, options);
|
|
|
177
210
|
| `on(listener)` | `(): () => void` | Subscribes to client events and returns an unsubscribe function. | `client.on(handleEvent)` |
|
|
178
211
|
| `sendMessage()` | `(message, options?) => Promise<void>` | Sends a user message and streams the orchestrator response. | `await client.sendMessage('Hello')` |
|
|
179
212
|
| `cancel()` | `(): void` | Cancels the current in-flight request. | `client.cancel()` |
|
|
180
|
-
| `clearHistory()` | `(): void` | Clears the transcript
|
|
213
|
+
| `clearHistory()` | `(): void` | Clears the local transcript. If `conversation.conversationId` is configured, the durable id is preserved. | `client.clearHistory()` |
|
|
181
214
|
| `trimHistoryBefore()` | `(messageId) => string \| null` | Removes a message and everything after it. | `client.trimHistoryBefore(id)` |
|
|
182
215
|
|
|
183
216
|
## Message Options
|
|
@@ -188,11 +221,18 @@ const client = new AIClient(config, options);
|
|
|
188
221
|
|---|---|---|---|
|
|
189
222
|
| `tools` | `'none' \| 'all' \| string[]` | Limits which MCP tools are available for the request. | `tools: 'none'` |
|
|
190
223
|
| `useCaseMessage` | `string` | Injects an additional use-case instruction as a system message. | `useCaseMessage: 'Keep it short and direct.'` |
|
|
224
|
+
| `userId` | `string` | Overrides the resolved user id for this request. | `userId: 'request-user'` |
|
|
225
|
+
| `useCaseId` | `string` | Overrides the configured use case for this request. | `useCaseId: 'uc-other'` |
|
|
226
|
+
| `snapshotId` | `string` | Overrides the configured snapshot for this request. | `snapshotId: 'snap-123'` |
|
|
227
|
+
| `conversationId` | `string` | Overrides the durable conversation id for this request. | `conversationId: 'conv-other'` |
|
|
228
|
+
| `conversationTitle` | `string` | Overrides the conversation title for this request. | `conversationTitle: 'Support chat'` |
|
|
229
|
+
| `conversationMemoryMaxTurns` | `number` | Overrides the server-side memory window for this request. | `conversationMemoryMaxTurns: 0` |
|
|
191
230
|
|
|
192
231
|
```ts
|
|
193
232
|
await client.sendMessage('Hello', {
|
|
194
233
|
tools: 'none',
|
|
195
234
|
useCaseMessage: 'You are helping a new customer onboard.',
|
|
235
|
+
conversationMemoryMaxTurns: 6,
|
|
196
236
|
});
|
|
197
237
|
```
|
|
198
238
|
|
|
@@ -209,6 +249,11 @@ await client.sendMessage('Hello', {
|
|
|
209
249
|
| `error` | `string \| undefined` | Safe user-facing error text. | `Request timed out before completion.` |
|
|
210
250
|
| `lastError` | `ClientErrorInfo \| undefined` | Structured internal error details. | `{ code: 'TIMEOUT', ... }` |
|
|
211
251
|
| `useCaseId` | `string` | Use case currently bound to the conversation. | `uc-default-1lji40` |
|
|
252
|
+
| `workflowId` | `string \| undefined` | Latest workflow run id returned by a V2 workflow use case. | `wf_123` |
|
|
253
|
+
| `workflowStatus` | `string \| undefined` | Latest workflow status returned by the orchestrator. | `completed` |
|
|
254
|
+
| `checkpointPrompt` | `string \| undefined` | Latest checkpoint prompt returned by a workflow use case. | `Review before continuing?` |
|
|
255
|
+
|
|
256
|
+
Checkpoint action UI is not included in the beta React widget. Consumers can inspect workflow metadata from state/events and add explicit continue/revise/cancel controls in a later integration.
|
|
212
257
|
|
|
213
258
|
## Client Events
|
|
214
259
|
|
|
@@ -239,24 +284,34 @@ await client.sendMessage('Hello', {
|
|
|
239
284
|
|
|
240
285
|
## Orchestrator Request Shape
|
|
241
286
|
|
|
242
|
-
The core client posts a canonical request to `/
|
|
287
|
+
The core client posts a canonical request to `/v2/chat`.
|
|
243
288
|
|
|
244
289
|
| Field | Type / values | Required | What it does | Example |
|
|
245
290
|
|---|---|---:|---|---|
|
|
246
291
|
| `use_case_id` | string | yes | Runtime use case identifier. | `uc-default-1lji40` |
|
|
247
292
|
| `stream` | `boolean` | no | Requests SSE when `true`. | `true` |
|
|
248
|
-
| `messages` | array | yes |
|
|
293
|
+
| `messages` | array | yes | Current user message, plus optional `useCaseMessage` system instruction. Server-side memory comes from `conversation_id`. | `[{ role: 'user', content: 'Hello' }]` |
|
|
249
294
|
| `tools` | `'none' \| 'all' \| string[]` | no | Limits which tools the orchestrator may use. | `['search_docs']` |
|
|
250
295
|
| `snapshot_id` | string | no | Pins the request to a published orchestration snapshot. | `snapshot_2026_04_14` |
|
|
296
|
+
| `runtime_version` | `'v2'` | yes | Runtime contract marker sent by the client. | `v2` |
|
|
297
|
+
| `user_id` | string | yes | User id for ownership and conversation memory. | `visitor_abc123` |
|
|
298
|
+
| `conversation_id` | string | yes | Durable conversation id. | `conv-homepage-001` |
|
|
299
|
+
| `session_id` | string | no | Backward-compatible mirror of `conversation_id` during migration. | `conv-homepage-001` |
|
|
300
|
+
| `conversation_title` | string | no | Optional conversation title. | `Homepage assistant` |
|
|
301
|
+
| `conversation_memory_max_turns` | number | no | Server-side memory window. | `6` |
|
|
251
302
|
|
|
252
303
|
Example:
|
|
253
304
|
|
|
254
305
|
```ts
|
|
255
306
|
{
|
|
256
307
|
use_case_id: 'uc-default-1lji40',
|
|
308
|
+
runtime_version: 'v2',
|
|
309
|
+
user_id: 'visitor_abc123',
|
|
310
|
+
conversation_id: 'conv-homepage-001',
|
|
311
|
+
session_id: 'conv-homepage-001',
|
|
312
|
+
conversation_memory_max_turns: 6,
|
|
257
313
|
stream: true,
|
|
258
314
|
messages: [
|
|
259
|
-
{ role: 'system', content: 'Keep it short and direct.' },
|
|
260
315
|
{ role: 'user', content: 'How do I get started?' },
|
|
261
316
|
],
|
|
262
317
|
tools: 'none',
|
|
@@ -275,7 +330,7 @@ When collector emission is enabled, the client emits a conversation envelope aft
|
|
|
275
330
|
| `remember` | boolean | Signals that the event should be retained for memory processing. | `true` |
|
|
276
331
|
| `eventType` | string | High-level event class. | `conversation` |
|
|
277
332
|
| `eventSubType` | string | Specific collector subtype. | `chat_turn` |
|
|
278
|
-
| `eventSubContext` | string | Context label for the event. | `
|
|
333
|
+
| `eventSubContext` | string | Context or sub-context label for the event. | `website-homepage` |
|
|
279
334
|
| `eventGuid` | string | Unique event identifier. | `1713100000000-x8q1abcde` |
|
|
280
335
|
| `sessionId` | string | Optional session identifier. | `session_abc123` |
|
|
281
336
|
| `entityId` | string | Entity identity for the event subject. | `user_123` |
|
|
@@ -291,7 +346,6 @@ When collector emission is enabled, the client emits a conversation envelope aft
|
|
|
291
346
|
| `content.contentData.agentMessageId` | string \| null | Assistant message ID when present. | `1713100000002-z1a3cdefg` |
|
|
292
347
|
| `content.contentData.userMessage` | string | Captured user message content. | `How do I get started?` |
|
|
293
348
|
| `content.contentData.agentMessage` | string \| null | Captured assistant message content. | `Open the onboarding checklist...` |
|
|
294
|
-
| `content.contentData.spaceId` | string | Optional space identifier. | `website-homepage` |
|
|
295
349
|
|
|
296
350
|
## Transport
|
|
297
351
|
|
|
@@ -302,7 +356,7 @@ import type { OrchestratorTransport } from '@tagit/ai-client-core';
|
|
|
302
356
|
|
|
303
357
|
const transport: OrchestratorTransport = {
|
|
304
358
|
async send(request, context) {
|
|
305
|
-
return fetch(`${context.baseUrl}
|
|
359
|
+
return fetch(`${context.baseUrl}${context.endpointPath}`, {
|
|
306
360
|
method: 'POST',
|
|
307
361
|
headers: context.headers,
|
|
308
362
|
body: JSON.stringify(request),
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClientConfig, ClientEventListener, ConversationState } from './types.js';
|
|
1
|
+
import type { ClientConfig, ClientEventListener, ConversationState, SendMessageOptions } from './types.js';
|
|
2
2
|
import { type OrchestratorTransport } from './transport.js';
|
|
3
3
|
/**
|
|
4
4
|
* Headless AI client core
|
|
@@ -34,6 +34,19 @@ export declare class AIClient {
|
|
|
34
34
|
* Check if history exceeds max messages and emit warning event
|
|
35
35
|
*/
|
|
36
36
|
private checkAndTrimHistory;
|
|
37
|
+
private getEndpointPath;
|
|
38
|
+
private buildRequestMessages;
|
|
39
|
+
resolveUserId(options?: Pick<SendMessageOptions, 'userId'>): string;
|
|
40
|
+
resolveConversationId(options?: Pick<SendMessageOptions, 'conversationId'>): string;
|
|
41
|
+
hasConfiguredConversationId(): boolean;
|
|
42
|
+
getResolvedIdentity(options?: Pick<SendMessageOptions, 'userId' | 'conversationId'>): {
|
|
43
|
+
userId: string;
|
|
44
|
+
conversationId: string;
|
|
45
|
+
entityId: string;
|
|
46
|
+
entityidType: string;
|
|
47
|
+
entityidAlgo: string;
|
|
48
|
+
entityidOwner: string;
|
|
49
|
+
};
|
|
37
50
|
/**
|
|
38
51
|
* Truncate error details to prevent massive error payloads
|
|
39
52
|
*/
|
|
@@ -41,10 +54,7 @@ export declare class AIClient {
|
|
|
41
54
|
/**
|
|
42
55
|
* Send a message and stream the response
|
|
43
56
|
*/
|
|
44
|
-
sendMessage(userMessage: string, options?:
|
|
45
|
-
tools?: 'none' | 'all' | string[];
|
|
46
|
-
useCaseMessage?: string;
|
|
47
|
-
}): Promise<void>;
|
|
57
|
+
sendMessage(userMessage: string, options?: SendMessageOptions): Promise<void>;
|
|
48
58
|
private streamResponseWithRetry;
|
|
49
59
|
/**
|
|
50
60
|
* Stream response from orchestrator
|
|
@@ -65,6 +75,7 @@ export declare class AIClient {
|
|
|
65
75
|
private appendAssistantDelta;
|
|
66
76
|
private applyTerminalContent;
|
|
67
77
|
private handleNonStreamingResponse;
|
|
78
|
+
private applyWorkflowDetails;
|
|
68
79
|
private extractAssistantText;
|
|
69
80
|
private shouldAcceptDegradedCompletion;
|
|
70
81
|
private hasAssistantContent;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EAEZ,mBAAmB,EACnB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EAEZ,mBAAmB,EACnB,iBAAiB,EAMjB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AASxB;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,SAAS,CAAwB;gBAGvC,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,qBAAqB,CAAC;KACnC;IAiBH;;OAEG;IACH,QAAQ,IAAI,iBAAiB;IAI7B;;OAEG;IACH,EAAE,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAO7C;;OAEG;IACH,OAAO,CAAC,IAAI;IAUZ;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,oBAAoB;IAwB5B,aAAa,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG,MAAM;IAYnE,qBAAqB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,GAAG,MAAM;IASnF,2BAA2B,IAAI,OAAO;IAItC,mBAAmB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,gBAAgB,CAAC,GAAG;QACpF,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB;IAYD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAmB5B;;OAEG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,IAAI,CAAC;YAuDF,uBAAuB;IAyCrC;;OAEG;YACW,cAAc;IA0M5B;;OAEG;YACW,WAAW;IAqHzB;;;OAGG;YACW,mBAAmB;IA0BjC,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,oBAAoB;YA0Bd,0BAA0B;IA2CxC,OAAO,CAAC,oBAAoB;IA+C5B,OAAO,CAAC,oBAAoB;IAkC5B,OAAO,CAAC,8BAA8B;IAgBtC,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,mBAAmB;IA+C3B;;OAEG;YACW,kBAAkB;IAkEhC;;OAEG;IACH,MAAM,IAAI,IAAI;IAUd;;;OAGG;IACH,YAAY,IAAI,IAAI;IAmBpB;;;;;OAKG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAWpD;AAED,eAAe,QAAQ,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -50,8 +50,11 @@ export class AIClient {
|
|
|
50
50
|
});
|
|
51
51
|
this.config = validateConfig(config);
|
|
52
52
|
this.transport = options?.transport ?? new FetchOrchestratorTransport();
|
|
53
|
+
const initialConversationId = this.config.conversation?.conversationId?.trim() ||
|
|
54
|
+
this.config.collector?.sessionId?.trim() ||
|
|
55
|
+
generateId();
|
|
53
56
|
this.conversationState = {
|
|
54
|
-
id:
|
|
57
|
+
id: initialConversationId,
|
|
55
58
|
messages: [],
|
|
56
59
|
isLoading: false,
|
|
57
60
|
isStreaming: false,
|
|
@@ -111,6 +114,56 @@ export class AIClient {
|
|
|
111
114
|
});
|
|
112
115
|
}
|
|
113
116
|
}
|
|
117
|
+
getEndpointPath() {
|
|
118
|
+
return '/v2/chat';
|
|
119
|
+
}
|
|
120
|
+
buildRequestMessages(useCaseMessage) {
|
|
121
|
+
const allMessages = this.conversationState.messages.map((msg) => ({
|
|
122
|
+
role: msg.role,
|
|
123
|
+
content: msg.content,
|
|
124
|
+
}));
|
|
125
|
+
let requestMessages = allMessages.slice(-1);
|
|
126
|
+
const trimmedUseCaseMessage = useCaseMessage?.trim();
|
|
127
|
+
if (trimmedUseCaseMessage) {
|
|
128
|
+
requestMessages = [
|
|
129
|
+
{
|
|
130
|
+
role: 'system',
|
|
131
|
+
content: trimmedUseCaseMessage,
|
|
132
|
+
},
|
|
133
|
+
...requestMessages,
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
return requestMessages;
|
|
137
|
+
}
|
|
138
|
+
resolveUserId(options) {
|
|
139
|
+
const user = this.config.user;
|
|
140
|
+
return (options?.userId?.trim() ||
|
|
141
|
+
user?.userId?.trim() ||
|
|
142
|
+
user?.entityId?.trim() ||
|
|
143
|
+
this.config.collector?.userId?.trim() ||
|
|
144
|
+
this.config.collector?.entityId?.trim() ||
|
|
145
|
+
this.conversationState.id);
|
|
146
|
+
}
|
|
147
|
+
resolveConversationId(options) {
|
|
148
|
+
return (options?.conversationId?.trim() ||
|
|
149
|
+
this.config.conversation?.conversationId?.trim() ||
|
|
150
|
+
this.config.collector?.sessionId?.trim() ||
|
|
151
|
+
this.conversationState.id);
|
|
152
|
+
}
|
|
153
|
+
hasConfiguredConversationId() {
|
|
154
|
+
return Boolean(this.config.conversation?.conversationId?.trim());
|
|
155
|
+
}
|
|
156
|
+
getResolvedIdentity(options) {
|
|
157
|
+
const userId = this.resolveUserId(options);
|
|
158
|
+
return {
|
|
159
|
+
userId,
|
|
160
|
+
conversationId: this.resolveConversationId(options),
|
|
161
|
+
entityId: this.config.user?.entityId?.trim() || this.config.collector?.entityId?.trim() || userId,
|
|
162
|
+
entityidType: this.config.user?.entityidType?.trim() || this.config.collector?.entityidType?.trim() || 'internal_user_id',
|
|
163
|
+
entityidAlgo: this.config.user?.entityidAlgo?.trim() || this.config.collector?.entityidAlgo?.trim() || 'native',
|
|
164
|
+
entityidOwner: this.config.user?.entityidOwner?.trim() || this.config.collector?.entityidOwner?.trim() || 'tagit-ai-client',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
114
167
|
/**
|
|
115
168
|
* Truncate error details to prevent massive error payloads
|
|
116
169
|
*/
|
|
@@ -156,11 +209,11 @@ export class AIClient {
|
|
|
156
209
|
this.conversationState.isLoading = true;
|
|
157
210
|
this.emit({ type: 'message_added', message: userMsg });
|
|
158
211
|
try {
|
|
159
|
-
await this.streamResponseWithRetry(options
|
|
212
|
+
await this.streamResponseWithRetry(options);
|
|
160
213
|
// Emit collector event if configured
|
|
161
214
|
if (this.config.collector?.enabled) {
|
|
162
215
|
const assistantMsg = this.findLatestAssistantMessage();
|
|
163
|
-
await this.emitCollectorEvent(userMsg, assistantMsg ?? null);
|
|
216
|
+
await this.emitCollectorEvent(userMsg, assistantMsg ?? null, options);
|
|
164
217
|
}
|
|
165
218
|
}
|
|
166
219
|
catch (error) {
|
|
@@ -183,13 +236,13 @@ export class AIClient {
|
|
|
183
236
|
this.emit({ type: 'state_synced' });
|
|
184
237
|
}
|
|
185
238
|
}
|
|
186
|
-
async streamResponseWithRetry(
|
|
239
|
+
async streamResponseWithRetry(options) {
|
|
187
240
|
const retries = this.config.orchestrator.maxRetries ?? 0;
|
|
188
241
|
const maxAttempts = Math.max(1, retries + 1);
|
|
189
242
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
190
243
|
const baselineLength = this.conversationState.messages.length;
|
|
191
244
|
try {
|
|
192
|
-
await this.streamResponse(
|
|
245
|
+
await this.streamResponse(options);
|
|
193
246
|
return;
|
|
194
247
|
}
|
|
195
248
|
catch (error) {
|
|
@@ -219,32 +272,30 @@ export class AIClient {
|
|
|
219
272
|
/**
|
|
220
273
|
* Stream response from orchestrator
|
|
221
274
|
*/
|
|
222
|
-
async streamResponse(
|
|
223
|
-
const requestMessages = this.
|
|
224
|
-
|
|
225
|
-
content: msg.content,
|
|
226
|
-
}));
|
|
227
|
-
const trimmedUseCaseMessage = useCaseMessage?.trim();
|
|
228
|
-
if (trimmedUseCaseMessage) {
|
|
229
|
-
requestMessages.unshift({
|
|
230
|
-
role: 'system',
|
|
231
|
-
content: trimmedUseCaseMessage,
|
|
232
|
-
});
|
|
233
|
-
}
|
|
275
|
+
async streamResponse(options) {
|
|
276
|
+
const requestMessages = this.buildRequestMessages(options?.useCaseMessage);
|
|
277
|
+
const endpointPath = this.getEndpointPath();
|
|
234
278
|
const request = {
|
|
235
|
-
use_case_id: this.config.orchestrator.useCaseId,
|
|
279
|
+
use_case_id: options?.useCaseId?.trim() || this.config.orchestrator.useCaseId,
|
|
236
280
|
stream: this.config.ui?.streaming ?? true,
|
|
237
281
|
messages: requestMessages,
|
|
238
282
|
};
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
283
|
+
request.runtime_version = 'v2';
|
|
284
|
+
request.conversation_id = this.resolveConversationId(options);
|
|
285
|
+
request.session_id = request.conversation_id;
|
|
286
|
+
request.user_id = this.resolveUserId(options);
|
|
287
|
+
request.conversation_title = options?.conversationTitle ?? this.config.conversation?.title;
|
|
288
|
+
request.conversation_memory_max_turns = options?.conversationMemoryMaxTurns ?? this.config.conversation?.memoryMaxTurns;
|
|
289
|
+
if (options?.tools) {
|
|
290
|
+
request.tools = options.tools;
|
|
291
|
+
}
|
|
292
|
+
const snapshotId = options?.snapshotId?.trim() || this.config.orchestrator.snapshotId;
|
|
293
|
+
if (snapshotId) {
|
|
294
|
+
request.snapshot_id = snapshotId;
|
|
244
295
|
}
|
|
245
296
|
this.emit({
|
|
246
297
|
type: 'orchestrator_request',
|
|
247
|
-
endpoint: `${this.config.orchestrator.baseUrl}
|
|
298
|
+
endpoint: `${this.config.orchestrator.baseUrl.replace(/\/+$/, '')}${endpointPath}`,
|
|
248
299
|
request,
|
|
249
300
|
});
|
|
250
301
|
this.abortReason = null;
|
|
@@ -265,6 +316,7 @@ export class AIClient {
|
|
|
265
316
|
try {
|
|
266
317
|
const response = await this.transport.send(request, {
|
|
267
318
|
baseUrl: this.config.orchestrator.baseUrl,
|
|
319
|
+
endpointPath,
|
|
268
320
|
headers,
|
|
269
321
|
signal: this.abortController.signal,
|
|
270
322
|
});
|
|
@@ -475,6 +527,7 @@ export class AIClient {
|
|
|
475
527
|
const text = this.extractAssistantText(chunk.data) ?? '';
|
|
476
528
|
const lastMsg = this.conversationState.messages[this.conversationState.messages.length - 1];
|
|
477
529
|
if (text.trim() && lastMsg?.role === 'assistant' && !lastMsg.content.trim()) {
|
|
530
|
+
this.applyWorkflowDetails(chunk.data);
|
|
478
531
|
// Server batched the full response with no deltas — animate it in.
|
|
479
532
|
this.emit({ type: 'first_token', messageId: lastMsg.id });
|
|
480
533
|
await this.simulateDeltaStream(text, lastMsg.id);
|
|
@@ -576,6 +629,7 @@ export class AIClient {
|
|
|
576
629
|
return target.id;
|
|
577
630
|
}
|
|
578
631
|
applyTerminalContent(data) {
|
|
632
|
+
this.applyWorkflowDetails(data);
|
|
579
633
|
const text = this.extractAssistantText(data) ?? '';
|
|
580
634
|
if (!text.trim()) {
|
|
581
635
|
return;
|
|
@@ -614,6 +668,7 @@ export class AIClient {
|
|
|
614
668
|
if (contentType.includes('application/json') || raw.trim().startsWith('{')) {
|
|
615
669
|
try {
|
|
616
670
|
const parsed = JSON.parse(raw);
|
|
671
|
+
this.applyWorkflowDetails(parsed);
|
|
617
672
|
const extracted = this.extractAssistantText(parsed);
|
|
618
673
|
assistantText = extracted ?? raw;
|
|
619
674
|
}
|
|
@@ -633,6 +688,48 @@ export class AIClient {
|
|
|
633
688
|
this.emit({ type: 'first_token', messageId: assistantMsg.id });
|
|
634
689
|
}
|
|
635
690
|
}
|
|
691
|
+
applyWorkflowDetails(payload) {
|
|
692
|
+
const details = payload.details;
|
|
693
|
+
if (!details || typeof details !== 'object') {
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
const workflow = details.workflow;
|
|
697
|
+
if (!workflow || typeof workflow !== 'object') {
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
const workflowDetails = workflow;
|
|
701
|
+
const conversationId = typeof workflowDetails.conversationId === 'string'
|
|
702
|
+
? workflowDetails.conversationId.trim()
|
|
703
|
+
: undefined;
|
|
704
|
+
const workflowId = typeof workflowDetails.workflowId === 'string'
|
|
705
|
+
? workflowDetails.workflowId.trim()
|
|
706
|
+
: undefined;
|
|
707
|
+
const status = typeof workflowDetails.status === 'string'
|
|
708
|
+
? workflowDetails.status.trim()
|
|
709
|
+
: undefined;
|
|
710
|
+
const checkpointPrompt = typeof workflowDetails.checkpointPrompt === 'string'
|
|
711
|
+
? workflowDetails.checkpointPrompt
|
|
712
|
+
: undefined;
|
|
713
|
+
if (conversationId && conversationId !== this.conversationState.id) {
|
|
714
|
+
this.conversationState.id = conversationId;
|
|
715
|
+
}
|
|
716
|
+
if (workflowId) {
|
|
717
|
+
this.conversationState.workflowId = workflowId;
|
|
718
|
+
}
|
|
719
|
+
if (status) {
|
|
720
|
+
this.conversationState.workflowStatus = status;
|
|
721
|
+
}
|
|
722
|
+
if (checkpointPrompt !== undefined) {
|
|
723
|
+
this.conversationState.checkpointPrompt = checkpointPrompt;
|
|
724
|
+
}
|
|
725
|
+
this.emit({
|
|
726
|
+
type: 'workflow_metadata_updated',
|
|
727
|
+
conversationId: conversationId || this.conversationState.id,
|
|
728
|
+
workflowId,
|
|
729
|
+
status,
|
|
730
|
+
checkpointPrompt,
|
|
731
|
+
});
|
|
732
|
+
}
|
|
636
733
|
extractAssistantText(payload) {
|
|
637
734
|
const messages = payload.messages;
|
|
638
735
|
if (Array.isArray(messages)) {
|
|
@@ -722,16 +819,18 @@ export class AIClient {
|
|
|
722
819
|
}
|
|
723
820
|
return undefined;
|
|
724
821
|
}
|
|
725
|
-
buildCollectorEvent(userMessage, assistantMessage) {
|
|
822
|
+
buildCollectorEvent(userMessage, assistantMessage, options) {
|
|
726
823
|
const collector = this.config.collector;
|
|
727
|
-
const
|
|
728
|
-
const
|
|
729
|
-
const
|
|
730
|
-
const
|
|
731
|
-
const
|
|
732
|
-
const
|
|
824
|
+
const resolved = this.getResolvedIdentity(options);
|
|
825
|
+
const userId = resolved.userId;
|
|
826
|
+
const requestUseCaseId = options?.useCaseId?.trim() || this.config.orchestrator.useCaseId;
|
|
827
|
+
const agentId = collector.agentId ?? requestUseCaseId;
|
|
828
|
+
const entityId = resolved.entityId;
|
|
829
|
+
const entityidType = resolved.entityidType;
|
|
830
|
+
const entityidAlgo = resolved.entityidAlgo;
|
|
831
|
+
const entityidOwner = resolved.entityidOwner;
|
|
733
832
|
const acceptCookies = collector.acceptCookies ?? false;
|
|
734
|
-
const
|
|
833
|
+
const eventSubContext = collector.eventSubContext ?? requestUseCaseId;
|
|
735
834
|
return {
|
|
736
835
|
tagId: collector.tagId,
|
|
737
836
|
tagType: 'web-sdk-nativeId',
|
|
@@ -739,7 +838,7 @@ export class AIClient {
|
|
|
739
838
|
remember: true,
|
|
740
839
|
eventType: 'conversation',
|
|
741
840
|
eventSubType: 'chat_turn',
|
|
742
|
-
eventSubContext
|
|
841
|
+
eventSubContext,
|
|
743
842
|
eventGuid: generateId(),
|
|
744
843
|
...(collector.sessionId ? { sessionId: collector.sessionId } : {}),
|
|
745
844
|
entityId,
|
|
@@ -752,12 +851,11 @@ export class AIClient {
|
|
|
752
851
|
contentData: {
|
|
753
852
|
userId,
|
|
754
853
|
agentId,
|
|
755
|
-
conversationId:
|
|
854
|
+
conversationId: resolved.conversationId,
|
|
756
855
|
userMessageId: userMessage.id,
|
|
757
856
|
agentMessageId: assistantMessage?.id ?? null,
|
|
758
857
|
userMessage: userMessage.content,
|
|
759
858
|
agentMessage: assistantMessage?.content ?? null,
|
|
760
|
-
spaceId,
|
|
761
859
|
},
|
|
762
860
|
},
|
|
763
861
|
};
|
|
@@ -765,12 +863,12 @@ export class AIClient {
|
|
|
765
863
|
/**
|
|
766
864
|
* Emit a conversation event to the TagIt collector
|
|
767
865
|
*/
|
|
768
|
-
async emitCollectorEvent(userMessage, assistantMessage) {
|
|
866
|
+
async emitCollectorEvent(userMessage, assistantMessage, options) {
|
|
769
867
|
if (!this.config.collector?.baseUrl || !this.config.collector?.tagId) {
|
|
770
868
|
return;
|
|
771
869
|
}
|
|
772
870
|
const endpoint = this.config.collector.baseUrl;
|
|
773
|
-
const event = this.buildCollectorEvent(userMessage, assistantMessage);
|
|
871
|
+
const event = this.buildCollectorEvent(userMessage, assistantMessage, options);
|
|
774
872
|
try {
|
|
775
873
|
const MAX_PAYLOAD_SIZE = 16 * 1024;
|
|
776
874
|
const body = JSON.stringify(event);
|
|
@@ -846,7 +944,9 @@ export class AIClient {
|
|
|
846
944
|
});
|
|
847
945
|
}
|
|
848
946
|
this.conversationState.messages = [];
|
|
849
|
-
this.
|
|
947
|
+
if (!this.hasConfiguredConversationId()) {
|
|
948
|
+
this.conversationState.id = generateId();
|
|
949
|
+
}
|
|
850
950
|
this.conversationState.error = undefined;
|
|
851
951
|
this.conversationState.lastError = undefined;
|
|
852
952
|
this.conversationState.isStreaming = false;
|