@diegoaltoworks/chatter 0.20.0 → 0.22.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.
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Brain hook — the seam where a consumer replaces the completion call.
3
+ *
4
+ * Every chat surface (widget routes, OpenAI-compatible routes, channels,
5
+ * programmatic use) asks for an answer through `answerOnce`/`answerStream`
6
+ * instead of calling `completeOnce`/`completeStream` directly. When
7
+ * `ChatterConfig.answerFn` is set it produces the answer — an agent
8
+ * framework, a graph runtime, a remote service, anything — and Chatter keeps
9
+ * owning the rest: retrieval and prompt assembly upstream, auth, rate
10
+ * limiting, transports and output guardrails around it.
11
+ *
12
+ * With no `answerFn` configured these are thin pass-throughs, so behaviour is
13
+ * exactly what it has always been.
14
+ */
15
+ import type OpenAI from "openai";
16
+ import type { PipelineMessage, PipelineMode } from "./pipeline";
17
+ /** Token accounting in the OpenAI wire shape */
18
+ export interface AnswerUsage {
19
+ prompt_tokens: number;
20
+ completion_tokens: number;
21
+ total_tokens: number;
22
+ }
23
+ /** What a brain is given: the assembled prompt plus who is asking */
24
+ export interface AnswerFnInput {
25
+ /** Fully assembled system prompt from `prepareChat` */
26
+ system: string;
27
+ /** Conversation messages */
28
+ messages: PipelineMessage[];
29
+ /** Which pipeline the answer is for */
30
+ mode: PipelineMode;
31
+ /** Channel-specific sender identity, when the surface knows one */
32
+ sender?: string;
33
+ }
34
+ /**
35
+ * What a brain returns: the answer text, optionally with token usage for
36
+ * surfaces that report it.
37
+ */
38
+ export type AnswerFnResult = string | {
39
+ content: string;
40
+ usage?: AnswerUsage;
41
+ };
42
+ /**
43
+ * Replaces the completion call on every chat surface. Rejections propagate to
44
+ * the caller like any other completion failure.
45
+ */
46
+ export type AnswerFn = (input: AnswerFnInput) => Promise<AnswerFnResult> | AnswerFnResult;
47
+ export interface AnswerOptions {
48
+ /** Caller-supplied brain; falls back to the built-in completion when unset */
49
+ answerFn?: AnswerFn;
50
+ /** Used by the built-in completion; untouched when `answerFn` answers */
51
+ client: OpenAI;
52
+ system: string;
53
+ messages: PipelineMessage[];
54
+ mode: PipelineMode;
55
+ sender?: string;
56
+ temperature?: number;
57
+ model?: string;
58
+ }
59
+ /**
60
+ * Produce one complete answer, from `answerFn` when configured.
61
+ */
62
+ export declare function answerOnce({ answerFn, client, system, messages, mode, sender, temperature, model, }: AnswerOptions): Promise<{
63
+ content: string;
64
+ usage: AnswerUsage;
65
+ }>;
66
+ /**
67
+ * Stream an answer. A brain that returns a plain string cannot stream, so its
68
+ * answer degrades to a single chunk followed by the stream's normal end —
69
+ * streaming surfaces keep their wire format either way.
70
+ *
71
+ * Because a brain's answer arrives whole, it gets the full guardrails; the
72
+ * built-in stream only scrubs each delta, since leakage detection needs text
73
+ * no streamed chunk has yet.
74
+ */
75
+ export declare function answerStream({ answerFn, client, system, messages, mode, sender, temperature, model, }: AnswerOptions): AsyncGenerator<string>;
76
+ //# sourceMappingURL=answer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../src/core/answer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhE,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,uCAAuC;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAE/E;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC;AAE1F,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAqBD;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAC/B,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,WAAW,EACX,KAAK,GACN,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC,CAKlE;AAED;;;;;;;;GAQG;AACH,wBAAuB,YAAY,CAAC,EAClC,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,WAAW,EACX,KAAK,GACN,EAAE,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC,CAOxC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Brain hook tests
3
+ *
4
+ * Uses a faked OpenAI client so both the built-in completion path and the
5
+ * `answerFn` path can be asserted without touching OpenAI.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=answer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answer.test.d.ts","sourceRoot":"","sources":["../../src/core/answer.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,3 +1,11 @@
1
1
  export declare function detectLeakage(text: string): boolean;
2
2
  export declare function scrubOutput(text: string): string;
3
+ /**
4
+ * Apply the full output guardrails to a complete answer: refuse leaked
5
+ * instructions outright, then scrub credentials from whatever remains.
6
+ *
7
+ * Used for every non-streamed answer, whoever produced it — the built-in
8
+ * completion or a caller-supplied brain (`answerFn`).
9
+ */
10
+ export declare function guardOutput(text: string): string;
3
11
  //# sourceMappingURL=guardrails.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASnD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD"}
