fred-sdk 3.3.2__tar.gz → 3.3.3__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.
Files changed (68) hide show
  1. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/PKG-INFO +4 -6
  2. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/README.md +0 -2
  3. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/__init__.py +35 -4
  4. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/authoring/__init__.py +0 -2
  5. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/authoring/knowledge_flow_mcp.py +0 -5
  6. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/__init__.py +40 -0
  7. fred_sdk-3.3.3/fred_sdk/contracts/capability/__init__.py +85 -0
  8. fred_sdk-3.3.3/fred_sdk/contracts/capability/base.py +180 -0
  9. fred_sdk-3.3.3/fred_sdk/contracts/capability/chat_controls.py +80 -0
  10. fred_sdk-3.3.3/fred_sdk/contracts/capability/context.py +115 -0
  11. fred_sdk-3.3.3/fred_sdk/contracts/capability/hitl.py +90 -0
  12. fred_sdk-3.3.3/fred_sdk/contracts/capability/manifest.py +331 -0
  13. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/context.py +6 -0
  14. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/execution.py +13 -0
  15. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/models.py +66 -13
  16. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/openai_compat.py +31 -11
  17. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/runtime.py +58 -1
  18. fred_sdk-3.3.3/fred_sdk/contracts/ui_part_union.py +218 -0
  19. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/support/builtins/__init__.py +0 -2
  20. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/support/builtins/catalog.py +1 -45
  21. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk.egg-info/PKG-INFO +4 -6
  22. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk.egg-info/SOURCES.txt +11 -1
  23. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk.egg-info/requires.txt +3 -3
  24. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/pyproject.toml +4 -4
  25. fred_sdk-3.3.3/tests/test_capability_contracts.py +411 -0
  26. fred_sdk-3.3.3/tests/test_document_search_port_1906.py +101 -0
  27. fred_sdk-3.3.3/tests/test_ui_part_union_1977.py +205 -0
  28. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/authoring/api.py +0 -0
  29. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/authoring/authored_tool_runtime.py +0 -0
  30. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/authoring/inspection.py +0 -0
  31. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/authoring/tool_args_schema.py +0 -0
  32. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/authoring/tool_context_helpers.py +0 -0
  33. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/eval.py +0 -0
  34. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/prompt_utils.py +0 -0
  35. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/contracts/react_contract.py +0 -0
  36. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/deep/__init__.py +0 -0
  37. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/graph/__init__.py +0 -0
  38. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/graph/authoring/__init__.py +0 -0
  39. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/graph/authoring/api.py +0 -0
  40. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/graph/authoring/team_api.py +0 -0
  41. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/graph/runtime.py +0 -0
  42. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/hello.py +0 -0
  43. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/react/__init__.py +0 -0
  44. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/resources/__init__.py +0 -0
  45. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/resources/packaged.py +0 -0
  46. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/resources/prompts/mermaid_output_contract.md +0 -0
  47. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/resources/prompts.py +0 -0
  48. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/runtime_support/__init__.py +0 -0
  49. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/runtime_support/remote_agent_invoker.py +0 -0
  50. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/support/__init__.py +0 -0
  51. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/support/authored_toolsets.py +0 -0
  52. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk/support/mcp_utils.py +0 -0
  53. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk.egg-info/dependency_links.txt +0 -0
  54. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/fred_sdk.egg-info/top_level.txt +0 -0
  55. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/setup.cfg +0 -0
  56. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_conversational_memory.py +0 -0
  57. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_execution_contracts.py +0 -0
  58. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_graph_choice_step.py +0 -0
  59. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_graph_models.py +0 -0
  60. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_hello.py +0 -0
  61. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_mcp_utils.py +0 -0
  62. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_openai_compat.py +0 -0
  63. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_prompt_bundles.py +0 -0
  64. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_prompt_utils.py +0 -0
  65. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_react_contract.py +0 -0
  66. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_sdk_purity.py +0 -0
  67. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_tool_args_schema.py +0 -0
  68. {fred_sdk-3.3.2 → fred_sdk-3.3.3}/tests/test_tool_context_workspace_fs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fred-sdk
3
- Version: 3.3.2
3
+ Version: 3.3.3
4
4
  Summary: Authoring SDK for Fred agents — graph, ReAct, and team agent primitives.
5
5
  Author-email: Thales <noreply@thalesgroup.com>
6
6
  License: Apache-2.0
