snowflake-cortex-agent-sdk 0.0.1__tar.gz → 0.0.2__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.
- snowflake_cortex_agent_sdk-0.0.2/PKG-INFO +118 -0
- snowflake_cortex_agent_sdk-0.0.2/README.md +90 -0
- snowflake_cortex_agent_sdk-0.0.2/cortex_agent_sdk/__init__.py +126 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_base_client.py +39 -8
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_generated/agent_runs.py +198 -5
- snowflake_cortex_agent_sdk-0.0.2/cortex_agent_sdk/_generated/data_agent.py +4733 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_generated/events.py +640 -45
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/_generated/data_agent.py → snowflake_cortex_agent_sdk-0.0.2/cortex_agent_sdk/_generated/lite_agent.py +198 -289
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_generated/threads.py +52 -2
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_version.py +1 -1
- snowflake_cortex_agent_sdk-0.0.2/cortex_agent_sdk/api.py +83 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/client.py +9 -6
- snowflake_cortex_agent_sdk-0.0.2/cortex_agent_sdk/conversation.py +295 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/__init__.py +1 -36
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/client.py +1 -15
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/fork_session.py +9 -22
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/types.py +5 -55
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/errors.py +33 -0
- snowflake_cortex_agent_sdk-0.0.2/cortex_agent_sdk/public_client.py +56 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/resources/coding_agent.py +83 -15
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/resources/runs.py +84 -0
- snowflake_cortex_agent_sdk-0.0.2/cortex_agent_sdk/turn.py +85 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/views/agent_response.py +52 -4
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/views/async_run.py +76 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/pyproject.toml +5 -7
- snowflake_cortex_agent_sdk-0.0.1/PKG-INFO +0 -194
- snowflake_cortex_agent_sdk-0.0.1/README.md +0 -165
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/__init__.py +0 -180
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/_generated/lite_agent.py +0 -1050
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/conversation.py +0 -428
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api.py +0 -988
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/__init__.py +0 -1
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/connection.py +0 -232
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/messages.py +0 -72
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/options.py +0 -100
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/settings.py +0 -31
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/tools.py +0 -55
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/trace.py +0 -99
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/types.py +0 -86
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/utils.py +0 -34
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/_internal/transport/api_support/wire.py +0 -530
- snowflake_cortex_agent_sdk-0.0.1/cortex_agent_sdk/cortexcode/threads.py +0 -190
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/.gitignore +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/LICENSE +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_constants.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_generated/__init__.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_request_options.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_resource.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_transport.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/_types.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/api_response.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/auth.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/constants.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/_errors.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/_internal/__init__.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/_internal/message_parser.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/_internal/query.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/_internal/transport/__init__.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/_internal/transport/subprocess_cli.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/py.typed +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/cortexcode/query.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/models.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/origin.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/py.typed +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/resources/__init__.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/resources/agent.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/resources/feedback.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/resources/threads.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/stream.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/streaming/__init__.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/streaming/parser.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/streaming/run_stream.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/threads_page.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/views/__init__.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/views/content_view.py +0 -0
- {snowflake_cortex_agent_sdk-0.0.1 → snowflake_cortex_agent_sdk-0.0.2}/cortex_agent_sdk/views/thread_message.py +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: snowflake-cortex-agent-sdk
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Python SDK for the Snowflake Cortex Agent REST API (agent:run streaming, threads, feedback)
|
|
5
|
+
Author-email: "Snowflake, Inc." <support@snowflake.com>
|
|
6
|
+
License: See LICENSE
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: cortex,cortex-agent,openapi,sdk,snowflake
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Requires-Dist: anyio>=4.0
|
|
14
|
+
Requires-Dist: httpx-sse>=0.4
|
|
15
|
+
Requires-Dist: httpx>=0.27
|
|
16
|
+
Requires-Dist: mcp<2,>=1.0
|
|
17
|
+
Requires-Dist: pydantic>=2.0
|
|
18
|
+
Requires-Dist: snowflake-connector-python[secure-local-storage]<5,>=4.7.1
|
|
19
|
+
Requires-Dist: typing-extensions>=4.0
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: datamodel-code-generator>=0.28; extra == 'dev'
|
|
22
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-asyncio>=0.20.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-timeout>=2.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Snowflake Cortex Agent SDK for Python
|
|
30
|
+
|
|
31
|
+
The SDK centers on conversations, durable turns, and completed responses. It
|
|
32
|
+
uses background runs internally while hiding run and thread bookkeeping.
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from cortex_agent_sdk import (
|
|
36
|
+
AgentResponse,
|
|
37
|
+
Conversation,
|
|
38
|
+
ConversationMessage,
|
|
39
|
+
CortexAgentClient,
|
|
40
|
+
Turn,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
client: CortexAgentClient = CortexAgentClient(account="my_account", auth="<token>")
|
|
44
|
+
conversation: Conversation = client.conversations.create(
|
|
45
|
+
origin_application="cortex_agent_sdk",
|
|
46
|
+
agent={"type": "inline", "spec": {"models": {"orchestration": "auto"}}},
|
|
47
|
+
)
|
|
48
|
+
turn: Turn = conversation.send("What is Snowflake Arctic?")
|
|
49
|
+
answer: AgentResponse = turn.result()
|
|
50
|
+
print(answer.text)
|
|
51
|
+
|
|
52
|
+
history: list[ConversationMessage] = conversation.history()
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Set a default agent when creating a conversation. A send can override it for
|
|
56
|
+
one turn when needed:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
inline_turn: Turn = conversation.send(
|
|
60
|
+
"Summarize the context.",
|
|
61
|
+
agent={"type": "inline", "spec": {"models": {"orchestration": "auto"}}},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
data_turn: Turn = conversation.send(
|
|
65
|
+
"Which products grew fastest?",
|
|
66
|
+
agent={
|
|
67
|
+
"type": "data",
|
|
68
|
+
"spec": {"database": "ANALYTICS", "schema": "PUBLIC", "name": "SALES_AGENT"},
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
coding_turn: Turn = conversation.send(
|
|
73
|
+
"Fix the failing test.",
|
|
74
|
+
agent={
|
|
75
|
+
"type": "coding",
|
|
76
|
+
"spec": {
|
|
77
|
+
"models": {"orchestration": "claude-sonnet-4-5"},
|
|
78
|
+
"permission_policy": "always_allow",
|
|
79
|
+
"workspace_mounts": [{"name": "USER$MY_USER.PUBLIC.DEFAULT$"}],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use `turn.events()` for event-level progress and `turn.cancel()` to stop a run.
|
|
86
|
+
|
|
87
|
+
The asynchronous API mirrors the sync API:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from cortex_agent_sdk import AgentResponse, AsyncConversation, AsyncCortexAgentClient, AsyncTurn
|
|
91
|
+
|
|
92
|
+
async with AsyncCortexAgentClient(account="my_account", auth="<token>") as client:
|
|
93
|
+
conversation: AsyncConversation = await client.conversations.create(
|
|
94
|
+
origin_application="cortex_agent_sdk", agent={"type": "inline", "spec": {}}
|
|
95
|
+
)
|
|
96
|
+
turn: AsyncTurn = await conversation.send("Analyze this data.")
|
|
97
|
+
answer: AgentResponse = await turn.result()
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The root client exposes `conversations` and `feedback`. Advanced streaming and
|
|
101
|
+
explicit run/thread management live under
|
|
102
|
+
`cortex_agent_sdk.api`:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from cortex_agent_sdk.api import CortexAgentClient
|
|
106
|
+
|
|
107
|
+
api_client: CortexAgentClient = CortexAgentClient(
|
|
108
|
+
account="my_account",
|
|
109
|
+
auth="<token>",
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Authentication headers are rebuilt for every attempt. `refresh_auth` runs only
|
|
114
|
+
for recognized token/session expiry responses; by default the SDK refreshes once
|
|
115
|
+
and replays the request once. SDK-generated errors do not include credential
|
|
116
|
+
values.
|
|
117
|
+
|
|
118
|
+
Requires Python 3.10 or newer.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Snowflake Cortex Agent SDK for Python
|
|
2
|
+
|
|
3
|
+
The SDK centers on conversations, durable turns, and completed responses. It
|
|
4
|
+
uses background runs internally while hiding run and thread bookkeeping.
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from cortex_agent_sdk import (
|
|
8
|
+
AgentResponse,
|
|
9
|
+
Conversation,
|
|
10
|
+
ConversationMessage,
|
|
11
|
+
CortexAgentClient,
|
|
12
|
+
Turn,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
client: CortexAgentClient = CortexAgentClient(account="my_account", auth="<token>")
|
|
16
|
+
conversation: Conversation = client.conversations.create(
|
|
17
|
+
origin_application="cortex_agent_sdk",
|
|
18
|
+
agent={"type": "inline", "spec": {"models": {"orchestration": "auto"}}},
|
|
19
|
+
)
|
|
20
|
+
turn: Turn = conversation.send("What is Snowflake Arctic?")
|
|
21
|
+
answer: AgentResponse = turn.result()
|
|
22
|
+
print(answer.text)
|
|
23
|
+
|
|
24
|
+
history: list[ConversationMessage] = conversation.history()
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Set a default agent when creating a conversation. A send can override it for
|
|
28
|
+
one turn when needed:
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
inline_turn: Turn = conversation.send(
|
|
32
|
+
"Summarize the context.",
|
|
33
|
+
agent={"type": "inline", "spec": {"models": {"orchestration": "auto"}}},
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
data_turn: Turn = conversation.send(
|
|
37
|
+
"Which products grew fastest?",
|
|
38
|
+
agent={
|
|
39
|
+
"type": "data",
|
|
40
|
+
"spec": {"database": "ANALYTICS", "schema": "PUBLIC", "name": "SALES_AGENT"},
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
coding_turn: Turn = conversation.send(
|
|
45
|
+
"Fix the failing test.",
|
|
46
|
+
agent={
|
|
47
|
+
"type": "coding",
|
|
48
|
+
"spec": {
|
|
49
|
+
"models": {"orchestration": "claude-sonnet-4-5"},
|
|
50
|
+
"permission_policy": "always_allow",
|
|
51
|
+
"workspace_mounts": [{"name": "USER$MY_USER.PUBLIC.DEFAULT$"}],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use `turn.events()` for event-level progress and `turn.cancel()` to stop a run.
|
|
58
|
+
|
|
59
|
+
The asynchronous API mirrors the sync API:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from cortex_agent_sdk import AgentResponse, AsyncConversation, AsyncCortexAgentClient, AsyncTurn
|
|
63
|
+
|
|
64
|
+
async with AsyncCortexAgentClient(account="my_account", auth="<token>") as client:
|
|
65
|
+
conversation: AsyncConversation = await client.conversations.create(
|
|
66
|
+
origin_application="cortex_agent_sdk", agent={"type": "inline", "spec": {}}
|
|
67
|
+
)
|
|
68
|
+
turn: AsyncTurn = await conversation.send("Analyze this data.")
|
|
69
|
+
answer: AgentResponse = await turn.result()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The root client exposes `conversations` and `feedback`. Advanced streaming and
|
|
73
|
+
explicit run/thread management live under
|
|
74
|
+
`cortex_agent_sdk.api`:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from cortex_agent_sdk.api import CortexAgentClient
|
|
78
|
+
|
|
79
|
+
api_client: CortexAgentClient = CortexAgentClient(
|
|
80
|
+
account="my_account",
|
|
81
|
+
auth="<token>",
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Authentication headers are rebuilt for every attempt. `refresh_auth` runs only
|
|
86
|
+
for recognized token/session expiry responses; by default the SDK refreshes once
|
|
87
|
+
and replays the request once. SDK-generated errors do not include credential
|
|
88
|
+
values.
|
|
89
|
+
|
|
90
|
+
Requires Python 3.10 or newer.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Snowflake Cortex Agent SDK (Python).
|
|
2
|
+
|
|
3
|
+
Sync::
|
|
4
|
+
|
|
5
|
+
from cortex_agent_sdk import AgentResponse, Conversation, CortexAgentClient, Turn
|
|
6
|
+
|
|
7
|
+
client = CortexAgentClient(account="myacct", auth="<pat>")
|
|
8
|
+
conversation: Conversation = client.conversations.create(
|
|
9
|
+
origin_application="cortex_agent_sdk", agent={"type": "inline", "spec": {}}
|
|
10
|
+
)
|
|
11
|
+
turn: Turn = conversation.send("What is Snowflake Arctic?")
|
|
12
|
+
answer: AgentResponse = turn.result()
|
|
13
|
+
print(answer.text)
|
|
14
|
+
|
|
15
|
+
Async::
|
|
16
|
+
|
|
17
|
+
import asyncio
|
|
18
|
+
from cortex_agent_sdk import AsyncConversation, AsyncCortexAgentClient
|
|
19
|
+
|
|
20
|
+
async def main():
|
|
21
|
+
async with AsyncCortexAgentClient(account="myacct", auth="<pat>") as client:
|
|
22
|
+
conversation: AsyncConversation = await client.conversations.create(
|
|
23
|
+
origin_application="cortex_agent_sdk", agent={"type": "inline", "spec": {}}
|
|
24
|
+
)
|
|
25
|
+
turn: AsyncTurn = await conversation.send("What is Snowflake Arctic?")
|
|
26
|
+
answer: AgentResponse = await turn.result()
|
|
27
|
+
print(answer.text)
|
|
28
|
+
|
|
29
|
+
asyncio.run(main())
|
|
30
|
+
|
|
31
|
+
Start with ``docs/01-getting-started.md``.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
from ._request_options import RequestOptions
|
|
37
|
+
from ._transport import AuthRefreshContext, RetryPolicy
|
|
38
|
+
from ._version import __title__, __version__
|
|
39
|
+
from .auth import (
|
|
40
|
+
Authenticator,
|
|
41
|
+
CallableAuth,
|
|
42
|
+
KeyPairJwtAuth,
|
|
43
|
+
OAuthAuth,
|
|
44
|
+
PatAuth,
|
|
45
|
+
SnowflakeSessionTokenAuth,
|
|
46
|
+
SnowflakeTokenAuth,
|
|
47
|
+
SnowflakeTokenType,
|
|
48
|
+
)
|
|
49
|
+
from .conversation import (
|
|
50
|
+
AgentSpec,
|
|
51
|
+
AsyncConversation,
|
|
52
|
+
CodingAgentSpec,
|
|
53
|
+
Conversation,
|
|
54
|
+
ConversationInput,
|
|
55
|
+
ConversationMessage,
|
|
56
|
+
DataAgentSpec,
|
|
57
|
+
InlineAgentSpec,
|
|
58
|
+
)
|
|
59
|
+
from .errors import (
|
|
60
|
+
APIConnectionAbortedError,
|
|
61
|
+
APIConnectionError,
|
|
62
|
+
APIStatusError,
|
|
63
|
+
APITimeoutError,
|
|
64
|
+
AuthenticationError,
|
|
65
|
+
AuthRefreshFailureContext,
|
|
66
|
+
BadRequestError,
|
|
67
|
+
ConflictError,
|
|
68
|
+
CortexAgentAPIError,
|
|
69
|
+
CortexAgentError,
|
|
70
|
+
InternalServerError,
|
|
71
|
+
NotFoundError,
|
|
72
|
+
PermissionDeniedError,
|
|
73
|
+
RateLimitError,
|
|
74
|
+
UnprocessableEntityError,
|
|
75
|
+
)
|
|
76
|
+
from .public_client import AsyncCortexAgentClient, CortexAgentClient
|
|
77
|
+
from .turn import AsyncTurn, Turn
|
|
78
|
+
from .views.agent_response import AgentResponseView as AgentResponse
|
|
79
|
+
|
|
80
|
+
__all__ = [
|
|
81
|
+
# Core clients + config
|
|
82
|
+
"AgentSpec",
|
|
83
|
+
"AgentResponse",
|
|
84
|
+
"AuthRefreshContext",
|
|
85
|
+
"AsyncConversation",
|
|
86
|
+
"AsyncCortexAgentClient",
|
|
87
|
+
"AsyncTurn",
|
|
88
|
+
"Conversation",
|
|
89
|
+
"ConversationInput",
|
|
90
|
+
"ConversationMessage",
|
|
91
|
+
"CodingAgentSpec",
|
|
92
|
+
"DataAgentSpec",
|
|
93
|
+
"InlineAgentSpec",
|
|
94
|
+
"CortexAgentClient",
|
|
95
|
+
"RequestOptions",
|
|
96
|
+
"RetryPolicy",
|
|
97
|
+
"Turn",
|
|
98
|
+
# Auth
|
|
99
|
+
"Authenticator",
|
|
100
|
+
"CallableAuth",
|
|
101
|
+
"KeyPairJwtAuth",
|
|
102
|
+
"OAuthAuth",
|
|
103
|
+
"PatAuth",
|
|
104
|
+
"SnowflakeSessionTokenAuth",
|
|
105
|
+
"SnowflakeTokenAuth",
|
|
106
|
+
"SnowflakeTokenType",
|
|
107
|
+
# Errors
|
|
108
|
+
"APIConnectionAbortedError",
|
|
109
|
+
"APIConnectionError",
|
|
110
|
+
"APIStatusError",
|
|
111
|
+
"APITimeoutError",
|
|
112
|
+
"AuthRefreshFailureContext",
|
|
113
|
+
"AuthenticationError",
|
|
114
|
+
"BadRequestError",
|
|
115
|
+
"ConflictError",
|
|
116
|
+
"CortexAgentAPIError",
|
|
117
|
+
"CortexAgentError",
|
|
118
|
+
"InternalServerError",
|
|
119
|
+
"NotFoundError",
|
|
120
|
+
"PermissionDeniedError",
|
|
121
|
+
"RateLimitError",
|
|
122
|
+
"UnprocessableEntityError",
|
|
123
|
+
# Metadata
|
|
124
|
+
"__title__",
|
|
125
|
+
"__version__",
|
|
126
|
+
]
|
|
@@ -55,7 +55,9 @@ from .errors import (
|
|
|
55
55
|
APIConnectionAbortedError,
|
|
56
56
|
APIConnectionError,
|
|
57
57
|
APITimeoutError,
|
|
58
|
+
AuthRefreshFailureContext,
|
|
58
59
|
CortexAgentError,
|
|
60
|
+
attach_auth_refresh_failure_context,
|
|
59
61
|
create_api_error,
|
|
60
62
|
)
|
|
61
63
|
|
|
@@ -84,8 +86,11 @@ class BaseClient:
|
|
|
84
86
|
) -> None:
|
|
85
87
|
if base_url is None and account is None:
|
|
86
88
|
raise CortexAgentError("Either `account` or `base_url` is required.")
|
|
89
|
+
# Account identifiers may contain underscores, but DNS host labels use
|
|
90
|
+
# Snowflake's canonical hyphenated form.
|
|
91
|
+
account_host = account.replace("_", "-") if account is not None else None
|
|
87
92
|
self.base_url = _validate_base_url(
|
|
88
|
-
(base_url or f"https://{
|
|
93
|
+
(base_url or f"https://{account_host}.snowflakecomputing.com").rstrip("/")
|
|
89
94
|
)
|
|
90
95
|
self.auth: Authenticator = coerce_authenticator(auth)
|
|
91
96
|
self.retry_policy = merge_retry_policies(None, retry_policy)
|
|
@@ -540,10 +545,18 @@ class SyncAPIClient(BaseClient):
|
|
|
540
545
|
try:
|
|
541
546
|
self.refresh_auth(refresh_context)
|
|
542
547
|
except Exception as exc:
|
|
543
|
-
|
|
548
|
+
api_error = create_api_error(
|
|
544
549
|
response.status_code,
|
|
545
550
|
refresh_context.request_id,
|
|
546
551
|
refresh_context.response_body,
|
|
552
|
+
)
|
|
553
|
+
raise attach_auth_refresh_failure_context(
|
|
554
|
+
api_error,
|
|
555
|
+
AuthRefreshFailureContext(
|
|
556
|
+
attempt=refresh_context.attempt,
|
|
557
|
+
provider=_auth_provider_name(self.auth),
|
|
558
|
+
request_id=refresh_context.request_id,
|
|
559
|
+
),
|
|
547
560
|
) from exc
|
|
548
561
|
auth_refresh_attempt += 1
|
|
549
562
|
continue
|
|
@@ -693,10 +706,18 @@ class AsyncAPIClient(BaseClient):
|
|
|
693
706
|
try:
|
|
694
707
|
await self._call_refresh_auth(refresh_context)
|
|
695
708
|
except Exception as exc:
|
|
696
|
-
|
|
709
|
+
api_error = create_api_error(
|
|
697
710
|
response.status_code,
|
|
698
711
|
refresh_context.request_id,
|
|
699
712
|
refresh_context.response_body,
|
|
713
|
+
)
|
|
714
|
+
raise attach_auth_refresh_failure_context(
|
|
715
|
+
api_error,
|
|
716
|
+
AuthRefreshFailureContext(
|
|
717
|
+
attempt=refresh_context.attempt,
|
|
718
|
+
provider=_auth_provider_name(self.auth),
|
|
719
|
+
request_id=refresh_context.request_id,
|
|
720
|
+
),
|
|
700
721
|
) from exc
|
|
701
722
|
auth_refresh_attempt += 1
|
|
702
723
|
continue
|
|
@@ -711,11 +732,16 @@ class AsyncAPIClient(BaseClient):
|
|
|
711
732
|
await asyncio.sleep(delay)
|
|
712
733
|
|
|
713
734
|
|
|
714
|
-
#: Hosts where plaintext HTTP is acceptable
|
|
715
|
-
#:
|
|
735
|
+
#: Hosts where plaintext HTTP is acceptable in local development. Local GS uses
|
|
736
|
+
#: account-qualified ``*.local`` names (for example ``snowflake.reg.local``),
|
|
737
|
+
#: while public endpoints must remain TLS-only.
|
|
716
738
|
_LOCAL_HOSTS = frozenset({"localhost", "127.0.0.1", "::1", "[::1]"})
|
|
717
739
|
|
|
718
740
|
|
|
741
|
+
def _is_local_host(hostname: str | None) -> bool:
|
|
742
|
+
return hostname in _LOCAL_HOSTS or (hostname is not None and hostname.endswith(".local"))
|
|
743
|
+
|
|
744
|
+
|
|
719
745
|
def _validate_base_url(base_url: str) -> str:
|
|
720
746
|
"""Reject a base URL that would put the credential on the wire in clear text.
|
|
721
747
|
|
|
@@ -728,7 +754,7 @@ def _validate_base_url(base_url: str) -> str:
|
|
|
728
754
|
parsed = urlparse(base_url)
|
|
729
755
|
if parsed.scheme == "https":
|
|
730
756
|
return base_url
|
|
731
|
-
if parsed.scheme == "http" and parsed.hostname
|
|
757
|
+
if parsed.scheme == "http" and _is_local_host(parsed.hostname):
|
|
732
758
|
return base_url
|
|
733
759
|
if not parsed.scheme:
|
|
734
760
|
raise CortexAgentError(
|
|
@@ -738,11 +764,16 @@ def _validate_base_url(base_url: str) -> str:
|
|
|
738
764
|
f"base_url must use https — got {parsed.scheme!r} in {base_url!r}. Every "
|
|
739
765
|
f"request sends a credential in an Authorization header, so a plaintext "
|
|
740
766
|
f"endpoint would expose it to anyone on the network path. "
|
|
741
|
-
|
|
742
|
-
|
|
767
|
+
"(http:// is allowed for local hosts only: localhost, loopback addresses, "
|
|
768
|
+
"or a *.local development endpoint.)"
|
|
743
769
|
)
|
|
744
770
|
|
|
745
771
|
|
|
772
|
+
def _auth_provider_name(auth: Authenticator) -> str:
|
|
773
|
+
name = type(auth).__name__
|
|
774
|
+
return name if name != "object" else "Authenticator"
|
|
775
|
+
|
|
776
|
+
|
|
746
777
|
def _parse_retry_after(headers: httpx.Headers) -> float | None:
|
|
747
778
|
"""Seconds from ``retry-after-ms`` (preferred), ``retry-after``, or an HTTP date."""
|
|
748
779
|
ms = headers.get("retry-after-ms")
|