alchemy 0.1.8 → 0.1.10

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 (242) hide show
  1. package/lib/$.d.ts +7 -0
  2. package/lib/$.d.ts.map +1 -0
  3. package/lib/$.js +31 -0
  4. package/lib/$.js.map +1 -0
  5. package/lib/agent/ai.d.ts +40 -0
  6. package/lib/agent/ai.d.ts.map +1 -0
  7. package/lib/agent/ai.js +132 -0
  8. package/lib/agent/ai.js.map +1 -0
  9. package/lib/agent/anthropic.d.ts +9 -0
  10. package/lib/agent/anthropic.d.ts.map +1 -0
  11. package/lib/agent/anthropic.js +25 -0
  12. package/lib/agent/anthropic.js.map +1 -0
  13. package/lib/agent/dependencies.d.ts +4 -0
  14. package/lib/agent/dependencies.d.ts.map +1 -0
  15. package/lib/agent/dependencies.js +48 -0
  16. package/lib/agent/dependencies.js.map +1 -0
  17. package/lib/agent/file-context.d.ts +13 -0
  18. package/lib/agent/file-context.d.ts.map +1 -0
  19. package/lib/agent/file-context.js +6 -0
  20. package/lib/agent/file-context.js.map +1 -0
  21. package/lib/agent/index.d.ts +10 -0
  22. package/lib/agent/index.d.ts.map +1 -0
  23. package/lib/agent/index.js +10 -0
  24. package/lib/agent/index.js.map +1 -0
  25. package/lib/agent/model.d.ts +8 -0
  26. package/lib/agent/model.d.ts.map +1 -0
  27. package/lib/agent/model.js +29 -0
  28. package/lib/agent/model.js.map +1 -0
  29. package/lib/agent/module.d.ts +81 -0
  30. package/lib/agent/module.d.ts.map +1 -0
  31. package/lib/agent/module.js +309 -0
  32. package/lib/agent/module.js.map +1 -0
  33. package/lib/agent/openai.d.ts +6 -0
  34. package/lib/agent/openai.d.ts.map +1 -0
  35. package/lib/agent/openai.js +41 -0
  36. package/lib/agent/openai.js.map +1 -0
  37. package/lib/agent/program.d.ts +12 -0
  38. package/lib/agent/program.d.ts.map +1 -0
  39. package/lib/agent/program.js +21 -0
  40. package/lib/agent/program.js.map +1 -0
  41. package/lib/agent/prompts.d.ts +4 -0
  42. package/lib/agent/prompts.d.ts.map +1 -0
  43. package/lib/agent/prompts.js +11 -0
  44. package/lib/agent/prompts.js.map +1 -0
  45. package/lib/agent/scrape.d.ts +71 -0
  46. package/lib/agent/scrape.d.ts.map +1 -0
  47. package/lib/agent/scrape.js +45 -0
  48. package/lib/agent/scrape.js.map +1 -0
  49. package/lib/alchemize.d.ts +43 -0
  50. package/lib/alchemize.d.ts.map +1 -0
  51. package/lib/alchemize.js +105 -0
  52. package/lib/alchemize.js.map +1 -0
  53. package/lib/apply.d.ts +23 -0
  54. package/lib/apply.d.ts.map +1 -0
  55. package/lib/apply.js +84 -0
  56. package/lib/apply.js.map +1 -0
  57. package/lib/aws/auto/docs.d.ts +11 -0
  58. package/lib/aws/auto/docs.d.ts.map +1 -0
  59. package/lib/aws/auto/docs.js +56 -0
  60. package/lib/aws/auto/docs.js.map +1 -0
  61. package/lib/aws/auto/index.d.ts +5 -0
  62. package/lib/aws/auto/index.d.ts.map +1 -0
  63. package/lib/aws/auto/index.js +5 -0
  64. package/lib/aws/auto/index.js.map +1 -0
  65. package/lib/aws/auto/resource.d.ts +24 -0
  66. package/lib/aws/auto/resource.d.ts.map +1 -0
  67. package/lib/aws/auto/resource.js +194 -0
  68. package/lib/aws/auto/resource.js.map +1 -0
  69. package/lib/aws/auto/service.d.ts +10 -0
  70. package/lib/aws/auto/service.d.ts.map +1 -0
  71. package/lib/aws/auto/service.js +34 -0
  72. package/lib/aws/auto/service.js.map +1 -0
  73. package/lib/aws/auto/spec.d.ts +83 -0
  74. package/lib/aws/auto/spec.d.ts.map +1 -0
  75. package/lib/aws/auto/spec.js +58 -0
  76. package/lib/aws/auto/spec.js.map +1 -0
  77. package/lib/aws/bucket.d.ts +21 -0
  78. package/lib/aws/bucket.d.ts.map +1 -0
  79. package/lib/aws/bucket.js +114 -0
  80. package/lib/aws/bucket.js.map +1 -0
  81. package/lib/aws/function.d.ts +53 -0
  82. package/lib/aws/function.d.ts.map +1 -0
  83. package/lib/aws/function.js +195 -0
  84. package/lib/aws/function.js.map +1 -0
  85. package/lib/aws/index.d.ts +7 -0
  86. package/lib/aws/index.d.ts.map +1 -0
  87. package/lib/aws/index.js +7 -0
  88. package/lib/aws/index.js.map +1 -0
  89. package/lib/aws/policy.d.ts +46 -0
  90. package/lib/aws/policy.d.ts.map +1 -0
  91. package/lib/aws/policy.js +139 -0
  92. package/lib/aws/policy.js.map +1 -0
  93. package/lib/aws/queue.d.ts +38 -0
  94. package/lib/aws/queue.d.ts.map +1 -0
  95. package/lib/aws/queue.js +162 -0
  96. package/lib/aws/queue.js.map +1 -0
  97. package/lib/aws/role.d.ts +27 -0
  98. package/lib/aws/role.d.ts.map +1 -0
  99. package/lib/aws/role.js +149 -0
  100. package/lib/aws/role.js.map +1 -0
  101. package/lib/aws/table.d.ts +26 -0
  102. package/lib/aws/table.d.ts.map +1 -0
  103. package/lib/aws/table.js +120 -0
  104. package/lib/aws/table.js.map +1 -0
  105. package/lib/destroy.d.ts +19 -0
  106. package/lib/destroy.d.ts.map +1 -0
  107. package/lib/destroy.js +47 -0
  108. package/lib/destroy.js.map +1 -0
  109. package/lib/error.d.ts +2 -0
  110. package/lib/error.d.ts.map +1 -0
  111. package/lib/error.js +13 -0
  112. package/lib/error.js.map +1 -0
  113. package/lib/esbuild.d.ts +70 -0
  114. package/lib/esbuild.d.ts.map +1 -0
  115. package/lib/esbuild.js +58 -0
  116. package/lib/esbuild.js.map +1 -0
  117. package/lib/fs.d.ts +12 -0
  118. package/lib/fs.d.ts.map +1 -0
  119. package/lib/fs.js +41 -0
  120. package/lib/fs.js.map +1 -0
  121. package/lib/global.d.ts +18 -0
  122. package/lib/global.d.ts.map +1 -0
  123. package/lib/global.js +42 -0
  124. package/lib/global.js.map +1 -0
  125. package/lib/index.d.ts +9 -0
  126. package/lib/index.d.ts.map +1 -0
  127. package/lib/index.js +8 -0
  128. package/lib/index.js.map +1 -0
  129. package/lib/input.d.ts +6 -0
  130. package/lib/input.d.ts.map +1 -0
  131. package/lib/input.js +2 -0
  132. package/lib/input.js.map +1 -0
  133. package/lib/main.d.ts +3 -0
  134. package/lib/main.d.ts.map +1 -0
  135. package/lib/main.js +32 -0
  136. package/lib/main.js.map +1 -0
  137. package/lib/markdown/design.d.ts +17 -0
  138. package/lib/markdown/design.d.ts.map +1 -0
  139. package/lib/markdown/design.js +92 -0
  140. package/lib/markdown/design.js.map +1 -0
  141. package/lib/markdown/extract.d.ts +7 -0
  142. package/lib/markdown/extract.d.ts.map +1 -0
  143. package/lib/markdown/extract.js +10 -0
  144. package/lib/markdown/extract.js.map +1 -0
  145. package/lib/markdown/index.d.ts +4 -0
  146. package/lib/markdown/index.d.ts.map +1 -0
  147. package/lib/markdown/index.js +4 -0
  148. package/lib/markdown/index.js.map +1 -0
  149. package/lib/markdown/requirements.d.ts +79 -0
  150. package/lib/markdown/requirements.d.ts.map +1 -0
  151. package/lib/markdown/requirements.js +105 -0
  152. package/lib/markdown/requirements.js.map +1 -0
  153. package/lib/output.d.ts +19 -0
  154. package/lib/output.d.ts.map +1 -0
  155. package/lib/output.js +16 -0
  156. package/lib/output.js.map +1 -0
  157. package/lib/resource.d.ts +66 -0
  158. package/lib/resource.d.ts.map +1 -0
  159. package/lib/resource.js +242 -0
  160. package/lib/resource.js.map +1 -0
  161. package/lib/scope.d.ts +15 -0
  162. package/lib/scope.d.ts.map +1 -0
  163. package/lib/scope.js +38 -0
  164. package/lib/scope.js.map +1 -0
  165. package/lib/slug.d.ts +2 -0
  166. package/lib/slug.d.ts.map +1 -0
  167. package/lib/slug.js +4 -0
  168. package/lib/slug.js.map +1 -0
  169. package/lib/state.d.ts +40 -0
  170. package/lib/state.d.ts.map +1 -0
  171. package/lib/state.js +73 -0
  172. package/lib/state.js.map +1 -0
  173. package/lib/stripe/index.d.ts +4 -0
  174. package/lib/stripe/index.d.ts.map +1 -0
  175. package/lib/stripe/index.js +4 -0
  176. package/lib/stripe/index.js.map +1 -0
  177. package/lib/stripe/price.d.ts +109 -0
  178. package/lib/stripe/price.d.ts.map +1 -0
  179. package/lib/stripe/price.js +112 -0
  180. package/lib/stripe/price.js.map +1 -0
  181. package/lib/stripe/product.d.ts +86 -0
  182. package/lib/stripe/product.d.ts.map +1 -0
  183. package/lib/stripe/product.js +90 -0
  184. package/lib/stripe/product.js.map +1 -0
  185. package/lib/stripe/webhook.d.ts +73 -0
  186. package/lib/stripe/webhook.d.ts.map +1 -0
  187. package/lib/stripe/webhook.js +94 -0
  188. package/lib/stripe/webhook.js.map +1 -0
  189. package/lib/typescript/check-omission.d.ts +2 -0
  190. package/lib/typescript/check-omission.d.ts.map +1 -0
  191. package/lib/typescript/check-omission.js +43 -0
  192. package/lib/typescript/check-omission.js.map +1 -0
  193. package/lib/typescript/debug-type-errors.d.ts +3 -0
  194. package/lib/typescript/debug-type-errors.d.ts.map +1 -0
  195. package/lib/typescript/debug-type-errors.js +35 -0
  196. package/lib/typescript/debug-type-errors.js.map +1 -0
  197. package/lib/typescript/extract.d.ts +7 -0
  198. package/lib/typescript/extract.d.ts.map +1 -0
  199. package/lib/typescript/extract.js +10 -0
  200. package/lib/typescript/extract.js.map +1 -0
  201. package/lib/typescript/index.d.ts +7 -0
  202. package/lib/typescript/index.d.ts.map +1 -0
  203. package/lib/typescript/index.js +7 -0
  204. package/lib/typescript/index.js.map +1 -0
  205. package/lib/typescript/install-dependencies.d.ts +29 -0
  206. package/lib/typescript/install-dependencies.d.ts.map +1 -0
  207. package/lib/typescript/install-dependencies.js +52 -0
  208. package/lib/typescript/install-dependencies.js.map +1 -0
  209. package/lib/typescript/package.d.ts +157 -0
  210. package/lib/typescript/package.d.ts.map +1 -0
  211. package/lib/typescript/package.js +115 -0
  212. package/lib/typescript/package.js.map +1 -0
  213. package/lib/typescript/repair-omissions.d.ts +3 -0
  214. package/lib/typescript/repair-omissions.d.ts.map +1 -0
  215. package/lib/typescript/repair-omissions.js +23 -0
  216. package/lib/typescript/repair-omissions.js.map +1 -0
  217. package/lib/typescript/repair.d.ts +3 -0
  218. package/lib/typescript/repair.d.ts.map +1 -0
  219. package/lib/typescript/repair.js +34 -0
  220. package/lib/typescript/repair.js.map +1 -0
  221. package/lib/typescript/tsconfig.d.ts +469 -0
  222. package/lib/typescript/tsconfig.d.ts.map +1 -0
  223. package/lib/typescript/tsconfig.js +143 -0
  224. package/lib/typescript/tsconfig.js.map +1 -0
  225. package/lib/typescript/typescript.d.ts +107 -0
  226. package/lib/typescript/typescript.d.ts.map +1 -0
  227. package/lib/typescript/typescript.js +180 -0
  228. package/lib/typescript/typescript.js.map +1 -0
  229. package/lib/typescript/validate.d.ts +10 -0
  230. package/lib/typescript/validate.d.ts.map +1 -0
  231. package/lib/typescript/validate.js +49 -0
  232. package/lib/typescript/validate.js.map +1 -0
  233. package/package.json +4 -3
  234. package/test/aws/function.test.ts +0 -144
  235. package/test/aws/queue.test.ts +0 -85
  236. package/test/aws/role.test.ts +0 -153
  237. package/test/aws/table.test.ts +0 -73
  238. package/test/esbuild.test.ts +0 -41
  239. package/test/handler.ts +0 -9
  240. package/test/scope.test.ts +0 -67
  241. package/test/stripe/stripe.test.ts +0 -136
  242. package/tsconfig.json +0 -33
