axion-code 1.0.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.
- axion/__init__.py +3 -0
- axion/api/__init__.py +0 -0
- axion/api/anthropic.py +460 -0
- axion/api/client.py +259 -0
- axion/api/error.py +161 -0
- axion/api/ollama.py +597 -0
- axion/api/openai_compat.py +805 -0
- axion/api/openai_responses.py +627 -0
- axion/api/prompt_cache.py +31 -0
- axion/api/sse.py +98 -0
- axion/api/types.py +451 -0
- axion/cli/__init__.py +0 -0
- axion/cli/init_cmd.py +50 -0
- axion/cli/input.py +290 -0
- axion/cli/main.py +2953 -0
- axion/cli/render.py +489 -0
- axion/cli/tui.py +766 -0
- axion/commands/__init__.py +0 -0
- axion/commands/handlers/__init__.py +0 -0
- axion/commands/handlers/agents.py +51 -0
- axion/commands/handlers/builtin_commands.py +367 -0
- axion/commands/handlers/mcp.py +59 -0
- axion/commands/handlers/models.py +75 -0
- axion/commands/handlers/plugins.py +55 -0
- axion/commands/handlers/skills.py +61 -0
- axion/commands/parsing.py +317 -0
- axion/commands/registry.py +166 -0
- axion/compat_harness/__init__.py +0 -0
- axion/compat_harness/extractor.py +145 -0
- axion/plugins/__init__.py +0 -0
- axion/plugins/hooks.py +22 -0
- axion/plugins/manager.py +391 -0
- axion/plugins/manifest.py +270 -0
- axion/runtime/__init__.py +0 -0
- axion/runtime/bash.py +388 -0
- axion/runtime/bootstrap.py +39 -0
- axion/runtime/claude_subscription.py +300 -0
- axion/runtime/compact.py +233 -0
- axion/runtime/config.py +397 -0
- axion/runtime/conversation.py +1073 -0
- axion/runtime/file_ops.py +613 -0
- axion/runtime/git.py +213 -0
- axion/runtime/hooks.py +235 -0
- axion/runtime/image.py +212 -0
- axion/runtime/lanes.py +282 -0
- axion/runtime/lsp.py +425 -0
- axion/runtime/mcp/__init__.py +0 -0
- axion/runtime/mcp/client.py +76 -0
- axion/runtime/mcp/lifecycle.py +96 -0
- axion/runtime/mcp/stdio.py +318 -0
- axion/runtime/mcp/tool_bridge.py +79 -0
- axion/runtime/memory.py +196 -0
- axion/runtime/oauth.py +329 -0
- axion/runtime/openai_subscription.py +346 -0
- axion/runtime/permissions.py +247 -0
- axion/runtime/plan_mode.py +96 -0
- axion/runtime/policy_engine.py +259 -0
- axion/runtime/prompt.py +586 -0
- axion/runtime/recovery.py +261 -0
- axion/runtime/remote.py +28 -0
- axion/runtime/sandbox.py +68 -0
- axion/runtime/scheduler.py +231 -0
- axion/runtime/session.py +365 -0
- axion/runtime/sharing.py +159 -0
- axion/runtime/skills.py +124 -0
- axion/runtime/tasks.py +258 -0
- axion/runtime/usage.py +241 -0
- axion/runtime/workers.py +186 -0
- axion/telemetry/__init__.py +0 -0
- axion/telemetry/events.py +67 -0
- axion/telemetry/profile.py +49 -0
- axion/telemetry/sink.py +60 -0
- axion/telemetry/tracer.py +95 -0
- axion/tools/__init__.py +0 -0
- axion/tools/lane_completion.py +33 -0
- axion/tools/registry.py +853 -0
- axion/tools/tool_search.py +226 -0
- axion_code-1.0.0.dist-info/METADATA +709 -0
- axion_code-1.0.0.dist-info/RECORD +82 -0
- axion_code-1.0.0.dist-info/WHEEL +4 -0
- axion_code-1.0.0.dist-info/entry_points.txt +2 -0
- axion_code-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Telemetry event types.
|
|
2
|
+
|
|
3
|
+
Maps to: rust/crates/telemetry/src/lib.rs (event types)
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class AnalyticsEvent:
|
|
14
|
+
"""User action event."""
|
|
15
|
+
|
|
16
|
+
namespace: str
|
|
17
|
+
action: str
|
|
18
|
+
properties: dict[str, Any] = field(default_factory=dict)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class HttpRequestStarted:
|
|
23
|
+
session_id: str
|
|
24
|
+
attempt: int
|
|
25
|
+
method: str
|
|
26
|
+
path: str
|
|
27
|
+
attributes: dict[str, Any] = field(default_factory=dict)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class HttpRequestSucceeded:
|
|
32
|
+
session_id: str
|
|
33
|
+
attempt: int
|
|
34
|
+
method: str
|
|
35
|
+
path: str
|
|
36
|
+
status: int
|
|
37
|
+
request_id: str | None = None
|
|
38
|
+
attributes: dict[str, Any] = field(default_factory=dict)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class HttpRequestFailed:
|
|
43
|
+
session_id: str
|
|
44
|
+
attempt: int
|
|
45
|
+
method: str
|
|
46
|
+
path: str
|
|
47
|
+
error: str
|
|
48
|
+
retryable: bool = False
|
|
49
|
+
attributes: dict[str, Any] = field(default_factory=dict)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class SessionTraceRecord:
|
|
54
|
+
session_id: str
|
|
55
|
+
sequence: int
|
|
56
|
+
name: str
|
|
57
|
+
timestamp_ms: int
|
|
58
|
+
attributes: dict[str, Any] = field(default_factory=dict)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
TelemetryEvent = (
|
|
62
|
+
HttpRequestStarted
|
|
63
|
+
| HttpRequestSucceeded
|
|
64
|
+
| HttpRequestFailed
|
|
65
|
+
| AnalyticsEvent
|
|
66
|
+
| SessionTraceRecord
|
|
67
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Anthropic request profile and client identity.
|
|
2
|
+
|
|
3
|
+
Maps to: rust/crates/telemetry/src/lib.rs (AnthropicRequestProfile, ClientIdentity)
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
DEFAULT_ANTHROPIC_VERSION = "2023-06-01"
|
|
12
|
+
DEFAULT_APP_NAME = "axion-code"
|
|
13
|
+
DEFAULT_RUNTIME = "python"
|
|
14
|
+
DEFAULT_AGENTIC_BETA = "claude-code-20250219"
|
|
15
|
+
DEFAULT_PROMPT_CACHING_SCOPE_BETA = "prompt-caching-scope-2026-01-05"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class ClientIdentity:
|
|
20
|
+
"""Application identity for API requests."""
|
|
21
|
+
|
|
22
|
+
app_name: str = DEFAULT_APP_NAME
|
|
23
|
+
app_version: str = "1.0.0"
|
|
24
|
+
runtime: str = DEFAULT_RUNTIME
|
|
25
|
+
|
|
26
|
+
def user_agent(self) -> str:
|
|
27
|
+
return f"{self.app_name}/{self.app_version}"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class AnthropicRequestProfile:
|
|
32
|
+
"""HTTP request configuration for Anthropic API."""
|
|
33
|
+
|
|
34
|
+
anthropic_version: str = DEFAULT_ANTHROPIC_VERSION
|
|
35
|
+
client_identity: ClientIdentity = field(default_factory=ClientIdentity)
|
|
36
|
+
betas: list[str] = field(
|
|
37
|
+
default_factory=lambda: [DEFAULT_AGENTIC_BETA, DEFAULT_PROMPT_CACHING_SCOPE_BETA]
|
|
38
|
+
)
|
|
39
|
+
extra_body: dict[str, Any] = field(default_factory=dict)
|
|
40
|
+
|
|
41
|
+
def header_pairs(self) -> dict[str, str]:
|
|
42
|
+
"""Generate HTTP headers for the request."""
|
|
43
|
+
headers = {
|
|
44
|
+
"anthropic-version": self.anthropic_version,
|
|
45
|
+
"user-agent": self.client_identity.user_agent(),
|
|
46
|
+
}
|
|
47
|
+
if self.betas:
|
|
48
|
+
headers["anthropic-beta"] = ",".join(self.betas)
|
|
49
|
+
return headers
|
axion/telemetry/sink.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Telemetry sinks for event recording.
|
|
2
|
+
|
|
3
|
+
Maps to: rust/crates/telemetry/src/lib.rs (TelemetrySink)
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import threading
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Protocol, runtime_checkable
|
|
12
|
+
|
|
13
|
+
from axion.telemetry.events import TelemetryEvent
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@runtime_checkable
|
|
17
|
+
class TelemetrySink(Protocol):
|
|
18
|
+
"""Protocol for recording telemetry events."""
|
|
19
|
+
|
|
20
|
+
def record(self, event: TelemetryEvent) -> None: ...
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class MemoryTelemetrySink:
|
|
24
|
+
"""In-memory telemetry sink for testing."""
|
|
25
|
+
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
self._events: list[TelemetryEvent] = []
|
|
28
|
+
self._lock = threading.Lock()
|
|
29
|
+
|
|
30
|
+
def record(self, event: TelemetryEvent) -> None:
|
|
31
|
+
with self._lock:
|
|
32
|
+
self._events.append(event)
|
|
33
|
+
|
|
34
|
+
def events(self) -> list[TelemetryEvent]:
|
|
35
|
+
with self._lock:
|
|
36
|
+
return list(self._events)
|
|
37
|
+
|
|
38
|
+
def clear(self) -> None:
|
|
39
|
+
with self._lock:
|
|
40
|
+
self._events.clear()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class JsonlTelemetrySink:
|
|
44
|
+
"""JSONL file-based telemetry sink."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, path: Path) -> None:
|
|
47
|
+
self._path = path
|
|
48
|
+
self._lock = threading.Lock()
|
|
49
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
50
|
+
|
|
51
|
+
def record(self, event: TelemetryEvent) -> None:
|
|
52
|
+
with self._lock:
|
|
53
|
+
with open(self._path, "a", encoding="utf-8") as f:
|
|
54
|
+
# Simple serialization
|
|
55
|
+
data: dict[str, Any] = {
|
|
56
|
+
"type": type(event).__name__,
|
|
57
|
+
}
|
|
58
|
+
for k, v in vars(event).items():
|
|
59
|
+
data[k] = v
|
|
60
|
+
f.write(json.dumps(data, default=str) + "\n")
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Session-level event tracer.
|
|
2
|
+
|
|
3
|
+
Maps to: rust/crates/telemetry/src/lib.rs (SessionTracer)
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import threading
|
|
9
|
+
import time
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from axion.telemetry.events import (
|
|
13
|
+
AnalyticsEvent,
|
|
14
|
+
HttpRequestFailed,
|
|
15
|
+
HttpRequestStarted,
|
|
16
|
+
HttpRequestSucceeded,
|
|
17
|
+
SessionTraceRecord,
|
|
18
|
+
)
|
|
19
|
+
from axion.telemetry.sink import TelemetrySink
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SessionTracer:
|
|
23
|
+
"""Session-level event recorder with atomic sequence counter.
|
|
24
|
+
|
|
25
|
+
Maps to: rust/crates/telemetry/src/lib.rs::SessionTracer
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, session_id: str, sink: TelemetrySink) -> None:
|
|
29
|
+
self.session_id = session_id
|
|
30
|
+
self._sink = sink
|
|
31
|
+
self._sequence = 0
|
|
32
|
+
self._lock = threading.Lock()
|
|
33
|
+
|
|
34
|
+
def _next_seq(self) -> int:
|
|
35
|
+
with self._lock:
|
|
36
|
+
self._sequence += 1
|
|
37
|
+
return self._sequence
|
|
38
|
+
|
|
39
|
+
def record(self, name: str, attributes: dict[str, Any] | None = None) -> None:
|
|
40
|
+
"""Record a session trace event."""
|
|
41
|
+
event = SessionTraceRecord(
|
|
42
|
+
session_id=self.session_id,
|
|
43
|
+
sequence=self._next_seq(),
|
|
44
|
+
name=name,
|
|
45
|
+
timestamp_ms=int(time.time() * 1000),
|
|
46
|
+
attributes=attributes or {},
|
|
47
|
+
)
|
|
48
|
+
self._sink.record(event)
|
|
49
|
+
|
|
50
|
+
def record_http_request_started(
|
|
51
|
+
self, attempt: int, method: str, path: str
|
|
52
|
+
) -> None:
|
|
53
|
+
self._sink.record(HttpRequestStarted(
|
|
54
|
+
session_id=self.session_id,
|
|
55
|
+
attempt=attempt,
|
|
56
|
+
method=method,
|
|
57
|
+
path=path,
|
|
58
|
+
))
|
|
59
|
+
|
|
60
|
+
def record_http_request_succeeded(
|
|
61
|
+
self,
|
|
62
|
+
attempt: int,
|
|
63
|
+
method: str,
|
|
64
|
+
path: str,
|
|
65
|
+
status: int,
|
|
66
|
+
request_id: str | None = None,
|
|
67
|
+
) -> None:
|
|
68
|
+
self._sink.record(HttpRequestSucceeded(
|
|
69
|
+
session_id=self.session_id,
|
|
70
|
+
attempt=attempt,
|
|
71
|
+
method=method,
|
|
72
|
+
path=path,
|
|
73
|
+
status=status,
|
|
74
|
+
request_id=request_id,
|
|
75
|
+
))
|
|
76
|
+
|
|
77
|
+
def record_http_request_failed(
|
|
78
|
+
self,
|
|
79
|
+
attempt: int,
|
|
80
|
+
method: str,
|
|
81
|
+
path: str,
|
|
82
|
+
error: str,
|
|
83
|
+
retryable: bool = False,
|
|
84
|
+
) -> None:
|
|
85
|
+
self._sink.record(HttpRequestFailed(
|
|
86
|
+
session_id=self.session_id,
|
|
87
|
+
attempt=attempt,
|
|
88
|
+
method=method,
|
|
89
|
+
path=path,
|
|
90
|
+
error=error,
|
|
91
|
+
retryable=retryable,
|
|
92
|
+
))
|
|
93
|
+
|
|
94
|
+
def record_analytics(self, event: AnalyticsEvent) -> None:
|
|
95
|
+
self._sink.record(event)
|
axion/tools/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Lane completion tools.
|
|
2
|
+
|
|
3
|
+
Maps to: rust/crates/tools/src/lane_completion.rs
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class LaneCompletionResult:
|
|
13
|
+
lane_id: str
|
|
14
|
+
status: str
|
|
15
|
+
message: str = ""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def complete_lane(lane_id: str) -> LaneCompletionResult:
|
|
19
|
+
"""Mark a lane as completed."""
|
|
20
|
+
return LaneCompletionResult(
|
|
21
|
+
lane_id=lane_id,
|
|
22
|
+
status="completed",
|
|
23
|
+
message=f"Lane {lane_id} marked as completed",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def reconcile_lane(lane_id: str) -> LaneCompletionResult:
|
|
28
|
+
"""Mark a lane as reconciled."""
|
|
29
|
+
return LaneCompletionResult(
|
|
30
|
+
lane_id=lane_id,
|
|
31
|
+
status="reconciled",
|
|
32
|
+
message=f"Lane {lane_id} reconciled",
|
|
33
|
+
)
|