ogx-api 1.1.2__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. {ogx_api-1.1.2 → ogx_api-1.2.0}/PKG-INFO +4 -4
  2. {ogx_api-1.1.2 → ogx_api-1.2.0}/__init__.py +76 -0
  3. ogx_api-1.2.0/containers/__init__.py +92 -0
  4. ogx_api-1.2.0/containers/api.py +206 -0
  5. ogx_api-1.2.0/containers/fastapi_routes.py +205 -0
  6. ogx_api-1.2.0/containers/models.py +444 -0
  7. {ogx_api-1.1.2 → ogx_api-1.2.0}/datatypes.py +4 -0
  8. {ogx_api-1.1.2 → ogx_api-1.2.0}/files/fastapi_routes.py +36 -5
  9. {ogx_api-1.1.2 → ogx_api-1.2.0}/inference/api.py +29 -0
  10. {ogx_api-1.1.2 → ogx_api-1.2.0}/internal/sqlstore.py +2 -0
  11. {ogx_api-1.1.2 → ogx_api-1.2.0}/ogx_api.egg-info/PKG-INFO +4 -4
  12. {ogx_api-1.1.2 → ogx_api-1.2.0}/ogx_api.egg-info/SOURCES.txt +8 -0
  13. {ogx_api-1.1.2 → ogx_api-1.2.0}/ogx_api.egg-info/requires.txt +3 -3
  14. {ogx_api-1.1.2 → ogx_api-1.2.0}/openai_responses.py +1 -0
  15. {ogx_api-1.1.2 → ogx_api-1.2.0}/pyproject.toml +5 -4
  16. {ogx_api-1.1.2 → ogx_api-1.2.0}/responses/__init__.py +2 -0
  17. {ogx_api-1.1.2 → ogx_api-1.2.0}/responses/models.py +55 -1
  18. {ogx_api-1.1.2 → ogx_api-1.2.0}/uv.lock +90 -24
  19. {ogx_api-1.1.2 → ogx_api-1.2.0}/vector_io/api.py +5 -1
  20. {ogx_api-1.1.2 → ogx_api-1.2.0}/vector_io/fastapi_routes.py +21 -1
  21. {ogx_api-1.1.2 → ogx_api-1.2.0}/vector_io/models.py +3 -2
  22. {ogx_api-1.1.2 → ogx_api-1.2.0}/README.md +0 -0
  23. {ogx_api-1.1.2 → ogx_api-1.2.0}/admin/__init__.py +0 -0
  24. {ogx_api-1.1.2 → ogx_api-1.2.0}/admin/api.py +0 -0
  25. {ogx_api-1.1.2 → ogx_api-1.2.0}/admin/fastapi_routes.py +0 -0
  26. {ogx_api-1.1.2 → ogx_api-1.2.0}/admin/models.py +0 -0
  27. {ogx_api-1.1.2 → ogx_api-1.2.0}/batches/__init__.py +0 -0
  28. {ogx_api-1.1.2 → ogx_api-1.2.0}/batches/api.py +0 -0
  29. {ogx_api-1.1.2 → ogx_api-1.2.0}/batches/fastapi_routes.py +0 -0
  30. {ogx_api-1.1.2 → ogx_api-1.2.0}/batches/models.py +0 -0
  31. {ogx_api-1.1.2 → ogx_api-1.2.0}/common/__init__.py +0 -0
  32. {ogx_api-1.1.2 → ogx_api-1.2.0}/common/content_types.py +0 -0
  33. {ogx_api-1.1.2 → ogx_api-1.2.0}/common/errors.py +0 -0
  34. {ogx_api-1.1.2 → ogx_api-1.2.0}/common/job_types.py +0 -0
  35. {ogx_api-1.1.2 → ogx_api-1.2.0}/common/responses.py +0 -0
  36. {ogx_api-1.1.2 → ogx_api-1.2.0}/common/type_system.py +0 -0
  37. {ogx_api-1.1.2 → ogx_api-1.2.0}/common/upload_limits.py +0 -0
  38. {ogx_api-1.1.2 → ogx_api-1.2.0}/connectors/__init__.py +0 -0
  39. {ogx_api-1.1.2 → ogx_api-1.2.0}/connectors/api.py +0 -0
  40. {ogx_api-1.1.2 → ogx_api-1.2.0}/connectors/models.py +0 -0
  41. {ogx_api-1.1.2 → ogx_api-1.2.0}/conversations/__init__.py +0 -0
  42. {ogx_api-1.1.2 → ogx_api-1.2.0}/conversations/api.py +0 -0
  43. {ogx_api-1.1.2 → ogx_api-1.2.0}/conversations/fastapi_routes.py +0 -0
  44. {ogx_api-1.1.2 → ogx_api-1.2.0}/conversations/models.py +0 -0
  45. {ogx_api-1.1.2 → ogx_api-1.2.0}/file_processors/__init__.py +0 -0
  46. {ogx_api-1.1.2 → ogx_api-1.2.0}/file_processors/api.py +0 -0
  47. {ogx_api-1.1.2 → ogx_api-1.2.0}/file_processors/fastapi_routes.py +0 -0
  48. {ogx_api-1.1.2 → ogx_api-1.2.0}/file_processors/models.py +0 -0
  49. {ogx_api-1.1.2 → ogx_api-1.2.0}/files/__init__.py +0 -0
  50. {ogx_api-1.1.2 → ogx_api-1.2.0}/files/api.py +0 -0
  51. {ogx_api-1.1.2 → ogx_api-1.2.0}/files/models.py +0 -0
  52. {ogx_api-1.1.2 → ogx_api-1.2.0}/filters.py +0 -0
  53. {ogx_api-1.1.2 → ogx_api-1.2.0}/inference/__init__.py +0 -0
  54. {ogx_api-1.1.2 → ogx_api-1.2.0}/inference/fastapi_routes.py +0 -0
  55. {ogx_api-1.1.2 → ogx_api-1.2.0}/inference/models.py +0 -0
  56. {ogx_api-1.1.2 → ogx_api-1.2.0}/inspect_api/__init__.py +0 -0
  57. {ogx_api-1.1.2 → ogx_api-1.2.0}/inspect_api/api.py +0 -0
  58. {ogx_api-1.1.2 → ogx_api-1.2.0}/inspect_api/fastapi_routes.py +0 -0
  59. {ogx_api-1.1.2 → ogx_api-1.2.0}/inspect_api/models.py +0 -0
  60. {ogx_api-1.1.2 → ogx_api-1.2.0}/interactions/__init__.py +0 -0
  61. {ogx_api-1.1.2 → ogx_api-1.2.0}/interactions/api.py +0 -0
  62. {ogx_api-1.1.2 → ogx_api-1.2.0}/interactions/fastapi_routes.py +0 -0
  63. {ogx_api-1.1.2 → ogx_api-1.2.0}/interactions/models.py +0 -0
  64. {ogx_api-1.1.2 → ogx_api-1.2.0}/internal/__init__.py +0 -0
  65. {ogx_api-1.1.2 → ogx_api-1.2.0}/internal/kvstore.py +0 -0
  66. {ogx_api-1.1.2 → ogx_api-1.2.0}/messages/__init__.py +0 -0
  67. {ogx_api-1.1.2 → ogx_api-1.2.0}/messages/api.py +0 -0
  68. {ogx_api-1.1.2 → ogx_api-1.2.0}/messages/fastapi_routes.py +0 -0
  69. {ogx_api-1.1.2 → ogx_api-1.2.0}/messages/models.py +0 -0
  70. {ogx_api-1.1.2 → ogx_api-1.2.0}/models/__init__.py +0 -0
  71. {ogx_api-1.1.2 → ogx_api-1.2.0}/models/api.py +0 -0
  72. {ogx_api-1.1.2 → ogx_api-1.2.0}/models/fastapi_routes.py +0 -0
  73. {ogx_api-1.1.2 → ogx_api-1.2.0}/models/models.py +0 -0
  74. {ogx_api-1.1.2 → ogx_api-1.2.0}/ogx_api.egg-info/dependency_links.txt +0 -0
  75. {ogx_api-1.1.2 → ogx_api-1.2.0}/ogx_api.egg-info/top_level.txt +0 -0
  76. {ogx_api-1.1.2 → ogx_api-1.2.0}/prompts/__init__.py +0 -0
  77. {ogx_api-1.1.2 → ogx_api-1.2.0}/prompts/api.py +0 -0
  78. {ogx_api-1.1.2 → ogx_api-1.2.0}/prompts/fastapi_routes.py +0 -0
  79. {ogx_api-1.1.2 → ogx_api-1.2.0}/prompts/models.py +0 -0
  80. {ogx_api-1.1.2 → ogx_api-1.2.0}/provider/__init__.py +0 -0
  81. {ogx_api-1.1.2 → ogx_api-1.2.0}/providers/__init__.py +0 -0
  82. {ogx_api-1.1.2 → ogx_api-1.2.0}/providers/api.py +0 -0
  83. {ogx_api-1.1.2 → ogx_api-1.2.0}/providers/fastapi_routes.py +0 -0
  84. {ogx_api-1.1.2 → ogx_api-1.2.0}/providers/models.py +0 -0
  85. {ogx_api-1.1.2 → ogx_api-1.2.0}/py.typed +0 -0
  86. {ogx_api-1.1.2 → ogx_api-1.2.0}/rag_tool.py +0 -0
  87. {ogx_api-1.1.2 → ogx_api-1.2.0}/resource.py +0 -0
  88. {ogx_api-1.1.2 → ogx_api-1.2.0}/responses/api.py +0 -0
  89. {ogx_api-1.1.2 → ogx_api-1.2.0}/responses/fastapi_routes.py +0 -0
  90. {ogx_api-1.1.2 → ogx_api-1.2.0}/router_utils.py +0 -0
  91. {ogx_api-1.1.2 → ogx_api-1.2.0}/schema_utils.py +0 -0
  92. {ogx_api-1.1.2 → ogx_api-1.2.0}/setup.cfg +0 -0
  93. {ogx_api-1.1.2 → ogx_api-1.2.0}/skills/__init__.py +0 -0
  94. {ogx_api-1.1.2 → ogx_api-1.2.0}/skills/api.py +0 -0
  95. {ogx_api-1.1.2 → ogx_api-1.2.0}/skills/fastapi_routes.py +0 -0
  96. {ogx_api-1.1.2 → ogx_api-1.2.0}/skills/models.py +0 -0
  97. {ogx_api-1.1.2 → ogx_api-1.2.0}/tools/__init__.py +0 -0
  98. {ogx_api-1.1.2 → ogx_api-1.2.0}/tools/api.py +0 -0
  99. {ogx_api-1.1.2 → ogx_api-1.2.0}/tools/models.py +0 -0
  100. {ogx_api-1.1.2 → ogx_api-1.2.0}/types/__init__.py +0 -0
  101. {ogx_api-1.1.2 → ogx_api-1.2.0}/validators.py +0 -0
  102. {ogx_api-1.1.2 → ogx_api-1.2.0}/vector_io/__init__.py +0 -0
  103. {ogx_api-1.1.2 → ogx_api-1.2.0}/vector_stores.py +0 -0
  104. {ogx_api-1.1.2 → ogx_api-1.2.0}/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ogx-api
