From 80597cd3fdf149cef87db55f03a3cc0bfd723a7a Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Thu, 29 May 2025 11:58:40 -0400 Subject: type error fix --- js/src/app/app.ts | 78 +++++++++++++++++++++++++++++++++++++++++ js/src/app/config.ts | 79 ------------------------------------------ js/src/app/index.ts | 78 ----------------------------------------- js/src/bus/index.ts | 2 +- js/src/config/config.ts | 51 +++++++++++++++++++++++++++ js/src/index.ts | 2 +- js/src/llm/llm.ts | 17 ++++----- js/src/llm/models/anthropic.ts | 0 js/src/llm/models/index.ts | 1 - js/src/llm/models/model.ts | 11 ------ js/src/lsp/client.ts | 3 +- js/src/lsp/index.ts | 3 +- js/src/provider/provider.ts | 32 +++++++++++++++++ js/src/server/server.ts | 6 ++-- js/src/session/session.ts | 2 +- js/src/share/share.ts | 2 +- js/src/storage/storage.ts | 2 +- js/src/tool/edit.ts | 3 -- js/src/tool/glob.ts | 2 +- js/src/tool/grep.ts | 2 +- js/src/tool/ls.ts | 2 +- js/src/tool/lsp-diagnostics.ts | 2 +- js/src/tool/lsp-hover.ts | 2 +- js/src/tool/util/file-times.ts | 2 +- 24 files changed, 187 insertions(+), 197 deletions(-) create mode 100644 js/src/app/app.ts delete mode 100644 js/src/app/config.ts delete mode 100644 js/src/app/index.ts create mode 100644 js/src/config/config.ts delete mode 100644 js/src/llm/models/anthropic.ts delete mode 100644 js/src/llm/models/index.ts delete mode 100644 js/src/llm/models/model.ts create mode 100644 js/src/provider/provider.ts (limited to 'js/src') diff --git a/js/src/app/app.ts b/js/src/app/app.ts new file mode 100644 index 000000000..0c6260bc7 --- /dev/null +++ b/js/src/app/app.ts @@ -0,0 +1,78 @@ +import fs from "fs/promises"; +import { AppPath } from "./path"; +import { Log } from "../util/log"; +import { Context } from "../util/context"; + +export namespace App { + const log = Log.create({ service: "app" }); + + export type Info = Awaited>; + + const ctx = Context.create("app"); + + async function create(input: { directory: string }) { + const dataDir = AppPath.data(input.directory); + await fs.mkdir(dataDir, { recursive: true }); + await Log.file(input.directory); + + log.info("created", { path: dataDir }); + + const services = new Map< + any, + { + state: any; + shutdown?: (input: any) => Promise; + } + >(); + + const result = { + get services() { + return services; + }, + get root() { + return input.directory; + }, + }; + + return result; + } + + export function state( + key: any, + init: (app: Info) => State, + shutdown?: (state: Awaited) => Promise, + ) { + return () => { + const app = ctx.use(); + const services = app.services; + if (!services.has(key)) { + log.info("registering service", { name: key }); + services.set(key, { + state: init(app), + shutdown: shutdown, + }); + } + return services.get(key)?.state as State; + }; + } + + export async function use() { + return ctx.use(); + } + + export async function provide any>( + input: { directory: string }, + cb: T, + ) { + const app = await create(input); + + return ctx.provide(app, async () => { + const result = await cb(app); + for (const [key, entry] of app.services.entries()) { + log.info("shutdown", { name: key }); + await entry.shutdown?.(await entry.state); + } + return result; + }); + } +} diff --git a/js/src/app/config.ts b/js/src/app/config.ts deleted file mode 100644 index e68b24bb9..000000000 --- a/js/src/app/config.ts +++ /dev/null @@ -1,79 +0,0 @@ -import path from "path"; -import { Log } from "../util/log"; -import { z } from "zod"; -import { App } from "."; - -export namespace Config { - const log = Log.create({ service: "config" }); - - export const state = App.state("config", async (app) => { - const result = await load(app.root); - return result; - }); - - export const Model = z - .object({ - name: z.string().optional(), - cost: z.object({ - input: z.number(), - inputCached: z.number(), - output: z.number(), - outputCached: z.number(), - }), - contextWindow: z.number(), - maxTokens: z.number().optional(), - attachment: z.boolean(), - reasoning: z.boolean().optional(), - }) - .openapi({ - ref: "model", - }); - export type Model = z.output; - - export const Provider = z - .object({ - options: z.record(z.string(), z.any()).optional(), - models: z.record(z.string(), Model), - }) - .openapi({ - ref: "provider", - }); - export type Provider = z.output; - - export const Info = z - .object({ - providers: z.record(z.string(), Provider).optional(), - }) - .strict(); - - export type Info = z.output; - - export function get() { - return state(); - } - - async function load(directory: string) { - let result: Info = {}; - for (const file of ["opencode.jsonc", "opencode.json"]) { - const resolved = path.join(directory, file); - log.info("searching", { path: resolved }); - try { - result = await import(path.join(directory, file)).then((mod) => - Info.parse(mod.default), - ); - log.info("found", { path: resolved }); - break; - } catch (e) { - if (e instanceof z.ZodError) { - for (const issue of e.issues) { - log.info(issue.message); - } - throw e; - } - continue; - } - } - log.info("loaded", result); - return result; - } -} diff --git a/js/src/app/index.ts b/js/src/app/index.ts deleted file mode 100644 index 0c6260bc7..000000000 --- a/js/src/app/index.ts +++ /dev/null @@ -1,78 +0,0 @@ -import fs from "fs/promises"; -import { AppPath } from "./path"; -import { Log } from "../util/log"; -import { Context } from "../util/context"; - -export namespace App { - const log = Log.create({ service: "app" }); - - export type Info = Awaited>; - - const ctx = Context.create("app"); - - async function create(input: { directory: string }) { - const dataDir = AppPath.data(input.directory); - await fs.mkdir(dataDir, { recursive: true }); - await Log.file(input.directory); - - log.info("created", { path: dataDir }); - - const services = new Map< - any, - { - state: any; - shutdown?: (input: any) => Promise; - } - >(); - - const result = { - get services() { - return services; - }, - get root() { - return input.directory; - }, - }; - - return result; - } - - export function state( - key: any, - init: (app: Info) => State, - shutdown?: (state: Awaited) => Promise, - ) { - return () => { - const app = ctx.use(); - const services = app.services; - if (!services.has(key)) { - log.info("registering service", { name: key }); - services.set(key, { - state: init(app), - shutdown: shutdown, - }); - } - return services.get(key)?.state as State; - }; - } - - export async function use() { - return ctx.use(); - } - - export async function provide any>( - input: { directory: string }, - cb: T, - ) { - const app = await create(input); - - return ctx.provide(app, async () => { - const result = await cb(app); - for (const [key, entry] of app.services.entries()) { - log.info("shutdown", { name: key }); - await entry.shutdown?.(await entry.state); - } - return result; - }); - } -} diff --git a/js/src/bus/index.ts b/js/src/bus/index.ts index cf5101b67..342d82b6d 100644 --- a/js/src/bus/index.ts +++ b/js/src/bus/index.ts @@ -1,5 +1,5 @@ import { z, type ZodType } from "zod"; -import { App } from "../app"; +import { App } from "../app/app"; import { Log } from "../util/log"; export namespace Bus { diff --git a/js/src/config/config.ts b/js/src/config/config.ts new file mode 100644 index 000000000..76181b792 --- /dev/null +++ b/js/src/config/config.ts @@ -0,0 +1,51 @@ +import path from "path"; +import { Log } from "../util/log"; +import { z } from "zod"; +import { App } from "../app/app"; +import { Provider } from "../provider/provider"; + +export namespace Config { + const log = Log.create({ service: "config" }); + + export const state = App.state("config", async (app) => { + const result = await load(app.root); + return result; + }); + + export const Info = z + .object({ + providers: z.record(z.string(), Provider.Info).optional(), + }) + .strict(); + + export type Info = z.output; + + export function get() { + return state(); + } + + async function load(directory: string) { + let result: Info = {}; + for (const file of ["opencode.jsonc", "opencode.json"]) { + const resolved = path.join(directory, file); + log.info("searching", { path: resolved }); + try { + result = await import(path.join(directory, file)).then((mod) => + Info.parse(mod.default), + ); + log.info("found", { path: resolved }); + break; + } catch (e) { + if (e instanceof z.ZodError) { + for (const issue of e.issues) { + log.info(issue.message); + } + throw e; + } + continue; + } + } + log.info("loaded", result); + return result; + } +} diff --git a/js/src/index.ts b/js/src/index.ts index ddea15e91..1f6c7ae26 100644 --- a/js/src/index.ts +++ b/js/src/index.ts @@ -1,5 +1,5 @@ import "zod-openapi/extend"; -import { App } from "./app"; +import { App } from "./app/app"; import { Server } from "./server/server"; import fs from "fs/promises"; import path from "path"; diff --git a/js/src/llm/llm.ts b/js/src/llm/llm.ts index e6230584a..990c30069 100644 --- a/js/src/llm/llm.ts +++ b/js/src/llm/llm.ts @@ -1,11 +1,12 @@ -import { App } from "../app"; +import { App } from "../app/app"; import { Log } from "../util/log"; import { mergeDeep } from "remeda"; import path from "path"; +import { Provider } from "../provider/provider"; -import type { LanguageModel, Provider } from "ai"; +import type { LanguageModel, Provider as ProviderInstance } from "ai"; import { NoSuchModelError } from "ai"; -import { Config } from "../app/config"; +import { Config } from "../config/config"; import { BunProc } from "../bun"; import { Global } from "../global"; @@ -18,7 +19,7 @@ export namespace LLM { } } - const NATIVE_PROVIDERS: Record = { + const NATIVE_PROVIDERS: Record = { anthropic: { models: { "claude-sonnet-4-20250514": { @@ -76,18 +77,18 @@ export namespace LLM { google: ["GOOGLE_GENERATIVE_AI_API_KEY"], }; - const state = App.state("llm", async (app) => { + const state = App.state("llm", async () => { const config = await Config.get(); const providers: Record< string, { - info: Config.Provider; - instance: Provider; + info: Provider.Info; + instance: ProviderInstance; } > = {}; const models = new Map< string, - { info: Config.Model; instance: LanguageModel } + { info: Provider.Model; instance: LanguageModel } >(); const list = mergeDeep(NATIVE_PROVIDERS, config.providers ?? {}); diff --git a/js/src/llm/models/anthropic.ts b/js/src/llm/models/anthropic.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/js/src/llm/models/index.ts b/js/src/llm/models/index.ts deleted file mode 100644 index f974b4d3e..000000000 --- a/js/src/llm/models/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * as anthropic from "./anthropic"; diff --git a/js/src/llm/models/model.ts b/js/src/llm/models/model.ts deleted file mode 100644 index e78dbb87f..000000000 --- a/js/src/llm/models/model.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface ModelInfo { - cost: { - input: number; - inputCached: number; - output: number; - outputCached: number; - }; - contextWindow: number; - maxTokens: number; - attachment: boolean; -} diff --git a/js/src/lsp/client.ts b/js/src/lsp/client.ts index cb8bdad2d..82caa82a2 100644 --- a/js/src/lsp/client.ts +++ b/js/src/lsp/client.ts @@ -6,7 +6,7 @@ import { StreamMessageWriter, } from "vscode-jsonrpc/node"; import type { Diagnostic as VSCodeDiagnostic } from "vscode-languageserver-types"; -import { App } from "../app"; +import { App } from "../app/app"; import { Log } from "../util/log"; import { LANGUAGE_EXTENSIONS } from "./language"; import { Bus } from "../bus"; @@ -31,7 +31,6 @@ export namespace LSPClient { export async function create(input: { cmd: string[]; serverID: string }) { log.info("starting client", input); - let version = 0; const app = await App.use(); const [command, ...args] = input.cmd; diff --git a/js/src/lsp/index.ts b/js/src/lsp/index.ts index ee5a8b2d7..e3344a934 100644 --- a/js/src/lsp/index.ts +++ b/js/src/lsp/index.ts @@ -1,4 +1,4 @@ -import { App } from "../app"; +import { App } from "../app/app"; import { Log } from "../util/log"; import { LSPClient } from "./client"; import path from "path"; @@ -9,6 +9,7 @@ export namespace LSP { const state = App.state( "lsp", async () => { + log.info("initializing"); const clients = new Map(); return { diff --git a/js/src/provider/provider.ts b/js/src/provider/provider.ts new file mode 100644 index 000000000..44482b6db --- /dev/null +++ b/js/src/provider/provider.ts @@ -0,0 +1,32 @@ +import z from "zod"; + +export namespace Provider { + export const Model = z + .object({ + name: z.string().optional(), + cost: z.object({ + input: z.number(), + inputCached: z.number(), + output: z.number(), + outputCached: z.number(), + }), + contextWindow: z.number(), + maxTokens: z.number().optional(), + attachment: z.boolean(), + reasoning: z.boolean().optional(), + }) + .openapi({ + ref: "Provider.Model", + }); + export type Model = z.output; + + export const Info = z + .object({ + options: z.record(z.string(), z.any()).optional(), + models: z.record(z.string(), Model), + }) + .openapi({ + ref: "Provider.Info", + }); + export type Info = z.output; +} diff --git a/js/src/server/server.ts b/js/src/server/server.ts index ff2d0924b..5bf8d9f54 100644 --- a/js/src/server/server.ts +++ b/js/src/server/server.ts @@ -6,9 +6,9 @@ import { streamSSE } from "hono/streaming"; import { Session } from "../session/session"; import { resolver, validator as zValidator } from "hono-openapi/zod"; import { z } from "zod"; -import { Config } from "../app/config"; import { LLM } from "../llm/llm"; import { Message } from "../session/message"; +import { Provider } from "../provider/provider"; export namespace Server { const log = Log.create({ service: "server" }); @@ -234,7 +234,7 @@ export namespace Server { description: "List of providers", content: { "application/json": { - schema: resolver(z.record(z.string(), Config.Provider)), + schema: resolver(z.record(z.string(), Provider.Info)), }, }, }, @@ -242,7 +242,7 @@ export namespace Server { }), async (c) => { const providers = await LLM.providers(); - const result: Record = {}; + const result: Record = {}; for (const [providerID, provider] of Object.entries(providers)) { result[providerID] = provider.info; } diff --git a/js/src/session/session.ts b/js/src/session/session.ts index 5e07764b8..f6b50a0bf 100644 --- a/js/src/session/session.ts +++ b/js/src/session/session.ts @@ -1,5 +1,5 @@ import path from "path"; -import { App } from "../app/"; +import { App } from "../app/app"; import { Identifier } from "../id/id"; import { LLM } from "../llm/llm"; import { Storage } from "../storage/storage"; diff --git a/js/src/share/share.ts b/js/src/share/share.ts index e77f692f4..62dee63a7 100644 --- a/js/src/share/share.ts +++ b/js/src/share/share.ts @@ -1,4 +1,4 @@ -import { App } from "../app"; +import { App } from "../app/app"; import { Bus } from "../bus"; import { Session } from "../session/session"; import { Storage } from "../storage/storage"; diff --git a/js/src/storage/storage.ts b/js/src/storage/storage.ts index 85fa26be6..983b7e0f9 100644 --- a/js/src/storage/storage.ts +++ b/js/src/storage/storage.ts @@ -2,7 +2,7 @@ import { FileStorage } from "@flystorage/file-storage"; import { LocalStorageAdapter } from "@flystorage/local-fs"; import fs from "fs/promises"; import { Log } from "../util/log"; -import { App } from "../app"; +import { App } from "../app/app"; import { AppPath } from "../app/path"; import { Bus } from "../bus"; import z from "zod"; diff --git a/js/src/tool/edit.ts b/js/src/tool/edit.ts index 3f784d616..41ff60855 100644 --- a/js/src/tool/edit.ts +++ b/js/src/tool/edit.ts @@ -1,12 +1,9 @@ import { z } from "zod"; import * as path from "path"; -import { Log } from "../util/log"; import { Tool } from "./tool"; import { FileTimes } from "./util/file-times"; import { LSP } from "../lsp"; -const log = Log.create({ service: "tool.edit" }); - const DESCRIPTION = `Edits files by replacing text, creating new files, or deleting content. For moving or renaming files, use the Bash tool with the 'mv' command instead. For larger file edits, use the FileWrite tool to overwrite files. Before using this tool: diff --git a/js/src/tool/glob.ts b/js/src/tool/glob.ts index 5f1952b78..f52c3f5d0 100644 --- a/js/src/tool/glob.ts +++ b/js/src/tool/glob.ts @@ -1,6 +1,6 @@ import { z } from "zod"; import { Tool } from "./tool"; -import { App } from "../app"; +import { App } from "../app/app"; const DESCRIPTION = `Fast file pattern matching tool that finds files by name and pattern, returning matching paths sorted by modification time (newest first). diff --git a/js/src/tool/grep.ts b/js/src/tool/grep.ts index d5c2d700c..0c5848074 100644 --- a/js/src/tool/grep.ts +++ b/js/src/tool/grep.ts @@ -1,6 +1,6 @@ import { z } from "zod"; import { Tool } from "./tool"; -import { App } from "../app"; +import { App } from "../app/app"; import { spawn } from "child_process"; import { promises as fs } from "fs"; import path from "path"; diff --git a/js/src/tool/ls.ts b/js/src/tool/ls.ts index 62c3d113b..5954355a3 100644 --- a/js/src/tool/ls.ts +++ b/js/src/tool/ls.ts @@ -1,6 +1,6 @@ import { z } from "zod"; import { Tool } from "./tool"; -import { App } from "../app"; +import { App } from "../app/app"; import * as path from "path"; import * as fs from "fs"; diff --git a/js/src/tool/lsp-diagnostics.ts b/js/src/tool/lsp-diagnostics.ts index c1372b0e9..ecd54c1a7 100644 --- a/js/src/tool/lsp-diagnostics.ts +++ b/js/src/tool/lsp-diagnostics.ts @@ -2,7 +2,7 @@ import { z } from "zod"; import { Tool } from "./tool"; import path from "path"; import { LSP } from "../lsp"; -import { App } from "../app"; +import { App } from "../app/app"; export const LspDiagnosticTool = Tool.define({ name: "diagnostics", diff --git a/js/src/tool/lsp-hover.ts b/js/src/tool/lsp-hover.ts index 9b6290ef5..4ffa90a75 100644 --- a/js/src/tool/lsp-hover.ts +++ b/js/src/tool/lsp-hover.ts @@ -2,7 +2,7 @@ import { z } from "zod"; import { Tool } from "./tool"; import path from "path"; import { LSP } from "../lsp"; -import { App } from "../app"; +import { App } from "../app/app"; export const LspHoverTool = Tool.define({ name: "lsp.hover", diff --git a/js/src/tool/util/file-times.ts b/js/src/tool/util/file-times.ts index aab562dd4..8d36d007d 100644 --- a/js/src/tool/util/file-times.ts +++ b/js/src/tool/util/file-times.ts @@ -1,4 +1,4 @@ -import { App } from "../../app"; +import { App } from "../../app/app"; export namespace FileTimes { export const state = App.state("tool.filetimes", () => ({ -- cgit v1.2.3