docket-client 0.3.2__py3-none-any.whl

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 (188) hide show
  1. docket/__init__.py +8 -0
  2. docket/api/__init__.py +1 -0
  3. docket/api/access/__init__.py +1 -0
  4. docket/api/access/add_principal.py +193 -0
  5. docket/api/access/archive_role_assignment.py +182 -0
  6. docket/api/access/create_api_token.py +198 -0
  7. docket/api/access/create_application_principal.py +188 -0
  8. docket/api/access/create_role_assignment.py +194 -0
  9. docket/api/access/list_api_tokens.py +184 -0
  10. docket/api/access/list_principals.py +184 -0
  11. docket/api/access/list_role_assignments.py +200 -0
  12. docket/api/access/revoke_api_token.py +173 -0
  13. docket/api/identity/__init__.py +1 -0
  14. docket/api/identity/create_my_api_token.py +206 -0
  15. docket/api/identity/get_me.py +127 -0
  16. docket/api/identity/list_my_api_tokens.py +151 -0
  17. docket/api/identity/revoke_my_api_token.py +178 -0
  18. docket/api/recurring_acquisitions/__init__.py +1 -0
  19. docket/api/recurring_acquisitions/archive_recurring_acquisition.py +207 -0
  20. docket/api/recurring_acquisitions/create_recurring_acquisition.py +218 -0
  21. docket/api/recurring_acquisitions/get_recurring_acquisition.py +163 -0
  22. docket/api/recurring_acquisitions/list_recurring_acquisitions.py +248 -0
  23. docket/api/recurring_acquisitions/preview_recurring_acquisition.py +187 -0
  24. docket/api/recurring_acquisitions/preview_split_recurring_acquisition.py +232 -0
  25. docket/api/recurring_acquisitions/split_recurring_acquisition.py +258 -0
  26. docket/api/runs/__init__.py +1 -0
  27. docket/api/runs/get_run.py +160 -0
  28. docket/api/runs/list_runs.py +180 -0
  29. docket/api/runs/report_run_outcome.py +206 -0
  30. docket/api/scheduled_acquisitions/__init__.py +1 -0
  31. docket/api/scheduled_acquisitions/archive_scheduled_acquisition.py +203 -0
  32. docket/api/scheduled_acquisitions/create_scheduled_acquisition.py +185 -0
  33. docket/api/scheduled_acquisitions/get_resolved_settings.py +169 -0
  34. docket/api/scheduled_acquisitions/get_scheduled_acquisition.py +159 -0
  35. docket/api/scheduled_acquisitions/list_active_acquisitions.py +297 -0
  36. docket/api/scheduled_acquisitions/list_runs_for_scheduled_acquisition.py +191 -0
  37. docket/api/scheduled_acquisitions/list_scheduled_acquisitions.py +332 -0
  38. docket/api/scheduled_acquisitions/preview_scheduled_acquisition_edit.py +224 -0
  39. docket/api/scheduled_acquisitions/set_planning_status.py +199 -0
  40. docket/api/scheduled_acquisitions/start_run.py +221 -0
  41. docket/api/scheduled_acquisitions/update_scheduled_acquisition.py +226 -0
  42. docket/api/settings/__init__.py +1 -0
  43. docket/api/settings/list_behavior_curriculum_discriminator_values.py +188 -0
  44. docket/api/settings/list_behavior_curriculum_settings.py +199 -0
  45. docket/api/settings/list_fip_discriminator_values.py +184 -0
  46. docket/api/settings/list_fip_settings.py +195 -0
  47. docket/api/settings/list_live_behavior_curriculum_settings.py +233 -0
  48. docket/api/settings/list_live_fip_settings.py +225 -0
  49. docket/api/settings/preview_behavior_curriculum_settings.py +191 -0
  50. docket/api/settings/preview_fip_settings.py +177 -0
  51. docket/api/settings/push_behavior_curriculum_settings.py +222 -0
  52. docket/api/settings/push_fip_settings.py +206 -0
  53. docket/api/templates/__init__.py +1 -0
  54. docket/api/templates/archive_template.py +203 -0
  55. docket/api/templates/create_template.py +206 -0
  56. docket/api/templates/get_template.py +159 -0
  57. docket/api/templates/list_templates.py +174 -0
  58. docket/api/templates/update_template.py +234 -0
  59. docket/api/vocabulary/__init__.py +1 -0
  60. docket/api/vocabulary/list_instruments.py +165 -0
  61. docket/api/vocabulary/list_persons.py +132 -0
  62. docket/api/vocabulary/list_projects.py +132 -0
  63. docket/api/vocabulary/list_subjects.py +132 -0
  64. docket/api/vocabulary/lookup_person.py +166 -0
  65. docket/api/vocabulary/lookup_subject.py +166 -0
  66. docket/api/vocabulary/sync_vocabulary.py +148 -0
  67. docket/client.py +272 -0
  68. docket/errors.py +16 -0
  69. docket/models/__init__.py +221 -0
  70. docket/models/access_role.py +12 -0
  71. docket/models/access_role_nullable_type_1.py +12 -0
  72. docket/models/access_role_nullable_type_2_type_1.py +12 -0
  73. docket/models/access_role_nullable_type_3_type_1.py +12 -0
  74. docket/models/acquisition_variable.py +72 -0
  75. docket/models/acquisition_warning.py +126 -0
  76. docket/models/add_principal_request.py +83 -0
  77. docket/models/api_token_response.py +271 -0
  78. docket/models/api_token_status.py +10 -0
  79. docket/models/archive_recurring_acquisition_request.py +77 -0
  80. docket/models/archive_recurring_acquisition_response.py +83 -0
  81. docket/models/archive_scheduled_acquisition_request.py +78 -0
  82. docket/models/archive_template_request.py +66 -0
  83. docket/models/auth_mode.py +10 -0
  84. docket/models/behavior_curriculum_push_settings_request.py +85 -0
  85. docket/models/behavior_curriculum_settings.py +55 -0
  86. docket/models/behavior_curriculum_settings_preview_response.py +102 -0
  87. docket/models/behavior_curriculum_settings_preview_response_promoted.py +50 -0
  88. docket/models/behavior_curriculum_settings_version_response.py +160 -0
  89. docket/models/behavior_curriculum_settings_version_response_promoted.py +50 -0
  90. docket/models/caller_kind.py +11 -0
  91. docket/models/create_api_token_request.py +97 -0
  92. docket/models/create_application_principal_request.py +65 -0
  93. docket/models/create_personal_api_token_request.py +167 -0
  94. docket/models/create_recurring_acquisition_request.py +269 -0
  95. docket/models/create_role_assignment_request.py +99 -0
  96. docket/models/create_scheduled_acquisition_request.py +265 -0
  97. docket/models/create_template_request.py +323 -0
  98. docket/models/created_api_token_response.py +82 -0
  99. docket/models/effective_status.py +15 -0
  100. docket/models/fip_color.py +13 -0
  101. docket/models/fip_fiber.py +93 -0
  102. docket/models/fip_mode.py +9 -0
  103. docket/models/fip_push_settings_request.py +82 -0
  104. docket/models/fip_settings.py +91 -0
  105. docket/models/fip_settings_preview_response.py +97 -0
  106. docket/models/fip_settings_preview_response_promoted.py +50 -0
  107. docket/models/fip_settings_version_response.py +155 -0
  108. docket/models/fip_settings_version_response_promoted.py +50 -0
  109. docket/models/future_occurrences.py +9 -0
  110. docket/models/get_resolved_settings_response_200.py +65 -0
  111. docket/models/held_role_response.py +116 -0
  112. docket/models/http_validation_problem_details.py +204 -0
  113. docket/models/http_validation_problem_details_errors.py +59 -0
  114. docket/models/instrument_response.py +91 -0
  115. docket/models/kept_occurrence.py +85 -0
  116. docket/models/kept_occurrence_reason.py +10 -0
  117. docket/models/list_active_acquisitions_effective_status_item.py +15 -0
  118. docket/models/list_scheduled_acquisitions_planning_status.py +11 -0
  119. docket/models/me_caller.py +118 -0
  120. docket/models/me_permission.py +98 -0
  121. docket/models/me_response.py +158 -0
  122. docket/models/me_role.py +75 -0
  123. docket/models/occurrence_preview.py +121 -0
  124. docket/models/occurrence_summary.py +126 -0
  125. docket/models/occurrence_warnings.py +91 -0
  126. docket/models/permission_action.py +12 -0
  127. docket/models/person_assignment.py +74 -0
  128. docket/models/person_lookup_response.py +131 -0
  129. docket/models/person_response.py +103 -0
  130. docket/models/person_role.py +9 -0
  131. docket/models/personal_token_limits.py +92 -0
  132. docket/models/planning_status.py +11 -0
  133. docket/models/principal_kind.py +9 -0
  134. docket/models/principal_response.py +216 -0
  135. docket/models/problem_details.py +177 -0
  136. docket/models/project_response.py +75 -0
  137. docket/models/recurrence_exception_kind.py +13 -0
  138. docket/models/recurrence_exception_response.py +103 -0
  139. docket/models/recurrence_frequency.py +9 -0
  140. docket/models/recurrence_preview_response.py +101 -0
  141. docket/models/recurrence_rule.py +207 -0
  142. docket/models/recurring_acquisition_created_response.py +123 -0
  143. docket/models/recurring_acquisition_detail_response.py +105 -0
  144. docket/models/recurring_acquisition_response.py +326 -0
  145. docket/models/report_run_outcome_request.py +89 -0
  146. docket/models/resolution_mode.py +10 -0
  147. docket/models/resolved_settings.py +73 -0
  148. docket/models/role_assignment_response.py +157 -0
  149. docket/models/role_origin.py +10 -0
  150. docket/models/role_source_kind.py +10 -0
  151. docket/models/run_origin.py +9 -0
  152. docket/models/run_outcome.py +9 -0
  153. docket/models/run_response.py +181 -0
  154. docket/models/run_settings_snapshot.py +72 -0
  155. docket/models/run_start_response.py +91 -0
  156. docket/models/run_start_response_settings.py +65 -0
  157. docket/models/run_status.py +11 -0
  158. docket/models/scheduled_acquisition_edit_preview_response.py +150 -0
  159. docket/models/scheduled_acquisition_response.py +366 -0
  160. docket/models/set_planning_status_request.py +90 -0
  161. docket/models/settings_selector.py +138 -0
  162. docket/models/skipped_occurrence.py +85 -0
  163. docket/models/split_preview_response.py +129 -0
  164. docket/models/split_recurring_acquisition_request.py +261 -0
  165. docket/models/split_recurring_acquisition_response.py +159 -0
  166. docket/models/start_run_request.py +73 -0
  167. docket/models/subject_lookup_response.py +149 -0
  168. docket/models/subject_response.py +128 -0
  169. docket/models/sync_counts.py +80 -0
  170. docket/models/sync_response.py +81 -0
  171. docket/models/template_response.py +302 -0
  172. docket/models/update_scheduled_acquisition_request.py +235 -0
  173. docket/models/update_template_request.py +279 -0
  174. docket/models/weekday.py +14 -0
  175. docket/types.py +54 -0
  176. docket_auth/__init__.py +239 -0
  177. docket_client-0.3.2.dist-info/METADATA +233 -0
  178. docket_client-0.3.2.dist-info/RECORD +188 -0
  179. docket_client-0.3.2.dist-info/WHEEL +4 -0
  180. docket_client-0.3.2.dist-info/entry_points.txt +2 -0
  181. docket_mcp/__init__.py +6 -0
  182. docket_mcp/api.py +207 -0
  183. docket_mcp/config.py +57 -0
  184. docket_mcp/server.py +78 -0
  185. docket_mcp/signin.py +155 -0
  186. docket_mcp/slots.py +80 -0
  187. docket_mcp/times.py +160 -0
  188. docket_mcp/tools.py +1202 -0
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.5
2
+ Name: docket-client
3
+ Version: 0.3.2
4
+ Summary: Typed Python client for the docket scheduling API
5
+ Project-URL: Homepage, https://github.com/AllenNeuralDynamics/docket
6
+ Project-URL: Repository, https://github.com/AllenNeuralDynamics/docket
7
+ Project-URL: Bug Tracker, https://github.com/AllenNeuralDynamics/docket/issues
8
+ Project-URL: Changelog, https://github.com/AllenNeuralDynamics/docket/releases
9
+ Author: Allen Institute for Neural Dynamics
10
+ License-Expression: MIT
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: attrs>=22.2.0
22
+ Requires-Dist: httpx<0.29.0,>=0.23.1
23
+ Provides-Extra: auth
24
+ Requires-Dist: msal<2,>=1.31; extra == 'auth'
25
+ Provides-Extra: mcp
26
+ Requires-Dist: mcp<2,>=1.30; extra == 'mcp'
27
+ Requires-Dist: msal<2,>=1.31; extra == 'mcp'
28
+ Requires-Dist: tzdata>=2024.1; (sys_platform == 'win32') and extra == 'mcp'
29
+ Requires-Dist: tzlocal<6,>=5; extra == 'mcp'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # docket
33
+
34
+ A typed Python client for the **docket** scheduling API.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install docket-client
40
+ # the unreleased version, from the repository:
41
+ pip install "docket-client @ git+https://github.com/AllenNeuralDynamics/docket#subdirectory=client"
42
+ # or, from the repo root during development:
43
+ pip install ./client
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ ```python
49
+ from docket import Client
50
+
51
+ client = Client(base_url="http://localhost:8001")
52
+ ```
53
+
54
+ For authenticated endpoints use `AuthenticatedClient`:
55
+
56
+ ```python
57
+ from docket import AuthenticatedClient
58
+
59
+ client = AuthenticatedClient(base_url="https://api.example.com", token="SuperSecretToken")
60
+ ```
61
+
62
+ Call any endpoint:
63
+
64
+ ```python
65
+ from docket.api.scheduled_acquisitions import list_active_acquisitions
66
+
67
+ sessions = list_active_acquisitions.sync(
68
+ client=client,
69
+ instrument_id="BEH.B-Box1",
70
+ before_minutes=15,
71
+ effective_status=["scheduled", "ongoing"],
72
+ )
73
+ ```
74
+
75
+ Every endpoint module exposes four variants:
76
+
77
+ | Function | Behaviour |
78
+ | --- | --- |
79
+ | `sync` | Blocking — returns the parsed response body or `None` |
80
+ | `sync_detailed` | Blocking — always returns a `Response` object with status code, headers, and `parsed` |
81
+ | `asyncio` | Async equivalent of `sync` |
82
+ | `asyncio_detailed` | Async equivalent of `sync_detailed` |
83
+
84
+ See [examples/downstream_usage.py](examples/downstream_usage.py) for a
85
+ full end-to-end walkthrough.
86
+
87
+ ## MCP server (`docket-mcp`)
88
+
89
+ `docket-mcp` lets an AI assistant (Claude Code, Claude Desktop, any MCP client) look at the
90
+ schedule and change it, through the same API as everyone else. It runs **locally over stdio**:
91
+ the client starts it on your machine, so it reaches Docket over your own network or VPN and
92
+ nothing new is hosted. It is the `docket_mcp` package here, next to `docket_auth`.
93
+
94
+ ### Install
95
+
96
+ ```bash
97
+ pip install "docket-client[mcp]"
98
+ # or as an isolated tool (puts `docket-mcp` on your PATH):
99
+ uv tool install "docket-client[mcp]"
100
+ # from a checkout:
101
+ uv tool install "./client[mcp]"
102
+ ```
103
+
104
+ ### Add it to your assistant
105
+
106
+ Claude Code:
107
+
108
+ ```bash
109
+ claude mcp add docket -e DOCKET_API_URL=http://localhost:8001 -e DOCKET_TIME_ZONE=America/Los_Angeles -- docket-mcp
110
+ # with an API token (see "Sign-in"):
111
+ claude mcp add docket -e DOCKET_API_URL=https://docket.example.org -e DOCKET_API_TOKEN=dkt_... -- docket-mcp
112
+ # straight from a checkout, without installing:
113
+ claude mcp add docket -e DOCKET_API_URL=http://localhost:8001 -- uv run --project ./client --extra mcp docket-mcp
114
+ ```
115
+
116
+ Claude Desktop (`claude_desktop_config.json`):
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "docket": {
122
+ "command": "docket-mcp",
123
+ "env": {
124
+ "DOCKET_API_URL": "http://localhost:8001",
125
+ "DOCKET_TIME_ZONE": "America/Los_Angeles",
126
+ "DOCKET_API_TOKEN": "dkt_..."
127
+ }
128
+ }
129
+ }
130
+ }
131
+ ```
132
+
133
+ If `docket-mcp` is not on the app's `PATH`, give its full path as `command`.
134
+
135
+ ### Configuration
136
+
137
+ All through environment variables:
138
+
139
+ | Variable | Meaning |
140
+ | --- | --- |
141
+ | `DOCKET_API_URL` | The API's address. Default `http://localhost:8001`. A frontend origin works too (`https://docket.example.org` or `…/api`), with its URL prefix if it has one (`https://host/docket`). |
142
+ | `DOCKET_TIME_ZONE` | IANA zone for the local times you give and get back. Default: this machine's zone. A tool's `time_zone` argument overrides it. |
143
+ | `DOCKET_API_TOKEN` | A Docket API token (`dkt_…`). Checked **first**; works in Tokens and Entra mode. |
144
+ | `DOCKET_AUTH_CLIENT_ID`, `DOCKET_AUTH_SCOPE`, `DOCKET_AUTH_TENANT_ID` (or `DOCKET_AUTH_AUTHORITY`) | Entra sign-in when there is no API token: the SPA's public client id, `api://…/access_as_user`, and the tenant (or another OIDC authority, such as the mock provider). |
145
+ | `DOCKET_AUTH_CLIENT_SECRET` | With the three above: sign in as an application (client credentials) instead of as a person. |
146
+ | `DOCKET_AUTH_CACHE_PATH` | Where the person's token cache lives. Default `~/.docket/mcp-token-cache.json` (holds refresh tokens: protect it). |
147
+
148
+ ### Sign-in
149
+
150
+ Reads are anonymous. The server asks `/api/v1/me` once for `auth_mode`, and only **writes** carry a token.
151
+
152
+ - `auth_mode: disabled` (the default Docket): nothing to set up and you are never asked to sign in.
153
+ - `auth_mode: tokens`: set `DOCKET_API_TOKEN`. Ask an admin for a token from **Settings > Access**. Without one, write tools say so.
154
+ - `auth_mode: entra`: set `DOCKET_API_TOKEN` too (simplest), or sign in as yourself. The first write prints a URL and a code to stderr **and** returns them as the tool's error text (some clients hide stderr); open the URL, enter the code, then run the tool again. The token is cached afterwards. Set `DOCKET_AUTH_CLIENT_SECRET` for an unattended application.
155
+
156
+ Tokens are never logged or returned by a tool. `whoami` shows your auth mode, caller, roles (and where each came from) and grants: as yourself when a credential is available without interaction (an API token, client credentials or a cached sign-in), otherwise as anonymous (`signed_in: false`). It never starts a sign-in.
157
+
158
+ The device-code token cache holds refresh tokens. It is created owner-only (`chmod 600`) on Linux and macOS; on Windows `chmod` is a no-op and the file relies on your user profile's ACL, so keep it there (the default is `~/.docket/`).
159
+
160
+ ### Tools
161
+
162
+ | Read | |
163
+ | --- | --- |
164
+ | `list_rigs`, `list_projects` | what you can book, with optional `search` |
165
+ | `lookup_subject`, `lookup_person` | check an id or username exists |
166
+ | `get_schedule` | sessions between two dates (rig, subject, person, archived filters) |
167
+ | `get_acquisition` | one session in full: people, notes, resolved settings, runs |
168
+ | `find_free_slots` | gaps on a rig long enough for a session, within daily bounds |
169
+ | `list_series`, `get_series` | recurring series and their rules |
170
+ | `list_templates`, `list_settings`, `list_runs`, `whoami` | |
171
+
172
+ | Write (all take `dry_run`, default **true**) | |
173
+ | --- | --- |
174
+ | `schedule_acquisition` | book one session (optionally from a template) |
175
+ | `move_acquisition` | change start, length or rig |
176
+ | `archive_acquisition` | archive a session (nothing is ever hard-deleted) |
177
+ | `create_series` | a finite daily/weekly series |
178
+ | `edit_series_from` | change a series from a date on (the old one ends, a new one starts) |
179
+ | `archive_series` | archive a series, keeping or archiving its upcoming sessions |
180
+ | `mark_outcome` | record succeeded / failed / cancelled by hand |
181
+
182
+ Not in v1: pushing settings, syncing vocabulary, managing templates and roles.
183
+
184
+ ### Dry runs
185
+
186
+ Every write tool previews by default and changes nothing: it returns what would happen,
187
+ including overlap warnings, skipped (daylight-saving) dates and which sessions a series edit
188
+ would replace or keep. The tool descriptions tell the assistant to show you the preview and
189
+ repeat the call with `dry_run=false` only once you agree. Series and moves use the server's own
190
+ preview endpoints; for a single session the API has none, so the preview checks the schedule
191
+ itself with the server's overlap rule (same rig only; the same subject on another rig is listed
192
+ as `advisory`) and the server checks again when it creates it.
193
+
194
+ Each preview returns what the confirmation needs, under `confirm_with`: the `expected_version`
195
+ of what it looked at (moves, archives, outcomes, series edits and archives) and an
196
+ `idempotency_key` (new sessions, series and series edits). Repeat the call with
197
+ `dry_run=false` and those values. If the session or series changed in between, the call is
198
+ refused with "changed since your preview; preview again" and nothing is written. A retry
199
+ after a timeout with the same key cannot book or create twice.
200
+
201
+ ### Times
202
+
203
+ Give local wall-clock times such as `2026-03-08T09:30`, never offsets. Results show the local
204
+ time (with its offset) and UTC. A time that does not exist (a spring-forward gap) is refused;
205
+ a repeated one (fall back) takes the first occurrence and says so.
206
+
207
+ ### Example prompts
208
+
209
+ - "What is on rig `BEH.A` next week, and which afternoons are free for a 90-minute session?"
210
+ - "Book subject 812345 on `BEH.A` under project `Vision` tomorrow at 10:00 for an hour, with me as experimenter." (it previews first)
211
+ - "Move session 412 to Thursday at 14:00."
212
+ - "Set up a weekly series, Mondays and Thursdays at 09:00 for eight sessions, for subject 812345."
213
+ - "From 2026-11-02, shift that series to 10:30." / "Cancel the rest of series 17 but keep what already ran."
214
+ - "Did anything fail on the FIP rigs this week?"
215
+
216
+ ### Developing
217
+
218
+ ```bash
219
+ uv sync --group dev
220
+ uv run pytest client/tests # unit tests + the stdio smoke test
221
+ uv run pytest client/tests -m integration # schedule -> move -> archive on a real server
222
+ ```
223
+
224
+ The integration test builds the server image and starts its own Compose project
225
+ (`docket-mcp-it`, API on port 8020, static vocabulary, nothing from the institute) and removes
226
+ it afterwards; set `DOCKET_IT_URL` to use a server that is already running instead.
227
+
228
+ ## Building / publishing
229
+
230
+ ```bash
231
+ # from the repo root
232
+ uv build --package docket-client # → dist/docket_client-*.whl
233
+ ```
@@ -0,0 +1,188 @@
1
+ docket/__init__.py,sha256=mXHDX36eM0PU_Xd8Z4QOu5uIMU_QOLVChHkMzeMXAH8,153
2
+ docket/client.py,sha256=RNOlUXJyXojGoTe70XQ7Ua3F6vL9VEVZrcyuN4a559I,12448
3
+ docket/errors.py,sha256=gO8GBmKqmSNgAg-E5oT-oOyxztvp7V_6XG7OUTT15q0,546
4
+ docket/types.py,sha256=Hs1kUAG3WouD0popBN5bf1TsZiJ73ARUAKs4UOJG_Lo,1343
5
+ docket/api/__init__.py,sha256=zTSiG_ujSjAqWPyc435YXaX9XTlpMjiJWBbV-f-YtdA,45
6
+ docket/api/access/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
7
+ docket/api/access/add_principal.py,sha256=0V2QI_d_xmSOoOhIu2FOwbw6fS8LTprrR7z8ja1r1J4,5956
8
+ docket/api/access/archive_role_assignment.py,sha256=BD39Ur9el4_JFGFrlNEMn3s9oB9UbKcFWFOAc7dYfB0,4936
9
+ docket/api/access/create_api_token.py,sha256=f-s8Pcnx5kJVtZVN4Eu-RqgjnWJAyopgrEUX4NjieI8,6254
10
+ docket/api/access/create_application_principal.py,sha256=6xxqWrOuzKphkDnRxYvMWzetUd8JKdpdhq0wYBRz9I8,6269
11
+ docket/api/access/create_role_assignment.py,sha256=JaZaejO2jMhVYA0ucmcZKmWnKgGvy3ih0Lwj7yAc6aQ,5867
12
+ docket/api/access/list_api_tokens.py,sha256=F0Eptt9fOnSS8irVVC7gZtO1tJNYlaiZM4RIUOkTWN8,5058
13
+ docket/api/access/list_principals.py,sha256=F2oLioAk7-VTIqs8NKurRrSqGXw2GWhMhZo1yEJSPN0,5061
14
+ docket/api/access/list_role_assignments.py,sha256=kPrAR5C6T5ebxYZ-xaCEcV1djpkFxKV9tUmQ_45nFxY,5820
15
+ docket/api/access/revoke_api_token.py,sha256=SIHQfjJLPp-n9x3T6VKyOKT8I3OmZlImiKO3dGab79o,4421
16
+ docket/api/identity/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
17
+ docket/api/identity/create_my_api_token.py,sha256=dWdLfR-nEYRn1xxtEY8fUwbt5Ii1O2-xBtpmXuYNgU8,6847
18
+ docket/api/identity/get_me.py,sha256=qItA6ZkXxfILbvko32T58WqdRhWyRm5PN7IbRRu8aDs,3104
19
+ docket/api/identity/list_my_api_tokens.py,sha256=B8j8joE6grTSPAADxYxHvgxSsdE0Z-ZBOwkVfC6qaOc,4390
20
+ docket/api/identity/revoke_my_api_token.py,sha256=3s0G6EWu7jiNoGZbQQfr2roncH6kmuyfY0m09SqwT-4,4504
21
+ docket/api/recurring_acquisitions/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
22
+ docket/api/recurring_acquisitions/archive_recurring_acquisition.py,sha256=t8bbswk6iRhrqovmPw4cAZrER5ohmjYk83ZYXulQNhQ,6428
23
+ docket/api/recurring_acquisitions/create_recurring_acquisition.py,sha256=lKcQj1jBJ3oVPQLOMP5MVXk74awamfys4XlzY1_WTOM,7331
24
+ docket/api/recurring_acquisitions/get_recurring_acquisition.py,sha256=nMoV8muigj6nDCtVk-GiuUtz-aJKrCJog6w4_htny3w,4399
25
+ docket/api/recurring_acquisitions/list_recurring_acquisitions.py,sha256=wmUPvLjGSnYGH0HqSuRB8dmM4ygqHEWJZbYlk76iP3Y,7725
26
+ docket/api/recurring_acquisitions/preview_recurring_acquisition.py,sha256=sQlMa1vhbOs1A-UpoZrkseqoaoXOvRNq9otIiVPrKLE,6203
27
+ docket/api/recurring_acquisitions/preview_split_recurring_acquisition.py,sha256=GIOJVOxnE820Nl4p5VZDxbvKx70UKzWydnXA5992ahE,8139
28
+ docket/api/recurring_acquisitions/split_recurring_acquisition.py,sha256=CfBlD_gKhZ3LgcTEc5og5V7e-qUTFl0er7EY_AE1lcs,9495
29
+ docket/api/runs/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
30
+ docket/api/runs/get_run.py,sha256=53faiXYr8tilRQJFKoP5rywTaAWCt8eIqWdTfLpbwAM,3883
31
+ docket/api/runs/list_runs.py,sha256=nn5mSzYzaw0NFlH5Z2V7oEM4rgG8fmetrBchzLAPXDY,4816
32
+ docket/api/runs/report_run_outcome.py,sha256=sT5FbEfgty0XCBpryJ6rAiZQafn4laS7nZWYivDzE-A,5924
33
+ docket/api/scheduled_acquisitions/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
34
+ docket/api/scheduled_acquisitions/archive_scheduled_acquisition.py,sha256=QnXScKVPI-QyyjdcJfmSZK7P17pQRVYO0I1KgnySHkE,5980
35
+ docket/api/scheduled_acquisitions/create_scheduled_acquisition.py,sha256=Xx1l4UQ7pmTGBRrC8pyXz6dZcONyLoF-iBU14NBSb9s,5768
36
+ docket/api/scheduled_acquisitions/get_resolved_settings.py,sha256=m-8iO5kMagbBLvaIWbXnk8ASTd13n-1mfwOZFkTK7zE,4916
37
+ docket/api/scheduled_acquisitions/get_scheduled_acquisition.py,sha256=RT9Eh8rD9nVcbo1ryiMYgY8FBJG1LPs0E_Gl8QFrzas,4032
38
+ docket/api/scheduled_acquisitions/list_active_acquisitions.py,sha256=kZaqYp3qWTV5-wdQSbpwH96iRg43L20iTedx4FaOL90,10278
39
+ docket/api/scheduled_acquisitions/list_runs_for_scheduled_acquisition.py,sha256=tg737gKCQtylQoHom-cR3IOtG9FbiLfDi2kR1MHOqEU,4839
40
+ docket/api/scheduled_acquisitions/list_scheduled_acquisitions.py,sha256=lZjNxLV5x9VWoah-cv6U8KjhzwXoL3reYnbKDyJNDrk,11573
41
+ docket/api/scheduled_acquisitions/preview_scheduled_acquisition_edit.py,sha256=3f8eDve9jAR96Tn759RdShVn0r6_G5lhsmBOuUYZD_c,7461
42
+ docket/api/scheduled_acquisitions/set_planning_status.py,sha256=27ttxqH1zw7AR7mHuos182uhoLQkmThMOhBxGqtlDsQ,5662
43
+ docket/api/scheduled_acquisitions/start_run.py,sha256=RR56dJJaob-CXGbZTv5Sj_jxCUp-crRwP3o3wJQkrrU,6573
44
+ docket/api/scheduled_acquisitions/update_scheduled_acquisition.py,sha256=ZWwpi-nCZ6a0VRV1-lCHx9JpMElNGzbqBn6g6KDKxyI,7271
45
+ docket/api/settings/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
46
+ docket/api/settings/list_behavior_curriculum_discriminator_values.py,sha256=1oXG-R-s4AbXmmqs9SKeYta3kzdw-AMA4xmDBbmVuw0,5089
47
+ docket/api/settings/list_behavior_curriculum_settings.py,sha256=MWJJaIH09ID2qpfPm7onqCfAaiujdhCbbB9BDpfo_ks,5992
48
+ docket/api/settings/list_fip_discriminator_values.py,sha256=5ZGay9NnXHu_CmpkYFwXY3oeSfDO1jr7felcsYhrtSY,4993
49
+ docket/api/settings/list_fip_settings.py,sha256=1vZ2EDjLzmGklblCwcg0GLkKjZOa6jpbN8plpHMUSBg,5677
50
+ docket/api/settings/list_live_behavior_curriculum_settings.py,sha256=_NwGd0awOeQtaNOu9LeV0Qrw5EWf4_poHFwg227ms0Q,7435
51
+ docket/api/settings/list_live_fip_settings.py,sha256=A20CWkO8zh8dChyr8wTksKot2E8u9m_si2BUYJrhl54,7104
52
+ docket/api/settings/preview_behavior_curriculum_settings.py,sha256=22x4WsaYcRDF7vh346lrFi7Y88ko-mA2V80IiSaNLx8,6424
53
+ docket/api/settings/preview_fip_settings.py,sha256=zbUhqijlSXdc8yoZoeIvVDkd7HuWzrHFf4SXojtbMA8,5253
54
+ docket/api/settings/push_behavior_curriculum_settings.py,sha256=hBTaRR9o0d0QEj4fYUFjV4-oZgiOarEu79OJ-bGsjUc,6965
55
+ docket/api/settings/push_fip_settings.py,sha256=rgy9xQAchdkBp66akJcaPe7zO_bD7wQUM7rNOxdhiyY,6463
56
+ docket/api/templates/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
57
+ docket/api/templates/archive_template.py,sha256=U5MbBg3YFMQ2hSgx54oLAnYd7K7UG4A7jV8iYaqwbjs,5737
58
+ docket/api/templates/create_template.py,sha256=TTNOk1xqhYyT53v3C2KTBQIXBpdVP0lmTkyy9GyMnvw,6788
59
+ docket/api/templates/get_template.py,sha256=R8yirbGaixhv8XyEh65hkRARwffHMSqlKxvJKMN65HE,3862
60
+ docket/api/templates/list_templates.py,sha256=3ly9Sj04b1iDhDORQKcOXObvDKhSv4OXyYvjj_m_zqk,4618
61
+ docket/api/templates/update_template.py,sha256=2_oo3e8c6-1cfEkJ4Df-nOlUfauFkwKFBPr19tT3SI4,7908
62
+ docket/api/vocabulary/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
63
+ docket/api/vocabulary/list_instruments.py,sha256=yfan5XkiWFlg86y6KjbGgTL5JHo67JryusCC3ZevN7c,4115
64
+ docket/api/vocabulary/list_persons.py,sha256=5UrgYqJQbjmk9GS-tIhxjlzzipyDL1PJIHcmaSANNko,3408
65
+ docket/api/vocabulary/list_projects.py,sha256=etbT6RJGCQXvB1HVBNWjDzHROkTI3ZjE8UGAQxPCKmU,3422
66
+ docket/api/vocabulary/list_subjects.py,sha256=eyC1SjKYcFrz5Fs4pM55Tldmu2lX9C0KicL9J8lP1MI,3422
67
+ docket/api/vocabulary/lookup_person.py,sha256=MrV6jb4JCR6HtdVUPCyI9LrfSthyQGQhVBE5cZfd0to,4290
68
+ docket/api/vocabulary/lookup_subject.py,sha256=dexBxL65qaJ8JjLa5KbD7B710ZrZGHYhMq72rwt3Njc,4342
69
+ docket/api/vocabulary/sync_vocabulary.py,sha256=-1QdTclGJyYnkZuTre83Y6G2jKAQCc-VtHVijW3Ms5w,3891
70
+ docket/models/__init__.py,sha256=ikA3t_CDFT88dYDA6xTyR5UOPe-ggO0pQE0Diu3w3Kk,9478
71
+ docket/models/access_role.py,sha256=qWKVQ2cb3GbZFqLHv8LY9aRHp6SMZzGNmIni_G4JV0E,297
72
+ docket/models/access_role_nullable_type_1.py,sha256=aT8uRQANzPRRVyuwKKioVMWCY_quqkdtb3a9OiSDSfA,310
73
+ docket/models/access_role_nullable_type_2_type_1.py,sha256=KitsG4ftAYt-Zlo2HenR4qBryd8oVARrEer75JNN8bI,315
74
+ docket/models/access_role_nullable_type_3_type_1.py,sha256=T-ygFj-sizAjJaEUYIaGqWZJ1-61_oO7vnCwAJ8YMNo,315
75
+ docket/models/acquisition_variable.py,sha256=98P7L5RmvVC8ZFTJ1hvVNpW-2eKpbHIfzPlozHbjHvY,1783
76
+ docket/models/acquisition_warning.py,sha256=7GStpBEyFvcwMTyP-nmVxvxjIMvB4jbMyGOl62ltIkU,3931
77
+ docket/models/add_principal_request.py,sha256=jqHX5h3ZwycVSNx__D1lmHjRxFz3cLCqFQX1JR6I5lQ,2340
78
+ docket/models/api_token_response.py,sha256=u_cYyJ6OFRMr5vP66dCL4yXRXk98qF1pcAPRmzLUekA,9542
79
+ docket/models/api_token_status.py,sha256=3TPFDd6-dx4trrj_MXT0wndji5ZSBb6NLxCZHqErzVc,189
80
+ docket/models/archive_recurring_acquisition_request.py,sha256=du7-4MOkHjL29fHUNwIsKLJVIOcB3UC191mWG5zEYJQ,2455
81
+ docket/models/archive_recurring_acquisition_response.py,sha256=WyJqHwxM29sQq2Etp7ShKJQJ6ZOGSMgYExXTS7mtGRM,2702
82
+ docket/models/archive_scheduled_acquisition_request.py,sha256=8M86ZgewdA7yw8nIkzjDc4Q07XEx4mhyNTPZeFtDV8c,2497
83
+ docket/models/archive_template_request.py,sha256=ffEGatgrHqHVfQDDy4Bp68avubZ0k-0-vVu7xaTzOwc,1934
84
+ docket/models/auth_mode.py,sha256=aZgoSip5S0Ahnxt7sph2Yb3VPrF4EWfEGr0VdSin2NA,181
85
+ docket/models/behavior_curriculum_push_settings_request.py,sha256=vLp3nUKR7r7diBz_NGJm-fFZncKduZpsrTEpuJDLYMo,2698
86
+ docket/models/behavior_curriculum_settings.py,sha256=Muq0ge13FhD1O7hlApyQB2p3GGmYF_PU1JU8FLRqONA,1633
87
+ docket/models/behavior_curriculum_settings_preview_response.py,sha256=26l3Ir4IhTKBawoFmUEJBuCZ0DRA9yIS2A-tem2ih94,3552
88
+ docket/models/behavior_curriculum_settings_preview_response_promoted.py,sha256=gkhtsWxC_XWowP0z-z6uO6zMsQGQ5Y00u_74hkq3whc,1557
89
+ docket/models/behavior_curriculum_settings_version_response.py,sha256=3acFoeKKPUZj7tQvg8R25lUCtHlNowEBSVU4kUXUq4g,5603
90
+ docket/models/behavior_curriculum_settings_version_response_promoted.py,sha256=nd0IASNNwsUD-MZrezzK_NIeKEAJd2rjHQIGn2ui7r8,1557
91
+ docket/models/caller_kind.py,sha256=QJI--8_BxjmzKINVOuKr0Ev-XfpmuUpL0oplw_Poo7s,217
92
+ docket/models/create_api_token_request.py,sha256=OMYnr0mssMh2QTbnvLsul3C5f9Yyqy2ka-qeziG3E1I,2912
93
+ docket/models/create_application_principal_request.py,sha256=6iANl-qR7G3z9oq9-073CRkUv4oXBx2ouy9i8SGWvEg,1870
94
+ docket/models/create_personal_api_token_request.py,sha256=FLUyDfkXMFWnp6ipTeHyUfoBtQmegKHELSbZ0X8angc,5699
95
+ docket/models/create_recurring_acquisition_request.py,sha256=o7TMCMJLT-l5IarfJU4ivLCgRgK0sFLNIA9SxBX_k4I,10867
96
+ docket/models/create_role_assignment_request.py,sha256=DY2tfrE-aqKXTgRZCBoHUYVi8Jwuv42aOXf1C4WPPjo,3042
97
+ docket/models/create_scheduled_acquisition_request.py,sha256=M-0gaUxEaS8sj3jVCIEQDSY-zUoF3OvMw0gwe63u-a4,9976
98
+ docket/models/create_template_request.py,sha256=BP7APCY9I-7LeBU3UxVWStcnqqjMNfXq5qcFrzdEOi4,12311
99
+ docket/models/created_api_token_response.py,sha256=qhP14Mq_jjTrW1RXObQtHWsisF8ewicPRruHl4d8p9Q,2363
100
+ docket/models/effective_status.py,sha256=LCY7nDShbxcLx8tFXTEuNKnCWx9I1mfBQYVN1URV0EM,330
101
+ docket/models/fip_color.py,sha256=v5TziP1WWvSzKk_2LCWnpajJgcf358lTwQgLqnacKqo,233
102
+ docket/models/fip_fiber.py,sha256=bdOUByJdJXVq6wQnvD2c86vjZZE0UWXHFSkRMILmqGs,2662
103
+ docket/models/fip_mode.py,sha256=b2u56KhLkIQDwD4DYMLZ1UtGEsvKvzlj-NCXBy_iqTQ,158
104
+ docket/models/fip_push_settings_request.py,sha256=Q-3Ii8IOquRvhKnw80hkWBSMzP-bOjCoi2YulDMdNbk,2302
105
+ docket/models/fip_settings.py,sha256=KF6xTkgRrC_r25AdofwczmXgfD51iIggFTMpULbki90,2413
106
+ docket/models/fip_settings_preview_response.py,sha256=UnxT6Cad4kDRkXXbcoZuGkFBk6XIuHz80gSpSpWLhr8,3001
107
+ docket/models/fip_settings_preview_response_promoted.py,sha256=Mc3fNZmF3d1Ogzs-2LsJ0q9P1v5kGn_RYDSbA4xiMEc,1479
108
+ docket/models/fip_settings_version_response.py,sha256=gIsDkTmVj25yM6HtfiR6dO5b1TMj9KuuWRFVgGwP9Ok,5052
109
+ docket/models/fip_settings_version_response_promoted.py,sha256=V-HtGVdxV75wkmNa0O9NzT90_OufZh-pPT3A_z7s9BE,1479
110
+ docket/models/future_occurrences.py,sha256=p4Y_QH32uvZ9V_0ttao6PsCb0IBFZOyr-0bnvyy-pSs,164
111
+ docket/models/get_resolved_settings_response_200.py,sha256=HyRstSONqyLneSdRdTKl0vBkUvhm9RdHbr_atlH_MhA,1999
112
+ docket/models/held_role_response.py,sha256=uCYqsiFfdXovuvznLSXMUkhfnGLgbqtza3gttoi8D_g,3408
113
+ docket/models/http_validation_problem_details.py,sha256=g4rZwOvp8pa-jT5ebo6_XHbI_Z7b2MLHyVDFlw_eOwg,6260
114
+ docket/models/http_validation_problem_details_errors.py,sha256=gqdYs_dHGp2V4RTkmfrXaqHYXJWkDDaL7GfjH-8LOl4,1769
115
+ docket/models/instrument_response.py,sha256=qLRqPvnDbZNSsuC-NnHEhWJv_qAa9S_P5BQK-kx1clQ,2282
116
+ docket/models/kept_occurrence.py,sha256=1z1J_A9zsdsJ66nRtNrni_jwXWztXpd99akl_e-C6q4,2669
117
+ docket/models/kept_occurrence_reason.py,sha256=DcIT5qbnanx0mKdzH5WHNCg0M4Gq3qN1W6SIoxIJnvQ,195
118
+ docket/models/list_active_acquisitions_effective_status_item.py,sha256=NLWnHJHcXjc0WqmOrD4FZPxGaIlkQDbuQIeIzzfQW28,356
119
+ docket/models/list_scheduled_acquisitions_planning_status.py,sha256=Rk1gkFHn3fYJnXjY1OmgnJXifQod_pciDjQOFMiBF68,250
120
+ docket/models/me_caller.py,sha256=CqzynuWxH7ki4hYVK9eZRddMsIxo39bK5x3063dmh5E,3509
121
+ docket/models/me_permission.py,sha256=r2jCTdEY34BS_iEO8x72Y0a3ZaRdK4ZsDZ1fpuF7Vs8,2701
122
+ docket/models/me_response.py,sha256=DTWgekrV0e4-CnKhN2Ar8a9akQoElj4rJ8ICOK-GNAA,5449
123
+ docket/models/me_role.py,sha256=UFfRzzVjFP4jkFrGzj5gZSq8xrF-ppdXjyUOl7RJDvA,1924
124
+ docket/models/occurrence_preview.py,sha256=VQn-aAx_mvmnGR-MEm5bGetBFXe0qPxNuWicIYLf37o,4175
125
+ docket/models/occurrence_summary.py,sha256=cuA0i3EiMnD5Is-uspzGWJ8Y2e_yZPSQQxk8qeUayfY,4203
126
+ docket/models/occurrence_warnings.py,sha256=C02Rf66Q6riToYlEJuNaqpMUhPewGybOwudHcbuzkTk,2715
127
+ docket/models/permission_action.py,sha256=aJliPOYJpeVhjQ_10AwnLUw34KMhxIdWnmphQFUGm3A,231
128
+ docket/models/person_assignment.py,sha256=_ME39Pb4YiolHyhursEqY01BYjKRPGcYLccXyY6mSAc,1889
129
+ docket/models/person_lookup_response.py,sha256=YDTbbL2sTI8LCc-TGb_g_3RC2D14fjx0oo71BvvLHoY,3779
130
+ docket/models/person_response.py,sha256=s15QvZD3wiJ8Qpf1X5cU4pF7108qvOxLrE-oK_-m-Co,2720
131
+ docket/models/person_role.py,sha256=NEWl-WLFLd7-BmQ9XBYi12Ng_zEDZXslYv2z4moUZ00,195
132
+ docket/models/personal_token_limits.py,sha256=HxNh_CInW5HHR8tJ6CekYBzwPnnmxckLrltYhhIVa0k,3012
133
+ docket/models/planning_status.py,sha256=K7dMJZYMcermMfWv8EljW_HUt4_j6eAWWaT1zQBIA4w,225
134
+ docket/models/principal_kind.py,sha256=x9X2HbMcpso8N3eW-BF2TXhT7bgVj3ynAAwPhPABCBs,172
135
+ docket/models/principal_response.py,sha256=MprsDZxFltiC8-4WTsxjdBtxD77ifUfuNTJ6cZ8yk_M,7789
136
+ docket/models/problem_details.py,sha256=anILAvUU2JQl-0CxqRH1TN_uAXO-FUC-WRFArJuNi9Y,5189
137
+ docket/models/project_response.py,sha256=0U-MWzYYOkm9Eu6q46949IW3rWKKdancep9d55pfOP8,1921
138
+ docket/models/recurrence_exception_kind.py,sha256=-TG6BR8dFtsR1juQlCeKCNnXM3wZENXIJaCZsJ1jh9U,362
139
+ docket/models/recurrence_exception_response.py,sha256=jkhSTHjOM9-zgdfV5bwvvlcMWWPfhjnGMxBpt5zMTmM,3456
140
+ docket/models/recurrence_frequency.py,sha256=EJd18ujrVqlb3IsHFQr9Q961yj1frw0dZcOpV-Tzp5E,166
141
+ docket/models/recurrence_preview_response.py,sha256=Jm-2oAsmMB8_8Lzto_3HCX-_VvRSMcReVbiH2ol34rI,3204
142
+ docket/models/recurrence_rule.py,sha256=yAJCN9w7ecdshyoZ_G2M3ksj5xLvs5ZO6qSiejOiJ1s,7148
143
+ docket/models/recurring_acquisition_created_response.py,sha256=ZnduO3MXjs3ZO_52fPLb2XpizD6RgUNgYR6f1k_n6-I,4309
144
+ docket/models/recurring_acquisition_detail_response.py,sha256=NuN4q--s_5LbVQQdir79TdL4DYxTvD3WVDDpQJN77Q0,3701
145
+ docket/models/recurring_acquisition_response.py,sha256=_ELOHRgOtvb0N5ke4yPGiX9MvuC64F-WrBM9DfDVdyU,11562
146
+ docket/models/report_run_outcome_request.py,sha256=4Ge2y05BbiI4Os_9rrWHlszBt24zvt9GqhzapH4DecE,2569
147
+ docket/models/resolution_mode.py,sha256=UnI3saqdfq65xsxxT6ytVG6vGLYpRPuaYTXTFA9AbcA,209
148
+ docket/models/resolved_settings.py,sha256=YHfHzcMfVKQ0Nn_40iCSGyJlYYDTPfa-A24RYJiBKco,1875
149
+ docket/models/role_assignment_response.py,sha256=GSruhGF7gkX--pdXUGInlXF36x0X7SK80PwujdSe4bY,5147
150
+ docket/models/role_origin.py,sha256=VCtrRpLcewjY1D1Gt-iUjBaAFz_bVPCkF58sWbvOSgs,197
151
+ docket/models/role_source_kind.py,sha256=9Bh6S1oIkOJj7kUXef0kBTBFI3YmKk3jvVioidHanSM,201
152
+ docket/models/run_origin.py,sha256=ABR3EFipFwRyHHcZ2ZXzmUvpsPKQ9J3AKEXrh5tJk2E,156
153
+ docket/models/run_outcome.py,sha256=S8Sxa4vCtTulOJuNeZNE6vyBW-Qz3W3fWr1wEky8HWI,167
154
+ docket/models/run_response.py,sha256=69X3Rh6Oy6GOBxDFoGQ9Irvg2MBlhzBTOZGVndxYpfY,5595
155
+ docket/models/run_settings_snapshot.py,sha256=v1PBssFrIXv2gXLXjr_0jmkn1N3dcA6GxBkjjYQ-9T8,1985
156
+ docket/models/run_start_response.py,sha256=BIe3EuTozc589o4z7uikV_yNljeBARHvVhpTcpMv2k4,2520
157
+ docket/models/run_start_response_settings.py,sha256=rYYsMBeQDO85xBvAlW9qw9-FwIm5kq4lP1-lYN02MZE,2028
158
+ docket/models/run_status.py,sha256=idt5-R9CD0jZg0ho-VyE0z_6grXjBbno9ZSR4PjPGRE,218
159
+ docket/models/scheduled_acquisition_edit_preview_response.py,sha256=srSR1v4tIyzOZQUgruh80sGrq1tB2tVvTkB8F-QipVk,5323
160
+ docket/models/scheduled_acquisition_response.py,sha256=u4gCN_0BA-FGHEbzbKRG-Aq6hoARAHKQwE1AJaFDPTk,13568
161
+ docket/models/set_planning_status_request.py,sha256=vj30lagVdhJVs_pupaG36QfVHKQwHpEh-Kb4G4otomM,2963
162
+ docket/models/settings_selector.py,sha256=bqX5Vxra5RUfGQXU-8dpHKBnb_caaYeIfknwu5x6aQ0,4900
163
+ docket/models/skipped_occurrence.py,sha256=RgP4qGkytpONsppYkQYGRleAuvJ9-BOK-NwnLKBmUfk,2538
164
+ docket/models/split_preview_response.py,sha256=YSyvPbD_kI1xZSas3o5OBY0r7mTZ_VgBRL8eaRQpk7o,4229
165
+ docket/models/split_recurring_acquisition_request.py,sha256=4jS_pfXJCeui7nXg7KLHpTMTf6VoSrESu14zmr6c-ho,10045
166
+ docket/models/split_recurring_acquisition_response.py,sha256=1FzZmqRQSC5-PkDZPBdRY_0zqLMLQpC2PSTxGcyCtqg,5640
167
+ docket/models/start_run_request.py,sha256=3lwwvlENoZp0o-U4QwEA2JfPTUxn5o0qwm03HisS1sE,2078
168
+ docket/models/subject_lookup_response.py,sha256=FMVOdZMIaCo55YpsWHpbb5c7UyUo8ObvTClyD8pN-QA,4494
169
+ docket/models/subject_response.py,sha256=iExW1E7fgMzigEinUFoaSvIxRiQCNXEbRfCHhRJsvKk,3684
170
+ docket/models/sync_counts.py,sha256=MYD5dQyyTeBc0Dwv-99pM3My_aDVqGF1NfIj8c22Au0,1943
171
+ docket/models/sync_response.py,sha256=Ocn-RWEIJwfnFiPnE2MN-q0YmHKAN3BSfAJtxy38w04,2100
172
+ docket/models/template_response.py,sha256=9rxRqK44AXY9NeSTDy8EGw8djJL0jWmhrGK5Un-WuFw,9966
173
+ docket/models/update_scheduled_acquisition_request.py,sha256=IUgkJOeP5nKDsOcfQj7ZW5wQyJMeOf-g4m9T-OSIpcI,9333
174
+ docket/models/update_template_request.py,sha256=kgUYLx_rUVss9OyAgcKenehi-PRIcQ_a7ZeygraFr-s,10653
175
+ docket/models/weekday.py,sha256=ynDKgQZbEeeJU3f6AAzURIxz4ILkuebmq6UFD9R68ms,282
176
+ docket_auth/__init__.py,sha256=T28BUSFiljQsQR8oOK2UxLJHCirg5D9zK6zCCdhT4R8,9166
177
+ docket_mcp/__init__.py,sha256=pOSC3KZ_hkFb0VW4QDDpkGa7lpUPGEMlUUmDd8HCwsg,368
178
+ docket_mcp/api.py,sha256=5eDiTC_lJJGKI02PQ_J1RytdltfllVSN9R93dXK3RE0,8483
179
+ docket_mcp/config.py,sha256=aKS_dc5-r9AeMzbgjHtYiFzBtH8ZTEb-7QsXqhXXpuw,2005
180
+ docket_mcp/server.py,sha256=nqgvV_mWkuDBwe8ORH54PxyHZhLjGtAqpA3yJgHCfh8,2563
181
+ docket_mcp/signin.py,sha256=lwFZ4lodUnaqOWg6ivsWeZVpzdHQD1mr8dwnDIZYb6c,5684
182
+ docket_mcp/slots.py,sha256=SUzQ6vXdgDH_6lwX9T6SMvRV-xo3i62X-oU76MDPNp0,2779
183
+ docket_mcp/times.py,sha256=HpoIaJ3uihwfY0oo3OBk5CJJzuRzCioDULJcXB9fl1E,5820
184
+ docket_mcp/tools.py,sha256=Z4L6WbTS5FlJYFvWVK3IrOXAgADeYqdwtHV4aKnIT60,52360
185
+ docket_client-0.3.2.dist-info/METADATA,sha256=xfL1wU9NPHXyUTYJFfCyoInY2IUBoHEbDdUdMKdbPoQ,10352
186
+ docket_client-0.3.2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
187
+ docket_client-0.3.2.dist-info/entry_points.txt,sha256=Wh6bZ_A_jc7MClLXlPaufhYtoYMGMLmTMC7ynpolbxk,54
188
+ docket_client-0.3.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ docket-mcp = docket_mcp.server:main
docket_mcp/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ """A local MCP server for Docket (console script ``docket-mcp``, install ``docket-client[mcp]``).
2
+
3
+ Hand-written, a sibling of ``docket_auth``; ``client/docket/`` is generated and never edited.
4
+ It speaks MCP over stdio and calls the Docket API through the generated client, so nothing new
5
+ is hosted and the institute network is reached from the user's own machine.
6
+ """
docket_mcp/api.py ADDED
@@ -0,0 +1,207 @@
1
+ """The HTTP layer: the generated client's connections, token handling and error mapping.
2
+
3
+ Reads go through an anonymous `docket.Client`; only writes use the token-carrying
4
+ [`docket.AuthenticatedClient`][docket.client.AuthenticatedClient] (from ``docket_auth``), mirroring the frontend. ``/api/v1/me``
5
+ is read once to learn ``auth_mode``: when it is ``disabled`` no token is ever requested and
6
+ sign-in is never prompted. Responses stay plain JSON so tools can reshape them for a model.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Any
12
+
13
+ import httpx
14
+ from docket import Client
15
+ from docket_auth import AuthenticationError, TokenProvider, authenticated_client
16
+
17
+ from .config import Settings
18
+ from .signin import SignInRequired, build_provider, non_interactive_token
19
+
20
+ __all__ = ["DocketApi", "DocketToolError"]
21
+
22
+ TOKEN_HELP = "Set DOCKET_API_TOKEN (ask an admin for a token from Settings > Access)."
23
+
24
+
25
+ class DocketToolError(Exception):
26
+ """A failure to report to the model as the tool's error text (never carries a token)."""
27
+
28
+
29
+ class DocketApi:
30
+ def __init__(
31
+ self,
32
+ settings: Settings,
33
+ *,
34
+ transport: httpx.BaseTransport | None = None,
35
+ token_provider: TokenProvider | None = None,
36
+ ) -> None:
37
+ self.settings = settings
38
+ extra: dict[str, Any] = {"transport": transport} if transport else {}
39
+ timeout = httpx.Timeout(30.0)
40
+ self._anonymous = Client(base_url=settings.api_url, timeout=timeout, httpx_args=extra)
41
+ self._provider = token_provider or build_provider(settings)
42
+ self._authed = (
43
+ authenticated_client(
44
+ settings.api_url, self._provider, timeout=timeout, httpx_args=dict(extra)
45
+ )
46
+ if self._provider
47
+ else None
48
+ )
49
+ self._me: dict[str, Any] | None = None
50
+
51
+ # -- reads (never carry a token) -------------------------------------------------------------
52
+
53
+ def get(self, path: str, *, what: str = "this", **params: Any) -> Any:
54
+ query = {k: v for k, v in params.items() if v is not None}
55
+ return self._send(self._anonymous, "GET", path, what, "read", params=query)
56
+
57
+ def me(self) -> dict[str, Any]:
58
+ if self._me is None:
59
+ self._me = self.get("/api/v1/me", what="the caller")
60
+ assert self._me is not None
61
+ return self._me
62
+
63
+ def me_as_caller(self) -> tuple[dict[str, Any], bool]:
64
+ """``/me`` with the caller's own credential when one is available without interaction.
65
+
66
+ Returns ``(me, signed_in)``. An API token, client credentials or a warm msal cache are
67
+ used; a device-code sign-in is never started here. Falls back to the anonymous view.
68
+ """
69
+ anonymous = self.me()
70
+ if (
71
+ anonymous.get("auth_mode") == "disabled"
72
+ or self._provider is None
73
+ or self._authed is None
74
+ ):
75
+ return anonymous, False
76
+ if non_interactive_token(self._provider) is None:
77
+ return anonymous, False
78
+ try:
79
+ return self._send(self._authed, "GET", "/api/v1/me", "the caller", "read"), True
80
+ except DocketToolError:
81
+ return anonymous, False # rejected or unreachable: show the anonymous view
82
+
83
+ @property
84
+ def auth_mode(self) -> str:
85
+ return str(self.me().get("auth_mode", "disabled"))
86
+
87
+ # -- writes (carry a token unless the server has auth disabled) ------------------------------
88
+
89
+ def post(
90
+ self,
91
+ path: str,
92
+ body: Any = None,
93
+ *,
94
+ action: str,
95
+ idempotency_key: str | None = None,
96
+ **params: Any,
97
+ ) -> Any:
98
+ headers = {"Idempotency-Key": idempotency_key} if idempotency_key else None
99
+ return self._write("POST", path, body, action, headers, params)
100
+
101
+ def patch(self, path: str, body: Any, *, action: str) -> Any:
102
+ return self._write("PATCH", path, body, action, None, {})
103
+
104
+ def preview(self, path: str, body: Any = None) -> Any:
105
+ """A server preview endpoint: it writes nothing, so it carries no token."""
106
+ return self._send(self._anonymous, "POST", path, "this", "preview", json=body)
107
+
108
+ def _write(
109
+ self,
110
+ method: str,
111
+ path: str,
112
+ body: Any,
113
+ action: str,
114
+ headers: dict[str, str] | None,
115
+ params: dict[str, Any],
116
+ ) -> Any:
117
+ client = self._anonymous if self.auth_mode == "disabled" else self._credentialed()
118
+ query = {k: v for k, v in params.items() if v is not None}
119
+ return self._send(
120
+ client, method, path, "this", action, json=body, headers=headers, params=query
121
+ )
122
+
123
+ def _credentialed(self) -> Client:
124
+ if self._authed is None or self._provider is None:
125
+ if self.auth_mode == "tokens":
126
+ raise DocketToolError(TOKEN_HELP)
127
+ raise DocketToolError(
128
+ "This Docket needs a signed-in caller for changes. "
129
+ f"{TOKEN_HELP} Or sign in as yourself: set DOCKET_AUTH_CLIENT_ID, DOCKET_AUTH_SCOPE "
130
+ "and DOCKET_AUTH_TENANT_ID (or DOCKET_AUTH_AUTHORITY)."
131
+ )
132
+ return self._authed # type: ignore[return-value]
133
+
134
+ # -- plumbing --------------------------------------------------------------------------------
135
+
136
+ def _send(
137
+ self, client: Any, method: str, path: str, what: str, action: str, **kwargs: Any
138
+ ) -> Any:
139
+ try:
140
+ response = client.get_httpx_client().request(method, path, **kwargs)
141
+ except SignInRequired as error:
142
+ raise DocketToolError(str(error)) from None
143
+ except AuthenticationError as error:
144
+ raise DocketToolError(f"Could not get a token: {error}") from None
145
+ except httpx.TimeoutException:
146
+ raise DocketToolError(
147
+ f"Docket at {self.settings.api_url} did not answer in time."
148
+ ) from None
149
+ except httpx.HTTPError as error:
150
+ raise DocketToolError(
151
+ f"Cannot reach Docket at {self.settings.api_url} ({type(error).__name__}). "
152
+ "Is the server running, and are you on the VPN? Check DOCKET_API_URL."
153
+ ) from None
154
+ if response.status_code >= 400:
155
+ raise _problem(response, action)
156
+ if not response.content:
157
+ return None
158
+ return response.json()
159
+
160
+
161
+ def _problem(response: httpx.Response, action: str) -> DocketToolError:
162
+ """Map an RFC 9457 problem response to a message the model can act on."""
163
+ detail = ""
164
+ code = ""
165
+ errors: Any = None
166
+ try:
167
+ body = response.json()
168
+ detail = str(body.get("detail") or body.get("title") or "")
169
+ code = str(body.get("code") or "")
170
+ errors = body.get("errors")
171
+ except ValueError:
172
+ detail = response.text[:200]
173
+ status = response.status_code
174
+ suffix = f" ({detail})" if detail else ""
175
+ if status == 401:
176
+ return DocketToolError(
177
+ f"Not signed in, or the credential was rejected{suffix}. "
178
+ "If you use an API token it may be revoked or expired: "
179
+ "ask an admin for a new one from Settings > Access."
180
+ )
181
+ if status == 403:
182
+ return DocketToolError(
183
+ f"You are not allowed to {action}{suffix}. "
184
+ "Sessions can usually only be changed by their creator, a schedule maintainer or an admin."
185
+ )
186
+ if status == 404:
187
+ return DocketToolError(f"Not found{suffix}. Check the id and try again.")
188
+ if status == 409:
189
+ return DocketToolError(
190
+ f"This changed since your preview, or conflicts with another change{suffix}. "
191
+ "Preview again (dry_run=true), show the user, and confirm that one."
192
+ )
193
+ if status in (400, 422):
194
+ fields = ""
195
+ if isinstance(errors, dict) and errors:
196
+ fields = " Fields: " + "; ".join(
197
+ f"{key}: {', '.join(map(str, value)) if isinstance(value, list) else value}"
198
+ for key, value in errors.items()
199
+ )
200
+ return DocketToolError(f"The server rejected the request{suffix}.{fields}")
201
+ if status == 429:
202
+ return DocketToolError(f"Too many requests{suffix}; wait a moment and retry.")
203
+ if status == 502 or status == 503 or code == "upstream_unavailable":
204
+ return DocketToolError(
205
+ f"Docket could not reach an upstream service{suffix}. Try again later."
206
+ )
207
+ return DocketToolError(f"Docket returned an unexpected error {status}{suffix}.")