@subcortex-ai/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1694 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AgentsNamespace: () => AgentsNamespace,
24
+ AssertionsNamespace: () => AssertionsNamespace,
25
+ CONTEXT_SCHEMA_VERSION: () => CONTEXT_SCHEMA_VERSION,
26
+ ConfidenceLevel: () => ConfidenceLevel,
27
+ ConfidenceScores: () => ConfidenceScores,
28
+ EntityPredicate: () => EntityPredicate,
29
+ EntityRelationship: () => EntityRelationship,
30
+ EventPredicate: () => EventPredicate,
31
+ IdentityPredicate: () => IdentityPredicate,
32
+ IntakeNamespace: () => IntakeNamespace,
33
+ MULTI_VALUE_PREDICATES: () => MULTI_VALUE_PREDICATES,
34
+ MemoryNamespace: () => MemoryNamespace,
35
+ MemoryPredicate: () => MemoryPredicate,
36
+ NEGATIVE_SIGNALS: () => NEGATIVE_SIGNALS,
37
+ OrgRelationship: () => OrgRelationship,
38
+ POSITIVE_SIGNALS: () => POSITIVE_SIGNALS,
39
+ Predicates: () => Predicates,
40
+ RELATIONSHIP_LABELS: () => RELATIONSHIP_LABELS,
41
+ REVERSE_RELATIONSHIPS: () => REVERSE_RELATIONSHIPS,
42
+ RapportPredicate: () => RapportPredicate,
43
+ RelationshipTypes: () => RelationshipTypes,
44
+ RelationshipsNamespace: () => RelationshipsNamespace,
45
+ SIGNAL_DECAY_CONFIG: () => SIGNAL_DECAY_CONFIG,
46
+ SYSTEM_SIGNAL_TYPES: () => SYSTEM_SIGNAL_TYPES,
47
+ SignalsNamespace: () => SignalsNamespace,
48
+ SubCortexAuthenticationError: () => SubCortexAuthenticationError,
49
+ SubCortexAuthorizationError: () => SubCortexAuthorizationError,
50
+ SubCortexClient: () => SubCortexClient,
51
+ SubCortexConflictError: () => SubCortexConflictError,
52
+ SubCortexError: () => SubCortexError,
53
+ SubCortexNetworkError: () => SubCortexNetworkError,
54
+ SubCortexNotFoundError: () => SubCortexNotFoundError,
55
+ SubCortexRateLimitError: () => SubCortexRateLimitError,
56
+ SubCortexServerError: () => SubCortexServerError,
57
+ SubCortexTimeoutError: () => SubCortexTimeoutError,
58
+ SubCortexValidationError: () => SubCortexValidationError,
59
+ SubjectPrefix: () => SubjectPrefix,
60
+ UsersNamespace: () => UsersNamespace,
61
+ WorkPredicate: () => WorkPredicate,
62
+ confidenceToScore: () => confidenceToScore,
63
+ formatContext: () => formatContext,
64
+ getDecayHalfLife: () => getDecayHalfLife,
65
+ isValidSignalType: () => isValidSignalType,
66
+ scoreToConfidence: () => scoreToConfidence,
67
+ subject: () => subject,
68
+ toContextXml: () => toContextXml
69
+ });
70
+ module.exports = __toCommonJS(index_exports);
71
+
72
+ // src/errors.ts
73
+ var SubCortexError = class extends Error {
74
+ /** HTTP status code (0 for network errors) */
75
+ statusCode;
76
+ /** Server-assigned request ID for debugging */
77
+ requestId;
78
+ /** Whether the request can be retried */
79
+ retryable;
80
+ /** Raw response body */
81
+ body;
82
+ constructor(message, statusCode, options) {
83
+ super(message);
84
+ this.name = "SubCortexError";
85
+ this.statusCode = statusCode;
86
+ this.requestId = options?.requestId;
87
+ this.retryable = options?.retryable ?? false;
88
+ this.body = options?.body;
89
+ }
90
+ };
91
+ var SubCortexValidationError = class extends SubCortexError {
92
+ /** Field-level validation errors if available */
93
+ details;
94
+ constructor(message, options) {
95
+ super(message, 400, { ...options, retryable: false });
96
+ this.name = "SubCortexValidationError";
97
+ this.details = options?.details;
98
+ }
99
+ };
100
+ var SubCortexAuthenticationError = class extends SubCortexError {
101
+ constructor(message, options) {
102
+ super(message, 401, { ...options, retryable: false });
103
+ this.name = "SubCortexAuthenticationError";
104
+ }
105
+ };
106
+ var SubCortexAuthorizationError = class extends SubCortexError {
107
+ constructor(message, options) {
108
+ super(message, 403, { ...options, retryable: false });
109
+ this.name = "SubCortexAuthorizationError";
110
+ }
111
+ };
112
+ var SubCortexNotFoundError = class extends SubCortexError {
113
+ constructor(message, options) {
114
+ super(message, 404, { ...options, retryable: false });
115
+ this.name = "SubCortexNotFoundError";
116
+ }
117
+ };
118
+ var SubCortexConflictError = class extends SubCortexError {
119
+ constructor(message, options) {
120
+ super(message, 409, { ...options, retryable: false });
121
+ this.name = "SubCortexConflictError";
122
+ }
123
+ };
124
+ var SubCortexRateLimitError = class extends SubCortexError {
125
+ /** Seconds to wait before retrying */
126
+ retryAfter;
127
+ constructor(message, options) {
128
+ super(message, 429, { ...options, retryable: true });
129
+ this.name = "SubCortexRateLimitError";
130
+ this.retryAfter = options?.retryAfter;
131
+ }
132
+ };
133
+ var SubCortexServerError = class extends SubCortexError {
134
+ constructor(message, statusCode, options) {
135
+ super(message, statusCode, { ...options, retryable: true });
136
+ this.name = "SubCortexServerError";
137
+ }
138
+ };
139
+ var SubCortexNetworkError = class extends SubCortexError {
140
+ cause;
141
+ constructor(message, options) {
142
+ super(message, 0, { retryable: true });
143
+ this.name = "SubCortexNetworkError";
144
+ this.cause = options?.cause;
145
+ }
146
+ };
147
+ var SubCortexTimeoutError = class extends SubCortexNetworkError {
148
+ constructor(timeoutMs) {
149
+ super(`Request timed out after ${timeoutMs}ms`);
150
+ this.name = "SubCortexTimeoutError";
151
+ }
152
+ };
153
+ function classifyError(statusCode, body, requestId, retryAfterHint) {
154
+ let errorCode = "";
155
+ let message = "";
156
+ let details;
157
+ try {
158
+ const parsed = JSON.parse(body);
159
+ if (parsed.error) {
160
+ errorCode = parsed.error.code || "";
161
+ message = parsed.error.message || "";
162
+ if (parsed.error.details) {
163
+ details = parsed.error.details;
164
+ }
165
+ }
166
+ } catch {
167
+ }
168
+ if (!message) {
169
+ message = body || `HTTP ${statusCode}`;
170
+ }
171
+ const opts = { requestId, body };
172
+ switch (statusCode) {
173
+ case 400:
174
+ return new SubCortexValidationError(message, { ...opts, details });
175
+ case 401:
176
+ return new SubCortexAuthenticationError(message, opts);
177
+ case 403:
178
+ return new SubCortexAuthorizationError(message, opts);
179
+ case 404:
180
+ return new SubCortexNotFoundError(message, opts);
181
+ case 409:
182
+ return new SubCortexConflictError(message, opts);
183
+ case 429: {
184
+ let retryAfter = retryAfterHint;
185
+ if (retryAfter === void 0) {
186
+ try {
187
+ const parsed = JSON.parse(body);
188
+ retryAfter = parsed.retryAfter ?? parsed.retry_after;
189
+ } catch {
190
+ }
191
+ }
192
+ return new SubCortexRateLimitError(message, { ...opts, retryAfter });
193
+ }
194
+ default:
195
+ if (statusCode >= 500) {
196
+ return new SubCortexServerError(message, statusCode, opts);
197
+ }
198
+ return new SubCortexError(message, statusCode, opts);
199
+ }
200
+ }
201
+
202
+ // src/http.ts
203
+ function snakeToCamel(s) {
204
+ return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
205
+ }
206
+ function camelToSnake(s) {
207
+ return s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
208
+ }
209
+ function mapKeys(obj, mapper) {
210
+ if (obj === null || obj === void 0) return obj;
211
+ if (Array.isArray(obj)) return obj.map((item) => mapKeys(item, mapper));
212
+ if (typeof obj === "object") {
213
+ const mapped = {};
214
+ for (const [key, value] of Object.entries(obj)) {
215
+ mapped[mapper(key)] = mapKeys(value, mapper);
216
+ }
217
+ return mapped;
218
+ }
219
+ return obj;
220
+ }
221
+ function fromWire(data) {
222
+ return mapKeys(data, snakeToCamel);
223
+ }
224
+ function toWire(data) {
225
+ return mapKeys(data, camelToSnake);
226
+ }
227
+ var counter = 0;
228
+ function generateRequestId() {
229
+ const ts = Date.now().toString(36);
230
+ const seq = (counter++).toString(36);
231
+ const rand = Math.random().toString(36).slice(2, 6);
232
+ return `scx-${ts}-${seq}-${rand}`;
233
+ }
234
+ function sleep(ms) {
235
+ return new Promise((resolve) => setTimeout(resolve, ms));
236
+ }
237
+ function computeDelay(attempt, config) {
238
+ const exponential = config.baseDelayMs * Math.pow(2, attempt);
239
+ const capped = Math.min(exponential, config.maxDelayMs);
240
+ const jitter = capped * (0.5 + Math.random());
241
+ return Math.round(jitter);
242
+ }
243
+ function isRetryable(status) {
244
+ return status === 429 || status >= 500;
245
+ }
246
+ var HttpTransport = class {
247
+ opts;
248
+ constructor(options) {
249
+ this.opts = {
250
+ ...options,
251
+ baseUrl: options.baseUrl.replace(/\/$/, "")
252
+ };
253
+ }
254
+ /** GET request with retry and typed response. */
255
+ async get(path, tenantId) {
256
+ return this.request("GET", path, void 0, tenantId);
257
+ }
258
+ /** POST request with retry and typed response. */
259
+ async post(path, body, tenantId) {
260
+ return this.request("POST", path, body, tenantId);
261
+ }
262
+ /** PUT request with retry and typed response. */
263
+ async put(path, body, tenantId) {
264
+ return this.request("PUT", path, body, tenantId);
265
+ }
266
+ /** DELETE request with retry and typed response. */
267
+ async delete(path, tenantId) {
268
+ return this.request("DELETE", path, void 0, tenantId);
269
+ }
270
+ /** Core request method with retry loop. */
271
+ async request(method, path, body, tenantIdOverride) {
272
+ const url = `${this.opts.baseUrl}${path}`;
273
+ const requestId = generateRequestId();
274
+ const tenantId = tenantIdOverride || this.opts.tenantId;
275
+ const headers = {
276
+ Accept: "application/json",
277
+ "X-Request-ID": requestId,
278
+ "X-Tenant-ID": tenantId,
279
+ ...this.opts.headers
280
+ };
281
+ if (body !== void 0) {
282
+ headers["Content-Type"] = "application/json";
283
+ }
284
+ if (this.opts.apiKey) {
285
+ headers["Authorization"] = `Bearer ${this.opts.apiKey}`;
286
+ } else if (this.opts.token) {
287
+ headers["Authorization"] = `Bearer ${this.opts.token}`;
288
+ }
289
+ const fetchOpts = {
290
+ method,
291
+ headers,
292
+ body: body !== void 0 ? JSON.stringify(body) : void 0
293
+ };
294
+ let lastError;
295
+ for (let attempt = 0; attempt <= this.opts.retry.maxRetries; attempt++) {
296
+ try {
297
+ const response = await this.fetchWithTimeout(url, fetchOpts);
298
+ if (response.ok) {
299
+ const text = await response.text();
300
+ if (!text) return void 0;
301
+ const parsed = JSON.parse(text);
302
+ return fromWire(parsed);
303
+ }
304
+ const responseBody = await response.text();
305
+ if (response.status === 429) {
306
+ const retryAfterRaw = response.headers.get("Retry-After");
307
+ const retryAfterSecs = retryAfterRaw ? parseInt(retryAfterRaw, 10) : 0;
308
+ if (attempt < this.opts.retry.maxRetries) {
309
+ const delay = retryAfterSecs > 0 ? retryAfterSecs * 1e3 : computeDelay(attempt, this.opts.retry);
310
+ await sleep(delay);
311
+ lastError = classifyError(response.status, responseBody, requestId, retryAfterSecs || void 0);
312
+ continue;
313
+ }
314
+ throw classifyError(response.status, responseBody, requestId, retryAfterSecs || void 0);
315
+ }
316
+ if (isRetryable(response.status) && attempt < this.opts.retry.maxRetries) {
317
+ lastError = classifyError(response.status, responseBody, requestId);
318
+ await sleep(computeDelay(attempt, this.opts.retry));
319
+ continue;
320
+ }
321
+ throw classifyError(response.status, responseBody, requestId);
322
+ } catch (error) {
323
+ if (error instanceof Error && error.name.startsWith("SubCortex")) {
324
+ if (!error.retryable || attempt >= this.opts.retry.maxRetries) {
325
+ throw error;
326
+ }
327
+ lastError = error;
328
+ await sleep(computeDelay(attempt, this.opts.retry));
329
+ continue;
330
+ }
331
+ if (error instanceof TypeError || error instanceof DOMException) {
332
+ lastError = new SubCortexNetworkError(
333
+ `Network error: ${error.message}`,
334
+ { cause: error }
335
+ );
336
+ if (attempt < this.opts.retry.maxRetries) {
337
+ await sleep(computeDelay(attempt, this.opts.retry));
338
+ continue;
339
+ }
340
+ throw lastError;
341
+ }
342
+ throw error;
343
+ }
344
+ }
345
+ throw lastError || new SubCortexNetworkError("Request failed after all retries");
346
+ }
347
+ /** Fetch with AbortController timeout. */
348
+ async fetchWithTimeout(url, init) {
349
+ const controller = new AbortController();
350
+ const timeoutId = setTimeout(
351
+ () => controller.abort(),
352
+ this.opts.timeoutMs
353
+ );
354
+ if (this.opts.signal) {
355
+ this.opts.signal.addEventListener("abort", () => controller.abort());
356
+ }
357
+ try {
358
+ return await this.opts.fetchImpl(url, {
359
+ ...init,
360
+ signal: controller.signal
361
+ });
362
+ } catch (error) {
363
+ if (error instanceof DOMException && error.name === "AbortError" && !this.opts.signal?.aborted) {
364
+ throw new SubCortexTimeoutError(this.opts.timeoutMs);
365
+ }
366
+ throw error;
367
+ } finally {
368
+ clearTimeout(timeoutId);
369
+ }
370
+ }
371
+ };
372
+
373
+ // src/types/schema.ts
374
+ var SubjectPrefix = /* @__PURE__ */ ((SubjectPrefix2) => {
375
+ SubjectPrefix2["USER"] = "user";
376
+ SubjectPrefix2["PERSON"] = "person";
377
+ SubjectPrefix2["ROLE"] = "role";
378
+ SubjectPrefix2["ENTITY"] = "entity";
379
+ SubjectPrefix2["PROPERTY"] = "property";
380
+ SubjectPrefix2["PROJECT"] = "project";
381
+ SubjectPrefix2["EVENT"] = "event";
382
+ SubjectPrefix2["AGENT"] = "agent";
383
+ return SubjectPrefix2;
384
+ })(SubjectPrefix || {});
385
+ var TITLE_NORMALIZATIONS = [
386
+ [/\bvp\b/gi, "Vice President"],
387
+ [/\bsvp\b/gi, "Senior Vice President"],
388
+ [/\bevp\b/gi, "Executive Vice President"],
389
+ [/\bcto\b/gi, "Chief Technology Officer"],
390
+ [/\bceo\b/gi, "Chief Executive Officer"],
391
+ [/\bcfo\b/gi, "Chief Financial Officer"],
392
+ [/\bcoo\b/gi, "Chief Operating Officer"],
393
+ [/\bcmo\b/gi, "Chief Marketing Officer"],
394
+ [/\bcpo\b/gi, "Chief Product Officer"],
395
+ [/\bcio\b/gi, "Chief Information Officer"],
396
+ [/\bea\b/gi, "Executive Assistant"],
397
+ [/\bpm\b/gi, "Project Manager"],
398
+ [/\bdir\b/gi, "Director"],
399
+ [/\bsr\b/gi, "Senior"],
400
+ [/\bjr\b/gi, "Junior"]
401
+ ];
402
+ function subject(prefix, identifier) {
403
+ let expanded = identifier;
404
+ if (prefix === "role" /* ROLE */ || prefix === "role") {
405
+ for (const [pattern, replacement] of TITLE_NORMALIZATIONS) {
406
+ expanded = expanded.replace(pattern, replacement);
407
+ }
408
+ }
409
+ const normalized = expanded.toLowerCase().replace(/\s+/g, "-");
410
+ return `${prefix}:${normalized}`;
411
+ }
412
+ var IdentityPredicate = /* @__PURE__ */ ((IdentityPredicate2) => {
413
+ IdentityPredicate2["NAME"] = "name";
414
+ IdentityPredicate2["FULL_NAME"] = "full_name";
415
+ IdentityPredicate2["ROLE"] = "role";
416
+ IdentityPredicate2["TITLE"] = "title";
417
+ IdentityPredicate2["DEPARTMENT"] = "department";
418
+ IdentityPredicate2["TEAM"] = "team";
419
+ IdentityPredicate2["START_DATE"] = "start_date";
420
+ IdentityPredicate2["EMAIL"] = "email";
421
+ return IdentityPredicate2;
422
+ })(IdentityPredicate || {});
423
+ var WorkPredicate = /* @__PURE__ */ ((WorkPredicate2) => {
424
+ WorkPredicate2["EXPERTISE"] = "expertise";
425
+ WorkPredicate2["CURRENT_PROJECT"] = "current_project";
426
+ WorkPredicate2["PAIN_POINT"] = "pain_point";
427
+ return WorkPredicate2;
428
+ })(WorkPredicate || {});
429
+ var EventPredicate = /* @__PURE__ */ ((EventPredicate2) => {
430
+ EventPredicate2["STATUS"] = "status";
431
+ EventPredicate2["STATUS_CHANGE"] = "status_change";
432
+ EventPredicate2["EVENT"] = "event";
433
+ EventPredicate2["DECISION"] = "decision";
434
+ EventPredicate2["OUTCOME"] = "outcome";
435
+ return EventPredicate2;
436
+ })(EventPredicate || {});
437
+ var RapportPredicate = /* @__PURE__ */ ((RapportPredicate2) => {
438
+ RapportPredicate2["SENTIMENT"] = "sentiment";
439
+ RapportPredicate2["FRUSTRATION"] = "frustration";
440
+ RapportPredicate2["EXCITEMENT"] = "excitement";
441
+ RapportPredicate2["CONCERN"] = "concern";
442
+ RapportPredicate2["GOAL"] = "goal";
443
+ RapportPredicate2["ASPIRATION"] = "aspiration";
444
+ RapportPredicate2["PREFERENCE"] = "preference";
445
+ RapportPredicate2["PAIN_POINT"] = "pain_point";
446
+ RapportPredicate2["INTEREST"] = "interest";
447
+ RapportPredicate2["COMMUNICATION_STYLE"] = "communication_style";
448
+ return RapportPredicate2;
449
+ })(RapportPredicate || {});
450
+ var MemoryPredicate = /* @__PURE__ */ ((MemoryPredicate2) => {
451
+ MemoryPredicate2["REMINDER"] = "reminder";
452
+ MemoryPredicate2["CONTEXT"] = "context";
453
+ MemoryPredicate2["CONTEXT_TASK"] = "context:task";
454
+ MemoryPredicate2["CURRENT_PROJECT"] = "current_project";
455
+ return MemoryPredicate2;
456
+ })(MemoryPredicate || {});
457
+ var EntityPredicate = /* @__PURE__ */ ((EntityPredicate2) => {
458
+ EntityPredicate2["TYPE"] = "type";
459
+ EntityPredicate2["DESCRIPTION"] = "description";
460
+ EntityPredicate2["FIELD_TYPE"] = "field_type";
461
+ EntityPredicate2["REQUIRED"] = "required";
462
+ EntityPredicate2["WORKFLOW"] = "workflow";
463
+ return EntityPredicate2;
464
+ })(EntityPredicate || {});
465
+ var Predicates = {
466
+ ...IdentityPredicate,
467
+ ...WorkPredicate,
468
+ ...EventPredicate,
469
+ ...RapportPredicate,
470
+ ...MemoryPredicate,
471
+ ...EntityPredicate
472
+ };
473
+ var OrgRelationship = /* @__PURE__ */ ((OrgRelationship2) => {
474
+ OrgRelationship2["REPORTS_TO"] = "reports_to";
475
+ OrgRelationship2["MANAGES"] = "manages";
476
+ OrgRelationship2["MEMBER_OF"] = "member_of";
477
+ OrgRelationship2["HAS_MEMBER"] = "has_member";
478
+ OrgRelationship2["HOLDS_ROLE"] = "holds_role";
479
+ OrgRelationship2["CANDIDATE_FOR"] = "candidate_for";
480
+ OrgRelationship2["COLLABORATES_WITH"] = "collaborates_with";
481
+ OrgRelationship2["MENTORS"] = "mentors";
482
+ OrgRelationship2["MENTORED_BY"] = "mentored_by";
483
+ OrgRelationship2["STAKEHOLDER_IN"] = "stakeholder_in";
484
+ return OrgRelationship2;
485
+ })(OrgRelationship || {});
486
+ var EntityRelationship = /* @__PURE__ */ ((EntityRelationship2) => {
487
+ EntityRelationship2["HAS_PROPERTY"] = "has_property";
488
+ EntityRelationship2["BELONGS_TO"] = "belongs_to";
489
+ EntityRelationship2["HAS_MANY"] = "has_many";
490
+ EntityRelationship2["MANY_TO_MANY"] = "many_to_many";
491
+ EntityRelationship2["DEPENDS_ON"] = "depends_on";
492
+ return EntityRelationship2;
493
+ })(EntityRelationship || {});
494
+ var RelationshipTypes = {
495
+ ...OrgRelationship,
496
+ ...EntityRelationship
497
+ };
498
+ var ConfidenceLevel = /* @__PURE__ */ ((ConfidenceLevel2) => {
499
+ ConfidenceLevel2["CONFIRMED"] = "confirmed";
500
+ ConfidenceLevel2["HIGH"] = "high";
501
+ ConfidenceLevel2["MODERATE"] = "moderate";
502
+ ConfidenceLevel2["LOW"] = "low";
503
+ return ConfidenceLevel2;
504
+ })(ConfidenceLevel || {});
505
+ var ConfidenceScores = {
506
+ ["confirmed" /* CONFIRMED */]: 0.99,
507
+ ["high" /* HIGH */]: 0.85,
508
+ ["moderate" /* MODERATE */]: 0.65,
509
+ ["low" /* LOW */]: 0.4
510
+ };
511
+ function confidenceToScore(level) {
512
+ return ConfidenceScores[level] ?? 0.7;
513
+ }
514
+ function scoreToConfidence(score) {
515
+ if (score >= 0.95) return "confirmed" /* CONFIRMED */;
516
+ if (score >= 0.8) return "high" /* HIGH */;
517
+ if (score >= 0.6) return "moderate" /* MODERATE */;
518
+ return "low" /* LOW */;
519
+ }
520
+ var MULTI_VALUE_PREDICATES = /* @__PURE__ */ new Set([
521
+ // Events — multiple things happen over time
522
+ "status_change" /* STATUS_CHANGE */,
523
+ "event" /* EVENT */,
524
+ "decision" /* DECISION */,
525
+ "outcome" /* OUTCOME */,
526
+ // Emotional — multiple sentiments about different things
527
+ "sentiment" /* SENTIMENT */,
528
+ "frustration" /* FRUSTRATION */,
529
+ "excitement" /* EXCITEMENT */,
530
+ "concern" /* CONCERN */,
531
+ "goal" /* GOAL */,
532
+ "interest" /* INTEREST */,
533
+ // Memory — multiple reminders, contexts, projects
534
+ "reminder" /* REMINDER */,
535
+ "context:task" /* CONTEXT_TASK */,
536
+ "current_project" /* CURRENT_PROJECT */,
537
+ // Timeline
538
+ "timeline"
539
+ ]);
540
+ var REVERSE_RELATIONSHIPS = {
541
+ // Proper OrgRelationship values
542
+ ["reports_to" /* REPORTS_TO */]: "manages" /* MANAGES */,
543
+ ["manages" /* MANAGES */]: "reports_to" /* REPORTS_TO */,
544
+ ["member_of" /* MEMBER_OF */]: "has_member" /* HAS_MEMBER */,
545
+ ["has_member" /* HAS_MEMBER */]: "member_of" /* MEMBER_OF */,
546
+ ["mentors" /* MENTORS */]: "mentored_by" /* MENTORED_BY */,
547
+ ["mentored_by" /* MENTORED_BY */]: "mentors" /* MENTORS */,
548
+ ["collaborates_with" /* COLLABORATES_WITH */]: "collaborates_with" /* COLLABORATES_WITH */,
549
+ ["candidate_for" /* CANDIDATE_FOR */]: "candidate_for" /* CANDIDATE_FOR */,
550
+ ["stakeholder_in" /* STAKEHOLDER_IN */]: "stakeholder_in" /* STAKEHOLDER_IN */,
551
+ // Agent-facing predicate names → proper relationship types
552
+ // The model sends 'direct_report' as predicate, SDK maps to proper relationships
553
+ "direct_report": "reports_to" /* REPORTS_TO */,
554
+ "team_member": "member_of" /* MEMBER_OF */,
555
+ "candidate": "candidate_for" /* CANDIDATE_FOR */,
556
+ "manager": "manages" /* MANAGES */,
557
+ "stakeholder": "stakeholder_in" /* STAKEHOLDER_IN */,
558
+ "collaborator": "collaborates_with" /* COLLABORATES_WITH */,
559
+ "mentor": "mentored_by" /* MENTORED_BY */
560
+ };
561
+ var RELATIONSHIP_LABELS = {
562
+ ["reports_to" /* REPORTS_TO */]: "reports to (person is a direct report)",
563
+ ["manages" /* MANAGES */]: "manages (user is the manager)",
564
+ ["member_of" /* MEMBER_OF */]: "is a member of (team, project)",
565
+ ["holds_role" /* HOLDS_ROLE */]: "holds a role/position",
566
+ ["candidate_for" /* CANDIDATE_FOR */]: "is a candidate for a role",
567
+ ["collaborates_with" /* COLLABORATES_WITH */]: "collaborates with",
568
+ ["mentors" /* MENTORS */]: "mentors",
569
+ ["stakeholder_in" /* STAKEHOLDER_IN */]: "is a stakeholder in"
570
+ };
571
+
572
+ // src/types/signals.ts
573
+ var SYSTEM_SIGNAL_TYPES = [
574
+ "frustration",
575
+ "excitement",
576
+ "concern",
577
+ "satisfaction",
578
+ "confusion",
579
+ "gratitude",
580
+ "tension",
581
+ "sentiment"
582
+ ];
583
+ function isValidSignalType(type) {
584
+ if (SYSTEM_SIGNAL_TYPES.includes(type)) return true;
585
+ if (type.startsWith("custom:")) return true;
586
+ return false;
587
+ }
588
+ var SIGNAL_DECAY_CONFIG = {
589
+ frustration: 24,
590
+ excitement: 24,
591
+ concern: 24,
592
+ satisfaction: 24,
593
+ confusion: 24,
594
+ gratitude: 24,
595
+ tension: 24,
596
+ sentiment: 24,
597
+ _default: 24
598
+ };
599
+ function getDecayHalfLife(signalType) {
600
+ return SIGNAL_DECAY_CONFIG[signalType] ?? SIGNAL_DECAY_CONFIG._default;
601
+ }
602
+ var POSITIVE_SIGNALS = /* @__PURE__ */ new Set([
603
+ "satisfaction",
604
+ "excitement",
605
+ "gratitude"
606
+ ]);
607
+ var NEGATIVE_SIGNALS = /* @__PURE__ */ new Set([
608
+ "frustration",
609
+ "concern",
610
+ "tension",
611
+ "confusion"
612
+ ]);
613
+
614
+ // src/signals.ts
615
+ var LEGACY_SIGNAL_PREDICATES = /* @__PURE__ */ new Set([
616
+ "sentiment",
617
+ "frustration",
618
+ "excitement",
619
+ "concern",
620
+ "goal",
621
+ "aspiration",
622
+ "preference",
623
+ "interest"
624
+ ]);
625
+ var SignalsNamespace = class {
626
+ constructor(http, tenantId) {
627
+ this.http = http;
628
+ this.tenantId = tenantId;
629
+ }
630
+ /**
631
+ * Record an emotional signal about a user.
632
+ *
633
+ * @example
634
+ * ```typescript
635
+ * await brain.signals.record({
636
+ * userId: 'cmk123',
637
+ * type: 'frustration',
638
+ * content: 'Frustrated about the hiring timeline',
639
+ * intensity: 0.85,
640
+ * aboutSubject: 'context:hiring-ea',
641
+ * })
642
+ * ```
643
+ */
644
+ async record(input) {
645
+ if (!isValidSignalType(input.type)) {
646
+ throw new Error(`Invalid signal type: ${input.type}. Use one of: ${SYSTEM_SIGNAL_TYPES.join(", ")} or custom:{tenant}:{type}`);
647
+ }
648
+ const userSubject = subject("user" /* USER */, input.userId);
649
+ const predicate = `signal:${input.type}`;
650
+ const value = {
651
+ content: input.content,
652
+ intensity: input.intensity ?? 0.7,
653
+ about_subject: input.aboutSubject || null,
654
+ session_id: input.sessionId || null
655
+ };
656
+ const result = await this.http.post("/api/v1/assertions", {
657
+ tenant_id: this.tenantId,
658
+ subject: userSubject,
659
+ predicate,
660
+ value,
661
+ confidence: input.intensity ?? 0.7
662
+ });
663
+ let resolved = 0;
664
+ if (input.resolveConflicting && POSITIVE_SIGNALS.has(input.type)) {
665
+ try {
666
+ const snapshot = await this.query(userSubject, { windowHours: 72 });
667
+ for (const sig of snapshot.signals) {
668
+ if (!NEGATIVE_SIGNALS.has(sig.type)) continue;
669
+ if (sig.resolvedBy) continue;
670
+ const sameContext = input.aboutSubject ? sig.aboutSubject === input.aboutSubject : !sig.aboutSubject;
671
+ if (sameContext) {
672
+ await this.resolve({ signalId: sig.id, resolvedBySignalId: result.id });
673
+ resolved++;
674
+ }
675
+ }
676
+ } catch {
677
+ }
678
+ }
679
+ return { id: result.id, ...resolved > 0 && { resolved } };
680
+ }
681
+ /**
682
+ * Query signals for a user with computed decay and trajectory.
683
+ * Delegates to the engine's signal query endpoint for server-side computation.
684
+ *
685
+ * @example
686
+ * ```typescript
687
+ * const snapshot = await brain.signals.query('user:cmk123', {
688
+ * windowHours: 72,
689
+ * type: 'frustration',
690
+ * })
691
+ * ```
692
+ */
693
+ async query(userSubject, options = {}) {
694
+ const windowHours = options.windowHours ?? 72;
695
+ const query = { window: String(windowHours) };
696
+ if (options.type) query.type = options.type;
697
+ const qs = new URLSearchParams(query).toString();
698
+ const response = await this.http.get(
699
+ `/api/v1/signals/${enc(this.tenantId)}/${enc(userSubject)}?${qs}`
700
+ );
701
+ const signals = response.signals.map((s) => ({
702
+ id: s.assertion_id,
703
+ type: s.signal_type,
704
+ content: s.content,
705
+ intensity: s.intensity,
706
+ decayedIntensity: s.decayed_intensity,
707
+ ageHours: Math.round(s.age_hours * 10) / 10,
708
+ aboutSubject: s.about_subject || void 0,
709
+ resolvedBy: s.resolved_by || void 0,
710
+ timestamp: s.timestamp
711
+ }));
712
+ return {
713
+ signals,
714
+ trajectory: response.trajectory,
715
+ aggregateIntensity: response.aggregate_intensity
716
+ };
717
+ }
718
+ /**
719
+ * Resolve a signal — mark it as resolved by a subsequent positive interaction.
720
+ * The resolved signal's effective intensity drops faster.
721
+ *
722
+ * @example
723
+ * ```typescript
724
+ * await brain.signals.resolve({
725
+ * signalId: 'abc123',
726
+ * resolvedBySignalId: 'def456',
727
+ * })
728
+ * ```
729
+ */
730
+ async resolve(input) {
731
+ const original = await this.http.get(
732
+ `/api/v1/assertions/${enc(this.tenantId)}/${enc(input.signalId)}`
733
+ ).catch(() => null);
734
+ if (!original) return { success: false };
735
+ const value = typeof original.value === "object" && original.value !== null ? { ...original.value, resolved_by: input.resolvedBySignalId } : { content: String(original.value), resolved_by: input.resolvedBySignalId };
736
+ await this.http.post("/api/v1/assertions/supersede", {
737
+ tenant_id: this.tenantId,
738
+ original_assertion_id: input.signalId,
739
+ subject: original.subject,
740
+ predicate: original.predicate,
741
+ value,
742
+ confidence: original.confidence
743
+ });
744
+ return { success: true };
745
+ }
746
+ };
747
+ function computeDecay(intensity, ageHours, halfLifeHours, isResolved = false) {
748
+ const effectiveHalfLife = isResolved ? halfLifeHours / 4 : halfLifeHours;
749
+ const decayed = intensity * Math.pow(2, -ageHours / effectiveHalfLife);
750
+ return Math.round(decayed * 100) / 100;
751
+ }
752
+ function extractSignals(assertions, windowHours = 72) {
753
+ const now = Date.now();
754
+ const windowMs = windowHours * 60 * 60 * 1e3;
755
+ const entries = [];
756
+ for (const a of assertions) {
757
+ if (a.isSuperseded) continue;
758
+ const isSignal = a.predicate.startsWith("signal:");
759
+ const isLegacy = LEGACY_SIGNAL_PREDICATES.has(a.predicate);
760
+ if (!isSignal && !isLegacy) continue;
761
+ const timestamp = a.validFrom;
762
+ const ageMs = now - new Date(timestamp).getTime();
763
+ if (ageMs > windowMs) continue;
764
+ const ageHours = ageMs / (60 * 60 * 1e3);
765
+ const type = isSignal ? a.predicate.slice(7) : a.predicate;
766
+ const halfLife = getDecayHalfLife(type);
767
+ let content = "";
768
+ let intensity = a.confidence ?? 0.7;
769
+ let aboutSubject;
770
+ let resolvedBy;
771
+ if (typeof a.value === "object" && a.value !== null) {
772
+ const v = a.value;
773
+ content = v.content || "";
774
+ intensity = v.intensity ?? intensity;
775
+ aboutSubject = v.about_subject || void 0;
776
+ resolvedBy = v.resolved_by || void 0;
777
+ } else {
778
+ content = String(a.value);
779
+ }
780
+ entries.push({
781
+ id: a.id,
782
+ type,
783
+ content,
784
+ intensity,
785
+ decayedIntensity: computeDecay(intensity, ageHours, halfLife, !!resolvedBy),
786
+ ageHours: Math.round(ageHours * 10) / 10,
787
+ aboutSubject,
788
+ resolvedBy,
789
+ timestamp
790
+ });
791
+ }
792
+ entries.sort((a, b) => a.ageHours - b.ageHours);
793
+ return entries;
794
+ }
795
+ function enc(s) {
796
+ return encodeURIComponent(s);
797
+ }
798
+
799
+ // src/users.ts
800
+ var UsersNamespace = class {
801
+ constructor(http, tenantId) {
802
+ this.http = http;
803
+ this.tenantId = tenantId;
804
+ }
805
+ /**
806
+ * Identify a user and retrieve their full context.
807
+ *
808
+ * This is the FIRST thing an agent should call at session start.
809
+ * Returns whether the user is known, their memories, connected
810
+ * people, reminders, conflicts, and a summary.
811
+ *
812
+ * @example
813
+ * ```typescript
814
+ * const user = await brain.users.identify({
815
+ * userId: 'cmk123...',
816
+ * displayName: 'Tom Santos',
817
+ * })
818
+ *
819
+ * if (!user.isKnown) {
820
+ * // First encounter — get to know them
821
+ * } else {
822
+ * // Returning user — reference what you know
823
+ * // user.reminders — bring these up
824
+ * // user.conflicts — address these
825
+ * // user.connectedPeople — context about their org
826
+ * }
827
+ * ```
828
+ */
829
+ async identify(input) {
830
+ const userSubject = subject("user" /* USER */, input.userId);
831
+ const assertions = await this.http.get(
832
+ `/api/v1/assertions/query/${enc2(this.tenantId)}/${enc2(userSubject)}`
833
+ );
834
+ const active = assertions.filter((a) => !a.isSuperseded);
835
+ const isKnown = active.length > 0;
836
+ if (input.displayName && !active.some((a) => a.predicate === "name" || a.predicate === "full_name")) {
837
+ try {
838
+ await this.http.post("/api/v1/assertions", {
839
+ tenant_id: this.tenantId,
840
+ subject: userSubject,
841
+ predicate: "name",
842
+ value: input.displayName,
843
+ confidence: 1
844
+ });
845
+ } catch {
846
+ }
847
+ }
848
+ const nameAssertion = active.find((a) => a.predicate === "name" || a.predicate === "full_name");
849
+ const name = nameAssertion?.value || input.displayName || null;
850
+ const reminders = active.filter((a) => a.predicate === "reminder").map((a) => ({ id: a.id, predicate: a.predicate, value: a.value, confidence: a.confidence, createdAt: a.validFrom }));
851
+ for (const reminder of reminders) {
852
+ try {
853
+ await this.http.post(
854
+ `/api/v1/assertions/retract/${enc2(this.tenantId)}/${enc2(reminder.id)}`,
855
+ {}
856
+ );
857
+ } catch {
858
+ }
859
+ }
860
+ const contexts = active.filter((a) => a.predicate === "context" || a.predicate === "context:task").map((a) => ({ id: a.id, predicate: a.predicate, value: a.value, confidence: a.confidence, createdAt: a.validFrom }));
861
+ const signals = extractSignals(assertions);
862
+ const signalIds = new Set(signals.map((s) => s.id));
863
+ let rapportTrajectory = "neutral";
864
+ try {
865
+ const qs = new URLSearchParams({ window: "72" }).toString();
866
+ const snapshot = await this.http.get(
867
+ `/api/v1/signals/${enc2(this.tenantId)}/${enc2(userSubject)}?${qs}`
868
+ );
869
+ rapportTrajectory = snapshot.trajectory;
870
+ } catch {
871
+ }
872
+ const memories = active.filter(
873
+ (a) => a.predicate !== "reminder" && a.predicate !== "context" && a.predicate !== "context:task" && !signalIds.has(a.id)
874
+ // exclude signals from memories
875
+ ).map((a) => ({ id: a.id, predicate: a.predicate, value: a.value, confidence: a.confidence, createdAt: a.validFrom }));
876
+ const connectedPeople = [];
877
+ try {
878
+ const relationships = await this.http.get(`/api/v1/relationships/${enc2(this.tenantId)}/${enc2(userSubject)}`);
879
+ const visited = /* @__PURE__ */ new Set();
880
+ for (const rel of relationships) {
881
+ const other = rel.fromSubject === userSubject ? rel.toSubject : rel.fromSubject;
882
+ if (!other || other === userSubject || visited.has(other)) continue;
883
+ visited.add(other);
884
+ const personAssertions = await this.http.get(
885
+ `/api/v1/assertions/query/${enc2(this.tenantId)}/${enc2(other)}`
886
+ );
887
+ const personActive = personAssertions.filter((a) => !a.isSuperseded);
888
+ const personName = personActive.find((a) => a.predicate === "name");
889
+ const facts = personActive.filter((a) => a.predicate !== "name").map((a) => ({ predicate: a.predicate, value: a.value }));
890
+ connectedPeople.push({
891
+ subject: other,
892
+ name: personName?.value || other,
893
+ relationship: rel.relationshipType,
894
+ facts
895
+ });
896
+ }
897
+ } catch {
898
+ }
899
+ const conflicts = [];
900
+ try {
901
+ if (!input.agentId) throw new Error("agentId is required on IdentifyUserInput to fetch conflicts");
902
+ const pending = await this.http.get(`/api/v1/intake/pending/${enc2(input.agentId)}?status=conflict_detected`);
903
+ for (const item of pending) {
904
+ if (item.acknowledged) continue;
905
+ const hint = item.surfacingHint || "";
906
+ const involvesUser = hint.includes(userSubject) || (item.persistedAssertionIds || []).some((id) => {
907
+ const a = assertions.find((a2) => a2.id === id);
908
+ return a?.subject === userSubject;
909
+ });
910
+ if (!involvesUser) continue;
911
+ let resolvedHint = hint || "A conflict was detected.";
912
+ if (name) {
913
+ resolvedHint = resolvedHint.replace(
914
+ new RegExp(userSubject.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
915
+ name
916
+ );
917
+ }
918
+ conflicts.push({ id: item.id, hint: resolvedHint });
919
+ }
920
+ } catch {
921
+ }
922
+ const parts = [];
923
+ if (conflicts.length > 0) {
924
+ parts.push(`ATTENTION: ${conflicts.length} knowledge conflict(s) \u2014 MUST address: ${conflicts.map((c) => c.hint).join(" | ")}`);
925
+ }
926
+ if (reminders.length > 0) {
927
+ parts.push(`REMINDERS (${reminders.length}): ${reminders.map((r) => `"${r.value}"`).join(", ")}. Dismiss each after surfacing.`);
928
+ }
929
+ if (connectedPeople.length > 0) {
930
+ parts.push(`Connected people:
931
+ ${connectedPeople.map((p) => {
932
+ const factsStr = p.facts.map((f) => `${f.predicate}: ${f.value}`).join(", ");
933
+ return `- ${p.name} (${p.relationship})${factsStr ? ": " + factsStr : ""}`;
934
+ }).join("\n")}`);
935
+ }
936
+ if (memories.length > 0 && parts.length === 0) {
937
+ parts.push(`You know ${memories.length} things about this user.`);
938
+ }
939
+ if (parts.length === 0) {
940
+ parts.push("This is a new user \u2014 no memories yet. Get to know them.");
941
+ }
942
+ return {
943
+ subject: userSubject,
944
+ isKnown,
945
+ name,
946
+ memories,
947
+ connectedPeople,
948
+ reminders,
949
+ contexts,
950
+ conflicts,
951
+ signals,
952
+ rapportTrajectory,
953
+ summary: parts.join("\n")
954
+ };
955
+ }
956
+ /**
957
+ * Register a person that the user mentioned.
958
+ *
959
+ * Creates the person node, their role, and bidirectional
960
+ * relationships to the user. One call does everything.
961
+ *
962
+ * @example
963
+ * ```typescript
964
+ * const result = await brain.users.registerPerson({
965
+ * name: 'John Smith',
966
+ * userId: 'cmk123...',
967
+ * relationship: 'direct_report',
968
+ * role: 'VP of Engineering',
969
+ * })
970
+ * ```
971
+ */
972
+ async registerPerson(input) {
973
+ const userSubject = subject("user" /* USER */, input.userId);
974
+ const personSubject = subject("person" /* PERSON */, input.name);
975
+ const conf = typeof input.confidence === "number" ? input.confidence : confidenceToScore(input.confidence || "confirmed" /* CONFIRMED */);
976
+ let assertionsCreated = 0;
977
+ let relationshipsCreated = 0;
978
+ const warnings = [];
979
+ await this.http.post("/api/v1/assertions", {
980
+ tenant_id: this.tenantId,
981
+ subject: personSubject,
982
+ predicate: "name",
983
+ value: input.name,
984
+ confidence: conf
985
+ });
986
+ assertionsCreated++;
987
+ if (input.role) {
988
+ try {
989
+ const existing = await this.http.get(
990
+ `/api/v1/assertions/query/${enc2(this.tenantId)}/${enc2(personSubject)}`
991
+ );
992
+ const existingRole = existing.find((a) => a.predicate === "role" && !a.isSuperseded);
993
+ if (existingRole && existingRole.value !== input.role) {
994
+ warnings.push(`${input.name} was previously "${existingRole.value}" \u2014 now being set as "${input.role}". Role change or mistake?`);
995
+ await this.http.post("/api/v1/assertions/supersede", {
996
+ tenant_id: this.tenantId,
997
+ original_assertion_id: existingRole.id,
998
+ subject: personSubject,
999
+ predicate: "role",
1000
+ value: input.role,
1001
+ confidence: conf
1002
+ });
1003
+ } else if (!existingRole) {
1004
+ await this.http.post("/api/v1/assertions", {
1005
+ tenant_id: this.tenantId,
1006
+ subject: personSubject,
1007
+ predicate: "role",
1008
+ value: input.role,
1009
+ confidence: conf
1010
+ });
1011
+ }
1012
+ } catch {
1013
+ await this.http.post("/api/v1/assertions", {
1014
+ tenant_id: this.tenantId,
1015
+ subject: personSubject,
1016
+ predicate: "role",
1017
+ value: input.role,
1018
+ confidence: conf
1019
+ });
1020
+ }
1021
+ assertionsCreated++;
1022
+ try {
1023
+ const allAssertions = await this.http.get(
1024
+ `/api/v1/assertions/list/${enc2(this.tenantId)}`
1025
+ );
1026
+ const sameRole = allAssertions.filter(
1027
+ (a) => a.subject.startsWith("person:") && a.subject !== personSubject && a.predicate === "role" && a.value === input.role && !a.isSuperseded
1028
+ );
1029
+ if (sameRole.length > 0) {
1030
+ const otherAssertions = await this.http.get(
1031
+ `/api/v1/assertions/query/${enc2(this.tenantId)}/${enc2(sameRole[0].subject)}`
1032
+ );
1033
+ const otherName = otherAssertions.find((a) => a.predicate === "name")?.value || sameRole[0].subject;
1034
+ warnings.push(`"${input.role}" is already held by ${otherName}. Is ${otherName} no longer in this role?`);
1035
+ }
1036
+ } catch {
1037
+ }
1038
+ const roleSubject = subject("role" /* ROLE */, input.role);
1039
+ await this.http.post("/api/v1/assertions", {
1040
+ tenant_id: this.tenantId,
1041
+ subject: roleSubject,
1042
+ predicate: "name",
1043
+ value: input.role,
1044
+ confidence: conf
1045
+ });
1046
+ await this.http.post("/api/v1/relationships", {
1047
+ tenant_id: this.tenantId,
1048
+ from_subject: personSubject,
1049
+ to_subject: roleSubject,
1050
+ relationship_type: "holds_role" /* HOLDS_ROLE */,
1051
+ confidence: conf
1052
+ });
1053
+ assertionsCreated++;
1054
+ relationshipsCreated++;
1055
+ }
1056
+ if (input.details) {
1057
+ await this.http.post("/api/v1/assertions", {
1058
+ tenant_id: this.tenantId,
1059
+ subject: personSubject,
1060
+ predicate: "details",
1061
+ value: input.details,
1062
+ confidence: conf
1063
+ });
1064
+ assertionsCreated++;
1065
+ }
1066
+ await this.http.post("/api/v1/assertions", {
1067
+ tenant_id: this.tenantId,
1068
+ subject: personSubject,
1069
+ predicate: "status",
1070
+ value: input.relationship === "candidate" ? "candidate" : "active",
1071
+ confidence: conf
1072
+ });
1073
+ assertionsCreated++;
1074
+ const FORWARD_MAP = {
1075
+ "direct_report": "manages" /* MANAGES */,
1076
+ "team_member": "has_member" /* HAS_MEMBER */,
1077
+ "candidate": "manages" /* MANAGES */,
1078
+ // user manages the hiring
1079
+ "manager": "reports_to" /* REPORTS_TO */,
1080
+ // user reports to this person
1081
+ "stakeholder": "stakeholder_in" /* STAKEHOLDER_IN */,
1082
+ "collaborator": "collaborates_with" /* COLLABORATES_WITH */,
1083
+ "mentor": "mentors" /* MENTORS */
1084
+ };
1085
+ const forwardType = FORWARD_MAP[input.relationship] || input.relationship;
1086
+ const reverseType = REVERSE_RELATIONSHIPS[input.relationship] || REVERSE_RELATIONSHIPS[forwardType] || input.relationship;
1087
+ await this.http.post("/api/v1/relationships", {
1088
+ tenant_id: this.tenantId,
1089
+ from_subject: userSubject,
1090
+ to_subject: personSubject,
1091
+ relationship_type: forwardType,
1092
+ confidence: conf
1093
+ });
1094
+ relationshipsCreated++;
1095
+ await this.http.post("/api/v1/relationships", {
1096
+ tenant_id: this.tenantId,
1097
+ from_subject: personSubject,
1098
+ to_subject: userSubject,
1099
+ relationship_type: reverseType,
1100
+ confidence: conf
1101
+ });
1102
+ relationshipsCreated++;
1103
+ return { personSubject, assertionsCreated, relationshipsCreated, warnings };
1104
+ }
1105
+ /**
1106
+ * Record an emotional state or rapport signal about the user.
1107
+ *
1108
+ * @example
1109
+ * ```typescript
1110
+ * await brain.users.recordRapport({
1111
+ * userId: 'cmk123...',
1112
+ * type: 'frustration',
1113
+ * value: 'Frustrated about losing the EA candidate',
1114
+ * aboutPerson: 'Sarah Johnson',
1115
+ * })
1116
+ * ```
1117
+ */
1118
+ async recordRapport(input) {
1119
+ const userSubject = subject("user" /* USER */, input.userId);
1120
+ const conf = typeof input.confidence === "number" ? input.confidence : confidenceToScore(input.confidence || "high" /* HIGH */);
1121
+ await this.http.post("/api/v1/assertions", {
1122
+ tenant_id: this.tenantId,
1123
+ subject: userSubject,
1124
+ predicate: input.type,
1125
+ value: input.value,
1126
+ confidence: conf
1127
+ });
1128
+ if (input.aboutPerson) {
1129
+ const personSubject = subject("person" /* PERSON */, input.aboutPerson);
1130
+ try {
1131
+ const personAssertions = await this.http.get(
1132
+ `/api/v1/assertions/query/${enc2(this.tenantId)}/${enc2(personSubject)}`
1133
+ );
1134
+ if (personAssertions.length > 0) {
1135
+ await this.http.post("/api/v1/assertions", {
1136
+ tenant_id: this.tenantId,
1137
+ subject: personSubject,
1138
+ predicate: "timeline",
1139
+ value: input.value,
1140
+ confidence: conf
1141
+ });
1142
+ }
1143
+ } catch {
1144
+ }
1145
+ }
1146
+ return { success: true };
1147
+ }
1148
+ /**
1149
+ * Dismiss a reminder after the agent has surfaced it.
1150
+ */
1151
+ async dismissReminder(userId, reminderContent) {
1152
+ const userSubject = subject("user" /* USER */, userId);
1153
+ const assertions = await this.http.get(
1154
+ `/api/v1/assertions/query/${enc2(this.tenantId)}/${enc2(userSubject)}`
1155
+ );
1156
+ const reminder = assertions.find(
1157
+ (a) => a.predicate === "reminder" && !a.isSuperseded && a.value.toLowerCase().includes(reminderContent.toLowerCase())
1158
+ );
1159
+ if (reminder) {
1160
+ await this.http.post(`/api/v1/assertions/retract/${enc2(this.tenantId)}/${enc2(reminder.id)}`, {});
1161
+ return { success: true };
1162
+ }
1163
+ return { success: false };
1164
+ }
1165
+ };
1166
+ function enc2(s) {
1167
+ return encodeURIComponent(s);
1168
+ }
1169
+
1170
+ // src/client.ts
1171
+ var AssertionsNamespace = class {
1172
+ constructor(http, tenantId) {
1173
+ this.http = http;
1174
+ this.tenantId = tenantId;
1175
+ }
1176
+ /** Create an assertion in the knowledge graph. */
1177
+ async create(input) {
1178
+ const tenantId = input.tenantId || this.tenantId;
1179
+ return this.http.post("/api/v1/assertions", {
1180
+ tenant_id: tenantId,
1181
+ subject: input.subject,
1182
+ predicate: input.predicate,
1183
+ value: input.value,
1184
+ confidence: input.confidence
1185
+ });
1186
+ }
1187
+ /** Get an assertion by its content-addressable ID. */
1188
+ async get(assertionId, options) {
1189
+ const tenantId = options?.tenantId || this.tenantId;
1190
+ return this.http.get(
1191
+ `/api/v1/assertions/${enc3(tenantId)}/${enc3(assertionId)}`
1192
+ );
1193
+ }
1194
+ /** Query assertions by subject. */
1195
+ async query(subject2, options) {
1196
+ const tenantId = options?.tenantId || this.tenantId;
1197
+ return this.http.get(
1198
+ `/api/v1/assertions/query/${enc3(tenantId)}/${enc3(subject2)}`
1199
+ );
1200
+ }
1201
+ /** List all active assertions for the tenant. */
1202
+ async list(options) {
1203
+ const tenantId = options?.tenantId || this.tenantId;
1204
+ return this.http.get(
1205
+ `/api/v1/assertions/list/${enc3(tenantId)}`
1206
+ );
1207
+ }
1208
+ /** Supersede an existing assertion with updated values. */
1209
+ async supersede(input) {
1210
+ const tenantId = input.tenantId || this.tenantId;
1211
+ return this.http.post("/api/v1/assertions/supersede", {
1212
+ tenant_id: tenantId,
1213
+ original_assertion_id: input.originalAssertionId,
1214
+ subject: input.subject,
1215
+ predicate: input.predicate,
1216
+ value: input.value,
1217
+ confidence: input.confidence
1218
+ });
1219
+ }
1220
+ /** Retract an assertion by closing its temporal bounds. */
1221
+ async retract(assertionId, options) {
1222
+ const tenantId = options?.tenantId || this.tenantId;
1223
+ return this.http.post(
1224
+ `/api/v1/assertions/retract/${enc3(tenantId)}/${enc3(assertionId)}`,
1225
+ {}
1226
+ );
1227
+ }
1228
+ };
1229
+ var RelationshipsNamespace = class {
1230
+ constructor(http, tenantId) {
1231
+ this.http = http;
1232
+ this.tenantId = tenantId;
1233
+ }
1234
+ /** Create a relationship between two subjects. */
1235
+ async create(input) {
1236
+ const tenantId = input.tenantId || this.tenantId;
1237
+ return this.http.post("/api/v1/relationships", {
1238
+ tenant_id: tenantId,
1239
+ from_subject: input.fromSubject,
1240
+ to_subject: input.toSubject,
1241
+ relationship_type: input.relationshipType,
1242
+ confidence: input.confidence,
1243
+ weight: input.weight,
1244
+ properties: input.properties
1245
+ });
1246
+ }
1247
+ /** Get relationships for a subject. */
1248
+ async query(subject2, options) {
1249
+ const tenantId = options?.tenantId || this.tenantId;
1250
+ return this.http.get(
1251
+ `/api/v1/relationships/${enc3(tenantId)}/${enc3(subject2)}`
1252
+ );
1253
+ }
1254
+ /** List all relationships for the tenant. */
1255
+ async list(options) {
1256
+ const tenantId = options?.tenantId || this.tenantId;
1257
+ return this.http.get(
1258
+ `/api/v1/relationships/list/${enc3(tenantId)}`
1259
+ );
1260
+ }
1261
+ };
1262
+ var AgentsNamespace = class {
1263
+ constructor(http, tenantId) {
1264
+ this.http = http;
1265
+ this.tenantId = tenantId;
1266
+ }
1267
+ /** Create a new agent. */
1268
+ async create(input) {
1269
+ const tenantId = input.tenantId || this.tenantId;
1270
+ return this.http.post("/api/v1/agents", {
1271
+ tenant_id: tenantId,
1272
+ name: input.name,
1273
+ description: input.description,
1274
+ personality: input.personality,
1275
+ instructions: input.instructions ? toWire(input.instructions) : void 0,
1276
+ model: input.model ? toWire(input.model) : void 0,
1277
+ capabilities: input.capabilities,
1278
+ memory_policy: input.memoryPolicy ? toWire(input.memoryPolicy) : void 0
1279
+ });
1280
+ }
1281
+ /** Get an agent by ID. */
1282
+ async get(agentId, options) {
1283
+ const tenantId = options?.tenantId || this.tenantId;
1284
+ return this.http.get(
1285
+ `/api/v1/agents/${enc3(tenantId)}/${enc3(agentId)}`
1286
+ );
1287
+ }
1288
+ /** Update an agent. */
1289
+ async update(agentId, input, options) {
1290
+ const tenantId = options?.tenantId || this.tenantId;
1291
+ return this.http.put(
1292
+ `/api/v1/agents/${enc3(tenantId)}/${enc3(agentId)}`,
1293
+ {
1294
+ tenant_id: tenantId,
1295
+ name: input.name,
1296
+ description: input.description,
1297
+ personality: input.personality,
1298
+ instructions: input.instructions ? toWire(input.instructions) : void 0,
1299
+ model: input.model ? toWire(input.model) : void 0,
1300
+ capabilities: input.capabilities,
1301
+ memory_policy: input.memoryPolicy ? toWire(input.memoryPolicy) : void 0,
1302
+ is_active: input.isActive
1303
+ }
1304
+ );
1305
+ }
1306
+ /** Delete an agent. */
1307
+ async delete(agentId, options) {
1308
+ const tenantId = options?.tenantId || this.tenantId;
1309
+ await this.http.delete(`/api/v1/agents/${enc3(tenantId)}/${enc3(agentId)}`);
1310
+ }
1311
+ /** List all agents for the tenant. */
1312
+ async list(options) {
1313
+ const tenantId = options?.tenantId || this.tenantId;
1314
+ return this.http.get(
1315
+ `/api/v1/agents/list/${enc3(tenantId)}`
1316
+ );
1317
+ }
1318
+ /** Get composed system instructions for an agent. */
1319
+ async getInstructions(agentId, options) {
1320
+ const tenantId = options?.tenantId || this.tenantId;
1321
+ return this.http.get(
1322
+ `/api/v1/agents/${enc3(tenantId)}/${enc3(agentId)}/instructions`
1323
+ );
1324
+ }
1325
+ };
1326
+ var MemoryNamespace = class {
1327
+ constructor(http, tenantId) {
1328
+ this.http = http;
1329
+ this.tenantId = tenantId;
1330
+ }
1331
+ /**
1332
+ * Store a fact in the agent's memory.
1333
+ *
1334
+ * Routes through the Thalamus by default. The Thalamus will:
1335
+ * - Classify the signal (reject noise)
1336
+ * - Check for contradictions with existing assertions
1337
+ * - Detect duplicates and reinforce instead of creating new
1338
+ *
1339
+ * Pass `raw: true` to bypass Thalamus for system operations.
1340
+ */
1341
+ async store(input) {
1342
+ const tenantId = input.tenantId || this.tenantId;
1343
+ if (input.raw) {
1344
+ return this.http.post("/api/v1/assertions", {
1345
+ tenant_id: tenantId,
1346
+ subject: input.subject,
1347
+ predicate: input.predicate,
1348
+ value: input.value,
1349
+ confidence: input.confidence
1350
+ });
1351
+ }
1352
+ const correlationId = `mem_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
1353
+ return this.http.post("/api/v1/intake/submit", {
1354
+ correlation_id: correlationId,
1355
+ agent_id: input.agentId,
1356
+ tenant_id: tenantId,
1357
+ candidates: [{
1358
+ subject: input.subject,
1359
+ predicate: input.predicate,
1360
+ value: input.value,
1361
+ source_confidence: input.confidence ?? 0.95,
1362
+ provenance: "agent",
1363
+ person_name: input.personName
1364
+ }],
1365
+ context: input.context
1366
+ });
1367
+ }
1368
+ /** Recall all memories for a subject. */
1369
+ async recall(subject2, options) {
1370
+ const tenantId = options?.tenantId || this.tenantId;
1371
+ return this.http.get(
1372
+ `/api/v1/assertions/query/${enc3(tenantId)}/${enc3(subject2)}`
1373
+ );
1374
+ }
1375
+ /** Forget a specific memory (retract the assertion). */
1376
+ async forget(assertionId, options) {
1377
+ const tenantId = options?.tenantId || this.tenantId;
1378
+ return this.http.post(
1379
+ `/api/v1/assertions/retract/${enc3(tenantId)}/${enc3(assertionId)}`,
1380
+ {}
1381
+ );
1382
+ }
1383
+ };
1384
+ var IntakeNamespace = class {
1385
+ constructor(http, tenantId) {
1386
+ this.http = http;
1387
+ this.tenantId = tenantId;
1388
+ }
1389
+ /** Submit candidate assertions for Thalamus processing. */
1390
+ async submit(input) {
1391
+ const tenantId = input.tenantId || this.tenantId;
1392
+ return this.http.post("/api/v1/intake/submit", {
1393
+ correlation_id: input.correlationId,
1394
+ agent_id: input.agentId,
1395
+ tenant_id: tenantId,
1396
+ candidates: input.candidates.map((c) => ({
1397
+ subject: c.subject,
1398
+ predicate: c.predicate,
1399
+ value: c.value,
1400
+ source_confidence: c.sourceConfidence,
1401
+ valid_from: c.validFrom,
1402
+ valid_until: c.validUntil,
1403
+ provenance: c.provenance,
1404
+ person_name: c.personName
1405
+ })),
1406
+ context: input.context
1407
+ });
1408
+ }
1409
+ /** Get pending intake results for an agent. */
1410
+ async pending(agentId, options) {
1411
+ let path = `/api/v1/intake/pending/${enc3(agentId)}`;
1412
+ const params = [];
1413
+ if (options?.status) params.push(`status=${options.status.join(",")}`);
1414
+ if (options?.limit) params.push(`limit=${options.limit}`);
1415
+ if (params.length) path += `?${params.join("&")}`;
1416
+ return this.http.get(path);
1417
+ }
1418
+ /** Acknowledge an intake result (mark as consumed). */
1419
+ async acknowledge(itemId) {
1420
+ await this.http.post(`/api/v1/intake/acknowledge/${enc3(itemId)}`, {});
1421
+ }
1422
+ /** Acknowledge all pending items for an agent. */
1423
+ async acknowledgeAll(agentId) {
1424
+ return this.http.post(
1425
+ `/api/v1/intake/acknowledge-all/${enc3(agentId)}`,
1426
+ {}
1427
+ );
1428
+ }
1429
+ /** Get intake processing stats for an agent. */
1430
+ async stats(agentId) {
1431
+ return this.http.get(`/api/v1/intake/stats/${enc3(agentId)}`);
1432
+ }
1433
+ };
1434
+ var DEFAULT_RETRY = {
1435
+ maxRetries: 3,
1436
+ baseDelayMs: 500,
1437
+ maxDelayMs: 1e4
1438
+ };
1439
+ var SubCortexClient = class {
1440
+ /** Assertion operations (low-level knowledge primitives) */
1441
+ assertions;
1442
+ /** Relationship operations */
1443
+ relationships;
1444
+ /** Agent identity & configuration */
1445
+ agents;
1446
+ /** Agent memory (semantic wrapper over assertions) */
1447
+ memory;
1448
+ /** Thalamus cognitive intake pipeline */
1449
+ intake;
1450
+ /** User rapport building operations */
1451
+ users;
1452
+ /** Emotional signals — record, query, and resolve */
1453
+ signals;
1454
+ http;
1455
+ constructor(options) {
1456
+ if (!options.apiKey && !options.token) {
1457
+ console.warn("[SubCortex] No apiKey or token provided \u2014 requests will be unauthenticated.");
1458
+ }
1459
+ this.http = new HttpTransport({
1460
+ baseUrl: options.endpoint,
1461
+ tenantId: options.tenantId,
1462
+ apiKey: options.apiKey,
1463
+ token: options.token,
1464
+ retry: { ...DEFAULT_RETRY, ...options.retry },
1465
+ timeoutMs: options.timeoutMs ?? 3e4,
1466
+ fetchImpl: options.fetch ?? globalThis.fetch,
1467
+ headers: options.headers ?? {},
1468
+ signal: options.signal
1469
+ });
1470
+ this.assertions = new AssertionsNamespace(this.http, options.tenantId);
1471
+ this.relationships = new RelationshipsNamespace(this.http, options.tenantId);
1472
+ this.agents = new AgentsNamespace(this.http, options.tenantId);
1473
+ this.memory = new MemoryNamespace(this.http, options.tenantId);
1474
+ this.intake = new IntakeNamespace(this.http, options.tenantId);
1475
+ this.users = new UsersNamespace(this.http, options.tenantId);
1476
+ this.signals = new SignalsNamespace(this.http, options.tenantId);
1477
+ }
1478
+ /** Check SubCortex server health. */
1479
+ async health() {
1480
+ return this.http.get("/health");
1481
+ }
1482
+ };
1483
+ function enc3(s) {
1484
+ return encodeURIComponent(s);
1485
+ }
1486
+
1487
+ // src/context.ts
1488
+ var CONTEXT_SCHEMA_VERSION = "1.0";
1489
+ function formatContext(user, options = {}) {
1490
+ const format = options.format ?? "xml";
1491
+ switch (format) {
1492
+ case "xml":
1493
+ return toContextXml(user, options);
1494
+ case "json":
1495
+ return JSON.stringify(user, null, 2);
1496
+ case "summary":
1497
+ return user.summary;
1498
+ }
1499
+ }
1500
+ function toContextXml(user, options = {}) {
1501
+ const {
1502
+ includeMemories = true,
1503
+ includeRelationships = true,
1504
+ includeReminders = true,
1505
+ includeConflicts = true,
1506
+ includeContexts = true,
1507
+ includeSignals = true,
1508
+ minConfidence = 0
1509
+ } = options;
1510
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
1511
+ const lines = [];
1512
+ const signalsByAbout = /* @__PURE__ */ new Map();
1513
+ const unattachedSignals = [];
1514
+ if (includeSignals && user.signals) {
1515
+ for (const sig of user.signals) {
1516
+ if (sig.aboutSubject) {
1517
+ const existing = signalsByAbout.get(sig.aboutSubject) || [];
1518
+ existing.push(sig);
1519
+ signalsByAbout.set(sig.aboutSubject, existing);
1520
+ } else {
1521
+ unattachedSignals.push(sig);
1522
+ }
1523
+ }
1524
+ }
1525
+ lines.push(`<subcortex_context version="${CONTEXT_SCHEMA_VERSION}" subject="${esc(user.subject)}" known="${user.isKnown}" ts="${ts}">`);
1526
+ if (includeConflicts && user.conflicts.length > 0) {
1527
+ lines.push(` <conflicts count="${user.conflicts.length}" priority="critical">`);
1528
+ for (const conflict of user.conflicts) {
1529
+ lines.push(` <conflict id="${esc(conflict.id)}">${esc(conflict.hint)}</conflict>`);
1530
+ }
1531
+ lines.push(` </conflicts>`);
1532
+ }
1533
+ if (includeReminders && user.reminders.length > 0) {
1534
+ lines.push(` <reminders count="${user.reminders.length}" priority="high">`);
1535
+ for (const reminder of user.reminders) {
1536
+ lines.push(` <reminder id="${esc(reminder.id)}" confidence="${fmtConf(reminder.confidence)}">${esc(String(reminder.value))}</reminder>`);
1537
+ }
1538
+ lines.push(` </reminders>`);
1539
+ }
1540
+ if (includeContexts && user.contexts.length > 0) {
1541
+ lines.push(` <active_contexts count="${user.contexts.length}">`);
1542
+ for (const ctx of user.contexts) {
1543
+ const ctxSignals = findSignalsForFact(ctx, signalsByAbout);
1544
+ if (ctxSignals.length > 0) {
1545
+ lines.push(` <context predicate="${esc(ctx.predicate)}" confidence="${fmtConf(ctx.confidence)}">`);
1546
+ lines.push(` ${esc(String(ctx.value))}`);
1547
+ for (const sig of ctxSignals) {
1548
+ lines.push(` ${renderSignal(sig)}`);
1549
+ }
1550
+ lines.push(` </context>`);
1551
+ } else {
1552
+ lines.push(` <context predicate="${esc(ctx.predicate)}" confidence="${fmtConf(ctx.confidence)}">${esc(String(ctx.value))}</context>`);
1553
+ }
1554
+ }
1555
+ lines.push(` </active_contexts>`);
1556
+ }
1557
+ if (user.name) {
1558
+ const trajectoryAttr = user.rapportTrajectory ? ` rapport_trajectory="${user.rapportTrajectory}"` : "";
1559
+ lines.push(` <identity name="${esc(String(user.name))}" subject="${esc(user.subject)}"${trajectoryAttr}>`);
1560
+ const identityPredicates = /* @__PURE__ */ new Set(["name", "full_name", "role", "title", "department", "team", "email", "start_date", "communication_style"]);
1561
+ const identityFacts = user.memories.filter((m) => identityPredicates.has(m.predicate) && m.confidence >= minConfidence);
1562
+ for (const fact of identityFacts) {
1563
+ const factSignals = findSignalsForFact(fact, signalsByAbout);
1564
+ if (factSignals.length > 0) {
1565
+ lines.push(` <fact predicate="${esc(fact.predicate)}" confidence="${fmtConf(fact.confidence)}">`);
1566
+ lines.push(` ${esc(String(fact.value))}`);
1567
+ for (const sig of factSignals) {
1568
+ lines.push(` ${renderSignal(sig)}`);
1569
+ }
1570
+ lines.push(` </fact>`);
1571
+ } else {
1572
+ lines.push(` <fact predicate="${esc(fact.predicate)}" confidence="${fmtConf(fact.confidence)}">${esc(String(fact.value))}</fact>`);
1573
+ }
1574
+ }
1575
+ for (const sig of unattachedSignals) {
1576
+ lines.push(` ${renderSignal(sig)}`);
1577
+ }
1578
+ lines.push(` </identity>`);
1579
+ }
1580
+ if (includeMemories) {
1581
+ const identityPredicates = /* @__PURE__ */ new Set(["name", "full_name", "role", "title", "department", "team", "email", "start_date", "communication_style"]);
1582
+ const knowledge = user.memories.filter(
1583
+ (m) => !identityPredicates.has(m.predicate) && m.confidence >= minConfidence
1584
+ );
1585
+ if (knowledge.length > 0) {
1586
+ lines.push(` <knowledge count="${knowledge.length}">`);
1587
+ for (const mem of knowledge) {
1588
+ const memSignals = findSignalsForFact(mem, signalsByAbout);
1589
+ if (memSignals.length > 0) {
1590
+ lines.push(` <fact predicate="${esc(mem.predicate)}" confidence="${fmtConf(mem.confidence)}">`);
1591
+ lines.push(` ${esc(String(mem.value))}`);
1592
+ for (const sig of memSignals) {
1593
+ lines.push(` ${renderSignal(sig)}`);
1594
+ }
1595
+ lines.push(` </fact>`);
1596
+ } else {
1597
+ lines.push(` <fact predicate="${esc(mem.predicate)}" confidence="${fmtConf(mem.confidence)}">${esc(String(mem.value))}</fact>`);
1598
+ }
1599
+ }
1600
+ lines.push(` </knowledge>`);
1601
+ }
1602
+ }
1603
+ if (includeRelationships && user.connectedPeople.length > 0) {
1604
+ lines.push(` <relationships count="${user.connectedPeople.length}">`);
1605
+ for (const person of user.connectedPeople) {
1606
+ const personSignals = signalsByAbout.get(person.subject) || [];
1607
+ const hasContent = person.facts.length > 0 || personSignals.length > 0;
1608
+ if (!hasContent) {
1609
+ lines.push(` <person name="${esc(person.name)}" relationship="${esc(person.relationship)}" />`);
1610
+ } else {
1611
+ lines.push(` <person name="${esc(person.name)}" relationship="${esc(person.relationship)}">`);
1612
+ for (const fact of person.facts) {
1613
+ lines.push(` <fact predicate="${esc(fact.predicate)}">${esc(String(fact.value))}</fact>`);
1614
+ }
1615
+ for (const sig of personSignals) {
1616
+ lines.push(` ${renderSignal(sig)}`);
1617
+ }
1618
+ lines.push(` </person>`);
1619
+ }
1620
+ }
1621
+ lines.push(` </relationships>`);
1622
+ }
1623
+ lines.push(`</subcortex_context>`);
1624
+ return lines.join("\n");
1625
+ }
1626
+ function renderSignal(sig) {
1627
+ const aboutAttr = sig.aboutSubject ? ` about="${esc(sig.aboutSubject)}"` : "";
1628
+ return `<signal type="${esc(sig.type)}" intensity="${fmtConf(sig.intensity)}" decayed="${fmtConf(sig.decayedIntensity)}" age_hours="${sig.ageHours}"${aboutAttr}>${esc(sig.content)}</signal>`;
1629
+ }
1630
+ function findSignalsForFact(fact, signalsByAbout) {
1631
+ const results = [];
1632
+ for (const [aboutSubject, signals] of signalsByAbout) {
1633
+ if (aboutSubject.includes(fact.predicate) || aboutSubject.includes(String(fact.value).toLowerCase().replace(/\s+/g, "-").slice(0, 30))) {
1634
+ results.push(...signals);
1635
+ }
1636
+ }
1637
+ return results;
1638
+ }
1639
+ function fmtConf(n) {
1640
+ return n.toFixed(2);
1641
+ }
1642
+ function esc(s) {
1643
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1644
+ }
1645
+ // Annotate the CommonJS export names for ESM import in node:
1646
+ 0 && (module.exports = {
1647
+ AgentsNamespace,
1648
+ AssertionsNamespace,
1649
+ CONTEXT_SCHEMA_VERSION,
1650
+ ConfidenceLevel,
1651
+ ConfidenceScores,
1652
+ EntityPredicate,
1653
+ EntityRelationship,
1654
+ EventPredicate,
1655
+ IdentityPredicate,
1656
+ IntakeNamespace,
1657
+ MULTI_VALUE_PREDICATES,
1658
+ MemoryNamespace,
1659
+ MemoryPredicate,
1660
+ NEGATIVE_SIGNALS,
1661
+ OrgRelationship,
1662
+ POSITIVE_SIGNALS,
1663
+ Predicates,
1664
+ RELATIONSHIP_LABELS,
1665
+ REVERSE_RELATIONSHIPS,
1666
+ RapportPredicate,
1667
+ RelationshipTypes,
1668
+ RelationshipsNamespace,
1669
+ SIGNAL_DECAY_CONFIG,
1670
+ SYSTEM_SIGNAL_TYPES,
1671
+ SignalsNamespace,
1672
+ SubCortexAuthenticationError,
1673
+ SubCortexAuthorizationError,
1674
+ SubCortexClient,
1675
+ SubCortexConflictError,
1676
+ SubCortexError,
1677
+ SubCortexNetworkError,
1678
+ SubCortexNotFoundError,
1679
+ SubCortexRateLimitError,
1680
+ SubCortexServerError,
1681
+ SubCortexTimeoutError,
1682
+ SubCortexValidationError,
1683
+ SubjectPrefix,
1684
+ UsersNamespace,
1685
+ WorkPredicate,
1686
+ confidenceToScore,
1687
+ formatContext,
1688
+ getDecayHalfLife,
1689
+ isValidSignalType,
1690
+ scoreToConfidence,
1691
+ subject,
1692
+ toContextXml
1693
+ });
1694
+ //# sourceMappingURL=index.cjs.map