Skip to content

Commit 842d900

Browse files
committed
Reverse refactor, use hono/client
Mostly taming errors unsure if anything works
1 parent 6db5688 commit 842d900

File tree

17 files changed

+91
-123
lines changed

17 files changed

+91
-123
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export async function handleResponse<T>(response: Response): Promise<T> {
2+
const data = await response.json();
3+
4+
if ('error' in data) {
5+
throw new Error(data.error);
6+
}
7+
8+
if (data.type === 'json') {
9+
return data.body;
10+
}
11+
12+
if (data instanceof Response) {
13+
throw new Error(data.statusText);
14+
}
15+
16+
return null as never;
17+
}

typescript/packages/toolshed/lib/llm/generateText.ts renamed to typescript/packages/toolshed/routes/ai/llm/generateText.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ import type { Context } from "hono";
1616
export interface GenerateTextParams {
1717
model?: string;
1818
task?: string;
19-
messages: { role: string; content: string }[];
19+
messages: { role: 'user' | 'assistant'; content: string }[];
2020
system?: string;
2121
stream?: boolean;
2222
stop_token?: string;
2323
abortSignal?: AbortSignal;
2424
}
2525

2626
export interface GenerateTextResult {
27-
message: { role: string; content: string };
27+
message: { role: 'user' | 'assistant'; content: string };
2828
stream?: ReadableStream;
2929
}
3030

@@ -48,15 +48,15 @@ export async function generateText(
4848
}
4949

5050
// Validate and configure model
51-
const modelConfig = findModel(modelName);
51+
const modelConfig = findModel(modelName!);
5252
if (!modelConfig) {
5353
console.error("Unsupported model:", modelName);
5454
throw new Error(`Unsupported model: ${modelName}`);
5555
}
5656

