Coverage for src / documint_mcp / models.py: 0%

357 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-30 22:30 -0400

1"""Typed models for the Documint control plane, drift engine, and publish workflows.""" 

2 

3from __future__ import annotations 

4 

5from datetime import datetime 

6from enum import StrEnum 

7from typing import Any 

8 

9from pydantic import BaseModel, Field 

10 

11 

12class ArtifactType(StrEnum): 

13 API_REFERENCE = "api_reference" 

14 SDK_GUIDES = "sdk_guides" 

15 MCP_REFERENCE = "mcp_reference" 

16 CHANGELOG = "changelog" 

17 MIGRATION_NOTES = "migration_notes" 

18 

19 

20class SourceSignalType(StrEnum): 

21 MANUAL = "manual" 

22 PUSH = "push" 

23 PULL_REQUEST = "pull_request" 

24 RELEASE = "release" 

25 

26 

27class FindingSeverity(StrEnum): 

28 HIGH = "high" 

29 MEDIUM = "medium" 

30 LOW = "low" 

31 

32 

33class JobStatus(StrEnum): 

34 PENDING = "pending" 

35 RUNNING = "running" 

36 COMPLETED = "completed" 

37 FAILED = "failed" 

38 

39 

40class VerificationStatus(StrEnum): 

41 VERIFIED = "verified" 

42 STALE = "stale" 

43 MISSING = "missing" 

44 

45 

46class RepositoryRevision(BaseModel): 

47 ref: str 

48 touched_at: datetime 

49 committed: bool = True 

50 

51 

52class User(BaseModel): 

53 id: str 

54 external_id: str | None = None 

55 email: str | None = None 

56 name: str 

57 provider: str 

58 created_at: datetime 

59 

60 

61class Workspace(BaseModel): 

62 id: str 

63 slug: str 

64 name: str 

65 description: str = "" 

66 created_at: datetime 

67 

68 

69class WorkspaceMember(BaseModel): 

70 id: str 

71 workspace_id: str 

72 user_id: str 

73 role: str 

74 created_at: datetime 

75 

76 

77class ApiTokenSummary(BaseModel): 

78 id: str 

79 workspace_id: str 

80 user_id: str 

81 label: str 

82 token_prefix: str 

83 scopes: list[str] = Field(default_factory=list) 

84 created_at: datetime 

85 last_used_at: datetime | None = None 

86 revoked_at: datetime | None = None 

87 token: str | None = None 

88 

89 

90class GitHubInstallation(BaseModel): 

91 id: str 

92 workspace_id: str 

93 installation_id: str | None = None 

94 account_login: str | None = None 

95 account_type: str | None = None 

96 repository_selection: str = "selected" 

97 metadata_json: dict[str, object] = Field(default_factory=dict) 

98 created_at: datetime 

99 updated_at: datetime 

100 

101 

102class GitHubRepository(BaseModel): 

103 id: str 

104 github_installation_id: str 

105 repository_id: str | None = None 

106 full_name: str 

107 owner: str 

108 name: str 

109 default_branch: str 

110 visibility: str = "private" 

111 is_private: bool = True 

112 is_archived: bool = False 

113 metadata_json: dict[str, object] = Field(default_factory=dict) 

114 created_at: datetime 

115 updated_at: datetime 

116 

117 

118class RepositorySource(BaseModel): 

119 id: str 

120 project_id: str | None = None 

121 provider: str = "github" 

122 owner: str 

123 repo: str 

124 default_branch: str 

125 local_path: str 

126 current_ref: str 

127 docs_root: str 

128 installation_id: str | None = None 

129 

130 

131class ProjectSettings(BaseModel): 

132 id: str 

133 project_id: str 

134 docs_root: str 

135 config_version: int = 1 

136 config_json: dict[str, object] = Field(default_factory=dict) 

137 ai_policy: dict[str, object] = Field(default_factory=dict) 

138 publish_behavior: dict[str, object] = Field(default_factory=dict) 

139 pr_behavior: dict[str, object] = Field(default_factory=dict) 

140 updated_at: datetime 

141 

142 

143class Project(BaseModel): 

144 id: str 

145 workspace_id: str | None = None 

146 github_installation_id: str | None = None 

147 name: str 

148 slug: str 

149 description: str 

150 public_url: str 

151 dashboard_url: str 

152 onboarding_status: str = "connected" 

