@sidurijs/core 1.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 (103) hide show
  1. package/dist/action-executor.d.ts +12 -0
  2. package/dist/action-executor.js +54 -0
  3. package/dist/action-policy.d.ts +79 -0
  4. package/dist/action-policy.js +439 -0
  5. package/dist/action-policy.test.d.ts +1 -0
  6. package/dist/action-policy.test.js +363 -0
  7. package/dist/action.d.ts +72 -0
  8. package/dist/action.js +2 -0
  9. package/dist/adversarial.test.d.ts +1 -0
  10. package/dist/adversarial.test.js +491 -0
  11. package/dist/architecture-boundary.test.d.ts +1 -0
  12. package/dist/architecture-boundary.test.js +108 -0
  13. package/dist/capability.d.ts +78 -0
  14. package/dist/capability.js +168 -0
  15. package/dist/capability.test.d.ts +1 -0
  16. package/dist/capability.test.js +311 -0
  17. package/dist/chat-contract.d.ts +94 -0
  18. package/dist/chat-contract.js +104 -0
  19. package/dist/cognition-planner.d.ts +15 -0
  20. package/dist/cognition-planner.js +23 -0
  21. package/dist/container.d.ts +74 -0
  22. package/dist/container.js +81 -0
  23. package/dist/context-retriever.d.ts +33 -0
  24. package/dist/context-retriever.js +260 -0
  25. package/dist/context.d.ts +46 -0
  26. package/dist/context.js +85 -0
  27. package/dist/context.test.d.ts +1 -0
  28. package/dist/context.test.js +76 -0
  29. package/dist/conversational-teach.test.d.ts +1 -0
  30. package/dist/conversational-teach.test.js +941 -0
  31. package/dist/database.d.ts +1 -0
  32. package/dist/database.js +17 -0
  33. package/dist/dispatcher.d.ts +14 -0
  34. package/dist/dispatcher.js +40 -0
  35. package/dist/dispatcher.test.d.ts +1 -0
  36. package/dist/dispatcher.test.js +58 -0
  37. package/dist/ear-types.d.ts +33 -0
  38. package/dist/ear-types.js +2 -0
  39. package/dist/evidence.d.ts +76 -0
  40. package/dist/evidence.js +27 -0
  41. package/dist/evidence.test.d.ts +1 -0
  42. package/dist/evidence.test.js +75 -0
  43. package/dist/experience-emitter.d.ts +21 -0
  44. package/dist/experience-emitter.js +47 -0
  45. package/dist/experience.d.ts +55 -0
  46. package/dist/experience.js +74 -0
  47. package/dist/experience.test.d.ts +1 -0
  48. package/dist/experience.test.js +55 -0
  49. package/dist/gating.d.ts +45 -0
  50. package/dist/gating.js +185 -0
  51. package/dist/gating.test.d.ts +1 -0
  52. package/dist/gating.test.js +186 -0
  53. package/dist/index.d.ts +367 -0
  54. package/dist/index.js +56 -0
  55. package/dist/input-normalizer.d.ts +14 -0
  56. package/dist/input-normalizer.js +76 -0
  57. package/dist/input-normalizer.test.d.ts +1 -0
  58. package/dist/input-normalizer.test.js +48 -0
  59. package/dist/intent-classifier.d.ts +37 -0
  60. package/dist/intent-classifier.js +150 -0
  61. package/dist/intent-classifier.test.d.ts +1 -0
  62. package/dist/intent-classifier.test.js +118 -0
  63. package/dist/memory-settler.d.ts +49 -0
  64. package/dist/memory-settler.js +161 -0
  65. package/dist/mouth-types.d.ts +90 -0
  66. package/dist/mouth-types.js +2 -0
  67. package/dist/perception-cycle.test.d.ts +1 -0
  68. package/dist/perception-cycle.test.js +301 -0
  69. package/dist/perception-pipeline.d.ts +77 -0
  70. package/dist/perception-pipeline.js +304 -0
  71. package/dist/perception-pipeline.test.d.ts +1 -0
  72. package/dist/perception-pipeline.test.js +65 -0
  73. package/dist/prompt-compiler.d.ts +26 -0
  74. package/dist/prompt-compiler.js +81 -0
  75. package/dist/prompt-compiler.test.d.ts +1 -0
  76. package/dist/prompt-compiler.test.js +90 -0
  77. package/dist/proposals.d.ts +33 -0
  78. package/dist/proposals.js +2 -0
  79. package/dist/response-envelope.d.ts +30 -0
  80. package/dist/response-envelope.js +90 -0
  81. package/dist/runtime-facades.test.d.ts +1 -0
  82. package/dist/runtime-facades.test.js +95 -0
  83. package/dist/runtime.d.ts +116 -0
  84. package/dist/runtime.js +778 -0
  85. package/dist/schema-validator.d.ts +9 -0
  86. package/dist/schema-validator.js +107 -0
  87. package/dist/schema-validator.test.d.ts +1 -0
  88. package/dist/schema-validator.test.js +124 -0
  89. package/dist/session-history.d.ts +20 -0
  90. package/dist/session-history.js +55 -0
  91. package/dist/session-history.test.d.ts +1 -0
  92. package/dist/session-history.test.js +38 -0
  93. package/dist/siduri-db.d.ts +235 -0
  94. package/dist/siduri-db.js +1405 -0
  95. package/dist/siduri-db.test.d.ts +1 -0
  96. package/dist/siduri-db.test.js +1021 -0
  97. package/dist/sqlite-action-store.d.ts +21 -0
  98. package/dist/sqlite-action-store.js +281 -0
  99. package/dist/sqlite-action-store.test.d.ts +1 -0
  100. package/dist/sqlite-action-store.test.js +261 -0
  101. package/dist/teaching.d.ts +14 -0
  102. package/dist/teaching.js +14 -0
  103. package/package.json +43 -0
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dispatchCompanionChat = dispatchCompanionChat;
4
+ /**
5
+ * Canonical helper to dispatch a chat request to a SiduriRuntime instance.
6
+ * Guarantees a 1:1 identical response structure for localweb (apps/api) and standalone CLI.
7
+ */
8
+ async function dispatchCompanionChat(runtime, payload) {
9
+ const runner = 'runtime' in runtime && typeof runtime.handleUserMessage !== 'function'
10
+ ? runtime.runtime
11
+ : runtime;
12
+ const userMessage = payload.message || payload.text || '';
13
+ const history = Array.isArray(payload.history) ? payload.history : [];
14
+ let roleOrContext;
15
+ if (payload.context) {
16
+ roleOrContext = payload.context;
17
+ }
18
+ else if (payload.role) {
19
+ roleOrContext = payload.role;
20
+ }
21
+ else {
22
+ roleOrContext = 'OWNER';
23
+ }
24
+ const requestedSubtitleLang = payload.subtitleLanguage || payload.subtitle_language;
25
+ const runtimeResult = (payload.medium || payload.signal || requestedSubtitleLang)
26
+ ? await runner.handleUserMessage(userMessage, roleOrContext, history, payload.medium, payload.signal, requestedSubtitleLang)
27
+ : await runner.handleUserMessage(userMessage, roleOrContext, history);
28
+ const delivery = runtimeResult?.delivery;
29
+ // Normalize response plan
30
+ const speech = delivery?.displayText ||
31
+ delivery?.text ||
32
+ runtimeResult?.response?.subtitle_ja ||
33
+ runtimeResult?.response?.subtitle_en ||
34
+ '';
35
+ const audioUrl = delivery?.audioUrl || runtimeResult?.response?.audio_url;
36
+ // Extract avatar expression if any event was generated or provided by Mouth delivery
37
+ let expression = delivery?.expression || 'neutral';
38
+ if (expression === 'neutral') {
39
+ const events = runtimeResult?.metadata?.events || [];
40
+ const avatarEvent = events.find((e) => e.kind === 'avatar' || e.kind === 'body');
41
+ if (avatarEvent && avatarEvent.expression) {
42
+ expression = avatarEvent.expression;
43
+ }
44
+ }
45
+ const resolvedSubtitles = {
46
+ ...(runtimeResult?.response?.subtitles || {}),
47
+ ...(delivery?.subtitles || {}),
48
+ };
49
+ const subtitle = (requestedSubtitleLang && resolvedSubtitles[requestedSubtitleLang]) ||
50
+ runtimeResult?.response?.subtitle ||
51
+ (requestedSubtitleLang === 'ja' ? (delivery?.subtitles?.ja ?? runtimeResult?.response?.subtitle_ja) : undefined) ||
52
+ (requestedSubtitleLang === 'en' ? (delivery?.subtitles?.en ?? runtimeResult?.response?.subtitle_en) : undefined);
53
+ if (subtitle && requestedSubtitleLang) {
54
+ resolvedSubtitles[requestedSubtitleLang] = subtitle;
55
+ }
56
+ const rawCitations = runtimeResult?.metadata?.citations ?? runtimeResult?.response?.citations ?? [];
57
+ const normalizedCitations = (Array.isArray(rawCitations) ? rawCitations : []).map((c) => ({
58
+ evidence_id: c.evidence_id || c.evidenceId,
59
+ evidenceId: c.evidenceId || c.evidence_id,
60
+ source_id: c.source_id || c.sourceId,
61
+ sourceId: c.sourceId || c.source_id,
62
+ document_id: c.document_id || c.documentId,
63
+ documentId: c.documentId || c.document_id,
64
+ chunk_id: c.chunk_id || c.chunkId,
65
+ chunkId: c.chunkId || c.chunk_id,
66
+ revision: c.revision,
67
+ provenance: c.provenance || c.sourceId || c.source_id,
68
+ preview: c.preview,
69
+ locator: c.locator,
70
+ }));
71
+ // Ensure both spoken_ja and subtitle_en are accessible alongside speech_id and evidence_ids
72
+ const responsePlan = {
73
+ speech_id: runtimeResult?.response?.speech_id,
74
+ audio_url: audioUrl,
75
+ subtitle_ja: delivery?.subtitles?.ja ?? runtimeResult?.response?.subtitle_ja ?? speech,
76
+ subtitle_en: delivery?.subtitles?.en ?? runtimeResult?.response?.subtitle_en ?? speech,
77
+ spoken_ja: delivery?.subtitles?.spoken ?? runtimeResult?.response?.spoken_ja ?? runtimeResult?.response?.subtitle_ja ?? speech,
78
+ subtitle,
79
+ subtitle_language: requestedSubtitleLang,
80
+ subtitles: resolvedSubtitles,
81
+ evidence_ids: runtimeResult?.metadata?.evidence_ids ?? runtimeResult?.response?.evidence_ids ?? (normalizedCitations.map((c) => c.evidence_id).filter(Boolean)),
82
+ citations: normalizedCitations,
83
+ gate: runtimeResult?.response?.gate ?? runtimeResult?.metadata?.gate,
84
+ };
85
+ const metadata = {
86
+ ...(runtimeResult?.metadata || {}),
87
+ citations: normalizedCitations,
88
+ };
89
+ delete metadata.internal_monologue;
90
+ delete metadata.internalMonologue;
91
+ return {
92
+ status: runtimeResult?.status || 'APPROVED',
93
+ response_id: runtimeResult?.response_id,
94
+ correlation_id: runtimeResult?.correlation_id,
95
+ response: responsePlan,
96
+ delivery,
97
+ metadata,
98
+ // Convenience fields for legacy/simple consumers
99
+ reply: speech,
100
+ text: speech,
101
+ audioUrl,
102
+ expression,
103
+ };
104
+ }
@@ -0,0 +1,15 @@
1
+ import { BrainOrgan, Message, ResponsePlan, MemoryScope } from './index';
2
+ export interface CognitionPlanningParams {
3
+ companionName: string;
4
+ brain?: BrainOrgan;
5
+ systemPrompt: string;
6
+ contextPrompt: string;
7
+ recentMessages: Message[];
8
+ recipient?: MemoryScope;
9
+ perceivedText: string;
10
+ }
11
+ /**
12
+ * Invokes BrainOrgan to generate a structured ResponsePlan, or provides
13
+ * a graceful baseline response if Brain is absent or in headless passive mode.
14
+ */
15
+ export declare function generateCognitionPlan(params: CognitionPlanningParams): Promise<ResponsePlan>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateCognitionPlan = generateCognitionPlan;
4
+ /**
5
+ * Invokes BrainOrgan to generate a structured ResponsePlan, or provides
6
+ * a graceful baseline response if Brain is absent or in headless passive mode.
7
+ */
8
+ async function generateCognitionPlan(params) {
9
+ const { companionName, brain, systemPrompt, contextPrompt, recentMessages, recipient, perceivedText, } = params;
10
+ if (brain && typeof brain.generatePlan === 'function') {
11
+ return brain.generatePlan({
12
+ systemPrompt,
13
+ contextPrompt,
14
+ recentMessages,
15
+ recipient,
16
+ });
17
+ }
18
+ // Graceful baseline response when Brain is not configured or in headless passive mode
19
+ return {
20
+ speech: `[Companion] Acknowledged: ${perceivedText}`,
21
+ language: 'en',
22
+ };
23
+ }
@@ -0,0 +1,74 @@
1
+ import { BrainOrgan, MemoryOrgan, VoiceOrgan, KnowledgeOrgan, VisionOrgan, BehaviorOrgan, BodyOrgan, HandsOrgan, EarOrgan, ObservationOrgan, MouthOrgan, SelfRepository, EKnowledgeOrgan, OrganConfig, ActionStore, ActionPolicyEngine, ResponseGatingEngine, ExperienceDispatcher, ExperienceAdapter } from './index';
2
+ import { SessionHistoryManager } from './session-history';
3
+ import { SiduriRuntime } from './runtime';
4
+ export interface SiduriRuntimeConfig {
5
+ name: string;
6
+ brain?: OrganConfig | Record<string, unknown>;
7
+ voice?: OrganConfig | Record<string, unknown>;
8
+ memory?: OrganConfig | Record<string, unknown>;
9
+ knowledge?: OrganConfig | Record<string, unknown>;
10
+ behavior?: OrganConfig | Record<string, unknown>;
11
+ body?: OrganConfig | Record<string, unknown>;
12
+ vision?: OrganConfig | Record<string, unknown>;
13
+ hands?: OrganConfig | Record<string, unknown>;
14
+ ear?: OrganConfig | Record<string, unknown>;
15
+ observation?: OrganConfig | Record<string, unknown>;
16
+ mouth?: OrganConfig | Record<string, unknown>;
17
+ self?: OrganConfig | Record<string, unknown>;
18
+ externalKnowledge?: OrganConfig | Record<string, unknown>;
19
+ actionPolicy?: Record<string, unknown>;
20
+ actionStore?: 'in-memory' | 'sqlite' | {
21
+ type: 'sqlite' | 'in-memory';
22
+ dbPath?: string;
23
+ };
24
+ actionStorePath?: string;
25
+ [key: string]: unknown;
26
+ }
27
+ export interface RuntimeOrgans {
28
+ brain?: BrainOrgan;
29
+ memory?: MemoryOrgan;
30
+ voice?: VoiceOrgan | ExperienceAdapter;
31
+ knowledge?: KnowledgeOrgan;
32
+ vision?: VisionOrgan;
33
+ behavior?: BehaviorOrgan;
34
+ body?: BodyOrgan | ExperienceAdapter;
35
+ hands?: HandsOrgan;
36
+ ear?: EarOrgan;
37
+ observation?: ObservationOrgan;
38
+ mouth?: MouthOrgan;
39
+ self?: SelfRepository;
40
+ externalKnowledge?: EKnowledgeOrgan;
41
+ actionStore?: ActionStore;
42
+ actionPolicy?: ActionPolicyEngine;
43
+ }
44
+ /**
45
+ * CompanionContainer manages the lifecycle, discovery, wiring, and dependency injection
46
+ * of organs and infrastructure for a companion instance.
47
+ */
48
+ export declare class CompanionContainer {
49
+ readonly id: string;
50
+ readonly config: SiduriRuntimeConfig;
51
+ readonly organs: RuntimeOrgans;
52
+ readonly gating: ResponseGatingEngine;
53
+ readonly actionPolicy: ActionPolicyEngine;
54
+ readonly dispatcher: ExperienceDispatcher;
55
+ readonly sessionHistory: SessionHistoryManager;
56
+ private _runtime?;
57
+ constructor(id: string, config: SiduriRuntimeConfig, organs?: RuntimeOrgans);
58
+ get brain(): BrainOrgan | undefined;
59
+ get memory(): MemoryOrgan | undefined;
60
+ get voice(): ExperienceAdapter | VoiceOrgan | undefined;
61
+ get knowledge(): KnowledgeOrgan | undefined;
62
+ get vision(): VisionOrgan | undefined;
63
+ get behavior(): BehaviorOrgan | undefined;
64
+ get body(): ExperienceAdapter | BodyOrgan | undefined;
65
+ get hands(): HandsOrgan | undefined;
66
+ get ear(): EarOrgan | undefined;
67
+ get observation(): ObservationOrgan | undefined;
68
+ set observation(org: ObservationOrgan | undefined);
69
+ get mouth(): MouthOrgan | undefined;
70
+ get self(): SelfRepository | undefined;
71
+ get externalKnowledge(): EKnowledgeOrgan | undefined;
72
+ initialize(): Promise<void>;
73
+ get runtime(): SiduriRuntime;
74
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CompanionContainer = void 0;
4
+ const index_1 = require("./index");
5
+ const session_history_1 = require("./session-history");
6
+ const runtime_1 = require("./runtime");
7
+ /**
8
+ * CompanionContainer manages the lifecycle, discovery, wiring, and dependency injection
9
+ * of organs and infrastructure for a companion instance.
10
+ */
11
+ class CompanionContainer {
12
+ id;
13
+ config;
14
+ organs;
15
+ gating;
16
+ actionPolicy;
17
+ dispatcher;
18
+ sessionHistory;
19
+ _runtime;
20
+ constructor(id, config, organs = {}) {
21
+ this.id = id;
22
+ this.config = config;
23
+ this.organs = organs;
24
+ this.gating = new index_1.ResponseGatingEngine();
25
+ let actionStore = organs.actionStore;
26
+ if (!actionStore) {
27
+ const storeOpt = config.actionStore;
28
+ const storePath = config.actionStorePath || (typeof storeOpt === 'object' ? storeOpt.dbPath : undefined);
29
+ if (storeOpt === 'sqlite' || (typeof storeOpt === 'object' && storeOpt.type === 'sqlite') || storePath) {
30
+ actionStore = new index_1.SqliteActionStore({ dbPath: storePath });
31
+ }
32
+ }
33
+ this.actionPolicy = organs.actionPolicy || new index_1.ActionPolicyEngine({
34
+ store: actionStore,
35
+ });
36
+ this.dispatcher = new index_1.ExperienceDispatcher();
37
+ if (this.organs.voice && typeof this.organs.voice.handleEvent === 'function') {
38
+ this.dispatcher.registerAdapter(this.organs.voice);
39
+ }
40
+ if (this.organs.body && typeof this.organs.body.handleEvent === 'function') {
41
+ this.dispatcher.registerAdapter(this.organs.body);
42
+ }
43
+ if (this.organs.mouth && typeof this.organs.mouth.handleEvent === 'function') {
44
+ this.dispatcher.registerAdapter(this.organs.mouth);
45
+ }
46
+ this.sessionHistory = new session_history_1.SessionHistoryManager();
47
+ }
48
+ // Direct organ accessors
49
+ get brain() { return this.organs.brain; }
50
+ get memory() { return this.organs.memory; }
51
+ get voice() { return this.organs.voice; }
52
+ get knowledge() { return this.organs.knowledge; }
53
+ get vision() { return this.organs.vision; }
54
+ get behavior() { return this.organs.behavior; }
55
+ get body() { return this.organs.body; }
56
+ get hands() { return this.organs.hands; }
57
+ get ear() { return this.organs.ear; }
58
+ get observation() { return this.organs.observation; }
59
+ set observation(org) { this.organs.observation = org; }
60
+ get mouth() { return this.organs.mouth; }
61
+ get self() { return this.organs.self; }
62
+ get externalKnowledge() { return this.organs.externalKnowledge; }
63
+ async initialize() {
64
+ if (this.organs.memory && typeof this.organs.memory.initialize === 'function') {
65
+ await this.organs.memory.initialize(this.id);
66
+ }
67
+ if (this.organs.hands && typeof this.organs.hands.listTools === 'function') {
68
+ const tools = await this.organs.hands.listTools();
69
+ for (const tool of tools) {
70
+ this.actionPolicy.registerToolDefinition(tool);
71
+ }
72
+ }
73
+ }
74
+ get runtime() {
75
+ if (!this._runtime) {
76
+ this._runtime = new runtime_1.SiduriRuntime(this.id, this.config, this);
77
+ }
78
+ return this._runtime;
79
+ }
80
+ }
81
+ exports.CompanionContainer = CompanionContainer;
@@ -0,0 +1,33 @@
1
+ import { KnowledgeOrgan, MemoryOrgan, KnowledgeItem, Claim, BehaviorDirective, EvidenceRecord, ResponseCitation, RequestContext, SelfRepository, LifeDatabase, EpisodicMemoryStore, EKnowledgeOrgan } from './index';
2
+ export interface ContextRetrievalParams {
3
+ companionId: string;
4
+ perceivedText: string;
5
+ requestContext: RequestContext;
6
+ role: 'OWNER' | 'VIEWER' | 'OPERATOR';
7
+ isContextObject: boolean;
8
+ shouldQueryKnowledge: boolean;
9
+ knowledgeQueries?: string[];
10
+ memoryQueries?: string[];
11
+ isSelfIdentityRequest?: boolean;
12
+ knowledge?: KnowledgeOrgan | LifeDatabase;
13
+ memory?: MemoryOrgan | EpisodicMemoryStore;
14
+ self?: SelfRepository;
15
+ externalKnowledge?: EKnowledgeOrgan | KnowledgeOrgan;
16
+ }
17
+ export interface RetrievedContext {
18
+ knowledgeData: KnowledgeItem[];
19
+ memoryData: Claim[];
20
+ activeDirectives: BehaviorDirective[];
21
+ subsystemDiagnostics: Record<string, string>;
22
+ collectedEvidence: EvidenceRecord[];
23
+ citations: ResponseCitation[];
24
+ lifeContext?: string[];
25
+ selfIdentity?: any;
26
+ selfRelationship?: any;
27
+ personality?: any;
28
+ }
29
+ /**
30
+ * Concurrently queries Self, Knowledge (Life DB), External Knowledge, and Memory
31
+ * in a single parallel pass with graceful degradation.
32
+ */
33
+ export declare function retrieveRuntimeContext(params: ContextRetrievalParams): Promise<RetrievedContext>;
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.retrieveRuntimeContext = retrieveRuntimeContext;
4
+ const intent_classifier_1 = require("./intent-classifier");
5
+ /**
6
+ * Concurrently queries Self, Knowledge (Life DB), External Knowledge, and Memory
7
+ * in a single parallel pass with graceful degradation.
8
+ */
9
+ async function retrieveRuntimeContext(params) {
10
+ const { companionId, perceivedText, requestContext, role, isContextObject, shouldQueryKnowledge, knowledgeQueries, memoryQueries, isSelfIdentityRequest, knowledge, memory, self, externalKnowledge, } = params;
11
+ const queryOptions = isContextObject
12
+ ? {
13
+ limit: 5,
14
+ }
15
+ : role;
16
+ const subsystemDiagnostics = {};
17
+ // 1. Resolve External Knowledge organ (either explicitly passed or from legacy knowledge with .search)
18
+ const extKnowledge = externalKnowledge || (knowledge && typeof knowledge.search === 'function' ? knowledge : undefined);
19
+ // Formulate queries: combine AI/cognitive queries, entity keywords, and cleaned query variants
20
+ const keywordQueries = (0, intent_classifier_1.extractSearchKeywords)(perceivedText, companionId, requestContext?.history);
21
+ const aiQueries = (knowledgeQueries || []).filter(Boolean);
22
+ // Clean AI queries of conversational filler if present (e.g. 'what is the lore on Sandrone' -> 'Sandrone')
23
+ const cleanedAiQueries = aiQueries.map((q) => q.replace(/^(?:what(?:\s+is|\s+are)?|who(?:\s+is|\s+are)?|tell(?:\s+me)?(?:\s+about)?|search(?:\s+for)?|information(?:\s+on|\s+about)?|details(?:\s+on|\s+about)?|lore(?:\s+for|\s+on|\s+about)?)\s+/gi, '').trim()).filter((q) => q.length > 0);
24
+ const queryCandidateSet = new Set();
25
+ for (const q of [...keywordQueries, ...aiQueries, ...cleanedAiQueries]) {
26
+ if (q && q.trim()) {
27
+ queryCandidateSet.add(q.trim());
28
+ }
29
+ }
30
+ if (queryCandidateSet.size === 0 && perceivedText && perceivedText.trim()) {
31
+ queryCandidateSet.add(perceivedText.trim());
32
+ }
33
+ const finalKnowledgeQueries = Array.from(queryCandidateSet);
34
+ const memoryQueryToRun = (memoryQueries && memoryQueries.length > 0 && memoryQueries[0])
35
+ ? memoryQueries[0]
36
+ : (0, intent_classifier_1.extractSearchKeywords)(perceivedText, companionId)[0] || perceivedText;
37
+ // 2. Query streams in parallel
38
+ const [knowledgeData, memoryData, selfOrMemoryDirectives, lifeContext, selfIdentity, selfRelationship, personality,] = await Promise.all([
39
+ // Stream A: External Cited Lore / Documentation
40
+ extKnowledge && shouldQueryKnowledge && typeof extKnowledge.search === 'function'
41
+ ? Promise.all(finalKnowledgeQueries.map((q) => extKnowledge.search(q).catch((e) => {
42
+ console.error(`[SiduriRuntime] Knowledge search failed for "${q}":`, e.message);
43
+ subsystemDiagnostics['knowledge'] = `UNAVAILABLE: ${e.message}`;
44
+ return [];
45
+ }))).then((resultsArray) => {
46
+ const merged = [];
47
+ const seen = new Set();
48
+ for (const list of resultsArray) {
49
+ if (!Array.isArray(list))
50
+ continue;
51
+ for (const item of list) {
52
+ const key = item.id || item.content || item.text || JSON.stringify(item.citations);
53
+ if (!seen.has(key)) {
54
+ seen.add(key);
55
+ merged.push(item);
56
+ }
57
+ }
58
+ }
59
+ return merged;
60
+ })
61
+ : Promise.resolve([]),
62
+ // Stream B: Episodic Memory / Verified Claims (SQLite FTS5 with Identity Fallback)
63
+ memory && typeof memory.searchClaims === 'function'
64
+ ? (async () => {
65
+ try {
66
+ // Support both (companionId, query, limit) and (query, options, limit)
67
+ let result = await memory.searchClaims(memoryQueryToRun, queryOptions, 5);
68
+ if ((!result || result.length === 0) && isSelfIdentityRequest) {
69
+ if (typeof memory.getApprovedClaims === 'function') {
70
+ const approved = await memory.getApprovedClaims(companionId, 10);
71
+ const identityClaims = approved.filter((c) => {
72
+ const pred = (c.predicate || '').toLowerCase();
73
+ const subj = (c.subject || '').toLowerCase();
74
+ return (['name', 'role', 'stated_relationship', 'relationship', 'origin', 'created_by', 'preferred_address', 'title', 'identity', 'creator', 'archetype', 'affiliation'].includes(pred) ||
75
+ subj.startsWith('companion') ||
76
+ subj === 'self' ||
77
+ subj === 'siduri' ||
78
+ subj.startsWith('actor:'));
79
+ });
80
+ result = identityClaims.length > 0 ? identityClaims.slice(0, 5) : approved.slice(0, 5);
81
+ }
82
+ else if (typeof memory.getClaims === 'function') {
83
+ const all = await memory.getClaims(50);
84
+ const approved = all.filter((c) => (c.status || '').toLowerCase() === 'approved');
85
+ result = approved.slice(0, 5);
86
+ }
87
+ }
88
+ return result || [];
89
+ }
90
+ catch (e) {
91
+ console.error('[SiduriRuntime] Memory search failed:', e.message);
92
+ subsystemDiagnostics['memory_claims'] = `UNAVAILABLE: ${e.message}`;
93
+ return [];
94
+ }
95
+ })()
96
+ : Promise.resolve([]),
97
+ // Stream C: Active Directives from Self (or fallback Memory)
98
+ self && typeof self.getActiveDirectives === 'function'
99
+ ? self.getActiveDirectives(companionId).catch((e) => {
100
+ console.error('[SiduriRuntime] Self directives failed:', e.message);
101
+ subsystemDiagnostics['self_directives'] = `UNAVAILABLE: ${e.message}`;
102
+ return [];
103
+ })
104
+ : memory && typeof memory.getDirectives === 'function'
105
+ ? memory.getDirectives().catch((e) => {
106
+ console.error('[SiduriRuntime] Memory directives failed:', e.message);
107
+ subsystemDiagnostics['memory_directives'] = `UNAVAILABLE: ${e.message}`;
108
+ return [];
109
+ })
110
+ : Promise.resolve([]),
111
+ // Stream D: Sovereign Life DB Context (Finances, Inventory, Schedule, Preferences)
112
+ knowledge && typeof knowledge.queryContext === 'function'
113
+ ? knowledge.queryContext(companionId, perceivedText).catch((e) => {
114
+ console.error('[SiduriRuntime] Life DB context failed:', e.message);
115
+ subsystemDiagnostics['life_db'] = `UNAVAILABLE: ${e.message}`;
116
+ return [];
117
+ })
118
+ : Promise.resolve([]),
119
+ // Stream E: Self Identity
120
+ self && typeof self.getIdentity === 'function'
121
+ ? self.getIdentity(companionId).catch((e) => {
122
+ console.error('[SiduriRuntime] Self identity failed:', e.message);
123
+ return undefined;
124
+ })
125
+ : Promise.resolve(undefined),
126
+ // Stream F: Self Relationship toward interacting actor
127
+ self && typeof self.getRelationship === 'function' && requestContext.actor?.actorId
128
+ ? self.getRelationship(companionId, requestContext.actor.actorId).catch((e) => {
129
+ console.error('[SiduriRuntime] Self relationship failed:', e.message);
130
+ return null;
131
+ })
132
+ : Promise.resolve(null),
133
+ // Stream G: Self Personality
134
+ self && typeof self.getPersonality === 'function'
135
+ ? self.getPersonality(companionId).catch(() => undefined)
136
+ : Promise.resolve(undefined),
137
+ ]);
138
+ const activeDirectives = (selfOrMemoryDirectives || []);
139
+ // Build evidence records from retrieved context streams
140
+ const collectedEvidence = [];
141
+ const citations = [];
142
+ // Stream A: External Knowledge
143
+ if (knowledgeData.length > 0) {
144
+ for (const k of knowledgeData) {
145
+ const previewText = k.content || k.text || k.summary || k.preview || '';
146
+ if (k.evidenceRecord) {
147
+ const nativeRecord = {
148
+ ...k.evidenceRecord,
149
+ };
150
+ collectedEvidence.push(nativeRecord);
151
+ citations.push({
152
+ evidenceId: nativeRecord.evidenceId,
153
+ provenance: k.provenance || nativeRecord.sourceId || 'knowledge',
154
+ sourceId: nativeRecord.sourceId,
155
+ revision: nativeRecord.revision,
156
+ documentId: nativeRecord.documentId || k.citations?.[0]?.documentId,
157
+ chunkId: nativeRecord.chunkId || k.citations?.[0]?.chunkId,
158
+ locator: nativeRecord.locator || k.citations?.[0]?.locator,
159
+ preview: previewText.slice(0, 300),
160
+ });
161
+ }
162
+ else {
163
+ // Synthesize fallback evidence record with provenance
164
+ const evId = `ev-know-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
165
+ const sourceId = k.provenance || 'configured-knowledge';
166
+ collectedEvidence.push({
167
+ evidenceId: evId,
168
+ sourceId,
169
+ revision: k.revision,
170
+ origin: 'knowledge',
171
+ trust: 'configured',
172
+ sensitivity: 'public',
173
+ companionId,
174
+ correlationId: requestContext.conversation.correlationId,
175
+ createdAt: new Date().toISOString(),
176
+ });
177
+ citations.push({
178
+ evidenceId: evId,
179
+ provenance: sourceId,
180
+ sourceId,
181
+ revision: k.revision,
182
+ documentId: k.citations?.[0]?.documentId,
183
+ chunkId: k.citations?.[0]?.chunkId,
184
+ locator: k.citations?.[0]?.locator,
185
+ preview: previewText.slice(0, 300),
186
+ });
187
+ }
188
+ }
189
+ }
190
+ // Stream B: Episodic Memory Claims
191
+ if (memoryData.length > 0) {
192
+ for (const m of memoryData) {
193
+ const claimId = m.claim_id || m.id || `claim-${Date.now()}`;
194
+ const sourceId = m.provenance || 'sqlite-memory';
195
+ const evId = `ev-mem-${claimId}`;
196
+ const claimPreview = m.content || `${m.subject || 'user'} ${m.predicate || 'claims'}: ${m.value || ''}`;
197
+ collectedEvidence.push({
198
+ evidenceId: evId,
199
+ sourceId,
200
+ documentId: claimId,
201
+ chunkId: `${m.subject || 'user'}:${m.predicate || 'claim'}`,
202
+ origin: 'memory',
203
+ trust: 'configured',
204
+ sensitivity: 'private',
205
+ companionId,
206
+ correlationId: requestContext.conversation.correlationId,
207
+ createdAt: new Date().toISOString(),
208
+ });
209
+ citations.push({
210
+ evidenceId: evId,
211
+ provenance: 'memory',
212
+ sourceId,
213
+ documentId: claimId,
214
+ chunkId: `${m.subject || 'user'}.${m.predicate || 'claim'}`,
215
+ locator: `claim:${claimId}`,
216
+ preview: claimPreview.slice(0, 300),
217
+ });
218
+ }
219
+ }
220
+ // Stream D: Life DB Context Items
221
+ if (lifeContext && lifeContext.length > 0) {
222
+ for (let i = 0; i < lifeContext.length; i++) {
223
+ const item = lifeContext[i];
224
+ const evId = `ev-life-${Date.now()}-${i}`;
225
+ const sourceId = 'sqlite-lifedb';
226
+ const itemPreview = item.title || item.name || item.summary || JSON.stringify(item);
227
+ collectedEvidence.push({
228
+ evidenceId: evId,
229
+ sourceId,
230
+ documentId: `item-${i}`,
231
+ origin: 'life',
232
+ trust: 'configured',
233
+ sensitivity: 'private',
234
+ companionId,
235
+ correlationId: requestContext.conversation.correlationId,
236
+ createdAt: new Date().toISOString(),
237
+ });
238
+ citations.push({
239
+ evidenceId: evId,
240
+ provenance: 'life',
241
+ sourceId,
242
+ documentId: `item-${i}`,
243
+ locator: `lifedb:item:${i}`,
244
+ preview: itemPreview.slice(0, 300),
245
+ });
246
+ }
247
+ }
248
+ return {
249
+ knowledgeData,
250
+ memoryData,
251
+ activeDirectives,
252
+ subsystemDiagnostics,
253
+ collectedEvidence,
254
+ citations,
255
+ lifeContext,
256
+ selfIdentity,
257
+ selfRelationship,
258
+ personality,
259
+ };
260
+ }
@@ -0,0 +1,46 @@
1
+ export interface ActorContext {
2
+ actorId: string;
3
+ sessionId: string;
4
+ authenticated?: boolean;
5
+ capabilities?: string[];
6
+ [key: string]: unknown;
7
+ }
8
+ export interface ConversationContext {
9
+ correlationId: string;
10
+ sessionId?: string;
11
+ channel?: string;
12
+ [key: string]: unknown;
13
+ }
14
+ export type SubjectKind = 'actor' | 'companion' | 'configured';
15
+ export type InteractionMode = 'casual' | 'teach' | 'hybrid';
16
+ export interface SubjectRef {
17
+ subjectId: string;
18
+ kind: SubjectKind;
19
+ ownerActorId?: string;
20
+ }
21
+ export interface RequestContext {
22
+ companionId: string;
23
+ actor: ActorContext;
24
+ conversation: ConversationContext;
25
+ source?: 'local' | 'external' | string;
26
+ subject?: SubjectRef;
27
+ mode?: InteractionMode;
28
+ metadata?: Record<string, unknown>;
29
+ }
30
+ export type DiagnosticCode = 'legacy_role_removed' | 'anonymous_session_generated' | 'companion_default_mapped_for_bootstrap' | 'actor_scoped_subject_mapped' | 'role_escalation_attempt_suppressed' | 'capability_escalation_attempt_suppressed';
31
+ export type ContextErrorCode = 'MISSING_CONTEXT' | 'INVALID_CONTEXT' | 'FORBIDDEN_CONTEXT' | 'AMBIGUOUS_CONTEXT' | 'UNAUTHORIZED_CAPABILITY';
32
+ export interface ContextError {
33
+ code: ContextErrorCode;
34
+ message?: string;
35
+ fields?: string[];
36
+ field?: string;
37
+ correlationId?: string;
38
+ }
39
+ export interface RequestContextValidationResult {
40
+ accepted: boolean;
41
+ context?: RequestContext;
42
+ diagnostics?: DiagnosticCode[];
43
+ error?: ContextError;
44
+ }
45
+ export declare function isValidSubjectKind(kind: unknown): kind is SubjectKind;
46
+ export declare function validateRequestContext(context: unknown): RequestContextValidationResult;