polaris-python-ai 0.0.1.dev2__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.
@@ -0,0 +1,351 @@
1
+ Metadata-Version: 2.4
2
+ Name: polaris-python-ai
3
+ Version: 0.0.1.dev2
4
+ Summary: Polaris integrations for Python AI frameworks.
5
+ License-Expression: BSD-3-Clause
6
+ Project-URL: Homepage, https://github.com/polaris-contrib/polaris-python-ai
7
+ Project-URL: Repository, https://github.com/polaris-contrib/polaris-python-ai
8
+ Project-URL: Issues, https://github.com/polaris-contrib/polaris-python-ai/issues
9
+ Project-URL: Documentation, https://github.com/polaris-contrib/polaris-python-ai#readme
10
+ Requires-Python: >=3.12
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: polaris-python<0.1,>=0.0.1.dev0
14
+ Provides-Extra: a2a
15
+ Requires-Dist: a2a-sdk<2,>=1.2.3; extra == "a2a"
16
+ Provides-Extra: agentscope
17
+ Requires-Dist: a2a-sdk<2,>=1.2.3; extra == "agentscope"
18
+ Requires-Dist: agentscope<3,>=2.0.10; extra == "agentscope"
19
+ Provides-Extra: langgraph
20
+ Requires-Dist: langgraph<2,>=1.0; extra == "langgraph"
21
+ Provides-Extra: mcp
22
+ Requires-Dist: a2a-sdk<2,>=1.2.3; extra == "mcp"
23
+ Requires-Dist: agentscope<3,>=2.0.10; extra == "mcp"
24
+ Requires-Dist: mcp<3,>=2; extra == "mcp"
25
+ Provides-Extra: all
26
+ Requires-Dist: a2a-sdk<2,>=1.2.3; extra == "all"
27
+ Requires-Dist: agentscope<3,>=2.0.10; extra == "all"
28
+ Requires-Dist: langgraph<2,>=1.0; extra == "all"
29
+ Requires-Dist: mcp<3,>=2; extra == "all"
30
+ Dynamic: license-file
31
+
32
+ # polaris-python-ai
33
+
34
+ Polaris integrations for Python AI frameworks. The repository publishes one
35
+ distribution, `polaris-python-ai`, with optional A2A, AgentScope, MCP, and
36
+ LangGraph extras under the `polaris_ai` import namespace.
37
+
38
+ ## Development Installation
39
+
40
+ Use Python 3.12 or newer. Run from this project's root directory:
41
+
42
+ ```bash
43
+ uv sync --all-extras
44
+ uv run python -m pytest
45
+ ```
46
+
47
+ The sibling `polaris-python` checkout is selected through `[tool.uv.sources]`;
48
+ published wheel metadata contains only version ranges.
49
+
50
+ Install framework adapters through package extras:
51
+
52
+ ```bash
53
+ pip install "polaris-python-ai[a2a]"
54
+ pip install "polaris-python-ai[agentscope]"
55
+ pip install "polaris-python-ai[langgraph]"
56
+ pip install "polaris-python-ai[mcp]"
57
+ ```
58
+
59
+ See [docs/version-release.md](docs/version-release.md) for the single version file,
60
+ Snapshot format, and release tag.
61
+
62
+ See [docs/configuration.md](docs/configuration.md) for the complete feature and
63
+ configuration guide, including Core SDK, Skill, A2A, MCP and AI logging settings.
64
+
65
+ AgentScope, A2A, and LangGraph are optional. Base-package imports do not load
66
+ their SDKs. The integration targets AgentScope 2.0.10, A2A SDK 1.2.3, and
67
+ LangGraph 1.x. Legacy Java AgentCard JSON is decoded through the official A2A
68
+ compatibility parser.
69
+
70
+ ## Shared AgentScope Context
71
+
72
+ ```python
73
+ from polaris_ai.agentscope import PolarisAgentContext
74
+
75
+ with PolarisAgentContext.from_address("127.0.0.1:8091", "default") as polaris:
76
+ provider = polaris.provider
77
+ consumer = polaris.consumer
78
+ skill = polaris.skill
79
+ ```
80
+
81
+ The factory owns and closes only the context it creates. It disables stat
82
+ reporting and the provider lossless lifecycle, writes the connector token, and
83
+ maps every discovery host to the Skill endpoint on port 8094 unless
84
+ `skill_address` is explicit. A context passed through `sdk_context` is borrowed
85
+ unchanged and is never destroyed by the factory.
86
+
87
+ Applications that prefer environment-driven assembly can use:
88
+
89
+ ```python
90
+ from polaris_ai.agentscope import PolarisAgentConfig, PolarisAgentRuntime
91
+
92
+ config = PolarisAgentConfig.from_env(agent_name="weather-agent")
93
+ async with PolarisAgentRuntime(config) as runtime:
94
+ loader = runtime.skill_loader
95
+ resolver = runtime.resolver
96
+ registrar = runtime.registrar
97
+ ```
98
+
99
+ `POLARIS_AI_*` variables take precedence. `POLARIS_SERVER_ADDRESS`,
100
+ `POLARIS_TOKEN`, `POLARIS_SERVICE_TOKEN`, and
101
+ `POLARIS_SKILL_SERVER_ADDRESS` are accepted as fallbacks. Connector and service
102
+ tokens remain separate. Passing an explicit `sdk_context` borrows it and never
103
+ changes its configuration or ownership.
104
+ When `skill.attach_to_agent` is true, `runtime.skill_toolkit` builds a native
105
+ Toolkit containing the Polaris loader, and `runtime.create_agent()` attaches that
106
+ Toolkit plus the dynamic refresh middleware.
107
+
108
+ ## AI Logging
109
+
110
+ AI extension logging is optional and disabled for managed files by default. Set
111
+ `ai_log_options` on the runtime to enable Polaris-managed category logs:
112
+
113
+ ```python
114
+ from polaris_ai import PolarisAILogOptions
115
+
116
+ runtime = PolarisAgentRuntime(
117
+ config,
118
+ log_options=core_sdk_log_options,
119
+ ai_log_options=PolarisAILogOptions(
120
+ level="info",
121
+ log_dir="./polaris/log/ai",
122
+ max_bytes=50 * 1024 * 1024,
123
+ backup_count=5,
124
+ max_age_days=30,
125
+ warning_throttle_seconds=30,
126
+ ),
127
+ )
128
+ ```
129
+
130
+ Managed logs are separated from Core SDK logs under `./polaris/log/ai` by
131
+ default. Categories are `base`, `agentscope`, `skill`, `a2a`, `mcp`,
132
+ `langgraph`, and `metrics`. Each active runtime writes files such as
133
+ `base/polaris-ai-base-<clientId>.log`; files are created on first use. Category
134
+ files rotate at 50MB, keep five backups, retain backups for 30 days, and use
135
+ exclusive file locks.
136
+
137
+ `POLARIS_AI_LOG_LEVEL` and `POLARIS_AI_LOG_PATH` are used when the corresponding
138
+ options are not assigned. `POLARIS_AI_LOG_CAPTURE_AGENTSCOPE=true` optionally
139
+ adds an AgentScope `"as"` logger handler for the runtime lifetime. The extension
140
+ does not call `agentscope.setup_logger()` or replace existing AgentScope handlers.
141
+ Because `"as"` is process-global, only one active runtime can capture it at a time.
142
+
143
+ The detail policy avoids flooding high-frequency paths:
144
+
145
+ - `INFO`: runtime lifecycle, Skill reference changes, A2A instance failover and MCP pool changes.
146
+ - `DEBUG`: per-page listing, cache hits, candidate filtering, selected endpoints and retries.
147
+ - `WARNING`: recoverable failures, deduplicated by key. The default interval is 30 seconds;
148
+ the next emitted warning includes the number of suppressed occurrences.
149
+
150
+ ## AgentScope Skill Loader
151
+
152
+ ```python
153
+ import asyncio
154
+ from agentscope.tool import Toolkit
155
+ from polaris.api.config import init_context_by_file
156
+ from polaris_ai.agentscope import PolarisSkillLoader
157
+
158
+ async def main():
159
+ context = init_context_by_file("polaris.yaml")
160
+ try:
161
+ async with PolarisSkillLoader(context, namespace="default") as loader:
162
+ toolkit = Toolkit(skills_or_loaders=[loader])
163
+ print(await toolkit.get_skill_instructions())
164
+ finally:
165
+ await asyncio.to_thread(context.destroy)
166
+
167
+ asyncio.run(main())
168
+ ```
169
+
170
+ Published loading uses 50-item pages, at most 100 skills, and a 30-second list
171
+ cache. `names=["weather"]` skips listing. `service_name="weather-agent"` loads
172
+ only that service's mounted skills. Mount identities are `namespace:skillName`,
173
+ split at the first colon; other namespaces are skipped. Version precedence is
174
+ mounted version, configured `version`, then the server's active version.
175
+
176
+ ZIPs include `SKILL.md` and assets. Both flat archives and a single skill folder
177
+ are accepted; traversal, absolute paths, links, conflicting entries and multiple
178
+ skill roots are rejected. Maximum archive/expanded size is 64 MiB and the entry
179
+ limit is 2048. Skills live in temporary directories until the loader closes.
180
+ Successful loads with an explicit version are cached by name/version. A blank
181
+ version is an active-version alias: it is revalidated and materialized under
182
+ the server-returned version. Middleware instances sharing one loader also
183
+ share one Toolkit snapshot, so agents created from the same runtime see the
184
+ latest successful refresh.
185
+ Persistent offline fallback is provided by the SDK, not a second adapter cache.
186
+ Published list errors propagate; an individual failed download is logged and
187
+ skipped. Empty mount tables are re-read on the next call.
188
+ `async_list_skill_names()` refreshes references without downloading ZIPs, and
189
+ mounted `async_skill_exists()` checks only the mount table. A `400202` response
190
+ raises `PolarisSkillNotFoundError`. The loader exposes `source`, `location`,
191
+ `get_repository_info()`, and its read-only identity.
192
+
193
+ `list_skills()` follows AgentScope's asynchronous interface. Explicit single-skill
194
+ loading is `async_get_skill()`. `close()` and `async_close()` remove temporary assets.
195
+
196
+ ## A2A
197
+
198
+ ```python
199
+ from polaris_ai.agentscope import A2ATransport, PolarisA2ARegistrar, PolarisA2AResolver
200
+ from agentscope.agent import A2AAgent
201
+
202
+ # card is the native a2a.types.AgentCard for an already listening server.
203
+ async with PolarisA2ARegistrar(context, service_token="service-token") as registrar:
204
+ await registrar.async_register(card, [A2ATransport("10.0.0.1", 8080)])
205
+ async with PolarisA2AResolver(context) as resolver:
206
+ remote_card = await resolver.async_resolve(card.name)
207
+ async with A2AAgent(remote_card) as agent:
208
+ reply = await agent.reply(message)
209
+ ```
210
+
211
+ Each transport becomes a Polaris instance. Metadata includes `ai-agent-name`,
212
+ `a2a.agent.card`, `a2a.transport` and `a2a.path`; TLS selects `http` or `https`.
213
+ Automatic heartbeat and re-registration use the SDK's `register_instance` with a
214
+ 5-second TTL. `service_token` is used for registration, heartbeats and
215
+ deregistration, is distinct from the connector token, and may be empty when the
216
+ server permits unauthenticated registration. The SDK's `bindIP` is not a business
217
+ host.
218
+
219
+ Partial registration failure rolls back only that call's created instances.
220
+ Failed deregistrations stay in `registrar.registered`, so another `close()` can
221
+ retry. Cancelled registration waits for in-flight SDK work and rolls back its
222
+ successes. A closed registrar accepts further cleanup, but no new registrations.
223
+ `PolarisA2AServerRegistration` waits for `server_ready` before registration and
224
+ deregisters on normal or exceptional exit, replacing the Java Server / Spring
225
+ lifecycle assembly.
226
+
227
+ The resolver refreshes discovery on every lookup and stays on the selected
228
+ healthy `host:port`. It sees card updates in place and switches when that instance
229
+ is unhealthy, isolated, absent or has invalid metadata. Successful empty results
230
+ raise `AgentCardNotFoundError`; SDK discovery errors reuse a previously decoded
231
+ card. The card's advertised URLs are preserved. Configure each server's card
232
+ with its externally reachable endpoints.
233
+
234
+ `PolarisA2AAgent` wraps the native AgentScope `A2AAgent`. It resolves once,
235
+ reuses the client for later turns, and rebuilds it after an explicit
236
+ `invalidate()` or a network failure that occurs before any response event is
237
+ delivered. Business errors are propagated without switching instances. Streaming
238
+ does not retry after an event has already been emitted.
239
+
240
+ Long-lived Skill-backed Agents can add `PolarisDynamicSkillMiddleware(loader)`.
241
+ It refreshes the loader before each reply, honors the loader's refresh interval,
242
+ and continues with the last successful state when Polaris is unavailable.
243
+
244
+ ## MCP
245
+
246
+ ```python
247
+ from polaris_ai.agentscope import PolarisMCPClientPool, PolarisMCPResolver
248
+
249
+ resolver = PolarisMCPResolver(context, "default")
250
+ client = await resolver.async_create_client("search-mcp")
251
+
252
+ async with PolarisMCPClientPool(resolver, "search-mcp") as pool:
253
+ selected = pool.choose_client()
254
+ ```
255
+
256
+ The resolver reads standard MCP instance metadata, validates the protocol, builds
257
+ an AgentScope `HttpMCPConfig`, and maps disabled contract Tools to
258
+ `MCPClient.disable_tools`. Streamable HTTP is stateless; SSE is connected as a
259
+ stateful client. The pool watches Polaris changes and reconciles clients.
260
+ MCP Tool calls automatically report the original Tool name as method and
261
+ `instance_type="mcp"`. A2A replies report `message/send` with
262
+ `instance_type="a2a"`; native A2A timeout errors are reported as timeouts.
263
+
264
+ `build_agent_card()` and `PolarisAgentCardTemplate` construct native A2A cards
265
+ with protocol, Skills, streaming capability, and input/output modes.
266
+
267
+ MCP-aware applications can enable the resolver with `POLARIS_AI_MCP_ENABLED=true`
268
+ and use `POLARIS_AI_MCP_PROTOCOL_VERSION`, `POLARIS_AI_MCP_SCHEME`,
269
+ `POLARIS_AI_MCP_TIMEOUT`, `POLARIS_AI_MCP_HEADERS`,
270
+ `POLARIS_AI_MCP_FILTER_CONTRACT`, `POLARIS_AI_MCP_CALLER_SERVICE`, and
271
+ `POLARIS_AI_MCP_LABELS`.
272
+
273
+ Ordinary A2A method names are synchronous; `async_` names are asynchronous.
274
+ Skill and A2A adapters borrow `SDKContext`; `PolarisAgentContext` is the only
275
+ component that can own one. Close adapters before destroying a shared context.
276
+ Configuration remains in `polaris.yaml` or SDK `Configuration` objects; framework
277
+ settings are code options.
278
+
279
+ ## LangGraph
280
+
281
+ ```python
282
+ from polaris_ai.langgraph import (
283
+ LangGraphTransport,
284
+ PolarisLangGraphContext,
285
+ PolarisLangGraphRegistrar,
286
+ PolarisLangGraphResolver,
287
+ PolarisRemoteGraph,
288
+ )
289
+
290
+ with PolarisLangGraphContext.from_address(
291
+ "127.0.0.1:8091",
292
+ "production",
293
+ ) as polaris, PolarisLangGraphRegistrar(
294
+ polaris.context,
295
+ "production",
296
+ ) as registrar, PolarisLangGraphResolver(
297
+ polaris.context,
298
+ "production",
299
+ ) as resolver:
300
+ registrar.register(
301
+ "review-service",
302
+ [LangGraphTransport("10.0.0.8", 8123, "/api", graph_id="review-graph")],
303
+ )
304
+ with PolarisRemoteGraph(
305
+ resolver,
306
+ "review-graph",
307
+ service="review-service",
308
+ ) as graph:
309
+ result = graph.invoke(
310
+ {"messages": []},
311
+ {"configurable": {"thread_id": "thread-1"}},
312
+ )
313
+ ```
314
+
315
+ The registrar writes `langgraph.graph-id`, `langgraph.path`, and
316
+ `langgraph.protocol` metadata to an ordinary Polaris instance. The resolver
317
+ selects a healthy, non-isolated instance for the requested graph, prefers the
318
+ previous `host:port`, and reuses the last endpoint when discovery temporarily
319
+ fails.
320
+
321
+ `PolarisRemoteGraph` exposes `invoke`, `ainvoke`, `stream`, and `astream`.
322
+ Each call refreshes discovery and reports `instance_type="langgraph"` to Polaris
323
+ without changing LangGraph's result or exception. The native `RemoteGraph`
324
+ client is reused until the selected URL changes.
325
+
326
+ `PolarisLangGraphConfig.from_env()` reads `POLARIS_AI_LANGGRAPH_*` first and
327
+ accepts `POLARIS_SERVER_ADDRESS`, `POLARIS_TOKEN`,
328
+ `POLARIS_SERVICE_TOKEN`, and `POLARIS_NAMESPACE` as fallbacks.
329
+
330
+ ## Validation
331
+
332
+ ```bash
333
+ uv run python -m pytest
334
+ uv build
335
+ ./examples/verify.sh
336
+ ./examples/verify.sh --only agentscope/a2a/skill
337
+ ./examples/verify.sh --only agentscope/mcp
338
+ ./examples/verify_e2e.sh --only agentscope/a2a
339
+ ```
340
+
341
+ Tests use real AgentScope Toolkit and A2A types, public Polaris API wrappers and
342
+ a deterministic SDK engine. The A2A transport test exercises the official server
343
+ routes, JSON-RPC/SSE and `A2AAgent` through an in-process HTTP transport. These
344
+ tests do not constitute a commercial Polaris server integration test.
345
+
346
+ Offline example verification uses real SDK contexts and AgentScope, replacing
347
+ only Polaris RPC calls. Real-registry verification is explicitly enabled through
348
+ `verify_e2e.sh`. See [examples/test.md](examples/test.md) for prerequisites,
349
+ per-run logs, assertions and cleanup, and [AgentScope examples](examples/agentscope/README.md)
350
+ for manual commands. Real MCP Server E2E, remote controller governance, and
351
+ Skill write operations remain outside the current example coverage.
@@ -0,0 +1,30 @@
1
+ polaris_ai/__init__.py,sha256=CaeZvcjeFFw3H-3Tm6eSWJT5Kx68f9sByzEO0Jocr_U,1057
2
+ polaris_ai/_async.py,sha256=cYXtctS6kPMaMsQKSOCMbvQLpZtwCqY4na-8rubk3QA,1256
3
+ polaris_ai/_version.py,sha256=bMt8kw7QITqgand1bMSAn0wN1u8ur136D_lGOAfA8C4,754
4
+ polaris_ai/log.py,sha256=rpHsU1IBLGtPTaobvXZWIgQC5QU3AztEmcgKCxsUgmg,13875
5
+ polaris_ai/metrics.py,sha256=0yuqHaZo4o4wiIZ8k-O7fHN2XzCsowld-09VVbhFI-M,4663
6
+ polaris_ai/a2a/__init__.py,sha256=39ih6kmEr_9zWnhwxNLaTQO1fyFq3faE5HZJ8myTurI,1185
7
+ polaris_ai/a2a/_card.py,sha256=2AvqQw_U5-8-ZDMmfHkcJ0BunHMHABpExCNsyWJCzhM,1603
8
+ polaris_ai/a2a/registry.py,sha256=R5orbOLQbL_2Dm587z_Ofu0ji5tS_cyI7l8Dv1ocbfw,10151
9
+ polaris_ai/a2a/resolver.py,sha256=oowjwLx10jzgm8NQvX3TTMrkPI1gUVH1YS6_bivmVWs,8422
10
+ polaris_ai/a2a/server.py,sha256=0LKH8fHAttfWWSarNygfa4GP38PBceKDQDYJD8JV8lM,3204
11
+ polaris_ai/agentscope/__init__.py,sha256=ZnzGn_OyiTyVswT01uF3-PviphsAniwmwymlXjNdxQQ,2610
12
+ polaris_ai/agentscope/a2a.py,sha256=TCo4bvmV5iyC_ebzKl0QJrPXWrNeE9s4w-u44iXlLGs,10621
13
+ polaris_ai/agentscope/cards.py,sha256=pQGg4-eIlb54jRBBddLi_sgLgNrCi7EGDLZs8OQFyWA,3653
14
+ polaris_ai/agentscope/config.py,sha256=5N_-72BLHTUjEm43Cfh871v41ODpUL8Ra_JkAR0CuUM,7909
15
+ polaris_ai/agentscope/context.py,sha256=hfSsGovPGWg4EJRv09j85ZC2tf8VUaHidlJl5Yl20lY,7311
16
+ polaris_ai/agentscope/mcp.py,sha256=ynqhEzqUUsasx_RVKWyDGHcqPP7io8xZmVmldgaXDZM,22796
17
+ polaris_ai/agentscope/middleware.py,sha256=AIRt8He8X3VTWTOB-aJE3kROrlKCGWkvxMImRs2PwgE,4126
18
+ polaris_ai/agentscope/runtime.py,sha256=NmP4-vM5ZwypH-WPp-EAtkR1yxPi6I30G1PMBhiZl8U,11496
19
+ polaris_ai/agentscope/skill.py,sha256=EYR6uIS9W_DPbn-4_Weo_9fAmf1wzpDAKJZw8F0jHh8,19599
20
+ polaris_ai/langgraph/__init__.py,sha256=INhTZKIFZu14S2VvlbIbVa3CAiDVWp8rORSrgP1nFMI,1616
21
+ polaris_ai/langgraph/config.py,sha256=4pD0P_93d_jkS1Wg4KhAWa7bbJI0pZO9DoC6zRpWB9g,5770
22
+ polaris_ai/langgraph/context.py,sha256=M-nIvvOfKSQH0U8z8qXLISeZQ_P33l4-FZBZ1EA-mv4,5357
23
+ polaris_ai/langgraph/registry.py,sha256=TXY6yu3sTirx-b6YTwPxpCTjCW_N0eCP2QnvTDiQgM4,9350
24
+ polaris_ai/langgraph/remote.py,sha256=Q15hy5rcWFOBZ4QSNBLOUdGvofKh5-1IV2yWxLBwbY4,11046
25
+ polaris_ai/langgraph/resolver.py,sha256=ZlZJBTf__kyfd_nqlahyfNeOj0DMiTHtZcX7DPakoY8,8581
26
+ polaris_python_ai-0.0.1.dev2.dist-info/licenses/LICENSE,sha256=YoVDzA2hP0mj2gVav7n65S2YyPlG0o19TaoXhCtDqkE,1513
27
+ polaris_python_ai-0.0.1.dev2.dist-info/METADATA,sha256=TlXfWQLXNuDtvC2LQpsdvol7DHCPG1ONstChxq8jGfM,14975
28
+ polaris_python_ai-0.0.1.dev2.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
29
+ polaris_python_ai-0.0.1.dev2.dist-info/top_level.txt,sha256=uL2b6ytNmKzijQaMPYutTpJJHHa6F4zY8mE2UquWrK4,11
30
+ polaris_python_ai-0.0.1.dev2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,27 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Tencent
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+ 3. Neither the name of the copyright holder nor the names of its contributors
15
+ may be used to endorse or promote products derived from this software without
16
+ specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1 @@
1
+ polaris_ai