@siduri-x/brain 2.0.7 → 2.0.10

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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BrainOrgan, BrainContext, ResponsePlan } from '@siduri-x/core';
1
+ import { BrainOrgan, BrainContext, ResponsePlan, RetrievalPlan, RequestContext } from '@siduri-x/core';
2
2
  export interface OpenAICompatibleBrainConfig {
3
3
  apiKey?: string;
4
4
  apiKeyEnv?: string;
@@ -24,6 +24,10 @@ export declare class OpenAICompatibleBrain implements BrainOrgan {
24
24
  protected resolvedApiKey: string;
25
25
  constructor(config: OpenAICompatibleBrainConfig);
26
26
  generatePlan(context: BrainContext): Promise<ResponsePlan>;
27
+ planRetrieval(text: string, context?: RequestContext, recentHistory?: {
28
+ role: string;
29
+ content: string;
30
+ }[]): Promise<RetrievalPlan>;
27
31
  }
28
32
  export declare class OpenRouterBrain extends OpenAICompatibleBrain {
29
33
  constructor(config: OpenRouterBrainConfig);
package/dist/index.js CHANGED
@@ -312,6 +312,75 @@ class OpenAICompatibleBrain {
312
312
  clearTimeout(overallTimer);
313
313
  }
314
314
  }
315
+ async planRetrieval(text, context, recentHistory) {
316
+ const defaultResponse = {
317
+ shouldQueryKnowledge: undefined,
318
+ knowledgeQueries: [],
319
+ shouldQueryMemory: undefined,
320
+ memoryQueries: [],
321
+ };
322
+ if (!text || !text.trim() || !this.resolvedApiKey) {
323
+ return defaultResponse;
324
+ }
325
+ const controller = new AbortController();
326
+ const timer = setTimeout(() => controller.abort(), 6000);
327
+ let historyContext = '';
328
+ if (recentHistory && recentHistory.length > 0) {
329
+ const recentTurns = recentHistory
330
+ .slice(-4)
331
+ .map((m) => `${m.role}: ${m.content}`)
332
+ .join('\n');
333
+ historyContext = `\n\nRecent conversation context:\n${recentTurns}\nIf the current user message uses pronouns (she, he, it, they) or refers to previously mentioned entities (e.g. 'where is she coming to banner?'), resolve the pronoun to the specific entity name from context (e.g. ['Sandrone banner']).`;
334
+ }
335
+ try {
336
+ const response = await fetch(`${this.config.baseUrl.replace(/\/+$/, '')}/chat/completions`, {
337
+ method: "POST",
338
+ headers: {
339
+ "Authorization": `Bearer ${this.resolvedApiKey || this.config.apiKey}`,
340
+ "Content-Type": "application/json",
341
+ },
342
+ body: JSON.stringify({
343
+ model: this.config.model,
344
+ messages: [
345
+ {
346
+ role: "system",
347
+ content: `You are an agentic query planning module for a companion. Analyze the user message.\nDecide:\n1. shouldQueryKnowledge (boolean): does this message ask about external world facts, domain documentation, fictional/real universe entities, lore, timelines, or specifications? (False if greeting, self-identity of the companion, or personal small talk).\n2. knowledgeQueries (string[]): 1-2 focused keyword queries of the specific entity, topic, or subject name (e.g. 'Sandrone', or with topic qualifier like 'Sandrone banner'; strictly remove companion mentions, greetings, and conversational fluff like 'who is', 'tell me about', 'what is').\n3. shouldQueryMemory (boolean): does this message ask about user identity, past conversation history, or shared facts?\n4. memoryQueries (string[]): 1-2 focused query keywords for episodic memory.${historyContext}\nRespond strictly in JSON format: {"shouldQueryKnowledge": boolean, "knowledgeQueries": string[], "shouldQueryMemory": boolean, "memoryQueries": string[]}`,
348
+ },
349
+ {
350
+ role: "user",
351
+ content: text,
352
+ },
353
+ ],
354
+ response_format: { type: "json_object" },
355
+ max_tokens: 150,
356
+ temperature: 0,
357
+ }),
358
+ signal: controller.signal,
359
+ });
360
+ if (!response.ok) {
361
+ return defaultResponse;
362
+ }
363
+ const data = await response.json();
364
+ const content = data?.choices?.[0]?.message?.content;
365
+ if (content) {
366
+ const parsed = JSON.parse(content);
367
+ return {
368
+ shouldQueryKnowledge: typeof parsed.shouldQueryKnowledge === 'boolean' ? parsed.shouldQueryKnowledge : undefined,
369
+ knowledgeQueries: Array.isArray(parsed.knowledgeQueries) ? parsed.knowledgeQueries.filter((q) => typeof q === 'string' && q.trim()) : [],
370
+ shouldQueryMemory: typeof parsed.shouldQueryMemory === 'boolean' ? parsed.shouldQueryMemory : undefined,
371
+ memoryQueries: Array.isArray(parsed.memoryQueries) ? parsed.memoryQueries.filter((q) => typeof q === 'string' && q.trim()) : [],
372
+ reasoning: parsed.reasoning,
373
+ };
374
+ }
375
+ }
376
+ catch {
377
+ // Fallback to heuristic extraction
378
+ }
379
+ finally {
380
+ clearTimeout(timer);
381
+ }
382
+ return defaultResponse;
383
+ }
315
384
  }
