crabcode 0.1.6__py3-none-win_amd64.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 (205) hide show
  1. crabcode-0.1.6.dist-info/METADATA +63 -0
  2. crabcode-0.1.6.dist-info/RECORD +205 -0
  3. crabcode-0.1.6.dist-info/WHEEL +4 -0
  4. crabcode-0.1.6.dist-info/entry_points.txt +2 -0
  5. crabcode_cli/__init__.py +7 -0
  6. crabcode_cli/__main__.py +4 -0
  7. crabcode_cli/_native/crabcode-computer-use-host.exe +0 -0
  8. crabcode_cli/_native/runtime.json +6 -0
  9. crabcode_cli/app.py +776 -0
  10. crabcode_cli/banner.py +39 -0
  11. crabcode_cli/computer_use.py +286 -0
  12. crabcode_cli/model_manager.py +649 -0
  13. crabcode_cli/model_picker.py +168 -0
  14. crabcode_cli/pipe.py +148 -0
  15. crabcode_cli/render/__init__.py +0 -0
  16. crabcode_cli/render/messages.py +19 -0
  17. crabcode_cli/repl.py +4841 -0
  18. crabcode_cli/session_picker.py +239 -0
  19. crabcode_core/__init__.py +7 -0
  20. crabcode_core/_version.py +3 -0
  21. crabcode_core/_windows_process.py +68 -0
  22. crabcode_core/agent_manager.py +1731 -0
  23. crabcode_core/api/__init__.py +20 -0
  24. crabcode_core/api/anthropic_adapter.py +648 -0
  25. crabcode_core/api/azure_adapter.py +69 -0
  26. crabcode_core/api/base.py +233 -0
  27. crabcode_core/api/codex_adapter.py +1327 -0
  28. crabcode_core/api/error_logging.py +132 -0
  29. crabcode_core/api/gemini_adapter.py +26 -0
  30. crabcode_core/api/model_info.py +257 -0
  31. crabcode_core/api/network.py +62 -0
  32. crabcode_core/api/ollama_adapter.py +27 -0
  33. crabcode_core/api/openai_adapter.py +323 -0
  34. crabcode_core/api/registry.py +58 -0
  35. crabcode_core/command_line.py +18 -0
  36. crabcode_core/compact/__init__.py +17 -0
  37. crabcode_core/compact/compact.py +514 -0
  38. crabcode_core/compact/context_tokens.py +165 -0
  39. crabcode_core/computer_use_mode.py +38 -0
  40. crabcode_core/computer_use_observation.py +144 -0
  41. crabcode_core/config/__init__.py +3 -0
  42. crabcode_core/config/claudemd.py +61 -0
  43. crabcode_core/config/manager.py +237 -0
  44. crabcode_core/config/model_catalog.py +256 -0
  45. crabcode_core/events.py +4896 -0
  46. crabcode_core/file_lock.py +81 -0
  47. crabcode_core/filesystem.py +22 -0
  48. crabcode_core/goal.py +149 -0
  49. crabcode_core/hooks/__init__.py +5 -0
  50. crabcode_core/hooks/manager.py +290 -0
  51. crabcode_core/image_io.py +111 -0
  52. crabcode_core/io_worker.py +211 -0
  53. crabcode_core/logging_utils.py +168 -0
  54. crabcode_core/lsp/__init__.py +6 -0
  55. crabcode_core/lsp/client.py +786 -0
  56. crabcode_core/lsp/diagnostics.py +150 -0
  57. crabcode_core/lsp/manager.py +583 -0
  58. crabcode_core/mcp/__init__.py +4 -0
  59. crabcode_core/mcp/client.py +169 -0
  60. crabcode_core/mcp/config.py +57 -0
  61. crabcode_core/path_validation.py +34 -0
  62. crabcode_core/paths.py +24 -0
  63. crabcode_core/peer/__init__.py +10 -0
  64. crabcode_core/peer/runtime.py +518 -0
  65. crabcode_core/permissions/__init__.py +7 -0
  66. crabcode_core/permissions/ai_reviewer.py +184 -0
  67. crabcode_core/permissions/manager.py +187 -0
  68. crabcode_core/plan/__init__.py +5 -0
  69. crabcode_core/plan/executor.py +270 -0
  70. crabcode_core/plan/types.py +169 -0
  71. crabcode_core/prompts/__init__.py +0 -0
  72. crabcode_core/prompts/blocks.py +10 -0
  73. crabcode_core/prompts/context.py +229 -0
  74. crabcode_core/prompts/library.py +92 -0
  75. crabcode_core/prompts/profile.py +79 -0
  76. crabcode_core/prompts/system.py +356 -0
  77. crabcode_core/prompts/templates.py +104 -0
  78. crabcode_core/query/__init__.py +0 -0
  79. crabcode_core/query/computer_use_history.py +83 -0
  80. crabcode_core/query/loop.py +2446 -0
  81. crabcode_core/query/retry.py +116 -0
  82. crabcode_core/schedule/__init__.py +13 -0
  83. crabcode_core/schedule/manager.py +631 -0
  84. crabcode_core/schedule/models.py +204 -0
  85. crabcode_core/schedule/store.py +558 -0
  86. crabcode_core/schedule/timing.py +287 -0
  87. crabcode_core/session/__init__.py +12 -0
  88. crabcode_core/session/export.py +141 -0
  89. crabcode_core/session/meta_db.py +684 -0
  90. crabcode_core/session/storage.py +2032 -0
  91. crabcode_core/session/title_gen.py +52 -0
  92. crabcode_core/skills/__init__.py +6 -0
  93. crabcode_core/skills/context.py +23 -0
  94. crabcode_core/skills/loader.py +214 -0
  95. crabcode_core/skills/matcher.py +203 -0
  96. crabcode_core/snapshot/__init__.py +21 -0
  97. crabcode_core/snapshot/snapshot.py +436 -0
  98. crabcode_core/snapshot/tracker.py +359 -0
  99. crabcode_core/subprocess_utils.py +260 -0
  100. crabcode_core/team/__init__.py +27 -0
  101. crabcode_core/team/bridge.py +66 -0
  102. crabcode_core/team/inbox.py +237 -0
  103. crabcode_core/team/manager.py +1660 -0
  104. crabcode_core/team/message_bus.py +821 -0
  105. crabcode_core/team/models.py +191 -0
  106. crabcode_core/team/recovery.py +192 -0
  107. crabcode_core/text_io.py +52 -0
  108. crabcode_core/tools/__init__.py +112 -0
  109. crabcode_core/tools/_input_helpers.py +39 -0
  110. crabcode_core/tools/_input_schema.py +130 -0
  111. crabcode_core/tools/agent.py +413 -0
  112. crabcode_core/tools/apply_patch.py +587 -0
  113. crabcode_core/tools/ask_user.py +122 -0
  114. crabcode_core/tools/bash.py +154 -0
  115. crabcode_core/tools/browser.py +678 -0
  116. crabcode_core/tools/checklist.py +241 -0
  117. crabcode_core/tools/checkpoint.py +78 -0
  118. crabcode_core/tools/computer_use.py +599 -0
  119. crabcode_core/tools/diff_utils.py +123 -0
  120. crabcode_core/tools/file_edit.py +240 -0
  121. crabcode_core/tools/file_read.py +187 -0
  122. crabcode_core/tools/file_write.py +154 -0
  123. crabcode_core/tools/glob.py +123 -0
  124. crabcode_core/tools/goal.py +134 -0
  125. crabcode_core/tools/grep.py +247 -0
  126. crabcode_core/tools/image.py +173 -0
  127. crabcode_core/tools/image_generate.py +115 -0
  128. crabcode_core/tools/lint.py +388 -0
  129. crabcode_core/tools/loading.py +187 -0
  130. crabcode_core/tools/memory.py +456 -0
  131. crabcode_core/tools/monitor.py +677 -0
  132. crabcode_core/tools/peer.py +103 -0
  133. crabcode_core/tools/revert.py +90 -0
  134. crabcode_core/tools/schedule.py +683 -0
  135. crabcode_core/tools/skill.py +108 -0
  136. crabcode_core/tools/switch_mode.py +213 -0
  137. crabcode_core/tools/team.py +329 -0
  138. crabcode_core/tools/tool_search.py +64 -0
  139. crabcode_core/tools/web_search.py +444 -0
  140. crabcode_core/turn_details.py +64 -0
  141. crabcode_core/types/__init__.py +95 -0
  142. crabcode_core/types/config.py +434 -0
  143. crabcode_core/types/event.py +334 -0
  144. crabcode_core/types/message.py +263 -0
  145. crabcode_core/types/tool.py +208 -0
  146. crabcode_core/usage.py +289 -0
  147. crabcode_core/utf8_sanitize.py +29 -0
  148. crabcode_debugger/__init__.py +5 -0
  149. crabcode_debugger/adapters.py +332 -0
  150. crabcode_debugger/dap.py +304 -0
  151. crabcode_debugger/memory.py +1806 -0
  152. crabcode_debugger/process.py +707 -0
  153. crabcode_debugger/runtime.py +58 -0
  154. crabcode_debugger/sessions.py +387 -0
  155. crabcode_debugger/tool.py +731 -0
  156. crabcode_gateway/__init__.py +18 -0
  157. crabcode_gateway/acp/__init__.py +13 -0
  158. crabcode_gateway/acp/agent.py +1581 -0
  159. crabcode_gateway/acp/session.py +114 -0
  160. crabcode_gateway/acp/transport.py +39 -0
  161. crabcode_gateway/acp/types.py +90 -0
  162. crabcode_gateway/adapter.py +30 -0
  163. crabcode_gateway/auth.py +139 -0
  164. crabcode_gateway/computer_use.py +364 -0
  165. crabcode_gateway/document_engine.py +637 -0
  166. crabcode_gateway/document_worker.py +301 -0
  167. crabcode_gateway/event_bus.py +655 -0
  168. crabcode_gateway/grpc/__init__.py +0 -0
  169. crabcode_gateway/grpc/crabcode_pb2.py +70 -0
  170. crabcode_gateway/grpc/crabcode_pb2_grpc.py +474 -0
  171. crabcode_gateway/grpc/proto/crabcode.proto +160 -0
  172. crabcode_gateway/grpc/server.py +765 -0
  173. crabcode_gateway/middleware.py +344 -0
  174. crabcode_gateway/protocol.py +17 -0
  175. crabcode_gateway/routes/__init__.py +0 -0
  176. crabcode_gateway/routes/agent.py +392 -0
  177. crabcode_gateway/routes/auth.py +150 -0
  178. crabcode_gateway/routes/computer_use.py +101 -0
  179. crabcode_gateway/routes/config.py +1698 -0
  180. crabcode_gateway/routes/document.py +1810 -0
  181. crabcode_gateway/routes/event.py +3801 -0
  182. crabcode_gateway/routes/git_review.py +232 -0
  183. crabcode_gateway/routes/health.py +14 -0
  184. crabcode_gateway/routes/peer.py +78 -0
  185. crabcode_gateway/routes/permission.py +121 -0
  186. crabcode_gateway/routes/schedule.py +300 -0
  187. crabcode_gateway/routes/session.py +1496 -0
  188. crabcode_gateway/routes/snapshot.py +211 -0
  189. crabcode_gateway/routes/tasks.py +318 -0
  190. crabcode_gateway/routes/team.py +392 -0
  191. crabcode_gateway/routes/usage.py +49 -0
  192. crabcode_gateway/routes/workspace.py +299 -0
  193. crabcode_gateway/safe_file.py +63 -0
  194. crabcode_gateway/schemas.py +1820 -0
  195. crabcode_gateway/server.py +514 -0
  196. crabcode_gateway/session_registry.py +36 -0
  197. crabcode_gateway/task_registry.py +708 -0
  198. crabcode_gateway/turn_details.py +60 -0
  199. crabcode_search/__init__.py +11 -0
  200. crabcode_search/background.py +368 -0
  201. crabcode_search/chunker.py +517 -0
  202. crabcode_search/embedder.py +497 -0
  203. crabcode_search/indexer.py +215 -0
  204. crabcode_search/store.py +222 -0
  205. crabcode_search/tool.py +268 -0
