kodelet-sdk 0.1.0__py3-none-any.whl
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.
- kodelet_sdk/__init__.py +66 -0
- kodelet_sdk/_utils.py +64 -0
- kodelet_sdk/api.py +684 -0
- kodelet_sdk/context.py +554 -0
- kodelet_sdk/py.typed +0 -0
- kodelet_sdk/runtime.py +246 -0
- kodelet_sdk/schemas.py +57 -0
- kodelet_sdk/template.py +30 -0
- kodelet_sdk/test_harness.py +95 -0
- kodelet_sdk-0.1.0.dist-info/METADATA +134 -0
- kodelet_sdk-0.1.0.dist-info/RECORD +13 -0
- kodelet_sdk-0.1.0.dist-info/WHEEL +4 -0
- kodelet_sdk-0.1.0.dist-info/licenses/LICENSE +21 -0
kodelet_sdk/__init__.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import jinja2 as jinja2
|
|
4
|
+
import pydantic as pydantic
|
|
5
|
+
from jinja2 import Environment, Template
|
|
6
|
+
from pydantic import BaseModel, Field, TypeAdapter
|
|
7
|
+
|
|
8
|
+
from .api import Extension, create_extension_host, define_extension, on
|
|
9
|
+
from .context import (
|
|
10
|
+
CommandContext,
|
|
11
|
+
EnvContext,
|
|
12
|
+
EventContext,
|
|
13
|
+
ExecResult,
|
|
14
|
+
FileSystemContext,
|
|
15
|
+
HostRPCClient,
|
|
16
|
+
LogContext,
|
|
17
|
+
PathContext,
|
|
18
|
+
ProcessContext,
|
|
19
|
+
SharedContext,
|
|
20
|
+
StorageContext,
|
|
21
|
+
ToolContext,
|
|
22
|
+
UIContext,
|
|
23
|
+
set_active_host_rpc_client,
|
|
24
|
+
)
|
|
25
|
+
from .runtime import run_extension
|
|
26
|
+
from .template import render_template
|
|
27
|
+
from .test_harness import ExtensionTestHarness, create_test_harness
|
|
28
|
+
|
|
29
|
+
ExtensionHost = Extension
|
|
30
|
+
Pydantic = pydantic
|
|
31
|
+
Jinja2 = jinja2
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"BaseModel",
|
|
35
|
+
"CommandContext",
|
|
36
|
+
"EnvContext",
|
|
37
|
+
"Environment",
|
|
38
|
+
"EventContext",
|
|
39
|
+
"ExecResult",
|
|
40
|
+
"Extension",
|
|
41
|
+
"ExtensionHost",
|
|
42
|
+
"ExtensionTestHarness",
|
|
43
|
+
"Field",
|
|
44
|
+
"FileSystemContext",
|
|
45
|
+
"HostRPCClient",
|
|
46
|
+
"Jinja2",
|
|
47
|
+
"LogContext",
|
|
48
|
+
"PathContext",
|
|
49
|
+
"ProcessContext",
|
|
50
|
+
"Pydantic",
|
|
51
|
+
"SharedContext",
|
|
52
|
+
"StorageContext",
|
|
53
|
+
"Template",
|
|
54
|
+
"ToolContext",
|
|
55
|
+
"TypeAdapter",
|
|
56
|
+
"UIContext",
|
|
57
|
+
"create_extension_host",
|
|
58
|
+
"create_test_harness",
|
|
59
|
+
"define_extension",
|
|
60
|
+
"jinja2",
|
|
61
|
+
"on",
|
|
62
|
+
"pydantic",
|
|
63
|
+
"render_template",
|
|
64
|
+
"run_extension",
|
|
65
|
+
"set_active_host_rpc_client",
|
|
66
|
+
]
|
kodelet_sdk/_utils.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
import json
|
|
5
|
+
from collections.abc import Awaitable, Mapping
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def maybe_await(value: Any) -> Any:
|
|
12
|
+
if inspect.isawaitable(value):
|
|
13
|
+
return await value
|
|
14
|
+
return value
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def to_plain(value: Any) -> Any:
|
|
18
|
+
if isinstance(value, BaseModel):
|
|
19
|
+
return value.model_dump(mode="json", exclude_none=True)
|
|
20
|
+
if isinstance(value, Mapping):
|
|
21
|
+
return {str(key): to_plain(item) for key, item in value.items() if item is not None}
|
|
22
|
+
if isinstance(value, list | tuple):
|
|
23
|
+
return [to_plain(item) for item in value]
|
|
24
|
+
return value
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def json_clone(value: Any) -> Any:
|
|
28
|
+
return json.loads(json.dumps(to_plain(value)))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def normalize_command_name(name: str) -> str:
|
|
32
|
+
return name.strip().lstrip("/")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def optional_timeout(timeout_in_sec: float | None) -> dict[str, float]:
|
|
36
|
+
if timeout_in_sec is None:
|
|
37
|
+
return {}
|
|
38
|
+
return {"timeoutInSec": timeout_in_sec}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def merge_timeout_in_sec(current: float | None, next_value: float | None) -> float | None:
|
|
42
|
+
if current == 0 or next_value == 0:
|
|
43
|
+
return 0
|
|
44
|
+
if current is None:
|
|
45
|
+
return next_value
|
|
46
|
+
if next_value is None:
|
|
47
|
+
return current
|
|
48
|
+
return max(current, next_value)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class AttrDict(dict[str, Any]):
|
|
52
|
+
"""Dictionary with attribute access for ergonomic event payload handling."""
|
|
53
|
+
|
|
54
|
+
def __getattr__(self, name: str) -> Any:
|
|
55
|
+
try:
|
|
56
|
+
return self[name]
|
|
57
|
+
except KeyError as exc:
|
|
58
|
+
raise AttributeError(name) from exc
|
|
59
|
+
|
|
60
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
61
|
+
self[name] = value
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
ConvertableAwaitable = Awaitable[Any] | Any
|