woobe-sdk 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Woobe
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.
@@ -0,0 +1,322 @@
1
+ Metadata-Version: 2.4
2
+ Name: woobe-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the Woobe Runtime API
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/A1b3rt0M3rcad0/woobe-sdk
7
+ Project-URL: Repository, https://github.com/A1b3rt0M3rcad0/woobe-sdk
8
+ Project-URL: Issues, https://github.com/A1b3rt0M3rcad0/woobe-sdk/issues
9
+ Keywords: woobe,sdk,agents,agentic,runtime
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE.md
13
+ Requires-Dist: httpx<1,>=0.28
14
+ Requires-Dist: pydantic<3,>=2.10
15
+ Provides-Extra: dev
16
+ Requires-Dist: build<2,>=1.2; extra == "dev"
17
+ Requires-Dist: pytest<9,>=8.3; extra == "dev"
18
+ Requires-Dist: pytest-asyncio<1,>=0.24; extra == "dev"
19
+ Requires-Dist: ruff<1,>=0.11; extra == "dev"
20
+ Requires-Dist: twine<7,>=6; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ # Woobe SDK
24
+
25
+ Python SDK for consuming Agents and Agent Networks running on the Woobe Runtime API.
26
+
27
+ The SDK is intentionally a **runtime client**, not a second control plane and not an agent framework. Agent configuration, Releases, Tools, Knowledge, execution strategies and runtime infrastructure remain server-side in Woobe. Applications connect to an already published runtime target and consume its execution events.
28
+
29
+ > **Pre-1.0:** the SDK is public and usable, but its APIs can still evolve before the 1.0.0 compatibility boundary.
30
+
31
+ ## Quick start
32
+
33
+ ```python
34
+ from woobe import Woobe
35
+
36
+
37
+ woobe = Woobe()
38
+
39
+ agent = woobe.connect.agent(
40
+ alias="support",
41
+ key="...",
42
+ )
43
+
44
+ # No HTTP request is executed here.
45
+ chat = agent.chat(input="Olá")
46
+
47
+ # The Runtime request starts when events() is actually iterated.
48
+ async for event in chat.events():
49
+ print(event.type, event.payload)
50
+ ```
51
+
52
+ `Chat` is lazy: constructing it does not create a Run. Iterating `events()` performs the Runtime request.
53
+
54
+ When the target policy supports conversational continuity, reuse the Session returned by the previous interaction:
55
+
56
+ ```python
57
+ chat = agent.chat(
58
+ input="Continue de onde paramos",
59
+ session_id=previous_chat.session_id,
60
+ )
61
+
62
+ async for event in chat.events():
63
+ print(event)
64
+ ```
65
+
66
+ When the selected Release declares an External Context contract, provide its values on the Run:
67
+
68
+ ```python
69
+ chat = agent.chat(
70
+ input="Consulte meus pedidos",
71
+ external_context={
72
+ "customer_id": "customer-123",
73
+ "language": "pt-BR",
74
+ },
75
+ )
76
+
77
+ async for event in chat.events():
78
+ print(event)
79
+ ```
80
+
81
+ The Runtime validates `external_context` against the Agent or Network Release contract during Acceptance. The SDK sends it only when creating the Run; reattach observes the already accepted Run and does not resend context.
82
+
83
+ After a completed Run, `Chat.result` exposes the terminal Runtime payload as typed SDK objects:
84
+
85
+ ```python
86
+ chat = agent.chat(
87
+ input="O que perguntei antes?",
88
+ session_id=session_id,
89
+ )
90
+
91
+ async for event in chat.events():
92
+ if event.type == "token":
93
+ print(event.payload["content"], end="")
94
+
95
+ result = chat.result
96
+ if result is not None:
97
+ print(result.answer)
98
+ print(result.message_id)
99
+ print(result.model)
100
+ print(result.provider)
101
+
102
+ if result.usage is not None:
103
+ print(result.usage.total_tokens)
104
+ print(result.usage.cost_usd)
105
+
106
+ print(result.agent_release_version)
107
+ print(result.execution_strategy)
108
+
109
+ if result.diagnostics is not None:
110
+ print(result.diagnostics.agent_runtime_latency_ms)
111
+ ```
112
+
113
+ `result` is `None` before completion and for terminal failures that do not produce a completed result. Agent `done` and Network `execution_completed` events are normalized to the same `ChatResult` surface. Raw streaming events remain available unchanged through `events()`.
114
+
115
+ The typed result includes `Usage`, `Source`, `ToolCall`, `FallbackInfo`, `ExecutionEvent` and `ExecutionDiagnostics` objects. Unknown future Runtime fields are preserved so the SDK remains forward compatible with additive payload changes.
116
+
117
+
118
+ ## Runtime contract validation
119
+
120
+ The SDK can validate both client-side contract declarations against the immutable Release bound to the Runtime Key before starting a Run.
121
+
122
+ ```python
123
+ from pydantic import BaseModel
124
+
125
+ from woobe import Woobe
126
+
127
+
128
+ class SupportOutput(BaseModel):
129
+ message: str
130
+ confidence: float
131
+
132
+
133
+ class SupportContext(BaseModel):
134
+ name: str
135
+ age: int
136
+
137
+
138
+ woobe = Woobe()
139
+
140
+ agent = woobe.connect.agent(
141
+ alias="support",
142
+ key="...",
143
+ )
144
+
145
+ validation = await agent.validate_contracts(
146
+ output_contract=SupportOutput,
147
+ external_context=SupportContext,
148
+ )
149
+
150
+ if not validation.valid:
151
+ for issue in validation.output_contract.issues:
152
+ print("output:", issue.code, issue.field)
153
+ for issue in validation.external_context.issues:
154
+ print("external_context:", issue.code, issue.field)
155
+ ```
156
+
157
+ `validate_contracts(...)` always declares both public contracts. Each argument accepts a Pydantic `BaseModel` type, a model instance, an explicit JSON Schema `dict`, or `None`. Local Pydantic `$ref` definitions are inlined before the request is sent to `POST /v1/contracts/validate`.
158
+
159
+ The Runtime Key determines the Agent or Network and the published `staging` or `production` Release being checked. The result contains the Release identity plus separate normalized comparisons for `output_contract` and `external_context`, including deterministic hashes and field-level mismatch issues.
160
+
161
+ For focused checks, the same target also exposes:
162
+
163
+ ```python
164
+ output = await agent.validate_output_contract(SupportOutput)
165
+ external = await agent.validate_external_context(SupportContext)
166
+ ```
167
+
168
+ The older `validate_output_context(...)` name remains available as a backward-compatible alias for `validate_output_contract(...)`.
169
+
170
+ These calls validate the SDK's declared contract shape against the published Release. Runtime External Context values passed to `chat(external_context=...)` are still validated authoritatively during Run Acceptance, including required/default/session semantics.
171
+
172
+ Validation is explicit and separate from `chat()`; the SDK does not add a hidden contract request to every Run.
173
+
174
+ The same validation surface is available for Networks.
175
+
176
+ ## Runtime model
177
+
178
+ The public SDK surface follows four concepts:
179
+
180
+ ```text
181
+ Target -> Agent or Network
182
+ Session -> longitudinal/correlation boundary
183
+ Run -> one finite logical execution
184
+ Event -> one semantic event from that Run
185
+ ```
186
+
187
+ Every accepted Run belongs to a Session. This also applies to stateless Agent execution: when no Session is supplied, Woobe creates an isolated Session for identity and correlation. That does not enable implicit history continuity for a stateless Agent.
188
+
189
+ Every event yielded by `Chat.events()` is a canonical Runtime Protocol v2 `WoobeEvent`:
190
+
191
+ ```python
192
+ async for event in chat.events():
193
+ event.protocol_version # 2
194
+ event.event_id
195
+ event.run_id
196
+ event.session_id
197
+ event.run_kind # "AGENT" | "NETWORK"
198
+ event.sequence
199
+ event.type
200
+ event.occurred_at
201
+ event.payload
202
+ ```
203
+
204
+ The SDK preserves Woobe event names and payloads. It does not infer identity from payload aliases such as `execution_id` or `network_session_id`.
205
+
206
+ ## `WoobeEvent`
207
+
208
+ ```python
209
+ class WoobeEvent(BaseModel):
210
+ protocol_version: Literal[2]
211
+ event_id: str
212
+ run_id: str
213
+ session_id: str
214
+ run_kind: Literal["AGENT", "NETWORK"]
215
+ sequence: int
216
+ type: str
217
+ occurred_at: datetime
218
+ payload: dict[str, Any]
219
+ ```
220
+
221
+ All fields above are mandatory for semantic events. The SDK validates the Runtime v2 envelope instead of fabricating missing identity or ordering metadata.
222
+
223
+ Transport/control frames are different. Heartbeats, realtime-degradation notices and pre-Acceptance errors do not pretend to be semantic Run events. They are handled internally by the SDK and are not yielded as `WoobeEvent` objects.
224
+
225
+ ## Reattach and duplicate-Run safety
226
+
227
+ A stream connection observes a Run; it does not own it.
228
+
229
+ Once the canonical `run_id` is known, a transport interruption is recovered through the reattach endpoint for the **same Run**:
230
+
231
+ ```text
232
+ POST /v1/run/stream
233
+ |
234
+ v
235
+ canonical run_id + session_id
236
+ |
237
+ connection loss
238
+ |
239
+ v
240
+ GET /v1/runs/{run_id}/stream
241
+ |
242
+ v
243
+ run.state @ high watermark
244
+ |
245
+ v
246
+ same Run
247
+ ```
248
+
249
+ If only the Session is known, the SDK can resolve the active Run through `/v1/sessions/{session_id}/active-run` before reattaching.
250
+
251
+ The SDK never submits a second Agent execution after learning the canonical Run ID. If the initial Agent connection is lost before identity can be recovered safely, it fails closed rather than risking a duplicate Run. Network create retries reuse one idempotency key for the same logical execution.
252
+
253
+ ## Sequence handling
254
+
255
+ `sequence` is the semantic ordering contract. The SSE `id:` field is a transport cursor and, when present for a semantic event, must match the canonical sequence.
256
+
257
+ The SDK:
258
+
259
+ - ignores stale or duplicate incremental events at or below the local sequence;
260
+ - detects sequence gaps and reattaches instead of guessing;
261
+ - treats `run.state` as replacement state at its high watermark;
262
+ - validates that Run, Session and Run kind do not change inside one `Chat`.
263
+
264
+ ## Configuration
265
+
266
+ The default hosted endpoint is `https://api.woobe.com.br`. Self-hosted environments can provide a base URL explicitly or through `WOOBE_BASE_URL`:
267
+
268
+ ```python
269
+ woobe = Woobe(base_url="https://woobe.internal.example")
270
+ ```
271
+
272
+ For long-lived processes, close the underlying async HTTP client on shutdown:
273
+
274
+ ```python
275
+ await woobe.aclose()
276
+ ```
277
+
278
+ or use an async context manager:
279
+
280
+ ```python
281
+ async with Woobe() as woobe:
282
+ agent = woobe.connect.agent(alias="support", key="...")
283
+ async for event in agent.chat(input="Olá").events():
284
+ print(event)
285
+ ```
286
+
287
+ ## Repository
288
+
289
+ ```text
290
+ src/woobe/ public SDK and private transport implementation
291
+ tests/ SDK unit tests
292
+ examples/ small executable usage examples
293
+ docs/ architecture and runtime contract documentation
294
+ ```
295
+
296
+ Start with [`docs/README.md`](docs/README.md) for the documentation index.
297
+
298
+ ## Development
299
+
300
+ ```bash
301
+ python -m venv .venv
302
+ source .venv/bin/activate
303
+ pip install -e '.[dev]'
304
+ pytest
305
+ ruff check .
306
+ ```
307
+
308
+ Pull requests run the same quality gate on supported Python versions. The integration branch is `master`.
309
+
310
+ ## Governance and licensing
311
+
312
+ Woobe SDK is licensed under the [MIT License](LICENSE.md). The SDK license is independent from the licenses that govern the Woobe platform itself; using this client does not relicense Woobe Core or Enterprise software.
313
+
314
+ Repository policies:
315
+
316
+ - [Contributing](CONTRIBUTING.md)
317
+ - [Releasing](RELEASING.md)
318
+ - [Security](SECURITY.md)
319
+ - [Licensing](LICENSING.md)
320
+ - [Trademark policy](TRADEMARKS.md)
321
+ - [Changelog](CHANGELOG.md)
322
+ - [Coding-agent entry point](AGENTS.md)
@@ -0,0 +1,300 @@
1
+ # Woobe SDK
2
+
3
+ Python SDK for consuming Agents and Agent Networks running on the Woobe Runtime API.
4
+
5
+ The SDK is intentionally a **runtime client**, not a second control plane and not an agent framework. Agent configuration, Releases, Tools, Knowledge, execution strategies and runtime infrastructure remain server-side in Woobe. Applications connect to an already published runtime target and consume its execution events.
6
+
7
+ > **Pre-1.0:** the SDK is public and usable, but its APIs can still evolve before the 1.0.0 compatibility boundary.
8
+
9
+ ## Quick start
10
+
11
+ ```python
12
+ from woobe import Woobe
13
+
14
+
15
+ woobe = Woobe()
16
+
17
+ agent = woobe.connect.agent(
18
+ alias="support",
19
+ key="...",
20
+ )
21
+
22
+ # No HTTP request is executed here.
23
+ chat = agent.chat(input="Olá")
24
+
25
+ # The Runtime request starts when events() is actually iterated.
26
+ async for event in chat.events():
27
+ print(event.type, event.payload)
28
+ ```
29
+
30
+ `Chat` is lazy: constructing it does not create a Run. Iterating `events()` performs the Runtime request.
31
+
32
+ When the target policy supports conversational continuity, reuse the Session returned by the previous interaction:
33
+
34
+ ```python
35
+ chat = agent.chat(
36
+ input="Continue de onde paramos",
37
+ session_id=previous_chat.session_id,
38
+ )
39
+
40
+ async for event in chat.events():
41
+ print(event)
42
+ ```
43
+
44
+ When the selected Release declares an External Context contract, provide its values on the Run:
45
+
46
+ ```python
47
+ chat = agent.chat(
48
+ input="Consulte meus pedidos",
49
+ external_context={
50
+ "customer_id": "customer-123",
51
+ "language": "pt-BR",
52
+ },
53
+ )
54
+
55
+ async for event in chat.events():
56
+ print(event)
57
+ ```
58
+
59
+ The Runtime validates `external_context` against the Agent or Network Release contract during Acceptance. The SDK sends it only when creating the Run; reattach observes the already accepted Run and does not resend context.
60
+
61
+ After a completed Run, `Chat.result` exposes the terminal Runtime payload as typed SDK objects:
62
+
63
+ ```python
64
+ chat = agent.chat(
65
+ input="O que perguntei antes?",
66
+ session_id=session_id,
67
+ )
68
+
69
+ async for event in chat.events():
70
+ if event.type == "token":
71
+ print(event.payload["content"], end="")
72
+
73
+ result = chat.result
74
+ if result is not None:
75
+ print(result.answer)
76
+ print(result.message_id)
77
+ print(result.model)
78
+ print(result.provider)
79
+
80
+ if result.usage is not None:
81
+ print(result.usage.total_tokens)
82
+ print(result.usage.cost_usd)
83
+
84
+ print(result.agent_release_version)
85
+ print(result.execution_strategy)
86
+
87
+ if result.diagnostics is not None:
88
+ print(result.diagnostics.agent_runtime_latency_ms)
89
+ ```
90
+
91
+ `result` is `None` before completion and for terminal failures that do not produce a completed result. Agent `done` and Network `execution_completed` events are normalized to the same `ChatResult` surface. Raw streaming events remain available unchanged through `events()`.
92
+
93
+ The typed result includes `Usage`, `Source`, `ToolCall`, `FallbackInfo`, `ExecutionEvent` and `ExecutionDiagnostics` objects. Unknown future Runtime fields are preserved so the SDK remains forward compatible with additive payload changes.
94
+
95
+
96
+ ## Runtime contract validation
97
+
98
+ The SDK can validate both client-side contract declarations against the immutable Release bound to the Runtime Key before starting a Run.
99
+
100
+ ```python
101
+ from pydantic import BaseModel
102
+
103
+ from woobe import Woobe
104
+
105
+
106
+ class SupportOutput(BaseModel):
107
+ message: str
108
+ confidence: float
109
+
110
+
111
+ class SupportContext(BaseModel):
112
+ name: str
113
+ age: int
114
+
115
+
116
+ woobe = Woobe()
117
+
118
+ agent = woobe.connect.agent(
119
+ alias="support",
120
+ key="...",
121
+ )
122
+
123
+ validation = await agent.validate_contracts(
124
+ output_contract=SupportOutput,
125
+ external_context=SupportContext,
126
+ )
127
+
128
+ if not validation.valid:
129
+ for issue in validation.output_contract.issues:
130
+ print("output:", issue.code, issue.field)
131
+ for issue in validation.external_context.issues:
132
+ print("external_context:", issue.code, issue.field)
133
+ ```
134
+
135
+ `validate_contracts(...)` always declares both public contracts. Each argument accepts a Pydantic `BaseModel` type, a model instance, an explicit JSON Schema `dict`, or `None`. Local Pydantic `$ref` definitions are inlined before the request is sent to `POST /v1/contracts/validate`.
136
+
137
+ The Runtime Key determines the Agent or Network and the published `staging` or `production` Release being checked. The result contains the Release identity plus separate normalized comparisons for `output_contract` and `external_context`, including deterministic hashes and field-level mismatch issues.
138
+
139
+ For focused checks, the same target also exposes:
140
+
141
+ ```python
142
+ output = await agent.validate_output_contract(SupportOutput)
143
+ external = await agent.validate_external_context(SupportContext)
144
+ ```
145
+
146
+ The older `validate_output_context(...)` name remains available as a backward-compatible alias for `validate_output_contract(...)`.
147
+
148
+ These calls validate the SDK's declared contract shape against the published Release. Runtime External Context values passed to `chat(external_context=...)` are still validated authoritatively during Run Acceptance, including required/default/session semantics.
149
+
150
+ Validation is explicit and separate from `chat()`; the SDK does not add a hidden contract request to every Run.
151
+
152
+ The same validation surface is available for Networks.
153
+
154
+ ## Runtime model
155
+
156
+ The public SDK surface follows four concepts:
157
+
158
+ ```text
159
+ Target -> Agent or Network
160
+ Session -> longitudinal/correlation boundary
161
+ Run -> one finite logical execution
162
+ Event -> one semantic event from that Run
163
+ ```
164
+
165
+ Every accepted Run belongs to a Session. This also applies to stateless Agent execution: when no Session is supplied, Woobe creates an isolated Session for identity and correlation. That does not enable implicit history continuity for a stateless Agent.
166
+
167
+ Every event yielded by `Chat.events()` is a canonical Runtime Protocol v2 `WoobeEvent`:
168
+
169
+ ```python
170
+ async for event in chat.events():
171
+ event.protocol_version # 2
172
+ event.event_id
173
+ event.run_id
174
+ event.session_id
175
+ event.run_kind # "AGENT" | "NETWORK"
176
+ event.sequence
177
+ event.type
178
+ event.occurred_at
179
+ event.payload
180
+ ```
181
+
182
+ The SDK preserves Woobe event names and payloads. It does not infer identity from payload aliases such as `execution_id` or `network_session_id`.
183
+
184
+ ## `WoobeEvent`
185
+
186
+ ```python
187
+ class WoobeEvent(BaseModel):
188
+ protocol_version: Literal[2]
189
+ event_id: str
190
+ run_id: str
191
+ session_id: str
192
+ run_kind: Literal["AGENT", "NETWORK"]
193
+ sequence: int
194
+ type: str
195
+ occurred_at: datetime
196
+ payload: dict[str, Any]
197
+ ```
198
+
199
+ All fields above are mandatory for semantic events. The SDK validates the Runtime v2 envelope instead of fabricating missing identity or ordering metadata.
200
+
201
+ Transport/control frames are different. Heartbeats, realtime-degradation notices and pre-Acceptance errors do not pretend to be semantic Run events. They are handled internally by the SDK and are not yielded as `WoobeEvent` objects.
202
+
203
+ ## Reattach and duplicate-Run safety
204
+
205
+ A stream connection observes a Run; it does not own it.
206
+
207
+ Once the canonical `run_id` is known, a transport interruption is recovered through the reattach endpoint for the **same Run**:
208
+
209
+ ```text
210
+ POST /v1/run/stream
211
+ |
212
+ v
213
+ canonical run_id + session_id
214
+ |
215
+ connection loss
216
+ |
217
+ v
218
+ GET /v1/runs/{run_id}/stream
219
+ |
220
+ v
221
+ run.state @ high watermark
222
+ |
223
+ v
224
+ same Run
225
+ ```
226
+
227
+ If only the Session is known, the SDK can resolve the active Run through `/v1/sessions/{session_id}/active-run` before reattaching.
228
+
229
+ The SDK never submits a second Agent execution after learning the canonical Run ID. If the initial Agent connection is lost before identity can be recovered safely, it fails closed rather than risking a duplicate Run. Network create retries reuse one idempotency key for the same logical execution.
230
+
231
+ ## Sequence handling
232
+
233
+ `sequence` is the semantic ordering contract. The SSE `id:` field is a transport cursor and, when present for a semantic event, must match the canonical sequence.
234
+
235
+ The SDK:
236
+
237
+ - ignores stale or duplicate incremental events at or below the local sequence;
238
+ - detects sequence gaps and reattaches instead of guessing;
239
+ - treats `run.state` as replacement state at its high watermark;
240
+ - validates that Run, Session and Run kind do not change inside one `Chat`.
241
+
242
+ ## Configuration
243
+
244
+ The default hosted endpoint is `https://api.woobe.com.br`. Self-hosted environments can provide a base URL explicitly or through `WOOBE_BASE_URL`:
245
+
246
+ ```python
247
+ woobe = Woobe(base_url="https://woobe.internal.example")
248
+ ```
249
+
250
+ For long-lived processes, close the underlying async HTTP client on shutdown:
251
+
252
+ ```python
253
+ await woobe.aclose()
254
+ ```
255
+
256
+ or use an async context manager:
257
+
258
+ ```python
259
+ async with Woobe() as woobe:
260
+ agent = woobe.connect.agent(alias="support", key="...")
261
+ async for event in agent.chat(input="Olá").events():
262
+ print(event)
263
+ ```
264
+
265
+ ## Repository
266
+
267
+ ```text
268
+ src/woobe/ public SDK and private transport implementation
269
+ tests/ SDK unit tests
270
+ examples/ small executable usage examples
271
+ docs/ architecture and runtime contract documentation
272
+ ```
273
+
274
+ Start with [`docs/README.md`](docs/README.md) for the documentation index.
275
+
276
+ ## Development
277
+
278
+ ```bash
279
+ python -m venv .venv
280
+ source .venv/bin/activate
281
+ pip install -e '.[dev]'
282
+ pytest
283
+ ruff check .
284
+ ```
285
+
286
+ Pull requests run the same quality gate on supported Python versions. The integration branch is `master`.
287
+
288
+ ## Governance and licensing
289
+
290
+ Woobe SDK is licensed under the [MIT License](LICENSE.md). The SDK license is independent from the licenses that govern the Woobe platform itself; using this client does not relicense Woobe Core or Enterprise software.
291
+
292
+ Repository policies:
293
+
294
+ - [Contributing](CONTRIBUTING.md)
295
+ - [Releasing](RELEASING.md)
296
+ - [Security](SECURITY.md)
297
+ - [Licensing](LICENSING.md)
298
+ - [Trademark policy](TRADEMARKS.md)
299
+ - [Changelog](CHANGELOG.md)
300
+ - [Coding-agent entry point](AGENTS.md)
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "woobe-sdk"
7
+ version = "0.1.0"
8
+ description = "Python SDK for the Woobe Runtime API"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE.md"]
13
+ keywords = ["woobe", "sdk", "agents", "agentic", "runtime"]
14
+ dependencies = [
15
+ "httpx>=0.28,<1",
16
+ "pydantic>=2.10,<3",
17
+ ]
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/A1b3rt0M3rcad0/woobe-sdk"
21
+ Repository = "https://github.com/A1b3rt0M3rcad0/woobe-sdk"
22
+ Issues = "https://github.com/A1b3rt0M3rcad0/woobe-sdk/issues"
23
+
24
+ [project.optional-dependencies]
25
+ dev = [
26
+ "build>=1.2,<2",
27
+ "pytest>=8.3,<9",
28
+ "pytest-asyncio>=0.24,<1",
29
+ "ruff>=0.11,<1",
30
+ "twine>=6,<7",
31
+ ]
32
+
33
+ [tool.setuptools]
34
+ package-dir = {"" = "src"}
35
+
36
+ [tool.setuptools.packages.find]
37
+ where = ["src"]
38
+ include = ["woobe*"]
39
+
40
+ [tool.setuptools.package-data]
41
+ woobe = ["py.typed"]
42
+
43
+ [tool.pytest.ini_options]
44
+ asyncio_mode = "auto"
45
+ testpaths = ["tests"]
46
+
47
+ [tool.ruff]
48
+ target-version = "py311"
49
+ line-length = 100
50
+
51
+ [tool.ruff.lint]
52
+ select = ["E", "F", "I", "UP", "B"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+