digital-employee-core 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- digital_employee_core-0.0.1/PKG-INFO +103 -0
- digital_employee_core-0.0.1/README.md +74 -0
- digital_employee_core-0.0.1/digital_employee_core/__init__.py +26 -0
- digital_employee_core-0.0.1/digital_employee_core/agents/__init__.py +1 -0
- digital_employee_core-0.0.1/digital_employee_core/config_templates/__init__.py +8 -0
- digital_employee_core-0.0.1/digital_employee_core/config_templates/loader.py +187 -0
- digital_employee_core-0.0.1/digital_employee_core/config_templates/mcp_configs.yaml +54 -0
- digital_employee_core-0.0.1/digital_employee_core/config_templates/tool_configs.yaml +9 -0
- digital_employee_core-0.0.1/digital_employee_core/configuration/__init__.py +7 -0
- digital_employee_core-0.0.1/digital_employee_core/configuration/configuration.py +27 -0
- digital_employee_core-0.0.1/digital_employee_core/connectors/__init__.py +4 -0
- digital_employee_core-0.0.1/digital_employee_core/connectors/mcps/__init__.py +22 -0
- digital_employee_core-0.0.1/digital_employee_core/connectors/mcps/google_mcps.py +62 -0
- digital_employee_core-0.0.1/digital_employee_core/connectors/tools/__init__.py +1 -0
- digital_employee_core-0.0.1/digital_employee_core/digital_employee/__init__.py +8 -0
- digital_employee_core-0.0.1/digital_employee_core/digital_employee/digital_employee.py +367 -0
- digital_employee_core-0.0.1/digital_employee_core/identity/__init__.py +16 -0
- digital_employee_core-0.0.1/digital_employee_core/identity/identity.py +83 -0
- digital_employee_core-0.0.1/pyproject.toml +64 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: digital-employee-core
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary:
|
|
5
|
+
Author: Digital Employee Team
|
|
6
|
+
Requires-Python: >=3.11,<3.13
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Requires-Dist: aip-agents-binary (>=0.4.8,<0.5.0)
|
|
11
|
+
Requires-Dist: apscheduler (>=3.11.0,<4.0.0)
|
|
12
|
+
Requires-Dist: authlib (>=1.6.1,<2.0.0)
|
|
13
|
+
Requires-Dist: email-validator (>=2.3.0,<3.0.0)
|
|
14
|
+
Requires-Dist: fastapi (>=0.117.1,<0.118.0)
|
|
15
|
+
Requires-Dist: glaip-sdk (>=0.6.2)
|
|
16
|
+
Requires-Dist: gllm-plugin-binary (>=0.0.7,<0.0.8)
|
|
17
|
+
Requires-Dist: google-api-python-client (>=2.0.0,<3.0.0)
|
|
18
|
+
Requires-Dist: opentelemetry-instrumentation-httpx
|
|
19
|
+
Requires-Dist: opentelemetry-instrumentation-requests
|
|
20
|
+
Requires-Dist: pre-commit (>=4.2.0,<5.0.0)
|
|
21
|
+
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
22
|
+
Requires-Dist: python-multipart (>=0.0.20,<0.0.21)
|
|
23
|
+
Requires-Dist: pyyaml (>=6.0.3,<7.0.0)
|
|
24
|
+
Requires-Dist: requests (>=2.32.0,<3.0.0)
|
|
25
|
+
Requires-Dist: ruff (>=0.14.0,<0.15.0)
|
|
26
|
+
Requires-Dist: uvicorn (>=0.34.0,<0.35.0)
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Digital Employee Core
|
|
30
|
+
|
|
31
|
+
A Python library for building and managing AI-powered digital employees with support for tools, MCPs (Model Context Protocol), and flexible configuration management.
|
|
32
|
+
|
|
33
|
+
## Setup
|
|
34
|
+
|
|
35
|
+
### 1. Install Dependencies
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
poetry install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Configure Environment
|
|
42
|
+
|
|
43
|
+
Copy the example environment file and add your credentials:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cp .env.example .env
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Edit `.env` with your configuration:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Required
|
|
53
|
+
AIP_API_URL=https://your-ai-platform-url.com
|
|
54
|
+
AIP_API_KEY=your-api-key
|
|
55
|
+
|
|
56
|
+
# Optional: Google MCP Configuration
|
|
57
|
+
GOOGLE_CALENDAR_MCP_URL=https://api.example.com/calendar/mcp
|
|
58
|
+
GOOGLE_DOCS_MCP_URL=https://api.example.com/docs/mcp
|
|
59
|
+
GOOGLE_MCP_X_API_KEY=your-google-mcp-key
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Run Examples
|
|
63
|
+
|
|
64
|
+
### Basic Usage
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
poetry run python examples/basic_usage.py
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Configuration Usage
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
poetry run python examples/configuration_usage.py
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Subclass Example
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
poetry run python examples/subclass_example.py
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Run Tests
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Run all tests
|
|
86
|
+
poetry run pytest
|
|
87
|
+
|
|
88
|
+
# Run with verbose output
|
|
89
|
+
poetry run pytest -v
|
|
90
|
+
|
|
91
|
+
# Run with coverage
|
|
92
|
+
poetry run coverage run -m pytest
|
|
93
|
+
poetry run coverage report
|
|
94
|
+
|
|
95
|
+
# Run with coverage HTML report
|
|
96
|
+
poetry run coverage run -m pytest
|
|
97
|
+
poetry run coverage html
|
|
98
|
+
# Open htmlcov/index.html in browser
|
|
99
|
+
|
|
100
|
+
# Run specific test file
|
|
101
|
+
poetry run pytest tests/digital_employee/test_digital_employee.py
|
|
102
|
+
```
|
|
103
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Digital Employee Core
|
|
2
|
+
|
|
3
|
+
A Python library for building and managing AI-powered digital employees with support for tools, MCPs (Model Context Protocol), and flexible configuration management.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### 1. Install Dependencies
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
poetry install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### 2. Configure Environment
|
|
14
|
+
|
|
15
|
+
Copy the example environment file and add your credentials:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cp .env.example .env
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Edit `.env` with your configuration:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Required
|
|
25
|
+
AIP_API_URL=https://your-ai-platform-url.com
|
|
26
|
+
AIP_API_KEY=your-api-key
|
|
27
|
+
|
|
28
|
+
# Optional: Google MCP Configuration
|
|
29
|
+
GOOGLE_CALENDAR_MCP_URL=https://api.example.com/calendar/mcp
|
|
30
|
+
GOOGLE_DOCS_MCP_URL=https://api.example.com/docs/mcp
|
|
31
|
+
GOOGLE_MCP_X_API_KEY=your-google-mcp-key
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Run Examples
|
|
35
|
+
|
|
36
|
+
### Basic Usage
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
poetry run python examples/basic_usage.py
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Configuration Usage
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
poetry run python examples/configuration_usage.py
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Subclass Example
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
poetry run python examples/subclass_example.py
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Run Tests
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Run all tests
|
|
58
|
+
poetry run pytest
|
|
59
|
+
|
|
60
|
+
# Run with verbose output
|
|
61
|
+
poetry run pytest -v
|
|
62
|
+
|
|
63
|
+
# Run with coverage
|
|
64
|
+
poetry run coverage run -m pytest
|
|
65
|
+
poetry run coverage report
|
|
66
|
+
|
|
67
|
+
# Run with coverage HTML report
|
|
68
|
+
poetry run coverage run -m pytest
|
|
69
|
+
poetry run coverage html
|
|
70
|
+
# Open htmlcov/index.html in browser
|
|
71
|
+
|
|
72
|
+
# Run specific test file
|
|
73
|
+
poetry run pytest tests/digital_employee/test_digital_employee.py
|
|
74
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Digital employee Core package.
|
|
2
|
+
|
|
3
|
+
This package provides the core functionality for building and managing
|
|
4
|
+
digital employees with support for tools, MCPs, and configurations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from digital_employee_core.config_templates import ConfigTemplateLoader
|
|
8
|
+
from digital_employee_core.configuration import DigitalEmployeeConfiguration
|
|
9
|
+
from digital_employee_core.digital_employee import DigitalEmployee
|
|
10
|
+
from digital_employee_core.identity import (
|
|
11
|
+
DigitalEmployeeIdentity,
|
|
12
|
+
DigitalEmployeeJob,
|
|
13
|
+
DigitalEmployeeSupervisor,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
# Core classes
|
|
18
|
+
"ConfigTemplateLoader",
|
|
19
|
+
"DigitalEmployee",
|
|
20
|
+
# Identity classes
|
|
21
|
+
"DigitalEmployeeIdentity",
|
|
22
|
+
"DigitalEmployeeJob",
|
|
23
|
+
"DigitalEmployeeSupervisor",
|
|
24
|
+
# Configuration classes
|
|
25
|
+
"DigitalEmployeeConfiguration",
|
|
26
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Agents package for digital employee core."""
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""Configuration template loader and processor.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for loading and processing configuration templates
|
|
4
|
+
from YAML files, replacing placeholders with values from DigitalEmployeeConfiguration objects.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Immanuel Rhesa (immanuel.rhesa@gdplabs.id)
|
|
8
|
+
|
|
9
|
+
References:
|
|
10
|
+
NONE
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
import yaml
|
|
18
|
+
|
|
19
|
+
from digital_employee_core.configuration.configuration import DigitalEmployeeConfiguration
|
|
20
|
+
|
|
21
|
+
# Configuration template filenames
|
|
22
|
+
MCP_CONFIGS_TEMPLATE = "mcp_configs.yaml"
|
|
23
|
+
TOOL_CONFIGS_TEMPLATE = "tool_configs.yaml"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ConfigTemplateLoader:
|
|
27
|
+
"""Loads and processes configuration templates from YAML files.
|
|
28
|
+
|
|
29
|
+
This class handles loading YAML configuration templates and replacing
|
|
30
|
+
placeholders with actual values from DigitalEmployeeConfiguration objects.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
template_dir (Path): Path to the directory containing template files.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, template_dir: str | Path | None = None):
|
|
37
|
+
"""Initialize the ConfigTemplateLoader.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
template_dir (str | Path | None, optional): Path to template directory. Defaults to config_templates
|
|
41
|
+
in the package directory.
|
|
42
|
+
"""
|
|
43
|
+
if template_dir is None:
|
|
44
|
+
# Default to config_templates directory in the package
|
|
45
|
+
package_dir = Path(__file__).parent.parent
|
|
46
|
+
template_dir = package_dir / "config_templates"
|
|
47
|
+
|
|
48
|
+
self.template_dir = Path(template_dir)
|
|
49
|
+
|
|
50
|
+
def load_template(self, filename: str) -> dict[str, Any]:
|
|
51
|
+
"""Load a YAML template file.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
filename (str): Name of the template file (e.g., 'mcp_configs.yaml').
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
dict[str, Any]: Dictionary containing the template configuration.
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
FileNotFoundError: If the template file does not exist.
|
|
61
|
+
"""
|
|
62
|
+
template_path = self.template_dir / filename
|
|
63
|
+
return self.load_template_from_path(template_path)
|
|
64
|
+
|
|
65
|
+
def load_template_from_path(self, filepath: str | Path) -> dict[str, Any]:
|
|
66
|
+
"""Load a YAML template file from an absolute path.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
filepath (str | Path): Absolute path to the template file.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
dict[str, Any]: Dictionary containing the template configuration.
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
FileNotFoundError: If the template file does not exist.
|
|
76
|
+
"""
|
|
77
|
+
template_path = Path(filepath)
|
|
78
|
+
if not template_path.exists():
|
|
79
|
+
raise FileNotFoundError(f"Template file not found: {template_path}")
|
|
80
|
+
|
|
81
|
+
with open(template_path) as f:
|
|
82
|
+
return yaml.safe_load(f) or {}
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def merge_configs(
|
|
86
|
+
base_config: dict[str, dict[str, Any]],
|
|
87
|
+
additional_config: dict[str, dict[str, Any]],
|
|
88
|
+
) -> dict[str, dict[str, Any]]:
|
|
89
|
+
"""Merge two configuration dictionaries.
|
|
90
|
+
|
|
91
|
+
The additional_config will override values in base_config for matching keys.
|
|
92
|
+
New keys in additional_config will be added to the result.
|
|
93
|
+
Performs recursive deep merge for nested dictionaries.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
base_config (dict[str, dict[str, Any]]): Base configuration dictionary.
|
|
97
|
+
additional_config (dict[str, dict[str, Any]]): Additional configuration to merge.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
dict[str, dict[str, Any]]: Merged configuration dictionary.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
def _deep_merge(base: dict[str, Any], additional: dict[str, Any]) -> dict[str, Any]:
|
|
104
|
+
"""Recursively merge two dictionaries."""
|
|
105
|
+
result = base.copy()
|
|
106
|
+
for key, value in additional.items():
|
|
107
|
+
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
|
108
|
+
# Recursively merge nested dictionaries
|
|
109
|
+
result[key] = _deep_merge(result[key], value)
|
|
110
|
+
else:
|
|
111
|
+
# Override or add new key
|
|
112
|
+
result[key] = value
|
|
113
|
+
return result
|
|
114
|
+
|
|
115
|
+
return _deep_merge(base_config, additional_config)
|
|
116
|
+
|
|
117
|
+
def _replace_placeholders(
|
|
118
|
+
self,
|
|
119
|
+
template: dict[str, Any],
|
|
120
|
+
configurations: list[DigitalEmployeeConfiguration],
|
|
121
|
+
) -> dict[str, Any]:
|
|
122
|
+
"""Replace placeholders in template with configuration values.
|
|
123
|
+
|
|
124
|
+
Placeholders are in format <PLACEHOLDER_KEY> and are replaced with
|
|
125
|
+
values from DigitalEmployeeConfiguration objects matching the key.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
template (dict[str, Any]): Template dictionary with placeholders.
|
|
129
|
+
configurations (list[DigitalEmployeeConfiguration]): List of DigitalEmployeeConfiguration objects.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
dict[str, Any]: Dictionary with placeholders replaced by actual values.
|
|
133
|
+
"""
|
|
134
|
+
# Create a mapping of keys to values from configurations
|
|
135
|
+
config_map: dict[str, str] = {}
|
|
136
|
+
for config in configurations:
|
|
137
|
+
config_map[config.key] = config.value
|
|
138
|
+
|
|
139
|
+
def replace_value(value: Any) -> Any:
|
|
140
|
+
"""Recursively replace placeholders in values."""
|
|
141
|
+
if isinstance(value, str):
|
|
142
|
+
# Find all placeholders in format <KEY>
|
|
143
|
+
placeholders = re.findall(r"<([^>]+)>", value)
|
|
144
|
+
result = value
|
|
145
|
+
for placeholder in placeholders:
|
|
146
|
+
if placeholder in config_map:
|
|
147
|
+
# Replace the placeholder with the actual value
|
|
148
|
+
result = result.replace(f"<{placeholder}>", config_map[placeholder])
|
|
149
|
+
return result
|
|
150
|
+
elif isinstance(value, dict):
|
|
151
|
+
return {k: replace_value(v) for k, v in value.items()}
|
|
152
|
+
elif isinstance(value, list):
|
|
153
|
+
return [replace_value(item) for item in value]
|
|
154
|
+
else:
|
|
155
|
+
return value
|
|
156
|
+
|
|
157
|
+
return replace_value(template)
|
|
158
|
+
|
|
159
|
+
def load_mcp_configs(
|
|
160
|
+
self,
|
|
161
|
+
configurations: list[DigitalEmployeeConfiguration],
|
|
162
|
+
) -> dict[str, dict[str, Any]]:
|
|
163
|
+
"""Load MCP configuration template and replace placeholders.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
configurations (list[DigitalEmployeeConfiguration]): List of DigitalEmployeeConfiguration objects.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
dict[str, dict[str, Any]]: Dictionary mapping MCP names to their configurations.
|
|
170
|
+
"""
|
|
171
|
+
template = self.load_template(MCP_CONFIGS_TEMPLATE)
|
|
172
|
+
return self._replace_placeholders(template, configurations)
|
|
173
|
+
|
|
174
|
+
def load_tool_configs(
|
|
175
|
+
self,
|
|
176
|
+
configurations: list[DigitalEmployeeConfiguration],
|
|
177
|
+
) -> dict[str, dict[str, Any]]:
|
|
178
|
+
"""Load tool configuration template and replace placeholders.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
configurations (list[DigitalEmployeeConfiguration]): List of DigitalEmployeeConfiguration objects.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
dict[str, dict[str, Any]]: Dictionary mapping tool names to their configurations.
|
|
185
|
+
"""
|
|
186
|
+
template = self.load_template(TOOL_CONFIGS_TEMPLATE)
|
|
187
|
+
return self._replace_placeholders(template, configurations)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# MCP Configuration Templates
|
|
2
|
+
#
|
|
3
|
+
# This file contains configuration templates for MCPs (Model Context Protocol servers).
|
|
4
|
+
# Placeholders in angle brackets (e.g., <PLACEHOLDER_KEY>) will be replaced with values
|
|
5
|
+
# from DigitalEmployeeConfiguration objects at runtime using the placeholder key.
|
|
6
|
+
#
|
|
7
|
+
# Format:
|
|
8
|
+
# mcp-name:
|
|
9
|
+
# config:
|
|
10
|
+
# key: value or <PLACEHOLDER_KEY>
|
|
11
|
+
# authentication:
|
|
12
|
+
# type: "api-key" | "oauth" | "bearer"
|
|
13
|
+
# key: "header-name"
|
|
14
|
+
# value: <PLACEHOLDER_KEY>
|
|
15
|
+
|
|
16
|
+
digital_employee_google_calendar_mcp:
|
|
17
|
+
config:
|
|
18
|
+
url: <GOOGLE_CALENDAR_MCP_URL>
|
|
19
|
+
authentication:
|
|
20
|
+
type: api-key
|
|
21
|
+
key: X-API-Key
|
|
22
|
+
value: <GOOGLE_MCP_X_API_KEY>
|
|
23
|
+
|
|
24
|
+
digital_employee_google_docs_mcp:
|
|
25
|
+
config:
|
|
26
|
+
url: <GOOGLE_DOCS_MCP_URL>
|
|
27
|
+
authentication:
|
|
28
|
+
type: api-key
|
|
29
|
+
key: X-API-Key
|
|
30
|
+
value: <GOOGLE_MCP_X_API_KEY>
|
|
31
|
+
|
|
32
|
+
digital_employee_google_drive_mcp:
|
|
33
|
+
config:
|
|
34
|
+
url: <GOOGLE_DRIVE_MCP_URL>
|
|
35
|
+
authentication:
|
|
36
|
+
type: api-key
|
|
37
|
+
key: X-API-Key
|
|
38
|
+
value: <GOOGLE_MCP_X_API_KEY>
|
|
39
|
+
|
|
40
|
+
digital_employee_google_mail_mcp:
|
|
41
|
+
config:
|
|
42
|
+
url: <GOOGLE_MAIL_MCP_URL>
|
|
43
|
+
authentication:
|
|
44
|
+
type: api-key
|
|
45
|
+
key: X-API-Key
|
|
46
|
+
value: <GOOGLE_MCP_X_API_KEY>
|
|
47
|
+
|
|
48
|
+
digital_employee_google_sheets_mcp:
|
|
49
|
+
config:
|
|
50
|
+
url: <GOOGLE_SHEETS_MCP_URL>
|
|
51
|
+
authentication:
|
|
52
|
+
type: api-key
|
|
53
|
+
key: X-API-Key
|
|
54
|
+
value: <GOOGLE_MCP_X_API_KEY>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Tool Configuration Templates
|
|
2
|
+
#
|
|
3
|
+
# This file contains configuration templates for tools.
|
|
4
|
+
# Placeholders in angle brackets (e.g., <PLACEHOLDER_KEY>) will be replaced with values
|
|
5
|
+
# from DigitalEmployeeConfiguration objects at runtime using the placeholder key.
|
|
6
|
+
#
|
|
7
|
+
# Format:
|
|
8
|
+
# tool_name:
|
|
9
|
+
# key: value or <PLACEHOLDER_KEY>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Configuration and credentials management for digital employee.
|
|
2
|
+
|
|
3
|
+
This module provides classes for managing configuration credentials.
|
|
4
|
+
|
|
5
|
+
Authors:
|
|
6
|
+
Immanuel Rhesa (immanuel.rhesa@gdplabs.id)
|
|
7
|
+
|
|
8
|
+
References:
|
|
9
|
+
NONE
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class DigitalEmployeeConfiguration:
|
|
17
|
+
"""Represents a single configuration for digital employee.
|
|
18
|
+
|
|
19
|
+
This class combines both configuration and credential information.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
key (str): The configuration key identifier (e.g., "GOOGLE_MCP_X_API_KEY", "SPREADSHEET_ID").
|
|
23
|
+
value (str): The configuration value or credential.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
key: str
|
|
27
|
+
value: str
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""MCPs package for Digital Employee Core.
|
|
2
|
+
|
|
3
|
+
This package provides pre-configured MCP instances for various services.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from digital_employee_core.connectors.mcps.google_mcps import (
|
|
7
|
+
ALL_GOOGLE_MCPS,
|
|
8
|
+
google_calendar_mcp,
|
|
9
|
+
google_docs_mcp,
|
|
10
|
+
google_drive_mcp,
|
|
11
|
+
google_mail_mcp,
|
|
12
|
+
google_sheets_mcp,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"google_calendar_mcp",
|
|
17
|
+
"google_docs_mcp",
|
|
18
|
+
"google_drive_mcp",
|
|
19
|
+
"google_mail_mcp",
|
|
20
|
+
"google_sheets_mcp",
|
|
21
|
+
"ALL_GOOGLE_MCPS",
|
|
22
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Google MCPs for Digital Employee Core.
|
|
2
|
+
|
|
3
|
+
This module provides pre-configured MCP instances for Google services
|
|
4
|
+
that can be easily imported and used in Digital Employee implementations.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Immanuel Rhesa (immanuel.rhesa@gdplabs.id)
|
|
8
|
+
|
|
9
|
+
References:
|
|
10
|
+
NONE
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from glaip_sdk import MCP
|
|
14
|
+
|
|
15
|
+
# Google Calendar MCP
|
|
16
|
+
google_calendar_mcp = MCP(
|
|
17
|
+
name="digital_employee_google_calendar_mcp",
|
|
18
|
+
description="MCP for Google Calendar Operation for DE",
|
|
19
|
+
transport="http",
|
|
20
|
+
config={"url": "https://default.com/google_calendar/mcp"},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Google Docs MCP
|
|
24
|
+
google_docs_mcp = MCP(
|
|
25
|
+
name="digital_employee_google_docs_mcp",
|
|
26
|
+
description="MCP for Google Docs Operation for DE",
|
|
27
|
+
transport="http",
|
|
28
|
+
config={"url": "https://default.com/google_docs/mcp"},
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Google Drive MCP
|
|
32
|
+
google_drive_mcp = MCP(
|
|
33
|
+
name="digital_employee_google_drive_mcp",
|
|
34
|
+
description="MCP for Google Drive Operation for DE",
|
|
35
|
+
transport="http",
|
|
36
|
+
config={"url": "https://default.com/google_drive/mcp"},
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Google Mail MCP
|
|
40
|
+
google_mail_mcp = MCP(
|
|
41
|
+
name="digital_employee_google_mail_mcp",
|
|
42
|
+
description="MCP for Google Mail Operation for DE",
|
|
43
|
+
transport="http",
|
|
44
|
+
config={"url": "https://default.com/google_mail/mcp"},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Google Sheets MCP
|
|
48
|
+
google_sheets_mcp = MCP(
|
|
49
|
+
name="digital_employee_google_sheets_mcp",
|
|
50
|
+
description="MCP for Google Sheets Operation for DE",
|
|
51
|
+
transport="http",
|
|
52
|
+
config={"url": "https://default.com/google_sheets/mcp"},
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Convenience list of all Google MCPs
|
|
56
|
+
ALL_GOOGLE_MCPS = [
|
|
57
|
+
google_calendar_mcp,
|
|
58
|
+
google_docs_mcp,
|
|
59
|
+
google_drive_mcp,
|
|
60
|
+
google_mail_mcp,
|
|
61
|
+
google_sheets_mcp,
|
|
62
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Tools package for digital employee core."""
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
"""Core digital employee orchestrator.
|
|
2
|
+
|
|
3
|
+
This module provides the base DigitalEmployee class that manages agents,
|
|
4
|
+
tools, and MCPs. It implements the ConfigBuilder interface to
|
|
5
|
+
provide configuration building capabilities.
|
|
6
|
+
|
|
7
|
+
Authors:
|
|
8
|
+
Immanuel Rhesa (immanuel.rhesa@gdplabs.id)
|
|
9
|
+
|
|
10
|
+
References:
|
|
11
|
+
NONE
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from glaip_sdk import MCP, Agent, Tool
|
|
17
|
+
|
|
18
|
+
from digital_employee_core.config_templates.loader import ConfigTemplateLoader
|
|
19
|
+
from digital_employee_core.configuration.configuration import (
|
|
20
|
+
DigitalEmployeeConfiguration,
|
|
21
|
+
)
|
|
22
|
+
from digital_employee_core.identity.identity import DigitalEmployeeIdentity
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DigitalEmployee:
|
|
26
|
+
"""Core digital employee orchestrator.
|
|
27
|
+
|
|
28
|
+
This class manages the lifecycle of a digital employee, including
|
|
29
|
+
initialization, deployment, and execution of agents with tools and MCPs.
|
|
30
|
+
Provides methods for building tool and MCP configurations from YAML templates.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
identity (DigitalEmployeeIdentity): The digital employee's identity.
|
|
34
|
+
tools (list[Tool]): List of tools the digital employee can use.
|
|
35
|
+
sub_agents (list[Agent]): List of sub-agents (for future use).
|
|
36
|
+
mcps (list[MCP]): List of MCPs the digital employee can use.
|
|
37
|
+
configurations (list[DigitalEmployeeConfiguration]): List of configuration objects for tools and MCPs.
|
|
38
|
+
agent (Agent | None): The main agent instance.
|
|
39
|
+
config_loader (ConfigTemplateLoader): The configuration template loader instance.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
identity: DigitalEmployeeIdentity,
|
|
45
|
+
tools: list[Tool] | None = None,
|
|
46
|
+
sub_agents: list[Agent] | None = None,
|
|
47
|
+
mcps: list[MCP] | None = None,
|
|
48
|
+
configurations: list[DigitalEmployeeConfiguration] | None = None,
|
|
49
|
+
):
|
|
50
|
+
"""Initialize the digital employee.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
identity (DigitalEmployeeIdentity): The digital employee's identity.
|
|
54
|
+
tools (list[Tool] | None, optional): List of tools the digital employee can use. Defaults to None.
|
|
55
|
+
sub_agents (list[Agent] | None, optional): List of sub-agents (for future use). Defaults to None.
|
|
56
|
+
mcps (list[MCP] | None, optional): List of MCPs the digital employee can use. Defaults to None.
|
|
57
|
+
configurations (list[DigitalEmployeeConfiguration] | None, optional): List of configuration objects
|
|
58
|
+
for tools and MCPs. Defaults to None.
|
|
59
|
+
"""
|
|
60
|
+
self.identity = identity
|
|
61
|
+
self.tools = tools or []
|
|
62
|
+
self.sub_agents = sub_agents or []
|
|
63
|
+
self.mcps = mcps or []
|
|
64
|
+
self.configurations = configurations or []
|
|
65
|
+
self.agent: Agent | None = None
|
|
66
|
+
self.config_loader = ConfigTemplateLoader()
|
|
67
|
+
|
|
68
|
+
def add_tools(self, tools: list[Tool]) -> None:
|
|
69
|
+
"""Add tools to the digital employee.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
tools (list[Tool]): List of tools to add.
|
|
73
|
+
"""
|
|
74
|
+
self.tools.extend(tools)
|
|
75
|
+
|
|
76
|
+
def add_mcps(self, mcps: list[MCP]) -> None:
|
|
77
|
+
"""Add MCPs to the digital employee.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
mcps (list[MCP]): List of MCPs to add.
|
|
81
|
+
"""
|
|
82
|
+
self.mcps.extend(mcps)
|
|
83
|
+
|
|
84
|
+
def add_sub_agents(self, sub_agents: list[Agent]) -> None:
|
|
85
|
+
"""Add sub-agents to the digital employee.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
sub_agents (list[Agent]): List of sub-agents to add.
|
|
89
|
+
"""
|
|
90
|
+
self.sub_agents.extend(sub_agents)
|
|
91
|
+
|
|
92
|
+
def build_instruction(self) -> str:
|
|
93
|
+
"""Build the instruction/prompt for the agent.
|
|
94
|
+
|
|
95
|
+
This method can be overridden by subclasses to provide custom
|
|
96
|
+
instructions based on the digital employee's identity and job.
|
|
97
|
+
Always includes the digital employee's name, email, and language preferences
|
|
98
|
+
in the prompt to ensure identity awareness.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
str: The instruction string for the agent.
|
|
102
|
+
"""
|
|
103
|
+
# Build identity information with language
|
|
104
|
+
language_names = [lang.value for lang in self.identity.languages]
|
|
105
|
+
|
|
106
|
+
if len(language_names) > 1:
|
|
107
|
+
language_list = ", ".join(language_names[:-1]) + f" and {language_names[-1]}"
|
|
108
|
+
language_instruction = (
|
|
109
|
+
f"You must respond only in the following languages: {language_list}. "
|
|
110
|
+
f"Choose the most appropriate language based on the user's input or context."
|
|
111
|
+
)
|
|
112
|
+
else:
|
|
113
|
+
language_instruction = f"You must respond only in {language_names[0]} language."
|
|
114
|
+
|
|
115
|
+
identity_prefix = (
|
|
116
|
+
f"You are {self.identity.name} ({self.identity.email}), {self.identity.job.title}. "
|
|
117
|
+
f"{language_instruction}"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
return f"{identity_prefix}\n\n{self.identity.job.instruction}"
|
|
121
|
+
|
|
122
|
+
def deploy(self) -> None:
|
|
123
|
+
"""Deploy the digital employee.
|
|
124
|
+
|
|
125
|
+
This method initializes the agent with tools and MCPs,
|
|
126
|
+
applies configurations to MCPs and tools, and deploys it to the AI platform.
|
|
127
|
+
"""
|
|
128
|
+
if self.configurations:
|
|
129
|
+
tool_configs = self.build_tool_config(self.configurations)
|
|
130
|
+
mcp_configs = self.build_mcp_config(self.configurations)
|
|
131
|
+
configured_mcps = self._apply_mcp_configs(self.mcps, mcp_configs)
|
|
132
|
+
configured_tools = self._apply_tool_configs(self.tools, tool_configs)
|
|
133
|
+
else:
|
|
134
|
+
configured_mcps = self.mcps
|
|
135
|
+
configured_tools = self.tools
|
|
136
|
+
|
|
137
|
+
self.agent = Agent(
|
|
138
|
+
name=self.identity.name,
|
|
139
|
+
description=self.identity.job.description,
|
|
140
|
+
instruction=self.build_instruction(),
|
|
141
|
+
tools=configured_tools,
|
|
142
|
+
agents=self.sub_agents,
|
|
143
|
+
mcps=configured_mcps,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
self.agent.deploy()
|
|
147
|
+
|
|
148
|
+
def run(
|
|
149
|
+
self,
|
|
150
|
+
message: str,
|
|
151
|
+
configurations: list[DigitalEmployeeConfiguration] | None = None,
|
|
152
|
+
) -> str:
|
|
153
|
+
"""Run the digital employee with a message.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
message (str): The message/prompt to send to the digital employee.
|
|
157
|
+
configurations (list[DigitalEmployeeConfiguration] | None, optional): List of configuration objects.
|
|
158
|
+
Defaults to None.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
str: The agent's response as a string.
|
|
162
|
+
|
|
163
|
+
Raises:
|
|
164
|
+
RuntimeError: If the agent has not been deployed.
|
|
165
|
+
"""
|
|
166
|
+
if self.agent is None:
|
|
167
|
+
raise RuntimeError("Agent has not been deployed. Call deploy() before run().")
|
|
168
|
+
|
|
169
|
+
configurations = configurations or []
|
|
170
|
+
runtime_config = self._build_runtime_configs(configurations)
|
|
171
|
+
|
|
172
|
+
return self.agent.run(message=message, runtime_config=runtime_config)
|
|
173
|
+
|
|
174
|
+
def build_tool_config(self, configurations: list[DigitalEmployeeConfiguration]) -> dict[str, dict[str, Any]]:
|
|
175
|
+
"""Build tool configuration based on identity and configurations.
|
|
176
|
+
|
|
177
|
+
This method loads tool configuration templates from YAML and replaces
|
|
178
|
+
placeholders with values from DigitalEmployeeConfiguration objects. Subclasses can
|
|
179
|
+
override this to provide custom logic and merge with parent configs.
|
|
180
|
+
|
|
181
|
+
Example for subclasses:
|
|
182
|
+
def build_tool_config(self, configurations):
|
|
183
|
+
# Get base configs from parent
|
|
184
|
+
base_configs = super().build_tool_config(configurations)
|
|
185
|
+
|
|
186
|
+
# Load additional configs for this subclass
|
|
187
|
+
additional = self.config_loader.load_tool_configs(configurations)
|
|
188
|
+
|
|
189
|
+
# Merge them
|
|
190
|
+
return self.config_loader.merge_configs(base_configs, additional)
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
configurations: List of configuration objects.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
dict[str, dict[str, Any]]: Dictionary mapping tool names to their configuration dictionaries.
|
|
197
|
+
"""
|
|
198
|
+
return self.config_loader.load_tool_configs(configurations)
|
|
199
|
+
|
|
200
|
+
def build_mcp_config(self, configurations: list[DigitalEmployeeConfiguration]) -> dict[str, dict[str, Any]]:
|
|
201
|
+
"""Build MCP configuration based on identity and configurations.
|
|
202
|
+
|
|
203
|
+
This method loads MCP configuration templates from YAML and replaces
|
|
204
|
+
placeholders with values from DigitalEmployeeConfiguration objects. Subclasses can
|
|
205
|
+
override this to provide custom logic and merge with parent configs.
|
|
206
|
+
|
|
207
|
+
Example for subclasses:
|
|
208
|
+
def build_mcp_config(self, configurations):
|
|
209
|
+
# Get base configs from parent
|
|
210
|
+
base_configs = super().build_mcp_config(configurations)
|
|
211
|
+
|
|
212
|
+
# Load additional configs for this subclass
|
|
213
|
+
additional = self.config_loader.load_mcp_configs(configurations)
|
|
214
|
+
|
|
215
|
+
# Merge them
|
|
216
|
+
return self.config_loader.merge_configs(base_configs, additional)
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
configurations (list[DigitalEmployeeConfiguration]): List of configuration objects.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
dict[str, dict[str, Any]]: Dictionary mapping MCP names to their configuration dictionaries.
|
|
223
|
+
"""
|
|
224
|
+
return self.config_loader.load_mcp_configs(configurations)
|
|
225
|
+
|
|
226
|
+
def _apply_mcp_configs(
|
|
227
|
+
self,
|
|
228
|
+
mcps: list[MCP],
|
|
229
|
+
mcp_configs: dict[str, dict[str, Any]],
|
|
230
|
+
) -> list[MCP]:
|
|
231
|
+
"""Apply configurations to MCPs.
|
|
232
|
+
|
|
233
|
+
This method updates the config and authentication attributes of MCPs
|
|
234
|
+
based on the provided configuration dictionary. Only updates MCPs
|
|
235
|
+
that have matching configurations.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
mcps (list[MCP]): List of MCP instances.
|
|
239
|
+
mcp_configs (dict[str, dict[str, Any]]): Dictionary mapping MCP names to their configurations.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
list[MCP]: List of MCPs with configurations applied.
|
|
243
|
+
"""
|
|
244
|
+
return [self._apply_single_mcp_config(mcp, mcp_configs) for mcp in mcps]
|
|
245
|
+
|
|
246
|
+
def _apply_single_mcp_config(self, mcp: MCP, mcp_configs: dict[str, dict[str, Any]]) -> MCP:
|
|
247
|
+
"""Apply configuration to a single MCP.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
mcp (MCP): MCP instance to configure.
|
|
251
|
+
mcp_configs (dict[str, dict[str, Any]]): Dictionary mapping MCP names to their configurations.
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
MCP: MCP with configuration applied.
|
|
255
|
+
"""
|
|
256
|
+
if not (mcp.name and mcp.name in mcp_configs):
|
|
257
|
+
return mcp
|
|
258
|
+
|
|
259
|
+
config_data = mcp_configs[mcp.name]
|
|
260
|
+
|
|
261
|
+
if config_data.get("config"):
|
|
262
|
+
if mcp.config is None:
|
|
263
|
+
mcp.config = {}
|
|
264
|
+
mcp.config.update(config_data["config"])
|
|
265
|
+
|
|
266
|
+
if config_data.get("authentication"):
|
|
267
|
+
if mcp.authentication is None:
|
|
268
|
+
mcp.authentication = {}
|
|
269
|
+
mcp.authentication.update(config_data["authentication"])
|
|
270
|
+
|
|
271
|
+
return mcp
|
|
272
|
+
|
|
273
|
+
def _apply_tool_configs(
|
|
274
|
+
self,
|
|
275
|
+
tools: list[Tool],
|
|
276
|
+
tool_configs: dict[str, dict[str, Any]],
|
|
277
|
+
) -> list[Tool]:
|
|
278
|
+
"""Apply configurations to tools.
|
|
279
|
+
|
|
280
|
+
This method updates tool configurations based on the provided
|
|
281
|
+
configuration dictionary. Only updates tools that have matching
|
|
282
|
+
configurations and a config attribute.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
tools (list[Tool]): List of tool names (strings) or Tool objects.
|
|
286
|
+
tool_configs (dict[str, dict[str, Any]]): Dictionary mapping tool names to their configurations.
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
list[Tool]: List of tools with configurations applied.
|
|
290
|
+
"""
|
|
291
|
+
configured_tools = []
|
|
292
|
+
for tool in tools:
|
|
293
|
+
if hasattr(tool, "name") and hasattr(tool, "config"):
|
|
294
|
+
if tool.name and tool.name in tool_configs:
|
|
295
|
+
config_data = tool_configs[tool.name]
|
|
296
|
+
if tool.config is None:
|
|
297
|
+
tool.config = {}
|
|
298
|
+
tool.config.update(config_data)
|
|
299
|
+
|
|
300
|
+
configured_tools.append(tool)
|
|
301
|
+
|
|
302
|
+
return configured_tools
|
|
303
|
+
|
|
304
|
+
def _filter_tool_configs(
|
|
305
|
+
self,
|
|
306
|
+
all_tool_configs: dict[str, dict[str, Any]],
|
|
307
|
+
) -> dict[str, dict[str, Any]]:
|
|
308
|
+
"""Filter tool configs to only include tools used by the agent.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
all_tool_configs (dict[str, dict[str, Any]]): All available tool configurations.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
dict[str, dict[str, Any]]: Filtered tool configurations for tools used by the agent.
|
|
315
|
+
"""
|
|
316
|
+
return {
|
|
317
|
+
name: config
|
|
318
|
+
for name, config in all_tool_configs.items()
|
|
319
|
+
if any(
|
|
320
|
+
(hasattr(tool, "name") and tool.name == name) or (isinstance(tool, str) and tool == name)
|
|
321
|
+
for tool in self.agent.tools
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
def _filter_mcp_configs(
|
|
326
|
+
self,
|
|
327
|
+
all_mcp_configs: dict[str, dict[str, Any]],
|
|
328
|
+
) -> dict[str, dict[str, Any]]:
|
|
329
|
+
"""Filter MCP configs to only include MCPs used by the agent.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
all_mcp_configs (dict[str, dict[str, Any]]): All available MCP configurations.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
dict[str, dict[str, Any]]: Filtered MCP configurations for MCPs used by the agent.
|
|
336
|
+
"""
|
|
337
|
+
return {
|
|
338
|
+
name: config
|
|
339
|
+
for name, config in all_mcp_configs.items()
|
|
340
|
+
if any(
|
|
341
|
+
(hasattr(mcp, "name") and mcp.name == name) or (isinstance(mcp, str) and mcp == name)
|
|
342
|
+
for mcp in self.agent.mcps
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
def _build_runtime_configs(
|
|
347
|
+
self,
|
|
348
|
+
configurations: list[DigitalEmployeeConfiguration],
|
|
349
|
+
) -> dict[str, dict[str, dict[str, Any]]]:
|
|
350
|
+
"""Build runtime configurations for tools and MCPs.
|
|
351
|
+
|
|
352
|
+
This method builds all configurations and filters them to only include
|
|
353
|
+
tools and MCPs that are actually used by the agent.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
configurations (list[DigitalEmployeeConfiguration]): List of configuration objects.
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
dict[str, dict[str, dict[str, Any]]]: Dictionary with 'tool_configs' and 'mcp_configs' keys.
|
|
360
|
+
"""
|
|
361
|
+
all_tool_configs = self.build_tool_config(configurations)
|
|
362
|
+
all_mcp_configs = self.build_mcp_config(configurations)
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
"tool_configs": self._filter_tool_configs(all_tool_configs),
|
|
366
|
+
"mcp_configs": self._filter_mcp_configs(all_mcp_configs),
|
|
367
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Identity module for digital employee.
|
|
2
|
+
|
|
3
|
+
This module provides identity classes for digital employees.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from digital_employee_core.identity.identity import (
|
|
7
|
+
DigitalEmployeeIdentity,
|
|
8
|
+
DigitalEmployeeJob,
|
|
9
|
+
DigitalEmployeeSupervisor,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"DigitalEmployeeIdentity",
|
|
14
|
+
"DigitalEmployeeJob",
|
|
15
|
+
"DigitalEmployeeSupervisor",
|
|
16
|
+
]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Digital employee identity classes.
|
|
2
|
+
|
|
3
|
+
This module provides identity classes for digital employees with support for
|
|
4
|
+
different levels of identity (base, HR, and specific implementations).
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Immanuel Rhesa (immanuel.rhesa@gdplabs.id)
|
|
8
|
+
|
|
9
|
+
References:
|
|
10
|
+
NONE
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from enum import StrEnum
|
|
14
|
+
from typing import Annotated
|
|
15
|
+
|
|
16
|
+
from pydantic import BaseModel, EmailStr, Field, StringConstraints
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class LangId(StrEnum):
|
|
20
|
+
"""The language id.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
EN: Id for English language.
|
|
24
|
+
ID: Id for Indonesian language.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
EN = "en"
|
|
28
|
+
ID = "id"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class DigitalEmployeeJob(BaseModel):
|
|
32
|
+
"""Digital employee Job definition.
|
|
33
|
+
|
|
34
|
+
Encapsulates job-specific information for a digital employee,
|
|
35
|
+
including title, description, and instructions.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
title (str): The job title or role name (e.g., "HR Assistant", "Payroll Specialist").
|
|
39
|
+
description (str): Detailed description of the job and responsibilities.
|
|
40
|
+
instruction (str): Specific instructions or guidelines for performing the job.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
title: str
|
|
44
|
+
description: str
|
|
45
|
+
instruction: str
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class DigitalEmployeeSupervisor(BaseModel):
|
|
49
|
+
"""Digital employee Supervisor information.
|
|
50
|
+
|
|
51
|
+
Represents the supervisor or manager overseeing the digital employee.
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
name (str): The supervisor's full name.
|
|
55
|
+
email (EmailStr): The supervisor's email address. Must be a valid email format.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
name: str
|
|
59
|
+
email: EmailStr
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class DigitalEmployeeIdentity(BaseModel):
|
|
63
|
+
"""Base digital employee Identity.
|
|
64
|
+
|
|
65
|
+
This is the base identity class that provides comprehensive information
|
|
66
|
+
for a digital employee, including personal details, job role, and supervisor.
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
name (Annotated[str, StringConstraints(max_length=100)]): The name of the digital employee.
|
|
70
|
+
Maximum length is 100 characters.
|
|
71
|
+
email (EmailStr): The digital employee's email address. Must be a valid email format.
|
|
72
|
+
job (DigitalEmployeeJob): The job information (title, description, instruction).
|
|
73
|
+
supervisor (DigitalEmployeeSupervisor | None, optional): The supervisor information (name and email).
|
|
74
|
+
Defaults to None.
|
|
75
|
+
languages (list[LangId]): The list of supported languages for the digital employee.
|
|
76
|
+
Defaults to [LangId.EN].
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
name: Annotated[str, StringConstraints(max_length=100)]
|
|
80
|
+
email: EmailStr
|
|
81
|
+
job: DigitalEmployeeJob
|
|
82
|
+
supervisor: DigitalEmployeeSupervisor | None = None
|
|
83
|
+
languages: list[LangId] = Field(default_factory=lambda: [LangId.EN])
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "digital-employee-core"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = ["Digital Employee Team"]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
[tool.poetry.dependencies]
|
|
10
|
+
python = ">=3.11,<3.13"
|
|
11
|
+
|
|
12
|
+
fastapi = ">=0.117.1,<0.118.0"
|
|
13
|
+
uvicorn = ">=0.34.0,<0.35.0"
|
|
14
|
+
|
|
15
|
+
authlib = "^1.6.1"
|
|
16
|
+
google-api-python-client = "^2.0.0"
|
|
17
|
+
python-multipart = "^0.0.20"
|
|
18
|
+
opentelemetry-instrumentation-requests = "*"
|
|
19
|
+
opentelemetry-instrumentation-httpx = "*"
|
|
20
|
+
apscheduler = "^3.11.0"
|
|
21
|
+
python-dotenv = "^1.0.0"
|
|
22
|
+
requests = "^2.32.0"
|
|
23
|
+
pre-commit = "^4.2.0"
|
|
24
|
+
glaip-sdk = ">=0.6.2"
|
|
25
|
+
ruff = "^0.14.0"
|
|
26
|
+
|
|
27
|
+
aip-agents-binary = "^0.4.8"
|
|
28
|
+
gllm-plugin-binary = "^0.0.7"
|
|
29
|
+
pyyaml = "^6.0.3"
|
|
30
|
+
email-validator = "^2.3.0"
|
|
31
|
+
|
|
32
|
+
[tool.poetry.group.dev.dependencies]
|
|
33
|
+
coverage = "^7.11.0"
|
|
34
|
+
pytest = "^8.4.2"
|
|
35
|
+
pytest-xdist = "^3.8.0"
|
|
36
|
+
black = "^25.1.0"
|
|
37
|
+
flake8 = "^7.3.0"
|
|
38
|
+
faker = "^37.12.0"
|
|
39
|
+
pytest-asyncio = "^1.2.0"
|
|
40
|
+
|
|
41
|
+
[[tool.poetry.source]]
|
|
42
|
+
name = "gen-ai-internal"
|
|
43
|
+
url = "https://asia-southeast2-python.pkg.dev/gdp-labs/gen-ai-internal/simple/"
|
|
44
|
+
priority = "supplemental"
|
|
45
|
+
|
|
46
|
+
[build-system]
|
|
47
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
48
|
+
build-backend = "poetry.core.masonry.api"
|
|
49
|
+
|
|
50
|
+
[tool.pytest.ini_options]
|
|
51
|
+
norecursedirs = ["docker/*", "pgdata"]
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 120
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint]
|
|
57
|
+
ignore = ["B008", "C901", "E266"]
|
|
58
|
+
select = ["B", "B9", "C", "D", "E", "F", "I", "PL", "W"]
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint.per-file-ignores]
|
|
61
|
+
"tests/*" = ["D", "PLR", "ARG"]
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint.pydocstyle]
|
|
64
|
+
convention = "google"
|