alchemy 0.2.5 → 0.3.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 (197) hide show
  1. package/README.md +3 -3
  2. package/lib/ai/approve.d.ts +99 -0
  3. package/lib/ai/approve.js +76 -0
  4. package/lib/ai/astro-file.d.ts +137 -0
  5. package/lib/ai/astro-file.js +156 -0
  6. package/lib/ai/client.d.ts +7 -8
  7. package/lib/ai/client.js +48 -19
  8. package/lib/ai/css-file.d.ts +131 -0
  9. package/lib/ai/css-file.js +141 -0
  10. package/lib/ai/data.d.ts +51 -6
  11. package/lib/ai/data.js +58 -12
  12. package/lib/ai/document.d.ts +108 -24
  13. package/lib/ai/document.js +166 -52
  14. package/lib/ai/html-file.d.ts +128 -0
  15. package/lib/ai/html-file.js +138 -0
  16. package/lib/ai/index.d.ts +9 -0
  17. package/lib/ai/index.js +9 -0
  18. package/lib/ai/json-file.d.ts +160 -0
  19. package/lib/ai/json-file.js +187 -0
  20. package/lib/ai/review.d.ts +122 -0
  21. package/lib/ai/review.js +101 -0
  22. package/lib/ai/typescript-file.d.ts +139 -0
  23. package/lib/ai/typescript-file.js +145 -0
  24. package/lib/ai/vue-file.d.ts +126 -0
  25. package/lib/ai/vue-file.js +136 -0
  26. package/lib/ai/yaml-file.d.ts +169 -0
  27. package/lib/ai/yaml-file.js +200 -0
  28. package/lib/alchemy.js +17 -2
  29. package/lib/apply.js +1 -1
  30. package/lib/cloudflare/dns.d.ts +88 -0
  31. package/lib/cloudflare/dns.js +192 -0
  32. package/lib/cloudflare/generate-asset-manifest.js +1 -1
  33. package/lib/cloudflare/index.d.ts +2 -1
  34. package/lib/cloudflare/index.js +2 -1
  35. package/lib/cloudflare/r2-rest-state-store.d.ts +125 -0
  36. package/lib/cloudflare/r2-rest-state-store.js +254 -0
  37. package/lib/cloudflare/response.d.ts +12 -0
  38. package/lib/cloudflare/response.js +0 -0
  39. package/lib/cloudflare/static-site-router.js +16 -7
  40. package/lib/cloudflare/static-site.js +3 -0
  41. package/lib/cloudflare/upload-asset-manifest.js +4 -2
  42. package/lib/cloudflare/zone.d.ts +18 -0
  43. package/lib/cloudflare/zone.js +17 -4
  44. package/lib/dns/godaddy.d.ts +7 -0
  45. package/lib/dns/godaddy.js +21 -0
  46. package/lib/dns/import-dns.d.ts +82 -0
  47. package/lib/dns/import-dns.js +114 -0
  48. package/lib/dns/index.d.ts +2 -0
  49. package/lib/dns/index.js +2 -0
  50. package/lib/dns/record.d.ts +88 -0
  51. package/lib/dns/record.js +13 -0
  52. package/lib/fs/copy-file.d.ts +54 -0
  53. package/lib/fs/copy-file.js +63 -0
  54. package/lib/fs/file-system-state-store.d.ts +17 -0
  55. package/lib/fs/file-system-state-store.js +87 -0
  56. package/lib/fs/file.d.ts +13 -0
  57. package/lib/fs/file.js +24 -5
  58. package/lib/fs/folder.d.ts +10 -0
  59. package/lib/fs/folder.js +2 -2
  60. package/lib/fs/index.d.ts +10 -4
  61. package/lib/fs/index.js +10 -4
  62. package/lib/fs/static-astro-file.d.ts +34 -0
  63. package/lib/fs/static-astro-file.js +39 -0
  64. package/lib/fs/static-css-file.d.ts +24 -0
  65. package/lib/fs/static-css-file.js +29 -0
  66. package/lib/fs/static-html-file.d.ts +31 -0
  67. package/lib/fs/static-html-file.js +36 -0
  68. package/lib/fs/{json-file.d.ts → static-json-file.d.ts} +3 -3
  69. package/lib/fs/static-json-file.js +15 -0
  70. package/lib/fs/{text-file.d.ts → static-text-file.d.ts} +2 -2
  71. package/lib/fs/static-text-file.js +8 -0
  72. package/lib/fs/{typescript-file.d.ts → static-typescript-file.d.ts} +3 -3
  73. package/lib/fs/{typescript-file.js → static-typescript-file.js} +3 -2
  74. package/lib/fs/static-vue-file.d.ts +28 -0
  75. package/lib/fs/static-vue-file.js +33 -0
  76. package/lib/fs/static-yaml-file.d.ts +22 -0
  77. package/lib/fs/{yaml-file.js → static-yaml-file.js} +3 -2
  78. package/lib/internal/getting-started.d.ts +21 -0
  79. package/lib/internal/getting-started.js +87 -0
  80. package/lib/internal/index.d.ts +3 -0
  81. package/lib/internal/index.js +3 -0
  82. package/lib/internal/providers.d.ts +27 -0
  83. package/lib/internal/providers.js +172 -0
  84. package/lib/internal/tutorial.d.ts +104 -0
  85. package/lib/internal/tutorial.js +251 -0
  86. package/lib/resource.js +8 -1
  87. package/lib/scope.d.ts +1 -1
  88. package/lib/scope.js +4 -2
  89. package/lib/state.d.ts +1 -16
  90. package/lib/state.js +0 -87
  91. package/lib/test/bun.d.ts +11 -0
  92. package/lib/test/bun.js +36 -8
  93. package/lib/web/astro.d.ts +147 -0
  94. package/lib/web/astro.js +414 -0
  95. package/lib/{shadcn/component.js → web/shadcn-component.js} +2 -9
  96. package/lib/web/shadcn.d.ts +97 -0
  97. package/lib/web/shadcn.js +99 -0
  98. package/lib/web/tailwind.d.ts +64 -0
  99. package/lib/web/tailwind.js +97 -0
  100. package/lib/{vite → web}/vite.d.ts +5 -0
  101. package/lib/{vite → web}/vite.js +44 -44
  102. package/lib/web/vitepress/config.d.ts +10 -0
  103. package/lib/web/vitepress/config.js +31 -0
  104. package/lib/web/vitepress/custom-theme.d.ts +173 -0
  105. package/lib/web/vitepress/custom-theme.js +336 -0
  106. package/lib/{vitepress → web/vitepress}/dependencies.d.ts +2 -2
  107. package/lib/{vitepress → web/vitepress}/dependencies.js +1 -1
  108. package/lib/web/vitepress/home-page.d.ts +246 -0
  109. package/lib/web/vitepress/home-page.js +147 -0
  110. package/lib/{vitepress → web/vitepress}/index.d.ts +2 -0
  111. package/lib/{vitepress → web/vitepress}/index.js +2 -0
  112. package/lib/{vitepress → web/vitepress}/vitepress.d.ts +15 -12
  113. package/lib/{vitepress → web/vitepress}/vitepress.js +26 -44
  114. package/package.json +6 -2
  115. package/src/ai/approve.ts +163 -0
  116. package/src/ai/astro-file.ts +269 -0
  117. package/src/ai/client.ts +60 -21
  118. package/src/ai/css-file.ts +247 -0
  119. package/src/ai/data.ts +81 -19
  120. package/src/ai/document.ts +240 -62
  121. package/src/ai/html-file.ts +244 -0
  122. package/src/ai/index.ts +9 -0
  123. package/src/ai/json-file.ts +325 -0
  124. package/src/ai/review.ts +213 -0
  125. package/src/ai/typescript-file.ts +259 -0
  126. package/src/ai/vue-file.ts +242 -0
  127. package/src/ai/yaml-file.ts +328 -0
  128. package/src/alchemy.ts +18 -7
  129. package/src/apply.ts +8 -9
  130. package/src/cloudflare/dns.ts +344 -0
  131. package/src/cloudflare/generate-asset-manifest.ts +4 -4
  132. package/src/cloudflare/index.ts +2 -1
  133. package/src/cloudflare/r2-rest-state-store.ts +353 -0
  134. package/src/cloudflare/response.ts +9 -0
  135. package/src/cloudflare/static-site-router.ts +18 -8
  136. package/src/cloudflare/static-site.ts +11 -7
  137. package/src/cloudflare/upload-asset-manifest.ts +6 -4
  138. package/src/cloudflare/worker.ts +44 -43
  139. package/src/cloudflare/zone.ts +39 -23
  140. package/src/dns/godaddy.ts +29 -0
  141. package/src/dns/import-dns.ts +213 -0
  142. package/src/dns/index.ts +2 -0
  143. package/src/dns/record.ts +121 -0
  144. package/src/fs/copy-file.ts +115 -0
  145. package/src/fs/file-system-state-store.ts +109 -0
  146. package/src/fs/file.ts +35 -9
  147. package/src/fs/folder.ts +14 -2
  148. package/src/fs/index.ts +10 -4
  149. package/src/fs/static-astro-file.ts +45 -0
  150. package/src/fs/static-css-file.ts +35 -0
  151. package/src/fs/static-html-file.ts +42 -0
  152. package/src/fs/static-json-file.ts +34 -0
  153. package/src/fs/{text-file.ts → static-text-file.ts} +9 -3
  154. package/src/fs/{typescript-file.ts → static-typescript-file.ts} +7 -6
  155. package/src/fs/static-vue-file.ts +39 -0
  156. package/src/fs/static-yaml-file.ts +33 -0
  157. package/src/internal/getting-started.ts +115 -0
  158. package/src/internal/index.ts +3 -0
  159. package/src/internal/providers.ts +241 -0
  160. package/src/internal/tutorial.ts +392 -0
  161. package/src/resource.ts +10 -1
  162. package/src/scope.ts +5 -6
  163. package/src/state.ts +1 -111
  164. package/src/test/bun.ts +60 -10
  165. package/src/web/astro.ts +644 -0
  166. package/src/{shadcn/component.ts → web/shadcn-component.ts} +5 -13
  167. package/src/web/shadcn.ts +219 -0
  168. package/src/web/tailwind.ts +167 -0
  169. package/src/{vite → web}/vite.ts +54 -56
  170. package/src/web/vitepress/config.ts +48 -0
  171. package/src/web/vitepress/custom-theme.ts +514 -0
  172. package/src/{vitepress → web/vitepress}/dependencies.ts +2 -2
  173. package/src/web/vitepress/home-page.ts +375 -0
  174. package/src/{vitepress → web/vitepress}/index.ts +2 -0
  175. package/src/{vitepress → web/vitepress}/vitepress.ts +62 -72
  176. package/lib/cloudflare/state.d.ts +0 -82
  177. package/lib/cloudflare/state.js +0 -108
  178. package/lib/fs/json-file.js +0 -7
  179. package/lib/fs/text-file.js +0 -7
  180. package/lib/fs/yaml-file.d.ts +0 -19
  181. package/lib/internal/docs.d.ts +0 -5
  182. package/lib/internal/docs.js +0 -287
  183. package/lib/shadcn/index.d.ts +0 -1
  184. package/lib/shadcn/index.js +0 -1
  185. package/lib/vite/index.d.ts +0 -1
  186. package/lib/vite/index.js +0 -1
  187. package/lib/vitepress/home-page.d.ts +0 -133
  188. package/lib/vitepress/home-page.js +0 -11
  189. package/src/cloudflare/state.ts +0 -138
  190. package/src/fs/json-file.ts +0 -23
  191. package/src/fs/yaml-file.ts +0 -26
  192. package/src/internal/docs.ts +0 -338
  193. package/src/shadcn/index.ts +0 -1
  194. package/src/vite/index.ts +0 -1
  195. package/src/vitepress/home-page.ts +0 -166
  196. /package/lib/{shadcn/component.d.ts → web/shadcn-component.d.ts} +0 -0
  197. /package/src/{vitepress → web/vitepress}/index.md +0 -0
