@api-client/core 0.19.4 → 0.19.6
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/lib/logging/index.d.ts +9 -0
- package/build/src/lib/logging/index.d.ts.map +1 -1
- package/build/src/lib/logging/index.js +10 -0
- package/build/src/lib/logging/index.js.map +1 -1
- package/build/src/modeling/ai/DataDomainDelta.d.ts +7 -7
- package/build/src/modeling/ai/DataDomainDelta.d.ts.map +1 -1
- package/build/src/modeling/ai/DataDomainDelta.js +44 -33
- package/build/src/modeling/ai/DataDomainDelta.js.map +1 -1
- package/build/src/modeling/ai/domain_response_schema.d.ts +90 -2
- package/build/src/modeling/ai/domain_response_schema.d.ts.map +1 -1
- package/build/src/modeling/ai/domain_response_schema.js +40 -25
- package/build/src/modeling/ai/domain_response_schema.js.map +1 -1
- package/build/src/modeling/ai/prompts/domain_system.d.ts +1 -1
- package/build/src/modeling/ai/prompts/domain_system.d.ts.map +1 -1
- package/build/src/modeling/ai/prompts/domain_system.js +12 -7
- package/build/src/modeling/ai/prompts/domain_system.js.map +1 -1
- package/build/src/modeling/ai/types.d.ts +18 -14
- package/build/src/modeling/ai/types.d.ts.map +1 -1
- package/build/src/modeling/ai/types.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/modeling/ai/DataDomainDelta.ts +49 -39
- package/src/modeling/ai/domain_response_schema.ts +41 -25
- package/src/modeling/ai/prompts/domain_system.ts +12 -7
- package/src/modeling/ai/types.ts +19 -14
- package/tests/unit/modeling/ai/DataDomainDelta.spec.ts +110 -0
package/package.json
CHANGED
|
@@ -119,7 +119,7 @@ export class DataDomainDelta {
|
|
|
119
119
|
|
|
120
120
|
if (delta.addedEntities) {
|
|
121
121
|
for (const e of delta.addedEntities) {
|
|
122
|
-
this.handleAddEntity(
|
|
122
|
+
this.handleAddEntity(e)
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -150,6 +150,9 @@ export class DataDomainDelta {
|
|
|
150
150
|
if (mod.name) entity.info.name = mod.name
|
|
151
151
|
if (mod.displayName) entity.info.displayName = mod.displayName
|
|
152
152
|
if (mod.description) entity.info.description = mod.description
|
|
153
|
+
if (mod.tags !== undefined) {
|
|
154
|
+
entity.tags = mod.tags === null ? [] : mod.tags
|
|
155
|
+
}
|
|
153
156
|
|
|
154
157
|
this.applySemantics(entity, mod.addedSemantics, mod.modifiedSemantics, mod.deletedSemanticIds)
|
|
155
158
|
|
|
@@ -181,8 +184,8 @@ export class DataDomainDelta {
|
|
|
181
184
|
* @param domain The data domain where the entity will reside.
|
|
182
185
|
* @param e The schema definition of the entity to be added.
|
|
183
186
|
*/
|
|
184
|
-
protected handleAddEntity(
|
|
185
|
-
const targetModel = this.getModel(domain, e.modelKey || 'ai_generated')
|
|
187
|
+
protected handleAddEntity(e: AiDomainEntityResponseSchema): void {
|
|
188
|
+
const targetModel = this.getModel(this.domain, e.modelKey || 'ai_generated')
|
|
186
189
|
const entityInput = { ...e }
|
|
187
190
|
delete entityInput.semantics
|
|
188
191
|
let entityKey = this.keyMap.get(e.key)
|
|
@@ -261,7 +264,7 @@ export class DataDomainDelta {
|
|
|
261
264
|
writeOnly: p.constraints?.writeOnly,
|
|
262
265
|
deprecated: p.deprecated,
|
|
263
266
|
schema: p.schema,
|
|
264
|
-
tags: p.tags,
|
|
267
|
+
tags: p.tags || undefined,
|
|
265
268
|
})
|
|
266
269
|
this.applySemantics(prop, p.semantics)
|
|
267
270
|
}
|
|
@@ -273,7 +276,7 @@ export class DataDomainDelta {
|
|
|
273
276
|
* @param domain The target data domain.
|
|
274
277
|
* @param keys The array of property keys (AI-generated or actual) to remove.
|
|
275
278
|
*/
|
|
276
|
-
handlePropertyDeletes(domain: DataDomain, keys?: string[]): void {
|
|
279
|
+
protected handlePropertyDeletes(domain: DataDomain, keys?: string[]): void {
|
|
277
280
|
if (!keys) {
|
|
278
281
|
return
|
|
279
282
|
}
|
|
@@ -294,7 +297,7 @@ export class DataDomainDelta {
|
|
|
294
297
|
* @param domain The target data domain.
|
|
295
298
|
* @param mods The list of property modifications to apply.
|
|
296
299
|
*/
|
|
297
|
-
handlePropertyMods(domain: DataDomain, mods?: AiDomainPropertyDelta[]): void {
|
|
300
|
+
protected handlePropertyMods(domain: DataDomain, mods?: AiDomainPropertyDelta[]): void {
|
|
298
301
|
if (!mods) {
|
|
299
302
|
return
|
|
300
303
|
}
|
|
@@ -317,72 +320,76 @@ export class DataDomainDelta {
|
|
|
317
320
|
prop.type = mod.type
|
|
318
321
|
}
|
|
319
322
|
if (mod.deprecated !== undefined) {
|
|
320
|
-
prop.deprecated = mod.deprecated
|
|
323
|
+
prop.deprecated = mod.deprecated === null ? undefined : mod.deprecated
|
|
321
324
|
}
|
|
322
325
|
if (mod.constraints) {
|
|
323
326
|
if (mod.constraints.required !== undefined) {
|
|
324
|
-
prop.required = mod.constraints.required
|
|
327
|
+
prop.required = mod.constraints.required === null ? undefined : mod.constraints.required
|
|
325
328
|
}
|
|
326
329
|
if (mod.constraints.unique !== undefined) {
|
|
327
|
-
prop.unique = mod.constraints.unique
|
|
330
|
+
prop.unique = mod.constraints.unique === null ? undefined : mod.constraints.unique
|
|
328
331
|
}
|
|
329
332
|
if (mod.constraints.index !== undefined) {
|
|
330
|
-
prop.index = mod.constraints.index
|
|
333
|
+
prop.index = mod.constraints.index === null ? undefined : mod.constraints.index
|
|
331
334
|
}
|
|
332
335
|
if (mod.constraints.primary !== undefined) {
|
|
333
|
-
prop.primary = mod.constraints.primary
|
|
336
|
+
prop.primary = mod.constraints.primary === null ? undefined : mod.constraints.primary
|
|
334
337
|
}
|
|
335
338
|
if (mod.constraints.multiple !== undefined) {
|
|
336
|
-
prop.multiple = mod.constraints.multiple
|
|
339
|
+
prop.multiple = mod.constraints.multiple === null ? undefined : mod.constraints.multiple
|
|
337
340
|
}
|
|
338
341
|
if (mod.constraints.readOnly !== undefined) {
|
|
339
|
-
prop.readOnly = mod.constraints.readOnly
|
|
342
|
+
prop.readOnly = mod.constraints.readOnly === null ? undefined : mod.constraints.readOnly
|
|
340
343
|
}
|
|
341
344
|
if (mod.constraints.writeOnly !== undefined) {
|
|
342
|
-
prop.writeOnly = mod.constraints.writeOnly
|
|
345
|
+
prop.writeOnly = mod.constraints.writeOnly === null ? undefined : mod.constraints.writeOnly
|
|
343
346
|
}
|
|
344
347
|
}
|
|
345
348
|
if (mod.schema) {
|
|
346
349
|
if (!prop.schema) {
|
|
347
350
|
prop.schema = {}
|
|
348
351
|
}
|
|
349
|
-
if (mod.schema.defaultValue) {
|
|
350
|
-
if (
|
|
351
|
-
prop.schema.defaultValue =
|
|
352
|
-
|
|
353
|
-
|
|
352
|
+
if (mod.schema.defaultValue !== undefined) {
|
|
353
|
+
if (mod.schema.defaultValue === null) {
|
|
354
|
+
prop.schema.defaultValue = undefined
|
|
355
|
+
} else {
|
|
356
|
+
if (!prop.schema.defaultValue) {
|
|
357
|
+
prop.schema.defaultValue = {
|
|
358
|
+
value: '',
|
|
359
|
+
type: 'literal',
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (mod.schema.defaultValue.type) {
|
|
363
|
+
prop.schema.defaultValue.type = mod.schema.defaultValue.type
|
|
364
|
+
}
|
|
365
|
+
if (mod.schema.defaultValue.value) {
|
|
366
|
+
prop.schema.defaultValue.value = mod.schema.defaultValue.value
|
|
354
367
|
}
|
|
355
|
-
}
|
|
356
|
-
if (mod.schema.defaultValue.type) {
|
|
357
|
-
prop.schema.defaultValue.type = mod.schema.defaultValue.type
|
|
358
|
-
}
|
|
359
|
-
if (mod.schema.defaultValue.value) {
|
|
360
|
-
prop.schema.defaultValue.value = mod.schema.defaultValue.value
|
|
361
368
|
}
|
|
362
369
|
}
|
|
363
370
|
if (mod.schema.pattern !== undefined) {
|
|
364
|
-
prop.schema.pattern = mod.schema.pattern
|
|
371
|
+
prop.schema.pattern = mod.schema.pattern === null ? undefined : mod.schema.pattern
|
|
365
372
|
}
|
|
366
373
|
if (mod.schema.minimum !== undefined) {
|
|
367
|
-
prop.schema.minimum = mod.schema.minimum
|
|
374
|
+
prop.schema.minimum = mod.schema.minimum === null ? undefined : mod.schema.minimum
|
|
368
375
|
}
|
|
369
376
|
if (mod.schema.maximum !== undefined) {
|
|
370
|
-
prop.schema.maximum = mod.schema.maximum
|
|
377
|
+
prop.schema.maximum = mod.schema.maximum === null ? undefined : mod.schema.maximum
|
|
371
378
|
}
|
|
372
379
|
if (mod.schema.exclusiveMinimum !== undefined) {
|
|
373
|
-
prop.schema.exclusiveMinimum = mod.schema.exclusiveMinimum
|
|
380
|
+
prop.schema.exclusiveMinimum = mod.schema.exclusiveMinimum === null ? undefined : mod.schema.exclusiveMinimum
|
|
374
381
|
}
|
|
375
382
|
if (mod.schema.exclusiveMaximum !== undefined) {
|
|
376
|
-
prop.schema.exclusiveMaximum = mod.schema.exclusiveMaximum
|
|
383
|
+
prop.schema.exclusiveMaximum = mod.schema.exclusiveMaximum === null ? undefined : mod.schema.exclusiveMaximum
|
|
377
384
|
}
|
|
378
385
|
if (mod.schema.multipleOf !== undefined) {
|
|
379
|
-
prop.schema.multipleOf = mod.schema.multipleOf
|
|
386
|
+
prop.schema.multipleOf = mod.schema.multipleOf === null ? undefined : mod.schema.multipleOf
|
|
380
387
|
}
|
|
381
388
|
if (mod.schema.enum !== undefined) {
|
|
382
|
-
prop.schema.enum = [...mod.schema.enum]
|
|
389
|
+
prop.schema.enum = mod.schema.enum === null ? undefined : [...mod.schema.enum]
|
|
383
390
|
}
|
|
384
391
|
if (mod.schema.examples !== undefined) {
|
|
385
|
-
prop.schema.examples = [...mod.schema.examples]
|
|
392
|
+
prop.schema.examples = mod.schema.examples === null ? undefined : [...mod.schema.examples]
|
|
386
393
|
}
|
|
387
394
|
}
|
|
388
395
|
this.applySemantics(prop, mod.addedSemantics, mod.modifiedSemantics, mod.deletedSemanticIds)
|
|
@@ -395,7 +402,7 @@ export class DataDomainDelta {
|
|
|
395
402
|
* @param entity The target domain entity referencing the newly created associations.
|
|
396
403
|
* @param adds An array of association definitions to add, if any.
|
|
397
404
|
*/
|
|
398
|
-
handleAssociationAdds(entity: DomainEntity, adds: AiDomainAssociation[] | undefined): void {
|
|
405
|
+
protected handleAssociationAdds(entity: DomainEntity, adds: AiDomainAssociation[] | undefined): void {
|
|
399
406
|
if (!adds) {
|
|
400
407
|
return
|
|
401
408
|
}
|
|
@@ -412,7 +419,7 @@ export class DataDomainDelta {
|
|
|
412
419
|
* @param entity The source domain entity creating the association.
|
|
413
420
|
* @param a The defining schema for the new association.
|
|
414
421
|
*/
|
|
415
|
-
handleAddAssociation(entity: DomainEntity, a: AiDomainAssociation): void {
|
|
422
|
+
protected handleAddAssociation(entity: DomainEntity, a: AiDomainAssociation): void {
|
|
416
423
|
let assocKey = this.keyMap.get(a.key)
|
|
417
424
|
if (!assocKey) {
|
|
418
425
|
assocKey = nanoid()
|
|
@@ -467,7 +474,7 @@ export class DataDomainDelta {
|
|
|
467
474
|
* @param domain The target data domain.
|
|
468
475
|
* @param keys An array of association keys to safely remove.
|
|
469
476
|
*/
|
|
470
|
-
handleAssociationDeletes(domain: DataDomain, keys?: string[]): void {
|
|
477
|
+
protected handleAssociationDeletes(domain: DataDomain, keys?: string[]): void {
|
|
471
478
|
if (!keys) {
|
|
472
479
|
return
|
|
473
480
|
}
|
|
@@ -488,7 +495,7 @@ export class DataDomainDelta {
|
|
|
488
495
|
* @param domain The target data domain containing the associations.
|
|
489
496
|
* @param mods An array of requested association modifications.
|
|
490
497
|
*/
|
|
491
|
-
handleAssociationMods(domain: DataDomain, mods: AiDomainAssociationDelta[] | undefined): void {
|
|
498
|
+
protected handleAssociationMods(domain: DataDomain, mods: AiDomainAssociationDelta[] | undefined): void {
|
|
492
499
|
if (!mods) {
|
|
493
500
|
return
|
|
494
501
|
}
|
|
@@ -508,10 +515,13 @@ export class DataDomainDelta {
|
|
|
508
515
|
assoc.info.description = mod.description
|
|
509
516
|
}
|
|
510
517
|
if (mod.required !== undefined) {
|
|
511
|
-
assoc.required = mod.required
|
|
518
|
+
assoc.required = mod.required === null ? undefined : mod.required
|
|
519
|
+
}
|
|
520
|
+
if (mod.multiple !== undefined) {
|
|
521
|
+
assoc.multiple = mod.multiple === null ? undefined : mod.multiple
|
|
512
522
|
}
|
|
513
523
|
if (mod.onDelete !== undefined) {
|
|
514
|
-
assoc.onDelete = mod.onDelete
|
|
524
|
+
assoc.onDelete = mod.onDelete === null ? undefined : mod.onDelete
|
|
515
525
|
}
|
|
516
526
|
|
|
517
527
|
if (mod.targets) {
|
|
@@ -9,6 +9,18 @@ const SemanticSchema = {
|
|
|
9
9
|
required: ['id'],
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
const AssociationTarget = {
|
|
13
|
+
type: Type.OBJECT,
|
|
14
|
+
properties: {
|
|
15
|
+
key: { type: Type.STRING, description: 'The key of the target entity.' },
|
|
16
|
+
domain: {
|
|
17
|
+
type: Type.STRING,
|
|
18
|
+
description: 'The key of the target data domain. Only set when the target is in a different data domain.',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
required: ['key'],
|
|
22
|
+
}
|
|
23
|
+
|
|
12
24
|
const SchemaDefaultValue = {
|
|
13
25
|
type: Type.OBJECT,
|
|
14
26
|
properties: {
|
|
@@ -27,28 +39,28 @@ const SchemaDefaultValue = {
|
|
|
27
39
|
const PropertySchemaShape = {
|
|
28
40
|
type: Type.OBJECT,
|
|
29
41
|
properties: {
|
|
30
|
-
minimum: { type: Type.NUMBER },
|
|
31
|
-
maximum: { type: Type.NUMBER },
|
|
32
|
-
exclusiveMinimum: { type: Type.BOOLEAN },
|
|
33
|
-
exclusiveMaximum: { type: Type.BOOLEAN },
|
|
34
|
-
multipleOf: { type: Type.NUMBER },
|
|
35
|
-
enum: { type: Type.ARRAY, items: { type: Type.STRING } },
|
|
36
|
-
examples: { type: Type.ARRAY, items: { type: Type.STRING } },
|
|
37
|
-
defaultValue: SchemaDefaultValue,
|
|
38
|
-
pattern: { type: Type.STRING },
|
|
42
|
+
minimum: { type: Type.NUMBER, nullable: true },
|
|
43
|
+
maximum: { type: Type.NUMBER, nullable: true },
|
|
44
|
+
exclusiveMinimum: { type: Type.BOOLEAN, nullable: true },
|
|
45
|
+
exclusiveMaximum: { type: Type.BOOLEAN, nullable: true },
|
|
46
|
+
multipleOf: { type: Type.NUMBER, nullable: true },
|
|
47
|
+
enum: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
|
|
48
|
+
examples: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
|
|
49
|
+
defaultValue: { ...SchemaDefaultValue, nullable: true },
|
|
50
|
+
pattern: { type: Type.STRING, nullable: true },
|
|
39
51
|
},
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
const PropertyConstraintsSchema = {
|
|
43
55
|
type: Type.OBJECT,
|
|
44
56
|
properties: {
|
|
45
|
-
required: { type: Type.BOOLEAN },
|
|
46
|
-
unique: { type: Type.BOOLEAN },
|
|
47
|
-
index: { type: Type.BOOLEAN },
|
|
48
|
-
primary: { type: Type.BOOLEAN },
|
|
49
|
-
multiple: { type: Type.BOOLEAN },
|
|
50
|
-
readOnly: { type: Type.BOOLEAN },
|
|
51
|
-
writeOnly: { type: Type.BOOLEAN },
|
|
57
|
+
required: { type: Type.BOOLEAN, nullable: true },
|
|
58
|
+
unique: { type: Type.BOOLEAN, nullable: true },
|
|
59
|
+
index: { type: Type.BOOLEAN, nullable: true },
|
|
60
|
+
primary: { type: Type.BOOLEAN, nullable: true },
|
|
61
|
+
multiple: { type: Type.BOOLEAN, nullable: true },
|
|
62
|
+
readOnly: { type: Type.BOOLEAN, nullable: true },
|
|
63
|
+
writeOnly: { type: Type.BOOLEAN, nullable: true },
|
|
52
64
|
},
|
|
53
65
|
}
|
|
54
66
|
|
|
@@ -74,7 +86,7 @@ const PropertySchema = {
|
|
|
74
86
|
items: SemanticSchema,
|
|
75
87
|
description: "List of semantics applied to this property. Note: ONLY use semantics with scope='property'.",
|
|
76
88
|
},
|
|
77
|
-
tags: { type: Type.ARRAY, items: { type: Type.STRING } },
|
|
89
|
+
tags: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
|
|
78
90
|
},
|
|
79
91
|
required: ['key', 'name', 'type', 'displayName', 'description'],
|
|
80
92
|
}
|
|
@@ -97,7 +109,7 @@ const AssociationSchema = {
|
|
|
97
109
|
name: { type: Type.STRING },
|
|
98
110
|
displayName: { type: Type.STRING },
|
|
99
111
|
description: { type: Type.STRING },
|
|
100
|
-
targets: { type: Type.ARRAY, items:
|
|
112
|
+
targets: { type: Type.ARRAY, items: AssociationTarget },
|
|
101
113
|
required: { type: Type.BOOLEAN },
|
|
102
114
|
multiple: {
|
|
103
115
|
type: Type.BOOLEAN,
|
|
@@ -150,6 +162,9 @@ const EntitySchema = {
|
|
|
150
162
|
required: ['key', 'name', 'modelKey', 'displayName', 'description'],
|
|
151
163
|
}
|
|
152
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Allows modifying a property (not adding)
|
|
167
|
+
*/
|
|
153
168
|
const PropertyDeltaSchema = {
|
|
154
169
|
type: Type.OBJECT,
|
|
155
170
|
properties: {
|
|
@@ -161,9 +176,9 @@ const PropertyDeltaSchema = {
|
|
|
161
176
|
type: Type.STRING,
|
|
162
177
|
description: 'Enum: string, number, boolean, date, datetime, time, binary',
|
|
163
178
|
},
|
|
164
|
-
constraints: PropertyConstraintsSchema,
|
|
165
|
-
deprecated: { type: Type.BOOLEAN },
|
|
166
|
-
schema: PropertySchemaShape,
|
|
179
|
+
constraints: { ...PropertyConstraintsSchema, nullable: true },
|
|
180
|
+
deprecated: { type: Type.BOOLEAN, nullable: true },
|
|
181
|
+
schema: { ...PropertySchemaShape, nullable: true },
|
|
167
182
|
addedSemantics: {
|
|
168
183
|
type: Type.ARRAY,
|
|
169
184
|
items: SemanticSchema,
|
|
@@ -182,13 +197,14 @@ const AssociationDeltaSchema = {
|
|
|
182
197
|
name: { type: Type.STRING },
|
|
183
198
|
displayName: { type: Type.STRING },
|
|
184
199
|
description: { type: Type.STRING },
|
|
185
|
-
targets: { type: Type.ARRAY, items:
|
|
186
|
-
required: { type: Type.BOOLEAN },
|
|
200
|
+
targets: { type: Type.ARRAY, items: AssociationTarget },
|
|
201
|
+
required: { type: Type.BOOLEAN, nullable: true },
|
|
187
202
|
multiple: {
|
|
188
203
|
type: Type.BOOLEAN,
|
|
204
|
+
nullable: true,
|
|
189
205
|
description: 'Whether the association can have multiple targets (like User has multiple addresses)',
|
|
190
206
|
},
|
|
191
|
-
onDelete: { type: Type.STRING, description: 'Enum: restrict, cascade, setNull, doNothing' },
|
|
207
|
+
onDelete: { type: Type.STRING, nullable: true, description: 'Enum: restrict, cascade, setNull, doNothing' },
|
|
192
208
|
addedSemantics: {
|
|
193
209
|
type: Type.ARRAY,
|
|
194
210
|
items: SemanticSchema,
|
|
@@ -256,7 +272,7 @@ export const DOMAIN_SCHEMA = {
|
|
|
256
272
|
name: { type: Type.STRING },
|
|
257
273
|
displayName: { type: Type.STRING },
|
|
258
274
|
description: { type: Type.STRING },
|
|
259
|
-
tags: { type: Type.ARRAY, items: { type: Type.STRING } },
|
|
275
|
+
tags: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
|
|
260
276
|
addedSemantics: {
|
|
261
277
|
type: Type.ARRAY,
|
|
262
278
|
items: SemanticSchema,
|
|
@@ -19,13 +19,12 @@ The \`reasoning\` string in your JSON output is the presentation layer. It will
|
|
|
19
19
|
- **Keep it Conversational:** Use simple markdown (like bullet points) to provide a friendly, easily scannable summary of what you built for them.
|
|
20
20
|
- **Proactive Next Steps:** Always conclude your summary with a single, highly relevant question asking the user what they want to do next. Base this on what you just built or what might be missing.
|
|
21
21
|
|
|
22
|
-
# REFERENTIAL INTEGRITY (
|
|
23
|
-
You must absolutely guarantee that
|
|
24
|
-
- **
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- **
|
|
28
|
-
- **Missing Targets:** If the user asks you to link to an entity that does not exist, you MUST create that missing entity in \`addedEntities\` first so you have a valid key to target.
|
|
22
|
+
# REFERENTIAL INTEGRITY (STRICT KEYS ONLY)
|
|
23
|
+
You must absolutely guarantee that you never hallucinate or invent a \`key\` for an existing object.
|
|
24
|
+
- **Modifications & Deletions:** When adding objects to \`modifiedModels\`, \`modifiedEntities\`, \`deletedModelKeys\`, or \`deletedEntityKeys\`, the \`key\` you use MUST be an exact match to an existing \`nanoid\` key provided to you in the Current Domain Context.
|
|
25
|
+
- **Association Targets:** A target key in an association is ONLY valid if it exists in the Current Domain Context, or if you are actively creating it in \`addedEntities\`.
|
|
26
|
+
- **ANTI-PATTERN:** Inventing a placeholder key to modify an object that you don't know the exact nanoid for.
|
|
27
|
+
- **Handling Missing Objects:** If the user asks you to modify an entity but it does not exist in the provided context, you MUST assume it is a brand new entity. Define its complete schema inside \`addedEntities\` instead of trying to modify a phantom key.
|
|
29
28
|
|
|
30
29
|
# CREATION & DEPENDENCY LOGIC (THE TWO-PASS RULE)
|
|
31
30
|
When creating multiple new entities that relate to one another, you must respect referential integrity. You cannot reference an entity in an association before it exists.
|
|
@@ -76,4 +75,10 @@ You are an enterprise Data Architect. You must actively defend against malicious
|
|
|
76
75
|
- **Conciseness:** If an operation requires more than 10 properties, suggest splitting the task into two parts rather than outputting one massive JSON array.
|
|
77
76
|
- **No Encoding:** Never attempt to output Base64, Hex, or encoded strings unless explicitly requested for a \`binary\` type.
|
|
78
77
|
- **Loop Prevention:** If you find yourself repeating the same key or value more than 5 times in a single array, stop and ask the user for clarification.
|
|
78
|
+
|
|
79
|
+
# PARTIAL UPDATES & DELETIONS
|
|
80
|
+
When modifying existing objects in the \`modifiedEntities\` or \`modifiedModels\` arrays, use strict partial-update logic:
|
|
81
|
+
- **To update a value:** Provide the key and the new value.
|
|
82
|
+
- **To leave a value unchanged:** Completely omit the key from the JSON object. Do not output it.
|
|
83
|
+
- **To delete an existing value:** You MUST explicitly output the key with a value of \`null\` (e.g., \`"description": null\`).
|
|
79
84
|
`
|
package/src/modeling/ai/types.ts
CHANGED
|
@@ -132,7 +132,7 @@ export interface AiDomainProperty {
|
|
|
132
132
|
deprecated?: boolean
|
|
133
133
|
schema?: PropertySchema
|
|
134
134
|
semantics?: AiDomainSemantic[]
|
|
135
|
-
tags?: string[]
|
|
135
|
+
tags?: string[] | null
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
/**
|
|
@@ -226,7 +226,7 @@ export interface AiDomainEntityDelta {
|
|
|
226
226
|
name?: string
|
|
227
227
|
displayName?: string
|
|
228
228
|
description?: string
|
|
229
|
-
tags?: string[]
|
|
229
|
+
tags?: string[] | null
|
|
230
230
|
// Entity semantics delta
|
|
231
231
|
addedSemantics?: AiDomainSemantic[]
|
|
232
232
|
modifiedSemantics?: AiDomainSemantic[]
|
|
@@ -240,6 +240,10 @@ export interface AiDomainEntityDelta {
|
|
|
240
240
|
deletedAssociationKeys?: string[]
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
export type NullablePropertySchema = {
|
|
244
|
+
[K in keyof PropertySchema]?: PropertySchema[K] | null
|
|
245
|
+
}
|
|
246
|
+
|
|
243
247
|
/**
|
|
244
248
|
* Represents a targeted modification to an existing property generated by the AI.
|
|
245
249
|
* It captures changes to superficial properties (name, description), type changes,
|
|
@@ -252,20 +256,20 @@ export interface AiDomainPropertyDelta {
|
|
|
252
256
|
description?: string
|
|
253
257
|
type?: DomainPropertyType
|
|
254
258
|
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
|
|
259
|
+
required?: boolean | null
|
|
260
|
+
unique?: boolean | null
|
|
261
|
+
index?: boolean | null
|
|
262
|
+
primary?: boolean | null
|
|
263
|
+
multiple?: boolean | null
|
|
264
|
+
readOnly?: boolean | null
|
|
265
|
+
writeOnly?: boolean | null
|
|
266
|
+
} | null
|
|
267
|
+
deprecated?: boolean | null
|
|
264
268
|
// Property semantics delta
|
|
265
269
|
addedSemantics?: AiDomainSemantic[]
|
|
266
270
|
modifiedSemantics?: AiDomainSemantic[]
|
|
267
271
|
deletedSemanticIds?: SemanticType[]
|
|
268
|
-
schema?:
|
|
272
|
+
schema?: NullablePropertySchema
|
|
269
273
|
}
|
|
270
274
|
|
|
271
275
|
/**
|
|
@@ -279,8 +283,9 @@ export interface AiDomainAssociationDelta {
|
|
|
279
283
|
displayName?: string
|
|
280
284
|
description?: string
|
|
281
285
|
targets?: AssociationTarget[]
|
|
282
|
-
required?: boolean
|
|
283
|
-
|
|
286
|
+
required?: boolean | null
|
|
287
|
+
multiple?: boolean | null
|
|
288
|
+
onDelete?: OnDeleteRule | null
|
|
284
289
|
// Association semantics delta
|
|
285
290
|
addedSemantics?: AiDomainSemantic[]
|
|
286
291
|
modifiedSemantics?: AiDomainSemantic[]
|
|
@@ -189,6 +189,116 @@ test.group('DataDomainDelta.apply()', () => {
|
|
|
189
189
|
assert.equal(prop2!.info.name, 'New Prop')
|
|
190
190
|
})
|
|
191
191
|
|
|
192
|
+
test('unsets properties, constraints, schema, and association options using null values', ({ assert }) => {
|
|
193
|
+
const domain = new DataDomain()
|
|
194
|
+
const model = domain.addModel()
|
|
195
|
+
const entity = domain.addEntity(model.key, { info: { name: 'unset-entity' }, tags: ['tag1'] })
|
|
196
|
+
|
|
197
|
+
entity.addProperty({
|
|
198
|
+
key: 'prop1',
|
|
199
|
+
type: 'string',
|
|
200
|
+
deprecated: true,
|
|
201
|
+
required: true,
|
|
202
|
+
unique: true,
|
|
203
|
+
index: true,
|
|
204
|
+
primary: true,
|
|
205
|
+
multiple: true,
|
|
206
|
+
readOnly: true,
|
|
207
|
+
writeOnly: true,
|
|
208
|
+
schema: {
|
|
209
|
+
defaultValue: { type: 'literal', value: 'foo' },
|
|
210
|
+
pattern: '^[a-z]+$',
|
|
211
|
+
minimum: 1,
|
|
212
|
+
maximum: 10,
|
|
213
|
+
exclusiveMinimum: true,
|
|
214
|
+
exclusiveMaximum: true,
|
|
215
|
+
multipleOf: 2,
|
|
216
|
+
enum: ['foo', 'bar'],
|
|
217
|
+
examples: ['foo'],
|
|
218
|
+
},
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
entity.addAssociation({
|
|
222
|
+
key: 'assoc1',
|
|
223
|
+
required: true,
|
|
224
|
+
multiple: true,
|
|
225
|
+
onDelete: 'cascade',
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
const delta = {
|
|
229
|
+
modifiedEntities: [
|
|
230
|
+
{
|
|
231
|
+
key: entity.key,
|
|
232
|
+
tags: null,
|
|
233
|
+
modifiedProperties: [
|
|
234
|
+
{
|
|
235
|
+
key: 'prop1',
|
|
236
|
+
deprecated: null,
|
|
237
|
+
constraints: {
|
|
238
|
+
required: null,
|
|
239
|
+
unique: null,
|
|
240
|
+
index: null,
|
|
241
|
+
primary: null,
|
|
242
|
+
multiple: null,
|
|
243
|
+
readOnly: null,
|
|
244
|
+
writeOnly: null,
|
|
245
|
+
},
|
|
246
|
+
schema: {
|
|
247
|
+
defaultValue: null,
|
|
248
|
+
pattern: null,
|
|
249
|
+
minimum: null,
|
|
250
|
+
maximum: null,
|
|
251
|
+
exclusiveMinimum: null,
|
|
252
|
+
exclusiveMaximum: null,
|
|
253
|
+
multipleOf: null,
|
|
254
|
+
enum: null,
|
|
255
|
+
examples: null,
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
modifiedAssociations: [
|
|
260
|
+
{
|
|
261
|
+
key: 'assoc1',
|
|
262
|
+
required: null,
|
|
263
|
+
multiple: null,
|
|
264
|
+
onDelete: null,
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const instance = new DataDomainDelta(domain)
|
|
272
|
+
instance.apply(delta)
|
|
273
|
+
|
|
274
|
+
assert.lengthOf(entity.tags, 0)
|
|
275
|
+
|
|
276
|
+
const prop1 = domain.findProperty('prop1')!
|
|
277
|
+
assert.isUndefined(prop1.deprecated)
|
|
278
|
+
assert.isUndefined(prop1.required)
|
|
279
|
+
assert.isUndefined(prop1.unique)
|
|
280
|
+
assert.isUndefined(prop1.index)
|
|
281
|
+
assert.isUndefined(prop1.primary)
|
|
282
|
+
assert.isUndefined(prop1.multiple)
|
|
283
|
+
assert.isUndefined(prop1.readOnly)
|
|
284
|
+
assert.isUndefined(prop1.writeOnly)
|
|
285
|
+
|
|
286
|
+
assert.isUndefined(prop1.schema?.defaultValue)
|
|
287
|
+
assert.isUndefined(prop1.schema?.pattern)
|
|
288
|
+
assert.isUndefined(prop1.schema?.minimum)
|
|
289
|
+
assert.isUndefined(prop1.schema?.maximum)
|
|
290
|
+
assert.isUndefined(prop1.schema?.exclusiveMinimum)
|
|
291
|
+
assert.isUndefined(prop1.schema?.exclusiveMaximum)
|
|
292
|
+
assert.isUndefined(prop1.schema?.multipleOf)
|
|
293
|
+
assert.isUndefined(prop1.schema?.enum)
|
|
294
|
+
assert.isUndefined(prop1.schema?.examples)
|
|
295
|
+
|
|
296
|
+
const assoc1 = domain.findAssociation('assoc1')!
|
|
297
|
+
assert.isUndefined(assoc1.required)
|
|
298
|
+
assert.isUndefined(assoc1.multiple)
|
|
299
|
+
assert.isUndefined(assoc1.onDelete)
|
|
300
|
+
})
|
|
301
|
+
|
|
192
302
|
test('deletes entity properties', ({ assert }) => {
|
|
193
303
|
const domain = new DataDomain()
|
|
194
304
|
const model = domain.addModel()
|