@diyor28/context 1.0.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.
Files changed (280) hide show
  1. package/README.md +270 -0
  2. package/dist/__tests__/attachment-selector.test.d.ts +11 -0
  3. package/dist/__tests__/attachment-selector.test.d.ts.map +1 -0
  4. package/dist/__tests__/attachment-selector.test.js +449 -0
  5. package/dist/__tests__/attachment-selector.test.js.map +1 -0
  6. package/dist/__tests__/cache-breakpoints.test.d.ts +11 -0
  7. package/dist/__tests__/cache-breakpoints.test.d.ts.map +1 -0
  8. package/dist/__tests__/cache-breakpoints.test.js +398 -0
  9. package/dist/__tests__/cache-breakpoints.test.js.map +1 -0
  10. package/dist/__tests__/codecs.test.d.ts +7 -0
  11. package/dist/__tests__/codecs.test.d.ts.map +1 -0
  12. package/dist/__tests__/codecs.test.js +331 -0
  13. package/dist/__tests__/codecs.test.js.map +1 -0
  14. package/dist/__tests__/compactor.test.d.ts +11 -0
  15. package/dist/__tests__/compactor.test.d.ts.map +1 -0
  16. package/dist/__tests__/compactor.test.js +519 -0
  17. package/dist/__tests__/compactor.test.js.map +1 -0
  18. package/dist/__tests__/context-graph.test.d.ts +7 -0
  19. package/dist/__tests__/context-graph.test.d.ts.map +1 -0
  20. package/dist/__tests__/context-graph.test.js +262 -0
  21. package/dist/__tests__/context-graph.test.js.map +1 -0
  22. package/dist/__tests__/hash.test.d.ts +7 -0
  23. package/dist/__tests__/hash.test.d.ts.map +1 -0
  24. package/dist/__tests__/hash.test.js +228 -0
  25. package/dist/__tests__/hash.test.js.map +1 -0
  26. package/dist/__tests__/integration.test.d.ts +15 -0
  27. package/dist/__tests__/integration.test.d.ts.map +1 -0
  28. package/dist/__tests__/integration.test.js +728 -0
  29. package/dist/__tests__/integration.test.js.map +1 -0
  30. package/dist/__tests__/kind-order.test.d.ts +7 -0
  31. package/dist/__tests__/kind-order.test.d.ts.map +1 -0
  32. package/dist/__tests__/kind-order.test.js +243 -0
  33. package/dist/__tests__/kind-order.test.js.map +1 -0
  34. package/dist/__tests__/phase2-integration.test.d.ts +5 -0
  35. package/dist/__tests__/phase2-integration.test.d.ts.map +1 -0
  36. package/dist/__tests__/phase2-integration.test.js +222 -0
  37. package/dist/__tests__/phase2-integration.test.js.map +1 -0
  38. package/dist/__tests__/queries.test.d.ts +7 -0
  39. package/dist/__tests__/queries.test.d.ts.map +1 -0
  40. package/dist/__tests__/queries.test.js +254 -0
  41. package/dist/__tests__/queries.test.js.map +1 -0
  42. package/dist/__tests__/token-estimator.test.d.ts +7 -0
  43. package/dist/__tests__/token-estimator.test.d.ts.map +1 -0
  44. package/dist/__tests__/token-estimator.test.js +267 -0
  45. package/dist/__tests__/token-estimator.test.js.map +1 -0
  46. package/dist/adapters/anthropic-estimator.d.ts +38 -0
  47. package/dist/adapters/anthropic-estimator.d.ts.map +1 -0
  48. package/dist/adapters/anthropic-estimator.js +108 -0
  49. package/dist/adapters/anthropic-estimator.js.map +1 -0
  50. package/dist/adapters/attachment-resolver.d.ts +96 -0
  51. package/dist/adapters/attachment-resolver.d.ts.map +1 -0
  52. package/dist/adapters/attachment-resolver.js +176 -0
  53. package/dist/adapters/attachment-resolver.js.map +1 -0
  54. package/dist/adapters/attachment-selector.d.ts +59 -0
  55. package/dist/adapters/attachment-selector.d.ts.map +1 -0
  56. package/dist/adapters/attachment-selector.js +163 -0
  57. package/dist/adapters/attachment-selector.js.map +1 -0
  58. package/dist/adapters/gemini-estimator.d.ts +27 -0
  59. package/dist/adapters/gemini-estimator.d.ts.map +1 -0
  60. package/dist/adapters/gemini-estimator.js +80 -0
  61. package/dist/adapters/gemini-estimator.js.map +1 -0
  62. package/dist/adapters/index.d.ts +12 -0
  63. package/dist/adapters/index.d.ts.map +1 -0
  64. package/dist/adapters/index.js +28 -0
  65. package/dist/adapters/index.js.map +1 -0
  66. package/dist/adapters/memory-store.d.ts +139 -0
  67. package/dist/adapters/memory-store.d.ts.map +1 -0
  68. package/dist/adapters/memory-store.js +187 -0
  69. package/dist/adapters/memory-store.js.map +1 -0
  70. package/dist/adapters/openai-estimator.d.ts +35 -0
  71. package/dist/adapters/openai-estimator.d.ts.map +1 -0
  72. package/dist/adapters/openai-estimator.js +89 -0
  73. package/dist/adapters/openai-estimator.js.map +1 -0
  74. package/dist/adapters/summarizer.d.ts +121 -0
  75. package/dist/adapters/summarizer.d.ts.map +1 -0
  76. package/dist/adapters/summarizer.js +121 -0
  77. package/dist/adapters/summarizer.js.map +1 -0
  78. package/dist/adapters/token-estimator.d.ts +63 -0
  79. package/dist/adapters/token-estimator.d.ts.map +1 -0
  80. package/dist/adapters/token-estimator.js +37 -0
  81. package/dist/adapters/token-estimator.js.map +1 -0
  82. package/dist/builder/context-builder.d.ts +186 -0
  83. package/dist/builder/context-builder.d.ts.map +1 -0
  84. package/dist/builder/context-builder.js +305 -0
  85. package/dist/builder/context-builder.js.map +1 -0
  86. package/dist/builder/context-fork.d.ts +166 -0
  87. package/dist/builder/context-fork.d.ts.map +1 -0
  88. package/dist/builder/context-fork.js +282 -0
  89. package/dist/builder/context-fork.js.map +1 -0
  90. package/dist/builder/index.d.ts +6 -0
  91. package/dist/builder/index.d.ts.map +1 -0
  92. package/dist/builder/index.js +22 -0
  93. package/dist/builder/index.js.map +1 -0
  94. package/dist/codecs/base.d.ts +18 -0
  95. package/dist/codecs/base.d.ts.map +1 -0
  96. package/dist/codecs/base.js +39 -0
  97. package/dist/codecs/base.js.map +1 -0
  98. package/dist/codecs/conversation-history.codec.d.ts +81 -0
  99. package/dist/codecs/conversation-history.codec.d.ts.map +1 -0
  100. package/dist/codecs/conversation-history.codec.js +89 -0
  101. package/dist/codecs/conversation-history.codec.js.map +1 -0
  102. package/dist/codecs/index.d.ts +31 -0
  103. package/dist/codecs/index.d.ts.map +1 -0
  104. package/dist/codecs/index.js +71 -0
  105. package/dist/codecs/index.js.map +1 -0
  106. package/dist/codecs/redacted-stub.codec.d.ts +32 -0
  107. package/dist/codecs/redacted-stub.codec.d.ts.map +1 -0
  108. package/dist/codecs/redacted-stub.codec.js +64 -0
  109. package/dist/codecs/redacted-stub.codec.js.map +1 -0
  110. package/dist/codecs/structured-reference.codec.d.ts +40 -0
  111. package/dist/codecs/structured-reference.codec.d.ts.map +1 -0
  112. package/dist/codecs/structured-reference.codec.js +81 -0
  113. package/dist/codecs/structured-reference.codec.js.map +1 -0
  114. package/dist/codecs/system-rules.codec.d.ts +32 -0
  115. package/dist/codecs/system-rules.codec.d.ts.map +1 -0
  116. package/dist/codecs/system-rules.codec.js +62 -0
  117. package/dist/codecs/system-rules.codec.js.map +1 -0
  118. package/dist/codecs/tool-output.codec.d.ts +66 -0
  119. package/dist/codecs/tool-output.codec.d.ts.map +1 -0
  120. package/dist/codecs/tool-output.codec.js +95 -0
  121. package/dist/codecs/tool-output.codec.js.map +1 -0
  122. package/dist/codecs/tool-schema.codec.d.ts +36 -0
  123. package/dist/codecs/tool-schema.codec.d.ts.map +1 -0
  124. package/dist/codecs/tool-schema.codec.js +74 -0
  125. package/dist/codecs/tool-schema.codec.js.map +1 -0
  126. package/dist/codecs/unsafe-text.codec.d.ts +28 -0
  127. package/dist/codecs/unsafe-text.codec.d.ts.map +1 -0
  128. package/dist/codecs/unsafe-text.codec.js +63 -0
  129. package/dist/codecs/unsafe-text.codec.js.map +1 -0
  130. package/dist/graph/context-graph.d.ts +121 -0
  131. package/dist/graph/context-graph.d.ts.map +1 -0
  132. package/dist/graph/context-graph.js +166 -0
  133. package/dist/graph/context-graph.js.map +1 -0
  134. package/dist/graph/index.d.ts +8 -0
  135. package/dist/graph/index.d.ts.map +1 -0
  136. package/dist/graph/index.js +24 -0
  137. package/dist/graph/index.js.map +1 -0
  138. package/dist/graph/kind-order.d.ts +60 -0
  139. package/dist/graph/kind-order.d.ts.map +1 -0
  140. package/dist/graph/kind-order.js +113 -0
  141. package/dist/graph/kind-order.js.map +1 -0
  142. package/dist/graph/queries.d.ts +68 -0
  143. package/dist/graph/queries.d.ts.map +1 -0
  144. package/dist/graph/queries.js +240 -0
  145. package/dist/graph/queries.js.map +1 -0
  146. package/dist/graph/views.d.ts +90 -0
  147. package/dist/graph/views.d.ts.map +1 -0
  148. package/dist/graph/views.js +173 -0
  149. package/dist/graph/views.js.map +1 -0
  150. package/dist/index.d.ts +16 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +40 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/pipeline/compactor.d.ts +128 -0
  155. package/dist/pipeline/compactor.d.ts.map +1 -0
  156. package/dist/pipeline/compactor.js +346 -0
  157. package/dist/pipeline/compactor.js.map +1 -0
  158. package/dist/pipeline/index.d.ts +6 -0
  159. package/dist/pipeline/index.d.ts.map +1 -0
  160. package/dist/pipeline/index.js +22 -0
  161. package/dist/pipeline/index.js.map +1 -0
  162. package/dist/pipeline/summarizer.d.ts +18 -0
  163. package/dist/pipeline/summarizer.d.ts.map +1 -0
  164. package/dist/pipeline/summarizer.js +68 -0
  165. package/dist/pipeline/summarizer.js.map +1 -0
  166. package/dist/policies/default-policy.d.ts +29 -0
  167. package/dist/policies/default-policy.d.ts.map +1 -0
  168. package/dist/policies/default-policy.js +58 -0
  169. package/dist/policies/default-policy.js.map +1 -0
  170. package/dist/policies/index.d.ts +5 -0
  171. package/dist/policies/index.d.ts.map +1 -0
  172. package/dist/policies/index.js +21 -0
  173. package/dist/policies/index.js.map +1 -0
  174. package/dist/providers/anthropic-compiler.d.ts +58 -0
  175. package/dist/providers/anthropic-compiler.d.ts.map +1 -0
  176. package/dist/providers/anthropic-compiler.js +182 -0
  177. package/dist/providers/anthropic-compiler.js.map +1 -0
  178. package/dist/providers/capabilities.d.ts +54 -0
  179. package/dist/providers/capabilities.d.ts.map +1 -0
  180. package/dist/providers/capabilities.js +87 -0
  181. package/dist/providers/capabilities.js.map +1 -0
  182. package/dist/providers/gemini-compiler.d.ts +51 -0
  183. package/dist/providers/gemini-compiler.d.ts.map +1 -0
  184. package/dist/providers/gemini-compiler.js +206 -0
  185. package/dist/providers/gemini-compiler.js.map +1 -0
  186. package/dist/providers/index.d.ts +8 -0
  187. package/dist/providers/index.d.ts.map +1 -0
  188. package/dist/providers/index.js +24 -0
  189. package/dist/providers/index.js.map +1 -0
  190. package/dist/providers/openai-compiler.d.ts +46 -0
  191. package/dist/providers/openai-compiler.d.ts.map +1 -0
  192. package/dist/providers/openai-compiler.js +149 -0
  193. package/dist/providers/openai-compiler.js.map +1 -0
  194. package/dist/types/attachment.d.ts +62 -0
  195. package/dist/types/attachment.d.ts.map +1 -0
  196. package/dist/types/attachment.js +6 -0
  197. package/dist/types/attachment.js.map +1 -0
  198. package/dist/types/block.d.ts +61 -0
  199. package/dist/types/block.d.ts.map +1 -0
  200. package/dist/types/block.js +8 -0
  201. package/dist/types/block.js.map +1 -0
  202. package/dist/types/codec.d.ts +58 -0
  203. package/dist/types/codec.d.ts.map +1 -0
  204. package/dist/types/codec.js +6 -0
  205. package/dist/types/codec.js.map +1 -0
  206. package/dist/types/compiled.d.ts +91 -0
  207. package/dist/types/compiled.d.ts.map +1 -0
  208. package/dist/types/compiled.js +6 -0
  209. package/dist/types/compiled.js.map +1 -0
  210. package/dist/types/hash.d.ts +24 -0
  211. package/dist/types/hash.d.ts.map +1 -0
  212. package/dist/types/hash.js +49 -0
  213. package/dist/types/hash.js.map +1 -0
  214. package/dist/types/index.d.ts +10 -0
  215. package/dist/types/index.d.ts.map +1 -0
  216. package/dist/types/index.js +26 -0
  217. package/dist/types/index.js.map +1 -0
  218. package/dist/types/policy.d.ts +128 -0
  219. package/dist/types/policy.d.ts.map +1 -0
  220. package/dist/types/policy.js +55 -0
  221. package/dist/types/policy.js.map +1 -0
  222. package/package.json +55 -0
  223. package/postcss.config.js +4 -0
  224. package/src/__tests__/attachment-selector.test.ts +559 -0
  225. package/src/__tests__/cache-breakpoints.test.ts +566 -0
  226. package/src/__tests__/codecs.test.ts +417 -0
  227. package/src/__tests__/compactor.test.ts +608 -0
  228. package/src/__tests__/context-graph.test.ts +383 -0
  229. package/src/__tests__/hash.test.ts +274 -0
  230. package/src/__tests__/integration.test.ts +866 -0
  231. package/src/__tests__/kind-order.test.ts +312 -0
  232. package/src/__tests__/phase2-integration.test.ts +253 -0
  233. package/src/__tests__/queries.test.ts +387 -0
  234. package/src/__tests__/token-estimator.test.ts +326 -0
  235. package/src/adapters/anthropic-estimator.ts +125 -0
  236. package/src/adapters/attachment-resolver.ts +295 -0
  237. package/src/adapters/attachment-selector.ts +218 -0
  238. package/src/adapters/gemini-estimator.ts +93 -0
  239. package/src/adapters/index.ts +12 -0
  240. package/src/adapters/memory-store.ts +299 -0
  241. package/src/adapters/openai-estimator.ts +105 -0
  242. package/src/adapters/summarizer.ts +250 -0
  243. package/src/adapters/token-estimator.ts +74 -0
  244. package/src/builder/context-builder.ts +467 -0
  245. package/src/builder/context-fork.ts +471 -0
  246. package/src/builder/index.ts +6 -0
  247. package/src/codecs/base.ts +36 -0
  248. package/src/codecs/conversation-history.codec.ts +108 -0
  249. package/src/codecs/index.ts +57 -0
  250. package/src/codecs/redacted-stub.codec.ts +76 -0
  251. package/src/codecs/structured-reference.codec.ts +96 -0
  252. package/src/codecs/system-rules.codec.ts +74 -0
  253. package/src/codecs/tool-output.codec.ts +109 -0
  254. package/src/codecs/tool-schema.codec.ts +87 -0
  255. package/src/codecs/unsafe-text.codec.ts +74 -0
  256. package/src/graph/context-graph.ts +205 -0
  257. package/src/graph/index.ts +8 -0
  258. package/src/graph/kind-order.ts +125 -0
  259. package/src/graph/queries.ts +306 -0
  260. package/src/graph/views.ts +255 -0
  261. package/src/index.ts +31 -0
  262. package/src/pipeline/compactor.ts +563 -0
  263. package/src/pipeline/index.ts +6 -0
  264. package/src/pipeline/summarizer.ts +76 -0
  265. package/src/policies/default-policy.ts +69 -0
  266. package/src/policies/index.ts +5 -0
  267. package/src/providers/anthropic-compiler.ts +294 -0
  268. package/src/providers/capabilities.ts +144 -0
  269. package/src/providers/gemini-compiler.ts +272 -0
  270. package/src/providers/index.ts +8 -0
  271. package/src/providers/openai-compiler.ts +191 -0
  272. package/src/types/attachment.ts +86 -0
  273. package/src/types/block.ts +84 -0
  274. package/src/types/codec.ts +68 -0
  275. package/src/types/compiled.ts +109 -0
  276. package/src/types/hash.ts +58 -0
  277. package/src/types/index.ts +10 -0
  278. package/src/types/policy.ts +194 -0
  279. package/tsconfig.json +21 -0
  280. package/vitest.config.ts +21 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Provider compiler exports.