153 source: RepositorySource 

154 artifact_types: list[ArtifactType] 

155 

156 

157class RuntimeStatus(BaseModel): 

158 environment: str 

159 deployment_provider: str 

160 job_execution_mode: str 

161 api_base_url: str 

162 public_base_url: str 

163 app_base_url: str 

164 repo_root: str 

165 docs_root: str 

166 git_available: bool 

167 git_metadata_available: bool 

168 current_ref: str 

169 current_ref_source: str 

170 auth_required: bool 

171 github_app_ready: bool 

172 deploy_branch: str | None = None 

173 database_configured: bool = True 

174 clerk_configured: bool = False 

175 huggingface_configured: bool = False 

176 

177 

178class SourceSignal(BaseModel): 

179 id: str | None = None 

180 type: SourceSignalType 

181 ref: str 

182 changed_files: list[str] = Field(default_factory=list) 

183 created_at: datetime 

184 

185 

186class ArtifactTrace(BaseModel): 

187 id: str 

188 slug: str 

189 title: str 

190 artifact_type: ArtifactType 

191 summary: str 

192 doc_paths: list[str] 

193 source_paths: list[str] 

194 latest_source_revision: RepositoryRevision | None = None 

195 latest_doc_revision: RepositoryRevision | None = None 

196 verification_status: VerificationStatus 

197 

198 

199class ArtifactDefinition(BaseModel): 

200 id: str 

201 project_id: str 

202 artifact_key: str 

203 slug: str 

204 title: str 

205 artifact_type: ArtifactType 

206 summary: str 

207 doc_paths: list[str] 

208 source_patterns: list[str] 

209 

210 

211class DriftFinding(BaseModel): 

212 id: str 

213 project_id: str | None = None 

214 verification_run_id: str | None = None 

215 artifact_id: str 

216 artifact_type: ArtifactType 

217 severity: FindingSeverity 

218 summary: str 

219 rationale: str 

220 source_paths: list[str] 

221 doc_paths: list[str] 

222 suggested_actions: list[str] 

223 source_revision: RepositoryRevision | None = None 

224 doc_revision: RepositoryRevision | None = None 

225 status: str = "open" 

226 created_at: datetime | None = None 

227 updated_at: datetime | None = None 

228 changed_symbols: list[dict] = Field(default_factory=list) 

229 symbol_hash: str | None = None 

230 confidence_score: float = 0.5 

231 has_breaking_changes: bool = False 

232 cross_artifact_refs: dict[str, list[str]] = Field(default_factory=dict) 

233 """Maps artifact_id -> [symbol_names] for OTHER artifacts affected by the same symbol changes.""" 

234 

235 

236class AgentRun(BaseModel): 

237 id: str 

238 project_id: str 

239 kind: str 

240 provider: str 

241 model: str | None = None 

242 status: str 

243 input_summary: str 

244 output_summary: str 

245 metadata_json: dict[str, object] = Field(default_factory=dict) 

246 created_at: datetime 

247 completed_at: datetime | None = None 

248 

249 

250class PatchCitation(BaseModel): 

251 path: str 

252 ref: str 

253 note: str 

254 

255 

256class DocPatch(BaseModel): 

257 id: str 

258 project_id: str | None = None 

259 finding_id: str | None = None 

260 artifact_id: str 

261 target_path: str 

262 summary: str 

263 rationale: str = "" 

264 proposed_sections: list[str] 

265 citations: list[PatchCitation] = Field(default_factory=list) 

266 preview_markdown: str 

267 ai_provider: str = "deterministic" 

268 model_name: str | None = None 

269 chain_steps_used: int | None = None 

270 confidence_score: float | None = None 

271 status: str = "draft" 

272 created_at: datetime | None = None 

273 updated_at: datetime | None = None 

274 

275 

276class PullRequestRecord(BaseModel): 

277 id: str 

278 project_id: str 

279 patch_id: str 

280 branch_name: str 

281 title: str 

282 url: str 

283 state: str 

284 created_at: datetime 

285 updated_at: datetime 

286 

287 

288class VerificationRun(BaseModel): 

289 id: str 

290 project_id: str 

291 status: JobStatus 

292 signal: SourceSignal 

293 findings_count: int 

294 findings: list[DriftFinding] = Field(default_factory=list) 

295 started_at: datetime 

296 completed_at: datetime | None = None 

297 

298 

