musehub_context.py
python
sha256:3ff9c9863a9891bdcde71b4a43228f66d0493e38b7cc1d09fe9eb7de774046b2
feat: add repair-commit wire endpoint (API parity with repa…
Opus 4.8
minor
⚠ breaking
1 day ago
| 1 | """Pydantic v2 request/response models for the agent context endpoint. |
| 2 | |
| 3 | The context endpoint (GET /musehub/repos/{repo_id}/context) is the canonical |
| 4 | agent entry point for composition sessions. These models define the wire |
| 5 | format that agents receive when they ask: "what do I need to know to start |
| 6 | composing in this project?" |
| 7 | |
| 8 | Depth levels control how much data is returned: |
| 9 | - ``brief`` — fits in ~2 K tokens; musical state + 3 history entries |
| 10 | - ``standard`` — fits in ~8 K tokens; full state + 10 history + analysis |
| 11 | - ``verbose`` — uncapped; all history, full issue/proposal bodies, full analysis |
| 12 | """ |
| 13 | |
| 14 | from enum import StrEnum |
| 15 | from typing import Annotated |
| 16 | |
| 17 | from pydantic import Field |
| 18 | |
| 19 | from musehub.models.base import CamelModel |
| 20 | |
| 21 | class ContextDepth(StrEnum): |
| 22 | """Depth level controlling how much data the context endpoint returns.""" |
| 23 | |
| 24 | brief = "brief" |
| 25 | standard = "standard" |
| 26 | verbose = "verbose" |
| 27 | |
| 28 | class ContextFormat(StrEnum): |
| 29 | """Wire format for the context response.""" |
| 30 | |
| 31 | json = "json" |
| 32 | yaml = "yaml" |
| 33 | |
| 34 | # --------------------------------------------------------------------------- |
| 35 | # Sub-sections of the context response |
| 36 | # --------------------------------------------------------------------------- |
| 37 | |
| 38 | class MusicalStateContext(CamelModel): |
| 39 | """Current musical state of the project at the resolved ref. |
| 40 | |
| 41 | All optional fields require Storpheus MIDI analysis and are None until |
| 42 | that integration is complete. Agents must handle None gracefully. |
| 43 | """ |
| 44 | |
| 45 | active_tracks: list[str] = Field( |
| 46 | default_factory=list, |
| 47 | description="Track names derived from the snapshot manifest", |
| 48 | ) |
| 49 | |
| 50 | class HistoryEntryContext(CamelModel): |
| 51 | """A single commit entry in the composition history.""" |
| 52 | |
| 53 | commit_id: str |
| 54 | message: str |
| 55 | author: str |
| 56 | timestamp: str = Field(description="ISO-8601 UTC timestamp") |
| 57 | active_tracks: list[str] = Field(default_factory=list) |
| 58 | |
| 59 | class AnalysisSummaryContext(CamelModel): |
| 60 | """Per-dimension analysis highlights for the current state. |
| 61 | |
| 62 | All fields are None until Storpheus MIDI analysis integration is complete. |
| 63 | Agents should treat None as "unknown" and compose without relying on these. |
| 64 | """ |
| 65 | |
| 66 | key_finding: Annotated[ |
| 67 | str | None, Field(description="Key and mode detection summary") |
| 68 | ] = None |
| 69 | chord_progression: Annotated[ |
| 70 | list[str] | None, |
| 71 | Field(description="Detected chord progression (e.g. ['Cm', 'Ab', 'Eb', 'Bb'])"), |
| 72 | ] = None |
| 73 | groove_score: Annotated[ |
| 74 | float | None, Field(description="Groove quality score [0.0, 1.0]") |
| 75 | ] = None |
| 76 | emotion: Annotated[str | None, Field(description="Emotional character")] = None |
| 77 | harmonic_tension: Annotated[ |
| 78 | str | None, |
| 79 | Field(description="Harmonic tension assessment ('low', 'medium', 'high')"), |
| 80 | ] = None |
| 81 | melodic_contour: Annotated[ |
| 82 | str | None, Field(description="Melodic contour description") |
| 83 | ] = None |
| 84 | |
| 85 | class ActiveProposalContext(CamelModel): |
| 86 | """An open proposal that may inform composition decisions.""" |
| 87 | |
| 88 | proposal_id: str |
| 89 | title: str |
| 90 | from_branch: str |
| 91 | to_branch: str |
| 92 | state: str |
| 93 | body: str = Field( |
| 94 | default="", |
| 95 | description="Proposal description; included at standard/verbose depth only", |
| 96 | ) |
| 97 | |
| 98 | class EnrichedProposalContext(ActiveProposalContext): |
| 99 | """``ActiveProposalContext`` extended with enrichment data from ``ProposalListEntry``. |
| 100 | |
| 101 | Returned by ``musehub_list_proposals_context``. Gives agents enough signal to |
| 102 | triage the full merge queue (risk, approvals, domain activity, blocking status) |
| 103 | without needing to call ``musehub_read_proposal`` for each entry. |
| 104 | """ |
| 105 | |
| 106 | aggregate_risk_band: str = Field( |
| 107 | "none", |
| 108 | description="'critical' (≥0.75) | 'high' (≥0.5) | 'medium' (≥0.25) | 'low' (>0) | 'none'", |
| 109 | ) |
| 110 | aggregate_risk_score: float = Field(0.0, ge=0.0, le=1.0) |
| 111 | active_domains: list[str] = Field(default_factory=list) |
| 112 | domain_risk_band: dict[str, str] = Field(default_factory=dict) |
| 113 | approval_count: int = Field(0, ge=0) |
| 114 | required_approvals: int = Field(2, ge=0) |
| 115 | all_merge_conditions_met: bool = False |
| 116 | is_blocked: bool = False |
| 117 | blocked_by: list[int] = Field(default_factory=list) |
| 118 | author_type: str = Field("human", description="'human' | 'agent' | 'org'") |
| 119 | breakage_count: int = Field(0, ge=0) |
| 120 | |
| 121 | |
| 122 | class OpenIssueContext(CamelModel): |
| 123 | """An open issue that may describe desired compositional changes.""" |
| 124 | |
| 125 | issue_id: str |
| 126 | number: int |
| 127 | title: str |
| 128 | labels: list[str] = Field(default_factory=list) |
| 129 | body: str = Field( |
| 130 | default="", |
| 131 | description="Issue body; included at verbose depth only", |
| 132 | ) |
| 133 | |
| 134 | # --------------------------------------------------------------------------- |
| 135 | # Top-level context response |
| 136 | # --------------------------------------------------------------------------- |
| 137 | |
| 138 | class AgentContextResponse(CamelModel): |
| 139 | """Complete agent context document for one project ref. |
| 140 | |
| 141 | This is the top-level response from GET /musehub/repos/{repo_id}/context. |
| 142 | It is self-contained: an agent receiving only this document has everything |
| 143 | it needs to generate structurally and stylistically coherent music. |
| 144 | |
| 145 | ``depth`` controls how much data is returned; ``format`` is echoed from |
| 146 | the request so agents can validate they received what they asked for. |
| 147 | """ |
| 148 | |
| 149 | repo_id: str |
| 150 | ref: str = Field(description="The resolved branch name or commit ID") |
| 151 | depth: str = Field(description="Depth level used to build this response") |
| 152 | musical_state: MusicalStateContext |
| 153 | history: list[HistoryEntryContext] = Field(default_factory=list) |
| 154 | analysis: AnalysisSummaryContext |
| 155 | active_proposals: list[ActiveProposalContext] = Field(default_factory=list) |
| 156 | open_issues: list[OpenIssueContext] = Field(default_factory=list) |
| 157 | suggestions: list[str] = Field( |
| 158 | default_factory=list, |
| 159 | description="AI-generated suggestions for next compositional actions", |
| 160 | ) |
File History
1 commit
sha256:3ff9c9863a9891bdcde71b4a43228f66d0493e38b7cc1d09fe9eb7de774046b2
feat: add repair-commit wire endpoint (API parity with repa…
Opus 4.8
minor
⚠
1 day ago