alchemy 0.0.8 → 0.1.2
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.
- package/README.md +355 -0
- package/package.json +24 -20
- package/src/alchemize.ts +151 -0
- package/src/apply.ts +117 -0
- package/src/components/agent/agent.ts +45 -0
- package/src/components/agent/anthropic.ts +27 -0
- package/src/components/agent/index.ts +4 -0
- package/src/components/agent/model.ts +22 -0
- package/src/components/agent/openai.ts +44 -0
- package/src/components/agent/package.ts +126 -0
- package/src/components/agent/requirements.ts +111 -0
- package/src/components/agent/scrape.ts +47 -0
- package/src/components/agent/tsconfig.ts +150 -0
- package/src/components/agent/typescript.ts +177 -0
- package/src/components/aws/bucket.ts +168 -0
- package/src/components/aws/function.ts +302 -0
- package/src/components/aws/index.ts +6 -0
- package/src/components/aws/policy.ts +245 -0
- package/src/components/aws/queue.ts +222 -0
- package/src/components/aws/role.ts +245 -0
- package/src/components/aws/table.ts +172 -0
- package/src/components/esbuild.ts +128 -0
- package/src/components/fs.ts +45 -0
- package/src/destroy.ts +63 -0
- package/src/error.ts +16 -0
- package/src/global.ts +72 -0
- package/src/index.ts +6 -0
- package/src/input.ts +16 -0
- package/src/main.ts +34 -0
- package/src/output.ts +49 -0
- package/src/resource.ts +313 -0
- package/src/state.ts +100 -0
- package/test/aws/function.test.ts +144 -0
- package/test/aws/queue.test.ts +85 -0
- package/test/aws/role.test.ts +153 -0
- package/test/aws/table.test.ts +73 -0
- package/test/esbuild.test.ts +41 -0
- package/test/handler.ts +9 -0
- package/tsconfig.json +7 -0
- package/Column.js +0 -1
- package/Create.js +0 -1
- package/Delete.js +0 -1
- package/Drop.js +0 -1
- package/Insert.js +0 -1
- package/Makefile +0 -8
- package/Select.js +0 -1
- package/Table.js +0 -1
- package/Transaction.js +0 -1
- package/Types.js +0 -1
- package/Update.js +0 -1
- package/alchemy.js +0 -57
- package/alchemy.sublime-project +0 -9
- package/alchemy.sublime-workspace +0 -2304
- package/config/app.js +0 -8
- package/config/db.js +0 -20
- package/copy.js +0 -1
- package/defaultEngine.js +0 -8
- package/engine.js +0 -282
- package/getInstantiatorFunction.js +0 -28
- package/index.js +0 -52
- package/jstest.js +0 -3
- package/loggerFactory.js +0 -27
- package/logs/alchemy.log +0 -46
- package/logs/sql.log +0 -41
- package/sql/Column.js +0 -158
- package/sql/Columnable.js +0 -21
- package/sql/Create.js +0 -15
- package/sql/Delete.js +0 -34
- package/sql/Drop.js +0 -36
- package/sql/Insert.js +0 -96
- package/sql/SchemaElement.js +0 -11
- package/sql/Select.js +0 -192
- package/sql/SqlBase.js +0 -134
- package/sql/SqlStatement.js +0 -80
- package/sql/Table.js +0 -96
- package/sql/Transaction.js +0 -45
- package/sql/Update.js +0 -105
- package/sql/defineElement.js +0 -26
- package/sql/defineStatement.js +0 -26
- package/sql/types/BaseType.js +0 -43
- package/sql/types/BigSerialType.js +0 -5
- package/sql/types/IntegerType.js +0 -5
- package/sql/types/JsonType.js +0 -5
- package/sql/types/SerialType.js +0 -5
- package/sql/types/StringType.js +0 -31
- package/sql/types/TimestampType.js +0 -5
- package/sql/types/UUIDType.js +0 -5
- package/sql/types/defineType.js +0 -25
- package/sql/types/getType.js +0 -12
- package/sql/types/index.js +0 -11
- package/sql/where.js +0 -31
- package/sql/whereToString.js +0 -29
- package/test/ColumnTests.js +0 -80
- package/test/CreateTable.js +0 -54
- package/test/DeleteTests.js +0 -28
- package/test/DropTests.js +0 -23
- package/test/GetTypeTests.js +0 -56
- package/test/InsertTests.js +0 -86
- package/test/SelectExistsTests.js +0 -26
- package/test/SelectTests.js +0 -130
- package/test/TableTests.js +0 -46
- package/test.js +0 -8
- package/test.ls +0 -4
- package/validate.js +0 -26
- package/x.js +0 -5
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ZodType } from "zod";
|
|
2
|
+
import { type Context, type Provider, Resource } from "../../resource";
|
|
3
|
+
|
|
4
|
+
export function Agent<Type extends string, TInput, TOutput>(
|
|
5
|
+
type: Type,
|
|
6
|
+
{
|
|
7
|
+
description,
|
|
8
|
+
input,
|
|
9
|
+
output,
|
|
10
|
+
}: {
|
|
11
|
+
description: string;
|
|
12
|
+
input: ZodType<TInput>;
|
|
13
|
+
output: ZodType<TOutput>;
|
|
14
|
+
},
|
|
15
|
+
handler: (ctx: Context<TOutput>, props: TInput) => Promise<TOutput | void>,
|
|
16
|
+
): Provider<Type, [TInput], Awaited<TOutput>> & {
|
|
17
|
+
description: string;
|
|
18
|
+
input: ZodType<TInput>;
|
|
19
|
+
output: ZodType<TOutput>;
|
|
20
|
+
} {
|
|
21
|
+
// @ts-expect-error - we don't care that the props are not statically known, they will be visible outside this scope
|
|
22
|
+
return class Agent extends Resource(
|
|
23
|
+
type,
|
|
24
|
+
async (ctx: Context<TOutput>, props: TInput): Promise<TOutput | void> => {
|
|
25
|
+
// Validate input
|
|
26
|
+
const validatedInput = input.parse(props);
|
|
27
|
+
|
|
28
|
+
// Call handler with validated input
|
|
29
|
+
const result = await handler(ctx, validatedInput);
|
|
30
|
+
|
|
31
|
+
if (ctx.event === "delete") {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Validate output
|
|
36
|
+
const validatedOutput = output.parse(result);
|
|
37
|
+
|
|
38
|
+
return validatedOutput;
|
|
39
|
+
},
|
|
40
|
+
) {
|
|
41
|
+
static readonly description = description;
|
|
42
|
+
static readonly input = input;
|
|
43
|
+
static readonly output = output;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://docs.anthropic.com/en/docs/about-claude/models#model-comparison-table
|
|
3
|
+
*/
|
|
4
|
+
export const AnthropicModels = [
|
|
5
|
+
// Claude 3.5 Sonnet models
|
|
6
|
+
"claude-3-5-sonnet",
|
|
7
|
+
"claude-3-5-sonnet-20241022",
|
|
8
|
+
"claude-3-5-sonnet-20240620",
|
|
9
|
+
|
|
10
|
+
// Claude 3.5 Haiku models
|
|
11
|
+
"claude-3-5-haiku",
|
|
12
|
+
"claude-3-5-haiku-20241022",
|
|
13
|
+
|
|
14
|
+
// Claude 3 models
|
|
15
|
+
"claude-3-opus",
|
|
16
|
+
"claude-3-opus-20240229",
|
|
17
|
+
"claude-3-sonnet",
|
|
18
|
+
"claude-3-sonnet-20240229",
|
|
19
|
+
"claude-3-haiku",
|
|
20
|
+
"claude-3-haiku-20240307",
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
23
|
+
export type AnthropicModelId = (typeof AnthropicModels)[number] | (string & {});
|
|
24
|
+
|
|
25
|
+
export function isAnthropicModel(model: string): model is AnthropicModelId {
|
|
26
|
+
return model.startsWith("claude-");
|
|
27
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AnthropicModelId, isAnthropicModel } from "./anthropic";
|
|
2
|
+
import { type OpenAIChatModelId, isOpenAIModel } from "./openai";
|
|
3
|
+
|
|
4
|
+
export type ModelId = OpenAIChatModelId | AnthropicModelId;
|
|
5
|
+
|
|
6
|
+
export async function resolveModel(modelId: ModelId) {
|
|
7
|
+
if (isOpenAIModel(modelId)) {
|
|
8
|
+
const { openai } = await import("@ai-sdk/openai");
|
|
9
|
+
return {
|
|
10
|
+
type: "openai" as const,
|
|
11
|
+
model: openai(modelId as OpenAIChatModelId),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
if (isAnthropicModel(modelId)) {
|
|
15
|
+
const { anthropic } = await import("@ai-sdk/anthropic");
|
|
16
|
+
return {
|
|
17
|
+
type: "anthropic" as const,
|
|
18
|
+
model: anthropic(modelId as AnthropicModelId),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`Unsupported model ID: ${modelId}`);
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const OpenAIModels = [
|
|
2
|
+
// O1 models
|
|
3
|
+
"o1",
|
|
4
|
+
"o1-2024-12-17",
|
|
5
|
+
"o1-mini",
|
|
6
|
+
"o1-mini-2024-09-12",
|
|
7
|
+
"o1-preview",
|
|
8
|
+
"o1-preview-2024-09-12",
|
|
9
|
+
|
|
10
|
+
// GPT-4O models
|
|
11
|
+
"gpt-4o",
|
|
12
|
+
"gpt-4o-2024-05-13",
|
|
13
|
+
"gpt-4o-2024-08-06",
|
|
14
|
+
"gpt-4o-2024-11-20",
|
|
15
|
+
"gpt-4o-audio-preview",
|
|
16
|
+
"gpt-4o-audio-preview-2024-10-01",
|
|
17
|
+
"gpt-4o-audio-preview-2024-12-17",
|
|
18
|
+
"gpt-4o-mini",
|
|
19
|
+
"gpt-4o-mini-2024-07-18",
|
|
20
|
+
|
|
21
|
+
// GPT-4 models
|
|
22
|
+
"gpt-4-turbo",
|
|
23
|
+
"gpt-4-turbo-2024-04-09",
|
|
24
|
+
"gpt-4-turbo-preview",
|
|
25
|
+
"gpt-4-0125-preview",
|
|
26
|
+
"gpt-4-1106-preview",
|
|
27
|
+
"gpt-4",
|
|
28
|
+
"gpt-4-0613",
|
|
29
|
+
|
|
30
|
+
// GPT-3.5 models
|
|
31
|
+
"gpt-3.5-turbo-0125",
|
|
32
|
+
"gpt-3.5-turbo",
|
|
33
|
+
"gpt-3.5-turbo-1106",
|
|
34
|
+
] as const;
|
|
35
|
+
|
|
36
|
+
export type OpenAIChatModelId = (typeof OpenAIModels)[number] | (string & {});
|
|
37
|
+
|
|
38
|
+
export function isOpenAIModel(model: string): model is OpenAIChatModelId {
|
|
39
|
+
return (
|
|
40
|
+
model.startsWith("gpt-") ||
|
|
41
|
+
model.startsWith("o1") ||
|
|
42
|
+
model.startsWith("gpt-4o")
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { generateObject } from "ai";
|
|
2
|
+
import { mkdir, unlink, writeFile } from "fs/promises";
|
|
3
|
+
import { dirname } from "path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Agent } from "./agent";
|
|
6
|
+
import type { AnthropicModelId } from "./anthropic";
|
|
7
|
+
import { resolveModel } from "./model";
|
|
8
|
+
import type { OpenAIChatModelId } from "./openai";
|
|
9
|
+
|
|
10
|
+
export type ModelId = OpenAIChatModelId | AnthropicModelId;
|
|
11
|
+
|
|
12
|
+
export const PackageJsonSchema = z.object({
|
|
13
|
+
name: z.string(),
|
|
14
|
+
version: z.string(),
|
|
15
|
+
description: z.string().optional(),
|
|
16
|
+
main: z.string().optional(),
|
|
17
|
+
types: z.string().optional(),
|
|
18
|
+
type: z.literal("module"),
|
|
19
|
+
scripts: z.record(z.string()).optional(),
|
|
20
|
+
peerDependencies: z.record(z.string()).optional(),
|
|
21
|
+
peerDependenciesMeta: z
|
|
22
|
+
.record(z.object({ optional: z.boolean() }))
|
|
23
|
+
.optional(),
|
|
24
|
+
devDependencies: z.record(z.string()).optional(),
|
|
25
|
+
keywords: z.array(z.string()).optional(),
|
|
26
|
+
author: z.string().optional(),
|
|
27
|
+
license: z.string().optional(),
|
|
28
|
+
repository: z
|
|
29
|
+
.object({
|
|
30
|
+
type: z.string(),
|
|
31
|
+
url: z.string(),
|
|
32
|
+
})
|
|
33
|
+
.optional(),
|
|
34
|
+
exports: z.unknown().optional(),
|
|
35
|
+
files: z.array(z.string()).optional(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const PackageInput = z.object({
|
|
39
|
+
/**
|
|
40
|
+
* List of requirements for the package
|
|
41
|
+
* Can include dependencies, dev dependencies, scripts, etc.
|
|
42
|
+
*/
|
|
43
|
+
requirements: z.array(z.string()),
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Name of the package
|
|
47
|
+
*/
|
|
48
|
+
name: z.string(),
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The ID of the model to use for generating package configuration
|
|
52
|
+
* @default "gpt-4o"
|
|
53
|
+
*/
|
|
54
|
+
model: z.string().optional(),
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Temperature setting for model generation
|
|
58
|
+
* @default 0.3
|
|
59
|
+
*/
|
|
60
|
+
temperature: z.number().optional(),
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Path to the package.json file to generate
|
|
64
|
+
*/
|
|
65
|
+
path: z.string(),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export type PackageInput = z.infer<typeof PackageInput>;
|
|
69
|
+
export type PackageOutput = z.infer<typeof PackageJsonSchema>;
|
|
70
|
+
|
|
71
|
+
export class PackageJson extends Agent(
|
|
72
|
+
"code::Package",
|
|
73
|
+
{
|
|
74
|
+
description:
|
|
75
|
+
"This Agent is responsible for generating package.json configuration based on requirements.",
|
|
76
|
+
input: PackageInput,
|
|
77
|
+
output: PackageJsonSchema,
|
|
78
|
+
},
|
|
79
|
+
async (ctx, input) => {
|
|
80
|
+
if (ctx.event === "delete") {
|
|
81
|
+
await unlink(input.path);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Get the appropriate model
|
|
86
|
+
const { model } = await resolveModel(input.model ?? "gpt-4o");
|
|
87
|
+
|
|
88
|
+
// Generate the package configuration using generateObject for type safety
|
|
89
|
+
const result = await generateObject({
|
|
90
|
+
model,
|
|
91
|
+
schema: PackageJsonSchema,
|
|
92
|
+
temperature: input.temperature ?? 0.3,
|
|
93
|
+
messages: [
|
|
94
|
+
{
|
|
95
|
+
role: "system",
|
|
96
|
+
content:
|
|
97
|
+
"You are an expert at creating Node.js/TypeScript package configurations. You will generate a package.json configuration based on requirements.",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
role: "user",
|
|
101
|
+
content: `Please generate a package.json configuration based on these requirements:
|
|
102
|
+
|
|
103
|
+
Package name: ${input.name}
|
|
104
|
+
|
|
105
|
+
Requirements:
|
|
106
|
+
${input.requirements.map((req) => `- ${req}`).join("\n")}
|
|
107
|
+
|
|
108
|
+
Rules:
|
|
109
|
+
1. All dependencies must be peer dependencies
|
|
110
|
+
2. Use latest stable versions for all dependencies
|
|
111
|
+
3. Include standard TypeScript configuration in devDependencies
|
|
112
|
+
4. Use "bun" as the package manager
|
|
113
|
+
5. Must use ESM modules (type: "module")`,
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Ensure the directory exists
|
|
119
|
+
await mkdir(dirname(input.path), { recursive: true });
|
|
120
|
+
|
|
121
|
+
// Write the package.json file
|
|
122
|
+
await writeFile(input.path, JSON.stringify(result.object, null, 2));
|
|
123
|
+
|
|
124
|
+
return result.object;
|
|
125
|
+
},
|
|
126
|
+
) {}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { generateText } from "ai";
|
|
2
|
+
import { mkdir, unlink, writeFile } from "fs/promises";
|
|
3
|
+
import { dirname } from "path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Agent } from "./agent";
|
|
6
|
+
import { resolveModel } from "./model";
|
|
7
|
+
import { scrapeWebPage } from "./scrape";
|
|
8
|
+
|
|
9
|
+
export const RequirementsInput = z.object({
|
|
10
|
+
/**
|
|
11
|
+
* The ID of the model to use for generating requirements documentation
|
|
12
|
+
* @default "gpt-4o"
|
|
13
|
+
*/
|
|
14
|
+
modelId: z.string().optional(),
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* List of requirements to document and analyze
|
|
18
|
+
*/
|
|
19
|
+
requirements: z.array(z.string()),
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* One-line summary of the requirements document
|
|
23
|
+
*/
|
|
24
|
+
title: z.string(),
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Temperature setting for model generation (higher = more creative, lower = more focused)
|
|
28
|
+
* @default 0.7
|
|
29
|
+
*/
|
|
30
|
+
temperature: z.number().optional(),
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* File path where the requirements document should be written
|
|
34
|
+
*/
|
|
35
|
+
path: z.string(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const RequirementsOutput = z.object({
|
|
39
|
+
/**
|
|
40
|
+
* Generated markdown document containing organized and analyzed requirements
|
|
41
|
+
*/
|
|
42
|
+
content: z.string(),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export type RequirementsInput = z.infer<typeof RequirementsInput>;
|
|
46
|
+
export type RequirementsOutput = z.infer<typeof RequirementsOutput>;
|
|
47
|
+
|
|
48
|
+
export class Requirements extends Agent(
|
|
49
|
+
"code::Requirements",
|
|
50
|
+
{
|
|
51
|
+
description:
|
|
52
|
+
"This Agent is responsible for writing and refining a detailed requirements document from a list of requirements.",
|
|
53
|
+
input: RequirementsInput,
|
|
54
|
+
output: RequirementsOutput,
|
|
55
|
+
},
|
|
56
|
+
async (ctx, input) => {
|
|
57
|
+
if (ctx.event === "delete") {
|
|
58
|
+
await unlink(input.path);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Get the appropriate model based on the ID
|
|
63
|
+
const { model } = await resolveModel(input.modelId ?? "gpt-4o");
|
|
64
|
+
|
|
65
|
+
// Generate the requirements document
|
|
66
|
+
const { text } = await generateText({
|
|
67
|
+
model,
|
|
68
|
+
temperature: input.temperature ?? 0.7,
|
|
69
|
+
maxSteps: 3, // Allow multiple steps for potential tool usage
|
|
70
|
+
tools: {
|
|
71
|
+
scrapeWebPage,
|
|
72
|
+
},
|
|
73
|
+
messages: [
|
|
74
|
+
{
|
|
75
|
+
role: "system",
|
|
76
|
+
content:
|
|
77
|
+
"You are a helpful assistant that creates markdown documents from requirements. You can use the scrapeWebPage tool to get additional requirements from relevant URLs if needed.",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
role: "user",
|
|
81
|
+
content: `Please analyze the following system requirements and create a comprehensive, unambiguous markdown document that covers all aspects:
|
|
82
|
+
|
|
83
|
+
Title: ${input.title}
|
|
84
|
+
|
|
85
|
+
Requirements:
|
|
86
|
+
${input.requirements.map((req) => `- ${req}`).join("\n")}
|
|
87
|
+
|
|
88
|
+
Guidelines:
|
|
89
|
+
1. Make explicit decisions for any ambiguous requirements - do not leave open questions
|
|
90
|
+
2. Document the reasoning behind key decisions
|
|
91
|
+
3. Be specific about technical choices and implementation details
|
|
92
|
+
4. Avoid phrases like "could be", "might need", or "possibly requires" - be definitive
|
|
93
|
+
5. Organize requirements into logical sections with clear dependencies and relationships
|
|
94
|
+
|
|
95
|
+
Format the output in markdown with appropriate headers, lists, and sections, starting with the title as an H1 header.
|
|
96
|
+
Include technical considerations and implementation details, ensuring every requirement has a clear, actionable specification.`,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Ensure the directory exists
|
|
102
|
+
await mkdir(dirname(input.path), { recursive: true });
|
|
103
|
+
|
|
104
|
+
// Write the requirements to the file
|
|
105
|
+
await writeFile(input.path, text);
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
content: text,
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
) {}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
2
|
+
import TurndownService from "turndown";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
export const scrapeWebPage = tool({
|
|
6
|
+
description: "Scrapes a web page and converts HTML content to Markdown",
|
|
7
|
+
parameters: z.object({
|
|
8
|
+
url: z.string().url().describe("The URL to scrape content from"),
|
|
9
|
+
turndownOptions: z
|
|
10
|
+
.object({
|
|
11
|
+
headingStyle: z.enum(["setext", "atx"]).optional(),
|
|
12
|
+
hr: z.string().optional(),
|
|
13
|
+
bulletListMarker: z.enum(["-", "*", "+"]).optional(),
|
|
14
|
+
codeBlockStyle: z.enum(["indented", "fenced"]).optional(),
|
|
15
|
+
emDelimiter: z.enum(["_", "*"]).optional(),
|
|
16
|
+
strongDelimiter: z.enum(["__", "**"]).optional(),
|
|
17
|
+
linkStyle: z.enum(["inlined", "referenced"]).optional(),
|
|
18
|
+
linkReferenceStyle: z
|
|
19
|
+
.enum(["full", "collapsed", "shortcut"])
|
|
20
|
+
.optional(),
|
|
21
|
+
})
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Custom options for Turndown HTML to Markdown conversion"),
|
|
24
|
+
}),
|
|
25
|
+
execute: async ({ url, turndownOptions }) => {
|
|
26
|
+
console.log("Scraping web page:", url);
|
|
27
|
+
try {
|
|
28
|
+
// Fetch the page content
|
|
29
|
+
const response = await fetch(url);
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Get the HTML content
|
|
35
|
+
const html = await response.text();
|
|
36
|
+
|
|
37
|
+
// Initialize Turndown with options
|
|
38
|
+
const turndownService = new TurndownService(turndownOptions);
|
|
39
|
+
|
|
40
|
+
// Convert HTML to Markdown and return
|
|
41
|
+
return turndownService.turndown(html);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error("Error scraping web page:", error);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { generateObject } from "ai";
|
|
2
|
+
import { mkdir, unlink, writeFile } from "fs/promises";
|
|
3
|
+
import { dirname } from "path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Agent } from "./agent";
|
|
6
|
+
import { resolveModel } from "./model";
|
|
7
|
+
|
|
8
|
+
export type TsConfigProps = z.infer<typeof TsConfigProps>;
|
|
9
|
+
|
|
10
|
+
export const TsConfigProps = z.object({
|
|
11
|
+
/**
|
|
12
|
+
* The ID of the model to use for generating tsconfig configuration
|
|
13
|
+
* @default "gpt-4o"
|
|
14
|
+
*/
|
|
15
|
+
modelId: z.string().optional(),
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* List of requirements for the TypeScript configuration
|
|
19
|
+
* Can include module settings, compilation options, etc.
|
|
20
|
+
*/
|
|
21
|
+
requirements: z.array(z.string()),
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Temperature setting for model generation
|
|
25
|
+
* @default 0.3
|
|
26
|
+
*/
|
|
27
|
+
temperature: z.number().optional(),
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Path to the tsconfig.json file to generate
|
|
31
|
+
*/
|
|
32
|
+
path: z.string(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export type TsConfigJson = z.infer<typeof TsConfigSchema>;
|
|
36
|
+
export const TsConfigSchema = z.object({
|
|
37
|
+
$schema: z.string().optional(),
|
|
38
|
+
compilerOptions: z.object({
|
|
39
|
+
target: z.enum([
|
|
40
|
+
"es2015",
|
|
41
|
+
"es2016",
|
|
42
|
+
"es2017",
|
|
43
|
+
"es2018",
|
|
44
|
+
"es2019",
|
|
45
|
+
"es2020",
|
|
46
|
+
"es2021",
|
|
47
|
+
"es2022",
|
|
48
|
+
"esnext",
|
|
49
|
+
]),
|
|
50
|
+
module: z.enum([
|
|
51
|
+
"commonjs",
|
|
52
|
+
"es2015",
|
|
53
|
+
"es2020",
|
|
54
|
+
"es2022",
|
|
55
|
+
"esnext",
|
|
56
|
+
"node16",
|
|
57
|
+
"nodenext",
|
|
58
|
+
]),
|
|
59
|
+
lib: z.array(z.string()).optional(),
|
|
60
|
+
declaration: z.boolean().optional(),
|
|
61
|
+
declarationMap: z.boolean().optional(),
|
|
62
|
+
sourceMap: z.boolean().optional(),
|
|
63
|
+
outDir: z.string().optional(),
|
|
64
|
+
rootDir: z.string().optional(),
|
|
65
|
+
strict: z.boolean(),
|
|
66
|
+
esModuleInterop: z.boolean().optional(),
|
|
67
|
+
skipLibCheck: z.boolean().optional(),
|
|
68
|
+
forceConsistentCasingInFileNames: z.boolean().optional(),
|
|
69
|
+
moduleResolution: z
|
|
70
|
+
.enum(["node", "node16", "nodenext", "bundler"])
|
|
71
|
+
.optional(),
|
|
72
|
+
resolveJsonModule: z.boolean().optional(),
|
|
73
|
+
isolatedModules: z.boolean().optional(),
|
|
74
|
+
allowJs: z.boolean().optional(),
|
|
75
|
+
checkJs: z.boolean().optional(),
|
|
76
|
+
noEmit: z.boolean().optional(),
|
|
77
|
+
incremental: z.boolean().optional(),
|
|
78
|
+
composite: z.boolean().optional(),
|
|
79
|
+
tsBuildInfoFile: z.string().optional(),
|
|
80
|
+
paths: z.record(z.array(z.string())).optional(),
|
|
81
|
+
baseUrl: z.string().optional(),
|
|
82
|
+
types: z.array(z.string()).optional(),
|
|
83
|
+
typeRoots: z.array(z.string()).optional(),
|
|
84
|
+
}),
|
|
85
|
+
include: z.array(z.string()).optional(),
|
|
86
|
+
exclude: z.array(z.string()).optional(),
|
|
87
|
+
references: z
|
|
88
|
+
.array(
|
|
89
|
+
z.object({
|
|
90
|
+
path: z.string(),
|
|
91
|
+
}),
|
|
92
|
+
)
|
|
93
|
+
.optional(),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export class TypeScriptConfig extends Agent(
|
|
97
|
+
"code::tsconfig",
|
|
98
|
+
{
|
|
99
|
+
description:
|
|
100
|
+
"This Agent is responsible for generating tsconfig.json configuration based on requirements.",
|
|
101
|
+
input: TsConfigProps,
|
|
102
|
+
output: TsConfigSchema,
|
|
103
|
+
},
|
|
104
|
+
async (ctx, props) => {
|
|
105
|
+
if (ctx.event === "delete") {
|
|
106
|
+
await unlink(props.path);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Get the appropriate model
|
|
111
|
+
const { model } = await resolveModel(props.modelId ?? "gpt-4o");
|
|
112
|
+
|
|
113
|
+
// Generate the tsconfig configuration using generateObject for type safety
|
|
114
|
+
const result = await generateObject({
|
|
115
|
+
model,
|
|
116
|
+
schema: TsConfigSchema,
|
|
117
|
+
temperature: props.temperature ?? 0.3,
|
|
118
|
+
messages: [
|
|
119
|
+
{
|
|
120
|
+
role: "system",
|
|
121
|
+
content:
|
|
122
|
+
"You are an expert at creating TypeScript configurations. You will generate a tsconfig.json configuration based on requirements.",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
role: "user",
|
|
126
|
+
content: `Please generate a tsconfig.json configuration based on these requirements:
|
|
127
|
+
|
|
128
|
+
Requirements:
|
|
129
|
+
${props.requirements.map((req) => `- ${req}`).join("\n")}
|
|
130
|
+
|
|
131
|
+
Rules:
|
|
132
|
+
1. Use modern TypeScript features
|
|
133
|
+
2. Enable strict type checking
|
|
134
|
+
3. Use ESM modules by default
|
|
135
|
+
4. Include source maps for better debugging
|
|
136
|
+
5. Infer appropriate settings for declarations, module resolution, and other options based on the requirements
|
|
137
|
+
6. Use appropriate paths for source and output directories`,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Ensure the directory exists
|
|
143
|
+
await mkdir(dirname(props.path), { recursive: true });
|
|
144
|
+
|
|
145
|
+
// Write the tsconfig.json file
|
|
146
|
+
await writeFile(props.path, JSON.stringify(result.object, null, 2));
|
|
147
|
+
|
|
148
|
+
return result.object;
|
|
149
|
+
},
|
|
150
|
+
) {}
|