holix-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.
- holix_sdk/__init__.py +26 -0
- holix_sdk/agent.py +62 -0
- holix_sdk/agent_runtime.py +39 -0
- holix_sdk/commands.py +5 -0
- holix_sdk/extension.py +90 -0
- holix_sdk/host.py +32 -0
- holix_sdk/i18n.py +5 -0
- holix_sdk/models.py +25 -0
- holix_sdk/paths.py +5 -0
- holix_sdk/profile.py +5 -0
- holix_sdk/security.py +27 -0
- holix_sdk/version.py +4 -0
- holix_sdk-0.1.0.dist-info/METADATA +94 -0
- holix_sdk-0.1.0.dist-info/RECORD +16 -0
- holix_sdk-0.1.0.dist-info/WHEEL +4 -0
- holix_sdk-0.1.0.dist-info/licenses/LICENSE +21 -0
holix_sdk/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Holix SDK — stable public API for extension authors."""
|
|
2
|
+
|
|
3
|
+
from holix_sdk.extension import (
|
|
4
|
+
CAPABILITY_AGENT,
|
|
5
|
+
CAPABILITY_CLI,
|
|
6
|
+
CAPABILITY_HTTP,
|
|
7
|
+
CAPABILITY_SIDECAR,
|
|
8
|
+
ExtensionBase,
|
|
9
|
+
ExtensionContext,
|
|
10
|
+
ExtensionInfo,
|
|
11
|
+
HolixExtension,
|
|
12
|
+
)
|
|
13
|
+
from holix_sdk.version import __api_version__, __version__
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"__api_version__",
|
|
17
|
+
"__version__",
|
|
18
|
+
"CAPABILITY_AGENT",
|
|
19
|
+
"CAPABILITY_CLI",
|
|
20
|
+
"CAPABILITY_HTTP",
|
|
21
|
+
"CAPABILITY_SIDECAR",
|
|
22
|
+
"ExtensionBase",
|
|
23
|
+
"ExtensionContext",
|
|
24
|
+
"ExtensionInfo",
|
|
25
|
+
"HolixExtension",
|
|
26
|
+
]
|
holix_sdk/agent.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Agent extension protocol — source of truth for Holix agent extensions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Protocol, runtime_checkable
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True, slots=True)
|
|
10
|
+
class SlashCommandSpec:
|
|
11
|
+
"""Slash command contributed by an agent extension."""
|
|
12
|
+
|
|
13
|
+
command: str
|
|
14
|
+
description: str
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True, slots=True)
|
|
18
|
+
class AgentExtensionContext:
|
|
19
|
+
"""Context passed to agent extensions during registration."""
|
|
20
|
+
|
|
21
|
+
profile_name: str
|
|
22
|
+
holix_version: str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@runtime_checkable
|
|
26
|
+
class AgentExtension(Protocol):
|
|
27
|
+
"""Extension that augments the Holix agent runtime."""
|
|
28
|
+
|
|
29
|
+
name: str
|
|
30
|
+
version: str
|
|
31
|
+
requires_holix: str
|
|
32
|
+
permissions: frozenset[str]
|
|
33
|
+
|
|
34
|
+
def register_tools(self, registry: Any, agent: Any) -> None:
|
|
35
|
+
"""Register additional tools on the agent ToolRegistry."""
|
|
36
|
+
...
|
|
37
|
+
|
|
38
|
+
def register_slash_commands(self, commands: list[SlashCommandSpec]) -> None:
|
|
39
|
+
"""Append slash commands (mutates the provided list)."""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def augment_system_prompt(self, profile: str) -> str | None:
|
|
43
|
+
"""Optional extra system prompt fragment for this profile."""
|
|
44
|
+
...
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class AgentExtensionBase:
|
|
48
|
+
"""Convenience base with defaults."""
|
|
49
|
+
|
|
50
|
+
name: str = ""
|
|
51
|
+
version: str = "0.0.0"
|
|
52
|
+
requires_holix: str = ">=0.1.0"
|
|
53
|
+
permissions: frozenset[str] = frozenset()
|
|
54
|
+
|
|
55
|
+
def register_tools(self, registry: Any, agent: Any) -> None:
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
def register_slash_commands(self, commands: list[SlashCommandSpec]) -> None:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
def augment_system_prompt(self, profile: str) -> str | None:
|
|
62
|
+
return None
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Agent runtime types for host extensions."""
|
|
2
|
+
|
|
3
|
+
from core.agent import HolixAgent
|
|
4
|
+
from core.agent_events import (
|
|
5
|
+
AgentEvent,
|
|
6
|
+
AgentEventBus,
|
|
7
|
+
AssistantDeltaEvent,
|
|
8
|
+
ErrorEvent,
|
|
9
|
+
EventType,
|
|
10
|
+
FinalResponseEvent,
|
|
11
|
+
ThinkingEvent,
|
|
12
|
+
ToolCallErrorEvent,
|
|
13
|
+
ToolCallResultEvent,
|
|
14
|
+
ToolCallStartEvent,
|
|
15
|
+
)
|
|
16
|
+
from core.plan_review.review_events import PlanReviewRequestEvent
|
|
17
|
+
from core.security.confirmation_events import ConfirmationRequestEvent, ConfirmationResponseEvent
|
|
18
|
+
from core.subagents.interaction_events import SubAgentQuestionEvent
|
|
19
|
+
from core.tools.file_diff import DIFF_SEPARATOR, format_write_file_result
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"DIFF_SEPARATOR",
|
|
23
|
+
"AgentEvent",
|
|
24
|
+
"AgentEventBus",
|
|
25
|
+
"AssistantDeltaEvent",
|
|
26
|
+
"ConfirmationRequestEvent",
|
|
27
|
+
"ConfirmationResponseEvent",
|
|
28
|
+
"ErrorEvent",
|
|
29
|
+
"EventType",
|
|
30
|
+
"FinalResponseEvent",
|
|
31
|
+
"HolixAgent",
|
|
32
|
+
"PlanReviewRequestEvent",
|
|
33
|
+
"SubAgentQuestionEvent",
|
|
34
|
+
"ThinkingEvent",
|
|
35
|
+
"ToolCallErrorEvent",
|
|
36
|
+
"ToolCallResultEvent",
|
|
37
|
+
"ToolCallStartEvent",
|
|
38
|
+
"format_write_file_result",
|
|
39
|
+
]
|
holix_sdk/commands.py
ADDED
holix_sdk/extension.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Extension protocol — source of truth for Holix host extensions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Protocol, runtime_checkable
|
|
7
|
+
|
|
8
|
+
CAPABILITY_CLI = "cli"
|
|
9
|
+
CAPABILITY_HTTP = "http"
|
|
10
|
+
CAPABILITY_SIDECAR = "sidecar"
|
|
11
|
+
CAPABILITY_AGENT = "agent"
|
|
12
|
+
|
|
13
|
+
ALL_CAPABILITIES = frozenset(
|
|
14
|
+
{CAPABILITY_CLI, CAPABILITY_HTTP, CAPABILITY_SIDECAR, CAPABILITY_AGENT}
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True, slots=True)
|
|
19
|
+
class ExtensionContext:
|
|
20
|
+
"""Runtime context passed to extensions on startup."""
|
|
21
|
+
|
|
22
|
+
holix_version: str
|
|
23
|
+
data_dir: str
|
|
24
|
+
profile: str | None = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True, slots=True)
|
|
28
|
+
class ExtensionInfo:
|
|
29
|
+
"""Metadata for ``holix extensions list``."""
|
|
30
|
+
|
|
31
|
+
name: str
|
|
32
|
+
version: str
|
|
33
|
+
requires_holix: str
|
|
34
|
+
description: str
|
|
35
|
+
capabilities: frozenset[str]
|
|
36
|
+
permissions: frozenset[str]
|
|
37
|
+
package: str
|
|
38
|
+
entry_point: str
|
|
39
|
+
manifest_id: str | None = None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@runtime_checkable
|
|
43
|
+
class HolixExtension(Protocol):
|
|
44
|
+
"""Optional package that plugs into Holix CLI, gateway, and/or agent runtime."""
|
|
45
|
+
|
|
46
|
+
name: str
|
|
47
|
+
version: str
|
|
48
|
+
requires_holix: str
|
|
49
|
+
description: str
|
|
50
|
+
capabilities: frozenset[str]
|
|
51
|
+
permissions: frozenset[str]
|
|
52
|
+
|
|
53
|
+
def register_cli(self, app: Any) -> None:
|
|
54
|
+
"""Attach Typer subcommands to the root ``holix`` CLI."""
|
|
55
|
+
...
|
|
56
|
+
|
|
57
|
+
def mount_gateway(self, app: Any) -> None:
|
|
58
|
+
"""Attach FastAPI routes to the API gateway (no-op if disabled)."""
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
def on_startup(self, ctx: ExtensionContext) -> None:
|
|
62
|
+
"""Called once after extension discovery (CLI or gateway boot)."""
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
def on_shutdown(self) -> None:
|
|
66
|
+
"""Called on process exit (best-effort)."""
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ExtensionBase:
|
|
71
|
+
"""Convenience base with defaults — subclass for new extensions."""
|
|
72
|
+
|
|
73
|
+
name: str = ""
|
|
74
|
+
version: str = "0.0.0"
|
|
75
|
+
requires_holix: str = ">=0.1.0"
|
|
76
|
+
description: str = ""
|
|
77
|
+
capabilities: frozenset[str] = frozenset()
|
|
78
|
+
permissions: frozenset[str] = frozenset()
|
|
79
|
+
|
|
80
|
+
def register_cli(self, app: Any) -> None:
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
def mount_gateway(self, app: Any) -> None:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def on_startup(self, ctx: ExtensionContext) -> None:
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
def on_shutdown(self) -> None:
|
|
90
|
+
return None
|
holix_sdk/host.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Host bridge utilities — requires Holix installed."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def __getattr__(name: str):
|
|
7
|
+
"""Lazy import from Holix CLI (runtime dependency)."""
|
|
8
|
+
if name in {
|
|
9
|
+
"AgentCommands",
|
|
10
|
+
"TranscriptStore",
|
|
11
|
+
"all_slash_commands",
|
|
12
|
+
"content_to_plain_text",
|
|
13
|
+
"is_slash_command",
|
|
14
|
+
"normalize_slash_input",
|
|
15
|
+
"slash_commands_for_locale",
|
|
16
|
+
}:
|
|
17
|
+
from cli.shared.commands.agent_commands import AgentCommands
|
|
18
|
+
from cli.shared.commands.registry import all_slash_commands, slash_commands_for_locale
|
|
19
|
+
from cli.shared.rich_text import content_to_plain_text
|
|
20
|
+
from cli.shared.slash_input import is_slash_command, normalize_slash_input
|
|
21
|
+
from cli.tui.shared.transcript_store import TranscriptStore
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
"AgentCommands": AgentCommands,
|
|
25
|
+
"TranscriptStore": TranscriptStore,
|
|
26
|
+
"all_slash_commands": all_slash_commands,
|
|
27
|
+
"content_to_plain_text": content_to_plain_text,
|
|
28
|
+
"is_slash_command": is_slash_command,
|
|
29
|
+
"normalize_slash_input": normalize_slash_input,
|
|
30
|
+
"slash_commands_for_locale": slash_commands_for_locale,
|
|
31
|
+
}[name]
|
|
32
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
holix_sdk/i18n.py
ADDED
holix_sdk/models.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Runtime model selection menus."""
|
|
2
|
+
|
|
3
|
+
from core.models.menu import (
|
|
4
|
+
ModelChoice,
|
|
5
|
+
ModelsMenuState,
|
|
6
|
+
ProviderMenu,
|
|
7
|
+
apply_model_choice_sync,
|
|
8
|
+
build_models_menu,
|
|
9
|
+
choice_for_provider_model,
|
|
10
|
+
current_model_label,
|
|
11
|
+
is_slot_active,
|
|
12
|
+
resolve_model_config,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"ModelChoice",
|
|
17
|
+
"ModelsMenuState",
|
|
18
|
+
"ProviderMenu",
|
|
19
|
+
"apply_model_choice_sync",
|
|
20
|
+
"build_models_menu",
|
|
21
|
+
"choice_for_provider_model",
|
|
22
|
+
"current_model_label",
|
|
23
|
+
"is_slot_active",
|
|
24
|
+
"resolve_model_config",
|
|
25
|
+
]
|
holix_sdk/paths.py
ADDED
holix_sdk/profile.py
ADDED
holix_sdk/security.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Security and approval helpers."""
|
|
2
|
+
|
|
3
|
+
from cli.tui.web_security import (
|
|
4
|
+
WebTuiSecurityError,
|
|
5
|
+
WebTuiSecurityPolicy,
|
|
6
|
+
append_query_token,
|
|
7
|
+
build_web_tui_policy,
|
|
8
|
+
generate_web_token,
|
|
9
|
+
is_loopback_host,
|
|
10
|
+
token_valid,
|
|
11
|
+
)
|
|
12
|
+
from core.plan_review.review_guard import PlanReviewChoice, get_plan_review_guard
|
|
13
|
+
from core.security.confirmation import ConfirmationChoice, get_action_guard
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"ConfirmationChoice",
|
|
17
|
+
"PlanReviewChoice",
|
|
18
|
+
"WebTuiSecurityError",
|
|
19
|
+
"WebTuiSecurityPolicy",
|
|
20
|
+
"append_query_token",
|
|
21
|
+
"build_web_tui_policy",
|
|
22
|
+
"generate_web_token",
|
|
23
|
+
"get_action_guard",
|
|
24
|
+
"get_plan_review_guard",
|
|
25
|
+
"is_loopback_host",
|
|
26
|
+
"token_valid",
|
|
27
|
+
]
|
holix_sdk/version.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: holix-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Stable public API for Holix extensions and host integrations
|
|
5
|
+
Project-URL: Homepage, https://holix-agent.ru
|
|
6
|
+
Project-URL: Repository, https://github.com/javded-itres/holix-sdk
|
|
7
|
+
Project-URL: Documentation, https://github.com/javded-itres/holix-sdk/blob/main/docs/en/EXTENSIONS.md
|
|
8
|
+
Project-URL: Issues, https://github.com/javded-itres/holix-sdk/issues
|
|
9
|
+
Author: Pavel Lukyanov
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agent,extensions,holix,sdk
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: holix>=0.1.21
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# holix-sdk
|
|
27
|
+
|
|
28
|
+
[](https://github.com/javded-itres/holix-sdk/actions/workflows/ci.yml)
|
|
29
|
+
|
|
30
|
+
**Separate installable package** — stable public API for [Holix](https://github.com/javded-itres/Holix) extension authors.
|
|
31
|
+
|
|
32
|
+
Holix core (`core.*`, `cli.*`) is internal. Extension packages import **only** `holix_sdk`.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install holix-sdk Holix
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Requires [Holix](https://pypi.org/project/Holix/) `>=0.1.21` on PyPI.
|
|
41
|
+
|
|
42
|
+
## API version
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from holix_sdk import __api_version__
|
|
46
|
+
# Currently: 1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Breaking changes to the extension API happen only in major releases of `holix-sdk`.
|
|
50
|
+
|
|
51
|
+
## Quick example
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from holix_sdk import ExtensionBase, CAPABILITY_CLI
|
|
55
|
+
from holix_sdk.agent import AgentExtensionBase, SlashCommandSpec
|
|
56
|
+
from holix_sdk.host import AgentCommands
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Documentation
|
|
60
|
+
|
|
61
|
+
| Language | Guide |
|
|
62
|
+
|----------|-------|
|
|
63
|
+
| English | [docs/en/EXTENSIONS.md](docs/en/EXTENSIONS.md) |
|
|
64
|
+
| Russian | [docs/ru/EXTENSIONS.md](docs/ru/EXTENSIONS.md) |
|
|
65
|
+
|
|
66
|
+
## Development
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone git@github.com:javded-itres/holix-sdk.git
|
|
70
|
+
cd holix-sdk
|
|
71
|
+
uv sync --group dev
|
|
72
|
+
uv run pytest -q
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Publish
|
|
76
|
+
|
|
77
|
+
Automated via GitHub Actions on tag `v*` — see [docs/PYPI.md](docs/PYPI.md).
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# bump pyproject.toml + holix_sdk/version.py, then:
|
|
81
|
+
git tag v0.1.0 && git push origin v0.1.0
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Local check:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
uv build && uv run twine check dist/*
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
PyPI package name: `holix-sdk`.
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
holix_sdk/__init__.py,sha256=76ms8k8enevh3kqkYWi0H1848LUKk16qzAs0jUXHL3Q,563
|
|
2
|
+
holix_sdk/agent.py,sha256=wgD-zZ48Tr7aDBfgum-1m49B2-eLUOH87tLJ0ym8A0U,1665
|
|
3
|
+
holix_sdk/agent_runtime.py,sha256=cnmhri4VihjtR-IZGFix6BogT24gPHr6ZJlE_GS-RUY,1066
|
|
4
|
+
holix_sdk/commands.py,sha256=fkuv-93JxDTZVuMaymebkrnmfmD1NBHg9yKWPvAGjQ0,187
|
|
5
|
+
holix_sdk/extension.py,sha256=tY8OTci7DDwXtqNq9ooOwCOPhRrODcNgbtXwuw0EGfU,2282
|
|
6
|
+
holix_sdk/host.py,sha256=K2I_aMwYuTzzxFDZRetrh4xBjfEpWW9AHFq1YJFW8yM,1290
|
|
7
|
+
holix_sdk/i18n.py,sha256=XT87W_2_fMyC-wdyJbqTHk1yfmLItKm3Atmo6MXXu-4,171
|
|
8
|
+
holix_sdk/models.py,sha256=sPXpfQQSN5FP2Nlq9jN28uzKw6l45oaUU43m-mB6tC0,523
|
|
9
|
+
holix_sdk/paths.py,sha256=wkXUf4uBCAHfQ6cw1I41dRBiaQG6RsDfJ1EdLbBCYLk,159
|
|
10
|
+
holix_sdk/profile.py,sha256=L5VJ_TB3VgxFQoPZZ_pQecoJV423pquj63GrNO9x_F4,122
|
|
11
|
+
holix_sdk/security.py,sha256=QmBC0enARSyib8EF_rIId55g_johSYeL9i373Qw1xj0,692
|
|
12
|
+
holix_sdk/version.py,sha256=tbfjcpEYGPo4UV746bpUQcC7As-fo4e6JBc4qfzztf4,119
|
|
13
|
+
holix_sdk-0.1.0.dist-info/METADATA,sha256=V_ntRQd5cX3GbK2Cf2WjdsQRV4p6ZupS5N7zPrXi2fw,2582
|
|
14
|
+
holix_sdk-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
15
|
+
holix_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=dXfm47JSjiyn_TZ2tj2V_aT2svtkzByqbN9uqu9pIl4,1074
|
|
16
|
+
holix_sdk-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Holix Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|