5757
const messages = params.messages;
5858
const streamParams = {
59-
model: modelConfig.model || modelName,
59+
model: modelConfig.model || modelName!,
6060
messages,
6161
stream: params.stream,
6262
system: params.system,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { AppType } from "@/app.ts";
2+
import { hc } from "hono/client";
3+
import { handleResponse } from "@/lib/response.ts";
4+
5+
const client = hc<AppType>("http://localhost:8000/");
6+
7+
export async function generateText(query: Parameters<typeof client.api.ai.llm.$post>[0]["json"]) {
8+
const res = await client.api.ai.llm.$post({ json: query });
9+
return handleResponse<{ content: string, role: string }>(res).then(data => data.content);
10+
}
11+
12+
export async function getAllBlobs(): Promise<string[]> {
13+
const res = await client.api.storage.blobby.get$();
14+
return handleResponse(res);
15+
}
16+
17+
export async function getBlob(key: string): Promise<string> {
18+
const res = await client.api.storage.blobby.get$(key);
19+
return handleResponse(res);
20+
}

typescript/packages/toolshed/lib/behavior/search.ts renamed to typescript/packages/toolshed/routes/ai/spell/behavior/search.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { BehaviourTree, State } from "mistreevous";
2-
import { BaseAgent } from "./agent.ts";
2+
import { BaseAgent } from "@/lib/agent.ts";
33
import { scanForKey } from "./strategies/scanForKey.ts";
44
import { scanForText } from "./strategies/scanForText.ts";
55
import { generateSchema, scanBySchema } from "./strategies/scanBySchema.ts";
66
import { scanByCollections } from "./strategies/scanByCollections.ts";
7-
import { Logger } from "../prefixed-logger.ts";
8-
import type { RedisClientType } from "redis";
7+
import { Logger } from "@/lib/prefixed-logger.ts";
98

109
export interface SearchResult {
1110
source: string;
@@ -47,12 +46,10 @@ class SearchAgent extends BaseAgent {
4746
private query: string = "";
4847
private results: SearchResult[] = [];
4948
private searchPromises: Map<string, Promise<SearchResult>> = new Map();
50-
private redis: RedisClientType;
5149

52-
constructor(query: string, redis: RedisClientType, logger: Logger) {
50+
constructor(query: string, logger: Logger) {
5351
super(logger, "SearchAgent");
5452
this.query = query;
55-
this.redis = redis;
5653
this.resetSearch();
5754
}
5855

@@ -77,7 +74,7 @@ class SearchAgent extends BaseAgent {
7774
this.logger.info("Starting key match search");
7875
this.searchPromises.set(
7976
"key-search",
80-
scanForKey(this.query, this.redis, this.logger),
77+
scanForKey(this.query, this.logger),
8178
);
8279
}
8380
return await resolve(State.SUCCEEDED);
@@ -90,7 +87,7 @@ class SearchAgent extends BaseAgent {
9087
this.logger.info("Starting text match search");
9188
this.searchPromises.set(
9289
"text-search",
93-
scanForText(this.query, this.redis, this.logger),
90+
scanForText(this.query, this.logger),
9491
);
9592
}
9693
return await resolve(State.SUCCEEDED);
@@ -106,7 +103,7 @@ class SearchAgent extends BaseAgent {
106103

107104
this.searchPromises.set(
108105
"schema-match",
109-
scanBySchema(schema, this.redis, this.logger),
106+
scanBySchema(schema, this.logger),
110107
);
111108
}
112109
return await resolve(State.SUCCEEDED);
@@ -119,7 +116,7 @@ class SearchAgent extends BaseAgent {
119116
this.logger.info("Starting collection match search");
120117
this.searchPromises.set(
121118
"collection-match",
122-
scanByCollections(this.query, this.redis, this.logger),
119+
scanByCollections(this.query, this.logger),
123120
);
124121
}
125122
return await resolve(State.SUCCEEDED);
@@ -171,11 +168,10 @@ class SearchAgent extends BaseAgent {
171168

172169
export function performSearch(
173170
query: string,
174-
redis: RedisClientType,
175171
logger: Logger,
176172
): Promise<CombinedResults> {
177173
return new Promise((resolve, reject) => {
178-
const agent = new SearchAgent(query, redis, logger);
174+
const agent = new SearchAgent(query, logger);
179175
const tree = new BehaviourTree(searchTreeDefinition, agent);
180176

181177
logger.info("Starting behavior tree execution");

typescript/packages/toolshed/lib/behavior/strategies/scanByCollections.ts renamed to typescript/packages/toolshed/routes/ai/spell/behavior/strategies/scanByCollections.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,25 @@
1-
import { storage } from "@/storage.ts";
21
import { SearchResult } from "../search.ts";
3-
import { Logger, PrefixedLogger } from "../../prefixed-logger.ts";
4-
import { generateText } from "../../llm/generateText.ts";
5-
import type { RedisClientType } from "redis";
2+
import { Logger, PrefixedLogger } from "@/lib/prefixed-logger.ts";
3+
import { generateText, getBlob} from "../effects.ts";
64

75
async function generateKeywords(
86
query: string,
97
logger: Logger,
108
): Promise<string[]> {
119
logger.info(`Generating keywords for query: ${query}`);
12-
1310
const keywordPrompt = {
1411
model: "claude-3-5-sonnet",
1512
messages: [
1613
{
17-
role: "system",
18-
content:
19-
"Generate exactly 3 single-word collection names that would be relevant for organizing content related to this query. Return only a JSON array of 3 strings.",
20-
},
21-
{
22-
role: "user",
14+
role: "user" as const,
2315
content: query,
2416
},
2517
],
18+
system: "Generate exactly 3 single-word collection names that would be relevant for organizing content related to this query. Return only a JSON array of 3 strings.",
2619
stream: false,
2720
};
28-
2921
const keywordText = await generateText(keywordPrompt);
30-
const keywords = JSON.parse(keywordText.message.content);
22+
const keywords = JSON.parse(keywordText);
3123

3224
// Add original query if it's a single word
3325
if (query.trim().split(/\s+/).length === 1) {
@@ -40,7 +32,6 @@ async function generateKeywords(
4032

4133
export async function scanByCollections(
4234
query: string,
43-
redis: RedisClientType,
4435
logger: Logger,
4536
): Promise<SearchResult> {
4637
const prefixedLogger = new PrefixedLogger(logger, "scanByCollections");
@@ -58,7 +49,7 @@ export async function scanByCollections(
5849

5950
for (const collectionKey of collectionKeys) {
6051
try {
61-
const content = await storage.getBlob(collectionKey);
52+
const content = await getBlob(collectionKey);
6253
if (!content) {
6354
prefixedLogger.info(
6455
`No content found for collection: ${collectionKey}`,
@@ -69,7 +60,7 @@ export async function scanByCollections(
6960
const keys = JSON.parse(content);
7061
for (const key of keys) {
7162
try {
72-
const blobContent = await storage.getBlob(key);
63+
const blobContent = await getBlob(key);
7364
if (blobContent) {
7465
matchingExamples.push({
7566
key,

typescript/packages/toolshed/lib/behavior/strategies/scanBySchema.ts renamed to typescript/packages/toolshed/routes/ai/spell/behavior/strategies/scanBySchema.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { getAllBlobs } from "@/lib/redis/redis.ts";
2-
import { storage } from "@/storage.ts";
3-
import { checkSchemaMatch } from "../schema-match.ts";
1+
import { checkSchemaMatch } from "@/lib/schema-match.ts";
42
import { SearchResult } from "../search.ts";
5-
import { Logger, PrefixedLogger } from "../../prefixed-logger.ts";
6-
import { generateText } from "../../llm/generateText.ts";
3+
import { Logger, PrefixedLogger } from "@/lib/prefixed-logger.ts";
74
import type { RedisClientType } from "redis";
5+
import { generateText, getBlob, getAllBlobs } from "../effects.ts";
6+
import { Schema } from 'jsonschema'
87

98
export async function generateSchema(
109
query: string,
@@ -16,33 +15,28 @@ export async function generateSchema(
1615
model: "claude-3-5-sonnet",
1716
messages: [
1817
{
19-
role: "system",
20-
content:
21-
"Generate a minimal JSON schema to match data that relates to this search query, aim for the absolute minimal number of fields that cature the essence of the data. (e.g. articles are really just title and url) Return only valid JSON schema.",
22-
},
23-
{
24-
role: "user",
18+
role: "user" as const,
2519
content: query,
2620
},
2721
],
22+
system: "Generate a minimal JSON schema to match data that relates to this search query, aim for the absolute minimal number of fields that cature the essence of the data. (e.g. articles are really just title and url) Return only valid JSON schema.",
2823
stream: false,
2924
};
3025

3126
const schemaText = await generateText(schemaPrompt);
32-
const schema = JSON.parse(schemaText.message.content);
27+
const schema = JSON.parse(schemaText);
3328
prefixedLogger.info(`Generated schema:\n${JSON.stringify(schema, null, 2)}`);
3429
return schema;
3530
}
3631

3732
export async function scanBySchema(
3833
schema: unknown,
39-
redis: RedisClientType,
4034
logger: Logger,
4135
): Promise<SearchResult> {
4236
const prefixedLogger = new PrefixedLogger(logger, "scanBySchema");
4337
prefixedLogger.info("Starting schema scan");
4438
prefixedLogger.info(`Using schema:\n${JSON.stringify(schema, null, 2)}`);
45-
const allBlobs = await getAllBlobs(redis);
39+
const allBlobs = await getAllBlobs();
4640
prefixedLogger.info(`Retrieved ${allBlobs.length} blobs to scan`);
4741

4842
const matchingExamples: Array<{
@@ -52,14 +46,14 @@ export async function scanBySchema(
5246

5347
for (const blobKey of allBlobs) {
5448
try {
55-
const content = await storage.getBlob(blobKey);
49+
const content = await getBlob(blobKey);
5650
if (!content) {
5751
prefixedLogger.info(`No content found for key: ${blobKey}`);
5852
continue;
5953
}
6054

6155
const blobData = JSON.parse(content);
62-
const matches = checkSchemaMatch(blobData, schema);
56+
const matches = checkSchemaMatch(blobData, schema as Schema);
6357

6458
if (matches) {
6559
matchingExamples.push({

0 commit comments

Comments
 (0)