cursorfleet 0.1.0__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.
- cursorfleet/__init__.py +9 -0
- cursorfleet/_templates/cursor/agents/architect.md +18 -0
- cursorfleet/_templates/cursor/agents/implementer.md +20 -0
- cursorfleet/_templates/cursor/agents/patcher.md +17 -0
- cursorfleet/_templates/cursor/agents/qa.md +21 -0
- cursorfleet/_templates/cursor/agents/reviewer.md +20 -0
- cursorfleet/_templates/cursor/agents/scout.md +17 -0
- cursorfleet/_templates/cursor/agents/tester.md +20 -0
- cursorfleet/_templates/cursor/agents-md/root.md +7 -0
- cursorfleet/_templates/cursor/agents-md/work.md +7 -0
- cursorfleet/_templates/cursor/config/config.toml +47 -0
- cursorfleet/_templates/cursor/hooks/entry.json +4 -0
- cursorfleet/_templates/cursor/rules/cursorfleet-core.mdc +10 -0
- cursorfleet/_templates/cursor/rules/cursorfleet-handoff.mdc +15 -0
- cursorfleet/_templates/cursor/skills/cursorfleet-artifacts/SKILL.md +57 -0
- cursorfleet/_templates/cursor/skills/cursorfleet-coordinator/SKILL.md +35 -0
- cursorfleet/adapters/__init__.py +0 -0
- cursorfleet/adapters/cursor/__init__.py +0 -0
- cursorfleet/adapters/cursor/blocks.py +104 -0
- cursorfleet/adapters/cursor/diagnostics.py +547 -0
- cursorfleet/adapters/cursor/fsutil.py +156 -0
- cursorfleet/adapters/cursor/hook_main.py +428 -0
- cursorfleet/adapters/cursor/hook_normalize.py +527 -0
- cursorfleet/adapters/cursor/hook_policy.py +76 -0
- cursorfleet/adapters/cursor/hook_sanitize.py +474 -0
- cursorfleet/adapters/cursor/hooksjson.py +305 -0
- cursorfleet/adapters/cursor/installer.py +626 -0
- cursorfleet/adapters/cursor/kit.py +210 -0
- cursorfleet/adapters/cursor/kit_probe.py +54 -0
- cursorfleet/adapters/cursor/lock.py +145 -0
- cursorfleet/adapters/cursor/templates.py +60 -0
- cursorfleet/adapters/cursor/validation.py +365 -0
- cursorfleet/adapters/cursor/workspace.py +80 -0
- cursorfleet/cli/__init__.py +0 -0
- cursorfleet/cli/commands/__init__.py +1 -0
- cursorfleet/cli/commands/_common.py +82 -0
- cursorfleet/cli/commands/_resolution.py +56 -0
- cursorfleet/cli/commands/doctor.py +81 -0
- cursorfleet/cli/commands/events.py +197 -0
- cursorfleet/cli/commands/index.py +55 -0
- cursorfleet/cli/commands/init.py +71 -0
- cursorfleet/cli/commands/migrate.py +43 -0
- cursorfleet/cli/commands/replay.py +76 -0
- cursorfleet/cli/commands/run.py +97 -0
- cursorfleet/cli/commands/status.py +210 -0
- cursorfleet/cli/commands/tui.py +47 -0
- cursorfleet/cli/commands/uninstall.py +73 -0
- cursorfleet/cli/commands/validate.py +69 -0
- cursorfleet/cli/main.py +81 -0
- cursorfleet/config/__init__.py +44 -0
- cursorfleet/config/io.py +27 -0
- cursorfleet/config/models.py +154 -0
- cursorfleet/config/roster.py +245 -0
- cursorfleet/events/__init__.py +39 -0
- cursorfleet/events/forbidden.py +45 -0
- cursorfleet/events/ids.py +109 -0
- cursorfleet/events/kinds.py +132 -0
- cursorfleet/events/models.py +213 -0
- cursorfleet/events/pathcheck.py +45 -0
- cursorfleet/git/__init__.py +0 -0
- cursorfleet/git/collector.py +226 -0
- cursorfleet/git/runner.py +135 -0
- cursorfleet/git/worktrees.py +71 -0
- cursorfleet/policy/__init__.py +0 -0
- cursorfleet/py.typed +0 -0
- cursorfleet/safeexe.py +70 -0
- cursorfleet/schema_gen.py +73 -0
- cursorfleet/state/__init__.py +0 -0
- cursorfleet/state/artifact_scan.py +309 -0
- cursorfleet/state/context.py +38 -0
- cursorfleet/state/event_store.py +227 -0
- cursorfleet/state/indexer.py +443 -0
- cursorfleet/state/lock.py +74 -0
- cursorfleet/state/models.py +268 -0
- cursorfleet/state/reducer.py +588 -0
- cursorfleet/state/retention.py +218 -0
- cursorfleet/state/run_builder.py +136 -0
- cursorfleet/state/run_model.py +43 -0
- cursorfleet/state/run_store.py +95 -0
- cursorfleet/state/runtime.py +645 -0
- cursorfleet/state/spool.py +186 -0
- cursorfleet/state/spool_read.py +242 -0
- cursorfleet/state/status_doc.py +293 -0
- cursorfleet/tui/__init__.py +0 -0
- cursorfleet/tui/app.py +581 -0
- cursorfleet/tui/data.py +545 -0
- cursorfleet/tui/filters.py +82 -0
- cursorfleet/tui/gates.py +255 -0
- cursorfleet/tui/help.py +101 -0
- cursorfleet/tui/layout.py +26 -0
- cursorfleet/tui/theme.py +176 -0
- cursorfleet/tui/views.py +1077 -0
- cursorfleet/tui/watch.py +33 -0
- cursorfleet/workflow/__init__.py +0 -0
- cursorfleet/workflow/artifacts.py +148 -0
- cursorfleet/workflow/frontmatter.py +232 -0
- cursorfleet-0.1.0.dist-info/METADATA +161 -0
- cursorfleet-0.1.0.dist-info/RECORD +101 -0
- cursorfleet-0.1.0.dist-info/WHEEL +4 -0
- cursorfleet-0.1.0.dist-info/entry_points.txt +3 -0
- cursorfleet-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""State models: persisted accumulators (projection) and derived views (``status --json``).
|
|
2
|
+
|
|
3
|
+
Accumulators (``*Acc``) are what the reducer folds events into and what SQLite stores as
|
|
4
|
+
JSON. Views (``*View``) are computed from accumulators plus an injected ``now``; they carry
|
|
5
|
+
the stale/offline decision and are what the CLI prints.
|
|
6
|
+
|
|
7
|
+
Lanes are HEURISTICS over observed (and self-reported) events, not ground truth; every
|
|
8
|
+
lane carries its ``lane_source`` and the TUI must say so (docs/status-json.md).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from datetime import UTC, datetime
|
|
14
|
+
from enum import StrEnum
|
|
15
|
+
from typing import Annotated, Literal
|
|
16
|
+
|
|
17
|
+
from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, field_validator
|
|
18
|
+
|
|
19
|
+
from cursorfleet.events.kinds import Attribution, Outcome, Source
|
|
20
|
+
|
|
21
|
+
STATE_SCHEMA_VERSION = 1
|
|
22
|
+
MAX_FILES_PER_AGENT = 500
|
|
23
|
+
BUDGET_UNKNOWN = "unknown" # Cursor hooks expose no token budget (ADR 0001 A9)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Lane(StrEnum):
|
|
27
|
+
"""Workflow lane. ``unknown`` means "no telemetry"; it is never rendered as idle."""
|
|
28
|
+
|
|
29
|
+
QUEUED = "queued"
|
|
30
|
+
LOADING_CONTEXT = "loading_context"
|
|
31
|
+
PLANNING = "planning"
|
|
32
|
+
WORKING = "working"
|
|
33
|
+
VERIFYING = "verifying"
|
|
34
|
+
AWAITING_REVIEW = "awaiting_review"
|
|
35
|
+
PATCHING = "patching"
|
|
36
|
+
BLOCKED = "blocked"
|
|
37
|
+
DONE = "done"
|
|
38
|
+
STALE_OFFLINE = "stale_offline"
|
|
39
|
+
UNKNOWN = "unknown"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def utc(value: datetime) -> datetime:
|
|
43
|
+
return value.astimezone(UTC)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
_STRICT = ConfigDict(extra="forbid", validate_assignment=False)
|
|
47
|
+
UtcDatetime = Annotated[AwareDatetime, Field()]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class _Acc(BaseModel):
|
|
51
|
+
model_config = _STRICT
|
|
52
|
+
|
|
53
|
+
@field_validator("*", mode="after")
|
|
54
|
+
@classmethod
|
|
55
|
+
def _normalize_tz(cls, value: object) -> object:
|
|
56
|
+
return utc(value) if isinstance(value, datetime) else value
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class LastTest(_Acc):
|
|
60
|
+
outcome: Outcome
|
|
61
|
+
ts: UtcDatetime
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class StopReport(_Acc):
|
|
65
|
+
"""What Cursor itself reported when a subagent stopped (``subagentStop``)."""
|
|
66
|
+
|
|
67
|
+
outcome: Outcome | None = None
|
|
68
|
+
duration_ms: int | None = None
|
|
69
|
+
tool_call_count: int | None = None
|
|
70
|
+
message_count: int | None = None
|
|
71
|
+
loop_count: int | None = None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class AgentAcc(_Acc):
|
|
75
|
+
key: str
|
|
76
|
+
role: str | None = None
|
|
77
|
+
instance_id: str | None = None
|
|
78
|
+
attribution: Attribution = Attribution.UNKNOWN
|
|
79
|
+
lane: Lane = Lane.UNKNOWN
|
|
80
|
+
lane_source: Source | None = None
|
|
81
|
+
lane_since: UtcDatetime | None = None
|
|
82
|
+
first_ts: UtcDatetime
|
|
83
|
+
last_ts: UtcDatetime
|
|
84
|
+
last_live_ts: UtcDatetime | None = None # last observed/derived event (not self-reported)
|
|
85
|
+
events: int = 0
|
|
86
|
+
lifecycle: Literal["none", "running", "stopped"] = "none"
|
|
87
|
+
lifecycle_only: bool = False # running subagent with no attributed telemetry yet
|
|
88
|
+
started_ts: UtcDatetime | None = None
|
|
89
|
+
stopped_ts: UtcDatetime | None = None
|
|
90
|
+
spawn_link: str | None = None # tool_use_id / tool_call_id (PROVISIONAL linkage)
|
|
91
|
+
pre_calls: int = 0
|
|
92
|
+
pre_shell_calls: int = 0
|
|
93
|
+
before_shell_calls: int = 0
|
|
94
|
+
tool_failures: int = 0
|
|
95
|
+
last_tool: str | None = None
|
|
96
|
+
compactions: int = 0
|
|
97
|
+
last_context_usage_percent: float | None = None
|
|
98
|
+
last_context_tokens: int | None = None
|
|
99
|
+
last_context_window: int | None = None
|
|
100
|
+
files: list[str] = Field(default_factory=list)
|
|
101
|
+
files_overflow: bool = False
|
|
102
|
+
reviewed: bool = False
|
|
103
|
+
last_test: LastTest | None = None
|
|
104
|
+
stop_report: StopReport | None = None
|
|
105
|
+
plans: int = 0
|
|
106
|
+
handoffs: int = 0
|
|
107
|
+
blockers: int = 0
|
|
108
|
+
contexts_loaded: int = 0
|
|
109
|
+
issue_refs: list[str] = Field(default_factory=list)
|
|
110
|
+
worktree_id: str | None = None
|
|
111
|
+
branch: str | None = None
|
|
112
|
+
commit: str | None = None
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def tool_call_count(self) -> int:
|
|
116
|
+
"""Tool calls seen. ``preToolUse`` is canonical; Shell-hook starts count only when
|
|
117
|
+
no ``preToolUse`` for Shell was seen (hook set may be a subset), so overlapping
|
|
118
|
+
hooks never double count."""
|
|
119
|
+
shell_fallback = self.before_shell_calls if self.pre_shell_calls == 0 else 0
|
|
120
|
+
return self.pre_calls + shell_fallback
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class GateAcc(_Acc):
|
|
124
|
+
state: str
|
|
125
|
+
ts: UtcDatetime
|
|
126
|
+
commit: str | None = None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class SessionAcc(_Acc):
|
|
130
|
+
schema_version: int = STATE_SCHEMA_VERSION
|
|
131
|
+
session_id: str
|
|
132
|
+
first_ts: UtcDatetime
|
|
133
|
+
last_ts: UtcDatetime
|
|
134
|
+
last_live_ts: UtcDatetime | None = None
|
|
135
|
+
started_ts: UtcDatetime | None = None
|
|
136
|
+
ended_ts: UtcDatetime | None = None
|
|
137
|
+
ended: bool = False
|
|
138
|
+
end_outcome: Outcome | None = None
|
|
139
|
+
cursor_version: str | None = None
|
|
140
|
+
branch: str | None = None
|
|
141
|
+
commit: str | None = None
|
|
142
|
+
worktree_ids: list[str] = Field(default_factory=list)
|
|
143
|
+
events: int = 0
|
|
144
|
+
by_source: dict[str, int] = Field(default_factory=dict)
|
|
145
|
+
unpaired_stops: int = 0
|
|
146
|
+
agents: dict[str, AgentAcc] = Field(default_factory=dict)
|
|
147
|
+
gates: dict[str, GateAcc] = Field(default_factory=dict)
|
|
148
|
+
watermark_ts: UtcDatetime
|
|
149
|
+
watermark_id: str
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# ---------------------------------------------------------------- views
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class _View(BaseModel):
|
|
156
|
+
model_config = ConfigDict(extra="forbid")
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class LastTestView(_View):
|
|
160
|
+
outcome: str
|
|
161
|
+
ts: datetime
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class StopReportView(_View):
|
|
165
|
+
outcome: str | None
|
|
166
|
+
duration_ms: int | None
|
|
167
|
+
tool_call_count: int | None
|
|
168
|
+
message_count: int | None
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class AgentView(_View):
|
|
172
|
+
key: str
|
|
173
|
+
role: str | None
|
|
174
|
+
instance_id: str | None
|
|
175
|
+
attribution: str
|
|
176
|
+
lane: str
|
|
177
|
+
lane_source: str | None
|
|
178
|
+
lane_basis: str
|
|
179
|
+
stale: bool
|
|
180
|
+
last_lane: str | None # the lane before it went stale_offline
|
|
181
|
+
lifecycle: str
|
|
182
|
+
lifecycle_only: bool
|
|
183
|
+
first_ts: datetime
|
|
184
|
+
last_ts: datetime
|
|
185
|
+
elapsed_s: float
|
|
186
|
+
tool_call_count: int
|
|
187
|
+
tool_failures: int
|
|
188
|
+
compactions: int
|
|
189
|
+
last_context_usage_percent: float | None
|
|
190
|
+
files_changed: int
|
|
191
|
+
reviewed: bool
|
|
192
|
+
last_test: LastTestView | None
|
|
193
|
+
stop_report: StopReportView | None
|
|
194
|
+
issue_refs: list[str]
|
|
195
|
+
worktree_id: str | None
|
|
196
|
+
branch: str | None
|
|
197
|
+
token_budget: str
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class GateView(_View):
|
|
201
|
+
name: str
|
|
202
|
+
state: str
|
|
203
|
+
ts: datetime
|
|
204
|
+
commit: str | None
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class SessionView(_View):
|
|
208
|
+
session_id: str
|
|
209
|
+
lane: str
|
|
210
|
+
ended: bool
|
|
211
|
+
end_outcome: str | None
|
|
212
|
+
first_ts: datetime
|
|
213
|
+
last_ts: datetime
|
|
214
|
+
started_ts: datetime | None
|
|
215
|
+
ended_ts: datetime | None
|
|
216
|
+
elapsed_s: float
|
|
217
|
+
tool_call_count: int
|
|
218
|
+
compactions: int
|
|
219
|
+
event_count: int
|
|
220
|
+
by_source: dict[str, int]
|
|
221
|
+
cursor_version: str | None
|
|
222
|
+
branch: str | None
|
|
223
|
+
commit: str | None
|
|
224
|
+
worktree_ids: list[str]
|
|
225
|
+
unpaired_stops: int
|
|
226
|
+
token_budget: str
|
|
227
|
+
agents: list[AgentView]
|
|
228
|
+
gates: list[GateView]
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class TaskView(_View):
|
|
232
|
+
issue_ref: str
|
|
233
|
+
lane: str
|
|
234
|
+
session_ids: list[str]
|
|
235
|
+
agent_keys: list[str]
|
|
236
|
+
first_ts: datetime
|
|
237
|
+
last_ts: datetime
|
|
238
|
+
plans: int
|
|
239
|
+
handoffs: int
|
|
240
|
+
blockers: int
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class FleetView(_View):
|
|
244
|
+
generated_at: datetime
|
|
245
|
+
stale_after_s: int
|
|
246
|
+
sessions: list[SessionView]
|
|
247
|
+
tasks: list[TaskView]
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
__all__ = [
|
|
251
|
+
"BUDGET_UNKNOWN",
|
|
252
|
+
"MAX_FILES_PER_AGENT",
|
|
253
|
+
"STATE_SCHEMA_VERSION",
|
|
254
|
+
"AgentAcc",
|
|
255
|
+
"AgentView",
|
|
256
|
+
"FleetView",
|
|
257
|
+
"GateAcc",
|
|
258
|
+
"GateView",
|
|
259
|
+
"Lane",
|
|
260
|
+
"LastTest",
|
|
261
|
+
"LastTestView",
|
|
262
|
+
"SessionAcc",
|
|
263
|
+
"SessionView",
|
|
264
|
+
"StopReport",
|
|
265
|
+
"StopReportView",
|
|
266
|
+
"TaskView",
|
|
267
|
+
"utc",
|
|
268
|
+
]
|