@@ -12,11 +12,11 @@ Classifier: Programming Language :: Python :: 3 :: Only
12
12
  Classifier: Operating System :: OS Independent
13
13
  Requires-Python: <3.13,>=3.12
14
14
  Description-Content-Type: text/markdown
15
- Requires-Dist: fred-core>=3.4.2
15
+ Requires-Dist: fred-core>=3.4.1
16
16
  Requires-Dist: pydantic<3.0.0,>=2.7.0
17
17
  Requires-Dist: langchain-core>=0.3.0
18
- Requires-Dist: langchain>=0.3.0
19
- Requires-Dist: langgraph>=1.1.3
18
+ Requires-Dist: langchain>=1.3.14
19
+ Requires-Dist: langgraph>=1.2.9
20
20
  Requires-Dist: httpx>=0.28.1
21
21
  Provides-Extra: dev
22
22
  Requires-Dist: bandit>=1.8.6; extra == "dev"
@@ -242,7 +242,6 @@ Built-in MCP server constants:
242
242
  | `MCP_SERVER_KNOWLEDGE_FLOW_CORPUS` | Document search and retrieval |
243
243
  | `MCP_SERVER_KNOWLEDGE_FLOW_FS` | Workspace file system |
244
244
  | `MCP_SERVER_KNOWLEDGE_FLOW_TABULAR` | Tabular data / CSV |
245
- | `MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS` | Statistical analysis |
246
245
  | `MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS` | OpenSearch operations |
247
246
 
248
247
  ---
@@ -264,7 +263,6 @@ class MyAgent(ReActAgent):
264
263
  | `TOOL_REF_RESOURCES_FETCH_TEXT` | Fetch document content as text |
265
264
  | `TOOL_REF_ARTIFACTS_PUBLISH_TEXT` | Publish a text artifact to the workspace |
266
265
  | `TOOL_REF_GEO_RENDER_POINTS` | Render geographic points on a map |
267
- | `TOOL_REF_LOGS_QUERY` | Query audit logs |
268
266
  | `TOOL_REF_TRACES_SUMMARIZE_CONVERSATION` | Summarize conversation traces |
269
267
 
270
268
  ---
@@ -213,7 +213,6 @@ Built-in MCP server constants:
213
213
  | `MCP_SERVER_KNOWLEDGE_FLOW_CORPUS` | Document search and retrieval |
214
214
  | `MCP_SERVER_KNOWLEDGE_FLOW_FS` | Workspace file system |
215
215
  | `MCP_SERVER_KNOWLEDGE_FLOW_TABULAR` | Tabular data / CSV |
216
- | `MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS` | Statistical analysis |
217
216
  | `MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS` | OpenSearch operations |
218
217
 
219
218
  ---
@@ -235,7 +234,6 @@ class MyAgent(ReActAgent):
235
234
  | `TOOL_REF_RESOURCES_FETCH_TEXT` | Fetch document content as text |
236
235
  | `TOOL_REF_ARTIFACTS_PUBLISH_TEXT` | Publish a text artifact to the workspace |
237
236
  | `TOOL_REF_GEO_RENDER_POINTS` | Render geographic points on a map |
238
- | `TOOL_REF_LOGS_QUERY` | Query audit logs |
239
237
  | `TOOL_REF_TRACES_SUMMARIZE_CONVERSATION` | Summarize conversation traces |
240
238
 
241
239
  ---
@@ -34,6 +34,10 @@ Human-in-the-loop
34
34
  -----------------
35
35
  from fred_sdk import HumanInputRequest, HumanChoiceOption
36
36
 
37
+ Capabilities (modular agent features)
38
+ -------------------------------------
39
+ from fred_sdk import AgentCapability, CapabilityManifest, CapabilityContext
40
+
37
41
  MCP server references
38
42
  ---------------------
39
43
  from fred_sdk import MCPServerRef, MCP_SERVER_KNOWLEDGE_FLOW_CORPUS
@@ -69,11 +73,26 @@ from fred_sdk.authoring.knowledge_flow_mcp import (
69
73
  MCP_SERVER_KNOWLEDGE_FLOW_FS,
70
74
  MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS,
71
75
  MCP_SERVER_KNOWLEDGE_FLOW_PROMETHEUS_OPS,
72
- MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS,
73
76
  MCP_SERVER_KNOWLEDGE_FLOW_TABULAR,
74
77
  MCP_SERVER_KNOWLEDGE_FLOW_TEXT,
75
78
  MCPServerRef,
76
79
  )
