mainsequence 9.0.9.dev46__tar.gz → 9.0.10__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.
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/PKG-INFO +1 -1
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +8 -5
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/mainsequence-inference/SKILL.md +15 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/agent_runtime_models.py +17 -1
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/inference.py +12 -1
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/models_user.py +81 -17
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence.egg-info/PKG-INFO +1 -1
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/pyproject.toml +1 -1
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_inference_client.py +30 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/LICENSE +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/README.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/maintenance/metatables_transition/SKILL.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/__init__.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/__main__.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/_request_identity.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/bootstrap.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/api.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/cli.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/code_repository_status.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/config.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/cli/ui.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/__init__.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/_transport.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/base.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/client.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/github_issues.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/models_foundry.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/observability.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/utils.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/value_sets.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/code_repository_context.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/code_repository_skills.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/defaults.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/logconf.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/repository_identity_security.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/runtime_credential_exchange.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/server/__init__.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/server/caller_assertions.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/server/fastapi.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence.egg-info/SOURCES.txt +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/setup.cfg +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_auth_bootstrap.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_auth_precedence.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_caller_assertions.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_canonical_api_route_contract.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_cli_auth_contract.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_cli_secure_storage.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_client.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_code_repository_branch_contract.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_code_repository_documentation_contract.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_code_repository_runtime_context.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_code_repository_skills.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_credential_repr.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_dependency_extras.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_dev_release_version.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_environment_resource_context.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_environment_response_contracts.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_fastapi_request_identity.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_github_issues_client.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_http_retry_budget.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_independent_context.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_instrumentation.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_job_client.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_local_ops.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_logconf.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_notification_uid_contract.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_observability_client.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_runtime_credential_exchange.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_secret_client_model.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_source_ownership.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_ssh_utils.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_tolerant_response_reading.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_tolerant_value_sets.py +0 -0
- {mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_user_application_facts.py +0 -0
|
@@ -138,11 +138,14 @@ remain projections of the same identity, not a separate resolver. Outside an
|
|
|
138
138
|
authenticated request, including public routes, `User.get_logged_user()` raises
|
|
139
139
|
`RequestIdentityError`.
|
|
140
140
|
|
|
141
|
-
On a protected route, this identity is the
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
On a protected route, this identity is the caller of the current HTTP request:
|
|
142
|
+
a person, or the workload identity a deployed Job, FastAPI release or Agent runs
|
|
143
|
+
as. It is not the release creator, deployment owner, the application's own
|
|
144
|
+
runtime workload principal, or the process account returned by
|
|
145
|
+
`User.get_authenticated_user_details()`. To tell a workload caller from a
|
|
146
|
+
person, read `User.get_by_uid(uid)`: a workload identity has `identity_type`
|
|
147
|
+
`"workload"`. Caller authentication is not resource authorization; apply the
|
|
148
|
+
endpoint's application policy using the verified user UID.
|
|
146
149
|
|
|
147
150
|
WebSockets retain the platform's gateway ticket/header contract rather than
|
|
148
151
|
the HTTP Bearer/assertion flow; the getter is available while the authenticated
|
|
@@ -46,6 +46,21 @@ context. Never invent an Environment, use another branch as a fallback, or add
|
|
|
46
46
|
inference environment variables. Provider secrets remain in existing server-side
|
|
47
47
|
credential storage and must not appear in messages or `provider_options`.
|
|
48
48
|
|
|
49
|
+
## Select a configured provider
|
|
50
|
+
|
|
51
|
+
Pass optional `custom_id="openai-work"` to `client.complete()` to select that named
|
|
52
|
+
credential within the caller's Environment. Omit it to retain the first available
|
|
53
|
+
owned credential, then the first shared credential. A missing or ambiguous explicit
|
|
54
|
+
name fails; do not retry using a different credential. Recorded requests retain the
|
|
55
|
+
exact credential UID for replay. Custom endpoints use their existing provider
|
|
56
|
+
identifier and do not accept `custom_id`.
|
|
57
|
+
|
|
58
|
+
Sharing a configured provider authorizes recipients, including workload users,
|
|
59
|
+
to use its credentials and receive them in local Tau. They may copy those credentials;
|
|
60
|
+
revoking a share cannot remove copies already delivered. Explain this before
|
|
61
|
+
guiding someone through sharing. This inference client executes on the server;
|
|
62
|
+
provider management remains with the existing provider clients.
|
|
63
|
+
|
|
49
64
|
## Construct a completion envelope
|
|
50
65
|
|
|
51
66
|
Every call supplies complete ordered text messages: `system`, `user`, `assistant`.
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/client/agent_runtime_models.py
RENAMED
|
@@ -727,6 +727,7 @@ class Agent(
|
|
|
727
727
|
llm_provider: str | None = None,
|
|
728
728
|
llm_model: str | None = None,
|
|
729
729
|
llm_thinking: str | None = None,
|
|
730
|
+
custom_id: str | None = None,
|
|
730
731
|
timeout=None,
|
|
731
732
|
) -> AgentSession:
|
|
732
733
|
"""
|
|
@@ -759,6 +760,10 @@ class Agent(
|
|
|
759
760
|
"llm_provider": llm_provider,
|
|
760
761
|
"llm_model": llm_model,
|
|
761
762
|
"llm_thinking": llm_thinking,
|
|
763
|
+
"custom_id": (
|
|
764
|
+
custom_id
|
|
765
|
+
if custom_id is not None else None
|
|
766
|
+
),
|
|
762
767
|
}
|
|
763
768
|
if resolved_session_uid and any(value is not None for value in creation_options.values()):
|
|
764
769
|
raise ValueError("Creation options require handle_unique_id, not session_uid")
|
|
@@ -787,7 +792,14 @@ class Agent(
|
|
|
787
792
|
session_payload = response.json()
|
|
788
793
|
if not isinstance(session_payload, dict):
|
|
789
794
|
raise TypeError("get_or_create_session response must be an AgentSession object")
|
|
790
|
-
|
|
795
|
+
session = AgentSession(**session_payload)
|
|
796
|
+
if (
|
|
797
|
+
custom_id is not None
|
|
798
|
+
and session.custom_id
|
|
799
|
+
!= creation_options["custom_id"]
|
|
800
|
+
):
|
|
801
|
+
raise ValueError("The returned session does not use the requested configured provider")
|
|
802
|
+
return session
|
|
791
803
|
|
|
792
804
|
|
|
793
805
|
class AgentSessionInsightsBase(BasePydanticModel):
|
|
@@ -1745,6 +1757,10 @@ class AgentSession(
|
|
|
1745
1757
|
None,
|
|
1746
1758
|
description="Timestamp when the session was archived.",
|
|
1747
1759
|
)
|
|
1760
|
+
model_provider_credential_uid: str | None = None
|
|
1761
|
+
custom_id: str | None = Field(
|
|
1762
|
+
None, description="Resolved configured provider name; None for custom endpoints."
|
|
1763
|
+
)
|
|
1748
1764
|
llm_provider: str = Field(
|
|
1749
1765
|
...,
|
|
1750
1766
|
description="Resolved LLM provider actually used for this session. Unlike Agent defaults, this is intended to be the authoritative runtime record.",
|
|
@@ -20,6 +20,8 @@ class InferenceResult(BaseModel):
|
|
|
20
20
|
sequence: int
|
|
21
21
|
provider: str
|
|
22
22
|
model: str
|
|
23
|
+
custom_id: str | None = None
|
|
24
|
+
model_provider_credential_uid: str | None = None
|
|
23
25
|
status: str
|
|
24
26
|
error_code: str
|
|
25
27
|
content_available: bool
|
|
@@ -125,6 +127,7 @@ class InferenceClient:
|
|
|
125
127
|
messages: list[dict[str, str]],
|
|
126
128
|
idempotency_key: str,
|
|
127
129
|
conversation_uid: str | UUID | None = None,
|
|
130
|
+
custom_id: str | None = None,
|
|
128
131
|
thinking_level: str | None = None,
|
|
129
132
|
provider_options: dict[str, Any] | None = None,
|
|
130
133
|
provider_storage: dict[str, Any] | None = None,
|
|
@@ -142,6 +145,8 @@ class InferenceClient:
|
|
|
142
145
|
"idempotency_key must contain 1–128 letters, digits, dots, underscores, colons or hyphens."
|
|
143
146
|
)
|
|
144
147
|
body = {"provider": provider, "model": model, "messages": deepcopy(messages)}
|
|
148
|
+
if custom_id is not None:
|
|
149
|
+
body["custom_id"] = custom_id
|
|
145
150
|
if conversation_uid is not None:
|
|
146
151
|
body["conversation_uid"] = str(UUID(str(conversation_uid)))
|
|
147
152
|
for name, value in (
|
|
@@ -153,9 +158,15 @@ class InferenceClient:
|
|
|
153
158
|
):
|
|
154
159
|
if value is not None:
|
|
155
160
|
body[name] = deepcopy(value)
|
|
156
|
-
|
|
161
|
+
result = self._request(
|
|
157
162
|
"POST", "inference/completions/", body=body, key=idempotency_key, timeout=timeout
|
|
158
163
|
)
|
|
164
|
+
if (
|
|
165
|
+
custom_id is not None
|
|
166
|
+
and result.custom_id != body["custom_id"]
|
|
167
|
+
):
|
|
168
|
+
raise InferenceTransportError(idempotency_key)
|
|
169
|
+
return result
|
|
159
170
|
|
|
160
171
|
def conversations(self, *, limit: int = 25, offset: int = 0) -> dict[str, Any]:
|
|
161
172
|
return self._request(
|
|
@@ -23,14 +23,21 @@ from .value_sets import OpenValueSet
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class RequestUserIdentity(BaseModel):
|
|
26
|
-
"""Minimal identity of the
|
|
26
|
+
"""Minimal identity of the caller of the current runtime request.
|
|
27
|
+
|
|
28
|
+
The caller is a person or a workload identity; ``User.get_by_uid(uid)``
|
|
29
|
+
reads its User.
|
|
30
|
+
"""
|
|
27
31
|
|
|
28
32
|
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
29
33
|
|
|
30
34
|
uid: str = Field(
|
|
31
35
|
...,
|
|
32
36
|
title="User UID",
|
|
33
|
-
description=
|
|
37
|
+
description=(
|
|
38
|
+
"Canonical public UUID of the User making the current request, a person or a "
|
|
39
|
+
"workload identity."
|
|
40
|
+
),
|
|
34
41
|
)
|
|
35
42
|
username: str | None = Field(
|
|
36
43
|
None,
|
|
@@ -954,6 +961,17 @@ class ShareableAccessState(BasePydanticModel):
|
|
|
954
961
|
|
|
955
962
|
|
|
956
963
|
class User(UserApiBaseObjectOrm, BasePydanticModel):
|
|
964
|
+
"""A platform User: a person, or the workload identity a deployed Job,
|
|
965
|
+
FastAPI release or Agent runs as.
|
|
966
|
+
|
|
967
|
+
A workload identity is read with ``User.get_by_uid(uid)`` or listed with
|
|
968
|
+
``User.filter(identity_type="workload")``. Its row carries ``uid``,
|
|
969
|
+
``identity_type`` (``"workload"``), ``is_active`` and the UID of its
|
|
970
|
+
workload in ``job_uid``, ``resource_release_uid`` or ``agent_uid``, without
|
|
971
|
+
a username, email, join date or name. Fields the row does not carry are
|
|
972
|
+
``None``, or empty for lists.
|
|
973
|
+
"""
|
|
974
|
+
|
|
957
975
|
# Platform facts, not application authorization policy. None means the
|
|
958
976
|
# connected platform has not supplied the versioned additive contract.
|
|
959
977
|
is_organization_admin: StrictBool | None = None
|
|
@@ -963,6 +981,7 @@ class User(UserApiBaseObjectOrm, BasePydanticModel):
|
|
|
963
981
|
FILTERSET_FIELDS: ClassVar[dict[str, list[str]] | None] = {
|
|
964
982
|
"uid": ["exact", "in"],
|
|
965
983
|
"email": ["exact", "contains", "in"],
|
|
984
|
+
"identity_type": ["exact"],
|
|
966
985
|
}
|
|
967
986
|
FILTER_VALUE_NORMALIZERS: ClassVar[dict[str, str]] = {
|
|
968
987
|
"uid": "uid",
|
|
@@ -970,6 +989,7 @@ class User(UserApiBaseObjectOrm, BasePydanticModel):
|
|
|
970
989
|
"email": "str",
|
|
971
990
|
"email__contains": "str",
|
|
972
991
|
"email__in": "str",
|
|
992
|
+
"identity_type": "str",
|
|
973
993
|
}
|
|
974
994
|
|
|
975
995
|
id: int | None = Field(
|
|
@@ -985,6 +1005,35 @@ class User(UserApiBaseObjectOrm, BasePydanticModel):
|
|
|
985
1005
|
description="Stable public unique identifier of the user.",
|
|
986
1006
|
examples=["8f5d6b54-2f5e-4a8b-bb10-0b17f3f4c123"],
|
|
987
1007
|
)
|
|
1008
|
+
identity_type: (
|
|
1009
|
+
OpenValueSet[Literal["human", "service_account", "deleted_user", "workload"]] | None
|
|
1010
|
+
) = Field(
|
|
1011
|
+
None,
|
|
1012
|
+
title="Identity Type",
|
|
1013
|
+
description=(
|
|
1014
|
+
"Kind of identity: `workload` for the identity a deployed Job, FastAPI release "
|
|
1015
|
+
"or Agent runs as. None when the response does not carry it."
|
|
1016
|
+
),
|
|
1017
|
+
examples=["workload"],
|
|
1018
|
+
)
|
|
1019
|
+
job_uid: str | None = Field(
|
|
1020
|
+
None,
|
|
1021
|
+
title="Job UID",
|
|
1022
|
+
description="UID of the Job a workload identity belongs to; None otherwise.",
|
|
1023
|
+
examples=["88888888-8888-4888-8888-888888888888"],
|
|
1024
|
+
)
|
|
1025
|
+
resource_release_uid: str | None = Field(
|
|
1026
|
+
None,
|
|
1027
|
+
title="Resource Release UID",
|
|
1028
|
+
description="UID of the release a workload identity belongs to; None otherwise.",
|
|
1029
|
+
examples=[None],
|
|
1030
|
+
)
|
|
1031
|
+
agent_uid: str | None = Field(
|
|
1032
|
+
None,
|
|
1033
|
+
title="Agent UID",
|
|
1034
|
+
description="UID of the Agent a workload identity belongs to; None otherwise.",
|
|
1035
|
+
examples=[None],
|
|
1036
|
+
)
|
|
988
1037
|
profile_picture: str | None = Field(
|
|
989
1038
|
None,
|
|
990
1039
|
title="Profile Picture URL",
|
|
@@ -1022,10 +1071,13 @@ class User(UserApiBaseObjectOrm, BasePydanticModel):
|
|
|
1022
1071
|
examples=["enterprise"],
|
|
1023
1072
|
)
|
|
1024
1073
|
|
|
1025
|
-
date_joined: datetime.datetime = Field(
|
|
1026
|
-
|
|
1074
|
+
date_joined: datetime.datetime | None = Field(
|
|
1075
|
+
None,
|
|
1027
1076
|
title="Date Joined",
|
|
1028
|
-
description=
|
|
1077
|
+
description=(
|
|
1078
|
+
"Timestamp when the user account was created. None when the response does not "
|
|
1079
|
+
"carry it, as for a workload identity."
|
|
1080
|
+
),
|
|
1029
1081
|
examples=["2025-01-10T08:15:00Z"],
|
|
1030
1082
|
)
|
|
1031
1083
|
is_active: bool = Field(
|
|
@@ -1034,16 +1086,22 @@ class User(UserApiBaseObjectOrm, BasePydanticModel):
|
|
|
1034
1086
|
description="Whether the user account is active.",
|
|
1035
1087
|
examples=[True],
|
|
1036
1088
|
)
|
|
1037
|
-
username: str = Field(
|
|
1038
|
-
|
|
1089
|
+
username: str | None = Field(
|
|
1090
|
+
None,
|
|
1039
1091
|
title="Username",
|
|
1040
|
-
description=
|
|
1092
|
+
description=(
|
|
1093
|
+
"Unique username used by the platform. None when the response does not carry it, "
|
|
1094
|
+
"as for a workload identity."
|
|
1095
|
+
),
|
|
1041
1096
|
examples=["jose@main-sequence.io"],
|
|
1042
1097
|
)
|
|
1043
|
-
email: str = Field(
|
|
1044
|
-
|
|
1098
|
+
email: str | None = Field(
|
|
1099
|
+
None,
|
|
1045
1100
|
title="Email",
|
|
1046
|
-
description=
|
|
1101
|
+
description=(
|
|
1102
|
+
"Primary email address of the user. None when the response does not carry it, "
|
|
1103
|
+
"as for a workload identity."
|
|
1104
|
+
),
|
|
1047
1105
|
examples=["jose@main-sequence.io"],
|
|
1048
1106
|
)
|
|
1049
1107
|
first_name: str | None = Field(
|
|
@@ -1064,16 +1122,22 @@ class User(UserApiBaseObjectOrm, BasePydanticModel):
|
|
|
1064
1122
|
description="Timestamp of the last successful login.",
|
|
1065
1123
|
examples=["2026-03-15T11:20:00Z"],
|
|
1066
1124
|
)
|
|
1067
|
-
api_request_limit: int = Field(
|
|
1068
|
-
|
|
1125
|
+
api_request_limit: int | None = Field(
|
|
1126
|
+
None,
|
|
1069
1127
|
title="API Request Limit",
|
|
1070
|
-
description=
|
|
1128
|
+
description=(
|
|
1129
|
+
"Maximum number of API requests available to the user in the current limit "
|
|
1130
|
+
"window. None when the response does not carry it, as for a workload identity."
|
|
1131
|
+
),
|
|
1071
1132
|
examples=[10000],
|
|
1072
1133
|
)
|
|
1073
|
-
mfa_enabled: bool = Field(
|
|
1074
|
-
|
|
1134
|
+
mfa_enabled: bool | None = Field(
|
|
1135
|
+
None,
|
|
1075
1136
|
title="MFA Enabled",
|
|
1076
|
-
description=
|
|
1137
|
+
description=(
|
|
1138
|
+
"Whether multi-factor authentication is enabled for the user. None when the "
|
|
1139
|
+
"response does not carry it, as for a workload identity."
|
|
1140
|
+
),
|
|
1077
1141
|
examples=[True],
|
|
1078
1142
|
)
|
|
1079
1143
|
organization: Organization | None = Field(
|
|
@@ -165,3 +165,33 @@ def test_invalid_success_is_uncertain_and_never_retried(transport, invalid):
|
|
|
165
165
|
assert exc.value.idempotency_key == "stable"
|
|
166
166
|
assert session.request.call_count == 1
|
|
167
167
|
assert session.request.call_args.kwargs["allow_redirects"] is False
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@pytest.mark.parametrize("subscription_uid", [None, "11111111-1111-4111-8111-111111111111"])
|
|
171
|
+
def test_completion_subscription_is_optional_and_preserves_request_identity(transport, subscription_uid):
|
|
172
|
+
session, response, _ = transport
|
|
173
|
+
response.json.return_value = result(custom_id=subscription_uid)
|
|
174
|
+
answer = inference.InferenceClient().complete(
|
|
175
|
+
provider="openai", model="configured-model", messages=[], idempotency_key="stable",
|
|
176
|
+
custom_id=subscription_uid,
|
|
177
|
+
)
|
|
178
|
+
body = session.request.call_args.kwargs["json"]
|
|
179
|
+
assert answer.custom_id == subscription_uid
|
|
180
|
+
assert session.request.call_args.kwargs["headers"]["Idempotency-Key"] == "stable"
|
|
181
|
+
if subscription_uid is None:
|
|
182
|
+
assert "custom_id" not in body
|
|
183
|
+
else:
|
|
184
|
+
assert body["custom_id"] == subscription_uid
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@pytest.mark.parametrize("resolved", [None, "22222222-2222-4222-8222-222222222222"])
|
|
188
|
+
def test_completion_does_not_accept_ignored_or_different_subscription(transport, resolved):
|
|
189
|
+
session, response, _ = transport
|
|
190
|
+
response.json.return_value = result(custom_id=resolved)
|
|
191
|
+
with pytest.raises(inference.InferenceTransportError) as error:
|
|
192
|
+
inference.InferenceClient().complete(
|
|
193
|
+
provider="openai", model="configured-model", messages=[], idempotency_key="stable",
|
|
194
|
+
custom_id="11111111-1111-4111-8111-111111111111",
|
|
195
|
+
)
|
|
196
|
+
assert error.value.idempotency_key == "stable"
|
|
197
|
+
assert session.request.call_count == 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md
RENAMED
|
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
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/repository_identity_security.py
RENAMED
|
File without changes
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/mainsequence/runtime_credential_exchange.py
RENAMED
|
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
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_code_repository_branch_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_code_repository_runtime_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_environment_response_contracts.py
RENAMED
|
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
|
{mainsequence-9.0.9.dev46 → mainsequence-9.0.10}/tests/test_models_user_request_bound_auth.py
RENAMED
|
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
|