├── data └── .gitkeep ├── hatchify ├── __init__.py ├── common │ ├── __init__.py │ ├── constants │ │ └── __init__.py │ ├── domain │ │ ├── __init__.py │ │ ├── entity │ │ │ ├── __init__.py │ │ │ ├── function_node_spec.py │ │ │ ├── graph_execute_data.py │ │ │ └── init_context.py │ │ ├── enums │ │ │ ├── __init__.py │ │ │ ├── db_type.py │ │ │ ├── storage_type.py │ │ │ ├── session_manager_type.py │ │ │ ├── conversation_mode.py │ │ │ ├── graph_version_type.py │ │ │ ├── session_scene.py │ │ │ ├── message_role.py │ │ │ ├── agent_category.py │ │ │ ├── execution_type.py │ │ │ └── execution_status.py │ │ ├── event │ │ │ ├── __init__.py │ │ │ ├── wrapper_event.py │ │ │ └── deploy_event.py │ │ ├── requests │ │ │ ├── __init__.py │ │ │ ├── graph_version.py │ │ │ ├── web_builder.py │ │ │ ├── base.py │ │ │ ├── execution.py │ │ │ ├── message.py │ │ │ ├── session.py │ │ │ └── graph_patch.py │ │ ├── responses │ │ │ ├── __init__.py │ │ │ ├── model_response.py │ │ │ ├── graph_spec_response.py │ │ │ ├── tool_response.py │ │ │ ├── session_response.py │ │ │ ├── graph_response.py │ │ │ ├── graph_version_response.py │ │ │ ├── web_hook.py │ │ │ └── message_response.py │ │ ├── structured_output │ │ │ └── __init__.py │ │ └── result │ │ │ ├── __init__.py │ │ │ └── result.py │ ├── extensions │ │ ├── __init__.py │ │ └── storage │ │ │ └── __init__.py │ └── settings │ │ └── __init__.py ├── core │ ├── __init__.py │ ├── factory │ │ ├── __init__.py │ │ └── sql_engine_factory.py │ ├── graph │ │ ├── __init__.py │ │ ├── hooks │ │ │ ├── __init__.py │ │ │ └── graph_state_hook.py │ │ ├── nodes │ │ │ └── __init__.py │ │ ├── tools │ │ │ ├── __init__.py │ │ │ └── math_tool.py │ │ └── functions │ │ │ ├── __init__.py │ │ │ └── echo_function.py │ ├── manager │ │ ├── __init__.py │ │ └── function_manager.py │ ├── mcp │ │ └── __init__.py │ ├── prompts │ │ └── __init__.py │ ├── utils │ │ └── __init__.py │ └── stream_handler │ │ ├── __init__.py │ │ └── event_listener │ │ ├── __init__.py │ │ └── event_listener.py ├── launch │ └── __init__.py ├── utils │ └── __init__.py └── business │ ├── __init__.py │ ├── api │ ├── __init__.py │ └── v1 │ │ ├── __init__.py │ │ └── models_router.py │ ├── db │ ├── __init__.py │ └── base.py │ ├── manager │ ├── __init__.py │ ├── repository_manager.py │ └── service_manager.py │ ├── models │ └── __init__.py │ ├── services │ ├── __init__.py │ ├── base │ │ └── __init__.py │ └── message_service.py │ ├── utils │ └── __init__.py │ ├── middleware │ └── __init__.py │ └── repositories │ ├── __init__.py │ ├── base │ └── __init__.py │ ├── message_repository.py │ ├── session_repository.py │ └── execution_repository.py ├── web ├── pnpm-workspace.yaml ├── src │ ├── types │ │ ├── vite-env.d.ts │ │ ├── i18next.d.ts │ │ ├── api.ts │ │ ├── resources.ts │ │ ├── agent.ts │ │ └── workflow.ts │ ├── app │ │ ├── studio │ │ │ └── components │ │ │ │ ├── WebsitePanel │ │ │ │ ├── index.tsx │ │ │ │ └── WebCreator │ │ │ │ │ └── types.ts │ │ │ │ └── ChatPanel │ │ │ │ ├── chatinput.module.scss │ │ │ │ ├── index.tsx │ │ │ │ └── ChatMessageArea │ │ │ │ ├── ChatLoadingItem.tsx │ │ │ │ ├── AssistantMessage │ │ │ │ ├── Progress.tsx │ │ │ │ └── index.module.scss │ │ │ │ └── UserMessge.tsx │ │ └── home │ │ │ └── components │ │ │ ├── ToolsLIst.tsx │ │ │ └── Header.tsx │ ├── styles │ │ └── index.css │ ├── assets │ │ └── fonts │ │ │ └── DmSans │ │ │ ├── rP2Hp2ywxg089UriCZOIHQ.woff2 │ │ │ └── rP2Hp2ywxg089UriCZ2IHSeH.woff2 │ ├── utils │ │ ├── getPreviewUrl.ts │ │ ├── index.ts │ │ ├── toError.ts │ │ ├── cn.tsx │ │ └── WaitLock.ts │ ├── api │ │ ├── index.ts │ │ ├── tools.ts │ │ ├── execution.ts │ │ └── model.ts │ ├── main.tsx │ ├── hooks │ │ ├── useBodyClassOnOpen.ts │ │ ├── useTheme.ts │ │ ├── useStudioParams.ts │ │ └── useLanguage.ts │ ├── components │ │ └── common │ │ │ ├── Markdown │ │ │ └── AnswerMakdown.scss │ │ │ ├── UserProfileHead.tsx │ │ │ ├── BrandButton │ │ │ └── brand-button.module.scss │ │ │ └── ModelSelecter.tsx │ ├── router.ts │ ├── stores │ │ └── workflow │ │ │ └── index.tsx │ └── i18n.ts ├── packages │ └── icons │ │ ├── .gitignore │ │ ├── src │ │ ├── index.ts │ │ └── type.ts │ │ ├── preview │ │ └── main.tsx │ │ ├── icons │ │ ├── success-dot.svg │ │ ├── video-pause-filled.svg │ │ ├── ai-logos-novita.svg │ │ ├── minus-circle-filled-M.svg │ │ ├── reduce.svg │ │ ├── minus-circle-filled-S.svg │ │ ├── minus-outline.svg │ │ ├── dividing-line.svg │ │ ├── minus-circle-filled-L.svg │ │ ├── line-divider-v.svg │ │ ├── credit-basic-filled.svg │ │ ├── expand-sm.svg │ │ ├── ai-logos-anthropic.svg │ │ ├── social-media-logos-mono-x.svg │ │ ├── social-media-logos-official-x.svg │ │ ├── title-txt-words.svg │ │ ├── ai-logos-microsoft.svg │ │ ├── position-left.svg │ │ ├── clock-loader-25.svg │ │ ├── slash-line.svg │ │ ├── down-md.svg │ │ ├── line-divider-tilt.svg │ │ ├── check-md.svg │ │ ├── position-right.svg │ │ ├── text.svg │ │ ├── window-size-change.svg │ │ ├── add-cross.svg │ │ ├── minus-circle-outline-M.svg │ │ ├── add-outline-s.svg │ │ ├── arrow-down.svg │ │ ├── arrow-right.svg │ │ ├── minus-circle-outline-S.svg │ │ ├── arrow-outline-s-b.svg │ │ ├── arrow-outline-s-r.svg │ │ ├── arrow-outline-s-t.svg │ │ ├── arrow-top.svg │ │ ├── back-arrow-left.svg │ │ ├── star-default.svg │ │ ├── arrow-outline-s-l.svg │ │ ├── check-mark.svg │ │ ├── right-outline-l.svg │ │ ├── right-outline-m.svg │ │ ├── add-outline-m.svg │ │ ├── arrow-outline-l-b.svg │ │ ├── arrow-outline-l-l.svg │ │ ├── arrow-outline-l-r.svg │ │ ├── arrow-outline-l-t.svg │ │ ├── arrow-outline-m-b.svg │ │ ├── arrow-outline-m-l.svg │ │ ├── arrow-outline-m-r.svg │ │ ├── arrow-outline-m-t.svg │ │ ├── right-outline-s.svg │ │ ├── back-arrow-line.svg │ │ ├── clock-loader-125.svg │ │ ├── arrow-handle-down.svg │ │ ├── arrow-line-b.svg │ │ ├── model-grok.svg │ │ ├── arrow-handle-right.svg │ │ ├── arrow-line-t.svg │ │ ├── arrow-handle-left.svg │ │ ├── arrow-line-tl.svg │ │ ├── arrow-line-bl.svg │ │ ├── credit-card.svg │ │ ├── arrow-line-l.svg │ │ ├── more-h.svg │ │ ├── more-v.svg │ │ ├── arrow-handle-down-right.svg │ │ ├── arrow-handle-top.svg │ │ ├── clock-loader-75.svg │ │ ├── minus-circle-filled.svg │ │ ├── start-recording.svg │ │ ├── arrow-handle-down-left.svg │ │ ├── minus-circle-outline-L.svg │ │ ├── add-outline-l.svg │ │ ├── arrow-filled-b.svg │ │ ├── arrow-filled-l.svg │ │ ├── arrow-filled-r.svg │ │ ├── arrow-filled-t.svg │ │ ├── arrow-line-br.svg │ │ ├── points-more-ellipsis.svg │ │ ├── arrow-handle-top-left.svg │ │ ├── arrow-handle-top-right.svg │ │ ├── arrow-line-r.svg │ │ ├── minus-circle-dark.svg │ │ ├── minus-circle-light.svg │ │ ├── model-api.svg │ │ ├── arrow-line-tr.svg │ │ ├── clock-loader-875.svg │ │ ├── arrow-turn-left.svg │ │ ├── close-outline-s.svg │ │ ├── enter-arrow-back-left.svg │ │ ├── job-done.svg │ │ ├── model-claude.svg │ │ ├── italic-tilt.svg │ │ ├── flag.svg │ │ ├── map-navigation.svg │ │ ├── search.svg │ │ ├── flag-target.svg │ │ ├── circle-clock-loader-125.svg │ │ ├── drawer-control-b.svg │ │ ├── drawer-control-t.svg │ │ ├── exclamation-mark-outline.svg │ │ ├── exclamation-mark.svg │ │ ├── wrong-cancel-close.svg │ │ ├── credit-elite-filled.svg │ │ ├── line-chart-2.svg │ │ ├── arrow-turn-right.svg │ │ ├── arrow-turn-back-right.svg │ │ ├── filter.svg │ │ ├── arrow-redo-right.svg │ │ ├── remind-circle-filled.svg │ │ ├── underline-straight.svg │ │ ├── arrow-return-left.svg │ │ ├── text-italic.svg │ │ ├── job-check.svg │ │ ├── hamburger-menu-m.svg │ │ ├── stop-rectangle.svg │ │ ├── exclamation-mark-circle-filled-error.svg │ │ ├── exclamation-mark-circle-filled-warning.svg │ │ ├── linkedIn.svg │ │ ├── remove-background-outline.svg │ │ ├── check-green-circle.svg │ │ ├── add-circle-filled.svg │ │ ├── clock-loader-375.svg │ │ ├── close-outline-m.svg │ │ ├── demo.svg │ │ ├── linkedin-rectangle.svg │ │ ├── minus-circle-outline.svg │ │ ├── right-circle-filled-success.svg │ │ ├── bold.svg │ │ ├── close-outline-l.svg │ │ ├── crop-focus.svg │ │ ├── image-model-flux-11-pro.svg │ │ ├── redo.svg │ │ ├── arrow-line-down.svg │ │ ├── image-model-flux-11-pro-ultra.svg │ │ ├── microsoft.svg │ │ ├── undo.svg │ │ ├── arrow-line-right.svg │ │ ├── edit-1.svg │ │ ├── text-bold.svg │ │ ├── write-pen.svg │ │ ├── arrow-line-top.svg │ │ ├── hamburger-menu-s.svg │ │ ├── layer-filled.svg │ │ ├── pill.svg │ │ ├── arrow-line-left.svg │ │ ├── circle-clock-loader-50.svg │ │ ├── contrast.svg │ │ ├── line-arrow-right.svg │ │ ├── twitter.svg │ │ ├── four-squares-filled.svg │ │ ├── cutting.svg │ │ ├── history.svg │ │ ├── line-chart-3.svg │ │ ├── right-circle-filled.svg │ │ ├── stroke-partial.svg │ │ ├── bar-chart-down.svg │ │ ├── bar-chart-up.svg │ │ ├── chart-pie.svg │ │ ├── social-media-logos-mono-youtube.svg │ │ ├── format-underlined.svg │ │ ├── ai-logos-groq.svg │ │ ├── circle-clock-loader-25.svg │ │ ├── read-aloud.svg │ │ ├── reduce-disable-circle.svg │ │ ├── circle-clock-loader-375.svg │ │ ├── line-arrow-up.svg │ │ ├── position-top-t.svg │ │ ├── screen-swith-full.svg │ │ ├── drawer-control-l.svg │ │ ├── drawer-control-r.svg │ │ ├── line-arrow-down.svg │ │ ├── line-arrow-left.svg │ │ ├── position-top-b.svg │ │ ├── screen-swith-collapse.svg │ │ ├── trends.svg │ │ ├── zoom-out.svg │ │ ├── avatar-filled.svg │ │ ├── right-muti.svg │ │ ├── clock-loader-50.svg │ │ ├── currency-yuan.svg │ │ ├── sort-normal.svg │ │ ├── trending-down.svg │ │ ├── arrow-double-outline-l-l.svg │ │ ├── line-chart-4.svg │ │ ├── trending-up.svg │ │ ├── arrow-double-outline-l-r.svg │ │ ├── arrow-double-outline-m-b.svg │ │ └── arrow-double-outline-s-b.svg │ │ ├── index.html │ │ ├── vite.config.ts │ │ ├── svgr.config.mjs │ │ └── tsconfig.json ├── .env.example ├── public │ └── default-cover.png ├── tsconfig.json ├── index.html ├── .gitignore ├── .dockerignore ├── tsconfig.node.json ├── vite.config.ts └── tsconfig.app.json ├── resources └── .env.example ├── main.py ├── Dockerfile └── pyproject.toml /data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/launch/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/api/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/db/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/factory/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/graph/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/manager/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/mcp/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/prompts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/api/v1/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/manager/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/services/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/constants/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/domain/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/extensions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/settings/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/graph/hooks/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/graph/nodes/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/graph/tools/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/middleware/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/repositories/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/services/base/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/domain/entity/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/domain/event/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/domain/requests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/graph/functions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/stream_handler/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/business/repositories/base/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/domain/responses/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/extensions/storage/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/common/domain/structured_output/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hatchify/core/stream_handler/event_listener/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" 3 | -------------------------------------------------------------------------------- /web/src/types/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /resources/.env.example: -------------------------------------------------------------------------------- 1 | ENVIRONMENT=development 2 | BYPASS_TOOL_CONSENT=true -------------------------------------------------------------------------------- /web/packages/icons/.gitignore: -------------------------------------------------------------------------------- 1 | # icons 2 | src/icons 3 | 4 | /node_modules 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /web/.env.example: -------------------------------------------------------------------------------- 1 | # Backend API URL for development proxy 2 | VITE_API_TARGET=http://localhost:8000 3 | -------------------------------------------------------------------------------- /web/public/default-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sider-ai/hatchify/HEAD/web/public/default-cover.png -------------------------------------------------------------------------------- /web/packages/icons/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './icons'; 2 | export * as icons from './icons'; 3 | export * from './type'; 4 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/db_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class DatabasePlatform(str, Enum): 5 | SQLITE = "sqlite" 6 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/storage_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class StorageType(str, Enum): 5 | LOCAL = "opendal" 6 | -------------------------------------------------------------------------------- /web/src/app/studio/components/WebsitePanel/index.tsx: -------------------------------------------------------------------------------- 1 | export default function WebsitePanel() { 2 | return
WebsitePanel
; 3 | } 4 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/session_manager_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class SessionManagerType(str, Enum): 5 | LOCAL = "file" 6 | -------------------------------------------------------------------------------- /web/src/styles/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | @import "../assets/fonts/DmSans/DmSans.css"; 3 | @import "./base.css"; 4 | @import "./theme.css"; 5 | -------------------------------------------------------------------------------- /web/src/app/home/components/ToolsLIst.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function ToolsLIst() { 4 | return
ToolsLIst
; 5 | } 6 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/conversation_mode.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class ConversationMode(str, Enum): 5 | CHAT = "chat" 6 | EDIT = "edit" 7 | -------------------------------------------------------------------------------- /web/src/assets/fonts/DmSans/rP2Hp2ywxg089UriCZOIHQ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sider-ai/hatchify/HEAD/web/src/assets/fonts/DmSans/rP2Hp2ywxg089UriCZOIHQ.woff2 -------------------------------------------------------------------------------- /web/src/utils/getPreviewUrl.ts: -------------------------------------------------------------------------------- 1 | export const getPreviewUrl = (workflowId: string) => { 2 | return `${import.meta.env.VITE_API_TARGET}/preview/${workflowId}`; 3 | }; 4 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /web/src/assets/fonts/DmSans/rP2Hp2ywxg089UriCZ2IHSeH.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sider-ai/hatchify/HEAD/web/src/assets/fonts/DmSans/rP2Hp2ywxg089UriCZ2IHSeH.woff2 -------------------------------------------------------------------------------- /web/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./cn"; 2 | export * from "./getPreviewUrl"; 3 | export * from "./toError"; 4 | export * from "./WaitLock"; 5 | export * from "./zip"; 6 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/graph_version_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class GraphVersionType(str, Enum): 5 | SNAPSHOT = "snapshot" 6 | DRAFT = "draft" 7 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/session_scene.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class SessionScene(str, Enum): 5 | GRAPH_EDIT = "graph_edit" 6 | SITE_GEN = "site_gen" 7 | -------------------------------------------------------------------------------- /web/src/types/i18next.d.ts: -------------------------------------------------------------------------------- 1 | import type { Resources } from "./resources"; 2 | 3 | declare module "i18next" { 4 | interface CustomTypeOptions { 5 | resources: Resources; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /hatchify/common/domain/responses/model_response.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class ModelResponse(BaseModel): 5 | id: str 6 | name: str 7 | description: str 8 | -------------------------------------------------------------------------------- /web/packages/icons/preview/main.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client'; 2 | import App from './index'; 3 | 4 | ReactDOM.createRoot(document.getElementById('root')!).render(); 5 | -------------------------------------------------------------------------------- /web/src/utils/toError.ts: -------------------------------------------------------------------------------- 1 | export function toError(error: unknown): Error { 2 | if (error instanceof Error) return error; 3 | return new Error(typeof error === "string" ? error : JSON.stringify(error)); 4 | } 5 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/message_role.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class MessageRole(str, Enum): 5 | USER = "user" 6 | ASSISTANT = "assistant" 7 | # SYSTEM = "system" 8 | # TOOL = "tool" 9 | -------------------------------------------------------------------------------- /hatchify/common/domain/result/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Time : 2025/7/1 4 | # @Author : .*? 5 | # @Email : amashiro2233@gmail.com 6 | # @File : __init__.py 7 | # @Software: PyCharm 8 | -------------------------------------------------------------------------------- /web/packages/icons/icons/success-dot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/src/api/index.ts: -------------------------------------------------------------------------------- 1 | export * as ExecutionApi from "./execution"; 2 | export * as ModelApi from "./model"; 3 | export * as ToolsApi from "./tools"; 4 | export * as WebCreatorApi from "./webcreator"; 5 | export * as WorkflowApi from "./workflow"; 6 | -------------------------------------------------------------------------------- /web/src/utils/cn.tsx: -------------------------------------------------------------------------------- 1 | import clsx, { type ClassValue } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | /** 5 | * enhancer tw class 6 | */ 7 | /*#__NO_SIDE_EFFECTS__*/ 8 | export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs)); 9 | -------------------------------------------------------------------------------- /web/src/app/studio/components/WebsitePanel/WebCreator/types.ts: -------------------------------------------------------------------------------- 1 | export const WebCreatorTab = { 2 | // Code: "code", 3 | Preview: "preview", 4 | Phone: "phone", 5 | } as const; 6 | 7 | export type WebCreatorTab = (typeof WebCreatorTab)[keyof typeof WebCreatorTab]; 8 | -------------------------------------------------------------------------------- /hatchify/common/domain/responses/graph_spec_response.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict 2 | 3 | from pydantic import BaseModel, Field 4 | 5 | 6 | class GraphSpecResponse(BaseModel): 7 | graph_id: str = Field(..., description="Graph ID") 8 | spec: Dict[str, Any] = Field(..., description="当前 GraphSpec") 9 | -------------------------------------------------------------------------------- /web/packages/icons/icons/video-pause-filled.svg: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /web/packages/icons/src/type.ts: -------------------------------------------------------------------------------- 1 | import { RefAttributes, SVGProps } from 'react'; 2 | 3 | export type SVGAttributes = Partial>; 4 | type ElementAttributes = RefAttributes & SVGAttributes; 5 | 6 | export interface IconProps extends ElementAttributes { 7 | size?: string | number; 8 | } 9 | -------------------------------------------------------------------------------- /web/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "@/styles/index.css"; 4 | import "@/i18n.ts"; 5 | import App from "@/App.tsx"; 6 | 7 | createRoot(document.getElementById("root")!).render( 8 | 9 | 10 | , 11 | ); 12 | -------------------------------------------------------------------------------- /hatchify/business/db/base.py: -------------------------------------------------------------------------------- 1 | from typing import Protocol, Any, runtime_checkable, TypeVar 2 | 3 | from sqlalchemy.orm import DeclarativeBase 4 | 5 | 6 | @runtime_checkable 7 | class HasId(Protocol): 8 | id: Any 9 | 10 | 11 | class Base(DeclarativeBase): 12 | pass 13 | 14 | 15 | T = TypeVar('T', bound=HasId) 16 | -------------------------------------------------------------------------------- /hatchify/common/domain/requests/graph_version.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import Field 4 | 5 | from hatchify.common.domain.requests.base import BasePageRequest 6 | 7 | 8 | class PageGraphVersionRequest(BasePageRequest): 9 | graph_id: Optional[str] = Field(default=None, description="按 graph_id 过滤") 10 | -------------------------------------------------------------------------------- /hatchify/business/repositories/message_repository.py: -------------------------------------------------------------------------------- 1 | from hatchify.business.models.messages import MessageTable 2 | from hatchify.business.repositories.base.generic_repository import GenericRepository 3 | 4 | 5 | class MessageRepository(GenericRepository[MessageTable]): 6 | 7 | def __init__(self): 8 | super().__init__(MessageTable) 9 | -------------------------------------------------------------------------------- /hatchify/business/repositories/session_repository.py: -------------------------------------------------------------------------------- 1 | from hatchify.business.models.session import SessionTable 2 | from hatchify.business.repositories.base.generic_repository import GenericRepository 3 | 4 | 5 | class SessionRepository(GenericRepository[SessionTable]): 6 | 7 | def __init__(self): 8 | super().__init__(SessionTable) 9 | -------------------------------------------------------------------------------- /hatchify/business/repositories/execution_repository.py: -------------------------------------------------------------------------------- 1 | from hatchify.business.models.execution import ExecutionTable 2 | from hatchify.business.repositories.base.generic_repository import GenericRepository 3 | 4 | 5 | class ExecutionRepository(GenericRepository[ExecutionTable]): 6 | 7 | def __init__(self): 8 | super().__init__(ExecutionTable) 9 | -------------------------------------------------------------------------------- /web/src/hooks/useBodyClassOnOpen.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | export function useBodyClassOnOpen(isOpen: boolean, className: string) { 4 | useEffect(() => { 5 | document.body.classList.toggle(className, isOpen); 6 | return () => { 7 | document.body.classList.remove(className); 8 | }; 9 | }, [isOpen, className]); 10 | } 11 | -------------------------------------------------------------------------------- /hatchify/common/domain/requests/web_builder.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from strands.types.content import Messages 3 | 4 | 5 | class WebBuilderConversationRequest(BaseModel): 6 | graph_id: str 7 | messages: Messages 8 | redeploy: bool = True 9 | 10 | 11 | class DeployRequest(BaseModel): 12 | graph_id: str 13 | rebuild: bool = False -------------------------------------------------------------------------------- /hatchify/common/domain/responses/tool_response.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, Optional 2 | 3 | from pydantic import BaseModel, Field 4 | 5 | 6 | class ToolResponse(BaseModel): 7 | name: str 8 | description: str 9 | input_schema: Dict[str, Any] = Field(default_factory=dict) 10 | output_schema: Optional[Dict[str, Any]] = Field(default=None) 11 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/agent_category.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class AgentCategory(str, Enum): 5 | """Agent 类型 6 | 7 | - GENERAL: 普通 Agent,执行具体任务 8 | - ROUTER: 路由 Agent,根据条件决定下一步执行哪个节点 9 | - ORCHESTRATOR: 编排 Agent,中心化协调所有其他节点 10 | """ 11 | GENERAL = "general" 12 | ROUTER = "router" 13 | ORCHESTRATOR = "orchestrator" 14 | -------------------------------------------------------------------------------- /hatchify/common/domain/entity/function_node_spec.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel, Field 2 | 3 | 4 | class FunctionNode(BaseModel): 5 | name: str = Field( 6 | ..., 7 | description="节点唯一名称(在 Graph 中的 ID,可以自定义)" 8 | ) 9 | function_ref: str = Field( 10 | ..., 11 | description="Function 类型(从 function_manager 查找对应的 @tool 函数名)" 12 | ) 13 | -------------------------------------------------------------------------------- /hatchify/common/domain/requests/base.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import BaseModel, Field 4 | 5 | 6 | class BasePageRequest(BaseModel): 7 | """基础分页请求类,使用 base-1(从1开始)的页码""" 8 | page: int = Field(default=1) # 页码,从1开始 9 | size: int = Field(default=10) # 每页大小 10 | sort: Optional[str] = Field(default=None, description="field1:asc,field2:desc") 11 | -------------------------------------------------------------------------------- /hatchify/core/graph/functions/echo_function.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from strands import tool 3 | 4 | 5 | class EchoResult(BaseModel): 6 | text: str 7 | 8 | 9 | @tool(name="echo_function", description="Echo the input text") 10 | async def echo_function(text: str) -> EchoResult: 11 | """简单的 echo function,用于测试""" 12 | return EchoResult(text=f"[ECHO] {text}") 13 | -------------------------------------------------------------------------------- /web/src/types/api.ts: -------------------------------------------------------------------------------- 1 | export type ApiExtraResponse = T; 2 | 3 | export type ApiResponse = { 4 | message: string; 5 | code: number; 6 | data: T; 7 | }; 8 | 9 | export type WithPagination = { 10 | page: number; 11 | limit: number; 12 | total: number; 13 | pages: number; 14 | hasNext: boolean; 15 | hasPrev: boolean; 16 | list: T[]; 17 | }; 18 | -------------------------------------------------------------------------------- /web/src/utils/WaitLock.ts: -------------------------------------------------------------------------------- 1 | export default class WaitLock { 2 | private p: Promise | null = null; 3 | private resolve: (value?: any) => void = () => {}; 4 | 5 | lock() { 6 | this.p = new Promise((resolve) => { 7 | this.resolve = resolve; 8 | }); 9 | } 10 | 11 | unlock(value?: any) { 12 | this.resolve(value); 13 | } 14 | 15 | wait() { 16 | return this.p; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /hatchify/common/domain/requests/execution.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import Field 4 | 5 | from hatchify.common.domain.enums.execution_status import ExecutionStatus 6 | from hatchify.common.domain.enums.execution_type import ExecutionType 7 | from hatchify.common.domain.requests.base import BasePageRequest 8 | 9 | 10 | class PageExecutionRequest(BasePageRequest): 11 | ... -------------------------------------------------------------------------------- /web/packages/icons/icons/ai-logos-novita.svg: -------------------------------------------------------------------------------- 1 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-circle-filled-M.svg: -------------------------------------------------------------------------------- 1 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /web/src/components/common/Markdown/AnswerMakdown.scss: -------------------------------------------------------------------------------- 1 | .cite-popover { 2 | .ant-popover-inner { 3 | display: flex !important; 4 | align-items: stretch !important; 5 | width: 320px !important; 6 | height: 96px !important; 7 | border-radius: 16px !important; 8 | padding: 8px !important; 9 | } 10 | 11 | .ant-popover-inner-content { 12 | flex: 1 1 0% !important; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | hatchify 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /hatchify/business/services/message_service.py: -------------------------------------------------------------------------------- 1 | from hatchify.business.models.messages import MessageTable 2 | from hatchify.business.repositories.message_repository import MessageRepository 3 | from hatchify.business.services.base.generic_service import GenericService 4 | 5 | 6 | class MessageService(GenericService[MessageTable]): 7 | 8 | def __init__(self): 9 | super().__init__(MessageTable, MessageRepository) 10 | -------------------------------------------------------------------------------- /web/packages/icons/icons/reduce.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-circle-filled-S.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-outline.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/src/hooks/useTheme.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { 3 | ThemeProviderContext, 4 | type ThemeProviderState, 5 | } from "@/components/provider/ThemeProvider"; 6 | 7 | export const useTheme = () => { 8 | const context = useContext(ThemeProviderContext); 9 | 10 | if (context === undefined) 11 | throw new Error("useTheme must be used within a ThemeProvider"); 12 | 13 | return context; 14 | }; 15 | -------------------------------------------------------------------------------- /hatchify/common/domain/event/wrapper_event.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Literal 2 | 3 | from pydantic import BaseModel, Field 4 | 5 | 6 | class AgentEvent(BaseModel): 7 | """Agent 对话事件包装""" 8 | data: Any 9 | type: Literal["agent"] = Field(default="agent", exclude=True) 10 | 11 | 12 | class DeployEvent(BaseModel): 13 | """部署构建事件包装""" 14 | data: Any 15 | type: Literal["deploy"] = Field(default="deploy", exclude=True) 16 | -------------------------------------------------------------------------------- /web/packages/icons/icons/dividing-line.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-circle-filled-L.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /hatchify/common/domain/entity/graph_execute_data.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Any 2 | 3 | from pydantic import BaseModel 4 | 5 | from hatchify.common.domain.enums.storage_type import StorageType 6 | 7 | 8 | class FileData(BaseModel): 9 | key: str 10 | mime: str 11 | name: str 12 | source: StorageType 13 | 14 | 15 | class GraphExecuteData(BaseModel): 16 | jsons: Dict[str, Any] 17 | files: Dict[str, List[FileData]] 18 | -------------------------------------------------------------------------------- /hatchify/common/domain/responses/session_response.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from pydantic import BaseModel, ConfigDict 4 | 5 | from hatchify.common.domain.enums.session_scene import SessionScene 6 | 7 | 8 | class SessionResponse(BaseModel): 9 | id: str 10 | graph_id: str 11 | scene: SessionScene 12 | created_at: datetime 13 | updated_at: datetime 14 | 15 | model_config = ConfigDict(from_attributes=True) 16 | -------------------------------------------------------------------------------- /web/packages/icons/icons/line-divider-v.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /hatchify/common/domain/enums/execution_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class ExecutionType(str, Enum): 5 | """执行类型 - 对应不同的任务场景""" 6 | WEBHOOK = "webhook" # Webhook 执行 (web_hook_router) 7 | GRAPH_BUILDER = "graph_builder" # Graph 对话 (graph_router) 8 | WEB_BUILDER = "web_builder" # Web Builder 对话 (web_builder_router) 9 | DEPLOY = "deploy" # 部署任务 (web_builder_router deploy) -------------------------------------------------------------------------------- /web/packages/icons/icons/credit-basic-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /web/src/components/common/UserProfileHead.tsx: -------------------------------------------------------------------------------- 1 | import { Settings as SettingsIcon } from "@hatchify/icons"; 2 | import { useNavigate } from "react-router"; 3 | 4 | export default function UserProfileHead() { 5 | const navigate = useNavigate(); 6 | return ( 7 |
8 | { 10 | navigate("/settings"); 11 | }} 12 | className="size-5 hover:text-primary-1 cursor-pointer" 13 | /> 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /web/src/hooks/useStudioParams.ts: -------------------------------------------------------------------------------- 1 | import { useParams } from "react-router"; 2 | import { webCreatorTaskId, workflowTaskId } from "@/utils/taskId"; 3 | 4 | export const useStudioParams = () => { 5 | const { id } = useParams<{ id: string }>(); 6 | const taskIdForWorkflow = id ? workflowTaskId.get(id) : undefined; 7 | const taskIdForWebCreator = id ? webCreatorTaskId.get(id) : undefined; 8 | return { workflowId: id, taskIdForWorkflow, taskIdForWebCreator }; 9 | }; 10 | -------------------------------------------------------------------------------- /web/packages/icons/icons/expand-sm.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /web/src/app/studio/components/ChatPanel/chatinput.module.scss: -------------------------------------------------------------------------------- 1 | .chatInput { 2 | &::-webkit-scrollbar { 3 | width: 4px; 4 | } 5 | 6 | &::-webkit-scrollbar-track { 7 | background: transparent; 8 | } 9 | 10 | /* 滚动条滑块 */ 11 | &::-webkit-scrollbar-thumb { 12 | background-color: #3a89ffaf; 13 | border-radius: 2px; 14 | } 15 | 16 | /* 鼠标悬停时的滑块样式 */ 17 | &::-webkit-scrollbar-thumb:hover { 18 | background-color: #3a89ff; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /hatchify/common/domain/requests/message.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import Field 4 | 5 | from hatchify.common.domain.enums.message_role import MessageRole 6 | from hatchify.common.domain.requests.base import BasePageRequest 7 | 8 | 9 | class PageMessageRequest(BasePageRequest): 10 | session_id: Optional[str] = Field(default=None, description="按 session_id 过滤") 11 | role: Optional[MessageRole] = Field(default=None, description="按角色过滤") 12 | -------------------------------------------------------------------------------- /hatchify/common/domain/requests/session.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import Field 4 | 5 | from hatchify.common.domain.enums.session_scene import SessionScene 6 | from hatchify.common.domain.requests.base import BasePageRequest 7 | 8 | 9 | class PageSessionRequest(BasePageRequest): 10 | graph_id: Optional[str] = Field(default=None, description="按 graph_id 过滤") 11 | scene: Optional[SessionScene] = Field(default=None, description="按 scene 过滤") 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/ai-logos-anthropic.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /web/src/types/resources.ts: -------------------------------------------------------------------------------- 1 | // This file is auto generated by scripts/build-locales-resource.ts 2 | // Don't modify it manually. 3 | 4 | import en from "@/locales/en.json"; 5 | import zh_CN from "@/locales/zh_CN.json"; 6 | 7 | export const resources = { 8 | en: { 9 | translation: en, 10 | }, 11 | zh_CN: { 12 | translation: zh_CN, 13 | }, 14 | }; 15 | 16 | export type Resources = (typeof resources)["en"]; 17 | 18 | export const supportLangs: string[] = ["en", "zh_CN"]; 19 | -------------------------------------------------------------------------------- /hatchify/common/domain/entity/init_context.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, Literal 2 | 3 | from pydantic import BaseModel, Field 4 | 5 | 6 | class InitContext(BaseModel): 7 | base_url: str 8 | repo_url: str 9 | graph_id: str 10 | graph_input_format: Literal["application/json", "multipart/form-data"] = Field(default="application/json") 11 | input_schema: Dict[str, Any] = Field(default_factory=dict) 12 | output_schema: Dict[str, Any] = Field(default_factory=dict) -------------------------------------------------------------------------------- /web/packages/icons/icons/social-media-logos-mono-x.svg: -------------------------------------------------------------------------------- 1 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /web/packages/icons/icons/social-media-logos-official-x.svg: -------------------------------------------------------------------------------- 1 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /web/packages/icons/icons/title-txt-words.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/src/app/studio/components/ChatPanel/index.tsx: -------------------------------------------------------------------------------- 1 | // import { useChatHistoryQuery } from "@/lib/webcreator/useChatHistoryQuery"; 2 | import { useChatHistoryQuery } from "@/hooks/useChatHistory"; 3 | import ChatInput from "./ChatInput"; 4 | import ChatMessageArea from "./ChatMessageArea"; 5 | 6 | export default function ChatPanel() { 7 | useChatHistoryQuery(); 8 | return ( 9 |
10 | 11 | 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /web/src/components/common/BrandButton/brand-button.module.scss: -------------------------------------------------------------------------------- 1 | .brandButton { 2 | background-color: rgba(0, 0, 0, 0.96); 3 | 4 | & > span { 5 | background: linear-gradient( 6 | 103deg, 7 | #ffe3aa 5.37%, 8 | #edf0ff 40.89%, 9 | #aebeff 68.56%, 10 | #bba3ff 91.14% 11 | ); 12 | background-clip: text; 13 | -webkit-background-clip: text; 14 | -webkit-text-fill-color: transparent; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/src/router.ts: -------------------------------------------------------------------------------- 1 | import { lazy } from "react"; 2 | import { createBrowserRouter } from "react-router"; 3 | import StudioPage from "@/app/studio/Studio"; 4 | 5 | const router = createBrowserRouter([ 6 | { 7 | path: "/", 8 | Component: lazy(() => import("@/app/home/Home")), 9 | }, 10 | { 11 | path: "/studio/:id", 12 | Component: StudioPage, 13 | }, 14 | { 15 | path: "/settings", 16 | Component: lazy(() => import("@/app/settings/Settings")), 17 | }, 18 | ]); 19 | export default router; 20 | -------------------------------------------------------------------------------- /hatchify/core/manager/function_manager.py: -------------------------------------------------------------------------------- 1 | from strands.tools.decorator import DecoratedFunctionTool 2 | 3 | from hatchify.core.factory.tool_factory import ToolRouter 4 | from hatchify.core.graph.functions.echo_function import echo_function 5 | 6 | # 限制 function_router 只接受 DecoratedFunctionTool 7 | # 这确保只有 @tool 装饰的函数可以注册为 Function 8 | # FunctionNodeWrapper 依赖 DecoratedFunctionTool 的特性(如 input_model) 9 | function_router = ToolRouter[DecoratedFunctionTool]() 10 | 11 | function_router.register(echo_function) 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/ai-logos-microsoft.svg: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /web/packages/icons/icons/position-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /web/packages/icons/icons/clock-loader-25.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/slash-line.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Environment variables 16 | .env 17 | .env.local 18 | .env.*.local 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | .DS_Store 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | 31 | # TypeScript 32 | *.tsbuildinfo 33 | tsconfig.tsbuildinfo 34 | -------------------------------------------------------------------------------- /web/packages/icons/icons/down-md.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /web/packages/icons/icons/line-divider-tilt.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/check-md.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /web/packages/icons/icons/position-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /web/src/types/agent.ts: -------------------------------------------------------------------------------- 1 | export type AgentDetail = { 2 | name: string; 3 | model: string; 4 | instruction: string; 5 | category: string; 6 | tools: string[]; 7 | structured_output_schema: { 8 | type: string; 9 | properties: { 10 | [key: string]: { 11 | type: string; 12 | description: string; 13 | }[]; 14 | }; 15 | }; 16 | }; 17 | 18 | export type AgentToolDetail = { 19 | name: string; 20 | description: string; 21 | input_schema: Record; 22 | output_schema: Record; 23 | }; 24 | -------------------------------------------------------------------------------- /web/packages/icons/icons/text.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/src/app/home/components/Header.tsx: -------------------------------------------------------------------------------- 1 | import { TextLogo } from "@hatchify/icons"; 2 | import UserProfileHead from "@/components/common/UserProfileHead"; 3 | 4 | function Header() { 5 | return ( 6 |
7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 | ); 15 | } 16 | 17 | export default Header; 18 | -------------------------------------------------------------------------------- /web/packages/icons/icons/window-size-change.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/vite.config.ts: -------------------------------------------------------------------------------- 1 | import react from '@vitejs/plugin-react'; 2 | import path from 'path'; 3 | import { defineConfig } from 'vite'; 4 | 5 | export default defineConfig({ 6 | plugins: [react()], 7 | resolve: { 8 | alias: { 9 | '@': path.resolve(__dirname, './preview'), 10 | '@icons': path.resolve(__dirname, './src'), 11 | }, 12 | }, 13 | css: { 14 | postcss: { 15 | plugins: [], 16 | }, 17 | }, 18 | server: { 19 | fs: { 20 | // 允许访问上级目录 21 | allow: ['../../..'], 22 | }, 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /web/packages/icons/icons/add-cross.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-circle-outline-M.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import uvicorn 4 | 5 | from hatchify.common.constants.constants import Constants 6 | from hatchify.common.settings.settings import get_hatchify_settings 7 | 8 | settings = get_hatchify_settings() 9 | if __name__ == "__main__": 10 | config = uvicorn.Config( 11 | "hatchify.launch.launch:app", 12 | host=settings.server.host, 13 | port=settings.server.port, 14 | loop="asyncio", 15 | env_file=Constants.Path.EnvPath 16 | ) 17 | server = uvicorn.Server(config) 18 | asyncio.run(server.serve()) 19 | -------------------------------------------------------------------------------- /web/packages/icons/icons/add-outline-s.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-circle-outline-S.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-s-b.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-s-r.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-s-t.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-top.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/back-arrow-left.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/star-default.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-s-l.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/check-mark.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/right-outline-l.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/right-outline-m.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/add-outline-m.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-l-b.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-l-l.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-l-r.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-l-t.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-m-b.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-m-l.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-m-r.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-outline-m-t.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/right-outline-s.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /hatchify/business/manager/repository_manager.py: -------------------------------------------------------------------------------- 1 | from typing import Type, Dict, Any 2 | 3 | 4 | class RepositoryManager: 5 | _instances: Dict[Type, Any] = {} 6 | 7 | @classmethod 8 | def get_repository(cls, repo_class: Type) -> Any: 9 | if repo_class not in cls._instances: 10 | cls._instances[repo_class] = repo_class() 11 | return cls._instances[repo_class] 12 | 13 | @classmethod 14 | def get_repository_dependency(cls, repo_class: Type): 15 | def provider(): 16 | return cls.get_repository(repo_class) 17 | 18 | return provider 19 | -------------------------------------------------------------------------------- /hatchify/common/domain/responses/graph_response.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Any, Dict, Optional 3 | 4 | from pydantic import BaseModel, ConfigDict, Field 5 | 6 | 7 | class GraphResponse(BaseModel): 8 | id: str 9 | name: str 10 | description: Optional[str] = Field(default=None) 11 | current_spec: Dict[str, Any] 12 | current_version_id: Optional[int] = Field(default=None) 13 | current_session_id: Optional[str] = Field(default=None) 14 | created_at: datetime 15 | updated_at: datetime 16 | 17 | model_config = ConfigDict(from_attributes=True) 18 | -------------------------------------------------------------------------------- /web/packages/icons/icons/back-arrow-line.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hatchify/business/manager/service_manager.py: -------------------------------------------------------------------------------- 1 | from typing import Type, Dict, Any 2 | 3 | 4 | class ServiceManager: 5 | _instances: Dict[Type, Any] = {} 6 | 7 | @classmethod 8 | def get_service(cls, service_class: Type) -> Any: 9 | if service_class not in cls._instances: 10 | cls._instances[service_class] = service_class() 11 | return cls._instances[service_class] 12 | 13 | @classmethod 14 | def get_service_dependency(cls, service_class: Type): 15 | def provider(): 16 | return cls.get_service(service_class) 17 | 18 | return provider 19 | -------------------------------------------------------------------------------- /web/packages/icons/icons/clock-loader-125.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/src/stores/workflow/index.tsx: -------------------------------------------------------------------------------- 1 | import { create } from "zustand"; 2 | import { devtools } from "zustand/middleware"; 3 | import type { ChatSlice } from "./slices/chatSlice"; 4 | import { createChatSlice } from "./slices/chatSlice"; 5 | import type { UiSlice } from "./slices/uiSlice"; 6 | import { createUiSlice } from "./slices/uiSlice"; 7 | 8 | type WorkflowStoreState = ChatSlice & UiSlice; 9 | 10 | const useWorkflowStore = create()( 11 | devtools((...a) => ({ 12 | ...createChatSlice(...a), 13 | ...createUiSlice(...a), 14 | })), 15 | ); 16 | 17 | export default useWorkflowStore; 18 | -------------------------------------------------------------------------------- /web/.dockerignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | **/node_modules 4 | 5 | # Build outputs 6 | dist 7 | **/dist 8 | .vite 9 | .turbo 10 | 11 | # Development files 12 | .git 13 | .github 14 | *.log 15 | npm-debug.log* 16 | pnpm-debug.log* 17 | yarn-debug.log* 18 | yarn-error.log* 19 | 20 | # IDE 21 | .vscode 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | .DS_Store 27 | 28 | # Test coverage 29 | coverage 30 | .nyc_output 31 | 32 | # Environment files 33 | .env 34 | .env.local 35 | .env.development 36 | .env.production 37 | .env*.local 38 | 39 | # Misc 40 | *.md 41 | !README.md 42 | .gitignore 43 | .editorconfig 44 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-handle-down.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-line-b.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/model-grok.svg: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-handle-right.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-line-t.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/src/app/studio/components/ChatPanel/ChatMessageArea/ChatLoadingItem.tsx: -------------------------------------------------------------------------------- 1 | import { Loading } from "@hatchify/icons"; 2 | 3 | function ChatLoadingItem() { 4 | return ( 5 |
6 |
13 | 14 |
15 |
16 | ); 17 | } 18 | 19 | export default ChatLoadingItem; 20 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-handle-left.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-line-tl.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-line-bl.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/credit-card.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-line-l.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/more-h.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web/packages/icons/icons/more-v.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-handle-down-right.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-handle-top.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/clock-loader-75.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-circle-filled.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /web/packages/icons/icons/start-recording.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-handle-down-left.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/minus-circle-outline-L.svg: -------------------------------------------------------------------------------- 1 | 8 | 15 | 16 | -------------------------------------------------------------------------------- /web/packages/icons/icons/add-outline-l.svg: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-filled-b.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-filled-l.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-filled-r.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-filled-t.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/arrow-line-br.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /web/packages/icons/icons/points-more-ellipsis.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web/src/components/common/ModelSelecter.tsx: -------------------------------------------------------------------------------- 1 | import { Select } from "antd"; 2 | import { ModelApi } from "@/api"; 3 | 4 | export default function ModelSelecter({ 5 | value, 6 | onChange, 7 | }: { 8 | value: string; 9 | onChange: (value: string) => void; 10 | }) { 11 | const { modelList } = ModelApi.useModelList(); 12 | 13 | const modelOptions = modelList.map((model) => ({ 14 | label: model.id, 15 | value: model.id, 16 | })); 17 | 18 | return ( 19 |