persona-sdk-python 0.2.18__tar.gz → 0.2.19__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.
Files changed (33) hide show
  1. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/PKG-INFO +1 -1
  2. persona_sdk_python-0.2.19/bitbucket-pipelines.yml +18 -0
  3. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/__init__.py +3 -0
  4. persona_sdk_python-0.2.19/persona_sdk/api/human_tasks.py +55 -0
  5. persona_sdk_python-0.2.19/persona_sdk/api/workflows.py +234 -0
  6. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/pyproject.toml +1 -1
  7. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/uv.lock +1 -9
  8. persona_sdk_python-0.2.18/bitbucket-pipelines.yml +0 -17
  9. persona_sdk_python-0.2.18/persona_sdk/api/workflows.py +0 -72
  10. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/.gitignore +0 -0
  11. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/DEPLOY.md +0 -0
  12. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/README.md +0 -0
  13. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/_serde.py +0 -0
  14. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/__init__.py +0 -0
  15. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/agents.py +0 -0
  16. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/credentials.py +0 -0
  17. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/features.py +0 -0
  18. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/knowledge_bases.py +0 -0
  19. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/known_models.py +0 -0
  20. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/missions.py +0 -0
  21. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/projects.py +0 -0
  22. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/service_prices.py +0 -0
  23. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/sessions.py +0 -0
  24. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/api/triggers.py +0 -0
  25. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/auth/__init__.py +0 -0
  26. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/auth/api_key_auth.py +0 -0
  27. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/auth/base.py +0 -0
  28. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/auth/bearer_token_auth.py +0 -0
  29. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/client.py +0 -0
  30. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/runners/__init__.py +0 -0
  31. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/runners/agent_runner.py +0 -0
  32. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/runners/resource_retriever.py +0 -0
  33. {persona_sdk_python-0.2.18 → persona_sdk_python-0.2.19}/persona_sdk/runners/tool_invoker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: persona-sdk-python
3
- Version: 0.2.18
3
+ Version: 0.2.19
4
4
  Summary: Async Python SDK for the Persona AI platform
5
5
  Project-URL: Homepage, https://persona.applica.guru
6
6
  Project-URL: Repository, https://bitbucket.org/applicaguru/persona-sdk-python
