@m6d/cortex-server 1.5.0 → 1.6.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/README.md CHANGED
@@ -57,7 +57,7 @@ export default {
57
57
 
58
58
  `cortex.serve()` is async — it runs database migrations on startup.
59
59
 
60
- Each key in `agents` becomes a route prefix (e.g. `assistant` → `/agents/assistant/...`). Agents can define per-agent `systemPrompt`, `tools`, `backendFetch`, `loadSessionData`, and lifecycle hooks (`onToolCall`, `onStreamFinish`).
60
+ Each key in `agents` becomes a route prefix (e.g. `assistant` → `/agents/assistant/...`). Agents can define per-agent `systemPrompt`, `tools`, `backendFetch`, `loadSessionData`, `resolveRequestContext`, and lifecycle hooks (`onToolCall`, `onStreamFinish`).
61
61
 
62
62
  ## Requirements
63
63
 
@@ -1,4 +1,4 @@
1
1
  import type { ResolvedCortexAgentConfig } from "../config.ts";
2
2
  import type { Thread } from "../types.ts";
3
- export declare function stream(messages: unknown[], thread: Thread, userId: string, token: string, config: ResolvedCortexAgentConfig): Promise<Response>;
3
+ export declare function stream(messages: unknown[], thread: Thread, userId: string, token: string, requestContext: Record<string, unknown>, config: ResolvedCortexAgentConfig): Promise<Response>;
4
4
  export declare function generateTitle(threadId: string, prompt: string, userId: string, config: ResolvedCortexAgentConfig): Promise<void>;
@@ -1,9 +1,9 @@
1
1
  import type { ResolvedContext } from "../graph/resolver.ts";
2
- import type { ResolvedCortexAgentConfig } from "../config.ts";
2
+ import type { PromptContext, ResolvedCortexAgentConfig } from "../config.ts";
3
3
  import type { Thread } from "../types.ts";
4
4
  /**
5
5
  * Resolves session data for the thread, loading from the configured
6
6
  * session loader if not already cached on the thread.
7
7
  */
8
8
  export declare function resolveSession(config: ResolvedCortexAgentConfig, thread: Thread, token: string): Promise<Record<string, unknown> | null>;
9
- export declare function buildSystemPrompt(config: ResolvedCortexAgentConfig, resolved: ResolvedContext | null, session: Record<string, unknown> | null): Promise<string>;
9
+ export declare function buildSystemPrompt(config: ResolvedCortexAgentConfig, resolved: ResolvedContext | null, promptContext: PromptContext): Promise<string>;
@@ -10,6 +10,10 @@ export type KnowledgeConfig = {
10
10
  };
11
11
  domains?: Record<string, DomainDef>;
12
12
  };
