getstack 0.16.0__tar.gz → 0.18.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-0.16.0 → getstack-0.18.0}/PKG-INFO +1 -1
- {getstack-0.16.0 → getstack-0.18.0}/pyproject.toml +1 -1
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/__init__.py +4 -0
- getstack-0.18.0/src/getstack/_async/partner_connect.py +43 -0
- getstack-0.18.0/src/getstack/_async/usage.py +25 -0
- getstack-0.18.0/src/getstack/partner_connect.py +69 -0
- getstack-0.18.0/src/getstack/usage.py +55 -0
- {getstack-0.16.0 → getstack-0.18.0}/tests/test_parity.py +2 -1
- getstack-0.16.0/src/getstack/_async/usage.py +0 -15
- getstack-0.16.0/src/getstack/usage.py +0 -37
- {getstack-0.16.0 → getstack-0.18.0}/.gitignore +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/CLAUDE.md +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/LICENSE +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/README.md +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/scripts/verify_sign_claim_crosslang.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/__init__.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/agents.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/audit.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/credentials.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/delivery_methods.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/detector_config.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/dropoffs.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/evidence_packs.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/identity.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/inbound_webhooks.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/intents.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/llm.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/missions.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/notifications.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/partner_tenants.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/passport_session.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/passports.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/proxy.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/reviews.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/scan.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/security_events.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/services.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/skills.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/_async/team.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/agent_auth.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/agents.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/audit.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/auth.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/browser_bootstrap.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/client.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/credentials.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/delivery_methods.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/detector_config.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/dropoffs.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/errors.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/evidence_packs.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/identity.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/inbound_webhooks.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/intents.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/llm.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/missions.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/notifications.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/partner_tenants.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/passport_header_verify.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/passport_session.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/passports.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/proxy.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/py.typed +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/reviews.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/scan.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/security_events.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/services.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/sign_claim.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/skills.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/team.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/types.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/src/getstack/verify_offline.py +0 -0
- {getstack-0.16.0 → getstack-0.18.0}/tests/test_sign_claim.py +0 -0
|
@@ -55,6 +55,7 @@ from .skills import SkillService
|
|
|
55
55
|
from .identity import IdentityService
|
|
56
56
|
from .inbound_webhooks import InboundWebhookService
|
|
57
57
|
from .partner_tenants import PartnerTenantsService
|
|
58
|
+
from .partner_connect import PartnerConnectService
|
|
58
59
|
from .passport_header_verify import verify_passport_header
|
|
59
60
|
from .verify_offline import verify_passport_offline
|
|
60
61
|
from .sign_claim import sign_claim_envelope
|
|
@@ -244,6 +245,7 @@ class Stack:
|
|
|
244
245
|
self.llm = LlmService(self._client)
|
|
245
246
|
self.inbound_webhooks = InboundWebhookService(self._client)
|
|
246
247
|
self.partner_tenants = PartnerTenantsService(self._client)
|
|
248
|
+
self.partner_connect = PartnerConnectService(self._client)
|
|
247
249
|
self.team = TeamService(self._client)
|
|
248
250
|
self.delivery_methods = DeliveryMethodService(self._client)
|
|
249
251
|
self.detector_config = DetectorConfigService(self._client)
|
|
@@ -389,6 +391,7 @@ class AsyncStack:
|
|
|
389
391
|
from ._async.llm import AsyncLlmService
|
|
390
392
|
from ._async.inbound_webhooks import AsyncInboundWebhookService
|
|
391
393
|
from ._async.partner_tenants import AsyncPartnerTenantsService
|
|
394
|
+
from ._async.partner_connect import AsyncPartnerConnectService
|
|
392
395
|
from ._async.evidence_packs import AsyncEvidencePacksService
|
|
393
396
|
from ._async.team import AsyncTeamService
|
|
394
397
|
from ._async.delivery_methods import AsyncDeliveryMethodService
|
|
@@ -414,6 +417,7 @@ class AsyncStack:
|
|
|
414
417
|
self.llm = AsyncLlmService(self._client)
|
|
415
418
|
self.inbound_webhooks = AsyncInboundWebhookService(self._client)
|
|
416
419
|
self.partner_tenants = AsyncPartnerTenantsService(self._client)
|
|
420
|
+
self.partner_connect = AsyncPartnerConnectService(self._client)
|
|
417
421
|
self.evidence_packs = AsyncEvidencePacksService(self._client)
|
|
418
422
|
self.team = AsyncTeamService(self._client)
|
|
419
423
|
self.delivery_methods = AsyncDeliveryMethodService(self._client)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Async mirror of PartnerConnectService (GET-210)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
from ..client import AsyncHttpClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AsyncPartnerConnectService:
|
|
11
|
+
def __init__(self, client: AsyncHttpClient):
|
|
12
|
+
self._client = client
|
|
13
|
+
|
|
14
|
+
async def connect(
|
|
15
|
+
self,
|
|
16
|
+
email: str,
|
|
17
|
+
external_customer_id: Optional[str] = None,
|
|
18
|
+
scopes: Optional[list[str]] = None,
|
|
19
|
+
providers: Optional[list[str]] = None,
|
|
20
|
+
) -> dict[str, Any]:
|
|
21
|
+
body: dict[str, Any] = {"email": email}
|
|
22
|
+
if external_customer_id is not None:
|
|
23
|
+
body["external_customer_id"] = external_customer_id
|
|
24
|
+
if scopes is not None:
|
|
25
|
+
body["scopes"] = scopes
|
|
26
|
+
if providers is not None:
|
|
27
|
+
body["providers"] = providers
|
|
28
|
+
return await self._client.post("/v1/partner/connect", json=body)
|
|
29
|
+
|
|
30
|
+
async def list_connections(self) -> list[dict[str, Any]]:
|
|
31
|
+
res = await self._client.get("/v1/partner/connections")
|
|
32
|
+
return list(res.get("connections", []))
|
|
33
|
+
|
|
34
|
+
async def get_connection(self, grant_id: str) -> dict[str, Any]:
|
|
35
|
+
return await self._client.get(f"/v1/partner/connections/{grant_id}")
|
|
36
|
+
|
|
37
|
+
async def revoke_connection(self, grant_id: str) -> dict[str, Any]:
|
|
38
|
+
return await self._client.delete(f"/v1/partner/connections/{grant_id}")
|
|
39
|
+
|
|
40
|
+
async def rotate_token(self, grant_id: str) -> dict[str, Any]:
|
|
41
|
+
return await self._client.post(
|
|
42
|
+
f"/v1/partner/connections/{grant_id}/rotate-token", json={}
|
|
43
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Async mirror of UsageService."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ..client import AsyncHttpClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AsyncUsageService:
|
|
11
|
+
def __init__(self, client: AsyncHttpClient):
|
|
12
|
+
self._client = client
|
|
13
|
+
|
|
14
|
+
async def get(
|
|
15
|
+
self,
|
|
16
|
+
*,
|
|
17
|
+
since: str | None = None,
|
|
18
|
+
until: str | None = None,
|
|
19
|
+
) -> dict[str, Any]:
|
|
20
|
+
params: dict[str, str] = {}
|
|
21
|
+
if since is not None:
|
|
22
|
+
params["since"] = since
|
|
23
|
+
if until is not None:
|
|
24
|
+
params["until"] = until
|
|
25
|
+
return await self._client.get("/v1/usage", params=params or None)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""GET-210 — "Connect with STACK" partner surface (sync).
|
|
2
|
+
|
|
3
|
+
connect(email) creates a USER-OWNED STACK account on the customer's
|
|
4
|
+
real email (Express model, notice email) or opens a consent flow when
|
|
5
|
+
the account exists, and returns an opaque ``sk_grant_*`` token you
|
|
6
|
+
attach to the calls you already make — same Bearer header, scoped to
|
|
7
|
+
what the grant created, revocable by the user under /services.
|
|
8
|
+
|
|
9
|
+
Supersedes the Phase 5.6 child-tenant OWNERSHIP semantics; the tenant
|
|
10
|
+
surface remains available through its deprecation window.
|
|
11
|
+
|
|
12
|
+
Near-zero integration::
|
|
13
|
+
|
|
14
|
+
res = stack.partner_connect.connect(email="customer@example.com")
|
|
15
|
+
user_stack = Stack(api_key=res["grant_token"])
|
|
16
|
+
# register agents, connect your provider, issue passports, proxy.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Any, Optional
|
|
22
|
+
|
|
23
|
+
from .client import HttpClient
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class PartnerConnectService:
|
|
27
|
+
def __init__(self, client: HttpClient):
|
|
28
|
+
self._client = client
|
|
29
|
+
|
|
30
|
+
def connect(
|
|
31
|
+
self,
|
|
32
|
+
email: str,
|
|
33
|
+
external_customer_id: Optional[str] = None,
|
|
34
|
+
scopes: Optional[list[str]] = None,
|
|
35
|
+
providers: Optional[list[str]] = None,
|
|
36
|
+
) -> dict[str, Any]:
|
|
37
|
+
"""One call: create-on-email or consent-request.
|
|
38
|
+
|
|
39
|
+
The response's ``grant_token`` is present EXACTLY ONCE, on the
|
|
40
|
+
call that created the grant. ``status`` is ``active`` (new
|
|
41
|
+
account) or ``pending_consent`` (existing account — the token
|
|
42
|
+
authenticates nothing until the user approves).
|
|
43
|
+
"""
|
|
44
|
+
body: dict[str, Any] = {"email": email}
|
|
45
|
+
if external_customer_id is not None:
|
|
46
|
+
body["external_customer_id"] = external_customer_id
|
|
47
|
+
if scopes is not None:
|
|
48
|
+
body["scopes"] = scopes
|
|
49
|
+
if providers is not None:
|
|
50
|
+
body["providers"] = providers
|
|
51
|
+
return self._client.post("/v1/partner/connect", json=body)
|
|
52
|
+
|
|
53
|
+
def list_connections(self) -> list[dict[str, Any]]:
|
|
54
|
+
res = self._client.get("/v1/partner/connections")
|
|
55
|
+
return list(res.get("connections", []))
|
|
56
|
+
|
|
57
|
+
def get_connection(self, grant_id: str) -> dict[str, Any]:
|
|
58
|
+
return self._client.get(f"/v1/partner/connections/{grant_id}")
|
|
59
|
+
|
|
60
|
+
def revoke_connection(self, grant_id: str) -> dict[str, Any]:
|
|
61
|
+
"""Revoke the edge. Cascades: grant-created agents' passports,
|
|
62
|
+
webhooks, and connections all die with it."""
|
|
63
|
+
return self._client.delete(f"/v1/partner/connections/{grant_id}")
|
|
64
|
+
|
|
65
|
+
def rotate_token(self, grant_id: str) -> dict[str, Any]:
|
|
66
|
+
"""Rotate the grant token (lost/leaked). New plaintext returned once."""
|
|
67
|
+
return self._client.post(
|
|
68
|
+
f"/v1/partner/connections/{grant_id}/rotate-token", json={}
|
|
69
|
+
)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Usage service — `/v1/usage` (usage + spend + earnings rollup).
|
|
2
|
+
|
|
3
|
+
The one-call rollup of what your operator consumed against its plan,
|
|
4
|
+
spent, and earned this billing period. Superset of the per-domain meters
|
|
5
|
+
(`stack.scan.usage()`, `stack.llm.usage`, `stack.proxy` counts) — one
|
|
6
|
+
authoritative shape the CLI and dashboard read too. Money fields are in
|
|
7
|
+
cents.
|
|
8
|
+
|
|
9
|
+
Example::
|
|
10
|
+
|
|
11
|
+
u = stack.usage.get()
|
|
12
|
+
p = u["consumption"]["passports"]
|
|
13
|
+
print(f"Passports {p['used']}/{p['limit']}")
|
|
14
|
+
print(f"Spent this period: ${u['spend_cents']['total'] / 100:.2f}")
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from .client import HttpClient
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class UsageService:
|
|
25
|
+
def __init__(self, client: HttpClient):
|
|
26
|
+
self._client = client
|
|
27
|
+
|
|
28
|
+
def get(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
since: str | None = None,
|
|
32
|
+
until: str | None = None,
|
|
33
|
+
) -> dict[str, Any]:
|
|
34
|
+
"""Usage, spend, and earnings for the current billing period.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
since: Optional window start (ISO-8601 or unix-ms). When set, the
|
|
38
|
+
flow metrics (spend, passports, dropoffs, skill invocations,
|
|
39
|
+
proxy) are scoped to the window; inventory meters gain a
|
|
40
|
+
``created_in_window`` count. Omit for the billing period.
|
|
41
|
+
until: Optional exclusive window end.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Dict with keys: tier, period_start, period_end, period_label,
|
|
45
|
+
consumption (per-meter {used, limit, created_in_window?}),
|
|
46
|
+
spend_cents (skills / llm_compute / identity / overage / total),
|
|
47
|
+
wallet_cents ({balance}), and earnings_cents ({unpaid, lifetime}).
|
|
48
|
+
All money in cents.
|
|
49
|
+
"""
|
|
50
|
+
params: dict[str, str] = {}
|
|
51
|
+
if since is not None:
|
|
52
|
+
params["since"] = since
|
|
53
|
+
if until is not None:
|
|
54
|
+
params["until"] = until
|
|
55
|
+
return self._client.get("/v1/usage", params=params or None)
|
|
@@ -34,7 +34,8 @@ EXPECTED_SERVICES = [
|
|
|
34
34
|
"agents", "passports", "credentials", "services", "dropoffs", "reviews",
|
|
35
35
|
"notifications", "audit", "proxy", "scan", "usage", "security_events",
|
|
36
36
|
"skills", "identity", "intents", "missions", "evidence_packs", "llm",
|
|
37
|
-
"inbound_webhooks", "partner_tenants",
|
|
37
|
+
"inbound_webhooks", "partner_tenants",
|
|
38
|
+
"partner_connect", "team", "delivery_methods",
|
|
38
39
|
"detector_config",
|
|
39
40
|
]
|
|
40
41
|
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""Async mirror of UsageService."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
from ..client import AsyncHttpClient
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class AsyncUsageService:
|
|
11
|
-
def __init__(self, client: AsyncHttpClient):
|
|
12
|
-
self._client = client
|
|
13
|
-
|
|
14
|
-
async def get(self) -> dict[str, Any]:
|
|
15
|
-
return await self._client.request("GET", "/v1/usage")
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"""Usage service — `/v1/usage` (usage + spend + earnings rollup).
|
|
2
|
-
|
|
3
|
-
The one-call rollup of what your operator consumed against its plan,
|
|
4
|
-
spent, and earned this billing period. Superset of the per-domain meters
|
|
5
|
-
(`stack.scan.usage()`, `stack.llm.usage`, `stack.proxy` counts) — one
|
|
6
|
-
authoritative shape the CLI and dashboard read too. Money fields are in
|
|
7
|
-
cents.
|
|
8
|
-
|
|
9
|
-
Example::
|
|
10
|
-
|
|
11
|
-
u = stack.usage.get()
|
|
12
|
-
p = u["consumption"]["passports"]
|
|
13
|
-
print(f"Passports {p['used']}/{p['limit']}")
|
|
14
|
-
print(f"Spent this period: ${u['spend_cents']['total'] / 100:.2f}")
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
from __future__ import annotations
|
|
18
|
-
|
|
19
|
-
from typing import Any
|
|
20
|
-
|
|
21
|
-
from .client import HttpClient
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class UsageService:
|
|
25
|
-
def __init__(self, client: HttpClient):
|
|
26
|
-
self._client = client
|
|
27
|
-
|
|
28
|
-
def get(self) -> dict[str, Any]:
|
|
29
|
-
"""Usage, spend, and earnings for the current billing period.
|
|
30
|
-
|
|
31
|
-
Returns:
|
|
32
|
-
Dict with keys: tier, period_start, period_end, consumption
|
|
33
|
-
(per-meter {used, limit}), spend_cents (skills / llm_compute /
|
|
34
|
-
identity / overage / total), wallet_cents ({balance}), and
|
|
35
|
-
earnings_cents ({unpaid, lifetime}). All money in cents.
|
|
36
|
-
"""
|
|
37
|
-
return self._client.request("GET", "/v1/usage")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|