@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,37 @@
1
+ /**
2
+ * AgentOS IngestRouter Module
3
+ *
4
+ * Input-stage LLM-as-judge orchestrator for memory ingest. Sibling of
5
+ * {@link MemoryRouter} (recall-stage), {@link QueryRouter} (Q&A-stage),
6
+ * and the output-stage guardrails. Together they form the agentos
7
+ * multi-stage guardrails pattern.
8
+ *
9
+ * Where MemoryRouter picks the recall architecture for a query,
10
+ * IngestRouter picks the storage architecture for incoming content. The
11
+ * choice affects what's STORED, which downstream MemoryRouter then queries.
12
+ *
13
+ * **Architecture Overview:**
14
+ * ```
15
+ * Content stream
16
+ * │
17
+ * ▼
18
+ * ┌────────────────────────────────────────────────┐
19
+ * │ IngestRouter │
20
+ * │ classify content → pick strategy → store │
21
+ * └────────────────────────────────────────────────┘
22
+ * │ │ │
23
+ * ▼ ▼ ▼
24
+ * raw-chunks summarized observational
25
+ * fact-graph hybrid skip
26
+ * ```
27
+ *
28
+ * @module @framers/agentos/ingest-router
29
+ */
30
+ export { INGEST_CONTENT_KINDS } from './routing-tables.js';
31
+ export { RAW_CHUNKS_TABLE, SUMMARIZED_TABLE, OBSERVATIONAL_TABLE, HYBRID_TABLE, PRESET_INGEST_TABLES, } from './routing-tables.js';
32
+ export { RAW_CHUNKS_COST, SUMMARIZED_COST, OBSERVATIONAL_COST, FACT_GRAPH_COST, HYBRID_COST, SKIP_COST, DEFAULT_INGEST_COSTS, } from './costs.js';
33
+ export { selectIngestStrategy, IngestRouterUnknownKindError, IngestRouterBudgetExceededError, } from './select-strategy.js';
34
+ export { INGEST_CLASSIFIER_SYSTEM_PROMPT, INGEST_CLASSIFIER_SYSTEM_PROMPT_FEWSHOT, SAFE_INGEST_FALLBACK_KIND, LLMIngestClassifier, normalizeIngestClassifierOutput, parseIngestClassifierOutput, } from './classifier.js';
35
+ export { FunctionIngestDispatcher, UnsupportedIngestStrategyError, } from './dispatcher.js';
36
+ export { IngestRouter, IngestRouterDispatcherMissingError, } from './IngestRouter.js';
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ingest-router/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAQH,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAoC3D,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,SAAS,EACT,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,+BAA+B,EAC/B,uCAAuC,EACvC,yBAAyB,EACzB,mBAAmB,EACnB,+BAA+B,EAC/B,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,YAAY,EACZ,kCAAkC,GACnC,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @file routing-tables.ts
3
+ * @description Preset routing tables for {@link IngestRouter}.
4
+ *
5
+ * IngestRouter is the input-stage sibling of MemoryRouter. Where MemoryRouter
6
+ * picks the recall architecture for a query, IngestRouter picks the storage
7
+ * architecture for incoming content. The choice affects what's STORED, which
8
+ * downstream MemoryRouter then queries.
9
+ *
10
+ * Four shipping presets express different cost-vs-recall priorities:
11
+ *
12
+ * - {@link RAW_CHUNKS_TABLE}: stores everything as raw chunks. Cheapest at
13
+ * ingest time. Pushes all complexity to retrieval. Default for cost-
14
+ * sensitive workloads.
15
+ * - {@link SUMMARIZED_TABLE}: applies session/article summarization on long
16
+ * content. Anthropic-style "contextual retrieval" — every chunk gets a
17
+ * dense session-summary prefix before embedding.
18
+ * - {@link OBSERVATIONAL_TABLE}: extracts observation logs (Mastra-style)
19
+ * from long conversational content. Most expensive at ingest, best for
20
+ * multi-session synthesis recall.
21
+ * - {@link HYBRID_TABLE}: applies multiple ingest strategies in parallel
22
+ * for long content (raw chunks + summary + observations). Highest cost,
23
+ * highest recall flexibility — every retrieval strategy has its substrate.
24
+ *
25
+ * @module @framers/agentos/ingest-router/routing-tables
26
+ */
27
+ /**
28
+ * The six content kinds the LLM-as-judge ingest classifier can emit.
29
+ * Coarse taxonomy chosen to map cleanly onto distinct ingest strategies —
30
+ * extending the taxonomy means extending the routing tables consistently.
31
+ */
32
+ export declare const INGEST_CONTENT_KINDS: readonly ["short-conversation", "long-conversation", "long-article", "code", "structured-data", "multimodal"];
33
+ export type IngestContentKind = (typeof INGEST_CONTENT_KINDS)[number];
34
+ /**
35
+ * The six storage strategies an IngestDispatcher can execute.
36
+ *
37
+ * - `raw-chunks`: standard turn-by-turn (or semantic) chunking, no LLM at
38
+ * ingest. The Memory.remember() default.
39
+ * - `summarized`: every chunk prepended with a dense session/document
40
+ * summary before embedding (Anthropic Sep 2024 "contextual retrieval").
41
+ * One LLM summarize call per session/document at ingest time.
42
+ * - `observational`: extract a structured observation log from the content
43
+ * (Mastra Observational Memory pattern). Multiple LLM extraction calls
44
+ * per session at ingest time. Recalled traces are observations rather
45
+ * than raw turns.
46
+ * - `fact-graph`: extract atomic fact triples from the content (Mem0-style).
47
+ * LLM-triple-extraction at ingest. Recall queries the fact graph.
48
+ * - `hybrid`: apply multiple strategies in parallel (e.g., raw-chunks +
49
+ * summarized + observational). Most expensive at ingest. Highest recall
50
+ * flexibility.
51
+ * - `skip`: do not ingest the content. For low-value session noise that
52
+ * wastes recall slots and inflates retrieval cost.
53
+ */
54
+ export type IngestStrategyId = 'raw-chunks' | 'summarized' | 'observational' | 'fact-graph' | 'hybrid' | 'skip';
55
+ /**
56
+ * The shipping preset names. Each names a cost-vs-recall point.
57
+ */
58
+ export type IngestRouterPreset = 'raw-chunks' | 'summarized' | 'observational' | 'hybrid';
59
+ /**
60
+ * A routing table maps every {@link IngestContentKind} to its preferred
61
+ * {@link IngestStrategyId}. Tables are frozen so consumers cannot mutate
62
+ * the routing surface from outside the module.
63
+ */
64
+ export interface IngestRoutingTable {
65
+ readonly preset: IngestRouterPreset;
66
+ readonly defaultMapping: Readonly<Record<IngestContentKind, IngestStrategyId>>;
67
+ }
68
+ /**
69
+ * Preset: raw-chunks (default for cost-sensitive workloads).
70
+ *
71
+ * Stores everything as raw chunks regardless of content kind. Zero LLM
72
+ * cost at ingest time. All complexity is pushed to retrieval where the
73
+ * MemoryRouter can compose hybrid retrieval over the raw chunks.
74
+ *
75
+ * Recommended when: ingest volume is high, retrieval-side compute is
76
+ * cheap, and you trust the retrieval stage to do the heavy lifting.
77
+ */
78
+ export declare const RAW_CHUNKS_TABLE: IngestRoutingTable;
79
+ /**
80
+ * Preset: summarized (contextual retrieval for long content).
81
+ *
82
+ * Long content (long-conversation, long-article) gets a session/document
83
+ * summary prepended to every chunk before embedding. Short content stays
84
+ * as raw chunks. Code and structured data are summarized for the
85
+ * cross-file context. Multimodal stays raw — embedding modality is
86
+ * orthogonal to summarization.
87
+ *
88
+ * Recommended when: documents and conversations have meaningful global
89
+ * context that improves retrieval recall.
90
+ */
91
+ export declare const SUMMARIZED_TABLE: IngestRoutingTable;
92
+ /**
93
+ * Preset: observational (Mastra-style for multi-session synthesis).
94
+ *
95
+ * Long conversational content (long-conversation) becomes a structured
96
+ * observation log via LLM extraction at ingest. Long articles get the
97
+ * cheaper summarized treatment. Short content, code, structured, and
98
+ * multimodal stay raw.
99
+ *
100
+ * Recommended when: workload is conversational and includes many
101
+ * multi-session synthesis questions ("what have we agreed to so far",
102
+ * "across our chats, what topics recur").
103
+ */
104
+ export declare const OBSERVATIONAL_TABLE: IngestRoutingTable;
105
+ /**
106
+ * Preset: hybrid (maximum-recall workloads).
107
+ *
108
+ * Applies multiple ingest strategies in parallel for long content. Every
109
+ * downstream retrieval architecture has its substrate (raw chunks for
110
+ * canonical hybrid, summary prefix for contextual retrieval, observation
111
+ * log for OM-style synthesis). Highest cost at ingest; highest flexibility
112
+ * at retrieval.
113
+ *
114
+ * Recommended when: cost-per-ingest is acceptable AND retrieval workload
115
+ * is heterogeneous enough that no single strategy dominates.
116
+ */
117
+ export declare const HYBRID_TABLE: IngestRoutingTable;
118
+ /**
119
+ * Preset registry keyed by name.
120
+ */
121
+ export declare const PRESET_INGEST_TABLES: Readonly<Record<IngestRouterPreset, IngestRoutingTable>>;
122
+ //# sourceMappingURL=routing-tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-tables.d.ts","sourceRoot":"","sources":["../../src/ingest-router/routing-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,+GAOvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,gBAAgB,GACxB,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,QAAQ,GACR,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,QAAQ,CAAC;AAEb;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAC/B,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAC5C,CAAC;CACH;AAMD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE,kBAUP,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,kBAUP,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBAUV,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,kBAUH,CAAC;AAEzB;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CACzC,MAAM,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAM9C,CAAC"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * @file routing-tables.ts
3
+ * @description Preset routing tables for {@link IngestRouter}.
4
+ *
5
+ * IngestRouter is the input-stage sibling of MemoryRouter. Where MemoryRouter
6
+ * picks the recall architecture for a query, IngestRouter picks the storage
7
+ * architecture for incoming content. The choice affects what's STORED, which
8
+ * downstream MemoryRouter then queries.
9
+ *
10
+ * Four shipping presets express different cost-vs-recall priorities:
11
+ *
12
+ * - {@link RAW_CHUNKS_TABLE}: stores everything as raw chunks. Cheapest at
13
+ * ingest time. Pushes all complexity to retrieval. Default for cost-
14
+ * sensitive workloads.
15
+ * - {@link SUMMARIZED_TABLE}: applies session/article summarization on long
16
+ * content. Anthropic-style "contextual retrieval" — every chunk gets a
17
+ * dense session-summary prefix before embedding.
18
+ * - {@link OBSERVATIONAL_TABLE}: extracts observation logs (Mastra-style)
19
+ * from long conversational content. Most expensive at ingest, best for
20
+ * multi-session synthesis recall.
21
+ * - {@link HYBRID_TABLE}: applies multiple ingest strategies in parallel
22
+ * for long content (raw chunks + summary + observations). Highest cost,
23
+ * highest recall flexibility — every retrieval strategy has its substrate.
24
+ *
25
+ * @module @framers/agentos/ingest-router/routing-tables
26
+ */
27
+ // ============================================================================
28
+ // Types
29
+ // ============================================================================
30
+ /**
31
+ * The six content kinds the LLM-as-judge ingest classifier can emit.
32
+ * Coarse taxonomy chosen to map cleanly onto distinct ingest strategies —
33
+ * extending the taxonomy means extending the routing tables consistently.
34
+ */
35
+ export const INGEST_CONTENT_KINDS = [
36
+ 'short-conversation',
37
+ 'long-conversation',
38
+ 'long-article',
39
+ 'code',
40
+ 'structured-data',
41
+ 'multimodal',
42
+ ];
43
+ // ============================================================================
44
+ // Preset tables
45
+ // ============================================================================
46
+ /**
47
+ * Preset: raw-chunks (default for cost-sensitive workloads).
48
+ *
49
+ * Stores everything as raw chunks regardless of content kind. Zero LLM
50
+ * cost at ingest time. All complexity is pushed to retrieval where the
51
+ * MemoryRouter can compose hybrid retrieval over the raw chunks.
52
+ *
53
+ * Recommended when: ingest volume is high, retrieval-side compute is
54
+ * cheap, and you trust the retrieval stage to do the heavy lifting.
55
+ */
56
+ export const RAW_CHUNKS_TABLE = Object.freeze({
57
+ preset: 'raw-chunks',
58
+ defaultMapping: Object.freeze({
59
+ 'short-conversation': 'raw-chunks',
60
+ 'long-conversation': 'raw-chunks',
61
+ 'long-article': 'raw-chunks',
62
+ code: 'raw-chunks',
63
+ 'structured-data': 'raw-chunks',
64
+ multimodal: 'raw-chunks',
65
+ }),
66
+ });
67
+ /**
68
+ * Preset: summarized (contextual retrieval for long content).
69
+ *
70
+ * Long content (long-conversation, long-article) gets a session/document
71
+ * summary prepended to every chunk before embedding. Short content stays
72
+ * as raw chunks. Code and structured data are summarized for the
73
+ * cross-file context. Multimodal stays raw — embedding modality is
74
+ * orthogonal to summarization.
75
+ *
76
+ * Recommended when: documents and conversations have meaningful global
77
+ * context that improves retrieval recall.
78
+ */
79
+ export const SUMMARIZED_TABLE = Object.freeze({
80
+ preset: 'summarized',
81
+ defaultMapping: Object.freeze({
82
+ 'short-conversation': 'raw-chunks',
83
+ 'long-conversation': 'summarized',
84
+ 'long-article': 'summarized',
85
+ code: 'summarized',
86
+ 'structured-data': 'raw-chunks',
87
+ multimodal: 'raw-chunks',
88
+ }),
89
+ });
90
+ /**
91
+ * Preset: observational (Mastra-style for multi-session synthesis).
92
+ *
93
+ * Long conversational content (long-conversation) becomes a structured
94
+ * observation log via LLM extraction at ingest. Long articles get the
95
+ * cheaper summarized treatment. Short content, code, structured, and
96
+ * multimodal stay raw.
97
+ *
98
+ * Recommended when: workload is conversational and includes many
99
+ * multi-session synthesis questions ("what have we agreed to so far",
100
+ * "across our chats, what topics recur").
101
+ */
102
+ export const OBSERVATIONAL_TABLE = Object.freeze({
103
+ preset: 'observational',
104
+ defaultMapping: Object.freeze({
105
+ 'short-conversation': 'raw-chunks',
106
+ 'long-conversation': 'observational',
107
+ 'long-article': 'summarized',
108
+ code: 'raw-chunks',
109
+ 'structured-data': 'raw-chunks',
110
+ multimodal: 'raw-chunks',
111
+ }),
112
+ });
113
+ /**
114
+ * Preset: hybrid (maximum-recall workloads).
115
+ *
116
+ * Applies multiple ingest strategies in parallel for long content. Every
117
+ * downstream retrieval architecture has its substrate (raw chunks for
118
+ * canonical hybrid, summary prefix for contextual retrieval, observation
119
+ * log for OM-style synthesis). Highest cost at ingest; highest flexibility
120
+ * at retrieval.
121
+ *
122
+ * Recommended when: cost-per-ingest is acceptable AND retrieval workload
123
+ * is heterogeneous enough that no single strategy dominates.
124
+ */
125
+ export const HYBRID_TABLE = Object.freeze({
126
+ preset: 'hybrid',
127
+ defaultMapping: Object.freeze({
128
+ 'short-conversation': 'raw-chunks',
129
+ 'long-conversation': 'hybrid',
130
+ 'long-article': 'hybrid',
131
+ code: 'summarized',
132
+ 'structured-data': 'raw-chunks',
133
+ multimodal: 'raw-chunks',
134
+ }),
135
+ });
136
+ /**
137
+ * Preset registry keyed by name.
138
+ */
139
+ export const PRESET_INGEST_TABLES = Object.freeze({
140
+ 'raw-chunks': RAW_CHUNKS_TABLE,
141
+ summarized: SUMMARIZED_TABLE,
142
+ observational: OBSERVATIONAL_TABLE,
143
+ hybrid: HYBRID_TABLE,
144
+ });
145
+ //# sourceMappingURL=routing-tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-tables.js","sourceRoot":"","sources":["../../src/ingest-router/routing-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,+EAA+E;AAC/E,QAAQ;AACR,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,oBAAoB;IACpB,mBAAmB;IACnB,cAAc;IACd,MAAM;IACN,iBAAiB;IACjB,YAAY;CACJ,CAAC;AAqDX,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAuB,MAAM,CAAC,MAAM,CAAC;IAChE,MAAM,EAAE,YAAqB;IAC7B,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,oBAAoB,EAAE,YAAY;QAClC,mBAAmB,EAAE,YAAY;QACjC,cAAc,EAAE,YAAY;QAC5B,IAAI,EAAE,YAAY;QAClB,iBAAiB,EAAE,YAAY;QAC/B,UAAU,EAAE,YAAY;KACzB,CAAC;CACH,CAAuB,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAuB,MAAM,CAAC,MAAM,CAAC;IAChE,MAAM,EAAE,YAAqB;IAC7B,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,oBAAoB,EAAE,YAAY;QAClC,mBAAmB,EAAE,YAAY;QACjC,cAAc,EAAE,YAAY;QAC5B,IAAI,EAAE,YAAY;QAClB,iBAAiB,EAAE,YAAY;QAC/B,UAAU,EAAE,YAAY;KACzB,CAAC;CACH,CAAuB,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAuB,MAAM,CAAC,MAAM,CAAC;IACnE,MAAM,EAAE,eAAwB;IAChC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,oBAAoB,EAAE,YAAY;QAClC,mBAAmB,EAAE,eAAe;QACpC,cAAc,EAAE,YAAY;QAC5B,IAAI,EAAE,YAAY;QAClB,iBAAiB,EAAE,YAAY;QAC/B,UAAU,EAAE,YAAY;KACzB,CAAC;CACH,CAAuB,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,YAAY,GAAuB,MAAM,CAAC,MAAM,CAAC;IAC5D,MAAM,EAAE,QAAiB;IACzB,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,oBAAoB,EAAE,YAAY;QAClC,mBAAmB,EAAE,QAAQ;QAC7B,cAAc,EAAE,QAAQ;QACxB,IAAI,EAAE,YAAY;QAClB,iBAAiB,EAAE,YAAY;QAC/B,UAAU,EAAE,YAAY;KACzB,CAAC;CACH,CAAuB,CAAC;AAEzB;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAE7B,MAAM,CAAC,MAAM,CAAC;IAChB,YAAY,EAAE,gBAAgB;IAC9B,UAAU,EAAE,gBAAgB;IAC5B,aAAa,EAAE,mBAAmB;IAClC,MAAM,EAAE,YAAY;CACrB,CAAC,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @file select-strategy.ts
3
+ * @description Pure function that picks an ingest strategy from a
4
+ * predicted content kind + routing table + budget policy.
5
+ *
6
+ * Stateless. Deterministic. No I/O. Same shape as
7
+ * {@link selectBackend} in memory-router so the multi-stage guardrails
8
+ * orchestrator can compose them uniformly.
9
+ *
10
+ * @module @framers/agentos/ingest-router/select-strategy
11
+ */
12
+ import type { IngestStrategyCostPoint } from './costs.js';
13
+ import type { IngestContentKind, IngestRouterPreset, IngestRoutingTable, IngestStrategyId } from './routing-tables.js';
14
+ /**
15
+ * Budget enforcement modes for ingest dispatch:
16
+ * - `hard`: throw {@link IngestRouterBudgetExceededError} if the
17
+ * routing-table pick exceeds the per-ingest USD ceiling.
18
+ * - `soft`: keep the picked strategy when the ceiling is exceeded
19
+ * (best-effort enforcement; flag exceeded in the decision).
20
+ * - `cheapest-fallback`: silently downgrade to the cheapest strategy
21
+ * that fits. If none fits, pick the absolute cheapest and flag.
22
+ */
23
+ export type IngestBudgetMode = 'hard' | 'soft' | 'cheapest-fallback';
24
+ /**
25
+ * Configuration object for {@link selectIngestStrategy}.
26
+ */
27
+ export interface IngestRouterConfig {
28
+ readonly table: IngestRoutingTable;
29
+ readonly budgetPerIngestUsd: number | null;
30
+ readonly budgetMode: IngestBudgetMode;
31
+ readonly strategyCosts: Readonly<Record<IngestStrategyId, IngestStrategyCostPoint>>;
32
+ }
33
+ /**
34
+ * Output of {@link selectIngestStrategy}. Carries the chosen strategy
35
+ * plus full telemetry about how the decision was made.
36
+ */
37
+ export interface IngestRoutingDecision {
38
+ readonly predictedKind: IngestContentKind;
39
+ /** Optional ground-truth kind (telemetry only; null in production). */
40
+ readonly groundTruthKind: IngestContentKind | null;
41
+ readonly chosenStrategy: IngestStrategyId;
42
+ readonly chosenStrategyReason: string;
43
+ readonly estimatedCostUsd: number;
44
+ readonly budgetCeiling: number | null;
45
+ readonly budgetExceeded: boolean;
46
+ readonly preset: IngestRouterPreset;
47
+ }
48
+ export declare class IngestRouterUnknownKindError extends Error {
49
+ readonly kind: string;
50
+ constructor(kind: string);
51
+ }
52
+ export declare class IngestRouterBudgetExceededError extends Error {
53
+ readonly strategy: IngestStrategyId;
54
+ readonly cost: number;
55
+ readonly budget: number;
56
+ constructor(strategy: IngestStrategyId, cost: number, budget: number);
57
+ }
58
+ /**
59
+ * Pure ingest-strategy selection. Mirrors selectBackend (memory-router)
60
+ * in structure for multi-stage composability.
61
+ */
62
+ export declare function selectIngestStrategy(args: {
63
+ predictedKind: IngestContentKind;
64
+ groundTruthKind: IngestContentKind | null;
65
+ config: IngestRouterConfig;
66
+ }): IngestRoutingDecision;
67
+ //# sourceMappingURL=select-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-strategy.d.ts","sourceRoot":"","sources":["../../src/ingest-router/select-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAC9B,MAAM,CAAC,gBAAgB,EAAE,uBAAuB,CAAC,CAClD,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAC;IAC1C,uEAAuE;IACvE,QAAQ,CAAC,eAAe,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,cAAc,EAAE,gBAAgB,CAAC;IAC1C,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,kBAAkB,CAAC;CACrC;AAED,qBAAa,4BAA6B,SAAQ,KAAK;aACzB,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;CAIzC;AAED,qBAAa,+BAAgC,SAAQ,KAAK;aAEtC,QAAQ,EAAE,gBAAgB;aAC1B,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;gBAFd,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAQjC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,aAAa,EAAE,iBAAiB,CAAC;IACjC,eAAe,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,MAAM,EAAE,kBAAkB,CAAC;CAC5B,GAAG,qBAAqB,CAsFxB"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @file select-strategy.ts
3
+ * @description Pure function that picks an ingest strategy from a
4
+ * predicted content kind + routing table + budget policy.
5
+ *
6
+ * Stateless. Deterministic. No I/O. Same shape as
7
+ * {@link selectBackend} in memory-router so the multi-stage guardrails
8
+ * orchestrator can compose them uniformly.
9
+ *
10
+ * @module @framers/agentos/ingest-router/select-strategy
11
+ */
12
+ export class IngestRouterUnknownKindError extends Error {
13
+ constructor(kind) {
14
+ super(`IngestRouter: kind '${kind}' not in routing table`);
15
+ this.kind = kind;
16
+ this.name = 'IngestRouterUnknownKindError';
17
+ }
18
+ }
19
+ export class IngestRouterBudgetExceededError extends Error {
20
+ constructor(strategy, cost, budget) {
21
+ super(`IngestRouter: strategy '${strategy}' cost $${cost.toFixed(4)} ` +
22
+ `exceeds hard budget $${budget.toFixed(4)}`);
23
+ this.strategy = strategy;
24
+ this.cost = cost;
25
+ this.budget = budget;
26
+ this.name = 'IngestRouterBudgetExceededError';
27
+ }
28
+ }
29
+ /**
30
+ * Pure ingest-strategy selection. Mirrors selectBackend (memory-router)
31
+ * in structure for multi-stage composability.
32
+ */
33
+ export function selectIngestStrategy(args) {
34
+ const { predictedKind, groundTruthKind, config } = args;
35
+ const { table, budgetPerIngestUsd, budgetMode, strategyCosts } = config;
36
+ const picked = table.defaultMapping[predictedKind];
37
+ if (!picked) {
38
+ throw new IngestRouterUnknownKindError(predictedKind);
39
+ }
40
+ const pickedCost = strategyCosts[picked].avgCostPerIngest;
41
+ if (budgetPerIngestUsd === null || pickedCost <= budgetPerIngestUsd) {
42
+ return {
43
+ predictedKind,
44
+ groundTruthKind,
45
+ chosenStrategy: picked,
46
+ chosenStrategyReason: budgetPerIngestUsd === null
47
+ ? 'routing-table pick, no budget'
48
+ : 'routing-table pick fits budget',
49
+ estimatedCostUsd: pickedCost,
50
+ budgetCeiling: budgetPerIngestUsd,
51
+ budgetExceeded: false,
52
+ preset: table.preset,
53
+ };
54
+ }
55
+ if (budgetMode === 'hard') {
56
+ throw new IngestRouterBudgetExceededError(picked, pickedCost, budgetPerIngestUsd);
57
+ }
58
+ const candidates = Object.values(strategyCosts).map((c) => ({ strategy: c.strategy, cost: c.avgCostPerIngest }));
59
+ const fits = candidates.filter((c) => c.cost <= budgetPerIngestUsd);
60
+ const cheapestFits = fits.length > 0
61
+ ? fits.reduce((a, b) => (a.cost <= b.cost ? a : b))
62
+ : null;
63
+ if (!cheapestFits) {
64
+ const globallyCheapest = candidates.reduce((a, b) => a.cost <= b.cost ? a : b);
65
+ return {
66
+ predictedKind,
67
+ groundTruthKind,
68
+ chosenStrategy: globallyCheapest.strategy,
69
+ chosenStrategyReason: 'no strategy fits budget; picking absolute cheapest',
70
+ estimatedCostUsd: globallyCheapest.cost,
71
+ budgetCeiling: budgetPerIngestUsd,
72
+ budgetExceeded: true,
73
+ preset: table.preset,
74
+ };
75
+ }
76
+ if (budgetMode === 'cheapest-fallback') {
77
+ return {
78
+ predictedKind,
79
+ groundTruthKind,
80
+ chosenStrategy: cheapestFits.strategy,
81
+ chosenStrategyReason: 'budget downgrade (cheapest-fallback mode)',
82
+ estimatedCostUsd: cheapestFits.cost,
83
+ budgetCeiling: budgetPerIngestUsd,
84
+ budgetExceeded: false,
85
+ preset: table.preset,
86
+ };
87
+ }
88
+ // soft: keep the pick, flag exceeded.
89
+ return {
90
+ predictedKind,
91
+ groundTruthKind,
92
+ chosenStrategy: picked,
93
+ chosenStrategyReason: 'soft exceed: keeping picked despite budget breach',
94
+ estimatedCostUsd: pickedCost,
95
+ budgetCeiling: budgetPerIngestUsd,
96
+ budgetExceeded: true,
97
+ preset: table.preset,
98
+ };
99
+ }
100
+ //# sourceMappingURL=select-strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-strategy.js","sourceRoot":"","sources":["../../src/ingest-router/select-strategy.ts"],"names":[],"mappings":"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"}