@@ -0,0 +1,247 @@
1
+ import { generateText } from "ai";
2
+ import type { Context } from "../context";
3
+ import { StaticCSSFile } from "../fs/static-css-file";
4
+ import { Resource } from "../resource";
5
+ import type { Secret } from "../secret";
6
+ import { type ModelConfig, createModel } from "./client";
7
+
8
+ /**
9
+ * Properties for creating or updating a CSSFile
10
+ */
11
+ export interface CSSFileProps {
12
+ /**
13
+ * Path to the CSS file
14
+ */
15
+ path: string;
16
+
17
+ /**
18
+ * Base URL for the OpenAI API
19
+ * @default 'https://api.openai.com/v1'
20
+ */
21
+ baseURL?: string;
22
+
23
+ /**
24
+ * Prompt for generating content
25
+ * Use alchemy template literals to include file context:
26
+ * @example
27
+ * prompt: await alchemy`
28
+ * Generate CSS styles for:
29
+ * ${alchemy.file("src/components/Button.jsx")}
30
+ * `
31
+ */
32
+ prompt: string;
33
+
34
+ /**
35
+ * System prompt for the model
36
+ * This is used to provide instructions to the model about how to format the response
37
+ * The default system prompt instructs the model to return CSS code inside ```css fences
38
+ * @default "You are a CSS code generator. Create CSS code based on the user's requirements. Your response MUST include only CSS code inside ```css fences. Do not include any other text, explanations, or multiple code blocks."
39
+ */
40
+ system?: string;
41
+
42
+ /**
43
+ * OpenAI API key to use for generating content
44
+ * If not provided, will use OPENAI_API_KEY environment variable
45
+ */
46
+ apiKey?: Secret;
47
+
48
+ /**
49
+ * Model configuration
50
+ */
51
+ model?: ModelConfig;
52
+
53
+ /**
54
+ * Temperature for controlling randomness in generation.
55
+ * Higher values (e.g., 0.8) make output more random,
56
+ * lower values (e.g., 0.2) make it more deterministic.
57
+ * @default 0.7
58
+ */
59
+ temperature?: number;
60
+ }
61
+
62
+ /**
63
+ * A CSS file that can be created, updated, and deleted
64
+ */
65
+ export interface CSSFile extends CSSFileProps, Resource<"ai::CSSFile"> {
66
+ /**
67
+ * Content of the CSS file
68
+ */
69
+ content: string;
70
+
71
+ /**
72
+ * Time at which the file was created
73
+ */
74
+ createdAt: number;
75
+
76
+ /**
77
+ * Time at which the file was last updated
78
+ */
79
+ updatedAt: number;
80
+ }
81
+
82
+ /**
83
+ * Default system prompt for CSS file generation
84
+ */
85
+ const DEFAULT_CSS_SYSTEM_PROMPT =
86
+ "You are a CSS code generator. Create CSS code based on the user's requirements. Your response MUST include only CSS code inside ```css fences. Do not include any other text, explanations, or multiple code blocks.";
87
+
88
+ /**
89
+ * Resource for generating CSS files using AI models.
90
+ * Extracts CSS code from between ```css fences and validates the response.
91
+ *
92
+ * @example
93
+ * // Create styles for a website
94
+ * const mainStyles = await CSSFile("main-styles", {
95
+ * path: "./public/css/main.css",
96
+ * prompt: await alchemy`
97
+ * Generate modern CSS styles for a company website with:
98
+ * - Clean, minimalist design
99
+ * - Primary color: #0062ff
100
+ * - Secondary color: #6c757d
101
+ * - Light gray background
102
+ * - Responsive layout for mobile, tablet, and desktop
103
+ * - Custom styles for buttons, cards, and navigation
104
+ * `,
105
+ * model: {
106
+ * id: "gpt-4o",
107
+ * provider: "openai"
108
+ * }
109
+ * });
110
+ *
111
+ * @example
112
+ * // Generate CSS based on existing HTML
113
+ * const componentStyles = await CSSFile("component-styles", {
114
+ * path: "./src/styles/component.css",
115
+ * prompt: await alchemy`
116
+ * Create CSS styles for this HTML component:
117
+ * ${alchemy.file("src/components/Card.html")}
118
+ *
119
+ * The styles should be:
120
+ * - Modern and clean
121
+ * - Include hover effects and transitions
122
+ * - Support both light and dark themes
123
+ * - Use CSS variables for colors and spacing
124
+ * `,
125
+ * temperature: 0.2
126
+ * });
127
+ *
128
+ * @example
129
+ * // Generate CSS animation with custom system prompt
130
+ * const animationStyles = await CSSFile("animations", {
131
+ * path: "./src/styles/animations.css",
132
+ * prompt: await alchemy`
133
+ * Create CSS animations for:
134
+ * - Fade in/out
135
+ * - Slide in from different directions
136
+ * - Pulse effect
137
+ * - Bounce effect
138
+ * - Scale in/out
139
+ * - Rotate
140
+ *
141
+ * Each animation should be reusable via class names.
142
+ * `,
143
+ * system: "You are an expert CSS animator. Create a single CSS file inside ```css fences with no additional text. Use modern CSS animation techniques and include vendor prefixes where needed for browser compatibility.",
144
+ * model: {
145
+ * id: "claude-3-opus-20240229",
146
+ * provider: "anthropic"
147
+ * }
148
+ * });
149
+ */
150
+ export const CSSFile = Resource(
151
+ "ai::CSSFile",
152
+ async function (
153
+ this: Context<CSSFile>,
154
+ id: string,
155
+ props: CSSFileProps
156
+ ): Promise<CSSFile> {
157
+ // Handle deletion phase
158
+ if (this.phase === "delete") {
159
+ return this.destroy();
160
+ }
161
+
162
+ // Use provided system prompt or default
163
+ const system = props.system || DEFAULT_CSS_SYSTEM_PROMPT;
164
+
165
+ // Generate initial content
166
+ const { text } = await generateText({
167
+ model: createModel(props),
168
+ prompt: props.prompt,
169
+ system,
170
+ providerOptions: props.model?.options,
171
+ ...(props.temperature === undefined
172
+ ? {}
173
+ : { temperature: props.temperature }),
174
+ });
175
+
176
+ // Extract and validate CSS code
177
+ let { code, error } = await extractCSSCode(text);
178
+
179
+ // Re-prompt if there are validation errors
180
+ if (error) {
181
+ const errorSystem = `${system}\n\nERROR: ${error}\n\nPlease try again and ensure your response contains exactly one CSS code block inside \`\`\`css fences.`;
182
+
183
+ const { text: retryText } = await generateText({
184
+ model: createModel(props),
185
+ prompt: props.prompt,
186
+ system: errorSystem,
187
+ providerOptions: props.model?.options,
188
+ ...(props.temperature === undefined
189
+ ? {}
190
+ : { temperature: props.temperature }),
191
+ });
192
+
193
+ const retryResult = await extractCSSCode(retryText);
194
+
195
+ if (retryResult.error) {
196
+ throw new Error(
197
+ `Failed to generate valid CSS code: ${retryResult.error}\n${retryText}`
198
+ );
199
+ }
200
+
201
+ code = retryResult.code;
202
+ }
203
+
204
+ // Use StaticCSSFile to create/update the file
205
+ const file = await StaticCSSFile("file", props.path, code);
206
+
207
+ // Return the resource
208
+ return this({
209
+ ...props,
210
+ content: file.content,
211
+ createdAt: Date.now(),
212
+ updatedAt: Date.now(),
213
+ });
214
+ }
215
+ );
216
+
217
+ /**
218
+ * Extracts CSS code from between ```css fences
219
+ * Validates that exactly one CSS code block exists
220
+ *
221
+ * @param text The text to extract CSS code from
222
+ * @returns The extracted CSS code or error message
223
+ */
224
+ async function extractCSSCode(
225
+ text: string
226
+ ): Promise<{ code: string; error?: string }> {
227
+ const cssCodeRegex = /```css\s*([\s\S]*?)```/g;
228
+ const matches = Array.from(text.matchAll(cssCodeRegex));
229
+
230
+ if (matches.length === 0) {
231
+ return {
232
+ code: "",
233
+ error:
234
+ "No CSS code block found in the response. Please include your code within ```css fences.",
235
+ };
236
+ }
237
+
238
+ if (matches.length > 1) {
239
+ return {
240
+ code: "",
241
+ error:
242
+ "Multiple CSS code blocks found in the response. Please provide exactly one code block within ```css fences.",
243
+ };
244
+ }
245
+
246
+ return { code: matches[0][1].trim() };
247
+ }
package/src/ai/data.ts CHANGED
@@ -1,15 +1,10 @@
1
- import { generateObject } from "ai";
1
+ import { generateObject, type CoreMessage } from "ai";
2
2
  import type { JsonSchema, Type, type } from "arktype";