@@ -0,0 +1,107 @@
1
+ import { z } from "zod";
2
+ export type TypeScriptFileInput = z.infer<typeof TypeScriptFileInput>;
3
+ declare const TypeScriptFileInput: z.ZodObject<{
4
+ /**
5
+ * The ID of the model to use for generating TypeScript code
6
+ * @default "gpt-4o"
7
+ */
8
+ modelId: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["o3-mini", "o1", "o1-2024-12-17", "o1-mini", "o1-mini-2024-09-12", "o1-preview", "o1-preview-2024-09-12", "gpt-4o", "gpt-4o-2024-05-13", "gpt-4o-2024-08-06", "gpt-4o-2024-11-20", "gpt-4o-audio-preview", "gpt-4o-audio-preview-2024-10-01", "gpt-4o-audio-preview-2024-12-17", "gpt-4o-mini", "gpt-4o-mini-2024-07-18", "gpt-4-turbo", "gpt-4-turbo-2024-04-09", "gpt-4-turbo-preview", "gpt-4-0125-preview", "gpt-4-1106-preview", "gpt-4", "gpt-4-0613", "gpt-3.5-turbo-0125", "gpt-3.5-turbo", "gpt-3.5-turbo-1106"]>, z.ZodEnum<["claude-3-5-sonnet-latest", "claude-3-5-sonnet-20241022", "claude-3-5-sonnet-20240620", "claude-3-5-haiku-latest", "claude-3-5-haiku-20241022", "claude-3-opus", "claude-3-opus-20240229", "claude-3-sonnet", "claude-3-sonnet-20240229", "claude-3-haiku", "claude-3-haiku-20240307"]>]>>;
9
+ /**
10
+ * The name of the file to write the code to
11
+ */
12
+ path: z.ZodString;
13
+ /**
14
+ * The requirements for the TypeScript file
15
+ */
16
+ requirements: z.ZodString;
17
+ /**
18
+ * List of other code files that it depends on
19
+ */
20
+ dependencies: z.ZodOptional<z.ZodArray<z.ZodObject<{
21
+ path: z.ZodString;
22
+ content: z.ZodOptional<z.ZodString>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ path: string;
25
+ content?: string | undefined;
26
+ }, {
27
+ path: string;
28
+ content?: string | undefined;
29
+ }>, "many">>;
30
+ /**
31
+ * Temperature setting for model generation (higher = more creative, lower = more focused)
32
+ * @default 0.7
33
+ */
34
+ temperature: z.ZodOptional<z.ZodNumber>;
35
+ /**
36
+ * Whether to perform TypeScript type checking on the generated code
37
+ * @default false
38
+ */
39
+ typeCheck: z.ZodOptional<z.ZodBoolean>;
40
+ /**
41
+ * Path to the tsconfig.json file to use for validation
42
+ * If not provided, will look for tsconfig.json in the project root
43
+ * Only used if typeCheck is true
44
+ */
45
+ tsconfigPath: z.ZodOptional<z.ZodString>;
46
+ /**
47
+ * Project root directory. Used to resolve tsconfig.json and module imports
48
+ * If not provided, will use the directory of the target file
49
+ * Only used if typeCheck is true
50
+ */
51
+ projectRoot: z.ZodOptional<z.ZodString>;
52
+ }, "strip", z.ZodTypeAny, {
53
+ path: string;
54
+ requirements: string;
55
+ temperature?: number | undefined;
56
+ modelId?: "o3-mini" | "o1" | "o1-2024-12-17" | "o1-mini" | "o1-mini-2024-09-12" | "o1-preview" | "o1-preview-2024-09-12" | "gpt-4o" | "gpt-4o-2024-05-13" | "gpt-4o-2024-08-06" | "gpt-4o-2024-11-20" | "gpt-4o-audio-preview" | "gpt-4o-audio-preview-2024-10-01" | "gpt-4o-audio-preview-2024-12-17" | "gpt-4o-mini" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo" | "gpt-3.5-turbo-1106" | "claude-3-5-sonnet-latest" | "claude-3-5-sonnet-20241022" | "claude-3-5-sonnet-20240620" | "claude-3-5-haiku-latest" | "claude-3-5-haiku-20241022" | "claude-3-opus" | "claude-3-opus-20240229" | "claude-3-sonnet" | "claude-3-sonnet-20240229" | "claude-3-haiku" | "claude-3-haiku-20240307" | undefined;
57
+ dependencies?: {
58
+ path: string;
59
+ content?: string | undefined;
60
+ }[] | undefined;
61
+ typeCheck?: boolean | undefined;
62
+ tsconfigPath?: string | undefined;
63
+ projectRoot?: string | undefined;
64
+ }, {
65
+ path: string;
66
+ requirements: string;
67
+ temperature?: number | undefined;
68
+ modelId?: "o3-mini" | "o1" | "o1-2024-12-17" | "o1-mini" | "o1-mini-2024-09-12" | "o1-preview" | "o1-preview-2024-09-12" | "gpt-4o" | "gpt-4o-2024-05-13" | "gpt-4o-2024-08-06" | "gpt-4o-2024-11-20" | "gpt-4o-audio-preview" | "gpt-4o-audio-preview-2024-10-01" | "gpt-4o-audio-preview-2024-12-17" | "gpt-4o-mini" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo" | "gpt-3.5-turbo-1106" | "claude-3-5-sonnet-latest" | "claude-3-5-sonnet-20241022" | "claude-3-5-sonnet-20240620" | "claude-3-5-haiku-latest" | "claude-3-5-haiku-20241022" | "claude-3-opus" | "claude-3-opus-20240229" | "claude-3-sonnet" | "claude-3-sonnet-20240229" | "claude-3-haiku" | "claude-3-haiku-20240307" | undefined;
69
+ dependencies?: {
70
+ path: string;
71
+ content?: string | undefined;
72
+ }[] | undefined;
73
+ typeCheck?: boolean | undefined;
74
+ tsconfigPath?: string | undefined;
75
+ projectRoot?: string | undefined;
76
+ }>;
77
+ export type TypeScriptFileOutput = z.infer<typeof TypeScriptFileOutput>;
78
+ export declare const TypeScriptFileOutput: z.ZodObject<{
79
+ path: z.ZodString;
80
+ content: z.ZodOptional<z.ZodString>;
81
+ }, "strip", z.ZodTypeAny, {
82
+ path: string;
83
+ content?: string | undefined;
84
+ }, {
85
+ path: string;
86
+ content?: string | undefined;
87
+ }>;
88
+ declare const TypeScriptFile_base: import("../resource").Provider<"code::TypeScriptFile", [props: {
89
+ path: string;
90
+ requirements: string;
91
+ temperature?: number | undefined;
92
+ modelId?: "o3-mini" | "o1" | "o1-2024-12-17" | "o1-mini" | "o1-mini-2024-09-12" | "o1-preview" | "o1-preview-2024-09-12" | "gpt-4o" | "gpt-4o-2024-05-13" | "gpt-4o-2024-08-06" | "gpt-4o-2024-11-20" | "gpt-4o-audio-preview" | "gpt-4o-audio-preview-2024-10-01" | "gpt-4o-audio-preview-2024-12-17" | "gpt-4o-mini" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo" | "gpt-3.5-turbo-1106" | "claude-3-5-sonnet-latest" | "claude-3-5-sonnet-20241022" | "claude-3-5-sonnet-20240620" | "claude-3-5-haiku-latest" | "claude-3-5-haiku-20241022" | "claude-3-opus" | "claude-3-opus-20240229" | "claude-3-sonnet" | "claude-3-sonnet-20240229" | "claude-3-haiku" | "claude-3-haiku-20240307" | undefined;
93
+ dependencies?: {
94
+ path: string;
95
+ content?: string | undefined;
96
+ }[] | undefined;
97
+ typeCheck?: boolean | undefined;
98
+ tsconfigPath?: string | undefined;
99
+ projectRoot?: string | undefined;
100
+ }], {
101
+ path: string;
102
+ content?: string | undefined;
103
+ }>;
104
+ export declare class TypeScriptFile extends TypeScriptFile_base {
105
+ }
106
+ export {};
107
+ //# sourceMappingURL=typescript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/typescript/typescript.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,QAAA,MAAM,mBAAmB;IACvB;;;OAGG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;;;;;;;;;;IAGH;;;OAGG;;IAGH;;;OAGG;;IAGH;;;;OAIG;;IAGH;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,eAAO,MAAM,oBAAoB;;;;;;;;;EAAc,CAAC;;;;;;;;;;;;;;;;;AAEhD,qBAAa,cAAe,SAAQ,mBAkJnC;CAAG"}
@@ -0,0 +1,180 @@
1
+ import { mkdir, writeFile } from "fs/promises";
2
+ import { dirname } from "path";
3
+ import { z } from "zod";
4
+ import { ModelId, generateText, resolveModel } from "../agent";
5
+ import { dependenciesAsMessages } from "../agent/dependencies";
6
+ import { FileContext } from "../agent/file-context";
7
+ import { rm } from "../fs";
8
+ import { Resource } from "../resource";
9
+ import { checkForCodeOmission } from "./check-omission";
10
+ import { debugTypeErrors } from "./debug-type-errors";
11
+ import { extractTypeScriptCode } from "./extract";
12
+ import { repairTypeScriptCode } from "./repair";
13
+ import { repairCodeOmissions } from "./repair-omissions";
14
+ import { validateTypeScript } from "./validate";
15
+ const TypeScriptFileInput = z.object({
16
+ /**
17
+ * The ID of the model to use for generating TypeScript code
18
+ * @default "gpt-4o"
19
+ */
20
+ modelId: ModelId.optional(),
21
+ /**
22
+ * The name of the file to write the code to
23
+ */
24
+ path: z.string(),
25
+ /**
26
+ * The requirements for the TypeScript file
27
+ */
28
+ requirements: z.string(),
29
+ /**
30
+ * List of other code files that it depends on
31
+ */
32
+ dependencies: z.array(FileContext).optional(),
33
+ /**
34
+ * Temperature setting for model generation (higher = more creative, lower = more focused)
35
+ * @default 0.7
36
+ */
37
+ temperature: z.number().optional(),
38
+ /**
39
+ * Whether to perform TypeScript type checking on the generated code
40
+ * @default false
41
+ */
42
+ typeCheck: z.boolean().optional(),
43
+ /**
44
+ * Path to the tsconfig.json file to use for validation
45
+ * If not provided, will look for tsconfig.json in the project root
46
+ * Only used if typeCheck is true
47
+ */
48
+ tsconfigPath: z.string().optional(),
49
+ /**
50
+ * Project root directory. Used to resolve tsconfig.json and module imports
51
+ * If not provided, will use the directory of the target file
52
+ * Only used if typeCheck is true
53
+ */
54
+ projectRoot: z.string().optional(),
55
+ });
56
+ export const TypeScriptFileOutput = FileContext;
57
+ export class TypeScriptFile extends Resource("code::TypeScriptFile", async (ctx, props) => {
58
+ if (ctx.event === "delete") {
59
+ await rm(props.path);
60
+ return;
61
+ }
62
+ console.log("Implementing", props.path);
63
+ // Get the appropriate model based on the ID
64
+ const model = await resolveModel(props.modelId ?? "gpt-4o");
65
+ const messages = [
66
+ {
67
+ role: "system",
68
+ content: "You are an expert TypeScript developer that generates clean, well-documented code following best practices. " +
69
+ "Your response must follow this exact format:\n" +
70
+ "1. A single sentence describing what the code will do\n" +
71
+ "2. A single TypeScript code block surrounded by ```ts and ``` tags containing the COMPLETE implementation\n" +
72
+ "IMPORTANT: You must ALWAYS provide the ENTIRE file contents, including ALL imports, types, and implementations.\n" +
73
+ "NEVER output partial code or omit any functionality from the original file when making changes.\n" +
74
+ "Do not include any other explanations or multiple code blocks.",
75
+ },
76
+ ...dependenciesAsMessages(props.dependencies),
77
+ {
78
+ role: "user",
79
+ content: `Please generate TypeScript code based on the following specifications:
80
+
81
+ Requirements:
82
+ ${props.requirements}
83
+
84
+ The code should:
85
+ 1. Be well-documented with JSDoc comments
86
+ 2. Follow TypeScript best practices
87
+ 3. Include proper type definitions
88
+ 4. Be ready to use with the provided context files
89
+ 5. Include ALL necessary imports and dependencies
90
+ 6. Contain the COMPLETE implementation with no omissions`,
91
+ },
92
+ ];
93
+ const maxAttempts = 3;
94
+ let code;
95
+ let typeErrors;
96
+ // Try generating and validating code up to maxAttempts times
97
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
98
+ try {
99
+ // After 2 failed attempts, consult o3-mini for analysis
100
+ if (attempt === maxAttempts) {
101
+ if (!ctx.quiet) {
102
+ console.log("[TypeScript] Consulting expert for code analysis...");
103
+ }
104
+ const diagnosis = await debugTypeErrors(messages, typeErrors);
105
+ messages.push({
106
+ role: "user",
107
+ content: diagnosis,
108
+ });
109
+ }
110
+ // Generate the TypeScript code
111
+ if (!ctx.quiet) {
112
+ console.log(`[TypeScript] Generating code attempt ${attempt}...`);
113
+ }
114
+ const { text } = await generateText({
115
+ model,
116
+ temperature: Math.max(0.1, (props.temperature ?? 0.7) * (1 - attempt * 0.2)),
117
+ messages,
118
+ });
119
+ code = extractTypeScriptCode(text);
120
+ if (!code) {
121
+ console.log("Format mismatch");
122
+ messages.push({
123
+ role: "assistant",
124
+ content: text,
125
+ }, {
126
+ role: "user",
127
+ content: "Your response did not match the required format. Please provide your response with exactly one sentence summary" +
128
+ " followed by a single TypeScript code block surrounded by ```ts and ``` tags containing the COMPLETE implementation. No other text or explanations.",
129
+ });
130
+ continue;
131
+ }
132
+ // First check for omissions
133
+ if (!ctx.quiet) {
134
+ console.log("[TypeScript] Checking for code omissions...");
135
+ }
136
+ const hasOmissions = await checkForCodeOmission(code);
137
+ if (hasOmissions) {
138
+ code = await repairCodeOmissions(model, messages);
139
+ }
140
+ // Ensure the directory exists
141
+ await mkdir(dirname(props.path), { recursive: true });
142
+ // Write the TypeScript file
143
+ await writeFile(props.path, code);
144
+ if (props.typeCheck) {
145
+ typeErrors = await validateTypeScript(props.path, {
146
+ tsconfigPath: props.tsconfigPath,
147
+ projectRoot: props.projectRoot,
148
+ });
149
+ if (typeErrors) {
150
+ if (attempt === maxAttempts) {
151
+ throw new Error(`Failed to generate type-safe code after maximum attempts. Errors:\n${typeErrors}`);
152
+ }
153
+ else {
154
+ code = await repairTypeScriptCode(model, typeErrors, messages);
155
+ continue;
156
+ }
157
+ }
158
+ }
159
+ // If we get here, the code is valid
160
+ return {
161
+ path: props.path,
162
+ content: code,
163
+ };
164
+ }
165
+ catch (error) {
166
+ // On the last attempt, rethrow the error
167
+ if (attempt === maxAttempts) {
168
+ throw error;
169
+ }
170
+ // Otherwise continue to the next attempt
171
+ if (!ctx.quiet) {
172
+ console.log(`Attempt ${attempt} failed:`, error);
173
+ }
174
+ }
175
+ }
176
+ // This should never be reached due to the throws above
177
+ throw new Error("Unexpected code generation failure");
178
+ }) {
179
+ }
180
+ //# sourceMappingURL=typescript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../src/typescript/typescript.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface TypeCheckOptions {
2
+ tsconfigPath?: string;
3
+ projectRoot?: string;
4
+ }
5
+ /**
6
+ * Validates TypeScript code and returns formatted error messages if there are any type errors
7
+ * @returns Formatted error message if there are errors, undefined if valid
8
+ */
9
+ export declare function validateTypeScript(filePath: string, options: TypeCheckOptions): Promise<string | undefined>;
10
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/typescript/validate.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAyD7B"}
@@ -0,0 +1,49 @@
1
+ import { dirname, resolve } from "path";
2
+ import * as ts from "typescript";
3
+ /**
4
+ * Validates TypeScript code and returns formatted error messages if there are any type errors
5
+ * @returns Formatted error message if there are errors, undefined if valid
6
+ */
7
+ export async function validateTypeScript(filePath, options) {
8
+ const projectRoot = options.projectRoot ?? dirname(filePath);
9
+ const tsconfigPath = options.tsconfigPath ?? resolve(projectRoot, "tsconfig.json");
10
+ // Load tsconfig.json if it exists
11
+ let compilerOptions = {
12
+ target: ts.ScriptTarget.ESNext,
13
+ module: ts.ModuleKind.ESNext,
14
+ strict: true,
15
+ esModuleInterop: true,
16
+ skipLibCheck: true,
17
+ noEmit: true,
18
+ };
19
+ if (ts.sys.fileExists(tsconfigPath)) {
20
+ const { config, error } = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
21
+ if (error) {
22
+ throw new Error(`Error reading tsconfig.json: ${error.messageText}`);
23
+ }
24
+ const { options: parsedOptions, errors } = ts.parseJsonConfigFileContent(config, ts.sys, projectRoot);
25
+ if (errors.length) {
26
+ throw new Error(`Error parsing tsconfig.json: ${errors.map((e) => e.messageText).join("\n")}`);
27
+ }
28
+ compilerOptions = parsedOptions;
29
+ }
30
+ // Create program
31
+ const program = ts.createProgram({
32
+ rootNames: [filePath],
33
+ options: compilerOptions,
34
+ });
35
+ // Get diagnostics
36
+ const diagnostics = [
37
+ ...program.getSemanticDiagnostics(),
38
+ ...program.getSyntacticDiagnostics(),
39
+ ];
40
+ if (diagnostics.length > 0) {
41
+ return ts.formatDiagnosticsWithColorAndContext(diagnostics, {
42
+ getCanonicalFileName: (path) => path,
43
+ getCurrentDirectory: () => projectRoot,
44
+ getNewLine: () => ts.sys.newLine,
45
+ });
46
+ }
47
+ return undefined;
48
+ }
49
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/typescript/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAOjC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,OAAyB;IAEzB,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7D,MAAM,YAAY,GAChB,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAEhE,kCAAkC;IAClC,IAAI,eAAe,GAAuB;QACxC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM;QAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM;QAC5B,MAAM,EAAE,IAAI;QACZ,eAAe,EAAE,IAAI;QACrB,YAAY,EAAE,IAAI;QAClB,MAAM,EAAE,IAAI;KACb,CAAC;IAEF,IAAI,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACpC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,YAAY,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3E,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,0BAA0B,CACtE,MAAM,EACN,EAAE,CAAC,GAAG,EACN,WAAW,CACZ,CAAC;QAEF,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,gCAAgC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9E,CAAC;QACJ,CAAC;QAED,eAAe,GAAG,aAAa,CAAC;IAClC,CAAC;IAED,iBAAiB;IACjB,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC;QAC/B,SAAS,EAAE,CAAC,QAAQ,CAAC;QACrB,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,WAAW,GAAG;QAClB,GAAG,OAAO,CAAC,sBAAsB,EAAE;QACnC,GAAG,OAAO,CAAC,uBAAuB,EAAE;KACrC,CAAC;IAEF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC,oCAAoC,CAAC,WAAW,EAAE;YAC1D,oBAAoB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI;YACpC,mBAAmB,EAAE,GAAG,EAAE,CAAC,WAAW;YACtC,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO;SACjC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "alchemy",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "publish:npm": "cp ../README.md ./README.md && npm publish && rm ./README.md"
7
7
  },
