@papr/memory 1.19.0 → 2.0.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.
Files changed (130) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE +1 -1
  3. package/README.md +13 -1
  4. package/client.d.mts +38 -10
  5. package/client.d.mts.map +1 -1
  6. package/client.d.ts +38 -10
  7. package/client.d.ts.map +1 -1
  8. package/client.js +17 -2
  9. package/client.js.map +1 -1
  10. package/client.mjs +17 -2
  11. package/client.mjs.map +1 -1
  12. package/internal/parse.d.mts.map +1 -1
  13. package/internal/parse.d.ts.map +1 -1
  14. package/internal/parse.js +5 -0
  15. package/internal/parse.js.map +1 -1
  16. package/internal/parse.mjs +5 -0
  17. package/internal/parse.mjs.map +1 -1
  18. package/internal/tslib.js +22 -22
  19. package/package.json +1 -1
  20. package/resources/document.d.mts +16 -3
  21. package/resources/document.d.mts.map +1 -1
  22. package/resources/document.d.ts +16 -3
  23. package/resources/document.d.ts.map +1 -1
  24. package/resources/index.d.mts +6 -3
  25. package/resources/index.d.mts.map +1 -1
  26. package/resources/index.d.ts +6 -3
  27. package/resources/index.d.ts.map +1 -1
  28. package/resources/index.js +7 -1
  29. package/resources/index.js.map +1 -1
  30. package/resources/index.mjs +3 -0
  31. package/resources/index.mjs.map +1 -1
  32. package/resources/memory.d.mts +527 -95
  33. package/resources/memory.d.mts.map +1 -1
  34. package/resources/memory.d.ts +527 -95
  35. package/resources/memory.d.ts.map +1 -1
  36. package/resources/memory.js +21 -6
  37. package/resources/memory.js.map +1 -1
  38. package/resources/memory.mjs +21 -6
  39. package/resources/memory.mjs.map +1 -1
  40. package/resources/messages/index.d.mts +3 -0
  41. package/resources/messages/index.d.mts.map +1 -0
  42. package/resources/messages/index.d.ts +3 -0
  43. package/resources/messages/index.d.ts.map +1 -0
  44. package/resources/messages/index.js +9 -0
  45. package/resources/messages/index.js.map +1 -0
  46. package/resources/messages/index.mjs +4 -0
  47. package/resources/messages/index.mjs.map +1 -0
  48. package/resources/messages/messages.d.mts +160 -0
  49. package/resources/messages/messages.d.mts.map +1 -0
  50. package/resources/messages/messages.d.ts +160 -0
  51. package/resources/messages/messages.d.ts.map +1 -0
  52. package/resources/messages/messages.js +54 -0
  53. package/resources/messages/messages.js.map +1 -0
  54. package/resources/messages/messages.mjs +49 -0
  55. package/resources/messages/messages.mjs.map +1 -0
  56. package/resources/messages/sessions.d.mts +262 -0
  57. package/resources/messages/sessions.d.mts.map +1 -0
  58. package/resources/messages/sessions.d.ts +262 -0
  59. package/resources/messages/sessions.d.ts.map +1 -0
  60. package/resources/messages/sessions.js +122 -0
  61. package/resources/messages/sessions.js.map +1 -0
  62. package/resources/messages/sessions.mjs +118 -0
  63. package/resources/messages/sessions.mjs.map +1 -0
  64. package/resources/messages.d.mts +2 -0
  65. package/resources/messages.d.mts.map +1 -0
  66. package/resources/messages.d.ts +2 -0
  67. package/resources/messages.d.ts.map +1 -0
  68. package/resources/messages.js +6 -0
  69. package/resources/messages.js.map +1 -0
  70. package/resources/messages.mjs +3 -0
  71. package/resources/messages.mjs.map +1 -0
  72. package/resources/omo.d.mts +98 -0
  73. package/resources/omo.d.mts.map +1 -0
  74. package/resources/omo.d.ts +98 -0
  75. package/resources/omo.d.ts.map +1 -0
  76. package/resources/omo.js +36 -0
  77. package/resources/omo.js.map +1 -0
  78. package/resources/omo.mjs +32 -0
  79. package/resources/omo.mjs.map +1 -0
  80. package/resources/schemas.d.mts +712 -92
  81. package/resources/schemas.d.mts.map +1 -1
  82. package/resources/schemas.d.ts +712 -92
  83. package/resources/schemas.d.ts.map +1 -1
  84. package/resources/schemas.js +23 -10
  85. package/resources/schemas.js.map +1 -1
  86. package/resources/schemas.mjs +23 -10
  87. package/resources/schemas.mjs.map +1 -1
  88. package/resources/shared.d.mts +671 -0
  89. package/resources/shared.d.mts.map +1 -1
  90. package/resources/shared.d.ts +671 -0
  91. package/resources/shared.d.ts.map +1 -1
  92. package/resources/sync.d.mts +142 -0
  93. package/resources/sync.d.mts.map +1 -0
  94. package/resources/sync.d.ts +142 -0
  95. package/resources/sync.d.ts.map +1 -0
  96. package/resources/sync.js +36 -0
  97. package/resources/sync.js.map +1 -0
  98. package/resources/sync.mjs +32 -0
  99. package/resources/sync.mjs.map +1 -0
  100. package/resources/user.d.mts +18 -1
  101. package/resources/user.d.mts.map +1 -1
  102. package/resources/user.d.ts +18 -1
  103. package/resources/user.d.ts.map +1 -1
  104. package/resources/user.js +11 -0
  105. package/resources/user.js.map +1 -1
  106. package/resources/user.mjs +11 -0
  107. package/resources/user.mjs.map +1 -1
  108. package/src/client.ts +81 -9
  109. package/src/internal/parse.ts +6 -0
  110. package/src/resources/document.ts +17 -4
  111. package/src/resources/index.ts +21 -0
  112. package/src/resources/memory.ts +586 -134
  113. package/src/resources/messages/index.ts +11 -0
  114. package/src/resources/messages/messages.ts +193 -0
  115. package/src/resources/messages/sessions.ts +315 -0
  116. package/src/resources/messages.ts +3 -0
  117. package/src/resources/omo.ts +132 -0
  118. package/src/resources/schemas.ts +740 -111
  119. package/src/resources/shared.ts +752 -0
  120. package/src/resources/sync.ts +179 -0
  121. package/src/resources/user.ts +23 -0
  122. package/src/version.ts +1 -1
  123. package/version.d.mts +1 -1
  124. package/version.d.mts.map +1 -1
  125. package/version.d.ts +1 -1
  126. package/version.d.ts.map +1 -1
  127. package/version.js +1 -1
  128. package/version.js.map +1 -1
  129. package/version.mjs +1 -1
  130. package/version.mjs.map +1 -1
@@ -1,6 +1,8 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  import { APIResource } from '../core/resource';
4
+ import * as SchemasAPI from './schemas';
5
+ import * as Shared from './shared';
4
6
  import { APIPromise } from '../core/api-promise';