3
3
  import type { Context } from "../context";
4
4
  import { Resource } from "../resource";
5
5
  import type { Secret } from "../secret";
6
6
  import { ark } from "./ark";
7
- import {
8
- type ModelConfig,
9
- createClient,
10
- getModelId,
11
- getModelOptions,
12
- } from "./client";
7
+ import { createModel, type ModelConfig } from "./client";
13
8
 
14
9
  /**
15
10
  * Properties for creating or updating an AI Object
@@ -29,7 +24,13 @@ export interface DataProps<T extends Type<any, any>> {
29
24
  * ${alchemy.file("src/data.ts")}
30
25
  * `
31
26
  */
32
- prompt: string;
27
+ prompt?: string;
28
+
29
+ /**
30
+ * Message history for the conversation
31
+ * If provided, this will be used instead of the prompt
32
+ */
33
+ messages?: CoreMessage[];
33
34
 
34
35
  /**
35
36
  * System prompt to guide the AI's behavior
@@ -38,6 +39,14 @@ export interface DataProps<T extends Type<any, any>> {
38
39
  */
39
40
  system?: string;
40
41
 
42
+ /**
43
+ * Temperature for controlling randomness in generation.
44
+ * Higher values (e.g., 0.8) make output more random,
45
+ * lower values (e.g., 0.2) make it more deterministic.
46
+ * @default 0.7
47
+ */
48
+ temperature?: number;
49
+
41
50
  /**
42
51
  * Base URL for the OpenAI API
43
52
  * @default 'https://api.openai.com/v1'
@@ -67,6 +76,11 @@ export interface Data<T> extends Resource<"ai::Object"> {
67
76
  */