8
+ "files": ["lib", "src"],
8
9
  "exports": {
9
10
  ".": "./lib/index.js",
10
11
  "./agent": "./lib/agent/index.js",
@@ -13,8 +14,8 @@
13
14
  "./esbuild": "./lib/esbuild.js",
14
15
  "./markdown": "./lib/markdown/index.js",
15
16
  "./fs": "./lib/fs.js",
16
- "./stripe": "./src/stripe/index.js",
17
- "./typescript": "./src/typescript/index.js"
17
+ "./stripe": "./lib/stripe/index.js",
18
+ "./typescript": "./lib/typescript/index.js"
18
19
  },
19
20
  "devDependencies": {
20
21
  "@types/bun": "latest",
@@ -1,144 +0,0 @@
1
- import {
2
- GetFunctionCommand,
3
- InvokeCommand,
4
- LambdaClient,
5
- ResourceNotFoundException,
6
- } from "@aws-sdk/client-lambda";
7
- import { describe, expect, test } from "bun:test";
8
- import path from "node:path";
9
- import { apply } from "../../src/apply";
10
- import { Function } from "../../src/aws/function";
11
- import type { PolicyDocument } from "../../src/aws/policy";
12
- import { Role } from "../../src/aws/role";
13
- import { destroy } from "../../src/destroy";
14
- import { Bundle } from "../../src/esbuild";
15
-
16
- const __dirname = path.dirname(new URL(import.meta.url).pathname);
17
-
18
- const lambda = new LambdaClient({});
19
-
20
- describe("AWS Resources", () => {
21
- describe("Function", () => {
22
- test("create function with bundled code", async () => {
23
- // First create the execution role
24
- const assumeRolePolicy: PolicyDocument = {
25
- Version: "2012-10-17",
26
- Statement: [
27
- {
28
- Effect: "Allow",
29
- Principal: {
30
- Service: "lambda.amazonaws.com",
31
- },
32
- Action: "sts:AssumeRole",
33
- },
34
- ],
35
- };
36
-
37
- const logsPolicy: PolicyDocument = {
38
- Version: "2012-10-17",
39
- Statement: [
40
- {
41
- Effect: "Allow",
42
- Action: [
43
- "logs:CreateLogGroup",
44
- "logs:CreateLogStream",
45
- "logs:PutLogEvents",
46
- ],
47
- Resource: "*",
48
- },
49
- ],
50
- };
51
-
52
- const role = new Role("alchemy-test-lambda-role", {
53
- roleName: "alchemy-test-lambda-role",
54
- assumeRolePolicy,
55
- description: "Test role for Lambda function",
56
- policies: [
57
- {
58
- policyName: "logs",
59
- policyDocument: logsPolicy,
60
- },
61
- ],
62
- tags: {
63
- Environment: "test",
64
- },
65
- });
66
-
67
- const roleOutput = await apply(role);
68
-
69
- // Bundle the handler code
70
- const bundle = new Bundle("test-lambda-bundle", {
71
- entryPoint: path.join(__dirname, "..", "handler.ts"),
72
- outdir: ".out",
73
- format: "cjs",
74
- platform: "node",
75
- target: "node18",
76
- });
77
-
78
- const bundleOutput = await apply(bundle);
79
-
80
- // Create the Lambda function
81
- const func = new Function("alchemy-test-function", {
82
- functionName: "alchemy-test-function",
83
- zipPath: bundleOutput.path,
84
- roleArn: roleOutput.arn,
85
- handler: "handler.handler",
86
- runtime: "nodejs20.x",
87
- tags: {
88
- Environment: "test",
89
- },
90
- });
91
-
92
- const output = await apply(func);
93
- expect(output.id).toBe("alchemy-test-function");
94
- expect(output.arn).toMatch(
95
- /^arn:aws:lambda:[a-z0-9-]+:\d+:function:alchemy-test-function$/,
96
- );
97
- expect(output.state).toBe("Active");
98
- expect(output.lastUpdateStatus).toBe("Successful");
99
- expect(output.invokeArn).toMatch(
100
- /^arn:aws:apigateway:[a-z0-9-]+:lambda:path\/2015-03-31\/functions\/arn:aws:lambda:[a-z0-9-]+:\d+:function:alchemy-test-function\/invocations$/,
101
- );
102
-
103
- // Immediately apply again to test stabilization logic
104
- const secondOutput = await apply(func);
105
- expect(secondOutput.state).toBe("Active");
106
- expect(secondOutput.lastUpdateStatus).toBe("Successful");
107
-
108
- // Invoke the function
109
- const testEvent = { test: "event" };
110
- const invokeResponse = await lambda.send(
111
- new InvokeCommand({
112
- FunctionName: output.functionName,
113
- Payload: JSON.stringify(testEvent),
114
- }),
115
- );
116
-
117
- // Parse the response
118
- const responsePayload = new TextDecoder().decode(invokeResponse.Payload);
119
- const response = JSON.parse(responsePayload);
120
- expect(response.statusCode).toBe(200);
121
-
122
- const body = JSON.parse(response.body);
123
- expect(body.message).toBe("Hello from bundled handler!");
124
- expect(body.event).toEqual(testEvent);
125
-
126
- // Clean up
127
- await destroy(func);
128
- await destroy(bundle);
129
- await destroy(role);
130
-
131
- await assertFunctionNotExists("alchemy-test-function");
132
- });
133
- });
134
- });
135
-
136
- async function assertFunctionNotExists(functionName: string) {
137
- await expect(
138
- lambda.send(
139
- new GetFunctionCommand({
140
- FunctionName: functionName,
141
- }),
142
- ),
143
- ).rejects.toThrow(ResourceNotFoundException);
144
- }
@@ -1,85 +0,0 @@
1
- import {
2
- GetQueueUrlCommand,
3
- SQSClient,
4
- SendMessageCommand,
5
- } from "@aws-sdk/client-sqs";
6
- import { describe, expect, test } from "bun:test";
7
- import { apply } from "../../src/apply";
8
- import { Queue } from "../../src/aws/queue";
9
- import { destroy } from "../../src/destroy";
10
-
11
- const sqs = new SQSClient({});
12
-
13
- describe("AWS Resources", () => {
14
- describe("Queue", () => {
15
- const queueName = "alchemy-test-queue";
16
-
17
- test("create queue, send message, delete, and recreate", async () => {
18
- // Create initial queue
19
- const queue = new Queue(queueName, {
20
- queueName,
21
- visibilityTimeout: 30,
22
- messageRetentionPeriod: 345600, // 4 days
23
- tags: {
24
- Environment: "test",
25
- },
26
- });
27
-
28
- const output = await apply(queue);
29
- expect(output.id).toBe(queueName);
30
- expect(output.arn).toMatch(
31
- new RegExp(`^arn:aws:sqs:[a-z0-9-]+:\\d+:${queueName}$`),
32
- );
33
- expect(output.url).toMatch(
34
- new RegExp(
35
- `^https:\\/\\/sqs\\.[a-z0-9-]+\\.amazonaws\\.com\\/\\d+\\/${queueName}$`,
36
- ),
37
- );
38
-
39
- // Send a test message
40
- const messageResponse = await sqs.send(
41
- new SendMessageCommand({
42
- QueueUrl: output.url,
43
- MessageBody: "Hello from test!",
44
- }),
45
- );
46
- expect(messageResponse.MessageId).toBeTruthy();
47
-
48
- // Delete the queue
49
- await destroy(queue);
50
-
51
- // Verify queue is fully deleted by checking if GetQueueUrl throws
52
- await expect(
53
- sqs.send(
54
- new GetQueueUrlCommand({
55
- QueueName: queueName,
56
- }),
57
- ),
58
- ).rejects.toThrow("The specified queue does not exist");
59
-
60
- // Immediately try to recreate the queue - this should handle the QueueDeletedRecently error
61
- const recreatedQueue = new Queue(queueName, {
62
- queueName,
63
- visibilityTimeout: 30,
64
- messageRetentionPeriod: 345600,
65
- tags: {
66
- Environment: "test",
67
- },
68
- });
69
-
70
- const recreatedOutput = await apply(recreatedQueue);
71
- expect(recreatedOutput.id).toBe(queueName);
72
- expect(recreatedOutput.arn).toMatch(
73
- new RegExp(`^arn:aws:sqs:[a-z0-9-]+:\\d+:${queueName}$`),
74
- );
75
- expect(recreatedOutput.url).toMatch(
76
- new RegExp(
77
- `^https:\\/\\/sqs\\.[a-z0-9-]+\\.amazonaws\\.com\\/\\d+\\/${queueName}$`,
78
- ),
79
- );
80
-
81
- // Clean up
82
- await destroy(recreatedQueue);
83
- });
84
- });
85
- });