80
+ from fred_sdk.contracts.capability import (
81
+ AgentCapability,
82
+ AssetSlot,
83
+ CapabilityContext,
84
+ CapabilityIdentity,
85
+ CapabilityManifest,
86
+ ChatControlSpec,
87
+ EmptyModel,
88
+ HitlGateRequest,
89
+ HitlSpec,
90
+ SaveContext,
91
+ SidePanelSpec,
92
+ TeamScopePolicy,
93
+ UploadedFile,
94
+ chat_part_kind,
95
+ )
77
96
  from fred_sdk.contracts.context import (
78
97
  AgentInvocationResult,
79
98
  FsEntry,
@@ -160,7 +179,6 @@ from fred_sdk.support.builtins import (
160
179
  TOOL_REF_ARTIFACTS_PUBLISH_TEXT,
161
180
  TOOL_REF_GEO_RENDER_POINTS,
162
181
  TOOL_REF_KNOWLEDGE_SEARCH,
163
- TOOL_REF_LOGS_QUERY,
164
182
  TOOL_REF_RESOURCES_FETCH_TEXT,
165
183
  TOOL_REF_TRACES_SUMMARIZE_CONVERSATION,
166
184
  )
@@ -186,7 +204,6 @@ __all__ = [
186
204
  "MCP_SERVER_KNOWLEDGE_FLOW_FS",
187
205
  "MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS",
188
206
  "MCP_SERVER_KNOWLEDGE_FLOW_PROMETHEUS_OPS",
189
- "MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS",
190
207
  "MCP_SERVER_KNOWLEDGE_FLOW_TABULAR",
191
208
  "MCP_SERVER_KNOWLEDGE_FLOW_TEXT",
192
209
  # Graph authoring
@@ -236,6 +253,21 @@ __all__ = [
236
253
  "ToolRefRequirement",
237
254
  "TuningScalar",
238
255
  "TuningValue",
256
+ # Capability authoring (#1973, RFC AGENT-CAPABILITY-RFC.md §3)
257
+ "AgentCapability",
258
+ "AssetSlot",
259
+ "CapabilityContext",
260
+ "CapabilityIdentity",
261
+ "CapabilityManifest",
262
+ "ChatControlSpec",
263
+ "EmptyModel",
264
+ "HitlGateRequest",
265
+ "HitlSpec",
266
+ "SaveContext",
267
+ "SidePanelSpec",
268
+ "TeamScopePolicy",
269
+ "UploadedFile",
270
+ "chat_part_kind",
239
271
  # Evaluation contracts (POST /agents/evaluate)
240
272
  "EvalStep",
241
273
  "EvalTrace",
@@ -249,7 +281,6 @@ __all__ = [
249
281
  "TOOL_REF_ARTIFACTS_PUBLISH_TEXT",
250
282
  "TOOL_REF_GEO_RENDER_POINTS",
251
283
  "TOOL_REF_KNOWLEDGE_SEARCH",
252
- "TOOL_REF_LOGS_QUERY",
253
284
  "TOOL_REF_RESOURCES_FETCH_TEXT",
254
285
  "TOOL_REF_TRACES_SUMMARIZE_CONVERSATION",
255
286
  ]
@@ -58,7 +58,6 @@ from .knowledge_flow_mcp import (
58
58
  MCP_SERVER_KNOWLEDGE_FLOW_CORPUS,
59
59
  MCP_SERVER_KNOWLEDGE_FLOW_FS,
60
60
  MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS,
61
- MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS,
62
61
  MCP_SERVER_KNOWLEDGE_FLOW_TABULAR,
63
62
  MCPServerRef,
64
63
  )
@@ -69,7 +68,6 @@ __all__ = [
69
68
  "MCP_SERVER_KNOWLEDGE_FLOW_CORPUS",
70
69
  "MCP_SERVER_KNOWLEDGE_FLOW_FS",
71
70
  "MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS",
72
- "MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS",
73
71
  "MCP_SERVER_KNOWLEDGE_FLOW_TABULAR",
74
72
  "ReActAgent",
75
73
  "ToolContext",
@@ -40,7 +40,6 @@ Current official Knowledge Flow MCP servers:
40
40
  - `MCP_SERVER_KNOWLEDGE_FLOW_CORPUS`: corpus administration operations
41
41
  - `MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS`: OpenSearch monitoring operations
42
42
  - `MCP_SERVER_KNOWLEDGE_FLOW_TABULAR`: tabular analysis operations
43
- - `MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS`: statistics analysis operations
44
43
  """
45
44
 
46
45
  from __future__ import annotations
@@ -63,9 +62,6 @@ MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS: Final[str] = (
63
62
  MCP_SERVER_KNOWLEDGE_FLOW_TABULAR: Final[str] = "mcp-knowledge-flow-mcp-tabular"
64
63
  """Tabular analysis MCP server id used by Tabular-style agents."""
65
64
 
66
- MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS: Final[str] = "mcp-knowledge-flow-statistics"
67
- """Statistics analysis MCP server id used by Statistics-style agents."""
68
-
69
65
  MCP_SERVER_KNOWLEDGE_FLOW_TEXT: Final[str] = "mcp-knowledge-flow-mcp-text"
70
66
  """Text search MCP server id — document full-text retrieval from the knowledge flow."""
71
67
 
@@ -80,7 +76,6 @@ __all__ = [
80
76
  "MCP_SERVER_KNOWLEDGE_FLOW_FS",
81
77
  "MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS",
82
78
  "MCP_SERVER_KNOWLEDGE_FLOW_PROMETHEUS_OPS",
83
- "MCP_SERVER_KNOWLEDGE_FLOW_STATISTICS",
84
79
  "MCP_SERVER_KNOWLEDGE_FLOW_TABULAR",
85
80
  "MCP_SERVER_KNOWLEDGE_FLOW_TEXT",
86
81
  ]
@@ -23,6 +23,22 @@ How to use:
23
23
  - keep SDK-specific runtime code outside this package
24
24
  """
25
25
 
26
+ from .capability import (
27
+ AgentCapability,
28
+ AssetSlot,
29
+ CapabilityContext,
30
+ CapabilityIdentity,
31
+ CapabilityManifest,
32
+ ChatControlSpec,
33
+ EmptyModel,
34
+ HitlGateRequest,
35
+ HitlSpec,
36
+ SaveContext,
37
+ SidePanelSpec,
38
+ TeamScopePolicy,
39
+ UploadedFile,
40
+ chat_part_kind,
41
+ )
26
42
  from .context import (
27
43
  ConversationalState,
28
44
  ConversationTurn,
@@ -52,8 +68,28 @@ from .prompt_utils import (
52
68
  validate_prompt_template,
53
69
  )
54
70
  from .runtime import RuntimeErrorEvent, TurnPersistedEvent
71
+ from .ui_part_union import (
72
+ BASE_UI_PARTS,
73
+ current_ui_part_union,
74
+ rebuild_ui_part_union,
75
+ )
55
76
 
56
77
  __all__ = [
78
+ # Capability contracts (#1973, RFC AGENT-CAPABILITY-RFC.md §3)
79
+ "AgentCapability",
80
+ "AssetSlot",
81
+ "CapabilityContext",
82
+ "CapabilityIdentity",
83
+ "CapabilityManifest",
84
+ "ChatControlSpec",
85
+ "EmptyModel",
86
+ "HitlGateRequest",
87
+ "HitlSpec",
88
+ "SaveContext",
89
+ "SidePanelSpec",
90
+ "TeamScopePolicy",
91
+ "UploadedFile",
92
+ "chat_part_kind",
57
93
  # Conversational memory
58
94
  "ConversationTurn",
59
95
  "ConversationalState",
@@ -62,6 +98,10 @@ __all__ = [
62
98
  "LinkKind",
63
99
  "LinkPart",
64
100
  "RuntimeContext",
101
+ # UiPart union registration (#1977, RFC AGENT-CAPABILITY-RFC.md §3.6/§4)
102
+ "BASE_UI_PARTS",
103
+ "current_ui_part_union",
104
+ "rebuild_ui_part_union",
65
105
  # Execution identity and authorization (Phase 1)
66
106
  "ActorContext",
67
107
  "TeamContext",
@@ -0,0 +1,85 @@
1
+ # Copyright Thales 2026
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Tier 0 capability contracts (#1973, RFC docs/swift/rfc/AGENT-CAPABILITY-RFC.md §3).
17
+
18
+ Why this package exists:
19
+ - one abstraction (`AgentCapability`) carries a modular agent feature end to
20
+ end: declaration (`CapabilityManifest`), save-time validation, computed chat
21
+ surface, HITL declarations, and the runtime middleware stack
22
+ - the runtime half (registry, boot validation, entry-point discovery, agent
23
+ assembly) lives in `fred_runtime.capabilities` — this package is the pure
24
+ contract surface capability authors import
25
+
26
+ How to use:
27
+ - `from fred_sdk.contracts.capability import AgentCapability, CapabilityManifest, ...`
28
+ - one module per concern: `base` (the ABC), `manifest` (declaration),
29
+ `context` (typed runtime/LLM split), `hitl` (approval declarations)
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ from ..models import StoredCapabilityConfig
35
+ from .base import AgentCapability
36
+ from .chat_controls import (
37
+ ChatControlsRequest,
38
+ ChatControlsRequestItem,
39
+ ChatControlsResponse,
40
+ ChatControlsResult,
41
+ )
42
+ from .context import (
43
+ CapabilityContext,
44
+ CapabilityIdentity,
45
+ EmptyModel,
46
+ SaveContext,
47
+ )
48
+ from .hitl import HitlGateRequest, HitlSpec
49
+ from .manifest import (
50
+ AssetSlot,
51
+ CapabilityCatalogEntry,
52
+ CapabilityManifest,
53
+ ChatControlDescriptor,
54
+ ChatControlItem,
55
+ ChatControlSpec,
56
+ SidePanelSpec,
57
+ TeamScopePolicy,
58
+ UploadedFile,
59
+ chat_part_kind,
60
+ )
61
+
62
+ __all__ = [
63
+ "AgentCapability",
64
+ "AssetSlot",
65
+ "CapabilityCatalogEntry",
66
+ "CapabilityContext",
67
+ "CapabilityIdentity",
68
+ "CapabilityManifest",
69
+ "ChatControlDescriptor",
70
+ "ChatControlItem",
71
+ "ChatControlSpec",
72
+ "ChatControlsRequest",
73
+ "ChatControlsRequestItem",
74
+ "ChatControlsResponse",
75
+ "ChatControlsResult",
76
+ "EmptyModel",
77
+ "HitlGateRequest",
78
+ "HitlSpec",
79
+ "SaveContext",
80
+ "SidePanelSpec",
81
+ "StoredCapabilityConfig",
82
+ "TeamScopePolicy",
83
+ "UploadedFile",
84
+ "chat_part_kind",
85
+ ]
@@ -0,0 +1,180 @@
1
+ # Copyright Thales 2026
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ `AgentCapability` — the Tier 0 abstraction for modular agent features
17
+ (#1973, RFC AGENT-CAPABILITY-RFC.md §3.2).
18
+
19
+ Why this module exists:
20
+ - one abstraction carries a feature's declaration (manifest), its save-time
21
+ validation, its computed chat surface, and its runtime middleware stack —
22
+ replacing the per-feature scatter the RFC measures in §1.1
23
+
24
+ How to use:
25
+ - subclass with the three generic parameters and declare `manifest` plus the
26
+ typed models; only `middleware()` is abstract::
27
+
28
+ class PptFillerCapability(AgentCapability[PptConfig, PptStored, PptTurn]):
29
+ manifest = CapabilityManifest(id="ppt_filler", ...)
30
+ ConfigModel = PptConfig
31
+ StoredConfigModel = PptStored # defaults to ConfigModel if omitted
32
+ TurnOptionsModel = PptTurn # defaults to EmptyModel if omitted
33
+
34
+ def middleware(self, ctx): ...
35
+
36
+ - installing the package IS the registration: declare a `fred.capabilities`
37
+ entry point pointing at the subclass (RFC §4, §7)
38
+
39
+ Contract rules (RFC §3.2, §5.3):
40
+ - returned middleware must act only on the capability's own tools and state
41
+ channels; capabilities must be mutually order-independent
42
+ - interrupt/HITL middleware is excluded — declare `HitlSpec`s instead (§5.4)
43
+ - capability `state_schema` channels are JSON-primitive by default; typed
44
+ (pydantic) channels opt into the checkpointer msgpack allowlist via
45
+ `manifest.state_models` (§5.2 spike rule, #1971)
46
+ """
47
+
48
+ from __future__ import annotations
49
+
50
+ from abc import ABC, abstractmethod
51
+ from collections.abc import Mapping, Sequence
52
+ from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypeVar, cast
53
+
54
+ from pydantic import BaseModel
55
+
56
+ from .context import CapabilityContext, EmptyModel, SaveContext
57
+ from .hitl import HitlSpec
58
+ from .manifest import CapabilityManifest, ChatControlSpec, UploadedFile
59
+
60
+ if TYPE_CHECKING:
61
+ from langchain.agents.middleware import AgentMiddleware
62
+
63
+ ConfigT = TypeVar("ConfigT", bound=BaseModel)
64
+ StoredT = TypeVar("StoredT", bound=BaseModel)
65
+ TurnOptionsT = TypeVar("TurnOptionsT", bound=BaseModel)
66
+
67
+
68
+ class AgentCapability(ABC, Generic[ConfigT, StoredT, TurnOptionsT]):
69
+ """
70
+ One modular agent feature: declaration + validation + runtime middleware.
71
+
72
+ The four typed models (RFC §3.2):
73
+ - `ConfigModel`: what the user SENDS at agent creation (drives
74
+ `manifest.config_fields`)
75
+ - `StoredConfigModel`: what the platform PERSISTS after
76
+ `validate_config` enrichment; defaults to `ConfigModel`, and a
77
+ capability deriving state at save time declares it as a SUBCLASS of
78
+ `ConfigModel` (RFC §3.2)
79
+ - `TurnOptionsModel`: typed chat-time values (RFC §3.5); `EmptyModel`
80
+ if none
81
+ - `TeamSettingsModel`: typed per-team enablement settings (RFC §8.2);
82
+ `EmptyModel` until Tier 3
83
+ """
84
+
85
+ manifest: ClassVar[CapabilityManifest]
86
+ ConfigModel: ClassVar[type[BaseModel]]
87
+ StoredConfigModel: ClassVar[type[BaseModel]]
88
+ TurnOptionsModel: ClassVar[type[BaseModel]] = EmptyModel
89
+ TeamSettingsModel: ClassVar[type[BaseModel]] = EmptyModel
90
+
91
+ def __init_subclass__(cls, **kwargs: Any) -> None:
92
+ super().__init_subclass__(**kwargs)
93
+ # StoredConfigModel defaults to ConfigModel (RFC §3.2). Only default it
94
+ # when the subclass declares its own ConfigModel and no
95
+ # StoredConfigModel is visible anywhere in the MRO.
96
+ if (
97
+ "ConfigModel" in cls.__dict__
98
+ and getattr(cls, "StoredConfigModel", None) is None
99
+ ):
100
+ cls.StoredConfigModel = cls.__dict__["ConfigModel"]
101
+
102
+ async def validate_config(
103
+ self,
104
+ config: ConfigT,
105
+ uploads: Mapping[str, list[UploadedFile]],
106
+ ctx: SaveContext,
107
+ ) -> StoredT:
108
+ """
109
+ Agent-save-time input → stored transform (RFC §3.2, §3.8).
110
+
111
+ Default: validate the input against `StoredConfigModel` unchanged —
112
+ correct for capabilities without save-time enrichment. Override to
113
+ parse uploads, raise typed validation errors, store asset binaries
114
+ through `ctx.services` and keep only their keys.
115
+ """
116
+
117
+ del uploads, ctx
118
+ return cast(StoredT, self.StoredConfigModel.model_validate(config.model_dump()))
119
+
120
+ def chat_controls(self, config: StoredT) -> list[ChatControlSpec]:
121
+ """
122
+ Computed chat-time control descriptors for one agent instance
123
+ (RFC §3.3). Evaluated at session-prep time, never persisted (§3.7).
124
+ List order = display order. Default: no chat controls.
125
+ """
126
+
127
+ del config
128
+ return []
129
+
130
+ def upgrade_config(self, stored: Mapping[str, Any], from_version: str) -> StoredT:
131
+ """
132
+ Migrate an old stored-config shape (RFC §3.9). Runs lazily at read
133
+ time. Default: plain `StoredConfigModel` validation. A raising upgrade
134
+ suspends the agent (`capability_config_invalid`).
135
+ """
136
+
137
+ del from_version
138
+ return cast(StoredT, self.StoredConfigModel.model_validate(stored))
139
+
140
+ def hitl_specs(self) -> Sequence[HitlSpec]:
141
+ """
142
+ Approval declarations for this capability's tools (RFC §5.4), merged
143
+ into the single platform HITL gate at assembly. Default: none.
144
+ """
145
+
146
+ return ()
147
+
148
+ @classmethod
149
+ def migrations_location(cls) -> str | None:
150
+ """
151
+ Filesystem path to this capability's own Alembic script directory
152
+ (RFC §7.1).
153
+
154
+ Why this exists:
155
+ - a capability that declares `manifest.tables` ships its own migration
156
+ scripts, applied under a per-capability version table
157
+ (`cap_<id>_alembic_version`) — never rebased against fred-runtime's
158
+ tree or another capability's (RFC §7.1)
159
+ - `python -m fred_runtime migrate` discovers installed capabilities via
160
+ the same `fred.capabilities` entry points and, for each one that
161
+ returns a location here, runs `alembic upgrade head` against it
162
+
163
+ How to use:
164
+ - return an absolute path to the package's Alembic dir (the dir holding
165
+ `env.py` + `versions/`), typically resolved relative to `__file__`
166
+ - return `None` (default) when the capability owns no tables
167
+ """
168
+
169
+ return None
170
+
171
+ @abstractmethod
172
+ def middleware(
173
+ self, ctx: CapabilityContext[StoredT, TurnOptionsT]
174
+ ) -> Sequence["AgentMiddleware"]:
175
+ """
176
+ The runtime half (RFC §3.2, §5): the LangChain middleware STACK
177
+ carrying this capability's tools and hooks, bound to the turn's
178
+ context. Authored list order is preserved within this capability's
179
+ block (§5.3).
180
+ """
@@ -0,0 +1,80 @@
1
+ # Copyright Thales 2026
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Chat-controls evaluation wire contract (#1976, RFC §3.3, §3.7).
17
+
18
+ Why this module exists:
19
+ - session prep computes each agent instance's chat-time controls on the POD
20
+ (capability code lives there, §7); control-plane asks the pod to evaluate
21
+ `chat_controls(config)` over a BATCH of capabilities in one round-trip and
22
+ caches the per-capability results cache-aside, keyed
23
+ `(capability_id, manifest.version, config_hash)` — nothing derived persisted
24
+ - the request/response models are shared (fred-sdk) so control-plane parses the
25
+ pod response with the SAME model, never a hand-declared copy — same rule as
26
+ `CapabilityCatalogEntry`
27
+
28
+ How to use:
29
+ - control-plane: POST `ChatControlsRequest` to `/agents/capabilities/chat-controls`
30
+ with only the cache-MISSED capabilities; merge `ChatControlsResponse.results`
31
+ with cached items, then flatten into `ExecutionPreparation.chat_controls`
32
+ - pod: evaluate each item and return one `ChatControlsResult` per capability
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ from pydantic import BaseModel, Field
38
+
39
+ from ..models import StoredCapabilityConfig
40
+ from .manifest import ChatControlItem
41
+
42
+
43
+ class ChatControlsRequestItem(BaseModel):
44
+ """One capability to evaluate: its id plus its verbatim stored slice."""
45
+
46
+ capability_id: str = Field(min_length=1)
47
+ # The stored envelope ({"schema_version", "config"}); None means "no stored
48
+ # slice" — the pod evaluates against StoredConfigModel defaults, mirroring
49
+ # execution-time assembly.
50
+ config_envelope: StoredCapabilityConfig | None = None
51
+
52
+
53
+ class ChatControlsRequest(BaseModel):
54
+ """Batch chat-controls evaluation request (control-plane → pod)."""
55
+
56
+ items: list[ChatControlsRequestItem] = Field(default_factory=list)
57
+
58
+
59
+ class ChatControlsResult(BaseModel):
60
+ """
61
+ One capability's evaluated chat controls.
62
+
63
+ `error` is non-None when the capability is not installed or its stored slice
64
+ could not be resolved (RFC §3.9 `capability_config_invalid`); control-plane
65
+ skips that capability with a warning rather than failing the whole prep.
66
+ `manifest_version` is the pod's installed version — the authoritative value
67
+ for the cache key — and is left empty on an error result (there is no
68
+ version to cache under, and control-plane never caches an error).
69
+ """
70
+
71
+ capability_id: str = Field(min_length=1)
72
+ manifest_version: str = ""
73
+ controls: list[ChatControlItem] = Field(default_factory=list)
74
+ error: str | None = None
75
+
76
+
77
+ class ChatControlsResponse(BaseModel):
78
+ """Batch chat-controls evaluation response (pod → control-plane)."""
79
+
80
+ results: list[ChatControlsResult] = Field(default_factory=list)