3
+ */
4
+
5
+ export * from './capabilities.js';
6
+ export * from './anthropic-compiler.js';
7
+ export * from './openai-compiler.js';
8
+ export * from './gemini-compiler.js';
@@ -0,0 +1,191 @@
1
+ /**
2
+ * OpenAI compiler: Pure compilation to OpenAI chat completion format.
3
+ *
4
+ * Features:
5
+ * - Inline system messages
6
+ * - Tool/function calling support
7
+ * - Structured outputs
8
+ */
9
+
10
+ import type { ContextBlock } from '../types/block.js';
11
+ import type { ContextPolicy } from '../types/policy.js';
12
+ import type { OpenAICompiledContext } from '../types/compiled.js';
13
+ import type { BlockCodec } from '../types/codec.js';
14
+ import { getProviderCapabilities } from './capabilities.js';
15
+
16
+ /**
17
+ * OpenAI compilation options.
18
+ */
19
+ export interface OpenAICompilationOptions {
20
+ /** Codec registry for rendering */
21
+ codecRegistry: Map<string, BlockCodec<unknown>>;
22
+
23
+ /** Include tool definitions (optional) */
24
+ tools?: unknown[];
25
+ }
26
+
27
+ /**
28
+ * Compile context to OpenAI chat completion format.
29
+ * Pure function: same inputs → identical outputs.
30
+ *
31
+ * @param blocks - Ordered blocks from ContextView
32
+ * @param policy - Context policy
33
+ * @param options - Compilation options
34
+ * @returns OpenAI compiled context
35
+ */
36
+ export function compileOpenAIContext(
37
+ blocks: ContextBlock[],
38
+ policy: ContextPolicy,
39
+ options: OpenAICompilationOptions
40
+ ): OpenAICompiledContext {
41
+ const capabilities = getProviderCapabilities('openai');
42
+
43
+ // Compile all blocks to messages (including system messages inline)
44
+ const messages = compileMessages(blocks, options.codecRegistry);
45
+
46
+ // Calculate tokens (simplified - would use actual estimator in production)
47
+ const estimatedTokens = blocks.length * 100; // Placeholder
48
+
49
+ return {
50
+ provider: 'openai',
51
+ modelId: policy.modelId,
52
+ messages,
53
+ estimatedTokens,
54
+ blocks,
55
+ meta: {
56
+ compiledAt: Math.floor(Date.now() / 1000),
57
+ contextWindow: policy.contextWindow,
58
+ completionReserve: policy.completionReserve,
59
+ availableTokens: policy.contextWindow - policy.completionReserve,
60
+ overflowed: false,
61
+ compacted: false,
62
+ truncated: false,
63
+ tokensByKind: {},
64
+ },
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Compile blocks to OpenAI messages.
70
+ * System messages are inlined as first messages.
71
+ *
72
+ * @param blocks - Context blocks
73
+ * @param codecRegistry - Codec registry
74
+ * @returns OpenAI messages
75
+ */
76
+ function compileMessages(
77
+ blocks: ContextBlock[],
78
+ codecRegistry: Map<string, BlockCodec<unknown>>
79
+ ): Array<{
80
+ role: 'system' | 'user' | 'assistant' | 'tool';
81
+ content: unknown;
82
+ name?: string;
83
+ tool_call_id?: string;
84
+ }> {
85
+ const messages: Array<{
86
+ role: 'system' | 'user' | 'assistant' | 'tool';
87
+ content: unknown;
88
+ name?: string;
89
+ tool_call_id?: string;
90
+ }> = [];
91
+
92
+ // Compile blocks in order
93
+ for (const block of blocks) {
94
+ const codec = codecRegistry.get(block.meta.codecId);
95
+
96
+ if (!codec) {
97
+ console.warn(`[OpenAI] Codec not found: ${block.meta.codecId}`);
98
+ continue;
99
+ }
100
+
101
+ const rendered = codec.render(block);
102
+ const openaiContent = rendered.openai as any;
103
+
104
+ // Handle different block kinds
105
+ if (block.meta.kind === 'pinned') {
106
+ // System messages
107
+ messages.push({
108
+ role: 'system',
109
+ content: openaiContent.content || openaiContent,
110
+ });
111
+ } else if (block.meta.kind === 'history') {
112
+ // History blocks are already in message format
113
+ if (Array.isArray(openaiContent)) {
114
+ messages.push(...openaiContent);
115
+ } else {
116
+ messages.push(openaiContent);
117
+ }
118
+ } else if (block.meta.kind === 'turn') {
119
+ // Turn blocks are user messages
120
+ messages.push({
121
+ role: 'user',
122
+ content: openaiContent.content || openaiContent,
123
+ });
124
+ } else if (block.meta.kind === 'tool_output') {
125
+ // Tool output blocks
126
+ messages.push({
127
+ role: 'tool',
128
+ content: typeof openaiContent === 'string'
129
+ ? openaiContent
130
+ : JSON.stringify(openaiContent),
131
+ tool_call_id: (block.payload as any).toolCallId || 'unknown',
132
+ });
133
+ } else {
134
+ // Other blocks (reference, memory, state) as user messages
135
+ messages.push({
136
+ role: 'user',
137
+ content: typeof openaiContent === 'string'
138
+ ? openaiContent
139
+ : JSON.stringify(openaiContent),
140
+ });
141
+ }
142
+ }
143
+
144
+ return messages;
145
+ }
146
+
147
+ /**
148
+ * Validate OpenAI message sequence.
149
+ * Ensures messages follow OpenAI's alternation rules.
150
+ *
151
+ * @param messages - OpenAI messages
152
+ * @returns Validation diagnostics
153
+ */
154
+ export function validateOpenAIMessages(
155
+ messages: Array<{ role: string; content: unknown }>
156
+ ): Array<{ level: 'error' | 'warning'; message: string }> {
157
+ const diagnostics: Array<{ level: 'error' | 'warning'; message: string }> = [];
158
+
159
+ // Check for empty messages
160
+ if (messages.length === 0) {
161
+ diagnostics.push({
162
+ level: 'error',
163
+ message: 'Message array is empty',
164
+ });
165
+ return diagnostics;
166
+ }
167
+
168
+ // Check for user-assistant alternation
169
+ let lastRole: string | null = null;
170
+ for (let i = 0; i < messages.length; i++) {
171
+ const msg = messages[i];
172
+
173
+ if (msg.role === 'user' && lastRole === 'user') {
174
+ diagnostics.push({
175
+ level: 'warning',
176
+ message: `Consecutive user messages at index ${i}`,
177
+ });
178
+ }
179
+
180
+ if (msg.role === 'assistant' && lastRole === 'assistant') {
181
+ diagnostics.push({
182
+ level: 'warning',
183
+ message: `Consecutive assistant messages at index ${i}`,
184
+ });
185
+ }
186
+
187
+ lastRole = msg.role;
188
+ }
189
+
190
+ return diagnostics;
191
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Attachment types for external content (images, PDFs, etc.).
3
+ */
4
+
5
+ /**
6
+ * Attachment MIME type.
7
+ */
8
+ export type AttachmentMimeType =
9
+ | 'image/png'
10
+ | 'image/jpeg'
11
+ | 'image/webp'
12
+ | 'image/gif'
13
+ | 'application/pdf'
14
+ | 'text/plain'
15
+ | 'text/markdown'
16
+ | 'application/json';
17
+
18
+ /**
19
+ * Attachment storage backend.
20
+ */
21
+ export type AttachmentStorage = 'local' | 's3' | 'gcs';
22
+
23
+ /**
24
+ * Attachment metadata.
25
+ */
26
+ export interface AttachmentMeta {
27
+ /** Attachment ID (content-addressed hash) */
28
+ attachmentId: string;
29
+
30
+ /** MIME type */
31
+ mimeType: AttachmentMimeType;
32
+
33
+ /** File size (bytes) */
34
+ sizeBytes: number;
35
+
36
+ /** Original filename (if available) */
37
+ filename?: string;
38
+
39
+ /** Storage backend */
40
+ storage: AttachmentStorage;
41
+
42
+ /** Storage path (backend-specific) */
43
+ storagePath: string;
44
+
45
+ /** Created timestamp (Unix seconds) */
46
+ createdAt: number;
47
+ }
48
+
49
+ /**
50
+ * Attachment reference in context block.
51
+ */
52
+ export interface AttachmentRef {
53
+ /** Attachment ID */
54
+ attachmentId: string;
55
+
56
+ /** Optional description/caption */
57
+ description?: string;
58
+ }
59
+
60
+ /**
61
+ * Resolved attachment with content.
62
+ */
63
+ export interface ResolvedAttachment extends AttachmentMeta {
64
+ /** Base64-encoded content (for images, PDFs) */
65
+ content?: string;
66
+
67
+ /** Text content (for text/plain, text/markdown) */
68
+ text?: string;
69
+
70
+ /** Parsed JSON content (for application/json) */
71
+ json?: unknown;
72
+ }
73
+
74
+ /**
75
+ * Attachment selection result (for token budgeting).
76
+ */
77
+ export interface AttachmentSelection {
78
+ /** Selected attachments */
79
+ selected: ResolvedAttachment[];
80
+
81
+ /** Excluded attachments (over budget) */
82
+ excluded: AttachmentRef[];
83
+
84
+ /** Total tokens consumed */
85
+ totalTokens: number;
86
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Block types for @foundry/context
3
+ *
4
+ * Core data structures for context blocks with stable hashing and ordering.
5
+ */
6
+
7
+ /**
8
+ * Block kind determines ordering in compiled context.
9
+ * Must follow KIND_ORDER for deterministic compilation.
10
+ */
11
+ export type BlockKind =
12
+ | 'pinned' // System rules, always first
13
+ | 'reference' // Tool schemas, external docs
14
+ | 'memory' // Long-term memory, RAG results
15
+ | 'state' // Current workflow/session state
16
+ | 'tool_output' // Tool execution results
17
+ | 'history' // Conversation history
18
+ | 'turn'; // Current turn (user message)
19
+
20
+ /**
21
+ * Sensitivity level for content filtering and forking.
22
+ */
23
+ export type SensitivityLevel =
24
+ | 'public' // Safe to fork to any model
25
+ | 'internal' // Contains business logic/PII
26
+ | 'restricted'; // Contains credentials/secrets
27
+
28
+ /**
29
+ * Block metadata (stable subset used for hashing).
30
+ */
31
+ export interface BlockMeta {
32
+ /** Block kind (determines ordering) */
33
+ kind: BlockKind;
34
+
35
+ /** Content sensitivity level */
36
+ sensitivity: SensitivityLevel;
37
+
38
+ /** Codec identifier for rendering */
39
+ codecId: string;
40
+
41
+ /** Codec version for rendering */
42
+ codecVersion: string;
43
+
44
+ /** Unix timestamp (seconds) */
45
+ createdAt: number;
46
+
47
+ /** Optional source identifier (workflow ID, session ID, etc.) */
48
+ source?: string;
49
+
50
+ /** Optional tags for filtering */
51
+ tags?: string[];
52
+ }
53
+
54
+ /**
55
+ * Subset of BlockMeta used for stable hashing.
56
+ * Excludes volatile fields like createdAt, source, tags.
57
+ */
58
+ export interface StableMetaSubset {
59
+ kind: BlockKind;
60
+ sensitivity: SensitivityLevel;
61
+ codecId: string;
62
+ codecVersion: string;
63
+ }
64
+
65
+ /**
66
+ * Context block with content-addressed hash.
67
+ */
68
+ export interface ContextBlock<TPayload = unknown> {
69
+ /** Content-addressed hash (computed from meta + payload) */
70
+ blockHash: string;
71
+
72
+ /** Block metadata */
73
+ meta: BlockMeta;
74
+
75
+ /** Block payload (codec-specific) */
76
+ payload: TPayload;
77
+ }
78
+
79
+ /**
80
+ * Block reference (hash only, used in compiled context).
81
+ */
82
+ export interface BlockRef {
83
+ blockHash: string;
84
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Block codec interface for rendering and validation.
3
+ */
4
+
5
+ import { z } from 'zod';
6
+ import type { ContextBlock } from './block.js';
7
+
8
+ /**
9
+ * Provider-specific rendered content.
10
+ */
11
+ export interface RenderedContent {
12
+ /** Anthropic Claude format */
13
+ anthropic?: unknown;
14
+
15
+ /** OpenAI GPT format */
16
+ openai?: unknown;
17
+
18
+ /** Google Gemini format */
19
+ gemini?: unknown;
20
+ }
21
+
22
+ /**
23
+ * Block codec for content rendering and validation.
24
+ */
25
+ export interface BlockCodec<TPayload = unknown> {
26
+ /** Unique codec identifier */
27
+ codecId: string;
28
+
29
+ /** Codec version (semver) */
30
+ version: string;
31
+
32
+ /** Payload schema for validation */
33
+ payloadSchema: z.ZodSchema<TPayload>;
34
+
35
+ /**
36
+ * Canonicalize payload for deterministic hashing.
37
+ * Must produce identical output for semantically equivalent inputs.
38
+ *
39
+ * @param payload - Raw payload
40
+ * @returns Canonicalized payload (serializable)
41
+ */
42
+ canonicalize(payload: TPayload): unknown;
43
+
44
+ /**
45
+ * Compute stable hash from canonicalized payload.
46
+ * Default: SHA-256 of JSON.stringify(canonicalized).
47
+ *
48
+ * @param canonicalized - Canonicalized payload
49
+ * @returns Hex-encoded hash
50
+ */
51
+ hash(canonicalized: unknown): string;
52
+
53
+ /**
54
+ * Render block content for provider-specific formats.
55
+ *
56
+ * @param block - Context block
57
+ * @returns Rendered content for each provider
58
+ */
59
+ render(block: ContextBlock<TPayload>): RenderedContent;
60
+
61
+ /**
62
+ * Validate payload against schema.
63
+ * Throws on validation failure.
64
+ *
65
+ * @param payload - Payload to validate
66
+ */
67
+ validate(payload: unknown): TPayload;
68
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Compiled context types for LLM provider consumption.
3
+ */
4
+
5
+ import type { ContextBlock } from './block.js';
6
+ import type { Provider } from './policy.js';
7
+ import type { ResolvedAttachment } from './attachment.js';
8
+
9
+ /**
10
+ * Compiled context for a specific provider.
11
+ */
12
+ export interface CompiledContext {
13
+ /** Target provider */
14
+ provider: Provider;
15
+
16
+ /** Model identifier */
17
+ modelId: string;
18
+
19
+ /** Provider-specific messages array */
20
+ messages: unknown[];
21
+
22
+ /** Provider-specific system message(s) */
23
+ system?: unknown;
24
+
25
+ /** Resolved attachments (if any) */
26
+ attachments?: ResolvedAttachment[];
27
+
28
+ /** Total estimated tokens */
29
+ estimatedTokens: number;
30
+
31
+ /** Blocks included in compilation */
32
+ blocks: ContextBlock[];
33
+
34
+ /** Blocks excluded (overflow, sensitivity, etc.) */
35
+ excludedBlocks?: ContextBlock[];
36
+
37
+ /** Compilation metadata */
38
+ meta: CompiledContextMeta;
39
+ }
40
+
41
+ /**
42
+ * Compilation metadata.
43
+ */
44
+ export interface CompiledContextMeta {
45
+ /** Compilation timestamp (Unix seconds) */
46
+ compiledAt: number;
47
+
48
+ /** Context window size */
49
+ contextWindow: number;
50
+
51
+ /** Completion reserve (tokens) */
52
+ completionReserve: number;
53
+
54
+ /** Available tokens (contextWindow - completionReserve) */
55
+ availableTokens: number;
56
+
57
+ /** Overflow occurred */
58
+ overflowed: boolean;
59
+
60
+ /** Compaction applied */
61
+ compacted: boolean;
62
+
63
+ /** Truncation applied */
64
+ truncated: boolean;
65
+
66
+ /** Token breakdown by block kind */
67
+ tokensByKind: Record<string, number>;
68
+ }
69
+
70
+ /**
71
+ * Anthropic-specific compiled context.
72
+ */
73
+ export interface AnthropicCompiledContext extends CompiledContext {
74
+ provider: 'anthropic';
75
+ messages: Array<{
76
+ role: 'user' | 'assistant';
77
+ content: unknown;
78
+ }>;
79
+ system?: Array<{
80
+ type: 'text';
81
+ text: string;
82
+ cache_control?: { type: 'ephemeral' };
83
+ }>;
84
+ }
85
+
86
+ /**
87
+ * OpenAI-specific compiled context.
88
+ */
89
+ export interface OpenAICompiledContext extends CompiledContext {
90
+ provider: 'openai';
91
+ messages: Array<{
92
+ role: 'system' | 'user' | 'assistant' | 'tool';
93
+ content: unknown;
94
+ name?: string;
95
+ tool_call_id?: string;
96
+ }>;
97
+ }
98
+
99
+ /**
100
+ * Gemini-specific compiled context.
101
+ */
102
+ export interface GeminiCompiledContext extends CompiledContext {
103
+ provider: 'gemini';
104
+ messages: Array<{
105
+ role: 'user' | 'model';
106
+ parts: unknown[];
107
+ }>;
108
+ system?: string;
109
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Block hashing utilities.
3
+ */
4
+
5
+ import { createHash } from 'crypto';
6
+ import type { BlockMeta, StableMetaSubset } from './block.js';
7
+ import type { BlockCodec } from './codec.js';
8
+
9
+ /**
10
+ * Extract stable metadata subset for hashing.
11
+ * Excludes volatile fields like createdAt, source, tags.
12
+ *
13
+ * @param meta - Full block metadata
14
+ * @returns Stable metadata subset
15
+ */
16
+ export function extractStableMetaSubset(meta: BlockMeta): StableMetaSubset {
17
+ return {
18
+ kind: meta.kind,
19
+ sensitivity: meta.sensitivity,
20
+ codecId: meta.codecId,
21
+ codecVersion: meta.codecVersion,
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Compute content-addressed block hash.
27
+ * Uses StableMetaSubset + codec.canonicalize(payload) for deterministic hashing.
28
+ *
29
+ * @param meta - Block metadata (or StableMetaSubset)
30
+ * @param payload - Block payload (or canonicalized payload if codec not provided)
31
+ * @param codec - Block codec for canonicalization (optional)
32
+ * @returns Hex-encoded SHA-256 hash
33
+ */
34
+ export function computeBlockHash<TPayload>(
35
+ meta: BlockMeta | StableMetaSubset,
36
+ payload: TPayload,
37
+ codec?: BlockCodec<TPayload>
38
+ ): string {
39
+ // Extract stable metadata subset (if full meta provided)
40
+ const stableMeta = 'createdAt' in meta ? extractStableMetaSubset(meta) : meta;
41
+
42
+ // Canonicalize payload (if codec provided)
43
+ const canonicalized = codec ? codec.canonicalize(payload) : payload;
44
+
45
+ // Combine stable meta + canonicalized payload
46
+ const combined = {
47
+ meta: stableMeta,
48
+ payload: canonicalized,
49
+ };
50
+
51
+ // Compute SHA-256 hash
52
+ const hash = createHash('sha256')
53
+ .update(JSON.stringify(combined))
54
+ .digest('hex');
55
+
56
+ return hash;
57
+ }
58
+
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Core types for @foundry/context
3
+ */
4
+
5
+ export * from './block.js';
6
+ export * from './codec.js';
7
+ export * from './hash.js';
8
+ export * from './policy.js';
9
+ export * from './attachment.js';
10
+ export * from './compiled.js';