299class PublishDeployment(BaseModel): 

300 id: str 

301 project_id: str 

302 status: JobStatus 

303 commit_ref: str 

304 site_url: str 

305 preview_url: str 

306 docs_count: int 

307 generated_at: datetime 

308 

309 

310class PublishedPage(BaseModel): 

311 id: str 

312 project_id: str 

313 deployment_id: str 

314 workspace_slug: str 

315 project_slug: str 

316 path: str 

317 title: str 

318 description: str 

319 content_markdown: str 

320 search_body: str 

321 source_path: str 

322 created_at: datetime 

323 updated_at: datetime 

324 

325 

326class ActivityEvent(BaseModel): 

327 id: str 

328 workspace_id: str 

329 project_id: str | None = None 

330 kind: str 

331 title: str 

332 body: str 

333 metadata_json: dict[str, object] = Field(default_factory=dict) 

334 created_at: datetime 

335 

336 

337class PublicDocPage(BaseModel): 

338 workspace_slug: str 

339 project_slug: str 

340 path: str 

341 title: str 

342 description: str 

343 content_markdown: str 

344 source_path: str 

345 deployment_id: str 

346 

347 

348class ProjectSnapshot(BaseModel): 

349 project: Project 

350 workspace: Workspace | None = None 

351 settings: ProjectSettings | None = None 

352 runtime: RuntimeStatus 

353 artifacts: list[ArtifactTrace] 

354 latest_run: VerificationRun | None = None 

355 latest_deployment: PublishDeployment | None = None 

356 findings: list[DriftFinding] = Field(default_factory=list) 

357 pull_requests: list[PullRequestRecord] = Field(default_factory=list) 

358 activity: list[ActivityEvent] = Field(default_factory=list) 

359 

360 

361class WorkspaceCreateRequest(BaseModel): 

362 name: str 

363 slug: str | None = None 

364 description: str = "" 

365 

366 

367class ProjectCreateRequest(BaseModel): 

368 workspace_id: str 

369 name: str 

370 slug: str | None = None 

371 description: str = "" 

372 owner: str 

373 repo: str 

374 default_branch: str = "main" 

375 installation_id: str | None = None 

376 local_path: str | None = None 

377 

378 

379class DriftJobRequest(BaseModel): 

380 project_id: str 

381 signal_type: SourceSignalType = SourceSignalType.MANUAL 

382 changed_files: list[str] | None = None 

383 

384 

385class PublishRequest(BaseModel): 

386 project_id: str 

387 

388 

389class QueuedJob(BaseModel): 

390 job_id: str 

391 job_kind: str 

392 project_id: str | None = None 

393 workspace_id: str | None = None 

394 status: JobStatus = JobStatus.PENDING 

395 attempt_count: int = 0 

396 error_summary: str | None = None 

397 resource_type: str | None = None 

398 resource_id: str | None = None 

399 result_summary: str | None = None 

400 site_url: str | None = None 

401 created_at: datetime | None = None 

402 started_at: datetime | None = None 

403 completed_at: datetime | None = None 

404 updated_at: datetime | None = None 

405 

406 

407class PatchCreateRequest(BaseModel): 

408 policy: str = "on_demand" 

409 

410 

411class PullRequestCreateRequest(BaseModel): 

412 title: str | None = None 

413 

414 

415class TokenCreateRequest(BaseModel): 

416 workspace_id: str = "" 

417 label: str = "CLI token" 

418 scopes: list[str] = Field( 

419 default_factory=lambda: ["projects:read", "projects:write"] 

420 ) 

421 

422 

423class CLIExchangeRequest(BaseModel): 

424 workspace_id: str 

425 label: str = "CLI token" 

426 scopes: list[str] = Field( 

427 default_factory=lambda: ["projects:read", "projects:write"] 

428 ) 

429 

430 

431class RevalidateRequest(BaseModel): 

432 project_id: str 

433 deployment_id: str | None = None 

434 

435 

436class AuthenticatedUser(BaseModel): 

437 user: User 

438 workspaces: list[Workspace] 

439 

440 

441class MCPTool(BaseModel): 

442 name: str 

443 description: str 

444 input_schema: dict[str, Any] 

445 

446 

447class MCPRequest(BaseModel): 

448 jsonrpc: str = "2.0" 

449 id: str | int | None = None 

450 method: str 

451 params: dict[str, Any] = Field(default_factory=dict)