Skip to content

Commit 3bb71f3

Browse files
committed
chore: infer when possible, move schemas, add tsconfig to scripts
1 parent a881cb5 commit 3bb71f3

File tree

6 files changed

+144
-160
lines changed

6 files changed

+144
-160
lines changed

packages/mcp-server/scripts/generate-summaries.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ import { writeFile, mkdir } from 'fs/promises';
44
import path from 'path';
55
import { fileURLToPath } from 'url';
66
import { get_sections } from '../src/mcp/utils.ts';
7-
import {
8-
AnthropicProvider,
9-
type AnthropicBatchRequest,
10-
type SummaryData,
11-
} from '../src/lib/anthropic.ts';
7+
import { AnthropicProvider } from '../src/lib/anthropic.ts';
8+
import { type AnthropicBatchRequest, type SummaryData } from '../src/lib/schemas.ts';
129

1310
const current_filename = fileURLToPath(import.meta.url);
1411
const current_dirname = path.dirname(current_filename);
@@ -57,14 +54,7 @@ Here is the documentation page content to analyze:
5754
5855
`;
5956

60-
interface Section {
61-
title: string;
62-
use_cases: string;
63-
slug: string;
64-
url: string;
65-
}
66-
67-
async function fetch_section_content(url: string): Promise<string> {
57+
async function fetch_section_content(url: string) {
6858
const response = await fetch(url, { signal: AbortSignal.timeout(30000) });
6959
if (!response.ok) {
7060
throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
@@ -86,7 +76,7 @@ async function main() {
8676

8777
// Get all sections
8878
console.log('📚 Fetching documentation sections...');
89-
let sections: Section[] = await get_sections();
79+
let sections = await get_sections();
9080
console.log(`Found ${sections.length} sections`);
9181

9282
// Debug mode: limit to 2 sections
@@ -99,7 +89,7 @@ async function main() {
9989
// Fetch content for each section
10090
console.log('📥 Downloading section content...');
10191
const sections_with_content: Array<{
102-
section: Section;
92+
section: (typeof sections)[number];
10393
content: string;
10494
index: number;
10595
}> = [];
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": "../../../tsconfig.json",
3+
"compilerOptions": {
4+
"allowImportingTsExtensions": true
5+
}
6+
}

packages/mcp-server/src/lib/anthropic.ts

Lines changed: 8 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,11 @@
11
import { Anthropic } from '@anthropic-ai/sdk';
22
import type { Model } from '@anthropic-ai/sdk/resources/messages/messages.js';
33
import * as v from 'valibot';
4-
5-
// Valibot schemas for Batch API
6-
export const summary_data_schema = v.object({
7-
generated_at: v.string(),
8-
model: v.string(),
9-
total_sections: v.number(),
10-
successful_summaries: v.number(),
11-
failed_summaries: v.number(),
12-
summaries: v.record(v.string(), v.string()),
13-
errors: v.optional(
14-
v.array(
15-
v.object({
16-
section: v.string(),
17-
error: v.string(),
18-
}),
19-
),
20-
),
21-
download_errors: v.optional(
22-
v.array(
23-
v.object({
24-
section: v.string(),
25-
error: v.string(),
26-
}),
27-
),
28-
),
29-
});
30-
31-
export const anthropic_batch_request_schema = v.object({
32-
custom_id: v.string(),
33-
params: v.object({
34-
model: v.string(),
35-
max_tokens: v.number(),
36-
messages: v.array(
37-
v.object({
38-
role: v.union([v.literal('user'), v.literal('assistant')]),
39-
content: v.union([
40-
v.string(),
41-
v.array(
42-
v.object({
43-
type: v.string(),
44-
text: v.string(),
45-
}),
46-
),
47-
]),
48-
}),
49-
),
50-
}),
51-
});
52-
53-
export const anthropic_batch_response_schema = v.object({
54-
id: v.string(),
55-
type: v.string(),
56-
processing_status: v.union([v.literal('in_progress'), v.literal('ended')]),
57-
request_counts: v.object({
58-
processing: v.number(),
59-
succeeded: v.number(),
60-
errored: v.number(),
61-
canceled: v.number(),
62-
expired: v.number(),
63-
}),
64-
ended_at: v.nullable(v.string()),
65-
created_at: v.string(),
66-
expires_at: v.string(),
67-
cancel_initiated_at: v.nullable(v.string()),
68-
results_url: v.nullable(v.string()),
69-
});
70-
71-
export const anthropic_batch_result_schema = v.object({
72-
custom_id: v.string(),
73-
result: v.object({
74-
type: v.union([
75-
v.literal('succeeded'),
76-
v.literal('errored'),
77-
v.literal('canceled'),
78-
v.literal('expired'),
79-
]),
80-
message: v.optional(
81-
v.object({
82-
id: v.string(),
83-
type: v.string(),
84-
role: v.string(),
85-
model: v.string(),
86-
content: v.array(
87-
v.object({
88-
type: v.string(),
89-
text: v.string(),
90-
}),
91-
),
92-
stop_reason: v.string(),
93-
stop_sequence: v.nullable(v.string()),
94-
usage: v.object({
95-
input_tokens: v.number(),
96-
output_tokens: v.number(),
97-
}),
98-
}),
99-
),
100-
error: v.optional(
101-
v.object({
102-
type: v.string(),
103-
message: v.string(),
104-
}),
105-
),
106-
}),
107-
});
108-
109-
// Export inferred types
110-
export type SummaryData = v.InferOutput<typeof summary_data_schema>;
111-
export type AnthropicBatchRequest = v.InferOutput<typeof anthropic_batch_request_schema>;
112-
export type AnthropicBatchResponse = v.InferOutput<typeof anthropic_batch_response_schema>;
113-
export type AnthropicBatchResult = v.InferOutput<typeof anthropic_batch_result_schema>;
4+
import {
5+
anthropic_batch_response_schema,
6+
anthropic_batch_result_schema,
7+
type AnthropicBatchRequest,
8+
} from './schemas.js';
1149

11510
export class AnthropicProvider {
11611
private client: Anthropic;
@@ -137,7 +32,7 @@ export class AnthropicProvider {
13732
return this.modelId;
13833
}
13934

140-
async create_batch(requests: AnthropicBatchRequest[]): Promise<AnthropicBatchResponse> {
35+
async create_batch(requests: AnthropicBatchRequest[]) {
14136
try {
14237
const response = await fetch(`${this.baseUrl}/messages/batches`, {
14338
method: 'POST',
@@ -174,11 +69,7 @@ export class AnthropicProvider {
17469
}
17570
}
17671

177-
async get_batch_status(
178-
batch_id: string,
179-
max_retries = 10,
180-
retry_delay = 30000,
181-
): Promise<AnthropicBatchResponse> {
72+
async get_batch_status(batch_id: string, max_retries = 10, retry_delay = 30000) {
18273
let retry_count = 0;
18374

18475
while (retry_count <= max_retries) {
@@ -237,7 +128,7 @@ export class AnthropicProvider {
237128
throw new Error(`Failed to get batch status for ${batch_id} after ${max_retries} retries`);
238129
}
239130

240-
async get_batch_results(results_url: string): Promise<AnthropicBatchResult[]> {
131+
async get_batch_results(results_url: string) {
241132
try {
242133
const response = await fetch(results_url, {
243134
method: 'GET',
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import * as v from 'valibot';
2+
3+
export const documentation_sections_schema = v.record(
4+
v.string(),
5+
v.object({
6+
metadata: v.object({
7+
title: v.string(),
8+
use_cases: v.optional(v.string()),
9+
}),
10+
slug: v.string(),
11+
}),
12+
);
13+
14+
// Valibot schemas for Batch API
15+
export const summary_data_schema = v.object({
16+
generated_at: v.string(),
17+
model: v.string(),
18+
total_sections: v.number(),
19+
successful_summaries: v.number(),
20+
failed_summaries: v.number(),
21+
summaries: v.record(v.string(), v.string()),
22+
errors: v.optional(
23+
v.array(
24+
v.object({
25+
section: v.string(),
26+
error: v.string(),
27+
}),
28+
),
29+
),
30+
download_errors: v.optional(
31+
v.array(
32+
v.object({
33+
section: v.string(),
34+
error: v.string(),
35+
}),
36+
),
37+
),
38+
});
39+
40+
export const anthropic_batch_request_schema = v.object({
41+
custom_id: v.string(),
42+
params: v.object({
43+
model: v.string(),
44+
max_tokens: v.number(),
45+
messages: v.array(
46+
v.object({
47+
role: v.union([v.literal('user'), v.literal('assistant')]),
48+
content: v.union([
49+
v.string(),
50+
v.array(
51+
v.object({
52+
type: v.string(),
53+
text: v.string(),
54+
}),
55+
),
56+
]),
57+
}),
58+
),
59+
}),
60+
});
61+
62+
export const anthropic_batch_response_schema = v.object({
63+
id: v.string(),
64+
type: v.string(),
65+
processing_status: v.union([v.literal('in_progress'), v.literal('ended')]),
66+
request_counts: v.object({
67+
processing: v.number(),
68+
succeeded: v.number(),
69+
errored: v.number(),
70+
canceled: v.number(),
71+
expired: v.number(),
72+
}),
73+
ended_at: v.nullable(v.string()),
74+
created_at: v.string(),
75+
expires_at: v.string(),
76+
cancel_initiated_at: v.nullable(v.string()),
77+
results_url: v.nullable(v.string()),
78+
});
79+
80+
export const anthropic_batch_result_schema = v.object({
81+
custom_id: v.string(),
82+
result: v.object({
83+
type: v.union([
84+
v.literal('succeeded'),
85+
v.literal('errored'),
86+
v.literal('canceled'),
87+
v.literal('expired'),
88+
]),
89+
message: v.optional(
90+
v.object({
91+
id: v.string(),
92+
type: v.string(),
93+
role: v.string(),
94+
model: v.string(),
95+
content: v.array(
96+
v.object({
97+
type: v.string(),
98+
text: v.string(),
99+
}),
100+
),
101+
stop_reason: v.string(),
102+
stop_sequence: v.nullable(v.string()),
103+
usage: v.object({
104+
input_tokens: v.number(),
105+
output_tokens: v.number(),
106+
}),
107+
}),
108+
),
109+
error: v.optional(
110+
v.object({
111+
type: v.string(),
112+
message: v.string(),
113+
}),
114+
),
115+
}),
116+
});
117+
118+
// Export inferred types
119+
export type SummaryData = v.InferOutput<typeof summary_data_schema>;
120+
export type AnthropicBatchRequest = v.InferOutput<typeof anthropic_batch_request_schema>;
121+
export type AnthropicBatchResponse = v.InferOutput<typeof anthropic_batch_response_schema>;
122+
export type AnthropicBatchResult = v.InferOutput<typeof anthropic_batch_result_schema>;

packages/mcp-server/src/mcp/schemas/index.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

packages/mcp-server/src/mcp/utils.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as v from 'valibot';
2-
import { documentation_sections_schema, section_schema } from '../mcp/schemas/index.ts';
2+
import { documentation_sections_schema } from '../lib/schemas.js';
33
import summary_data from '../use_cases.json' with { type: 'json' };
44

55
export async function fetch_with_timeout(
@@ -45,16 +45,10 @@ export async function get_sections() {
4545
};
4646
});
4747

48-
const validated_output = v.safeParse(v.array(section_schema), mapped_sections);
49-
if (!validated_output.success) {
50-
console.error('Section validation failed:', validated_output.issues);
51-
return [];
52-
}
53-
54-
return validated_output.output;
48+
return mapped_sections;
5549
}
5650

57-
export async function format_sections_list(): Promise<string> {
51+
export async function format_sections_list() {
5852
const sections = await get_sections();
5953
return sections
6054
.map((s) => `* title: ${s.title}, use_cases: ${s.use_cases}, path: ${s.slug}`)

0 commit comments

Comments
 (0)