68
77
  object: T;
69
78
 
79
+ /**
80
+ * Updated message history with the AI's response appended
81
+ */
82
+ messages: CoreMessage[];
83
+
70
84
  /**
71
85
  * Time at which the content was generated
72
86
  */
@@ -86,13 +100,20 @@ export interface Data<T> extends Resource<"ai::Object"> {
86
100
  * price: "number"
87
101
  * });
88
102
  *
89
- * const product = await Object("new-product", {
103
+ * const product = await Data("new-product", {
90
104
  * schema: productSchema,
91
105
  * prompt: "Generate a product description for a new smartphone",
92
- * system: "You are a product copywriter specializing in tech products"
106
+ * system: "You are a product copywriter specializing in tech products",
107
+ * model: {
108
+ * id: "gpt-4o",
109
+ * provider: "openai",
110
+ * options: {
111
+ * temperature: 0.7
112
+ * }
113
+ * }
93
114
  * });
94
115
  *
95
- * console.log(product.content); // Typed as per schema
116
+ * console.log(product.object); // Typed as per schema
96
117
  *
97
118
  * @example
98
119
  * // Generate code documentation with context
@@ -106,13 +127,34 @@ export interface Data<T> extends Resource<"ai::Object"> {
106
127
  * returns: "string"
107
128
  * });
108
129
  *
109
- * const docs = await Object("function-docs", {
130
+ * const docs = await Data("function-docs", {
110
131
  * schema: docSchema,
111
132
  * prompt: await alchemy`
112
133
  * Generate documentation for this function:
113
134
  * ${alchemy.file("src/utils/format.ts")}
114
135
  * `,
115
- * system: "You are a technical documentation writer"
136
+ * system: "You are a technical documentation writer",
137
+ * temperature: 0.2
138
+ * });
139
+ *
140
+ * @example
141
+ * // Using message history for iterative generation
142
+ * const feedbackSchema = type({
143
+ * rating: "number",
144
+ * positives: "string[]",
145
+ * improvements: "string[]",
146
+ * summary: "string"
147
+ * });
148
+ *
149
+ * const feedback = await Data("product-feedback", {
150
+ * schema: feedbackSchema,
151
+ * messages: [
152
+ * { role: "user", content: "I'd like feedback on my product design" },
153
+ * { role: "assistant", content: "I'd be happy to provide feedback. What's your product?" },
154
+ * { role: "user", content: "It's a new smart home device that..." }
155
+ * ],
156
+ * system: "You are a product design expert providing structured feedback",
157
+ * temperature: 0.3
116
158
  * });
117
159
  */
118
160
  export const Data = Resource("ai::Object", async function <
@@ -124,26 +166,46 @@ export const Data = Resource("ai::Object", async function <
124
166
  return this.destroy();
125
167
  }
126
168
 
127
- // Initialize OpenAI compatible provider using shared client
128
- const provider = createClient(props);
169
+ // Validate that either prompt or messages is provided
170
+ if (!props.prompt && !props.messages) {
171
+ throw new Error("Either prompt or messages must be provided");
172
+ }
173
+
174
+ // Create messages array if only prompt is provided
175
+ const messages = props.messages || [{ role: "user", content: props.prompt! }];
129
176
 
130
177
  // Generate structured output using generateObject
131
178
  const { object } = await generateObject({
132
- model: provider(getModelId(props)),
179
+ model: createModel(props),
133
180
  // Convert ArkType schema to Zod schema for generateObject
134
181
  // This is needed because generateObject expects a Zod schema
135
182
  schema: ark.schema<type.infer<T>>(props.schema),
183
+ providerOptions: props.model?.options,
136
184
  system:
137
185
  props.system ||
138
186
  "You are an AI assistant tasked with generating structured content.",
139
- prompt: props.prompt,
140
- ...getModelOptions(props),
187
+ messages,
188
+ ...(props.temperature === undefined
189
+ ? {}
190
+ : // some models error if you provide it (rather than ignoring it)
191
+ { temperature: props.temperature }),
141
192
  });
142
193
 
143
- // Return the resource with typed content
194
+ // Create updated message history with the structured response
195
+ const responseText = JSON.stringify(object);
196
+ const updatedMessages = [
197
+ ...messages,
198
+ {
199
+ role: "assistant" as const,
200
+ content: responseText,
201
+ },
202
+ ];
203
+
204
+ // Return the resource with typed content and updated messages
144
205
  return this({
145
206
  type: props.schema,
146
207
  object: object,
208
+ messages: updatedMessages,
147
209
  createdAt: Date.now(),
148
210
  });
149
211
  });