1
+ {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASnD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhD"}
@@ -1 +1 @@
1
- {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/core/llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,wBAAsB,YAAY,CAAC,EACjC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAiB,EACjB,KAAqB,GACtB,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;GAaA;AAGD,wBAAuB,cAAc,CAAC,EACpC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAiB,EACjB,KAAqB,GACtB,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,yCAYA"}
1
+ {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/core/llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,wBAAsB,YAAY,CAAC,EACjC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAiB,EACjB,KAAqB,GACtB,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;GAWA;AAGD,wBAAuB,cAAc,CAAC,EACpC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAiB,EACjB,KAAqB,GACtB,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,yCAYA"}
@@ -4,7 +4,9 @@
4
4
  * This is the single place where a conversation is turned into a
5
5
  * retrieval-augmented completion request. Every surface (widget routes,
6
6
  * OpenAI-compatible routes, MCP, programmatic use) should go through here
7
- * so behaviour stays identical regardless of how the chat is consumed.
7
+ * so behaviour stays identical regardless of how the chat is consumed, and
8
+ * then ask for the answer via `answerOnce`/`answerStream` (see ./answer.ts)
9
+ * so a caller-supplied brain is honoured.
8
10
  */
9
11
  import type { PromptLoader } from "./prompts";
10
12
  import type { VectorStore } from "./retrieval";
@@ -14,7 +16,7 @@ export interface PipelineMessage {
14
16
  content: string;
15
17
  }
16
18
  export interface PreparedChat {
17
- /** Fully assembled system prompt (rules + persona + retrieved context) */
19
+ /** Fully assembled system prompt (see `prepareChat` for the layer order) */
18
20
  system: string;
19
21
  /** Conversation messages, unchanged */
20
22
  messages: PipelineMessage[];
@@ -22,12 +24,24 @@ export interface PreparedChat {
22
24
  /**
23
25
  * Run retrieval for the latest user message and assemble the system prompt.
24
26
  *
27
+ * The assembled system prompt is layered, in order:
28
+ * base rules → persona → channel hint (optional) → retrieved context.
29
+ *
30
+ * `personaLayer` and `channelHint` let a caller shape those middle layers
31
+ * without hand-rolling its own sandwich around `store`/`prompts`. Both are
32
+ * optional, and blank (or whitespace-only) values are ignored: omit them and
33
+ * the prompt is exactly what it has always been.
34
+ *
25
35
  * @throws if the conversation contains no user message
26
36
  */
27
- export declare function prepareChat({ store, prompts, mode, messages, }: {
37
+ export declare function prepareChat({ store, prompts, mode, messages, personaLayer, channelHint, }: {
28
38
  store: VectorStore;
29
39
  prompts: PromptLoader;
30
40
  mode: PipelineMode;
31
41
  messages: PipelineMessage[];
42
+ /** Replaces the mode's persona from the loader when provided */
43
+ personaLayer?: string;
44
+ /** Extra system-prompt section describing the delivery channel */
45
+ channelHint?: string;
32
46
  }): Promise<PreparedChat>;
33
47
  //# sourceMappingURL=pipeline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAOD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,EAChC,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,GAAG,OAAO,CAAC,YAAY,CAAC,CAYxB"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAAC,EAChC,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,YAAY,CAAC,CAmBxB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Chat pipeline tests
3
+ *
4
+ * Uses faked prompts and vector store so prompt assembly can be asserted
5
+ * without touching OpenAI or Turso.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=pipeline.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.test.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
package/dist/index.d.ts CHANGED
@@ -14,7 +14,9 @@ export type { ApiKeyOptions, ApiKeyPayload, VerifyResult } from "./auth";
14
14
  export { ApiKeyManager } from "./auth";
15
15
  export type { ChatBotConfig, ChatButtonConfig, ChatConfig, ChatMessage, ChatMode, StreamCallbacks, } from "./client";
16
16
  export { Chat, ChatBot, ChatButton } from "./client";
17
- export { detectLeakage, scrubOutput } from "./core/guardrails";
17
+ export type { AnswerFn, AnswerFnInput, AnswerFnResult, AnswerOptions, AnswerUsage, } from "./core/answer";
18
+ export { answerOnce, answerStream } from "./core/answer";
19
+ export { detectLeakage, guardOutput, scrubOutput } from "./core/guardrails";
18
20
  export { completeOnce, completeStream, DEFAULT_MODEL } from "./core/llm";
19
21
  export { loadKnowledge } from "./core/loaders";
20
22
  export type { PipelineMessage, PipelineMode, PreparedChat } from "./core/pipeline";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,eAAe,GAChB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,YAAY,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,eAAe,GAChB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACrD,YAAY,EACV,QAAQ,EACR,aAAa,EACb,cAAc,EACd,aAAa,EACb,WAAW,GACZ,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,YAAY,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -7537,6 +7537,8 @@ __export(index_exports, {
7537
7537
  DEFAULT_MODEL: () => DEFAULT_MODEL,
7538
7538
  PromptLoader: () => PromptLoader,
7539
7539
  VectorStore: () => VectorStore,
7540
+ answerOnce: () => answerOnce,
7541
+ answerStream: () => answerStream,
7540
7542
  completeOnce: () => completeOnce,
7541
7543
  completeStream: () => completeStream,
7542
7544
  cors: () => cors,
@@ -7552,6 +7554,7 @@ __export(index_exports, {
7552
7554
  detectLeakage: () => detectLeakage,
7553
7555
  getActiveSessions: () => getActiveSessions,
7554
7556
  getSessionInfo: () => getSessionInfo,
7557
+ guardOutput: () => guardOutput,
7555
7558
  loadKnowledge: () => loadKnowledge,
7556
7559
  openaiRoutes: () => openaiRoutes,
7557
7560
  prepareChat: () => prepareChat,
@@ -7690,6 +7693,12 @@ function detectLeakage(text) {
7690
7693
  function scrubOutput(text) {
7691
7694
  return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
7692
7695
  }
7696
+ function guardOutput(text) {
7697
+ if (detectLeakage(text)) {
7698
+ return "Sorry, I can't share internal instructions. How else can I help?";
7699
+ }
7700
+ return scrubOutput(text);
7701
+ }
7693
7702
 
7694
7703
  // src/core/llm.ts
7695
7704
  var DEFAULT_MODEL = "gpt-4o";
@@ -7705,11 +7714,9 @@ async function completeOnce({
7705
7714
  temperature,
7706
7715
  messages: [{ role: "system", content: system }, ...messages]
7707
7716
  });
7708
- let text = res.choices[0]?.message?.content ?? "";
7709
- if (detectLeakage(text))
7710
- text = "Sorry, I can't share internal instructions. How else can I help?";
7717
+ const text = res.choices[0]?.message?.content ?? "";
7711
7718
  return {
7712
- content: scrubOutput(text),
7719
+ content: guardOutput(text),
7713
7720
  usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
7714
7721
  };
7715
7722
  }
@@ -7732,6 +7739,50 @@ async function* completeStream({
7732
7739
  }
7733
7740
  }
7734
7741
 
7742
+ // src/core/answer.ts
7743
+ var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
7744
+ async function runAnswerFn(answerFn, { system, messages, mode, sender }) {
7745
+ const result = await answerFn({ system, messages, mode, sender });
7746
+ const raw = typeof result === "string" ? result : result?.content;
7747
+ const usage = typeof result === "string" ? void 0 : result?.usage;
7748
+ return {
7749
+ content: guardOutput(typeof raw === "string" ? raw : ""),
7750
+ usage: usage ?? noUsage()
7751
+ };
7752
+ }
7753
+ async function answerOnce({
7754
+ answerFn,
7755
+ client,
7756
+ system,
7757
+ messages,
7758
+ mode,
7759
+ sender,
7760
+ temperature,
7761
+ model
7762
+ }) {
7763
+ if (answerFn) {
7764
+ return runAnswerFn(answerFn, { system, messages, mode, sender });
7765
+ }
7766
+ return completeOnce({ client, system, messages, temperature, model });
7767
+ }
7768
+ async function* answerStream({
7769
+ answerFn,
7770
+ client,
7771
+ system,
7772
+ messages,
7773
+ mode,
7774
+ sender,
7775
+ temperature,
7776
+ model
7777
+ }) {
7778
+ if (answerFn) {
7779
+ const { content } = await runAnswerFn(answerFn, { system, messages, mode, sender });
7780
+ if (content) yield content;
7781
+ return;
7782
+ }
7783
+ yield* completeStream({ client, system, messages, temperature, model });
7784
+ }
7785
+
7735
7786
  // src/core/loaders.ts
7736
7787
  var import_node_fs = require("node:fs");
7737
7788
  var import_node_path = require("node:path");
@@ -7768,7 +7819,9 @@ async function prepareChat({
7768
7819
  store,
7769
7820
  prompts,
7770
7821
  mode,
7771
- messages
7822
+ messages,
7823
+ personaLayer,
7824
+ channelHint
7772
7825
  }) {
7773
7826
  const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
7774
7827
  if (!lastUserMsg) {
@@ -7776,9 +7829,15 @@ async function prepareChat({
7776
7829
  }
7777
7830
  const { topK, label } = MODE_SETTINGS[mode];
7778
7831
  const ctx = await store.query(lastUserMsg.content, topK, ["base", mode]);
7779
- const persona = mode === "private" ? prompts.privatePersona : prompts.publicPersona;
7780
- const system = [prompts.baseSystemRules, persona, `${label}:
7781
- ${ctx.join("\n\n")}`].join("\n\n");
7832
+ const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
7833
+ const hint = channelHint?.trim();
7834
+ const system = [
7835
+ prompts.baseSystemRules,
7836
+ persona,
7837
+ ...hint ? [hint] : [],
7838
+ `${label}:
7839
+ ${ctx.join("\n\n")}`
7840
+ ].join("\n\n");
7782
7841
  return { system, messages };
7783
7842
  }
7784
7843
 
@@ -32240,10 +32299,12 @@ async function createMCPServer(config2) {
32240
32299
  `Context:
32241
32300
  ${ctx.join("\n\n")}`
32242
32301
  ].join("\n\n");
32243
- const result = await completeOnce({
32302
+ const result = await answerOnce({
32303
+ answerFn: config2.answerFn,
32244
32304
  client,
32245
32305
  system,
32246
- messages: conversationMessages
32306
+ messages: conversationMessages,
32307
+ mode: "public"
32247
32308
  });
32248
32309
  const cost = calculateCost(result.usage);
32249
32310
  const duration3 = Date.now() - startTime;
@@ -32324,10 +32385,12 @@ ${ctx.join("\n\n")}`
32324
32385
  `Internal Context:
32325
32386
  ${ctx.join("\n\n")}`
32326
32387
  ].join("\n\n");
32327
- const result = await completeOnce({
32388
+ const result = await answerOnce({
32389
+ answerFn: config2.answerFn,
32328
32390
  client,
32329
32391
  system,
32330
- messages: conversationMessages
32392
+ messages: conversationMessages,
32393
+ mode: "private"
32331
32394
  });
32332
32395
  const cost = calculateCost(result.usage);
32333
32396
  const duration3 = Date.now() - startTime;
@@ -32745,7 +32808,13 @@ ${ctx.join("\n\n")}`
32745
32808
  const wantsStream3 = url2.searchParams.get("stream") === "1";
32746
32809
  if (wantsStream3) {
32747
32810
  return (0, import_streaming.stream)(c, async (s) => {
32748
- for await (const delta of completeStream({ client, system, messages })) {
32811
+ for await (const delta of answerStream({
32812
+ answerFn: config2.answerFn,
32813
+ client,
32814
+ system,
32815
+ messages,
32816
+ mode: "public"
32817
+ })) {
32749
32818
  await s.write(`data: ${JSON.stringify({ delta })}
32750
32819
 
32751
32820
  `);
@@ -32753,7 +32822,13 @@ ${ctx.join("\n\n")}`
32753
32822
  await s.write("event: end\ndata: {}\n\n");
32754
32823
  });
32755
32824
  }
32756
- const out = await completeOnce({ client, system, messages });
32825
+ const out = await answerOnce({
32826
+ answerFn: config2.answerFn,
32827
+ client,
32828
+ system,
32829
+ messages,
32830
+ mode: "public"
32831
+ });
32757
32832
  return c.json({ reply: out.content });
32758
32833
  } catch (error51) {
32759
32834
  const err = error51;
@@ -32850,10 +32925,12 @@ function openaiRoutes(deps) {
32850
32925
 
32851
32926
  `;
32852
32927
  await s.write(chunk2({ role: "assistant", content: "" }, null));
32853
- for await (const delta of completeStream({
32928
+ for await (const delta of answerStream({
32929
+ answerFn: config2.answerFn,
32854
32930
  client,
32855
32931
  system,
32856
32932
  messages,
32933
+ mode,
32857
32934
  temperature,
32858
32935
  model: serverModel
32859
32936
  })) {
@@ -32863,7 +32940,15 @@ function openaiRoutes(deps) {
32863
32940
  await s.write("data: [DONE]\n\n");
32864
32941
  });
32865
32942
  }
32866
- const out = await completeOnce({ client, system, messages, temperature, model: serverModel });
32943
+ const out = await answerOnce({
32944
+ answerFn: config2.answerFn,
32945
+ client,
32946
+ system,
32947
+ messages,
32948
+ mode,
32949
+ temperature,
32950
+ model: serverModel
32951
+ });
32867
32952
  return c.json({
32868
32953
  id,
32869
32954
  object: "chat.completion",
@@ -32924,9 +33009,17 @@ function privateRoutes(deps) {
32924
33009
  return c.json({ error: "no user message found in conversation" }, 400);
32925
33010
  }
32926
33011
  const model = config2.openai.model;
33012
+ const answerFn = config2.answerFn;
32927
33013
  if (wantsStream(c)) {
32928
33014
  return (0, import_streaming3.stream)(c, async (s) => {
32929
- for await (const delta of completeStream({ client, system, messages, model })) {
33015
+ for await (const delta of answerStream({
33016
+ answerFn,
33017
+ client,
33018
+ system,
33019
+ messages,
33020
+ mode: "private",
33021
+ model
33022
+ })) {
32930
33023
  await s.write(`data: ${JSON.stringify({ delta })}
32931
33024
 
32932
33025
  `);
@@ -32934,7 +33027,7 @@ function privateRoutes(deps) {
32934
33027
  await s.write("event: end\ndata: {}\n\n");
32935
33028
  });
32936
33029
  }
32937
- const out = await completeOnce({ client, system, messages, model });
33030
+ const out = await answerOnce({ answerFn, client, system, messages, mode: "private", model });
32938
33031
  return c.json({ reply: out.content });
32939
33032
  });
32940
33033
  return app;
@@ -32979,9 +33072,17 @@ function publicRoutes(deps) {
32979
33072
  return c.json({ error: "no user message found in conversation" }, 400);
32980
33073
  }
32981
33074
  const model = config2.openai.model;
33075
+ const answerFn = config2.answerFn;
32982
33076
  if (wantsStream2(c)) {
32983
33077
  return (0, import_streaming4.stream)(c, async (s) => {
32984
- for await (const delta of completeStream({ client, system, messages, model })) {
33078
+ for await (const delta of answerStream({
33079
+ answerFn,
33080
+ client,
33081
+ system,
33082
+ messages,
33083
+ mode: "public",
33084
+ model
33085
+ })) {
32985
33086
  await s.write(`data: ${JSON.stringify({ delta })}
32986
33087
 
32987
33088
  `);
@@ -32989,7 +33090,7 @@ function publicRoutes(deps) {
32989
33090
  await s.write("event: end\ndata: {}\n\n");
32990
33091
  });
32991
33092
  }
32992
- const out = await completeOnce({ client, system, messages, model });
33093
+ const out = await answerOnce({ answerFn, client, system, messages, mode: "public", model });
32993
33094
  return c.json({ reply: out.content });
32994
33095
  });
32995
33096
  return app;
@@ -33150,6 +33251,8 @@ async function createServer(config2) {
33150
33251
  DEFAULT_MODEL,
33151
33252
  PromptLoader,
33152
33253
  VectorStore,
33254
+ answerOnce,
33255
+ answerStream,
33153
33256
  completeOnce,
33154
33257
  completeStream,
33155
33258
  cors,
@@ -33165,6 +33268,7 @@ async function createServer(config2) {
33165
33268
  detectLeakage,
33166
33269
  getActiveSessions,
33167
33270
  getSessionInfo,
33271
+ guardOutput,
33168
33272
  loadKnowledge,
33169
33273
  openaiRoutes,
33170
33274
  prepareChat,
package/dist/index.mjs CHANGED
@@ -7659,6 +7659,12 @@ function detectLeakage(text) {
7659
7659
  function scrubOutput(text) {
7660
7660
  return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
7661
7661
  }
7662
+ function guardOutput(text) {
7663
+ if (detectLeakage(text)) {
7664
+ return "Sorry, I can't share internal instructions. How else can I help?";
7665
+ }
7666
+ return scrubOutput(text);
7667
+ }
7662
7668
 
7663
7669
  // src/core/llm.ts
7664
7670
  var DEFAULT_MODEL = "gpt-4o";
@@ -7674,11 +7680,9 @@ async function completeOnce({
7674
7680
  temperature,
7675
7681
  messages: [{ role: "system", content: system }, ...messages]
7676
7682
  });
7677
- let text = res.choices[0]?.message?.content ?? "";
7678
- if (detectLeakage(text))
7679
- text = "Sorry, I can't share internal instructions. How else can I help?";
7683
+ const text = res.choices[0]?.message?.content ?? "";
7680
7684
  return {
7681
- content: scrubOutput(text),
7685
+ content: guardOutput(text),
7682
7686
  usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
7683
7687
  };
7684
7688
  }
@@ -7701,6 +7705,50 @@ async function* completeStream({
7701
7705
  }
7702
7706
  }
7703
7707
 
7708
+ // src/core/answer.ts
7709
+ var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
7710
+ async function runAnswerFn(answerFn, { system, messages, mode, sender }) {
7711
+ const result = await answerFn({ system, messages, mode, sender });
7712
+ const raw = typeof result === "string" ? result : result?.content;
7713
+ const usage = typeof result === "string" ? void 0 : result?.usage;
7714
+ return {
7715
+ content: guardOutput(typeof raw === "string" ? raw : ""),
7716
+ usage: usage ?? noUsage()
7717
+ };
7718
+ }
7719
+ async function answerOnce({
7720
+ answerFn,
7721
+ client,
7722
+ system,
7723
+ messages,
7724
+ mode,
7725
+ sender,
7726
+ temperature,
7727
+ model
7728
+ }) {
7729
+ if (answerFn) {
7730
+ return runAnswerFn(answerFn, { system, messages, mode, sender });
7731
+ }
7732
+ return completeOnce({ client, system, messages, temperature, model });
7733
+ }
7734
+ async function* answerStream({
7735
+ answerFn,
7736
+ client,
7737
+ system,
7738
+ messages,
7739
+ mode,
7740
+ sender,
7741
+ temperature,
7742
+ model
7743
+ }) {
7744
+ if (answerFn) {
7745
+ const { content } = await runAnswerFn(answerFn, { system, messages, mode, sender });
7746
+ if (content) yield content;
7747
+ return;
7748
+ }
7749
+ yield* completeStream({ client, system, messages, temperature, model });
7750
+ }
7751
+
7704
7752
  // src/core/loaders.ts
7705
7753
  import { readdirSync, readFileSync, statSync } from "node:fs";
7706
7754
  import { join } from "node:path";
@@ -7737,7 +7785,9 @@ async function prepareChat({
7737
7785
  store,
7738
7786
  prompts,
7739
7787
  mode,
7740
- messages
7788
+ messages,
7789
+ personaLayer,
7790
+ channelHint
7741
7791
  }) {
7742
7792
  const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
7743
7793
  if (!lastUserMsg) {
@@ -7745,9 +7795,15 @@ async function prepareChat({
7745
7795
  }
7746
7796
  const { topK, label } = MODE_SETTINGS[mode];
7747
7797
  const ctx = await store.query(lastUserMsg.content, topK, ["base", mode]);
7748
- const persona = mode === "private" ? prompts.privatePersona : prompts.publicPersona;
7749
- const system = [prompts.baseSystemRules, persona, `${label}:
7750
- ${ctx.join("\n\n")}`].join("\n\n");
7798
+ const persona = personaLayer?.trim() || (mode === "private" ? prompts.privatePersona : prompts.publicPersona);
7799
+ const hint = channelHint?.trim();
7800
+ const system = [
7801
+ prompts.baseSystemRules,
7802
+ persona,
7803
+ ...hint ? [hint] : [],
7804
+ `${label}:
7805
+ ${ctx.join("\n\n")}`
7806
+ ].join("\n\n");
7751
7807
  return { system, messages };
7752
7808
  }
7753
7809
 
@@ -32209,10 +32265,12 @@ async function createMCPServer(config2) {
32209
32265
  `Context:
32210
32266
  ${ctx.join("\n\n")}`
32211
32267
  ].join("\n\n");
32212
- const result = await completeOnce({
32268
+ const result = await answerOnce({
32269
+ answerFn: config2.answerFn,
32213
32270
  client,
32214
32271
  system,
32215
- messages: conversationMessages
32272
+ messages: conversationMessages,
32273
+ mode: "public"
32216
32274
  });
32217
32275
  const cost = calculateCost(result.usage);
32218
32276
  const duration3 = Date.now() - startTime;
@@ -32293,10 +32351,12 @@ ${ctx.join("\n\n")}`
32293
32351
  `Internal Context:
32294
32352
  ${ctx.join("\n\n")}`
32295
32353
  ].join("\n\n");
32296
- const result = await completeOnce({
32354
+ const result = await answerOnce({
32355
+ answerFn: config2.answerFn,
32297
32356
  client,
32298
32357
  system,
32299
- messages: conversationMessages
32358
+ messages: conversationMessages,
32359
+ mode: "private"
32300
32360
  });
32301
32361
  const cost = calculateCost(result.usage);
32302
32362
  const duration3 = Date.now() - startTime;
@@ -32714,7 +32774,13 @@ ${ctx.join("\n\n")}`
32714
32774
  const wantsStream3 = url2.searchParams.get("stream") === "1";
32715
32775
  if (wantsStream3) {
32716
32776
  return stream(c, async (s) => {
32717
- for await (const delta of completeStream({ client, system, messages })) {
32777
+ for await (const delta of answerStream({
32778
+ answerFn: config2.answerFn,
32779
+ client,
32780
+ system,
32781
+ messages,
32782
+ mode: "public"
32783
+ })) {
32718
32784
  await s.write(`data: ${JSON.stringify({ delta })}
32719
32785
 
32720
32786
  `);
@@ -32722,7 +32788,13 @@ ${ctx.join("\n\n")}`
32722
32788
  await s.write("event: end\ndata: {}\n\n");
32723
32789
  });
32724
32790
  }
32725
- const out = await completeOnce({ client, system, messages });
32791
+ const out = await answerOnce({
32792
+ answerFn: config2.answerFn,
32793
+ client,
32794
+ system,
32795
+ messages,
32796
+ mode: "public"
32797
+ });
32726
32798
  return c.json({ reply: out.content });
32727
32799
  } catch (error51) {
32728
32800
  const err = error51;
@@ -32819,10 +32891,12 @@ function openaiRoutes(deps) {
32819
32891
 
32820
32892
  `;
32821
32893
  await s.write(chunk2({ role: "assistant", content: "" }, null));
32822
- for await (const delta of completeStream({
32894
+ for await (const delta of answerStream({
32895
+ answerFn: config2.answerFn,
32823
32896
  client,
32824
32897
  system,
32825
32898
  messages,
32899
+ mode,
32826
32900
  temperature,
32827
32901
  model: serverModel
32828
32902
  })) {
@@ -32832,7 +32906,15 @@ function openaiRoutes(deps) {
32832
32906
  await s.write("data: [DONE]\n\n");
32833
32907
  });
32834
32908
  }
32835
- const out = await completeOnce({ client, system, messages, temperature, model: serverModel });
32909
+ const out = await answerOnce({
32910
+ answerFn: config2.answerFn,
32911
+ client,
32912
+ system,
32913
+ messages,
32914
+ mode,
32915
+ temperature,
32916
+ model: serverModel
32917
+ });
32836
32918
  return c.json({
32837
32919
  id,
32838
32920
  object: "chat.completion",
@@ -32893,9 +32975,17 @@ function privateRoutes(deps) {
32893
32975
  return c.json({ error: "no user message found in conversation" }, 400);
32894
32976
  }
32895
32977
  const model = config2.openai.model;
32978
+ const answerFn = config2.answerFn;
32896
32979
  if (wantsStream(c)) {
32897
32980
  return stream3(c, async (s) => {
32898
- for await (const delta of completeStream({ client, system, messages, model })) {
32981
+ for await (const delta of answerStream({
32982
+ answerFn,
32983
+ client,
32984
+ system,
32985
+ messages,
32986
+ mode: "private",
32987
+ model
32988
+ })) {
32899
32989
  await s.write(`data: ${JSON.stringify({ delta })}
32900
32990
 
32901
32991
  `);
@@ -32903,7 +32993,7 @@ function privateRoutes(deps) {
32903
32993
  await s.write("event: end\ndata: {}\n\n");
32904
32994
  });
32905
32995
  }
32906
- const out = await completeOnce({ client, system, messages, model });
32996
+ const out = await answerOnce({ answerFn, client, system, messages, mode: "private", model });
32907
32997
  return c.json({ reply: out.content });
32908
32998
  });
32909
32999
  return app;
@@ -32948,9 +33038,17 @@ function publicRoutes(deps) {
32948
33038
  return c.json({ error: "no user message found in conversation" }, 400);
32949
33039
  }
32950
33040
  const model = config2.openai.model;
33041
+ const answerFn = config2.answerFn;
32951
33042
  if (wantsStream2(c)) {
32952
33043
  return stream4(c, async (s) => {
32953
- for await (const delta of completeStream({ client, system, messages, model })) {
33044
+ for await (const delta of answerStream({
33045
+ answerFn,
33046
+ client,
33047
+ system,
33048
+ messages,
33049
+ mode: "public",
33050
+ model
33051
+ })) {
32954
33052
  await s.write(`data: ${JSON.stringify({ delta })}
32955
33053
 
32956
33054
  `);
@@ -32958,7 +33056,7 @@ function publicRoutes(deps) {
32958
33056
  await s.write("event: end\ndata: {}\n\n");
32959
33057
  });
32960
33058
  }
32961
- const out = await completeOnce({ client, system, messages, model });
33059
+ const out = await answerOnce({ answerFn, client, system, messages, mode: "public", model });
32962
33060
  return c.json({ reply: out.content });
32963
33061
  });
32964
33062
  return app;
@@ -33120,6 +33218,8 @@ export {
33120
33218
  DEFAULT_MODEL,
33121
33219
  PromptLoader,
33122
33220
  VectorStore,
33221
+ answerOnce,
33222
+ answerStream,
33123
33223
  completeOnce,
33124
33224
  completeStream,
33125
33225
  cors,
@@ -33135,6 +33235,7 @@ export {
33135
33235
  detectLeakage,
33136
33236
  getActiveSessions,
33137
33237
  getSessionInfo,
33238
+ guardOutput,
33138
33239
  loadKnowledge,
33139
33240
  openaiRoutes,
33140
33241
  prepareChat,
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAYpE,YAAY,EACV,WAAW,EACX,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,gBAAgB,sBAuS7D"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAYpE,YAAY,EACV,WAAW,EACX,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,gBAAgB,sBA2S7D"}
@@ -51,6 +51,12 @@ function detectLeakage(text) {
51
51
  function scrubOutput(text) {
52
52
  return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
53
53
  }
54
+ function guardOutput(text) {
55
+ if (detectLeakage(text)) {
56
+ return "Sorry, I can't share internal instructions. How else can I help?";
57
+ }
58
+ return scrubOutput(text);
59
+ }
54
60
 
55
61
  // src/core/llm.ts
56
62
  var DEFAULT_MODEL = "gpt-4o";
@@ -66,15 +72,40 @@ async function completeOnce({
66
72
  temperature,
67
73
  messages: [{ role: "system", content: system }, ...messages]
68
74
  });
69
- let text = res.choices[0]?.message?.content ?? "";
70
- if (detectLeakage(text))
71
- text = "Sorry, I can't share internal instructions. How else can I help?";
75
+ const text = res.choices[0]?.message?.content ?? "";
72
76
  return {
73
- content: scrubOutput(text),
77
+ content: guardOutput(text),
74
78
  usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
75
79
  };
76
80
  }
77
81
 
82
+ // src/core/answer.ts
83
+ var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
84
+ async function runAnswerFn(answerFn, { system, messages, mode, sender }) {
85
+ const result = await answerFn({ system, messages, mode, sender });
86
+ const raw = typeof result === "string" ? result : result?.content;
87
+ const usage = typeof result === "string" ? void 0 : result?.usage;
88
+ return {
89
+ content: guardOutput(typeof raw === "string" ? raw : ""),
90
+ usage: usage ?? noUsage()
91
+ };
92
+ }
93
+ async function answerOnce({
94
+ answerFn,
95
+ client,
96
+ system,
97
+ messages,
98
+ mode,
99
+ sender,
100
+ temperature,
101
+ model
102
+ }) {
103
+ if (answerFn) {
104
+ return runAnswerFn(answerFn, { system, messages, mode, sender });
105
+ }
106
+ return completeOnce({ client, system, messages, temperature, model });
107
+ }
108
+
78
109
  // src/core/prompts.ts
79
110
  var import_node_fs = require("node:fs");
80
111
  var import_node_path = require("node:path");
@@ -531,10 +562,12 @@ async function createMCPServer(config) {
531
562
  `Context:
532
563
  ${ctx.join("\n\n")}`
533
564
  ].join("\n\n");
534
- const result = await completeOnce({
565
+ const result = await answerOnce({
566
+ answerFn: config.answerFn,
535
567
  client,
536
568
  system,
537
- messages: conversationMessages
569
+ messages: conversationMessages,
570
+ mode: "public"
538
571
  });
539
572
  const cost = calculateCost(result.usage);
540
573
  const duration = Date.now() - startTime;
@@ -615,10 +648,12 @@ ${ctx.join("\n\n")}`
615
648
  `Internal Context:
616
649
  ${ctx.join("\n\n")}`
617
650
  ].join("\n\n");
618
- const result = await completeOnce({
651
+ const result = await answerOnce({
652
+ answerFn: config.answerFn,
619
653
  client,
620
654
  system,
621
- messages: conversationMessages
655
+ messages: conversationMessages,
656
+ mode: "private"
622
657
  });
623
658
  const cost = calculateCost(result.usage);
624
659
  const duration = Date.now() - startTime;
@@ -17,6 +17,12 @@ function detectLeakage(text) {
17
17
  function scrubOutput(text) {
18
18
  return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
19
19
  }
20
+ function guardOutput(text) {
21
+ if (detectLeakage(text)) {
22
+ return "Sorry, I can't share internal instructions. How else can I help?";
23
+ }
24
+ return scrubOutput(text);
25
+ }
20
26
 
21
27
  // src/core/llm.ts
22
28
  var DEFAULT_MODEL = "gpt-4o";
@@ -32,15 +38,40 @@ async function completeOnce({
32
38
  temperature,
33
39
  messages: [{ role: "system", content: system }, ...messages]
34
40
  });
35
- let text = res.choices[0]?.message?.content ?? "";
36
- if (detectLeakage(text))
37
- text = "Sorry, I can't share internal instructions. How else can I help?";
41
+ const text = res.choices[0]?.message?.content ?? "";
38
42
  return {
39
- content: scrubOutput(text),
43
+ content: guardOutput(text),
40
44
  usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
41
45
  };
42
46
  }
43
47
 
48
+ // src/core/answer.ts
49
+ var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
50
+ async function runAnswerFn(answerFn, { system, messages, mode, sender }) {
51
+ const result = await answerFn({ system, messages, mode, sender });
52
+ const raw = typeof result === "string" ? result : result?.content;
53
+ const usage = typeof result === "string" ? void 0 : result?.usage;
54
+ return {
55
+ content: guardOutput(typeof raw === "string" ? raw : ""),
56
+ usage: usage ?? noUsage()
57
+ };
58
+ }
59
+ async function answerOnce({
60
+ answerFn,
61
+ client,
62
+ system,
63
+ messages,
64
+ mode,
65
+ sender,
66
+ temperature,
67
+ model
68
+ }) {
69
+ if (answerFn) {
70
+ return runAnswerFn(answerFn, { system, messages, mode, sender });
71
+ }
72
+ return completeOnce({ client, system, messages, temperature, model });
73
+ }
74
+
44
75
  // src/core/prompts.ts
45
76
  import { readFileSync } from "node:fs";
46
77
  import { join } from "node:path";
@@ -497,10 +528,12 @@ async function createMCPServer(config) {
497
528
  `Context:
498
529
  ${ctx.join("\n\n")}`
499
530
  ].join("\n\n");
500
- const result = await completeOnce({
531
+ const result = await answerOnce({
532
+ answerFn: config.answerFn,
501
533
  client,
502
534
  system,
503
- messages: conversationMessages
535
+ messages: conversationMessages,
536
+ mode: "public"
504
537
  });
505
538
  const cost = calculateCost(result.usage);
506
539
  const duration = Date.now() - startTime;
@@ -581,10 +614,12 @@ ${ctx.join("\n\n")}`
581
614
  `Internal Context:
582
615
  ${ctx.join("\n\n")}`
583
616
  ].join("\n\n");
584
- const result = await completeOnce({
617
+ const result = await answerOnce({
618
+ answerFn: config.answerFn,
585
619
  client,
586
620
  system,
587
- messages: conversationMessages
621
+ messages: conversationMessages,
622
+ mode: "private"
588
623
  });
589
624
  const cost = calculateCost(result.usage);
590
625
  const duration = Date.now() - startTime;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Widget chat route tests
3
+ *
4
+ * Covers the brain hook on the public and private chat routes with faked
5
+ * dependencies: no OpenAI, no Turso, and a locally generated RS256 keypair
6
+ * for the private route's JWT so real verification runs offline.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=chat.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.test.d.ts","sourceRoot":"","sources":["../../src/routes/chat.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1 +1 @@
1
- {"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/routes/demo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAsHnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,kBAAkB,8EAqGlD"}
1
+ {"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/routes/demo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAsHnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,kBAAkB,8EAiHlD"}
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/routes/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,KAAK,eAAe,EAAkC,MAAM,kBAAkB,CAAC;AAGxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,EAAE,GAAG,IAAI,CA8BxE;AASD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EAsHpD"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/routes/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,EAAE,KAAK,eAAe,EAAkC,MAAM,kBAAkB,CAAC;AAGxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,EAAE,GAAG,IAAI,CA8BxE;AASD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EAgIpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/routes/private.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,8EAqDrD"}
1
+ {"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/routes/private.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,8EA6DrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/routes/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EA8DpD"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/routes/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EAsEpD"}
package/dist/types.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import type { Hono } from "hono";
8
8
  import type OpenAI from "openai";
9
+ import type { AnswerFn } from "./core/answer";
9
10
  import type { PromptLoader } from "./core/prompts";
10
11
  import type { VectorStore } from "./core/retrieval";
11
12
  /**
@@ -143,6 +144,17 @@ export interface ChatterConfig {
143
144
  */
144
145
  allowedOrigins?: string[];
145
146
  };
147
+ /**
148
+ * Replaces the completion call on every chat surface with your own brain —
149
+ * an agent framework, a graph runtime, a remote service. Receives the
150
+ * assembled system prompt and conversation from the pipeline and returns
151
+ * the answer text (optionally with token usage).
152
+ *
153
+ * Retrieval, prompt assembly, auth, rate limiting, transports and output
154
+ * guardrails all stay Chatter's. Errors surface as normal completion
155
+ * errors. Unset: the built-in OpenAI completion is used.
156
+ */
157
+ answerFn?: AnswerFn;
146
158
  /** Custom route handler for advanced use cases */
147
159
  customRoutes?: (app: Hono, deps: ServerDependencies) => void;
148
160
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegoaltoworks/chatter",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Embeddable AI chatbot framework with RAG, authentication, and customizable widgets",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -94,19 +94,19 @@
94
94
  "zod": "^3.25.76 || ^4.4.3"
95
95
  },
96
96
  "dependencies": {
97
- "jose": "6.2.3"
97
+ "jose": "6.2.8"
98
98
  },
99
99
  "devDependencies": {
100
- "@biomejs/biome": "2.5.6",
100
+ "@biomejs/biome": "2.5.7",
101
101
  "@libsql/client": "0.17.4",
102
102
  "@modelcontextprotocol/sdk": "1.30.0",
103
103
  "@types/bun": "1.3.14",
104
- "@types/node": "26.1.2",
104
+ "@types/node": "26.2.0",
105
105
  "esbuild": "0.28.1",
106
- "hono": "4.12.34",
106
+ "hono": "4.13.1",
107
107
  "husky": "9.1.7",
108
108
  "lint-staged": "17.3.0",
109
- "openai": "7.3.0",
109
+ "openai": "7.4.0",
110
110
  "typescript": "7.0.2",
111
111
  "zod": "4.4.3"
112
112
  },