5
7
  import { RequestOptions } from '../internal/request-options';
6
8
  import { path } from '../internal/utils/path';
@@ -16,9 +18,16 @@ export class Schemas extends APIResource {
16
18
  * - Define custom node types with properties and validation rules
17
19
  * - Define custom relationship types with constraints
18
20
  * - Automatic validation against system schemas
19
- * - Support for different scopes (personal, workspace, organization)
20
- * - **Enum support**: Use `enum_values` to restrict property values to a predefined list (max 10 values)
21
- * - **Auto-indexing**: Required properties are automatically indexed in Neo4j for optimal query performance
21
+ * - Support for different scopes (personal, workspace, namespace, organization)
22
+ * - **Status control**: Set `status` to "active" to immediately activate the schema, or "draft" to save as draft (default)
23
+ * - **Enum support**: Use `enum_values` to restrict property values to a predefined list (max 15 values)
24
+ * - **Auto-indexing**: Required properties are automatically indexed in Neo4j when schema becomes active
25
+ *
26
+ * **Schema Limits (optimized for LLM performance):**
27
+ * - **Maximum 10 node types** per schema
28
+ * - **Maximum 20 relationship types** per schema
29
+ * - **Maximum 10 properties** per node type
30
+ * - **Maximum 15 enum values** per property
22
31
  *
23
32
  * **Property Types & Validation:**
24
33
  * - `string`: Text values with optional `enum_values`, `min_length`, `max_length`, `pattern`
@@ -31,18 +40,18 @@ export class Schemas extends APIResource {
31
40
  *
32
41
  * **Enum Values:**
33
42
  * - Add `enum_values` to any string property to restrict values to a predefined list
34
- * - Maximum 10 enum values allowed per property
43
+ * - Maximum 15 enum values allowed per property
35
44
  * - Use with `default` to set a default enum value
36
45
  * - Example: `"enum_values": ["small", "medium", "large"]`
37
46
  *
38
47
  * **When to Use Enums:**
39
- * - Limited, well-defined options (≤10 values): sizes, statuses, categories, priorities
48
+ * - Limited, well-defined options (≤15 values): sizes, statuses, categories, priorities
40
49
  * - Controlled vocabularies: "active/inactive", "high/medium/low", "bronze/silver/gold"
41
50
  * - When you want exact matching and no variations
42
51
  *
43
52
  * **When to Avoid Enums:**
44
53
  * - Open-ended text fields: names, titles, descriptions, addresses
45
- * - Large sets of options (>10): countries, cities, product models
54
+ * - Large sets of options (>15): countries, cities, product models
46
55
  * - When you want semantic similarity matching for entity resolution
47
56
  * - Dynamic or frequently changing value sets
48
57
  *
@@ -52,8 +61,8 @@ export class Schemas extends APIResource {
52
61
  * - **Without enum_values**: Semantic similarity matching is used - entities with similar meanings are automatically merged
53
62
  * - Example: A "name" unique_identifier without enums will merge "Apple Inc" and "Apple Inc." as the same entity
54
63
  * - Example: A "sku" unique_identifier with enums will only merge entities with exactly matching SKU codes
55
- * - Use enums for unique_identifiers when you have a limited, predefined set of values (≤10 options)
56
- * - Avoid enums for unique_identifiers when you have broad, open-ended values or >10 possible options
64
+ * - Use enums for unique_identifiers when you have a limited, predefined set of values (≤15 options)
65
+ * - Avoid enums for unique_identifiers when you have broad, open-ended values or >15 possible options
57
66
  * - **Best practices**: Use enums for controlled vocabularies (status codes, categories), avoid for open text (company names, product titles)
58
67
  * - **In the example above**: "name" uses semantic similarity (open-ended), "sku" uses exact matching (controlled set)
59
68
  *
@@ -90,9 +99,14 @@ export class Schemas extends APIResource {
90
99
  /**
91
100
  * Update an existing schema.
92
101
  *
93
- * Allows modification of schema properties, node types, and relationship types.
102
+ * Allows modification of schema properties, node types, relationship types, and status.
94
103
  * User must have write access to the schema. Updates create a new version
95
104
  * while preserving the existing data.
105
+ *
106
+ * **Status Management:**
107
+ * - Set `status` to "active" to activate the schema and trigger Neo4j index creation
108
+ * - Set `status` to "draft" to deactivate the schema
109
+ * - Set `status` to "archived" to soft-delete the schema
96
110
  */
97
111
  update(
98
112
  schemaID: string,
@@ -108,7 +122,8 @@ export class Schemas extends APIResource {
108
122
  *
109
123
  * Returns schemas that the user owns or has read access to, including:
110
124
  * - Personal schemas created by the user
111
- * - Workspace schemas shared within the user's workspace
125
+ * - Workspace schemas shared within the user's workspace (legacy)
126
+ * - Namespace schemas shared within the user's namespace
112
127
  * - Organization schemas available to the user's organization
113
128
  *
114
129
  * **Authentication Required**:
@@ -136,6 +151,131 @@ export class Schemas extends APIResource {
136
151
  }
137
152
  }
138
153
 
154
+ /**
155
+ * Property definition for nodes/relationships
156
+ */
157
+ export interface PropertyDefinition {
158
+ type: 'string' | 'integer' | 'float' | 'boolean' | 'array' | 'datetime' | 'object';
159
+
160
+ default?: unknown;
161
+
162
+ description?: string | null;
163
+
164
+ /**
165
+ * List of allowed enum values (max 15)
166
+ */
167
+ enum_values?: Array<string> | null;
168
+
169
+ max_length?: number | null;
170
+
171
+ max_value?: number | null;
172
+
173
+ min_length?: number | null;
174
+
175
+ min_value?: number | null;
176
+
177
+ pattern?: string | null;
178
+
179
+ required?: boolean;
180
+ }
181
+
182
+ /**
183
+ * Configuration for finding/selecting existing nodes.
184
+ *
185
+ * Defines which properties to match on and how, in priority order. The first
186
+ * matching property wins.
187
+ *
188
+ * **String Shorthand** (simple cases - converts to exact match):
189
+ * SearchConfig(properties=["id", "email"]) # Equivalent to:
190
+ * SearchConfig(properties=[PropertyMatch.exact("id"),
191
+ * PropertyMatch.exact("email")])
192
+ *
193
+ * **Mixed Form** (combine strings and PropertyMatch): SearchConfig(properties=[
194
+ * "id", # String -> exact match PropertyMatch.semantic("title", 0.9) # Full
195
+ * control ])
196
+ *
197
+ * **Full Form** (maximum control): SearchConfig(properties=[
198
+ * PropertyMatch(name="id", mode="exact"), PropertyMatch(name="title",
199
+ * mode="semantic", threshold=0.85) ])
200
+ *
201
+ * **To select a specific node by ID**:
202
+ * SearchConfig(properties=[PropertyMatch.exact("id", "TASK-123")])
203
+ */
204
+ export interface SearchConfigOutput {
205
+ /**
206
+ * Default search mode when property doesn't specify one. 'semantic' (vector
207
+ * similarity), 'exact' (property match), 'fuzzy' (partial match).
208
+ */
209
+ mode?: 'semantic' | 'exact' | 'fuzzy';
210
+
211
+ /**
212
+ * Properties to match on, in priority order (first match wins). Accepts strings
213
+ * (converted to exact match) or PropertyMatch objects. Use PropertyMatch with
214
+ * 'value' field for specific node selection.
215
+ */
216
+ properties?: Array<SearchConfigOutput.Property> | null;
217
+
218
+ /**
219
+ * Default similarity threshold for semantic/fuzzy matching (0.0-1.0). Used when
220
+ * property doesn't specify its own threshold.
221
+ */
222
+ threshold?: number;
223
+
224
+ /**
225
+ * Search for nodes via their relationships. Example: Find tasks assigned to a
226
+ * specific person. Each RelationshipMatch specifies edge_type, target_type, and
227
+ * target_search. Multiple relationship matches are ANDed together.
228
+ */
229
+ via_relationship?: Array<unknown> | null;
230
+ }
231
+
232
+ export namespace SearchConfigOutput {
233
+ /**
234
+ * Property matching configuration.
235
+ *
236
+ * Defines which property to match on and how. When listed in search.properties,
237
+ * this property becomes a unique identifier.
238
+ *
239
+ * **Shorthand Helpers** (recommended for common cases):
240
+ * PropertyMatch.exact("id") # Exact match on id PropertyMatch.exact("id",
241
+ * "TASK-123") # Exact match with specific value PropertyMatch.semantic("title") #
242
+ * Semantic match with default threshold PropertyMatch.semantic("title", 0.9) #
243
+ * Semantic match with custom threshold PropertyMatch.semantic("title",
244
+ * value="bug") # Semantic search for "bug" PropertyMatch.fuzzy("name", 0.8) #
245
+ * Fuzzy match
246
+ *
247
+ * **Full Form** (when you need all options): PropertyMatch(name="title",
248
+ * mode="semantic", threshold=0.9, value="auth bug")
249
+ *
250
+ * **String Shorthand** (in SearchConfig.properties): properties=["id", "email"] #
251
+ * Equivalent to [PropertyMatch.exact("id"), PropertyMatch.exact("email")]
252
+ */
253
+ export interface Property {
254
+ /**
255
+ * Property name to match on (e.g., 'id', 'email', 'title')
256
+ */
257
+ name: string;
258
+
259
+ /**
260
+ * Matching mode: 'exact' (string match), 'semantic' (embedding similarity),
261
+ * 'fuzzy' (Levenshtein distance)
262
+ */
263
+ mode?: 'semantic' | 'exact' | 'fuzzy';
264
+
265
+ /**
266
+ * Similarity threshold for semantic/fuzzy modes (0.0-1.0). Ignored for exact mode.
267
+ */
268
+ threshold?: number;
269
+
270
+ /**
271
+ * Runtime value override. If set, use this value for matching instead of
272
+ * extracting from content. Useful for memory-level overrides when you know the
273
+ * exact value to search for.
274
+ */
275
+ value?: unknown;
276
+ }
277
+ }
278
+
139
279
  /**
140
280
  * Complete user-defined graph schema
141
281
  */
@@ -151,10 +291,37 @@ export interface UserGraphSchemaOutput {
151
291
  last_used_at?: string | null;
152
292
 
153
293
  /**
154
- * Custom node types (max 15 per schema)
294
+ * Default memory policy for memories using this schema. Includes mode ('auto',
295
+ * 'manual'), node_constraints (applied in auto mode when present), and OMO safety
296
+ * settings (consent, risk). Memory-level policies override schema-level.
297
+ */
298
+ memory_policy?: { [key: string]: unknown } | null;
299
+
300
+ /**
301
+ * @deprecated DEPRECATED: Use 'namespace_id' instead. Accepts Parse pointer or
302
+ * objectId.
303
+ */
304
+ namespace?: string | { [key: string]: unknown } | null;
305
+
306
+ /**
307
+ * Namespace ID this schema belongs to. Accepts legacy 'namespace' alias.
308
+ */
309
+ namespace_id?: string | null;
310
+
311
+ /**
312
+ * Custom node types (max 10 per schema)
155
313
  */
156
314
  node_types?: { [key: string]: UserGraphSchemaOutput.NodeTypes };
157
315
 
316
+ /**
317
+ * @deprecated DEPRECATED: Use 'organization_id' instead. Accepts Parse pointer or
318
+ * objectId.
319
+ */
320
+ organization?: string | { [key: string]: unknown } | null;
321
+
322
+ /**
323
+ * Organization ID this schema belongs to. Accepts legacy 'organization' alias.
324
+ */
158
325
  organization_id?: string | null;
159
326
 
160
327
  read_access?: Array<string>;
@@ -164,7 +331,10 @@ export interface UserGraphSchemaOutput {
164
331
  */
165
332
  relationship_types?: { [key: string]: UserGraphSchemaOutput.RelationshipTypes };
166
333
 
167
- scope?: 'personal' | 'workspace' | 'organization';
334
+ /**
335
+ * Schema scopes available through the API
336
+ */
337
+ scope?: 'personal' | 'workspace' | 'namespace' | 'organization';
168
338
 
169
339
  status?: 'draft' | 'active' | 'deprecated' | 'archived';
170
340
 
@@ -183,7 +353,23 @@ export interface UserGraphSchemaOutput {
183
353
 
184
354
  export namespace UserGraphSchemaOutput {
185
355
  /**
186
- * User-defined node type
356
+ * User-defined node type with optional inline constraint.
357
+ *
358
+ * The `constraint` field allows defining default matching/creation behavior
359
+ * directly within the node type definition. This replaces the need to put
360
+ * constraints only in memory_policy.node_constraints.
361
+ *
362
+ * Schema-level constraints:
363
+ *
364
+ * - `node_type` is implicit (taken from parent UserNodeType.name)
365
+ * - Defines default matching strategy via `search.properties`
366
+ * - Can be overridden per-memory via memory_policy.node_constraints
367
+ *
368
+ * Example: UserNodeType( name="Task", label="Task", properties={ "id":
369
+ * PropertyDefinition(type="string"), "title": PropertyDefinition(type="string",
370
+ * required=True) }, constraint=NodeConstraint( search=SearchConfig(properties=[
371
+ * PropertyMatch(name="id", mode="exact"), PropertyMatch(name="title",
372
+ * mode="semantic", threshold=0.85) ]), create="auto" ) )
187
373
  */
188
374
  export interface NodeTypes {
189
375
  label: string;
@@ -192,56 +378,222 @@ export namespace UserGraphSchemaOutput {
192
378
 
193
379
  color?: string | null;
194
380
 
381
+ /**
382
+ * Policy for how nodes of a specific type should be handled.
383
+ *
384
+ * Used in two places:
385
+ *
386
+ * 1. **Schema level**: Inside `UserNodeType.constraint` - `node_type` is implicit
387
+ * from parent
388
+ * 2. **Memory level**: In `memory_policy.node_constraints[]` - `node_type` is
389
+ * required
390
+ *
391
+ * Node constraints allow developers to control:
392
+ *
393
+ * - Which node types can be created vs. linked
394
+ * - How to find/select existing nodes (via `search`)
395
+ * - What property values to set (exact or auto-extracted)
396
+ * - When to apply the constraint (conditional with logical operators)
397
+ *
398
+ * **The `search` field** handles node selection:
399
+ *
400
+ * - Uses PropertyMatch list to define unique identifiers and matching strategy
401
+ * - Example:
402
+ * `{"properties": [{"name": "id", "mode": "exact"}, {"name": "title", "mode": "semantic"}]}`
403
+ * - For direct selection, use PropertyMatch with value:
404
+ * `{"name": "id", "mode": "exact", "value": "proj_123"}`
405
+ *
406
+ * **The `set` field** controls property values:
407
+ *
408
+ * - Exact value: `{"status": "done"}` - sets exact value
409
+ * - Auto-extract: `{"status": {"mode": "auto"}}` - LLM extracts from content
410
+ *
411
+ * **The `when` field** supports logical operators:
412
+ *
413
+ * - Simple: `{"priority": "high"}`
414
+ * - AND: `{"_and": [{"priority": "high"}, {"status": "active"}]}`
415
+ * - OR: `{"_or": [{"status": "active"}, {"status": "pending"}]}`
416
+ * - NOT: `{"_not": {"status": "completed"}}`
417
+ * - Complex:
418
+ * `{"_and": [{"priority": "high"}, {"_or": [{"status": "active"}, {"urgent": true}]}]}`
419
+ */
420
+ constraint?: NodeTypes.Constraint | null;
421
+
195
422
  description?: string | null;
196
423
 
197
424
  icon?: string | null;
198
425
 
199
426
  /**
200
- * Node properties (max 15 per node type)
427
+ * DEPRECATED: Use resolution_policy='lookup' instead. Shorthand for constraint
428
+ * with create='lookup'. When True, only links to existing nodes (controlled
429
+ * vocabulary). Equivalent to @lookup decorator. If constraint is also provided,
430
+ * link_only=True will override constraint.create to 'lookup'.
431
+ */
432
+ link_only?: boolean;
433
+
434
+ /**
435
+ * Node properties (max 10 per node type)
201
436
  */
202
- properties?: { [key: string]: NodeTypes.Properties };
437
+ properties?: { [key: string]: SchemasAPI.PropertyDefinition };
203
438
 
204
439
  required_properties?: Array<string>;
205
440
 
206
441
  /**
207
- * Properties that uniquely identify this node type. Used for MERGE operations to
208
- * avoid duplicates. Example: ['name', 'email'] for Customer nodes.
442
+ * Shorthand for constraint.create. 'upsert': Create if not found (default).
443
+ * 'lookup': Only link to existing nodes (controlled vocabulary). Equivalent to
444
+ * @upsert/@lookup decorators. If constraint is also provided, resolution_policy
445
+ * will set constraint.create accordingly.
446
+ */
447
+ resolution_policy?: 'upsert' | 'lookup';
448
+
449
+ /**
450
+ * DEPRECATED: Use 'constraint.search.properties' instead. Properties that uniquely
451
+ * identify this node type. Example: ['name', 'email'] for Customer nodes.
209
452
  */
210
453
  unique_identifiers?: Array<string>;
211
454
  }
212
455
 
213
456
  export namespace NodeTypes {
214
457
  /**
215
- * Property definition for nodes/relationships
458
+ * Policy for how nodes of a specific type should be handled.
459
+ *
460
+ * Used in two places:
461
+ *
462
+ * 1. **Schema level**: Inside `UserNodeType.constraint` - `node_type` is implicit
463
+ * from parent
464
+ * 2. **Memory level**: In `memory_policy.node_constraints[]` - `node_type` is
465
+ * required
466
+ *
467
+ * Node constraints allow developers to control:
468
+ *
469
+ * - Which node types can be created vs. linked
470
+ * - How to find/select existing nodes (via `search`)
471
+ * - What property values to set (exact or auto-extracted)
472
+ * - When to apply the constraint (conditional with logical operators)
473
+ *
474
+ * **The `search` field** handles node selection:
475
+ *
476
+ * - Uses PropertyMatch list to define unique identifiers and matching strategy
477
+ * - Example:
478
+ * `{"properties": [{"name": "id", "mode": "exact"}, {"name": "title", "mode": "semantic"}]}`
479
+ * - For direct selection, use PropertyMatch with value:
480
+ * `{"name": "id", "mode": "exact", "value": "proj_123"}`
481
+ *
482
+ * **The `set` field** controls property values:
483
+ *
484
+ * - Exact value: `{"status": "done"}` - sets exact value
485
+ * - Auto-extract: `{"status": {"mode": "auto"}}` - LLM extracts from content
486
+ *
487
+ * **The `when` field** supports logical operators:
488
+ *
489
+ * - Simple: `{"priority": "high"}`
490
+ * - AND: `{"_and": [{"priority": "high"}, {"status": "active"}]}`
491
+ * - OR: `{"_or": [{"status": "active"}, {"status": "pending"}]}`
492
+ * - NOT: `{"_not": {"status": "completed"}}`
493
+ * - Complex:
494
+ * `{"_and": [{"priority": "high"}, {"_or": [{"status": "active"}, {"urgent": true}]}]}`
216
495
  */
217
- export interface Properties {
218
- type: 'string' | 'integer' | 'float' | 'boolean' | 'array' | 'datetime' | 'object';
219
-
220
- default?: unknown;
221
-
222
- description?: string | null;
223
-
496
+ export interface Constraint {
224
497
  /**
225
- * List of allowed enum values (max 10)
498
+ * 'upsert': Create if not found via search (default). 'lookup': Only link to
499
+ * existing nodes (controlled vocabulary). Deprecated aliases: 'auto' -> 'upsert',
500
+ * 'never' -> 'lookup'.
226
501
  */
227
- enum_values?: Array<string> | null;
502
+ create?: 'upsert' | 'lookup' | 'auto' | 'never';
228
503
 
229
- max_length?: number | null;
504
+ /**
505
+ * DEPRECATED: Use create='lookup' instead. Shorthand for create='lookup'. When
506
+ * True, only links to existing nodes (controlled vocabulary). Equivalent to
507
+ * @lookup decorator in schema definitions.
508
+ */
509
+ link_only?: boolean;
230
510
 
231
- max_value?: number | null;
511
+ /**
512
+ * Node type this constraint applies to (e.g., 'Task', 'Project', 'Person').
513
+ * Optional at schema level (implicit from parent UserNodeType), required at memory
514
+ * level (in memory_policy.node_constraints).
515
+ */
516
+ node_type?: string | null;
232
517
 
233
- min_length?: number | null;
518
+ /**
519
+ * Explicit behavior when no match found via search. 'create': create new node
520
+ * (same as upsert). 'ignore': skip node creation (same as lookup). 'error': raise
521
+ * error if node not found. If specified, overrides 'create' field.
522
+ */
523
+ on_miss?: 'create' | 'ignore' | 'error' | null;
234
524
 
235
- min_value?: number | null;
525
+ /**
526
+ * Configuration for finding/selecting existing nodes.
527
+ *
528
+ * Defines which properties to match on and how, in priority order. The first
529
+ * matching property wins.
530
+ *
531
+ * **String Shorthand** (simple cases - converts to exact match):
532
+ * SearchConfig(properties=["id", "email"]) # Equivalent to:
533
+ * SearchConfig(properties=[PropertyMatch.exact("id"),
534
+ * PropertyMatch.exact("email")])
535
+ *
536
+ * **Mixed Form** (combine strings and PropertyMatch): SearchConfig(properties=[
537
+ * "id", # String -> exact match PropertyMatch.semantic("title", 0.9) # Full
538
+ * control ])
539
+ *
540
+ * **Full Form** (maximum control): SearchConfig(properties=[
541
+ * PropertyMatch(name="id", mode="exact"), PropertyMatch(name="title",
542
+ * mode="semantic", threshold=0.85) ])
543
+ *
544
+ * **To select a specific node by ID**:
545
+ * SearchConfig(properties=[PropertyMatch.exact("id", "TASK-123")])
546
+ */
547
+ search?: SchemasAPI.SearchConfigOutput | null;
236
548
 
237
- pattern?: string | null;
549
+ /**
550
+ * Set property values on nodes. Supports: 1. Exact value: {'status': 'done'} -
551
+ * sets exact value. 2. Auto-extract: {'status': {'mode': 'auto'}} - LLM extracts
552
+ * from content. 3. Text mode: {'summary': {'mode': 'auto', 'text_mode':
553
+ * 'merge'}} - controls text updates. For text properties, text_mode can be
554
+ * 'replace', 'append', or 'merge'.
555
+ */
556
+ set?: {
557
+ [key: string]:
558
+ | string
559
+ | number
560
+ | boolean
561
+ | Array<unknown>
562
+ | { [key: string]: unknown }
563
+ | Shared.PropertyValue;
564
+ } | null;
238
565
 
239
- required?: boolean;
566
+ /**
567
+ * Condition for when this constraint applies. Supports logical operators: '\_and',
568
+ * '\_or', '\_not'. Examples: Simple: {'priority': 'high'} - matches when priority
569
+ * equals 'high'. AND: {'\_and': [{'priority': 'high'}, {'status': 'active'}]} -
570
+ * all must match. OR: {'\_or': [{'status': 'active'}, {'status': 'pending'}]} -
571
+ * any must match. NOT: {'\_not': {'status': 'completed'}} - negation. Complex:
572
+ * {'\_and': [{'priority': 'high'}, {'\_or': [{'status': 'active'}, {'urgent':
573
+ * true}]}]}
574
+ */
575
+ when?: { [key: string]: unknown } | null;
240
576
  }
241
577
  }
242
578
 
243
579
  /**
244
- * User-defined relationship type
580
+ * User-defined relationship type with optional inline constraint.
581
+ *
582
+ * The `constraint` field allows defining default matching/creation behavior
583
+ * directly within the relationship type definition. This mirrors the pattern used
584
+ * in UserNodeType.constraint for nodes.
585
+ *
586
+ * Schema-level edge constraints:
587
+ *
588
+ * - `edge_type` is implicit (taken from parent UserRelationshipType.name)
589
+ * - Defines default target node matching strategy via `search.properties`
590
+ * - Can be overridden per-memory via memory_policy.edge_constraints
591
+ *
592
+ * Example: UserRelationshipType( name="MITIGATES", label="Mitigates",
593
+ * allowed_source_types=["SecurityBehavior"], allowed_target_types=["TacticDef"],
594
+ * constraint=EdgeConstraint( search=SearchConfig(properties=[
595
+ * PropertyMatch(name="name", mode="semantic", threshold=0.90) ]), create="never" #
596
+ * Controlled vocabulary - only link to existing targets ) )
245
597
  */
246
598
  export interface RelationshipTypes {
247
599
  allowed_source_types: Array<string>;
@@ -256,38 +608,200 @@ export namespace UserGraphSchemaOutput {
256
608
 
257
609
  color?: string | null;
258
610
 
611
+ /**
612
+ * Policy for how edges/relationships of a specific type should be handled.
613
+ *
614
+ * Used in two places:
615
+ *
616
+ * 1. **Schema level**: Inside `UserRelationshipType.constraint` - `edge_type` is
617
+ * implicit from parent
618
+ * 2. **Memory level**: In `memory_policy.edge_constraints[]` - `edge_type` is
619
+ * required
620
+ *
621
+ * Edge constraints allow developers to control:
622
+ *
623
+ * - Which edge types can be created vs. linked to existing targets
624
+ * - How to find/select target nodes (via `search`)
625
+ * - What edge property values to set (exact or auto-extracted)
626
+ * - When to apply the constraint (conditional with logical operators)
627
+ * - Filter by source/target node types
628
+ *
629
+ * **The `search` field** handles target node selection:
630
+ *
631
+ * - Uses SearchConfig to define how to find existing target nodes
632
+ * - Example: `{"properties": [{"name": "name", "mode": "semantic"}]}`
633
+ * - For controlled vocabulary: find existing target, don't create new
634
+ *
635
+ * **The `set` field** controls edge property values:
636
+ *
637
+ * - Exact value: `{"weight": 1.0}` - sets exact value
638
+ * - Auto-extract: `{"reason": {"mode": "auto"}}` - LLM extracts from content
639
+ *
640
+ * **The `when` field** supports logical operators (same as NodeConstraint):
641
+ *
642
+ * - Simple: `{"severity": "high"}`
643
+ * - AND: `{"_and": [{"severity": "high"}, {"confirmed": true}]}`
644
+ * - OR: `{"_or": [{"type": "MITIGATES"}, {"type": "PREVENTS"}]}`
645
+ * - NOT: `{"_not": {"status": "deprecated"}}`
646
+ */
647
+ constraint?: RelationshipTypes.Constraint | null;
648
+
259
649
  description?: string | null;
260
650
 
261
- properties?: { [key: string]: RelationshipTypes.Properties };
651
+ /**
652
+ * DEPRECATED: Use resolution_policy='lookup' instead. Shorthand for constraint
653
+ * with create='lookup'. When True, only links to existing target nodes (controlled
654
+ * vocabulary). Equivalent to @lookup decorator. If constraint is also provided,
655
+ * link_only=True will override constraint.create to 'lookup'.
656
+ */
657
+ link_only?: boolean;
658
+
659
+ properties?: { [key: string]: SchemasAPI.PropertyDefinition };
660
+
661
+ /**
662
+ * Shorthand for constraint.create. 'upsert': Create target if not found (default).
663
+ * 'lookup': Only link to existing targets (controlled vocabulary). Equivalent to
664
+ * @upsert/@lookup decorators. If constraint is also provided, resolution_policy
665
+ * will set constraint.create accordingly.
666
+ */
667
+ resolution_policy?: 'upsert' | 'lookup';
262
668
  }
263
669
 
264
670
  export namespace RelationshipTypes {
265
671
  /**
266
- * Property definition for nodes/relationships
672
+ * Policy for how edges/relationships of a specific type should be handled.
673
+ *
674
+ * Used in two places:
675
+ *
676
+ * 1. **Schema level**: Inside `UserRelationshipType.constraint` - `edge_type` is
677
+ * implicit from parent
678
+ * 2. **Memory level**: In `memory_policy.edge_constraints[]` - `edge_type` is
679
+ * required
680
+ *
681
+ * Edge constraints allow developers to control:
682
+ *
683
+ * - Which edge types can be created vs. linked to existing targets
684
+ * - How to find/select target nodes (via `search`)
685
+ * - What edge property values to set (exact or auto-extracted)
686
+ * - When to apply the constraint (conditional with logical operators)
687
+ * - Filter by source/target node types
688
+ *
689
+ * **The `search` field** handles target node selection:
690
+ *
691
+ * - Uses SearchConfig to define how to find existing target nodes
692
+ * - Example: `{"properties": [{"name": "name", "mode": "semantic"}]}`
693
+ * - For controlled vocabulary: find existing target, don't create new
694
+ *
695
+ * **The `set` field** controls edge property values:
696
+ *
697
+ * - Exact value: `{"weight": 1.0}` - sets exact value
698
+ * - Auto-extract: `{"reason": {"mode": "auto"}}` - LLM extracts from content
699
+ *
700
+ * **The `when` field** supports logical operators (same as NodeConstraint):
701
+ *
702
+ * - Simple: `{"severity": "high"}`
703
+ * - AND: `{"_and": [{"severity": "high"}, {"confirmed": true}]}`
704
+ * - OR: `{"_or": [{"type": "MITIGATES"}, {"type": "PREVENTS"}]}`
705
+ * - NOT: `{"_not": {"status": "deprecated"}}`
267
706
  */
268
- export interface Properties {
269
- type: 'string' | 'integer' | 'float' | 'boolean' | 'array' | 'datetime' | 'object';
707
+ export interface Constraint {
708
+ /**
709
+ * 'upsert': Create target node if not found via search (default). 'lookup': Only
710
+ * link to existing target nodes (controlled vocabulary). When 'lookup', edges to
711
+ * non-existing targets are skipped. Deprecated aliases: 'auto' -> 'upsert',
712
+ * 'never' -> 'lookup'.
713
+ */
714
+ create?: 'upsert' | 'lookup' | 'auto' | 'never';
270
715
 
271
- default?: unknown;
716
+ /**
717
+ * Direction of edges this constraint applies to. 'outgoing': edges where current
718
+ * node is source (default). 'incoming': edges where current node is target.
719
+ * 'both': applies in either direction.
720
+ */
721
+ direction?: 'outgoing' | 'incoming' | 'both';
272
722
 
273
- description?: string | null;
723
+ /**
724
+ * Edge/relationship type this constraint applies to (e.g., 'MITIGATES',
725
+ * 'ASSIGNED_TO'). Optional at schema level (implicit from parent
726
+ * UserRelationshipType), required at memory level (in
727
+ * memory_policy.edge_constraints).
728
+ */
729
+ edge_type?: string | null;
274
730
 
275
731
  /**
276
- * List of allowed enum values (max 10)
732
+ * DEPRECATED: Use create='lookup' instead. Shorthand for create='lookup'. When
733
+ * True, only links to existing target nodes. Equivalent to @lookup decorator in
734
+ * schema definitions.
277
735
  */
278
- enum_values?: Array<string> | null;
736
+ link_only?: boolean;
279
737
 
280
- max_length?: number | null;
738
+ /**
739
+ * Explicit behavior when no target match found via search. 'create': create new
740
+ * target node (same as upsert). 'ignore': skip edge creation (same as lookup).
741
+ * 'error': raise error if target not found. If specified, overrides 'create'
742
+ * field.
743
+ */
744
+ on_miss?: 'create' | 'ignore' | 'error' | null;
281
745
 
282
- max_value?: number | null;
746
+ /**
747
+ * Configuration for finding/selecting existing nodes.
748
+ *
749
+ * Defines which properties to match on and how, in priority order. The first
750
+ * matching property wins.
751
+ *
752
+ * **String Shorthand** (simple cases - converts to exact match):
753
+ * SearchConfig(properties=["id", "email"]) # Equivalent to:
754
+ * SearchConfig(properties=[PropertyMatch.exact("id"),
755
+ * PropertyMatch.exact("email")])
756
+ *
757
+ * **Mixed Form** (combine strings and PropertyMatch): SearchConfig(properties=[
758
+ * "id", # String -> exact match PropertyMatch.semantic("title", 0.9) # Full
759
+ * control ])
760
+ *
761
+ * **Full Form** (maximum control): SearchConfig(properties=[
762
+ * PropertyMatch(name="id", mode="exact"), PropertyMatch(name="title",
763
+ * mode="semantic", threshold=0.85) ])
764
+ *
765
+ * **To select a specific node by ID**:
766
+ * SearchConfig(properties=[PropertyMatch.exact("id", "TASK-123")])
767
+ */
768
+ search?: SchemasAPI.SearchConfigOutput | null;
283
769
 
284
- min_length?: number | null;
770
+ /**
771
+ * Set property values on edges. Supports: 1. Exact value: {'weight': 1.0} - sets
772
+ * exact value. 2. Auto-extract: {'reason': {'mode': 'auto'}} - LLM extracts from
773
+ * content. Edge properties are useful for relationship metadata (weight,
774
+ * timestamp, reason, etc.).
775
+ */
776
+ set?: {
777
+ [key: string]:
778
+ | string
779
+ | number
780
+ | boolean
781
+ | Array<unknown>
782
+ | { [key: string]: unknown }
783
+ | Shared.PropertyValue;
784
+ } | null;
285
785
 
286
- min_value?: number | null;
786
+ /**
787
+ * Filter: only apply when source node is of this type. Example:
788
+ * source_type='SecurityBehavior' - only applies to edges from SecurityBehavior
789
+ * nodes.
790
+ */
791
+ source_type?: string | null;
287
792
 
288
- pattern?: string | null;
793
+ /**
794
+ * Filter: only apply when target node is of this type. Example:
795
+ * target_type='TacticDef' - only applies to edges targeting TacticDef nodes.
796
+ */
797
+ target_type?: string | null;
289
798
 
290
- required?: boolean;
799
+ /**
800
+ * Condition for when this constraint applies. Supports logical operators: '\_and',
801
+ * '\_or', '\_not'. Applied to edge properties or context. Example: {'\_and':
802
+ * [{'severity': 'high'}, {'_not': {'status': 'deprecated'}}]}
803
+ */
804
+ when?: { [key: string]: unknown } | null;
291
805
  }
292
806
  }
293
807
  }
@@ -369,10 +883,37 @@ export interface SchemaCreateParams {
369
883
  last_used_at?: string | null;
370
884
 
371
885
  /**
372
- * Custom node types (max 15 per schema)
886
+ * Default memory policy for memories using this schema. Includes mode ('auto',
887
+ * 'manual'), node_constraints (applied in auto mode when present), and OMO safety
888
+ * settings (consent, risk). Memory-level policies override schema-level.
889
+ */
890
+ memory_policy?: { [key: string]: unknown } | null;
891
+
892
+ /**
893
+ * @deprecated DEPRECATED: Use 'namespace_id' instead. Accepts Parse pointer or
894
+ * objectId.
895
+ */
896
+ namespace?: string | { [key: string]: unknown } | null;
897
+
898
+ /**
899
+ * Namespace ID this schema belongs to. Accepts legacy 'namespace' alias.
900
+ */
901
+ namespace_id?: string | null;
902
+
903
+ /**
904
+ * Custom node types (max 10 per schema)
373
905
  */
374
906
  node_types?: { [key: string]: SchemaCreateParams.NodeTypes };
375
907
 
908
+ /**
909
+ * @deprecated DEPRECATED: Use 'organization_id' instead. Accepts Parse pointer or
910
+ * objectId.
911
+ */
912
+ organization?: string | { [key: string]: unknown } | null;
913
+
914
+ /**
915
+ * Organization ID this schema belongs to. Accepts legacy 'organization' alias.
916
+ */
376
917
  organization_id?: string | null;
377
918
 
378
919
  read_access?: Array<string>;
@@ -382,7 +923,10 @@ export interface SchemaCreateParams {
382
923
  */
383
924
  relationship_types?: { [key: string]: SchemaCreateParams.RelationshipTypes };
384
925
 
385
- scope?: 'personal' | 'workspace' | 'organization';
926
+ /**
927
+ * Schema scopes available through the API
928
+ */
929
+ scope?: 'personal' | 'workspace' | 'namespace' | 'organization';
386
930
 
387
931
  status?: 'draft' | 'active' | 'deprecated' | 'archived';
388
932
 
@@ -401,7 +945,23 @@ export interface SchemaCreateParams {
401
945
 
402
946
  export namespace SchemaCreateParams {
403
947
  /**
404
- * User-defined node type
948
+ * User-defined node type with optional inline constraint.
949
+ *
950
+ * The `constraint` field allows defining default matching/creation behavior
951
+ * directly within the node type definition. This replaces the need to put
952
+ * constraints only in memory_policy.node_constraints.
953
+ *
954
+ * Schema-level constraints:
955
+ *
956
+ * - `node_type` is implicit (taken from parent UserNodeType.name)
957
+ * - Defines default matching strategy via `search.properties`
958
+ * - Can be overridden per-memory via memory_policy.node_constraints
959
+ *
960
+ * Example: UserNodeType( name="Task", label="Task", properties={ "id":
961
+ * PropertyDefinition(type="string"), "title": PropertyDefinition(type="string",
962
+ * required=True) }, constraint=NodeConstraint( search=SearchConfig(properties=[
963
+ * PropertyMatch(name="id", mode="exact"), PropertyMatch(name="title",
964
+ * mode="semantic", threshold=0.85) ]), create="auto" ) )
405
965
  */
406
966
  export interface NodeTypes {
407
967
  label: string;
@@ -410,56 +970,99 @@ export namespace SchemaCreateParams {
410
970
 
411
971
  color?: string | null;
412
972
 
973
+ /**
974
+ * Policy for how nodes of a specific type should be handled.
975
+ *
976
+ * Used in two places:
977
+ *
978
+ * 1. **Schema level**: Inside `UserNodeType.constraint` - `node_type` is implicit
979
+ * from parent
980
+ * 2. **Memory level**: In `memory_policy.node_constraints[]` - `node_type` is
981
+ * required
982
+ *
983
+ * Node constraints allow developers to control:
984
+ *
985
+ * - Which node types can be created vs. linked
986
+ * - How to find/select existing nodes (via `search`)
987
+ * - What property values to set (exact or auto-extracted)
988
+ * - When to apply the constraint (conditional with logical operators)
989
+ *
990
+ * **The `search` field** handles node selection:
991
+ *
992
+ * - Uses PropertyMatch list to define unique identifiers and matching strategy
993
+ * - Example:
994
+ * `{"properties": [{"name": "id", "mode": "exact"}, {"name": "title", "mode": "semantic"}]}`
995
+ * - For direct selection, use PropertyMatch with value:
996
+ * `{"name": "id", "mode": "exact", "value": "proj_123"}`
997
+ *
998
+ * **The `set` field** controls property values:
999
+ *
1000
+ * - Exact value: `{"status": "done"}` - sets exact value
1001
+ * - Auto-extract: `{"status": {"mode": "auto"}}` - LLM extracts from content
1002
+ *
1003
+ * **The `when` field** supports logical operators:
1004
+ *
1005
+ * - Simple: `{"priority": "high"}`
1006
+ * - AND: `{"_and": [{"priority": "high"}, {"status": "active"}]}`
1007
+ * - OR: `{"_or": [{"status": "active"}, {"status": "pending"}]}`
1008
+ * - NOT: `{"_not": {"status": "completed"}}`
1009
+ * - Complex:
1010
+ * `{"_and": [{"priority": "high"}, {"_or": [{"status": "active"}, {"urgent": true}]}]}`
1011
+ */
1012
+ constraint?: Shared.NodeConstraintInput | null;
1013
+
413
1014
  description?: string | null;
414
1015
 
415
1016
  icon?: string | null;
416
1017
 
417
1018
  /**
418
- * Node properties (max 15 per node type)
1019
+ * DEPRECATED: Use resolution_policy='lookup' instead. Shorthand for constraint
1020
+ * with create='lookup'. When True, only links to existing nodes (controlled
1021
+ * vocabulary). Equivalent to @lookup decorator. If constraint is also provided,
1022
+ * link_only=True will override constraint.create to 'lookup'.
1023
+ */
1024
+ link_only?: boolean;
1025
+
1026
+ /**
1027
+ * Node properties (max 10 per node type)
419
1028
  */
420
- properties?: { [key: string]: NodeTypes.Properties };
1029
+ properties?: { [key: string]: SchemasAPI.PropertyDefinition };
421
1030
 
422
1031
  required_properties?: Array<string>;
423
1032
 
424
1033
  /**
425
- * Properties that uniquely identify this node type. Used for MERGE operations to
426
- * avoid duplicates. Example: ['name', 'email'] for Customer nodes.
1034
+ * Shorthand for constraint.create. 'upsert': Create if not found (default).
1035
+ * 'lookup': Only link to existing nodes (controlled vocabulary). Equivalent to
1036
+ * @upsert/@lookup decorators. If constraint is also provided, resolution_policy
1037
+ * will set constraint.create accordingly.
427
1038
  */
428
- unique_identifiers?: Array<string>;
429
- }
1039
+ resolution_policy?: 'upsert' | 'lookup';
430
1040
 
431
- export namespace NodeTypes {
432
1041
  /**
433
- * Property definition for nodes/relationships
1042
+ * DEPRECATED: Use 'constraint.search.properties' instead. Properties that uniquely
1043
+ * identify this node type. Example: ['name', 'email'] for Customer nodes.
434
1044
  */
435
- export interface Properties {
436
- type: 'string' | 'integer' | 'float' | 'boolean' | 'array' | 'datetime' | 'object';
437
-
438
- default?: unknown;
439
-
440
- description?: string | null;
441
-
442
- /**
443
- * List of allowed enum values (max 10)
444
- */
445
- enum_values?: Array<string> | null;
446
-
447
- max_length?: number | null;
448
-
449
- max_value?: number | null;
450
-
451
- min_length?: number | null;
452
-
453
- min_value?: number | null;
454
-
455
- pattern?: string | null;
456
-
457
- required?: boolean;
458
- }
1045
+ unique_identifiers?: Array<string>;
459
1046
  }
460
1047
 
461
1048
  /**
462
- * User-defined relationship type
1049
+ * User-defined relationship type with optional inline constraint.
1050
+ *
1051
+ * The `constraint` field allows defining default matching/creation behavior
1052
+ * directly within the relationship type definition. This mirrors the pattern used
1053
+ * in UserNodeType.constraint for nodes.
1054
+ *
1055
+ * Schema-level edge constraints:
1056
+ *
1057
+ * - `edge_type` is implicit (taken from parent UserRelationshipType.name)
1058
+ * - Defines default target node matching strategy via `search.properties`
1059
+ * - Can be overridden per-memory via memory_policy.edge_constraints
1060
+ *
1061
+ * Example: UserRelationshipType( name="MITIGATES", label="Mitigates",
1062
+ * allowed_source_types=["SecurityBehavior"], allowed_target_types=["TacticDef"],
1063
+ * constraint=EdgeConstraint( search=SearchConfig(properties=[
1064
+ * PropertyMatch(name="name", mode="semantic", threshold=0.90) ]), create="never" #
1065
+ * Controlled vocabulary - only link to existing targets ) )
463
1066
  */
464
1067
  export interface RelationshipTypes {
465
1068
  allowed_source_types: Array<string>;
@@ -474,39 +1077,63 @@ export namespace SchemaCreateParams {
474
1077
 
475
1078
  color?: string | null;
476
1079
 
477
- description?: string | null;
478
-
479
- properties?: { [key: string]: RelationshipTypes.Properties };
480
- }
481
-
482
- export namespace RelationshipTypes {
483
1080
  /**
484
- * Property definition for nodes/relationships
1081
+ * Policy for how edges/relationships of a specific type should be handled.
1082
+ *
1083
+ * Used in two places:
1084
+ *
1085
+ * 1. **Schema level**: Inside `UserRelationshipType.constraint` - `edge_type` is
1086
+ * implicit from parent
1087
+ * 2. **Memory level**: In `memory_policy.edge_constraints[]` - `edge_type` is
1088
+ * required
1089
+ *
1090
+ * Edge constraints allow developers to control:
1091
+ *
1092
+ * - Which edge types can be created vs. linked to existing targets
1093
+ * - How to find/select target nodes (via `search`)
1094
+ * - What edge property values to set (exact or auto-extracted)
1095
+ * - When to apply the constraint (conditional with logical operators)
1096
+ * - Filter by source/target node types
1097
+ *
1098
+ * **The `search` field** handles target node selection:
1099
+ *
1100
+ * - Uses SearchConfig to define how to find existing target nodes
1101
+ * - Example: `{"properties": [{"name": "name", "mode": "semantic"}]}`
1102
+ * - For controlled vocabulary: find existing target, don't create new
1103
+ *
1104
+ * **The `set` field** controls edge property values:
1105
+ *
1106
+ * - Exact value: `{"weight": 1.0}` - sets exact value
1107
+ * - Auto-extract: `{"reason": {"mode": "auto"}}` - LLM extracts from content
1108
+ *
1109
+ * **The `when` field** supports logical operators (same as NodeConstraint):
1110
+ *
1111
+ * - Simple: `{"severity": "high"}`
1112
+ * - AND: `{"_and": [{"severity": "high"}, {"confirmed": true}]}`
1113
+ * - OR: `{"_or": [{"type": "MITIGATES"}, {"type": "PREVENTS"}]}`
1114
+ * - NOT: `{"_not": {"status": "deprecated"}}`
485
1115
  */
486
- export interface Properties {
487
- type: 'string' | 'integer' | 'float' | 'boolean' | 'array' | 'datetime' | 'object';
488
-
489
- default?: unknown;
1116
+ constraint?: Shared.EdgeConstraintInput | null;
490
1117
 
491
- description?: string | null;
492
-
493
- /**
494
- * List of allowed enum values (max 10)
495
- */
496
- enum_values?: Array<string> | null;
497
-
498
- max_length?: number | null;
499
-
500
- max_value?: number | null;
501
-
502
- min_length?: number | null;
1118
+ description?: string | null;
503
1119
 
504
- min_value?: number | null;
1120
+ /**
1121
+ * DEPRECATED: Use resolution_policy='lookup' instead. Shorthand for constraint
1122
+ * with create='lookup'. When True, only links to existing target nodes (controlled
1123
+ * vocabulary). Equivalent to @lookup decorator. If constraint is also provided,
1124
+ * link_only=True will override constraint.create to 'lookup'.
1125
+ */
1126
+ link_only?: boolean;
505
1127
 
506
- pattern?: string | null;
1128
+ properties?: { [key: string]: SchemasAPI.PropertyDefinition };
507
1129
 
508
- required?: boolean;
509
- }
1130
+ /**
1131
+ * Shorthand for constraint.create. 'upsert': Create target if not found (default).
1132
+ * 'lookup': Only link to existing targets (controlled vocabulary). Equivalent to
1133
+ * @upsert/@lookup decorators. If constraint is also provided, resolution_policy
1134
+ * will set constraint.create accordingly.
1135
+ */
1136
+ resolution_policy?: 'upsert' | 'lookup';
510
1137
  }
511
1138
  }
512
1139
 
@@ -528,6 +1155,8 @@ export interface SchemaListParams {
528
1155
 
529
1156
  export declare namespace Schemas {
530
1157
  export {
1158
+ type PropertyDefinition as PropertyDefinition,
1159
+ type SearchConfigOutput as SearchConfigOutput,
531
1160
  type UserGraphSchemaOutput as UserGraphSchemaOutput,
532
1161
  type SchemaCreateResponse as SchemaCreateResponse,
533
1162
  type SchemaRetrieveResponse as SchemaRetrieveResponse,