@fastpaca/cria 0.0.1 → 1.0.1

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 (140) hide show
  1. package/README.md +93 -106
  2. package/dist/ai-sdk/index.d.ts +43 -0
  3. package/dist/ai-sdk/index.d.ts.map +1 -0
  4. package/dist/ai-sdk/index.js +303 -0
  5. package/dist/ai-sdk/index.js.map +1 -0
  6. package/dist/ai-sdk/index.test.d.ts +2 -0
  7. package/dist/ai-sdk/index.test.d.ts.map +1 -0
  8. package/dist/ai-sdk/index.test.js +101 -0
  9. package/dist/ai-sdk/index.test.js.map +1 -0
  10. package/dist/anthropic/index.d.ts +74 -0
  11. package/dist/anthropic/index.d.ts.map +1 -0
  12. package/dist/anthropic/index.js +238 -0
  13. package/dist/anthropic/index.js.map +1 -0
  14. package/dist/anthropic/index.test.d.ts +2 -0
  15. package/dist/anthropic/index.test.d.ts.map +1 -0
  16. package/dist/anthropic/index.test.js +115 -0
  17. package/dist/anthropic/index.test.js.map +1 -0
  18. package/dist/components/additional.test.d.ts +2 -0
  19. package/dist/components/additional.test.d.ts.map +1 -0
  20. package/dist/components/additional.test.js +31 -0
  21. package/dist/components/additional.test.js.map +1 -0
  22. package/dist/components/index.d.ts +148 -0
  23. package/dist/components/index.d.ts.map +1 -0
  24. package/dist/components/index.js +184 -0
  25. package/dist/components/index.js.map +1 -0
  26. package/dist/components/summary.d.ts +91 -0
  27. package/dist/components/summary.d.ts.map +1 -0
  28. package/dist/components/summary.js +118 -0
  29. package/dist/components/summary.js.map +1 -0
  30. package/dist/components/summary.test.d.ts +2 -0
  31. package/dist/components/summary.test.d.ts.map +1 -0
  32. package/dist/components/summary.test.js +101 -0
  33. package/dist/components/summary.test.js.map +1 -0
  34. package/dist/components/vector-search.d.ts +70 -0
  35. package/dist/components/vector-search.d.ts.map +1 -0
  36. package/dist/components/vector-search.js +110 -0
  37. package/dist/components/vector-search.js.map +1 -0
  38. package/dist/components/vector-search.test.d.ts +2 -0
  39. package/dist/components/vector-search.test.d.ts.map +1 -0
  40. package/dist/components/vector-search.test.js +113 -0
  41. package/dist/components/vector-search.test.js.map +1 -0
  42. package/dist/index.d.ts +12 -5
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +9 -5
  45. package/dist/index.js.map +1 -1
  46. package/dist/instrumentation/otel.d.ts +19 -0
  47. package/dist/instrumentation/otel.d.ts.map +1 -0
  48. package/dist/instrumentation/otel.js +102 -0
  49. package/dist/instrumentation/otel.js.map +1 -0
  50. package/dist/instrumentation/otel.test.d.ts +2 -0
  51. package/dist/instrumentation/otel.test.d.ts.map +1 -0
  52. package/dist/instrumentation/otel.test.js +116 -0
  53. package/dist/instrumentation/otel.test.js.map +1 -0
  54. package/dist/jsx-dev-runtime.d.ts +2 -0
  55. package/dist/jsx-dev-runtime.d.ts.map +1 -0
  56. package/dist/jsx-dev-runtime.js +2 -0
  57. package/dist/jsx-dev-runtime.js.map +1 -0
  58. package/dist/jsx-runtime.d.ts +30 -8
  59. package/dist/jsx-runtime.d.ts.map +1 -1
  60. package/dist/jsx-runtime.js +13 -10
  61. package/dist/jsx-runtime.js.map +1 -1
  62. package/dist/memory/chroma/index.d.ts +59 -0
  63. package/dist/memory/chroma/index.d.ts.map +1 -0
  64. package/dist/memory/chroma/index.js +172 -0
  65. package/dist/memory/chroma/index.js.map +1 -0
  66. package/dist/memory/index.d.ts +4 -0
  67. package/dist/memory/index.d.ts.map +1 -0
  68. package/dist/memory/index.js +2 -0
  69. package/dist/memory/index.js.map +1 -0
  70. package/dist/memory/key-value.d.ts +71 -0
  71. package/dist/memory/key-value.d.ts.map +1 -0
  72. package/dist/memory/key-value.js +34 -0
  73. package/dist/memory/key-value.js.map +1 -0
  74. package/dist/memory/postgres.d.ts +71 -0
  75. package/dist/memory/postgres.d.ts.map +1 -0
  76. package/dist/memory/postgres.js +109 -0
  77. package/dist/memory/postgres.js.map +1 -0
  78. package/dist/memory/qdrant/index.d.ts +64 -0
  79. package/dist/memory/qdrant/index.d.ts.map +1 -0
  80. package/dist/memory/qdrant/index.js +136 -0
  81. package/dist/memory/qdrant/index.js.map +1 -0
  82. package/dist/memory/redis.d.ts +70 -0
  83. package/dist/memory/redis.d.ts.map +1 -0
  84. package/dist/memory/redis.js +100 -0
  85. package/dist/memory/redis.js.map +1 -0
  86. package/dist/memory/vector.d.ts +53 -0
  87. package/dist/memory/vector.d.ts.map +1 -0
  88. package/dist/memory/vector.js +2 -0
  89. package/dist/memory/vector.js.map +1 -0
  90. package/dist/openai/index.d.ts +46 -0
  91. package/dist/openai/index.d.ts.map +1 -0
  92. package/dist/openai/index.js +260 -0
  93. package/dist/openai/index.js.map +1 -0
  94. package/dist/openai/index.test.d.ts +2 -0
  95. package/dist/openai/index.test.d.ts.map +1 -0
  96. package/dist/openai/index.test.js +204 -0
  97. package/dist/openai/index.test.js.map +1 -0
  98. package/dist/providers/index.d.ts +2 -0
  99. package/dist/providers/index.d.ts.map +1 -0
  100. package/dist/providers/index.js +2 -0
  101. package/dist/providers/index.js.map +1 -0
  102. package/dist/providers/types.d.ts +2 -0
  103. package/dist/providers/types.d.ts.map +1 -0
  104. package/dist/providers/types.js +2 -0
  105. package/dist/providers/types.js.map +1 -0
  106. package/dist/render.d.ts +44 -40
  107. package/dist/render.d.ts.map +1 -1
  108. package/dist/render.js +162 -148
  109. package/dist/render.js.map +1 -1
  110. package/dist/render.test.js +146 -28
  111. package/dist/render.test.js.map +1 -1
  112. package/dist/renderers/markdown.d.ts +3 -0
  113. package/dist/renderers/markdown.d.ts.map +1 -0
  114. package/dist/renderers/markdown.js +43 -0
  115. package/dist/renderers/markdown.js.map +1 -0
  116. package/dist/renderers/shared.d.ts +82 -0
  117. package/dist/renderers/shared.d.ts.map +1 -0
  118. package/dist/renderers/shared.js +156 -0
  119. package/dist/renderers/shared.js.map +1 -0
  120. package/dist/snapshot.d.ts +47 -0
  121. package/dist/snapshot.d.ts.map +1 -0
  122. package/dist/snapshot.js +140 -0
  123. package/dist/snapshot.js.map +1 -0
  124. package/dist/snapshot.test.d.ts +2 -0
  125. package/dist/snapshot.test.d.ts.map +1 -0
  126. package/dist/snapshot.test.js +68 -0
  127. package/dist/snapshot.test.js.map +1 -0
  128. package/dist/tokenizers.d.ts +14 -0
  129. package/dist/tokenizers.d.ts.map +1 -0
  130. package/dist/tokenizers.js +45 -0
  131. package/dist/tokenizers.js.map +1 -0
  132. package/dist/types.d.ts +212 -84
  133. package/dist/types.d.ts.map +1 -1
  134. package/dist/types.js +109 -0
  135. package/dist/types.js.map +1 -1
  136. package/package.json +88 -3
  137. package/dist/components.d.ts +0 -78
  138. package/dist/components.d.ts.map +0 -1
  139. package/dist/components.js +0 -98
  140. package/dist/components.js.map +0 -1