13
+ export type PromptContext = {
14
+ session: Record<string, unknown> | null;
15
+ requestContext: Record<string, unknown>;
16
+ };
13
17
  export type DatabaseConfig = {
14
18
  type: "mssql";
15
19
  connectionString: string;
@@ -23,7 +27,7 @@ export type StorageConfig = {
23
27
  bucketName?: string;
24
28
  };
25
29
  export type CortexAgentDefinition = {
26
- systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
30
+ systemPrompt: string | ((context: PromptContext) => string | Promise<string>);
27
31
  tools?: ToolSet;
28
32
  backendFetch?: {
29
33
  baseUrl: string;
@@ -35,6 +39,7 @@ export type CortexAgentDefinition = {
35
39
  interceptor?: RequestInterceptorOptions;
36
40
  };
37
41
  loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
42
+ resolveRequestContext?: (request: Request) => Record<string, unknown> | Promise<Record<string, unknown>>;
38
43
  onToolCall?: (toolCall: {
39
44
  toolName: string;
40
45
  toolCallId: string;
@@ -92,7 +97,7 @@ export type ResolvedCortexAgentConfig = {
92
97
  url: string;
93
98
  apiKey: string;
94
99
  };
95
- systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
100
+ systemPrompt: string | ((context: PromptContext) => string | Promise<string>);
96
101
  tools?: ToolSet;
97
102
  backendFetch?: {
98
103
  baseUrl: string;
@@ -104,6 +109,7 @@ export type ResolvedCortexAgentConfig = {
104
109
  interceptor?: RequestInterceptorOptions;
105
110
  };
106
111
  loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
112
+ resolveRequestContext?: (request: Request) => Record<string, unknown> | Promise<Record<string, unknown>>;
107
113
  onToolCall?: (toolCall: {
108
114
  toolName: string;
109
115
  toolCallId: string;
@@ -1,4 +1,4 @@
1
- export type { CortexConfig, CortexAgentDefinition, KnowledgeConfig, DatabaseConfig, StorageConfig, } from "./config";
1
+ export type { CortexConfig, CortexAgentDefinition, KnowledgeConfig, DatabaseConfig, StorageConfig, PromptContext, } from "./config";
2
2
  export type { ContextConfig, ThreadContextMeta } from "./ai/context/types";
3
3
  export type { Thread, AppEnv } from "./types";
4
4
  export type { CortexInstance } from "./factory";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m6d/cortex-server",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Reusable AI agent chat server library for Hono + Bun",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/ai/index.ts CHANGED
@@ -36,6 +36,7 @@ export async function stream(
36
36
  thread: Thread,
37
37
  userId: string,
38
38
  token: string,
39
+ requestContext: Record<string, unknown>,
39
40
  config: ResolvedCortexAgentConfig,
40
41
  ) {
41
42
  const abortController = new AbortController();
@@ -111,7 +112,10 @@ export async function stream(
111
112
  ...config.tools,
112
113
  } as ToolSet;
113
114
 
114
- const systemPrompt = await buildSystemPrompt(config, resolved, session);
115
+ const systemPrompt = await buildSystemPrompt(config, resolved, {
116
+ session,
117
+ requestContext,
118
+ });
115
119
 
116
120
  // The context builder reserved a static token budget for the system prompt + tools.
117
121
  // Now that we have the actual values, verify the reserve was sufficient and trim
package/src/ai/prompt.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedContext } from "../graph/resolver.ts";
2
- import type { ResolvedCortexAgentConfig } from "../config.ts";
2
+ import type { PromptContext, ResolvedCortexAgentConfig } from "../config.ts";
3
3
  import type { Thread } from "../types.ts";
4
4
 
5
5
  /**
@@ -26,12 +26,12 @@ export async function resolveSession(
26
26
  export async function buildSystemPrompt(
27
27
  config: ResolvedCortexAgentConfig,
28
28
  resolved: ResolvedContext | null,
29
- session: Record<string, unknown> | null,
29
+ promptContext: PromptContext,
30
30
  ) {
31
31
  // Resolve the consumer's base system prompt
32
32
  let basePrompt: string;
33
33
  if (typeof config.systemPrompt === "function") {
34
- basePrompt = await config.systemPrompt(session);
34
+ basePrompt = await config.systemPrompt(promptContext);
35
35
  } else {
36
36
  basePrompt = config.systemPrompt;
37
37
  }
package/src/config.ts CHANGED
@@ -10,6 +10,11 @@ export type KnowledgeConfig = {
10
10
  domains?: Record<string, DomainDef>;
11
11
  };
12
12
 
13
+ export type PromptContext = {
14
+ session: Record<string, unknown> | null;
15
+ requestContext: Record<string, unknown>;
16
+ };
17
+
13
18
  export type DatabaseConfig = {
14
19
  type: "mssql";
15
20
  connectionString: string;
@@ -25,7 +30,7 @@ export type StorageConfig = {
25
30
  };
26
31
 
27
32
  export type CortexAgentDefinition = {
28
- systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
33
+ systemPrompt: string | ((context: PromptContext) => string | Promise<string>);
29
34
  tools?: ToolSet;
30
35
  backendFetch?: {
31
36
  baseUrl: string;
@@ -38,6 +43,9 @@ export type CortexAgentDefinition = {
38
43
  interceptor?: RequestInterceptorOptions;
39
44
  };
40
45
  loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
46
+ resolveRequestContext?: (
47
+ request: Request,
48
+ ) => Record<string, unknown> | Promise<Record<string, unknown>>;
41
49
  onToolCall?: (toolCall: {
42
50
  toolName: string;
43
51
  toolCallId: string;
@@ -93,7 +101,7 @@ export type ResolvedCortexAgentConfig = {
93
101
  url: string;
94
102
  apiKey: string;
95
103
  };
96
- systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
104
+ systemPrompt: string | ((context: PromptContext) => string | Promise<string>);
97
105
  tools?: ToolSet;
98
106
  backendFetch?: {
99
107
  baseUrl: string;
@@ -106,6 +114,9 @@ export type ResolvedCortexAgentConfig = {
106
114
  interceptor?: RequestInterceptorOptions;
107
115
  };
108
116
  loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
117
+ resolveRequestContext?: (
118
+ request: Request,
119
+ ) => Record<string, unknown> | Promise<Record<string, unknown>>;
109
120
  onToolCall?: (toolCall: {
110
121
  toolName: string;
111
122
  toolCallId: string;
package/src/factory.ts CHANGED
@@ -95,6 +95,7 @@ export function createCortex(config: CortexConfig) {
95
95
  tools: agentDef.tools,
96
96
  backendFetch: agentDef.backendFetch,
97
97
  loadSessionData: agentDef.loadSessionData,
98
+ resolveRequestContext: agentDef.resolveRequestContext,
98
99
  onToolCall: agentDef.onToolCall,
99
100
  onStreamFinish: agentDef.onStreamFinish,
100
101
  context: resolvedContext,
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export type {
5
5
  KnowledgeConfig,
6
6
  DatabaseConfig,
7
7
  StorageConfig,
8
+ PromptContext,
8
9
  } from "./config";
9
10
 
10
11
  export type { ContextConfig, ThreadContextMeta } from "./ai/context/types";
@@ -27,6 +27,9 @@ export function createChatRoutes() {
27
27
  const agentId = c.get("agentId");
28
28
  const { id: userId, token } = c.get("user");
29
29
  const { messages, id: threadId } = c.req.valid("json");
30
+ const requestContext = config.resolveRequestContext
31
+ ? await config.resolveRequestContext(c.req.raw)
32
+ : {};
30
33
 
31
34
  const thread = await config.db.threads.getById(userId, threadId);
32
35
 
@@ -34,7 +37,7 @@ export function createChatRoutes() {
34
37
  throw new HTTPException(404, { message: "Not found" });
35
38
  }
36
39
 
37
- return stream(messages, thread, userId, token, config);
40
+ return stream(messages, thread, userId, token, requestContext, config);
38
41
  },
39
42
  );
40
43