@@ -0,0 +1,204 @@
1
+ """Core data models for the Schedule subsystem.
2
+
3
+ Defines ScheduleJob, JobRun and related types used by the scheduler engine
4
+ and persistence layer.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import uuid
10
+ from datetime import datetime, timezone
11
+ from enum import Enum
12
+ from typing import Any
13
+
14
+ from pydantic import BaseModel, Field
15
+
16
+
17
+ def _now_iso() -> str:
18
+ return datetime.now(timezone.utc).isoformat()
19
+
20
+
21
+ def _new_id() -> str:
22
+ return str(uuid.uuid4())
23
+
24
+
25
+ # ---------------------------------------------------------------------------
26
+ # Enums
27
+ # ---------------------------------------------------------------------------
28
+
29
+
30
+ class ScheduleType(str, Enum):
31
+ """How a job is triggered."""
32
+
33
+ CRON = "cron"
34
+ INTERVAL = "interval"
35
+ ONCE = "once"
36
+
37
+
38
+ class JobStatus(str, Enum):
39
+ """Lifecycle status of a ScheduleJob."""
40
+
41
+ ACTIVE = "active"
42
+ PAUSED = "paused"
43
+ COMPLETED = "completed"
44
+ DISABLED = "disabled"
45
+ ERROR = "error"
46
+
47
+
48
+ class RunStatus(str, Enum):
49
+ """Status of an individual JobRun execution."""
50
+
51
+ PENDING = "pending"
52
+ RUNNING = "running"
53
+ SUCCESS = "success"
54
+ FAILED = "failed"
55
+ TIMEOUT = "timeout"
56
+ SKIPPED = "skipped"
57
+
58
+
59
+ # ---------------------------------------------------------------------------
60
+ # Models
61
+ # ---------------------------------------------------------------------------
62
+
63
+
64
+ class ScheduleJob(BaseModel):
65
+ """A scheduled job definition.
66
+
67
+ A job encapsulates a prompt that will be executed on a time-based
68
+ schedule (cron expression, fixed interval, or a single one-shot).
69
+ """
70
+
71
+ id: str = Field(default_factory=_new_id, description="Unique job identifier")
72
+ name: str = Field(description="Human-readable job name")
73
+ prompt: str = Field(description="The prompt to send to the agent when the job fires")
74
+ schedule: str = Field(
75
+ description="Schedule definition: cron expression, interval string (e.g. '30m', '2h'), or ISO timestamp for once"
76
+ )
77
+ schedule_type: ScheduleType = Field(description="Type of schedule: cron | interval | once")
78
+ cwd: str | None = Field(default=None, description="Working directory for the job execution")
79
+ enabled: bool = Field(default=True, description="Whether the job is enabled")
80
+ status: JobStatus = Field(default=JobStatus.ACTIVE, description="Current lifecycle status")
81
+ last_run: str | None = Field(default=None, description="ISO timestamp of the last run")
82
+ next_run: str | None = Field(default=None, description="ISO timestamp of the next scheduled run")
83
+ run_count: int = Field(default=0, description="Total number of completed runs")
84
+ max_runs: int | None = Field(
85
+ default=None, description="Maximum allowed runs (None = unlimited)"
86
+ )
87
+ created_at: str = Field(default_factory=_now_iso, description="ISO timestamp of creation")
88
+ session_id: str | None = Field(
89
+ default=None,
90
+ description="Associated session ID (reused if set, otherwise a new session is created per run)",
91
+ )
92
+
93
+ # Optional metadata
94
+ description: str = Field(default="", description="Optional longer description of the job")
95
+ tags: list[str] = Field(default_factory=list, description="Arbitrary tags for filtering")
96
+ timeout: int | None = Field(
97
+ default=None, description="Per-job timeout in seconds (overrides ScheduleSettings.default_timeout)"
98
+ )
99
+ model_profile: str | None = Field(
100
+ default=None, description="Model profile to use for this job's agent"
101
+ )
102
+ extra: dict[str, Any] = Field(
103
+ default_factory=dict, description="Extension key-value pairs for future use"
104
+ )
105
+
106
+ def mark_running(self) -> None:
107
+ """Transition to active status when a run starts."""
108
+ if self.status in (JobStatus.ACTIVE, JobStatus.ERROR):
109
+ self.status = JobStatus.ACTIVE
110
+
111
+ def mark_completed(self) -> None:
112
+ """Mark the job as fully completed (e.g. max_runs reached or one-shot done)."""
113
+ self.status = JobStatus.COMPLETED
114
+
115
+ def increment_run(self, timestamp: str | None = None) -> None:
116
+ """Record a successful run: bump run_count and set last_run."""
117
+ self.run_count += 1
118
+ self.last_run = timestamp or _now_iso()
119
+ # Auto-complete when max_runs is reached
120
+ if self.max_runs is not None and self.run_count >= self.max_runs:
121
+ self.status = JobStatus.COMPLETED
122
+
123
+
124
+ class JobRun(BaseModel):
125
+ """A single execution record of a ScheduleJob.
126
+
127
+ Each time a job fires, a JobRun is created to track that invocation's
128
+ lifecycle from pending → running → success/failed/timeout.
129
+ """
130
+
131
+ id: str = Field(default_factory=_new_id, description="Unique run identifier")
132
+ job_id: str = Field(description="Foreign key to the parent ScheduleJob.id")
133
+ status: RunStatus = Field(default=RunStatus.PENDING, description="Current execution status")
134
+ started_at: str | None = Field(default=None, description="ISO timestamp when the run started")
135
+ finished_at: str | None = Field(default=None, description="ISO timestamp when the run finished")
136
+ duration_seconds: float | None = Field(
137
+ default=None, description="Wall-clock duration in seconds"
138
+ )
139
+ session_id: str | None = Field(
140
+ default=None, description="Session used for this specific run"
141
+ )
142
+ exit_code: int | None = Field(default=None, description="Process exit code if applicable")
143
+ error_message: str | None = Field(default=None, description="Error details on failure")
144
+ result_summary: str = Field(
145
+ default="", description="Short summary of the run outcome"
146
+ )
147
+ tokens_used: int = Field(default=0, description="Token usage for this run")
148
+ created_at: str = Field(default_factory=_now_iso, description="ISO timestamp of creation")
149
+
150
+ def start(self, session_id: str | None = None) -> None:
151
+ """Transition from PENDING → RUNNING."""
152
+ if self.status != RunStatus.PENDING:
153
+ return
154
+ self.status = RunStatus.RUNNING
155
+ self.started_at = _now_iso()
156
+ if session_id:
157
+ self.session_id = session_id
158
+
159
+ def succeed(self, summary: str = "", tokens: int = 0) -> None:
160
+ """Transition from RUNNING → SUCCESS."""
161
+ if self.status != RunStatus.RUNNING:
162
+ return
163
+ self.status = RunStatus.SUCCESS
164
+ self.finished_at = _now_iso()
165
+ self._compute_duration()
166
+ self.result_summary = summary
167
+ self.tokens_used = tokens
168
+
169
+ def fail(self, error: str = "", exit_code: int | None = None) -> None:
170
+ """Transition from RUNNING → FAILED."""
171
+ if self.status != RunStatus.RUNNING:
172
+ return
173
+ self.status = RunStatus.FAILED
174
+ self.finished_at = _now_iso()
175
+ self._compute_duration()
176
+ self.error_message = error
177
+ self.exit_code = exit_code
178
+
179
+ def timeout(self) -> None:
180
+ """Transition from RUNNING → TIMEOUT."""
181
+ if self.status != RunStatus.RUNNING:
182
+ return
183
+ self.status = RunStatus.TIMEOUT
184
+ self.finished_at = _now_iso()
185
+ self._compute_duration()
186
+ self.error_message = "Job execution timed out"
187
+
188
+ def skip(self, reason: str = "") -> None:
189
+ """Transition from PENDING → SKIPPED (e.g. concurrency limit)."""
190
+ if self.status != RunStatus.PENDING:
191
+ return
192
+ self.status = RunStatus.SKIPPED
193
+ self.finished_at = _now_iso()
194
+ self.result_summary = reason or "Skipped"
195
+
196
+ def _compute_duration(self) -> None:
197
+ """Calculate duration_seconds from started_at and finished_at."""
198
+ if self.started_at and self.finished_at:
199
+ try:
200
+ start = datetime.fromisoformat(self.started_at)
201
+ end = datetime.fromisoformat(self.finished_at)
202
+ self.duration_seconds = (end - start).total_seconds()
203
+ except (ValueError, TypeError):
204
+ pass