getstack 2.0.0__tar.gz → 4.0.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.
- {getstack-2.0.0 → getstack-4.0.0}/.gitignore +11 -0
- getstack-4.0.0/CLAUDE.md +50 -0
- {getstack-2.0.0 → getstack-4.0.0}/PKG-INFO +43 -9
- {getstack-2.0.0 → getstack-4.0.0}/README.md +38 -8
- {getstack-2.0.0 → getstack-4.0.0}/pyproject.toml +34 -1
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/__init__.py +203 -170
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/__init__.py +1 -1
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/agents.py +13 -11
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/audit.py +4 -4
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/authority.py +94 -109
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/credentials.py +1 -3
- getstack-4.0.0/src/getstack/_async/delivery_methods.py +95 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/detector_config.py +9 -8
- getstack-4.0.0/src/getstack/_async/dropoffs.py +81 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/evidence_packs.py +6 -8
- getstack-4.0.0/src/getstack/_async/fleets.py +155 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/identity.py +30 -19
- getstack-4.0.0/src/getstack/_async/inbound_webhooks.py +60 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/intents.py +34 -24
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/llm.py +35 -19
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/missions.py +49 -21
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/notifications.py +14 -10
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/partner_connect.py +10 -10
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/partner_tenants.py +49 -27
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/passport_session.py +15 -8
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/passports.py +217 -103
- getstack-4.0.0/src/getstack/_async/pii_config.py +26 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/proxy.py +14 -10
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/reviews.py +1 -1
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/scan.py +10 -7
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/security_events.py +5 -7
- getstack-4.0.0/src/getstack/_async/services.py +78 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/skills.py +29 -25
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/team.py +5 -5
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_async/usage.py +2 -2
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_authority_request.py +1 -2
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/_fleet_key.py +6 -3
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/agent_auth.py +42 -33
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/agents.py +6 -6
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/audit.py +4 -4
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/auth.py +6 -10
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/authority.py +57 -82
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/browser_bootstrap.py +38 -28
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/client.py +18 -10
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/credentials.py +0 -1
- getstack-4.0.0/src/getstack/delivery_methods.py +92 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/detector_config.py +15 -18
- getstack-4.0.0/src/getstack/dropoffs.py +86 -0
- getstack-4.0.0/src/getstack/errors.py +143 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/evidence_packs.py +5 -8
- getstack-4.0.0/src/getstack/fleets.py +149 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/identity.py +28 -20
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/inbound_webhooks.py +26 -13
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/intents.py +48 -37
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/llm.py +37 -20
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/missions.py +95 -34
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/notifications.py +13 -9
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/partner_connect.py +9 -11
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/partner_tenants.py +51 -27
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/passport_header_verify.py +4 -7
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/passport_session.py +20 -10
- getstack-4.0.0/src/getstack/passports.py +749 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/pii_config.py +7 -19
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/proxy.py +20 -19
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/reviews.py +11 -10
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/scan.py +10 -7
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/security_events.py +4 -4
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/services.py +25 -27
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/sign_claim.py +2 -9
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/skills.py +27 -19
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/team.py +5 -5
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/types.py +4 -2
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/usage.py +2 -2
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/verify_offline.py +7 -3
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_authority.py +86 -66
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_delivery_methods.py +2 -2
- getstack-4.0.0/tests/test_dropoffs.py +119 -0
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_errors.py +1 -1
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_fleets.py +66 -18
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_identity_requirements.py +3 -4
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_inbound_webhooks.py +7 -5
- getstack-4.0.0/tests/test_mission_binding.py +378 -0
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_missions.py +2 -2
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_parity.py +119 -33
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_partner_signing.py +13 -5
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_sign_claim.py +1 -1
- getstack-2.0.0/CLAUDE.md +0 -77
- getstack-2.0.0/src/getstack/_async/delivery_methods.py +0 -85
- getstack-2.0.0/src/getstack/_async/dropoffs.py +0 -64
- getstack-2.0.0/src/getstack/_async/fleets.py +0 -82
- getstack-2.0.0/src/getstack/_async/inbound_webhooks.py +0 -47
- getstack-2.0.0/src/getstack/_async/pii_config.py +0 -38
- getstack-2.0.0/src/getstack/_async/services.py +0 -80
- getstack-2.0.0/src/getstack/delivery_methods.py +0 -85
- getstack-2.0.0/src/getstack/dropoffs.py +0 -59
- getstack-2.0.0/src/getstack/errors.py +0 -79
- getstack-2.0.0/src/getstack/fleets.py +0 -82
- getstack-2.0.0/src/getstack/passports.py +0 -502
- getstack-2.0.0/tests/test_dropoffs.py +0 -70
- {getstack-2.0.0 → getstack-4.0.0}/LICENSE +0 -0
- {getstack-2.0.0 → getstack-4.0.0}/scripts/verify_sign_claim_crosslang.py +0 -0
- {getstack-2.0.0 → getstack-4.0.0}/src/getstack/py.typed +0 -0
- {getstack-2.0.0 → getstack-4.0.0}/tests/test_evidence_packs.py +0 -0
|
@@ -92,3 +92,14 @@ scratchpad/
|
|
|
92
92
|
|
|
93
93
|
# Isolated test-only LangChain, CrewAI and AutoGen verification environment.
|
|
94
94
|
.tmp/fleet-framework-venv/
|
|
95
|
+
|
|
96
|
+
# Local verification output (benchmark, fleet and release evidence). Never commit.
|
|
97
|
+
/artifacts/
|
|
98
|
+
|
|
99
|
+
# Cleanup 2026-10: local-only files
|
|
100
|
+
.claude/settings.local.json
|
|
101
|
+
.tmp/
|
|
102
|
+
*.paint
|
|
103
|
+
*.zip
|
|
104
|
+
STATUS.md
|
|
105
|
+
design-qa.md
|
getstack-4.0.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# getstack (Python SDK)
|
|
2
|
+
|
|
3
|
+
The Python SDK, published to PyPI as `getstack` (MIT, Python 3.9+, built with hatchling from `pyproject.toml`). It is not a pnpm workspace member and has its own tooling. Runtime dependencies: `httpx`, `cryptography`, `pyjwt`, `cbor2`. It tracks the TypeScript SDK (`packages/sdk`) service for service.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
- `sdk-python/src/getstack/__init__.py`: the sync `Stack` and async `AsyncStack` clients, `__all__`, auth selection.
|
|
8
|
+
- Sync services, one module per REST domain in `sdk-python/src/getstack/` (`agents`, `passports`, `missions`, `fleets`, `authority`, `evidence_packs`, `llm`, `proxy`, `team`, `delivery_methods`, `detector_config`, `pii_config`, `partner_tenants`, `partner_connect`, and others).
|
|
9
|
+
- Async mirrors of the same services in `sdk-python/src/getstack/_async/`.
|
|
10
|
+
- `sdk-python/src/getstack/client.py`, `auth.py`, `agent_auth.py`, `credentials.py`, `browser_bootstrap.py`: HTTP clients and credential sources.
|
|
11
|
+
- `sdk-python/src/getstack/verify_offline.py`, `passport_header_verify.py`, `sign_claim.py`: offline Passport verification and customer-managed claim signing.
|
|
12
|
+
- `sdk-python/src/getstack/errors.py`: `StackError` with `NotFoundError`, `UnauthorizedError`, `ForbiddenError`, `ValidationError`, `PassportBlockedError`, `MissionEndedError`.
|
|
13
|
+
|
|
14
|
+
## Sync and async parity
|
|
15
|
+
|
|
16
|
+
Every service and method on `Stack` must also exist on `AsyncStack` (the async modules live under `sdk-python/src/getstack/_async/`). `sdk-python/tests/test_parity.py` is the guard: it asserts both clients expose the services in `EXPECTED_SERVICES` and the integration-critical methods in `EXPECTED_METHODS`, and that signatures such as `agents.register` match. When adding a service or method, add it to both clients and to those lists. Mirror new REST routes in `packages/sdk` too.
|
|
17
|
+
|
|
18
|
+
## Auth and offline crypto
|
|
19
|
+
|
|
20
|
+
- Credential resolution (`Stack.__init__`): a pre-built `_auth`, then `agent_id` (agent keypair mode, `AgentKeypairAuth`), then `api_key` or `STACK_API_KEY`, then `~/.stack/credentials.json` (OAuth refresh token written by the CLI), then an interactive browser bootstrap when the process has a TTY and is not CI. Otherwise a `ValueError` is raised.
|
|
21
|
+
- `verify_passport_offline` (`verify_offline.py`) mirrors the JS function: EdDSA via PyJWT, with `jwks_url` or `public_jwk`. It cannot see revocation.
|
|
22
|
+
- `sign_claim_envelope` (`sign_claim.py`) produces COSE_Sign1 for `customer_managed` agents and must stay byte-compatible with the TS SDK and the server verifier. `sdk-python/scripts/verify_sign_claim_crosslang.py` proves it by signing in Python and verifying with the JS code; run it from the repo root (needs the JS SDK's `node_modules` for `cbor-x`).
|
|
23
|
+
|
|
24
|
+
## Mission context manager
|
|
25
|
+
|
|
26
|
+
`stack.passports.mission(agent_id=..., intent=..., services=[...])` (and `async with` on `AsyncStack`) opens a Mission and its Passport in one call, submits checkpoints on a timer, checks out on exit, then completes the Mission. If the block raises, the Mission is revoked instead. Pass `mission_id="ms_..."` to bind an existing Mission, which is then left open on exit. `continuous_mission` rotates Passports under one Mission and raises `MissionEndedError` when the Mission ends. The TypeScript SDK has no equivalent context manager; keep keyword names aligned if one is added.
|
|
27
|
+
|
|
28
|
+
## Run and test
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cd sdk-python
|
|
32
|
+
python -m pip install -e ".[dev]" # pytest, ruff, mypy
|
|
33
|
+
ruff check . # lint, import order (rules in pyproject.toml)
|
|
34
|
+
ruff format --check . # formatting, line length 120
|
|
35
|
+
mypy src # strict typing of src/ only; tests are not type-checked
|
|
36
|
+
python -m pytest -q # same tests as `pnpm verify:python`
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Run the three checks with a Python 3.10+ interpreter (current mypy no longer runs on 3.9). Fix findings in the code; the only suppressions are narrow `# type: ignore[code]` comments in tests. The HTTP client returns untyped JSON (`Any`), so service methods wrap it in `cast("<return type>", ...)` to satisfy `warn_return_any`. A service class that defines a `list` method must annotate later signatures as `builtins.list[...]`.
|
|
40
|
+
|
|
41
|
+
The integration-guide smoke test (`scripts/smoke-test-integration-guides.py`, with `scripts/smoke-test-integration-guides-setup.mjs`) needs a local API (port 3001); `scripts/release.mjs` runs it during `/publish sdk-python` when the API is reachable and aborts the release on failure.
|
|
42
|
+
|
|
43
|
+
## Publishing
|
|
44
|
+
|
|
45
|
+
A change to this package must be released in the same session: bump `version` in `pyproject.toml` and run `/publish sdk-python <bump>`. That runs `scripts/release.mjs`, tags `sdk-python-v*`, and `publish-sdk-python.yml` uploads to PyPI. Do not run `twine` by hand. Versions are independent of the TypeScript SDK.
|
|
46
|
+
|
|
47
|
+
## Gotchas
|
|
48
|
+
|
|
49
|
+
- The grant field on the wire is `service_connection_id`. Notification rules use `/v1/notifications/channels` (`notifications`); delivery methods use `/v1/notifications/destinations` (`delivery_methods`).
|
|
50
|
+
- The monorepo's JS lockfile does not resolve Python dependencies.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: getstack
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Python SDK for STACK — trust infrastructure for AI agents
|
|
5
5
|
Project-URL: Homepage, https://getstack.run
|
|
6
6
|
Project-URL: Documentation, https://getstack.run/docs/sdk
|
|
@@ -23,6 +23,10 @@ Requires-Dist: cbor2>=5.6.0
|
|
|
23
23
|
Requires-Dist: cryptography>=42.0.0
|
|
24
24
|
Requires-Dist: httpx>=0.25.0
|
|
25
25
|
Requires-Dist: pyjwt>=2.8.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.9.0; extra == 'dev'
|
|
26
30
|
Description-Content-Type: text/markdown
|
|
27
31
|
|
|
28
32
|
# getstack
|
|
@@ -54,13 +58,24 @@ def run_fleet_mission_example(stack, request, provider_url="https://slack.com/ap
|
|
|
54
58
|
repeated = stack.missions.start(request)
|
|
55
59
|
assert repeated["mission_id"] == started["mission_id"]
|
|
56
60
|
operation_id = hashlib.sha256(json.dumps([started["mission_id"], "support-update"]).encode()).hexdigest()
|
|
57
|
-
response = stack.proxy.request(
|
|
61
|
+
response = stack.proxy.request(
|
|
62
|
+
"slack",
|
|
63
|
+
provider_url,
|
|
64
|
+
"POST",
|
|
58
65
|
body={"channel": "C123", "text": "Support update"},
|
|
59
|
-
passport_token=started["passport"]["token"],
|
|
66
|
+
passport_token=started["passport"]["token"],
|
|
67
|
+
authority_request_id=operation_id,
|
|
68
|
+
)
|
|
60
69
|
assert response.status == 200
|
|
61
70
|
try:
|
|
62
|
-
stack.proxy.request(
|
|
63
|
-
|
|
71
|
+
stack.proxy.request(
|
|
72
|
+
"slack",
|
|
73
|
+
provider_url,
|
|
74
|
+
"POST",
|
|
75
|
+
body={"channel": "OTHER", "text": "Support update"},
|
|
76
|
+
passport_token=started["passport"]["token"],
|
|
77
|
+
authority_request_id=operation_id + "_denied",
|
|
78
|
+
)
|
|
64
79
|
except StackError as error:
|
|
65
80
|
assert error.status_code == 403
|
|
66
81
|
else:
|
|
@@ -125,8 +140,15 @@ stack.agents.list()
|
|
|
125
140
|
stack.agents.update(agent_id, **fields)
|
|
126
141
|
stack.agents.unblock(agent_id)
|
|
127
142
|
|
|
143
|
+
# Missions (every passport is issued for exactly one Mission)
|
|
144
|
+
stack.missions.open(intent_summary, agent_id=None, intent_services=None, ...)
|
|
145
|
+
stack.missions.start(agent_id=agent_id, mission={"intent_summary": "..."}, passport=None)
|
|
146
|
+
stack.missions.complete(mission_id) # also revokes the Mission's passports
|
|
147
|
+
stack.missions.revoke(mission_id, reason="operator_initiated_clean")
|
|
148
|
+
|
|
128
149
|
# Passports
|
|
129
|
-
stack.passports.issue(agent_id, intent=None, services=None, ...)
|
|
150
|
+
stack.passports.issue(agent_id, mission_ids=[mission_id], intent=None, services=None, ...)
|
|
151
|
+
stack.passports.mission(agent_id, intent, services, ...) # context manager: Mission + passport, closed on exit
|
|
130
152
|
stack.passports.verify(token)
|
|
131
153
|
stack.passports.revoke(jti, reason=None)
|
|
132
154
|
stack.passports.checkpoint(jti, services_used, actions_count, ...)
|
|
@@ -148,9 +170,9 @@ stack.reviews.list(status="flagged")
|
|
|
148
170
|
stack.reviews.decide(checkout_id, decision, notes=None, block_future=False)
|
|
149
171
|
|
|
150
172
|
# Drop-offs
|
|
151
|
-
stack.dropoffs.create(from_agent_id, to_agent_id, schema,
|
|
152
|
-
stack.dropoffs.deposit(dropoff_id, data, agent_id)
|
|
153
|
-
stack.dropoffs.collect(dropoff_id, agent_id)
|
|
173
|
+
stack.dropoffs.create(from_agent_id, to_agent_id, schema, ..., passport_token=None)
|
|
174
|
+
stack.dropoffs.deposit(dropoff_id, data, agent_id, passport_token=None)
|
|
175
|
+
stack.dropoffs.collect(dropoff_id, agent_id, passport_token=None)
|
|
154
176
|
|
|
155
177
|
# Notifications
|
|
156
178
|
stack.notifications.list()
|
|
@@ -161,6 +183,18 @@ stack.notifications.delete(channel_id)
|
|
|
161
183
|
stack.audit.list(page=1, limit=50, action=None, agent_id=None)
|
|
162
184
|
```
|
|
163
185
|
|
|
186
|
+
## Development
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
python -m pip install -e ".[dev]"
|
|
190
|
+
ruff check .
|
|
191
|
+
ruff format --check .
|
|
192
|
+
mypy src
|
|
193
|
+
python -m pytest -q
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The package ships `py.typed`; `mypy src` runs in strict mode.
|
|
197
|
+
|
|
164
198
|
## Links
|
|
165
199
|
|
|
166
200
|
- [Documentation](https://getstack.run/docs/sdk)
|
|
@@ -27,13 +27,24 @@ def run_fleet_mission_example(stack, request, provider_url="https://slack.com/ap
|
|
|
27
27
|
repeated = stack.missions.start(request)
|
|
28
28
|
assert repeated["mission_id"] == started["mission_id"]
|
|
29
29
|
operation_id = hashlib.sha256(json.dumps([started["mission_id"], "support-update"]).encode()).hexdigest()
|
|
30
|
-
response = stack.proxy.request(
|
|
30
|
+
response = stack.proxy.request(
|
|
31
|
+
"slack",
|
|
32
|
+
provider_url,
|
|
33
|
+
"POST",
|
|
31
34
|
body={"channel": "C123", "text": "Support update"},
|
|
32
|
-
passport_token=started["passport"]["token"],
|
|
35
|
+
passport_token=started["passport"]["token"],
|
|
36
|
+
authority_request_id=operation_id,
|
|
37
|
+
)
|
|
33
38
|
assert response.status == 200
|
|
34
39
|
try:
|
|
35
|
-
stack.proxy.request(
|
|
36
|
-
|
|
40
|
+
stack.proxy.request(
|
|
41
|
+
"slack",
|
|
42
|
+
provider_url,
|
|
43
|
+
"POST",
|
|
44
|
+
body={"channel": "OTHER", "text": "Support update"},
|
|
45
|
+
passport_token=started["passport"]["token"],
|
|
46
|
+
authority_request_id=operation_id + "_denied",
|
|
47
|
+
)
|
|
37
48
|
except StackError as error:
|
|
38
49
|
assert error.status_code == 403
|
|
39
50
|
else:
|
|
@@ -98,8 +109,15 @@ stack.agents.list()
|
|
|
98
109
|
stack.agents.update(agent_id, **fields)
|
|
99
110
|
stack.agents.unblock(agent_id)
|
|
100
111
|
|
|
112
|
+
# Missions (every passport is issued for exactly one Mission)
|
|
113
|
+
stack.missions.open(intent_summary, agent_id=None, intent_services=None, ...)
|
|
114
|
+
stack.missions.start(agent_id=agent_id, mission={"intent_summary": "..."}, passport=None)
|
|
115
|
+
stack.missions.complete(mission_id) # also revokes the Mission's passports
|
|
116
|
+
stack.missions.revoke(mission_id, reason="operator_initiated_clean")
|
|
117
|
+
|
|
101
118
|
# Passports
|
|
102
|
-
stack.passports.issue(agent_id, intent=None, services=None, ...)
|
|
119
|
+
stack.passports.issue(agent_id, mission_ids=[mission_id], intent=None, services=None, ...)
|
|
120
|
+
stack.passports.mission(agent_id, intent, services, ...) # context manager: Mission + passport, closed on exit
|
|
103
121
|
stack.passports.verify(token)
|
|
104
122
|
stack.passports.revoke(jti, reason=None)
|
|
105
123
|
stack.passports.checkpoint(jti, services_used, actions_count, ...)
|
|
@@ -121,9 +139,9 @@ stack.reviews.list(status="flagged")
|
|
|
121
139
|
stack.reviews.decide(checkout_id, decision, notes=None, block_future=False)
|
|
122
140
|
|
|
123
141
|
# Drop-offs
|
|
124
|
-
stack.dropoffs.create(from_agent_id, to_agent_id, schema,
|
|
125
|
-
stack.dropoffs.deposit(dropoff_id, data, agent_id)
|
|
126
|
-
stack.dropoffs.collect(dropoff_id, agent_id)
|
|
142
|
+
stack.dropoffs.create(from_agent_id, to_agent_id, schema, ..., passport_token=None)
|
|
143
|
+
stack.dropoffs.deposit(dropoff_id, data, agent_id, passport_token=None)
|
|
144
|
+
stack.dropoffs.collect(dropoff_id, agent_id, passport_token=None)
|
|
127
145
|
|
|
128
146
|
# Notifications
|
|
129
147
|
stack.notifications.list()
|
|
@@ -134,6 +152,18 @@ stack.notifications.delete(channel_id)
|
|
|
134
152
|
stack.audit.list(page=1, limit=50, action=None, agent_id=None)
|
|
135
153
|
```
|
|
136
154
|
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
python -m pip install -e ".[dev]"
|
|
159
|
+
ruff check .
|
|
160
|
+
ruff format --check .
|
|
161
|
+
mypy src
|
|
162
|
+
python -m pytest -q
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The package ships `py.typed`; `mypy src` runs in strict mode.
|
|
166
|
+
|
|
137
167
|
## Links
|
|
138
168
|
|
|
139
169
|
- [Documentation](https://getstack.run/docs/sdk)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "getstack"
|
|
7
|
-
version = "
|
|
7
|
+
version = "4.0.0"
|
|
8
8
|
description = "Python SDK for STACK — trust infrastructure for AI agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -46,3 +46,36 @@ Repository = "https://github.com/getstack-run/sdk-python"
|
|
|
46
46
|
|
|
47
47
|
[tool.hatch.build.targets.wheel]
|
|
48
48
|
packages = ["src/getstack"]
|
|
49
|
+
|
|
50
|
+
[project.optional-dependencies]
|
|
51
|
+
dev = [
|
|
52
|
+
"pytest>=8.0.0",
|
|
53
|
+
"ruff>=0.9.0",
|
|
54
|
+
"mypy>=1.13.0",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.ruff]
|
|
58
|
+
line-length = 120
|
|
59
|
+
target-version = "py39"
|
|
60
|
+
src = ["src", "tests"]
|
|
61
|
+
|
|
62
|
+
[tool.ruff.lint]
|
|
63
|
+
select = [
|
|
64
|
+
"E", # pycodestyle errors
|
|
65
|
+
"W", # pycodestyle warnings
|
|
66
|
+
"F", # pyflakes
|
|
67
|
+
"I", # isort import order
|
|
68
|
+
"B", # flake8-bugbear
|
|
69
|
+
"UP", # pyupgrade
|
|
70
|
+
"SIM", # flake8-simplify
|
|
71
|
+
"C4", # flake8-comprehensions
|
|
72
|
+
"RUF", # ruff-specific rules
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
[tool.ruff.lint.isort]
|
|
76
|
+
known-first-party = ["getstack"]
|
|
77
|
+
|
|
78
|
+
[tool.mypy]
|
|
79
|
+
strict = true
|
|
80
|
+
mypy_path = "src"
|
|
81
|
+
files = ["src"]
|