ms-tau-sdk 2.0.0.dev29__tar.gz → 2.0.0.dev32__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.
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/PKG-INFO +1 -1
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/pyproject.toml +1 -1
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/models.py +3 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/sessions.py +10 -1
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/client.py +53 -23
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/local.py +110 -11
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/models.py +7 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/providers/factory.py +14 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/manager.py +7 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/settings.py +4 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/.gitignore +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/CHANGELOG.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/README.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/app.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/cli.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/config.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/env_file.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/logs.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/proxy.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/state.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/static/BULMA-LICENSE.txt +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/static/app.js +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/static/board.css +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/static/bulma.min.css +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/static/index.html +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/agent_skills/tau_a2a_runtime_adapter/SKILL.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/agent_skills/tau_local_development/SKILL.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/agent_skills/tau_project_customization/SKILL.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/agent_skills/tau_repository_integration/SKILL.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/a2a.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/chat.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/conversations.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/dependencies.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/health.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/inspection.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/local_chat.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/api/request_identity.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/app.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/application.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/assertions.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/auth.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/mcp.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/backend/routes.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/cli.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/errors.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/logging.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/protocols/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/protocols/a2a_failure.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/protocols/a2a_message.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/protocols/a2a_roles.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/protocols/assistant_ui.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/protocols/chat_history.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/protocols/strict_json.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/providers/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/providers/definitions.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/providers/tau_compat.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/resources/SYSTEM.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/resources/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/resources/loader.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/resources/prompts/review-code-repository.md +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/deployment_health.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/events.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/extensions.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/failures.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/live_turns.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/observability.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/provenance.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/session.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/snapshots.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/task_context.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/sessions/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/sessions/storage.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/skills.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/tools/__init__.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/tools/mainsequence_mcp.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/tools/skill_read.py +0 -0
- {ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/tools/task_control.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ms-tau-sdk
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev32
|
|
4
4
|
Summary: Workspace-bound Tau application primitives for Main Sequence projects
|
|
5
5
|
Project-URL: Changelog, https://github.com/mainsequence-sdk/ms-tau-sdk/blob/development/CHANGELOG.md
|
|
6
6
|
Project-URL: Documentation, https://github.com/mainsequence-sdk/ms-tau-sdk/tree/development/docs
|
|
@@ -57,6 +57,9 @@ class CancelRequest(ApiModel):
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
class SessionModelSelection(ApiModel):
|
|
60
|
+
custom_id: str | None = Field(
|
|
61
|
+
default=None, validation_alias=AliasChoices("customId", "custom_id")
|
|
62
|
+
)
|
|
60
63
|
session_uid: str = Field(validation_alias=AliasChoices("sessionUid", "session_uid"))
|
|
61
64
|
provider: str
|
|
62
65
|
model: str
|
|
@@ -37,6 +37,7 @@ async def session_model(
|
|
|
37
37
|
"provider": session.active_provider,
|
|
38
38
|
"model": session.active_model,
|
|
39
39
|
"thinkingLevel": session.active_thinking,
|
|
40
|
+
**({"customId": session.custom_id} if session.custom_id is not None else {}),
|
|
40
41
|
},
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -45,7 +46,13 @@ async def session_model(
|
|
|
45
46
|
async def model_providers(client: BackendDep, config: SettingsDep) -> dict[str, object]:
|
|
46
47
|
if not config.local_mode:
|
|
47
48
|
raise HTTPException(status_code=409, detail="Provider catalog is local-mode only")
|
|
48
|
-
return await client.list_model_providers(
|
|
49
|
+
return await client.list_model_providers(
|
|
50
|
+
**(
|
|
51
|
+
{"organization_environment_uid": config.local_organization_environment_uid}
|
|
52
|
+
if config.local_organization_environment_uid
|
|
53
|
+
else {}
|
|
54
|
+
)
|
|
55
|
+
)
|
|
49
56
|
|
|
50
57
|
|
|
51
58
|
@router.put("/session-model")
|
|
@@ -62,6 +69,7 @@ async def select_session_model(
|
|
|
62
69
|
provider=body.provider,
|
|
63
70
|
model=body.model,
|
|
64
71
|
thinking_level=body.thinking_level,
|
|
72
|
+
**({"custom_id": body.custom_id} if body.custom_id is not None else {}),
|
|
65
73
|
)
|
|
66
74
|
session = await manager.backend.get_session(session_uid)
|
|
67
75
|
return {
|
|
@@ -70,6 +78,7 @@ async def select_session_model(
|
|
|
70
78
|
"provider": session.active_provider,
|
|
71
79
|
"model": session.active_model,
|
|
72
80
|
"thinkingLevel": session.active_thinking,
|
|
81
|
+
**({"customId": session.custom_id} if session.custom_id is not None else {}),
|
|
73
82
|
},
|
|
74
83
|
}
|
|
75
84
|
|
|
@@ -356,9 +356,16 @@ class MainSequenceClient:
|
|
|
356
356
|
detail=error.errors(include_input=False),
|
|
357
357
|
) from error
|
|
358
358
|
|
|
359
|
-
async def list_model_providers(
|
|
359
|
+
async def list_model_providers(
|
|
360
|
+
self, *, organization_environment_uid: str | None = None
|
|
361
|
+
) -> dict[str, Any]:
|
|
360
362
|
"""Read the authenticated user's safe provider catalog from Main Sequence."""
|
|
361
|
-
|
|
363
|
+
options: dict[str, Any] = (
|
|
364
|
+
{"params": {"organization_environment_uid": organization_environment_uid}}
|
|
365
|
+
if organization_environment_uid
|
|
366
|
+
else {}
|
|
367
|
+
)
|
|
368
|
+
data = await self._request("GET", MODEL_PROVIDERS, idempotent=True, **options)
|
|
362
369
|
if not isinstance(data, dict) or not isinstance(data.get("providers"), list):
|
|
363
370
|
raise BackendError("Backend model-provider catalog response is invalid")
|
|
364
371
|
return data
|
|
@@ -370,6 +377,7 @@ class MainSequenceClient:
|
|
|
370
377
|
provider: str,
|
|
371
378
|
model: str,
|
|
372
379
|
thinking_level: str | None,
|
|
380
|
+
custom_id: str | None = None,
|
|
373
381
|
) -> AgentSession:
|
|
374
382
|
payload: dict[str, Any] = {
|
|
375
383
|
"llm_provider": provider,
|
|
@@ -377,13 +385,18 @@ class MainSequenceClient:
|
|
|
377
385
|
}
|
|
378
386
|
if thinking_level is not None:
|
|
379
387
|
payload["llm_thinking"] = thinking_level
|
|
388
|
+
if custom_id is not None:
|
|
389
|
+
payload["custom_id"] = custom_id
|
|
380
390
|
data = await self._request(
|
|
381
391
|
"PATCH",
|
|
382
392
|
agent_session(session_uid),
|
|
383
393
|
json=payload,
|
|
384
394
|
idempotent=True,
|
|
385
395
|
)
|
|
386
|
-
|
|
396
|
+
session = AgentSession.model_validate(data)
|
|
397
|
+
if custom_id is not None and session.custom_id != custom_id:
|
|
398
|
+
raise BackendError("Backend did not select the requested configured provider")
|
|
399
|
+
return session
|
|
387
400
|
|
|
388
401
|
async def get_agent_card(self, session_uid: str) -> AgentCardEnvelope:
|
|
389
402
|
data = await self._request(
|
|
@@ -601,23 +614,27 @@ class MainSequenceClient:
|
|
|
601
614
|
model: str,
|
|
602
615
|
session_uid: str,
|
|
603
616
|
holder_id: str,
|
|
617
|
+
custom_id: str | None = None,
|
|
604
618
|
) -> ProviderExecutionEvidence:
|
|
619
|
+
payload: dict[str, Any] = {
|
|
620
|
+
"agent_session_uid": session_uid,
|
|
621
|
+
"providers": [provider],
|
|
622
|
+
"holder_id": holder_id,
|
|
623
|
+
"supported_provider_control_schema_versions": [1],
|
|
624
|
+
"execution_selection": {"provider": provider, "model": model},
|
|
625
|
+
}
|
|
626
|
+
if custom_id is not None:
|
|
627
|
+
payload["custom_id"] = custom_id
|
|
605
628
|
data = await self._request(
|
|
606
629
|
"POST",
|
|
607
630
|
model_provider_credentials("hydrate"),
|
|
608
|
-
json=
|
|
609
|
-
"agent_session_uid": session_uid,
|
|
610
|
-
"providers": [provider],
|
|
611
|
-
"holder_id": holder_id,
|
|
612
|
-
"supported_provider_control_schema_versions": [1],
|
|
613
|
-
"execution_selection": {
|
|
614
|
-
"provider": provider,
|
|
615
|
-
"model": model,
|
|
616
|
-
},
|
|
617
|
-
},
|
|
631
|
+
json=payload,
|
|
618
632
|
idempotent=True,
|
|
619
633
|
)
|
|
620
|
-
|
|
634
|
+
evidence = self._provider_evidence(provider, data)
|
|
635
|
+
if custom_id is not None and evidence.credential.custom_id != custom_id:
|
|
636
|
+
raise BackendError("Backend did not hydrate the requested configured provider")
|
|
637
|
+
return evidence
|
|
621
638
|
|
|
622
639
|
async def hydrate_local_provider_credential(
|
|
623
640
|
self,
|
|
@@ -626,24 +643,33 @@ class MainSequenceClient:
|
|
|
626
643
|
model: str,
|
|
627
644
|
thinking_level: str | None,
|
|
628
645
|
holder_id: str,
|
|
646
|
+
custom_id: str | None = None,
|
|
647
|
+
organization_environment_uid: str | None = None,
|
|
629
648
|
) -> ProviderExecutionEvidence:
|
|
630
|
-
"""Hydrate
|
|
631
|
-
|
|
649
|
+
"""Hydrate an owned or shared selection using the backend's access checks."""
|
|
632
650
|
selection: dict[str, str] = {"provider": provider, "model": model}
|
|
633
651
|
if thinking_level:
|
|
634
652
|
selection["thinking_level"] = thinking_level
|
|
653
|
+
payload: dict[str, Any] = {
|
|
654
|
+
"providers": [provider],
|
|
655
|
+
"holder_id": holder_id,
|
|
656
|
+
"supported_provider_control_schema_versions": [1],
|
|
657
|
+
"execution_selection": selection,
|
|
658
|
+
}
|
|
659
|
+
if organization_environment_uid is not None:
|
|
660
|
+
payload["organization_environment_uid"] = organization_environment_uid
|
|
661
|
+
if custom_id is not None:
|
|
662
|
+
payload["custom_id"] = custom_id
|
|
635
663
|
data = await self._request(
|
|
636
664
|
"POST",
|
|
637
665
|
model_provider_credentials("hydrate"),
|
|
638
|
-
json=
|
|
639
|
-
"providers": [provider],
|
|
640
|
-
"holder_id": holder_id,
|
|
641
|
-
"supported_provider_control_schema_versions": [1],
|
|
642
|
-
"execution_selection": selection,
|
|
643
|
-
},
|
|
666
|
+
json=payload,
|
|
644
667
|
idempotent=True,
|
|
645
668
|
)
|
|
646
|
-
|
|
669
|
+
evidence = self._provider_evidence(provider, data)
|
|
670
|
+
if custom_id is not None and evidence.credential.custom_id != custom_id:
|
|
671
|
+
raise BackendError("Backend did not hydrate the requested configured provider")
|
|
672
|
+
return evidence
|
|
647
673
|
|
|
648
674
|
def _provider_evidence(self, provider: str, data: object) -> ProviderExecutionEvidence:
|
|
649
675
|
if not isinstance(data, dict):
|
|
@@ -679,6 +705,10 @@ class MainSequenceClient:
|
|
|
679
705
|
return ProviderCredential.model_validate(
|
|
680
706
|
{
|
|
681
707
|
"provider": provider,
|
|
708
|
+
"custom_id": hydrated.get("custom_id"),
|
|
709
|
+
"model_provider_credential_uid": hydrated.get("uid"),
|
|
710
|
+
"organization_environment_uid": hydrated.get("organization_environment_uid"),
|
|
711
|
+
"owner_user_uid": hydrated.get("user_uid"),
|
|
682
712
|
"credential_kind": credential_kind,
|
|
683
713
|
"api_key": raw.get("api_key") or raw.get("key"),
|
|
684
714
|
"access_token": access_token,
|
|
@@ -147,8 +147,15 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
147
147
|
async def aclose(self) -> None:
|
|
148
148
|
await self._services.aclose()
|
|
149
149
|
|
|
150
|
-
async def list_model_providers(
|
|
151
|
-
|
|
150
|
+
async def list_model_providers(
|
|
151
|
+
self, *, organization_environment_uid: str | None = None
|
|
152
|
+
) -> dict[str, Any]:
|
|
153
|
+
environment_uid = (
|
|
154
|
+
organization_environment_uid or self.settings.local_organization_environment_uid
|
|
155
|
+
)
|
|
156
|
+
return await self._services.list_model_providers(
|
|
157
|
+
**({"organization_environment_uid": environment_uid} if environment_uid else {})
|
|
158
|
+
)
|
|
152
159
|
|
|
153
160
|
async def _ensure_initialized(self) -> None:
|
|
154
161
|
if self._initialized:
|
|
@@ -391,6 +398,13 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
391
398
|
"TEXT NOT NULL DEFAULT ''",
|
|
392
399
|
)
|
|
393
400
|
self._ensure_schema_column(connection, "sessions", "active_task_attempt_uid", "TEXT")
|
|
401
|
+
self._ensure_schema_column(connection, "sessions", "custom_id", "TEXT")
|
|
402
|
+
self._ensure_schema_column(
|
|
403
|
+
connection, "sessions", "model_provider_credential_uid", "TEXT"
|
|
404
|
+
)
|
|
405
|
+
self._ensure_schema_column(
|
|
406
|
+
connection, "sessions", "organization_environment_uid", "TEXT"
|
|
407
|
+
)
|
|
394
408
|
self._ensure_schema_column(connection, "entries", "turn_uid", "TEXT")
|
|
395
409
|
self._ensure_schema_column(connection, "a2a_task_attempts", "turn_uid", "TEXT")
|
|
396
410
|
self._ensure_schema_column(
|
|
@@ -513,14 +527,31 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
513
527
|
return "sha256:" + hashlib.sha256(payload).hexdigest()
|
|
514
528
|
|
|
515
529
|
async def _hydrate_evidence(
|
|
516
|
-
self,
|
|
530
|
+
self,
|
|
531
|
+
*,
|
|
532
|
+
holder_id: str,
|
|
533
|
+
selection: tuple[str, str, str | None] | None = None,
|
|
534
|
+
custom_id: str | None = None,
|
|
535
|
+
credential_uid: str | None = None,
|
|
536
|
+
organization_environment_uid: str | None = None,
|
|
517
537
|
) -> ProviderExecutionEvidence:
|
|
518
538
|
provider, model, thinking = selection or self._selection()
|
|
539
|
+
options: dict[str, Any] = {}
|
|
540
|
+
if custom_id is None and selection is None:
|
|
541
|
+
custom_id = self.settings.local_custom_id
|
|
542
|
+
environment_uid = (
|
|
543
|
+
organization_environment_uid or self.settings.local_organization_environment_uid
|
|
544
|
+
)
|
|
545
|
+
if custom_id is not None:
|
|
546
|
+
options["custom_id"] = custom_id
|
|
547
|
+
if environment_uid is not None:
|
|
548
|
+
options["organization_environment_uid"] = environment_uid
|
|
519
549
|
evidence = await self._services.hydrate_local_provider_credential(
|
|
520
550
|
provider,
|
|
521
551
|
model=model,
|
|
522
552
|
thinking_level=thinking,
|
|
523
553
|
holder_id=holder_id,
|
|
554
|
+
**options,
|
|
524
555
|
)
|
|
525
556
|
if (
|
|
526
557
|
evidence.provider_control.provider != provider
|
|
@@ -529,6 +560,16 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
529
560
|
raise BackendConflictError(
|
|
530
561
|
"Main Sequence provider evidence does not match the local selection"
|
|
531
562
|
)
|
|
563
|
+
if (
|
|
564
|
+
credential_uid is not None
|
|
565
|
+
and evidence.credential.model_provider_credential_uid != credential_uid
|
|
566
|
+
):
|
|
567
|
+
raise BackendConflictError("Main Sequence changed the local session credential")
|
|
568
|
+
if (
|
|
569
|
+
environment_uid is not None
|
|
570
|
+
and evidence.credential.organization_environment_uid != environment_uid
|
|
571
|
+
):
|
|
572
|
+
raise BackendConflictError("Main Sequence changed the local session Environment")
|
|
532
573
|
return evidence
|
|
533
574
|
|
|
534
575
|
async def prefetch_provider(self) -> None:
|
|
@@ -560,6 +601,10 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
560
601
|
return {
|
|
561
602
|
"credentials": {
|
|
562
603
|
credential.provider: {
|
|
604
|
+
"uid": credential.model_provider_credential_uid,
|
|
605
|
+
"custom_id": credential.custom_id,
|
|
606
|
+
"organization_environment_uid": credential.organization_environment_uid,
|
|
607
|
+
"user_uid": credential.owner_user_uid,
|
|
563
608
|
"credential_kind": credential.credential_kind,
|
|
564
609
|
"credential": {key: value for key, value in raw.items() if value is not None},
|
|
565
610
|
"version": credential.metadata.get("version"),
|
|
@@ -576,14 +621,24 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
576
621
|
session_uid: str | None = None,
|
|
577
622
|
agent_uid: str | None = None,
|
|
578
623
|
holder_id: str,
|
|
624
|
+
custom_id: str | None = None,
|
|
579
625
|
) -> ProviderExecutionEvidence:
|
|
580
626
|
del agent_uid
|
|
581
627
|
selected_provider, selected_model, selected_thinking = self._selection()
|
|
628
|
+
credential_uid = None
|
|
629
|
+
environment_uid = None
|
|
582
630
|
if session_uid is not None:
|
|
583
631
|
session = await self.get_session(session_uid)
|
|
584
632
|
selected_provider = session.active_provider or ""
|
|
585
633
|
selected_model = session.active_model or ""
|
|
586
634
|
selected_thinking = session.active_thinking
|
|
635
|
+
if custom_id is not None and custom_id != session.custom_id:
|
|
636
|
+
raise BackendConflictError(
|
|
637
|
+
"Local refresh must retain the session's configured provider"
|
|
638
|
+
)
|
|
639
|
+
custom_id = session.custom_id
|
|
640
|
+
credential_uid = session.model_provider_credential_uid
|
|
641
|
+
environment_uid = session.organization_environment_uid
|
|
587
642
|
if provider != selected_provider or model != selected_model:
|
|
588
643
|
raise BackendConflictError(
|
|
589
644
|
"Local provider refresh does not match the session selection"
|
|
@@ -595,6 +650,9 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
595
650
|
return await self._hydrate_evidence(
|
|
596
651
|
holder_id=holder_id,
|
|
597
652
|
selection=(selected_provider, selected_model, selected_thinking),
|
|
653
|
+
custom_id=custom_id,
|
|
654
|
+
credential_uid=credential_uid,
|
|
655
|
+
organization_environment_uid=environment_uid,
|
|
598
656
|
)
|
|
599
657
|
|
|
600
658
|
async def get_session(self, session_uid: str) -> AgentSession:
|
|
@@ -617,13 +675,19 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
617
675
|
provider: str,
|
|
618
676
|
model: str,
|
|
619
677
|
thinking_level: str | None,
|
|
678
|
+
custom_id: str | None = None,
|
|
620
679
|
) -> AgentSession:
|
|
621
680
|
if not provider or not model:
|
|
622
681
|
raise BackendConflictError("A provider and model are required")
|
|
623
682
|
selection = (provider, model, thinking_level)
|
|
624
|
-
await self.
|
|
683
|
+
previous = await self.get_session(session_uid)
|
|
684
|
+
retained = custom_id is None and previous.active_provider == provider
|
|
685
|
+
evidence = await self._hydrate_evidence(
|
|
625
686
|
holder_id=f"local-selection-{self.settings.workspace_digest}",
|
|
626
687
|
selection=selection,
|
|
688
|
+
custom_id=previous.custom_id if retained else custom_id,
|
|
689
|
+
credential_uid=previous.model_provider_credential_uid if retained else None,
|
|
690
|
+
organization_environment_uid=previous.organization_environment_uid,
|
|
627
691
|
)
|
|
628
692
|
|
|
629
693
|
def operation() -> None:
|
|
@@ -637,11 +701,16 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
637
701
|
raise BackendConflictError("Cannot change a model while the session is working")
|
|
638
702
|
connection.execute(
|
|
639
703
|
"UPDATE sessions SET provider = ?, model = ?, thinking = ?, "
|
|
640
|
-
"runtime_config_sha256 = ?, updated_at =
|
|
704
|
+
"runtime_config_sha256 = ?, updated_at = ?, custom_id = ?, "
|
|
705
|
+
"model_provider_credential_uid = ?, "
|
|
706
|
+
"organization_environment_uid = ? WHERE uid = ?",
|
|
641
707
|
(
|
|
642
708
|
*selection,
|
|
643
709
|
self._runtime_config_sha256(selection),
|
|
644
710
|
_iso(_utcnow()),
|
|
711
|
+
evidence.credential.custom_id,
|
|
712
|
+
evidence.credential.model_provider_credential_uid,
|
|
713
|
+
evidence.credential.organization_environment_uid,
|
|
645
714
|
session_uid,
|
|
646
715
|
),
|
|
647
716
|
)
|
|
@@ -1504,6 +1573,9 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
1504
1573
|
"active_provider": str(row["provider"]),
|
|
1505
1574
|
"active_model": str(row["model"]),
|
|
1506
1575
|
"active_thinking": row["thinking"],
|
|
1576
|
+
"custom_id": row["custom_id"],
|
|
1577
|
+
"model_provider_credential_uid": row["model_provider_credential_uid"],
|
|
1578
|
+
"organization_environment_uid": row["organization_environment_uid"],
|
|
1507
1579
|
"status": "local",
|
|
1508
1580
|
"runtime_capabilities": LOCAL_RUNTIME_CAPABILITIES,
|
|
1509
1581
|
"runtime_config_sha256": str(row["runtime_config_sha256"]),
|
|
@@ -1586,18 +1658,31 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
1586
1658
|
session_uid: str,
|
|
1587
1659
|
request: TauRuntimeBootstrapRequest,
|
|
1588
1660
|
) -> TauRuntimeBootstrap:
|
|
1589
|
-
def stored_selection() -> tuple[
|
|
1661
|
+
def stored_selection() -> tuple[
|
|
1662
|
+
tuple[str, str, str | None], str | None, str | None, str | None
|
|
1663
|
+
]:
|
|
1590
1664
|
with closing(self._connect()) as connection:
|
|
1591
1665
|
row = connection.execute(
|
|
1592
|
-
"SELECT
|
|
1666
|
+
"SELECT * FROM sessions WHERE uid = ?", (session_uid,)
|
|
1593
1667
|
).fetchone()
|
|
1594
1668
|
if row is None:
|
|
1595
|
-
return self._selection()
|
|
1596
|
-
return
|
|
1669
|
+
return self._selection(), self.settings.local_custom_id, None, None
|
|
1670
|
+
return (
|
|
1671
|
+
(str(row["provider"]), str(row["model"]), row["thinking"]),
|
|
1672
|
+
row["custom_id"],
|
|
1673
|
+
row["model_provider_credential_uid"],
|
|
1674
|
+
row["organization_environment_uid"],
|
|
1675
|
+
)
|
|
1597
1676
|
|
|
1598
|
-
selection = await self._run(stored_selection)
|
|
1677
|
+
selection, custom_id, credential_uid, environment_uid = await self._run(stored_selection)
|
|
1599
1678
|
provider, model, thinking = selection
|
|
1600
|
-
evidence = await self._hydrate_evidence(
|
|
1679
|
+
evidence = await self._hydrate_evidence(
|
|
1680
|
+
holder_id=request.holder_id,
|
|
1681
|
+
selection=selection,
|
|
1682
|
+
custom_id=custom_id,
|
|
1683
|
+
credential_uid=credential_uid,
|
|
1684
|
+
organization_environment_uid=environment_uid,
|
|
1685
|
+
)
|
|
1601
1686
|
|
|
1602
1687
|
def operation() -> TauRuntimeBootstrap:
|
|
1603
1688
|
now = _utcnow()
|
|
@@ -1640,6 +1725,20 @@ class LocalDevelopmentBackend(MainSequenceClient):
|
|
|
1640
1725
|
raise BackendConflictError(
|
|
1641
1726
|
"Existing local session uses a different provider/model selection"
|
|
1642
1727
|
)
|
|
1728
|
+
if row is not None and row["model_provider_credential_uid"] is None:
|
|
1729
|
+
connection.execute(
|
|
1730
|
+
"UPDATE sessions SET custom_id = ?, model_provider_credential_uid = ?, "
|
|
1731
|
+
"organization_environment_uid = ? WHERE uid = ?",
|
|
1732
|
+
(
|
|
1733
|
+
evidence.credential.custom_id,
|
|
1734
|
+
evidence.credential.model_provider_credential_uid,
|
|
1735
|
+
evidence.credential.organization_environment_uid,
|
|
1736
|
+
session_uid,
|
|
1737
|
+
),
|
|
1738
|
+
)
|
|
1739
|
+
row = connection.execute(
|
|
1740
|
+
"SELECT * FROM sessions WHERE uid = ?", (session_uid,)
|
|
1741
|
+
).fetchone()
|
|
1643
1742
|
assert row is not None
|
|
1644
1743
|
current_lease = connection.execute(
|
|
1645
1744
|
"SELECT * FROM leases WHERE session_uid = ?",
|
|
@@ -52,7 +52,10 @@ class BackendRequestModel(BackendModel):
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
class AgentSession(BackendModel):
|
|
55
|
+
organization_environment_uid: str | None = None
|
|
55
56
|
uid: str
|
|
57
|
+
custom_id: str | None = None
|
|
58
|
+
model_provider_credential_uid: str | None = None
|
|
56
59
|
agent_uid: str | None = None
|
|
57
60
|
harness: HarnessKind
|
|
58
61
|
harness_protocol: HarnessProtocol
|
|
@@ -389,6 +392,10 @@ class TauResumeSnapshotUploadResponse(BackendModel):
|
|
|
389
392
|
|
|
390
393
|
class ProviderCredential(BackendModel):
|
|
391
394
|
provider: str
|
|
395
|
+
custom_id: str | None = None
|
|
396
|
+
model_provider_credential_uid: str | None = None
|
|
397
|
+
organization_environment_uid: str | None = None
|
|
398
|
+
owner_user_uid: str | None = None
|
|
392
399
|
credential_kind: str = "api_key"
|
|
393
400
|
api: str | None = None
|
|
394
401
|
api_key: SecretStr | None = None
|
|
@@ -291,6 +291,11 @@ class ProviderFactory:
|
|
|
291
291
|
credential = evidence.credential
|
|
292
292
|
if credential.provider != provider_name:
|
|
293
293
|
raise ConfigurationError("Backend credential does not match the selected provider")
|
|
294
|
+
if (
|
|
295
|
+
session.model_provider_credential_uid is not None
|
|
296
|
+
and credential.model_provider_credential_uid != session.model_provider_credential_uid
|
|
297
|
+
):
|
|
298
|
+
raise ConfigurationError("Backend credential does not match the session binding")
|
|
294
299
|
thinking_level = self.validate_execution(
|
|
295
300
|
evidence.provider_control,
|
|
296
301
|
provider_name=provider_name,
|
|
@@ -324,6 +329,15 @@ class ProviderFactory:
|
|
|
324
329
|
"Provider-control execution capability changed during "
|
|
325
330
|
"credential refresh"
|
|
326
331
|
)
|
|
332
|
+
if cached_credential.model_provider_credential_uid is not None and (
|
|
333
|
+
refreshed.credential.model_provider_credential_uid
|
|
334
|
+
!= cached_credential.model_provider_credential_uid
|
|
335
|
+
or refreshed.credential.organization_environment_uid
|
|
336
|
+
!= cached_credential.organization_environment_uid
|
|
337
|
+
):
|
|
338
|
+
raise ConfigurationError(
|
|
339
|
+
"Credential refresh changed the configured provider"
|
|
340
|
+
)
|
|
327
341
|
cached_credential = refreshed.credential
|
|
328
342
|
return cached_credential
|
|
329
343
|
|
|
@@ -2080,6 +2080,7 @@ class SessionRuntimeManager:
|
|
|
2080
2080
|
provider: str,
|
|
2081
2081
|
model: str,
|
|
2082
2082
|
thinking_level: str | None,
|
|
2083
|
+
custom_id: str | None = None,
|
|
2083
2084
|
) -> None:
|
|
2084
2085
|
"""Switch an idle session and reload it with backend-authorized evidence."""
|
|
2085
2086
|
if not self.settings.local_mode:
|
|
@@ -2105,6 +2106,7 @@ class SessionRuntimeManager:
|
|
|
2105
2106
|
provider=provider,
|
|
2106
2107
|
model=model,
|
|
2107
2108
|
thinking_level=thinking_level,
|
|
2109
|
+
**({"custom_id": custom_id} if custom_id is not None else {}),
|
|
2108
2110
|
)
|
|
2109
2111
|
except BaseException:
|
|
2110
2112
|
runtime.evicting = False
|
|
@@ -2119,6 +2121,11 @@ class SessionRuntimeManager:
|
|
|
2119
2121
|
provider=previous.active_provider,
|
|
2120
2122
|
model=previous.active_model,
|
|
2121
2123
|
thinking_level=previous.active_thinking,
|
|
2124
|
+
**(
|
|
2125
|
+
{"custom_id": previous.custom_id}
|
|
2126
|
+
if previous.custom_id is not None
|
|
2127
|
+
else {}
|
|
2128
|
+
),
|
|
2122
2129
|
)
|
|
2123
2130
|
await self._load(session_uid)
|
|
2124
2131
|
except Exception:
|
|
@@ -152,6 +152,10 @@ class TauSDKSettings(BaseSettings):
|
|
|
152
152
|
default=False,
|
|
153
153
|
validation_alias="TAU_EXCLUDE_MAINSEQUENCE_MCP",
|
|
154
154
|
)
|
|
155
|
+
local_custom_id: str | None = Field(default=None, validation_alias="TAU_LOCAL_CUSTOM_ID")
|
|
156
|
+
local_organization_environment_uid: str | None = Field(
|
|
157
|
+
default=None, validation_alias="TAU_LOCAL_ORGANIZATION_ENVIRONMENT_UID"
|
|
158
|
+
)
|
|
155
159
|
local_provider: str | None = Field(default=None, validation_alias="TAU_LOCAL_PROVIDER")
|
|
156
160
|
local_model: str | None = Field(default=None, validation_alias="TAU_LOCAL_MODEL")
|
|
157
161
|
local_thinking: (
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/__init__.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/app.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/cli.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/config.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/env_file.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/logs.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/proxy.py
RENAMED
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/state.py
RENAMED
|
File without changes
|
|
File without changes
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/packages/tau-board/src/ms_tau_board/static/app.js
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
|
{ms_tau_sdk-2.0.0.dev29 → ms_tau_sdk-2.0.0.dev32}/src/ms_tau_sdk/runtime/deployment_health.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
|