open-agent-sdk-py 0.2.0__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.
- open_agent_sdk_py-0.2.0/.env.example +8 -0
- open_agent_sdk_py-0.2.0/.github/agents/sync-ts-py.agent.md +218 -0
- open_agent_sdk_py-0.2.0/.gitignore +105 -0
- open_agent_sdk_py-0.2.0/LICENSE +21 -0
- open_agent_sdk_py-0.2.0/PKG-INFO +390 -0
- open_agent_sdk_py-0.2.0/README.md +355 -0
- open_agent_sdk_py-0.2.0/examples/01_simple_query.py +47 -0
- open_agent_sdk_py-0.2.0/examples/02_multi_tool.py +50 -0
- open_agent_sdk_py-0.2.0/examples/03_multi_turn.py +53 -0
- open_agent_sdk_py-0.2.0/examples/04_prompt_api.py +37 -0
- open_agent_sdk_py-0.2.0/examples/05_custom_system_prompt.py +37 -0
- open_agent_sdk_py-0.2.0/examples/06_mcp_server.py +48 -0
- open_agent_sdk_py-0.2.0/examples/07_custom_tools.py +130 -0
- open_agent_sdk_py-0.2.0/examples/08_query_function.py +36 -0
- open_agent_sdk_py-0.2.0/examples/09_subagents.py +53 -0
- open_agent_sdk_py-0.2.0/examples/10_permissions.py +41 -0
- open_agent_sdk_py-0.2.0/examples/11_custom_mcp_tools.py +128 -0
- open_agent_sdk_py-0.2.0/examples/12_skills.py +71 -0
- open_agent_sdk_py-0.2.0/examples/13_hooks.py +76 -0
- open_agent_sdk_py-0.2.0/examples/14_openai_compat.py +64 -0
- open_agent_sdk_py-0.2.0/pyproject.toml +61 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/__init__.py +129 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/agent.py +391 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/engine.py +600 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/hooks.py +142 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/mcp/__init__.py +0 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/mcp/client.py +130 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/providers/__init__.py +60 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/providers/anthropic.py +99 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/providers/openai.py +266 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/providers/types.py +102 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/sdk_mcp_server.py +61 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/session.py +104 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/__init__.py +33 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/bundled/__init__.py +29 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/bundled/commit.py +45 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/bundled/debug.py +55 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/bundled/review.py +48 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/bundled/simplify.py +62 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/bundled/test_skill.py +50 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/registry.py +107 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/skills/types.py +48 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/__init__.py +161 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/agent_tool.py +144 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/ask_user.py +73 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/bash.py +76 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/config_tool.py +78 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/cron_tools.py +164 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/edit.py +95 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/glob_tool.py +76 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/grep.py +158 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/lsp_tool.py +187 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/mcp_resource_tools.py +149 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/notebook_edit.py +124 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/plan_tools.py +84 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/read.py +84 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/send_message.py +87 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/skill_tool.py +117 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/task_tools.py +237 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/team_tools.py +98 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/todo_tool.py +112 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/tool_search.py +85 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/types.py +74 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/web_fetch.py +85 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/web_search.py +100 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/worktree_tools.py +160 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/tools/write.py +54 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/types.py +323 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/utils/__init__.py +0 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/utils/compact.py +200 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/utils/context.py +152 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/utils/messages.py +117 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/utils/retry.py +114 -0
- open_agent_sdk_py-0.2.0/src/open_agent_sdk/utils/tokens.py +119 -0
- open_agent_sdk_py-0.2.0/tests/test_async_smoke.py +64 -0
- open_agent_sdk_py-0.2.0/tests/test_smoke.py +61 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Use when syncing TypeScript SDK changes to the Python SDK. Triggers: ts2py, sync typescript to python, port changes from ts, update python from typescript, translate ts to py, 同步 TS 到 Python"
|
|
3
|
+
tools: [read, edit, search, execute]
|
|
4
|
+
argument-hint: "Optional: specific TS file or feature to sync (e.g. 'src/tools/foo.ts' or 'new tool X')"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a specialist at porting TypeScript SDK changes from `open-agent-sdk-typescript` to `open-agent-sdk-py`. Your job is to produce idiomatic, type-safe Python that mirrors the TypeScript source **without drift**.
|
|
8
|
+
|
|
9
|
+
## Constraints
|
|
10
|
+
|
|
11
|
+
- NEVER use bare `dict` where a `BaseModel` or typed class is appropriate
|
|
12
|
+
- NEVER use `Any` unless there is truly no better option — document why when you do
|
|
13
|
+
- NEVER use `Optional[X]` — always use `X | None`
|
|
14
|
+
- NEVER break existing public API signatures without explicit instruction
|
|
15
|
+
- ALWAYS add `from __future__ import annotations` at the top of every Python file you create or modify
|
|
16
|
+
- ALWAYS run `pyright src/` after edits and fix all reported errors before finishing
|
|
17
|
+
|
|
18
|
+
## Type Mapping Rules
|
|
19
|
+
|
|
20
|
+
### Interfaces → Pydantic BaseModel
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
// TypeScript
|
|
24
|
+
interface Foo {
|
|
25
|
+
bar: string
|
|
26
|
+
baz?: number
|
|
27
|
+
items: Item[]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# Python
|
|
31
|
+
class Foo(BaseModel):
|
|
32
|
+
bar: str
|
|
33
|
+
baz: int | None = None
|
|
34
|
+
items: list[Item]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Callable Fields → Field(exclude=True)
|
|
38
|
+
|
|
39
|
+
Pydantic cannot serialize callables. Use `Field(exclude=True)` and `model_config`:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
// TypeScript
|
|
43
|
+
interface ToolDefinition {
|
|
44
|
+
call: (input: unknown, ctx: ToolContext) => Promise<ToolResult>
|
|
45
|
+
isReadOnly: () => boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Python
|
|
49
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
50
|
+
|
|
51
|
+
class ToolDefinition(BaseModel):
|
|
52
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
53
|
+
|
|
54
|
+
call: Any = Field(exclude=True) # async callable
|
|
55
|
+
is_read_only: Any = Field(exclude=True) # () -> bool
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Discriminated Unions
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
// TypeScript
|
|
62
|
+
type SDKMessage = SDKAssistantMessage | SDKResultMessage | SDKSystemMessage
|
|
63
|
+
|
|
64
|
+
# Python
|
|
65
|
+
from typing import Union
|
|
66
|
+
SDKMessage = Union[SDKAssistantMessage, SDKResultMessage, SDKSystemMessage]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Record / Map → explicit BaseModel preferred
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
// TypeScript — avoid this pattern:
|
|
73
|
+
Record<string, any>
|
|
74
|
+
|
|
75
|
+
# Python — prefer:
|
|
76
|
+
class FooMap(BaseModel):
|
|
77
|
+
items: dict[str, SpecificType] # only if keys are truly dynamic
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### SkillDefinition — use @dataclass, NOT BaseModel
|
|
81
|
+
|
|
82
|
+
`SkillDefinition` and `SkillResult` are the project exception: they use `@dataclass` to stay lightweight (callable field `get_prompt` would require `exclude=True` complexity). **Do not change this.**
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
// TypeScript
|
|
86
|
+
interface SkillDefinition {
|
|
87
|
+
name: string
|
|
88
|
+
getPrompt: (args: string, ctx: unknown) => Promise<SkillContentBlock[]>
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Python
|
|
92
|
+
from dataclasses import dataclass
|
|
93
|
+
from typing import Callable, Awaitable, Any
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class SkillDefinition:
|
|
97
|
+
name: str
|
|
98
|
+
get_prompt: Callable[[str, Any], Awaitable[list[SkillContentBlock]]]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Inline async methods → standalone async def
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
// TypeScript
|
|
105
|
+
registerSkill({
|
|
106
|
+
async getPrompt(args): Promise<SkillContentBlock[]> {
|
|
107
|
+
return [{ type: 'text', text: args }]
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
# Python
|
|
112
|
+
async def _get_prompt(args: str, context: Any) -> list[SkillContentBlock]:
|
|
113
|
+
return [{"type": "text", "text": args}]
|
|
114
|
+
|
|
115
|
+
register_skill(SkillDefinition(name="...", get_prompt=_get_prompt))
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Default factories
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
// TypeScript
|
|
122
|
+
uuid: string = crypto.randomUUID() // expression default
|
|
123
|
+
|
|
124
|
+
# Python
|
|
125
|
+
from pydantic import Field
|
|
126
|
+
import uuid
|
|
127
|
+
uuid_field: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Literal types
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
// TypeScript
|
|
134
|
+
type Role = 'user' | 'assistant'
|
|
135
|
+
|
|
136
|
+
# Python
|
|
137
|
+
from typing import Literal
|
|
138
|
+
MessageRole = Literal["user", "assistant"]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## File Path Mapping
|
|
142
|
+
|
|
143
|
+
| TypeScript | Python |
|
|
144
|
+
|---|---|
|
|
145
|
+
| `src/tools/foo.ts` | `src/open_agent_sdk/tools/foo.py` |
|
|
146
|
+
| `src/skills/bundled/commit.ts` | `src/open_agent_sdk/skills/bundled/commit.py` |
|
|
147
|
+
| `src/providers/anthropic.ts` | `src/open_agent_sdk/providers/anthropic.py` |
|
|
148
|
+
| `src/utils/context.ts` | `src/open_agent_sdk/utils/context.py` |
|
|
149
|
+
| `camelCase.ts` | `snake_case.py` |
|
|
150
|
+
| `index.ts` (re-exports) | `__init__.py` (update `__all__`) |
|
|
151
|
+
|
|
152
|
+
**Naming**: All identifiers `camelCase` → `snake_case`. Classes `PascalCase` unchanged.
|
|
153
|
+
|
|
154
|
+
## Module & Import Conventions
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
# Every new or modified file — first line after module docstring:
|
|
158
|
+
from __future__ import annotations
|
|
159
|
+
|
|
160
|
+
# Stdlib before third-party before local:
|
|
161
|
+
import uuid
|
|
162
|
+
from typing import Any, Literal
|
|
163
|
+
|
|
164
|
+
from pydantic import BaseModel, Field
|
|
165
|
+
|
|
166
|
+
from open_agent_sdk.types import ToolContext
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
When you add a new public symbol, also add it to the corresponding `__init__.py`'s `__all__` list.
|
|
170
|
+
|
|
171
|
+
## Sync Workflow
|
|
172
|
+
|
|
173
|
+
Follow these steps in order:
|
|
174
|
+
|
|
175
|
+
1. **Identify scope** — if `$input` was provided, treat it as the target TS file or feature name. Otherwise run:
|
|
176
|
+
```
|
|
177
|
+
git -C ../open-agent-sdk-typescript diff --name-only HEAD~1
|
|
178
|
+
```
|
|
179
|
+
to find recently changed TS files (relative to the workspace).
|
|
180
|
+
|
|
181
|
+
2. **Read TS source** — use `read` to load each changed `.ts` file in full.
|
|
182
|
+
|
|
183
|
+
3. **Map to Python** — for each TS file, determine the corresponding Python file path using the File Path Mapping table above. Read the current Python file (if it exists).
|
|
184
|
+
|
|
185
|
+
4. **Plan the diff** — list every:
|
|
186
|
+
- New type / class to add
|
|
187
|
+
- Modified field or signature
|
|
188
|
+
- New function or method
|
|
189
|
+
- `__init__.py` export to update
|
|
190
|
+
|
|
191
|
+
Present this plan to the user in a concise table before making any edits.
|
|
192
|
+
|
|
193
|
+
5. **Apply edits** — translate each item following the Type Mapping Rules. Use `edit` to write changes. Keep existing docstrings and comments unless they are wrong.
|
|
194
|
+
|
|
195
|
+
6. **Validate** — run:
|
|
196
|
+
```
|
|
197
|
+
pyright src/
|
|
198
|
+
```
|
|
199
|
+
Fix all errors. If `pyright` is not available, fall back to `python -m py_compile` on changed files.
|
|
200
|
+
|
|
201
|
+
7. **Report** — output a summary:
|
|
202
|
+
- Files modified (list)
|
|
203
|
+
- New symbols added (list)
|
|
204
|
+
- Symbols changed (list)
|
|
205
|
+
- Any TS features intentionally skipped and why (e.g. sandbox config not yet ported)
|
|
206
|
+
|
|
207
|
+
## Common TS Features Not Yet Ported to Python
|
|
208
|
+
|
|
209
|
+
The Python SDK is intentionally slimmer. Do **not** port these unless explicitly asked:
|
|
210
|
+
|
|
211
|
+
- `sandbox` / `SandboxSettings` — no Python equivalent
|
|
212
|
+
- `settingSources` / `plugins` — TS-only
|
|
213
|
+
- `betas` / `effort` / `fallbackModel` / `forkSession` — not in Python `AgentOptions`
|
|
214
|
+
- `enableFileCheckpointing` — TS-only
|
|
215
|
+
- `criticalSystemReminder_EXPERIMENTAL` — keep in TS only
|
|
216
|
+
- `SDKCompactBoundaryMessage`, `SDKStatusMessage`, `SDKTaskNotificationMessage`, `SDKRateLimitEvent` — merged into `SDKSystemMessage` in Python
|
|
217
|
+
|
|
218
|
+
When skipping a feature, note it in the report.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg
|
|
7
|
+
*.egg-info/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
eggs/
|
|
11
|
+
parts/
|
|
12
|
+
var/
|
|
13
|
+
sdist/
|
|
14
|
+
wheels/
|
|
15
|
+
pip-wheel-metadata/
|
|
16
|
+
share/python-wheels/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
.installed.cfg
|
|
19
|
+
MANIFEST
|
|
20
|
+
|
|
21
|
+
# Virtual environments
|
|
22
|
+
.env
|
|
23
|
+
.venv
|
|
24
|
+
env/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
env.bak/
|
|
28
|
+
venv.bak/
|
|
29
|
+
|
|
30
|
+
# Distribution / packaging
|
|
31
|
+
.Python
|
|
32
|
+
develop-eggs/
|
|
33
|
+
downloads/
|
|
34
|
+
lib/
|
|
35
|
+
lib64/
|
|
36
|
+
.eggs/
|
|
37
|
+
|
|
38
|
+
# Unit test / coverage reports
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.nox/
|
|
42
|
+
.coverage
|
|
43
|
+
.coverage.*
|
|
44
|
+
.cache
|
|
45
|
+
nosetests.xml
|
|
46
|
+
coverage.xml
|
|
47
|
+
*.cover
|
|
48
|
+
*.py,cover
|
|
49
|
+
.hypothesis/
|
|
50
|
+
.pytest_cache/
|
|
51
|
+
pytestdebug.log
|
|
52
|
+
|
|
53
|
+
# Type checkers
|
|
54
|
+
.mypy_cache/
|
|
55
|
+
.dmypy.json
|
|
56
|
+
dmypy.json
|
|
57
|
+
.pyre/
|
|
58
|
+
.pytype/
|
|
59
|
+
|
|
60
|
+
# Jupyter Notebook
|
|
61
|
+
.ipynb_checkpoints
|
|
62
|
+
*.ipynb
|
|
63
|
+
|
|
64
|
+
# pyenv
|
|
65
|
+
.python-version
|
|
66
|
+
|
|
67
|
+
# pipenv
|
|
68
|
+
Pipfile.lock
|
|
69
|
+
|
|
70
|
+
# poetry
|
|
71
|
+
poetry.lock
|
|
72
|
+
|
|
73
|
+
# uv
|
|
74
|
+
.uv/
|
|
75
|
+
uv.lock
|
|
76
|
+
|
|
77
|
+
# Environments / secrets
|
|
78
|
+
.env
|
|
79
|
+
.env.*
|
|
80
|
+
!.env.example
|
|
81
|
+
*.pem
|
|
82
|
+
*.key
|
|
83
|
+
|
|
84
|
+
# IDEs
|
|
85
|
+
.idea/
|
|
86
|
+
.vscode/
|
|
87
|
+
*.swp
|
|
88
|
+
*.swo
|
|
89
|
+
*~
|
|
90
|
+
|
|
91
|
+
# macOS
|
|
92
|
+
.DS_Store
|
|
93
|
+
.AppleDouble
|
|
94
|
+
.LSOverride
|
|
95
|
+
._*
|
|
96
|
+
.Spotlight-V100
|
|
97
|
+
.Trashes
|
|
98
|
+
|
|
99
|
+
# Logs
|
|
100
|
+
*.log
|
|
101
|
+
logs/
|
|
102
|
+
|
|
103
|
+
# Temporary files
|
|
104
|
+
*.tmp
|
|
105
|
+
*.bak
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 CodeAny (https://codeany.ai)
|
|
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.
|