mainsequence 8.1.20.dev3__tar.gz → 8.1.20.dev7__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-8.1.20.dev3/mainsequence.egg-info → mainsequence-8.1.20.dev7}/PKG-INFO +1 -1
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +10 -5
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +13 -9
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +9 -4
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/base.py +14 -1
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/metatables/core.py +48 -65
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/models_foundry.py +0 -29
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence.egg-info/SOURCES.txt +1 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/pyproject.toml +1 -1
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_canonical_api_route_contract.py +18 -1
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_code_repository_branch_contract.py +6 -2
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_code_repository_documentation_contract.py +53 -4
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_code_repository_runtime_context.py +7 -3
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_environment_response_contracts.py +5 -5
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_filter_normalization.py +63 -32
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_observability_client.py +6 -5
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_source_table_configuration.py +14 -8
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_time_index_table_update_configuration_client.py +6 -3
- mainsequence-8.1.20.dev7/tests/test_tolerant_response_reading.py +137 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_update_uid_guards.py +0 -1
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/LICENSE +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/MANIFEST.in +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/README.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/__main__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/bootstrap.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/api.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/cli.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/code_repository_status.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/config.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/migrations.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/cli/ui.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/client.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/github_issues.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/models_user.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/observability.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/utils.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/code_repository_context.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/code_repository_skills.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/defaults.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/logconf.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/alembic.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/env.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/provider.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/registry.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/repository_identity_security.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/setup.cfg +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_auth_precedence.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_cli.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_cli_migrations.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_client.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_code_repository_batch_jobs_from_file.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_code_repository_skills.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_dependency_extras.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_dev_release_version.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_environment_resource_context.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_github_issues_client.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_instrumentation.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_local_ops.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_logconf.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_meta_table_migrations.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_meta_tables_client_models.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_notification_uid_contract.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_schema_names.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_secret_client_model.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_ssh_utils.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_time_index_table_access_dimension_audit.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_time_index_table_dimension_queries.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_time_index_table_update_configuration.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_time_index_table_update_flow.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_time_index_table_update_hard_cut.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_update_statistics.py +0 -0
|
@@ -17,11 +17,16 @@ platform-managed application tables outside the migration workflow.
|
|
|
17
17
|
|
|
18
18
|
## Read First
|
|
19
19
|
|
|
20
|
-
1. `docs/
|
|
21
|
-
2. `docs/knowledge/meta_tables/
|
|
22
|
-
3. `docs/
|
|
23
|
-
4. `docs/adr/
|
|
24
|
-
|
|
20
|
+
1. `docs/knowledge/meta_tables/migrations.md`
|
|
21
|
+
2. `docs/knowledge/meta_tables/api.md`
|
|
22
|
+
3. `docs/adr/0020-metatable-migration-artifact-registry.md`
|
|
23
|
+
4. `docs/adr/0026-sdk-owned-migration-scaffolding.md`
|
|
24
|
+
|
|
25
|
+
`docs/knowledge/meta_tables/migrations.md` is the authoritative SDK reference for
|
|
26
|
+
provider behavior and migration contracts. The runnable beginner migration
|
|
27
|
+
walkthrough is maintained in the separate canonical tutorial CodeRepository at
|
|
28
|
+
<https://github.com/mainsequence-projects/mainsequence-sdk-tutorial>; read it
|
|
29
|
+
only when a runnable end-to-end example is needed.
|
|
25
30
|
|
|
26
31
|
## Required Decisions
|
|
27
32
|
|
|
@@ -49,15 +49,19 @@ If the user is still in the discovery process and does not yet know what data ex
|
|
|
49
49
|
|
|
50
50
|
## Read First
|
|
51
51
|
|
|
52
|
-
1. `docs/
|
|
53
|
-
2.
|
|
52
|
+
1. `docs/knowledge/meta_tables/index.md`
|
|
53
|
+
2. `docs/knowledge/meta_tables/sqlalchemy.md`
|
|
54
|
+
3. `docs/knowledge/meta_tables/compiled_sql.md`
|
|
55
|
+
4. `docs/knowledge/meta_tables/migrations.md`
|
|
56
|
+
5. `docs/knowledge/meta_tables/api.md`
|
|
57
|
+
6. For migration work, use
|
|
54
58
|
`.agents/skills/mainsequence/data_publishing/meta_table_migrations/SKILL.md`
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
|
|
60
|
+
The knowledge pages above are the authoritative SDK reference for MetaTables.
|
|
61
|
+
The runnable beginner walkthrough is maintained in the separate canonical
|
|
62
|
+
tutorial CodeRepository at
|
|
63
|
+
<https://github.com/mainsequence-projects/mainsequence-sdk-tutorial>; read it
|
|
64
|
+
only when a runnable end-to-end example is needed.
|
|
61
65
|
|
|
62
66
|
## Inputs This Skill Needs
|
|
63
67
|
|
|
@@ -310,7 +314,7 @@ asset_meta_table = MetaTable.register(asset_request)
|
|
|
310
314
|
|
|
311
315
|
When doing migration work, use
|
|
312
316
|
`.agents/skills/mainsequence/data_publishing/meta_table_migrations/SKILL.md`
|
|
313
|
-
and read `docs/
|
|
317
|
+
and read `docs/knowledge/meta_tables/migrations.md`. The migration skill owns the
|
|
314
318
|
provider-based Alembic lifecycle.
|
|
315
319
|
|
|
316
320
|
Do not apply in-place contract changes by changing a `PlatformManagedMetaTable`
|
|
@@ -61,11 +61,16 @@ This skill only reasons about access to deployed resources such as `ResourceRele
|
|
|
61
61
|
|
|
62
62
|
## Read First
|
|
63
63
|
|
|
64
|
-
1. `docs/
|
|
65
|
-
2. `docs/knowledge/infrastructure/
|
|
66
|
-
3. `docs/knowledge/infrastructure/constants_and_secrets.md`
|
|
64
|
+
1. `docs/knowledge/infrastructure/users_and_access.md`
|
|
65
|
+
2. `docs/knowledge/infrastructure/constants_and_secrets.md`
|
|
67
66
|
|
|
68
|
-
If the task is specifically about a resource type, also read the corresponding knowledge or
|
|
67
|
+
If the task is specifically about a resource type, also read the corresponding knowledge or CLI page for that resource.
|
|
68
|
+
|
|
69
|
+
The knowledge pages above are the authoritative SDK reference for access control
|
|
70
|
+
and sharing. The runnable beginner walkthrough is maintained in the separate
|
|
71
|
+
canonical tutorial CodeRepository at
|
|
72
|
+
<https://github.com/mainsequence-projects/mainsequence-sdk-tutorial>; read it
|
|
73
|
+
only when a runnable end-to-end example is needed.
|
|
69
74
|
|
|
70
75
|
## Inputs This Skill Needs
|
|
71
76
|
|
|
@@ -58,7 +58,9 @@ class HtmlSaveException(Exception):
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
class BasePydanticModel(BaseModel):
|
|
61
|
-
|
|
61
|
+
# Tolerant reading (ADR 0032): a backend response that carries a field this
|
|
62
|
+
# SDK release does not declare parses, and the undeclared field is dropped.
|
|
63
|
+
model_config = ConfigDict(extra="ignore")
|
|
62
64
|
orm_class: str = None # This will be set to the class that inherits
|
|
63
65
|
|
|
64
66
|
@classmethod
|
|
@@ -780,10 +782,21 @@ class BaseObjectOrm:
|
|
|
780
782
|
|
|
781
783
|
return raw_key
|
|
782
784
|
|
|
785
|
+
def _declares_field(obj, field_name: str) -> bool:
|
|
786
|
+
if not isinstance(obj, BaseModel):
|
|
787
|
+
return True
|
|
788
|
+
if field_name in type(obj).model_fields:
|
|
789
|
+
return True
|
|
790
|
+
# Tolerant reading (ADR 0032): a model that keeps undeclared keys can
|
|
791
|
+
# take them; every other model drops them, as parsing does.
|
|
792
|
+
return type(obj).model_config.get("extra") == "allow"
|
|
793
|
+
|
|
783
794
|
def recursive_update(obj, update_dict, path=()):
|
|
784
795
|
for k, v in update_dict.items():
|
|
785
796
|
current_path = (*path, k)
|
|
786
797
|
field_name = _resolve_model_field_name(obj, k)
|
|
798
|
+
if not _declares_field(obj, field_name):
|
|
799
|
+
continue
|
|
787
800
|
# Get the existing nested object, defaulting to None if it doesn't exist
|
|
788
801
|
nested_obj = getattr(obj, field_name, None)
|
|
789
802
|
|
{mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/mainsequence/client/metatables/core.py
RENAMED
|
@@ -1945,54 +1945,6 @@ class MetaTable(
|
|
|
1945
1945
|
raise_for_response(response, payload=error_payload)
|
|
1946
1946
|
return response.json()
|
|
1947
1947
|
|
|
1948
|
-
@classmethod
|
|
1949
|
-
def description_search(
|
|
1950
|
-
cls,
|
|
1951
|
-
q: str,
|
|
1952
|
-
*,
|
|
1953
|
-
q_embedding: Sequence[float] | None = None,
|
|
1954
|
-
trigram_k: int = 200,
|
|
1955
|
-
embed_k: int = 200,
|
|
1956
|
-
w_trgm: float = 0.65,
|
|
1957
|
-
w_emb: float = 0.35,
|
|
1958
|
-
embedding_model: str = "default",
|
|
1959
|
-
**filters,
|
|
1960
|
-
):
|
|
1961
|
-
q = (q or "").strip()
|
|
1962
|
-
if not q:
|
|
1963
|
-
raise ValueError("q is required")
|
|
1964
|
-
operation = f"{cls.__name__}.description_search"
|
|
1965
|
-
cls._reject_sdk_context_overrides(filters, operation=operation)
|
|
1966
|
-
|
|
1967
|
-
body = {
|
|
1968
|
-
"q": q,
|
|
1969
|
-
"trigram_k": trigram_k,
|
|
1970
|
-
"embed_k": embed_k,
|
|
1971
|
-
"w_trgm": w_trgm,
|
|
1972
|
-
"w_emb": w_emb,
|
|
1973
|
-
"embedding_model": embedding_model,
|
|
1974
|
-
}
|
|
1975
|
-
|
|
1976
|
-
if q_embedding is not None:
|
|
1977
|
-
body["q_embedding"] = [float(x) for x in q_embedding]
|
|
1978
|
-
|
|
1979
|
-
if filters:
|
|
1980
|
-
body.update(filters)
|
|
1981
|
-
body.update(cls._sdk_owned_query_context(operation))
|
|
1982
|
-
|
|
1983
|
-
payload = {"params": serialize_to_json(body)}
|
|
1984
|
-
response = make_request(
|
|
1985
|
-
s=cls.build_session(),
|
|
1986
|
-
loaders=cls.LOADERS,
|
|
1987
|
-
r_type="GET",
|
|
1988
|
-
url=f"{cls.get_object_url().rstrip('/')}/description-search/",
|
|
1989
|
-
payload=payload,
|
|
1990
|
-
)
|
|
1991
|
-
if response.status_code != 200:
|
|
1992
|
-
raise_for_response(response, payload=payload)
|
|
1993
|
-
|
|
1994
|
-
return cls._deserialize_search_response(response.json())
|
|
1995
|
-
|
|
1996
1948
|
@classmethod
|
|
1997
1949
|
def column_search(cls, q: str, **filters):
|
|
1998
1950
|
q = (q or "").strip()
|
|
@@ -2768,23 +2720,6 @@ class TimeIndexTableUpdate(TableUpdateNode, BaseObjectOrm):
|
|
|
2768
2720
|
return None
|
|
2769
2721
|
return r.json()
|
|
2770
2722
|
|
|
2771
|
-
def verify_if_direct_dependencies_are_updated(self) -> dict:
|
|
2772
|
-
"""
|
|
2773
|
-
Response({
|
|
2774
|
-
"error_on_update_dependencies": False,
|
|
2775
|
-
"updated": all_success,
|
|
2776
|
-
})
|
|
2777
|
-
"""
|
|
2778
|
-
s = self.build_session()
|
|
2779
|
-
url = (
|
|
2780
|
-
self.get_object_url()
|
|
2781
|
-
+ f"/{self._public_uid()}/verify-if-direct-dependencies-are-updated/"
|
|
2782
|
-
)
|
|
2783
|
-
r = make_request(s=s, loaders=None, r_type="GET", url=url)
|
|
2784
|
-
if r.status_code != 200:
|
|
2785
|
-
raise Exception(f"Error in request: {r.text}")
|
|
2786
|
-
return r.json()
|
|
2787
|
-
|
|
2788
2723
|
def get_data_between_dates_from_api(self, *args, **kwargs):
|
|
2789
2724
|
return self.output_table.get_data_between_dates_from_api(*args, **kwargs)
|
|
2790
2725
|
|
|
@@ -3259,6 +3194,54 @@ class TimeIndexMetaTable(MetaTable):
|
|
|
3259
3194
|
)
|
|
3260
3195
|
return self
|
|
3261
3196
|
|
|
3197
|
+
@classmethod
|
|
3198
|
+
def description_search(
|
|
3199
|
+
cls,
|
|
3200
|
+
q: str,
|
|
3201
|
+
*,
|
|
3202
|
+
q_embedding: Sequence[float] | None = None,
|
|
3203
|
+
trigram_k: int = 200,
|
|
3204
|
+
embed_k: int = 200,
|
|
3205
|
+
w_trgm: float = 0.65,
|
|
3206
|
+
w_emb: float = 0.35,
|
|
3207
|
+
embedding_model: str = "default",
|
|
3208
|
+
**filters,
|
|
3209
|
+
):
|
|
3210
|
+
q = (q or "").strip()
|
|
3211
|
+
if not q:
|
|
3212
|
+
raise ValueError("q is required")
|
|
3213
|
+
operation = f"{cls.__name__}.description_search"
|
|
3214
|
+
cls._reject_sdk_context_overrides(filters, operation=operation)
|
|
3215
|
+
|
|
3216
|
+
body = {
|
|
3217
|
+
"q": q,
|
|
3218
|
+
"trigram_k": trigram_k,
|
|
3219
|
+
"embed_k": embed_k,
|
|
3220
|
+
"w_trgm": w_trgm,
|
|
3221
|
+
"w_emb": w_emb,
|
|
3222
|
+
"embedding_model": embedding_model,
|
|
3223
|
+
}
|
|
3224
|
+
|
|
3225
|
+
if q_embedding is not None:
|
|
3226
|
+
body["q_embedding"] = [float(x) for x in q_embedding]
|
|
3227
|
+
|
|
3228
|
+
if filters:
|
|
3229
|
+
body.update(filters)
|
|
3230
|
+
body.update(cls._sdk_owned_query_context(operation))
|
|
3231
|
+
|
|
3232
|
+
payload = {"params": serialize_to_json(body)}
|
|
3233
|
+
response = make_request(
|
|
3234
|
+
s=cls.build_session(),
|
|
3235
|
+
loaders=cls.LOADERS,
|
|
3236
|
+
r_type="GET",
|
|
3237
|
+
url=f"{cls.get_object_url().rstrip('/')}/description-search/",
|
|
3238
|
+
payload=payload,
|
|
3239
|
+
)
|
|
3240
|
+
if response.status_code != 200:
|
|
3241
|
+
raise_for_response(response, payload=payload)
|
|
3242
|
+
|
|
3243
|
+
return cls._deserialize_search_response(response.json())
|
|
3244
|
+
|
|
3262
3245
|
def _time_indexed_storage_layout(self) -> dict[str, Any]:
|
|
3263
3246
|
profile = self.time_indexed_profile
|
|
3264
3247
|
if profile is not None and isinstance(profile.storage_layout, Mapping):
|
|
@@ -697,13 +697,6 @@ class GitHubRepositoryBranchList(BasePydanticModel):
|
|
|
697
697
|
results: list[GitHubRepositoryBranch]
|
|
698
698
|
|
|
699
699
|
|
|
700
|
-
class GitHubRepositoryBranchImportResult(BasePydanticModel):
|
|
701
|
-
repository_uid: str
|
|
702
|
-
code_repository_branch_uid: str
|
|
703
|
-
repository_branch: str
|
|
704
|
-
is_initialized: bool
|
|
705
|
-
|
|
706
|
-
|
|
707
700
|
class GitHubRepositoryBinding(BasePydanticModel, BaseObjectOrm):
|
|
708
701
|
FILTERSET_FIELDS: ClassVar[dict[str, list[str]]] = {
|
|
709
702
|
"uid": ["in", "exact"],
|
|
@@ -731,28 +724,6 @@ class GitHubRepositoryBinding(BasePydanticModel, BaseObjectOrm):
|
|
|
731
724
|
raise_for_response(r)
|
|
732
725
|
return GitHubRepositoryBranchList.model_validate(r.json())
|
|
733
726
|
|
|
734
|
-
def import_branch(
|
|
735
|
-
self,
|
|
736
|
-
*,
|
|
737
|
-
repository_branch: str,
|
|
738
|
-
metatables_data_source_uid: str | None = None,
|
|
739
|
-
timeout=None,
|
|
740
|
-
) -> GitHubRepositoryBranchImportResult:
|
|
741
|
-
body: dict[str, Any] = {"repository_branch": repository_branch}
|
|
742
|
-
if metatables_data_source_uid is not None:
|
|
743
|
-
body["metatables_data_source_uid"] = str(metatables_data_source_uid)
|
|
744
|
-
url = f"{type(self).get_object_url()}/{self._public_detail_reference()}/import-branch/"
|
|
745
|
-
r = make_request(
|
|
746
|
-
s=type(self).build_session(),
|
|
747
|
-
loaders=type(self).LOADERS,
|
|
748
|
-
r_type="POST",
|
|
749
|
-
url=url,
|
|
750
|
-
payload={"json": body},
|
|
751
|
-
time_out=timeout,
|
|
752
|
-
)
|
|
753
|
-
raise_for_response(r)
|
|
754
|
-
return GitHubRepositoryBranchImportResult.model_validate(r.json())
|
|
755
|
-
|
|
756
727
|
|
|
757
728
|
class CodeRepositoryImageSourceProvenance(BasePydanticModel):
|
|
758
729
|
verification_state: Literal["verified", "unverified", "building", "failed"]
|
|
@@ -133,6 +133,7 @@ tests/test_time_index_table_update_configuration.py
|
|
|
133
133
|
tests/test_time_index_table_update_configuration_client.py
|
|
134
134
|
tests/test_time_index_table_update_flow.py
|
|
135
135
|
tests/test_time_index_table_update_hard_cut.py
|
|
136
|
+
tests/test_tolerant_response_reading.py
|
|
136
137
|
tests/test_update_runner_uid_runtime.py
|
|
137
138
|
tests/test_update_statistics.py
|
|
138
139
|
tests/test_update_uid_guards.py
|
{mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_canonical_api_route_contract.py
RENAMED
|
@@ -129,11 +129,18 @@ def test_client_auth_provider_routes_match_backend_contract(monkeypatch):
|
|
|
129
129
|
|
|
130
130
|
def test_removed_backend_actions_are_not_exposed_by_client_models():
|
|
131
131
|
from mainsequence.client.metatables import DataSource, TimeIndexTableUpdate
|
|
132
|
+
from mainsequence.client.models_foundry import GitHubRepositoryBinding
|
|
132
133
|
from mainsequence.client.models_helpers import Job
|
|
133
134
|
|
|
134
135
|
removed_actions = {
|
|
135
136
|
DataSource: ("get_or_create_sqlite", "create_sqlite"),
|
|
136
|
-
TimeIndexTableUpdate: (
|
|
137
|
+
TimeIndexTableUpdate: (
|
|
138
|
+
"add_tags",
|
|
139
|
+
"filter_by_hash_id",
|
|
140
|
+
"get_upstream_nodes",
|
|
141
|
+
"verify_if_direct_dependencies_are_updated",
|
|
142
|
+
),
|
|
143
|
+
GitHubRepositoryBinding: ("import_branch",),
|
|
137
144
|
Job: ("bulk_get_or_create", "create_from_configuration", "sync_jobs"),
|
|
138
145
|
}
|
|
139
146
|
violations = [
|
|
@@ -146,6 +153,16 @@ def test_removed_backend_actions_are_not_exposed_by_client_models():
|
|
|
146
153
|
assert violations == []
|
|
147
154
|
|
|
148
155
|
|
|
156
|
+
def test_description_search_is_defined_only_where_the_backend_serves_it():
|
|
157
|
+
"""`description-search/` is served for time-index-meta-tables only."""
|
|
158
|
+
from mainsequence.client.metatables import MetaTable, TimeIndexMetaTable
|
|
159
|
+
|
|
160
|
+
assert "description_search" not in vars(MetaTable)
|
|
161
|
+
assert not hasattr(MetaTable, "description_search")
|
|
162
|
+
assert "description_search" in vars(TimeIndexMetaTable)
|
|
163
|
+
assert TimeIndexMetaTable.get_object_url().endswith("/time-index-meta-tables")
|
|
164
|
+
|
|
165
|
+
|
|
149
166
|
def test_cli_does_not_reintroduce_legacy_numeric_detail_routes_or_agent_runs():
|
|
150
167
|
from mainsequence.cli import api
|
|
151
168
|
from mainsequence.client import agent_runtime_models
|
{mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_code_repository_branch_contract.py
RENAMED
|
@@ -82,11 +82,15 @@ def test_code_repository_is_only_the_logical_aggregate_contract():
|
|
|
82
82
|
assert not hasattr(code_repository.branches[0], "code_repository_type")
|
|
83
83
|
assert not hasattr(code_repository, "repository_branch")
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
# Tolerant reading (ADR 0032): the retired field is dropped, not declared.
|
|
86
|
+
assert "repository_branch" not in models_foundry.CodeRepository.model_fields
|
|
87
|
+
assert not hasattr(
|
|
86
88
|
models_foundry.CodeRepository(
|
|
87
89
|
**logical_code_repository_payload(),
|
|
88
90
|
repository_branch="main",
|
|
89
|
-
)
|
|
91
|
+
),
|
|
92
|
+
"repository_branch",
|
|
93
|
+
)
|
|
90
94
|
|
|
91
95
|
|
|
92
96
|
def test_code_repository_requires_canonical_type_and_derived_technology():
|
|
@@ -23,6 +23,14 @@ STREAMLIT_REMOVAL_LINK_PATHS = {
|
|
|
23
23
|
Path("docs/SUMMARY.md"),
|
|
24
24
|
Path("docs/index.md"),
|
|
25
25
|
}
|
|
26
|
+
SKILL_ROOT = REPOSITORY_ROOT / "agent_scaffold" / "skills"
|
|
27
|
+
# Skills ship inside the wheel but reference repository documentation by its
|
|
28
|
+
# repository-relative path, so every referenced path must exist in the tree that
|
|
29
|
+
# produced the release.
|
|
30
|
+
SKILL_DOCUMENTATION_REFERENCE = re.compile(r"`(docs/[A-Za-z0-9_./-]+\.md)`")
|
|
31
|
+
# Skills are copied into a CodeRepository under `.agents/skills/<namespace>/`, so
|
|
32
|
+
# a cross-skill reference maps back to a shipped `agent_scaffold/skills` path.
|
|
33
|
+
SKILL_CROSS_REFERENCE = re.compile(r"`\.agents/skills/[A-Za-z0-9_]+/([A-Za-z0-9_./-]+/SKILL\.md)`")
|
|
26
34
|
RETIRED_PUBLIC_IDENTIFIERS = {
|
|
27
35
|
"project_context": re.compile(r"(?<![A-Za-z0-9_])project_context(?![A-Za-z0-9_])"),
|
|
28
36
|
"project-context": re.compile(r"(?<![A-Za-z0-9_])project-context(?![A-Za-z0-9_])"),
|
|
@@ -46,6 +54,10 @@ RETIRED_PUBLIC_IDENTIFIERS = {
|
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
|
|
57
|
+
def _skill_files() -> tuple[Path, ...]:
|
|
58
|
+
return tuple(sorted(SKILL_ROOT.rglob("SKILL.md")))
|
|
59
|
+
|
|
60
|
+
|
|
49
61
|
def _documentation_files() -> tuple[Path, ...]:
|
|
50
62
|
files = {REPOSITORY_ROOT / "README.md", REPOSITORY_ROOT / "CHANGELOG.md"}
|
|
51
63
|
for root in DOCUMENTATION_ROOTS:
|
|
@@ -74,10 +86,7 @@ def test_current_documentation_excludes_retired_project_identifiers(path: Path)
|
|
|
74
86
|
|
|
75
87
|
def test_code_repository_context_adr_describes_the_current_cutover() -> None:
|
|
76
88
|
adr = (
|
|
77
|
-
REPOSITORY_ROOT
|
|
78
|
-
/ "docs"
|
|
79
|
-
/ "adr"
|
|
80
|
-
/ "0031-process-lifetime-code-repository-branch-context.md"
|
|
89
|
+
REPOSITORY_ROOT / "docs" / "adr" / "0031-process-lifetime-code-repository-branch-context.md"
|
|
81
90
|
).read_text(encoding="utf-8")
|
|
82
91
|
|
|
83
92
|
assert "get_code_repository_context()" in adr
|
|
@@ -121,3 +130,43 @@ def test_current_documentation_does_not_advertise_streamlit_support(path: Path)
|
|
|
121
130
|
assert "streamlit" not in text.lower()
|
|
122
131
|
assert "create_dashboard" not in text
|
|
123
132
|
assert "delete_dashboard" not in text
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@pytest.mark.parametrize(
|
|
136
|
+
"path",
|
|
137
|
+
_skill_files(),
|
|
138
|
+
ids=lambda path: str(path.relative_to(REPOSITORY_ROOT)),
|
|
139
|
+
)
|
|
140
|
+
def test_skill_documentation_references_resolve(path: Path) -> None:
|
|
141
|
+
relative_path = path.relative_to(REPOSITORY_ROOT)
|
|
142
|
+
text = path.read_text(encoding="utf-8")
|
|
143
|
+
|
|
144
|
+
missing = sorted(
|
|
145
|
+
{
|
|
146
|
+
reference
|
|
147
|
+
for reference in SKILL_DOCUMENTATION_REFERENCE.findall(text)
|
|
148
|
+
if not (REPOSITORY_ROOT / reference).is_file()
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
assert not missing, f"{relative_path} references documentation that does not exist: {missing}"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@pytest.mark.parametrize(
|
|
156
|
+
"path",
|
|
157
|
+
_skill_files(),
|
|
158
|
+
ids=lambda path: str(path.relative_to(REPOSITORY_ROOT)),
|
|
159
|
+
)
|
|
160
|
+
def test_skill_cross_references_resolve(path: Path) -> None:
|
|
161
|
+
relative_path = path.relative_to(REPOSITORY_ROOT)
|
|
162
|
+
text = path.read_text(encoding="utf-8")
|
|
163
|
+
|
|
164
|
+
missing = sorted(
|
|
165
|
+
{
|
|
166
|
+
reference
|
|
167
|
+
for reference in SKILL_CROSS_REFERENCE.findall(text)
|
|
168
|
+
if not (SKILL_ROOT / reference).is_file()
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
assert not missing, f"{relative_path} references skills that are not shipped: {missing}"
|
{mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_code_repository_runtime_context.py
RENAMED
|
@@ -722,7 +722,7 @@ def test_metatable_request_always_submits_git_resolved_context(monkeypatch):
|
|
|
722
722
|
}
|
|
723
723
|
|
|
724
724
|
|
|
725
|
-
def
|
|
725
|
+
def test_code_repository_model_drops_removed_default_data_source_fields():
|
|
726
726
|
payload = {
|
|
727
727
|
"uid": CODE_REPOSITORY_UID,
|
|
728
728
|
"code_repository_name": "Example CodeRepository",
|
|
@@ -737,5 +737,9 @@ def test_code_repository_model_rejects_removed_default_data_source_fields():
|
|
|
737
737
|
"default_metatables_data_source_uid": DATA_SOURCE_UID,
|
|
738
738
|
}
|
|
739
739
|
|
|
740
|
-
|
|
741
|
-
|
|
740
|
+
# Tolerant reading (ADR 0032): the retired field is dropped, not declared.
|
|
741
|
+
assert "default_metatables_data_source_uid" not in models_foundry.CodeRepository.model_fields
|
|
742
|
+
assert not hasattr(
|
|
743
|
+
models_foundry.CodeRepository.model_validate(payload),
|
|
744
|
+
"default_metatables_data_source_uid",
|
|
745
|
+
)
|
{mainsequence-8.1.20.dev3 → mainsequence-8.1.20.dev7}/tests/test_environment_response_contracts.py
RENAMED
|
@@ -87,13 +87,13 @@ RUNTIME_UPDATE_FIELD = "runtime_update"
|
|
|
87
87
|
),
|
|
88
88
|
],
|
|
89
89
|
)
|
|
90
|
-
def
|
|
90
|
+
def test_backend_environment_response_contract_is_declared_by_sdk_model(
|
|
91
91
|
serializer_names,
|
|
92
92
|
model,
|
|
93
93
|
expected_fields,
|
|
94
94
|
):
|
|
95
95
|
"""Keep SDK response models aligned with ADR-0036/ADR-0037 projections."""
|
|
96
|
-
assert model.model_config.get("extra") == "
|
|
96
|
+
assert model.model_config.get("extra") == "ignore", serializer_names
|
|
97
97
|
assert expected_fields <= set(model.model_fields), serializer_names
|
|
98
98
|
|
|
99
99
|
|
|
@@ -106,13 +106,13 @@ def test_backend_environment_response_contract_is_declared_by_strict_sdk_model(
|
|
|
106
106
|
helper_models.ResourceRelease,
|
|
107
107
|
],
|
|
108
108
|
)
|
|
109
|
-
def
|
|
110
|
-
assert model.model_config.get("extra") == "
|
|
109
|
+
def test_owner_observability_code_repositoryion_is_declared_by_sdk_model(model):
|
|
110
|
+
assert model.model_config.get("extra") == "ignore"
|
|
111
111
|
assert "observability" in model.model_fields
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
def test_agent_session_runtime_capabilities_code_repositoryion_is_declared_and_typed():
|
|
115
|
-
assert agent_models.AgentSession.model_config.get("extra") == "
|
|
115
|
+
assert agent_models.AgentSession.model_config.get("extra") == "ignore"
|
|
116
116
|
assert (
|
|
117
117
|
agent_models.AgentSession.model_fields["runtime_capabilities"].annotation == dict[str, str]
|
|
118
118
|
)
|