316
385
  exports.OpenAICompatibleBrain = OpenAICompatibleBrain;
317
386
  class OpenRouterBrain extends OpenAICompatibleBrain {
@@ -171,7 +171,7 @@ describe('PromptAssembler', () => {
171
171
  contextPrompt: "Memories: none",
172
172
  recentMessages: []
173
173
  });
174
- expect(res.messages[0].content).toContain("[SIDURI TRUSTED SYSTEM CONTEXT]");
174
+ expect(res.messages[0].content).toContain("[COMPANION TRUSTED SYSTEM CONTEXT]");
175
175
  expect(res.messages[0].content).toContain("I am Ganyu");
176
176
  expect(res.messages[1].content).toContain("[CONTEXTUAL AWARENESS]");
177
177
  expect(res.messages[1].content).toContain("Memories: none");
@@ -13,7 +13,7 @@ describe('T3 Prompt Section Matrix Contract Suite', () => {
13
13
  const ctx = assembler.contextPrompt(context);
14
14
  const assembled = assembler.assemble(context);
15
15
  // Assertions of required sections
16
- expect(sys).toContain('[SIDURI TRUSTED SYSTEM CONTEXT]');
16
+ expect(sys).toContain('[COMPANION TRUSTED SYSTEM CONTEXT]');
17
17
  expect(sys).toContain('[IDENTITY NUCLEUS]');
18
18
  expect(sys).toContain('You are NeutralCompanion.');
19
19
  expect(sys).toContain('[IMMUTABLE RUNTIME RULES]');
@@ -31,7 +31,7 @@ describe('T3 Prompt Section Matrix Contract Suite', () => {
31
31
  };
32
32
  const sys = assembler.systemPrompt(context);
33
33
  const ctx = assembler.contextPrompt(context);
34
- const idxSysCtx = sys.indexOf('[SIDURI TRUSTED SYSTEM CONTEXT]');
34
+ const idxSysCtx = sys.indexOf('[COMPANION TRUSTED SYSTEM CONTEXT]');
35
35
  const idxIdentity = sys.indexOf('[IDENTITY NUCLEUS]');
36
36
  const idxRules = sys.indexOf('[IMMUTABLE RUNTIME RULES]');
37
37
  expect(idxSysCtx).toBeLessThan(idxIdentity);
package/dist/prompt.js CHANGED
@@ -4,7 +4,7 @@ exports.PromptAssembler = void 0;
4
4
  class PromptAssembler {
5
5
  systemPrompt(context) {
6
6
  const parts = [
7
- "[SIDURI TRUSTED SYSTEM CONTEXT]",
7
+ "[COMPANION TRUSTED SYSTEM CONTEXT]",
8
8
  "[IDENTITY NUCLEUS]",
9
9
  context.systemPrompt, // Core neutral identity config and compiled active self
10
10
  "[IMMUTABLE RUNTIME RULES]",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@siduri-x/brain",
3
3
  "organType": "brain",
4
- "version": "2.0.5",
4
+ "version": "2.0.10",
5
5
  "displayName": "Brain (Cognition & Planning)",
6
6
  "description": "Provider-neutral LLM reasoning, response planning, and proposal generation",
7
7
  "entrypoint": "./dist/index.js",
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@siduri-x/brain",
3
- "version": "2.0.7",
3
+ "version": "2.0.10",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
7
7
  "zod": "^4.6.2",
8
- "@siduri-x/core": "2.0.11"
8
+ "@siduri-x/core": "2.0.13"
9
9
  },
10
10
  "devDependencies": {
11
11
  "@types/jest": "^30.0.0",