First Types
This commit is contained in:
parent
cbe4943e3f
commit
2c5f66d98a
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,4 +22,3 @@ cabal.project.local
|
||||
cabal.project.local~
|
||||
.HTF/
|
||||
.ghc.environment.*
|
||||
|
||||
|
51
app/Main.hs
51
app/Main.hs
@ -1,8 +1,53 @@
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
|
||||
module Main where
|
||||
|
||||
import qualified MyLib (someFunc)
|
||||
import Agent.Server.Config (Config, configFile, loadConfigOrDefault, saveConfig)
|
||||
import Agent.Tools.Time ()
|
||||
import Agent.Tools.Tool (Tool, getToolListTH, toMarkdownDL)
|
||||
import Control.Concurrent (threadDelay)
|
||||
import Control.Exception (AsyncException (UserInterrupt), bracket, catch)
|
||||
import Control.Monad (when)
|
||||
import qualified Data.ByteString as BS
|
||||
import Data.Default
|
||||
import Data.Either (fromRight, isRight)
|
||||
import Data.Either.Extra (fromRight')
|
||||
import Data.Proxy
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as T
|
||||
import Data.Yaml (decodeFileThrow)
|
||||
import qualified Data.Yaml as YAML
|
||||
import Language.Haskell.TH
|
||||
import System.IO (hFlush, stdout)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn "Hello, Haskell!"
|
||||
MyLib.someFunc
|
||||
(conf :: Config) <- (configFile >>= maybe (return def) decodeFileThrow)
|
||||
|
||||
let availableTools = ($(getToolListTH) :: [Tool])
|
||||
putStrLn "# HAgent\n"
|
||||
putStrLn "\n## Cofig\n"
|
||||
BS.putStr $ (YAML.encode conf) <> "\n"
|
||||
putStrLn "## Available Tools\n"
|
||||
mapM_ T.putStrLn $ toMarkdownDL <$> availableTools
|
||||
bracket acquireResource releaseResource $ \_ ->
|
||||
mainLoop `catch` handler
|
||||
where
|
||||
acquireResource :: IO ()
|
||||
acquireResource = putStrLn "Acquiring resource..."
|
||||
|
||||
releaseResource :: () -> IO ()
|
||||
releaseResource _ = putStrLn "Releasing resource..."
|
||||
|
||||
mainLoop :: IO ()
|
||||
mainLoop = do
|
||||
putStr "waiting for work ...\r"
|
||||
hFlush stdout
|
||||
-- Simulate work
|
||||
-- Add your main loop logic here
|
||||
threadDelay 1000000
|
||||
mainLoop
|
||||
|
||||
handler :: AsyncException -> IO ()
|
||||
handler UserInterrupt = putStrLn "\nCaught Ctrl-C. Exiting gracefully."
|
||||
|
1
cabal.project
Normal file
1
cabal.project
Normal file
@ -0,0 +1 @@
|
||||
packages: *.cabal
|
191
hagent.cabal
191
hagent.cabal
@ -1,127 +1,96 @@
|
||||
cabal-version: 3.4
|
||||
-- The cabal-version field refers to the version of the .cabal specification,
|
||||
-- and can be different from the cabal-install (the tool) version and the
|
||||
-- Cabal (the library) version you are using. As such, the Cabal (the library)
|
||||
-- version used must be equal or greater than the version stated in this field.
|
||||
-- Starting from the specification version 2.2, the cabal-version field must be
|
||||
-- the first thing in the cabal file.
|
||||
cabal-version: 1.12
|
||||
|
||||
-- Initial package description 'hagent' generated by
|
||||
-- 'cabal init'. For further documentation, see:
|
||||
-- http://haskell.org/cabal/users-guide/
|
||||
-- This file has been generated from package.yaml by hpack version 0.38.0.
|
||||
--
|
||||
-- The name of the package.
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: hagent
|
||||
|
||||
-- The package version.
|
||||
-- See the Haskell package versioning policy (PVP) for standards
|
||||
-- guiding when and how versions should be incremented.
|
||||
-- https://pvp.haskell.org
|
||||
-- PVP summary: +-+------- breaking API changes
|
||||
-- | | +----- non-breaking API additions
|
||||
-- | | | +--- code changes with no API change
|
||||
version: 0.1.0.0
|
||||
|
||||
-- A short (one-line) description of the package.
|
||||
-- synopsis:
|
||||
|
||||
-- A longer description of the package.
|
||||
-- description:
|
||||
|
||||
-- The license under which the package is released.
|
||||
license: AGPL-3.0-only
|
||||
|
||||
-- The file containing the license text.
|
||||
license: AGPL-3.0
|
||||
license-file: LICENSE
|
||||
|
||||
-- The package author(s).
|
||||
author: Nicole Dresselhaus
|
||||
|
||||
-- An email address to which users can send suggestions, bug reports, and patches.
|
||||
maintainer: nicole@dresselhaus.cloud
|
||||
|
||||
-- A copyright notice.
|
||||
-- copyright:
|
||||
build-type: Simple
|
||||
|
||||
-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.
|
||||
extra-doc-files: CHANGELOG.md
|
||||
|
||||
-- Extra source files to be distributed with the package, such as examples, or a tutorial module.
|
||||
-- extra-source-files:
|
||||
|
||||
common warnings
|
||||
ghc-options: -Wall
|
||||
|
||||
library
|
||||
-- Import common warning flags.
|
||||
import: warnings
|
||||
|
||||
-- Modules exported by the library.
|
||||
exposed-modules: MyLib
|
||||
|
||||
-- Modules included in this library but not exported.
|
||||
-- other-modules:
|
||||
|
||||
-- LANGUAGE extensions used by modules in this package.
|
||||
-- other-extensions:
|
||||
|
||||
-- Other library packages from which modules are imported.
|
||||
build-depends: base ^>=4.20.0.0
|
||||
|
||||
-- Directories containing source files.
|
||||
hs-source-dirs: src
|
||||
|
||||
-- Base language which the package is written in.
|
||||
default-language: GHC2024
|
||||
exposed-modules:
|
||||
Agent.Server.Config
|
||||
Agent.Tools.Tool
|
||||
Agent.Tools.Time
|
||||
other-modules:
|
||||
Paths_hagent
|
||||
build-depends:
|
||||
base >=4.20.0 && <4.21,
|
||||
bytestring,
|
||||
data-default >=0.8.0 && <0.9,
|
||||
directory >=1.3.8 && <1.4,
|
||||
extra ==1.8.*,
|
||||
filepath >=1.5.2 && <1.6,
|
||||
ollama-haskell >=0.1.2 && <0.2,
|
||||
template-haskell,
|
||||
text,
|
||||
yaml >=0.11.11 && <0.12
|
||||
hs-source-dirs:
|
||||
src
|
||||
default-extensions:
|
||||
OverloadedStrings
|
||||
DerivingStrategies
|
||||
DeriveAnyClass
|
||||
DeriveGeneric
|
||||
DerivingVia
|
||||
GADTs
|
||||
default-language: Haskell2010
|
||||
|
||||
executable hagent
|
||||
-- Import common warning flags.
|
||||
import: warnings
|
||||
|
||||
-- .hs or .lhs file containing the Main module.
|
||||
main-is: Main.hs
|
||||
|
||||
-- Modules included in this executable, other than Main.
|
||||
-- other-modules:
|
||||
|
||||
-- LANGUAGE extensions used by modules in this package.
|
||||
-- other-extensions:
|
||||
|
||||
-- Other library packages from which modules are imported.
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
Paths_hagent
|
||||
build-depends:
|
||||
base ^>=4.20.0.0,
|
||||
hagent
|
||||
|
||||
-- Directories containing source files.
|
||||
hs-source-dirs: app
|
||||
|
||||
-- Base language which the package is written in.
|
||||
default-language: GHC2024
|
||||
base >=4.20.0 && <4.21,
|
||||
bytestring,
|
||||
data-default >=0.8.0 && <0.9,
|
||||
directory >=1.3.8 && <1.4,
|
||||
extra ==1.8.*,
|
||||
filepath >=1.5.2 && <1.6,
|
||||
hagent,
|
||||
ollama-haskell >=0.1.2 && <0.2,
|
||||
template-haskell,
|
||||
text,
|
||||
yaml >=0.11.11 && <0.12
|
||||
hs-source-dirs:
|
||||
app
|
||||
default-extensions:
|
||||
OverloadedStrings
|
||||
DerivingStrategies
|
||||
DeriveAnyClass
|
||||
DeriveGeneric
|
||||
DerivingVia
|
||||
GADTs
|
||||
default-language: Haskell2010
|
||||
|
||||
test-suite hagent-test
|
||||
-- Import common warning flags.
|
||||
import: warnings
|
||||
|
||||
-- Base language which the package is written in.
|
||||
default-language: GHC2024
|
||||
|
||||
-- Modules included in this executable, other than Main.
|
||||
-- other-modules:
|
||||
|
||||
-- LANGUAGE extensions used by modules in this package.
|
||||
-- other-extensions:
|
||||
|
||||
-- The interface type and version of the test suite.
|
||||
type: exitcode-stdio-1.0
|
||||
|
||||
-- Directories containing source files.
|
||||
hs-source-dirs: test
|
||||
|
||||
-- The entrypoint to the test suite.
|
||||
main-is: Main.hs
|
||||
|
||||
-- Test dependencies.
|
||||
default-language: Haskell2010
|
||||
type: exitcode-stdio-1.0
|
||||
hs-source-dirs:
|
||||
test
|
||||
default-extensions:
|
||||
OverloadedStrings
|
||||
DerivingStrategies
|
||||
DeriveAnyClass
|
||||
DeriveGeneric
|
||||
DerivingVia
|
||||
GADTs
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
Paths_hagent
|
||||
build-depends:
|
||||
base ^>=4.20.0.0,
|
||||
hagent
|
||||
base >=4.20.0 && <4.21,
|
||||
bytestring,
|
||||
data-default >=0.8.0 && <0.9,
|
||||
directory >=1.3.8 && <1.4,
|
||||
extra ==1.8.*,
|
||||
filepath >=1.5.2 && <1.6,
|
||||
hagent,
|
||||
ollama-haskell >=0.1.2 && <0.2,
|
||||
text,
|
||||
yaml >=0.11.11 && <0.12
|
||||
|
43
package.yaml
Normal file
43
package.yaml
Normal file
@ -0,0 +1,43 @@
|
||||
name: hagent
|
||||
version: '0.1.0.0'
|
||||
author: Nicole Dresselhaus
|
||||
maintainer: nicole@dresselhaus.cloud
|
||||
license: AGPL-3.0
|
||||
dependencies:
|
||||
- base >= 4.20.0 && < 4.21
|
||||
- data-default >= 0.8.0 && < 0.9
|
||||
- directory >= 1.3.8 && < 1.4
|
||||
- filepath >= 1.5.2 && < 1.6
|
||||
- extra >= 1.8 && < 1.9
|
||||
- ollama-haskell >= 0.1.2 && < 0.2
|
||||
- yaml >= 0.11.11 && < 0.12
|
||||
- text
|
||||
- bytestring
|
||||
default-extensions:
|
||||
- OverloadedStrings
|
||||
- DerivingStrategies
|
||||
- DeriveAnyClass
|
||||
- DeriveGeneric
|
||||
- DerivingVia
|
||||
- GADTs
|
||||
library:
|
||||
source-dirs: src
|
||||
exposed-modules:
|
||||
- Agent.Server.Config
|
||||
- Agent.Tools.Tool
|
||||
- Agent.Tools.Time
|
||||
dependencies:
|
||||
- template-haskell
|
||||
executables:
|
||||
hagent:
|
||||
main: Main.hs
|
||||
source-dirs: app
|
||||
dependencies:
|
||||
- hagent
|
||||
- template-haskell
|
||||
tests:
|
||||
hagent-test:
|
||||
main: Main.hs
|
||||
source-dirs: test
|
||||
dependencies:
|
||||
- hagent
|
92
src/Agent/Server/Config.hs
Normal file
92
src/Agent/Server/Config.hs
Normal file
@ -0,0 +1,92 @@
|
||||
{-# LANGUAGE DeriveAnyClass #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE DerivingStrategies #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Agent.Server.Config
|
||||
( configPath,
|
||||
loadConfig,
|
||||
loadConfigOrDefault,
|
||||
saveConfig,
|
||||
Config (..),
|
||||
OllamaConfig (..),
|
||||
NoConfigFoundException,
|
||||
configFile,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Exception (Exception (..))
|
||||
import Control.Monad.Extra (whenMaybeM)
|
||||
import Data.Default (Default (..))
|
||||
import Data.Text (Text (..))
|
||||
import Data.Yaml (FromJSON, ParseException (..), ToJSON, decodeFileEither, decodeFileThrow, encodeFile)
|
||||
import GHC.Generics (Generic)
|
||||
import System.Directory (XdgDirectory (..), createDirectoryIfMissing, doesFileExist, getXdgDirectory)
|
||||
import System.FilePath ((</>))
|
||||
|
||||
data Config = Config
|
||||
{ startOllama :: Bool,
|
||||
ollama :: OllamaConfig
|
||||
}
|
||||
deriving stock (Show, Eq, Generic)
|
||||
deriving anyclass (FromJSON, ToJSON)
|
||||
|
||||
instance Default Config where
|
||||
def =
|
||||
Config
|
||||
{ startOllama = False,
|
||||
ollama = def
|
||||
}
|
||||
|
||||
data OllamaConfig = OllamaConfig
|
||||
{ host :: Text,
|
||||
port :: Int,
|
||||
cmdExtra :: Text
|
||||
}
|
||||
deriving stock (Show, Eq, Generic)
|
||||
deriving anyclass (FromJSON, ToJSON)
|
||||
|
||||
instance Default OllamaConfig where
|
||||
def =
|
||||
OllamaConfig
|
||||
{ host = "localhost",
|
||||
port = 11434,
|
||||
cmdExtra = ""
|
||||
}
|
||||
|
||||
data NoConfigFoundException = NotFound FilePath
|
||||
deriving (Show)
|
||||
|
||||
instance Exception NoConfigFoundException
|
||||
|
||||
configPath :: FilePath
|
||||
configPath = "hAgent"
|
||||
|
||||
configName :: FilePath
|
||||
configName = "config.yaml"
|
||||
|
||||
configFile :: IO (Maybe FilePath)
|
||||
configFile = do
|
||||
filepath <- (getXdgDirectory XdgConfig (configPath </> configName))
|
||||
whenMaybeM (doesFileExist filepath) (return filepath)
|
||||
|
||||
loadConfig :: IO (Either ParseException Config)
|
||||
loadConfig = do
|
||||
filepath <- (getXdgDirectory XdgConfig (configPath </> configName))
|
||||
confFile <- configFile
|
||||
case confFile of
|
||||
Just f -> decodeFileEither f
|
||||
Nothing -> return $ Left $ OtherParseException $ toException $ NotFound $ filepath
|
||||
|
||||
loadConfigOrDefault :: IO (Either ParseException Config)
|
||||
loadConfigOrDefault = do
|
||||
confFile <- configFile
|
||||
case confFile of
|
||||
Just f -> decodeFileEither f
|
||||
Nothing -> return $ Right $ def
|
||||
|
||||
saveConfig :: Config -> IO ()
|
||||
saveConfig conf = do
|
||||
getXdgDirectory XdgConfig configPath >>= createDirectoryIfMissing True
|
||||
confPath <- (getXdgDirectory XdgConfig (configPath </> configName))
|
||||
encodeFile confPath conf
|
26
src/Agent/Tools/Time.hs
Normal file
26
src/Agent/Tools/Time.hs
Normal file
@ -0,0 +1,26 @@
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE InstanceSigs #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
|
||||
module Agent.Tools.Time where
|
||||
|
||||
import Agent.Tools.Tool
|
||||
import Agent.Tools.Tool (Tool)
|
||||
import Control.Monad.IO.Class
|
||||
import Data.Proxy
|
||||
import Data.Text
|
||||
|
||||
data CurrentTimeTool
|
||||
|
||||
instance KnownTool CurrentTimeTool where
|
||||
toolVal _ =
|
||||
Tool
|
||||
{ name = "current_time",
|
||||
call = "",
|
||||
description = "Get the current Time"
|
||||
}
|
||||
|
||||
instance Dispatchable CurrentTimeTool () where
|
||||
dispatch :: (MonadIO m) => Proxy t -> () -> m Text
|
||||
dispatch Proxy () = return "Current Timed: 09.03.2025 14:38"
|
||||
parseArgs _ _ = ()
|
46
src/Agent/Tools/Tool.hs
Normal file
46
src/Agent/Tools/Tool.hs
Normal file
@ -0,0 +1,46 @@
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE KindSignatures #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
|
||||
module Agent.Tools.Tool where
|
||||
|
||||
import Control.Monad.IO.Class
|
||||
import qualified Data.Kind as DK (Type)
|
||||
import Data.Proxy
|
||||
import Data.Text
|
||||
import Language.Haskell.TH
|
||||
|
||||
data Tool = Tool
|
||||
{ name :: Text,
|
||||
description :: Text,
|
||||
call :: Text
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
toMarkdownDL :: Tool -> Text
|
||||
toMarkdownDL t = "- " <> name t <> "(" <> call t <> ")\n: " <> description t
|
||||
|
||||
-- | This type represents unknown type-level tools.
|
||||
data SomeTool = forall t. (KnownTool t) => SomeTool (Proxy t)
|
||||
|
||||
-- | This class gives the tool associated with a type-level tool.
|
||||
-- There are instances of the class for every concrete tool included.
|
||||
class KnownTool (t :: DK.Type) where
|
||||
toolVal :: Proxy t -> Tool
|
||||
|
||||
class (KnownTool t) => Dispatchable t a where
|
||||
dispatch :: (MonadIO m) => Proxy t -> a -> m Text
|
||||
parseArgs :: Proxy t -> Text -> a
|
||||
|
||||
getToolListTH :: Q Exp
|
||||
getToolListTH = do
|
||||
ClassI _ instances <- reify ''Dispatchable
|
||||
let toolExps =
|
||||
[ [|toolVal (Proxy :: Proxy $(return t))|]
|
||||
| InstanceD _ _ (AppT (AppT _ t) _) _ <-
|
||||
instances
|
||||
]
|
||||
listE toolExps
|
@ -1,4 +0,0 @@
|
||||
module MyLib (someFunc) where
|
||||
|
||||
someFunc :: IO ()
|
||||
someFunc = putStrLn "someFunc"
|
Loading…
x
Reference in New Issue
Block a user