3
- Version: 1.1.2
3
+ Version: 1.2.0
4
4
  Summary: API and Provider specifications for OGX - lightweight package with protocol definitions and provider specs
5
5
  Author-email: The OGX Contributors <contributors@ogx.dev>
6
6
  License: MIT
@@ -15,12 +15,12 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
15
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
16
16
  Requires-Python: >=3.12
17
17
  Description-Content-Type: text/markdown
18
- Requires-Dist: openai>=2.41.0
18
+ Requires-Dist: openai>=2.43.0
19
19
  Requires-Dist: fastapi<1.0,>=0.136.3
20
20
  Requires-Dist: pydantic>=2.11.9
21
21
  Requires-Dist: jsonschema>=4.26.0
22
- Requires-Dist: opentelemetry-sdk>=1.42.1
23
- Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.42.1
22
+ Requires-Dist: opentelemetry-sdk>=1.43.0
23
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.43.0
24
24
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.42.1
25
25
 
26
26
  # ogx-api
@@ -64,6 +64,7 @@ from .responses import (
64
64
  DeleteResponseRequest,
65
65
  ListResponseInputItemsRequest,
66
66
  ListResponsesRequest,
67
+ MemoryToolConfig,
67
68
  ResponseItemInclude,
68
69
  ResponseTruncation,
69
70
  ResponseStreamOptions,
@@ -130,6 +131,44 @@ from .connectors import (
130
131
  GetConnectorToolRequest,
131
132
  ListConnectorToolsRequest,
132
133
  )
134
+ from .containers import (
135
+ Container,
136
+ ContainerCreateRequest,
137
+ ContainerDeleteResponse,
138
+ ContainerExpiresAfter,
139
+ ContainerFile,
140
+ ContainerFileDeleteResponse,
141
+ ContainerFileSource,
142
+ ContainerRuntime,
143
+ Containers,
144
+ ContainerStatus,
145
+ DeleteContainerFileRequest,
146
+ DeleteContainerRequest,
147
+ ExecuteShellRequest,
148
+ GetContainerFileContentRequest,
149
+ GetContainerFileRequest,
150
+ GetContainerRequest,
151
+ ListContainerFilesRequest,
152
+ ListContainerFilesResponse,
153
+ ListContainersRequest,
154
+ ListContainersResponse,
155
+ MountSkillsRequest,
156
+ NetworkCredential,
157
+ NetworkDomainCredential,
158
+ NetworkPolicy,
159
+ NetworkPolicyExtended,
160
+ NetworkPolicyMode,
161
+ ShellCallOutput,
162
+ ShellEnvironment,
163
+ ShellEnvironmentContainerAuto,
164
+ ShellEnvironmentContainerReference,
165
+ ShellEnvironmentLocal,
166
+ ShellOutcome,
167
+ ShellOutcomeFailure,
168
+ ShellOutcomeSuccess,
169
+ ShellOutcomeTimeout,
170
+ UploadContainerFileRequest,
171
+ )
133
172
  from .conversations import (
134
173
  AddItemsRequest,
135
174
  Conversation,
@@ -550,6 +589,7 @@ __all__ = [
550
589
  "DeleteResponseRequest",
551
590
  "ListResponseInputItemsRequest",
552
591
  "ListResponsesRequest",
592
+ "MemoryToolConfig",
553
593
  "RetrieveResponseRequest",
554
594
  "AllowedToolsFilter",
555
595
  "Api",
@@ -587,6 +627,42 @@ __all__ = [
587
627
  "ConnectorInput",
588
628
  "Connectors",
589
629
  "ConnectorType",
630
+ "Container",
631
+ "ContainerCreateRequest",
632
+ "ContainerDeleteResponse",
633
+ "ContainerExpiresAfter",
634
+ "ContainerFile",
635
+ "ContainerFileDeleteResponse",
636
+ "ContainerFileSource",
637
+ "ContainerRuntime",
638
+ "Containers",
639
+ "ContainerStatus",
640
+ "DeleteContainerFileRequest",
641
+ "DeleteContainerRequest",
642
+ "ExecuteShellRequest",
643
+ "GetContainerFileContentRequest",
644
+ "GetContainerFileRequest",
645
+ "GetContainerRequest",
646
+ "ListContainerFilesRequest",
647
+ "ListContainerFilesResponse",
648
+ "ListContainersRequest",
649
+ "ListContainersResponse",
650
+ "MountSkillsRequest",
651
+ "NetworkCredential",
652
+ "NetworkDomainCredential",
653
+ "NetworkPolicy",
654
+ "NetworkPolicyExtended",
655
+ "NetworkPolicyMode",
656
+ "ShellCallOutput",
657
+ "ShellEnvironment",
658
+ "ShellEnvironmentContainerAuto",
659
+ "ShellEnvironmentContainerReference",
660
+ "ShellEnvironmentLocal",
661
+ "ShellOutcome",
662
+ "ShellOutcomeFailure",
663
+ "ShellOutcomeSuccess",
664
+ "ShellOutcomeTimeout",
665
+ "UploadContainerFileRequest",
590
666
  "AddItemsRequest",
591
667
  "Conversation",
592
668
  "ConversationDeletedResource",
@@ -0,0 +1,92 @@
1
+ # Copyright (c) The OGX Contributors.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ """Containers API module.
8
+
9
+ Provides CRUD over sandboxed execution environments used by the Responses
10
+ ``shell`` and ``code_interpreter`` tools. Protocol definitions are in
11
+ ``api.py``, Pydantic models in ``models.py``, and FastAPI routes in
12
+ ``fastapi_routes.py``.
13
+ """
14
+
15
+ from . import fastapi_routes
16
+ from .api import ContainerRuntime, Containers
17
+ from .models import (
18
+ Container,
19
+ ContainerCreateRequest,
20
+ ContainerDeleteResponse,
21
+ ContainerExpiresAfter,
22
+ ContainerFile,
23
+ ContainerFileDeleteResponse,
24
+ ContainerFileSource,
25
+ ContainerStatus,
26
+ DeleteContainerFileRequest,
27
+ DeleteContainerRequest,
28
+ ExecuteShellRequest,
29
+ GetContainerFileContentRequest,
30
+ GetContainerFileRequest,
31
+ GetContainerRequest,
32
+ ListContainerFilesRequest,
33
+ ListContainerFilesResponse,
34
+ ListContainersRequest,
35
+ ListContainersResponse,
36
+ MountSkillsRequest,
37
+ NetworkCredential,
38
+ NetworkDomainCredential,
39
+ NetworkPolicy,
40
+ NetworkPolicyExtended,
41
+ NetworkPolicyMode,
42
+ ShellCallOutput,
43
+ ShellEnvironment,
44
+ ShellEnvironmentContainerAuto,
45
+ ShellEnvironmentContainerReference,
46
+ ShellEnvironmentLocal,
47
+ ShellOutcome,
48
+ ShellOutcomeFailure,
49
+ ShellOutcomeSuccess,
50
+ ShellOutcomeTimeout,
51
+ UploadContainerFileRequest,
52
+ )
53
+
54
+ __all__ = [
55
+ "Container",
56
+ "ContainerCreateRequest",
57
+ "ContainerDeleteResponse",
58
+ "ContainerExpiresAfter",
59
+ "ContainerFile",
60
+ "ContainerFileDeleteResponse",
61
+ "ContainerFileSource",
62
+ "ContainerRuntime",
63
+ "ContainerStatus",
64
+ "Containers",
65
+ "DeleteContainerFileRequest",
66
+ "DeleteContainerRequest",
67
+ "ExecuteShellRequest",
68
+ "GetContainerFileContentRequest",
69
+ "GetContainerFileRequest",
70
+ "GetContainerRequest",
71
+ "ListContainerFilesRequest",
72
+ "ListContainerFilesResponse",
73
+ "ListContainersRequest",
74
+ "ListContainersResponse",
75
+ "MountSkillsRequest",
76
+ "NetworkCredential",
77
+ "NetworkDomainCredential",
78
+ "NetworkPolicy",
79
+ "NetworkPolicyExtended",
80
+ "NetworkPolicyMode",
81
+ "ShellCallOutput",
82
+ "ShellEnvironment",
83
+ "ShellEnvironmentContainerAuto",
84
+ "ShellEnvironmentContainerReference",
85
+ "ShellEnvironmentLocal",
86
+ "ShellOutcome",
87
+ "ShellOutcomeFailure",
88
+ "ShellOutcomeSuccess",
89
+ "ShellOutcomeTimeout",
90
+ "UploadContainerFileRequest",
91
+ "fastapi_routes",
92
+ ]
@@ -0,0 +1,206 @@
1
+ # Copyright (c) The OGX Contributors.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ """Containers API protocol definitions.
8
+
9
+ This module contains two protocols:
10
+
11
+ * ``Containers`` — the HTTP-facing CRUD API for sandboxed execution
12
+ environments.
13
+ * ``ContainerRuntime`` — the internal provider protocol that backends
14
+ (Docker/Podman, Kubernetes, local) implement. The Containers provider
15
+ delegates to a ``ContainerRuntime`` for the actual lifecycle, file, and
16
+ shell-execution work.
17
+
18
+ Pydantic models are defined in ``models.py`` and FastAPI routes in
19
+ ``fastapi_routes.py``.
20
+ """
21
+
22
+ from typing import Protocol, runtime_checkable
23
+
24
+ from fastapi import Response, UploadFile
25
+
26
+ from .models import (
27
+ Container,
28
+ ContainerCreateRequest,
29
+ ContainerDeleteResponse,
30
+ ContainerFile,
31
+ ContainerFileDeleteResponse,
32
+ DeleteContainerFileRequest,
33
+ DeleteContainerRequest,
34
+ ExecuteShellRequest,
35
+ GetContainerFileContentRequest,
36
+ GetContainerFileRequest,
37
+ GetContainerRequest,
38
+ ListContainerFilesRequest,
39
+ ListContainerFilesResponse,
40
+ ListContainersRequest,
41
+ ListContainersResponse,
42
+ MountSkillsRequest,
43
+ ShellCallOutput,
44
+ UploadContainerFileRequest,
45
+ )
46
+
47
+
48
+ @runtime_checkable
49
+ class Containers(Protocol):
50
+ """HTTP API for managing sandboxed execution containers.
51
+
52
+ Implementations enforce policy layering (request-supplied
53
+ ``NetworkPolicyExtended`` cannot expand operator defaults) and then
54
+ delegate to a configured :class:`ContainerRuntime` for backend work.
55
+ """
56
+
57
+ async def create_container(
58
+ self,
59
+ request: ContainerCreateRequest,
60
+ ) -> Container: ...
61
+
62
+ async def list_containers(
63
+ self,
64
+ request: ListContainersRequest,
65
+ ) -> ListContainersResponse: ...
66
+
67
+ async def get_container(
68
+ self,
69
+ request: GetContainerRequest,
70
+ ) -> Container: ...
71
+
72
+ async def delete_container(
73
+ self,
74
+ request: DeleteContainerRequest,
75
+ ) -> ContainerDeleteResponse: ...
76
+
77
+ async def upload_container_file(
78
+ self,
79
+ request: UploadContainerFileRequest,
80
+ file: UploadFile,
81
+ ) -> ContainerFile: ...
82
+
83
+ async def list_container_files(
84
+ self,
85
+ request: ListContainerFilesRequest,
86
+ ) -> ListContainerFilesResponse: ...
87
+
88
+ async def get_container_file(
89
+ self,
90
+ request: GetContainerFileRequest,
91
+ ) -> ContainerFile: ...
92
+
93
+ async def get_container_file_content(
94
+ self,
95
+ request: GetContainerFileContentRequest,
96
+ ) -> Response: ...
97
+
98
+ async def delete_container_file(
99
+ self,
100
+ request: DeleteContainerFileRequest,
101
+ ) -> ContainerFileDeleteResponse: ...
102
+
103
+
104
+ @runtime_checkable
105
+ class ContainerRuntime(Protocol):
106
+ """Internal provider protocol for container backends.
107
+
108
+ A ``ContainerRuntime`` provider is the thin layer between the Containers
109
+ API and a concrete backend (Docker/Podman socket, Kubernetes API, local
110
+ process supervisor). The Responses ``shell`` tool also calls
111
+ ``execute_shell`` directly when running in ``container_auto`` /
112
+ ``container_reference`` modes.
113
+
114
+ This protocol is not exposed over HTTP.
115
+ """
116
+
117
+ # --- lifecycle -------------------------------------------------------
118
+
119
+ async def create_container(
120
+ self,
121
+ request: ContainerCreateRequest,
122
+ ) -> Container:
123
+ """Create and start a container. Raises if resource limits are exceeded."""
124
+ ...
125
+
126
+ async def get_container(self, request: GetContainerRequest) -> Container:
127
+ """Fetch the current state of a container, including ``last_active_at``."""
128
+ ...
129
+
130
+ async def list_containers(
131
+ self,
132
+ request: ListContainersRequest,
133
+ ) -> ListContainersResponse:
134
+ """List containers known to this runtime."""
135
+ ...
136
+
137
+ async def delete_container(self, request: DeleteContainerRequest) -> ContainerDeleteResponse:
138
+ """Stop and remove a container along with its filesystem."""
139
+ ...
140
+
141
+ # --- file management ------------------------------------------------
142
+
143
+ async def upload_file(
144
+ self,
145
+ request: UploadContainerFileRequest,
146
+ file: UploadFile,
147
+ ) -> ContainerFile:
148
+ """Copy an uploaded file into the container at the runtime-chosen path."""
149
+ ...
150
+
151
+ async def list_files(
152
+ self,
153
+ request: ListContainerFilesRequest,
154
+ ) -> ListContainerFilesResponse:
155
+ """List files tracked inside a container."""
156
+ ...
157
+
158
+ async def get_file(
159
+ self,
160
+ request: GetContainerFileRequest,
161
+ ) -> ContainerFile:
162
+ """Get metadata for a single file inside a container."""
163
+ ...
164
+
165
+ async def get_file_content(
166
+ self,
167
+ request: GetContainerFileContentRequest,
168
+ ) -> Response:
169
+ """Stream the bytes of a file inside a container."""
170
+ ...
171
+
172
+ async def delete_file(
173
+ self,
174
+ request: DeleteContainerFileRequest,
175
+ ) -> ContainerFileDeleteResponse:
176
+ """Remove a file from a container's filesystem."""
177
+ ...
178
+
179
+ # --- execution ------------------------------------------------------
180
+
181
+ async def execute_shell(
182
+ self,
183
+ request: ExecuteShellRequest,
184
+ ) -> ShellCallOutput:
185
+ """Run a shell command inside the container and capture its output.
186
+
187
+ ``request.command`` is passed as ``argv`` (no shell expansion) to keep
188
+ the interface uniform across backends. Implementations are expected to
189
+ update ``last_active_at`` on the container as a side effect.
190
+ """
191
+ ...
192
+
193
+ # --- skill mounting -------------------------------------------------
194
+
195
+ async def mount_skills(
196
+ self,
197
+ request: MountSkillsRequest,
198
+ ) -> None:
199
+ """Mount skill bundles into ``/mnt/skills/{skill_name}/`` inside the container.
200
+
201
+ Each entry of ``request.skill_bundles`` is ``(skill_name, zip_bytes)``
202
+ — the zip archive is extracted into the named directory. Calling this
203
+ method multiple times with overlapping names overwrites the previous
204
+ contents.
205
+ """
206
+ ...
@@ -0,0 +1,205 @@
1
+ # Copyright (c) The OGX Contributors.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ """FastAPI routes for the Containers API.
8
+
9
+ Endpoints are mounted at ``/v1alpha/containers``. See
10
+ :class:`ogx_api.containers.api.Containers` for the protocol implementations
11
+ must satisfy.
12
+ """
13
+
14
+ from typing import Annotated
15
+
16
+ from fastapi import APIRouter, Depends, UploadFile
17
+ from fastapi.param_functions import File
18
+ from fastapi.responses import Response
19
+
20
+ from ogx_api.common.upload_limits import (
21
+ DEFAULT_MAX_UPLOAD_SIZE_BYTES,
22
+ PreReadUploadFile,
23
+ read_upload_with_size_limit,
24
+ )
25
+ from ogx_api.router_utils import create_path_dependency, create_query_dependency, standard_responses
26
+ from ogx_api.version import OGX_API_V1ALPHA
27
+
28
+ from .api import Containers
29
+ from .models import (
30
+ Container,
31
+ ContainerCreateRequest,
32
+ ContainerDeleteResponse,
33
+ ContainerFile,
34
+ ContainerFileDeleteResponse,
35
+ DeleteContainerFileRequest,
36
+ DeleteContainerRequest,
37
+ GetContainerFileContentRequest,
38
+ GetContainerFileRequest,
39
+ GetContainerRequest,
40
+ ListContainerFilesRequest,
41
+ ListContainerFilesResponse,
42
+ ListContainersRequest,
43
+ ListContainersResponse,
44
+ UploadContainerFileRequest,
45
+ )
46
+
47
+ get_list_containers_request = create_query_dependency(ListContainersRequest)
48
+ get_container_request = create_path_dependency(GetContainerRequest)
49
+ get_delete_container_request = create_path_dependency(DeleteContainerRequest)
50
+ get_upload_container_file_request = create_path_dependency(UploadContainerFileRequest)
51
+
52
+
53
+ # Multi-field path-parameter models cannot use create_path_dependency, which only
54
+ # supports single-field models. The helpers below combine path (+ query) params
55
+ # into the request model explicitly.
56
+
57
+
58
+ def _list_container_files_request(
59
+ container_id: str,
60
+ after: str | None = None,
61
+ limit: int | None = 20,
62
+ order: str | None = "desc",
63
+ ) -> ListContainerFilesRequest:
64
+ return ListContainerFilesRequest.model_validate(
65
+ {"container_id": container_id, "after": after, "limit": limit, "order": order}
66
+ )
67
+
68
+
69
+ def _get_container_file_request(container_id: str, file_id: str) -> GetContainerFileRequest:
70
+ return GetContainerFileRequest(container_id=container_id, file_id=file_id)
71
+
72
+
73
+ def _get_container_file_content_request(container_id: str, file_id: str) -> GetContainerFileContentRequest:
74
+ return GetContainerFileContentRequest(container_id=container_id, file_id=file_id)
75
+
76
+
77
+ def _delete_container_file_request(container_id: str, file_id: str) -> DeleteContainerFileRequest:
78
+ return DeleteContainerFileRequest(container_id=container_id, file_id=file_id)
79
+
80
+
81
+ def create_router(impl: Containers, max_upload_size_bytes: int = DEFAULT_MAX_UPLOAD_SIZE_BYTES) -> APIRouter:
82
+ router = APIRouter(
83
+ prefix=f"/{OGX_API_V1ALPHA}",
84
+ tags=["Containers"],
85
+ responses=standard_responses,
86
+ )
87
+
88
+ @router.post(
89
+ "/containers",
90
+ response_model=Container,
91
+ summary="Create container",
92
+ description="Create a sandboxed container for shell/code execution.",
93
+ responses={200: {"description": "The created container."}},
94
+ )
95
+ async def create_container(request: ContainerCreateRequest) -> Container:
96
+ return await impl.create_container(request)
97
+
98
+ @router.get(
99
+ "/containers",
100
+ response_model=ListContainersResponse,
101
+ summary="List containers",
102
+ description="List containers.",
103
+ responses={200: {"description": "The list of containers."}},
104
+ )
105
+ async def list_containers(
106
+ request: Annotated[ListContainersRequest, Depends(get_list_containers_request)],
107
+ ) -> ListContainersResponse:
108
+ return await impl.list_containers(request)
109
+
110
+ @router.get(
111
+ "/containers/{container_id}",
112
+ response_model=Container,
113
+ summary="Get container",
114
+ description="Get a container by ID.",
115
+ responses={200: {"description": "The container."}},
116
+ )
117
+ async def get_container(
118
+ request: Annotated[GetContainerRequest, Depends(get_container_request)],
119
+ ) -> Container:
120
+ return await impl.get_container(request)
121
+
122
+ @router.delete(
123
+ "/containers/{container_id}",
124
+ response_model=ContainerDeleteResponse,
125
+ summary="Delete container",
126
+ description="Stop and remove a container.",
127
+ responses={200: {"description": "The container was deleted."}},
128
+ )
129
+ async def delete_container(
130
+ request: Annotated[DeleteContainerRequest, Depends(get_delete_container_request)],
131
+ ) -> ContainerDeleteResponse:
132
+ return await impl.delete_container(request)
133
+
134
+ @router.post(
135
+ "/containers/{container_id}/files",
136
+ response_model=ContainerFile,
137
+ summary="Upload container file",
138
+ description="Upload a file into a container's filesystem.",
139
+ responses={200: {"description": "The uploaded container file."}},
140
+ )
141
+ async def upload_container_file(
142
+ container_id: str,
143
+ file: Annotated[UploadFile, File(description="The file to upload into the container.")],
144
+ ) -> ContainerFile:
145
+ content = await read_upload_with_size_limit(file, max_upload_size_bytes)
146
+ safe_file = PreReadUploadFile(content, filename=file.filename, content_type=file.content_type)
147
+ return await impl.upload_container_file(
148
+ UploadContainerFileRequest(container_id=container_id),
149
+ safe_file,
150
+ )
151
+
152
+ @router.get(
153
+ "/containers/{container_id}/files",
154
+ response_model=ListContainerFilesResponse,
155
+ summary="List container files",
156
+ description="List files inside a container.",
157
+ responses={200: {"description": "The list of files."}},
158
+ )
159
+ async def list_container_files(
160
+ request: Annotated[ListContainerFilesRequest, Depends(_list_container_files_request)],
161
+ ) -> ListContainerFilesResponse:
162
+ return await impl.list_container_files(request)
163
+
164
+ @router.get(
165
+ "/containers/{container_id}/files/{file_id}",
166
+ response_model=ContainerFile,
167
+ summary="Get container file",
168
+ description="Get metadata for a file inside a container.",
169
+ responses={200: {"description": "The container file metadata."}},
170
+ )
171
+ async def get_container_file(
172
+ request: Annotated[GetContainerFileRequest, Depends(_get_container_file_request)],
173
+ ) -> ContainerFile:
174
+ return await impl.get_container_file(request)
175
+
176
+ @router.get(
177
+ "/containers/{container_id}/files/{file_id}/content",
178
+ status_code=200,
179
+ summary="Get container file content",
180
+ description="Download the contents of a file inside a container.",
181
+ responses={
182
+ 200: {
183
+ "description": "The file content.",
184
+ "content": {"application/octet-stream": {"schema": {"type": "string", "format": "binary"}}},
185
+ },
186
+ },
187
+ )
188
+ async def get_container_file_content(
189
+ request: Annotated[GetContainerFileContentRequest, Depends(_get_container_file_content_request)],
190
+ ) -> Response:
191
+ return await impl.get_container_file_content(request)
192
+
193
+ @router.delete(
194
+ "/containers/{container_id}/files/{file_id}",
195
+ response_model=ContainerFileDeleteResponse,
196
+ summary="Delete container file",
197
+ description="Remove a file from a container's filesystem.",
198
+ responses={200: {"description": "The file was deleted."}},
199
+ )
200
+ async def delete_container_file(
201
+ request: Annotated[DeleteContainerFileRequest, Depends(_delete_container_file_request)],
202
+ ) -> ContainerFileDeleteResponse:
203
+ return await impl.delete_container_file(request)
204
+
205
+ return router