@framers/agentos 0.2.6 → 0.2.8

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 (93) hide show
  1. package/dist/ingest-router/IngestRouter.d.ts +72 -0
  2. package/dist/ingest-router/IngestRouter.d.ts.map +1 -0
  3. package/dist/ingest-router/IngestRouter.js +98 -0
  4. package/dist/ingest-router/IngestRouter.js.map +1 -0
  5. package/dist/ingest-router/classifier.d.ts +63 -0
  6. package/dist/ingest-router/classifier.d.ts.map +1 -0
  7. package/dist/ingest-router/classifier.js +111 -0
  8. package/dist/ingest-router/classifier.js.map +1 -0
  9. package/dist/ingest-router/costs.d.ts +48 -0
  10. package/dist/ingest-router/costs.d.ts.map +1 -0
  11. package/dist/ingest-router/costs.js +63 -0
  12. package/dist/ingest-router/costs.js.map +1 -0
  13. package/dist/ingest-router/dispatcher.d.ts +35 -0
  14. package/dist/ingest-router/dispatcher.d.ts.map +1 -0
  15. package/dist/ingest-router/dispatcher.js +32 -0
  16. package/dist/ingest-router/dispatcher.js.map +1 -0
  17. package/dist/ingest-router/index.d.ts +43 -0
  18. package/dist/ingest-router/index.d.ts.map +1 -0
  19. package/dist/ingest-router/index.js +37 -0
  20. package/dist/ingest-router/index.js.map +1 -0
  21. package/dist/ingest-router/routing-tables.d.ts +122 -0
  22. package/dist/ingest-router/routing-tables.d.ts.map +1 -0
  23. package/dist/ingest-router/routing-tables.js +145 -0
  24. package/dist/ingest-router/routing-tables.js.map +1 -0
  25. package/dist/ingest-router/select-strategy.d.ts +67 -0
  26. package/dist/ingest-router/select-strategy.d.ts.map +1 -0
  27. package/dist/ingest-router/select-strategy.js +100 -0
  28. package/dist/ingest-router/select-strategy.js.map +1 -0
  29. package/dist/memory-router/MemoryRouter.d.ts +195 -0
  30. package/dist/memory-router/MemoryRouter.d.ts.map +1 -0
  31. package/dist/memory-router/MemoryRouter.js +155 -0
  32. package/dist/memory-router/MemoryRouter.js.map +1 -0
  33. package/dist/memory-router/adaptive.d.ts +142 -0
  34. package/dist/memory-router/adaptive.d.ts.map +1 -0
  35. package/dist/memory-router/adaptive.js +202 -0
  36. package/dist/memory-router/adaptive.js.map +1 -0
  37. package/dist/memory-router/backend-costs.d.ts +67 -0
  38. package/dist/memory-router/backend-costs.d.ts.map +1 -0
  39. package/dist/memory-router/backend-costs.js +136 -0
  40. package/dist/memory-router/backend-costs.js.map +1 -0
  41. package/dist/memory-router/classifier.d.ts +169 -0
  42. package/dist/memory-router/classifier.d.ts.map +1 -0
  43. package/dist/memory-router/classifier.js +193 -0
  44. package/dist/memory-router/classifier.js.map +1 -0
  45. package/dist/memory-router/dispatcher.d.ts +115 -0
  46. package/dist/memory-router/dispatcher.d.ts.map +1 -0
  47. package/dist/memory-router/dispatcher.js +84 -0
  48. package/dist/memory-router/dispatcher.js.map +1 -0
  49. package/dist/memory-router/index.d.ts +126 -0
  50. package/dist/memory-router/index.d.ts.map +1 -0
  51. package/dist/memory-router/index.js +122 -0
  52. package/dist/memory-router/index.js.map +1 -0
  53. package/dist/memory-router/routing-tables.d.ts +125 -0
  54. package/dist/memory-router/routing-tables.d.ts.map +1 -0
  55. package/dist/memory-router/routing-tables.js +137 -0
  56. package/dist/memory-router/routing-tables.js.map +1 -0
  57. package/dist/memory-router/select-backend.d.ts +136 -0
  58. package/dist/memory-router/select-backend.d.ts.map +1 -0
  59. package/dist/memory-router/select-backend.js +210 -0
  60. package/dist/memory-router/select-backend.js.map +1 -0
  61. package/dist/multi-stage-guardrails/index.d.ts +190 -0
  62. package/dist/multi-stage-guardrails/index.d.ts.map +1 -0
  63. package/dist/multi-stage-guardrails/index.js +186 -0
  64. package/dist/multi-stage-guardrails/index.js.map +1 -0
  65. package/dist/read-router/ReadRouter.d.ts +58 -0
  66. package/dist/read-router/ReadRouter.d.ts.map +1 -0
  67. package/dist/read-router/ReadRouter.js +91 -0
  68. package/dist/read-router/ReadRouter.js.map +1 -0
  69. package/dist/read-router/classifier.d.ts +54 -0
  70. package/dist/read-router/classifier.d.ts.map +1 -0
  71. package/dist/read-router/classifier.js +104 -0
  72. package/dist/read-router/classifier.js.map +1 -0
  73. package/dist/read-router/costs.d.ts +23 -0
  74. package/dist/read-router/costs.d.ts.map +1 -0
  75. package/dist/read-router/costs.js +51 -0
  76. package/dist/read-router/costs.js.map +1 -0
  77. package/dist/read-router/dispatcher.d.ts +33 -0
  78. package/dist/read-router/dispatcher.d.ts.map +1 -0
  79. package/dist/read-router/dispatcher.js +29 -0
  80. package/dist/read-router/dispatcher.js.map +1 -0
  81. package/dist/read-router/index.d.ts +23 -0
  82. package/dist/read-router/index.d.ts.map +1 -0
  83. package/dist/read-router/index.js +17 -0
  84. package/dist/read-router/index.js.map +1 -0
  85. package/dist/read-router/routing-tables.d.ts +85 -0
  86. package/dist/read-router/routing-tables.d.ts.map +1 -0
  87. package/dist/read-router/routing-tables.js +79 -0
  88. package/dist/read-router/routing-tables.js.map +1 -0
  89. package/dist/read-router/select-strategy.d.ts +42 -0
  90. package/dist/read-router/select-strategy.d.ts.map +1 -0
  91. package/dist/read-router/select-strategy.js +92 -0
  92. package/dist/read-router/select-strategy.js.map +1 -0
  93. package/package.json +21 -1
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @file classifier.ts
3
+ * @description LLM-as-judge classifier that maps a query+evidence pair
4
+ * to one of the five {@link ReadIntent} values.
5
+ *
6
+ * @module @framers/agentos/read-router/classifier
7
+ */
8
+ import { READ_INTENTS } from './routing-tables.js';
9
+ // ============================================================================
10
+ // Prompts
11
+ // ============================================================================
12
+ export const READ_INTENT_CLASSIFIER_SYSTEM_PROMPT = `You are classifying a user query (with retrieved evidence) into one of five read intents.
13
+
14
+ Return ONLY the intent token (no explanation, no quotes, no punctuation).
15
+
16
+ Intents:
17
+ - precise-fact: the user wants a specific named entity, number, date, or fact. Examples: "What is X's email?", "When was the last release?"
18
+ - multi-source-synthesis: the answer requires combining information from multiple evidence chunks. Examples: "Summarize all the topics we discussed", "Aggregate counts across sessions."
19
+ - time-interval: the query asks about durations, orderings, or "how long ago / before / after" timing. Examples: "How many days since X?", "In what order did Y, Z, W happen?"
20
+ - preference-recommendation: the user wants tips, suggestions, advice, or recommendations grounded in their own context. Examples: "Any tips for X?", "Can you suggest Y?"
21
+ - abstention-candidate: the question may be unanswerable from the evidence. Adversarial or off-topic. Examples: "Where did I move to last year?" when no move is in evidence.`;
22
+ export const READ_INTENT_CLASSIFIER_SYSTEM_PROMPT_FEWSHOT = `You are classifying a user query (with retrieved evidence) into one of five read intents.
23
+
24
+ Return ONLY the intent token (no explanation, no quotes, no punctuation).
25
+
26
+ Intents:
27
+ - precise-fact: a specific named entity, number, date, or fact.
28
+ - multi-source-synthesis: combining information across multiple evidence chunks.
29
+ - time-interval: durations, orderings, or "how long ago".
30
+ - preference-recommendation: tips / suggestions / advice grounded in user context.
31
+ - abstention-candidate: question may be unanswerable from evidence.
32
+
33
+ Examples:
34
+
35
+ Question: What was my final boss's name in the game I played last week?
36
+ Intent: precise-fact
37
+
38
+ Question: What topics did we discuss across our last five conversations?
39
+ Intent: multi-source-synthesis
40
+
41
+ Question: How many weeks have passed since I started the new job?
42
+ Intent: time-interval
43
+
44
+ Question: Any tips for improving my morning routine?
45
+ Intent: preference-recommendation
46
+
47
+ Question: Where did I move to four years ago?
48
+ Intent: abstention-candidate`;
49
+ export const SAFE_READ_INTENT_FALLBACK = 'multi-source-synthesis';
50
+ export function normalizeReadIntentClassifierOutput(raw) {
51
+ const lines = raw.split('\n');
52
+ let firstLine = '';
53
+ for (const ln of lines) {
54
+ if (ln.trim().length > 0) {
55
+ firstLine = ln;
56
+ break;
57
+ }
58
+ }
59
+ let cleaned = firstLine.trim().toLowerCase();
60
+ cleaned = cleaned.replace(/^(intent|category|type|answer|label|class)\s*[:\-=]\s*/, '');
61
+ cleaned = cleaned.replace(/^["'`]+|["'`]+$/g, '');
62
+ cleaned = cleaned.replace(/[.,;!?]+$/g, '');
63
+ return cleaned.trim();
64
+ }
65
+ export function parseReadIntentClassifierOutput(raw) {
66
+ const cleaned = normalizeReadIntentClassifierOutput(raw);
67
+ for (const token of READ_INTENTS) {
68
+ if (cleaned === token ||
69
+ cleaned.startsWith(`${token} `) ||
70
+ cleaned.startsWith(`${token}\n`)) {
71
+ return token;
72
+ }
73
+ }
74
+ return SAFE_READ_INTENT_FALLBACK;
75
+ }
76
+ export class LLMReadIntentClassifier {
77
+ constructor(options) {
78
+ this.llm = options.llm;
79
+ this.maxTokens = options.maxTokens ?? 16;
80
+ this.maxEvidenceChars = options.maxEvidenceChars ?? 600;
81
+ }
82
+ async classify(query, evidence, options) {
83
+ const system = options?.useFewShotPrompt
84
+ ? READ_INTENT_CLASSIFIER_SYSTEM_PROMPT_FEWSHOT
85
+ : READ_INTENT_CLASSIFIER_SYSTEM_PROMPT;
86
+ const evidencePreview = evidence
87
+ .join('\n---\n')
88
+ .slice(0, this.maxEvidenceChars);
89
+ const user = `Question: ${query}\n\nEvidence (preview):\n${evidencePreview}\n\nIntent:`;
90
+ const response = await this.llm.invoke({
91
+ system,
92
+ user,
93
+ maxTokens: this.maxTokens,
94
+ temperature: 0,
95
+ });
96
+ return {
97
+ intent: parseReadIntentClassifierOutput(response.text),
98
+ tokensIn: response.tokensIn,
99
+ tokensOut: response.tokensOut,
100
+ model: response.model,
101
+ };
102
+ }
103
+ }
104
+ //# sourceMappingURL=classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../src/read-router/classifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAiDpE,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E,MAAM,CAAC,MAAM,oCAAoC,GAAG;;;;;;;;;8KAS0H,CAAC;AAE/K,MAAM,CAAC,MAAM,4CAA4C,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;6BA0B/B,CAAC;AAE9B,MAAM,CAAC,MAAM,yBAAyB,GAAe,wBAAwB,CAAC;AAE9E,MAAM,UAAU,mCAAmC,CAAC,GAAW;IAC7D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,SAAS,GAAG,EAAE,CAAC;YACf,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC7C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,wDAAwD,EAAE,EAAE,CAAC,CAAC;IACxF,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,GAAW;IACzD,MAAM,OAAO,GAAG,mCAAmC,CAAC,GAAG,CAAC,CAAC;IACzD,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QACjC,IACE,OAAO,KAAK,KAAK;YACjB,OAAO,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC;YAC/B,OAAO,CAAC,UAAU,CAAC,GAAG,KAAK,IAAI,CAAC,EAChC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,yBAAyB,CAAC;AACnC,CAAC;AAaD,MAAM,OAAO,uBAAuB;IAKlC,YAAY,OAAuC;QACjD,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;QACzC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,GAAG,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,KAAa,EACb,QAA2B,EAC3B,OAA6C;QAE7C,MAAM,MAAM,GAAG,OAAO,EAAE,gBAAgB;YACtC,CAAC,CAAC,4CAA4C;YAC9C,CAAC,CAAC,oCAAoC,CAAC;QACzC,MAAM,eAAe,GAAG,QAAQ;aAC7B,IAAI,CAAC,SAAS,CAAC;aACf,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,aAAa,KAAK,4BAA4B,eAAe,aAAa,CAAC;QAExF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YACrC,MAAM;YACN,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,WAAW,EAAE,CAAC;SACf,CAAC,CAAC;QAEH,OAAO;YACL,MAAM,EAAE,+BAA+B,CAAC,QAAQ,CAAC,IAAI,CAAC;YACtD,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,KAAK,EAAE,QAAQ,CAAC,KAAK;SACtB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @file costs.ts
3
+ * @description Per-strategy cost-points for ReadRouter budget logic.
4
+ * Numbers are illustrative averages on gpt-4o reader; consumers should
5
+ * override with measurements from their own workload.
6
+ *
7
+ * @module @framers/agentos/read-router/costs
8
+ */
9
+ import type { ReadStrategyId } from './routing-tables.js';
10
+ export interface ReadStrategyCostPoint {
11
+ readonly strategy: ReadStrategyId;
12
+ readonly avgCostPerReadUsd: number;
13
+ readonly avgLatencyMs: number;
14
+ readonly callCount: number;
15
+ readonly description: string;
16
+ }
17
+ export declare const SINGLE_CALL_COST: ReadStrategyCostPoint;
18
+ export declare const TWO_CALL_EXTRACT_ANSWER_COST: ReadStrategyCostPoint;
19
+ export declare const COMMIT_VS_ABSTAIN_COST: ReadStrategyCostPoint;
20
+ export declare const VERBATIM_CITATION_COST: ReadStrategyCostPoint;
21
+ export declare const SCRATCHPAD_COST: ReadStrategyCostPoint;
22
+ export declare const DEFAULT_READ_COSTS: Readonly<Record<ReadStrategyId, ReadStrategyCostPoint>>;
23
+ //# sourceMappingURL=costs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"costs.d.ts","sourceRoot":"","sources":["../../src/read-router/costs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,gBAAgB,EAAE,qBAMJ,CAAC;AAE5B,eAAO,MAAM,4BAA4B,EAAE,qBAMhB,CAAC;AAE5B,eAAO,MAAM,sBAAsB,EAAE,qBAMV,CAAC;AAE5B,eAAO,MAAM,sBAAsB,EAAE,qBAMV,CAAC;AAE5B,eAAO,MAAM,eAAe,EAAE,qBAMH,CAAC;AAE5B,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,MAAM,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAO7C,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @file costs.ts
3
+ * @description Per-strategy cost-points for ReadRouter budget logic.
4
+ * Numbers are illustrative averages on gpt-4o reader; consumers should
5
+ * override with measurements from their own workload.
6
+ *
7
+ * @module @framers/agentos/read-router/costs
8
+ */
9
+ export const SINGLE_CALL_COST = Object.freeze({
10
+ strategy: 'single-call',
11
+ avgCostPerReadUsd: 0.0150,
12
+ avgLatencyMs: 1500,
13
+ callCount: 1,
14
+ description: 'one reader.invoke call',
15
+ });
16
+ export const TWO_CALL_EXTRACT_ANSWER_COST = Object.freeze({
17
+ strategy: 'two-call-extract-answer',
18
+ avgCostPerReadUsd: 0.0280,
19
+ avgLatencyMs: 2900,
20
+ callCount: 2,
21
+ description: 'extract-then-answer: claim extraction call + answer call',
22
+ });
23
+ export const COMMIT_VS_ABSTAIN_COST = Object.freeze({
24
+ strategy: 'commit-vs-abstain',
25
+ avgCostPerReadUsd: 0.0220,
26
+ avgLatencyMs: 2200,
27
+ callCount: 2,
28
+ description: 'binary commit/abstain decision + answer-or-refuse call',
29
+ });
30
+ export const VERBATIM_CITATION_COST = Object.freeze({
31
+ strategy: 'verbatim-citation',
32
+ avgCostPerReadUsd: 0.0170,
33
+ avgLatencyMs: 1700,
34
+ callCount: 1,
35
+ description: 'single call with verbatim-citation prompt rule',
36
+ });
37
+ export const SCRATCHPAD_COST = Object.freeze({
38
+ strategy: 'scratchpad-then-answer',
39
+ avgCostPerReadUsd: 0.0190,
40
+ avgLatencyMs: 1900,
41
+ callCount: 1,
42
+ description: 'single call with explicit scratchpad-before-answer scaffold',
43
+ });
44
+ export const DEFAULT_READ_COSTS = Object.freeze({
45
+ 'single-call': SINGLE_CALL_COST,
46
+ 'two-call-extract-answer': TWO_CALL_EXTRACT_ANSWER_COST,
47
+ 'commit-vs-abstain': COMMIT_VS_ABSTAIN_COST,
48
+ 'verbatim-citation': VERBATIM_CITATION_COST,
49
+ 'scratchpad-then-answer': SCRATCHPAD_COST,
50
+ });
51
+ //# sourceMappingURL=costs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"costs.js","sourceRoot":"","sources":["../../src/read-router/costs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,MAAM,CAAC,MAAM,gBAAgB,GAA0B,MAAM,CAAC,MAAM,CAAC;IACnE,QAAQ,EAAE,aAAsB;IAChC,iBAAiB,EAAE,MAAM;IACzB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,wBAAwB;CACtC,CAA0B,CAAC;AAE5B,MAAM,CAAC,MAAM,4BAA4B,GAA0B,MAAM,CAAC,MAAM,CAAC;IAC/E,QAAQ,EAAE,yBAAkC;IAC5C,iBAAiB,EAAE,MAAM;IACzB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,0DAA0D;CACxE,CAA0B,CAAC;AAE5B,MAAM,CAAC,MAAM,sBAAsB,GAA0B,MAAM,CAAC,MAAM,CAAC;IACzE,QAAQ,EAAE,mBAA4B;IACtC,iBAAiB,EAAE,MAAM;IACzB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,wDAAwD;CACtE,CAA0B,CAAC;AAE5B,MAAM,CAAC,MAAM,sBAAsB,GAA0B,MAAM,CAAC,MAAM,CAAC;IACzE,QAAQ,EAAE,mBAA4B;IACtC,iBAAiB,EAAE,MAAM;IACzB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,gDAAgD;CAC9D,CAA0B,CAAC;AAE5B,MAAM,CAAC,MAAM,eAAe,GAA0B,MAAM,CAAC,MAAM,CAAC;IAClE,QAAQ,EAAE,wBAAiC;IAC3C,iBAAiB,EAAE,MAAM;IACzB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,6DAA6D;CAC3E,CAA0B,CAAC;AAE5B,MAAM,CAAC,MAAM,kBAAkB,GAE3B,MAAM,CAAC,MAAM,CAAC;IAChB,aAAa,EAAE,gBAAgB;IAC/B,yBAAyB,EAAE,4BAA4B;IACvD,mBAAmB,EAAE,sBAAsB;IAC3C,mBAAmB,EAAE,sBAAsB;IAC3C,wBAAwB,EAAE,eAAe;CAC1C,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @file dispatcher.ts
3
+ * @description Per-strategy execution layer for ReadRouter. Same
4
+ * registry-of-functions pattern as ingest-router and memory-router.
5
+ *
6
+ * @module @framers/agentos/read-router/dispatcher
7
+ */
8
+ import type { ReadStrategyId } from './routing-tables.js';
9
+ export type ReadStrategyExecutor<TOutcome, TPayload = undefined> = (query: string, evidence: readonly string[], payload: TPayload) => Promise<TOutcome>;
10
+ export interface ReadDispatchArgs<TPayload = undefined> {
11
+ readonly strategy: ReadStrategyId;
12
+ readonly query: string;
13
+ readonly evidence: readonly string[];
14
+ readonly payload?: TPayload;
15
+ }
16
+ export interface ReadDispatchResult<TOutcome> {
17
+ readonly outcome: TOutcome;
18
+ readonly strategy: ReadStrategyId;
19
+ }
20
+ export interface IReadDispatcher<TOutcome = unknown, TPayload = unknown> {
21
+ dispatch(args: ReadDispatchArgs<TPayload>): Promise<ReadDispatchResult<TOutcome>>;
22
+ }
23
+ export declare class UnsupportedReadStrategyError extends Error {
24
+ readonly strategy: ReadStrategyId;
25
+ constructor(strategy: ReadStrategyId);
26
+ }
27
+ export type ReadStrategyRegistry<TOutcome, TPayload> = Partial<Record<ReadStrategyId, ReadStrategyExecutor<TOutcome, TPayload>>>;
28
+ export declare class FunctionReadDispatcher<TOutcome, TPayload = undefined> implements IReadDispatcher<TOutcome, TPayload> {
29
+ private readonly registry;
30
+ constructor(registry: ReadStrategyRegistry<TOutcome, TPayload>);
31
+ dispatch(args: ReadDispatchArgs<TPayload>): Promise<ReadDispatchResult<TOutcome>>;
32
+ }
33
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/read-router/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,MAAM,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,IAAI,CACjE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,OAAO,EAAE,QAAQ,KACd,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB,MAAM,WAAW,gBAAgB,CAAC,QAAQ,GAAG,SAAS;IACpD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB,CAAC,QAAQ;IAC1C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;CACnC;AAED,MAAM,WAAW,eAAe,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IACrE,QAAQ,CACN,IAAI,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GAC/B,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;CAC1C;AAED,qBAAa,4BAA6B,SAAQ,KAAK;aACzB,QAAQ,EAAE,cAAc;gBAAxB,QAAQ,EAAE,cAAc;CAOrD;AAED,MAAM,MAAM,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,IAAI,OAAO,CAC5D,MAAM,CAAC,cAAc,EAAE,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CACjE,CAAC;AAEF,qBAAa,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAChE,YAAW,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;gBAExD,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAIxD,QAAQ,CACZ,IAAI,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GAC/B,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;CAYzC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @file dispatcher.ts
3
+ * @description Per-strategy execution layer for ReadRouter. Same
4
+ * registry-of-functions pattern as ingest-router and memory-router.
5
+ *
6
+ * @module @framers/agentos/read-router/dispatcher
7
+ */
8
+ export class UnsupportedReadStrategyError extends Error {
9
+ constructor(strategy) {
10
+ super(`ReadDispatcher: strategy '${strategy}' is not registered. ` +
11
+ `Supply an executor for this strategy at construction.`);
12
+ this.strategy = strategy;
13
+ this.name = 'UnsupportedReadStrategyError';
14
+ }
15
+ }
16
+ export class FunctionReadDispatcher {
17
+ constructor(registry) {
18
+ this.registry = registry;
19
+ }
20
+ async dispatch(args) {
21
+ const exec = this.registry[args.strategy];
22
+ if (!exec) {
23
+ throw new UnsupportedReadStrategyError(args.strategy);
24
+ }
25
+ const outcome = await exec(args.query, args.evidence, args.payload);
26
+ return { outcome, strategy: args.strategy };
27
+ }
28
+ }
29
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/read-router/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4BH,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrD,YAA4B,QAAwB;QAClD,KAAK,CACH,6BAA6B,QAAQ,uBAAuB;YAC1D,uDAAuD,CAC1D,CAAC;QAJwB,aAAQ,GAAR,QAAQ,CAAgB;QAKlD,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;IAC7C,CAAC;CACF;AAMD,MAAM,OAAO,sBAAsB;IAKjC,YAAY,QAAkD;QAC5D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,IAAgC;QAEhC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,4BAA4B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CACxB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAmB,CACzB,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9C,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * AgentOS ReadRouter Module
3
+ *
4
+ * Read-stage LLM-as-judge orchestrator that picks a reader strategy per
5
+ * query+evidence pair. Sibling of {@link IngestRouter} (input-stage),
6
+ * {@link MemoryRouter} (recall-stage), and the output-stage guardrails.
7
+ *
8
+ * @module @framers/agentos/read-router
9
+ */
10
+ export type { ReadIntent, ReadStrategyId, ReadRouterPreset, ReadRoutingTable, } from './routing-tables.js';
11
+ export { READ_INTENTS } from './routing-tables.js';
12
+ export type { ReadStrategyCostPoint } from './costs.js';
13
+ export type { ReadBudgetMode, ReadRouterConfig, ReadRoutingDecision, } from './select-strategy.js';
14
+ export type { IReadIntentClassifier, IReadIntentClassifierLLM, ReadIntentClassifierLLMRequest, ReadIntentClassifierLLMResponse, ReadIntentClassifierClassifyOptions, ReadIntentClassifierResult, LLMReadIntentClassifierOptions, } from './classifier.js';
15
+ export type { IReadDispatcher, ReadDispatchArgs, ReadDispatchResult, ReadStrategyExecutor, ReadStrategyRegistry, } from './dispatcher.js';
16
+ export type { ReadBudgetPolicy, ReadRouterOptions, ReadRouterDecideOptions, ReadRouterDecision, ReadRouterDispatchedResult, } from './ReadRouter.js';
17
+ export { PRECISE_FACT_TABLE, SYNTHESIS_TABLE, TEMPORAL_TABLE, PRESET_READ_TABLES, } from './routing-tables.js';
18
+ export { SINGLE_CALL_COST, TWO_CALL_EXTRACT_ANSWER_COST, COMMIT_VS_ABSTAIN_COST, VERBATIM_CITATION_COST, SCRATCHPAD_COST, DEFAULT_READ_COSTS, } from './costs.js';
19
+ export { selectReadStrategy, ReadRouterUnknownIntentError, ReadRouterBudgetExceededError, } from './select-strategy.js';
20
+ export { READ_INTENT_CLASSIFIER_SYSTEM_PROMPT, READ_INTENT_CLASSIFIER_SYSTEM_PROMPT_FEWSHOT, SAFE_READ_INTENT_FALLBACK, LLMReadIntentClassifier, normalizeReadIntentClassifierOutput, parseReadIntentClassifierOutput, } from './classifier.js';
21
+ export { FunctionReadDispatcher, UnsupportedReadStrategyError, } from './dispatcher.js';
22
+ export { ReadRouter, ReadRouterDispatcherMissingError, } from './ReadRouter.js';
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/read-router/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,8BAA8B,EAC9B,+BAA+B,EAC/B,mCAAmC,EACnC,0BAA0B,EAC1B,8BAA8B,GAC/B,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,oCAAoC,EACpC,4CAA4C,EAC5C,yBAAyB,EACzB,uBAAuB,EACvB,mCAAmC,EACnC,+BAA+B,GAChC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,UAAU,EACV,gCAAgC,GACjC,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * AgentOS ReadRouter Module
3
+ *
4
+ * Read-stage LLM-as-judge orchestrator that picks a reader strategy per
5
+ * query+evidence pair. Sibling of {@link IngestRouter} (input-stage),
6
+ * {@link MemoryRouter} (recall-stage), and the output-stage guardrails.
7
+ *
8
+ * @module @framers/agentos/read-router
9
+ */
10
+ export { READ_INTENTS } from './routing-tables.js';
11
+ export { PRECISE_FACT_TABLE, SYNTHESIS_TABLE, TEMPORAL_TABLE, PRESET_READ_TABLES, } from './routing-tables.js';
12
+ export { SINGLE_CALL_COST, TWO_CALL_EXTRACT_ANSWER_COST, COMMIT_VS_ABSTAIN_COST, VERBATIM_CITATION_COST, SCRATCHPAD_COST, DEFAULT_READ_COSTS, } from './costs.js';
13
+ export { selectReadStrategy, ReadRouterUnknownIntentError, ReadRouterBudgetExceededError, } from './select-strategy.js';
14
+ export { READ_INTENT_CLASSIFIER_SYSTEM_PROMPT, READ_INTENT_CLASSIFIER_SYSTEM_PROMPT_FEWSHOT, SAFE_READ_INTENT_FALLBACK, LLMReadIntentClassifier, normalizeReadIntentClassifierOutput, parseReadIntentClassifierOutput, } from './classifier.js';
15
+ export { FunctionReadDispatcher, UnsupportedReadStrategyError, } from './dispatcher.js';
16
+ export { ReadRouter, ReadRouterDispatcherMissingError, } from './ReadRouter.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/read-router/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAoCnD,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,oCAAoC,EACpC,4CAA4C,EAC5C,yBAAyB,EACzB,uBAAuB,EACvB,mCAAmC,EACnC,+BAA+B,GAChC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,UAAU,EACV,gCAAgC,GACjC,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @file routing-tables.ts
3
+ * @description Preset routing tables for {@link ReadRouter}.
4
+ *
5
+ * ReadRouter is the read-stage sibling of MemoryRouter (recall-stage)
6
+ * and IngestRouter (input-stage). It picks a reader strategy after
7
+ * retrieval has produced candidate evidence — single-call generation
8
+ * vs two-call extract-then-answer (Emergence pattern) vs commit-vs-
9
+ * abstain (explicit binary decision before answer) vs verbatim citation
10
+ * vs scratchpad-then-answer (chain-of-thought-lite for temporal questions).
11
+ *
12
+ * @module @framers/agentos/read-router/routing-tables
13
+ */
14
+ export declare const READ_INTENTS: readonly ["precise-fact", "multi-source-synthesis", "time-interval", "preference-recommendation", "abstention-candidate"];
15
+ /**
16
+ * Why the user is reading. Determines the optimal reader strategy.
17
+ *
18
+ * - `precise-fact`: a specific named entity / number / date is wanted.
19
+ * Reader should commit to a single best fact from the evidence.
20
+ * - `multi-source-synthesis`: requires combining evidence from multiple
21
+ * chunks. Two-call extract-then-answer often beats single-call here.
22
+ * - `time-interval`: durations / orderings / "how long ago" questions.
23
+ * Scratchpad-then-answer (compute interval inline before final answer)
24
+ * beats single-call on these.
25
+ * - `preference-recommendation`: "any tips for X" / "do you have ideas".
26
+ * Reader must reference user-specific context from the evidence;
27
+ * single-call with a personalization rule works.
28
+ * - `abstention-candidate`: question is likely unanswerable from the
29
+ * evidence (adversarial, off-topic). Commit-vs-abstain forces the
30
+ * reader to pick refuse-or-commit explicitly before generating prose.
31
+ */
32
+ export type ReadIntent = (typeof READ_INTENTS)[number];
33
+ /**
34
+ * Reader strategies. Different prompt scaffolds + call counts.
35
+ *
36
+ * - `single-call`: one reader.invoke call. Cheapest, fastest. Default
37
+ * for precise-fact and preference-recommendation intents.
38
+ * - `two-call-extract-answer`: first call extracts relevant claims from
39
+ * evidence; second call answers using the extracted claims. Reduces
40
+ * distractor influence on multi-source synthesis. Emergence Simple
41
+ * pattern.
42
+ * - `commit-vs-abstain`: an explicit upfront binary judgment ("can this
43
+ * evidence answer the question? yes/no") before generating prose.
44
+ * Reduces over-commit on abstention-candidate questions.
45
+ * - `verbatim-citation`: appends a verbatim-citation rule to the system
46
+ * prompt for KU/SSU-style questions where the answer should be a
47
+ * direct quote from the evidence.
48
+ * - `scratchpad-then-answer`: writes a short scratchpad before the final
49
+ * answer line. Best for temporal-reasoning where date arithmetic
50
+ * benefits from explicit reasoning.
51
+ */
52
+ export type ReadStrategyId = 'single-call' | 'two-call-extract-answer' | 'commit-vs-abstain' | 'verbatim-citation' | 'scratchpad-then-answer';
53
+ export type ReadRouterPreset = 'precise-fact' | 'synthesis' | 'temporal';
54
+ export interface ReadRoutingTable {
55
+ readonly preset: ReadRouterPreset;
56
+ readonly defaultMapping: Readonly<Record<ReadIntent, ReadStrategyId>>;
57
+ }
58
+ /**
59
+ * Preset: precise-fact (default for fact-recall workloads).
60
+ *
61
+ * Precise facts get single-call (cheap, accurate when evidence is clear).
62
+ * Synthesis gets two-call extract-then-answer. Time intervals get
63
+ * scratchpad. Preferences get single-call. Abstention candidates get the
64
+ * explicit commit-vs-abstain decision.
65
+ */
66
+ export declare const PRECISE_FACT_TABLE: ReadRoutingTable;
67
+ /**
68
+ * Preset: synthesis (synthesis-heavy workloads).
69
+ *
70
+ * Routes more aggressively to two-call extract-then-answer for both
71
+ * synthesis and precise-fact (the extract pass cleans up noisy evidence).
72
+ * Verbatim citation for KU/SSU-style precise facts to reduce paraphrase
73
+ * loss. Higher cost, higher fidelity.
74
+ */
75
+ export declare const SYNTHESIS_TABLE: ReadRoutingTable;
76
+ /**
77
+ * Preset: temporal (time-heavy workloads).
78
+ *
79
+ * Almost everything goes through scratchpad-then-answer because the
80
+ * scratchpad's date-arithmetic discipline transfers to non-temporal
81
+ * questions about WHEN events happened.
82
+ */
83
+ export declare const TEMPORAL_TABLE: ReadRoutingTable;
84
+ export declare const PRESET_READ_TABLES: Readonly<Record<ReadRouterPreset, ReadRoutingTable>>;
85
+ //# sourceMappingURL=routing-tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-tables.d.ts","sourceRoot":"","sources":["../../src/read-router/routing-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,YAAY,2HAMf,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,yBAAyB,GACzB,mBAAmB,GACnB,mBAAmB,GACnB,wBAAwB,CAAC;AAE7B,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,WAAW,GACX,UAAU,CAAC;AAEf,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC;CACvE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBASX,CAAC;AAEvB;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,gBASR,CAAC;AAEvB;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,gBASP,CAAC;AAEvB,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAK1C,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @file routing-tables.ts
3
+ * @description Preset routing tables for {@link ReadRouter}.
4
+ *
5
+ * ReadRouter is the read-stage sibling of MemoryRouter (recall-stage)
6
+ * and IngestRouter (input-stage). It picks a reader strategy after
7
+ * retrieval has produced candidate evidence — single-call generation
8
+ * vs two-call extract-then-answer (Emergence pattern) vs commit-vs-
9
+ * abstain (explicit binary decision before answer) vs verbatim citation
10
+ * vs scratchpad-then-answer (chain-of-thought-lite for temporal questions).
11
+ *
12
+ * @module @framers/agentos/read-router/routing-tables
13
+ */
14
+ export const READ_INTENTS = [
15
+ 'precise-fact',
16
+ 'multi-source-synthesis',
17
+ 'time-interval',
18
+ 'preference-recommendation',
19
+ 'abstention-candidate',
20
+ ];
21
+ /**
22
+ * Preset: precise-fact (default for fact-recall workloads).
23
+ *
24
+ * Precise facts get single-call (cheap, accurate when evidence is clear).
25
+ * Synthesis gets two-call extract-then-answer. Time intervals get
26
+ * scratchpad. Preferences get single-call. Abstention candidates get the
27
+ * explicit commit-vs-abstain decision.
28
+ */
29
+ export const PRECISE_FACT_TABLE = Object.freeze({
30
+ preset: 'precise-fact',
31
+ defaultMapping: Object.freeze({
32
+ 'precise-fact': 'single-call',
33
+ 'multi-source-synthesis': 'two-call-extract-answer',
34
+ 'time-interval': 'scratchpad-then-answer',
35
+ 'preference-recommendation': 'single-call',
36
+ 'abstention-candidate': 'commit-vs-abstain',
37
+ }),
38
+ });
39
+ /**
40
+ * Preset: synthesis (synthesis-heavy workloads).
41
+ *
42
+ * Routes more aggressively to two-call extract-then-answer for both
43
+ * synthesis and precise-fact (the extract pass cleans up noisy evidence).
44
+ * Verbatim citation for KU/SSU-style precise facts to reduce paraphrase
45
+ * loss. Higher cost, higher fidelity.
46
+ */
47
+ export const SYNTHESIS_TABLE = Object.freeze({
48
+ preset: 'synthesis',
49
+ defaultMapping: Object.freeze({
50
+ 'precise-fact': 'verbatim-citation',
51
+ 'multi-source-synthesis': 'two-call-extract-answer',
52
+ 'time-interval': 'scratchpad-then-answer',
53
+ 'preference-recommendation': 'two-call-extract-answer',
54
+ 'abstention-candidate': 'commit-vs-abstain',
55
+ }),
56
+ });
57
+ /**
58
+ * Preset: temporal (time-heavy workloads).
59
+ *
60
+ * Almost everything goes through scratchpad-then-answer because the
61
+ * scratchpad's date-arithmetic discipline transfers to non-temporal
62
+ * questions about WHEN events happened.
63
+ */
64
+ export const TEMPORAL_TABLE = Object.freeze({
65
+ preset: 'temporal',
66
+ defaultMapping: Object.freeze({
67
+ 'precise-fact': 'scratchpad-then-answer',
68
+ 'multi-source-synthesis': 'scratchpad-then-answer',
69
+ 'time-interval': 'scratchpad-then-answer',
70
+ 'preference-recommendation': 'single-call',
71
+ 'abstention-candidate': 'commit-vs-abstain',
72
+ }),
73
+ });
74
+ export const PRESET_READ_TABLES = Object.freeze({
75
+ 'precise-fact': PRECISE_FACT_TABLE,
76
+ synthesis: SYNTHESIS_TABLE,
77
+ temporal: TEMPORAL_TABLE,
78
+ });
79
+ //# sourceMappingURL=routing-tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-tables.js","sourceRoot":"","sources":["../../src/read-router/routing-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,cAAc;IACd,wBAAwB;IACxB,eAAe;IACf,2BAA2B;IAC3B,sBAAsB;CACd,CAAC;AAyDX;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAqB,MAAM,CAAC,MAAM,CAAC;IAChE,MAAM,EAAE,cAAuB;IAC/B,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,cAAc,EAAE,aAAa;QAC7B,wBAAwB,EAAE,yBAAyB;QACnD,eAAe,EAAE,wBAAwB;QACzC,2BAA2B,EAAE,aAAa;QAC1C,sBAAsB,EAAE,mBAAmB;KAC5C,CAAC;CACH,CAAqB,CAAC;AAEvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC7D,MAAM,EAAE,WAAoB;IAC5B,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,cAAc,EAAE,mBAAmB;QACnC,wBAAwB,EAAE,yBAAyB;QACnD,eAAe,EAAE,wBAAwB;QACzC,2BAA2B,EAAE,yBAAyB;QACtD,sBAAsB,EAAE,mBAAmB;KAC5C,CAAC;CACH,CAAqB,CAAC;AAEvB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC5D,MAAM,EAAE,UAAmB;IAC3B,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,cAAc,EAAE,wBAAwB;QACxC,wBAAwB,EAAE,wBAAwB;QAClD,eAAe,EAAE,wBAAwB;QACzC,2BAA2B,EAAE,aAAa;QAC1C,sBAAsB,EAAE,mBAAmB;KAC5C,CAAC;CACH,CAAqB,CAAC;AAEvB,MAAM,CAAC,MAAM,kBAAkB,GAE3B,MAAM,CAAC,MAAM,CAAC;IAChB,cAAc,EAAE,kBAAkB;IAClC,SAAS,EAAE,eAAe;IAC1B,QAAQ,EAAE,cAAc;CACzB,CAAC,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @file select-strategy.ts
3
+ * @description Pure selection function for ReadRouter. Mirrors the
4
+ * memory-router and ingest-router patterns.
5
+ *
6
+ * @module @framers/agentos/read-router/select-strategy
7
+ */
8
+ import type { ReadStrategyCostPoint } from './costs.js';
9
+ import type { ReadIntent, ReadRouterPreset, ReadRoutingTable, ReadStrategyId } from './routing-tables.js';
10
+ export type ReadBudgetMode = 'hard' | 'soft' | 'cheapest-fallback';
11
+ export interface ReadRouterConfig {
12
+ readonly table: ReadRoutingTable;
13
+ readonly budgetPerReadUsd: number | null;
14
+ readonly budgetMode: ReadBudgetMode;
15
+ readonly strategyCosts: Readonly<Record<ReadStrategyId, ReadStrategyCostPoint>>;
16
+ }
17
+ export interface ReadRoutingDecision {
18
+ readonly predictedIntent: ReadIntent;
19
+ readonly groundTruthIntent: ReadIntent | null;
20
+ readonly chosenStrategy: ReadStrategyId;
21
+ readonly chosenStrategyReason: string;
22
+ readonly estimatedCostUsd: number;
23
+ readonly budgetCeiling: number | null;
24
+ readonly budgetExceeded: boolean;
25
+ readonly preset: ReadRouterPreset;
26
+ }
27
+ export declare class ReadRouterUnknownIntentError extends Error {
28
+ readonly intent: string;
29
+ constructor(intent: string);
30
+ }
31
+ export declare class ReadRouterBudgetExceededError extends Error {
32
+ readonly strategy: ReadStrategyId;
33
+ readonly cost: number;
34
+ readonly budget: number;
35
+ constructor(strategy: ReadStrategyId, cost: number, budget: number);
36
+ }
37
+ export declare function selectReadStrategy(args: {
38
+ predictedIntent: ReadIntent;
39
+ groundTruthIntent: ReadIntent | null;
40
+ config: ReadRouterConfig;
41
+ }): ReadRoutingDecision;
42
+ //# sourceMappingURL=select-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-strategy.d.ts","sourceRoot":"","sources":["../../src/read-router/select-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACf,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC,CAAC;CACjF;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAED,qBAAa,4BAA6B,SAAQ,KAAK;aACzB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAI3C;AAED,qBAAa,6BAA8B,SAAQ,KAAK;aAEpC,QAAQ,EAAE,cAAc;aACxB,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;gBAFd,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAQjC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,eAAe,EAAE,UAAU,CAAC;IAC5B,iBAAiB,EAAE,UAAU,GAAG,IAAI,CAAC;IACrC,MAAM,EAAE,gBAAgB,CAAC;CAC1B,GAAG,mBAAmB,CAoFtB"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @file select-strategy.ts
3
+ * @description Pure selection function for ReadRouter. Mirrors the
4
+ * memory-router and ingest-router patterns.
5
+ *
6
+ * @module @framers/agentos/read-router/select-strategy
7
+ */
8
+ export class ReadRouterUnknownIntentError extends Error {
9
+ constructor(intent) {
10
+ super(`ReadRouter: intent '${intent}' not in routing table`);
11
+ this.intent = intent;
12
+ this.name = 'ReadRouterUnknownIntentError';
13
+ }
14
+ }
15
+ export class ReadRouterBudgetExceededError extends Error {
16
+ constructor(strategy, cost, budget) {
17
+ super(`ReadRouter: strategy '${strategy}' cost $${cost.toFixed(4)} ` +
18
+ `exceeds hard budget $${budget.toFixed(4)}`);
19
+ this.strategy = strategy;
20
+ this.cost = cost;
21
+ this.budget = budget;
22
+ this.name = 'ReadRouterBudgetExceededError';
23
+ }
24
+ }
25
+ export function selectReadStrategy(args) {
26
+ const { predictedIntent, groundTruthIntent, config } = args;
27
+ const { table, budgetPerReadUsd, budgetMode, strategyCosts } = config;
28
+ const picked = table.defaultMapping[predictedIntent];
29
+ if (!picked) {
30
+ throw new ReadRouterUnknownIntentError(predictedIntent);
31
+ }
32
+ const pickedCost = strategyCosts[picked].avgCostPerReadUsd;
33
+ if (budgetPerReadUsd === null || pickedCost <= budgetPerReadUsd) {
34
+ return {
35
+ predictedIntent,
36
+ groundTruthIntent,
37
+ chosenStrategy: picked,
38
+ chosenStrategyReason: budgetPerReadUsd === null
39
+ ? 'routing-table pick, no budget'
40
+ : 'routing-table pick fits budget',
41
+ estimatedCostUsd: pickedCost,
42
+ budgetCeiling: budgetPerReadUsd,
43
+ budgetExceeded: false,
44
+ preset: table.preset,
45
+ };
46
+ }
47
+ if (budgetMode === 'hard') {
48
+ throw new ReadRouterBudgetExceededError(picked, pickedCost, budgetPerReadUsd);
49
+ }
50
+ const candidates = Object.values(strategyCosts).map((c) => ({
51
+ strategy: c.strategy,
52
+ cost: c.avgCostPerReadUsd,
53
+ }));
54
+ const fits = candidates.filter((c) => c.cost <= budgetPerReadUsd);
55
+ const cheapestFits = fits.length > 0 ? fits.reduce((a, b) => (a.cost <= b.cost ? a : b)) : null;
56
+ if (!cheapestFits) {
57
+ const globallyCheapest = candidates.reduce((a, b) => a.cost <= b.cost ? a : b);
58
+ return {
59
+ predictedIntent,
60
+ groundTruthIntent,
61
+ chosenStrategy: globallyCheapest.strategy,
62
+ chosenStrategyReason: 'no strategy fits budget; picking absolute cheapest',
63
+ estimatedCostUsd: globallyCheapest.cost,
64
+ budgetCeiling: budgetPerReadUsd,
65
+ budgetExceeded: true,
66
+ preset: table.preset,
67
+ };
68
+ }
69
+ if (budgetMode === 'cheapest-fallback') {
70
+ return {
71
+ predictedIntent,
72
+ groundTruthIntent,
73
+ chosenStrategy: cheapestFits.strategy,
74
+ chosenStrategyReason: 'budget downgrade (cheapest-fallback mode)',
75
+ estimatedCostUsd: cheapestFits.cost,
76
+ budgetCeiling: budgetPerReadUsd,
77
+ budgetExceeded: false,
78
+ preset: table.preset,
79
+ };
80
+ }
81
+ return {
82
+ predictedIntent,
83
+ groundTruthIntent,
84
+ chosenStrategy: picked,
85
+ chosenStrategyReason: 'soft exceed: keeping picked despite budget breach',
86
+ estimatedCostUsd: pickedCost,
87
+ budgetCeiling: budgetPerReadUsd,
88
+ budgetExceeded: true,
89
+ preset: table.preset,
90
+ };
91
+ }
92
+ //# sourceMappingURL=select-strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-strategy.js","sourceRoot":"","sources":["../../src/read-router/select-strategy.ts"],"names":[],"mappings":"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"}