@@ -0,0 +1,18 @@
1
+ image: python:3.12
2
+
3
+ pipelines:
4
+ branches:
5
+ main:
6
+ - step:
7
+ name: Publish to PyPI
8
+ caches:
9
+ - pip
10
+ script:
11
+ - apt-get update && apt-get install -y git
12
+ - pip install build twine
13
+ - export VERSION=0.2.$BITBUCKET_BUILD_NUMBER
14
+ - sed -i "s/^version = .*/version = \"$VERSION\"/" pyproject.toml
15
+ - python -m build
16
+ - twine upload dist/* -u __token__ -p $PYPI_TOKEN
17
+ - git tag -a $VERSION -m "$VERSION"
18
+ - git push origin $VERSION
@@ -11,6 +11,7 @@ from persona_sdk.api.service_prices import ServicePricesApi
11
11
  from persona_sdk.api.sessions import SessionsApi
12
12
  from persona_sdk.api.triggers import TriggersApi
13
13
  from persona_sdk.api.workflows import WorkflowsApi
14
+ from persona_sdk.api.human_tasks import HumanTasksApi
14
15
  from persona_sdk.auth import (
15
16
  ApiKeyAuthenticationProvider,
16
17
  AuthenticationProvider,
@@ -56,6 +57,7 @@ __all__ = [
56
57
  "SessionsApi",
57
58
  "TriggersApi",
58
59
  "WorkflowsApi",
60
+ "HumanTasksApi",
59
61
  # Domain models (re-exported from persona-models)
60
62
  "Paginated",
61
63
  "AgentConfiguration",
@@ -131,6 +133,7 @@ class PersonaSdk:
131
133
  )
132
134
  self.agents = AgentsApi(self.client)
133
135
  self.workflows = WorkflowsApi(self.workflows_client)
136
+ self.human_tasks = HumanTasksApi(self.workflows_client)
134
137
  self.triggers = TriggersApi(self.client)
135
138
  self.sessions = SessionsApi(self.client)
136
139
  self.credentials = CredentialsApi(self.client)
@@ -0,0 +1,55 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from persona_sdk.client import PersonaClient
6
+
7
+
8
+ class HumanTasksApi:
9
+ """
10
+ Human-in-the-loop tasks. A task is created when a workflow step
11
+ suspends waiting for a human (a declared ``human`` node or an agent
12
+ escalation); responding to it resumes the run.
13
+
14
+ Lives on the workflows service (same client as ``WorkflowsApi``).
15
+ Tasks are returned as plain dicts — the contract is owned by the
16
+ workflows service and intentionally not constrained here.
17
+ """
18
+
19
+ def __init__(self, client: PersonaClient):
20
+ self._client = client
21
+
22
+ async def list(
23
+ self,
24
+ status: str | None = "pending",
25
+ assignee: str | None = None,
26
+ workflow_id: str | None = None,
27
+ execution_id: str | None = None,
28
+ page: int = 1,
29
+ size: int = 50,
30
+ ) -> dict[str, Any]:
31
+ """The project's human-task inbox (``Paginated[HumanTask]`` shape)."""
32
+ params: dict[str, Any] = {"page": page, "size": size}
33
+ if status:
34
+ params["status"] = status
35
+ if assignee:
36
+ params["assignee"] = assignee
37
+ if workflow_id:
38
+ params["workflowId"] = workflow_id
39
+ if execution_id:
40
+ params["executionId"] = execution_id
41
+ return await self._client.get("/human-tasks", params=params)
42
+
43
+ async def respond(
44
+ self,
45
+ human_task_id: str,
46
+ response: Any,
47
+ responded_by: str | None = None,
48
+ ) -> dict[str, Any]:
49
+ """Answer a pending human task and resume the suspended execution."""
50
+ body: dict[str, Any] = {"response": response}
51
+ if responded_by:
52
+ body["respondedBy"] = responded_by
53
+ return await self._client.post(
54
+ f"/human-tasks/{human_task_id}/respond", json=body
55
+ )
@@ -0,0 +1,234 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from persona_models.common import Paginated
6
+ from persona_models.workflows import Workflow
7
+
8
+ from persona_sdk._serde import dump_payload
9
+ from persona_sdk.client import PersonaClient
10
+
11
+
12
+ class WorkflowsApi:
13
+ def __init__(self, client: PersonaClient):
14
+ self._client = client
15
+
16
+ async def list(
17
+ self, keyword: str | None = None, page: int = 1, size: int = 20
18
+ ) -> Paginated[Workflow]:
19
+ params: dict[str, Any] = {"page": page, "size": size}
20
+ if keyword:
21
+ params["keyword"] = keyword
22
+ data = await self._client.get("/workflows", params=params)
23
+ return Paginated[Workflow].model_validate(data)
24
+
25
+ async def get(self, workflow_id: str) -> Workflow:
26
+ data = await self._client.get(f"/workflows/{workflow_id}")
27
+ return Workflow.model_validate(data)
28
+
29
+ async def create(self, workflow: Workflow | dict[str, Any]) -> Workflow:
30
+ data = await self._client.post("/workflows", json=dump_payload(workflow))
31
+ return Workflow.model_validate(data)
32
+
33
+ async def update(
34
+ self, workflow_id: str, workflow: Workflow | dict[str, Any]
35
+ ) -> Workflow:
36
+ data = await self._client.put(
37
+ f"/workflows/{workflow_id}", json=dump_payload(workflow)
38
+ )
39
+ return Workflow.model_validate(data)
40
+
41
+ async def delete(self, workflow_id: str) -> dict[str, Any]:
42
+ return await self._client.delete(f"/workflows/{workflow_id}")
43
+
44
+ # ------------------------------------------------------------------ #
45
+ # Executions
46
+ #
47
+ # Executions, human tasks, traces and stats are returned as plain
48
+ # dicts: the execution contract is owned by the workflows service and
49
+ # intentionally not constrained here.
50
+ # ------------------------------------------------------------------ #
51
+
52
+ def _run_body(
53
+ self,
54
+ data: dict[str, Any] | None,
55
+ user_id: str | None,
56
+ callback_url: str | None,
57
+ events_hook: str | None,
58
+ ) -> dict[str, Any]:
59
+ body: dict[str, Any] = {"initialData": data or {}}
60
+ if user_id:
61
+ body["userId"] = user_id
62
+ if callback_url:
63
+ body["callbackUrl"] = callback_url
64
+ if events_hook:
65
+ body["eventsHook"] = events_hook
66
+ return body
67
+
68
+ async def execute(
69
+ self,
70
+ workflow_id: str,
71
+ data: dict[str, Any] | None = None,
72
+ user_id: str | None = None,
73
+ callback_url: str | None = None,
74
+ events_hook: str | None = None,
75
+ ) -> dict[str, Any]:
76
+ """Run a workflow synchronously (returns when terminal or suspended)."""
77
+ return await self._client.post(
78
+ f"/workflows/{workflow_id}/executions",
79
+ json=self._run_body(data, user_id, callback_url, events_hook),
80
+ )
81
+
82
+ async def queue(
83
+ self,
84
+ workflow_id: str,
85
+ data: dict[str, Any] | None = None,
86
+ user_id: str | None = None,
87
+ callback_url: str | None = None,
88
+ events_hook: str | None = None,
89
+ ) -> dict[str, Any]:
90
+ """Queue a workflow for asynchronous execution (returns an ``Execution``)."""
91
+ return await self._client.post(
92
+ f"/workflows/{workflow_id}/executions/queue",
93
+ json=self._run_body(data, user_id, callback_url, events_hook),
94
+ )
95
+
96
+ async def list_executions(
97
+ self, workflow_id: str, page: int = 1, size: int = 20
98
+ ) -> dict[str, Any]:
99
+ """List executions for a workflow (``Paginated[Execution]`` shape)."""
100
+ params: dict[str, Any] = {"page": page, "size": size}
101
+ return await self._client.get(
102
+ f"/workflows/{workflow_id}/executions", params=params
103
+ )
104
+
105
+ async def get_execution(
106
+ self, workflow_id: str, execution_id: str
107
+ ) -> dict[str, Any]:
108
+ """Get a single execution (run) with its steps, status and outputs."""
109
+ return await self._client.get(
110
+ f"/workflows/{workflow_id}/executions/{execution_id}"
111
+ )
112
+
113
+ async def list_runs(
114
+ self,
115
+ status: str | None = None,
116
+ workflow_id: str | None = None,
117
+ date_from: str | None = None,
118
+ date_to: str | None = None,
119
+ page: int = 1,
120
+ size: int = 20,
121
+ ) -> dict[str, Any]:
122
+ """List runs across all workflows in the project."""
123
+ params: dict[str, Any] = {"page": page, "size": size}
124
+ if status:
125
+ params["status"] = status
126
+ if workflow_id:
127
+ params["workflowId"] = workflow_id
128
+ if date_from:
129
+ params["dateFrom"] = date_from
130
+ if date_to:
131
+ params["dateTo"] = date_to
132
+ return await self._client.get("/executions", params=params)
133
+
134
+ async def cancel_execution(
135
+ self, workflow_id: str, execution_id: str
136
+ ) -> dict[str, Any]:
137
+ """Request cancellation of a running/waiting execution."""
138
+ return await self._client.post(
139
+ f"/workflows/{workflow_id}/executions/{execution_id}/cancel", json={}
140
+ )
141
+
142
+ async def rerun_execution(
143
+ self,
144
+ workflow_id: str,
145
+ execution_id: str,
146
+ from_node_id: str,
147
+ mode: str = "reuse_outputs",
148
+ user_id: str | None = None,
149
+ ) -> dict[str, Any]:
150
+ """Re-run an execution from a given node. mode: 'reuse_outputs' | 'fresh'."""
151
+ body: dict[str, Any] = {"fromNodeId": from_node_id, "mode": mode}
152
+ if user_id:
153
+ body["userId"] = user_id
154
+ return await self._client.post(
155
+ f"/workflows/{workflow_id}/executions/{execution_id}/rerun", json=body
156
+ )
157
+
158
+ async def dry_run_node(
159
+ self,
160
+ workflow_id: str,
161
+ node_id: str,
162
+ inputs: dict[str, Any] | None = None,
163
+ user_id: str | None = None,
164
+ ) -> dict[str, Any]:
165
+ """Execute a single node in isolation with the given inputs (debugging)."""
166
+ body: dict[str, Any] = {"inputs": inputs or {}}
167
+ if user_id:
168
+ body["userId"] = user_id
169
+ return await self._client.post(
170
+ f"/workflows/{workflow_id}/nodes/{node_id}/dry-run", json=body
171
+ )
172
+
173
+ async def get_step_trace(
174
+ self,
175
+ workflow_id: str,
176
+ execution_id: str,
177
+ step_id: str,
178
+ page: int = 1,
179
+ size: int = 200,
180
+ ) -> dict[str, Any]:
181
+ """Normalized action trace of an agent step (reasoning, tool calls, messages)."""
182
+ params: dict[str, Any] = {"page": page, "size": size}
183
+ return await self._client.get(
184
+ f"/workflows/{workflow_id}/executions/{execution_id}/steps/{step_id}/trace",
185
+ params=params,
186
+ )
187
+
188
+ # ------------------------------------------------------------------ #
189
+ # Stats
190
+ # ------------------------------------------------------------------ #
191
+
192
+ async def stats_overview(self) -> dict[str, Any]:
193
+ return await self._client.get("/stats/overview")
194
+
195
+ async def stats_executions_timeseries(
196
+ self,
197
+ date_from: str | None = None,
198
+ date_to: str | None = None,
199
+ workflow_id: str | None = None,
200
+ bucket: str = "day",
201
+ ) -> Any:
202
+ params: dict[str, Any] = {"bucket": bucket}
203
+ if date_from:
204
+ params["dateFrom"] = date_from
205
+ if date_to:
206
+ params["dateTo"] = date_to
207
+ if workflow_id:
208
+ params["workflowId"] = workflow_id
209
+ return await self._client.get("/stats/executions/timeseries", params=params)
210
+
211
+ async def stats_failing_nodes(
212
+ self,
213
+ date_from: str | None = None,
214
+ workflow_id: str | None = None,
215
+ limit: int = 10,
216
+ ) -> Any:
217
+ params: dict[str, Any] = {"limit": limit}
218
+ if date_from:
219
+ params["dateFrom"] = date_from
220
+ if workflow_id:
221
+ params["workflowId"] = workflow_id
222
+ return await self._client.get(
223
+ "/stats/executions/failing-nodes", params=params
224
+ )
225
+
226
+ async def stats_human_response_times(
227
+ self, date_from: str | None = None
228
+ ) -> dict[str, Any]:
229
+ params: dict[str, Any] = {}
230
+ if date_from:
231
+ params["dateFrom"] = date_from
232
+ return await self._client.get(
233
+ "/stats/human-tasks/response-times", params=params
234
+ )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "persona-sdk-python"
3
- version = "0.2.18"
3
+ version = "0.2.19"
4
4
  description = "Async Python SDK for the Persona AI platform"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -116,7 +116,7 @@ dependencies = [
116
116
  [package.metadata]
117
117
  requires-dist = [
118
118
  { name = "httpx", specifier = ">=0.27.0" },
119
- { name = "persona-models", specifier = ">=0.2.2" },
119
+ { name = "persona-models", specifier = ">=0.2.4" },
120
120
  ]
121
121
 
122
122
  [[package]]
@@ -226,14 +226,6 @@ wheels = [
226
226
  { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906 },
227
227
  { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607 },
228
228
  { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769 },
229
- { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441 },
230
- { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291 },
231
- { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632 },
232
- { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905 },
233
- { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495 },
234
- { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388 },
235
- { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879 },
236
- { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017 },
237
229
  { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351 },
238
230
  { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363 },
239
231
  { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615 },
@@ -1,17 +0,0 @@
1
- image: python:3.12
2
-
3
- pipelines:
4
- default:
5
- - step:
6
- name: Publish to PyPI
7
- caches:
8
- - pip
9
- script:
10
- - apt-get update && apt-get install -y git
11
- - pip install build twine
12
- - export VERSION=0.2.$BITBUCKET_BUILD_NUMBER
13
- - sed -i "s/^version = .*/version = \"$VERSION\"/" pyproject.toml
14
- - python -m build
15
- - twine upload dist/* -u __token__ -p $PYPI_TOKEN
16
- - git tag -a $VERSION -m "$VERSION"
17
- - git push origin $VERSION
@@ -1,72 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
-
5
- from persona_models.common import Paginated
6
- from persona_models.workflows import Workflow
7
-
8
- from persona_sdk._serde import dump_payload
9
- from persona_sdk.client import PersonaClient
10
-
11
-
12
- class WorkflowsApi:
13
- def __init__(self, client: PersonaClient):
14
- self._client = client
15
-
16
- async def list(
17
- self, keyword: str | None = None, page: int = 1, size: int = 20
18
- ) -> Paginated[Workflow]:
19
- params: dict[str, Any] = {"page": page, "size": size}
20
- if keyword:
21
- params["keyword"] = keyword
22
- data = await self._client.get("/workflows", params=params)
23
- return Paginated[Workflow].model_validate(data)
24
-
25
- async def get(self, workflow_id: str) -> Workflow:
26
- data = await self._client.get(f"/workflows/{workflow_id}")
27
- return Workflow.model_validate(data)
28
-
29
- async def create(self, workflow: Workflow | dict[str, Any]) -> Workflow:
30
- data = await self._client.post("/workflows", json=dump_payload(workflow))
31
- return Workflow.model_validate(data)
32
-
33
- async def update(
34
- self, workflow_id: str, workflow: Workflow | dict[str, Any]
35
- ) -> Workflow:
36
- data = await self._client.put(
37
- f"/workflows/{workflow_id}", json=dump_payload(workflow)
38
- )
39
- return Workflow.model_validate(data)
40
-
41
- async def delete(self, workflow_id: str) -> dict[str, Any]:
42
- return await self._client.delete(f"/workflows/{workflow_id}")
43
-
44
- async def execute(
45
- self, workflow_id: str, data: dict[str, Any] | None = None
46
- ) -> dict[str, Any]:
47
- """Execute a workflow synchronously.
48
-
49
- Returns the workflow ``Execution`` (``status``, ``steps``, ``output``,
50
- ``error``, ...) as a plain dict; the execution contract is owned by the
51
- workflows service and intentionally not constrained here.
52
- """
53
- return await self._client.post(
54
- f"/workflows/{workflow_id}/execute", json=data or {}
55
- )
56
-
57
- async def queue(
58
- self, workflow_id: str, data: dict[str, Any] | None = None
59
- ) -> dict[str, Any]:
60
- """Queue a workflow for asynchronous execution (returns an ``Execution``)."""
61
- return await self._client.post(
62
- f"/workflows/{workflow_id}/queue", json=data or {}
63
- )
64
-
65
- async def list_executions(
66
- self, workflow_id: str, page: int = 1, size: int = 20
67
- ) -> dict[str, Any]:
68
- """List executions for a workflow (``Paginated[Execution]`` shape)."""
69
- params: dict[str, Any] = {"page": page, "size": size}
70
- return await self._client.get(
71
- f"/workflows/{workflow_id}/executions", params=params
72
- )