{"id":16665199,"url":"https://github.com/TypeAI-dev/typeai","last_synced_at":"2025-10-30T17:31:19.742Z","repository":{"id":185705707,"uuid":"673986287","full_name":"TypeAI-dev/typeai","owner":"TypeAI-dev","description":"✨ TypeAI: An AI Engineering Framework for TypeScript","archived":false,"fork":false,"pushed_at":"2023-08-26T13:16:58.000Z","size":793,"stargazers_count":101,"open_issues_count":4,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-25T17:41:55.078Z","etag":null,"topics":["agents","ai","ai-functions","artificial-intelligence","deepkit","gpt","llm","openai","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@typeai/core","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TypeAI-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-02T22:08:33.000Z","updated_at":"2024-04-21T18:21:39.000Z","dependencies_parsed_at":"2024-10-12T11:04:09.059Z","dependency_job_id":"9592fde5-46e9-47f7-980b-b3d05415d359","html_url":"https://github.com/TypeAI-dev/typeai","commit_stats":null,"previous_names":["typeai-dev/typeai-core","typeai-dev/typeai"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TypeAI-dev%2Ftypeai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TypeAI-dev%2Ftypeai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TypeAI-dev%2Ftypeai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TypeAI-dev%2Ftypeai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TypeAI-dev","download_url":"https://codeload.github.com/TypeAI-dev/typeai/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239011367,"owners_count":19567650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","ai","ai-functions","artificial-intelligence","deepkit","gpt","llm","openai","typescript"],"created_at":"2024-10-12T11:01:52.118Z","updated_at":"2025-10-30T17:31:14.312Z","avatar_url":"https://github.com/TypeAI-dev.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# TypeAI: An AI Engineering Framework for TypeScript\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"GitHub top language\" src=\"https://img.shields.io/github/languages/top/TypeAI-dev/typeai\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@typeai/core\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/@typeai/core\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/TypeAI-dev/typeai/actions/workflows/ci.yml\"\u003e\n    \u003cimg src=\"https://github.com/TypeAI-dev/typeai/actions/workflows/ci.yml/badge.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/TypeAI-dev/typeai/blob/main/LICENSE.txt\"\u003e\n\t\u003cimg alt=\"GitHub\" src=\"https://img.shields.io/github/license/TypeAI-dev/typeai\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n![TypeAI Example](docs/image/example-aiModel.png)\n\nTypeAI is a toolkit for building AI-enabled apps using TypeScript that makes things look so simple it seems like magic. More importantly, it makes building with LLMs \"feel\" like ordinary code with low impedance mismatch.\n\nAn example:\n\n```typescript\nimport { toAIFunction } from '@typeai/core'\n\n/** @description Given `text`, returns a number between 1 (positive) and -1 (negative) indicating its sentiment score. */\nfunction sentimentSpec(text: string): number | void {}\nconst sentiment = toAIFunction(sentimentSpec)\n\nconst score = await sentiment('That was surprisingly easy!')\n```\n\nJust specify your types and function signatures as you naturally would, and TypeAI will generate the appropriate implementation respecting your type declarations. No loading separate schema files, no prompt engineering, and no manually writing JSON Schema representations of your functions.\n\n### Contents\n\n1. [Installation](#installation)\n2. [Usage](#usage)\n   - **Using TypeAI to generate functionality**\n     - AI Models\n     - AI Functions\n     - AI Classifiers\n   - **Using TypeAI to expose functionality to an LLM**\n     - AI \"Tool Functions\"\n3. [Gotchas](#gotchas)\n4. [How does it work?](#how)\n5. [Future Direction \u0026 TODOs](#future)\n6. [Acknowledgements](#acknowledgements)\n7. [License](#license)\n\n### Support\n\nFollow me on Twitter: ![Twitter Follow](https://img.shields.io/twitter/follow/jefflaporte)\n\n## \u003ca name=\"installation\"\u003e\u003c/a\u003eInstallation\n\n[DeepKit](\u003c[url](https://github.com/deepkit/deepkit-framework)\u003e) is required in order to provide runtime type information on your functions and types.\n\n```sh\nnpm install @typeai/core @deepkit/core\n```\n\n\u003e NOTE: For now, automatic extraction of JSDoc @description tags requires these\n\u003e forked npm package builds @deepkit/type and @deepkit/type-compiler\n\n```sh\nnpm install @deepkit/type@npm:@jefflaporte/deepkit-type@1.0.1-alpha.97-jl\nnpm install --save-dev @deepkit/type-compiler@npm:@jefflaporte/deepkit-type-compiler@1.0.1-alpha.97-jl\n# Bash\n./node_modules/.bin/deepkit-type-install\n# PowerShell\npwsh ./node_modules/.bin/deepkit-type-install.ps1\n```\n\n_tsconfig.json_\n\n```js\n// tsconfig.json\n{\n  \"compilerOptions\": {\n    // ...\n\n    // Note: DeepKit says that experimentalDecorators is not necessary when using @deepkit/type,\n    // but I have found that deepkit's typeOf() does not always work with TypeScript \u003e 4.9\n    // without experimentalDecorators set.\n    \"experimentalDecorators\": true\n  },\n  \"reflection\": true\n}\n```\n\nNOTE: Some runtimes, such as `tsx`, won't work with Deepkit. See [Gotchas](#gotchas) for more info.\n\n_At execution time_\n\n```sh\nexport OPENAI_API_KEY='...'    # currently required for core functionality\nexport BING_API_KEY='...'      # if using predefined SearchWeb Tool function\n```\n\nTypeAI makes connecting your functions and types to AI APIs like OpenAI's chat completion endpoints lightweight by using runtime type reflection on TypeScript code to generate the JSON schema required by OpenAI's function calling feature, and by handling function dispatch and result delivery to the LLM.\n\n## \u003ca name=\"usage\"\u003e\u003c/a\u003eUsage\n\nTypeAI currently provides two main areas of functionality:\n\n- Generation of \"magic\" AI-backed functions\n  - AI Models\n  - AI Functions\n  - AI Classifiers\n- Generation and handing of LLM tool function glue\n  - AI \"Tool Functions\"\n\n### AI Functions\n\nTo create an AI-backed function, write a stub function and pass it to `toAIFunction()`, which will generate an AI-backed function with the desired behaviour.\n\n```typescript\n/** @description Given `text`, returns a number between 1 (positive) and -1 (negative) indicating its sentiment score. */\nfunction sentimentSpec(text: string): number | void {}\nconst sentiment = toAIFunction(sentimentSpec)\n\nconst score = await sentiment('That was surprisingly easy!')\n```\n\nFunctions with complex input and output TypeScript types work too. Here's a more interesting example:\n\n```typescript\ntype Patient = {\n  name: string\n  age: number\n  isSmoker: boolean\n}\ntype Diagnosis = {\n  condition: string\n  diagnosisDate: Date\n  stage?: string\n  type?: string\n  histology?: string\n  complications?: string\n}\ntype Treatment = {\n  name: string\n  startDate: Date\n  endDate?: Date\n}\ntype Medication = Treatment \u0026 {\n  dose?: string\n}\ntype BloodTest = {\n  name: string\n  result: string\n  testDate: Date\n}\ntype PatientData = {\n  patient: Patient\n  diagnoses: Diagnosis[]\n  treatments: Treatment | Medication[]\n  bloodTests: BloodTest[]\n}\n\n/** @description Returns a PatientData record generate from the content of doctorsNotes notes. */\nfunction generateElectronicHealthRecordSpec(input: string): PatientData | void {}\nconst generateElectronicHealthRecord = toAIFunction(generateElectronicHealthRecordSpec, {\n  model: 'gpt-4',\n})\n```\n\n#### TypeScript enums to AI-backed Classifiers\n\n```typescript\nenum AppRouteEnum {\n  USER_PROFILE = '/user-profile',\n  SEARCH = '/search',\n  NOTIFICATIONS = '/notifications',\n  SETTINGS = '/settings',\n  HELP = '/help',\n  SUPPORT_CHAT = '/support-chat',\n  DOCS = '/docs',\n  PROJECTS = '/projects',\n  WORKSPACES = '/workspaces',\n}\nconst AppRoute = toAIClassifier(AppRouteEnum)\n\nconst appRouteRes = await AppRoute('I need to talk to somebody about billing')\n```\n\n### AI \"Tool Function\" Helpers\n\nAn AI tool function is a function provided to an LLM for it's own use in generating answers.\n\nSay you have a function and want to provide it's functionality to OpenAI's LLM for use with their **_Function Calling_** feature.\n\n_See:_\n\n- [OpenAI Blog: Function calling and other API updates](https://openai.com/blog/function-calling-and-other-api-updates)\n- [OpenAI API: Create Chat Completion](https://platform.openai.com/docs/api-reference/chat/create)\n\nTypeAI provides three functions that make exposing your functions and models to GPT-3.5/4, and handling the resulting function call requests from GPT-3/4, transparent:\n\n```typescript\nstatic ToolFunction.from\u003cR\u003e(\n  fn: (...args: any[]) =\u003e R,\n  options?: ToolFunctionFromOptions\n): ToolFunction\n\nstatic ToolFunction.modelSubmissionToolFor\u003cT\u003e(\n  cb: (arg: T) =\u003e Promise\u003cvoid\u003e\n): ToolFunction\n\nfunction handleToolUse(\n  openAIClient: OpenAIApi,\n  originalRequest: CreateChatCompletionRequest,\n  responseData: CreateChatCompletionResponse,\n  options?: {\n    model?: string,\n    registry?: SchemaRegistry,\n    handle?: 'single' | 'multiple'\n  },\n): Promise\u003cCreateChatCompletionResponse | undefined\u003e\n```\n\nThey can be used like this:\n\n```typescript\nimport {\n  OpenAIApi,\n  Configuration,\n  CreateChatCompletionRequest,\n  ChatCompletionRequestMessage,\n  ChatCompletionRequestMessageRoleEnum,\n} from 'openai'\nimport { ToolFunction, handleToolUse } from '@typeai/core'\nimport { getCurrentWeather } from 'yourModule'\n\n// Init OpenAI client\nconst configuration = new Configuration({ apiKey: process.env.OPENAI_API_KEY })\nconst openai = new OpenAIApi(configuration)\n\n// Generate JSON Schema for function and dependent types\nconst getCurrentWeatherTool = ToolFunction.from(getCurrentWeather)\n\n// Run a chat completion sequence\nconst messages: ChatCompletionRequestMessage[] = [\n  {\n    role: ChatCompletionRequestMessageRoleEnum.User,\n    content: \"What's the weather like in Boston? Say it like a weather reporter.\",\n  },\n]\nconst request: CreateChatCompletionRequest = {\n  model: 'gpt-3.5-turbo',\n  messages,\n  functions: [getCurrentWeatherTool.schema],\n  stream: false,\n  max_tokens: 1000,\n}\nconst { data: response } = await openai.createChatCompletion(request)\n\n// Transparently handle any LLM calls to your function.\n// handleToolUse() returns OpenAI's final response after\n// any/all function calls have been completed\nconst responseData = await handleToolUse(openai, request, response)\nconst result = responseData?.choices[0].message\n\n/*\nGood afternoon, Boston! This is your weather reporter bringing you the latest\nupdates. Currently, we're experiencing a pleasant temperature of 82 degrees Celsius. The sky is a mix of sunshine and clouds, making for a beautiful day. However, there is a 25% chance of precipitation, so you might want to keep an umbrella handy. Additionally, the atmospheric pressure is at 25 mmHg. Overall, it's a great day to get outside and enjoy the city. Stay safe and have a wonderful time!\n*/\n```\n\n## \u003ca name=\"gotchas\"\u003e\u003c/a\u003eGotchas\n\nDue to the way Deepkit injects it's type-compiler transform, by patching tsc, some runtimes may not work. These are know NOT to work:\n\n- `tsx`\n\n## \u003ca name=\"how\"\u003e\u003c/a\u003eHow does it work?\n\nTypeAI uses TypeScript runtime type info provided by `@deepkit/type` to:\n\n- generate replacement functions with the same signature as your function stubs\n- generate JSON Schema descriptions of your function and dependent types which are provided to the OpenAI API so that it can repect your desired type structure\n\nThis results in a coding experience that feels \"native\".\n\n_Example_\n\n```typescript\nimport { ToolFunction, handleToolUse } from '@typeai/core'\n\n// Your type definitions\n// ...\n// Your function definitions dependent on your types\n// ...\n// eg:\nconst getCurrentWeather = function getCurrentWeather(\n  location: string,\n  unit: TemperatureUnit = 'fahrenheit',\n  options?: WeatherOptions,\n): WeatherInfo {\n  const weatherInfo: WeatherInfo = {\n    location: location,\n    temperature: 82,\n    unit: unit,\n    precipitationPct: options?.flags?.includePrecipitation ? 25 : undefined,\n    pressureMmHg: options?.flags?.includePressure ? 25 : undefined,\n    forecast: ['sunny', 'cloudy'],\n  }\n  return weatherInfo\n}\n\n// Register your function and type info\nconst getCurrentWeatherTool = ToolFunction.from(getCurrentWeather)\n\n// Run a completion series\nconst messages: ChatCompletionRequestMessage[] = [\n  {\n    role: ChatCompletionRequestMessageRoleEnum.User,\n    content: \"What's the weather like in Boston? Say it like a weather reporter.\",\n  },\n]\nconst request: CreateChatCompletionRequest = {\n  model: 'gpt-3.5-turbo-0613',\n  messages,\n  functions: [getCurrentWeatherTool.schema],\n  stream: false,\n  max_tokens: 1000,\n}\nconst { data: response } = await openai.createChatCompletion(request)\nconst responseData = await handleToolUse(openai, request, response)\nconst result = responseData?.choices[0].message\nconsole.log(`LLM final result: ${JSON.stringify(result, null, 2)}`)\n```\n\nNote: The OpenAI completion API does not like void function responses.\n\n## \u003ca name=\"future\"\u003e\u003c/a\u003eFuture Direction \u0026 TODOs\n\n- TODO\n\n## \u003ca name=\"acknowledgements\"\u003e\u003c/a\u003eAcknowledgements\n\n- the Prefect / Marvin Team\n  - The concept of source-code-less AI Functions, Models, and that use function specification and description info to auto-generate their behavior is originally due to the amazing team at [PrefectHQ](https://www.prefect.io/opensource/) that created [prefecthq/marvin](https://github.com/prefecthq/marvin) for use in Python.\n- Wang Chenyu\n  - TypeAI's JSON Schema generation is currently a hacked up version of code plucked from Chenyu's [hanayashiki/deepkit-openapi](https://github.com/hanayashiki/deepkit-openapi)\n\n## \u003ca name=\"license\"\u003e\u003c/a\u003eLicense\n\n[See LICENSE.txt](LICENSE.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTypeAI-dev%2Ftypeai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTypeAI-dev%2Ftypeai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTypeAI-dev%2Ftypeai/lists"}