@sidurijs/core 1.0.0 → 1.0.1

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/runtime.js CHANGED
@@ -31,7 +31,7 @@ class SiduriRuntime {
31
31
  // Direct organ accessors through container
32
32
  get organs() { return this.container.organs; }
33
33
  get brain() { return this.container.brain; }
34
- get memory() { return this.container.memory; }
34
+ get archive() { return this.container.archive; }
35
35
  get voice() { return this.container.voice; }
36
36
  get knowledge() { return this.container.knowledge; }
37
37
  get vision() { return this.container.vision; }
@@ -57,45 +57,9 @@ class SiduriRuntime {
57
57
  }
58
58
  async initialize() {
59
59
  await this.container.initialize();
60
- if (this.memory && this.self && typeof this.memory.approveClaim === 'function') {
61
- const originalApproveClaim = this.memory.approveClaim.bind(this.memory);
62
- this.memory.approveClaim = async (id) => {
63
- await originalApproveClaim(id);
64
- const targetCompId = this.id;
65
- const claims = typeof this.memory.getAllClaims === 'function'
66
- ? await this.memory.getAllClaims(500)
67
- : await this.memory.getClaims(500);
68
- let found = claims.find((c) => c.id === id);
69
- if (!found && typeof this.memory.getPendingClaims === 'function') {
70
- const pending = await this.memory.getPendingClaims(500);
71
- found = pending.find((c) => c.id === id);
72
- }
73
- if (found && this.self) {
74
- await promoteApprovedClaimToSelf(found, this.self, targetCompId);
75
- }
76
- if (found && this.container.knowledge) {
77
- await promoteApprovedClaimToKnowledge(found, this.container.knowledge, targetCompId);
78
- }
79
- };
80
- }
81
- // Sync any pre-existing approved claims to Knowledge / Life DB
82
- if (this.memory && this.container.knowledge) {
83
- try {
84
- const claims = typeof this.memory.getAllClaims === 'function'
85
- ? await this.memory.getAllClaims(500)
86
- : await this.memory.getClaims(500);
87
- const approvedClaims = (claims || []).filter((c) => (c.status || '').toLowerCase() === 'approved');
88
- for (const c of approvedClaims) {
89
- await promoteApprovedClaimToKnowledge(c, this.container.knowledge, this.id);
90
- }
91
- }
92
- catch {
93
- // non-blocking
94
- }
95
- }
96
60
  }
97
61
  get db() {
98
- return this.container.db || this.memory?.db || this.self?.db;
62
+ return this.container.db || this.self?.db || this.archive?.db;
99
63
  }
100
64
  log(level, subsystem, message, metadata) {
101
65
  if (this.db && typeof this.db.insertLog === 'function') {
@@ -129,86 +93,101 @@ class SiduriRuntime {
129
93
  this.container.sessionHistory.clear(sessionKey);
130
94
  }
131
95
  /**
132
- * Approves a memory proposal or behavior proposal and canonically promotes
133
- * Self-affecting mutations to SelfRepository.
96
+ * Approves a proposal using Direct Domain Routing (RFC VX-26-13):
97
+ * - Behavioral & relational directives route directly to SelfRepository.
98
+ * - Life state facts route directly to Knowledge / Life DB.
134
99
  */
135
100
  async approveProposal(proposalId, options) {
136
101
  const companionId = options?.companionId || this.id;
137
- // 1. Approve claim in memory if present
138
- if (this.memory && typeof this.memory.approveClaim === 'function') {
139
- await this.memory.approveClaim(proposalId);
102
+ // 1. Direct Domain Routing: If proposalId is a directive ID, route directly to Self
103
+ if (proposalId.startsWith('dir-') && this.self && typeof this.self.approveDirective === 'function') {
104
+ try {
105
+ const approved = await this.self.approveDirective(proposalId, companionId);
106
+ if (approved !== false) {
107
+ const identity = typeof this.self.getIdentity === 'function' ? await this.self.getIdentity(companionId) : null;
108
+ this.log('info', 'truth_gate', `Approved behavioral directive proposal '${proposalId}' directly in Self`, {
109
+ proposalId,
110
+ companionId,
111
+ target: 'self',
112
+ });
113
+ return { success: true, target: 'self', name: identity?.name };
114
+ }
115
+ }
116
+ catch {
117
+ // Fall through
118
+ }
140
119
  }
141
- // 2. Fetch claim
142
- let claim;
143
- if (this.memory) {
144
- const claims = typeof this.memory.getAllClaims === 'function'
145
- ? await this.memory.getAllClaims(500)
146
- : await this.memory.getClaims(500);
147
- claim = claims.find((c) => c.id === proposalId);
148
- if (!claim && typeof this.memory.getPendingClaims === 'function') {
149
- const pending = await this.memory.getPendingClaims(500);
120
+ // 2. If memory organ is present, support legacy claim approval
121
+ if (this.container.organs.memory) {
122
+ const memory = this.container.organs.memory;
123
+ if (typeof memory.approveClaim === 'function') {
124
+ await memory.approveClaim(proposalId);
125
+ }
126
+ let claim;
127
+ if (typeof memory.getAllClaims === 'function') {
128
+ const claims = await memory.getAllClaims(500);
129
+ claim = claims.find((c) => c.id === proposalId);
130
+ }
131
+ else if (typeof memory.getClaims === 'function') {
132
+ const claims = await memory.getClaims(500);
133
+ claim = claims.find((c) => c.id === proposalId);
134
+ }
135
+ if (!claim && typeof memory.getPendingClaims === 'function') {
136
+ const pending = await memory.getPendingClaims(500);
150
137
  claim = pending.find((c) => c.id === proposalId);
151
138
  }
152
- }
153
- // 3. Promote to Knowledge / Life DB if claim is Knowledge-affecting
154
- if (claim && this.container.knowledge) {
155
- const promotedToKnowledge = await promoteApprovedClaimToKnowledge(claim, this.container.knowledge, companionId);
156
- if (promotedToKnowledge) {
157
- this.log('info', 'truth_gate', `Approved and promoted claim '${proposalId}' to Knowledge / Life DB`, {
139
+ if (claim && this.container.knowledge) {
140
+ const promotedToKnowledge = await promoteApprovedClaimToKnowledge(claim, this.container.knowledge, companionId);
141
+ if (promotedToKnowledge) {
142
+ this.log('info', 'truth_gate', `Approved and promoted claim '${proposalId}' to Knowledge / Life DB`, {
143
+ proposalId,
144
+ companionId,
145
+ target: 'knowledge',
146
+ subject: claim.subject,
147
+ predicate: claim.predicate,
148
+ });
149
+ return { success: true, target: 'knowledge' };
150
+ }
151
+ }
152
+ if (claim && this.self) {
153
+ await promoteApprovedClaimToSelf(claim, this.self, companionId);
154
+ const identity = typeof this.self.getIdentity === 'function' ? await this.self.getIdentity(companionId) : null;
155
+ this.log('info', 'truth_gate', `Approved and promoted claim '${proposalId}' to Self`, {
158
156
  proposalId,
159
157
  companionId,
160
- target: 'knowledge',
158
+ target: 'self',
161
159
  subject: claim.subject,
162
160
  predicate: claim.predicate,
163
161
  });
164
- return { success: true, target: 'knowledge' };
162
+ return { success: true, target: 'self', name: identity?.name };
165
163
  }
166
164
  }
167
- // 4. Promote to SelfRepository if claim is Self-affecting
168
- if (claim && this.self) {
169
- await promoteApprovedClaimToSelf(claim, this.self, companionId);
170
- const identity = typeof this.self.getIdentity === 'function' ? await this.self.getIdentity(companionId) : null;
171
- this.log('info', 'truth_gate', `Approved and promoted claim '${proposalId}' to Self`, {
172
- proposalId,
173
- companionId,
174
- target: 'self',
175
- subject: claim.subject,
176
- predicate: claim.predicate,
177
- });
178
- return { success: true, target: 'self', name: identity?.name };
179
- }
180
- // 5. Also check if this proposal ID is a behavioral directive in Self
165
+ // 3. Direct Self directive check
181
166
  if (this.self && typeof this.self.approveDirective === 'function') {
182
167
  try {
183
- await this.self.approveDirective(proposalId, companionId);
184
- const identity = typeof this.self.getIdentity === 'function' ? await this.self.getIdentity(companionId) : null;
185
- this.log('info', 'truth_gate', `Approved behavioral directive proposal '${proposalId}'`, {
186
- proposalId,
187
- companionId,
188
- target: 'self',
189
- });
190
- return { success: true, target: 'self', name: identity?.name };
168
+ const approved = await this.self.approveDirective(proposalId, companionId);
169
+ if (approved !== false) {
170
+ const identity = typeof this.self.getIdentity === 'function' ? await this.self.getIdentity(companionId) : null;
171
+ this.log('info', 'truth_gate', `Approved behavioral directive proposal '${proposalId}' directly in Self`, {
172
+ proposalId,
173
+ companionId,
174
+ target: 'self',
175
+ });
176
+ return { success: true, target: 'self', name: identity?.name };
177
+ }
191
178
  }
192
179
  catch {
193
- // Not a pending directive or already active
180
+ // Not a pending directive
194
181
  }
195
182
  }
196
183
  const identity = this.self && typeof this.self.getIdentity === 'function' ? await this.self.getIdentity(companionId) : null;
197
- this.log('info', 'truth_gate', `Approved memory proposal '${proposalId}'`, {
198
- proposalId,
199
- companionId,
200
- target: 'memory',
201
- });
202
- return { success: true, target: 'memory', name: identity?.name };
184
+ return { success: true, target: 'self', name: identity?.name };
203
185
  }
204
186
  /**
205
- * Rejects a memory or behavior proposal.
187
+ * Rejects a proposal.
206
188
  */
207
189
  async rejectProposal(proposalId, options) {
208
190
  const companionId = options?.companionId || this.id;
209
- if (this.memory && typeof this.memory.rejectClaim === 'function') {
210
- await this.memory.rejectClaim(proposalId);
211
- }
212
191
  if (this.self && typeof this.self.rejectDirective === 'function') {
213
192
  try {
214
193
  await this.self.rejectDirective(proposalId, companionId);
@@ -217,6 +196,9 @@ class SiduriRuntime {
217
196
  // ignore
218
197
  }
219
198
  }
199
+ if (this.container.organs.memory && typeof this.container.organs.memory.rejectClaim === 'function') {
200
+ await this.container.organs.memory.rejectClaim(proposalId);
201
+ }
220
202
  this.log('info', 'truth_gate', `Rejected proposal '${proposalId}'`, {
221
203
  proposalId,
222
204
  companionId,
@@ -224,16 +206,13 @@ class SiduriRuntime {
224
206
  return { success: true };
225
207
  }
226
208
  /**
227
- * Approves a behavioral directive in Self and Memory.
209
+ * Approves a behavioral directive directly in Self.
228
210
  */
229
211
  async approveDirective(directiveId, options) {
230
212
  const companionId = options?.companionId || this.id;
231
213
  if (this.self && typeof this.self.approveDirective === 'function') {
232
214
  await this.self.approveDirective(directiveId, companionId);
233
215
  }
234
- if (this.memory && typeof this.memory.approveDirective === 'function') {
235
- await this.memory.approveDirective(directiveId, companionId);
236
- }
237
216
  // If directive pertains to companion name, ensure self identity reflects it
238
217
  if (this.self && typeof this.self.getActiveDirectives === 'function') {
239
218
  try {
@@ -269,16 +248,13 @@ class SiduriRuntime {
269
248
  return { success: true, name: identity?.name };
270
249
  }
271
250
  /**
272
- * Rejects a behavioral directive in Self and Memory.
251
+ * Rejects a behavioral directive in Self.
273
252
  */
274
253
  async rejectDirective(directiveId, options) {
275
254
  const companionId = options?.companionId || this.id;
276
255
  if (this.self && typeof this.self.rejectDirective === 'function') {
277
256
  await this.self.rejectDirective(directiveId, companionId);
278
257
  }
279
- if (this.memory && typeof this.memory.rejectDirective === 'function') {
280
- await this.memory.rejectDirective(directiveId, companionId);
281
- }
282
258
  this.log('info', 'truth_gate', `Rejected behavioral directive '${directiveId}'`, {
283
259
  directiveId,
284
260
  companionId,
@@ -286,16 +262,13 @@ class SiduriRuntime {
286
262
  return { success: true };
287
263
  }
288
264
  /**
289
- * Revokes a behavioral directive in Self and Memory.
265
+ * Revokes a behavioral directive in Self.
290
266
  */
291
267
  async revokeDirective(directiveId, options) {
292
268
  const companionId = options?.companionId || this.id;
293
269
  if (this.self && typeof this.self.revokeDirective === 'function') {
294
270
  await this.self.revokeDirective(directiveId, companionId);
295
271
  }
296
- if (this.memory && typeof this.memory.revokeDirective === 'function') {
297
- await this.memory.revokeDirective(directiveId, companionId);
298
- }
299
272
  return { success: true };
300
273
  }
301
274
  /**
@@ -333,7 +306,10 @@ class SiduriRuntime {
333
306
  }
334
307
  exports.SiduriRuntime = SiduriRuntime;
335
308
  /**
336
- * Canonically promotes an approved Claim into SelfRepository state.
309
+ * @deprecated RFC VX-26-13: Deconstructing Memory.
310
+ * Prefer Direct Domain Routing: behavioral directives, identity mutations, and relational
311
+ * stances should route directly to SelfRepository (`commitDirectives`, `setIdentity`, `updateRelationship`)
312
+ * rather than being staged in memory_claims and promoted downstream.
337
313
  */
338
314
  async function promoteApprovedClaimToSelf(claim, self, companionId) {
339
315
  const targetCompanionId = companionId || claim.companionId || 'default';
@@ -551,7 +527,9 @@ function isKnowledgeAffectingClaim(claim) {
551
527
  predicate === 'prefers');
552
528
  }
553
529
  /**
554
- * Canonically promotes an approved Claim into Knowledge / LifeDatabase state.
530
+ * @deprecated RFC VX-26-13: Deconstructing Memory.
531
+ * Prefer Direct Domain Routing: user life facts (entities, inventory, finances, schedule, preferences)
532
+ * should route directly to Knowledge / LifeDatabase rather than being staged as generic memory claims.
555
533
  */
556
534
  async function promoteApprovedClaimToKnowledge(claim, knowledge, companionId) {
557
535
  if (!knowledge)
@@ -1,13 +1,13 @@
1
- import { Message } from './index';
1
+ import { Message, DialogueHistory } from './index';
2
2
  export interface SessionHistoryOptions {
3
3
  maxSessions?: number;
4
4
  maxMessagesPerSession?: number;
5
5
  }
6
6
  /**
7
7
  * Manages conversation history scoped by session key to prevent cross-session
8
- * and cross-channel memory/conversation leakage.
8
+ * and cross-channel dialogue leakage. Implements the DialogueHistory primitive (RFC VX-26-13).
9
9
  */
10
- export declare class SessionHistoryManager {
10
+ export declare class SessionHistoryManager implements DialogueHistory {
11
11
  private readonly sessions;
12
12
  private readonly maxSessions;
13
13
  private readonly maxMessagesPerSession;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SessionHistoryManager = void 0;
4
4
  /**
5
5
  * Manages conversation history scoped by session key to prevent cross-session
6
- * and cross-channel memory/conversation leakage.
6
+ * and cross-channel dialogue leakage. Implements the DialogueHistory primitive (RFC VX-26-13).
7
7
  */
8
8
  class SessionHistoryManager {
9
9
  sessions = new Map();
@@ -108,13 +108,14 @@ export interface LifeTask {
108
108
  metadata?: Record<string, unknown>;
109
109
  updatedAt?: string;
110
110
  }
111
- export interface EpisodicEvent {
111
+ export interface ArchiveEvent {
112
112
  id: string;
113
113
  companionId: string;
114
- sourceType: 'chat_turn' | 'tool_result' | 'sensory';
114
+ sourceType: string;
115
115
  occurredAt: string;
116
116
  payload: Record<string, unknown>;
117
117
  }
118
+ export type EpisodicEvent = ArchiveEvent;
118
119
  export interface MemoryClaim {
119
120
  id: string;
120
121
  companionId: string;
@@ -188,32 +189,11 @@ export declare class SiduriDatabase {
188
189
  getTasks(companionId: string, status?: string): LifeTask[];
189
190
  upsertTask(task: LifeTask): void;
190
191
  deleteTask(id: string): boolean;
191
- recordEvent(event: EpisodicEvent): void;
192
- getRecentEvents(companionId: string, limit?: number): EpisodicEvent[];
193
- getEvent(id: string): EpisodicEvent | undefined;
194
- private rowToMemoryClaim;
195
- proposeClaim(claim: Omit<MemoryClaim, 'status' | 'confidence' | 'assertedAt'> & {
196
- confidence?: number;
197
- assertedAt?: string;
198
- supersedes?: string;
199
- sourceEventId?: string;
200
- status?: string;
201
- }): MemoryClaim;
202
- approveClaim(id: string, companionId?: string): void;
203
- /**
204
- * Canonically promotes a Claim into Self domain tables.
205
- */
206
- promoteClaimToSelf(claim: MemoryClaim | any): void;
207
- rejectClaim(id: string, companionId?: string): void;
208
- revokeClaim(id: string, companionId?: string): void;
209
- expireClaim(id: string, companionId?: string): void;
210
- markClaimSessionOnly(id: string, companionId?: string): void;
211
- searchClaims(companionId: string, query: string, limit?: number): MemoryClaim[];
212
- getPendingClaims(companionId: string, limit?: number): MemoryClaim[];
213
- getApprovedClaims(companionId: string, limit?: number): MemoryClaim[];
214
- getAllClaims(companionId?: string, limit?: number): MemoryClaim[];
215
- getClaim(id: string): MemoryClaim | undefined;
216
- resetMemory(companionId: string): void;
192
+ recordArchiveEvent(event: ArchiveEvent | EpisodicEvent): void;
193
+ getRecentArchiveEvents(companionId: string, limit?: number): ArchiveEvent[];
194
+ getArchiveEvent(id: string): ArchiveEvent | undefined;
195
+ searchArchiveEvents(companionId: string, query: string, limit?: number): ArchiveEvent[];
196
+ resetArchive(companionId: string): void;
217
197
  insertLog(entry: {
218
198
  id?: string;
219
199
  companionId?: string;