@api-client/core 0.19.0 → 0.19.2
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/build/src/decorators/observed.d.ts.map +1 -1
- package/build/src/decorators/observed.js +49 -8
- package/build/src/decorators/observed.js.map +1 -1
- package/build/src/mocking/ModelingMock.d.ts +2 -0
- package/build/src/mocking/ModelingMock.d.ts.map +1 -1
- package/build/src/mocking/ModelingMock.js +2 -0
- package/build/src/mocking/ModelingMock.js.map +1 -1
- package/build/src/mocking/lib/Ai.d.ts +11 -0
- package/build/src/mocking/lib/Ai.d.ts.map +1 -0
- package/build/src/mocking/lib/Ai.js +53 -0
- package/build/src/mocking/lib/Ai.js.map +1 -0
- package/build/src/modeling/ai/DataDomainDelta.d.ts +146 -0
- package/build/src/modeling/ai/DataDomainDelta.d.ts.map +1 -0
- package/build/src/modeling/ai/DataDomainDelta.js +729 -0
- package/build/src/modeling/ai/DataDomainDelta.js.map +1 -0
- package/build/src/modeling/ai/DomainSerialization.d.ts +20 -0
- package/build/src/modeling/ai/DomainSerialization.d.ts.map +1 -0
- package/build/src/modeling/ai/DomainSerialization.js +185 -0
- package/build/src/modeling/ai/DomainSerialization.js.map +1 -0
- package/build/src/modeling/ai/domain_response_schema.d.ts +806 -0
- package/build/src/modeling/ai/domain_response_schema.d.ts.map +1 -0
- package/build/src/modeling/ai/domain_response_schema.js +289 -0
- package/build/src/modeling/ai/domain_response_schema.js.map +1 -0
- package/build/src/modeling/ai/domain_tools.d.ts +68 -0
- package/build/src/modeling/ai/domain_tools.d.ts.map +1 -0
- package/build/src/modeling/ai/domain_tools.js +71 -0
- package/build/src/modeling/ai/domain_tools.js.map +1 -0
- package/build/src/modeling/ai/index.d.ts +10 -0
- package/build/src/modeling/ai/index.d.ts.map +1 -0
- package/build/src/modeling/ai/index.js +9 -0
- package/build/src/modeling/ai/index.js.map +1 -0
- package/build/src/modeling/ai/message_parser.d.ts +23 -0
- package/build/src/modeling/ai/message_parser.d.ts.map +1 -0
- package/build/src/modeling/ai/message_parser.js +93 -0
- package/build/src/modeling/ai/message_parser.js.map +1 -0
- package/build/src/modeling/ai/prompts/domain_system.d.ts +6 -0
- package/build/src/modeling/ai/prompts/domain_system.d.ts.map +1 -0
- package/build/src/modeling/ai/prompts/domain_system.js +80 -0
- package/build/src/modeling/ai/prompts/domain_system.js.map +1 -0
- package/build/src/modeling/ai/tools/DataDomain.tools.d.ts +25 -0
- package/build/src/modeling/ai/tools/DataDomain.tools.d.ts.map +1 -0
- package/build/src/modeling/ai/tools/DataDomain.tools.js +334 -0
- package/build/src/modeling/ai/tools/DataDomain.tools.js.map +1 -0
- package/build/src/modeling/ai/tools/Semantic.tools.d.ts +48 -0
- package/build/src/modeling/ai/tools/Semantic.tools.d.ts.map +1 -0
- package/build/src/modeling/ai/tools/Semantic.tools.js +36 -0
- package/build/src/modeling/ai/tools/Semantic.tools.js.map +1 -0
- package/build/src/modeling/ai/tools/config.d.ts +13 -0
- package/build/src/modeling/ai/tools/config.d.ts.map +1 -0
- package/build/src/modeling/ai/tools/config.js +2 -0
- package/build/src/modeling/ai/tools/config.js.map +1 -0
- package/build/src/modeling/ai/types.d.ts +302 -0
- package/build/src/modeling/ai/types.d.ts.map +1 -0
- package/build/src/modeling/ai/types.js +40 -0
- package/build/src/modeling/ai/types.js.map +1 -0
- package/build/src/models/AiMessage.d.ts +185 -0
- package/build/src/models/AiMessage.d.ts.map +1 -0
- package/build/src/models/AiMessage.js +203 -0
- package/build/src/models/AiMessage.js.map +1 -0
- package/build/src/models/AiSession.d.ts +80 -0
- package/build/src/models/AiSession.d.ts.map +1 -0
- package/build/src/models/AiSession.js +102 -0
- package/build/src/models/AiSession.js.map +1 -0
- package/build/src/models/kinds.d.ts +2 -0
- package/build/src/models/kinds.d.ts.map +1 -1
- package/build/src/models/kinds.js +2 -0
- package/build/src/models/kinds.js.map +1 -1
- package/build/src/sdk/AiSdk.d.ts +93 -0
- package/build/src/sdk/AiSdk.d.ts.map +1 -0
- package/build/src/sdk/AiSdk.js +348 -0
- package/build/src/sdk/AiSdk.js.map +1 -0
- package/build/src/sdk/RouteBuilder.d.ts +7 -0
- package/build/src/sdk/RouteBuilder.d.ts.map +1 -1
- package/build/src/sdk/RouteBuilder.js +18 -0
- package/build/src/sdk/RouteBuilder.js.map +1 -1
- package/build/src/sdk/Sdk.d.ts +2 -0
- package/build/src/sdk/Sdk.d.ts.map +1 -1
- package/build/src/sdk/Sdk.js +2 -0
- package/build/src/sdk/Sdk.js.map +1 -1
- package/build/src/sdk/SdkBase.d.ts +4 -0
- package/build/src/sdk/SdkBase.d.ts.map +1 -1
- package/build/src/sdk/SdkBase.js.map +1 -1
- package/build/src/sdk/SdkMock.d.ts +15 -0
- package/build/src/sdk/SdkMock.d.ts.map +1 -1
- package/build/src/sdk/SdkMock.js +118 -0
- package/build/src/sdk/SdkMock.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/decorators/observed.ts +51 -9
- package/src/mocking/ModelingMock.ts +2 -0
- package/src/mocking/lib/Ai.ts +71 -0
- package/src/modeling/ai/DataDomainDelta.ts +798 -0
- package/src/modeling/ai/DomainSerialization.ts +199 -0
- package/src/modeling/ai/domain_response_schema.ts +301 -0
- package/src/modeling/ai/domain_tools.ts +76 -0
- package/src/modeling/ai/message_parser.ts +101 -0
- package/src/modeling/ai/prompts/domain_system.ts +79 -0
- package/src/modeling/ai/readme.md +8 -0
- package/src/modeling/ai/tools/DataDomain.tools.ts +365 -0
- package/src/modeling/ai/tools/Semantic.tools.ts +38 -0
- package/src/modeling/ai/tools/config.ts +13 -0
- package/src/modeling/ai/tools/readme.md +3 -0
- package/src/modeling/ai/types.ts +306 -0
- package/src/models/AiMessage.ts +335 -0
- package/src/models/AiSession.ts +160 -0
- package/src/models/kinds.ts +2 -0
- package/src/sdk/AiSdk.ts +395 -0
- package/src/sdk/RouteBuilder.ts +27 -0
- package/src/sdk/Sdk.ts +3 -0
- package/src/sdk/SdkBase.ts +4 -0
- package/src/sdk/SdkMock.ts +185 -0
- package/tests/unit/decorators/observed_recursive.spec.ts +39 -0
- package/tests/unit/mocking/current/Ai.spec.ts +109 -0
- package/tests/unit/modeling/ai/DataDomainDelta.spec.ts +419 -0
- package/tests/unit/modeling/ai/DomainAiTools.spec.ts +29 -0
- package/tests/unit/modeling/ai/DomainSerialization.spec.ts +143 -0
- package/tests/unit/modeling/ai/message_parser.spec.ts +157 -0
- package/tests/unit/modeling/ai/tools/DataDomain.tools.spec.ts +64 -0
- package/tests/unit/modeling/ai/tools/Semantic.tools.spec.ts +55 -0
- package/tests/unit/models/AiMessage.spec.ts +216 -0
- package/tests/unit/models/AiSession.spec.ts +147 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import type { IApiAssociationShape } from '../../amf/definitions/Shapes.js'
|
|
2
|
+
import type { Exception } from '../../exceptions/exception.js'
|
|
3
|
+
import type { AiSessionSchema } from '../../models/AiSession.js'
|
|
4
|
+
import type { DomainPropertyType } from '../DataFormat.js'
|
|
5
|
+
import type { OnDeleteRule } from '../index.js'
|
|
6
|
+
import { SemanticType } from '../Semantics.js'
|
|
7
|
+
import type { AssociationTarget, PropertySchema } from '../types.js'
|
|
8
|
+
import type { AiMessageSchema, AiModelMessage } from '../../models/AiMessage.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A copy of the `Type` enum from the `@google/genai` package.
|
|
12
|
+
* It's here so we don't need to import the nodejs only package.
|
|
13
|
+
*/
|
|
14
|
+
export enum Type {
|
|
15
|
+
/**
|
|
16
|
+
* Not specified, should not be used.
|
|
17
|
+
*/
|
|
18
|
+
TYPE_UNSPECIFIED = 'TYPE_UNSPECIFIED',
|
|
19
|
+
/**
|
|
20
|
+
* OpenAPI string type
|
|
21
|
+
*/
|
|
22
|
+
STRING = 'STRING',
|
|
23
|
+
/**
|
|
24
|
+
* OpenAPI number type
|
|
25
|
+
*/
|
|
26
|
+
NUMBER = 'NUMBER',
|
|
27
|
+
/**
|
|
28
|
+
* OpenAPI integer type
|
|
29
|
+
*/
|
|
30
|
+
INTEGER = 'INTEGER',
|
|
31
|
+
/**
|
|
32
|
+
* OpenAPI boolean type
|
|
33
|
+
*/
|
|
34
|
+
BOOLEAN = 'BOOLEAN',
|
|
35
|
+
/**
|
|
36
|
+
* OpenAPI array type
|
|
37
|
+
*/
|
|
38
|
+
ARRAY = 'ARRAY',
|
|
39
|
+
/**
|
|
40
|
+
* OpenAPI object type
|
|
41
|
+
*/
|
|
42
|
+
OBJECT = 'OBJECT',
|
|
43
|
+
/**
|
|
44
|
+
* Null type
|
|
45
|
+
*/
|
|
46
|
+
NULL = 'NULL',
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A lightweight representation of the `DataDomain` used specifically for serializing
|
|
51
|
+
* the current domain state and sending it as context to the AI endpoint.
|
|
52
|
+
* It omits complex internal graph structures, including only essential keys, names,
|
|
53
|
+
* descriptions, and the hierarchical structure of models and entities.
|
|
54
|
+
*/
|
|
55
|
+
export interface AiDataDomainSchema {
|
|
56
|
+
key: string
|
|
57
|
+
name: string
|
|
58
|
+
models: AiDataModelSchema[]
|
|
59
|
+
entities: AiDomainEntitySchema[]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A stripped-down representation of a `DomainModel` sent to the AI as part of the
|
|
64
|
+
* domain context. It provides the AI with the existing model hierarchy and descriptions.
|
|
65
|
+
*/
|
|
66
|
+
export interface AiDataModelSchema {
|
|
67
|
+
key: string
|
|
68
|
+
name?: string
|
|
69
|
+
description?: string
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Represents a semantic annotation applied to an entity, property, or association
|
|
74
|
+
* within the AI's understanding or response. It defines the "meaning" of a field
|
|
75
|
+
* (e.g., "Email", "Password", "Address").
|
|
76
|
+
*/
|
|
77
|
+
export interface AiDomainSemantic {
|
|
78
|
+
id: SemanticType
|
|
79
|
+
config?: Record<string, unknown>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Represents a full or partial entity schema as generated by the AI in its response delta.
|
|
84
|
+
* It defines a new entity or updates to an existing one, including its properties,
|
|
85
|
+
* associations, semantics, and tags. This is also used by the `get_entity_details` tool
|
|
86
|
+
* to send detailed serialized entity information back to the AI.
|
|
87
|
+
*/
|
|
88
|
+
export interface AiDomainEntityResponseSchema {
|
|
89
|
+
key: string
|
|
90
|
+
modelKey: string
|
|
91
|
+
name?: string
|
|
92
|
+
displayName?: string
|
|
93
|
+
description?: string
|
|
94
|
+
tags?: string[]
|
|
95
|
+
semantics?: AiDomainSemantic[]
|
|
96
|
+
properties?: AiDomainProperty[]
|
|
97
|
+
associations?: AiDomainAssociation[]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A minimal representation of an entity used purely for context-setting when
|
|
102
|
+
* sending the current domain structure to the AI. It excludes deeply nested
|
|
103
|
+
* properties and associations to save token space.
|
|
104
|
+
*/
|
|
105
|
+
export interface AiDomainEntitySchema {
|
|
106
|
+
key: string
|
|
107
|
+
modelKey: string
|
|
108
|
+
name?: string
|
|
109
|
+
description?: string
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Represents a property definition generated by the AI. It maps the complex internal
|
|
114
|
+
* domain property structure into a simpler, flat structure that the AI generates,
|
|
115
|
+
* including data types, constraints, schema metadata, and semantics.
|
|
116
|
+
*/
|
|
117
|
+
export interface AiDomainProperty {
|
|
118
|
+
key?: string
|
|
119
|
+
name?: string
|
|
120
|
+
displayName?: string
|
|
121
|
+
description?: string
|
|
122
|
+
type: DomainPropertyType
|
|
123
|
+
constraints?: {
|
|
124
|
+
required?: boolean
|
|
125
|
+
unique?: boolean
|
|
126
|
+
index?: boolean
|
|
127
|
+
primary?: boolean
|
|
128
|
+
multiple?: boolean
|
|
129
|
+
readOnly?: boolean
|
|
130
|
+
writeOnly?: boolean
|
|
131
|
+
}
|
|
132
|
+
deprecated?: boolean
|
|
133
|
+
schema?: PropertySchema
|
|
134
|
+
semantics?: AiDomainSemantic[]
|
|
135
|
+
tags?: string[]
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Represents an association definition generated by the AI, linking an entity
|
|
140
|
+
* to one or more target entities. It includes relationship rules (like onDelete)
|
|
141
|
+
* and semantic annotations.
|
|
142
|
+
*/
|
|
143
|
+
export interface AiDomainAssociation {
|
|
144
|
+
key: string
|
|
145
|
+
name?: string
|
|
146
|
+
displayName?: string
|
|
147
|
+
description?: string
|
|
148
|
+
targets: AssociationTarget[]
|
|
149
|
+
required?: boolean
|
|
150
|
+
multiple?: boolean
|
|
151
|
+
onDelete?: OnDeleteRule
|
|
152
|
+
semantics?: AiDomainSemantic[]
|
|
153
|
+
schema?: IApiAssociationShape
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* The core structure representing a set of modifications (a delta) proposed by the AI.
|
|
158
|
+
* It contains arrays of models and entities to add, delete, or modify. The application
|
|
159
|
+
* processes this delta to transition the data domain to the new requested state.
|
|
160
|
+
*/
|
|
161
|
+
export interface AiDomainDelta {
|
|
162
|
+
/**
|
|
163
|
+
* Models to add to the domain.
|
|
164
|
+
*/
|
|
165
|
+
addedModels?: AiDataModelSchema[]
|
|
166
|
+
/**
|
|
167
|
+
* Keys of models to delete from the domain.
|
|
168
|
+
*/
|
|
169
|
+
deletedModelKeys?: string[]
|
|
170
|
+
/**
|
|
171
|
+
* Models to modify in the domain.
|
|
172
|
+
*/
|
|
173
|
+
modifiedModels?: AiDataModelSchema[]
|
|
174
|
+
/**
|
|
175
|
+
* Entities to add to the domain.
|
|
176
|
+
*/
|
|
177
|
+
addedEntities?: AiDomainEntityResponseSchema[]
|
|
178
|
+
/**
|
|
179
|
+
* Keys of entities to delete from the domain.
|
|
180
|
+
*/
|
|
181
|
+
deletedEntityKeys?: string[]
|
|
182
|
+
/**
|
|
183
|
+
* Entities to modify in the domain.
|
|
184
|
+
*/
|
|
185
|
+
modifiedEntities?: AiDomainEntityDelta[]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The expected JSON schema structure returned by the AI endpoint when performing
|
|
190
|
+
* data domain manipulation. It includes the AI's step-by-step reasoning and the
|
|
191
|
+
* actionable delta to be applied.
|
|
192
|
+
*/
|
|
193
|
+
export interface AiDomainDeltaResponse {
|
|
194
|
+
/**
|
|
195
|
+
* The LLM reasoning.
|
|
196
|
+
*/
|
|
197
|
+
reasoning: string
|
|
198
|
+
/**
|
|
199
|
+
* Domain changes delta
|
|
200
|
+
*/
|
|
201
|
+
delta?: AiDomainDelta
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Union type for progressive SSE stream chunks
|
|
206
|
+
* received from the AI generation endpoint.
|
|
207
|
+
*/
|
|
208
|
+
export type AiStreamEvent =
|
|
209
|
+
| { event: 'user-message'; data: AiMessageSchema }
|
|
210
|
+
| { event: 'agent-message'; data: AiMessageSchema }
|
|
211
|
+
| { event: 'thought-chunk'; data: string }
|
|
212
|
+
| { event: 'text-chunk'; data: string }
|
|
213
|
+
| { event: 'done'; data: AiMessageSchema }
|
|
214
|
+
| { event: 'error'; data: Exception }
|
|
215
|
+
| { event: 'session-updated'; data: AiSessionSchema }
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Represents a targeted modification to an existing entity generated by the AI.
|
|
219
|
+
* Instead of providing the full entity state, the AI provides explicit arrays
|
|
220
|
+
* of properties, associations, and semantics to add, modify, or delete, enabling
|
|
221
|
+
* precise, non-destructive updates.
|
|
222
|
+
*/
|
|
223
|
+
export interface AiDomainEntityDelta {
|
|
224
|
+
key: string
|
|
225
|
+
modelKey?: string // Provide to move the entity to a different model
|
|
226
|
+
name?: string
|
|
227
|
+
displayName?: string
|
|
228
|
+
description?: string
|
|
229
|
+
tags?: string[]
|
|
230
|
+
// Entity semantics delta
|
|
231
|
+
addedSemantics?: AiDomainSemantic[]
|
|
232
|
+
modifiedSemantics?: AiDomainSemantic[]
|
|
233
|
+
deletedSemanticIds?: SemanticType[]
|
|
234
|
+
// Explicit deltas so the LLM doesn't have to list untouched properties
|
|
235
|
+
addedProperties?: AiDomainProperty[]
|
|
236
|
+
modifiedProperties?: AiDomainPropertyDelta[]
|
|
237
|
+
deletedPropertyKeys?: string[]
|
|
238
|
+
addedAssociations?: AiDomainAssociation[]
|
|
239
|
+
modifiedAssociations?: AiDomainAssociationDelta[]
|
|
240
|
+
deletedAssociationKeys?: string[]
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Represents a targeted modification to an existing property generated by the AI.
|
|
245
|
+
* It captures changes to superficial properties (name, description), type changes,
|
|
246
|
+
* constraint updates, and semantic alterations.
|
|
247
|
+
*/
|
|
248
|
+
export interface AiDomainPropertyDelta {
|
|
249
|
+
key: string
|
|
250
|
+
name?: string
|
|
251
|
+
displayName?: string
|
|
252
|
+
description?: string
|
|
253
|
+
type?: DomainPropertyType
|
|
254
|
+
constraints?: {
|
|
255
|
+
required?: boolean
|
|
256
|
+
unique?: boolean
|
|
257
|
+
index?: boolean
|
|
258
|
+
primary?: boolean
|
|
259
|
+
multiple?: boolean
|
|
260
|
+
readOnly?: boolean
|
|
261
|
+
writeOnly?: boolean
|
|
262
|
+
}
|
|
263
|
+
deprecated?: boolean
|
|
264
|
+
// Property semantics delta
|
|
265
|
+
addedSemantics?: AiDomainSemantic[]
|
|
266
|
+
modifiedSemantics?: AiDomainSemantic[]
|
|
267
|
+
deletedSemanticIds?: SemanticType[]
|
|
268
|
+
schema?: PropertySchema
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Represents a targeted modification to an existing association generated by the AI.
|
|
273
|
+
* It captures updates to relationship cardinality, target entities, deletion rules,
|
|
274
|
+
* and applied semantics.
|
|
275
|
+
*/
|
|
276
|
+
export interface AiDomainAssociationDelta {
|
|
277
|
+
key: string
|
|
278
|
+
name?: string
|
|
279
|
+
displayName?: string
|
|
280
|
+
description?: string
|
|
281
|
+
targets?: AssociationTarget[]
|
|
282
|
+
required?: boolean
|
|
283
|
+
onDelete?: OnDeleteRule
|
|
284
|
+
// Association semantics delta
|
|
285
|
+
addedSemantics?: AiDomainSemantic[]
|
|
286
|
+
modifiedSemantics?: AiDomainSemantic[]
|
|
287
|
+
deletedSemanticIds?: SemanticType[]
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* An enriched, in-memory representation of a model's message that includes the globally
|
|
292
|
+
* parsed `AiDomainDelta` object.
|
|
293
|
+
* This is not stored directly in the datastore as-is; instead, the raw JSON text is stored,
|
|
294
|
+
* and this structure is assembled at runtime when the chat history is loaded into the UI.
|
|
295
|
+
*/
|
|
296
|
+
export interface AiModelMessageWithDelta extends AiModelMessage {
|
|
297
|
+
/**
|
|
298
|
+
* The delta of the message, if any.
|
|
299
|
+
*/
|
|
300
|
+
delta?: AiDomainDelta
|
|
301
|
+
/**
|
|
302
|
+
* The reasoning of the delta.
|
|
303
|
+
* Format in markdown.
|
|
304
|
+
*/
|
|
305
|
+
reasoning?: string
|
|
306
|
+
}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import type { IDeletion } from './store/Deletion.js'
|
|
2
|
+
import { AiMessageKind } from './kinds.js'
|
|
3
|
+
import { nanoid } from '../nanoid.js'
|
|
4
|
+
import type { AiDomainDelta } from '../modeling/ai/types.js'
|
|
5
|
+
import { DataDomainDelta } from '../modeling/ai/DataDomainDelta.js'
|
|
6
|
+
|
|
7
|
+
export type AiMessageRole = 'user' | 'model'
|
|
8
|
+
export type AiMessageState = 'loading' | 'complete' | 'error' | 'terminated'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The base interface representing a single message in the domain manipulation chat history.
|
|
12
|
+
* It tracks metadata like timestamps, the associated session, and the raw text content.
|
|
13
|
+
* See `AiUserMessage` and `AiModelMessage` for specific role implementations.
|
|
14
|
+
*/
|
|
15
|
+
export interface AiMessageSchemaBase {
|
|
16
|
+
readonly kind: typeof AiMessageKind
|
|
17
|
+
/**
|
|
18
|
+
* The datastore key of the message.
|
|
19
|
+
*/
|
|
20
|
+
key: string
|
|
21
|
+
/**
|
|
22
|
+
* The role of the message.
|
|
23
|
+
*/
|
|
24
|
+
role: AiMessageRole
|
|
25
|
+
/**
|
|
26
|
+
* The timestamp of when the message was created.
|
|
27
|
+
*/
|
|
28
|
+
createdAt: number
|
|
29
|
+
/**
|
|
30
|
+
* The timestamp of when the message was last updated.
|
|
31
|
+
*/
|
|
32
|
+
updatedAt: number
|
|
33
|
+
/**
|
|
34
|
+
* The datastore key of the session.
|
|
35
|
+
*/
|
|
36
|
+
session: string
|
|
37
|
+
/**
|
|
38
|
+
* The text of the message.
|
|
39
|
+
*/
|
|
40
|
+
text: string
|
|
41
|
+
/**
|
|
42
|
+
* Whether the message is deleted.
|
|
43
|
+
*/
|
|
44
|
+
deleted?: boolean
|
|
45
|
+
/**
|
|
46
|
+
* The information about the delete information.
|
|
47
|
+
* Always set when the `deleted` is true.
|
|
48
|
+
*/
|
|
49
|
+
deletedInfo?: IDeletion
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The schema for a user message.
|
|
54
|
+
*/
|
|
55
|
+
export interface AiUserMessageSchema extends AiMessageSchemaBase {
|
|
56
|
+
/**
|
|
57
|
+
* The role of the message.
|
|
58
|
+
*/
|
|
59
|
+
role: 'user'
|
|
60
|
+
/**
|
|
61
|
+
* The state of the user message.
|
|
62
|
+
* Can only be `complete`.
|
|
63
|
+
*/
|
|
64
|
+
state: 'complete'
|
|
65
|
+
/**
|
|
66
|
+
* The user utterance.
|
|
67
|
+
* Note, the actual message sent to the LLM may be different from the utterance
|
|
68
|
+
* as it has additional instructions and the domain context. However, we are not storing
|
|
69
|
+
* the full message in the datastore, only the utterance.
|
|
70
|
+
*/
|
|
71
|
+
text: string
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The schema for a model message.
|
|
76
|
+
*/
|
|
77
|
+
export interface AiModelMessageSchema extends AiMessageSchemaBase {
|
|
78
|
+
/**
|
|
79
|
+
* The role of the message.
|
|
80
|
+
*/
|
|
81
|
+
role: 'model'
|
|
82
|
+
/**
|
|
83
|
+
* The full text of the message returned by the LLM.
|
|
84
|
+
* It is most likely a structured message that needs to be parsed
|
|
85
|
+
* to the corresponding message object.
|
|
86
|
+
*/
|
|
87
|
+
text: string
|
|
88
|
+
/**
|
|
89
|
+
* The state of the message.
|
|
90
|
+
* - loading: the message is being generated
|
|
91
|
+
* - complete: the message is complete
|
|
92
|
+
* - error: the message generation failed
|
|
93
|
+
* - terminated: the message generation was terminated by the user
|
|
94
|
+
*/
|
|
95
|
+
state: AiMessageState
|
|
96
|
+
/**
|
|
97
|
+
* Whether the message has been applied.
|
|
98
|
+
*/
|
|
99
|
+
applied?: boolean
|
|
100
|
+
/**
|
|
101
|
+
* The thoughts of the message.
|
|
102
|
+
*/
|
|
103
|
+
thoughts?: string
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A union type representing any valid chat message in the AI session history.
|
|
108
|
+
*/
|
|
109
|
+
export type AiMessageSchema = AiUserMessageSchema | AiModelMessageSchema
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The base class for all AI messages.
|
|
113
|
+
* It provides common functionality for all message types.
|
|
114
|
+
*/
|
|
115
|
+
export abstract class AiMessageBase<
|
|
116
|
+
T extends AiMessageSchemaBase = AiMessageSchemaBase,
|
|
117
|
+
> implements AiMessageSchemaBase {
|
|
118
|
+
/**
|
|
119
|
+
* The kind of the schema.
|
|
120
|
+
*/
|
|
121
|
+
static get Kind(): typeof AiMessageKind {
|
|
122
|
+
return AiMessageKind
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The kind of the schema.
|
|
127
|
+
*/
|
|
128
|
+
get kind(): typeof AiMessageKind {
|
|
129
|
+
return AiMessageKind
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
key: string
|
|
133
|
+
role: T['role']
|
|
134
|
+
createdAt: number
|
|
135
|
+
updatedAt: number
|
|
136
|
+
session: string
|
|
137
|
+
text: string
|
|
138
|
+
deleted: boolean
|
|
139
|
+
deletedInfo?: IDeletion
|
|
140
|
+
|
|
141
|
+
protected static createBaseSchema(input: Partial<AiMessageSchemaBase>): Omit<AiMessageSchemaBase, 'role'> {
|
|
142
|
+
const { key = nanoid(), session, text = '', createdAt = 0, updatedAt = 0 } = input
|
|
143
|
+
if (!session) {
|
|
144
|
+
throw new Error('Session is required to create an AiMessage.')
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
key,
|
|
148
|
+
kind: AiMessageKind,
|
|
149
|
+
session,
|
|
150
|
+
text,
|
|
151
|
+
createdAt,
|
|
152
|
+
updatedAt,
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
constructor(input: Partial<T> = {}, role: T['role']) {
|
|
157
|
+
const base = AiMessageBase.createBaseSchema(input)
|
|
158
|
+
this.key = base.key
|
|
159
|
+
this.role = role
|
|
160
|
+
this.session = base.session
|
|
161
|
+
this.text = base.text
|
|
162
|
+
this.createdAt = base.createdAt
|
|
163
|
+
this.updatedAt = base.updatedAt
|
|
164
|
+
this.deleted = input.deleted || false
|
|
165
|
+
this.deletedInfo = input.deletedInfo
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
toJSON(): T {
|
|
169
|
+
const result = {
|
|
170
|
+
kind: this.kind,
|
|
171
|
+
key: this.key,
|
|
172
|
+
role: this.role,
|
|
173
|
+
session: this.session,
|
|
174
|
+
text: this.text,
|
|
175
|
+
createdAt: this.createdAt,
|
|
176
|
+
updatedAt: this.updatedAt,
|
|
177
|
+
}
|
|
178
|
+
if (this.deleted && this.deletedInfo) {
|
|
179
|
+
Object.assign(result, {
|
|
180
|
+
deleted: this.deleted,
|
|
181
|
+
deletedInfo: { ...this.deletedInfo },
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
return result as unknown as T
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export class AiUserMessage extends AiMessageBase<AiUserMessageSchema> implements AiUserMessageSchema {
|
|
189
|
+
state: 'complete'
|
|
190
|
+
|
|
191
|
+
static createSchema(input: Partial<AiUserMessageSchema>): AiUserMessageSchema {
|
|
192
|
+
const base = AiMessageBase.createBaseSchema(input)
|
|
193
|
+
return {
|
|
194
|
+
...base,
|
|
195
|
+
role: 'user',
|
|
196
|
+
state: 'complete',
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
constructor(input: Partial<AiUserMessageSchema> = {}) {
|
|
201
|
+
super(input, 'user')
|
|
202
|
+
this.state = 'complete'
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
override toJSON(): AiUserMessageSchema {
|
|
206
|
+
return {
|
|
207
|
+
...super.toJSON(),
|
|
208
|
+
state: this.state,
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export class AiModelMessage extends AiMessageBase<AiModelMessageSchema> implements AiModelMessageSchema {
|
|
214
|
+
state: AiMessageState
|
|
215
|
+
applied?: boolean
|
|
216
|
+
thoughts: string
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* The delta of the message, if any.
|
|
220
|
+
*/
|
|
221
|
+
delta?: AiDomainDelta
|
|
222
|
+
/**
|
|
223
|
+
* The reasoning of the delta.
|
|
224
|
+
* Format in markdown.
|
|
225
|
+
*/
|
|
226
|
+
reasoning?: string
|
|
227
|
+
|
|
228
|
+
static createSchema(input: Partial<AiModelMessageSchema>): AiModelMessageSchema {
|
|
229
|
+
const base = AiMessageBase.createBaseSchema(input)
|
|
230
|
+
return {
|
|
231
|
+
...base,
|
|
232
|
+
role: 'model',
|
|
233
|
+
state: input.state || 'loading',
|
|
234
|
+
applied: input.applied,
|
|
235
|
+
thoughts: input.thoughts || '',
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
constructor(input: Partial<AiModelMessageSchema> = {}) {
|
|
240
|
+
super(input, 'model')
|
|
241
|
+
this.state = input.state || 'loading'
|
|
242
|
+
this.applied = input.applied
|
|
243
|
+
this.thoughts = input.thoughts || ''
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
override toJSON(): AiModelMessageSchema {
|
|
247
|
+
const result: AiModelMessageSchema = {
|
|
248
|
+
...super.toJSON(),
|
|
249
|
+
state: this.state,
|
|
250
|
+
thoughts: this.thoughts,
|
|
251
|
+
}
|
|
252
|
+
if (this.applied !== undefined) {
|
|
253
|
+
result.applied = this.applied
|
|
254
|
+
}
|
|
255
|
+
return result
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Adds a thought to the message. Useful when streaming.
|
|
260
|
+
* @param thought The thought to add.
|
|
261
|
+
*/
|
|
262
|
+
addThought(thought?: string): void {
|
|
263
|
+
if (!thought) {
|
|
264
|
+
return
|
|
265
|
+
}
|
|
266
|
+
this.thoughts += thought
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Adds a text chunk to the message. Useful when streaming.
|
|
271
|
+
* @param text The text chunk to add.
|
|
272
|
+
*/
|
|
273
|
+
addText(text?: string): void {
|
|
274
|
+
if (!text) {
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
this.text += text
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Processes the message.
|
|
282
|
+
* If the message is not valid JSON, it will throw an error.
|
|
283
|
+
* It sets the delta and reasoning fields, if found in the message.
|
|
284
|
+
*/
|
|
285
|
+
processMessage(): void {
|
|
286
|
+
if (!this.text) {
|
|
287
|
+
return
|
|
288
|
+
}
|
|
289
|
+
const parsed = JSON.parse(this.text)
|
|
290
|
+
if (parsed.delta) {
|
|
291
|
+
this.delta = DataDomainDelta.normalize(parsed.delta)
|
|
292
|
+
}
|
|
293
|
+
if (parsed.reasoning) {
|
|
294
|
+
this.reasoning = parsed.reasoning
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Processes the message safely.
|
|
300
|
+
* If the message is not valid JSON, it will be ignored.
|
|
301
|
+
*/
|
|
302
|
+
processMessageSafe(): void {
|
|
303
|
+
try {
|
|
304
|
+
this.processMessage()
|
|
305
|
+
} catch {
|
|
306
|
+
// do nothing
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Creates an empty model message. Useful when initializing LLM flow.
|
|
312
|
+
* @param session The session key.
|
|
313
|
+
* @returns An empty model message.
|
|
314
|
+
*/
|
|
315
|
+
static createEmpty(session: string): AiModelMessage {
|
|
316
|
+
return new AiModelMessage({
|
|
317
|
+
session,
|
|
318
|
+
state: 'loading',
|
|
319
|
+
})
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* A union type representing any valid chat message in the AI session history.
|
|
325
|
+
*/
|
|
326
|
+
export type AiMessage = AiUserMessage | AiModelMessage
|
|
327
|
+
|
|
328
|
+
export const AiMessageFactory = {
|
|
329
|
+
fromSchema(schema: Partial<AiMessageSchema>): AiMessage {
|
|
330
|
+
if (schema.role === 'model') {
|
|
331
|
+
return new AiModelMessage(schema as Partial<AiModelMessageSchema>)
|
|
332
|
+
}
|
|
333
|
+
return new AiUserMessage(schema as Partial<AiUserMessageSchema>)
|
|
334
|
+
},
|
|
335
|
+
}
|