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.
- crabcode-0.1.6.dist-info/METADATA +63 -0
- crabcode-0.1.6.dist-info/RECORD +205 -0
- crabcode-0.1.6.dist-info/WHEEL +4 -0
- crabcode-0.1.6.dist-info/entry_points.txt +2 -0
- crabcode_cli/__init__.py +7 -0
- crabcode_cli/__main__.py +4 -0
- crabcode_cli/_native/crabcode-computer-use-host.exe +0 -0
- crabcode_cli/_native/runtime.json +6 -0
- crabcode_cli/app.py +776 -0
- crabcode_cli/banner.py +39 -0
- crabcode_cli/computer_use.py +286 -0
- crabcode_cli/model_manager.py +649 -0
- crabcode_cli/model_picker.py +168 -0
- crabcode_cli/pipe.py +148 -0
- crabcode_cli/render/__init__.py +0 -0
- crabcode_cli/render/messages.py +19 -0
- crabcode_cli/repl.py +4841 -0
- crabcode_cli/session_picker.py +239 -0
- crabcode_core/__init__.py +7 -0
- crabcode_core/_version.py +3 -0
- crabcode_core/_windows_process.py +68 -0
- crabcode_core/agent_manager.py +1731 -0
- crabcode_core/api/__init__.py +20 -0
- crabcode_core/api/anthropic_adapter.py +648 -0
- crabcode_core/api/azure_adapter.py +69 -0
- crabcode_core/api/base.py +233 -0
- crabcode_core/api/codex_adapter.py +1327 -0
- crabcode_core/api/error_logging.py +132 -0
- crabcode_core/api/gemini_adapter.py +26 -0
- crabcode_core/api/model_info.py +257 -0
- crabcode_core/api/network.py +62 -0
- crabcode_core/api/ollama_adapter.py +27 -0
- crabcode_core/api/openai_adapter.py +323 -0
- crabcode_core/api/registry.py +58 -0
- crabcode_core/command_line.py +18 -0
- crabcode_core/compact/__init__.py +17 -0
- crabcode_core/compact/compact.py +514 -0
- crabcode_core/compact/context_tokens.py +165 -0
- crabcode_core/computer_use_mode.py +38 -0
- crabcode_core/computer_use_observation.py +144 -0
- crabcode_core/config/__init__.py +3 -0
- crabcode_core/config/claudemd.py +61 -0
- crabcode_core/config/manager.py +237 -0
- crabcode_core/config/model_catalog.py +256 -0
- crabcode_core/events.py +4896 -0
- crabcode_core/file_lock.py +81 -0
- crabcode_core/filesystem.py +22 -0
- crabcode_core/goal.py +149 -0
- crabcode_core/hooks/__init__.py +5 -0
- crabcode_core/hooks/manager.py +290 -0
- crabcode_core/image_io.py +111 -0
- crabcode_core/io_worker.py +211 -0
- crabcode_core/logging_utils.py +168 -0
- crabcode_core/lsp/__init__.py +6 -0
- crabcode_core/lsp/client.py +786 -0
- crabcode_core/lsp/diagnostics.py +150 -0
- crabcode_core/lsp/manager.py +583 -0
- crabcode_core/mcp/__init__.py +4 -0
- crabcode_core/mcp/client.py +169 -0
- crabcode_core/mcp/config.py +57 -0
- crabcode_core/path_validation.py +34 -0
- crabcode_core/paths.py +24 -0
- crabcode_core/peer/__init__.py +10 -0
- crabcode_core/peer/runtime.py +518 -0
- crabcode_core/permissions/__init__.py +7 -0
- crabcode_core/permissions/ai_reviewer.py +184 -0
- crabcode_core/permissions/manager.py +187 -0
- crabcode_core/plan/__init__.py +5 -0
- crabcode_core/plan/executor.py +270 -0
- crabcode_core/plan/types.py +169 -0
- crabcode_core/prompts/__init__.py +0 -0
- crabcode_core/prompts/blocks.py +10 -0
- crabcode_core/prompts/context.py +229 -0
- crabcode_core/prompts/library.py +92 -0
- crabcode_core/prompts/profile.py +79 -0
- crabcode_core/prompts/system.py +356 -0
- crabcode_core/prompts/templates.py +104 -0
- crabcode_core/query/__init__.py +0 -0
- crabcode_core/query/computer_use_history.py +83 -0
- crabcode_core/query/loop.py +2446 -0
- crabcode_core/query/retry.py +116 -0
- crabcode_core/schedule/__init__.py +13 -0
- crabcode_core/schedule/manager.py +631 -0
- crabcode_core/schedule/models.py +204 -0
- crabcode_core/schedule/store.py +558 -0
- crabcode_core/schedule/timing.py +287 -0
- crabcode_core/session/__init__.py +12 -0
- crabcode_core/session/export.py +141 -0
- crabcode_core/session/meta_db.py +684 -0
- crabcode_core/session/storage.py +2032 -0
- crabcode_core/session/title_gen.py +52 -0
- crabcode_core/skills/__init__.py +6 -0
- crabcode_core/skills/context.py +23 -0
- crabcode_core/skills/loader.py +214 -0
- crabcode_core/skills/matcher.py +203 -0
- crabcode_core/snapshot/__init__.py +21 -0
- crabcode_core/snapshot/snapshot.py +436 -0
- crabcode_core/snapshot/tracker.py +359 -0
- crabcode_core/subprocess_utils.py +260 -0
- crabcode_core/team/__init__.py +27 -0
- crabcode_core/team/bridge.py +66 -0
- crabcode_core/team/inbox.py +237 -0
- crabcode_core/team/manager.py +1660 -0
- crabcode_core/team/message_bus.py +821 -0
- crabcode_core/team/models.py +191 -0
- crabcode_core/team/recovery.py +192 -0
- crabcode_core/text_io.py +52 -0
- crabcode_core/tools/__init__.py +112 -0
- crabcode_core/tools/_input_helpers.py +39 -0
- crabcode_core/tools/_input_schema.py +130 -0
- crabcode_core/tools/agent.py +413 -0
- crabcode_core/tools/apply_patch.py +587 -0
- crabcode_core/tools/ask_user.py +122 -0
- crabcode_core/tools/bash.py +154 -0
- crabcode_core/tools/browser.py +678 -0
- crabcode_core/tools/checklist.py +241 -0
- crabcode_core/tools/checkpoint.py +78 -0
- crabcode_core/tools/computer_use.py +599 -0
- crabcode_core/tools/diff_utils.py +123 -0
- crabcode_core/tools/file_edit.py +240 -0
- crabcode_core/tools/file_read.py +187 -0
- crabcode_core/tools/file_write.py +154 -0
- crabcode_core/tools/glob.py +123 -0
- crabcode_core/tools/goal.py +134 -0
- crabcode_core/tools/grep.py +247 -0
- crabcode_core/tools/image.py +173 -0
- crabcode_core/tools/image_generate.py +115 -0
- crabcode_core/tools/lint.py +388 -0
- crabcode_core/tools/loading.py +187 -0
- crabcode_core/tools/memory.py +456 -0
- crabcode_core/tools/monitor.py +677 -0
- crabcode_core/tools/peer.py +103 -0
- crabcode_core/tools/revert.py +90 -0
- crabcode_core/tools/schedule.py +683 -0
- crabcode_core/tools/skill.py +108 -0
- crabcode_core/tools/switch_mode.py +213 -0
- crabcode_core/tools/team.py +329 -0
- crabcode_core/tools/tool_search.py +64 -0
- crabcode_core/tools/web_search.py +444 -0
- crabcode_core/turn_details.py +64 -0
- crabcode_core/types/__init__.py +95 -0
- crabcode_core/types/config.py +434 -0
- crabcode_core/types/event.py +334 -0
- crabcode_core/types/message.py +263 -0
- crabcode_core/types/tool.py +208 -0
- crabcode_core/usage.py +289 -0
- crabcode_core/utf8_sanitize.py +29 -0
- crabcode_debugger/__init__.py +5 -0
- crabcode_debugger/adapters.py +332 -0
- crabcode_debugger/dap.py +304 -0
- crabcode_debugger/memory.py +1806 -0
- crabcode_debugger/process.py +707 -0
- crabcode_debugger/runtime.py +58 -0
- crabcode_debugger/sessions.py +387 -0
- crabcode_debugger/tool.py +731 -0
- crabcode_gateway/__init__.py +18 -0
- crabcode_gateway/acp/__init__.py +13 -0
- crabcode_gateway/acp/agent.py +1581 -0
- crabcode_gateway/acp/session.py +114 -0
- crabcode_gateway/acp/transport.py +39 -0
- crabcode_gateway/acp/types.py +90 -0
- crabcode_gateway/adapter.py +30 -0
- crabcode_gateway/auth.py +139 -0
- crabcode_gateway/computer_use.py +364 -0
- crabcode_gateway/document_engine.py +637 -0
- crabcode_gateway/document_worker.py +301 -0
- crabcode_gateway/event_bus.py +655 -0
- crabcode_gateway/grpc/__init__.py +0 -0
- crabcode_gateway/grpc/crabcode_pb2.py +70 -0
- crabcode_gateway/grpc/crabcode_pb2_grpc.py +474 -0
- crabcode_gateway/grpc/proto/crabcode.proto +160 -0
- crabcode_gateway/grpc/server.py +765 -0
- crabcode_gateway/middleware.py +344 -0
- crabcode_gateway/protocol.py +17 -0
- crabcode_gateway/routes/__init__.py +0 -0
- crabcode_gateway/routes/agent.py +392 -0
- crabcode_gateway/routes/auth.py +150 -0
- crabcode_gateway/routes/computer_use.py +101 -0
- crabcode_gateway/routes/config.py +1698 -0
- crabcode_gateway/routes/document.py +1810 -0
- crabcode_gateway/routes/event.py +3801 -0
- crabcode_gateway/routes/git_review.py +232 -0
- crabcode_gateway/routes/health.py +14 -0
- crabcode_gateway/routes/peer.py +78 -0
- crabcode_gateway/routes/permission.py +121 -0
- crabcode_gateway/routes/schedule.py +300 -0
- crabcode_gateway/routes/session.py +1496 -0
- crabcode_gateway/routes/snapshot.py +211 -0
- crabcode_gateway/routes/tasks.py +318 -0
- crabcode_gateway/routes/team.py +392 -0
- crabcode_gateway/routes/usage.py +49 -0
- crabcode_gateway/routes/workspace.py +299 -0
- crabcode_gateway/safe_file.py +63 -0
- crabcode_gateway/schemas.py +1820 -0
- crabcode_gateway/server.py +514 -0
- crabcode_gateway/session_registry.py +36 -0
- crabcode_gateway/task_registry.py +708 -0
- crabcode_gateway/turn_details.py +60 -0
- crabcode_search/__init__.py +11 -0
- crabcode_search/background.py +368 -0
- crabcode_search/chunker.py +517 -0
- crabcode_search/embedder.py +497 -0
- crabcode_search/indexer.py +215 -0
- crabcode_search/store.py +222 -0
- 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
|