soulbridge 0.0.15 → 0.0.16

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.
@@ -20,6 +20,7 @@ export * from './storage/transcript.ts';
20
20
  import type { AffectSignal, ContextRequest, Correction, Memory, ContextResult, Emotion, LlmFn, MemoryType, ObserveResult, ReflectResult, ScoredMemory, Turn, Visibility } from './types.ts';
21
21
  import type { SoulStore } from './store.ts';
22
22
  import type { AffectAnalyzer } from './affect/port.ts';
23
+ export { gateDrafts } from './reflect.ts';
23
24
  export interface SoulOptions {
24
25
  store: SoulStore;
25
26
  soulId: string;
@@ -91,6 +92,21 @@ export declare class Soul {
91
92
  importance?: number;
92
93
  visibility?: Visibility;
93
94
  }): string;
95
+ /**
96
+ * Explicit write requested by a host or its model (RFC 0005). Unlike
97
+ * `remember`, it passes the same gates as `observe` and dedupes by content,
98
+ * so a tool cannot bypass shape/semantics or flood duplicates.
99
+ */
100
+ rememberExplicit(input: {
101
+ content: string;
102
+ type?: MemoryType;
103
+ importance?: number;
104
+ }): {
105
+ ok: boolean;
106
+ id?: string;
107
+ duplicate?: boolean;
108
+ reason?: string;
109
+ };
94
110
  /** Verb 4: session end. */
95
111
  reflect(turns: Turn[], options?: {
96
112
  updateEmotion?: boolean;
@@ -20,6 +20,7 @@ import { reflect, ruleExtract, nextEmotion } from './reflect.js';
20
20
  import { rank, tokenize } from './scoring.js';
21
21
  import { analyzeAffect, emptyAffect, lexiconAnalyzer } from './affect/analyze.js';
22
22
  import { gateDrafts, llmExtractTurn } from './reflect.js';
23
+ export { gateDrafts } from './reflect.js';
23
24
  export class Soul {
24
25
  store;
25
26
  soulId;
@@ -214,6 +215,33 @@ export class Soul {
214
215
  });
215
216
  return id;
216
217
  }
218
+ /**
219
+ * Explicit write requested by a host or its model (RFC 0005). Unlike
220
+ * `remember`, it passes the same gates as `observe` and dedupes by content,
221
+ * so a tool cannot bypass shape/semantics or flood duplicates.
222
+ */
223
+ rememberExplicit(input) {
224
+ const type = input.type ?? 'fact';
225
+ const importance = Math.min(10, Math.max(1, input.importance ?? 7));
226
+ const { accepted, rejected } = gateDrafts([{ type, content: input.content, importance }]);
227
+ if (accepted.length === 0) {
228
+ return { ok: false, reason: rejected[0]?.reason ?? 'rejected by write gates' };
229
+ }
230
+ const content = accepted[0].content;
231
+ const existing = this.store
232
+ .query({
233
+ soulId: this.soulId,
234
+ userId: this.userId,
235
+ status: ['active'],
236
+ includeExpired: true,
237
+ limit: 10_000,
238
+ })
239
+ .find((memory) => memory.content.trim() === content);
240
+ if (existing)
241
+ return { ok: true, id: existing.id, duplicate: true };
242
+ const id = this.remember(content, { type, importance });
243
+ return { ok: true, id };
244
+ }
217
245
  /** Verb 4: session end. */
218
246
  async reflect(turns, options = {}) {
219
247
  return reflect(this.store, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soulbridge",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "A personality layer for any agent: continuity, forgetting, and growth across tools.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",