@@ -0,0 +1,148 @@
1
+ import type { Child } from "../jsx-runtime";
2
+ import type { PromptElement, PromptRole, Strategy } from "../types";
3
+ interface RegionProps {
4
+ /** Lower number = higher importance. Default: 0 (highest priority) */
5
+ priority?: number;
6
+ /** Optional strategy to apply when this region needs to shrink */
7
+ strategy?: Strategy;
8
+ /** Stable identifier for caching/debugging */
9
+ id?: string;
10
+ /** Content of this region */
11
+ children?: Child;
12
+ }
13
+ /**
14
+ * The fundamental building block of Cria prompts—think of it as `<div>`.
15
+ *
16
+ * Regions define sections of your prompt with a priority level. During fitting,
17
+ * regions with higher priority numbers (less important) are reduced first.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <Region priority={0}>You are a helpful assistant.</Region>
22
+ * <Region priority={2}>{documents}</Region>
23
+ * <Region priority={1}>{userMessage}</Region>
24
+ * ```
25
+ */
26
+ export declare function Region({ priority, strategy, id, children, }: RegionProps): PromptElement;
27
+ interface SemanticRegionProps {
28
+ /** Lower number = higher importance. Default: 0 (highest priority) */
29
+ priority?: number;
30
+ /** Optional strategy to apply when this region needs to shrink */
31
+ strategy?: Strategy;
32
+ /** Stable identifier for caching/debugging */
33
+ id?: string;
34
+ }
35
+ interface MessageProps extends SemanticRegionProps {
36
+ /** The message role (user, assistant, system, etc.) */
37
+ messageRole: PromptRole;
38
+ children?: Child;
39
+ }
40
+ export declare function Message({ messageRole, priority, strategy, id, children, }: MessageProps): PromptElement;
41
+ interface ReasoningProps extends SemanticRegionProps {
42
+ text: string;
43
+ }
44
+ export declare function Reasoning({ text, priority, strategy, id, }: ReasoningProps): PromptElement;
45
+ interface ToolCallProps extends SemanticRegionProps {
46
+ toolCallId: string;
47
+ toolName: string;
48
+ input: unknown;
49
+ }
50
+ export declare function ToolCall({ toolCallId, toolName, input, priority, strategy, id, }: ToolCallProps): PromptElement;
51
+ interface ToolResultProps extends SemanticRegionProps {
52
+ toolCallId: string;
53
+ toolName: string;
54
+ output: unknown;
55
+ }
56
+ export declare function ToolResult({ toolCallId, toolName, output, priority, strategy, id, }: ToolResultProps): PromptElement;
57
+ interface TruncateProps {
58
+ /** Maximum token count for this region's content */
59
+ budget: number;
60
+ /** Which end to truncate from. Default: "start" */
61
+ from?: "start" | "end";
62
+ /** Lower number = higher importance. Default: 0 */
63
+ priority?: number;
64
+ /** Stable identifier for caching/debugging */
65
+ id?: string;
66
+ /** Content to truncate */
67
+ children?: Child;
68
+ }
69
+ /**
70
+ * A region that truncates its content to fit within a token budget.
71
+ *
72
+ * When the overall prompt exceeds budget, Truncate regions progressively
73
+ * remove content from the specified direction until they meet their budget.
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * <Truncate budget={20000} priority={2}>
78
+ * {conversationHistory}
79
+ * </Truncate>
80
+ * ```
81
+ */
82
+ export declare function Truncate({ budget, from, priority, id, children, }: TruncateProps): PromptElement;
83
+ interface OmitProps {
84
+ /** Lower number = higher importance. Default: 0 */
85
+ priority?: number;
86
+ /** Stable identifier for caching/debugging */
87
+ id?: string;
88
+ /** Content that may be omitted */
89
+ children?: Child;
90
+ }
91
+ /**
92
+ * A region that is entirely removed when the prompt needs to shrink.
93
+ *
94
+ * Use Omit for "nice to have" content that can be dropped entirely if needed.
95
+ * When the prompt exceeds budget, Omit regions are removed (lowest priority first).
96
+ *
97
+ * @example
98
+ * ```tsx
99
+ * <Omit priority={3}>
100
+ * {optionalExamples}
101
+ * </Omit>
102
+ * ```
103
+ */
104
+ export declare function Omit({ priority, id, children, }: OmitProps): PromptElement;
105
+ interface LastProps {
106
+ /** Number of children to keep */
107
+ N: number;
108
+ /** Priority for this region. Default: 0 */
109
+ priority?: number;
110
+ /** Children to filter */
111
+ children?: Child;
112
+ }
113
+ /**
114
+ * Keeps only the last N children.
115
+ *
116
+ * @example
117
+ * ```tsx
118
+ * <Last N={50}>{messages}</Last>
119
+ * ```
120
+ */
121
+ export declare function Last({ N, priority, children, }: LastProps): PromptElement;
122
+ export type { StoredSummary, Summarizer, SummarizerContext } from "./summary";
123
+ export { Summary } from "./summary";
124
+ export type { ResultFormatter } from "./vector-search";
125
+ export { VectorSearch } from "./vector-search";
126
+ interface SeparatorProps {
127
+ value?: string;
128
+ priority?: number;
129
+ id?: string;
130
+ children?: Child;
131
+ }
132
+ export declare function Separator({ value, priority, id, children, }: SeparatorProps): PromptElement;
133
+ interface ExamplesProps {
134
+ title?: string;
135
+ separator?: string;
136
+ priority?: number;
137
+ id?: string;
138
+ children?: Child;
139
+ }
140
+ export declare function Examples({ title, separator, priority, id, children, }: ExamplesProps): PromptElement;
141
+ interface CodeBlockProps {
142
+ code: string;
143
+ language?: string;
144
+ priority?: number;
145
+ id?: string;
146
+ }
147
+ export declare function CodeBlock({ code, language, priority, id, }: CodeBlockProps): PromptElement;
148
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAEV,aAAa,EACb,UAAU,EACV,QAAQ,EACT,MAAM,UAAU,CAAC;AAElB,UAAU,WAAW;IACnB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,8CAA8C;IAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,EACrB,QAAY,EACZ,QAAQ,EACR,EAAE,EACF,QAAa,GACd,EAAE,WAAW,GAAG,aAAa,CAO7B;AAED,UAAU,mBAAmB;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,8CAA8C;IAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,UAAU,YAAa,SAAQ,mBAAmB;IAChD,uDAAuD;IACvD,WAAW,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,wBAAgB,OAAO,CAAC,EACtB,WAAW,EACX,QAAY,EACZ,QAAQ,EACR,EAAE,EACF,QAAa,GACd,EAAE,YAAY,GAAG,aAAa,CAS9B;AAED,UAAU,cAAe,SAAQ,mBAAmB;IAClD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,QAAY,EACZ,QAAQ,EACR,EAAE,GACH,EAAE,cAAc,GAAG,aAAa,CAShC;AAED,UAAU,aAAc,SAAQ,mBAAmB;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,QAAQ,CAAC,EACvB,UAAU,EACV,QAAQ,EACR,KAAK,EACL,QAAY,EACZ,QAAQ,EACR,EAAE,GACH,EAAE,aAAa,GAAG,aAAa,CAW/B;AAED,UAAU,eAAgB,SAAQ,mBAAmB;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,QAAQ,EACR,MAAM,EACN,QAAY,EACZ,QAAQ,EACR,EAAE,GACH,EAAE,eAAe,GAAG,aAAa,CAWjC;AAED,UAAU,aAAa;IACrB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACvB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,IAAc,EACd,QAAY,EACZ,EAAE,EACF,QAAa,GACd,EAAE,aAAa,GAAG,aAAa,CAgC/B;AAED,UAAU,SAAS;IACjB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,EACnB,QAAY,EACZ,EAAE,EACF,QAAa,GACd,EAAE,SAAS,GAAG,aAAa,CAS3B;AAED,UAAU,SAAS;IACjB,iCAAiC;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,EACnB,CAAC,EACD,QAAY,EACZ,QAAa,GACd,EAAE,SAAS,GAAG,aAAa,CAQ3B;AAED,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAY/C,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAY,EACZ,QAAY,EACZ,EAAE,EACF,QAAa,GACd,EAAE,cAAc,GAAG,aAAa,CAOhC;AAED,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAmB,EACnB,SAAkB,EAClB,QAAY,EACZ,EAAE,EACF,QAAa,GACd,EAAE,aAAa,GAAG,aAAa,CAa/B;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,QAAQ,EACR,QAAY,EACZ,EAAE,GACH,EAAE,cAAc,GAAG,aAAa,CAOhC"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * The fundamental building block of Cria prompts—think of it as `<div>`.
3
+ *
4
+ * Regions define sections of your prompt with a priority level. During fitting,
5
+ * regions with higher priority numbers (less important) are reduced first.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * <Region priority={0}>You are a helpful assistant.</Region>
10
+ * <Region priority={2}>{documents}</Region>
11
+ * <Region priority={1}>{userMessage}</Region>
12
+ * ```
13
+ */
14
+ export function Region({ priority = 0, strategy, id, children = [], }) {
15
+ return {
16
+ priority,
17
+ children: children,
18
+ ...(strategy && { strategy }),
19
+ ...(id && { id }),
20
+ };
21
+ }
22
+ export function Message({ messageRole, priority = 0, strategy, id, children = [], }) {
23
+ return {
24
+ kind: "message",
25
+ role: messageRole,
26
+ priority,
27
+ children: children,
28
+ ...(strategy && { strategy }),
29
+ ...(id && { id }),
30
+ };
31
+ }
32
+ export function Reasoning({ text, priority = 0, strategy, id, }) {
33
+ return {
34
+ kind: "reasoning",
35
+ text,
36
+ priority,
37
+ children: [],
38
+ ...(strategy && { strategy }),
39
+ ...(id && { id }),
40
+ };
41
+ }
42
+ export function ToolCall({ toolCallId, toolName, input, priority = 0, strategy, id, }) {
43
+ return {
44
+ kind: "tool-call",
45
+ toolCallId,
46
+ toolName,
47
+ input,
48
+ priority,
49
+ children: [],
50
+ ...(strategy && { strategy }),
51
+ ...(id && { id }),
52
+ };
53
+ }
54
+ export function ToolResult({ toolCallId, toolName, output, priority = 0, strategy, id, }) {
55
+ return {
56
+ kind: "tool-result",
57
+ toolCallId,
58
+ toolName,
59
+ output,
60
+ priority,
61
+ children: [],
62
+ ...(strategy && { strategy }),
63
+ ...(id && { id }),
64
+ };
65
+ }
66
+ /**
67
+ * A region that truncates its content to fit within a token budget.
68
+ *
69
+ * When the overall prompt exceeds budget, Truncate regions progressively
70
+ * remove content from the specified direction until they meet their budget.
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * <Truncate budget={20000} priority={2}>
75
+ * {conversationHistory}
76
+ * </Truncate>
77
+ * ```
78
+ */
79
+ export function Truncate({ budget, from = "start", priority = 0, id, children = [], }) {
80
+ const strategy = (input) => {
81
+ const content = input.tokenString(input.target);
82
+ let tokens = input.tokenizer(content);
83
+ if (tokens <= budget) {
84
+ return input.target;
85
+ }
86
+ let truncated = content;
87
+ while (tokens > budget && truncated.length > 0) {
88
+ const charsToRemove = Math.max(1, Math.floor(truncated.length * 0.1));
89
+ truncated =
90
+ from === "start"
91
+ ? truncated.slice(charsToRemove)
92
+ : truncated.slice(0, -charsToRemove);
93
+ tokens = input.tokenizer(truncated);
94
+ }
95
+ if (truncated.length === 0) {
96
+ return null;
97
+ }
98
+ return { ...input.target, children: [truncated] };
99
+ };
100
+ return {
101
+ priority,
102
+ children: children,
103
+ strategy,
104
+ ...(id && { id }),
105
+ };
106
+ }
107
+ /**
108
+ * A region that is entirely removed when the prompt needs to shrink.
109
+ *
110
+ * Use Omit for "nice to have" content that can be dropped entirely if needed.
111
+ * When the prompt exceeds budget, Omit regions are removed (lowest priority first).
112
+ *
113
+ * @example
114
+ * ```tsx
115
+ * <Omit priority={3}>
116
+ * {optionalExamples}
117
+ * </Omit>
118
+ * ```
119
+ */
120
+ export function Omit({ priority = 0, id, children = [], }) {
121
+ const strategy = () => null;
122
+ return {
123
+ priority,
124
+ children: children,
125
+ strategy,
126
+ ...(id && { id }),
127
+ };
128
+ }
129
+ /**
130
+ * Keeps only the last N children.
131
+ *
132
+ * @example
133
+ * ```tsx
134
+ * <Last N={50}>{messages}</Last>
135
+ * ```
136
+ */
137
+ export function Last({ N, priority = 0, children = [], }) {
138
+ const normalizedChildren = children;
139
+ const lastN = normalizedChildren.slice(-N);
140
+ return {
141
+ priority,
142
+ children: lastN,
143
+ };
144
+ }
145
+ export { Summary } from "./summary";
146
+ export { VectorSearch } from "./vector-search";
147
+ /**
148
+ * Intersperse a separator between elements of an array.
149
+ */
150
+ function intersperse(items, separator) {
151
+ if (items.length === 0) {
152
+ return [];
153
+ }
154
+ return items.flatMap((item, i) => (i === 0 ? [item] : [separator, item]));
155
+ }
156
+ export function Separator({ value = "\n", priority = 0, id, children = [], }) {
157
+ const normalized = children;
158
+ return {
159
+ priority,
160
+ children: intersperse(normalized, value),
161
+ ...(id && { id }),
162
+ };
163
+ }
164
+ export function Examples({ title = "Examples:", separator = "\n\n", priority = 2, id, children = [], }) {
165
+ const normalized = children;
166
+ const withSeparators = intersperse(normalized, separator);
167
+ const prefixed = title
168
+ ? [`${title}\n`, ...withSeparators]
169
+ : withSeparators;
170
+ return {
171
+ priority,
172
+ children: prefixed,
173
+ ...(id && { id }),
174
+ };
175
+ }
176
+ export function CodeBlock({ code, language, priority = 0, id, }) {
177
+ const fenced = `\`\`\`${language ?? ""}\n${code}\n\`\`\`\n`;
178
+ return {
179
+ priority,
180
+ children: [fenced],
181
+ ...(id && { id }),
182
+ };
183
+ }
184
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import type { Child } from "../jsx-runtime";
2
+ import type { KVMemory } from "../memory";
3
+ import type { MaybePromise, PromptElement } from "../types";
4
+ /**
5
+ * Stored summary data persisted across renders.
6
+ */
7
+ export interface StoredSummary {
8
+ /** The summary text content */
9
+ content: string;
10
+ /** Token count of the summary */
11
+ tokenCount: number;
12
+ }
13
+ /**
14
+ * Context passed to the summarizer function.
15
+ */
16
+ export interface SummarizerContext {
17
+ /** The content to summarize (as rendered string) */
18
+ content: string;
19
+ /** Previous summary to build upon (null if first summary) */
20
+ existingSummary: string | null;
21
+ }
22
+ /**
23
+ * Function that generates summaries.
24
+ */
25
+ export type Summarizer = (ctx: SummarizerContext) => MaybePromise<string>;
26
+ interface SummaryProps {
27
+ /** Unique identifier for this summary in the store */
28
+ id: string;
29
+ /** Storage adapter for persisting summaries */
30
+ store: KVMemory<StoredSummary>;
31
+ /**
32
+ * Function that generates summaries.
33
+ * If omitted, uses the ModelProvider from render options with a default prompt.
34
+ */
35
+ summarize?: Summarizer;
36
+ /** Priority for this region (higher number = reduced first). Default: 0 */
37
+ priority?: number;
38
+ /** Content to potentially summarize */
39
+ children?: Child;
40
+ }
41
+ /**
42
+ * A region that summarizes its content when the prompt needs to shrink.
43
+ *
44
+ * When the overall prompt exceeds budget and this region is selected for
45
+ * reduction (based on priority), the summarizer is called and the result
46
+ * replaces the original content.
47
+ *
48
+ * If no `summarize` function is provided, the component will use the
49
+ * `ModelProvider` from an ancestor provider component with a default
50
+ * summarization prompt.
51
+ *
52
+ * @example Using a custom summarizer
53
+ * ```tsx
54
+ * import { InMemoryStore, Summary, type StoredSummary } from "@fastpaca/cria";
55
+ *
56
+ * const store = new InMemoryStore<StoredSummary>();
57
+ *
58
+ * <Summary
59
+ * id="conv-history"
60
+ * store={store}
61
+ * summarize={async ({ content, existingSummary }) => {
62
+ * return callAI(`Summarize, building on: ${existingSummary}\n\n${content}`);
63
+ * }}
64
+ * priority={2}
65
+ * >
66
+ * {conversationHistory}
67
+ * </Summary>
68
+ * ```
69
+ *
70
+ * @example Using a provider component
71
+ * ```tsx
72
+ * import { InMemoryStore, Summary, type StoredSummary, render } from "@fastpaca/cria";
73
+ * import { AISDKProvider } from "@fastpaca/cria/ai-sdk";
74
+ * import { openai } from "@ai-sdk/openai";
75
+ *
76
+ * const store = new InMemoryStore<StoredSummary>();
77
+ *
78
+ * const prompt = (
79
+ * <AISDKProvider model={openai("gpt-4o")}>
80
+ * <Summary id="conv-history" store={store} priority={2}>
81
+ * {conversationHistory}
82
+ * </Summary>
83
+ * </AISDKProvider>
84
+ * );
85
+ *
86
+ * const result = await render(prompt, { tokenizer, budget: 4000 });
87
+ * ```
88
+ */
89
+ export declare function Summary({ id, store, summarize, priority, children, }: SummaryProps): PromptElement;
90
+ export {};
91
+ //# sourceMappingURL=summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/components/summary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EACV,YAAY,EAGZ,aAAa,EAGd,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,iBAAiB,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;AAwF1E,UAAU,YAAY;IACpB,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,+CAA+C;IAC/C,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,OAAO,CAAC,EACtB,EAAE,EACF,KAAK,EACL,SAAS,EACT,QAAY,EACZ,QAAa,GACd,EAAE,YAAY,GAAG,aAAa,CAM9B"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Default summarizer that uses a ModelProvider.
3
+ * This is used when no custom summarize function is provided.
4
+ */
5
+ async function defaultSummarizer(ctx, provider) {
6
+ const systemPrompt = "You are a conversation summarizer. Create a concise summary that captures the key points and context needed to continue the conversation. Be brief but preserve essential information.";
7
+ let userPrompt;
8
+ if (ctx.existingSummary) {
9
+ userPrompt = `Here is the existing summary of the conversation so far:
10
+
11
+ ${ctx.existingSummary}
12
+
13
+ Here is new conversation content to incorporate into the summary:
14
+
15
+ ${ctx.content}
16
+
17
+ Please provide an updated summary that incorporates both the existing summary and the new content.`;
18
+ }
19
+ else {
20
+ userPrompt = `Please summarize the following conversation:
21
+
22
+ ${ctx.content}`;
23
+ }
24
+ const result = await provider.completion({
25
+ system: systemPrompt,
26
+ messages: [{ role: "user", content: userPrompt }],
27
+ });
28
+ return result.text;
29
+ }
30
+ function createSummaryStrategy({ id, store, summarize, }) {
31
+ return async (input) => {
32
+ const { target, tokenizer, tokenString, context } = input;
33
+ const content = tokenString(target);
34
+ const existingEntry = await store.get(id);
35
+ const summarizerContext = {
36
+ content,
37
+ existingSummary: existingEntry?.data.content ?? null,
38
+ };
39
+ let newSummary;
40
+ if (summarize) {
41
+ newSummary = await summarize(summarizerContext);
42
+ }
43
+ else if (context.provider) {
44
+ newSummary = await defaultSummarizer(summarizerContext, context.provider);
45
+ }
46
+ else {
47
+ throw new Error(`Summary "${id}" requires either a 'summarize' function or a provider component ancestor (e.g. <AISDKProvider>)`);
48
+ }
49
+ const newTokenCount = tokenizer(newSummary);
50
+ await store.set(id, {
51
+ content: newSummary,
52
+ tokenCount: newTokenCount,
53
+ });
54
+ // Return as an assistant message so it renders properly
55
+ return {
56
+ kind: "message",
57
+ role: "assistant",
58
+ priority: target.priority,
59
+ children: [`[Summary of earlier conversation]\n${newSummary}`],
60
+ };
61
+ };
62
+ }
63
+ /**
64
+ * A region that summarizes its content when the prompt needs to shrink.
65
+ *
66
+ * When the overall prompt exceeds budget and this region is selected for
67
+ * reduction (based on priority), the summarizer is called and the result
68
+ * replaces the original content.
69
+ *
70
+ * If no `summarize` function is provided, the component will use the
71
+ * `ModelProvider` from an ancestor provider component with a default
72
+ * summarization prompt.
73
+ *
74
+ * @example Using a custom summarizer
75
+ * ```tsx
76
+ * import { InMemoryStore, Summary, type StoredSummary } from "@fastpaca/cria";
77
+ *
78
+ * const store = new InMemoryStore<StoredSummary>();
79
+ *
80
+ * <Summary
81
+ * id="conv-history"
82
+ * store={store}
83
+ * summarize={async ({ content, existingSummary }) => {
84
+ * return callAI(`Summarize, building on: ${existingSummary}\n\n${content}`);
85
+ * }}
86
+ * priority={2}
87
+ * >
88
+ * {conversationHistory}
89
+ * </Summary>
90
+ * ```
91
+ *
92
+ * @example Using a provider component
93
+ * ```tsx
94
+ * import { InMemoryStore, Summary, type StoredSummary, render } from "@fastpaca/cria";
95
+ * import { AISDKProvider } from "@fastpaca/cria/ai-sdk";
96
+ * import { openai } from "@ai-sdk/openai";
97
+ *
98
+ * const store = new InMemoryStore<StoredSummary>();
99
+ *
100
+ * const prompt = (
101
+ * <AISDKProvider model={openai("gpt-4o")}>
102
+ * <Summary id="conv-history" store={store} priority={2}>
103
+ * {conversationHistory}
104
+ * </Summary>
105
+ * </AISDKProvider>
106
+ * );
107
+ *
108
+ * const result = await render(prompt, { tokenizer, budget: 4000 });
109
+ * ```
110
+ */
111
+ export function Summary({ id, store, summarize, priority = 0, children = [], }) {
112
+ return {
113
+ priority,
114
+ strategy: createSummaryStrategy({ id, store, summarize }),
115
+ children: children,
116
+ };
117
+ }
118
+ //# sourceMappingURL=summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.js","sourceRoot":"","sources":["../../src/components/summary.ts"],"names":[],"mappings":"AAoCA;;;GAGG;AACH,KAAK,UAAU,iBAAiB,CAC9B,GAAsB,EACtB,QAAuB;IAEvB,MAAM,YAAY,GAChB,wLAAwL,CAAC;IAE3L,IAAI,UAAkB,CAAC;IACvB,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;QACxB,UAAU,GAAG;;EAEf,GAAG,CAAC,eAAe;;;;EAInB,GAAG,CAAC,OAAO;;mGAEsF,CAAC;IAClG,CAAC;SAAM,CAAC;QACN,UAAU,GAAG;;EAEf,GAAG,CAAC,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC;QACvC,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;KAClD,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAQD,SAAS,qBAAqB,CAAC,EAC7B,EAAE,EACF,KAAK,EACL,SAAS,GACc;IACvB,OAAO,KAAK,EAAE,KAAoB,EAAE,EAAE;QACpC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAE1D,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAE1C,MAAM,iBAAiB,GAAsB;YAC3C,OAAO;YACP,eAAe,EAAE,aAAa,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;SACrD,CAAC;QAEF,IAAI,UAAkB,CAAC;QACvB,IAAI,SAAS,EAAE,CAAC;YACd,UAAU,GAAG,MAAM,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC5B,UAAU,GAAG,MAAM,iBAAiB,CAAC,iBAAiB,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5E,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,YAAY,EAAE,kGAAkG,CACjH,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;QAE5C,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;YAClB,OAAO,EAAE,UAAU;YACnB,UAAU,EAAE,aAAa;SAC1B,CAAC,CAAC;QAEH,wDAAwD;QACxD,OAAO;YACL,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ,EAAE,CAAC,sCAAsC,UAAU,EAAE,CAAC;SAC/D,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,UAAU,OAAO,CAAC,EACtB,EAAE,EACF,KAAK,EACL,SAAS,EACT,QAAQ,GAAG,CAAC,EACZ,QAAQ,GAAG,EAAE,GACA;IACb,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,qBAAqB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACzD,QAAQ,EAAE,QAA0B;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=summary.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.test.d.ts","sourceRoot":"","sources":["../../src/components/summary.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,101 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@fastpaca/cria/jsx-runtime";
2
+ import { expect, test } from "vitest";
3
+ import { InMemoryStore, Last, Region, render, Summary, } from "../index";
4
+ // Simple tokenizer: 1 token per 4 characters
5
+ const tokenizer = (text) => Math.ceil(text.length / 4);
6
+ test("Summary: triggers summarization when over budget", async () => {
7
+ const store = new InMemoryStore();
8
+ let summarizeCalled = false;
9
+ const summarize = ({ content }) => {
10
+ summarizeCalled = true;
11
+ return `Summary of: ${content.slice(0, 20)}...`;
12
+ };
13
+ const longContent = "A".repeat(200);
14
+ const element = (_jsx(Region, { priority: 0, children: _jsx(Summary, { id: "test-1", priority: 1, store: store, summarize: summarize, children: longContent }) }));
15
+ // Render with small budget to trigger summarization
16
+ // Budget needs to fit the summary output + "[Summary of earlier conversation]\n" prefix
17
+ const result = await render(element, { tokenizer, budget: 30 });
18
+ expect(summarizeCalled).toBe(true);
19
+ expect(result).toContain("Summary of:");
20
+ expect(result.length).toBeLessThan(longContent.length);
21
+ });
22
+ test("Summary: stores summary in store", async () => {
23
+ const store = new InMemoryStore();
24
+ const summarize = () => "This is the summary";
25
+ const element = (_jsx(Region, { priority: 0, children: _jsx(Summary, { id: "test-2", priority: 1, store: store, summarize: summarize, children: "Long content ".repeat(50) }) }));
26
+ await render(element, { tokenizer, budget: 20 });
27
+ const entry = store.get("test-2");
28
+ expect(entry).not.toBeNull();
29
+ expect(entry?.data.content).toBe("This is the summary");
30
+ expect(entry?.data.tokenCount).toBeGreaterThan(0);
31
+ expect(entry?.updatedAt).toBeGreaterThan(0);
32
+ });
33
+ test("Summary: passes existing summary to summarizer", async () => {
34
+ const store = new InMemoryStore();
35
+ // Pre-populate store
36
+ store.set("test-3", {
37
+ content: "Previous summary",
38
+ tokenCount: 10,
39
+ });
40
+ let receivedExisting = null;
41
+ const summarize = ({ existingSummary, }) => {
42
+ receivedExisting = existingSummary;
43
+ return "Updated summary";
44
+ };
45
+ const element = (_jsx(Region, { priority: 0, children: _jsx(Summary, { id: "test-3", priority: 1, store: store, summarize: summarize, children: "Content ".repeat(100) }) }));
46
+ await render(element, { tokenizer, budget: 20 });
47
+ expect(receivedExisting).toBe("Previous summary");
48
+ });
49
+ test("Summary: does not trigger when under budget", async () => {
50
+ const store = new InMemoryStore();
51
+ let summarizeCalled = false;
52
+ const summarize = () => {
53
+ summarizeCalled = true;
54
+ return "Summary";
55
+ };
56
+ const element = (_jsx(Region, { priority: 0, children: _jsx(Summary, { id: "test-4", priority: 1, store: store, summarize: summarize, children: "Short" }) }));
57
+ // Large budget - no need to summarize
58
+ await render(element, { tokenizer, budget: 1000 });
59
+ expect(summarizeCalled).toBe(false);
60
+ });
61
+ test("Last: keeps only last N children", async () => {
62
+ const messages = ["First", "Second", "Third", "Fourth", "Fifth"];
63
+ const element = (_jsx(Region, { priority: 0, children: _jsx(Last, { N: 2, children: messages }) }));
64
+ const result = await render(element, { tokenizer, budget: 1000 });
65
+ expect(result).not.toContain("First");
66
+ expect(result).not.toContain("Second");
67
+ expect(result).not.toContain("Third");
68
+ expect(result).toContain("Fourth");
69
+ expect(result).toContain("Fifth");
70
+ });
71
+ test("Last: handles N larger than children count", async () => {
72
+ const messages = ["One", "Two"];
73
+ const element = (_jsx(Region, { priority: 0, children: _jsx(Last, { N: 10, children: messages }) }));
74
+ const result = await render(element, { tokenizer, budget: 1000 });
75
+ expect(result).toContain("One");
76
+ expect(result).toContain("Two");
77
+ });
78
+ test("Summary + Last: typical usage pattern", async () => {
79
+ const store = new InMemoryStore();
80
+ // Summarizer produces a short fixed-length output
81
+ const summarize = () => "Discussed greetings";
82
+ // Use longer messages so the summary provides real compression
83
+ const messages = [
84
+ "Message 1: Hello there, how are you doing today?",
85
+ "Message 2: I am doing great, thanks for asking!",
86
+ "Message 3: That is wonderful to hear from you.",
87
+ "Message 4: Recent message here",
88
+ "Message 5: Final message",
89
+ ];
90
+ const element = (_jsxs(Region, { priority: 0, children: [_jsx(Summary, { id: "conv", priority: 2, store: store, summarize: summarize, children: messages.slice(0, -2) }), _jsx(Last, { N: 2, children: messages })] }));
91
+ // Full content: ~180 chars = 45 tokens
92
+ // Summarized: prefix (34) + summary (19) + last 2 msgs (~50) = ~103 chars = 26 tokens
93
+ const result = await render(element, { tokenizer, budget: 30 });
94
+ // Should have summary of older messages (wrapped with prefix)
95
+ expect(result).toContain("[Summary of earlier conversation]");
96
+ expect(result).toContain("Discussed greetings");
97
+ // Should have recent messages in full
98
+ expect(result).toContain("Message 4: Recent message here");
99
+ expect(result).toContain("Message 5: Final message");
100
+ });
101
+ //# sourceMappingURL=summary.test.js.map